Commit 9e73b423 authored by Enrico Ros's avatar Enrico Ros

Fixed type-ahead searches. Reworked search code. Found alternative way to

setRasterOp. Cleaned up RenningSearch class. Performance fix on actions.

svn path=/trunk/kdegraphics/kpdf/; revision=385447
parent 6fb78405
......@@ -6,22 +6,20 @@ Legend:
MRG - MeRGed (code from a branch or a patch)
Status:
-> 2005-02-02: Features for 3.4 done. Ready for bugfixes.
-> 2005-01-27: Stable and leakchecked. Usability: needs testing.
-> 2005-01-20: Stable. Apart from a bad (but still safe) memory deallocation
mechanism the core is ready for a public release.
In progress 3.4 features (deadline is 2k5-Feb-2):
-> new word highlighting for searches / other highlights
More items (first items will enter 'In progress list' first):
-> go to next/previous bookmark actions (showing in thumbnailslist rmb popup too)
-> viewport restoring: sometimes it seems to restore the viewport a bit under where it was
-> viewport restoring: save the page width setting between runs (save/restore zoom factor)
-> presentation: provide a pageX/totalPages indicator in addition to the circle one
-> add scrollbar marks for bookmarks (like kate)
-> google search in the page
-> search: google search in the page
-> cleanup code and update README.png
-> find-as-you-type: use shortcut for 'find next' action (not the default one)
-> search: use shortcut for 'find next' action (not the default one) in find-ahead
-> show Viewport in ThumbnailsList (blended/contour)
-> Delay TOC (DocumentSynapsis) generation (and move it on thread)
-> refactor ThumbnailsList to do internal rendering as pageview does (way faster
......@@ -79,6 +77,7 @@ More items (first items will enter 'In progress list' first):
-> export: export to other formats keeping formatting (a dream.. except for PNG :-) (PS is easy, we just have PSOutputDev that does it :-D)
Done (newest features come first):
-> FIX: memleaks, bugfixes (1,..)
-> CHG: changes and cleanups in pageView's mouse handling functions
-> ADD: KTTSD simple support: speech selection using kspeech api via pure dcop (don't break compatibiltiy)
-> CHG: right click and drag while in 'normal' mode changes to 'selection' mode and selects
......
This diff is collapsed.
......@@ -82,10 +82,10 @@ class KPDFDocument : public QObject
enum SearchType { NextMatch, PrevMatch, AllDoc, GoogleLike };
bool searchText( int searchID, const QString & text, bool fromStart, bool caseSensitive,
SearchType type, bool moveViewport, const QColor & color );
SearchType type, bool moveViewport, const QColor & color, bool noDialogs = false );
bool continueSearch( int searchID );
void resetSearch( int searchID );
void toggleBookmark( int page );
void processLink( const KPDFLink * link );
bool print( KPrinter &printer );
......
......@@ -65,6 +65,9 @@
#include "core/document.h"
#include "core/page.h"
// definition of searchID for this class
#define PART_SEARCH_ID 1
typedef KParts::GenericFactory<KPDF::Part> KPDFPartFactory;
K_EXPORT_COMPONENT_FACTORY(libkpdfpart, KPDFPartFactory)
......@@ -75,7 +78,8 @@ unsigned int Part::m_count = 0;
Part::Part(QWidget *parentWidget, const char *widgetName,
QObject *parent, const char *name,
const QStringList & /*args*/ )
: DCOPObject("kpdf"), KParts::ReadOnlyPart(parent, name), m_showMenuBarAction(0), m_actionsSearched(false)
: DCOPObject("kpdf"), KParts::ReadOnlyPart(parent, name), m_showMenuBarAction(0),
m_actionsSearched(false), m_searchStarted(false)
{
// load catalog for translation
KGlobal::locale()->insertCatalogue("kpdf");
......@@ -255,7 +259,7 @@ Part::Part(QWidget *parentWidget, const char *widgetName,
// set our XML-UI resource file
setXMLFile("part.rc");
updateActions();
updateViewActions();
slotWatchFile();
}
......@@ -278,7 +282,7 @@ void Part::notifyViewportChanged( bool /*smoothMove*/ )
int viewportPage = m_document->viewport().pageNumber;
if ( viewportPage != lastPage )
{
updateActions();
updateViewActions();
lastPage = viewportPage;
}
}
......@@ -315,11 +319,15 @@ bool Part::openFile()
bool ok = m_document->openDocument( m_file );
// update one-time actions
m_find->setEnabled( ok );
m_findNext->setEnabled( ok );
m_saveAs->setEnabled( ok );
m_printPreview->setEnabled( ok );
m_showProperties->setEnabled( ok );
m_showPresentation->setEnabled( ok );
// update viewing actions
updateActions();
updateViewActions();
if ( !ok )
{
......@@ -353,6 +361,21 @@ bool Part::openURL(const KURL &url)
return b;
}
bool Part::closeURL()
{
m_find->setEnabled( false );
m_findNext->setEnabled( false );
m_saveAs->setEnabled( false );
m_printPreview->setEnabled( false );
m_showProperties->setEnabled( false );
m_showPresentation->setEnabled( false );
updateViewActions();
m_searchStarted = false;
if (!m_file.isEmpty()) m_watcher->removeFile(m_file);
m_document->closeDocument();
return KParts::ReadOnlyPart::closeURL();
}
void Part::slotWatchFile()
{
Settings::setWatchFile(m_watchFile->isChecked());
......@@ -388,19 +411,10 @@ void Part::slotDoFileDirty()
}
}
bool Part::closeURL()
{
m_saveAs->setEnabled( false );
m_printPreview->setEnabled( false );
if (!m_file.isEmpty()) m_watcher->removeFile(m_file);
m_document->closeDocument();
return KParts::ReadOnlyPart::closeURL();
}
void Part::updateActions()
void Part::updateViewActions()
{
bool ok = m_document->pages() > 0;
if ( ok )
bool opened = m_document->pages() > 0;
if ( opened )
{
bool atBegin = m_document->currentPage() < 1;
bool atEnd = m_document->currentPage() >= (m_document->pages() - 1);
......@@ -422,9 +436,6 @@ void Part::updateActions()
m_historyBack->setEnabled( false );
m_historyNext->setEnabled( false );
}
m_find->setEnabled( ok );
m_showProperties->setEnabled( ok );
m_showPresentation->setEnabled( ok );
}
void Part::enableTOC(bool enable)
......@@ -512,15 +523,18 @@ void Part::slotFind()
#endif
if ( dlg.exec() == QDialog::Accepted )
{
m_findNext->setEnabled( true );
m_document->searchText( 10, dlg.pattern(), false, dlg.options() & KFindDialog::CaseSensitive,
m_searchStarted = true;
m_document->searchText( PART_SEARCH_ID, dlg.pattern(), false, dlg.options() & KFindDialog::CaseSensitive,
KPDFDocument::NextMatch, true, Qt::red );
}
}
void Part::slotFindNext()
{
m_document->continueSearch( 10 );
if ( m_searchStarted )
m_document->continueSearch( PART_SEARCH_ID );
else
slotFind();
}
void Part::slotSaveFileAs()
......
......@@ -101,7 +101,7 @@ protected slots:
void slotShowProperties();
void slotShowPresentation();
// can be connected to widget elements
void updateActions();
void updateViewActions();
void enableTOC(bool enable);
public slots:
......@@ -125,7 +125,7 @@ private:
SearchWidget *m_searchWidget;
ThumbnailList *m_thumbnailList;
PageView *m_pageView;
QGuardedPtr<PresentationWidget> m_presentationWidget;
QGuardedPtr<PresentationWidget> m_presentationWidget;
// static instances counter
static unsigned int m_count;
......@@ -151,6 +151,7 @@ private:
KToggleAction* m_showMenuBarAction;
KToggleAction* m_showFullScreenAction;
bool m_actionsSearched;
bool m_searchStarted;
};
......
......@@ -46,6 +46,7 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
}
}
// if have no pixmap, draw blank page with gray cross and exit
if ( !pixmap )
{
if ( Settings::changeColors() &&
......@@ -62,11 +63,34 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
return;
}
// clear accessibility flag if not really needed
if ( !Settings::changeColors() || Settings::renderMode() == Settings::EnumRenderMode::Paper )
flags &= ~Accessibility;
// use backBuffer if accessiblity (page color processing) is needed
bool backBuffer = flags & Accessibility;
// use backBuffer even if we have to render highlights
if ( !backBuffer && (flags & Highlights) && !page->m_highlights.isEmpty() )
{
// precalc normalized limits rect for intersection
double nXMin = (double)limits.left() / (double)width,
nXMax = (double)(limits.right() + 1) / (double)width,
nYMin = (double)limits.top() / (double)height,
nYMax = (double)(limits.bottom() + 1) / (double)height;
// if an highlightRect intersects limits, use backBuffer for painting
QValueList< HighlightRect * >::const_iterator hIt = page->m_highlights.begin(), hEnd = page->m_highlights.end();
for ( ; hIt != hEnd; ++hIt )
{
HighlightRect * r = *hIt;
// intersection: A) highlightRect, B) normalized limits
if ( (r->left < nXMax) && (r->right > nXMin) && (r->top < nYMax) && (r->bottom > nYMin) )
{
backBuffer = true;
break;
}
}
}
// we have a pixmap to paint, now let's paint it using a direct or buffered painter
bool backBuffer = Settings::changeColors() &&
Settings::renderMode() != Settings::EnumRenderMode::Paper;
// if PagePainter::Accessibility is not in 'flags', disable backBuffer
backBuffer = backBuffer && (flags & Accessibility);
QPixmap * backPixmap = 0;
QPainter * p = destPainter;
if ( backBuffer )
......@@ -171,25 +195,52 @@ void PagePainter::paintPageOnPainter( const KPDFPage * page, int id, int flags,
}
// draw selection (note: it is rescaled since the text page is at 100% scale)
if ( ( flags & Highlights ) && !page->m_highlights.isEmpty() )
if ( backBuffer && ( flags & Highlights ) && !page->m_highlights.isEmpty() )
{
QImage backImage = backPixmap->convertToImage();
// draw highlights that are inside the 'limits' paint region
QValueList< HighlightRect * >::const_iterator hIt = page->m_highlights.begin(), hEnd = page->m_highlights.end();
for ( ; hIt != hEnd; ++hIt )
{
HighlightRect * r = *hIt;
int x = (int)( r->left * width ),
y = (int)( r->top * height ),
w = (int)( r->right * width ) - x,
h = (int)( r->bottom * height ) - y;
if ( w > 0 && h > 0 )
QRect highlightRect( (int)(r->left * width), (int)(r->top * height),
(int)((r->right - r->left) * width) + 1, (int)((r->bottom - r->top) * height) + 1 );
if ( highlightRect.isValid() && highlightRect.intersects( limits ) )
{
#if 0
// TODO setRasterOp is no more on Qt4 find an alternative way of doing this
p->setBrush( Qt::SolidPattern );
p->setPen( QPen( Qt::black, 1 ) ); // should not be necessary bug a Qt bug makes it necessary
p->setRasterOp( Qt::NotROP );
p->drawRect( x, y, w, h );
p->drawRect( highlightRect );
#else
// TODO this is the other way
// find out the rect to highlight on pixmap
highlightRect = highlightRect.intersect( limits );
highlightRect.moveBy( -limits.left(), -limits.top() );
// Manual yellow highlight
unsigned int * data = (unsigned int *)backImage.bits();
int val,
rh = r->color.red(),
gh = r->color.green(),
bh = r->color.blue();
for( int y = highlightRect.top(); y < highlightRect.bottom(); ++y )
{
int offset = y * backImage.width();
for( int x = highlightRect.left(); x < highlightRect.right(); ++x )
{
val = data[x + offset];
int newR = (qRed(val) * rh) / 255,
newG = (qGreen(val) * gh) / 255,
newB = (qBlue(val) * bh) / 255;
data[x + offset] = qRgba( newR, newG, newB, 255 );
}
}
#endif
}
}
backPixmap->convertFromImage( backImage );
}
// if was backbuffering, copy the backPixmap to destination
......
......@@ -53,6 +53,9 @@
#define ROUND(x) (int(x + 0.5))
// definition of searchID for this class
#define PAGEVIEW_SEARCH_ID 2
// structure used internally by PageView for data storage
class PageViewPrivate
{
......@@ -549,8 +552,7 @@ void PageView::keyPressEvent( QKeyEvent * e )
e->accept();
// if performing a selection or dyn zooming, disable keys handling
if ( !d->mouseSelectionRect.isNull() || d->mouseMidStartY != -1 ||
d->viewportMoveActive )
if ( !d->mouseSelectionRect.isNull() || d->mouseMidStartY != -1 )
return;
// handle 'find as you type' (based on khtml/khtmlview.cpp)
......@@ -562,8 +564,8 @@ void PageView::keyPressEvent( QKeyEvent * e )
if( d->typeAheadString.length() > 1 )
{
d->typeAheadString = d->typeAheadString.left( d->typeAheadString.length() - 1 );
bool found = d->document->searchText( 69, d->typeAheadString, true, false,
KPDFDocument::NextMatch, true, Qt::yellow );
bool found = d->document->searchText( PAGEVIEW_SEARCH_ID, d->typeAheadString, true, false,
KPDFDocument::NextMatch, true, Qt::yellow, true );
QString status = found ? i18n("Text found: \"%1\".") : i18n("Text not found: \"%1\".");
d->messageWindow->display( status.arg(d->typeAheadString.lower()),
found ? PageViewMessage::Find : PageViewMessage::Warning, 4000 );
......@@ -572,7 +574,7 @@ void PageView::keyPressEvent( QKeyEvent * e )
else
{
findAheadStop();
d->document->resetSearch( 69 );
d->document->resetSearch( PAGEVIEW_SEARCH_ID );
}
}
// F3: go to next occurrency
......@@ -581,7 +583,7 @@ void PageView::keyPressEvent( QKeyEvent * e )
// part doesn't get this key event because of the keyboard grab
d->findTimeoutTimer->stop(); // restore normal operation during possible messagebox is displayed
releaseKeyboard();
if ( d->document->continueSearch( 69 ) )
if ( d->document->continueSearch( PAGEVIEW_SEARCH_ID ) )
d->messageWindow->display( i18n("Text found: \"%1\".").arg(d->typeAheadString.lower()),
PageViewMessage::Find, 3000 );
d->findTimeoutTimer->start( 3000, true );
......@@ -592,11 +594,12 @@ void PageView::keyPressEvent( QKeyEvent * e )
{
findAheadStop();
}
// other key: add to text and search
else if( !e->text().isEmpty() )
{
d->typeAheadString += e->text();
bool found = d->document->searchText( 69, d->typeAheadString, false, false,
KPDFDocument::NextMatch, true, Qt::yellow );
bool found = d->document->searchText( PAGEVIEW_SEARCH_ID, d->typeAheadString, false, false,
KPDFDocument::NextMatch, true, Qt::yellow, true );
QString status = found ? i18n("Text found: \"%1\".") : i18n("Text not found: \"%1\".");
d->messageWindow->display( status.arg(d->typeAheadString.lower()),
found ? PageViewMessage::Find : PageViewMessage::Warning, 4000 );
......@@ -627,6 +630,10 @@ void PageView::keyPressEvent( QKeyEvent * e )
return;
}
// if viewport is moving, disable keys handling
if ( d->viewportMoveActive )
return;
// move/scroll page by using keys
switch ( e->key() )
{
......
......@@ -24,6 +24,9 @@
#include "core/document.h"
#include "conf/settings.h"
// definition of searchID for this class
#define SW_SEARCH_ID 3
// uncomment following to enable the case switching button
//#define SW_ENABLE_CASE_BUTTON
#define CLEAR_ID 1
......@@ -75,7 +78,7 @@ SearchWidget::SearchWidget( QWidget * parent, KPDFDocument * document )
void SearchWidget::slotTextChanged( const QString & text )
{
// if length<3 set 'red' text and send a blank string to document
QColor color = text.length() < 3 ? Qt::red : palette().active().text();
QColor color = text.length() < 3 ? Qt::darkRed : palette().active().text();
getLined( LEDIT_ID )->setPaletteForegroundColor( color );
m_inputDelayTimer->stop();
m_inputDelayTimer->start(333, true);
......@@ -83,11 +86,16 @@ void SearchWidget::slotTextChanged( const QString & text )
void SearchWidget::startSearch()
{
// search text if have more than 3 chars or else clear search
QString text = getLined( LEDIT_ID )->text();
bool ok = true;
if ( text.length() >= 3 )
m_document->searchText( 9, text, true, m_caseSensitive, KPDFDocument::AllDoc, false, Qt::green );
ok = m_document->searchText( SW_SEARCH_ID, text, true, m_caseSensitive, KPDFDocument::AllDoc, false, Qt::green );
else
m_document->resetSearch( 9 );
m_document->resetSearch( SW_SEARCH_ID );
// change color to red if text not found
QColor color = ok ? palette().active().text() : Qt::red;
getLined( LEDIT_ID )->setPaletteForegroundColor( color );
}
void SearchWidget::slotCaseChanged( int index )
......
......@@ -520,7 +520,7 @@ void ThumbnailWidget::paintEvent( QPaintEvent * e )
pixH = bookmarkPixmap->height();
clipRect = clipRect.intersect( QRect( m_pixmapWidth - pixW, 0, pixW, pixH ) );
if ( clipRect.isValid() )
p.drawPixmap( m_pixmapWidth - pixW, -pixH/8, *bookmarkPixmap );
p.drawPixmap( m_pixmapWidth - pixW, -pixH/8, *bookmarkPixmap );
}
}
}
......
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