File indexing completed on 2024-05-12 04:37:37
0001 /* 0002 SPDX-FileCopyrightText: 2008 Vladimir Prus <ghost@cs.msu.su> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "treemodel.h" 0008 0009 #include <iostream> 0010 0011 #include "treeitem.h" 0012 0013 using namespace KDevelop; 0014 0015 class KDevelop::TreeModelPrivate 0016 { 0017 public: 0018 explicit TreeModelPrivate(const QVector<QString>& headers) 0019 : headers(headers) 0020 { 0021 } 0022 0023 QVector<QString> headers; 0024 TreeItem* root = nullptr; 0025 }; 0026 0027 TreeModel::TreeModel(const QVector<QString>& headers, 0028 QObject *parent) 0029 : QAbstractItemModel(parent) 0030 , d_ptr(new TreeModelPrivate(headers)) 0031 { 0032 } 0033 0034 void TreeModel::setRootItem(TreeItem *item) 0035 { 0036 Q_D(TreeModel); 0037 0038 d->root = item; 0039 d->root->fetchMoreChildren(); 0040 } 0041 0042 TreeModel::~TreeModel() 0043 { 0044 Q_D(TreeModel); 0045 0046 delete d->root; 0047 } 0048 0049 int TreeModel::columnCount(const QModelIndex &parent) const 0050 { 0051 Q_D(const TreeModel); 0052 0053 Q_UNUSED(parent); 0054 return d->headers.size(); 0055 } 0056 0057 QVariant TreeModel::data(const QModelIndex &index, int role) const 0058 { 0059 if (!index.isValid()) 0060 return QVariant(); 0061 0062 auto *item = static_cast<TreeItem*>(index.internalPointer()); 0063 if (role == ItemRole) 0064 return QVariant::fromValue(item); 0065 0066 return item->data(index.column(), role); 0067 } 0068 0069 Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const 0070 { 0071 if (!index.isValid()) 0072 return Qt::NoItemFlags; 0073 0074 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 0075 } 0076 0077 QVariant TreeModel::headerData(int section, Qt::Orientation orientation, 0078 int role) const 0079 { 0080 Q_D(const TreeModel); 0081 0082 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) 0083 return d->headers.value(section); 0084 0085 return QVariant(); 0086 } 0087 0088 QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) 0089 const 0090 { 0091 Q_D(const TreeModel); 0092 0093 if (!hasIndex(row, column, parent)) 0094 return QModelIndex(); 0095 0096 TreeItem *parentItem; 0097 0098 if (!parent.isValid()) 0099 parentItem = d->root; 0100 else 0101 parentItem = static_cast<TreeItem*>(parent.internalPointer()); 0102 0103 TreeItem *childItem = parentItem->child(row); 0104 if (childItem) 0105 return createIndex(row, column, childItem); 0106 else 0107 return createIndex(row, column, nullptr); 0108 } 0109 0110 QModelIndex TreeModel::parent(const QModelIndex &index) const 0111 { 0112 Q_D(const TreeModel); 0113 0114 if (!index.isValid()) 0115 return QModelIndex(); 0116 0117 auto *childItem = static_cast<TreeItem*>(index.internalPointer()); 0118 TreeItem *parentItem = childItem->parent(); 0119 0120 if (parentItem == d->root) 0121 return QModelIndex(); 0122 0123 return createIndex(parentItem->row(), 0, parentItem); 0124 } 0125 0126 int TreeModel::rowCount(const QModelIndex &parent) const 0127 { 0128 Q_D(const TreeModel); 0129 0130 TreeItem *parentItem; 0131 if (parent.column() > 0) 0132 return 0; 0133 0134 if (!parent.isValid()) 0135 parentItem = d->root; 0136 else 0137 parentItem = static_cast<TreeItem*>(parent.internalPointer()); 0138 0139 if(parentItem) 0140 return parentItem->childCount(); 0141 else 0142 return 0; 0143 } 0144 0145 TreeItem* TreeModel::itemForIndex(const QModelIndex& index) const 0146 { 0147 Q_D(const TreeModel); 0148 0149 if (!index.isValid()) 0150 return d->root; 0151 else 0152 return static_cast<TreeItem*>(index.internalPointer()); 0153 } 0154 0155 QModelIndex TreeModel::indexForItem(TreeItem *item, int column) const 0156 { 0157 if (item->parent() == nullptr) 0158 return QModelIndex(); 0159 0160 if (TreeItem* parent = item->parent()) 0161 { 0162 /* FIXME: we might store row directly in item. */ 0163 int row = parent->childItems.indexOf(item); 0164 Q_ASSERT(row != -1); 0165 0166 return createIndex(row, column, item); 0167 } 0168 else 0169 { 0170 return QModelIndex(); 0171 } 0172 } 0173 0174 void TreeModel::expanded(const QModelIndex &index) 0175 { 0176 TreeItem* item = itemForIndex(index); 0177 QObject::connect(item, &TreeItem::allChildrenFetched, this, &TreeModel::itemChildrenReady); 0178 if (item->hasMore() && item->childCount() == 1) 0179 item->fetchMoreChildren(); 0180 else 0181 emit itemChildrenReady(); 0182 item->setExpanded(true); 0183 } 0184 0185 void TreeModel::collapsed(const QModelIndex &index) 0186 { 0187 TreeItem* item = itemForIndex(index); 0188 item->setExpanded(false); 0189 } 0190 0191 void TreeModel::clicked(const QModelIndex &index) 0192 { 0193 TreeItem* item = itemForIndex(index); 0194 item->clicked(); 0195 } 0196 0197 bool TreeModel::setData(const QModelIndex& index, const QVariant& value, 0198 int role) 0199 { 0200 /* FIXME: CheckStateRole is dirty. Should we pass the role to 0201 the item? */ 0202 if (index.isValid() 0203 && (role == Qt::EditRole || role == Qt::CheckStateRole)) 0204 { 0205 0206 auto *item = static_cast<TreeItem*>(index.internalPointer()); 0207 item->setColumn(index.column(), value); 0208 return true; 0209 } 0210 return false; 0211 } 0212 0213 KDevelop::TreeItem* KDevelop::TreeModel::root() const 0214 { 0215 Q_D(const TreeModel); 0216 0217 return d->root; 0218 } 0219 0220 #include "moc_treemodel.cpp"