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>
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"
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
)
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
);
62 QString file
= text
.mid( pos
, fileEnd
- pos
);
64 makeLink( KUrl(file
).fileName(), file
, NavigationAction( KUrl(file
), KTextEditor::Cursor() ) );
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
;
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
;
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
);
121 case NavigationAction::JumpToSource
:
123 KUrl doc
= action
.document
;
124 KTextEditor::Cursor cursor
= action
.cursor
;
126 doc
= KUrl(action
.decl
->url().str());
127 /* if(action.decl->internalContext())
128 cursor = action.decl->internalContext()->range().textRange().start() + KTextEditor::Cursor(0, 1);
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
) );
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 )
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 )
165 if( m_linkCount
> 0 ) {
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
) {
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());
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");
223 kind
= i18n("Namespace alias");
227 kind
= i18n("Function");
229 if( decl
->isForwardDeclaration() )
230 kind
= i18n("Forward Declaration");
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);