KDEUI
kdialog.cpp
Go to the documentation of this file.
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 * by Holger Freyther <freyther@kde.org> 00005 * 2005-2009 by Olivier Goffart (ogoffart at kde.org) 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Library General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Library General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Library General Public License 00018 * along with this library; see the file COPYING.LIB. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include "kdialog.h" 00024 #include "kdialog_p.h" 00025 #include <kdebug.h> 00026 #include "kdialogqueue_p.h" 00027 00028 #include <config.h> 00029 00030 #include <QApplication> 00031 #include <QDesktopWidget> 00032 #include <QDialogButtonBox> 00033 #include <QHBoxLayout> 00034 #include <QHideEvent> 00035 #include <QPointer> 00036 #include <QStyle> 00037 #include <QTimer> 00038 #include <QVBoxLayout> 00039 #include <QWhatsThis> 00040 00041 #include <klocale.h> 00042 #include <kpushbutton.h> 00043 #include <kseparator.h> 00044 #include <kstandardguiitem.h> 00045 #include <ktoolinvocation.h> 00046 #include <kurllabel.h> 00047 00048 #ifdef Q_WS_X11 00049 #include <qx11info_x11.h> 00050 #include <netwm.h> 00051 #endif 00052 00053 static bool sAllowEmbeddingInGraphicsView = false; 00054 00055 void KDialogPrivate::setupLayout() 00056 { 00057 Q_Q(KDialog); 00058 if (!dirty) { 00059 QMetaObject::invokeMethod( q, "queuedLayoutUpdate", Qt::QueuedConnection ); 00060 dirty = true; 00061 } 00062 } 00063 00064 void KDialogPrivate::queuedLayoutUpdate() 00065 { 00066 if (!dirty) 00067 return; 00068 00069 dirty = false; 00070 00071 Q_Q(KDialog); 00072 00073 // Don't lose the focus widget when re-creating the layout. 00074 // Testcase: KOrganizer's "Select Categories" dialog 00075 QPointer<QWidget> focusWidget = mMainWidget ? mMainWidget->focusWidget() : 0; 00076 00077 if (q->layout() && q->layout() != mTopLayout) { 00078 kWarning(240) << q->metaObject()->className() << "created with a layout; don't do that, KDialog takes care of it, use mainWidget or setMainWidget instead"; 00079 delete q->layout(); 00080 } 00081 00082 delete mTopLayout; 00083 00084 if ( mButtonOrientation == Qt::Horizontal ) 00085 mTopLayout = new QVBoxLayout(q); 00086 else 00087 mTopLayout = new QHBoxLayout(q); 00088 00089 if ( mUrlHelp ) 00090 mTopLayout->addWidget( mUrlHelp, 0, Qt::AlignRight ); 00091 00092 if ( mMainWidget ) 00093 mTopLayout->addWidget( mMainWidget, 10 ); 00094 00095 if ( mDetailsWidget ) 00096 mTopLayout->addWidget( mDetailsWidget ); 00097 00098 if ( mActionSeparator ) 00099 mTopLayout->addWidget( mActionSeparator ); 00100 00101 if ( mButtonBox ) { 00102 mButtonBox->setOrientation( mButtonOrientation ); 00103 mTopLayout->addWidget( mButtonBox ); 00104 } 00105 00106 if (focusWidget) { 00107 focusWidget->setFocus(); 00108 } 00109 } 00110 00111 void KDialogPrivate::appendButton(KDialog::ButtonCode key, const KGuiItem &item) 00112 { 00113 Q_Q(KDialog); 00114 00115 QDialogButtonBox::ButtonRole role = QDialogButtonBox::InvalidRole; 00116 switch ( key ) { 00117 case KDialog::Help: 00118 case KDialog::Details: 00119 role = QDialogButtonBox::HelpRole; 00120 break; 00121 case KDialog::Default: 00122 case KDialog::Reset: 00123 role = QDialogButtonBox::ResetRole; 00124 break; 00125 case KDialog::Ok: 00126 role = QDialogButtonBox::AcceptRole; 00127 break; 00128 case KDialog::Apply: 00129 role = QDialogButtonBox::ApplyRole; 00130 break; 00131 case KDialog::Try: 00132 case KDialog::Yes: 00133 role = QDialogButtonBox::YesRole; 00134 break; 00135 case KDialog::Close: 00136 case KDialog::Cancel: 00137 role = QDialogButtonBox::RejectRole; 00138 break; 00139 case KDialog::No: 00140 role = QDialogButtonBox::NoRole; 00141 break; 00142 case KDialog::User1: 00143 case KDialog::User2: 00144 case KDialog::User3: 00145 role = QDialogButtonBox::ActionRole; 00146 break; 00147 default: 00148 role = QDialogButtonBox::InvalidRole; 00149 break; 00150 } 00151 00152 if ( role == QDialogButtonBox::InvalidRole ) 00153 return; 00154 00155 KPushButton *button = new KPushButton( item ); 00156 mButtonBox->addButton( button, role ); 00157 00158 mButtonList.insert( key, button ); 00159 mButtonSignalMapper.setMapping( button, key ); 00160 00161 QObject::connect(button, SIGNAL(clicked()), 00162 &mButtonSignalMapper, SLOT( map() ) ); 00163 00164 if (key == mDefaultButton) { 00165 // Now that it exists, set it as default 00166 q->setDefaultButton(mDefaultButton); 00167 } 00168 } 00169 00170 void KDialogPrivate::init(KDialog *q) 00171 { 00172 q_ptr = q; 00173 00174 dirty = false; 00175 00176 q->setButtons(KDialog::Ok | KDialog::Cancel); 00177 q->setDefaultButton(KDialog::Ok); 00178 00179 q->connect(&mButtonSignalMapper, SIGNAL(mapped(int)), q, SLOT(slotButtonClicked(int))); 00180 00181 q->setPlainCaption(KGlobal::caption()); // set appropriate initial window title for case it gets not set later 00182 } 00183 00184 void KDialogPrivate::helpLinkClicked() 00185 { 00186 q_ptr->slotButtonClicked(KDialog::Help); 00187 } 00188 00189 KDialog::KDialog( QWidget *parent, Qt::WFlags flags ) 00190 : QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget ), d_ptr(new KDialogPrivate) 00191 { 00192 d_ptr->init(this); 00193 } 00194 00195 KDialog::KDialog(KDialogPrivate &dd, QWidget *parent, Qt::WFlags flags) 00196 : QDialog(parent, sAllowEmbeddingInGraphicsView ? flags : flags | Qt::BypassGraphicsProxyWidget), d_ptr(&dd) 00197 { 00198 d_ptr->init(this); 00199 } 00200 00201 KDialog::~KDialog() 00202 { 00203 delete d_ptr; 00204 } 00205 00206 void KDialog::setButtons( ButtonCodes buttonMask ) 00207 { 00208 Q_D(KDialog); 00209 if ( d->mButtonBox ) { 00210 d->mButtonList.clear(); 00211 00212 delete d->mButtonBox; 00213 d->mButtonBox = 0; 00214 } 00215 00216 if ( buttonMask & Cancel ) 00217 buttonMask &= ~Close; 00218 00219 if ( buttonMask & Apply ) 00220 buttonMask &= ~Try; 00221 00222 if ( buttonMask & Details ) 00223 buttonMask &= ~Default; 00224 00225 if ( buttonMask == None ) { 00226 d->setupLayout(); 00227 return; // When we want no button box 00228 } 00229 00230 d->mEscapeButton = (buttonMask & Cancel) ? Cancel : Close; 00231 d->mButtonBox = new QDialogButtonBox( this ); 00232 00233 if ( buttonMask & Help ) 00234 d->appendButton( Help, KStandardGuiItem::help() ); 00235 if ( buttonMask & Default ) 00236 d->appendButton( Default, KStandardGuiItem::defaults() ); 00237 if ( buttonMask & Reset ) 00238 d->appendButton( Reset, KStandardGuiItem::reset() ); 00239 if ( buttonMask & User3 ) 00240 d->appendButton( User3, KGuiItem() ); 00241 if ( buttonMask & User2 ) 00242 d->appendButton( User2, KGuiItem() ); 00243 if ( buttonMask & User1 ) 00244 d->appendButton( User1, KGuiItem() ); 00245 if ( buttonMask & Ok ) 00246 d->appendButton( Ok, KStandardGuiItem::ok() ); 00247 if ( buttonMask & Apply ) 00248 d->appendButton( Apply, KStandardGuiItem::apply() ); 00249 if ( buttonMask & Try ) 00250 d->appendButton( Try, KGuiItem(i18n( "&Try" )) ); 00251 if ( buttonMask & Cancel ) 00252 d->appendButton( Cancel, KStandardGuiItem::cancel() ); 00253 if ( buttonMask & Close ) 00254 d->appendButton( Close, KStandardGuiItem::close() ); 00255 if ( buttonMask & Yes ) 00256 d->appendButton( Yes, KStandardGuiItem::yes() ); 00257 if ( buttonMask & No ) 00258 d->appendButton( No, KStandardGuiItem::no() ); 00259 if ( buttonMask & Details ) { 00260 d->appendButton( Details, KGuiItem(QString(), "help-about") ); 00261 setDetailsWidgetVisible( false ); 00262 } 00263 00264 d->setupLayout(); 00265 } 00266 00267 00268 void KDialog::setButtonsOrientation( Qt::Orientation orientation ) 00269 { 00270 Q_D(KDialog); 00271 if ( d->mButtonOrientation != orientation ) { 00272 d->mButtonOrientation = orientation; 00273 00274 if ( d->mActionSeparator ) 00275 d->mActionSeparator->setOrientation( d->mButtonOrientation ); 00276 00277 if ( d->mButtonOrientation == Qt::Vertical ) 00278 enableLinkedHelp( false ); // 2000-06-18 Espen: No support for this yet. 00279 } 00280 } 00281 00282 void KDialog::setEscapeButton( ButtonCode id ) 00283 { 00284 d_func()->mEscapeButton = id; 00285 } 00286 00287 void KDialog::setDefaultButton( ButtonCode newDefaultButton ) 00288 { 00289 Q_D(KDialog); 00290 00291 if (newDefaultButton == None) 00292 newDefaultButton = NoDefault; // #148969 00293 00294 const KDialog::ButtonCode oldDefault = defaultButton(); 00295 00296 bool oldDefaultHadFocus = false; 00297 00298 if (oldDefault != NoDefault) { 00299 KPushButton *old = button(oldDefault); 00300 if (old) { 00301 oldDefaultHadFocus = (focusWidget() == old); 00302 old->setDefault(false); 00303 } 00304 } 00305 00306 if (newDefaultButton != NoDefault) { 00307 KPushButton *b = button(newDefaultButton); 00308 if (b) { 00309 b->setDefault(true); 00310 if (focusWidget() == 0 || oldDefaultHadFocus) { 00311 // No widget had focus yet, or the old default button had 00312 // -> ok to give focus to the new default button, so that it's 00313 // really default (Enter triggers it). 00314 // But we don't do this if the kdialog user gave focus to a 00315 // specific widget in the dialog. 00316 b->setFocus(); 00317 } 00318 } 00319 } 00320 d->mDefaultButton = newDefaultButton; 00321 Q_ASSERT(defaultButton() == newDefaultButton); 00322 } 00323 00324 KDialog::ButtonCode KDialog::defaultButton() const 00325 { 00326 Q_D(const KDialog); 00327 QHashIterator<int, KPushButton*> it( d->mButtonList ); 00328 while ( it.hasNext() ) { 00329 it.next(); 00330 if (it.value()->isDefault()) { 00331 return (ButtonCode)it.key(); 00332 } 00333 } 00334 00335 return d->mDefaultButton; 00336 } 00337 00338 void KDialog::setMainWidget( QWidget *widget ) 00339 { 00340 Q_D(KDialog); 00341 if ( d->mMainWidget == widget ) 00342 return; 00343 d->mMainWidget = widget; 00344 if (d->mMainWidget && d->mMainWidget->layout()) { 00345 // Avoid double-margin problem 00346 d->mMainWidget->layout()->setMargin(0); 00347 } 00348 d->setupLayout(); 00349 } 00350 00351 QWidget *KDialog::mainWidget() 00352 { 00353 Q_D(KDialog); 00354 if (!d->mMainWidget) 00355 setMainWidget( new QWidget(this) ); 00356 return d->mMainWidget; 00357 } 00358 00359 QSize KDialog::sizeHint() const 00360 { 00361 Q_D(const KDialog); 00362 00363 if (!d->mMinSize.isEmpty()) 00364 return d->mMinSize.expandedTo( minimumSizeHint() ) + d->mIncSize; 00365 else { 00366 if (d->dirty) 00367 const_cast<KDialogPrivate*>(d)->queuedLayoutUpdate(); 00368 return QDialog::sizeHint() + d->mIncSize; 00369 } 00370 } 00371 00372 QSize KDialog::minimumSizeHint() const 00373 { 00374 Q_D(const KDialog); 00375 00376 if (d->dirty) 00377 const_cast<KDialogPrivate*>(d)->queuedLayoutUpdate(); 00378 return QDialog::minimumSizeHint() + d->mIncSize; 00379 } 00380 00381 // 00382 // Grab QDialogs keypresses if non-modal. 00383 // 00384 void KDialog::keyPressEvent( QKeyEvent *event ) 00385 { 00386 Q_D(KDialog); 00387 if ( event->modifiers() == 0 ) { 00388 if ( event->key() == Qt::Key_F1 ) { 00389 KPushButton *button = this->button( Help ); 00390 00391 if ( button ) { 00392 button->animateClick(); 00393 event->accept(); 00394 return; 00395 } 00396 } 00397 00398 if ( event->key() == Qt::Key_Escape ) { 00399 KPushButton *button = this->button( d->mEscapeButton ); 00400 00401 if ( button ) { 00402 button->animateClick(); 00403 event->accept(); 00404 return; 00405 } 00406 00407 } 00408 } else if ( event->key() == Qt::Key_F1 && event->modifiers() == Qt::ShiftModifier ) { 00409 QWhatsThis::enterWhatsThisMode(); 00410 event->accept(); 00411 return; 00412 } else if ( event->modifiers() == Qt::ControlModifier && 00413 ( event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter ) ) { 00414 // accept the dialog when Ctrl-Return is pressed 00415 KPushButton *button = this->button( Ok ); 00416 00417 if ( button ) { 00418 button->animateClick(); 00419 event->accept(); 00420 return; 00421 } 00422 } 00423 00424 QDialog::keyPressEvent( event ); 00425 } 00426 00427 int KDialog::marginHint() 00428 { 00429 return QApplication::style()->pixelMetric( QStyle::PM_DefaultChildMargin ); 00430 } 00431 00432 int KDialog::spacingHint() 00433 { 00434 return QApplication::style()->pixelMetric( QStyle::PM_DefaultLayoutSpacing ); 00435 } 00436 00437 int KDialog::groupSpacingHint() 00438 { 00439 return QApplication::fontMetrics().lineSpacing(); 00440 } 00441 00442 QString KDialog::makeStandardCaption( const QString &userCaption, 00443 QWidget* window, 00444 CaptionFlags flags ) 00445 { 00446 Q_UNUSED(window); 00447 QString caption = KGlobal::caption(); 00448 QString captionString = userCaption.isEmpty() ? caption : userCaption; 00449 00450 // If the document is modified, add '[modified]'. 00451 if (flags & ModifiedCaption) 00452 captionString += QString::fromUtf8(" [") + i18n("modified") + QString::fromUtf8("]"); 00453 00454 if ( !userCaption.isEmpty() ) { 00455 // Add the application name if: 00456 // User asked for it, it's not a duplication and the app name (caption()) is not empty 00457 if ( flags & AppNameCaption && 00458 !caption.isEmpty() && 00459 !userCaption.endsWith(caption) ) { 00460 // TODO: check to see if this is a transient/secondary window before trying to add the app name 00461 // on platforms that need this 00462 captionString += i18nc("Document/application separator in titlebar", " – ") + caption; 00463 } 00464 } 00465 00466 return captionString; 00467 } 00468 00469 void KDialog::setCaption( const QString &_caption ) 00470 { 00471 const QString caption = makeStandardCaption( _caption, this ); 00472 setPlainCaption( caption ); 00473 } 00474 00475 void KDialog::setCaption( const QString &caption, bool modified ) 00476 { 00477 CaptionFlags flags = HIGCompliantCaption; 00478 00479 if ( modified ) 00480 { 00481 flags |= ModifiedCaption; 00482 } 00483 00484 setPlainCaption( makeStandardCaption(caption, this, flags) ); 00485 } 00486 00487 00488 void KDialog::setPlainCaption( const QString &caption ) 00489 { 00490 if (QWidget *win = window()) { 00491 win->setWindowTitle( caption ); 00492 #ifdef Q_WS_X11 00493 NETWinInfo info( QX11Info::display(), win->winId(), QX11Info::appRootWindow(), 0 ); 00494 info.setName( caption.toUtf8().constData() ); 00495 #endif 00496 } 00497 } 00498 00499 void KDialog::resizeLayout( QWidget *widget, int margin, int spacing ) //static 00500 { 00501 if ( widget->layout() ) 00502 resizeLayout( widget->layout(), margin, spacing ); 00503 00504 if ( widget->children().count() > 0 ) { 00505 const QList<QObject*> list = widget->children(); 00506 foreach ( QObject *object, list ) { 00507 if ( object->isWidgetType() ) 00508 resizeLayout( (QWidget*)object, margin, spacing ); 00509 } 00510 } 00511 } 00512 00513 void KDialog::resizeLayout( QLayout *layout, int margin, int spacing ) //static 00514 { 00515 QLayoutItem *child; 00516 int pos = 0; 00517 00518 while ( (child = layout->itemAt( pos ) ) ) { 00519 if ( child->layout() ) 00520 resizeLayout( child->layout(), margin, spacing ); 00521 00522 ++pos; 00523 } 00524 00525 if ( layout->layout() ) { 00526 layout->layout()->setMargin( margin ); 00527 layout->layout()->setSpacing( spacing ); 00528 } 00529 } 00530 00531 static QRect screenRect( QWidget *widget, int screen ) 00532 { 00533 QDesktopWidget *desktop = QApplication::desktop(); 00534 KConfig gc( "kdeglobals", KConfig::NoGlobals ); 00535 KConfigGroup cg(&gc, "Windows" ); 00536 if ( desktop->isVirtualDesktop() && 00537 cg.readEntry( "XineramaEnabled", true ) && 00538 cg.readEntry( "XineramaPlacementEnabled", true ) ) { 00539 00540 if ( screen < 0 || screen >= desktop->numScreens() ) { 00541 if ( screen == -1 ) 00542 screen = desktop->primaryScreen(); 00543 else if ( screen == -3 ) 00544 screen = desktop->screenNumber( QCursor::pos() ); 00545 else 00546 screen = desktop->screenNumber( widget ); 00547 } 00548 00549 return desktop->availableGeometry( screen ); 00550 } else 00551 return desktop->geometry(); 00552 } 00553 00554 void KDialog::centerOnScreen( QWidget *widget, int screen ) 00555 { 00556 if ( !widget ) 00557 return; 00558 00559 #ifdef Q_WS_X11 00560 if( !( widget->windowFlags() & Qt::X11BypassWindowManagerHint ) && widget->windowType() != Qt::Popup 00561 && NETRootInfo( QX11Info::display(), NET::Supported ).isSupported( NET::WM2FullPlacement )) { 00562 return; // the WM can handle placement much better 00563 } 00564 #endif 00565 00566 QRect rect = screenRect( widget, screen ); 00567 00568 widget->move( rect.center().x() - widget->width() / 2, 00569 rect.center().y() - widget->height() / 2 ); 00570 } 00571 00572 bool KDialog::avoidArea( QWidget *widget, const QRect& area, int screen ) 00573 { 00574 if ( !widget ) 00575 return false; 00576 00577 QRect fg = widget->frameGeometry(); 00578 if ( !fg.intersects( area ) ) 00579 return true; // nothing to do. 00580 00581 const QRect scr = screenRect( widget, screen ); 00582 QRect avoid( area ); // let's add some margin 00583 avoid.translate( -5, -5 ); 00584 avoid.setRight( avoid.right() + 10 ); 00585 avoid.setBottom( avoid.bottom() + 10 ); 00586 00587 if ( qMax( fg.top(), avoid.top() ) <= qMin( fg.bottom(), avoid.bottom() ) ) { 00588 // We need to move the widget up or down 00589 int spaceAbove = qMax( 0, avoid.top() - scr.top() ); 00590 int spaceBelow = qMax( 0, scr.bottom() - avoid.bottom() ); 00591 if ( spaceAbove > spaceBelow ) // where's the biggest side? 00592 if ( fg.height() <= spaceAbove ) // big enough? 00593 fg.setY( avoid.top() - fg.height() ); 00594 else 00595 return false; 00596 else 00597 if ( fg.height() <= spaceBelow ) // big enough? 00598 fg.setY( avoid.bottom() ); 00599 else 00600 return false; 00601 } 00602 00603 if ( qMax( fg.left(), avoid.left() ) <= qMin( fg.right(), avoid.right() ) ) { 00604 // We need to move the widget left or right 00605 const int spaceLeft = qMax( 0, avoid.left() - scr.left() ); 00606 const int spaceRight = qMax( 0, scr.right() - avoid.right() ); 00607 if ( spaceLeft > spaceRight ) // where's the biggest side? 00608 if ( fg.width() <= spaceLeft ) // big enough? 00609 fg.setX( avoid.left() - fg.width() ); 00610 else 00611 return false; 00612 else 00613 if ( fg.width() <= spaceRight ) // big enough? 00614 fg.setX( avoid.right() ); 00615 else 00616 return false; 00617 } 00618 00619 widget->move( fg.x(), fg.y() ); 00620 00621 return true; 00622 } 00623 00624 void KDialog::showButtonSeparator( bool state ) 00625 { 00626 Q_D(KDialog); 00627 if ( ( d->mActionSeparator != 0 ) == state ) 00628 return; 00629 if ( state ) { 00630 if ( d->mActionSeparator ) 00631 return; 00632 00633 d->mActionSeparator = new KSeparator( this ); 00634 d->mActionSeparator->setOrientation( d->mButtonOrientation ); 00635 } else { 00636 delete d->mActionSeparator; 00637 d->mActionSeparator = 0; 00638 } 00639 00640 d->setupLayout(); 00641 } 00642 00643 void KDialog::setInitialSize( const QSize &size ) 00644 { 00645 d_func()->mMinSize = size; 00646 adjustSize(); 00647 } 00648 00649 void KDialog::incrementInitialSize( const QSize &size ) 00650 { 00651 d_func()->mIncSize = size; 00652 adjustSize(); 00653 } 00654 00655 KPushButton *KDialog::button( ButtonCode id ) const 00656 { 00657 Q_D(const KDialog); 00658 return d->mButtonList.value( id, 0 ); 00659 } 00660 00661 void KDialog::enableButton( ButtonCode id, bool state ) 00662 { 00663 KPushButton *button = this->button( id ); 00664 if ( button ) 00665 button->setEnabled( state ); 00666 } 00667 00668 bool KDialog::isButtonEnabled( ButtonCode id ) const 00669 { 00670 KPushButton *button = this->button( id ); 00671 if ( button ) 00672 return button->isEnabled(); 00673 00674 return false; 00675 } 00676 00677 void KDialog::enableButtonOk( bool state ) 00678 { 00679 enableButton( Ok, state ); 00680 } 00681 00682 void KDialog::enableButtonApply( bool state ) 00683 { 00684 enableButton( Apply, state ); 00685 } 00686 00687 void KDialog::enableButtonCancel( bool state ) 00688 { 00689 enableButton( Cancel, state ); 00690 } 00691 00692 void KDialog::showButton( ButtonCode id, bool state ) 00693 { 00694 KPushButton *button = this->button( id ); 00695 if ( button ) 00696 state ? button->show() : button->hide(); 00697 } 00698 00699 void KDialog::setButtonGuiItem( ButtonCode id, const KGuiItem &item ) 00700 { 00701 KPushButton *button = this->button( id ); 00702 if ( !button ) 00703 return; 00704 00705 button->setGuiItem( item ); 00706 } 00707 00708 void KDialog::setButtonMenu( ButtonCode id, QMenu *menu, ButtonPopupMode popupmode) 00709 { 00710 KPushButton *button = this->button( id ); 00711 if ( button ) { 00712 if (popupmode==InstantPopup) 00713 button->setMenu( menu ); 00714 else 00715 button->setDelayedMenu(menu); 00716 } 00717 } 00718 00719 void KDialog::setButtonText( ButtonCode id, const QString &text ) 00720 { 00721 Q_D(KDialog); 00722 if ( !d->mSettingDetails && (id == Details) ) { 00723 d->mDetailsButtonText = text; 00724 setDetailsWidgetVisible( d->mDetailsVisible ); 00725 return; 00726 } 00727 00728 KPushButton *button = this->button( id ); 00729 if ( button ) 00730 button->setText( text ); 00731 } 00732 00733 QString KDialog::buttonText( ButtonCode id ) const 00734 { 00735 KPushButton *button = this->button( id ); 00736 if ( button ) 00737 return button->text(); 00738 else 00739 return QString(); 00740 } 00741 00742 void KDialog::setButtonIcon( ButtonCode id, const KIcon &icon ) 00743 { 00744 KPushButton *button = this->button( id ); 00745 if ( button ) 00746 button->setIcon( icon ); 00747 } 00748 00749 KIcon KDialog::buttonIcon( ButtonCode id ) const 00750 { 00751 KPushButton *button = this->button( id ); 00752 if ( button ) 00753 return KIcon(button->icon()); 00754 else 00755 return KIcon(); 00756 } 00757 00758 void KDialog::setButtonToolTip( ButtonCode id, const QString &text ) 00759 { 00760 KPushButton *button = this->button( id ); 00761 if ( button ) { 00762 if ( text.isEmpty() ) 00763 button->setToolTip( QString() ); 00764 else 00765 button->setToolTip( text ); 00766 } 00767 } 00768 00769 QString KDialog::buttonToolTip( ButtonCode id ) const 00770 { 00771 KPushButton *button = this->button( id ); 00772 if ( button ) 00773 return button->toolTip(); 00774 else 00775 return QString(); 00776 } 00777 00778 void KDialog::setButtonWhatsThis( ButtonCode id, const QString &text ) 00779 { 00780 KPushButton *button = this->button( id ); 00781 if ( button ) { 00782 if ( text.isEmpty() ) 00783 button->setWhatsThis( QString() ); 00784 else 00785 button->setWhatsThis( text ); 00786 } 00787 } 00788 00789 QString KDialog::buttonWhatsThis( ButtonCode id ) const 00790 { 00791 KPushButton *button = this->button( id ); 00792 if ( button ) 00793 return button->whatsThis(); 00794 else 00795 return QString(); 00796 } 00797 00798 void KDialog::setButtonFocus( ButtonCode id ) 00799 { 00800 KPushButton *button = this->button( id ); 00801 if ( button ) { 00802 button->setFocus(); 00803 } 00804 } 00805 00806 void KDialog::setDetailsWidget( QWidget *detailsWidget ) 00807 { 00808 Q_D(KDialog); 00809 if ( d->mDetailsWidget == detailsWidget ) 00810 return; 00811 delete d->mDetailsWidget; 00812 d->mDetailsWidget = detailsWidget; 00813 00814 if ( d->mDetailsWidget->parentWidget() != this ) 00815 d->mDetailsWidget->setParent( this ); 00816 00817 d->mDetailsWidget->hide(); 00818 d->setupLayout(); 00819 00820 if ( !d->mSettingDetails ) 00821 setDetailsWidgetVisible( d->mDetailsVisible ); 00822 } 00823 00824 bool KDialog::isDetailsWidgetVisible() const 00825 { 00826 return d_func()->mDetailsVisible; 00827 } 00828 00829 void KDialog::setDetailsWidgetVisible( bool visible ) 00830 { 00831 Q_D(KDialog); 00832 if ( d->mDetailsButtonText.isEmpty() ) 00833 d->mDetailsButtonText = i18n( "&Details" ); 00834 00835 d->mSettingDetails = true; 00836 d->mDetailsVisible = visible; 00837 if ( d->mDetailsVisible ) { 00838 emit aboutToShowDetails(); 00839 setButtonText( Details, d->mDetailsButtonText + " <<" ); 00840 if ( d->mDetailsWidget ) { 00841 if ( layout() ) 00842 layout()->setEnabled( false ); 00843 00844 d->mDetailsWidget->show(); 00845 00846 adjustSize(); 00847 00848 if ( layout() ) { 00849 layout()->activate(); 00850 layout()->setEnabled( true ); 00851 } 00852 } 00853 } else { 00854 setButtonText( Details, d->mDetailsButtonText + " >>" ); 00855 if ( d->mDetailsWidget ) 00856 d->mDetailsWidget->hide(); 00857 00858 if ( layout() ) 00859 layout()->activate(); 00860 00861 adjustSize(); 00862 } 00863 00864 d->mSettingDetails = false; 00865 } 00866 00867 void KDialog::delayedDestruct() 00868 { 00869 if ( isVisible() ) 00870 hide(); 00871 00872 deleteLater(); 00873 } 00874 00875 00876 void KDialog::slotButtonClicked( int button ) 00877 { 00878 Q_D(KDialog); 00879 emit buttonClicked( static_cast<KDialog::ButtonCode>(button) ); 00880 00881 switch( button ) { 00882 case Ok: 00883 emit okClicked(); 00884 accept(); 00885 break; 00886 case Apply: 00887 emit applyClicked(); 00888 break; 00889 case Try: 00890 emit tryClicked(); 00891 break; 00892 case User3: 00893 emit user3Clicked(); 00894 break; 00895 case User2: 00896 emit user2Clicked(); 00897 break; 00898 case User1: 00899 emit user1Clicked(); 00900 break; 00901 case Yes: 00902 emit yesClicked(); 00903 done( Yes ); 00904 break; 00905 case No: 00906 emit noClicked(); 00907 done( No ); 00908 break; 00909 case Cancel: 00910 emit cancelClicked(); 00911 reject(); 00912 break; 00913 case Close: 00914 emit closeClicked(); 00915 done(Close); // KDE5: call reject() instead; more QDialog-like. 00916 break; 00917 case Help: 00918 emit helpClicked(); 00919 if ( !d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty() ) 00920 KToolInvocation::invokeHelp( d->mAnchor, d->mHelpApp ); 00921 break; 00922 case Default: 00923 emit defaultClicked(); 00924 break; 00925 case Reset: 00926 emit resetClicked(); 00927 break; 00928 case Details: 00929 setDetailsWidgetVisible( !d->mDetailsVisible ); 00930 break; 00931 } 00932 00933 // If we're here from the closeEvent, and auto-delete is on, well, auto-delete now. 00934 if (d->mDeferredDelete) { 00935 d->mDeferredDelete = false; 00936 delayedDestruct(); 00937 } 00938 } 00939 00940 void KDialog::enableLinkedHelp( bool state ) 00941 { 00942 Q_D(KDialog); 00943 if ( ( d->mUrlHelp != 0 ) == state ) 00944 return; 00945 if ( state ) { 00946 if ( d->mUrlHelp ) 00947 return; 00948 00949 d->mUrlHelp = new KUrlLabel( this ); 00950 d->mUrlHelp->setText( helpLinkText() ); 00951 d->mUrlHelp->setFloatEnabled( true ); 00952 d->mUrlHelp->setUnderline( true ); 00953 d->mUrlHelp->setMinimumHeight( fontMetrics().height() + marginHint() ); 00954 connect( d->mUrlHelp, SIGNAL(leftClickedUrl()), SLOT(helpLinkClicked()) ); 00955 00956 d->mUrlHelp->show(); 00957 } else { 00958 delete d->mUrlHelp; 00959 d->mUrlHelp = 0; 00960 } 00961 00962 d->setupLayout(); 00963 } 00964 00965 00966 void KDialog::setHelp( const QString &anchor, const QString &appname ) 00967 { 00968 Q_D(KDialog); 00969 d->mAnchor = anchor; 00970 d->mHelpApp = appname; 00971 } 00972 00973 00974 void KDialog::setHelpLinkText( const QString &text ) 00975 { 00976 Q_D(KDialog); 00977 d->mHelpLinkText = text; 00978 if ( d->mUrlHelp ) 00979 d->mUrlHelp->setText( helpLinkText() ); 00980 } 00981 00982 QString KDialog::helpLinkText() const 00983 { 00984 Q_D(const KDialog); 00985 return ( d->mHelpLinkText.isEmpty() ? i18n( "Get help..." ) : d->mHelpLinkText ); 00986 } 00987 00988 void KDialog::updateGeometry() 00989 { 00990 } 00991 00992 void KDialog::hideEvent( QHideEvent *event ) 00993 { 00994 emit hidden(); 00995 00996 if ( !event->spontaneous() ) 00997 emit finished(); 00998 } 00999 01000 void KDialog::closeEvent( QCloseEvent *event ) 01001 { 01002 Q_D(KDialog); 01003 KPushButton *button = this->button(d->mEscapeButton); 01004 if (button && !isHidden()) { 01005 button->animateClick(); 01006 01007 if (testAttribute(Qt::WA_DeleteOnClose)) { 01008 // Don't let QWidget::close do a deferred delete just yet, wait for the click first 01009 d->mDeferredDelete = true; 01010 setAttribute(Qt::WA_DeleteOnClose, false); 01011 } 01012 } else { 01013 QDialog::closeEvent(event); 01014 } 01015 } 01016 01017 void KDialog::restoreDialogSize( const KConfigGroup& cfg ) 01018 { 01019 int width, height; 01020 int scnum = QApplication::desktop()->screenNumber( parentWidget() ); 01021 QRect desk = QApplication::desktop()->screenGeometry( scnum ); 01022 01023 width = sizeHint().width(); 01024 height = sizeHint().height(); 01025 01026 width = cfg.readEntry( QString::fromLatin1( "Width %1" ).arg( desk.width() ), width ); 01027 height = cfg.readEntry( QString::fromLatin1( "Height %1" ).arg( desk.height() ), height ); 01028 01029 resize( width, height ); 01030 } 01031 01032 void KDialog::saveDialogSize( KConfigGroup& config, KConfigGroup::WriteConfigFlags options ) const 01033 { 01034 int scnum = QApplication::desktop()->screenNumber( parentWidget() ); 01035 QRect desk = QApplication::desktop()->screenGeometry( scnum ); 01036 01037 const QSize sizeToSave = size(); 01038 01039 config.writeEntry( QString::fromLatin1("Width %1").arg( desk.width() ), sizeToSave.width(), options ); 01040 config.writeEntry( QString::fromLatin1("Height %1").arg( desk.height() ), sizeToSave.height(), options ); 01041 } 01042 01043 void KDialog::setAllowEmbeddingInGraphicsView( bool allowEmbedding ) 01044 { 01045 sAllowEmbeddingInGraphicsView = allowEmbedding; 01046 } 01047 01048 01049 class KDialogQueue::Private 01050 { 01051 public: 01052 Private(KDialogQueue *q): q(q) {} 01053 01054 void slotShowQueuedDialog(); 01055 01056 KDialogQueue *q; 01057 QList< QPointer<QDialog> > queue; 01058 bool busy; 01059 01060 }; 01061 01062 KDialogQueue* KDialogQueue::self() 01063 { 01064 K_GLOBAL_STATIC(KDialogQueue, _self) 01065 return _self; 01066 } 01067 01068 KDialogQueue::KDialogQueue() 01069 : d( new Private(this) ) 01070 { 01071 d->busy = false; 01072 } 01073 01074 KDialogQueue::~KDialogQueue() 01075 { 01076 delete d; 01077 } 01078 01079 // static 01080 void KDialogQueue::queueDialog( QDialog *dialog ) 01081 { 01082 KDialogQueue *_this = self(); 01083 _this->d->queue.append( dialog ); 01084 01085 QTimer::singleShot( 0, _this, SLOT( slotShowQueuedDialog() ) ); 01086 } 01087 01088 void KDialogQueue::Private::slotShowQueuedDialog() 01089 { 01090 if ( busy ) 01091 return; 01092 01093 QDialog *dialog; 01094 do { 01095 if ( queue.isEmpty() ) 01096 return; 01097 dialog = queue.first(); 01098 queue.pop_front(); 01099 } while( !dialog ); 01100 01101 busy = true; 01102 dialog->exec(); 01103 busy = false; 01104 delete dialog; 01105 01106 if ( !queue.isEmpty() ) 01107 QTimer::singleShot( 20, q, SLOT( slotShowQueuedDialog() ) ); 01108 } 01109 01110 #include "kdialog.moc" 01111 #include "kdialogqueue_p.moc"
KDE 4.6 API Reference