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 KMessageDialogPrivate; |
21 | class KGuiItem; |
22 | class QWidget; |
23 | |
24 | /** |
25 | * @class KMessageDialog kmessagedialog.h <KMessageDialog> |
26 | * |
27 | * |
28 | * @brief KMessageDialog creates a message box similar to the ones you get from KMessageBox, |
29 | * but that can be used asynchronously, i.e. you can show the dialog by using @c show() |
30 | * or @c open(). |
31 | * |
32 | * This class contructs a dialog similar to the dialogs the KMessageBox convenience functions |
33 | * create. The main difference is that the KMessageBox methods typically use @c exec() to show |
34 | * the dialogs; one of the main disadvantages of using @c exec(), is that it starts a nested |
35 | * eventloop, which could lead to nasty crashes. |
36 | * |
37 | * Another difference is that the API is supposed to be slightly easier to use as it has |
38 | * various methods to set up the dialog, e.g. @ref setCaption(), @ref setDetails() ...etc. |
39 | * |
40 | * By default, appropriate buttons based on the dialog type are added (since 5.85) (e.g. an |
41 | * "OK" button is added to an Information dialog), you can set custom buttons by using the |
42 | * @ref setButtons() method. |
43 | * |
44 | * The @ref QDialog::done() slot is called to set the result of the dialog, which will emit the |
45 | * @ref QDialog::finished() signal with that result. The result is one of the |
46 | * KMessageDialog::ButtonType enum. This is useful as you can tell exactly which button |
47 | * was clicked by the user. E.g.: |
48 | * - the secondary action button having been clicked, in which case you may still want to save the status |
49 | * of the "Do not ask again" CheckBox |
50 | * - the "Cancel" button having been clicked, in which case you ideally will ignore the status |
51 | * of the "Do not ask again" CheckBox |
52 | * |
53 | * For "warning" dialogs, i.e. dialogs with a potentially destructive action, the default |
54 | * button is set to a button with the QDialogButtonBox::RejectRole. If the "Cancel" button |
55 | + * is used, it will be the default, otherwise the secondary action button. |
56 | * |
57 | * This class intends to be very flexible with the buttons that can be used, since you can |
58 | * call the @ref setButtons() method with a KGuiItem that has custom text/icon. |
59 | * |
60 | * Since Frameworks 5.97 a notification sound is played when the dialog opens like KMessageBox |
61 | * does, this can be controlled using the @ref setNotifyEnabled() method. |
62 | * |
63 | * Example: |
64 | * @code |
65 | * auto *dlg = new KMessageDialog(KMessageDialog::QuestionTwoActionsCancel, |
66 | * QStringLiteral("Back or forward?"), |
67 | * nullptr); |
68 | * |
69 | * dlg->setCaption(QStringLiteral("Window Title")); |
70 | * dlg->setButtons(KStandardGuiItem::back(), KStandardGuiItem::forward(), 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<KMessageDialog::ButtonType>(result); |
83 | * switch(button) { |
84 | * case KMessageDialog::PrimaryAction: |
85 | * // The user clicked the primary action, handle the result... |
86 | * // save the "do not ask again" box status... |
87 | * break; |
88 | * case KMessageDialog::SecondaryAction: |
89 | * // The user clicked the secondary action, handle the result... |
90 | * // save the "do not ask again" box status... |
91 | * break; |
92 | * case KMessageDialog::Cancel: |
93 | * // The user clicked cancel, reject the changes... |
94 | * break; |
95 | * default: |
96 | * break; |
97 | * } |
98 | * }); |
99 | * |
100 | * dlg->show(); |
101 | * @endcode |
102 | * |
103 | * @since 5.77 |
104 | */ |
105 | |
106 | class KWIDGETSADDONS_EXPORT KMessageDialog : public QDialog |
107 | { |
108 | Q_OBJECT |
109 | |
110 | public: |
111 | /** |
112 | * Button types |
113 | * @since 5.100 |
114 | */ |
115 | enum ButtonType { |
116 | Ok = 1, ///< Ok button |
117 | Cancel = 2, ///< Cancel button |
118 | PrimaryAction = 3, ///< Primary action button |
119 | SecondaryAction = 4, ///< Secondary action button |
120 | }; |
121 | |
122 | enum Type { |
123 | QuestionTwoActions = 1, ///< Question dialog with two buttons; @since 5.100 |
124 | QuestionTwoActionsCancel = 2, ///< Question dialog with two buttons and Cancel; @since 5.100 |
125 | WarningTwoActions = 3, ///< Warning dialog with two buttons; @since 5.100 |
126 | WarningTwoActionsCancel = 4, ///< Warning dialog with two buttons and Cancel; @since 5.100 |
127 | WarningContinueCancel = 5, ///< Warning dialog with Continue and Cancel |
128 | Information = 6, ///< Information dialog |
129 | Error = 8, ///< Error dialog |
130 | }; |
131 | |
132 | /** |
133 | * Constructs a KMessageDialog. |
134 | * |
135 | * Buttons based on the dialog type are set by default in some cases, |
136 | * using KStandardGuiItem instances. For the dialog types Information and Error |
137 | * the button is set to KStandardGuiItem::ok(). For the type WarningContinueCancel |
138 | * the buttons are set to KStandardGuiItem::cont() & KStandardGuiItem::cancel(). |
139 | * |
140 | * For the other Quesion* and Warning* types the buttons are to be set explicitly. |
141 | * |
142 | * @param type the dialog Type, one of KMessageDialog::Type enum |
143 | * @param text the text message that is going to be displayed in the dialog |
144 | * @param parent a QWidget* that will be set as the dialog parent |
145 | */ |
146 | explicit KMessageDialog(KMessageDialog::Type type, const QString &text, QWidget *parent = nullptr); |
147 | |
148 | /** |
149 | * This constructor takes the window Id of the parent window, instead of a QWidget*. |
150 | * |
151 | * @param type the dialog Type, one of KMessageDialog::Type enum |
152 | * @param text the text message that is going to be displayed in the dialog |
153 | * @param parent_id the native parent's window system identifier |
154 | */ |
155 | explicit KMessageDialog(KMessageDialog::Type type, const QString &text, WId parent_id); |
156 | /** |
157 | * Destructor |
158 | */ |
159 | ~KMessageDialog() override; |
160 | |
161 | /** |
162 | * This can be used to set the title of the dialog window. If you pass an |
163 | * empty QString(), a generic title will be used depending on the dialog |
164 | * Type. E.g. for KMessageDialog::WarningTwoActions, "Warning" will be used. |
165 | */ |
166 | void setCaption(const QString &caption); |
167 | |
168 | /** |
169 | * This can be used to set an icon that will be shown next to the main |
170 | * text message. If you pass a null QIcon() a generic icon based on the dialog |
171 | * Type will be used. E.g. for KMessageDialog::QuestionTwoActions, QMessageBox::Question |
172 | * will be used. |
173 | */ |
174 | void setIcon(const QIcon &icon); |
175 | |
176 | /** |
177 | * This will add a QListWidget to the dialog and populate it with @p strlist. |
178 | * If @p strlist is empty, the list widget will not be shown. |
179 | */ |
180 | void setListWidgetItems(const QStringList &strlist); |
181 | |
182 | /** |
183 | * This will add a KCollapsibleGroupBox with a title "Details", as the class name |
184 | * implies it is collapsible (and collapsed by default); you can use it to add a |
185 | * more detailed explanation of what the dialog is trying to tell the user. |
186 | * |
187 | * If @p details is empty, the details widget will not be shown. |
188 | */ |
189 | void setDetails(const QString &details); |
190 | |
191 | /** |
192 | * This will add a "Do not ask again" checkbox to the dialog with the text |
193 | * from @p dontAskAgainText. You can set the initial status of the checkbox |
194 | * by using setDontAskAgainChecked(). |
195 | * |
196 | * If @p dontAskAgainText is empty, no checkbox will be shown. |
197 | * |
198 | * Typical usage of this checkbox is for recurring questions, e.g. showing |
199 | * a dialog to confirm moving files/directories to trash, the user can then |
200 | * set the checkbox so as not to be asked about that again. |
201 | * |
202 | * You can get the state of the checkbox by using isDontAskAgainChecked(). |
203 | */ |
204 | void setDontAskAgainText(const QString &dontAskAgainText); |
205 | |
206 | /** |
207 | * This can be used to set the initial status of the "Do not ask again" checkbox, |
208 | * checked or unchecked, by setting @p isChecked to @c true or @c false |
209 | * respectively. |
210 | * |
211 | * You need to call setDontAskAgainText() first to actually show a checkbox in |
212 | * the dialog, otherwise calling this function will have no effect. |
213 | */ |
214 | void setDontAskAgainChecked(bool isChecked); |
215 | |
216 | /** |
217 | * This can be used to query the status of the "Do not ask again" checkbox; |
218 | * returns @c true if the box is checked and @c false otherwise. |
219 | * |
220 | * @note This method will return @c false if a checkbox widget isn't shown in |
221 | * the dialog. The dialog will not show a checkbox if setDontAskAgainText() was |
222 | * not used previously to add a checkbox to begin with. |
223 | */ |
224 | bool isDontAskAgainChecked() const; |
225 | |
226 | /** |
227 | * Sets the text labels in the dialog to either allow opening external links or not. |
228 | */ |
229 | void setOpenExternalLinks(bool isAllowed); |
230 | |
231 | /** |
232 | * Whether a KNotification is emitted when the dialog is shown. |
233 | * |
234 | * This typically plays a notification sound. Default is true. |
235 | * |
236 | * @since 5.97 |
237 | * @sa KMessageBox::Notify |
238 | */ |
239 | bool isNotifyEnabled() const; |
240 | |
241 | /** |
242 | * Whether to emit a KNotification when the dialog is shown. |
243 | * |
244 | * This typically plays a notification sound. |
245 | * |
246 | * @since 5.97 |
247 | * @sa KMessageBox::Notify |
248 | */ |
249 | void setNotifyEnabled(bool enable); |
250 | |
251 | /** |
252 | * Sets the buttons in the buttom box. |
253 | * |
254 | * Using this method, you can customize the behavior based on your use-case, by |
255 | * using a KGuiItem to get a button with custom text and icon. |
256 | * |
257 | * Since 5.85 buttons based on the dialog type are added by default (see |
258 | * KMessageDialog(KMessageDialog::Type, const QString &, QWidget *) for details). |
259 | * Before, this method had to be called explicitly to have any buttons added to the dialog. |
260 | * |
261 | * @note |
262 | * - For dialog types Information and Error only one button |
263 | * (KStandardGuiItem::ok()) is added to the dialog. |
264 | * |
265 | * @param primaryAction the action for the primary button. |
266 | * Reported in the result for dialog types Information and Error |
267 | * as KMessageDialog::Ok enum value, otherwise as KMessageDialog::PrimaryAction. |
268 | * @param secondaryAction the action for the secondary button. |
269 | * Reported in the result as KMessageDialog::SecondaryAction enum value. |
270 | * Ignored with all dialog types without a "secondary" action. |
271 | * @param cancelAction the action for the cancel button. |
272 | * Reported in the result as KMessageDialog::Cancel enum value. |
273 | * Ignored with all dialog types without a Cancel button. |
274 | */ |
275 | void setButtons(const KGuiItem &primaryAction = KGuiItem(), const KGuiItem &secondaryAction = KGuiItem(), const KGuiItem &cancelAction = KGuiItem()); |
276 | |
277 | /** |
278 | * Manually play the notification sound |
279 | * |
280 | * When implementing your entirely own message box, not using KMessageDialog, |
281 | * you can call this function to play the relevant notification sound (if enabled). |
282 | * |
283 | * @note You don't need to call this when using KMessageDialog, it plays the sound automatically. |
284 | * |
285 | * @param type The message box type |
286 | * @param text The message box contents, for accessibility purposes. |
287 | * @param dialog The dialog that was displayed |
288 | * @since 6.0 |
289 | * @sa setNotifyEnabled |
290 | */ |
291 | static void beep(KMessageDialog::Type type, const QString &text = QString(), QWidget *dialog = nullptr); |
292 | |
293 | protected: |
294 | void showEvent(QShowEvent *event) override; |
295 | |
296 | private: |
297 | std::unique_ptr<KMessageDialogPrivate> const d; |
298 | }; |
299 | |
300 | #endif // KMESSAGEDIALOG_H |
301 | |