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