Răsfoiți Sursa

obs-frontend-api,UI,docs: Add API to add custom docks with no toggle

Some plugin does that by deleting the QAction returned by
obs_frontend_add_dock().

Now that obs_frontend_add_dock() is deprecated,
obs_frontend_add_custom_qdock() replace this usage.
tytan652 3 ani în urmă
părinte
comite
90d96e92c2

+ 18 - 0
UI/api-interface.cpp

@@ -427,6 +427,24 @@ struct OBSStudioAPI : obs_frontend_callbacks {
 		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,
 					     void *private_data) override
 	{

+ 6 - 0
UI/obs-frontend-api/obs-frontend-api.cpp

@@ -344,6 +344,12 @@ void obs_frontend_remove_dock(const char *id)
 		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)
 {

+ 3 - 0
UI/obs-frontend-api/obs-frontend-api.h

@@ -147,6 +147,9 @@ EXPORT bool obs_frontend_add_dock_by_id(const char *id, const char *title,
 
 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);
 

+ 2 - 0
UI/obs-frontend-api/obs-frontend-internal.hpp

@@ -70,6 +70,8 @@ struct obs_frontend_callbacks {
 						 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,

+ 57 - 9
UI/window-basic-main.cpp

@@ -9311,10 +9311,12 @@ void OBSBasic::on_resetDocks_triggered(bool force)
 
 #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"),
@@ -9347,6 +9349,7 @@ void OBSBasic::on_resetDocks_triggered(bool force)
 	}
 
 	RESET_DOCKLIST(extraDocks)
+	RESET_DOCKLIST(extraCustomDocks)
 #ifdef BROWSER_AVAILABLE
 	RESET_DOCKLIST(extraBrowserDocks)
 #endif
@@ -9406,6 +9409,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);
@@ -10321,13 +10327,17 @@ void OBSBasic::AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area,
 
 void OBSBasic::RemoveDockWidget(const QString &name)
 {
-	if (!extraDockNames.contains(name))
-		return;
-
-	int idx = extraDockNames.indexOf(name);
-	extraDockNames.removeAt(idx);
-	extraDocks[idx].clear();
-	extraDocks.removeAt(idx);
+	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)
@@ -10341,10 +10351,48 @@ bool OBSBasic::IsDockObjectNameUsed(const QString &name)
 	     << "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]));
+
+	dock->setObjectName(extraCustomDockNames[idx]);
+}
+
 OBSBasic *OBSBasic::Get()
 {
 	return reinterpret_cast<OBSBasic *>(App()->GetMainWindow());

+ 5 - 0
UI/window-basic-main.hpp

@@ -557,6 +557,9 @@ private:
 	QStringList extraDockNames;
 	QList<QSharedPointer<QDockWidget>> extraDocks;
 
+	QStringList extraCustomDockNames;
+	QList<QPointer<QDockWidget>> extraCustomDocks;
+
 #ifdef BROWSER_AVAILABLE
 	QPointer<QAction> extraBrowserMenuDocksSeparator;
 
@@ -972,6 +975,7 @@ public:
 			   bool extraBrowser = false);
 	void RemoveDockWidget(const QString &name);
 	bool IsDockObjectNameUsed(const QString &name);
+	void AddCustomDockWidget(QDockWidget *dock);
 
 	static OBSBasic *Get();
 
@@ -1205,6 +1209,7 @@ private slots:
 	void ResizeOutputSizeOfSource();
 
 	void RepairOldExtraDockName();
+	void RepairCustomExtraDockName();
 
 public slots:
 	void on_actionResetTransform_triggered();

+ 16 - 1
docs/sphinx/reference-frontend-api.rst

@@ -448,7 +448,8 @@ Functions
    :return: A pointer to the added QAction
 
 .. deprecated:: 29.1
-   Prefer :c:func:`obs_frontend_add_dock_by_id()` instead.
+   Prefer :c:func:`obs_frontend_add_dock_by_id()` or
+   :c:func:`obs_frontend_add_custom_qdock()` instead.
 
 ---------------------------------------
 
@@ -476,6 +477,20 @@ Functions
 
 ---------------------------------------
 
+.. 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)
 
    Adds a callback that will be called when a frontend event occurs.