diff --git a/src/lib/data/PersistentStorage.cpp b/src/lib/data/PersistentStorage.cpp index aa17d4b1..efd7e332 100644 --- a/src/lib/data/PersistentStorage.cpp +++ b/src/lib/data/PersistentStorage.cpp @@ -17,6 +17,7 @@ #include "utility/utilityString.h" #include "data/graph/token_component/TokenComponentAggregation.h" +#include "data/graph/token_component/TokenComponentFilePath.h" #include "data/graph/token_component/TokenComponentSignature.h" #include "data/graph/Graph.h" #include "data/location/TokenLocation.h" @@ -1467,6 +1468,7 @@ void PersistentStorage::addNodesToGraph(const std::vector& nodeIds, Graph* g NameHierarchy(filePath.fileName()), true ); + node->addComponentFilePath(std::make_shared(filePath)); node->setExplicit(true); } else diff --git a/src/lib_gui/qt/element/QtCodeArea.cpp b/src/lib_gui/qt/element/QtCodeArea.cpp index dd8ffcb4..6189a99b 100644 --- a/src/lib_gui/qt/element/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/QtCodeArea.cpp @@ -569,7 +569,16 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event) if (m_setIDECursorPositionAction != nullptr) { m_eventPosition = event->pos(); - QtContextMenu::getInstance()->showExtended(event, this, std::vector(1, m_setIDECursorPositionAction)); + + QtContextMenu menu(event, this); + if (!m_locationFile->getFilePath().empty()) + { + menu.addSeparator(); + menu.addFileActions(m_locationFile->getFilePath()); + menu.addSeparator(); + menu.addAction(m_setIDECursorPositionAction); + } + menu.show(); } } diff --git a/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp b/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp index bb105388..2a24fbae 100644 --- a/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp +++ b/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp @@ -1,15 +1,11 @@ #include "qt/element/QtCodeFileTitleButton.h" -#include -#include -#include -#include - #include "utility/file/FileSystem.h" #include "utility/messaging/type/MessageActivateFile.h" #include "utility/messaging/type/MessageProjectEdit.h" #include "Application.h" +#include "Project.h" #include "qt/utility/QtContextMenu.h" #include "qt/utility/utilityQt.h" #include "settings/ColorScheme.h" @@ -26,16 +22,6 @@ QtCodeFileTitleButton::QtCodeFileTitleButton(QWidget* parent) setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed); connect(this, SIGNAL(clicked()), this, SLOT(clickedTitle())); - - m_copyFullPathAction = new QAction(tr("Copy Full Path"), this); - m_copyFullPathAction->setStatusTip(tr("Copies the path of this file to the clipboard")); - m_copyFullPathAction->setToolTip(tr("Copies the path of this file to the clipboard")); - connect(m_copyFullPathAction, SIGNAL(triggered()), this, SLOT(copyFullPath())); - - m_openContainingFolderAction = new QAction(tr("Open Containing Folder"), this); - m_openContainingFolderAction->setStatusTip(tr("Opens the folder that contains this file")); - m_openContainingFolderAction->setToolTip(tr("Opens the folder that contains this file")); - connect(m_openContainingFolderAction, SIGNAL(triggered()), this, SLOT(openContainingFolder())); } QtCodeFileTitleButton::~QtCodeFileTitleButton() @@ -45,6 +31,7 @@ QtCodeFileTitleButton::~QtCodeFileTitleButton() void QtCodeFileTitleButton::setFilePath(const FilePath& filePath) { m_filePath = filePath; + setText(""); setText(filePath.fileName().c_str()); setToolTip(filePath.str().c_str()); @@ -69,6 +56,7 @@ void QtCodeFileTitleButton::setModificationTime(const TimePoint modificationTime void QtCodeFileTitleButton::setProject(const std::string& name) { setText(name.c_str()); + m_filePath = FilePath(); if (Application::getInstance()->isInTrial()) { @@ -109,17 +97,25 @@ void QtCodeFileTitleButton::checkModification() void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event) { + QtContextMenu menu(event, this); + menu.addSeparator(); + if (!m_filePath.empty()) { - std::vector actions; - actions.push_back(m_copyFullPathAction); - actions.push_back(m_openContainingFolderAction); - QtContextMenu::getInstance()->showExtended(event, this, actions); + menu.addFileActions(m_filePath); } else if (text().size()) { - QPushButton::contextMenuEvent(event); + Project* currentProject = Application::getInstance()->getCurrentProject().get(); + if (!currentProject) + { + return; + } + + menu.addFileActions(currentProject->getProjectSettingsFilePath()); } + + menu.show(); } void QtCodeFileTitleButton::clickedTitle() @@ -133,23 +129,3 @@ void QtCodeFileTitleButton::clickedTitle() MessageProjectEdit().dispatch(); } } - -void QtCodeFileTitleButton::copyFullPath() -{ - const std::string pathString = (QSysInfo::windowsVersion() != QSysInfo::WV_None) ? m_filePath.getBackslashedString() : m_filePath.str(); - QApplication::clipboard()->setText(pathString.c_str()); -} - -void QtCodeFileTitleButton::openContainingFolder() -{ - FilePath dir = m_filePath.parentDirectory(); - if (dir.exists()) - { - QDesktopServices::openUrl(QUrl(("file:///" + dir.str()).c_str(), QUrl::TolerantMode)); - } - else - { - LOG_ERROR("Unable to open directory: " + dir.str()); - } -} - diff --git a/src/lib_gui/qt/element/QtCodeFileTitleButton.h b/src/lib_gui/qt/element/QtCodeFileTitleButton.h index 502becc5..f88b73d4 100644 --- a/src/lib_gui/qt/element/QtCodeFileTitleButton.h +++ b/src/lib_gui/qt/element/QtCodeFileTitleButton.h @@ -26,14 +26,10 @@ protected: private slots: void clickedTitle(); - void copyFullPath(); - void openContainingFolder(); private: FilePath m_filePath; TimePoint m_modificationTime; - QAction* m_copyFullPathAction; - QAction* m_openContainingFolderAction; }; #endif // QT_CODE_FILE_TITLE_BUTTON_H diff --git a/src/lib_gui/qt/graphics/QtGraphicsView.cpp b/src/lib_gui/qt/graphics/QtGraphicsView.cpp index 1fd18431..46bfd447 100644 --- a/src/lib_gui/qt/graphics/QtGraphicsView.cpp +++ b/src/lib_gui/qt/graphics/QtGraphicsView.cpp @@ -219,11 +219,18 @@ void QtGraphicsView::wheelEvent(QWheelEvent* event) void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) { m_clipboardNodeName = ""; + FilePath clipboardFilePath; QtGraphNode* node = getNodeAtCursorPosition(); while (node) { - if (dynamic_cast(node) || dynamic_cast(node)) + QtGraphNodeData* dataNode = dynamic_cast(node); + if (dataNode) + { + m_clipboardNodeName = dataNode->getName(); + clipboardFilePath = dataNode->getFilePath(); + } + else if (dynamic_cast(node)) { m_clipboardNodeName = node->getName(); break; @@ -231,14 +238,26 @@ void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) node = node->getParent(); } - std::vector actions; - actions.push_back(m_exportGraphAction); - if (!m_clipboardNodeName.empty()) + QtContextMenu menu(event, this); + menu.addSeparator(); + menu.addAction(m_exportGraphAction); + + if (!m_clipboardNodeName.empty() || !clipboardFilePath.empty()) { - actions.push_back(m_copyNodeNameAction); + menu.addSeparator(); } - QtContextMenu::getInstance()->showExtended(event, this, actions); + if (!m_clipboardNodeName.empty()) + { + menu.addAction(m_copyNodeNameAction); + } + + if (!clipboardFilePath.empty()) + { + menu.addFileActions(clipboardFilePath); + } + + menu.show(); } void QtGraphicsView::updateTimer() diff --git a/src/lib_gui/qt/graphics/QtGraphicsView.h b/src/lib_gui/qt/graphics/QtGraphicsView.h index 4d5761a3..8e9d5503 100644 --- a/src/lib_gui/qt/graphics/QtGraphicsView.h +++ b/src/lib_gui/qt/graphics/QtGraphicsView.h @@ -1,13 +1,12 @@ #ifndef QT_GRAPHICS_VIEW_H #define QT_GRAPHICS_VIEW_H +#include #include #include -#include - -#include +#include "utility/file/FilePath.h" class QTimer; class QtGraphNode; diff --git a/src/lib_gui/qt/utility/QtContextMenu.cpp b/src/lib_gui/qt/utility/QtContextMenu.cpp index 99645e63..489a9582 100644 --- a/src/lib_gui/qt/utility/QtContextMenu.cpp +++ b/src/lib_gui/qt/utility/QtContextMenu.cpp @@ -1,59 +1,83 @@ #include "qt/utility/QtContextMenu.h" -#include +#include +#include #include +#include +#include #include "utility/messaging/type/MessageRedo.h" #include "utility/messaging/type/MessageUndo.h" -std::shared_ptr QtContextMenu::s_instance; +QtContextMenu* QtContextMenu::s_instance; -QtContextMenu* QtContextMenu::getInstance() +QAction* QtContextMenu::s_undoAction; +QAction* QtContextMenu::s_redoAction; + +QAction* QtContextMenu::s_copyFullPathAction; +QAction* QtContextMenu::s_openContainingFolderAction; + +FilePath QtContextMenu::s_filePath; + +QtContextMenu::QtContextMenu(QContextMenuEvent* event, QWidget* origin) + : m_menu(origin) + , m_point(event->globalPos()) { if (!s_instance) { - s_instance = std::make_shared(); + s_instance = new QtContextMenu(); + + s_undoAction = new QAction(tr("Back"), s_instance); + s_undoAction->setStatusTip(tr("Go back to last active symbol")); + s_undoAction->setToolTip(tr("Go back to last active symbol")); + connect(s_undoAction, SIGNAL(triggered()), s_instance, SLOT(undoActionTriggered())); + + s_redoAction = new QAction(tr("Forward"), s_instance); + s_redoAction->setStatusTip(tr("Go forward to next active symbol")); + s_redoAction->setToolTip(tr("Go forward to next active symbol")); + connect(s_redoAction, SIGNAL(triggered()), s_instance, SLOT(redoActionTriggered())); + + s_copyFullPathAction = new QAction(tr("Copy Full Path"), s_instance); + s_copyFullPathAction->setStatusTip(tr("Copies the path of this file to the clipboard")); + s_copyFullPathAction->setToolTip(tr("Copies the path of this file to the clipboard")); + connect(s_copyFullPathAction, SIGNAL(triggered()), s_instance, SLOT(copyFullPathActionTriggered())); + + s_openContainingFolderAction = new QAction(tr("Open Containing Folder"), s_instance); + s_openContainingFolderAction->setStatusTip(tr("Opens the folder that contains this file")); + s_openContainingFolderAction->setToolTip(tr("Opens the folder that contains this file")); + connect(s_openContainingFolderAction, SIGNAL(triggered()), s_instance, SLOT(openContainingFolderActionTriggered())); } - return s_instance.get(); + addUndoActions(); } -QtContextMenu::QtContextMenu() +void QtContextMenu::addAction(QAction* action) { - m_undoAction = new QAction(tr("Back"), this); - m_undoAction->setStatusTip(tr("Go back to last active symbol")); - m_undoAction->setToolTip(tr("Go back to last active symbol")); - connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undoActionTriggered())); - - m_redoAction = new QAction(tr("Forward"), this); - m_redoAction->setStatusTip(tr("Go forward to next active symbol")); - m_redoAction->setToolTip(tr("Go forward to next active symbol")); - connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redoActionTriggered())); + m_menu.addAction(action); } -void QtContextMenu::showDefault(QContextMenuEvent* event, QWidget* origin) +void QtContextMenu::addUndoActions() { - showExtended(event, origin, std::vector()); + addAction(s_undoAction); + addAction(s_redoAction); } -void QtContextMenu::showExtended(QContextMenuEvent* event, QWidget* origin, const std::vector& actions) +void QtContextMenu::addFileActions(FilePath filePath) { - QMenu menu(origin); + s_filePath = filePath; - menu.addAction(m_undoAction); - menu.addAction(m_redoAction); + addAction(s_copyFullPathAction); + addAction(s_openContainingFolderAction); +} - if (actions.size()) - { - menu.addSeparator(); +void QtContextMenu::addSeparator() +{ + m_menu.addSeparator(); +} - for (QAction* action : actions) - { - menu.addAction(action); - } - } - - menu.exec(event->globalPos()); +void QtContextMenu::show() +{ + m_menu.exec(m_point); } void QtContextMenu::undoActionTriggered() @@ -65,3 +89,26 @@ void QtContextMenu::redoActionTriggered() { MessageRedo().dispatch(); } + +void QtContextMenu::copyFullPathActionTriggered() +{ + const std::string pathString = (QSysInfo::windowsVersion() != QSysInfo::WV_None) ? s_filePath.getBackslashedString() : s_filePath.str(); + QApplication::clipboard()->setText(pathString.c_str()); +} + +void QtContextMenu::openContainingFolderActionTriggered() +{ + FilePath dir = s_filePath.parentDirectory(); + if (dir.exists()) + { + QDesktopServices::openUrl(QUrl(("file:///" + dir.str()).c_str(), QUrl::TolerantMode)); + } + else + { + LOG_ERROR("Unable to open directory: " + dir.str()); + } +} + +QtContextMenu::QtContextMenu() +{ +} diff --git a/src/lib_gui/qt/utility/QtContextMenu.h b/src/lib_gui/qt/utility/QtContextMenu.h index ccc1b01a..e5be6781 100644 --- a/src/lib_gui/qt/utility/QtContextMenu.h +++ b/src/lib_gui/qt/utility/QtContextMenu.h @@ -3,30 +3,50 @@ #include #include +#include #include +#include "utility/file/FilePath.h" +#include "utility/logging/logging.h" + class QtContextMenu : public QObject { Q_OBJECT public: - static QtContextMenu* getInstance(); + QtContextMenu(QContextMenuEvent* event, QWidget* origin); - QtContextMenu(); + void addAction(QAction* action); + void addUndoActions(); + void addFileActions(FilePath filePath); - void showDefault(QContextMenuEvent* event, QWidget* origin); - void showExtended(QContextMenuEvent* event, QWidget* origin, const std::vector& actions); + void addSeparator(); + + void show(); private slots: void undoActionTriggered(); void redoActionTriggered(); -private: - static std::shared_ptr s_instance; + void copyFullPathActionTriggered(); + void openContainingFolderActionTriggered(); - QAction* m_undoAction; - QAction* m_redoAction; +private: + QtContextMenu(); + + static QtContextMenu* s_instance; + + static QAction* s_undoAction; + static QAction* s_redoAction; + + static QAction* s_copyFullPathAction; + static QAction* s_openContainingFolderAction; + + static FilePath s_filePath; + + QMenu m_menu; + QPoint m_point; }; #endif // QT_CONTEXT_MENU_H diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp index de5d55b2..f78c355b 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp @@ -6,6 +6,7 @@ #include "utility/messaging/type/MessageFocusOut.h" #include "utility/messaging/type/MessageGraphNodeMove.h" +#include "data/graph/token_component/TokenComponentFilePath.h" #include "data/graph/token_component/TokenComponentSignature.h" QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible, bool hasQualifier) @@ -35,6 +36,14 @@ QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool toolTip += ": " + sig->getSignature(); } } + else + { + FilePath path = getFilePath(); + if (!path.empty()) + { + toolTip += ": " + path.str(); + } + } this->setToolTip(QString::fromStdString(toolTip)); } @@ -48,6 +57,16 @@ const Node* QtGraphNodeData::getData() const return m_data; } +FilePath QtGraphNodeData::getFilePath() const +{ + if (m_data->isType(Node::NODE_FILE)) + { + return m_data->getComponent()->getFilePath(); + } + + return FilePath(); +} + bool QtGraphNodeData::isDataNode() const { return true; diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h index b92f3b95..cd741340 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h @@ -1,6 +1,8 @@ #ifndef QT_GRAPH_NODE_DATA_H #define QT_GRAPH_NODE_DATA_H +#include "utility/file/FilePath.h" + #include "qt/view/graphElements/QtGraphNode.h" class QtGraphNodeData @@ -11,6 +13,7 @@ public: virtual ~QtGraphNodeData(); const Node* getData() const; + FilePath getFilePath() const; // QtGraphNode implementation virtual bool isDataNode() const; diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp index 1814e75d..f9a1753d 100644 --- a/src/lib_gui/qt/window/QtMainWindow.cpp +++ b/src/lib_gui/qt/window/QtMainWindow.cpp @@ -272,7 +272,8 @@ void QtMainWindow::keyPressEvent(QKeyEvent* event) void QtMainWindow::contextMenuEvent(QContextMenuEvent* event) { - QtContextMenu::getInstance()->showDefault(event, this); + QtContextMenu menu(event, this); + menu.show(); } void QtMainWindow::closeEvent(QCloseEvent* event)