diff --git a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
index 0ace432a2a..20e8fe548a 100644
--- a/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxDetailTile.qml
@@ -48,7 +48,7 @@ Rectangle
Button {
id: installButton
text: {
- if ( manager.isDownloading )
+ if ( manager.isDownloading && manager.activePackage == model )
{
return catalog.i18nc("@action:button", "Cancel")
}
@@ -61,8 +61,7 @@ Rectangle
{
if ( manager.isDownloading )
{
- return true
- // return manager.activePackage == model ? true : false
+ return manager.activePackage == model ? true : false
}
else
{
@@ -75,7 +74,7 @@ Rectangle
{
implicitWidth: 96
implicitHeight: 30
- color: UM.Theme.getColor("primary")
+ color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary")
}
label: Label
{
@@ -87,7 +86,8 @@ Rectangle
}
onClicked:
{
- console.log( "MODEL", model.download_url )
+ console.log( "MODEL", model.id )
+ manager.activePackage = model
// if ( manager.isDownloading && manager.activePackage == model )
if ( manager.isDownloading )
{
diff --git a/plugins/Toolbox/resources/qml/ToolboxFooter.qml b/plugins/Toolbox/resources/qml/ToolboxFooter.qml
index b1ef00f313..598514a176 100644
--- a/plugins/Toolbox/resources/qml/ToolboxFooter.qml
+++ b/plugins/Toolbox/resources/qml/ToolboxFooter.qml
@@ -11,36 +11,51 @@ import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
-Rectangle {
+Item
+{
width: parent.width
height: UM.Theme.getSize("base_unit").height * 4
- color: "transparent"
anchors.bottom: parent.bottom
-
- Label {
+ Label
+ {
visible: manager.restartRequired
text: "You will need to restart Cura before changes in plugins have effect."
- height: 30
+ height: UM.Theme.getSize("base_unit").height * 2
verticalAlignment: Text.AlignVCenter
+ anchors
+ {
+ top: closeButton.top
+ left: parent.left
+ leftMargin: UM.Theme.getSize("default_margin").width
+ }
}
- Button {
- id: restartChangedButton
+ Button
+ {
+ id: restartButton
text: "Quit Cura"
- anchors.right: closeButton.left
- anchors.rightMargin: UM.Theme.getSize("default_margin").width
+ anchors
+ {
+ top: closeButton.top
+ right: closeButton.left
+ rightMargin: UM.Theme.getSize("default_margin").width
+ }
visible: manager.restartRequired
iconName: "dialog-restart"
onClicked: manager.restart()
- style: ButtonStyle {
- background: Rectangle {
+ style: ButtonStyle
+ {
+ background: Rectangle
+ {
implicitWidth: 96
- implicitHeight: 30
- color: UM.Theme.getColor("primary")
+ implicitHeight: UM.Theme.getSize("base_unit").height * 2
+ color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary")
}
- label: Text {
+ label: Text
+ {
verticalAlignment: Text.AlignVCenter
color: UM.Theme.getColor("button_text")
- font {
+ font
+ {
pixelSize: 13
bold: true
}
@@ -50,12 +65,15 @@ Rectangle {
}
}
- Button {
+ Button
+ {
id: closeButton
text: catalog.i18nc("@action:button", "Close")
iconName: "dialog-close"
- onClicked: {
- if ( manager.isDownloading ) {
+ onClicked:
+ {
+ if ( manager.isDownloading )
+ {
manager.cancelDownload()
}
base.close();
@@ -65,19 +83,23 @@ Rectangle {
top: parent.top
topMargin: UM.Theme.getSize("default_margin").height
right: parent.right
- rightMargin: UM.Theme.getSize("default_margin").height
+ rightMargin: UM.Theme.getSize("default_margin").width
}
- style: ButtonStyle {
- background: Rectangle {
+ style: ButtonStyle
+ {
+ background: Rectangle
+ {
color: "transparent"
implicitWidth: 96
- implicitHeight: 30
- border {
+ implicitHeight: UM.Theme.getSize("base_unit").height * 2
+ border
+ {
width: 1
color: UM.Theme.getColor("lining")
}
}
- label: Text {
+ label: Text
+ {
verticalAlignment: Text.AlignVCenter
color: UM.Theme.getColor("text")
text: control.text
diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py
index b80757309d..fef45dec7c 100644
--- a/plugins/Toolbox/src/Toolbox.py
+++ b/plugins/Toolbox/src/Toolbox.py
@@ -52,7 +52,7 @@ class Toolbox(QObject, Extension):
self._packages_model = None # Model that list the remote available packages
self._showcase_model = None
self._authors_model = None
-
+ self._installed_model = None
# These properties are for keeping track of the UI state:
# ----------------------------------------------------------------------
@@ -73,12 +73,6 @@ class Toolbox(QObject, Extension):
# to "author" or a plugin name if it is set to "detail").
self._view_selection = ""
- # For any view page above, self._packages_model can be filtered.
- # For example:
- # self._view_category = "material"
- # if self._view_page == "author":
- # filter with "author == self._view_selection"
-
# Active package refers to which package is currently being downloaded,
# installed, or otherwise modified.
self._active_package = None
@@ -88,15 +82,11 @@ class Toolbox(QObject, Extension):
self._current_view = "plugins"
self._detail_data = {} # Extraneous since can just use the data prop of the model.
-
-
self._restart_required = False
self._dialog = None
self._restartDialog = None
-
-
self._request_header = [b"User-Agent",
str.encode("%s/%s (%s %s)" % (Application.getInstance().getApplicationName(),
Application.getInstance().getVersion(),
@@ -178,56 +168,12 @@ class Toolbox(QObject, Extension):
dialog = Application.getInstance().createQmlComponent(path, {"manager": self})
return dialog
- ## Checks if the downloaded plugin ZIP file contains a license file or not.
- # If it does, it will show a popup dialog displaying the license to the user. The plugin will be installed if the
- # user accepts the license.
- # If there is no license file, the plugin will be directory installed.
- def _checkPluginLicenseOrInstall(self, file_path):
- with zipfile.ZipFile(file_path, "r") as zip_ref:
- plugin_id = None
- for file in zip_ref.infolist():
- if file.filename.endswith("/"):
- plugin_id = file.filename.strip("/")
- break
-
- if plugin_id is None:
- msg = i18n_catalog.i18nc("@info:status", "Failed to get plugin ID from {0}", file_path)
- msg_title = i18n_catalog.i18nc("@info:tile", "Warning")
- self._progress_message = Message(msg, lifetime=0, dismissable=False, title = msg_title)
- return
-
- # find a potential license file
- plugin_root_dir = plugin_id + "/"
- license_file = None
- for f in zip_ref.infolist():
- # skip directories (with file_size = 0) and files not in the plugin directory
- if f.file_size == 0 or not f.filename.startswith(plugin_root_dir):
- continue
- file_name = os.path.basename(f.filename).lower()
- file_base_name, file_ext = os.path.splitext(file_name)
- if file_base_name in ["license", "licence"]:
- license_file = f.filename
- break
-
- # show a dialog for user to read and accept/decline the license
- if license_file is not None:
- Logger.log("i", "Found license file for plugin [%s], showing the license dialog to the user", plugin_id)
- license_content = zip_ref.read(license_file).decode('utf-8')
- self.openLicenseDialog(plugin_id, license_content, file_path)
- return
-
- # there is no license file, directly install the plugin
- self.installPlugin(file_path)
-
@pyqtSlot(str)
def installPlugin(self, file_path):
# Ensure that it starts with a /, as otherwise it doesn't work on windows.
if not file_path.startswith("/"):
- location = "/" + file_path
- else:
- location = file_path
-
- result = PluginRegistry.getInstance().installPlugin("file://" + location)
+ file_path = "/" + file_path
+ result = PluginRegistry.getInstance().installPlugin("file://" + file_path)
self._newly_installed_plugin_ids.append(result["id"])
self.packagesMetadataChanged.emit()
@@ -294,9 +240,6 @@ class Toolbox(QObject, Extension):
return self._packages_model is not None
def _checkCanUpgrade(self, id, version):
-
- # 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._packages_metadata:
if id == plugin["id"]:
@@ -474,16 +417,51 @@ class Toolbox(QObject, Extension):
# must not delete the temporary file on Windows
self._temp_plugin_file = tempfile.NamedTemporaryFile(mode = "w+b", suffix = ".curaplugin", delete = False)
- location = self._temp_plugin_file.name
+ file_path = self._temp_plugin_file.name
# write first and close, otherwise on Windows, it cannot read the file
self._temp_plugin_file.write(self._download_reply.readAll())
self._temp_plugin_file.close()
- self._checkPluginLicenseOrInstall(location)
+ self._onDownloadComplete(file_path)
return
- def _onDownloadComplete(self, location):
+ def _onDownloadComplete(self, file_path):
+ with zipfile.ZipFile(file_path, "r") as zip_ref:
+ plugin_id = None
+ for file in zip_ref.infolist():
+ if file.filename.endswith("/"):
+ plugin_id = file.filename.strip("/")
+ break
+
+ if plugin_id is None:
+ msg = i18n_catalog.i18nc("@info:status", "Failed to get plugin ID from {0}", file_path)
+ msg_title = i18n_catalog.i18nc("@info:tile", "Warning")
+ self._progress_message = Message(msg, lifetime=0, dismissable=False, title = msg_title)
+ return
+
+ # find a potential license file
+ plugin_root_dir = plugin_id + "/"
+ license_file = None
+ for f in zip_ref.infolist():
+ # skip directories (with file_size = 0) and files not in the plugin directory
+ if f.file_size == 0 or not f.filename.startswith(plugin_root_dir):
+ continue
+ file_name = os.path.basename(f.filename).lower()
+ file_base_name, file_ext = os.path.splitext(file_name)
+ if file_base_name in ["license", "licence"]:
+ license_file = f.filename
+ break
+
+ # show a dialog for user to read and accept/decline the license
+ if license_file is not None:
+ Logger.log("i", "Found license file for plugin [%s], showing the license dialog to the user", plugin_id)
+ license_content = zip_ref.read(license_file).decode('utf-8')
+ self.openLicenseDialog(plugin_id, license_content, file_path)
+ return
+
+ # there is no license file, directly install the plugin
+ self.installPlugin(file_path)
return