File indexing completed on 2024-05-19 05:42:24

0001 // ct_lvtqtc_undo_add_edge.cpp                                       -*-C++-*-
0002 
0003 /*
0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk>
0005 // SPDX-License-Identifier: Apache-2.0
0006 //
0007 // Licensed under the Apache License, Version 2.0 (the "License");
0008 // you may not use this file except in compliance with the License.
0009 // You may obtain a copy of the License at
0010 //
0011 //     http://www.apache.org/licenses/LICENSE-2.0
0012 //
0013 // Unless required by applicable law or agreed to in writing, software
0014 // distributed under the License is distributed on an "AS IS" BASIS,
0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0016 // See the License for the specific language governing permissions and
0017 // limitations under the License.
0018 */
0019 
0020 #include <ct_lvtqtc_undo_add_edge.h>
0021 
0022 #include <ct_lvtqtc_graphicsscene.h>
0023 #include <ct_lvtqtc_graphicsview.h>
0024 #include <ct_lvtqtc_isa.h>
0025 #include <ct_lvtqtc_lakosentity.h>
0026 
0027 #include <ct_lvtldr_lakosiannode.h>
0028 #include <ct_lvtldr_nodestorage.h>
0029 #include <ct_lvtldr_typenode.h>
0030 #include <ct_lvtshr_graphenums.h>
0031 
0032 #include <QDebug>
0033 #include <QPointF>
0034 
0035 using namespace Codethink::lvtqtc;
0036 using Codethink::lvtshr::LakosRelationType;
0037 
0038 struct UndoAddEdge::Private {
0039     std::string fromQualifiedName;
0040     std::string toQualifiedName;
0041     lvtshr::LakosRelationType relationType;
0042     QtcUtil::UndoActionType undoActionType;
0043     lvtldr::NodeStorage& nodeStorage;
0044 };
0045 
0046 UndoAddEdge::UndoAddEdge(std::string fromQualifiedName,
0047                          std::string toQualifiedName,
0048                          lvtshr::LakosRelationType relationType,
0049                          QtcUtil::UndoActionType undoActionType,
0050                          lvtldr::NodeStorage& nodeStorage,
0051                          QUndoCommand *parent):
0052     QUndoCommand(parent),
0053     d(std::make_unique<UndoAddEdge::Private>(
0054         Private{std::move(fromQualifiedName), std::move(toQualifiedName), relationType, undoActionType, nodeStorage}))
0055 {
0056     setText(
0057         QObject::tr("Undo %1 relationship").arg(undoActionType == QtcUtil::UndoActionType::e_Add ? "Add" : "Remove"));
0058 }
0059 
0060 UndoAddEdge::~UndoAddEdge() = default;
0061 
0062 namespace {
0063 
0064 using namespace Codethink::lvtldr;
0065 
0066 std::pair<LakosianNode *, LakosianNode *>
0067 findNodes(NodeStorage& storage, const std::string& fromStr, const std::string& toStr)
0068 {
0069     using Codethink::lvtshr::DiagramType;
0070 
0071     LakosianNode *from = storage.findByQualifiedName(DiagramType::PackageType, fromStr);
0072     LakosianNode *to = storage.findByQualifiedName(DiagramType::PackageType, toStr);
0073     if (!from || !to) {
0074         from = storage.findByQualifiedName(DiagramType::ComponentType, fromStr);
0075         to = storage.findByQualifiedName(DiagramType::ComponentType, toStr);
0076     }
0077     if (!from || !to) {
0078         from = storage.findByQualifiedName(DiagramType::ClassType, fromStr);
0079         to = storage.findByQualifiedName(DiagramType::ClassType, toStr);
0080     }
0081 
0082     assert(from && to);
0083     return {from, to};
0084 }
0085 
0086 void removeRelationship(std::unique_ptr<UndoAddEdge::Private>& d)
0087 {
0088     auto [from, to] = findNodes(d->nodeStorage, d->fromQualifiedName, d->toQualifiedName);
0089 
0090     auto isPhysicalDependency = d->relationType == LakosRelationType::PackageDependency;
0091     if (isPhysicalDependency) {
0092         d->nodeStorage.removePhysicalDependency(from, to).expect("");
0093     }
0094 
0095     auto isLogicalRelation = d->relationType == LakosRelationType::IsA
0096         || d->relationType == LakosRelationType::UsesInTheInterface
0097         || d->relationType == LakosRelationType::UsesInTheImplementation;
0098     if (isLogicalRelation) {
0099         d->nodeStorage
0100             .removeLogicalRelation(dynamic_cast<TypeNode *>(from), dynamic_cast<TypeNode *>(to), d->relationType)
0101             .expect("Unexpected undo/redo error: Remove logical relation failed");
0102     }
0103 }
0104 
0105 void addRelationship(std::unique_ptr<UndoAddEdge::Private>& d)
0106 {
0107     auto [from, to] = findNodes(d->nodeStorage, d->fromQualifiedName, d->toQualifiedName);
0108 
0109     auto isPhysicalDependency = d->relationType == LakosRelationType::PackageDependency;
0110     if (isPhysicalDependency) {
0111         d->nodeStorage.addPhysicalDependency(from, to).expect("Unexpected undo/redo action");
0112     }
0113 
0114     auto isLogicalRelation = d->relationType == LakosRelationType::IsA
0115         || d->relationType == LakosRelationType::UsesInTheInterface
0116         || d->relationType == LakosRelationType::UsesInTheImplementation;
0117     if (isLogicalRelation) {
0118         d->nodeStorage.addLogicalRelation(dynamic_cast<TypeNode *>(from), dynamic_cast<TypeNode *>(to), d->relationType)
0119             .expect("Unexpected undo/redo error: Add logical relation failed");
0120     }
0121 }
0122 
0123 } // namespace
0124 
0125 void UndoAddEdge::undo()
0126 {
0127     switch (d->undoActionType) {
0128     case QtcUtil::UndoActionType::e_Add:
0129         removeRelationship(d);
0130         break;
0131     case QtcUtil::UndoActionType::e_Remove:
0132         addRelationship(d);
0133         break;
0134     }
0135 }
0136 
0137 void UndoAddEdge::redo()
0138 {
0139     IGNORE_FIRST_CALL
0140 
0141     switch (d->undoActionType) {
0142     case QtcUtil::UndoActionType::e_Add:
0143         addRelationship(d);
0144         break;
0145     case QtcUtil::UndoActionType::e_Remove:
0146         removeRelationship(d);
0147         break;
0148     }
0149 }