diff --git a/ui/bookmarklist.cpp b/ui/bookmarklist.cpp index ebbf3787e..0c762a4e6 100644 --- a/ui/bookmarklist.cpp +++ b/ui/bookmarklist.cpp @@ -1,471 +1,472 @@ /*************************************************************************** * Copyright (C) 2006 by Pino Toscano * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "bookmarklist.h" // qt/kde includes #include #include #include #include #include #include #include #include #include #include #include #include "pageitemdelegate.h" #include "core/action.h" #include "core/bookmarkmanager.h" #include "core/document.h" static const int BookmarkItemType = QTreeWidgetItem::UserType + 1; static const int FileItemType = QTreeWidgetItem::UserType + 2; static const int UrlRole = Qt::UserRole + 1; class BookmarkItem : public QTreeWidgetItem { public: BookmarkItem( const KBookmark& bm ) : QTreeWidgetItem( BookmarkItemType ), m_bookmark( bm ) { setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable ); m_url = m_bookmark.url(); m_viewport = Okular::DocumentViewport( m_url.fragment(QUrl::FullyDecoded) ); m_url.setFragment( QString() ); setText( 0, m_bookmark.fullText() ); if ( m_viewport.isValid() ) setData( 0, PageItemDelegate::PageRole, QString::number( m_viewport.pageNumber + 1 ) ); } QVariant data( int column, int role ) const override { switch ( role ) { case Qt::ToolTipRole: return m_bookmark.fullText(); } return QTreeWidgetItem::data( column, role ); } bool operator<( const QTreeWidgetItem& other ) const override { if ( other.type() == BookmarkItemType ) { const BookmarkItem *cmp = static_cast< const BookmarkItem* >( &other ); return m_viewport < cmp->m_viewport; } return QTreeWidgetItem::operator<( other ); } KBookmark& bookmark() { return m_bookmark; } const Okular::DocumentViewport& viewport() const { return m_viewport; } QUrl url() const { return m_url; } private: KBookmark m_bookmark; QUrl m_url; Okular::DocumentViewport m_viewport; }; class FileItem : public QTreeWidgetItem { public: FileItem( const QUrl & url, QTreeWidget *tree, Okular::Document *document ) : QTreeWidgetItem( tree, FileItemType ) { setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable ); const QString fileString = document->bookmarkManager()->titleForUrl( url ); setText( 0, fileString ); setData( 0, UrlRole, qVariantFromValue( url ) ); } QVariant data( int column, int role ) const override { switch ( role ) { case Qt::ToolTipRole: return i18ncp( "%1 is the file name", "%1\n\nOne bookmark", "%1\n\n%2 bookmarks", text( 0 ), childCount() ); } return QTreeWidgetItem::data( column, role ); } }; BookmarkList::BookmarkList( Okular::Document *document, QWidget *parent ) : QWidget( parent ), m_document( document ), m_currentDocumentItem( nullptr ) { QVBoxLayout *mainlay = new QVBoxLayout( this ); mainlay->setMargin( 0 ); mainlay->setSpacing( 6 ); m_searchLine = new KTreeWidgetSearchLine( this ); mainlay->addWidget( m_searchLine ); + m_searchLine->setPlaceholderText(i18n( "Search..." )); m_tree = new QTreeWidget( this ); mainlay->addWidget( m_tree ); QStringList cols; cols.append( QStringLiteral("Bookmarks") ); m_tree->setContextMenuPolicy( Qt::CustomContextMenu ); m_tree->setHeaderLabels( cols ); m_tree->setSortingEnabled( false ); m_tree->setRootIsDecorated( true ); m_tree->setAlternatingRowColors( true ); m_tree->setItemDelegate( new PageItemDelegate( m_tree ) ); m_tree->header()->hide(); m_tree->setSelectionBehavior( QAbstractItemView::SelectRows ); m_tree->setEditTriggers( QAbstractItemView::EditKeyPressed ); connect(m_tree, &QTreeWidget::itemActivated, this, &BookmarkList::slotExecuted); connect(m_tree, &QTreeWidget::customContextMenuRequested, this, &BookmarkList::slotContextMenu); m_searchLine->addTreeWidget( m_tree ); QToolBar * bookmarkController = new QToolBar( this ); mainlay->addWidget( bookmarkController ); bookmarkController->setObjectName( QStringLiteral( "BookmarkControlBar" ) ); // change toolbar appearance bookmarkController->setIconSize( QSize( 16, 16 ) ); bookmarkController->setMovable( false ); QSizePolicy sp = bookmarkController->sizePolicy(); sp.setVerticalPolicy( QSizePolicy::Minimum ); bookmarkController->setSizePolicy( sp ); // insert a togglebutton [show only bookmarks in the current document] m_showBoomarkOnlyAction = bookmarkController->addAction( QIcon::fromTheme( QStringLiteral("bookmarks") ), i18n( "Current document only" ) ); m_showBoomarkOnlyAction->setCheckable( true ); connect(m_showBoomarkOnlyAction, &QAction::toggled, this, &BookmarkList::slotFilterBookmarks); connect( m_document->bookmarkManager(), &Okular::BookmarkManager::bookmarksChanged, this, &BookmarkList::slotBookmarksChanged ); rebuildTree( m_showBoomarkOnlyAction->isChecked() ); } BookmarkList::~BookmarkList() { m_document->removeObserver( this ); } void BookmarkList::notifySetup( const QVector< Okular::Page * > & pages, int setupFlags ) { Q_UNUSED( pages ); if ( !( setupFlags & Okular::DocumentObserver::UrlChanged ) ) return; // clear contents m_searchLine->clear(); if ( m_showBoomarkOnlyAction->isChecked() ) { rebuildTree( m_showBoomarkOnlyAction->isChecked() ); } else { disconnect(m_tree, &QTreeWidget::itemChanged, this, &BookmarkList::slotChanged); if ( m_currentDocumentItem && m_currentDocumentItem != m_tree->invisibleRootItem() ) { m_currentDocumentItem->setIcon( 0, QIcon() ); } m_currentDocumentItem = itemForUrl( m_document->currentDocument() ); if ( m_currentDocumentItem && m_currentDocumentItem != m_tree->invisibleRootItem() ) { m_currentDocumentItem->setIcon( 0, QIcon::fromTheme( QStringLiteral("bookmarks") ) ); m_currentDocumentItem->setExpanded( true ); } connect(m_tree, &QTreeWidget::itemChanged, this, &BookmarkList::slotChanged); } } void BookmarkList::slotFilterBookmarks( bool on ) { rebuildTree( on ); } void BookmarkList::slotExecuted( QTreeWidgetItem * item ) { BookmarkItem* bmItem = dynamic_cast( item ); if ( !bmItem || !bmItem->viewport().isValid() ) return; goTo( bmItem ); } void BookmarkList::slotChanged( QTreeWidgetItem * item ) { BookmarkItem* bmItem = dynamic_cast( item ); if ( bmItem && bmItem->viewport().isValid() ) { bmItem->bookmark().setFullText( bmItem->text( 0 ) ); m_document->bookmarkManager()->save(); } FileItem* fItem = dynamic_cast( item ); if ( fItem ) { const QUrl url = fItem->data( 0, UrlRole ).value< QUrl >(); m_document->bookmarkManager()->renameBookmark( url, fItem->text( 0 ) ); m_document->bookmarkManager()->save(); } } void BookmarkList::slotContextMenu( const QPoint& p ) { QTreeWidgetItem * item = m_tree->itemAt( p ); BookmarkItem* bmItem = item ? dynamic_cast( item ) : nullptr; if ( bmItem ) contextMenuForBookmarkItem( p, bmItem ); else if ( FileItem* fItem = dynamic_cast< FileItem * >( item ) ) contextMenuForFileItem( p, fItem ); } void BookmarkList::contextMenuForBookmarkItem( const QPoint& p, BookmarkItem* bmItem ) { Q_UNUSED( p ); if ( !bmItem || !bmItem->viewport().isValid() ) return; QMenu menu( this ); QAction * gotobm = menu.addAction( i18n( "Go to This Bookmark" ) ); QAction * editbm = menu.addAction( QIcon::fromTheme( QStringLiteral("edit-rename") ), i18n( "Rename Bookmark" ) ); QAction * removebm = menu.addAction( QIcon::fromTheme( QStringLiteral("list-remove") ), i18n( "Remove Bookmark" ) ); QAction * res = menu.exec( QCursor::pos() ); if ( !res ) return; if ( res == gotobm ) goTo( bmItem ); else if ( res == editbm ) m_tree->editItem( bmItem, 0 ); else if ( res == removebm ) m_document->bookmarkManager()->removeBookmark( bmItem->url(), bmItem->bookmark() ); } void BookmarkList::contextMenuForFileItem( const QPoint& p, FileItem* fItem ) { Q_UNUSED( p ); if ( !fItem ) return; const QUrl itemurl = fItem->data( 0, UrlRole ).value< QUrl >(); const bool thisdoc = itemurl == m_document->currentDocument(); QMenu menu( this ); QAction * open = nullptr; if ( !thisdoc ) open = menu.addAction( i18nc( "Opens the selected document", "Open Document" ) ); QAction * editbm = menu.addAction( QIcon::fromTheme( QStringLiteral("edit-rename") ), i18n( "Rename Bookmark" ) ); QAction * removebm = menu.addAction( QIcon::fromTheme( QStringLiteral("list-remove") ), i18n( "Remove Bookmarks" ) ); QAction * res = menu.exec( QCursor::pos() ); if ( !res ) return; if ( res == open ) { Okular::GotoAction action( itemurl.toDisplayString(QUrl::PreferLocalFile), Okular::DocumentViewport() ); m_document->processAction( &action ); } else if ( res == editbm ) m_tree->editItem( fItem, 0 ); else if ( res == removebm ) { KBookmark::List list; for ( int i = 0; i < fItem->childCount(); ++i ) { list.append( static_cast( fItem->child( i ) )->bookmark() ); } m_document->bookmarkManager()->removeBookmarks( itemurl, list ); } } void BookmarkList::slotBookmarksChanged(const QUrl &url ) { // special case here, as m_currentDocumentItem could represent // the invisible root item if ( url == m_document->currentDocument() ) { selectiveUrlUpdate( m_document->currentDocument(), m_currentDocumentItem ); return; } // we are showing the bookmarks for the current document only if ( m_showBoomarkOnlyAction->isChecked() ) return; QTreeWidgetItem *item = itemForUrl( url ); selectiveUrlUpdate( url, item ); } QList createItems( const QUrl& baseurl, const KBookmark::List& bmlist ) { Q_UNUSED(baseurl) QList ret; foreach ( const KBookmark& bm, bmlist ) { // qCDebug(OkularUiDebug).nospace() << "checking '" << tmp << "'"; // qCDebug(OkularUiDebug).nospace() << " vs '" << baseurl << "'"; // TODO check that bm and baseurl are the same (#ref excluded) QTreeWidgetItem * item = new BookmarkItem( bm ); ret.append( item ); } return ret; } void BookmarkList::rebuildTree( bool filter ) { // disconnect and reconnect later, otherwise we'll get many itemChanged() // signals for all the current items disconnect(m_tree, &QTreeWidget::itemChanged, this, &BookmarkList::slotChanged); m_currentDocumentItem = nullptr; m_tree->clear(); QList urls = m_document->bookmarkManager()->files(); if ( filter ) { if ( m_document->isOpened() ) { foreach ( const QUrl& url, urls ) { if ( url == m_document->currentDocument() ) { m_tree->addTopLevelItems( createItems( url, m_document->bookmarkManager()->bookmarks( url ) ) ); m_currentDocumentItem = m_tree->invisibleRootItem(); break; } } } } else { QTreeWidgetItem * currenturlitem = nullptr; foreach ( const QUrl& url, urls ) { QList subitems = createItems( url, m_document->bookmarkManager()->bookmarks( url ) ); if ( !subitems.isEmpty() ) { FileItem * item = new FileItem( url, m_tree, m_document ); item->addChildren( subitems ); if ( !currenturlitem && url == m_document->currentDocument() ) { currenturlitem = item; } } } if ( currenturlitem ) { currenturlitem->setExpanded( true ); currenturlitem->setIcon( 0, QIcon::fromTheme( QStringLiteral("bookmarks") ) ); m_tree->scrollToItem( currenturlitem, QAbstractItemView::PositionAtTop ); m_currentDocumentItem = currenturlitem; } } m_tree->sortItems( 0, Qt::AscendingOrder ); connect(m_tree, &QTreeWidget::itemChanged, this, &BookmarkList::slotChanged); } void BookmarkList::goTo( BookmarkItem * item ) { if ( item->url() == m_document->currentDocument() ) { m_document->setViewport( item->viewport() ); } else { Okular::GotoAction action( item->url().toDisplayString(QUrl::PreferLocalFile), item->viewport() ); m_document->processAction( &action ); } } void BookmarkList::selectiveUrlUpdate( const QUrl& url, QTreeWidgetItem*& item ) { disconnect(m_tree, &QTreeWidget::itemChanged, this, &BookmarkList::slotChanged); const KBookmark::List urlbookmarks = m_document->bookmarkManager()->bookmarks( url ); if ( urlbookmarks.isEmpty() ) { if ( item != m_tree->invisibleRootItem() ) { m_tree->invisibleRootItem()->removeChild( item ); item = nullptr; } else if ( item ) { for ( int i = item->childCount(); i >= 0; --i ) { item->removeChild( item->child( i ) ); } } } else { bool fileitem_created = false; if ( item ) { for ( int i = item->childCount() - 1; i >= 0; --i ) { item->removeChild( item->child( i ) ); } } else { item = new FileItem( url, m_tree, m_document ); fileitem_created = true; } if ( m_document->isOpened() && url == m_document->currentDocument() ) { item->setIcon( 0, QIcon::fromTheme( QStringLiteral("bookmarks") ) ); item->setExpanded( true ); } item->addChildren( createItems( url, urlbookmarks ) ); if ( fileitem_created ) { // we need to sort also the parent of the new file item, // so it can be properly shown in the correct place m_tree->invisibleRootItem()->sortChildren( 0, Qt::AscendingOrder ); } item->sortChildren( 0, Qt::AscendingOrder ); } connect(m_tree, &QTreeWidget::itemChanged, this, &BookmarkList::slotChanged); } QTreeWidgetItem* BookmarkList::itemForUrl( const QUrl& url ) const { const int count = m_tree->topLevelItemCount(); for ( int i = 0; i < count; ++i ) { QTreeWidgetItem *item = m_tree->topLevelItem( i ); const QUrl itemurl = item->data( 0, UrlRole ).value< QUrl >(); if ( itemurl.isValid() && itemurl == url ) { return item; } } return nullptr; } #include "moc_bookmarklist.cpp" diff --git a/ui/searchwidget.cpp b/ui/searchwidget.cpp index 154fdb370..96fc16589 100644 --- a/ui/searchwidget.cpp +++ b/ui/searchwidget.cpp @@ -1,109 +1,110 @@ /*************************************************************************** * Copyright (C) 2004 by Enrico Ros * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "searchwidget.h" // qt/kde includes #include #include #include #include #include #include #include // local includes #include "searchlineedit.h" SearchWidget::SearchWidget( QWidget * parent, Okular::Document * document ) : QWidget( parent ) { setObjectName( QStringLiteral( "iSearchBar" ) ); QSizePolicy sp = sizePolicy(); sp.setVerticalPolicy( QSizePolicy::Minimum ); setSizePolicy( sp ); QHBoxLayout * mainlay = new QHBoxLayout( this ); mainlay->setMargin( 0 ); mainlay->setSpacing( 3 ); // 2. text line m_lineEdit = new SearchLineEdit( this, document ); m_lineEdit->setClearButtonEnabled( true ); + m_lineEdit->setPlaceholderText(i18n( "Search..." )); m_lineEdit->setToolTip(i18n( "Enter at least 3 letters to filter pages" )); m_lineEdit->setSearchCaseSensitivity( Qt::CaseInsensitive ); m_lineEdit->setSearchMinimumLength( 3 ); m_lineEdit->setSearchType( Okular::Document::GoogleAll ); m_lineEdit->setSearchId( SW_SEARCH_ID ); m_lineEdit->setSearchColor( qRgb( 0, 183, 255 ) ); mainlay->addWidget( m_lineEdit ); // 3.1. create the popup menu for changing filtering features m_menu = new QMenu( this ); m_caseSensitiveAction = m_menu->addAction( i18n("Case Sensitive") ); m_menu->addSeparator(); m_matchPhraseAction = m_menu->addAction( i18n("Match Phrase") ); m_marchAllWordsAction = m_menu->addAction( i18n("Match All Words") ); m_marchAnyWordsAction = m_menu->addAction( i18n("Match Any Word") ); m_caseSensitiveAction->setCheckable( true ); QActionGroup *actgrp = new QActionGroup( this ); m_matchPhraseAction->setCheckable( true ); m_matchPhraseAction->setActionGroup( actgrp ); m_marchAllWordsAction->setCheckable( true ); m_marchAllWordsAction->setActionGroup( actgrp ); m_marchAnyWordsAction->setCheckable( true ); m_marchAnyWordsAction->setActionGroup( actgrp ); m_marchAllWordsAction->setChecked( true ); connect(m_menu, &QMenu::triggered, this, &SearchWidget::slotMenuChaged); // 3.2. create the toolbar button that spawns the popup menu QToolButton *optionsMenuAction = new QToolButton( this ); mainlay->addWidget( optionsMenuAction ); optionsMenuAction->setAutoRaise( true ); optionsMenuAction->setIcon( QIcon::fromTheme( QStringLiteral("view-filter") ) ); optionsMenuAction->setToolTip( i18n( "Filter Options" ) ); optionsMenuAction->setPopupMode( QToolButton::InstantPopup ); optionsMenuAction->setMenu( m_menu ); } void SearchWidget::clearText() { m_lineEdit->clear(); } void SearchWidget::slotMenuChaged( QAction * act ) { // update internal variables and checked state if ( act == m_caseSensitiveAction ) { m_lineEdit->setSearchCaseSensitivity( m_caseSensitiveAction->isChecked() ? Qt::CaseSensitive : Qt::CaseInsensitive ); } else if ( act == m_matchPhraseAction ) { m_lineEdit->setSearchType( Okular::Document::AllDocument ); } else if ( act == m_marchAllWordsAction ) { m_lineEdit->setSearchType( Okular::Document::GoogleAll ); } else if ( act == m_marchAnyWordsAction ) { m_lineEdit->setSearchType( Okular::Document::GoogleAny ); } else return; // update search m_lineEdit->restartSearch(); } #include "moc_searchwidget.cpp" diff --git a/ui/side_reviews.cpp b/ui/side_reviews.cpp index 25e358816..e50d2f162 100644 --- a/ui/side_reviews.cpp +++ b/ui/side_reviews.cpp @@ -1,288 +1,289 @@ /*************************************************************************** * Copyright (C) 2005 by Enrico Ros * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "side_reviews.h" // qt/kde includes #include #include #include #include #include #include #include #include #include #include #include #include #include // local includes #include "core/annotations.h" #include "core/document.h" #include "core/page.h" #include "settings.h" #include "annotationpopup.h" #include "annotationproxymodels.h" #include "annotationmodel.h" #include "ktreeviewsearchline.h" class TreeView : public QTreeView { Q_OBJECT public: TreeView( Okular::Document *document, QWidget *parent = Q_NULLPTR ) : QTreeView( parent ), m_document( document ) { } protected: void paintEvent( QPaintEvent *event ) override { bool hasAnnotations = false; for ( uint i = 0; i < m_document->pages(); ++i ) if ( m_document->page( i )->hasAnnotations() ) { hasAnnotations = true; break; } if ( !hasAnnotations ) { QPainter p( viewport() ); p.setRenderHint( QPainter::Antialiasing, true ); p.setClipRect( event->rect() ); QTextDocument document; document.setHtml( i18n( "

No annotations

" "To create new annotations press F6 or select Tools -> Review" " from the menu.
" ) ); document.setTextWidth( width() - 50 ); const uint w = document.size().width() + 20; const uint h = document.size().height() + 20; p.setBrush( palette().background() ); p.translate( 0.5, 0.5 ); p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h ); p.translate( 20, 20 ); document.drawContents( &p ); } else { QTreeView::paintEvent( event ); } } private: Okular::Document *m_document; }; Reviews::Reviews( QWidget * parent, Okular::Document * document ) : QWidget( parent ), m_document( document ) { // create widgets and layout them vertically QVBoxLayout * vLayout = new QVBoxLayout( this ); vLayout->setMargin( 0 ); vLayout->setSpacing( 6 ); m_view = new TreeView( m_document, this ); m_view->setAlternatingRowColors( true ); m_view->setSelectionMode( QAbstractItemView::ExtendedSelection ); m_view->header()->hide(); QToolBar *toolBar = new QToolBar( this ); toolBar->setObjectName( QStringLiteral( "reviewOptsBar" ) ); QSizePolicy sp = toolBar->sizePolicy(); sp.setVerticalPolicy( QSizePolicy::Minimum ); toolBar->setSizePolicy( sp ); m_model = new AnnotationModel( m_document, m_view ); m_filterProxy = new PageFilterProxyModel( m_view ); m_groupProxy = new PageGroupProxyModel( m_view ); m_authorProxy = new AuthorGroupProxyModel( m_view ); m_filterProxy->setSourceModel( m_model ); m_groupProxy->setSourceModel( m_filterProxy ); m_authorProxy->setSourceModel( m_groupProxy ); m_view->setModel( m_authorProxy ); m_searchLine = new KTreeViewSearchLine( this, m_view ); + m_searchLine->setPlaceholderText(i18n( "Search..." )); m_searchLine->setCaseSensitivity( Okular::Settings::self()->reviewsSearchCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive ); m_searchLine->setRegularExpression( Okular::Settings::self()->reviewsSearchRegularExpression() ); connect(m_searchLine, &KTreeViewSearchLine::searchOptionsChanged, this, &Reviews::saveSearchOptions); vLayout->addWidget( m_searchLine ); vLayout->addWidget( m_view ); vLayout->addWidget( toolBar ); toolBar->setIconSize( QSize( 16, 16 ) ); toolBar->setMovable( false ); // - add Page button QAction * groupByPageAction = toolBar->addAction( QIcon::fromTheme( QStringLiteral("text-x-generic") ), i18n( "Group by Page" ) ); groupByPageAction->setCheckable( true ); connect(groupByPageAction, &QAction::toggled, this, &Reviews::slotPageEnabled); groupByPageAction->setChecked( Okular::Settings::groupByPage() ); // - add Author button QAction * groupByAuthorAction = toolBar->addAction( QIcon::fromTheme( QStringLiteral("user-identity") ), i18n( "Group by Author" ) ); groupByAuthorAction->setCheckable( true ); connect(groupByAuthorAction, &QAction::toggled, this, &Reviews::slotAuthorEnabled); groupByAuthorAction->setChecked( Okular::Settings::groupByAuthor() ); // - add separator toolBar->addSeparator(); // - add Current Page Only button QAction * curPageOnlyAction = toolBar->addAction( QIcon::fromTheme( QStringLiteral("arrow-down") ), i18n( "Show reviews for current page only" ) ); curPageOnlyAction->setCheckable( true ); connect(curPageOnlyAction, &QAction::toggled, this, &Reviews::slotCurrentPageOnly); curPageOnlyAction->setChecked( Okular::Settings::currentPageOnly() ); connect(m_view, &TreeView::activated, this, &Reviews::activated); m_view->setContextMenuPolicy( Qt::CustomContextMenu ); connect(m_view, &TreeView::customContextMenuRequested, this, &Reviews::contextMenuRequested); } Reviews::~Reviews() { m_document->removeObserver( this ); } //BEGIN DocumentObserver Notifies void Reviews::notifyCurrentPageChanged( int previousPage, int currentPage ) { Q_UNUSED( previousPage ) m_filterProxy->setCurrentPage( currentPage ); } //END DocumentObserver Notifies void Reviews::reparseConfig() { m_searchLine->setCaseSensitivity( Okular::Settings::reviewsSearchCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive ); m_searchLine->setRegularExpression( Okular::Settings::reviewsSearchRegularExpression() ); m_view->update(); } //BEGIN GUI Slots -> requestListViewUpdate void Reviews::slotPageEnabled( bool on ) { // store toggle state in Settings and update the listview Okular::Settings::setGroupByPage( on ); m_groupProxy->groupByPage( on ); m_view->expandAll(); } void Reviews::slotAuthorEnabled( bool on ) { // store toggle state in Settings and update the listview Okular::Settings::setGroupByAuthor( on ); m_authorProxy->groupByAuthor( on ); m_view->expandAll(); } void Reviews::slotCurrentPageOnly( bool on ) { // store toggle state in Settings and update the listview Okular::Settings::setCurrentPageOnly( on ); m_filterProxy->groupByCurrentPage( on ); m_view->expandAll(); } //END GUI Slots void Reviews::activated( const QModelIndex &index ) { const QModelIndex authorIndex = m_authorProxy->mapToSource( index ); const QModelIndex filterIndex = m_groupProxy->mapToSource( authorIndex ); const QModelIndex annotIndex = m_filterProxy->mapToSource( filterIndex ); Okular::Annotation *annotation = m_model->annotationForIndex( annotIndex ); if ( !annotation ) return; int pageNumber = m_model->data( annotIndex, AnnotationModel::PageRole ).toInt(); const Okular::Page * page = m_document->page( pageNumber ); // calculating the right coordinates to center the view on the annotation QRect rect = Okular::AnnotationUtils::annotationGeometry( annotation, page->width(), page->height() ); Okular::NormalizedRect nr( rect, (int)page->width(), (int)page->height() ); // set the viewport parameters Okular::DocumentViewport vp; vp.pageNumber = pageNumber; vp.rePos.enabled = true; vp.rePos.pos = Okular::DocumentViewport::Center; vp.rePos.normalizedX = ( nr.right + nr.left ) / 2.0; vp.rePos.normalizedY = ( nr.bottom + nr.top ) / 2.0; // setting the viewport m_document->setViewport( vp, nullptr, true ); } QModelIndexList Reviews::retrieveAnnotations(const QModelIndex& idx) const { QModelIndexList ret; if ( idx.isValid() ) { if ( idx.model()->hasChildren( idx ) ) { int rowCount = idx.model()->rowCount( idx ); for ( int i = 0; i < rowCount; i++ ) { ret += retrieveAnnotations( idx.child( i, idx.column() ) ); } } else { ret += idx; } } return ret; } void Reviews::contextMenuRequested( const QPoint &pos ) { AnnotationPopup popup( m_document, AnnotationPopup::SingleAnnotationMode, this ); connect(&popup, &AnnotationPopup::openAnnotationWindow, this, &Reviews::openAnnotationWindow); QModelIndexList indexes = m_view->selectionModel()->selectedIndexes(); Q_FOREACH ( const QModelIndex &index, indexes ) { QModelIndexList annotations = retrieveAnnotations(index); Q_FOREACH ( const QModelIndex &idx, annotations ) { const QModelIndex authorIndex = m_authorProxy->mapToSource( idx ); const QModelIndex filterIndex = m_groupProxy->mapToSource( authorIndex ); const QModelIndex annotIndex = m_filterProxy->mapToSource( filterIndex ); Okular::Annotation *annotation = m_model->annotationForIndex( annotIndex ); if ( annotation ) { const int pageNumber = m_model->data( annotIndex, AnnotationModel::PageRole ).toInt(); popup.addAnnotation( annotation, pageNumber ); } } } popup.exec( m_view->viewport()->mapToGlobal( pos ) ); } void Reviews::saveSearchOptions() { Okular::Settings::setReviewsSearchRegularExpression( m_searchLine->regularExpression() ); Okular::Settings::setReviewsSearchCaseSensitive( m_searchLine->caseSensitivity() == Qt::CaseSensitive ? true : false ); Okular::Settings::self()->save(); } #include "side_reviews.moc" diff --git a/ui/toc.cpp b/ui/toc.cpp index fadc1315a..d913d27ba 100644 --- a/ui/toc.cpp +++ b/ui/toc.cpp @@ -1,236 +1,238 @@ /*************************************************************************** * Copyright (C) 2004-2006 by Albert Astals Cid * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * ***************************************************************************/ #include "toc.h" // qt/kde includes #include #include #include #include #include #include +#include // local includes #include "ktreeviewsearchline.h" #include "pageitemdelegate.h" #include "tocmodel.h" #include "core/action.h" #include "core/document.h" #include "settings.h" TOC::TOC(QWidget *parent, Okular::Document *document) : QWidget(parent), m_document(document) { QVBoxLayout *mainlay = new QVBoxLayout( this ); mainlay->setMargin( 0 ); mainlay->setSpacing( 6 ); m_searchLine = new KTreeViewSearchLine( this ); mainlay->addWidget( m_searchLine ); + m_searchLine->setPlaceholderText(i18n( "Search..." )); m_searchLine->setCaseSensitivity( Okular::Settings::self()->contentsSearchCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive ); m_searchLine->setRegularExpression( Okular::Settings::self()->contentsSearchRegularExpression() ); connect(m_searchLine, &KTreeViewSearchLine::searchOptionsChanged, this, &TOC::saveSearchOptions); m_treeView = new QTreeView( this ); mainlay->addWidget( m_treeView ); m_model = new TOCModel( document, m_treeView ); m_treeView->setModel( m_model ); m_treeView->setSortingEnabled( false ); m_treeView->setRootIsDecorated( true ); m_treeView->setAlternatingRowColors( true ); m_treeView->setItemDelegate( new PageItemDelegate( m_treeView ) ); m_treeView->header()->hide(); m_treeView->setSelectionBehavior( QAbstractItemView::SelectRows ); connect(m_treeView, &QTreeView::clicked, this, &TOC::slotExecuted); connect(m_treeView, &QTreeView::activated, this, &TOC::slotExecuted); m_searchLine->setTreeView( m_treeView ); } TOC::~TOC() { m_document->removeObserver( this ); } void TOC::notifySetup( const QVector< Okular::Page * > & /*pages*/, int setupFlags ) { if ( !( setupFlags & Okular::DocumentObserver::DocumentChanged ) ) return; // clear contents m_model->clear(); // request synopsis description (is a dom tree) const Okular::DocumentSynopsis * syn = m_document->documentSynopsis(); if ( !syn ) { if ( m_document->isOpened() ) { // Make sure we clear the reload old model data m_model->setOldModelData( nullptr, QVector() ); } emit hasTOC( false ); return; } m_model->fill( syn ); emit hasTOC( !m_model->isEmpty() ); } void TOC::notifyCurrentPageChanged( int, int ) { m_model->setCurrentViewport( m_document->viewport() ); } void TOC::prepareForReload() { if( m_model->isEmpty() ) return; const QVector list = expandedNodes(); TOCModel *m = m_model; m_model = new TOCModel( m_document, m_treeView ); m_model->setOldModelData( m, list ); m->setParent( nullptr ); } void TOC::rollbackReload() { if( !m_model->hasOldModelData() ) return; TOCModel *m = m_model; m_model = m->clearOldModelData(); m_model->setParent( m_treeView ); delete m; } void TOC::finishReload() { m_treeView->setModel( m_model ); m_model->setParent( m_treeView ); } QVector TOC::expandedNodes( const QModelIndex &parent ) const { QVector list; for ( int i = 0; i < m_model->rowCount( parent ); i++ ) { const QModelIndex index = m_model->index( i, 0, parent ); if ( m_treeView->isExpanded( index ) ) { list << index; } if ( m_model->hasChildren( index ) ) { list << expandedNodes( index ); } } return list; } void TOC::reparseConfig() { m_searchLine->setCaseSensitivity( Okular::Settings::contentsSearchCaseSensitive() ? Qt::CaseSensitive : Qt::CaseInsensitive ); m_searchLine->setRegularExpression( Okular::Settings::contentsSearchRegularExpression() ); m_treeView->update(); } void TOC::slotExecuted( const QModelIndex &index ) { if ( !index.isValid() ) return; QString url = m_model->urlForIndex( index ); if ( !url.isEmpty() ) { Okular::BrowseAction action( QUrl::fromLocalFile( url ) ); m_document->processAction( &action ); return; } QString externalFileName = m_model->externalFileNameForIndex( index ); Okular::DocumentViewport viewport = m_model->viewportForIndex( index ); if ( !externalFileName.isEmpty() ) { Okular::GotoAction action( externalFileName, viewport ); m_document->processAction( &action ); } else if ( viewport.isValid() ) { m_document->setViewport( viewport ); } } void TOC::saveSearchOptions() { Okular::Settings::setContentsSearchRegularExpression( m_searchLine->regularExpression() ); Okular::Settings::setContentsSearchCaseSensitive( m_searchLine->caseSensitivity() == Qt::CaseSensitive ? true : false ); Okular::Settings::self()->save(); } void TOC::contextMenuEvent(QContextMenuEvent* e) { QModelIndex index = m_treeView->currentIndex(); if (!index.isValid()) return; Okular::DocumentViewport viewport = m_model->viewportForIndex(index); emit rightClick(viewport, e->globalPos(), m_model->data(index).toString()); } void TOC::expandRecursively() { QList worklist = { m_treeView->currentIndex() }; if ( !worklist[0].isValid() ) { return; } while ( !worklist.isEmpty() ) { QModelIndex index = worklist.takeLast(); m_treeView->expand( index ); for ( int i = 0; i < m_model->rowCount(index); i++ ) { worklist += m_model->index( i, 0, index ); } } } void TOC::collapseRecursively() { QList worklist = { m_treeView->currentIndex() }; if ( !worklist[0].isValid() ) { return; } while ( !worklist.isEmpty() ) { QModelIndex index = worklist.takeLast(); m_treeView->collapse( index ); for ( int i = 0; i < m_model->rowCount(index); i++ ) { worklist += m_model->index( i, 0, index ); } } } void TOC::expandAll() { m_treeView->expandAll(); } void TOC::collapseAll() { m_treeView->collapseAll(); } #include "moc_toc.cpp"