diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/messageview.cpp | 52 | ||||
| -rw-r--r-- | src/messageview.h | 21 |
2 files changed, 73 insertions, 0 deletions
diff --git a/src/messageview.cpp b/src/messageview.cpp index bdf1b13..68821d8 100644 --- a/src/messageview.cpp +++ b/src/messageview.cpp @@ -612,6 +612,54 @@ SearchOffer MessageView::selectionSearchOffer(const QString &selectedText) const query }; } +void MessageView::removeBrowserActions(QMenu *menu, QWebEnginePage *page) +{ + if (!menu || !page) + return; + + // Item 100. Every one of these needs a history, a network or a file, and + // this pane has none of the three. + // + // ViewSource is NOT in this list, and that is deliberate. It was removed + // here first, on the reasoning that it was the same kind of thing; it is + // not. The four below have nothing to act on, while view-source has a real + // document and a real use. Chromium's own entry cannot work here either + // (it navigates to view-source:<url>, which MessagePage refuses), so item + // 113 implements it as our own plain-text dialog. Removing it in the + // meantime would delete the gesture the user reaches for. + static constexpr QWebEnginePage::WebAction kUnwanted[] = { + QWebEnginePage::Back, + QWebEnginePage::Forward, + QWebEnginePage::Reload, + QWebEnginePage::SavePage, + }; + + for (const QWebEnginePage::WebAction which : kUnwanted) { + // pageAction() is the same QAction instance the standard menu holds, + // so the pointer identifies it whatever language it is displayed in. + if (QAction *action = page->action(which)) + menu->removeAction(action); + } + + // Removing entries can leave a separator at an edge or two in a row, which + // reads as a menu that lost something. Qt has no "tidy separators", so + // this walks what is left. + const QList<QAction *> remaining = menu->actions(); + bool previousWasSeparator = true; // leading separators are unwanted too + for (QAction *action : remaining) { + if (!action->isSeparator()) { + previousWasSeparator = false; + continue; + } + if (previousWasSeparator) + menu->removeAction(action); + else + previousWasSeparator = true; + } + if (!menu->actions().isEmpty() && menu->actions().constLast()->isSeparator()) + menu->removeAction(menu->actions().constLast()); +} + void MessageView::showBodyContextMenu(const QPoint &pos) { // The page's own menu first: copy, select all and the rest stay exactly as @@ -621,6 +669,10 @@ void MessageView::showBodyContextMenu(const QPoint &pos) menu = new QMenu(this); menu->setAttribute(Qt::WA_DeleteOnClose); + // ...minus the browser's own navigation and page actions, which cannot + // apply here. Item 100. + removeBrowserActions(menu, m_view->page()); + // selectedText() reads the selection out of the render process with no // script injection. JavaScript is disabled in this profile and stays so. const SearchOffer offer = selectionSearchOffer(m_view->page()->selectedText()); diff --git a/src/messageview.h b/src/messageview.h index 56925b2..df20e40 100644 --- a/src/messageview.h +++ b/src/messageview.h @@ -29,6 +29,7 @@ class QLabel; class QMenu; +class QWebEnginePage; class QPushButton; class QWebEngineView; class QWebEngineProfile; @@ -149,6 +150,26 @@ public: /// of which notmuch reports as an error. SearchOffer selectionSearchOffer(const QString &selectedText) const; + /// Strips the browser actions out of Chromium's standard context menu. + /// + /// Item 100. The pane is not a browser: every document arrives through + /// setHtml() with a fixed base URL, so Back, Forward, Reload and Save page + /// have nothing to act on and the interceptor blocks everything by default + /// anyway. Copy and Select all are the reason the standard menu is used at + /// all, so the menu is filtered, not rebuilt. + /// + /// View source is NOT filtered, though it was at first. It has a real + /// document and a real use; item 113 implements it as our own dialog, + /// since Chromium's entry navigates to view-source:<url> and MessagePage + /// refuses that. + /// + /// Matches on the page's own QAction POINTERS, never on text, which is + /// translated and would make the filter fail in every locale but one. + /// + /// Static and taking the menu so a test can build one and check it + /// without a rendered document or a shown popup. + static void removeBrowserActions(QMenu *menu, QWebEnginePage *page); + /// Tells the pane whether the query bar currently holds anything. /// /// The menus need it to grey out "Exclude from search": excluding from an |
