#include "buttonsearch.h" #include "ui_buttonsearch.h" #include #include 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]; } }