Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 6 additions & 43 deletions cura/Machines/Models/IntentCategoryModel.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#Copyright (c) 2019 Ultimaker B.V.
#Cura is released under the terms of the LGPLv3 or higher.

import collections
from PyQt6.QtCore import Qt, QTimer
from typing import TYPE_CHECKING, Optional, Dict

from cura.Machines.Models.IntentModel import IntentModel
from cura.Machines.Models.IntentTranslations import IntentTranslations
from cura.Settings.IntentManager import IntentManager
from UM.Qt.ListModel import ListModel
from UM.Settings.ContainerRegistry import ContainerRegistry #To update the list if anything changes.
Expand All @@ -29,45 +29,6 @@ class IntentCategoryModel(ListModel):

modelUpdated = pyqtSignal()

_translations = collections.OrderedDict() # type: "collections.OrderedDict[str,Dict[str,Optional[str]]]"

@classmethod
def _get_translations(cls):
"""Translations to user-visible string. Ordered by weight.

TODO: Create a solution for this name and weight to be used dynamically.
"""
if len(cls._translations) == 0:
cls._translations["default"] = {
"name": catalog.i18nc("@label", "Balanced"),
"description": catalog.i18nc("@text",
"The balanced profile is designed to strike a balance between productivity, surface quality, mechanical properties and dimensional accuracy.")
}
cls._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.")
}
cls._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.")
}
cls._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.")
}
cls._translations["annealing"] = {
"name": catalog.i18nc("@label", "Annealing"),
"description": catalog.i18nc("@text",
"The annealing profile requires post-processing in an oven after the print is finished. This profile retains the dimensional accuracy of the printed part after annealing and improves strength, stiffness, and thermal resistance.")

}
cls._translations["solid"] = {
"name": catalog.i18nc("@label", "Solid"),
"description": catalog.i18nc("@text",
"A highly dense and strong part but at a slower print time. Great for functional parts.")
}
return cls._translations

