浏览代码

refine context menu of VWebView

- Hide unused actions.
Le Tan 8 年之前
父节点
当前提交
d193cd28a5
共有 2 个文件被更改,包括 155 次插入44 次删除
  1. 141 43
      src/vwebview.cpp
  2. 14 1
      src/vwebview.h

+ 141 - 43
src/vwebview.cpp

@@ -19,59 +19,38 @@
 static const QString c_ClipboardPropertyMark = "CopiedImageURLAltered";
 
 VWebView::VWebView(VFile *p_file, QWidget *p_parent)
-    : QWebEngineView(p_parent), m_file(p_file), m_actionHooked(false)
+    : QWebEngineView(p_parent),
+      m_file(p_file),
+      m_copyImageUrlActionHooked(false),
+      m_copyActionHooked(false)
 {
     setAcceptDrops(false);
 }
 
 void VWebView::contextMenuEvent(QContextMenuEvent *p_event)
 {
-#if defined(Q_OS_WIN)
-    if (!m_actionHooked) {
-        m_actionHooked = true;
+    QMenu *menu = page()->createStandardContextMenu();
+    menu->setToolTipsVisible(true);
+
+    const QList<QAction *> actions = menu->actions();
 
+#if defined(Q_OS_WIN)
+    if (!m_copyImageUrlActionHooked) {
         // "Copy Image URL" action will put the encoded URL to the clipboard as text
         // and the URL as URLs. If the URL contains Chinese, OneNote or Word could not
         // recognize it.
         // We need to change it to only-space-encoded text.
-        QAction *copyImageUrlAct = pageAction(QWebEnginePage::CopyImageUrlToClipboard);
-        connect(copyImageUrlAct, &QAction::triggered,
-                this, [this](){
-                    // To avoid failure of setting clipboard mime data.
-                    QCoreApplication::processEvents();
-
-                    QClipboard *clipboard = QApplication::clipboard();
-                    const QMimeData *mimeData = clipboard->mimeData();
-                    clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), false);
-                    if (clipboard->ownsClipboard()
-                        && mimeData->hasText()
-                        && mimeData->hasUrls()) {
-                        QString text = mimeData->text();
-                        QList<QUrl> urls = mimeData->urls();
-                        if (urls.size() == 1
-                            && urls[0].isLocalFile()
-                            && urls[0].toEncoded() == text) {
-                            QString spaceOnlyText = urls[0].toString(QUrl::EncodeSpaces);
-                            if (spaceOnlyText != text) {
-                                // Set new mime data.
-                                QMimeData *data = new QMimeData();
-                                data->setUrls(urls);
-                                data->setText(spaceOnlyText);
-                                clipboard->setMimeData(data);
-
-                                clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), true);
-                                qDebug() << "clipboard copy image URL altered" << spaceOnlyText;
-                            }
-                        }
-                    }
-                });
-    }
-#endif
+        QAction *copyImageUrlAct = getPageAction(actions, QWebEnginePage::CopyImageUrlToClipboard);
+        if (actions.contains(copyImageUrlAct)) {
+            connect(copyImageUrlAct, &QAction::triggered,
+                    this, &VWebView::handleCopyImageUrlAction);
 
-    QMenu *menu = page()->createStandardContextMenu();
-    menu->setToolTipsVisible(true);
+            m_copyImageUrlActionHooked = true;
 
-    const QList<QAction *> actions = menu->actions();
+            qDebug() << "hooked CopyImageUrl action" << copyImageUrlAct;
+        }
+    }
+#endif
 
     if (!hasSelection() && m_file && m_file->isModifiable()) {
         QAction *editAct= new QAction(VIconUtils::menuIcon(":/resources/icons/edit_note.svg"),
@@ -90,17 +69,19 @@ void VWebView::contextMenuEvent(QContextMenuEvent *p_event)
     // the fully-encoded URL to fetch the image while Windows seems to not
     // recognize it.
 #if defined(Q_OS_WIN)
-    QAction *defaultCopyImageAct = pageAction(QWebEnginePage::CopyImageToClipboard);
+    QAction *defaultCopyImageAct = getPageAction(actions, QWebEnginePage::CopyImageToClipboard);
     if (defaultCopyImageAct && actions.contains(defaultCopyImageAct)) {
         QAction *copyImageAct = new QAction(defaultCopyImageAct->text(), menu);
         copyImageAct->setToolTip(defaultCopyImageAct->toolTip());
         connect(copyImageAct, &QAction::triggered,
                 this, &VWebView::copyImage);
         menu->insertAction(defaultCopyImageAct, copyImageAct);
-        menu->removeAction(defaultCopyImageAct);
+        defaultCopyImageAct->setVisible(false);
     }
 #endif
 
+    hideUnusedActions(menu);
+
     menu->exec(p_event->globalPos());
     delete menu;
 }
@@ -112,7 +93,7 @@ void VWebView::handleEditAction()
 
 void VWebView::copyImage()
 {
-    Q_ASSERT(m_actionHooked);
+    Q_ASSERT(m_copyImageUrlActionHooked);
 
     // triggerPageAction(QWebEnginePage::CopyImageUrlToClipboard) will not really
     // trigger the corresponding action. It just do the stuff directly.
@@ -145,3 +126,120 @@ void VWebView::copyImage()
     // Fall back.
     triggerPageAction(QWebEnginePage::CopyImageToClipboard);
 }
+
+void VWebView::handleCopyImageUrlAction()
+{
+    // To avoid failure of setting clipboard mime data.
+    QCoreApplication::processEvents();
+
+    QClipboard *clipboard = QApplication::clipboard();
+    const QMimeData *mimeData = clipboard->mimeData();
+    clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), false);
+    if (clipboard->ownsClipboard()
+        && mimeData->hasText()
+        && mimeData->hasUrls()) {
+        QString text = mimeData->text();
+        QList<QUrl> urls = mimeData->urls();
+        if (urls.size() == 1
+            && urls[0].isLocalFile()
+            && urls[0].toEncoded() == text) {
+            QString spaceOnlyText = urls[0].toString(QUrl::EncodeSpaces);
+            if (spaceOnlyText != text) {
+                // Set new mime data.
+                QMimeData *data = new QMimeData();
+                data->setUrls(urls);
+                data->setText(spaceOnlyText);
+                clipboard->setMimeData(data);
+
+                clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), true);
+                qDebug() << "clipboard copy image URL altered" << spaceOnlyText;
+            }
+        }
+    }
+}
+
+void VWebView::hideUnusedActions(QMenu *p_menu)
+{
+    const QList<QAction *> actions = p_menu->actions();
+
+    QList<QAction *> unusedActions;
+
+    // Back.
+    QAction *act = getPageAction(actions, QWebEnginePage::Back);
+    unusedActions.append(act);
+
+    // Forward.
+    act = getPageAction(actions, QWebEnginePage::Forward);
+    unusedActions.append(act);
+
+    // Reload.
+    act = getPageAction(actions, QWebEnginePage::Reload);
+    unusedActions.append(act);
+
+    // ViewSource.
+    act = getPageAction(actions, QWebEnginePage::ViewSource);
+    unusedActions.append(act);
+
+    // DownloadImageToDisk.
+    act = getPageAction(actions, QWebEnginePage::DownloadImageToDisk);
+    unusedActions.append(act);
+
+    for (auto it : unusedActions) {
+        if (it) {
+            it->setVisible(false);
+        }
+    }
+}
+
+void VWebView::handleCopyAction()
+{
+    // To avoid failure of setting clipboard mime data.
+    QCoreApplication::processEvents();
+
+    QClipboard *clipboard = QApplication::clipboard();
+    const QMimeData *mimeData = clipboard->mimeData();
+    clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), false);
+    qDebug() << clipboard->ownsClipboard() << mimeData->hasHtml();
+    if (clipboard->ownsClipboard()
+        && mimeData->hasHtml()) {
+        QString html = mimeData->html();
+        if (html.startsWith("<html>")) {
+            return;
+        }
+
+        html = QString("<html><body><!--StartFragment-->%1<!--EndFragment--></body></html>").arg(html);
+
+        // Set new mime data.
+        QMimeData *data = new QMimeData();
+        data->setHtml(html);
+
+        if (mimeData->hasUrls()) {
+            data->setUrls(mimeData->urls());
+        }
+
+        if (mimeData->hasText()) {
+            data->setText(mimeData->text());
+        }
+
+        clipboard->setMimeData(data);
+        clipboard->setProperty(c_ClipboardPropertyMark.toLatin1(), true);
+        qDebug() << "clipboard copy Html altered" << html;
+    }
+}
+
+QAction *VWebView::getPageAction(const QList<QAction *> &p_actions,
+                                 QWebEnginePage::WebAction p_webAction)
+{
+    QAction *act = pageAction(p_webAction);
+    if (act && !p_actions.contains(act)) {
+        QString text = act->text();
+        for (auto it : p_actions) {
+            if (it->text().endsWith(text)) {
+                act = it;
+                break;
+            }
+        }
+    }
+
+    return act;
+}

+ 14 - 1
src/vwebview.h

@@ -4,6 +4,7 @@
 #include <QWebEngineView>
 
 class VFile;
+class QMenu;
 
 class VWebView : public QWebEngineView
 {
@@ -21,15 +22,27 @@ protected:
 private slots:
     void handleEditAction();
 
+    void handleCopyImageUrlAction();
+
+    void handleCopyAction();
+
     // Copy the clicked image.
     // Used to replace the default CopyImageToClipboard action.
     void copyImage();
 
 private:
+    void hideUnusedActions(QMenu *p_menu);
+
+    // pageAction() may not return exactly the action in use.
+    QAction *getPageAction(const QList<QAction *> &p_actions,
+                           QWebEnginePage::WebAction p_webAction);
+
     VFile *m_file;
 
     // Whether this view has hooked the Copy Image Url action.
-    bool m_actionHooked;
+    bool m_copyImageUrlActionHooked;
+
+    bool m_copyActionHooked;
 };
 
 #endif // VWEBVIEW_H