#include "mainwindow.h" #include "ui_mainwindow.h" #include "buttonmanager.h" #include "editsample.h" #include "settings.h" #include "buttonsearch.h" #include #include #include #include #include MainWindow::MainWindow(const std::string& binary, QWidget* parent) : QMainWindow(parent), ui(new Ui::Soundboard), config(binary) { ui->setupUi(this); reloadConfig(); QObject::connect(ui->stopButton, SIGNAL( clicked() ), this, SLOT( stop() )); QObject::connect(ui->actionSaveConfig, SIGNAL( triggered() ), this, SLOT( saveConfig() )); QObject::connect(ui->actionButtonManager, SIGNAL( triggered() ), this, SLOT( openButtonManager() )); QObject::connect(ui->actionSettings, SIGNAL( triggered() ), this, SLOT( openSettings() )); QObject::connect(ui->actionReloadConfig, SIGNAL( triggered() ), this, SLOT(reloadConfig())); QObject::connect(ui->alwaysOnTop, SIGNAL( stateChanged(int) ), this, SLOT( alwaysOnTopSettingChange(int) )); QObject::connect(this, SIGNAL(newStatusMessage(const QString&)), ui->statusbar, SLOT(showMessage(const QString&))); } MainWindow::~MainWindow() { delete ui; delete stopGlobal; delete up; delete down; delete left; delete right; delete play; delete search; Sound::deinitInstance(); } void MainWindow::reloadConfig() { Log::info << "realodConfig()"; QString loaded = QString::fromStdString("loading config"); emit newStatusMessage(loaded); config.load(); loadSoundFromConfig(); loadShortcuts(); removeAllButtons(); loadButtonsFromConfig(); QString done = QString::fromStdString("config loaded"); emit newStatusMessage(done); Log::info << "realodConfig() done"; } void MainWindow::stop() { Sound::instance().stopAll(); } static uint8_t wrap(uint8_t a, uint8_t max) { if(a >= max) return max-1; return a; } static uint8_t wrap0(uint8_t a, uint8_t max) { if(a >= max) return 0; return a; } void MainWindow::moveUp() { reselectNext([max = ui->gridLayout->rowCount()](uint8_t&, uint8_t& y){ y = wrap(--y, max); }); } void MainWindow::moveDown() { reselectNext([max = ui->gridLayout->rowCount()](uint8_t&, uint8_t& y){ y = wrap0(++y, max); }); } void MainWindow::moveLeft() { reselectNext([max = ui->gridLayout->columnCount()](uint8_t& x, uint8_t&){ x = wrap(--x, max); }); } void MainWindow::moveRight() { reselectNext([max = ui->gridLayout->columnCount()](uint8_t& x, uint8_t&){ x = wrap0(++x, max); }); } void MainWindow::playCurrent() { QLayoutItem* item = ui->gridLayout->itemAtPosition(yCoord, xCoord); if(item && item->widget()) { SoundButton* button = (SoundButton*) item->widget(); button->click(); } } void MainWindow::reloadButtonConfig() { removeAllButtons(); loadButtonsFromConfig(); } void MainWindow::alwaysOnTopSettingChange(int status) { Qt::WindowFlags eFlags = windowFlags(); Log::debug << "status: " << status; if(status) { setWindowFlags(eFlags | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); } else { setWindowFlags(eFlags & ~(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint)); } show(); } void MainWindow::saveConfig() { Log::info << "save Config"; config.save(); } void MainWindow::openButtonManager() { Log::info << "openButtonManager"; ButtonManager buttonManager(config, this); buttonManager.exec(); // reload button config if(buttonManager.result() == QMessageBox::ButtonRole::AcceptRole) { reloadButtonConfig(); } } void MainWindow::openSettings() { Log::info << "openSettings"; Settings settings(config, this); settings.exec(); // reload complete config if(settings.result() == QMessageBox::ButtonRole::AcceptRole) { reloadConfig(); } } void MainWindow::openSearch() { Log::info << "openSearch"; ButtonSearch* bs = new ButtonSearch(config); int res = bs->exec(); if(res >= 0) { playButtonID(res); } delete bs; } void MainWindow::loadSoundFromConfig() { Sound& sound = Sound::instance(); // init sound sound.reset(); const std::vector& devices = config.rootConfig.audio.devices; for (const std::string& device : devices) { Log::note << "loadAudio device: \"" << device << '"'; if (!sound.addDeviceWithName(device)) { Log::warn << "AudioDevice could not be loaded: \"" << device << '"'; QString done = QString::fromStdString("Sound Device: " + device + " not found!"); emit newStatusMessage(done); return; } } Log::debug << "Sound devices loaded"; sound.setMasterVolume(config.rootConfig.audio.volume); Sound::FOLDER = config.rootConfig.audioPath; Log::debug << "Sound::FOLDER: " << Sound::FOLDER; } void MainWindow::loadShortcuts() { delete up; delete down; delete left; delete right; delete play; delete search; delete stopGlobal; const Config::ShortcutConfig& sc = config.rootConfig.shortcuts; up = loadShortcut(sc.up); down = loadShortcut(sc.down); left = loadShortcut(sc.left); right = loadShortcut(sc.right); play = loadShortcut(sc.play); search = loadShortcut(sc.search); stopGlobal = loadShortcut(sc.stop); QObject::connect(up, SIGNAL( activated() ), this, SLOT( moveUp() )); QObject::connect(down, SIGNAL( activated() ), this, SLOT( moveDown() )); QObject::connect(left, SIGNAL( activated() ), this, SLOT( moveLeft() )); QObject::connect(right, SIGNAL( activated() ), this, SLOT( moveRight() )); QObject::connect(play, SIGNAL( activated() ), this, SLOT( playCurrent() )); QObject::connect(search, SIGNAL( activated() ), this, SLOT( openSearch() )); QObject::connect(stopGlobal, SIGNAL( activated() ), this, SLOT( stop() )); } void MainWindow::removeAllButtons() { //remove old buttons for (SoundButton* sb : soundbuttons) { ui->gridLayout->removeWidget(sb); delete sb; } soundbuttons.clear(); } void MainWindow::loadButtonsFromConfig() { int x = 0; int y = 0; const std::vector>& buttonConfigs = config.rootConfig.buttons; for (const std::vector& line : buttonConfigs) { if(line.empty()) continue; for (const Config::ButtonConfig& bc : line) { if (!bc.isValid()) continue; SoundButton* sb = new SoundButton(bc.id, bc.name, bc.key); for(const Config::SampleConfig& sc : bc.samples) { if(!sc.isValid()) continue; SoundButton::Sample sample = {sc.file, sc.offset, sc.length, sc.volume}; sb->addSample(sample); } soundbuttons.push_back(sb); ui->gridLayout->addWidget(sb, y, x, 1, bc.width); sb->show(); x += bc.width; } //ui->gridLayout->setRowMinimumHeight(y, 60); x = 0; y++; } xCoord = 0; yCoord = 0; // select the first button QLayoutItem* item = ui->gridLayout->itemAtPosition(0, 0); if(item && item->widget()) { ((SoundButton*) item->widget())->setHighlighted(true); } // ui->gridLayout->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); } void MainWindow::playButtonID(uint32_t buttonid) { const Config::ButtonConfig* btnconf = config.getButtonByID(buttonid); if(!btnconf) { Log::error << "invalid button id triggered: " << buttonid; return; } SoundButton* sb = findChild(QString::fromStdString("soundButton" + std::to_string(buttonid))); if(sb == nullptr) { Log::error << "button not found: " << buttonid; return; } sb->click(); } void MainWindow::reselectNext(std::function stepf) { QLayoutItem* item = ui->gridLayout->itemAtPosition(yCoord, xCoord); QLayoutItem* newitem = findNextButton(stepf); if(item != newitem) { if(item && item->widget()) { ((SoundButton*) item->widget())->setHighlighted(false); } if(newitem && newitem->widget()) { ((SoundButton*) newitem->widget())->setHighlighted(true); } } } QLayoutItem* MainWindow::findNextButton(std::function stepf) { // need copy for while condition uint8_t x = xCoord; uint8_t y = yCoord; QLayoutItem* currentItem = ui->gridLayout->itemAtPosition(y, x); QLayoutItem* item = currentItem; do { stepf(x, y); item = ui->gridLayout->itemAtPosition(y, x); } while(item == currentItem && (x != xCoord || y != yCoord)); xCoord = x; yCoord = y; // might the same item return item; } QxtGlobalShortcut* MainWindow::loadShortcut(const std::string& key) { QKeySequence seq(QString::fromStdString(key)); if(seq.isEmpty()) return nullptr; return new QxtGlobalShortcut(seq); }