def __init__(self, intent_category: str) -> None:
"""Creates a new model for a certain intent category.

Expand Down Expand Up @@ -120,7 +81,7 @@ def _update(self) -> None:
qualities = IntentModel()
qualities.setIntentCategory(category)
try:
weight = list(IntentCategoryModel._get_translations().keys()).index(category)
weight = IntentTranslations.getInstance().index(category)
except ValueError:
weight = 99
result.append({
Expand All @@ -137,5 +98,7 @@ def _update(self) -> None:
def translation(category: str, key: str, default: Optional[str] = None):
"""Get a display value for a category.for categories and keys"""

display_strings = IntentCategoryModel._get_translations().get(category, {})
return display_strings.get(key, default)
try:
return IntentTranslations.getInstance().getTranslation(category)[key]
except KeyError:
return default
96 changes: 67 additions & 29 deletions cura/Machines/Models/IntentTranslations.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,73 @@
import collections
from typing import Dict, Optional
import warnings
import json
from typing import Dict

from UM.Decorators import singleton, deprecated
from UM.i18n import i18nCatalog
from typing import Dict, Optional
from UM.Logger import Logger
from UM.Resources import Resources
catalog = i18nCatalog("cura")


intent_translations = collections.OrderedDict() # type: collections.OrderedDict[str, Dict[str, Optional[str]]]
intent_translations["default"] = {
"name": catalog.i18nc("@label", "Balanced"),
"description": catalog.i18nc("@text",
"The balanced profile is designed to strike a balance between productivity, surface quality, mechanical properties and dimensional accuracy.")
}
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.")
}
intent_translations["annealing"] = {
"name": catalog.i18nc("@label", "Annealing"),
"description": catalog.i18nc("@text", "The annealing profile requires post-processing in an oven after the print is finished. This profile retains the dimensional accuracy of the printed part after annealing and improves strength, stiffness, and thermal resistance.")
}
intent_translations["solid"] = {
"name": catalog.i18nc("@label", "Solid"),
"description": catalog.i18nc("@text",
"A highly dense and strong part but at a slower print time. Great for functional parts.")
}
@singleton
class IntentTranslations:
def __init__(self):
from cura.CuraApplication import CuraApplication
intents_definition_path = Resources.getPath(CuraApplication.ResourceTypes.IntentInstanceContainer, "intents.json")
self._intent_translations: collections.OrderedDict[str, Dict[str, str]] = collections.OrderedDict()

with open(intents_definition_path, "r") as file:
intents_data = json.load(file)
for intent_id in intents_data:
intent_definition = intents_data[intent_id]
self._intent_translations[intent_id] = {
"name": catalog.i18nc(f"{intent_id} intent label", intent_definition["label"]),
"description": catalog.i18nc(f"{intent_id} intent description", intent_definition["description"])
}

def index(self, intent_id: str) -> int:
"""
Get the index of the given intent key in the list
:warning: There is no checking for presence, so this will throw a ValueError if the id is not present
"""
return list(self._intent_translations.keys()).index(intent_id)

def getTranslation(self, intent_id: str) -> Dict[str, str]:
"""
Get the translation of the given intent key
:return If found, a dictionary containing the name and description of the intent
:warning: There is no checking for presence, so this will throw a KeyError if the id is not present
"""
return self._intent_translations[intent_id]

def getLabel(self, intent_id: str) -> str:
"""
Get the translated name of the given intent key
:warning: There is no checking for presence, so this will throw a KeyError if the id is not present
"""
return self.getTranslation(intent_id)["name"]

def getDescription(self, intent_id: str) -> str:
"""
Get the translated description of the given intent key
:warning: There is no checking for presence, so this will throw a KeyError if the id is not present
"""
return self.getTranslation(intent_id)["description"]

@deprecated("This method only exists to provide the old intent_translations list, it should not be used anywhere else", "5.12")
def getTranslations(self) -> collections.OrderedDict[str, Dict[str, str]]:
return self._intent_translations


def __getattr__(name):
if name == "intent_translations":
warning = ("IntentTranslations.intent_translations is deprecated since 5.12, please use the IntentTranslations "
"singleton instead. Note that the intents translations will not work as long as this old behavior "
"is used within a plugin")
Logger.log("w_once", warning)
warnings.warn(warning, DeprecationWarning, stacklevel=2)

return IntentTranslations.getInstance().getTranslations()

return None
17 changes: 10 additions & 7 deletions cura/Machines/Models/QualityManagementModel.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from cura.Settings.cura_empty_instance_containers import empty_quality_changes_container
from cura.Settings.IntentManager import IntentManager
from cura.Machines.Models.MachineModelUtils import fetchLayerHeight
from cura.Machines.Models.IntentTranslations import intent_translations
from cura.Machines.Models.IntentTranslations import IntentTranslations

from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura")
Expand Down Expand Up @@ -343,7 +343,7 @@ def _update(self):
"quality_type": quality_group.quality_type,
"quality_changes_group": None,
"intent_category": "default",
"section_name": catalog.i18nc("@label", "Balanced"),
"section_name": IntentTranslations.getInstance().getLabel("default"),
"layer_height": layer_height, # layer_height is only used for sorting
}
item_list.append(item)
Expand All @@ -358,23 +358,26 @@ def _update(self):
for intent_category, quality_type in available_intent_list:
if not quality_group_dict[quality_type].is_available:
continue


try:
intent_label = IntentTranslations.getInstance().getLabel(intent_category)
except KeyError:
intent_label = catalog.i18nc("@label", intent_category.title())

result.append({
"name": quality_group_dict[quality_type].name, # Use the quality name as the display name
"is_read_only": True,
"quality_group": quality_group_dict[quality_type],
"quality_type": quality_type,
"quality_changes_group": None,
"intent_category": intent_category,
"section_name": catalog.i18nc("@label", intent_translations.get(intent_category, {}).get("name", catalog.i18nc("@label", intent_category.title()))),
"section_name": intent_label,
})

# Sort by quality_type for each intent category
intent_translations_list = list(intent_translations)

def getIntentWeight(intent_category):
try:
return intent_translations_list.index(intent_category)
return IntentTranslations.getInstance().index(intent_category)
except ValueError:
return 99

Expand Down
8 changes: 4 additions & 4 deletions plugins/3MFReader/WorkspaceDialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import List, Optional, Dict, cast

from cura.Machines.Models.MachineListModel import MachineListModel
from cura.Machines.Models.IntentTranslations import intent_translations
from cura.Machines.Models.IntentTranslations import IntentTranslations
from cura.Settings.GlobalStack import GlobalStack
from UM.Application import Application
from UM.FlameProfiler import pyqtSlot
Expand Down Expand Up @@ -259,13 +259,13 @@ def intentName(self) -> str:
def setIntentName(self, intent_name: str) -> None:
if self._intent_name != intent_name:
try:
self._intent_name = intent_translations[intent_name]["name"]
except:
self._intent_name = IntentTranslations.getInstance().getLabel(intent_name)
except KeyError:
self._intent_name = intent_name.title()
self.intentNameChanged.emit()

if not self._intent_name:
self._intent_name = intent_translations["default"]["name"]
self._intent_name = IntentTranslations.getInstance().getLabel("default")
self.intentNameChanged.emit()

@pyqtProperty(str, notify=activeModeChanged)
Expand Down
Loading
Loading