summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/messageview.cpp52
-rw-r--r--src/messageview.h21
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