Add context menu to open file location to model views
authorMilian Wolff <mail@milianw.de>
Sat, 21 Jan 2017 22:46:24 +0000 (23:46 +0100)
committerMilian Wolff <mail@milianw.de>
Sat, 21 Jan 2017 23:56:07 +0000 (00:56 +0100)
This just goes through QDesktopServices and does not yet allow
the user to configure what editor he wants to use to open the file.

src/analyze/gui/callercalleemodel.cpp
src/analyze/gui/callercalleemodel.h
src/analyze/gui/locationdata.h
src/analyze/gui/mainwindow.cpp
src/analyze/gui/treemodel.cpp
src/analyze/gui/treemodel.h

index 61d7267..82912fa 100644 (file)
@@ -241,6 +241,8 @@ QVariant CallerCalleeModel::data(const QModelIndex& index, int role) const
         stream << '\n';
         stream << "</pre></qt>";
         return tooltip;
+    } else if (role == LocationRole) {
+        return QVariant::fromValue(row.location);
     }
     return {};
 }
index d9ebbf7..065973f 100644 (file)
@@ -33,7 +33,7 @@ struct CallerCalleeData
 {
     AllocationData inclusiveCost;
     AllocationData selfCost;
-    std::shared_ptr<LocationData> location;
+    LocationData::Ptr location;
 };
 Q_DECLARE_TYPEINFO(CallerCalleeData, Q_MOVABLE_TYPE);
 
@@ -68,7 +68,8 @@ public:
 
     enum Roles {
         SortRole = Qt::UserRole,
-        MaxCostRole = Qt::UserRole + 1
+        MaxCostRole,
+        LocationRole
     };
 
     QVariant headerData(int section, Qt::Orientation orientation = Qt::Horizontal,
index 797c2c3..2a0b8b2 100644 (file)
@@ -26,6 +26,8 @@
 
 struct LocationData
 {
+    using Ptr = std::shared_ptr<LocationData>;
+
     QString function;
     QString file;
     QString module;
@@ -55,8 +57,9 @@ struct LocationData
     }
 };
 Q_DECLARE_TYPEINFO(LocationData, Q_MOVABLE_TYPE);
+Q_DECLARE_METATYPE(LocationData::Ptr)
 
-inline bool operator<(const std::shared_ptr<LocationData>& lhs, const LocationData& rhs)
+inline bool operator<(const LocationData::Ptr& lhs, const LocationData& rhs)
 {
     return *lhs < rhs;
 }
index bf4c290..dce5406 100644 (file)
 
 #include <KRecursiveFilterProxyModel>
 #include <KLocalizedString>
+#include <KConfigGroup>
 
 #include <QFileDialog>
 #include <QStatusBar>
-#include <KConfigGroup>
 #include <QDebug>
+#include <QMenu>
+#include <QAction>
+#include <QDesktopServices>
 
 #include "treemodel.h"
 #include "treeproxy.h"
@@ -63,6 +66,34 @@ const char State[] = "State";
 }
 }
 
+void addContextMenu(QTreeView* treeView, int role)
+{
+    treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+    QObject::connect(treeView, &QTreeView::customContextMenuRequested,
+        treeView, [treeView, role] (const QPoint& pos) {
+            auto index = treeView->indexAt(pos);
+            if (!index.isValid()) {
+                return;
+            }
+            const auto location = index.data(role).value<LocationData::Ptr>();
+            if (!location || !QFile::exists(location->file)) {
+                return;
+            }
+            auto menu = new QMenu(treeView);
+            auto openFile = new QAction(QIcon::fromTheme(QStringLiteral("document-open")),
+                                        QObject::tr("Open file in editor"));
+            QObject::connect(openFile, &QAction::triggered,
+                openFile, [location] {
+                    /// FIXME: add settings to let user configure this
+                    auto url = QUrl::fromLocalFile(location->file);
+                    url.setFragment(QString::number(location->line));
+                    QDesktopServices::openUrl(url);
+                });
+            menu->addAction(openFile);
+            menu->popup(treeView->mapToGlobal(pos));
+        });
+}
+
 void setupTopView(TreeModel* source, QTreeView* view, TopProxy::Type type)
 {
     auto proxy = new TopProxy(type, source);
@@ -73,6 +104,7 @@ void setupTopView(TreeModel* source, QTreeView* view, TopProxy::Type type)
     view->setUniformRowHeights(true);
     view->sortByColumn(0);
     view->header()->setStretchLastSection(true);
+    addContextMenu(view, TreeModel::LocationRole);
 }
 
 #if KChart_FOUND
@@ -251,6 +283,7 @@ MainWindow::MainWindow(QWidget* parent)
             bottomUpProxy, &TreeProxy::setFileFilter);
     connect(m_ui->bottomUpFilterModule, &QLineEdit::textChanged,
             bottomUpProxy, &TreeProxy::setModuleFilter);
+    addContextMenu(m_ui->bottomUpResults, TreeModel::LocationRole);
 
     auto topDownProxy = new TreeProxy(TreeModel::FunctionColumn,
                                       TreeModel::FileColumn,
@@ -274,6 +307,7 @@ MainWindow::MainWindow(QWidget* parent)
             topDownProxy, &TreeProxy::setFileFilter);
     connect(m_ui->topDownFilterModule, &QLineEdit::textChanged,
             topDownProxy, &TreeProxy::setModuleFilter);
+    addContextMenu(m_ui->topDownResults, TreeModel::LocationRole);
 
     auto callerCalleeProxy = new TreeProxy(CallerCalleeModel::FunctionColumn,
                                            CallerCalleeModel::FileColumn,
@@ -303,6 +337,7 @@ MainWindow::MainWindow(QWidget* parent)
             callerCalleeProxy, &TreeProxy::setFileFilter);
     connect(m_ui->callerCalleeFilterModule, &QLineEdit::textChanged,
             callerCalleeProxy, &TreeProxy::setModuleFilter);
+    addContextMenu(m_ui->callerCalleeResults, CallerCalleeModel::LocationRole);
 
     auto validateInputFile = [this] (const QString &path, bool allowEmpty) -> bool {
         if (path.isEmpty()) {
index 8746b73..1689098 100644 (file)
@@ -250,6 +250,8 @@ QVariant TreeModel::data(const QModelIndex& index, int role) const
         }
         stream << "</pre></qt>";
         return tooltip;
+    } else if (role == LocationRole) {
+        return QVariant::fromValue(row->location);
     }
     return {};
 }
index 1428d05..0df38dd 100644 (file)
@@ -32,7 +32,7 @@
 struct RowData
 {
     AllocationData cost;
-    std::shared_ptr<LocationData> location;
+    LocationData::Ptr location;
     const RowData* parent;
     QVector<RowData> children;
     bool operator<(const std::shared_ptr<LocationData>& rhs) const
@@ -68,7 +68,8 @@ public:
 
     enum Roles {
         SortRole = Qt::UserRole,
-        MaxCostRole = Qt::UserRole + 1
+        MaxCostRole,
+        LocationRole
     };
 
     QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;