diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp index fddac8d5851..7b75d792708 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.cpp @@ -46,6 +46,8 @@ #include "qmt/model/mdiagram.h" #include "qmt/model/mrelation.h" +#include + namespace qmt { class DiagramController::Clone @@ -166,6 +168,7 @@ private: emit diagramController->endUpdateElement(row, diagram); } diagramController->diagramModified(diagram); + diagramController->verifyDiagramsIntegrity(); } DiagramController::UpdateAction m_updateAction = DiagramController::UpdateMajor; @@ -208,6 +211,7 @@ protected: } if (removed) diagramController->diagramModified(diagram); + diagramController->verifyDiagramsIntegrity(); } void insert() @@ -227,6 +231,7 @@ protected: } if (inserted) diagramController->diagramModified(diagram); + diagramController->verifyDiagramsIntegrity(); } QList m_clonedElements; @@ -398,6 +403,7 @@ void DiagramController::addElement(DElement *element, MDiagram *diagram) diagram->addDiagramElement(element); emit endInsertElement(row, diagram); diagramModified(diagram); + verifyDiagramsIntegrity(); } void DiagramController::removeElement(DElement *element, MDiagram *diagram) @@ -413,6 +419,7 @@ void DiagramController::removeElement(DElement *element, MDiagram *diagram) diagram->removeDiagramElement(element); emit endRemoveElement(row, diagram); diagramModified(diagram); + verifyDiagramsIntegrity(); } DElement *DiagramController::findElement(const Uid &key, const MDiagram *diagram) const @@ -452,6 +459,7 @@ void DiagramController::finishUpdateElement(DElement *element, MDiagram *diagram emit endUpdateElement(diagram->diagramElements().indexOf(element), diagram); if (!cancelled) diagramModified(diagram); + verifyDiagramsIntegrity(); } void DiagramController::breakUndoChain() @@ -540,6 +548,7 @@ void DiagramController::pasteElements(const DContainer &diagramContainer, MDiagr diagramModified(diagram); if (m_undoController) m_undoController->endMergeSequence(); + verifyDiagramsIntegrity(); } void DiagramController::deleteElements(const DSelection &diagramSelection, MDiagram *diagram) @@ -570,6 +579,7 @@ void DiagramController::onEndResetModel() updateElementFromModel(element, diagram, false); } emit endResetAllDiagrams(); + verifyDiagramsIntegrity(); } void DiagramController::onBeginUpdateObject(int row, const MObject *parent) @@ -601,6 +611,7 @@ void DiagramController::onEndUpdateObject(int row, const MObject *parent) } } } + verifyDiagramsIntegrity(); } void DiagramController::onBeginInsertObject(int row, const MObject *owner) @@ -618,6 +629,7 @@ void DiagramController::onEndInsertObject(int row, const MObject *owner) QMT_CHECK(!m_allDiagrams.contains(modelDiagram)); m_allDiagrams.append(modelDiagram); } + verifyDiagramsIntegrity(); } void DiagramController::onBeginRemoveObject(int row, const MObject *parent) @@ -654,6 +666,7 @@ void DiagramController::onEndMoveObject(int row, const MObject *owner) updateElementFromModel(diagramElement, modelDiagram, false); emit endResetDiagram(modelDiagram); } + verifyDiagramsIntegrity(); } void DiagramController::onBeginUpdateRelation(int row, const MObject *owner) @@ -673,6 +686,7 @@ void DiagramController::onEndUpdateRelation(int row, const MObject *owner) updateElementFromModel(relation, diagram, true); } } + verifyDiagramsIntegrity(); } void DiagramController::onBeginRemoveRelation(int row, const MObject *owner) @@ -733,6 +747,7 @@ void DiagramController::deleteElements(const DSelection &diagramSelection, MDiag diagramModified(diagram); if (m_undoController) m_undoController->endMergeSequence(); + verifyDiagramsIntegrity(); } DElement *DiagramController::findElementOnAnyDiagram(const Uid &uid) @@ -772,6 +787,7 @@ void DiagramController::removeObjects(MObject *modelObject) removeElement(element, diagram); } } + verifyDiagramsIntegrity(); } void DiagramController::removeRelations(MRelation *modelRelation) @@ -781,6 +797,7 @@ void DiagramController::removeRelations(MRelation *modelRelation) if (diagramElement) removeElement(diagramElement, diagram); } + verifyDiagramsIntegrity(); } void DiagramController::removeRelations(DElement *element, MDiagram *diagram) @@ -795,6 +812,7 @@ void DiagramController::removeRelations(DElement *element, MDiagram *diagram) } } } + verifyDiagramsIntegrity(); } } @@ -847,6 +865,7 @@ void DiagramController::updateElementFromModel(DElement *element, const MDiagram } else { melement->accept(&visitor); } + verifyDiagramsIntegrity(); } void DiagramController::diagramModified(MDiagram *diagram) @@ -897,4 +916,51 @@ void DiagramController::updateAllDiagramsList() } } +void DiagramController::verifyDiagramsIntegrity() +{ + static const bool debugDiagramsIntegrity = false; + if (debugDiagramsIntegrity) { + QList allDiagrams; + if (m_modelController && m_modelController->rootPackage()) { + FindDiagramsVisitor visitor(&allDiagrams); + m_modelController->rootPackage()->accept(&visitor); + } + QMT_CHECK(allDiagrams == m_allDiagrams); + foreach (const MDiagram *diagram, allDiagrams) + verifyDiagramIntegrity(diagram); + } +} + +void DiagramController::verifyDiagramIntegrity(const MDiagram *diagram) +{ + QHash delementsMap; + foreach (const DElement *delement, diagram->diagramElements()) { + delementsMap.insert(delement->uid(), delement); + if (dynamic_cast(delement) != 0 || dynamic_cast(delement) != 0) { + QMT_CHECK(delement->modelUid().isValid()); + QMT_CHECK(m_modelController->findElement(delement->modelUid()) != 0); + if (!delement->modelUid().isValid() || m_modelController->findElement(delement->modelUid()) == 0) { + if (const DObject *dobject = dynamic_cast(delement)) + qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": object" << dobject->name() << dobject->uid().toString() << "has invalid reference to model element."; + else if (const DRelation *drelation = dynamic_cast(delement)) + qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": relation" << drelation->uid().toString() << "has invalid refeference to model element."; + } + } else { + QMT_CHECK(!delement->modelUid().isValid()); + } + } + foreach (const DElement *delement, diagram->diagramElements()) { + if (const DRelation *drelation = dynamic_cast(delement)) { + QMT_CHECK(drelation->endAUid().isValid()); + QMT_CHECK(delementsMap.contains(drelation->endAUid())); + if (!drelation->endAUid().isValid() || !delementsMap.contains(drelation->endAUid())) + qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": relation" << drelation->uid().toString() << "has invalid end A."; + QMT_CHECK(drelation->endBUid().isValid()); + QMT_CHECK(delementsMap.contains(drelation->endBUid())); + if (!drelation->endBUid().isValid() || !delementsMap.contains(drelation->endBUid())) + qWarning() << "Diagram" << diagram->name() << diagram->uid().toString() << ": relation" << drelation->uid().toString() << "has invalid end B."; + } + } +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h index 4199208e535..24675e79714 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h +++ b/src/libs/modelinglib/qmt/diagram_controller/diagramcontroller.h @@ -163,6 +163,9 @@ private: void updateAllDiagramsList(); + void verifyDiagramsIntegrity(); + void verifyDiagramIntegrity(const MDiagram *diagram); + ModelController *m_modelController; UndoController *m_undoController; QList m_allDiagrams; diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp index d898e287dd0..33ed331de2b 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp @@ -814,7 +814,7 @@ void DiagramSceneModel::onSelectionChanged() QMT_CHECK(endBObject); QGraphicsItem *endBItem = m_elementToItemMap.value(endBObject); QMT_CHECK(endBItem); - if (!relationItem->isSelected() + if (relationItem && !relationItem->isSelected() && (m_selectedItems.contains(endAItem) || newSecondarySelectedItems.contains(endAItem)) && (m_selectedItems.contains(endBItem) || newSecondarySelectedItems.contains(endBItem))) { QMT_CHECK(!m_selectedItems.contains(relationItem)); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp index caa54576e35..338c57595b6 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp @@ -68,14 +68,17 @@ public: { DObject *baseObject = m_diagramSceneModel->diagramController()->findElement(inheritance->base(), m_diagramSceneModel->diagram()); QMT_CHECK(baseObject); - bool baseIsInterface = baseObject->stereotypes().contains(QStringLiteral("interface")); + bool baseIsInterface = false; bool lollipopDisplay = false; - if (baseIsInterface) { - StereotypeDisplayVisitor stereotypeDisplayVisitor; - stereotypeDisplayVisitor.setModelController(m_diagramSceneModel->diagramSceneController()->modelController()); - stereotypeDisplayVisitor.setStereotypeController(m_diagramSceneModel->stereotypeController()); - baseObject->accept(&stereotypeDisplayVisitor); - lollipopDisplay = stereotypeDisplayVisitor.stereotypeDisplay() == DObject::StereotypeIcon; + if (baseObject) { + baseIsInterface = baseObject->stereotypes().contains(QStringLiteral("interface")); + if (baseIsInterface) { + StereotypeDisplayVisitor stereotypeDisplayVisitor; + stereotypeDisplayVisitor.setModelController(m_diagramSceneModel->diagramSceneController()->modelController()); + stereotypeDisplayVisitor.setStereotypeController(m_diagramSceneModel->stereotypeController()); + baseObject->accept(&stereotypeDisplayVisitor); + lollipopDisplay = stereotypeDisplayVisitor.stereotypeDisplay() == DObject::StereotypeIcon; + } } if (lollipopDisplay) { m_arrow->setShaft(ArrowItem::ShaftSolid); @@ -484,7 +487,8 @@ QPointF RelationItem::calcEndPoint(const Uid &end, const Uid &otherEnd, int near } else { DObject *endOtherObject = m_diagramSceneModel->diagramController()->findElement(otherEnd, m_diagramSceneModel->diagram()); QMT_CHECK(endOtherObject); - otherEndPos = endOtherObject->pos(); + if (endOtherObject) + otherEndPos = endOtherObject->pos(); } return calcEndPoint(end, otherEndPos, nearestIntermediatePointIndex); }