mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 23:34:08 +00:00
UI: Add ability to parse OBSStyle from qss
Adds the ability to set the current palette for the program via adding "OBSTheme" objects to the qss files. The values for the OBSTheme object are the values used by QPalette::ColorRole. Modifying the global palette allows the ability to easily/quickly look up application theme colors (especially if you would like to use them for QML), as well as the ability to fix the hyperlink color issue. (On dark themes, links would still be dark blue, causing them to be difficult to see)
This commit is contained in:
parent
8b6d437a97
commit
e1ab9a0fc4
|
@ -1,3 +1,37 @@
|
|||
/* OBSTheme, main QApplication palette and QML values */
|
||||
OBSTheme {
|
||||
window: #181819;
|
||||
windowText: rgb(225,224,225);
|
||||
base: rgb(18,18,21);
|
||||
alternateBase: rgb(0,0,0);
|
||||
text: rgb(225,224,225);
|
||||
button: #162458;
|
||||
buttonText: rgb(225,224,225);
|
||||
brightText: #484848;
|
||||
|
||||
light: #162458;
|
||||
mid: #181819;
|
||||
dark: rgb(18,18,21);
|
||||
shadow: rgb(0,0,0);
|
||||
|
||||
highlight: #252458;
|
||||
highlightText: #FFFFFF;
|
||||
|
||||
link: #605ee6;
|
||||
linkVisited: #605ee6;
|
||||
}
|
||||
|
||||
OBSTheme::disabled {
|
||||
text: #484848;
|
||||
buttonText: #484848;
|
||||
brightText: #484848;
|
||||
}
|
||||
|
||||
OBSTheme::inactive {
|
||||
highlight: rgb(48,47,48);
|
||||
highlightText: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
/* General style, we override only what is needed. */
|
||||
QWidget {
|
||||
background-color: #181819;
|
||||
|
|
|
@ -28,6 +28,44 @@
|
|||
/* rgb(42,130,218); /* blue */
|
||||
|
||||
|
||||
/* Custom theme information. This will set the application's QPalette, as
|
||||
* well as pass to QML via the OBSTheme object.
|
||||
* Can also use OBSTheme::disabled, OBSTheme::active, and OBSTheme::inactive.
|
||||
* Using it without will set all three (making 'active' a bit redundant) */
|
||||
OBSTheme {
|
||||
window: rgb(58,57,58); /* dark */
|
||||
windowText: rgb(225,224,225); /* veryLight */
|
||||
base: rgb(31,30,31); /* veryDark */
|
||||
alternateBase: rgb(11,10,11); /* veryVeryDark */
|
||||
text: rgb(225,224,225); /* veryLight */
|
||||
button: rgb(88,87,88); /* kindaDark */
|
||||
buttonText: rgb(225,224,225); /* veryLight */
|
||||
brightText: rgb(200,199,200); /* lighter */
|
||||
|
||||
light: rgb(88,87,88); /* kindaDark */
|
||||
mid: rgb(58,57,58); /* dark */
|
||||
dark: rgb(31,30,31); /* veryDark */
|
||||
shadow: rgb(11,10,11); /* veryVeryDark */
|
||||
|
||||
highlight: rgb(42,130,218); /* blue */
|
||||
highlightText: rgb(0,0,0);
|
||||
|
||||
link: rgb(42,130,218); /* blue */
|
||||
linkVisited: rgb(42,130,218); /* blue */
|
||||
}
|
||||
|
||||
OBSTheme::disabled {
|
||||
text: rgb(200,199,200); /* lighter */
|
||||
buttonText: rgb(200,199,200); /* lighter */
|
||||
brightText: rgb(200,199,200); /* lighter */
|
||||
}
|
||||
|
||||
OBSTheme::inactive {
|
||||
highlight: rgb(48,47,48);
|
||||
highlightText: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
|
||||
/* General style, we override only what is needed. */
|
||||
QWidget {
|
||||
background-color: rgb(58,57,58); /* dark */
|
||||
|
|
|
@ -40,6 +40,44 @@
|
|||
/***************************************************************************/
|
||||
|
||||
|
||||
/************************/
|
||||
/* ---- Main Theme ---- */
|
||||
/************************/
|
||||
|
||||
OBSTheme {
|
||||
window: rgb(49, 54, 59); /* Blue-gray */
|
||||
windowText: rgb(239, 240, 241); /* White */
|
||||
base: rgb(0, 139, 163); /* Dark Cyan (Primary Dark) */
|
||||
alternateBase: rgb(186, 45, 101); /* Dark Pink (Secondary Dark) */
|
||||
text: rgb(239, 240, 241); /* White */
|
||||
button: rgb(0, 188, 212); /* Cyan (Primary) */
|
||||
buttonText: rgb(239, 240, 241); /* White */
|
||||
brightText: rgb(255, 148, 194); /* Light Pink (Secondary Light) */
|
||||
|
||||
light: rgb(162, 161, 162); /* Lighter Gray */
|
||||
mid: rgb(118, 121, 124); /* Light Grey */
|
||||
dark: rgb(84, 87, 91); /* Gray */
|
||||
shadow: rgb(35, 38, 41); /* Dark Gray */
|
||||
|
||||
highlight: rgb(98, 238, 255); /* Light Cyan (Primary Light) */
|
||||
highlightText: rgb(0,0,0);
|
||||
|
||||
link: rgb(98, 238, 255); /* Light Cyan (Primary Light) */
|
||||
linkVisited: rgb(98, 238, 255); /* Light Cyan (Primary Light) */
|
||||
}
|
||||
|
||||
OBSTheme::disabled {
|
||||
text: rgb(255, 148, 194); /* Light Pink (Secondary Light) */
|
||||
buttonText: rgb(255, 148, 194); /* Light Pink (Secondary Light) */
|
||||
brightText: rgb(255, 148, 194); /* Light Pink (Secondary Light) */
|
||||
}
|
||||
|
||||
OBSTheme::inactive {
|
||||
highlight: rgb(0, 188, 212); /* Cyan (Primary) */
|
||||
highlightText: rgb(239, 240, 241); /* White */
|
||||
}
|
||||
|
||||
|
||||
/*************************/
|
||||
/* --- General style --- */
|
||||
/*************************/
|
||||
|
|
194
UI/obs-app.cpp
194
UI/obs-app.cpp
|
@ -24,9 +24,10 @@
|
|||
#include <sstream>
|
||||
#include <mutex>
|
||||
#include <util/bmem.h>
|
||||
#include <util/dstr.h>
|
||||
#include <util/dstr.hpp>
|
||||
#include <util/platform.h>
|
||||
#include <util/profiler.hpp>
|
||||
#include <util/cf-parser.h>
|
||||
#include <obs-config.h>
|
||||
#include <obs.hpp>
|
||||
|
||||
|
@ -782,6 +783,192 @@ bool OBSApp::InitLocale()
|
|||
return true;
|
||||
}
|
||||
|
||||
void OBSApp::AddExtraThemeColor(QPalette &pal, int group,
|
||||
const char *name, uint32_t color)
|
||||
{
|
||||
std::function<void(QPalette::ColorGroup)> func;
|
||||
|
||||
#define DEF_PALETTE_ASSIGN(name) \
|
||||
do { \
|
||||
func = [&] (QPalette::ColorGroup group) \
|
||||
{ \
|
||||
pal.setColor(group, QPalette::name, \
|
||||
QColor::fromRgb(color)); \
|
||||
}; \
|
||||
} while (false)
|
||||
|
||||
if (astrcmpi(name, "alternateBase") == 0) {
|
||||
DEF_PALETTE_ASSIGN(AlternateBase);
|
||||
} else if (astrcmpi(name, "base") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Base);
|
||||
} else if (astrcmpi(name, "brightText") == 0) {
|
||||
DEF_PALETTE_ASSIGN(BrightText);
|
||||
} else if (astrcmpi(name, "button") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Button);
|
||||
} else if (astrcmpi(name, "buttonText") == 0) {
|
||||
DEF_PALETTE_ASSIGN(ButtonText);
|
||||
} else if (astrcmpi(name, "brightText") == 0) {
|
||||
DEF_PALETTE_ASSIGN(BrightText);
|
||||
} else if (astrcmpi(name, "dark") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Dark);
|
||||
} else if (astrcmpi(name, "highlight") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Highlight);
|
||||
} else if (astrcmpi(name, "highlightedText") == 0) {
|
||||
DEF_PALETTE_ASSIGN(HighlightedText);
|
||||
} else if (astrcmpi(name, "light") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Light);
|
||||
} else if (astrcmpi(name, "link") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Link);
|
||||
} else if (astrcmpi(name, "linkVisited") == 0) {
|
||||
DEF_PALETTE_ASSIGN(LinkVisited);
|
||||
} else if (astrcmpi(name, "mid") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Mid);
|
||||
} else if (astrcmpi(name, "midlight") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Midlight);
|
||||
} else if (astrcmpi(name, "shadow") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Shadow);
|
||||
} else if (astrcmpi(name, "text") == 0 ||
|
||||
astrcmpi(name, "foreground") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Text);
|
||||
} else if (astrcmpi(name, "toolTipBase") == 0) {
|
||||
DEF_PALETTE_ASSIGN(ToolTipBase);
|
||||
} else if (astrcmpi(name, "toolTipText") == 0) {
|
||||
DEF_PALETTE_ASSIGN(ToolTipText);
|
||||
} else if (astrcmpi(name, "windowText") == 0) {
|
||||
DEF_PALETTE_ASSIGN(WindowText);
|
||||
} else if (astrcmpi(name, "window") == 0 ||
|
||||
astrcmpi(name, "background") == 0) {
|
||||
DEF_PALETTE_ASSIGN(Window);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
#undef DEF_PALETTE_ASSIGN
|
||||
|
||||
switch (group) {
|
||||
case QPalette::Disabled:
|
||||
case QPalette::Active:
|
||||
case QPalette::Inactive:
|
||||
func((QPalette::ColorGroup)group);
|
||||
break;
|
||||
default:
|
||||
func((QPalette::ColorGroup)QPalette::Disabled);
|
||||
func((QPalette::ColorGroup)QPalette::Active);
|
||||
func((QPalette::ColorGroup)QPalette::Inactive);
|
||||
}
|
||||
}
|
||||
|
||||
struct CFParser {
|
||||
cf_parser cfp = {};
|
||||
inline ~CFParser() {cf_parser_free(&cfp);}
|
||||
inline operator cf_parser*() {return &cfp;}
|
||||
inline cf_parser *operator->() {return &cfp;}
|
||||
};
|
||||
|
||||
void OBSApp::ParseExtraThemeData(const char *path)
|
||||
{
|
||||
BPtr<char> data = os_quick_read_utf8_file(path);
|
||||
QPalette pal = palette();
|
||||
CFParser cfp;
|
||||
int ret;
|
||||
|
||||
cf_parser_parse(cfp, data, path);
|
||||
|
||||
while (cf_go_to_token(cfp, "OBSTheme", nullptr)) {
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
int group = -1;
|
||||
|
||||
if (cf_token_is(cfp, ":")) {
|
||||
ret = cf_next_token_should_be(cfp, ":", nullptr,
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
if (cf_token_is(cfp, "disabled")) {
|
||||
group = QPalette::Disabled;
|
||||
} else if (cf_token_is(cfp, "active")) {
|
||||
group = QPalette::Active;
|
||||
} else if (cf_token_is(cfp, "inactive")) {
|
||||
group = QPalette::Inactive;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cf_next_token(cfp)) return;
|
||||
}
|
||||
|
||||
if (!cf_token_is(cfp, "{")) continue;
|
||||
|
||||
for (;;) {
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
ret = cf_token_is_type(cfp, CFTOKEN_NAME, "name",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS)
|
||||
break;
|
||||
|
||||
DStr name;
|
||||
dstr_copy_strref(name, &cfp->cur_token->str);
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ":", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
const char *array;
|
||||
uint32_t color = 0;
|
||||
|
||||
if (cf_token_is(cfp, "#")) {
|
||||
array = cfp->cur_token->str.array;
|
||||
color = strtol(array + 1, nullptr, 16);
|
||||
|
||||
} else if (cf_token_is(cfp, "rgb")) {
|
||||
ret = cf_next_token_should_be(cfp, "(", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10) << 16;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ",", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10) << 8;
|
||||
|
||||
ret = cf_next_token_should_be(cfp, ",", ";",
|
||||
nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
if (!cf_next_token(cfp)) return;
|
||||
|
||||
array = cfp->cur_token->str.array;
|
||||
color |= strtol(array, nullptr, 10);
|
||||
|
||||
} else if (cf_token_is(cfp, "white")) {
|
||||
color = 0xFFFFFF;
|
||||
|
||||
} else if (cf_token_is(cfp, "black")) {
|
||||
color = 0;
|
||||
}
|
||||
|
||||
if (!cf_go_to_token(cfp, ";", nullptr)) return;
|
||||
|
||||
AddExtraThemeColor(pal, group, name->array, color);
|
||||
}
|
||||
|
||||
ret = cf_token_should_be(cfp, "}", "}", nullptr);
|
||||
if (ret != PARSE_SUCCESS) continue;
|
||||
}
|
||||
|
||||
setPalette(pal);
|
||||
}
|
||||
|
||||
bool OBSApp::SetTheme(std::string name, std::string path)
|
||||
{
|
||||
theme = name;
|
||||
|
@ -803,12 +990,17 @@ bool OBSApp::SetTheme(std::string name, std::string path)
|
|||
}
|
||||
|
||||
QString mpath = QString("file:///") + path.c_str();
|
||||
setPalette(defaultPalette);
|
||||
setStyleSheet(mpath);
|
||||
ParseExtraThemeData(path.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OBSApp::InitTheme()
|
||||
{
|
||||
defaultPalette = palette();
|
||||
|
||||
const char *themeName = config_get_string(globalConfig, "General",
|
||||
"CurrentTheme");
|
||||
if (!themeName) {
|
||||
|
|
|
@ -87,6 +87,12 @@ private:
|
|||
|
||||
inline void ResetHotkeyState(bool inFocus);
|
||||
|
||||
QPalette defaultPalette;
|
||||
|
||||
void ParseExtraThemeData(const char *path);
|
||||
void AddExtraThemeColor(QPalette &pal, int group,
|
||||
const char *name, uint32_t color);
|
||||
|
||||
public:
|
||||
OBSApp(int &argc, char **argv, profiler_name_store_t *store);
|
||||
~OBSApp();
|
||||
|
|
Loading…
Reference in a new issue