diff options
author | Jochen Becher <jochen_becher@gmx.de> | 2017-12-22 18:37:50 +0100 |
---|---|---|
committer | Jochen Becher <jochen_becher@gmx.de> | 2018-01-09 14:21:35 +0000 |
commit | cdc5b9265b075b10c6a07dd231404104cd125946 (patch) | |
tree | eee842a8936f4144fd96704b4f513d118bdc433b /src/plugins/modeleditor | |
parent | e8b3b9b1e41d99e68c7b035fded7ddd93a0a46e5 (diff) |
ModelEditor: Implement Drag'n'Drop for most panes
Components and classes may be dragged and dropped not only from project
explorer but from any pane that allows to drag and drop a file.
Task-number: QTCREATORBUG-19117
Change-Id: I4c39e3771d37c0aed4b00204db0876e6b9093828
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'src/plugins/modeleditor')
-rw-r--r-- | src/plugins/modeleditor/classviewcontroller.cpp | 41 | ||||
-rw-r--r-- | src/plugins/modeleditor/classviewcontroller.h | 10 | ||||
-rw-r--r-- | src/plugins/modeleditor/componentviewcontroller.cpp | 27 | ||||
-rw-r--r-- | src/plugins/modeleditor/componentviewcontroller.h | 8 | ||||
-rw-r--r-- | src/plugins/modeleditor/editordiagramview.cpp | 27 | ||||
-rw-r--r-- | src/plugins/modeleditor/editordiagramview.h | 2 | ||||
-rw-r--r-- | src/plugins/modeleditor/pxnodecontroller.cpp | 99 | ||||
-rw-r--r-- | src/plugins/modeleditor/pxnodecontroller.h | 6 | ||||
-rw-r--r-- | src/plugins/modeleditor/pxnodeutilities.cpp | 12 | ||||
-rw-r--r-- | src/plugins/modeleditor/pxnodeutilities.h | 1 |
10 files changed, 125 insertions, 108 deletions
diff --git a/src/plugins/modeleditor/classviewcontroller.cpp b/src/plugins/modeleditor/classviewcontroller.cpp index 32cd3d1ac2c..ae8340d3115 100644 --- a/src/plugins/modeleditor/classviewcontroller.cpp +++ b/src/plugins/modeleditor/classviewcontroller.cpp @@ -38,7 +38,7 @@ ClassViewController::ClassViewController(QObject *parent) { } -QSet<QString> ClassViewController::findClassDeclarations(const QString &fileName) +QSet<QString> ClassViewController::findClassDeclarations(const QString &fileName, int line, int column) { QSet<QString> classNames; @@ -48,32 +48,39 @@ QSet<QString> ClassViewController::findClassDeclarations(const QString &fileName // scan original file CPlusPlus::Document::Ptr document = snapshot.document(fileName); if (!document.isNull()) - appendClassDeclarationsFromDocument(document, &classNames); + appendClassDeclarationsFromDocument(document, line, column, &classNames); - QString otherFileName = CppTools::correspondingHeaderOrSource(fileName); - - // scan other file - document = snapshot.document(otherFileName); - if (!document.isNull()) - appendClassDeclarationsFromDocument(document, &classNames); + if (line <= 0) { + QString otherFileName = CppTools::correspondingHeaderOrSource(fileName); + // scan other file + document = snapshot.document(otherFileName); + if (!document.isNull()) + appendClassDeclarationsFromDocument(document, -1, -1, &classNames); + } return classNames; } void ClassViewController::appendClassDeclarationsFromDocument(CPlusPlus::Document::Ptr document, - QSet<QString> *classNames) + int line, int column, + QSet<QString> *classNames) { - int total = document->globalSymbolCount(); - for (int i = 0; i < total; ++i) { + unsigned int total = document->globalSymbolCount(); + for (unsigned int i = 0; i < total; ++i) { CPlusPlus::Symbol *symbol = document->globalSymbolAt(i); - appendClassDeclarationsFromSymbol(symbol, classNames); + appendClassDeclarationsFromSymbol(symbol, line, column, classNames); } } void ClassViewController::appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *symbol, - QSet<QString> *classNames) + int line, int column, + QSet<QString> *classNames) { - if (symbol->isClass()) { + if (symbol->isClass() + && (line <= 0 + || (symbol->line() == static_cast<unsigned int>(line) + && symbol->column() == static_cast<unsigned int>(column + 1)))) + { CPlusPlus::Overview overview; QString className = overview.prettyName( CPlusPlus::LookupContext::fullyQualifiedName(symbol)); @@ -84,10 +91,10 @@ void ClassViewController::appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *s if (symbol->isScope()) { CPlusPlus::Scope *scope = symbol->asScope(); - int total = scope->memberCount(); - for (int i = 0; i < total; ++i) { + unsigned int total = scope->memberCount(); + for (unsigned int i = 0; i < total; ++i) { CPlusPlus::Symbol *member = scope->memberAt(i); - appendClassDeclarationsFromSymbol(member, classNames); + appendClassDeclarationsFromSymbol(member, line, column, classNames); } } } diff --git a/src/plugins/modeleditor/classviewcontroller.h b/src/plugins/modeleditor/classviewcontroller.h index f9534204523..bcae5d2c06d 100644 --- a/src/plugins/modeleditor/classviewcontroller.h +++ b/src/plugins/modeleditor/classviewcontroller.h @@ -41,10 +41,12 @@ public: explicit ClassViewController(QObject *parent = nullptr); ~ClassViewController() = default; - QSet<QString> findClassDeclarations(const QString &fileName); - void appendClassDeclarationsFromDocument(CPlusPlus::Document::Ptr document, - QSet<QString> *classNames); - void appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *symbol, QSet<QString> *classNames); + QSet<QString> findClassDeclarations(const QString &fileName, int line = -1, int column = -1); + +private: + void appendClassDeclarationsFromDocument(CPlusPlus::Document::Ptr document, int line, int column, + QSet<QString> *classNames); + void appendClassDeclarationsFromSymbol(CPlusPlus::Symbol *symbol, int line, int column, QSet<QString> *classNames); }; } // namespace Internal diff --git a/src/plugins/modeleditor/componentviewcontroller.cpp b/src/plugins/modeleditor/componentviewcontroller.cpp index b9fadc2bd1f..1c35e912021 100644 --- a/src/plugins/modeleditor/componentviewcontroller.cpp +++ b/src/plugins/modeleditor/componentviewcontroller.cpp @@ -385,12 +385,12 @@ void ComponentViewController::setDiagramSceneController(qmt::DiagramSceneControl d->diagramSceneController = diagramSceneController; } -void ComponentViewController::createComponentModel(const ProjectExplorer::FolderNode *folderNode, +void ComponentViewController::createComponentModel(const QString &filePath, qmt::MDiagram *diagram, - const QString anchorFolder) + const QString &anchorFolder) { d->diagramSceneController->modelController()->startResetModel(); - doCreateComponentModel(folderNode, diagram, anchorFolder); + doCreateComponentModel(filePath, diagram, anchorFolder); d->diagramSceneController->modelController()->finishResetModel(true); } @@ -404,13 +404,14 @@ void ComponentViewController::updateIncludeDependencies(qmt::MPackage *rootPacka d->diagramSceneController->modelController()->finishResetModel(true); } -void ComponentViewController::doCreateComponentModel(const ProjectExplorer::FolderNode *folderNode, qmt::MDiagram *diagram, const QString anchorFolder) +void ComponentViewController::doCreateComponentModel(const QString &filePath, qmt::MDiagram *diagram, const QString &anchorFolder) { - foreach (const ProjectExplorer::FileNode *fileNode, folderNode->fileNodes()) { - QString componentName = qmt::NameController::convertFileNameToElementName(fileNode->filePath().toString()); + for (const QString &fileName : QDir(filePath).entryList(QDir::Files)) { + QString file = filePath + "/" + fileName; + QString componentName = qmt::NameController::convertFileNameToElementName(file); qmt::MComponent *component = nullptr; bool isSource = false; - CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(fileNode->filePath().toString()); + CppTools::ProjectFile::Kind kind = CppTools::ProjectFile::classify(file); switch (kind) { case CppTools::ProjectFile::AmbiguousHeader: case CppTools::ProjectFile::CHeader: @@ -437,7 +438,7 @@ void ComponentViewController::doCreateComponentModel(const ProjectExplorer::Fold } if (component) { QStringList relativeElements = qmt::NameController::buildElementsPath( - d->pxnodeUtilities->calcRelativePath(fileNode, anchorFolder), false); + d->pxnodeUtilities->calcRelativePath(file, anchorFolder), false); if (d->pxnodeUtilities->findSameObject(relativeElements, component)) { delete component; } else { @@ -447,12 +448,10 @@ void ComponentViewController::doCreateComponentModel(const ProjectExplorer::Fold } } } - - foreach (const ProjectExplorer::FolderNode *subNode, folderNode->folderNodes()) - doCreateComponentModel(subNode, diagram, anchorFolder); - auto containerNode = dynamic_cast<const ProjectExplorer::ContainerNode *>(folderNode); - if (containerNode) - doCreateComponentModel(containerNode->rootProjectNode(), diagram, anchorFolder); + for (const QString &fileName : QDir(filePath).entryList(QDir::Dirs|QDir::NoDotAndDotDot)) { + QString file = filePath + "/" + fileName; + doCreateComponentModel(file, diagram, anchorFolder); + } } } // namespace Internal diff --git a/src/plugins/modeleditor/componentviewcontroller.h b/src/plugins/modeleditor/componentviewcontroller.h index a0a70b73b8b..98f4ac0ca6f 100644 --- a/src/plugins/modeleditor/componentviewcontroller.h +++ b/src/plugins/modeleditor/componentviewcontroller.h @@ -53,13 +53,13 @@ public: void setPxNodeUtilties(PxNodeUtilities *pxnodeUtilities); void setDiagramSceneController(qmt::DiagramSceneController *diagramSceneController); - void createComponentModel(const ProjectExplorer::FolderNode *folderNode, - qmt::MDiagram *diagram, const QString anchorFolder); + void createComponentModel(const QString &filePath, + qmt::MDiagram *diagram, const QString &anchorFolder); void updateIncludeDependencies(qmt::MPackage *rootPackage); private: - void doCreateComponentModel(const ProjectExplorer::FolderNode *folderNode, - qmt::MDiagram *diagram, const QString anchorFolder); + void doCreateComponentModel(const QString &filePath, + qmt::MDiagram *diagram, const QString &anchorFolder); ComponentViewControllerPrivate *d; }; diff --git a/src/plugins/modeleditor/editordiagramview.cpp b/src/plugins/modeleditor/editordiagramview.cpp index 5e2fe5b65e7..445ed2925ed 100644 --- a/src/plugins/modeleditor/editordiagramview.cpp +++ b/src/plugins/modeleditor/editordiagramview.cpp @@ -50,7 +50,9 @@ EditorDiagramView::EditorDiagramView(QWidget *parent) auto droputils = new Utils::DropSupport( this, [](QDropEvent *event, Utils::DropSupport *dropSupport) - -> bool { return dropSupport->isValueDrop(event); }); + -> bool { return dropSupport->isFileDrop(event) || dropSupport->isValueDrop(event); }); + connect(droputils, &Utils::DropSupport::filesDropped, + this, &EditorDiagramView::dropFiles); connect(droputils, &Utils::DropSupport::valuesDropped, this, &EditorDiagramView::dropProjectExplorerNodes); } @@ -78,16 +80,31 @@ void EditorDiagramView::wheelEvent(QWheelEvent *wheelEvent) void EditorDiagramView::dropProjectExplorerNodes(const QList<QVariant> &values, const QPoint &pos) { - foreach (const QVariant &value, values) { + for (const auto &value : values) { if (value.canConvert<ProjectExplorer::Node *>()) { auto node = value.value<ProjectExplorer::Node *>(); QPointF scenePos = mapToScene(pos); - d->pxNodeController->addExplorerNode( - node, diagramSceneModel()->findTopmostElement(scenePos), - scenePos, diagramSceneModel()->diagram()); + auto folderNode = dynamic_cast<ProjectExplorer::FolderNode *>(node); + if (folderNode) { + d->pxNodeController->addFileSystemEntry( + folderNode->filePath().toString(), -1, -1, + diagramSceneModel()->findTopmostElement(scenePos), + scenePos, diagramSceneModel()->diagram()); + } } } } +void EditorDiagramView::dropFiles(const QList<Utils::DropSupport::FileSpec> &files, const QPoint &pos) +{ + for (const auto &fileSpec : files) { + QPointF scenePos = mapToScene(pos); + d->pxNodeController->addFileSystemEntry( + fileSpec.filePath, fileSpec.line, fileSpec.column, + diagramSceneModel()->findTopmostElement(scenePos), + scenePos, diagramSceneModel()->diagram()); + } +} + } // namespace Internal } // namespace ModelEditor diff --git a/src/plugins/modeleditor/editordiagramview.h b/src/plugins/modeleditor/editordiagramview.h index 984445d68f0..5dd43b10944 100644 --- a/src/plugins/modeleditor/editordiagramview.h +++ b/src/plugins/modeleditor/editordiagramview.h @@ -26,6 +26,7 @@ #pragma once #include "qmt/diagram_widgets_ui/diagramview.h" +#include "utils/dropsupport.h" namespace ModelEditor { namespace Internal { @@ -54,6 +55,7 @@ protected: private: void dropProjectExplorerNodes(const QList<QVariant> &values, const QPoint &pos); + void dropFiles(const QList<Utils::DropSupport::FileSpec> &files, const QPoint &pos); EditorDiagramViewPrivate *d; }; diff --git a/src/plugins/modeleditor/pxnodecontroller.cpp b/src/plugins/modeleditor/pxnodecontroller.cpp index 61e2f36541b..bdbadae8a07 100644 --- a/src/plugins/modeleditor/pxnodecontroller.cpp +++ b/src/plugins/modeleditor/pxnodecontroller.cpp @@ -131,57 +131,41 @@ void PxNodeController::setAnchorFolder(const QString &anchorFolder) d->anchorFolder = anchorFolder; } -void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node, - qmt::DElement *topMostElementAtPos, const QPointF &pos, - qmt::MDiagram *diagram) +void PxNodeController::addFileSystemEntry(const QString &filePath, int line, int column, + qmt::DElement *topMostElementAtPos, const QPointF &pos, + qmt::MDiagram *diagram) { - QMT_ASSERT(node, return); QMT_ASSERT(diagram, return); - QString elementName = qmt::NameController::convertFileNameToElementName( - node->filePath().toString()); + QString elementName = qmt::NameController::convertFileNameToElementName(filePath); - switch (node->nodeType()) { - case ProjectExplorer::NodeType::File: - { - QStringList classNames = d->classViewController->findClassDeclarations( - node->filePath().toString()).toList(); + QFileInfo fileInfo(filePath); + if (fileInfo.exists() && fileInfo.isFile()) { auto menu = new QMenu; menu->addAction(new MenuAction(tr("Add Component %1").arg(elementName), elementName, MenuAction::TYPE_ADD_COMPONENT, menu)); - menu->addSeparator(); - int index = 0; - foreach (const QString &className, classNames) { - auto action = new MenuAction(tr("Add Class %1").arg(className), elementName, - MenuAction::TYPE_ADD_CLASS, index, menu); - action->className = className; - menu->addAction(action); - ++index; + QStringList classNames = d->classViewController->findClassDeclarations(filePath, line, column).toList(); + if (!classNames.empty()) { + menu->addSeparator(); + int index = 0; + foreach (const QString &className, classNames) { + auto action = new MenuAction(tr("Add Class %1").arg(className), elementName, + MenuAction::TYPE_ADD_CLASS, index, menu); + action->className = className; + menu->addAction(action); + ++index; + } } connect(menu, &QMenu::aboutToHide, menu, &QMenu::deleteLater); connect(menu, &QMenu::triggered, this, [=](QAction *action) { - // TODO potential risk if node, topMostElementAtPos or diagram is deleted in between - onMenuActionTriggered(static_cast<MenuAction *>(action), node, topMostElementAtPos, + // TODO potential risk if topMostElementAtPos or diagram is deleted in between + onMenuActionTriggered(static_cast<MenuAction *>(action), filePath, topMostElementAtPos, pos, diagram); }); menu->popup(QCursor::pos()); - break; - } - case ProjectExplorer::NodeType::Folder: - case ProjectExplorer::NodeType::VirtualFolder: - case ProjectExplorer::NodeType::Project: - { + } else if (fileInfo.exists() && fileInfo.isDir()) { + // ignore line and column QString stereotype; - switch (node->nodeType()) { - case ProjectExplorer::NodeType::VirtualFolder: - stereotype = "virtual folder"; - break; - case ProjectExplorer::NodeType::Project: - stereotype = "project"; - break; - default: - break; - } auto menu = new QMenu; auto action = new MenuAction(tr("Add Package %1").arg(elementName), elementName, MenuAction::TYPE_ADD_PACKAGE, menu); @@ -197,12 +181,10 @@ void PxNodeController::addExplorerNode(const ProjectExplorer::Node *node, menu->addAction(action); connect(menu, &QMenu::aboutToHide, menu, &QMenu::deleteLater); connect(menu, &QMenu::triggered, this, [=](QAction *action) { - onMenuActionTriggered(static_cast<MenuAction *>(action), node, topMostElementAtPos, + onMenuActionTriggered(static_cast<MenuAction *>(action), filePath, topMostElementAtPos, pos, diagram); }); menu->popup(QCursor::pos()); - break; - } } } @@ -273,7 +255,7 @@ qmt::MDiagram *PxNodeController::findDiagramForExplorerNode(const ProjectExplore } void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *action, - const ProjectExplorer::Node *node, + const QString &filePath, qmt::DElement *topMostElementAtPos, const QPointF &pos, qmt::MDiagram *diagram) { @@ -321,27 +303,22 @@ void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *actio package->setName(action->elementName); if (!action->packageStereotype.isEmpty()) package->setStereotypes(QStringList() << action->packageStereotype); - auto folderNode = dynamic_cast<const ProjectExplorer::FolderNode *>(node); - if (QTC_GUARD(folderNode)) { - d->diagramSceneController->modelController()->undoController()->beginMergeSequence(tr("Create Component Model")); - QStringList relativeElements = qmt::NameController::buildElementsPath( - d->pxnodeUtilities->calcRelativePath(folderNode, d->anchorFolder), true); - if (qmt::MObject *existingObject = d->pxnodeUtilities->findSameObject(relativeElements, package)) { - delete package; - package = dynamic_cast<qmt::MPackage *>(existingObject); - QMT_ASSERT(package, return); - d->diagramSceneController->addExistingModelElement(package->uid(), pos, diagram); - } else { - qmt::MPackage *requestedRootPackage = d->diagramSceneController->findSuitableParentPackage(topMostElementAtPos, diagram); - qmt::MPackage *bestParentPackage = d->pxnodeUtilities->createBestMatchingPackagePath(requestedRootPackage, relativeElements); - d->diagramSceneController->dropNewModelElement(package, bestParentPackage, pos, diagram); - } - d->componentViewController->createComponentModel(folderNode, diagram, d->anchorFolder); - d->componentViewController->updateIncludeDependencies(package); - d->diagramSceneController->modelController()->undoController()->endMergeSequence(); - } else { + d->diagramSceneController->modelController()->undoController()->beginMergeSequence(tr("Create Component Model")); + QStringList relativeElements = qmt::NameController::buildElementsPath( + d->pxnodeUtilities->calcRelativePath(filePath, d->anchorFolder), true); + if (qmt::MObject *existingObject = d->pxnodeUtilities->findSameObject(relativeElements, package)) { delete package; + package = dynamic_cast<qmt::MPackage *>(existingObject); + QMT_ASSERT(package, return); + d->diagramSceneController->addExistingModelElement(package->uid(), pos, diagram); + } else { + qmt::MPackage *requestedRootPackage = d->diagramSceneController->findSuitableParentPackage(topMostElementAtPos, diagram); + qmt::MPackage *bestParentPackage = d->pxnodeUtilities->createBestMatchingPackagePath(requestedRootPackage, relativeElements); + d->diagramSceneController->dropNewModelElement(package, bestParentPackage, pos, diagram); } + d->componentViewController->createComponentModel(filePath, diagram, d->anchorFolder); + d->componentViewController->updateIncludeDependencies(package); + d->diagramSceneController->modelController()->undoController()->endMergeSequence(); break; } } @@ -350,7 +327,7 @@ void PxNodeController::onMenuActionTriggered(PxNodeController::MenuAction *actio d->diagramSceneController->modelController()->undoController()->beginMergeSequence(tr("Drop Node")); qmt::MObject *parentForDiagram = nullptr; QStringList relativeElements = qmt::NameController::buildElementsPath( - d->pxnodeUtilities->calcRelativePath(node, d->anchorFolder), + d->pxnodeUtilities->calcRelativePath(filePath, d->anchorFolder), dynamic_cast<qmt::MPackage *>(newObject) != nullptr); if (qmt::MObject *existingObject = d->pxnodeUtilities->findSameObject(relativeElements, newObject)) { delete newObject; diff --git a/src/plugins/modeleditor/pxnodecontroller.h b/src/plugins/modeleditor/pxnodecontroller.h index 7f5d570a9ba..f6ea029652c 100644 --- a/src/plugins/modeleditor/pxnodecontroller.h +++ b/src/plugins/modeleditor/pxnodecontroller.h @@ -57,13 +57,13 @@ public: void setDiagramSceneController(qmt::DiagramSceneController *diagramSceneController); void setAnchorFolder(const QString &anchorFolder); - void addExplorerNode(const ProjectExplorer::Node *node, qmt::DElement *topMostElementAtPos, - const QPointF &pos, qmt::MDiagram *diagram); + void addFileSystemEntry(const QString &filePath, int line, int column, qmt::DElement *topMostElementAtPos, + const QPointF &pos, qmt::MDiagram *diagram); bool hasDiagramForExplorerNode(const ProjectExplorer::Node *node); qmt::MDiagram *findDiagramForExplorerNode(const ProjectExplorer::Node *node); private: - void onMenuActionTriggered(MenuAction *action, const ProjectExplorer::Node *node, + void onMenuActionTriggered(MenuAction *action, const QString &filePath, qmt::DElement *topMostElementAtPos, const QPointF &pos, qmt::MDiagram *diagram); diff --git a/src/plugins/modeleditor/pxnodeutilities.cpp b/src/plugins/modeleditor/pxnodeutilities.cpp index 34f830fb417..4deec764ccb 100644 --- a/src/plugins/modeleditor/pxnodeutilities.cpp +++ b/src/plugins/modeleditor/pxnodeutilities.cpp @@ -85,6 +85,18 @@ QString PxNodeUtilities::calcRelativePath(const ProjectExplorer::Node *node, return qmt::NameController::calcRelativePath(nodePath, anchorFolder); } +QString PxNodeUtilities::calcRelativePath(const QString &filePath, const QString &anchorFolder) +{ + QString path; + + QFileInfo fileInfo(filePath); + if (fileInfo.exists() && fileInfo.isFile()) + path = fileInfo.path(); + else + path = filePath; + return qmt::NameController::calcRelativePath(path, anchorFolder); +} + qmt::MPackage *PxNodeUtilities::createBestMatchingPackagePath( qmt::MPackage *suggestedParentPackage, const QStringList &relativeElements) { diff --git a/src/plugins/modeleditor/pxnodeutilities.h b/src/plugins/modeleditor/pxnodeutilities.h index fd620de63e9..d79079cfafd 100644 --- a/src/plugins/modeleditor/pxnodeutilities.h +++ b/src/plugins/modeleditor/pxnodeutilities.h @@ -51,6 +51,7 @@ public: void setDiagramSceneController(qmt::DiagramSceneController *diagramSceneController); QString calcRelativePath(const ProjectExplorer::Node *node, const QString &anchorFolder); + QString calcRelativePath(const QString &filePath, const QString &anchorFolder); qmt::MPackage *createBestMatchingPackagePath(qmt::MPackage *suggestedParentPackage, const QStringList &relativeElements); qmt::MObject *findSameObject(const QStringList &relativeElements, |