KDevelop API Documentation

parts/bookmarks/bookmarks_part.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 * Copyright (C) 2003 by Jens Dagerbo * 00003 * jens.dagerbo@swipnet.se * 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 <qwhatsthis.h> 00013 #include <qvbox.h> 00014 #include <qtimer.h> 00015 #include <qtextstream.h> 00016 #include <qfile.h> 00017 00018 #include <kdebug.h> 00019 #include <kiconloader.h> 00020 #include <klocale.h> 00021 #include <kdevgenericfactory.h> 00022 #include <ktexteditor/markinterface.h> 00023 #include <ktexteditor/editinterface.h> 00024 #include <ktexteditor/document.h> 00025 #include <kaction.h> 00026 #include <kdialogbase.h> 00027 00028 #include <kdevpartcontroller.h> 00029 #include <kdevcore.h> 00030 #include <kdevmainwindow.h> 00031 #include "domutil.h" 00032 00033 #include "bookmarks_widget.h" 00034 #include "bookmarks_part.h" 00035 #include "bookmarks_settings.h" 00036 #include "bookmarks_config.h" 00037 00038 #include <configwidgetproxy.h> 00039 00040 #define BOOKMARKSETTINGSPAGE 1 00041 00042 typedef KDevGenericFactory<BookmarksPart> BookmarksFactory; 00043 static const KAboutData data("kdevbookmarks", I18N_NOOP("Bookmarks"), "1.0"); 00044 K_EXPORT_COMPONENT_FACTORY( libkdevbookmarks, BookmarksFactory( &data ) ) 00045 00046 BookmarksPart::BookmarksPart(QObject *parent, const char *name, const QStringList& ) 00047 : KDevPlugin("bookmarks", "bookmarks", parent, name ? name : "BookmarksPart" ) 00048 { 00049 setInstance(BookmarksFactory::instance()); 00050 00051 _widget = new BookmarksWidget(this); 00052 00053 _widget->setCaption(i18n("Bookmarks")); 00054 _widget->setIcon(SmallIcon("bookmark")); 00055 00056 _marksChangeTimer = new QTimer( this ); 00057 00058 QWhatsThis::add(_widget, i18n("<b>Bookmarks</b><p>" 00059 "The bookmark viewer shows all the source bookmarks in the project.")); 00060 00061 mainWindow()->embedSelectView(_widget, i18n("Bookmarks"), i18n("Source bookmarks")); 00062 00063 _editorMap.setAutoDelete( true ); 00064 _settingMarks = false; 00065 00066 connect( partController(), SIGNAL( partAdded( KParts::Part * ) ), this, SLOT( partAdded( KParts::Part * ) ) ); 00067 00068 _configProxy = new ConfigWidgetProxy( core() ); 00069 _configProxy->createProjectConfigPage( i18n("Bookmarks"), BOOKMARKSETTINGSPAGE ); 00070 connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )), 00071 this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) ); 00072 00073 connect( _widget, SIGNAL( removeAllBookmarksForURL( const KURL & ) ), 00074 this, SLOT( removeAllBookmarksForURL( const KURL & ) ) ); 00075 connect( _widget, SIGNAL( removeBookmarkForURL( const KURL &, int ) ), 00076 this, SLOT( removeBookmarkForURL( const KURL &, int ) ) ); 00077 00078 connect( _marksChangeTimer, SIGNAL( timeout() ), this, SLOT( marksChanged() ) ); 00079 00080 _config = new BookmarksConfig; 00081 _config->readConfig(); 00082 00083 storeBookmarksForAllURLs(); 00084 updateContextStringForAll(); 00085 _widget->update( _editorMap ); 00086 } 00087 00088 BookmarksPart::~BookmarksPart() 00089 { 00090 if( _widget ) { 00091 mainWindow()->removeView( _widget ); 00092 delete _widget; 00093 } 00094 delete _config; 00095 delete _configProxy; 00096 } 00097 00098 void BookmarksPart::partAdded( KParts::Part * part ) 00099 { 00100 //kdDebug(0) << "BookmarksPart::partAdded()" << endl; 00101 00102 if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( part ) ) 00103 { 00104 if ( setBookmarksForURL( ro_part ) ) 00105 { 00106 updateContextStringForURL( ro_part ); 00107 if ( EditorData * data = _editorMap.find( ro_part->url().path() ) ) 00108 { 00109 _widget->updateURL( data ); 00110 } 00111 00112 // connect to this editor 00113 KTextEditor::Document * doc = static_cast<KTextEditor::Document*>( ro_part ); 00114 connect( doc, SIGNAL( marksChanged() ), this, SLOT( marksEvent() ) ); 00115 00116 // workaround for a katepart oddity where it drops all bookmarks on 'reload' 00117 connect( doc, SIGNAL( completed() ), this, SLOT( reload() ) ); 00118 } 00119 } 00120 } 00121 00122 void BookmarksPart::reload() 00123 { 00124 //kdDebug(0) << "BookmarksPart::reload()" << endl; 00125 00126 QObject * senderobj = const_cast<QObject*>( sender() ); 00127 if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( senderobj ) ) 00128 { 00129 if ( partIsSane( ro_part ) ) 00130 { 00131 setBookmarksForURL( ro_part ); 00132 } 00133 } 00134 } 00135 00136 void BookmarksPart::marksEvent() 00137 { 00138 //kdDebug(0) << "BookmarksPart::marksEvent()" << endl; 00139 00140 if ( ! _settingMarks ) 00141 { 00142 QObject * senderobj = const_cast<QObject*>( sender() ); 00143 KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( senderobj ); 00144 00145 if ( partIsSane( ro_part ) && !_dirtyParts.contains( ro_part ) ) 00146 { 00147 _dirtyParts.push_back( ro_part ); 00148 _marksChangeTimer->start( 1000, true ); 00149 } 00150 } 00151 } 00152 00153 void BookmarksPart::marksChanged() 00154 { 00155 //kdDebug(0) << "BookmarksPart::marksChanged()" << endl; 00156 00157 QValueListIterator<KParts::ReadOnlyPart*> it = _dirtyParts.begin(); 00158 while ( it != _dirtyParts.end() ) 00159 { 00160 KParts::ReadOnlyPart * ro_part = *it; 00161 if ( partIsSane( ro_part ) ) 00162 { 00163 if ( dynamic_cast<KTextEditor::MarkInterface*>( ro_part ) ) 00164 { 00165 if ( EditorData * data = storeBookmarksForURL( ro_part ) ) 00166 { 00167 updateContextStringForURL( ro_part ); 00168 _widget->updateURL( data ); 00169 } 00170 else 00171 { 00172 _widget->removeURL( ro_part->url() ); 00173 } 00174 } 00175 } 00176 ++it; 00177 } 00178 _dirtyParts.clear(); 00179 } 00180 00181 void BookmarksPart::restorePartialProjectSession( const QDomElement * el ) 00182 { 00183 //kdDebug(0) << "BookmarksPart::restorePartialProjectSession()" << endl; 00184 00185 if ( ! el ) return; 00186 00187 QDomElement bookmarksList = el->namedItem( "bookmarks" ).toElement(); 00188 if ( bookmarksList.isNull() ) return; 00189 00190 QDomElement bookmark = bookmarksList.firstChild().toElement(); 00191 while ( ! bookmark.isNull() ) 00192 { 00193 QString path = bookmark.attribute( "url" ); 00194 if ( path != QString::null ) 00195 { 00196 EditorData * data = new EditorData; 00197 data->url.setPath( path ); 00198 00199 QDomElement mark = bookmark.firstChild().toElement(); 00200 while ( ! mark.isNull() ) 00201 { 00202 QString line = mark.attribute( "line" ); 00203 if ( line != QString::null ) 00204 { 00205 data->marks.append( qMakePair( line.toInt(), QString() ) ); 00206 } 00207 mark = mark.nextSibling().toElement(); 00208 } 00209 00210 if ( ! data->marks.isEmpty() ) 00211 { 00212 _editorMap.insert( data->url.path(), data ); 00213 } 00214 else 00215 { 00216 delete data; 00217 } 00218 } 00219 bookmark = bookmark.nextSibling().toElement(); 00220 } 00221 setBookmarksForAllURLs(); 00222 updateContextStringForAll(); 00223 _widget->update( _editorMap ); 00224 } 00225 00226 void BookmarksPart::savePartialProjectSession( QDomElement * el ) 00227 { 00228 //kdDebug(0) << "BookmarksPart::savePartialProjectSession()" << endl; 00229 00230 if ( ! el ) return; 00231 00232 QDomDocument domDoc = el->ownerDocument(); 00233 if ( domDoc.isNull() ) return; 00234 00235 QDomElement bookmarksList = domDoc.createElement( "bookmarks" ); 00236 00237 QDictIterator<EditorData> it( _editorMap ); 00238 while ( it.current() ) 00239 { 00240 QDomElement bookmark = domDoc.createElement( "bookmark" ); 00241 bookmark.setAttribute( "url", it.current()->url.path() ); 00242 bookmarksList.appendChild( bookmark ); 00243 00244 QValueListIterator< QPair<int,QString> > it2 = it.current()->marks.begin(); 00245 while ( it2 != it.current()->marks.end() ) 00246 { 00247 QDomElement line = domDoc.createElement( "mark" ); 00248 line.setAttribute( "line", (*it2).first ); 00249 bookmark.appendChild( line ); 00250 ++it2; 00251 } 00252 ++it; 00253 } 00254 00255 if ( ! bookmarksList.isNull() ) 00256 { 00257 el->appendChild( bookmarksList ); 00258 } 00259 } 00260 00261 void BookmarksPart::removeAllBookmarksForURL( KURL const & url ) 00262 { 00263 //kdDebug(0) << "BookmarksPart::removeAllBookmarksForURL()" << endl; 00264 00265 _editorMap.remove( url.path() ); 00266 00267 setBookmarksForURL( partForURL( url ) ); 00268 _widget->removeURL( url ); 00269 } 00270 00271 void BookmarksPart::removeBookmarkForURL( KURL const & url, int line ) 00272 { 00273 //kdDebug(0) << "BookmarksPart::removeBookmarkForURL()" << endl; 00274 00275 if ( EditorData * data = _editorMap.find( url.path() ) ) 00276 { 00277 QValueListIterator< QPair<int,QString> > it = data->marks.begin(); 00278 while ( it != data->marks.end() ) 00279 { 00280 if ( (*it).first == line ) 00281 { 00282 data->marks.remove( it ); 00283 break; 00284 } 00285 ++it; 00286 } 00287 00288 if ( data->marks.isEmpty() ) 00289 { 00290 removeAllBookmarksForURL( url ); 00291 } 00292 else 00293 { 00294 setBookmarksForURL( partForURL( url ) ); 00295 _widget->updateURL( data ); 00296 } 00297 } 00298 } 00299 00300 void BookmarksPart::updateContextStringForURL( KParts::ReadOnlyPart * ro_part ) 00301 { 00302 if ( ! ro_part ) return; 00303 00304 KTextEditor::EditInterface * ed = 00305 dynamic_cast<KTextEditor::EditInterface *>( ro_part ); 00306 00307 EditorData * data = _editorMap.find( ro_part->url().path() ); 00308 00309 if ( ! ( data && ed ) ) return; 00310 00311 QValueListIterator< QPair<int,QString> > it = data->marks.begin(); 00312 while ( it != data->marks.end() ) 00313 { 00314 (*it).second = ed->textLine( (*it).first ); 00315 ++it; 00316 } 00317 } 00318 00319 void BookmarksPart::updateContextStringForURL( KURL const & url ) 00320 { 00321 updateContextStringForURL( partForURL( url ) ); 00322 } 00323 00324 void BookmarksPart::updateContextStringForAll() 00325 { 00326 QDictIterator<EditorData> it( _editorMap ); 00327 while ( it.current() ) 00328 { 00329 if ( ! it.current()->marks.isEmpty() ) 00330 { 00331 updateContextStringForURL( it.current()->url ); 00332 } 00333 ++it; 00334 } 00335 } 00336 00337 bool BookmarksPart::setBookmarksForURL( KParts::ReadOnlyPart * ro_part ) 00338 { 00339 if ( KTextEditor::MarkInterface * mi = dynamic_cast<KTextEditor::MarkInterface *>(ro_part) ) 00340 { 00341 clearBookmarksForURL( ro_part ); 00342 00343 _settingMarks = true; 00344 00345 if ( EditorData * data = _editorMap.find( ro_part->url().path() ) ) 00346 { 00347 // we've seen this one before, apply stored bookmarks 00348 00349 QValueListIterator< QPair<int,QString> > it = data->marks.begin(); 00350 while ( it != data->marks.end() ) 00351 { 00352 mi->addMark( (*it).first, KTextEditor::MarkInterface::markType01 ); 00353 ++it; 00354 } 00355 } 00356 _settingMarks = false; 00357 00358 // true == this is a MarkInterface 00359 return true; 00360 } 00361 return false; 00362 } 00363 00364 // Note: This method is only a convenience method to clear the bookmark marks, 00365 // the way a hypothetical KTextEditor::MarkInterface::clearMarks( uint markType ) 00366 // would work. 00367 bool BookmarksPart::clearBookmarksForURL( KParts::ReadOnlyPart * ro_part ) 00368 { 00369 if ( KTextEditor::MarkInterface * mi = dynamic_cast<KTextEditor::MarkInterface *>(ro_part) ) 00370 { 00371 _settingMarks = true; 00372 00373 QPtrList<KTextEditor::Mark> marks = mi->marks(); 00374 QPtrListIterator<KTextEditor::Mark> it( marks ); 00375 while ( it.current() ) 00376 { 00377 if ( it.current()->type & KTextEditor::MarkInterface::markType01 ) 00378 { 00379 mi->removeMark( it.current()->line, KTextEditor::MarkInterface::markType01 ); 00380 } 00381 ++it; 00382 } 00383 00384 _settingMarks = false; 00385 00386 // true == this is a MarkInterface 00387 return true; 00388 } 00389 return false; 00390 } 00391 00392 EditorData * BookmarksPart::storeBookmarksForURL( KParts::ReadOnlyPart * ro_part ) 00393 { 00394 //kdDebug(0) << "BookmarksPart::storeBookmarksForURL()" << endl; 00395 00396 if ( KTextEditor::MarkInterface * mi = dynamic_cast<KTextEditor::MarkInterface *>( ro_part ) ) 00397 { 00398 EditorData * data = new EditorData; 00399 data->url = ro_part->url(); 00400 00401 // removing previous data for this url, if any 00402 _editorMap.remove( data->url.path() ); 00403 00404 QPtrList<KTextEditor::Mark> marks = mi->marks(); 00405 QPtrListIterator<KTextEditor::Mark> it( marks ); 00406 while ( it.current() ) 00407 { 00408 if ( it.current()->type & KTextEditor::MarkInterface::markType01 ) 00409 { 00410 int line = it.current()->line; 00411 data->marks.append( qMakePair( line, QString() ) ); 00412 } 00413 ++it; 00414 } 00415 00416 if ( ! data->marks.isEmpty() ) 00417 { 00418 _editorMap.insert( data->url.path(), data ); 00419 } 00420 else 00421 { 00422 delete data; 00423 data = 0; 00424 } 00425 return data; 00426 } 00427 return 0; 00428 } 00429 00430 void BookmarksPart::setBookmarksForAllURLs() 00431 { 00432 if( const QPtrList<KParts::Part> * partlist = partController()->parts() ) 00433 { 00434 QPtrListIterator<KParts::Part> it( *partlist ); 00435 while ( KParts::Part* part = it.current() ) 00436 { 00437 if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( part ) ) 00438 { 00439 setBookmarksForURL( ro_part ); 00440 } 00441 ++it; 00442 } 00443 } 00444 } 00445 00446 void BookmarksPart::storeBookmarksForAllURLs() 00447 { 00448 if( const QPtrList<KParts::Part> * partlist = partController()->parts() ) 00449 { 00450 QPtrListIterator<KParts::Part> it( *partlist ); 00451 while ( KParts::Part* part = it.current() ) 00452 { 00453 if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( part ) ) 00454 { 00455 storeBookmarksForURL( ro_part ); 00456 } 00457 ++it; 00458 } 00459 } 00460 } 00461 00462 // reimplemented from PartController::partForURL to avoid linking 00463 KParts::ReadOnlyPart * BookmarksPart::partForURL( KURL const & url ) 00464 { 00465 QPtrListIterator<KParts::Part> it( *partController()->parts() ); 00466 while( it.current() ) 00467 { 00468 KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(it.current()); 00469 if (ro_part && url == ro_part->url()) 00470 { 00471 return ro_part; 00472 } 00473 ++it; 00474 } 00475 return 0; 00476 } 00477 00478 bool BookmarksPart::partIsSane( KParts::ReadOnlyPart * ro_part ) 00479 { 00480 return ( ro_part != 0 ) && 00481 partController()->parts()->contains( ro_part) && 00482 !ro_part->url().path().isEmpty(); 00483 } 00484 00485 void BookmarksPart::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber ) 00486 { 00487 kdDebug() << k_funcinfo << endl; 00488 00489 if ( pagenumber == BOOKMARKSETTINGSPAGE ) 00490 { 00491 BookmarkSettings * w = new BookmarkSettings( this, page ); 00492 connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) ); 00493 } 00494 } 00495 00497 00498 QStringList BookmarksPart::getContextFromStream( QTextStream & istream, unsigned int line, unsigned int context ) 00499 { 00500 kdDebug() << k_funcinfo << endl; 00501 00502 int startline = context > line ? 0 : line - context; 00503 int endline = line + context; 00504 00505 int n = 0; 00506 QStringList list; 00507 while ( !istream.atEnd() ) 00508 { 00509 QString templine = istream.readLine(); 00510 if ( (n >= startline) && ( n <= endline ) ) 00511 { 00512 list << templine; 00513 } 00514 n++; 00515 } 00516 00517 // maybe pad empty lines to the tail 00518 while( n < endline ) 00519 { 00520 list.append( " " ); 00521 n++; 00522 } 00523 00524 // maybe pad empty lines to the head 00525 while( list.count() < ( context * 2 + 1) ) 00526 { 00527 list.prepend( " " ); 00528 } 00529 00530 return list; 00531 } 00532 00533 QStringList BookmarksPart::getContext( KURL const & url, unsigned int line, unsigned int context ) 00534 { 00535 // if the file is open - get the line from the editor buffer 00536 if ( KTextEditor::EditInterface * ei = dynamic_cast<KTextEditor::EditInterface*>( partForURL( url ) ) ) 00537 { 00538 kdDebug() << "the file is open - get the line from the editor buffer" << endl; 00539 00540 QString ibuffer = ei->text(); 00541 QTextStream istream( &ibuffer, IO_ReadOnly ); 00542 return getContextFromStream( istream, line, context ); 00543 } 00544 else if ( url.isLocalFile() ) // else the file is not open - get the line from the file on disk 00545 { 00546 kdDebug() << "the file is not open - get the line from the file on disk" << endl; 00547 00548 QFile file( url.path() ); 00549 QString buffer; 00550 00551 if ( file.open( IO_ReadOnly ) ) 00552 { 00553 QTextStream istream( &file ); 00554 return getContextFromStream( istream, line, context ); 00555 } 00556 } 00557 return QStringList( i18n("Couldn't find file") ); 00558 } 00559 00560 BookmarksConfig * BookmarksPart::config( ) 00561 { 00562 return _config; 00563 } 00564 00565 #include "bookmarks_part.moc" 00566 00567 // kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;
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:09 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003