~ubuntu-branches/debian/sid/kdevelop/sid

« back to all changes in this revision

Viewing changes to parts/bookmarks/bookmarks_part.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jeremy Lainé
  • Date: 2006-05-23 18:39:42 UTC
  • Revision ID: james.westby@ubuntu.com-20060523183942-hucifbvh68k2bwz7
Tags: upstream-3.3.2
Import upstream version 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2003 by Jens Dagerbo                                    *
 
3
 *   jens.dagerbo@swipnet.se                                               *
 
4
 *                                                                         *
 
5
 *   This program is free software; you can redistribute it and/or modify  *
 
6
 *   it under the terms of the GNU General Public License as published by  *
 
7
 *   the Free Software Foundation; either version 2 of the License, or     *
 
8
 *   (at your option) any later version.                                   *
 
9
 *                                                                         *
 
10
 ***************************************************************************/
 
11
 
 
12
#include <qwhatsthis.h>
 
13
#include <qvbox.h>
 
14
#include <qtimer.h>
 
15
#include <qtextstream.h>
 
16
#include <qfile.h>
 
17
 
 
18
#include <kdebug.h>
 
19
#include <kiconloader.h>
 
20
#include <klocale.h>
 
21
#include <kdevgenericfactory.h>
 
22
#include <ktexteditor/markinterface.h>
 
23
#include <ktexteditor/editinterface.h>
 
24
#include <ktexteditor/document.h>
 
25
#include <kaction.h>
 
26
#include <kdialogbase.h>
 
27
 
 
28
#include <kdevpartcontroller.h>
 
29
#include <kdevcore.h>
 
30
#include <kdevmainwindow.h>
 
31
#include "domutil.h"
 
32
 
 
33
#include "bookmarks_widget.h"
 
34
#include "bookmarks_part.h"
 
35
#include "bookmarks_settings.h"
 
36
#include "bookmarks_config.h"
 
37
 
 
38
#include <configwidgetproxy.h>
 
39
#include <kdevplugininfo.h>
 
40
 
 
41
#define BOOKMARKSETTINGSPAGE 1
 
42
 
 
43
typedef KDevGenericFactory<BookmarksPart> BookmarksFactory;
 
44
static const KDevPluginInfo data("kdevbookmarks");
 
45
K_EXPORT_COMPONENT_FACTORY( libkdevbookmarks, BookmarksFactory( data ) )
 
46
 
 
47
BookmarksPart::BookmarksPart(QObject *parent, const char *name, const QStringList& )
 
48
        : KDevPlugin(&data, parent, name ? name : "BookmarksPart" )
 
49
{
 
50
        setInstance(BookmarksFactory::instance());
 
51
 
 
52
        _widget = new BookmarksWidget(this);
 
53
 
 
54
        _widget->setCaption(i18n("Bookmarks"));
 
55
        _widget->setIcon(SmallIcon( info()->icon() ));
 
56
 
 
57
        _marksChangeTimer = new QTimer( this );
 
58
 
 
59
        QWhatsThis::add(_widget, i18n("<b>Bookmarks</b><p>"
 
60
                        "The bookmark viewer shows all the source bookmarks in the project."));
 
61
 
 
62
        mainWindow()->embedSelectView(_widget, i18n("Bookmarks"), i18n("Source bookmarks"));
 
63
 
 
64
        _editorMap.setAutoDelete( true );
 
65
        _settingMarks = false;
 
66
 
 
67
        connect( partController(), SIGNAL( partAdded( KParts::Part * ) ), this, SLOT( partAdded( KParts::Part * ) ) );
 
68
 
 
69
        _configProxy = new ConfigWidgetProxy( core() );
 
70
        _configProxy->createProjectConfigPage( i18n("Bookmarks"), BOOKMARKSETTINGSPAGE, info()->icon() );
 
71
        connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )),
 
72
                this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) );
 
