Add AbstractDeclarationNavigationContext, and move the html-method from
[kdevelopdvcssupport.git] / language / duchain / navigation / abstractnavigationcontext.cpp
blobaaa778d6f9bee6005352d40d808ed85f55a1d82a
1 /*
2 Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
19 #include "abstractnavigationcontext.h"
21 #include <QtGui/QTextDocument>
22 #include <klocale.h>
24 #include "abstractdeclarationnavigationcontext.h"
25 #include "../../../interfaces/icore.h"
26 #include "../../../interfaces/idocumentcontroller.h"
27 #include "../functiondeclaration.h"
28 #include "../functiondefinition.h"
29 #include "../namespacealiasdeclaration.h"
30 #include "../classmemberdeclaration.h"
31 #include "../classfunctiondeclaration.h"
32 #include "../forwarddeclaration.h"
33 #include "../duchainutils.h"
34 #include "../types/functiontype.h"
35 #include "../types/enumeratortype.h"
36 #include "../types/enumerationtype.h"
37 #include "../types/referencetype.h"
38 #include "../types/pointertype.h"
41 namespace KDevelop {
43 AbstractNavigationContext::AbstractNavigationContext( KDevelop::TopDUContextPointer topContext, AbstractNavigationContext* previousContext)
44 : m_selectedLink(0), m_linkCount(-1),
45 m_previousContext(previousContext), m_topContext(topContext)
49 void AbstractNavigationContext::addExternalHtml( const QString& text )
51 int lastPos = 0;
52 int pos = 0;
53 QString fileMark = "KDEV_FILE_LINK{";
54 while( pos < text.length() && (pos = text.indexOf( fileMark, pos)) != -1 ) {
55 m_currentText += text.mid(lastPos, pos-lastPos);
57 pos += fileMark.length();
59 if( pos != text.length() ) {
60 int fileEnd = text.indexOf('}', pos);
61 if( fileEnd != -1 ) {
62 QString file = text.mid( pos, fileEnd - pos );
63 pos = fileEnd + 1;
64 makeLink( KUrl(file).fileName(), file, NavigationAction( KUrl(file), KTextEditor::Cursor() ) );
68 lastPos = pos;
71 m_currentText += text.mid(lastPos, text.length()-lastPos);
74 void AbstractNavigationContext::makeLink( const QString& name, DeclarationPointer declaration, NavigationAction::Type actionType )
76 NavigationAction action( declaration, actionType );
77 QString targetId = QString("%1").arg((quint64)declaration.data());
78 makeLink(name, targetId, action);
81 void AbstractNavigationContext::makeLink( const QString& name, QString targetId, const NavigationAction& action)
83 m_links[ targetId ] = action;
84 m_intLinks[ m_linkCount ] = action;
86 QString str = Qt::escape(name);
87 if( m_linkCount == m_selectedLink ) ///@todo Change background-color here instead of foreground-color
88 str = "<font color=\"#880088\">" + str + "</font>";
90 m_currentText += "<a href=\"" + targetId + "\"" + (m_linkCount == m_selectedLink ? QString(" name = \"selectedItem\"") : QString()) + ">" + str + "</a>";
92 if( m_selectedLink == m_linkCount )
93 m_selectedLinkAction = action;
95 ++m_linkCount;
98 NavigationContextPointer AbstractNavigationContext::execute(NavigationAction& action)
100 if(action.targetContext)
101 return NavigationContextPointer(action.targetContext);
103 if( !action.decl && (action.type != NavigationAction::JumpToSource || action.document.isEmpty()) ) {
104 kDebug(9007) << "Navigation-action has invalid declaration" << endl;
105 return NavigationContextPointer(this);
107 qRegisterMetaType<KUrl>("KUrl");
108 qRegisterMetaType<KTextEditor::Cursor>("KTextEditor::Cursor");
110 switch( action.type ) {
111 case NavigationAction::None:
112 kDebug(9007) << "Tried to execute an invalid action in navigation-widget" << endl;
113 break;
114 case NavigationAction::NavigateDeclaration:
116 AbstractDeclarationNavigationContext* ctx = dynamic_cast<AbstractDeclarationNavigationContext*>(m_previousContext);
117 if( ctx && ctx->declaration() == action.decl )
118 return NavigationContextPointer( m_previousContext );
119 return registerChild(action.decl);
120 } break;
121 case NavigationAction::JumpToSource:
123 KUrl doc = action.document;
124 KTextEditor::Cursor cursor = action.cursor;
125 if(doc.isEmpty()) {
126 doc = KUrl(action.decl->url().str());
127 /* if(action.decl->internalContext())
128 cursor = action.decl->internalContext()->range().textRange().start() + KTextEditor::Cursor(0, 1);
129 else*/
130 cursor = action.decl->range().textRange().start();
133 action.decl->activateSpecialization();
135 //This is used to execute the slot delayed in the event-loop, so crashes are avoided
136 QMetaObject::invokeMethod( ICore::self()->documentController(), "openDocument", Qt::QueuedConnection, Q_ARG(KUrl, doc), Q_ARG(KTextEditor::Cursor, cursor) );
137 break;
141 return NavigationContextPointer( this );
144 NavigationContextPointer AbstractNavigationContext::registerChild( AbstractNavigationContext* context ) {
145 m_children << NavigationContextPointer(context);
146 return m_children.last();
149 void AbstractNavigationContext::nextLink()
151 //Make sure link-count is valid
152 if( m_linkCount == -1 )
153 html();
155 if( m_linkCount > 0 )
156 m_selectedLink = (m_selectedLink+1) % m_linkCount;
159 void AbstractNavigationContext::previousLink()
161 //Make sure link-count is valid
162 if( m_linkCount == -1 )
163 html();
165 if( m_linkCount > 0 ) {
166 --m_selectedLink;
167 if( m_selectedLink < 0 )
168 m_selectedLink += m_linkCount;
171 Q_ASSERT(m_selectedLink >= 0);
174 void AbstractNavigationContext::setPrefixSuffix( const QString& prefix, const QString& suffix ) {
175 m_prefix = prefix;
176 m_suffix = suffix;
179 NavigationContextPointer AbstractNavigationContext::accept() {
180 if( m_selectedLink >= 0 && m_selectedLink < m_linkCount )
182 NavigationAction action = m_intLinks[m_selectedLink];
183 return execute(action);
185 return NavigationContextPointer(this);
188 NavigationContextPointer AbstractNavigationContext::acceptLink(const QString& link) {
189 if( !m_links.contains(link) ) {
190 kDebug(9007) << "Executed unregistered link " << link << endl;
191 return NavigationContextPointer(this);
194 return execute(m_links[link]);
198 NavigationAction AbstractNavigationContext::currentAction() const {
199 return m_selectedLinkAction;
203 QString AbstractNavigationContext::declarationKind(DeclarationPointer decl)
205 const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(decl.data());
207 QString kind;
209 if( decl->isTypeAlias() )
210 kind = i18n("Typedef");
211 else if( decl->kind() == Declaration::Type ) {
212 if( decl->type<StructureType>() )
213 kind = i18n("Class");
216 if( decl->kind() == Declaration::Instance )
217 kind = i18n("Variable");
219 if( NamespaceAliasDeclaration* alias = dynamic_cast<NamespaceAliasDeclaration*>(decl.data()) ) {
220 if( alias->identifier().isEmpty() )
221 kind = i18n("Namespace import");
222 else
223 kind = i18n("Namespace alias");
226 if(function)
227 kind = i18n("Function");
229 if( decl->isForwardDeclaration() )
230 kind = i18n("Forward Declaration");
232 return kind;
235 const Colorizer AbstractNavigationContext::errorHighlight("990000");
236 const Colorizer AbstractNavigationContext::labelHighlight("000035");
237 const Colorizer AbstractNavigationContext::codeHighlight("005000");
238 const Colorizer AbstractNavigationContext::propertyHighlight("009900");
239 const Colorizer AbstractNavigationContext::navigationHighlight("000099");
240 const Colorizer AbstractNavigationContext::importantHighlight("000000", true, true);
241 const Colorizer AbstractNavigationContext::commentHighlight("000000", false, true);
242 const Colorizer AbstractNavigationContext::nameHighlight("000000", true, false);