mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-25 07:33:57 -06:00
Merge branch '4.4' into translations_4.4
This commit is contained in:
commit
5cae2fd098
14 changed files with 107 additions and 34 deletions
|
@ -140,7 +140,7 @@ class MachineNode(ContainerNode):
|
||||||
elif groups_by_name[name].intent_category == "default": # Intent category should be stored as "default" if everything is default or as the intent if any of the extruder have an actual intent.
|
elif groups_by_name[name].intent_category == "default": # Intent category should be stored as "default" if everything is default or as the intent if any of the extruder have an actual intent.
|
||||||
groups_by_name[name].intent_category = quality_changes.get("intent_category", "default")
|
groups_by_name[name].intent_category = quality_changes.get("intent_category", "default")
|
||||||
|
|
||||||
if "position" in quality_changes: # An extruder profile.
|
if quality_changes.get("position") is not None: # An extruder profile.
|
||||||
groups_by_name[name].metadata_per_extruder[int(quality_changes["position"])] = quality_changes
|
groups_by_name[name].metadata_per_extruder[int(quality_changes["position"])] = quality_changes
|
||||||
else: # Global profile.
|
else: # Global profile.
|
||||||
groups_by_name[name].metadata_for_global = quality_changes
|
groups_by_name[name].metadata_for_global = quality_changes
|
||||||
|
|
|
@ -6,6 +6,7 @@ from typing import Dict, Set
|
||||||
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtProperty
|
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, pyqtProperty
|
||||||
|
|
||||||
from UM.Qt.ListModel import ListModel
|
from UM.Qt.ListModel import ListModel
|
||||||
|
from UM.Logger import Logger
|
||||||
|
|
||||||
import cura.CuraApplication # Imported like this to prevent a circular reference.
|
import cura.CuraApplication # Imported like this to prevent a circular reference.
|
||||||
from cura.Machines.ContainerTree import ContainerTree
|
from cura.Machines.ContainerTree import ContainerTree
|
||||||
|
@ -153,7 +154,12 @@ class BaseMaterialsModel(ListModel):
|
||||||
if not extruder_stack:
|
if not extruder_stack:
|
||||||
return
|
return
|
||||||
nozzle_name = extruder_stack.variant.getName()
|
nozzle_name = extruder_stack.variant.getName()
|
||||||
materials = ContainerTree.getInstance().machines[global_stack.definition.getId()].variants[nozzle_name].materials
|
machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
|
||||||
|
if nozzle_name not in machine_node.variants:
|
||||||
|
Logger.log("w", "Unable to find variant %s in container tree", nozzle_name)
|
||||||
|
self._available_materials = {}
|
||||||
|
return
|
||||||
|
materials = machine_node.variants[nozzle_name].materials
|
||||||
approximate_material_diameter = extruder_stack.getApproximateMaterialDiameter()
|
approximate_material_diameter = extruder_stack.getApproximateMaterialDiameter()
|
||||||
self._available_materials = {key: material for key, material in materials.items() if float(material.getMetaDataEntry("approximate_diameter", -1)) == approximate_material_diameter}
|
self._available_materials = {key: material for key, material in materials.items() if float(material.getMetaDataEntry("approximate_diameter", -1)) == approximate_material_diameter}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#Copyright (c) 2019 Ultimaker B.V.
|
#Copyright (c) 2019 Ultimaker B.V.
|
||||||
#Cura is released under the terms of the LGPLv3 or higher.
|
#Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QTimer
|
|
||||||
import collections
|
import collections
|
||||||
|
from PyQt5.QtCore import Qt, QTimer
|
||||||
from typing import TYPE_CHECKING, Optional, Dict
|
from typing import TYPE_CHECKING, Optional, Dict
|
||||||
|
from cura.Machines.Models.IntentTranslations import intent_translations
|
||||||
|
|
||||||
from cura.Machines.Models.IntentModel import IntentModel
|
from cura.Machines.Models.IntentModel import IntentModel
|
||||||
from cura.Settings.IntentManager import IntentManager
|
from cura.Settings.IntentManager import IntentManager
|
||||||
|
@ -53,7 +54,6 @@ class IntentCategoryModel(ListModel):
|
||||||
}
|
}
|
||||||
return cls._translations
|
return cls._translations
|
||||||
|
|
||||||
|
|
||||||
## Creates a new model for a certain intent category.
|
## Creates a new model for a certain intent category.
|
||||||
# \param The category to list the intent profiles for.
|
# \param The category to list the intent profiles for.
|
||||||
def __init__(self, intent_category: str) -> None:
|
def __init__(self, intent_category: str) -> None:
|
||||||
|
@ -110,7 +110,7 @@ class IntentCategoryModel(ListModel):
|
||||||
result.sort(key = lambda k: k["weight"])
|
result.sort(key = lambda k: k["weight"])
|
||||||
self.setItems(result)
|
self.setItems(result)
|
||||||
|
|
||||||
## Get a display value for a category. See IntenCategoryModel._translations
|
## Get a display value for a category.
|
||||||
## for categories and keys
|
## for categories and keys
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def translation(category: str, key: str, default: Optional[str] = None):
|
def translation(category: str, key: str, default: Optional[str] = None):
|
||||||
|
|
21
cura/Machines/Models/IntentTranslations.py
Normal file
21
cura/Machines/Models/IntentTranslations.py
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import collections
|
||||||
|
from UM.i18n import i18nCatalog
|
||||||
|
from typing import Dict, Optional
|
||||||
|
catalog = i18nCatalog("cura")
|
||||||
|
|
||||||
|
intent_translations = collections.OrderedDict() # type: "collections.OrderedDict[str, Dict[str, Optional[str]]]"
|
||||||
|
intent_translations["default"] = {
|
||||||
|
"name": catalog.i18nc("@label", "Default")
|
||||||
|
}
|
||||||
|
intent_translations["visual"] = {
|
||||||
|
"name": catalog.i18nc("@label", "Visual"),
|
||||||
|
"description": catalog.i18nc("@text", "The visual profile is designed to print visual prototypes and models with the intent of high visual and surface quality.")
|
||||||
|
}
|
||||||
|
intent_translations["engineering"] = {
|
||||||
|
"name": catalog.i18nc("@label", "Engineering"),
|
||||||
|
"description": catalog.i18nc("@text", "The engineering profile is designed to print functional prototypes and end-use parts with the intent of better accuracy and for closer tolerances.")
|
||||||
|
}
|
||||||
|
intent_translations["quick"] = {
|
||||||
|
"name": catalog.i18nc("@label", "Draft"),
|
||||||
|
"description": catalog.i18nc("@text", "The draft profile is designed to print initial prototypes and concept validation with the intent of significant print time reduction.")
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ from cura.Machines.ContainerTree import ContainerTree
|
||||||
from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container
|
from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container
|
||||||
from cura.Settings.IntentManager import IntentManager
|
from cura.Settings.IntentManager import IntentManager
|
||||||
from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
|
from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
|
||||||
|
from cura.Machines.Models.IntentTranslations import intent_translations
|
||||||
|
|
||||||
from UM.i18n import i18nCatalog
|
from UM.i18n import i18nCatalog
|
||||||
catalog = i18nCatalog("cura")
|
catalog = i18nCatalog("cura")
|
||||||
|
@ -336,10 +337,11 @@ class QualityManagementModel(ListModel):
|
||||||
"quality_type": quality_type,
|
"quality_type": quality_type,
|
||||||
"quality_changes_group": None,
|
"quality_changes_group": None,
|
||||||
"intent_category": intent_category,
|
"intent_category": intent_category,
|
||||||
"section_name": catalog.i18nc("@label", intent_category.capitalize()),
|
"section_name": catalog.i18nc("@label", intent_translations.get(intent_category, {}).get("name", catalog.i18nc("@label", "Unknown"))),
|
||||||
})
|
})
|
||||||
# Sort by quality_type for each intent category
|
# Sort by quality_type for each intent category
|
||||||
result = sorted(result, key = lambda x: (x["intent_category"], x["quality_type"]))
|
|
||||||
|
result = sorted(result, key = lambda x: (list(intent_translations).index(x["intent_category"]), x["quality_type"]))
|
||||||
item_list += result
|
item_list += result
|
||||||
|
|
||||||
# Create quality_changes group items
|
# Create quality_changes group items
|
||||||
|
|
|
@ -85,11 +85,20 @@ class VariantNode(ContainerNode):
|
||||||
for base_material, material_node in self.materials.items():
|
for base_material, material_node in self.materials.items():
|
||||||
if self.machine.preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
if self.machine.preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
||||||
return material_node
|
return material_node
|
||||||
# First fallback: Choose any material with matching diameter.
|
|
||||||
|
# First fallback: Check if we should be checking for the 175 variant.
|
||||||
|
if approximate_diameter == 2:
|
||||||
|
preferred_material = self.machine.preferred_material + "_175"
|
||||||
|
for base_material, material_node in self.materials.items():
|
||||||
|
if preferred_material == base_material and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
||||||
|
return material_node
|
||||||
|
|
||||||
|
# Second fallback: Choose any material with matching diameter.
|
||||||
for material_node in self.materials.values():
|
for material_node in self.materials.values():
|
||||||
if material_node.getMetaDataEntry("approximate_diameter") and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
if material_node.getMetaDataEntry("approximate_diameter") and approximate_diameter == int(material_node.getMetaDataEntry("approximate_diameter")):
|
||||||
Logger.log("w", "Could not find preferred material %s, falling back to whatever works", self.machine.preferred_material)
|
Logger.log("w", "Could not find preferred material %s, falling back to whatever works", self.machine.preferred_material)
|
||||||
return material_node
|
return material_node
|
||||||
|
|
||||||
fallback = next(iter(self.materials.values())) # Should only happen with empty material node.
|
fallback = next(iter(self.materials.values())) # Should only happen with empty material node.
|
||||||
Logger.log("w", "Could not find preferred material {preferred_material} with diameter {diameter} for variant {variant_id}, falling back to {fallback}.".format(
|
Logger.log("w", "Could not find preferred material {preferred_material} with diameter {diameter} for variant {variant_id}, falling back to {fallback}.".format(
|
||||||
preferred_material = self.machine.preferred_material,
|
preferred_material = self.machine.preferred_material,
|
||||||
|
|
|
@ -99,7 +99,7 @@ class AuthorizationHelpers:
|
||||||
})
|
})
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
# Connection was suddenly dropped. Nothing we can do about that.
|
# Connection was suddenly dropped. Nothing we can do about that.
|
||||||
Logger.log("w", "Something failed while attempting to parse the JWT token")
|
Logger.logException("w", "Something failed while attempting to parse the JWT token")
|
||||||
return None
|
return None
|
||||||
if token_request.status_code not in (200, 201):
|
if token_request.status_code not in (200, 201):
|
||||||
Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text)
|
Logger.log("w", "Could not retrieve token data from auth server: %s", token_request.text)
|
||||||
|
|
|
@ -339,11 +339,11 @@ class ContainerManager(QObject):
|
||||||
# \return A list of names of materials with the same GUID.
|
# \return A list of names of materials with the same GUID.
|
||||||
@pyqtSlot("QVariant", bool, result = "QStringList")
|
@pyqtSlot("QVariant", bool, result = "QStringList")
|
||||||
def getLinkedMaterials(self, material_node: "MaterialNode", exclude_self: bool = False) -> List[str]:
|
def getLinkedMaterials(self, material_node: "MaterialNode", exclude_self: bool = False) -> List[str]:
|
||||||
same_guid = ContainerRegistry.getInstance().findInstanceContainersMetadata(guid = material_node.guid)
|
same_guid = ContainerRegistry.getInstance().findInstanceContainersMetadata(GUID = material_node.guid)
|
||||||
if exclude_self:
|
if exclude_self:
|
||||||
return [metadata["name"] for metadata in same_guid if metadata["base_file"] != material_node.base_file]
|
return list({meta["name"] for meta in same_guid if meta["base_file"] != material_node.base_file})
|
||||||
else:
|
else:
|
||||||
return [metadata["name"] for metadata in same_guid]
|
return list({meta["name"] for meta in same_guid})
|
||||||
|
|
||||||
## Unlink a material from all other materials by creating a new GUID
|
## Unlink a material from all other materials by creating a new GUID
|
||||||
# \param material_id \type{str} the id of the material to create a new GUID for.
|
# \param material_id \type{str} the id of the material to create a new GUID for.
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal, pyqtSlot
|
||||||
from typing import Any, Dict, List, Optional, Set, Tuple, TYPE_CHECKING
|
from typing import Any, Dict, List, Optional, Set, Tuple, TYPE_CHECKING
|
||||||
import cura.CuraApplication
|
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
|
|
||||||
|
import cura.CuraApplication
|
||||||
from cura.Machines.ContainerTree import ContainerTree
|
from cura.Machines.ContainerTree import ContainerTree
|
||||||
from cura.Settings.cura_empty_instance_containers import empty_intent_container
|
from cura.Settings.cura_empty_instance_containers import empty_intent_container
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from UM.Settings.InstanceContainer import InstanceContainer
|
from UM.Settings.InstanceContainer import InstanceContainer
|
||||||
|
@ -36,8 +38,12 @@ class IntentManager(QObject):
|
||||||
# \return A list of metadata dictionaries matching the search criteria, or
|
# \return A list of metadata dictionaries matching the search criteria, or
|
||||||
# an empty list if nothing was found.
|
# an empty list if nothing was found.
|
||||||
def intentMetadatas(self, definition_id: str, nozzle_name: str, material_base_file: str) -> List[Dict[str, Any]]:
|
def intentMetadatas(self, definition_id: str, nozzle_name: str, material_base_file: str) -> List[Dict[str, Any]]:
|
||||||
material_node = ContainerTree.getInstance().machines[definition_id].variants[nozzle_name].materials[material_base_file]
|
intent_metadatas = [] # type: List[Dict[str, Any]]
|
||||||
intent_metadatas = []
|
materials = ContainerTree.getInstance().machines[definition_id].variants[nozzle_name].materials
|
||||||
|
if material_base_file not in materials:
|
||||||
|
return intent_metadatas
|
||||||
|
|
||||||
|
material_node = materials[material_base_file]
|
||||||
for quality_node in material_node.qualities.values():
|
for quality_node in material_node.qualities.values():
|
||||||
for intent_node in quality_node.intents.values():
|
for intent_node in quality_node.intents.values():
|
||||||
intent_metadatas.append(intent_node.getMetadata())
|
intent_metadatas.append(intent_node.getMetadata())
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Toolbox(QObject, Extension):
|
||||||
self._download_progress = 0 # type: float
|
self._download_progress = 0 # type: float
|
||||||
self._is_downloading = False # type: bool
|
self._is_downloading = False # type: bool
|
||||||
self._network_manager = None # type: Optional[QNetworkAccessManager]
|
self._network_manager = None # type: Optional[QNetworkAccessManager]
|
||||||
self._request_headers = [] # type: List[Tuple[bytes, bytes]]
|
self._request_headers = [] # type: List[Tuple[bytes, bytes]]
|
||||||
self._updateRequestHeader()
|
self._updateRequestHeader()
|
||||||
|
|
||||||
self._request_urls = {} # type: Dict[str, QUrl]
|
self._request_urls = {} # type: Dict[str, QUrl]
|
||||||
|
@ -59,13 +59,15 @@ class Toolbox(QObject, Extension):
|
||||||
# The responses as given by the server parsed to a list.
|
# The responses as given by the server parsed to a list.
|
||||||
self._server_response_data = {
|
self._server_response_data = {
|
||||||
"authors": [],
|
"authors": [],
|
||||||
"packages": []
|
"packages": [],
|
||||||
|
"updates": [],
|
||||||
} # type: Dict[str, List[Any]]
|
} # type: Dict[str, List[Any]]
|
||||||
|
|
||||||
# Models:
|
# Models:
|
||||||
self._models = {
|
self._models = {
|
||||||
"authors": AuthorsModel(self),
|
"authors": AuthorsModel(self),
|
||||||
"packages": PackagesModel(self),
|
"packages": PackagesModel(self),
|
||||||
|
"updates": PackagesModel(self),
|
||||||
} # type: Dict[str, Union[AuthorsModel, PackagesModel]]
|
} # type: Dict[str, Union[AuthorsModel, PackagesModel]]
|
||||||
|
|
||||||
self._plugins_showcase_model = PackagesModel(self)
|
self._plugins_showcase_model = PackagesModel(self)
|
||||||
|
@ -186,18 +188,24 @@ class Toolbox(QObject, Extension):
|
||||||
cloud_api_version = self._cloud_api_version,
|
cloud_api_version = self._cloud_api_version,
|
||||||
sdk_version = self._sdk_version
|
sdk_version = self._sdk_version
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# We need to construct a query like installed_packages=ID:VERSION&installed_packages=ID:VERSION, etc.
|
||||||
|
installed_package_ids_with_versions = [":".join(items) for items in
|
||||||
|
self._package_manager.getAllInstalledPackageIdsAndVersions()]
|
||||||
|
installed_packages_query = "&installed_packages=".join(installed_package_ids_with_versions)
|
||||||
|
|
||||||
self._request_urls = {
|
self._request_urls = {
|
||||||
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
|
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
|
||||||
"packages": QUrl("{base_url}/packages".format(base_url = self._api_url))
|
"packages": QUrl("{base_url}/packages".format(base_url = self._api_url)),
|
||||||
|
"updates": QUrl("{base_url}/packages/package-updates?installed_packages={query}".format(
|
||||||
|
base_url = self._api_url, query = installed_packages_query))
|
||||||
}
|
}
|
||||||
|
|
||||||
# Request the latest and greatest!
|
# On boot we check which packages have updates.
|
||||||
self._fetchPackageData()
|
if len(installed_package_ids_with_versions) > 0:
|
||||||
|
self._fetchPackageUpdates()
|
||||||
|
|
||||||
def _fetchPackageData(self):
|
def _prepareNetworkManager(self):
|
||||||
# Create the network manager:
|
|
||||||
# This was formerly its own function but really had no reason to be as
|
|
||||||
# it was never called more than once ever.
|
|
||||||
if self._network_manager is not None:
|
if self._network_manager is not None:
|
||||||
self._network_manager.finished.disconnect(self._onRequestFinished)
|
self._network_manager.finished.disconnect(self._onRequestFinished)
|
||||||
self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccessibleChanged)
|
self._network_manager.networkAccessibleChanged.disconnect(self._onNetworkAccessibleChanged)
|
||||||
|
@ -205,10 +213,15 @@ class Toolbox(QObject, Extension):
|
||||||
self._network_manager.finished.connect(self._onRequestFinished)
|
self._network_manager.finished.connect(self._onRequestFinished)
|
||||||
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccessibleChanged)
|
self._network_manager.networkAccessibleChanged.connect(self._onNetworkAccessibleChanged)
|
||||||
|
|
||||||
|
def _fetchPackageUpdates(self):
|
||||||
|
self._prepareNetworkManager()
|
||||||
|
self._makeRequestByType("updates")
|
||||||
|
|
||||||
|
def _fetchPackageData(self):
|
||||||
|
self._prepareNetworkManager()
|
||||||
# Make remote requests:
|
# Make remote requests:
|
||||||
self._makeRequestByType("packages")
|
self._makeRequestByType("packages")
|
||||||
self._makeRequestByType("authors")
|
self._makeRequestByType("authors")
|
||||||
|
|
||||||
# Gather installed packages:
|
# Gather installed packages:
|
||||||
self._updateInstalledModels()
|
self._updateInstalledModels()
|
||||||
|
|
||||||
|
@ -234,7 +247,7 @@ class Toolbox(QObject, Extension):
|
||||||
if not plugin_path:
|
if not plugin_path:
|
||||||
return None
|
return None
|
||||||
path = os.path.join(plugin_path, "resources", "qml", qml_name)
|
path = os.path.join(plugin_path, "resources", "qml", qml_name)
|
||||||
|
|
||||||
dialog = self._application.createQmlComponent(path, {"toolbox": self})
|
dialog = self._application.createQmlComponent(path, {"toolbox": self})
|
||||||
if not dialog:
|
if not dialog:
|
||||||
raise Exception("Failed to create Marketplace dialog")
|
raise Exception("Failed to create Marketplace dialog")
|
||||||
|
@ -618,7 +631,7 @@ class Toolbox(QObject, Extension):
|
||||||
if not self._models[response_type]:
|
if not self._models[response_type]:
|
||||||
Logger.log("e", "Could not find the %s model.", response_type)
|
Logger.log("e", "Could not find the %s model.", response_type)
|
||||||
break
|
break
|
||||||
|
|
||||||
self._server_response_data[response_type] = json_data["data"]
|
self._server_response_data[response_type] = json_data["data"]
|
||||||
self._models[response_type].setMetadata(self._server_response_data[response_type])
|
self._models[response_type].setMetadata(self._server_response_data[response_type])
|
||||||
|
|
||||||
|
@ -630,6 +643,10 @@ class Toolbox(QObject, Extension):
|
||||||
elif response_type == "authors":
|
elif response_type == "authors":
|
||||||
self._models[response_type].setFilter({"package_types": "material"})
|
self._models[response_type].setFilter({"package_types": "material"})
|
||||||
self._models[response_type].setFilter({"tags": "generic"})
|
self._models[response_type].setFilter({"tags": "generic"})
|
||||||
|
elif response_type == "updates":
|
||||||
|
# Tell the package manager that there's a new set of updates available.
|
||||||
|
packages = set([pkg["package_id"] for pkg in self._server_response_data[response_type]])
|
||||||
|
self._package_manager.setPackagesWithUpdate(packages)
|
||||||
|
|
||||||
self.metadataChanged.emit()
|
self.metadataChanged.emit()
|
||||||
|
|
||||||
|
@ -660,7 +677,7 @@ class Toolbox(QObject, Extension):
|
||||||
self.setIsDownloading(False)
|
self.setIsDownloading(False)
|
||||||
self._download_reply = cast(QNetworkReply, self._download_reply)
|
self._download_reply = cast(QNetworkReply, self._download_reply)
|
||||||
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
||||||
|
|
||||||
# Check if the download was sucessfull
|
# Check if the download was sucessfull
|
||||||
if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
|
if self._download_reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) != 200:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -100,7 +100,6 @@ UM.Dialog
|
||||||
{
|
{
|
||||||
text: styleData.value
|
text: styleData.value
|
||||||
font: UM.Theme.getFont("system")
|
font: UM.Theme.getFont("system")
|
||||||
color: UM.Theme.getColor("setting_control_disabled_text")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ TabView
|
||||||
{
|
{
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return linkedMaterials.join(", ");
|
return linkedMaterials;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getApproximateDiameter(diameter)
|
function getApproximateDiameter(diameter)
|
||||||
|
|
|
@ -160,15 +160,25 @@ Item
|
||||||
enabled: model.description !== undefined
|
enabled: model.description !== undefined
|
||||||
acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks
|
acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks
|
||||||
|
|
||||||
onEntered:
|
Timer
|
||||||
{
|
{
|
||||||
base.showTooltip(
|
id: intentTooltipTimer
|
||||||
|
interval: 500
|
||||||
|
running: false
|
||||||
|
repeat: false
|
||||||
|
onTriggered: base.showTooltip(
|
||||||
intentCategoryLabel,
|
intentCategoryLabel,
|
||||||
Qt.point(-(intentCategoryLabel.x - qualityRow.x) - UM.Theme.getSize("thick_margin").width, 0),
|
Qt.point(-(intentCategoryLabel.x - qualityRow.x) - UM.Theme.getSize("thick_margin").width, 0),
|
||||||
model.description
|
model.description
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
onExited: base.hideTooltip()
|
|
||||||
|
onEntered: intentTooltipTimer.start()
|
||||||
|
onExited:
|
||||||
|
{
|
||||||
|
base.hideTooltip()
|
||||||
|
intentTooltipTimer.stop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NoIntentIcon // This icon has hover priority over intentDescriptionHoverArea, so draw it above it.
|
NoIntentIcon // This icon has hover priority over intentDescriptionHoverArea, so draw it above it.
|
||||||
|
|
|
@ -139,6 +139,7 @@ def test_preferredMaterialExactMatch(empty_variant_node):
|
||||||
"some_different_material": MagicMock(getMetaDataEntry = lambda x: 3),
|
"some_different_material": MagicMock(getMetaDataEntry = lambda x: 3),
|
||||||
"preferred_material_base_file": MagicMock(getMetaDataEntry = lambda x: 3) # Exact match.
|
"preferred_material_base_file": MagicMock(getMetaDataEntry = lambda x: 3) # Exact match.
|
||||||
}
|
}
|
||||||
|
empty_variant_node.machine.preferred_material = "preferred_material_base_file"
|
||||||
|
|
||||||
assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_base_file"], "It should match exactly on this one since it's the preferred material."
|
assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_base_file"], "It should match exactly on this one since it's the preferred material."
|
||||||
|
|
||||||
|
@ -149,6 +150,7 @@ def test_preferredMaterialSubmaterial(empty_variant_node):
|
||||||
"some_different_material": MagicMock(getMetaDataEntry = lambda x: 3),
|
"some_different_material": MagicMock(getMetaDataEntry = lambda x: 3),
|
||||||
"preferred_material_base_file_aa04": MagicMock(getMetaDataEntry = lambda x: 3) # This is a submaterial of the preferred material.
|
"preferred_material_base_file_aa04": MagicMock(getMetaDataEntry = lambda x: 3) # This is a submaterial of the preferred material.
|
||||||
}
|
}
|
||||||
|
empty_variant_node.machine.preferred_material = "preferred_material_base_file_aa04"
|
||||||
|
|
||||||
assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_base_file_aa04"], "It should match on the submaterial just as well."
|
assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_base_file_aa04"], "It should match on the submaterial just as well."
|
||||||
|
|
||||||
|
@ -160,6 +162,7 @@ def test_preferredMaterialDiameter(empty_variant_node):
|
||||||
"preferred_material_wrong_diameter": MagicMock(getMetaDataEntry = lambda x: 2), # Approximate diameter is 2 instead of 3.
|
"preferred_material_wrong_diameter": MagicMock(getMetaDataEntry = lambda x: 2), # Approximate diameter is 2 instead of 3.
|
||||||
"preferred_material_correct_diameter": MagicMock(getMetaDataEntry = lambda x: 3) # Correct approximate diameter.
|
"preferred_material_correct_diameter": MagicMock(getMetaDataEntry = lambda x: 3) # Correct approximate diameter.
|
||||||
}
|
}
|
||||||
|
empty_variant_node.machine.preferred_material = "preferred_material_correct_diameter"
|
||||||
|
|
||||||
assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_correct_diameter"], "It should match only on the material with correct diameter."
|
assert empty_variant_node.preferredMaterial(approximate_diameter = 3) == empty_variant_node.materials["preferred_material_correct_diameter"], "It should match only on the material with correct diameter."
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue