ui: Refactored context menu API, added file path actions in graph and code

* Add 'copy full path' and 'show containing folder' actions to graph view, code view
* Added file path to file node tooltip

bug id = 320
This commit is contained in:
Eberhard Graether
2017-01-26 21:54:57 +01:00
parent 4fc0785002
commit 2aa8c4c22c
11 changed files with 185 additions and 94 deletions
+2
View File
@@ -17,6 +17,7 @@
#include "utility/utilityString.h" #include "utility/utilityString.h"
#include "data/graph/token_component/TokenComponentAggregation.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/token_component/TokenComponentSignature.h"
#include "data/graph/Graph.h" #include "data/graph/Graph.h"
#include "data/location/TokenLocation.h" #include "data/location/TokenLocation.h"
@@ -1467,6 +1468,7 @@ void PersistentStorage::addNodesToGraph(const std::vector<Id>& nodeIds, Graph* g
NameHierarchy(filePath.fileName()), NameHierarchy(filePath.fileName()),
true true
); );
node->addComponentFilePath(std::make_shared<TokenComponentFilePath>(filePath));
node->setExplicit(true); node->setExplicit(true);
} }
else else
+10 -1
View File
@@ -569,7 +569,16 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event)
if (m_setIDECursorPositionAction != nullptr) if (m_setIDECursorPositionAction != nullptr)
{ {
m_eventPosition = event->pos(); m_eventPosition = event->pos();
QtContextMenu::getInstance()->showExtended(event, this, std::vector<QAction*>(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();
} }
} }
@@ -1,15 +1,11 @@
#include "qt/element/QtCodeFileTitleButton.h" #include "qt/element/QtCodeFileTitleButton.h"
#include <QApplication>
#include <QClipboard>
#include <QDesktopServices>
#include <QUrl>
#include "utility/file/FileSystem.h" #include "utility/file/FileSystem.h"
#include "utility/messaging/type/MessageActivateFile.h" #include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessageProjectEdit.h" #include "utility/messaging/type/MessageProjectEdit.h"
#include "Application.h" #include "Application.h"
#include "Project.h"
#include "qt/utility/QtContextMenu.h" #include "qt/utility/QtContextMenu.h"
#include "qt/utility/utilityQt.h" #include "qt/utility/utilityQt.h"
#include "settings/ColorScheme.h" #include "settings/ColorScheme.h"
@@ -26,16 +22,6 @@ QtCodeFileTitleButton::QtCodeFileTitleButton(QWidget* parent)
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed); setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
connect(this, SIGNAL(clicked()), this, SLOT(clickedTitle())); 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() QtCodeFileTitleButton::~QtCodeFileTitleButton()
@@ -45,6 +31,7 @@ QtCodeFileTitleButton::~QtCodeFileTitleButton()
void QtCodeFileTitleButton::setFilePath(const FilePath& filePath) void QtCodeFileTitleButton::setFilePath(const FilePath& filePath)
{ {
m_filePath = filePath; m_filePath = filePath;
setText("");
setText(filePath.fileName().c_str()); setText(filePath.fileName().c_str());
setToolTip(filePath.str().c_str()); setToolTip(filePath.str().c_str());
@@ -69,6 +56,7 @@ void QtCodeFileTitleButton::setModificationTime(const TimePoint modificationTime
void QtCodeFileTitleButton::setProject(const std::string& name) void QtCodeFileTitleButton::setProject(const std::string& name)
{ {
setText(name.c_str()); setText(name.c_str());
m_filePath = FilePath();
if (Application::getInstance()->isInTrial()) if (Application::getInstance()->isInTrial())
{ {
@@ -109,17 +97,25 @@ void QtCodeFileTitleButton::checkModification()
void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event) void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event)
{ {
QtContextMenu menu(event, this);
menu.addSeparator();
if (!m_filePath.empty()) if (!m_filePath.empty())
{ {
std::vector<QAction*> actions; menu.addFileActions(m_filePath);
actions.push_back(m_copyFullPathAction);
actions.push_back(m_openContainingFolderAction);
QtContextMenu::getInstance()->showExtended(event, this, actions);
} }
else if (text().size()) 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() void QtCodeFileTitleButton::clickedTitle()
@@ -133,23 +129,3 @@ void QtCodeFileTitleButton::clickedTitle()
MessageProjectEdit().dispatch(); 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());
}
}
@@ -26,14 +26,10 @@ protected:
private slots: private slots:
void clickedTitle(); void clickedTitle();
void copyFullPath();
void openContainingFolder();
private: private:
FilePath m_filePath; FilePath m_filePath;
TimePoint m_modificationTime; TimePoint m_modificationTime;
QAction* m_copyFullPathAction;
QAction* m_openContainingFolderAction;
}; };
#endif // QT_CODE_FILE_TITLE_BUTTON_H #endif // QT_CODE_FILE_TITLE_BUTTON_H
+25 -6
View File
@@ -219,11 +219,18 @@ void QtGraphicsView::wheelEvent(QWheelEvent* event)
void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event)
{ {
m_clipboardNodeName = ""; m_clipboardNodeName = "";
FilePath clipboardFilePath;
QtGraphNode* node = getNodeAtCursorPosition(); QtGraphNode* node = getNodeAtCursorPosition();
while (node) while (node)
{ {
if (dynamic_cast<QtGraphNodeData*>(node) || dynamic_cast<QtGraphNodeBundle*>(node)) QtGraphNodeData* dataNode = dynamic_cast<QtGraphNodeData*>(node);
if (dataNode)
{
m_clipboardNodeName = dataNode->getName();
clipboardFilePath = dataNode->getFilePath();
}
else if (dynamic_cast<QtGraphNodeBundle*>(node))
{ {
m_clipboardNodeName = node->getName(); m_clipboardNodeName = node->getName();
break; break;
@@ -231,14 +238,26 @@ void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event)
node = node->getParent(); node = node->getParent();
} }
std::vector<QAction*> actions; QtContextMenu menu(event, this);
actions.push_back(m_exportGraphAction); menu.addSeparator();
if (!m_clipboardNodeName.empty()) 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() void QtGraphicsView::updateTimer()
+2 -3
View File
@@ -1,13 +1,12 @@
#ifndef QT_GRAPHICS_VIEW_H #ifndef QT_GRAPHICS_VIEW_H
#define QT_GRAPHICS_VIEW_H #define QT_GRAPHICS_VIEW_H
#include <functional>
#include <memory> #include <memory>
#include <QGraphicsView> #include <QGraphicsView>
#include <memory> #include "utility/file/FilePath.h"
#include <functional>
class QTimer; class QTimer;
class QtGraphNode; class QtGraphNode;
+78 -31
View File
@@ -1,59 +1,83 @@
#include "qt/utility/QtContextMenu.h" #include "qt/utility/QtContextMenu.h"
#include <QMenu> #include <QApplication>
#include <QClipboard>
#include <QContextMenuEvent> #include <QContextMenuEvent>
#include <QDesktopServices>
#include <QUrl>
#include "utility/messaging/type/MessageRedo.h" #include "utility/messaging/type/MessageRedo.h"
#include "utility/messaging/type/MessageUndo.h" #include "utility/messaging/type/MessageUndo.h"
std::shared_ptr<QtContextMenu> 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) if (!s_instance)
{ {
s_instance = std::make_shared<QtContextMenu>(); 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_menu.addAction(action);
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()));
} }
void QtContextMenu::showDefault(QContextMenuEvent* event, QWidget* origin) void QtContextMenu::addUndoActions()
{ {
showExtended(event, origin, std::vector<QAction*>()); addAction(s_undoAction);
addAction(s_redoAction);
} }
void QtContextMenu::showExtended(QContextMenuEvent* event, QWidget* origin, const std::vector<QAction*>& actions) void QtContextMenu::addFileActions(FilePath filePath)
{ {
QMenu menu(origin); s_filePath = filePath;
menu.addAction(m_undoAction); addAction(s_copyFullPathAction);
menu.addAction(m_redoAction); addAction(s_openContainingFolderAction);
}
if (actions.size()) void QtContextMenu::addSeparator()
{ {
menu.addSeparator(); m_menu.addSeparator();
}
for (QAction* action : actions) void QtContextMenu::show()
{ {
menu.addAction(action); m_menu.exec(m_point);
}
}
menu.exec(event->globalPos());
} }
void QtContextMenu::undoActionTriggered() void QtContextMenu::undoActionTriggered()
@@ -65,3 +89,26 @@ void QtContextMenu::redoActionTriggered()
{ {
MessageRedo().dispatch(); 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()
{
}
+28 -8
View File
@@ -3,30 +3,50 @@
#include <memory> #include <memory>
#include <QAction> #include <QAction>
#include <QMenu>
#include <QObject> #include <QObject>
#include "utility/file/FilePath.h"
#include "utility/logging/logging.h"
class QtContextMenu class QtContextMenu
: public QObject : public QObject
{ {
Q_OBJECT Q_OBJECT
public: 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 addSeparator();
void showExtended(QContextMenuEvent* event, QWidget* origin, const std::vector<QAction*>& actions);
void show();
private slots: private slots:
void undoActionTriggered(); void undoActionTriggered();
void redoActionTriggered(); void redoActionTriggered();
private: void copyFullPathActionTriggered();
static std::shared_ptr<QtContextMenu> s_instance; void openContainingFolderActionTriggered();
QAction* m_undoAction; private:
QAction* m_redoAction; 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 #endif // QT_CONTEXT_MENU_H
@@ -6,6 +6,7 @@
#include "utility/messaging/type/MessageFocusOut.h" #include "utility/messaging/type/MessageFocusOut.h"
#include "utility/messaging/type/MessageGraphNodeMove.h" #include "utility/messaging/type/MessageGraphNodeMove.h"
#include "data/graph/token_component/TokenComponentFilePath.h"
#include "data/graph/token_component/TokenComponentSignature.h" #include "data/graph/token_component/TokenComponentSignature.h"
QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible, bool hasQualifier) 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(); toolTip += ": " + sig->getSignature();
} }
} }
else
{
FilePath path = getFilePath();
if (!path.empty())
{
toolTip += ": " + path.str();
}
}
this->setToolTip(QString::fromStdString(toolTip)); this->setToolTip(QString::fromStdString(toolTip));
} }
@@ -48,6 +57,16 @@ const Node* QtGraphNodeData::getData() const
return m_data; return m_data;
} }
FilePath QtGraphNodeData::getFilePath() const
{
if (m_data->isType(Node::NODE_FILE))
{
return m_data->getComponent<TokenComponentFilePath>()->getFilePath();
}
return FilePath();
}
bool QtGraphNodeData::isDataNode() const bool QtGraphNodeData::isDataNode() const
{ {
return true; return true;
@@ -1,6 +1,8 @@
#ifndef QT_GRAPH_NODE_DATA_H #ifndef QT_GRAPH_NODE_DATA_H
#define QT_GRAPH_NODE_DATA_H #define QT_GRAPH_NODE_DATA_H
#include "utility/file/FilePath.h"
#include "qt/view/graphElements/QtGraphNode.h" #include "qt/view/graphElements/QtGraphNode.h"
class QtGraphNodeData class QtGraphNodeData
@@ -11,6 +13,7 @@ public:
virtual ~QtGraphNodeData(); virtual ~QtGraphNodeData();
const Node* getData() const; const Node* getData() const;
FilePath getFilePath() const;
// QtGraphNode implementation // QtGraphNode implementation
virtual bool isDataNode() const; virtual bool isDataNode() const;
+2 -1
View File
@@ -272,7 +272,8 @@ void QtMainWindow::keyPressEvent(QKeyEvent* event)
void QtMainWindow::contextMenuEvent(QContextMenuEvent* event) void QtMainWindow::contextMenuEvent(QContextMenuEvent* event)
{ {
QtContextMenu::getInstance()->showDefault(event, this); QtContextMenu menu(event, this);
menu.show();
} }
void QtMainWindow::closeEvent(QCloseEvent* event) void QtMainWindow::closeEvent(QCloseEvent* event)