Changeset View
Standalone View
kcms/icons/main.cpp
1 | /* | 1 | /* | ||
---|---|---|---|---|---|
2 | * main.cpp | 2 | * main.cpp | ||
3 | * | 3 | * | ||
4 | * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> | 4 | * Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> | ||
5 | * Copyright (c) 2000 Antonio Larrosa <larrosa@kde.org> | 5 | * Copyright (c) 2000 Antonio Larrosa <larrosa@kde.org> | ||
6 | * Copyright (C) 2000 Geert Jansen <jansen@kde.org> | 6 | * Copyright (C) 2000 Geert Jansen <jansen@kde.org> | ||
7 | * KDE Frameworks 5 port Copyright (C) 2013 Jonathan Riddell <jr@jriddell.org> | 7 | * KDE Frameworks 5 port Copyright (C) 2013 Jonathan Riddell <jr@jriddell.org> | ||
8 | * Copyright (C) 2018 Kai Uwe Broulik <kde@privat.broulik.de> | 8 | * Copyright (C) 2018 Kai Uwe Broulik <kde@privat.broulik.de> | ||
9 | * Copyright (C) 2019 Benjamin Port <benjamin.port@enioka.com> | ||||
9 | * | 10 | * | ||
10 | * Requires the Qt widget libraries, available at no cost at | 11 | * Requires the Qt widget libraries, available at no cost at | ||
11 | * http://www.troll.no/ | 12 | * http://www.troll.no/ | ||
12 | * | 13 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | 16 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | 17 | * (at your option) any later version. | ||
Show All 33 Lines | |||||
50 | #include <KTar> | 51 | #include <KTar> | ||
51 | 52 | | |||
52 | #include <KIO/DeleteJob> | 53 | #include <KIO/DeleteJob> | ||
53 | #include <KIO/FileCopyJob> | 54 | #include <KIO/FileCopyJob> | ||
54 | 55 | | |||
55 | #include <algorithm> | 56 | #include <algorithm> | ||
56 | #include <unistd.h> // for unlink | 57 | #include <unistd.h> // for unlink | ||
57 | 58 | | |||
59 | #include "iconssettings.h" | ||||
58 | #include "iconsmodel.h" | 60 | #include "iconsmodel.h" | ||
59 | 61 | | |||
60 | #include "config.h" // for CMAKE_INSTALL_FULL_LIBEXECDIR | 62 | #include "config.h" // for CMAKE_INSTALL_FULL_LIBEXECDIR | ||
61 | 63 | | |||
62 | static const QVector<int> s_defaultIconSizes = { 32, 22, 22, 16, 48, 32 }; | 64 | static const QVector<int> s_defaultIconSizes = { 32, 22, 22, 16, 48, 32 }; | ||
63 | // we try to use KIconTheme::defaultThemeName() but that could be "hicolor" which isn't a "real" theme | 65 | // we try to use KIconTheme::defaultThemeName() but that could be "hicolor" which isn't a "real" theme | ||
64 | static const QString s_defaultThemeName = QStringLiteral("breeze"); | 66 | static const QString s_defaultThemeName = QStringLiteral("breeze"); | ||
65 | 67 | | |||
66 | K_PLUGIN_FACTORY_WITH_JSON(IconsFactory, "kcm_icons.json", registerPlugin<IconModule>();) | 68 | K_PLUGIN_FACTORY_WITH_JSON(IconsFactory, "kcm_icons.json", registerPlugin<IconModule>();) | ||
67 | 69 | | |||
68 | IconModule::IconModule(QObject *parent, const QVariantList &args) | 70 | IconModule::IconModule(QObject *parent, const QVariantList &args) | ||
69 | : KQuickAddons::ConfigModule(parent, args) | 71 | : KQuickAddons::ConfigModule(parent, args) | ||
72 | , m_settings(new IconsSettings(this)) | ||||
70 | , m_model(new IconsModel(this)) | 73 | , m_model(new IconsModel(this)) | ||
71 | , m_iconGroups{ | 74 | , m_iconGroups{ | ||
72 | QStringLiteral("Desktop"), | 75 | QStringLiteral("Desktop"), | ||
73 | QStringLiteral("Toolbar"), | 76 | QStringLiteral("Toolbar"), | ||
74 | QStringLiteral("MainToolbar"), | 77 | QStringLiteral("MainToolbar"), | ||
75 | QStringLiteral("Small"), | 78 | QStringLiteral("Small"), | ||
76 | QStringLiteral("Panel"), | 79 | QStringLiteral("Panel"), | ||
77 | QStringLiteral("Dialog") | 80 | QStringLiteral("Dialog") | ||
78 | } | 81 | } | ||
79 | { | 82 | { | ||
83 | qmlRegisterType<IconsSettings>(); | ||||
80 | qmlRegisterType<IconsModel>(); | 84 | qmlRegisterType<IconsModel>(); | ||
81 | 85 | | |||
82 | // to be able to access its enums | 86 | // to be able to access its enums | ||
83 | qmlRegisterUncreatableType<KIconLoader>("org.kde.private.kcms.icons", 1, 0, "KIconLoader", QString()); | 87 | qmlRegisterUncreatableType<KIconLoader>("org.kde.private.kcms.icons", 1, 0, "KIconLoader", QString()); | ||
84 | 88 | | |||
85 | KAboutData* about = new KAboutData(QStringLiteral("kcm5_icons"), i18n("Icons"), QStringLiteral("1.0"), | 89 | KAboutData* about = new KAboutData(QStringLiteral("kcm5_icons"), i18n("Icons"), QStringLiteral("1.0"), | ||
86 | i18n("Icons Control Panel Module"), KAboutLicense::GPL, | 90 | i18n("Icons Control Panel Module"), KAboutLicense::GPL, | ||
87 | i18n("(c) 2000-2003 Geert Jansen")); | 91 | i18n("(c) 2000-2003 Geert Jansen")); | ||
88 | about->addAuthor(i18n("Geert Jansen"), QString(), QStringLiteral("jansen@kde.org")); | 92 | about->addAuthor(i18n("Geert Jansen"), QString(), QStringLiteral("jansen@kde.org")); | ||
89 | about->addAuthor(i18n("Antonio Larrosa Jimenez"), QString(), QStringLiteral("larrosa@kde.org")); | 93 | about->addAuthor(i18n("Antonio Larrosa Jimenez"), QString(), QStringLiteral("larrosa@kde.org")); | ||
90 | about->addCredit(i18n("Torsten Rahn"), QString(), QStringLiteral("torsten@kde.org")); | 94 | about->addCredit(i18n("Torsten Rahn"), QString(), QStringLiteral("torsten@kde.org")); | ||
91 | about->addAuthor(i18n("Jonathan Riddell"), QString(), QStringLiteral("jr@jriddell.org")); | 95 | about->addAuthor(i18n("Jonathan Riddell"), QString(), QStringLiteral("jr@jriddell.org")); | ||
92 | about->addAuthor(i18n("Kai Uwe Broulik"), QString(), QStringLiteral("kde@privat.broulik.de>")); | 96 | about->addAuthor(i18n("Kai Uwe Broulik"), QString(), QStringLiteral("kde@privat.broulik.de>")); | ||
93 | setAboutData(about); | 97 | setAboutData(about); | ||
94 | 98 | | |||
95 | setButtons(Apply | Default); | 99 | setButtons(Apply | Default); | ||
96 | 100 | | |||
97 | connect(m_model, &IconsModel::selectedThemeChanged, this, [this] { | 101 | connect(m_model, &IconsModel::selectedThemeChanged, this, &IconModule::updateNeedsSave); | ||
98 | m_selectedThemeDirty = true; | 102 | connect(m_model, &IconsModel::pendingDeletionsChanged, this, &IconModule::updateNeedsSave); | ||
ervin: Now that my ManagedConfigModule change landed, you should use a proper compile time check… | |||||
ervin: I still think those connects might not be necessary. | |||||
99 | setNeedsSave(true); | 103 | connect(m_settings, &IconsSettings::DesktopSizeChanged, this, &IconModule::updateNeedsSave); | ||
100 | }); | 104 | connect(m_settings, &IconsSettings::SmallSizeChanged, this, &IconModule::updateNeedsSave); | ||
101 | connect(m_model, &IconsModel::pendingDeletionsChanged, this, [this] { | 105 | connect(m_settings, &IconsSettings::PanelSizeChanged, this, &IconModule::updateNeedsSave); | ||
102 | setNeedsSave(true); | 106 | connect(m_settings, &IconsSettings::ToolbarSizeChanged, this, &IconModule::updateNeedsSave); | ||
103 | }); | 107 | connect(m_settings, &IconsSettings::MainToolbarSizeChanged, this, &IconModule::updateNeedsSave); | ||
108 | connect(m_settings, &IconsSettings::DialogSizeChanged, this, &IconModule::updateNeedsSave); | ||||
Shouldn't you be able to remove that connect? I'd expect this signal trickling down to changing the settings object, wouldn't it? ervin: Shouldn't you be able to remove that connect? I'd expect this signal trickling down to changing… | |||||
104 | 109 | | |||
105 | // When user has a lot of themes installed, preview pixmaps might get evicted prematurely | 110 | // When user has a lot of themes installed, preview pixmaps might get evicted prematurely | ||
106 | QPixmapCache::setCacheLimit(50 * 1024); // 50 MiB | 111 | QPixmapCache::setCacheLimit(50 * 1024); // 50 MiB | ||
107 | } | 112 | } | ||
108 | 113 | | |||
109 | IconModule::~IconModule() | 114 | IconModule::~IconModule() | ||
110 | { | 115 | { | ||
111 | 116 | | |||
Don't do foreach. Instead write: for (auto theme : qAsConst(m_iconThemeCache)) { Or even better, just use qDeleteAll: qDeleteAll(m_iconThemeCache) Or even better yet : try to use std::unique_ptr, std::shared_ptr or QScopedPointer as values in your associative container (I let you check which one fits best). ervin: Don't do foreach. Instead write:
```
for (auto theme : qAsConst(m_iconThemeCache)) {
```
Or… | |||||
ervin: Still not addressed... mind your for loops... | |||||
112 | } | 117 | } | ||
113 | 118 | | |||
119 | IconsSettings *IconModule::iconsSettings() const | ||||
120 | { | ||||
121 | return m_settings; | ||||
122 | } | ||||
123 | | ||||
114 | IconsModel *IconModule::iconsModel() const | 124 | IconsModel *IconModule::iconsModel() const | ||
115 | { | 125 | { | ||
116 | return m_model; | 126 | return m_model; | ||
117 | } | 127 | } | ||
118 | 128 | | |||
119 | QStringList IconModule::iconGroups() const | 129 | QStringList IconModule::iconGroups() const | ||
120 | { | 130 | { | ||
121 | return m_iconGroups; | 131 | return m_iconGroups; | ||
122 | } | 132 | } | ||
123 | 133 | | |||
124 | bool IconModule::downloadingFile() const | 134 | bool IconModule::downloadingFile() const | ||
125 | { | 135 | { | ||
126 | return m_tempCopyJob; | 136 | return m_tempCopyJob; | ||
127 | } | 137 | } | ||
128 | 138 | | |||
129 | int IconModule::iconSize(int group) const | | |||
130 | { | | |||
131 | return m_iconSizes[group]; | | |||
132 | } | | |||
133 | | ||||
134 | void IconModule::setIconSize(int group, int size) | | |||
135 | { | | |||
136 | if (iconSize(group) == size) { | | |||
137 | return; | | |||
138 | } | | |||
139 | | ||||
140 | m_iconSizes[group] = size; | | |||
141 | setNeedsSave(true); | | |||
142 | m_iconSizesDirty = true; | | |||
143 | emit iconSizesChanged(); | | |||
144 | } | | |||
145 | | ||||
146 | QList<int> IconModule::availableIconSizes(int group) const | 139 | QList<int> IconModule::availableIconSizes(int group) const | ||
nitpick, I find = more readable in such a context (and less prone to the most vexing parse since you don't use curly braces init). I'd write: const auto themeName = m_model->selectedTheme(); ervin: nitpick, I find = more readable in such a context (and less prone to the most vexing parse… | |||||
Couldn't you fill the cache as soon as the selected theme changes instead? This way you wouldn't need to modify your cache here. ervin: Couldn't you fill the cache as soon as the selected theme changes instead? This way you… | |||||
nitpick, I find = more readable in such a context (and less prone to the most vexing parse since you don't use curly braces init). I'd write: const auto themeName = m_model->selectedTheme(); ervin: nitpick, I find = more readable in such a context (and less prone to the most vexing parse… | |||||
147 | { | 140 | { | ||
148 | return KIconLoader::global()->theme()->querySizes(static_cast<KIconLoader::Group>(group)); | 141 | KIconTheme theme(m_model->selectedTheme()); | ||
Does this KIconTheme instance need caching? I recall creating those parses a tonne of files and directories and is quite slow broulik: Does this `KIconTheme` instance need caching? I recall creating those parses a tonne of files… | |||||
Agreed, it'll hit the disk quite a bit, this might be a problem in a function which takes part in bindings (more than one which will change around the same time). ervin: Agreed, it'll hit the disk quite a bit, this might be a problem in a function which takes part… | |||||
142 | return theme.querySizes(static_cast<KIconLoader::Group>(group)); | ||||
149 | } | 143 | } | ||
150 | 144 | | |||
151 | void IconModule::load() | 145 | void IconModule::load() | ||
152 | { | 146 | { | ||
147 | m_settings->load(); | ||||
153 | m_model->load(); | 148 | m_model->load(); | ||
154 | loadIconSizes(); | | |||
155 | m_model->setSelectedTheme(KIconTheme::current()); | 149 | m_model->setSelectedTheme(KIconTheme::current()); | ||
156 | setNeedsSave(false); | 150 | updateNeedsSave(); | ||
This one likely requires a comment, since normally you wouldn't need such an emit. ervin: This one likely requires a comment, since normally you wouldn't need such an emit. | |||||
157 | m_selectedThemeDirty = false; | | |||
158 | m_iconSizesDirty = false; | | |||
159 | } | 151 | } | ||
160 | 152 | | |||
161 | void IconModule::save() | 153 | void IconModule::save() | ||
162 | { | 154 | { | ||
163 | if (m_selectedThemeDirty) { | 155 | if (isThemeDirty()) { | ||
164 | QProcess::startDetached(CMAKE_INSTALL_FULL_LIBEXECDIR "/plasma-changeicons", {m_model->selectedTheme()}); | 156 | QProcess::startDetached(CMAKE_INSTALL_FULL_LIBEXECDIR "/plasma-changeicons", {m_model->selectedTheme()}); | ||
165 | } | 157 | } | ||
166 | 158 | | |||
167 | if (m_iconSizesDirty) { | 159 | if (m_settings->isSaveNeeded()) { | ||
168 | auto cfg = KSharedConfig::openConfig(); | 160 | m_settings->save(); | ||
169 | for (int i = 0; i < m_iconGroups.count(); ++i) { | | |||
170 | const QString &group = m_iconGroups.at(i); | | |||
171 | KConfigGroup cg(cfg, group + QLatin1String("Icons")); | | |||
172 | cg.writeEntry("Size", m_iconSizes.at(i), KConfig::Normal | KConfig::Global); | | |||
173 | } | | |||
174 | cfg->sync(); | | |||
175 | } | 161 | } | ||
176 | 162 | | |||
177 | if (m_selectedThemeDirty || m_iconSizesDirty) { | 163 | if (isThemeDirty() || m_settings->isSaveNeeded()) { | ||
178 | exportToKDE4(); | 164 | exportToKDE4(); | ||
179 | } | 165 | } | ||
180 | 166 | | |||
181 | processPendingDeletions(); | 167 | processPendingDeletions(); | ||
182 | 168 | | |||
183 | KIconLoader::global()->newIconLoader(); | 169 | KIconLoader::global()->newIconLoader(); | ||
184 | 170 | | |||
185 | setNeedsSave(false); | 171 | updateNeedsSave(); | ||
186 | m_selectedThemeDirty = false; | 172 | } | ||
187 | m_iconSizesDirty = false; | 173 | | ||
174 | bool IconModule::isThemeDirty() const | ||||
175 | { | ||||
176 | return m_model->selectedTheme() != KIconTheme::current(); | ||||
ervin: Indentation looks wrong here. | |||||
177 | } | ||||
178 | | ||||
179 | void IconModule::updateNeedsSave() | ||||
180 | { | ||||
181 | setNeedsSave(m_settings->isSaveNeeded() || | ||||
182 | isThemeDirty() || | ||||
183 | !m_model->pendingDeletions().isEmpty()); | ||||
188 | } | 184 | } | ||
189 | 185 | | |||
190 | void IconModule::processPendingDeletions() | 186 | void IconModule::processPendingDeletions() | ||
191 | { | 187 | { | ||
192 | const QStringList pendingDeletions = m_model->pendingDeletions(); | 188 | const QStringList pendingDeletions = m_model->pendingDeletions(); | ||
193 | 189 | | |||
194 | for (const QString &themeName : pendingDeletions) { | 190 | for (const QString &themeName : pendingDeletions) { | ||
195 | Q_ASSERT(themeName != m_model->selectedTheme()); | 191 | Q_ASSERT(themeName != m_model->selectedTheme()); | ||
196 | 192 | | |||
197 | KIconTheme theme(themeName); | 193 | KIconTheme theme(themeName); | ||
198 | auto *job = KIO::del(QUrl::fromLocalFile(theme.dir()), KIO::HideProgressInfo); | 194 | auto *job = KIO::del(QUrl::fromLocalFile(theme.dir()), KIO::HideProgressInfo); | ||
199 | // needs to block for it to work on "OK" where the dialog (kcmshell) closes | 195 | // needs to block for it to work on "OK" where the dialog (kcmshell) closes | ||
200 | job->exec(); | 196 | job->exec(); | ||
201 | } | 197 | } | ||
202 | 198 | | |||
203 | m_model->removeItemsPendingDeletion(); | 199 | m_model->removeItemsPendingDeletion(); | ||
204 | } | 200 | } | ||
205 | 201 | | |||
206 | void IconModule::defaults() | 202 | void IconModule::defaults() | ||
207 | { | 203 | { | ||
208 | if (m_iconSizes != s_defaultIconSizes) { | 204 | m_settings->setDefaults(); | ||
209 | m_iconSizes = s_defaultIconSizes; | | |||
210 | emit iconSizesChanged(); | | |||
211 | } | | |||
212 | 205 | | |||
213 | auto setThemeIfAvailable = [this](const QString &themeName) { | 206 | auto setThemeIfAvailable = [this](const QString &themeName) { | ||
214 | const auto results = m_model->match(m_model->index(0, 0), ThemeNameRole, themeName); | 207 | const auto results = m_model->match(m_model->index(0, 0), ThemeNameRole, themeName); | ||
215 | if (results.isEmpty()) { | 208 | if (results.isEmpty()) { | ||
216 | return false; | 209 | return false; | ||
217 | } | 210 | } | ||
218 | 211 | | |||
219 | m_model->setSelectedTheme(themeName); | 212 | m_model->setSelectedTheme(themeName); | ||
220 | return true; | 213 | return true; | ||
221 | }; | 214 | }; | ||
222 | 215 | | |||
223 | if (!setThemeIfAvailable(KIconTheme::defaultThemeName())) { | 216 | if (!setThemeIfAvailable(KIconTheme::defaultThemeName())) { | ||
224 | setThemeIfAvailable(QStringLiteral("breeze")); | 217 | setThemeIfAvailable(QStringLiteral("breeze")); | ||
225 | } | 218 | } | ||
226 | | ||||
227 | setNeedsSave(true); | | |||
228 | } | | |||
229 | | ||||
230 | void IconModule::loadIconSizes() | | |||
231 | { | | |||
232 | auto cfg = KSharedConfig::openConfig(); | | |||
233 | | ||||
234 | QVector<int> iconSizes(6, 0); // why doesn't KIconLoader::LastGroup - 1 work here?! | | |||
235 | | ||||
236 | int i = KIconLoader::FirstGroup; | | |||
237 | for (const QString &group : qAsConst(m_iconGroups)) { | | |||
238 | int size = KIconLoader::global()->theme()->defaultSize(static_cast<KIconLoader::Group>(i)); | | |||
239 | | ||||
240 | KConfigGroup iconGroup(cfg, group + QLatin1String("Icons")); | | |||
241 | size = iconGroup.readEntry("Size", size); | | |||
242 | | ||||
243 | iconSizes[i] = size; | | |||
244 | | ||||
245 | ++i; | | |||
246 | } | | |||
247 | | ||||
248 | if (m_iconSizes != iconSizes) { | | |||
249 | m_iconSizes = iconSizes; | | |||
250 | emit iconSizesChanged(); | | |||
251 | } | | |||
252 | } | 219 | } | ||
253 | 220 | | |||
254 | void IconModule::getNewStuff(QQuickItem *ctx) | 221 | void IconModule::getNewStuff(QQuickItem *ctx) | ||
255 | { | 222 | { | ||
256 | if (!m_newStuffDialog) { | 223 | if (!m_newStuffDialog) { | ||
257 | m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("icons.knsrc")); | 224 | m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("icons.knsrc")); | ||
258 | m_newStuffDialog->setWindowTitle(i18n("Download New Icon Themes")); | 225 | m_newStuffDialog->setWindowTitle(i18n("Download New Icon Themes")); | ||
259 | m_newStuffDialog->setWindowModality(Qt::WindowModal); | 226 | m_newStuffDialog->setWindowModality(Qt::WindowModal); | ||
▲ Show 20 Lines • Show All 317 Lines • Show Last 20 Lines |
Now that my ManagedConfigModule change landed, you should use a proper compile time check connect to settingsChanged here.