From 7a7e710b2a4fa3751fefe4d0f7029cceb93b237c Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 6 Mar 2019 17:50:40 +0100 Subject: [PATCH 01/13] Support for manual device addition for plugins (WIP). [CURA-6294] --- cura/UI/WelcomePagesModel.py | 7 ++++--- plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py | 5 +++++ resources/qml/WelcomePages/AddPrinterByIpContent.qml | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cura/UI/WelcomePagesModel.py b/cura/UI/WelcomePagesModel.py index b22fc31408..afcbee5f01 100644 --- a/cura/UI/WelcomePagesModel.py +++ b/cura/UI/WelcomePagesModel.py @@ -7,6 +7,7 @@ from PyQt5.QtCore import QUrl, Qt from UM.Qt.ListModel import ListModel from UM.Resources import Resources +from logging import Logger if TYPE_CHECKING: from PyQt5.QtCore import QObject @@ -17,6 +18,7 @@ class WelcomePagesModel(ListModel): PageUrlRole = Qt.UserRole + 2 # URL to the page's QML file NextPageIdRole = Qt.UserRole + 3 # The next page ID it should go to + def __init__(self, parent: Optional["QObject"] = None) -> None: super().__init__(parent) @@ -28,6 +30,7 @@ class WelcomePagesModel(ListModel): def initialize(self) -> None: from cura.CuraApplication import CuraApplication + # Add default welcome pages self._pages.append({"id": "welcome", "page_url": QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, @@ -51,9 +54,7 @@ class WelcomePagesModel(ListModel): }) self._pages.append({"id": "add_printer_by_ip", "page_url": QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, - os.path.join("WelcomePages", - "AddPrinterByIpContent.qml"))), - }) + os.path.join("WelcomePages", "AddPrinterByIpContent.qml")))}) self._pages.append({"id": "cloud", "page_url": QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, os.path.join("WelcomePages", diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 4529b31c45..b49113b538 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -15,6 +15,7 @@ from cura.CuraApplication import CuraApplication from cura.PrinterOutputDevice import ConnectionType from cura.Settings.GlobalStack import GlobalStack # typing from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin +from UM.OutputDevice.OutputDeviceManager import ManualDeviceAdditionAttempt from UM.Logger import Logger from UM.Signal import Signal, signalemitter from UM.Version import Version @@ -181,6 +182,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._zero_conf.close() self._cloud_output_device_manager.stop() + def canAddManualDevice(self, address: str) -> ManualDeviceAdditionAttempt: + return ManualDeviceAdditionAttempt.POSSIBLE + # TODO?: Check if address is a valid IP (by regexp?). + def removeManualDevice(self, key, address = None): if key in self._discovered_devices: if not address: diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index 25a6d532ce..465e02e1ff 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -148,6 +148,8 @@ Item { addPrinterByIpScreen.hasPushedAdd = true tempTimerRequest.running = true + + UM.OutputDeviceManager.addManualDevice(hostnameField.text, hostnameField.text) } } From 6d34a2abd0a9fbb6c94decfe89816b7e92f75285 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 8 Mar 2019 13:08:44 +0100 Subject: [PATCH 02/13] Start to connect/handle new signals for manual device addition. [CURA-6294] --- plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index b49113b538..8d8bcef4da 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -34,8 +34,6 @@ i18n_catalog = i18nCatalog("cura") # If we discover a printer that has the same key as the active machine instance a connection is made. @signalemitter class UM3OutputDevicePlugin(OutputDevicePlugin): - addDeviceSignal = Signal() - removeDeviceSignal = Signal() discoveredDevicesChanged = Signal() cloudFlowIsPossible = Signal() From bb17ab14da5c0b9ba19651f1d39d47f14b5e7a74 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 13 Mar 2019 15:46:02 +0100 Subject: [PATCH 03/13] (WIP) Connect manual-device-added signals to AddPrinterByIP-page. [CURA-6294] --- .../src/UM3OutputDevicePlugin.py | 13 +++++++ .../WelcomePages/AddPrinterByIpContent.qml | 39 ++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 8d8bcef4da..0a94a228c7 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -34,6 +34,8 @@ i18n_catalog = i18nCatalog("cura") # If we discover a printer that has the same key as the active machine instance a connection is made. @signalemitter class UM3OutputDevicePlugin(OutputDevicePlugin): + addDeviceSignal = Signal() + removeDeviceSignal = Signal() discoveredDevicesChanged = Signal() cloudFlowIsPossible = Signal() @@ -173,6 +175,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self.checkCloudFlowIsPossible() else: self.getOutputDeviceManager().removeOutputDevice(key) + if key.startswith("manual:"): + self.removeManualDeviceSignal.emit(self.getPluginId(), key, self._discovered_devices[key].address()) # TODO? def stop(self): if self._zero_conf is not None: @@ -195,6 +199,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._manual_instances.remove(address) self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances)) + self.removeManualDeviceSignal.emit(self.getPluginId(), key, address) # TODO? + def addManualDevice(self, address): if address not in self._manual_instances: self._manual_instances.append(address) @@ -232,6 +238,10 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): def _onNetworkRequestFinished(self, reply): reply_url = reply.url().toString() + address = "" + device = None + properties = {} # type: Dict[bytes, bytes] + if "system" in reply_url: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200: # Something went wrong with checking the firmware version! @@ -291,6 +301,9 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._onRemoveDevice(instance_name) self._onAddDevice(instance_name, address, properties) + if device: + self.addManualDeviceSignal.emit(self.getPluginId(), device.getId(), address, properties) + def _onRemoveDevice(self, device_id): device = self._discovered_devices.pop(device_id, None) if device: diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index 465e02e1ff..cd13743cd7 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -70,7 +70,7 @@ Item anchors.topMargin: 40 anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter - text: catalog.i18nc("@label", "Add printer by IP adress") + text: catalog.i18nc("@label", "Add printer by IP address") color: UM.Theme.getColor("primary_button") font: UM.Theme.getFont("large_bold") renderType: Text.NativeRendering @@ -193,23 +193,44 @@ Item anchors.top: parent.top font: UM.Theme.getFont("large") - text: "Davids-desktop" // TODO: placeholder, alter after interface review. + text: "???" } GridLayout { + id: printerInfoGrid anchors.top: printerNameLabel.bottom columns: 2 columnSpacing: 20 - Text { font: UM.Theme.getFont("default"); text: "Type" } - Text { font: UM.Theme.getFont("default"); text: "Ultimaker S5" } // TODO: placeholder, alter after interface review. + Text { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Type") } + Label { id: typeText; font: UM.Theme.getFont("default"); text: "?" } - Text { font: UM.Theme.getFont("default"); text: "Firmware version" } - Text { font: UM.Theme.getFont("default"); text: "4.3.3.20180529" } // TODO: placeholder, alter after interface review. + Text { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Firmware version") } + Label { id: firmwareText; font: UM.Theme.getFont("default"); text: "0.0.0.0" } - Text { font: UM.Theme.getFont("default"); text: "Address" } - Text { font: UM.Theme.getFont("default"); text: "10.183.1.115" } // TODO: placeholder, alter after interface review. + Text { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Address") } + Label { id: addressText; font: UM.Theme.getFont("default"); text: "0.0.0.0" } + + Connections + { + target: UM.OutputDeviceManager + onManualDeviceChanged: + { + typeText.text = UM.OutputDeviceManager.manualDeviceProperty("printer_type") + firmwareText.text = UM.OutputDeviceManager.manualDeviceProperty("firmware_version") + addressText.text = UM.OutputDeviceManager.manualDeviceProperty("address") + } + } + } + + Connections + { + target: UM.OutputDeviceManager + onManualDeviceChanged: + { + printerNameLabel.text = UM.OutputDeviceManager.manualDeviceProperty("name") + } } } } @@ -222,7 +243,7 @@ Item anchors.left: parent.left anchors.bottom: parent.bottom anchors.margins: 40 - text: catalog.i18nc("@button", "Back") + text: catalog.i18nc("@button", "Cancel") width: 140 fixedWidthMode: true onClicked: base.showPreviousPage() From b12b6892caddcb0f4341a3e9824f50c2c4d2614d Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 13 Mar 2019 17:36:03 +0100 Subject: [PATCH 04/13] Add-by-IP onboarding: Create (and set active) new device. [CURA-6294] --- .../src/UM3OutputDevicePlugin.py | 3 +- .../WelcomePages/AddPrinterByIpContent.qml | 63 ++++--------------- 2 files changed, 15 insertions(+), 51 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 0a94a228c7..0b0b4a5bf0 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -301,7 +301,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._onRemoveDevice(instance_name) self._onAddDevice(instance_name, address, properties) - if device: + if device and address in self._manual_instances: + self.getOutputDeviceManager().addOutputDevice(device) self.addManualDeviceSignal.emit(self.getPluginId(), device.getId(), address, properties) def _onRemoveDevice(self, device_id): diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index cd13743cd7..c09abac863 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -22,47 +22,6 @@ Item property bool hasSentRequest: false property bool haveConnection: false - Timer - { - id: tempTimerButton - - interval: 1200 - running: false - repeat: false - onTriggered: - { - hasPushedAdd = true - tempTimerRequest.running = true - } - } - // TODO: Remove timers after review interface! - - Timer - { - id: tempTimerRequest - - interval: 1200 - running: false - repeat: false - onTriggered: - { - hasSentRequest = true - tempTimerConnection.running = true - } - } - // TODO: Remove timers after review interface! - - Timer - { - id: tempTimerConnection - - interval: 1200 - running: false - repeat: false - onTriggered: haveConnection = true - } - // TODO: Remove timers after review interface! - Label { id: titleLabel @@ -141,14 +100,9 @@ Item text: catalog.i18nc("@button", "Add") onClicked: { - // TEMP: Simulate successfull connection to printer with 127.0.0.1 or unsuccessful with anything else - // TODO, alter after review interface, now it just starts the timers. - if (hostnameField.text.trim() != "") { addPrinterByIpScreen.hasPushedAdd = true - tempTimerRequest.running = true - UM.OutputDeviceManager.addManualDevice(hostnameField.text, hostnameField.text) } } @@ -203,13 +157,13 @@ Item columns: 2 columnSpacing: 20 - Text { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Type") } + Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Type") } Label { id: typeText; font: UM.Theme.getFont("default"); text: "?" } - Text { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Firmware version") } + Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Firmware version") } Label { id: firmwareText; font: UM.Theme.getFont("default"); text: "0.0.0.0" } - Text { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Address") } + Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Address") } Label { id: addressText; font: UM.Theme.getFont("default"); text: "0.0.0.0" } Connections @@ -230,6 +184,7 @@ Item onManualDeviceChanged: { printerNameLabel.text = UM.OutputDeviceManager.manualDeviceProperty("name") + addPrinterByIpScreen.haveConnection = true } } } @@ -260,7 +215,15 @@ Item text: catalog.i18nc("@button", "Connect") width: 140 fixedWidthMode: true - onClicked: base.showNextPage() + onClicked: + { + Cura.MachineManager.addMachine( + UM.OutputDeviceManager.manualDeviceProperty("printer_type"), + UM.OutputDeviceManager.manualDeviceProperty("name") + ) + UM.OutputDeviceManager.setActiveDevice(UM.OutputDeviceManager.manualDeviceProperty("device_id")) + base.showNextPage() + } enabled: addPrinterByIpScreen.haveConnection } From 2693eecd33313264aaadaf3b3f930fdd89a25605 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 14 Mar 2019 13:33:24 +0100 Subject: [PATCH 05/13] (Add-by-IP/onboard) Cleanup and use discovered-printer instead of machine-manager. [CURA-6294] --- cura/Machines/Models/DiscoveredPrintersModel.py | 8 ++++++++ .../src/UM3OutputDevicePlugin.py | 8 +++----- .../qml/WelcomePages/AddPrinterByIpContent.qml | 15 +++++++++------ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/cura/Machines/Models/DiscoveredPrintersModel.py b/cura/Machines/Models/DiscoveredPrintersModel.py index 0dd07eb9ce..e31b8133a8 100644 --- a/cura/Machines/Models/DiscoveredPrintersModel.py +++ b/cura/Machines/Models/DiscoveredPrintersModel.py @@ -126,3 +126,11 @@ class DiscoveredPrintersModel(QObject): @pyqtSlot("QVariant") def createMachineFromDiscoveredPrinter(self, discovered_printer: "DiscoveredPrinter") -> None: discovered_printer.create_callback(discovered_printer.getKey()) + + @pyqtSlot(str) + def createMachineFromDiscoveredPrinterAddress(self, ip_address: str) -> None: + if ip_address not in self._discovered_printer_dict: + Logger.log("i", "Key [%s] does not exist in the discovered printers list.", ip_address) + return + + self.createMachineFromDiscoveredPrinter(self._discovered_printer_dict[ip_address]) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index c99b12de55..4c775572f3 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -179,7 +179,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): else: self.getOutputDeviceManager().removeOutputDevice(key) if key.startswith("manual:"): - self.removeManualDeviceSignal.emit(self.getPluginId(), key, self._discovered_devices[key].address()) # TODO? + self.removeManualDeviceSignal.emit(self.getPluginId(), key, self._discovered_devices[key].address) def stop(self): if self._zero_conf is not None: @@ -188,8 +188,8 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._cloud_output_device_manager.stop() def canAddManualDevice(self, address: str) -> ManualDeviceAdditionAttempt: + # This plugin should always be the fallback option (at least try it): return ManualDeviceAdditionAttempt.POSSIBLE - # TODO?: Check if address is a valid IP (by regexp?). def removeManualDevice(self, key, address = None): if key in self._discovered_devices: @@ -202,7 +202,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._manual_instances.remove(address) self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances)) - self.removeManualDeviceSignal.emit(self.getPluginId(), key, address) # TODO? + self.removeManualDeviceSignal.emit(self.getPluginId(), key, address) def addManualDevice(self, address): if address not in self._manual_instances: @@ -226,8 +226,6 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._checkManualDevice(address) def _createMachineFromDiscoveredPrinter(self, key: str) -> None: - # TODO: This needs to be implemented. It's supposed to create a machine given a unique key as already discovered - # by this plugin. discovered_device = self._discovered_devices.get(key) if discovered_device is None: Logger.log("e", "Could not find discovered device with key [%s]", key) diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index 47e45cda8a..3aa3e8dc2b 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -55,7 +55,6 @@ Item width: parent.width anchors.top: parent.top anchors.margins: 20 - //anchors.bottomMargin: 20 font: UM.Theme.getFont("default") text: catalog.i18nc("@label", "Enter the IP address or hostname of your printer on the network.") @@ -111,7 +110,12 @@ Item BusyIndicator { anchors.fill: parent - running: { ! parent.enabled && ! addPrinterByIpScreen.hasSentRequest } + running: + { + ! parent.enabled && + ! addPrinterByIpScreen.hasSentRequest && + ! addPrinterByIpScreen.haveConnection + } } } } @@ -154,6 +158,7 @@ Item { id: printerInfoGrid anchors.top: printerNameLabel.bottom + anchors.margins: 20 columns: 2 columnSpacing: 20 @@ -217,10 +222,8 @@ Item fixedWidthMode: true onClicked: { - Cura.MachineManager.addMachine( - UM.OutputDeviceManager.manualDeviceProperty("printer_type"), - UM.OutputDeviceManager.manualDeviceProperty("name") - ) + CuraApplication.getDiscoveredPrintersModel().createMachineFromDiscoveredPrinterAddress( + UM.OutputDeviceManager.manualDeviceProperty("address")) UM.OutputDeviceManager.setActiveDevice(UM.OutputDeviceManager.manualDeviceProperty("device_id")) base.showNextPage() } From 0f116fa3f47e563bea69f3497d32b9fac3c114f0 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 14 Mar 2019 14:59:04 +0100 Subject: [PATCH 06/13] Replace old User-Agreement-page with new Welcome-Pages. [CURA-6057] --- cura/CuraApplication.py | 7 +++++++ plugins/UserAgreement/UserAgreement.py | 9 +++++---- resources/qml/Cura.qml | 2 +- .../qml/WelcomePages/UserAgreementContent.qml | 14 ++++++++++++-- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 1192455312..d02e630911 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -555,11 +555,18 @@ class CuraApplication(QtApplication): def needToShowUserAgreement(self) -> bool: return self._need_to_show_user_agreement + @pyqtSlot(bool) def setNeedToShowUserAgreement(self, set_value = True) -> None: self._need_to_show_user_agreement = set_value + @pyqtSlot(str, str) + def writeToLog(self, severity: str, message: str) -> None: + Logger.log(severity, message) + # DO NOT call this function to close the application, use checkAndExitApplication() instead which will perform # pre-exit checks such as checking for in-progress USB printing, etc. + # Except for the 'Decline and close' in the 'User Agreement'-step in the Welcome-pages, that should be a hard exit. + @pyqtSlot() def closeApplication(self) -> None: Logger.log("i", "Close application") main_window = self.getMainWindow() diff --git a/plugins/UserAgreement/UserAgreement.py b/plugins/UserAgreement/UserAgreement.py index 4ea1ccf9bb..92d23ce725 100644 --- a/plugins/UserAgreement/UserAgreement.py +++ b/plugins/UserAgreement/UserAgreement.py @@ -24,10 +24,11 @@ class UserAgreement(QObject, Extension): self.showUserAgreement() def showUserAgreement(self): - if not self._user_agreement_window: - self.createUserAgreementWindow() - - self._user_agreement_window.show() + # if not self._user_agreement_window: + # self.createUserAgreementWindow() + # + # self._user_agreement_window.show() + pass @pyqtSlot(bool) def didAgree(self, user_choice): diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 47f712e21a..9d1a3e1201 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -45,7 +45,7 @@ UM.MainWindow WelcomeDialog { id: welcomeDialog - visible: false + visible: CuraApplication.needToShowUserAgreement } Rectangle diff --git a/resources/qml/WelcomePages/UserAgreementContent.qml b/resources/qml/WelcomePages/UserAgreementContent.qml index 871dea4602..82b16ba2ee 100644 --- a/resources/qml/WelcomePages/UserAgreementContent.qml +++ b/resources/qml/WelcomePages/UserAgreementContent.qml @@ -62,7 +62,12 @@ Item text: catalog.i18nc("@button", "Agree") width: 140 fixedWidthMode: true - onClicked: base.showNextPage() + onClicked: + { + CuraApplication.writeToLog("i", "User accepted the User-Agreement.") + CuraApplication.setNeedToShowUserAgreement(false) + base.showNextPage() + } } Cura.SecondaryButton @@ -74,6 +79,11 @@ Item text: catalog.i18nc("@button", "Decline and close") width: 140 fixedWidthMode: true - onClicked: base.showNextPage() // TODO: quit + onClicked: + { + CuraApplication.writeToLog("i", "User declined the User Agreement.") + base.passLastPage() + CuraApplication.closeApplication() // NOTE: Hard exit, don't use if anything needs to be saved! + } } } From 4a95564277395d8ec8ad9a7d4617b601ffcd7d15 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 15 Mar 2019 11:30:07 +0100 Subject: [PATCH 07/13] Only show Welcome-Pages when needed. [CURA-6057] --- cura/CuraApplication.py | 8 ++------ resources/qml/Cura.qml | 9 ++++++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index d02e630911..2b6546ba1e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -245,8 +245,6 @@ class CuraApplication(QtApplication): self._update_platform_activity_timer = None - self._need_to_show_user_agreement = True - self._sidebar_custom_menu_items = [] # type: list # Keeps list of custom menu items for the side bar self._plugins_loaded = False @@ -530,8 +528,6 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/expanded_brands", "") preferences.addPreference("cura/expanded_types", "") - self._need_to_show_user_agreement = not preferences.getValue("general/accepted_user_agreement") - for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin "dialog_profile_path", @@ -553,11 +549,11 @@ class CuraApplication(QtApplication): @pyqtProperty(bool) def needToShowUserAgreement(self) -> bool: - return self._need_to_show_user_agreement + return not self.getPreferences().getValue("general/accepted_user_agreement") @pyqtSlot(bool) def setNeedToShowUserAgreement(self, set_value = True) -> None: - self._need_to_show_user_agreement = set_value + self.getPreferences().setValue("general/accepted_user_agreement", not set_value) @pyqtSlot(str, str) def writeToLog(self, severity: str, message: str) -> None: diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 9d1a3e1201..72d3c77838 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -45,7 +45,7 @@ UM.MainWindow WelcomeDialog { id: welcomeDialog - visible: CuraApplication.needToShowUserAgreement + visible: true // True, so if somehow no preferences are found/loaded, it's shown anyway. } Rectangle @@ -83,6 +83,13 @@ UM.MainWindow // This has been fixed for QtQuick Controls 2 since the Shortcut item has a context property. Cura.Actions.parent = backgroundItem CuraApplication.purgeWindows() + + if (CuraApplication.needToShowUserAgreement) + { + welcomeDialog.visible = true; + welcomeDialog.currentStep = 0; + welcomeDialog.show(); + } } Item From 5b31feebba4df36481392f4c1f45fc016fd2a9f3 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 15 Mar 2019 13:58:36 +0100 Subject: [PATCH 08/13] Remove UserAgreement-plugin in favour of Welcome-Pages. [CURA-6057] --- cura/CuraApplication.py | 4 +- plugins/UserAgreement/UserAgreement.py | 47 ------------------ plugins/UserAgreement/UserAgreement.qml | 63 ------------------------- plugins/UserAgreement/__init__.py | 10 ---- plugins/UserAgreement/plugin.json | 8 ---- resources/bundled_packages/cura.json | 17 ------- resources/qml/Cura.qml | 15 ++---- 7 files changed, 8 insertions(+), 156 deletions(-) delete mode 100644 plugins/UserAgreement/UserAgreement.py delete mode 100644 plugins/UserAgreement/UserAgreement.qml delete mode 100644 plugins/UserAgreement/__init__.py delete mode 100644 plugins/UserAgreement/plugin.json diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2b6546ba1e..5f13d50b98 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -456,7 +456,7 @@ class CuraApplication(QtApplication): # Misc.: "ConsoleLogger", #You want to be able to read the log if something goes wrong. "CuraEngineBackend", #Cura is useless without this one since you can't slice. - "UserAgreement", #Our lawyers want every user to see this at least once. + # NOTE: User-Agreement is part of the 'onboarding flow' now (See Welcome Pages). "FileLogger", #You want to be able to read the log if something goes wrong. "XmlMaterialProfile", #Cura crashes without this one. "Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back. @@ -528,6 +528,8 @@ class CuraApplication(QtApplication): preferences.addPreference("cura/expanded_brands", "") preferences.addPreference("cura/expanded_types", "") + preferences.addPreference("general/accepted_user_agreement", False) + for key in [ "dialog_load_path", # dialog_save_path is in LocalFileOutputDevicePlugin "dialog_profile_path", diff --git a/plugins/UserAgreement/UserAgreement.py b/plugins/UserAgreement/UserAgreement.py deleted file mode 100644 index 92d23ce725..0000000000 --- a/plugins/UserAgreement/UserAgreement.py +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -import os - -from PyQt5.QtCore import QObject, pyqtSlot - -from UM.Extension import Extension -from UM.Logger import Logger - - -class UserAgreement(QObject, Extension): - def __init__(self, application): - super(UserAgreement, self).__init__() - self._application = application - self._user_agreement_window = None - self._user_agreement_context = None - self._application.engineCreatedSignal.connect(self._onEngineCreated) - - self._application.getPreferences().addPreference("general/accepted_user_agreement", False) - - def _onEngineCreated(self): - if not self._application.getPreferences().getValue("general/accepted_user_agreement"): - self.showUserAgreement() - - def showUserAgreement(self): - # if not self._user_agreement_window: - # self.createUserAgreementWindow() - # - # self._user_agreement_window.show() - pass - - @pyqtSlot(bool) - def didAgree(self, user_choice): - if user_choice: - Logger.log("i", "User agreed to the user agreement") - self._application.getPreferences().setValue("general/accepted_user_agreement", True) - self._user_agreement_window.hide() - else: - Logger.log("i", "User did NOT agree to the user agreement") - self._application.getPreferences().setValue("general/accepted_user_agreement", False) - self._application.quit() - self._application.setNeedToShowUserAgreement(False) - - def createUserAgreementWindow(self): - path = os.path.join(self._application.getPluginRegistry().getPluginPath(self.getPluginId()), "UserAgreement.qml") - self._user_agreement_window = self._application.createQmlComponent(path, {"manager": self}) diff --git a/plugins/UserAgreement/UserAgreement.qml b/plugins/UserAgreement/UserAgreement.qml deleted file mode 100644 index 2e5893fc41..0000000000 --- a/plugins/UserAgreement/UserAgreement.qml +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2017 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.2 -import QtQuick.Controls 1.4 - -import UM 1.3 as UM - -UM.Dialog -{ - id: baseDialog - minimumWidth: Math.round(UM.Theme.getSize("modal_window_minimum").width * 0.75) - minimumHeight: Math.round(UM.Theme.getSize("modal_window_minimum").height * 0.5) - width: minimumWidth - height: minimumHeight - title: catalog.i18nc("@title:window", "User Agreement") - - TextArea - { - anchors.top: parent.top - width: parent.width - anchors.bottom: buttonRow.top - text: '

