00001
00002
00003
00004
00005
00006
00007
00008
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
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
00113
KTextEditor::Document * doc = static_cast<KTextEditor::Document*>( ro_part );
00114 connect( doc, SIGNAL(
marksChanged() ),
this, SLOT(
marksEvent() ) );
00115
00116
00117 connect( doc, SIGNAL( completed() ),
this, SLOT(
reload() ) );
00118 }
00119 }
00120 }
00121
00122 void BookmarksPart::reload()
00123 {
00124
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
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
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
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
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
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
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
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
00359
return true;
00360 }
00361
return false;
00362 }
00363
00364
00365
00366
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
00387
return true;
00388 }
00389
return false;
00390 }
00391
00392 EditorData *
BookmarksPart::storeBookmarksForURL(
KParts::ReadOnlyPart * ro_part )
00393 {
00394
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
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
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
00518
while( n < endline )
00519 {
00520 list.append(
" " );
00521 n++;
00522 }
00523
00524
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
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() )
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