recoll/src/qtgui/actsearch_w.cpp
2021-10-10 08:27:08 +01:00

113 lines
3.8 KiB
C++

/* Copyright (C) 2020-2021 J.F.Dockes
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "autoconfig.h"
#include <QShortcut>
#include <QCompleter>
#include <QAbstractItemView>
#include <QLineEdit>
#include <QAction>
#include <QKeyEvent>
#include "log.h"
#include "actsearch_w.h"
// A window for letting the user to search among menu entries (actions) and execute the one found.
void ActSearchW::init()
{
new QShortcut(QKeySequence("Esc"), this, SLOT(hide()));
connect(actCMB, SIGNAL(activated(int)), this, SLOT(onActivated(int)));
}
void ActSearchW::setActList(QList<QAction*> actlist)
{
for (int i = 0; i < actlist.size(); i++) {
if (!actlist[i]->text().isEmpty()) {
m_actions.push_back(actlist[i]);
}
}
std::sort(m_actions.begin(), m_actions.end(),
[] (const QAction *act1, const QAction *act2) {
auto txt1 = act1->text().remove('&');
auto txt2 = act2->text().remove('&');
return txt1.compare(txt2, Qt::CaseInsensitive) < 0;});
QStringList sl;
for (const auto act : m_actions) {
auto txt = act->text().remove('&');
actCMB->addItem(txt);
sl.push_back(txt);
}
actCMB->setCurrentText("");
m_completer = new QCompleter(sl, this);
m_completer->setCaseSensitivity(Qt::CaseInsensitive);
if (m_match_contains) {
m_completer->setFilterMode(Qt::MatchContains);
}
actCMB->setCompleter(m_completer);
m_completer->popup()->installEventFilter(this);
actCMB->installEventFilter(this);
}
// This is to avoid that if the user types Backspace or Del while we
// have inserted / selected the current completion, the lineedit text
// goes back to what it was, the completion fires, and it looks like
// nothing was typed. Disable the completion after Del or Backspace
// is typed.
bool ActSearchW::eventFilter(QObject *target, QEvent *event)
{
Q_UNUSED(target);
if (event->type() != QEvent::KeyPress) {
return false;
}
QKeyEvent *keyEvent = (QKeyEvent *)event;
if (keyEvent->key() == Qt::Key_Backspace || keyEvent->key()==Qt::Key_Delete) {
actCMB->setCompleter(nullptr);
return false;
} else {
if (nullptr == actCMB->completer()) {
actCMB->setCompleter(m_completer);
}
}
return false;
}
void ActSearchW::onTextChanged(const QString&)
{
if (actCMB->completer() && actCMB->completer()->completionCount() == 1) {
// We append the completion part to the end of the current input, line, and select it so
// that the user has a clear indication of what will happen if they type Enter.
auto le = actCMB->lineEdit();
int pos = le->cursorPosition();
auto text = actCMB->completer()->currentCompletion();
int len = text.size() - actCMB->currentText().size();
le->setText(text);
if (!m_match_contains) {
le->setCursorPosition(pos);
le->setSelection(pos, len);
}
}
}
void ActSearchW::onActivated(int index)
{
if (index < 0 || index >= int(m_actions.size()))
return;
m_actions[index]->trigger();
hide();
}