From b7904d6e056b1edbac2ac8b75755704d4ad47f75 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 17 Dec 2018 13:04:23 +0100 Subject: [PATCH 01/43] Unify the CuraDrive plugin with the rest of the items in Cura For instance, the buttons were converted to either primary buttons or secondary buttons. A new CheckBox component was created in Cura in order to reuse it in the future. Contributes to CURA-6005. --- .../src/qml/components/ActionButton.qml | 67 ------------------- .../src/qml/components/ActionCheckBox.qml | 49 -------------- .../src/qml/components/ActionToolTip.qml | 4 +- .../src/qml/components/BackupListFooter.qml | 10 +-- .../src/qml/components/BackupListItem.qml | 15 +++-- plugins/CuraDrive/src/qml/main.qml | 6 +- .../CuraDrive/src/qml/pages/WelcomePage.qml | 9 ++- resources/qml/ActionButton.qml | 15 +++++ resources/qml/CheckBox.qml | 61 +++++++++++++++++ resources/qml/Cura.qml | 11 +++ resources/qml/qmldir | 3 +- resources/themes/cura-light/styles.qml | 2 +- 12 files changed, 115 insertions(+), 137 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/components/ActionButton.qml delete mode 100644 plugins/CuraDrive/src/qml/components/ActionCheckBox.qml create mode 100644 resources/qml/CheckBox.qml diff --git a/plugins/CuraDrive/src/qml/components/ActionButton.qml b/plugins/CuraDrive/src/qml/components/ActionButton.qml deleted file mode 100644 index 843079ed88..0000000000 --- a/plugins/CuraDrive/src/qml/components/ActionButton.qml +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -import QtQuick 2.7 -import QtQuick.Controls 2.1 -import QtQuick.Layouts 1.3 - -import UM 1.1 as UM - -Button -{ - id: button - property alias cursorShape: mouseArea.cursorShape - property var iconSource: "" - property var busy: false - property var color: UM.Theme.getColor("primary") - property var hoverColor: UM.Theme.getColor("primary_hover") - property var disabledColor: color - property var textColor: UM.Theme.getColor("button_text") - property var textHoverColor: UM.Theme.getColor("button_text_hover") - property var textDisabledColor: textColor - property var textFont: UM.Theme.getFont("action_button") - - contentItem: RowLayout - { - Icon - { - id: buttonIcon - iconSource: button.iconSource - width: 16 * screenScaleFactor - color: button.hovered ? button.textHoverColor : button.textColor - visible: button.iconSource != "" && !loader.visible - } - - Icon - { - id: loader - iconSource: "../images/loading.gif" - width: 16 * screenScaleFactor - color: button.hovered ? button.textHoverColor : button.textColor - visible: button.busy - animated: true - } - - Label - { - id: buttonText - text: button.text - color: button.enabled ? (button.hovered ? button.textHoverColor : button.textColor): button.textDisabledColor - font: button.textFont - visible: button.text != "" - renderType: Text.NativeRendering - } - } - - background: Rectangle - { - color: button.enabled ? (button.hovered ? button.hoverColor : button.color) : button.disabledColor - } - - MouseArea - { - id: mouseArea - anchors.fill: parent - onPressed: mouse.accepted = false - hoverEnabled: true - cursorShape: button.enabled ? (hovered ? Qt.PointingHandCursor : Qt.ArrowCursor) : Qt.ForbiddenCursor - } -} diff --git a/plugins/CuraDrive/src/qml/components/ActionCheckBox.qml b/plugins/CuraDrive/src/qml/components/ActionCheckBox.qml deleted file mode 100644 index 71f5e6035d..0000000000 --- a/plugins/CuraDrive/src/qml/components/ActionCheckBox.qml +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -import QtQuick 2.7 -import QtQuick.Controls 2.1 -import QtQuick.Layouts 1.3 - -import UM 1.3 as UM - -CheckBox -{ - id: checkbox - hoverEnabled: true - - property var label: "" - - indicator: Rectangle { - implicitWidth: 30 * screenScaleFactor - implicitHeight: 30 * screenScaleFactor - x: 0 - y: Math.round(parent.height / 2 - height / 2) - color: UM.Theme.getColor("sidebar") - border.color: UM.Theme.getColor("text") - - Rectangle { - width: 14 * screenScaleFactor - height: 14 * screenScaleFactor - x: 8 * screenScaleFactor - y: 8 * screenScaleFactor - color: UM.Theme.getColor("primary") - visible: checkbox.checked - } - } - - contentItem: Label { - anchors - { - left: checkbox.indicator.right - leftMargin: 5 * screenScaleFactor - } - text: catalog.i18nc("@checkbox:description", "Auto Backup") - color: UM.Theme.getColor("text") - renderType: Text.NativeRendering - verticalAlignment: Text.AlignVCenter - } - - ActionToolTip - { - text: checkbox.label - } -} diff --git a/plugins/CuraDrive/src/qml/components/ActionToolTip.qml b/plugins/CuraDrive/src/qml/components/ActionToolTip.qml index 93b92bc2df..7401221328 100644 --- a/plugins/CuraDrive/src/qml/components/ActionToolTip.qml +++ b/plugins/CuraDrive/src/qml/components/ActionToolTip.qml @@ -14,7 +14,7 @@ ToolTip background: Rectangle { - color: UM.Theme.getColor("sidebar") + color: UM.Theme.getColor("main_background") border.color: UM.Theme.getColor("primary") border.width: 1 * screenScaleFactor } @@ -23,7 +23,7 @@ ToolTip { text: tooltip.text color: UM.Theme.getColor("text") - font: UM.Theme.getFont("very_small") + font: UM.Theme.getFont("default") renderType: Text.NativeRendering } } diff --git a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml index 80f47d6cba..1e7fc16801 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml @@ -4,6 +4,7 @@ import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 import UM 1.3 as UM +import Cura 1.0 as Cura import "../components" @@ -13,7 +14,7 @@ RowLayout width: parent.width property bool showInfoButton: false - ActionButton + Cura.PrimaryButton { id: infoButton text: catalog.i18nc("@button", "Want more?") @@ -22,7 +23,7 @@ RowLayout visible: backupListFooter.showInfoButton } - ActionButton + Cura.PrimaryButton { id: createBackupButton text: catalog.i18nc("@button", "Backup Now") @@ -32,11 +33,12 @@ RowLayout busy: CuraDrive.isCreatingBackup } - ActionCheckBox + Cura.CheckBox { id: autoBackupEnabled checked: CuraDrive.autoBackupEnabled onClicked: CuraDrive.toggleAutoBackup(autoBackupEnabled.checked) - label: catalog.i18nc("@checkbox:description", "Automatically create a backup each day that Cura is started.") + text: catalog.i18nc("@checkbox:description", "Auto Backup") + tooltip: catalog.i18nc("@checkbox:description", "Automatically create a backup each day that Cura is started.") } } diff --git a/plugins/CuraDrive/src/qml/components/BackupListItem.qml b/plugins/CuraDrive/src/qml/components/BackupListItem.qml index abe9a1acf9..ad1ce5f9df 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItem.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItem.qml @@ -5,6 +5,7 @@ import QtQuick.Layouts 1.3 import QtQuick.Dialogs 1.1 import UM 1.1 as UM +import Cura 1.0 as Cura Item { @@ -29,7 +30,7 @@ Item width: parent.width height: 50 * screenScaleFactor - ActionButton + Cura.ActionButton { color: "transparent" hoverColor: "transparent" @@ -61,18 +62,18 @@ Item renderType: Text.NativeRendering } - ActionButton + Cura.SecondaryButton { text: catalog.i18nc("@button", "Restore") - color: "transparent" - hoverColor: "transparent" - textColor: UM.Theme.getColor("text") - textHoverColor: UM.Theme.getColor("text_link") +// color: "transparent" +// hoverColor: "transparent" +// textColor: UM.Theme.getColor("text") +// textHoverColor: UM.Theme.getColor("text_link") enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup onClicked: confirmRestoreDialog.visible = true } - ActionButton + Cura.ActionButton { color: "transparent" hoverColor: "transparent" diff --git a/plugins/CuraDrive/src/qml/main.qml b/plugins/CuraDrive/src/qml/main.qml index 4a2219cf1f..359f8dd725 100644 --- a/plugins/CuraDrive/src/qml/main.qml +++ b/plugins/CuraDrive/src/qml/main.qml @@ -14,11 +14,11 @@ Window id: curaDriveDialog minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width) minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height) - maximumWidth: minimumWidth * 1.2 - maximumHeight: minimumHeight * 1.2 + maximumWidth: Math.round(minimumWidth * 1.2) + maximumHeight: Math.round(minimumHeight * 1.2) width: minimumWidth height: minimumHeight - color: UM.Theme.getColor("sidebar") + color: UM.Theme.getColor("main_background") title: catalog.i18nc("@title:window", "Cura Backups") // Globally available. diff --git a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml index 882656dc4a..b7f96d162a 100644 --- a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml +++ b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml @@ -38,11 +38,14 @@ Column renderType: Text.NativeRendering } - ActionButton + Cura.PrimaryButton { id: loginButton - onClicked: Cura.API.account.login() - text: catalog.i18nc("@button", "Sign In") + width: UM.Theme.getSize("account_button").width + height: UM.Theme.getSize("account_button").height anchors.horizontalCenter: parent.horizontalCenter + text: catalog.i18nc("@button", "Sign in") + onClicked: Cura.API.account.login() + fixedWidthMode: true } } diff --git a/resources/qml/ActionButton.qml b/resources/qml/ActionButton.qml index 3a9552cd9c..573ead2910 100644 --- a/resources/qml/ActionButton.qml +++ b/resources/qml/ActionButton.qml @@ -4,6 +4,7 @@ import QtQuick 2.7 import QtQuick.Controls 2.1 import QtGraphicalEffects 1.0 // For the dropshadow + import UM 1.1 as UM import Cura 1.0 as Cura @@ -30,6 +31,7 @@ Button property color outlineDisabledColor: outlineColor property alias shadowColor: shadow.color property alias shadowEnabled: shadow.visible + property alias busy: busyIndicator.visible // This property is used to indicate whether the button has a fixed width or the width would depend on the contents // Be careful when using fixedWidthMode, the translated texts can be too long that they won't fit. In any case, @@ -117,4 +119,17 @@ Button delay: 500 visible: text != "" && button.hovered } + + BusyIndicator { + id: busyIndicator + + anchors { + centerIn: parent + } + + width: height + height: parent.height + + visible: false + } } \ No newline at end of file diff --git a/resources/qml/CheckBox.qml b/resources/qml/CheckBox.qml new file mode 100644 index 0000000000..7a79182a4b --- /dev/null +++ b/resources/qml/CheckBox.qml @@ -0,0 +1,61 @@ +// Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + +import QtQuick 2.7 +import QtQuick.Controls 2.1 + +import UM 1.3 as UM + +CheckBox +{ + id: checkbox + hoverEnabled: true + + property alias tooltip: tooltip.text + + indicator: Rectangle { + implicitWidth: UM.Theme.getSize("checkbox").width + implicitHeight: UM.Theme.getSize("checkbox").height + x: 0 + y: Math.round(parent.height / 2 - height / 2) + color: UM.Theme.getColor("main_background") + radius: UM.Theme.getSize("checkbox_radius").width + border.width: UM.Theme.getSize("default_lining").width + border.color: checkbox.hovered ? UM.Theme.getColor("checkbox_border_hover") : UM.Theme.getColor("checkbox_border") + + UM.RecolorImage + { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: Math.round(parent.width / 2.5) + height: Math.round(parent.height / 2.5) + sourceSize.height: width + color: UM.Theme.getColor("checkbox_mark") + source: UM.Theme.getIcon("check") + opacity: checkbox.checked + Behavior on opacity { NumberAnimation { duration: 100; } } + } + } + + contentItem: Label { + anchors + { + left: checkbox.indicator.right + leftMargin: UM.Theme.getSize("narrow_margin").width + } + text: checkbox.text + color: UM.Theme.getColor("checkbox_text") + font: UM.Theme.getFont("default") + renderType: Text.NativeRendering + elide: Text.ElideRight + verticalAlignment: Text.AlignVCenter + } + + ToolTip + { + id: tooltip + text: "" + delay: 500 + visible: text != "" && checkbox.hovered + } +} diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 8ab943b93b..71b97fa6f4 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -123,6 +123,17 @@ UM.MainWindow } } } + + // This is a placehoder for adding a pattern in the header + Image + { + id: backgroundPattern + anchors.fill: parent + fillMode: Image.Tile + source: UM.Theme.getImage("header_pattern") + horizontalAlignment: Image.AlignLeft + verticalAlignment: Image.AlignTop + } } MainWindowHeader diff --git a/resources/qml/qmldir b/resources/qml/qmldir index 1dc21150ce..4e28e12f62 100644 --- a/resources/qml/qmldir +++ b/resources/qml/qmldir @@ -14,4 +14,5 @@ PrinterTypeLabel 1.0 PrinterTypeLabel.qml ViewsSelector 1.0 ViewsSelector.qml ToolbarButton 1.0 ToolbarButton.qml SettingView 1.0 SettingView.qml -ProfileMenu 1.0 ProfileMenu.qml \ No newline at end of file +ProfileMenu 1.0 ProfileMenu.qml +CheckBox 1.0 CheckBox.qml \ No newline at end of file diff --git a/resources/themes/cura-light/styles.qml b/resources/themes/cura-light/styles.qml index 89729fc08c..95f811c3aa 100755 --- a/resources/themes/cura-light/styles.qml +++ b/resources/themes/cura-light/styles.qml @@ -478,7 +478,7 @@ QtObject color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_hover") : (control.enabled ? Theme.getColor("checkbox") : Theme.getColor("checkbox_disabled")) Behavior on color { ColorAnimation { duration: 50; } } - radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : UM.Theme.getSize("checkbox_radius").width + radius: control.exclusiveGroup ? Math.round(Theme.getSize("checkbox").width / 2) : Theme.getSize("checkbox_radius").width border.width: Theme.getSize("default_lining").width border.color: (control.hovered || control._hovered) ? Theme.getColor("checkbox_border_hover") : Theme.getColor("checkbox_border") From 02825a062fd4e2413938fb8eee3969d7c3cbdc06 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Mon, 17 Dec 2018 13:38:41 +0100 Subject: [PATCH 02/43] Change the remove and the info buttons Contributes to CURA-6005. --- .../src/qml/components/ActionToolTip.qml | 29 ------------------ .../src/qml/components/BackupList.qml | 2 +- .../src/qml/components/BackupListFooter.qml | 4 +-- .../src/qml/components/BackupListItem.qml | 30 ++++++++----------- plugins/CuraDrive/src/qml/images/delete.svg | 7 ----- plugins/CuraDrive/src/qml/images/info.svg | 4 --- resources/qml/ActionButton.qml | 2 +- 7 files changed, 17 insertions(+), 61 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/components/ActionToolTip.qml delete mode 100644 plugins/CuraDrive/src/qml/images/delete.svg delete mode 100644 plugins/CuraDrive/src/qml/images/info.svg diff --git a/plugins/CuraDrive/src/qml/components/ActionToolTip.qml b/plugins/CuraDrive/src/qml/components/ActionToolTip.qml deleted file mode 100644 index 7401221328..0000000000 --- a/plugins/CuraDrive/src/qml/components/ActionToolTip.qml +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -import QtQuick 2.7 -import QtQuick.Controls 2.1 -import QtQuick.Layouts 1.3 - -import UM 1.1 as UM - -ToolTip -{ - id: tooltip - visible: parent.hovered - opacity: 0.9 - delay: 500 - - background: Rectangle - { - color: UM.Theme.getColor("main_background") - border.color: UM.Theme.getColor("primary") - border.width: 1 * screenScaleFactor - } - - contentItem: Label - { - text: tooltip.text - color: UM.Theme.getColor("text") - font: UM.Theme.getFont("default") - renderType: Text.NativeRendering - } -} diff --git a/plugins/CuraDrive/src/qml/components/BackupList.qml b/plugins/CuraDrive/src/qml/components/BackupList.qml index 231f25afc8..a19d1f0ae7 100644 --- a/plugins/CuraDrive/src/qml/components/BackupList.qml +++ b/plugins/CuraDrive/src/qml/components/BackupList.qml @@ -18,7 +18,7 @@ ListView BackupListItem { id: backupListItem - width: parent.width + width: parent.width - UM.Theme.getSize("default_margin").width // Add a margin, otherwise the scrollbar is be on top of the right most component } Divider diff --git a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml index 1e7fc16801..72dc3df044 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml @@ -18,7 +18,7 @@ RowLayout { id: infoButton text: catalog.i18nc("@button", "Want more?") - iconSource: "../images/info.svg" + iconSource: UM.Theme.getIcon("info") onClicked: Qt.openUrlExternally("https://goo.gl/forms/QACEP8pP3RV60QYG2") visible: backupListFooter.showInfoButton } @@ -28,7 +28,7 @@ RowLayout id: createBackupButton text: catalog.i18nc("@button", "Backup Now") iconSource: "../images/backup.svg" - enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup + enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup && !backupListFooter.showInfoButton onClicked: CuraDrive.createBackup() busy: CuraDrive.isCreatingBackup } diff --git a/plugins/CuraDrive/src/qml/components/BackupListItem.qml b/plugins/CuraDrive/src/qml/components/BackupListItem.qml index ad1ce5f9df..a84caeb6ab 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItem.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItem.qml @@ -26,17 +26,17 @@ Item RowLayout { id: dataRow - spacing: UM.Theme.getSize("default_margin").width * 2 + spacing: UM.Theme.getSize("wide_margin").width width: parent.width height: 50 * screenScaleFactor - Cura.ActionButton + UM.SimpleButton { - color: "transparent" - hoverColor: "transparent" - textColor: UM.Theme.getColor("text") - textHoverColor: UM.Theme.getColor("primary") - iconSource: "../images/info.svg" + width: UM.Theme.getSize("section_icon").width + height: UM.Theme.getSize("section_icon").height + color: UM.Theme.getColor("small_button_text") + hoverColor: UM.Theme.getColor("small_button_text_hover") + iconSource: UM.Theme.getIcon("info") onClicked: backupListItem.showDetails = !backupListItem.showDetails } @@ -65,21 +65,17 @@ Item Cura.SecondaryButton { text: catalog.i18nc("@button", "Restore") -// color: "transparent" -// hoverColor: "transparent" -// textColor: UM.Theme.getColor("text") -// textHoverColor: UM.Theme.getColor("text_link") enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup onClicked: confirmRestoreDialog.visible = true } - Cura.ActionButton + UM.SimpleButton { - color: "transparent" - hoverColor: "transparent" - textColor: UM.Theme.getColor("setting_validation_error") - textHoverColor: UM.Theme.getColor("setting_validation_error") - iconSource: "../images/delete.svg" + width: UM.Theme.getSize("message_close").width + height: UM.Theme.getSize("message_close").height + color: UM.Theme.getColor("small_button_text") + hoverColor: UM.Theme.getColor("small_button_text_hover") + iconSource: UM.Theme.getIcon("cross1") onClicked: confirmDeleteDialog.visible = true } } diff --git a/plugins/CuraDrive/src/qml/images/delete.svg b/plugins/CuraDrive/src/qml/images/delete.svg deleted file mode 100644 index 2f6190ad43..0000000000 --- a/plugins/CuraDrive/src/qml/images/delete.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/info.svg b/plugins/CuraDrive/src/qml/images/info.svg deleted file mode 100644 index 36154d6729..0000000000 --- a/plugins/CuraDrive/src/qml/images/info.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/resources/qml/ActionButton.qml b/resources/qml/ActionButton.qml index 573ead2910..2448b9a551 100644 --- a/resources/qml/ActionButton.qml +++ b/resources/qml/ActionButton.qml @@ -55,7 +55,7 @@ Button width: visible ? height : 0 sourceSize.width: width sourceSize.height: height - color: button.hovered ? button.textHoverColor : button.textColor + color: button.enabled ? (button.hovered ? button.textHoverColor : button.textColor) : button.textDisabledColor visible: source != "" && !button.isIconOnRightSide anchors.verticalCenter: parent.verticalCenter } From da69c16e0962231b2d8ae14cc5684d5788f57bf8 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 18 Dec 2018 16:14:13 +0100 Subject: [PATCH 03/43] Split the constants in to files, indicating which constants each file stores. Contributes to CURA-6005. --- cura/API/Account.py | 4 +- ...uraConstants.py => ApplicationMetadata.py} | 96 +++++++------------ cura/CuraApplication.py | 14 +-- cura/UltimakerCloudAuthentication.py | 24 +++++ plugins/CuraDrive/src/Settings.py | 4 +- plugins/Toolbox/src/Toolbox.py | 10 +- 6 files changed, 76 insertions(+), 76 deletions(-) rename cura/{CuraConstants.py => ApplicationMetadata.py} (50%) create mode 100644 cura/UltimakerCloudAuthentication.py diff --git a/cura/API/Account.py b/cura/API/Account.py index 7b4bc32e99..47f67af8ce 100644 --- a/cura/API/Account.py +++ b/cura/API/Account.py @@ -6,7 +6,7 @@ from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty from UM.i18n import i18nCatalog from UM.Message import Message -from cura import CuraConstants +from cura import UltimakerCloudAuthentication from cura.OAuth2.AuthorizationService import AuthorizationService from cura.OAuth2.Models import OAuth2Settings @@ -38,7 +38,7 @@ class Account(QObject): self._logged_in = False self._callback_port = 32118 - self._oauth_root = CuraConstants.CuraCloudAccountAPIRoot + self._oauth_root = UltimakerCloudAuthentication.CuraCloudAccountAPIRoot self._oauth_settings = OAuth2Settings( OAUTH_SERVER_URL= self._oauth_root, diff --git a/cura/CuraConstants.py b/cura/ApplicationMetadata.py similarity index 50% rename from cura/CuraConstants.py rename to cura/ApplicationMetadata.py index 7ca8ea865b..e2ac4453eb 100644 --- a/cura/CuraConstants.py +++ b/cura/ApplicationMetadata.py @@ -1,60 +1,36 @@ -# -# This file contains all constant values in Cura -# - -# ------------- -# Cura Versions -# ------------- -DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura" -DEFAULT_CURA_VERSION = "master" -DEFAULT_CURA_BUILD_TYPE = "" -DEFAULT_CURA_DEBUG_MODE = False -DEFAULT_CURA_SDK_VERSION = "5.0.0" - -try: - from cura.CuraVersion import CuraAppDisplayName # type: ignore -except ImportError: - CuraAppDisplayName = DEFAULT_CURA_DISPLAY_NAME - -try: - from cura.CuraVersion import CuraVersion # type: ignore -except ImportError: - CuraVersion = DEFAULT_CURA_VERSION # [CodeStyle: Reflecting imported value] - -try: - from cura.CuraVersion import CuraBuildType # type: ignore -except ImportError: - CuraBuildType = DEFAULT_CURA_BUILD_TYPE - -try: - from cura.CuraVersion import CuraDebugMode # type: ignore -except ImportError: - CuraDebugMode = DEFAULT_CURA_DEBUG_MODE - -try: - from cura.CuraVersion import CuraSDKVersion # type: ignore -except ImportError: - CuraSDKVersion = DEFAULT_CURA_SDK_VERSION - - -# --------- -# Cloud API -# --------- -DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str -DEFAULT_CLOUD_API_VERSION = "1" # type: str -DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str - -try: - from cura.CuraVersion import CuraCloudAPIRoot # type: ignore -except ImportError: - CuraCloudAPIRoot = DEFAULT_CLOUD_API_ROOT - -try: - from cura.CuraVersion import CuraCloudAPIVersion # type: ignore -except ImportError: - CuraCloudAPIVersion = DEFAULT_CLOUD_API_VERSION - -try: - from cura.CuraVersion import CuraCloudAccountAPIRoot # type: ignore -except ImportError: - CuraCloudAccountAPIRoot = DEFAULT_CLOUD_ACCOUNT_API_ROOT +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +# --------- +# Genearl constants used in Cura +# --------- +DEFAULT_CURA_DISPLAY_NAME = "Ultimaker Cura" +DEFAULT_CURA_VERSION = "master" +DEFAULT_CURA_BUILD_TYPE = "" +DEFAULT_CURA_DEBUG_MODE = False +DEFAULT_CURA_SDK_VERSION = "6.0.0" + +try: + from cura.CuraVersion import CuraAppDisplayName # type: ignore +except ImportError: + CuraAppDisplayName = DEFAULT_CURA_DISPLAY_NAME + +try: + from cura.CuraVersion import CuraVersion # type: ignore +except ImportError: + CuraVersion = DEFAULT_CURA_VERSION # [CodeStyle: Reflecting imported value] + +try: + from cura.CuraVersion import CuraBuildType # type: ignore +except ImportError: + CuraBuildType = DEFAULT_CURA_BUILD_TYPE + +try: + from cura.CuraVersion import CuraDebugMode # type: ignore +except ImportError: + CuraDebugMode = DEFAULT_CURA_DEBUG_MODE + +try: + from cura.CuraVersion import CuraSDKVersion # type: ignore +except ImportError: + CuraSDKVersion = DEFAULT_CURA_SDK_VERSION diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index a7845708e4..748c5c2fc4 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -115,7 +115,7 @@ from cura.ObjectsModel import ObjectsModel from cura.PrinterOutput.NetworkMJPGImage import NetworkMJPGImage -from cura import CuraConstants +from cura import ApplicationMetadata from UM.FlameProfiler import pyqtSlot from UM.Decorators import override @@ -164,11 +164,11 @@ class CuraApplication(QtApplication): def __init__(self, *args, **kwargs): super().__init__(name = "cura", - app_display_name = CuraConstants.CuraAppDisplayName, - version = CuraConstants.CuraVersion, - api_version = CuraConstants.CuraSDKVersion, - buildtype = CuraConstants.CuraBuildType, - is_debug_mode = CuraConstants.CuraDebugMode, + app_display_name = ApplicationMetadata.CuraAppDisplayName, + version = ApplicationMetadata.CuraVersion, + api_version = ApplicationMetadata.CuraSDKVersion, + buildtype = ApplicationMetadata.CuraBuildType, + is_debug_mode = ApplicationMetadata.CuraDebugMode, tray_icon_name = "cura-icon-32.png", **kwargs) @@ -953,7 +953,7 @@ class CuraApplication(QtApplication): engine.rootContext().setContextProperty("CuraApplication", self) engine.rootContext().setContextProperty("PrintInformation", self._print_information) engine.rootContext().setContextProperty("CuraActions", self._cura_actions) - engine.rootContext().setContextProperty("CuraSDKVersion", CuraConstants.CuraSDKVersion) + engine.rootContext().setContextProperty("CuraSDKVersion", ApplicationMetadata.CuraSDKVersion) qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") diff --git a/cura/UltimakerCloudAuthentication.py b/cura/UltimakerCloudAuthentication.py new file mode 100644 index 0000000000..7ebdfd054b --- /dev/null +++ b/cura/UltimakerCloudAuthentication.py @@ -0,0 +1,24 @@ +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +# --------- +# Constants used for the Cloud API +# --------- +DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str +DEFAULT_CLOUD_API_VERSION = "1" # type: str +DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str + +try: + from cura.CuraVersion import CuraCloudAPIRoot # type: ignore +except ImportError: + CuraCloudAPIRoot = DEFAULT_CLOUD_API_ROOT + +try: + from cura.CuraVersion import CuraCloudAPIVersion # type: ignore +except ImportError: + CuraCloudAPIVersion = DEFAULT_CLOUD_API_VERSION + +try: + from cura.CuraVersion import CuraCloudAccountAPIRoot # type: ignore +except ImportError: + CuraCloudAccountAPIRoot = DEFAULT_CLOUD_ACCOUNT_API_ROOT diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index c0df66b950..4ee73ad149 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. from UM import i18nCatalog -from cura import CuraConstants +from cura import UltimakerCloudAuthentication class Settings: @@ -9,7 +9,7 @@ class Settings: Keeps the application settings. """ DRIVE_API_VERSION = 1 - DRIVE_API_URL = "{}/cura-drive/v{}".format(CuraConstants.CuraCloudAPIRoot, str(DRIVE_API_VERSION)) + DRIVE_API_URL = "{}/cura-drive/v{}".format(UltimakerCloudAuthentication.CuraCloudAPIRoot, str(DRIVE_API_VERSION)) AUTO_BACKUP_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled" AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index 2229ab1f67..e7e849f1d2 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -16,8 +16,8 @@ from UM.Extension import Extension from UM.i18n import i18nCatalog from UM.Version import Version -import cura -from cura import CuraConstants +from cura import ApplicationMetadata +from cura import UltimakerCloudAuthentication from cura.CuraApplication import CuraApplication from .AuthorsModel import AuthorsModel @@ -39,9 +39,9 @@ class Toolbox(QObject, Extension): self._application = application # type: CuraApplication - self._sdk_version = CuraConstants.CuraSDKVersion # type: Union[str, int] - self._cloud_api_version = CuraConstants.CuraCloudAPIVersion # type: int - self._cloud_api_root = CuraConstants.CuraCloudAPIRoot # type: str + self._sdk_version = ApplicationMetadata.CuraSDKVersion # type: Union[str, int] + self._cloud_api_version = UltimakerCloudAuthentication.CuraCloudAPIVersion # type: int + self._cloud_api_root = UltimakerCloudAuthentication.CuraCloudAPIRoot # type: str self._api_url = None # type: Optional[str] # Network: From 8e78582b619e9e2511f57dd00162c800fcf4c43d Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 18 Dec 2018 16:17:37 +0100 Subject: [PATCH 04/43] Add correct copyright and license header to all the files in the plugin Contributes to CURA-6005. --- plugins/CuraDrive/__init__.py | 4 +++- plugins/CuraDrive/plugin.json | 2 +- plugins/CuraDrive/src/DriveApiService.py | 4 +++- plugins/CuraDrive/src/DrivePluginExtension.py | 4 +++- plugins/CuraDrive/src/Settings.py | 2 ++ plugins/CuraDrive/src/UploadBackupJob.py | 2 ++ plugins/CuraDrive/src/models/BackupListModel.py | 2 ++ plugins/CuraDrive/src/qml/components/BackupList.qml | 2 ++ plugins/CuraDrive/src/qml/components/BackupListFooter.qml | 2 ++ plugins/CuraDrive/src/qml/components/BackupListItem.qml | 2 ++ .../CuraDrive/src/qml/components/BackupListItemDetails.qml | 2 ++ .../CuraDrive/src/qml/components/BackupListItemDetailsRow.qml | 2 ++ plugins/CuraDrive/src/qml/components/Divider.qml | 2 ++ plugins/CuraDrive/src/qml/components/Icon.qml | 2 ++ plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml | 2 ++ plugins/CuraDrive/src/qml/main.qml | 2 ++ plugins/CuraDrive/src/qml/pages/BackupsPage.qml | 2 ++ plugins/CuraDrive/src/qml/pages/WelcomePage.qml | 2 ++ 18 files changed, 38 insertions(+), 4 deletions(-) diff --git a/plugins/CuraDrive/__init__.py b/plugins/CuraDrive/__init__.py index 6612a5d614..4103b0cf2e 100644 --- a/plugins/CuraDrive/__init__.py +++ b/plugins/CuraDrive/__init__.py @@ -1,4 +1,6 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import os is_testing = os.getenv('ENV_NAME', "development") == "testing" diff --git a/plugins/CuraDrive/plugin.json b/plugins/CuraDrive/plugin.json index 6cf1fa273c..d1cab39ca5 100644 --- a/plugins/CuraDrive/plugin.json +++ b/plugins/CuraDrive/plugin.json @@ -3,6 +3,6 @@ "author": "Ultimaker B.V.", "description": "Backup and restore your configuration.", "version": "1.2.0", - "api": 5, + "api": 6, "i18n-catalog": "cura" } diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 98199c91cf..7c3e7b7026 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -1,4 +1,6 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import base64 import hashlib from datetime import datetime diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 7e1472b988..a76c623fe8 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -1,4 +1,6 @@ -# Copyright (c) 2017 Ultimaker B.V. +# Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import os from datetime import datetime from typing import Optional diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index 4ee73ad149..04ace8af95 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -1,4 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from UM import i18nCatalog from cura import UltimakerCloudAuthentication diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index bcecce554a..ae6cb13f2e 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -1,4 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + import requests from UM.Job import Job diff --git a/plugins/CuraDrive/src/models/BackupListModel.py b/plugins/CuraDrive/src/models/BackupListModel.py index 93b0c4c48c..06b256b22c 100644 --- a/plugins/CuraDrive/src/models/BackupListModel.py +++ b/plugins/CuraDrive/src/models/BackupListModel.py @@ -1,4 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + from typing import Any, List, Dict from UM.Qt.ListModel import ListModel diff --git a/plugins/CuraDrive/src/qml/components/BackupList.qml b/plugins/CuraDrive/src/qml/components/BackupList.qml index a19d1f0ae7..af7e72b6e6 100644 --- a/plugins/CuraDrive/src/qml/components/BackupList.qml +++ b/plugins/CuraDrive/src/qml/components/BackupList.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml index 72dc3df044..2a6d82bc74 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/components/BackupListItem.qml b/plugins/CuraDrive/src/qml/components/BackupListItem.qml index a84caeb6ab..ba4f1a32a4 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItem.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItem.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml index 74d4c5ab57..38a2557c47 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml index dad1674fe7..d1c8dd33d2 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/components/Divider.qml b/plugins/CuraDrive/src/qml/components/Divider.qml index bba2f2f29c..202794fe23 100644 --- a/plugins/CuraDrive/src/qml/components/Divider.qml +++ b/plugins/CuraDrive/src/qml/components/Divider.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import UM 1.3 as UM diff --git a/plugins/CuraDrive/src/qml/components/Icon.qml b/plugins/CuraDrive/src/qml/components/Icon.qml index 3cb822bf82..8d559bc2b4 100644 --- a/plugins/CuraDrive/src/qml/components/Icon.qml +++ b/plugins/CuraDrive/src/qml/components/Icon.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtGraphicalEffects 1.0 diff --git a/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml b/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml index 5ac5df15ff..5ef8558ee7 100644 --- a/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml +++ b/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/main.qml b/plugins/CuraDrive/src/qml/main.qml index 359f8dd725..e8a49a49e5 100644 --- a/plugins/CuraDrive/src/qml/main.qml +++ b/plugins/CuraDrive/src/qml/main.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Window 2.2 diff --git a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml index 88ce766383..0a7b00d2cb 100644 --- a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml +++ b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Layouts 1.3 diff --git a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml index b7f96d162a..19eecedf28 100644 --- a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml +++ b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml @@ -1,4 +1,6 @@ // Copyright (c) 2018 Ultimaker B.V. +// Cura is released under the terms of the LGPLv3 or higher. + import QtQuick 2.7 import QtQuick.Controls 2.1 import QtQuick.Window 2.2 From 8206fde2237930de5347a711ae6539055952888f Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 18 Dec 2018 16:24:13 +0100 Subject: [PATCH 05/43] Remove the non-load-only-when-testing check Contributes to CURA-6005. --- plugins/CuraDrive/__init__.py | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/CuraDrive/__init__.py b/plugins/CuraDrive/__init__.py index 4103b0cf2e..766d94752f 100644 --- a/plugins/CuraDrive/__init__.py +++ b/plugins/CuraDrive/__init__.py @@ -1,16 +1,10 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -import os +from .src.DrivePluginExtension import DrivePluginExtension -is_testing = os.getenv('ENV_NAME', "development") == "testing" +def getMetaData(): + return {} -# Only load the whole plugin when not running tests as __init__.py is automatically loaded by PyTest -if not is_testing: - from .src.DrivePluginExtension import DrivePluginExtension - - def getMetaData(): - return {} - - def register(app): - return {"extension": DrivePluginExtension(app)} +def register(app): + return {"extension": DrivePluginExtension(app)} From 773190bee18dd7e18fefacfe2aca0104a0762897 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Wed, 19 Dec 2018 12:53:41 +0100 Subject: [PATCH 06/43] Fix code style Add space between binary operator. Contributes to CURA-6005. --- plugins/CuraDrive/src/DriveApiService.py | 30 ++++++++++++------------ 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 7c3e7b7026..a542ac439e 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -43,7 +43,7 @@ class DriveApiService: Logger.log("w", "Could not get access token.") return [] - backup_list_request = requests.get(self.GET_BACKUPS_URL, headers={ + backup_list_request = requests.get(self.GET_BACKUPS_URL, headers = { "Authorization": "Bearer {}".format(access_token) }) if backup_list_request.status_code > 299: @@ -55,12 +55,12 @@ class DriveApiService: def createBackup(self) -> None: """Create a backup and upload it to CuraDrive cloud storage.""" - self.onCreatingStateChanged.emit(is_creating=True) + self.onCreatingStateChanged.emit(is_creating = True) # Create the backup. backup_zip_file, backup_meta_data = self._cura_api.backups.createBackup() if not backup_zip_file or not backup_meta_data: - self.onCreatingStateChanged.emit(is_creating=False, error_message="Could not create backup.") + self.onCreatingStateChanged.emit(is_creating = False, error_message = "Could not create backup.") return # Create an upload entry for the backup. @@ -68,7 +68,7 @@ class DriveApiService: backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) backup_upload_url = self._requestBackupUpload(backup_meta_data, len(backup_zip_file)) if not backup_upload_url: - self.onCreatingStateChanged.emit(is_creating=False, error_message="Could not upload backup.") + self.onCreatingStateChanged.emit(is_creating = False, error_message = "Could not upload backup.") return # Upload the backup to storage. @@ -83,29 +83,29 @@ class DriveApiService: """ if job.backup_upload_error_message != "": # If the job contains an error message we pass it along so the UI can display it. - self.onCreatingStateChanged.emit(is_creating=False, error_message=job.backup_upload_error_message) + self.onCreatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) else: - self.onCreatingStateChanged.emit(is_creating=False) + self.onCreatingStateChanged.emit(is_creating = False) def restoreBackup(self, backup: Dict[str, Any]) -> None: """ Restore a previously exported backup from cloud storage. :param backup: A dict containing an entry from the API list response. """ - self.onRestoringStateChanged.emit(is_restoring=True) + self.onRestoringStateChanged.emit(is_restoring = True) download_url = backup.get("download_url") if not download_url: # If there is no download URL, we can't restore the backup. return self._emitRestoreError() - download_package = requests.get(download_url, stream=True) + download_package = requests.get(download_url, stream = True) if download_package.status_code != 200: # Something went wrong when attempting to download the backup. Logger.log("w", "Could not download backup from url %s: %s", download_url, download_package.text) return self._emitRestoreError() # We store the file in a temporary path fist to ensure integrity. - temporary_backup_file = NamedTemporaryFile(delete=False) + temporary_backup_file = NamedTemporaryFile(delete = False) with open(temporary_backup_file.name, "wb") as write_backup: for chunk in download_package: write_backup.write(chunk) @@ -119,13 +119,13 @@ class DriveApiService: # Tell Cura to place the backup back in the user data folder. with open(temporary_backup_file.name, "rb") as read_backup: self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("data")) - self.onRestoringStateChanged.emit(is_restoring=False) + self.onRestoringStateChanged.emit(is_restoring = False) def _emitRestoreError(self, error_message: str = Settings.translatable_messages["backup_restore_error_message"]): """Helper method for emitting a signal when restoring failed.""" self.onRestoringStateChanged.emit( - is_restoring=False, - error_message=error_message + is_restoring = False, + error_message = error_message ) @staticmethod @@ -137,7 +137,7 @@ class DriveApiService: :return: Success or not. """ with open(file_path, "rb") as read_backup: - local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars=b"_-").decode("utf-8") + local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") return known_hash == local_md5_hash def deleteBackup(self, backup_id: str) -> bool: @@ -171,12 +171,12 @@ class DriveApiService: Logger.log("w", "Could not get access token.") return None - backup_upload_request = requests.put(self.PUT_BACKUP_URL, json={ + backup_upload_request = requests.put(self.PUT_BACKUP_URL, json = { "data": { "backup_size": backup_size, "metadata": backup_metadata } - }, headers={ + }, headers = { "Authorization": "Bearer {}".format(access_token) }) From 136317c3c761e416ddaad78f455fb5c79062ad50 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 3 Jan 2019 11:08:01 +0100 Subject: [PATCH 07/43] Fix code styles CURA-6005 --- resources/qml/ActionButton.qml | 7 +++---- resources/qml/CheckBox.qml | 8 +++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/resources/qml/ActionButton.qml b/resources/qml/ActionButton.qml index 2448b9a551..9e963f8d3e 100644 --- a/resources/qml/ActionButton.qml +++ b/resources/qml/ActionButton.qml @@ -120,12 +120,11 @@ Button visible: text != "" && button.hovered } - BusyIndicator { + BusyIndicator + { id: busyIndicator - anchors { - centerIn: parent - } + anchors.centerIn: parent width: height height: parent.height diff --git a/resources/qml/CheckBox.qml b/resources/qml/CheckBox.qml index 7a79182a4b..403efb4d7b 100644 --- a/resources/qml/CheckBox.qml +++ b/resources/qml/CheckBox.qml @@ -13,11 +13,12 @@ CheckBox property alias tooltip: tooltip.text - indicator: Rectangle { + indicator: Rectangle + { implicitWidth: UM.Theme.getSize("checkbox").width implicitHeight: UM.Theme.getSize("checkbox").height x: 0 - y: Math.round(parent.height / 2 - height / 2) + anchors.verticalCenter: parent.verticalCenter color: UM.Theme.getColor("main_background") radius: UM.Theme.getSize("checkbox_radius").width border.width: UM.Theme.getSize("default_lining").width @@ -37,7 +38,8 @@ CheckBox } } - contentItem: Label { + contentItem: Label + { anchors { left: checkbox.indicator.right From 56c9de44f741f919214e7d7f563876944f5b9bf4 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 3 Jan 2019 11:09:10 +0100 Subject: [PATCH 08/43] Update Cura Backups sdk_version to 6 in bundled json CURA-6005 --- resources/bundled_packages/cura.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/bundled_packages/cura.json b/resources/bundled_packages/cura.json index 896033fb22..2b5750ea8d 100644 --- a/resources/bundled_packages/cura.json +++ b/resources/bundled_packages/cura.json @@ -57,7 +57,7 @@ "display_name": "Cura Backups", "description": "Backup and restore your configuration.", "package_version": "1.2.0", - "sdk_version": 5, + "sdk_version": 6, "website": "https://ultimaker.com", "author": { "author_id": "UltimakerPackages", From a14c846e294acbc169fdca3c5756222ae2088c6a Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Thu, 3 Jan 2019 11:53:17 +0100 Subject: [PATCH 09/43] Rename CheckBox.qml to CheckBoxWithTooltip.qml CURA-6005 --- plugins/CuraDrive/src/qml/components/BackupListFooter.qml | 2 +- resources/qml/{CheckBox.qml => CheckBoxWithTooltip.qml} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename resources/qml/{CheckBox.qml => CheckBoxWithTooltip.qml} (100%) diff --git a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml index 2a6d82bc74..a0bc212597 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml @@ -35,7 +35,7 @@ RowLayout busy: CuraDrive.isCreatingBackup } - Cura.CheckBox + Cura.CheckBoxWithTooltip { id: autoBackupEnabled checked: CuraDrive.autoBackupEnabled diff --git a/resources/qml/CheckBox.qml b/resources/qml/CheckBoxWithTooltip.qml similarity index 100% rename from resources/qml/CheckBox.qml rename to resources/qml/CheckBoxWithTooltip.qml From 65183ade0a53deceac8c00413e656aec79e12628 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 16:44:08 +0100 Subject: [PATCH 10/43] No longer chache singleton objects CURA-6005 --- plugins/CuraDrive/__init__.py | 2 +- plugins/CuraDrive/src/DriveApiService.py | 11 ++++------- plugins/CuraDrive/src/DrivePluginExtension.py | 18 ++++++++---------- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/plugins/CuraDrive/__init__.py b/plugins/CuraDrive/__init__.py index 766d94752f..dd7ffeaac3 100644 --- a/plugins/CuraDrive/__init__.py +++ b/plugins/CuraDrive/__init__.py @@ -7,4 +7,4 @@ def getMetaData(): return {} def register(app): - return {"extension": DrivePluginExtension(app)} + return {"extension": DrivePluginExtension()} diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index a542ac439e..3b6641cd74 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -12,16 +12,14 @@ import requests from UM.Logger import Logger from UM.Message import Message from UM.Signal import Signal +from cura.CuraApplication import CuraApplication from .UploadBackupJob import UploadBackupJob from .Settings import Settings +## The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling. class DriveApiService: - """ - The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling. - """ - GET_BACKUPS_URL = "{}/backups".format(Settings.DRIVE_API_URL) PUT_BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) DELETE_BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) @@ -32,9 +30,8 @@ class DriveApiService: # Emit signal when creating backup started or finished. onCreatingStateChanged = Signal() - def __init__(self, cura_api) -> None: - """Create a new instance of the Drive API service and set the cura_api object.""" - self._cura_api = cura_api + def __init__(self) -> None: + self._cura_api = CuraApplication.getInstance().getCuraAPI() def getBackups(self) -> List[Dict[str, Any]]: """Get all backups from the API.""" diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index a76c623fe8..bed54140d9 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -7,8 +7,10 @@ from typing import Optional from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal +from UM.Application import Application from UM.Extension import Extension from UM.Message import Message +from cura.CuraApplication import CuraApplication from .Settings import Settings from .DriveApiService import DriveApiService @@ -34,11 +36,8 @@ class DrivePluginExtension(QObject, Extension): DATE_FORMAT = "%d/%m/%Y %H:%M:%S" - def __init__(self, application): + def __init__(self): super(DrivePluginExtension, self).__init__() - - # Re-usable instance of application. - self._application = application # Local data caching for the UI. self._drive_window = None # type: Optional[QObject] @@ -47,12 +46,11 @@ class DrivePluginExtension(QObject, Extension): self._is_creating_backup = False # Initialize services. - self._preferences = self._application.getPreferences() - self._cura_api = self._application.getCuraAPI() - self._drive_api_service = DriveApiService(self._cura_api) + self._preferences = CuraApplication.getInstance().getPreferences() + self._drive_api_service = DriveApiService() # Attach signals. - self._cura_api.account.loginStateChanged.connect(self._onLoginStateChanged) + CuraApplication.getInstance().getCuraAPI().account.loginStateChanged.connect(self._onLoginStateChanged) self._drive_api_service.onRestoringStateChanged.connect(self._onRestoringStateChanged) self._drive_api_service.onCreatingStateChanged.connect(self._onCreatingStateChanged) @@ -65,7 +63,7 @@ class DrivePluginExtension(QObject, Extension): self._updateMenuItems() # Make auto-backup on boot if required. - self._application.engineCreatedSignal.connect(self._autoBackup) + CuraApplication.getInstance().engineCreatedSignal.connect(self._autoBackup) def showDriveWindow(self) -> None: """Show the Drive UI popup window.""" @@ -81,7 +79,7 @@ class DrivePluginExtension(QObject, Extension): :return: The popup window object. """ path = os.path.join(os.path.dirname(__file__), "qml", "main.qml") - return self._application.createQmlComponent(path, {"CuraDrive": self}) + return CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self}) def _updateMenuItems(self) -> None: """Update the menu items.""" From ea1712df0f120985fb62fb474a698320b4da6726 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 16:51:11 +0100 Subject: [PATCH 11/43] Codestyle fixes & simplifications CURA-6005 --- plugins/CuraDrive/src/DrivePluginExtension.py | 64 ++++--------------- 1 file changed, 11 insertions(+), 53 deletions(-) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index bed54140d9..cd8274f83a 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -16,6 +16,9 @@ from .Settings import Settings from .DriveApiService import DriveApiService from .models.BackupListModel import BackupListModel +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + class DrivePluginExtension(QObject, Extension): """ @@ -37,7 +40,8 @@ class DrivePluginExtension(QObject, Extension): DATE_FORMAT = "%d/%m/%Y %H:%M:%S" def __init__(self): - super(DrivePluginExtension, self).__init__() + QObject.__init__(self, None) + Extension.__init__(self) # Local data caching for the UI. self._drive_window = None # type: Optional[QObject] @@ -59,8 +63,8 @@ class DrivePluginExtension(QObject, Extension): self._preferences.addPreference(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, datetime.now() .strftime(self.DATE_FORMAT)) - # Register menu items. - self._updateMenuItems() + # Register the menu item + self.addMenuItem(catalog.i18nc("@item:inmenu", "Manage backups"), self.showDriveWindow) # Make auto-backup on boot if required. CuraApplication.getInstance().engineCreatedSignal.connect(self._autoBackup) @@ -68,59 +72,41 @@ class DrivePluginExtension(QObject, Extension): def showDriveWindow(self) -> None: """Show the Drive UI popup window.""" if not self._drive_window: - self._drive_window = self.createDriveWindow() + path = os.path.join(os.path.dirname(__file__), "qml", "main.qml") + self._drive_window = CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self}) self.refreshBackups() if self._drive_window: self._drive_window.show() - def createDriveWindow(self) -> Optional["QObject"]: - """ - Create an instance of the Drive UI popup window. - :return: The popup window object. - """ - path = os.path.join(os.path.dirname(__file__), "qml", "main.qml") - return CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self}) - - def _updateMenuItems(self) -> None: - """Update the menu items.""" - self.addMenuItem(Settings.translatable_messages["extension_menu_entry"], self.showDriveWindow) - def _autoBackup(self) -> None: - """Automatically make a backup on boot if enabled.""" - if self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY) and self._lastBackupTooLongAgo(): + if self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY) and self._isLastBackupTooLongAgo(): self.createBackup() - def _lastBackupTooLongAgo(self) -> bool: - """Check if the last backup was longer than 1 day ago.""" + def _isLastBackupTooLongAgo(self) -> bool: current_date = datetime.now() last_backup_date = self._getLastBackupDate() date_diff = current_date - last_backup_date return date_diff.days > 1 def _getLastBackupDate(self) -> "datetime": - """Get the last backup date as datetime object.""" last_backup_date = self._preferences.getValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY) return datetime.strptime(last_backup_date, self.DATE_FORMAT) def _storeBackupDate(self) -> None: - """Store the current date as last backup date.""" backup_date = datetime.now().strftime(self.DATE_FORMAT) self._preferences.setValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, backup_date) def _onLoginStateChanged(self, logged_in: bool = False) -> None: - """Callback handler for changes in the login state.""" if logged_in: self.refreshBackups() def _onRestoringStateChanged(self, is_restoring: bool = False, error_message: str = None) -> None: - """Callback handler for changes in the restoring state.""" self._is_restoring_backup = is_restoring self.restoringStateChanged.emit() if error_message: Message(error_message, title = Settings.MESSAGE_TITLE, lifetime = 5).show() def _onCreatingStateChanged(self, is_creating: bool = False, error_message: str = None) -> None: - """Callback handler for changes in the creation state.""" self._is_creating_backup = is_creating self.creatingStateChanged.emit() if error_message: @@ -133,69 +119,41 @@ class DrivePluginExtension(QObject, Extension): @pyqtSlot(bool, name = "toggleAutoBackup") def toggleAutoBackup(self, enabled: bool) -> None: - """Enable or disable the auto-backup feature.""" self._preferences.setValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, enabled) self.preferencesChanged.emit() @pyqtProperty(bool, notify = preferencesChanged) def autoBackupEnabled(self) -> bool: - """Check if auto-backup is enabled or not.""" return bool(self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY)) @pyqtProperty(QObject, notify = backupsChanged) def backups(self) -> BackupListModel: - """ - Get a list of the backups. - :return: The backups as Qt List Model. - """ return self._backups_list_model @pyqtSlot(name = "refreshBackups") def refreshBackups(self) -> None: - """ - Forcefully refresh the backups list. - """ self._backups_list_model.loadBackups(self._drive_api_service.getBackups()) self.backupsChanged.emit() @pyqtProperty(bool, notify = restoringStateChanged) def isRestoringBackup(self) -> bool: - """ - Get the current restoring state. - :return: Boolean if we are restoring or not. - """ return self._is_restoring_backup @pyqtProperty(bool, notify = creatingStateChanged) def isCreatingBackup(self) -> bool: - """ - Get the current creating state. - :return: Boolean if we are creating or not. - """ return self._is_creating_backup @pyqtSlot(str, name = "restoreBackup") def restoreBackup(self, backup_id: str) -> None: - """ - Download and restore a backup by ID. - :param backup_id: The ID of the backup. - """ index = self._backups_list_model.find("backup_id", backup_id) backup = self._backups_list_model.getItem(index) self._drive_api_service.restoreBackup(backup) @pyqtSlot(name = "createBackup") def createBackup(self) -> None: - """ - Create a new backup. - """ self._drive_api_service.createBackup() @pyqtSlot(str, name = "deleteBackup") def deleteBackup(self, backup_id: str) -> None: - """ - Delete a backup by ID. - :param backup_id: The ID of the backup. - """ self._drive_api_service.deleteBackup(backup_id) self.refreshBackups() From 4d1e9d24f98d3c12e8f91f02d416ab1ddb8287b7 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 16:58:51 +0100 Subject: [PATCH 12/43] Cleanup documentation Either fix the style to doxygen or remove it if it just repeated the functionnname. CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 43 +++++++----------------- 1 file changed, 13 insertions(+), 30 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 3b6641cd74..39045d1317 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -34,7 +34,6 @@ class DriveApiService: self._cura_api = CuraApplication.getInstance().getCuraAPI() def getBackups(self) -> List[Dict[str, Any]]: - """Get all backups from the API.""" access_token = self._cura_api.account.accessToken if not access_token: Logger.log("w", "Could not get access token.") @@ -43,6 +42,7 @@ class DriveApiService: backup_list_request = requests.get(self.GET_BACKUPS_URL, headers = { "Authorization": "Bearer {}".format(access_token) }) + if backup_list_request.status_code > 299: Logger.log("w", "Could not get backups list from remote: %s", backup_list_request.text) Message(Settings.translatable_messages["get_backups_error"], title = Settings.MESSAGE_TITLE, @@ -51,7 +51,6 @@ class DriveApiService: return backup_list_request.json()["data"] def createBackup(self) -> None: - """Create a backup and upload it to CuraDrive cloud storage.""" self.onCreatingStateChanged.emit(is_creating = True) # Create the backup. @@ -74,10 +73,6 @@ class DriveApiService: upload_backup_job.start() def _onUploadFinished(self, job: "UploadBackupJob") -> None: - """ - Callback handler for the upload job. - :param job: The executed job. - """ if job.backup_upload_error_message != "": # If the job contains an error message we pass it along so the UI can display it. self.onCreatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) @@ -85,10 +80,6 @@ class DriveApiService: self.onCreatingStateChanged.emit(is_creating = False) def restoreBackup(self, backup: Dict[str, Any]) -> None: - """ - Restore a previously exported backup from cloud storage. - :param backup: A dict containing an entry from the API list response. - """ self.onRestoringStateChanged.emit(is_restoring = True) download_url = backup.get("download_url") if not download_url: @@ -119,30 +110,22 @@ class DriveApiService: self.onRestoringStateChanged.emit(is_restoring = False) def _emitRestoreError(self, error_message: str = Settings.translatable_messages["backup_restore_error_message"]): - """Helper method for emitting a signal when restoring failed.""" self.onRestoringStateChanged.emit( is_restoring = False, error_message = error_message ) + # Verify the MD5 hash of a file. + # \param file_path Full path to the file. + # \param known_hash The known MD5 hash of the file. + # \return: Success or not. @staticmethod def _verifyMd5Hash(file_path: str, known_hash: str) -> bool: - """ - Verify the MD5 hash of a file. - :param file_path: Full path to the file. - :param known_hash: The known MD5 hash of the file. - :return: Success or not. - """ with open(file_path, "rb") as read_backup: local_md5_hash = base64.b64encode(hashlib.md5(read_backup.read()).digest(), altchars = b"_-").decode("utf-8") return known_hash == local_md5_hash def deleteBackup(self, backup_id: str) -> bool: - """ - Delete a backup from the server by ID. - :param backup_id: The ID of the backup to delete. - :return: Success bool. - """ access_token = self._cura_api.account.accessToken if not access_token: Logger.log("w", "Could not get access token.") @@ -156,13 +139,12 @@ class DriveApiService: return False return True + # Request a backup upload slot from the API. + # \param backup_metadata: A dict containing some meta data about the backup. + # \param backup_size The size of the backup file in bytes. + # \return: The upload URL for the actual backup file if successful, otherwise None. def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> Optional[str]: - """ - Request a backup upload slot from the API. - :param backup_metadata: A dict containing some meta data about the backup. - :param backup_size: The size of the backup file in bytes. - :return: The upload URL for the actual backup file if successful, otherwise None. - """ + access_token = self._cura_api.account.accessToken if not access_token: Logger.log("w", "Could not get access token.") @@ -176,8 +158,9 @@ class DriveApiService: }, headers = { "Authorization": "Bearer {}".format(access_token) }) - - if backup_upload_request.status_code > 299: + + # Any status code of 300 or above indicates an error. + if backup_upload_request.status_code >= 300: Logger.log("w", "Could not request backup upload: %s", backup_upload_request.text) return None From ed9a51791b9ed83c517dc5d1ba26b489905078ec Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 17:05:58 +0100 Subject: [PATCH 13/43] Handle bunch of review comments CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 23 ++++++++++++----------- plugins/CuraDrive/src/Settings.py | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 39045d1317..f74f30bcda 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -17,6 +17,9 @@ from cura.CuraApplication import CuraApplication from .UploadBackupJob import UploadBackupJob from .Settings import Settings +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") + ## The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling. class DriveApiService: @@ -42,11 +45,10 @@ class DriveApiService: backup_list_request = requests.get(self.GET_BACKUPS_URL, headers = { "Authorization": "Bearer {}".format(access_token) }) - - if backup_list_request.status_code > 299: + + if backup_list_request.status_code >= 300: Logger.log("w", "Could not get backups list from remote: %s", backup_list_request.text) - Message(Settings.translatable_messages["get_backups_error"], title = Settings.MESSAGE_TITLE, - lifetime = 10).show() + Message(catalog.i18nc("@info:backup_status", "There was an error listing your backups."), title = Settings.MESSAGE_TITLE).show() return [] return backup_list_request.json()["data"] @@ -87,7 +89,7 @@ class DriveApiService: return self._emitRestoreError() download_package = requests.get(download_url, stream = True) - if download_package.status_code != 200: + if download_package.status_code >= 300: # Something went wrong when attempting to download the backup. Logger.log("w", "Could not download backup from url %s: %s", download_url, download_package.text) return self._emitRestoreError() @@ -109,11 +111,10 @@ class DriveApiService: self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("data")) self.onRestoringStateChanged.emit(is_restoring = False) - def _emitRestoreError(self, error_message: str = Settings.translatable_messages["backup_restore_error_message"]): - self.onRestoringStateChanged.emit( - is_restoring = False, - error_message = error_message - ) + def _emitRestoreError(self): + self.onRestoringStateChanged.emit(is_restoring = False, + error_message = catalog.i18nc("@info:backup_status", + "There was an error trying to restore your backup.")) # Verify the MD5 hash of a file. # \param file_path Full path to the file. @@ -134,7 +135,7 @@ class DriveApiService: delete_backup = requests.delete("{}/{}".format(self.DELETE_BACKUP_URL, backup_id), headers = { "Authorization": "Bearer {}".format(access_token) }) - if delete_backup.status_code > 299: + if delete_backup.status_code >= 300: Logger.log("w", "Could not delete backup: %s", delete_backup.text) return False return True diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index 04ace8af95..10d1ba4397 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -19,7 +19,7 @@ class Settings: I18N_CATALOG_ID = "cura" I18N_CATALOG = i18nCatalog(I18N_CATALOG_ID) - MESSAGE_TITLE = I18N_CATALOG.i18nc("@info:title", "Backups"), + MESSAGE_TITLE = I18N_CATALOG.i18nc("@info:title", "Backups") # Translatable messages for the entire plugin. translatable_messages = { From e36b3e37d1b680b89f2beb2b4af4bd2cdab233ec Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 17:13:47 +0100 Subject: [PATCH 14/43] Remove indirection in the translation CURA-6005 --- plugins/CuraDrive/src/Settings.py | 22 ++-------------------- plugins/CuraDrive/src/UploadBackupJob.py | 14 +++++++------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index 10d1ba4397..fcb05b8c04 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -16,24 +16,6 @@ class Settings: AUTO_BACKUP_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled" AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" - I18N_CATALOG_ID = "cura" - I18N_CATALOG = i18nCatalog(I18N_CATALOG_ID) + I18N_CATALOG = i18nCatalog("cura") - MESSAGE_TITLE = I18N_CATALOG.i18nc("@info:title", "Backups") - - # Translatable messages for the entire plugin. - translatable_messages = { - - # Menu items. - "extension_menu_entry": I18N_CATALOG.i18nc("@item:inmenu", "Manage backups"), - - # Notification messages. - "backup_failed": I18N_CATALOG.i18nc("@info:backup_status", "There was an error while creating your backup."), - "uploading_backup": I18N_CATALOG.i18nc("@info:backup_status", "Uploading your backup..."), - "uploading_backup_success": I18N_CATALOG.i18nc("@info:backup_status", "Your backup has finished uploading."), - "uploading_backup_error": I18N_CATALOG.i18nc("@info:backup_status", - "There was an error while uploading your backup."), - "get_backups_error": I18N_CATALOG.i18nc("@info:backup_status", "There was an error listing your backups."), - "backup_restore_error_message": I18N_CATALOG.i18nc("@info:backup_status", - "There was an error trying to restore your backup.") - } + MESSAGE_TITLE = I18N_CATALOG.i18nc("@info:title", "Backups") \ No newline at end of file diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index ae6cb13f2e..bdcc8dd8a6 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -8,14 +8,17 @@ from UM.Logger import Logger from UM.Message import Message from .Settings import Settings +from UM.i18n import i18nCatalog +catalog = i18nCatalog("cura") class UploadBackupJob(Job): + MESSAGE_TITLE = catalog.i18nc("@info:title", "Backups") + """ This job is responsible for uploading the backup file to cloud storage. As it can take longer than some other tasks, we schedule this using a Cura Job. """ - def __init__(self, signed_upload_url: str, backup_zip: bytes) -> None: super().__init__() self._signed_upload_url = signed_upload_url @@ -24,18 +27,15 @@ class UploadBackupJob(Job): self.backup_upload_error_message = "" def run(self) -> None: - Message(Settings.translatable_messages["uploading_backup"], title = Settings.MESSAGE_TITLE, - lifetime = 10).show() + Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE).show() backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip) if backup_upload.status_code not in (200, 201): self.backup_upload_error_message = backup_upload.text Logger.log("w", "Could not upload backup file: %s", backup_upload.text) - Message(Settings.translatable_messages["uploading_backup_error"], title = Settings.MESSAGE_TITLE, - lifetime = 10).show() + Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title = self.MESSAGE_TITLE).show() else: self._upload_success = True - Message(Settings.translatable_messages["uploading_backup_success"], title = Settings.MESSAGE_TITLE, - lifetime = 10).show() + Message(catalog.i18nc("@info:backup_status", "Your backup has finished uploading."), title = self.MESSAGE_TITLE).show() self.finished.emit(self) From 83fbb78c9ee4437d736696e5e74a9a747daabcad Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 17:15:32 +0100 Subject: [PATCH 15/43] Backup uploading now shows a intermediate progress bar and hides when done CURA-6005 --- plugins/CuraDrive/src/UploadBackupJob.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index bdcc8dd8a6..d9532a96f0 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -27,9 +27,12 @@ class UploadBackupJob(Job): self.backup_upload_error_message = "" def run(self) -> None: - Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE).show() + upload_message = Message(catalog.i18nc("@info:backup_status", "Uploading your backup..."), title = self.MESSAGE_TITLE, progress = -1) + upload_message.show() backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip) + upload_message.hide() + if backup_upload.status_code not in (200, 201): self.backup_upload_error_message = backup_upload.text Logger.log("w", "Could not upload backup file: %s", backup_upload.text) From 1578aaa301876cce04dfb6f7fc0c5c936fdad56a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 17:17:40 +0100 Subject: [PATCH 16/43] Minor code cleanup CURA-6005 --- plugins/CuraDrive/src/UploadBackupJob.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/CuraDrive/src/UploadBackupJob.py b/plugins/CuraDrive/src/UploadBackupJob.py index d9532a96f0..2e76ed9b4b 100644 --- a/plugins/CuraDrive/src/UploadBackupJob.py +++ b/plugins/CuraDrive/src/UploadBackupJob.py @@ -7,7 +7,6 @@ from UM.Job import Job from UM.Logger import Logger from UM.Message import Message -from .Settings import Settings from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -15,10 +14,8 @@ catalog = i18nCatalog("cura") class UploadBackupJob(Job): MESSAGE_TITLE = catalog.i18nc("@info:title", "Backups") - """ - This job is responsible for uploading the backup file to cloud storage. - As it can take longer than some other tasks, we schedule this using a Cura Job. - """ + # This job is responsible for uploading the backup file to cloud storage. + # As it can take longer than some other tasks, we schedule this using a Cura Job. def __init__(self, signed_upload_url: str, backup_zip: bytes) -> None: super().__init__() self._signed_upload_url = signed_upload_url @@ -33,7 +30,7 @@ class UploadBackupJob(Job): backup_upload = requests.put(self._signed_upload_url, data = self._backup_zip) upload_message.hide() - if backup_upload.status_code not in (200, 201): + if backup_upload.status_code >= 300: self.backup_upload_error_message = backup_upload.text Logger.log("w", "Could not upload backup file: %s", backup_upload.text) Message(catalog.i18nc("@info:backup_status", "There was an error while uploading your backup."), title = self.MESSAGE_TITLE).show() From 49076a7103715703b9a7aeef591cbf2f74207c88 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 3 Jan 2019 17:42:58 +0100 Subject: [PATCH 17/43] Remove the unneeded BackupListModel CURA-6005 --- plugins/CuraDrive/src/DrivePluginExtension.py | 23 ++++++----- .../CuraDrive/src/models/BackupListModel.py | 40 ------------------- plugins/CuraDrive/src/models/__init__.py | 0 .../src/qml/components/BackupListItem.qml | 10 ++--- .../qml/components/BackupListItemDetails.qml | 10 ++--- 5 files changed, 22 insertions(+), 61 deletions(-) delete mode 100644 plugins/CuraDrive/src/models/BackupListModel.py delete mode 100644 plugins/CuraDrive/src/models/__init__.py diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index cd8274f83a..041c01a14d 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -3,18 +3,17 @@ import os from datetime import datetime -from typing import Optional +from typing import Optional, List from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal -from UM.Application import Application from UM.Extension import Extension +from UM.Logger import Logger from UM.Message import Message from cura.CuraApplication import CuraApplication from .Settings import Settings from .DriveApiService import DriveApiService -from .models.BackupListModel import BackupListModel from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -45,7 +44,7 @@ class DrivePluginExtension(QObject, Extension): # Local data caching for the UI. self._drive_window = None # type: Optional[QObject] - self._backups_list_model = BackupListModel() + self._backups = [] self._is_restoring_backup = False self._is_creating_backup = False @@ -126,13 +125,13 @@ class DrivePluginExtension(QObject, Extension): def autoBackupEnabled(self) -> bool: return bool(self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY)) - @pyqtProperty(QObject, notify = backupsChanged) - def backups(self) -> BackupListModel: - return self._backups_list_model + @pyqtProperty("QVariantList", notify = backupsChanged) + def backups(self) -> List: + return self._backups @pyqtSlot(name = "refreshBackups") def refreshBackups(self) -> None: - self._backups_list_model.loadBackups(self._drive_api_service.getBackups()) + self._backups = self._drive_api_service.getBackups() self.backupsChanged.emit() @pyqtProperty(bool, notify = restoringStateChanged) @@ -145,9 +144,11 @@ class DrivePluginExtension(QObject, Extension): @pyqtSlot(str, name = "restoreBackup") def restoreBackup(self, backup_id: str) -> None: - index = self._backups_list_model.find("backup_id", backup_id) - backup = self._backups_list_model.getItem(index) - self._drive_api_service.restoreBackup(backup) + for backup in self._backups: + if backup.get("backup_id") == backup_id: + self._drive_api_service.restoreBackup(backup) + return + Logger.log("w", "Unable to find backup with the ID %s", backup_id) @pyqtSlot(name = "createBackup") def createBackup(self) -> None: diff --git a/plugins/CuraDrive/src/models/BackupListModel.py b/plugins/CuraDrive/src/models/BackupListModel.py deleted file mode 100644 index 06b256b22c..0000000000 --- a/plugins/CuraDrive/src/models/BackupListModel.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright (c) 2018 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from typing import Any, List, Dict - -from UM.Qt.ListModel import ListModel - -from PyQt5.QtCore import Qt - - -class BackupListModel(ListModel): - """ - The BackupListModel transforms the backups data that came from the server so it can be served to the Qt UI. - """ - - def __init__(self, parent = None) -> None: - super().__init__(parent) - self.addRoleName(Qt.UserRole + 1, "backup_id") - self.addRoleName(Qt.UserRole + 2, "download_url") - self.addRoleName(Qt.UserRole + 3, "generated_time") - self.addRoleName(Qt.UserRole + 4, "md5_hash") - self.addRoleName(Qt.UserRole + 5, "data") - - def loadBackups(self, data: List[Dict[str, Any]]) -> None: - """ - Populate the model with server data. - :param data: - """ - items = [] - for backup in data: - # We do this loop because we only want to append these specific fields. - # Without this, ListModel will break. - items.append({ - "backup_id": backup["backup_id"], - "download_url": backup["download_url"], - "generated_time": backup["generated_time"], - "md5_hash": backup["md5_hash"], - "data": backup["metadata"] - }) - self.setItems(items) diff --git a/plugins/CuraDrive/src/models/__init__.py b/plugins/CuraDrive/src/models/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/plugins/CuraDrive/src/qml/components/BackupListItem.qml b/plugins/CuraDrive/src/qml/components/BackupListItem.qml index ba4f1a32a4..0cd897fada 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItem.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItem.qml @@ -44,7 +44,7 @@ Item Label { - text: new Date(model["generated_time"]).toLocaleString(UM.Preferences.getValue("general/language")) + text: new Date(modelData.generated_time).toLocaleString(UM.Preferences.getValue("general/language")) color: UM.Theme.getColor("text") elide: Text.ElideRight Layout.minimumWidth: 100 * screenScaleFactor @@ -55,7 +55,7 @@ Item Label { - text: model["data"]["description"] + text: modelData.metadata.description color: UM.Theme.getColor("text") elide: Text.ElideRight Layout.minimumWidth: 100 * screenScaleFactor @@ -85,7 +85,7 @@ Item BackupListItemDetails { id: backupDetails - backupDetailsData: model + backupDetailsData: modelData width: parent.width visible: parent.showDetails anchors.top: dataRow.bottom @@ -97,7 +97,7 @@ Item title: catalog.i18nc("@dialog:title", "Delete Backup") text: catalog.i18nc("@dialog:info", "Are you sure you want to delete this backup? This cannot be undone.") standardButtons: StandardButton.Yes | StandardButton.No - onYes: CuraDrive.deleteBackup(model["backup_id"]) + onYes: CuraDrive.deleteBackup(modelData.backup_id) } MessageDialog @@ -106,6 +106,6 @@ Item title: catalog.i18nc("@dialog:title", "Restore Backup") text: catalog.i18nc("@dialog:info", "You will need to restart Cura before your backup is restored. Do you want to close Cura now?") standardButtons: StandardButton.Yes | StandardButton.No - onYes: CuraDrive.restoreBackup(model["backup_id"]) + onYes: CuraDrive.restoreBackup(modelData.backup_id) } } diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml index 38a2557c47..e84f1e0982 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml @@ -19,7 +19,7 @@ ColumnLayout { iconSource: "../images/cura.svg" label: catalog.i18nc("@backuplist:label", "Cura Version") - value: backupDetailsData["data"]["cura_release"] + value: backupDetailsData.metadata.cura_release } // Machine count. @@ -27,7 +27,7 @@ ColumnLayout { iconSource: "../images/printer.svg" label: catalog.i18nc("@backuplist:label", "Machines") - value: backupDetailsData["data"]["machine_count"] + value: backupDetailsData.metadata.machine_count } // Meterial count. @@ -35,7 +35,7 @@ ColumnLayout { iconSource: "../images/material.svg" label: catalog.i18nc("@backuplist:label", "Materials") - value: backupDetailsData["data"]["material_count"] + value: backupDetailsData.metadata.material_count } // Meterial count. @@ -43,7 +43,7 @@ ColumnLayout { iconSource: "../images/profile.svg" label: catalog.i18nc("@backuplist:label", "Profiles") - value: backupDetailsData["data"]["profile_count"] + value: backupDetailsData.metadata.profile_count } // Meterial count. @@ -51,7 +51,7 @@ ColumnLayout { iconSource: "../images/plugin.svg" label: catalog.i18nc("@backuplist:label", "Plugins") - value: backupDetailsData["data"]["plugin_count"] + value: backupDetailsData.metadata.plugin_count } // Spacer. From 0edc3f2680d03aa158a6218c30580290e37a6664 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:17:06 +0100 Subject: [PATCH 18/43] Make some minor improvements to the qml This implements some of the best practices that weren't used yet for the QML CURA-6005 --- .../qml/components/BackupListItemDetails.qml | 2 +- .../components/BackupListItemDetailsRow.qml | 16 ++--- plugins/CuraDrive/src/qml/components/Icon.qml | 58 ------------------- plugins/CuraDrive/src/qml/main.qml | 2 +- .../CuraDrive/src/qml/pages/BackupsPage.qml | 2 +- .../CuraDrive/src/qml/pages/WelcomePage.qml | 5 +- 6 files changed, 16 insertions(+), 69 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/components/Icon.qml diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml index e84f1e0982..d07bb50b11 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml @@ -11,7 +11,7 @@ ColumnLayout { id: backupDetails width: parent.width - spacing: 10 * screenScaleFactor + spacing: UM.Theme.getSize("default_margin").width property var backupDetailsData // Cura version diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml index d1c8dd33d2..550bdaefab 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml @@ -13,9 +13,9 @@ RowLayout width: parent.width height: 40 * screenScaleFactor - property var iconSource - property var label - property var value + property alias iconSource: icon.source + property alias label: detailName.text + property alias value: detailValue.text // Spacing. Item @@ -23,16 +23,18 @@ RowLayout width: 40 * screenScaleFactor } - Icon + UM.RecolorImage { + id: icon width: 18 * screenScaleFactor - iconSource: detailsRow.iconSource + height: width + source: "" color: UM.Theme.getColor("text") } Label { - text: detailsRow.label + id: detailName color: UM.Theme.getColor("text") elide: Text.ElideRight Layout.minimumWidth: 50 * screenScaleFactor @@ -43,7 +45,7 @@ RowLayout Label { - text: detailsRow.value + id: detailValue color: UM.Theme.getColor("text") elide: Text.ElideRight Layout.minimumWidth: 50 * screenScaleFactor diff --git a/plugins/CuraDrive/src/qml/components/Icon.qml b/plugins/CuraDrive/src/qml/components/Icon.qml deleted file mode 100644 index 8d559bc2b4..0000000000 --- a/plugins/CuraDrive/src/qml/components/Icon.qml +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 2.1 -import QtGraphicalEffects 1.0 - -Item -{ - id: icon - width: parent.height - height: width - property var color: "transparent" - property var iconSource - property bool animated: false - - Image - { - id: iconImage - width: parent.height - height: width - smooth: true - source: icon.iconSource - sourceSize.width: width - sourceSize.height: height - antialiasing: true - visible: !icon.animated - } - - AnimatedImage - { - id: animatedIconImage - width: parent.height - height: width - smooth: true - antialiasing: true - source: "../images/loading.gif" - visible: icon.animated - } - - ColorOverlay - { - anchors.fill: iconImage - source: iconImage - color: icon.color - antialiasing: true - visible: !icon.animated - } - - ColorOverlay - { - anchors.fill: animatedIconImage - source: animatedIconImage - color: icon.color - antialiasing: true - visible: icon.animated - } -} diff --git a/plugins/CuraDrive/src/qml/main.qml b/plugins/CuraDrive/src/qml/main.qml index e8a49a49e5..48bf3b6ea4 100644 --- a/plugins/CuraDrive/src/qml/main.qml +++ b/plugins/CuraDrive/src/qml/main.qml @@ -27,7 +27,7 @@ Window UM.I18nCatalog { id: catalog - name: "cura_drive" + name: "cura" } WelcomePage diff --git a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml index 0a7b00d2cb..3b905a4a39 100644 --- a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml +++ b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml @@ -18,7 +18,7 @@ Item ColumnLayout { - spacing: UM.Theme.getSize("default_margin").height * 2 + spacing: UM.Theme.getSize("wide_margin").height width: parent.width anchors.fill: parent diff --git a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml index 19eecedf28..0b207bc170 100644 --- a/plugins/CuraDrive/src/qml/pages/WelcomePage.qml +++ b/plugins/CuraDrive/src/qml/pages/WelcomePage.qml @@ -10,12 +10,14 @@ import Cura 1.1 as Cura import "../components" + Column { id: welcomePage spacing: UM.Theme.getSize("wide_margin").height width: parent.width - topPadding: 150 * screenScaleFactor + height: childrenRect.height + anchors.centerIn: parent Image { @@ -51,3 +53,4 @@ Column fixedWidthMode: true } } + From 6492b51d7cbbefa0123f0c86bf9b4a984fd127b6 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:25:22 +0100 Subject: [PATCH 19/43] Remove duplicated icons CURA-6005 --- .../src/qml/components/BackupListItemDetails.qml | 12 ++++++------ plugins/CuraDrive/src/qml/images/material.svg | 7 ------- plugins/CuraDrive/src/qml/images/plugin.svg | 7 ------- plugins/CuraDrive/src/qml/images/profile.svg | 3 --- 4 files changed, 6 insertions(+), 23 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/images/material.svg delete mode 100644 plugins/CuraDrive/src/qml/images/plugin.svg delete mode 100644 plugins/CuraDrive/src/qml/images/profile.svg diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml index d07bb50b11..cf365501ec 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml @@ -30,26 +30,26 @@ ColumnLayout value: backupDetailsData.metadata.machine_count } - // Meterial count. + // Material count BackupListItemDetailsRow { - iconSource: "../images/material.svg" + iconSource: UM.Theme.getIcon("category_material") label: catalog.i18nc("@backuplist:label", "Materials") value: backupDetailsData.metadata.material_count } - // Meterial count. + // Profile count. BackupListItemDetailsRow { - iconSource: "../images/profile.svg" + iconSource: UM.Theme.getIcon("profile") label: catalog.i18nc("@backuplist:label", "Profiles") value: backupDetailsData.metadata.profile_count } - // Meterial count. + // Plugin count. BackupListItemDetailsRow { - iconSource: "../images/plugin.svg" + iconSource: UM.Theme.getIcon("plugin") label: catalog.i18nc("@backuplist:label", "Plugins") value: backupDetailsData.metadata.plugin_count } diff --git a/plugins/CuraDrive/src/qml/images/material.svg b/plugins/CuraDrive/src/qml/images/material.svg deleted file mode 100644 index eac724e471..0000000000 --- a/plugins/CuraDrive/src/qml/images/material.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/plugin.svg b/plugins/CuraDrive/src/qml/images/plugin.svg deleted file mode 100644 index 674eb99a54..0000000000 --- a/plugins/CuraDrive/src/qml/images/plugin.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/profile.svg b/plugins/CuraDrive/src/qml/images/profile.svg deleted file mode 100644 index ec2130f3d6..0000000000 --- a/plugins/CuraDrive/src/qml/images/profile.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file From 551f07552789505f4c456bcb4d35d6be4572ab15 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:27:41 +0100 Subject: [PATCH 20/43] Removed unneeded destinction between get/put/delete URL They are all the same, so no real need to keep this seperate. CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index f74f30bcda..d9185cc1d2 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -23,9 +23,7 @@ catalog = i18nCatalog("cura") ## The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling. class DriveApiService: - GET_BACKUPS_URL = "{}/backups".format(Settings.DRIVE_API_URL) - PUT_BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) - DELETE_BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) + BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) # Emit signal when restoring backup started or finished. onRestoringStateChanged = Signal() @@ -42,7 +40,7 @@ class DriveApiService: Logger.log("w", "Could not get access token.") return [] - backup_list_request = requests.get(self.GET_BACKUPS_URL, headers = { + backup_list_request = requests.get(self.BACKUP_URL, headers = { "Authorization": "Bearer {}".format(access_token) }) @@ -132,7 +130,7 @@ class DriveApiService: Logger.log("w", "Could not get access token.") return False - delete_backup = requests.delete("{}/{}".format(self.DELETE_BACKUP_URL, backup_id), headers = { + delete_backup = requests.delete("{}/{}".format(self.BACKUP_URL, backup_id), headers = { "Authorization": "Bearer {}".format(access_token) }) if delete_backup.status_code >= 300: @@ -151,7 +149,7 @@ class DriveApiService: Logger.log("w", "Could not get access token.") return None - backup_upload_request = requests.put(self.PUT_BACKUP_URL, json = { + backup_upload_request = requests.put(self.BACKUP_URL, json = { "data": { "backup_size": backup_size, "metadata": backup_metadata From 31156d623017f7a6a00a4cba1a574b4a86230037 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:28:54 +0100 Subject: [PATCH 21/43] Add missing signalemitter decorater CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index d9185cc1d2..d9116eccb2 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -11,7 +11,7 @@ import requests from UM.Logger import Logger from UM.Message import Message -from UM.Signal import Signal +from UM.Signal import Signal, signalemitter from cura.CuraApplication import CuraApplication from .UploadBackupJob import UploadBackupJob @@ -22,6 +22,7 @@ catalog = i18nCatalog("cura") ## The DriveApiService is responsible for interacting with the CuraDrive API and Cura's backup handling. +@signalemitter class DriveApiService: BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) From 8ebd4282fd661582e144531f75ca8ee833841c50 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:39:39 +0100 Subject: [PATCH 22/43] Make the backupList use a scrollview instead of manually re-doing it CURA-6005 --- .../src/qml/components/BackupList.qml | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/plugins/CuraDrive/src/qml/components/BackupList.qml b/plugins/CuraDrive/src/qml/components/BackupList.qml index af7e72b6e6..10ca15afe5 100644 --- a/plugins/CuraDrive/src/qml/components/BackupList.qml +++ b/plugins/CuraDrive/src/qml/components/BackupList.qml @@ -2,32 +2,35 @@ // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 -import QtQuick.Controls 2.1 +import QtQuick.Controls 2.2 import QtQuick.Layouts 1.3 import UM 1.1 as UM -ListView +ScrollView { - id: backupList + property alias model: backupList.model width: parent.width - clip: true - delegate: Item + ListView { + id: backupList width: parent.width - height: childrenRect.height - - BackupListItem - { - id: backupListItem - width: parent.width - UM.Theme.getSize("default_margin").width // Add a margin, otherwise the scrollbar is be on top of the right most component - } - - Divider + delegate: Item { width: parent.width - anchors.top: backupListItem.bottom + height: childrenRect.height + + BackupListItem + { + id: backupListItem + width: parent.width + } + + Divider + { + width: parent.width + anchors.top: backupListItem.bottom + } } } - ScrollBar.vertical: RightSideScrollBar {} } From 87eb8634512f8f97a191d5074b2f3e07e700487f Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:43:40 +0100 Subject: [PATCH 23/43] Remove the final traces of the translation indirection CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 2 +- plugins/CuraDrive/src/DrivePluginExtension.py | 4 ++-- plugins/CuraDrive/src/Settings.py | 10 ++-------- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index d9116eccb2..7ca009018b 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -47,7 +47,7 @@ class DriveApiService: if backup_list_request.status_code >= 300: Logger.log("w", "Could not get backups list from remote: %s", backup_list_request.text) - Message(catalog.i18nc("@info:backup_status", "There was an error listing your backups."), title = Settings.MESSAGE_TITLE).show() + Message(catalog.i18nc("@info:backup_status", "There was an error listing your backups."), title = catalog.i18nc("@info:title", "Backup")).show() return [] return backup_list_request.json()["data"] diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 041c01a14d..edd89745ea 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -103,13 +103,13 @@ class DrivePluginExtension(QObject, Extension): self._is_restoring_backup = is_restoring self.restoringStateChanged.emit() if error_message: - Message(error_message, title = Settings.MESSAGE_TITLE, lifetime = 5).show() + Message(error_message, title = catalog.i18nc("@info:title", "Backup")).show() def _onCreatingStateChanged(self, is_creating: bool = False, error_message: str = None) -> None: self._is_creating_backup = is_creating self.creatingStateChanged.emit() if error_message: - Message(error_message, title = Settings.MESSAGE_TITLE, lifetime = 5).show() + Message(error_message, title = catalog.i18nc("@info:title", "Backup")).show() else: self._storeBackupDate() if not is_creating: diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index fcb05b8c04..c5383555b2 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -7,15 +7,9 @@ from cura import UltimakerCloudAuthentication class Settings: - """ - Keeps the application settings. - """ + # Keeps the plugin settings. DRIVE_API_VERSION = 1 DRIVE_API_URL = "{}/cura-drive/v{}".format(UltimakerCloudAuthentication.CuraCloudAPIRoot, str(DRIVE_API_VERSION)) AUTO_BACKUP_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled" - AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" - - I18N_CATALOG = i18nCatalog("cura") - - MESSAGE_TITLE = I18N_CATALOG.i18nc("@info:title", "Backups") \ No newline at end of file + AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" \ No newline at end of file From 63c2a901bb54a9f50cbdec259d06ae969192419e Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:45:24 +0100 Subject: [PATCH 24/43] Prevent double emits / recalculations when not needed CURA-6005 --- plugins/CuraDrive/src/DrivePluginExtension.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index edd89745ea..d1ea34f4a5 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -112,14 +112,13 @@ class DrivePluginExtension(QObject, Extension): Message(error_message, title = catalog.i18nc("@info:title", "Backup")).show() else: self._storeBackupDate() - if not is_creating: + if not is_creating and not error_message: # We've finished creating a new backup, to the list has to be updated. self.refreshBackups() @pyqtSlot(bool, name = "toggleAutoBackup") def toggleAutoBackup(self, enabled: bool) -> None: self._preferences.setValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, enabled) - self.preferencesChanged.emit() @pyqtProperty(bool, notify = preferencesChanged) def autoBackupEnabled(self) -> bool: From 23315260ae1870f393f720393e8b3d5af6df0c47 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:49:41 +0100 Subject: [PATCH 25/43] Fix some of the documentation CURA-6005 --- plugins/CuraDrive/src/DrivePluginExtension.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index d1ea34f4a5..ce9a6651d5 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -18,11 +18,8 @@ from .DriveApiService import DriveApiService from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") - +# The DivePluginExtension provides functionality to backup and restore your Cura configuration to Ultimaker's cloud. class DrivePluginExtension(QObject, Extension): - """ - The DivePluginExtension provides functionality to backup and restore your Cura configuration to Ultimaker's cloud. - """ # Signal emitted when the list of backups changed. backupsChanged = pyqtSignal() @@ -38,7 +35,7 @@ class DrivePluginExtension(QObject, Extension): DATE_FORMAT = "%d/%m/%Y %H:%M:%S" - def __init__(self): + def __init__(self) -> None: QObject.__init__(self, None) Extension.__init__(self) @@ -69,7 +66,6 @@ class DrivePluginExtension(QObject, Extension): CuraApplication.getInstance().engineCreatedSignal.connect(self._autoBackup) def showDriveWindow(self) -> None: - """Show the Drive UI popup window.""" if not self._drive_window: path = os.path.join(os.path.dirname(__file__), "qml", "main.qml") self._drive_window = CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self}) From 3b498d3a34cbfd1a1abd3ae909cec8383ec5f8b1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:51:07 +0100 Subject: [PATCH 26/43] Change name of the signals so they are consistent with rest of the code CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 22 +++++++++---------- plugins/CuraDrive/src/DrivePluginExtension.py | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 7ca009018b..3bb416fce6 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -27,10 +27,10 @@ class DriveApiService: BACKUP_URL = "{}/backups".format(Settings.DRIVE_API_URL) # Emit signal when restoring backup started or finished. - onRestoringStateChanged = Signal() + restoringStateChanged = Signal() # Emit signal when creating backup started or finished. - onCreatingStateChanged = Signal() + creatingStateChanged = Signal() def __init__(self) -> None: self._cura_api = CuraApplication.getInstance().getCuraAPI() @@ -52,12 +52,12 @@ class DriveApiService: return backup_list_request.json()["data"] def createBackup(self) -> None: - self.onCreatingStateChanged.emit(is_creating = True) + self.creatingStateChanged.emit(is_creating = True) # Create the backup. backup_zip_file, backup_meta_data = self._cura_api.backups.createBackup() if not backup_zip_file or not backup_meta_data: - self.onCreatingStateChanged.emit(is_creating = False, error_message = "Could not create backup.") + self.creatingStateChanged.emit(is_creating = False, error_message ="Could not create backup.") return # Create an upload entry for the backup. @@ -65,7 +65,7 @@ class DriveApiService: backup_meta_data["description"] = "{}.backup.{}.cura.zip".format(timestamp, backup_meta_data["cura_release"]) backup_upload_url = self._requestBackupUpload(backup_meta_data, len(backup_zip_file)) if not backup_upload_url: - self.onCreatingStateChanged.emit(is_creating = False, error_message = "Could not upload backup.") + self.creatingStateChanged.emit(is_creating = False, error_message ="Could not upload backup.") return # Upload the backup to storage. @@ -76,12 +76,12 @@ class DriveApiService: def _onUploadFinished(self, job: "UploadBackupJob") -> None: if job.backup_upload_error_message != "": # If the job contains an error message we pass it along so the UI can display it. - self.onCreatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) + self.creatingStateChanged.emit(is_creating = False, error_message = job.backup_upload_error_message) else: - self.onCreatingStateChanged.emit(is_creating = False) + self.creatingStateChanged.emit(is_creating = False) def restoreBackup(self, backup: Dict[str, Any]) -> None: - self.onRestoringStateChanged.emit(is_restoring = True) + self.restoringStateChanged.emit(is_restoring = True) download_url = backup.get("download_url") if not download_url: # If there is no download URL, we can't restore the backup. @@ -108,11 +108,11 @@ class DriveApiService: # Tell Cura to place the backup back in the user data folder. with open(temporary_backup_file.name, "rb") as read_backup: self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("data")) - self.onRestoringStateChanged.emit(is_restoring = False) + self.restoringStateChanged.emit(is_restoring = False) def _emitRestoreError(self): - self.onRestoringStateChanged.emit(is_restoring = False, - error_message = catalog.i18nc("@info:backup_status", + self.restoringStateChanged.emit(is_restoring = False, + error_message = catalog.i18nc("@info:backup_status", "There was an error trying to restore your backup.")) # Verify the MD5 hash of a file. diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index ce9a6651d5..8944b9a980 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -51,8 +51,8 @@ class DrivePluginExtension(QObject, Extension): # Attach signals. CuraApplication.getInstance().getCuraAPI().account.loginStateChanged.connect(self._onLoginStateChanged) - self._drive_api_service.onRestoringStateChanged.connect(self._onRestoringStateChanged) - self._drive_api_service.onCreatingStateChanged.connect(self._onCreatingStateChanged) + self._drive_api_service.restoringStateChanged.connect(self._onRestoringStateChanged) + self._drive_api_service.creatingStateChanged.connect(self._onCreatingStateChanged) # Register preferences. self._preferences.addPreference(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, False) From 0ec0b68360d7029349702f0e7099e9c8e28087bb Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:54:23 +0100 Subject: [PATCH 27/43] Remove unneeded component CURA-6005 --- .../src/qml/components/RightSideScrollBar.qml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml diff --git a/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml b/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml deleted file mode 100644 index 5ef8558ee7..0000000000 --- a/plugins/CuraDrive/src/qml/components/RightSideScrollBar.qml +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 -import QtQuick.Controls 2.1 -import QtQuick.Layouts 1.3 - -ScrollBar -{ - active: true - size: parent.height - anchors.top: parent.top - anchors.right: parent.right - anchors.bottom: parent.bottom -} From 74087ade05117ee2c048de387de023cfdd69c1a1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 10:58:51 +0100 Subject: [PATCH 28/43] Remove a number of orphaned files CURA-6005 --- .../CuraDrive/src/qml/images/avatar_default.png | Bin 3115 -> 0 bytes plugins/CuraDrive/src/qml/images/background.svg | 12 ------------ plugins/CuraDrive/src/qml/images/cura_logo.jpg | Bin 19308 -> 0 bytes plugins/CuraDrive/src/qml/images/cura_logo.png | Bin 13258 -> 0 bytes plugins/CuraDrive/src/qml/images/folder.svg | 7 ------- plugins/CuraDrive/src/qml/images/home.svg | 3 --- .../src/qml/images/inverted_circle.png | Bin 1608 -> 0 bytes plugins/CuraDrive/src/qml/images/restore.svg | 7 ------- 8 files changed, 29 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/images/avatar_default.png delete mode 100644 plugins/CuraDrive/src/qml/images/background.svg delete mode 100644 plugins/CuraDrive/src/qml/images/cura_logo.jpg delete mode 100644 plugins/CuraDrive/src/qml/images/cura_logo.png delete mode 100644 plugins/CuraDrive/src/qml/images/folder.svg delete mode 100644 plugins/CuraDrive/src/qml/images/home.svg delete mode 100644 plugins/CuraDrive/src/qml/images/inverted_circle.png delete mode 100644 plugins/CuraDrive/src/qml/images/restore.svg diff --git a/plugins/CuraDrive/src/qml/images/avatar_default.png b/plugins/CuraDrive/src/qml/images/avatar_default.png deleted file mode 100644 index 0c306680f721dba0de73fb7be90fe5c548608692..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3115 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 - - - Polygon 18 - Created with Sketch. - - - - - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/cura_logo.jpg b/plugins/CuraDrive/src/qml/images/cura_logo.jpg deleted file mode 100644 index 621c03f035cddb3c9337099c25bccf19a5866968..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19308 zcmeHuc|6qJ_xRghD5)k|NlGdEPD~*si7GS!1Uf=KQ`TXHjaw?*`Ezs@` z7+>rjh?!NFRZy3e7nM_1S5i|~P=p|k+idfFGZ+wbn|-klw&L3yi)knZ^vAro**F&H zr;!#fp_H_*bsv7v$sR6NCxy^9#U)*R6xCTPG~Y&$<>K^O?Wi*;euK zty;Zm&Fa-_)~{Z@dOh>Ddi{JA!T+QI#-EVj3P>5c&A}!Hu?w{jG4os zXZLW*LQRNn6gmIG^JecJik`&v)QbhNFIqm2rxjMTewi?L^tlvwzvyLK@1)9M3n$;u z`1In+H+@rr5IZ}dmXk#j4>y+*i-hfRYdHZ0o?`2`@LMY=<-Ag3=YYHU3lfY<)_&Hd83PNyb!Yo>U=boL` z8kyrGw@wykpiD1YM<`9bZGXCd82zvq8)r+KnMsC^+6vL%uiVqAk3`OS%@AU**(k%! zD)VMaw zyzK3qiuz4L!gD0yL6Z&}zYIO6uMjPsCZ2~aFABCEpc*}YJ*bHM+`28zTz!iQ8`1&4 zC+bXGoaXrFMjJzc4W`)5D03C#UR4aTW6tsV^=sn$Bf{k}L-Y(I?kBz+lFEG=;XKz@ z_N^_)eRS-`#I~fZrZe{p5`T+Bct_IfVohec=HkWEGxSXcwmRLPDBYgYEIq5IaMNmE z`=m?f*5Q&u5f1v> zI@T0lPt0UMR7@n@PyhJfk(2KfQOGwjSI69h6fF^vEowQN6MGquWk%*6eevj{ct*nn zB4#3;h?oexgYvfKo-%1@KhxZGras+3D@HS^v%E8z0Ud6!s;MVc+Kf_jFVB+P9caP( zZe{Kv=QAMHkYeu`_7C@3FvGJCQZx&ZJ#U`SS0}c;WkBn@PKR-Jn@i+ACViY}!iTjX z_bSbT3+-UYz4GoD+MU9a$r{f-- zdZx4KW8afAr%OJxzQ;%6X}XRK$R>(5Yc=#{J6-84`~)Rzi`F^(@L;s*bNppE&7>Fq zNdn*Z-g}s@g7o5s2qj6@cb1OA1m%jss%W z<&V)%ni@={ifN!&-k8I%S3=icukJLlrzKrJ`^~Y!3k{`_^ znYj`Ome%x&A&2%EzMGxr+$IAe(q4x&&Jtc~Jq-SB$kzJtqr8UMQ&VwvzrB%xg^IYD zwKb0B&RPyy<_FijBfa!|7_2vVsid>$59E~LcqjvEu<@ktdKWSJpx*n_{g?JuU+qT@ zC1oMY;9ur$O);RhIo<0mPSY7PBfX(plx0)uyjzbjAf*wPKK05Yb^T>}ACi(AYO|DQ zBF~)v{X^UPdTcOB`z0|wzMcW~7%(8AU?X}i11cI9Pj3%NXF%Pi_ZZNpEqK~^MNXd9 za=>Ionvc1(8v86E7qT$*xQAc0PBoiYXU*Vtavq;FK`r#2Tj z7-fYW=(^YuM`3{j>$$&b1P3fyEfJF4XnIO=+KjJ%l@uMaa$+;8Q zJKjay6Q?Be!ZuqYFPvSp#nPrLG=FOmzFFTW7MGLMN-v(XTYqjSFW*)9%V)PWFXIiV%1Y(8Tyx60 zbjI-?`w6s7GaB2%b2EtB;=X3ZDL-!4P`ZcQOm{Y$fgkLj6WG#&%Qm-f>yhc$`C1Iw z`uN$bTgQ`kgPP9b>Al1({B%}-*EC*;0m047V^6)7n0_=9e=+vBqssAdvRt-X0jaHY zIB-Q?v0Ly6vZ#!7^RdJA*1=m^S2LTv9{U`osCjF}U*r6JtT<4GMzEg{g}O-?wmum!XFy-tqEl37;^_+XhZDqXVNDU`Y+Jp#;k-7v;fG&yYJBngUEcRu z&@Xz~{;&*WYzI<|Lo#tU2OozT{Wy+tM~*j5YZ zQjg%ECzCUA0mbq@N`(sV5Vb^Vkpg9{snZ~yzEd4e7X)Hk?|MqcxVGwbZT^m(9bd%@ z{FH9r%0}XqB5mSBFGrofe0%2}2>J5D~$jeJiAYV>g5zMcuA+iUeJT5iBo zi%D~y)}N^ne#au7iZ?{95c#C2wWAu)m5Ehuh%1~b zsTDuq(P6EkGF4WGwa~u%Qocwj!Wk*dVbvA}t>Um^k0!=Tlti0mb*mWW*a{Vf3y)s; z9YJC=O_;@3XNso}rv9HEjCYLTb+X@&xeC&|L=- zCC8m`K1-QHZmzmZ8NkQyO=~01I4v+@o=cF)VQn2i4bxtNOdLc-9WdVZ2QVL*S=M#f z%l&UKZP&l!X?r=CA>46#J4{@ebGvkDyE=&e3~qvT#j)VVey#^hme6^9P)HocOV+!WC!@C-7tPKpa z##}15!A}_^KSB`d0D$j-gn>)ym&@vx%j%cQ>X*yvm&@vx%j%cQ>X*yvm&@vx%j)kw zF2=k0^X7JNhJ>Kg;0Ml}z=;GMgdBhYXAj&yqQDX44AMC8!?IGqR0Xb?e~%#w>3}~` zNFI`fiX_joSi!orLU_g2F5LoMmwl0DLEpQk@9jcnX}8RKQHJG7$j)pd#|cWN@{k>N{&*Fj%o^0a&jnTDOF`h zJ1JFJJ7q_EM`cx2hb3y}eG+!A%Ufkq{X={ z>>cfuWff)ZWmQy}63r44^&@C3m_Gl7HDZeLTu8a1MOkv8Zii%gdo{(7%!x)hh%JE8 zKjFuJ)bm1pU*Mzsx3fRrI~L=J^R@Fr9drV``%eT+=3ml}acBA=zK_7e&I`EOaVRgW zrkJA_#!Yly7(CpaL~)pf3`;WpWs_JtpYP56j3NJ-fXt6{IYWLbseao`sResSRc zBMyAG{ZQ`UXyFSiyJexbz@}UXz2)ZQ?CpB_Yj=2H^P#Vw z6gJp@6Zbkdwo^yZH2Q8H68lU^S0d(KzOs;+1MYcK_ljNTSMmyPym0-HUTT4PGh+89 zau0_6tkMcvSVae|nFaz9riK@{P=rSMLU>lIlmTTmr%q zvmRHs56;Yo>T+;#f$(9@6&xIHtalL1XyJogCjiCVo@cMg-^u;9{%PZ<9ojGxd#^DC zaYdbT8=_5j-bLm;n#f#ULH041I_=2Y$wudAm2URTY3 z?dnA0G!y@H-6X7zmmqcVZaO4%31O@X@INkK>AM$fgDh6Jgc-qWSqR4oM>-ezs4U%E$Dpx@uX zfKvC4&fE#VUk>60Z~jh8ryMUkbGtvF`Ls)MT15eO+lZE)B6@RAwD>_?J@`6%qRvA1 z-3MU1e)m?*f)%<+t=dNB(&E+?sf1boZ<&1R;Qo-*wc@#LHyh9MMtO!4mqxj?`bdnH z?^8@b#i`!&M|o~Jaqjik0|;YDeTmz`gg&D>IJIU@Nbgb7QL^FVGeWs?`rc|(KBeCd z>AIBK;M=FE;z9ABCQM;LUAijP((3lVxzR=L@A=%mXaVsl|X?I;)_HYCcIo2 z5KlTrk^%y8nrcmdw?SlL)i%j0mKL#v<6ob_e06I<$3=xS}G zu}kpju!M0S!sSxmmOfCb&6o(HlP+81o&?-rECAFw)crP(8t<*4}SO0n0P zy9twzQiGc3X5JDiyh*D5`8F}hh1nkl4H=M(#oB7_mbV&f>q%^{5y(22?i0xq_Q!R$y z7*M=K1ucQl`+m7D|8LHw#j`F-4E$#CHXKFw@#GK#lj;GxRq z2j+dz9rsL14?+b|%^wfW+6uv@b1fRx;j~XO(PC%u$Ii6Jc2=6W>27GGJ$igfg{CEW z1AGsV5Mm0nt9w2J(gzxB(kT21{lar{3fhe&fV z-8l^Cjw}s?^T%~M(WAlQ{F(v_sQ)7<>K;|3da~TQ@pG~@pK|Qoz&MNRH&W47*;h8r zr7KQ*n(Ks@8ql#E3`qPdX|kb^0Y#2kJO@kEVj%ttiEcpJi|-J7PQP=n!g2%ac+fXW zt;5h_XN=~GJ~E&TgKWf@BPf`;ai0NIs=uMjf{18A;jA4n|8&}Ci(5v3Oi86H84hw? zgOZ9J8(crl)AxW)YVvdpX;G8!OOpM$x zdiju>OIzk0I_Xp2x4R^vkA%U~Jao@KGWO6#WN3|YaWoe%rR%)U$bodRT~eEJM+ffO zXI9d(1gcYJVhU_$4iqtM5t zv##ovh?U+_j+PoEqU*hW_AZ#&Pi9V^_5~>8NGkH4zs{*PDH$cl$IZA|!V~XkKi-X^ z7gG=Xc_5XzbGm#VVr&GkZ_1X|Ekf5PV5nE0Frdp3h+);gpXwNImc+XnPr0ey=|Il8 z6utFg>(_7Ri@u0m44+$f5k6#3j2$zpsj-56AoXrl(J9~^?edC!~3Y%3o zv5B~wYN1ai#_z*z-L-w|tq6lniO}mmgS<3%t5tQav(J19C|cUr{vqKCDgjFQIU(#McJcgt}|jXPthI-n{K>`X8baUus|> zH~IslZ{6viw9-miaqii(^~FVDK1be!5wG|<&fTv#u|T^mSc^9{bq#dY3dju(ZI9FF z)EhjxB^r-I*{$h%7!@W=*j!;V2d3#F6^rhbQMK`pF$pt7erb*9(EYeR@Ks5G!?{(# zFuj;Lya6ou0ZSphBq`v@*8chQx9y>G+ONV%ip=ftKU7cO578BPN@7kW<*Hp-YZ~&&^)?*(Fgbs|R*->BdX5(H-({G}AZgNzQTosPc$wfzSvuAlus0+Ie2(=9KDc%W7Gw!Z zLhhqUW3PeUh>&AIFZ3kCz{U->Z4CJ4XuUrwkZ)tvjH5_1ET}m=zpKi*$>_Drp1m2r zDXns+VD4r{x7*isVsY*CW7#5*E3%e&0XH|Mz z;6!02A}VAr+SP(C{+7_cpDAeOO4KAkaz|atK)Kz@Eb5Up`gH}gN_91 zu^R~s{D~C;zFt~{R;5sqX5^x3wJh7twhuN1DsK&KOFR+n1;wfx~#QcwcnBXi}9N0G6JqE@_QX}Z7r)0pwo z+4~MY5HF6<5hYUP^=iWNx3HF1T^A)Ou~d!WFK@IMSzm#Wv#0{!vh!X_RY6^Urotp8Q@G$H2?7jU!F|5$K5jP-!JyVQQ{T0Ct2oZF0r$0+HL4jVdp{eh9OM zAUA0A8;_5g<35vD+l8;}Oh1uvNqA%Jx0m~5=oU`b@m)eBvNU`qGs)=lvCePQl<9aK zdbnceJ9twiU8;-xWdA+-bQv&*JQ+~yG5j?J-{-yfZi~6~=qGvjv?!YOPI7UQV!eF3 zp?7*}<`(&Y1HDPX#^8I>O6ZH45Wk--Gr*qC1cn;o0t(Ls}X+pv>yl>uo2H)2# zN>e2MwS~VpHHw_qP5&TcYD}gP@B%PGLP*84C~~m!L=s)Ln|Oh_{_o($;C;Kr$&nFS zRunITz&pBV6ke!OGb`mSN<84<`API_6*v)0uY(0^riOThAY9sNJe_*W6waG|Ozze2 z=L$mJtQ4Eu8-8DeoJ*3y4>~pB2h=<0XDUuJpuL;PQ}p}667(2w=qyEa{f`)`&4rpO zrUeFd$|IXQ)FgM56kkI{h9^rM)~?)MDmE(1=oXvt0mhcXEf-ZPLwx>Ns+Wq)(Vy%idKjL2`0x4yTQ&vf#$qco7B z;2gLU?6;Ey4O#^GMY#j*4f(^(%-6yrO(TP4oXRPr0PqRky5AYlo?MIm*FX!Bd1$>; zv@{zl29&Uo^m$T}N`M9Md={b~H`>F1YQ2D_vxbF)vjmwr@zd6HubNjpV8tY^bBP=C zXr?_EF4IG7KlJCc^oBCNd}4OjSQ52OJ)p3hX{PkrX0y=CaJ*qe!V@! z+~`if$~Ii9ot(?2_x4ii5?q%1&T~s2gpYk2%uW%Qa(*z0s<74V1{Fl{uQB*)#1|s< zY!cnbo|u?xaXaK7{_|&Y3awIxb_j_1{l!xnQ4^R{ImNUWWX+d1Hf0Sd$CfmXtbkdz zU^XI;iVw{eO+T8u4Da+KP&!PTF$HzneaA@`hly_D&hDbujy_i3Bp<7|BM7mIwN1=m z=^lY}jbvcCCs-R%)pkkF82#rWcbR?$U(E%45cL8xVNuGOF?2Z*3hBLmbKpU`1e^jN zNVU~;a-cHLwnQ{7k^x=i23v<5o+5=!815R~F=yK}WmApE!iN}8nZS{{%`FRBd6{n| zQzeO(@?}(|U!gx>;%?_#Bb^st8>>i;M>;0Ojox7FkeGTPzzI0a(w%6{REf>Ek_S?#Fhpw;1?d~=yN)v>Adbm_(Kz00R4g0bM85*itxDXvr0}O7_G9v~%FJ`05LsdewIN ziaoLM80#3q(t)K>lzd>70sWVdTa@Yi>b`%L>hxi}&cN~YK`XroC26YJ&!@stMqlsF zBJ{}Y53%qcdL?wJt5zL+9N!W~TptkEWNa~ol`6v9ud|v$+!u~*ajxKFOdQD zZfK?-*AFj`q16E@+udND8^e8Zg(LvRexoSNHNJkH$OwJ%bEHs3eZ zH6GX14D+4i75dyo%kRQBS>ulZ7r}1Z7(BT?7`PGK=Hx8W{Uu%{O2q6har-hX=wPVa zP}Pu~;}B4@<47x#Zh8~3AJFy$X8NeOxa6EcU|94S|Lds_tL|KDya+a9ojqF*R@kWY z;i)f1t4HNFx+}g-BTwFu*fIESo3Rkms<1TH3LnDp%SQF*09g`efy z8+<+}c%MS-HljWw)`_(Qo9ZG)bf<0dig%!s^dr7-a zhWElIZjC1NJcMd{IX-Coc1Shjr(H$tgMUZ%27+_`|nuG%~Jk z<+LZl-{AYUk#Gccee%<+TxK*UWBjYyU6je~ zr#SapH{asNyqMf?4f7ZH_j8>}U00RJbB$J>xcWlg{p9HV)%j}Is7GA71UX<1s#!eN zjoF2_}U zWk6Lua|(8}{FE8E#0mPPg0d#?USO1JT5iCAg6qMnfvE9HsuO%X#9*=T6;42UKz&tw ztK!>W)mNXt8c86#>$+sUH{IxsUw@^r$vJo6)AI=9V|k%_7L9JkcPAW6v;329rM^2v V{_(E9+wT8(SKsZ~f4r-A{|^$iZYBT# diff --git a/plugins/CuraDrive/src/qml/images/cura_logo.png b/plugins/CuraDrive/src/qml/images/cura_logo.png deleted file mode 100644 index f846f2a0f0934f4843c3279ed741c149c77b2e1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13258 zcmeHu;4V*)BSRu^XaTvbLN?uz4uJ)2XzHpY!LRVSFdoD6lJwuy+WyZdCve~ygc*u(2ZXX z6n8BJ=~tEGlzXpU@kS`gN`3M{In2g&`K-Ng?48+YOUK6%Q!&j{8UO%f(B`2OjGe6E z=pFl$ws^S=Htqi&Eu+nt`f5zkAyuM|<9+lUC7ObBbhAJ)l>)Q49oq{+g+>xugU({Y z!PhW}n#xpMueQi{{k(Xgq^qIfb|t>U@SfRMr>zd5Z{lC^?1wlPJ#bg}3RdVQbU~*? z`TxiNdl#7g_x2?FIG|)>n5~LZ=;-U{r$9xWcyi_~xxLz49$qf=d`tG6X zIStGm9v<#dC-s0$b#qRMgsHFQp^FeRDg%|8>pO3^vnue#Z%ltH62Zo)abYu)lLUvz zhB9bh6s{bH^OfNC;bPHuwsUnckKTeN_+-^P3q;Rl_BXG`4v(a2lIvSvy%OYFLvt*Z39TCgr_a$F=Mp8M>*tj%kWC~v)94VFN5 z1qXZl?GEiRi;f`o`qcv{-e76%eFdNVsQd3-SZTWP)QI7xn+|JN!Q5xxAATLlA*Y)u z8pe!KMjd{a`|_;R{4@b4QtZ`tcX#VkMd;L<4<)IL{^KurzKG;6p8r3E0*#`BRc1%Z4{vHItk9179tO)8Rr)A_% z^@S+;h%bJ(TWOfDQ?c0pN|yDfn~1yLxnevG5wggjcb=tILHvFOzr@qF%`oJMOSJ+{ zvx|e^`kBeW*=VvqpXlg0-=GhY0MM;vt$z~ATSwB$WVr;veV2t$H*iB= z9Qz*R+wd#7o~OW+AvB*R9cy`8kkDbTmzQzWzP^*cskOBg%~EfKP~j8Ris_&aPFLcN zUi#uzboWne?!(MqzJEh8^?ZVidSPC0n3@71p>*8%Z)6$;fFKy%0QQAvykQl%ipl86D zp6LP5w;D0G`6p$=CEh&yyO5|8W$0;Ch)sve$3xGmuBW@dNk;N!XYs*xus)kGap#&jjLnRa>E$AcC6{{L0hB2p z(d5UzFVqZCgKNN3ck+4~>(E_#s08-L_qzM?y77I))HmP8By}+g-%woX6(1QP(8wUT z8_$T)hmPi*wF8sEf`U=ZECL~5A8}a?!?V`I{7*d4ZwX7Lx}uJP?o@<9_<=V#dT;p< zkU)+;E_S^HTK+lpxLcUa<4?$|o6Zp!vVcu&0D#Dwt;O`Ed(S5i;&3`TIyU^WPfJ>o zMJ{QDzv6}BI!lIRtO*usuLGIrp1YIl0XL^Co4C=jrpf69aHA(>N7tQyTpu5(GS~d5%UqzuqpMu?ZR; zn5YT+op(z-ohE~l$Y}oqN`(%5@MOS)F7%$_xUvh1wzo$U0txB7mObYxX2K4(z=BQ| zLm$e;sDrk?iu{re_7*`Ura)P?pJy5L-*KN1(;Z=9a~CixFsrkfDi}Z}`u3eqNJx

{tidI^DPfL*th*F*+_ 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 diff --git a/plugins/CuraDrive/src/qml/images/folder.svg b/plugins/CuraDrive/src/qml/images/folder.svg deleted file mode 100644 index f66f83a888..0000000000 --- a/plugins/CuraDrive/src/qml/images/folder.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/home.svg b/plugins/CuraDrive/src/qml/images/home.svg deleted file mode 100644 index 9d0e4d802c..0000000000 --- a/plugins/CuraDrive/src/qml/images/home.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/inverted_circle.png b/plugins/CuraDrive/src/qml/images/inverted_circle.png deleted file mode 100644 index 3612b37d4d38cd7b1218be42c943932a79f7b465..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1608 zcmV-O2DkZ%P)Px*0!c(cRCodHojY&bMihm$2^^$|ogzu+GJuKziK{dQ0@$6KbS?t}`UTGaabp-t z;i~kgR zm9(f#Bk`Hh#bQJToQuwp^t1Gf^xI;wNV0G!$A#wim2^+K zFMT83l8Q%Z1I|R?x%5mr7Vv*8h{%xl)y`e%JL#eHu~Z~V7{F5fT6!wI6!f=6GOrqy z86Rr&Tj`PXKw@pN3pPPU@weJJl)kXbZnu``Th&MUY7%<}t&q$U>GR!il>0P&t@@nZ zh};GoD-m{nlMMPUkwdn~WxyZm@quK!J<0Kd99kqasqEGcb@~(JT5IK!cP27c-S#u#kG0(8mB)x!EuI zv3W3&cHSKAY5+T(*>3Y==1IR!KzbqHGm%;v-v;2 z4RYK2u#!6cSnF!Qxky!b|3W&lo2<^=jwe1)mBu@+orz~NMqnp!_)z@gNL*nofa?r5*u znHuo8zp#~HypGs_SMis8IxPW_f3>Esk@uq6KaHk+GChGN|X7 z)YpLLr7x7tnD=OAT`}g0@KppSG~}9j4+8?Q4&1{|_)ITw&Af*J0a!~gU+;vEtZt4l z$ZzybRIHEaXxImETabq>ffaLB1BD-WvxU#5{|?|8IhXvfv%LWvraosAbfRrilDiR& zbC`5<74ws&0h7*T+MRa;3j5~MnScA#mXalmQ=Fbpry4LcAnp|E$84L0IpEm`5cgIC|7%EK z$vhZv->_kCYDHkhoYg?#mnIr67UI3WG%@T0Fu^a*H8KI#04KsGh^8rI?O{XU9qW}3 z%fEhuh5>w$-g<)uCETeZ?va-OjA6Zs+8V&9-=r77WEzU`k9FqtoiMNaZK|2TGh6X( zy-gJp{6_6eCcqZJ^@!I1-t$rg84M8D&ZP=4!HabyHUXx9jpMR4fX}cN_+2xJOn_y@ zRD))0Gk{Nd!KMTTh-0sUO~Iyv1bvwGECjN5$udmvqJ0AvAMqPpv=0-!Y-LXqU{d?E`(IhHzx!sYx(+Mf - - - - - - \ No newline at end of file From add5f17ae75bd23734142875e348f4aa2574b774 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:06:43 +0100 Subject: [PATCH 29/43] And removed even more unneeded / duplicate / orphaned images CURA-6005 --- .../src/qml/components/BackupListFooter.qml | 2 +- .../src/qml/components/BackupListItemDetails.qml | 6 +++--- plugins/CuraDrive/src/qml/images/backup.svg | 3 --- plugins/CuraDrive/src/qml/images/cura.svg | 7 ------- .../CuraDrive/src/qml/images/preview_banner.png | Bin 8324 -> 0 bytes plugins/CuraDrive/src/qml/images/printer.svg | 14 -------------- 6 files changed, 4 insertions(+), 28 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/images/backup.svg delete mode 100644 plugins/CuraDrive/src/qml/images/cura.svg delete mode 100644 plugins/CuraDrive/src/qml/images/preview_banner.png delete mode 100644 plugins/CuraDrive/src/qml/images/printer.svg diff --git a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml index a0bc212597..56706b9990 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListFooter.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListFooter.qml @@ -29,7 +29,7 @@ RowLayout { id: createBackupButton text: catalog.i18nc("@button", "Backup Now") - iconSource: "../images/backup.svg" + iconSource: UM.Theme.getIcon("plus") enabled: !CuraDrive.isCreatingBackup && !CuraDrive.isRestoringBackup && !backupListFooter.showInfoButton onClicked: CuraDrive.createBackup() busy: CuraDrive.isCreatingBackup diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml index cf365501ec..2f2dd48e13 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml @@ -17,7 +17,7 @@ ColumnLayout // Cura version BackupListItemDetailsRow { - iconSource: "../images/cura.svg" + iconSource: UM.Theme.getIcon("application") label: catalog.i18nc("@backuplist:label", "Cura Version") value: backupDetailsData.metadata.cura_release } @@ -25,7 +25,7 @@ ColumnLayout // Machine count. BackupListItemDetailsRow { - iconSource: "../images/printer.svg" + iconSource: UM.Theme.getIcon("printer_single") label: catalog.i18nc("@backuplist:label", "Machines") value: backupDetailsData.metadata.machine_count } @@ -41,7 +41,7 @@ ColumnLayout // Profile count. BackupListItemDetailsRow { - iconSource: UM.Theme.getIcon("profile") + iconSource: UM.Theme.getIcon("settings") label: catalog.i18nc("@backuplist:label", "Profiles") value: backupDetailsData.metadata.profile_count } diff --git a/plugins/CuraDrive/src/qml/images/backup.svg b/plugins/CuraDrive/src/qml/images/backup.svg deleted file mode 100644 index 51f6be4cba..0000000000 --- a/plugins/CuraDrive/src/qml/images/backup.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/cura.svg b/plugins/CuraDrive/src/qml/images/cura.svg deleted file mode 100644 index 6b1b6c0c79..0000000000 --- a/plugins/CuraDrive/src/qml/images/cura.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/plugins/CuraDrive/src/qml/images/preview_banner.png b/plugins/CuraDrive/src/qml/images/preview_banner.png deleted file mode 100644 index 414019531beed2e503e05cc394fc7e6de246830a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8324 zcmY+pc|4Tg`#*kW%rM3_LUwME>|3_Va@&vJ_^F zvXre5vMXEmC59~D+w1qo@BNv7=AQfUyq?!}u5)eY%snd$6E?g69st00+|=+i04U@U z1#pbW*SQ;c?t8y(o;J}3#ce{<06;p&4fSjSP;(hfDYo738+#yD*4t4J`8av5@x`5z zQ$A(Gt@byhojdN)tLDSG)e;x7rte9wDJ-8n`CMW-t3*m7@E*4R@uxh!3*5mBa+(bF z-0o5ghtJLo^{qb-o?QL7p1->t;xnIK)~>Vretlu~?bn~Tv-MquA&2FO3t6?6g-*SU zw&Z#Bqi%oh6co;|1s!aQM*B)x+4)+-Wc`OeVE{dPtKJrQ!win2AaWf$k;ur&X@tSE zVu%CWgbqj>BI_9%p0`H@gC=tnitRfCTENhdn~}$d@&5o!QU3oIz`gi?058s>!azbA z8ZD5`gi(!&ky4cz5d}A_VK`#-Kb?`1*l-l=g~we^5JB`F$m$@&KL1e)e|PIGW#r*B zx{klgKpfyAP+n5J@20E*XtJ!F=td9a$Zi1|g=NVfasxzLeE5 z@H>|X zC1x`ba9&SQb^y&FQO7QiPhlcTa1lCO<&f3K#AKZyT?UW_7E_STv2q9^7^|K8RRrGx z3910ymb4gxAuP)CSghJW4#4yVKv}*F$OO0m&%1}WqzKwT!j?!B?GH$2zy;v$*6VP` zFo8!(Ff}@`+5&~C=BD}jW5*cwtn{gPSn`rcRD9<1=rwu?4L`!*dIcnVEnq0cS<_LP zpbI1p5{YFdY>qIQap^|z6%_z2BfG64hJ?VUb4H0mAZC_GjA~&*)~c*=N`eI(I0li$ zR!~Spv>0(WGZ35DahIF!?78%?sF4Z^D%%qm-4j1)l6dZa#owNi5d2^9i`>mj|0~XG zbQJurxKX0W|B4?z#d@OqaaZ@>@BG%2j|0B82Jn4JdIs%Y;RwmhJ?O2VK(z@Th*7$Z zPiZ>uuGWOYWDgAgCHby)3^1!+Nnz$fq1_K(3A$j}bBJi$6C28&M+;l-ilTMu^bZ*{ z%6q@?FJE)Wbnf)N!+v?6%KLBGyx>4!17zhyw=G6vp6u)Wa|Rj&1T_^j>J_bol^rK_ zu(Ug$c#q>`#`MZVS%&LqzetLwiQ@L}XY4=w`t3Sgca;sMNL(F~BN<{o#sutl4iNa0 z+kl$Cn7KK^xY=ece5)bT5k-QI2uw1bhPE@ok4E#pNuuLuSY=@FbhD1~Yf_SsT9O~X zjViAW(~0jRCUN+S$OagnfJQ17W&i!ub8QQe@2Y02VK^avEkZUS&JxVrd^K_tx;&cP z_|dI336;snoe&in}Ylb;5!~JrdTJy_4;Bi0!3!tAOpM z;{pc^mppHdl}`hN*IYQ%N1EdCZQ8Hv7q=&pLoCiOc@EzC{5B(}URTpcb?)$0pK0$J zU4W_yl2k08MZ@nb2$*y{MPj9qDK1yrWd49|NTldaO+;$Nyj;30Tf~Z=@WjjqpF=35 z{+Kn|_AwHBArzrhcI$il@Hgvg)Zm_&x>dsZ(!WT!r%flQIK)Icy7igryVd>{4wxES zywsQ)0%97J^${1E>F(ZJ_a?8+jY6f7Vq{uz{dSK?ms(u~5%y_)6lSCYAio$C+AGqf zc0;tkGQ%PW(!@xvu-1t;^d#Ttu}%v*L22Cqn3g|+A+sAO;$=ZGOf{aO@}3K`COS7z z>c9OWuFKvF`(K|=gy3_b(usHkM7AxLdRpP=yd;-c+iW51r zEe5TVyvo^imbDu-A2!)V?JU=YG@duu56vsyUhVK6?sW+GC8`l9WiEQQn16Nc@3%Kv z0*i@BBsCztMLBvyPPj`od&ClmGj=A*zqGg%ih@oE5{bAEi>1a#y(gN&<+u0m(3-b~ z&$~r;?5e=o9#nbL(cOjuzYl+^S{W>?BX?J)Kc~|ElxJCU!mdP{s^LU$5VOIiKT@O} z{V!<6Zj#m@c6;@0K|$@`bd3-G9nZpk8gi(4znxduDpuI~gMndb(ra53fV-41q-R?C z3z2O%!fI>-bSb+VPHeZd?EZPEvA@V4=wA0I{-fwZd74z*uYX;8+zaMOwjQ->M4@sp zGJ?B^GB*2NuubCdvbSt4~IO{HR-as07H1s>`9T08LUs4Ii`leqN4aV#d=hC zE-`NP{nNQyxu5f!Q0LMJ?fP6fh5Etp0@3d{n@NlS{GKXZ$Xv;@b7>%$OnX&nw$!u# z)qy-_sY}Z>STH-AxerH|-}=M(|66dX##|EO;#B)#_Usgm!T4K%xHiM1eO;L9SpqP{pk3)U>l(7vfEc9gTHn1oWpG#(P?(Cv}&fy9Yhz zB|If?qsPu(7UqyWGrG;S-2)*RR8EAIYFaYc0Op$}Bd(GsbYsG$y^yhev^%0+pE_nA zBgr1&@dD}-W0^z)z1MvI<;{s8dz?_Sb0qu3G)<;x`1CE+f*th=BXeqcdEEs@5I$|I zbqu}dZf~IKGZ;tBf)pBPn2GH^1w+*|49-3F8Pu=tOOA6bLx++b3KP7jx>< zv*^@zMd<`a-Hi$VnLlqMsAX;qJOdBEa=Y=cUlTfM*^*{hHdcy9T&gRq#gcz>)fDa)W)7>H_LIbi-afa51keEZD1 zYcH7xx({I~&INqidJk(BhTI*-N6y&{JRNQd#p$k0NfsI98GdalPiIkChTmvK>EY5_ zoo+gNhko=JO3t{iQx}TOL2~Qb2-aAqHtVU#9S`zN&MFH$rRXdqa$kwmWZrxW+2>n* ztprSVV%v15aWKbA_>oHG8pS?&t9g1uo(&o^pZ(B0n+R z{ZSK|vNQQ$jhR)QH7bx$=$jMoGI0O(wYeAF)kXFlwB4kfB=G9M`J%)Y&!RwyXVNDf z3-)19&qQ6>B0}u@=UaDi$3zDw{b#0AC%@ce0;s~W>Fqgjv+VWJ3ub|6$fwP@ewrc4 z$RHG)mg>Rb|?MRT{=52jjFaxXA|ll+RtxRy(nvB?lOgp4!)o29k4p3>fzDNTd1Rkw#IhG8GHXA3j7RIczbU(Je!2Z1Em&dN}Fk z@y*PGRhEQP3shF;=n>097G&n6%w!aHG_zhh8O9tAAL#V=| z)ATq2nA`6@SrU3c+}Y{%<%!&Fdq22Z)fmnbn&`%SjAiMUI6;jhr4rv441oJz`9?23 zblKI#mT%*4w&T5fEne;BKP~DE`Fby3Xw+j+k>WjezR6>)MAkl}Xww@eJ0#xPW&?&- z6e9?i-6=rk-6AQ5KiTN ze)(mZi%c>1oz4eNs}o5ogrfK<8+uOR!rgz4riU;)x1*$a-BOG$zrP|+8SEh!A9O!A zQ$&QxCEhynfsflqTZ+U?#fJmqD|jwAbY2=BUN}SV)}X+y8%tbM32**J1~Q!HN?7#t z;$6fqAA$4)7{l6>Hk%KRlMI}D7L2eg z-AEVhr>asixTe~n+FF{8t1cm7#j?MKwBs?Cbh^FXYc}NKF-zmCew&hs5A>PjboMzM zttEgwBW>Xx0U~_6ESx*^_Vw2UtEHwj#RyP5t(cA)8iuHakZNpx8aem z|6;SF>OSAkh4;EtVfN*rtn*5-WB~JZpFHP=Lys*Q{AD*S`)rUP$AyIHok#~rDO@|@ zj<5T-*Utuut_Le_Z;dOsth4#=g9tVnnSIdZcbd9S(2Ni{h^dH>()dt+{;2yMa{^sG zSg>HdN&7pS=8v+0-uLbPr-S1=$-k}c_nkuq>6o!fmN??W@1Fvwa6Ost=by_q&*$eW z%D*>?48cjthQ%DO1sE^!zj0ge^b_)g5@Wc=>~xPl^AmL5+PXYhu`6OWoU8r|Sj8iu znsc}RN5rUC@>q&8cAqoXqRdv-*XdwZMWp=x+vHU@v8Rte%wvwhJEPQqV&s_C^Nv(v zvc#kO=NqnpgCusZfF~7{cZUo`t+;$Th17t??J=FCJ&0VHK;rFhiGuVwQOnWfCs~ps z?uvkFo*^M*CWcYaBF~DG9}n-?Io@Gz5SNBVvX6n0?30hyUg6LtmU*vUO0vr5`-@Yy z9o_OblOJ{LG7$348168FS)1cywNK!Y17G`H7=@j-@AyVtP?11RGjjmg$Ugc_;bJG9 zbz|(5)@p#U&yuReeq+e_Y!UbwzJkit>qrzN0itc3>efR7x@Sq^Ii&YPEN{les~VY~ zo%qN4UGTLhMS{k~t*7*yANyoof=(s8tITAI0@doY5PuDfKQHl71gkmO?)q!cC!9okH}*$3U+&lls>jBLl>-=%NBH*I>2vG zni$QQ# zavq%-X!F?+i(9=GY*|;s2aV*UtRv%v7w9?dg@k?P@-M`xXq`}4h#A&kDj4{fqg?rZB3U`1kC;E(dCU?z!Q zTiad7RUd3`9k(y{GJDbAQGCoY3NyTQn%Ajbgp|HtPTKIoN~Y5&C0&RGbX$LEf#ytRC7{HE1Nd2=WiBU*w>lX6~c zq3qSK@~a6~-rrKWZxx05`u+EL!I{UW=;O_0+ee5msNGc>o?$GQwv?lpJ;W;W$(PMa z=L=t+x);o&sIb}0BY0(E;Ya6z;$@Sw^qjf#eagQsKXUPJBz=;CU6tdjTh0aQu|ZbG zrqj)gSJ7YkOQlrYx<>TvhC*g4y5+1=G$`CV(GwQgHAjS(Ezdyuyf1XE$!ye2i$2Y- zu4zPe(p6+`Vw-4SZW1o*M&csx+~efy`eNk5McKo9*B|TGCu*+@i1M1Sm|YRP%#~+! z)+y2@NZ7_IBC8B<4c0zf3@&*QRi~6SEwdFiSedal-q2Vm*O`Dqc|RE8LiT(1 zIp@kGv5ls?zLWHwCT>^j!7A^%U??+k6P8x?VF9dN5-!0P!io8`l2|6>>^o2ah#z$} zGzF9~CwW6JsUin~(P}J6f8X4b7y}V(N9`K+8uyx`D*ETlBT5aYD(fGatqbX&OZ=YJ zZVblWt}F0UW&MCdvf_bemDa^PNhSYfs}JjRW}Zhut$*G=Tr8|i*qyqRiT2R_aBn~5 zhf_$?n)k<4YWhEiyd%WP3;i+I{c}A^30FZmW6P3-ff{LC>tq0DJKjbNX)49FPq!>- zkaO5bvWfb)t?5g4zh%5WzIHMnsjIU02WsHsKzPWQOfW${@TTv1^>j&XiMR4vMTtj) zH_uJ3^w(_UESlM6-W@;pIAEc2leXaCiB8t))Ef>ecu7d!*?r`~1;DDK_AzAvA~9Lh zE0PjdC-%bEG-E$*E2@SoV`K7+%FG?jJ^}#MH!cpvo8VALM}7A43@*LagkkWFyBTr| z&~%+U%&q-XpeMp*^N{xAEC~k@vKI^Q{=lPn+D+HIHfhn4os!N(!`yw7%;?J)n=0Vw zfn`-=Ef9>7-n#Mn&c1Z&9QwQ*@+jd*H`fGC`TTyd z4=Q8{p}$~5+NWnEb*Or6q-RaOU62rcAg;RW*|P+#cKzJvU9q7tYR*_zy%CdH=a!#F zy;R#}$9Ms=(3;?GG|6+Q-}G$*K#TSM@wriBSw`jMnt?s%SL+4^PBc1CO-Wa(%g!mSi622+6U%?3o)fuO zoB80^;X9yHnlme&O@mHd>yELu**g7GSRA#hwpBCv=Bj204ef$kSOl_m`+U+`>oG4 zh(y?oCa=`)TnvtlbU95Jo?4Q-w4&>R_C?l2A75Pv*v zh73Y=5r0(FE)W1N{i`pj5X~G(zEdymr9qChE^;2h`i~Fc?>@N@z zma31^)pfhuKdvV9VE!gjPU=opcIlCDVv7sW8b>6uZmh3!2$^$5KQ+N-tOumIRb&<2 z*&1Q~HC^o1V8?o@yrGiBD^@ihSr)-HqpVGNi5N_7bco4uK*D#?ecfVnsdL`j_xO*{ z0iX3t#kGY#{hm&@bTxKtqooJ5>0iZDr%Dc4?p->`3eQhX%hP!VuKEfsZd3fNf+=C) z-|zhlONj<&n0|Pv8rq+Rp^hGnOl_7Wg|-%fZ~^s!FV_CvAvq76hi0{UO$O(WdR0I6 z_Gf-Q&=a=v#qV}r>C;gf%bK7O(!}o@vno)y{MXjLwY$t`E%=__MRCZA{LuA)_X}+B zFT_i7Ly$=71aH#q&O6oseoKxiK7leI&>vcAI4=w9CQtI@`HU8*U!4|R6gMR_Ldil} zQA283Wl{s%Kh8Lmmc>0EH>Pb@G5XFAjW2Ao1PlO6`&gxv2zcDugl<}C`;c1+pmhH< z8y>hqwLWjOqQ3cA_Os6J%Z8rEEtvFHN6&!V*U<_AWpVR?AGhxLjElKlPTmptq|F+o zyG)si;78Kyo1;pme=G{kySPd0G}(_FSM4U-L#}a|3%+4#Hl@Z}7OqOl$+CpSd-7B) zdPI&}XIiAHJh6E0kghD1iDBVmU&3x9c{cXeeP>=s4CD8Uw6XiW)PHUzW8h%#@eJF)K}Y5a48Ex0u5j27&JWuW-^pvX8rw|cYr9!c0IJ0L z7|G)eF(lc_pE?8I$r_m~l-pYrE!x~H4?TxKMsx5 znte_!^1CuyPqeZ54F>N^f@IaAN|y8Vd=0aLxGwhkJQ73drXy#V$xEUhuH~6(*BZa` zaP`Z@244RW=h6PR#+`R}NCqWKw|le~bf!GkD#dQC%t{^&xOVAfRu`1bxg;lE%XqZ} z8C9H*pc-4HU2$k$-NED5bcU?~{?B!~DhVdFOXH5i?N4^62dwBkp^poF#1xhO+{)?vrl&B^=9hE zXKQC=!{phavibN4f1h^!Jd~ju|G;N66oVS7#PN)1a>ZzOk{9LRfSIfO*17&yE9-*C zRo*oHtcR9NkJW8x-SC+f^kv<5+HzktGHpoBmBzV{QpBM8@a`t+yl~BGtL?a#?vli< zmC?A>`P?tYwF){5`@CE#myd+au}m1TGok>s+Q=sw!hgb`He!>Hpk&T%47dkHm@LJJ zlFR~ktF+c#0{5MsZ2ChR9tlLdB<~{da+Jt?ldn>0$b@Fr%+)nEtP#m=0WuE7ye16;3tQ`=Z3;-tlCC>J{-dWgkAf zjmf1idOsiwINNby|NM`c_adgN-s@3%0Q%NoFcu)P1+5(_wNKVX9Wx56vw+(suqSML z8@8hh1g+MNR}7gCygpPZdx|gr zevhWK{o3jARfNk8_|X6^m(OT@br_JY;m6l(j1Uic35?p`-~kxb-rRY007t~e9FW8U zQfed51N`(1QE!DL!BfFp(I z;=Bmc!NUyTp!A}+9rBF5$pEUp{0->EBhqLfa|5%}lz~1H4M4(2p?D?{GW-y!0<2AJ zy@_Vn8+fEZC07Y^TrY&#k=MNwnAw)s=pzvbx251Vy?ktbIa9RQVF-Q=k_=T=>dBiqX{ExStFtYPf-~WuybtuG=i*!pa8dxfTtI{Y3J;@@XENY!dV$^rejnw|-g0XA2$0WlBMZY~eb?~+ E2O#6GiU0rr diff --git a/plugins/CuraDrive/src/qml/images/printer.svg b/plugins/CuraDrive/src/qml/images/printer.svg deleted file mode 100644 index f7dc83987d..0000000000 --- a/plugins/CuraDrive/src/qml/images/printer.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - icn_singlePrinter - Created with Sketch. - - - - - - - - - \ No newline at end of file From 98153769ff64c306bcf7f6997c10875a2dffbe20 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:23:34 +0100 Subject: [PATCH 30/43] Use wide_margin instead of multiplying default margin CURA-6005 --- plugins/CuraDrive/src/qml/pages/BackupsPage.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml index 3b905a4a39..0ba0cae09b 100644 --- a/plugins/CuraDrive/src/qml/pages/BackupsPage.qml +++ b/plugins/CuraDrive/src/qml/pages/BackupsPage.qml @@ -14,7 +14,7 @@ Item { id: backupsPage anchors.fill: parent - anchors.margins: UM.Theme.getSize("default_margin").width * 3 + anchors.margins: UM.Theme.getSize("wide_margin").width ColumnLayout { From b4911478e343dfcb0dde658014b20181790a40da Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:35:34 +0100 Subject: [PATCH 31/43] Made the plugin depend more on the theme CURA-6005 --- plugins/CuraDrive/src/qml/components/BackupListItem.qml | 2 ++ .../src/qml/components/BackupListItemDetails.qml | 2 +- .../src/qml/components/BackupListItemDetailsRow.qml | 8 ++------ 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/CuraDrive/src/qml/components/BackupListItem.qml b/plugins/CuraDrive/src/qml/components/BackupListItem.qml index 0cd897fada..5cdb500b4e 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItem.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItem.qml @@ -50,6 +50,7 @@ Item Layout.minimumWidth: 100 * screenScaleFactor Layout.maximumWidth: 500 * screenScaleFactor Layout.fillWidth: true + font: UM.Theme.getFont("default") renderType: Text.NativeRendering } @@ -61,6 +62,7 @@ Item Layout.minimumWidth: 100 * screenScaleFactor Layout.maximumWidth: 500 * screenScaleFactor Layout.fillWidth: true + font: UM.Theme.getFont("default") renderType: Text.NativeRendering } diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml index 2f2dd48e13..4da15c6f16 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetails.qml @@ -58,6 +58,6 @@ ColumnLayout Item { width: parent.width - height: 10 * screenScaleFactor + height: UM.Theme.getSize("default_margin").height } } diff --git a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml index 550bdaefab..9e4612fcf8 100644 --- a/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml +++ b/plugins/CuraDrive/src/qml/components/BackupListItemDetailsRow.qml @@ -17,12 +17,6 @@ RowLayout property alias label: detailName.text property alias value: detailValue.text - // Spacing. - Item - { - width: 40 * screenScaleFactor - } - UM.RecolorImage { id: icon @@ -40,6 +34,7 @@ RowLayout Layout.minimumWidth: 50 * screenScaleFactor Layout.maximumWidth: 100 * screenScaleFactor Layout.fillWidth: true + font: UM.Theme.getFont("default") renderType: Text.NativeRendering } @@ -51,6 +46,7 @@ RowLayout Layout.minimumWidth: 50 * screenScaleFactor Layout.maximumWidth: 100 * screenScaleFactor Layout.fillWidth: true + font: UM.Theme.getFont("default") renderType: Text.NativeRendering } } From c10b8b5c3f5f97a3c08be797614bd6e03662422c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:37:52 +0100 Subject: [PATCH 32/43] Fix crash when attempting to restore backup CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 3bb416fce6..79f49bf1a3 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -107,7 +107,7 @@ class DriveApiService: # Tell Cura to place the backup back in the user data folder. with open(temporary_backup_file.name, "rb") as read_backup: - self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("data")) + self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("metadata", {})) self.restoringStateChanged.emit(is_restoring = False) def _emitRestoreError(self): From 3df9b369f7aaa4aaddee974cfd2449cecd69064d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:40:09 +0100 Subject: [PATCH 33/43] Removed the divider as a seperate component Since it's only used in one place, there is no real point in making it a seperate file CURA-6005 --- plugins/CuraDrive/src/qml/components/BackupList.qml | 7 ++++--- plugins/CuraDrive/src/qml/components/Divider.qml | 13 ------------- 2 files changed, 4 insertions(+), 16 deletions(-) delete mode 100644 plugins/CuraDrive/src/qml/components/Divider.qml diff --git a/plugins/CuraDrive/src/qml/components/BackupList.qml b/plugins/CuraDrive/src/qml/components/BackupList.qml index 10ca15afe5..afa9538486 100644 --- a/plugins/CuraDrive/src/qml/components/BackupList.qml +++ b/plugins/CuraDrive/src/qml/components/BackupList.qml @@ -26,10 +26,11 @@ ScrollView width: parent.width } - Divider + Rectangle { - width: parent.width - anchors.top: backupListItem.bottom + id: divider + color: UM.Theme.getColor("lining") + height: UM.Theme.getSize("default_lining").height } } } diff --git a/plugins/CuraDrive/src/qml/components/Divider.qml b/plugins/CuraDrive/src/qml/components/Divider.qml deleted file mode 100644 index 202794fe23..0000000000 --- a/plugins/CuraDrive/src/qml/components/Divider.qml +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) 2018 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.7 - -import UM 1.3 as UM - -Rectangle -{ - id: divider - color: UM.Theme.getColor("lining") - height: UM.Theme.getSize("default_lining").height -} From bca070d567937f5743b3707f25d84a095e1e31d9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:41:21 +0100 Subject: [PATCH 34/43] Fixed typing CURA-6005 --- cura/API/Backups.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/API/Backups.py b/cura/API/Backups.py index 8e5cd7b83a..ef74e74be0 100644 --- a/cura/API/Backups.py +++ b/cura/API/Backups.py @@ -1,6 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Tuple, Optional, TYPE_CHECKING +from typing import Tuple, Optional, TYPE_CHECKING, Dict, Any from cura.Backups.BackupsManager import BackupsManager @@ -24,12 +24,12 @@ class Backups: ## Create a new back-up using the BackupsManager. # \return Tuple containing a ZIP file with the back-up data and a dict # with metadata about the back-up. - def createBackup(self) -> Tuple[Optional[bytes], Optional[dict]]: + def createBackup(self) -> Tuple[Optional[bytes], Optional[Dict[str, Any]]]: return self.manager.createBackup() ## Restore a back-up using the BackupsManager. # \param zip_file A ZIP file containing the actual back-up data. # \param meta_data Some metadata needed for restoring a back-up, like the # Cura version number. - def restoreBackup(self, zip_file: bytes, meta_data: dict) -> None: + def restoreBackup(self, zip_file: bytes, meta_data: Dict[str, Any]) -> None: return self.manager.restoreBackup(zip_file, meta_data) From b363be4afb861bb128357433d765bdc69104d746 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:48:06 +0100 Subject: [PATCH 35/43] Fix typing --- cura/UltimakerCloudAuthentication.py | 2 +- plugins/CuraDrive/src/DrivePluginExtension.py | 4 ++-- plugins/Toolbox/src/Toolbox.py | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/cura/UltimakerCloudAuthentication.py b/cura/UltimakerCloudAuthentication.py index 7ebdfd054b..ac752231b9 100644 --- a/cura/UltimakerCloudAuthentication.py +++ b/cura/UltimakerCloudAuthentication.py @@ -5,7 +5,7 @@ # Constants used for the Cloud API # --------- DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str -DEFAULT_CLOUD_API_VERSION = "1" # type: str +DEFAULT_CLOUD_API_VERSION = 1 # type: int DEFAULT_CLOUD_ACCOUNT_API_ROOT = "https://account.ultimaker.com" # type: str try: diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 8944b9a980..baa8ce092e 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -3,7 +3,7 @@ import os from datetime import datetime -from typing import Optional, List +from typing import Optional, List, Dict, Any from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal @@ -41,7 +41,7 @@ class DrivePluginExtension(QObject, Extension): # Local data caching for the UI. self._drive_window = None # type: Optional[QObject] - self._backups = [] + self._backups = [] # type: List[Dict[str, Any]] self._is_restoring_backup = False self._is_creating_backup = False diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index e7e849f1d2..192471a357 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -31,9 +31,6 @@ i18n_catalog = i18nCatalog("cura") ## The Toolbox class is responsible of communicating with the server through the API class Toolbox(QObject, Extension): - DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com" # type: str - DEFAULT_CLOUD_API_VERSION = 1 # type: int - def __init__(self, application: CuraApplication) -> None: super().__init__() From b4b7e1fc2138718a92a3470254c957d99a2d2b9d Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Fri, 4 Jan 2019 11:50:02 +0100 Subject: [PATCH 36/43] Codestyle & typing --- plugins/CuraDrive/__init__.py | 2 ++ plugins/CuraDrive/src/DriveApiService.py | 3 +-- plugins/CuraDrive/src/DrivePluginExtension.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/CuraDrive/__init__.py b/plugins/CuraDrive/__init__.py index dd7ffeaac3..eeb6b78689 100644 --- a/plugins/CuraDrive/__init__.py +++ b/plugins/CuraDrive/__init__.py @@ -3,8 +3,10 @@ from .src.DrivePluginExtension import DrivePluginExtension + def getMetaData(): return {} + def register(app): return {"extension": DrivePluginExtension()} diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 79f49bf1a3..23e70a978c 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -110,7 +110,7 @@ class DriveApiService: self._cura_api.backups.restoreBackup(read_backup.read(), backup.get("metadata", {})) self.restoringStateChanged.emit(is_restoring = False) - def _emitRestoreError(self): + def _emitRestoreError(self) -> None: self.restoringStateChanged.emit(is_restoring = False, error_message = catalog.i18nc("@info:backup_status", "There was an error trying to restore your backup.")) @@ -144,7 +144,6 @@ class DriveApiService: # \param backup_size The size of the backup file in bytes. # \return: The upload URL for the actual backup file if successful, otherwise None. def _requestBackupUpload(self, backup_metadata: Dict[str, Any], backup_size: int) -> Optional[str]: - access_token = self._cura_api.account.accessToken if not access_token: Logger.log("w", "Could not get access token.") diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index baa8ce092e..fdf7fc1609 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -121,7 +121,7 @@ class DrivePluginExtension(QObject, Extension): return bool(self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY)) @pyqtProperty("QVariantList", notify = backupsChanged) - def backups(self) -> List: + def backups(self) -> List[Dict[str, Any]]: return self._backups @pyqtSlot(name = "refreshBackups") From 53cb2ce1891066c0437effb7a961a1c982f320f2 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 8 Jan 2019 13:29:45 +0100 Subject: [PATCH 37/43] Add comments for http status >=300 check CURA-6005 --- plugins/CuraDrive/src/DriveApiService.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/CuraDrive/src/DriveApiService.py b/plugins/CuraDrive/src/DriveApiService.py index 23e70a978c..7c1f8faa83 100644 --- a/plugins/CuraDrive/src/DriveApiService.py +++ b/plugins/CuraDrive/src/DriveApiService.py @@ -45,6 +45,8 @@ class DriveApiService: "Authorization": "Bearer {}".format(access_token) }) + # HTTP status 300s mean redirection. 400s and 500s are errors. + # Technically 300s are not errors, but the use case here relies on "requests" to handle redirects automatically. if backup_list_request.status_code >= 300: Logger.log("w", "Could not get backups list from remote: %s", backup_list_request.text) Message(catalog.i18nc("@info:backup_status", "There was an error listing your backups."), title = catalog.i18nc("@info:title", "Backup")).show() From a8fe5ced89c92bc7a8362fe280b0c1b5e62cc14e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 8 Jan 2019 13:33:46 +0100 Subject: [PATCH 38/43] Remove unused import CURA-6005 --- plugins/CuraDrive/src/Settings.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/CuraDrive/src/Settings.py b/plugins/CuraDrive/src/Settings.py index c5383555b2..abe64e0acd 100644 --- a/plugins/CuraDrive/src/Settings.py +++ b/plugins/CuraDrive/src/Settings.py @@ -1,8 +1,6 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from UM import i18nCatalog - from cura import UltimakerCloudAuthentication @@ -12,4 +10,4 @@ class Settings: DRIVE_API_URL = "{}/cura-drive/v{}".format(UltimakerCloudAuthentication.CuraCloudAPIRoot, str(DRIVE_API_VERSION)) AUTO_BACKUP_ENABLED_PREFERENCE_KEY = "cura_drive/auto_backup_enabled" - AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" \ No newline at end of file + AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY = "cura_drive/auto_backup_date" From aee4034e3e5d01f43ba34324efb38dc676a6c7c9 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Tue, 8 Jan 2019 15:49:34 +0100 Subject: [PATCH 39/43] No caching preferences CURA-6005 --- plugins/CuraDrive/src/DrivePluginExtension.py | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index fdf7fc1609..1f66706ce6 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -18,6 +18,7 @@ from .DriveApiService import DriveApiService from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") + # The DivePluginExtension provides functionality to backup and restore your Cura configuration to Ultimaker's cloud. class DrivePluginExtension(QObject, Extension): @@ -32,7 +33,7 @@ class DrivePluginExtension(QObject, Extension): # Signal emitted when preferences changed (like auto-backup). preferencesChanged = pyqtSignal() - + DATE_FORMAT = "%d/%m/%Y %H:%M:%S" def __init__(self) -> None: @@ -46,7 +47,7 @@ class DrivePluginExtension(QObject, Extension): self._is_creating_backup = False # Initialize services. - self._preferences = CuraApplication.getInstance().getPreferences() + preferences = CuraApplication.getInstance().getPreferences() self._drive_api_service = DriveApiService() # Attach signals. @@ -55,10 +56,10 @@ class DrivePluginExtension(QObject, Extension): self._drive_api_service.creatingStateChanged.connect(self._onCreatingStateChanged) # Register preferences. - self._preferences.addPreference(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, False) - self._preferences.addPreference(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, datetime.now() - .strftime(self.DATE_FORMAT)) - + preferences.addPreference(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, False) + preferences.addPreference(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, + datetime.now().strftime(self.DATE_FORMAT)) + # Register the menu item self.addMenuItem(catalog.i18nc("@item:inmenu", "Manage backups"), self.showDriveWindow) @@ -74,9 +75,10 @@ class DrivePluginExtension(QObject, Extension): self._drive_window.show() def _autoBackup(self) -> None: - if self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY) and self._isLastBackupTooLongAgo(): + preferences = CuraApplication.getInstance().getPreferences() + if preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY) and self._isLastBackupTooLongAgo(): self.createBackup() - + def _isLastBackupTooLongAgo(self) -> bool: current_date = datetime.now() last_backup_date = self._getLastBackupDate() @@ -84,12 +86,14 @@ class DrivePluginExtension(QObject, Extension): return date_diff.days > 1 def _getLastBackupDate(self) -> "datetime": - last_backup_date = self._preferences.getValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY) + preferences = CuraApplication.getInstance().getPreferences() + last_backup_date = preferences.getValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY) return datetime.strptime(last_backup_date, self.DATE_FORMAT) def _storeBackupDate(self) -> None: backup_date = datetime.now().strftime(self.DATE_FORMAT) - self._preferences.setValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, backup_date) + preferences = CuraApplication.getInstance().getPreferences() + preferences.setValue(Settings.AUTO_BACKUP_LAST_DATE_PREFERENCE_KEY, backup_date) def _onLoginStateChanged(self, logged_in: bool = False) -> None: if logged_in: @@ -114,11 +118,13 @@ class DrivePluginExtension(QObject, Extension): @pyqtSlot(bool, name = "toggleAutoBackup") def toggleAutoBackup(self, enabled: bool) -> None: - self._preferences.setValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, enabled) + preferences = CuraApplication.getInstance().getPreferences() + preferences.setValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY, enabled) @pyqtProperty(bool, notify = preferencesChanged) def autoBackupEnabled(self) -> bool: - return bool(self._preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY)) + preferences = CuraApplication.getInstance().getPreferences() + return bool(preferences.getValue(Settings.AUTO_BACKUP_ENABLED_PREFERENCE_KEY)) @pyqtProperty("QVariantList", notify = backupsChanged) def backups(self) -> List[Dict[str, Any]]: From 520b34ab8901df47a55c90fe98bf827cef9d2499 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 9 Jan 2019 08:41:13 +0100 Subject: [PATCH 40/43] Use getPluginPath() CURA-6005 --- plugins/CuraDrive/src/DrivePluginExtension.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/CuraDrive/src/DrivePluginExtension.py b/plugins/CuraDrive/src/DrivePluginExtension.py index 1f66706ce6..060f1496f1 100644 --- a/plugins/CuraDrive/src/DrivePluginExtension.py +++ b/plugins/CuraDrive/src/DrivePluginExtension.py @@ -68,7 +68,8 @@ class DrivePluginExtension(QObject, Extension): def showDriveWindow(self) -> None: if not self._drive_window: - path = os.path.join(os.path.dirname(__file__), "qml", "main.qml") + plugin_dir_path = CuraApplication.getInstance().getPluginRegistry().getPluginPath("CuraDrive") + path = os.path.join(plugin_dir_path, "src", "qml", "main.qml") self._drive_window = CuraApplication.getInstance().createQmlComponent(path, {"CuraDrive": self}) self.refreshBackups() if self._drive_window: From 580a69f11e864f1d5328143613398abbec29ec39 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 9 Jan 2019 09:27:31 +0100 Subject: [PATCH 41/43] Add CuraCloudAccountAPIRoot to CuraVersion.py.in CURA-6005 --- cura/CuraVersion.py.in | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/CuraVersion.py.in b/cura/CuraVersion.py.in index 7c6304231d..d0f07ebb8c 100644 --- a/cura/CuraVersion.py.in +++ b/cura/CuraVersion.py.in @@ -8,3 +8,4 @@ CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False CuraSDKVersion = "@CURA_SDK_VERSION@" CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@" CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@" +CuraCloudAccountAPIRoot = "CURA_CLOUD_ACCOUNT_API_ROOT" From 03b4121d2289a89d0b779309190bd3d0b8d4efa6 Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Thu, 10 Jan 2019 13:59:22 +0100 Subject: [PATCH 42/43] Fix broken shortcut for slice or stop slicing. --- resources/qml/ActionPanel/SliceProcessWidget.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/ActionPanel/SliceProcessWidget.qml b/resources/qml/ActionPanel/SliceProcessWidget.qml index 1695be8748..0f415a6a2d 100644 --- a/resources/qml/ActionPanel/SliceProcessWidget.qml +++ b/resources/qml/ActionPanel/SliceProcessWidget.qml @@ -194,7 +194,7 @@ Column shortcut: "Ctrl+P" onTriggered: { - if (prepareButton.enabled) + if (sliceButton.enabled) { sliceOrStopSlicing() } From a042de128b64b91421625507e4410496cf050b1a Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 10 Jan 2019 14:16:20 +0100 Subject: [PATCH 43/43] Tag CuraCloudAPIVersion-string-value as expression instead of literal. [CURA-6005] --- cura/CuraVersion.py.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/CuraVersion.py.in b/cura/CuraVersion.py.in index d0f07ebb8c..770a0efd7b 100644 --- a/cura/CuraVersion.py.in +++ b/cura/CuraVersion.py.in @@ -8,4 +8,4 @@ CuraDebugMode = True if "@_cura_debugmode@" == "ON" else False CuraSDKVersion = "@CURA_SDK_VERSION@" CuraCloudAPIRoot = "@CURA_CLOUD_API_ROOT@" CuraCloudAPIVersion = "@CURA_CLOUD_API_VERSION@" -CuraCloudAccountAPIRoot = "CURA_CLOUD_ACCOUNT_API_ROOT" +CuraCloudAccountAPIRoot = "@CURA_CLOUD_ACCOUNT_API_ROOT@"