diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ find_package(KF5 ${KF5_MIN_VERSION} REQUIRED Bookmarks Completion Config ConfigWidgets CoreAddons Crash GuiAddons DBusAddons - I18n IconThemes Init KIO Notifications NotifyConfig + I18n IconThemes Init KIO NewStuff NewStuffCore Notifications NotifyConfig Parts Pty Service TextWidgets WidgetsAddons WindowSystem XmlGui DBusAddons GlobalAccel ) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,3 +1,5 @@ add_subdirectory( color-schemes ) add_subdirectory( keyboard-layouts ) + +install( FILES konsole.knsrc DESTINATION ${CONFIG_INSTALL_DIR}) diff --git a/data/konsole.knsrc b/data/konsole.knsrc new file mode 100644 --- /dev/null +++ b/data/konsole.knsrc @@ -0,0 +1,5 @@ +[KNewStuff3] +ProvidersUrl=https://download.kde.org/ocs/providers.xml +Categories=Konsole Color Schemes +TargetDir=konsole +AcceptHtmlDownloads=false diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -124,6 +124,7 @@ KF5::KIOWidgets KF5::DBusAddons KF5::GlobalAccel + KF5::NewStuff ) if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") diff --git a/src/ColorSchemeManager.h b/src/ColorSchemeManager.h --- a/src/ColorSchemeManager.h +++ b/src/ColorSchemeManager.h @@ -2,6 +2,7 @@ This source file is part of Konsole, a terminal emulator. Copyright 2007-2008 by Robert Knight + Copyright 2018 by Harald Sitter 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 @@ -100,23 +101,33 @@ */ bool isColorSchemeDeletable(const QString &name); -private: - Q_DISABLE_COPY(ColorSchemeManager) - // loads a color scheme from a KDE 4+ .colorscheme file bool loadColorScheme(const QString &path); + + // unloads a color scheme by it's file path (doesn't delete!) + bool unloadColorScheme(const QString &path); + + // @returns the scheme name of a given file or a null string if the file is + // no theme + static QString colorSchemeNameFromPath(const QString &path); + +private: // returns a list of paths of color schemes in the KDE 4+ .colorscheme file format QStringList listColorSchemes(); // loads all of the color schemes void loadAllColorSchemes(); // finds the path of a color scheme QString findColorSchemePath(const QString &name) const; + // @returns whether a path is a valid color scheme name + static bool pathIsColorScheme(const QString &path); QHash _colorSchemes; bool _haveLoadedAll; static const ColorScheme _defaultColorScheme; + + Q_DISABLE_COPY(ColorSchemeManager) }; } diff --git a/src/ColorSchemeManager.cpp b/src/ColorSchemeManager.cpp --- a/src/ColorSchemeManager.cpp +++ b/src/ColorSchemeManager.cpp @@ -2,6 +2,7 @@ This source file is part of Konsole, a terminal emulator. Copyright 2007-2008 by Robert Knight + Copyright 2018 by Harald Sitter 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 @@ -85,15 +86,15 @@ bool ColorSchemeManager::loadColorScheme(const QString &filePath) { - if (!filePath.endsWith(QLatin1String(".colorscheme")) || !QFile::exists(filePath)) { + if (!pathIsColorScheme(filePath) || !QFile::exists(filePath)) { return false; } - QFileInfo info(filePath); + auto name = colorSchemeNameFromPath(filePath); KConfig config(filePath, KConfig::NoGlobals); auto scheme = new ColorScheme(); - scheme->setName(info.completeBaseName()); + scheme->setName(name); scheme->read(config); if (scheme->name().isEmpty()) { @@ -103,7 +104,7 @@ return false; } - if (!_colorSchemes.contains(info.completeBaseName())) { + if (!_colorSchemes.contains(name)) { _colorSchemes.insert(scheme->name(), scheme); } else { //qDebug() << "color scheme with name" << scheme->name() << "has already been" << @@ -115,6 +116,24 @@ return true; } +bool ColorSchemeManager::unloadColorScheme(const QString &filePath) +{ + if (!pathIsColorScheme(filePath)) { + return false; + } + auto name = colorSchemeNameFromPath(filePath); + delete _colorSchemes.take(name); + return true; +} + +QString ColorSchemeManager::colorSchemeNameFromPath(const QString &path) +{ + if (!pathIsColorScheme(path)) { + return QString(); + } + return QFileInfo(path).completeBaseName(); +} + QStringList ColorSchemeManager::listColorSchemes() { QStringList colorschemes; @@ -141,8 +160,7 @@ { // remove existing colorscheme with the same name if (_colorSchemes.contains(scheme->name())) { - delete _colorSchemes[scheme->name()]; - _colorSchemes.remove(scheme->name()); + delete _colorSchemes.take(scheme->name()); } _colorSchemes.insert(scheme->name(), scheme); @@ -165,8 +183,7 @@ // look up the path and delete QString path = findColorSchemePath(name); if (QFile::remove(path)) { - delete _colorSchemes[name]; - _colorSchemes.remove(name); + delete _colorSchemes.take(name); return true; } else { qCDebug(KonsoleDebug)<<"Failed to remove color scheme -"< + Copyright 2018 by Harald Sitter 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 @@ -22,11 +23,12 @@ // Qt #include +#include #include #include -// KDE -#include +// KDe +#include // Konsole #include "Profile.h" @@ -132,6 +134,7 @@ void editColorScheme(); void saveColorScheme(const ColorScheme &scheme, bool isNewScheme); void removeColorScheme(); + void gotNewColorSchemes(const KNS3::Entry::List &changedEntries); /** * Deletes the selected colorscheme from the user's home dir location diff --git a/src/EditProfileDialog.cpp b/src/EditProfileDialog.cpp --- a/src/EditProfileDialog.cpp +++ b/src/EditProfileDialog.cpp @@ -1,5 +1,6 @@ /* Copyright 2007-2008 by Robert Knight + Copyright 2018 by Harald Sitter 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 @@ -37,13 +38,14 @@ #include #include #include + // KDE #include - #include #include #include #include +#include #include #include #include @@ -537,10 +539,17 @@ _ui->transparencyWarningWidget->setCloseButtonVisible(false); _ui->transparencyWarningWidget->setMessageType(KMessageWidget::Warning); + _ui->colorSchemeMessageWidget->setVisible(false); + _ui->colorSchemeMessageWidget->setWordWrap(true); + _ui->colorSchemeMessageWidget->setCloseButtonVisible(false); + _ui->colorSchemeMessageWidget->setMessageType(KMessageWidget::Warning); + _ui->editColorSchemeButton->setEnabled(false); _ui->removeColorSchemeButton->setEnabled(false); _ui->resetColorSchemeButton->setEnabled(false); + _ui->downloadColorSchemeButton->setConfigFile(QStringLiteral("konsole.knsrc")); + // setup color list // select the colorScheme used in the current profile updateColorSchemeList(currentColorSchemeName()); @@ -563,6 +572,8 @@ &Konsole::EditProfileDialog::removeColorScheme); connect(_ui->newColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::newColorScheme); + connect(_ui->downloadColorSchemeButton, &KNS3::Button::dialogFinished, this, + &Konsole::EditProfileDialog::gotNewColorSchemes); connect(_ui->resetColorSchemeButton, &QPushButton::clicked, this, &Konsole::EditProfileDialog::resetColorScheme); @@ -842,14 +853,98 @@ void EditProfileDialog::removeColorScheme() { QModelIndexList selected = _ui->colorSchemeList->selectionModel()->selectedIndexes(); + if (selected.isEmpty()) { + return; + } - if (!selected.isEmpty()) { + // The actual delete runs async because we need to on-demand query + // files managed by KNS. Deleting files managed by KNS screws up the + // KNS states (entry gets shown as installed when in fact we deleted it). + auto *manager = new KNSCore::DownloadManager(QStringLiteral("konsole.knsrc"), this); + connect(manager, &KNSCore::DownloadManager::searchResult, + [=](const KNSCore::EntryInternal::List &entries) { const QString &name = selected.first().data(Qt::UserRole + 1).value()->name(); + Q_ASSERT(!name.isEmpty()); + bool uninstalled = false; + // Check if the theme was installed by KNS, if so uninstall it through + // there and unload it. + for (auto entry : entries) { + for (const auto &file : entry.installedFiles()) { + if (ColorSchemeManager::colorSchemeNameFromPath(file) != name) { + continue; + } + // Make sure the manager can unload it before uninstalling it. + if (ColorSchemeManager::instance()->unloadColorScheme(file)) { + manager->uninstallEntry(entry); + uninstalled = true; + } + } + if (uninstalled) { + break; + } + } + + // If KNS wasn't able to remove it is a custom theme and we'll drop + // it manually. + if (!uninstalled) { + uninstalled = ColorSchemeManager::instance()->deleteColorScheme(name); + } - if (ColorSchemeManager::instance()->deleteColorScheme(name)) { + if (uninstalled) { _ui->colorSchemeList->model()->removeRow(selected.first().row()); } + + manager->deleteLater(); + }); + manager->checkForInstalled(); + + return; +} + +void EditProfileDialog::gotNewColorSchemes(const KNS3::Entry::List &changedEntries) +{ + int failures = 0; + for (auto entry : changedEntries) { + switch (entry.status()) { + case KNS3::Entry::Installed: + for (const auto &file : entry.installedFiles()) { + if (ColorSchemeManager::instance()->loadColorScheme(file)) { + continue; + } + qWarning() << "Failed to load file" << file; + ++failures; + } + if (failures == entry.installedFiles().size()) { + _ui->colorSchemeMessageWidget->setText( + xi18nc("@info", + "Scheme %1 failed to load.", + entry.name())); + _ui->colorSchemeMessageWidget->animatedShow(); + QTimer::singleShot(8000, + _ui->colorSchemeMessageWidget, + &KMessageWidget::animatedHide); + } + break; + case KNS3::Entry::Deleted: + for (const auto &file : entry.uninstalledFiles()) { + if (ColorSchemeManager::instance()->unloadColorScheme(file)) { + continue; + } + qWarning() << "Failed to unload file" << file; + // If unloading fails we do not care. Iff the scheme failed here + // it either wasn't loaded or was invalid to begin with. + } + break; + case KNS3::Entry::Invalid: + case KNS3::Entry::Installing: + case KNS3::Entry::Downloadable: + case KNS3::Entry::Updateable: + case KNS3::Entry::Updating: + // Not interesting. + break; + } } + updateColorSchemeList(currentColorSchemeName()); } void EditProfileDialog::resetColorScheme() diff --git a/src/EditProfileDialog.ui b/src/EditProfileDialog.ui --- a/src/EditProfileDialog.ui +++ b/src/EditProfileDialog.ui @@ -467,54 +467,51 @@ true - - - - QAbstractItemView::ScrollPerPixel - - - - - + + - Create a new color scheme based upon the selected scheme + Reset the selected color scheme settings to the default values - New... + Defaults - - + + - Edit the selected color scheme + Delete the selected color scheme - Edit... + Remove - - - - Delete the selected color scheme + + + + QAbstractItemView::ScrollPerPixel + + + + - Remove + Get New... - - + + - Reset the selected color scheme settings to the default values + Create a new color scheme based upon the selected scheme - Defaults + New... - + Qt::Vertical @@ -527,9 +524,29 @@ - + + + + + Edit the selected color scheme + + + Edit... + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + @@ -1489,6 +1506,11 @@ QComboBox
kcombobox.h
+ + KNS3::Button + QPushButton +
KNS3/Button
+
KPluralHandlingSpinBox QSpinBox @@ -1507,7 +1529,7 @@ KMessageWidget QFrame -
kmessagewidget.h
+
kmessagewidget.h
1