Cleaned up the API of TextEntity and TextPage, ready for release ;)

svn path=/trunk/playground/graphics/okular/; revision=607211
remotes/origin/KDE/4.0
Tobias Koenig 20 years ago
parent 4848631daf
commit 471c71d256
  1. 144
      core/textpage.cpp
  2. 124
      core/textpage.h

@ -15,19 +15,81 @@
using namespace Okular; using namespace Okular;
struct Okular::SearchPoint class SearchPoint
{ {
SearchPoint() : theIt( 0 ), offset_begin( -1 ), offset_end( -1 ) {} public:
QList<TextEntity*>::ConstIterator theIt; SearchPoint()
int offset_begin; : theIt( 0 ), offset_begin( -1 ), offset_end( -1 )
int offset_end; {
}
TextEntity::List::ConstIterator theIt;
int offset_begin;
int offset_end;
};
TextEntity::TextEntity( const QString &text, NormalizedRect *area )
: m_text( text ), m_area( area ), d( 0 )
{
}
TextEntity::~TextEntity()
{
delete m_area;
}
QString TextEntity::text() const
{
return m_text;
}
NormalizedRect* TextEntity::area() const
{
return m_area;
}
class TextPage::Private
{
public:
Private( const TextEntity::List &words )
: m_words( words )
{
}
~Private()
{
qDeleteAll( m_words );
qDeleteAll( m_searchPoints );
}
RegularAreaRect * findTextInternalForward( int searchID, const QString &query,
Qt::CaseSensitivity caseSensitivity,
const TextEntity::List::ConstIterator &start,
const TextEntity::List::ConstIterator &end );
TextEntity::List m_words;
QMap< int, SearchPoint* > m_searchPoints;
}; };
TextPage::TextPage()
: d( new Private( TextEntity::List() ) )
{
}
TextPage::TextPage( const TextEntity::List &words )
: d( new Private( words ) )
{
}
TextPage::~TextPage() TextPage::~TextPage()
{ {
qDeleteAll(m_words); delete d;
qDeleteAll(m_searchPoints); }
void TextPage::append( const QString &text, NormalizedRect *area )
{
d->m_words.append( new TextEntity( text, area ) );
} }
RegularAreaRect * TextPage::textArea ( TextSelection * sel) const RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
@ -61,9 +123,9 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
#ifdef DEBUG_TEXTPAGE #ifdef DEBUG_TEXTPAGE
kWarning() << "running first loop\n"; kWarning() << "running first loop\n";
#endif #endif
for (it=0;it<m_words.count();it++) for (it=0;it<d->m_words.count();it++)
{ {
tmp=m_words[it]->area; tmp=d->m_words[it]->area();
if (tmp->contains(startCx,startCy) if (tmp->contains(startCx,startCy)
|| ( tmp->top <= startCy && tmp->bottom >= startCy && tmp->left >= startCx ) || ( tmp->top <= startCy && tmp->bottom >= startCy && tmp->left >= startCx )
|| ( tmp->top >= startCy)) || ( tmp->top >= startCy))
@ -71,7 +133,7 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
/// we have found the (rx,ry)x(tx,ty) /// we have found the (rx,ry)x(tx,ty)
itB=it; itB=it;
#ifdef DEBUG_TEXTPAGE #ifdef DEBUG_TEXTPAGE
kWarning() << "start is " << itB << " count is " << m_words.count() << endl; kWarning() << "start is " << itB << " count is " << d->m_words.count() << endl;
#endif #endif
break; break;
} }
@ -89,9 +151,9 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
#ifdef DEBUG_TEXTPAGE #ifdef DEBUG_TEXTPAGE
kWarning() << "running second loop\n"; kWarning() << "running second loop\n";
#endif #endif
for (it=m_words.count()-1; it>=itB;it--) for (it=d->m_words.count()-1; it>=itB;it--)
{ {
tmp=m_words[it]->area; tmp=d->m_words[it]->area();
if (tmp->contains(endCx,endCy) if (tmp->contains(endCx,endCy)
|| ( tmp->top <= endCy && tmp->bottom >= endCy && tmp->right <= endCx ) || ( tmp->top <= endCy && tmp->bottom >= endCy && tmp->right <= endCx )
|| ( tmp->bottom <= endCy)) || ( tmp->bottom <= endCy))
@ -99,7 +161,7 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
/// we have found the (ux,uy)x(vx,vy) /// we have found the (ux,uy)x(vx,vy)
itE=it; itE=it;
#ifdef DEBUG_TEXTPAGE #ifdef DEBUG_TEXTPAGE
kWarning() << "ending is " << itE << " count is " << m_words.count() << endl; kWarning() << "ending is " << itE << " count is " << d->m_words.count() << endl;
kWarning () << "conditions " << tmp->contains(endCx,endCy) << " " kWarning () << "conditions " << tmp->contains(endCx,endCy) << " "
<< ( tmp->top <= endCy && tmp->bottom >= endCy && tmp->right <= endCx ) << " " << << ( tmp->top <= endCy && tmp->bottom >= endCy && tmp->right <= endCx ) << " " <<
( tmp->top >= endCy) << endl; ( tmp->top >= endCy) << endl;
@ -116,8 +178,8 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
if (sel->itB()!=-1 && sel->itE()!=-1) if (sel->itB()!=-1 && sel->itE()!=-1)
{ {
start=m_words[sel->itB()]->area; start=d->m_words[sel->itB()]->area();
end=m_words[sel->itE()]->area; end=d->m_words[sel->itE()]->area();
NormalizedRect first,second,third;/* NormalizedRect first,second,third;/*
first.right=1; first.right=1;
@ -133,7 +195,7 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
first.bottom=end->bottom; first.bottom=end->bottom;
for (it=qMin(sel->itB(),sel->itE()); it<=qMax(sel->itB(),sel->itE());it++) for (it=qMin(sel->itB(),sel->itE()); it<=qMax(sel->itB(),sel->itE());it++)
{ {
tmp=m_words[it]->area; tmp=d->m_words[it]->area();
if (tmp->intersects(&first)) if (tmp->intersects(&first))
ret->append(tmp); ret->append(tmp);
} }
@ -152,7 +214,7 @@ RegularAreaRect * TextPage::textArea ( TextSelection * sel) const
int selMax = qMax( sel->itB(), sel->itE() ); int selMax = qMax( sel->itB(), sel->itE() );
for ( it = qMin( sel->itB(), sel->itE() ); it <= selMax; ++it ) for ( it = qMin( sel->itB(), sel->itE() ); it <= selMax; ++it )
{ {
tmp=m_words[it]->area; tmp=d->m_words[it]->area();
if (tmp->intersects(&first) || tmp->intersects(&second) || tmp->intersects(&third)) if (tmp->intersects(&first) || tmp->intersects(&second) || tmp->intersects(&third))
ret->append(new NormalizedRect(*tmp)); ret->append(new NormalizedRect(*tmp));
} }
@ -172,9 +234,9 @@ RegularAreaRect* TextPage::findText( int searchID, const QString &query, SearchD
// invalid search request // invalid search request
if ( query.isEmpty() || area->isNull() ) if ( query.isEmpty() || area->isNull() )
return 0; return 0;
QList<TextEntity*>::ConstIterator start; TextEntity::List::ConstIterator start;
QList<TextEntity*>::ConstIterator end; TextEntity::List::ConstIterator end;
if ( !m_searchPoints.contains( searchID ) ) if ( !d->m_searchPoints.contains( searchID ) )
{ {
// if no previous run of this search is found, then set it to start // if no previous run of this search is found, then set it to start
// from the beginning (respecting the search direction) // from the beginning (respecting the search direction)
@ -187,32 +249,32 @@ RegularAreaRect* TextPage::findText( int searchID, const QString &query, SearchD
switch ( dir ) switch ( dir )
{ {
case FromTop: case FromTop:
start = m_words.begin(); start = d->m_words.begin();
end = m_words.end(); end = d->m_words.end();
break; break;
case FromBottom: case FromBottom:
start = m_words.end(); start = d->m_words.end();
end = m_words.begin(); end = d->m_words.begin();
if ( !m_words.isEmpty() ) if ( !d->m_words.isEmpty() )
{ {
--start; --start;
} }
forward = false; forward = false;
break; break;
case NextResult: case NextResult:
start = m_searchPoints[ searchID ]->theIt; start = d->m_searchPoints[ searchID ]->theIt;
end = m_words.end(); end = d->m_words.end();
break; break;
case PreviousResult: case PreviousResult:
start = m_searchPoints[ searchID ]->theIt; start = d->m_searchPoints[ searchID ]->theIt;
end = m_words.begin(); end = d->m_words.begin();
forward = false; forward = false;
break; break;
}; };
RegularAreaRect* ret = 0; RegularAreaRect* ret = 0;
if ( forward ) if ( forward )
{ {
ret = findTextInternalForward( searchID, query, caseSensitivity, start, end ); ret = d->findTextInternalForward( searchID, query, caseSensitivity, start, end );
} }
// TODO implement backward search // TODO implement backward search
#if 0 #if 0
@ -225,10 +287,10 @@ RegularAreaRect* TextPage::findText( int searchID, const QString &query, SearchD
} }
RegularAreaRect* TextPage::findTextInternalForward( int searchID, const QString &_query, RegularAreaRect* TextPage::Private::findTextInternalForward( int searchID, const QString &_query,
Qt::CaseSensitivity caseSensitivity, Qt::CaseSensitivity caseSensitivity,
const QList<TextEntity*>::ConstIterator &start, const TextEntity::List::ConstIterator &start,
const QList<TextEntity*>::ConstIterator &end ) const TextEntity::List::ConstIterator &end )
{ {
RegularAreaRect* ret=new RegularAreaRect; RegularAreaRect* ret=new RegularAreaRect;
@ -244,11 +306,11 @@ RegularAreaRect* TextPage::findTextInternalForward( int searchID, const QString
bool haveMatch=false; bool haveMatch=false;
bool dontIncrement=false; bool dontIncrement=false;
bool offsetMoved = false; bool offsetMoved = false;
QList<TextEntity*>::ConstIterator it = start; TextEntity::List::ConstIterator it = start;
for ( ; it != end; ++it ) for ( ; it != end; ++it )
{ {
curEntity = *it; curEntity = *it;
str = curEntity->txt; str = curEntity->text();
if ( !offsetMoved && ( it == start ) ) if ( !offsetMoved && ( it == start ) )
{ {
if ( m_searchPoints.contains( searchID ) ) if ( m_searchPoints.contains( searchID ) )
@ -311,7 +373,7 @@ RegularAreaRect* TextPage::findTextInternalForward( int searchID, const QString
kDebug(1223) << "\tmatched" << endl; kDebug(1223) << "\tmatched" << endl;
#endif #endif
haveMatch=true; haveMatch=true;
ret->append( curEntity->area ); ret->append( curEntity->area() );
j+=min; j+=min;
queryLeft-=min; queryLeft-=min;
} }
@ -350,15 +412,15 @@ QString TextPage::text(const RegularAreaRect *area) const
return QString(); return QString();
QString ret = ""; QString ret = "";
QList<TextEntity*>::ConstIterator it,end = m_words.end(); TextEntity::List::ConstIterator it,end = d->m_words.end();
TextEntity * last=0; TextEntity * last=0;
for ( it = m_words.begin(); it != end; ++it ) for ( it = d->m_words.begin(); it != end; ++it )
{ {
// provide the string FIXME?: newline handling // provide the string FIXME?: newline handling
if (area->intersects((*it)->area)) if (area->intersects((*it)->area()))
{ {
// kDebug()<< "[" << (*it)->area->left << "," << (*it)->area->top << "]x["<< (*it)->area->right << "," << (*it)->area->bottom << "]\n"; // kDebug()<< "[" << (*it)->area->left << "," << (*it)->area->top << "]x["<< (*it)->area->right << "," << (*it)->area->bottom << "]\n";
ret += (*it)->txt; ret += (*it)->text();
last=*it; last=*it;
} }
} }

@ -39,7 +39,7 @@ class TextSelection;
*/ */
typedef enum SearchDirection{ FromTop, FromBottom, NextResult, PreviousResult }; typedef enum SearchDirection{ FromTop, FromBottom, NextResult, PreviousResult };
/*! @struct TextEntity /*! @class TextEntity
* @short Abstract textentity of Okular * @short Abstract textentity of Okular
* @par The context * @par The context
* A document can provide different forms of information about textual representation * A document can provide different forms of information about textual representation
@ -51,44 +51,102 @@ typedef enum SearchDirection{ FromTop, FromBottom, NextResult, PreviousResult };
* *
* Also some document types have glyphes - sets of characters rendered as one, so in search they should * Also some document types have glyphes - sets of characters rendered as one, so in search they should
* appear as a text but are only one character when drawn on screen. We need to allow this. * appear as a text but are only one character when drawn on screen. We need to allow this.
* @par The idea
* We need several
*/ */
class TextEntity
struct TextEntity
{ {
// public:
QString txt; typedef QList<TextEntity*> List;
NormalizedRect* area;
TextEntity(QString text, NormalizedRect* ar) : txt(text) /**
{ area=ar; }; * Creates a new text entity with the given @p text and the
~TextEntity() { delete area; }; * given @p area.
*/
TextEntity( const QString &text, NormalizedRect *area );
/**
* Destroys the text entity.
*/
~TextEntity();
/**
* Returns the text of the text entity.
*/
QString text() const;
/**
* Returns the bounding area of the text entity.
*/
NormalizedRect* area() const;
private:
QString m_text;
NormalizedRect* m_area;
class Private;
Private *d;
Q_DISABLE_COPY( TextEntity )
}; };
struct SearchPoint; /**
* The TextPage class represents the text of a page by
* providing @see TextEntity items for every word/character of
* the page.
*/
class TextPage class TextPage
{ {
public: public:
RegularAreaRect* findText( int id, const QString &query, SearchDirection & direct, /**
Qt::CaseSensitivity caseSensitivity, const RegularAreaRect *area); * Creates a new text page.
*/
QString text( const RegularAreaRect *rect ) const; TextPage();
RegularAreaRect * textArea( TextSelection* ) const;
/**
TextPage( QList<TextEntity*> words) : m_words(words) {}; * Creates a new text page with the given @p words.
TextPage() : m_words() {}; */
TextPage( const TextEntity::List &words );
void append(QString txt, NormalizedRect* area)
{ m_words.append(new TextEntity(txt,area) ); }; /**
~TextPage(); * Destroys the text page.
*/
private: ~TextPage();
RegularAreaRect * findTextInternalForward(int searchID, const QString &query,
Qt::CaseSensitivity caseSensitivity, const QList<TextEntity*>::ConstIterator &start, /**
const QList<TextEntity*>::ConstIterator &end); * Appends the given @p text with the given @p area as new
QList<TextEntity*> m_words; * @see TextItem to the page.
QMap<int, Okular::SearchPoint*> m_searchPoints; */
void append( const QString &text, NormalizedRect *area );
/**
* Returns the bounding rect of the text which matches the following criteria
* or 0 if the search is not successful.
*
* @param id An unique id for this search.
* @param text The search text.
* @param direction The direction of the search (@see SearchDirection)
* @param caseSensitivity If Qt::CaseSensitive, the search is case sensitive; otherwise
* the search is case insensitive.
* @param lastRect If 0 the search starts at the beginning of the page, otherwise
* right/below the coordinates of the the given rect.
*/
RegularAreaRect* findText( int id, const QString &text, SearchDirection & direction,
Qt::CaseSensitivity caseSensitivity, const RegularAreaRect *lastRect );
/**
* Returns the text which is included by rectangular area @p rect or an empty string.
*/
QString text( const RegularAreaRect *rect ) const;
/**
* Returns the rectangular area of the given @p selection.
*/
RegularAreaRect *textArea( TextSelection *selection ) const;
private:
class Private;
Private* const d;
Q_DISABLE_COPY( TextPage )
}; };
} }

Loading…
Cancel
Save