File indexing completed on 2024-04-28 03:59:07

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 1999 Waldo Bastian <bastian@kde.org>
0004     SPDX-FileCopyrightText: 2012 David Faure <faure+bluesystems@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-only
0007 */
0008 
0009 #include "kmessagebox.h"
0010 #include "kmessagebox_p.h"
0011 
0012 #include <QCheckBox>
0013 #include <QDialog>
0014 #include <QLabel>
0015 #include <QLayout>
0016 #include <QListWidget>
0017 #include <QPointer>
0018 #include <QPushButton>
0019 #include <QScreen>
0020 #include <QScrollArea>
0021 #include <QScrollBar>
0022 #include <QTextBrowser>
0023 #include <QWindow>
0024 
0025 #include <qapplication.h>
0026 #if 0
0027 // NOTE waiting for the notification framework plan
0028 #include <knotification.h>
0029 #endif
0030 #include <ksqueezedtextlabel.h>
0031 
0032 #include <KCollapsibleGroupBox>
0033 
0034 namespace KMessageBox
0035 {
0036 /**
0037  * @private Prevent kapidox's doxygen config to pick up this namespace variable
0038  * this static is used by the createKMessageBox function to enqueue dialogs
0039  * FIXME what should we do about this static?
0040  */
0041 QDialogButtonBox::StandardButton KWIDGETSADDONS_EXPORT (*KMessageBox_exec_hook)(QDialog *) = nullptr;
0042 
0043 /// @private Prevent kapidox's doxygen config pick up this namespace method
0044 static void applyOptions(QDialog *dialog, KMessageBox::Options options)
0045 {
0046     if (options & KMessageBox::WindowModal) {
0047         dialog->setWindowModality(Qt::WindowModal);
0048     }
0049     dialog->setModal(true);
0050 }
0051 
0052 /// @private Prevent kapidox's doxygen config pick up this namespace method
0053 // This method has been copied from KWindowSystem to avoid depending on it
0054 static void setMainWindow(QWidget *subWidget, WId mainWindowId)
0055 {
0056 #ifdef Q_OS_OSX
0057     if (!QWidget::find(mainWindowId)) {
0058         return;
0059     }
0060 #endif
0061     // Set the WA_NativeWindow attribute to force the creation of the QWindow.
0062     // Without this QWidget::windowHandle() returns 0.
0063     subWidget->setAttribute(Qt::WA_NativeWindow, true);
0064     QWindow *subWindow = subWidget->windowHandle();
0065     Q_ASSERT(subWindow);
0066 
0067     QWindow *mainWindow = QWindow::fromWinId(mainWindowId);
0068     if (!mainWindow) {
0069         // foreign windows not supported on all platforms
0070         return;
0071     }
0072     // mainWindow is not the child of any object, so make sure it gets deleted at some point
0073     QObject::connect(subWidget, &QObject::destroyed, mainWindow, &QObject::deleteLater);
0074     subWindow->setTransientParent(mainWindow);
0075 }
0076 
0077 /**
0078  * @private Prevent kapidox's doxygen config pick up this namespace method
0079  * Create a QDialog whose parent is a foreign window
0080  */
0081 static QDialog *createWIdDialog(WId parent_id)
0082 {
0083     QWidget *parent = QWidget::find(parent_id);
0084     QDialog *dialog = new QDialog(parent, Qt::Dialog);
0085     if (!parent && parent_id) {
0086         setMainWindow(dialog, parent_id);
0087     }
0088     return dialog;
0089 }
0090 
0091 class DialogButtonsHelper : public QObject
0092 {
0093     Q_OBJECT
0094 public:
0095     DialogButtonsHelper(QDialog *dialog, QDialogButtonBox *buttons)
0096         : QObject(dialog)
0097         , m_dialog(dialog)
0098         , m_buttons(buttons)
0099         , m_details(nullptr)
0100     {
0101         connect(m_buttons, &QDialogButtonBox::clicked, this, &DialogButtonsHelper::onButtonClicked);
0102     }
0103 
0104     void setDetailsWidget(QWidget *widget)
0105     {
0106         m_details = widget;
0107     }
0108 
0109 public Q_SLOTS:
0110     void onButtonClicked(QAbstractButton *button)
0111     {
0112         QDialogButtonBox::StandardButton code = m_buttons->standardButton(button);
0113         if (code != QDialogButtonBox::NoButton) {
0114             m_dialog->done(code);
0115         }
0116     }
0117 
0118 private:
0119     QDialog *const m_dialog;
0120     QDialogButtonBox *const m_buttons;
0121     QWidget *m_details;
0122 };
0123 
0124 QDialogButtonBox::StandardButton createKMessageBox(QDialog *dialog,
0125                                                    QDialogButtonBox *buttons,
0126                                                    QMessageBox::Icon icon,
0127                                                    const QString &text,
0128                                                    const QStringList &strlist,
0129                                                    const QString &ask,
0130                                                    bool *checkboxReturn,
0131                                                    Options options,
0132                                                    const QString &details)
0133 {
0134     QIcon tmpIcon;
0135     QStyle *style = dialog ? dialog->style() : QApplication::style();
0136     switch (icon) {
0137     case QMessageBox::Information:
0138         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxInformation, nullptr, dialog);
0139         break;
0140     case QMessageBox::Warning:
0141         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, dialog);
0142         break;
0143     case QMessageBox::Critical:
0144         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxCritical, nullptr, dialog);
0145         break;
0146     case QMessageBox::Question:
0147         tmpIcon = style->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, dialog);
0148         break;
0149     default:
0150         break;
0151     }
0152 
0153     return createKMessageBox(dialog, buttons, tmpIcon, text, strlist, ask, checkboxReturn, options, details, icon);
0154 }
0155 
0156 QDialogButtonBox::StandardButton createKMessageBox(QDialog *dialog,
0157                                                    QDialogButtonBox *buttons,
0158                                                    const QIcon &icon,
0159                                                    const QString &text,
0160                                                    const QStringList &strlist,
0161                                                    const QString &ask,
0162                                                    bool *checkboxReturn,
0163                                                    Options options,
0164                                                    const QString &details,
0165                                                    QMessageBox::Icon notifyType)
0166 {
0167     if (!isNotifyInterfaceLoaded()) {
0168         // This is annoying. Loading the interface later (or at any point) will
0169         // install the qm translation of the knotifications library which will cause a LanguageChange event to be sent
0170         // Which will end up in QDialogButtonBoxPrivate::retranslateStrings and will overwrite the texts
0171         // we have just set. So here we save our texts, force load the interface and reset the texts
0172         // For people wondering if they can remove this bit of code later, this seems to only be an issue
0173         // in non Plasma desktops, emulate by running something like XDG_CURRENT_DESKTOP=X-Cinnamon okular
0174         // on plasma desktops the platform plugin already uses knotifications so it's qm has been loaded on startup
0175         QMap<QPointer<QAbstractButton>, QString> buttonTexts;
0176         for (QAbstractButton *b : buttons->buttons()) {
0177             buttonTexts[b] = b->text();
0178         }
0179         notifyInterface();
0180         QApplication::processEvents(); // We need to force the LanguageChange to be processed
0181         for (auto it = buttonTexts.constBegin(); it != buttonTexts.constEnd(); ++it) {
0182             if (it.key()) {
0183                 it.key()->setText(it.value());
0184             }
0185         }
0186     }
0187 
0188     DialogButtonsHelper *buttonsHelper = new DialogButtonsHelper(dialog, buttons);
0189 
0190     QWidget *mainWidget = new QWidget(dialog);
0191     QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget);
0192     const int verticalSpacing = mainWidget->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing);
0193     const int horizontalSpacing = mainWidget->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
0194     mainLayout->setSpacing(verticalSpacing * 2); // provide extra spacing
0195     mainLayout->setContentsMargins(0, 0, 0, 0);
0196     buttons->setParent(dialog);
0197 
0198     QHBoxLayout *hLayout = new QHBoxLayout();
0199     hLayout->setContentsMargins(0, 0, 0, 0);
0200     hLayout->setSpacing(-1); // use default spacing
0201     mainLayout->addLayout(hLayout, 5);
0202 
0203     QLabel *iconLabel = new QLabel(mainWidget);
0204 
0205     if (!icon.isNull()) {
0206         QStyleOption option;
0207         option.initFrom(mainWidget);
0208         iconLabel->setPixmap(icon.pixmap(mainWidget->style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, mainWidget)));
0209     }
0210 
0211     QVBoxLayout *iconLayout = new QVBoxLayout();
0212     iconLayout->addStretch(1);
0213     iconLayout->addWidget(iconLabel);
0214     iconLayout->addStretch(5);
0215 
0216     hLayout->addLayout(iconLayout, 0);
0217     hLayout->addSpacing(horizontalSpacing);
0218 
0219     QLabel *messageLabel = new QLabel(text, mainWidget);
0220     messageLabel->setOpenExternalLinks(options & KMessageBox::AllowLink);
0221     Qt::TextInteractionFlags flags = Qt::TextSelectableByMouse;
0222     if (options & KMessageBox::AllowLink) {
0223         flags |= Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard;
0224     }
0225     messageLabel->setTextInteractionFlags(flags);
0226 
0227     QRect desktop = dialog->screen()->geometry();
0228     bool usingSqueezedTextLabel = false;
0229     if (messageLabel->sizeHint().width() > desktop.width() * 0.5) {
0230         // enable automatic wrapping of messages which are longer than 50% of screen width
0231         messageLabel->setWordWrap(true);
0232         // use a squeezed label if text is still too wide
0233         usingSqueezedTextLabel = messageLabel->sizeHint().width() > desktop.width() * 0.85;
0234         if (usingSqueezedTextLabel) {
0235             delete messageLabel;
0236             messageLabel = new KSqueezedTextLabel(text, mainWidget);
0237             messageLabel->setOpenExternalLinks(options & KMessageBox::AllowLink);
0238             messageLabel->setTextInteractionFlags(flags);
0239         }
0240     }
0241 
0242     QPalette messagePal(messageLabel->palette());
0243     messagePal.setColor(QPalette::Window, Qt::transparent);
0244     messageLabel->setPalette(messagePal);
0245 
0246     bool usingScrollArea = desktop.height() / 3 < messageLabel->sizeHint().height();
0247     if (usingScrollArea) {
0248         QScrollArea *messageScrollArea = new QScrollArea(mainWidget);
0249         messageScrollArea->setWidget(messageLabel);
0250         messageScrollArea->setFrameShape(QFrame::NoFrame);
0251         messageScrollArea->setWidgetResizable(true);
0252         QPalette scrollPal(messageScrollArea->palette());
0253         scrollPal.setColor(QPalette::Window, Qt::transparent);
0254         messageScrollArea->viewport()->setPalette(scrollPal);
0255         hLayout->addWidget(messageScrollArea, 5);
0256     } else {
0257         hLayout->addWidget(messageLabel, 5);
0258     }
0259 
0260     const bool usingListWidget = !strlist.isEmpty();
0261     if (usingListWidget) {
0262         // enable automatic wrapping since the listwidget has already a good initial width
0263         messageLabel->setWordWrap(true);
0264         QListWidget *listWidget = new QListWidget(mainWidget);
0265         listWidget->addItems(strlist);
0266 
0267         QStyleOptionViewItem styleOption;
0268         styleOption.initFrom(listWidget);
0269         QFontMetrics fm(styleOption.font);
0270         int w = listWidget->width();
0271         for (const QString &str : strlist) {
0272             w = qMax(w, fm.boundingRect(str).width());
0273         }
0274         const int borderWidth = listWidget->width() - listWidget->viewport()->width() + listWidget->verticalScrollBar()->height();
0275         w += borderWidth;
0276         if (w > desktop.width() * 0.85) { // limit listWidget size to 85% of screen width
0277             w = qRound(desktop.width() * 0.85);
0278         }
0279         listWidget->setMinimumWidth(w);
0280 
0281         mainLayout->addWidget(listWidget, usingScrollArea ? 10 : 50);
0282         listWidget->setSelectionMode(QListWidget::NoSelection);
0283         messageLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
0284     } else if (!usingScrollArea) {
0285         mainLayout->addStretch(15);
0286     }
0287 
0288     QPointer<QCheckBox> checkbox = nullptr;
0289     if (!ask.isEmpty()) {
0290         checkbox = new QCheckBox(ask, mainWidget);
0291         mainLayout->addWidget(checkbox);
0292         if (checkboxReturn) {
0293             checkbox->setChecked(*checkboxReturn);
0294         }
0295     }
0296 
0297     QVBoxLayout *topLayout = new QVBoxLayout(dialog);
0298     topLayout->addWidget(mainWidget);
0299 
0300     if (!details.isEmpty()) {
0301         QHBoxLayout *detailsHLayout = new QHBoxLayout();
0302         detailsHLayout->addSpacing(2 * horizontalSpacing + iconLayout->sizeHint().width());
0303         KCollapsibleGroupBox *detailsGroup = new KCollapsibleGroupBox();
0304         detailsGroup->setTitle(QApplication::translate("KMessageBox", "Details"));
0305         QVBoxLayout *detailsLayout = new QVBoxLayout(detailsGroup);
0306         if (details.length() < 512) {
0307             QLabel *detailsLabel = new QLabel(details);
0308             detailsLabel->setOpenExternalLinks(options & KMessageBox::AllowLink);
0309             Qt::TextInteractionFlags flags = Qt::TextSelectableByMouse;
0310             if (options & KMessageBox::AllowLink) {
0311                 flags |= Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard;
0312             };
0313             detailsLabel->setTextInteractionFlags(flags);
0314             detailsLabel->setWordWrap(true);
0315             detailsLabel->setMinimumSize(detailsLabel->sizeHint());
0316             detailsLayout->addWidget(detailsLabel, 50);
0317         } else {
0318             QTextBrowser *detailTextEdit = new QTextBrowser();
0319             detailTextEdit->setText(details);
0320             detailTextEdit->setReadOnly(true);
0321             detailTextEdit->setMinimumHeight(detailTextEdit->fontMetrics().lineSpacing() * 11);
0322             detailsLayout->addWidget(detailTextEdit, 50);
0323         }
0324         if (!usingListWidget) {
0325             mainLayout->setStretchFactor(hLayout, 10);
0326         }
0327         detailsHLayout->addWidget(detailsGroup);
0328         topLayout->addLayout(detailsHLayout);
0329         buttonsHelper->setDetailsWidget(detailsGroup);
0330     }
0331 
0332     topLayout->addWidget(buttons);
0333     topLayout->setSizeConstraint(QLayout::SetFixedSize);
0334 
0335     if (!usingListWidget && !usingScrollArea && !usingSqueezedTextLabel && details.isEmpty()) {
0336         dialog->setFixedSize(dialog->sizeHint() + QSize(10, 10));
0337     }
0338 
0339     if ((options & KMessageBox::Dangerous)) {
0340         QPushButton *cancelButton = buttons->button(QDialogButtonBox::Cancel);
0341         QPushButton *noButton = buttons->button(QDialogButtonBox::No);
0342 
0343         if (cancelButton && cancelButton->isEnabled()) {
0344             cancelButton->setDefault(true);
0345             cancelButton->setFocus();
0346         } else if (noButton && noButton->isEnabled()) {
0347             noButton->setDefault(true);
0348             noButton->setFocus();
0349         }
0350     }
0351 
0352 #ifndef Q_OS_WIN // FIXME problems with KNotify on Windows
0353     if ((options & KMessageBox::Notify)) {
0354         QString message = text;
0355         if (!strlist.isEmpty()) {
0356             message += QLatin1Char('\n') + strlist.join(QLatin1Char('\n'));
0357         }
0358         notifyInterface()->sendNotification(notifyType, message, dialog->topLevelWidget());
0359     }
0360 #endif
0361 
0362     if (KMessageBox_exec_hook) {
0363         return KMessageBox_exec_hook(dialog);
0364     }
0365 
0366     if ((options & KMessageBox::NoExec)) {
0367         return QDialogButtonBox::NoButton; // We have to return something.
0368     }
0369 
0370     // We use a QPointer because the dialog may get deleted
0371     // during exec() if the parent of the dialog gets deleted.
0372     // In that case the QPointer will reset to 0.
0373     QPointer<QDialog> guardedDialog = dialog;
0374 
0375     const QDialogButtonBox::StandardButton result = QDialogButtonBox::StandardButton(guardedDialog->exec());
0376     if (checkbox && checkboxReturn) {
0377         *checkboxReturn = checkbox->isChecked();
0378     }
0379 
0380     delete guardedDialog;
0381     return result;
0382 }
0383 
0384 ButtonCode questionTwoActions(QWidget *parent,
0385                               const QString &text,
0386                               const QString &title,
0387                               const KGuiItem &primaryAction,
0388                               const KGuiItem &secondaryAction,
0389                               const QString &dontAskAgainName,
0390                               Options options)
0391 {
0392     return questionTwoActionsList(parent, text, QStringList(), title, primaryAction, secondaryAction, dontAskAgainName, options);
0393 }
0394 
0395 bool shouldBeShownTwoActions(const QString &dontShowAgainName, ButtonCode &result)
0396 {
0397     if (dontShowAgainName.isEmpty()) {
0398         return true;
0399     }
0400     return dontAskAgainInterface()->shouldBeShownTwoActions(dontShowAgainName, result);
0401 }
0402 
0403 bool shouldBeShownContinue(const QString &dontShowAgainName)
0404 {
0405     if (dontShowAgainName.isEmpty()) {
0406         return true;
0407     }
0408     return dontAskAgainInterface()->shouldBeShownContinue(dontShowAgainName);
0409 }
0410 
0411 void saveDontShowAgainTwoActions(const QString &dontShowAgainName, ButtonCode result)
0412 {
0413     if (dontShowAgainName.isEmpty()) {
0414         return;
0415     }
0416     dontAskAgainInterface()->saveDontShowAgainTwoActions(dontShowAgainName, result);
0417 }
0418 
0419 void saveDontShowAgainContinue(const QString &dontShowAgainName)
0420 {
0421     if (dontShowAgainName.isEmpty()) {
0422         return;
0423     }
0424     dontAskAgainInterface()->saveDontShowAgainContinue(dontShowAgainName);
0425 }
0426 
0427 void enableAllMessages()
0428 {
0429     dontAskAgainInterface()->enableAllMessages();
0430 }
0431 
0432 void enableMessage(const QString &dontShowAgainName)
0433 {
0434     dontAskAgainInterface()->enableMessage(dontShowAgainName);
0435 }
0436 
0437 void setDontShowAgainConfig(KConfig *cfg)
0438 {
0439     dontAskAgainInterface()->setConfig(cfg);
0440 }
0441 
0442 /// @private Prevent kapidox's doxygen config pick up this namespace method
0443 static ButtonCode questionTwoActionsListInternal(QDialog *dialog,
0444                                                  const QString &text,
0445                                                  const QStringList &strlist,
0446                                                  const QString &title,
0447                                                  const KGuiItem &primaryAction,
0448                                                  const KGuiItem &secondaryAction,
0449                                                  const QString &dontAskAgainName,
0450                                                  Options options)
0451 {
0452     ButtonCode res;
0453     if (!shouldBeShownTwoActions(dontAskAgainName, res)) {
0454         delete dialog;
0455         return res;
0456     }
0457 
0458     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Question") : title);
0459     dialog->setObjectName(QStringLiteral("questionTwoActions"));
0460 
0461     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0462     buttonBox->setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
0463     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), primaryAction);
0464     KGuiItem::assign(buttonBox->button(QDialogButtonBox::No), secondaryAction);
0465 
0466     applyOptions(dialog, options);
0467 
0468     bool checkboxResult = false;
0469     const int result = createKMessageBox(dialog,
0470                                          buttonBox,
0471                                          QMessageBox::Question,
0472                                          text,
0473                                          strlist,
0474                                          dontAskAgainName.isEmpty() ? QString() : QApplication::translate("KMessageBox", "Do not ask again"),
0475                                          &checkboxResult,
0476                                          options);
0477     res = (result == QDialogButtonBox::Yes ? PrimaryAction : SecondaryAction);
0478 
0479     if (checkboxResult) {
0480         saveDontShowAgainTwoActions(dontAskAgainName, res);
0481     }
0482     return res;
0483 }
0484 
0485 ButtonCode questionTwoActionsList(QWidget *parent,
0486                                   const QString &text,
0487                                   const QStringList &strlist,
0488                                   const QString &title,
0489                                   const KGuiItem &primaryAction,
0490                                   const KGuiItem &secondaryAction,
0491                                   const QString &dontAskAgainName,
0492                                   Options options)
0493 {
0494     return questionTwoActionsListInternal(new QDialog(parent), text, strlist, title, primaryAction, secondaryAction, dontAskAgainName, options);
0495 }
0496 
0497 /// @private Prevent kapidox's doxygen config pick up this namespace method
0498 static ButtonCode questionTwoActionsCancelInternal(QDialog *dialog,
0499                                                    const QString &text,
0500                                                    const QString &title,
0501                                                    const KGuiItem &primaryAction,
0502                                                    const KGuiItem &secondaryAction,
0503                                                    const KGuiItem &cancelAction,
0504                                                    const QString &dontAskAgainName,
0505                                                    Options options)
0506 {
0507     ButtonCode res;
0508     if (!shouldBeShownTwoActions(dontAskAgainName, res)) {
0509         delete dialog;
0510         return res;
0511     }
0512 
0513     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Question") : title);
0514     dialog->setObjectName(QStringLiteral("QuestionTwoActionsCancel"));
0515 
0516     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0517     buttonBox->setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel);
0518     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), primaryAction);
0519     KGuiItem::assign(buttonBox->button(QDialogButtonBox::No), secondaryAction);
0520     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), cancelAction);
0521 
0522     applyOptions(dialog, options);
0523 
0524     bool checkboxResult = false;
0525     const int result = createKMessageBox(dialog,
0526                                          buttonBox,
0527                                          QMessageBox::Question,
0528                                          text,
0529                                          QStringList(),
0530                                          dontAskAgainName.isEmpty() ? QString() : QApplication::translate("KMessageBox", "Do not ask again"),
0531                                          &checkboxResult,
0532                                          options);
0533 
0534     if (result == QDialogButtonBox::Yes) {
0535         res = PrimaryAction;
0536     } else if (result == QDialogButtonBox::No) {
0537         res = SecondaryAction;
0538     } else {
0539         return Cancel;
0540     }
0541 
0542     if (checkboxResult) {
0543         saveDontShowAgainTwoActions(dontAskAgainName, res);
0544     }
0545     return res;
0546 }
0547 
0548 ButtonCode questionTwoActionsCancel(QWidget *parent,
0549                                     const QString &text,
0550                                     const QString &title,
0551                                     const KGuiItem &primaryAction,
0552                                     const KGuiItem &secondaryAction,
0553                                     const KGuiItem &cancelAction,
0554                                     const QString &dontAskAgainName,
0555                                     Options options)
0556 {
0557     return questionTwoActionsCancelInternal(new QDialog(parent), text, title, primaryAction, secondaryAction, cancelAction, dontAskAgainName, options);
0558 }
0559 
0560 ButtonCode warningTwoActions(QWidget *parent,
0561                              const QString &text,
0562                              const QString &title,
0563                              const KGuiItem &primaryAction,
0564                              const KGuiItem &secondaryAction,
0565                              const QString &dontAskAgainName,
0566                              Options options)
0567 {
0568     return warningTwoActionsList(parent, text, QStringList(), title, primaryAction, secondaryAction, dontAskAgainName, options);
0569 }
0570 
0571 /// @private Prevent kapidox's doxygen config pick up this namespace method
0572 static ButtonCode warningTwoActionsListInternal(QDialog *dialog,
0573                                                 const QString &text,
0574                                                 const QStringList &strlist,
0575                                                 const QString &title,
0576                                                 const KGuiItem &primaryAction,
0577                                                 const KGuiItem &secondaryAction,
0578                                                 const QString &dontAskAgainName,
0579                                                 Options options)
0580 {
0581     ButtonCode res;
0582     if (!shouldBeShownTwoActions(dontAskAgainName, res)) {
0583         delete dialog;
0584         return res;
0585     }
0586 
0587     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Warning") : title);
0588     dialog->setObjectName(QStringLiteral("warningTwoActionsList"));
0589 
0590     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0591     buttonBox->setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
0592     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), primaryAction);
0593     KGuiItem::assign(buttonBox->button(QDialogButtonBox::No), secondaryAction);
0594 
0595     applyOptions(dialog, options);
0596 
0597     bool checkboxResult = false;
0598     const int result = createKMessageBox(dialog,
0599                                          buttonBox,
0600                                          QMessageBox::Warning,
0601                                          text,
0602                                          strlist,
0603                                          dontAskAgainName.isEmpty() ? QString() : QApplication::translate("KMessageBox", "Do not ask again"),
0604                                          &checkboxResult,
0605                                          options);
0606     res = (result == QDialogButtonBox::Yes ? PrimaryAction : SecondaryAction);
0607 
0608     if (checkboxResult) {
0609         saveDontShowAgainTwoActions(dontAskAgainName, res);
0610     }
0611     return res;
0612 }
0613 
0614 ButtonCode warningTwoActionsList(QWidget *parent,
0615                                  const QString &text,
0616                                  const QStringList &strlist,
0617                                  const QString &title,
0618                                  const KGuiItem &primaryAction,
0619                                  const KGuiItem &secondaryAction,
0620                                  const QString &dontAskAgainName,
0621                                  Options options)
0622 {
0623     return warningTwoActionsListInternal(new QDialog(parent), text, strlist, title, primaryAction, secondaryAction, dontAskAgainName, options);
0624 }
0625 
0626 ButtonCode warningContinueCancel(QWidget *parent,
0627                                  const QString &text,
0628                                  const QString &title,
0629                                  const KGuiItem &buttonContinue,
0630                                  const KGuiItem &buttonCancel,
0631                                  const QString &dontAskAgainName,
0632                                  Options options)
0633 {
0634     return warningContinueCancelList(parent, text, QStringList(), title, buttonContinue, buttonCancel, dontAskAgainName, options);
0635 }
0636 
0637 /// @private Prevent kapidox's doxygen config pick up this namespace method
0638 static ButtonCode warningContinueCancelListInternal(QDialog *dialog,
0639                                                     const QString &text,
0640                                                     const QStringList &strlist,
0641                                                     const QString &title,
0642                                                     const KGuiItem &buttonContinue,
0643                                                     const KGuiItem &buttonCancel,
0644                                                     const QString &dontAskAgainName,
0645                                                     Options options,
0646                                                     const QString &details)
0647 {
0648     if (!shouldBeShownContinue(dontAskAgainName)) {
0649         delete dialog;
0650         return Continue;
0651     }
0652 
0653     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Warning") : title);
0654     dialog->setObjectName(QStringLiteral("warningYesNo"));
0655 
0656     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0657     buttonBox->setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No);
0658     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), buttonContinue);
0659     KGuiItem::assign(buttonBox->button(QDialogButtonBox::No), buttonCancel);
0660 
0661     applyOptions(dialog, options);
0662 
0663     bool checkboxResult = false;
0664     const int result = createKMessageBox(dialog,
0665                                          buttonBox,
0666                                          QMessageBox::Warning,
0667                                          text,
0668                                          strlist,
0669                                          dontAskAgainName.isEmpty() ? QString() : QApplication::translate("KMessageBox", "Do not ask again"),
0670                                          &checkboxResult,
0671                                          options,
0672                                          details);
0673 
0674     if (result != QDialogButtonBox::Yes) {
0675         return Cancel;
0676     }
0677     if (checkboxResult) {
0678         saveDontShowAgainContinue(dontAskAgainName);
0679     }
0680     return Continue;
0681 }
0682 
0683 ButtonCode warningContinueCancelList(QWidget *parent,
0684                                      const QString &text,
0685                                      const QStringList &strlist,
0686                                      const QString &title,
0687                                      const KGuiItem &buttonContinue,
0688                                      const KGuiItem &buttonCancel,
0689                                      const QString &dontAskAgainName,
0690                                      Options options)
0691 {
0692     return warningContinueCancelListInternal(new QDialog(parent), text, strlist, title, buttonContinue, buttonCancel, dontAskAgainName, options, QString());
0693 }
0694 
0695 ButtonCode warningContinueCancelDetailed(QWidget *parent,
0696                                          const QString &text,
0697                                          const QString &title,
0698                                          const KGuiItem &buttonContinue,
0699                                          const KGuiItem &buttonCancel,
0700                                          const QString &dontAskAgainName,
0701                                          Options options,
0702                                          const QString &details)
0703 {
0704     return warningContinueCancelListInternal(new QDialog(parent), text, QStringList(), title, buttonContinue, buttonCancel, dontAskAgainName, options, details);
0705 }
0706 
0707 ButtonCode warningTwoActionsCancel(QWidget *parent,
0708                                    const QString &text,
0709                                    const QString &title,
0710                                    const KGuiItem &primaryAction,
0711                                    const KGuiItem &secondaryAction,
0712                                    const KGuiItem &cancelAction,
0713                                    const QString &dontAskAgainName,
0714                                    Options options)
0715 {
0716     return warningTwoActionsCancelList(parent, text, QStringList(), title, primaryAction, secondaryAction, cancelAction, dontAskAgainName, options);
0717 }
0718 
0719 /// @private Prevent kapidox's doxygen config pick up this namespace method
0720 static ButtonCode warningTwoActionsCancelListInternal(QDialog *dialog,
0721                                                       const QString &text,
0722                                                       const QStringList &strlist,
0723                                                       const QString &title,
0724                                                       const KGuiItem &primaryAction,
0725                                                       const KGuiItem &secondaryAction,
0726                                                       const KGuiItem &cancelAction,
0727                                                       const QString &dontAskAgainName,
0728                                                       Options options)
0729 {
0730     ButtonCode res;
0731     if (!shouldBeShownTwoActions(dontAskAgainName, res)) {
0732         delete dialog;
0733         return res;
0734     }
0735 
0736     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Warning") : title);
0737     dialog->setObjectName(QStringLiteral("warningTwoActionsCancel"));
0738 
0739     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0740     buttonBox->setStandardButtons(QDialogButtonBox::Yes | QDialogButtonBox::No | QDialogButtonBox::Cancel);
0741     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Yes), primaryAction);
0742     KGuiItem::assign(buttonBox->button(QDialogButtonBox::No), secondaryAction);
0743     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), cancelAction);
0744 
0745     applyOptions(dialog, options);
0746 
0747     bool checkboxResult = false;
0748     const int result = createKMessageBox(dialog,
0749                                          buttonBox,
0750                                          QMessageBox::Warning,
0751                                          text,
0752                                          strlist,
0753                                          dontAskAgainName.isEmpty() ? QString() : QApplication::translate("KMessageBox", "Do not ask again"),
0754                                          &checkboxResult,
0755                                          options);
0756 
0757     if (result == QDialogButtonBox::Yes) {
0758         res = PrimaryAction;
0759     } else if (result == QDialogButtonBox::No) {
0760         res = SecondaryAction;
0761     } else {
0762         return Cancel;
0763     }
0764 
0765     if (checkboxResult) {
0766         saveDontShowAgainTwoActions(dontAskAgainName, res);
0767     }
0768     return res;
0769 }
0770 
0771 ButtonCode warningTwoActionsCancelList(QWidget *parent,
0772                                        const QString &text,
0773                                        const QStringList &strlist,
0774                                        const QString &title,
0775                                        const KGuiItem &primaryAction,
0776                                        const KGuiItem &secondaryAction,
0777                                        const KGuiItem &cancelAction,
0778                                        const QString &dontAskAgainName,
0779                                        Options options)
0780 {
0781     return warningTwoActionsCancelListInternal(new QDialog(parent),
0782                                                text,
0783                                                strlist,
0784                                                title,
0785                                                primaryAction,
0786                                                secondaryAction,
0787                                                cancelAction,
0788                                                dontAskAgainName,
0789                                                options);
0790 }
0791 
0792 /// @private Prevent kapidox's doxygen config pick up this namespace method
0793 static void errorInternal(QDialog *dialog, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options)
0794 {
0795     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Error") : title);
0796     dialog->setObjectName(QStringLiteral("error"));
0797 
0798     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0799     buttonBox->setStandardButtons(QDialogButtonBox::Ok);
0800     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), buttonOk);
0801 
0802     applyOptions(dialog, options);
0803 
0804     createKMessageBox(dialog, buttonBox, QMessageBox::Critical, text, QStringList(), QString(), nullptr, options);
0805 }
0806 
0807 void error(QWidget *parent, const QString &text, const QString &title, Options options)
0808 {
0809     errorInternal(new QDialog(parent), text, title, KStandardGuiItem::ok(), options);
0810 }
0811 
0812 void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options)
0813 {
0814     errorInternal(new QDialog(parent), text, title, buttonOk, options);
0815 }
0816 
0817 /// @private Prevent kapidox's doxygen config pick up this namespace method
0818 static void errorListInternal(QDialog *dialog, const QString &text, const QStringList &strlist, const QString &title, Options options)
0819 {
0820     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Error") : title);
0821     dialog->setObjectName(QStringLiteral("error"));
0822 
0823     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0824     buttonBox->setStandardButtons(QDialogButtonBox::Ok);
0825 
0826     applyOptions(dialog, options);
0827 
0828     createKMessageBox(dialog, buttonBox, QMessageBox::Critical, text, strlist, QString(), nullptr, options);
0829 }
0830 
0831 void errorList(QWidget *parent, const QString &text, const QStringList &strlist, const QString &title, Options options)
0832 {
0833     errorListInternal(new QDialog(parent), text, strlist, title, options);
0834 }
0835 
0836 /// @private Prevent kapidox's doxygen config pick up this namespace method
0837 static void detailedErrorInternal(QDialog *dialog, const QString &text, const QString &details, const QString &title, const KGuiItem &buttonOk, Options options)
0838 {
0839     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Error") : title);
0840     dialog->setObjectName(QStringLiteral("error"));
0841 
0842     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0843     buttonBox->addButton(QDialogButtonBox::Ok);
0844     KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), buttonOk);
0845     buttonBox->button(QDialogButtonBox::Ok)->setFocus();
0846 
0847     applyOptions(dialog, options);
0848 
0849     createKMessageBox(dialog, buttonBox, QMessageBox::Critical, text, QStringList(), QString(), nullptr, options, details);
0850 }
0851 
0852 void detailedError(QWidget *parent, const QString &text, const QString &details, const QString &title, Options options)
0853 {
0854     detailedErrorInternal(new QDialog(parent), text, details, title, KStandardGuiItem::ok(), options);
0855 }
0856 
0857 void detailedError(QWidget *parent, const QString &text, const QString &details, const QString &title, const KGuiItem &buttonOk, Options options)
0858 {
0859     detailedErrorInternal(new QDialog(parent), text, details, title, buttonOk, options);
0860 }
0861 
0862 void information(QWidget *parent, const QString &text, const QString &title, const QString &dontShowAgainName, Options options)
0863 {
0864     informationList(parent, text, QStringList(), title, dontShowAgainName, options);
0865 }
0866 
0867 /// @private Prevent kapidox's doxygen config pick up this namespace method
0868 static void informationListInternal(QDialog *dialog,
0869                                     const QString &text,
0870                                     const QStringList &strlist,
0871                                     const QString &title,
0872                                     const QString &dontShowAgainName,
0873                                     Options options)
0874 {
0875     if (!shouldBeShownContinue(dontShowAgainName)) {
0876         delete dialog;
0877         return;
0878     }
0879 
0880     dialog->setWindowTitle(title.isEmpty() ? QApplication::translate("KMessageBox", "Information") : title);
0881     dialog->setObjectName(QStringLiteral("information"));
0882 
0883     QDialogButtonBox *buttonBox = new QDialogButtonBox(dialog);
0884     buttonBox->setStandardButtons(QDialogButtonBox::Ok);
0885 
0886     applyOptions(dialog, options);
0887 
0888     bool checkboxResult = false;
0889 
0890     createKMessageBox(dialog,
0891                       buttonBox,
0892                       QMessageBox::Information,
0893                       text,
0894                       strlist,
0895                       dontShowAgainName.isEmpty() ? QString() : QApplication::translate("KMessageBox", "Do not show this message again"),
0896                       &checkboxResult,
0897                       options);
0898 
0899     if (checkboxResult) {
0900         saveDontShowAgainContinue(dontShowAgainName);
0901     }
0902 }
0903 
0904 void informationList(QWidget *parent, const QString &text, const QStringList &strlist, const QString &title, const QString &dontShowAgainName, Options options)
0905 {
0906     informationListInternal(new QDialog(parent), text, strlist, title, dontShowAgainName, options);
0907 }
0908 
0909 /// @private Prevent kapidox's doxygen config pick up this namespace method
0910 static ButtonCode messageBoxInternal(QDialog *dialog,
0911                                      DialogType type,
0912                                      const QString &text,
0913                                      const QString &title,
0914                                      const KGuiItem &primaryAction,
0915                                      const KGuiItem &secondaryAction,
0916                                      const KGuiItem &cancelAction,
0917                                      const QString &dontShow,
0918                                      Options options)
0919 {
0920     switch (type) {
0921     case QuestionTwoActions:
0922         return questionTwoActionsListInternal(dialog, text, QStringList(), title, primaryAction, secondaryAction, dontShow, options);
0923     case QuestionTwoActionsCancel:
0924         return questionTwoActionsCancelInternal(dialog, text, title, primaryAction, secondaryAction, cancelAction, dontShow, options);
0925     case WarningTwoActions:
0926         return warningTwoActionsListInternal(dialog, text, QStringList(), title, primaryAction, secondaryAction, dontShow, options);
0927     case WarningContinueCancel:
0928         return warningContinueCancelListInternal(dialog,
0929                                                  text,
0930                                                  QStringList(),
0931                                                  title,
0932                                                  KGuiItem(primaryAction.text()),
0933                                                  cancelAction,
0934                                                  dontShow,
0935                                                  options,
0936                                                  QString());
0937     case WarningTwoActionsCancel:
0938         return warningTwoActionsCancelListInternal(dialog, text, QStringList(), title, primaryAction, secondaryAction, cancelAction, dontShow, options);
0939     case Information:
0940         informationListInternal(dialog, text, QStringList(), title, dontShow, options);
0941         return KMessageBox::Ok;
0942 
0943     case Error:
0944         errorListInternal(dialog, text, QStringList(), title, options);
0945         return KMessageBox::Ok;
0946     }
0947     return KMessageBox::Cancel;
0948 }
0949 
0950 ButtonCode messageBox(QWidget *parent,
0951                       DialogType type,
0952                       const QString &text,
0953                       const QString &title,
0954                       const KGuiItem &primaryAction,
0955                       const KGuiItem &secondaryAction,
0956                       const KGuiItem &buttonCancel,
0957                       const QString &dontShow,
0958                       Options options)
0959 {
0960     return messageBoxInternal(new QDialog(parent), type, text, title, primaryAction, secondaryAction, buttonCancel, dontShow, options);
0961 }
0962 
0963 ButtonCode questionTwoActionsWId(WId parent_id,
0964                                  const QString &text,
0965                                  const QString &title,
0966                                  const KGuiItem &primaryAction,
0967                                  const KGuiItem &secondaryAction,
0968                                  const QString &dontAskAgainName,
0969                                  Options options)
0970 {
0971     return questionTwoActionsListWId(parent_id, text, QStringList(), title, primaryAction, secondaryAction, dontAskAgainName, options);
0972 }
0973 
0974 ButtonCode questionTwoActionsListWId(WId parent_id,
0975                                      const QString &text,
0976                                      const QStringList &strlist,
0977                                      const QString &title,
0978                                      const KGuiItem &primaryAction,
0979                                      const KGuiItem &secondaryAction,
0980                                      const QString &dontAskAgainName,
0981                                      Options options)
0982 {
0983     return questionTwoActionsListInternal(createWIdDialog(parent_id), text, strlist, title, primaryAction, secondaryAction, dontAskAgainName, options);
0984 }
0985 
0986 ButtonCode questionTwoActionsCancelWId(WId parent_id,
0987                                        const QString &text,
0988                                        const QString &title,
0989                                        const KGuiItem &primaryAction,
0990                                        const KGuiItem &secondaryAction,
0991                                        const KGuiItem &cancelAction,
0992                                        const QString &dontAskAgainName,
0993                                        Options options)
0994 {
0995     return questionTwoActionsCancelInternal(createWIdDialog(parent_id), text, title, primaryAction, secondaryAction, cancelAction, dontAskAgainName, options);
0996 }
0997 
0998 ButtonCode warningTwoActionsWId(WId parent_id,
0999                                 const QString &text,
1000                                 const QString &title,
1001                                 const KGuiItem &primaryAction,
1002                                 const KGuiItem &secondaryAction,
1003                                 const QString &dontAskAgainName,
1004                                 Options options)
1005 {
1006     return warningTwoActionsListWId(parent_id, text, QStringList(), title, primaryAction, secondaryAction, dontAskAgainName, options);
1007 }
1008 
1009 ButtonCode warningTwoActionsListWId(WId parent_id,
1010                                     const QString &text,
1011                                     const QStringList &strlist,
1012                                     const QString &title,
1013                                     const KGuiItem &primaryAction,
1014                                     const KGuiItem &secondaryAction,
1015                                     const QString &dontAskAgainName,
1016                                     Options options)
1017 {
1018     return warningTwoActionsListInternal(createWIdDialog(parent_id), text, strlist, title, primaryAction, secondaryAction, dontAskAgainName, options);
1019 }
1020 
1021 ButtonCode warningContinueCancelWId(WId parent_id,
1022                                     const QString &text,
1023                                     const QString &title,
1024                                     const KGuiItem &buttonContinue,
1025                                     const KGuiItem &buttonCancel,
1026                                     const QString &dontAskAgainName,
1027                                     Options options)
1028 {
1029     return warningContinueCancelListWId(parent_id, text, QStringList(), title, buttonContinue, buttonCancel, dontAskAgainName, options);
1030 }
1031 
1032 ButtonCode warningContinueCancelListWId(WId parent_id,
1033                                         const QString &text,
1034                                         const QStringList &strlist,
1035                                         const QString &title,
1036                                         const KGuiItem &buttonContinue,
1037                                         const KGuiItem &buttonCancel,
1038                                         const QString &dontAskAgainName,
1039                                         Options options)
1040 {
1041     return warningContinueCancelListInternal(createWIdDialog(parent_id),
1042                                              text,
1043                                              strlist,
1044                                              title,
1045                                              buttonContinue,
1046                                              buttonCancel,
1047                                              dontAskAgainName,
1048                                              options,
1049                                              QString());
1050 }
1051 
1052 ButtonCode warningTwoActionsCancelWId(WId parent_id,
1053                                       const QString &text,
1054                                       const QString &title,
1055                                       const KGuiItem &primaryAction,
1056                                       const KGuiItem &secondaryAction,
1057                                       const KGuiItem &buttonCancel,
1058                                       const QString &dontAskAgainName,
1059                                       Options options)
1060 {
1061     return warningTwoActionsCancelListWId(parent_id, text, QStringList(), title, primaryAction, secondaryAction, buttonCancel, dontAskAgainName, options);
1062 }
1063 
1064 ButtonCode warningTwoActionsCancelListWId(WId parent_id,
1065                                           const QString &text,
1066                                           const QStringList &strlist,
1067                                           const QString &title,
1068                                           const KGuiItem &primaryAction,
1069                                           const KGuiItem &secondaryAction,
1070                                           const KGuiItem &buttonCancel,
1071                                           const QString &dontAskAgainName,
1072                                           Options options)
1073 {
1074     return warningTwoActionsCancelList(createWIdDialog(parent_id),
1075                                        text,
1076                                        strlist,
1077                                        title,
1078                                        primaryAction,
1079                                        secondaryAction,
1080                                        buttonCancel,
1081                                        dontAskAgainName,
1082                                        options);
1083 }
1084 
1085 void errorWId(WId parent_id, const QString &text, const QString &title, Options options)
1086 {
1087     errorListWId(parent_id, text, QStringList(), title, options);
1088 }
1089 
1090 void errorListWId(WId parent_id, const QString &text, const QStringList &strlist, const QString &title, Options options)
1091 {
1092     errorListInternal(createWIdDialog(parent_id), text, strlist, title, options);
1093 }
1094 
1095 void detailedErrorWId(WId parent_id, const QString &text, const QString &details, const QString &title, Options options)
1096 {
1097     detailedErrorInternal(createWIdDialog(parent_id), text, details, title, KStandardGuiItem::ok(), options);
1098 }
1099 
1100 void detailedErrorWId(WId parent_id, const QString &text, const QString &details, const QString &title, const KGuiItem &buttonOk, Options options)
1101 {
1102     detailedErrorInternal(createWIdDialog(parent_id), text, details, title, buttonOk, options);
1103 }
1104 
1105 void informationWId(WId parent_id, const QString &text, const QString &title, const QString &dontShowAgainName, Options options)
1106 {
1107     informationListWId(parent_id, text, QStringList(), title, dontShowAgainName, options);
1108 }
1109 
1110 void informationListWId(WId parent_id, const QString &text, const QStringList &strlist, const QString &title, const QString &dontShowAgainName, Options options)
1111 {
1112     informationListInternal(createWIdDialog(parent_id), text, strlist, title, dontShowAgainName, options);
1113 }
1114 
1115 ButtonCode messageBoxWId(WId parent_id,
1116                          DialogType type,
1117                          const QString &text,
1118                          const QString &title,
1119                          const KGuiItem &primaryAction,
1120                          const KGuiItem &secondaryAction,
1121                          const KGuiItem &cancelAction,
1122                          const QString &dontShow,
1123                          Options options)
1124 {
1125     return messageBoxInternal(createWIdDialog(parent_id), type, text, title, primaryAction, secondaryAction, cancelAction, dontShow, options);
1126 }
1127 
1128 } // namespace
1129 
1130 #include "kmessagebox.moc"