• Skip to content
  • Skip to link menu
KDE 4.4 API Reference
  • KDE API Reference
  • KDevelop Platform Libraries
  • Sitemap
  • Contact Us
 

language/duchain

abstractnavigationcontext.cpp

00001 /*
00002    Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    along with this library; see the file COPYING.LIB.  If not, write to
00015    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016    Boston, MA 02110-1301, USA.
00017 */
00018 
00019 #include "abstractnavigationcontext.h"
00020 
00021 #include <QtGui/QTextDocument>
00022 #include <klocale.h>
00023 
00024 #include "abstractdeclarationnavigationcontext.h"
00025 #include "usesnavigationcontext.h"
00026 #include "../../../interfaces/icore.h"
00027 #include "../../../interfaces/idocumentcontroller.h"
00028 #include "../functiondeclaration.h"
00029 #include "../functiondefinition.h"
00030 #include "../namespacealiasdeclaration.h"
00031 #include "../classmemberdeclaration.h"
00032 #include "../classfunctiondeclaration.h"
00033 #include "../forwarddeclaration.h"
00034 #include "../duchainutils.h"
00035 #include "../types/functiontype.h"
00036 #include "../types/enumeratortype.h"
00037 #include "../types/enumerationtype.h"
00038 #include "../types/referencetype.h"
00039 #include "../types/pointertype.h"
00040 #include <interfaces/idocumentationcontroller.h>
00041 
00042 
00043 namespace KDevelop {
00044   
00045 void AbstractNavigationContext::setTopContext(KDevelop::TopDUContextPointer context) {
00046   m_topContext = context;
00047 }
00048 
00049 KDevelop::TopDUContextPointer AbstractNavigationContext::topContext() const {
00050   return m_topContext;
00051 }
00052 
00053 
00054 AbstractNavigationContext::AbstractNavigationContext( KDevelop::TopDUContextPointer topContext, AbstractNavigationContext* previousContext)
00055   : m_selectedLink(0), m_shorten(false), m_linkCount(-1), m_currentPositionLine(0),
00056     m_previousContext(previousContext), m_topContext(topContext)
00057 {
00058 }
00059 
00060 void AbstractNavigationContext::addExternalHtml( const QString& text )
00061 {
00062   int lastPos = 0;
00063   int pos = 0;
00064   QString fileMark = "KDEV_FILE_LINK{";
00065   while( pos < text.length() && (pos = text.indexOf( fileMark, pos)) != -1 ) {
00066     modifyHtml() +=  text.mid(lastPos, pos-lastPos);
00067 
00068     pos += fileMark.length();
00069 
00070     if( pos != text.length() ) {
00071       int fileEnd = text.indexOf('}', pos);
00072       if( fileEnd != -1 ) {
00073         QString file = text.mid( pos, fileEnd - pos );
00074         pos = fileEnd + 1;
00075         makeLink( KUrl(file).fileName(), file, NavigationAction( KUrl(file), KTextEditor::Cursor() ) );
00076       }
00077     }
00078 
00079     lastPos = pos;
00080   }
00081 
00082   modifyHtml() +=  text.mid(lastPos, text.length()-lastPos);
00083 }
00084 
00085 void AbstractNavigationContext::makeLink( const QString& name, DeclarationPointer declaration, NavigationAction::Type actionType )
00086 {
00087   NavigationAction action( declaration, actionType );
00088   QString targetId = QString::number((quint64)declaration.data() * actionType);
00089   makeLink(name, targetId, action);
00090 }
00091 
00092 void AbstractNavigationContext::makeLink( const QString& name, QString targetId, const NavigationAction& action)
00093 {
00094   if(m_shorten) {
00095     //Do not create links in shortened mode, it's only for viewing
00096     modifyHtml() += typeHighlight(Qt::escape(name));
00097     return;
00098   }
00099   
00100   m_links[ targetId ] = action;
00101   m_intLinks[ m_linkCount ] = action;
00102   m_linkLines[ m_linkCount ] = m_currentLine;
00103   if(m_currentPositionLine == m_currentLine) {
00104     m_currentPositionLine = -1;
00105     m_selectedLink = m_linkCount;
00106   }
00107   
00108   QString str = Qt::escape(name);
00109   if( m_linkCount == m_selectedLink )
00110     str = "<font style=\"background-color:#f1f1f1;\" color=\"#880088\">" + str + "</font>";
00111 
00112   modifyHtml() +=  "<a href=\"" + targetId + "\"" + ((m_linkCount == m_selectedLink && m_currentPositionLine == -1) ? QString(" name = \"currentPosition\"") : QString()) + ">" + str + "</a>";
00113 
00114   if( m_selectedLink == m_linkCount )
00115     m_selectedLinkAction = action;
00116 
00117   ++m_linkCount;
00118 }
00119 
00120 void AbstractNavigationContext::clear() {
00121     m_linkCount = 0;
00122     m_currentLine = 0;
00123     m_currentText.clear();
00124     m_links.clear();
00125     m_intLinks.clear();
00126     m_linkLines.clear();
00127 }
00128 
00129 
00130 NavigationContextPointer AbstractNavigationContext::executeLink (QString link)
00131 {
00132   if(!m_links.contains(link))
00133     return NavigationContextPointer(this);
00134 
00135   return execute(m_links[link]);
00136 }
00137 
00138 NavigationContextPointer AbstractNavigationContext::executeKeyAction(QString key) {
00139   Q_UNUSED(key);
00140   return NavigationContextPointer(this);
00141 }
00142 
00143 NavigationContextPointer AbstractNavigationContext::execute(NavigationAction& action)
00144 {
00145   if(action.targetContext)
00146     return NavigationContextPointer(action.targetContext);
00147 
00148   if(action.type == NavigationAction::ExecuteKey)
00149     return executeKeyAction(action.key);
00150 
00151 
00152   if( !action.decl && (action.type != NavigationAction::JumpToSource || action.document.isEmpty()) ) {
00153       kDebug() << "Navigation-action has invalid declaration" << endl;
00154       return NavigationContextPointer(this);
00155   }
00156   qRegisterMetaType<KUrl>("KUrl");
00157   qRegisterMetaType<KTextEditor::Cursor>("KTextEditor::Cursor");
00158 
00159   switch( action.type ) {
00160     case NavigationAction::None:
00161       kDebug() << "Tried to execute an invalid action in navigation-widget" << endl;
00162       break;
00163     case NavigationAction::NavigateDeclaration:
00164     {
00165       AbstractDeclarationNavigationContext* ctx = dynamic_cast<AbstractDeclarationNavigationContext*>(m_previousContext);
00166       if( ctx && ctx->declaration() == action.decl )
00167         return NavigationContextPointer( m_previousContext );
00168       return AbstractNavigationContext::registerChild(action.decl);
00169     } break;
00170     case NavigationAction::NavigateUses:
00171       return registerChild(new UsesNavigationContext(action.decl.data(), this));
00172     case NavigationAction::JumpToSource:
00173       {
00174         KUrl doc = action.document;
00175         KTextEditor::Cursor cursor = action.cursor;
00176         {
00177           DUChainReadLocker lock(DUChain::lock());
00178           if(action.decl) {
00179             if(doc.isEmpty()) {
00180               doc = action.decl->url().toUrl();
00181     /*          if(action.decl->internalContext())
00182                 cursor = action.decl->internalContext()->range().textRange().start() + KTextEditor::Cursor(0, 1);
00183               else*/
00184                 cursor = action.decl->range().textRange().start();
00185             }
00186 
00187             action.decl->activateSpecialization();
00188           }
00189         }
00190 
00191         //This is used to execute the slot delayed in the event-loop, so crashes are avoided
00192         QMetaObject::invokeMethod( ICore::self()->documentController(), "openDocument", Qt::QueuedConnection, Q_ARG(KUrl, doc), Q_ARG(KTextEditor::Cursor, cursor) );
00193         break;
00194       }
00195     case NavigationAction::ShowDocumentation: {
00196         KSharedPtr<IDocumentation> doc=ICore::self()->documentationController()->documentationForDeclaration(action.decl.data());
00197         ICore::self()->documentationController()->showDocumentation(doc);
00198       }
00199       break;
00200   }
00201 
00202   return NavigationContextPointer( this );
00203 }
00204 
00205 void AbstractNavigationContext::setPreviousContext(KDevelop::AbstractNavigationContext* previous) {
00206   m_previousContext = previous;
00207 }
00208 
00209 NavigationContextPointer AbstractNavigationContext::registerChild( AbstractNavigationContext* context ) {
00210   m_children << NavigationContextPointer(context);
00211   return m_children.last();
00212 }
00213 
00214 NavigationContextPointer AbstractNavigationContext::registerChild(DeclarationPointer declaration) {
00215   //We create a navigation-widget here, and steal its context.. evil ;)
00216   QWidget* navigationWidget = declaration->context()->createNavigationWidget(declaration.data());
00217   NavigationContextPointer ret;
00218   AbstractNavigationWidget* abstractNavigationWidget = dynamic_cast<AbstractNavigationWidget*>(navigationWidget);
00219   if(abstractNavigationWidget)
00220     ret = abstractNavigationWidget->context();
00221   delete navigationWidget;
00222   ret->setPreviousContext(this);
00223   m_children << ret;
00224   return ret;
00225 }
00226 
00227 const int lineJump = 3;
00228 
00229 void AbstractNavigationContext::down() {
00230   //Make sure link-count is valid
00231   if( m_linkCount == -1 )
00232     html();
00233 
00234   int fromLine = m_currentPositionLine;
00235 
00236   if(m_selectedLink >= 0 && m_selectedLink < m_linkCount) {
00237 
00238     if(fromLine == -1)
00239       fromLine = m_linkLines[m_selectedLink];
00240 
00241     for(int newSelectedLink = m_selectedLink+1; newSelectedLink < m_linkCount; ++newSelectedLink) {
00242       if(m_linkLines[newSelectedLink] > fromLine && m_linkLines[newSelectedLink] - fromLine <= lineJump) {
00243         m_selectedLink = newSelectedLink;
00244         m_currentPositionLine = -1;
00245         return;
00246       }
00247     }
00248   }
00249   if(fromLine == -1)
00250     fromLine = 0;
00251 
00252   m_currentPositionLine = fromLine + lineJump;
00253 
00254   if(m_currentPositionLine > m_currentLine)
00255     m_currentPositionLine = m_currentLine;
00256 }
00257 
00258 void AbstractNavigationContext::up() {
00259   //Make sure link-count is valid
00260   if( m_linkCount == -1 )
00261     html();
00262 
00263   int fromLine = m_currentPositionLine;
00264 
00265   if(m_selectedLink >= 0 && m_selectedLink < m_linkCount) {
00266 
00267     if(fromLine == -1)
00268       fromLine = m_linkLines[m_selectedLink];
00269 
00270     for(int newSelectedLink = m_selectedLink-1; newSelectedLink >= 0; --newSelectedLink) {
00271       if(m_linkLines[newSelectedLink] < fromLine && fromLine - m_linkLines[newSelectedLink] <= lineJump) {
00272         m_selectedLink = newSelectedLink;
00273         m_currentPositionLine = -1;
00274         return;
00275       }
00276     }
00277   }
00278 
00279   if(fromLine == -1)
00280     fromLine = m_currentLine;
00281 
00282   m_currentPositionLine = fromLine - lineJump;
00283   if(m_currentPositionLine < 0)
00284     m_currentPositionLine = 0;
00285 }
00286 
00287 void AbstractNavigationContext::nextLink()
00288 {
00289   //Make sure link-count is valid
00290   if( m_linkCount == -1 )
00291     html();
00292 
00293   m_currentPositionLine = -1;
00294 
00295   if( m_linkCount > 0 )
00296     m_selectedLink = (m_selectedLink+1) % m_linkCount;
00297 }
00298 
00299 void AbstractNavigationContext::previousLink()
00300 {
00301   //Make sure link-count is valid
00302   if( m_linkCount == -1 )
00303     html();
00304 
00305   m_currentPositionLine = -1;
00306 
00307   if( m_linkCount > 0 ) {
00308     --m_selectedLink;
00309     if( m_selectedLink <  0 )
00310       m_selectedLink += m_linkCount;
00311   }
00312 
00313   Q_ASSERT(m_selectedLink >= 0);
00314 }
00315 
00316 void AbstractNavigationContext::setPrefixSuffix( const QString& prefix, const QString& suffix ) {
00317   m_prefix = prefix;
00318   m_suffix = suffix;
00319 }
00320 
00321 NavigationContextPointer AbstractNavigationContext::back() {
00322   if(m_previousContext)
00323     return NavigationContextPointer(m_previousContext);
00324   else
00325     return NavigationContextPointer(this);
00326 }
00327 
00328 NavigationContextPointer AbstractNavigationContext::accept() {
00329   if( m_selectedLink >= 0 &&  m_selectedLink < m_linkCount )
00330   {
00331     NavigationAction action = m_intLinks[m_selectedLink];
00332     return execute(action);
00333   }
00334   return NavigationContextPointer(this);
00335 }
00336 
00337 NavigationContextPointer AbstractNavigationContext::accept(IndexedDeclaration decl) {
00338   if(decl.data()) {
00339     NavigationAction action(DeclarationPointer(decl.data()), NavigationAction::NavigateDeclaration);
00340     return execute(action);
00341   }else{
00342     return NavigationContextPointer(this);
00343   }
00344 }
00345 
00346 NavigationContextPointer AbstractNavigationContext::acceptLink(const QString& link) {
00347   if( !m_links.contains(link) ) {
00348     kDebug() << "Executed unregistered link " << link << endl;
00349     return NavigationContextPointer(this);
00350   }
00351   
00352   return execute(m_links[link]);
00353 }
00354 
00355 
00356 NavigationAction AbstractNavigationContext::currentAction() const {
00357   return m_selectedLinkAction;
00358 }
00359 
00360 
00361 QString AbstractNavigationContext::declarationKind(DeclarationPointer decl)
00362 {
00363   const AbstractFunctionDeclaration* function = dynamic_cast<const AbstractFunctionDeclaration*>(decl.data());
00364 
00365   QString kind;
00366 
00367   if( decl->isTypeAlias() )
00368     kind = i18n("Typedef");
00369   else if( decl->kind() == Declaration::Type ) {
00370     if( decl->type<StructureType>() )
00371       kind = i18n("Class");
00372   }
00373 
00374   if( decl->kind() == Declaration::Instance )
00375     kind = i18n("Variable");
00376 
00377   if( NamespaceAliasDeclaration* alias = dynamic_cast<NamespaceAliasDeclaration*>(decl.data()) ) {
00378     if( alias->identifier().isEmpty() )
00379       kind = i18n("Namespace import");
00380     else
00381       kind = i18n("Namespace alias");
00382   }
00383 
00384   if(function)
00385     kind = i18n("Function");
00386 
00387   if( decl->isForwardDeclaration() )
00388     kind = i18n("Forward Declaration");
00389 
00390   return kind;
00391 }
00392 
00393 QString AbstractNavigationContext::html(bool shorten) {
00394   m_shorten = shorten;
00395   return QString();
00396 }
00397 
00398 bool AbstractNavigationContext::alreadyComputed() const {
00399   return !m_currentText.isEmpty();
00400 }
00401 
00402 bool AbstractNavigationContext::isWidgetMaximized() const
00403 {
00404   return true;
00405 }
00406 
00407 QWidget* AbstractNavigationContext::widget() const {
00408   return 0;
00409 }
00410 
00412 static QStringList splitAndKeep(QString str, QRegExp regExp) {
00413   QStringList ret;
00414   int place = regExp.indexIn(str);
00415   while(place != -1) {
00416     ret << str.left(place + regExp.matchedLength());
00417     str = str.mid(place + regExp.matchedLength());
00418     place = regExp.indexIn(str);
00419   }
00420   ret << str;
00421   return ret;
00422 }
00423 
00424 void AbstractNavigationContext::addHtml(QString html) {
00425   QRegExp newLineRegExp("<br>|<br */>");
00426   foreach(QString line, splitAndKeep(html, newLineRegExp)) {
00427     m_currentText +=  line;
00428     if(line.indexOf(newLineRegExp) != -1) {
00429       ++m_currentLine;
00430       if(m_currentLine == m_currentPositionLine) {
00431         m_currentText += "<font color=\"#880088\"> <a name = \"currentPosition\" >" + Qt::escape("<->") + "</a> </font>";
00432       }
00433     }
00434   }
00435 }
00436 
00437 QString AbstractNavigationContext::currentHtml() const {
00438   return m_currentText;
00439 }
00440 
00441 
00442 const Colorizer AbstractNavigationContext::typeHighlight("006000");
00443 const Colorizer AbstractNavigationContext::errorHighlight("990000");
00444 const Colorizer AbstractNavigationContext::labelHighlight("000035");
00445 const Colorizer AbstractNavigationContext::codeHighlight("005000");
00446 const Colorizer AbstractNavigationContext::propertyHighlight("009900");
00447 const Colorizer AbstractNavigationContext::navigationHighlight("000099");
00448 const Colorizer AbstractNavigationContext::importantHighlight("000000", true, true);
00449 const Colorizer AbstractNavigationContext::commentHighlight("000000", false, true);
00450 const Colorizer AbstractNavigationContext::nameHighlight("000000", true, false);
00451 
00452 }

language/duchain

Skip menu "language/duchain"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDevelop Platform Libraries

Skip menu "KDevelop Platform Libraries"
  • interfaces
  • language
  •   codegen
  •   duchain
  •   editor
  • outputview
  • project
  • shell
  • sublime
  • util
  • vcs
Generated for KDevelop Platform Libraries by doxygen 1.5.9-20090814
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal