Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / ui / qt / welcome_page.cpp
blob8a93c5044553902ee7dec2e483b775d5199718e2
1 /* welcome_page.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 "config.h"
12 #include <epan/prefs.h>
14 #include "ui/capture_globals.h"
15 #include "ui/urls.h"
17 #include "wsutil/filesystem.h"
18 #include "wsutil/version_info.h"
20 #include "welcome_page.h"
21 #include <ui_welcome_page.h>
22 #include <ui/qt/utils/tango_colors.h>
23 #include <ui/qt/utils/color_utils.h>
24 #include <ui/qt/utils/qt_ui_utils.h>
25 #include "main_application.h"
27 #include <QClipboard>
28 #include <QDate>
29 #include <QDesktopServices>
30 #include <QDir>
31 #include <QListWidget>
32 #include <QMenu>
33 #include <QResizeEvent>
34 #include <QUrl>
35 #include <QWidget>
37 #ifndef VERSION_FLAVOR
38 #define VERSION_FLAVOR ""
39 #endif
41 #include <extcap.h>
43 WelcomePage::WelcomePage(QWidget *parent) :
44 QFrame(parent),
45 welcome_ui_(new Ui::WelcomePage),
46 flavor_(tr(VERSION_FLAVOR)),
47 #ifdef Q_OS_MAC
48 show_in_str_(tr("Show in Finder")),
49 #else
50 show_in_str_(tr("Show in Folder")),
51 #endif
52 splash_overlay_(NULL)
55 welcome_ui_->setupUi(this);
57 recent_files_ = welcome_ui_->recentList;
59 welcome_ui_->captureFilterComboBox->setEnabled(false);
61 welcome_ui_->mainWelcomeBanner->setText(tr("Welcome to %1").arg(mainApp->applicationName()));
63 updateStyleSheets();
66 #ifdef Q_OS_MAC
67 recent_files_->setAttribute(Qt::WA_MacShowFocusRect, false);
68 #endif
70 welcome_ui_->openFrame->hide();
71 recent_files_->setTextElideMode(Qt::ElideLeft);
73 welcome_ui_->recentList->setContextMenuPolicy(Qt::CustomContextMenu);
74 connect(recent_files_, &QListWidget::customContextMenuRequested, this, &WelcomePage::showRecentContextMenu);
76 connect(mainApp, &MainApplication::updateRecentCaptureStatus, this, &WelcomePage::updateRecentCaptures);
77 connect(mainApp, &MainApplication::preferencesChanged, this, &WelcomePage::updateRecentCaptures);
78 connect(mainApp, &MainApplication::appInitialized, this, &WelcomePage::appInitialized);
79 connect(mainApp, &MainApplication::localInterfaceListChanged, this, &WelcomePage::interfaceListChanged);
80 #ifdef HAVE_LIBPCAP
81 connect(mainApp, &MainApplication::scanLocalInterfaces,
82 welcome_ui_->interfaceFrame, &InterfaceFrame::scanLocalInterfaces);
83 #endif
84 connect(welcome_ui_->interfaceFrame, &InterfaceFrame::itemSelectionChanged,
85 welcome_ui_->captureFilterComboBox, &CaptureFilterCombo::interfacesChanged);
86 connect(welcome_ui_->interfaceFrame, &InterfaceFrame::typeSelectionChanged,
87 this, &WelcomePage::interfaceListChanged);
88 connect(welcome_ui_->interfaceFrame, &InterfaceFrame::itemSelectionChanged, this, &WelcomePage::interfaceSelected);
89 connect(welcome_ui_->captureFilterComboBox->lineEdit(), &QLineEdit::textEdited,
90 this, &WelcomePage::captureFilterTextEdited);
91 connect(welcome_ui_->captureFilterComboBox, &CaptureFilterCombo::captureFilterSyntaxChanged,
92 this, &WelcomePage::captureFilterSyntaxChanged);
93 connect(welcome_ui_->captureFilterComboBox, &CaptureFilterCombo::startCapture,
94 this, &WelcomePage::captureStarting);
95 connect(recent_files_, &QListWidget::itemActivated, this, &WelcomePage::openRecentItem);
96 updateRecentCaptures();
98 splash_overlay_ = new SplashOverlay(this);
101 WelcomePage::~WelcomePage()
103 delete welcome_ui_;
106 InterfaceFrame *WelcomePage::getInterfaceFrame()
108 return welcome_ui_->interfaceFrame;
111 const QString WelcomePage::captureFilter()
113 return welcome_ui_->captureFilterComboBox->currentText();
116 void WelcomePage::setCaptureFilter(const QString capture_filter)
118 // capture_filter comes from the current filter in
119 // CaptureInterfacesDialog. We need to find a good way to handle
120 // multiple filters.
121 welcome_ui_->captureFilterComboBox->lineEdit()->setText(capture_filter);
124 void WelcomePage::interfaceListChanged()
126 QString btnText = tr("All interfaces shown");
127 if (welcome_ui_->interfaceFrame->interfacesHidden() > 0) {
128 btnText = tr("%n interface(s) shown, %1 hidden", "",
129 welcome_ui_->interfaceFrame->interfacesPresent())
130 .arg(welcome_ui_->interfaceFrame->interfacesHidden());
132 welcome_ui_->btnInterfaceType->setText(btnText);
133 welcome_ui_->btnInterfaceType->setMenu(welcome_ui_->interfaceFrame->getSelectionMenu());
136 void WelcomePage::setReleaseLabel()
138 // XXX Add a "check for updates" link?
139 QString full_release;
140 QDate today = QDate::currentDate();
141 if ((today.month() == 4 && today.day() == 1) || (today.month() == 7 && today.day() == 14)) {
142 if (is_packet_configuration_namespace()) {
143 full_release = tr("You are sniffing the glue that holds the Internet together using Wireshark ");
144 } else {
145 full_release = tr("You are sniffing the glue that holds your system together using Stratoshark ");
147 } else {
148 if (is_packet_configuration_namespace()) {
149 full_release = tr("You are running Wireshark ");
150 } else {
151 full_release = tr("You are running Stratoshark ");
154 full_release += is_packet_configuration_namespace() ? get_ws_vcs_version_info() : get_ss_vcs_version_info();
155 full_release += ".";
156 #ifdef HAVE_SOFTWARE_UPDATE
157 if (prefs.gui_update_enabled) {
158 full_release += tr(" You receive automatic updates.");
159 } else {
160 full_release += tr(" You have disabled automatic updates.");
162 #else
163 // XXX Is there a way to tell if the user installed Wireshark via an
164 // external package manager? If so we could say so here. We could
165 // also add a link to the download page.
166 #endif
167 welcome_ui_->fullReleaseLabel->setText(full_release);
170 void WelcomePage::appInitialized()
172 setReleaseLabel();
174 #ifdef HAVE_LIBPCAP
175 welcome_ui_->captureFilterComboBox->lineEdit()->setText(global_capture_opts.default_options.cfilter);
176 #endif // HAVE_LIBPCAP
178 welcome_ui_->captureFilterComboBox->setEnabled(true);
180 interfaceListChanged();
182 welcome_ui_->interfaceFrame->ensureSelectedInterface();
184 delete splash_overlay_;
185 splash_overlay_ = NULL;
188 #ifdef HAVE_LIBPCAP
189 // Update each selected device cfilter when the user changes the contents
190 // of the capture filter lineedit. We do so here so that we don't clobber
191 // filters set in the Capture Options / Interfaces dialog or ones set via
192 // the command line.
193 void WelcomePage::captureFilterTextEdited(const QString capture_filter)
195 if (global_capture_opts.num_selected > 0) {
196 interface_t *device;
198 for (unsigned i = 0; i < global_capture_opts.all_ifaces->len; i++) {
199 device = &g_array_index(global_capture_opts.all_ifaces, interface_t, i);
200 if (!device->selected) {
201 continue;
203 // if (device->active_dlt == -1) {
204 // simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "The link type of interface %s was not specified.", device->name);
205 // continue; /* Programming error: somehow managed to select an "unsupported" entry */
206 // }
207 g_free(device->cfilter);
208 if (capture_filter.isEmpty()) {
209 device->cfilter = NULL;
210 } else {
211 device->cfilter = qstring_strdup(capture_filter);
213 // update_filter_string(device->name, filter_text);
217 #else
218 // No-op if we don't have capturing.
219 void WelcomePage::captureFilterTextEdited(const QString)
222 #endif
224 // The interface list selection has changed. At this point the user might
225 // have entered a filter or we might have pre-filled one from a number of
226 // sources such as our remote connection, the command line, or a previous
227 // selection.
228 // Must not change any interface data.
229 void WelcomePage::interfaceSelected()
231 QPair <const QString, bool> sf_pair = CaptureFilterEdit::getSelectedFilter();
232 const QString user_filter = sf_pair.first;
233 bool conflict = sf_pair.second;
235 if (conflict) {
236 welcome_ui_->captureFilterComboBox->lineEdit()->clear();
237 welcome_ui_->captureFilterComboBox->setConflict(true);
238 } else {
239 welcome_ui_->captureFilterComboBox->lineEdit()->setText(user_filter);
242 // Notify others (capture options dialog) that the selection has changed.
243 emit interfacesChanged();
246 bool WelcomePage::event(QEvent *event)
248 switch (event->type()) {
249 case QEvent::ApplicationPaletteChange:
250 updateStyleSheets();
251 break;
252 default:
253 break;
256 return QFrame::event(event);
259 void WelcomePage::on_interfaceFrame_showExtcapOptions(QString device_name, bool startCaptureOnClose)
261 emit showExtcapOptions(device_name, startCaptureOnClose);
264 void WelcomePage::on_interfaceFrame_startCapture(QStringList ifaces)
266 emit startCapture(ifaces);
269 void WelcomePage::captureStarting()
271 welcome_ui_->interfaceFrame->ensureSelectedInterface();
272 emit startCapture(QStringList());
275 void WelcomePage::updateRecentCaptures() {
276 QString itemLabel;
277 QListWidgetItem *rfItem;
278 QFont rfFont;
279 QString selectedFilename;
281 if (!recent_files_->selectedItems().isEmpty()) {
282 rfItem = recent_files_->selectedItems().first();
283 selectedFilename = rfItem->data(Qt::UserRole).toString();
286 if (mainApp->recentItems().count() == 0 || prefs.gui_welcome_page_show_recent) {
287 // Recent menu has been cleared, remove all recent files.
288 while (recent_files_->count()) {
289 delete recent_files_->item(0);
293 int rfRow = 0;
294 if(prefs.gui_welcome_page_show_recent) {
295 foreach (recent_item_status *ri, mainApp->recentItems()) {
296 itemLabel = ri->filename;
298 if (rfRow >= recent_files_->count()) {
299 recent_files_->addItem(itemLabel);
302 itemLabel.append(" (");
303 if (ri->accessible) {
304 if (ri->size/1024/1024/1024 > 10) {
305 itemLabel.append(QStringLiteral("%1 GB").arg(ri->size/1024/1024/1024));
306 } else if (ri->size/1024/1024 > 10) {
307 itemLabel.append(QStringLiteral("%1 MB").arg(ri->size/1024/1024));
308 } else if (ri->size/1024 > 10) {
309 itemLabel.append(QStringLiteral("%1 KB").arg(ri->size/1024));
310 } else {
311 itemLabel.append(QStringLiteral("%1 Bytes").arg(ri->size));
313 } else {
314 itemLabel.append(tr("not found"));
316 itemLabel.append(")");
317 rfFont.setItalic(!ri->accessible);
318 rfItem = recent_files_->item(rfRow);
319 rfItem->setText(itemLabel);
320 rfItem->setData(Qt::AccessibleTextRole, itemLabel);
321 rfItem->setData(Qt::UserRole, ri->filename);
322 rfItem->setFlags(ri->accessible ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags);
323 rfItem->setFont(rfFont);
324 if (ri->filename == selectedFilename) {
325 rfItem->setSelected(true);
327 rfRow++;
331 int row = recent_files_->count();
332 while (row > 0 && (row > (int) prefs.gui_recent_files_count_max || row > rfRow)) {
333 row--;
334 delete recent_files_->item(row);
336 if (recent_files_->count() > 0) {
337 welcome_ui_->openFrame->animatedShow();
338 } else {
339 welcome_ui_->openFrame->animatedHide();
343 void WelcomePage::openRecentItem(QListWidgetItem *item) {
344 QString cfPath = item->data(Qt::UserRole).toString();
345 emit recentFileActivated(cfPath);
348 void WelcomePage::resizeEvent(QResizeEvent *event)
350 if (splash_overlay_)
351 splash_overlay_->resize(event->size());
352 // event->accept();
354 QFrame::resizeEvent(event);
357 void WelcomePage::setCaptureFilterText(const QString capture_filter)
359 welcome_ui_->captureFilterComboBox->lineEdit()->setText(capture_filter);
360 captureFilterTextEdited(capture_filter);
363 void WelcomePage::changeEvent(QEvent* event)
365 if (0 != event)
367 switch (event->type())
369 case QEvent::LanguageChange:
370 welcome_ui_->retranslateUi(this);
371 welcome_ui_->flavorBanner->setText(flavor_);
372 interfaceListChanged();
373 setReleaseLabel();
374 break;
375 default:
376 break;
379 QFrame::changeEvent(event);
382 void WelcomePage::showRecentContextMenu(QPoint pos)
384 QListWidgetItem *li = recent_files_->itemAt(pos);
385 if (!li) return;
387 QMenu *recent_ctx_menu = new QMenu(this);
388 recent_ctx_menu->setAttribute(Qt::WA_DeleteOnClose);
390 QString cf_path = li->data(Qt::UserRole).toString();
392 QAction *show_action = recent_ctx_menu->addAction(show_in_str_);
393 show_action->setData(cf_path);
394 connect(show_action, &QAction::triggered, this, &WelcomePage::showRecentFolder);
396 QAction *copy_action = recent_ctx_menu->addAction(tr("Copy file path"));
397 copy_action->setData(cf_path);
398 connect(copy_action, &QAction::triggered, this, &WelcomePage::copyRecentPath);
400 recent_ctx_menu->addSeparator();
402 QAction *remove_action = recent_ctx_menu->addAction(tr("Remove from list"));
403 remove_action->setData(cf_path);
404 connect(remove_action, &QAction::triggered, this, &WelcomePage::removeRecentPath);
406 recent_ctx_menu->popup(recent_files_->mapToGlobal(pos));
409 void WelcomePage::showRecentFolder()
411 QAction *ria = qobject_cast<QAction*>(sender());
412 if (!ria) return;
414 QString cf_path = ria->data().toString();
415 if (cf_path.isEmpty()) return;
417 desktop_show_in_folder(cf_path);
420 void WelcomePage::copyRecentPath()
422 QAction *ria = qobject_cast<QAction*>(sender());
423 if (!ria) return;
425 QString cf_path = ria->data().toString();
426 if (cf_path.isEmpty()) return;
428 mainApp->clipboard()->setText(cf_path);
431 void WelcomePage::removeRecentPath()
433 QAction *ria = qobject_cast<QAction*>(sender());
434 if (!ria) return;
436 QString cf_path = ria->data().toString();
437 if (cf_path.isEmpty()) return;
439 mainApp->removeRecentItem(cf_path);
442 void WelcomePage::on_captureLabel_clicked()
444 mainApp->doTriggerMenuItem(MainApplication::CaptureOptionsDialog);
447 void WelcomePage::on_helpLabel_clicked()
449 QDesktopServices::openUrl(QUrl(WS_DOCS_URL));
452 void WelcomePage::updateStyleSheets()
454 QString welcome_ss = QString(
455 "WelcomePage {"
456 " padding: 1em;"
457 " }"
458 "WelcomePage, QAbstractItemView {"
459 " background-color: palette(base);"
460 " color: palette(text);"
461 " }"
462 "QAbstractItemView {"
463 " border: 0;"
466 #if !defined(Q_OS_WIN)
467 welcome_ss += QString(
468 "QAbstractItemView:item:hover {"
469 " background-color: %1;"
470 " color: palette(text);"
473 .arg(ColorUtils::hoverBackground().name(QColor::HexArgb));
474 #endif
475 setStyleSheet(welcome_ss);
477 QString banner_ss = QString(
478 "QLabel {"
479 " border-radius: 0.33em;"
480 " color: %1;"
481 " background-color: %2;"
482 " padding: 0.33em;"
485 .arg(QColor(tango_aluminium_6).name()) // Text color
486 .arg(QColor(tango_sky_blue_2).name()); // Background color
487 welcome_ui_->mainWelcomeBanner->setStyleSheet(banner_ss);
489 QString title_button_ss = QString(
490 "QLabel {"
491 " color: %1;"
493 "QLabel::hover {"
494 " color: %2;"
497 .arg(QColor(tango_aluminium_4).name()) // Text color
498 .arg(QColor(tango_sky_blue_4).name()); // Hover color
500 // XXX Is there a better term than "flavor"? Provider? Admonition (a la DocBook)?
501 // Release_source?
502 // Typical use cases are automated builds from wireshark.org and private,
503 // not-for-redistribution packages.
504 if (flavor_.isEmpty()) {
505 welcome_ui_->flavorBanner->hide();
506 } else {
507 // If needed there are a couple of ways we can make this customizable.
508 // - Add one or more classes, e.g. "note" or "warning" similar to
509 // SyntaxLineEdit, which we can then expose vi #defines.
510 // - Just expose direct color values via #defines.
511 QString flavor_ss = QString(
512 "QLabel {"
513 " border-radius: 0.25em;"
514 " color: %1;"
515 " background-color: %2;"
516 " padding: 0.25em;"
519 .arg("white") // Text color
520 .arg("#2c4bc4"); // Background color. Matches capture start button.
521 // .arg(QColor(tango_butter_5).name()); // "Warning" background
523 welcome_ui_->flavorBanner->setText(flavor_);
524 welcome_ui_->flavorBanner->setStyleSheet(flavor_ss);
526 welcome_ui_->captureLabel->setStyleSheet(title_button_ss);
527 welcome_ui_->recentLabel->setStyleSheet(title_button_ss);
528 welcome_ui_->helpLabel->setStyleSheet(title_button_ss);
530 recent_files_->setStyleSheet(
531 "QListWidget::item {"
532 " padding-top: 0.2em;"
533 " padding-bottom: 0.2em;"
535 "QListWidget::item::first {"
536 " padding-top: 0;"
538 "QListWidget::item::last {"
539 " padding-bottom: 0;"
543 // The helpLinks markup includes its own <style>...</style> section.
544 // Replacing it with a stylesheet and reapplying it like we do above
545 // doesn't work, but this does.
546 QString hl_text = welcome_ui_->helpLinks->text();
547 welcome_ui_->helpLinks->clear();
548 welcome_ui_->helpLinks->setText(hl_text);
551 void WelcomePage::on_recentLabel_clicked()
553 mainApp->doTriggerMenuItem(MainApplication::FileOpenDialog);