diff --git a/language/CMakeLists.txt b/language/CMakeLists.txt index 2c2b0285b6..7d2ca5d307 100644 --- a/language/CMakeLists.txt +++ b/language/CMakeLists.txt @@ -1,383 +1,400 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kdevplatform\") add_subdirectory(highlighting/tests) add_subdirectory(duchain/tests) add_subdirectory(backgroundparser/tests) add_subdirectory(codegen/tests) set(KDevPlatformLanguage_LIB_SRCS assistant/staticassistantsmanager.cpp assistant/renameaction.cpp assistant/renameassistant.cpp assistant/renamefileaction.cpp assistant/staticassistant.cpp editor/persistentmovingrangeprivate.cpp editor/persistentmovingrange.cpp editor/modificationrevisionset.cpp editor/modificationrevision.cpp backgroundparser/backgroundparser.cpp backgroundparser/parsejob.cpp backgroundparser/documentchangetracker.cpp backgroundparser/parseprojectjob.cpp backgroundparser/urlparselock.cpp duchain/specializationstore.cpp duchain/codemodel.cpp duchain/duchain.cpp duchain/waitforupdate.cpp duchain/duchainpointer.cpp duchain/ducontext.cpp duchain/indexedducontext.cpp duchain/indexedtopducontext.cpp duchain/localindexedducontext.cpp duchain/indexeddeclaration.cpp duchain/localindexeddeclaration.cpp duchain/topducontext.cpp duchain/topducontextdynamicdata.cpp duchain/topducontextutils.cpp duchain/functiondefinition.cpp duchain/declaration.cpp duchain/classmemberdeclaration.cpp duchain/classfunctiondeclaration.cpp duchain/classdeclaration.cpp duchain/use.cpp duchain/forwarddeclaration.cpp duchain/duchainbase.cpp duchain/duchainlock.cpp duchain/identifier.cpp duchain/parsingenvironment.cpp duchain/abstractfunctiondeclaration.cpp duchain/functiondeclaration.cpp duchain/stringhelpers.cpp duchain/namespacealiasdeclaration.cpp duchain/aliasdeclaration.cpp duchain/dumpdotgraph.cpp duchain/duchainutils.cpp duchain/declarationid.cpp duchain/definitions.cpp duchain/uses.cpp duchain/importers.cpp duchain/duchaindumper.cpp duchain/duchainregister.cpp duchain/persistentsymboltable.cpp duchain/instantiationinformation.cpp duchain/problem.cpp duchain/types/typesystem.cpp duchain/types/typeregister.cpp duchain/types/typerepository.cpp duchain/types/identifiedtype.cpp duchain/types/abstracttype.cpp duchain/types/integraltype.cpp duchain/types/functiontype.cpp duchain/types/structuretype.cpp duchain/types/pointertype.cpp duchain/types/referencetype.cpp duchain/types/delayedtype.cpp duchain/types/arraytype.cpp duchain/types/indexedtype.cpp duchain/types/enumerationtype.cpp duchain/types/constantintegraltype.cpp duchain/types/enumeratortype.cpp duchain/types/typeutils.cpp duchain/types/typealiastype.cpp duchain/types/unsuretype.cpp duchain/types/containertypes.cpp duchain/builders/dynamiclanguageexpressionvisitor.cpp duchain/navigation/problemnavigationcontext.cpp duchain/navigation/abstractnavigationwidget.cpp duchain/navigation/abstractnavigationcontext.cpp duchain/navigation/usesnavigationcontext.cpp duchain/navigation/abstractdeclarationnavigationcontext.cpp duchain/navigation/abstractincludenavigationcontext.cpp duchain/navigation/useswidget.cpp duchain/navigation/usescollector.cpp interfaces/abbreviations.cpp interfaces/iastcontainer.cpp interfaces/ilanguagesupport.cpp interfaces/quickopendataprovider.cpp interfaces/iquickopen.cpp interfaces/editorcontext.cpp interfaces/codecontext.cpp interfaces/icreateclasshelper.cpp interfaces/icontextbrowser.cpp codecompletion/codecompletion.cpp codecompletion/codecompletionworker.cpp codecompletion/codecompletionmodel.cpp codecompletion/codecompletionitem.cpp codecompletion/codecompletioncontext.cpp codecompletion/codecompletionitemgrouper.cpp codecompletion/codecompletionhelper.cpp codecompletion/normaldeclarationcompletionitem.cpp codegen/applychangeswidget.cpp codegen/coderepresentation.cpp codegen/documentchangeset.cpp codegen/duchainchangeset.cpp codegen/utilities.cpp codegen/codedescription.cpp codegen/basicrefactoring.cpp codegen/progressdialogs/refactoringdialog.cpp util/setrepository.cpp util/includeitem.cpp util/navigationtooltip.cpp util/debug.cpp highlighting/colorcache.cpp highlighting/configurablecolors.cpp highlighting/codehighlighting.cpp checks/dataaccessrepository.cpp checks/dataaccess.cpp checks/controlflowgraph.cpp checks/controlflownode.cpp + + classmodel/classmodel.cpp + classmodel/classmodelnode.cpp + classmodel/classmodelnodescontroller.cpp + classmodel/allclassesfolder.cpp + classmodel/documentclassesfolder.cpp + classmodel/projectfolder.cpp ) set(grantlee_LIB_SRCS codegen/templatesmodel.cpp codegen/templateclassgenerator.cpp codegen/sourcefiletemplate.cpp codegen/templaterenderer.cpp codegen/templateengine.cpp codegen/archivetemplateloader.cpp ) if (Grantlee5_FOUND) list(APPEND KDevPlatformLanguage_LIB_SRCS ${grantlee_LIB_SRCS}) endif() ki18n_wrap_ui(KDevPlatformLanguage_LIB_SRCS codegen/basicrefactoring.ui codegen/progressdialogs/refactoringdialog.ui) add_library(KDevPlatformLanguage ${KDevPlatformLanguage_LIB_SRCS}) add_library(KDev::Language ALIAS KDevPlatformLanguage) generate_export_header(KDevPlatformLanguage EXPORT_FILE_NAME languageexport.h) target_link_libraries(KDevPlatformLanguage LINK_PUBLIC KF5::ThreadWeaver KDev::Interfaces KDev::Serialization LINK_PRIVATE KF5::GuiAddons KF5::TextEditor KF5::Parts KF5::Archive KDev::Util KDev::Project ) if (Grantlee5_FOUND) target_link_libraries(KDevPlatformLanguage LINK_PRIVATE Grantlee5::Templates) endif() set_target_properties(KDevPlatformLanguage PROPERTIES VERSION ${KDEVPLATFORM_LIB_VERSION} SOVERSION ${KDEVPLATFORM_LIB_SOVERSION} EXPORT_NAME Language) install(TARGETS KDevPlatformLanguage EXPORT KDevPlatformTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) ########### install files ############### install(FILES ${CMAKE_CURRENT_BINARY_DIR}/languageexport.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language COMPONENT Devel ) install(FILES assistant/renameaction.h assistant/renameassistant.h assistant/staticassistant.h assistant/staticassistantsmanager.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/assistant COMPONENT Devel ) install(FILES interfaces/ilanguagesupport.h interfaces/icodehighlighting.h interfaces/quickopendataprovider.h interfaces/quickopenfilter.h interfaces/iquickopen.h interfaces/codecontext.h interfaces/editorcontext.h interfaces/iastcontainer.h interfaces/icreateclasshelper.h interfaces/icontextbrowser.h interfaces/abbreviations.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/interfaces COMPONENT Devel ) install(FILES editor/persistentmovingrange.h editor/documentrange.h editor/documentcursor.h editor/cursorinrevision.h editor/rangeinrevision.h editor/modificationrevision.h editor/modificationrevisionset.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/editor COMPONENT Devel ) install(FILES backgroundparser/backgroundparser.h backgroundparser/parsejob.h backgroundparser/parseprojectjob.h backgroundparser/urlparselock.h backgroundparser/documentchangetracker.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/backgroundparser COMPONENT Devel ) install(FILES util/navigationtooltip.h util/setrepository.h util/basicsetrepository.h util/includeitem.h util/debuglanguageparserhelper.h util/kdevhash.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/util COMPONENT Devel ) install(FILES duchain/parsingenvironment.h duchain/duchain.h duchain/codemodel.h duchain/ducontext.h duchain/ducontextdata.h duchain/topducontext.h duchain/topducontextutils.h duchain/topducontextdata.h duchain/declaration.h duchain/declarationdata.h duchain/classmemberdeclaration.h duchain/classmemberdeclarationdata.h duchain/classfunctiondeclaration.h duchain/classdeclaration.h duchain/functiondefinition.h duchain/use.h duchain/forwarddeclaration.h duchain/duchainbase.h duchain/duchainpointer.h duchain/duchainlock.h duchain/identifier.h duchain/abstractfunctiondeclaration.h duchain/functiondeclaration.h duchain/stringhelpers.h duchain/safetycounter.h duchain/namespacealiasdeclaration.h duchain/aliasdeclaration.h duchain/dumpdotgraph.h duchain/duchainutils.h duchain/duchaindumper.h duchain/declarationid.h duchain/appendedlist.h duchain/duchainregister.h duchain/persistentsymboltable.h duchain/instantiationinformation.h duchain/specializationstore.h duchain/persistentsetmap.h duchain/indexedducontext.h duchain/indexedtopducontext.h duchain/localindexedducontext.h duchain/indexeddeclaration.h duchain/localindexeddeclaration.h duchain/definitions.h duchain/problem.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/duchain COMPONENT Devel ) install(FILES duchain/types/unsuretype.h duchain/types/identifiedtype.h duchain/types/typesystem.h duchain/types/typeregister.h duchain/types/typerepository.h duchain/types/typepointer.h duchain/types/typesystemdata.h duchain/types/abstracttype.h duchain/types/integraltype.h duchain/types/functiontype.h duchain/types/structuretype.h duchain/types/pointertype.h duchain/types/referencetype.h duchain/types/delayedtype.h duchain/types/arraytype.h duchain/types/indexedtype.h duchain/types/enumerationtype.h duchain/types/constantintegraltype.h duchain/types/enumeratortype.h duchain/types/alltypes.h duchain/types/typeutils.h duchain/types/typealiastype.h duchain/types/containertypes.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/duchain/types COMPONENT Devel ) install(FILES duchain/builders/abstractcontextbuilder.h duchain/builders/abstractdeclarationbuilder.h duchain/builders/abstracttypebuilder.h duchain/builders/abstractusebuilder.h duchain/builders/dynamiclanguageexpressionvisitor.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/duchain/builders COMPONENT Devel ) install(FILES codecompletion/codecompletion.h codecompletion/codecompletionworker.h codecompletion/codecompletionmodel.h codecompletion/codecompletionitem.h codecompletion/codecompletioncontext.h codecompletion/codecompletionitemgrouper.h codecompletion/codecompletionhelper.h codecompletion/normaldeclarationcompletionitem.h codecompletion/abstractincludefilecompletionitem.h codecompletion/codecompletiontesthelper.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/codecompletion COMPONENT Devel ) install(FILES codegen/applychangeswidget.h codegen/astchangeset.h codegen/duchainchangeset.h codegen/documentchangeset.h codegen/coderepresentation.h codegen/utilities.h codegen/templatesmodel.h codegen/templaterenderer.h codegen/templateengine.h codegen/sourcefiletemplate.h codegen/templateclassgenerator.h codegen/codedescription.h codegen/basicrefactoring.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/codegen COMPONENT Devel ) install(FILES duchain/navigation/usesnavigationcontext.h duchain/navigation/abstractnavigationcontext.h duchain/navigation/abstractdeclarationnavigationcontext.h duchain/navigation/abstractincludenavigationcontext.h duchain/navigation/abstractnavigationwidget.h duchain/navigation/navigationaction.h duchain/navigation/useswidget.h duchain/navigation/usescollector.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/duchain/navigation COMPONENT Devel ) install(FILES highlighting/codehighlighting.h highlighting/colorcache.h highlighting/configurablecolors.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/highlighting COMPONENT Devel ) install(FILES checks/dataaccess.h checks/dataaccessrepository.h checks/controlflowgraph.h checks/controlflownode.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/checks COMPONENT Devel ) + +install(FILES + classmodel/classmodel.h + classmodel/classmodelnode.h + classmodel/classmodelnodescontroller.h + classmodel/allclassesfolder.h + classmodel/documentclassesfolder.h + classmodel/projectfolder.h + DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kdevplatform/language/classmodel COMPONENT Devel +) diff --git a/plugins/classbrowser/allclassesfolder.cpp b/language/classmodel/allclassesfolder.cpp similarity index 99% rename from plugins/classbrowser/allclassesfolder.cpp rename to language/classmodel/allclassesfolder.cpp index 6b40a44fea..654cccf51c 100644 --- a/plugins/classbrowser/allclassesfolder.cpp +++ b/language/classmodel/allclassesfolder.cpp @@ -1,132 +1,132 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "allclassesfolder.h" -#include +#include "../../interfaces/icore.h" #include #include #include using namespace KDevelop; using namespace ClassModelNodes; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// AllClassesFolder::AllClassesFolder(NodesModelInterface* a_model) : DocumentClassesFolder(i18n("All projects classes"), a_model) { } void AllClassesFolder::nodeCleared() { DocumentClassesFolder::nodeCleared(); disconnect(ICore::self()->projectController(), &IProjectController::projectOpened, this, &AllClassesFolder::projectOpened); disconnect(ICore::self()->projectController(), &IProjectController::projectClosing, this, &AllClassesFolder::projectClosing); } void AllClassesFolder::populateNode() { DocumentClassesFolder::populateNode(); // Get notification for future project addition / removal. connect (ICore::self()->projectController(), &IProjectController::projectOpened, this, &AllClassesFolder::projectOpened); connect (ICore::self()->projectController(), &IProjectController::projectClosing, this, &AllClassesFolder::projectClosing); // Parse each existing project file foreach(IProject* project, ICore::self()->projectController()->projects()) { projectOpened(project); } } void AllClassesFolder::projectClosing(KDevelop::IProject* project) { // Run over all the files in the project. foreach(const IndexedString& file, project->fileSet()) closeDocument(file); } void AllClassesFolder::projectOpened(KDevelop::IProject* project) { // Run over all the files in the project. foreach(const IndexedString& file, project->fileSet()) parseDocument(file); recursiveSort(); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// FilteredAllClassesFolder::FilteredAllClassesFolder(NodesModelInterface* a_model) : AllClassesFolder(a_model) { } void FilteredAllClassesFolder::updateFilterString(QString a_newFilterString) { m_filterString = a_newFilterString; if ( isPopulated() ) { #if 1 // Choose speed over correctness. // Close the node and re-open it should be quicker than reload each document // and remove indevidual nodes (at the cost of loosing the current selection). performPopulateNode(true); #else bool hadChanges = false; // Reload the documents. foreach( const IndexedString& file, getAllOpenDocuments() ) hadChanges |= updateDocument(file); // Sort if we've updated documents. if ( hadChanges ) recursiveSort(); else { // If nothing changed, the title changed so mark the node as updated. m_model->nodesLayoutAboutToBeChanged(this); m_model->nodesLayoutChanged(this); } #endif } else { // Displayed name changed only... m_model->nodesLayoutAboutToBeChanged(this); m_model->nodesLayoutChanged(this); } } bool FilteredAllClassesFolder::isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) { return !a_id.last().toString().contains(m_filterString, Qt::CaseInsensitive); } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/allclassesfolder.h b/language/classmodel/allclassesfolder.h similarity index 95% rename from plugins/classbrowser/allclassesfolder.h rename to language/classmodel/allclassesfolder.h index 48544d284e..f97f9f0c3d 100644 --- a/plugins/classbrowser/allclassesfolder.h +++ b/language/classmodel/allclassesfolder.h @@ -1,74 +1,74 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KDEVPLATFORM_PLUGIN_ALLCLASSESFOLDER_H -#define KDEVPLATFORM_PLUGIN_ALLCLASSESFOLDER_H +#ifndef KDEVPLATFORM_ALLCLASSESFOLDER_H +#define KDEVPLATFORM_ALLCLASSESFOLDER_H #include "documentclassesfolder.h" namespace KDevelop { class IProject; } namespace ClassModelNodes { /// Special folder. /// It displays all the classes in the projects by using the IProject class AllClassesFolder : public DocumentClassesFolder { Q_OBJECT public: explicit AllClassesFolder(NodesModelInterface* a_model); public: // Node overrides virtual void nodeCleared() override; virtual void populateNode() override; private Q_SLOTS: // Project watching void projectOpened(KDevelop::IProject* project); void projectClosing(KDevelop::IProject* project); }; /// Contains a filter for the all classes folder. class FilteredAllClassesFolder : public AllClassesFolder { Q_OBJECT public: explicit FilteredAllClassesFolder(NodesModelInterface* a_model); public: // Operations. /// Call this to update the classes filter string. void updateFilterString(QString a_newFilterString); private: // DocumentClassesFolder overrides virtual bool isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) override; private: /// We'll use this string to display only classes that match this string. QString m_filterString; }; } // namespace ClassModelNodes #endif diff --git a/plugins/classbrowser/classmodel.cpp b/language/classmodel/classmodel.cpp similarity index 97% rename from plugins/classbrowser/classmodel.cpp rename to language/classmodel/classmodel.cpp index 4aff279fb7..535da1fae7 100644 --- a/plugins/classbrowser/classmodel.cpp +++ b/language/classmodel/classmodel.cpp @@ -1,272 +1,272 @@ /* * KDevelop Class Browser * * Copyright 2007-2008 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "classmodel.h" #include "classmodelnode.h" #include "allclassesfolder.h" #include "projectfolder.h" -#include +#include "../duchain/declaration.h" #include -#include -#include -#include +#include "../../interfaces/icore.h" +#include "../../interfaces/iproject.h" +#include "../../interfaces/iprojectcontroller.h" using namespace KDevelop; using namespace ClassModelNodes; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// NodesModelInterface::~NodesModelInterface() { } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ClassModel::ClassModel() { m_topNode = new FolderNode("Top Node", this); m_allClassesNode = new FilteredAllClassesFolder(this); m_topNode->addNode( m_allClassesNode ); connect(ICore::self()->projectController(), &IProjectController::projectClosing, this, &ClassModel::removeProjectNode); connect(ICore::self()->projectController(), &IProjectController::projectOpened, this, &ClassModel::addProjectNode); foreach ( IProject* project, ICore::self()->projectController()->projects() ) { addProjectNode(project); } } ClassModel::~ClassModel() { delete m_topNode; } void ClassModel::updateFilterString(QString a_newFilterString) { m_allClassesNode->updateFilterString(a_newFilterString); foreach ( ClassModelNodes::FilteredProjectFolder* folder, m_projectNodes ) { folder->updateFilterString(a_newFilterString); } } void ClassModel::collapsed(const QModelIndex& index) { Node* node = static_cast(index.internalPointer()); node->collapse(); } void ClassModel::expanded(const QModelIndex& index) { Node* node = static_cast(index.internalPointer()); node->expand(); } QFlags< Qt::ItemFlag > ClassModel::flags(const QModelIndex&) const { return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } int ClassModel::rowCount(const QModelIndex& parent) const { Node* node = m_topNode; if ( parent.isValid() ) node = static_cast(parent.internalPointer()); return node->getChildren().size(); } QVariant ClassModel::data(const QModelIndex& index, int role) const { if ( !index.isValid() ) return QVariant(); Node* node = static_cast(index.internalPointer()); if ( role == Qt::DisplayRole ) return node->displayName(); if ( role == Qt::DecorationRole ) { QIcon icon = node->getCachedIcon(); return icon.isNull() ? QVariant() : icon; } return QVariant(); } QVariant ClassModel::headerData(int, Qt::Orientation, int role) const { if ( role == Qt::DisplayRole ) return "Class"; return QVariant(); } int ClassModel::columnCount(const QModelIndex&) const { return 1; } bool ClassModel::hasChildren(const QModelIndex& parent) const { if ( !parent.isValid() ) return true; Node* node = static_cast(parent.internalPointer()); return node->hasChildren(); } QModelIndex ClassModel::index(int row, int column, const QModelIndex& parent) const { if (row < 0 || column != 0) return QModelIndex(); Node* node = m_topNode; if ( parent.isValid() ) node = static_cast(parent.internalPointer()); if ( row >= node->getChildren().size() ) return QModelIndex(); return index(node->getChildren()[row]); } QModelIndex ClassModel::parent(const QModelIndex& childIndex) const { if ( !childIndex.isValid() ) return QModelIndex(); Node* childNode = static_cast(childIndex.internalPointer()); if ( childNode->getParent() == m_topNode ) return QModelIndex(); return index( childNode->getParent() ); } QModelIndex ClassModel::index(ClassModelNodes::Node* a_node) const { if (!a_node) { return QModelIndex(); } // If no parent exists, we have an invalid index (root node or not part of a model). if ( a_node->getParent() == 0 ) return QModelIndex(); return createIndex(a_node->row(), 0, a_node); } KDevelop::DUChainBase* ClassModel::duObjectForIndex(const QModelIndex& a_index) { if ( !a_index.isValid() ) return 0; Node* node = static_cast(a_index.internalPointer()); if ( IdentifierNode* identifierNode = dynamic_cast(node) ) return identifierNode->getDeclaration(); // Non was found. return 0; } QModelIndex ClassModel::getIndexForIdentifier(const KDevelop::IndexedQualifiedIdentifier& a_id) { ClassNode* node = m_allClassesNode->findClassNode(a_id); if ( node == 0 ) return QModelIndex(); return index(node); } void ClassModel::nodesLayoutAboutToBeChanged(ClassModelNodes::Node*) { emit layoutAboutToBeChanged(); } void ClassModel::nodesLayoutChanged(ClassModelNodes::Node*) { QModelIndexList oldIndexList = persistentIndexList(); QModelIndexList newIndexList; foreach(const QModelIndex& oldIndex, oldIndexList) { Node* node = static_cast(oldIndex.internalPointer()); if ( node ) { // Re-map the index. newIndexList << createIndex(node->row(), 0, node); } else newIndexList << oldIndex; } changePersistentIndexList(oldIndexList, newIndexList); emit layoutChanged(); } void ClassModel::nodesRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) { beginRemoveRows(index(a_parent), a_first, a_last); endRemoveRows(); } void ClassModel::nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) { beginInsertRows(index(a_parent), a_pos, a_pos + a_size - 1); } void ClassModel::nodesAdded(ClassModelNodes::Node*) { endInsertRows(); } void ClassModel::addProjectNode( IProject* project ) { m_projectNodes[project] = new ClassModelNodes::FilteredProjectFolder(this, project); nodesLayoutAboutToBeChanged(m_projectNodes[project]); m_topNode->addNode(m_projectNodes[project]); nodesLayoutChanged(m_projectNodes[project]); } void ClassModel::removeProjectNode( IProject* project ) { m_topNode->removeNode(m_projectNodes[project]); m_projectNodes.remove(project); } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classmodel.h b/language/classmodel/classmodel.h similarity index 95% rename from plugins/classbrowser/classmodel.h rename to language/classmodel/classmodel.h index c6f0d3ae95..bb3331c9a5 100644 --- a/plugins/classbrowser/classmodel.h +++ b/language/classmodel/classmodel.h @@ -1,136 +1,138 @@ /* * KDevelop Class Browser * * Copyright 2007-2008 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KDEVPLATFORM_PLUGIN_CLASSMODEL_H -#define KDEVPLATFORM_PLUGIN_CLASSMODEL_H +#ifndef KDEVPLATFORM_CLASSMODEL_H +#define KDEVPLATFORM_CLASSMODEL_H #include #include "classmodelnode.h" +#include + class ClassBrowserPlugin; namespace KDevelop { class TopDUContext; class IDocument; class ParseJob; class DUContext; class IProject; class DUChainBase; class IndexedQualifiedIdentifier; } namespace ClassModelNodes { class Node; class FilteredAllClassesFolder; class FilteredProjectFolder; class FolderNode; class IdentifierNode; } /// The model interface accessible from the nodes. class NodesModelInterface { public: virtual ~NodesModelInterface(); public: virtual void nodesLayoutAboutToBeChanged(ClassModelNodes::Node* a_parent) = 0; virtual void nodesLayoutChanged(ClassModelNodes::Node* a_parent) = 0; virtual void nodesRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) = 0; virtual void nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) = 0; virtual void nodesAdded(ClassModelNodes::Node* a_parent) = 0; }; /** * @short A model that holds a convinient representation of the defined class in the project * * This model doesn't have much code in it, it mostly acts as a glue between the different * nodes and the tree view. * * The nodes are defined in the namespace @ref ClassModelNodes */ -class ClassModel : public QAbstractItemModel, public NodesModelInterface +class KDEVPLATFORMLANGUAGE_EXPORT ClassModel : public QAbstractItemModel, public NodesModelInterface { Q_OBJECT public: ClassModel(); virtual ~ClassModel(); public: /// Retrieve the DU object related to the specified index. /// @note DUCHAINS READER LOCK MUST BE TAKEN! KDevelop::DUChainBase* duObjectForIndex(const QModelIndex& a_index); /// Call this to retrieve the index for the node associated with the specified id. QModelIndex getIndexForIdentifier(const KDevelop::IndexedQualifiedIdentifier& a_id); /// Return the model index associated with the given node. QModelIndex index(ClassModelNodes::Node* a_node) const; public Q_SLOTS: /// Call this to update the filter string for the search results folder. void updateFilterString(QString a_newFilterString); /// removes the project-specific node void removeProjectNode(KDevelop::IProject* project); /// adds the project-specific node void addProjectNode(KDevelop::IProject* project); private: // NodesModelInterface overrides virtual void nodesLayoutAboutToBeChanged(ClassModelNodes::Node* a_parent) override; virtual void nodesLayoutChanged(ClassModelNodes::Node* a_parent) override; virtual void nodesRemoved(ClassModelNodes::Node* a_parent, int a_first, int a_last) override; virtual void nodesAboutToBeAdded(ClassModelNodes::Node* a_parent, int a_pos, int a_size) override; virtual void nodesAdded(ClassModelNodes::Node* a_parent) override; private: /// Main level node - it's usually invisible. ClassModelNodes::Node* m_topNode; ClassModelNodes::FilteredAllClassesFolder* m_allClassesNode; QMap m_projectNodes; public Q_SLOTS: /// This slot needs to be attached to collapsed signal in the tree view. void collapsed(const QModelIndex& index); /// This slot needs to be attached to expanded signal in the tree view. void expanded(const QModelIndex& index); public: // QAbstractItemModel overrides virtual QFlags< Qt::ItemFlag > flags(const QModelIndex&) const override; virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override; virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; virtual int rowCount(const QModelIndex& parent = QModelIndex()) const override; virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override; virtual bool hasChildren(const QModelIndex& parent = QModelIndex()) const override; virtual QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; virtual QModelIndex parent(const QModelIndex& child) const override; }; #endif // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classmodelnode.cpp b/language/classmodel/classmodelnode.cpp similarity index 96% rename from plugins/classbrowser/classmodelnode.cpp rename to language/classmodel/classmodelnode.cpp index 5f8e449bf9..c9cd8d7acd 100644 --- a/plugins/classbrowser/classmodelnode.cpp +++ b/language/classmodel/classmodelnode.cpp @@ -1,604 +1,606 @@ /* * KDevelop Class Browser * * Copyright 2007-2009 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "classmodelnode.h" #include "debug.h" #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "../duchain/duchainlock.h" +#include "../duchain/duchain.h" +#include "../duchain/persistentsymboltable.h" +#include "../duchain/duchainutils.h" +#include "../duchain/classdeclaration.h" +#include "../duchain/classfunctiondeclaration.h" +#include "../duchain/types/functiontype.h" +#include "../duchain/types/enumerationtype.h" + +#include "util/debug.h" using namespace KDevelop; using namespace ClassModelNodes; IdentifierNode::IdentifierNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model, const QString& a_displayName) : DynamicNode(a_displayName.isEmpty() ? a_decl->identifier().toString() : a_displayName, a_model) , m_identifier(a_decl->qualifiedIdentifier()) , m_indexedDeclaration(a_decl) , m_cachedDeclaration(a_decl) { } Declaration* IdentifierNode::getDeclaration() { if ( !m_cachedDeclaration ) m_cachedDeclaration = m_indexedDeclaration.declaration(); return m_cachedDeclaration.data(); } bool IdentifierNode::getIcon(QIcon& a_resultIcon) { DUChainReadLocker readLock(DUChain::lock()); Declaration* decl = getDeclaration(); if ( decl ) a_resultIcon = DUChainUtils::iconForDeclaration(decl); return !a_resultIcon.isNull(); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// EnumNode::EnumNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model) : IdentifierNode(a_decl, a_model) { // Set display name for anonymous enums if ( m_displayName.isEmpty() ) m_displayName = "*Anonymous*"; } bool EnumNode::getIcon(QIcon& a_resultIcon) { DUChainReadLocker readLock(DUChain::lock()); ClassMemberDeclaration* decl = dynamic_cast(getDeclaration()); if ( decl == 0 ) { static QIcon Icon = QIcon::fromTheme("enum"); a_resultIcon = Icon; } else { if ( decl->accessPolicy() == Declaration::Protected ) { static QIcon Icon = QIcon::fromTheme("protected_enum"); a_resultIcon = Icon; } else if ( decl->accessPolicy() == Declaration::Private ) { static QIcon Icon = QIcon::fromTheme("private_enum"); a_resultIcon = Icon; } else { static QIcon Icon = QIcon::fromTheme("enum"); a_resultIcon = Icon; } } return true; } void EnumNode::populateNode() { DUChainReadLocker readLock(DUChain::lock()); Declaration* decl = getDeclaration(); if ( decl->internalContext() ) foreach( Declaration* enumDecl, decl->internalContext()->localDeclarations() ) addNode( new EnumNode(enumDecl, m_model) ); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ClassNode::ClassNode(Declaration* a_decl, NodesModelInterface* a_model) : IdentifierNode(a_decl, a_model) { } ClassNode::~ClassNode() { if ( !m_cachedUrl.isEmpty() ) { ClassModelNodesController::self().unregisterForChanges(m_cachedUrl, this); m_cachedUrl = IndexedString(); } } void ClassNode::populateNode() { DUChainReadLocker readLock(DUChain::lock()); if ( updateClassDeclarations() ) { m_cachedUrl = getDeclaration()->url(); ClassModelNodesController::self().registerForChanges(m_cachedUrl, this); } // Add special folders addBaseAndDerived(); } template <> inline bool qMapLessThanKey(const IndexedIdentifier &key1, const IndexedIdentifier &key2) { return key1.getIndex() < key2.getIndex(); } bool ClassNode::updateClassDeclarations() { bool hadChanges = false; SubIdentifiersMap existingIdentifiers = m_subIdentifiers; ClassDeclaration* klass = dynamic_cast(getDeclaration()); if ( klass ) { foreach(Declaration* decl, klass->internalContext()->localDeclarations()) { // Ignore forward declarations. if ( decl->isForwardDeclaration() ) continue; // Don't add existing declarations. if ( existingIdentifiers.contains( decl->ownIndex() ) ) { existingIdentifiers.remove(decl->ownIndex()); continue; } Node* newNode = 0; if ( EnumerationType::Ptr enumType = decl->type() ) newNode = new EnumNode( decl, m_model ); else if ( decl->isFunctionDeclaration() ) newNode = new FunctionNode( decl, m_model ); else if ( ClassDeclaration* classDecl = dynamic_cast(decl) ) newNode = new ClassNode(classDecl, m_model); else if ( ClassMemberDeclaration* memDecl = dynamic_cast(decl) ) newNode = new ClassMemberNode( memDecl, m_model ); else { // Debug - for reference. - qCDebug(PLUGIN_CLASSBROWSER) << "class: " << klass->toString() << "name: " << decl->toString() << " - unknown declaration type: " << typeid(*decl).name(); + qCDebug(LANGUAGE) << "class: " << klass->toString() << "name: " << decl->toString() << " - unknown declaration type: " << typeid(*decl).name(); } if ( newNode ) { addNode(newNode); // Also remember the identifier. m_subIdentifiers.insert(decl->ownIndex(), newNode); hadChanges = true; } } } // Remove old existing identifiers for ( SubIdentifiersMap::iterator iter = existingIdentifiers.begin(); iter != existingIdentifiers.end(); ++iter ) { iter.value()->removeSelf(); m_subIdentifiers.remove(iter.key()); hadChanges = true; } return hadChanges; } bool ClassNode::addBaseAndDerived() { bool added = false; BaseClassesFolderNode *baseClassesNode = new BaseClassesFolderNode( m_model ); addNode( baseClassesNode ); if ( !baseClassesNode->hasChildren() ) removeNode( baseClassesNode ); else added = true; DerivedClassesFolderNode *derivedClassesNode = new DerivedClassesFolderNode( m_model ); addNode( derivedClassesNode ); if ( !derivedClassesNode->hasChildren() ) removeNode( derivedClassesNode ); else added = true; return added; } void ClassNode::nodeCleared() { if ( !m_cachedUrl.isEmpty() ) { ClassModelNodesController::self().unregisterForChanges(m_cachedUrl, this); m_cachedUrl = IndexedString(); } m_subIdentifiers.clear(); } void ClassModelNodes::ClassNode::documentChanged(const KDevelop::IndexedString&) { DUChainReadLocker readLock(DUChain::lock()); if ( updateClassDeclarations() ) recursiveSort(); } ClassNode* ClassNode::findSubClass(const KDevelop::IndexedQualifiedIdentifier& a_id) { // Make sure we have sub nodes. performPopulateNode(); /// @todo This is slow - we go over all the sub identifiers but the assumption is that /// this function call is rare and the list is not that long. foreach(Node* item, m_subIdentifiers) { ClassNode* classNode = dynamic_cast(item); if ( classNode == 0 ) continue; if ( classNode->getIdentifier() == a_id ) return classNode; } return 0; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// FunctionNode::FunctionNode(Declaration* a_decl, NodesModelInterface* a_model) : IdentifierNode(a_decl, a_model) { // Append the argument signature to the identifier's name (which is what the displayName is. if (FunctionType::Ptr type = a_decl->type()) m_displayName += type->partToString(FunctionType::SignatureArguments); // Add special values for ctor / dtor to sort first ClassFunctionDeclaration* classmember = dynamic_cast(a_decl); if ( classmember ) { if ( classmember->isConstructor() || classmember->isDestructor() ) m_sortableString = '0' + m_displayName; else m_sortableString = '1' + m_displayName; } else { m_sortableString = m_displayName; } } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ClassMemberNode::ClassMemberNode(KDevelop::ClassMemberDeclaration* a_decl, NodesModelInterface* a_model) : IdentifierNode(a_decl, a_model) { } bool ClassMemberNode::getIcon(QIcon& a_resultIcon) { DUChainReadLocker readLock(DUChain::lock()); ClassMemberDeclaration* decl = dynamic_cast(getDeclaration()); if ( decl == 0 ) return false; if ( decl->isTypeAlias() ) { static QIcon Icon = QIcon::fromTheme("typedef"); a_resultIcon = Icon; } else if ( decl->accessPolicy() == Declaration::Protected ) { static QIcon Icon = QIcon::fromTheme("protected_field"); a_resultIcon = Icon; } else if ( decl->accessPolicy() == Declaration::Private ) { static QIcon Icon = QIcon::fromTheme("private_field"); a_resultIcon = Icon; } else { static QIcon Icon = QIcon::fromTheme("field"); a_resultIcon = Icon; } return true; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// DynamicFolderNode::DynamicFolderNode(const QString& a_displayName, NodesModelInterface* a_model) : DynamicNode(a_displayName, a_model) { } bool DynamicFolderNode::getIcon(QIcon& a_resultIcon) { static QIcon folderIcon = QIcon::fromTheme("folder"); a_resultIcon = folderIcon; return true; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// FolderNode::FolderNode(const QString& a_displayName, NodesModelInterface* a_model) : Node(a_displayName, a_model) { } bool FolderNode::getIcon(QIcon& a_resultIcon) { static QIcon folderIcon = QIcon::fromTheme("folder"); a_resultIcon = folderIcon; return true; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// BaseClassesFolderNode::BaseClassesFolderNode(NodesModelInterface* a_model) : DynamicFolderNode(i18n("Base classes"), a_model) { } void BaseClassesFolderNode::populateNode() { DUChainReadLocker readLock(DUChain::lock()); ClassDeclaration* klass = dynamic_cast( static_cast(getParent())->getDeclaration() ); if ( klass ) { // I use the imports instead of the baseClasses in the ClassDeclaration because I need // to get to the base class identifier which is not directly accessible through the // baseClasses function. foreach( const DUContext::Import& import, klass->internalContext()->importedParentContexts() ) { DUContext* baseContext = import.context( klass->topContext() ); if ( baseContext && baseContext->type() == DUContext::Class ) { Declaration* baseClassDeclaration = baseContext->owner(); if ( baseClassDeclaration ) { // Add the base class. addNode( new ClassNode(baseClassDeclaration, m_model) ); } } } } } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// DerivedClassesFolderNode::DerivedClassesFolderNode(NodesModelInterface* a_model) : DynamicFolderNode(i18n("Derived classes"), a_model) { } void DerivedClassesFolderNode::populateNode() { DUChainReadLocker readLock(DUChain::lock()); ClassDeclaration* klass = dynamic_cast( static_cast(getParent())->getDeclaration() ); if ( klass ) { uint steps = 10000; QList< Declaration* > inheriters = DUChainUtils::getInheriters(klass, steps, true); foreach( Declaration* decl, inheriters ) { addNode( new ClassNode(decl, m_model) ); } } } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// Node::Node(const QString& a_displayName, NodesModelInterface* a_model) : m_parentNode(0) , m_displayName(a_displayName) , m_model(a_model) { } Node::~Node() { // Notify the model about the removal of this nodes' children. if ( !m_children.empty() && m_model ) m_model->nodesRemoved(this, 0, m_children.size()-1); clear(); } void Node::clear() { qDeleteAll(m_children); m_children.clear(); } void Node::addNode(Node* a_child) { /// @note This is disabled for performance reasons - we add them to the bottom and a /// sort usually follows which causes a layout change to be fired. // m_model->nodesAboutToBeAdded(this, m_children.size(), 1); a_child->m_parentNode = this; m_children.push_back(a_child); // m_model->nodesAdded(this); } void Node::removeNode(Node* a_child) { int row = a_child->row(); m_children.removeAt(row); m_model->nodesRemoved(this, row, row ); delete a_child; } // Sort algorithm for the nodes. struct SortNodesFunctor { bool operator() (Node* a_lhs, Node* a_rhs) { if ( a_lhs->getScore() == a_rhs->getScore() ) { return a_lhs->getSortableString() < a_rhs->getSortableString(); } else return a_lhs->getScore() < a_rhs->getScore(); } }; void Node::recursiveSortInternal() { // Sort my nodes. std::sort(m_children.begin(), m_children.end(), SortNodesFunctor()); // Tell each node to sort it self. foreach (Node* node, m_children) node->recursiveSortInternal(); } void Node::recursiveSort() { m_model->nodesLayoutAboutToBeChanged(this); recursiveSortInternal(); m_model->nodesLayoutChanged(this); } int Node::row() { if ( m_parentNode == 0 ) return -1; return m_parentNode->m_children.indexOf(this); } QIcon ClassModelNodes::Node::getCachedIcon() { // Load the cached icon if it's null. if ( m_cachedIcon.isNull() ) { if ( !getIcon(m_cachedIcon) ) m_cachedIcon = QIcon(); } return m_cachedIcon; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// DynamicNode::DynamicNode(const QString& a_displayName, NodesModelInterface* a_model) : Node(a_displayName, a_model) , m_populated(false) { } void DynamicNode::collapse() { performNodeCleanup(); } void DynamicNode::expand() { performPopulateNode(); } void DynamicNode::performNodeCleanup() { if ( !m_populated ) return; if ( !m_children.empty() ) { // Notify model for this node. m_model->nodesRemoved(this, 0, m_children.size()-1); } // Clear sub-nodes. clear(); // This shouldn't be called from clear since clear is called also from the d-tor // and the function is virtual. nodeCleared(); // Mark the fact that we've been collapsed m_populated = false; } void DynamicNode::performPopulateNode(bool a_forceRepopulate) { if ( m_populated ) { if ( a_forceRepopulate ) performNodeCleanup(); else return; } populateNode(); // We're populated. m_populated = true; // Sort the list. recursiveSort(); } bool DynamicNode::hasChildren() const { // To get a true status, we'll need to populate the node. const_cast(this)->performPopulateNode(); return !m_children.empty(); } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classmodelnode.h b/language/classmodel/classmodelnode.h similarity index 98% rename from plugins/classbrowser/classmodelnode.h rename to language/classmodel/classmodelnode.h index b8c038c2ff..4220159816 100644 --- a/plugins/classbrowser/classmodelnode.h +++ b/language/classmodel/classmodelnode.h @@ -1,332 +1,332 @@ /* * KDevelop Class Browser * * Copyright 2007-2009 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KDEVPLATFORM_PLUGIN_CLASSMODELNODE_H -#define KDEVPLATFORM_PLUGIN_CLASSMODELNODE_H +#ifndef KDEVPLATFORM_CLASSMODELNODE_H +#define KDEVPLATFORM_CLASSMODELNODE_H #include "classmodel.h" #include -#include -#include +#include "../duchain/identifier.h" +#include "../duchain/duchainpointer.h" #include "classmodelnodescontroller.h" class QTimer; class NodesModelInterface; namespace KDevelop { class ClassDeclaration; class ClassFunctionDeclaration; class ClassMemberDeclaration; class Declaration; } namespace ClassModelNodes { /// Base node class - provides basic functionality. class Node { public: Node(const QString& a_displayName, NodesModelInterface* a_model); virtual ~Node(); public: // Operations /// Clear all the children from the node. void clear(); /// Called by the model to collapse the node and remove sub-items if needed. virtual void collapse() {}; /// Called by the model to expand the node and populate it with sub-nodes if needed. virtual void expand() {}; /// Append a new child node to the list. void addNode(Node* a_child); /// Remove child node from the list and delete it. void removeNode(Node* a_child); /// Remove this node and delete it. void removeSelf() { m_parentNode->removeNode(this); } /// Called once the node has been populated to sort the entire tree / branch. void recursiveSort(); public: // Info retrieval /// Return the parent associated with this node. Node* getParent() const { return m_parentNode; } /// Get my index in the parent node int row(); /// Return the display name for the node. QString displayName() const { return m_displayName; } /// Returns a list of child nodes const QList& getChildren() const { return m_children; } /// Return an icon representation for the node. /// @note It calls the internal getIcon and caches the result. QIcon getCachedIcon(); public: // overridables /// Return a score when sorting the nodes. virtual int getScore() const = 0; /// Return true if the node contains sub-nodes. virtual bool hasChildren() const { return !m_children.empty(); } /// We use this string when sorting items. virtual QString getSortableString() const { return m_displayName; } protected: /// fill a_resultIcon with a display icon for the node. /// @param a_resultIcon returned icon. /// @return true if result was returned. virtual bool getIcon(QIcon& a_resultIcon) = 0; private: Node* m_parentNode; /// Called once the node has been populated to sort the entire tree / branch. void recursiveSortInternal(); protected: typedef QList< Node* > NodesList; NodesList m_children; QString m_displayName; QIcon m_cachedIcon; NodesModelInterface* m_model; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Base class for nodes that generate and populate their child nodes dynamically class DynamicNode : public Node { public: DynamicNode(const QString& a_displayName, NodesModelInterface* a_model); /// Return true if the node was populated already. bool isPopulated() const { return m_populated; } /// Populate the node and mark the flag - called from expand or can be used internally. void performPopulateNode(bool a_forceRepopulate = false); public: // Node overrides. virtual void collapse() override; virtual void expand() override; virtual bool hasChildren() const override; protected: // overridables /// Called by the framework when the node is about to be expanded /// it should be populated with sub-nodes if applicable. virtual void populateNode() {} /// Called after the nodes have been removed. /// It's for derived classes to clean cached data. virtual void nodeCleared() {} private: bool m_populated; /// Clear all the child nodes and mark flag. void performNodeCleanup(); }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Base class for nodes associated with a @ref KDevelop::QualifiedIdentifier class IdentifierNode : public DynamicNode { public: IdentifierNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model, const QString& a_displayName = QString()); public: /// Returns the qualified identifier for this node by going through the tree const KDevelop::IndexedQualifiedIdentifier& getIdentifier() const { return m_identifier; } public: // Node overrides virtual bool getIcon(QIcon& a_resultIcon) override; public: // Overridables /// Return the associated declaration /// @note DU CHAIN MUST BE LOCKED FOR READ virtual KDevelop::Declaration* getDeclaration(); private: KDevelop::IndexedQualifiedIdentifier m_identifier; KDevelop::IndexedDeclaration m_indexedDeclaration; KDevelop::DeclarationPointer m_cachedDeclaration; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// A node that represents an enum value. class EnumNode : public IdentifierNode { public: EnumNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model); public: // Node overrides virtual int getScore() const override { return 102; } virtual bool getIcon(QIcon& a_resultIcon) override; virtual void populateNode() override; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides display for a single class. class ClassNode : public IdentifierNode, public ClassModelNodeDocumentChangedInterface { public: ClassNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model); virtual ~ClassNode(); /// Lookup a contained class and return the related node. /// @return the node pointer or 0 if non was found. ClassNode* findSubClass(const KDevelop::IndexedQualifiedIdentifier& a_id); public: // Node overrides virtual int getScore() const override { return 300; } virtual void populateNode() override; virtual void nodeCleared() override; virtual bool hasChildren() const override { return true; } protected: // ClassModelNodeDocumentChangedInterface overrides virtual void documentChanged(const KDevelop::IndexedString& a_file) override; private: typedef QMap< uint, Node* > SubIdentifiersMap; /// Set of known sub-identifiers. It's used for updates check. SubIdentifiersMap m_subIdentifiers; /// We use this variable to know if we've registered for change notification or not. KDevelop::IndexedString m_cachedUrl; /// Updates the node to reflect changes in the declaration. /// @note DU CHAIN MUST BE LOCKED FOR READ /// @return true if something was updated. bool updateClassDeclarations(); /// Add "Base classes" and "Derived classes" folders, if needed /// @return true if one of the folders was added. bool addBaseAndDerived(); }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides a display for a single class function. class FunctionNode : public IdentifierNode { public: FunctionNode(KDevelop::Declaration* a_decl, NodesModelInterface* a_model); public: // Node overrides virtual int getScore() const override { return 400; } virtual QString getSortableString() const override { return m_sortableString; } private: QString m_sortableString; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides display for a single class variable. class ClassMemberNode : public IdentifierNode { public: ClassMemberNode(KDevelop::ClassMemberDeclaration* a_decl, NodesModelInterface* a_model); public: // Node overrides virtual int getScore() const override { return 500; } virtual bool getIcon(QIcon& a_resultIcon) override; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides a folder node with a static list of nodes. class FolderNode : public Node { public: FolderNode(const QString& a_displayName, NodesModelInterface* a_model); public: // Node overrides virtual bool getIcon(QIcon& a_resultIcon) override; virtual int getScore() const override { return 100; } }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Provides a folder node with a dynamic list of nodes. class DynamicFolderNode : public DynamicNode { public: DynamicFolderNode(const QString& a_displayName, NodesModelInterface* a_model); public: // Node overrides virtual bool getIcon(QIcon& a_resultIcon) override; virtual int getScore() const override { return 100; } }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Special folder - the parent is assumed to be a ClassNode. /// It then displays the base classes for the class it sits in. class BaseClassesFolderNode : public DynamicFolderNode { public: explicit BaseClassesFolderNode(NodesModelInterface* a_model); public: // Node overrides virtual void populateNode() override; }; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Special folder - the parent is assumed to be a ClassNode. /// It then displays list of derived classes from the parent class. class DerivedClassesFolderNode : public DynamicFolderNode { public: explicit DerivedClassesFolderNode(NodesModelInterface* a_model); public: // Node overrides virtual void populateNode() override; }; } // namespace classModelNodes #endif // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classmodelnodescontroller.cpp b/language/classmodel/classmodelnodescontroller.cpp similarity index 94% rename from plugins/classbrowser/classmodelnodescontroller.cpp rename to language/classmodel/classmodelnodescontroller.cpp index a51baa2a9d..620df98b21 100644 --- a/plugins/classbrowser/classmodelnodescontroller.cpp +++ b/language/classmodel/classmodelnodescontroller.cpp @@ -1,75 +1,75 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "classmodelnodescontroller.h" #include "classmodelnode.h" -#include -#include -#include +#include "../duchain/duchainlock.h" +#include "../duchain/duchain.h" +#include "../duchain/classdeclaration.h" #include using namespace KDevelop; ClassModelNodeDocumentChangedInterface::~ClassModelNodeDocumentChangedInterface() { } ClassModelNodesController::ClassModelNodesController() : m_updateTimer( new QTimer(this) ) { m_updateTimer->setSingleShot(true); connect( m_updateTimer, &QTimer::timeout, this, &ClassModelNodesController::updateChangedFiles); } ClassModelNodesController::~ClassModelNodesController() { } ClassModelNodesController& ClassModelNodesController::self() { static ClassModelNodesController ret; return ret; } void ClassModelNodesController::registerForChanges(const KDevelop::IndexedString& a_file, ClassModelNodeDocumentChangedInterface* a_node) { m_filesMap.insert(a_file, a_node); } void ClassModelNodesController::unregisterForChanges(const KDevelop::IndexedString& a_file, ClassModelNodeDocumentChangedInterface* a_node) { m_filesMap.remove(a_file, a_node); } void ClassModelNodesController::updateChangedFiles() { // re-parse changed documents. foreach( const IndexedString& file, m_updatedFiles ) foreach( ClassModelNodeDocumentChangedInterface* value, m_filesMap.values(file) ) { value->documentChanged(file); } // Processed all files. m_updatedFiles.clear(); } diff --git a/plugins/classbrowser/classmodelnodescontroller.h b/language/classmodel/classmodelnodescontroller.h similarity index 92% rename from plugins/classbrowser/classmodelnodescontroller.h rename to language/classmodel/classmodelnodescontroller.h index c1394651ff..a08e5e0dc8 100644 --- a/plugins/classbrowser/classmodelnodescontroller.h +++ b/language/classmodel/classmodelnodescontroller.h @@ -1,73 +1,73 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KDEVPLATFORM_PLUGIN_CLASSMODELNODESCONTROLLER_H -#define KDEVPLATFORM_PLUGIN_CLASSMODELNODESCONTROLLER_H +#ifndef KDEVPLATFORM_CLASSMODELNODESCONTROLLER_H +#define KDEVPLATFORM_CLASSMODELNODESCONTROLLER_H #include -#include -#include +#include "../../serialization/indexedstring.h" +#include "../duchain/ducontext.h" class QTimer; class ClassModelNodeDocumentChangedInterface { public: virtual ~ClassModelNodeDocumentChangedInterface(); /// Called when the registered document is changed. virtual void documentChanged(const KDevelop::IndexedString& a_file) = 0; }; /// This class provides notifications for updates between the different nodes /// and the various kdevelop sub-systems (such as notification when a DUChain gets /// updated). class ClassModelNodesController : public QObject { Q_OBJECT public: ClassModelNodesController(); ~ClassModelNodesController(); static ClassModelNodesController& self(); /// Register the given class node to receive notifications about its top context changes. void registerForChanges(const KDevelop::IndexedString& a_file, ClassModelNodeDocumentChangedInterface* a_node); /// Unregister the given class node from further notifications. void unregisterForChanges(const KDevelop::IndexedString& a_file, ClassModelNodeDocumentChangedInterface* a_node); private Q_SLOTS: // Files update. void updateChangedFiles(); private: // File updates related. /// List of updated files we check this list when update timer expires. QSet m_updatedFiles; /// Timer for batch updates. QTimer* m_updateTimer; typedef QMultiMap< KDevelop::IndexedString, ClassModelNodeDocumentChangedInterface* > FilesMap; /// Maps between monitored files and their class nodes. FilesMap m_filesMap; }; #endif diff --git a/plugins/classbrowser/documentclassesfolder.cpp b/language/classmodel/documentclassesfolder.cpp similarity index 98% rename from plugins/classbrowser/documentclassesfolder.cpp rename to language/classmodel/documentclassesfolder.cpp index e05e3658a4..b42e0cbf4d 100644 --- a/plugins/classbrowser/documentclassesfolder.cpp +++ b/language/classmodel/documentclassesfolder.cpp @@ -1,451 +1,451 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "documentclassesfolder.h" -#include -#include -#include -#include -#include +#include "../duchain/declaration.h" +#include "../duchain/duchainlock.h" +#include "../duchain/duchain.h" +#include "../duchain/persistentsymboltable.h" +#include "../duchain/codemodel.h" #include #include #include using namespace KDevelop; using namespace ClassModelNodes; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// /// Contains a static list of classes within the namespace. class ClassModelNodes::StaticNamespaceFolderNode : public Node { public: StaticNamespaceFolderNode(const KDevelop::QualifiedIdentifier& a_identifier, NodesModelInterface* a_model); /// Returns the qualified identifier for this node const KDevelop::QualifiedIdentifier& qualifiedIdentifier() const { return m_identifier; } public: // Node overrides virtual bool getIcon(QIcon& a_resultIcon) override; virtual int getScore() const override { return 101; } private: /// The namespace identifier. KDevelop::QualifiedIdentifier m_identifier; }; StaticNamespaceFolderNode::StaticNamespaceFolderNode(const KDevelop::QualifiedIdentifier& a_identifier, NodesModelInterface* a_model) : Node(a_identifier.last().toString(), a_model) , m_identifier(a_identifier) { } bool StaticNamespaceFolderNode::getIcon(QIcon& a_resultIcon) { static QIcon folderIcon = QIcon::fromTheme("namespace"); a_resultIcon = folderIcon; return true; } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// DocumentClassesFolder::OpenedFileClassItem::OpenedFileClassItem(const KDevelop::IndexedString& a_file, const KDevelop::IndexedQualifiedIdentifier& a_classIdentifier, ClassModelNodes::ClassNode* a_nodeItem) : file(a_file) , classIdentifier(a_classIdentifier) , nodeItem(a_nodeItem) { } DocumentClassesFolder::DocumentClassesFolder(const QString& a_displayName, NodesModelInterface* a_model) : DynamicFolderNode(a_displayName, a_model) , m_updateTimer( new QTimer(this) ) { connect( m_updateTimer, &QTimer::timeout, this, &DocumentClassesFolder::updateChangedFiles); } void DocumentClassesFolder::updateChangedFiles() { bool hadChanges = false; // re-parse changed documents. foreach( const IndexedString& file, m_updatedFiles ) { // Make sure it's one of the monitored files. if ( m_openFiles.contains(file) ) hadChanges |= updateDocument(file); } // Processed all files. m_updatedFiles.clear(); // Sort if had changes. if ( hadChanges ) recursiveSort(); } void DocumentClassesFolder::nodeCleared() { // Clear cached namespaces list (node was cleared). m_namespaces.clear(); // Clear open files and classes list m_openFiles.clear(); m_openFilesClasses.clear(); // Stop the update timer. m_updateTimer->stop(); } void DocumentClassesFolder::populateNode() { // Start updates timer - this is the required delay. m_updateTimer->start(2000); } QSet< KDevelop::IndexedString > DocumentClassesFolder::getAllOpenDocuments() { return m_openFiles; } ClassNode* DocumentClassesFolder::findClassNode(const IndexedQualifiedIdentifier& a_id) { // Make sure that the classes node is populated, otherwise // the lookup will not work. performPopulateNode(); ClassIdentifierIterator iter = m_openFilesClasses.get().find(a_id); if ( iter == m_openFilesClasses.get().end() ) return 0; // If the node is invisible - make it visible by going over the identifiers list. if ( iter->nodeItem == 0 ) { QualifiedIdentifier qualifiedIdentifier = a_id.identifier(); // Ignore zero length identifiers. if ( qualifiedIdentifier.count() == 0 ) return 0; ClassNode* closestNode = 0; int closestNodeIdLen = qualifiedIdentifier.count(); // First find the closest visible class node by reverse iteration over the id list. while ( (closestNodeIdLen > 0) && (closestNode == 0) ) { // Omit one from the end. --closestNodeIdLen; // Find the closest class. closestNode = findClassNode(qualifiedIdentifier.mid(0, closestNodeIdLen)); } if ( closestNode != 0 ) { // Start iterating forward from this node by exposing each class. // By the end of this loop, closestNode should hold the actual node. while ( closestNode && (closestNodeIdLen < qualifiedIdentifier.count()) ) { // Try the next Id. ++closestNodeIdLen; closestNode = closestNode->findSubClass(qualifiedIdentifier.mid(0, closestNodeIdLen)); } } return closestNode; } return iter->nodeItem; } void DocumentClassesFolder::closeDocument(const IndexedString& a_file) { // Get list of nodes associated with this file and remove them. std::pair< FileIterator, FileIterator > range = m_openFilesClasses.get().equal_range( a_file ); if ( range.first != m_openFilesClasses.get().end() ) { BOOST_FOREACH( const OpenedFileClassItem& item, range ) { if ( item.nodeItem ) removeClassNode(item.nodeItem); } // Clear the lists m_openFilesClasses.get().erase(range.first, range.second); } // Clear the file from the list of monitored documents. m_openFiles.remove(a_file); } bool DocumentClassesFolder::updateDocument(const KDevelop::IndexedString& a_file) { uint codeModelItemCount = 0; const CodeModelItem* codeModelItems; CodeModel::self().items(a_file, codeModelItemCount, codeModelItems); // List of declared namespaces in this file. QSet< QualifiedIdentifier > declaredNamespaces; // List of removed classes - it initially contains all the known classes, we'll eliminate them // one by one later on when we encounter them in the document. QMap< IndexedQualifiedIdentifier, FileIterator > removedClasses; { std::pair< FileIterator, FileIterator > range = m_openFilesClasses.get().equal_range( a_file ); for ( FileIterator iter = range.first; iter != range.second; ++iter ) { removedClasses.insert(iter->classIdentifier, iter); } } bool documentChanged = false; for(uint codeModelItemIndex = 0; codeModelItemIndex < codeModelItemCount; ++codeModelItemIndex) { const CodeModelItem& item = codeModelItems[codeModelItemIndex]; // Don't insert unknown or forward declarations into the class browser if ( (item.kind & CodeModelItem::Unknown) || (item.kind & CodeModelItem::ForwardDeclaration) ) continue; KDevelop::QualifiedIdentifier id = item.id.identifier(); // Don't add empty identifiers. if ( id.count() == 0 ) continue; // If it's a namespace, create it in the list. if ( item.kind & CodeModelItem::Namespace ) { // This should create the namespace folder and add it to the cache. getNamespaceFolder(id); // Add to the locally created namespaces. declaredNamespaces.insert(id); } else if ( item.kind & CodeModelItem::Class ) { // Ignore empty unnamed classes. if ( id.last().toString().isEmpty() ) continue; // See if it matches our filter? if ( isClassFiltered(id) ) continue; // Is this a new class or an existing class? if ( removedClasses.contains(id) ) { // It already exist - remove it from the known classes and continue. removedClasses.remove(id); continue; } // Where should we put this class? Node* parentNode = 0; // Check if it's namespaced and add it to the proper namespace. if ( id.count() > 1 ) { QualifiedIdentifier parentIdentifier(id.left(-1)); // Look up the namespace in the cache. // If we fail to find it we assume that the parent context is a class // and in that case, when the parent class gets expanded, it will show it. NamespacesMap::iterator iter = m_namespaces.find(parentIdentifier); if ( iter != m_namespaces.end() ) { // Add to the namespace node. parentNode = iter.value(); } else { // Reaching here means we didn't encounter any namespace declaration in the document // But a class might still be declared under a namespace. // So we'll perform a more through search to see if it's under a namespace. DUChainReadLocker readLock(DUChain::lock()); uint declsCount = 0; const IndexedDeclaration* decls; PersistentSymbolTable::self().declarations(parentIdentifier, declsCount, decls); for ( uint i = 0; i < declsCount; ++i ) { // Look for the first valid declaration. if ( decls->declaration() ) { // See if it should be namespaced. if ( decls->declaration()->kind() == Declaration::Namespace ) { // This should create the namespace folder and add it to the cache. parentNode = getNamespaceFolder(parentIdentifier); // Add to the locally created namespaces. declaredNamespaces.insert(parentIdentifier); } break; } } } } else { // Add to the main root. parentNode = this; } ClassNode* newNode = 0; if ( parentNode != 0 ) { // Create the new node and add it. IndexedDeclaration decl; uint count = 0; const IndexedDeclaration* declarations; DUChainReadLocker lock; PersistentSymbolTable::self().declarations(item.id, count, declarations); for ( uint i = 0; i < count; ++i ) { if (declarations[i].indexedTopContext().url() == a_file) { decl = declarations[i]; break; } } if (decl.isValid()) { newNode = new ClassNode(decl.declaration(), m_model); parentNode->addNode( newNode ); } } // Insert it to the map - newNode can be 0 - meaning the class is hidden. m_openFilesClasses.insert( OpenedFileClassItem( a_file, id, newNode ) ); documentChanged = true; } } // Remove empty namespaces from the list. // We need this because when a file gets unloaded, we unload the declared classes in it // and if a namespace has no class in it, it'll forever exist and no one will remove it // from the children list. foreach( const QualifiedIdentifier& id, declaredNamespaces ) removeEmptyNamespace(id); // Clear erased classes. foreach( const FileIterator& item, removedClasses ) { if ( item->nodeItem ) removeClassNode(item->nodeItem); m_openFilesClasses.get().erase(item); documentChanged = true; } return documentChanged; } void DocumentClassesFolder::parseDocument(const IndexedString& a_file) { // Add the document to the list of open files - this means we monitor it. if ( !m_openFiles.contains(a_file) ) m_openFiles.insert(a_file); updateDocument(a_file); } void DocumentClassesFolder::removeClassNode(ClassModelNodes::ClassNode* a_node) { // Get the parent namespace identifier. QualifiedIdentifier parentNamespaceIdentifier; if ( auto namespaceParent = dynamic_cast(a_node->getParent()) ) { parentNamespaceIdentifier = namespaceParent->qualifiedIdentifier(); } // Remove the node. a_node->removeSelf(); // Remove empty namespace removeEmptyNamespace(parentNamespaceIdentifier); } void DocumentClassesFolder::removeEmptyNamespace(const QualifiedIdentifier& a_identifier) { // Stop condition. if ( a_identifier.count() == 0 ) return; // Look it up in the cache. NamespacesMap::iterator iter = m_namespaces.find(a_identifier); if ( iter != m_namespaces.end() ) { if ( !(*iter)->hasChildren() ) { // Remove this node and try to remove the parent node. QualifiedIdentifier parentIdentifier = (*iter)->qualifiedIdentifier().left(-1); (*iter)->removeSelf(); m_namespaces.remove(a_identifier); removeEmptyNamespace(parentIdentifier); } } } StaticNamespaceFolderNode* DocumentClassesFolder::getNamespaceFolder(const KDevelop::QualifiedIdentifier& a_identifier) { // Stop condition. if ( a_identifier.count() == 0 ) return 0; // Look it up in the cache. NamespacesMap::iterator iter = m_namespaces.find(a_identifier); if ( iter == m_namespaces.end() ) { // It's not in the cache - create folders up to it. Node* parentNode = getNamespaceFolder(a_identifier.left(-1)); if ( parentNode == 0 ) parentNode = this; // Create the new node. StaticNamespaceFolderNode* newNode = new StaticNamespaceFolderNode(a_identifier, m_model); parentNode->addNode( newNode ); // Add it to the cache. m_namespaces.insert( a_identifier, newNode ); // Return the result. return newNode; } else return *iter; } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/documentclassesfolder.h b/language/classmodel/documentclassesfolder.h similarity index 97% rename from plugins/classbrowser/documentclassesfolder.h rename to language/classmodel/documentclassesfolder.h index 3fd30a45b2..5479329442 100644 --- a/plugins/classbrowser/documentclassesfolder.h +++ b/language/classmodel/documentclassesfolder.h @@ -1,155 +1,155 @@ /* * KDevelop Class Browser * * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KDEVPLATFORM_PLUGIN_DOCUMENTCLASSESFOLDER_H -#define KDEVPLATFORM_PLUGIN_DOCUMENTCLASSESFOLDER_H +#ifndef KDEVPLATFORM_DOCUMENTCLASSESFOLDER_H +#define KDEVPLATFORM_DOCUMENTCLASSESFOLDER_H #include "classmodelnode.h" #include #include #include namespace ClassModelNodes { class StaticNamespaceFolderNode; /// This folder displays all the classes that relate to a list of documents. class DocumentClassesFolder : public QObject, public DynamicFolderNode { Q_OBJECT public: DocumentClassesFolder(const QString& a_displayName, NodesModelInterface* a_model); public: // Operations /// Find a class node in the lists by its id. ClassNode* findClassNode(const KDevelop::IndexedQualifiedIdentifier& a_id); protected: // Documents list handling. /// Parse a single document for classes and add them to the list. void parseDocument(const KDevelop::IndexedString& a_file); /// Re-parse the given document - remove old declarations and add new declarations. bool updateDocument(const KDevelop::IndexedString& a_file); /// Close and remove all the nodes related to the specified document. void closeDocument(const KDevelop::IndexedString& a_file); /// Returns a list of documents we have monitored. QSet< KDevelop::IndexedString > getAllOpenDocuments(); protected: // Overridables /// Override this to filter the found classes. virtual bool isClassFiltered(const KDevelop::QualifiedIdentifier&) { return false; } public: // Node overrides virtual void nodeCleared() override; virtual void populateNode() override; virtual bool hasChildren() const override { return true; } private Q_SLOTS: // Files update. void updateChangedFiles(); private: // File updates related. /// List of updated files we check this list when update timer expires. QSet m_updatedFiles; /// Timer for batch updates. QTimer* m_updateTimer; private: // Opened class identifiers container definition. // An opened class item. struct OpenedFileClassItem { OpenedFileClassItem(); OpenedFileClassItem(const KDevelop::IndexedString& a_file, const KDevelop::IndexedQualifiedIdentifier& a_classIdentifier, ClassNode* a_nodeItem); /// The file this class declaration comes from. KDevelop::IndexedString file; /// The identifier for this class. KDevelop::IndexedQualifiedIdentifier classIdentifier; /// An existing node item. It maybe 0 - meaning the class node is currently hidden. ClassNode* nodeItem; }; // Index definitions. struct FileIndex {}; struct ClassIdentifierIndex {}; // Member types definitions. typedef boost::multi_index::member< OpenedFileClassItem, KDevelop::IndexedString, &OpenedFileClassItem::file> FileMember; typedef boost::multi_index::member< OpenedFileClassItem, KDevelop::IndexedQualifiedIdentifier, &OpenedFileClassItem::classIdentifier> ClassIdentifierMember; // Container definition. typedef boost::multi_index::multi_index_container< OpenedFileClassItem, boost::multi_index::indexed_by< boost::multi_index::ordered_non_unique< boost::multi_index::tag, FileMember >, boost::multi_index::ordered_unique< boost::multi_index::tag, ClassIdentifierMember > > > OpenFilesContainer; // Iterators definition. typedef OpenFilesContainer::index_iterator::type FileIterator; typedef OpenFilesContainer::index_iterator::type ClassIdentifierIterator; /// Maps all displayed classes and their referenced files. OpenFilesContainer m_openFilesClasses; /// Holds a set of open files. QSet< KDevelop::IndexedString > m_openFiles; private: typedef QMap< KDevelop::IndexedQualifiedIdentifier, StaticNamespaceFolderNode* > NamespacesMap; /// Holds a map between an identifier and a namespace folder we hold. NamespacesMap m_namespaces; /// Recursively create a namespace folder for the specified identifier if it doesn't /// exist, cache it and return it (or just return it from the cache). StaticNamespaceFolderNode* getNamespaceFolder(const KDevelop::QualifiedIdentifier& a_identifier); /// Removes the given namespace identifier recursively if it's empty. void removeEmptyNamespace(const KDevelop::QualifiedIdentifier& a_identifier); /// Remove a single class node from the lists. void removeClassNode(ClassNode* a_node); }; } // namespace ClassModelNodes -#endif // KDEVPLATFORM_PLUGIN_DOCUMENTCLASSESFOLDER_H +#endif // KDEVPLATFORM_DOCUMENTCLASSESFOLDER_H diff --git a/plugins/classbrowser/projectfolder.cpp b/language/classmodel/projectfolder.cpp similarity index 97% rename from plugins/classbrowser/projectfolder.cpp rename to language/classmodel/projectfolder.cpp index 26834c1ad0..613529a6fb 100644 --- a/plugins/classbrowser/projectfolder.cpp +++ b/language/classmodel/projectfolder.cpp @@ -1,97 +1,97 @@ /* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "projectfolder.h" -#include -#include +#include "../../interfaces/iproject.h" +#include "../../serialization/indexedstring.h" #include using namespace KDevelop; using namespace ClassModelNodes; ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// ProjectFolder::ProjectFolder( NodesModelInterface* a_model, IProject* project ) : DocumentClassesFolder( i18n("Classes in project %1", project->name()), a_model ) , m_project(project) { } ProjectFolder::ProjectFolder( NodesModelInterface* a_model ) : DocumentClassesFolder( "", a_model ) , m_project( 0 ) { } void ProjectFolder::populateNode() { foreach( const IndexedString &file, m_project->fileSet() ) { parseDocument(file); } recursiveSort(); } ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// FilteredProjectFolder::FilteredProjectFolder(NodesModelInterface* a_model, IProject* project) : ProjectFolder(a_model, project) { } void FilteredProjectFolder::updateFilterString(QString a_newFilterString) { m_filterString = a_newFilterString; if ( isPopulated() ) { #if 1 // Choose speed over correctness. // Close the node and re-open it should be quicker than reload each document // and remove indevidual nodes (at the cost of loosing the current selection). performPopulateNode(true); #else bool hadChanges = false; // Reload the documents. foreach( const IndexedString& file, getAllOpenDocuments() ) hadChanges |= updateDocument(file); // Sort if we've updated documents. if ( hadChanges ) recursiveSort(); else { // If nothing changed, the title changed so mark the node as updated. m_model->nodesLayoutAboutToBeChanged(this); m_model->nodesLayoutChanged(this); } #endif } else { // Displayed name changed only... m_model->nodesLayoutAboutToBeChanged(this); m_model->nodesLayoutChanged(this); } } bool FilteredProjectFolder::isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) { return !a_id.last().toString().contains(m_filterString, Qt::CaseInsensitive); } // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/projectfolder.h b/language/classmodel/projectfolder.h similarity index 93% rename from plugins/classbrowser/projectfolder.h rename to language/classmodel/projectfolder.h index accb9a6bde..c9fd858754 100644 --- a/plugins/classbrowser/projectfolder.h +++ b/language/classmodel/projectfolder.h @@ -1,71 +1,71 @@ /* * KDevelop Class Browser * * Copyright 2009 Milian Wolff * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef KDEVPLATFORM_PLUGIN_PROJECTFOLDER_H -#define KDEVPLATFORM_PLUGIN_PROJECTFOLDER_H +#ifndef KDEVPLATFORM_PROJECTFOLDER_H +#define KDEVPLATFORM_PROJECTFOLDER_H #include "documentclassesfolder.h" namespace KDevelop { class IProject; } namespace ClassModelNodes { /// Special folder /// It displays all items of a given project. class ProjectFolder : public DocumentClassesFolder { Q_OBJECT public: ProjectFolder(NodesModelInterface* a_model, KDevelop::IProject* project); explicit ProjectFolder(NodesModelInterface* a_model); virtual void populateNode() override; protected: KDevelop::IProject* m_project; }; /// Filter for the project folder. /// TODO: can't we share some code with FilteredAllClassesFolder somehow? class FilteredProjectFolder : public ProjectFolder { Q_OBJECT public: FilteredProjectFolder(NodesModelInterface* a_model, KDevelop::IProject* project); public: // Operations. /// Call this to update the classes filter string. void updateFilterString(QString a_newFilterString); private: // DocumentClassesFolder overrides virtual bool isClassFiltered(const KDevelop::QualifiedIdentifier& a_id) override; private: /// We'll use this string to display only classes that match this string. QString m_filterString; }; } -#endif // KDEVPLATFORM_PLUGIN_PROJECTFOLDER_H +#endif // KDEVPLATFORM_PROJECTFOLDER_H diff --git a/plugins/classbrowser/CMakeLists.txt b/plugins/classbrowser/CMakeLists.txt index 9989a4c7fb..532f927f2a 100644 --- a/plugins/classbrowser/CMakeLists.txt +++ b/plugins/classbrowser/CMakeLists.txt @@ -1,34 +1,28 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kdevclassbrowser\") include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${KDevPlatform_SOURCE_DIR} ${Boost_INCLUDE_DIRS} ) # workaround a boost bug in 1.37 and 1.38 that causes link failure when exceptions are disabled # see https://svn.boost.org/trac/boost/ticket/2947 for details if( ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_PATCH_VERSION} VERSION_GREATER 1.36.1 ) kde_enable_exceptions() endif() ########### next target ############### set(kdevclassbrowser_PART_SRCS classbrowserplugin.cpp - classmodel.cpp - classmodelnode.cpp - classmodelnodescontroller.cpp classwidget.cpp classtree.cpp - documentclassesfolder.cpp - projectfolder.cpp - allclassesfolder.cpp ) kdevplatform_add_plugin(kdevclassbrowser JSON kdevclassbrowser.json SOURCES ${kdevclassbrowser_PART_SRCS}) target_link_libraries(kdevclassbrowser KF5::TextEditor KDev::Util KDev::Language KDev::Interfaces KDev::Project) ########### install files ############### install(FILES kdevclassbrowser.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/kdevclassbrowser) diff --git a/plugins/classbrowser/classbrowserplugin.cpp b/plugins/classbrowser/classbrowserplugin.cpp index 140ed7d9a2..ba98ee3bb4 100644 --- a/plugins/classbrowser/classbrowserplugin.cpp +++ b/plugins/classbrowser/classbrowserplugin.cpp @@ -1,187 +1,187 @@ /* * This file is part of KDevelop * * Copyright 2006 Adam Treat * Copyright 2006-2008 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "classbrowserplugin.h" #include #include #include #include "interfaces/icore.h" #include "interfaces/iuicontroller.h" #include "interfaces/idocumentcontroller.h" #include "interfaces/contextmenuextension.h" #include "language/interfaces/codecontext.h" #include "language/duchain/duchainbase.h" #include "language/duchain/duchain.h" #include "language/duchain/duchainlock.h" #include "language/duchain/declaration.h" #include #include "debug.h" -#include "classmodel.h" +#include "language/classmodel/classmodel.h" #include "classtree.h" #include "classwidget.h" #include #include #include #include #include #include Q_LOGGING_CATEGORY(PLUGIN_CLASSBROWSER, "kdevplatform.plugins.classbrowser") K_PLUGIN_FACTORY_WITH_JSON(KDevClassBrowserFactory, "kdevclassbrowser.json", registerPlugin(); ) using namespace KDevelop; class ClassBrowserFactory: public KDevelop::IToolViewFactory { public: ClassBrowserFactory(ClassBrowserPlugin *plugin): m_plugin(plugin) {} virtual QWidget* create(QWidget *parent = 0) override { return new ClassWidget(parent, m_plugin); } virtual Qt::DockWidgetArea defaultPosition() override { return Qt::LeftDockWidgetArea; } virtual QString id() const override { return "org.kdevelop.ClassBrowserView"; } private: ClassBrowserPlugin *m_plugin; }; ClassBrowserPlugin::ClassBrowserPlugin(QObject *parent, const QVariantList&) : KDevelop::IPlugin("kdevclassbrowser", parent) , m_factory(new ClassBrowserFactory(this)) , m_activeClassTree(0) { core()->uiController()->addToolView(i18n("Classes"), m_factory); setXMLFile( "kdevclassbrowser.rc" ); m_findInBrowser = new QAction(i18n("Find in &Class Browser"), this); connect(m_findInBrowser, &QAction::triggered, this, &ClassBrowserPlugin::findInClassBrowser); } ClassBrowserPlugin::~ClassBrowserPlugin() { } void ClassBrowserPlugin::unload() { core()->uiController()->removeToolView(m_factory); } KDevelop::ContextMenuExtension ClassBrowserPlugin::contextMenuExtension( KDevelop::Context* context) { KDevelop::ContextMenuExtension menuExt = KDevelop::IPlugin::contextMenuExtension( context ); // No context menu if we don't have a class browser at hand. if ( m_activeClassTree == 0 ) return menuExt; KDevelop::DeclarationContext *codeContext = dynamic_cast(context); if (!codeContext) return menuExt; DUChainReadLocker readLock(DUChain::lock()); Declaration* decl(codeContext->declaration().data()); if (decl) { if(decl->inSymbolTable()) { if(!ClassTree::populatingClassBrowserContextMenu() && ICore::self()->projectController()->findProjectForUrl(decl->url().toUrl()) && decl->kind() == Declaration::Type && decl->internalContext() && decl->internalContext()->type() == DUContext::Class) { //Currently "Find in Class Browser" seems to only work for classes, so only show it in that case m_findInBrowser->setData(QVariant::fromValue(DUChainBasePointer(decl))); menuExt.addAction( KDevelop::ContextMenuExtension::ExtensionGroup, m_findInBrowser); } } } return menuExt; } void ClassBrowserPlugin::findInClassBrowser() { ICore::self()->uiController()->findToolView(i18n("Classes"), m_factory, KDevelop::IUiController::CreateAndRaise); Q_ASSERT(qobject_cast(sender())); if ( m_activeClassTree == 0 ) return; DUChainReadLocker readLock(DUChain::lock()); QAction* a = static_cast(sender()); Q_ASSERT(a->data().canConvert()); DeclarationPointer decl = qvariant_cast(a->data()).dynamicCast(); if (decl) m_activeClassTree->highlightIdentifier(decl->qualifiedIdentifier()); } void ClassBrowserPlugin::showDefinition(DeclarationPointer declaration) { DUChainReadLocker readLock(DUChain::lock()); if ( !declaration ) return; Declaration* decl = declaration.data(); // If it's a function, find the function definition to go to the actual declaration. if ( decl && decl->isFunctionDeclaration() ) { FunctionDefinition* funcDefinition = dynamic_cast(decl); if ( funcDefinition == 0 ) funcDefinition = FunctionDefinition::definition(decl); if ( funcDefinition ) decl = funcDefinition; } if (decl) { QUrl url = decl->url().toUrl(); KTextEditor::Range range = decl->rangeInCurrentRevision(); readLock.unlock(); ICore::self()->documentController()->openDocument(url, range.start()); } } #include "classbrowserplugin.moc" // kate: space-indent on; indent-width 2; tab-width 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classtree.cpp b/plugins/classbrowser/classtree.cpp index c173e0935f..24ef38a680 100644 --- a/plugins/classbrowser/classtree.cpp +++ b/plugins/classbrowser/classtree.cpp @@ -1,161 +1,161 @@ /* * KDevelop Class viewer * * Copyright 2006 Adam Treat * Copyright (c) 2006-2007 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "classtree.h" #include #include #include #include "interfaces/contextmenuextension.h" #include "interfaces/icore.h" #include "interfaces/idocumentcontroller.h" #include "interfaces/idocument.h" #include "interfaces/iplugincontroller.h" #include "language/interfaces/codecontext.h" #include "language/duchain/duchainbase.h" #include "language/duchain/duchain.h" #include "language/duchain/duchainlock.h" #include "language/duchain/declaration.h" #include -#include "classmodel.h" +#include "language/classmodel/classmodel.h" #include "classbrowserplugin.h" using namespace KDevelop; ClassTree::ClassTree( QWidget* parent, ClassBrowserPlugin* plugin ) : QTreeView( parent ) , m_plugin( plugin ), m_tooltip( 0 ) { header()->hide(); setIndentation( 10 ); connect( this, &ClassTree::activated, this, &ClassTree::itemActivated ); } ClassTree::~ClassTree() { } static bool _populatingClassBrowserContextMenu = false; bool ClassTree::populatingClassBrowserContextMenu() { return _populatingClassBrowserContextMenu; } void ClassTree::contextMenuEvent( QContextMenuEvent* e ) { QMenu *menu = new QMenu( this ); QModelIndex index = indexAt( e->pos() ); if ( index.isValid() ) { Context* c; { DUChainReadLocker readLock( DUChain::lock() ); if( Declaration* decl = dynamic_cast( model()->duObjectForIndex( index ) ) ) c = new DeclarationContext( decl ); else { delete menu; return; } } _populatingClassBrowserContextMenu = true; QList extensions = ICore::self()->pluginController()->queryPluginsForContextMenuExtensions( c ); ContextMenuExtension::populateMenu( menu, extensions ); _populatingClassBrowserContextMenu = false; } if ( !menu->actions().isEmpty() ) menu->exec( QCursor::pos() ); } bool ClassTree::event( QEvent* event ) { if ( event->type() == QEvent::ToolTip ) { // if we request a tooltip over a duobject item, show a tooltip for it const QPoint &p = mapFromGlobal( QCursor::pos() ); const QModelIndex &idxView = indexAt( p ); DUChainReadLocker readLock( DUChain::lock() ); if ( Declaration* decl = dynamic_cast( model()->duObjectForIndex( idxView ) ) ) { if ( m_tooltip ) { m_tooltip->close(); } QWidget* navigationWidget = decl->topContext()->createNavigationWidget( decl ); if ( navigationWidget ) { m_tooltip = new KDevelop::NavigationToolTip( this, mapToGlobal( p ) + QPoint( 40, 0 ), navigationWidget ); m_tooltip->resize( navigationWidget->sizeHint() + QSize( 10, 10 ) ); ActiveToolTip::showToolTip( m_tooltip ); return true; } } } return QAbstractItemView::event( event ); } ClassModel* ClassTree::model() { return static_cast( QTreeView::model() ); } void ClassTree::itemActivated( const QModelIndex& index ) { DUChainReadLocker readLock( DUChain::lock() ); DeclarationPointer decl = DeclarationPointer( dynamic_cast( model()->duObjectForIndex( index ) ) ); readLock.unlock(); // Delegate to plugin function m_plugin->showDefinition( decl ); if( isExpanded( index ) ) collapse( index ); else expand( index ); } void ClassTree::highlightIdentifier( KDevelop::IndexedQualifiedIdentifier a_id ) { QModelIndex index = model()->getIndexForIdentifier( a_id ); if ( !index.isValid() ) return; // expand and select the item. selectionModel()->select( index, QItemSelectionModel::ClearAndSelect ); scrollTo( index, PositionAtCenter ); expand( index ); } // kate: space-indent on; indent-width 2; tab-width: 4; replace-tabs on; auto-insert-doxygen on diff --git a/plugins/classbrowser/classwidget.cpp b/plugins/classbrowser/classwidget.cpp index 53d09ab32e..4a8db5c000 100644 --- a/plugins/classbrowser/classwidget.cpp +++ b/plugins/classbrowser/classwidget.cpp @@ -1,94 +1,94 @@ /* * KDevelop Class viewer * * Copyright 2006 Adam Treat * Copyright (c) 2006-2007 Hamish Rodda * Copyright 2009 Lior Mualem * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "classwidget.h" #include #include #include #include #include #include -#include "classmodel.h" +#include "language/classmodel/classmodel.h" #include "classtree.h" #include "classbrowserplugin.h" using namespace KDevelop; ClassWidget::ClassWidget(QWidget* parent, ClassBrowserPlugin* plugin) : QWidget(parent) , m_plugin(plugin) , m_model(new ClassModel()) , m_tree(new ClassTree(this, plugin)) , m_searchLine(new QLineEdit(this)) { setObjectName("Class Browser Tree"); setWindowTitle(i18n("Classes")); setWindowIcon(QIcon::fromTheme("code-class")); // Set tree in the plugin m_plugin->setActiveClassTree(m_tree); // Set model in the tree view m_tree->setModel(m_model); m_tree->header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); m_tree->header()->setStretchLastSection(false); // We need notification in the model for the collapse/expansion of nodes. connect(m_tree, &ClassTree::collapsed, m_model, &ClassModel::collapsed); connect(m_tree, &ClassTree::expanded, m_model, &ClassModel::expanded); // Init search box m_searchLine->setClearButtonEnabled( true ); connect(m_searchLine, &QLineEdit::textChanged, m_model, &ClassModel::updateFilterString); QLabel *searchLabel = new QLabel( i18n("S&earch:"), this ); searchLabel->setBuddy( m_searchLine ); QHBoxLayout* layout = new QHBoxLayout(); layout->setSpacing( 5 ); layout->setMargin( 0 ); layout->addWidget(searchLabel); layout->addWidget(m_searchLine); setFocusProxy( m_searchLine ); QVBoxLayout* vbox = new QVBoxLayout(this); vbox->setMargin(0); vbox->addLayout(layout); vbox->addWidget(m_tree); setLayout( vbox ); setWhatsThis( i18n( "Class Browser" ) ); } ClassWidget::~ClassWidget() { delete m_model; } // kate: space-indent on; indent-width 2; tab-width: 4; replace-tabs on; auto-insert-doxygen on