Let the user type the hyphen if he wants when searching

It happens that sometimes the hypen is actually "part of the word" like
in one-third, so if there's one- at the end of a line
and third at the beginning of the next, we should still match and not
force the user to type onethird, even we will also match onethird since
there's no way to know if "hyphen at end of line" is supposed to be part
of the word or not

BUGS: 418520
remotes/origin/work/aacid/use_mimes_open_dialog
Albert Astals Cid 6 years ago
parent 054f8930ab
commit 9694113a96
  1. 16
      autotests/searchtest.cpp
  2. 87
      core/textpage.cpp

@ -288,6 +288,22 @@ void SearchTest::testHyphenAtEndOfLineWithoutYOverlap()
QCOMPARE(*result, expected); QCOMPARE(*result, expected);
delete result; delete result;
result = tp->findText(0, QStringLiteral("supercalifragilisticexpialidocious"),
Okular::FromBottom, Qt::CaseSensitive, nullptr);
QVERIFY(result);
QCOMPARE(*result, expected);
delete result;
// If the user is looking for the text explicitely with the hyphen also find it
result = tp->findText(0, QStringLiteral("super-cali-fragilistic"), Okular::FromTop, Qt::CaseSensitive, nullptr);
QVERIFY(result);
delete result;
// If the user is looking for the text explicitely with the hyphen also find it
result = tp->findText(0, QStringLiteral("super-cali-fragilistic"), Okular::FromBottom, Qt::CaseSensitive, nullptr);
QVERIFY(result);
delete result;
delete page; delete page;
} }

