From 1899a3838f012a43abaeba3959c1b591649fde1e Mon Sep 17 00:00:00 2001
From: Eike Ziller <eike.ziller@nokia.com>
Date: Fri, 9 Dec 2011 12:23:46 +0100
Subject: [PATCH] Provide "Open with" context menu in qrc editor.

Task-number: QTCREATORBUG-4224

Change-Id: If2b13fa8b58779058d483d532c2c9649f7fa8dfd
Reviewed-by: Jarek Kobus <jaroslaw.kobus@nokia.com>
---
 src/plugins/coreplugin/filemanager.cpp        |  1 +
 src/plugins/coreplugin/filemanager.h          |  3 ++-
 .../foldernavigationwidget.cpp                |  2 +-
 .../projectexplorer/projectexplorer.cpp       | 10 +-------
 src/plugins/projectexplorer/projectexplorer.h |  1 -
 .../resourceeditor/resourceeditorw.cpp        | 25 +++++++++++++++++--
 src/plugins/resourceeditor/resourceeditorw.h  |  7 ++++++
 src/shared/qrceditor/qrceditor.cpp            |  2 ++
 src/shared/qrceditor/qrceditor.h              |  1 +
 src/shared/qrceditor/resourceview.cpp         | 12 +++++++++
 src/shared/qrceditor/resourceview.h           |  4 +++
 11 files changed, 54 insertions(+), 14 deletions(-)

