diff --git a/kpdf/Makefile.am b/kpdf/Makefile.am index 9b4e7e3a0..0775f32a0 100644 --- a/kpdf/Makefile.am +++ b/kpdf/Makefile.am @@ -38,7 +38,7 @@ shellrc_DATA = kpdf_shell.rc kde_module_LTLIBRARIES = libkpdfpart.la # the Part's source, library search path, and link libraries -libkpdfpart_la_SOURCES = QOutputDev.cpp QOutputDevKPrinter.cpp kpdf_part.cpp kpdf_pagewidget.cc thumbnail.cpp thumbnaillist.cpp kpdf_error.cpp xpdf_errors.cpp thumbnailgenerator.cpp document.cpp page.cpp +libkpdfpart_la_SOURCES = QOutputDev.cpp QOutputDevKPrinter.cpp kpdf_part.cpp kpdf_pagewidget.cc thumbnail.cpp thumbnaillist.cpp kpdf_error.cpp xpdf_errors.cpp thumbnailgenerator.cpp document.cpp page.cpp searchwidget.cpp libkpdfpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) libkpdfpart_la_LIBADD = ../xpdf/libxpdf.la $(LIB_KPARTS) $(LIB_KFILE) $(LIB_KDEPRINT) $(LIB_KUTILS) -lm diff --git a/kpdf/TODO b/kpdf/TODO index a17b16861..3205d9896 100644 --- a/kpdf/TODO +++ b/kpdf/TODO @@ -13,11 +13,12 @@ More items Porting / In progress on the branch (first item comes first): -> porting Albert's link following --> porting Albert's search -> implementing async document generator using Albert's thread as the generation thread -> better zoom handling Done (sorted by inv.time) +-> added a 'search bar' with prune-as-you-type feature +-> ported Albert's search -> smart handling of pixmap using an Observer ID (thumbnails are gone, only pixmaps now) -> some toolbar/menu changes -> outline bottom and right edges (of pages) diff --git a/kpdf/document.cpp b/kpdf/document.cpp index da0081d73..014886688 100644 --- a/kpdf/document.cpp +++ b/kpdf/document.cpp @@ -50,6 +50,8 @@ public: // filtering related QString filterString; + bool filterCaseSensitive; + int filterLastCount; // observers related (note: won't delete oservers) QMap< int, KPDFDocumentObserver* > observers; @@ -70,6 +72,7 @@ KPDFDocument::KPDFDocument() d->currentPage = -1; d->currentPosition = 0; d->lastSearchPage = 0; + d->filterLastCount = 0; SplashColor paperColor; paperColor.rgb8 = splashMakeRGB8( 0xff, 0xff, 0xff ); d->kpdfOutputDev = new KPDFOutputDev( paperColor ); @@ -216,11 +219,11 @@ void KPDFDocument::slotSetCurrentPagePosition( int page, float position ) pageChanged(); } -void KPDFDocument::slotSetFilter( const QString & pattern ) +void KPDFDocument::slotSetFilter( const QString & pattern, bool caseSensitive ) { + d->filterCaseSensitive = caseSensitive; d->filterString = pattern; - if ( pattern.length() > 3 ) - sendFilteredPageList(); + sendFilteredPageList(); } void KPDFDocument::slotFind( const QString & t, long opt ) @@ -301,10 +304,37 @@ void KPDFDocument::sendFilteredPageList( bool forceEmpty ) { // make up a value list of the pages [1,2,3..] uint pageCount = d->pages.count(); + //d->filterLastCount QValueList pagesList; if ( !forceEmpty ) + { for ( uint i = 0; i < pageCount ; i++ ) - pagesList.push_back( i ); + { + KPDFPage * page = d->pages[ i ]; + if ( d->filterString.length() < 3 ) + { + pagesList.push_back( i ); + page->hilightLastSearch( false ); + } + else + { + if ( !page->hasSearchPage() ) + { + // build a TextPage using the lightweight KPDFTextDev generator.. + KPDFTextDev td; + d->docLock.lock(); + d->pdfdoc->displayPage( &td, page->number()+1, 72, 72, 0, true, false ); + d->docLock.unlock(); + // ..and attach it to the page + page->setSearchPage( td.takeTextPage() ); + } + bool ok = page->hasText( d->filterString, d->filterCaseSensitive, true ); + if ( ok ) + pagesList.push_back( i ); + page->hilightLastSearch( ok ); + } + } + } // send the list to observers foreachObserver( pageSetup( pagesList ) ); @@ -324,6 +354,7 @@ void KPDFDocument::deletePages() d->pages.clear(); d->currentPage = -1; d->lastSearchPage = 0; + d->filterLastCount = 0; } /** TO BE IMPORTED: diff --git a/kpdf/document.h b/kpdf/document.h index 98d19510e..5dfebe3df 100644 --- a/kpdf/document.h +++ b/kpdf/document.h @@ -71,7 +71,7 @@ public slots: // document commands via slots void slotSetCurrentPage( int page ); void slotSetCurrentPagePosition( int page, float position ); - void slotSetFilter( const QString & pattern ); + void slotSetFilter( const QString & pattern, bool caseSensitive ); void slotFind( const QString & text = "", long options = 0 ); void slotGoToLink( /* QString anchor */ ); diff --git a/kpdf/kpdf_pagewidget.cc b/kpdf/kpdf_pagewidget.cc index f294c32a6..759e8873e 100644 --- a/kpdf/kpdf_pagewidget.cc +++ b/kpdf/kpdf_pagewidget.cc @@ -29,8 +29,9 @@ #include "kpdf_pagewidget.h" #include "page.h" + PageWidget::PageWidget( QWidget *parent, KPDFDocument *document ) - : QScrollView( parent, "KPDF::pageWidget", WRepaintNoErase ), + : QScrollView( parent, "KPDF::pageWidget", WRepaintNoErase | WStaticContents ), m_document( document ), m_page( 0 ), m_mouseMode( MouseNormal ), m_mouseOnLink( false ), m_zoomMode( FixedFactor ), m_zoomFactor( 1.0 ), diff --git a/kpdf/kpdf_pagewidget.h b/kpdf/kpdf_pagewidget.h index f9815af9d..643360d6e 100644 --- a/kpdf/kpdf_pagewidget.h +++ b/kpdf/kpdf_pagewidget.h @@ -17,6 +17,7 @@ #include #include +#include #include "CharTypes.h" #include "document.h" @@ -28,7 +29,7 @@ class KConfigGroup; class PageWidget : public QScrollView, public KPDFDocumentObserver { - Q_OBJECT +Q_OBJECT public: PageWidget( QWidget *parent, KPDFDocument *document ); diff --git a/kpdf/kpdf_part.cpp b/kpdf/kpdf_part.cpp index 8b3f906db..2606a78bc 100644 --- a/kpdf/kpdf_part.cpp +++ b/kpdf/kpdf_part.cpp @@ -21,14 +21,11 @@ * (at your option) any later version. * ***************************************************************************/ -#include "kpdf_part.moc" - -#include - #include #include #include #include +#include #include #include @@ -39,19 +36,19 @@ #include #include #include -#include #include #include +#include #include "kpdf_error.h" -#include "GString.h" - #include "GlobalParams.h" #include "QOutputDevKPrinter.h" -#include "thumbnaillist.h" +#include "kpdf_part.h" #include "kpdf_pagewidget.h" +#include "searchwidget.h" +#include "thumbnaillist.h" #include "document.h" typedef KParts::GenericFactory KPDFPartFactory; @@ -93,7 +90,11 @@ Part::Part(QWidget *parentWidget, const char *widgetName, m_thumbnailList->setMinimumWidth( 50 ); document->addObserver( m_thumbnailList ); - m_pageWidget = new PageWidget( m_splitter, document ); + QVBox * rightVBox = new QVBox( m_splitter ); + + m_searchWidget = new SearchWidget( rightVBox, document ); + + m_pageWidget = new PageWidget( rightVBox, document ); connect( m_pageWidget, SIGNAL( urlDropped( const KURL& ) ), SLOT( openURL( const KURL & ))); //connect(m _pageWidget, SIGNAL( rightClick() ), this, SIGNAL( rightClick() )); document->addObserver( m_pageWidget ); @@ -131,6 +132,7 @@ Part::Part(QWidget *parentWidget, const char *widgetName, // attach the actions of the 2 children widgets too KConfigGroup settings( KPDFPartFactory::instance()->config(), "General" ); m_pageWidget->setupActions( ac, &settings ); + m_searchWidget->setupActions( ac, &settings ); m_thumbnailList->setupActions( ac, &settings ); // local settings @@ -145,6 +147,7 @@ Part::~Part() { KConfigGroup settings( KPDFPartFactory::instance()->config(), "General" ); m_pageWidget->saveSettings( &settings ); + m_searchWidget->saveSettings( &settings ); m_thumbnailList->saveSettings( &settings ); settings.writeEntry( "SplitterSizes", m_splitter->sizes() ); settings.sync(); @@ -279,8 +282,7 @@ void Part::slotSaveFileAs() QString::null, widget(), QString::null ); - if( !KIO::NetAccess::upload( url().path(), - saveURL, static_cast( 0 ) ) ) + if( !KIO::NetAccess::upload( url().path(), saveURL, static_cast( 0 ) ) ) ; // TODO: Proper error dialog } @@ -527,4 +529,4 @@ void BrowserExtension::print() static_cast(parent())->slotPrint(); } -// vim:ts=2:sw=2:tw=78:et +#include "kpdf_part.moc" diff --git a/kpdf/kpdf_part.h b/kpdf/kpdf_part.h index 9bce12274..56d7b1cf1 100644 --- a/kpdf/kpdf_part.h +++ b/kpdf/kpdf_part.h @@ -34,6 +34,7 @@ class LinkDest; class ThumbnailList; class PageWidget; +class SearchWidget; class KPDFDocument; namespace KPDF @@ -104,6 +105,7 @@ namespace KPDF QSplitter *m_splitter; ThumbnailList *m_thumbnailList; PageWidget *m_pageWidget; + SearchWidget *m_searchWidget; // static instances counter static unsigned int m_count; diff --git a/kpdf/kpdf_part.rc b/kpdf/kpdf_part.rc index a761e5a72..1078de3fe 100644 --- a/kpdf/kpdf_part.rc +++ b/kpdf/kpdf_part.rc @@ -28,6 +28,7 @@ &Settings + Main Toolbar diff --git a/kpdf/searchwidget.cpp b/kpdf/searchwidget.cpp new file mode 100644 index 000000000..8b09f893a --- /dev/null +++ b/kpdf/searchwidget.cpp @@ -0,0 +1,103 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +// qt/kde includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// local includes +#include "searchwidget.h" +#include "document.h" + +//#include +SearchWidget::SearchWidget( QWidget * parent, KPDFDocument * document ) + : QHBox( parent ), m_document( document ), m_caseSensitive( false ) +{ + setMargin( 4 ); + + // clear button + KToolBarButton * clear = new KToolBarButton( SmallIcon("locationbar_erase"), 1, this ); + QToolTip::add( clear, i18n( "Clear filter" ) ); + + // line edit + m_lineEdit = new KLineEdit( this ); + m_lineEdit->setFrame( QFrame::Sunken ); + connect( m_lineEdit, SIGNAL(textChanged(const QString &)), SLOT(slotTextChanged(const QString &)) ); + connect( clear, SIGNAL(clicked()), m_lineEdit, SLOT(clear()) ); + QToolTip::add( m_lineEdit, i18n( "Enter at least 3 letters to filter pages" ) ); + + // change case button and menu + KToolBarButton * search = new KToolBarButton( SmallIcon("find"), 2, this ); + m_caseMenu = new KPopupMenu( search ); + m_caseMenu->insertItem( i18n("Case Insensitive"), 1 ); + m_caseMenu->insertItem( i18n("Case Sensitive"), 2 ); + m_caseMenu->setItemChecked( 1, true ); + connect( m_caseMenu, SIGNAL( activated(int) ), SLOT( slotChangeCase(int) ) ); + search->setPopup( m_caseMenu ); + + clear->setMinimumHeight( m_lineEdit->sizeHint().height() ); + search->setMinimumHeight( m_lineEdit->sizeHint().height() ); +} + +void SearchWidget::setupActions( KActionCollection * ac, KConfigGroup * config ) +{ + KToggleAction * ss = new KToggleAction( i18n( "Show Search Bar" ), 0, ac, "show_searchbar" ); + ss->setCheckedState(i18n("Hide Search Bar")); + connect( ss, SIGNAL( toggled( bool ) ), SLOT( slotToggleSearchBar( bool ) ) ); + + ss->setChecked( config->readBoolEntry( "ShowSearchBar", false ) ); + slotToggleSearchBar( ss->isChecked() ); +} + +void SearchWidget::saveSettings( KConfigGroup * config ) +{ + config->writeEntry( "ShowSearchBar", isShown() ); +} + +void SearchWidget::slotTextChanged( const QString & text ) +{ + if ( text.length() > 2 || text.isEmpty() ) + { + m_lineEdit->setPaletteForegroundColor( palette().active().text() ); + m_document->slotSetFilter( text, m_caseSensitive ); + } + else + { + m_lineEdit->setPaletteForegroundColor( Qt::red ); + m_document->slotSetFilter( QString::null, m_caseSensitive ); + } +} + +void SearchWidget::slotChangeCase( int index ) +{ + bool newState = (index == 2); + if ( newState != m_caseSensitive ) + { + m_caseSensitive = newState; + m_caseMenu->setItemChecked( 1, !m_caseSensitive ); + m_caseMenu->setItemChecked( 2, m_caseSensitive ); + slotTextChanged( m_lineEdit->text() ); + } +} + +void SearchWidget::slotToggleSearchBar( bool visible ) +{ + setShown( visible ); + if ( !visible ) + m_document->slotSetFilter( QString::null, m_caseSensitive ); +} + +#include "searchwidget.moc" diff --git a/kpdf/searchwidget.h b/kpdf/searchwidget.h new file mode 100644 index 000000000..d530cb46b --- /dev/null +++ b/kpdf/searchwidget.h @@ -0,0 +1,50 @@ +/*************************************************************************** + * 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. * + ***************************************************************************/ + +#ifndef _KPDF_SEARCHWIDGET_H_ +#define _KPDF_SEARCHWIDGET_H_ + +#include + +class KActionCollection; +class KConfigGroup; +class KPopupMenu; +class KLineEdit; + +class KPDFDocument; + +/** + * @short A search widget for find-as-you-type search. + * + * ... + */ +class SearchWidget : public QHBox +{ +Q_OBJECT + +public: + SearchWidget( QWidget *parent, KPDFDocument *document ); + + // create actions that interact with this widget + void setupActions( KActionCollection * collection, KConfigGroup * config ); + void saveSettings( KConfigGroup * config ); + +private slots: + void slotTextChanged( const QString & text ); + void slotChangeCase( int index ); + void slotToggleSearchBar( bool visible ); + +private: + KPDFDocument * m_document; + KLineEdit * m_lineEdit; + KPopupMenu * m_caseMenu; + bool m_caseSensitive; +}; + +#endif