Warning, file /office/calligra/libs/widgets/KoDialog.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*  This file is part of the KDE Libraries
0002  *  Copyright (C) 1998 Thomas Tanghus (tanghus@earthling.net)
0003  *  Additions 1999-2000 by Espen Sand (espen@kde.org)
0004  *                      by Holger Freyther <freyther@kde.org>
0005  *            2005-2009 by Olivier Goffart (ogoffart at kde.org)
0006  *
0007  *  This library is free software; you can redistribute it and/or
0008  *  modify it under the terms of the GNU Library General Public
0009  *  License as published by the Free Software Foundation; either
0010  *  version 2 of the License, or (at your option) any later version.
0011  *
0012  *  This library is distributed in the hope that it will be useful,
0013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  *  Library General Public License for more details.
0016  *
0017  *  You should have received a copy of the GNU Library General Public License
0018  *  along with this library; see the file COPYING.LIB.  If not, write to
0019  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  *  Boston, MA 02110-1301, USA.
0021  */
0022 
0023 #include "KoDialog.h"
0024 #include "KoDialog_p.h"
0025 
0026 #include <QApplication>
0027 #include <QDesktopWidget>
0028 #include <QDialogButtonBox>
0029 #include <QHBoxLayout>
0030 #include <QHideEvent>
0031 #include <QPointer>
0032 #include <QStyle>
0033 #include <QTimer>
0034 #include <QVBoxLayout>
0035 #include <QWhatsThis>
0036 #include <QDebug>
0037 #include <QPushButton>
0038 
0039 #include <kconfig.h>
0040 #include <klocalizedstring.h>
0041 
0042 #include <kseparator.h>
0043 #include <kstandardguiitem.h>
0044 #include <khelpclient.h>
0045 #include <kurllabel.h>
0046 #include <kwindowconfig.h>
0047 
0048 void KoDialogPrivate::setupLayout()
0049 {
0050     Q_Q(KoDialog);
0051     if (!dirty) {
0052         QMetaObject::invokeMethod(q, "queuedLayoutUpdate", Qt::QueuedConnection);
0053         dirty = true;
0054     }
0055 }
0056 
0057 void KoDialogPrivate::queuedLayoutUpdate()
0058 {
0059     if (!dirty) {
0060         return;
0061     }
0062 
0063     dirty = false;
0064 
0065     Q_Q(KoDialog);
0066 
0067     // Don't lose the focus widget when re-creating the layout.
0068     // Testcase: KOrganizer's "Select Categories" dialog
0069     QPointer<QWidget> focusWidget = mMainWidget ? mMainWidget->focusWidget() : 0;
0070 
0071     if (q->layout() && q->layout() != mTopLayout) {
0072         qWarning() << q->metaObject()->className() << "created with a layout; don't do that, KoDialog takes care of it, use mainWidget or setMainWidget instead";
0073         delete q->layout();
0074     }
0075 
0076     delete mTopLayout;
0077 
0078     if (mButtonOrientation == Qt::Horizontal) {
0079         mTopLayout = new QVBoxLayout(q);
0080     } else {
0081         mTopLayout = new QHBoxLayout(q);
0082     }
0083 
0084     if (mUrlHelp) {
0085         mTopLayout->addWidget(mUrlHelp, 0, Qt::AlignRight);
0086     }
0087 
0088     if (mMainWidget) {
0089         mTopLayout->addWidget(mMainWidget, 10);
0090     }
0091 
0092     if (mDetailsWidget) {
0093         mTopLayout->addWidget(mDetailsWidget);
0094     }
0095 
0096     if (mActionSeparator) {
0097         mTopLayout->addWidget(mActionSeparator);
0098     }
0099 
0100     if (mButtonBox) {
0101         mButtonBox->setOrientation(mButtonOrientation);
0102         mTopLayout->addWidget(mButtonBox);
0103     }
0104 
0105     if (focusWidget) {
0106         focusWidget->setFocus();
0107     }
0108 }
0109 
0110 void KoDialogPrivate::appendButton(KoDialog::ButtonCode key, const KGuiItem &item)
0111 {
0112     Q_Q(KoDialog);
0113 
0114     QDialogButtonBox::ButtonRole role = QDialogButtonBox::InvalidRole;
0115     switch (key) {
0116     case KoDialog::Help:
0117     case KoDialog::Details:
0118         role = QDialogButtonBox::HelpRole;
0119         break;
0120     case KoDialog::Default:
0121     case KoDialog::Reset:
0122         role = QDialogButtonBox::ResetRole;
0123         break;
0124     case KoDialog::Ok:
0125         role = QDialogButtonBox::AcceptRole;
0126         break;
0127     case KoDialog::Apply:
0128         role = QDialogButtonBox::ApplyRole;
0129         break;
0130     case KoDialog::Try:
0131     case KoDialog::Yes:
0132         role = QDialogButtonBox::YesRole;
0133         break;
0134     case KoDialog::Close:
0135     case KoDialog::Cancel:
0136         role = QDialogButtonBox::RejectRole;
0137         break;
0138     case KoDialog::No:
0139         role = QDialogButtonBox::NoRole;
0140         break;
0141     case KoDialog::User1:
0142     case KoDialog::User2:
0143     case KoDialog::User3:
0144         role = QDialogButtonBox::ActionRole;
0145         break;
0146     default:
0147         role = QDialogButtonBox::InvalidRole;
0148         break;
0149     }
0150 
0151     if (role == QDialogButtonBox::InvalidRole) {
0152         return;
0153     }
0154 
0155     QPushButton *button = new QPushButton;
0156     KGuiItem::assign(button, item);
0157     mButtonBox->addButton(button, role);
0158 
0159     mButtonList.insert(key, button);
0160 
0161     QObject::connect(button, &QPushButton::clicked, [this, key] { q_ptr->slotButtonClicked(key); });
0162 
0163     if (key == mDefaultButton) {
0164         // Now that it exists, set it as default
0165         q->setDefaultButton(mDefaultButton);
0166     }
0167 }
0168 
0169 void KoDialogPrivate::init(KoDialog *q)
0170 {
0171     q_ptr = q;
0172 
0173     dirty = false;
0174 
0175     q->setButtons(KoDialog::Ok | KoDialog::Cancel);
0176     q->setDefaultButton(KoDialog::Ok);
0177 
0178     q->setPlainCaption(qApp->applicationDisplayName()); // set appropriate initial window title for case it gets not set later
0179 }
0180 
0181 void KoDialogPrivate::helpLinkClicked()
0182 {
0183     q_ptr->slotButtonClicked(KoDialog::Help);
0184 }
0185 
0186 KoDialog::KoDialog(QWidget *parent, Qt::WindowFlags flags)
0187     : QDialog(parent, flags)
0188     , d_ptr(new KoDialogPrivate)
0189 {
0190     d_ptr->init(this);
0191 }
0192 
0193 KoDialog::KoDialog(KoDialogPrivate &dd, QWidget *parent, Qt::WindowFlags flags)
0194     : QDialog(parent, flags)
0195     , d_ptr(&dd)
0196 {
0197     d_ptr->init(this);
0198 }
0199 
0200 KoDialog::~KoDialog()
0201 {
0202     delete d_ptr;
0203 }
0204 
0205 void KoDialog::setButtons(ButtonCodes buttonMask)
0206 {
0207     Q_D(KoDialog);
0208     if (d->mButtonBox) {
0209         d->mButtonList.clear();
0210 
0211         delete d->mButtonBox;
0212         d->mButtonBox = 0;
0213     }
0214 
0215     if (buttonMask & Cancel) {
0216         buttonMask &= ~Close;
0217     }
0218 
0219     if (buttonMask & Apply) {
0220         buttonMask &= ~Try;
0221     }
0222 
0223     if (buttonMask & Details) {
0224         buttonMask &= ~Default;
0225     }
0226 
0227     if (buttonMask == None) {
0228         d->setupLayout();
0229         return; // When we want no button box
0230     }
0231 
0232     d->mEscapeButton = (buttonMask & Cancel) ? Cancel : Close;
0233     d->mButtonBox = new QDialogButtonBox(this);
0234 
0235     if (buttonMask & Help) {
0236         d->appendButton(Help, KStandardGuiItem::help());
0237     }
0238     if (buttonMask & Default) {
0239         d->appendButton(Default, KStandardGuiItem::defaults());
0240     }
0241     if (buttonMask & Reset) {
0242         d->appendButton(Reset, KStandardGuiItem::reset());
0243     }
0244     if (buttonMask & User3) {
0245         d->appendButton(User3, KGuiItem());
0246     }
0247     if (buttonMask & User2) {
0248         d->appendButton(User2, KGuiItem());
0249     }
0250     if (buttonMask & User1) {
0251         d->appendButton(User1, KGuiItem());
0252     }
0253     if (buttonMask & Ok) {
0254         d->appendButton(Ok, KStandardGuiItem::ok());
0255     }
0256     if (buttonMask & Apply) {
0257         d->appendButton(Apply, KStandardGuiItem::apply());
0258     }
0259     if (buttonMask & Try) {
0260         d->appendButton(Try, KGuiItem(i18n("&Try")));
0261     }
0262     if (buttonMask & Cancel) {
0263         d->appendButton(Cancel, KStandardGuiItem::cancel());
0264     }
0265     if (buttonMask & Close) {
0266         d->appendButton(Close, KStandardGuiItem::close());
0267     }
0268     if (buttonMask & Yes) {
0269         d->appendButton(Yes, KStandardGuiItem::yes());
0270     }
0271     if (buttonMask & No) {
0272         d->appendButton(No, KStandardGuiItem::no());
0273     }
0274     if (buttonMask & Details) {
0275         d->appendButton(Details, KGuiItem(QString(), "help-about"));
0276         setDetailsWidgetVisible(false);
0277     }
0278 
0279     d->setupLayout();
0280 }
0281 
0282 void KoDialog::setButtonsOrientation(Qt::Orientation orientation)
0283 {
0284     Q_D(KoDialog);
0285     if (d->mButtonOrientation != orientation) {
0286         d->mButtonOrientation = orientation;
0287 
0288         if (d->mActionSeparator) {
0289             d->mActionSeparator->setOrientation(d->mButtonOrientation);
0290         }
0291 
0292         if (d->mButtonOrientation == Qt::Vertical) {
0293             enableLinkedHelp(false);    // 2000-06-18 Espen: No support for this yet.
0294         }
0295     }
0296 }
0297 
0298 void KoDialog::setEscapeButton(ButtonCode id)
0299 {
0300     d_func()->mEscapeButton = id;
0301 }
0302 
0303 void KoDialog::setDefaultButton(ButtonCode newDefaultButton)
0304 {
0305     Q_D(KoDialog);
0306 
0307     if (newDefaultButton == None) {
0308         newDefaultButton = NoDefault;    // #148969
0309     }
0310 
0311     const KoDialog::ButtonCode oldDefault = defaultButton();
0312 
0313     bool oldDefaultHadFocus = false;
0314 
0315     if (oldDefault != NoDefault) {
0316         QPushButton *old = button(oldDefault);
0317         if (old) {
0318             oldDefaultHadFocus = (focusWidget() == old);
0319             old->setDefault(false);
0320         }
0321     }
0322 
0323     if (newDefaultButton != NoDefault) {
0324         QPushButton *b = button(newDefaultButton);
0325         if (b) {
0326             b->setDefault(true);
0327             if (focusWidget() == 0 || oldDefaultHadFocus) {
0328                 // No widget had focus yet, or the old default button had
0329                 // -> ok to give focus to the new default button, so that it's
0330                 // really default (Enter triggers it).
0331                 // But we don't do this if the kdialog user gave focus to a
0332                 // specific widget in the dialog.
0333                 b->setFocus();
0334             }
0335         }
0336     }
0337     d->mDefaultButton = newDefaultButton;
0338     Q_ASSERT(defaultButton() == newDefaultButton);
0339 }
0340 
0341 KoDialog::ButtonCode KoDialog::defaultButton() const
0342 {
0343     Q_D(const KoDialog);
0344     QHashIterator<int, QPushButton *> it(d->mButtonList);
0345     while (it.hasNext()) {
0346         it.next();
0347         if (it.value()->isDefault()) {
0348             return (ButtonCode)it.key();
0349         }
0350     }
0351 
0352     return d->mDefaultButton;
0353 }
0354 
0355 void KoDialog::setMainWidget(QWidget *widget)
0356 {
0357     Q_D(KoDialog);
0358     if (d->mMainWidget == widget) {
0359         return;
0360     }
0361     d->mMainWidget = widget;
0362     if (d->mMainWidget && d->mMainWidget->layout()) {
0363         // Avoid double-margin problem
0364         d->mMainWidget->layout()->setMargin(0);
0365     }
0366     d->setupLayout();
0367 }
0368 
0369 QWidget *KoDialog::mainWidget()
0370 {
0371     Q_D(KoDialog);
0372     if (!d->mMainWidget) {
0373         setMainWidget(new QWidget(this));
0374     }
0375     return d->mMainWidget;
0376 }
0377 
0378 QSize KoDialog::sizeHint() const
0379 {
0380     Q_D(const KoDialog);
0381 
0382     if (!d->mMinSize.isEmpty()) {
0383         return d->mMinSize.expandedTo(minimumSizeHint()) + d->mIncSize;
0384     } else {
0385         if (d->dirty) {
0386             const_cast<KoDialogPrivate *>(d)->queuedLayoutUpdate();
0387         }
0388         return QDialog::sizeHint() + d->mIncSize;
0389     }
0390 }
0391 
0392 QSize KoDialog::minimumSizeHint() const
0393 {
0394     Q_D(const KoDialog);
0395 
0396     if (d->dirty) {
0397         const_cast<KoDialogPrivate *>(d)->queuedLayoutUpdate();
0398     }
0399     return QDialog::minimumSizeHint() + d->mIncSize;
0400 }
0401 
0402 //
0403 // Grab QDialogs keypresses if non-modal.
0404 //
0405 void KoDialog::keyPressEvent(QKeyEvent *event)
0406 {
0407     Q_D(KoDialog);
0408     if (event->modifiers() == 0) {
0409         if (event->key() == Qt::Key_F1) {
0410             QPushButton *button = this->button(Help);
0411 
0412             if (button) {
0413                 button->animateClick();
0414                 event->accept();
0415                 return;
0416             }
0417         }
0418 
0419         if (event->key() == Qt::Key_Escape) {
0420             QPushButton *button = this->button(d->mEscapeButton);
0421 
0422             if (button) {
0423                 button->animateClick();
0424                 event->accept();
0425                 return;
0426             }
0427 
0428         }
0429     } else if (event->key() == Qt::Key_F1 && event->modifiers() == Qt::ShiftModifier) {
0430         QWhatsThis::enterWhatsThisMode();
0431         event->accept();
0432         return;
0433     } else if (event->modifiers() == Qt::ControlModifier &&
0434                (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)) {
0435         // accept the dialog when Ctrl-Return is pressed
0436         QPushButton *button = this->button(Ok);
0437 
0438         if (button) {
0439             button->animateClick();
0440             event->accept();
0441             return;
0442         }
0443     }
0444 
0445     QDialog::keyPressEvent(event);
0446 }
0447 
0448 int KoDialog::marginHint()
0449 {
0450     return QApplication::style()->pixelMetric(QStyle::PM_DefaultChildMargin);
0451 }
0452 
0453 int KoDialog::spacingHint()
0454 {
0455     return QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
0456 }
0457 
0458 int KoDialog::groupSpacingHint()
0459 {
0460     return QApplication::fontMetrics().lineSpacing();
0461 }
0462 
0463 QString KoDialog::makeStandardCaption(const QString &userCaption,
0464                                      QWidget *window,
0465                                      CaptionFlags flags)
0466 {
0467     Q_UNUSED(window);
0468     QString caption = qApp->applicationDisplayName();
0469     QString captionString = userCaption.isEmpty() ? caption : userCaption;
0470 
0471     // If the document is modified, add '[modified]'.
0472     if (flags & ModifiedCaption) {
0473         captionString += QString::fromUtf8(" [") + i18n("modified") + QString::fromUtf8("]");
0474     }
0475 
0476     if (!userCaption.isEmpty()) {
0477         // Add the application name if:
0478         // User asked for it, it's not a duplication  and the app name (caption()) is not empty
0479         if (flags & AppNameCaption &&
0480                 !caption.isEmpty() &&
0481                 !userCaption.endsWith(caption)) {
0482             // TODO: check to see if this is a transient/secondary window before trying to add the app name
0483             //       on platforms that need this
0484             captionString += i18nc("Document/application separator in titlebar", " – ") + caption;
0485         }
0486     }
0487 
0488     return captionString;
0489 }
0490 
0491 void KoDialog::setCaption(const QString &_caption)
0492 {
0493     const QString caption = makeStandardCaption(_caption, this);
0494     setPlainCaption(caption);
0495 }
0496 
0497 void KoDialog::setCaption(const QString &caption, bool modified)
0498 {
0499     CaptionFlags flags = HIGCompliantCaption;
0500 
0501     // ### Qt5 TODO: port to [*], see QWidget::setWindowFilePath
0502     if (modified) {
0503         flags |= ModifiedCaption;
0504     }
0505 
0506     setPlainCaption(makeStandardCaption(caption, this, flags));
0507 }
0508 
0509 void KoDialog::setPlainCaption(const QString &caption)
0510 {
0511     if (QWidget *win = window()) {
0512         win->setWindowTitle(caption);
0513     }
0514 }
0515 
0516 void KoDialog::resizeLayout(QWidget *widget, int margin, int spacing)   //static
0517 {
0518     if (widget->layout()) {
0519         resizeLayout(widget->layout(), margin, spacing);
0520     }
0521 
0522     if (widget->children().count() > 0) {
0523         const QList<QObject *> list = widget->children();
0524         foreach (QObject *object, list) {
0525             if (object->isWidgetType()) {
0526                 resizeLayout((QWidget *)object, margin, spacing);
0527             }
0528         }
0529     }
0530 }
0531 
0532 void KoDialog::resizeLayout(QLayout *layout, int margin, int spacing)   //static
0533 {
0534     QLayoutItem *child;
0535     int pos = 0;
0536 
0537     while ((child = layout->itemAt(pos))) {
0538         if (child->layout()) {
0539             resizeLayout(child->layout(), margin, spacing);
0540         }
0541 
0542         ++pos;
0543     }
0544 
0545     if (layout->layout()) {
0546         layout->layout()->setMargin(margin);
0547         layout->layout()->setSpacing(spacing);
0548     }
0549 }
0550 
0551 static QRect screenRect(QWidget *widget, int screen)
0552 {
0553     QDesktopWidget *desktop = QApplication::desktop();
0554     KConfig gc("kdeglobals", KConfig::NoGlobals);
0555     KConfigGroup cg(&gc, "Windows");
0556     if (desktop->isVirtualDesktop() &&
0557             cg.readEntry("XineramaEnabled", true) &&
0558             cg.readEntry("XineramaPlacementEnabled", true)) {
0559 
0560         if (screen < 0 || screen >= desktop->numScreens()) {
0561             if (screen == -1) {
0562                 screen = desktop->primaryScreen();
0563             } else if (screen == -3) {
0564                 screen = desktop->screenNumber(QCursor::pos());
0565             } else {
0566                 screen = desktop->screenNumber(widget);
0567             }
0568         }
0569 
0570         return desktop->availableGeometry(screen);
0571     } else {
0572         return desktop->geometry();
0573     }
0574 }
0575 
0576 void KoDialog::centerOnScreen(QWidget *widget, int screen)
0577 {
0578     if (!widget) {
0579         return;
0580     }
0581 
0582     QRect rect = screenRect(widget, screen);
0583 
0584     widget->move(rect.center().x() - widget->width() / 2,
0585                  rect.center().y() - widget->height() / 2);
0586 }
0587 
0588 bool KoDialog::avoidArea(QWidget *widget, const QRect &area, int screen)
0589 {
0590     if (!widget) {
0591         return false;
0592     }
0593 
0594     QRect fg = widget->frameGeometry();
0595     if (!fg.intersects(area)) {
0596         return true;    // nothing to do.
0597     }
0598 
0599     const QRect scr = screenRect(widget, screen);
0600     QRect avoid(area);   // let's add some margin
0601     avoid.translate(-5, -5);
0602     avoid.setRight(avoid.right() + 10);
0603     avoid.setBottom(avoid.bottom() + 10);
0604 
0605     if (qMax(fg.top(), avoid.top()) <= qMin(fg.bottom(), avoid.bottom())) {
0606         // We need to move the widget up or down
0607         int spaceAbove = qMax(0, avoid.top() - scr.top());
0608         int spaceBelow = qMax(0, scr.bottom() - avoid.bottom());
0609         if (spaceAbove > spaceBelow)   // where's the biggest side?
0610             if (fg.height() <= spaceAbove) { // big enough?
0611                 fg.setY(avoid.top() - fg.height());
0612             } else {
0613                 return false;
0614             }
0615         else if (fg.height() <= spaceBelow) { // big enough?
0616             fg.setY(avoid.bottom());
0617         } else {
0618             return false;
0619         }
0620     }
0621 
0622     if (qMax(fg.left(), avoid.left()) <= qMin(fg.right(), avoid.right())) {
0623         // We need to move the widget left or right
0624         const int spaceLeft = qMax(0, avoid.left() - scr.left());
0625         const int spaceRight = qMax(0, scr.right() - avoid.right());
0626         if (spaceLeft > spaceRight)   // where's the biggest side?
0627             if (fg.width() <= spaceLeft) { // big enough?
0628                 fg.setX(avoid.left() - fg.width());
0629             } else {
0630                 return false;
0631             }
0632         else if (fg.width() <= spaceRight) { // big enough?
0633             fg.setX(avoid.right());
0634         } else {
0635             return false;
0636         }
0637     }
0638 
0639     widget->move(fg.x(), fg.y());
0640 
0641     return true;
0642 }
0643 
0644 void KoDialog::showButtonSeparator(bool state)
0645 {
0646     Q_D(KoDialog);
0647     if ((d->mActionSeparator != 0) == state) {
0648         return;
0649     }
0650     if (state) {
0651         if (d->mActionSeparator) {
0652             return;
0653         }
0654 
0655         d->mActionSeparator = new KSeparator(this);
0656         d->mActionSeparator->setOrientation(d->mButtonOrientation);
0657     } else {
0658         delete d->mActionSeparator;
0659         d->mActionSeparator = 0;
0660     }
0661 
0662     d->setupLayout();
0663 }
0664 
0665 void KoDialog::setInitialSize(const QSize &size)
0666 {
0667     d_func()->mMinSize = size;
0668     adjustSize();
0669 }
0670 
0671 void KoDialog::incrementInitialSize(const QSize &size)
0672 {
0673     d_func()->mIncSize = size;
0674     adjustSize();
0675 }
0676 
0677 QPushButton *KoDialog::button(ButtonCode id) const
0678 {
0679     Q_D(const KoDialog);
0680     return d->mButtonList.value(id, 0);
0681 }
0682 
0683 void KoDialog::enableButton(ButtonCode id, bool state)
0684 {
0685     QPushButton *button = this->button(id);
0686     if (button) {
0687         button->setEnabled(state);
0688     }
0689 }
0690 
0691 bool KoDialog::isButtonEnabled(ButtonCode id) const
0692 {
0693     QPushButton *button = this->button(id);
0694     if (button) {
0695         return button->isEnabled();
0696     }
0697 
0698     return false;
0699 }
0700 
0701 void KoDialog::enableButtonOk(bool state)
0702 {
0703     enableButton(Ok, state);
0704 }
0705 
0706 void KoDialog::enableButtonApply(bool state)
0707 {
0708     enableButton(Apply, state);
0709 }
0710 
0711 void KoDialog::enableButtonCancel(bool state)
0712 {
0713     enableButton(Cancel, state);
0714 }
0715 
0716 void KoDialog::showButton(ButtonCode id, bool state)
0717 {
0718     QPushButton *button = this->button(id);
0719     if (button) {
0720         state ? button->show() : button->hide();
0721     }
0722 }
0723 
0724 void KoDialog::setButtonGuiItem(ButtonCode id, const KGuiItem &item)
0725 {
0726     QPushButton *button = this->button(id);
0727     if (!button) {
0728         return;
0729     }
0730 
0731     KGuiItem::assign(button, item);
0732 }
0733 
0734 void KoDialog::setButtonText(ButtonCode id, const QString &text)
0735 {
0736     Q_D(KoDialog);
0737     if (!d->mSettingDetails && (id == Details)) {
0738         d->mDetailsButtonText = text;
0739         setDetailsWidgetVisible(d->mDetailsVisible);
0740         return;
0741     }
0742 
0743     QPushButton *button = this->button(id);
0744     if (button) {
0745         button->setText(text);
0746     }
0747 }
0748 
0749 QString KoDialog::buttonText(ButtonCode id) const
0750 {
0751     QPushButton *button = this->button(id);
0752     if (button) {
0753         return button->text();
0754     } else {
0755         return QString();
0756     }
0757 }
0758 
0759 void KoDialog::setButtonIcon(ButtonCode id, const QIcon &icon)
0760 {
0761     QPushButton *button = this->button(id);
0762     if (button) {
0763         button->setIcon(icon);
0764     }
0765 }
0766 
0767 QIcon KoDialog::buttonIcon(ButtonCode id) const
0768 {
0769     QPushButton *button = this->button(id);
0770     if (button) {
0771         return button->icon();
0772     } else {
0773         return QIcon();
0774     }
0775 }
0776 
0777 void KoDialog::setButtonToolTip(ButtonCode id, const QString &text)
0778 {
0779     QPushButton *button = this->button(id);
0780     if (button) {
0781         if (text.isEmpty()) {
0782             button->setToolTip(QString());
0783         } else {
0784             button->setToolTip(text);
0785         }
0786     }
0787 }
0788 
0789 QString KoDialog::buttonToolTip(ButtonCode id) const
0790 {
0791     QPushButton *button = this->button(id);
0792     if (button) {
0793         return button->toolTip();
0794     } else {
0795         return QString();
0796     }
0797 }
0798 
0799 void KoDialog::setButtonWhatsThis(ButtonCode id, const QString &text)
0800 {
0801     QPushButton *button = this->button(id);
0802     if (button) {
0803         if (text.isEmpty()) {
0804             button->setWhatsThis(QString());
0805         } else {
0806             button->setWhatsThis(text);
0807         }
0808     }
0809 }
0810 
0811 QString KoDialog::buttonWhatsThis(ButtonCode id) const
0812 {
0813     QPushButton *button = this->button(id);
0814     if (button) {
0815         return button->whatsThis();
0816     } else {
0817         return QString();
0818     }
0819 }
0820 
0821 void KoDialog::setButtonFocus(ButtonCode id)
0822 {
0823     QPushButton *button = this->button(id);
0824     if (button) {
0825         button->setFocus();
0826     }
0827 }
0828 
0829 void KoDialog::setDetailsWidget(QWidget *detailsWidget)
0830 {
0831     Q_D(KoDialog);
0832     if (d->mDetailsWidget == detailsWidget) {
0833         return;
0834     }
0835     delete d->mDetailsWidget;
0836     d->mDetailsWidget = detailsWidget;
0837 
0838     if (d->mDetailsWidget->parentWidget() != this) {
0839         d->mDetailsWidget->setParent(this);
0840     }
0841 
0842     d->mDetailsWidget->hide();
0843     d->setupLayout();
0844 
0845     if (!d->mSettingDetails) {
0846         setDetailsWidgetVisible(d->mDetailsVisible);
0847     }
0848 }
0849 
0850 bool KoDialog::isDetailsWidgetVisible() const
0851 {
0852     return d_func()->mDetailsVisible;
0853 }
0854 
0855 void KoDialog::setDetailsWidgetVisible(bool visible)
0856 {
0857     Q_D(KoDialog);
0858     if (d->mDetailsButtonText.isEmpty()) {
0859         d->mDetailsButtonText = i18n("&Details");
0860     }
0861 
0862     d->mSettingDetails = true;
0863     d->mDetailsVisible = visible;
0864     if (d->mDetailsVisible) {
0865         emit aboutToShowDetails();
0866         setButtonText(Details, d->mDetailsButtonText + " <<");
0867         if (d->mDetailsWidget) {
0868             if (layout()) {
0869                 layout()->setEnabled(false);
0870             }
0871 
0872             d->mDetailsWidget->show();
0873 
0874             adjustSize();
0875 
0876             if (layout()) {
0877                 layout()->activate();
0878                 layout()->setEnabled(true);
0879             }
0880         }
0881     } else {
0882         setButtonText(Details, d->mDetailsButtonText + " >>");
0883         if (d->mDetailsWidget) {
0884             d->mDetailsWidget->hide();
0885         }
0886 
0887         if (layout()) {
0888             layout()->activate();
0889             adjustSize();
0890         }
0891 
0892     }
0893 
0894     d->mSettingDetails = false;
0895 }
0896 
0897 void KoDialog::delayedDestruct()
0898 {
0899     if (isVisible()) {
0900         hide();
0901     }
0902 
0903     deleteLater();
0904 }
0905 
0906 void KoDialog::slotButtonClicked(int button)
0907 {
0908     Q_D(KoDialog);
0909     emit buttonClicked(static_cast<KoDialog::ButtonCode>(button));
0910 
0911     switch (button) {
0912     case Ok:
0913         emit okClicked();
0914         accept();
0915         break;
0916     case Apply:
0917         emit applyClicked();
0918         break;
0919     case Try:
0920         emit tryClicked();
0921         break;
0922     case User3:
0923         emit user3Clicked();
0924         break;
0925     case User2:
0926         emit user2Clicked();
0927         break;
0928     case User1:
0929         emit user1Clicked();
0930         break;
0931     case Yes:
0932         emit yesClicked();
0933         done(Yes);
0934         break;
0935     case No:
0936         emit noClicked();
0937         done(No);
0938         break;
0939     case Cancel:
0940         emit cancelClicked();
0941         reject();
0942         break;
0943     case Close:
0944         emit closeClicked();
0945         done(Close); // KDE5: call reject() instead; more QDialog-like.
0946         break;
0947     case Help:
0948         emit helpClicked();
0949         if (!d->mAnchor.isEmpty() || !d->mHelpApp.isEmpty()) {
0950             KHelpClient::invokeHelp(d->mAnchor, d->mHelpApp);
0951         }
0952         break;
0953     case Default:
0954         emit defaultClicked();
0955         break;
0956     case Reset:
0957         emit resetClicked();
0958         break;
0959     case Details:
0960         setDetailsWidgetVisible(!d->mDetailsVisible);
0961         break;
0962     }
0963 
0964     // If we're here from the closeEvent, and auto-delete is on, well, auto-delete now.
0965     if (d->mDeferredDelete) {
0966         d->mDeferredDelete = false;
0967         delayedDestruct();
0968     }
0969 }
0970 
0971 void KoDialog::enableLinkedHelp(bool state)
0972 {
0973     Q_D(KoDialog);
0974     if ((d->mUrlHelp != 0) == state) {
0975         return;
0976     }
0977     if (state) {
0978         if (d->mUrlHelp) {
0979             return;
0980         }
0981 
0982         d->mUrlHelp = new KUrlLabel(this);
0983         d->mUrlHelp->setText(helpLinkText());
0984         d->mUrlHelp->setFloatEnabled(true);
0985         d->mUrlHelp->setUnderline(true);
0986         d->mUrlHelp->setMinimumHeight(fontMetrics().height() + marginHint());
0987         connect(d->mUrlHelp, SIGNAL(leftClickedUrl()), SLOT(helpLinkClicked()));
0988 
0989         d->mUrlHelp->show();
0990     } else {
0991         delete d->mUrlHelp;
0992         d->mUrlHelp = 0;
0993     }
0994 
0995     d->setupLayout();
0996 }
0997 
0998 void KoDialog::setHelp(const QString &anchor, const QString &appname)
0999 {
1000     Q_D(KoDialog);
1001     d->mAnchor  = anchor;
1002     d->mHelpApp = appname;
1003 }
1004 
1005 void KoDialog::setHelpLinkText(const QString &text)
1006 {
1007     Q_D(KoDialog);
1008     d->mHelpLinkText = text;
1009     if (d->mUrlHelp) {
1010         d->mUrlHelp->setText(helpLinkText());
1011     }
1012 }
1013 
1014 QString KoDialog::helpLinkText() const
1015 {
1016     Q_D(const KoDialog);
1017     return (d->mHelpLinkText.isEmpty() ? i18n("Get help...") : d->mHelpLinkText);
1018 }
1019 
1020 void KoDialog::updateGeometry()
1021 {
1022 }
1023 
1024 void KoDialog::hideEvent(QHideEvent *event)
1025 {
1026     emit hidden();
1027 
1028     if (!event->spontaneous()) {
1029         emit finished();
1030     }
1031 }
1032 
1033 void KoDialog::closeEvent(QCloseEvent *event)
1034 {
1035     Q_D(KoDialog);
1036     QPushButton *button = this->button(d->mEscapeButton);
1037     if (button && !isHidden()) {
1038         button->animateClick();
1039 
1040         if (testAttribute(Qt::WA_DeleteOnClose)) {
1041             // Don't let QWidget::close do a deferred delete just yet, wait for the click first
1042             d->mDeferredDelete = true;
1043             setAttribute(Qt::WA_DeleteOnClose, false);
1044         }
1045     } else {
1046         QDialog::closeEvent(event);
1047     }
1048 }
1049 
1050 #include "moc_KoDialog.cpp"