diff options
| author | Stanislaw Halik <sthalik@misaki.pl> | 2018-01-16 04:33:14 +0100 | 
|---|---|---|
| committer | Stanislaw Halik <sthalik@misaki.pl> | 2018-01-16 06:45:52 +0100 | 
| commit | 2b1c5593b0bc1ebfcd2e808f128e4b0312f59d93 (patch) | |
| tree | e7e8f5d8d3af88a6df37cbd482edcbd3ff8def26 /variant | |
| parent | 3583e3d3cd0b6ca2515ada16ca7dcc8cce83031f (diff) | |
gui, variant/default: move default UI
Diffstat (limited to 'variant')
| -rw-r--r-- | variant/default/main-window.cpp | 945 | ||||
| -rw-r--r-- | variant/default/main-window.hpp | 158 | ||||
| -rw-r--r-- | variant/default/main-window.ui | 1453 | ||||
| -rw-r--r-- | variant/default/main.cpp | 2 | ||||
| -rw-r--r-- | variant/default/new_config.ui | 45 | ||||
| -rw-r--r-- | variant/default/new_file_dialog.cpp | 39 | ||||
| -rw-r--r-- | variant/default/new_file_dialog.h | 25 | 
7 files changed, 2666 insertions, 1 deletions
| diff --git a/variant/default/main-window.cpp b/variant/default/main-window.cpp new file mode 100644 index 00000000..9d27afdc --- /dev/null +++ b/variant/default/main-window.cpp @@ -0,0 +1,945 @@ +/* Copyright (c) 2013-2016, 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 "main-window.hpp" +#include "logic/pipeline.hpp" +#include "options/options.hpp" +#include "opentrack-library-path.h" +#include "new_file_dialog.h" +#include "migration/migration.hpp" +#include "compat/check-visible.hpp" +#include "compat/sleep.hpp" +#include "compat/macros.hpp" + +#include <QMessageBox> +#include <QDesktopServices> +#include <QDir> + +extern "C" const char* const opentrack_version; + +#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 _WIN32 && !defined __APPLE__ +#   include <unistd.h> +void MainWindow::annoy_if_root() +{ +    if (geteuid() == 0) +    { +        portable::sleep(4000); +        QMessageBox::critical(this, +                              tr("Running as root is bad"), +                              tr("Do not run as root. Set correct device node permissions."), +                              QMessageBox::Ok); +        portable::sleep(4000); +        QMessageBox::critical(this, +                              tr("Running as root is bad, seriously"), +                              tr("Do not run as root. I'll keep whining at every startup."), +                              QMessageBox::Ok); +        portable::sleep(4000); +        QMessageBox::critical(this, +                              tr("Running as root is really seriously bad"), +                              tr("Do not run as root. Be annoyed, comprehensively."), +                              QMessageBox::Ok); +    } +} +#endif + +main_window::main_window() : +    State(OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH) +{ +    ui.setupUi(this); + +#if !defined _WIN32 && !defined __APPLE__ +    annoy_if_root(); +#endif + +    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); +    setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | windowFlags()); + +    update_button_state(false, false); + +    if (group::ini_directory().size() == 0) +    { +        die_on_config_not_writable(); +        return; +    } + +    if (!refresh_config_list()) +    { +        exit(64); +        return; +    } + +    connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(show_mapping_window())); +    connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(show_options_dialog())); +    connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(show_tracker_settings())); +    connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(show_proto_settings())); +    connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(show_filter_settings())); +    connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(start_tracker_())); +    connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stop_tracker_())); +    connect(ui.iconcomboProfile, &QComboBox::currentTextChanged, this, [&](const QString& x) { set_profile(x); }); + +    // fill dylib comboboxen +    { +        modules.filters().push_front(std::make_shared<dylib>("", dylib::Filter)); + +        for (std::shared_ptr<dylib>& x : modules.trackers()) +            ui.iconcomboTrackerSource->addItem(x->icon, x->name); + +        for (std::shared_ptr<dylib>& x : modules.protocols()) +            ui.iconcomboProtocol->addItem(x->icon, x->name); + +        for (std::shared_ptr<dylib>& x : modules.filters()) +            ui.iconcomboFilter->addItem(x->icon, x->name); +    } + +    // timers +    connect(&config_list_timer, &QTimer::timeout, this, [this]() { refresh_config_list(); }); +    connect(&pose_update_timer, SIGNAL(timeout()), this, SLOT(show_pose()), Qt::DirectConnection); +    connect(&det_timer, SIGNAL(timeout()), this, SLOT(maybe_start_profile_from_executable())); + +    // ctrl+q exits +    connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit())); + +    // profile menu +    { +        profile_menu.addAction(tr("Create new empty config"), this, SLOT(make_empty_config())); +        profile_menu.addAction(tr("Create new copied config"), this, SLOT(make_copied_config())); +        profile_menu.addAction(tr("Open configuration directory"), this, SLOT(open_config_directory())); +        ui.profile_button->setMenu(&profile_menu); +    } + +    { +        const QString cur = group::ini_filename(); +        bool ok = is_config_listed(cur) ? set_profile(cur) : set_profile(OPENTRACK_DEFAULT_CONFIG); +        if (!ok) +        { +            exit(64); +            return; +        } +    } + +    // only tie and connect main screen options after migrations are done +    // below is fine, set_profile() is called already + +    // dylibs +    { +        connect(ui.iconcomboTrackerSource, +                &QComboBox::currentTextChanged, +                this, +                [&](const QString&) { if (pTrackerDialog) pTrackerDialog = nullptr; }); + +        connect(ui.iconcomboTrackerSource, +                &QComboBox::currentTextChanged, +                this, +                [&](const QString&) { if (pProtocolDialog) pProtocolDialog = nullptr; }); + +        connect(ui.iconcomboTrackerSource, +                &QComboBox::currentTextChanged, +                this, +                [&](const QString&) { if (pFilterDialog) pFilterDialog = nullptr; }); + +        connect(&m.tracker_dll, base_value::value_changed<QString>(), this, &main_window::save_modules, Qt::DirectConnection); +        connect(&m.protocol_dll, base_value::value_changed<QString>(), this, &main_window::save_modules, Qt::DirectConnection); +        connect(&m.filter_dll, base_value::value_changed<QString>(), this, &main_window::save_modules, Qt::DirectConnection); + +        tie_setting(m.tracker_dll, ui.iconcomboTrackerSource); +        tie_setting(m.protocol_dll, ui.iconcomboProtocol); +        tie_setting(m.filter_dll, ui.iconcomboFilter); +    } + +    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"; if (work) stop_tracker_(); else start_tracker_(); }, +            Qt::QueuedConnection); + +    connect(this, &main_window::restart_tracker, +            this, [&]() { qDebug() << "restart tracker"; stop_tracker_(); start_tracker_(); }, +            Qt::QueuedConnection); + +    init_tray(); + +    register_shortcuts(); +    det_timer.start(1000); +    config_list_timer.start(1000 * 5); +    kbd_quit.setEnabled(true); + +    adjustSize(); +    setFixedSize(size()); + +    if (!start_in_tray()) +    { +        setVisible(true); +        show(); +    } +    else +        setVisible(false); +} + +void main_window::init_tray() +{ +    tray_menu.clear(); + +    QString display_name(opentrack_version); +    if (display_name.startsWith("opentrack-")) +    { +        display_name = tr("opentrack") + " " + display_name.mid(sizeof("opentrack-") - 1); +    } +    if (display_name.endsWith("-DEBUG")) +        display_name.replace(display_name.size() - int(sizeof("DEBUG")), display_name.size(), tr(" (debug)")); + +    menu_action_header.setEnabled(false); +    menu_action_header.setText(display_name); +    menu_action_header.setIcon(QIcon(":/images/facetracknoir.png")); +    tray_menu.addAction(&menu_action_header); + +    menu_action_show.setIconVisibleInMenu(true); +    menu_action_show.setText(isHidden() ? tr("Show the Octopus") : tr("Hide the Octopus")); +    menu_action_show.setIcon(QIcon(":/images/facetracknoir.png")); +    QObject::connect(&menu_action_show, &QAction::triggered, this, [&]() { toggle_restore_from_tray(QSystemTrayIcon::Trigger); }); +    tray_menu.addAction(&menu_action_show); + +    tray_menu.addSeparator(); + +    menu_action_tracker.setText(tr("Tracker settings")); +    menu_action_tracker.setIcon(QIcon(":/images/tools.png")); +    QObject::connect(&menu_action_tracker, &QAction::triggered, this, &main_window::show_tracker_settings); +    tray_menu.addAction(&menu_action_tracker); + +    menu_action_filter.setText(tr("Filter settings")); +    menu_action_filter.setIcon(QIcon(":/images/filter-16.png")); +    QObject::connect(&menu_action_filter, &QAction::triggered, this, &main_window::show_filter_settings); +    tray_menu.addAction(&menu_action_filter); + +    menu_action_proto.setText(tr("Protocol settings")); +    menu_action_proto.setIcon(QIcon(":/images/settings16.png")); +    QObject::connect(&menu_action_proto, &QAction::triggered, this, &main_window::show_proto_settings); +    tray_menu.addAction(&menu_action_proto); + +    tray_menu.addSeparator(); + +    menu_action_mappings.setIcon(QIcon(":/images/curves.png")); +    menu_action_mappings.setText(tr("Mappings")); +    QObject::connect(&menu_action_mappings, &QAction::triggered, this, &main_window::show_mapping_window); +    tray_menu.addAction(&menu_action_mappings); + +    menu_action_options.setIcon(QIcon(":/images/tools.png")); +    menu_action_options.setText(tr("Options")); +    QObject::connect(&menu_action_options, &QAction::triggered, this, &main_window::show_options_dialog); +    tray_menu.addAction(&menu_action_options); + +    tray_menu.addSeparator(); + +    menu_action_exit.setText(tr("Exit")); +    QObject::connect(&menu_action_exit, &QAction::triggered, this, &main_window::exit); +    tray_menu.addAction(&menu_action_exit); + +    connect(&s.tray_enabled, +            static_cast<void (base_value::*)(bool) const>(&base_value::valueChanged), +            this, +            &main_window::ensure_tray); +} + +void main_window::register_shortcuts() +{ +    using t_key = Shortcuts::t_key; +    using t_keys = Shortcuts::t_keys; + +    t_keys keys +    { +        t_key(s.key_start_tracking1, [&](bool) { start_tracker(); }, true), +        t_key(s.key_start_tracking2, [&](bool) { start_tracker(); }, true), + +        t_key(s.key_stop_tracking1, [&](bool) { stop_tracker(); }, true), +        t_key(s.key_stop_tracking2, [&](bool) { stop_tracker(); }, true), + +        t_key(s.key_toggle_tracking1, [&](bool) { toggle_tracker(); }, true), +        t_key(s.key_toggle_tracking2, [&](bool) { toggle_tracker(); }, true), + +        t_key(s.key_restart_tracking1, [&](bool) { restart_tracker(); }, true), +        t_key(s.key_restart_tracking2, [&](bool) { restart_tracker(); }, true), +    }; + +    global_shortcuts.reload(keys); + +    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\nExiting now.").arg(group::ini_directory()).arg(pad), +                          QMessageBox::Close, QMessageBox::NoButton); + +    exit(64); +} + +bool main_window::maybe_die_on_config_not_writable(const QString& current, QStringList* ini_list_) +{ +    const bool writable = +        group::with_settings_object([&](QSettings& s) { +            return s.isWritable(); +        }); + +    if (writable) +        return false; + +    const bool open = QFile(group::ini_combine(current)).open(QFile::ReadWrite); +    const QStringList ini_list = group::ini_list(); + +    if (!ini_list.contains(current) || !open) +    { +        die_on_config_not_writable(); +        return true; +    } + +    if (ini_list_ != nullptr) +        *ini_list_ = ini_list; + +    return false; +} + +bool main_window::get_new_config_name_from_dialog(QString& ret) +{ +    new_file_dialog dlg; +    dlg.exec(); +    return dlg.is_ok(ret); +} + +main_window::~main_window() +{ +    if (tray) +        tray->hide(); +    tray = nullptr; + +    const bool just_stopping = bool(work); + +    // stupid ps3 eye has LED issues +    if (just_stopping) +    { +        stop_tracker_(); +        close(); +        QEventLoop ev; +        ev.processEvents(); +        portable::sleep(2000); +    } +} + +void main_window::set_working_directory() +{ +    QDir::setCurrent(OPENTRACK_BASE_PATH); +} + +void main_window::save_modules() +{ +    qDebug() << "save modules"; +    m.b->save(); +} + +void main_window::make_empty_config() +{ +    QString name; +    if (get_new_config_name_from_dialog(name)) +    { +        QFile(group::ini_combine(name)).open(QFile::ReadWrite); + +        if (!refresh_config_list()) +            return; + +        if (is_config_listed(name)) +        { +            QSignalBlocker q(ui.iconcomboProfile); + +            if (!set_profile(name)) +                return; +            mark_config_as_not_needing_migration(); +        } +    } +} + +void main_window::make_copied_config() +{ +    const QString cur = group::ini_pathname(); +    QString name; +    if (cur != "" && get_new_config_name_from_dialog(name)) +    { +        const QString new_name = group::ini_combine(name); +        (void) QFile::remove(new_name); +        QFile::copy(cur, new_name); + +        if (!refresh_config_list()) +            return; + +        if (is_config_listed(name)) +        { +            QSignalBlocker q(ui.iconcomboProfile); + +            if (!set_profile(name)) +                return; +            mark_config_as_not_needing_migration(); +        } +    } + +} + +void main_window::open_config_directory() +{ +    QDesktopServices::openUrl("file:///" + QDir::toNativeSeparators(group::ini_directory())); +} + +bool main_window::refresh_config_list() +{ +    if (work) +        return true; + +    QStringList ini_list = group::ini_list(); + +    // check for sameness +    const bool exact_same = ini_list.size() > 0 && progn( +        if (ini_list.size() == ui.iconcomboProfile->count()) +        { +            const int sz = ini_list.size(); +            for (int i = 0; i < sz; i++) +            { +                if (ini_list[i] != ui.iconcomboProfile->itemText(i)) +                    return false; +            } +            return true; +        } + +        return false; +    ); + +    QString current = group::ini_filename(); + +    if (!ini_list.contains(current)) +        current = OPENTRACK_DEFAULT_CONFIG_Q; + +    if (maybe_die_on_config_not_writable(current, &ini_list)) +        return false; + +    if (exact_same) +        return true; + +    const QIcon icon(":/images/settings16.png"); + +    QSignalBlocker l(ui.iconcomboProfile); + +    ui.iconcomboProfile->clear(); +    ui.iconcomboProfile->addItems(ini_list); + +    for (int i = 0; i < ini_list.size(); i++) +        ui.iconcomboProfile->setItemIcon(i, icon); + +    ui.iconcomboProfile->setCurrentText(current); + +    return true; +} + +void main_window::update_button_state(bool running, bool inertialp) +{ +    bool not_running = !running; +    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); +    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; + +    { +        double p[6] = {0,0,0, 0,0,0}; +        display_pose(p, p); +    } + +    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()); + +    pose_update_timer.start(50); + +    // 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; + +    pose_update_timer.stop(); +    ui.pose_display->rotate_sync(0,0,0, 0,0,0); + +    if (pTrackerDialog) +        pTrackerDialog->unregister_tracker(); + +    if (pProtocolDialog) +        pProtocolDialog->unregister_protocol(); + +    if (pFilterDialog) +        pFilterDialog->unregister_filter(); + +    work = nullptr; + +    { +        double p[6] = {0,0,0, 0,0,0}; +        display_pose(p, p); +    } + +    update_button_state(false, false); +    set_title(); +    ui.btnStartTracker->setFocus(); +} + +void main_window::display_pose(const double *mapped, const double *raw) +{ +    ui.pose_display->rotate_async(mapped[Yaw], mapped[Pitch], -mapped[Roll], +                                  mapped[TX], mapped[TY], mapped[TZ]); + +    QLCDNumber* raw_[] = { +        ui.raw_x, ui.raw_y, ui.raw_z, +        ui.raw_yaw, ui.raw_pitch, ui.raw_roll, +    }; + +    QLCDNumber* mapped_[] = { +        ui.pose_x, ui.pose_y, ui.pose_z, +        ui.pose_yaw, ui.pose_pitch, ui.pose_roll, +    }; + +    for (int k = 0; k < 6; k++) +    { +        raw_[k]->display(iround(raw[k])); +        mapped_[k]->display(iround(mapped[k])); +    } + +    QString game_title; +    if (work && work->libs.pProtocol) +        game_title = work->libs.pProtocol->game_name(); +    set_title(game_title); +} + +void main_window::set_title(const QString& game_title_) +{ +    QString game_title; +    if (game_title_ != "") +        game_title = tr(" :: ") + game_title_; +    QString current = group::ini_filename(); +    QString version(opentrack_version); +    version = tr("opentrack") + " " + version.mid(sizeof("opentrack-") - 1); +    setWindowTitle(version + tr(" :: ") + current + game_title); +} + +void main_window::show_pose() +{ +    set_is_visible(*this); + +    if (mapping_widget) +        mapping_widget->refresh_tab(); + +    if (!check_is_visible()) +        return; + +    double mapped[6], raw[6]; + +    work->tracker->raw_and_mapped_pose(mapped, raw); + +    display_pose(mapped, raw); +} + +template<typename t, typename F> +bool main_window::mk_window_common(std::unique_ptr<t>& d, F&& ctor) +{ +    if (d) +    { +        d->show(); +        d->raise(); + +        return false; +    } +    else if ((d = std::unique_ptr<t>(ctor()))) +    { +        QWidget& w = *d; + +        w.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | w.windowFlags()); + +        w.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + +        w.show(); +        w.adjustSize(); +        w.setFixedSize(w.size()); + +        return true; +    } + +    return false; +} + +template<typename t, typename... Args> +inline bool main_window::mk_window(std::unique_ptr<t>& place, Args&&... params) +{ +    return mk_window_common(place, [&]() { return new t(std::forward<Args>(params)...); }); +} + +template<typename t> +bool main_window::mk_dialog(std::shared_ptr<dylib> lib, std::unique_ptr<t>& d) +{ +    const bool just_created = mk_window_common(d, [&]() -> t* { +        if (lib && lib->Dialog) +            return (t*) lib->Dialog(); +        return nullptr; +    }); + +    return just_created; +} + +void main_window::show_tracker_settings() +{ +    if (mk_dialog(current_tracker(), pTrackerDialog) && work && work->libs.pTracker) +        pTrackerDialog->register_tracker(work->libs.pTracker.get()); +    if (pTrackerDialog) +        // must run bundle::reload(), don't remove next line +        QObject::connect(pTrackerDialog.get(), &ITrackerDialog::closing, +                         this, [this]() { pTrackerDialog = nullptr; }); +} + +void main_window::show_proto_settings() +{ +    if (mk_dialog(current_protocol(), pProtocolDialog) && work && work->libs.pProtocol) +        pProtocolDialog->register_protocol(work->libs.pProtocol.get()); +    if (pProtocolDialog) +        // must run bundle::reload(), don't remove next line +        QObject::connect(pProtocolDialog.get(), &IProtocolDialog::closing, +                         this, [this]() { pProtocolDialog = nullptr; }); +} + +void main_window::show_filter_settings() +{ +    if (mk_dialog(current_filter(), pFilterDialog) && work && work->libs.pFilter) +        pFilterDialog->register_filter(work->libs.pFilter.get()); +    if (pFilterDialog) +        // must run bundle::reload(), don't remove next line +        QObject::connect(pFilterDialog.get(), &IFilterDialog::closing, +                         this, [this]() { pFilterDialog = nullptr; }); +} + +void main_window::show_options_dialog() +{ +    if (mk_window(options_widget, [&](bool flag) { set_keys_enabled(!flag); })) +    { +        connect(options_widget.get(), &options_dialog::closing, +                  this, &main_window::register_shortcuts); +    } +} + +void main_window::show_mapping_window() +{ +    mk_window(mapping_widget, pose); +} + +void main_window::exit(int status) +{ +    QApplication::setQuitOnLastWindowClosed(true); +    if (tray) +        tray->hide(); +    tray = nullptr; +    close(); +    QApplication::exit(status); +} + +bool main_window::set_profile(const QString& new_name_) +{ +    if (!refresh_config_list()) +        return false; + +    QString new_name = new_name_; + +    if (!is_config_listed(new_name)) +        new_name = OPENTRACK_DEFAULT_CONFIG_Q; + +    if (maybe_die_on_config_not_writable(new_name, nullptr)) +        return false; + +    ui.iconcomboProfile->setCurrentText(new_name); +    set_profile_in_registry(new_name); + +    set_title(); +    options::detail::bundler::refresh_all_bundles(); + +    // migrations are for config layout changes and other user-visible +    // incompatibilities in future versions +    run_migrations(); + +    return true; +} + +void main_window::ensure_tray() +{     +    if (!QSystemTrayIcon::isSystemTrayAvailable()) +    { +        QApplication::setQuitOnLastWindowClosed(true); +        return; +    } + +    if (s.tray_enabled) +    { +        if (!tray) +        { +            tray = std::make_unique<QSystemTrayIcon>(this); +            tray->setIcon(QIcon(":/images/facetracknoir.png")); +            tray->setContextMenu(&tray_menu); +            tray->show(); + +            connect(tray.get(), +                    &QSystemTrayIcon::activated, +                    this, +                    &main_window::toggle_restore_from_tray); +        } + +        QApplication::setQuitOnLastWindowClosed(false); +    } +    else +    { +        const bool is_hidden = isHidden() || !isVisible(); + +        if (is_hidden) +        { +            show(); +            setVisible(true); + +            raise(); // for OSX +            activateWindow(); // for Windows +        } + +        if (tray) +            tray->hide(); +        tray = nullptr; + +        QApplication::setQuitOnLastWindowClosed(true); +    } +} + +void main_window::toggle_restore_from_tray(QSystemTrayIcon::ActivationReason e) +{ +    if (progn( +        switch (e) +        { +        // if we enable double click also then it causes +        // toggle back to the original state +        //case QSystemTrayIcon::DoubleClick: +        case QSystemTrayIcon::Trigger: // single click +            return false; +        default: +            return true; +        } +    )) +    { +        return; +    } + +    ensure_tray(); + +    const bool is_minimized = isHidden() || !is_tray_enabled(); + +    menu_action_show.setText(!isHidden() ? tr("Show the Octopus") : tr("Hide the Octopus")); + +    setVisible(is_minimized); +    setHidden(!is_minimized); + +    setWindowState(progn( +        using ws = Qt::WindowStates; +        if (is_minimized) +           return ws(windowState() & (~Qt::WindowMinimized)); +        else +           return ws(Qt::WindowNoState); +    )); + +    if (is_minimized) +    { +        raise(); // for OSX +        activateWindow(); // for Windows +    } +    else +    { +        lower(); +        clearFocus(); +    } +} + +bool main_window::maybe_hide_to_tray(QEvent* e) +{ +    if (e->type() == QEvent::WindowStateChange && +        (windowState() & Qt::WindowMinimized) && +        is_tray_enabled()) +    { +        e->accept(); +        ensure_tray(); +        hide(); + +        return true; +    } + +    return false; +} + +void main_window::maybe_start_profile_from_executable() +{ +    if (!work) +    { +        QString prof; +        if (det.config_to_start(prof)) +        { +            ui.iconcomboProfile->setCurrentText(prof); +            start_tracker_(); +        } +    } +    else +    { +        if (det.should_stop()) +            stop_tracker_(); +    } +} + +void main_window::set_keys_enabled(bool flag) +{ +    if (!flag) +    { +        if (work) +            work->sc->reload({}); +        global_shortcuts.reload({}); +    } +    else +    { +        register_shortcuts(); +    } +} + +bool main_window::is_config_listed(const QString& name) +{ +    const int sz = ui.iconcomboProfile->count(); +    for (int i = 0; i < sz; i++) +        if (ui.iconcomboProfile->itemText(i) == name) +            return true; +    return false; +} + +void main_window::changeEvent(QEvent* e) +{ +    if (!maybe_hide_to_tray(e)) +        e->ignore(); +} + +void main_window::closeEvent(QCloseEvent* ev) +{ +    if (tray && tray->isVisible()) +    { +        ev->ignore(); +        setVisible(false); +    } +    else +    { +        ev->accept(); +    } +} + +bool main_window::event(QEvent* event) +{ +    using t = QEvent::Type; + +    if (work) +    { +        switch (event->type()) +        { +        case t::Hide: +        case t::WindowActivate: +        case t::WindowDeactivate: +        case t::WindowStateChange: +        case t::FocusIn: +            set_is_visible(*this, true); +            /*FALLTHROUGH*/ +        default: +            break; +        } +    } +    return QMainWindow::event(event); +} + +bool main_window::is_tray_enabled() +{ +    return s.tray_enabled && QSystemTrayIcon::isSystemTrayAvailable(); +} + +bool main_window::start_in_tray() +{ +    return s.tray_enabled && s.tray_start && QSystemTrayIcon::isSystemTrayAvailable(); +} + +void main_window::set_profile_in_registry(const QString &profile) +{ +    group::with_global_settings_object([&](QSettings& s) { +        s.setValue(OPENTRACK_CONFIG_FILENAME_KEY, profile); +    }); +} diff --git a/variant/default/main-window.hpp b/variant/default/main-window.hpp new file mode 100644 index 00000000..844542f1 --- /dev/null +++ b/variant/default/main-window.hpp @@ -0,0 +1,158 @@ +/* Copyright (c) 2013-2016, 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. + */ + +#pragma once + +#include "api/plugin-support.hpp" +#include "gui/mapping-dialog.hpp" +#include "gui/settings.hpp" +#include "gui/process_detector.h" +#include "logic/main-settings.hpp" +#include "logic/pipeline.hpp" +#include "logic/shortcuts.h" +#include "logic/work.hpp" +#include "logic/state.hpp" +#include "options/options.hpp" + +#include <QApplication> +#include <QMainWindow> +#include <QKeySequence> +#include <QShortcut> +#include <QPixmap> +#include <QTimer> +#include <QSystemTrayIcon> +#include <QString> +#include <QMenu> +#include <QAction> +#include <QEvent> +#include <QCloseEvent> + +#include <vector> +#include <tuple> +#include <memory> + +#include "gui/ui_main-window.h" + +using namespace options; + +class main_window : public QMainWindow, private State +{ +    Q_OBJECT + +    Ui::main_window ui; + +    Shortcuts global_shortcuts; +    module_settings m; +    std::unique_ptr<QSystemTrayIcon> tray; +    QMenu tray_menu; +    QTimer pose_update_timer { this }; +    QTimer det_timer; +    QTimer config_list_timer; +    std::unique_ptr<options_dialog> options_widget; +    std::unique_ptr<mapping_dialog> mapping_widget; +    QShortcut kbd_quit { QKeySequence("Ctrl+Q"), this }; +    std::unique_ptr<IFilterDialog> pFilterDialog; +    std::unique_ptr<IProtocolDialog> pProtocolDialog; +    std::unique_ptr<ITrackerDialog> pTrackerDialog; + +    process_detector_worker det; +    QMenu profile_menu; + +    QAction menu_action_header   { &tray_menu }, +            menu_action_show     { &tray_menu }, +            menu_action_exit     { &tray_menu }, +            menu_action_tracker  { &tray_menu }, +            menu_action_filter   { &tray_menu }, +            menu_action_proto    { &tray_menu }, +            menu_action_options  { &tray_menu }, +            menu_action_mappings { &tray_menu }; + +    std::shared_ptr<dylib> current_tracker() +    { +        return modules.trackers().value(ui.iconcomboTrackerSource->currentIndex(), nullptr); +    } +    std::shared_ptr<dylib> current_protocol() +    { +        return modules.protocols().value(ui.iconcomboProtocol->currentIndex(), nullptr); +    } +    std::shared_ptr<dylib> current_filter() +    { +        return modules.filters().value(ui.iconcomboFilter->currentIndex(), nullptr); +    } + +    void update_button_state(bool running, bool inertialp); +    void display_pose(const double* mapped, const double* raw); +    void set_title(const QString& game_title = QStringLiteral("")); +    static bool get_new_config_name_from_dialog(QString &ret); +    void set_profile_in_registry(const QString& profile); +    void register_shortcuts(); +    void set_keys_enabled(bool flag); +    bool is_config_listed(const QString& name); + +    void init_tray(); + +    void changeEvent(QEvent* e) override; +    void closeEvent(QCloseEvent* ev) override; +    bool event(QEvent *event) override; +    bool maybe_hide_to_tray(QEvent* e); +#if !defined _WIN32 && !defined __APPLE__ +    void annoy_if_root(); +#endif + +    // only use in impl file since no definition in header! +    template<typename t> +    bool mk_dialog(std::shared_ptr<dylib> lib, std::unique_ptr<t>& d); + +    // idem +    template<typename t, typename... Args> +    inline bool mk_window(std::unique_ptr<t>& place, Args&&... params); + +    // idem +    template<typename t, typename F> +    bool mk_window_common(std::unique_ptr<t>& d, F&& ctor); + +private slots: +    void save_modules(); +    void exit(int status = EXIT_SUCCESS); +    bool set_profile(const QString& new_name); + +    void show_tracker_settings(); +    void show_proto_settings(); +    void show_filter_settings(); +    void show_options_dialog(); +    void show_mapping_window(); +    void show_pose(); + +    void maybe_start_profile_from_executable(); + +    void make_empty_config(); +    void make_copied_config(); +    void open_config_directory(); +    bool refresh_config_list(); + +    void start_tracker_(); +    void stop_tracker_(); + +    void ensure_tray(); + +    void toggle_restore_from_tray(QSystemTrayIcon::ActivationReason e); + +signals: +    void start_tracker(); +    void stop_tracker(); +    void toggle_tracker(); +    void restart_tracker(); +public: +    main_window(); +    ~main_window(); +    static void set_working_directory(); +    bool maybe_die_on_config_not_writable(const QString& current, QStringList* ini_list); +    void die_on_config_not_writable(); +    bool is_tray_enabled(); +    bool start_in_tray(); +}; diff --git a/variant/default/main-window.ui b/variant/default/main-window.ui new file mode 100644 index 00000000..ce8e161f --- /dev/null +++ b/variant/default/main-window.ui @@ -0,0 +1,1453 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <author>Lovecraftian Octopus</author> + <class>main_window</class> + <widget class="QMainWindow" name="main_window"> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>651</width> +    <height>499</height> +   </rect> +  </property> +  <property name="windowIcon"> +   <iconset resource="opentrack-res.qrc"> +    <normaloff>:/images/facetracknoir.png</normaloff>:/images/facetracknoir.png</iconset> +  </property> +  <property name="styleSheet"> +   <string notr="true">#video_feed { border: 0; } +</string> +  </property> +  <widget class="QWidget" name="content"> +   <property name="sizePolicy"> +    <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +     <horstretch>0</horstretch> +     <verstretch>0</verstretch> +    </sizepolicy> +   </property> +   <layout class="QHBoxLayout" name="horizontalLayout_5"> +    <property name="spacing"> +     <number>0</number> +    </property> +    <property name="leftMargin"> +     <number>0</number> +    </property> +    <property name="topMargin"> +     <number>0</number> +    </property> +    <property name="rightMargin"> +     <number>6</number> +    </property> +    <property name="bottomMargin"> +     <number>6</number> +    </property> +    <item> +     <widget class="QFrame" name="frame"> +      <property name="frameShape"> +       <enum>QFrame::NoFrame</enum> +      </property> +      <property name="frameShadow"> +       <enum>QFrame::Raised</enum> +      </property> +      <property name="lineWidth"> +       <number>0</number> +      </property> +      <layout class="QVBoxLayout" name="verticalLayout_5"> +       <property name="spacing"> +        <number>0</number> +       </property> +       <property name="leftMargin"> +        <number>0</number> +       </property> +       <property name="topMargin"> +        <number>0</number> +       </property> +       <property name="rightMargin"> +        <number>0</number> +       </property> +       <property name="bottomMargin"> +        <number>0</number> +       </property> +       <item> +        <widget class="QFrame" name="top"> +         <property name="sizePolicy"> +          <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +           <horstretch>0</horstretch> +           <verstretch>0</verstretch> +          </sizepolicy> +         </property> +         <property name="frameShape"> +          <enum>QFrame::NoFrame</enum> +         </property> +         <layout class="QHBoxLayout" name="horizontalLayout_2"> +          <property name="spacing"> +           <number>0</number> +          </property> +          <property name="leftMargin"> +           <number>0</number> +          </property> +          <property name="topMargin"> +           <number>0</number> +          </property> +          <property name="rightMargin"> +           <number>0</number> +          </property> +          <property name="bottomMargin"> +           <number>4</number> +          </property> +          <item> +           <widget class="QFrame" name="video_feed"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="minimumSize"> +             <size> +              <width>320</width> +              <height>240</height> +             </size> +            </property> +            <property name="maximumSize"> +             <size> +              <width>320</width> +              <height>240</height> +             </size> +            </property> +            <widget class="QFrame" name="video_frame"> +             <property name="geometry"> +              <rect> +               <x>0</x> +               <y>0</y> +               <width>320</width> +               <height>240</height> +              </rect> +             </property> +             <property name="sizePolicy"> +              <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> +               <horstretch>0</horstretch> +               <verstretch>0</verstretch> +              </sizepolicy> +             </property> +             <property name="minimumSize"> +              <size> +               <width>320</width> +               <height>240</height> +              </size> +             </property> +             <property name="maximumSize"> +              <size> +               <width>320</width> +               <height>240</height> +              </size> +             </property> +             <widget class="QLabel" name="video_frame_label"> +              <property name="geometry"> +               <rect> +                <x>0</x> +                <y>0</y> +                <width>320</width> +                <height>240</height> +               </rect> +              </property> +              <property name="sizePolicy"> +               <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> +                <horstretch>0</horstretch> +                <verstretch>0</verstretch> +               </sizepolicy> +              </property> +              <property name="minimumSize"> +               <size> +                <width>320</width> +                <height>240</height> +               </size> +              </property> +              <property name="maximumSize"> +               <size> +                <width>320</width> +                <height>240</height> +               </size> +              </property> +              <property name="font"> +               <font> +                <family>Candara</family> +                <pointsize>37</pointsize> +                <weight>50</weight> +                <bold>false</bold> +                <kerning>true</kerning> +               </font> +              </property> +              <property name="text"> +               <string/> +              </property> +              <property name="pixmap"> +               <pixmap resource="opentrack-res.qrc">:/images/tracking-not-started.png</pixmap> +              </property> +              <property name="scaledContents"> +               <bool>false</bool> +              </property> +              <property name="alignment"> +               <set>Qt::AlignCenter</set> +              </property> +              <property name="wordWrap"> +               <bool>true</bool> +              </property> +             </widget> +            </widget> +           </widget> +          </item> +          <item> +           <widget class="pose_widget" name="pose_display" native="true"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="minimumSize"> +             <size> +              <width>320</width> +              <height>240</height> +             </size> +            </property> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QFrame" name="top_display"> +         <property name="sizePolicy"> +          <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +           <horstretch>0</horstretch> +           <verstretch>0</verstretch> +          </sizepolicy> +         </property> +         <property name="frameShape"> +          <enum>QFrame::NoFrame</enum> +         </property> +         <property name="lineWidth"> +          <number>0</number> +         </property> +         <layout class="QHBoxLayout" name="horizontalLayout_3"> +          <property name="spacing"> +           <number>6</number> +          </property> +          <property name="leftMargin"> +           <number>5</number> +          </property> +          <property name="topMargin"> +           <number>0</number> +          </property> +          <property name="rightMargin"> +           <number>0</number> +          </property> +          <property name="bottomMargin"> +           <number>6</number> +          </property> +          <item> +           <widget class="QGroupBox" name="box_raw_headpose"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="title"> +             <string>Raw tracker data</string> +            </property> +            <layout class="QGridLayout" name="gridLayout_12"> +             <property name="leftMargin"> +              <number>0</number> +             </property> +             <property name="topMargin"> +              <number>0</number> +             </property> +             <property name="rightMargin"> +              <number>0</number> +             </property> +             <property name="bottomMargin"> +              <number>0</number> +             </property> +             <property name="spacing"> +              <number>0</number> +             </property> +             <item row="0" column="3"> +              <widget class="QLCDNumber" name="raw_yaw"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="0"> +              <widget class="QLabel" name="lblZ_4"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Z</string> +               </property> +              </widget> +             </item> +             <item row="1" column="2"> +              <widget class="QLabel" name="lblRotY_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Pitch</string> +               </property> +              </widget> +             </item> +             <item row="1" column="3"> +              <widget class="QLCDNumber" name="raw_pitch"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="1" column="0"> +              <widget class="QLabel" name="lblY_4"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Y</string> +               </property> +              </widget> +             </item> +             <item row="0" column="0"> +              <widget class="QLabel" name="lblX_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>X</string> +               </property> +              </widget> +             </item> +             <item row="0" column="1"> +              <widget class="QLCDNumber" name="raw_x"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="2"> +              <widget class="QLabel" name="lblRotZ_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Roll</string> +               </property> +              </widget> +             </item> +             <item row="0" column="2"> +              <widget class="QLabel" name="lblRotX_4"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Yaw</string> +               </property> +              </widget> +             </item> +             <item row="1" column="1"> +              <widget class="QLCDNumber" name="raw_y"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="3"> +              <widget class="QLCDNumber" name="raw_roll"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="1"> +              <widget class="QLCDNumber" name="raw_z"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Plain</enum> +               </property> +               <property name="lineWidth"> +                <number>1</number> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Outline</enum> +               </property> +              </widget> +             </item> +            </layout> +           </widget> +          </item> +          <item> +           <widget class="QGroupBox" name="box_mapped_headpose"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum"> +              <horstretch>0</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="title"> +             <string>Game data</string> +            </property> +            <layout class="QGridLayout" name="gridLayout_14"> +             <property name="leftMargin"> +              <number>0</number> +             </property> +             <property name="topMargin"> +              <number>0</number> +             </property> +             <property name="rightMargin"> +              <number>0</number> +             </property> +             <property name="bottomMargin"> +              <number>0</number> +             </property> +             <property name="spacing"> +              <number>0</number> +             </property> +             <item row="1" column="3"> +              <widget class="QLCDNumber" name="pose_pitch"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="0" column="3"> +              <widget class="QLCDNumber" name="pose_yaw"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="1"> +              <widget class="QLCDNumber" name="pose_z"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="0" column="0"> +              <widget class="QLabel" name="lblx"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>X</string> +               </property> +              </widget> +             </item> +             <item row="1" column="0"> +              <widget class="QLabel" name="lblY_2"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Y</string> +               </property> +              </widget> +             </item> +             <item row="0" column="1"> +              <widget class="QLCDNumber" name="pose_x"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="1" column="2"> +              <widget class="QLabel" name="lblRotY_2"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Pitch</string> +               </property> +              </widget> +             </item> +             <item row="2" column="2"> +              <widget class="QLabel" name="lblRotZ_2"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Roll</string> +               </property> +              </widget> +             </item> +             <item row="0" column="2"> +              <widget class="QLabel" name="lblRotX_2"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Yaw</string> +               </property> +              </widget> +             </item> +             <item row="2" column="0"> +              <widget class="QLabel" name="lblZ_2"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="autoFillBackground"> +                <bool>false</bool> +               </property> +               <property name="frameShadow"> +                <enum>QFrame::Raised</enum> +               </property> +               <property name="text"> +                <string>Z</string> +               </property> +              </widget> +             </item> +             <item row="1" column="1"> +              <widget class="QLCDNumber" name="pose_y"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +             <item row="2" column="3"> +              <widget class="QLCDNumber" name="pose_roll"> +               <property name="enabled"> +                <bool>true</bool> +               </property> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="font"> +                <font> +                 <stylestrategy>NoAntialias</stylestrategy> +                 <kerning>false</kerning> +                </font> +               </property> +               <property name="frameShape"> +                <enum>QFrame::NoFrame</enum> +               </property> +               <property name="smallDecimalPoint"> +                <bool>true</bool> +               </property> +               <property name="digitCount"> +                <number>4</number> +               </property> +               <property name="segmentStyle"> +                <enum>QLCDNumber::Flat</enum> +               </property> +              </widget> +             </item> +            </layout> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +       <item> +        <widget class="QFrame" name="bottom_controls"> +         <property name="sizePolicy"> +          <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +           <horstretch>0</horstretch> +           <verstretch>0</verstretch> +          </sizepolicy> +         </property> +         <layout class="QGridLayout" name="gridLayout_2"> +          <property name="leftMargin"> +           <number>6</number> +          </property> +          <property name="topMargin"> +           <number>0</number> +          </property> +          <property name="rightMargin"> +           <number>0</number> +          </property> +          <property name="bottomMargin"> +           <number>0</number> +          </property> +          <property name="spacing"> +           <number>6</number> +          </property> +          <item row="0" column="1"> +           <widget class="QFrame" name="groupWindows"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +              <horstretch>4</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="lineWidth"> +             <number>0</number> +            </property> +            <layout class="QVBoxLayout" name="verticalLayout_3"> +             <property name="spacing"> +              <number>3</number> +             </property> +             <property name="leftMargin"> +              <number>0</number> +             </property> +             <property name="topMargin"> +              <number>0</number> +             </property> +             <property name="rightMargin"> +              <number>0</number> +             </property> +             <property name="bottomMargin"> +              <number>0</number> +             </property> +             <item> +              <widget class="QFrame" name="groupProfile"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <layout class="QHBoxLayout" name="horizontalLayout"> +                <property name="spacing"> +                 <number>0</number> +                </property> +                <property name="leftMargin"> +                 <number>0</number> +                </property> +                <property name="topMargin"> +                 <number>0</number> +                </property> +                <property name="rightMargin"> +                 <number>0</number> +                </property> +                <property name="bottomMargin"> +                 <number>0</number> +                </property> +                <item> +                 <widget class="QToolButton" name="profile_button"> +                  <property name="enabled"> +                   <bool>true</bool> +                  </property> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::StrongFocus</enum> +                  </property> +                  <property name="text"> +                   <string>Profile</string> +                  </property> +                  <property name="popupMode"> +                   <enum>QToolButton::InstantPopup</enum> +                  </property> +                  <property name="toolButtonStyle"> +                   <enum>Qt::ToolButtonTextBesideIcon</enum> +                  </property> +                  <property name="autoRaise"> +                   <bool>true</bool> +                  </property> +                  <property name="arrowType"> +                   <enum>Qt::DownArrow</enum> +                  </property> +                 </widget> +                </item> +                <item> +                 <widget class="QComboBox" name="iconcomboProfile"> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::StrongFocus</enum> +                  </property> +                  <property name="maxVisibleItems"> +                   <number>20</number> +                  </property> +                 </widget> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <widget class="QPushButton" name="btnShortcuts"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="text"> +                <string>Options</string> +               </property> +               <property name="icon"> +                <iconset resource="opentrack-res.qrc"> +                 <normaloff>:/images/tools.png</normaloff>:/images/tools.png</iconset> +               </property> +               <property name="iconSize"> +                <size> +                 <width>80</width> +                 <height>24</height> +                </size> +               </property> +              </widget> +             </item> +             <item> +              <widget class="QPushButton" name="btnEditCurves"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="text"> +                <string>Mapping</string> +               </property> +               <property name="icon"> +                <iconset resource="opentrack-res.qrc"> +                 <normaloff>:/images/curves.png</normaloff>:/images/curves.png</iconset> +               </property> +               <property name="iconSize"> +                <size> +                 <width>80</width> +                 <height>24</height> +                </size> +               </property> +              </widget> +             </item> +             <item> +              <widget class="QGroupBox" name="groupStartStop"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +                 <horstretch>3</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="title"> +                <string>Tracking</string> +               </property> +               <property name="flat"> +                <bool>true</bool> +               </property> +               <layout class="QHBoxLayout" name="horizontalLayout_4"> +                <property name="spacing"> +                 <number>8</number> +                </property> +                <property name="leftMargin"> +                 <number>0</number> +                </property> +                <property name="topMargin"> +                 <number>6</number> +                </property> +                <property name="rightMargin"> +                 <number>0</number> +                </property> +                <property name="bottomMargin"> +                 <number>6</number> +                </property> +                <item> +                 <widget class="QToolButton" name="btnStartTracker"> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="font"> +                   <font> +                    <weight>75</weight> +                    <bold>true</bold> +                   </font> +                  </property> +                  <property name="text"> +                   <string>Start</string> +                  </property> +                 </widget> +                </item> +                <item> +                 <widget class="QToolButton" name="btnStopTracker"> +                  <property name="enabled"> +                   <bool>false</bool> +                  </property> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="font"> +                   <font> +                    <weight>75</weight> +                    <bold>true</bold> +                   </font> +                  </property> +                  <property name="text"> +                   <string>Stop</string> +                  </property> +                 </widget> +                </item> +               </layout> +              </widget> +             </item> +            </layout> +           </widget> +          </item> +          <item row="0" column="0"> +           <widget class="QFrame" name="frame_2"> +            <property name="sizePolicy"> +             <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +              <horstretch>4</horstretch> +              <verstretch>0</verstretch> +             </sizepolicy> +            </property> +            <property name="frameShape"> +             <enum>QFrame::NoFrame</enum> +            </property> +            <property name="frameShadow"> +             <enum>QFrame::Raised</enum> +            </property> +            <layout class="QVBoxLayout" name="verticalLayout"> +             <property name="spacing"> +              <number>2</number> +             </property> +             <property name="leftMargin"> +              <number>3</number> +             </property> +             <property name="topMargin"> +              <number>2</number> +             </property> +             <property name="rightMargin"> +              <number>3</number> +             </property> +             <property name="bottomMargin"> +              <number>8</number> +             </property> +             <item> +              <widget class="QGroupBox" name="groupTrackerSource"> +               <property name="title"> +                <string>Input</string> +               </property> +               <layout class="QGridLayout" name="gridLayout"> +                <property name="leftMargin"> +                 <number>4</number> +                </property> +                <property name="topMargin"> +                 <number>0</number> +                </property> +                <property name="rightMargin"> +                 <number>0</number> +                </property> +                <property name="bottomMargin"> +                 <number>0</number> +                </property> +                <property name="horizontalSpacing"> +                 <number>3</number> +                </property> +                <property name="verticalSpacing"> +                 <number>0</number> +                </property> +                <item row="0" column="0"> +                 <widget class="QComboBox" name="iconcomboTrackerSource"> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::TabFocus</enum> +                  </property> +                 </widget> +                </item> +                <item row="0" column="1"> +                 <widget class="QToolButton" name="btnShowEngineControls"> +                  <property name="enabled"> +                   <bool>true</bool> +                  </property> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="font"> +                   <font> +                    <family>DejaVu Sans</family> +                    <stylestrategy>PreferAntialias</stylestrategy> +                    <kerning>false</kerning> +                   </font> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::ClickFocus</enum> +                  </property> +                  <property name="text"> +                   <string>🔨</string> +                  </property> +                  <property name="flat" stdset="0"> +                   <bool>false</bool> +                  </property> +                 </widget> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <widget class="QGroupBox" name="groupGameProtocol"> +               <property name="title"> +                <string>Output</string> +               </property> +               <layout class="QGridLayout" name="gridLayout_4"> +                <property name="leftMargin"> +                 <number>4</number> +                </property> +                <property name="topMargin"> +                 <number>0</number> +                </property> +                <property name="rightMargin"> +                 <number>0</number> +                </property> +                <property name="bottomMargin"> +                 <number>0</number> +                </property> +                <property name="horizontalSpacing"> +                 <number>3</number> +                </property> +                <property name="verticalSpacing"> +                 <number>0</number> +                </property> +                <item row="0" column="0"> +                 <widget class="QComboBox" name="iconcomboProtocol"> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::TabFocus</enum> +                  </property> +                 </widget> +                </item> +                <item row="0" column="1"> +                 <widget class="QToolButton" name="btnShowServerControls"> +                  <property name="enabled"> +                   <bool>true</bool> +                  </property> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="font"> +                   <font> +                    <family>DejaVu Sans</family> +                    <stylestrategy>PreferAntialias</stylestrategy> +                    <kerning>false</kerning> +                   </font> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::ClickFocus</enum> +                  </property> +                  <property name="text"> +                   <string>🔨</string> +                  </property> +                  <property name="flat" stdset="0"> +                   <bool>false</bool> +                  </property> +                 </widget> +                </item> +               </layout> +              </widget> +             </item> +             <item> +              <widget class="QGroupBox" name="groupFilter"> +               <property name="title"> +                <string>Filter</string> +               </property> +               <layout class="QGridLayout" name="gridLayout_3"> +                <property name="leftMargin"> +                 <number>4</number> +                </property> +                <property name="topMargin"> +                 <number>0</number> +                </property> +                <property name="rightMargin"> +                 <number>0</number> +                </property> +                <property name="bottomMargin"> +                 <number>0</number> +                </property> +                <property name="horizontalSpacing"> +                 <number>3</number> +                </property> +                <property name="verticalSpacing"> +                 <number>0</number> +                </property> +                <item row="0" column="0"> +                 <widget class="QComboBox" name="iconcomboFilter"> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Minimum" vsizetype="Maximum"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::TabFocus</enum> +                  </property> +                 </widget> +                </item> +                <item row="0" column="1"> +                 <widget class="QToolButton" name="btnShowFilterControls"> +                  <property name="enabled"> +                   <bool>true</bool> +                  </property> +                  <property name="sizePolicy"> +                   <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> +                    <horstretch>0</horstretch> +                    <verstretch>0</verstretch> +                   </sizepolicy> +                  </property> +                  <property name="font"> +                   <font> +                    <family>DejaVu Sans</family> +                    <stylestrategy>PreferAntialias</stylestrategy> +                    <kerning>false</kerning> +                   </font> +                  </property> +                  <property name="focusPolicy"> +                   <enum>Qt::ClickFocus</enum> +                  </property> +                  <property name="text"> +                   <string>🔨</string> +                  </property> +                  <property name="flat" stdset="0"> +                   <bool>false</bool> +                  </property> +                 </widget> +                </item> +               </layout> +              </widget> +             </item> +            </layout> +           </widget> +          </item> +         </layout> +        </widget> +       </item> +      </layout> +     </widget> +    </item> +   </layout> +  </widget> + </widget> + <customwidgets> +  <customwidget> +   <class>pose_widget</class> +   <extends>QWidget</extends> +   <header>pose-widget/pose-widget.hpp</header> +  </customwidget> + </customwidgets> + <tabstops> +  <tabstop>btnStartTracker</tabstop> +  <tabstop>btnStopTracker</tabstop> +  <tabstop>profile_button</tabstop> +  <tabstop>iconcomboProfile</tabstop> +  <tabstop>btnShortcuts</tabstop> +  <tabstop>btnEditCurves</tabstop> + </tabstops> + <resources> +  <include location="opentrack-res.qrc"/> + </resources> + <connections/> +</ui> diff --git a/variant/default/main.cpp b/variant/default/main.cpp index e539c635..3ee93422 100644 --- a/variant/default/main.cpp +++ b/variant/default/main.cpp @@ -1,5 +1,5 @@  #include "gui/init.hpp" -#include "gui/main-window.hpp" +#include "main-window.hpp"  #if defined _WIN32  #   include <windows.h> diff --git a/variant/default/new_config.ui b/variant/default/new_config.ui new file mode 100644 index 00000000..27dce0f8 --- /dev/null +++ b/variant/default/new_config.ui @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>UI_new_config</class> + <widget class="QDialog" name="UI_new_config"> +  <property name="windowModality"> +   <enum>Qt::ApplicationModal</enum> +  </property> +  <property name="geometry"> +   <rect> +    <x>0</x> +    <y>0</y> +    <width>269</width> +    <height>67</height> +   </rect> +  </property> +  <property name="windowTitle"> +   <string>Config filename</string> +  </property> +  <property name="windowIcon"> +   <iconset> +    <normaloff>images/facetracknoir.png</normaloff>images/facetracknoir.png</iconset> +  </property> +  <layout class="QFormLayout" name="formLayout"> +   <item row="0" column="0"> +    <widget class="QLabel" name="label"> +     <property name="text"> +      <string>New file name:</string> +     </property> +    </widget> +   </item> +   <item row="0" column="1"> +    <widget class="QLineEdit" name="lineEdit"/> +   </item> +   <item row="1" column="1"> +    <widget class="QDialogButtonBox" name="buttonBox"> +     <property name="standardButtons"> +      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> +     </property> +    </widget> +   </item> +  </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/variant/default/new_file_dialog.cpp b/variant/default/new_file_dialog.cpp new file mode 100644 index 00000000..831fe63e --- /dev/null +++ b/variant/default/new_file_dialog.cpp @@ -0,0 +1,39 @@ +#pragma once + +#include "new_file_dialog.h" + +new_file_dialog::new_file_dialog(QWidget* parent) : QDialog(parent) +{ +    ui.setupUi(this); +    connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(ok_clicked())); +    connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(cancel_clicked())); +    setFixedSize(size()); +} + +bool new_file_dialog::is_ok(QString& name_) +{ +    name_ = name; +    return ok; +} + +void new_file_dialog::cancel_clicked() { close(); } + +void new_file_dialog::ok_clicked() +{ +    QString text = ui.lineEdit->text(); +    text = text.replace('/', ""); +    text = text.replace('\\', ""); +    if (text != "" && !text.endsWith(".ini")) +        text += ".ini"; +    if (text == "" || text == ".ini" || QFile(options::group::ini_directory() + "/" + text).exists()) +    { +        QMessageBox::warning(this, +                             tr("File exists"), +                             tr("This file already exists. Pick another name."), +                             QMessageBox::Ok, QMessageBox::NoButton); +        return; +    } +    ok = true; +    close(); +    name = text; +} diff --git a/variant/default/new_file_dialog.h b/variant/default/new_file_dialog.h new file mode 100644 index 00000000..5669e4a9 --- /dev/null +++ b/variant/default/new_file_dialog.h @@ -0,0 +1,25 @@ +#pragma once + +#include "ui_new_config.h" +#include "options/options.hpp" +#include <QFile> +#include <QRegExp> +#include <QString> +#include <QMessageBox> + +class new_file_dialog : public QDialog +{ +    Q_OBJECT +public: +    new_file_dialog(QWidget* parent = 0); +    bool is_ok(QString& name_); + +private: +    Ui::UI_new_config ui; +    bool ok = false; +    QString name; + +private slots: +    void cancel_clicked(); +    void ok_clicked(); +}; | 
