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.
* IOGraph automatically adds a graph for the selected display filter if no
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)
since version 3.0.0:

View File

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

View File

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

View File

@ -48,6 +48,7 @@
#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_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_LOWER_PANE "gui.geometry_main_lower_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);
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, "# Decimal number.\n");
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) {
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) {
num = strtol(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_maximized= FALSE;
recent.gui_geometry_leftalign_actions = FALSE;
recent.gui_geometry_status_pane_left = (DEF_WIDTH/3);
recent.gui_geometry_status_pane_right = (DEF_WIDTH/3);
recent.gui_geometry_wlan_stats_pane = 200;

View File

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