Added "search-as-you-tipe" feature. Note:takes lots of ram for big

documents but you can try it for 200 pages pdfs. It's pretty fast. You
type in some words and only pages containing that sting are displayed.

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=347060
This commit is contained in:
Enrico Ros 2004-09-16 21:27:34 +00:00
parent 4569e4eea9
commit 7cd6bbf139
11 changed files with 213 additions and 21 deletions

View File

@ -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

View File

@ -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)

View File

@ -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<int> 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:

View File

@ -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 */ );

View File

@ -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 ),

View File

@ -17,6 +17,7 @@
#include <qscrollview.h>
#include <qvaluevector.h>
#include <qhbox.h>
#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 );

View File

@ -21,14 +21,11 @@
* (at your option) any later version. *
***************************************************************************/
#include "kpdf_part.moc"
#include <math.h>
#include <qsplitter.h>
#include <qpainter.h>
#include <qlayout.h>
#include <qlabel.h>
#include <qvbox.h>
#include <kaction.h>
#include <kinstance.h>
@ -39,19 +36,19 @@
#include <kurldrag.h>
#include <kfiledialog.h>
#include <kmessagebox.h>
#include <kio/netaccess.h>
#include <kfinddialog.h>
#include <knuminput.h>
#include <kio/netaccess.h>
#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<KPDF::Part> 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<QWidget*>( 0 ) ) )
if( !KIO::NetAccess::upload( url().path(), saveURL, static_cast<QWidget*>( 0 ) ) )
; // TODO: Proper error dialog
}
@ -527,4 +529,4 @@ void BrowserExtension::print()
static_cast<Part*>(parent())->slotPrint();
}
// vim:ts=2:sw=2:tw=78:et
#include "kpdf_part.moc"

View File

@ -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;

View File

@ -28,6 +28,7 @@
<Menu name="settings"><text>&amp;Settings</text>
<Action name="show_scrollbars" group="show_merge"/>
<Action name="show_thumbnails" group="show_merge"/>
<Action name="show_searchbar" group="show_merge"/>
</Menu>
</MenuBar>
<ToolBar name="mainToolBar"><text>Main Toolbar</text>

103
kpdf/searchwidget.cpp Normal file
View File

@ -0,0 +1,103 @@
/***************************************************************************
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> *
* *
* 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 <qtooltip.h>
#include <kaction.h>
#include <kactioncollection.h>
#include <kconfigbase.h>
#include <klocale.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <kpopupmenu.h>
#include <ktoolbarbutton.h>
// local includes
#include "searchwidget.h"
#include "document.h"
//#include <qiconset.h>
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"

50
kpdf/searchwidget.h Normal file
View File

@ -0,0 +1,50 @@
/***************************************************************************
* Copyright (C) 2004 by Enrico Ros <eros.kde@email.it> *
* *
* 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 <qhbox.h>
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