Merge branch 'master' into WIP_improve_initialization

This commit is contained in:
Diego Prado Gesto 2018-05-16 16:57:51 +02:00
commit e38b31c0eb
21 changed files with 358 additions and 215 deletions

View file

@ -297,7 +297,6 @@ class CuraApplication(QtApplication):
if not hasattr(sys, "frozen"): if not hasattr(sys, "frozen"):
resource_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources") resource_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources")
Resources.addSearchPath(resource_path) Resources.addSearchPath(resource_path)
Resources.setBundledResourcesPath(resource_path)
# Adds custom property types, settings types, and extra operators (functions) that need to be registered in # Adds custom property types, settings types, and extra operators (functions) that need to be registered in
# SettingDefinition and SettingFunction. # SettingDefinition and SettingFunction.
@ -397,6 +396,7 @@ class CuraApplication(QtApplication):
def __setLatestResouceVersionsForVersionUpgrade(self): def __setLatestResouceVersionsForVersionUpgrade(self):
self._version_upgrade_manager.setCurrentVersions( self._version_upgrade_manager.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"),

View file

@ -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)
@ -28,15 +25,19 @@ class CuraPackageManager(QObject):
self._container_registry = self._application.getContainerRegistry() self._container_registry = self._application.getContainerRegistry()
self._plugin_registry = self._application.getPluginRegistry() self._plugin_registry = self._application.getPluginRegistry()
# JSON file that keeps track of all installed packages. #JSON files that keep track of all installed packages.
self._bundled_package_management_file_path = os.path.join( self._user_package_management_file_path = None
os.path.abspath(Resources.getBundledResourcesPath()), self._bundled_package_management_file_path = None
"packages.json" for search_path in Resources.getSearchPaths():
) candidate_bundled_path = os.path.join(search_path, "bundled_packages.json")
self._user_package_management_file_path = os.path.join( if os.path.exists(candidate_bundled_path):
os.path.abspath(Resources.getDataStoragePath()), self._bundled_package_management_file_path = candidate_bundled_path
"packages.json" for search_path in (Resources.getDataStoragePath(), Resources.getConfigStoragePath()):
) candidate_user_path = os.path.join(search_path, "packages.json")
if os.path.exists(candidate_user_path):
self._user_package_management_file_path = candidate_user_path
if self._user_package_management_file_path is None: #Doesn't exist yet.
self._user_package_management_file_path = os.path.join(Resources.getDataStoragePath(), "packages.json")
self._bundled_package_dict = {} # A dict of all bundled packages self._bundled_package_dict = {} # A dict of all bundled packages
self._installed_package_dict = {} # A dict of all installed packages self._installed_package_dict = {} # A dict of all installed packages
@ -136,14 +137,14 @@ class CuraPackageManager(QObject):
all_installed_ids = all_installed_ids.union(set(self._bundled_package_dict.keys())) all_installed_ids = all_installed_ids.union(set(self._bundled_package_dict.keys()))
if self._installed_package_dict.keys(): if self._installed_package_dict.keys():
all_installed_ids = all_installed_ids.union(set(self._installed_package_dict.keys())) all_installed_ids = all_installed_ids.union(set(self._installed_package_dict.keys()))
all_installed_ids = all_installed_ids.difference(self._to_remove_package_set)
# If it's going to be installed and to be removed, then the package is being updated and it should be listed.
if self._to_install_package_dict.keys(): if self._to_install_package_dict.keys():
all_installed_ids = all_installed_ids.union(set(self._to_install_package_dict.keys())) all_installed_ids = all_installed_ids.union(set(self._to_install_package_dict.keys()))
all_installed_ids = all_installed_ids.difference(self._to_remove_package_set)
# map of <package_type> -> <package_id> -> <package_info> # map of <package_type> -> <package_id> -> <package_info>
installed_packages_dict = {} installed_packages_dict = {}
for package_id in all_installed_ids: for package_id in all_installed_ids:
# Skip required plugins as they should not be tampered with # Skip required plugins as they should not be tampered with
if package_id in Application.getInstance().getRequiredPlugins(): if package_id in Application.getInstance().getRequiredPlugins():
continue continue
@ -168,7 +169,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:
@ -179,7 +180,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
@ -194,11 +195,6 @@ class CuraPackageManager(QObject):
return return
package_id = package_info["package_id"] package_id = package_info["package_id"]
# Check the delayed installation and removal lists first
if package_id in self._to_remove_package_set:
self._to_remove_package_set.remove(package_id)
has_changes = True
# Check if it is installed # Check if it is installed
installed_package_info = self.getInstalledPackageInfo(package_info["package_id"]) installed_package_info = self.getInstalledPackageInfo(package_info["package_id"])
to_install_package = installed_package_info is None # Install if the package has not been installed to_install_package = installed_package_info is None # Install if the package has not been installed
@ -235,23 +231,35 @@ class CuraPackageManager(QObject):
self.installedPackagesChanged.emit() self.installedPackagesChanged.emit()
# Schedules the given package to be removed upon the next start. # Schedules the given package to be removed upon the next start.
# \param package_id id of the package
# \param force_add is used when updating. In that case you actually want to uninstall & install
@pyqtSlot(str) @pyqtSlot(str)
def removePackage(self, package_id: str) -> None: def removePackage(self, package_id: str, force_add: bool = False) -> None:
# Check the delayed installation and removal lists first # Check the delayed installation and removal lists first
if not self.isPackageInstalled(package_id): if not self.isPackageInstalled(package_id):
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
# Remove from the delayed installation list if present # Extra safety check
if package_id in self._to_install_package_dict: if package_id not in self._installed_package_dict and package_id in self._bundled_package_dict:
del self._to_install_package_dict[package_id] Logger.log("i", "Not uninstalling [%s] because it is a bundled package.")
return
# Schedule for a delayed removal: if package_id not in self._to_install_package_dict or force_add:
self._to_remove_package_set.add(package_id) # Schedule for a delayed removal:
self._to_remove_package_set.add(package_id)
else:
if package_id in self._to_install_package_dict:
# Remove from the delayed installation list if present
del self._to_install_package_dict[package_id]
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
@ -302,27 +310,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:
@ -342,13 +338,7 @@ class CuraPackageManager(QObject):
with zipfile.ZipFile(filename) as archive: with zipfile.ZipFile(filename) as archive:
# Go through all the files and use the first successful read as the result # Go through all the files and use the first successful read as the result
for file_info in archive.infolist(): for file_info in archive.infolist():
is_dir = lambda file_info: file_info.filename.endswith('/') if file_info.filename.endswith("LICENSE"):
if is_dir or not file_info.filename.startswith("files/"):
continue
filename_parts = os.path.basename(file_info.filename.lower()).split(".")
stripped_filename = filename_parts[0]
if stripped_filename in ("license", "licence"):
Logger.log("d", "Found potential license file '%s'", file_info.filename) Logger.log("d", "Found potential license file '%s'", file_info.filename)
try: try:
with archive.open(file_info.filename, "r") as f: with archive.open(file_info.filename, "r") as f:

