File indexing completed on 2024-12-22 04:13:59

0001 /* This file is part of the KDE project
0002  * SPDX-FileCopyrightText: 2013 Martin Gräßlin <mgraesslin@kde.org>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 #include "kcolorschememanager.h"
0007 #include "kcolorschememanager_p.h"
0008 
0009 #include <kactionmenu.h>
0010 #include <kconfiggroup.h>
0011 #include <kcolorscheme.h>
0012 #include <ksharedconfig.h>
0013 
0014 #include <QApplication>
0015 #include <QDir>
0016 #include <QFileInfo>
0017 #include <QPainter>
0018 #include <KoResourcePaths.h>
0019 
0020 KColorSchemeManagerPrivate::KColorSchemeManagerPrivate()
0021     : model(new KColorSchemeModel())
0022 {
0023 }
0024 
0025 KColorSchemeModel::KColorSchemeModel(QObject *parent)
0026     : QAbstractListModel(parent)
0027 {
0028     init();
0029 }
0030 
0031 KColorSchemeModel::~KColorSchemeModel()
0032 {
0033 }
0034 
0035 int KColorSchemeModel::rowCount(const QModelIndex &parent) const
0036 {
0037     if (parent.isValid()) {
0038         return 0;
0039     }
0040     return m_data.count();
0041 }
0042 
0043 QVariant KColorSchemeModel::data(const QModelIndex &index, int role) const
0044 {
0045     if (!index.isValid() || (index.row() >= m_data.count())) {
0046         return QVariant();
0047     }
0048 
0049     switch (role) {
0050     case Qt::DisplayRole:
0051         return m_data.at(index.row()).name;
0052     case Qt::DecorationRole:
0053         return m_data.at(index.row()).preview;
0054     case Qt::UserRole:
0055         return m_data.at(index.row()).path;
0056     default:
0057         return QVariant();
0058     }
0059 }
0060 
0061 void KColorSchemeModel::init()
0062 {
0063     beginResetModel();
0064     m_data.clear();
0065 
0066     const QStringList dirs = KoResourcePaths::findDirs(QStringLiteral("color-schemes"));
0067     QStringList schemeFiles;
0068     Q_FOREACH (const QString &dir, dirs) {
0069         const QStringList fileNames = QDir(dir).entryList(QStringList() << QStringLiteral("*.colors"));
0070         Q_FOREACH (const QString &file, fileNames) {
0071             schemeFiles << dir + '/' + file;
0072         }
0073     }
0074     Q_FOREACH (const QString &schemeFile, schemeFiles) {
0075         KSharedConfigPtr config = KSharedConfig::openConfig(schemeFile);
0076         KConfigGroup group(config, QStringLiteral("General"));
0077         const QString name = group.readEntry("Name", QFileInfo(schemeFile).completeBaseName());
0078         const KColorSchemeModelData data = {name, schemeFile, createPreview(schemeFile)};
0079         m_data.append(data);
0080     }
0081     std::sort(m_data.begin(), m_data.end(), [](const KColorSchemeModelData & first, const KColorSchemeModelData & second) {
0082         return first.name < second.name;
0083     });
0084     endResetModel();
0085 }
0086 
0087 QIcon KColorSchemeModel::createPreview(const QString &path)
0088 {
0089     KSharedConfigPtr schemeConfig = KSharedConfig::openConfig(path);
0090     QIcon result;
0091     KColorScheme activeWindow(QPalette::Active, KColorScheme::Window, schemeConfig);
0092     KColorScheme activeButton(QPalette::Active, KColorScheme::Button, schemeConfig);
0093     KColorScheme activeView(QPalette::Active, KColorScheme::View, schemeConfig);
0094     KColorScheme activeSelection(QPalette::Active, KColorScheme::Selection, schemeConfig);
0095 
0096     auto pixmap = [&](int size) {
0097         QPixmap pix(size, size);
0098         pix.fill(Qt::black);
0099         QPainter p;
0100         p.begin(&pix);
0101         const int itemSize = size / 2 - 1;
0102         p.fillRect(1, 1, itemSize, itemSize, activeWindow.background());
0103         p.fillRect(1 + itemSize, 1, itemSize, itemSize, activeButton.background());
0104         p.fillRect(1, 1 + itemSize, itemSize, itemSize, activeView.background());
0105         p.fillRect(1 + itemSize, 1 + itemSize, itemSize, itemSize, activeSelection.background());
0106         p.end();
0107         result.addPixmap(pix);
0108     };
0109     // 16x16
0110     pixmap(16);
0111     // 24x24
0112     pixmap(24);
0113 
0114     return result;
0115 }
0116 
0117 KColorSchemeManager::KColorSchemeManager(QObject *parent)
0118     : QObject(parent)
0119     , d(new KColorSchemeManagerPrivate)
0120 {
0121 }
0122 
0123 KColorSchemeManager::~KColorSchemeManager()
0124 {
0125 }
0126 
0127 QAbstractItemModel *KColorSchemeManager::model() const
0128 {
0129     return d->model.data();
0130 }
0131 
0132 QModelIndex KColorSchemeManager::indexForScheme(const QString &name) const
0133 {
0134     for (int i = 0; i < d->model->rowCount(); ++i) {
0135         QModelIndex index = d->model->index(i);
0136         if (index.data().toString() == name) {
0137             return index;
0138         }
0139     }
0140     return QModelIndex();
0141 }
0142 
0143 KActionMenu *KColorSchemeManager::createSchemeSelectionMenu(const QIcon &icon, const QString &name, const QString &selectedSchemeName, QObject *parent)
0144 {
0145     KActionMenu *menu = new KActionMenu(icon, name, parent);
0146     QActionGroup *group = new QActionGroup(menu);
0147     connect(group, &QActionGroup::triggered, [](QAction * action) {
0148         // hint for the style to synchronize the color scheme with the window manager/compositor
0149         qApp->setProperty("KDE_COLOR_SCHEME_PATH", action->data());
0150         qApp->setPalette(KColorScheme::createApplicationPalette(KSharedConfig::openConfig(action->data().toString())));
0151     });
0152     for (int i = 0; i < d->model->rowCount(); ++i) {
0153         QModelIndex index = d->model->index(i);
0154         QAction *action = new QAction(index.data(Qt::DecorationRole).value<QIcon>(), index.data().toString(), menu);
0155         action->setData(index.data(Qt::UserRole));
0156         action->setActionGroup(group);
0157         action->setCheckable(true);
0158         if (index.data().toString() == selectedSchemeName) {
0159             action->setChecked(true);
0160         }
0161         menu->addAction(action);
0162     }
0163     return menu;
0164 }
0165 
0166 KActionMenu *KColorSchemeManager::createSchemeSelectionMenu(const QString &text, const QString &selectedSchemeName, QObject *parent)
0167 {
0168     return createSchemeSelectionMenu(QIcon(), text, selectedSchemeName, parent);
0169 }
0170 
0171 KActionMenu *KColorSchemeManager::createSchemeSelectionMenu(const QString &selectedSchemeName, QObject *parent)
0172 {
0173     return createSchemeSelectionMenu(QIcon(), QString(), selectedSchemeName, parent);
0174 }
0175 
0176 void KColorSchemeManager::activateScheme(const QModelIndex &index)
0177 {
0178     if (!index.isValid()) {
0179         return;
0180     }
0181     if (index.model() != d->model.data()) {
0182         return;
0183     }
0184     // hint for the style to synchronize the color scheme with the window manager/compositor
0185     qApp->setProperty("KDE_COLOR_SCHEME_PATH", index.data(Qt::UserRole));
0186     qApp->setPalette(KColorScheme::createApplicationPalette(KSharedConfig::openConfig(index.data(Qt::UserRole).toString())));
0187 }