kdialog.cpp
00001 /* This file is part of the KDE Libraries 00002 * Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net) 00003 * Additions 1999-2000 by Espen Sand (espen@kde.org) 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include <kconfig.h> 00022 #include <kapplication.h> 00023 #include <kdialog.h> 00024 #include <kwhatsthismanager_p.h> 00025 #include <kdebug.h> 00026 #include <kstaticdeleter.h> 00027 #include <kiconloader.h> 00028 #include <kglobalsettings.h> 00029 #include <klocale.h> 00030 00031 #include <tqlayout.h> 00032 #include <tqobjectlist.h> 00033 #include <tqguardedptr.h> 00034 #include <tqlineedit.h> 00035 #include <tqvaluelist.h> 00036 #include <tqtimer.h> 00037 #include <tqcursor.h> 00038 #include <tqlabel.h> 00039 #include <tqstyle.h> 00040 #include <tqimage.h> 00041 00042 #include "config.h" 00043 #ifdef Q_WS_X11 00044 #include <netwm.h> 00045 #endif 00046 00047 const int KDialog::mMarginSize = 11; 00048 const int KDialog::mSpacingSize = 6; 00049 00050 template class TQPtrList<TQLayoutItem>; 00051 00052 KDialog::KDialog(TQWidget *parent, const char *name, bool modal, WFlags f) 00053 : TQDialog(parent, name, modal, f), d(0) 00054 { 00055 KWhatsThisManager::init (); 00056 } 00057 00058 // 00059 // Grab QDialogs keypresses if non-modal. 00060 // 00061 void KDialog::keyPressEvent(TQKeyEvent *e) 00062 { 00063 if ( e->state() == 0 ) 00064 { 00065 switch ( e->key() ) 00066 { 00067 case Key_Escape: 00068 case Key_Enter: 00069 case Key_Return: 00070 { 00071 if(testWFlags((WFlags)(WType_Dialog | WShowModal))) 00072 { 00073 TQDialog::keyPressEvent(e); 00074 } 00075 else 00076 { 00077 e->ignore(); 00078 } 00079 } 00080 break; 00081 default: 00082 e->ignore(); 00083 return; 00084 } 00085 } 00086 else 00087 { 00088 // accept the dialog when Ctrl-Return is pressed 00089 if ( e->state() == ControlButton && 00090 (e->key() == Key_Return || e->key() == Key_Enter) ) 00091 { 00092 e->accept(); 00093 accept(); 00094 } 00095 else 00096 { 00097 e->ignore(); 00098 } 00099 } 00100 } 00101 00102 00103 int KDialog::marginHint() 00104 { 00105 return mMarginSize; 00106 } 00107 00108 00109 int KDialog::spacingHint() 00110 { 00111 return mSpacingSize; 00112 } 00113 00114 // KDE4: Remove me 00115 void KDialog::polish() 00116 { 00117 TQDialog::polish(); 00118 } 00119 00120 00121 void KDialog::setCaption( const TQString &_caption ) 00122 { 00123 TQString caption = kapp ? kapp->makeStdCaption( _caption ) : _caption; 00124 setPlainCaption( caption ); 00125 } 00126 00127 00128 void KDialog::setPlainCaption( const TQString &caption ) 00129 { 00130 TQDialog::setCaption( caption ); 00131 00132 #ifdef Q_WS_X11 00133 NETWinInfo info( qt_xdisplay(), winId(), qt_xrootwin(), 0 ); 00134 info.setName( caption.utf8().data() ); 00135 #endif 00136 } 00137 00138 00139 void KDialog::resizeLayout( TQWidget *w, int margin, int spacing ) 00140 { 00141 if( w->layout() ) 00142 { 00143 resizeLayout( TQT_TQLAYOUTITEM(w->layout()), margin, spacing ); 00144 } 00145 00146 if( !w->childrenListObject().isEmpty() ) 00147 { 00148 const TQObjectList l = w->childrenListObject(); 00149 TQObjectListIterator itr(l); 00150 TQObject *o; 00151 while ((o = itr.current()) != 0) { 00152 if( o->isWidgetType() ) 00153 { 00154 resizeLayout( (TQWidget*)o, margin, spacing ); 00155 } 00156 ++itr; 00157 } 00158 } 00159 } 00160 00161 00162 void KDialog::resizeLayout( TQLayoutItem *lay, int margin, int spacing ) 00163 { 00164 TQLayoutIterator it = lay->iterator(); 00165 TQLayoutItem *child; 00166 while ( (child = it.current() ) ) 00167 { 00168 resizeLayout( child, margin, spacing ); 00169 ++it; 00170 } 00171 if( lay->layout() ) 00172 { 00173 lay->layout()->setMargin( margin ); 00174 lay->layout()->setSpacing( spacing ); 00175 } 00176 } 00177 00178 static TQRect screenRect( TQWidget *w, int screen ) 00179 { 00180 TQDesktopWidget *desktop = TQApplication::desktop(); 00181 KConfig gc("kdeglobals", false, false); 00182 gc.setGroup("Windows"); 00183 if (desktop->isVirtualDesktop() && 00184 gc.readBoolEntry("XineramaEnabled", true) && 00185 gc.readBoolEntry("XineramaPlacementEnabled", true)) { 00186 if ( screen < 0 || screen >= desktop->numScreens() ) { 00187 if ( screen == -1 ) { 00188 screen = desktop->primaryScreen(); 00189 } else if ( screen == -3 ) { 00190 screen = desktop->screenNumber( TQCursor::pos() ); 00191 } else { 00192 screen = desktop->screenNumber( w ); 00193 } 00194 } 00195 return desktop->availableGeometry(screen); 00196 } else { 00197 return desktop->geometry(); 00198 } 00199 } 00200 00201 void KDialog::centerOnScreen( TQWidget *w, int screen ) 00202 { 00203 if ( !w ) 00204 return; 00205 TQRect r = screenRect( w, screen ); 00206 00207 w->move( r.center().x() - w->width()/2, 00208 r.center().y() - w->height()/2 ); 00209 } 00210 00211 bool KDialog::avoidArea( TQWidget *w, const TQRect& area, int screen ) 00212 { 00213 if ( !w ) 00214 return false; 00215 TQRect fg = w->frameGeometry(); 00216 if ( !fg.intersects( area ) ) 00217 return true; // nothing to do. 00218 00219 TQRect scr = screenRect( w, screen ); 00220 TQRect avoid( area ); // let's add some margin 00221 avoid.moveBy( -5, -5 ); 00222 avoid.rRight() += 10; 00223 avoid.rBottom() += 10; 00224 00225 if ( QMAX( fg.top(), avoid.top() ) <= QMIN( fg.bottom(), avoid.bottom() ) ) 00226 { 00227 // We need to move the widget up or down 00228 int spaceAbove = QMAX(0, avoid.top() - scr.top()); 00229 int spaceBelow = QMAX(0, scr.bottom() - avoid.bottom()); 00230 if ( spaceAbove > spaceBelow ) // where's the biggest side? 00231 if ( fg.height() <= spaceAbove ) // big enough? 00232 fg.setY( avoid.top() - fg.height() ); 00233 else 00234 return false; 00235 else 00236 if ( fg.height() <= spaceBelow ) // big enough? 00237 fg.setY( avoid.bottom() ); 00238 else 00239 return false; 00240 } 00241 00242 if ( QMAX( fg.left(), avoid.left() ) <= QMIN( fg.right(), avoid.right() ) ) 00243 { 00244 // We need to move the widget left or right 00245 int spaceLeft = QMAX(0, avoid.left() - scr.left()); 00246 int spaceRight = QMAX(0, scr.right() - avoid.right()); 00247 if ( spaceLeft > spaceRight ) // where's the biggest side? 00248 if ( fg.width() <= spaceLeft ) // big enough? 00249 fg.setX( avoid.left() - fg.width() ); 00250 else 00251 return false; 00252 else 00253 if ( fg.width() <= spaceRight ) // big enough? 00254 fg.setX( avoid.right() ); 00255 else 00256 return false; 00257 } 00258 //kdDebug() << "Moving window to " << fg.x() << "," << fg.y() << endl; 00259 w->move(fg.x(), fg.y()); 00260 return true; 00261 } 00262 00263 class KDialogQueuePrivate 00264 { 00265 public: 00266 TQValueList< TQGuardedPtr<TQDialog> > queue; 00267 bool busy; 00268 }; 00269 00270 static KStaticDeleter<KDialogQueue> ksdkdq; 00271 00272 KDialogQueue *KDialogQueue::_self=0; 00273 00274 KDialogQueue* KDialogQueue::self() 00275 { 00276 if (!_self) 00277 _self = ksdkdq.setObject(_self, new KDialogQueue); 00278 return _self; 00279 } 00280 00281 KDialogQueue::KDialogQueue() : d(new KDialogQueuePrivate) 00282 { 00283 d->busy = false; 00284 } 00285 00286 KDialogQueue::~KDialogQueue() 00287 { 00288 delete d; 00289 _self = 0; 00290 } 00291 00292 // static 00293 void KDialogQueue::queueDialog(TQDialog *dialog) 00294 { 00295 KDialogQueue *_this = self(); 00296 _this->d->queue.append(dialog); 00297 TQTimer::singleShot(0, _this, TQT_SLOT(slotShowQueuedDialog())); 00298 } 00299 00300 void KDialogQueue::slotShowQueuedDialog() 00301 { 00302 if (d->busy) 00303 return; 00304 TQDialog *dialog; 00305 do { 00306 if(d->queue.isEmpty()) 00307 return; 00308 dialog = d->queue.first(); 00309 d->queue.pop_front(); 00310 } 00311 while(!dialog); 00312 00313 d->busy = true; 00314 dialog->exec(); 00315 d->busy = false; 00316 delete dialog; 00317 00318 if (!d->queue.isEmpty()) 00319 TQTimer::singleShot(20, this, TQT_SLOT(slotShowQueuedDialog())); 00320 else 00321 ksdkdq.destructObject(); // Suicide. 00322 } 00323 00324 void KDialog::virtual_hook( int, void* ) 00325 { /*BASE::virtual_hook( id, data );*/ } 00326 00327 KSMModalDialogHeader::KSMModalDialogHeader(TQWidget* parent) 00328 : TQWidget( parent, "", Qt::WDestructiveClose ) 00329 { 00330 TQVBoxLayout* vbox = new TQVBoxLayout( this ); 00331 00332 TQFrame* frame = new TQFrame( this ); 00333 frame->setFrameStyle( TQFrame::NoFrame ); 00334 frame->setLineWidth( 0 ); 00335 // we need to set the minimum size for the window 00336 frame->setMinimumWidth(400); 00337 vbox->addWidget( frame ); 00338 TQGridLayout* gbox = new TQGridLayout( frame, 1, 1, 0, KDialog::spacingHint() ); 00339 TQHBoxLayout* centerbox = new TQHBoxLayout( KDialog::spacingHint() ); 00340 TQHBoxLayout* seperatorbox = new TQHBoxLayout( 0 ); 00341 centerbox->setMargin(0); 00342 seperatorbox->setMargin(0); 00343 00344 TQWidget* ticon = new TQWidget( frame ); 00345 KIconLoader * ldr = KGlobal::iconLoader(); 00346 TQPixmap trinityPixmap = ldr->loadIcon("kmenu", KIcon::Panel, KIcon::SizeLarge, KIcon::DefaultState, 0L, true); 00347 00348 // Manually draw the alpha portions of the icon onto the widget background color... 00349 TQRgb backgroundRgb = ticon->paletteBackgroundColor().rgb(); 00350 TQImage correctedImage = trinityPixmap.convertToImage(); 00351 correctedImage = correctedImage.convertDepth(32); 00352 correctedImage.setAlphaBuffer(true); 00353 int w = correctedImage.width(); 00354 int h = correctedImage.height(); 00355 for (int y = 0; y < h; ++y) { 00356 TQRgb *ls = (TQRgb *)correctedImage.scanLine( y ); 00357 for (int x = 0; x < w; ++x) { 00358 TQRgb l = ls[x]; 00359 float alpha_adjust = tqAlpha( l )/255.0; 00360 int r = int( (tqRed( l ) * alpha_adjust) + (tqRed( backgroundRgb ) * (1.0-alpha_adjust)) ); 00361 int g = int( (tqGreen( l ) * alpha_adjust) + (tqGreen( backgroundRgb ) * (1.0-alpha_adjust)) ); 00362 int b = int( (tqBlue( l ) * alpha_adjust) + (tqBlue( backgroundRgb ) * (1.0-alpha_adjust)) ); 00363 int a = int( 255 ); 00364 ls[x] = tqRgba( r, g, b, a ); 00365 } 00366 } 00367 trinityPixmap.convertFromImage(correctedImage); 00368 00369 ticon->setBackgroundPixmap(trinityPixmap); 00370 ticon->setMinimumSize(trinityPixmap.size()); 00371 ticon->setMaximumSize(trinityPixmap.size()); 00372 ticon->resize(trinityPixmap.size()); 00373 centerbox->addWidget( ticon, AlignCenter ); 00374 00375 TQWidget* swidget = new TQWidget( frame ); 00376 swidget->resize(2, frame->sizeHint().width()); 00377 swidget->setBackgroundColor(Qt::black); 00378 seperatorbox->addWidget( swidget, AlignCenter ); 00379 00380 TQLabel* label = new TQLabel( i18n("Trinity Desktop Environment"), frame ); 00381 TQFont fnt = label->font(); 00382 fnt.setBold( true ); 00383 fnt.setPointSize( fnt.pointSize() * 3 / 2 ); 00384 label->setFont( fnt ); 00385 centerbox->addWidget( label, AlignCenter ); 00386 00387 gbox->addLayout(centerbox, 0, 0); 00388 gbox->addLayout(seperatorbox, 1, 0); 00389 00390 setFixedSize( sizeHint() ); 00391 } 00392 00393 KSMModalDialogHeader::~KSMModalDialogHeader() 00394 { 00395 } 00396 00397 KSMModalDialog::KSMModalDialog(TQWidget* parent) 00398 : TQWidget( 0, "systemmodaldialogclass", Qt::WStyle_Customize | Qt::WType_Dialog | Qt::WStyle_Title | Qt::WStyle_StaysOnTop | Qt::WDestructiveClose ), m_keepOnTopTimer(NULL), m_allowClose(false) 00399 00400 { 00401 // Signal that we do not want any window controls to be shown at all 00402 Atom kde_wm_system_modal_notification; 00403 kde_wm_system_modal_notification = XInternAtom(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False); 00404 XChangeProperty(qt_xdisplay(), winId(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L); 00405 00406 TQVBoxLayout* vbox = new TQVBoxLayout( this ); 00407 00408 TQFrame* frame = new TQFrame( this ); 00409 frame->setFrameStyle( TQFrame::NoFrame ); 00410 frame->setLineWidth( style().pixelMetric( TQStyle::PM_DefaultFrameWidth, frame ) ); 00411 // we need to set the minimum size for the window 00412 frame->setMinimumWidth(400); 00413 vbox->addWidget( frame ); 00414 TQGridLayout* gbox = new TQGridLayout( frame, 1, 1, KDialog::marginHint(), KDialog::spacingHint() ); 00415 TQHBoxLayout* centerbox = new TQHBoxLayout( KDialog::spacingHint() ); 00416 00417 m_statusLabel = new TQLabel( i18n("Pondering what to do next").append("..."), frame ); 00418 TQFont fnt = m_statusLabel->font(); 00419 fnt.setBold( false ); 00420 fnt.setPointSize( fnt.pointSize() * 1 ); 00421 m_statusLabel->setFont( fnt ); 00422 gbox->addMultiCellWidget( m_statusLabel, 2, 2, 0, 0, AlignLeft | AlignVCenter ); 00423 00424 KSMModalDialogHeader *theader = new KSMModalDialogHeader(this); 00425 centerbox->addWidget( theader, AlignCenter ); 00426 00427 gbox->addLayout(centerbox, 0, 0); 00428 00429 setFixedSize( sizeHint() ); 00430 setCaption( i18n("Please wait...") ); 00431 00432 // Center the dialog 00433 TQSize sh = sizeHint(); 00434 TQRect rect = KGlobalSettings::desktopGeometry(TQCursor::pos()); 00435 move(rect.x() + (rect.width() - sh.width())/2, rect.y() + (rect.height() - sh.height())/2); 00436 00437 show(); 00438 keepMeOnTop(); 00439 } 00440 00441 void KSMModalDialog::keepMeOnTop() 00442 { 00443 if (!m_keepOnTopTimer) { 00444 m_keepOnTopTimer = new TQTimer(); 00445 connect(m_keepOnTopTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(keepMeOnTop())); 00446 m_keepOnTopTimer->start(100, FALSE); 00447 } 00448 setActiveWindow(); 00449 raise(); 00450 setFocus(); 00451 } 00452 00453 KSMModalDialog::~KSMModalDialog() 00454 { 00455 m_keepOnTopTimer->stop(); 00456 delete m_keepOnTopTimer; 00457 } 00458 00459 void KSMModalDialog::setStatusMessage(TQString message) 00460 { 00461 if (message == "") { 00462 m_statusLabel->setText(i18n("Pondering what to do next").append("...")); 00463 } 00464 else { 00465 m_statusLabel->setText(message); 00466 } 00467 } 00468 00469 void KSMModalDialog::closeSMDialog() 00470 { 00471 m_allowClose = true; 00472 close(); 00473 } 00474 00475 void KSMModalDialog::closeEvent(TQCloseEvent *e) 00476 { 00477 //--------------------------------------------- 00478 // Don't call the base function because 00479 // we want to ignore the close event 00480 //--------------------------------------------- 00481 00482 if (m_allowClose) 00483 TQWidget::closeEvent(e); 00484 } 00485 00486 void KSMModalDialog::setStartupPhase(TQString msg) 00487 { 00488 if (msg == TQString("dcop")) setStatusMessage(i18n("Starting DCOP").append("...")); 00489 if (msg == TQString("kded")) setStatusMessage(i18n("Starting TDE daemon").append("...")); 00490 if (msg == TQString("kcminit")) setStatusMessage(i18n("Starting services").append("...")); 00491 if (msg == TQString("ksmserver")) setStatusMessage(i18n("Starting session").append("...")); 00492 if (msg == TQString("wm started")) setStatusMessage(i18n("Initializing window manager").append("...")); 00493 if (msg == TQString("kdesktop")) setStatusMessage(i18n("Loading desktop").append("...")); 00494 if (msg == TQString("kicker")) setStatusMessage(i18n("Loading panels").append("...")); 00495 if (msg == TQString("session ready")) setStatusMessage(i18n("Restoring applications").append("...")); 00496 } 00497 00498 #include "kdialog.moc"