00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "bookmarkmanager.h"
00011
00012
00013 #include <qhash.h>
00014 #include <qset.h>
00015 #include <kbookmarkmanager.h>
00016 #include <kbookmarkmenu.h>
00017 #include <kdebug.h>
00018 #include <kglobal.h>
00019 #include <kstandarddirs.h>
00020
00021
00022 #include "document_p.h"
00023 #include "observer.h"
00024
00025 using namespace Okular;
00026
00027 #define foreachObserver( cmd ) {\
00028 QMap< int, DocumentObserver * >::const_iterator it = d->document->m_observers.begin(), end = d->document->m_observers.end();\
00029 for ( ; it != end ; ++ it ) { (*it)-> cmd ; } }
00030
00031 class OkularBookmarkAction : public KBookmarkAction
00032 {
00033 public:
00034 OkularBookmarkAction( const Okular::DocumentViewport& vp, const KBookmark& bk, KBookmarkOwner* owner, QObject *parent )
00035 : KBookmarkAction( bk, owner, parent )
00036 {
00037 if ( vp.isValid() )
00038 setText( QString::number( vp.pageNumber + 1 ) + " - " + text() );
00039 }
00040 };
00041
00042 class BookmarkManager::Private : public KBookmarkOwner
00043 {
00044 public:
00045 Private( BookmarkManager * qq )
00046 : KBookmarkOwner(), q( qq ), document( 0 ), manager( 0 )
00047 {
00048 }
00049
00050 ~Private()
00051 {
00052 knownFiles.clear();
00053
00054
00055 }
00056
00057 virtual QString currentUrl() const;
00058 virtual QString currentTitle() const;
00059 virtual bool enableOption(BookmarkOption option) const;
00060 virtual void openBookmark( const KBookmark & bm, Qt::MouseButtons, Qt::KeyboardModifiers );
00061
00062 BookmarkManager * q;
00063 KUrl url;
00064 QSet<int> urlBookmarks;
00065 DocumentPrivate * document;
00066 QString file;
00067 KBookmarkManager * manager;
00068 QHash<KUrl, KBookmarkGroup> knownFiles;
00069 };
00070
00071 BookmarkManager::BookmarkManager( DocumentPrivate * document )
00072 : QObject( document->m_parent ), d( new Private( this ) )
00073 {
00074 setObjectName( "Okular::BookmarkManager" );
00075
00076 d->document = document;
00077
00078 d->file = KStandardDirs::locateLocal( "data", "okular/bookmarks.xml" );
00079
00080 d->manager = KBookmarkManager::managerForFile( d->file, "okular" );
00081 d->manager->setEditorOptions( KGlobal::caption(), false );
00082 d->manager->setUpdate( true );
00083 }
00084
00085 BookmarkManager::~BookmarkManager()
00086 {
00087 save();
00088 delete d;
00089 }
00090
00091
00092 QString BookmarkManager::Private::currentUrl() const
00093 {
00094 return url.prettyUrl();
00095 }
00096
00097 QString BookmarkManager::Private::currentTitle() const
00098 {
00099 return url.isLocalFile() ? url.path() : url.prettyUrl();
00100 }
00101
00102 bool BookmarkManager::Private::enableOption(BookmarkOption option) const
00103 {
00104 Q_UNUSED( option )
00105 return false;
00106 }
00107
00108 void BookmarkManager::Private::openBookmark( const KBookmark & bm, Qt::MouseButtons, Qt::KeyboardModifiers )
00109 {
00110 emit q->openUrl( bm.url() );
00111 }
00112
00113
00114 KUrl::List BookmarkManager::files() const
00115 {
00116 KUrl::List ret;
00117 KBookmarkGroup group = d->manager->root();
00118 for ( KBookmark bm = group.first(); !bm.isNull(); bm = group.next( bm ) )
00119 {
00120 if ( bm.isSeparator() || !bm.isGroup() )
00121 continue;
00122
00123 ret.append( KUrl( bm.fullText() ) );
00124 }
00125 return ret;
00126 }
00127
00128 KBookmark::List BookmarkManager::bookmarks( const KUrl& url ) const
00129 {
00130 KBookmark::List ret;
00131 KBookmarkGroup group = d->manager->root();
00132 for ( KBookmark bm = group.first(); !bm.isNull(); bm = group.next( bm ) )
00133 {
00134 if ( !bm.isGroup() || KUrl( bm.fullText() ) != url )
00135 continue;
00136
00137 KBookmarkGroup group = bm.toGroup();
00138 for ( KBookmark b = group.first(); !b.isNull(); b = group.next( b ) )
00139 {
00140 if ( b.isSeparator() || b.isGroup() )
00141 continue;
00142
00143 ret.append( b );
00144 }
00145 break;
00146 }
00147 return ret;
00148 }
00149
00150 void BookmarkManager::save() const
00151 {
00152 d->manager->save( false );
00153 emit const_cast<BookmarkManager*>( this )->saved();
00154 }
00155
00156 static QHash<KUrl, KBookmarkGroup>::iterator find( QHash<KUrl, KBookmarkGroup>& files, const KUrl& url, KBookmarkManager * manager, bool doCreate )
00157 {
00158 QHash<KUrl, KBookmarkGroup>::iterator it = files.find( url );
00159 if ( it == files.end() )
00160 {
00161
00162
00163
00164 bool found = false;
00165 KBookmarkGroup root = manager->root();
00166 for ( KBookmark bm = root.first(); !found && !bm.isNull(); bm = root.next( bm ) )
00167 {
00168 if ( bm.isSeparator() || !bm.isGroup() )
00169 continue;
00170
00171 KUrl tmpurl( bm.fullText() );
00172 if ( tmpurl == url )
00173 {
00174
00175 it = files.insert( url, bm.toGroup() );
00176 found = true;
00177 break;
00178 }
00179 }
00180 if ( !found && doCreate )
00181 {
00182
00183
00184 QString purl = url.isLocalFile() ? url.path() : url.prettyUrl();
00185 it = files.insert( url, root.createNewFolder( purl ) );
00186 }
00187 }
00188 return it;
00189 }
00190
00191 void BookmarkManager::addBookmark( int n )
00192 {
00193 if ( n >= 0 && n < (int)d->document->m_pagesVector.count() )
00194 {
00195 if ( setPageBookmark( n ) )
00196 foreachObserver( notifyPageChanged( n, DocumentObserver::Bookmark ) );
00197 }
00198 }
00199
00200 bool BookmarkManager::addBookmark( const KUrl& referurl, const Okular::DocumentViewport& vp, const QString& title )
00201 {
00202 if ( !referurl.isValid() || !vp.isValid() )
00203 return false;
00204
00205 QHash<KUrl, KBookmarkGroup>::iterator it = find( d->knownFiles, referurl, d->manager, true );
00206 Q_ASSERT( it != d->knownFiles.end() );
00207
00208 QString newtitle;
00209 if ( title.isEmpty() )
00210 {
00211
00212
00213
00214 int count = 0;
00215 for ( KBookmark bm = it.value().first(); !bm.isNull(); bm = it.value().next( bm ) )
00216 {
00217 if ( !bm.isSeparator() && !bm.isGroup() )
00218 ++count;
00219 }
00220 newtitle = QString( "#%1" ).arg( count + 1 );
00221 }
00222 else
00223 newtitle = title;
00224 KUrl newurl = referurl;
00225 newurl.setHTMLRef( vp.toString() );
00226 it.value().addBookmark( newtitle, newurl, QString() );
00227 foreachObserver( notifyPageChanged( vp.pageNumber, DocumentObserver::Bookmark ) );
00228 return true;
00229 }
00230
00231 void BookmarkManager::removeBookmark( int n )
00232 {
00233 if ( n >= 0 && n < (int)d->document->m_pagesVector.count() )
00234 {
00235 if ( removePageBookmark( n ) )
00236 foreachObserver( notifyPageChanged( n, DocumentObserver::Bookmark ) );
00237 }
00238 }
00239
00240 int BookmarkManager::removeBookmark( const KUrl& referurl, const KBookmark& bm )
00241 {
00242 if ( !referurl.isValid() || bm.isNull() || bm.isGroup() || bm.isSeparator() )
00243 return -1;
00244
00245 DocumentViewport vp( bm.url().htmlRef() );
00246 if ( !vp.isValid() )
00247 return -1;
00248
00249 QHash<KUrl, KBookmarkGroup>::iterator it = find( d->knownFiles, referurl, d->manager, false );
00250 if ( it == d->knownFiles.end() )
00251 return -1;
00252
00253 it.value().deleteBookmark( bm );
00254
00255 foreachObserver( notifyPageChanged( vp.pageNumber, DocumentObserver::Bookmark ) );
00256
00257 return vp.pageNumber;
00258 }
00259
00260 QList< QAction * > BookmarkManager::actionsForUrl( const KUrl& url ) const
00261 {
00262 QList< QAction * > ret;
00263 KBookmarkGroup group = d->manager->root();
00264 for ( KBookmark bm = group.first(); !bm.isNull(); bm = group.next( bm ) )
00265 {
00266 if ( !bm.isGroup() || KUrl( bm.fullText() ) != url )
00267 continue;
00268
00269 KBookmarkGroup group = bm.toGroup();
00270 for ( KBookmark b = group.first(); !b.isNull(); b = group.next( b ) )
00271 {
00272 if ( b.isSeparator() || b.isGroup() )
00273 continue;
00274
00275 ret.append( new OkularBookmarkAction( DocumentViewport( b.url().htmlRef() ), b, d, 0 ) );
00276 }
00277 break;
00278 }
00279 return ret;
00280 }
00281
00282 void BookmarkManager::setUrl( const KUrl& url )
00283 {
00284 d->url = url;
00285 d->urlBookmarks.clear();
00286 QHash<KUrl, KBookmarkGroup>::iterator it = find( d->knownFiles, url, d->manager, false );
00287 if ( it != d->knownFiles.end() )
00288 {
00289 for ( KBookmark bm = it.value().first(); !bm.isNull(); bm = it.value().next( bm ) )
00290 {
00291 if ( bm.isSeparator() || bm.isGroup() )
00292 continue;
00293
00294 DocumentViewport vp( bm.url().htmlRef() );
00295 if ( !vp.isValid() )
00296 continue;
00297
00298 d->urlBookmarks.insert( vp.pageNumber );
00299 }
00300 }
00301 }
00302
00303 bool BookmarkManager::setPageBookmark( int page )
00304 {
00305 QHash<KUrl, KBookmarkGroup>::iterator it = find( d->knownFiles, d->url, d->manager, true );
00306 Q_ASSERT( it != d->knownFiles.end() );
00307
00308 bool found = false;
00309 bool added = false;
00310 for ( KBookmark bm = it.value().first(); !found && !bm.isNull(); bm = it.value().next( bm ) )
00311 {
00312 if ( bm.isSeparator() || bm.isGroup() )
00313 continue;
00314
00315 DocumentViewport vp( bm.url().htmlRef() );
00316 if ( vp.isValid() && vp.pageNumber == page )
00317 found = true;
00318
00319 }
00320 if ( !found )
00321 {
00322 d->urlBookmarks.insert( page );
00323 DocumentViewport vp;
00324 vp.pageNumber = page;
00325 KUrl newurl = d->url;
00326 newurl.setHTMLRef( vp.toString() );
00327 it.value().addBookmark( QString::fromLatin1( "#" ) + QString::number( vp.pageNumber + 1 ), newurl, QString() );
00328 added = true;
00329 }
00330 return added;
00331 }
00332
00333 bool BookmarkManager::removePageBookmark( int page )
00334 {
00335 QHash<KUrl, KBookmarkGroup>::iterator it = find( d->knownFiles, d->url, d->manager, false );
00336 if ( it == d->knownFiles.end() )
00337 return false;
00338
00339 bool found = false;
00340 for ( KBookmark bm = it.value().first(); !found && !bm.isNull(); bm = it.value().next( bm ) )
00341 {
00342 if ( bm.isSeparator() || bm.isGroup() )
00343 continue;
00344
00345 DocumentViewport vp( bm.url().htmlRef() );
00346 if ( vp.isValid() && vp.pageNumber == page )
00347 {
00348 found = true;
00349 it.value().deleteBookmark( bm );
00350 d->urlBookmarks.remove( page );
00351 }
00352 }
00353 return found;
00354 }
00355
00356 bool BookmarkManager::isBookmarked( int page ) const
00357 {
00358 return d->urlBookmarks.contains( page );
00359 }
00360
00361 #include "bookmarkmanager.moc"