Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 64 additions & 1 deletion UI/api-interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,70 @@ struct OBSStudioAPI : obs_frontend_callbacks {

void *obs_frontend_add_dock(void *dock) override
{
return (void *)main->AddDockWidget((QDockWidget *)dock);
QDockWidget *d = reinterpret_cast<QDockWidget *>(dock);

QString name = d->objectName();
if (name.isEmpty() || main->IsDockObjectNameUsed(name)) {
blog(LOG_WARNING,
"The object name of the added dock is empty or already used,"
" a temporary one will be set to avoid conflicts");

char *uuid = os_generate_uuid();
name = QT_UTF8(uuid);
bfree(uuid);
name.append("_oldExtraDock");

d->setObjectName(name);
}

return (void *)main->AddDockWidget(d);
}

bool obs_frontend_add_dock_by_id(const char *id, const char *title,
void *widget) override
{
if (main->IsDockObjectNameUsed(QT_UTF8(id))) {
blog(LOG_WARNING,
"Dock id '%s' already used! "
"Duplicate library?",
id);
return false;
}

OBSDock *dock = new OBSDock(main);
dock->setWidget((QWidget *)widget);
dock->setWindowTitle(QT_UTF8(title));
dock->setObjectName(QT_UTF8(id));

main->AddDockWidget(dock, Qt::RightDockWidgetArea);

dock->setFloating(true);
dock->setVisible(false);

return true;
}

void obs_frontend_remove_dock(const char *id) override
{
main->RemoveDockWidget(QT_UTF8(id));
}

bool obs_frontend_add_custom_qdock(const char *id, void *dock) override
{
if (main->IsDockObjectNameUsed(QT_UTF8(id))) {
blog(LOG_WARNING,
"Dock id '%s' already used! "
"Duplicate library?",
id);
return false;
}

QDockWidget *d = reinterpret_cast<QDockWidget *>(dock);
d->setObjectName(QT_UTF8(id));

main->AddCustomDockWidget(d);

return true;
}

void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
Expand Down
20 changes: 20 additions & 0 deletions UI/obs-frontend-api/obs-frontend-api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,26 @@ void *obs_frontend_add_dock(void *dock)
return !!callbacks_valid() ? c->obs_frontend_add_dock(dock) : nullptr;
}

bool obs_frontend_add_dock_by_id(const char *id, const char *title,
void *widget)
{
return !!callbacks_valid()
? c->obs_frontend_add_dock_by_id(id, title, widget)
: false;
}

void obs_frontend_remove_dock(const char *id)
{
if (callbacks_valid())
c->obs_frontend_remove_dock(id);
}

bool obs_frontend_add_custom_qdock(const char *id, void *dock)
{
return !!callbacks_valid() ? c->obs_frontend_add_custom_qdock(id, dock)
: false;
}

void obs_frontend_add_event_callback(obs_frontend_event_cb callback,
void *private_data)
{
Expand Down
10 changes: 10 additions & 0 deletions UI/obs-frontend-api/obs-frontend-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,18 @@ EXPORT void obs_frontend_add_tools_menu_item(const char *name,
void *private_data);

/* takes QDockWidget and returns QAction */
OBS_DEPRECATED
EXPORT void *obs_frontend_add_dock(void *dock);

/* takes QWidget for widget */
EXPORT bool obs_frontend_add_dock_by_id(const char *id, const char *title,
void *widget);

EXPORT void obs_frontend_remove_dock(const char *id);

/* takes QDockWidget for dock */
EXPORT bool obs_frontend_add_custom_qdock(const char *id, void *dock);

typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event,
void *private_data);

Expand Down
7 changes: 7 additions & 0 deletions UI/obs-frontend-api/obs-frontend-internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ struct obs_frontend_callbacks {

virtual void *obs_frontend_add_dock(void *dock) = 0;

virtual bool obs_frontend_add_dock_by_id(const char *id,
const char *title,
void *widget) = 0;
virtual void obs_frontend_remove_dock(const char *id) = 0;
virtual bool obs_frontend_add_custom_qdock(const char *id,
void *dock) = 0;

virtual void
obs_frontend_add_event_callback(obs_frontend_event_cb callback,
void *private_data) = 0;
Expand Down
102 changes: 95 additions & 7 deletions UI/window-basic-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9296,15 +9296,18 @@ void OBSBasic::on_resetDocks_triggered(bool force)
for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
if (!oldExtraDocks[i]) {
oldExtraDocks.removeAt(i);
oldExtraDockNames.removeAt(i);
}
}

