diff --git a/kcms/icons/main.cpp b/kcms/icons/main.cpp index 2a7a5a535..e44763043 100644 --- a/kcms/icons/main.cpp +++ b/kcms/icons/main.cpp @@ -1,559 +1,559 @@ /* * main.cpp * * Copyright (c) 1999 Matthias Hoelzer-Kluepfel * Copyright (c) 2000 Antonio Larrosa * Copyright (C) 2000 Geert Jansen * KDE Frameworks 5 port Copyright (C) 2013 Jonathan Riddell * Copyright (C) 2018 Kai Uwe Broulik * * Requires the Qt widget libraries, available at no cost at * http://www.troll.no/ * * 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 "main.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // for unlink #include "iconsmodel.h" #include "config.h" // for CMAKE_INSTALL_FULL_LIBEXECDIR static const QVector 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(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") } { qmlRegisterType(); // to be able to access its enums qmlRegisterUncreatableType("org.kde.private.kcms.icons", 1, 0, "KIconLoader", QString()); - KAboutData* about = new KAboutData(QStringLiteral("kcm_icons"), i18n("Icons"), QStringLiteral("1.0"), + KAboutData* about = new KAboutData(QStringLiteral("kcm5_icons"), i18n("Icons"), QStringLiteral("1.0"), i18n("Icons Control Panel Module"), KAboutLicense::GPL, i18n("(c) 2000-2003 Geert Jansen")); about->addAuthor(i18n("Geert Jansen"), QString(), QStringLiteral("jansen@kde.org")); about->addAuthor(i18n("Antonio Larrosa Jimenez"), QString(), QStringLiteral("larrosa@kde.org")); about->addCredit(i18n("Torsten Rahn"), QString(), QStringLiteral("torsten@kde.org")); about->addAuthor(i18n("Jonathan Riddell"), QString(), QStringLiteral("jr@jriddell.org")); about->addAuthor(i18n("Kai Uwe Broulik"), QString(), QStringLiteral("kde@privat.broulik.de>")); setAboutData(about); setButtons(Apply | Default); connect(m_model, &IconsModel::selectedThemeChanged, this, [this] { m_selectedThemeDirty = true; setNeedsSave(true); }); connect(m_model, &IconsModel::pendingDeletionsChanged, this, [this] { setNeedsSave(true); }); } IconModule::~IconModule() { } IconsModel *IconModule::iconsModel() const { return m_model; } QStringList IconModule::iconGroups() const { return m_iconGroups; } 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 IconModule::availableIconSizes(int group) const { return KIconLoader::global()->theme()->querySizes(static_cast(group)); } void IconModule::load() { m_model->load(); loadIconSizes(); m_model->setSelectedTheme(KIconTheme::current()); setNeedsSave(false); m_selectedThemeDirty = false; m_iconSizesDirty = false; } void IconModule::save() { if (m_selectedThemeDirty) { QProcess::startDetached(CMAKE_INSTALL_FULL_LIBEXECDIR "/plasma-changeicons", {m_model->selectedTheme()}); } if (m_iconSizesDirty || m_revertIconEffects) { auto cfg = KSharedConfig::openConfig(); for (int i = 0; i < m_iconGroups.count(); ++i) { const QString &group = m_iconGroups.at(i); KConfigGroup cg(cfg, group + QLatin1String("Icons")); cg.writeEntry("Size", m_iconSizes.at(i), KConfig::Normal | KConfig::Global); if (m_revertIconEffects) { cg.revertToDefault("Animated"); const QStringList states = { QStringLiteral("Default"), QStringLiteral("Active"), QStringLiteral("Disabled") }; const QStringList keys = { QStringLiteral("Effect"), QStringLiteral("Value"), QStringLiteral("Color"), QStringLiteral("Color2"), QStringLiteral("SemiTransparent") }; for (const QString &state : states) { for (const QString &key : keys) { cg.revertToDefault(state + key); } } } } cfg->sync(); } if (m_selectedThemeDirty || m_iconSizesDirty || m_revertIconEffects) { exportToKDE4(); } processPendingDeletions(); KIconLoader::global()->newIconLoader(); setNeedsSave(false); m_selectedThemeDirty = false; m_iconSizesDirty = false; m_revertIconEffects = false; } void IconModule::processPendingDeletions() { const QStringList pendingDeletions = m_model->pendingDeletions(); for (const QString &themeName : pendingDeletions) { Q_ASSERT(themeName != m_model->selectedTheme()); KIconTheme theme(themeName); auto *job = KIO::del(QUrl::fromLocalFile(theme.dir()), KIO::HideProgressInfo); // needs to block for it to work on "OK" where the dialog (kcmshell) closes job->exec(); } m_model->removeItemsPendingDeletion(); } void IconModule::defaults() { if (m_iconSizes != s_defaultIconSizes) { m_iconSizes = s_defaultIconSizes; emit iconSizesChanged(); } auto setThemeIfAvailable = [this](const QString &themeName) { const auto results = m_model->match(m_model->index(0, 0), ThemeNameRole, themeName); if (results.isEmpty()) { return false; } m_model->setSelectedTheme(themeName); return true; }; if (!setThemeIfAvailable(KIconTheme::defaultThemeName())) { setThemeIfAvailable(QStringLiteral("breeze")); } m_revertIconEffects = true; setNeedsSave(true); } void IconModule::loadIconSizes() { auto cfg = KSharedConfig::openConfig(); QVector iconSizes(6, 0); // why doesn't KIconLoader::LastGroup - 1 work here?! int i = KIconLoader::FirstGroup; for (const QString &group : qAsConst(m_iconGroups)) { int size = KIconLoader::global()->theme()->defaultSize(static_cast(i)); KConfigGroup iconGroup(cfg, group + QLatin1String("Icons")); size = iconGroup.readEntry("Size", size); iconSizes[i] = size; ++i; } if (m_iconSizes != iconSizes) { m_iconSizes = iconSizes; emit iconSizesChanged(); } } void IconModule::getNewStuff(QQuickItem *ctx) { if (!m_newStuffDialog) { m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("icons.knsrc")); m_newStuffDialog->setWindowTitle(i18n("Download New Icon Themes")); m_newStuffDialog->setWindowModality(Qt::WindowModal); m_newStuffDialog->winId(); // so it creates the windowHandle(); // TODO would be lovely to scroll to and select the newly installed scheme, if any connect(m_newStuffDialog.data(), &KNS3::DownloadDialog::accepted, this, [this] { if (m_newStuffDialog->changedEntries().isEmpty()) { return; } // reload the display icontheme items KIconLoader::global()->newIconLoader(); m_model->load(); }); } if (ctx && ctx->window()) { m_newStuffDialog->windowHandle()->setTransientParent(ctx->window()); } m_newStuffDialog->show(); } void IconModule::installThemeFromFile(const QUrl &url) { if (url.isLocalFile()) { installThemeFile(url.toLocalFile()); return; } m_tempInstallFile.reset(new QTemporaryFile()); if (!m_tempInstallFile->open()) { emit showErrorMessage(i18n("Unable to create a temporary file.")); m_tempInstallFile.reset(); return; } KIO::FileCopyJob *job = KIO::file_copy(url,QUrl::fromLocalFile(m_tempInstallFile->fileName()), -1, KIO::Overwrite); job->uiDelegate()->setAutoErrorHandlingEnabled(true); connect(job, &KIO::FileCopyJob::result, this, [this, url](KJob *job) { if (job->error() != KJob::NoError) { emit showErrorMessage(i18n("Unable to download the icon theme archive: %1", job->errorText())); return; } installThemeFile(m_tempInstallFile->fileName()); m_tempInstallFile.reset(); }); } void IconModule::installThemeFile(const QString &path) { const QStringList themesNames = findThemeDirs(path); if (themesNames.isEmpty()) { emit showErrorMessage(i18n("The file is not a valid icon theme archive.")); return; } if (!installThemes(themesNames, path)) { emit showErrorMessage(i18n("A problem occurred during the installation process; however, most of the themes in the archive have been installed")); return; } emit showSuccessMessage(i18n("Theme installed successfully.")); KIconLoader::global()->newIconLoader(); m_model->load(); } void IconModule::exportToKDE4() { //TODO: killing the kde4 icon cache: possible? (kde4migration doesn't let access the cache folder) Kdelibs4Migration migration; QString configFilePath = migration.saveLocation("config"); if (configFilePath.isEmpty()) { return; } configFilePath += QLatin1String("kdeglobals"); KSharedConfigPtr kglobalcfg = KSharedConfig::openConfig(QStringLiteral("kdeglobals")); KConfig kde4config(configFilePath, KConfig::SimpleConfig); KConfigGroup kde4IconGroup(&kde4config, "Icons"); kde4IconGroup.writeEntry("Theme", m_model->selectedTheme()); //Synchronize icon effects for (const QString &group : qAsConst(m_iconGroups)) { const QString groupName = group + QLatin1String("Icons"); KConfigGroup cg(kglobalcfg, groupName); KConfigGroup kde4Cg(&kde4config, groupName); // HACK copyTo only copies keys, it doesn't replace the entire group // which means if we removed the effects in our config it won't remove // them from the kde4 config, hence revert all of them prior to copying const QStringList keys = cg.keyList() + kde4Cg.keyList(); for (const QString &key : keys) { kde4Cg.revertToDefault(key); } // now copy over the new values cg.copyTo(&kde4Cg); } kde4config.sync(); QProcess *cachePathProcess = new QProcess(this); connect(cachePathProcess, QOverload::of(&QProcess::finished), this, [cachePathProcess](int exitCode, QProcess::ExitStatus status) { if (status == QProcess::NormalExit && exitCode == 0) { QString path = cachePathProcess->readAllStandardOutput().trimmed(); path.append(QLatin1String("icon-cache.kcache")); QFile::remove(path); } //message kde4 apps that icon theme is changed for (int i = 0; i < KIconLoader::LastGroup; i++) { KIconLoader::emitChange(KIconLoader::Group(i)); QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KGlobalSettings"), QStringLiteral("org.kde.KGlobalSettings"), QStringLiteral("notifyChange")); message.setArguments({ 4, // KGlobalSettings::IconChanged KIconLoader::Group(i) }); QDBusConnection::sessionBus().send(message); } cachePathProcess->deleteLater(); }); cachePathProcess->start(QStringLiteral("kde4-config --path cache")); } QStringList IconModule::findThemeDirs(const QString &archiveName) { QStringList foundThemes; KTar archive(archiveName); archive.open(QIODevice::ReadOnly); const KArchiveDirectory *themeDir = archive.directory(); KArchiveEntry *possibleDir = nullptr; KArchiveDirectory *subDir = nullptr; // iterate all the dirs looking for an index.theme or index.desktop file const QStringList entries = themeDir->entries(); for (const QString &entry : entries) { possibleDir = const_cast(themeDir->entry(entry)); if (!possibleDir->isDirectory()) { continue; } subDir = dynamic_cast(possibleDir); if (!subDir) { continue; } if (subDir->entry(QStringLiteral("index.theme")) || subDir->entry(QStringLiteral("index.desktop"))) { foundThemes.append(subDir->name()); } } archive.close(); return foundThemes; } bool IconModule::installThemes(const QStringList &themes, const QString &archiveName) { bool everythingOk = true; const QString localThemesDir(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/icons/./")); emit showProgress(i18n("Installing icon themes...")); KTar archive(archiveName); archive.open(QIODevice::ReadOnly); qApp->processEvents(QEventLoop::ExcludeUserInputEvents); const KArchiveDirectory *rootDir = archive.directory(); KArchiveDirectory *currentTheme = nullptr; for (const QString &theme : themes) { emit showProgress(i18n("Installing %1 theme...", theme)); qApp->processEvents(QEventLoop::ExcludeUserInputEvents); currentTheme = dynamic_cast(const_cast(rootDir->entry(theme))); if (!currentTheme) { // we tell back that something went wrong, but try to install as much // as possible everythingOk = false; continue; } currentTheme->copyTo(localThemesDir + theme); } archive.close(); emit hideProgress(); return everythingOk; } QVariantList IconModule::previewIcons(const QString &themeName, int size, qreal dpr) const { KIconTheme theme(themeName); QSvgRenderer renderer; auto getBestIcon = [&](const QStringList &iconNames) { const int iconSize = size * dpr; // not using initializer list as we want to unwrap inherits() const QStringList themes = QStringList() << theme.internalName() << theme.inherits(); for (const QString &themeName : themes) { KIconTheme theme(themeName); for (const QString &iconName : iconNames) { QString path = theme.iconPath(QStringLiteral("%1.png").arg(iconName), iconSize, KIconLoader::MatchBest); if (!path.isEmpty()) { QPixmap pixmap(path); pixmap.setDevicePixelRatio(dpr); return pixmap; } //could not find the .png, try loading the .svg or .svgz path = theme.iconPath(QStringLiteral("%1.svg").arg(iconName), iconSize, KIconLoader::MatchBest); if (path.isEmpty()) { path = theme.iconPath(QStringLiteral("%1.svgz").arg(iconName), iconSize, KIconLoader::MatchBest); } if (path.isEmpty()) { continue; } if (!renderer.load(path)) { continue; } QPixmap pixmap(iconSize, iconSize); pixmap.setDevicePixelRatio(dpr); pixmap.fill(QColor(Qt::transparent)); QPainter p(&pixmap); p.setViewport(0, 0, size, size); renderer.render(&p); return pixmap; } } return QPixmap(); }; QVariantList pixmaps{ getBestIcon({QStringLiteral("system-run"), QStringLiteral("exec")}), getBestIcon({QStringLiteral("folder")}), getBestIcon({QStringLiteral("document"), QStringLiteral("text-x-generic")}), getBestIcon({QStringLiteral("user-trash"), QStringLiteral("user-trash-empty")}), getBestIcon({QStringLiteral("system-help"), QStringLiteral("help-about"), QStringLiteral("help-contents")}), getBestIcon({QStringLiteral("preferences-system"), QStringLiteral("systemsettings"), QStringLiteral("configure")}), getBestIcon({QStringLiteral("text-html")}), getBestIcon({QStringLiteral("image-x-generic"), QStringLiteral("image-png"), QStringLiteral("image-jpeg")}), getBestIcon({QStringLiteral("video-x-generic"), QStringLiteral("video-x-theora+ogg"), QStringLiteral("video-mp4")}), getBestIcon({QStringLiteral("x-office-document")}), getBestIcon({QStringLiteral("x-office-spreadsheet")}), getBestIcon({QStringLiteral("x-office-presentation"), QStringLiteral("application-presentation")}), getBestIcon({QStringLiteral("user-home")}), getBestIcon({QStringLiteral("user-desktop"), QStringLiteral("desktop")}), getBestIcon({QStringLiteral("folder-image"), QStringLiteral("folder-images"), QStringLiteral("folder-pictures"), QStringLiteral("folder-picture")}), getBestIcon({QStringLiteral("folder-documents")}), getBestIcon({QStringLiteral("folder-download"), QStringLiteral("folder-downloads")}), getBestIcon({QStringLiteral("folder-video"), QStringLiteral("folder-videos")}) }; // remove missing icons pixmaps.erase(std::remove_if(pixmaps.begin(), pixmaps.end(), [](const QVariant &pixmapVariant) { return pixmapVariant.value().isNull(); }), pixmaps.end()); return pixmaps; } #include "main.moc" diff --git a/kcms/launch/CMakeLists.txt b/kcms/launch/CMakeLists.txt index 7db74aa54..0d8bcd078 100644 --- a/kcms/launch/CMakeLists.txt +++ b/kcms/launch/CMakeLists.txt @@ -1,27 +1,27 @@ # KI18N Translation Domain for this library. -add_definitions(-DTRANSLATION_DOMAIN=\"kcmlaunchfeedback\") +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_launchfeedback\") ########### next target ############### set(kcm_launchfeedback_PART_SRCS launchfeedback.cpp) set_source_files_properties(${KWIN_EFFECTS_INTERFACE} PROPERTIES INCLUDE "interface_util.h") qt5_add_dbus_interface(kcm_launchfeedback_PART_SRCS ${KWIN_EFFECTS_INTERFACE} kwin_interface) add_library(kcm_launchfeedback MODULE ${kcm_launchfeedback_PART_SRCS}) target_link_libraries(kcm_launchfeedback Qt5::DBus KF5::I18n KF5::KCMUtils KF5::QuickAddons ) kcoreaddons_desktop_to_json(kcm_launchfeedback "kcm_launchfeedback.desktop") ########### install files ############### install(TARGETS kcm_launchfeedback DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) install(FILES kcm_launchfeedback.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) kpackage_install_package(package kcm_launchfeedback kcms) diff --git a/kcms/launch/Messages.sh b/kcms/launch/Messages.sh index bd110b958..71d9b7d85 100644 --- a/kcms/launch/Messages.sh +++ b/kcms/launch/Messages.sh @@ -1,2 +1,2 @@ #! /usr/bin/env bash -$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcmlaunchfeedback.pot +$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcm_launchfeedback.pot diff --git a/kcms/translations/CMakeLists.txt b/kcms/translations/CMakeLists.txt index 0530205e5..45cab1e5a 100644 --- a/kcms/translations/CMakeLists.txt +++ b/kcms/translations/CMakeLists.txt @@ -1,26 +1,26 @@ include(ECMQMLModules) ecm_find_qmlmodule(org.kde.plasma.core 2.0) # KI18N Translation Domain for this library. -add_definitions(-DTRANSLATION_DOMAIN=\"kcmtranslations\") +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_translations\") ########### next target ############### set(kcm_translations_PART_SRCS translations.cpp translationsmodel.cpp) add_library(kcm_translations MODULE ${kcm_translations_PART_SRCS}) target_link_libraries(kcm_translations KF5::I18n KF5::KCMUtils KF5::QuickAddons ) kcoreaddons_desktop_to_json(kcm_translations "kcm_translations.desktop") ########### install files ############### install(TARGETS kcm_translations DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) install(FILES kcm_translations.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) kpackage_install_package(package kcm_translations kcms) diff --git a/kcms/translations/Messages.sh b/kcms/translations/Messages.sh index 2312e470d..96d449a97 100644 --- a/kcms/translations/Messages.sh +++ b/kcms/translations/Messages.sh @@ -1,2 +1,2 @@ #! /usr/bin/env bash -$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcmtranslations.pot +$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcm_translations.pot diff --git a/kcms/workspaceoptions/CMakeLists.txt b/kcms/workspaceoptions/CMakeLists.txt index 95811d698..f981ccade 100644 --- a/kcms/workspaceoptions/CMakeLists.txt +++ b/kcms/workspaceoptions/CMakeLists.txt @@ -1,27 +1,27 @@ # KI18N Translation Domain for this library -add_definitions(-DTRANSLATION_DOMAIN=\"kcm5_workspace\") +add_definitions(-DTRANSLATION_DOMAIN=\"kcm_workspace\") ########### next target ############### set(kcm_workspace_SRCS workspaceoptions.cpp ) add_library(kcm_workspace MODULE ${kcm_workspace_SRCS}) target_link_libraries(kcm_workspace KF5::QuickAddons KF5::I18n KF5::ConfigWidgets KF5::Declarative KF5::KDELibs4Support Qt5::DBus ) kcoreaddons_desktop_to_json(kcm_workspace "kcm_workspace.desktop" SERVICE_TYPES kcmodule.desktop) ########### install files ############### install( FILES kcm_workspace.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) install(TARGETS kcm_workspace DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) kpackage_install_package(package kcm_workspace kcms) diff --git a/kcms/workspaceoptions/Messages.sh b/kcms/workspaceoptions/Messages.sh index 63a598430..69ba853c7 100644 --- a/kcms/workspaceoptions/Messages.sh +++ b/kcms/workspaceoptions/Messages.sh @@ -1,2 +1,2 @@ #! /usr/bin/env bash -$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcm5_workspace.pot +$XGETTEXT `find . -name "*.cpp" -o -name "*.qml"` -o $podir/kcm_workspace.pot