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"