From e0e3c9609f499040f43dd3e329831204de0ba6b0 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 10 Apr 2019 10:52:08 +0200 Subject: [PATCH 01/32] Fix update should show logic CURA-6447 --- cura/UI/WelcomePagesModel.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/UI/WelcomePagesModel.py b/cura/UI/WelcomePagesModel.py index b465e9f252..be29ed5619 100644 --- a/cura/UI/WelcomePagesModel.py +++ b/cura/UI/WelcomePagesModel.py @@ -202,7 +202,7 @@ class WelcomePagesModel(ListModel): # FIXME: HACKs for optimization that we don't update the model every time the active machine gets changed. def _onActiveMachineChanged(self) -> None: self._application.getMachineManager().globalContainerChanged.disconnect(self._onActiveMachineChanged) - self.initialize() + self._initialize() def initialize(self) -> None: self._application.getMachineManager().globalContainerChanged.connect(self._onActiveMachineChanged) @@ -210,7 +210,7 @@ class WelcomePagesModel(ListModel): def _initialize(self) -> None: has_active_machine = self._application.getMachineManager().activeMachine is not None - has_app_just_upgraded = self._application.hasJustUpgradedToNewVersion() + has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion() # Only show the what's new dialog if there's no machine and we have just upgraded show_complete_flow = not has_active_machine From 9494173f43ff5dfebd963413083f17d36fd63d57 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 12 Apr 2019 12:10:56 +0200 Subject: [PATCH 02/32] Remove hack in WelcomePagesModel and add WhatsNewPagesModel CURA-6447 --- cura/CuraApplication.py | 26 +++++++ cura/UI/WelcomePagesModel.py | 42 +--------- cura/UI/WhatsNewPagesModel.py | 22 ++++++ resources/qml/Actions.qml | 8 ++ resources/qml/Cura.qml | 78 ++++++++++++++----- resources/qml/MainWindow/ApplicationMenu.qml | 1 + .../qml/WelcomePages/WhatsNewContent.qml | 2 +- 7 files changed, 116 insertions(+), 63 deletions(-) create mode 100644 cura/UI/WhatsNewPagesModel.py diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 1bc55d76f9..d5ab2bd706 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -114,6 +114,7 @@ from cura.UI.ObjectsModel import ObjectsModel from cura.UI.TextManager import TextManager from cura.UI.AddPrinterPagesModel import AddPrinterPagesModel from cura.UI.WelcomePagesModel import WelcomePagesModel +from cura.UI.WhatsNewPagesModel import WhatsNewPagesModel from .SingleInstance import SingleInstance from .AutoSave import AutoSave @@ -219,6 +220,7 @@ class CuraApplication(QtApplication): self._first_start_machine_actions_model = FirstStartMachineActionsModel(self) self._welcome_pages_model = WelcomePagesModel(self) self._add_printer_pages_model = AddPrinterPagesModel(self) + self._whats_new_pages_model = WhatsNewPagesModel(self) self._text_manager = TextManager(self) self._quality_profile_drop_down_menu_model = None @@ -765,6 +767,7 @@ class CuraApplication(QtApplication): self._output_device_manager.start() self._welcome_pages_model.initialize() self._add_printer_pages_model.initialize() + self._whats_new_pages_model.initialize() # Detect in which mode to run and execute that mode if self._is_headless: @@ -880,6 +883,10 @@ class CuraApplication(QtApplication): def getAddPrinterPagesModel(self, *args) -> "AddPrinterPagesModel": return self._add_printer_pages_model + @pyqtSlot(result = QObject) + def getWhatsNewPagesModel(self, *args) -> "WhatsNewPagesModel": + return self._whats_new_pages_model + @pyqtSlot(result = QObject) def getMachineSettingsManager(self, *args) -> "MachineSettingsManager": return self._machine_settings_manager @@ -1021,6 +1028,7 @@ class CuraApplication(QtApplication): qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) qmlRegisterType(WelcomePagesModel, "Cura", 1, 0, "WelcomePagesModel") + qmlRegisterType(WhatsNewPagesModel, "Cura", 1, 0, "WhatsNewPagesModel") qmlRegisterType(AddPrinterPagesModel, "Cura", 1, 0, "AddPrinterPagesModel") qmlRegisterType(TextManager, "Cura", 1, 0, "TextManager") @@ -1765,3 +1773,21 @@ class CuraApplication(QtApplication): def getSidebarCustomMenuItems(self) -> list: return self._sidebar_custom_menu_items + @pyqtSlot(result = bool) + def shouldShowWelcomeDialog(self) -> bool: + has_active_machine = self._machine_manager.activeMachine is not None + + # Only show the complete flow if there is not printer yet. + show_complete_flow = not has_active_machine + return show_complete_flow + + @pyqtSlot(result = bool) + def shouldShowWhatsNewDialog(self) -> bool: + has_active_machine = self._machine_manager.activeMachine is not None + has_app_just_upgraded = self.hasJustUpdatedFromOldVersion() + + print("!!!!!!!!!!!!! has_active_machine = ", has_active_machine) + + # Only show the what's new dialog if there's no machine and we have just upgraded + show_whatsnew_only = has_active_machine and has_app_just_upgraded + return show_whatsnew_only diff --git a/cura/UI/WelcomePagesModel.py b/cura/UI/WelcomePagesModel.py index be29ed5619..f75082e20d 100644 --- a/cura/UI/WelcomePagesModel.py +++ b/cura/UI/WelcomePagesModel.py @@ -59,10 +59,6 @@ class WelcomePagesModel(ListModel): # Store all the previous page indices so it can go back. self._previous_page_indices_stack = deque() # type: deque - # If the welcome flow should be shown. It can show the complete flow or just the changelog depending on the - # specific case. See initialize() for how this variable is set. - self._should_show_welcome_flow = False - allFinished = pyqtSignal() # emitted when all steps have been finished currentPageIndexChanged = pyqtSignal() @@ -178,12 +174,6 @@ class WelcomePagesModel(ListModel): self.currentPageIndexChanged.emit() - shouldShowWelcomeFlowChanged = pyqtSignal() - - @pyqtProperty(bool, notify = shouldShowWelcomeFlowChanged) - def shouldShowWelcomeFlow(self) -> bool: - return self._should_show_welcome_flow - # Gets the page index with the given page ID. If the page ID doesn't exist, returns None. def getPageIndexById(self, page_id: str) -> Optional[int]: page_idx = None @@ -199,33 +189,7 @@ class WelcomePagesModel(ListModel): return QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, os.path.join("WelcomePages", page_filename))) - # FIXME: HACKs for optimization that we don't update the model every time the active machine gets changed. - def _onActiveMachineChanged(self) -> None: - self._application.getMachineManager().globalContainerChanged.disconnect(self._onActiveMachineChanged) - self._initialize() - def initialize(self) -> None: - self._application.getMachineManager().globalContainerChanged.connect(self._onActiveMachineChanged) - self._initialize() - - def _initialize(self) -> None: - has_active_machine = self._application.getMachineManager().activeMachine is not None - has_app_just_upgraded = self._application.hasJustUpdatedFromOldVersion() - - # Only show the what's new dialog if there's no machine and we have just upgraded - show_complete_flow = not has_active_machine - show_whatsnew_only = has_active_machine and has_app_just_upgraded - - # FIXME: This is a hack. Because of the circular dependency between MachineManager, ExtruderManager, and - # possibly some others, setting the initial active machine is not done when the MachineManager gets initialized. - # So at this point, we don't know if there will be an active machine or not. It could be that the active machine - # files are corrupted so we cannot rely on Preferences either. This makes sure that once the active machine - # gets changed, this model updates the flags, so it can decide whether to show the welcome flow or not. - should_show_welcome_flow = show_complete_flow or show_whatsnew_only - if should_show_welcome_flow != self._should_show_welcome_flow: - self._should_show_welcome_flow = should_show_welcome_flow - self.shouldShowWelcomeFlowChanged.emit() - # All pages all_pages_list = [{"id": "welcome", "page_url": self._getBuiltinWelcomePagePath("WelcomeContent.qml"), @@ -257,11 +221,7 @@ class WelcomePagesModel(ListModel): }, ] - pages_to_show = all_pages_list - if show_whatsnew_only: - pages_to_show = list(filter(lambda x: x["id"] == "whats_new", all_pages_list)) - - self._pages = pages_to_show + self._pages = all_pages_list self.setItems(self._pages) # For convenience, inject the default "next" button text to each item if it's not present. diff --git a/cura/UI/WhatsNewPagesModel.py b/cura/UI/WhatsNewPagesModel.py new file mode 100644 index 0000000000..5b968ae574 --- /dev/null +++ b/cura/UI/WhatsNewPagesModel.py @@ -0,0 +1,22 @@ +# Copyright (c) 2019 Ultimaker B.V. +# Cura is released under the terms of the LGPLv3 or higher. + +from .WelcomePagesModel import WelcomePagesModel + + +# +# This Qt ListModel is more or less the same the WelcomePagesModel, except that this model is only for showing the +# "what's new" page. This is also used in the "Help" menu to show the changes log. +# +class WhatsNewPagesModel(WelcomePagesModel): + + def initialize(self) -> None: + self._pages = [] + self._pages.append({"id": "whats_new", + "page_url": self._getBuiltinWelcomePagePath("WhatsNewContent.qml"), + "next_page_button_text": self._catalog.i18nc("@action:button", "Close"), + }) + self.setItems(self._pages) + + +__all__ = ["WhatsNewPagesModel"] diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index 81c14aa01a..ed89eb553e 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -61,6 +61,7 @@ Item property alias documentation: documentationAction; property alias showTroubleshooting: showTroubleShootingAction property alias reportBug: reportBugAction; + property alias whatsNew: whatsNewAction property alias about: aboutAction; property alias toggleFullScreen: toggleFullScreenAction; @@ -229,6 +230,13 @@ Item onTriggered: CuraActions.openBugReportPage(); } + Action + { + id: whatsNewAction; + text: catalog.i18nc("@action:inmenu menubar:help", "What's New"); + iconName: "help-whats-new"; + } + Action { id: aboutAction; diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index bdd016d24c..08fbc95b0e 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -68,32 +68,54 @@ UM.MainWindow z: greyOutBackground.z + 1 } - Component.onCompleted: + Connections { - CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size")) - // Workaround silly issues with QML Action's shortcut property. - // - // Currently, there is no way to define shortcuts as "Application Shortcut". - // This means that all Actions are "Window Shortcuts". The code for this - // implements a rather naive check that just checks if any of the action's parents - // are a window. Since the "Actions" object is a singleton it has no parent by - // default. If we set its parent to something contained in this window, the - // shortcut will activate properly because one of its parents is a window. - // - // This has been fixed for QtQuick Controls 2 since the Shortcut item has a context property. - Cura.Actions.parent = backgroundItem - CuraApplication.purgeWindows() + target: CuraApplication + onInitializationFinished: + { + CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size")) + // Workaround silly issues with QML Action's shortcut property. + // + // Currently, there is no way to define shortcuts as "Application Shortcut". + // This means that all Actions are "Window Shortcuts". The code for this + // implements a rather naive check that just checks if any of the action's parents + // are a window. Since the "Actions" object is a singleton it has no parent by + // default. If we set its parent to something contained in this window, the + // shortcut will activate properly because one of its parents is a window. + // + // This has been fixed for QtQuick Controls 2 since the Shortcut item has a context property. + Cura.Actions.parent = backgroundItem + CuraApplication.purgeWindows() - if (CuraApplication.getWelcomePagesModel().shouldShowWelcomeFlow) - { - welcomeDialogItem.visible = true - } - else - { - welcomeDialogItem.visible = false + if (CuraApplication.shouldShowWelcomeDialog()) + { + welcomeDialogItem.visible = true + } + else + { + welcomeDialogItem.visible = false + } + + if (CuraApplication.shouldShowWhatsNewDialog()) + { + showWhatsNewDialogTimer.start() + } } } + // HACK: Use a timer here because if we call "Cura.Actions.whatsNew.trigger()" or "whatsNewDialog.show()" when + // the component gets completed or when the application finishes its initialization, the main window has not been + // fully initialized yet. If we should the dialog before the main window is fully initialized, you will see the + // dialog first but when the main windows is fully initialized, the dialog will disappear. Adding a timer here is + // to bypass this problem. + Timer + { + id: showWhatsNewDialogTimer + repeat: false + interval: 1000 + onTriggered: Cura.Actions.whatsNew.trigger() + } + Item { id: backgroundItem @@ -780,6 +802,20 @@ UM.MainWindow progressBarVisible: false } + Cura.WizardDialog + { + id: whatsNewDialog + title: catalog.i18nc("@title:window", "What's New") + model: CuraApplication.getWhatsNewPagesModel() + progressBarVisible: false + } + + Connections + { + target: Cura.Actions.whatsNew + onTriggered: whatsNewDialog.show() + } + Connections { target: Cura.Actions.addMachine diff --git a/resources/qml/MainWindow/ApplicationMenu.qml b/resources/qml/MainWindow/ApplicationMenu.qml index 2f18df8914..7f343eb8f4 100644 --- a/resources/qml/MainWindow/ApplicationMenu.qml +++ b/resources/qml/MainWindow/ApplicationMenu.qml @@ -101,6 +101,7 @@ Item MenuItem { action: Cura.Actions.documentation } MenuItem { action: Cura.Actions.reportBug } MenuSeparator { } + MenuItem { action: Cura.Actions.whatsNew } MenuItem { action: Cura.Actions.about } } } diff --git a/resources/qml/WelcomePages/WhatsNewContent.qml b/resources/qml/WelcomePages/WhatsNewContent.qml index 415acae05c..51a347779a 100644 --- a/resources/qml/WelcomePages/WhatsNewContent.qml +++ b/resources/qml/WelcomePages/WhatsNewContent.qml @@ -51,7 +51,7 @@ Item id: getStartedButton anchors.right: parent.right anchors.bottom: parent.bottom - text: catalog.i18nc("@button", "Next") + text: base.currentItem.next_page_button_text onClicked: base.showNextPage() } } From 3794c8f75e9dde99f3cf373a0ab1a95a4cdc786f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 12 Apr 2019 11:09:10 +0200 Subject: [PATCH 03/32] Remove ChangeLog plugin CURA-6436 CURA-6447 --- plugins/ChangeLogPlugin/ChangeLog.py | 65 --------------------------- plugins/ChangeLogPlugin/ChangeLog.qml | 43 ------------------ plugins/ChangeLogPlugin/__init__.py | 11 ----- plugins/ChangeLogPlugin/plugin.json | 8 ---- resources/bundled_packages/cura.json | 17 ------- 5 files changed, 144 deletions(-) delete mode 100644 plugins/ChangeLogPlugin/ChangeLog.py delete mode 100644 plugins/ChangeLogPlugin/ChangeLog.qml delete mode 100644 plugins/ChangeLogPlugin/__init__.py delete mode 100644 plugins/ChangeLogPlugin/plugin.json diff --git a/plugins/ChangeLogPlugin/ChangeLog.py b/plugins/ChangeLogPlugin/ChangeLog.py deleted file mode 100644 index 241d7a8953..0000000000 --- a/plugins/ChangeLogPlugin/ChangeLog.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) 2019 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -import os.path - -from PyQt5.QtCore import QObject - -from UM.i18n import i18nCatalog -from UM.Extension import Extension -from UM.Application import Application -from UM.PluginRegistry import PluginRegistry -from UM.Version import Version - -catalog = i18nCatalog("cura") - - -class ChangeLog(Extension, QObject): - def __init__(self, parent = None): - QObject.__init__(self, parent) - Extension.__init__(self) - self._changelog_window = None - self._changelog_context = None - version_string = Application.getInstance().getVersion() - if version_string is not "master": - self._current_app_version = Version(version_string) - else: - self._current_app_version = None - - Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated) - Application.getInstance().getPreferences().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium - self.setMenuName(catalog.i18nc("@item:inmenu", "Changelog")) - self.addMenuItem(catalog.i18nc("@item:inmenu", "Show Changelog"), self.showChangelog) - - def _onEngineCreated(self): - if not self._current_app_version: - return #We're on dev branch. - - if Application.getInstance().getPreferences().getValue("general/latest_version_changelog_shown") == "master": - latest_version_shown = Version("0.0.0") - else: - latest_version_shown = Version(Application.getInstance().getPreferences().getValue("general/latest_version_changelog_shown")) - - Application.getInstance().getPreferences().setValue("general/latest_version_changelog_shown", Application.getInstance().getVersion()) - - # Do not show the changelog when there is no global container stack - # This implies we are running Cura for the first time. - if not Application.getInstance().getGlobalContainerStack(): - return - - if self._current_app_version > latest_version_shown: - self.showChangelog() - - def showChangelog(self): - if not self._changelog_window: - self.createChangelogWindow() - - self._changelog_window.show() - - def hideChangelog(self): - if self._changelog_window: - self._changelog_window.hide() - - def createChangelogWindow(self): - path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml") - self._changelog_window = Application.getInstance().createQmlComponent(path, {"manager": self}) diff --git a/plugins/ChangeLogPlugin/ChangeLog.qml b/plugins/ChangeLogPlugin/ChangeLog.qml deleted file mode 100644 index 7089a56caf..0000000000 --- a/plugins/ChangeLogPlugin/ChangeLog.qml +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2015 Ultimaker B.V. -// Cura is released under the terms of the LGPLv3 or higher. - -import QtQuick 2.1 -import QtQuick.Controls 1.3 -import QtQuick.Layouts 1.1 -import QtQuick.Window 2.1 - -import UM 1.3 as UM -import Cura 1.0 as Cura - - -UM.Dialog -{ - id: base - minimumWidth: (UM.Theme.getSize("modal_window_minimum").width * 0.75) | 0 - minimumHeight: (UM.Theme.getSize("modal_window_minimum").height * 0.75) | 0 - width: minimumWidth - height: minimumHeight - title: catalog.i18nc("@label", "Changelog") - - TextArea - { - anchors.fill: parent - text: CuraApplication.getTextManager().getChangeLogText() - readOnly: true; - textFormat: TextEdit.RichText - } - - rightButtons: [ - Button - { - UM.I18nCatalog - { - id: catalog - name: "cura" - } - - text: catalog.i18nc("@action:button", "Close") - onClicked: base.hide() - } - ] -} diff --git a/plugins/ChangeLogPlugin/__init__.py b/plugins/ChangeLogPlugin/__init__.py deleted file mode 100644 index a5452b60c8..0000000000 --- a/plugins/ChangeLogPlugin/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2015 Ultimaker B.V. -# Cura is released under the terms of the LGPLv3 or higher. - -from . import ChangeLog - - -def getMetaData(): - return {} - -def register(app): - return {"extension": ChangeLog.ChangeLog()} diff --git a/plugins/ChangeLogPlugin/plugin.json b/plugins/ChangeLogPlugin/plugin.json deleted file mode 100644 index 92041d1543..0000000000 --- a/plugins/ChangeLogPlugin/plugin.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "Changelog", - "author": "Ultimaker B.V.", - "version": "1.0.1", - "description": "Shows changes since latest checked version.", - "api": "6.0", - "i18n-catalog": "cura" -} diff --git a/resources/bundled_packages/cura.json b/resources/bundled_packages/cura.json index 3dcc02a503..cf8ecfb010 100644 --- a/resources/bundled_packages/cura.json +++ b/resources/bundled_packages/cura.json @@ -33,23 +33,6 @@ } } }, - "ChangeLogPlugin": { - "package_info": { - "package_id": "ChangeLogPlugin", - "package_type": "plugin", - "display_name": "Change Log", - "description": "Shows changes since latest checked version.", - "package_version": "1.0.1", - "sdk_version": "6.0.0", - "website": "https://ultimaker.com", - "author": { - "author_id": "UltimakerPackages", - "display_name": "Ultimaker B.V.", - "email": "plugins@ultimaker.com", - "website": "https://ultimaker.com" - } - } - }, "CuraDrive": { "package_info": { "package_id": "CuraDrive", From f30348559554066b3bfa48a6c3c0cfc8338c19eb Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Fri, 12 Apr 2019 11:12:17 +0200 Subject: [PATCH 04/32] Remove changelog preferences entry in version upgrade CURA-6436 CURA-6447 --- .../VersionUpgrade40to41/VersionUpgrade40to41.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py index d80e0007aa..ad22bf2ee9 100644 --- a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py +++ b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py @@ -62,6 +62,11 @@ class VersionUpgrade40to41(VersionUpgrade): parser["general"]["version"] = "6" if "metadata" not in parser: parser["metadata"] = {} + + # Remove changelog plugin + if "latest_version_changelog_shown" in parser["general"]: + del parser["general"]["latest_version_changelog_shown"] + parser["metadata"]["setting_version"] = "7" result = io.StringIO() From d3310be8462e7c2b2107324e565f3de5dacff0f2 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Fri, 12 Apr 2019 16:19:54 +0200 Subject: [PATCH 05/32] Deprecate some MachineManagaer functions. Note: You need the 'handle_log_once' branch in Uranium to prevent spamming the logs! part of CURA-6457 --- cura/Settings/MachineManager.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7d0e7506b8..f4acbf2748 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -9,6 +9,7 @@ from typing import Any, List, Dict, TYPE_CHECKING, Optional, cast from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, QTimer from UM.ConfigurationErrorMessage import ConfigurationErrorMessage +from UM.Decorators import deprecated from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.Interfaces import ContainerInterface @@ -498,30 +499,35 @@ class MachineManager(QObject): return bool(self._stacks_have_errors) @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use Cura.MachineManager.activeMachine.definition.getName instead", "4.1") def activeMachineDefinitionName(self) -> str: if self._global_container_stack: return self._global_container_stack.definition.getName() return "" @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use Cura.MachineManager.activeMachine.getName instead", "4.1") def activeMachineName(self) -> str: if self._global_container_stack: return self._global_container_stack.getMetaDataEntry("group_name", self._global_container_stack.getName()) return "" @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use Cura.MachineManager.activeMachine.getId instead", "4.1") def activeMachineId(self) -> str: if self._global_container_stack: return self._global_container_stack.getId() return "" @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use Cura.MachineManager.activeMachine.firmwareVersion instead", "4.1") def activeMachineFirmwareVersion(self) -> str: if not self._printer_output_devices: return "" return self._printer_output_devices[0].firmwareVersion @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use Cura.MachineManager.activeMachine.address instead", "4.1") def activeMachineAddress(self) -> str: if not self._printer_output_devices: return "" @@ -543,21 +549,25 @@ class MachineManager(QObject): return False @pyqtProperty("QVariantList", notify=globalContainerChanged) + @deprecated("use Cura.MachineManager.activeMachine.configuredConnectionTypes instead", "4.1") def activeMachineConfiguredConnectionTypes(self): if self._global_container_stack: return self._global_container_stack.configuredConnectionTypes return [] @pyqtProperty(bool, notify = printerConnectedStatusChanged) + @deprecated("use len(Cura.MachineManager.activeMachine.printers) instead", "4.1") def activeMachineIsGroup(self) -> bool: return bool(self._printer_output_devices) and len(self._printer_output_devices[0].printers) > 1 @pyqtProperty(bool, notify = printerConnectedStatusChanged) + @deprecated("use Cura.MachineManager.activeMachine.connectionType instead", "4.1") def activeMachineHasNetworkConnection(self) -> bool: # A network connection is only available if any output device is actually a network connected device. return any(d.connectionType == ConnectionType.NetworkConnection for d in self._printer_output_devices) @pyqtProperty(bool, notify = printerConnectedStatusChanged) + @deprecated("use Cura.MachineManager.activeMachine.connectionType instead", "4.1") def activeMachineHasCloudConnection(self) -> bool: # A cloud connection is only available if any output device actually is a cloud connected device. return any(d.connectionType == ConnectionType.CloudConnection for d in self._printer_output_devices) @@ -715,6 +725,7 @@ class MachineManager(QObject): extruder_stack.userChanges.setProperty(key, "value", new_value) @pyqtProperty(str, notify = activeVariantChanged) + @deprecated("use XXY instead", "4.1") def activeVariantName(self) -> str: if self._active_container_stack: variant = self._active_container_stack.variant @@ -733,6 +744,7 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify = activeVariantChanged) + @deprecated("use XXY instead", "4.1") def activeVariantBuildplateName(self) -> str: if self._global_container_stack: variant = self._global_container_stack.variant @@ -751,6 +763,7 @@ class MachineManager(QObject): ## Get the Definition ID to use to select quality profiles for the currently active machine # \returns DefinitionID (string) if found, empty string otherwise @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use XXY instead", "4.1") def activeQualityDefinitionId(self) -> str: if self._global_container_stack: return getMachineDefinitionIDForQualitySearch(self._global_container_stack.definition) From 932fb75145eeebbdea1e3389ad9f2cbb8355c819 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 12 Apr 2019 18:40:22 +0200 Subject: [PATCH 06/32] Add maximum deviation setting This setting allows tweaking the deviation from the norm separately from the length of line segments. Implements CURA-6458. --- resources/definitions/fdmprinter.def.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8ce0246a93..11da222833 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5875,6 +5875,19 @@ "settable_per_mesh": false, "settable_per_extruder": true }, + "meshfix_maximum_deviation": + { + "label": "Maximum Deviation", + "description": "The maximum deviation allowed when reducing the resolution for the Maximum Resolution setting. If you increase this, the print will be less accurate, but the g-code will be smaller.", + "type": "float", + "unit": "mm", + "default_value": 0.005, + "value": "meshfix_maximum_resolution / 2", + "minimum_value": "0.001", + "minimum_value_warning": "0.003", + "maximum_value_warning": "0.1", + "settable_per_mesh": true + }, "support_skip_some_zags": { "label": "Break Up Support In Chunks", From e35c0cc363951e4eff88037d92df78df1aa868c5 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 15 Apr 2019 08:14:54 +0200 Subject: [PATCH 07/32] Fix incorrect import in UFPReader --- plugins/UFPReader/UFPReader.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/UFPReader/UFPReader.py b/plugins/UFPReader/UFPReader.py index cec70ef655..e2073a6496 100644 --- a/plugins/UFPReader/UFPReader.py +++ b/plugins/UFPReader/UFPReader.py @@ -1,15 +1,13 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import cast - from Charon.VirtualFile import VirtualFile from UM.Mesh.MeshReader import MeshReader from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase from UM.PluginRegistry import PluginRegistry + from cura.Scene.CuraSceneNode import CuraSceneNode -from plugins.GCodeReader.GCodeReader import GCodeReader class UFPReader(MeshReader): @@ -36,6 +34,6 @@ class UFPReader(MeshReader): gcode_stream = gcode_data["/3D/model.gcode"].decode("utf-8") # Open the GCodeReader to parse the data - gcode_reader = cast(GCodeReader, PluginRegistry.getInstance().getPluginObject("GCodeReader")) + gcode_reader = PluginRegistry.getInstance().getPluginObject("GCodeReader") # type: ignore gcode_reader.preReadFromStream(gcode_stream) return gcode_reader.readFromStream(gcode_stream) From 77ffc16c3318f8e8b256d3c5158d3cfdad581a58 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 15 Apr 2019 08:26:54 +0200 Subject: [PATCH 08/32] Move type checking imports into type checking closure --- plugins/UFPReader/UFPReader.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/UFPReader/UFPReader.py b/plugins/UFPReader/UFPReader.py index e2073a6496..275726b25b 100644 --- a/plugins/UFPReader/UFPReader.py +++ b/plugins/UFPReader/UFPReader.py @@ -1,13 +1,16 @@ # Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. +from typing import TYPE_CHECKING + from Charon.VirtualFile import VirtualFile from UM.Mesh.MeshReader import MeshReader from UM.MimeTypeDatabase import MimeType, MimeTypeDatabase from UM.PluginRegistry import PluginRegistry -from cura.Scene.CuraSceneNode import CuraSceneNode +if TYPE_CHECKING: + from cura.Scene.CuraSceneNode import CuraSceneNode class UFPReader(MeshReader): @@ -24,7 +27,7 @@ class UFPReader(MeshReader): ) self._supported_extensions = [".ufp"] - def _read(self, file_name: str) -> CuraSceneNode: + def _read(self, file_name: str) -> "CuraSceneNode": # Open the file archive = VirtualFile() archive.open(file_name) From 5f7f7f944f34055d976183348caba85ca2e2a836 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 15 Apr 2019 09:39:05 +0200 Subject: [PATCH 09/32] Remove use XYZ instead --- cura/Settings/MachineManager.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index f4acbf2748..21826745e7 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -725,7 +725,7 @@ class MachineManager(QObject): extruder_stack.userChanges.setProperty(key, "value", new_value) @pyqtProperty(str, notify = activeVariantChanged) - @deprecated("use XXY instead", "4.1") + @deprecated("use Cura.activeStack.variant.name instead", "4.1") def activeVariantName(self) -> str: if self._active_container_stack: variant = self._active_container_stack.variant @@ -744,7 +744,7 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify = activeVariantChanged) - @deprecated("use XXY instead", "4.1") + @deprecated("use Cura.activeMachine.variant.name instead", "4.1") def activeVariantBuildplateName(self) -> str: if self._global_container_stack: variant = self._global_container_stack.variant @@ -763,7 +763,6 @@ class MachineManager(QObject): ## Get the Definition ID to use to select quality profiles for the currently active machine # \returns DefinitionID (string) if found, empty string otherwise @pyqtProperty(str, notify = globalContainerChanged) - @deprecated("use XXY instead", "4.1") def activeQualityDefinitionId(self) -> str: if self._global_container_stack: return getMachineDefinitionIDForQualitySearch(self._global_container_stack.definition) From ba37812793bb084ee70c9c36160effee97d3daf8 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 15 Apr 2019 09:47:09 +0200 Subject: [PATCH 10/32] Correct some deprecations and remove duplicated code --- cura/Settings/GlobalStack.py | 3 +++ cura/Settings/MachineManager.py | 19 ++++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index df881b4714..df43b1c1f7 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -258,6 +258,9 @@ class GlobalStack(CuraContainerStack): def getHasVariants(self) -> bool: return parseBool(self.getMetaDataEntry("has_variants", False)) + def getHasVariantsBuildPlates(self) -> bool: + return parseBool(self._global_container_stack.getMetaDataEntry("has_variant_buildplates", False)) + def getHasMachineQuality(self) -> bool: return parseBool(self.getMetaDataEntry("has_machine_quality", False)) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 21826745e7..5832dd2fe6 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -499,35 +499,33 @@ class MachineManager(QObject): return bool(self._stacks_have_errors) @pyqtProperty(str, notify = globalContainerChanged) - @deprecated("use Cura.MachineManager.activeMachine.definition.getName instead", "4.1") + @deprecated("use Cura.MachineManager.activeMachine.definition.name instead", "4.1") def activeMachineDefinitionName(self) -> str: if self._global_container_stack: return self._global_container_stack.definition.getName() return "" @pyqtProperty(str, notify = globalContainerChanged) - @deprecated("use Cura.MachineManager.activeMachine.getName instead", "4.1") + @deprecated("use Cura.MachineManager.activeMachine.name instead", "4.1") def activeMachineName(self) -> str: if self._global_container_stack: return self._global_container_stack.getMetaDataEntry("group_name", self._global_container_stack.getName()) return "" @pyqtProperty(str, notify = globalContainerChanged) - @deprecated("use Cura.MachineManager.activeMachine.getId instead", "4.1") + @deprecated("use Cura.MachineManager.activeMachine.id instead", "4.1") def activeMachineId(self) -> str: if self._global_container_stack: return self._global_container_stack.getId() return "" @pyqtProperty(str, notify = globalContainerChanged) - @deprecated("use Cura.MachineManager.activeMachine.firmwareVersion instead", "4.1") def activeMachineFirmwareVersion(self) -> str: if not self._printer_output_devices: return "" return self._printer_output_devices[0].firmwareVersion @pyqtProperty(str, notify = globalContainerChanged) - @deprecated("use Cura.MachineManager.activeMachine.address instead", "4.1") def activeMachineAddress(self) -> str: if not self._printer_output_devices: return "" @@ -556,18 +554,15 @@ class MachineManager(QObject): return [] @pyqtProperty(bool, notify = printerConnectedStatusChanged) - @deprecated("use len(Cura.MachineManager.activeMachine.printers) instead", "4.1") def activeMachineIsGroup(self) -> bool: return bool(self._printer_output_devices) and len(self._printer_output_devices[0].printers) > 1 @pyqtProperty(bool, notify = printerConnectedStatusChanged) - @deprecated("use Cura.MachineManager.activeMachine.connectionType instead", "4.1") def activeMachineHasNetworkConnection(self) -> bool: # A network connection is only available if any output device is actually a network connected device. return any(d.connectionType == ConnectionType.NetworkConnection for d in self._printer_output_devices) @pyqtProperty(bool, notify = printerConnectedStatusChanged) - @deprecated("use Cura.MachineManager.activeMachine.connectionType instead", "4.1") def activeMachineHasCloudConnection(self) -> bool: # A cloud connection is only available if any output device actually is a cloud connected device. return any(d.connectionType == ConnectionType.CloudConnection for d in self._printer_output_devices) @@ -735,6 +730,7 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify = activeVariantChanged) + @deprecated("use Cura.activeStack.variant.id instead", "4.1") def activeVariantId(self) -> str: if self._active_container_stack: variant = self._active_container_stack.variant @@ -754,6 +750,7 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify = globalContainerChanged) + @deprecated("use Cura.activeMachine.definition.id instead", "4.1") def activeDefinitionId(self) -> str: if self._global_container_stack: return self._global_container_stack.definition.id @@ -818,19 +815,19 @@ class MachineManager(QObject): @pyqtProperty(bool, notify = globalContainerChanged) def hasMaterials(self) -> bool: if self._global_container_stack: - return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_materials", False)) + return self._global_container_stack.getHasMaterials() return False @pyqtProperty(bool, notify = globalContainerChanged) def hasVariants(self) -> bool: if self._global_container_stack: - return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variants", False)) + return self._global_container_stack.getHasVariants() return False @pyqtProperty(bool, notify = globalContainerChanged) def hasVariantBuildplates(self) -> bool: if self._global_container_stack: - return Util.parseBool(self._global_container_stack.getMetaDataEntry("has_variant_buildplates", False)) + return self._global_container_stack.getHasVariantsBuildPlates() return False ## The selected buildplate is compatible if it is compatible with all the materials in all the extruders From 2f6a2b9ee5646c319b04a1846655d23ace910b47 Mon Sep 17 00:00:00 2001 From: Ian Paschal Date: Mon, 15 Apr 2019 10:12:48 +0200 Subject: [PATCH 11/32] Make pop up more visible Contributes to CL-1298 --- resources/themes/cura-light/theme.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/themes/cura-light/theme.json b/resources/themes/cura-light/theme.json index 4b2f92e6e5..f1e35f189f 100644 --- a/resources/themes/cura-light/theme.json +++ b/resources/themes/cura-light/theme.json @@ -433,7 +433,7 @@ "monitor_skeleton_loading": [238, 238, 238, 255], "monitor_placeholder_image": [230, 230, 230, 255], "monitor_image_overlay": [0, 0, 0, 255], - "monitor_shadow": [220, 220, 220, 255], + "monitor_shadow": [200, 200, 200, 255], "monitor_carousel_dot": [216, 216, 216, 255], "monitor_carousel_dot_current": [119, 119, 119, 255] From 0fe65558810b1f9d16448dc8561ac9b63cdd8ced Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 15 Apr 2019 13:09:44 +0200 Subject: [PATCH 12/32] Remove debug code CURA-6447 --- cura/CuraApplication.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index d5ab2bd706..60722c4767 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1786,8 +1786,6 @@ class CuraApplication(QtApplication): has_active_machine = self._machine_manager.activeMachine is not None has_app_just_upgraded = self.hasJustUpdatedFromOldVersion() - print("!!!!!!!!!!!!! has_active_machine = ", has_active_machine) - # Only show the what's new dialog if there's no machine and we have just upgraded show_whatsnew_only = has_active_machine and has_app_just_upgraded return show_whatsnew_only From fdc629de32c46f5d3bd103aaa4ac99b93e4b114f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 15 Apr 2019 13:17:31 +0200 Subject: [PATCH 13/32] Make error message log which layer could not be found --- plugins/PostProcessingPlugin/scripts/FilamentChange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/PostProcessingPlugin/scripts/FilamentChange.py b/plugins/PostProcessingPlugin/scripts/FilamentChange.py index febb93be4c..2acb01d5cc 100644 --- a/plugins/PostProcessingPlugin/scripts/FilamentChange.py +++ b/plugins/PostProcessingPlugin/scripts/FilamentChange.py @@ -97,7 +97,7 @@ class FilamentChange(Script): if layer_num <= len(data): index, layer_data = self._searchLayerData(data, layer_num - 1) if layer_data is None: - Logger.log("e", "Could not found the layer") + Logger.log("e", "Could not find the layer {layer_num}".format(layer_num = layer_num)) continue lines = layer_data.split("\n") lines.insert(2, color_change) From 8e579d2d68873f368033d176638fceb81617f2f3 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Mon, 15 Apr 2019 13:24:39 +0200 Subject: [PATCH 14/32] Update default extruder when applying remote config CURA-6452 --- cura/Settings/MachineManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 7d0e7506b8..c39572f6f6 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1428,6 +1428,7 @@ class MachineManager(QObject): self._global_container_stack.extruders[position].setEnabled(True) self.updateMaterialWithVariant(position) + self.updateDefaultExtruder() self.updateNumberExtrudersEnabled() if configuration.buildplateConfiguration is not None: From d5fa0b395e5185968c70147cf24cb421369fa2f0 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 15 Apr 2019 14:08:18 +0200 Subject: [PATCH 15/32] Hide travel jerk settings for RepRap flavour The firmware doesn't support it there. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8ce0246a93..8a223fcaef 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3312,7 +3312,7 @@ "minimum_value": "0", "maximum_value_warning": "50", "value": "jerk_print if magic_spiralize else 30", - "enabled": "resolveOrValue('jerk_enabled')", + "enabled": "resolveOrValue('jerk_enabled') and machine_gcode_flavor != \"RepRap (RepRap)\"", "settable_per_mesh": false }, "jerk_layer_0": @@ -3352,7 +3352,7 @@ "value": "jerk_layer_0 * jerk_travel / jerk_print", "minimum_value": "0", "maximum_value_warning": "50", - "enabled": "resolveOrValue('jerk_enabled')", + "enabled": "resolveOrValue('jerk_enabled') and machine_gcode_flavor != \"RepRap (RepRap)\"", "settable_per_extruder": true, "settable_per_mesh": false } From 42b1a0e028b852f2c257df910131f0ca19f7e5aa Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 15 Apr 2019 17:36:55 +0200 Subject: [PATCH 16/32] Refactor some small bits of the setting override decorator There was code duplication and a number of functions that should be private contributes to #5603 --- cura/Settings/SettingOverrideDecorator.py | 12 ++++++------ plugins/CuraEngineBackend/StartSliceJob.py | 5 +---- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index 429e6d16ec..f82d718398 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -73,8 +73,8 @@ class SettingOverrideDecorator(SceneNodeDecorator): # use value from the stack because there can be a delay in signal triggering and "_is_non_printing_mesh" # has not been updated yet. - deep_copy._is_non_printing_mesh = self.evaluateIsNonPrintingMesh() - deep_copy._is_non_thumbnail_visible_mesh = self.evaluateIsNonThumbnailVisibleMesh() + deep_copy._is_non_printing_mesh = self._evaluateIsNonPrintingMesh() + deep_copy._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh() return deep_copy @@ -102,20 +102,20 @@ class SettingOverrideDecorator(SceneNodeDecorator): def isNonPrintingMesh(self): return self._is_non_printing_mesh - def evaluateIsNonPrintingMesh(self): + def _evaluateIsNonPrintingMesh(self): return any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_printing_mesh_settings) def isNonThumbnailVisibleMesh(self): return self._is_non_thumbnail_visible_mesh - def evaluateIsNonThumbnailVisibleMesh(self): + def _evaluateIsNonThumbnailVisibleMesh(self): return any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_thumbnail_visible_settings) def _onSettingChanged(self, instance, property_name): # Reminder: 'property' is a built-in function if property_name == "value": # Trigger slice/need slicing if the value has changed. - self._is_non_printing_mesh = self.evaluateIsNonPrintingMesh() - self._is_non_thumbnail_visible_mesh = self.evaluateIsNonThumbnailVisibleMesh() + self._is_non_printing_mesh = self._evaluateIsNonPrintingMesh() + self._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh() Application.getInstance().getBackend().needsSlicing() Application.getInstance().getBackend().tickle() diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index ef97364118..d9e1a7806d 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -196,10 +196,7 @@ class StartSliceJob(Job): has_printing_mesh = False for node in DepthFirstIterator(self._scene.getRoot()): #type: ignore #Ignore type error because iter() should get called automatically by Python syntax. if node.callDecoration("isSliceable") and node.getMeshData() and node.getMeshData().getVertices() is not None: - per_object_stack = node.callDecoration("getStack") - is_non_printing_mesh = False - if per_object_stack: - is_non_printing_mesh = any(per_object_stack.getProperty(key, "value") for key in NON_PRINTING_MESH_SETTINGS) + is_non_printing_mesh = bool(node.callDecoration("isNonPrintingMesh")) # Find a reason not to add the node if node.callDecoration("getBuildPlateNumber") != self._build_plate_number: From e8d2e070d83194aae1490dee07ed73b6d34fecb8 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 15 Apr 2019 17:46:54 +0200 Subject: [PATCH 17/32] Dont calculate bounding box for non printing meshes Fixes #5603 --- cura/Settings/SettingOverrideDecorator.py | 3 ++- plugins/SliceInfoPlugin/SliceInfo.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index f82d718398..c2097cf601 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -116,7 +116,8 @@ class SettingOverrideDecorator(SceneNodeDecorator): # Trigger slice/need slicing if the value has changed. self._is_non_printing_mesh = self._evaluateIsNonPrintingMesh() self._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh() - + # Only calculate the bounding box of the mesh if it's an actual mesh (and not a helper) + self._node.setCalculateBoundingBox(not self._is_non_printing_mesh) Application.getInstance().getBackend().needsSlicing() Application.getInstance().getBackend().tickle() diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 3763db5534..fecf3d16bb 100755 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -181,6 +181,8 @@ class SliceInfo(QObject, Extension): model = dict() model["hash"] = node.getMeshData().getHash() bounding_box = node.getBoundingBox() + if not bounding_box: + continue model["bounding_box"] = {"minimum": {"x": bounding_box.minimum.x, "y": bounding_box.minimum.y, "z": bounding_box.minimum.z}, From abb13e89920e72c53fdba7b56377a5a8285604a1 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 15 Apr 2019 17:52:13 +0200 Subject: [PATCH 18/32] Prevend unneeded tickles of the backend for setting override decorators --- cura/Settings/SettingOverrideDecorator.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index c2097cf601..d9b12720ac 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -114,12 +114,19 @@ class SettingOverrideDecorator(SceneNodeDecorator): def _onSettingChanged(self, instance, property_name): # Reminder: 'property' is a built-in function if property_name == "value": # Trigger slice/need slicing if the value has changed. - self._is_non_printing_mesh = self._evaluateIsNonPrintingMesh() - self._is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh() - # Only calculate the bounding box of the mesh if it's an actual mesh (and not a helper) - self._node.setCalculateBoundingBox(not self._is_non_printing_mesh) - Application.getInstance().getBackend().needsSlicing() - Application.getInstance().getBackend().tickle() + new_is_non_printing_mesh = self._evaluateIsNonPrintingMesh() + new_is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh() + changed = False + if self._is_non_printing_mesh != new_is_non_printing_mesh: + self._is_non_printing_mesh = new_is_non_printing_mesh + self._node.setCalculateBoundingBox(not self._is_non_printing_mesh) + changed = True + if self._is_non_thumbnail_visible_mesh != new_is_non_thumbnail_visible_mesh: + changed = True + + if changed: + Application.getInstance().getBackend().needsSlicing() + Application.getInstance().getBackend().tickle() ## Makes sure that the stack upon which the container stack is placed is # kept up to date. From 8267ef670a58becc5f21f2e9fba6c9520e81998a Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 15 Apr 2019 17:59:27 +0200 Subject: [PATCH 19/32] Greatly decrease amount of tickles to the backend for settingOverrideDecorator --- cura/Settings/SettingOverrideDecorator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index d9b12720ac..d230953f9c 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -111,8 +111,9 @@ class SettingOverrideDecorator(SceneNodeDecorator): def _evaluateIsNonThumbnailVisibleMesh(self): return any(bool(self._stack.getProperty(setting, "value")) for setting in self._non_thumbnail_visible_settings) - def _onSettingChanged(self, instance, property_name): # Reminder: 'property' is a built-in function - if property_name == "value": + def _onSettingChanged(self, setting_key, property_name): # Reminder: 'property' is a built-in function + # We're only interested in a few settings and only if it's value changed. + if property_name == "value" and (setting_key in self._non_printing_mesh_settings or setting_key in self._non_thumbnail_visible_settings): # Trigger slice/need slicing if the value has changed. new_is_non_printing_mesh = self._evaluateIsNonPrintingMesh() new_is_non_thumbnail_visible_mesh = self._evaluateIsNonThumbnailVisibleMesh() From cea742218bb5def49c510266ad433a6e67c31ae3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 09:42:32 +0200 Subject: [PATCH 20/32] Revert "Hide travel jerk settings for RepRap flavour" This reverts commit d5fa0b395e5185968c70147cf24cb421369fa2f0. It was made based on bad information; travel moves do properly use jerk in RepRap. --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8a223fcaef..8ce0246a93 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -3312,7 +3312,7 @@ "minimum_value": "0", "maximum_value_warning": "50", "value": "jerk_print if magic_spiralize else 30", - "enabled": "resolveOrValue('jerk_enabled') and machine_gcode_flavor != \"RepRap (RepRap)\"", + "enabled": "resolveOrValue('jerk_enabled')", "settable_per_mesh": false }, "jerk_layer_0": @@ -3352,7 +3352,7 @@ "value": "jerk_layer_0 * jerk_travel / jerk_print", "minimum_value": "0", "maximum_value_warning": "50", - "enabled": "resolveOrValue('jerk_enabled') and machine_gcode_flavor != \"RepRap (RepRap)\"", + "enabled": "resolveOrValue('jerk_enabled')", "settable_per_extruder": true, "settable_per_mesh": false } From 7b62eb9560b20f85052f3285ed810ecb22c0b67b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 09:53:53 +0200 Subject: [PATCH 21/32] Make minimum wall flow also settable per extruder It was settable per mesh but not per extruder, but we want it to be settable per extruder as well, causing all meshes printed with that extruder to use that setting value. That's how most of these settings work (like Outer Wall Speed and such). There are some exceptions to this where a setting only makes sense if applied in per-object settings, such as Infill Mesh or support blockers, but this is not such a setting. Fixes #5622. --- resources/definitions/fdmprinter.def.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 8ce0246a93..7909281c10 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -1316,8 +1316,7 @@ "default_value": 0, "type": "float", "enabled": "travel_compensate_overlapping_walls_0_enabled or travel_compensate_overlapping_walls_x_enabled", - "settable_per_mesh": true, - "settable_per_extruder": false + "settable_per_mesh": true }, "wall_min_flow_retract": { @@ -1326,8 +1325,7 @@ "type": "bool", "default_value": false, "enabled": "(travel_compensate_overlapping_walls_0_enabled or travel_compensate_overlapping_walls_x_enabled) and wall_min_flow > 0", - "settable_per_mesh": true, - "settable_per_extruder": false + "settable_per_mesh": true }, "fill_perimeter_gaps": { From c2a00d6b53923494196b4fd032f753e2083484fd Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Tue, 16 Apr 2019 10:53:06 +0200 Subject: [PATCH 22/32] Fix copy paste error Simple fix that caused crash for getHasVariantBuildplates --- cura/Settings/GlobalStack.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/Settings/GlobalStack.py b/cura/Settings/GlobalStack.py index df43b1c1f7..3ec73972dd 100755 --- a/cura/Settings/GlobalStack.py +++ b/cura/Settings/GlobalStack.py @@ -259,7 +259,7 @@ class GlobalStack(CuraContainerStack): return parseBool(self.getMetaDataEntry("has_variants", False)) def getHasVariantsBuildPlates(self) -> bool: - return parseBool(self._global_container_stack.getMetaDataEntry("has_variant_buildplates", False)) + return parseBool(self.getMetaDataEntry("has_variant_buildplates", False)) def getHasMachineQuality(self) -> bool: return parseBool(self.getMetaDataEntry("has_machine_quality", False)) From 60777b72fcd3c7dea7511bd7c24da194abfd5478 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 11:27:29 +0200 Subject: [PATCH 23/32] Increase defaults for Maximum Resolution significantly We want to limit it mostly to the Maximum Deviation now. So also don't increase the Maximum Deviation along this time. Contributes to issue CURA-6458. --- resources/definitions/fdmprinter.def.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 11da222833..15e3209e49 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5855,7 +5855,7 @@ "description": "The minimum size of a line segment after slicing. If you increase this, the mesh will have a lower resolution. This may allow the printer to keep up with the speed it has to process g-code and will increase slice speed by removing details of the mesh that it can't process anyway.", "type": "float", "unit": "mm", - "default_value": 0.01, + "default_value": 0.25, "minimum_value": "0.001", "minimum_value_warning": "0.005", "maximum_value_warning": "0.1", @@ -5867,7 +5867,7 @@ "description": "The minimum size of a travel line segment after slicing. If you increase this, the travel moves will have less smooth corners. This may allow the printer to keep up with the speed it has to process g-code, but it may cause model avoidance to become less accurate.", "type": "float", "unit": "mm", - "default_value": 0.02, + "default_value": 0.5, "value": "meshfix_maximum_resolution * speed_travel / speed_print", "minimum_value": "0.001", "minimum_value_warning": "0.005", @@ -5882,7 +5882,6 @@ "type": "float", "unit": "mm", "default_value": 0.005, - "value": "meshfix_maximum_resolution / 2", "minimum_value": "0.001", "minimum_value_warning": "0.003", "maximum_value_warning": "0.1", From 6325a5f1c24ad218beccfbcf2ee925f496172327 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 11:36:07 +0200 Subject: [PATCH 24/32] Change setting value defaults for maximum resolution to use deviation All profiles that use maximum resolution should use maximum deviation instead, and halve it. Contributes to issue CURA-6458. --- .../VersionUpgrade40to41/VersionUpgrade40to41.py | 11 ++++++++++- resources/definitions/peopoly_moai.def.json | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py index d80e0007aa..f79ec66e5a 100644 --- a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py +++ b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py @@ -1,4 +1,4 @@ -# Copyright (c) 2018 Ultimaker B.V. +# Copyright (c) 2019 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import configparser @@ -49,6 +49,15 @@ class VersionUpgrade40to41(VersionUpgrade): parser["general"]["version"] = "4" parser["metadata"]["setting_version"] = "7" + # Limit Maximum Deviation instead of Maximum Resolution. This should have approximately the same effect as before the algorithm change, only more consistent. + if "meshfix_maximum_resolution" in parser["values"]: + resolution = parser["values"]["meshfix_maximum_resolution"] + if resolution.startswith("="): + resolution = resolution[1:] + resolution = "=(" + resolution + ") / 2" + parser["values"]["meshfix_maximum_deviation"] = resolution + del parser["values"]["meshfix_maximum_resolution"] + result = io.StringIO() parser.write(result) return [filename], [result.getvalue()] diff --git a/resources/definitions/peopoly_moai.def.json b/resources/definitions/peopoly_moai.def.json index a578cc4240..177a6a801e 100644 --- a/resources/definitions/peopoly_moai.def.json +++ b/resources/definitions/peopoly_moai.def.json @@ -173,8 +173,8 @@ "minimum_polygon_circumference": { "value": "0.1" }, - "meshfix_maximum_resolution": { - "value": "0.005" + "meshfix_maximum_deviation": { + "value": "0.003" }, "skin_outline_count": { "value": 0 From 3b184a5a9a05969eb8368aa498ddbb8d9c4c2c01 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 11:36:59 +0200 Subject: [PATCH 25/32] Add maximum deviation to expert settings Contributes to issue CURA-6458. --- resources/setting_visibility/expert.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/setting_visibility/expert.cfg b/resources/setting_visibility/expert.cfg index 7754555ba7..0765c51749 100644 --- a/resources/setting_visibility/expert.cfg +++ b/resources/setting_visibility/expert.cfg @@ -347,6 +347,7 @@ infill_enable_travel_optimization material_flow_dependent_temperature material_flow_temp_graph meshfix_maximum_resolution +meshfix_maximum_deviation support_skip_some_zags support_skip_zag_per_mm support_zag_skip_count From eb3e343be5dd6f7b2a53a88edaf36ad75ab798ac Mon Sep 17 00:00:00 2001 From: Diego Prado Gesto Date: Tue, 16 Apr 2019 12:04:34 +0200 Subject: [PATCH 26/32] Rename variable Even if we could reuse the other, it make sense to call it 'deviation' Contributes to CURA-6458. --- .../VersionUpgrade40to41/VersionUpgrade40to41.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py index f79ec66e5a..db7d3c75da 100644 --- a/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py +++ b/plugins/VersionUpgrade/VersionUpgrade40to41/VersionUpgrade40to41.py @@ -54,8 +54,8 @@ class VersionUpgrade40to41(VersionUpgrade): resolution = parser["values"]["meshfix_maximum_resolution"] if resolution.startswith("="): resolution = resolution[1:] - resolution = "=(" + resolution + ") / 2" - parser["values"]["meshfix_maximum_deviation"] = resolution + deviation = "=(" + resolution + ") / 2" + parser["values"]["meshfix_maximum_deviation"] = deviation del parser["values"]["meshfix_maximum_resolution"] result = io.StringIO() From 3771040c04a280077c02dd299bf0877cb2745ff0 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 12:58:47 +0200 Subject: [PATCH 27/32] Adjust warning values for maximum resolution Due to the change in tactics to limit resolution by deviation, this can be increased quite a lot (as long as you don't increase deviation too much). --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index 15e3209e49..e903dceb0c 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5857,8 +5857,8 @@ "unit": "mm", "default_value": 0.25, "minimum_value": "0.001", - "minimum_value_warning": "0.005", - "maximum_value_warning": "0.1", + "minimum_value_warning": "0.02", + "maximum_value_warning": "2", "settable_per_mesh": true }, "meshfix_maximum_travel_resolution": From 96abaf23767899fd622753e22a85f270b0ed854a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 16 Apr 2019 12:59:45 +0200 Subject: [PATCH 28/32] Adjust warning values for maximum travel resolution Due to the change in tactics to limit resolution by deviation, this can be increased quite a lot (as long as you don't increase deviation too much). --- resources/definitions/fdmprinter.def.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json index e903dceb0c..5e5c34338b 100644 --- a/resources/definitions/fdmprinter.def.json +++ b/resources/definitions/fdmprinter.def.json @@ -5870,8 +5870,8 @@ "default_value": 0.5, "value": "meshfix_maximum_resolution * speed_travel / speed_print", "minimum_value": "0.001", - "minimum_value_warning": "0.005", - "maximum_value_warning": "1", + "minimum_value_warning": "0.05", + "maximum_value_warning": "10", "settable_per_mesh": false, "settable_per_extruder": true }, From 46fa45768afcad824fd2a893a9100c69e0a1a18e Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 17 Apr 2019 09:34:59 +0200 Subject: [PATCH 29/32] Simplify shouldShowWelcomeDialog() CURA-6447 --- cura/CuraApplication.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 60722c4767..0310526c2e 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -1775,11 +1775,8 @@ class CuraApplication(QtApplication): @pyqtSlot(result = bool) def shouldShowWelcomeDialog(self) -> bool: - has_active_machine = self._machine_manager.activeMachine is not None - - # Only show the complete flow if there is not printer yet. - show_complete_flow = not has_active_machine - return show_complete_flow + # Only show the complete flow if there is no printer yet. + return self._machine_manager.activeMachine is None @pyqtSlot(result = bool) def shouldShowWhatsNewDialog(self) -> bool: From 64cb86217e5f74ddb723284ba437bc26e79ef632 Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 17 Apr 2019 09:36:01 +0200 Subject: [PATCH 30/32] Remove non-existing icon CURA-6447 --- resources/qml/Actions.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/Actions.qml b/resources/qml/Actions.qml index ed89eb553e..ce9618a560 100644 --- a/resources/qml/Actions.qml +++ b/resources/qml/Actions.qml @@ -234,7 +234,6 @@ Item { id: whatsNewAction; text: catalog.i18nc("@action:inmenu menubar:help", "What's New"); - iconName: "help-whats-new"; } Action From a49d00c60ee03284dfe67492bfbe2807ae38bc6f Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 17 Apr 2019 09:42:40 +0200 Subject: [PATCH 31/32] Move some code into Component.onCompleted CURA-6447 --- resources/qml/Cura.qml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 08fbc95b0e..1b05b6987a 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -68,12 +68,17 @@ UM.MainWindow z: greyOutBackground.z + 1 } + Component.onCompleted: + { + CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size")) + CuraApplication.purgeWindows() + } + Connections { target: CuraApplication onInitializationFinished: { - CuraApplication.setMinimumWindowSize(UM.Theme.getSize("window_minimum_size")) // Workaround silly issues with QML Action's shortcut property. // // Currently, there is no way to define shortcuts as "Application Shortcut". @@ -85,7 +90,6 @@ 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.shouldShowWelcomeDialog()) { From 44a0f00f0b32e9f2e78632bc1c8a98551b191fef Mon Sep 17 00:00:00 2001 From: Lipu Fei Date: Wed, 17 Apr 2019 09:58:05 +0200 Subject: [PATCH 32/32] Reuse welcome dialog item to show whats new upon start CURA-6447 --- resources/qml/Cura.qml | 18 ++++-------------- .../qml/WelcomePages/WelcomeDialogItem.qml | 1 + 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 1b05b6987a..f5cbe8ad53 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -100,26 +100,16 @@ UM.MainWindow welcomeDialogItem.visible = false } + // Reuse the welcome dialog item to show "What's New" only. if (CuraApplication.shouldShowWhatsNewDialog()) { - showWhatsNewDialogTimer.start() + welcomeDialogItem.model = CuraApplication.getWhatsNewPagesModel() + welcomeDialogItem.progressBarVisible = false + welcomeDialogItem.visible = true } } } - // HACK: Use a timer here because if we call "Cura.Actions.whatsNew.trigger()" or "whatsNewDialog.show()" when - // the component gets completed or when the application finishes its initialization, the main window has not been - // fully initialized yet. If we should the dialog before the main window is fully initialized, you will see the - // dialog first but when the main windows is fully initialized, the dialog will disappear. Adding a timer here is - // to bypass this problem. - Timer - { - id: showWhatsNewDialogTimer - repeat: false - interval: 1000 - onTriggered: Cura.Actions.whatsNew.trigger() - } - Item { id: backgroundItem diff --git a/resources/qml/WelcomePages/WelcomeDialogItem.qml b/resources/qml/WelcomePages/WelcomeDialogItem.qml index 1ab722598b..7da4c6e897 100644 --- a/resources/qml/WelcomePages/WelcomeDialogItem.qml +++ b/resources/qml/WelcomePages/WelcomeDialogItem.qml @@ -26,6 +26,7 @@ Item property int shadowOffset: 1 * screenScaleFactor + property alias progressBarVisible: wizardPanel.progressBarVisible property var model: CuraApplication.getWelcomePagesModel() onVisibleChanged: