File indexing completed on 2024-04-28 04:37:30

0001 /*
0002     SPDX-FileCopyrightText: 2007 Alexander Dymo <adymo@kdevelop.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "aggregatemodel.h"
0008 
0009 #include <QStandardItem>
0010 #include <QStandardItemModel>
0011 
0012 
0013 namespace Sublime {
0014 
0015 class AggregateModelPrivate
0016 {
0017 public:
0018     /*Instance of this class is used as an internal pointer to the aggregator items
0019     in the model to differentiate between aggregators and non-aggregators.*/
0020     class AggregateInternalData {
0021     };
0022 
0023     AggregateModelPrivate()
0024     {
0025         internal = new AggregateInternalData();
0026     }
0027     ~AggregateModelPrivate()
0028     {
0029         delete internal;
0030     }
0031 
0032     QList<QStandardItemModel*> modelList;
0033     QMap<QStandardItemModel*, QString> modelNames;
0034     AggregateInternalData *internal;
0035 };
0036 
0037 
0038 
0039 AggregateModel::AggregateModel(QObject *parent)
0040     :QAbstractItemModel(parent)
0041     ,d_ptr(new AggregateModelPrivate())
0042 {
0043 }
0044 
0045 AggregateModel::~AggregateModel() = default;
0046 
0047 void AggregateModel::addModel(const QString &name, QStandardItemModel *model)
0048 {
0049     Q_D(AggregateModel);
0050 
0051     beginResetModel();
0052     d->modelList << model;
0053     d->modelNames[model] = name;
0054     endResetModel();
0055 }
0056 
0057 void AggregateModel::removeModel(QStandardItemModel *model)
0058 {
0059     Q_D(AggregateModel);
0060 
0061     beginResetModel();
0062     d->modelList.removeAll(model);
0063     d->modelNames.remove(model);
0064     endResetModel();
0065 }
0066 
0067 
0068 
0069 // reimplemented methods from QAbstractItemModel
0070 
0071 Qt::ItemFlags AggregateModel::flags(const QModelIndex &index) const
0072 {
0073     if (!index.isValid())
0074         return Qt::NoItemFlags;
0075     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0076 }
0077 
0078 QVariant AggregateModel::headerData(int section, Qt::Orientation orientation, int role) const
0079 {
0080     Q_UNUSED(section);
0081     Q_UNUSED(orientation);
0082     Q_UNUSED(role);
0083     //there's nothing to return here because aggregated models will have different headers
0084     //so we just use empty headers for aggregate model.
0085     return QString();
0086 }
0087 
0088 int AggregateModel::columnCount(const QModelIndex &parent) const
0089 {
0090     Q_UNUSED(parent);
0091     //only 1 column is supported atm
0092     return 1;
0093 }
0094 
0095 int AggregateModel::rowCount(const QModelIndex &parent) const
0096 {
0097     Q_D(const AggregateModel);
0098 
0099     if (!parent.isValid())
0100     {
0101         //toplevel items represent aggregated models
0102         return d->modelList.count();
0103     }
0104     else
0105     {
0106         //Qt model guideline - only 1st column has children
0107         if (parent.column() != 0)
0108             return 0;
0109 
0110         //find out if the parent is an aggregator
0111         if (parent.internalPointer() == d->internal)
0112         {
0113             //return the number of toplevel rows in the source model
0114             return d->modelList[parent.row()]->rowCount(QModelIndex());
0115         }
0116         else
0117         {
0118             //we have a standard item in the source model - just map it into our model
0119             auto *item = static_cast<QStandardItem*>(parent.internalPointer());
0120             return item->rowCount();
0121         }
0122     }
0123 }
0124 
0125 QVariant AggregateModel::data(const QModelIndex &index, int role) const
0126 {
0127     Q_D(const AggregateModel);
0128 
0129     if (!index.isValid() || (role != Qt::DisplayRole))
0130         return QVariant();
0131 
0132     if (!index.parent().isValid())
0133     {
0134         //aggregator item
0135         return d->modelNames[d->modelList[index.row()]];
0136     }
0137     else
0138     {
0139         //we have a standard item in the source model - just map it into our model
0140         auto *item = static_cast<QStandardItem*>(index.internalPointer());
0141         return item->data(role);
0142     }
0143 }
0144 
0145 QModelIndex AggregateModel::parent(const QModelIndex &index) const
0146 {
0147     Q_D(const AggregateModel);
0148 
0149     if (!index.isValid())
0150         return QModelIndex();
0151 
0152     if (index.internalPointer() == d->internal)
0153     {
0154         //this is aggregator item, it has no parents
0155         return QModelIndex();
0156     }
0157 
0158     //this is just an item from the model
0159     auto *item = static_cast<QStandardItem*>(index.internalPointer());
0160     QModelIndex parent;
0161     if (!item->parent())
0162     {
0163         //we need to find the aggregator item that owns this index
0164         //first find the model for this index
0165         QStandardItemModel *model = item->model();
0166         //next find the row number of the aggregator item
0167         int row = d->modelList.indexOf(model);
0168         parent = createIndex(row, 0, d->internal);
0169     }
0170     else
0171     {
0172         //we have a standard item in the source model - just map it into our model
0173         parent = createIndex(item->parent()->row(), 0, item->parent());
0174     }
0175     return parent;
0176 }
0177 
0178 QModelIndex AggregateModel::index(int row, int column, const QModelIndex &parent) const
0179 {
0180     Q_D(const AggregateModel);
0181 
0182     if (row < 0 || column < 0)
0183         return QModelIndex();
0184 
0185     if (!parent.isValid())
0186     {
0187         if (column > 1 || row >= d->modelList.count())
0188             return QModelIndex();
0189         //this is an aggregator item
0190         return createIndex(row, column, d->internal);
0191     }
0192     else if (parent.internalPointer() == d->internal)
0193     {
0194         //the parent is an aggregator
0195         //find the model that holds the items
0196         QStandardItemModel *model = d->modelList[parent.row()];
0197         //this is the first level of items
0198         QStandardItem *item = model->item(row, column);
0199         if (item)
0200             return createIndex(row, column, item);
0201         else
0202             return QModelIndex();
0203     }
0204     else
0205     {
0206         //we have a standard item in the source model - just map it into our model
0207         auto *parentItem = static_cast<QStandardItem*>(parent.internalPointer());
0208         return createIndex(row, column, parentItem->child(row, column));
0209     }
0210 }
0211 
0212 }
0213 
0214 #include "moc_aggregatemodel.cpp"