1 /* 2 This file is part of the KDE libraries 3 SPDX-FileCopyrightText: 2020 Ahmad Samir <a.samirh78@gmail.com> 4 5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 6 */ 7 8 #ifndef KMESSAGEDIALOG_H 9 #define KMESSAGEDIALOG_H 10 11 #include <kwidgetsaddons_export.h> 12 13 #include <KStandardGuiItem> 14 15 #include <QDialog> 16 #include <QMessageBox> 17 18 #include <memory> 19 20 class QDialogButtonBox; 21 22 class KMessageDialogPrivate; 23 class KGuiItem; 24 25 /** 26 * @class KMessageDialog kmessagedialog.h <KMessageDialog> 27 * 28 * 29 * @brief KMessageDialog creates a message box similar to the ones you get from KMessageBox, 30 * but that can be used asynchronously, i.e. you can show the dialog by using @c show() 31 * or @c open(). 32 * 33 * This class contructs a dialog similar to the dialogs the KMessageBox convenience functions 34 * create. The main difference is that the KMessageBox methods typically use @c exec() to show 35 * the dialogs; one of the main disadvantages of using @c exec(), is that it starts a nested 36 * eventloop, which could lead to nasty crashes. 37 * 38 * Another difference is that the API is supposed to be slightly easier to use as it has 39 * various methods to set up the dialog, e.g. @ref setCaption(), @ref setDetails() ...etc. 40 * 41 * By default, appropriate buttons based on the dialog type are added (since 5.85) (e.g. an 42 * "OK" button is added to an Information dialog), you can set custom buttons by using the 43 * @ref setButtons() method. 44 * 45 * The @ref QDialog::done() slot is called to set the result of the dialog, which will emit the 46 * @ref QDialog::finished() signal with that result. The result is one of the 47 * QDialogButtonBox::StandardButton enum. This is useful as you can tell exactly which button 48 * was clicked by the user. E.g.: 49 * - the "No" button having been clicked, in which case you may still want to save the status 50 * of the "Do not ask again" CheckBox 51 * - the "Cancel" button having been clicked, in which case you ideally will ignore the status 52 * of the "Do not ask again" CheckBox 53 * 54 * For "warning" dialogs, i.e. dialogs with a potentially destructive action, the default 55 * button is set to a button with the QDialogButtonBox::RejectRole, typically either button 56 * "No" or "Cancel" depending on which one is shown in the dialog. If both of them are shown 57 * (as is the case with KMessageDialog::WarningYesNoCancel dialog Type) then the "Cancel" 58 * button will be set as the default one. 59 * 60 * This class intends to be very flexible with the buttons that can be used, since you can 61 * call the @ref setButtons() method with a KGuiItem that has custom text/icon. 62 * 63 * Example: 64 * @code 65 * auto *dlg = new KMessageDialog(KMessageDialog::QuestionYesNoCancel, 66 * QStringLiteral("Do you agree?"), 67 * nullptr); 68 * 69 * dlg->setCaption(QStringLiteral("Window Title")); 70 * dlg->setButtons(KStandardGuiItem::yes(), KStandardGuiItem::no(), KStandardGuiItem::cancel()); 71 * dlg->setListWidgetItems(QStringList{QStringLiteral("file1"), QStringLiteral("file2")}); 72 * dlg->setDetails(QStringLiteral("Some more details.")); 73 * dlg->setDontAskAgainText(QStringLiteral("Do not ask again")); 74 * dlg->setDontAskAgainChecked(false); 75 * 76 * // Delete the dialog when it's closed 77 * dlg->setAttribute(Qt::WA_DeleteOnClose); 78 * // Make the dialog window modal 79 * dlg->setWindowModality(Qt::WindowModal); 80 * 81 * QObject::connect(dlg, &QDialog::finished, &app, [dlg](int result) { 82 * auto button = static_cast<QDialogButtonBox::StandardButton>(result); 83 * switch(button) { 84 * case QDialogButtonBox::Ok: 85 * case QDialogButtonBox::Yes: 86 * // The user clicked OK, handle the result... 87 * // save the "do not ask again" box status... 88 * break; 89 * case QDialogButtonBox::No: 90 * // The user clicked no, reject the changes... 91 * // save the "do not ask again" box status... 92 * break; 93 * case QDialogButtonBox::Cancel: 94 * // The user clicked cancel, reject the changes... 95 * break; 96 * default: 97 * break; 98 * } 99 * }); 100 * 101 * dlg->show(); 102 * @endcode 103 * 104 * @since 5.77 105 */ 106 107 class KWIDGETSADDONS_EXPORT KMessageDialog : public QDialog 108 { 109 Q_OBJECT 110 111 public: 112 enum Type { 113 QuestionYesNo = 1, 114 QuestionYesNoCancel, 115 WarningYesNo, 116 WarningYesNoCancel, 117 WarningContinueCancel, 118 Information, 119 Sorry, 120 Error, 121 }; 122 123 /** 124 * Constructs a KMessageDialog. 125 * 126 * @param type the dialog Type, one of KMessageDialog::Type enum 127 * @param text the text message that is going to be displayed in the dialog 128 * @param parent a QWidget* that will be set as the dialog parent 129 */ 130 explicit KMessageDialog(KMessageDialog::Type type, const QString &text, QWidget *parent = nullptr); 131 132 /** 133 * This constructor takes the window Id of the parent window, instead of a QWidget*. 134 * 135 * @param type the dialog Type, one of KMessageDialog::Type enum 136 * @param text the text message that is going to be displayed in the dialog 137 * @param parent_id the native parent's window system identifier 138 */ 139 explicit KMessageDialog(KMessageDialog::Type type, const QString &text, WId parent_id); 140 /** 141 * Destructor 142 */ 143 ~KMessageDialog() override; 144 145 /** 146 * This can be used to set the title of the dialog window. If you pass an 147 * empty QString(), a generic title will be used depending on the dialog 148 * Type. E.g. for KMessageDialog::WarningYesNo, "Warning" will be used. 149 */ 150 void setCaption(const QString &caption); 151 152 /** 153 * This can be used to set an icon that will be shown next to the main 154 * text message. If you pass a null QIcon() a generic icon based on the dialog 155 * Type will be used. E.g. for KMessageDialog::QuestionYesNo, QMessageBox::Question 156 * will be used. 157 */ 158 void setIcon(const QIcon &icon); 159 160 /** 161 * This will add a QListWidget to the dialog and populate it with @p strlist. 162 * If @p strlist is empty, the list widget will not be shown. 163 */ 164 void setListWidgetItems(const QStringList &strlist); 165 166 /** 167 * This will add a KCollapsibleGroupBox with a title "Details", as the class name 168 * implies it is collapsible (and collapsed by default); you can use it to add a 169 * more detailed explanation of what the dialog is trying to tell the user. 170 * 171 * If @p details is empty, the details widget will not be shown. 172 */ 173 void setDetails(const QString &details); 174 175 /** 176 * This will add a "Do not ask again" checkbox to the dialog with the text 177 * from @p dontAskAgainText. You can set the initial status of the checkbox 178 * by using setDontAskAgainChecked(). 179 * 180 * If @p dontAskAgainText is empty, no checkbox will be shown. 181 * 182 * Typical usage of this checkbox is for recurring questions, e.g. showing 183 * a dialog to confirm moving files/directories to trash, the user can then 184 * set the checkbox so as not to be asked about that again. 185 * 186 * You can get the state of the checkbox by using isDontAskAgainChecked(). 187 */ 188 void setDontAskAgainText(const QString &dontAskAgainText); 189 190 /** 191 * This can be used to set the initial status of the "Do not ask again" checkbox, 192 * checked or unchecked, by setting @p isChecked to @c true or @c false 193 * respectively. 194 * 195 * You need to call setDontAskAgainText() first to actually show a checkbox in 196 * the dialog, otherwise calling this function will have no effect. 197 */ 198 void setDontAskAgainChecked(bool isChecked); 199 200 /** 201 * This can be used to query the status of the "Do not ask again" checkbox; 202 * returns @c true if the box is checked and @c false otherwise. 203 * 204 * @note This method will return @c false if a checkbox widget isn't shown in 205 * the dialog. The dialog will not show a checkbox if setDontAskAgainText() was 206 * not used previously to add a checkbox to begin with. 207 */ 208 bool isDontAskAgainChecked() const; 209 210 /** 211 * Sets the text labels in the dialog to either allow opening external links or not. 212 */ 213 void setOpenExternalLinks(bool isAllowed); 214 215 /** 216 * Since 5.85 buttons based on the dialog type are added by default, e.g. an OK 217 * button to Information and Sorry dialogs; (before 5.85, if you didn't call this 218 * method no buttons were added to the dialog). 219 * 220 * This will add a QDialogButtonBox populated with @p buttonAccept and @p buttonNo, 221 * by default KStandardGuiItem::yes() and KStandardGuiItem::no() respectively. For 222 * dialog Types that have a Cancel button, @p buttonCancel will be used. 223 * 224 * Using this method, you can customize the behavior based on your use-case, by 225 * using a KGuiItem to get a button with custom text and icon. 226 * 227 * @note 228 * - For WarningContinueCancel dialog Type, if buttonAccept has the same text as 229 * KStandardGuiItem::yes(), KStandardGuiItem::cont() will be used instead 230 * - For dialog Types: Information, Sorry, and Error only one button 231 * (KStandardGuiItem::ok()) is added to the dialog. 232 */ 233 void setButtons(const KGuiItem &buttonAccept = KStandardGuiItem::yes(), 234 const KGuiItem &buttonNo = KStandardGuiItem::no(), 235 const KGuiItem &buttonCancel = KStandardGuiItem::cancel()); 236 237 private: 238 std::unique_ptr<KMessageDialogPrivate> const d; 239 }; 240 241 #endif // KMESSAGEDIALOG_H 242