View file

@ -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"]

View file

@ -345,7 +345,7 @@ class PrintInformation(QObject):
except: except:
Logger.log("w", "Unsupported Mime Type Database file extension") Logger.log("w", "Unsupported Mime Type Database file extension")
if data is not None: if data is not None and check_name is not None:
self._base_name = data self._base_name = data
else: else:
self._base_name = '' self._base_name = ''

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View file

@ -0,0 +1 @@
<svg width="200px" height="200px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-rolling" style="animation-play-state: running; animation-delay: 0s; background-image: none; background-position: initial initial; background-repeat: initial initial;"><circle cx="50" cy="50" fill="none" ng-attr-stroke="{{config.color}}" ng-attr-stroke-width="{{config.width}}" ng-attr-r="{{config.radius}}" ng-attr-stroke-dasharray="{{config.dasharray}}" stroke="#0CA9E3" stroke-width="13" r="43" stroke-dasharray="202.63272615654165 69.54424205218055" style="animation-play-state: running; animation-delay: 0s;"><animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite" style="animation-play-state: running; animation-delay: 0s;"></animateTransform></circle></svg>

After

Width:  |  Height:  |  Size: 903 B

View file

@ -20,7 +20,7 @@ Item
{ {
left: parent.left left: parent.left
right: controls.left right: controls.left
rightMargin: UM.Theme.getSize("default_margin").width rightMargin: UM.Theme.getSize("default_margin").width * 2 + UM.Theme.getSize("toolbox_loader").width
top: parent.top top: parent.top
} }
Label Label
@ -53,60 +53,28 @@ Item
anchors.top: tile.top anchors.top: tile.top
width: childrenRect.width width: childrenRect.width
height: childrenRect.height height: childrenRect.height
Button
ToolboxProgressButton
{ {
id: installButton id: installButton
text: active: toolbox.isDownloading && toolbox.activePackage == model
complete: tile.installed
readyAction: function()
{ {
if (installed) toolbox.activePackage = model
{ toolbox.startDownload(model.download_url)
return catalog.i18nc("@action:button", "Installed")
}
else
{
if (toolbox.isDownloading && toolbox.activePackage == model)
{
return catalog.i18nc("@action:button", "Cancel")
}
else
{
return catalog.i18nc("@action:button", "Install")
}
}
} }
enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model) //Don't allow installing while another download is running. activeAction: function()
{
toolbox.cancelDownload()
}
completeAction: function()
{
toolbox.viewCategory = "installed"
}
// Don't allow installing while another download is running
enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model)
opacity: enabled ? 1.0 : 0.5 opacity: enabled ? 1.0 : 0.5
property alias installed: tile.installed
style: UM.Theme.styles.toolbox_action_button
onClicked:
{
if (installed)
{
toolbox.viewCategory = "installed"
}
else
{
// if ( toolbox.isDownloading && toolbox.activePackage == model )
if ( toolbox.isDownloading )
{
toolbox.cancelDownload();
}
else
{
toolbox.activePackage = model
// toolbox.activePackage = model;
if ( model.can_upgrade )
{
// toolbox.downloadAndInstallPlugin( model.update_url );
}
else
{
toolbox.startDownload( model.download_url );
}
}
}
}
} }
} }