@ -54,11 +54,17 @@ class SearchPoint
static bool CaseInsensitiveCmpFn( const QStringRef & from, const QStringRef & to ) static bool CaseInsensitiveCmpFn( const QStringRef & from, const QStringRef & to )
{ {
#ifdef DEBUG_TEXTPAGE
qDebug(OkularCoreDebug) << from << ":" << to << "(case insensitive)";
#endif
return from.compare( to, Qt::CaseInsensitive ) == 0; return from.compare( to, Qt::CaseInsensitive ) == 0;
} }
static bool CaseSensitiveCmpFn( const QStringRef & from, const QStringRef & to ) static bool CaseSensitiveCmpFn( const QStringRef & from, const QStringRef & to )
{ {
#ifdef DEBUG_TEXTPAGE
qDebug(OkularCoreDebug) << from << ":" << to << "(case sensitive)";
#endif
return from.compare( to, Qt::CaseSensitive ) == 0; return from.compare( to, Qt::CaseSensitive ) == 0;
} }
@ -780,7 +786,7 @@ RegularAreaRect* TextPage::findText( int searchID, const QString &query, SearchD
// if the '-' is the last entry // if the '-' is the last entry
static int stringLengthAdaptedWithHyphen(const QString &str, const TextList::ConstIterator &it, const TextList::ConstIterator &textListEnd) static int stringLengthAdaptedWithHyphen(const QString &str, const TextList::ConstIterator &it, const TextList::ConstIterator &textListEnd)
{ {
int len = str.length(); const int len = str.length();
// hyphenated '-' must be at the end of a word, so hyphenation means // hyphenated '-' must be at the end of a word, so hyphenation means
// we have a '-' just followed by a '\n' character // we have a '-' just followed by a '\n' character
@ -795,10 +801,9 @@ static int stringLengthAdaptedWithHyphen(const QString &str, const TextList::Con
const QString &lookahedStr = (*(it+1))->text(); const QString &lookahedStr = (*(it+1))->text();
if (lookahedStr.startsWith(QLatin1Char('\n'))) if (lookahedStr.startsWith(QLatin1Char('\n')))
{ {
len -= 1; return len - 1;
} }
else
{
// 2. if the next word is in a different line or not // 2. if the next word is in a different line or not
const NormalizedRect& hyphenArea = (*it)->area; const NormalizedRect& hyphenArea = (*it)->area;
const NormalizedRect& lookaheadArea = (*(it + 1))->area; const NormalizedRect& lookaheadArea = (*(it + 1))->area;
@ -806,15 +811,14 @@ static int stringLengthAdaptedWithHyphen(const QString &str, const TextList::Con
// lookahead to check whether both the '-' rect and next character rect overlap // lookahead to check whether both the '-' rect and next character rect overlap
if( !doesConsumeY( hyphenArea, lookaheadArea, 70 ) ) if( !doesConsumeY( hyphenArea, lookaheadArea, 70 ) )
{ {
len -= 1; return len - 1;
}
} }
} }
} }
// else if it is the second last entry - for example in pdf format // else if it is the second last entry - for example in pdf format
else if (str.endsWith(QLatin1String("-\n"))) else if (str.endsWith(QLatin1String("-\n")))
{ {
len -= 2; return len - 2;
} }
return len; return len;
@ -850,8 +854,7 @@ RegularAreaRect* TextPagePrivate::findTextInternalForward( int searchID, const Q
const QString query = _query.normalized(QString::NormalizationForm_KC); const QString query = _query.normalized(QString::NormalizationForm_KC);
// j is the current position in our query // j is the current position in our query
// len is the length of the string in TextEntity // queryLeft is the length of the query we have left to match
// queryLeft is the length of the query we have left
int j=0, queryLeft=query.length(); int j=0, queryLeft=query.length();
TextList::ConstIterator it = start; TextList::ConstIterator it = start;
@ -864,9 +867,11 @@ RegularAreaRect* TextPagePrivate::findTextInternalForward( int searchID, const Q
{ {
const TinyTextEntity* curEntity = *it; const TinyTextEntity* curEntity = *it;
const QString& str = curEntity->text(); const QString& str = curEntity->text();
int len = stringLengthAdaptedWithHyphen(str, it, m_words.constEnd()); const int strLen = str.length();
const int adjustedLen = stringLengthAdaptedWithHyphen(str, it, m_words.constEnd());
// adjustedLen <= strLen
if (offset >= len) if (offset >= strLen)
{ {
it++; it++;
offset = 0; offset = 0;
@ -879,15 +884,21 @@ RegularAreaRect* TextPagePrivate::findTextInternalForward( int searchID, const Q
offset_begin = offset; offset_begin = offset;
} }
int min=qMin(queryLeft,len-offset); // Let the user write the hyphen or not when searching for text
int matchedLen = -1;
for (int matchingLen = strLen; matchingLen >= adjustedLen; matchingLen--)
{ {
#ifdef DEBUG_TEXTPAGE
qCDebug(OkularCoreDebug) << str.midRef(offset, min) << ":" << _query.midRef(j, min);
#endif
// we have equal (or less than) area of the query left as the length of the current // we have equal (or less than) area of the query left as the length of the current
// entity // entity
const int min = qMin(queryLeft, matchingLen - offset);
if ( comparer( str.midRef( offset, min ), query.midRef( j, min ) ) )
{
matchedLen = min;
break;
}
}
if ( !comparer( str.midRef( offset, min ), query.midRef( j, min ) ) ) if ( matchedLen == -1 )
{ {
// we have not matched // we have not matched
// this means we do not have a complete match // this means we do not have a complete match
@ -911,10 +922,10 @@ RegularAreaRect* TextPagePrivate::findTextInternalForward( int searchID, const Q
// subtract the length of the current entity from // subtract the length of the current entity from
// the left length of the query // the left length of the query
#ifdef DEBUG_TEXTPAGE #ifdef DEBUG_TEXTPAGE
qCDebug(OkularCoreDebug) << "\tmatched"; qCDebug(OkularCoreDebug) << "\tmatched" << matchedLen;
#endif #endif
j += min; j += matchedLen;
queryLeft -= min; queryLeft -= matchedLen;
if (queryLeft==0) if (queryLeft==0)
{ {
@ -928,7 +939,7 @@ RegularAreaRect* TextPagePrivate::findTextInternalForward( int searchID, const Q
sp->it_begin = it_begin; sp->it_begin = it_begin;
sp->it_end = it; sp->it_end = it;
sp->offset_begin = offset_begin; sp->offset_begin = offset_begin;
sp->offset_end = offset + min; sp->offset_end = offset + matchedLen;
return searchPointToArea(sp); return searchPointToArea(sp);
} }
@ -936,7 +947,6 @@ RegularAreaRect* TextPagePrivate::findTextInternalForward( int searchID, const Q
offset = 0; offset = 0;
} }
} }
}
// end of loop - it means that we've ended the textentities // end of loop - it means that we've ended the textentities
const QMap< int, SearchPoint* >::iterator sIt = m_searchPoints.find( searchID ); const QMap< int, SearchPoint* >::iterator sIt = m_searchPoints.find( searchID );
@ -982,11 +992,13 @@ RegularAreaRect* TextPagePrivate::findTextInternalBackward( int searchID, const
const TinyTextEntity* curEntity = *it; const TinyTextEntity* curEntity = *it;
const QString& str = curEntity->text(); const QString& str = curEntity->text();
int len = stringLengthAdaptedWithHyphen(str, it, m_words.constEnd()); const int strLen = str.length();
const int adjustedLen = stringLengthAdaptedWithHyphen(str, it, m_words.constEnd());
// adjustedLen <= strLen
if (offset <= 0) if (offset <= 0)
{ {
offset = len; offset = strLen;
} }
if ( it_begin == TextList::ConstIterator() ) if ( it_begin == TextList::ConstIterator() )
@ -995,16 +1007,22 @@ RegularAreaRect* TextPagePrivate::findTextInternalBackward( int searchID, const
offset_begin = offset; offset_begin = offset;
} }
int min=qMin(queryLeft,offset); // Let the user write the hyphen or not when searching for text
{ int matchedLen = -1;
#ifdef DEBUG_TEXTPAGE
qCDebug(OkularCoreDebug) << str.midRef(offset-min, min) << " : " << _query.midRef(j-min, min);
#endif
// we have equal (or less than) area of the query left as the length of the current // we have equal (or less than) area of the query left as the length of the current
// entity // entity
for (int matchingLen = strLen; matchingLen >= adjustedLen; matchingLen--)
{
const int hyphenOffset = (strLen - matchingLen);
const int min = qMin(queryLeft + hyphenOffset, offset);
if ( comparer( str.midRef( offset - min, min - hyphenOffset ), query.midRef( j - min + hyphenOffset, min - hyphenOffset ) ) )
{
matchedLen = min - hyphenOffset;
break;
}
}
// Note len is not str.length() so we can't use rightRef here if ( matchedLen == -1 )
if ( !comparer( str.midRef(offset-min, min ), query.midRef( j - min, min ) ) )
{ {
// we have not matched // we have not matched
// this means we do not have a complete match // this means we do not have a complete match
@ -1031,8 +1049,8 @@ RegularAreaRect* TextPagePrivate::findTextInternalBackward( int searchID, const
#ifdef DEBUG_TEXTPAGE #ifdef DEBUG_TEXTPAGE
qCDebug(OkularCoreDebug) << "\tmatched"; qCDebug(OkularCoreDebug) << "\tmatched";
#endif #endif
j -= min; j -= matchedLen;
queryLeft -= min; queryLeft -= matchedLen;
if ( queryLeft == 0 ) if ( queryLeft == 0 )
{ {
@ -1045,16 +1063,13 @@ RegularAreaRect* TextPagePrivate::findTextInternalBackward( int searchID, const
SearchPoint* sp = *sIt; SearchPoint* sp = *sIt;
sp->it_begin = it; sp->it_begin = it;
sp->it_end = it_begin; sp->it_end = it_begin;
sp->offset_begin = offset - min; sp->offset_begin = offset - matchedLen;
sp->offset_end = offset_begin; sp->offset_end = offset_begin;
return searchPointToArea(sp); return searchPointToArea(sp);
} }
offset = 0; offset = 0;
} }
}
} }
// end of loop - it means that we've ended the textentities // end of loop - it means that we've ended the textentities

Loading…
Cancel
Save