ソースを参照

UI: Implement theme selection option

OBS will offer the user a list of themes which are .qss files inside
data/obs-studio/themes.  If no theme is found in the configuration, it
loads the default theme for the system.
Socapex 11 年 前
コミット
6a16778bc9

+ 1 - 0
obs/data/locale/en-US.ini

@@ -217,6 +217,7 @@ Basic.Settings.Confirm="You have unsaved changes.  Save changes?"
 
 # basic mode 'general' settings
 Basic.Settings.General="General"
+Basic.Settings.General.Theme="Theme"
 Basic.Settings.General.Language="Language"
 
 # basic mode 'stream' settings

+ 15 - 5
obs/forms/OBSBasicSettings.ui

@@ -6,7 +6,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>770</width>
+    <width>895</width>
     <height>602</height>
    </rect>
   </property>
@@ -143,6 +143,16 @@
          <item row="1" column="1">
           <widget class="QComboBox" name="language"/>
          </item>
+         <item row="2" column="0">
+          <widget class="QLabel" name="label_42">
+           <property name="text">
+            <string>Basic.Settings.General.Theme</string>
+           </property>
+          </widget>
+         </item>
+         <item row="2" column="1">
+          <widget class="QComboBox" name="theme"/>
+         </item>
         </layout>
        </widget>
        <widget class="QWidget" name="streamPage">
@@ -2326,8 +2336,8 @@
              <rect>
               <x>0</x>
               <y>0</y>
-              <width>609</width>
-              <height>553</height>
+              <width>724</width>
+              <height>536</height>
              </rect>
             </property>
             <layout class="QVBoxLayout" name="verticalLayout_16">
@@ -2362,7 +2372,7 @@
                     <widget class="QLabel" name="label_35">
                      <property name="minimumSize">
                       <size>
-                       <width>170</width>
+                       <width>0</width>
                        <height>0</height>
                       </size>
                      </property>
@@ -2409,7 +2419,7 @@
                      </property>
                      <property name="minimumSize">
                       <size>
-                       <width>170</width>
+                       <width>0</width>
                        <height>0</height>
                       </size>
                      </property>

+ 2 - 2
obs/forms/obs.qrc

@@ -1,5 +1,5 @@
 <RCC>
-  <qresource prefix="res">
+  <qresource prefix="/res">
     <file>images/configuration21_16.png</file>
     <file>images/list_remove.png</file>
     <file>images/add.png</file>
@@ -10,7 +10,7 @@
     <file>images/up.png</file>
     <file>images/obs.png</file>
   </qresource>
-  <qresource prefix="settings">
+  <qresource prefix="/settings">
     <file>images/settings/advanced.png</file>
     <file>images/settings/network.png</file>
     <file>images/settings/video-display-3.png</file>

+ 41 - 0
obs/obs-app.cpp

@@ -29,6 +29,7 @@
 #include "qt-wrappers.hpp"
 #include "obs-app.hpp"
 #include "window-basic-main.hpp"
+#include "window-basic-settings.hpp"
 #include "window-license-agreement.hpp"
 #include "crash-report.hpp"
 #include "platform.hpp"
@@ -233,6 +234,44 @@ bool OBSApp::InitLocale()
 	return true;
 }
 
+bool OBSApp::SetTheme(std::string name, std::string path)
+{
+	theme = name;
+
+	/* Check user dir first, then preinstalled themes. */
+	if (path == "") {
+		char userDir[512];
+		name = "themes/" + name + ".qss";
+		string temp = "obs-studio/" + name;
+		int ret = os_get_config_path(userDir, sizeof(userDir),
+				temp.c_str());
+
+		if (ret > 0 && QFile::exists(userDir)) {
+			path = string(userDir);
+		} else if (!GetDataFilePath(name.c_str(), path)) {
+			OBSErrorBox(NULL, "Failed to find %s.", name.c_str());
+			return false;
+		}
+	}
+
+	QString mpath = QString("file:///") + path.c_str();
+	setStyleSheet(mpath);
+	return true;
+}
+
+bool OBSApp::InitTheme()
+{
+	const char *themeName = config_get_string(globalConfig, "General",
+			"Theme");
+
+	if (!themeName)
+		themeName = "Default";
+
+	stringstream t;
+	t << themeName;
+	return SetTheme(t.str());
+}
+
 OBSApp::OBSApp(int &argc, char **argv)
 	: QApplication(argc, argv)
 {}