View file

@ -90,6 +90,16 @@ Item
color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining") color: model.enabled ? UM.Theme.getColor("text") : UM.Theme.getColor("lining")
linkColor: UM.Theme.getColor("text_link") linkColor: UM.Theme.getColor("text_link")
} }
Label
{
text: model.version
width: parent.width
height: UM.Theme.getSize("toolbox_property_label").height
color: UM.Theme.getColor("text")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignLeft
}
} }
ToolboxInstalledTileActions ToolboxInstalledTileActions
{ {
@ -102,4 +112,4 @@ Item
onMetadataChanged: canUpdate = toolbox.canUpdate(model.id) onMetadataChanged: canUpdate = toolbox.canUpdate(model.id)
} }
} }
} }

View file

@ -11,56 +11,28 @@ Column
width: UM.Theme.getSize("toolbox_action_button").width width: UM.Theme.getSize("toolbox_action_button").width
spacing: UM.Theme.getSize("narrow_margin").height spacing: UM.Theme.getSize("narrow_margin").height
Item ToolboxProgressButton
{ {
width: parent.width id: updateButton
height: childrenRect.height active: toolbox.isDownloading && toolbox.activePackage == model
readyLabel: catalog.i18nc("@action:button", "Update")
activeLabel: catalog.i18nc("@action:button", "Updating")
completeLabel: catalog.i18nc("@action:button", "Updated")
readyAction: function()
{
toolbox.activePackage = model
toolbox.update(model.id)
}
activeAction: function()
{
toolbox.cancelDownload()
}
// Don't allow installing while another download is running
enabled: !(toolbox.isDownloading && toolbox.activePackage != model)
opacity: enabled ? 1.0 : 0.5
visible: canUpdate visible: canUpdate
Button
{
id: updateButton
text: catalog.i18nc("@action:button", "Update")
style: ButtonStyle
{
background: Rectangle
{
implicitWidth: UM.Theme.getSize("toolbox_action_button").width
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
color: control.hovered ? UM.Theme.getColor("primary_hover") : UM.Theme.getColor("primary")
}
label: Label
{
text: control.text
color: control.hovered ? UM.Theme.getColor("button_text") : UM.Theme.getColor("button_text_hover")
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font: UM.Theme.getFont("default_bold")
}
}
onClicked: toolbox.update(model.id)
}
ProgressBar
{
id: progressbar
width: parent.width
value: toolbox.isDownloading ? toolbox.downloadProgress : 0
visible: toolbox.isDownloading
style: ProgressBarStyle
{
background: Rectangle
{
color: "transparent"
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
}
progress: Rectangle
{
// TODO Define a good color that fits the purpuse
color: "blue"
opacity: 0.5
}
}
}
} }
Button Button
{ {
id: removeButton id: removeButton
@ -90,4 +62,4 @@ Column
} }
onClicked: toolbox.uninstall(model.id) onClicked: toolbox.uninstall(model.id)
} }
} }

View file

@ -0,0 +1,125 @@
// Copyright (c) 2018 Ultimaker B.V.
// Toolbox is released under the terms of the LGPLv3 or higher.
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import UM 1.1 as UM
Item
{
id: base
property var active: false
property var complete: false
property var readyLabel: catalog.i18nc("@action:button", "Install")
property var activeLabel: catalog.i18nc("@action:button", "Cancel")
property var completeLabel: catalog.i18nc("@action:button", "Installed")
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 completeAction: null // Action when button is complete and clicked (likely go to installed)
width: UM.Theme.getSize("toolbox_action_button").width
height: UM.Theme.getSize("toolbox_action_button").height
Button
{
id: button
text:
{
if (complete)
{
return completeLabel
}
else if (active)
{
return activeLabel
}
else
{
return readyLabel
}
}
onClicked:
{
if (complete)
{
return completeAction()
}
else if (active)
{
return activeAction()
}
else
{
return readyAction()
}
}
style: ButtonStyle
{
background: Rectangle
{
implicitWidth: UM.Theme.getSize("toolbox_action_button").width
implicitHeight: UM.Theme.getSize("toolbox_action_button").height
color:
{
if (base.complete)
{
return UM.Theme.getColor("action_button_disabled")
}
else
{
if (control.hovered)
{
return UM.Theme.getColor("primary_hover")
}
else
{
return UM.Theme.getColor("primary")
}
}
}
}
label: Label
{
text: control.text
color:
{
if (base.complete)
{
return UM.Theme.getColor("action_button_disabled_text")
}
else
{
if (control.hovered)
{
return UM.Theme.getColor("button_text_hover")
}
else
{
return UM.Theme.getColor("button_text")
}
}
}
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
font: UM.Theme.getFont("default_bold")
}
}
}
AnimatedImage
{
id: loader
visible: active
source: "../images/loading.gif"
width: UM.Theme.getSize("toolbox_loader").width
height: UM.Theme.getSize("toolbox_loader").height
anchors.right: button.left
anchors.rightMargin: UM.Theme.getSize("default_margin").width
anchors.verticalCenter: button.verticalCenter
}
}

