Result list: improve the spelling suggestions now presented as links which will replace the appropriate word inside the query

This commit is contained in:
Jean-Francois Dockes 2012-02-17 09:01:28 +01:00
parent cc5ba21d79
commit f6e50fd9eb
7 changed files with 64 additions and 18 deletions

View File

@ -306,6 +306,8 @@ void RclMain::init()
this, SLOT(docExpand(Rcl::Doc))); this, SLOT(docExpand(Rcl::Doc)));
connect(reslist, SIGNAL(wordSelect(QString)), connect(reslist, SIGNAL(wordSelect(QString)),
sSearch, SLOT(addTerm(QString))); sSearch, SLOT(addTerm(QString)));
connect(reslist, SIGNAL(wordReplace(const QString&, const QString&)),
sSearch, SLOT(onWordReplace(const QString&, const QString&)));
connect(reslist, SIGNAL(nextPageAvailable(bool)), connect(reslist, SIGNAL(nextPageAvailable(bool)),
this, SLOT(enableNextPage(bool))); this, SLOT(enableNextPage(bool)));
connect(reslist, SIGNAL(prevPageAvailable(bool)), connect(reslist, SIGNAL(prevPageAvailable(bool)),

View File

@ -76,7 +76,8 @@ public:
virtual string nextUrl(); virtual string nextUrl();
virtual string prevUrl(); virtual string prevUrl();
virtual string pageTop(); virtual string pageTop();
virtual void suggest(const vector<string>uterms, vector<string>&sugg); virtual void suggest(const vector<string>uterms,
map<string, vector<string> >& sugg);
virtual string absSep() {return (const char *)(prefs.abssep.toUtf8());} virtual string absSep() {return (const char *)(prefs.abssep.toUtf8());}
virtual string iconUrl(RclConfig *, Rcl::Doc& doc); virtual string iconUrl(RclConfig *, Rcl::Doc& doc);
private: private:
@ -163,7 +164,8 @@ string QtGuiResListPager::pageTop()
} }
void QtGuiResListPager::suggest(const vector<string>uterms, vector<string>&sugg) void QtGuiResListPager::suggest(const vector<string>uterms,
map<string, vector<string> >& sugg)
{ {
sugg.clear(); sugg.clear();
#ifdef RCL_USE_ASPELL #ifdef RCL_USE_ASPELL
@ -179,6 +181,10 @@ void QtGuiResListPager::suggest(const vector<string>uterms, vector<string>&sugg)
uit != uterms.end(); uit++) { uit != uterms.end(); uit++) {
list<string> asuggs; list<string> asuggs;
string reason; string reason;
// If the term is in the index, we don't suggest alternatives.
// Actually, we may want to check the frequencies and propose something
// anyway if a possible variation is much more common (as google does)
if (aspell->check(*rcldb, *uit, reason)) if (aspell->check(*rcldb, *uit, reason))
continue; continue;
else if (!reason.empty()) else if (!reason.empty())
@ -189,7 +195,15 @@ void QtGuiResListPager::suggest(const vector<string>uterms, vector<string>&sugg)
continue; continue;
} }
if (!asuggs.empty()) { if (!asuggs.empty()) {
sugg.push_back(*asuggs.begin()); sugg[*uit] = vector<string>(asuggs.begin(), asuggs.end());
if (sugg[*uit].size() > 5)
sugg[*uit].resize(5);
// Set up the links as a <href="Sold|new">.
for (vector<string>::iterator it = sugg[*uit].begin();
it != sugg[*uit].end(); it++) {
*it = string("<a href=\"S") + *uit + "|" + *it + "\">" +
*it + "</a>";
}
} }
} }
#endif #endif
@ -607,11 +621,9 @@ void ResList::mouseDoubleClickEvent(QMouseEvent *event)
void ResList::linkWasClicked(const QUrl &url) void ResList::linkWasClicked(const QUrl &url)
{ {
QByteArray s = url.toString().toAscii(); string ascurl = (const char *)url.toString().toAscii();;
const char *ascurl = (const char *)s; LOGDEB(("ResList::linkWasClicked: [%s]\n", ascurl.c_str()));
LOGDEB(("ResList::linkWasClicked: [%s]\n", ascurl));
int i = atoi(ascurl+1) - 1;
int what = ascurl[0]; int what = ascurl[0];
switch (what) { switch (what) {
case 'H': case 'H':
@ -620,6 +632,7 @@ void ResList::linkWasClicked(const QUrl &url)
case 'P': case 'P':
case 'E': case 'E':
{ {
int i = atoi(ascurl.c_str()+1) - 1;
Rcl::Doc doc; Rcl::Doc doc;
if (!getDoc(i, doc)) { if (!getDoc(i, doc)) {
LOGERR(("ResList::linkWasClicked: can't get doc for %d\n", i)); LOGERR(("ResList::linkWasClicked: can't get doc for %d\n", i));
@ -637,8 +650,21 @@ void ResList::linkWasClicked(const QUrl &url)
case 'p': case 'p':
resultPageBack(); resultPageBack();
break; break;
case 'S':
{
QString s = url.toString();
if (!s.isEmpty())
s = s.right(s.size()-1);
int bar = s.indexOf("|");
if (bar != -1 && bar < s.size()-1) {
QString o = s.left(bar);
QString n = s.right(s.size() - (bar+1));
emit wordReplace(o, n);
}
}
break;
default: default:
LOGERR(("ResList::linkWasClicked: bad link [%s]\n", ascurl)); LOGERR(("ResList::linkWasClicked: bad link [%s]\n", ascurl.c_str()));
break;// ?? break;// ??
} }
} }

View File

@ -105,6 +105,7 @@ class ResList : public QTextBrowser
void headerClicked(); void headerClicked();
void docExpand(Rcl::Doc); void docExpand(Rcl::Doc);
void wordSelect(QString); void wordSelect(QString);
void wordReplace(const QString&, const QString&);
void linkClicked(const QString&, int); // See emitLinkClicked() void linkClicked(const QString&, int); // See emitLinkClicked()
void hasResults(int); void hasResults(int);

View File

@ -236,6 +236,15 @@ void SSearch::addTerm(QString term)
queryText->setEditText(text); queryText->setEditText(text);
} }
void SSearch::onWordReplace(const QString& o, const QString& n)
{
QString txt = queryText->currentText();
QRegExp exp = QRegExp(QString("\\b") + o + QString("\\b"));
exp.setCaseSensitivity(Qt::CaseInsensitive);
txt.replace(exp, n);
queryText->setEditText(txt);
}
void SSearch::setAnyTermMode() void SSearch::setAnyTermMode()
{ {
searchTypCMB->setCurrentIndex(SST_ANY); searchTypCMB->setCurrentIndex(SST_ANY);

View File

@ -51,7 +51,7 @@ public slots:
virtual void setSearchString(const QString& text); virtual void setSearchString(const QString& text);
virtual void startSimpleSearch(); virtual void startSimpleSearch();
virtual void addTerm(QString); virtual void addTerm(QString);
virtual void onWordReplace(const QString&, const QString&);
signals: signals:
void startSearch(RefCntr<Rcl::SearchData>); void startSearch(RefCntr<Rcl::SearchData>);
void clearSearch(); void clearSearch();

View File

@ -290,17 +290,24 @@ void ResListPager::displayPage(RclConfig *config)
vector<string>uterms; vector<string>uterms;
m_docSource->getUTerms(uterms); m_docSource->getUTerms(uterms);
if (!uterms.empty()) { if (!uterms.empty()) {
vector<string> spellings; map<string, vector<string> > spellings;
suggest(uterms, spellings); suggest(uterms, spellings);
if (!spellings.empty()) { if (!spellings.empty()) {
chunk << chunk <<
trans("<p><i>Alternate spellings (accents suppressed): </i>"); trans("<p><i>Alternate spellings (accents suppressed): </i>")
for (vector<string>::iterator it = spellings.begin(); << "<br /><blockquote>";
it != spellings.end(); it++) {
chunk << *it; for (map<string, vector<string> >::const_iterator it0 =
chunk << " "; spellings.begin(); it0 != spellings.end(); it0++) {
} chunk << "<b>" << it0->first << "</b> : ";
chunk << "</p>"; for (vector<string>::const_iterator it =
it0->second.begin();
it != it0->second.end(); it++) {
chunk << *it << " ";
}
chunk << "<br />";
}
chunk << "</blockquote></p>";
} }
} }
} else { } else {

View File

@ -111,7 +111,8 @@ public:
virtual string prevUrl(); virtual string prevUrl();
virtual string pageTop() {return string();} virtual string pageTop() {return string();}
virtual string iconUrl(RclConfig *, Rcl::Doc& doc); virtual string iconUrl(RclConfig *, Rcl::Doc& doc);
virtual void suggest(const vector<string>, vector<string>&sugg) { virtual void suggest(const vector<string>,
map<string, vector<string> >& sugg) {
sugg.clear(); sugg.clear();
} }
virtual string absSep() {return "&hellip;";} virtual string absSep() {return "&hellip;";}