diff --git a/cura/Machines/Models/MaterialBrandsModel.py b/cura/Machines/Models/MaterialBrandsModel.py index 184d27f390..b0594cb286 100644 --- a/cura/Machines/Models/MaterialBrandsModel.py +++ b/cura/Machines/Models/MaterialBrandsModel.py @@ -34,7 +34,7 @@ class MaterialBrandsModel(BaseMaterialsModel): brand_item_list = [] brand_group_dict = {} - # Part 1: Generate the entire tree of brands -> material types -> spcific materials + # Part 1: Generate the entire tree of brands -> material types -> specific materials for root_material_id, container_node in self._available_materials.items(): # Do not include the materials from a to-be-removed package if bool(container_node.getMetaDataEntry("removed", False)): diff --git a/cura/Machines/VariantNode.py b/cura/Machines/VariantNode.py index 550b5881a3..0f30782a91 100644 --- a/cura/Machines/VariantNode.py +++ b/cura/Machines/VariantNode.py @@ -51,7 +51,7 @@ class VariantNode(ContainerNode): # Find all the materials for this variant's name. else: # Printer has its own material profiles. Look for material profiles with this printer's definition. base_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = "fdmprinter") - printer_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id, variant_name = None) + printer_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id) variant_specific_materials = container_registry.findInstanceContainersMetadata(type = "material", definition = self.machine.container_id, variant_name = self.variant_name) # If empty_variant, this won't return anything. materials_per_base_file = {material["base_file"]: material for material in base_materials} materials_per_base_file.update({material["base_file"]: material for material in printer_specific_materials}) # Printer-specific profiles override global ones. diff --git a/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml b/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml index a6ce7fc865..41020f2415 100644 --- a/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml +++ b/plugins/Toolbox/resources/qml/dialogs/CompatibilityDialog.qml @@ -74,7 +74,7 @@ UM.Dialog{ } Label { - text: model.name + text: model.display_name font: UM.Theme.getFont("medium_bold") anchors.left: packageIcon.right anchors.leftMargin: UM.Theme.getSize("default_margin").width @@ -104,7 +104,7 @@ UM.Dialog{ { width: parent.width property int lineHeight: 60 - visible: !model.is_compatible + visible: !model.is_compatible && !model.is_dismissed height: visible ? (lineHeight + UM.Theme.getSize("default_margin").height) : 0 // We only show the incompatible packages here Image { @@ -117,7 +117,7 @@ UM.Dialog{ } Label { - text: model.name + text: model.display_name font: UM.Theme.getFont("medium_bold") anchors.left: packageIcon.right anchors.leftMargin: UM.Theme.getSize("default_margin").width @@ -125,6 +125,26 @@ UM.Dialog{ color: UM.Theme.getColor("text") elide: Text.ElideRight } + UM.TooltipArea + { + width: childrenRect.width; + height: childrenRect.height; + text: catalog.i18nc("@info:tooltip", "Dismisses the package and won't be shown in this dialog anymore") + anchors.right: parent.right + anchors.verticalCenter: packageIcon.verticalCenter + Label + { + text: "(Dismiss)" + font: UM.Theme.getFont("small") + color: UM.Theme.getColor("text") + MouseArea + { + cursorShape: Qt.PointingHandCursor + anchors.fill: parent + onClicked: toolbox.dismissIncompatiblePackage(model.package_id) + } + } + } } } } diff --git a/plugins/Toolbox/src/SubscribedPackagesModel.py b/plugins/Toolbox/src/SubscribedPackagesModel.py index cf0d07c153..e6886f23ce 100644 --- a/plugins/Toolbox/src/SubscribedPackagesModel.py +++ b/plugins/Toolbox/src/SubscribedPackagesModel.py @@ -4,6 +4,8 @@ from PyQt5.QtCore import Qt from UM.Qt.ListModel import ListModel from cura import ApplicationMetadata +from UM.Logger import Logger +from typing import List, Dict, Any class SubscribedPackagesModel(ListModel): @@ -15,25 +17,27 @@ class SubscribedPackagesModel(ListModel): self._discrepancies = None self._sdk_version = ApplicationMetadata.CuraSDKVersion - self.addRoleName(Qt.UserRole + 1, "name") - self.addRoleName(Qt.UserRole + 2, "icon_url") - self.addRoleName(Qt.UserRole + 3, "is_compatible") + self.addRoleName(Qt.UserRole + 1, "package_id") + self.addRoleName(Qt.UserRole + 2, "display_name") + self.addRoleName(Qt.UserRole + 3, "icon_url") + self.addRoleName(Qt.UserRole + 4, "is_compatible") + self.addRoleName(Qt.UserRole + 5, "is_dismissed") - def setMetadata(self, data): - if self._metadata != data: - self._metadata = data + def setMetadata(self, data: List[Dict[str, List[Any]]]) -> None: + self._metadata = data - def addValue(self, discrepancy): - if self._discrepancies != discrepancy: - self._discrepancies = discrepancy + def addDiscrepancies(self, discrepancy: List[str]) -> None: + self._discrepancies = discrepancy - def update(self): + def initialize(self) -> None: self._items.clear() - for item in self._metadata: if item["package_id"] not in self._discrepancies: continue - package = {"name": item["display_name"], "sdk_versions": item["sdk_versions"]} + package = {"package_id": item["package_id"], + "display_name": item["display_name"], + "sdk_versions": item["sdk_versions"], + "is_dismissed": False} if self._sdk_version not in item["sdk_versions"]: package.update({"is_compatible": False}) else: @@ -42,7 +46,6 @@ class SubscribedPackagesModel(ListModel): package.update({"icon_url": item["icon_url"]}) except KeyError: # There is no 'icon_url" in the response payload for this package package.update({"icon_url": ""}) - self._items.append(package) self.setItems(self._items) @@ -58,4 +61,11 @@ class SubscribedPackagesModel(ListModel): for item in self._items: if item['is_compatible'] == False: has_incompatible_items = True - return has_incompatible_items \ No newline at end of file + return has_incompatible_items + + # Sets the "is_compatible" to True for the given package, in memory + def dismissPackage(self, package_id: str) -> None: + package = self.find(key="package_id", value=package_id) + if package != -1: + self.setProperty(package, property="is_dismissed", value=True) + Logger.debug("Package {} has been dismissed".format(package_id)) diff --git a/plugins/Toolbox/src/Toolbox.py b/plugins/Toolbox/src/Toolbox.py index ee260f6808..dd01458a32 100644 --- a/plugins/Toolbox/src/Toolbox.py +++ b/plugins/Toolbox/src/Toolbox.py @@ -556,6 +556,11 @@ class Toolbox(QObject, Extension): populated += 1 return populated == len(self._server_response_data.items()) + @pyqtSlot(str) + def dismissIncompatiblePackage(self, package_id: str): + self._models["subscribed_packages"].dismissPackage(package_id) # sets "is_compatible" to True, in-memory + self._package_manager.dismissPackage(package_id) # adds this package_id as dismissed in the user config file + # Make API Calls # -------------------------------------------------------------------------- def _makeRequestByType(self, request_type: str) -> None: @@ -663,13 +668,15 @@ class Toolbox(QObject, Extension): def _checkCompatibilities(self, json_data) -> None: user_subscribed_packages = [plugin["package_id"] for plugin in json_data] user_installed_packages = self._package_manager.getUserInstalledPackages() - - # We check if there are packages installed in Cloud Marketplace but not in Cura marketplace (discrepancy) + user_dismissed_packages = self._package_manager.getDismissedPackages() + if user_dismissed_packages: + user_installed_packages += user_dismissed_packages + # We check if there are packages installed in Cloud Marketplace but not in Cura marketplace package_discrepancy = list(set(user_subscribed_packages).difference(user_installed_packages)) if package_discrepancy: - self._models["subscribed_packages"].addValue(package_discrepancy) - self._models["subscribed_packages"].update() - Logger.log("d", "Discrepancy found between Cloud subscribed packages and Cura installed packages") + self._models["subscribed_packages"].addDiscrepancies(package_discrepancy) + self._models["subscribed_packages"].initialize() + Logger.debug("Discrepancy found between Cloud subscribed packages and Cura installed packages") sync_message = Message(i18n_catalog.i18nc( "@info:generic", "\nDo you want to sync material and software packages with your account?"), @@ -680,7 +687,6 @@ class Toolbox(QObject, Extension): icon="", description="Sync your Cloud subscribed packages to your local environment.", button_align=Message.ActionButtonAlignment.ALIGN_RIGHT) - sync_message.actionTriggered.connect(self._onSyncButtonClicked) sync_message.show() diff --git a/resources/qml/Cura.qml b/resources/qml/Cura.qml index 8dcf60018f..d6f50f939b 100644 --- a/resources/qml/Cura.qml +++ b/resources/qml/Cura.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2019 Ultimaker B.V. +// Copyright (c) 2020 Ultimaker B.V. // Cura is released under the terms of the LGPLv3 or higher. import QtQuick 2.7 @@ -21,7 +21,16 @@ UM.MainWindow id: base // Cura application window title - title: PrintInformation.jobName + " - " + catalog.i18nc("@title:window", CuraApplication.applicationDisplayName) + title: + { + let result = ""; + if(PrintInformation.jobName != "") + { + result += PrintInformation.jobName + " - "; + } + result += CuraApplication.applicationDisplayName; + return result; + } backgroundColor: UM.Theme.getColor("viewport_background") @@ -244,23 +253,6 @@ UM.MainWindow } } - Toolbar - { - // The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by - // plugins) - id: toolbar - - property int mouseX: base.mouseX - property int mouseY: base.mouseY - - anchors - { - verticalCenter: parent.verticalCenter - left: parent.left - } - visible: CuraApplication.platformActivity && !PrintInformation.preSliced - } - ObjectSelector { id: objectSelector @@ -302,6 +294,23 @@ UM.MainWindow } } + Toolbar + { + // The toolbar is the left bar that is populated by all the tools (which are dynamicly populated by + // plugins) + id: toolbar + + property int mouseX: base.mouseX + property int mouseY: base.mouseY + + anchors + { + verticalCenter: parent.verticalCenter + left: parent.left + } + visible: CuraApplication.platformActivity && !PrintInformation.preSliced + } + // A hint for the loaded content view. Overlay items / controls can safely be placed in this area Item { id: mainSafeArea diff --git a/test-in-docker.sh b/test-in-docker.sh new file mode 100755 index 0000000000..e5a1116646 --- /dev/null +++ b/test-in-docker.sh @@ -0,0 +1,5 @@ +sudo rm -rf ./build ./Uranium +sudo docker run -it --rm \ + -v "$(pwd):/srv/cura" ultimaker/cura-build-environment \ + /srv/cura/docker/build.sh +sudo rm -rf ./build ./Uranium