soundboard/src/buttonsearch.cpp

164 lines
5.2 KiB
C++

#include "buttonsearch.h"
#include "ui_buttonsearch.h"
#include <QVariant>
#include <Log.h>
static char getSymbol(uint8_t i) {
return (i < 10) ? ('0' + i) : ('a' + i-10);
}
static bool startsWith(const std::string& a, const std::string& b) {
// not very performant but working
return QString().fromStdString(a).toLower().startsWith(QString().fromStdString(b).toLower());
}
ButtonSearch::ButtonSearch(const Config& config, QWidget *parent) : QDialog(parent), config(config), ui(new Ui::ButtonSearch) {
ui->setupUi(this);
Qt::WindowFlags eFlags = windowFlags();
setWindowFlags(eFlags | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
esc = new QxtGlobalShortcut(QKeySequence("Esc"));
QObject::connect(esc, &QxtGlobalShortcut::activated, [this](){ buttonPressed(-1); });
enter = new QxtGlobalShortcut(QKeySequence("Enter"));
QObject::connect(enter, &QxtGlobalShortcut::activated, [this](){ buttonPressed(-2); });
up = new QxtGlobalShortcut(QKeySequence("Up"));
QObject::connect(up, &QxtGlobalShortcut::activated, std::bind(&ButtonSearch::selectionUp, this));
down = new QxtGlobalShortcut(QKeySequence("Down"));
QObject::connect(down, &QxtGlobalShortcut::activated, std::bind(&ButtonSearch::selectionDown, this));
for(uint8_t i = 0; i < NUMCOUNT-10; ++i) {
nums[i] = new QxtGlobalShortcut(QKeySequence(QString() + getSymbol(i)));
QObject::connect(nums[i], &QxtGlobalShortcut::activated, [this, i](){ buttonPressed(i); });
}
// numpad numbers
for(uint8_t i = 0; i < 10; ++i) {
nums[NUMCOUNT-10 +i] = new QxtGlobalShortcut(QKeySequence(QString("Num+") + getSymbol(i)));
QObject::connect(nums[NUMCOUNT-10 +i], &QxtGlobalShortcut::activated, [this, i](){ buttonPressed(i); });
}
}
void ButtonSearch::buttonPressed(int i) {
if(i == -1) {
// esc
Log::info << "esc pressed";
done(-1);
} else if(i == -2) {
// enter
Log::info << "enter pressed";
closeSearch();
} else {
char sym = getSymbol(i);
Log::info << "button pressed: " << i << " sym: " << getSymbol(i);
ui->searchText->setText(ui->searchText->toPlainText() + sym);
ui->searchResults->clear();
// execute search
const std::string searchStr = ui->searchText->toPlainText().toStdString();
for(const auto& row : config.rootConfig.buttons) {
for(const auto& btn : row) {
if(startsWith(btn.name, searchStr)) {
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(btn.name));
item->setData(Qt::UserRole, QVariant(btn.id));
ui->searchResults->addItem(item);
} else if(startsWith(std::to_string(btn.id), searchStr)) {
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(btn.name));
item->setData(Qt::UserRole, QVariant(btn.id));
ui->searchResults->addItem(item);
}
}
}
}
}
void ButtonSearch::closeSearch() {
QItemSelectionModel* selmod = ui->searchResults->selectionModel();
auto idx = selmod->selectedRows();
if(idx.isEmpty()) {
if(ui->searchResults->count() == 1) {
Log::info << "only one selected";
QVariant var = ui->searchResults->item(0)->data(Qt::UserRole);
assert(var.type() == QVariant::Type::UInt);
done((int) var.toUInt());
return;
}
done(-1); // nothing selected
} else {
QVariant var = idx.at(0).data(Qt::UserRole);
assert(var.type() == QVariant::Type::UInt);
done((int) var.toUInt());
}
}
void ButtonSearch::selectionDown() {
Log::info << "down";
if(ui->searchResults->count() == 0) {
Log::warn << "empty search results";
return; // avoid empty list
}
QItemSelectionModel* selmod = ui->searchResults->selectionModel();
QAbstractItemModel* itemmod = ui->searchResults->model();
auto idx = selmod->selectedRows();
if(idx.isEmpty()) {
// none selected - select first
Log::debug << "select first";
selmod->setCurrentIndex(itemmod->index(0, 0), QItemSelectionModel::SelectionFlag::ClearAndSelect);
} else {
// select next
int selectedRow = idx.at(0).row();
Log::debug << "idx: " << selectedRow;
if(ui->searchResults->count() > selectedRow+1) {
selmod->setCurrentIndex(itemmod->index(selectedRow+1, 0), QItemSelectionModel::SelectionFlag::ClearAndSelect);
} else {
// wrap around
selmod->setCurrentIndex(itemmod->index(0, 0), QItemSelectionModel::SelectionFlag::ClearAndSelect);
}
}
}
void ButtonSearch::selectionUp() {
Log::info << "up";
if(ui->searchResults->count() == 0) {
Log::warn << "empty search results";
return; // avoid empty list
}
QItemSelectionModel* selmod = ui->searchResults->selectionModel();
QAbstractItemModel* itemmod = ui->searchResults->model();
auto idx = selmod->selectedRows();
if(idx.isEmpty()) {
// none selected - select last
Log::debug << "select last";
selmod->setCurrentIndex(itemmod->index(itemmod->rowCount()-1, 0), QItemSelectionModel::SelectionFlag::ClearAndSelect);
} else {
// select next
int selectedRow = idx.at(0).row();
Log::debug << "idx: " << selectedRow;
if(selectedRow-1 >= 0) {
selmod->setCurrentIndex(itemmod->index(selectedRow-1, 0), QItemSelectionModel::SelectionFlag::ClearAndSelect);
} else {
// wrap around
selmod->setCurrentIndex(itemmod->index(itemmod->rowCount()-1, 0), QItemSelectionModel::SelectionFlag::ClearAndSelect);
}
}
}
ButtonSearch::~ButtonSearch() {
delete ui;
delete esc;
delete enter;
for(uint8_t i = 0; i < NUMCOUNT; ++i) {
delete nums[i];
}
}