support arbitrary color schemes in ollie-gui

Scan ~/.local/share/color-schemes/ in addition to /usr/share/color-schemes/
so user-installed themes (e.g. Catppuccin) are discovered. Mode is now any
scheme name rather than just system/light/dark. Settings dialog uses a
ComboBox listing all available schemes plus "System".
This commit is contained in:
Levi Neely 2026-07-16 06:08:41 +02:00
parent fcc3cd2313
commit 7b8fa5eca4
4 changed files with 62 additions and 66 deletions

View File

@ -48,31 +48,21 @@ ApplicationWindow {
font.bold: true
}
Label {
text: "Uses KDE Breeze color schemes"
opacity: 0.6
wrapMode: Text.Wrap
ComboBox {
id: schemeCombo
Layout.fillWidth: true
font.pixelSize: Qt.application.font.pixelSize * 0.9
}
ColumnLayout {
spacing: 8
RadioButton {
text: "Use system theme"
checked: theme.mode === "system"
onClicked: theme.mode = "system"
model: ["System"].concat(theme.availableSchemes)
currentIndex: {
if (theme.mode === "system") return 0
var idx = theme.availableSchemes.indexOf(theme.mode)
return idx >= 0 ? idx + 1 : 0
}
RadioButton {
text: "Breeze Light"
checked: theme.mode === "light"
onClicked: theme.mode = "light"
}
RadioButton {
text: "Breeze Dark"
checked: theme.mode === "dark"
onClicked: theme.mode = "dark"
onActivated: {
if (currentIndex === 0) {
theme.mode = "system"
} else {
theme.mode = theme.availableSchemes[currentIndex - 1]
}
}
}

View File

@ -51,34 +51,21 @@ ApplicationWindow {
font.bold: true
}
Label {
text: "Uses KDE Breeze color schemes from /usr/share/color-schemes/"
opacity: 0.6
wrapMode: Text.Wrap
ComboBox {
id: schemeCombo
Layout.fillWidth: true
font.pixelSize: Qt.application.font.pixelSize * 0.9
}
ColumnLayout {
spacing: 8
RadioButton {
id: systemRadio
text: "Use system theme"
checked: theme.mode === "system"
onClicked: theme.mode = "system"
model: ["System"].concat(theme.availableSchemes)
currentIndex: {
if (theme.mode === "system") return 0
let idx = theme.availableSchemes.indexOf(theme.mode)
return idx >= 0 ? idx + 1 : 0
}
RadioButton {
id: lightRadio
text: "Breeze Light"
checked: theme.mode === "light"
onClicked: theme.mode = "light"
}
RadioButton {
id: darkRadio
text: "Breeze Dark"
checked: theme.mode === "dark"
onClicked: theme.mode = "dark"
onActivated: {
if (currentIndex === 0) {
theme.mode = "system"
} else {
theme.mode = theme.availableSchemes[currentIndex - 1]
}
}
}

View File

@ -40,13 +40,10 @@ QString ThemeManager::mode() const
void ThemeManager::setMode(const QString &mode)
{
QString m = mode.toLower();
if (m != "system" && m != "light" && m != "dark")
return;
if (m == m_mode)
if (mode == m_mode)
return;
m_mode = m;
m_mode = mode;
saveSettings();
applyPalette();
emit modeChanged();
@ -56,11 +53,16 @@ void ThemeManager::setMode(const QString &mode)
QStringList ThemeManager::availableSchemes() const
{
QStringList schemes;
QDir dir(SCHEMES_DIR);
const auto entries = dir.entryInfoList({"*.colors"}, QDir::Files, QDir::Name);
for (const auto &entry : entries) {
schemes << entry.baseName();
QStringList dirs = schemeDirs();
for (const QString &dirPath : dirs) {
QDir dir(dirPath);
const auto entries = dir.entryInfoList({"*.colors"}, QDir::Files, QDir::Name);
for (const auto &entry : entries) {
if (!schemes.contains(entry.baseName()))
schemes << entry.baseName();
}
}
schemes.sort(Qt::CaseInsensitive);
return schemes;
}
@ -76,12 +78,12 @@ bool ThemeManager::isDark() const
void ThemeManager::applyPalette()
{
QString path;
if (m_mode == "light") {
path = schemePath("BreezeLight");
} else if (m_mode == "dark") {
path = schemePath("BreezeDark");
} else {
if (m_mode == "system") {
path = systemSchemePath();
} else {
// Mode is a scheme name (e.g. "BreezeLight", "BreezeDark",
// "CatppuccinMochaMauve", etc.)
path = schemePath(m_mode);
}
if (path.isEmpty() || !QFile::exists(path)) {
@ -279,9 +281,27 @@ QString ThemeManager::systemSchemePath() const
QString ThemeManager::schemePath(const QString &name) const
{
for (const QString &dir : schemeDirs()) {
QString path = QString("%1/%2.colors").arg(dir, name);
if (QFile::exists(path))
return path;
}
// Fallback to system dir even if file doesn't exist
return QString("%1/%2.colors").arg(SCHEMES_DIR, name);
}
QStringList ThemeManager::schemeDirs() const
{
QStringList dirs;
// User dir first (higher priority)
QString userDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ "/color-schemes";
if (QDir(userDir).exists())
dirs << userDir;
dirs << SCHEMES_DIR;
return dirs;
}
// --- Font methods ---
QString ThemeManager::fontFamily() const
@ -405,9 +425,7 @@ void ThemeManager::loadSettings()
if (QFile::exists(configFile)) {
QSettings settings(configFile, QSettings::IniFormat);
m_mode = settings.value("General/mode", "system").toString().toLower();
if (m_mode != "system" && m_mode != "light" && m_mode != "dark")
m_mode = "system";
m_mode = settings.value("General/mode", "system").toString();
m_fontFamily = settings.value("Font/family", "").toString();
m_fontSize = settings.value("Font/size", 0).toInt();

View File

@ -107,6 +107,7 @@ private:
QColor parseColor(const QVariant &value) const;
QString systemSchemePath() const;
QString schemePath(const QString &name) const;
QStringList schemeDirs() const;
void loadSettings();
void saveSettings();