Qt: Allow action buttons to be left-aligned

Buttons can be left-aligned in the display filter edit bar, by selecting
the corresponding option from the context menu

Bug: 14123
Change-Id: I18b48bb0ea43a598b2e309dcad9210463be06414
Reviewed-on: https://code.wireshark.org/review/34980
Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
Roland Knall 2019-11-05 11:41:18 +00:00
parent a218460e22
commit a802000a2e
5 changed files with 143 additions and 87 deletions

View File

@ -39,6 +39,7 @@ since version 3.1.0:
* The Windows packages are now built using Microsoft Visual Studio 2019. * The Windows packages are now built using Microsoft Visual Studio 2019.
* IOGraph automatically adds a graph for the selected display filter if no * IOGraph automatically adds a graph for the selected display filter if no
previous graph exists previous graph exists
* Action buttons for the display filter bar may be aligned left via the context menu
The following features are new (or have been significantly updated) The following features are new (or have been significantly updated)
since version 3.0.0: since version 3.0.0:

View File

@ -13,7 +13,7 @@
#include <epan/dfilter/dfilter.h> #include <epan/dfilter/dfilter.h>
#include <ui/filter_files.h> #include <ui/recent.h>
#include <wsutil/utf8_entities.h> #include <wsutil/utf8_entities.h>
@ -66,7 +66,8 @@ DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, DisplayFilterEditType type
actions_(Q_NULLPTR), actions_(Q_NULLPTR),
bookmark_button_(NULL), bookmark_button_(NULL),
clear_button_(NULL), clear_button_(NULL),
apply_button_(NULL) apply_button_(NULL),
leftAlignActions_(false)
{ {
setAccessibleName(tr("Display filter entry")); setAccessibleName(tr("Display filter entry"));
@ -76,77 +77,108 @@ DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, DisplayFilterEditType type
setDefaultPlaceholderText(); setDefaultPlaceholderText();
// DFCombo QString buttonStyle = QString(
// Bookmark "QToolButton {"
// DisplayFilterEdit " border: none;"
// Clear button " background: transparent;" // Disables platform style on Windows.
// Apply (right arrow) " padding: 0 0 0 0;"
// Combo drop-down "}"
"QToolButton::menu-indicator {"
" image: none;"
"}"
);
if (type_ == DisplayFilterToApply) { if (type_ == DisplayFilterToApply) {
bookmark_button_ = new StockIconToolButton(this, "x-display-filter-bookmark"); bookmark_button_ = new StockIconToolButton(this, "x-display-filter-bookmark");
bookmark_button_->setCursor(Qt::ArrowCursor);
bookmark_button_->setMenu(new QMenu(bookmark_button_)); bookmark_button_->setMenu(new QMenu(bookmark_button_));
bookmark_button_->setPopupMode(QToolButton::InstantPopup); bookmark_button_->setPopupMode(QToolButton::InstantPopup);
bookmark_button_->setToolTip(tr("Manage saved bookmarks.")); bookmark_button_->setToolTip(tr("Manage saved bookmarks."));
bookmark_button_->setIconSize(QSize(14, 14)); bookmark_button_->setIconSize(QSize(14, 14));
bookmark_button_->setStyleSheet( bookmark_button_->setStyleSheet(buttonStyle);
"QToolButton {"
" border: none;"
" background: transparent;" // Disables platform style on Windows.
" padding: 0 0 0 0;"
"}"
"QToolButton::menu-indicator { image: none; }"
);
clear_button_ = new StockIconToolButton(this, "x-filter-clear"); clear_button_ = new StockIconToolButton(this, "x-filter-clear");
clear_button_->setCursor(Qt::ArrowCursor);
clear_button_->setToolTip(tr("Clear display filter")); clear_button_->setToolTip(tr("Clear display filter"));
clear_button_->setIconSize(QSize(14, 14)); clear_button_->setIconSize(QSize(14, 14));
clear_button_->setStyleSheet( clear_button_->setStyleSheet(buttonStyle);
"QToolButton {" clear_button_->setVisible(false);
" border: none;"
" background: transparent;" // Disables platform style on Windows. apply_button_ = new StockIconToolButton(this, "x-filter-apply");
" padding: 0 0 0 0;" apply_button_->setEnabled(false);
" margin-left: 1px;" apply_button_->setToolTip(tr("Apply display filter"));
"}" apply_button_->setIconSize(QSize(24, 14));
); apply_button_->setStyleSheet(buttonStyle);
connect(clear_button_, &StockIconToolButton::clicked, this, &DisplayFilterEdit::clearFilter); connect(clear_button_, &StockIconToolButton::clicked, this, &DisplayFilterEdit::clearFilter);
connect(apply_button_, &StockIconToolButton::clicked, this, &DisplayFilterEdit::applyDisplayFilter);
connect(this, &DisplayFilterEdit::returnPressed, this, &DisplayFilterEdit::applyDisplayFilter);
} }
connect(this, &DisplayFilterEdit::textChanged, this, connect(this, &DisplayFilterEdit::textChanged, this,
static_cast<void (DisplayFilterEdit::*)(const QString &)>(&DisplayFilterEdit::checkFilter)); static_cast<void (DisplayFilterEdit::*)(const QString &)>(&DisplayFilterEdit::checkFilter));
connect(wsApp, &WiresharkApplication::appInitialized, this, &DisplayFilterEdit::updateBookmarkMenu);
connect(wsApp, &WiresharkApplication::displayFilterListChanged, this, &DisplayFilterEdit::updateBookmarkMenu);
leftAlignActions_ = recent.gui_geometry_leftalign_actions;
alignActionButtons();
}
void DisplayFilterEdit::contextMenuEvent(QContextMenuEvent *event){
QMenu *menu = this->createStandardContextMenu();
menu->addSeparator();
QAction * na = new QAction(tr("Left align buttons"));
na->setCheckable(true);
na->setChecked(leftAlignActions_);
connect(na, &QAction::triggered, this, &DisplayFilterEdit::triggerAlignementAction);
menu->addAction(na);
menu->exec(event->globalPos());
}
void DisplayFilterEdit::triggerAlignementAction()
{
leftAlignActions_ = ! leftAlignActions_;
if ( qobject_cast<QAction *>(sender()) )
qobject_cast<QAction *>(sender())->setChecked(leftAlignActions_);
recent.gui_geometry_leftalign_actions = leftAlignActions_;
write_recent();
alignActionButtons();
}
void DisplayFilterEdit::alignActionButtons()
{
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
QSize bksz, cbsz, apsz;
bksz = apsz = cbsz = QSize(0,0);
if (type_ == DisplayFilterToApply) { if (type_ == DisplayFilterToApply) {
apply_button_ = new StockIconToolButton(this, "x-filter-apply"); bookmark_button_->setMinimumHeight(contentsRect().height());
apply_button_->setCursor(Qt::ArrowCursor); bookmark_button_->setMaximumHeight(contentsRect().height());
apply_button_->setEnabled(false); bksz = bookmark_button_->sizeHint();
apply_button_->setToolTip(tr("Apply display filter"));
apply_button_->setIconSize(QSize(24, 14)); if ( clear_button_->isVisible() )
apply_button_->setStyleSheet( {
"QToolButton {" cbsz = clear_button_->sizeHint();
" border: none;" clear_button_->setMinimumHeight(contentsRect().height());
" background: transparent;" // Disables platform style on Windows. clear_button_->setMaximumHeight(contentsRect().height());
" padding: 0 0 0 0;" }
"}"
); apsz = apply_button_->sizeHint();
connect(apply_button_, &StockIconToolButton::clicked, this, &DisplayFilterEdit::applyDisplayFilter); apply_button_->setMinimumHeight(contentsRect().height());
connect(this, &DisplayFilterEdit::returnPressed, this, &DisplayFilterEdit::applyDisplayFilter); apply_button_->setMaximumHeight(contentsRect().height());
} }
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); int leftPadding = frameWidth + 1;
QSize bksz; int leftMargin = bksz.width();
if (bookmark_button_) { int rightMargin = cbsz.width() + apsz.width() + frameWidth + 1;
bksz = bookmark_button_->sizeHint(); if ( leftAlignActions_ )
} {
QSize cbsz; leftMargin = rightMargin + bksz.width();
if (clear_button_) { rightMargin = 0;
cbsz = clear_button_->sizeHint();
}
QSize apsz;
if (apply_button_) {
apsz = apply_button_->sizeHint();
} }
setStyleSheet(QString( setStyleSheet(QString(
"DisplayFilterEdit {" "DisplayFilterEdit {"
" padding-left: %1px;" " padding-left: %1px;"
@ -154,14 +186,35 @@ DisplayFilterEdit::DisplayFilterEdit(QWidget *parent, DisplayFilterEditType type
" margin-right: %3px;" " margin-right: %3px;"
"}" "}"
) )
.arg(frameWidth + 1) .arg(leftPadding)
.arg(bksz.width()) .arg(leftMargin)
.arg(cbsz.width() + apsz.width() + frameWidth + 1) .arg(rightMargin)
); );
connect(wsApp, &WiresharkApplication::appInitialized, this, &DisplayFilterEdit::updateBookmarkMenu); if (clear_button_) {
connect(wsApp, &WiresharkApplication::displayFilterListChanged, this, &DisplayFilterEdit::updateBookmarkMenu); if ( ! leftAlignActions_ )
{
clear_button_->move(contentsRect().right() - frameWidth - cbsz.width() - apsz.width(),
contentsRect().top());
} else {
clear_button_->move(contentsRect().left() + bookmark_button_->width(), contentsRect().top());
}
}
if (apply_button_) {
if ( ! leftAlignActions_ )
{
apply_button_->move(contentsRect().right() - frameWidth - apsz.width(),
contentsRect().top());
} else {
int additionalWidth = bookmark_button_->width();
if ( clear_button_ && clear_button_->isVisible() )
additionalWidth += clear_button_->width();
apply_button_->move(contentsRect().left() + additionalWidth, contentsRect().top());
}
}
update();
} }
void DisplayFilterEdit::setDefaultPlaceholderText() void DisplayFilterEdit::setDefaultPlaceholderText()
@ -187,6 +240,8 @@ void DisplayFilterEdit::setDefaultPlaceholderText()
void DisplayFilterEdit::paintEvent(QPaintEvent *evt) { void DisplayFilterEdit::paintEvent(QPaintEvent *evt) {
SyntaxLineEdit::paintEvent(evt); SyntaxLineEdit::paintEvent(evt);
alignActionButtons();
if (bookmark_button_) { if (bookmark_button_) {
// Draw the right border by hand. We could try to do this in the // Draw the right border by hand. We could try to do this in the
// style sheet but it's a pain. // style sheet but it's a pain.
@ -198,40 +253,23 @@ void DisplayFilterEdit::paintEvent(QPaintEvent *evt) {
QPainter painter(this); QPainter painter(this);
painter.setPen(divider_color); painter.setPen(divider_color);
QRect cr = contentsRect(); QRect cr = contentsRect();
QSize bksz = bookmark_button_->size(); int xpos = 0;
painter.drawLine(bksz.width(), cr.top(), bksz.width(), cr.bottom()); if ( leftAlignActions_ )
{
xpos = bookmark_button_->size().width() + apply_button_->size().width();
if ( clear_button_->isVisible() )
xpos += clear_button_->size().width();
}
else
xpos = bookmark_button_->size().width();
painter.drawLine(xpos, cr.top(), xpos, cr.bottom());
} }
} }
void DisplayFilterEdit::resizeEvent(QResizeEvent *) void DisplayFilterEdit::resizeEvent(QResizeEvent *)
{ {
QSize cbsz; alignActionButtons();
if (clear_button_) {
cbsz = clear_button_->sizeHint();
}
QSize apsz;
if (apply_button_) {
apsz = apply_button_->sizeHint();
} else {
apsz.setHeight(0); apsz.setWidth(0);
}
int frameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
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());
}
} }
void DisplayFilterEdit::focusOutEvent(QFocusEvent *event) void DisplayFilterEdit::focusOutEvent(QFocusEvent *event)
@ -257,6 +295,7 @@ void DisplayFilterEdit::checkFilter(const QString& filter_text)
if (clear_button_) { if (clear_button_) {
clear_button_->setVisible(!filter_text.isEmpty()); clear_button_->setVisible(!filter_text.isEmpty());
alignActionButtons();
} }
emit popFilterSyntaxStatus(); emit popFilterSyntaxStatus();

