KDevelop API Documentation

navigator.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2004 by Alexander Dymo                                  *
00003  *   adymo@mksat.net                                                       *
00004  *   Portions Copyright (C) 2002-2003 by Roberto Raggi                     *
00005  *   roberto@kdevelop.org                                                  *
00006  *                                                                         *
00007  *   This program is free software; you can redistribute it and/or modify  *
00008  *   it under the terms of the GNU General Public License as published by  *
00009  *   the Free Software Foundation; either version 2 of the License, or     *
00010  *   (at your option) any later version.                                   *
00011  *                                                                         *
00012  *   This program is distributed in the hope that it will be useful,       *
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00015  *   GNU General Public License for more details.                          *
00016  *                                                                         *
00017  *   You should have received a copy of the GNU General Public License     *
00018  *   along with this program; if not, write to the                         *
00019  *   Free Software Foundation, Inc.,                                       *
00020  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00021  ***************************************************************************/
00022 #include "navigator.h"
00023 
00024 #include <qtimer.h>
00025 
00026 #include <kconfig.h>
00027 #include <kdebug.h>
00028 #include <kiconloader.h>
00029 #include <kapplication.h>
00030 #include <ktexteditor/viewcursorinterface.h>
00031 
00032 #include <kcomboview.h>
00033 #include <klistviewaction.h>
00034 #include <kdevpartcontroller.h>
00035 #include <kdevlanguagesupport.h>
00036 #include <codemodel_utils.h>
00037 
00038 #include "classviewpart.h"
00039 
00040 
00041 struct NavOp
00042 {
00043    NavOp(Navigator *navigator, const QString &fullName)
00044        :m_navigator(navigator), m_fullName(fullName) {}
00045 
00046    bool operator() ( const FunctionDefinitionDom& def ) const
00047    {
00048        return (m_navigator->fullFunctionDefinitionName(def) == m_fullName);
00049    }
00050    bool operator() ( const FunctionDom& def ) const
00051    {
00052        return (m_navigator->fullFunctionDeclarationName(def) == m_fullName);
00053    }
00054 
00055 private:
00056     Navigator *m_navigator;
00057     QString m_fullName;
00058 };
00059 
00060 
00061 
00062 class FunctionNavItem: public QListViewItem {
00063 public:
00064     enum Type { Declaration, Definition };
00065     
00066     FunctionNavItem(ClassViewPart *part, QListView *parent, QString name, Type type)
00067         :QListViewItem(parent, name), m_part(part), m_type(type) {}
00068     FunctionNavItem(ClassViewPart *part, QListViewItem *parent, QString name, Type type)
00069         :QListViewItem(parent, name), m_part(part), m_type(type) {}
00070     ~FunctionNavItem() {}
00071     
00072     virtual void setup()
00073     {
00074         QListViewItem::setup();
00075         setPixmap( 0, UserIcon("CVpublic_meth", KIcon::DefaultState, m_part->instance()) );
00076     }
00077     Type type() { return m_type; }
00078     
00079 private:
00080     ClassViewPart *m_part;
00081     Type m_type;
00082 };
00083 
00084 
00085 Navigator::Navigator(ClassViewPart *parent, const char *name)
00086  : QObject(parent, name), m_part(parent)
00087 {
00088     m_state = GoToDefinitions;
00089     m_navNoDefinition = true;
00090 
00091     m_syncTimer = new QTimer(this);
00092     connect(m_syncTimer, SIGNAL(timeout()), this, SLOT(syncFunctionNav()));
00093 }
00094 
00095 Navigator::~Navigator()
00096 {
00097 }
00098 
00099 void Navigator::selectFunctionNav(QListViewItem *item)
00100 {
00101     FunctionNavItem *nav = dynamic_cast<FunctionNavItem*>(item);
00102     if (!nav)
00103         return;
00104 
00105     FileDom file = m_part->codeModel()->fileByName(m_part->m_activeFileName);
00106     if (!file)
00107         return;
00108         
00109     switch (nav->type())
00110     {
00111         case FunctionNavItem::Definition: //jump to definition
00112         {
00113             FileList files;
00114             files.append(file);
00115             FunctionDefinitionList deflist;
00116             CodeModelUtils::findFunctionDefinitions(NavOp(this, nav->text(0)), files, deflist);
00117             if (deflist.count() < 1)
00118                 return;
00119             
00120             FunctionDefinitionDom fun = deflist.first();
00121             if (!fun)
00122                 return;
00123             int startLine = 0, startColumn = 0;
00124             fun->getStartPosition(&startLine, &startColumn);
00125             m_part->partController()->editDocument(KURL(fun->fileName()), startLine);
00126             break;
00127         }
00128         case FunctionNavItem::Declaration: //jump to declaration
00129         {
00130             FileList files;
00131             files.append(file);
00132             FunctionList declist;
00133             CodeModelUtils::findFunctionDeclarations(NavOp(this, nav->text(0)), files, declist);
00134             if (declist.count() < 1)
00135                 return;
00136             
00137             FunctionDom fun = declist.first();
00138             if (!fun)
00139                 return;
00140             int startLine = 0, startColumn = 0;
00141             fun->getStartPosition(&startLine, &startColumn);
00142             m_part->partController()->editDocument(KURL(fun->fileName()), startLine);
00143             break;
00144         }
00145     }
00146 }
00147 
00148 void Navigator::functionNavUnFocused()
00149 {
00150     /*if (m_navNoDefinition)
00151         m_part->m_functionsnav->view()->setCurrentText(NAV_NODEFINITION);
00152     else*/
00153     if (m_part->m_functionsnav->view()->currentItem())
00154         m_part->m_functionsnav->view()->setCurrentText(m_part->m_functionsnav->view()->currentItem()->text(0));
00155     else
00156         m_part->m_functionsnav->view()->setCurrentText(NAV_NODEFINITION);
00157 }
00158 
00159 void Navigator::functionNavFocused()
00160 {
00161     m_navNoDefinition = (m_part->m_functionsnav->view()->currentText() == NAV_NODEFINITION);
00162     m_part->m_functionsnav->view()->setCurrentText("");
00163 }
00164 
00165 void Navigator::slotCursorPositionChanged()
00166 {
00167     //FIXME: we assume that background parser delay is set globally in kdeveloprc file
00168     //for all available language supports
00169     //this is reasonable assumption because problem reporter should be the same for all languages
00170     KConfig* config = kapp->config();
00171     config->setGroup( "General Options" );
00172     int m_delay = config->readNumEntry( "BgParserDelay", 250 );
00173     
00174     m_syncTimer->changeInterval(500 >= m_delay+100 ? 500 : m_delay+100 );
00175 }
00176 
00177 void Navigator::stopTimer( )
00178 {
00179     m_syncTimer->stop();
00180 }
00181 
00182 void Navigator::syncFunctionNavDelayed(int delay)
00183 {
00184     m_syncTimer->changeInterval(delay);
00185 }
00186 
00187 void Navigator::syncFunctionNav()
00188 {
00189     m_syncTimer->stop();
00190     
00191     if (FunctionDefinitionDom fun = currentFunctionDefinition())
00192     {
00193         if (functionNavDefs[fullFunctionDefinitionName(fun)])
00194         {
00195             m_part->m_functionsnav->view()->blockSignals(true);
00196             m_part->m_functionsnav->view()->setCurrentActiveItem(functionNavDefs[fullFunctionDefinitionName(fun)]);
00197             m_part->m_functionsnav->view()->blockSignals(false);
00198         }
00199     }
00200     else if (FunctionDom fun = currentFunctionDeclaration())
00201     {
00202         if (functionNavDecls[fullFunctionDeclarationName(fun)])
00203         {
00204             m_part->m_functionsnav->view()->blockSignals(true);
00205             m_part->m_functionsnav->view()->setCurrentActiveItem(functionNavDecls[fullFunctionDeclarationName(fun)]);
00206             m_part->m_functionsnav->view()->blockSignals(false);
00207         }
00208     }
00209     else
00210         m_part->m_functionsnav->view()->setCurrentText(NAV_NODEFINITION);
00211 }
00212 
00213 void Navigator::refreshNavBars(const QString &activeFileName, bool clear)
00214 {
00215     kdDebug() << "Navigator::refreshNavBars" << endl;
00216     if (clear)
00217     {
00218         m_part->m_functionsnav->view()->clear();
00219         functionNavDefs.clear();
00220         functionNavDecls.clear();
00221     }
00222     
00223     FileDom file = m_part->codeModel()->fileByName(activeFileName);
00224     if (!file)
00225         return;
00226 
00227     QStringList toLeave;
00228     
00229     FunctionList list1 = CodeModelUtils::allFunctions(file);
00230     for (FunctionList::const_iterator it = list1.begin(); it != list1.end(); ++it)
00231     {
00232         QString fullName = fullFunctionDeclarationName(*it);
00233         
00234         if (clear || !functionNavDecls[fullName])
00235         {
00236             FunctionNavItem *item = new FunctionNavItem(m_part,
00237                 m_part->m_functionsnav->view()->listView(), fullName,
00238                 FunctionNavItem::Declaration);
00239             functionNavDecls[fullName] = item;
00240             m_part->m_functionsnav->view()->addItem(item);
00241         }
00242         toLeave << fullName;
00243     }
00244     kdDebug() << "leave list: " << toLeave << endl;
00245     
00246     //remove items not in toLeave list
00247     for (QMap<QString, QListViewItem*>::iterator it = functionNavDecls.begin();
00248         it != functionNavDecls.end(); ++it)
00249     {
00250         if (!toLeave.contains(it.key()))
00251         {
00252             if (it.data())
00253                 m_part->m_functionsnav->view()->removeItem(it.data());
00254             functionNavDecls.remove(it);
00255         }
00256     }
00257         
00258     toLeave.clear();
00259     FunctionDefinitionList list = CodeModelUtils::allFunctionDefinitionsDetailed(file).functionList;
00260     for (FunctionDefinitionList::const_iterator it = list.begin(); it != list.end(); ++it)
00261     {
00262         QString fullName = fullFunctionDefinitionName(*it);
00263         
00264         if (clear || !functionNavDefs[fullName])
00265         {
00266             FunctionNavItem *item = new FunctionNavItem(m_part,
00267                 m_part->m_functionsnav->view()->listView(), fullName, FunctionNavItem::Definition);
00268             functionNavDefs[fullName] = item;
00269             m_part->m_functionsnav->view()->addItem(item);
00270         }
00271             
00272         //remove unnecessary items with function declarations for which a definition item was created
00273         if (functionNavDecls[fullName])
00274         {
00275             m_part->m_functionsnav->view()->removeItem(functionNavDecls[fullName]);
00276             functionNavDecls.remove(fullName);
00277         }
00278         
00279         toLeave << fullName;
00280     }
00281         
00282     kdDebug() << "leave list: " << toLeave << endl;
00283     //remove items not in toLeave list
00284     for (QMap<QString, QListViewItem*>::iterator it = functionNavDefs.begin();
00285         it != functionNavDefs.end(); ++it)
00286     {
00287         if (!toLeave.contains(it.key()))
00288         {
00289             if (it.data())
00290                 m_part->m_functionsnav->view()->removeItem(it.data());
00291             functionNavDefs.remove(it);
00292         }
00293     }
00294 }
00295 
00296 void Navigator::refresh()
00297 {
00298     refreshNavBars(m_part->m_activeFileName, true);
00299 }
00300 
00301 void Navigator::addFile(const QString & file)
00302 {
00303     kdDebug() << "Navigator::addFile" << endl;
00304     if (file == m_part->m_activeFileName)
00305     {
00306         kdDebug() << "Navigator::addFile, processing active file" << endl;
00307         refreshNavBars(m_part->m_activeFileName, false);
00308     }
00309 }
00310 
00311 
00312 
00313 FunctionDefinitionDom Navigator::currentFunctionDefinition()
00314 {
00315     if (!m_part->m_activeViewCursor)
00316         return FunctionDefinitionDom();
00317 
00318     unsigned int line, column;
00319     m_part->m_activeViewCursor->cursorPositionReal(&line, &column);
00320     return functionDefinitionAt(line, column);
00321 }
00322 
00323 FunctionDefinitionDom Navigator::functionDefinitionAt(int line, int column)
00324 {
00325     if (!m_part->codeModel()->hasFile(m_part->m_activeFileName))
00326         return FunctionDefinitionDom();
00327 
00328     FileDom file = m_part->codeModel()->fileByName(m_part->m_activeFileName);
00329     return functionDefinitionAt(model_cast<NamespaceDom>(file), line, column);
00330 }
00331 
00332 FunctionDefinitionDom Navigator::functionDefinitionAt(NamespaceDom ns, int line, int column)
00333 {
00334     NamespaceList namespaceList = ns->namespaceList();
00335     for (NamespaceList::iterator it=namespaceList.begin(); it!=namespaceList.end(); ++it)
00336     {
00337         if (FunctionDefinitionDom def = functionDefinitionAt(*it, line, column))
00338             return def;
00339     }
00340 
00341     ClassList classList = ns->classList();
00342     for (ClassList::iterator it=classList.begin(); it!=classList.end(); ++it)
00343     {
00344         if (FunctionDefinitionDom def = functionDefinitionAt(*it, line, column))
00345             return def;
00346     }
00347 
00348     FunctionDefinitionList functionDefinitionList = ns->functionDefinitionList();
00349     for (FunctionDefinitionList::iterator it=functionDefinitionList.begin();
00350         it!=functionDefinitionList.end(); ++it )
00351     {
00352         if (FunctionDefinitionDom def = functionDefinitionAt(*it, line, column))
00353             return def;
00354     }
00355 
00356     return FunctionDefinitionDom();
00357 }
00358 
00359 FunctionDefinitionDom Navigator::functionDefinitionAt(ClassDom klass, int line, int column)
00360 {
00361     ClassList classList = klass->classList();
00362     for (ClassList::iterator it=classList.begin(); it!=classList.end(); ++it)
00363     {
00364         if (FunctionDefinitionDom def = functionDefinitionAt(*it, line, column))
00365             return def;
00366     }
00367 
00368     FunctionDefinitionList functionDefinitionList = klass->functionDefinitionList();
00369     for (FunctionDefinitionList::Iterator it=functionDefinitionList.begin();
00370         it!=functionDefinitionList.end(); ++it)
00371     {
00372         if (FunctionDefinitionDom def = functionDefinitionAt(*it, line, column))
00373             return def;
00374     }
00375 
00376     return FunctionDefinitionDom();
00377 }
00378 
00379 FunctionDefinitionDom Navigator::functionDefinitionAt(FunctionDefinitionDom fun, int line, int column)
00380 {
00381     int startLine, startColumn;
00382     int endLine, endColumn;
00383 
00384     fun->getStartPosition(&startLine, &startColumn);
00385     fun->getEndPosition(&endLine, &endColumn);
00386 
00387     if (!(line >= startLine && line <= endLine))
00388         return FunctionDefinitionDom();
00389 
00390 /*    if (line == startLine && column < startColumn)
00391         return FunctionDefinitionDom();
00392 
00393     if (line == endLine && column > endColumn)
00394         return FunctionDefinitionDom();*/
00395 
00396     return fun;
00397 }
00398 
00399 
00400 FunctionDom Navigator::currentFunctionDeclaration()
00401 {
00402     if (!m_part->m_activeViewCursor)
00403         return FunctionDom();
00404 
00405     unsigned int line, column;
00406     m_part->m_activeViewCursor->cursorPositionReal(&line, &column);
00407     return functionDeclarationAt(line, column);
00408 }
00409 
00410 FunctionDom Navigator::functionDeclarationAt(int line, int column)
00411 {
00412     if (!m_part->codeModel()->hasFile(m_part->m_activeFileName))
00413         return FunctionDom();
00414 
00415     FileDom file = m_part->codeModel()->fileByName(m_part->m_activeFileName);
00416     return functionDeclarationAt(model_cast<NamespaceDom>(file), line, column);
00417 }
00418 
00419 FunctionDom Navigator::functionDeclarationAt(NamespaceDom ns, int line, int column)
00420 {
00421     NamespaceList namespaceList = ns->namespaceList();
00422     for (NamespaceList::iterator it=namespaceList.begin(); it!=namespaceList.end(); ++it)
00423     {
00424         if (FunctionDom def = functionDeclarationAt(*it, line, column))
00425             return def;
00426     }
00427 
00428     ClassList classList = ns->classList();
00429     for (ClassList::iterator it=classList.begin(); it!=classList.end(); ++it)
00430     {
00431         if (FunctionDom def = functionDeclarationAt(*it, line, column))
00432             return def;
00433     }
00434 
00435     FunctionList functionList = ns->functionList();
00436     for (FunctionList::iterator it=functionList.begin();
00437         it!=functionList.end(); ++it )
00438     {
00439         if (FunctionDom def = functionDeclarationAt(*it, line, column))
00440             return def;
00441     }
00442 
00443     return FunctionDom();
00444 }
00445 
00446 FunctionDom Navigator::functionDeclarationAt(ClassDom klass, int line, int column)
00447 {
00448     ClassList classList = klass->classList();
00449     for (ClassList::iterator it=classList.begin(); it!=classList.end(); ++it)
00450     {
00451         if (FunctionDom def = functionDeclarationAt(*it, line, column))
00452             return def;
00453     }
00454 
00455     FunctionList functionList = klass->functionList();
00456     for (FunctionList::Iterator it=functionList.begin();
00457         it!=functionList.end(); ++it)
00458     {
00459         if (FunctionDom def = functionDeclarationAt(*it, line, column))
00460             return def;
00461     }
00462 
00463     return FunctionDom();
00464 }
00465 
00466 FunctionDom Navigator::functionDeclarationAt(FunctionDom fun, int line, int column)
00467 {
00468     int startLine, startColumn;
00469     int endLine, endColumn;
00470 
00471     fun->getStartPosition(&startLine, &startColumn);
00472     fun->getEndPosition(&endLine, &endColumn);
00473 
00474     if (!(line >= startLine && line <= endLine))
00475         return FunctionDom();
00476 
00477 /*    if (line == startLine && column < startColumn)
00478         return FunctionDom();
00479 
00480     if (line == endLine && column > endColumn)
00481         return FunctionDom();*/
00482 
00483     return fun;
00484 }
00485 
00486 
00487 QString Navigator::fullFunctionDefinitionName(FunctionDefinitionDom fun)
00488 {        
00489     QStringList scope = fun->scope();
00490     QString funName = scope.join(".");
00491     if (!funName.isEmpty())
00492         funName += ".";
00493     funName += m_part->languageSupport()->formatModelItem(fun, true);   
00494     funName = m_part->languageSupport()->formatClassName(funName);
00495     
00496     return funName;
00497 }
00498 
00499 QString Navigator::fullFunctionDeclarationName(FunctionDom fun)
00500 {
00501     QStringList scope = fun->scope();
00502     QString funName = scope.join(".");
00503     if (!funName.isEmpty())
00504         funName += ".";
00505     funName += m_part->languageSupport()->formatModelItem(fun, true);   
00506     funName = m_part->languageSupport()->formatClassName(funName);
00507     
00508     return funName;
00509 }
00510 
00511 #include "navigator.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:38 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003