Commit b9db06f8 authored by Enrico Ros's avatar Enrico Ros

Some cleanups. Some experiments. Nothing cool, boring stuf.

svn path=/branches/kpdf_experiments/kdegraphics/kpdf/; revision=347252
parent 87131472
......@@ -170,7 +170,7 @@ void KPDFTextDev::updateFont(GfxState *state)
m_text->updateFont(state);
}
void KPDFTextDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double originX, double originY, CharCode code, Unicode *u, int uLen)
void KPDFTextDev::drawChar(GfxState *state, double x, double y, double dx, double dy, double /*originX*/, double /*originY*/, CharCode code, Unicode *u, int uLen)
{
m_text->addChar(state, x, y, dx, dy, code, u, uLen);
}
......
......@@ -15,10 +15,11 @@ Porting / In progress on the branch (first item comes first):
-> porting Albert's link following
-> implementing async document generator using Albert's thread as the generation thread
-> better zoom handling
-> (store observers data into pages?)
Done (sorted by inv.time)
-> added a 'search bar' with prune-as-you-type feature
-> ported Albert's search
-> ported Albert's search and implemented case sensitive
-> 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)
......
......@@ -16,6 +16,7 @@
#include <klocale.h>
#include <kfinddialog.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
// local includes
#include "PDFDoc.h"
......@@ -26,9 +27,8 @@
#include "page.h"
/* Notes:
- FIXME event queuing to avoid flow interruption (!!??) maybe avoided by the
- FIXME event queuing to avoid flow loops (!!??) maybe avoided by the
warning to not call something 'active' inside an observer method.
- TODO implement filtering (on: "incremental search", "annotated pages",
*/
// structure used internally by KPDFDocument for data storage
......@@ -44,14 +44,12 @@ public:
QValueVector< KPDFPage* > pages;
// find related
QString lastSearchText;
long lastSearchOptions;
KPDFPage * lastSearchPage;
QString searchText;
bool searchCase;
int searchPage;
// filtering related
QString filterString;
bool filterCaseSensitive;
int filterLastCount;
QString filterText;
bool filterCase;
// observers related (note: won't delete oservers)
QMap< int, KPDFDocumentObserver* > observers;
......@@ -71,8 +69,7 @@ KPDFDocument::KPDFDocument()
d->pdfdoc = 0;
d->currentPage = -1;
d->currentPosition = 0;
d->lastSearchPage = 0;
d->filterLastCount = 0;
d->searchPage = -1;
SplashColor paperColor;
paperColor.rgb8 = splashMakeRGB8( 0xff, 0xff, 0xff );
d->kpdfOutputDev = new KPDFOutputDev( paperColor );
......@@ -80,23 +77,26 @@ KPDFDocument::KPDFDocument()
KPDFDocument::~KPDFDocument()
{
close();
closeDocument();
delete d->kpdfOutputDev;
delete d;
}
bool KPDFDocument::openFile( const QString & docFile )
bool KPDFDocument::openDocument( const QString & docFile )
{
// docFile is always local so we can use QFile on it
QFile fileReadTest( docFile );
if ( !fileReadTest.open( IO_ReadOnly ) )
return false;
long fileSize = fileReadTest.size();
fileReadTest.close();
// free internal data
closeDocument();
GString *filename = new GString( QFile::encodeName( docFile ) );
delete d->pdfdoc;
d->pdfdoc = new PDFDoc( filename, 0, 0 );
deletePages();
if ( !d->pdfdoc->isOk() )
{
......@@ -119,17 +119,34 @@ bool KPDFDocument::openFile( const QString & docFile )
for ( uint i = 0; i < pageCount ; i++ )
d->pages[i] = new KPDFPage( i, d->pdfdoc->getPageWidth(i+1), d->pdfdoc->getPageHeight(i+1), d->pdfdoc->getPageRotate(i+1) );
// filter pages, setup observers and set the first page as current
sendFilteredPageList();
processPageList( true );
slotSetCurrentPage( 0 );
}
// check local directory for an overlay xml
QString fileName = docFile.contains('/') ? docFile.section('/', -1, -1) : docFile;
fileName = "kpdf/" + QString::number(fileSize) + "." + fileName + ".xml";
QString localFN = locateLocal( "data", fileName );
kdWarning() << localFN << endl;
return true;
}
void KPDFDocument::close()
void KPDFDocument::closeDocument()
{
//stopRunningJobs()...
deletePages();
// delete pages and clear container
for ( uint i = 0; i < d->pages.count() ; i++ )
delete d->pages[i];
d->pages.clear();
// broadcast zero pages
processPageList( true );
// reset internal variables
d->currentPage = -1;
d->searchPage = -1;
// delete xpds's PDFDoc contents generator
delete d->pdfdoc;
d->pdfdoc = 0;
}
......@@ -163,7 +180,7 @@ const KPDFPage * KPDFDocument::page( uint n ) const
void KPDFDocument::addObserver( KPDFDocumentObserver * pObserver )
{
d->observers[ pObserver->observerId() ] = pObserver;
d->observers[ pObserver->observerId() ] = pObserver;
}
void KPDFDocument::requestPixmap( int id, uint page, int width, int height, bool syn )
......@@ -219,37 +236,37 @@ void KPDFDocument::slotSetCurrentPagePosition( int page, float position )
pageChanged();
}
void KPDFDocument::slotSetFilter( const QString & pattern, bool caseSensitive )
void KPDFDocument::slotSetFilter( const QString & pattern, bool keepCase )
{
d->filterCaseSensitive = caseSensitive;
d->filterString = pattern;
sendFilteredPageList();
d->filterText = pattern;
d->filterCase = keepCase;
processPageList( false );
}
void KPDFDocument::slotFind( const QString & t, long opt )
void KPDFDocument::slotFind( const QString & string, bool keepCase )
{
// reload last options if in 'find next' case
long options = t.isEmpty() ? d->lastSearchOptions : opt;
QString text = t.isEmpty() ? d->lastSearchText : t;
if ( !t.isEmpty() )
// turn selection drawing off on filtered pages
if ( !d->filterText.isEmpty() )
unHilightPages();
// save params for the 'find next' case
if ( !string.isEmpty() )
{
d->lastSearchText = t;
d->lastSearchOptions = opt;
d->searchText = string;
d->searchCase = keepCase;
}
// check enabled options (only caseSensitive support until now)
bool caseSensitive = options & KFindDialog::CaseSensitive;
// continue checking last SearchPage first (if it is the current page)
KPDFPage * foundPage = 0;
int currentPage = d->currentPage;
int pageCount = d->pages.count();
if ( d->lastSearchPage && (int)d->lastSearchPage->number() == currentPage )
if ( d->lastSearchPage->hasText( text, caseSensitive, false ) )
foundPage = d->lastSearchPage;
KPDFPage * foundPage = 0,
* lastPage = (d->searchPage > -1) ? d->pages[ d->searchPage ] : 0;
if ( lastPage && d->searchPage == currentPage )
if ( lastPage->hasText( d->searchText, d->searchCase, false ) )
foundPage = lastPage;
else
{
d->lastSearchPage->hilightLastSearch( false );
lastPage->hilightLastSearch( false );
currentPage++;
pageCount--;
}
......@@ -276,7 +293,7 @@ void KPDFDocument::slotFind( const QString & t, long opt )
// ..and attach it to the page
page->setSearchPage( td.takeTextPage() );
}
if ( page->hasText( text, caseSensitive, true ) )
if ( page->hasText( d->searchText, d->searchCase, true ) )
{
foundPage = page;
break;
......@@ -286,13 +303,14 @@ void KPDFDocument::slotFind( const QString & t, long opt )
if ( foundPage )
{
d->lastSearchPage = foundPage;
int pageNumber = foundPage->number();
d->searchPage = pageNumber;
foundPage->hilightLastSearch( true );
slotSetCurrentPage( foundPage->number() );
foreachObserver( notifyPixmapChanged( foundPage->number() ) );
slotSetCurrentPage( pageNumber );
foreachObserver( notifyPixmapChanged( pageNumber ) );
}
else
KMessageBox::information( 0, i18n("No matches found for '%1'.").arg(text) );
KMessageBox::information( 0, i18n("No matches found for '%1'.").arg(d->searchText) );
}
void KPDFDocument::slotGoToLink( /* QString anchor */ )
......@@ -300,22 +318,18 @@ void KPDFDocument::slotGoToLink( /* QString anchor */ )
}
//END slots
void KPDFDocument::sendFilteredPageList( bool forceEmpty )
void KPDFDocument::processPageList( bool documentChanged )
{
// make up a value list of the pages [1,2,3..]
uint pageCount = d->pages.count();
//d->filterLastCount
QValueList<int> pagesList;
if ( !forceEmpty )
if ( d->filterText.length() < 3 )
unHilightPages();
else
{
uint pageCount = d->pages.count();
for ( uint i = 0; i < pageCount ; i++ )
{
KPDFPage * page = d->pages[ i ];
if ( d->filterString.length() < 3 )
{
pagesList.push_back( i );
if ( d->filterText.length() < 3 )
page->hilightLastSearch( false );
}
else
{
if ( !page->hasSearchPage() )
......@@ -328,33 +342,32 @@ void KPDFDocument::sendFilteredPageList( bool forceEmpty )
// ..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 );
bool found = page->hasText( d->filterText, d->filterCase, true );
page->hilightLastSearch( found );
}
}
}
// send the list to observers
foreachObserver( pageSetup( pagesList ) );
foreachObserver( pageSetup( d->pages, documentChanged ) );
}
void KPDFDocument::deletePages()
void KPDFDocument::unHilightPages()
{
if ( d->pages.isEmpty() )
if ( d->filterText == "" )
return;
// broadcast an empty page list to observers
sendFilteredPageList( true );
// delete pages and clear container
for ( uint i = 0; i < d->pages.count() ; i++ )
delete d->pages[i];
d->pages.clear();
d->currentPage = -1;
d->lastSearchPage = 0;
d->filterLastCount = 0;
d->filterText = "";
QValueVector<KPDFPage*>::iterator it = d->pages.begin(), end = d->pages.end();
for ( ; it != end; ++it )
{
KPDFPage * page = *it;
if ( page->isHilighted() )
{
page->hilightLastSearch( false );
foreachObserver( notifyPixmapChanged( page->number() ) );
}
}
}
/** TO BE IMPORTED:
......
......@@ -11,7 +11,7 @@
#define _KPDF_DOCUMENT_H_
#include <qobject.h>
#include <qvaluelist.h>
#include <qvaluevector.h>
class KPDFPage;
......@@ -31,7 +31,7 @@ public:
virtual void notifyPixmapChanged( int /*pageNumber*/ ) {};
// commands from the Document to all observers
virtual void pageSetup( const QValueList<int> & /*pages*/ ) {};
virtual void pageSetup( const QValueVector<KPDFPage*> & /*pages*/, bool /*documentChanged*/ ) {};
virtual void pageSetCurrent( int /*pageNumber*/, float /*position*/ ) {};
};
......@@ -53,8 +53,8 @@ public:
~KPDFDocument();
// document handling
bool openFile( const QString & docFile );
void close();
bool openDocument( const QString & docFile );
void closeDocument();
// query methods
uint currentPage() const;
......@@ -72,16 +72,16 @@ public slots:
void slotSetCurrentPage( int page );
void slotSetCurrentPagePosition( int page, float position );
void slotSetFilter( const QString & pattern, bool caseSensitive );
void slotFind( const QString & text = "", long options = 0 );
void slotGoToLink( /* QString anchor */ );
void slotFind( const QString & text = "", bool caseSensitive = false );
void slotGoToLink( /* UnknownType unknown */ );
signals:
// notify changes via signals
void pageChanged();
private:
void sendFilteredPageList( bool forceEmpty = false );
void deletePages();
void processPageList( bool documentChanged );
void unHilightPages();
class KPDFDocumentPrivate * d;
};
......
......@@ -110,8 +110,11 @@ void PageWidget::saveSettings( KConfigGroup * config )
//BEGIN KPDFDocumentObserver inherited methods
void PageWidget::pageSetup( const QValueList<int> & pages )
void PageWidget::pageSetup( const QValueVector<KPDFPage*> & pages, bool documentChanged )
{
//TODO
documentChanged = false;
//TODO
m_pages.clear();
m_page = 0;
......@@ -119,10 +122,10 @@ void PageWidget::pageSetup( const QValueList<int> & pages )
return;
// populate internal vector with the list of pages and update
QValueList<int>::const_iterator pageIt = pages.begin();
QValueList<int>::const_iterator pageEnd = pages.end();
QValueVector<KPDFPage*>::const_iterator pageIt = pages.begin();
QValueVector<KPDFPage*>::const_iterator pageEnd = pages.end();
for ( ; pageIt != pageEnd ; ++pageIt )
m_pages.push_back( *pageIt );
m_pages.push_back( (*pageIt)->number() );
}
void PageWidget::pageSetCurrent( int pageNumber, float position )
......
......@@ -40,7 +40,7 @@ public:
void saveSettings( KConfigGroup * config );
// inherited from KPDFDocumentObserver
void pageSetup( const QValueList<int> & pages );
void pageSetup( const QValueVector<KPDFPage*> & pages, bool documentChanged );
void pageSetCurrent( int pageNumber, float position );
void notifyPixmapChanged( int pageNumber );
......
......@@ -26,6 +26,7 @@
#include <qlayout.h>
#include <qlabel.h>
#include <qvbox.h>
#include <qpushbutton.h>
#include <kaction.h>
#include <kinstance.h>
......@@ -38,6 +39,7 @@
#include <kmessagebox.h>
#include <kfinddialog.h>
#include <knuminput.h>
#include <kiconloader.h>
#include <kio/netaccess.h>
#include "kpdf_error.h"
......@@ -85,16 +87,20 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
m_splitter->setOpaqueResize( true );
setWidget( m_splitter );
m_thumbnailList = new ThumbnailList( m_splitter, document );
m_thumbnailList->setMaximumWidth( 125 );
m_thumbnailList->setMinimumWidth( 50 );
document->addObserver( m_thumbnailList );
QVBox * leftVBox = new QVBox( m_splitter );
leftVBox->setMaximumWidth( 150 );
leftVBox->setMinimumWidth( 50 );
new QPushButton( QIconSet(SmallIcon("thumbnail")), "only a", leftVBox );
new QPushButton( QIconSet(SmallIcon("bookmark")), "layout", leftVBox );
new QPushButton( QIconSet(SmallIcon("filter")), "test", leftVBox );
QVBox * rightVBox = new QVBox( m_splitter );
m_searchWidget = new SearchWidget( leftVBox, document );
m_searchWidget = new SearchWidget( rightVBox, document );
m_thumbnailList = new ThumbnailList( leftVBox, document );
document->addObserver( m_thumbnailList );
m_pageWidget = new PageWidget( rightVBox, document );
m_pageWidget = new PageWidget( m_splitter, document );
connect( m_pageWidget, SIGNAL( urlDropped( const KURL& ) ), SLOT( openURL( const KURL & )));
//connect(m _pageWidget, SIGNAL( rightClick() ), this, SIGNAL( rightClick() ));
document->addObserver( m_pageWidget );
......@@ -168,14 +174,14 @@ KAboutData* Part::createAboutData()
bool Part::openFile()
{
bool ok = document->openFile( m_file );
bool ok = document->openDocument( m_file );
m_find->setEnabled( ok );
return ok;
}
bool Part::closeURL()
{
document->close();
document->closeDocument();
return KParts::ReadOnlyPart::closeURL();
}
......@@ -264,7 +270,7 @@ void Part::slotFind()
if (dlg.exec() == QDialog::Accepted)
{
m_findNext->setEnabled( true );
document->slotFind( dlg.pattern(), dlg.options() );
document->slotFind( dlg.pattern(), dlg.options() & KFindDialog::CaseSensitive );
}
}
......
......@@ -24,7 +24,7 @@
KPDFPage::KPDFPage( int page, float w, float h, int r )
: m_number( page ), m_rotation( r ), m_width( w ), m_height( h ),
m_sEnabled( false ), m_sLeft( 0 ), m_sTop( 0 ), m_sRight( 0 ),
m_hilighting( false ), m_sLeft( 0 ), m_sTop( 0 ), m_sRight( 0 ),
m_sBottom( 0 ), m_text( 0 )
{
}
......@@ -103,7 +103,7 @@ void KPDFPage::drawPixmap( int id, QPainter * p, const QRect & limits, int width
p->drawLine( 0, height, width, 0 );
}
// draw selection
if ( m_sEnabled )
if ( m_hilighting )
{
int x = (int)( m_sLeft * width / m_width ),
y = (int)( m_sTop * height / m_height ),
......@@ -145,7 +145,8 @@ bool KPDFPage::hasText( const QString & text, bool strictCase, bool fromTop )
void KPDFPage::hilightLastSearch( bool on )
{
m_sEnabled = on;
m_hilighting = on;
//if ( !on ) -> invalidate search rect?
}
// END commands (paint / search)
......
......@@ -39,6 +39,7 @@ public:
float height() const { return m_height; }
float ratio() const { return m_height / m_width; }
float rotation() const { return m_rotation; }
bool isHilighted() const { return m_hilighting; }
bool hasPixmap( int id, int width, int height ) const;
bool hasSearchPage() const;
bool hasLink( int mouseX, int mouseY ) const;
......@@ -57,7 +58,7 @@ public:
private:
int m_number, m_rotation;
float m_width, m_height;
bool m_sEnabled;
bool m_hilighting;
double m_sLeft, m_sTop, m_sRight, m_sBottom;
QMap<int,QPixmap *> m_pixmaps;
......
......@@ -40,16 +40,17 @@ SearchWidget::SearchWidget( QWidget * parent, KPDFDocument * document )
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 );
/* 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() );
*/
int sideLength = m_lineEdit->sizeHint().height();
clear->setMinimumSize( QSize( sideLength, sideLength ) );
// search->setMinimumSize( QSize( sideLength, sideLength ) );
}
void SearchWidget::setupActions( KActionCollection * ac, KConfigGroup * config )
......
......@@ -18,7 +18,8 @@
#include "page.h"
ThumbnailList::ThumbnailList(QWidget *parent, KPDFDocument *document)
: QScrollView(parent), m_document(document), m_selected(0), m_delayTimer(0)
: QScrollView(parent, "KPDF::Thumbnails", WNoAutoErase),
m_document(document), m_selected(0), m_delayTimer(0)
{
// set scrollbars
setHScrollBarMode( QScrollView::AlwaysOff );
......@@ -29,7 +30,8 @@ ThumbnailList::ThumbnailList(QWidget *parent, KPDFDocument *document)
// can be focused by tab and mouse click and grabs key events
viewport()->setFocusPolicy( StrongFocus );
viewport()->setInputMethodEnabled( true );
setFocusPolicy( NoFocus );
setInputMethodEnabled( true );
// set contents background to the 'base' color
viewport()->setPaletteBackgroundColor( palette().active().base() );
......@@ -54,8 +56,11 @@ void ThumbnailList::saveSettings( KConfigGroup * config )
}
//BEGIN KPDFDocumentObserver inherited methods
void ThumbnailList::pageSetup( const QValueList<int> & pages )
void ThumbnailList::pageSetup( const QValueVector<KPDFPage*> & pages, bool documentChanged )
{
//TODO
documentChanged = false;
//TODO
// delete all the Thumbnails
QValueVector<Thumbnail *>::iterator thumbIt = m_thumbnails.begin();
QValueVector<Thumbnail *>::iterator thumbEnd = m_thumbnails.end();
......@@ -74,19 +79,19 @@ void ThumbnailList::pageSetup( const QValueList<int> & pages )
Thumbnail *t;
int width = clipper()->width(),
totalHeight = 0;
QValueList<int>::const_iterator pageIt = pages.begin();
QValueList<int>::const_iterator pageEnd = pages.end();
QValueVector<KPDFPage*>::const_iterator pageIt = pages.begin();
QValueVector<KPDFPage*>::const_iterator pageEnd = pages.end();
for (; pageIt != pageEnd ; ++pageIt)
{
t = new Thumbnail( viewport(), m_document->page(*pageIt) );
// add to the scrollview
addChild( t, 0, totalHeight );
// add to the internal queue
m_thumbnails.push_back( t );
// update total height (asking widget its own height)
totalHeight += t->setThumbnailWidth( width );
t->show();
}
if ( (*pageIt)->isHilighted() ) {
t = new Thumbnail( viewport(), *pageIt );
// add to the scrollview
addChild( t, 0, totalHeight );
// add to the internal queue
m_thumbnails.push_back( t );
// update total height (asking widget its own height)
totalHeight += t->setThumbnailWidth( width );
t->show();
}
// update scrollview's contents size (sets scrollbars limits)
resizeContents( width, totalHeight );
......
......@@ -31,7 +31,7 @@ Q_OBJECT
void saveSettings( KConfigGroup * config );
// create thumbnails ( inherited as a DocumentObserver )
void pageSetup( const QValueList<int> & pages );
void pageSetup( const QValueVector<KPDFPage*> & pages, bool documentChanged );
// hilihght current thumbnail ( inherited as DocumentObserver )
void pageSetCurrent( int pageNumber, float position );
......
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