View File

@ -40,6 +40,7 @@ protected:
virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dragEnterEvent(QDragEnterEvent *event);
virtual void dragMoveEvent(QDragMoveEvent *event); virtual void dragMoveEvent(QDragMoveEvent *event);
virtual void dropEvent(QDropEvent *event); virtual void dropEvent(QDropEvent *event);
virtual void contextMenuEvent(QContextMenuEvent *menu);
public slots: public slots:
bool checkFilter(); bool checkFilter();
@ -58,6 +59,8 @@ private slots:
void showExpressionPrefs(); void showExpressionPrefs();
void applyOrPrepareFilter(); void applyOrPrepareFilter();
void triggerAlignementAction();
private: private:
DisplayFilterEditType type_; DisplayFilterEditType type_;
QString placeholder_text_; QString placeholder_text_;
@ -67,12 +70,15 @@ private:
StockIconToolButton *bookmark_button_; StockIconToolButton *bookmark_button_;
StockIconToolButton *clear_button_; StockIconToolButton *clear_button_;
StockIconToolButton *apply_button_; StockIconToolButton *apply_button_;
bool leftAlignActions_;
void setDefaultPlaceholderText(); void setDefaultPlaceholderText();
void buildCompletionList(const QString& field_word); void buildCompletionList(const QString& field_word);
void createFilterTextDropMenu(QDropEvent *event, bool prepare, QString filterText = QString()); void createFilterTextDropMenu(QDropEvent *event, bool prepare, QString filterText = QString());
void alignActionButtons();
signals: signals:
void pushFilterSyntaxStatus(const QString&); void pushFilterSyntaxStatus(const QString&);
void popFilterSyntaxStatus(); void popFilterSyntaxStatus();

