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.master
parent
5262fa31c0
commit
6a16778bc9
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -180,6 +180,7 @@ private:
|
|||
void AddSource(const char *id);
|
||||
QMenu *CreateAddSourcePopupMenu();
|
||||
void AddSourcePopupMenu(const QPoint &pos);
|
||||
void copyActionsDynamicProperties();
|
||||
|
||||
public:
|
||||
OBSScene GetCurrentScene();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013-2014 by Hugh Bailey <obs.jim@gmail.com>
|
||||
Philippe Groarke <philippe.groarke@gmail.com>
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/******************************************************************************
|
||||
Copyright (C) 2013 by Hugh Bailey <obs.jim@gmail.com>
|
||||
Philippe Groarke <philippe.groarke@gmail.com>
|
||||
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue