Improved ergonomy of term completion by using combobox listview instead of separate dialog

This commit is contained in:
Jean-Francois Dockes 2012-11-15 08:31:43 +01:00
parent 8f703fce74
commit 96d4bc4f41
2 changed files with 70 additions and 24 deletions

View File

@ -24,6 +24,7 @@
#include <qwhatsthis.h>
#include <qmessagebox.h>
#include <qevent.h>
#include <QTimer>
#include "debuglog.h"
#include "guiutils.h"
@ -58,6 +59,8 @@ void SSearch::init()
connect(searchTypCMB, SIGNAL(activated(int)), this, SLOT(searchTypeChanged(int)));
queryText->installEventFilter(this);
queryText->view()->installEventFilter(this);
m_displayingCompletions = false;
m_escape = false;
}
@ -261,9 +264,9 @@ void SSearch::completion()
return;
}
// Extract last word in text
string txt = (const char *)queryText->currentText().toUtf8();
string::size_type cs = txt.find_last_of(" ");
if (cs == string::npos)
QString txt = queryText->currentText();
int cs = txt.lastIndexOf(" ");
if (cs == -1)
cs = 0;
else
cs++;
@ -271,10 +274,10 @@ void SSearch::completion()
QApplication::beep();
return;
}
string s = txt.substr(cs) + "*";
LOGDEB(("Completing: [%s]\n", s.c_str()));
// Query database
// Query database for completions
string s = qs2utf8s(txt.right(txt.size() - cs)) + "*";
const int max = 100;
Rcl::TermMatchResult tmres;
@ -286,37 +289,62 @@ void SSearch::completion()
return;
}
if (tmres.entries.size() == (unsigned int)max) {
QMessageBox::warning(0, "Recoll", tr("Too many completions"));
QMessageBox *warning = new QMessageBox;
warning->setWindowTitle(tr("Recoll"));
warning->setText(tr("Too many completions"));
warning->show();
QTimer::singleShot(500, warning, SLOT(close()));
return;
}
// If list from db is single word, insert it, else ask user to select
QString res;
bool ok = false;
// If list from db is single word, insert it, else popup the listview
if (tmres.entries.size() == 1) {
res = QString::fromUtf8(tmres.entries.begin()->term.c_str());
ok = true;
QString res = QString::fromUtf8(tmres.entries.begin()->term.c_str());
txt.truncate(cs);
txt.append(res);
queryText->setEditText(txt);
} else {
QStringList lst;
for (vector<Rcl::TermMatchEntry>::iterator it = tmres.entries.begin();
it != tmres.entries.end(); it++) {
lst.push_back(QString::fromUtf8(it->term.c_str()));
}
res = QInputDialog::getItem (this, tr("Completions"),
tr("Select an item:"),
lst, 0, false, &ok);
}
// Insert result
if (ok) {
txt.erase(cs);
txt.append((const char *)res.toUtf8());
queryText->setEditText(QString::fromUtf8(txt.c_str()));
} else {
return;
m_savedEditText = queryText->currentText();
m_displayingCompletions = true;
m_chosenCompletion.clear();
m_completedWordStart = cs;
queryText->clear();
queryText->addItems(lst);
queryText->showPopup();
connect(queryText, SIGNAL(activated(const QString&)), this,
SLOT(completionTermChosen(const QString&)));
}
}
void SSearch::completionTermChosen(const QString& text)
{
m_chosenCompletion = text;
}
void SSearch::wrapupCompletion()
{
queryText->clear();
queryText->addItems(prefs.ssearchHistory);
if (!m_chosenCompletion.isEmpty()) {
m_savedEditText.truncate(m_completedWordStart);
m_savedEditText.append(m_chosenCompletion);
}
queryText->setEditText(m_savedEditText);
m_savedEditText.clear();
m_chosenCompletion.clear();
disconnect(queryText, SIGNAL(activated(const QString&)), this,
SLOT(completionTermChosen(const QString&)));
}
#undef SHOWEVENTS
#if defined(SHOWEVENTS)
const char *eventTypeToStr(int tp)
@ -458,7 +486,7 @@ const char *eventTypeToStr(int tp)
}
#endif
bool SSearch::eventFilter(QObject *, QEvent *event)
bool SSearch::eventFilter(QObject *target, QEvent *event)
{
#if defined(SHOWEVENTS)
if (event->type() == QEvent::Timer ||
@ -470,6 +498,18 @@ bool SSearch::eventFilter(QObject *, QEvent *event)
eventTypeToStr(event->type())));
#endif
if (target == queryText->view()) {
if (event->type() == QEvent::Hide) {
// List was closed. If we were displaying completions, need
// to reset state.
if (m_displayingCompletions) {
QTimer::singleShot(0, this, SLOT(wrapupCompletion()));
m_displayingCompletions = false;
}
}
return false;
}
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = (QKeyEvent *)event;
LOGDEB1(("SSearch::eventFilter: keyPress (m_escape %d) key %d\n",

View File

@ -51,11 +51,17 @@ public slots:
virtual void startSimpleSearch();
virtual void addTerm(QString);
virtual void onWordReplace(const QString&, const QString&);
virtual void completionTermChosen(const QString& text);
virtual void wrapupCompletion();
signals:
void startSearch(RefCntr<Rcl::SearchData>);
void clearSearch();
private:
bool m_escape;
bool m_displayingCompletions;
QString m_chosenCompletion;
QString m_savedEditText;
unsigned int m_completedWordStart;
};