View file

@ -34,7 +34,7 @@ class Toolbox(QObject, Extension):
self._plugin_registry = Application.getInstance().getPluginRegistry() self._plugin_registry = Application.getInstance().getPluginRegistry()
self._packages_version = self._getPackagesVersion() self._packages_version = self._getPackagesVersion()
self._api_version = 1 self._api_version = 1
self._api_url = "https://api-staging.ultimaker.com/cura-packages/v{api_version}/cura/v{package_version}".format( api_version = self._api_version, package_version = self._packages_version) self._api_url = "https://api.ultimaker.com/cura-packages/v{api_version}/cura/v{package_version}".format( api_version = self._api_version, package_version = self._packages_version)
# Network: # Network:
self._get_packages_request = None self._get_packages_request = None
@ -61,6 +61,7 @@ class Toolbox(QObject, Extension):
"plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)), "plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)),
"materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)) "materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url))
} }
self._to_update = [] # Package_ids that are waiting to be updated
# Data: # Data:
self._metadata = { self._metadata = {
@ -216,13 +217,36 @@ class Toolbox(QObject, Extension):
@pyqtSlot(str) @pyqtSlot(str)
def uninstall(self, plugin_id: str) -> None: def uninstall(self, plugin_id: str) -> None:
self._package_manager.removePackage(plugin_id) self._package_manager.removePackage(plugin_id, force_add = True)
self.installChanged.emit() self.installChanged.emit()
self._updateInstalledModels() self._updateInstalledModels()
self.metadataChanged.emit() self.metadataChanged.emit()
self._restart_required = True self._restart_required = True
self.restartRequiredChanged.emit() self.restartRequiredChanged.emit()
## Actual update packages that are in self._to_update
def _update(self) -> None:
if self._to_update:
plugin_id = self._to_update.pop(0)
remote_package = self.getRemotePackage(plugin_id)
if remote_package:
download_url = remote_package["download_url"]
Logger.log("d", "Updating package [%s]..." % plugin_id)
if self._package_manager.isUserInstalledPackage(plugin_id):
self.uninstall(plugin_id)
self.startDownload(download_url)
else:
Logger.log("e", "Could not update package [%s] because there is no remote package info available.", plugin_id)
if self._to_update:
self._application.callLater(self._update)
## Update a plugin by plugin_id
@pyqtSlot(str)
def update(self, plugin_id: str) -> None:
self._to_update.append(plugin_id)
self._application.callLater(self._update)
@pyqtSlot(str) @pyqtSlot(str)
def enable(self, plugin_id: str) -> None: def enable(self, plugin_id: str) -> None:
self._plugin_registry.enablePlugin(plugin_id) self._plugin_registry.enablePlugin(plugin_id)
@ -251,6 +275,15 @@ class Toolbox(QObject, Extension):
def restart(self): def restart(self):
CuraApplication.getInstance().windowClosed() CuraApplication.getInstance().windowClosed()
def getRemotePackage(self, package_id: str) -> Optional[Dict]:
# TODO: make the lookup in a dict, not a loop. canUpdate is called for every item.
remote_package = None
for package in self._metadata["packages"]:
if package["package_id"] == package_id:
remote_package = package
break
return remote_package
# Checks # Checks
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@pyqtSlot(str, result = bool) @pyqtSlot(str, result = bool)
@ -259,16 +292,13 @@ class Toolbox(QObject, Extension):
if local_package is None: if local_package is None:
return False return False
remote_package = None remote_package = self.getRemotePackage(package_id)
for package in self._metadata["packages"]:
if package["package_id"] == package_id:
remote_package = package
if remote_package is None: if remote_package is None:
return False return False
local_version = local_package["package_version"] local_version = Version(local_package["package_version"])
remote_version = remote_package["package_version"] remote_version = Version(remote_package["package_version"])
return Version(remote_version) > Version(local_version) return remote_version > local_version
@pyqtSlot(str, result = bool) @pyqtSlot(str, result = bool)
def isInstalled(self, package_id: str) -> bool: def isInstalled(self, package_id: str) -> bool:
@ -321,8 +351,8 @@ class Toolbox(QObject, Extension):
def resetDownload(self) -> None: def resetDownload(self) -> None:
if self._download_reply: if self._download_reply:
self._download_reply.abort()
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress) self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
self._download_reply.abort()
self._download_reply = None self._download_reply = None
self._download_request = None self._download_request = None
self.setDownloadProgress(0) self.setDownloadProgress(0)

View file

@ -8,7 +8,8 @@
"manufacturer": "101Hero", "manufacturer": "101Hero",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"platform": "101hero-platform.stl", "platform": "101hero-platform.stl",
"supports_usb_connection": true "supports_usb_connection": true,
"preferred_quality_type": "draft"
}, },
"overrides": { "overrides": {
@ -19,7 +20,6 @@
"machine_depth": { "default_value": 149.86 }, "machine_depth": { "default_value": 149.86 },
"machine_height": { "default_value": 99.822 }, "machine_height": { "default_value": 99.822 },
"machine_center_is_zero": { "default_value": true }, "machine_center_is_zero": { "default_value": true },
"layer_height": { "default_value": 0.2 },
"machine_nozzle_size": { "default_value": 0.4 }, "machine_nozzle_size": { "default_value": 0.4 },
"material_diameter": { "default_value": 1.75 }, "material_diameter": { "default_value": 1.75 },
"machine_head_with_fans_polygon": { "machine_head_with_fans_polygon": {

View file

@ -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",

View file

@ -8,7 +8,8 @@
"manufacturer": "3DMaker", "manufacturer": "3DMaker",
"file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj", "file_formats": "text/x-gcode;application/x-stl-ascii;application/x-stl-binary;application/x-wavefront-obj",
"icon": "icon_ultimaker2.png", "icon": "icon_ultimaker2.png",
"platform": "makerstarter_platform.stl" "platform": "makerstarter_platform.stl",
"preferred_quality_type": "draft"
}, },
"overrides": { "overrides": {
@ -49,9 +50,6 @@
"machine_nozzle_expansion_angle": { "machine_nozzle_expansion_angle": {
"default_value": 45 "default_value": 45
}, },
"layer_height": {
"default_value": 0.2
},
"layer_height_0": { "layer_height_0": {
"default_value": 0.2 "default_value": 0.2
}, },
@ -167,4 +165,4 @@
"default_value": 2 "default_value": 2
} }
} }
} }