DISCLAIMER BY ULTIMAKER

-

PLEASE READ THIS DISCLAIMER CAREFULLY.

-

EXCEPT WHEN OTHERWISE STATED IN WRITING, ULTIMAKER PROVIDES ANY ULTIMAKER SOFTWARE OR THIRD PARTY SOFTWARE “AS IS” WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF ULTIMAKER SOFTWARE IS WITH YOU.

-

UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, IN NO EVENT WILL ULTIMAKER BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE ANY ULTIMAKER SOFTWARE OR THIRD PARTY SOFTWARE.

- ' - readOnly: true; - textFormat: TextEdit.RichText - } - - Item - { - id: buttonRow - anchors.bottom: parent.bottom - width: parent.width - anchors.bottomMargin: UM.Theme.getSize("default_margin").height - - UM.I18nCatalog { id: catalog; name: "cura" } - - Button - { - anchors.right: parent.right - text: catalog.i18nc("@action:button", "I understand and agree") - onClicked: { - baseDialog.accepted() - } - } - - Button - { - anchors.left: parent.left - text: catalog.i18nc("@action:button", "I don't agree") - onClicked: { - baseDialog.rejected() - } - } - } - - onAccepted: manager.didAgree(true) - onRejected: manager.didAgree(false) - onClosing: manager.didAgree(false) -} diff --git a/plugins/UserAgreement/__init__.py b/plugins/UserAgreement/__init__.py deleted file mode 100644 index 3cf81c64f4..0000000000 --- a/plugins/UserAgreement/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2017 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from . import UserAgreement - -def getMetaData(): - return {} - -def register(app): - return {"extension": UserAgreement.UserAgreement(app)} diff --git a/plugins/UserAgreement/plugin.json b/plugins/UserAgreement/plugin.json deleted file mode 100644 index b172d1f9a2..0000000000 --- a/plugins/UserAgreement/plugin.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "UserAgreement", - "author": "Ultimaker B.V.", - "version": "1.0.1", - "description": "Ask the user once if he/she agrees with our license.", - "api": "6.0", - "i18n-catalog": "cura" -} diff --git a/resources/bundled_packages/cura.json b/resources/bundled_packages/cura.json index 9e126ee028..12cdf7b80a 100644 --- a/resources/bundled_packages/cura.json +++ b/resources/bundled_packages/cura.json @@ -560,23 +560,6 @@ } } }, - "UserAgreement": { - "package_info": { - "package_id": "UserAgreement", - "package_type": "plugin", - "display_name": "User Agreement", - "description": "Ask the user once if he/she agrees with our license.", - "package_version": "1.0.1", - "sdk_version": "6.0", - "website": "https://ultimaker.com", - "author": { - "author_id": "UltimakerPackages", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, "VersionUpgrade21to22": { "package_info": { "package_id": "VersionUpgrade21to22", diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 72d3c77838..6af28d3e7b 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -90,6 +90,11 @@ UM.MainWindow welcomeDialog.currentStep = 0; welcomeDialog.show(); } + else + { + welcomeDialog.hide() + welcomeDialog.visible = false; + } } Item @@ -845,16 +850,6 @@ UM.MainWindow { base.visible = true; } - - // check later if the user agreement dialog has been closed - if (CuraApplication.needToShowUserAgreement) - { - restart(); - } - else if(Cura.MachineManager.activeMachine == null) - { - addMachineDialog.open(); - } } } From 740dd095cccbc14315cd4c64b4c8db1e8e6fb149 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 19 Mar 2019 13:45:56 +0100 Subject: [PATCH 09/13] (Add-by-IP) Incorporated review comments. [CURA-6294] --- plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py index 4c775572f3..d0fc543cd6 100644 --- a/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/src/UM3OutputDevicePlugin.py @@ -37,8 +37,8 @@ i18n_catalog = i18nCatalog("cura") # If we discover a printer that has the same key as the active machine instance a connection is made. @signalemitter class UM3OutputDevicePlugin(OutputDevicePlugin): - addDeviceSignal = Signal() - removeDeviceSignal = Signal() + addDeviceSignal = Signal() # Called '...Signal' to avoid confusion with function-names. + removeDeviceSignal = Signal() # Ditto ^^^. discoveredDevicesChanged = Signal() cloudFlowIsPossible = Signal() @@ -187,7 +187,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin): self._zero_conf.close() self._cloud_output_device_manager.stop() - def canAddManualDevice(self, address: str) -> ManualDeviceAdditionAttempt: + def canAddManualDevice(self, address: str = "") -> ManualDeviceAdditionAttempt: # This plugin should always be the fallback option (at least try it): return ManualDeviceAdditionAttempt.POSSIBLE From 61d2aa5c5f747bf80ec349de2a8edae9cc4a7656 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 20 Mar 2019 13:16:10 +0100 Subject: [PATCH 10/13] No more hardcoded margins (and other QML fixes) in 'add-by-ip'. [CURA-6294] --- .../WelcomePages/AddPrinterByIpContent.qml | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index 3aa3e8dc2b..40216ec235 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -26,7 +26,7 @@ Item { id: titleLabel anchors.top: parent.top - anchors.topMargin: 40 + anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.horizontalCenter: parent.horizontalCenter horizontalAlignment: Text.AlignHCenter text: catalog.i18nc("@label", "Add printer by IP address") @@ -35,14 +35,14 @@ Item renderType: Text.NativeRendering } - Rectangle + Item { anchors.top: titleLabel.bottom anchors.bottom: connectButton.top - anchors.topMargin: 40 - anchors.bottomMargin: 40 + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.bottomMargin: UM.Theme.getSize("default_margin").height anchors.horizontalCenter: parent.horizontalCenter - width: parent.width * 3 / 4 + width: (parent.width * 3 / 4) | 0 Item { @@ -54,7 +54,7 @@ Item height: contentHeight width: parent.width anchors.top: parent.top - anchors.margins: 20 + anchors.margins: UM.Theme.getSize("default_margin").width font: UM.Theme.getFont("default") text: catalog.i18nc("@label", "Enter the IP address or hostname of your printer on the network.") @@ -74,14 +74,12 @@ Item anchors.left: parent.left height: addPrinterButton.height anchors.right: addPrinterButton.left - anchors.margins: 20 + anchors.margins: UM.Theme.getSize("default_margin").width font: UM.Theme.getFont("default") - text: "" - validator: RegExpValidator { - regExp: /[a-zA-Z0-9\.\-\_]*/ + regExp: /[0-9\.\-\_]*/ } onAccepted: addPrinterButton.clicked() @@ -92,8 +90,8 @@ Item id: addPrinterButton anchors.top: parent.top anchors.right: parent.right - anchors.margins: 20 - width: 140 + anchors.margins: UM.Theme.getSize("default_margin").width + width: UM.Theme.getSize("action_button").width fixedWidthMode: true text: catalog.i18nc("@button", "Add") @@ -124,13 +122,13 @@ Item { width: parent.width anchors.top: userInputFields.bottom - anchors.margins: 20 + anchors.margins: UM.Theme.getSize("default_margin").width Label { id: waitResponseLabel anchors.top: parent.top - anchors.margins: 20 + anchors.margins: UM.Theme.getSize("default_margin").width font: UM.Theme.getFont("default") visible: { addPrinterByIpScreen.hasSentRequest && ! addPrinterByIpScreen.haveConnection } @@ -141,7 +139,7 @@ Item { id: printerInfoLabels anchors.top: parent.top - anchors.margins: 20 + anchors.margins: UM.Theme.getSize("default_margin").width visible: addPrinterByIpScreen.haveConnection @@ -158,9 +156,9 @@ Item { id: printerInfoGrid anchors.top: printerNameLabel.bottom - anchors.margins: 20 + anchors.margins: UM.Theme.getSize("default_margin").width columns: 2 - columnSpacing: 20 + columnSpacing: UM.Theme.getSize("default_margin").width Label { font: UM.Theme.getFont("default"); text: catalog.i18nc("@label", "Type") } Label { id: typeText; font: UM.Theme.getFont("default"); text: "?" } @@ -202,9 +200,9 @@ Item id: backButton anchors.left: parent.left anchors.bottom: parent.bottom - anchors.margins: 40 + anchors.margins: UM.Theme.getSize("default_margin").width text: catalog.i18nc("@button", "Cancel") - width: 140 + width: UM.Theme.getSize("action_button").width fixedWidthMode: true onClicked: base.gotoPage("add_printer_by_selection") @@ -216,9 +214,9 @@ Item id: connectButton anchors.right: parent.right anchors.bottom: parent.bottom - anchors.margins: 40 + anchors.margins: UM.Theme.getSize("default_margin").width text: catalog.i18nc("@button", "Connect") - width: 140 + width: UM.Theme.getSize("action_button").width fixedWidthMode: true onClicked: { From 1f2fea14ceed8b66f45ee6faf5ccd2dfe69a6035 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 20 Mar 2019 16:08:50 +0100 Subject: [PATCH 11/13] Little refactors (apply review comments). [CURA-6294] --- cura/CuraApplication.py | 1 - cura/UI/WelcomePagesModel.py | 1 - resources/qml/Cura.qml | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index f3a79cecce..6fbe8fde73 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -453,7 +453,6 @@ class CuraApplication(QtApplication): # Misc.: "ConsoleLogger", #You want to be able to read the log if something goes wrong. "CuraEngineBackend", #Cura is useless without this one since you can't slice. - # NOTE: User-Agreement is part of the 'onboarding flow' now (See Welcome Pages). "FileLogger", #You want to be able to read the log if something goes wrong. "XmlMaterialProfile", #Cura crashes without this one. "Toolbox", #This contains the interface to enable/disable plug-ins, so if you disable it you can't enable it back. diff --git a/cura/UI/WelcomePagesModel.py b/cura/UI/WelcomePagesModel.py index c0aeffb3ad..d72071fd7f 100644 --- a/cura/UI/WelcomePagesModel.py +++ b/cura/UI/WelcomePagesModel.py @@ -7,7 +7,6 @@ from PyQt5.QtCore import QUrl, Qt from UM.Qt.ListModel import ListModel from UM.Resources import Resources -from logging import Logger if TYPE_CHECKING: from PyQt5.QtCore import QObject diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index d71f219052..47fa54dbc1 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -78,13 +78,13 @@ UM.MainWindow { welcomeDialog.visible = true; welcomeDialog.currentStep = 0; - welcomeDialog.show(); } else { - welcomeDialog.hide() welcomeDialog.visible = false; } + // TODO: While the new onboarding process contains the user-agreement, + // it should probably not entirely rely on 'needToShowUserAgreement' for show/hide. } Item From 9a2b800fe814c61360df20775bfe0aba66a11f40 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 20 Mar 2019 17:01:37 +0100 Subject: [PATCH 12/13] Future proof: also accept IPv6 address. [CURA-6294] --- resources/qml/WelcomePages/AddPrinterByIpContent.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index 40216ec235..0ffc79cc5b 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -79,7 +79,7 @@ Item validator: RegExpValidator { - regExp: /[0-9\.\-\_]*/ + regExp: /[a-fA-F0-9\.\:]*/ } onAccepted: addPrinterButton.clicked() From 8f9bd0ad0697774c51194606f4fe65c553f6c252 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 20 Mar 2019 17:20:06 +0100 Subject: [PATCH 13/13] Adapted to more review comments. [CURA-6294] --- resources/qml/WelcomePages/AddPrinterByIpContent.qml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/resources/qml/WelcomePages/AddPrinterByIpContent.qml b/resources/qml/WelcomePages/AddPrinterByIpContent.qml index 0ffc79cc5b..f3ed58200b 100644 --- a/resources/qml/WelcomePages/AddPrinterByIpContent.qml +++ b/resources/qml/WelcomePages/AddPrinterByIpContent.qml @@ -18,7 +18,6 @@ Item id: addPrinterByIpScreen - property bool hasPushedAdd: false property bool hasSentRequest: false property bool haveConnection: false @@ -42,7 +41,7 @@ Item anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.bottomMargin: UM.Theme.getSize("default_margin").height anchors.horizontalCenter: parent.horizontalCenter - width: (parent.width * 3 / 4) | 0 + width: Math.floor(parent.width * 3 / 4) Item { @@ -99,12 +98,11 @@ Item { if (hostnameField.text.trim() != "") { - addPrinterByIpScreen.hasPushedAdd = true - UM.OutputDeviceManager.addManualDevice(hostnameField.text, hostnameField.text) + enabled = false; + UM.OutputDeviceManager.addManualDevice(hostnameField.text, hostnameField.text); } } - enabled: ! addPrinterByIpScreen.hasPushedAdd BusyIndicator { anchors.fill: parent