File indexing completed on 2024-04-28 08:25:29

0001 /*
0002  * This file is part of KDevelop Krazy2 Plugin.
0003  *
0004  * Copyright 2012 Daniel Calviño Sánchez <danxuliu@gmail.com>
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License
0008  * as published by the Free Software Foundation; either version 2
0009  * of the License, or (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014  * GNU General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU General Public License
0017  * along with this program. If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "checkermodel.h"
0021 
0022 #include <KLocalizedString>
0023 
0024 #include "checker.h"
0025 
0026 class Item {
0027 public:
0028 
0029     enum ItemType {
0030         FileTypeItem,
0031         CheckerItem,
0032         ExtraHeaderItem
0033     };
0034 
0035     Item():
0036         m_parent(nullptr),
0037         m_checker(nullptr) {
0038     }
0039 
0040     ~Item() {
0041         qDeleteAll(m_children);
0042     }
0043 
0044     ItemType type() const {
0045         return m_type;
0046     }
0047 
0048     void setType(ItemType type) {
0049         m_type = type;
0050     }
0051 
0052     const QList<Item*>& children() const {
0053         return m_children;
0054     }
0055 
0056     void addChild(Item* item) {
0057         item->setParent(this);
0058         m_children.append(item);
0059     }
0060 
0061     Item* parent() const {
0062         return m_parent;
0063     }
0064 
0065     void setParent(Item* parent) {
0066         m_parent = parent;
0067     }
0068 
0069     const QString& fileType() const {
0070         return m_fileType;
0071     }
0072 
0073     void setFileType(const QString& fileType) {
0074         m_fileType = fileType;
0075     }
0076 
0077     const Checker* checker() const {
0078         return m_checker;
0079     }
0080 
0081     void setChecker(const Checker* checker) {
0082         m_checker = checker;
0083     }
0084 
0085 private:
0086 
0087     ItemType m_type;
0088     QList<Item*> m_children;
0089     Item* m_parent;
0090 
0091     QString m_fileType;
0092     const Checker* m_checker;
0093 
0094 };
0095 
0096 //public:
0097 
0098 CheckerModel::CheckerModel(QObject* parent /*= 0*/):
0099     QAbstractItemModel(parent) {
0100 }
0101 
0102 CheckerModel::~CheckerModel() {
0103     qDeleteAll(m_fileTypeItems);
0104 }
0105 
0106 QModelIndex CheckerModel::index(int row, int column, const QModelIndex& parent /* = QModelIndex()*/) const {
0107     if (!hasIndex(row, column, parent)) {
0108         return QModelIndex();
0109     }
0110 
0111     Item* item;
0112     if (!parent.isValid()) {
0113         item = m_fileTypeItems.at(row);
0114     } else {
0115         item = static_cast<Item*>(parent.internalPointer())->children().at(row);
0116     }
0117 
0118     return createIndex(row, column, item);
0119 }
0120 
0121 QModelIndex CheckerModel::parent(const QModelIndex& index) const {
0122     if (!index.isValid()) {
0123         return QModelIndex();
0124     }
0125 
0126     Item* childItem = static_cast<Item*>(index.internalPointer());
0127     Item* parentItem = childItem->parent();
0128 
0129     if (!parentItem) {
0130         return QModelIndex();
0131     }
0132 
0133     int row;
0134     if (parentItem->type() == Item::FileTypeItem) {
0135         row = m_fileTypeItems.indexOf(parentItem);
0136     } else {
0137         row = parentItem->parent()->children().indexOf(parentItem);
0138     }
0139 
0140     return createIndex(row, 0, parentItem);
0141 }
0142 
0143 int CheckerModel::rowCount(const QModelIndex& parent /*= QModelIndex()*/) const {
0144     if (parent.column() > 0) {
0145         return 0;
0146     }
0147 
0148     if (!parent.isValid()) {
0149         return m_fileTypeItems.count();
0150     }
0151 
0152     return static_cast<Item*>(parent.internalPointer())->children().count();
0153 }
0154 
0155 int CheckerModel::columnCount(const QModelIndex& parent /*= QModelIndex()*/) const {
0156     Q_UNUSED(parent);
0157 
0158     return 1;
0159 }
0160 
0161 QVariant CheckerModel::data(const QModelIndex& index, int role /*= Qt::DisplayRole*/) const {
0162     if (!index.isValid()) {
0163         return QVariant();
0164     }
0165 
0166     if (role != Qt::DisplayRole && role != Qt::ToolTipRole) {
0167         return QVariant();
0168     }
0169 
0170     Item* item = static_cast<Item*>(index.internalPointer());
0171     if (role == Qt::ToolTipRole) {
0172         if (item->type() != Item::CheckerItem) {
0173             return QVariant();
0174         }
0175 
0176         if (item->checker()->description().isEmpty()) {
0177             return i18nc("@info:tooltip The underlying command did not provide a text output",
0178                          "Sorry, no description given");
0179         }
0180 
0181         return "<p>" + item->checker()->description() + "</p>";
0182     }
0183 
0184     if (item->type() == Item::FileTypeItem) {
0185         return item->fileType();
0186     }
0187 
0188     if (item->type() == Item::ExtraHeaderItem) {
0189         return i18nc("@item Extra Krazy2 checkers", "[EXTRA]");
0190     }
0191 
0192     return item->checker()->name();
0193 }
0194 
0195 const Checker* CheckerModel::checkerForIndex(const QModelIndex& index) const {
0196     if (!index.isValid()) {
0197         return nullptr;
0198     }
0199 
0200     Item* item = static_cast<Item*>(index.internalPointer());
0201     if (item->type() == Item::FileTypeItem || item->type() == Item::ExtraHeaderItem) {
0202         return nullptr;
0203     }
0204 
0205     return item->checker();
0206 }
0207 
0208 void CheckerModel::setCheckers(const QList< const Checker* >& checkers) {
0209     beginResetModel();
0210 
0211     QMultiMap<QString, const Checker*> checkersByFileType;
0212     foreach (const Checker* checker, checkers) {
0213         checkersByFileType.insert(checker->fileType(), checker);
0214     }
0215 
0216     qDeleteAll(m_fileTypeItems);
0217     m_fileTypeItems.clear();
0218 
0219     //Keys are returned in ascending order
0220     foreach (const QString& fileType, checkersByFileType.uniqueKeys()) {
0221         auto  fileTypeItem = new Item();
0222         fileTypeItem->setType(Item::FileTypeItem);
0223         fileTypeItem->setFileType(fileType);
0224         m_fileTypeItems.append(fileTypeItem);
0225 
0226         QMap<QString, Item*> checkerItems;
0227         QMap<QString, Item*> extraCheckerItems;
0228         foreach (const Checker* checker, checkersByFileType.values(fileType)) {
0229             auto  checkerItem = new Item();
0230             checkerItem->setType(Item::CheckerItem);
0231             checkerItem->setChecker(checker);
0232 
0233             if (!checker->isExtra()) {
0234                 checkerItems.insert(checker->name(), checkerItem);
0235             } else {
0236                 extraCheckerItems.insert(checker->name(), checkerItem);
0237             }
0238         }
0239 
0240         //Values are returned in ascending order of their keys
0241         foreach (Item* checkerItem, checkerItems.values()) {
0242             fileTypeItem->addChild(checkerItem);
0243         }
0244 
0245         if (!extraCheckerItems.values().isEmpty()) {
0246             auto  extraHeaderItem = new Item();
0247             extraHeaderItem->setType(Item::ExtraHeaderItem);
0248             extraHeaderItem->setFileType(fileTypeItem->fileType());
0249             fileTypeItem->addChild(extraHeaderItem);
0250 
0251             //Values are returned in ascending order of their keys
0252             foreach (Item* checkerItem, extraCheckerItems.values()) {
0253                 extraHeaderItem->addChild(checkerItem);
0254             }
0255         }
0256     }
0257 
0258     endResetModel();
0259 }