View file

@ -675,7 +675,7 @@ msgstr "G 코드 수정"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12 #: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:12
msgctxt "@label" msgctxt "@label"
msgid "Support Blocker" msgid "Support Blocker"
msgstr "지지대 차단기" msgstr "서포트 차단기"
#: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:13 #: /home/ruben/Projects/Cura/plugins/SupportEraser/__init__.py:13
msgctxt "@info:tooltip" msgctxt "@info:tooltip"
@ -971,7 +971,7 @@ msgstr "펌웨어 업그레이드"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14 #: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/UMOCheckupMachineAction.py:14
msgctxt "@action" msgctxt "@action"
msgid "Checkup" msgid "Checkup"
msgstr "대조" msgstr "검사"
#: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21 #: /home/ruben/Projects/Cura/plugins/UltimakerMachineActions/BedLevelMachineAction.py:21
msgctxt "@action" msgctxt "@action"
@ -991,7 +991,7 @@ msgstr "내벽"
#: /home/ruben/Projects/Cura/cura/PrintInformation.py:98 #: /home/ruben/Projects/Cura/cura/PrintInformation.py:98
msgctxt "@tooltip" msgctxt "@tooltip"
msgid "Skin" msgid "Skin"
msgstr "외판" msgstr "스킨"
#: /home/ruben/Projects/Cura/cura/PrintInformation.py:99 #: /home/ruben/Projects/Cura/cura/PrintInformation.py:99
msgctxt "@tooltip" msgctxt "@tooltip"
@ -2348,7 +2348,7 @@ msgstr "밀리미터 단위의 빌드 플레이트에서 기저부 높이."
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:61 #: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:61
msgctxt "@action:label" msgctxt "@action:label"
msgid "Base (mm)" msgid "Base (mm)"
msgstr "바 (mm)" msgstr "바 (mm)"
#: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:79 #: /home/ruben/Projects/Cura/plugins/ImageReader/ConfigUI.qml:79
msgctxt "@info:tooltip" msgctxt "@info:tooltip"
@ -2420,7 +2420,7 @@ msgstr "서포터로 프린팅"
#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84 #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:84
msgctxt "@label" msgctxt "@label"
msgid "Don't support overlap with other models" msgid "Don't support overlap with other models"
msgstr "다른 모델과 오버랩되도록 지하지 않음" msgstr "다른 모델과 오버랩되도록 지하지 않음"
#: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92 #: /home/ruben/Projects/Cura/plugins/PerObjectSettingsTool/PerObjectSettingsPanel.qml:92
msgctxt "@label" msgctxt "@label"
@ -3631,7 +3631,7 @@ msgstr "버전: %1"
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56 #: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:56
msgctxt "@label" msgctxt "@label"
msgid "End-to-end solution for fused filament 3D printing." msgid "End-to-end solution for fused filament 3D printing."
msgstr "3D 인쇄를 위해 필라멘트를 한줄로 용." msgstr "3D 프린팅을 위한 엔드 투 엔트 솔루션."
#: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:69 #: /home/ruben/Projects/Cura/resources/qml/AboutDialog.qml:69
msgctxt "@info:credit" msgctxt "@info:credit"

View file

