/* Copyright (c) 2015, Stanislaw Halik * Permission to use, copy, modify, and/or distribute this * software for any purpose with or without fee is hereby granted, * provided that the above copyright notice and this permission * notice appear in all copies. */ #include "process_detector.h" #include "options/options.hpp" #include "compat/process-list.hpp" #include "compat/base-path.hpp" #include #include #include #include #include #include #include #include static constexpr auto RECORD_SEPARATOR = QChar(char(0x1e)); // RS ^] static constexpr auto UNIT_SEPARATOR = QChar(char(0x1f)); // US ^_ using namespace options; using namespace options::globals; void proc_detector_settings::set_game_list(const QString &game_list) { with_global_settings_object([&](QSettings& settings) { settings.setValue("executable-list", game_list); mark_global_ini_modified(); }); } QString proc_detector_settings::get_game_list() { return with_global_settings_object([&](QSettings& settings) { return settings.value("executable-list").toString(); }); } bool proc_detector_settings::is_enabled() { return with_global_settings_object([&](QSettings& settings) { return settings.value("executable-detector-enabled", false).toBool(); }); } void proc_detector_settings::set_is_enabled(bool enabled) { with_global_settings_object([&](QSettings& settings) { settings.setValue("executable-detector-enabled", enabled); mark_global_ini_modified(); }); } #ifdef __GNUG__ # pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif QHash proc_detector_settings::split_process_names() { QString str = get_game_list(); QStringList pairs = str.split(RECORD_SEPARATOR, QString::SkipEmptyParts); QHash ret; ret.reserve(pairs.size() * 2); for (auto const& pair : pairs) { QStringList tmp = pair.split(UNIT_SEPARATOR); if (tmp.count() != 2) continue; if (tmp[0].contains(UNIT_SEPARATOR) || tmp[0].contains(RECORD_SEPARATOR)) continue; if (tmp[1].contains(UNIT_SEPARATOR) || tmp[1].contains(RECORD_SEPARATOR)) continue; if (tmp[0].isEmpty() || tmp[1].isEmpty()) continue; ret[tmp[0]] = tmp[1]; } return ret; } void BrowseButton::browse() { QString dir_path = QFileInfo(ini_pathname()).absolutePath(); QString filename = QFileDialog::getOpenFileName( this, tr("Set executable name"), dir_path, tr("Executable (*.exe);;All Files (*)")); QDir::setCurrent(OPENTRACK_BASE_PATH); filename = QFileInfo(filename).fileName(); if (!filename.isNull()) twi->setText(filename); } int process_detector::add_row(QString const& exe_name, QString const& profile) { int i = ui.tableWidget->rowCount(); ui.tableWidget->insertRow(i); QComboBox* cb = new QComboBox(); cb->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Maximum); cb->addItems(ini_list()); cb->setCurrentText(ini_filename()); ui.tableWidget->setCellWidget(i, 1, cb); QTableWidgetItem* twi = new QTableWidgetItem(exe_name); ui.tableWidget->setItem(i, 0, twi); { BrowseButton* b = new BrowseButton(twi); b->setText("..."); QObject::connect(b, &BrowseButton::clicked, b, &BrowseButton::browse); ui.tableWidget->setCellWidget(i, 2, b); } cb->setCurrentText(profile); return i; } void process_detector::load_rows() { for (int k = ui.tableWidget->size().height() - 1; k >= 0; k--) ui.tableWidget->removeRow(k); auto names = s.split_process_names(); auto keys = names.keys(); std::sort(keys.begin(), keys.end()); for (auto const& n : keys) add_row(n, names[n]); } process_detector::process_detector(QWidget* parent) : QWidget(parent) { ui.setupUi(this); connect(ui.add, SIGNAL(clicked()), this, SLOT(add())); connect(ui.remove, SIGNAL(clicked()), this, SLOT(remove())); load_rows(); QResizeEvent e(ui.tableWidget->size(), ui.tableWidget->size()); ui.tableWidget->resizeEvent(&e); ui.enabled->setChecked(s.is_enabled()); } void process_detector::save() { QString str; for (int i = 0; i < ui.tableWidget->rowCount(); i++) { auto exe = ui.tableWidget->item(i, 0)->text(); auto widget = qobject_cast(ui.tableWidget->cellWidget(i, 1)); if (!widget) continue; auto profile = widget->currentText(); str += RECORD_SEPARATOR + exe + UNIT_SEPARATOR + profile; } s.set_game_list(str); s.set_is_enabled(ui.enabled->isChecked()); } void process_detector::revert() { load_rows(); ui.enabled->setChecked(s.is_enabled()); } void process_detector::add() { add_row(); } void process_detector::remove() { int r = ui.tableWidget->currentRow(); if (r != -1) ui.tableWidget->removeRow(r); } bool process_detector_worker::should_stop() { if (last_exe_name == QString()) return false; proc_detector_settings s; if (!s.is_enabled()) { last_exe_name = QString{}; return false; } QStringList exe_list = get_all_executable_names(); if (exe_list.contains(last_exe_name)) return false; last_exe_name = QString{}; return true; } bool process_detector_worker::profile_to_start(QString& str) { proc_detector_settings s; if (!s.is_enabled()) { last_exe_name = QString{}; return false; } auto filenames = s.split_process_names(); QStringList exe_list = get_all_executable_names(); // assuming manual stop by user button click. // don't automatically start again while the same process is running. if (!last_exe_name.isEmpty() && exe_list.contains(last_exe_name)) return false; // it's gone, we can start automatically again last_exe_name = QString(); for (auto&& name : exe_list) if (filenames.contains(name)) { str = filenames[name]; last_exe_name = name; return str != QString{}; } return false; }