File indexing completed on 2025-01-05 05:23:46
0001 /* 0002 This file is part of the Okteta Kasten Framework, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2009, 2012 Alex Richardson <alex.richardson@gmx.de> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "structureaddremovewidget.hpp" 0010 0011 #include "../structuresmanager.hpp" 0012 #include "../structuredefinitionfile.hpp" 0013 #include "structureenabledlist.hpp" 0014 #include <structureslogging.hpp> 0015 // KF 0016 #include <KLocalizedString> 0017 // Qt 0018 #include <QPushButton> 0019 #include <QLabel> 0020 #include <QHBoxLayout> 0021 #include <QVBoxLayout> 0022 #include <QTreeWidget> 0023 #include <QTreeWidgetItem> 0024 #include <QRegularExpression> 0025 // Std 0026 #include <utility> 0027 0028 using namespace Kasten; 0029 0030 namespace { 0031 0032 enum EntryRoles { 0033 OnlyOneRole = Qt::UserRole, 0034 }; 0035 constexpr int OnlyOneRowColumn = 0; 0036 0037 } 0038 0039 StructureAddRemoveWidget::StructureAddRemoveWidget(const QMap<QString, Kasten::StructureDefinitionFile*>& structureDefs, 0040 const StructureEnabledList& enabledList, 0041 QWidget* parent) 0042 : QWidget(parent) 0043 { 0044 auto* baseLayout = new QHBoxLayout(); 0045 baseLayout->setContentsMargins(0, 0, 0, 0); 0046 0047 auto* tree1Layout = new QVBoxLayout(); 0048 mTree1Label = new QLabel(i18nc("@info:label", "Installed structures:"), this); 0049 tree1Layout->addWidget(mTree1Label); 0050 mTreeAvailable = new QTreeWidget(this); 0051 mTreeAvailable->setHeaderHidden(true); 0052 mTreeAvailable->setSelectionMode(QAbstractItemView::ExtendedSelection); 0053 mTreeAvailable->setColumnCount(2); 0054 mTreeAvailable->setColumnHidden(1, true); 0055 tree1Layout->addWidget(mTreeAvailable); 0056 0057 auto* tree2Layout = new QVBoxLayout(); 0058 mTree2Label = new QLabel(i18nc("@info:label", "Used structures:"), this); 0059 tree2Layout->addWidget(mTree2Label); 0060 mTreeSelected = new QTreeWidget(this); 0061 mTreeSelected->setHeaderHidden(true); 0062 mTreeSelected->setSelectionMode(QAbstractItemView::ExtendedSelection); 0063 mTreeSelected->setColumnCount(2); 0064 mTreeSelected->setColumnHidden(1, true); 0065 tree2Layout->addWidget(mTreeSelected); 0066 0067 auto* leftRightLayout = new QVBoxLayout(); 0068 leftRightLayout->addStretch(); 0069 mRightButton = new QPushButton(QIcon::fromTheme(QStringLiteral("arrow-right")), QString(), this); 0070 leftRightLayout->addWidget(mRightButton); 0071 mLeftButton = new QPushButton(QIcon::fromTheme(QStringLiteral("arrow-left")), QString(), this); 0072 leftRightLayout->addWidget(mLeftButton); 0073 leftRightLayout->addStretch(); 0074 0075 auto* upDownLayout = new QVBoxLayout(); 0076 upDownLayout->addStretch(); 0077 mUpButton = new QPushButton(QIcon::fromTheme(QStringLiteral("arrow-up")), QString(), this); 0078 upDownLayout->addWidget(mUpButton); 0079 mDownButton = new QPushButton(QIcon::fromTheme(QStringLiteral("arrow-down")), QString(), this); 0080 upDownLayout->addWidget(mDownButton); 0081 upDownLayout->addStretch(); 0082 0083 baseLayout->addLayout(tree1Layout); 0084 baseLayout->addLayout(leftRightLayout); 0085 baseLayout->addLayout(tree2Layout); 0086 baseLayout->addLayout(upDownLayout); 0087 setLayout(baseLayout); 0088 0089 connect(mLeftButton, &QPushButton::pressed, this, &StructureAddRemoveWidget::moveLeft); 0090 connect(mRightButton, &QPushButton::pressed, this, &StructureAddRemoveWidget::moveRight); 0091 connect(mUpButton, &QPushButton::pressed, this, &StructureAddRemoveWidget::moveUp); 0092 connect(mDownButton, &QPushButton::pressed, this, &StructureAddRemoveWidget::moveDown); 0093 0094 buildAvailableList(structureDefs, enabledList); 0095 0096 // already loaded defs: 0097 for (const StructureEnabledData& enabledData : enabledList) { 0098 if (enabledData.structure == QLatin1String("*")) { 0099 // add all of them 0100 StructureDefinitionFile* def = structureDefs.value(enabledData.id); 0101 if (!def) { 0102 continue; 0103 } 0104 const auto structureNames = def->structureNames(); 0105 const bool isOnlyOne = (structureNames.size() == 1); 0106 for (const QString& structure : structureNames) { 0107 appendEnabledStructureItem(enabledData.id, structure, isOnlyOne); 0108 } 0109 } else { 0110 appendEnabledStructureItem(enabledData.id, enabledData.structure, false); 0111 } 0112 } 0113 } 0114 0115 StructureAddRemoveWidget::~StructureAddRemoveWidget() = default; 0116 0117 QStringList StructureAddRemoveWidget::values() const 0118 { 0119 const QString expressionTemplate = QStringLiteral("\'%1\':\'%2\'"); 0120 0121 QStringList enabledStructures; 0122 const int topLevelItemCount = mTreeSelected->topLevelItemCount(); 0123 enabledStructures.reserve(topLevelItemCount); 0124 for (int i = 0; i < topLevelItemCount; ++i) { 0125 QTreeWidgetItem* item = mTreeSelected->topLevelItem(i); 0126 const bool isOnlyOne = item->data(OnlyOneRowColumn, ::OnlyOneRole).toBool(); 0127 const QString id = item->text(1); 0128 const QString structure = isOnlyOne ? QStringLiteral("*") : item->text(0); 0129 enabledStructures.append(expressionTemplate.arg(id, structure)); 0130 } 0131 0132 return enabledStructures; 0133 } 0134 0135 void StructureAddRemoveWidget::buildAvailableList(const QMap<QString, Kasten::StructureDefinitionFile*>& structureDefs, 0136 const StructureEnabledList& enabledList) 0137 { 0138 QList<QTreeWidgetItem*> availableItems; 0139 for (StructureDefinitionFile* def : structureDefs) { 0140 if (!def->isValid()) { 0141 continue; 0142 } 0143 const QString id = def->metaData().id(); 0144 if (!enabledList.isEnabled(id)) { 0145 continue; 0146 } 0147 auto* item = new QTreeWidgetItem(mTreeAvailable, QStringList { def->metaData().id(), id }); 0148 const auto structureNames = def->structureNames(); 0149 for (const QString& name : structureNames) { 0150 auto* subItem = new QTreeWidgetItem(item, QStringList { name, id }); 0151 item->addChild(subItem); 0152 } 0153 0154 availableItems.append(item); 0155 } 0156 0157 mTreeAvailable->addTopLevelItems(availableItems); 0158 0159 } 0160 0161 void StructureAddRemoveWidget::appendEnabledStructureItem(const QString& id, const QString& structure, 0162 bool isOnlyOne) 0163 { 0164 auto* item = new QTreeWidgetItem(mTreeSelected, QStringList { structure, id }); 0165 item->setData(OnlyOneRowColumn, ::OnlyOneRole, isOnlyOne); 0166 mTreeSelected->addTopLevelItem(item); 0167 } 0168 0169 void StructureAddRemoveWidget::moveLeft() 0170 { 0171 const QList<QTreeWidgetItem*> selected = mTreeSelected->selectedItems(); 0172 for (QTreeWidgetItem* item : selected) { 0173 delete mTreeSelected->takeTopLevelItem( 0174 mTreeSelected->indexOfTopLevelItem(item)); 0175 } 0176 } 0177 0178 void StructureAddRemoveWidget::moveRight() 0179 { 0180 const QList<QTreeWidgetItem*> selected = mTreeAvailable->selectedItems(); 0181 for (const QTreeWidgetItem* item : selected) { 0182 if (!item->parent()) { 0183 continue; // maybe sometime add all subitems 0184 } 0185 const bool isOnlyOne = item->data(OnlyOneRowColumn, ::OnlyOneRole).toBool(); 0186 const QString id = item->text(1); 0187 const QString structure = item->text(0); 0188 appendEnabledStructureItem(id, structure, isOnlyOne); 0189 } 0190 } 0191 0192 void StructureAddRemoveWidget::moveUp() 0193 { 0194 const QList<QTreeWidgetItem*> selected = mTreeSelected->selectedItems(); 0195 int firstIndex = -1; 0196 for (QTreeWidgetItem* item : selected) { 0197 int idx = mTreeSelected->indexOfTopLevelItem(item); 0198 int newIdx = qMax(0, idx - 1); 0199 mTreeSelected->insertTopLevelItem(newIdx, 0200 mTreeSelected->takeTopLevelItem(idx)); 0201 // only first index 0202 firstIndex = firstIndex == -1 ? newIdx : firstIndex; 0203 } 0204 0205 if (firstIndex != -1) { 0206 mTreeSelected->setCurrentItem(mTreeSelected->topLevelItem(firstIndex)); 0207 } 0208 } 0209 0210 void StructureAddRemoveWidget::moveDown() 0211 { 0212 const QList<QTreeWidgetItem*> selected = mTreeSelected->selectedItems(); 0213 int firstIndex = -1; 0214 int maxItmCount = mTreeSelected->topLevelItemCount(); 0215 for (QTreeWidgetItem* item : selected) { 0216 int idx = mTreeSelected->indexOfTopLevelItem(item); 0217 int newIdx = qMin(idx + 1, maxItmCount - 1); 0218 mTreeSelected->insertTopLevelItem(newIdx, 0219 mTreeSelected->takeTopLevelItem(idx)); 0220 // only first index 0221 firstIndex = firstIndex == -1 ? newIdx : firstIndex; 0222 } 0223 0224 if (firstIndex != -1) { 0225 mTreeSelected->setCurrentItem(mTreeSelected->topLevelItem(firstIndex)); 0226 } 0227 } 0228 0229 #include "moc_structureaddremovewidget.cpp"