1 /***************************************************************************
2 * Copyright (C) 2006 by Pino Toscano <pino@kde.org> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "bookmarklist.h"
15 #include <qheaderview.h>
18 #include <qtreewidget.h>
24 #include <ktreewidgetsearchline.h>
26 #include "pageitemdelegate.h"
27 #include "core/action.h"
28 #include "core/bookmarkmanager.h"
29 #include "core/document.h"
31 static const int BookmarkItemType
= QTreeWidgetItem::UserType
+ 1;
32 static const int FileItemType
= QTreeWidgetItem::UserType
+ 2;
33 static const int UrlRole
= Qt::UserRole
+ 1;
35 class BookmarkItem
: public QTreeWidgetItem
38 BookmarkItem( const KBookmark
& bm
)
39 : QTreeWidgetItem( BookmarkItemType
), m_bookmark( bm
)
41 setFlags( Qt::ItemIsSelectable
| Qt::ItemIsEnabled
| Qt::ItemIsEditable
);
42 m_url
= m_bookmark
.url();
43 m_viewport
= Okular::DocumentViewport( m_url
.htmlRef() );
44 m_url
.setHTMLRef( QString() );
45 setText( 0, m_bookmark
.fullText() );
46 if ( m_viewport
.isValid() )
47 setData( 0, PageItemDelegate::PageRole
, QString::number( m_viewport
.pageNumber
+ 1 ) );
50 virtual QVariant
data( int column
, int role
) const
55 return m_bookmark
.fullText();
57 return QTreeWidgetItem::data( column
, role
);
65 const Okular::DocumentViewport
& viewport() const
78 Okular::DocumentViewport m_viewport
;
82 BookmarkList::BookmarkList( Okular::Document
*document
, QWidget
*parent
)
83 : QWidget( parent
), m_document( document
), m_currentDocumentItem( 0 )
85 QVBoxLayout
*mainlay
= new QVBoxLayout( this );
86 mainlay
->setMargin( 0 );
87 mainlay
->setSpacing( 6 );
89 m_searchLine
= new KTreeWidgetSearchLine( this );
90 mainlay
->addWidget( m_searchLine
);
92 m_tree
= new QTreeWidget( this );
93 mainlay
->addWidget( m_tree
);
95 cols
.append( "Bookmarks" );
96 m_tree
->setContextMenuPolicy( Qt::CustomContextMenu
);
97 m_tree
->setHeaderLabels( cols
);
98 m_tree
->setSortingEnabled( false );
99 m_tree
->setRootIsDecorated( true );
100 m_tree
->setAlternatingRowColors( true );
101 m_tree
->setItemDelegate( new PageItemDelegate( m_tree
) );
102 m_tree
->header()->hide();
103 m_tree
->setSelectionBehavior( QAbstractItemView::SelectRows
);
104 m_tree
->setEditTriggers( QAbstractItemView::EditKeyPressed
);
105 connect( m_tree
, SIGNAL( itemActivated( QTreeWidgetItem
*, int ) ), this, SLOT( slotExecuted( QTreeWidgetItem
* ) ) );
106 connect( m_tree
, SIGNAL( customContextMenuRequested( const QPoint
& ) ), this, SLOT( slotContextMenu( const QPoint
& ) ) );
107 m_searchLine
->addTreeWidget( m_tree
);
109 QToolBar
* bookmarkController
= new QToolBar( this );
110 mainlay
->addWidget( bookmarkController
);
111 bookmarkController
->setObjectName( "BookmarkControlBar" );
112 // change toolbar appearance
113 bookmarkController
->setIconSize( QSize( 16, 16 ) );
114 bookmarkController
->setMovable( false );
115 QSizePolicy sp
= bookmarkController
->sizePolicy();
116 sp
.setVerticalPolicy( QSizePolicy::Minimum
);
117 bookmarkController
->setSizePolicy( sp
);
118 // insert a togglebutton [show only bookmarks in the current document]
119 m_showBoomarkOnlyAction
= bookmarkController
->addAction( KIcon( "bookmarks" ), i18n( "Current document only" ) );
120 m_showBoomarkOnlyAction
->setCheckable( true );
121 connect( m_showBoomarkOnlyAction
, SIGNAL( toggled( bool ) ), this, SLOT( slotFilterBookmarks( bool ) ) );
123 connect( m_document
->bookmarkManager(), SIGNAL( bookmarksChanged( const KUrl
& ) ), this, SLOT( slotBookmarksChanged( const KUrl
& ) ) );
125 rebuildTree( m_showBoomarkOnlyAction
->isChecked() );
128 BookmarkList::~BookmarkList()
132 uint
BookmarkList::observerId() const
134 return BOOKMARKLIST_ID
;
137 void BookmarkList::notifySetup( const QVector
< Okular::Page
* > & pages
, int setupFlags
)
139 if ( !( setupFlags
& Okular::DocumentObserver::DocumentChanged
) )
143 m_searchLine
->clear();
145 if ( m_showBoomarkOnlyAction
->isChecked() )
147 rebuildTree( m_showBoomarkOnlyAction
->isChecked() );
151 disconnect( m_tree
, SIGNAL( itemChanged( QTreeWidgetItem
*, int ) ), this, SLOT( slotChanged( QTreeWidgetItem
* ) ) );
152 if ( m_currentDocumentItem
&& m_currentDocumentItem
!= m_tree
->invisibleRootItem() )
154 m_currentDocumentItem
->setIcon( 0, QIcon() );
156 m_currentDocumentItem
= itemForUrl( m_document
->currentDocument() );
157 if ( m_currentDocumentItem
&& m_currentDocumentItem
!= m_tree
->invisibleRootItem() )
159 m_currentDocumentItem
->setIcon( 0, KIcon( "bookmarks" ) );
160 m_currentDocumentItem
->setExpanded( true );
162 connect( m_tree
, SIGNAL( itemChanged( QTreeWidgetItem
*, int ) ), this, SLOT( slotChanged( QTreeWidgetItem
* ) ) );
166 void BookmarkList::slotFilterBookmarks( bool on
)
171 void BookmarkList::slotExecuted( QTreeWidgetItem
* item
)
173 BookmarkItem
* bmItem
= dynamic_cast<BookmarkItem
*>( item
);
174 if ( !bmItem
|| !bmItem
->viewport().isValid() )
180 void BookmarkList::slotChanged( QTreeWidgetItem
* item
)
182 BookmarkItem
* bmItem
= dynamic_cast<BookmarkItem
*>( item
);
183 if ( !bmItem
|| !bmItem
->viewport().isValid() )
186 bmItem
->bookmark().setFullText( bmItem
->text( 0 ) );
187 m_document
->bookmarkManager()->save();
190 void BookmarkList::slotContextMenu( const QPoint
& p
)
192 QTreeWidgetItem
* item
= m_tree
->itemAt( p
);
193 BookmarkItem
* bmItem
= item
? dynamic_cast<BookmarkItem
*>( item
) : 0;
194 if ( !bmItem
|| !bmItem
->viewport().isValid() )
198 QAction
* gotobm
= menu
.addAction( i18n( "Go to This Bookmark" ) );
199 QAction
* editbm
= menu
.addAction( KIcon( "edit-rename" ), i18n( "Rename Bookmark" ) );
200 QAction
* removebm
= menu
.addAction( KIcon( "list-remove" ), i18n( "Remove Bookmark" ) );
201 QAction
* res
= menu
.exec( QCursor::pos() );
207 else if ( res
== editbm
)
208 m_tree
->editItem( item
, 0 );
209 else if ( res
== removebm
)
210 m_document
->bookmarkManager()->removeBookmark( bmItem
->url(), bmItem
->bookmark() );
213 void BookmarkList::slotBookmarksChanged( const KUrl
& url
)
215 // special case here, as m_currentDocumentItem could represent
216 // the invisible root item
217 if ( url
== m_document
->currentDocument() )
219 selectiveUrlUpdate( m_document
->currentDocument(), m_currentDocumentItem
);
223 // we are showing the bookmarks for the current document only
224 if ( m_showBoomarkOnlyAction
->isChecked() )
227 QTreeWidgetItem
*item
= itemForUrl( url
);
230 selectiveUrlUpdate( url
, item
);
234 QList
<QTreeWidgetItem
*> createItems( const KUrl
& baseurl
, const KBookmark::List
& bmlist
)
237 QList
<QTreeWidgetItem
*> ret
;
238 foreach ( const KBookmark
& bm
, bmlist
)
240 // kDebug().nospace() << "checking '" << tmp << "'";
241 // kDebug().nospace() << " vs '" << baseurl << "'";
242 // TODO check that bm and baseurl are the same (#ref excluded)
243 QTreeWidgetItem
* item
= new BookmarkItem( bm
);
249 void BookmarkList::rebuildTree( bool filter
)
251 // disconnect and reconnect later, otherwise we'll get many itemChanged()
252 // signals for all the current items
253 disconnect( m_tree
, SIGNAL( itemChanged( QTreeWidgetItem
*, int ) ), this, SLOT( slotChanged( QTreeWidgetItem
* ) ) );
255 m_currentDocumentItem
= 0;
258 KUrl::List urls
= m_document
->bookmarkManager()->files();
261 if ( m_document
->isOpened() )
263 foreach ( const KUrl
& url
, urls
)
265 if ( url
== m_document
->currentDocument() )
267 m_tree
->addTopLevelItems( createItems( url
, m_document
->bookmarkManager()->bookmarks( url
) ) );
268 m_currentDocumentItem
= m_tree
->invisibleRootItem();
276 QTreeWidgetItem
* currenturlitem
= 0;
277 foreach ( const KUrl
& url
, urls
)
279 QList
<QTreeWidgetItem
*> subitems
= createItems( url
, m_document
->bookmarkManager()->bookmarks( url
) );
280 if ( !subitems
.isEmpty() )
282 QTreeWidgetItem
* item
= new QTreeWidgetItem( m_tree
, FileItemType
);
283 QString fileString
= url
.isLocalFile() ? url
.path() : url
.prettyUrl();
284 item
->setText( 0, fileString
);
285 item
->setToolTip( 0, i18ncp( "%1 is the file name", "%1\n\nOne bookmark", "%1\n\n%2 bookmarks", fileString
, subitems
.count() ) );
286 item
->setData( 0, UrlRole
, qVariantFromValue( url
) );
287 item
->addChildren( subitems
);
288 if ( !currenturlitem
&& url
== m_document
->currentDocument() )
290 currenturlitem
= item
;
294 if ( currenturlitem
)
296 currenturlitem
->setExpanded( true );
297 currenturlitem
->setIcon( 0, KIcon( "bookmarks" ) );
298 m_tree
->scrollToItem( currenturlitem
, QAbstractItemView::PositionAtTop
);
299 m_currentDocumentItem
= currenturlitem
;
303 connect( m_tree
, SIGNAL( itemChanged( QTreeWidgetItem
*, int ) ), this, SLOT( slotChanged( QTreeWidgetItem
* ) ) );
306 void BookmarkList::goTo( BookmarkItem
* item
)
308 if ( item
->url() == m_document
->currentDocument() )
310 m_document
->setViewport( item
->viewport() );
314 Okular::GotoAction
action( item
->url().pathOrUrl(), item
->viewport() );
315 m_document
->processAction( &action
);
319 void BookmarkList::selectiveUrlUpdate( const KUrl
& url
, QTreeWidgetItem
*& item
)
321 disconnect( m_tree
, SIGNAL( itemChanged( QTreeWidgetItem
*, int ) ), this, SLOT( slotChanged( QTreeWidgetItem
* ) ) );
323 const KBookmark::List urlbookmarks
= m_document
->bookmarkManager()->bookmarks( url
);
324 if ( urlbookmarks
.isEmpty() )
326 if ( item
!= m_tree
->invisibleRootItem() )
328 m_tree
->invisibleRootItem()->removeChild( item
);
333 for ( int i
= item
->childCount(); i
>= 0; --i
)
335 item
->removeChild( item
->child( i
) );
341 const QString fileString
= url
.isLocalFile() ? url
.path() : url
.prettyUrl();
344 for ( int i
= item
->childCount(); i
>= 0; --i
)
346 item
->removeChild( item
->child( i
) );
351 item
= new QTreeWidgetItem( m_tree
, FileItemType
);
352 item
->setIcon( 0, KIcon( "bookmarks" ) );
353 item
->setExpanded( true );
354 item
->setText( 0, fileString
);
356 item
->addChildren( createItems( url
, urlbookmarks
) );
357 if ( item
!= m_tree
->invisibleRootItem() )
359 item
->setToolTip( 0, i18ncp( "%1 is the file name", "%1\n\nOne bookmark", "%1\n\n%2 bookmarks", fileString
, item
->childCount() ) );
363 connect( m_tree
, SIGNAL( itemChanged( QTreeWidgetItem
*, int ) ), this, SLOT( slotChanged( QTreeWidgetItem
* ) ) );
366 QTreeWidgetItem
* BookmarkList::itemForUrl( const KUrl
& url
) const
368 const int count
= m_tree
->topLevelItemCount();
369 for ( int i
= 0; i
< count
; ++i
)
371 QTreeWidgetItem
*item
= m_tree
->topLevelItem( i
);
372 const KUrl itemurl
= item
->data( 0, UrlRole
).value
< KUrl
>();
373 if ( itemurl
.isValid() && itemurl
== url
)
381 #include "bookmarklist.moc"