From e2fa510436b48d7bdfc1b76cf7bb2d2e4e57d304 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Thu, 12 Dec 2019 17:07:26 -0800 Subject: [PATCH] UI: Add save button next to replay buffer button Allows the ability to save replays with a button rather than with the keyboard if desired. Closes obsproject/obs-studio#1954 --- UI/data/locale/en-US.ini | 1 + UI/data/themes/Acri.qss | 6 ++++++ UI/data/themes/Dark.qss | 6 ++++++ UI/data/themes/Dark/save.svg | 3 +++ UI/data/themes/Rachni.qss | 6 ++++++ UI/data/themes/System.qss | 6 ++++++ UI/forms/images/save.svg | 3 +++ UI/forms/obs.qrc | 1 + UI/record-button.cpp | 17 +++++++++++++++++ UI/record-button.hpp | 13 +++++++++++++ UI/window-basic-main.cpp | 30 ++++++++++++++++++++++++++++-- UI/window-basic-main.hpp | 4 ++++ 12 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 UI/data/themes/Dark/save.svg create mode 100644 UI/forms/images/save.svg diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini index 44978dd8c..b6db39c48 100644 --- a/UI/data/locale/en-US.ini +++ b/UI/data/locale/en-US.ini @@ -517,6 +517,7 @@ Basic.Main.Controls="Controls" Basic.Main.Connecting="Connecting..." Basic.Main.StartRecording="Start Recording" Basic.Main.StartReplayBuffer="Start Replay Buffer" +Basic.Main.SaveReplay="Save Replay" Basic.Main.StartStreaming="Start Streaming" Basic.Main.StopRecording="Stop Recording" Basic.Main.PauseRecording="Pause Recording" diff --git a/UI/data/themes/Acri.qss b/UI/data/themes/Acri.qss index ffd972b3c..e1d4b0c6b 100644 --- a/UI/data/themes/Acri.qss +++ b/UI/data/themes/Acri.qss @@ -1044,3 +1044,9 @@ SceneTree#scenes { padding-right: 10px; margin: 0px; } + +/* Save replay icon */ + +* [themeID="replayIconSmall"] { + qproperty-icon: url(./Dark/save.svg); +} diff --git a/UI/data/themes/Dark.qss b/UI/data/themes/Dark.qss index 94819ae70..03838e697 100644 --- a/UI/data/themes/Dark.qss +++ b/UI/data/themes/Dark.qss @@ -809,3 +809,9 @@ SceneTree { *[gridMode="true"] SceneTree::item:checked { background-color: rgb(122,121,122); /* light */ } + +/* Save icon */ + +* [themeID="replayIconSmall"] { + qproperty-icon: url(./Dark/save.svg); +} diff --git a/UI/data/themes/Dark/save.svg b/UI/data/themes/Dark/save.svg new file mode 100644 index 000000000..346fca847 --- /dev/null +++ b/UI/data/themes/Dark/save.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/data/themes/Rachni.qss b/UI/data/themes/Rachni.qss index 2aa304f9b..e852ca7ef 100644 --- a/UI/data/themes/Rachni.qss +++ b/UI/data/themes/Rachni.qss @@ -1372,3 +1372,9 @@ SceneTree#scenes { qproperty-gridItemWidth: 150; qproperty-gridItemHeight: 30; } + +/* Save icon */ + +* [themeID="replayIconSmall"] { + qproperty-icon: url(./Dark/save.svg); +} diff --git a/UI/data/themes/System.qss b/UI/data/themes/System.qss index 572946219..99b146761 100644 --- a/UI/data/themes/System.qss +++ b/UI/data/themes/System.qss @@ -240,3 +240,9 @@ SceneTree { qproperty-gridItemWidth: 150; qproperty-gridItemHeight: 24; } + +/* Save icon */ + +* [themeID="replayIconSmall"] { + qproperty-icon: url(:res/images/save.svg); +} diff --git a/UI/forms/images/save.svg b/UI/forms/images/save.svg new file mode 100644 index 000000000..39fb418fa --- /dev/null +++ b/UI/forms/images/save.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/forms/obs.qrc b/UI/forms/obs.qrc index 449b217e1..0cd6cf2ee 100644 --- a/UI/forms/obs.qrc +++ b/UI/forms/obs.qrc @@ -1,5 +1,6 @@ + images/save.svg images/media-pause.svg images/mute.svg images/refresh.svg diff --git a/UI/record-button.cpp b/UI/record-button.cpp index 021f5b83e..0e080a796 100644 --- a/UI/record-button.cpp +++ b/UI/record-button.cpp @@ -17,3 +17,20 @@ void RecordButton::resizeEvent(QResizeEvent *event) event->accept(); } + +void ReplayBufferButton::resizeEvent(QResizeEvent *event) +{ + OBSBasic *main = OBSBasic::Get(); + if (!main->replay) + return; + + QSize replaySize = main->replay->size(); + int height = main->ui->recordButton->size().height(); + + if (replaySize.height() != height || replaySize.width() != height) { + main->replay->setMinimumSize(height, height); + main->replay->setMaximumSize(height, height); + } + + event->accept(); +} diff --git a/UI/record-button.hpp b/UI/record-button.hpp index c1782aafa..d6c083e21 100644 --- a/UI/record-button.hpp +++ b/UI/record-button.hpp @@ -10,3 +10,16 @@ public: virtual void resizeEvent(QResizeEvent *event) override; }; + +class ReplayBufferButton : public QPushButton { + Q_OBJECT + +public: + inline ReplayBufferButton(const QString &text, + QWidget *parent = nullptr) + : QPushButton(text, parent) + { + } + + virtual void resizeEvent(QResizeEvent *event) override; +}; diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index a54f95785..1ed02c9e7 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -1501,18 +1501,22 @@ void OBSBasic::ResetOutputs() : CreateSimpleOutputHandler(this)); delete replayBufferButton; + delete replayLayout; if (outputHandler->replayBuffer) { - replayBufferButton = new QPushButton( + replayBufferButton = new ReplayBufferButton( QTStr("Basic.Main.StartReplayBuffer"), this); replayBufferButton->setCheckable(true); connect(replayBufferButton.data(), &QPushButton::clicked, this, &OBSBasic::ReplayBufferClicked); + replayLayout = new QHBoxLayout(this); + replayLayout->addWidget(replayBufferButton); + replayBufferButton->setProperty("themeID", "replayBufferButton"); - ui->buttonsVLayout->insertWidget(2, replayBufferButton); + ui->buttonsVLayout->insertLayout(2, replayLayout); } if (sysTrayReplayBuffer) @@ -5664,6 +5668,7 @@ void OBSBasic::ReplayBufferStart() api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STARTED); OnActivate(); + UpdateReplayBuffer(); blog(LOG_INFO, REPLAY_BUFFER_START); } @@ -5725,6 +5730,7 @@ void OBSBasic::ReplayBufferStop(int code) api->on_event(OBS_FRONTEND_EVENT_REPLAY_BUFFER_STOPPED); OnDeactivate(); + UpdateReplayBuffer(false); } void OBSBasic::on_streamButton_clicked() @@ -7602,6 +7608,26 @@ void OBSBasic::UpdatePause(bool activate) } } +void OBSBasic::UpdateReplayBuffer(bool activate) +{ + if (!activate || !outputHandler || + !outputHandler->ReplayBufferActive()) { + replay.reset(); + return; + } + + replay.reset(new QPushButton()); + replay->setAccessibleName(QTStr("Basic.Main.SaveReplay")); + replay->setToolTip(QTStr("Basic.Main.SaveReplay")); + replay->setCheckable(true); + replay->setChecked(false); + replay->setProperty("themeID", + QVariant(QStringLiteral("replayIconSmall"))); + connect(replay.data(), &QAbstractButton::clicked, this, + &OBSBasic::ReplayBufferSave); + replayLayout->addWidget(replay.data()); +} + #define MBYTE (1024ULL * 1024ULL) #define MBYTES_LEFT_STOP_REC 50ULL #define MAX_BYTES_LEFT (MBYTES_LEFT_STOP_REC * MBYTE) diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index 935e553ba..df0606cb9 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -157,6 +157,7 @@ class OBSBasic : public OBSMainWindow { friend class AutoConfig; friend class AutoConfigStreamPage; friend class RecordButton; + friend class ReplayBufferButton; friend class ExtraBrowsersModel; friend class ExtraBrowsersDelegate; friend struct OBSStudioAPI; @@ -241,7 +242,9 @@ private: QPointer transitionButton; QPointer replayBufferButton; + QPointer replayLayout; QScopedPointer pause; + QScopedPointer replay; QScopedPointer trayIcon; QPointer sysTrayStream; @@ -669,6 +672,7 @@ private: void AutoRemux(); void UpdatePause(bool activate = true); + void UpdateReplayBuffer(bool activate = true); bool LowDiskSpace(); void DiskSpaceMessage();