View File

@ -48,6 +48,7 @@
#define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width" #define RECENT_GUI_GEOMETRY_MAIN_WIDTH "gui.geometry_main_width"
#define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height" #define RECENT_GUI_GEOMETRY_MAIN_HEIGHT "gui.geometry_main_height"
#define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized" #define RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED "gui.geometry_main_maximized"
#define RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS "gui.geometry_leftalign_actions"
#define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane" #define RECENT_GUI_GEOMETRY_MAIN_UPPER_PANE "gui.geometry_main_upper_pane"
#define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane" #define RECENT_GUI_GEOMETRY_MAIN_LOWER_PANE "gui.geometry_main_lower_pane"
#define RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT "gui.geometry_status_pane" #define RECENT_GUI_GEOMETRY_STATUS_PANE_LEFT "gui.geometry_status_pane"
@ -713,6 +714,10 @@ write_recent(void)
RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED,
recent.gui_geometry_main_maximized); recent.gui_geometry_main_maximized);
write_recent_boolean(rf, "Leftalign Action Buttons",
RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS,
recent.gui_geometry_leftalign_actions);
fprintf(rf, "\n# Statusbar left pane size.\n"); fprintf(rf, "\n# Statusbar left pane size.\n");
fprintf(rf, "# Decimal number.\n"); fprintf(rf, "# Decimal number.\n");
if (recent.gui_geometry_status_pane_left != 0) { if (recent.gui_geometry_status_pane_left != 0) {
@ -941,6 +946,8 @@ read_set_recent_common_pair_static(gchar *key, const gchar *value,
if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) { if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_MAXIMIZED) == 0) {
parse_recent_boolean(value, &recent.gui_geometry_main_maximized); parse_recent_boolean(value, &recent.gui_geometry_main_maximized);
} else if (strcmp(key, RECENT_GUI_GEOMETRY_LEFTALIGN_ACTIONS) == 0) {
parse_recent_boolean(value, &recent.gui_geometry_leftalign_actions);
} else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) { } else if (strcmp(key, RECENT_GUI_GEOMETRY_MAIN_X) == 0) {
num = strtol(value, &p, 0); num = strtol(value, &p, 0);
if (p == value || *p != '\0') if (p == value || *p != '\0')
@ -1263,6 +1270,8 @@ recent_read_static(char **rf_path_return, int *rf_errno_return)
recent.gui_geometry_main_height = DEF_HEIGHT; recent.gui_geometry_main_height = DEF_HEIGHT;
recent.gui_geometry_main_maximized= FALSE; recent.gui_geometry_main_maximized= FALSE;
recent.gui_geometry_leftalign_actions = FALSE;
recent.gui_geometry_status_pane_left = (DEF_WIDTH/3); recent.gui_geometry_status_pane_left = (DEF_WIDTH/3);
recent.gui_geometry_status_pane_right = (DEF_WIDTH/3); recent.gui_geometry_status_pane_right = (DEF_WIDTH/3);
recent.gui_geometry_wlan_stats_pane = 200; recent.gui_geometry_wlan_stats_pane = 200;

View File

@ -109,6 +109,7 @@ typedef struct recent_settings_tag {
gint gui_geometry_main_height; gint gui_geometry_main_height;
gboolean gui_geometry_main_maximized; gboolean gui_geometry_main_maximized;
gboolean gui_geometry_leftalign_actions;
gboolean has_gui_geometry_main_upper_pane; /* gui_geometry_main_upper_pane is valid */ gboolean has_gui_geometry_main_upper_pane; /* gui_geometry_main_upper_pane is valid */
gint gui_geometry_main_upper_pane; gint gui_geometry_main_upper_pane;