浏览代码

UI: Add new theme, update theme capabilities

I have always felt that the out of the box themes for OBS were quite
lacking, and have spent a lot of time going through and sorting out the
difficulties with the current setup. I've added a new themeID parameter to
several elements that were otherwise impossible to target with QSS in a
theme. Since Qt has pushed for the use of QML over QSS at this point,
these should be considered workarounds. Included is the theme I was
working on that can serve as a base. I'm hoping to encourage others to
make their own themes, so we can grow the available themes for OBS.

I am happy for any feedback on the theme itself, or other updates that
can me made to make creating new themes easier overall.
Joel Bethke 8 年之前
父节点
当前提交
432e285257

+ 1021 - 0
UI/data/themes/Rachni.qss

@@ -0,0 +1,1021 @@
+/***************************************************************************/
+/*   Copyright (C) 2017 by Joel Bethke <[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  */
+/*   the Free Software Foundation, either version 2 of the License, or     */
+/*   (at your option) any later version.                                   */
+/*                                                                         */
+/*   This program is distributed in the hope that it will be useful,       */
+/*   but WITHOUT ANY WARRANTY; without even the implied warranty of        */
+/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
+/*   GNU General Public License for more details.                          */
+/*                                                                         */
+/*   You should have received a copy of the GNU General Public License     */
+/*   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+/*                                                                         */
+/* ======================================================================= */
+
+/* =========================== Color Palette ============================= */
+/*                                                                         */
+/* rgb(49, 54, 59)      - Blue-gray (Main Background)                      */
+/* rgb(58, 64, 69);     - Light Blue-gray                                  */
+/*                                                                         */
+/* rgb(239, 240, 241)   - "White"                                          */
+/*                                                                         */
+/* rgb(162, 161, 162)   - Lighter Gray                                     */
+/* rgb(118, 121, 124)   - Light Grey                                       */
+/* rgb(84, 87, 91)      - Gray                                             */
+/* rgb(35, 38, 41)      - Dark Gray                                        */
+/*                                                                         */
+/* rgb(0, 188, 212)     - Cyan (Primary)                                   */
+/* rgb(98, 238, 255)    - Light Cyan (Primary Light - unused)              */
+/* rgb(0, 139, 163)     - Dark Cyan (Primary Dark)                         */
+/*                                                                         */
+/* rgb(240, 98, 146)    - Pink (Secondary)                                 */
+/* rgb(255, 148, 194)   - Light Pink (Secondary Light)                     */
+/* rgb(186, 45, 101)    - Dark Pink (Secondary Dark)                       */
+/*                                                                         */
+/***************************************************************************/
+
+
+/*************************/
+/* --- General style --- */
+/*************************/
+
+QMainWindow,
+QDialog,
+QWidget {
+	background-color: rgb(49, 54, 59); /* Blue-gray */
+	color: rgb(239, 240, 241); /* White */
+	selection-background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+	selection-color: rgb(239, 240, 241); /* White */
+	outline: none;
+	font-family: Noto Sans, Tahoma;
+	font-size: 11px;
+}
+
+QWidget::disabled {
+	color: 2px solid rgba(255, 148, 194, 0.25); /* Light Pink (Secondary Light) */
+}
+
+QWidget:item:hover {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+	color: rgb(118, 121, 124); /* Light Gray */
+}
+
+QComboBox:hover,
+QAbstractSpinBox:hover,
+QLineEdit:hover,
+QTextEdit:hover,
+QPlainTextEdit:hover,
+QAbstractView:hover,
+QTreeView:hover {
+	border: 1px solid rgb(0, 188, 212); /* Cyan (Primary) */
+	color: rgb(239, 240, 241); /* White */
+}
+
+QSizeGrip {
+	image: url(./Rachni/sizegrip.png);
+	width: 12px;
+	height: 12px;
+}
+
+/***********************/
+/* --- List widget --- */
+/***********************/
+
+QListWidget::item:selected:!active {
+	color: rgb(239, 240, 241); /* White */
+	background-color: rgba(255, 148, 194, 0.25); /* Light Pink (Secondary Light) */
+	border: none;
+}
+
+QListWidget::item:selected {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border: none;
+}
+
+QListWidget::item:hover,
+QListWidget::item:disabled:hover,
+QListWidget::item:hover:!active {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+	color: rgb(239, 240, 241); /* White */
+	border: none;
+}
+
+
+/***********************/
+/* --- Group Boxes --- */
+/***********************/
+
+QGroupBox {
+	font-size: 13px;
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	border-radius: 2px;
+	padding-top: 16px;
+	margin-top: 20px;
+}
+
+QGroupBox::title {
+	color: rgb(240, 98, 146); /* Pink (Secondary) */
+	left: 20px;
+	padding-left: 5px;
+	padding-right: 4px;
+	padding-top: -14px;
+}
+
+/*****************/
+/* --- Menus --- */
+/*****************/
+
+QMenuBar {
+	background-color: rgb(49, 54, 59); /* Blue-gray */
+	color: rgb(239, 240, 241); /* White */
+}
+
+QMenuBar::item {
+	background: transparent;
+}
+
+QMenuBar::item:selected {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border-radius: 1px;
+}
+
+QMenuBar::item:pressed {
+	border: none;
+	background-color: rgb(0, 188, 212);
+	margin-bottom: -1px;
+	padding-bottom: 1px;
+}
+
+/**********************/
+/* --- ScrollBars --- */
+/**********************/
+
+QScrollBar:horizontal {
+	height: 15px;
+	margin: 3px 15px 3px 15px;
+	border: 1px transparent;
+	border-radius: 4px;
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+}
+
+QScrollBar::handle:horizontal {
+	background-color: rgb(118, 121, 124); /* Light Gray */
+	min-width: 5px;
+	border-radius: 4px;
+}
+
+QScrollBar::add-line:horizontal {
+	margin: 0 3px 0 3px;
+	border-image: url(./Rachni/right_arrow_disabled.png);
+	width: 10px;
+	height: 10px;
+	subcontrol-position: right;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal {
+	margin: 0 3px 0 3px;
+	border-image: url(./Rachni/left_arrow_disabled.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: left;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:horizontal:hover,
+QScrollBar::add-line:horizontal:on {
+	border-image: url(./Rachni/right_arrow.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: right;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:horizontal:hover,
+QScrollBar::sub-line:horizontal:on {
+	border-image: url(./Rachni/left_arrow.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: left;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:horizontal,
+QScrollBar::down-arrow:horizontal {
+	background: none;
+}
+
+QScrollBar::add-page:horizontal,
+QScrollBar::sub-page:horizontal {
+	background: none;
+}
+
+QScrollBar:vertical {
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+	width: 15px;
+	margin: 15px 3px 15px 3px;
+	border: 1px transparent;
+	border-radius: 4px;
+}
+
+QScrollBar::handle:vertical {
+	background-color: rgb(118, 121, 124); /* Light Gray */
+	min-height: 5px;
+	border-radius: 4px;
+}
+
+QScrollBar::sub-line:vertical {
+	margin: 3px 0 3px 0;
+	border-image: url(./Rachni/up_arrow_disabled.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: top;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:vertical {
+	margin: 3px 0 3px 0;
+	border-image: url(./Rachni/down_arrow_disabled.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: bottom;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::sub-line:vertical:hover,
+QScrollBar::sub-line:vertical:on {
+	border-image: url(./Rachni/up_arrow.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: top;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::add-line:vertical:hover,
+QScrollBar::add-line:vertical:on {
+	border-image: url(./Rachni/down_arrow.png);
+	height: 10px;
+	width: 10px;
+	subcontrol-position: bottom;
+	subcontrol-origin: margin;
+}
+
+QScrollBar::up-arrow:vertical,
+QScrollBar::down-arrow:vertical {
+	background: none;
+}
+
+QScrollBar::add-page:vertical,
+QScrollBar::sub-page:vertical {
+	background: none;
+}
+
+/***********************/
+/* --- Tab Widgets --- */
+/***********************/
+
+QTabWidget {
+	border: none;
+}
+
+QTabWidget::pane {
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	padding: 5px;
+	margin: 0;
+}
+
+QTabWidget::tab-bar {
+	left: 5px;
+}
+
+/********************/
+/* --- Tab Bars --- */
+/********************/
+
+QTabBar {
+	qproperty-drawBase: 0;
+	border-radius: 3px;
+}
+
+QTabBar:focus {
+	border: none;
+}
+
+QTabBar::close-button {
+	image: url(./Rachni/close.png);
+	background: transparent;
+}
+
+QTabBar::close-button:hover {
+	image: url(./Rachni/close-hover.png);
+	background: transparent;
+}
+
+QTabBar::close-button:pressed {
+	image: url(:./Rachni/close-pressed.png);
+	background: transparent;
+}
+
+QTabBar::tab {
+	color: rgb(239, 240, 241); /* White */
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	border-bottom: 1px transparent;
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	padding: 5px;
+	min-width: 50px;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 2px;
+}
+
+QTabBar::tab:!selected {
+	color: rgb(239, 240, 241); /* White */
+	background-color: rgb(84, 87, 91); /* Gray */
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	border-bottom: 1px transparent;
+	border-top-left-radius: 2px;
+	border-top-right-radius: 2px;
+}
+
+QTabBar::tab:!selected:hover {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+}
+
+/********************/
+/* --- Toolbars --- */
+/********************/
+
+QToolBar {
+	background-color: rgb(49, 54, 59); /* Blue-gray */
+	border: none;
+}
+
+QToolButton:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border-radius: 2px;
+}
+
+QToolButton:pressed {
+	background-color: rgb(240, 98, 146); /* Pink (Secondary) */
+	border-radius: 2px;
+}
+
+* [themeID="addIconSmall"] {
+	qproperty-icon: url(./Dark/plus.png);
+}
+
+* [themeID="removeIconSmall"] {
+	qproperty-icon: url(./Dark/minus.png);
+}
+
+* [themeID="propertiesIconSmall"] {
+	qproperty-icon: url(./Dark/cogwheel.png);
+}
+
+* [themeID="configIconSmall"] {
+	qproperty-icon: url(./Dark/cogwheel.png);
+}
+
+* [themeID="upArrowIconSmall"] {
+	qproperty-icon: url(./Dark/up_arrow.png);
+}
+
+* [themeID="downArrowIconSmall"] {
+	qproperty-icon: url(./Dark/down_arrow.png);
+}
+
+/***********************/
+/* --- Combo boxes --- */
+/***********************/
+
+QComboBox {
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	border-radius: 2px;
+	padding: 5px;
+	min-width: 75px;
+}
+
+QComboBox:on {
+	padding-top: 3px;
+	padding-left: 4px;
+}
+
+QComboBox QAbstractItemView {
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+	border-radius: 2px;
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+}
+
+QComboBox::drop-down {
+	subcontrol-origin: padding;
+	subcontrol-position: top right;
+	width: 15px;
+
+	border-left-width: 0;
+	border-left-color: rgb(169, 169, 169);
+	border-left-style: solid;
+	border-top-right-radius: 3px;
+	border-bottom-right-radius: 3px;
+}
+
+QComboBox::down-arrow,
+QComboBox::down-arrow:pressed,
+QComboBox::down-arrow:focus {
+	image: url(./Rachni/down_arrow_disabled.png);
+}
+
+QComboBox::down-arrow:on,
+QComboBox::down-arrow:hover {
+	image: url(./Rachni/down_arrow.png);
+}
+
+/*********************/
+/* --- Spinboxes --- */
+/*********************/
+
+QAbstractSpinBox {
+	padding: 5px;
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+	color: rgb(239, 240, 241); /* White */
+	border-radius: 2px;
+	min-width: 75px;
+}
+
+QAbstractSpinBox:up-button {
+	background-color: transparent;
+	subcontrol-origin: border;
+	subcontrol-position: top right;
+}
+
+QAbstractSpinBox:down-button {
+	background-color: transparent;
+	subcontrol-origin: border;
+	subcontrol-position: bottom right;
+}
+
+QAbstractSpinBox::up-arrow,
+QAbstractSpinBox::up-arrow:disabled,
+QAbstractSpinBox::up-arrow:off {
+	image: url(./Rachni/up_arrow_disabled.png);
+	width: 10px;
+	height: 10px;
+}
+
+QAbstractSpinBox::up-arrow:hover {
+	image: url(./Rachni/up_arrow.png);
+}
+
+QAbstractSpinBox::down-arrow,
+QAbstractSpinBox::down-arrow:disabled,
+QAbstractSpinBox::down-arrow:off {
+	image: url(./Rachni/down_arrow_disabled.png);
+	width: 10px;
+	height: 10px;
+}
+
+QAbstractSpinBox::down-arrow:hover {
+	image: url(./Rachni/down_arrow.png);
+}
+
+/**********************/
+/* --- Line edits --- */
+/**********************/
+
+QLineEdit {
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+	padding: 5px;
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	border-radius: 2px;
+	color: rgb(239, 240, 241); /* White */
+}
+
+/**********************/
+/* --- Checkboxes --- */
+/**********************/
+
+QCheckBox {
+	spacing: 5px;
+	outline: none;
+	color: rgb(239, 240, 241); /* White */
+	margin-bottom: 2px;
+}
+
+QCheckBox:hover, QCheckBox:focus {
+	color: rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+QCheckBox:disabled {
+	color: rgb(118, 121, 124); /* Light Gray */
+}
+
+QCheckBox::indicator,
+QGroupBox::indicator {
+	width: 18px;
+	height: 18px;
+}
+
+QGroupBox::indicator {
+	margin-left: 2px;
+}
+
+QCheckBox::indicator:unchecked {
+	image: url(./Rachni/checkbox_unchecked.png);
+}
+
+QCheckBox::indicator:unchecked:hover,
+QGroupBox::indicator:unchecked:hover {
+	border: none;
+	image: url(./Rachni/checkbox_unchecked_focus.png);
+}
+
+QCheckBox::indicator:checked {
+	image: url(./Rachni/checkbox_checked.png);
+}
+
+QCheckBox::indicator:checked:hover,
+QGroupBox::indicator:checked:hover {
+	border: none;
+	image: url(./Rachni/checkbox_checked_focus.png);
+}
+
+QCheckBox::indicator:checked:disabled,
+QGroupBox::indicator:checked:disabled {
+	image: url(./Rachni/checkbox_checked_disabled.png);
+}
+
+QCheckBox::indicator:unchecked:disabled,
+QGroupBox::indicator:unchecked:disabled {
+	image: url(./Rachni/checkbox_unchecked_disabled.png);
+}
+
+/***********************/
+/* --- Radio boxes --- */
+/***********************/
+
+QRadioButton {
+	spacing: 5px;
+	outline: none;
+	color: rgb(239, 240, 241); /* White */
+	margin-bottom: 2px;
+}
+
+QRadioButton:disabled {
+	color: rgb(118, 121, 124); /* Light Gray */
+}
+
+QRadioButton::indicator {
+	width: 21px;
+	height: 21px;
+}
+
+QRadioButton::indicator:unchecked {
+	image: url(./Rachni/radio_unchecked.png);
+}
+
+
+QRadioButton::indicator:unchecked:hover,
+QRadioButton::indicator:unchecked:focus,
+QRadioButton::indicator:unchecked:pressed {
+	border: none;
+	outline: none;
+	image: url(./Rachni/radio_unchecked_focus.png);
+}
+
+QRadioButton::indicator:checked {
+	border: none;
+	outline: none;
+	image: url(./Rachni/radio_checked.png);
+}
+
+QRadioButton::indicator:checked:hover,
+QRadioButton::indicator:checked:focus,
+QRadioButton::indicator:checked:pressed {
+	border: none;
+	outline: none;
+	image: url(./Rachni/radio_checked_focus.png);
+}
+
+QRadioButton::indicator:checked:disabled {
+	outline: none;
+	image: url(./Rachni/radio_checked_disabled.png);
+}
+
+QRadioButton::indicator:unchecked:disabled {
+	image: url(./Rachni/radio_unchecked_disabled.png);
+}
+
+/***************************/
+/* --- Mute Checkboxes --- */
+/***************************/
+
+MuteCheckBox {
+	outline: none;
+}
+
+MuteCheckBox::indicator:checked {
+	image: url(./Dark/mute.png);
+}
+
+MuteCheckBox::indicator:unchecked {
+	image: url(./Dark/unmute.png);
+}
+
+MuteCheckBox::indicator:unchecked:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	image: url(./Dark/unmute.png);
+}
+
+MuteCheckBox::indicator:unchecked:focus {
+	image: url(./Dark/unmute.png);
+}
+MuteCheckBox::indicator:checked:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	image: url(./Dark/mute.png);
+}
+
+MuteCheckBox::indicator:checked:focus {
+	image: url(./Dark/mute.png);
+}
+
+MuteCheckBox::indicator:checked:disabled {
+	image: url(./Dark/mute.png);
+}
+
+MuteCheckBox::indicator:unchecked:disabled {
+	image: url(./Dark/unmute.png);
+}
+
+/*************************/
+/* --- Progress bars --- */
+/*************************/
+
+QProgressBar {
+	border: 2px solid rgb(118, 121, 124); /* Light Gray */
+	border-radius: 5px;
+	text-align: center;
+}
+
+QProgressBar::chunk {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+}
+
+/**************************/
+/* --- Volume Control --- */
+/**************************/
+
+VolumeMeter {
+	qproperty-bkColor: rgb(35, 38, 41); /* Dark Gray */
+	qproperty-magColor: rgb(186, 45, 101); /* Dark Pink (Secondary Dark) */
+	qproperty-peakColor: rgb(240, 98, 146); /* Pink (Secondary) */
+	qproperty-peakHoldColor: rgb(255, 148, 194); /* Light Pink (Secondary Light) */
+}
+
+/*******************/
+/* --- Buttons --- */
+/*******************/
+
+QPushButton {
+	background-color: rgb(0, 188, 212);; /* Cyan (Primary) */
+	color: rgb(239, 240, 241); /* White */
+	border-radius: 2px;
+	border: 1px solid rgb(0, 188, 212); /* Cyan (Primary) */
+	padding: 4px;
+	padding-left: 15px;
+	padding-right: 15px;
+}
+
+QPushButton:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border: 1px solid rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QPushButton:pressed {
+	background-color: rgb(240, 98, 146); /* Pink (Secondary) */
+	border: 1px solid rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+QPushButton:checked:pressed {
+	background-color: rgb(240, 98, 146); /* Pink (Secondary) */
+	border: 1px solid rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+QPushButton:checked {
+	border: 1px solid rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QPushButton:checked:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QPushButton:disabled {
+	background-color: rgb(0, 139, 163); /* Dark Cyan (Primary Dark) */
+	border: 1px solid rgb(0, 139, 163); /* Dark Cyan (Primary Dark) */
+	color: rgb(162, 161, 162); /* Lighter Gray */
+}
+
+
+
+/******************************/
+/* --- Dialog Box Buttons --- */
+/******************************/
+/* These currently match the  */
+/* default button style, but  */
+/* I left this section in as  */
+/* a reference to themers.    */
+/******************************/
+
+QDialogButtonBox QPushButton {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+}
+
+QDialogButtonBox QPushButton:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border: 1px solid rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QDialogButtonBox QPushButton:pressed {
+	background-color: rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+QDialogButtonBox QPushButton:disabled {
+	background-color: rgb(0, 139, 163); /* Dark Cyan (Primary Dark) */
+	border: 1px solid rgb(0, 139, 163); /* Dark Cyan (Primary Dark) */
+	color: rgb(162, 161, 162); /* Lighter Gray */
+}
+
+/*******************************/
+/* --- OBS Main UI Buttons --- */
+/********************************/
+/* This will style the buttons  */
+/* from the main OBS UI apart   */
+/* from the rest of the general */
+/* button styles. Currently     */
+/* these match, but left in for */
+/* reference to new themers.    */
+/********************************/
+
+QPushButton#streamButton,
+QPushButton#recordButton,
+QPushButton[themeID="replayBufferButton"],
+QPushButton#modeSwitch,
+QPushButton#settingsButton,
+QPushButton#exitButton {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+}
+
+QPushButton#recordButton {
+	padding-left: 5px;
+	padding-right: 5px;
+}
+
+QPushButton:hover#streamButton,
+QPushButton:hover#recordButton,
+QPushButton:hover[themeID="replayBufferButton"],
+QPushButton:hover#modeSwitch,
+QPushButton:hover#settingsButton,
+QPushButton:hover#exitButton {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border: 1px solid rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QPushButton:pressed#streamButton,
+QPushButton:pressed#recordButton,
+QPushButton:pressed[themeID="replayBufferButton"],
+QPushButton:pressed#modeSwitch,
+QPushButton:pressed#settingsButton,
+QPushButton:pressed#exitButton {
+	background-color: rgb(240, 98, 146); /* Pink (Secondary) */
+	border: 1px solid rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+QPushButton:checked[themeID="replayBufferButton"],
+QPushButton:checked#modeSwitch {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border: 1px solid rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+/**************************/
+/*  --- Icon Buttons ---  */
+/**************************/
+/* This fixes the issues  */
+/* with the icon buttons  */
+/* sharing the same style */
+/* as other buttons.      */
+/**************************/
+
+QPushButton[themeID="addIconSmall"],
+QPushButton[themeID="removeIconSmall"],
+QPushButton[themeID="configIconSmall"],
+QPushButton#transitionRemove,
+QPushButton#moveAsyncFilterUp,
+QPushButton#moveAsyncFilterDown,
+QPushButton#moveEffectFilterDown,
+QPushButton#moveEffectFilterUp {
+	background-color: rgb(49, 54, 59); /* Blue-gray */
+	border: none;
+}
+
+
+QPushButton:hover[themeID="addIconSmall"],
+QPushButton:hover[themeID="removeIconSmall"],
+QPushButton:hover[themeID="configIconSmall"],
+QPushButton:hover#transitionRemove,
+QPushButton:hover#moveAsyncFilterUp,
+QPushButton:hover#moveAsyncFilterDown,
+QPushButton:hover#moveEffectFilterDown,
+QPushButton:hover#moveEffectFilterUp {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	margin: 0;
+	padding: 0;
+	border-radius: 2px;
+	border: none;
+	outline: none;
+}
+
+/******************************/
+/*   --- Hotkey Buttons ---   */
+/******************************/
+/* Fix for the hotkey buttons */
+/* looking terrible with my   */
+/* color choices.             */
+/******************************/
+
+QPushButton[themeID="hotkeyButtons"] {
+	background-color: rgb(58, 64, 69); /* Light Blue-gray */
+	color: rgb(239, 240, 241); /* White */
+	border-radius: 2px;
+	border: none;
+	margin: 4px;
+	padding-top: 6px;
+	padding-bottom: 6px;
+}
+
+QPushButton:hover[themeID="hotkeyButtons"] {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+	border: 1px solid rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QPushButton:pressed[themeID="hotkeyButtons"] {
+	background-color: rgb(240, 98, 146); /* Pink (Secondary) */
+	border: 1px solid rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+QPushButton:disabled[themeID="hotkeyButtons"] {
+	background-color: rgb(58, 64, 69); /* Light Blue-gray */
+	color: rgb(162, 161, 162); /* Lighter Gray */
+}
+
+/******************/
+/* --- Labels --- */
+/******************/
+
+/* Titles for main UI */
+QLabel#scenesLabel,
+QLabel#sourcesLabel,
+QLabel#mixerLabel,
+QLabel#sceneTransitionsLabel {
+	color: rgb(240, 98, 146); /* Pink (Secondary) */
+	margin-top: 5px;
+}
+
+/* warning and error */
+QLabel#warningLabel {
+	color: rgb(255, 148, 194); /* Light Pink (Secondary Light) */
+	font-weight: bold;
+}
+
+QLabel#errorLabel {
+	color: rgb(186, 45, 101); /* Dark Pink (Secondary Dark) */
+	font-weight: bold;
+}
+
+/****************************/
+/*     --- Splitter ---     */
+/****************************/
+/* This styles the splitter */
+/* object to show a dashed  */
+/* line, indicating that it */
+/* is present and can be    */
+/* adjusted.                */
+/****************************/
+
+QSplitter::handle {
+	border: 1px dashed rgb(118, 121, 124); /* Light Gray */
+}
+
+QSplitter::handle:hover {
+	background-color: rgba(240, 98, 146, 0.5); /* Pink (Secondary) */
+}
+
+QSplitter::handle:horizontal {
+	width: 1px;
+}
+
+QSplitter::handle:vertical {
+	height: 1px;
+}
+
+/*******************************/
+/*       --- Sliders ---       */
+/*******************************/
+/* Not really happy with       */
+/* these, but not sure what    */
+/* else to do. All colors not  */
+/* in the palette for now      */
+/*******************************/
+
+QSlider::groove:horizontal {
+	background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
+	stop: 0 rgb(35, 38, 41), /* Dark Gray */
+	stop: 0.75 rgb(50, 49, 50));
+	height: 4px;
+	border: none;
+	border-radius: 2px;
+}
+
+QSlider::handle:horizontal {
+	background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
+	stop: 0 rgb(240, 239, 240),
+	stop: 0.25 rgb(200, 199, 200),
+	stop: 1 rgb(162, 161, 162));
+	border: 1px solid rgb(58, 57, 58);
+	border-radius: 3px;
+	height: 10px;
+	width: 18px;
+	margin: -3px 0;
+}
+
+QSlider::handle:horizontal:pressed {
+	background-color: QLinearGradient(x1: 0, y1: 1, x2: 0, y2: 0,
+	stop: 0 rgb(240, 239, 240),
+	stop: 0.25 rgb(200, 199, 200),
+	stop: 1 rgb(162, 161, 162));
+}
+
+QSlider::sub-page:horizontal:disabled {
+	background-color: QLinearGradient(x1: 0, y1: 0, x2: 0, y2: 1,
+	stop: 0 rgb(35, 38, 41), /* Dark Gray */
+	stop: 0.75 rgb(50, 49, 50));
+	border-radius: 2px;
+}
+
+QSlider::handle:hover {
+	background-color: rgb(200, 199, 200);
+}
+
+QSlider::sub-page {
+	background-color: rgb(0, 188, 212); /* Cyan (Primary) */
+	border-radius: 2px;
+}
+
+QSlider::handle:disabled {
+	background-color: rgb(122, 121, 122);
+}
+
+/****************/
+/* --- Misc --- */
+/****************/
+
+
+/* Highlight linked hotkeys */
+OBSHotkeyLabel[hotkeyPairHover=true] {
+	color: rgb(240, 98, 146); /* Pink (Secondary) */
+}
+
+/* Workaround so frame borders in dark themes don't look like poop */
+* [frameShape="1"],
+* [frameShape="2"],
+* [frameShape="3"],
+* [frameShape="4"],
+* [frameShape="5"],
+* [frameShape="6"] {
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+}
+
+QFrame[frameShape="0"] {
+	border-radius: 2px;
+	border: 1px transparent;
+}
+
+
+/* Misc style tweaks for dark themes */
+QStatusBar::item {
+	border: none;
+}
+
+QAbstractItemView {
+	background-color: rgb(35, 38, 41); /* Dark Gray */
+}
+
+QToolTip {
+	border: 1px solid rgb(118, 121, 124); /* Light Gray */
+	background-color: rgb(49, 54, 59); /* Blue-gray */
+	color: rgb(240, 98, 146); /* Pink (Secondary) */
+}

二进制
UI/data/themes/Rachni/checkbox_checked.png


二进制
UI/data/themes/Rachni/checkbox_checked_disabled.png


二进制
UI/data/themes/Rachni/checkbox_checked_focus.png


二进制
UI/data/themes/Rachni/checkbox_unchecked.png


二进制
UI/data/themes/Rachni/checkbox_unchecked_disabled.png


二进制
UI/data/themes/Rachni/checkbox_unchecked_focus.png


二进制
UI/data/themes/Rachni/down_arrow.png


二进制
UI/data/themes/Rachni/down_arrow_disabled.png


二进制
UI/data/themes/Rachni/left_arrow.png


二进制
UI/data/themes/Rachni/left_arrow_disabled.png


二进制
UI/data/themes/Rachni/radio_checked.png


二进制
UI/data/themes/Rachni/radio_checked_disabled.png


二进制
UI/data/themes/Rachni/radio_checked_focus.png


二进制
UI/data/themes/Rachni/radio_unchecked.png


二进制
UI/data/themes/Rachni/radio_unchecked_disabled.png


二进制
UI/data/themes/Rachni/radio_unchecked_focus.png


二进制
UI/data/themes/Rachni/right_arrow.png


二进制
UI/data/themes/Rachni/right_arrow_disabled.png


二进制
UI/data/themes/Rachni/sizegrip.png


二进制
UI/data/themes/Rachni/up_arrow.png


二进制
UI/data/themes/Rachni/up_arrow_disabled.png


+ 4 - 0
UI/hotkey-edit.cpp

@@ -272,10 +272,12 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
 	edit->setToolTip(toolTip);
 	edit->setToolTip(toolTip);
 
 
 	auto revert = new QPushButton;
 	auto revert = new QPushButton;
+	revert->setProperty("themeID", "hotkeyButtons");
 	revert->setText(QTStr("Revert"));
 	revert->setText(QTStr("Revert"));
 	revert->setEnabled(false);
 	revert->setEnabled(false);
 
 
 	auto clear = new QPushButton;
 	auto clear = new QPushButton;
+	clear->setProperty("themeID", "hotkeyButtons");
 	clear->setText(QTStr("Clear"));
 	clear->setText(QTStr("Clear"));
 	clear->setEnabled(!obs_key_combination_is_empty(combo));
 	clear->setEnabled(!obs_key_combination_is_empty(combo));
 
 
@@ -287,10 +289,12 @@ void OBSHotkeyWidget::AddEdit(obs_key_combination combo, int idx)
 	});
 	});
 
 
 	auto add = new QPushButton;
 	auto add = new QPushButton;
+	add->setProperty("themeID", "hotkeyButtons");
 	add->setText("+");
 	add->setText("+");
 	add->setMinimumWidth(50);
 	add->setMinimumWidth(50);
 
 
 	auto remove = new QPushButton;
 	auto remove = new QPushButton;
+	remove->setProperty("themeID", "hotkeyButtons");
 	remove->setText("-");
 	remove->setText("-");
 	remove->setEnabled(removeButtons.size() > 0);
 	remove->setEnabled(removeButtons.size() > 0);
 	remove->setMinimumWidth(50);
 	remove->setMinimumWidth(50);

+ 5 - 0
UI/properties-view.cpp

@@ -296,6 +296,7 @@ void OBSPropertiesView::AddPath(obs_property_t *prop, QFormLayout *layout,
 		button->setEnabled(false);
 		button->setEnabled(false);
 	}
 	}
 
 
+	button->setProperty("themeID", "settingsButtons");
 	edit->setText(QT_UTF8(val));
 	edit->setText(QT_UTF8(val));
 	edit->setReadOnly(true);
 	edit->setReadOnly(true);
 	edit->setToolTip(QT_UTF8(obs_property_long_description(prop)));
 	edit->setToolTip(QT_UTF8(obs_property_long_description(prop)));
@@ -610,6 +611,7 @@ QWidget *OBSPropertiesView::AddButton(obs_property_t *prop)
 	const char *desc = obs_property_description(prop);
 	const char *desc = obs_property_description(prop);
 
 
 	QPushButton *button = new QPushButton(QT_UTF8(desc));
 	QPushButton *button = new QPushButton(QT_UTF8(desc));
+	button->setProperty("themeID", "settingsButtons");
 	button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 	button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
 	return NewWidget(prop, button, SIGNAL(clicked()));
 	return NewWidget(prop, button, SIGNAL(clicked()));
 }
 }
@@ -628,6 +630,7 @@ void OBSPropertiesView::AddColor(obs_property_t *prop, QFormLayout *layout,
 		colorLabel->setEnabled(false);
 		colorLabel->setEnabled(false);
 	}
 	}
 
 
+	button->setProperty("themeID", "settingsButtons");
 	button->setText(QTStr("Basic.PropertiesWindow.SelectColor"));
 	button->setText(QTStr("Basic.PropertiesWindow.SelectColor"));
 	button->setToolTip(QT_UTF8(obs_property_long_description(prop)));
 	button->setToolTip(QT_UTF8(obs_property_long_description(prop)));
 
 
@@ -698,6 +701,7 @@ void OBSPropertiesView::AddFont(obs_property_t *prop, QFormLayout *layout,
 	font = fontLabel->font();
 	font = fontLabel->font();
 	MakeQFont(font_obj, font, true);
 	MakeQFont(font_obj, font, true);
 
 
+	button->setProperty("themeID", "settingsButtons");
 	button->setText(QTStr("Basic.PropertiesWindow.SelectFont"));
 	button->setText(QTStr("Basic.PropertiesWindow.SelectFont"));
 	button->setToolTip(QT_UTF8(obs_property_long_description(prop)));
 	button->setToolTip(QT_UTF8(obs_property_long_description(prop)));
 
 
@@ -1795,6 +1799,7 @@ public:
 		if (browse) {
 		if (browse) {
 			QPushButton *browseButton =
 			QPushButton *browseButton =
 				new QPushButton(QTStr("Browse"));
 				new QPushButton(QTStr("Browse"));
+			browseButton->setProperty("themeID", "settingsButtons");
 			topLayout->addWidget(browseButton);
 			topLayout->addWidget(browseButton);
 			topLayout->setAlignment(browseButton, Qt::AlignVCenter);
 			topLayout->setAlignment(browseButton, Qt::AlignVCenter);
 
 

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

@@ -1213,6 +1213,7 @@ void OBSBasic::ResetOutputs()
 					this,
 					this,
 					&OBSBasic::ReplayBufferClicked);
 					&OBSBasic::ReplayBufferClicked);
 
 
+			replayBufferButton->setProperty("themeID", "replayBufferButton");
 			ui->buttonsVLayout->insertWidget(2, replayBufferButton);
 			ui->buttonsVLayout->insertWidget(2, replayBufferButton);
 		}
 		}