view src/gui/theme.cc @ 337:a7d4e5107531

dep/animone: REFACTOR ALL THE THINGS 1: animone now has its own syntax divergent from anisthesia, making different platforms actually have their own sections 2: process names in animone are now called `comm' (this will probably break things). this is what its called in bsd/linux so I'm just going to use it everywhere 3: the X11 code now checks for the existence of a UTF-8 window title and passes it if available 4: ANYTHING THATS NOT LINUX IS 100% UNTESTED AND CAN AND WILL BREAK! I still actually need to test the bsd code. to be honest I'm probably going to move all of the bsds into separate files because they're all essentially different operating systems at this point
author Paper <paper@paper.us.eu.org>
date Wed, 19 Jun 2024 12:51:15 -0400
parents 91ac90a34003
children c844f8bb87ce
line wrap: on
line source

#include "core/config.h"
#include "core/session.h"
#include "gui/theme.h"
#include <QApplication>
#include <QDebug>
#include <QFile>
#include <QStyleFactory>
#include <QTextStream>
#include <QStyle>
#include <QtGlobal>
#ifdef MACOSX
#	include "sys/osx/dark_theme.h"
#elif defined(WIN32)
#	include "sys/win32/dark_theme.h"
#else
#	ifdef GLIB
#		include "sys/glib/dark_theme.h"
#	endif
#endif

/* Weird quirks of this implementation:
 *   1. Dark mode stuff in Qt changes a lot and Qt 5 and Qt 6 are massively different
 *   2. Some widgets, i.e. QTabWidget, QTabBar, etc., just completely IGNORE the QPalette setting
 *      on different platforms and the only way to fix it is by using Fusion
 *   3. Windows dark mode support in Qt 6.5 (with Fusion) is completely unavoidable
 */

namespace Theme {

ThemeManager::ThemeManager(Theme theme) {
	this->theme = theme;
}

Theme ThemeManager::GetTheme() const {
	return theme;
}

bool ThemeManager::IsInDarkTheme() const {
	switch (theme) {
		case Theme::Default:
#ifdef MACOSX
			if (osx::DarkThemeAvailable())
				return osx::IsInDarkTheme();
#elif defined(WIN32)
			if (win32::DarkThemeAvailable())
				return win32::IsInDarkTheme();
#else
#	ifdef GLIB
			return glib::IsInDarkTheme();
#	endif
#endif
		default: break;
	}
	return (theme == Theme::Dark);
}

void ThemeManager::SetToDarkTheme() {
	/* macOS >= 10.14 has its own global dark theme,
	   use it :) */
#ifdef MACOSX
	if (osx::DarkThemeAvailable())
		osx::SetToDarkTheme();
	else
#elif defined(WIN32)
	if (win32::DarkThemeAvailable())
		win32::SetTitleBarsToBlack(true);
#endif
		SetStyleSheet(Theme::Dark);
}

void ThemeManager::SetToLightTheme() {
#ifdef MACOSX
	if (osx::DarkThemeAvailable())
		osx::SetToLightTheme();
	else
#elif defined(WIN32)
	if (win32::DarkThemeAvailable())
		win32::SetTitleBarsToBlack(false);
#endif
		SetStyleSheet(Theme::Light);
}

Theme ThemeManager::GetCurrentOSTheme() const {
	return IsInDarkTheme() ? Theme::Dark : Theme::Light;
}

/* this function is private, and should stay that way */
void ThemeManager::SetStyleSheet(Theme theme) {
	switch (theme) {
		case Theme::Dark: {
			const QColor darkGray(53, 53, 53);
			const QColor gray(128, 128, 128);
			const QColor black(25, 25, 25);
			const QColor blue(42, 130, 218);

			QPalette pal;

			pal.setColor(QPalette::Window, darkGray);
			pal.setColor(QPalette::WindowText, Qt::white);
			pal.setColor(QPalette::Base, black);
			pal.setColor(QPalette::AlternateBase, darkGray);
			pal.setColor(QPalette::ToolTipBase, blue);
			pal.setColor(QPalette::ToolTipText, Qt::white);
			pal.setColor(QPalette::Text, Qt::white);
			pal.setColor(QPalette::Button, darkGray);
			pal.setColor(QPalette::ButtonText, Qt::white);
			pal.setColor(QPalette::Link, blue);
			pal.setColor(QPalette::Highlight, blue);
			pal.setColor(QPalette::HighlightedText, Qt::black);

			pal.setColor(QPalette::Active, QPalette::Button, gray.darker());
			pal.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
			pal.setColor(QPalette::Disabled, QPalette::WindowText, gray);
			pal.setColor(QPalette::Disabled, QPalette::Text, gray);
			pal.setColor(QPalette::Disabled, QPalette::Light, darkGray);

			qApp->setPalette(pal);

#ifdef WIN32
			qApp->setStyleSheet([] {
				QFile f(":/dark.qss");
				if (!f.exists())
					return QStringLiteral("");
				f.open(QFile::ReadOnly | QFile::Text);
				QTextStream ts(&f);
				return ts.readAll();
			}());
#endif
			break;
		}
		default:
			/* this sucks */
			QPalette pal(QApplication::style()->standardPalette());
#ifdef WIN32 /* fuck you Qt 6 */
			pal.setColor(QPalette::Window, QColor(0xF0, 0xF0, 0xF0));
#endif
			qApp->setPalette(pal);

			qApp->setStyleSheet("");
			break;
	}
}

void ThemeManager::SetTheme(Theme theme) {
	switch (theme) {
		case Theme::Light: SetToLightTheme(); break;
		case Theme::Dark: SetToDarkTheme(); break;
		case Theme::Default:
			if (GetCurrentOSTheme() == Theme::Light)
				SetToLightTheme();
			else
				SetToDarkTheme();
			break;
	}
	this->theme = theme;
}

void ThemeManager::RepaintCurrentTheme() {
	SetTheme(theme);
}

} // namespace Theme