diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 096c860d1..d93b16593 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -390,8 +390,8 @@ Deinterlacing.TopFieldFirst="Top Field First" Deinterlacing.BottomFieldFirst="Bottom Field First" # volume control accessibility text -VolControl.SliderUnmuted="Volume slider for '%1': %2" -VolControl.SliderMuted="Volume slider for '%1': %2 (currently muted)" +VolControl.SliderUnmuted="Volume slider for '%1':" +VolControl.SliderMuted="Volume slider for '%1': (currently muted)" VolControl.Mute="Mute '%1'" VolControl.Properties="Properties for '%1'" @@ -430,6 +430,12 @@ Basic.SourceSelect.CreateNew="Create new" Basic.SourceSelect.AddExisting="Add Existing" Basic.SourceSelect.AddVisible="Make source visible" +# source box +Basic.Main.Sources.Visibility="Visibility" +Basic.Main.Sources.VisibilityDescription="Controls the visibility of '%1' in the canvas" +Basic.Main.Sources.Lock="Lock" +Basic.Main.Sources.LockDescription="Locks the position and scale of '%1' in the canvas" + # properties window Basic.PropertiesWindow="Properties for '%1'" Basic.PropertiesWindow.AutoSelectFormat="%1 (autoselect: %2)" @@ -733,6 +739,7 @@ Basic.Settings.Output.Adv.Audio.Track6="Track 6" # basic mode 'output' settings - advanced section - recording subsection Basic.Settings.Output.Adv.Recording="Recording" +Basic.Settings.Output.Adv.Recording.RecType="Recording Type" Basic.Settings.Output.Adv.Recording.Type="Type" Basic.Settings.Output.Adv.Recording.Type.Standard="Standard" Basic.Settings.Output.Adv.Recording.Type.FFmpegOutput="Custom Output (FFmpeg)" diff --git a/UI/forms/OBSBasicSettings.ui b/UI/forms/OBSBasicSettings.ui index a10e48277..e00325843 100644 --- a/UI/forms/OBSBasicSettings.ui +++ b/UI/forms/OBSBasicSettings.ui @@ -371,33 +371,13 @@ - - + + - Basic.Settings.General.ScreenSnapping + Basic.Settings.General.SnapDistance - - true - - - - - - - Basic.Settings.General.CenterSnapping - - - true - - - - - - - Basic.Settings.General.SourceSnapping - - - true + + snapDistance @@ -414,13 +394,13 @@ - - + + - Basic.Settings.General.SnapDistance + Basic.Settings.General.ScreenSnapping - - snapDistance + + true @@ -440,6 +420,26 @@ + + + + Basic.Settings.General.SourceSnapping + + + true + + + + + + + Basic.Settings.General.CenterSnapping + + + true + + + @@ -568,13 +568,6 @@ 2 - - - - Basic.Settings.General.OverflowAlwaysVisible - - - @@ -588,13 +581,6 @@ - - - - Basic.Settings.General.OverflowSelectionHidden - - - @@ -602,6 +588,20 @@ + + + + Basic.Settings.General.OverflowAlwaysVisible + + + + + + + Basic.Settings.General.OverflowSelectionHidden + + + @@ -721,9 +721,6 @@ - - - @@ -734,6 +731,9 @@ + + + @@ -4636,6 +4636,16 @@ + + + + Basic.Settings.Advanced.Video.ColorSpace + + + colorSpace + + + @@ -4685,16 +4695,6 @@ - - - - Basic.Settings.Advanced.Video.ColorSpace - - - colorSpace - - - @@ -4746,6 +4746,23 @@ + + + + Basic.Settings.Advanced.AutoRemux + + + + + + + Basic.Settings.Output.ReplayBuffer.Prefix + + + simpleRBPrefix + + + @@ -4778,16 +4795,6 @@ - - - - Basic.Settings.Output.ReplayBuffer.Prefix - - - simpleRBPrefix - - - @@ -4801,13 +4808,6 @@ - - - - Basic.Settings.Advanced.AutoRemux - - - @@ -4839,6 +4839,16 @@ 2 + + + + Enable + + + true + + + @@ -4915,16 +4925,6 @@ - - - - Enable - - - true - - - @@ -4966,6 +4966,16 @@ + + + + Basic.Settings.Output.RetryDelay + + + reconnectRetryDelay + + + @@ -5018,16 +5028,6 @@ - - - - Basic.Settings.Output.RetryDelay - - - reconnectRetryDelay - - - @@ -5072,6 +5072,16 @@ + + + + Basic.Settings.Output.DynamicBitrate.TT + + + Basic.Settings.Output.DynamicBitrate.Beta + + + @@ -5102,16 +5112,6 @@ - - - - Basic.Settings.Output.DynamicBitrate.TT - - - Basic.Settings.Output.DynamicBitrate.Beta - - - diff --git a/UI/hotkey-edit.cpp b/UI/hotkey-edit.cpp index 37e5a7d4d..2ee0cc39b 100644 --- a/UI/hotkey-edit.cpp +++ b/UI/hotkey-edit.cpp @@ -293,11 +293,13 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx) auto add = new QPushButton; add->setProperty("themeID", "addIconSmall"); + add->setToolTip(QTStr("Add")); add->setFixedSize(24, 24); add->setFlat(true); auto remove = new QPushButton; remove->setProperty("themeID", "removeIconSmall"); + remove->setToolTip(QTStr("Remove")); remove->setEnabled(removeButtons.size() > 0); remove->setFixedSize(24, 24); remove->setFlat(true); diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp index 46967e650..5051b433d 100644 --- a/UI/obs-app.cpp +++ b/UI/obs-app.cpp @@ -34,9 +34,11 @@ #include #include #include +#include #include "qt-wrappers.hpp" #include "obs-app.hpp" +#include "slider-ignorewheel.hpp" #include "window-basic-main.hpp" #include "window-basic-settings.hpp" #include "crash-report.hpp" @@ -1720,6 +1722,17 @@ static auto ProfilerFree = [](void *) { profiler_free(); }; +QAccessibleInterface *accessibleFactory(const QString &classname, + QObject *object) +{ + if (classname == QLatin1String("VolumeSlider") && object && + object->isWidgetType()) + return new VolumeAccessibleInterface( + static_cast(object)); + + return nullptr; +} + static const char *run_program_init = "run_program_init"; static int run_program(fstream &logFile, int argc, char *argv[]) { @@ -1743,6 +1756,8 @@ static int run_program(fstream &logFile, int argc, char *argv[]) OBSApp program(argc, argv, profilerNameStore.get()); try { + QAccessible::installFactory(accessibleFactory); + bool created_log = false; program.AppInit(); diff --git a/UI/slider-ignorewheel.cpp b/UI/slider-ignorewheel.cpp index 8203c81f9..dea80c18f 100644 --- a/UI/slider-ignorewheel.cpp +++ b/UI/slider-ignorewheel.cpp @@ -1,4 +1,5 @@ #include "slider-ignorewheel.hpp" +#include "volume-control.hpp" SliderIgnoreScroll::SliderIgnoreScroll(QWidget *parent) : QSlider(parent) { @@ -20,3 +21,82 @@ void SliderIgnoreScroll::wheelEvent(QWheelEvent *event) else QSlider::wheelEvent(event); } + +VolumeSlider::VolumeSlider(obs_fader_t *fader, QWidget *parent) + : SliderIgnoreScroll(parent) +{ + fad = fader; +} + +VolumeSlider::VolumeSlider(obs_fader_t *fader, Qt::Orientation orientation, + QWidget *parent) + : SliderIgnoreScroll(orientation, parent) +{ + fad = fader; +} + +VolumeAccessibleInterface::VolumeAccessibleInterface(QWidget *w) + : QAccessibleWidget(w) +{ +} + +VolumeSlider *VolumeAccessibleInterface::slider() const +{ + return qobject_cast(object()); +} + +QString VolumeAccessibleInterface::text(QAccessible::Text t) const +{ + if (slider()->isVisible()) { + switch (t) { + case QAccessible::Text::Value: + return currentValue().toString(); + default: + break; + } + } + return QAccessibleWidget::text(t); +} + +QVariant VolumeAccessibleInterface::currentValue() const +{ + QString text; + float db = obs_fader_get_db(slider()->fad); + + if (db < -96.0f) + text = "-inf dB"; + else + text = QString::number(db, 'f', 1).append(" dB"); + + return text; +} + +void VolumeAccessibleInterface::setCurrentValue(const QVariant &value) +{ + slider()->setValue(value.toInt()); +} + +QVariant VolumeAccessibleInterface::maximumValue() const +{ + return slider()->maximum(); +} + +QVariant VolumeAccessibleInterface::minimumValue() const +{ + return slider()->minimum(); +} + +QVariant VolumeAccessibleInterface::minimumStepSize() const +{ + return slider()->singleStep(); +} + +QAccessible::Role VolumeAccessibleInterface::role() const +{ + return QAccessible::Role::Slider; +} + +/**QAccessible::State VolumeAccessibleInterface::state() const +{ + return QAccessible::State:: +}**/ diff --git a/UI/slider-ignorewheel.hpp b/UI/slider-ignorewheel.hpp index f5c7e5d72..40d04487c 100644 --- a/UI/slider-ignorewheel.hpp +++ b/UI/slider-ignorewheel.hpp @@ -1,8 +1,10 @@ #pragma once +#include "obs.hpp" #include #include #include +#include class SliderIgnoreScroll : public QSlider { Q_OBJECT @@ -15,3 +17,35 @@ public: protected: virtual void wheelEvent(QWheelEvent *event) override; }; + +class VolumeSlider : public SliderIgnoreScroll { + Q_OBJECT + +public: + obs_fader_t *fad; + + VolumeSlider(obs_fader_t *fader, QWidget *parent = nullptr); + VolumeSlider(obs_fader_t *fader, Qt::Orientation orientation, + QWidget *parent = nullptr); +}; + +class VolumeAccessibleInterface : public QAccessibleWidget { + +public: + VolumeAccessibleInterface(QWidget *w); + + QVariant currentValue() const; + void setCurrentValue(const QVariant &value); + + QVariant maximumValue() const; + QVariant minimumValue() const; + + QVariant minimumStepSize() const; + +private: + VolumeSlider *slider() const; + +protected: + virtual QAccessible::Role role() const override; + virtual QString text(QAccessible::Text t) const override; +}; diff --git a/UI/source-tree.cpp b/UI/source-tree.cpp index 4032f3a3e..083a85de5 100644 --- a/UI/source-tree.cpp +++ b/UI/source-tree.cpp @@ -62,12 +62,18 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) vis->setFixedSize(16, 16); vis->setChecked(obs_sceneitem_visible(sceneitem)); vis->setStyleSheet("background: none"); + vis->setAccessibleName(QTStr("Basic.Main.Sources.Visibility")); + vis->setAccessibleDescription( + QTStr("Basic.Main.Sources.VisibilityDescription").arg(name)); lock = new LockedCheckBox(); lock->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); lock->setFixedSize(16, 16); lock->setChecked(obs_sceneitem_locked(sceneitem)); lock->setStyleSheet("background: none"); + lock->setAccessibleName(QTStr("Basic.Main.Sources.Lock")); + lock->setAccessibleDescription( + QTStr("Basic.Main.Sources.LockDescription").arg(name)); label = new QLabel(QT_UTF8(name)); label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -107,8 +113,8 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) obs_sceneitem_set_locked(sceneitem, checked); }; - connect(vis, &QAbstractButton::clicked, setItemVisible); - connect(lock, &QAbstractButton::clicked, setItemLocked); + connect(vis, &QAbstractButton::toggled, setItemVisible); + connect(lock, &QAbstractButton::toggled, setItemLocked); } void SourceTreeItem::paintEvent(QPaintEvent *event) diff --git a/UI/volume-control.cpp b/UI/volume-control.cpp index 35fdb0c2a..51d5bc4d5 100644 --- a/UI/volume-control.cpp +++ b/UI/volume-control.cpp @@ -89,7 +89,7 @@ void VolControl::updateText() : "VolControl.SliderUnmuted"; QString sourceName = obs_source_get_name(source); - QString accText = QTStr(accTextLookup).arg(sourceName, db); + QString accText = QTStr(accTextLookup).arg(sourceName); slider->setAccessibleName(accText); } @@ -161,7 +161,7 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical) QHBoxLayout *meterLayout = new QHBoxLayout; volMeter = new VolumeMeter(nullptr, obs_volmeter, true); - slider = new SliderIgnoreScroll(Qt::Vertical); + slider = new VolumeSlider(obs_fader, Qt::Vertical); nameLayout->setAlignment(Qt::AlignCenter); meterLayout->setAlignment(Qt::AlignCenter); @@ -205,7 +205,7 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical) QHBoxLayout *botLayout = new QHBoxLayout; volMeter = new VolumeMeter(nullptr, obs_volmeter, false); - slider = new SliderIgnoreScroll(Qt::Horizontal); + slider = new VolumeSlider(obs_fader, Qt::Horizontal); textLayout->setContentsMargins(0, 0, 0, 0); textLayout->addWidget(nameLabel); @@ -254,7 +254,7 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical) QWidget::connect(slider, SIGNAL(valueChanged(int)), this, SLOT(SliderChanged(int))); - QWidget::connect(mute, SIGNAL(clicked(bool)), this, + QWidget::connect(mute, SIGNAL(toggled(bool)), this, SLOT(SetMuted(bool))); obs_fader_attach_source(obs_fader, source); diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 0980dd297..9f503b32d 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -1486,7 +1486,7 @@ void OBSBasic::ResetOutputs() QTStr("Basic.Main.StartReplayBuffer"), this); replayBufferButton->setCheckable(true); connect(replayBufferButton.data(), - &QPushButton::clicked, this, + &QPushButton::toggled, this, &OBSBasic::ReplayBufferClicked); replayBufferButton->setProperty("themeID", @@ -7506,7 +7506,7 @@ void OBSBasic::UpdatePause(bool activate) pause->setChecked(false); pause->setProperty("themeID", QVariant(QStringLiteral("pauseIconSmall"))); - connect(pause.data(), &QAbstractButton::clicked, this, + connect(pause.data(), &QAbstractButton::toggled, this, &OBSBasic::PauseToggled); ui->recordingLayout->addWidget(pause.data()); } else { diff --git a/UI/window-basic-settings.cpp b/UI/window-basic-settings.cpp index 4d10e72d2..1a2d29c37 100644 --- a/UI/window-basic-settings.cpp +++ b/UI/window-basic-settings.cpp @@ -260,10 +260,9 @@ void OBSBasicSettings::HookWidget(QWidget *widget, const char *signal, #define COMBO_CHANGED SIGNAL(currentIndexChanged(int)) #define EDIT_CHANGED SIGNAL(textChanged(const QString &)) #define CBEDIT_CHANGED SIGNAL(editTextChanged(const QString &)) -#define CHECK_CHANGED SIGNAL(clicked(bool)) +#define CHECK_CHANGED SIGNAL(toggled(bool)) #define SCROLL_CHANGED SIGNAL(valueChanged(int)) #define DSCROLL_CHANGED SIGNAL(valueChanged(double)) -#define TOGGLE_CHANGED SIGNAL(toggled(bool)) #define GENERAL_CHANGED SLOT(GeneralChanged()) #define STREAM1_CHANGED SLOT(Stream1Changed()) @@ -726,18 +725,68 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent) InitStreamPage(); LoadSettings(false); + ui->advOutTrack1->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track1")); + ui->advOutTrack2->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track2")); + ui->advOutTrack3->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track3")); + ui->advOutTrack4->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track4")); + ui->advOutTrack5->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track5")); + ui->advOutTrack6->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track6")); + + ui->advOutRecTrack1->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track1")); + ui->advOutRecTrack2->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track2")); + ui->advOutRecTrack3->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track3")); + ui->advOutRecTrack4->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track4")); + ui->advOutRecTrack5->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track5")); + ui->advOutRecTrack6->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track6")); + + ui->advOutFFTrack1->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track1")); + ui->advOutFFTrack2->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track2")); + ui->advOutFFTrack3->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track3")); + ui->advOutFFTrack4->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track4")); + ui->advOutFFTrack5->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track5")); + ui->advOutFFTrack6->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Audio.Track6")); + + ui->snappingEnabled->setAccessibleName( + QTStr("Basic.Settings.General.Snapping")); + ui->systemTrayEnabled->setAccessibleName( + QTStr("Basic.Settings.General.SysTray")); + ui->label_31->setAccessibleName( + QTStr("Basic.Settings.Output.Adv.Recording.RecType")); + ui->streamDelayEnable->setAccessibleName( + QTStr("Basic.Settings.Advanced.StreamDelay")); + ui->reconnectEnable->setAccessibleName( + QTStr("Basic.Settings.Output.Reconnect")); + // Add warning checks to advanced output recording section controls - connect(ui->advOutRecTrack1, SIGNAL(clicked()), this, + connect(ui->advOutRecTrack1, SIGNAL(toggled()), this, SLOT(AdvOutRecCheckWarnings())); - connect(ui->advOutRecTrack2, SIGNAL(clicked()), this, + connect(ui->advOutRecTrack2, SIGNAL(toggled()), this, SLOT(AdvOutRecCheckWarnings())); - connect(ui->advOutRecTrack3, SIGNAL(clicked()), this, + connect(ui->advOutRecTrack3, SIGNAL(toggled()), this, SLOT(AdvOutRecCheckWarnings())); - connect(ui->advOutRecTrack4, SIGNAL(clicked()), this, + connect(ui->advOutRecTrack4, SIGNAL(toggled()), this, SLOT(AdvOutRecCheckWarnings())); - connect(ui->advOutRecTrack5, SIGNAL(clicked()), this, + connect(ui->advOutRecTrack5, SIGNAL(toggled()), this, SLOT(AdvOutRecCheckWarnings())); - connect(ui->advOutRecTrack6, SIGNAL(clicked()), this, + connect(ui->advOutRecTrack6, SIGNAL(toggled()), this, SLOT(AdvOutRecCheckWarnings())); connect(ui->advOutRecFormat, SIGNAL(currentIndexChanged(int)), this, SLOT(AdvOutRecCheckWarnings()));