File indexing completed on 2024-11-24 03:56:27

0001 /*
0002  * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best>
0003  *
0004  * SPDX-License-Identifier: GPL-3.0-or-later
0005  */
0006 
0007 #include "palette_settings.hpp"
0008 
0009 #include <QSet>
0010 #include <QApplication>
0011 #include <QMetaEnum>
0012 #include <QStyleFactory>
0013 
0014 #include "app/widgets/widget_palette_editor.hpp"
0015 #include "app/utils/string_view.hpp"
0016 
0017 app::settings::PaletteSettings::PaletteSettings()
0018     : default_palette(QGuiApplication::palette(), true)
0019 {
0020 }
0021 
0022 
0023 QString app::settings::PaletteSettings::slug() const
0024 {
0025     return "palette";
0026 }
0027 
0028 QIcon app::settings::PaletteSettings::icon() const
0029 {
0030     return QIcon::fromTheme("preferences-desktop-theme-global");
0031 }
0032 
0033 QString app::settings::PaletteSettings::label() const
0034 {
0035     return QObject::tr("Widget Theme");
0036 }
0037 
0038 void app::settings::PaletteSettings::save ( QSettings& settings )
0039 {
0040     settings.setValue("theme", selected);
0041     settings.setValue("style", style);
0042 
0043     settings.beginWriteArray("themes");
0044 
0045     int i = 0;
0046     for ( auto it = palettes.begin(); it != palettes.end(); ++it )
0047     {
0048         if ( !it->built_in )
0049         {
0050             settings.setArrayIndex(i);
0051             write_palette(settings, it.key(), *it);
0052             ++i;
0053         }
0054 
0055     }
0056 
0057     settings.endArray();
0058 }
0059 
0060 void app::settings::PaletteSettings::write_palette ( QSettings& settings, const QString& name, const QPalette& palette )
0061 {
0062     settings.setValue("name", name);
0063     for ( const auto& p : roles() )
0064     {
0065         settings.setValue(p.first + "_active",   color_to_string(palette.color(QPalette::Active, p.second)));
0066         settings.setValue(p.first + "_inactive", color_to_string(palette.color(QPalette::Inactive, p.second)));
0067         settings.setValue(p.first + "_disabled", color_to_string(palette.color(QPalette::Disabled, p.second)));
0068     }
0069 }
0070 
0071 
0072 void app::settings::PaletteSettings::load_palette ( const QSettings& settings, bool mark_built_in )
0073 {
0074     QString name = settings.value("name").toString();
0075     if ( name.isEmpty() )
0076         return;
0077 
0078     auto it = palettes.find(name);
0079     if ( it != palettes.end() && it->built_in && !mark_built_in )
0080         return;
0081 
0082     Palette palette;
0083     palette.built_in = mark_built_in;
0084 
0085     for ( const auto& p : roles() )
0086     {
0087         palette.setColor(QPalette::Active,   p.second, string_to_color(settings.value(p.first + "_active").toString()));
0088         palette.setColor(QPalette::Inactive, p.second, string_to_color(settings.value(p.first + "_inactive").toString()));
0089         palette.setColor(QPalette::Disabled, p.second, string_to_color(settings.value(p.first + "_disabled").toString()));
0090     }
0091 
0092     palettes.insert(name, palette);
0093 }
0094 
0095 
0096 void app::settings::PaletteSettings::load ( QSettings& settings )
0097 {
0098     selected = settings.value("theme").toString();
0099     style = settings.value("style").toString();
0100     if ( !style.isEmpty() )
0101         set_style(style);
0102 
0103     int n = settings.beginReadArray("themes");
0104 
0105     for ( int i = 0; i < n; i++ )
0106     {
0107         settings.setArrayIndex(i);
0108         load_palette(settings);
0109     }
0110 
0111     settings.endArray();
0112 
0113     apply_palette(palette());
0114 }
0115 
0116 const QPalette& app::settings::PaletteSettings::palette() const
0117 {
0118     auto it = palettes.find(selected);
0119     if ( it == palettes.end() )
0120         return default_palette;
0121 
0122     return *it;
0123 }
0124 
0125 
0126 const std::vector<std::pair<QString, QPalette::ColorRole> > & app::settings::PaletteSettings::roles()
0127 {
0128     static std::vector<std::pair<QString, QPalette::ColorRole> > roles;
0129     if ( roles.empty() )
0130     {
0131         QSet<QString> blacklisted = {
0132             "Background", "Foreground", "NColorRoles"
0133         };
0134         QMetaEnum me = QMetaEnum::fromType<QPalette::ColorRole>();
0135         for ( int i = 0; i < me.keyCount(); i++ )
0136         {
0137             if ( blacklisted.contains(me.key(i)) )
0138                 continue;
0139 
0140             roles.emplace_back(
0141                 me.key(i),
0142                 QPalette::ColorRole(me.value(i))
0143             );
0144         }
0145     }
0146 
0147     return roles;
0148 }
0149 
0150 void app::settings::PaletteSettings::set_selected ( const QString& name )
0151 {
0152     selected = name;
0153     apply_palette(palette());
0154 }
0155 
0156 QWidget * app::settings::PaletteSettings::make_widget ( QWidget* parent )
0157 {
0158     return new WidgetPaletteEditor(this, parent);
0159 }
0160 
0161 void app::settings::PaletteSettings::apply_palette(const QPalette& palette)
0162 {
0163     QGuiApplication::setPalette(palette);
0164     QApplication::setPalette(palette);
0165 
0166     for ( auto window : QApplication::topLevelWidgets() )
0167         window->setPalette(palette);
0168 }
0169 
0170 QString app::settings::PaletteSettings::color_to_string(const QColor& c)
0171 {
0172     QString s = c.name();
0173     if ( c.alpha() < 255 )
0174         s += utils::right_ref(QString::number(0x100|c.alpha(), 16), 2);
0175     return s;
0176 }
0177 
0178 QColor app::settings::PaletteSettings::string_to_color(const QString& s)
0179 {
0180     if ( s.startsWith('#') && s.length() == 9 )
0181     {
0182         QColor c(utils::left_ref(s, 7));
0183         c.setAlpha(s.right(2).toInt(nullptr, 16));
0184         return c;
0185     }
0186 
0187     return QColor(s);
0188 }
0189 
0190 void app::settings::PaletteSettings::set_style(const QString& name)
0191 {
0192     QApplication::setStyle(QStyleFactory::create(name));
0193     style = name;
0194 }