@ -433,7 +433,7 @@ msgstr "Repetier"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_firmware_retract label" msgctxt "machine_firmware_retract label"
msgid "Firmware Retraction" msgid "Firmware Retraction"
msgstr "펌웨어 제거" msgstr "펌웨어 리트렉션"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_firmware_retract description" msgctxt "machine_firmware_retract description"
@ -521,7 +521,7 @@ msgstr "노즐의 내경. 비표준 노즐 크기를 사용할 때 이 설정을
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords label" msgctxt "machine_use_extruder_offset_to_offset_coords label"
msgid "Offset With Extruder" msgid "Offset With Extruder"
msgstr "압출기로 오프셋" msgstr "익스트루더로 오프셋"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_use_extruder_offset_to_offset_coords description" msgctxt "machine_use_extruder_offset_to_offset_coords description"
@ -531,7 +531,7 @@ msgstr "익스트루더 오프셋을 좌표계에 적용하십시오."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "extruder_prime_pos_z label" msgctxt "extruder_prime_pos_z label"
msgid "Extruder Prime Z Position" msgid "Extruder Prime Z Position"
msgstr "압출기 프라임 Z 포지션" msgstr "익스트루더 프라임 Z 포지션"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "extruder_prime_pos_z description" msgctxt "extruder_prime_pos_z description"
@ -543,7 +543,7 @@ msgstr "프린팅가 시작될 때 노즐 위치의 Z 좌표입니다."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "extruder_prime_pos_abs label" msgctxt "extruder_prime_pos_abs label"
msgid "Absolute Extruder Prime Position" msgid "Absolute Extruder Prime Position"
msgstr "독립 압출 기 프라임 포지션" msgstr "독립 익스트루더 프라임 포지션"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "extruder_prime_pos_abs description" msgctxt "extruder_prime_pos_abs description"
@ -667,7 +667,7 @@ msgstr "Z 방향 모터의 기본 Jerk."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_jerk_e label" msgctxt "machine_max_jerk_e label"
msgid "Default Filament Jerk" msgid "Default Filament Jerk"
msgstr "기본 Filament Jerk" msgstr "기본 필라멘트 Jerk"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "machine_max_jerk_e description" msgctxt "machine_max_jerk_e description"
@ -1868,7 +1868,7 @@ msgstr "내부채움 패턴이 Y축을 따라 이 거리만큼 이동합니다."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "sub_div_rad_add label" msgctxt "sub_div_rad_add label"
msgid "Cubic Subdivision Shell" msgid "Cubic Subdivision Shell"
msgstr "입방 세분 내관" msgstr "입방 세분 "
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "sub_div_rad_add description" msgctxt "sub_div_rad_add description"
@ -2339,7 +2339,7 @@ msgctxt "material_flow description"
msgid "" msgid ""
"Flow compensation: the amount of material extruded is multiplied by this " "Flow compensation: the amount of material extruded is multiplied by this "
"value." "value."
msgstr "량 보상: 압출 된 재료의 양에 이 값을 곱합니다." msgstr "압출량 보상: 압출 된 재료의 양에 이 값을 곱합니다."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "material_flow_layer_0 label" msgctxt "material_flow_layer_0 label"
@ -2420,7 +2420,7 @@ msgstr "리트렉션 이동 중에 필라멘트가 프라이밍되는 속도입
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_extra_prime_amount label" msgctxt "retraction_extra_prime_amount label"
msgid "Retraction Extra Prime Amount" msgid "Retraction Extra Prime Amount"
msgstr "후퇴 Extra 초기 속도" msgstr "추가적인 리트렉션 정도"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_extra_prime_amount description" msgctxt "retraction_extra_prime_amount description"
@ -2433,7 +2433,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_min_travel label" msgctxt "retraction_min_travel label"
msgid "Retraction Minimum Travel" msgid "Retraction Minimum Travel"
msgstr "리트렉션 최소 움직임" msgstr "리트렉션 최소 이동"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_min_travel description" msgctxt "retraction_min_travel description"
@ -2724,7 +2724,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "speed_travel label" msgctxt "speed_travel label"
msgid "Travel Speed" msgid "Travel Speed"
msgstr "움직임 속도" msgstr "이동 속도"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "speed_travel description" msgctxt "speed_travel description"
@ -2841,7 +2841,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "speed_equalize_flow_max label" msgctxt "speed_equalize_flow_max label"
msgid "Maximum Speed for Flow Equalization" msgid "Maximum Speed for Flow Equalization"
msgstr "량 균등화를위한 최대 속도" msgstr "압출량 균등화를위한 최대 속도"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "speed_equalize_flow_max description" msgctxt "speed_equalize_flow_max description"
@ -3008,7 +3008,7 @@ msgstr "프라임 타워가 프린팅되는 가속도."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "acceleration_travel label" msgctxt "acceleration_travel label"
msgid "Travel Acceleration" msgid "Travel Acceleration"
msgstr "움직임 가속" msgstr "이동 가속"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "acceleration_travel description" msgctxt "acceleration_travel description"
@ -3038,7 +3038,7 @@ msgstr "초기 레이어 프린팅 중 가속도."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "acceleration_travel_layer_0 label" msgctxt "acceleration_travel_layer_0 label"
msgid "Initial Layer Travel Acceleration" msgid "Initial Layer Travel Acceleration"
msgstr "초기 레이어 움직임 가속도" msgstr "초기 레이어 이동 가속도"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "acceleration_travel_layer_0 description" msgctxt "acceleration_travel_layer_0 description"
@ -3229,7 +3229,7 @@ msgstr "프라임 타워가 프린팅되는 최대 순간 속도 변화."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "jerk_travel label" msgctxt "jerk_travel label"
msgid "Travel Jerk" msgid "Travel Jerk"
msgstr "움직임 Jerk" msgstr "이동 Jerk"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "jerk_travel description" msgctxt "jerk_travel description"
@ -3262,7 +3262,7 @@ msgstr "초기 층의 프린팅 중 최대 순간 속도 변화."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "jerk_travel_layer_0 label" msgctxt "jerk_travel_layer_0 label"
msgid "Initial Layer Travel Jerk" msgid "Initial Layer Travel Jerk"
msgstr "초기 레이어 움직임 Jerk" msgstr "초기 레이어 이동 Jerk"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "jerk_travel_layer_0 description" msgctxt "jerk_travel_layer_0 description"
@ -3284,12 +3284,12 @@ msgstr "스커트와 브림이 프린팅되는 최대 순간 속도 변화."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "travel label" msgctxt "travel label"
msgid "Travel" msgid "Travel"
msgstr "움직임" msgstr "이동"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "travel description" msgctxt "travel description"
msgid "travel" msgid "travel"
msgstr "움직임" msgstr "이동"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_combing label" msgctxt "retraction_combing label"
@ -3320,7 +3320,7 @@ msgstr "모두"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "retraction_combing option noskin" msgctxt "retraction_combing option noskin"
msgid "No Skin" msgid "No Skin"
msgstr "피부가 없다" msgstr "스킨이 없음"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "travel_retract_before_outer_wall label" msgctxt "travel_retract_before_outer_wall label"
@ -3349,7 +3349,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "travel_avoid_distance label" msgctxt "travel_avoid_distance label"
msgid "Travel Avoid Distance" msgid "Travel Avoid Distance"
msgstr "움직일 때 피하기 거리" msgstr "이동중 피하는 거리"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "travel_avoid_distance description" msgctxt "travel_avoid_distance description"
@ -3826,7 +3826,7 @@ msgstr "십자"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "zig_zaggify_support label" msgctxt "zig_zaggify_support label"
msgid "Connect Support Lines" msgid "Connect Support Lines"
msgstr "지지대 선 연결" msgstr "서포트 선 연결"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "zig_zaggify_support description" msgctxt "zig_zaggify_support description"
@ -3966,7 +3966,7 @@ msgstr "X/Y 방향에서 오버행으로부터 서포트까지의 거리. "
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_bottom_stair_step_height label" msgctxt "support_bottom_stair_step_height label"
msgid "Support Stair Step Height" msgid "Support Stair Step Height"
msgstr "계단 Step Height 지지대" msgstr "계단 Step Height 서포트"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_bottom_stair_step_height description" msgctxt "support_bottom_stair_step_height description"
@ -3998,7 +3998,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_join_distance label" msgctxt "support_join_distance label"
msgid "Support Join Distance" msgid "Support Join Distance"
msgstr "지지대 Join 거리" msgstr "서포트 Join 거리"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_join_distance description" msgctxt "support_join_distance description"
@ -4013,7 +4013,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_offset label" msgctxt "support_offset label"
msgid "Support Horizontal Expansion" msgid "Support Horizontal Expansion"
msgstr "수평 확장 지지대" msgstr "수평 확장 서포트"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_offset description" msgctxt "support_offset description"
@ -5879,7 +5879,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_zag_skip_count label" msgctxt "support_zag_skip_count label"
msgid "Support Chunk Line Count" msgid "Support Chunk Line Count"
msgstr "Chunk 라인 카운트 지지대" msgstr "Chunk 라인 카운트 서포트"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "support_zag_skip_count description" msgctxt "support_zag_skip_count description"
@ -6046,7 +6046,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "skin_alternate_rotation label" msgctxt "skin_alternate_rotation label"
msgid "Alternate Skin Rotation" msgid "Alternate Skin Rotation"
msgstr "대체 피부 회전" msgstr "대체 스킨 회전"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "skin_alternate_rotation description" msgctxt "skin_alternate_rotation description"
@ -6429,7 +6429,7 @@ msgid ""
"Flow compensation: the amount of material extruded is multiplied by this " "Flow compensation: the amount of material extruded is multiplied by this "
"value. Only applies to Wire Printing." "value. Only applies to Wire Printing."
msgstr "" msgstr ""
"량 보상 : 압출 된 재료의 양에 이 값을 곱합니다. 와이어 프린팅에만 적용됩니" "압출량 보상 : 압출 된 재료의 양에 이 값을 곱합니다. 와이어 프린팅에만 적용됩니"
"다." "다."
#: fdmprinter.def.json #: fdmprinter.def.json
@ -6440,7 +6440,7 @@ msgstr "WP 연결 흐름"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "wireframe_flow_connection description" msgctxt "wireframe_flow_connection description"
msgid "Flow compensation when going up or down. Only applies to Wire Printing." msgid "Flow compensation when going up or down. Only applies to Wire Printing."
msgstr "위 또는 아래로 이동할 때 량 보정. 와이어 프린팅에만 적용됩니다." msgstr "위 또는 아래로 이동할 때 압출량 보정. 와이어 프린팅에만 적용됩니다."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "wireframe_flow_flat label" msgctxt "wireframe_flow_flat label"
@ -6451,7 +6451,7 @@ msgstr "WP 플랫 플로우"
msgctxt "wireframe_flow_flat description" msgctxt "wireframe_flow_flat description"
msgid "" msgid ""
"Flow compensation when printing flat lines. Only applies to Wire Printing." "Flow compensation when printing flat lines. Only applies to Wire Printing."
msgstr "평평한 선을 프린팅 할 때 량 보정. 와이어 프린팅에만 적용됩니다." msgstr "평평한 선을 프린팅 할 때 압출량 보정. 와이어 프린팅에만 적용됩니다."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "wireframe_top_delay label" msgctxt "wireframe_top_delay label"
@ -6496,7 +6496,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "wireframe_up_half_speed label" msgctxt "wireframe_up_half_speed label"
msgid "WP Ease Upward" msgid "WP Ease Upward"
msgstr "WP는 쉽게 상향 조정" msgstr "WP 상향 조정"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "wireframe_up_half_speed description" msgctxt "wireframe_up_half_speed description"
@ -6761,7 +6761,7 @@ msgstr ""
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_wall_max_overhang label" msgctxt "bridge_wall_max_overhang label"
msgid "Bridge Wall Max Overhang" msgid "Bridge Wall Max Overhang"
msgstr "브리지 벽 최대 돌출" msgstr "브리지 벽 최대 오버행"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_wall_max_overhang description" msgctxt "bridge_wall_max_overhang description"
@ -6808,7 +6808,7 @@ msgstr "브릿지 벽이 프린팅되는 속도."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_wall_material_flow label" msgctxt "bridge_wall_material_flow label"
msgid "Bridge Wall Flow" msgid "Bridge Wall Flow"
msgstr "브리지 벽 량" msgstr "브리지 벽 압출량"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_wall_material_flow description" msgctxt "bridge_wall_material_flow description"
@ -6831,7 +6831,7 @@ msgstr "브릿지 스킨 층이 프린팅되는 속도."
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_skin_material_flow label" msgctxt "bridge_skin_material_flow label"
msgid "Bridge Skin Flow" msgid "Bridge Skin Flow"
msgstr "브리지 스킨 량" msgstr "브리지 스킨 압출량"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_skin_material_flow description" msgctxt "bridge_skin_material_flow description"
@ -6892,7 +6892,7 @@ msgstr "두번째 브릿지 스킨 레이어를 인쇄 할 때 사용할 인쇄
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_skin_material_flow_2 label" msgctxt "bridge_skin_material_flow_2 label"
msgid "Bridge Second Skin Flow" msgid "Bridge Second Skin Flow"
msgstr "브리지 두 번째 스킨 량" msgstr "브리지 두 번째 스킨 압출량"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_skin_material_flow_2 description" msgctxt "bridge_skin_material_flow_2 description"
@ -6939,7 +6939,7 @@ msgstr "세번째 브릿지 스킨 레이어를 인쇄 할 때 사용할 인쇄
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_skin_material_flow_3 label" msgctxt "bridge_skin_material_flow_3 label"
msgid "Bridge Third Skin Flow" msgid "Bridge Third Skin Flow"
msgstr "브리지 세 번째 스킨 량" msgstr "브리지 세 번째 스킨 압출량"
#: fdmprinter.def.json #: fdmprinter.def.json
msgctxt "bridge_skin_material_flow_3 description" msgctxt "bridge_skin_material_flow_3 description"

