File indexing completed on 2024-05-19 05:38:25
0001 /* 0002 SPDX-FileCopyrightText: 2020 Mikhail Zolotukhin <zomial@protonmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include <QDebug> 0008 #include <QDir> 0009 #include <QStandardPaths> 0010 #include <QUrl> 0011 0012 #include <KIO/DeleteJob> 0013 0014 #include "gtkthemesmodel.h" 0015 0016 GtkThemesModel::GtkThemesModel(QObject *parent) 0017 : QAbstractListModel(parent) 0018 , m_selectedTheme(QStringLiteral("Breeze")) 0019 , m_themes() 0020 { 0021 } 0022 0023 void GtkThemesModel::load() 0024 { 0025 QMap<QString, QString> gtk3ThemesNames; 0026 0027 static const QStringList gtk3SubdirPattern(QStringLiteral("gtk-3.*")); 0028 for (const QString &possibleThemePath : possiblePathsToThemes()) { 0029 // If the directory contains any of gtk-3.X folders, it is the GTK3 theme for sure 0030 QDir possibleThemeDirectory(possibleThemePath); 0031 if (!possibleThemeDirectory.entryList(gtk3SubdirPattern, QDir::Dirs).isEmpty()) { 0032 // Do not show dark Breeze GTK variant, since the colors of it 0033 // are coming from the color scheme and selecting them here 0034 // is redundant and does not work 0035 if (possibleThemeDirectory.dirName() == QStringLiteral("Breeze-Dark")) { 0036 continue; 0037 } 0038 0039 gtk3ThemesNames.insert(possibleThemeDirectory.dirName(), possibleThemeDirectory.path()); 0040 } 0041 } 0042 0043 setThemesList(gtk3ThemesNames); 0044 } 0045 0046 QString GtkThemesModel::themePath(const QString &themeName) 0047 { 0048 if (themeName.isEmpty()) { 0049 return QString(); 0050 } else { 0051 return m_themes.constFind(themeName).value(); 0052 } 0053 } 0054 0055 QVariant GtkThemesModel::data(const QModelIndex &index, int role) const 0056 { 0057 if (!checkIndex(index)) { 0058 return QVariant(); 0059 } 0060 0061 auto it = m_themes.constBegin(); 0062 std::advance(it, index.row()); 0063 0064 switch (role) { 0065 case Qt::DisplayRole: 0066 case Roles::ThemeNameRole: 0067 return it.key(); 0068 case Roles::ThemePathRole: 0069 return it.value(); 0070 default: 0071 return QVariant(); 0072 } 0073 } 0074 0075 QHash<int, QByteArray> GtkThemesModel::roleNames() const 0076 { 0077 QHash<int, QByteArray> roles = QAbstractListModel::roleNames(); 0078 roles[Roles::ThemeNameRole] = "theme-name"; 0079 roles[Roles::ThemePathRole] = "theme-path"; 0080 0081 return roles; 0082 } 0083 0084 int GtkThemesModel::rowCount(const QModelIndex &parent) const 0085 { 0086 if (parent.isValid()) { 0087 return 0; 0088 } 0089 return m_themes.count(); 0090 } 0091 0092 void GtkThemesModel::setThemesList(const QMap<QString, QString> &themes) 0093 { 0094 beginResetModel(); 0095 m_themes = themes; 0096 endResetModel(); 0097 } 0098 0099 QMap<QString, QString> GtkThemesModel::themesList() 0100 { 0101 return m_themes; 0102 } 0103 0104 void GtkThemesModel::setSelectedTheme(const QString &themeName) 0105 { 0106 m_selectedTheme = themeName; 0107 Q_EMIT selectedThemeChanged(themeName); 0108 } 0109 0110 QString GtkThemesModel::selectedTheme() 0111 { 0112 return m_selectedTheme; 0113 } 0114 0115 QStringList GtkThemesModel::possiblePathsToThemes() 0116 { 0117 QStringList possibleThemesPaths; 0118 0119 QStringList themesLocationsPaths = 0120 QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("themes"), QStandardPaths::LocateDirectory); 0121 // TODO: Remove. See https://gitlab.gnome.org/GNOME/gtk/-/issues/6219 for when GTK plans to, and when we should, 0122 // remove it as well. 0123 themesLocationsPaths << QDir::homePath() + QStringLiteral("/.themes"); 0124 0125 for (const QString &themesLocationPath : std::as_const(themesLocationsPaths)) { 0126 const QStringList possibleThemesDirectoriesNames = QDir(themesLocationPath).entryList(QDir::NoDotAndDotDot | QDir::AllDirs); 0127 for (const QString &possibleThemeDirectoryName : possibleThemesDirectoriesNames) { 0128 possibleThemesPaths += themesLocationPath + '/' + possibleThemeDirectoryName; 0129 } 0130 } 0131 0132 return possibleThemesPaths; 0133 } 0134 0135 bool GtkThemesModel::selectedThemeRemovable() 0136 { 0137 return themePath(m_selectedTheme).contains(QDir::homePath()); 0138 } 0139 0140 void GtkThemesModel::removeSelectedTheme() 0141 { 0142 QString path = themePath(m_selectedTheme); 0143 KIO::DeleteJob *deleteJob = KIO::del(QUrl::fromLocalFile(path), KIO::HideProgressInfo); 0144 connect(deleteJob, &KJob::finished, this, [this]() { 0145 Q_EMIT themeRemoved(); 0146 }); 0147 } 0148 0149 int GtkThemesModel::findThemeIndex(const QString &themeName) 0150 { 0151 return static_cast<int>(std::distance(m_themes.constBegin(), m_themes.constFind(themeName))); 0152 } 0153 0154 void GtkThemesModel::setSelectedThemeDirty() 0155 { 0156 Q_EMIT selectedThemeChanged(m_selectedTheme); 0157 }