mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-05 23:49:20 +00:00
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:
parent
4569e4eea9
commit
7cd6bbf139
|
@ -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,10 +219,10 @@ 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();
|
||||
}
|
||||
|
||||
|
@ -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++ )
|
||||
{
|
||||
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>&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
103
kpdf/searchwidget.cpp
Normal 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
50
kpdf/searchwidget.h
Normal 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
|
Loading…
Reference in a new issue