Skip to content

Commit

Permalink
UI: Add API to create simple browser docks
Browse files Browse the repository at this point in the history
  • Loading branch information
Elgato-AStory committed Jan 14, 2022
1 parent 5defdaf commit 50a7f9c
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 28 deletions.
26 changes: 26 additions & 0 deletions UI/api-interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,32 @@ struct OBSStudioAPI : obs_frontend_callbacks {
return (void *)main->AddDockWidget((QDockWidget *)dock);
}

void *obs_frontend_add_browser_dock(const char *id, const char *title,
const char *url) override
{
#ifdef BROWSER_AVAILABLE
QString qstrID = QT_UTF8(id);
QString qstrTitle = QT_UTF8(title);
QString qstrURL = QT_UTF8(url);

return main->AddPluginBrowserDock(qstrID, qstrTitle, qstrURL);
#else
UNUSED_PARAMETER(id);
UNUSED_PARAMETER(title);
UNUSED_PARAMETER(url);
return nullptr;
#endif
}

void obs_frontend_remove_browser_dock(void *dock) override
{
#ifdef BROWSER_AVAILABLE
main->RemovePluginBrowserDock((QDockWidget *)dock);
#else
UNUSED_PARAMETER(dock);
#endif
}

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

void *obs_frontend_add_browser_dock(const char *id, const char *title,
const char *url)
{
return !!callbacks_valid()
? c->obs_frontend_add_browser_dock(id, title, url)
: nullptr;
}

void obs_frontend_remove_browser_dock(void *dock)
{
if (callbacks_valid())
c->obs_frontend_remove_browser_dock(dock);
}

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

/* takes QDockWidget and returns QAction */
EXPORT void *obs_frontend_add_dock(void *dock);
/* returns QDockWidget */
EXPORT void *obs_frontend_add_browser_dock(const char *id, const char *title,
const char *url);
/* takes QDockWidget, calls delete on dock and its corresponding QAction */
EXPORT void obs_frontend_remove_browser_dock(void *dock);

typedef void (*obs_frontend_event_cb)(enum obs_frontend_event event,
void *private_data);
Expand Down
4 changes: 4 additions & 0 deletions UI/obs-frontend-api/obs-frontend-internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ struct obs_frontend_callbacks {
void *private_data) = 0;

virtual void *obs_frontend_add_dock(void *dock) = 0;
virtual void *obs_frontend_add_browser_dock(const char *id,
const char *title,
const char *url) = 0;
virtual void obs_frontend_remove_browser_dock(void *dock) = 0;

