Browse Source

UI: Avoid having two dock with the same object name

https://doc.qt.io/qt-6/qmainwindow.html#saveState

You should make sure that this property is unique for each QToolBar and
QDockWidget you add to the QMainWindow.
tytan652 3 years ago
parent
commit
f2fa54120a
3 changed files with 61 additions and 1 deletions
  1. 17 1
      UI/api-interface.cpp
  2. 40 0
      UI/window-basic-main.cpp
  3. 4 0
      UI/window-basic-main.hpp

+ 17 - 1
UI/api-interface.cpp

@@ -379,7 +379,23 @@ 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);
 	}
 
 	void obs_frontend_add_event_callback(obs_frontend_event_cb callback,

+ 40 - 0
UI/window-basic-main.cpp

@@ -9305,6 +9305,7 @@ 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);
 		}
 	}
 
@@ -9413,6 +9414,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);
 		}
@@ -10221,6 +10223,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);
 
@@ -10235,6 +10241,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 =
@@ -10249,12 +10256,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)
 {
@@ -10305,6 +10330,21 @@ void OBSBasic::RemoveDockWidget(const QString &name)
 	extraDocks.removeAt(idx);
 }
 
+bool OBSBasic::IsDockObjectNameUsed(const QString &name)
+{
+	QStringList list;
+	list << "scenesDock"
+	     << "sourcesDock"
+	     << "mixerDock"
+	     << "transitionsDock"
+	     << "controlsDock"
+	     << "statsDock";
+	list << oldExtraDockNames;
+	list << extraDockNames;
+
+	return list.contains(name);
+}
+
 OBSBasic *OBSBasic::Get()
 {
 	return reinterpret_cast<OBSBasic *>(App()->GetMainWindow());

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

@@ -229,6 +229,7 @@ private:
 	std::vector<OBSSignal> signalHandlers;
 
 	QList<QPointer<QDockWidget>> oldExtraDocks;
+	QStringList oldExtraDockNames;
 
 	bool loaded = false;
 	long disableSaving = 1;
@@ -970,6 +971,7 @@ public:
 	void AddDockWidget(QDockWidget *dock, Qt::DockWidgetArea area,
 			   bool extraBrowser = false);
 	void RemoveDockWidget(const QString &name);
+	bool IsDockObjectNameUsed(const QString &name);
 
 	static OBSBasic *Get();
 
@@ -1202,6 +1204,8 @@ private slots:
 
 	void ResizeOutputSizeOfSource();
 
+	void RepairOldExtraDockName();
+
 public slots:
 	void on_actionResetTransform_triggered();