View file

@ -179,6 +179,15 @@ Item
height: visible ? UM.Theme.getSize("setting_control").height : 0 height: visible ? UM.Theme.getSize("setting_control").height : 0
Behavior on height { NumberAnimation { duration: 100 } } Behavior on height { NumberAnimation { duration: 100 } }
Timer
{
id: settingsSearchTimer
onTriggered: filter.editingFinished()
interval: 500
running: false
repeat: false
}
TextField TextField
{ {
id: filter; id: filter;
@ -201,6 +210,11 @@ Item
property bool lastFindingSettings: false property bool lastFindingSettings: false
onTextChanged: onTextChanged:
{
settingsSearchTimer.restart()
}
onEditingFinished:
{ {
definitionsModel.filter = {"i18n_label": "*" + text}; definitionsModel.filter = {"i18n_label": "*" + text};
findingSettings = (text.length > 0); findingSettings = (text.length > 0);

View file

@ -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

View file

@ -458,6 +458,7 @@
"toolbox_header": [1.0, 4.0], "toolbox_header": [1.0, 4.0],
"toolbox_progress_bar": [8.0, 0.5], "toolbox_progress_bar": [8.0, 0.5],
"toolbox_chart_row": [1.0, 2.0], "toolbox_chart_row": [1.0, 2.0],
"toolbox_action_button": [8.0, 2.5] "toolbox_action_button": [8.0, 2.5],
"toolbox_loader": [2.0, 2.0]
} }
} }

View file

@ -0,0 +1,13 @@
[general]
name = Aluminum
version = 4
definition = ultimaker_s5
[metadata]
setting_version = 4
type = variant
hardware_type = buildplate
[values]
material_bed_temperature = =default_material_bed_temperature + 10
machine_buildplate_type = aluminum