diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp index a794de55a76..00688013593 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp @@ -487,7 +487,7 @@ DContainer DiagramController::copyElements(const DSelection &diagramSelection, c return copiedElements; } -void DiagramController::pasteElements(const DContainer &diagramContainer, MDiagram *diagram) +void DiagramController::pasteElements(const DReferences &diagramContainer, MDiagram *diagram) { QMT_ASSERT(diagram, return); diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h index aa09636e5e3..e84cec69209 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h +++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h @@ -120,7 +120,7 @@ public: DContainer cutElements(const DSelection &diagramSelection, MDiagram *diagram); DContainer copyElements(const DSelection &diagramSelection, const MDiagram *diagram); - void pasteElements(const DContainer &diagramContainer, MDiagram *diagram); + void pasteElements(const DReferences &diagramContainer, MDiagram *diagram); void deleteElements(const DSelection &diagramSelection, MDiagram *diagram); private: diff --git a/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp b/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp index 009e16d2d15..19db9ed5194 100644 --- a/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp +++ b/src/libs/modelinglib/qmt/document_controller/documentcontroller.cpp @@ -35,7 +35,6 @@ #include "qmt/diagram_ui/diagramsmanager.h" #include "qmt/diagram_ui/sceneinspector.h" #include "qmt/model_controller/mcontainer.h" -#include "qmt/model_controller/modelcontroller.h" #include "qmt/model_controller/mselection.h" #include "qmt/model/mcanvasdiagram.h" #include "qmt/model/mclass.h" @@ -70,9 +69,7 @@ DocumentController::DocumentController(QObject *parent) : m_treeModel(new TreeModel(this)), m_sortedTreeModel(new SortedTreeModel(this)), m_diagramsManager(new DiagramsManager(this)), - m_sceneInspector(new SceneInspector(this)), - m_modelClipboard(new MContainer()), - m_diagramClipboard(new DContainer()) + m_sceneInspector(new SceneInspector(this)) { // project controller connect(m_projectController, &ProjectController::changed, this, &DocumentController::changed); @@ -135,44 +132,30 @@ DocumentController::~DocumentController() delete m_projectController; } -bool DocumentController::isModelClipboardEmpty() const -{ - return m_modelClipboard->isEmpty(); -} - -bool DocumentController::isDiagramClipboardEmpty() const -{ - return m_diagramClipboard->isEmpty(); -} - bool DocumentController::hasDiagramSelection(const MDiagram *diagram) const { return m_diagramsManager->diagramSceneModel(diagram)->hasSelection(); } -void DocumentController::cutFromModel(const MSelection &selection) +MContainer DocumentController::cutFromModel(const MSelection &selection) { - *m_modelClipboard = m_modelController->cutElements(selection); - emit modelClipboardChanged(isModelClipboardEmpty()); + return m_modelController->cutElements(selection); } -void DocumentController::cutFromDiagram(MDiagram *diagram) +DContainer DocumentController::cutFromDiagram(MDiagram *diagram) { - *m_diagramClipboard = m_diagramController->cutElements(m_diagramsManager->diagramSceneModel(diagram)->selectedElements(), diagram); - emit diagramClipboardChanged(isDiagramClipboardEmpty()); + return m_diagramController->cutElements(m_diagramsManager->diagramSceneModel(diagram)->selectedElements(), diagram); } -void DocumentController::copyFromModel(const MSelection &selection) +MContainer DocumentController::copyFromModel(const MSelection &selection) { - *m_modelClipboard = m_modelController->copyElements(selection); - emit modelClipboardChanged(isModelClipboardEmpty()); + return m_modelController->copyElements(selection); } -void DocumentController::copyFromDiagram(const qmt::MDiagram *diagram) +DContainer DocumentController::copyFromDiagram(const qmt::MDiagram *diagram) { m_diagramsManager->diagramSceneModel(diagram)->copyToClipboard(); - *m_diagramClipboard = m_diagramController->copyElements(m_diagramsManager->diagramSceneModel(diagram)->selectedElements(), diagram); - emit diagramClipboardChanged(isDiagramClipboardEmpty()); + return m_diagramController->copyElements(m_diagramsManager->diagramSceneModel(diagram)->selectedElements(), diagram); } void DocumentController::copyDiagram(const MDiagram *diagram) @@ -180,15 +163,15 @@ void DocumentController::copyDiagram(const MDiagram *diagram) m_diagramsManager->diagramSceneModel(diagram)->copyToClipboard(); } -void DocumentController::pasteIntoModel(MObject *modelObject) +void DocumentController::pasteIntoModel(MObject *modelObject, const MReferences &container, ModelController::PasteOption option) { if (modelObject) - m_modelController->pasteElements(modelObject, *m_modelClipboard); + m_modelController->pasteElements(modelObject, container, option); } -void DocumentController::pasteIntoDiagram(MDiagram *diagram) +void DocumentController::pasteIntoDiagram(MDiagram *diagram, const DReferences &container) { - m_diagramController->pasteElements(*m_diagramClipboard, diagram); + m_diagramController->pasteElements(container, diagram); } void DocumentController::deleteFromModel(const MSelection &selection) diff --git a/src/libs/modelinglib/qmt/document_controller/documentcontroller.h b/src/libs/modelinglib/qmt/document_controller/documentcontroller.h index 6b4eea96760..e6e0f9dca6b 100644 --- a/src/libs/modelinglib/qmt/document_controller/documentcontroller.h +++ b/src/libs/modelinglib/qmt/document_controller/documentcontroller.h @@ -27,12 +27,12 @@ #include #include "qmt/infrastructure/qmt_global.h" +#include "qmt/model_controller/modelcontroller.h" namespace qmt { class ProjectController; class UndoController; -class ModelController; class DiagramController; class DiagramSceneController; class StyleController; @@ -49,6 +49,7 @@ class MDiagram; class MCanvasDiagram; class MContainer; class DContainer; +class DReferences; class MSelection; class MObject; @@ -61,8 +62,6 @@ public: signals: void changed(); - void modelClipboardChanged(bool isEmpty); - void diagramClipboardChanged(bool isEmpty); public: ProjectController *projectController() const { return m_projectController; } @@ -78,17 +77,15 @@ public: DiagramsManager *diagramsManager() const { return m_diagramsManager; } SceneInspector *sceneInspector() const { return m_sceneInspector; } - bool isModelClipboardEmpty() const; - bool isDiagramClipboardEmpty() const; bool hasDiagramSelection(const qmt::MDiagram *diagram) const; - void cutFromModel(const MSelection &selection); - void cutFromDiagram(MDiagram *diagram); - void copyFromModel(const MSelection &selection); - void copyFromDiagram(const MDiagram *diagram); + MContainer cutFromModel(const MSelection &selection); + DContainer cutFromDiagram(MDiagram *diagram); + MContainer copyFromModel(const MSelection &selection); + DContainer copyFromDiagram(const MDiagram *diagram); void copyDiagram(const MDiagram *diagram); - void pasteIntoModel(MObject *modelObject); - void pasteIntoDiagram(MDiagram *diagram); + void pasteIntoModel(MObject *modelObject, const MReferences &container, ModelController::PasteOption option); + void pasteIntoDiagram(MDiagram *diagram, const DReferences &container); void deleteFromModel(const MSelection &selection); void deleteFromDiagram(MDiagram *diagram); void removeFromDiagram(MDiagram *diagram); @@ -118,8 +115,6 @@ private: SortedTreeModel *m_sortedTreeModel = nullptr; DiagramsManager *m_diagramsManager = nullptr; SceneInspector *m_sceneInspector = nullptr; - QScopedPointer m_modelClipboard; - QScopedPointer m_diagramClipboard; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp b/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp index fc3072da27f..ff74d61ff33 100644 --- a/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp +++ b/src/libs/modelinglib/qmt/model_controller/modelcontroller.cpp @@ -604,16 +604,24 @@ void ModelController::setUndoController(UndoController *undoController) m_undoController = undoController; } +Uid ModelController::ownerKey(const Uid &key) const +{ + MElement *element = findElement(key); + if (!element) + return Uid::invalidUid(); + return ownerKey(element); +} + Uid ModelController::ownerKey(const MElement *element) const { QMT_ASSERT(element, return Uid()); MObject *owner = element->owner(); if (!owner) - return Uid(); + return Uid::invalidUid(); return owner->uid(); } -MElement *ModelController::findElement(const Uid &key) +MElement *ModelController::findElement(const Uid &key) const { if (MObject *object = findObject(key)) return object; @@ -915,17 +923,20 @@ MContainer ModelController::copyElements(const MSelection &modelSelection) return copiedElements; } -void ModelController::pasteElements(MObject *owner, const MContainer &modelContainer) +void ModelController::pasteElements(MObject *owner, const MReferences &modelContainer, PasteOption option) { // clone all elements and renew their keys QHash renewedKeys; QList clonedElements; foreach (MElement *element, modelContainer.elements()) { - MCloneDeepVisitor visitor; - element->accept(&visitor); - MElement *clonedElement = visitor.cloned(); - renewElementKey(clonedElement, &renewedKeys); - clonedElements.append(clonedElement); + if (option == PasteAlwaysWithNewKeys || option == PasteAlwaysAndKeepKeys || !findElement(element->uid())) { + MCloneDeepVisitor visitor; + element->accept(&visitor); + MElement *clonedElement = visitor.cloned(); + if (option == PasteAlwaysWithNewKeys || (option == PasteAlwaysAndKeepKeys && findElement(element->uid()))) + renewElementKey(clonedElement, &renewedKeys); + clonedElements.append(clonedElement); + } } // fix all keys referencing between pasting elements foreach (MElement *clonedElement, clonedElements) diff --git a/src/libs/modelinglib/qmt/model_controller/modelcontroller.h b/src/libs/modelinglib/qmt/model_controller/modelcontroller.h index 345d5c0ce98..5b95d2a575b 100644 --- a/src/libs/modelinglib/qmt/model_controller/modelcontroller.h +++ b/src/libs/modelinglib/qmt/model_controller/modelcontroller.h @@ -61,6 +61,13 @@ class QMT_EXPORT ModelController : public QObject class MoveRelationCommand; public: + + enum PasteOption { + PasteAlwaysWithNewKeys, + PasteAlwaysAndKeepKeys, + PasteOnlyNewElements + }; + explicit ModelController(QObject *parent = nullptr); ~ModelController() override; @@ -93,8 +100,9 @@ public: UndoController *undoController() const { return m_undoController; } void setUndoController(UndoController *undoController); + Uid ownerKey(const Uid &key) const; Uid ownerKey(const MElement *element) const; - MElement *findElement(const Uid &key); + MElement *findElement(const Uid &key) const; template T *findElement(const Uid &key) { return dynamic_cast(findElement(key)); } @@ -124,7 +132,7 @@ public: MContainer cutElements(const MSelection &modelSelection); MContainer copyElements(const MSelection &modelSelection); - void pasteElements(MObject *owner, const MContainer &modelContainer); + void pasteElements(MObject *owner, const MReferences &modelContainer, PasteOption option); void deleteElements(const MSelection &modelSelection); private: diff --git a/src/plugins/modeleditor/modeleditor.cpp b/src/plugins/modeleditor/modeleditor.cpp index dba9416a4a9..6af7b79e3c3 100644 --- a/src/plugins/modeleditor/modeleditor.cpp +++ b/src/plugins/modeleditor/modeleditor.cpp @@ -42,6 +42,8 @@ #include "qmt/controller/undocontroller.h" #include "qmt/diagram/dpackage.h" #include "qmt/diagram_controller/diagramcontroller.h" +#include "qmt/diagram_controller/dcontainer.h" +#include "qmt/diagram_controller/dreferences.h" #include "qmt/diagram_controller/dselection.h" #include "qmt/diagram_scene/diagramscenemodel.h" #include "qmt/diagram_ui/diagram_mime_types.h" @@ -51,6 +53,8 @@ #include "qmt/model/mcomponent.h" #include "qmt/model/mcanvasdiagram.h" #include "qmt/model_controller/modelcontroller.h" +#include "qmt/model_controller/mcontainer.h" +#include "qmt/model_controller/mreferences.h" #include "qmt/model_controller/mselection.h" #include "qmt/model_ui/treemodel.h" #include "qmt/model_ui/treemodelmanager.h" @@ -390,7 +394,7 @@ void ModelEditor::initDocument() d->modelTreeViewServant->setTreeModel(documentController->treeModel()); - connect(documentController, &qmt::DocumentController::diagramClipboardChanged, + connect(ModelEditorPlugin::modelsManager(), &ModelsManager::diagramClipboardChanged, this, &ModelEditor::onDiagramClipboardChanged, Qt::QueuedConnection); connect(documentController->undoController()->undoStack(), &QUndoStack::canUndoChanged, this, &ModelEditor::onCanUndoChanged, Qt::QueuedConnection); @@ -459,15 +463,16 @@ void ModelEditor::redo() void ModelEditor::cut() { ExtDocumentController *documentController = d->document->documentController(); + ModelsManager *modelsManager = ModelEditorPlugin::modelsManager(); switch (d->selectedArea) { case SelectedArea::Nothing: break; case SelectedArea::Diagram: - documentController->cutFromDiagram(currentDiagram()); + setDiagramClipboard(documentController->cutFromDiagram(currentDiagram())); break; case SelectedArea::TreeView: - documentController->cutFromModel(d->modelTreeViewServant->selectedObjects()); + modelsManager->setModelClipboard(documentController, documentController->cutFromModel(d->modelTreeViewServant->selectedObjects())); break; } } @@ -475,18 +480,19 @@ void ModelEditor::cut() void ModelEditor::copy() { ExtDocumentController *documentController = d->document->documentController(); + ModelsManager *modelsManager = ModelEditorPlugin::modelsManager(); switch (d->selectedArea) { case SelectedArea::Nothing: break; case SelectedArea::Diagram: if (documentController->hasDiagramSelection(currentDiagram())) - documentController->copyFromDiagram(currentDiagram()); + setDiagramClipboard(documentController->copyFromDiagram(currentDiagram())); else documentController->copyDiagram(currentDiagram()); break; case SelectedArea::TreeView: - documentController->copyFromModel(d->modelTreeViewServant->selectedObjects()); + modelsManager->setModelClipboard(documentController, documentController->copyFromModel(d->modelTreeViewServant->selectedObjects())); break; } } @@ -494,15 +500,20 @@ void ModelEditor::copy() void ModelEditor::paste() { ExtDocumentController *documentController = d->document->documentController(); + ModelsManager *modelsManager = ModelEditorPlugin::modelsManager(); switch (d->selectedArea) { case SelectedArea::Nothing: break; case SelectedArea::Diagram: - documentController->pasteIntoDiagram(currentDiagram()); + // on cut/copy diagram and model elements were copied. + documentController->pasteIntoModel(currentDiagram(), modelsManager->modelClipboard(), qmt::ModelController::PasteOnlyNewElements); + documentController->pasteIntoDiagram(currentDiagram(), modelsManager->diagramClipboard()); break; case SelectedArea::TreeView: - documentController->pasteIntoModel(d->modelTreeViewServant->selectedObject()); + documentController->pasteIntoModel(d->modelTreeViewServant->selectedObject(), modelsManager->modelClipboard(), + documentController == modelsManager->modelClipboardDocumentController() + ? qmt::ModelController::PasteAlwaysWithNewKeys : qmt::ModelController::PasteAlwaysAndKeepKeys); break; } } @@ -656,6 +667,7 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea) d->selectedArea = selectedArea; qmt::DocumentController *documentController = d->document->documentController(); + ModelsManager *modelsManager = ModelEditorPlugin::modelsManager(); bool canCutCopyDelete = false; bool canRemove = false; bool canPaste = false; @@ -680,7 +692,7 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea) bool hasSelection = documentController->diagramsManager()->diagramSceneModel(activeDiagram)->hasSelection(); canCutCopyDelete = hasSelection; canRemove = hasSelection; - canPaste = !documentController->isDiagramClipboardEmpty(); + canPaste = !modelsManager->isDiagramClipboardEmpty(); canSelectAll = !activeDiagram->diagramElements().isEmpty(); canCopyDiagram = !hasSelection; canExportDiagram = true; @@ -705,7 +717,7 @@ void ModelEditor::updateSelectedArea(SelectedArea selectedArea) bool hasSelection = !d->modelTreeViewServant->selectedObjects().isEmpty(); bool hasSingleSelection = d->modelTreeViewServant->selectedObjects().indices().size() == 1; canCutCopyDelete = hasSelection && !d->modelTreeViewServant->isRootPackageSelected(); - canPaste = hasSingleSelection && !documentController->isModelClipboardEmpty(); + canPaste = hasSingleSelection && !modelsManager->isModelClipboardEmpty(); canSelectAll = activeDiagram && !activeDiagram->diagramElements().isEmpty(); canExportDiagram = activeDiagram != nullptr; QModelIndexList indexes = d->modelTreeView->selectedSourceModelIndexes(); @@ -1224,6 +1236,20 @@ void ModelEditor::onContentSet() expandModelTreeToDepth(0); } +void ModelEditor::setDiagramClipboard(const qmt::DContainer &dcontainer) +{ + ExtDocumentController *documentController = d->document->documentController(); + qmt::ModelController *modelController = documentController->modelController(); + qmt::MSelection modelSelection; + for (const auto &delement : dcontainer.elements()) { + qmt::Uid melementUid = delement->modelUid(); + qmt::Uid mownerUid = modelController->ownerKey(melementUid); + modelSelection.append(melementUid, mownerUid); + } + qmt::MContainer mcontainer = modelController->copyElements(modelSelection); + ModelEditorPlugin::modelsManager()->setDiagramClipboard(documentController, dcontainer, mcontainer); +} + void ModelEditor::addDiagramToSelector(const qmt::MDiagram *diagram) { QString diagramLabel = buildDiagramLabel(diagram); diff --git a/src/plugins/modeleditor/modeleditor.h b/src/plugins/modeleditor/modeleditor.h index 3fdeb8d1d9c..ed7eed431f7 100644 --- a/src/plugins/modeleditor/modeleditor.h +++ b/src/plugins/modeleditor/modeleditor.h @@ -41,6 +41,7 @@ class MElement; class MPackage; class MDiagram; class DElement; +class DContainer; class DocumentController; } @@ -140,6 +141,8 @@ private: void onContentSet(); + void setDiagramClipboard(const qmt::DContainer &dcontainer); + void addDiagramToSelector(const qmt::MDiagram *diagram); void updateDiagramSelector(); void onDiagramSelectorSelected(int index); diff --git a/src/plugins/modeleditor/modelsmanager.cpp b/src/plugins/modeleditor/modelsmanager.cpp index 89d691ddc6e..683006817de 100644 --- a/src/plugins/modeleditor/modelsmanager.cpp +++ b/src/plugins/modeleditor/modelsmanager.cpp @@ -34,10 +34,14 @@ #include "pxnodecontroller.h" #include "qmt/config/configcontroller.h" +#include "qmt/diagram_controller/dcontainer.h" +#include "qmt/diagram_controller/dreferences.h" #include "qmt/diagram_scene/diagramscenemodel.h" #include "qmt/diagram_ui/diagramsmanager.h" #include "qmt/model/mdiagram.h" #include "qmt/model_controller/modelcontroller.h" +#include "qmt/model_controller/mcontainer.h" +#include "qmt/model_controller/mreferences.h" #include "qmt/project_controller/projectcontroller.h" #include "qmt/project/project.h" #include "qmt/stereotype/stereotypecontroller.h" @@ -91,6 +95,11 @@ public: ModelIndexer *modelIndexer = nullptr; QList documentsToBeClosed; + ExtDocumentController *modelClipboardDocumentController = nullptr; + qmt::MContainer modelClipboard; + ExtDocumentController *diagramClipboardDocumentController = nullptr; + qmt::DContainer diagramClipboard; + QAction *openDiagramContextMenuItem = nullptr; ProjectExplorer::Node *contextMenuOwnerNode = nullptr; }; @@ -142,6 +151,10 @@ ExtDocumentController *ModelsManager::createModel(ModelDocument *modelDocument) void ModelsManager::releaseModel(ExtDocumentController *documentController) { + if (documentController == d->modelClipboardDocumentController) + d->modelClipboardDocumentController = nullptr; + if (documentController == d->diagramClipboardDocumentController) + d->diagramClipboardDocumentController = nullptr; for (int i = 0; i < d->managedModels.size(); ++i) { ManagedModel *managedModel = &d->managedModels[i]; if (managedModel->m_documentController == documentController) { @@ -165,6 +178,55 @@ void ModelsManager::openDiagram(const qmt::Uid &modelUid, const qmt::Uid &diagra } } +bool ModelsManager::isModelClipboardEmpty() const +{ + return d->modelClipboard.isEmpty(); +} + +ExtDocumentController *ModelsManager::modelClipboardDocumentController() const +{ + return d->modelClipboardDocumentController; +} + +qmt::MReferences ModelsManager::modelClipboard() const +{ + qmt::MReferences clipboard; + clipboard.setElements(d->modelClipboard.elements()); + return clipboard; +} + +void ModelsManager::setModelClipboard(ExtDocumentController *documentController, const qmt::MContainer &container) +{ + d->modelClipboardDocumentController = documentController; + d->modelClipboard = container; + emit modelClipboardChanged(isModelClipboardEmpty()); +} + +bool ModelsManager::isDiagramClipboardEmpty() const +{ + return d->diagramClipboard.isEmpty(); +} + +ExtDocumentController *ModelsManager::diagramClipboardDocumentController() const +{ + return d->diagramClipboardDocumentController; +} + +qmt::DReferences ModelsManager::diagramClipboard() const +{ + qmt::DReferences clipboard; + clipboard.setElements(d->diagramClipboard.elements()); + return clipboard; +} + +void ModelsManager::setDiagramClipboard(ExtDocumentController *documentController, const qmt::DContainer &dcontainer, const qmt::MContainer &mcontainer) +{ + setModelClipboard(documentController, mcontainer); + d->diagramClipboardDocumentController = documentController; + d->diagramClipboard = dcontainer; + emit diagramClipboardChanged(isDiagramClipboardEmpty()); +} + void ModelsManager::onAboutToShowContextMenu(ProjectExplorer::Project *project, ProjectExplorer::Node *node) { diff --git a/src/plugins/modeleditor/modelsmanager.h b/src/plugins/modeleditor/modelsmanager.h index 09b1e290551..71972203503 100644 --- a/src/plugins/modeleditor/modelsmanager.h +++ b/src/plugins/modeleditor/modelsmanager.h @@ -36,6 +36,10 @@ namespace qmt { class Uid; class MDiagram; class DiagramsViewInterface; +class MContainer; +class MReferences; +class DContainer; +class DReferences; } namespace ModelEditor { @@ -56,10 +60,26 @@ public: explicit ModelsManager(QObject *parent = nullptr); ~ModelsManager(); +signals: + void modelClipboardChanged(bool isEmpty); + void diagramClipboardChanged(bool isEmpty); + +public: ExtDocumentController *createModel(ModelDocument *modelDocument); void releaseModel(ExtDocumentController *documentController); void openDiagram(const qmt::Uid &modelUid, const qmt::Uid &diagramUid); + bool isModelClipboardEmpty() const; + ExtDocumentController *modelClipboardDocumentController() const; + qmt::MReferences modelClipboard() const; + void setModelClipboard(ExtDocumentController *documentController, const qmt::MContainer &container); + + bool isDiagramClipboardEmpty() const; + ExtDocumentController *diagramClipboardDocumentController() const; + qmt::DReferences diagramClipboard() const; + void setDiagramClipboard(ExtDocumentController *documentController, const qmt::DContainer &dcontainer, + const qmt::MContainer &mcontainer); + private: void onAboutToShowContextMenu(ProjectExplorer::Project *project, ProjectExplorer::Node *node); void onOpenDiagramFromProjectExplorer();