73
 
 
74
        connect( _widget, SIGNAL( removeAllBookmarksForURL( const KURL & ) ),
 
75
                this, SLOT( removeAllBookmarksForURL( const KURL & ) ) );
 
76
        connect( _widget, SIGNAL( removeBookmarkForURL( const KURL &, int ) ),
 
77
                this, SLOT( removeBookmarkForURL( const KURL &, int ) ) );
 
78
 
 
79
        connect( _marksChangeTimer, SIGNAL( timeout() ), this, SLOT( marksChanged() ) );
 
80
 
 
81
        _config = new BookmarksConfig;
 
82
        _config->readConfig();
 
83
 
 
84
        storeBookmarksForAllURLs();
 
85
        updateContextStringForAll();
 
86
        _widget->update( _editorMap );
 
87
}
 
88
 
 
89
BookmarksPart::~BookmarksPart()
 
90
{
 
91
        if( _widget ) {
 
92
                mainWindow()->removeView( _widget );
 
93
                delete _widget;
 
94
        }
 
95
        delete _config;
 
96
        delete _configProxy;
 
97
}
 
98
 
 
99
void BookmarksPart::partAdded( KParts::Part * part )
 
100
{
 
101
        //kdDebug(0) << "BookmarksPart::partAdded()" << endl;
 
102
 
 
103
        if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( part ) )
 
104
        {
 
105
                if ( setBookmarksForURL( ro_part ) )
 
106
                {
 
107
                        updateContextStringForURL( ro_part );
 
108
                        if ( EditorData * data = _editorMap.find( ro_part->url().path() ) )
 
109
                        {
 
110
                                _widget->updateURL( data );
 
111
                        }
 
112
 
 
113
                        // connect to this editor
 
114
                        KTextEditor::Document * doc = static_cast<KTextEditor::Document*>( ro_part );
 
115
                        connect( doc, SIGNAL( marksChanged() ), this, SLOT( marksEvent() ) );
 
116
 
 
117
                        // workaround for a katepart oddity where it drops all bookmarks on 'reload'
 
118
                        connect( doc, SIGNAL( completed() ), this, SLOT( reload() ) );
 
119
                }
 
120
        }
 
121
}
 
122
 
 
123
void BookmarksPart::reload()
 
124
{
 
125
        //kdDebug(0) << "BookmarksPart::reload()" << endl;
 
126
 
 
127
        QObject * senderobj = const_cast<QObject*>( sender() );
 
128
        if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( senderobj ) )
 
129
        {
 
130
                if ( partIsSane( ro_part ) )
 
131
                {
 
132
                        setBookmarksForURL( ro_part );
 
133
                }
 
134
        }
 
135
}
 
136
 
 
137
void BookmarksPart::marksEvent()
 
138
{
 
139
        //kdDebug(0) << "BookmarksPart::marksEvent()" << endl;
 
140
 
 
141
        if ( ! _settingMarks )
 
142
        {
 
143
                QObject * senderobj = const_cast<QObject*>( sender() );
 
144
                KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( senderobj );
 
145
 
 
146
                if ( partIsSane( ro_part ) && !_dirtyParts.contains( ro_part ) )
 
147
                {
 
148
                        _dirtyParts.push_back( ro_part );
 
149
                        _marksChangeTimer->start( 1000, true );
 
150
                }
 
151
        }
 
152
}
 
153
 
 
154
void BookmarksPart::marksChanged()
 
155
{
 
156
        //kdDebug(0) << "BookmarksPart::marksChanged()" << endl;
 
157
 
 
158
        QValueListIterator<KParts::ReadOnlyPart*> it = _dirtyParts.begin();
 
159
        while ( it != _dirtyParts.end() )
 
160
        {
 
161
                KParts::ReadOnlyPart * ro_part = *it;
 
162
                if ( partIsSane( ro_part ) )
 
163
                {
 
164
                        if ( dynamic_cast<KTextEditor::MarkInterface*>( ro_part ) )
 
165
                        {
 
166
                                if ( EditorData * data = storeBookmarksForURL( ro_part ) )
 
167
                                {
 
168
                                        updateContextStringForURL( ro_part );
 
169
                                        _widget->updateURL( data );
 
170
                                }
 
171
                                else
 
172
                                {
 
173
                                        _widget->removeURL( ro_part->url() );
 
174
                                }
 
175
                        }
 
176
                }
 
177
                ++it;
 
178
        }
 
179
        _dirtyParts.clear();
 
180
}
 
