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"