diff --git a/src/plugins/coreplugin/filemanager.cpp b/src/plugins/coreplugin/filemanager.cpp
index 52be854cd89..2e4391260a9 100644
--- a/src/plugins/coreplugin/filemanager.cpp
+++ b/src/plugins/coreplugin/filemanager.cpp
@@ -1333,6 +1333,7 @@ void FileManager::populateOpenWithMenu(QMenu *menu, const QString &fileName)
 
 void FileManager::executeOpenWithMenuAction(QAction *action)
 {
+    QTC_ASSERT(action, return);
     EditorManager *em = EditorManager::instance();
     const QVariant data = action->data();
     Internal::OpenWithEntry entry = qVariantValue<Internal::OpenWithEntry>(data);
diff --git a/src/plugins/coreplugin/filemanager.h b/src/plugins/coreplugin/filemanager.h
index 65218d4bf40..9b91198440f 100644
--- a/src/plugins/coreplugin/filemanager.h
+++ b/src/plugins/coreplugin/filemanager.h
@@ -138,13 +138,14 @@ public:
     void setProjectsDirectory(const QString &);
 
     static void populateOpenWithMenu(QMenu *menu, const QString &fileName);
-    static void executeOpenWithMenuAction(QAction *action);
 
 public slots:
     /* Used to notify e.g. the code model to update the given files. Does *not*
        lead to any editors to reload or any other editor manager actions. */
     void notifyFilesChangedInternally(const QStringList &files);
 
+    void executeOpenWithMenuAction(QAction *action);
+
 signals:
     void currentFileChanged(const QString &filePath);
     /* Used to notify e.g. the code model to update the given files. Does *not*
diff --git a/src/plugins/projectexplorer/foldernavigationwidget.cpp b/src/plugins/projectexplorer/foldernavigationwidget.cpp
index d0c359a1d4a..4a54fa21c42 100644
--- a/src/plugins/projectexplorer/foldernavigationwidget.cpp
+++ b/src/plugins/projectexplorer/foldernavigationwidget.cpp
@@ -361,7 +361,7 @@ void FolderNavigationWidget::contextMenuEvent(QContextMenuEvent *ev)
             findOnFileSystem(info.absolutePath());
         return;
     }
-    Core::FileManager::executeOpenWithMenuAction(action);
+    Core::FileManager::instance()->executeOpenWithMenuAction(action);
 }
 
 QString FolderNavigationWidget::msgFindOnFileSystem()
diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp
index 13f091d400a..57304c0306e 100644
--- a/src/plugins/projectexplorer/projectexplorer.cpp
+++ b/src/plugins/projectexplorer/projectexplorer.cpp
@@ -515,7 +515,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
     d->m_openWithMenu->setTitle(tr("Open With"));
 
     connect(d->m_openWithMenu, SIGNAL(triggered(QAction *)),
-            this, SLOT(openWithMenuTriggered(QAction *)));
+            Core::FileManager::instance(), SLOT(executeOpenWithMenuAction(QAction*)));
 
     //
     // Separators
@@ -2785,14 +2785,6 @@ void ProjectExplorerPlugin::populateOpenWithMenu()
     Core::FileManager::populateOpenWithMenu(d->m_openWithMenu, currentNode()->path());
 }
 
-void ProjectExplorerPlugin::openWithMenuTriggered(QAction *action)
-{
-    if (!action)
-        qWarning() << "ProjectExplorerPlugin::openWithMenuTriggered no action, can't happen.";
-    else
-        Core::FileManager::executeOpenWithMenuAction(action);
-}
-
 void ProjectExplorerPlugin::updateSessionMenu()
 {
     d->m_sessionMenu->clear();
diff --git a/src/plugins/projectexplorer/projectexplorer.h b/src/plugins/projectexplorer/projectexplorer.h
index d59c0356fcc..5faad029b81 100644
--- a/src/plugins/projectexplorer/projectexplorer.h
+++ b/src/plugins/projectexplorer/projectexplorer.h
@@ -176,7 +176,6 @@ private slots:
     void newProject();
     void showSessionManager();
     void populateOpenWithMenu();
-    void openWithMenuTriggered(QAction *action);
     void updateSessionMenu();
     void setSession(QAction *action);
 
diff --git a/src/plugins/resourceeditor/resourceeditorw.cpp b/src/plugins/resourceeditor/resourceeditorw.cpp
index 6ad8ec4b035..a7fa3eadee2 100644
--- a/src/plugins/resourceeditor/resourceeditorw.cpp
+++ b/src/plugins/resourceeditor/resourceeditorw.cpp
@@ -38,6 +38,7 @@
 
 #include <coreplugin/icore.h>
 #include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/filemanager.h>
 #include <utils/reloadpromptutils.h>
 #include <utils/fileutils.h>
 
@@ -45,8 +46,9 @@
 #include <QtCore/QFileInfo>
 #include <QtCore/QDir>
 #include <QtCore/qdebug.h>
-#include <QtGui/QMainWindow>
 #include <QtGui/QHBoxLayout>
+#include <QtGui/QMainWindow>
+#include <QtGui/QMenu>
 
 namespace ResourceEditor {
 namespace Internal {
@@ -77,16 +79,27 @@ ResourceEditorW::ResourceEditorW(const Core::Context &context,
         m_resourceFile(new ResourceEditorFile(this)),
         m_plugin(plugin),
         m_shouldAutoSave(false),
-        m_diskIo(false)
+        m_diskIo(false),
+        m_contextMenu(new QMenu)
 {
     setContext(context);
     setWidget(m_resourceEditor);
 
     m_resourceEditor->setResourceDragEnabled(true);
+    m_openWithMenu = m_contextMenu->addMenu(tr("Open With"));
+    // Below we need QueuedConnection because otherwise, if this qrc file
+    // is inside of the qrc file, crashes happen when using "Open With" on it.
+    // (That is because this editor instance is deleted in executeOpenWithMenuAction
+    // in that case.)
+    connect(m_openWithMenu, SIGNAL(triggered(QAction*)),
+            Core::FileManager::instance(), SLOT(executeOpenWithMenuAction(QAction*)),
+            Qt::QueuedConnection);
 
     connect(m_resourceEditor, SIGNAL(dirtyChanged(bool)), this, SLOT(dirtyChanged(bool)));
     connect(m_resourceEditor, SIGNAL(undoStackChanged(bool, bool)),
             this, SLOT(onUndoStackChanged(bool, bool)));
+    connect(m_resourceEditor, SIGNAL(showContextMenu(QPoint,QString)),
+            this, SLOT(showContextMenu(QPoint,QString)));
     connect(m_resourceEditor->commandHistory(), SIGNAL(indexChanged(int)),
             this, SLOT(setShouldAutoSave()));
     connect(m_resourceFile, SIGNAL(changed()), this, SIGNAL(changed()));
@@ -98,6 +111,7 @@ ResourceEditorW::~ResourceEditorW()
 {
     if (m_resourceEditor)
         m_resourceEditor->deleteLater();
+    delete m_contextMenu;
 }
 
 bool ResourceEditorW::createNew(const QString &contents)
@@ -264,6 +278,13 @@ void ResourceEditorW::onUndoStackChanged(bool canUndo, bool canRedo)
     m_plugin->onUndoStackChanged(this, canUndo, canRedo);
 }
 
+void ResourceEditorW::showContextMenu(const QPoint &globalPoint, const QString &fileName)
+{
+    Core::FileManager::populateOpenWithMenu(m_openWithMenu, fileName);
+    if (!m_openWithMenu->actions().isEmpty())
+        m_contextMenu->popup(globalPoint);
+}
+
 void ResourceEditorW::onUndo()
 {
     if (!m_resourceEditor.isNull())
diff --git a/src/plugins/resourceeditor/resourceeditorw.h b/src/plugins/resourceeditor/resourceeditorw.h
index ac13330ce2b..5b24ac53206 100644
--- a/src/plugins/resourceeditor/resourceeditorw.h
+++ b/src/plugins/resourceeditor/resourceeditorw.h
@@ -38,6 +38,10 @@
 
 #include <QtCore/QPointer>
 
+QT_BEGIN_NAMESPACE
+class QMenu;
+QT_END_NAMESPACE
+
 namespace SharedTools {
     class QrcEditor;
 }
@@ -104,6 +108,7 @@ private slots:
     void dirtyChanged(bool);
     void onUndoStackChanged(bool canUndo, bool canRedo);
     void setShouldAutoSave(bool sad = true) { m_shouldAutoSave = sad; }
+    void showContextMenu(const QPoint &globalPoint, const QString &fileName);
 
 private:
     const QString m_extension;
@@ -115,6 +120,8 @@ private:
     ResourceEditorPlugin *m_plugin;
     bool m_shouldAutoSave;
     bool m_diskIo;
+    QMenu *m_contextMenu;
+    QMenu *m_openWithMenu;
 
 public:
     void onUndo();
diff --git a/src/shared/qrceditor/qrceditor.cpp b/src/shared/qrceditor/qrceditor.cpp
index b83368c16ab..e06a939ca41 100644
--- a/src/shared/qrceditor/qrceditor.cpp
+++ b/src/shared/qrceditor/qrceditor.cpp
@@ -66,6 +66,8 @@ QrcEditor::QrcEditor(QWidget *parent)
     connect(m_treeview->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
             this, SLOT(updateCurrent()));
     connect(m_treeview, SIGNAL(dirtyChanged(bool)), this, SIGNAL(dirtyChanged(bool)));
+    connect(m_treeview, SIGNAL(showContextMenu(QPoint,QString)),
+            this, SIGNAL(showContextMenu(QPoint,QString)));
     m_treeview->setFocus();
 
     connect(m_ui.aliasText, SIGNAL(textEdited(QString)),
diff --git a/src/shared/qrceditor/qrceditor.h b/src/shared/qrceditor/qrceditor.h
index d0aae75cfd1..117d82decf4 100644
--- a/src/shared/qrceditor/qrceditor.h
+++ b/src/shared/qrceditor/qrceditor.h
@@ -68,6 +68,7 @@ public:
 
 signals:
     void dirtyChanged(bool dirty);
+    void showContextMenu(const QPoint &globalPos, const QString &fileName);
 
 private slots:
     void updateCurrent();
diff --git a/src/shared/qrceditor/resourceview.cpp b/src/shared/qrceditor/resourceview.cpp
index d34196fffe5..54d3d3854ed 100644
--- a/src/shared/qrceditor/resourceview.cpp
+++ b/src/shared/qrceditor/resourceview.cpp
@@ -182,11 +182,14 @@ ResourceView::ResourceView(QUndoStack *history, QWidget *parent) :
 {
     advanceMergeId();
     setModel(m_qrcModel);
+    setContextMenuPolicy(Qt::CustomContextMenu);
 
     header()->hide();
 
     connect(m_qrcModel, SIGNAL(dirtyChanged(bool)),
         this, SIGNAL(dirtyChanged(bool)));
+    connect(this, SIGNAL(customContextMenuRequested(QPoint)),
+            this, SLOT(showContextMenu(QPoint)));
 }
 
 ResourceView::~ResourceView()
@@ -429,6 +432,15 @@ void ResourceView::changeValue(const QModelIndex &nodeIndex, NodeProperty proper
     }
 }
 
+void ResourceView::showContextMenu(const QPoint &pos)
+{
+    const QModelIndex index = indexAt(pos);
+    const QString fileName = m_qrcModel->file(index);
+    if (fileName.isEmpty())
+        return;
+    emit showContextMenu(mapToGlobal(pos), fileName);
+}
+
 void ResourceView::advanceMergeId()
 {
     m_mergeId++;
diff --git a/src/shared/qrceditor/resourceview.h b/src/shared/qrceditor/resourceview.h
index 1b62ff968eb..a608608a537 100644
--- a/src/shared/qrceditor/resourceview.h
+++ b/src/shared/qrceditor/resourceview.h
@@ -130,11 +130,15 @@ protected:
 signals:
     void removeItem();
     void dirtyChanged(bool b);
+    void showContextMenu(const QPoint &globalPos, const QString &fileName);
 
 public:
     QString getCurrentValue(NodeProperty property) const;
     void changeValue(const QModelIndex &nodeIndex, NodeProperty property, const QString &value);
 
+private slots:
+    void showContextMenu(const QPoint &pos);
+
 private:
     void addUndoCommand(const QModelIndex &nodeIndex, NodeProperty property,
                         const QString &before, const QString &after);
-- 
GitLab