Commit 38ba4507 authored by Benjamin Port's avatar Benjamin Port
Browse files

Port kcm icons to kconfigxt

Summary:
Also fix 2 bugs:
- keyboard navigation on size category didn't work as expected, we didn't saved what we see
(open size widget: arrow down, arrow right, save => will save the size to desktop entry instead of toolbar
- the icon slider was not updated when we change theme

Reviewers: ervin, mart, #plasma, crossi

Subscribers: broulik, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D24846
parent 4f6784ef
......@@ -2,8 +2,9 @@ add_definitions(-DTRANSLATION_DOMAIN=\"kcm5_icons\")
########### next target ###############
set(kcm_icons_PART_SRCS main.cpp iconsmodel.cpp)
set(kcm_icons_PART_SRCS main.cpp iconsmodel.cpp iconsizecategorymodel.cpp iconssettings.cpp)
kconfig_add_kcfg_files(kcm_icons_PART_SRCS iconssettingsbase.kcfgc GENERATE_MOC)
add_library(kcm_icons MODULE ${kcm_icons_PART_SRCS})
target_link_libraries(kcm_icons
......@@ -20,10 +21,16 @@ target_link_libraries(kcm_icons
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/config.h CONTENT "#define CMAKE_INSTALL_FULL_LIBEXECDIR \"${CMAKE_INSTALL_FULL_LIBEXECDIR}\"")
add_executable(plasma-changeicons changeicons.cpp)
target_link_libraries(plasma-changeicons PRIVATE Qt5::Core KF5::KIOWidgets KF5::IconThemes)
set(changeicons_SRCS changeicons.cpp iconssettings.cpp)
kconfig_add_kcfg_files(changeicons_SRCS iconssettingsbase.kcfgc GENERATE_MOC)
add_executable(plasma-changeicons ${changeicons_SRCS})
target_link_libraries(plasma-changeicons PRIVATE Qt5::Core KF5::KIOWidgets KF5::KCMUtils KF5::IconThemes)
kcoreaddons_desktop_to_json(kcm_icons "kcm_icons.desktop")
install(FILES iconssettingsbase.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
install(FILES icons_remove_effects.upd DESTINATION ${KDE_INSTALL_DATADIR}/kconf_update)
install(FILES kcm_icons.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
install(TARGETS kcm_icons DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms)
......
......@@ -18,12 +18,7 @@
*/
#include <QApplication>
#include <KConfigGroup>
#include <KIconTheme>
#include <KSharedConfig>
#include <KSharedDataCache>
#include <KBuildSycocaProgressDialog>
#include <QDebug>
#include "iconssettings.h"
int main(int argc, char** argv)
{
......@@ -33,28 +28,15 @@ int main(int argc, char** argv)
return 1;
}
{
//KNS will give us a path
QString themeName = app.arguments().last();
int idx = themeName.lastIndexOf('/');
if (idx>=0) {
themeName = themeName.mid(idx);
}
KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::SimpleConfig), "Icons");
config.writeEntry("Theme", themeName);
config.sync();
}
KIconTheme::reconfigure();
KSharedDataCache::deleteCache(QStringLiteral("icon-cache"));
for (int i=0; i<KIconLoader::LastGroup; i++)
{
KIconLoader::emitChange(KIconLoader::Group(i));
//KNS will give us a path
QString themeName = app.arguments().last();
int idx = themeName.lastIndexOf('/');
if (idx>=0) {
themeName = themeName.mid(idx);
}
KBuildSycocaProgressDialog::rebuildKSycoca(nullptr);
IconsSettings settings;
settings.setTheme(themeName);
settings.save();
return 0;
}
/*
* Copyright (c) 2019 Benjamin Port <benjamin.port@enioka.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "iconsizecategorymodel.h"
#include <KLocalizedString>
IconSizeCategoryModel::IconSizeCategoryModel(QObject *parent)
: QAbstractListModel(parent)
, m_data({
{QStringLiteral("desktopSize"), I18N_NOOP("Desktop"), QStringLiteral("Desktop")},
{QStringLiteral("toolbarSize"), I18N_NOOP("Toolbar"), QStringLiteral("Toolbar")},
{QStringLiteral("mainToolbarSize"), I18N_NOOP("Main Toolbar"), QStringLiteral("MainToolbar")},
{QStringLiteral("smallSize"), I18N_NOOP("Small Icons"), QStringLiteral("Small")},
{QStringLiteral("panelSize"), I18N_NOOP("Panel"), QStringLiteral("Panel")},
{QStringLiteral("dialogSize"), I18N_NOOP("Dialogs"), QStringLiteral("Dialog")}
})
{
}
IconSizeCategoryModel::~IconSizeCategoryModel() = default;
int IconSizeCategoryModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return m_data.count();
}
QVariant IconSizeCategoryModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() >= m_data.count()) {
return QVariant();
}
const auto &item = m_data.at(index.row());
switch (role) {
case Qt::DisplayRole:
return item.display;
case ConfigKeyRole:
return item.configKey;
case ConfigSectionRole:
return item.configSection;
}
return QVariant();
}
QHash<int, QByteArray> IconSizeCategoryModel::roleNames() const
{
QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames();
roleNames[ConfigKeyRole] = QByteArrayLiteral("configKey");
roleNames[ConfigSectionRole] = QByteArrayLiteral("configSectionRole");
return roleNames;
}
/*
* Copyright (c) 2019 Benjamin Port <benjamin.port@enioka.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <QAbstractListModel>
#include <QString>
#include <QVector>
struct IconSizeCategoryModelData
{
QString configKey;
QString display;
QString configSection;
};
Q_DECLARE_TYPEINFO(IconSizeCategoryModelData, Q_MOVABLE_TYPE);
class IconSizeCategoryModel : public QAbstractListModel
{
Q_OBJECT
public:
IconSizeCategoryModel(QObject *parent);
~IconSizeCategoryModel() override;
enum Roles {
ConfigKeyRole = Qt::UserRole + 1,
ConfigSectionRole
};
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
void load();
signals:
void categorySelectedIndexChanged();
private:
QVector<IconSizeCategoryModelData> m_data;
};
......@@ -29,7 +29,11 @@
#include <KIconTheme>
IconsModel::IconsModel(QObject *parent) : QAbstractListModel(parent)
#include "iconssettings.h"
IconsModel::IconsModel(IconsSettings *iconsSettings, QObject *parent)
: QAbstractListModel(parent)
, m_settings(iconsSettings)
{
}
......@@ -82,7 +86,7 @@ bool IconsModel::setData(const QModelIndex &index, const QVariant &value, int ro
// move to the next non-pending theme
const auto nonPending = match(index, PendingDeletionRole, false);
if (!nonPending.isEmpty()) {
setSelectedTheme(nonPending.first().data(ThemeNameRole).toString());
m_settings->setTheme(nonPending.first().data(ThemeNameRole).toString());
}
emit pendingDeletionsChanged();
......@@ -104,45 +108,10 @@ QHash<int, QByteArray> IconsModel::roleNames() const
};
}
QString IconsModel::selectedTheme() const
{
return m_selectedTheme;
}
void IconsModel::setSelectedTheme(const QString &theme)
{
if (m_selectedTheme == theme) {
return;
}
const bool firstTime = m_selectedTheme.isNull();
m_selectedTheme = theme;
if (!firstTime) {
emit selectedThemeChanged();
}
emit selectedThemeIndexChanged();
}
int IconsModel::selectedThemeIndex() const
{
auto it = std::find_if(m_data.begin(), m_data.end(), [this](const IconsModelData &item) {
return item.themeName == m_selectedTheme;
});
if (it != m_data.end()) {
return std::distance(m_data.begin(), it);
}
return -1;
}
void IconsModel::load()
{
beginResetModel();
const int oldCount = m_data.count();
m_data.clear();
const QStringList themes = KIconTheme::list();
......@@ -175,11 +144,6 @@ void IconsModel::load()
});
endResetModel();
// an item might have been added before the currently selected one
if (oldCount != m_data.count()) {
emit selectedThemeIndexChanged();
}
}
QStringList IconsModel::pendingDeletions() const
......
......@@ -27,6 +27,8 @@
#include <QString>
#include <QVector>
class IconsSettings;
struct IconsModelData
{
QString display;
......@@ -41,11 +43,8 @@ class IconsModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QString selectedTheme READ selectedTheme WRITE setSelectedTheme NOTIFY selectedThemeChanged)
Q_PROPERTY(int selectedThemeIndex READ selectedThemeIndex NOTIFY selectedThemeIndexChanged)
public:
IconsModel(QObject *parent);
IconsModel(IconsSettings *iconsSettings, QObject *parent = nullptr);
~IconsModel() override;
enum Roles {
......@@ -60,25 +59,16 @@ public:
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QHash<int, QByteArray> roleNames() const override;
QString selectedTheme() const;
void setSelectedTheme(const QString &theme);
int selectedThemeIndex() const;
QStringList pendingDeletions() const;
void removeItemsPendingDeletion();
void load();
signals:
void selectedThemeChanged();
void selectedThemeIndexChanged();
void pendingDeletionsChanged();
private:
QString m_selectedTheme;
QVector<IconsModelData> m_data;
IconsSettings *m_settings;
};
/*
* Copyright (c) 2019 Benjamin Port <benjamin.port@enioka.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <QObject>
#include <QDebug>
#include <KBuildSycocaProgressDialog>
#include <KIconTheme>
#include <KSharedDataCache>
#include "iconssettings.h"
IconsSettings::IconsSettings(QObject *parent)
: IconsSettingsBase(parent)
, m_themeDirty(false)
{
connect(this, &IconsSettings::configChanged, this, &IconsSettings::updateIconTheme);
connect(this, &IconsSettings::ThemeChanged, this, &IconsSettings::updateThemeDirty);
}
IconsSettings::~IconsSettings()
{
}
void IconsSettings::updateThemeDirty()
{
m_themeDirty = theme() != KIconTheme::current();
}
void IconsSettings::updateIconTheme()
{
if (m_themeDirty) {
KIconTheme::reconfigure();
KSharedDataCache::deleteCache(QStringLiteral("icon-cache"));
for (int i = 0; i < KIconLoader::LastGroup; i++) {
KIconLoader::emitChange(KIconLoader::Group(i));
}
KBuildSycocaProgressDialog::rebuildKSycoca(nullptr);
}
}
/*
* Copyright (c) 2019 Benjamin Port <benjamin.port@enioka.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PLASMA_DESKTOP_ICONSSETTINGS_H
#define PLASMA_DESKTOP_ICONSSETTINGS_H
#include "iconssettingsbase.h"
class IconsSettings : public IconsSettingsBase {
Q_OBJECT
public:
IconsSettings(QObject *parent = nullptr);
~IconsSettings() override;
public slots:
void updateIconTheme();
void updateThemeDirty();
private:
bool m_themeDirty;
};
#endif //PLASMA_DESKTOP_ICONSSETTINGS_H
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="kdeglobals" />
<group name="Icons">
<entry name="Theme" type="String">
<label>Name of the current icon theme</label>
<default>breeze</default>
</entry>
</group>
<group name="DesktopIcons">
<entry key="Size" name="desktopSize" type="Int">
<label>Desktop icons size</label>
<default>32</default>
</entry>
</group>
<group name="ToolbarIcons">
<entry key="Size" name="toolbarSize" type="Int">
<label>Toolbar icons size</label>
<default>22</default>
</entry>
</group>
<group name="MainToolbarIcons">
<entry key="Size" name="mainToolbarSize" type="Int">
<label>Main toolbar icons size</label>
<default>22</default>
</entry>
</group>
<group name="SmallIcons">
<entry key="Size" name="smallSize" type="Int">
<label>Small icons size</label>
<default>16</default>
</entry>
</group>
<group name="PanelIcons">
<entry key="Size" name="panelSize" type="Int">
<label>Panel icons size</label>
<default>48</default>
</entry>
</group>
<group name="DialogIcons">
<entry key="Size" name="dialogSize" type="Int">
<label>Dialog icons size</label>
<default>32</default>
</entry>
</group>
</kcfg>
File=iconssettingsbase.kcfg
ClassName=IconsSettingsBase
Mutators=true
DefaultValueGetters=true
GenerateProperties=true
ParentInConstructor=true
......@@ -6,6 +6,7 @@
* Copyright (C) 2000 Geert Jansen <jansen@kde.org>
* KDE Frameworks 5 port Copyright (C) 2013 Jonathan Riddell <jr@jriddell.org>
* Copyright (C) 2018 Kai Uwe Broulik <kde@privat.broulik.de>
* Copyright (C) 2019 Benjamin Port <benjamin.port@enioka.com>
*
* Requires the Qt widget libraries, available at no cost at
* https://www.qt.io/
......@@ -55,29 +56,23 @@
#include <algorithm>
#include <unistd.h> // for unlink
#include "iconssettings.h"
#include "iconsmodel.h"
#include "iconsizecategorymodel.h"
#include "config.h" // for CMAKE_INSTALL_FULL_LIBEXECDIR
static const QVector<int> s_defaultIconSizes = { 32, 22, 22, 16, 48, 32 };
// we try to use KIconTheme::defaultThemeName() but that could be "hicolor" which isn't a "real" theme
static const QString s_defaultThemeName = QStringLiteral("breeze");
K_PLUGIN_FACTORY_WITH_JSON(IconsFactory, "kcm_icons.json", registerPlugin<IconModule>();)
IconModule::IconModule(QObject *parent, const QVariantList &args)
: KQuickAddons::ConfigModule(parent, args)
, m_model(new IconsModel(this))
, m_iconGroups{
QStringLiteral("Desktop"),
QStringLiteral("Toolbar"),
QStringLiteral("MainToolbar"),
QStringLiteral("Small"),
QStringLiteral("Panel"),
QStringLiteral("Dialog")
}
: KQuickAddons::ManagedConfigModule(parent, args)
, m_settings(new IconsSettings(this))
, m_model(new IconsModel(m_settings, this))
, m_iconSizeCategoryModel(new IconSizeCategoryModel(this))
{
qmlRegisterType<IconsSettings>();
qmlRegisterType<IconsModel>();
qmlRegisterType<IconSizeCategoryModel>();
// to be able to access its enums
qmlRegisterUncreatableType<KIconLoader>("org.kde.private.kcms.icons", 1, 0, "KIconLoader", QString());
......@@ -94,13 +89,7 @@ IconModule::IconModule(QObject *parent, const QVariantList &args)
setButtons(Apply | Default);
connect(m_model, &IconsModel::selectedThemeChanged, this, [this] {
m_selectedThemeDirty = true;
setNeedsSave(true);
});
connect(m_model, &IconsModel::pendingDeletionsChanged, this, [this] {
setNeedsSave(true);
});
connect(m_model, &IconsModel::pendingDeletionsChanged, this, &IconModule::settingsChanged);
// When user has a lot of themes installed, preview pixmaps might get evicted prematurely
QPixmapCache::setCacheLimit(50 * 1024); // 50 MiB
......@@ -108,7 +97,11 @@ IconModule::IconModule(QObject *parent, const QVariantList &args)
IconModule::~IconModule()
{
}
IconsSettings *IconModule::iconsSettings() const
{
return m_settings;
}
IconsModel *IconModule::iconsModel() const
......@@ -116,9 +109,9 @@ IconsModel *IconModule::iconsModel() const
return m_model;
}
QStringList IconModule::iconGroups() const
IconSizeCategoryModel *IconModule::iconSizeCategoryModel() const
{
return m_iconGroups;
return m_iconSizeCategoryModel;
}
bool IconModule::downloadingFile() const
......@@ -126,65 +119,41 @@ bool IconModule::downloadingFile() const
return m_tempCopyJob;
}
int IconModule::iconSize(int group) const
{
return m_iconSizes[group];
}
void IconModule::setIconSize(int group, int size)
{
if (iconSize(group) == size) {
return;
}
m_iconSizes[group] = size;
setNeedsSave(true);
m_iconSizesDirty = true;
emit iconSizesChanged();
}
QList<int> IconModule::availableIconSizes(int group) const
{
return KIconLoader::global()->theme()->querySizes(static_cast<KIconLoader::Group>(group));
const auto themeName = m_settings->theme();
if (!m_kiconThemeCache.contains(m_settings->theme())) {
m_kiconThemeCache.insert(themeName, new KIconTheme(themeName));
}
return m_kiconThemeCache[themeName]->querySizes(static_cast<KIconLoader::Group>(group));
}
void IconModule::load()
{
ManagedConfigModule::load();
m_model->load();
loadIconSizes();
m_model->setSelectedTheme(KIconTheme::current());
setNeedsSave(false);
m_selectedThemeDirty = false;
m_iconSizesDirty = false;
// Model has been cleared so pretend the theme name changed to force view update
emit m_settings->ThemeChanged();
}
void IconModule::save()
{