#ifdef BROWSER_AVAILABLE
if ((oldExtraDocks.size() || extraDocks.size() ||
extraBrowserDocks.size()) &&
extraCustomDocks.size() || extraBrowserDocks.size()) &&
!force) {
#else
if ((oldExtraDocks.size() || extraDocks.size()) && !force) {
if ((oldExtraDocks.size() || extraDocks.size() ||
extraCustomDocks.size()) &&
!force) {
#endif
QMessageBox::StandardButton button = QMessageBox::question(
this, QTStr("ResetUIWarning.Title"),
Expand Down Expand Up @@ -9337,6 +9340,7 @@ void OBSBasic::on_resetDocks_triggered(bool force)
}

RESET_DOCKLIST(extraDocks)
RESET_DOCKLIST(extraCustomDocks)
#ifdef BROWSER_AVAILABLE
RESET_DOCKLIST(extraBrowserDocks)
#endif
Expand Down Expand Up @@ -9396,6 +9400,9 @@ void OBSBasic::on_lockDocks_toggled(bool lock)
for (int i = extraDocks.size() - 1; i >= 0; i--)
extraDocks[i]->setFeatures(features);

for (int i = extraCustomDocks.size() - 1; i >= 0; i--)
extraCustomDocks[i]->setFeatures(features);

#ifdef BROWSER_AVAILABLE
for (int i = extraBrowserDocks.size() - 1; i >= 0; i--)
extraBrowserDocks[i]->setFeatures(features);
Expand All @@ -9404,6 +9411,7 @@ void OBSBasic::on_lockDocks_toggled(bool lock)
for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
if (!oldExtraDocks[i]) {
oldExtraDocks.removeAt(i);
oldExtraDockNames.removeAt(i);
} else {
oldExtraDocks[i]->setFeatures(features);
}
Expand Down Expand Up @@ -10196,6 +10204,10 @@ void OBSBasic::ResizeOutputSizeOfSource()

QAction *OBSBasic::AddDockWidget(QDockWidget *dock)
{
// Prevent the object name from being changed
connect(dock, &QObject::objectNameChanged, this,
&OBSBasic::RepairOldExtraDockName);

#ifdef BROWSER_AVAILABLE
QAction *action = new QAction(dock->windowTitle(), ui->menuDocks);

Expand All @@ -10210,6 +10222,7 @@ QAction *OBSBasic::AddDockWidget(QDockWidget *dock)
action->setCheckable(true);
assignDockToggle(dock, action);
oldExtraDocks.push_back(dock);
oldExtraDockNames.push_back(dock->objectName());

bool lock = ui->lockDocks->isChecked();
QDockWidget::DockWidgetFeatures features =
Expand All @@ -10224,12 +10237,30 @@ QAction *OBSBasic::AddDockWidget(QDockWidget *dock)
for (int i = oldExtraDocks.size() - 1; i >= 0; i--) {
if (!oldExtraDocks[i]) {
oldExtraDocks.removeAt(i);
oldExtraDockNames.removeAt(i);
}
}

return action;
}

void OBSBasic::RepairOldExtraDockName()
{
QDockWidget *dock = reinterpret_cast<QDockWidget *>(sender());
int idx = oldExtraDocks.indexOf(dock);
QSignalBlocker block(dock);

if (idx == -1) {
blog(LOG_WARNING, "A dock got its object name changed");
return;
}

blog(LOG_WARNING, "The dock '%s' got its object name restored",
QT_TO_UTF8(oldExtraDockNames[idx]));

dock->setObjectName(oldExtraDockNames[idx]);
}

void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area,
bool extraBrowser)
{
Expand Down Expand Up @@ -10271,13 +10302,70 @@ void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area,

void OBSBasic::RemoveDockWidget(const QString &name)
{
if (!extraDockNames.contains(name))
if (extraDockNames.contains(name)) {
int idx = extraDockNames.indexOf(name);
extraDockNames.removeAt(idx);
extraDocks[idx].clear();
extraDocks.removeAt(idx);
} else if (extraCustomDockNames.contains(name)) {
int idx = extraCustomDockNames.indexOf(name);
extraCustomDockNames.removeAt(idx);
removeDockWidget(extraCustomDocks[idx]);
extraCustomDocks.removeAt(idx);
}
}

bool OBSBasic::IsDockObjectNameUsed(const QString &name)
{
QStringList list;
list << "scenesDock"
<< "sourcesDock"
<< "mixerDock"
<< "transitionsDock"
<< "controlsDock"
<< "statsDock";
list << oldExtraDockNames;
list << extraDockNames;
list << extraCustomDockNames;

return list.contains(name);
}

void OBSBasic::AddCustomDockWidget(QDockWidget *dock)
{
// Prevent the object name from being changed
connect(dock, &QObject::objectNameChanged, this,
&OBSBasic::RepairCustomExtraDockName);

bool lock = ui->lockDocks->isChecked();
QDockWidget::DockWidgetFeatures features =
lock ? QDockWidget::NoDockWidgetFeatures
: (QDockWidget::DockWidgetClosable |
QDockWidget::DockWidgetMovable |
QDockWidget::DockWidgetFloatable);

dock->setFeatures(features);
addDockWidget(Qt::RightDockWidgetArea, dock);

extraCustomDockNames.push_back(dock->objectName());
extraCustomDocks.push_back(dock);
}

void OBSBasic::RepairCustomExtraDockName()
{
QDockWidget *dock = reinterpret_cast<QDockWidget *>(sender());
int idx = extraCustomDocks.indexOf(dock);
QSignalBlocker block(dock);

if (idx == -1) {
blog(LOG_WARNING, "A custom dock got its object name changed");
return;
}

blog(LOG_WARNING, "The custom dock '%s' got its object name restored",
QT_TO_UTF8(extraCustomDockNames[idx]));

int idx = extraDockNames.indexOf(name);
extraDockNames.removeAt(idx);
extraDocks[idx].clear();
extraDocks.removeAt(idx);
dock->setObjectName(extraCustomDockNames[idx]);
}

OBSBasic *OBSBasic::Get()
Expand Down
9 changes: 9 additions & 0 deletions UI/window-basic-main.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ class OBSBasic : public OBSMainWindow {
std::vector<OBSSignal> signalHandlers;

QList<QPointer<QDockWidget>> oldExtraDocks;
QStringList oldExtraDockNames;

bool loaded = false;
long disableSaving = 1;
Expand Down Expand Up @@ -556,6 +557,9 @@ class OBSBasic : public OBSMainWindow {
QStringList extraDockNames;
QList<QSharedPointer<QDockWidget>> extraDocks;

QStringList extraCustomDockNames;
QList<QPointer<QDockWidget>> extraCustomDocks;

#ifdef BROWSER_AVAILABLE
QPointer<QAction> extraBrowserMenuDocksSeparator;

Expand Down Expand Up @@ -970,6 +974,8 @@ private slots:
void AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area,
bool extraBrowser = false);
void RemoveDockWidget(const QString &name);
bool IsDockObjectNameUsed(const QString &name);
void AddCustomDockWidget(QDockWidget *dock);

static OBSBasic *Get();

Expand Down Expand Up @@ -1201,6 +1207,9 @@ private slots:

void ResizeOutputSizeOfSource();

void RepairOldExtraDockName();
void RepairCustomExtraDockName();

public slots:
void on_actionResetTransform_triggered();

Expand Down
42 changes: 42 additions & 0 deletions docs/sphinx/reference-frontend-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,48 @@ Functions
:param dock: QDockWidget to add/create
:return: A pointer to the added QAction

.. deprecated:: 29.1
Prefer :c:func:`obs_frontend_add_dock_by_id()` or
:c:func:`obs_frontend_add_custom_qdock()` instead.

---------------------------------------

.. function:: bool obs_frontend_add_dock_by_id(const char *id, const char *title, void *widget)

Adds a dock with the widget to the UI with a toggle in the Docks
menu.

Note: Use :c:func:`obs_frontend_remove_dock` to remove the dock
and the id from the UI.

:param id: Unique identifier of the dock
:param title: Window title of the dock
:param widget: QWidget to insert in the dock
:return: *true* if the dock was added, *false* if the id was already
used

---------------------------------------

.. function:: void obs_frontend_remove_dock(const char *id)

Removes the dock with this id from the UI.

:param id: Unique identifier of the dock to remove.

---------------------------------------

.. function:: bool obs_frontend_add_custom_qdock(const char *id, void *dock)

Adds a custom dock to the UI with no toggle.

Note: Use :c:func:`obs_frontend_remove_dock` to remove the dock
reference and id from the UI.

:param id: Unique identifier of the dock
:param dock: QDockWidget to add
:return: *true* if the dock was added, *false* if the id was already
used

---------------------------------------

.. function:: void obs_frontend_add_event_callback(obs_frontend_event_cb callback, void *private_data)
Expand Down