diff --git a/kcms/desktoptheme/CMakeLists.txt b/kcms/desktoptheme/CMakeLists.txt --- a/kcms/desktoptheme/CMakeLists.txt +++ b/kcms/desktoptheme/CMakeLists.txt @@ -10,6 +10,8 @@ target_link_libraries(kcm_desktoptheme KF5::CoreAddons KF5::KCMUtils + KF5::KIOCore + KF5::KIOWidgets KF5::I18n KF5::Plasma KF5::Declarative diff --git a/kcms/desktoptheme/kcm.h b/kcms/desktoptheme/kcm.h --- a/kcms/desktoptheme/kcm.h +++ b/kcms/desktoptheme/kcm.h @@ -26,11 +26,18 @@ #include +class QTemporaryFile; + namespace Plasma { class Svg; class Theme; } +namespace KIO +{ +class FileCopyJob; +} + class QQuickItem; class QStandardItemModel; @@ -40,6 +47,7 @@ Q_PROPERTY(QStandardItemModel *desktopThemeModel READ desktopThemeModel CONSTANT) Q_PROPERTY(QString selectedPlugin READ selectedPlugin WRITE setSelectedPlugin NOTIFY selectedPluginChanged) Q_PROPERTY(int selectedPluginIndex READ selectedPluginIndex NOTIFY selectedPluginIndexChanged) + Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged) Q_PROPERTY(bool canEditThemes READ canEditThemes CONSTANT) public: @@ -61,10 +69,12 @@ void setSelectedPlugin(const QString &plugin); int selectedPluginIndex() const; + bool downloadingFile() const; + bool canEditThemes() const; Q_INVOKABLE void getNewStuff(QQuickItem *ctx); - Q_INVOKABLE void installThemeFromFile(const QUrl &file); + Q_INVOKABLE void installThemeFromFile(const QUrl &url); Q_INVOKABLE void setPendingDeletion(int index, bool pending); @@ -75,6 +85,8 @@ Q_SIGNALS: void selectedPluginChanged(const QString &plugin); void selectedPluginIndexChanged(); + void downloadingFileChanged(); + void showSuccessMessage(const QString &message); void showErrorMessage(const QString &message); @@ -88,14 +100,19 @@ void processPendingDeletions(); + void installTheme(const QString &path); + QStandardItemModel *m_model; QString m_selectedPlugin; QStringList m_pendingRemoval; Plasma::Theme *m_defaultTheme; QHash m_themes; bool m_haveThemeExplorerInstalled; QPointer m_newStuffDialog; + + QScopedPointer m_tempInstallFile; + QPointer m_tempCopyJob; }; Q_DECLARE_LOGGING_CATEGORY(KCM_DESKTOP_THEME) diff --git a/kcms/desktoptheme/kcm.cpp b/kcms/desktoptheme/kcm.cpp --- a/kcms/desktoptheme/kcm.cpp +++ b/kcms/desktoptheme/kcm.cpp @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include @@ -36,6 +39,7 @@ #include #include #include +#include #include @@ -108,6 +112,11 @@ return -1; } +bool KCMDesktopTheme::downloadingFile() const +{ + return m_tempCopyJob; +} + void KCMDesktopTheme::setPendingDeletion(int index, bool pending) { QModelIndex idx = m_model->index(index, 0); @@ -140,12 +149,47 @@ m_newStuffDialog.data()->show(); } -void KCMDesktopTheme::installThemeFromFile(const QUrl &file) +void KCMDesktopTheme::installThemeFromFile(const QUrl &url) +{ + if (url.isLocalFile()) { + installTheme(url.toLocalFile()); + return; + } + + if (m_tempCopyJob) { + return; + } + + m_tempInstallFile.reset(new QTemporaryFile()); + if (!m_tempInstallFile->open()) { + emit showErrorMessage(i18n("Unable to create a temporary file.")); + m_tempInstallFile.reset(); + return; + } + + m_tempCopyJob = KIO::file_copy(url, QUrl::fromLocalFile(m_tempInstallFile->fileName()), + -1, KIO::Overwrite); + m_tempCopyJob->uiDelegate()->setAutoErrorHandlingEnabled(true); + emit downloadingFileChanged(); + + connect(m_tempCopyJob, &KIO::FileCopyJob::result, this, [this, url](KJob *job) { + if (job->error() != KJob::NoError) { + emit showErrorMessage(i18n("Unable to download the color scheme: %1", job->errorText())); + return; + } + + installTheme(m_tempInstallFile->fileName()); + m_tempInstallFile.reset(); + }); + connect(m_tempCopyJob, &QObject::destroyed, this, &KCMDesktopTheme::downloadingFileChanged); +} + +void KCMDesktopTheme::installTheme(const QString &path) { - qCDebug(KCM_DESKTOP_THEME) << "Installing ... " << file; + qCDebug(KCM_DESKTOP_THEME) << "Installing ... " << path; const QString program = QStringLiteral("kpackagetool5"); - const QStringList arguments = { QStringLiteral("--type"), QStringLiteral("Plasma/Theme"), QStringLiteral("--install"), file.toLocalFile()}; + const QStringList arguments = { QStringLiteral("--type"), QStringLiteral("Plasma/Theme"), QStringLiteral("--install"), path}; qCDebug(KCM_DESKTOP_THEME) << program << arguments.join(QStringLiteral(" ")); QProcess *myProcess = new QProcess(this); diff --git a/kcms/desktoptheme/package/contents/ui/main.qml b/kcms/desktoptheme/package/contents/ui/main.qml --- a/kcms/desktoptheme/package/contents/ui/main.qml +++ b/kcms/desktoptheme/package/contents/ui/main.qml @@ -32,6 +32,8 @@ view.model: kcm.desktopThemeModel view.currentIndex: kcm.selectedPluginIndex + enabled: !kcm.downloadingFile + DropArea { anchors.fill: parent onEntered: {