virtual void
obs_frontend_add_event_callback(obs_frontend_event_cb callback,
Expand Down
33 changes: 25 additions & 8 deletions UI/window-basic-main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1923,6 +1923,8 @@ void OBSBasic::OBSInit()

#ifdef BROWSER_AVAILABLE
if (cef) {
LoadPluginBrowserDocks();

QAction *action = new QAction(QTStr("Basic.MainMenu.Docks."
"CustomBrowserDocks"),
this);
Expand Down Expand Up @@ -9530,8 +9532,30 @@ void OBSBasic::ResizeOutputSizeOfSource()

QAction *OBSBasic::AddDockWidget(QDockWidget *dock)
{
bool hasDock = false;
QString dockUUID = dock->property("uuid").toString();
/* prune deleted docks and prevent adding the same dock again */
for (int i = extraDocks.size() - 1; i >= 0; i--) {
if (!extraDocks[i]) {
extraDocks.removeAt(i);
continue;
}
if (!hasDock &&
extraDocks[i]->property("uuid").toString() == dockUUID) {
hasDock = true;
}
}
if (hasDock) {
/* Return the existing action */
for (const auto action : ui->menuDocks->actions()) {
if (action->property("uuid").toString() == dockUUID) {
return action;
}
}
}

QAction *action = ui->menuDocks->addAction(dock->windowTitle());
action->setProperty("uuid", dock->property("uuid").toString());
action->setProperty("uuid", dockUUID);
action->setCheckable(true);
assignDockToggle(dock, action);
extraDocks.push_back(dock);
Expand All @@ -9545,13 +9569,6 @@ QAction *OBSBasic::AddDockWidget(QDockWidget *dock)

dock->setFeatures(features);

/* prune deleted docks */
for (int i = extraDocks.size() - 1; i >= 0; i--) {
if (!extraDocks[i]) {
extraDocks.removeAt(i);
}
}

return action;
}

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 @@ -544,6 +544,15 @@ class OBSBasic : public OBSMainWindow {
void ManageExtraBrowserDocks();
void AddExtraBrowserDock(const QString &title, const QString &url,
const QString &uuid, bool firstCreate);

QStringList pluginBrowserDockTargets;
QList<QPointer<QDockWidget>> pluginBrowserDocks;

void LoadPluginBrowserDocks();
void *AddPluginBrowserDock(const QString &id, const QString &title,
const QString &url);
void RemovePluginBrowserDock(QDockWidget *dock);

#endif

QIcon imageIcon;
Expand Down
104 changes: 85 additions & 19 deletions UI/window-extra-browsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ void OBSExtraBrowsers::on_apply_clicked()

/* ------------------------------------------------------------------------- */

static QAction *PrepareBrowserDockWindow(OBSBasic *api, BrowserDock *dock,
QString url, bool firstCreate);

void OBSBasic::ClearExtraBrowserDocks()
{
extraBrowserDockTargets.clear();
Expand Down Expand Up @@ -524,11 +527,6 @@ void OBSBasic::ManageExtraBrowserDocks()
void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
const QString &uuid, bool firstCreate)
{
static int panel_version = -1;
if (panel_version == -1) {
panel_version = obs_browser_qcef_version();
}

BrowserDock *dock = new BrowserDock();
QString bId(uuid.isEmpty() ? QUuid::createUuid().toString() : uuid);
bId.replace(QRegularExpression("[{}-]"), "");
Expand All @@ -539,6 +537,84 @@ void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
dock->setWindowTitle(title);
dock->setAllowedAreas(Qt::AllDockWidgetAreas);

QAction *action =
PrepareBrowserDockWindow(this, dock, url, firstCreate);
if (!action) {
return;
}

if (firstCreate) {
dock->setVisible(true);
action->blockSignals(true);
action->setChecked(true);
action->blockSignals(false);
}

extraBrowserDocks.push_back(QSharedPointer<QDockWidget>(dock));
extraBrowserDockActions.push_back(QSharedPointer<QAction>(action));
extraBrowserDockTargets.push_back(url);
}

void OBSBasic::LoadPluginBrowserDocks()
{
/* Deferred loading of plugin browser docks since CEF is initialized
at this point */
for (int i = 0; i < pluginBrowserDocks.size(); ++i) {
auto dock = static_cast<BrowserDock *>(
pluginBrowserDocks[i].data());
(void)PrepareBrowserDockWindow(
this, dock, pluginBrowserDockTargets[i], true);
}
}

void *OBSBasic::AddPluginBrowserDock(const QString &id, const QString &title,
const QString &url)
{

BrowserDock *dock = new BrowserDock();
QString bId(QUuid::createUuid().toString());
bId.replace(QRegularExpression("[{}-]"), "");
dock->setProperty("uuid", bId);
dock->setObjectName(id + "_pluginBrowser");
dock->resize(460, 600);
dock->setMinimumSize(80, 80);
dock->setWindowTitle(title);
dock->setAllowedAreas(Qt::AllDockWidgetAreas);
dock->setVisible(false);

pluginBrowserDocks.push_back(dock);
pluginBrowserDockTargets.push_back(url);

if (cef) {
(void)PrepareBrowserDockWindow(this, dock, url, true);
}

return static_cast<QDockWidget *>(dock);
}

void OBSBasic::RemovePluginBrowserDock(QDockWidget *dock)
{
QString dockUUID = dock->property("uuid").toString();
for (const auto action : ui->menuDocks->actions()) {
if (action && action->property("uuid").toString() == dockUUID) {
delete action;
}
}
delete dock;
}

/* fills a browser dock window with CEF and adds compatibility shims */
static QAction *PrepareBrowserDockWindow(OBSBasic *api, BrowserDock *dock,
QString url, bool firstCreate)
{
if (!dock) {
return nullptr;
}
static int panel_version = -1;
if (panel_version == -1) {
panel_version = obs_browser_qcef_version();
}

QCefWidget *browser =
cef->create_widget(dock, QT_TO_UTF8(url), nullptr);
if (browser && panel_version >= 1)
Expand All @@ -564,30 +640,20 @@ void OBSBasic::AddExtraBrowserDock(const QString &title, const QString &url,
}
}

addDockWidget(Qt::RightDockWidgetArea, dock);
api->addDockWidget(Qt::RightDockWidgetArea, dock);

if (firstCreate) {
dock->setFloating(true);

QPoint curPos = pos();
QSize wSizeD2 = size() / 2;
QPoint curPos = api->pos();
QSize wSizeD2 = api->size() / 2;
QSize dSizeD2 = dock->size() / 2;

curPos.setX(curPos.x() + wSizeD2.width() - dSizeD2.width());
curPos.setY(curPos.y() + wSizeD2.height() - dSizeD2.height());

dock->move(curPos);
dock->setVisible(true);
}

QAction *action = AddDockWidget(dock);
if (firstCreate) {
action->blockSignals(true);
action->setChecked(true);
action->blockSignals(false);
}

extraBrowserDocks.push_back(QSharedPointer<QDockWidget>(dock));
extraBrowserDockActions.push_back(QSharedPointer<QAction>(action));
extraBrowserDockTargets.push_back(url);
return api->AddDockWidget(dock);
}
26 changes: 25 additions & 1 deletion docs/sphinx/reference-frontend-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Structures/Enumerations
- **OBS_FRONTEND_EVENT_TRANSITION_DURATION_CHANGED**

Triggered when the transition duration has been changed by the
user.
user.

- **OBS_FRONTEND_EVENT_TBAR_VALUE_CHANGED**

Expand Down Expand Up @@ -423,6 +423,30 @@ Functions

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

.. function:: void *obs_frontend_add_browser_dock(const char *id, const char *title, const char *url)

Adds a plugin-controlled browser dock to the UI. The dock will automatically
be added to the Docks menu, however in order to retrieve the associated
QAction, you must call :c:func:`obs_frontend_add_dock()` with the returned
pointer.

:param id: A unique ID used to identify this dock
:param title: Name of the dock to create
:param url: URL of page to show in the new dock
:return: A pointer to a new QDockWidget

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

.. function:: void obs_frontend_remove_browser_dock(void *dock)

Deletes a browser dock and any associated QActions. This is an alternative
to calling delete directly on the returned pointer for non-C++ plugins.

:param dock: A pointer to a QDockWidget returned from
:c:func:`obs_frontend_add_browser_dock()`

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

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

Adds a callback that will be called when a frontend event occurs.
Expand Down

0 comments on commit 50a7f9c

Please sign in to comment.