diff --git a/plugins/PluginBrowser/PluginBrowser.py b/plugins/PluginBrowser/PluginBrowser.py index e1862dc06e..f08eb294e8 100644 --- a/plugins/PluginBrowser/PluginBrowser.py +++ b/plugins/PluginBrowser/PluginBrowser.py @@ -22,6 +22,8 @@ import platform import zipfile import shutil +from cura.CuraApplication import CuraApplication + i18n_catalog = i18nCatalog("cura") # Architecture thoughts: @@ -76,6 +78,11 @@ class PluginBrowser(QObject, Extension): self._plugins_metadata = [] self._plugins_model = None + # Can be 'installed' or 'availble' + self._view = "available" + + self._restart_required = False + self._dialog = None self._restartDialog = None self._download_progress = 0 @@ -112,6 +119,8 @@ class PluginBrowser(QObject, Extension): pluginsMetadataChanged = pyqtSignal() onDownloadProgressChanged = pyqtSignal() onIsDownloadingChanged = pyqtSignal() + restartRequiredChanged = pyqtSignal() + viewChanged = pyqtSignal() @pyqtSlot(result = str) def getLicenseDialogPluginName(self): @@ -245,6 +254,8 @@ class PluginBrowser(QObject, Extension): self.pluginsMetadataChanged.emit() self.openRestartDialog(result["message"]) + self._restart_required = True + self.restartRequiredChanged.emit() # Application.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Plugin browser"), result["message"]) @pyqtSlot(str) @@ -254,8 +265,23 @@ class PluginBrowser(QObject, Extension): self._newly_uninstalled_plugin_ids.append(result["id"]) self.pluginsMetadataChanged.emit() + self._restart_required = True + self.restartRequiredChanged.emit() + Application.getInstance().messageBox(i18n_catalog.i18nc("@window:title", "Plugin browser"), result["message"]) + @pyqtSlot(str) + def enablePlugin(self, plugin_id): + self._plugin_registry.enablePlugin(plugin_id) + self.pluginsMetadataChanged.emit() + Logger.log("i", "%s was set as 'active'", id) + + @pyqtSlot(str) + def disablePlugin(self, plugin_id): + self._plugin_registry.disablePlugin(plugin_id) + self.pluginsMetadataChanged.emit() + Logger.log("i", "%s was set as 'deactive'", id) + @pyqtProperty(int, notify = onDownloadProgressChanged) def downloadProgress(self): return self._download_progress @@ -287,51 +313,51 @@ class PluginBrowser(QObject, Extension): self.setDownloadProgress(0) self.setIsDownloading(False) - @pyqtProperty(QObject, notify=pluginsMetadataChanged) + @pyqtSlot(str) + def setView(self, view): + self._view = view + self.viewChanged.emit() + self.pluginsMetadataChanged.emit() + @pyqtProperty(QObject, notify=pluginsMetadataChanged) def pluginsModel(self): - self._plugins_model = PluginsModel() - """ - if self._plugins_model is None: - self._plugins_model = PluginsModel() - else: - self._plugins_model.clear() - items = [] - for metadata in self._plugins_metadata: - items.append({ - "name": metadata["label"], - "id": metadata["id"], - "version": metadata["version"], - "short_description": metadata["short_description"], - "author": metadata["author"], - "author_email": "author@gmail.com", - "status": self._checkInstallStatus(metadata["id"]), - "already_installed": self._checkAlreadyInstalled(metadata["id"]), - "file_location": metadata["file_location"], - # "active": self._checkActive(metadata["id"]), - "enabled": True, - "can_upgrade": self._checkCanUpgrade(metadata["id"], metadata["version"]) - }) - self._plugins_model.setItems(items) - """ + print("Updating plugins model...", self._view) + self._plugins_model = PluginsModel(self._view) + # self._plugins_model.update() + + # Check each plugin the registry for matching plugin from server + # metadata, and if found, compare the versions. Higher version sets + # 'can_upgrade' to 'True': + for plugin in self._plugins_model.items: + if self._checkCanUpgrade(plugin["id"], plugin["version"]): + plugin["can_upgrade"] = True + print(self._plugins_metadata) + + for item in self._plugins_metadata: + if item["id"] == plugin["id"]: + plugin["update_url"] = item["file_location"] + print("Updating from", item["file_location"]) + return self._plugins_model + + def _checkCanUpgrade(self, id, version): - plugin_registry = Application.getInstance().getPluginRegistry() - plugin_registry = PluginRegistry.getInstance() - metadata = plugin_registry.getMetaData(id) - if metadata != {}: - if id in self._newly_installed_plugin_ids: - return False # We already updated this plugin. - current_version = Version(metadata["plugin"]["version"]) - new_version = Version(version) - if new_version > current_version: - return True + + # TODO: This could maybe be done more efficiently using a dictionary... + + # Scan plugin server data for plugin with the given id: + for plugin in self._plugins_metadata: + if id == plugin["id"]: + reg_version = Version(version) + new_version = Version(plugin["version"]) + if new_version > reg_version: + Logger.log("i", "%s has an update availible: %s", plugin["id"], plugin["version"]) + return True return False def _checkAlreadyInstalled(self, id): - plugin_registry = PluginRegistry.getInstance() - metadata = plugin_registry.getMetaData(id) + metadata = self._plugin_registry.getMetaData(id) # We already installed this plugin, but the registry just doesn't know it yet. if id in self._newly_installed_plugin_ids: return True @@ -344,24 +370,14 @@ class PluginBrowser(QObject, Extension): return False def _checkInstallStatus(self, plugin_id): - plugin_registry = PluginRegistry.getInstance() - - # If plugin is registered, it's installed: - if plugin_id in plugin_registry._plugins: + if plugin_id in self._plugin_registry.getInstalledPlugins(): return "installed" else: return "uninstalled" def _checkEnabled(self, id): - plugin_registry = PluginRegistry.getInstance() - metadata = plugin_registry.getMetaData(id) - # if metadata != {}: - # if id in self._newly_installed_plugin_ids: - # return False # We already updated this plugin. - # current_version = Version(metadata["plugin"]["version"]) - # new_version = Version(version) - # if new_version > current_version: - # return True + if id in self._plugin_registry.getActivePlugins(): + return True return False def _onRequestFinished(self, reply): @@ -384,7 +400,11 @@ class PluginBrowser(QObject, Extension): if reply_url == self._api_url + "plugins": try: json_data = json.loads(bytes(reply.readAll()).decode("utf-8")) + + # Add metadata to the manager: self._plugins_metadata = json_data + print(self._plugins_metadata) + self._plugin_registry.addExternalPlugins(self._plugins_metadata) self.pluginsMetadataChanged.emit() except json.decoder.JSONDecodeError: Logger.log("w", "Received an invalid print job state message: Not valid JSON.") @@ -410,3 +430,15 @@ class PluginBrowser(QObject, Extension): self._network_manager = QNetworkAccessManager() self._network_manager.finished.connect(self._onRequestFinished) self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccesibleChanged) + + @pyqtProperty(bool, notify=restartRequiredChanged) + def restartRequired(self): + return self._restart_required + + @pyqtProperty(str, notify=viewChanged) + def viewing(self): + return self._view + + @pyqtSlot() + def restart(self): + CuraApplication.getInstance().quit() diff --git a/plugins/PluginBrowser/PluginBrowser.qml b/plugins/PluginBrowser/PluginBrowser.qml index 1a606e114b..229d5c1755 100644 --- a/plugins/PluginBrowser/PluginBrowser.qml +++ b/plugins/PluginBrowser/PluginBrowser.qml @@ -11,7 +11,7 @@ import QtQuick.Controls.Styles 1.4 import UM 1.1 as UM -UM.Dialog { +Window { id: base title: catalog.i18nc("@title:tab", "Plugins"); @@ -19,109 +19,154 @@ UM.Dialog { height: 640 * screenScaleFactor minimumWidth: 350 * screenScaleFactor minimumHeight: 350 * screenScaleFactor + color: "white" - Column { - // anchors.fill: parent - height: parent.height - width: parent.width - spacing: UM.Theme.getSize("default_margin").height + Item { + id: view + anchors { + fill: parent + leftMargin: UM.Theme.getSize("default_margin").width + rightMargin: UM.Theme.getSize("default_margin").width + topMargin: UM.Theme.getSize("default_margin").height + bottomMargin: UM.Theme.getSize("default_margin").height + } Rectangle { id: topBar width: parent.width - color: "red" - height: 30 - Text { - text: "Search" + color: "transparent" + height: childrenRect.height + + Row { + spacing: 12 + height: childrenRect.height + width: childrenRect.width + anchors.horizontalCenter: parent.horizontalCenter + + Button { + text: "Install" + style: ButtonStyle { + background: Rectangle { + color: "transparent" + implicitWidth: 96 + implicitHeight: 48 + Rectangle { + visible: manager.viewing == "available" ? true : false + color: UM.Theme.getColor("primary") + anchors.bottom: parent.bottom + width: parent.width + height: 3 + } + } + label: Text { + text: control.text + color: UM.Theme.getColor("text") + font { + pixelSize: 15 + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: manager.setView("available") + } + + Button { + text: "Manage" + style: ButtonStyle { + background: Rectangle { + color: "transparent" + implicitWidth: 96 + implicitHeight: 48 + Rectangle { + visible: manager.viewing == "installed" ? true : false + color: UM.Theme.getColor("primary") + anchors.bottom: parent.bottom + width: parent.width + height: 3 + } + } + label: Text { + text: control.text + color: UM.Theme.getColor("text") + font { + pixelSize: 15 + } + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: manager.setView("installed") + } } } - /* - Item { - id: topBar - height: childrenRect.height; - width: parent.width - - Label { - id: introText - text: catalog.i18nc("@label", "Here you can find a list of Third Party plugins.") - width: parent.width - height: 30 - } - - Button { - id: refresh - text: catalog.i18nc("@action:button", "Refresh") - onClicked: manager.requestPluginList() - anchors.right: parent.right - enabled: !manager.isDownloading - } - } - */ - // Scroll view breaks in QtQuick.Controls 2.x - Label { - text: "Installed Plugins" - } ScrollView { id: installedPluginList width: parent.width - height: 280 - /* - anchors.top: topBar.bottom - anchors.bottom: availiblePluginList.top - anchors.bottomMargin: UM.Theme.getSize("default_margin").height - */ - frameVisible: true + height: 400 + anchors { + top: topBar.bottom + topMargin: UM.Theme.getSize("default_margin").height + bottom: bottomBar.top + bottomMargin: UM.Theme.getSize("default_margin").height + } + + frameVisible: true ListView { id: pluginList - model: manager.pluginsModel - anchors.fill: parent property var activePlugin - delegate: pluginDelegate - } - } - Label { - text: "Availible plugins..." - } - /* - Rectangle { - width: parent.width - color: "red" - height: 200 - Text { - text: "Plugins not installed yet" - } - } - */ + property var filter: "installed" - // Scroll view breaks in QtQuick.Controls 2.x - ScrollView { - id: availiblePluginList - width: parent.width - /* - anchors.top: installedPluginList.bottom - anchors.bottom: bottomBar.top - anchors.bottomMargin: UM.Theme.getSize("default_margin").height - */ - frameVisible: true - height: 180 + anchors.fill: parent - Rectangle { - width: parent.width - color: "red" - height: 1000 + model: manager.pluginsModel + delegate: PluginEntry {} } } Rectangle { id: bottomBar width: parent.width - height: childrenRect.height; - // anchors.bottom: parent.bottom - // anchors.left: parent.left + height: childrenRect.height + color: "transparent" + anchors.bottom: parent.bottom + + Label { + visible: manager.restartRequired + text: "You will need to restart Cura before changes in plugins have effect." + height: 30 + verticalAlignment: Text.AlignVCenter + } + Button { + id: restartChangedButton + text: "Quit Cura" + anchors.right: closeButton.left + anchors.rightMargin: UM.Theme.getSize("default_margin").width + visible: manager.restartRequired + iconName: "dialog-restart" + onClicked: manager.restart() + style: ButtonStyle { + background: Rectangle { + implicitWidth: 96 + implicitHeight: 30 + color: UM.Theme.getColor("primary") + } + label: Text { + verticalAlignment: Text.AlignVCenter + color: "white" + font { + pixelSize: 13 + bold: true + } + text: control.text + horizontalAlignment: Text.AlignHCenter + } + } + } Button { id: closeButton @@ -133,298 +178,27 @@ UM.Dialog { } base.close(); } - anchors.bottom: parent.bottom anchors.right: parent.right - } - } - - Rectangle { - Component { - id: pluginDelegate - - Rectangle { - width: pluginList.width; - height: 102 - color: index % 2 ? UM.Theme.getColor("secondary") : "white" - - // Plugin info - Column { - id: pluginInfo - height: parent.height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.right: authorInfo.left - anchors.rightMargin: UM.Theme.getSize("default_margin").width - - Label { - text: model.name - width: parent.width - height: 24 - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - font { - pixelSize: 13 - bold: true - } - // color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("secondary") - color: UM.Theme.getColor("text") - } - - Label { - text: model.short_description - width: parent.width - height: 72 - wrapMode: Text.WordWrap + style: ButtonStyle { + background: Rectangle { + color: "transparent" + implicitWidth: 96 + implicitHeight: 30 + border { + width: 1 + color: UM.Theme.getColor("lining") } } - - // Author info - Column { - id: authorInfo - width: 192 - height: parent.height - - - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - - anchors.right: pluginActions.left - anchors.rightMargin: UM.Theme.getSize("default_margin").width - - Label { - text: model.author - width: parent.width - height: 24 - wrapMode: Text.WordWrap - verticalAlignment: Text.AlignVCenter - horizontalAlignment: Text.AlignRight - } - - Label { - text: model.author_email - width: parent.width - height: 72 - wrapMode: Text.WordWrap - horizontalAlignment: Text.AlignRight - } - } - - // Plugin actions - Row { - id: pluginActions - width: 180 + UM.Theme.getSize("default_margin").width - height: parent.height - anchors { - top: parent.top - right: parent.right - topMargin: UM.Theme.getSize("default_margin").height - rightMargin: UM.Theme.getSize("default_margin").width - } - layoutDirection: Qt.RightToLeft - spacing: UM.Theme.getSize("default_margin").width - - Rectangle { - id: removeControls - visible: model.already_installed - width: 108 - height: 30 - color: "transparent" - Button { - id: removeButton - text: "Remove" - enabled: { - if ( manager.isDownloading && pluginList.activePlugin == model ) { - return false; - } else { - return true; - } - } - onClicked: { - manager.removePlugin(model.id); - } - style: ButtonStyle { - background: Rectangle { - color: white - implicitWidth: 108 - implicitHeight: 30 - border { - width: 1 - color: "grey" - } - } - label: Text { - verticalAlignment: Text.AlignVCenter - color: "grey" - text: control.text - horizontalAlignment: Text.AlignLeft - } - } - } - Button { - id: removeDropDown - property bool open: false - UM.RecolorImage { - anchors.centerIn: parent - height: 10 - width: 10 - source: UM.Theme.getIcon("arrow_bottom") - color: "grey" - } - enabled: { - if ( model.required || ( manager.isDownloading && pluginList.activePlugin == model )) { - return false; - } else { - return true; - } - } - anchors.right: parent.right - style: ButtonStyle { - background: Rectangle { - color: "transparent" - implicitWidth: 30 - implicitHeight: 30 - } - label: Text { - verticalAlignment: Text.AlignVCenter - color: "grey" - text: control.text - horizontalAlignment: Text.AlignHCenter - } - } - - - - // For the disable option: - // onClicked: pluginList.model.setEnabled(model.id, checked) - - onClicked: { - if ( !removeDropDown.open ) { - removeDropDown.open = true - } - else { - removeDropDown.open = false - } - } - } - - Rectangle { - id: divider - width: 1 - height: parent.height - anchors.right: removeDropDown.left - color: "grey" - } - - Column { - id: options - anchors { - top: removeButton.bottom - left: parent.left - right: parent.right - } - height: childrenRect.height - visible: removeDropDown.open - - Button { - text: "Disable" - height: 30 - width: parent.width - onClicked: { - removeDropDown.open = false - model.setEnabled(model.id, checked) - } - } - } - } - - Button { - id: updateButton - visible: model.already_installed && model.can_upgrade - // visible: model.already_installed - text: { - // If currently downloading: - if ( manager.isDownloading && pluginList.activePlugin == model ) { - return catalog.i18nc( "@action:button", "Cancel" ); - } else { - return catalog.i18nc("@action:button", "Update"); - } - } - style: ButtonStyle { - background: Rectangle { - color: UM.Theme.getColor("primary") - implicitWidth: 72 - implicitHeight: 30 - // radius: 4 - } - label: Text { - verticalAlignment: Text.AlignVCenter - color: "white" - text: control.text - horizontalAlignment: Text.AlignHCenter - } - } - } - Button { - id: installButton - visible: !model.already_installed - text: { - // If currently downloading: - if ( manager.isDownloading && pluginList.activePlugin == model ) { - return catalog.i18nc( "@action:button", "Cancel" ); - } else { - return catalog.i18nc("@action:button", "Install"); - } - } - onClicked: { - if ( manager.isDownloading && pluginList.activePlugin == model ) { - manager.cancelDownload(); - } else { - pluginList.activePlugin = model; - manager.downloadAndInstallPlugin( model.file_location ); - } - } - style: ButtonStyle { - background: Rectangle { - color: UM.Theme.getColor("primary") - implicitWidth: 72 - implicitHeight: 30 - // radius: 4 - } - label: Text { - verticalAlignment: Text.AlignVCenter - color: "white" - text: control.text - horizontalAlignment: Text.AlignHCenter - } - } - } - ProgressBar { - id: progressbar - minimumValue: 0; - maximumValue: 100 - anchors.left: installButton.left - anchors.right: installButton.right - anchors.top: installButton.bottom - anchors.topMargin: 4 - value: manager.isDownloading ? manager.downloadProgress : 0 - visible: manager.isDownloading && pluginList.activePlugin == model - style: ProgressBarStyle { - background: Rectangle { - color: "lightgray" - implicitHeight: 6 - } - progress: Rectangle { - color: UM.Theme.getColor("primary") - } - } - } - + label: Text { + verticalAlignment: Text.AlignVCenter + color: "grey" + text: control.text + horizontalAlignment: Text.AlignHCenter } } } } + UM.I18nCatalog { id: catalog; name: "cura" } Connections { diff --git a/plugins/PluginBrowser/PluginEntry.qml b/plugins/PluginBrowser/PluginEntry.qml new file mode 100644 index 0000000000..d53e839094 --- /dev/null +++ b/plugins/PluginBrowser/PluginEntry.qml @@ -0,0 +1,473 @@ +// Copyright (c) 2017 Ultimaker B.V. +// PluginBrowser is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.2 +import QtQuick.Dialogs 1.1 +import QtQuick.Window 2.2 +import QtQuick.Controls 1.4 +import QtQuick.Controls.Styles 1.4 + +// TODO: Switch to QtQuick.Controls 2.x and remove QtQuick.Controls.Styles + +import UM 1.1 as UM + +Component { + id: pluginDelegate + + Rectangle { + + // Don't show required plugins as they can't be managed anyway: + height: !model.required ? 84 : 0 + visible: !model.required ? true : false + color: "transparent" + anchors { + left: parent.left + leftMargin: UM.Theme.getSize("default_margin").width + right: parent.right + rightMargin: UM.Theme.getSize("default_margin").width + } + + + // Bottom border: + Rectangle { + color: UM.Theme.getColor("lining") + width: parent.width + height: 1 + anchors.bottom: parent.bottom + } + + // Plugin info + Column { + id: pluginInfo + + property var color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") + + // Styling: + height: parent.height + anchors { + left: parent.left + top: parent.top + topMargin: UM.Theme.getSize("default_margin").height + right: authorInfo.left + rightMargin: UM.Theme.getSize("default_margin").width + } + + + Label { + text: model.name + width: parent.width + height: 24 + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + font { + pixelSize: 13 + bold: true + } + color: pluginInfo.color + } + + Text { + text: model.description + width: parent.width + height: 36 + clip: true + wrapMode: Text.WordWrap + color: pluginInfo.color + elide: Text.ElideRight + } + } + + // Author info + Column { + id: authorInfo + width: 192 + height: parent.height + anchors { + top: parent.top + topMargin: UM.Theme.getSize("default_margin").height + right: pluginActions.left + rightMargin: UM.Theme.getSize("default_margin").width + } + + Label { + text: ""+model.author+"" + width: parent.width + height: 24 + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignLeft + onLinkActivated: Qt.openUrlExternally("mailto:"+model.author_email+"?Subject=Cura: "+model.name+" Plugin") + color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") + } + } + + // Plugin actions + Row { + id: pluginActions + + width: 96 + height: parent.height + anchors { + top: parent.top + right: parent.right + topMargin: UM.Theme.getSize("default_margin").height + } + layoutDirection: Qt.RightToLeft + spacing: UM.Theme.getSize("default_margin").width + + // For 3rd-Party Plugins: + Button { + id: installButton + text: { + if ( manager.isDownloading && pluginList.activePlugin == model ) { + return catalog.i18nc( "@action:button", "Cancel" ); + } else { + if (model.can_upgrade) { + return catalog.i18nc("@action:button", "Update"); + } + return catalog.i18nc("@action:button", "Install"); + } + } + visible: model.external && ((model.status !== "installed") || model.can_upgrade) + style: ButtonStyle { + background: Rectangle { + implicitWidth: 96 + implicitHeight: 30 + color: "transparent" + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Label { + text: control.text + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: { + if ( manager.isDownloading && pluginList.activePlugin == model ) { + manager.cancelDownload(); + } else { + pluginList.activePlugin = model; + if ( model.can_upgrade ) { + manager.downloadAndInstallPlugin( model.update_url ); + } else { + manager.downloadAndInstallPlugin( model.update_url ); + } + + } + } + } + Button { + id: removeButton + text: "Uninstall" + visible: model.external && model.status == "installed" + enabled: !manager.isDownloading + style: ButtonStyle { + background: Rectangle { + implicitWidth: 96 + implicitHeight: 30 + color: "transparent" + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Text { + text: control.text + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: manager.removePlugin( model.id ) + } + + // For Ultimaker Plugins: + Button { + id: enableButton + text: "Enable" + visible: !model.external && model.enabled == false + style: ButtonStyle { + background: Rectangle { + implicitWidth: 96 + implicitHeight: 30 + color: "transparent" + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Text { + text: control.text + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: { + manager.enablePlugin(model.id); + } + } + Button { + id: disableButton + text: "Disable" + visible: !model.external && model.enabled == true + style: ButtonStyle { + background: Rectangle { + implicitWidth: 96 + implicitHeight: 30 + color: "transparent" + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Text { + text: control.text + color: UM.Theme.getColor("text") + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + } + onClicked: { + manager.disablePlugin(model.id); + } + } + /* + Rectangle { + id: removeControls + visible: model.status == "installed" && model.enabled + width: 96 + height: 30 + color: "transparent" + Button { + id: removeButton + text: "Disable" + enabled: { + if ( manager.isDownloading && pluginList.activePlugin == model ) { + return false; + } else if ( model.required ) { + return false; + } else { + return true; + } + } + onClicked: { + manager.disablePlugin(model.id); + } + style: ButtonStyle { + background: Rectangle { + color: "white" + implicitWidth: 96 + implicitHeight: 30 + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Text { + verticalAlignment: Text.AlignVCenter + color: "grey" + text: control.text + horizontalAlignment: Text.AlignLeft + } + } + } + Button { + id: removeDropDown + property bool open: false + UM.RecolorImage { + anchors.centerIn: parent + height: 10 + width: 10 + source: UM.Theme.getIcon("arrow_bottom") + color: "grey" + } + enabled: { + if ( manager.isDownloading && pluginList.activePlugin == model ) { + return false; + } else if ( model.required ) { + return false; + } else { + return true; + } + } + anchors.right: parent.right + style: ButtonStyle { + background: Rectangle { + color: "transparent" + implicitWidth: 30 + implicitHeight: 30 + } + label: Text { + verticalAlignment: Text.AlignVCenter + color: "grey" + text: control.text + horizontalAlignment: Text.AlignHCenter + } + } + + + + // For the disable option: + // onClicked: pluginList.model.setEnabled(model.id, checked) + + onClicked: { + if ( !removeDropDown.open ) { + removeDropDown.open = true + } + else { + removeDropDown.open = false + } + } + } + + Rectangle { + id: divider + width: 1 + height: parent.height + anchors.right: removeDropDown.left + color: UM.Theme.getColor("lining") + } + + Column { + id: options + anchors { + top: removeButton.bottom + left: parent.left + right: parent.right + } + height: childrenRect.height + visible: removeDropDown.open + + Button { + id: disableButton + text: "Remove" + height: 30 + width: parent.width + onClicked: { + removeDropDown.open = false; + manager.removePlugin( model.id ); + } + } + } + } + */ + /* + Button { + id: enableButton + visible: !model.enabled && model.status == "installed" + onClicked: manager.enablePlugin( model.id ); + + text: "Enable" + style: ButtonStyle { + background: Rectangle { + color: "transparent" + implicitWidth: 96 + implicitHeight: 30 + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Text { + verticalAlignment: Text.AlignVCenter + color: UM.Theme.getColor("text") + text: control.text + horizontalAlignment: Text.AlignHCenter + } + } + } + + Button { + id: updateButton + visible: model.status == "installed" && model.can_upgrade && model.enabled + // visible: model.already_installed + text: { + // If currently downloading: + if ( manager.isDownloading && pluginList.activePlugin == model ) { + return catalog.i18nc( "@action:button", "Cancel" ); + } else { + return catalog.i18nc("@action:button", "Update"); + } + } + style: ButtonStyle { + background: Rectangle { + color: UM.Theme.getColor("primary") + implicitWidth: 96 + implicitHeight: 30 + // radius: 4 + } + label: Text { + verticalAlignment: Text.AlignVCenter + color: "white" + text: control.text + horizontalAlignment: Text.AlignHCenter + } + } + } + Button { + id: externalControls + visible: model.status == "available" ? true : false + text: { + // If currently downloading: + if ( manager.isDownloading && pluginList.activePlugin == model ) { + return catalog.i18nc( "@action:button", "Cancel" ); + } else { + return catalog.i18nc("@action:button", "Install"); + } + } + onClicked: { + if ( manager.isDownloading && pluginList.activePlugin == model ) { + manager.cancelDownload(); + } else { + pluginList.activePlugin = model; + manager.downloadAndInstallPlugin( model.file_location ); + } + } + style: ButtonStyle { + background: Rectangle { + color: "transparent" + implicitWidth: 96 + implicitHeight: 30 + border { + width: 1 + color: UM.Theme.getColor("lining") + } + } + label: Text { + verticalAlignment: Text.AlignVCenter + color: "grey" + text: control.text + horizontalAlignment: Text.AlignHCenter + } + } + } + */ + ProgressBar { + id: progressbar + minimumValue: 0; + maximumValue: 100 + anchors.left: installButton.left + anchors.right: installButton.right + anchors.top: installButton.bottom + anchors.topMargin: 4 + value: manager.isDownloading ? manager.downloadProgress : 0 + visible: manager.isDownloading && pluginList.activePlugin == model + style: ProgressBarStyle { + background: Rectangle { + color: "lightgray" + implicitHeight: 6 + } + progress: Rectangle { + color: UM.Theme.getColor("primary") + } + } + } + + } + } +}