void GraphicalModelView::rowsInserted(const QModelIndex &parent, int start, int end) { const QPersistentModelIndex parentIndex = parent.sibling(parent.row(), 0); Id parentLogicalId = parentIndex.data(roles::logicalIdRole).value<Id>(); for (int row = start; row <= end; ++row) { const QPersistentModelIndex current = model()->index(row, 0, parent); const Id logicalId = current.data(roles::logicalIdRole).value<Id>(); if (parentLogicalId.isNull() || parentLogicalId.editor() != "MetaEditor" || logicalId.editor() != "MetaEditor") { parentLogicalId = Id::rootId(); } const QString name = current.data(Qt::DisplayRole).toString(); if (logicalId.isNull()) { // No logical Id for this item, so logical model shouldn't care // about it. continue; } // Add this element to a root for now. To be able to do something // useful, we need to establish a correspondence between logical // and graphical model hierarchy. It is not always easy since // some elements have no correspondences in another model, and tree // structures may be very different by themselves. LogicalModel * const logicalModel = static_cast<LogicalModel *>(mModel); const bool isEdge = mModel->editorManagerInterface().isNodeOrEdge(logicalId.editor(), logicalId.element()); ElementInfo elementInfo(logicalId, logicalId, parentLogicalId, Id(), {{"name", name}}, {}, Id(), isEdge); logicalModel->addElementToModel(elementInfo); } }
void SuggestToCreateDiagramWidget::addItem(Id const &editor, Id const &diagram) { EditorInterface *editorInterface = mMainWindow->manager()->editorInterface(editor.editor()); QString const diagramName = editorInterface->diagramName(diagram.diagram()); QString const diagramNodeName = editorInterface->diagramNodeName(diagram.diagram()); if (diagramNodeName.isEmpty()) { return; } ListWidget::addItem(diagramName , "qrm:/" + editor.editor() + "/" + diagram.diagram() + "/" + diagramNodeName , tr("editor: ") + editor.editor() + tr(", diagram: ") + diagram.diagram()); }
void RefactoringApplier::changeElementInModel(const Id &changeFromId, const Id &changeToId) { if (mLogicalModelApi.isLogicalId(changeFromId)) { return; } if (!refactoringElements.contains(changeToId.element())) { IdList const inLinks = mGraphicalModelApi.mutableGraphicalRepoApi().incomingLinks(changeFromId); IdList const outLinks = mGraphicalModelApi.mutableGraphicalRepoApi().outgoingLinks(changeFromId); Id const parentId = mGraphicalModelApi.mutableGraphicalRepoApi().parent(changeFromId); QVariant const position = mGraphicalModelApi.mutableGraphicalRepoApi().position(changeFromId); bool const isFromLogicalModel = false; QString const refactoringsMetamodel = "RefactoringsMetamodel"; QString newEditor = changeToId.editor(); newEditor.chop(refactoringsMetamodel.length()); Id const newId = Id(newEditor, changeToId.diagram(), changeToId.element(), QUuid::createUuid().toString()); Id const newElementId = mGraphicalModelApi.createElement(parentId, newId , isFromLogicalModel, "ololo", position.toPointF()); for (Id idLink : inLinks) { mGraphicalModelApi.mutableGraphicalRepoApi().setTo(idLink, newElementId); } for (Id idLink : outLinks) { mGraphicalModelApi.mutableGraphicalRepoApi().setFrom(idLink, newElementId); } mGraphicalModelApi.mutableGraphicalRepoApi().removeChild(parentId, changeFromId); mGraphicalModelApi.mutableGraphicalRepoApi().removeElement(changeFromId); } }
void Exploser::refreshPalette(gui::PaletteTreeWidget * const tree, Id const &diagram) { QList<QPair<QString, QList<gui::PaletteElement>>> groups; QMap<QString, QString> descriptions; descriptions[mUserGroupTitle] = mUserGroupDescription; IdList const childTypes = mApi.editorManagerInterface().elements(diagram); for (Id const &child : childTypes) { QList<Explosion> const explosions = mApi.editorManagerInterface().explosions(child); for (Explosion const &explosion : explosions) { if (!explosion.isReusable()) { continue; } Id const targetNodeOrGroup = explosion.target(); Id target; if (mApi.editorManagerInterface().isNodeOrEdge(targetNodeOrGroup.editor(), targetNodeOrGroup.element())) { target = targetNodeOrGroup; } else { Pattern const pattern = mApi.editorManagerInterface().getPatternByName(targetNodeOrGroup.element()); target = Id(targetNodeOrGroup.editor(), targetNodeOrGroup.diagram(), pattern.rootType()); } IdList const allTargets = mApi.logicalRepoApi().elementsByType(target.element(), true); QList<gui::PaletteElement> groupElements; for (Id const &targetInstance : allTargets) { if (mApi.isLogicalId(targetInstance)) { groupElements << gui::PaletteElement(child , mApi.logicalRepoApi().name(targetInstance) , QString(), mApi.editorManagerInterface().icon(child) , mApi.editorManagerInterface().iconSize(child) , targetInstance); } } if (!groupElements.isEmpty()) { groups << qMakePair(mUserGroupTitle, groupElements); } } } tree->addGroups(groups, descriptions, true, mApi.editorManagerInterface().friendlyName(diagram), true); }
void PaletteToolbox::addItemType(Id const &id, QString const &name, QString const &description, QIcon const &icon) { Id category(id.editor(), id.diagram()); QWidget *tab = mTabs[mCategories[category]]; Q_ASSERT(tab); DraggableElement *element = new DraggableElement(id, name, description, icon, this); tab->layout()->addWidget(element); }
TEST(IdsTest, gettersTest) { Id id = Id::loadFromString("qrm:/editor/diagram/element/id"); EXPECT_EQ(id.editor(), "editor"); EXPECT_EQ(id.diagram(), "diagram"); EXPECT_EQ(id.element(), "element"); EXPECT_EQ(id.id(), "id"); EXPECT_EQ(id.type() ,Id("editor", "diagram", "element")); }
Id LogicalModelAssistApi::createElement(const Id &parent, const Id &type) { Q_ASSERT(type.idSize() == 3); Q_ASSERT(parent.idSize() == 4); const Id newElementId = type.sameTypeId(); const QString elementFriendlyName = mModelsAssistApi.editorManagerInterface().friendlyName(type); const bool isEdge = mModelsAssistApi.editorManagerInterface().isNodeOrEdge( newElementId.editor(), newElementId.element()) == -1; ElementInfo newElement(newElementId, Id(), parent, Id(), {{"name", elementFriendlyName}}, {}, Id(), isEdge); mLogicalModel.addElementToModel(newElement); return newElementId; }
Id ModelsAssistApi::createElement(Id const &parent, Id const &id, Id const &logicalId , bool isFromLogicalModel, QString const &name, QPointF const &position) { Q_ASSERT(parent.idSize() == 4); Id newId = id; Id realLogicalId = logicalId; if (isFromLogicalModel) { realLogicalId = id; newId = Id(id.editor(), id.diagram(), id.element(), QUuid::createUuid().toString()); } mModel.addElementToModel(parent, newId, realLogicalId, name, position); return newId; }
SaveConvertionManager::GraphicalFilter SaveConvertionManager::graphicalRecreate( const SaveConvertionManager::GraphicalReplacer &replacer , const SaveConvertionManager::GraphicalConstructor &constructor) { return [replacer, constructor](const Id &block, GraphicalModelAssistInterface &graphicalApi) { // Just iterating throught the elements on some diagram, ignoring the diagram itself. if (isDiagramType(block)) { return false; } // For each element trying to find out what to replace it with. const Id newType = replacer(block, graphicalApi); if (newType.isNull()) { // Not every element be replaced, concrete implementation must decide it. return false; } // Then creating new element of some type... const Id newBlock = Id::createElementId(newType.editor(), newType.diagram(), newType.element()); graphicalApi.createElement(graphicalApi.parent(block) , newBlock , false , graphicalApi.name(block) , graphicalApi.position(block) , graphicalApi.logicalId(block)); // And initializing it... constructor(newBlock, block, graphicalApi); const bool isEdge = isEdgeType(block); if (isEdge) { // If out element is edge then connecting it to same elements as the old one was connected graphicalApi.setFrom(newBlock, graphicalApi.from(block)); graphicalApi.setTo(newBlock, graphicalApi.to(block)); } else { // Replacing old node in all incomming and outgoing edges of the old node with the new one. for (const Id &edge : graphicalApi.graphicalRepoApi().outgoingLinks(block)) { graphicalApi.mutableGraphicalRepoApi().setProperty(edge, "from", newBlock.toVariant()); } for (const Id &edge : graphicalApi.graphicalRepoApi().incomingLinks(block)) { graphicalApi.mutableGraphicalRepoApi().setProperty(edge, "to", newBlock.toVariant()); } } // And finally disposing of outdated entity. graphicalApi.removeElement(block); return true; }; }
void ExploserView::createAddExplosionMenu(const Element * const element , QMenu &contextMenu, QList<Explosion> const &explosions , const Id &alreadyConnectedElement) const { bool hasAnyActions = false; const QString menuName = alreadyConnectedElement.isNull() ? mCustomizer.addExplosionMenuName() : mCustomizer.changeExplosionMenuName(); QMenu *addExplosionMenu = new QMenu(menuName); for (const Explosion &explosion : explosions) { for (const Id &elementId : mLogicalApi.logicalRepoApi().logicalElements(explosion.target())) { if (alreadyConnectedElement == elementId) { continue; } QAction *action = addExplosionMenu->addAction(mLogicalApi.logicalRepoApi().name(elementId)); hasAnyActions = true; connect(action, SIGNAL(triggered()), SLOT(addExplosionActionTriggered())); QList<QVariant> tag; tag << element->logicalId().toVariant() << elementId.toVariant(); action->setData(tag); } } if (hasAnyActions) { addExplosionMenu->addSeparator(); } for (const Explosion &explosion : explosions) { const Id diagramType = mLogicalApi.editorManagerInterface().findElementByType(explosion.target().element()); const QString name = mLogicalApi.editorManagerInterface().friendlyName(diagramType); const QString editorName = mLogicalApi.editorManagerInterface().friendlyName(Id(diagramType.editor())); QAction *action = addExplosionMenu->addAction(tr("New ") + editorName + "/" + name); hasAnyActions = true; connect(action, SIGNAL(triggered()), SLOT(addExplosionActionTriggered())); action->setData(QVariantList() << element->logicalId().toVariant() << diagramType.toVariant()); } contextMenu.addMenu(addExplosionMenu); if (alreadyConnectedElement != Id()) { QAction * const gotoAction = contextMenu.addAction(mCustomizer.goToConnectedMenuName() , this, SLOT(goToActionTriggered())); gotoAction->setData(alreadyConnectedElement.toVariant()); } }
virtual QStringList callMethod( EditorManagerInterface *editorManagerInterface , const Id &editorId , const Id &diagramId , const Id &elementId , const QString &propertyName ) const { Q_UNUSED(elementId); Q_UNUSED(propertyName); const QString &editorName = editorId.editor(); const QString &diagramName = diagramId.diagram(); mResult = callFunction([editorManagerInterface, editorName, diagramName]() { return editorManagerInterface->elements(editorName, diagramName); }); return editorManagerInterface->elements(editorName, diagramName); }
virtual QStringList callMethod( EditorManagerInterface *editorManagerInterface , const Id &editorId , const Id &diagramId , const Id &elementId , const QString &propertyName ) const { Q_UNUSED(diagramId); Q_UNUSED(propertyName); const QString &editorName = editorId.editor(); const QString &elementName = elementId.element(); mResult = callFunction([editorManagerInterface, editorName, elementName]() { return editorManagerInterface->isNodeOrEdge(editorName, elementName); }); return ConvertingMethods::convertIntIntoStringList( editorManagerInterface->isNodeOrEdge(editorName, elementName)); }
bool Model::isDiagram(Id const &id) const { return ((id != ROOT_ID) && (id.element() == assistApi().editorManager().getEditorInterface(id.editor())->diagramNodeName(id.diagram()))); }
bool SaveConvertionManager::isRobotsDiagram(const Id &element) { const QStringList robotsDiagrams = { "RobotsDiagram", "SubprogramDiagram" }; return element.editor() == editor() && robotsDiagrams.contains(element.diagram()); }
CreateGroupCommand::CreateGroupCommand(models::LogicalModelAssistApi &logicalApi , models::GraphicalModelAssistApi &graphicalApi , models::Exploser &exploser , const Id &logicalParent , const Id &graphicalParent , const Id &id , bool isFromLogicalModel , const QPointF &position) : mLogicalApi(logicalApi) , mGraphicalApi(graphicalApi) , mExploser(exploser) , mLogicalParent(logicalParent) , mGraphicalParent(graphicalParent) , mId(id) , mIsFromLogicalModel(isFromLogicalModel) , mPosition(position) , mPattern(graphicalApi.editorManagerInterface().getPatternByName(id.element())) { const QPointF size = mPattern.size(); // Pattern nodes create may have hierarchic structure. So we must create them in correct order // (parent first, child after). Cycles in hierarchy and nodes with incorrect parent id are fully ignored QList<GroupNode> toCreate = mPattern.nodes(); QSet<QString> consideredNodes; QMap<QString, Id> createdNodesIds; // If group node has no parent then it has 'global' one createdNodesIds[QString()] = graphicalParent; bool somethingChangedThisIteration = true; while (!toCreate.isEmpty() && somethingChangedThisIteration) { somethingChangedThisIteration = false; for (const GroupNode &node : toCreate) { if (!node.parent.isEmpty() && !consideredNodes.contains(node.parent)) { continue; } const Id element(id.editor(), id.diagram(), node.type, QUuid::createUuid().toString()); createdNodesIds[node.id] = element; if (node.id == mPattern.rootNode()) { mRootId = element; } const QPointF nodePos(position.x() - size.x() / 2 + node.position.x() , position.y() + node.position.y()); CreateElementCommand *createNodeCommand = new CreateElementCommand( logicalApi, graphicalApi, exploser, logicalParent , createdNodesIds[node.parent], element, isFromLogicalModel , mLogicalApi.editorManagerInterface().friendlyName(element.type()), nodePos); mNodeCommands[node.id] = createNodeCommand; addPreAction(createNodeCommand); consideredNodes << node.id; toCreate.removeAll(node); somethingChangedThisIteration = true; } } // TODO: display here error if toCreate still non-empty for (const GroupEdge &edge : mPattern.edges()) { const Id element(id.editor(), id.diagram(), edge.type, QUuid::createUuid().toString()); CreateElementCommand *createEdgeCommand = new CreateElementCommand( logicalApi, graphicalApi, exploser, logicalParent, graphicalParent, element, isFromLogicalModel , mLogicalApi.editorManagerInterface().friendlyName(element.type()), QPointF()); mEdgeCommands.append(createEdgeCommand); addPreAction(createEdgeCommand); } }