@@ -247,6 +286,8 @@ void OBSApp::AppInit()
 		throw "Failed to initialize global config";
 	if (!InitLocale())
 		throw "Failed to load locale";
+	if (!InitTheme())
+		throw "Failed to load theme";
 }
 
 const char *OBSApp::GetRenderModule() const

+ 5 - 0
obs/obs-app.hpp

@@ -55,6 +55,7 @@ class OBSApp : public QApplication {
 
 private:
 	std::string                    locale;
+	std::string		       theme;
 	ConfigFile                     globalConfig;
 	TextLookup                     textLookup;
 	QPointer<OBSMainWindow>        mainWindow;
@@ -62,6 +63,7 @@ private:
 	bool InitGlobalConfig();
 	bool InitGlobalConfigDefaults();
 	bool InitLocale();
+	bool InitTheme();
 
 public:
 	OBSApp(int &argc, char **argv);
@@ -78,6 +80,9 @@ public:
 		return locale.c_str();
 	}
 
+	inline const char *GetTheme() const {return theme.c_str();}
+	bool SetTheme(std::string name, std::string path = "");
+
 	inline lookup_t *GetTextLookup() const {return textLookup;}
 
 	inline const char *GetString(const char *lookupVal) const

+ 21 - 0
obs/window-basic-main.cpp

@@ -82,6 +82,7 @@ OBSBasic::OBSBasic(QWidget *parent)
 	  ui             (new Ui::OBSBasic)
 {
 	ui->setupUi(this);
+	copyActionsDynamicProperties();
 
 	int width = config_get_int(App()->GlobalConfig(), "MainWindow", "cx");
 
@@ -197,6 +198,26 @@ static obs_data_t *GenerateSaveData()
 	return saveData;
 }
 
+void OBSBasic::copyActionsDynamicProperties()
+{
+	// Themes need the QAction dynamic properties
+	for (QAction *x : ui->scenesToolbar->actions()) {
+		QWidget* temp = ui->scenesToolbar->widgetForAction(x);
+
+		for (QByteArray &y : x->dynamicPropertyNames()) {
+			temp->setProperty(y, x->property(y));
+		}
+	}
+
+	for (QAction *x : ui->sourcesToolbar->actions()) {
+		QWidget* temp = ui->sourcesToolbar->widgetForAction(x);
+
+		for (QByteArray &y : x->dynamicPropertyNames()) {
+			temp->setProperty(y, x->property(y));
+		}
+	}
+}
+
 void OBSBasic::ClearVolumeControls()
 {
 	VolControl *control;

+ 1 - 0
obs/window-basic-main.hpp

@@ -180,6 +180,7 @@ private:
 	void AddSource(const char *id);
 	QMenu *CreateAddSourcePopupMenu();
 	void AddSourcePopupMenu(const QPoint &pos);
+	void copyActionsDynamicProperties();
 
 public:
 	OBSScene      GetCurrentScene();

+ 62 - 0
obs/window-basic-settings.cpp

@@ -1,5 +1,6 @@
 /******************************************************************************
     Copyright (C) 2013-2014 by Hugh Bailey <[email protected]>
+                               Philippe Groarke <[email protected]>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -23,6 +24,7 @@
 #include <QMessageBox>
 #include <QCloseEvent>
 #include <QFileDialog>
+#include <QDirIterator>
 
 #include "obs-app.hpp"
 #include "platform.hpp"
@@ -134,6 +136,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
 	ui->setupUi(this);
 
 	HookWidget(ui->language,             COMBO_CHANGED,  GENERAL_CHANGED);
+	HookWidget(ui->theme, 		     COMBO_CHANGED,  GENERAL_CHANGED);
 	HookWidget(ui->outputMode,           COMBO_CHANGED,  OUTPUTS_CHANGED);
 	HookWidget(ui->streamType,           COMBO_CHANGED,  STREAM1_CHANGED);
 	HookWidget(ui->simpleOutputPath,     EDIT_CHANGED,   OUTPUTS_CHANGED);
@@ -336,11 +339,52 @@ void OBSBasicSettings::LoadLanguageList()
 	ui->language->model()->sort(0);
 }
 
+void OBSBasicSettings::LoadThemeList()
+{
+	/* Save theme if user presses Cancel */
+	savedTheme = string(App()->GetTheme());
+
+	ui->theme->clear();
+	QSet<QString> uniqueSet;
+	string themeDir;
+	char userThemeDir[512];
+	int ret = os_get_config_path(userThemeDir, sizeof(userThemeDir),
+			"obs-studio/themes/");
+	GetDataFilePath("themes/", themeDir);
+
+	/* Check user dir first. */
+	if (ret > 0) {
+		QDirIterator it(QString(userThemeDir), QStringList() << "*.qss",
+				QDir::Files);
+		while (it.hasNext()) {
+			it.next();
+			QString name = it.fileName().section(".",0,0);
+			ui->theme->addItem(name);
+			uniqueSet.insert(name);
+		}
+	}
+
+	/* Check shipped themes. */
+	QDirIterator uIt(QString(themeDir.c_str()), QStringList() << "*.qss",
+			QDir::Files);
+	while (uIt.hasNext()) {
+		uIt.next();
+		QString name = uIt.fileName().section(".",0,0);
+		if (!uniqueSet.contains(name))
+			ui->theme->addItem(name);
+	}
+
+	int idx = ui->theme->findText(App()->GetTheme());
+	if (idx != -1)
+		ui->theme->setCurrentIndex(idx);
+}
+
 void OBSBasicSettings::LoadGeneralSettings()
 {
 	loading = true;
 
 	LoadLanguageList();
+	LoadThemeList();
 
 	loading = false;
 }