181
 
 
182
void BookmarksPart::restorePartialProjectSession( const QDomElement * el )
 
183
{
 
184
        //kdDebug(0) << "BookmarksPart::restorePartialProjectSession()" << endl;
 
185
 
 
186
        if ( ! el ) return;
 
187
 
 
188
        QDomElement bookmarksList = el->namedItem( "bookmarks" ).toElement();
 
189
        if ( bookmarksList.isNull() ) return;
 
190
 
 
191
        QDomElement bookmark = bookmarksList.firstChild().toElement();
 
192
        while ( ! bookmark.isNull() )
 
193
        {
 
194
                QString path = bookmark.attribute( "url" );
 
195
                if ( path != QString::null )
 
196
                {
 
197
                        EditorData * data = new EditorData;
 
198
                        data->url.setPath( path );
 
199
 
 
200
                        QDomElement mark = bookmark.firstChild().toElement();
 
201
                        while ( ! mark.isNull() )
 
202
                        {
 
203
                                QString line = mark.attribute( "line" );
 
204
                                if ( line != QString::null )
 
205
                                {
 
206
                                        data->marks.append( qMakePair( line.toInt(), QString() ) );
 
207
                                }
 
208
                                mark = mark.nextSibling().toElement();
 
209
                        }
 
210
 
 
211
                        if ( ! data->marks.isEmpty() )
 
212
                        {
 
213
                                _editorMap.insert( data->url.path(), data );
 
214
                        }
 
215
                        else
 
216
                        {
 
217
                                delete data;
 
218
                        }
 
219
                }
 
220
                bookmark = bookmark.nextSibling().toElement();
 
221
        }
 
222
        setBookmarksForAllURLs();
 
223
        updateContextStringForAll();
 
224
        _widget->update( _editorMap );
 
225
}
 
226
 
 
227
void BookmarksPart::savePartialProjectSession( QDomElement * el )
 
228
{
 
229
        //kdDebug(0) << "BookmarksPart::savePartialProjectSession()" << endl;
 
230
 
 
231
        if ( ! el ) return;
 
232
 
 
233
    QDomDocument domDoc = el->ownerDocument();
 
234
    if ( domDoc.isNull() ) return;
 
235
 
 
236
        QDomElement bookmarksList = domDoc.createElement( "bookmarks" );
 
237
 
 
238
        QDictIterator<EditorData> it( _editorMap );
 
239
        while ( it.current() )
 
240
        {
 
241
                QDomElement bookmark = domDoc.createElement( "bookmark" );
 
242
                bookmark.setAttribute( "url", it.current()->url.path() );
 
243
                bookmarksList.appendChild( bookmark );
 
244
 
 
245
                QValueListIterator< QPair<int,QString> > it2 = it.current()->marks.begin();
 
246
                while ( it2 != it.current()->marks.end() )
 
247
                {
 
248
                        QDomElement line = domDoc.createElement( "mark" );
 
249
                        line.setAttribute( "line", (*it2).first );
 
250
                        bookmark.appendChild( line );
 
251
                        ++it2;
 
252
                }
 
253
                ++it;
 
254
        }
 
255
 
 
256
        if ( ! bookmarksList.isNull() )
 
257
        {
 
258
                el->appendChild( bookmarksList );
 
259
        }
 
260
}
 
261
 
 
262
void BookmarksPart::removeAllBookmarksForURL( KURL const & url )
 
