File indexing completed on 2024-05-19 05:42:22
0001 // ct_lvtqtw_tool_add_package.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_tool_add_logical_entity.h> 0021 0022 #include <ct_lvtqtc_componententity.h> 0023 #include <ct_lvtqtc_graphicsscene.h> 0024 #include <ct_lvtqtc_graphicsview.h> 0025 #include <ct_lvtqtc_inputdialog.h> 0026 #include <ct_lvtqtc_logicalentity.h> 0027 #include <ct_lvtqtc_packageentity.h> 0028 #include <ct_lvtqtc_undo_add_logicalentity.h> 0029 0030 #include <ct_lvtqtc_util.h> 0031 0032 #include <ct_lvtldr_lakosiannode.h> 0033 #include <ct_lvtldr_nodestorage.h> 0034 #include <ct_lvtqtc_iconhelpers.h> 0035 #include <ct_lvtshr_functional.h> 0036 0037 #include <QApplication> 0038 #include <QDebug> 0039 #include <QInputDialog> 0040 #include <QMessageBox> 0041 0042 #include <preferences.h> 0043 0044 using namespace Codethink::lvtldr; 0045 using namespace Codethink::lvtshr; 0046 0047 namespace Codethink::lvtqtc { 0048 0049 struct ToolAddLogicalEntity::Private { 0050 NodeStorage& nodeStorage; 0051 0052 explicit Private(NodeStorage& nodeStorage): nodeStorage(nodeStorage) 0053 { 0054 } 0055 }; 0056 0057 ToolAddLogicalEntity::ToolAddLogicalEntity(GraphicsView *gv, NodeStorage& nodeStorage): 0058 BaseAddEntityTool(tr("Logical Entity"), 0059 tr("Creates a Logical Entity (such as classes or structs)"), 0060 IconHelpers::iconFrom(":/icons/class"), 0061 gv), 0062 d(std::make_unique<Private>(nodeStorage)) 0063 { 0064 auto *inputDataDialog = inputDialog(); 0065 inputDataDialog->addTextField("name", tr("Name:")); 0066 inputDataDialog->addComboBoxField("kind", tr("Kind:"), {"Class", "Enum", "Struct", "TypeAlias", "Union"}); 0067 inputDataDialog->finish(); 0068 } 0069 0070 ToolAddLogicalEntity::~ToolAddLogicalEntity() = default; 0071 0072 template<typename T> 0073 cpp::result<void, InvalidLogicalEntityError> 0074 checkNameError(bool hasParent, const std::string& name, const std::string& parentName) 0075 { 0076 return T::checkName(hasParent, name, parentName); 0077 } 0078 0079 void ToolAddLogicalEntity::activate() 0080 { 0081 Q_EMIT sendMessage(tr("Click on a Component, Class or Struct to add a new Logical Entity"), 0082 KMessageWidget::Information); 0083 BaseAddEntityTool::activate(); 0084 } 0085 0086 void ToolAddLogicalEntity::mousePressEvent(QMouseEvent *event) 0087 { 0088 qCDebug(LogTool) << name() << "Mouse Press Event"; 0089 0090 using Codethink::lvtshr::ScopeExit; 0091 ScopeExit _([&]() { 0092 deactivate(); 0093 }); 0094 0095 auto *parentView = [&]() -> LakosEntity * { 0096 auto *parentClass = graphicsView()->itemByTypeAt<LogicalEntity>(event->pos()); 0097 if (parentClass != nullptr) { 0098 return parentClass; 0099 } 0100 return graphicsView()->itemByTypeAt<ComponentEntity>(event->pos()); 0101 }(); 0102 0103 if (!parentView) { 0104 Q_EMIT sendMessage( 0105 tr("This is not a valid parent for a user defined type. Parent must be a 'Component', a 'Class' or a " 0106 "'Struct'."), 0107 KMessageWidget::Error); 0108 return; 0109 } 0110 0111 if (m_nameDialog->exec() == QDialog::Rejected) { 0112 return; 0113 } 0114 assert(parentView); 0115 0116 auto *parent = parentView->internalNode(); 0117 auto parentName = parent->name(); 0118 auto name = std::any_cast<QString>(m_nameDialog->fieldValue("name")).toStdString(); 0119 auto qualifiedName = parentName + "::" + name; 0120 0121 auto kindInput = std::any_cast<QString>(m_nameDialog->fieldValue("kind")); 0122 auto kind = ([&kindInput]() { 0123 if (kindInput == "Class") { 0124 return UDTKind::Class; 0125 } 0126 if (kindInput == "Enum") { 0127 return UDTKind::Enum; 0128 } 0129 if (kindInput == "Struct") { 0130 return UDTKind::Struct; 0131 } 0132 if (kindInput == "TypeAlias") { 0133 return UDTKind::TypeAlias; 0134 } 0135 if (kindInput == "Union") { 0136 return UDTKind::Union; 0137 } 0138 return UDTKind::Unknown; 0139 })(); 0140 0141 auto result = d->nodeStorage.addLogicalEntity(name, qualifiedName, parent, kind); 0142 if (result.has_error()) { 0143 using Kind = ErrorAddUDT::Kind; 0144 switch (result.error().kind) { 0145 case Kind::BadParentType: { 0146 Q_EMIT sendMessage( 0147 tr("This is not a valid parent for a user defined type. Parent must be a 'Component', a 'Class' or a " 0148 "'Struct'."), 0149 KMessageWidget::Error); 0150 return; 0151 } 0152 } 0153 } 0154 0155 // Success, clean the message on the view. 0156 Q_EMIT sendMessage(QString(), KMessageWidget::Information); 0157 0158 auto *newLogicalEntity = result.value(); 0159 0160 auto *scene = qobject_cast<GraphicsScene *>(graphicsView()->scene()); 0161 const QPointF scenePos = graphicsView()->mapToScene(event->pos()); 0162 const QPointF itemPos = parentView->mapFromScene(scenePos); 0163 scene->setEntityPos(newLogicalEntity->uid(), itemPos); 0164 scene->updateBoundingRect(); 0165 Q_EMIT undoCommandCreated(new UndoAddLogicalEntity(scene, 0166 itemPos, 0167 name, 0168 qualifiedName, 0169 parent->qualifiedName(), 0170 QtcUtil::UndoActionType::e_Add, 0171 d->nodeStorage)); 0172 } 0173 0174 cpp::result<void, InvalidLogicalEntityError> 0175 LogicalEntityNameRules::checkName(bool hasParent, const std::string& name, const std::string& parentName) 0176 { 0177 return {}; 0178 } 0179 0180 } // namespace Codethink::lvtqtc