Skip to content

Extensions: Added uninstall and update process #27768

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/framework/extensions/extensionstypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ struct Manifest {
};

Uri uri;
io::path_t path;
Type type = Type::Undefined;
String title;
String description;
Expand All @@ -226,6 +227,7 @@ struct Manifest {
String version;
int apiversion = DEFAULT_API_VERSION;
bool legacyPlugin = false;
bool isUserExtension = false;

std::vector<Action> actions;

Expand Down
1 change: 1 addition & 0 deletions src/framework/extensions/iextensionsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class IExtensionsProvider : MODULE_EXPORT_INTERFACE
virtual ~IExtensionsProvider() = default;

virtual void reloadExtensions() = 0;
virtual Ret removeExtension(const Uri& uri) = 0;

virtual ManifestList manifestList(Filter filter = Filter::All) const = 0;
virtual async::Notification manifestListChanged() const = 0;
Expand Down
34 changes: 32 additions & 2 deletions src/framework/extensions/internal/extensioninstaller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "global/io/fileinfo.h"
#include "global/serialization/zipreader.h"
#include "global/translation.h"
#include "global/uuid.h"

#include "../extensionstypes.h"
Expand Down Expand Up @@ -36,11 +37,40 @@ Ret ExtensionInstaller::installExtension(const io::path_t srcPath)
ExtensionsLoader loader;
Manifest m = loader.parseManifest(data);

bool hasSame = provider()->manifest(m.uri).isValid();
if (hasSame) {
Manifest existingManifest = provider()->manifest(m.uri);
bool alreadyInstalled = existingManifest.isValid();
if (alreadyInstalled && existingManifest.version == m.version) {
LOGI() << "already installed: " << m.uri;

interactive()->info(trc("extensions", "The extension is already installed."), std::string(),
{ interactive()->buttonData(IInteractive::Button::Ok) });

return make_ok();
}

if (alreadyInstalled && !existingManifest.isUserExtension) {
interactive()->error(trc("extensions", "This extension cannot be updated."), std::string(),
{ interactive()->buttonData(IInteractive::Button::Ok) });

return make_ok();
}

if (alreadyInstalled) {
std::string text = qtrc("extensions", "Another version of the extension “%1” is already installed (version %2). "
"Do you want to replace it with version %3?")
.arg(existingManifest.title, existingManifest.version, m.version).toStdString();

IInteractive::Result result = interactive()->question(trc("extensions", "Update Extension"), text, {
interactive()->buttonData(IInteractive::Button::Cancel),
interactive()->buttonData(IInteractive::Button::Ok)
});

if (result.button() == int(IInteractive::Button::Ok)) {
provider()->removeExtension(existingManifest.uri);
} else {
return make_ok();
}
}
}

// unpack
Expand Down
4 changes: 4 additions & 0 deletions src/framework/extensions/internal/extensioninstaller.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
#include "modularity/ioc.h"
#include "../iextensionsconfiguration.h"
#include "../iextensionsprovider.h"
#include "global/iinteractive.h"
#include "io/ifilesystem.h"

namespace muse::extensions {
class ExtensionInstaller : public IExtensionInstaller
{
muse::GlobalInject<IExtensionsConfiguration> configuration;
muse::GlobalInject<IExtensionsProvider> provider;
muse::GlobalInject<muse::IInteractive> interactive;
muse::GlobalInject<io::IFileSystem> fileSystem;

public:
ExtensionInstaller() = default;
Expand Down
4 changes: 3 additions & 1 deletion src/framework/extensions/internal/extensionsloader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ ManifestList ExtensionsLoader::loadManifestList(const io::path_t& defPath, const
retList.push_back(m);
}

for (const Manifest& m : externalManifests) {
for (Manifest& m : externalManifests) {
if (!m.isValid()) {
continue;
}
Expand All @@ -67,6 +67,7 @@ ManifestList ExtensionsLoader::loadManifestList(const io::path_t& defPath, const
continue;
}

m.isUserExtension = true;
retList.push_back(m);
}

Expand All @@ -80,6 +81,7 @@ ManifestList ExtensionsLoader::manifestList(const io::path_t& rootPath) const
for (const io::path_t& path : paths) {
LOGD() << "parsing manifest: " << path;
Manifest manifest = parseManifest(path);
manifest.path = path;
resolvePaths(manifest, io::FileInfo(path).dirPath());
manifests.push_back(manifest);
}
Expand Down
20 changes: 20 additions & 0 deletions src/framework/extensions/internal/extensionsprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "global/containers.h"
#include "global/async/async.h"
#include "global/io/path.h"

#include "extensionsloader.h"
#include "legacy/extpluginsloader.h"
Expand Down Expand Up @@ -68,6 +69,25 @@ void ExtensionsProvider::reloadExtensions()
m_manifestListChanged.notify();
}

muse::Ret ExtensionsProvider::removeExtension(const Uri& uri)
{
const Manifest manifest = this->manifest(uri);
if (!manifest.isValid()) {
return make_ret(Ret::Code::UnknownError);
}

io::path_t path = manifest.path;

Ret ret = fileSystem()->remove(io::dirpath(path));
if (!ret) {
LOGE() << "Failed to delete the folder: " << path;
return ret;
}

reloadExtensions();
return make_ok();
}

ManifestList ExtensionsProvider::manifestList(Filter filter) const
{
if (filter == Filter::Enabled) {
Expand Down
3 changes: 3 additions & 0 deletions src/framework/extensions/internal/extensionsprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,22 @@
#include "../iextensionsprovider.h"
#include "../iextensionsexecpointsregister.h"
#include "global/iinteractive.h"
#include "io/ifilesystem.h"

namespace muse::extensions {
class ExtensionsProvider : public IExtensionsProvider, public Injectable, public async::Asyncable
{
Inject<IExtensionsConfiguration> configuration = { this };
Inject<IExtensionsExecPointsRegister> execPointsRegister = { this };
Inject<IInteractive> interactive = { this };
Inject<io::IFileSystem> fileSystem = { this };

public:
ExtensionsProvider(const modularity::ContextPtr& iocCtx)
: Injectable(iocCtx) {}

void reloadExtensions() override;
Ret removeExtension(const Uri& uri) override;

ManifestList manifestList(Filter filter = Filter::All) const override;
async::Notification manifestListChanged() const override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,11 @@ ManifestList ExtPluginsLoader::loadManifestList(const io::path_t& defPath, const
retList.push_back(m);
}

for (const Manifest& m : externalManifests) {
for (Manifest& m : externalManifests) {
if (!m.isValid()) {
continue;
}
m.isUserExtension = true;
retList.push_back(m);
}

Expand All @@ -95,6 +96,7 @@ ManifestList ExtPluginsLoader::manifestList(const io::path_t& rootPath) const
if (!manifest.isValid()) {
continue;
}
manifest.path = path;
resolvePaths(manifest, io::FileInfo(path).dirPath());
manifests.push_back(manifest);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ Item {
background: flickable

isEnabled: Boolean(selectedPlugin) ? selectedPlugin.enabled : false
isUserExtension: Boolean(selectedPlugin) ? selectedPlugin.isUserExtension : false

additionalInfoModel: [
{"title": qsTrc("extensions", "Version:"), "value": Boolean(selectedPlugin) ? selectedPlugin.version : "" },
Expand All @@ -198,6 +199,12 @@ Item {
extensionsModel.selectExecPoint(selectedPlugin.uri, index)
}

onRemove: function() {
extensionsModel.removeExtension(selectedPlugin.uri)
prv.resetSelectedPlugin()
panel.close()
}

onEditShortcutRequested: {
Qt.callLater(extensionsModel.editShortcut, selectedPlugin.uri)
panel.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ InfoPanel {

property var execPointsModel: null
property int currentExecPointIndex: 0
property bool isUserExtension: false

signal editShortcutRequested()
signal execPointSelected(int index)
signal remove()

buttonsPanel: RowLayout {
id: buttons
Expand Down Expand Up @@ -84,37 +86,62 @@ InfoPanel {
}
}



FlatButton {
id: mainButton
RowLayout {
Layout.alignment: Qt.AlignRight
spacing: 22

FlatButton {
id: removeButton

visible: root.isUserExtension
navigation.name: text + "Button"
navigation.panel: root.contentNavigation
navigation.column: 2
accessible.ignored: true
navigation.onActiveChanged: {
if (!navigation.active) {
accessible.ignored = false
}
}

navigation.name: text + "Button"
navigation.panel: root.contentNavigation
navigation.column: 3
accessible.ignored: true
navigation.onActiveChanged: {
if (!navigation.active) {
accessible.ignored = false
text: qsTrc("workspace", "Remove")

onClicked: {
root.remove()
}
}

text: !root.isEnabled ? qsTrc("extensions", "Enable") : qsTrc("extensions", "Disable")

Component.onCompleted: {
root.mainButton = mainButton
}

onClicked: {
//! NOTE temporary
// The function with the choice of the call point is not ready yet.
// Therefore, here is the previous solution with the button,
// but in fact the choice is made from the list
// 0 - disabled
// 1 - enabled (manual call)
// (here we switch to the opposite state)
root.execPointSelected(root.isEnabled ? 0 : 1)
FlatButton {
id: mainButton

navigation.name: text + "Button"
navigation.panel: root.contentNavigation
navigation.column: 3
accessible.ignored: true
navigation.onActiveChanged: {
if (!navigation.active) {
accessible.ignored = false
}
}

text: !root.isEnabled ? qsTrc("extensions", "Enable") : qsTrc("extensions", "Disable")

Component.onCompleted: {
root.mainButton = mainButton
}

onClicked: {
//! NOTE temporary
// The function with the choice of the call point is not ready yet.
// Therefore, here is the previous solution with the button,
// but in fact the choice is made from the list
// 0 - disabled
// 1 - enabled (manual call)
// (here we switch to the opposite state)
root.execPointSelected(root.isEnabled ? 0 : 1)
}
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions src/framework/extensions/view/extensionslistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ ExtensionsListModel::ExtensionsListModel(QObject* parent)
{ rCategory, "category" },
{ rVersion, "version" },
{ rShortcuts, "shortcuts" },
{ rIsUserExtension, "isUserExtension" }
};
}

Expand Down Expand Up @@ -120,6 +121,9 @@ QVariant ExtensionsListModel::data(const QModelIndex& index, int role) const
//: No keyboard shortcut is assigned to this plugin.
return muse::qtrc("extensions", "Not defined");
}
case rIsUserExtension: {
return plugin.isUserExtension;
}
}

return QVariant();
Expand Down Expand Up @@ -219,6 +223,11 @@ void ExtensionsListModel::reloadPlugins()
provider()->reloadExtensions();
}

void ExtensionsListModel::removeExtension(const QString& uri)
{
provider()->removeExtension(Uri(uri.toStdString()));
}

QVariantList ExtensionsListModel::categories() const
{
QVariantList result;
Expand Down
4 changes: 3 additions & 1 deletion src/framework/extensions/view/extensionslistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class ExtensionsListModel : public QAbstractListModel, public Injectable, public

Q_INVOKABLE void editShortcut(const QString& uri);
Q_INVOKABLE void reloadPlugins();
Q_INVOKABLE void removeExtension(const QString& uri);

Q_INVOKABLE QVariantList categories() const;

Expand All @@ -73,7 +74,8 @@ class ExtensionsListModel : public QAbstractListModel, public Injectable, public
rEnabled,
rCategory,
rVersion,
rShortcuts
rShortcuts,
rIsUserExtension
};

struct ExecPoints {
Expand Down