263
{
 
264
        //kdDebug(0) << "BookmarksPart::removeAllBookmarksForURL()" << endl;
 
265
 
 
266
        _editorMap.remove( url.path() );
 
267
 
 
268
        setBookmarksForURL( partForURL( url ) );
 
269
        _widget->removeURL( url );
 
270
}
 
271
 
 
272
void BookmarksPart::removeBookmarkForURL( KURL const & url, int line )
 
273
{
 
274
        //kdDebug(0) << "BookmarksPart::removeBookmarkForURL()" << endl;
 
275
 
 
276
        if ( EditorData * data = _editorMap.find( url.path() ) )
 
277
        {
 
278
                QValueListIterator< QPair<int,QString> > it = data->marks.begin();
 
279
                while ( it != data->marks.end() )
 
280
                {
 
281
                        if ( (*it).first == line )
 
282
                        {
 
283
                                data->marks.remove( it );
 
284
                                break;
 
285
                        }
 
286
                        ++it;
 
287
                }
 
288
 
 
289
                if ( data->marks.isEmpty() )
 
290
                {
 
291
                        removeAllBookmarksForURL( url );
 
292
                }
 
293
                else
 
294
                {
 
295
                        setBookmarksForURL( partForURL( url ) );
 
296
                        _widget->updateURL( data );
 
297
                }
 
298
        }
 
299
}
 
300
 
 
301
void BookmarksPart::updateContextStringForURL( KParts::ReadOnlyPart * ro_part )
 
302
{
 
303
        if ( ! ro_part ) return;
 
304
 
 
305
        KTextEditor::EditInterface * ed =
 
306
                dynamic_cast<KTextEditor::EditInterface *>( ro_part );
 
307
 
 
308
        EditorData * data = _editorMap.find( ro_part->url().path() );
 
309
 
 
310
        if ( ! ( data && ed ) ) return;
 
311
 
 
312
        QValueListIterator< QPair<int,QString> > it = data->marks.begin();
 
313
        while ( it != data->marks.end() )
 
314
        {
 
315
                (*it).second = ed->textLine( (*it).first );
 
316
                ++it;
 
317
        }
 
318
}
 
319
 
 
320
void BookmarksPart::updateContextStringForURL( KURL const & url )
 
321
{
 
322
        updateContextStringForURL( partForURL( url ) );
 
323
}
 
324
 
 
325
void BookmarksPart::updateContextStringForAll()
 
326
{
 
327
        QDictIterator<EditorData> it( _editorMap );
 
328
        while ( it.current() )
 
329
        {
 
330
                if ( ! it.current()->marks.isEmpty() )
 
331
                {
 
332
                        updateContextStringForURL( it.current()->url );
 
333
                }
 
334
                ++it;
 
335
        }
 
336
}
 
337
 
 
338
bool BookmarksPart::setBookmarksForURL( KParts::ReadOnlyPart * ro_part )
 
339
{
 
340
        if ( KTextEditor::MarkInterface * mi = dynamic_cast<KTextEditor::MarkInterface *>(ro_part) )
 
341
        {
 
342
                clearBookmarksForURL( ro_part );
 
343
 
 
344
                _settingMarks = true;
 
345
 
 
346
                if ( EditorData * data = _editorMap.find( ro_part->url().path() ) )
 
347
                {
 
348
                        // we've seen this one before, apply stored bookmarks
 
349
 
 
350
                        QValueListIterator< QPair<int,QString> > it = data->marks.begin();
 
351
                        while ( it != data->marks.end() )
 
352
                        {
 
353
                                mi->addMark( (*it).first, KTextEditor::MarkInterface::markType01 );
 
354
                                ++it;
 
355
                        }
 
356
                }
 
357
                _settingMarks = false;
 
358
 
 
359
                // true == this is a MarkInterface
 
360
                return true;
 
361
        }
 
362
        return false;
 
363
}
 
364
 
 
365
// Note: This method is only a convenience method to clear the bookmark marks,
 
366
// the way a hypothetical KTextEditor::MarkInterface::clearMarks( uint markType )
 
367
// would work.
 
