summaryrefslogtreecommitdiffhomepage
path: root/trackmouse/window.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2019-03-28 13:40:33 +0100
committerStanislaw Halik <sthalik@misaki.pl>2019-03-28 13:44:59 +0100
commit47d4b25bd0583b1fd65ae885950efd34c9df256b (patch)
treef3a155717092c436e9211e1dc244edc9c9d62fa9 /trackmouse/window.cpp
parent79d56147198dc873e30ae0ca8d554d37106db56f (diff)
cmake: move around variant directories
Diffstat (limited to 'trackmouse/window.cpp')
-rw-r--r--trackmouse/window.cpp388
1 files changed, 388 insertions, 0 deletions
diff --git a/trackmouse/window.cpp b/trackmouse/window.cpp
new file mode 100644
index 00000000..d6c8a8dd
--- /dev/null
+++ b/trackmouse/window.cpp
@@ -0,0 +1,388 @@
+/* Copyright (c) 2013-2018, Stanislaw Halik <sthalik@misaki.pl>
+
+ * 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 "window.hpp"
+#include "options/options.hpp"
+#include "migration/migration.hpp"
+#include "compat/check-visible.hpp"
+#include "compat/sleep.hpp"
+#include "compat/macros.hpp"
+#include "compat/library-path.hpp"
+#include "compat/math.hpp"
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+#include <QMessageBox>
+#include <QDir>
+#include <QFile>
+#include <QString>
+#include <QList>
+#include <QEventLoop>
+#include <QApplication>
+
+extern "C" const char* const opentrack_version;
+
+using namespace options::globals;
+using namespace options;
+
+#if !defined EXIT_SUCCESS
+# define EXIT_SUCCESS 0
+#endif
+
+#if !defined EXIT_FAILURE
+# define EXIT_FAILURE 1
+#endif
+
+/* FreeBSD sysexits(3)
+ *
+ * The input data was incorrect in some way. This
+ * should only be used for user's data and not system
+ * files.
+ */
+
+#if !defined EX_OSFILE
+# define EX_OSFILE 72
+#endif
+
+void force_trackmouse_settings();
+
+main_window::main_window() : State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH)
+{
+ ui.setupUi(this);
+
+ update_button_state(false, false);
+
+ // ctrl+q exits
+ connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit()));
+
+ if (!set_profile())
+ {
+ die_on_config_not_writable();
+ exit(EX_OSFILE);
+ return;
+ }
+
+ // only tie and connect main screen options after migrations are done
+ // below is fine, set_profile() is called already
+
+ connect(this, &main_window::start_tracker,
+ this, [&] { qDebug() << "start tracker"; start_tracker_(); },
+ Qt::QueuedConnection);
+
+ connect(this, &main_window::stop_tracker,
+ this, [&] { qDebug() << "stop tracker"; stop_tracker_(); },
+ Qt::QueuedConnection);
+
+ connect(this, &main_window::toggle_tracker,
+ this, [&] { qDebug() << "toggle tracker"; toggle_tracker_(); },
+ Qt::QueuedConnection);
+
+ connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(start_tracker_()));
+ connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stop_tracker_()));
+
+ {
+ tie_setting(mouse.sensitivity_x, ui.sensitivity_slider);
+ tie_setting(mouse.sensitivity_x, ui.sensitivity_label,
+ [](double x) { return QString::number(x) + QStringLiteral("%"); });
+ // one-way only
+ tie_setting(mouse.sensitivity_x, this,
+ [this](double x) { mouse.sensitivity_y = *mouse.sensitivity_x; });
+
+ // no "ok" button, gotta save on timer
+ auto save = [this] {
+ qDebug() << "trackmouse: saving settings";
+ mouse.b->save();
+ save_settings_timer.stop();
+ };
+
+ auto start_save_timer = [this](double) {
+ save_settings_timer.start();
+ };
+
+ save_settings_timer.setInterval(save_settings_interval_ms);
+ save_settings_timer.setSingleShot(true);
+
+ ui.sensitivity_slider->setTracking(false);
+ connect(&save_settings_timer, &QTimer::timeout, this, save, Qt::DirectConnection);
+#if 1
+ // this doesn't fire the timer on application load
+ connect(ui.sensitivity_slider, &QSlider::valueChanged, this, start_save_timer, Qt::DirectConnection);
+#else
+ // but this does so let's not not use it
+ tie_setting(mouse.sensitivity_x, this, start_save_timer);
+#endif
+ }
+
+ force_trackmouse_settings();
+
+ register_shortcuts();
+ kbd_quit.setEnabled(true);
+
+ setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | windowFlags());
+ setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ adjustSize();
+
+ setVisible(true);
+ show();
+}
+
+void main_window::register_shortcuts()
+{
+ global_shortcuts.reload({
+ { s.key_toggle_tracking1, [this](bool) { main_window::toggle_tracker(); }, true },
+ });
+
+ if (work)
+ work->reload_shortcuts();
+}
+
+void main_window::die_on_config_not_writable()
+{
+ stop_tracker_();
+
+ static const QString pad(16, QChar(' '));
+
+ QMessageBox::critical(this,
+ tr("The Octopus is sad"),
+ tr("Check permissions for your .ini directory:\n\n%1\"%2\n\n"
+ "Exiting now."
+ ).arg(ini_directory(), pad),
+ QMessageBox::Close, QMessageBox::NoButton);
+
+ exit(EX_OSFILE);
+}
+
+bool main_window::maybe_die_on_config_not_writable(const QString& current)
+{
+ const bool writable =
+ with_settings_object([&](QSettings& s) {
+ return s.isWritable();
+ });
+
+ if (writable)
+ return false;
+
+ if (!QFile(ini_combine(current)).open(QFile::ReadWrite))
+ {
+ die_on_config_not_writable();
+ return true;
+ }
+
+ return false;
+}
+
+main_window::~main_window()
+{
+ // stupid ps3 eye has LED issues
+ if (work)
+ {
+ stop_tracker_();
+ close();
+
+ constexpr int inc = 100, max = 2000;
+
+ for (int k = 0; k < max; k += inc)
+ {
+ QEventLoop ev;
+ ev.processEvents();
+ portable::sleep(inc);
+ }
+ }
+
+ exit();
+}
+
+void main_window::set_working_directory()
+{
+ QDir::setCurrent(OPENTRACK_BASE_PATH);
+}
+
+void main_window::save_modules()
+{
+ m.b->save();
+}
+
+std::tuple<main_window::dylib_ptr, int>
+main_window::module_by_name(const QString& name, Modules::dylib_list& list)
+{
+ auto it = std::find_if(list.cbegin(), list.cend(), [&name](const dylib_ptr& lib) {
+ if (!lib)
+ return name.isEmpty();
+ else
+ return name == lib->module_name;
+ });
+
+ if (it == list.cend())
+ return { nullptr, -1 };
+ else
+ return { *it, std::distance(list.cbegin(), it) };
+}
+
+main_window::dylib_ptr main_window::current_tracker()
+{
+ auto [ptr, idx] = module_by_name(m.tracker_dll, modules.trackers());
+ return ptr;
+}
+
+main_window::dylib_ptr main_window::current_protocol()
+{
+ auto [ptr, idx] = module_by_name(m.protocol_dll, modules.protocols());
+ return ptr;
+}
+
+main_window::dylib_ptr main_window::current_filter()
+{
+ auto [ptr, idx] = module_by_name(m.filter_dll, modules.filters());
+ return ptr;
+}
+
+void main_window::update_button_state(bool running, bool inertialp)
+{
+ bool not_running = !running;
+#if 0
+ ui.iconcomboProfile->setEnabled(not_running);
+ ui.btnStartTracker->setEnabled(not_running);
+ ui.btnStopTracker->setEnabled(running);
+ ui.iconcomboProtocol->setEnabled(not_running);
+ ui.iconcomboFilter->setEnabled(not_running);
+ ui.iconcomboTrackerSource->setEnabled(not_running);
+ ui.profile_button->setEnabled(not_running);
+#endif
+ ui.video_frame_label->setVisible(not_running || inertialp);
+ if(not_running)
+ {
+ ui.video_frame_label->setPixmap(QPixmap(":/images/tracking-not-started.png"));
+ }
+ else {
+ ui.video_frame_label->setPixmap(QPixmap(":/images/no-feed.png"));
+ }
+}
+
+void main_window::start_tracker_()
+{
+ if (work)
+ return;
+
+ work = std::make_shared<Work>(pose, ev, ui.video_frame, current_tracker(), current_protocol(), current_filter());
+
+ if (!work->is_ok())
+ {
+ work = nullptr;
+ return;
+ }
+
+ if (pTrackerDialog)
+ pTrackerDialog->register_tracker(work->libs.pTracker.get());
+
+ if (pFilterDialog)
+ pFilterDialog->register_filter(work->libs.pFilter.get());
+
+ if (pProtocolDialog)
+ pProtocolDialog->register_protocol(work->libs.pProtocol.get());
+
+ // NB check valid since SelectedLibraries ctor called
+ // trackers take care of layout state updates
+ const bool is_inertial = ui.video_frame->layout() == nullptr;
+ update_button_state(true, is_inertial);
+
+ ui.btnStopTracker->setFocus();
+}
+
+void main_window::stop_tracker_()
+{
+ if (!work)
+ return;
+
+ with_tracker_teardown sentinel;
+
+ if (pTrackerDialog)
+ pTrackerDialog->unregister_tracker();
+
+ if (pProtocolDialog)
+ pProtocolDialog->unregister_protocol();
+
+ if (pFilterDialog)
+ pFilterDialog->unregister_filter();
+
+ work = nullptr;
+
+ update_button_state(false, false);
+ set_title();
+ ui.btnStartTracker->setFocus();
+}
+
+void main_window::set_title(const QString& game_title)
+{
+ static const QString version{opentrack_version};
+ static const QString sep { tr(" :: ") };
+ static const QString pat1{ version + sep + "%1" + sep + "%2" };
+ static const QString pat2{ version + sep + "%1" };
+
+ const QString current = ini_filename();
+
+ if (game_title.isEmpty())
+ setWindowTitle(pat2.arg(current));
+ else
+ setWindowTitle(pat1.arg(current, game_title));
+}
+
+void main_window::exit(int status)
+{
+ if (exiting_already)
+ return;
+ exiting_already = true;
+
+ qDebug() << "trackmouse: saving settings on app exit";
+ save_settings_timer.stop();
+ mouse.b->save();
+
+ //close();
+ QApplication::setQuitOnLastWindowClosed(true);
+ QApplication::exit(status);
+}
+
+bool main_window::set_profile()
+{
+ if (maybe_die_on_config_not_writable(OPENTRACK_DEFAULT_CONFIG))
+ return false;
+
+ set_profile_in_registry();
+
+ options::detail::bundler::refresh_all_bundles();
+
+ // migrations are for config layout changes and other user-visible
+ // incompatibilities in future versions
+ run_migrations();
+
+ set_title();
+
+ return true;
+}
+
+void main_window::closeEvent(QCloseEvent*)
+{
+ exit();
+}
+
+void main_window::set_profile_in_registry()
+{
+ with_global_settings_object([&](QSettings& s) {
+ s.setValue(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG);
+ });
+}
+
+void main_window::toggle_tracker_()
+{
+ qDebug() << "toggle tracker";
+ if (work)
+ stop_tracker_();
+ else
+ start_tracker_();
+}