Commit 6301d6b3 authored by Pino Toscano's avatar Pino Toscano

In the hope I didn not break anything, this is the new way of searching...

In the hope I didn not break anything, this is the new way of searching through the text pages. The new way stores the search point for every searchID, avoid to search from the beginning every time.
Also, the structure for backward search is there, (just...) need to add a findTextInternalBackward and do the job there.

svn path=/branches/work/kde4/playground/graphics/okular/; revision=545298
parent 59b26738
......@@ -811,9 +811,9 @@ bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStar
while ( 1 )
{
if ( lastMatch )
lastMatch = page->findText( text, NextRes , caseSensitive, lastMatch);
lastMatch = page->findText( searchID, text, NextRes, caseSensitive, lastMatch );
else
lastMatch = page->findText( text, FromTop, caseSensitive);
lastMatch = page->findText( searchID, text, FromTop, caseSensitive );
if ( !lastMatch )
break;
......@@ -853,9 +853,9 @@ bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStar
if ( lastPage && lastPage->number() == s->continueOnPage )
{
if ( newText )
match = lastPage->findText( text, FromTop , caseSensitive);
match = lastPage->findText( searchID, text, FromTop, caseSensitive );
else
match = lastPage->findText( text, NextRes, caseSensitive,&s->continueOnMatch );
match = lastPage->findText( searchID, text, NextRes, caseSensitive, &s->continueOnMatch );
if ( !match )
currentPage++;
}
......@@ -879,7 +879,7 @@ bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStar
if ( !page->hasSearchPage() )
requestTextPage( page->number() );
// if found a match on the current page, end the loop
if ( (match = page->findText( text, FromTop, caseSensitive )) )
if ( ( match = page->findText( searchID, text, FromTop, caseSensitive ) ) )
break;
currentPage++;
}
......@@ -957,9 +957,9 @@ bool KPDFDocument::searchText( int searchID, const QString & text, bool fromStar
while ( 1 )
{
if ( lastMatch )
lastMatch = page->findText( word, NextRes, caseSensitive, lastMatch );
lastMatch = page->findText( searchID, word, NextRes, caseSensitive, lastMatch );
else
lastMatch = page->findText( word, FromTop, caseSensitive);
lastMatch = page->findText( searchID, word, FromTop, caseSensitive);
if ( !lastMatch )
break;
......
......@@ -114,7 +114,7 @@ bool KPDFPage::hasTransition() const
}
RegularAreaRect * KPDFPage::findText( const QString & text, SearchDir dir, const bool strictCase,
RegularAreaRect * KPDFPage::findText( int searchID, const QString & text, SearchDir dir, bool strictCase,
const RegularAreaRect * lastRect/*, const Generator &generator */) const
{
RegularAreaRect* ret=0;
......@@ -124,7 +124,7 @@ RegularAreaRect * KPDFPage::findText( const QString & text, SearchDir dir, const
if (generator->preferInternalSearch())
return generator->;*/
ret=m_text->findText(text, dir, strictCase,lastRect);
ret=m_text->findText(searchID, text, dir, strictCase,lastRect);
return ret;
/*
......
......@@ -69,7 +69,7 @@ class OKULAR_EXPORT KPDFPage
//bool hasAnnotation( double x, double y ) const;
bool hasTransition() const;
RegularAreaRect * findText( const QString & text, SearchDir dir, bool strictCase, const RegularAreaRect * lastRect=0) const;
RegularAreaRect * findText( int searchID, const QString & text, SearchDir dir, bool strictCase, const RegularAreaRect * lastRect=0) const;
QString getText( const RegularAreaRect * rect ) const;
RegularAreaRect * getTextArea ( TextSelection * ) const;
// const ObjectRect * getObjectRect( double x, double y ) const;
......
......@@ -11,9 +11,19 @@
#include "misc.h"
#include <kdebug.h>
struct SearchPoint
{
SearchPoint() : theIt( 0 ), offset_begin( -1 ), offset_end( -1 ) {}
QList<KPDFTextEntity*>::Iterator theIt;
int offset_begin;
int offset_end;
};
KPDFTextPage::~KPDFTextPage()
{
qDeleteAll(m_words);
qDeleteAll(m_searchPoints);
}
RegularAreaRect * KPDFTextPage::getTextArea ( TextSelection * sel) const
......@@ -134,82 +144,67 @@ RegularAreaRect * KPDFTextPage::getTextArea ( TextSelection * sel) const
}
RegularAreaRect* KPDFTextPage::findText(const QString &query, SearchDir & direct,
const bool &strictCase, const RegularAreaRect *area)
RegularAreaRect* KPDFTextPage::findText(int searchID, const QString &query, SearchDir & direct,
bool strictCase, const RegularAreaRect *area)
{
SearchDir dir=direct;
// invalid search request
if (query.isEmpty() || (area->isNull() && dir!=FromTop))
if ( query.isEmpty() || area->isNull() )
return 0;
QList<KPDFTextEntity*>::Iterator start;
if (dir == FromTop)
QList<KPDFTextEntity*>::Iterator end;
if ( !m_searchPoints.contains( searchID ) )
{
start=m_words.begin();
dir=NextRes;
// if no previous run of this search is found, then set it to start
// from the beginning (respecting the search direction)
if ( dir == NextRes )
dir = FromTop;
else if ( dir == PrevRes )
dir = FromBottom;
}
else
{
// locate the current search position
QString * str=0;
int j=0, len=0, queryLeft=query.length()-1;
bool haveMatch=false;
QList<KPDFTextEntity*>::Iterator it;
for( it=m_words.begin() ; it != m_words.end(); ++it )
bool forward = true;
switch ( dir )
{
str= &((*it)->txt);
continue;
len=str->length()-1;
// we have equal (or less then) area of the query left as the lengt of the current
// entity
if (queryLeft<=len)
{
if (((strictCase)
? (*str != query)
: (str->toLower() != query.toLower() ))
|| (!(area->intersects((*it)->area))))
{
// we not have matched
// this means we dont have a complete match
// we need to get back to query start
// and continue the search from this place
haveMatch=false;
j=0;
queryLeft=query.length()-1;
}
else
{
// we have a match
// move the current position in the query
// to the position after the length of this string
// we matched
// substract the length of the current entity from
// the left length of the query
haveMatch=true;
j+=qMin(queryLeft,len);
queryLeft-=qMin(queryLeft,len);
}
}
if (haveMatch && queryLeft==0 && j==query.length()-1)
case FromTop:
start = m_words.begin();
end = m_words.end();
break;
}
start=it;
}
switch (dir)
case FromBottom:
start = m_words.end();
end = m_words.begin();
if ( !m_words.isEmpty() )
{
case PrevRes:
return findTextInternal(query,false, strictCase, start,m_words.begin());
--start;
}
forward = false;
break;
case FromTop:
case NextRes:
return findTextInternal(query,true, strictCase, start,m_words.end());
start = m_searchPoints[ searchID ]->theIt;
end = m_words.end();
break;
case PrevRes:
start = m_searchPoints[ searchID ]->theIt;
end = m_words.begin();
forward = false;
break;
};
RegularAreaRect* ret = 0;
if ( forward )
{
ret = findTextInternalForward( searchID, query, strictCase, start, end );
}
return 0;
// TODO implement backward search
#if 0
else
{
ret = findTextInternalBackward( searchID, query, strictCase, start, end );
}
#endif
return ret;
}
RegularAreaRect* KPDFTextPage::findTextInternal(const QString &query, bool forward,
RegularAreaRect* KPDFTextPage::findTextInternalForward(int searchID, const QString &query,
bool strictCase, const QList<KPDFTextEntity*>::Iterator &start,
const QList<KPDFTextEntity*>::Iterator &end)
{
......@@ -220,17 +215,26 @@ RegularAreaRect* KPDFTextPage::findTextInternal(const QString &query, bool forwa
// len is the length of the string in kpdftextentity
// queryLeft is the length of the query we have left
QString str;
KPDFTextEntity* curEntity = 0;
int j=0, len=0, queryLeft=query.length();
int offset = 0;
bool haveMatch=false;
bool dontIncrement=false;
QList<KPDFTextEntity*>::Iterator it;
// we dont support backward search yet
for( it=start ; it != end; (!dontIncrement) ? (++it) : it )
bool offsetMoved = false;
QList<KPDFTextEntity*>::Iterator it = start;
for ( ; it != end; ++it )
{
// a static cast would be faster?
str=(*it)->txt;
// TODO This is impossible, ask niedakh if he wanted a || ?
if (query.mid(j,1)==" " && query.mid(j,1)=="\n")
curEntity = *it;
str = curEntity->txt;
if ( !offsetMoved && ( it == start ) )
{
if ( m_searchPoints.contains( searchID ) )
{
offset = qMax( m_searchPoints[ searchID ]->offset_end, 0 );
}
offsetMoved = true;
}
if ( query.at(j).isSpace() )
{
// lets match newline as a space
#ifdef DEBUG_TEXTPAGE
......@@ -248,13 +252,13 @@ RegularAreaRect* KPDFTextPage::findTextInternal(const QString &query, bool forwa
dontIncrement=false;
len=str.length();
int min=qMin(queryLeft,len);
kDebug(1223) << str.left(min) << " : " << query.mid(j,min) << endl;
kDebug(1223) << str.mid(offset,min) << " : " << query.mid(j,min) << endl;
// we have equal (or less then) area of the query left as the lengt of the current
// entity
if ((strictCase)
? (str.left(min) != query.mid(j,min))
: (str.left(min).toLower() != query.mid(j,min).toLower())
? (str.mid(offset,min) != query.mid(j,min))
: (str.mid(offset,min).toLower() != query.mid(j,min).toLower())
)
{
// we not have matched
......@@ -267,6 +271,7 @@ RegularAreaRect* KPDFTextPage::findTextInternal(const QString &query, bool forwa
kDebug(1223) << "\tnot matched" << endl;
#endif
j=0;
offset = 0;
queryLeft=query.length();
}
else
......@@ -281,7 +286,7 @@ RegularAreaRect* KPDFTextPage::findTextInternal(const QString &query, bool forwa
kDebug(1223) << "\tmatched" << endl;
#endif
haveMatch=true;
ret->append( (*it)->area );
ret->append( curEntity->area );
j+=min;
queryLeft-=min;
}
......@@ -289,11 +294,28 @@ RegularAreaRect* KPDFTextPage::findTextInternal(const QString &query, bool forwa
if (haveMatch && queryLeft==0 && j==query.length())
{
// save or update the search point for the current searchID
if ( !m_searchPoints.contains( searchID ) )
{
SearchPoint* newsp = new SearchPoint;
m_searchPoints.insert( searchID, newsp );
}
SearchPoint* sp = m_searchPoints[ searchID ];
sp->theIt = it;
sp->offset_begin = j;
sp->offset_end = j + qMin( queryLeft, len );
ret->simplify();
return ret;
}
}
// end of loop - it means that we've ended the textentities
if ( m_searchPoints.contains( searchID ) )
{
SearchPoint* sp = m_searchPoints[ searchID ];
m_searchPoints.remove( searchID );
delete sp;
}
delete ret;
return 0;
}
......
......@@ -12,6 +12,7 @@
#include <qlist.h>
#include <qmap.h>
#include <qstringlist.h>
#include "area.h"
class TextSelection;
......@@ -21,6 +22,9 @@ class TextSelection;
*! @enum SearchDir FromTop
* Searching from top of the page, next result is to be found,
* there was no earlier search result.
*! @enum SearchDir FromBottom
* Searching from bottom of the page, next result is to be found,
* there was no earlier search result.
*! @enum SearchDir NextRes
* Searching for the next result on the page, earlier result should be
* located so we search from the last result not from the beginning of the
......@@ -30,7 +34,7 @@ class TextSelection;
* located so we search from the last result not from the beginning of the
* page.
*/
typedef enum SearchDir{ FromTop, NextRes, PrevRes };
typedef enum SearchDir{ FromTop, FromBottom, NextRes, PrevRes };
/*! @struct KPDFTextEntity
* @short Abstract textentity of KPDF
......@@ -58,10 +62,12 @@ struct KPDFTextEntity
~KPDFTextEntity() { delete area; };
};
struct SearchPoint;
class KPDFTextPage {
public:
RegularAreaRect* findText(const QString &query, SearchDir & direct,
const bool &strictCase, const RegularAreaRect *area);
RegularAreaRect* findText(int searchID, const QString &query, SearchDir & direct,
bool strictCase, const RegularAreaRect *area);
QString getText(const RegularAreaRect *rect) const;
RegularAreaRect * getTextArea ( TextSelection* ) const;
KPDFTextPage(QList<KPDFTextEntity*> words) : m_words(words) {};
......@@ -70,9 +76,11 @@ class KPDFTextPage {
{ m_words.append(new KPDFTextEntity(txt,area) ); };
~KPDFTextPage();
private:
RegularAreaRect * findTextInternal(const QString &query, bool forward,
bool strictCase, const QList<KPDFTextEntity*>::Iterator &start, const QList<KPDFTextEntity*>::Iterator &end);
RegularAreaRect * findTextInternalForward(int searchID, const QString &query,
bool strictCase, const QList<KPDFTextEntity*>::Iterator &start,
const QList<KPDFTextEntity*>::Iterator &end);
QList<KPDFTextEntity*> m_words;
QMap<int, SearchPoint*> m_searchPoints;
};
......
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