368
bool BookmarksPart::clearBookmarksForURL( KParts::ReadOnlyPart * ro_part )
 
369
{
 
370
        if ( KTextEditor::MarkInterface * mi = dynamic_cast<KTextEditor::MarkInterface *>(ro_part) )
 
371
        {
 
372
                _settingMarks = true;
 
373
 
 
374
                QPtrList<KTextEditor::Mark> marks = mi->marks();
 
375
                QPtrListIterator<KTextEditor::Mark> it( marks );
 
376
                while ( it.current() )
 
377
                {
 
378
                        if ( it.current()->type & KTextEditor::MarkInterface::markType01 )
 
379
                        {
 
380
                                mi->removeMark( it.current()->line, KTextEditor::MarkInterface::markType01 );
 
381
                        }
 
382
                        ++it;
 
383
                }
 
384
 
 
385
                _settingMarks = false;
 
386
 
 
387
                // true == this is a MarkInterface
 
388
                return true;
 
389
        }
 
390
        return false;
 
391
}
 
392
 
 
393
EditorData * BookmarksPart::storeBookmarksForURL( KParts::ReadOnlyPart * ro_part )
 
394
{
 
395
        //kdDebug(0) << "BookmarksPart::storeBookmarksForURL()" << endl;
 
396
 
 
397
        if ( KTextEditor::MarkInterface * mi = dynamic_cast<KTextEditor::MarkInterface *>( ro_part ) )
 
398
        {
 
399
                EditorData * data = new EditorData;
 
400
                data->url = ro_part->url();
 
401
 
 
402
                // removing previous data for this url, if any
 
403
                _editorMap.remove( data->url.path() );
 
404
 
 
405
                QPtrList<KTextEditor::Mark> marks = mi->marks();
 
406
                QPtrListIterator<KTextEditor::Mark> it( marks );
 
407
                while ( it.current() )
 
408
                {
 
409
                        if ( it.current()->type & KTextEditor::MarkInterface::markType01 )
 
410
                        {
 
411
                            int line = it.current()->line;
 
412
                                data->marks.append( qMakePair( line, QString() ) );
 
413
                        }
 
414
                        ++it;
 
415
                }
 
416
 
 
417
                if ( ! data->marks.isEmpty() )
 
418
                {
 
419
                        _editorMap.insert( data->url.path(), data );
 
420
                }
 
421
                else
 
422
                {
 
423
                        delete data;
 
424
                        data = 0;
 
425
                }
 
426
                return data;
 
427
        }
 
428
        return 0;
 
429
}
 
430
 
 
431
void BookmarksPart::setBookmarksForAllURLs()
 
432
{
 
433
        if( const QPtrList<KParts::Part> * partlist = partController()->parts() )
 
434
        {
 
435
                QPtrListIterator<KParts::Part> it( *partlist );
 
436
                while ( KParts::Part* part = it.current() )
 
437
                {
 
438
                        if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( part ) )
 
439
                        {
 
440
                                setBookmarksForURL( ro_part );
 
441
                        }
 
442
                        ++it;
 
443
                }
 
444
        }
 
445
}
 
446
 
 
447
void BookmarksPart::storeBookmarksForAllURLs()
 
448
{
 
449
        if( const QPtrList<KParts::Part> * partlist = partController()->parts() )
 
450
        {
 
451
                QPtrListIterator<KParts::Part> it( *partlist );
 
452
                while ( KParts::Part* part = it.current() )
 
453
                {
 
454
                        if ( KParts::ReadOnlyPart * ro_part = dynamic_cast<KParts::ReadOnlyPart *>( part ) )
 
455
                        {
 
456
                                storeBookmarksForURL( ro_part );
 
457
                        }
 
458
                        ++it;
 
459
                }
 
460
        }
 
461
}
 
462
 
 
463
// reimplemented from PartController::partForURL to avoid linking
 
464
KParts::ReadOnlyPart * BookmarksPart::partForURL( KURL const & url )
 
