UI: Don't recreate entire Hotkey Settings tab
This replaces the programmatic generation of the hotkeys tab with XML. Also fixes a memory leak. Reuses concepts from LoadAudioSources().
This commit is contained in:
parent
a46f56a3e9
commit
e00195ad6f
@ -4690,31 +4690,87 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QScrollArea" name="hotkeyPage">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="hotkeyWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>98</width>
|
||||
<height>28</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="hotkeyLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="hotkeyPage">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_25">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="hotkeySearchLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="hotkeySearchLabel">
|
||||
<property name="text">
|
||||
<string>Basic.Settings.Hotkeys.Filter</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="hotkeyFilterSearch"/>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="hotkeyFilterLabel">
|
||||
<property name="text">
|
||||
<string>Basic.Settings.Hotkeys.FilterByHotkey</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="OBSHotkeyEdit" name="hotkeyFilterInput"/>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="hotkeyFilterReset">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>trashIcon</string>
|
||||
</property>
|
||||
<property name="fixedSize" stdset="0">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="hotkeyScrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="hotkeyScrollContents">
|
||||
<layout class="QFormLayout" name="hotkeyFormLayout">
|
||||
<property name="labelAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="verticalSpacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="advancedPage">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
@ -5572,6 +5628,11 @@
|
||||
<extends>QPushButton</extends>
|
||||
<header>url-push-button.hpp</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>OBSHotkeyEdit</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>hotkey-edit.hpp</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>listWidget</tabstop>
|
||||
|
@ -175,7 +175,7 @@ void OBSHotkeyEdit::ClearKey()
|
||||
|
||||
void OBSHotkeyEdit::UpdateDuplicationState()
|
||||
{
|
||||
if (dupeIcon->isVisible() != hasDuplicate) {
|
||||
if (dupeIcon && dupeIcon->isVisible() != hasDuplicate) {
|
||||
dupeIcon->setVisible(hasDuplicate);
|
||||
update();
|
||||
}
|
||||
@ -194,8 +194,8 @@ void OBSHotkeyEdit::InitSignalHandler()
|
||||
|
||||
void OBSHotkeyEdit::CreateDupeIcon()
|
||||
{
|
||||
dupeIcon = this->addAction(settings->GetHotkeyConflictIcon(),
|
||||
ActionPosition::TrailingPosition);
|
||||
dupeIcon = addAction(settings->GetHotkeyConflictIcon(),
|
||||
ActionPosition::TrailingPosition);
|
||||
dupeIcon->setToolTip(QTStr("Basic.Settings.Hotkeys.DuplicateWarning"));
|
||||
QObject::connect(dupeIcon, &QAction::triggered,
|
||||
[=] { emit SearchKey(key); });
|
||||
@ -274,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, settings);
|
||||
auto edit = new OBSHotkeyEdit(parentWidget(), combo, settings);
|
||||
edit->setToolTip(toolTip);
|
||||
|
||||
auto revert = new QPushButton;
|
||||
|
@ -62,9 +62,9 @@ class OBSHotkeyEdit : public QLineEdit {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
OBSHotkeyEdit(obs_key_combination_t original,
|
||||
OBSHotkeyEdit(QWidget *parent, obs_key_combination_t original,
|
||||
OBSBasicSettings *settings)
|
||||
: QLineEdit(nullptr), original(original), settings(settings)
|
||||
: QLineEdit(parent), original(original), settings(settings)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// disable the input cursor on OSX, focus should be clear
|
||||
@ -77,6 +77,19 @@ public:
|
||||
CreateDupeIcon();
|
||||
ResetKey();
|
||||
}
|
||||
OBSHotkeyEdit(QWidget *parent = nullptr)
|
||||
: QLineEdit(parent), original({}), settings(nullptr)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// disable the input cursor on OSX, focus should be clear
|
||||
// enough with the default focus frame
|
||||
setReadOnly(true);
|
||||
#endif
|
||||
setAttribute(Qt::WA_InputMethodEnabled, false);
|
||||
setAttribute(Qt::WA_MacShowFocusRect, true);
|
||||
InitSignalHandler();
|
||||
ResetKey();
|
||||
}
|
||||
|
||||
obs_key_combination_t original;
|
||||
obs_key_combination_t key;
|
||||
@ -116,10 +129,10 @@ class OBSHotkeyWidget : public QWidget {
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
OBSHotkeyWidget(obs_hotkey_id id, std::string name,
|
||||
OBSHotkeyWidget(QWidget *parent, obs_hotkey_id id, std::string name,
|
||||
OBSBasicSettings *settings,
|
||||
const std::vector<obs_key_combination_t> &combos = {})
|
||||
: QWidget(nullptr),
|
||||
: QWidget(parent),
|
||||
id(id),
|
||||
name(name),
|
||||
bindingsChanged(obs_get_signal_handler(),
|
||||
|
@ -2620,11 +2620,11 @@ LayoutHotkey(OBSBasicSettings *settings, obs_hotkey_id id, obs_hotkey_t *key,
|
||||
|
||||
auto combos = keys.find(id);
|
||||
if (combos == std::end(keys))
|
||||
hw = new OBSHotkeyWidget(id, obs_hotkey_get_name(key),
|
||||
hw = new OBSHotkeyWidget(settings, id, obs_hotkey_get_name(key),
|
||||
settings);
|
||||
else
|
||||
hw = new OBSHotkeyWidget(id, obs_hotkey_get_name(key), settings,
|
||||
combos->second);
|
||||
hw = new OBSHotkeyWidget(settings, id, obs_hotkey_get_name(key),
|
||||
settings, combos->second);
|
||||
|
||||
hw->label = label;
|
||||
label->widget = hw;
|
||||
@ -2700,7 +2700,17 @@ static inline void AddHotkeys(
|
||||
void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
{
|
||||
hotkeys.clear();
|
||||
ui->hotkeyPage->takeWidget()->deleteLater();
|
||||
if (ui->hotkeyFormLayout->rowCount() > 0) {
|
||||
QLayoutItem *forDeletion = ui->hotkeyFormLayout->takeAt(0);
|
||||
forDeletion->widget()->deleteLater();
|
||||
delete forDeletion;
|
||||
}
|
||||
ui->hotkeyFilterSearch->blockSignals(true);
|
||||
ui->hotkeyFilterInput->blockSignals(true);
|
||||
ui->hotkeyFilterSearch->setText("");
|
||||
ui->hotkeyFilterInput->ResetKey();
|
||||
ui->hotkeyFilterSearch->blockSignals(false);
|
||||
ui->hotkeyFilterInput->blockSignals(false);
|
||||
|
||||
using keys_t = map<obs_hotkey_id, vector<obs_key_combination_t>>;
|
||||
keys_t keys;
|
||||
@ -2717,104 +2727,14 @@ void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
},
|
||||
&keys);
|
||||
|
||||
auto layout = new QVBoxLayout();
|
||||
ui->hotkeyPage->setLayout(layout);
|
||||
|
||||
auto widget = new QWidget();
|
||||
auto scrollArea = new QScrollArea();
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setWidget(widget);
|
||||
|
||||
auto hotkeysLayout = new QFormLayout();
|
||||
QFormLayout *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 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 = hotkeysLayout->itemAt(row, QFormLayout::FieldRole);
|
||||
if (field)
|
||||
field->widget()->setVisible(visible);
|
||||
};
|
||||
|
||||
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, [=](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->addLayout(filterLayout);
|
||||
layout->addWidget(scrollArea);
|
||||
auto hotkeyChildWidget = new QWidget();
|
||||
hotkeyChildWidget->setLayout(hotkeysLayout);
|
||||
ui->hotkeyFormLayout->addRow(hotkeyChildWidget);
|
||||
|
||||
using namespace std;
|
||||
using encoders_elem_t =
|
||||
@ -2938,9 +2858,9 @@ void OBSBasicSettings::LoadHotkeySettings(obs_hotkey_id ignoreKey)
|
||||
});
|
||||
connect(hw, &OBSHotkeyWidget::SearchKey,
|
||||
[=](obs_key_combination_t combo) {
|
||||
filter->setText("");
|
||||
filterHotkeyInput->HandleNewKey(combo);
|
||||
filterHotkeyInput->KeyChanged(combo);
|
||||
ui->hotkeyFilterSearch->setText("");
|
||||
ui->hotkeyFilterInput->HandleNewKey(combo);
|
||||
ui->hotkeyFilterInput->KeyChanged(combo);
|
||||
});
|
||||
};
|
||||
|
||||
@ -4343,6 +4263,78 @@ void OBSBasicSettings::HotkeysChanged()
|
||||
EnableApplyButton(true);
|
||||
}
|
||||
|
||||
void OBSBasicSettings::SearchHotkeys(const QString &text,
|
||||
obs_key_combination_t filterCombo)
|
||||
{
|
||||
|
||||
if (ui->hotkeyFormLayout->rowCount() == 0)
|
||||
return;
|
||||
|
||||
std::vector<obs_key_combination_t> combos;
|
||||
bool showHotkey;
|
||||
ui->hotkeyScrollArea->ensureVisible(0, 0);
|
||||
ui->hotkeyScrollArea->setUpdatesEnabled(false);
|
||||
|
||||
QLayoutItem *hotkeysItem = ui->hotkeyFormLayout->itemAt(0);
|
||||
QWidget *hotkeys = hotkeysItem->widget();
|
||||
if (!hotkeys)
|
||||
return;
|
||||
|
||||
QFormLayout *hotkeysLayout =
|
||||
qobject_cast<QFormLayout *>(hotkeys->layout());
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label->widget()->setVisible(showHotkey);
|
||||
|
||||
auto field = hotkeysLayout->itemAt(i, QFormLayout::FieldRole);
|
||||
if (field)
|
||||
field->widget()->setVisible(showHotkey);
|
||||
}
|
||||
ui->hotkeyScrollArea->setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void OBSBasicSettings::on_hotkeyFilterReset_clicked()
|
||||
{
|
||||
ui->hotkeyFilterSearch->setText("");
|
||||
ui->hotkeyFilterInput->ResetKey();
|
||||
}
|
||||
|
||||
void OBSBasicSettings::on_hotkeyFilterSearch_textChanged(const QString text)
|
||||
{
|
||||
SearchHotkeys(text, ui->hotkeyFilterInput->key);
|
||||
}
|
||||
|
||||
void OBSBasicSettings::on_hotkeyFilterInput_KeyChanged(
|
||||
obs_key_combination_t combo)
|
||||
{
|
||||
SearchHotkeys(ui->hotkeyFilterSearch->text(), combo);
|
||||
}
|
||||
|
||||
static bool MarkHotkeyConflicts(OBSHotkeyLabel *item1, OBSHotkeyLabel *item2)
|
||||
{
|
||||
if (item1->pairPartner == item2)
|
||||
|
@ -268,6 +268,10 @@ private slots:
|
||||
void on_useStreamKey_clicked();
|
||||
void on_useAuth_toggled();
|
||||
|
||||
void on_hotkeyFilterReset_clicked();
|
||||
void on_hotkeyFilterSearch_textChanged(const QString text);
|
||||
void on_hotkeyFilterInput_KeyChanged(obs_key_combination_t combo);
|
||||
|
||||
private:
|
||||
/* output */
|
||||
void LoadSimpleOutputSettings();
|
||||
@ -303,6 +307,9 @@ private:
|
||||
void SaveAdvancedSettings();
|
||||
void SaveSettings();
|
||||
|
||||
void SearchHotkeys(const QString &text,
|
||||
obs_key_combination_t filterCombo);
|
||||
|
||||
void UpdateSimpleOutStreamDelayEstimate();
|
||||
void UpdateAdvOutStreamDelayEstimate();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user