UI: Add Hotkey filter search and duplicate detection
This commit is contained in:
parent
16906e7290
commit
0c1524b53c
@ -1051,6 +1051,8 @@ Basic.AdvAudio.AudioTracks="Tracks"
|
||||
Basic.Settings.Hotkeys="Hotkeys"
|
||||
Basic.Settings.Hotkeys.Pair="Key combinations shared with '%1' act as toggles"
|
||||
Basic.Settings.Hotkeys.Filter="Filter"
|
||||
Basic.Settings.Hotkeys.FilterByHotkey="Filter by Hotkey"
|
||||
Basic.Settings.Hotkeys.DuplicateWarning="This hotkey is shared by one or more other actions, click to show conflicts"
|
||||
|
||||
# basic mode hotkeys
|
||||
Basic.Hotkeys.SelectScene="Switch to scene"
|
||||
|
1
UI/forms/images/warning.svg
Normal file
1
UI/forms/images/warning.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#eed202" fill-rule="evenodd" d="m12.89267,5.4995c-0.183,-0.31 -0.52,-0.5 -0.887,-0.5s-0.703,0.19 -0.886,0.5l-6.982,11.999a0.98,0.98 0 0 0 0,1.001c0.193,0.31 0.53,0.501 0.886,0.501l13.964,0c0.367,0 0.704,-0.19 0.877,-0.5a1.03,1.03 0 0 0 0.01,-1.002l-6.982,-11.999zm0.133,11.497l-2.039,0l0,-2.003l2.039,0l0,2.003zm0,-3.004l-2.039,0l0,-4.006l2.039,0l0,4.006z"/></svg>
|
After Width: | Height: | Size: 436 B |
@ -27,6 +27,7 @@
|
||||
<file>images/trash.svg</file>
|
||||
<file>images/revert.svg</file>
|
||||
<file>images/alert.svg</file>
|
||||
<file>images/warning.svg</file>
|
||||
<file>images/sources/brush.svg</file>
|
||||
<file>images/sources/camera.svg</file>
|
||||
<file>images/sources/gamepad.svg</file>
|
||||
|
@ -15,27 +15,17 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
******************************************************************************/
|
||||
|
||||
#include "window-basic-settings.hpp"
|
||||
#include "hotkey-edit.hpp"
|
||||
|
||||
#include <util/dstr.hpp>
|
||||
#include <QPointer>
|
||||
#include <QStyle>
|
||||
#include <QAction>
|
||||
|
||||
#include "obs-app.hpp"
|
||||
#include "qt-wrappers.hpp"
|
||||
|
||||
static inline bool operator!=(const obs_key_combination_t &c1,
|
||||
const obs_key_combination_t &c2)
|
||||
{
|
||||
return c1.modifiers != c2.modifiers || c1.key != c2.key;
|
||||
}
|
||||
|
||||
static inline bool operator==(const obs_key_combination_t &c1,
|
||||
const obs_key_combination_t &c2)
|
||||
{
|
||||
return !(c1 != c2);
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->isAutoRepeat())
|
||||
@ -183,6 +173,14 @@ void OBSHotkeyEdit::ClearKey()
|
||||
RenderKey();
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::UpdateDuplicationState()
|
||||
{
|
||||
if (dupeIcon->isVisible() != hasDuplicate) {
|
||||
dupeIcon->setVisible(hasDuplicate);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::InitSignalHandler()
|
||||
{
|
||||
layoutChanged = {
|
||||
@ -194,6 +192,16 @@ void OBSHotkeyEdit::InitSignalHandler()
|
||||
this};
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::CreateDupeIcon()
|
||||
{
|
||||
dupeIcon = this->addAction(settings->GetHotkeyConflictIcon(),
|
||||
ActionPosition::TrailingPosition);
|
||||
dupeIcon->setToolTip(QTStr("Basic.Settings.Hotkeys.DuplicateWarning"));
|
||||
QObject::connect(dupeIcon, &QAction::triggered,
|
||||
[=] { emit SearchKey(key); });
|
||||
dupeIcon->setVisible(false);
|
||||
}
|
||||
|
||||
void OBSHotkeyEdit::ReloadKeyLayout()
|
||||
{
|
||||
RenderKey();
|
||||
@ -266,7 +274,7 @@ void OBSHotkeyWidget::Save(std::vector<obs_key_combination_t> &combinations)
|
||||
|
||||
void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
||||
{
|
||||
auto edit = new OBSHotkeyEdit(combo);
|
||||
auto edit = new OBSHotkeyEdit(combo, settings);
|
||||
edit->setToolTip(toolTip);
|
||||
|
||||
auto revert = new QPushButton;
|
||||
@ -347,6 +355,10 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
|
||||
|
||||
QObject::connect(edit, &OBSHotkeyEdit::KeyChanged,
|
||||
[&](obs_key_combination) { emit KeyChanged(); });
|
||||
QObject::connect(edit, &OBSHotkeyEdit::SearchKey,
|
||||
[=](obs_key_combination combo) {
|
||||
emit SearchKey(combo);
|
||||
});
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::RemoveEdit(size_t idx, bool signal)
|
||||
@ -354,7 +366,6 @@ void OBSHotkeyWidget::RemoveEdit(size_t idx, bool signal)
|
||||
auto &edit = *(begin(edits) + idx);
|
||||
if (!obs_key_combination_is_empty(edit->original) && signal) {
|
||||
changed = true;
|
||||
emit KeyChanged();
|
||||
}
|
||||
|
||||
revertButtons.erase(begin(revertButtons) + idx);
|
||||
@ -371,6 +382,8 @@ void OBSHotkeyWidget::RemoveEdit(size_t idx, bool signal)
|
||||
|
||||
if (removeButtons.size() == 1)
|
||||
removeButtons.front()->setEnabled(false);
|
||||
|
||||
emit KeyChanged();
|
||||
}
|
||||
|
||||
void OBSHotkeyWidget::BindingsChanged(void *data, calldata_t *param)
|
||||
@ -458,6 +471,7 @@ void OBSHotkeyLabel::enterEvent(QEnterEvent *event)
|
||||
void OBSHotkeyLabel::enterEvent(QEvent *event)
|
||||
#endif
|
||||
{
|
||||
|
||||
if (!pairPartner)
|
||||
return;
|
||||
|
||||
|
@ -27,6 +27,19 @@
|
||||
|
||||
#include <obs.hpp>
|
||||
|
||||
static inline bool operator!=(const obs_key_combination_t &c1,
|
||||
const obs_key_combination_t &c2)
|
||||
{
|
||||
return c1.modifiers != c2.modifiers || c1.key != c2.key;
|
||||
}
|
||||
|
||||
static inline bool operator==(const obs_key_combination_t &c1,
|
||||
const obs_key_combination_t &c2)
|
||||
{
|
||||
return !(c1 != c2);
|
||||
}
|
||||
|
||||
class OBSBasicSettings;
|
||||
class OBSHotkeyWidget;
|
||||
|
||||
class OBSHotkeyLabel : public QLabel {
|
||||
@ -49,8 +62,9 @@ class OBSHotkeyEdit : public QLineEdit {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
OBSHotkeyEdit(obs_key_combination_t original, QWidget *parent = nullptr)
|
||||
: QLineEdit(parent), original(original)
|
||||
OBSHotkeyEdit(obs_key_combination_t original,
|
||||
OBSBasicSettings *settings)
|
||||
: QLineEdit(nullptr), original(original), settings(settings)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// disable the input cursor on OSX, focus should be clear
|
||||
@ -60,17 +74,24 @@ public:
|
||||
setAttribute(Qt::WA_InputMethodEnabled, false);
|
||||
setAttribute(Qt::WA_MacShowFocusRect, true);
|
||||
InitSignalHandler();
|
||||
CreateDupeIcon();
|
||||
ResetKey();
|
||||
}
|
||||
|
||||
obs_key_combination_t original;
|
||||
obs_key_combination_t key;
|
||||
OBSBasicSettings *settings;
|
||||
bool changed = false;
|
||||
|
||||
void UpdateDuplicationState();
|
||||
bool hasDuplicate = false;
|
||||
|
||||
protected:
|
||||
OBSSignal layoutChanged;
|
||||
QAction *dupeIcon;
|
||||
|
||||
void InitSignalHandler();
|
||||
void CreateDupeIcon();
|
||||
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
#ifdef __APPLE__
|
||||
@ -78,16 +99,17 @@ protected:
|
||||
#endif
|
||||
void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
void HandleNewKey(obs_key_combination_t new_key);
|
||||
void RenderKey();
|
||||
|
||||
public slots:
|
||||
void HandleNewKey(obs_key_combination_t new_key);
|
||||
void ReloadKeyLayout();
|
||||
void ResetKey();
|
||||
void ClearKey();
|
||||
|
||||
signals:
|
||||
void KeyChanged(obs_key_combination_t);
|
||||
void SearchKey(obs_key_combination_t);
|
||||
};
|
||||
|
||||
class OBSHotkeyWidget : public QWidget {
|
||||
@ -95,14 +117,15 @@ class OBSHotkeyWidget : public QWidget {
|
||||
|
||||
public:
|
||||
OBSHotkeyWidget(obs_hotkey_id id, std::string name,
|
||||
const std::vector<obs_key_combination_t> &combos = {},
|
||||
QWidget *parent = nullptr)
|
||||
: QWidget(parent),
|
||||
OBSBasicSettings *settings,
|
||||
const std::vector<obs_key_combination_t> &combos = {})
|
||||
: QWidget(nullptr),
|
||||
id(id),
|
||||
name(name),
|
||||
bindingsChanged(obs_get_signal_handler(),
|
||||
"hotkey_bindings_changed",
|
||||
&OBSHotkeyWidget::BindingsChanged, this)
|
||||
&OBSHotkeyWidget::BindingsChanged, this),
|
||||
settings(settings)
|
||||
{
|
||||
auto layout = new QVBoxLayout;
|
||||
layout->setSpacing(0);
|
||||
@ -121,6 +144,7 @@ public:
|
||||
bool Changed() const;
|
||||
|
||||
QPointer<OBSHotkeyLabel> label;
|
||||
std::vector<QPointer<OBSHotkeyEdit>> edits;
|
||||
|
||||
QString toolTip;
|
||||
void setToolTip(const QString &toolTip_)
|
||||
@ -148,11 +172,11 @@ private:
|
||||
|
||||
static void BindingsChanged(void *data, calldata_t *param);
|
||||
|
||||
std::vector<QPointer<OBSHotkeyEdit>> edits;
|
||||
std::vector<QPointer<QPushButton>> removeButtons;
|
||||
std::vector<QPointer<QPushButton>> revertButtons;
|
||||
OBSSignal bindingsChanged;
|
||||
bool ignoreChangedBindings = false;
|
||||
OBSBasicSettings *settings;
|
||||
|
||||
QVBoxLayout *layout() const
|
||||
{
|
||||
@ -164,4 +188,5 @@ private slots:
|
||||
|
||||
signals:
|
||||
void KeyChanged();
|
||||
void SearchKey(obs_key_combination_t);
|
||||
};
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "window-projector.hpp"
|
||||
|
||||
#include <util/platform.h>
|
||||
#include <util/dstr.hpp>
|
||||
#include "ui-config.h"
|
||||
|
||||
#define ENCODER_HIDE_FLAGS \
|
||||
@ -713,6 +714,9 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
|
||||
channelChanged.Connect(obs_get_signal_handler(), "channel_change",
|
||||
ReloadAudioSources, this);
|
||||
|
||||
hotkeyConflictIcon =
|
||||
QIcon::fromTheme("obs", QIcon(":/res/images/warning.svg"));
|
||||
|
||||
auto ReloadHotkeys = [](void *data, calldata_t *) {
|
||||
auto settings = static_cast<OBSBasicSettings *>(data);
|
||||
QMetaObject::invokeMethod(settings, "ReloadHotkeys");
|
||||
@ -2600,7 +2604,8 @@ void OBSBasicSettings::LoadAdvancedSettings()
|
||||
|
||||
template<typename Func>
|
||||
static inline void
|
||||
LayoutHotkey(obs_hotkey_id id, obs_hotkey_t *key, Func &&fun,
|
||||
LayoutHotkey(OBSBasicSettings *settings, obs_hotkey_id id, obs_hotkey_t *key,
|
||||
Func &&fun,
|
||||
const map<obs_hotkey_id, vector<obs_key_combination_t>> &keys)
|
||||
{
|
||||
auto *label = new OBSHotkeyLabel;
|
||||
@ -2619,9 +2624,10 @@ LayoutHotkey(obs_hotkey_id id, obs_hotkey_t *key, Func &&fun,
|
||||
|
||||
auto combos = keys.find(id);
|
||||
if (combos == std::end(keys))
|
||||
hw = new OBSHotkeyWidget(id, obs_hotkey_get_name(key));
|
||||
else
|
||||
hw = new OBSHotkeyWidget(id, obs_hotkey_get_name(key),
|
||||
settings);
|
||||
else
|
||||
hw = new OBSHotkeyWidget(id, obs_hotkey_get_name(key), settings,
|
||||
combos->second);
|
||||
|
||||
hw->label = label;
|
||||
@ -2715,58 +2721,104 @@ void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
},
|
||||
&keys);
|
||||
|
||||
auto layout = new QFormLayout();
|
||||
layout->setVerticalSpacing(0);
|
||||
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||
layout->setLabelAlignment(Qt::AlignRight | Qt::AlignTrailing |
|
||||
Qt::AlignVCenter);
|
||||
auto layout = new QVBoxLayout();
|
||||
ui->hotkeyPage->setLayout(layout);
|
||||
|
||||
auto widget = new QWidget();
|
||||
widget->setLayout(layout);
|
||||
ui->hotkeyPage->setWidget(widget);
|
||||
auto scrollArea = new QScrollArea();
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setWidget(widget);
|
||||
|
||||
auto hotkeysLayout = new QFormLayout();
|
||||
hotkeysLayout->setVerticalSpacing(0);
|
||||
hotkeysLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
|
||||
hotkeysLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignTrailing |
|
||||
Qt::AlignVCenter);
|
||||
widget->setLayout(hotkeysLayout);
|
||||
|
||||
auto filterLayout = new QGridLayout();
|
||||
auto filterWidget = new QWidget();
|
||||
filterWidget->setLayout(filterLayout);
|
||||
|
||||
auto filterLabel = new QLabel(QTStr("Basic.Settings.Hotkeys.Filter"));
|
||||
auto filter = new QLineEdit();
|
||||
auto filterHotkeyLabel =
|
||||
new QLabel(QTStr("Basic.Settings.Hotkeys.FilterByHotkey"));
|
||||
auto filterHotkeyInput = new OBSHotkeyEdit({}, this);
|
||||
auto filterReset = new QPushButton;
|
||||
filterReset->setProperty("themeID", "trashIcon");
|
||||
filterReset->setToolTip(QTStr("Clear"));
|
||||
filterReset->setFixedSize(24, 24);
|
||||
filterReset->setFlat(true);
|
||||
|
||||
auto setRowVisible = [=](int row, bool visible, QLayoutItem *label) {
|
||||
label->widget()->setVisible(visible);
|
||||
|
||||
auto field = layout->itemAt(row, QFormLayout::FieldRole);
|
||||
auto field = hotkeysLayout->itemAt(row, QFormLayout::FieldRole);
|
||||
if (field)
|
||||
field->widget()->setVisible(visible);
|
||||
};
|
||||
|
||||
auto searchFunction = [=](const QString &text) {
|
||||
for (int i = 0; i < layout->rowCount(); i++) {
|
||||
auto label = layout->itemAt(i, QFormLayout::LabelRole);
|
||||
if (label) {
|
||||
OBSHotkeyLabel *item =
|
||||
qobject_cast<OBSHotkeyLabel *>(
|
||||
label->widget());
|
||||
if (item) {
|
||||
QString fullname =
|
||||
item->property("fullName")
|
||||
.value<QString>();
|
||||
if (fullname.toLower().contains(
|
||||
text.toLower()))
|
||||
setRowVisible(i, true, label);
|
||||
else
|
||||
setRowVisible(i, false, label);
|
||||
auto searchFunction = [=](const QString &text,
|
||||
obs_key_combination_t filterCombo) {
|
||||
std::vector<obs_key_combination_t> combos;
|
||||
bool showHotkey;
|
||||
scrollArea->ensureVisible(0, 0);
|
||||
scrollArea->setUpdatesEnabled(false);
|
||||
|
||||
for (int i = 0; i < hotkeysLayout->rowCount(); i++) {
|
||||
auto label = hotkeysLayout->itemAt(
|
||||
i, QFormLayout::LabelRole);
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
OBSHotkeyLabel *item =
|
||||
qobject_cast<OBSHotkeyLabel *>(label->widget());
|
||||
if (!item)
|
||||
continue;
|
||||
|
||||
item->widget->GetCombinations(combos);
|
||||
QString fullname =
|
||||
item->property("fullName").value<QString>();
|
||||
|
||||
showHotkey =
|
||||
text.isEmpty() ||
|
||||
fullname.toLower().contains(text.toLower());
|
||||
|
||||
if (showHotkey &&
|
||||
!obs_key_combination_is_empty(filterCombo)) {
|
||||
showHotkey = false;
|
||||
for (auto combo : combos) {
|
||||
if (combo == filterCombo) {
|
||||
showHotkey = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
setRowVisible(i, showHotkey, label);
|
||||
}
|
||||
scrollArea->setUpdatesEnabled(true);
|
||||
};
|
||||
|
||||
connect(filter, &QLineEdit::textChanged, this, searchFunction);
|
||||
connect(filter, &QLineEdit::textChanged, this, [=](const QString text) {
|
||||
searchFunction(text, filterHotkeyInput->key);
|
||||
});
|
||||
|
||||
connect(filterHotkeyInput, &OBSHotkeyEdit::KeyChanged, this,
|
||||
[=](obs_key_combination_t combo) {
|
||||
searchFunction(filter->text(), combo);
|
||||
});
|
||||
|
||||
connect(filterReset, &QPushButton::clicked, this, [=]() {
|
||||
filter->setText("");
|
||||
filterHotkeyInput->ResetKey();
|
||||
});
|
||||
|
||||
filterLayout->addWidget(filterLabel, 0, 0);
|
||||
filterLayout->addWidget(filter, 0, 1);
|
||||
filterLayout->addWidget(filterHotkeyLabel, 0, 2);
|
||||
filterLayout->addWidget(filterHotkeyInput, 0, 3);
|
||||
filterLayout->addWidget(filterReset, 0, 4);
|
||||
|
||||
layout->addRow(filterWidget);
|
||||
layout->addLayout(filterLayout);
|
||||
layout->addWidget(scrollArea);
|
||||
|
||||
using namespace std;
|
||||
using encoders_elem_t =
|
||||
@ -2858,7 +2910,7 @@ void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
|
||||
switch (registerer_type) {
|
||||
case OBS_HOTKEY_REGISTERER_FRONTEND:
|
||||
layout->addRow(label, hw);
|
||||
hotkeysLayout->addRow(label, hw);
|
||||
break;
|
||||
|
||||
case OBS_HOTKEY_REGISTERER_ENCODER:
|
||||
@ -2884,17 +2936,27 @@ void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
|
||||
hotkeys.emplace_back(
|
||||
registerer_type == OBS_HOTKEY_REGISTERER_FRONTEND, hw);
|
||||
connect(hw, &OBSHotkeyWidget::KeyChanged, this,
|
||||
&OBSBasicSettings::HotkeysChanged);
|
||||
connect(hw, &OBSHotkeyWidget::KeyChanged, this, [=]() {
|
||||
HotkeysChanged();
|
||||
ScanDuplicateHotkeys(hotkeysLayout);
|
||||
});
|
||||
connect(hw, &OBSHotkeyWidget::SearchKey,
|
||||
[=](obs_key_combination_t combo) {
|
||||
filter->setText("");
|
||||
filterHotkeyInput->HandleNewKey(combo);
|
||||
filterHotkeyInput->KeyChanged(combo);
|
||||
});
|
||||
};
|
||||
|
||||
auto data = make_tuple(RegisterHotkey, std::move(keys), ignoreKey);
|
||||
auto data =
|
||||
make_tuple(RegisterHotkey, std::move(keys), ignoreKey, this);
|
||||
using data_t = decltype(data);
|
||||
obs_enum_hotkeys(
|
||||
[](void *data, obs_hotkey_id id, obs_hotkey_t *key) {
|
||||
data_t &d = *static_cast<data_t *>(data);
|
||||
if (id != get<2>(d))
|
||||
LayoutHotkey(id, key, get<0>(d), get<1>(d));
|
||||
LayoutHotkey(get<3>(d), id, key, get<0>(d),
|
||||
get<1>(d));
|
||||
return true;
|
||||
},
|
||||
&data);
|
||||
@ -2937,11 +2999,13 @@ void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
Update(label2, name2, label1, name1);
|
||||
}
|
||||
|
||||
AddHotkeys(*layout, obs_output_get_name, outputs);
|
||||
AddHotkeys(*layout, obs_source_get_name, scenes);
|
||||
AddHotkeys(*layout, obs_source_get_name, sources);
|
||||
AddHotkeys(*layout, obs_encoder_get_name, encoders);
|
||||
AddHotkeys(*layout, obs_service_get_name, services);
|
||||
AddHotkeys(*hotkeysLayout, obs_output_get_name, outputs);
|
||||
AddHotkeys(*hotkeysLayout, obs_source_get_name, scenes);
|
||||
AddHotkeys(*hotkeysLayout, obs_source_get_name, sources);
|
||||
AddHotkeys(*hotkeysLayout, obs_encoder_get_name, encoders);
|
||||
AddHotkeys(*hotkeysLayout, obs_service_get_name, services);
|
||||
|
||||
ScanDuplicateHotkeys(hotkeysLayout);
|
||||
}
|
||||
|
||||
void OBSBasicSettings::LoadSettings(bool changedOnly)
|
||||
@ -4274,6 +4338,66 @@ void OBSBasicSettings::HotkeysChanged()
|
||||
EnableApplyButton(true);
|
||||
}
|
||||
|
||||
static bool MarkHotkeyConflicts(OBSHotkeyLabel *item1, OBSHotkeyLabel *item2)
|
||||
{
|
||||
if (item1->pairPartner == item2)
|
||||
return false;
|
||||
|
||||
auto &edits1 = item1->widget->edits;
|
||||
auto &edits2 = item2->widget->edits;
|
||||
bool hasDupes = false;
|
||||
|
||||
for (auto &edit1 : edits1) {
|
||||
for (auto &edit2 : edits2) {
|
||||
bool isDupe =
|
||||
!obs_key_combination_is_empty(edit1->key) &&
|
||||
edit1->key == edit2->key;
|
||||
|
||||
hasDupes |= isDupe;
|
||||
edit1->hasDuplicate |= isDupe;
|
||||
edit2->hasDuplicate |= isDupe;
|
||||
}
|
||||
}
|
||||
|
||||
return hasDupes;
|
||||
};
|
||||
|
||||
bool OBSBasicSettings::ScanDuplicateHotkeys(QFormLayout *layout)
|
||||
{
|
||||
vector<OBSHotkeyLabel *> items;
|
||||
bool hasDupes = false;
|
||||
|
||||
for (int i = 0; i < layout->rowCount(); i++) {
|
||||
auto label = layout->itemAt(i, QFormLayout::LabelRole);
|
||||
if (!label)
|
||||
continue;
|
||||
OBSHotkeyLabel *item =
|
||||
qobject_cast<OBSHotkeyLabel *>(label->widget());
|
||||
if (!item)
|
||||
continue;
|
||||
|
||||
items.push_back(item);
|
||||
|
||||
for (auto &edit : item->widget->edits)
|
||||
edit->hasDuplicate = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
OBSHotkeyLabel *item1 = items[i];
|
||||
|
||||
for (int j = i + 1; j < items.size(); j++)
|
||||
hasDupes |= MarkHotkeyConflicts(item1, items[j]);
|
||||
}
|
||||
|
||||
for (auto *item : items) {
|
||||
for (auto &edit : item->widget->edits) {
|
||||
edit->UpdateDuplicationState();
|
||||
}
|
||||
}
|
||||
|
||||
return hasDupes;
|
||||
}
|
||||
|
||||
void OBSBasicSettings::ReloadHotkeys(obs_hotkey_id ignoreKey)
|
||||
{
|
||||
LoadHotkeySettings(ignoreKey);
|
||||
|
@ -165,6 +165,8 @@ private:
|
||||
QPointer<QWidget> vodTrackContainer;
|
||||
QPointer<QRadioButton> vodTrack[MAX_AUDIO_MIXES];
|
||||
|
||||
QIcon hotkeyConflictIcon;
|
||||
|
||||
void SaveCombo(QComboBox *widget, const char *section,
|
||||
const char *value);
|
||||
void SaveComboData(QComboBox *widget, const char *section,
|
||||
@ -370,6 +372,7 @@ private slots:
|
||||
void VideoChangedResolution();
|
||||
void VideoChangedRestart();
|
||||
void HotkeysChanged();
|
||||
bool ScanDuplicateHotkeys(QFormLayout *layout);
|
||||
void ReloadHotkeys(obs_hotkey_id ignoreKey = OBS_INVALID_HOTKEY_ID);
|
||||
void AdvancedChanged();
|
||||
void AdvancedChangedRestart();
|
||||
@ -408,4 +411,9 @@ protected:
|
||||
public:
|
||||
OBSBasicSettings(QWidget *parent);
|
||||
~OBSBasicSettings();
|
||||
|
||||
inline const QIcon &GetHotkeyConflictIcon() const
|
||||
{
|
||||
return hotkeyConflictIcon;
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user