File indexing completed on 2024-06-23 04:36:25

0001 /*
0002     SPDX-FileCopyrightText: 2014 Sergey Kalinichev <kalinichev.so.0@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "compilersmodel.h"
0008 
0009 #include <KLocalizedString>
0010 #include <QVariant>
0011 
0012 //Represents a single row in the table
0013 class TreeItem
0014 {
0015 public:
0016     explicit TreeItem(const QList<QVariant> &data, TreeItem *parent = nullptr)
0017         :m_itemData(data)
0018         ,m_parentItem(parent)
0019     {}
0020 
0021     virtual ~TreeItem()
0022     {
0023         removeChilds();
0024     }
0025 
0026     void appendChild(TreeItem *item)
0027     {
0028         m_childItems.append(item);
0029     }
0030 
0031     void removeChild(int row)
0032     {
0033         m_childItems.removeAt(row);
0034     }
0035 
0036     TreeItem *child(int row)
0037     {
0038         return m_childItems.value(row);
0039     }
0040 
0041     int childCount() const
0042     {
0043         return m_childItems.count();
0044     }
0045 
0046     int columnCount() const
0047     {
0048         return m_itemData.count();
0049     }
0050 
0051     virtual QVariant data(int column) const
0052     {
0053         return m_itemData.value(column);
0054     }
0055 
0056     TreeItem *parent()
0057     {
0058         return m_parentItem;
0059     }
0060 
0061     int row() const
0062     {
0063         if (m_parentItem) {
0064             return m_parentItem->m_childItems.indexOf(const_cast<TreeItem*>(this));
0065         }
0066 
0067         return 0;
0068     }
0069 
0070     void removeChilds()
0071     {
0072         qDeleteAll(m_childItems);
0073         m_childItems.clear();
0074     }
0075 
0076 private:
0077     QList<TreeItem*> m_childItems;
0078     QList<QVariant> m_itemData;
0079     TreeItem *m_parentItem;
0080 };
0081 
0082 class CompilerItem : public TreeItem {
0083 public:
0084     CompilerItem(const CompilerPointer& compiler, TreeItem* parent)
0085         : TreeItem(QList<QVariant>{compiler->name(), compiler->factoryName()}, parent)
0086     , m_compiler(compiler)
0087     {}
0088 
0089     CompilerPointer compiler()
0090     {
0091         return m_compiler;
0092     }
0093 
0094     QVariant data(int column) const override
0095     {
0096         return !column ? m_compiler->name() : m_compiler->factoryName();
0097     }
0098 
0099 private:
0100     CompilerPointer m_compiler;
0101 };
0102 
0103 namespace {
0104 TreeItem* autoDetectedRootItem(TreeItem* root)
0105 {
0106     return root->child(0);
0107 }
0108 
0109 TreeItem* manualRootItem(TreeItem* root)
0110 {
0111     return root->child(1);
0112 }
0113 }
0114 
0115 CompilersModel::CompilersModel(QObject* parent)
0116     : QAbstractItemModel(parent)
0117     , m_rootItem(new TreeItem({i18nc("@title:column", "Name"), i18nc("@title:column", "Type")}))
0118 {
0119     m_rootItem->appendChild(new TreeItem( QList<QVariant>{i18nc("@item", "Auto-detected"), QString()}, m_rootItem));
0120     m_rootItem->appendChild(new TreeItem( QList<QVariant>{i18nc("@item", "Manual"), QString()}, m_rootItem));
0121 }
0122 
0123 CompilersModel::~CompilersModel()
0124 {
0125     delete m_rootItem;
0126 }
0127 
0128 QVariant CompilersModel::data(const QModelIndex& index, int role) const
0129 {
0130     if (!index.isValid() || (role != Qt::DisplayRole && role != CompilerDataRole)) {
0131         return QVariant();
0132     }
0133 
0134     auto *item = static_cast<TreeItem*>(index.internalPointer());
0135 
0136     if (role == CompilerDataRole) {
0137         QVariant v;
0138         if (auto c = dynamic_cast<CompilerItem*>(item)) {
0139             if (item->parent() == manualRootItem(m_rootItem)) {
0140                 v.setValue<CompilerPointer>(c->compiler());
0141             }
0142         }
0143         return v;
0144     }
0145 
0146     return item->data(index.column());
0147 }
0148 
0149 int CompilersModel::rowCount(const QModelIndex& parent) const
0150 {
0151     TreeItem *parentItem;
0152     if (parent.column() > 0) {
0153         return 0;
0154     }
0155 
0156     if (!parent.isValid()) {
0157         parentItem = m_rootItem;
0158     } else {
0159         parentItem = static_cast<TreeItem*>(parent.internalPointer());
0160     }
0161 
0162     return parentItem->childCount();
0163 }
0164 
0165 int CompilersModel::columnCount(const QModelIndex& parent) const
0166 {
0167     if (parent.isValid()) {
0168         return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
0169     } else {
0170         return m_rootItem->columnCount();
0171     }
0172 }
0173 
0174 QVariant CompilersModel::headerData(int section, Qt::Orientation orientation, int role) const
0175 {
0176     if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
0177         return m_rootItem->data(section);
0178     }
0179     return QVariant();
0180 }
0181 
0182 Qt::ItemFlags CompilersModel::flags(const QModelIndex& index) const
0183 {
0184     if (!index.isValid()) {
0185         return Qt::NoItemFlags;
0186     }
0187 
0188     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0189 }
0190 
0191 QModelIndex CompilersModel::index(int row, int column, const QModelIndex& parent) const
0192 {
0193     if (!hasIndex(row, column, parent)) {
0194         return QModelIndex();
0195     }
0196 
0197     TreeItem *parentItem;
0198 
0199     if (!parent.isValid()) {
0200         parentItem = m_rootItem;
0201     } else {
0202         parentItem = static_cast<TreeItem*>(parent.internalPointer());
0203     }
0204 
0205     TreeItem* childItem = parentItem->child(row);
0206     if (childItem) {
0207         return createIndex(row, column, childItem);
0208     } else {
0209         return QModelIndex();
0210     }
0211 }
0212 
0213 QModelIndex CompilersModel::parent(const QModelIndex& index) const
0214 {
0215     if (!index.isValid()) {
0216         return QModelIndex();
0217     }
0218 
0219     auto *childItem = static_cast<TreeItem*>(index.internalPointer());
0220     TreeItem *parentItem = childItem->parent();
0221 
0222     if (parentItem == m_rootItem) {
0223         return QModelIndex();
0224     }
0225 
0226     return createIndex(parentItem->row(), 0, parentItem);
0227 }
0228 
0229 QVector< CompilerPointer > CompilersModel::compilers() const
0230 {
0231     QVector<CompilerPointer> compilers;
0232     for (int idx = 0; idx < 2; idx++) {
0233         for (int i = 0; i< m_rootItem->child(idx)->childCount(); i++) {
0234             auto compiler = static_cast<CompilerItem*>(m_rootItem->child(idx)->child(i))->compiler();
0235             if (!compiler->name().isEmpty() && !compiler->path().isEmpty()) {
0236                 compilers.append(compiler);
0237             }
0238         }
0239     }
0240 
0241     return compilers;
0242 }
0243 
0244 void CompilersModel::setCompilers(const QVector< CompilerPointer >& compilers)
0245 {
0246     beginResetModel();
0247     autoDetectedRootItem(m_rootItem)->removeChilds();
0248     manualRootItem(m_rootItem)->removeChilds();
0249 
0250     for (auto& compiler: compilers) {
0251         if (compiler->factoryName().isEmpty()) {
0252             continue;
0253         }
0254         TreeItem* parent = autoDetectedRootItem(m_rootItem);
0255         if (compiler->editable()) {
0256             parent = manualRootItem(m_rootItem);
0257         }
0258         parent->appendChild(new CompilerItem(compiler, parent));
0259     }
0260 
0261     endResetModel();
0262 }
0263 
0264 QModelIndex CompilersModel::addCompiler(const CompilerPointer& compiler)
0265 {
0266     beginInsertRows(index(1, 0), manualRootItem(m_rootItem)->childCount(), manualRootItem(m_rootItem)->childCount());
0267     Q_ASSERT(!compiler->factoryName().isEmpty());
0268     manualRootItem(m_rootItem)->appendChild(new CompilerItem(compiler, manualRootItem(m_rootItem)));
0269     endInsertRows();
0270 
0271     emit compilerChanged();
0272     return index(manualRootItem(m_rootItem)->childCount()-1, 0, index(1, 0));
0273 }
0274 
0275 bool CompilersModel::removeRows(int row, int count, const QModelIndex& parent)
0276 {
0277     if (row >= 0 && count > 0 &&  parent.isValid() && static_cast<TreeItem*>(parent.internalPointer()) == manualRootItem(m_rootItem)) {
0278         beginRemoveRows(parent, row, row + count - 1);
0279         for (int i = 0; i < count; ++i) {
0280             manualRootItem(m_rootItem)->removeChild(row);
0281         }
0282         endRemoveRows();
0283 
0284         emit compilerChanged();
0285         return true;
0286     }
0287     return false;
0288 }
0289 
0290 void CompilersModel::updateCompiler(const QItemSelection& compiler)
0291 {
0292     const auto& indexes = compiler.indexes();
0293     for (const auto& idx : indexes) {
0294         emit dataChanged(idx, idx);
0295     }
0296     emit compilerChanged();
0297 }
0298 
0299 #include "moc_compilersmodel.cpp"