diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 2e6c0c47bf..ea95d7d22e 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -125,6 +125,7 @@ set(WIRESHARK_QT_HEADERS stats_tree_dialog.h service_response_time_dialog.h simple_statistics_dialog.h + stock_icon_tool_button.h syntax_line_edit.h tap_parameter_dialog.h tcp_stream_dialog.h @@ -259,6 +260,7 @@ set(WIRESHARK_QT_SRC splash_overlay.cpp sparkline_delegate.cpp stock_icon.cpp + stock_icon_tool_button.cpp syntax_line_edit.cpp tap_parameter_dialog.cpp tcp_stream_dialog.cpp diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index a796e46f89..04449457f4 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -244,6 +244,7 @@ MOC_HDRS = \ sparkline_delegate.h \ splash_overlay.h \ stats_tree_dialog.h \ + stock_icon_tool_button.h \ syntax_line_edit.h \ tap_parameter_dialog.h \ tcp_stream_dialog.h \ @@ -483,6 +484,7 @@ WIRESHARK_QT_SRC = \ sparkline_delegate.cpp \ splash_overlay.cpp \ stock_icon.cpp \ + stock_icon_tool_button.cpp \ syntax_line_edit.cpp \ tap_parameter_dialog.cpp \ tcp_stream_dialog.cpp \ diff --git a/ui/qt/Wireshark.pro b/ui/qt/Wireshark.pro index 5ecc77fa67..56513f6233 100644 --- a/ui/qt/Wireshark.pro +++ b/ui/qt/Wireshark.pro @@ -641,6 +641,7 @@ HEADERS += \ sequence_dialog.h \ simple_dialog.h \ sparkline_delegate.h \ + stock_icon_tool_button.h \ syntax_line_edit.h \ tap_parameter_dialog.h \ time_shift_dialog.h \ @@ -760,6 +761,7 @@ SOURCES += \ splash_overlay.cpp \ stats_tree_dialog.cpp \ stock_icon.cpp \ + stock_icon_tool_button.cpp \ syntax_line_edit.cpp \ tap_parameter_dialog.cpp \ tcp_stream_dialog.cpp \ diff --git a/ui/qt/capture_filter_edit.cpp b/ui/qt/capture_filter_edit.cpp index bfd7c8b747..46f67d084a 100644 --- a/ui/qt/capture_filter_edit.cpp +++ b/ui/qt/capture_filter_edit.cpp @@ -33,6 +33,7 @@ #include "capture_filter_edit.h" #include "capture_filter_syntax_worker.h" +#include "stock_icon_tool_button.h" #include "wireshark_application.h" #include @@ -124,90 +125,54 @@ CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) : setPlaceholderText(placeholder_text_); #endif - // DFCombo - // Bookmark (star) - // DispalyFilterEdit - // Clear button - // Apply (right arrow) + Cancel (x) + Reload (arrowed circle) - // Combo drop-down - - // XXX - Move bookmark and apply buttons to the toolbar a la Firefox, Chrome & Safari? - // XXX - Use native buttons on OS X? + // These are fully implemented in DisplayFilterEdit but not here. if (!plain_) { - bookmark_button_ = new QToolButton(this); + bookmark_button_ = new StockIconToolButton(this, "x-filter-bookmark"); bookmark_button_->setCursor(Qt::ArrowCursor); - bookmark_button_->setStyleSheet(QString( - "QToolButton { /* all types of tool button */" - " border 0 0 0 0;" -#ifdef Q_OS_MAC - " border-right: %1px solid gray;" -#else - " border-right: %1px solid palette(shadow);" -#endif - " border-top-left-radius: 3px;" - " border-bottom-left-radius: 3px;" - " padding-left: 1px;" - " image: url(:/dfilter/dfilter_bookmark_normal.png) center;" - "}" - - "QToolButton:hover {" - " image: url(:/dfilter/dfilter_bookmark_hover.png) center;" - "}" - "QToolButton:pressed {" - " image: url(:/dfilter/dfilter_bookmark_pressed.png) center;" - "}" - "QToolButton:disabled {" - " image: url(:/dfilter/dfilter_bookmark_disabled.png) center;" - "}" - ).arg(plain_ ? 0 : 1) + bookmark_button_->setPopupMode(QToolButton::InstantPopup); + bookmark_button_->setToolTip(tr("Manage saved bookmarks.")); + bookmark_button_->setIconSize(QSize(14, 14)); + bookmark_button_->setStyleSheet( + "QToolButton {" + " border: none;" + " background: transparent;" // Disables platform style on Windows. + " padding: 0 0 0 0;" + "}" + "QToolButton::menu-indicator { image: none; }" ); connect(bookmark_button_, SIGNAL(clicked()), this, SLOT(bookmarkClicked())); } if (!plain_) { - clear_button_ = new QToolButton(this); + clear_button_ = new StockIconToolButton(this, "x-filter-clear"); clear_button_->setCursor(Qt::ArrowCursor); + clear_button_->setToolTip(QString()); + clear_button_->setIconSize(QSize(14, 14)); clear_button_->setStyleSheet( - "QToolButton {" - " image: url(:/dfilter/dfilter_erase_normal.png) center;" - " border: none;" - " width: 16px;" - "}" - "QToolButton:hover {" - " image: url(:/dfilter/dfilter_erase_active.png) center;" - "}" - "QToolButton:pressed {" - " image: url(:/dfilter/dfilter_erase_selected.png) center;" - "}" - ); - clear_button_->hide(); + "QToolButton {" + " border: none;" + " background: transparent;" // Disables platform style on Windows. + " padding: 0 0 0 0;" + " margin-left: 1px;" + "}" + ); connect(clear_button_, SIGNAL(clicked()), this, SLOT(clear())); } connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(checkFilter(const QString&))); if (!plain_) { - apply_button_ = new QToolButton(this); + apply_button_ = new StockIconToolButton(this, "x-filter-apply"); apply_button_->setCursor(Qt::ArrowCursor); apply_button_->setEnabled(false); + apply_button_->setToolTip(tr("Apply this filter string to the display.")); + apply_button_->setIconSize(QSize(24, 14)); apply_button_->setStyleSheet( - "QToolButton { /* all types of tool button */" - " border 0 0 0 0;" - " border-top-right-radius: 3px;" - " border-bottom-right-radius: 3px;" - " padding-right: 1px;" - " image: url(:/dfilter/dfilter_apply_normal.png) center;" - "}" - - "QToolButton:hover {" - " image: url(:/dfilter/dfilter_apply_hover.png) center;" - "}" - "QToolButton:pressed {" - " image: url(:/dfilter/dfilter_apply_pressed.png) center;" - "}" - "QToolButton:disabled {" - " image: url(:/dfilter/dfilter_apply_disabled.png) center;" + "QToolButton {" + " border: none;" + " background: transparent;" // Disables platform style on Windows. + " padding: 0 0 0 0;" "}" ); connect(apply_button_, SIGNAL(clicked()), this, SLOT(applyCaptureFilter())); @@ -244,6 +209,8 @@ CaptureFilterEdit::CaptureFilterEdit(QWidget *parent, bool plain) : this, SLOT(setFilterSyntaxState(QString,bool,QString))); connect(syntax_thread, SIGNAL(finished()), syntax_worker_, SLOT(deleteLater())); syntax_thread->start(); + + checkFilter(); } #if QT_VERSION < QT_VERSION_CHECK(4, 7, 0) @@ -285,14 +252,17 @@ void CaptureFilterEdit::resizeEvent(QResizeEvent *) if (clear_button_) { clear_button_->move(contentsRect().right() - frameWidth - cbsz.width() - apsz.width(), contentsRect().top()); + clear_button_->setMinimumHeight(contentsRect().height()); clear_button_->setMaximumHeight(contentsRect().height()); } if (apply_button_) { apply_button_->move(contentsRect().right() - frameWidth - apsz.width(), contentsRect().top()); + apply_button_->setMinimumHeight(contentsRect().height()); apply_button_->setMaximumHeight(contentsRect().height()); } if (bookmark_button_) { + bookmark_button_->setMinimumHeight(contentsRect().height()); bookmark_button_->setMaximumHeight(contentsRect().height()); } } diff --git a/ui/qt/capture_filter_edit.h b/ui/qt/capture_filter_edit.h index c6372db408..a0e83e2eff 100644 --- a/ui/qt/capture_filter_edit.h +++ b/ui/qt/capture_filter_edit.h @@ -27,6 +27,7 @@ #include "syntax_line_edit.h" class CaptureFilterSyntaxWorker; +class StockIconToolButton; class CaptureFilterEdit : public SyntaxLineEdit { @@ -56,9 +57,9 @@ private: bool plain_; bool field_name_only_; QString placeholder_text_; - QToolButton *bookmark_button_; - QToolButton *clear_button_; - QToolButton *apply_button_; + StockIconToolButton *bookmark_button_; + StockIconToolButton *clear_button_; + StockIconToolButton *apply_button_; CaptureFilterSyntaxWorker *syntax_worker_; void buildCompletionList(const QString& primitive_word); diff --git a/ui/qt/display_filter_edit.cpp b/ui/qt/display_filter_edit.cpp index ff2c6df435..863729f7e3 100644 --- a/ui/qt/display_filter_edit.cpp +++ b/ui/qt/display_filter_edit.cpp @@ -31,23 +31,17 @@ #include "display_filter_edit.h" #include "filter_dialog.h" -#include "stock_icon.h" +#include "stock_icon_tool_button.h" #include "syntax_line_edit.h" #include #include -#include #include #include #include -#include -#include #include -#include #include #include -#include -#include #include "ui/utf8_entities.h" @@ -57,94 +51,6 @@ // - Add a separator or otherwise distinguish between recent items and fields // in the completion dropdown. -// We want nice icons that render correctly, and that are responsive -// when the user hovers and clicks them. -// Using setIcon renders correctly on normal and retina displays. It is -// not completely responsive, particularly on OS X. -// Calling setStyleSheet is responsive, but does not render correctly on -// retina displays: https://bugreports.qt.io/browse/QTBUG-36825 -// Subclass QToolButton, which lets us catch events and set icons as needed. - -class StockIconToolButton : public QToolButton -{ -public: - explicit StockIconToolButton(QWidget * parent = 0, QString stock_icon_name = QString()) : - QToolButton(parent), - leave_timer_(0) - { - if (!stock_icon_name.isEmpty()) { - setStockIcon(stock_icon_name); - } - } - - void setIconMode(QIcon::Mode mode = QIcon::Normal) { - QIcon mode_icon; - QList states = QList() << QIcon::Off << QIcon::On; - foreach (QIcon::State state, states) { - foreach (QSize size, base_icon_.availableSizes(mode, state)) { - mode_icon.addPixmap(base_icon_.pixmap(size, mode, state), mode, state); - } - } - setIcon(mode_icon); - } - - void setStockIcon(QString icon_name) { - base_icon_ = StockIcon(icon_name); - setIconMode(); - } - -protected: - virtual bool event(QEvent *event) { - switch (event->type()) { - case QEvent::Enter: - if (isEnabled()) { - setIconMode(QIcon::Active); - if (leave_timer_ > 0) killTimer(leave_timer_); - leave_timer_ = startTimer(leave_interval_); - } - break; - case QEvent::MouseButtonPress: - if (isEnabled()) { - setIconMode(QIcon::Selected); - } - break; - case QEvent::Leave: - if (leave_timer_ > 0) killTimer(leave_timer_); - leave_timer_ = 0; - case QEvent::MouseButtonRelease: - setIconMode(); - break; - case QEvent::Timer: - { - // We can lose QEvent::Leave, QEvent::HoverLeave and underMouse() - // if a tooltip appears, at least OS X: - // https://bugreports.qt.io/browse/QTBUG-46379 - // Work around the issue by periodically checking the mouse - // position and scheduling a fake leave event when the mouse - // moves away. - QTimerEvent *te = (QTimerEvent *) event; - bool under_mouse = rect().contains(mapFromGlobal(QCursor::pos())); - if (te->timerId() == leave_timer_ && !under_mouse) { - killTimer(leave_timer_); - leave_timer_ = 0; - QMouseEvent *me = new QMouseEvent(QEvent::Leave, mapFromGlobal(QCursor::pos()), Qt::NoButton, Qt::NoButton, Qt::NoModifier); - QApplication::postEvent(this, me); - } - break; - } - default: - break; - } - - return QToolButton::event(event); - } - -private: - QIcon base_icon_; - int leave_timer_; - static const int leave_interval_ = 500; // ms -}; - #if defined(Q_OS_MAC) && 0 // http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSImage_Class/Reference/Reference.html // http://www.virtualbox.org/svn/vbox/trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaSpecialControls.mm diff --git a/ui/qt/progress_frame.cpp b/ui/qt/progress_frame.cpp index 8c9576ae0a..43d9b3b231 100644 --- a/ui/qt/progress_frame.cpp +++ b/ui/qt/progress_frame.cpp @@ -31,7 +31,7 @@ #include #include -#include "stock_icon.h" +#include "stock_icon_tool_button.h" #include "wireshark_application.h" // To do: @@ -126,26 +126,20 @@ ProgressFrame::ProgressFrame(QWidget *parent) : " background: transparent;" "}")); - int one_em = fontMetrics().height(); - ui->pushButton->setIconSize(QSize(one_em, one_em)); - ui->pushButton->setStyleSheet(QString( - "QPushButton {" - " image: url(:/dfilter/dfilter_erase_normal.png) center;" + ui->stopButton->setStockIcon("x-filter-clear"); + ui->stopButton->setIconSize(QSize(14, 14)); + ui->stopButton->setStyleSheet( + "QToolButton {" + " border: none;" + " background: transparent;" // Disables platform style on Windows. + " padding: 0px;" + " margin: 0px;" " min-height: 0.8em;" " max-height: 1em;" " min-width: 0.8em;" " max-width: 1em;" - " border: 0px;" - " padding: 0px;" - " margin: 0px;" - " background: transparent;" "}" - "QPushButton:hover {" - " image: url(:/dfilter/dfilter_erase_active.png) center;" - "}" - "QPushButton:pressed {" - " image: url(:/dfilter/dfilter_erase_selected.png) center;" - "}")); + ); connect(this, SIGNAL(showRequested(bool,bool,gboolean*)), this, SLOT(show(bool,bool,gboolean*))); hide(); @@ -267,7 +261,7 @@ void ProgressFrame::hide() #endif } -void ProgressFrame::on_pushButton_clicked() +void ProgressFrame::on_stopButton_clicked() { emit stopLoading(); } @@ -279,9 +273,9 @@ void ProgressFrame::show(bool animate, bool terminate_is_stop, gboolean *stop_fl stop_flag_ = stop_flag; if (stop_flag) { - ui->pushButton->show(); + ui->stopButton->show(); } else { - ui->pushButton->hide(); + ui->stopButton->hide(); } #if !defined(Q_OS_MAC) || QT_VERSION > QT_VERSION_CHECK(5, 0, 0) diff --git a/ui/qt/progress_frame.h b/ui/qt/progress_frame.h index 032176809f..997f5434f1 100644 --- a/ui/qt/progress_frame.h +++ b/ui/qt/progress_frame.h @@ -71,8 +71,8 @@ signals: void setHidden(); void stopLoading(); -#if !defined(Q_OS_MAC) || QT_VERSION > QT_VERSION_CHECK(5, 0, 0) protected: +#if !defined(Q_OS_MAC) || QT_VERSION > QT_VERSION_CHECK(5, 0, 0) void timerEvent(QTimerEvent *event); #endif @@ -93,7 +93,7 @@ private: #endif private slots: - void on_pushButton_clicked(); + void on_stopButton_clicked(); void show(bool animate, bool terminate_is_stop, gboolean *stop_flag); void setMaximumValue(int value); diff --git a/ui/qt/progress_frame.ui b/ui/qt/progress_frame.ui index 2ea1d49479..f82e0d4ea6 100644 --- a/ui/qt/progress_frame.ui +++ b/ui/qt/progress_frame.ui @@ -40,7 +40,7 @@ - + @@ -50,13 +50,17 @@ 12 - - true - + + + StockIconToolButton + QToolButton +
stock_icon_tool_button.h
+
+
diff --git a/ui/qt/stock_icon_tool_button.cpp b/ui/qt/stock_icon_tool_button.cpp new file mode 100644 index 0000000000..fe0a6e7e39 --- /dev/null +++ b/ui/qt/stock_icon_tool_button.cpp @@ -0,0 +1,123 @@ +/* stock_icon_tool_button.cpp + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "stock_icon_tool_button.h" + +#include "stock_icon.h" + +#include +#include +#include +#include + +// We want nice icons that render correctly, and that are responsive +// when the user hovers and clicks them. +// Using setIcon renders correctly on normal and retina displays. It is +// not completely responsive, particularly on OS X. +// Calling setStyleSheet is responsive, but does not render correctly on +// retina displays: https://bugreports.qt.io/browse/QTBUG-36825 +// Subclass QToolButton, which lets us catch events and set icons as needed. + +StockIconToolButton::StockIconToolButton(QWidget * parent, QString stock_icon_name) : + QToolButton(parent), + leave_timer_(0) +{ + if (!stock_icon_name.isEmpty()) { + setStockIcon(stock_icon_name); + } +} + +void StockIconToolButton::setIconMode(QIcon::Mode mode) +{ + QIcon mode_icon; + QList states = QList() << QIcon::Off << QIcon::On; + foreach (QIcon::State state, states) { + foreach (QSize size, base_icon_.availableSizes(mode, state)) { + mode_icon.addPixmap(base_icon_.pixmap(size, mode, state), mode, state); + } + } + setIcon(mode_icon); +} + +void StockIconToolButton::setStockIcon(QString icon_name) +{ + base_icon_ = StockIcon(icon_name); + setIconMode(); +} + +bool StockIconToolButton::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::Enter: + if (isEnabled()) { + setIconMode(QIcon::Active); + if (leave_timer_ > 0) killTimer(leave_timer_); + leave_timer_ = startTimer(leave_interval_); + } + break; + case QEvent::MouseButtonPress: + if (isEnabled()) { + setIconMode(QIcon::Selected); + } + break; + case QEvent::Leave: + if (leave_timer_ > 0) killTimer(leave_timer_); + leave_timer_ = 0; + case QEvent::MouseButtonRelease: + setIconMode(); + break; + case QEvent::Timer: + { + // We can lose QEvent::Leave, QEvent::HoverLeave and underMouse() + // on OS X if a tooltip appears: + // https://bugreports.qt.io/browse/QTBUG-46379 + // Work around the issue by periodically checking the mouse + // position and scheduling a fake leave event when the mouse + // moves away. + QTimerEvent *te = (QTimerEvent *) event; + bool under_mouse = rect().contains(mapFromGlobal(QCursor::pos())); + if (te->timerId() == leave_timer_ && !under_mouse) { + killTimer(leave_timer_); + leave_timer_ = 0; + QMouseEvent *me = new QMouseEvent(QEvent::Leave, mapFromGlobal(QCursor::pos()), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + QApplication::postEvent(this, me); + } + break; + } + default: + break; + } + + return QToolButton::event(event); +} + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/ui/qt/stock_icon_tool_button.h b/ui/qt/stock_icon_tool_button.h new file mode 100644 index 0000000000..49b8742596 --- /dev/null +++ b/ui/qt/stock_icon_tool_button.h @@ -0,0 +1,58 @@ +/* stock_icon_tool_button.h + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef STOCKICONTOOLBUTTON_H +#define STOCKICONTOOLBUTTON_H + +#include + +class StockIconToolButton : public QToolButton +{ + Q_OBJECT +public: + explicit StockIconToolButton(QWidget * parent = 0, QString stock_icon_name = QString()); + + void setIconMode(QIcon::Mode mode = QIcon::Normal); + void setStockIcon(QString icon_name); + +protected: + virtual bool event(QEvent *event); + +private: + QIcon base_icon_; + int leave_timer_; + static const int leave_interval_ = 500; // ms +}; + +#endif // STOCKICONTOOLBUTTON_H + +/* + * Editor modelines + * + * Local Variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * ex: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */