File indexing completed on 2024-05-12 04:37:43
0001 /* 0002 SPDX-FileCopyrightText: 2007-2008 Hamish Rodda <rodda@kde.org> 0003 SPDX-FileCopyrightText: 2009 Lior Mualem <lior.m.kde@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "classmodel.h" 0009 #include "classmodelnode.h" 0010 #include "allclassesfolder.h" 0011 #include "projectfolder.h" 0012 #include "../duchain/declaration.h" 0013 #include <typeinfo> 0014 0015 #include "../../interfaces/icore.h" 0016 #include "../../interfaces/iproject.h" 0017 #include "../../interfaces/iprojectcontroller.h" 0018 0019 using namespace KDevelop; 0020 using namespace ClassModelNodes; 0021 0022 ////////////////////////////////////////////////////////////////////////////// 0023 ////////////////////////////////////////////////////////////////////////////// 0024 0025 NodesModelInterface::~NodesModelInterface() 0026 { 0027 } 0028 0029 ////////////////////////////////////////////////////////////////////////////// 0030 ////////////////////////////////////////////////////////////////////////////// 0031 0032 ClassModel::ClassModel() 0033 : m_features(NodesModelInterface::AllProjectsClasses | 0034 NodesModelInterface::BaseAndDerivedClasses | 0035 NodesModelInterface::ClassInternals) 0036 { 0037 m_topNode = new FolderNode(QStringLiteral("Top Node"), this); 0038 0039 if (features().testFlag(NodesModelInterface::AllProjectsClasses)) { 0040 m_allClassesNode = new FilteredAllClassesFolder(this); 0041 m_topNode->addNode(m_allClassesNode); 0042 } 0043 0044 connect(ICore::self()->projectController(), &IProjectController::projectClosing, 0045 this, &ClassModel::removeProjectNode); 0046 connect(ICore::self()->projectController(), &IProjectController::projectOpened, 0047 this, &ClassModel::addProjectNode); 0048 0049 const auto projects = ICore::self()->projectController()->projects(); 0050 for (IProject* project : projects) { 0051 addProjectNode(project); 0052 } 0053 } 0054 0055 ClassModel::~ClassModel() 0056 { 0057 delete m_topNode; 0058 } 0059 0060 void ClassModel::updateFilterString(const QString& a_newFilterString) 0061 { 0062 m_allClassesNode->updateFilterString(a_newFilterString); 0063 for (ClassModelNodes::FilteredProjectFolder* folder : qAsConst(m_projectNodes)) { 0064 folder->updateFilterString(a_newFilterString); 0065 } 0066 } 0067 0068 void ClassModel::collapsed(const QModelIndex& index) 0069 { 0070 Node* node = static_cast<Node*>(index.internalPointer()); 0071 0072 node->collapse(); 0073 } 0074 0075 void ClassModel::expanded(const QModelIndex& index) 0076 { 0077 Node* node = static_cast<Node*>(index.internalPointer()); 0078 0079 node->expand(); 0080 } 0081 0082 QFlags<Qt::ItemFlag> ClassModel::flags(const QModelIndex&) const 0083 { 0084 return Qt::ItemIsSelectable | Qt::ItemIsEnabled; 0085 } 0086 0087 int ClassModel::rowCount(const QModelIndex& parent) const 0088 { 0089 Node* node = m_topNode; 0090 0091 if (parent.isValid()) 0092 node = static_cast<Node*>(parent.internalPointer()); 0093 0094 return node->children().size(); 0095 } 0096 0097 QVariant ClassModel::data(const QModelIndex& index, int role) const 0098 { 0099 if (!index.isValid()) 0100 return QVariant(); 0101 0102 Node* node = static_cast<Node*>(index.internalPointer()); 0103 0104 if (role == Qt::DisplayRole) 0105 return node->displayName(); 0106 0107 if (role == Qt::DecorationRole) { 0108 QIcon icon = node->cachedIcon(); 0109 return icon.isNull() ? QVariant() : icon; 0110 } 0111 0112 return QVariant(); 0113 } 0114 0115 QVariant ClassModel::headerData(int, Qt::Orientation, int role) const 0116 { 0117 if (role == Qt::DisplayRole) 0118 return QStringLiteral("Class"); 0119 0120 return QVariant(); 0121 } 0122 0123 int ClassModel::columnCount(const QModelIndex&) const 0124 { 0125 return 1; 0126 } 0127 0128 bool ClassModel::hasChildren(const QModelIndex& parent) const 0129 { 0130 if (!parent.isValid()) 0131 return true; 0132 0133 Node* node = static_cast<Node*>(parent.internalPointer()); 0134 0135 return node->hasChildren(); 0136 } 0137 0138 QModelIndex ClassModel::index(int row, int column, const QModelIndex& parent) const 0139 { 0140 if (row < 0 || column != 0) 0141 return QModelIndex(); 0142 0143 Node* node = m_topNode; 0144 if (parent.isValid()) 0145 node = static_cast<Node*>(parent.internalPointer()); 0146 0147 if (row >= node->children().size()) 0148 return QModelIndex(); 0149 0150 return index(node->children()[row]); 0151 } 0152 0153 QModelIndex ClassModel::parent(const QModelIndex& childIndex) const 0154 { 0155 if (!childIndex.isValid()) 0156 return QModelIndex(); 0157 0158 Node* childNode = static_cast<Node*>(childIndex.internalPointer()); 0159 0160 if (childNode->parent() == m_topNode) 0161 return QModelIndex(); 0162 0163 return index(childNode->parent()); 0164 } 0165 0166 QModelIndex ClassModel::index(ClassModelNodes::Node* a_node) const 0167 { 0168 if (!a_node) { 0169 return QModelIndex(); 0170 } 0171 0172 // If no parent exists, we have an invalid index (root node or not part of a model). 0173 if (a_node->parent() == nullptr) 0174 return QModelIndex(); 0175 0176 return createIndex(a_node->row(), 0, a_node); 0177 } 0178 0179 KDevelop::DUChainBase* ClassModel::duObjectForIndex(const QModelIndex& a_index) 0180 { 0181 if (!a_index.isValid()) 0182 return nullptr; 0183 0184 Node* node = static_cast<Node*>(a_index.internalPointer()); 0185 0186 if (auto* identifierNode = dynamic_cast<IdentifierNode*>(node)) 0187 return identifierNode->declaration(); 0188 0189 // Non was found. 0190 return nullptr; 0191 } 0192 0193 QModelIndex ClassModel::indexForIdentifier(const KDevelop::IndexedQualifiedIdentifier& a_id) 0194 { 0195 ClassNode* node = m_allClassesNode->findClassNode(a_id); 0196 if (node == nullptr) 0197 return QModelIndex(); 0198 0199 return index(node); 0200 } 0201 0202 void ClassModel::nodesLayoutAboutToBeChanged(ClassModelNodes::Node*) 0203 { 0204 emit layoutAboutToBeChanged(); 0205 } 0206 0207 void ClassModel::nodesLayoutChanged(ClassModelNodes::Node*) 0208 { 0209 const QModelIndexList oldIndexList = persistentIndexList(); 0210 QModelIndexList newIndexList; 0211 0212 newIndexList.reserve(oldIndexList.size()); 0213 for (const QModelIndex& oldIndex : oldIndexList) { 0214 Node* node = static_cast<Node*>(oldIndex.internalPointer()); 0215 if (node) { 0216 // Re-map the index. 0217 newIndexList << createIndex(node->row(), 0, node); 0218 } else 0219 newIndexList << oldIndex; 0220 } 0221 0222 changePersistentIndexList(oldIndexList, newIndexList); 0223 0224 emit layoutChanged(); 0225 } 0226 0227 void ClassModel::nodesAboutToBeRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) 0228 { 0229 beginRemoveRows(index(a_parent), a_first, a_last); 0230 } 0231 0232 void ClassModel::nodesRemoved(ClassModelNodes::Node*) 0233 { 0234 endRemoveRows(); 0235 } 0236 0237 void ClassModel::nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) 0238 { 0239 beginInsertRows(index(a_parent), a_pos, a_pos + a_size - 1); 0240 } 0241 0242 void ClassModel::nodesAdded(ClassModelNodes::Node*) 0243 { 0244 endInsertRows(); 0245 } 0246 0247 void ClassModel::addProjectNode(IProject* project) 0248 { 0249 m_projectNodes[project] = new ClassModelNodes::FilteredProjectFolder(this, project); 0250 nodesLayoutAboutToBeChanged(m_projectNodes[project]); 0251 m_topNode->addNode(m_projectNodes[project]); 0252 nodesLayoutChanged(m_projectNodes[project]); 0253 } 0254 0255 void ClassModel::removeProjectNode(IProject* project) 0256 { 0257 m_topNode->removeNode(m_projectNodes[project]); 0258 m_projectNodes.remove(project); 0259 } 0260 0261 #include "moc_classmodel.cpp"