KDevelop API Documentation

parts/ctags/ctagspart.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2001 by Bernd Gehrmann * 00003 * bernd@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 #include "ctagspart.h" 00013 00014 #include <qapplication.h> 00015 #include <qfileinfo.h> 00016 #include <qpopupmenu.h> 00017 #include <klocale.h> 00018 #include <kdevgenericfactory.h> 00019 #include <kaction.h> 00020 #include <kdebug.h> 00021 #include <kmainwindow.h> 00022 #include <kmessagebox.h> 00023 #include <kprocess.h> 00024 #include <qregexp.h> 00025 #include <ktempfile.h> 00026 00027 #include "kdevcore.h" 00028 #include "kdevproject.h" 00029 #include "kdevmainwindow.h" 00030 #include "kdevpartcontroller.h" 00031 #include "ctagskinds.h" 00032 #include "ctagsdlg.h" 00033 00034 00035 typedef KDevGenericFactory<CTagsPart> CTagsFactory; 00036 static const KAboutData data("kdevctags", I18N_NOOP("CTags..."), "1.0"); 00037 K_EXPORT_COMPONENT_FACTORY( libkdevctags, CTagsFactory( &data ) ) 00038 00039 CTagsPart::CTagsPart( QObject *parent, const char *name, const QStringList & ) 00040 : KDevPlugin("CTags", "ctags", parent, name ? name : "CTagsPart") 00041 { 00042 setInstance(CTagsFactory::instance()); 00043 setXMLFile("kdevctags.rc"); 00044 00045 KAction *action; 00046 00047 action = new KAction( i18n("CTags..."), 0, 00048 this, SLOT(slotSearchTags()), 00049 actionCollection(), "tools_ctags" ); 00050 action->setToolTip(i18n("CTags dialog")); 00051 action->setWhatsThis(i18n("<b>CTags</b><p>Allows to create tags database and provides a dialog to search in tags database.")); 00052 00053 mOccuresTagsDlg = 0; 00054 mOccuresTagsDlg = new OccuresTagsDlg; 00055 mOccuresTagsDlg->hide(); 00056 00057 connect( mOccuresTagsDlg->mOcurresList, SIGNAL(clicked( QListBoxItem * )), 00058 this, SLOT(slotGotoTag( QListBoxItem * )) ); 00059 connect( core(), SIGNAL(projectClosed()), 00060 this, SLOT(projectClosed()) ); 00061 connect( core(), SIGNAL(contextMenu(QPopupMenu *, const Context *)), 00062 this, SLOT(contextMenu(QPopupMenu *, const Context *)) ); 00063 00064 m_tags = 0; 00065 m_dialog = 0; 00066 } 00067 00068 00069 CTagsPart::~CTagsPart() 00070 { 00071 delete m_dialog; 00072 delete m_tags; 00073 delete mOccuresTagsDlg; 00074 } 00075 00076 00077 void CTagsPart::projectClosed() 00078 { 00079 delete m_dialog; 00080 delete m_tags; 00081 delete mOccuresTagsDlg; 00082 m_dialog = 0; 00083 m_tags = 0; 00084 mOccuresTagsDlg = 0; 00085 } 00086 00087 00088 void CTagsPart::contextMenu(QPopupMenu *popup, const Context *context) 00089 { 00090 if (!context->hasType( Context::EditorContext )) 00091 return; 00092 00093 const EditorContext *econtext = static_cast<const EditorContext*>(context); 00094 QString ident = econtext->currentWord(); 00095 if (ident.isEmpty()) 00096 return; 00097 00098 m_contextString = ident; 00099 int id = popup->insertItem( i18n("Go to ctags Declaration: %1").arg(ident), 00100 this, SLOT(slotGotoDeclaration()) ); 00101 popup->setWhatsThis(id, i18n("<b>Go to ctags declaration</b><p>Searches in the tags database for a symbol " 00102 "under the cursor and opens a file that contains the symbol declaration.")); 00103 id = popup->insertItem( i18n("Go to ctags Definition: %1").arg(ident), 00104 this, SLOT(slotGotoDefinition()) ); 00105 popup->setWhatsThis(id, i18n("<b>Go to ctags definition</b><p>Searches in the tags database for a symbol " 00106 "under the cursor and opens a file that contains the symbol definition.")); 00107 } 00108 00109 00110 void CTagsPart::gotoTag(const QString &tag, const QString &kindChars) 00111 { 00112 if (!ensureTagsLoaded()) 00113 return; 00114 00115 QString fileName, pattern; 00116 QStringList occuresList; 00117 00118 CTagsMapIterator result = m_tags->find(tag); 00119 if (result != m_tags->end()) { 00120 CTagsTagInfoListConstIterator it; 00121 for (it = (*result).begin(); it != (*result).end(); ++it) 00122 { 00123 if (kindChars.find((*it).kind) != -1) { 00124 fileName = (*it).fileName; 00125 pattern = (*it).pattern; 00126 occuresList.append( fileName+":"+pattern ); 00127 } 00128 } 00129 } 00130 00131 if (fileName.isNull()) { 00132 KMessageBox::sorry(0, i18n("Tag not found")); 00133 return; 00134 } 00135 00136 if ( occuresList.count() > 1 ) { 00137 mOccuresTagsDlg->mOcurresList->clear(); 00138 mOccuresTagsDlg->mOcurresList->insertStringList( occuresList ); 00139 mOccuresTagsDlg->show(); 00140 } 00141 else 00142 gotoFinalTag( occuresList[0] ); 00143 } 00144 00145 void CTagsPart::slotGotoTag( QListBoxItem *item ) 00146 { 00147 if ( item ) 00148 gotoFinalTag( item->text() ); 00149 } 00150 00151 void CTagsPart::gotoFinalTag( const QString & contextStr ) 00152 { 00153 mOccuresTagsDlg->hide(); 00154 00155 QString fileName = contextStr.section( ':', 0, 0 ); 00156 QString pattern = contextStr.section( ':', -1 ); 00157 00158 bool ok; 00159 int lineNum = pattern.toInt(&ok); 00160 if (!ok) { 00161 KMessageBox::sorry(0, i18n("Currently, only tags with line numbers (option -n) are supported")); 00162 return; 00163 } 00164 00165 partController()->editDocument(fileName, lineNum-1); 00166 } 00167 00168 00169 void CTagsPart::slotGotoDeclaration() 00170 { 00171 gotoTag(m_contextString, "Lcegmnpsux"); 00172 } 00173 00174 00175 void CTagsPart::slotGotoDefinition() 00176 { 00177 gotoTag(m_contextString, "Sdftv"); 00178 } 00179 00180 00181 void CTagsPart::slotSearchTags() 00182 { 00183 if (!m_dialog) { 00184 if( ensureTagsLoaded() ) 00185 m_dialog = new CTagsDialog(this); 00186 } 00187 00188 if (m_dialog) 00189 m_dialog->show(); 00190 } 00191 00192 00193 bool CTagsPart::ensureTagsLoaded() 00194 { 00195 if (m_tags) 00196 return true; 00197 if (!project()) 00198 return false; 00199 00200 kdDebug(9022) << "create/load tags" << endl; 00201 00202 QFileInfo fi(project()->projectDirectory() + "/tags"); 00203 if (!fi.exists()) { 00204 int r = KMessageBox::questionYesNo(mainWindow()->main(), i18n("A ctags file for this project does not exist yet. Create it now?")); 00205 if (r != KMessageBox::Yes) 00206 return false; 00207 if (!createTagsFile()) { 00208 KMessageBox::sorry(mainWindow()->main(), i18n("Could not create tags file!\n\nPlease make sure 'ctags' can be found in your PATH.")); 00209 return false; 00210 } 00211 } 00212 00213 kdDebug(9022) << "load tags from " << endl; 00214 return loadTagsFile(); 00215 } 00216 00217 00218 bool CTagsPart::loadTagsFile() 00219 { 00220 kdDebug(9022) << "load tags file" << endl; 00221 00222 QFile f(project()->projectDirectory() + "/tags"); 00223 if (!f.open(IO_ReadOnly)) 00224 return false; 00225 00226 if (m_tags) 00227 m_tags->clear(); 00228 else 00229 m_tags = new CTagsMap; 00230 m_kindStrings.clear(); 00231 00232 QTextStream stream(&f); 00233 QRegExp re("^([^\t]*)\t([^\t]*)\t([^;]*);\"\t(.*)$"); 00234 00235 QString line; 00236 while (!stream.atEnd()) { 00237 line = stream.readLine().latin1(); 00238 // kdDebug() << "Line: " << line << endl; 00239 if (re.search(line) == -1) 00240 continue; 00241 00242 00243 QString tag = re.cap(1); 00244 QString file = re.cap(2); 00245 QString pattern = re.cap(3); 00246 QString extfield = re.cap(4); 00247 // kdDebug() <<"Tag " << tag << ", file " << file << ", pattern " 00248 // << pattern << ", extfield " << extfield << endl; 00249 CTagsMapIterator tiit = m_tags->find(tag); 00250 if (tiit == m_tags->end()) 00251 tiit = m_tags->insert(tag, CTagsTagInfoList()); 00252 00253 CTagsTagInfo ti; 00254 ti.fileName = re.cap(2); 00255 ti.pattern = re.cap(3); 00256 ti.kind = re.cap(4)[0].latin1(); 00257 (*tiit).append(ti); 00258 00259 // Put kind in kind list if not already there 00260 QString extension; 00261 if (ti.fileName.right(9) == "/Makefile") 00262 extension = "mak"; 00263 else { 00264 int pos = ti.fileName.findRev('.'); 00265 if (pos > 0) 00266 extension = ti.fileName.mid(pos+1); 00267 } 00268 if (extension.isNull()) 00269 continue; 00270 00271 QString kindString = CTagsKinds::findKind(ti.kind, extension); 00272 if (kindString.isNull()) 00273 continue; 00274 00275 if (!m_kindStrings.contains(kindString)) 00276 m_kindStrings.append(kindString); 00277 } 00278 00279 f.close(); 00280 00281 return true; 00282 00283 #if 0 00284 QDictIterator<CTagsTagInfoList> it(tags); 00285 for (; it.current(); ++it) { 00286 kdDebug() << "Id: " << it.currentKey() << endl; 00287 CTagsTagInfoList *l = it.current(); 00288 QValueList<CTagsTagInfo>::ConstIterator it2; 00289 for (it2 = l->begin(); it2 != l->end(); ++it2) 00290 kdDebug() << "at " << (*it2).fileName << "," << (*it2).pattern << endl; 00291 } 00292 #endif 00293 } 00294 00295 00296 bool CTagsPart::createTagsFile() 00297 { 00298 kdDebug(9022) << "create tags file" << endl; 00299 00300 KProcess proc; 00301 proc.setWorkingDirectory( project()->projectDirectory() ); 00302 00303 QStringList l = project()->allFiles(); 00304 00305 KTempFile ifile; 00306 QTextStream& is = *ifile.textStream(); 00307 is << l.join( "\n" ); 00308 is << "\n"; 00309 ifile.close(); 00310 00311 proc << "ctags"; 00312 proc << "-n"; 00313 proc << "--c++-types=+px"; 00314 proc << "-L" << ifile.name(); 00315 00316 QApplication::setOverrideCursor(Qt::waitCursor); 00317 bool success = proc.start(KProcess::Block); 00318 QApplication::restoreOverrideCursor(); 00319 00320 return success; 00321 } 00322 00323 #include "ctagspart.moc"
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:10 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003