summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLeandro Melo <leandro.melo@nokia.com>2010-08-13 16:38:45 +0200
committerLeandro Melo <leandro.melo@nokia.com>2010-08-13 16:44:59 +0200
commitf79187ca9772b70a07694becabd936b0184337ed (patch)
treed196bb186e1c46f6eb3cb6dc5f62422c03874515 /src
parent761a9694f9413bf11425b7f1607a2ae04cf8ab3b (diff)
downloadqt-creator-f79187ca9772b70a07694becabd936b0184337ed.tar.gz
Create type hierarchy widget; Refactor code from C++ hover into a simple reusable model.
Hierarchy information removed from tooltips now.
Diffstat (limited to 'src')
-rw-r--r--src/plugins/cppeditor/cppeditor.cpp3
-rw-r--r--src/plugins/cppeditor/cppeditor.h7
-rw-r--r--src/plugins/cppeditor/cppeditor.pro14
-rw-r--r--src/plugins/cppeditor/cppeditorconstants.h3
-rw-r--r--src/plugins/cppeditor/cppelementevaluator.cpp500
-rw-r--r--src/plugins/cppeditor/cppelementevaluator.h238
-rw-r--r--src/plugins/cppeditor/cpphoverhandler.cpp409
-rw-r--r--src/plugins/cppeditor/cpphoverhandler.h27
-rw-r--r--src/plugins/cppeditor/cppplugin.cpp29
-rw-r--r--src/plugins/cppeditor/cppplugin.h3
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.cpp267
-rw-r--r--src/plugins/cppeditor/cpptypehierarchy.h142
-rw-r--r--src/plugins/texteditor/basehoverhandler.cpp4
-rw-r--r--src/plugins/texteditor/basehoverhandler.h26
-rw-r--r--src/plugins/texteditor/basetexteditor.h2
15 files changed, 1237 insertions, 437 deletions
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index a25d67c60d..9913d2a289 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -1755,6 +1755,9 @@ void CPPEditor::unCommentSelection()
CPPEditor::Link CPPEditor::linkToSymbol(CPlusPlus::Symbol *symbol)
{
+ if (!symbol)
+ return Link();
+
const QString fileName = QString::fromUtf8(symbol->fileName(),
symbol->fileNameLength());
unsigned line = symbol->line();
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 40fe6b1e6c..994bfacb67 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -180,6 +180,10 @@ public:
void setObjCEnabled(bool onoff);
bool isObjCEnabled() const;
+ bool openLink(const Link &link) { return openCppEditorAt(link); }
+
+ static Link linkToSymbol(CPlusPlus::Symbol *symbol);
+
Q_SIGNALS:
void outlineModelIndexChanged(const QModelIndex &index);
@@ -267,13 +271,10 @@ private:
void abortRename();
Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
- bool openLink(const Link &link) { return openCppEditorAt(link); }
bool openCppEditorAt(const Link &);
QModelIndex indexForPosition(int line, int column, const QModelIndex &rootIndex = QModelIndex()) const;
- static Link linkToSymbol(CPlusPlus::Symbol *symbol);
-
CppTools::CppModelManagerInterface *m_modelManager;
QComboBox *m_outlineCombo;
diff --git a/src/plugins/cppeditor/cppeditor.pro b/src/plugins/cppeditor/cppeditor.pro
index be74639661..4e37070300 100644
--- a/src/plugins/cppeditor/cppeditor.pro
+++ b/src/plugins/cppeditor/cppeditor.pro
@@ -20,8 +20,9 @@ HEADERS += cppplugin.h \
cppsemanticinfo.h \
cppoutline.h \
cppdeclfromdef.h \
- cpplocalsymbols.h
-
+ cpplocalsymbols.h \
+ cpptypehierarchy.h \
+ cppelementevaluator.h
SOURCES += cppplugin.cpp \
cppeditor.cpp \
cpphighlighter.cpp \
@@ -35,8 +36,9 @@ SOURCES += cppplugin.cpp \
cppsemanticinfo.cpp \
cppoutline.cpp \
cppdeclfromdef.cpp \
- cpplocalsymbols.cpp
-
+ cpplocalsymbols.cpp \
+ cpptypehierarchy.cpp \
+ cppelementevaluator.cpp
RESOURCES += cppeditor.qrc
-
-OTHER_FILES += CppEditor.pluginspec CppEditor.mimetypes.xml
+OTHER_FILES += CppEditor.pluginspec \
+ CppEditor.mimetypes.xml
diff --git a/src/plugins/cppeditor/cppeditorconstants.h b/src/plugins/cppeditor/cppeditorconstants.h
index 192cd83df5..8993e03a28 100644
--- a/src/plugins/cppeditor/cppeditorconstants.h
+++ b/src/plugins/cppeditor/cppeditorconstants.h
@@ -48,6 +48,9 @@ const char * const FIND_REFERENCES = "CppEditor.FindReferences";
const char * const JUMP_TO_DEFINITION = "CppEditor.JumpToDefinition";
const char * const UPDATE_CODEMODEL = "CppEditor.UpdateCodeModel";
+const char * const TYPE_HIERARCHY_ID = "CppEditor.TypeHierarchy";
+const char * const OPEN_TYPE_HIERARCHY = "CppEditor.OpenTypeHierarchy";
+
const char * const HEADER_FILE_TYPE = "CppHeaderFiles";
const char * const SOURCE_FILE_TYPE = "CppSourceFiles";
diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp
new file mode 100644
index 0000000000..2902051d6a
--- /dev/null
+++ b/src/plugins/cppeditor/cppelementevaluator.cpp
@@ -0,0 +1,500 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cppelementevaluator.h"
+
+#include <coreplugin/ifile.h>
+#include <cpptools/cppmodelmanagerinterface.h>
+
+#include <FullySpecifiedType.h>
+#include <Names.h>
+#include <CoreTypes.h>
+#include <Scope.h>
+#include <Symbol.h>
+#include <Symbols.h>
+#include <cplusplus/ExpressionUnderCursor.h>
+#include <cplusplus/Overview.h>
+#include <cplusplus/TypeOfExpression.h>
+#include <cplusplus/LookupContext.h>
+#include <cplusplus/LookupItem.h>
+#include <cplusplus/Icons.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QSet>
+#include <QtCore/QQueue>
+
+using namespace CppEditor;
+using namespace Internal;
+using namespace CPlusPlus;
+
+namespace {
+ void moveCursorToEndOfName(QTextCursor *tc) {
+ QTextDocument *doc = tc->document();
+ if (!doc)
+ return;
+
+ QChar ch = doc->characterAt(tc->position());
+ while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
+ tc->movePosition(QTextCursor::NextCharacter);
+ ch = doc->characterAt(tc->position());
+ }
+ }
+}
+
+CppElementEvaluator::CppElementEvaluator(CPPEditor *editor) :
+ m_editor(editor),
+ m_modelManager(CppTools::CppModelManagerInterface::instance()),
+ m_tc(editor->textCursor()),
+ m_lookupBaseClasses(false)
+{}
+
+void CppElementEvaluator::setTextCursor(const QTextCursor &tc)
+{ m_tc = tc; }
+
+void CppElementEvaluator::setLookupBaseClasses(const bool lookup)
+{ m_lookupBaseClasses = lookup; }
+
+QSharedPointer<CppElement> CppElementEvaluator::identifyCppElement()
+{
+ m_element.clear();
+ evaluate();
+ return m_element;
+}
+
+// @todo: Consider refactoring code from CPPEditor::findLinkAt into here.
+void CppElementEvaluator::evaluate()
+{
+ if (!m_modelManager)
+ return;
+
+ const Snapshot &snapshot = m_modelManager->snapshot();
+ Document::Ptr doc = snapshot.document(m_editor->file()->fileName());
+ if (!doc)
+ return;
+
+ int line = 0;
+ int column = 0;
+ const int pos = m_tc.position();
+ m_editor->convertPosition(pos, &line, &column);
+
+ if (!matchDiagnosticMessage(doc, line)) {
+ if (!matchIncludeFile(doc, line) && !matchMacroInUse(doc, pos)) {
+ moveCursorToEndOfName(&m_tc);
+
+ // Fetch the expression's code
+ ExpressionUnderCursor expressionUnderCursor;
+ const QString &expression = expressionUnderCursor(m_tc);
+ Scope *scope = doc->scopeAt(line, column);
+
+ TypeOfExpression typeOfExpression;
+ typeOfExpression.init(doc, snapshot);
+ const QList<LookupItem> &lookupItems = typeOfExpression(expression, scope);
+ if (lookupItems.isEmpty())
+ return;
+
+ const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
+ handleLookupItemMatch(snapshot, lookupItem, typeOfExpression.context());
+ }
+ }
+}
+
+bool CppElementEvaluator::matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document,
+ unsigned line)
+{
+ foreach (const Document::DiagnosticMessage &m, document->diagnosticMessages()) {
+ if (m.line() == line) {
+ m_element = QSharedPointer<CppElement>(new CppDiagnosis(m));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CppElementEvaluator::matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line)
+{
+ foreach (const Document::Include &includeFile, document->includes()) {
+ if (includeFile.line() == line) {
+ m_element = QSharedPointer<CppElement>(new CppInclude(includeFile));
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CppElementEvaluator::matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos)
+{
+ foreach (const Document::MacroUse &use, document->macroUses()) {
+ if (use.contains(pos)) {
+ const unsigned begin = use.begin();
+ const QString &name = use.macro().name();
+ if (pos < begin + name.length()) {
+ m_element = QSharedPointer<CppElement>(new CppMacro(use.macro()));
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot,
+ const LookupItem &lookupItem,
+ const LookupContext &context)
+{
+ Symbol *declaration = lookupItem.declaration();
+ if (!declaration) {
+ const QString &type = Overview().prettyType(lookupItem.type(), QString());
+ m_element = QSharedPointer<CppElement>(new Unknown(type));
+ } else {
+ const FullySpecifiedType &type = declaration->type();
+ if (declaration->isNamespace()) {
+ m_element = QSharedPointer<CppElement>(new CppNamespace(declaration));
+ } else if (declaration->isClass() || declaration->isForwardClassDeclaration()) {
+ if (declaration->isForwardClassDeclaration())
+ if (Symbol *classDeclaration = snapshot.findMatchingClassDeclaration(declaration))
+ declaration = classDeclaration;
+ CppClass *cppClass = new CppClass(declaration);
+ if (m_lookupBaseClasses)
+ cppClass->lookupBases(declaration, context);
+ m_element = QSharedPointer<CppElement>(cppClass);
+ } else if (declaration->isEnum() || declaration->scope()->isEnum()) {
+ m_element = QSharedPointer<CppElement>(new CppEnum(declaration));
+ } else if (declaration->isTypedef()) {
+ m_element = QSharedPointer<CppElement>(new CppTypedef(declaration));
+ } else if (declaration->isFunction() || (type.isValid() && type->isFunctionType())) {
+ m_element = QSharedPointer<CppElement>(new CppFunction(declaration));
+ } else if (declaration->isDeclaration() && type.isValid()) {
+ m_element = QSharedPointer<CppElement>(
+ new CppVariable(declaration, context, lookupItem.scope()));
+ } else {
+ m_element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration));
+ }
+ }
+}
+
+// CppElement
+CppElement::CppElement() : m_helpCategory(CppHoverHandler::HelpCandidate::Unknown)
+{}
+
+CppElement::~CppElement()
+{}
+
+void CppElement::setHelpCategory(const CppHoverHandler::HelpCandidate::Category &cat)
+{ m_helpCategory = cat; }
+
+const CppHoverHandler::HelpCandidate::Category &CppElement::helpCategory() const
+{ return m_helpCategory; }
+
+void CppElement::setHelpIdCandidates(const QStringList &candidates)
+{ m_helpIdCandidates = candidates; }
+
+void CppElement::addHelpIdCandidate(const QString &candidate)
+{ m_helpIdCandidates.append(candidate); }
+
+const QStringList &CppElement::helpIdCandidates() const
+{ return m_helpIdCandidates; }
+
+void CppElement::setHelpMark(const QString &mark)
+{ m_helpMark = mark; }
+
+const QString &CppElement::helpMark() const
+{ return m_helpMark; }
+
+void CppElement::setLink(const CPPEditor::Link &link)
+{ m_link = link; }
+
+const CPPEditor::Link &CppElement::link() const
+{ return m_link; }
+
+void CppElement::setTooltip(const QString &tooltip)
+{ m_tooltip = tooltip; }
+
+const QString &CppElement::tooltip() const
+{ return m_tooltip; }
+
+
+// Unknown
+Unknown::Unknown(const QString &type) : CppElement(), m_type(type)
+{
+ setTooltip(m_type);
+}
+
+Unknown::~Unknown()
+{}
+
+const QString &Unknown::type() const
+{ return m_type; }
+
+// CppDiagnosis
+CppDiagnosis::CppDiagnosis(const Document::DiagnosticMessage &message) :
+ CppElement(), m_text(message.text())
+{
+ setTooltip(m_text);
+}
+
+CppDiagnosis::~CppDiagnosis()
+{}
+
+const QString &CppDiagnosis::text() const
+{ return m_text; }
+
+// CppInclude
+CppInclude::~CppInclude()
+{}
+
+CppInclude::CppInclude(const Document::Include &includeFile) :
+ CppElement(),
+ m_path(QDir::toNativeSeparators(includeFile.fileName())),
+ m_fileName(QFileInfo(includeFile.fileName()).fileName())
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::Brief);
+ setHelpIdCandidates(QStringList(m_fileName));
+ setHelpMark(m_fileName);
+ setLink(CPPEditor::Link(m_path));
+ setTooltip(m_path);
+}
+
+const QString &CppInclude::path() const
+{ return m_path; }
+
+const QString &CppInclude::fileName() const
+{ return m_fileName; }
+
+// CppMacro
+CppMacro::CppMacro(const Macro &macro) : CppElement()
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::Macro);
+ setHelpIdCandidates(QStringList(macro.name()));
+ setHelpMark(macro.name());
+ setLink(CPPEditor::Link(macro.fileName(), macro.line()));
+ setTooltip(macro.toString());
+}
+
+CppMacro::~CppMacro()
+{}
+
+// CppDeclarableElement
+CppDeclarableElement::CppDeclarableElement(Symbol *declaration) : CppElement()
+{
+ const FullySpecifiedType &type = declaration->type();
+
+ Overview overview;
+ overview.setShowArgumentNames(true);
+ overview.setShowReturnTypes(true);
+
+ m_icon = Icons().iconForSymbol(declaration);
+ m_name = overview.prettyName(declaration->name());
+ if (declaration->scope()->isClass() ||
+ declaration->scope()->isNamespace() ||
+ declaration->scope()->isEnum()) {
+ m_qualifiedName = overview.prettyName(LookupContext::fullyQualifiedName(declaration));
+ } else {
+ m_qualifiedName = m_name;
+ }
+
+ if (declaration->isClass() ||
+ declaration->isNamespace() ||
+ declaration->isForwardClassDeclaration() ||
+ declaration->isEnum()) {
+ m_type = m_qualifiedName;
+ } else {
+ m_type = overview.prettyType(type, m_qualifiedName);
+ }
+
+ setTooltip(m_type);
+ setLink(CPPEditor::linkToSymbol(declaration));
+
+ QStringList helpIds;
+ helpIds << m_name << m_qualifiedName;
+ setHelpIdCandidates(helpIds);
+ setHelpMark(m_name);
+}
+
+CppDeclarableElement::~CppDeclarableElement()
+{}
+
+void CppDeclarableElement::setName(const QString &name)
+{ m_name = name; }
+
+const QString &CppDeclarableElement::name() const
+{ return m_name; }
+
+void CppDeclarableElement::setQualifiedName(const QString &name)
+{ m_qualifiedName = name; }
+
+const QString &CppDeclarableElement::qualifiedName() const
+{ return m_qualifiedName; }
+
+void CppDeclarableElement::setType(const QString &type)
+{ m_type = type; }
+
+const QString &CppDeclarableElement::type() const
+{ return m_type; }
+
+void CppDeclarableElement::setIcon(const QIcon &icon)
+{ m_icon = icon; }
+
+const QIcon &CppDeclarableElement::icon() const
+{ return m_icon; }
+
+// CppNamespace
+CppNamespace::CppNamespace(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+}
+
+CppNamespace::~CppNamespace()
+{}
+
+// CppClass
+CppClass::CppClass(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+}
+
+CppClass::~CppClass()
+{}
+
+void CppClass::lookupBases(Symbol *declaration, const CPlusPlus::LookupContext &context)
+{
+ typedef QPair<ClassOrNamespace *, CppClass *> Data;
+
+ if (ClassOrNamespace *clazz = context.lookupType(declaration)) {
+ QSet<ClassOrNamespace *> visited;
+
+ QQueue<Data> q;
+ q.enqueue(qMakePair(clazz, this));
+ while (!q.isEmpty()) {
+ Data current = q.dequeue();
+ clazz = current.first;
+ visited.insert(clazz);
+ const QList<ClassOrNamespace *> &bases = clazz->usings();
+ foreach (ClassOrNamespace *baseClass, bases) {
+ const QList<Symbol *> &symbols = baseClass->symbols();
+ foreach (Symbol *symbol, symbols) {
+ if (symbol->isClass() && (
+ clazz = context.lookupType(symbol)) &&
+ !visited.contains(clazz)) {
+ CppClass baseCppClass(symbol);
+ CppClass *cppClass = current.second;
+ cppClass->m_bases.append(baseCppClass);
+ q.enqueue(qMakePair(clazz, &cppClass->m_bases.last()));
+ }
+ }
+ }
+ }
+ }
+}
+
+const QList<CppClass> &CppClass::bases() const
+{ return m_bases; }
+
+// CppFunction
+CppFunction::CppFunction(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::Function);
+
+ const FullySpecifiedType &type = declaration->type();
+
+ // Functions marks can be found either by the main overload or signature based
+ // (with no argument names and no return). Help ids have no signature at all.
+ Overview overview;
+ overview.setShowDefaultArguments(false);
+ setHelpMark(overview.prettyType(type, name()));
+
+ overview.setShowFunctionSignatures(false);
+ addHelpIdCandidate(overview.prettyName(declaration->name()));
+}
+
+CppFunction::~CppFunction()
+{}
+
+// CppEnum
+CppEnum::CppEnum(Symbol *declaration) : CppDeclarableElement(declaration)
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::Enum);
+
+ if (declaration->scope()->isEnum()) {
+ Symbol *enumSymbol = declaration->scope()->asEnum();
+ Overview overview;
+ setHelpMark(overview.prettyName(enumSymbol->name()));
+ setTooltip(overview.prettyName(LookupContext::fullyQualifiedName(enumSymbol)));
+ }
+}
+
+CppEnum::~CppEnum()
+{}
+
+// CppTypedef
+CppTypedef::CppTypedef(Symbol *declaration) :
+ CppDeclarableElement(declaration)
+{
+ setHelpCategory(CppHoverHandler::HelpCandidate::Typedef);
+}
+
+CppTypedef::~CppTypedef()
+{}
+
+// CppVariable
+CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scope *scope) :
+ CppDeclarableElement(declaration)
+{
+ const FullySpecifiedType &type = declaration->type();
+
+ const Name *typeName = 0;
+ if (type->isNamedType()) {
+ typeName = type->asNamedType()->name();
+ } else if (type->isPointerType() || type->isReferenceType()) {
+ FullySpecifiedType associatedType;
+ if (type->isPointerType())
+ associatedType = type->asPointerType()->elementType();
+ else
+ associatedType = type->asReferenceType()->elementType();
+ if (associatedType->isNamedType())
+ typeName = associatedType->asNamedType()->name();
+ }
+
+ if (typeName) {
+ if (ClassOrNamespace *clazz = context.lookupType(typeName, scope)) {
+ if (!clazz->symbols().isEmpty()) {
+ Overview overview;
+ Symbol *symbol = clazz->symbols().at(0);
+ const QString &name =
+ overview.prettyName(LookupContext::fullyQualifiedName(symbol));
+ setTooltip(name);
+ setHelpCategory(CppHoverHandler::HelpCandidate::ClassOrNamespace);
+ setHelpMark(name);
+ setHelpIdCandidates(QStringList(name));
+ }
+ }
+ }
+}
+
+CppVariable::~CppVariable()
+{}
diff --git a/src/plugins/cppeditor/cppelementevaluator.h b/src/plugins/cppeditor/cppelementevaluator.h
new file mode 100644
index 0000000000..92a454877b
--- /dev/null
+++ b/src/plugins/cppeditor/cppelementevaluator.h
@@ -0,0 +1,238 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPPHIGHLEVELMODEL_H
+#define CPPHIGHLEVELMODEL_H
+
+#include "cppeditor.h"
+#include "cpphoverhandler.h"
+
+#include <cplusplus/CppDocument.h>
+#include <cplusplus/Overview.h>
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QTextCursor>
+#include <QtGui/QIcon>
+
+namespace CPlusPlus {
+class LookupItem;
+class LookupContext;
+}
+
+namespace CppTools {
+class CppModelManagerInterface;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class CPPEditor;
+class CppElement;
+
+class CppElementEvaluator
+{
+public:
+ CppElementEvaluator(CPPEditor *editor);
+
+ void setTextCursor(const QTextCursor &tc);
+ void setLookupBaseClasses(const bool lookup);
+
+ QSharedPointer<CppElement> identifyCppElement();
+
+private:
+ void evaluate();
+ bool matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document, unsigned line);
+ bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line);
+ bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos);
+ void handleLookupItemMatch(const CPlusPlus::Snapshot &snapshot,
+ const CPlusPlus::LookupItem &lookupItem,
+ const CPlusPlus::LookupContext &lookupContext);
+
+ CPPEditor *m_editor;
+ CppTools::CppModelManagerInterface *m_modelManager;
+ QTextCursor m_tc;
+ bool m_lookupBaseClasses;
+ QSharedPointer<CppElement> m_element;
+};
+
+class CppElement
+{
+public:
+ virtual ~CppElement();
+
+ const CppHoverHandler::HelpCandidate::Category &helpCategory() const;
+ const QStringList &helpIdCandidates() const;
+ const QString &helpMark() const;
+ const CPPEditor::Link &link() const;
+ const QString &tooltip() const;
+
+protected:
+ CppElement();
+
+ void setHelpCategory(const CppHoverHandler::HelpCandidate::Category &category);
+ void setLink(const CPPEditor::Link &link);
+ void setTooltip(const QString &tooltip);
+ void setHelpIdCandidates(const QStringList &candidates);
+ void addHelpIdCandidate(const QString &candidate);
+ void setHelpMark(const QString &mark);
+
+private:
+ CppHoverHandler::HelpCandidate::Category m_helpCategory;
+ QStringList m_helpIdCandidates;
+ QString m_helpMark;
+ CPPEditor::Link m_link;
+ QString m_tooltip;
+};
+
+class Unknown : public CppElement
+{
+public:
+ Unknown(const QString &type);
+ virtual ~Unknown();
+
+ const QString &type() const;
+
+private:
+ QString m_type;
+};
+
+class CppDiagnosis : public CppElement
+{
+public:
+ CppDiagnosis(const CPlusPlus::Document::DiagnosticMessage &message);
+ virtual ~CppDiagnosis();
+
+ const QString &text() const;
+
+private:
+ QString m_text;
+};
+
+class CppInclude : public CppElement
+{
+public:
+ CppInclude(const CPlusPlus::Document::Include &includeFile);
+ virtual ~CppInclude();
+
+ const QString &path() const;
+ const QString &fileName() const;
+
+private:
+ QString m_path;
+ QString m_fileName;
+};
+
+class CppMacro : public CppElement
+{
+public:
+ CppMacro(const CPlusPlus::Macro &macro);
+ virtual ~CppMacro();
+};
+
+class CppDeclarableElement : public CppElement
+{
+public:
+ CppDeclarableElement(CPlusPlus::Symbol *declaration);
+ virtual ~CppDeclarableElement();
+
+ const QString &name() const;
+ const QString &qualifiedName() const;
+ const QString &type() const;
+ const QIcon &icon() const;
+
+protected:
+ void setName(const QString &name);
+ void setQualifiedName(const QString &name);
+ void setType(const QString &type);
+ void setIcon(const QIcon &icon);
+
+private:
+ QString m_name;
+ QString m_qualifiedName;
+ QString m_type;
+ QIcon m_icon;
+};
+
+class CppNamespace : public CppDeclarableElement
+{
+public:
+ CppNamespace(CPlusPlus::Symbol *declaration);
+ virtual ~CppNamespace();
+};
+
+class CppClass : public CppDeclarableElement
+{
+public:
+ CppClass(CPlusPlus::Symbol *declaration);
+ virtual ~CppClass();
+
+ void lookupBases(CPlusPlus::Symbol *declaration, const CPlusPlus::LookupContext &context);
+
+ const QList<CppClass> &bases() const;
+
+private:
+ QList<CppClass> m_bases;
+};
+
+class CppFunction : public CppDeclarableElement
+{
+public:
+ CppFunction(CPlusPlus::Symbol *declaration);
+ virtual ~CppFunction();
+};
+
+class CppEnum : public CppDeclarableElement
+{
+public:
+ CppEnum(CPlusPlus::Symbol *declaration);
+ virtual ~CppEnum();
+};
+
+class CppTypedef : public CppDeclarableElement
+{
+public:
+ CppTypedef(CPlusPlus::Symbol *declaration);
+ virtual ~CppTypedef();
+};
+
+class CppVariable : public CppDeclarableElement
+{
+public:
+ CppVariable(CPlusPlus::Symbol *declaration,
+ const CPlusPlus::LookupContext &context,
+ CPlusPlus::Scope *scope);
+ virtual ~CppVariable();
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPHIGHLEVELMODEL_H
diff --git a/src/plugins/cppeditor/cpphoverhandler.cpp b/src/plugins/cppeditor/cpphoverhandler.cpp
index 0d4d24241b..15922d906e 100644
--- a/src/plugins/cppeditor/cpphoverhandler.cpp
+++ b/src/plugins/cppeditor/cpphoverhandler.cpp
@@ -29,6 +29,7 @@
#include "cpphoverhandler.h"
#include "cppeditor.h"
+#include "cppelementevaluator.h"
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -37,29 +38,9 @@
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h>
-#include <FullySpecifiedType.h>
-#include <Names.h>
-#include <CoreTypes.h>
-#include <Scope.h>
-#include <Symbol.h>
-#include <Symbols.h>
-#include <cplusplus/ExpressionUnderCursor.h>
-#include <cplusplus/Overview.h>
-#include <cplusplus/TypeOfExpression.h>
-#include <cplusplus/LookupContext.h>
-#include <cplusplus/LookupItem.h>
-
-#include <QtCore/QSet>
-#include <QtCore/QDir>
-#include <QtCore/QFileInfo>
-#include <QtCore/QtAlgorithms>
-#include <QtCore/QStringBuilder>
#include <QtGui/QTextCursor>
-#include <algorithm>
-
using namespace CppEditor::Internal;
-using namespace CPlusPlus;
using namespace Core;
namespace {
@@ -70,73 +51,13 @@ namespace {
else
return name.right(name.length() - index - 1);
}
-
- void moveCursorToEndOfName(QTextCursor *tc) {
- QTextDocument *doc = tc->document();
- if (!doc)
- return;
-
- QChar ch = doc->characterAt(tc->position());
- while (ch.isLetterOrNumber() || ch == QLatin1Char('_')) {
- tc->movePosition(QTextCursor::NextCharacter);
- ch = doc->characterAt(tc->position());
- }
- }
-
- void buildClassHierarchyHelper(ClassOrNamespace *classSymbol,
- const LookupContext &context,
- const Overview &overview,
- QList<QStringList> *hierarchy,
- QSet<ClassOrNamespace *> *visited) {
- visited->insert(classSymbol);
- const QList<ClassOrNamespace *> &bases = classSymbol->usings();
- foreach (ClassOrNamespace *baseClass, bases) {
- const QList<Symbol *> &symbols = baseClass->symbols();
- foreach (Symbol *baseSymbol, symbols) {
- if (baseSymbol->isClass() && (
- classSymbol = context.lookupType(baseSymbol)) &&
- !visited->contains(classSymbol)) {
- const QString &qualifiedName = overview.prettyName(
- LookupContext::fullyQualifiedName(baseSymbol));
- if (!qualifiedName.isEmpty()) {
- hierarchy->back().append(qualifiedName);
- buildClassHierarchyHelper(classSymbol,
- context,
- overview,
- hierarchy,
- visited);
- hierarchy->append(hierarchy->back());
- hierarchy->back().removeLast();
- }
- }
- }
- }
- }
-
- void buildClassHierarchy(Symbol *symbol,
- const LookupContext &context,
- const Overview &overview,
- QList<QStringList> *hierarchy) {
- if (ClassOrNamespace *classSymbol = context.lookupType(symbol)) {
- hierarchy->append(QStringList());
- QSet<ClassOrNamespace *> visited;
- buildClassHierarchyHelper(classSymbol, context, overview, hierarchy, &visited);
- hierarchy->removeLast();
- }
- }
-
- struct ClassHierarchyComp
- {
- bool operator()(const QStringList &a, const QStringList &b)
- { return a.size() < b.size(); }
- };
}
-CppHoverHandler::CppHoverHandler(QObject *parent) : BaseHoverHandler(parent), m_modelManager(0)
-{
- m_modelManager =
- ExtensionSystem::PluginManager::instance()->getObject<CppTools::CppModelManagerInterface>();
-}
+CppHoverHandler::CppHoverHandler(QObject *parent) : BaseHoverHandler(parent)
+{}
+
+CppHoverHandler::~CppHoverHandler()
+{}
bool CppHoverHandler::acceptEditor(IEditor *editor)
{
@@ -148,191 +69,25 @@ bool CppHoverHandler::acceptEditor(IEditor *editor)
void CppHoverHandler::identifyMatch(TextEditor::ITextEditor *editor, int pos)
{
- if (!m_modelManager)
- return;
-
- const Snapshot &snapshot = m_modelManager->snapshot();
- Document::Ptr doc = snapshot.document(editor->file()->fileName());
- if (!doc)
+ CPPEditor *cppEditor = qobject_cast<CPPEditor *>(editor->widget());
+ if (!cppEditor)
return;
- int line = 0;
- int column = 0;
- editor->convertPosition(pos, &line, &column);
-
- if (!matchDiagnosticMessage(doc, line)) {
- if (!matchIncludeFile(doc, line) && !matchMacroInUse(doc, pos)) {
- TextEditor::BaseTextEditor *baseEditor = baseTextEditor(editor);
- if (!baseEditor)
- return;
-
- bool extraSelectionTooltip = false;
- if (!baseEditor->extraSelectionTooltip(pos).isEmpty()) {
- setToolTip(baseEditor->extraSelectionTooltip(pos));
- extraSelectionTooltip = true;
- }
-
- QTextCursor tc(baseEditor->document());
- tc.setPosition(pos);
- moveCursorToEndOfName(&tc);
-
- // Fetch the expression's code
- ExpressionUnderCursor expressionUnderCursor;
- const QString &expression = expressionUnderCursor(tc);
- Scope *scope = doc->scopeAt(line, column);
-
- TypeOfExpression typeOfExpression;
- typeOfExpression.init(doc, snapshot);
- const QList<LookupItem> &lookupItems = typeOfExpression(expression, scope);
- if (lookupItems.isEmpty())
- return;
-
- const LookupItem &lookupItem = lookupItems.first(); // ### TODO: select best candidate.
- handleLookupItemMatch(lookupItem, typeOfExpression.context(), !extraSelectionTooltip);
- }
- }
-}
-
-bool CppHoverHandler::matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document,
- unsigned line)
-{
- foreach (const Document::DiagnosticMessage &m, document->diagnosticMessages()) {
- if (m.line() == line) {
- setToolTip(m.text());
- return true;
- }
- }
- return false;
-}
-
-bool CppHoverHandler::matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line)
-{
- foreach (const Document::Include &includeFile, document->includes()) {
- if (includeFile.line() == line) {
- setToolTip(QDir::toNativeSeparators(includeFile.fileName()));
- const QString &fileName = QFileInfo(includeFile.fileName()).fileName();
- addHelpCandidate(HelpCandidate(fileName, fileName, HelpCandidate::Brief));
- return true;
- }
- }
- return false;
-}
-
-bool CppHoverHandler::matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos)
-{
- foreach (const Document::MacroUse &use, document->macroUses()) {
- if (use.contains(pos)) {
- const unsigned begin = use.begin();
- const QString &name = use.macro().name();
- if (pos < begin + name.length()) {
- setToolTip(use.macro().toString());
- addHelpCandidate(HelpCandidate(name, name, HelpCandidate::Macro));
- return true;
- }
- }
- }
- return false;
-}
-
-void CppHoverHandler::handleLookupItemMatch(const LookupItem &lookupItem,
- const LookupContext &context,
- const bool assignTooltip)
-{
- Symbol *matchingDeclaration = lookupItem.declaration();
- FullySpecifiedType matchingType = lookupItem.type();
-
- Overview overview;
- overview.setShowArgumentNames(true);
- overview.setShowReturnTypes(true);
-
- if (!matchingDeclaration && assignTooltip) {
- setToolTip(overview.prettyType(matchingType, QString()));
+ if (!cppEditor->extraSelectionTooltip(pos).isEmpty()) {
+ setToolTip(cppEditor->extraSelectionTooltip(pos));
} else {
- QString name;
- if (matchingDeclaration->scope()->isClass() ||
- matchingDeclaration->scope()->isNamespace() ||
- matchingDeclaration->scope()->isEnum()) {
- name.append(overview.prettyName(
- LookupContext::fullyQualifiedName(matchingDeclaration)));
-
- if (matchingDeclaration->isClass() ||
- matchingDeclaration->isForwardClassDeclaration()) {
- buildClassHierarchy(matchingDeclaration, context, overview, &m_classHierarchy);
- }
- } else {
- name.append(overview.prettyName(matchingDeclaration->name()));
- }
-
- if (assignTooltip) {
- if (matchingDeclaration->isClass() ||
- matchingDeclaration->isNamespace() ||
- matchingDeclaration->isForwardClassDeclaration() ||
- matchingDeclaration->isEnum()) {
- setToolTip(name);
- } else {
- setToolTip(overview.prettyType(matchingType, name));
- }
- }
-
- HelpCandidate::Category helpCategory = HelpCandidate::Unknown;
- if (matchingDeclaration->isNamespace() ||
- matchingDeclaration->isClass() ||
- matchingDeclaration->isForwardClassDeclaration()) {
- helpCategory = HelpCandidate::ClassOrNamespace;
- } else if (matchingDeclaration->isEnum() ||
- matchingDeclaration->scope()->isEnum()) {
- helpCategory = HelpCandidate::Enum;
- } else if (matchingDeclaration->isTypedef()) {
- helpCategory = HelpCandidate::Typedef;
- } else if (matchingDeclaration->isFunction() ||
- (matchingType.isValid() && matchingType->isFunctionType())){
- helpCategory = HelpCandidate::Function;
- } else if (matchingDeclaration->isDeclaration() && matchingType.isValid()) {
- const Name *typeName = 0;
- if (matchingType->isNamedType()) {
- typeName = matchingType->asNamedType()->name();
- } else if (matchingType->isPointerType() || matchingType->isReferenceType()) {
- FullySpecifiedType type;
- if (matchingType->isPointerType())
- type = matchingType->asPointerType()->elementType();
- else
- type = matchingType->asReferenceType()->elementType();
- if (type->isNamedType())
- typeName = type->asNamedType()->name();
- }
-
- if (typeName) {
- if (ClassOrNamespace *clazz = context.lookupType(typeName, lookupItem.scope())) {
- if (!clazz->symbols().isEmpty()) {
- Symbol *symbol = clazz->symbols().at(0);
- matchingDeclaration = symbol;
- name = overview.prettyName(LookupContext::fullyQualifiedName(symbol));
- setToolTip(name);
- buildClassHierarchy(symbol, context, overview, &m_classHierarchy);
- helpCategory = HelpCandidate::ClassOrNamespace;
- }
- }
- }
- }
-
- if (helpCategory != HelpCandidate::Unknown) {
- QString docMark = overview.prettyName(matchingDeclaration->name());
-
- if (matchingType.isValid() && matchingType->isFunctionType()) {
- // Functions marks can be found either by the main overload or signature based
- // (with no argument names and no return). Help ids have no signature at all.
- overview.setShowArgumentNames(false);
- overview.setShowReturnTypes(false);
- docMark = overview.prettyType(matchingType, docMark);
- overview.setShowFunctionSignatures(false);
- const QString &functionName = overview.prettyName(matchingDeclaration->name());
- addHelpCandidate(HelpCandidate(functionName, docMark, helpCategory));
- } else if (matchingDeclaration->scope()->isEnum()) {
- Symbol *enumSymbol = matchingDeclaration->scope()->asEnum();
- docMark = overview.prettyName(enumSymbol->name());
- }
-
- addHelpCandidate(HelpCandidate(name, docMark, helpCategory));
+ QTextCursor tc(cppEditor->document());
+ tc.setPosition(pos);
+
+ CppElementEvaluator evaluator(cppEditor);
+ evaluator.setTextCursor(tc);
+ QSharedPointer<CppElement> cppElement = evaluator.identifyCppElement();
+ if (!cppElement.isNull()) {
+ setToolTip(cppElement->tooltip());
+ foreach (const QString &helpId, cppElement->helpIdCandidates())
+ addHelpCandidate(HelpCandidate(helpId,
+ cppElement->helpMark(),
+ cppElement->helpCategory()));
}
}
}
@@ -357,121 +112,8 @@ void CppHoverHandler::evaluateHelpCandidates()
void CppHoverHandler::decorateToolTip(TextEditor::ITextEditor *editor)
{
- if (!m_classHierarchy.isEmpty())
- generateDiagramTooltip(extendToolTips(editor));
- else
- generateNormalTooltip(extendToolTips(editor));
-}
-
-void CppHoverHandler::generateDiagramTooltip(const bool extendTooltips)
-{
- QString clazz = toolTip();
-
- qSort(m_classHierarchy.begin(), m_classHierarchy.end(), ClassHierarchyComp());
-
- // Remove duplicates (in case there are any).
- m_classHierarchy.erase(std::unique(m_classHierarchy.begin(), m_classHierarchy.end()),
- m_classHierarchy.end());
-
- QStringList directBaseClasses;
- foreach (const QStringList &hierarchy, m_classHierarchy) {
- if (hierarchy.size() > 1)
- break;
- directBaseClasses.append(hierarchy.at(0));
- }
-
- QString diagram(QLatin1String("<table>"));
- for (int i = 0; i < directBaseClasses.size(); ++i) {
- if (i == 0) {
- diagram.append(QString(
- "<tr><td>%1</td><td>"
- "<img src=\":/cppeditor/images/rightarrow.png\"></td>"
- "<td>%2</td></tr>").arg(toolTip()).arg(directBaseClasses.at(i)));
- } else {
- diagram.append(QString(
- "<tr><td></td><td>"
- "<img src=\":/cppeditor/images/larrow.png\"></td>"
- "<td>%1</td></tr>").arg(directBaseClasses.at(i)));
- }
- }
- diagram.append(QLatin1String("</table>"));
- setToolTip(diagram);
-
- if (matchingHelpCandidate() != -1) {
- appendToolTip(getDocContents(extendTooltips));
- } else {
- // Look for documented base classes. Diagram the nearest one or the nearest ones (in
- // the case there are many at the same level).
- int helpLevel = 0;
- QList<int> baseClassesWithHelp;
- for (int i = 0; i < m_classHierarchy.size(); ++i) {
- const QStringList &hierarchy = m_classHierarchy.at(i);
- if (helpLevel != 0 && hierarchy.size() != helpLevel)
- break;
-
- bool exists = false;
- QString name = hierarchy.last();
- if (helpIdExists(name)) {
- exists = true;
- } else {
- name = removeClassNameQualification(name);
- if (helpIdExists(name)) {
- exists = true;
- m_classHierarchy[i].last() = name;
- }
- }
- if (exists) {
- baseClassesWithHelp.append(i);
- if (helpLevel == 0)
- helpLevel = hierarchy.size();
- }
- }
-
- if (!baseClassesWithHelp.isEmpty()) {
- // Choose the first one as the help match.
- QString base = m_classHierarchy.at(baseClassesWithHelp.at(0)).last();
- HelpCandidate help(base, base, HelpCandidate::ClassOrNamespace);
- addHelpCandidate(help);
- setMatchingHelpCandidate(helpCandidates().size() - 1);
-
- if (baseClassesWithHelp.size() == 1 && helpLevel == 1) {
- appendToolTip(getDocContents(help, extendTooltips));
- } else {
- foreach (int hierarchyIndex, baseClassesWithHelp) {
- appendToolTip(QLatin1String("<p>"));
- const QStringList &hierarchy = m_classHierarchy.at(hierarchyIndex);
- Q_ASSERT(helpLevel <= hierarchy.size());
-
- // Following contents are inside tables so they are on the exact same
- // alignment as the top level diagram.
- diagram = QString(QLatin1String("<table><tr><td>%1</td>")).arg(clazz);
- for (int i = 0; i < helpLevel; ++i) {
- diagram.append(
- QLatin1String("<td><img src=\":/cppeditor/images/rightarrow.png\">"
- "</td><td>") %
- hierarchy.at(i) %
- QLatin1String("</td>"));
- }
- diagram.append(QLatin1String("</tr></table>"));
-
- base = hierarchy.at(helpLevel - 1);
- const QString &contents =
- getDocContents(HelpCandidate(base, base, HelpCandidate::Brief), false);
- if (!contents.isEmpty()) {
- appendToolTip(diagram % QLatin1String("<table><tr><td>") %
- contents % QLatin1String("</td></tr></table>"));
- }
- appendToolTip(QLatin1String("</p>"));
- }
- }
- }
- }
-}
-
-void CppHoverHandler::generateNormalTooltip(const bool extendTooltips)
-{
if (matchingHelpCandidate() != -1) {
- const QString &contents = getDocContents(extendTooltips);
+ const QString &contents = getDocContents(extendToolTips(editor));
if (!contents.isEmpty()) {
HelpCandidate::Category cat = helpCandidate(matchingHelpCandidate()).m_category;
if (cat == HelpCandidate::ClassOrNamespace)
@@ -486,8 +128,3 @@ void CppHoverHandler::generateNormalTooltip(const bool extendTooltips)
}
}
}
-
-void CppHoverHandler::resetExtras()
-{
- m_classHierarchy.clear();
-}
diff --git a/src/plugins/cppeditor/cpphoverhandler.h b/src/plugins/cppeditor/cpphoverhandler.h
index 1fab49b1d2..6c7de5cd1f 100644
--- a/src/plugins/cppeditor/cpphoverhandler.h
+++ b/src/plugins/cppeditor/cpphoverhandler.h
@@ -30,26 +30,14 @@
#ifndef CPPHOVERHANDLER_H
#define CPPHOVERHANDLER_H
-#include <cplusplus/CppDocument.h>
#include <texteditor/basehoverhandler.h>
#include <QtCore/QObject>
-#include <QtCore/QList>
-#include <QtCore/QStringList>
-
-namespace CPlusPlus {
-class LookupItem;
-class LookupContext;
-}
namespace Core {
class IEditor;
}
-namespace CppTools {
-class CppModelManagerInterface;
-}
-
namespace TextEditor {
class ITextEditor;
}
@@ -62,26 +50,13 @@ class CppHoverHandler : public TextEditor::BaseHoverHandler
Q_OBJECT
public:
CppHoverHandler(QObject *parent = 0);
+ virtual ~CppHoverHandler();
private:
virtual bool acceptEditor(Core::IEditor *editor);
virtual void identifyMatch(TextEditor::ITextEditor *editor, int pos);
- virtual void resetExtras();
virtual void evaluateHelpCandidates();
virtual void decorateToolTip(TextEditor::ITextEditor *editor);
-
- bool matchDiagnosticMessage(const CPlusPlus::Document::Ptr &document, unsigned line);
- bool matchIncludeFile(const CPlusPlus::Document::Ptr &document, unsigned line);
- bool matchMacroInUse(const CPlusPlus::Document::Ptr &document, unsigned pos);
- void handleLookupItemMatch(const CPlusPlus::LookupItem &lookupItem,
- const CPlusPlus::LookupContext &lookupContext,
- const bool assignTooltip);
-
- void generateDiagramTooltip(const bool extendTooltips);
- void generateNormalTooltip(const bool extendTooltips);
-
- CppTools::CppModelManagerInterface *m_modelManager;
- QList<QStringList> m_classHierarchy;
};
} // namespace Internal
diff --git a/src/plugins/cppeditor/cppplugin.cpp b/src/plugins/cppeditor/cppplugin.cpp
index b43bdd980b..858d2b7606 100644
--- a/src/plugins/cppeditor/cppplugin.cpp
+++ b/src/plugins/cppeditor/cppplugin.cpp
@@ -36,6 +36,7 @@
#include "cpphoverhandler.h"
#include "cppquickfix.h"
#include "cppoutline.h"
+#include "cpptypehierarchy.h"
#include <coreplugin/icore.h>
#include <coreplugin/coreconstants.h>
@@ -46,6 +47,7 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/progressmanager/progressmanager.h>
+#include <coreplugin/navigationwidget.h>
#include <texteditor/completionsupport.h>
#include <texteditor/fontsettings.h>
#include <texteditor/storagesettings.h>
@@ -60,6 +62,7 @@
#include <QtCore/QSettings>
#include <QtCore/QTimer>
#include <QtCore/QCoreApplication>
+#include <QtCore/QStringList>
#include <QtGui/QMenu>
@@ -139,8 +142,8 @@ CppPlugin::CppPlugin() :
m_sortedOutline(false),
m_renameSymbolUnderCursorAction(0),
m_findUsagesAction(0),
- m_updateCodeModelAction(0)
-
+ m_updateCodeModelAction(0),
+ m_openTypeHierarchyAction(0)
{
m_instance = this;
@@ -205,7 +208,7 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
addAutoReleasedObject(new CppEditorFactory(this));
addAutoReleasedObject(new CppHoverHandler);
addAutoReleasedObject(new CppOutlineWidgetFactory);
-
+ addAutoReleasedObject(new CppTypeHierarchyFactory);
m_quickFixCollector = new CppQuickFixCollector;
addAutoReleasedObject(m_quickFixCollector);
@@ -274,6 +277,13 @@ bool CppPlugin::initialize(const QStringList & /*arguments*/, QString *errorMess
contextMenu->addAction(cmd);
cppToolsMenu->addAction(cmd);
+ m_openTypeHierarchyAction = new QAction(tr("Open Type Hierarchy"), this);
+ cmd = am->registerAction(m_openTypeHierarchyAction, Constants::OPEN_TYPE_HIERARCHY, context);
+ cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+Shift+T")));
+ connect(m_openTypeHierarchyAction, SIGNAL(triggered()), this, SLOT(openTypeHierarchy()));
+ contextMenu->addAction(cmd);
+ cppToolsMenu->addAction(cmd);
+
// Update context in global context
Core::Context globalContext(Core::Constants::C_GLOBAL);
cppToolsMenu->addAction(createSeparator(am, this, globalContext, CppEditor::Constants::SEPARATOR2));
@@ -391,6 +401,7 @@ void CppPlugin::onTaskStarted(const QString &type)
m_renameSymbolUnderCursorAction->setEnabled(false);
m_findUsagesAction->setEnabled(false);
m_updateCodeModelAction->setEnabled(false);
+ m_openTypeHierarchyAction->setEnabled(false);
}
}
@@ -400,6 +411,7 @@ void CppPlugin::onAllTasksFinished(const QString &type)
m_renameSymbolUnderCursorAction->setEnabled(true);
m_findUsagesAction->setEnabled(true);
m_updateCodeModelAction->setEnabled(true);
+ m_openTypeHierarchyAction->setEnabled(true);
}
}
@@ -413,4 +425,15 @@ void CppPlugin::currentEditorChanged(Core::IEditor *editor)
}
}
+void CppPlugin::openTypeHierarchy()
+{
+ Core::EditorManager *em = Core::EditorManager::instance();
+ CPPEditor *editor = qobject_cast<CPPEditor*>(em->currentEditor()->widget());
+ if (editor) {
+ Core::NavigationWidget *navigation = Core::NavigationWidget::instance();
+ navigation->activateSubWidget(QLatin1String(Constants::TYPE_HIERARCHY_ID));
+ emit typeHierarchyRequested();
+ }
+}
+
Q_EXPORT_PLUGIN(CppPlugin)
diff --git a/src/plugins/cppeditor/cppplugin.h b/src/plugins/cppeditor/cppplugin.h
index b72a8a8df0..36550b560f 100644
--- a/src/plugins/cppeditor/cppplugin.h
+++ b/src/plugins/cppeditor/cppplugin.h
@@ -71,6 +71,7 @@ public:
signals:
void outlineSortingChanged(bool sort);
+ void typeHierarchyRequested();
public slots:
void setSortedOutline(bool sorted);
@@ -85,6 +86,7 @@ private slots:
void quickFix(TextEditor::ITextEditable *editable);
void quickFixNow();
void currentEditorChanged(Core::IEditor *editor);
+ void openTypeHierarchy();
private:
Core::IEditor *createEditor(QWidget *parent);
@@ -98,6 +100,7 @@ private:
QAction *m_renameSymbolUnderCursorAction;
QAction *m_findUsagesAction;
QAction *m_updateCodeModelAction;
+ QAction *m_openTypeHierarchyAction;
CppQuickFixCollector *m_quickFixCollector;
diff --git a/src/plugins/cppeditor/cpptypehierarchy.cpp b/src/plugins/cppeditor/cpptypehierarchy.cpp
new file mode 100644
index 0000000000..a132654152
--- /dev/null
+++ b/src/plugins/cppeditor/cpptypehierarchy.cpp
@@ -0,0 +1,267 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "cpptypehierarchy.h"
+#include "cppeditorconstants.h"
+#include "cppeditor.h"
+#include "cppelementevaluator.h"
+#include "cppplugin.h"
+
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/coreconstants.h>
+#include <utils/navigationtreeview.h>
+
+#include <QtCore/QLatin1Char>
+#include <QtCore/QLatin1String>
+#include <QtCore/QModelIndex>
+#include <QtCore/QSettings>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QStandardItemModel>
+#include <QtGui/QFontMetrics>
+#include <QtGui/QApplication>
+#include <QtGui/QPainter>
+#include <QtGui/QLabel>
+
+using namespace CppEditor;
+using namespace Internal;
+
+// CppTypeHierarchyItem
+CppTypeHierarchyItem::CppTypeHierarchyItem(const CppClass &cppClass) :
+ QStandardItem(), m_cppClass(cppClass)
+{}
+
+CppTypeHierarchyItem::~CppTypeHierarchyItem()
+{}
+
+int CppTypeHierarchyItem::type() const
+{ return UserType; }
+
+const CppClass &CppTypeHierarchyItem::cppClass() const
+{ return m_cppClass; }
+
+// CppTypeHierarchyDelegate
+CppTypeHierarchyDelegate::CppTypeHierarchyDelegate(QObject *parent) : QStyledItemDelegate(parent)
+{}
+
+CppTypeHierarchyDelegate::~CppTypeHierarchyDelegate()
+{}
+
+void CppTypeHierarchyDelegate::paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ if (const QStyleOptionViewItemV3 *v3 =
+ qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option)) {
+ QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, v3, painter, v3->widget);
+
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption(&opt, index);
+
+ const QStandardItemModel *model = static_cast<const QStandardItemModel *>(index.model());
+ CppTypeHierarchyItem *item =
+ static_cast<CppTypeHierarchyItem *>(model->itemFromIndex(index));
+
+ painter->save();
+ const QIcon &icon = item->cppClass().icon();
+ const QSize &iconSize = icon.actualSize(opt.decorationSize);
+ QRect workingRect(opt.rect);
+ QRect decorationRect(workingRect.topLeft(), iconSize);
+ icon.paint(painter, decorationRect, opt.decorationAlignment);
+ workingRect.setX(workingRect.x() + iconSize.width() + 4);
+
+ QRect boundingRect;
+ const QString &name = item->cppClass().name() + QLatin1Char(' ');
+ painter->drawText(workingRect, Qt::AlignLeft, name, &boundingRect);
+ if (item->cppClass().name() != item->cppClass().qualifiedName()) {
+ QFont font(painter->font());
+ if (font.pointSize() > 2)
+ font.setPointSize(font.pointSize() - 2);
+ else if (font.pointSize() > 1)
+ font.setPointSize(font.pointSize() - 1);
+ font.setItalic(true);
+ painter->setFont(font);
+
+ QFontMetrics metrics(font);
+ workingRect.setX(boundingRect.x() + boundingRect.width());
+ workingRect.setY(boundingRect.y() + boundingRect.height() - metrics.height());
+ painter->drawText(workingRect, Qt::AlignLeft, item->cppClass().qualifiedName());
+ }
+ painter->restore();
+ } else {
+ QStyledItemDelegate::paint(painter, option, index);
+ }
+}
+
+QSize CppTypeHierarchyDelegate::sizeHint(const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QSize size = QStyledItemDelegate::sizeHint(option, index);
+ size.rwidth() += 5; // Extend a bit because of the font processing.
+ return size;
+}
+
+// CppTypeHierarchyWidget
+CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) :
+ QWidget(0),
+ m_cppEditor(0),
+ m_treeView(0),
+ m_model(0),
+ m_delegate(0)
+{
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+
+ if (CPPEditorEditable *cppEditable = qobject_cast<CPPEditorEditable *>(editor)) {
+ m_cppEditor = static_cast<CPPEditor *>(cppEditable->widget());
+
+ m_model = new QStandardItemModel;
+ m_treeView = new Utils::NavigationTreeView;
+ m_delegate = new CppTypeHierarchyDelegate;
+ m_treeView->setModel(m_model);
+ m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ m_treeView->setItemDelegate(m_delegate);
+ layout->addWidget(m_treeView);
+
+ connect(m_treeView, SIGNAL(clicked(QModelIndex)), this, SLOT(onItemClicked(QModelIndex)));
+ connect(CppPlugin::instance(), SIGNAL(typeHierarchyRequested()), this, SLOT(perform()));
+ } else {
+ QLabel *label = new QLabel(tr("No type hierarchy available"), this);
+ label->setAlignment(Qt::AlignCenter);
+ label->setAutoFillBackground(true);
+ label->setBackgroundRole(QPalette::Base);
+ layout->addWidget(label);
+ }
+ setLayout(layout);
+}
+
+CppTypeHierarchyWidget::~CppTypeHierarchyWidget()
+{
+ delete m_model;
+ delete m_delegate;
+}
+
+void CppTypeHierarchyWidget::perform()
+{
+ if (!m_cppEditor)
+ return;
+
+ m_model->clear();
+
+ CppElementEvaluator evaluator(m_cppEditor);
+ evaluator.setLookupBaseClasses(true);
+ QSharedPointer<CppElement> cppElement = evaluator.identifyCppElement();
+ if (!cppElement.isNull()) {
+ CppElement *element = cppElement.data();
+ if (CppClass *cppClass = dynamic_cast<CppClass *>(element))
+ buildModel(*cppClass, m_model->invisibleRootItem());
+ }
+}
+
+void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem *parent)
+{
+ CppTypeHierarchyItem *item = new CppTypeHierarchyItem(cppClass);
+ parent->appendRow(item);
+
+ // The delegate retrieves data from the item directly. This is to help size hint.
+ const QString &display = cppClass.name() + cppClass.qualifiedName();
+ m_model->setData(m_model->indexFromItem(item), display, Qt::DisplayRole);
+ m_model->setData(m_model->indexFromItem(item), cppClass.icon(), Qt::DecorationRole);
+
+ foreach (const CppClass &cppBase, cppClass.bases())
+ buildModel(cppBase, item);
+
+ m_treeView->expand(m_model->indexFromItem(item));
+}
+
+void CppTypeHierarchyWidget::onItemClicked(const QModelIndex &index)
+{
+ if (QStandardItem *item = m_model->itemFromIndex(index)) {
+ CppTypeHierarchyItem *cppItem = static_cast<CppTypeHierarchyItem *>(item);
+ m_cppEditor->openLink(cppItem->cppClass().link());
+ }
+}
+
+// CppTypeHierarchyStackedWidget
+CppTypeHierarchyStackedWidget::CppTypeHierarchyStackedWidget(QWidget *parent) :
+ QStackedWidget(parent),
+ m_typeHiearchyWidgetInstance(
+ new CppTypeHierarchyWidget(Core::EditorManager::instance()->currentEditor()))
+{
+ addWidget(m_typeHiearchyWidgetInstance);
+
+ connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)),
+ this, SLOT(editorChanged(Core::IEditor*)));
+}
+
+CppTypeHierarchyStackedWidget::~CppTypeHierarchyStackedWidget()
+{
+ delete m_typeHiearchyWidgetInstance;
+}
+
+void CppTypeHierarchyStackedWidget::editorChanged(Core::IEditor *editor)
+{
+ CppTypeHierarchyWidget *replacement = new CppTypeHierarchyWidget(editor);
+ removeWidget(m_typeHiearchyWidgetInstance);
+ m_typeHiearchyWidgetInstance->deleteLater();
+ m_typeHiearchyWidgetInstance = replacement;
+ addWidget(m_typeHiearchyWidgetInstance);
+}
+
+// CppTypeHierarchyFactory
+CppTypeHierarchyFactory::CppTypeHierarchyFactory()
+{}
+
+CppTypeHierarchyFactory::~CppTypeHierarchyFactory()
+{}
+
+QString CppTypeHierarchyFactory::displayName() const
+{
+ return tr("Type Hierarchy");
+}
+
+QString CppTypeHierarchyFactory::id() const
+{
+ return QLatin1String(Constants::TYPE_HIERARCHY_ID);
+}
+
+QKeySequence CppTypeHierarchyFactory::activationSequence() const
+{
+ return QKeySequence();
+}
+
+Core::NavigationView CppTypeHierarchyFactory::createWidget()
+{
+ CppTypeHierarchyStackedWidget *w = new CppTypeHierarchyStackedWidget;
+ static_cast<CppTypeHierarchyWidget *>(w->currentWidget())->perform();
+ Core::NavigationView navigationView;
+ navigationView.widget = w;
+ return navigationView;
+}
diff --git a/src/plugins/cppeditor/cpptypehierarchy.h b/src/plugins/cppeditor/cpptypehierarchy.h
new file mode 100644
index 0000000000..8bc2c192a5
--- /dev/null
+++ b/src/plugins/cppeditor/cpptypehierarchy.h
@@ -0,0 +1,142 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#ifndef CPPTYPEHIERARCHY_H
+#define CPPTYPEHIERARCHY_H
+
+#include "cppelementevaluator.h"
+
+#include <coreplugin/inavigationwidgetfactory.h>
+
+#include <QtCore/QString>
+#include <QtGui/QWidget>
+#include <QtGui/QStackedWidget>
+#include <QtGui/QStandardItem>
+#include <QtGui/QStyledItemDelegate>
+
+QT_BEGIN_NAMESPACE
+class QStandardItemModel;
+class QModelIndex;
+class QPainter;
+QT_END_NAMESPACE
+
+namespace Core {
+class IEditor;
+}
+
+namespace Utils {
+class NavigationTreeView;
+}
+
+namespace CppEditor {
+namespace Internal {
+
+class CPPEditor;
+
+class CppTypeHierarchyItem : public QStandardItem
+{
+public:
+ CppTypeHierarchyItem(const CppClass &cppClass);
+ virtual ~CppTypeHierarchyItem();
+
+ virtual int type() const;
+
+ const CppClass &cppClass() const;
+
+private:
+ CppClass m_cppClass;
+};
+
+class CppTypeHierarchyDelegate : public QStyledItemDelegate
+{
+public:
+ CppTypeHierarchyDelegate(QObject *parent = 0);
+ virtual ~CppTypeHierarchyDelegate();
+
+ virtual void paint(QPainter *painter,
+ const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+ virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+};
+
+class CppTypeHierarchyWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ CppTypeHierarchyWidget(Core::IEditor *editor);
+ virtual ~CppTypeHierarchyWidget();
+
+public slots:
+ void perform();
+
+private slots:
+ void onItemClicked(const QModelIndex &index);
+
+private:
+ void buildModel(const CppClass &cppClass, QStandardItem *item);
+
+ CPPEditor *m_cppEditor;
+ Utils::NavigationTreeView *m_treeView;
+ QStandardItemModel *m_model;
+ CppTypeHierarchyDelegate *m_delegate;
+};
+
+// @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the
+// outline factory so that it works for different widgets that support the same editor.
+class CppTypeHierarchyStackedWidget : public QStackedWidget
+{
+ Q_OBJECT
+public:
+ CppTypeHierarchyStackedWidget(QWidget *parent = 0);
+ virtual ~CppTypeHierarchyStackedWidget();
+
+public slots:
+ void editorChanged(Core::IEditor* editor);
+
+private:
+ CppTypeHierarchyWidget *m_typeHiearchyWidgetInstance;
+};
+
+class CppTypeHierarchyFactory : public Core::INavigationWidgetFactory
+{
+ Q_OBJECT
+public:
+ CppTypeHierarchyFactory();
+ virtual ~CppTypeHierarchyFactory();
+
+ virtual QString displayName() const;
+ virtual QString id() const;
+ virtual QKeySequence activationSequence() const;
+ virtual Core::NavigationView createWidget();
+};
+
+} // namespace Internal
+} // namespace CppEditor
+
+#endif // CPPTYPEHIERARCHY_H
diff --git a/src/plugins/texteditor/basehoverhandler.cpp b/src/plugins/texteditor/basehoverhandler.cpp
index d993bb1246..21aaa63687 100644
--- a/src/plugins/texteditor/basehoverhandler.cpp
+++ b/src/plugins/texteditor/basehoverhandler.cpp
@@ -95,6 +95,10 @@ void BaseHoverHandler::showToolTip(TextEditor::ITextEditor *editor, const QPoint
void BaseHoverHandler::updateContextHelpId(TextEditor::ITextEditor *editor, int pos)
{
+ BaseTextEditor *baseEditor = baseTextEditor(editor);
+ if (!baseEditor)
+ return;
+
// If the tooltip is visible and there is a help match, this match is used to update
// the help id. Otherwise, let the identification process happen.
if (!ToolTip::instance()->isVisible() || m_matchingHelpCandidate == -1)
diff --git a/src/plugins/texteditor/basehoverhandler.h b/src/plugins/texteditor/basehoverhandler.h
index 587f257210..737b44660f 100644
--- a/src/plugins/texteditor/basehoverhandler.h
+++ b/src/plugins/texteditor/basehoverhandler.h
@@ -57,19 +57,6 @@ class TEXTEDITOR_EXPORT BaseHoverHandler : public QObject
public:
BaseHoverHandler(QObject *parent = 0);
-private slots:
- void editorOpened(Core::IEditor *editor);
-
-public slots:
- void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
- void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
-
-protected:
- void setToolTip(const QString &tooltip);
- const QString &toolTip() const;
- void appendToolTip(const QString &extension);
- void addF1ToToolTip();
-
struct HelpCandidate
{
enum Category {
@@ -94,6 +81,19 @@ protected:
Category m_category;
};
+private slots:
+ void editorOpened(Core::IEditor *editor);
+
+public slots:
+ void showToolTip(TextEditor::ITextEditor *editor, const QPoint &point, int pos);
+ void updateContextHelpId(TextEditor::ITextEditor *editor, int pos);
+
+protected:
+ void setToolTip(const QString &tooltip);
+ const QString &toolTip() const;
+ void appendToolTip(const QString &extension);
+ void addF1ToToolTip();
+
void addHelpCandidate(const HelpCandidate &helpCandidate);
void setHelpCandidate(const HelpCandidate &helpCandidate, int index);
const QList<HelpCandidate> &helpCandidates() const;
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index afa439ed9f..121ba012cd 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -463,6 +463,7 @@ protected:
static void countBrackets(QTextCursor cursor, int from, int end, QChar open, QChar close,
int *errors, int *stillopen);
+public:
struct Link
{
Link(const QString &fileName = QString(),
@@ -489,6 +490,7 @@ protected:
int column; // Target column
};
+protected:
/*!
Reimplement this function to enable code navigation.