From 8268bb478dbdf9f23b35c5114c5d13bc98254659 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Thu, 13 Aug 2026 19:40:27 +0200 Subject: fix(queries): give Save query a clearer icon and a label document-save is the floppy/disk shape. It means "write a file somewhere", which leaves the user to guess what is being written, and next to a row of saved-query buttons it reads as an unrelated control. Saving a query is bookmarking a search, so bookmark-new is the icon every desktop already uses for "keep this for later". Verified to resolve with real art in the desktop's actual theme rather than assumed present. The button also shows its label now instead of the icon alone. It sits among text buttons, and an icon on its own next to them reads as a different kind of control; it is also the one action whose meaning an icon cannot carry, since "save" is a familiar shape whose question is always "save what?". The toolbar is unaffected and still follows the desktop's own button style. The label is the button's own text rather than the action's. "&Save query..." is menu phrasing, and setDefaultAction copies it verbatim, so the button rendered an accelerator ampersand and the ellipsis that promises a dialog. The action keeps both for the menu it lives in, and the test asserts the override survives setDefaultAction rather than trusting that it does. Co-Authored-By: Claude Opus 5 --- src/mainwindow.cpp | 19 +++++++++++++++++-- tests/test_mainwindow.cpp | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 61c883e..f06b308 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -353,7 +353,18 @@ MainWindow::MainWindow(const Config &config, QWidget *parent) // action's text, icon, tooltip and ENABLED state, so it cannot end up // offering to save an empty query while the menu entry refuses. m_saveQueryButton->setDefaultAction(save); - m_saveQueryButton->setToolButtonStyle(Qt::ToolButtonIconOnly); + // Icon AND text, unlike the toolbar, which follows the desktop's + // button style. This button sits in a row of text buttons, the saved + // queries, and an icon on its own next to them reads as a different + // kind of control than it is. It is also the one action whose meaning + // an icon alone does not carry: "save" is a shape everyone knows and + // the question is always "save WHAT". + m_saveQueryButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + // Its own text, not the action's: "&Save query..." is menu phrasing, + // and a button rendering the ampersand's accelerator and the ellipsis + // that promises a dialog reads as a menu entry that escaped. The + // action keeps both for the menu it lives in. + m_saveQueryButton->setText(tr("Save")); auto updateSaveState = [this, save]() { save->setEnabled(!m_queryEdit->text().trimmed().isEmpty()); @@ -1066,7 +1077,11 @@ void MainWindow::buildMenus() // the selection's tags. { QStringLiteral("tag_rules"), QStringLiteral("configure") }, { QStringLiteral("complete_query"), QStringLiteral("edit-find-replace") }, - { QStringLiteral("save_query"), QStringLiteral("document-save") }, + // NOT "document-save": that is the floppy/disk shape, which reads as + // "write a file somewhere" and asks the user to guess what is being + // written. Saving a query is bookmarking a search, and bookmark-new is + // the icon set every desktop already uses for "keep this for later". + { QStringLiteral("save_query"), QStringLiteral("bookmark-new") }, { QStringLiteral("select_all"), QStringLiteral("edit-select-all") }, { QStringLiteral("clear_pane"), QStringLiteral("edit-clear") }, { QStringLiteral("clear_selection"), QStringLiteral("edit-clear-all") }, diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp index 080e4cd..42d7d78 100644 --- a/tests/test_mainwindow.cpp +++ b/tests/test_mainwindow.cpp @@ -52,6 +52,7 @@ #include #include +#include #include #include #include @@ -5560,6 +5561,23 @@ void TestMainWindow::thereIsASaveButtonBesideTheQueryBar() window.findChild(QStringLiteral("saveQueryButton")); QVERIFY2(button, "no Save query button beside the query bar"); + // Icon AND text. An icon alone was the first version and read as + // ambiguous: "save" is a familiar shape whose meaning is always "save + // what?". + auto *toolButton = qobject_cast(button); + QVERIFY(toolButton); + QCOMPARE(toolButton->toolButtonStyle(), Qt::ToolButtonTextBesideIcon); + QVERIFY2(!button->icon().isNull(), "the button has no icon"); + QVERIFY2(!button->text().isEmpty(), "the button has no text"); + + // Button phrasing, not the menu's: no accelerator ampersand, and no + // ellipsis. setDefaultAction copies the action's text, so this asserts the + // override survived it. + QVERIFY2(!button->text().contains(QLatin1Char('&')), + "the menu accelerator leaked onto the button"); + QVERIFY2(!button->text().contains(QStringLiteral("...")), + "the menu's ellipsis leaked onto the button"); + auto *queryEdit = window.findChild(QStringLiteral("queryEdit")); QVERIFY(queryEdit); -- cgit v1.2.3