File indexing completed on 2024-05-19 05:41:57
0001 // ct_lvtcgn_codegentreemodel.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_lvtcgn_cogedentreemodel.h> 0021 #include <ct_lvtcgn_generatecode.h> 0022 0023 Q_DECLARE_METATYPE(Codethink::lvtcgn::mdl::IPhysicalEntityInfo *) 0024 0025 namespace Codethink::lvtcgn::gui { 0026 0027 using namespace Codethink::lvtcgn::mdl; 0028 0029 CodeGenerationEntitiesTreeModel::CodeGenerationEntitiesTreeModel(ICodeGenerationDataProvider& dataProvider, 0030 QObject *parent): 0031 QStandardItemModel(parent), dataProvider(dataProvider) 0032 { 0033 setHorizontalHeaderLabels({tr("Generation selection")}); 0034 refreshContents(); 0035 0036 connect(this, &CodeGenerationEntitiesTreeModel::itemChanged, [this](QStandardItem *item) { 0037 auto& info = *item->data(CodeGenerationDataRole::InfoReferenceRole).value<IPhysicalEntityInfo *>(); 0038 info.setSelectedForCodeGeneration(item->checkState() == Qt::Checked 0039 || item->checkState() == Qt::PartiallyChecked); 0040 0041 if (itemChangedCascadeUpdate) { 0042 itemChangedCascadeUpdate = false; 0043 updateAllChildrenState(item); 0044 updateParentState(item); 0045 itemChangedCascadeUpdate = true; 0046 } 0047 }); 0048 } 0049 0050 void CodeGenerationEntitiesTreeModel::updateAllChildrenState(QStandardItem *item) 0051 { 0052 if (item->checkState() == Qt::PartiallyChecked) { 0053 return; 0054 } 0055 0056 for (int i = 0; i < item->rowCount(); ++i) { 0057 item->child(i)->setCheckState(item->checkState()); 0058 updateAllChildrenState(item->child(i)); 0059 } 0060 } 0061 0062 void CodeGenerationEntitiesTreeModel::updateParentState(QStandardItem *item) 0063 { 0064 auto *parentItem = item->parent(); 0065 if (!parentItem) { 0066 return; 0067 } 0068 0069 auto allChildrenHaveSameState = true; 0070 auto referenceState = parentItem->child(0)->checkState(); 0071 for (int i = 0; i < parentItem->rowCount(); ++i) { 0072 if (parentItem->child(i)->checkState() != referenceState) { 0073 allChildrenHaveSameState = false; 0074 break; 0075 } 0076 } 0077 0078 parentItem->setCheckState(allChildrenHaveSameState ? referenceState : Qt::PartiallyChecked); 0079 updateParentState(parentItem); 0080 } 0081 0082 void CodeGenerationEntitiesTreeModel::populateItemAndChildren(IPhysicalEntityInfo& info, QStandardItem *parent) 0083 { 0084 auto *item = new QStandardItem(QString::fromStdString(info.name())); 0085 item->setData(QString::fromStdString(info.name()), CodeGenerationDataRole::EntityNameRole); 0086 item->setData(QVariant::fromValue(&info), CodeGenerationDataRole::InfoReferenceRole); 0087 item->setCheckable(true); 0088 item->setCheckState(info.selectedForCodeGeneration() ? Qt::Checked : Qt::Unchecked); 0089 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); 0090 if (parent == nullptr) { 0091 appendRow(item); 0092 } else { 0093 parent->appendRow(item); 0094 } 0095 0096 auto children = info.children(); 0097 std::sort(children.begin(), children.end(), [](IPhysicalEntityInfo const& l, IPhysicalEntityInfo const& r) { 0098 return l.name() < r.name(); 0099 }); 0100 for (const auto& childInfo : children) { 0101 populateItemAndChildren(childInfo.get(), item); 0102 } 0103 } 0104 0105 void CodeGenerationEntitiesTreeModel::refreshContents() 0106 { 0107 auto children = dataProvider.topLevelEntities(); 0108 std::sort(children.begin(), children.end(), [](IPhysicalEntityInfo const& l, IPhysicalEntityInfo const& r) { 0109 if (l.name() == "non-lakosian group") { 0110 return false; 0111 } 0112 if (r.name() == "non-lakosian group") { 0113 return true; 0114 } 0115 return l.name() < r.name(); 0116 }); 0117 0118 for (const auto& rootInfo : children) { 0119 populateItemAndChildren(rootInfo.get(), nullptr); 0120 } 0121 } 0122 0123 void CodeGenerationEntitiesTreeModel::recursiveExec(std::function<RecursiveExec(QStandardItem *)> f) 0124 { 0125 std::function<RecursiveExec(QStandardItem * item)> recursiveSearchAndExec = [&](QStandardItem *item) { 0126 if (f(item) == RecursiveExec::StopSearch) { 0127 return RecursiveExec::StopSearch; 0128 } 0129 0130 for (auto i = 0; i < item->rowCount(); ++i) { 0131 auto *childItem = item->child(i); 0132 if (recursiveSearchAndExec(childItem) == RecursiveExec::StopSearch) { 0133 return RecursiveExec::StopSearch; 0134 } 0135 } 0136 return RecursiveExec::ContinueSearch; 0137 }; 0138 0139 for (auto i = 0; i < rowCount(); ++i) { 0140 if (recursiveSearchAndExec(item(i)) == RecursiveExec::StopSearch) { 0141 return; 0142 } 0143 } 0144 } 0145 0146 } // namespace Codethink::lvtcgn::gui