mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-12 01:07:52 -06:00
Merge branch 'master' into feature-backup-manager
This commit is contained in:
commit
d27ac3cf31
7 changed files with 47 additions and 35 deletions
|
@ -207,6 +207,7 @@ class CuraApplication(QtApplication):
|
||||||
|
|
||||||
UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions(
|
UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions(
|
||||||
{
|
{
|
||||||
|
("quality", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"),
|
||||||
("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityChangesInstanceContainer, "application/x-uranium-instancecontainer"),
|
("quality_changes", InstanceContainer.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.QualityChangesInstanceContainer, "application/x-uranium-instancecontainer"),
|
||||||
("machine_stack", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
|
("machine_stack", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.MachineStack, "application/x-cura-globalstack"),
|
||||||
("extruder_train", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
|
("extruder_train", ContainerStack.Version * 1000000 + self.SettingVersion): (self.ResourceTypes.ExtruderStack, "application/x-cura-extruderstack"),
|
||||||
|
|
|
@ -18,9 +18,6 @@ from UM.Version import Version
|
||||||
class CuraPackageManager(QObject):
|
class CuraPackageManager(QObject):
|
||||||
Version = 1
|
Version = 1
|
||||||
|
|
||||||
# The prefix that's added to all files for an installed package to avoid naming conflicts with user created files.
|
|
||||||
PREFIX_PLACE_HOLDER = "-CP;"
|
|
||||||
|
|
||||||
def __init__(self, parent = None):
|
def __init__(self, parent = None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
|
|
||||||
|
@ -171,7 +168,7 @@ class CuraPackageManager(QObject):
|
||||||
package_info["is_active"] = self._plugin_registry.isActivePlugin(package_id)
|
package_info["is_active"] = self._plugin_registry.isActivePlugin(package_id)
|
||||||
|
|
||||||
# If the package ID is in bundled, label it as such
|
# If the package ID is in bundled, label it as such
|
||||||
package_info["is_bundled"] = package_info["package_id"] in self._bundled_package_dict.keys()
|
package_info["is_bundled"] = package_info["package_id"] in self._bundled_package_dict.keys() and not self.isUserInstalledPackage(package_info["package_id"])
|
||||||
|
|
||||||
# If there is not a section in the dict for this type, add it
|
# If there is not a section in the dict for this type, add it
|
||||||
if package_info["package_type"] not in installed_packages_dict:
|
if package_info["package_type"] not in installed_packages_dict:
|
||||||
|
@ -182,7 +179,7 @@ class CuraPackageManager(QObject):
|
||||||
|
|
||||||
return installed_packages_dict
|
return installed_packages_dict
|
||||||
|
|
||||||
# Checks if the given package is installed.
|
# Checks if the given package is installed (at all).
|
||||||
def isPackageInstalled(self, package_id: str) -> bool:
|
def isPackageInstalled(self, package_id: str) -> bool:
|
||||||
return self.getInstalledPackageInfo(package_id) is not None
|
return self.getInstalledPackageInfo(package_id) is not None
|
||||||
|
|
||||||
|
@ -242,7 +239,7 @@ class CuraPackageManager(QObject):
|
||||||
Logger.log("i", "Attempt to remove package [%s] that is not installed, do nothing.", package_id)
|
Logger.log("i", "Attempt to remove package [%s] that is not installed, do nothing.", package_id)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Temp hack
|
# Extra safety check
|
||||||
if package_id not in self._installed_package_dict and package_id in self._bundled_package_dict:
|
if package_id not in self._installed_package_dict and package_id in self._bundled_package_dict:
|
||||||
Logger.log("i", "Not uninstalling [%s] because it is a bundled package.")
|
Logger.log("i", "Not uninstalling [%s] because it is a bundled package.")
|
||||||
return
|
return
|
||||||
|
@ -258,6 +255,10 @@ class CuraPackageManager(QObject):
|
||||||
self._saveManagementData()
|
self._saveManagementData()
|
||||||
self.installedPackagesChanged.emit()
|
self.installedPackagesChanged.emit()
|
||||||
|
|
||||||
|
## Is the package an user installed package?
|
||||||
|
def isUserInstalledPackage(self, package_id: str):
|
||||||
|
return package_id in self._installed_package_dict
|
||||||
|
|
||||||
# Removes everything associated with the given package ID.
|
# Removes everything associated with the given package ID.
|
||||||
def _purgePackage(self, package_id: str) -> None:
|
def _purgePackage(self, package_id: str) -> None:
|
||||||
# Iterate through all directories in the data storage directory and look for sub-directories that belong to
|
# Iterate through all directories in the data storage directory and look for sub-directories that belong to
|
||||||
|
@ -308,27 +309,15 @@ class CuraPackageManager(QObject):
|
||||||
|
|
||||||
if not os.path.exists(src_dir_path):
|
if not os.path.exists(src_dir_path):
|
||||||
continue
|
continue
|
||||||
|
self.__installPackageFiles(package_id, src_dir_path, dst_dir_path)
|
||||||
# Need to rename the container files so they don't get ID conflicts
|
|
||||||
to_rename_files = sub_dir_name not in ("plugins",)
|
|
||||||
self.__installPackageFiles(package_id, src_dir_path, dst_dir_path, need_to_rename_files= to_rename_files)
|
|
||||||
|
|
||||||
# Remove the file
|
# Remove the file
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
|
|
||||||
def __installPackageFiles(self, package_id: str, src_dir: str, dst_dir: str, need_to_rename_files: bool = True) -> None:
|
def __installPackageFiles(self, package_id: str, src_dir: str, dst_dir: str) -> None:
|
||||||
|
Logger.log("i", "Moving package {package_id} from {src_dir} to {dst_dir}".format(package_id=package_id, src_dir=src_dir, dst_dir=dst_dir))
|
||||||
shutil.move(src_dir, dst_dir)
|
shutil.move(src_dir, dst_dir)
|
||||||
|
|
||||||
# Rename files if needed
|
|
||||||
if not need_to_rename_files:
|
|
||||||
return
|
|
||||||
for root, _, file_names in os.walk(dst_dir):
|
|
||||||
for filename in file_names:
|
|
||||||
new_filename = self.PREFIX_PLACE_HOLDER + package_id + "-" + filename
|
|
||||||
old_file_path = os.path.join(root, filename)
|
|
||||||
new_file_path = os.path.join(root, new_filename)
|
|
||||||
os.rename(old_file_path, new_file_path)
|
|
||||||
|
|
||||||
# Gets package information from the given file.
|
# Gets package information from the given file.
|
||||||
def getPackageInfo(self, filename: str) -> Dict[str, Any]:
|
def getPackageInfo(self, filename: str) -> Dict[str, Any]:
|
||||||
with zipfile.ZipFile(filename) as archive:
|
with zipfile.ZipFile(filename) as archive:
|
||||||
|
|
|
@ -113,8 +113,6 @@ class MaterialManager(QObject):
|
||||||
grouped_by_type_dict = dict()
|
grouped_by_type_dict = dict()
|
||||||
material_types_without_fallback = set()
|
material_types_without_fallback = set()
|
||||||
for root_material_id, material_node in self._material_group_map.items():
|
for root_material_id, material_node in self._material_group_map.items():
|
||||||
if not self._container_registry.isReadOnly(root_material_id):
|
|
||||||
continue
|
|
||||||
material_type = material_node.root_material_node.metadata["material"]
|
material_type = material_node.root_material_node.metadata["material"]
|
||||||
if material_type not in grouped_by_type_dict:
|
if material_type not in grouped_by_type_dict:
|
||||||
grouped_by_type_dict[material_type] = {"generic": None,
|
grouped_by_type_dict[material_type] = {"generic": None,
|
||||||
|
@ -127,9 +125,15 @@ class MaterialManager(QObject):
|
||||||
diameter = material_node.root_material_node.metadata.get("approximate_diameter")
|
diameter = material_node.root_material_node.metadata.get("approximate_diameter")
|
||||||
if diameter != self._default_approximate_diameter_for_quality_search:
|
if diameter != self._default_approximate_diameter_for_quality_search:
|
||||||
to_add = False # don't add if it's not the default diameter
|
to_add = False # don't add if it's not the default diameter
|
||||||
|
|
||||||
if to_add:
|
if to_add:
|
||||||
grouped_by_type_dict[material_type] = material_node.root_material_node.metadata
|
# Checking this first allow us to differentiate between not read only materials:
|
||||||
material_types_without_fallback.remove(material_type)
|
# - if it's in the list, it means that is a new material without fallback
|
||||||
|
# - if it is not, then it is a custom material with a fallback material (parent)
|
||||||
|
if material_type in material_types_without_fallback:
|
||||||
|
grouped_by_type_dict[material_type] = material_node.root_material_node.metadata
|
||||||
|
material_types_without_fallback.remove(material_type)
|
||||||
|
|
||||||
# Remove the materials that have no fallback materials
|
# Remove the materials that have no fallback materials
|
||||||
for material_type in material_types_without_fallback:
|
for material_type in material_types_without_fallback:
|
||||||
del grouped_by_type_dict[material_type]
|
del grouped_by_type_dict[material_type]
|
||||||
|
@ -147,9 +151,6 @@ class MaterialManager(QObject):
|
||||||
material_group_dict = dict()
|
material_group_dict = dict()
|
||||||
keys_to_fetch = ("name", "material", "brand", "color")
|
keys_to_fetch = ("name", "material", "brand", "color")
|
||||||
for root_material_id, machine_node in self._material_group_map.items():
|
for root_material_id, machine_node in self._material_group_map.items():
|
||||||
if not self._container_registry.isReadOnly(root_material_id):
|
|
||||||
continue
|
|
||||||
|
|
||||||
root_material_metadata = machine_node.root_material_node.metadata
|
root_material_metadata = machine_node.root_material_node.metadata
|
||||||
|
|
||||||
key_data = []
|
key_data = []
|
||||||
|
@ -157,8 +158,13 @@ class MaterialManager(QObject):
|
||||||
key_data.append(root_material_metadata.get(key))
|
key_data.append(root_material_metadata.get(key))
|
||||||
key_data = tuple(key_data)
|
key_data = tuple(key_data)
|
||||||
|
|
||||||
|
# If the key_data doesn't exist, no matter if the material is read only...
|
||||||
if key_data not in material_group_dict:
|
if key_data not in material_group_dict:
|
||||||
material_group_dict[key_data] = dict()
|
material_group_dict[key_data] = dict()
|
||||||
|
else:
|
||||||
|
# ...but if key_data exists, we just overrite it if the material is read only, otherwise we skip it
|
||||||
|
if not machine_node.is_read_only:
|
||||||
|
continue
|
||||||
approximate_diameter = root_material_metadata.get("approximate_diameter")
|
approximate_diameter = root_material_metadata.get("approximate_diameter")
|
||||||
material_group_dict[key_data][approximate_diameter] = root_material_metadata["id"]
|
material_group_dict[key_data][approximate_diameter] = root_material_metadata["id"]
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,9 @@ Item
|
||||||
property var active: false
|
property var active: false
|
||||||
property var complete: false
|
property var complete: false
|
||||||
|
|
||||||
property var readyLabel: "Install"
|
property var readyLabel: catalog.i18nc("@action:button", "Install")
|
||||||
property var activeLabel: "Installing"
|
property var activeLabel: catalog.i18nc("@action:button", "Cancel")
|
||||||
property var completeLabel: "Installed"
|
property var completeLabel: catalog.i18nc("@action:button", "Installed")
|
||||||
|
|
||||||
property var readyAction: null // Action when button is ready and clicked (likely install)
|
property var readyAction: null // Action when button is ready and clicked (likely install)
|
||||||
property var activeAction: null // Action when button is active and clicked (likely cancel)
|
property var activeAction: null // Action when button is active and clicked (likely cancel)
|
||||||
|
@ -32,15 +32,15 @@ Item
|
||||||
{
|
{
|
||||||
if (complete)
|
if (complete)
|
||||||
{
|
{
|
||||||
return catalog.i18nc("@action:button", "Installed")
|
return completeLabel
|
||||||
}
|
}
|
||||||
else if (active)
|
else if (active)
|
||||||
{
|
{
|
||||||
return catalog.i18nc("@action:button", "Cancel")
|
return activeLabel
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return catalog.i18nc("@action:button", "Install")
|
return readyLabel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onClicked:
|
onClicked:
|
||||||
|
|
|
@ -250,7 +250,8 @@ class Toolbox(QObject, Extension):
|
||||||
if remote_package:
|
if remote_package:
|
||||||
download_url = remote_package["download_url"]
|
download_url = remote_package["download_url"]
|
||||||
Logger.log("d", "Updating package [%s]..." % plugin_id)
|
Logger.log("d", "Updating package [%s]..." % plugin_id)
|
||||||
self.uninstall(plugin_id)
|
if self._package_manager.isUserInstalledPackage(plugin_id):
|
||||||
|
self.uninstall(plugin_id)
|
||||||
self.startDownload(download_url)
|
self.startDownload(download_url)
|
||||||
else:
|
else:
|
||||||
Logger.log("e", "Could not update package [%s] because there is no remote package info available.", plugin_id)
|
Logger.log("e", "Could not update package [%s] because there is no remote package info available.", plugin_id)
|
||||||
|
|
|
@ -3703,6 +3703,20 @@
|
||||||
"settable_per_mesh": false,
|
"settable_per_mesh": false,
|
||||||
"settable_per_extruder": true
|
"settable_per_extruder": true
|
||||||
},
|
},
|
||||||
|
"support_wall_count":
|
||||||
|
{
|
||||||
|
"label": "Support Wall Line Count",
|
||||||
|
"description": "The number of walls with which to surround support infill. Adding a wall can make support print more reliably and can support overhangs better, but increases print time and material used.",
|
||||||
|
"default_value": 1,
|
||||||
|
"minimum_value": "0",
|
||||||
|
"minimum_value_warning": "1 if support_pattern == 'concentric' else 0",
|
||||||
|
"maximum_value_warning": "3",
|
||||||
|
"type": "int",
|
||||||
|
"value": "1 if (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'concentric') else 0",
|
||||||
|
"enabled": "support_enable",
|
||||||
|
"limit_to_extruder": "support_infill_extruder_nr",
|
||||||
|
"settable_per_mesh": true
|
||||||
|
},
|
||||||
"zig_zaggify_support":
|
"zig_zaggify_support":
|
||||||
{
|
{
|
||||||
"label": "Connect Support Lines",
|
"label": "Connect Support Lines",
|
||||||
|
|
|
@ -220,6 +220,7 @@ support_bottom_extruder_nr
|
||||||
support_type
|
support_type
|
||||||
support_angle
|
support_angle
|
||||||
support_pattern
|
support_pattern
|
||||||
|
support_wall_count
|
||||||
zig_zaggify_support
|
zig_zaggify_support
|
||||||
support_connect_zigzags
|
support_connect_zigzags
|
||||||
support_infill_rate
|
support_infill_rate
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue