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 "treeitem.h" 0008 0009 #include <QModelIndex> 0010 0011 #include <debug.h> 0012 #include "treemodel.h" 0013 0014 using namespace KDevelop; 0015 0016 TreeItem::TreeItem(TreeModel* model, TreeItem *parent) 0017 : model_(model), more_(false), ellipsis_(nullptr), expanded_(false) 0018 { 0019 parentItem = parent; 0020 } 0021 0022 TreeItem::~TreeItem() 0023 { 0024 const auto copy = childItems; 0025 for (TreeItem* it : copy) { 0026 delete it; 0027 } 0028 delete ellipsis_; 0029 } 0030 0031 void TreeItem::setData(const QVector<QVariant> &data) 0032 { 0033 itemData=data; 0034 } 0035 0036 void TreeItem::appendChild(TreeItem *item, bool initial) 0037 { 0038 QModelIndex index = model_->indexForItem(this, 0); 0039 0040 // Note that we need emit beginRemoveRows, even if we're replacing 0041 // ellipsis item with the real one. The number of rows does not change 0042 // with the result, but the last item is different. The address of the 0043 // item is stored inside QModelIndex, so just replacing the item, and 0044 // deleting the old one, will lead to crash. 0045 if (more_) 0046 { 0047 if (!initial) 0048 model_->beginRemoveRows(index, childItems.size(), childItems.size()); 0049 more_ = false; 0050 delete ellipsis_; 0051 ellipsis_ = nullptr; 0052 if (!initial) 0053 model_->endRemoveRows(); 0054 } 0055 0056 if (!initial) 0057 model_->beginInsertRows(index, childItems.size(), childItems.size()); 0058 childItems.append(item); 0059 if (!initial) 0060 model_->endInsertRows(); 0061 } 0062 0063 void TreeItem::insertChild(int position, TreeItem *child, bool initial) 0064 { 0065 QModelIndex index = model_->indexForItem(this, 0); 0066 0067 if (!initial) 0068 model_->beginInsertRows(index, position, position); 0069 childItems.insert(position, child); 0070 if (!initial) 0071 model_->endInsertRows(); 0072 } 0073 0074 void TreeItem::reportChange() 0075 { 0076 QModelIndex index = model_->indexForItem(this, 0); 0077 QModelIndex index2 = model_->indexForItem(this, itemData.size()-1); 0078 emit model_->dataChanged(index, index2); 0079 } 0080 0081 void KDevelop::TreeItem::reportChange(int column) 0082 { 0083 QModelIndex index = model_->indexForItem(this, column); 0084 emit model_->dataChanged(index, index); 0085 } 0086 0087 0088 void TreeItem::removeChild(int index) 0089 { 0090 QModelIndex modelIndex = model_->indexForItem(this, 0); 0091 0092 model_->beginRemoveRows(modelIndex, index, index); 0093 childItems.erase(childItems.begin() + index); 0094 model_->endRemoveRows(); 0095 } 0096 0097 void TreeItem::removeSelf() 0098 { 0099 QModelIndex modelIndex = model_->indexForItem(this, 0); 0100 parentItem->removeChild(modelIndex.row()); 0101 } 0102 0103 void TreeItem::deleteChildren() 0104 { 0105 QVector<TreeItem*> copy = childItems; 0106 clear(); 0107 // Only delete the children after removing them 0108 // from model. Otherwise, the model will touch 0109 // deleted things, with undefined results. 0110 qDeleteAll(copy); 0111 } 0112 0113 void TreeItem::clear() 0114 { 0115 if (!childItems.isEmpty() || more_) 0116 { 0117 QModelIndex index = model_->indexForItem(this, 0); 0118 model_->beginRemoveRows(index, 0, childItems.size()-1+more_); 0119 childItems.clear(); 0120 more_ = false; 0121 delete ellipsis_; 0122 ellipsis_ = nullptr; 0123 model_->endRemoveRows(); 0124 } 0125 } 0126 0127 TreeItem *TreeItem::child(int row) 0128 { 0129 if (row < childItems.size()) 0130 return childItems.value(row); 0131 else if (row == childItems.size() && more_) 0132 return ellipsis_; 0133 else 0134 return nullptr; 0135 0136 } 0137 0138 int TreeItem::childCount() const 0139 { 0140 return childItems.count() + more_; 0141 } 0142 0143 int TreeItem::columnCount() const 0144 { 0145 return itemData.count(); 0146 } 0147 0148 QVariant TreeItem::data(int column, int role) const 0149 { 0150 if (role == Qt::DecorationRole) 0151 return icon(column); 0152 else if (role==Qt::DisplayRole || role == Qt::EditRole) 0153 return itemData.value(column); 0154 return QVariant(); 0155 } 0156 0157 TreeItem *TreeItem::parent() 0158 { 0159 return parentItem; 0160 } 0161 0162 int TreeItem::row() const 0163 { 0164 if (parentItem) 0165 return parentItem->childItems.indexOf(const_cast<TreeItem*>(this)); 0166 0167 return 0; 0168 } 0169 0170 class EllipsisItem : public TreeItem 0171 { 0172 Q_OBJECT 0173 public: 0174 EllipsisItem(TreeModel *model, TreeItem *parent) 0175 : TreeItem(model, parent) 0176 { 0177 const int dataCount = model->columnCount(QModelIndex()); 0178 QVector<QVariant> data; 0179 data.reserve(dataCount); 0180 data.push_back(QVariant(QStringLiteral("..."))); 0181 for (int i = 1; i < dataCount; ++i) 0182 data.push_back(QString()); 0183 setData(data); 0184 } 0185 0186 void clicked() override 0187 { 0188 qCDebug(DEBUGGER) << "Ellipsis item clicked"; 0189 /* FIXME: restore 0190 Q_ASSERT (parentItem->hasMore()); */ 0191 parentItem->fetchMoreChildren(); 0192 } 0193 0194 void fetchMoreChildren() override {} 0195 }; 0196 0197 void TreeItem::setHasMore(bool more) 0198 { 0199 /* FIXME: this will crash if used in ctor of root item, 0200 where the model is not associated with item or something. */ 0201 QModelIndex index = model_->indexForItem(this, 0); 0202 0203 if (more && !more_) 0204 { 0205 model_->beginInsertRows(index, childItems.size(), childItems.size()); 0206 ellipsis_ = new EllipsisItem (model(), this); 0207 more_ = more; 0208 model_->endInsertRows(); 0209 } 0210 else if (!more && more_) 0211 { 0212 model_->beginRemoveRows(index, childItems.size(), childItems.size()); 0213 delete ellipsis_; 0214 ellipsis_ = nullptr; 0215 more_ = more; 0216 model_->endRemoveRows(); 0217 } 0218 } 0219 0220 void TreeItem::emitAllChildrenFetched() 0221 { 0222 emit allChildrenFetched(); 0223 } 0224 0225 void TreeItem::setHasMoreInitial(bool more) 0226 { 0227 more_ = more; 0228 0229 if (more) 0230 { 0231 ellipsis_ = new EllipsisItem (model(), this); 0232 } 0233 } 0234 0235 QVariant KDevelop::TreeItem::icon(int column) const 0236 { 0237 Q_UNUSED(column); 0238 return QVariant(); 0239 } 0240 0241 void KDevelop::TreeItem::setExpanded(bool b) 0242 { 0243 if (expanded_ != b) { 0244 expanded_ = b; 0245 if (expanded_) emit expanded(); 0246 else emit collapsed(); 0247 } 0248 } 0249 0250 #include "treeitem.moc" 0251 #include "moc_treeitem.cpp"