|
| 1 | +/* |
| 2 | +Joypad to OBS |
| 3 | +Copyright (C) 2026 FabioZumbi12 <admin@areaz12server.net.br> |
| 4 | +
|
| 5 | +This program is free software; you can redistribute it and/or modify |
| 6 | +it under the terms of the GNU General Public License as published by |
| 7 | +the Free Software Foundation; either version 2 of the License, or |
| 8 | +(at your option) any later version. |
| 9 | +
|
| 10 | +This program is distributed in the hope that it will be useful, |
| 11 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 | +GNU General Public License for more details. |
| 14 | +
|
| 15 | +You should have received a copy of the GNU General Public License along |
| 16 | +with this program. If not, see <https://www.gnu.org/licenses/> |
| 17 | +*/ |
| 18 | + |
| 19 | +#include "joypad-dock.h" |
| 20 | +#include "joypad-ui.h" |
| 21 | + |
| 22 | +#include <obs-module.h> |
| 23 | + |
| 24 | +#include <QComboBox> |
| 25 | +#include <QLabel> |
| 26 | +#include <QPushButton> |
| 27 | +#include <QSignalBlocker> |
| 28 | +#include <QSizePolicy> |
| 29 | +#include <QStyle> |
| 30 | +#include <QTimer> |
| 31 | +#include <QHBoxLayout> |
| 32 | +#include <QVBoxLayout> |
| 33 | +#include <QWidget> |
| 34 | + |
| 35 | +namespace { |
| 36 | +inline QString L(const char *key) |
| 37 | +{ |
| 38 | + return QString::fromUtf8(obs_module_text(key)); |
| 39 | +} |
| 40 | +} // namespace |
| 41 | + |
| 42 | +JoypadControlDock::JoypadControlDock(QWidget *parent, JoypadConfigStore *config) : QDockWidget(parent), config_(config) |
| 43 | +{ |
| 44 | + setObjectName(QStringLiteral("joypad_to_obs_dock")); |
| 45 | + setWindowTitle(L("JoypadToOBS.Dock.Title")); |
| 46 | + |
| 47 | + auto *content = new QWidget(this); |
| 48 | + auto *layout = new QVBoxLayout(content); |
| 49 | + layout->setContentsMargins(6, 6, 6, 6); |
| 50 | + layout->setSpacing(6); |
| 51 | + layout->setAlignment(Qt::AlignTop); |
| 52 | + |
| 53 | + auto *profile_row = new QHBoxLayout(); |
| 54 | + profile_row->setContentsMargins(0, 0, 0, 0); |
| 55 | + profile_row->setSpacing(6); |
| 56 | + profile_row->addWidget(new QLabel(L("JoypadToOBS.Profile.Name"), content), 0); |
| 57 | + |
| 58 | + profile_combo_ = new QComboBox(content); |
| 59 | + profile_combo_->setMinimumContentsLength(12); |
| 60 | + profile_combo_->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon); |
| 61 | + profile_combo_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); |
| 62 | + profile_row->addWidget(profile_combo_, 2); |
| 63 | + |
| 64 | + input_toggle_button_ = new QPushButton(content); |
| 65 | + input_toggle_button_->setCheckable(true); |
| 66 | + input_toggle_button_->setText(QString()); |
| 67 | + input_toggle_button_->setFixedWidth(34); |
| 68 | + input_toggle_button_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); |
| 69 | + profile_row->addWidget(input_toggle_button_, 0); |
| 70 | + |
| 71 | + layout->addLayout(profile_row); |
| 72 | + setWidget(content); |
| 73 | + |
| 74 | + connect(profile_combo_, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) { |
| 75 | + if (!config_) { |
| 76 | + return; |
| 77 | + } |
| 78 | + config_->SetCurrentProfile(index); |
| 79 | + RefreshState(); |
| 80 | + }); |
| 81 | + connect(input_toggle_button_, &QPushButton::toggled, this, |
| 82 | + [](bool enabled) { JoypadUiSetInputListeningEnabled(enabled); }); |
| 83 | + |
| 84 | + update_timer_ = new QTimer(this); |
| 85 | + connect(update_timer_, &QTimer::timeout, this, [this]() { RefreshState(); }); |
| 86 | + update_timer_->start(200); |
| 87 | + |
| 88 | + RefreshState(); |
| 89 | +} |
| 90 | + |
| 91 | +void JoypadControlDock::RefreshState() |
| 92 | +{ |
| 93 | + RefreshProfiles(); |
| 94 | + if (!input_toggle_button_) { |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + const bool enabled = JoypadUiIsInputListeningEnabled(); |
| 99 | + if (input_toggle_button_->isChecked() != enabled) { |
| 100 | + const QSignalBlocker blocker(input_toggle_button_); |
| 101 | + input_toggle_button_->setChecked(enabled); |
| 102 | + } |
| 103 | + const QString status = enabled ? L("JoypadToOBS.Common.On") : L("JoypadToOBS.Common.Off"); |
| 104 | + const QStyle::StandardPixmap icon_type = enabled ? QStyle::SP_DialogApplyButton : QStyle::SP_DialogCancelButton; |
| 105 | + input_toggle_button_->setIcon(style()->standardIcon(icon_type)); |
| 106 | + input_toggle_button_->setToolTip(L("JoypadToOBS.Dock.ListeningButton").arg(status)); |
| 107 | +} |
| 108 | + |
| 109 | +void JoypadControlDock::RefreshProfiles() |
| 110 | +{ |
| 111 | + if (!config_ || !profile_combo_) { |
| 112 | + return; |
| 113 | + } |
| 114 | + |
| 115 | + const auto names = config_->GetProfileNames(); |
| 116 | + bool needs_rebuild = profile_combo_->count() != (int)names.size(); |
| 117 | + if (!needs_rebuild) { |
| 118 | + for (int i = 0; i < profile_combo_->count(); ++i) { |
| 119 | + if (profile_combo_->itemData(i).toString() != QString::fromStdString(names[(size_t)i])) { |
| 120 | + needs_rebuild = true; |
| 121 | + break; |
| 122 | + } |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + if (needs_rebuild) { |
| 127 | + const QSignalBlocker blocker(profile_combo_); |
| 128 | + profile_combo_->clear(); |
| 129 | + for (const auto &name : names) { |
| 130 | + const QString q_name = QString::fromStdString(name); |
| 131 | + profile_combo_->addItem(q_name, q_name); |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + const int current = config_->GetCurrentProfileIndex(); |
| 136 | + if (current >= 0 && current < profile_combo_->count() && profile_combo_->currentIndex() != current) { |
| 137 | + const QSignalBlocker blocker(profile_combo_); |
| 138 | + profile_combo_->setCurrentIndex(current); |
| 139 | + } |
| 140 | +} |
0 commit comments