diff --git a/ui/qt/interface_tree.cpp b/ui/qt/interface_tree.cpp index 52819d8c12..c22c1a247d 100644 --- a/ui/qt/interface_tree.cpp +++ b/ui/qt/interface_tree.cpp @@ -27,8 +27,6 @@ #include "ui/iface_lists.h" #include "ui/utf8_entities.h" -#include "epan/prefs.h" - #include "sparkline_delegate.h" #include "wireshark_application.h" @@ -49,6 +47,7 @@ InterfaceTree::InterfaceTree(QWidget *parent) : setRootIsDecorated(false); setUniformRowHeights(true); setColumnCount(2); + setSelectionMode(QAbstractItemView::ExtendedSelection); setAccessibleName(tr("Welcome screen list")); setItemDelegateForColumn(1, new SparkLineDelegate()); @@ -59,7 +58,8 @@ InterfaceTree::InterfaceTree(QWidget *parent) : addTopLevelItem(ti); resizeColumnToContents(0); - connect (wsApp, SIGNAL(appInitialized()), this, SLOT(getInterfaceList())); + connect(wsApp, SIGNAL(appInitialized()), this, SLOT(getInterfaceList())); + connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(updateSelectedInterfaces())); } InterfaceTree::~InterfaceTree() { @@ -120,30 +120,30 @@ void InterfaceTree::getInterfaceList() // XXX Do we need to check for this? capture_interface_list returns an error if the length is 0. if (g_list_length(if_list) > 0) { - if_info_t *if_info; - GList *curr; + interface_t device; setDisabled(false); - for (curr = g_list_first(if_list); curr; curr = g_list_next(curr)) { + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { QList *points; - QVariant v; - if_info = (if_info_t *) curr->data; + device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + /* Continue if capture device is hidden */ - if (prefs_is_capture_device_hidden(if_info->name)) { + if (device.hidden) { continue; } QTreeWidgetItem *ti = new QTreeWidgetItem(); - // XXX Using if_info->name is amazingly ugly under Windows but it's needed for - // statistics updates -// ti->setText(0, QString().fromUtf8(if_info->vendor_description ? if_info->vendor_description : if_info->name)); - ti->setText(0, QString().fromUtf8(if_info->name)); + ti->setText(0, QString().fromUtf8(device.display_name)); + ti->setData(0, Qt::UserRole, QString(device.name)); points = new QList(); - v.setValue(points); - ti->setData(1, Qt::UserRole, v); + ti->setData(1, Qt::UserRole, qVariantFromValue(points)); addTopLevelItem(ti); + // XXX Add other device information resizeColumnToContents(1); + if (device.selected) { + ti->setSelected(true); + } } } free_interface_list(if_list); @@ -171,11 +171,11 @@ void InterfaceTree::updateStatistics(void) { QTreeWidgetItemIterator iter(this); while (*iter) { QList *points; - QVariant v; for (if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { device = g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx); - if ((*iter)->text(0).compare(QString().fromUtf8(device.name)) || device.hidden || device.type == IF_PIPE) + QString device_name = (*iter)->data(0, Qt::UserRole).value(); + if (device_name.compare(device.name) || device.hidden || device.type == IF_PIPE) continue; diff = 0; @@ -186,8 +186,7 @@ void InterfaceTree::updateStatistics(void) { device.last_packets = stats.ps_recv; } - v = (*iter)->data(1, Qt::UserRole); - points = v.value *>(); + points = (*iter)->data(1, Qt::UserRole).value *>(); points->append(diff); update(indexFromItem((*iter), 1)); global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, if_idx); @@ -197,6 +196,41 @@ void InterfaceTree::updateStatistics(void) { } } +void InterfaceTree::updateSelectedInterfaces() +{ + QTreeWidgetItemIterator iter(this); + + global_capture_opts.num_selected = 0; + + while (*iter) { + for (guint i = 0; i < global_capture_opts.all_ifaces->len; i++) { + QString device_name = (*iter)->data(0, Qt::UserRole).value(); + interface_t device = g_array_index(global_capture_opts.all_ifaces, interface_t, i); + if (device_name.compare(QString().fromUtf8(device.name)) == 0) { + if (!device.locked) { + if ((*iter)->isSelected()) { + device.selected = TRUE; + global_capture_opts.num_selected++; + } else { + device.selected = FALSE; + } + device.locked = TRUE; + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + + emit interfaceUpdated(device.name, device.selected); + + device.locked = FALSE; + global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i); + g_array_insert_val(global_capture_opts.all_ifaces, i, device); + } + break; + } + } + iter++; + } +} + /* * Editor modelines * diff --git a/ui/qt/interface_tree.h b/ui/qt/interface_tree.h index 4840b1b15e..cb3eec39a4 100644 --- a/ui/qt/interface_tree.h +++ b/ui/qt/interface_tree.h @@ -53,12 +53,17 @@ private: QTimer *stat_timer_; signals: + void interfaceUpdated(const char *device_name, bool selected); public slots: + // add_interface_to_list + // change_interface_selection + // change_interface_selection_for_all private slots: void getInterfaceList(); void updateStatistics(void); + void updateSelectedInterfaces(); }; #endif // INTERFACE_TREE_H diff --git a/ui/qt/main_status_bar.cpp b/ui/qt/main_status_bar.cpp index af6f823a72..e9e458ba6e 100644 --- a/ui/qt/main_status_bar.cpp +++ b/ui/qt/main_status_bar.cpp @@ -27,10 +27,6 @@ #include "main_status_bar.h" -#include "wireshark_application.h" - -#include "globals.h" - #include "epan/expert.h" #include "ui/main_statusbar.h" @@ -42,9 +38,9 @@ #include "tango_colors.h" #ifdef HAVE_LIBPCAP -#define DEF_READY_MESSAGE QObject::tr("Ready to load or capture") +#define DEF_READY_MESSAGE tr("Ready to load or capture") #else -#define DEF_READY_MESSAGE QObject::tr("Ready to load file") +#define DEF_READY_MESSAGE tr("Ready to load file") #endif // XXX - The GTK+ code assigns priorities to these and pushes/pops accordingly. @@ -89,43 +85,12 @@ statusbar_push_temporary_msg(const gchar *msg_format, ...) void packets_bar_update(void) { - QString packetsStr = QString(""); - - if (!cur_main_status_bar_) return; - - cur_main_status_bar_->popPacketStatus(); - - /* Do we have any packets? */ - if (cfile.count) { - packetsStr.append(QString(QObject::tr("Packets: %1 %4 Displayed: %2 %4 Marked: %3")) - .arg(cfile.count) - .arg(cfile.displayed_count) - .arg(cfile.marked_count) - .arg(UTF8_MIDDLE_DOT)); - if(cfile.drops_known) { - packetsStr.append(QString(QObject::tr(" %1 Dropped: %2"))).arg(UTF8_MIDDLE_DOT).arg(cfile.drops); - } - if(cfile.ignored_count > 0) { - packetsStr.append(QString(QObject::tr(" %1 Ignored: %2")).arg(UTF8_MIDDLE_DOT).arg(cfile.ignored_count)); - } - if(!cfile.is_tempfile) { - /* Loading an existing file */ - gulong computed_elapsed = cf_get_computed_elapsed(); - packetsStr.append(QString(QObject::tr(" %1 Load time: %2:%3.%4")) - .arg(UTF8_MIDDLE_DOT) - .arg(computed_elapsed/60000) - .arg(computed_elapsed%60000/1000) - .arg(computed_elapsed%1000)); - } - } else { - packetsStr.append(QObject::tr("No Packets")); - } - - cur_main_status_bar_->pushPacketStatus(packetsStr); + // XXX Implement } MainStatusBar::MainStatusBar(QWidget *parent) : - QStatusBar(parent) + QStatusBar(parent), + cap_file_(NULL) { QSplitter *splitter = new QSplitter(this); QString ready_msg(DEF_READY_MESSAGE); @@ -178,6 +143,8 @@ MainStatusBar::MainStatusBar(QWidget *parent) : connect(wsApp, SIGNAL(appInitialized()), splitter, SLOT(show())); connect(&info_status_, SIGNAL(toggleTemporaryFlash(bool)), this, SLOT(toggleBackground(bool))); + connect(wsApp, SIGNAL(captureCaptureUpdateContinue(capture_options*)), + this, SLOT(updateCaptureStatistics(capture_options*))); } void MainStatusBar::showExpert() { @@ -224,6 +191,11 @@ void MainStatusBar::expertUpdate() { expert_status_.show(); } +void MainStatusBar::setCaptureFile(capture_file *cf) +{ + cap_file_ = cf; +} + void MainStatusBar::pushTemporaryStatus(QString &message) { info_status_.pushText(message, STATUS_CTX_TEMPORARY); } @@ -292,6 +264,42 @@ void MainStatusBar::toggleBackground(bool enabled) } } +void MainStatusBar::updateCaptureStatistics(capture_options *capture_opts) +{ + QString packets_str; + + if (capture_opts->cf != cap_file_ || !cap_file_) return; + + /* Do we have any packets? */ + if (cap_file_->count) { + packets_str.append(QString(tr("Packets: %1 %4 Displayed: %2 %4 Marked: %3")) + .arg(cap_file_->count) + .arg(cap_file_->displayed_count) + .arg(cap_file_->marked_count) + .arg(UTF8_MIDDLE_DOT)); + if(cap_file_->drops_known) { + packets_str.append(QString(tr(" %1 Dropped: %2")).arg(UTF8_MIDDLE_DOT).arg(cap_file_->drops)); + } + if(cap_file_->ignored_count > 0) { + packets_str.append(QString(tr(" %1 Ignored: %2")).arg(UTF8_MIDDLE_DOT).arg(cap_file_->ignored_count)); + } + if(!cap_file_->is_tempfile) { + /* Loading an existing file */ + gulong computed_elapsed = cf_get_computed_elapsed(); + packets_str.append(QString(tr(" %1 Load time: %2:%3.%4")) + .arg(UTF8_MIDDLE_DOT) + .arg(computed_elapsed/60000) + .arg(computed_elapsed%60000/1000) + .arg(computed_elapsed%1000)); + } + } else { + packets_str.append(tr("No Packets")); + } + + popPacketStatus(); + pushPacketStatus(packets_str); +} + /* * Editor modelines * diff --git a/ui/qt/main_status_bar.h b/ui/qt/main_status_bar.h index 164d89b430..06c75cd1ea 100644 --- a/ui/qt/main_status_bar.h +++ b/ui/qt/main_status_bar.h @@ -24,12 +24,15 @@ #ifndef MAIN_STATUS_BAR_H #define MAIN_STATUS_BAR_H +#include "wireshark_application.h" #include "label_stack.h" #include "progress_bar.h" #include #include +#include "cfile.h" + class MainStatusBar : public QStatusBar { Q_OBJECT @@ -44,12 +47,14 @@ private: ProgressBar progress_bar_; LabelStack packet_status_; LabelStack profile_status_; + capture_file *cap_file_; void expertUpdate(); signals: public slots: + void setCaptureFile(capture_file *cf); void pushTemporaryStatus(QString &message); void popTemporaryStatus(); void pushFileStatus(QString &message); @@ -65,6 +70,7 @@ public slots: private slots: void toggleBackground(bool enabled); + void updateCaptureStatistics(capture_options * capture_opts); }; #endif // MAIN_STATUS_BAR_H diff --git a/ui/qt/main_welcome.cpp b/ui/qt/main_welcome.cpp index 1a105c7586..679a849707 100644 --- a/ui/qt/main_welcome.cpp +++ b/ui/qt/main_welcome.cpp @@ -51,15 +51,12 @@ MainWelcome::MainWelcome(QWidget *parent) : // QGridLayout *grid = new QGridLayout(this); // QVBoxLayout *column; // QLabel *heading; -#ifdef Q_WS_MAC - InterfaceTree *iface_tree; -#endif welcome_ui_->setupUi(this); + + welcome_ui_->mainWelcomeBanner->setText("Wireshark
" VERSION ""); + task_list_ = welcome_ui_->taskList; -#ifdef Q_WS_MAC - iface_tree = welcome_ui_->interfaceTree; -#endif recent_files_ = welcome_ui_->recentList; setStyleSheet(QString( @@ -103,7 +100,7 @@ MainWelcome::MainWelcome(QWidget *parent) : #ifdef Q_WS_MAC recent_files_->setAttribute(Qt::WA_MacShowFocusRect, false); welcome_ui_->taskList->setAttribute(Qt::WA_MacShowFocusRect, false); - iface_tree->setAttribute(Qt::WA_MacShowFocusRect, false); + welcome_ui_->interfaceTree->setAttribute(Qt::WA_MacShowFocusRect, false); #endif task_list_->setStyleSheet( @@ -138,6 +135,8 @@ MainWelcome::MainWelcome(QWidget *parent) : connect(wsApp, SIGNAL(updateRecentItemStatus(const QString &, qint64, bool)), this, SLOT(updateRecentFiles())); connect(wsApp, SIGNAL(appInitialized()), this, SLOT(destroySplashOverlay())); connect(task_list_, SIGNAL(itemSelectionChanged()), this, SLOT(showTask())); + connect(welcome_ui_->interfaceTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), + this, SLOT(interfaceDoubleClicked(QTreeWidgetItem*,int))); connect(recent_files_, SIGNAL(itemActivated(QListWidgetItem *)), this, SLOT(openRecentItem(QListWidgetItem *))); updateRecentFiles(); @@ -166,6 +165,15 @@ void MainWelcome::showTask() { welcome_ui_->taskStack->setCurrentIndex(task_list_->currentRow()); } +void MainWelcome::interfaceDoubleClicked(QTreeWidgetItem *item, int column) +{ + Q_UNUSED(column); + + if (item) { + emit startCapture(); + } +} + void MainWelcome::updateRecentFiles() { QString itemLabel; QListWidgetItem *rfItem; diff --git a/ui/qt/main_welcome.h b/ui/qt/main_welcome.h index 6b61734c83..9fe7f07c8d 100644 --- a/ui/qt/main_welcome.h +++ b/ui/qt/main_welcome.h @@ -26,6 +26,7 @@ #include #include +#include #include "splash_overlay.h" @@ -54,14 +55,15 @@ private: signals: + void startCapture(); void recentFileActivated(QString& cfile); private slots: void destroySplashOverlay(); void showTask(); + void interfaceDoubleClicked(QTreeWidgetItem *item, int column); void updateRecentFiles(); void openRecentItem(QListWidgetItem *item); - }; #endif // MAIN_WELCOME_H diff --git a/ui/qt/main_welcome.ui b/ui/qt/main_welcome.ui index e9eddf51b0..d484f8051b 100644 --- a/ui/qt/main_welcome.ui +++ b/ui/qt/main_welcome.ui @@ -133,7 +133,7 @@ more about Wireshark - <html><head/><body><p>Wireshark</p></body></html> + diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index 0d577474e3..3ef16d4e8b 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -90,6 +90,7 @@ MainWindow::MainWindow(QWidget *parent) : setMenusForSelectedTreeRow(); setForCaptureInProgress(false); setMenusForFileSet(false); + interfaceSelectionChanged(); connect(wsApp, SIGNAL(updateRecentItemStatus(const QString &, qint64, bool)), this, SLOT(updateRecentFiles())); updateRecentFiles(); @@ -181,9 +182,13 @@ MainWindow::MainWindow(QWidget *parent) : connect(wsApp, SIGNAL(captureFileClosed(const capture_file*)), this, SLOT(captureFileClosed(const capture_file*))); + connect(main_welcome_, SIGNAL(startCapture()), + this, SLOT(startCapture())); connect(main_welcome_, SIGNAL(recentFileActivated(QString&)), this, SLOT(openCaptureFile(QString&))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + main_ui_->statusBar, SLOT(setCaptureFile(capture_file*))); connect(this, SIGNAL(setCaptureFile(capture_file*)), packet_list_, SLOT(setCaptureFile(capture_file*))); connect(this, SIGNAL(setCaptureFile(capture_file*)), @@ -214,6 +219,11 @@ MainWindow::MainWindow(QWidget *parent) : connect(&file_set_dialog_, SIGNAL(fileSetOpenCaptureFile(QString&)), this, SLOT(openCaptureFile(QString&))); + QTreeWidget *iface_tree = findChild("interfaceTree"); + if (iface_tree) { + connect(iface_tree, SIGNAL(itemSelectionChanged()), + this, SLOT(interfaceSelectionChanged())); + } main_ui_->mainStack->setCurrentWidget(main_welcome_); } @@ -443,8 +453,10 @@ void MainWindow::mergeCaptureFile() cf_close(cap_file_); /* Try to open the merged capture file. */ + cfile.window = this; if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) { /* We couldn't open it; fail. */ + cfile.window = NULL; if (rfcode != NULL) dfilter_free(rfcode); g_free(tmpname); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index ebe7626925..ea8bc74893 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -151,6 +151,7 @@ private slots: void updateRecentFiles(); void recentActionTriggered(); void setMenusForSelectedTreeRow(field_info *fi = NULL); + void interfaceSelectionChanged(); void on_actionFileOpen_triggered(); void on_actionFileMerge_triggered(); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 5b6dd9760a..5400a31252 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -328,8 +328,7 @@ void MainWindow::startCapture() { guint i; /* did the user ever select a capture interface before? */ - if(global_capture_opts.num_selected == 0 && - ((prefs.capture_device == NULL) || (*prefs.capture_device != '\0'))) { + if(global_capture_opts.num_selected == 0) { QString msg = QString("No interface selected"); main_ui_->statusBar->pushTemporaryStatus(msg); return; @@ -349,6 +348,7 @@ void MainWindow::startCapture() { this capture. */ collect_ifaces(&global_capture_opts); + cfile.window = this; if (capture_start(&global_capture_opts)) { /* The capture succeeded, which means the capture filter syntax is valid; add this capture filter to the recent capture filter list. */ @@ -358,6 +358,8 @@ void MainWindow::startCapture() { // cfilter_combo_add_recent(interface_opts.cfilter); } } + } else { + cfile.window = NULL; } } @@ -617,6 +619,15 @@ void MainWindow::setMenusForSelectedTreeRow(field_info *fi) { } } +void MainWindow::interfaceSelectionChanged() +{ + if (global_capture_opts.num_selected > 0) { + main_ui_->actionStartCapture->setEnabled(true); + } else { + main_ui_->actionStartCapture->setEnabled(false); + } +} + // File Menu @@ -970,12 +981,8 @@ void MainWindow::on_actionStartCapture_triggered() main_ui_->mainStack->setCurrentWidget(packet_splitter_); if (global_capture_opts.num_selected == 0) { - QMessageBox::critical( - this, - tr("No Interface Selected"), - tr("You didn't specify an interface on which to capture packets."), - QMessageBox::Ok - ); + QString err_msg = tr("No Interface Selected"); + main_ui_->statusBar->pushTemporaryStatus(err_msg); return; } diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp index 235b5dea13..6fe91d36ab 100644 --- a/ui/qt/wireshark_application.cpp +++ b/ui/qt/wireshark_application.cpp @@ -182,7 +182,8 @@ void WiresharkApplication::captureCallback(int event, capture_options * capture_ emit captureCaptureUpdateStarted(capture_opts); break; case(capture_cb_capture_update_continue): - /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/ + g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue"); + emit captureCaptureUpdateContinue(capture_opts); break; case(capture_cb_capture_update_finished): g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished"); diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h index df77715bbf..a050e30270 100644 --- a/ui/qt/wireshark_application.h +++ b/ui/qt/wireshark_application.h @@ -91,6 +91,7 @@ signals: // XXX It might make more sense to move these to main.cpp or main_window.cpp or their own class. void captureCapturePrepared(capture_options *capture_opts); void captureCaptureUpdateStarted(capture_options *capture_opts); + void captureCaptureUpdateContinue(capture_options *capture_opts); void captureCaptureUpdateFinished(capture_options *capture_opts); void captureCaptureFixedStarted(capture_options *capture_opts); void captureCaptureFixedFinished(capture_options *capture_opts);