KDevelop API Documentation

parts/sourcenav/sourcenav_part.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2000-2001 by Harald Fernengel * 00003 * harry@kdevelop.org * 00004 * * 00005 * This program is free software; you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation; either version 2 of the License, or * 00008 * (at your option) any later version. * 00009 * * 00010 ***************************************************************************/ 00011 00012 00013 #include "sourcenav_part.h" 00014 00015 #include <kdebug.h> 00016 #include <ktexteditor/viewcursorinterface.h> 00017 #include <ktexteditor/document.h> 00018 #include <ktexteditor/editinterface.h> 00019 #include <kgenericfactory.h> 00020 #include <kaction.h> 00021 #include <kguiitem.h> 00022 #include <kpopupmenu.h> 00023 00024 #include "kdevcore.h" 00025 #include "kdevpartcontroller.h" 00026 00027 // maximum steps to remember 00028 static const int MAX_HISTORY = 50; 00029 // textchanges after which the QValueLists are cleaned 00030 static const int MAX_CLEANUP = 200; 00031 // maximum number of items to display in Popup 00032 static const int MAX_ITEMS = 20; 00033 00034 static int anchorID = 0; 00035 00036 int Anchor::nextID() 00037 { 00038 return anchorID++; 00039 } 00040 00041 typedef KGenericFactory<SourceNavPart> SourceNavFactory; 00042 K_EXPORT_COMPONENT_FACTORY( libkdevsourcenav, SourceNavFactory( "kdevsourcenav" ) ) 00043 00044 SourceNavPart::SourceNavPart(QObject *parent, const char *name, const QStringList& ) 00045 : KDevPlugin("SourceNav", "sourcenav", parent, name ? name : "SourceNavPart") 00046 { 00047 setInstance(SourceNavFactory::instance()); 00048 setXMLFile("kdevpart_sourcenav.rc"); 00049 00050 backPopupVisible = false; 00051 forwardPopupVisible = false; 00052 00053 connect( partController(), SIGNAL(partAdded(KParts::Part*)), this, SLOT(slotPartAdded(KParts::Part*)) ); 00054 00055 navForward = new KToolBarPopupAction( KGuiItem( i18n("Navigate Forward"), "1rightarrow", i18n( "ToolTip" ), i18n( "What's This" ) ), 00056 0, this, SLOT(slotNavForward()), actionCollection(), "navForward" ); 00057 00058 navBack = new KToolBarPopupAction( KGuiItem( i18n("Navigate Backwards"), "1leftarrow", i18n( "ToolTip" ), i18n( "What's This" ) ), 00059 0, this, SLOT(slotNavBack()), actionCollection(), "navBack" ); 00060 00061 connect( navForward->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(fillForwardPopup()) ); 00062 connect( navForward->popupMenu(), SIGNAL(activated(int)), this, SLOT(forwardPopupClicked(int)) ); 00063 connect( navBack->popupMenu(), SIGNAL(aboutToShow()), this, SLOT(fillBackPopup()) ); 00064 connect( navBack->popupMenu(), SIGNAL(activated(int)), this, SLOT(backPopupClicked(int)) ); 00065 00066 navForward->setEnabled( false ); 00067 navBack->setEnabled( false ); 00068 } 00069 00070 00071 SourceNavPart::~SourceNavPart() 00072 { 00073 } 00074 00075 void SourceNavPart::backPopupClicked( int id ) 00076 { 00077 navigate( id, navList, forwardList ); 00078 } 00079 00080 void SourceNavPart::forwardPopupClicked( int id ) 00081 { 00082 navigate( id, forwardList, navList ); 00083 } 00084 00085 void SourceNavPart::fillPopup( const AnchorList& list, QPopupMenu* pop ) 00086 { 00087 if ( !pop ) 00088 return; 00089 00090 QString item; 00091 int i = 0; 00092 pop->clear(); 00093 AnchorList::ConstIterator it = list.begin(); 00094 while ( it != list.end() && i < MAX_ITEMS ) { 00095 if ( (*it).url().isLocalFile() ) { 00096 item = (*it).url().fileName(); 00097 } else { 00098 item = (*it).url().prettyURL(); 00099 } 00100 item += ":" + QString::number( (*it).line() ); 00101 pop->insertItem( item, (*it).id() ); 00102 ++i; 00103 ++it; 00104 } 00105 } 00106 00107 void SourceNavPart::fillBackPopup() 00108 { 00109 fillPopup( navList, navBack->popupMenu() ); 00110 } 00111 00112 void SourceNavPart::fillForwardPopup() 00113 { 00114 fillPopup( forwardList, navForward->popupMenu() ); 00115 } 00116 00117 // called when a new document has been added 00118 void SourceNavPart::slotPartAdded( KParts::Part *part ) 00119 { 00120 if ( !part ) 00121 return; 00122 00123 KTextEditor::Document *doc = dynamic_cast<KTextEditor::Document*>(part); 00124 if ( !doc ) 00125 return; 00126 00127 KTextEditor::EditInterface *ed = dynamic_cast<KTextEditor::EditInterface*>(doc); 00128 if ( ed ) { 00129 connect( doc, SIGNAL(textChanged()), this, SLOT(slotTextChanged())); 00130 } 00131 00132 } 00133 00134 Anchor SourceNavPart::getCurrentPos() 00135 { 00136 uint line = 0; 00137 uint col = 0; 00138 00139 if ( !partController() ) 00140 return Anchor(); 00141 00142 KTextEditor::Document *doc = dynamic_cast<KTextEditor::Document*>(partController()->activePart()); 00143 QWidget *view = partController()->activeWidget(); 00144 if ( !doc || !view ) 00145 return Anchor(); 00146 00147 // hm, let's hope that this is the currently active view... 00148 KTextEditor::ViewCursorInterface *cur = dynamic_cast<KTextEditor::ViewCursorInterface*>(view); 00149 if ( cur ) { 00150 cur->cursorPosition( &line, &col ); 00151 } 00152 00153 return Anchor( doc->url(), line, col ); 00154 } 00155 00156 void SourceNavPart::gotoPos( const Anchor& ankh ) 00157 { 00158 if ( !partController() ) 00159 return; 00160 partController()->editDocument( ankh.url(), ankh.line() ); 00161 } 00162 00163 // returns true if pos1 is near to pos2 00164 bool SourceNavPart::isNearby( const Anchor& pos1, const Anchor& pos2 ) 00165 { 00166 // 10 is just a magic number, might need a bit tweaking ;) 00167 if ( pos1.isValid() && pos2.isValid() && pos1.url() == pos2.url() && QABS((int)pos1.line() - (int)pos2.line()) < 5 ) 00168 return true; 00169 return false; 00170 } 00171 00172 void SourceNavPart::slotTextChanged() 00173 { 00174 const Anchor cur = getCurrentPos(); 00175 const Anchor old = navList.isEmpty() ? Anchor() : navList.first(); 00176 00177 if ( !isNearby( cur, old ) ) { 00178 navList.push_front( cur ); 00179 } 00180 00181 if ( cur.id() % MAX_CLEANUP == 0 ) { 00182 cleanupList( navList ); 00183 cleanupList( forwardList ); 00184 } 00185 00186 enableActions(); 00187 } 00188 00189 void SourceNavPart::navigate( int id, AnchorList& list1, AnchorList& list2 ) 00190 { 00191 Anchor ankh; 00192 00193 AnchorList::Iterator it = list1.begin(); 00194 while ( it != list1.end() ) { 00195 ankh = (*it); 00196 list2.push_front( *it ); 00197 it = list1.remove( it ); 00198 00199 if ( ankh.id() == id ) { 00200 // found the right position 00201 it = list1.end(); 00202 } 00203 } 00204 00205 if ( ankh.isValid() ) { 00206 gotoPos( ankh ); 00207 } 00208 enableActions(); 00209 } 00210 00211 void SourceNavPart::navigate( AnchorList& list1, AnchorList& list2 ) 00212 { 00213 if ( list1.isEmpty() ) 00214 return; 00215 00216 const Anchor cur = getCurrentPos(); 00217 Anchor last = list1.first(); 00218 00219 list2.push_front( last ); 00220 list1.pop_front(); 00221 00222 if ( isNearby( cur, last ) ) { 00223 // we are currently at the position of the last change, so go to the one before 00224 if ( list1.isEmpty() ) { 00225 //nowhere to go... 00226 enableActions(); 00227 return; 00228 } 00229 last = list1.first(); 00230 list2.push_front( last ); 00231 list1.pop_front(); 00232 } 00233 00234 gotoPos( last ); 00235 enableActions(); 00236 } 00237 00238 void SourceNavPart::slotNavBack() 00239 { 00240 navigate( navList, forwardList ); 00241 } 00242 00243 void SourceNavPart::slotNavForward() 00244 { 00245 navigate( forwardList, navList ); 00246 } 00247 00248 void SourceNavPart::enableActions() 00249 { 00250 navForward->setEnabled( !forwardList.isEmpty() ); 00251 navBack->setEnabled( !navList.isEmpty() ); 00252 } 00253 00254 void SourceNavPart::cleanupList( AnchorList& list ) 00255 { 00256 AnchorList::Iterator it = list.at( MAX_HISTORY ); 00257 while ( it != list.end() ) { 00258 it = list.remove( it ); 00259 } 00260 } 00261 00262 #include "sourcenav_part.moc" 00263
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Oct 6 17:39:13 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003