@@ -984,6 +1028,16 @@ void OBSBasicSettings::SaveGeneralSettings()
 	if (WidgetChanged(ui->language))
 		config_set_string(GetGlobalConfig(), "General", "Language",
 				language.c_str());
+
+	int themeIndex = ui->theme->currentIndex();
+	QString themeData = ui->theme->itemText(themeIndex);
+	string theme = themeData.toStdString();
+
+	if (WidgetChanged(ui->theme)) {
+		config_set_string(GetGlobalConfig(), "General", "Theme",
+				  theme.c_str());
+		App()->SetTheme(theme);
+	}
 }
 
 void OBSBasicSettings::SaveStream1Settings()
@@ -1241,6 +1295,12 @@ void OBSBasicSettings::closeEvent(QCloseEvent *event)
 		event->ignore();
 }
 
+void OBSBasicSettings::on_theme_activated(int idx)
+{
+	string currT = ui->theme->itemText(idx).toStdString();
+	App()->SetTheme(currT);
+}
+
 void OBSBasicSettings::on_simpleOutUseBufsize_toggled(bool checked)
 {
 	if (!checked)
@@ -1276,6 +1336,8 @@ void OBSBasicSettings::on_buttonBox_clicked(QAbstractButton *button)
 
 	if (val == QDialogButtonBox::AcceptRole ||
 	    val == QDialogButtonBox::RejectRole) {
+		if (val == QDialogButtonBox::RejectRole)
+			App()->SetTheme(savedTheme);
 		ClearChanged();
 		close();
 	}

+ 6 - 0
obs/window-basic-settings.hpp

@@ -1,5 +1,6 @@
 /******************************************************************************
     Copyright (C) 2013 by Hugh Bailey <[email protected]>
+                          Philippe Groarke <[email protected]>
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -20,6 +21,7 @@
 #include <util/util.hpp>
 #include <QDialog>
 #include <memory>
+#include <string>
 
 #include <obs.h>
 
@@ -45,6 +47,7 @@ private:
 	bool advancedChanged = false;
 	int  pageIndex = 0;
 	bool loading = true;
+	std::string savedTheme;
 
 	OBSPropertiesView *streamProperties = nullptr;
 	OBSPropertiesView *streamEncoderProps = nullptr;
@@ -104,6 +107,7 @@ private:
 
 	/* general */
 	void LoadLanguageList();
+	void LoadThemeList();
 
 	/* output */
 	void LoadSimpleOutputSettings();
@@ -136,6 +140,8 @@ private:
 	void SaveSettings();
 
 private slots:
+	void on_theme_activated(int idx);
+
 	void on_simpleOutUseBufsize_toggled(bool checked);
 	void on_simpleOutputVBitrate_valueChanged(int val);