Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 7cd6bbf1 authored by Enrico Ros's avatar Enrico Ros

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
parent 4569e4ee
......@@ -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
......
......@@ -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)
......
......@@ -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:
......
......@@ -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 */ );
......
......@@ -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 ),
......
......@@ -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 );
......
......@@ -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"
......@@ -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;
......
......@@ -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>
......
/***************************************************************************
* 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"
/***************************************************************************
* 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment