mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-05 23:49:20 +00:00
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
This commit is contained in:
parent
6fb7840575
commit
9e73b4235e
9
TODO
9
TODO
|
@ -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
|
||||
|
|
|
@ -35,11 +35,13 @@
|
|||
#include "conf/settings.h"
|
||||
|
||||
// structures used internally by KPDFDocument for local variables storage
|
||||
class AllocatedPixmap;
|
||||
class RunningSearch;
|
||||
class KPDFDocumentPrivate
|
||||
{
|
||||
public:
|
||||
// find descriptors (can handle multiple searches)
|
||||
QMap< int, class RunningSearch * > searches;
|
||||
// find descriptors, mapped by ID (we handle multiple searches)
|
||||
QMap< int, RunningSearch * > searches;
|
||||
|
||||
// cached stuff
|
||||
QString docFileName;
|
||||
|
@ -52,7 +54,7 @@ class KPDFDocumentPrivate
|
|||
// observers / requests / allocator stuff
|
||||
QMap< int, DocumentObserver * > observers;
|
||||
QValueList< PixmapRequest * > pixmapRequestsStack;
|
||||
QValueList< class AllocatedPixmap * > allocatedPixmapsFifo;
|
||||
QValueList< AllocatedPixmap * > allocatedPixmapsFifo;
|
||||
int allocatedPixmapsTotalMemory;
|
||||
|
||||
// timers (memory checking / info saver)
|
||||
|
@ -72,19 +74,18 @@ struct AllocatedPixmap
|
|||
|
||||
struct RunningSearch
|
||||
{
|
||||
// publicly accessible fields
|
||||
QString text;
|
||||
bool caseSensitive;
|
||||
bool moveViewport;
|
||||
KPDFDocument::SearchType type;
|
||||
QColor highlightColor;
|
||||
// store search properties
|
||||
int continueOnPage;
|
||||
HighlightRect continueOnMatch;
|
||||
QValueList< int > highlightedPages;
|
||||
|
||||
int lastPage;
|
||||
HighlightRect lastMatch;
|
||||
QValueList< int > matchedPages;
|
||||
|
||||
// public constructor: initialize data
|
||||
|
||||
// fields related to previous searches (used for 'continueSearch')
|
||||
QString cachedString;
|
||||
KPDFDocument::SearchType cachedType;
|
||||
bool cachedCaseSensitive;
|
||||
bool cachedViewportMove;
|
||||
bool cachedNoDialogs;
|
||||
QColor cachedColor;
|
||||
};
|
||||
|
||||
#define foreachObserver( cmd ) {\
|
||||
|
@ -415,7 +416,7 @@ void KPDFDocument::requestPixmaps( const QValueList< PixmapRequest * > & request
|
|||
// add request to the 'stack' at the right place
|
||||
if ( !request->priority )
|
||||
// add priority zero requests to the top of the stack
|
||||
d->pixmapRequestsStack.push_back( request );
|
||||
d->pixmapRequestsStack.append( request );
|
||||
else
|
||||
{
|
||||
// insert in stack sorted by priority
|
||||
|
@ -550,57 +551,58 @@ void KPDFDocument::setNextViewport()
|
|||
}
|
||||
|
||||
|
||||
bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStart,
|
||||
bool caseSensitive, SearchType type, bool moveViewport, const QColor & color )
|
||||
bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStart, bool caseSensitive,
|
||||
SearchType type, bool moveViewport, const QColor & color, bool noDialogs )
|
||||
{
|
||||
// add a new search descriptor to runningSearches
|
||||
// if searchID search not recorded, create new descriptor and init params
|
||||
if ( !d->searches.contains( searchID ) )
|
||||
{
|
||||
RunningSearch * search = new RunningSearch();
|
||||
search->text = text;
|
||||
search->caseSensitive = caseSensitive;
|
||||
search->moveViewport = moveViewport;
|
||||
search->type = type;
|
||||
search->highlightColor = color;
|
||||
search->lastPage = -1;
|
||||
search->continueOnPage = -1;
|
||||
d->searches[ searchID ] = search;
|
||||
}
|
||||
|
||||
// get search descriptor and update stucture
|
||||
RunningSearch * s = d->searches[ searchID ];
|
||||
if ( text != s->text )
|
||||
s->text = text;
|
||||
if ( type != s->type )
|
||||
s->type = type;
|
||||
|
||||
// update search stucture
|
||||
bool newText = text != s->cachedString;
|
||||
s->cachedString = text;
|
||||
s->cachedType = type;
|
||||
s->cachedCaseSensitive = caseSensitive;
|
||||
s->cachedViewportMove = moveViewport;
|
||||
s->cachedNoDialogs = noDialogs;
|
||||
s->cachedColor = color;
|
||||
|
||||
// global data for search
|
||||
bool foundAMatch = false;
|
||||
QValueList< int > pagesToNotify;
|
||||
|
||||
// remove highlights from pages and queue them for notifying changes
|
||||
pagesToNotify += s->highlightedPages;
|
||||
QValueList< int >::iterator it = s->highlightedPages.begin(), end = s->highlightedPages.end();
|
||||
for ( ; it != end; ++it )
|
||||
pages_vector[ *it ]->deleteHighlights( searchID );
|
||||
s->highlightedPages.clear();
|
||||
|
||||
// set hourglass cursor
|
||||
QApplication::setOverrideCursor( waitCursor );
|
||||
|
||||
// unhighlight pages and inform observers about that
|
||||
QValueList< int >::iterator it = s->matchedPages.begin(), end = s->matchedPages.end();
|
||||
for ( ; it != end; ++it )
|
||||
{
|
||||
int pageNumber = *it;
|
||||
pages_vector[ pageNumber ]->deleteHighlights( searchID );
|
||||
foreachObserver( notifyPageChanged( pageNumber, DocumentObserver::Highlights ) );
|
||||
}
|
||||
s->matchedPages.clear();
|
||||
|
||||
//
|
||||
bool foundAMatch = false;
|
||||
|
||||
// [1] ALLDOC - proces all document marking pages
|
||||
// 1. ALLDOC - proces all document marking pages
|
||||
if ( type == AllDoc )
|
||||
{
|
||||
// perform a linear search/mark
|
||||
// search and highlight text on all pages
|
||||
QValueVector< KPDFPage * >::iterator it = pages_vector.begin(), end = pages_vector.end();
|
||||
for ( ; it != end; ++it )
|
||||
{
|
||||
// get page (from the first to the last)
|
||||
KPDFPage * page = *it;
|
||||
if ( !page->hasSearchPage() )
|
||||
requestTextPage( page->number() );
|
||||
int pageNumber = page->number();
|
||||
|
||||
bool found = false;
|
||||
// request search page if needed
|
||||
if ( !page->hasSearchPage() )
|
||||
requestTextPage( pageNumber );
|
||||
|
||||
// loop on a page adding highlights for all found items
|
||||
bool addedHighlights = false;
|
||||
HighlightRect * lastMatch = 0;
|
||||
while ( 1 )
|
||||
{
|
||||
|
@ -612,66 +614,64 @@ bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStar
|
|||
if ( !lastMatch )
|
||||
break;
|
||||
|
||||
found = true;
|
||||
// add highligh rect to the page
|
||||
lastMatch->id = searchID;
|
||||
lastMatch->color = color;
|
||||
page->setHighlight( lastMatch );
|
||||
s->lastMatch = *lastMatch;
|
||||
addedHighlights = true;
|
||||
}
|
||||
|
||||
if ( found )
|
||||
// if added highlights, udpate internals and queue page for notify
|
||||
if ( addedHighlights )
|
||||
{
|
||||
foundAMatch = true;
|
||||
s->matchedPages.append( page->number() );
|
||||
s->highlightedPages.append( pageNumber );
|
||||
if ( !pagesToNotify.contains( pageNumber ) )
|
||||
pagesToNotify.append( pageNumber );
|
||||
}
|
||||
}
|
||||
// send page lists
|
||||
foreachObserver( notifySetup( pages_vector, false ) );
|
||||
|
||||
// reset cursor to previous shape
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
// send page lists if found anything new
|
||||
//if ( foundAMatch ) ?maybe?
|
||||
foreachObserver( notifySetup( pages_vector, false ) );
|
||||
}
|
||||
// [2] NEXTMATCH - find next matching item (or start from top)
|
||||
else if ( s->type == NextMatch )
|
||||
// 2. NEXTMATCH - find next matching item (or start from top)
|
||||
else if ( type == NextMatch )
|
||||
{
|
||||
// find out from where to start/resume search from
|
||||
int viewportPage = (*d->viewportIterator).pageNumber;
|
||||
int currentPage = 0;
|
||||
KPDFPage * lastPage = 0;
|
||||
if ( !fromStart )
|
||||
{
|
||||
currentPage = s->lastPage != -1 ? s->lastPage : viewportPage;
|
||||
lastPage = pages_vector[ currentPage ];
|
||||
}
|
||||
else
|
||||
{
|
||||
s->lastPage = 0;
|
||||
}
|
||||
|
||||
HighlightRect * r = 0;
|
||||
int currentPage = fromStart ? 0 : ((s->continueOnPage != -1) ? s->continueOnPage : viewportPage);
|
||||
KPDFPage * lastPage = fromStart ? 0 : pages_vector[ currentPage ];
|
||||
|
||||
// continue checking last SearchPage first (if it is the current page)
|
||||
if ( lastPage && lastPage->number() == s->lastPage )
|
||||
HighlightRect * r = 0;
|
||||
if ( lastPage && lastPage->number() == s->continueOnPage )
|
||||
{
|
||||
r = lastPage->searchText( text, caseSensitive, &s->lastMatch );
|
||||
if ( !r )
|
||||
if ( newText )
|
||||
r = lastPage->searchText( text, caseSensitive );
|
||||
else
|
||||
r = lastPage->searchText( text, caseSensitive, &s->continueOnMatch );
|
||||
if ( r )
|
||||
{
|
||||
lastPage->deleteHighlights( searchID );
|
||||
currentPage++;
|
||||
s->continueOnMatch = *r;
|
||||
s->highlightedPages.append( currentPage );
|
||||
}
|
||||
else
|
||||
{
|
||||
s->lastMatch = *r;
|
||||
s->matchedPages.push_back( currentPage );
|
||||
}
|
||||
currentPage++;
|
||||
}
|
||||
|
||||
// if no match found, loop through the whole doc, starting from currentPage
|
||||
if ( !r )
|
||||
{
|
||||
// loop through the whole document
|
||||
const int pageCount = pages_vector.count();
|
||||
for ( int i = 0; i < pageCount; i++ )
|
||||
{
|
||||
if ( currentPage >= pageCount )
|
||||
{
|
||||
if ( /*FIXME !findAhead &&*/ KMessageBox::questionYesNo(0, i18n("End of document reached.\nContinue from the beginning?")) == KMessageBox::Yes )
|
||||
if ( !noDialogs && KMessageBox::questionYesNo(0, i18n("End of document reached.\nContinue from the beginning?")) == KMessageBox::Yes )
|
||||
currentPage = 0;
|
||||
else
|
||||
break;
|
||||
|
@ -681,62 +681,75 @@ bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStar
|
|||
requestTextPage( page->number() );
|
||||
if ( (r = page->searchText( text, caseSensitive )) )
|
||||
{
|
||||
s->lastPage = currentPage;
|
||||
s->lastMatch = *r;
|
||||
s->matchedPages.push_back( currentPage );
|
||||
s->continueOnPage = currentPage;
|
||||
s->continueOnMatch = *r;
|
||||
s->highlightedPages.append( currentPage );
|
||||
break;
|
||||
}
|
||||
currentPage++;
|
||||
}
|
||||
}
|
||||
|
||||
// reset cursor to previous shape
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
// if a match has been found..
|
||||
if ( r )
|
||||
{
|
||||
// add highlight to the page
|
||||
foundAMatch = true;
|
||||
// ..add highlight to the page..
|
||||
int pageNumber = currentPage;
|
||||
KPDFPage * foundPage = pages_vector[ currentPage ];
|
||||
r->id = searchID;
|
||||
r->color = color;
|
||||
foundPage->setHighlight( r );
|
||||
|
||||
// move the viewport to show the searched word centered
|
||||
DocumentViewport searchViewport( pageNumber );
|
||||
searchViewport.reCenter.enabled = true;
|
||||
searchViewport.reCenter.normalizedCenterX = (r->left + r->right) / 2.0;
|
||||
searchViewport.reCenter.normalizedCenterY = (r->top + r->bottom) / 2.0;
|
||||
setViewport( searchViewport, -1, true );
|
||||
// ..queue page for notifying changes..
|
||||
if ( !pagesToNotify.contains( pageNumber ) )
|
||||
pagesToNotify.append( pageNumber );
|
||||
|
||||
// notify all observers about hilighting chages
|
||||
foreachObserver( notifyPageChanged( pageNumber, DocumentObserver::Highlights ) );
|
||||
// ..move the viewport to show the searched word centered
|
||||
if ( moveViewport )
|
||||
{
|
||||
DocumentViewport searchViewport( pageNumber );
|
||||
searchViewport.reCenter.enabled = true;
|
||||
searchViewport.reCenter.normalizedCenterX = (r->left + r->right) / 2.0;
|
||||
searchViewport.reCenter.normalizedCenterY = (r->top + r->bottom) / 2.0;
|
||||
setViewport( searchViewport, -1, true );
|
||||
}
|
||||
}
|
||||
else if ( true /*FIXME !findAhead*/ )
|
||||
else if ( !noDialogs )
|
||||
KMessageBox::information( 0, i18n("No matches found for '%1'.").arg( text ) );
|
||||
}
|
||||
// 3. PREVMATCH //TODO
|
||||
else if ( type == PrevMatch )
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
// 4. GOOGLELIKE //TODO
|
||||
else if ( type == GoogleLike )
|
||||
{
|
||||
//TODO
|
||||
}
|
||||
|
||||
// reset cursor to previous shape
|
||||
QApplication::restoreOverrideCursor();
|
||||
// notify observers about highlights changes
|
||||
QValueList< int >::iterator nIt = pagesToNotify.begin(), nEnd = pagesToNotify.end();
|
||||
for ( ; nIt != nEnd; ++nIt )
|
||||
foreachObserver( notifyPageChanged( *nIt, DocumentObserver::Highlights ) );
|
||||
|
||||
// return if search has found one or more matches
|
||||
return foundAMatch;
|
||||
}
|
||||
|
||||
|
||||
bool KPDFDocument::continueSearch( int searchID )
|
||||
{
|
||||
// check if searchID is present in runningSearches
|
||||
if ( !d->searches.contains( searchID ) )
|
||||
return false;
|
||||
|
||||
// get previous parameters for search
|
||||
// start search with cached parameters from last search by searchID
|
||||
RunningSearch * p = d->searches[ searchID ];
|
||||
return searchText( searchID, p->text, false, p->caseSensitive, p->type, p->moveViewport, p->highlightColor );
|
||||
return searchText( searchID, p->cachedString, false, p->cachedCaseSensitive,
|
||||
p->cachedType, p->cachedViewportMove, p->cachedColor,
|
||||
p->cachedNoDialogs );
|
||||
}
|
||||
|
||||
void KPDFDocument::resetSearch( int searchID )
|
||||
|
@ -749,14 +762,16 @@ void KPDFDocument::resetSearch( int searchID )
|
|||
RunningSearch * s = d->searches[ searchID ];
|
||||
|
||||
// unhighlight pages and inform observers about that
|
||||
QValueList< int >::iterator it = s->matchedPages.begin(), end = s->matchedPages.end();
|
||||
QValueList< int >::iterator it = s->highlightedPages.begin(), end = s->highlightedPages.end();
|
||||
for ( ; it != end; ++it )
|
||||
{
|
||||
int pageNumber = *it;
|
||||
pages_vector[ pageNumber ]->deleteHighlights( searchID );
|
||||
foreachObserver( notifyPageChanged( pageNumber, DocumentObserver::Highlights ) );
|
||||
}
|
||||
s->matchedPages.clear();
|
||||
|
||||
// send the setup signal too (to update views that filter on matches)
|
||||
foreachObserver( notifySetup( pages_vector, false ) );
|
||||
|
||||
// remove serch from the runningSearches list and delete it
|
||||
d->searches.remove( searchID );
|
||||
|
|
|
@ -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 );
|
||||
|
|
58
part.cpp
58
part.cpp
|
@ -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()
|
||||
void Part::updateViewActions()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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()
|
||||
|
|
5
part.h
5
part.h
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue