Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / ui / qt / simple_dialog.cpp
blobef5ee2de69a1c7b9553492ec3a83ffcaf60192ea
1 /* simple_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include "simple_dialog.h"
12 #include "file.h"
14 #include "epan/strutil.h"
15 #include "epan/prefs.h"
17 #include "ui/commandline.h"
19 #include <wsutil/utf8_entities.h>
20 #include <wsutil/wslog.h>
22 #include <ui/qt/utils/qt_ui_utils.h>
23 #include "main_application.h"
25 #include <functional>
26 #include <QCheckBox>
27 #include <QMessageBox>
28 #include <QMutex>
29 #include <QRegularExpression>
30 #include <QTextCodec>
32 /* Simple dialog function - Displays a dialog box with the supplied message
33 * text.
35 * This is meant to be used as a backend for the functions defined in
36 * ui/simple_dialog.h. Qt code should use QMessageBox directly.
38 * Args:
39 * type : One of ESD_TYPE_*.
40 * btn_mask : The value passed in determines which buttons are displayed.
41 * msg_format : Sprintf-style format of the text displayed in the dialog.
42 * ... : Argument list for msg_format
45 QList<MessagePair> message_queue_;
46 ESD_TYPE_E max_severity_ = ESD_TYPE_INFO;
48 struct VisibleAsyncMessage
50 QMessageBox *box;
51 int counter;
53 VisibleAsyncMessage(QMessageBox *box) : box(box), counter(0) {}
56 static QList<VisibleAsyncMessage> visible_messages;
57 static QMutex visible_messages_mutex;
59 static void visible_message_finished(QMessageBox *box, int result _U_)
61 visible_messages_mutex.lock();
62 for (int i = 0; i < visible_messages.size(); i++) {
63 if (visible_messages[i].box == box) {
64 if (visible_messages[i].counter) {
65 ws_log(LOG_DOMAIN_MAIN, LOG_LEVEL_WARNING, "%d duplicates of \"%s\" were suppressed",
66 visible_messages[i].counter, box->text().toStdString().c_str());
68 visible_messages.removeAt(i);
69 break;
72 visible_messages_mutex.unlock();
75 char *
76 simple_dialog_format_message(const char *msg)
78 return g_strdup(msg);
81 void *
82 simple_dialog(ESD_TYPE_E type, int btn_mask, const char *msg_format, ...)
84 va_list ap;
86 va_start(ap, msg_format);
87 SimpleDialog sd(mainApp->mainWindow(), type, btn_mask, msg_format, ap);
88 va_end(ap);
90 sd.exec();
91 return NULL;
94 void *
95 simple_dialog_async(ESD_TYPE_E type, int btn_mask, const char *msg_format, ...)
97 va_list ap;
99 va_start(ap, msg_format);
100 SimpleDialog sd(mainApp->mainWindow(), type, btn_mask, msg_format, ap);
101 va_end(ap);
103 sd.show();
104 return NULL;
108 * Alert box, with optional "don't show this message again" variable
109 * and checkbox, and optional secondary text.
111 void
112 simple_message_box(ESD_TYPE_E type, bool *notagain,
113 const char *secondary_msg, const char *msg_format, ...)
115 if (notagain && *notagain) {
116 return;
119 va_list ap;
121 va_start(ap, msg_format);
122 SimpleDialog sd(mainApp->mainWindow(), type, ESD_BTN_OK, msg_format, ap);
123 va_end(ap);
125 sd.setInformativeText(secondary_msg);
127 QCheckBox *cb = NULL;
128 if (notagain) {
129 cb = new QCheckBox();
130 cb->setChecked(true);
131 cb->setText(SimpleDialog::dontShowThisAgain());
132 sd.setCheckBox(cb);
135 sd.exec();
137 if (notagain && cb) {
138 *notagain = cb->isChecked();
143 * Error alert box, taking a format and a va_list argument.
145 void
146 vsimple_error_message_box(const char *msg_format, va_list ap)
148 #ifdef HAVE_LIBPCAP
149 // We want to quit after reading the capture file, hence
150 // we don't actually open the error dialog.
151 if (global_commandline_info.quit_after_cap)
152 exit(0);
153 #endif
155 SimpleDialog sd(mainApp->mainWindow(), ESD_TYPE_ERROR, ESD_BTN_OK, msg_format, ap);
156 sd.show();
160 * Warning alert box, taking a format and a va_list argument.
162 void
163 vsimple_warning_message_box(const char *msg_format, va_list ap)
165 #ifdef HAVE_LIBPCAP
166 // We want to quit after reading the capture file, hence
167 // we don't actually open the error dialog.
168 if (global_commandline_info.quit_after_cap)
169 exit(0);
170 #endif
172 SimpleDialog sd(mainApp->mainWindow(), ESD_TYPE_WARN, ESD_BTN_OK, msg_format, ap);
173 sd.show();
177 * Error alert box, taking a format and a list of arguments.
179 void
180 simple_error_message_box(const char *msg_format, ...)
182 va_list ap;
184 va_start(ap, msg_format);
185 vsimple_error_message_box(msg_format, ap);
186 va_end(ap);
189 SimpleDialog::SimpleDialog(QWidget *parent, ESD_TYPE_E type, int btn_mask, const char *msg_format, va_list ap) :
190 check_box_(0),
191 message_box_(0)
193 char *vmessage;
194 QString message;
196 vmessage = ws_strdup_vprintf(msg_format, ap);
197 #ifdef _WIN32
199 // On Windows, filename strings inside Wireshark are UTF-8 strings,
200 // so error messages containing file names are UTF-8 strings. Convert
201 // from UTF-8, not from the local code page.
203 message = QString().fromUtf8(vmessage, -1);
204 #else
206 // On UN*X, who knows? Assume the locale's encoding.
208 message = QTextCodec::codecForLocale()->toUnicode(vmessage);
209 #endif
210 g_free(vmessage);
212 MessagePair msg_pair(message, QString());
213 // Remove leading and trailing whitespace along with excessive newline runs.
214 QString primary = msg_pair.first.trimmed();
215 QString secondary = msg_pair.second.trimmed();
216 secondary.replace(QRegularExpression("\n\n+"), "\n\n");
218 if (primary.isEmpty()) {
219 return;
222 if (!parent || !mainApp->isInitialized() || mainApp->isReloadingLua()) {
223 message_queue_ << msg_pair;
224 if (type > max_severity_) {
225 max_severity_ = type;
227 return;
230 message_box_ = new QMessageBox(parent);
231 message_box_->setTextFormat(Qt::PlainText);
232 message_box_->setTextInteractionFlags(Qt::TextSelectableByMouse);
234 switch(type) {
235 case ESD_TYPE_ERROR:
236 message_box_->setIcon(QMessageBox::Critical);
237 break;
238 case ESD_TYPE_WARN:
239 message_box_->setIcon(QMessageBox::Warning);
240 break;
241 case ESD_TYPE_CONFIRMATION:
242 message_box_->setIcon(QMessageBox::Question);
243 break;
244 case ESD_TYPE_INFO:
245 default:
246 message_box_->setIcon(QMessageBox::Information);
247 break;
250 if (btn_mask & ESD_BTN_OK) {
251 message_box_->addButton(QMessageBox::Ok);
253 if (btn_mask & ESD_BTN_CANCEL) {
254 message_box_->addButton(QMessageBox::Cancel);
256 if (btn_mask & ESD_BTN_YES) {
257 message_box_->addButton(QMessageBox::Yes);
259 if (btn_mask & ESD_BTN_NO) {
260 message_box_->addButton(QMessageBox::No);
262 // if (btn_mask & ESD_BTN_CLEAR) {
263 // addButton(QMessageBox::);
264 // }
265 if (btn_mask & ESD_BTN_SAVE) {
266 message_box_->addButton(QMessageBox::Save);
268 if (btn_mask & ESD_BTN_DONT_SAVE) {
269 message_box_->addButton(QMessageBox::Discard);
271 // if (btn_mask & ESD_BTN_QUIT_DONT_SAVE) {
272 // addButton(QMessageBox::);
273 // }
276 message_box_->setText(primary);
277 message_box_->setInformativeText(secondary);
280 SimpleDialog::~SimpleDialog()
284 void SimpleDialog::displayQueuedMessages(QWidget *parent)
286 if (message_queue_.isEmpty()) {
287 return;
290 QMessageBox mb(parent ? parent : mainApp->mainWindow());
292 switch(max_severity_) {
293 case ESD_TYPE_ERROR:
294 mb.setIcon(QMessageBox::Critical);
295 break;
296 case ESD_TYPE_WARN:
297 mb.setIcon(QMessageBox::Warning);
298 break;
299 case ESD_TYPE_CONFIRMATION:
300 mb.setIcon(QMessageBox::Question);
301 break;
302 case ESD_TYPE_INFO:
303 default:
304 mb.setIcon(QMessageBox::Information);
305 break;
308 mb.addButton(QMessageBox::Ok);
310 if (message_queue_.length() > 1) {
311 QStringList msg_details;
312 QString first_primary = message_queue_[0].first;
313 first_primary.append(UTF8_HORIZONTAL_ELLIPSIS);
315 mb.setText(QObject::tr("Multiple problems found"));
316 mb.setInformativeText(first_primary);
318 foreach (MessagePair msg_pair, message_queue_) {
319 msg_details << msg_pair.first;
320 if (!msg_pair.second.isEmpty()) {
321 msg_details.append(msg_pair.second);
324 mb.setDetailedText(msg_details.join("\n\n"));
325 } else {
326 mb.setText(message_queue_[0].first);
327 mb.setInformativeText(message_queue_[0].second);
330 message_queue_.clear();
331 max_severity_ = ESD_TYPE_INFO;
333 mb.exec();
336 QString SimpleDialog::dontShowThisAgain()
338 return QObject::tr("Don't show this message again.");
341 int SimpleDialog::exec()
343 if (!message_box_) {
344 return 0;
347 message_box_->setInformativeText(informative_text_);
348 message_box_->setDetailedText(detailed_text_);
349 message_box_->setCheckBox(check_box_);
351 int status = message_box_->exec();
352 delete message_box_;
353 message_box_ = 0;
354 informative_text_ = QString();
355 detailed_text_ = QString();
357 switch (status) {
358 case QMessageBox::Ok:
359 return ESD_BTN_OK;
360 case QMessageBox::Yes:
361 return ESD_BTN_YES;
362 case QMessageBox::No:
363 return ESD_BTN_NO;
364 case QMessageBox::Save:
365 return ESD_BTN_SAVE;
366 case QMessageBox::Discard:
367 return ESD_BTN_DONT_SAVE;
368 case QMessageBox::Cancel: // XXX Should OK be the default?
369 default:
370 return ESD_BTN_CANCEL;
374 void SimpleDialog::show()
376 if (!message_box_) {
377 return;
380 message_box_->setInformativeText(informative_text_);
381 message_box_->setDetailedText(detailed_text_);
382 message_box_->setCheckBox(check_box_);
384 visible_messages_mutex.lock();
385 bool found = false;
386 for (int i = 0; i < visible_messages.size(); i++) {
387 VisibleAsyncMessage &msg = visible_messages[i];
388 if ((msg.box->icon() == message_box_->icon()) &&
389 (msg.box->checkBox() == message_box_->checkBox()) &&
390 (msg.box->text() == message_box_->text()) &&
391 (msg.box->informativeText() == message_box_->informativeText()) &&
392 (msg.box->detailedText() == message_box_->detailedText()))
394 /* Message box of same type with same text is already visible. */
395 msg.counter++;
396 found = true;
397 break;
400 if (!found) {
401 visible_messages.append(VisibleAsyncMessage(message_box_));
403 visible_messages_mutex.unlock();
405 if (found)
407 delete message_box_;
409 else
411 QObject::connect(message_box_, &QMessageBox::finished,
412 std::bind(visible_message_finished,message_box_,std::placeholders::_1));
413 message_box_->setModal(Qt::WindowModal);
414 message_box_->setAttribute(Qt::WA_DeleteOnClose);
415 message_box_->show();
418 /* Message box was shown and will be deleted once user closes it */
419 message_box_ = 0;