465
{
 
466
        QPtrListIterator<KParts::Part> it( *partController()->parts() );
 
467
        while( it.current() )
 
468
        {
 
469
                KParts::ReadOnlyPart *ro_part = dynamic_cast<KParts::ReadOnlyPart*>(it.current());
 
470
                if (ro_part && url == ro_part->url())
 
471
                {
 
472
                        return ro_part;
 
473
                }
 
474
                ++it;
 
475
        }
 
476
        return 0;
 
477
}
 
478
 
 
479
bool BookmarksPart::partIsSane( KParts::ReadOnlyPart * ro_part )
 
480
{
 
481
        return ( ro_part != 0 ) &&
 
482
                        partController()->parts()->contains( ro_part) &&
 
483
                        !ro_part->url().path().isEmpty();
 
484
}
 
485
 
 
486
void BookmarksPart::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber )
 
487
{
 
488
        kdDebug() << k_funcinfo << endl;
 
489
 
 
490
        if ( pagenumber == BOOKMARKSETTINGSPAGE )
 
491
        {
 
492
                BookmarkSettings * w = new BookmarkSettings( this, page );
 
493
                connect( dlg, SIGNAL(okClicked()), w, SLOT(slotAccept()) );
 
494
        }
 
495
}
 
496
 
 
497
////////////////////////////////////////////
 
498
 
 
499
QStringList BookmarksPart::getContextFromStream( QTextStream & istream, unsigned int line, unsigned int context )
 
500
{
 
501
        kdDebug() << k_funcinfo << endl;
 
502
 
 
503
        int startline = context > line ? 0 : line - context;
 
504
        int endline = line + context;
 
505
 
 
506
        int n = 0;
 
507
        QStringList list;
 
508
        while ( !istream.atEnd() )
 
509
        {
 
510
                QString templine = istream.readLine();
 
511
                if ( (n >= startline) && ( n <= endline ) )
 
512
                {
 
513
                        list << templine;
 
514
                }
 
515
                n++;
 
516
        }
 
517
 
 
518
        // maybe pad empty lines to the tail
 
519
        while( n < endline )
 
520
        {
 
521
                list.append( " " );
 
522
                n++;
 
523
        }
 
524
 
 
525
        // maybe pad empty lines to the head
 
526
        while( list.count() < ( context * 2 + 1) )
 
527
        {
 
528
                list.prepend( " " );
 
529
        }
 
530
 
 
531
        return list;
 
532
}
 
533
 
 
534
QStringList BookmarksPart::getContext( KURL const & url, unsigned int line, unsigned int context )
 
535
{
 
536
        // if the file is open - get the line from the editor buffer
 
537
        if ( KTextEditor::EditInterface * ei = dynamic_cast<KTextEditor::EditInterface*>( partForURL( url ) ) )
 
538
        {
 
539
                kdDebug() << "the file is open - get the line from the editor buffer" << endl;
 
540
 
 
541
                QString ibuffer = ei->text();
 
542
                QTextStream istream( &ibuffer, IO_ReadOnly );
 
543
                return getContextFromStream( istream, line, context );
 
544
        }
 
545
        else if ( url.isLocalFile() ) // else the file is not open - get the line from the file on disk
 
546
        {
 
547
                kdDebug() << "the file is not open - get the line from the file on disk" << endl;
 
548
 
 
549
                QFile file( url.path() );
 
550
                QString buffer;
 
551
 
 
552
                if ( file.open( IO_ReadOnly ) )
 
553
                {
 
554
                        QTextStream istream( &file );
 
555
                        return getContextFromStream( istream, line, context );
 
556
                }
 
557
        }
 
558
        return QStringList( i18n("Could not find file") );
 
559
}
 
560
 
 
561
BookmarksConfig * BookmarksPart::config( )
 
562
{
 
563
        return _config;
 
564
}
 
565
 
 
566
#include "bookmarks_part.moc"
 
567
 
 
568
// kate: space-indent off; indent-width 4; tab-width 4; show-tabs off;