1 /***************************************************************************
2 * Copyright (C) 2005 by Enrico Ros <eros.kde@email.it> *
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 "side_reviews.h"
13 #include <QtCore/QStringList>
14 #include <QtGui/QHeaderView>
15 #include <QtGui/QLayout>
16 #include <QtGui/QPaintEvent>
17 #include <QtGui/QPainter>
18 #include <QtGui/QSizePolicy>
19 #include <QtGui/QTextDocument>
20 #include <QtGui/QToolBar>
21 #include <QtGui/QTreeView>
25 #include <kiconloader.h>
29 #include "core/annotations.h"
30 #include "core/document.h"
31 #include "core/page.h"
33 #include "annotationpopup.h"
34 #include "annotationproxymodels.h"
35 #include "annotationmodel.h"
36 #include "ktreeviewsearchline.h"
38 class TreeView
: public QTreeView
41 TreeView( Okular::Document
*document
, QWidget
*parent
= 0 )
42 : QTreeView( parent
), m_document( document
)
47 virtual void paintEvent( QPaintEvent
*event
)
49 bool hasAnnotations
= false;
50 for ( uint i
= 0; i
< m_document
->pages(); ++i
)
51 if ( m_document
->page( i
)->hasAnnotations() ) {
52 hasAnnotations
= true;
55 if ( !hasAnnotations
) {
56 QPainter
p( viewport() );
57 p
.setRenderHint( QPainter::Antialiasing
, true );
58 p
.setClipRect( event
->rect() );
60 QTextDocument document
;
61 document
.setHtml( i18n( "<div align=center><h3>No annotations</h3>"
62 "To create new annotations press F6 or select <i>Tools -> Review</i>"
63 " from the menu.</div>" ) );
64 document
.setTextWidth( width() - 50 );
66 const uint w
= document
.size().width() + 20;
67 const uint h
= document
.size().height() + 20;
69 p
.setBrush( palette().background() );
70 p
.translate( 0.5, 0.5 );
71 p
.drawRoundRect( 15, 15, w
, h
, (8*200)/w
, (8*200)/h
);
72 p
.translate( 20, 20 );
73 document
.drawContents( &p
);
76 QTreeView::paintEvent( event
);
81 Okular::Document
*m_document
;
85 Reviews::Reviews( QWidget
* parent
, Okular::Document
* document
)
86 : QWidget( parent
), m_document( document
)
88 // create widgets and layout them vertically
89 QVBoxLayout
* vLayout
= new QVBoxLayout( this );
90 vLayout
->setMargin( 0 );
91 vLayout
->setSpacing( 6 );
93 m_view
= new TreeView( m_document
, this );
94 m_view
->setAlternatingRowColors( true );
95 m_view
->setSelectionMode( QAbstractItemView::ExtendedSelection
);
96 m_view
->header()->hide();
98 QToolBar
*toolBar
= new QToolBar( this );
99 toolBar
->setObjectName( "reviewOptsBar" );
100 QSizePolicy sp
= toolBar
->sizePolicy();
101 sp
.setVerticalPolicy( QSizePolicy::Minimum
);
102 toolBar
->setSizePolicy( sp
);
104 m_model
= new AnnotationModel( m_document
, m_view
);
106 m_filterProxy
= new PageFilterProxyModel( m_view
);
107 m_groupProxy
= new PageGroupProxyModel( m_view
);
108 m_authorProxy
= new AuthorGroupProxyModel( m_view
);
110 m_filterProxy
->setSourceModel( m_model
);
111 m_groupProxy
->setSourceModel( m_filterProxy
);
112 m_authorProxy
->setSourceModel( m_groupProxy
);
115 m_view
->setModel( m_authorProxy
);
117 vLayout
->addWidget( new KTreeViewSearchLine( this, m_view
) );
118 vLayout
->addWidget( m_view
);
119 vLayout
->addWidget( toolBar
);
121 toolBar
->setIconSize( QSize( 16, 16 ) );
122 toolBar
->setMovable( false );
124 QAction
* groupByPageAction
= toolBar
->addAction( KIcon( "text-x-generic" ), i18n( "Group by Page" ) );
125 groupByPageAction
->setCheckable( true );
126 connect( groupByPageAction
, SIGNAL( toggled( bool ) ), this, SLOT( slotPageEnabled( bool ) ) );
127 groupByPageAction
->setChecked( Okular::Settings::groupByPage() );
128 // - add Author button
129 QAction
* groupByAuthorAction
= toolBar
->addAction( KIcon( "user-identity" ), i18n( "Group by Author" ) );
130 groupByAuthorAction
->setCheckable( true );
131 connect( groupByAuthorAction
, SIGNAL( toggled( bool ) ), this, SLOT( slotAuthorEnabled( bool ) ) );
132 groupByAuthorAction
->setChecked( Okular::Settings::groupByAuthor() );
135 toolBar
->addSeparator();
136 // - add Current Page Only button
137 QAction
* curPageOnlyAction
= toolBar
->addAction( KIcon( "arrow-down" ), i18n( "Show reviews for current page only" ) );
138 curPageOnlyAction
->setCheckable( true );
139 connect( curPageOnlyAction
, SIGNAL( toggled( bool ) ), this, SLOT( slotCurrentPageOnly( bool ) ) );
140 curPageOnlyAction
->setChecked( Okular::Settings::currentPageOnly() );
142 connect( m_view
, SIGNAL( activated( const QModelIndex
& ) ),
143 this, SLOT( activated( const QModelIndex
& ) ) );
145 m_view
->setContextMenuPolicy( Qt::CustomContextMenu
);
146 connect( m_view
, SIGNAL( customContextMenuRequested( const QPoint
& ) ),
147 this, SLOT( contextMenuRequested( const QPoint
& ) ) );
153 m_document
->removeObserver( this );
156 //BEGIN DocumentObserver Notifies
157 void Reviews::notifyViewportChanged( bool )
159 m_filterProxy
->setCurrentPage( m_document
->currentPage() );
161 //END DocumentObserver Notifies
163 //BEGIN GUI Slots -> requestListViewUpdate
164 void Reviews::slotPageEnabled( bool on
)
166 // store toggle state in Settings and update the listview
167 Okular::Settings::setGroupByPage( on
);
168 m_groupProxy
->groupByPage( on
);
173 void Reviews::slotAuthorEnabled( bool on
)
175 // store toggle state in Settings and update the listview
176 Okular::Settings::setGroupByAuthor( on
);
177 m_authorProxy
->groupByAuthor( on
);
182 void Reviews::slotCurrentPageOnly( bool on
)
184 // store toggle state in Settings and update the listview
185 Okular::Settings::setCurrentPageOnly( on
);
186 m_filterProxy
->groupByCurrentPage( on
);
193 void Reviews::activated( const QModelIndex
&index
)
195 const QModelIndex authorIndex
= m_authorProxy
->mapToSource( index
);
196 const QModelIndex filterIndex
= m_groupProxy
->mapToSource( authorIndex
);
197 const QModelIndex annotIndex
= m_filterProxy
->mapToSource( filterIndex
);
199 Okular::Annotation
*annotation
= m_model
->annotationForIndex( annotIndex
);
203 int pageNumber
= m_model
->data( annotIndex
, AnnotationModel::PageRole
).toInt();
204 const Okular::Page
* page
= m_document
->page( pageNumber
);
206 // calculating the right coordinates to center the view on the annotation
207 QRect rect
= Okular::AnnotationUtils::annotationGeometry( annotation
, page
->width(), page
->height() );
208 Okular::NormalizedRect
nr( rect
, (int)page
->width(), (int)page
->height() );
209 // set the viewport parameters
210 Okular::DocumentViewport vp
;
211 vp
.pageNumber
= pageNumber
;
212 vp
.rePos
.enabled
= true;
213 vp
.rePos
.pos
= Okular::DocumentViewport::Center
;
214 vp
.rePos
.normalizedX
= ( nr
.right
+ nr
.left
) / 2.0;
215 vp
.rePos
.normalizedY
= ( nr
.bottom
+ nr
.top
) / 2.0;
216 // setting the viewport
217 m_document
->setViewport( vp
, -1, true );
220 QModelIndexList
Reviews::retrieveAnnotations(const QModelIndex
& idx
) const
225 if ( idx
.model()->hasChildren( idx
) )
227 int rowCount
= idx
.model()->rowCount( idx
);
228 for ( int i
= 0; i
< rowCount
; i
++ )
230 ret
+= retrieveAnnotations( idx
.child( i
, idx
.column() ) );
242 void Reviews::contextMenuRequested( const QPoint
&pos
)
244 AnnotationPopup
popup( m_document
, this );
245 connect( &popup
, SIGNAL( setAnnotationWindow( Okular::Annotation
* ) ),
246 this, SIGNAL( setAnnotationWindow( Okular::Annotation
* ) ) );
247 connect( &popup
, SIGNAL( removeAnnotationWindow( Okular::Annotation
* ) ),
248 this, SIGNAL( removeAnnotationWindow( Okular::Annotation
* ) ) );
250 QModelIndexList indexes
= m_view
->selectionModel()->selectedIndexes();
251 Q_FOREACH ( const QModelIndex
&index
, indexes
)
253 QModelIndexList annotations
= retrieveAnnotations(index
);
254 Q_FOREACH ( const QModelIndex
&idx
, annotations
)
256 const QModelIndex authorIndex
= m_authorProxy
->mapToSource( idx
);
257 const QModelIndex filterIndex
= m_groupProxy
->mapToSource( authorIndex
);
258 const QModelIndex annotIndex
= m_filterProxy
->mapToSource( filterIndex
);
259 Okular::Annotation
*annotation
= m_model
->annotationForIndex( annotIndex
);
262 const int pageNumber
= m_model
->data( annotIndex
, AnnotationModel::PageRole
).toInt();
263 popup
.addAnnotation( annotation
, pageNumber
);
268 popup
.exec( m_view
->viewport()->mapToGlobal( pos
) );
271 #include "side_reviews.moc"