Improve dock handling when changing scene collections

Note that the positions of the docks will still not be restored
perfectly when changing scene collections.
To my understanding this would somehow have to be handled by the
QMainWindow which is controlled by OBS.

This might have to be revisited at a later date.
This commit is contained in:
WarmUpTill 2023-04-08 23:42:22 +02:00 committed by WarmUpTill
parent 17d24d642e
commit 1ddd48e008
4 changed files with 109 additions and 17 deletions

View File

@ -44,6 +44,9 @@ MacroDock::MacroDock(Macro *m, QWidget *parent)
wrapper->setFrameShadow(QFrame::Sunken);
wrapper->setLayout(layout);
setWidget(wrapper);
setFloating(true);
hide();
}
void MacroDock::SetName(const QString &name)

View File

@ -267,6 +267,11 @@ void Macro::SetOnChangeHighlight()
_onChangeTriggered = true;
}
bool Macro::DockIsVisible() const
{
return _dock && _dockAction && _dock->isVisible();
}
void Macro::SetPaused(bool pause)
{
if (_paused && !pause) {
@ -341,13 +346,7 @@ bool Macro::Save(obs_data_t *obj) const
return true;
}
obs_data_set_bool(obj, "registerDock", _registerDock);
// The object name is used to restore the position of the dock
if (_registerDock) {
SetDockWidgetName();
}
obs_data_set_bool(obj, "dockHasRunButton", _dockHasRunButton);
obs_data_set_bool(obj, "dockHasPauseButton", _dockHasPauseButton);
SaveDockSettings(obj);
obs_data_set_bool(obj, "registerHotkeys", _registerHotkeys);
obs_data_array_t *pauseHotkey = obs_hotkey_save(_pauseHotkey);
@ -438,9 +437,7 @@ bool Macro::Load(obs_data_t *obj)
return true;
}
_dockHasRunButton = obs_data_get_bool(obj, "dockHasRunButton");
_dockHasPauseButton = obs_data_get_bool(obj, "dockHasPauseButton");
EnableDock(obs_data_get_bool(obj, "registerDock"));
LoadDockSettings(obj);
obs_data_set_default_bool(obj, "registerHotkeys", true);
_registerHotkeys = obs_data_get_bool(obj, "registerHotkeys");
@ -583,22 +580,103 @@ bool Macro::PauseHotkeysEnabled()
return _registerHotkeys;
}
void Macro::SaveDockSettings(obs_data_t *obj) const
{
auto dockSettings = obs_data_create();
obs_data_set_bool(dockSettings, "register", _registerDock);
// The object name is used to restore the position of the dock
if (_registerDock) {
SetDockWidgetName();
}
obs_data_set_bool(dockSettings, "hasRunButton", _dockHasRunButton);
obs_data_set_bool(dockSettings, "hasPauseButton", _dockHasPauseButton);
if (_dock) {
auto window = static_cast<QMainWindow *>(
obs_frontend_get_main_window());
obs_data_set_bool(dockSettings, "isFloating",
_dock->isFloating());
obs_data_set_bool(dockSettings, "isVisible", DockIsVisible());
obs_data_set_int(dockSettings, "area",
window->dockWidgetArea(_dock));
obs_data_set_string(
dockSettings, "geometry",
_dock->saveGeometry().toBase64().constData());
}
obs_data_set_obj(obj, "dockSettings", dockSettings);
obs_data_release(dockSettings);
}
void Macro::LoadDockSettings(obs_data_t *obj)
{
auto dockSettings = obs_data_get_obj(obj, "dockSettings");
if (!dockSettings) {
// TODO: Remove this fallback
_dockHasRunButton = obs_data_get_bool(obj, "dockHasRunButton");
_dockHasPauseButton =
obs_data_get_bool(obj, "dockHasPauseButton");
EnableDock(obs_data_get_bool(obj, "registerDock"));
return;
}
const bool dockEnabled = obs_data_get_bool(dockSettings, "register");
_dockIsVisible = obs_data_get_bool(dockSettings, "isVisible");
if (dockEnabled) {
_dockHasRunButton =
obs_data_get_bool(dockSettings, "hasRunButton");
_dockHasPauseButton =
obs_data_get_bool(dockSettings, "hasPauseButton");
_dockIsFloating = obs_data_get_bool(dockSettings, "isFloating");
_dockArea = static_cast<Qt::DockWidgetArea>(
obs_data_get_int(dockSettings, "area"));
auto geometryStr =
obs_data_get_string(dockSettings, "geometry");
if (geometryStr && strlen(geometryStr)) {
_dockGeo =
QByteArray::fromBase64(QByteArray(geometryStr));
}
}
EnableDock(dockEnabled);
obs_data_release(dockSettings);
}
void Macro::EnableDock(bool value)
{
if (_registerDock == value) {
return;
}
// Reset dock regardless
RemoveDock();
if (!_registerDock) {
_dock = new MacroDock(this,
static_cast<QMainWindow *>(
obs_frontend_get_main_window()));
_dockAction =
static_cast<QAction *>(obs_frontend_add_dock(_dock));
SetDockWidgetName();
// Unregister dock
if (_registerDock) {
_dockIsFloating = true;
_dockGeo = QByteArray();
_registerDock = value;
return;
}
// Create new dock widget
auto window =
static_cast<QMainWindow *>(obs_frontend_get_main_window());
_dock = new MacroDock(this, window);
SetDockWidgetName(); // Used by OBS to restore position
// Register new dock
_dockAction = static_cast<QAction *>(obs_frontend_add_dock(_dock));
// Note that OBSBasic::OBSInit() has precedence over the visibility and
// geometry set here.
// The function calls here are only intended to attempt to restore the
// dock status when switching scene collections.
_dock->setVisible(_dockIsVisible);
if (window->dockWidgetArea(_dock) != _dockArea) {
window->addDockWidget(_dockArea, _dock);
}
if (_dock->isFloating() != _dockIsFloating) {
_dock->setFloating(_dockIsFloating);
}
_dock->restoreGeometry(_dockGeo);
_registerDock = value;
}

View File

@ -4,6 +4,7 @@
#include "macro-ref.hpp"
#include <QString>
#include <QByteArray>
#include <string>
#include <deque>
#include <memory>
@ -96,7 +97,10 @@ private:
void RunActions(bool &ret, bool ignorePause);
void RunActions(bool ignorePause);
void SetOnChangeHighlight();
bool DockIsVisible() const;
void SetDockWidgetName() const;
void SaveDockSettings(obs_data_t *obj) const;
void LoadDockSettings(obs_data_t *obj);
void RemoveDock();
std::string _name = "";
@ -125,6 +129,10 @@ private:
bool _registerDock = false;
bool _dockHasRunButton = true;
bool _dockHasPauseButton = true;
bool _dockIsFloating = true;
bool _dockIsVisible = false;
Qt::DockWidgetArea _dockArea;
QByteArray _dockGeo;
MacroDock *_dock = nullptr;
QAction *_dockAction = nullptr;

View File

@ -146,6 +146,9 @@ StatusDock::StatusDock(QWidget *parent) : OBSDock(parent)
wrapper->setFrameShadow(QFrame::Sunken);
wrapper->setLayout(layout);
setWidget(wrapper);
setFloating(true);
hide();
}
void SetupDock()