Merge remote-tracking branch 'origin/master' into CURA-5095_collect_user_modified_settings

This commit is contained in:
Lipu Fei 2018-09-05 11:31:21 +02:00
commit 082b9a4076
76 changed files with 570 additions and 190 deletions

1
.gitignore vendored
View File

@ -26,6 +26,7 @@ LC_MESSAGES
*.lprof *.lprof
*~ *~
*.qm *.qm
.directory
.idea .idea
cura.desktop cura.desktop

View File

@ -124,7 +124,7 @@ class BaseMaterialsModel(ListModel):
"description": metadata["description"], "description": metadata["description"],
"material": metadata["material"], "material": metadata["material"],
"color_name": metadata["color_name"], "color_name": metadata["color_name"],
"color_code": metadata["color_code"], "color_code": metadata.get("color_code", ""),
"density": metadata.get("properties", {}).get("density", ""), "density": metadata.get("properties", {}).get("density", ""),
"diameter": metadata.get("properties", {}).get("diameter", ""), "diameter": metadata.get("properties", {}).get("diameter", ""),
"approximate_diameter": metadata["approximate_diameter"], "approximate_diameter": metadata["approximate_diameter"],

View File

@ -6,10 +6,10 @@ from PyQt5.QtCore import Qt
from UM.Application import Application from UM.Application import Application
from UM.Logger import Logger from UM.Logger import Logger
from UM.Qt.ListModel import ListModel from UM.Qt.ListModel import ListModel
from UM.Settings.SettingFunction import SettingFunction
from cura.Machines.QualityManager import QualityGroup from cura.Machines.QualityManager import QualityGroup
# #
# QML Model for all built-in quality profiles. This model is used for the drop-down quality menu. # QML Model for all built-in quality profiles. This model is used for the drop-down quality menu.
# #
@ -106,4 +106,8 @@ class QualityProfilesDropDownMenuModel(ListModel):
container = global_stack.definition container = global_stack.definition
if container and container.hasProperty("layer_height", "value"): if container and container.hasProperty("layer_height", "value"):
layer_height = container.getProperty("layer_height", "value") layer_height = container.getProperty("layer_height", "value")
if isinstance(layer_height, SettingFunction):
layer_height = layer_height(global_stack)
return float(layer_height) return float(layer_height)

View File

@ -363,8 +363,19 @@ class QualityManager(QObject):
@pyqtSlot(QObject) @pyqtSlot(QObject)
def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup"): def removeQualityChangesGroup(self, quality_changes_group: "QualityChangesGroup"):
Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name) Logger.log("i", "Removing quality changes group [%s]", quality_changes_group.name)
removed_quality_changes_ids = set()
for node in quality_changes_group.getAllNodes(): for node in quality_changes_group.getAllNodes():
self._container_registry.removeContainer(node.getMetaDataEntry("id")) container_id = node.getMetaDataEntry("id")
self._container_registry.removeContainer(container_id)
removed_quality_changes_ids.add(container_id)
# Reset all machines that have activated this quality changes to empty.
for global_stack in self._container_registry.findContainerStacks(type = "machine"):
if global_stack.qualityChanges.getId() in removed_quality_changes_ids:
global_stack.qualityChanges = self._empty_quality_changes_container
for extruder_stack in self._container_registry.findContainerStacks(type = "extruder_train"):
if extruder_stack.qualityChanges.getId() in removed_quality_changes_ids:
extruder_stack.qualityChanges = self._empty_quality_changes_container
# #
# Rename a set of quality changes containers. Returns the new name. # Rename a set of quality changes containers. Returns the new name.

View File

@ -85,14 +85,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
def __init__(self) -> None: def __init__(self) -> None:
super().__init__() super().__init__()
MimeTypeDatabase.addMimeType(
MimeType(
name="application/x-curaproject+xml",
comment="Cura Project File",
suffixes=["curaproject.3mf"]
)
)
self._supported_extensions = [".3mf"] self._supported_extensions = [".3mf"]
self._dialog = WorkspaceDialog() self._dialog = WorkspaceDialog()
self._3mf_mesh_reader = None self._3mf_mesh_reader = None
@ -726,8 +718,6 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
nodes = [] nodes = []
base_file_name = os.path.basename(file_name) base_file_name = os.path.basename(file_name)
if base_file_name.endswith(".curaproject.3mf"):
base_file_name = base_file_name[:base_file_name.rfind(".curaproject.3mf")]
self.setWorkspaceName(base_file_name) self.setWorkspaceName(base_file_name)
return nodes return nodes

View File

@ -18,11 +18,7 @@ catalog = i18nCatalog("cura")
def getMetaData() -> Dict: def getMetaData() -> Dict:
# Workaround for osx not supporting double file extensions correctly.
if Platform.isOSX():
workspace_extension = "3mf" workspace_extension = "3mf"
else:
workspace_extension = "curaproject.3mf"
metaData = {} metaData = {}
if "3MFReader.ThreeMFReader" in sys.modules: if "3MFReader.ThreeMFReader" in sys.modules:

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for reading 3MF files.", "description": "Provides support for reading 3MF files.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -15,11 +15,7 @@ from UM.Platform import Platform
i18n_catalog = i18nCatalog("uranium") i18n_catalog = i18nCatalog("uranium")
def getMetaData(): def getMetaData():
# Workarround for osx not supporting double file extensions correctly.
if Platform.isOSX():
workspace_extension = "3mf" workspace_extension = "3mf"
else:
workspace_extension = "curaproject.3mf"
metaData = {} metaData = {}
@ -36,7 +32,7 @@ def getMetaData():
"output": [{ "output": [{
"extension": workspace_extension, "extension": workspace_extension,
"description": i18n_catalog.i18nc("@item:inlistbox", "Cura Project 3MF file"), "description": i18n_catalog.i18nc("@item:inlistbox", "Cura Project 3MF file"),
"mime_type": "application/x-curaproject+xml", "mime_type": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml",
"mode": ThreeMFWorkspaceWriter.ThreeMFWorkspaceWriter.OutputMode.BinaryMode "mode": ThreeMFWorkspaceWriter.ThreeMFWorkspaceWriter.OutputMode.BinaryMode
}] }]
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for writing 3MF files.", "description": "Provides support for writing 3MF files.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Shows changes since latest checked version.", "description": "Shows changes since latest checked version.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -2,7 +2,7 @@
"name": "CuraEngine Backend", "name": "CuraEngine Backend",
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"description": "Provides the link to the CuraEngine slicing backend.", "description": "Provides the link to the CuraEngine slicing backend.",
"api": 4, "api": 5,
"version": "1.0.0", "version": "1.0.0",
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for importing Cura profiles.", "description": "Provides support for importing Cura profiles.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for exporting Cura profiles.", "description": "Provides support for exporting Cura profiles.",
"api": 4, "api": 5,
"i18n-catalog":"cura" "i18n-catalog":"cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Checks for firmware updates.", "description": "Checks for firmware updates.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Reads g-code from a compressed archive.", "description": "Reads g-code from a compressed archive.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Writes g-code to a compressed archive.", "description": "Writes g-code to a compressed archive.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for importing profiles from g-code files.", "description": "Provides support for importing profiles from g-code files.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Victor Larchenko", "author": "Victor Larchenko",
"version": "1.0.0", "version": "1.0.0",
"description": "Allows loading and displaying G-code files.", "description": "Allows loading and displaying G-code files.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Writes g-code to a file.", "description": "Writes g-code to a file.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Enables ability to generate printable geometry from 2D image files.", "description": "Enables ability to generate printable geometry from 2D image files.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for importing profiles from legacy Cura versions.", "description": "Provides support for importing profiles from legacy Cura versions.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "fieldOfView", "author": "fieldOfView",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).", "description": "Provides a way to change machine settings (such as build volume, nozzle size, etc.).",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -2,7 +2,7 @@
"name": "Model Checker", "name": "Model Checker",
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "0.1", "version": "0.1",
"api": 4, "api": 5,
"description": "Checks models and print configuration for possible printing issues and give suggestions.", "description": "Checks models and print configuration for possible printing issues and give suggestions.",
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides a monitor stage in Cura.", "description": "Provides a monitor stage in Cura.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides the Per Model Settings.", "description": "Provides the Per Model Settings.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -2,7 +2,7 @@
"name": "Post Processing", "name": "Post Processing",
"author": "Ultimaker", "author": "Ultimaker",
"version": "2.2", "version": "2.2",
"api": 4, "api": 5,
"description": "Extension that allows for user created scripts for post processing", "description": "Extension that allows for user created scripts for post processing",
"catalog": "cura" "catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides a prepare stage in Cura.", "description": "Provides a prepare stage in Cura.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"description": "Provides removable drive hotplugging and writing support.", "description": "Provides removable drive hotplugging and writing support.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides the Simulation view.", "description": "Provides the Simulation view.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Submits anonymous slice info. Can be disabled through preferences.", "description": "Submits anonymous slice info. Can be disabled through preferences.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides a normal solid mesh view.", "description": "Provides a normal solid mesh view.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Creates an eraser mesh to block the printing of support in certain places", "description": "Creates an eraser mesh to block the printing of support in certain places",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -2,6 +2,6 @@
"name": "Toolbox", "name": "Toolbox",
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 5,
"description": "Find, manage and install new Cura packages." "description": "Find, manage and install new Cura packages."
} }

View File

@ -82,9 +82,16 @@ Item
} }
spacing: Math.floor(UM.Theme.getSize("narrow_margin").height) spacing: Math.floor(UM.Theme.getSize("narrow_margin").height)
width: childrenRect.width width: childrenRect.width
Label Label
{ {
text: catalog.i18nc("@label", "Contact") + ":" text: catalog.i18nc("@label", "Website") + ":"
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text_medium")
}
Label
{
text: catalog.i18nc("@label", "Email") + ":"
font: UM.Theme.getFont("very_small") font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text_medium") color: UM.Theme.getColor("text_medium")
} }
@ -100,18 +107,32 @@ Item
topMargin: UM.Theme.getSize("default_margin").height topMargin: UM.Theme.getSize("default_margin").height
} }
spacing: Math.floor(UM.Theme.getSize("narrow_margin").height) spacing: Math.floor(UM.Theme.getSize("narrow_margin").height)
Label
{
text:
{
if (details.website)
{
return "<a href=\"" + details.website + "\">" + details.website + "</a>"
}
return ""
}
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
}
Label Label
{ {
text: text:
{ {
if (details.email) if (details.email)
{ {
return "<a href=\"mailto:"+details.email+"\">"+details.name+"</a>" return "<a href=\"mailto:" + details.email + "\">" + details.email + "</a>"
}
else
{
return "<a href=\""+details.website+"\">"+details.name+"</a>"
} }
return ""
} }
font: UM.Theme.getFont("very_small") font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text") color: UM.Theme.getColor("text")

View File

@ -8,7 +8,18 @@ import UM 1.1 as UM
Item Item
{ {
id: base
property var packageData property var packageData
property var technicalDataSheetUrl: {
var link = undefined
if ("Technical Data Sheet" in packageData.links)
{
link = packageData.links["Technical Data Sheet"]
}
return link
}
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
height: visible ? childrenRect.height : 0 height: visible ? childrenRect.height : 0
visible: packageData.type == "material" && packageData.has_configs visible: packageData.type == "material" && packageData.has_configs
@ -132,4 +143,25 @@ Item
width: Math.floor(table.width * 0.1) width: Math.floor(table.width * 0.1)
} }
} }
Label
{
id: technical_data_sheet
anchors.top: table.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height / 2
visible: base.technicalDataSheetUrl !== undefined
text:
{
if (base.technicalDataSheetUrl !== undefined)
{
return "<a href='%1'>%2</a>".arg(base.technicalDataSheetUrl).arg("Technical Data Sheet")
}
return ""
}
font: UM.Theme.getFont("very_small")
color: UM.Theme.getColor("text")
linkColor: UM.Theme.getColor("text_link")
onLinkActivated: Qt.openUrlExternally(link)
}
} }

View File

@ -9,7 +9,7 @@ import UM 1.1 as UM
Item Item
{ {
property int packageCount: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getTotalNumberOfPackagesByAuthor(model.id) : 1 property int packageCount: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getTotalNumberOfMaterialPackagesByAuthor(model.id) : 1
property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0) property int installedPackages: (toolbox.viewCategory == "material" && model.type === undefined) ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
height: childrenRect.height height: childrenRect.height
Layout.alignment: Qt.AlignTop | Qt.AlignLeft Layout.alignment: Qt.AlignTop | Qt.AlignLeft

View File

@ -30,7 +30,7 @@ ScrollView
id: allPlugins id: allPlugins
width: parent.width width: parent.width
heading: toolbox.viewCategory == "material" ? catalog.i18nc("@label", "Community Contributions") : catalog.i18nc("@label", "Community Plugins") heading: toolbox.viewCategory == "material" ? catalog.i18nc("@label", "Community Contributions") : catalog.i18nc("@label", "Community Plugins")
model: toolbox.viewCategory == "material" ? toolbox.authorsModel : toolbox.packagesModel model: toolbox.viewCategory == "material" ? toolbox.materialsAvailableModel : toolbox.pluginsAvailableModel
} }
ToolboxDownloadsGrid ToolboxDownloadsGrid

View File

@ -9,7 +9,7 @@ import UM 1.1 as UM
Rectangle Rectangle
{ {
property int packageCount: toolbox.viewCategory == "material" ? toolbox.getTotalNumberOfPackagesByAuthor(model.id) : 1 property int packageCount: toolbox.viewCategory == "material" ? toolbox.getTotalNumberOfMaterialPackagesByAuthor(model.id) : 1
property int installedPackages: toolbox.viewCategory == "material" ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0) property int installedPackages: toolbox.viewCategory == "material" ? toolbox.getNumberOfInstalledPackagesByAuthor(model.id) : (toolbox.isInstalled(model.id) ? 1 : 0)
id: tileBase id: tileBase
width: UM.Theme.getSize("toolbox_thumbnail_large").width + (2 * UM.Theme.getSize("default_lining").width) width: UM.Theme.getSize("toolbox_thumbnail_large").width + (2 * UM.Theme.getSize("default_lining").width)

View File

@ -5,9 +5,13 @@ import re
from typing import Dict from typing import Dict
from PyQt5.QtCore import Qt, pyqtProperty from PyQt5.QtCore import Qt, pyqtProperty
from UM.Logger import Logger
from UM.Qt.ListModel import ListModel from UM.Qt.ListModel import ListModel
from .ConfigsModel import ConfigsModel from .ConfigsModel import ConfigsModel
## Model that holds cura packages. By setting the filter property the instances held by this model can be changed. ## Model that holds cura packages. By setting the filter property the instances held by this model can be changed.
class PackagesModel(ListModel): class PackagesModel(ListModel):
def __init__(self, parent = None): def __init__(self, parent = None):
@ -34,6 +38,8 @@ class PackagesModel(ListModel):
self.addRoleName(Qt.UserRole + 17, "supported_configs") self.addRoleName(Qt.UserRole + 17, "supported_configs")
self.addRoleName(Qt.UserRole + 18, "download_count") self.addRoleName(Qt.UserRole + 18, "download_count")
self.addRoleName(Qt.UserRole + 19, "tags") self.addRoleName(Qt.UserRole + 19, "tags")
self.addRoleName(Qt.UserRole + 20, "links")
self.addRoleName(Qt.UserRole + 21, "website")
# List of filters for queries. The result is the union of the each list of results. # List of filters for queries. The result is the union of the each list of results.
self._filter = {} # type: Dict[str, str] self._filter = {} # type: Dict[str, str]
@ -45,10 +51,16 @@ class PackagesModel(ListModel):
def _update(self): def _update(self):
items = [] items = []
for package in self._metadata: if self._metadata is None:
Logger.logException("w", "Failed to load packages for Toolbox")
self.setItems(items)
return
for package in self._metadata:
has_configs = False has_configs = False
configs_model = None configs_model = None
links_dict = {}
if "data" in package: if "data" in package:
if "supported_configs" in package["data"]: if "supported_configs" in package["data"]:
if len(package["data"]["supported_configs"]) > 0: if len(package["data"]["supported_configs"]) > 0:
@ -56,6 +68,11 @@ class PackagesModel(ListModel):
configs_model = ConfigsModel() configs_model = ConfigsModel()
configs_model.setConfigs(package["data"]["supported_configs"]) configs_model.setConfigs(package["data"]["supported_configs"])
# Links is a list of dictionaries with "title" and "url". Convert this list into a dict so it's easier
# to process.
link_list = package['data']['links'] if 'links' in package['data'] else []
links_dict = {d["title"]: d["url"] for d in link_list}
if "author_id" not in package["author"] or "display_name" not in package["author"]: if "author_id" not in package["author"] or "display_name" not in package["author"]:
package["author"]["author_id"] = "" package["author"]["author_id"] = ""
package["author"]["display_name"] = "" package["author"]["display_name"] = ""
@ -80,17 +97,19 @@ class PackagesModel(ListModel):
"has_configs": has_configs, "has_configs": has_configs,
"supported_configs": configs_model, "supported_configs": configs_model,
"download_count": package["download_count"] if "download_count" in package else 0, "download_count": package["download_count"] if "download_count" in package else 0,
"tags": package["tags"] if "tags" in package else [] "tags": package["tags"] if "tags" in package else [],
"links": links_dict,
"website": package["website"] if "website" in package else None,
}) })
# Filter on all the key-word arguments. # Filter on all the key-word arguments.
for key, value in self._filter.items(): for key, value in self._filter.items():
if key is "tags": if key is "tags":
key_filter = lambda item, value = value: value in item["tags"] key_filter = lambda item, v = value: v in item["tags"]
elif "*" in value: elif "*" in value:
key_filter = lambda candidate, key = key, value = value: self._matchRegExp(candidate, key, value) key_filter = lambda candidate, k = key, v = value: self._matchRegExp(candidate, k, v)
else: else:
key_filter = lambda candidate, key = key, value = value: self._matchString(candidate, key, value) key_filter = lambda candidate, k = key, v = value: self._matchString(candidate, k, v)
items = filter(key_filter, items) items = filter(key_filter, items)
# Execute all filters. # Execute all filters.

View File

@ -83,7 +83,7 @@ class Toolbox(QObject, Extension):
"plugins_available": PackagesModel(self), "plugins_available": PackagesModel(self),
"plugins_installed": PackagesModel(self), "plugins_installed": PackagesModel(self),
"materials_showcase": AuthorsModel(self), "materials_showcase": AuthorsModel(self),
"materials_available": PackagesModel(self), "materials_available": AuthorsModel(self),
"materials_installed": PackagesModel(self), "materials_installed": PackagesModel(self),
"materials_generic": PackagesModel(self) "materials_generic": PackagesModel(self)
} # type: Dict[str, ListModel] } # type: Dict[str, ListModel]
@ -514,10 +514,12 @@ class Toolbox(QObject, Extension):
count += 1 count += 1
return count return count
# This slot is only used to get the number of material packages by author, not any other type of packages.
@pyqtSlot(str, result = int) @pyqtSlot(str, result = int)
def getTotalNumberOfPackagesByAuthor(self, author_id: str) -> int: def getTotalNumberOfMaterialPackagesByAuthor(self, author_id: str) -> int:
count = 0 count = 0
for package in self._metadata["materials_available"]: for package in self._metadata["packages"]:
if package["package_type"] == "material":
if package["author"]["author_id"] == author_id: if package["author"]["author_id"] == author_id:
count += 1 count += 1
return count return count
@ -606,8 +608,21 @@ class Toolbox(QObject, Extension):
self.resetDownload() self.resetDownload()
return return
# HACK: These request are not handled independently at this moment, but together from the "packages" call
do_not_handle = [
"materials_available",
"materials_showcase",
"plugins_available",
"plugins_showcase",
]
if reply.operation() == QNetworkAccessManager.GetOperation: if reply.operation() == QNetworkAccessManager.GetOperation:
for type, url in self._request_urls.items(): for type, url in self._request_urls.items():
# HACK: Do nothing because we'll handle these from the "packages" call
if type in do_not_handle:
return
if reply.url() == url: if reply.url() == url:
if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200: if reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 200:
try: try:
@ -624,17 +639,6 @@ class Toolbox(QObject, Extension):
Logger.log("e", "Could not find the %s model.", type) Logger.log("e", "Could not find the %s model.", type)
break break
# HACK: Eventually get rid of the code from here...
if type is "plugins_showcase" or type is "materials_showcase":
self._metadata["plugins_showcase"] = json_data["data"]["plugin"]["packages"]
self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"])
self._metadata["materials_showcase"] = json_data["data"]["material"]["authors"]
self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"])
else:
# ...until here.
# This hack arises for multiple reasons but the main
# one is because there are not separate API calls
# for different kinds of showcases.
self._metadata[type] = json_data["data"] self._metadata[type] = json_data["data"]
self._models[type].setMetadata(self._metadata[type]) self._models[type].setMetadata(self._metadata[type])
@ -642,6 +646,8 @@ class Toolbox(QObject, Extension):
# TODO: Make multiple API calls in the future to handle this # TODO: Make multiple API calls in the future to handle this
if type is "packages": if type is "packages":
self._models[type].setFilter({"type": "plugin"}) self._models[type].setFilter({"type": "plugin"})
self.buildMaterialsModels()
self.buildPluginsModels()
if type is "authors": if type is "authors":
self._models[type].setFilter({"package_types": "material"}) self._models[type].setFilter({"package_types": "material"})
if type is "materials_generic": if type is "materials_generic":
@ -755,6 +761,10 @@ class Toolbox(QObject, Extension):
def pluginsShowcaseModel(self) -> PackagesModel: def pluginsShowcaseModel(self) -> PackagesModel:
return cast(PackagesModel, self._models["plugins_showcase"]) return cast(PackagesModel, self._models["plugins_showcase"])
@pyqtProperty(QObject, notify = metadataChanged)
def pluginsAvailableModel(self) -> PackagesModel:
return cast(PackagesModel, self._models["plugins_available"])
@pyqtProperty(QObject, notify = metadataChanged) @pyqtProperty(QObject, notify = metadataChanged)
def pluginsInstalledModel(self) -> PackagesModel: def pluginsInstalledModel(self) -> PackagesModel:
return cast(PackagesModel, self._models["plugins_installed"]) return cast(PackagesModel, self._models["plugins_installed"])
@ -763,6 +773,10 @@ class Toolbox(QObject, Extension):
def materialsShowcaseModel(self) -> AuthorsModel: def materialsShowcaseModel(self) -> AuthorsModel:
return cast(AuthorsModel, self._models["materials_showcase"]) return cast(AuthorsModel, self._models["materials_showcase"])
@pyqtProperty(QObject, notify = metadataChanged)
def materialsAvailableModel(self) -> AuthorsModel:
return cast(AuthorsModel, self._models["materials_available"])
@pyqtProperty(QObject, notify = metadataChanged) @pyqtProperty(QObject, notify = metadataChanged)
def materialsInstalledModel(self) -> PackagesModel: def materialsInstalledModel(self) -> PackagesModel:
return cast(PackagesModel, self._models["materials_installed"]) return cast(PackagesModel, self._models["materials_installed"])
@ -798,3 +812,46 @@ class Toolbox(QObject, Extension):
return return
self._models[model_type].setFilter({}) self._models[model_type].setFilter({})
self.filterChanged.emit() self.filterChanged.emit()
# HACK(S):
# --------------------------------------------------------------------------
def buildMaterialsModels(self) -> None:
self._metadata["materials_showcase"] = []
self._metadata["materials_available"] = []
processed_authors = [] # type: List[str]
for item in self._metadata["packages"]:
if item["package_type"] == "material":
author = item["author"]
if author["author_id"] in processed_authors:
continue
if "showcase" in item["tags"]:
self._metadata["materials_showcase"].append(author)
else:
self._metadata["materials_available"].append(author)
processed_authors.append(author["author_id"])
self._models["materials_showcase"].setMetadata(self._metadata["materials_showcase"])
self._models["materials_available"].setMetadata(self._metadata["materials_available"])
def buildPluginsModels(self) -> None:
self._metadata["plugins_showcase"] = []
self._metadata["plugins_available"] = []
for item in self._metadata["packages"]:
if item["package_type"] == "plugin":
if "showcase" in item["tags"]:
self._metadata["plugins_showcase"].append(item)
else:
self._metadata["plugins_available"].append(item)
self._models["plugins_showcase"].setMetadata(self._metadata["plugins_showcase"])
self._models["plugins_available"].setMetadata(self._metadata["plugins_available"])

View File

@ -13,6 +13,7 @@ from UM.PluginRegistry import PluginRegistry #To get the g-code writer.
from PyQt5.QtCore import QBuffer from PyQt5.QtCore import QBuffer
from cura.Snapshot import Snapshot from cura.Snapshot import Snapshot
from cura.Utils.Threading import call_on_qt_thread
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
catalog = i18nCatalog("cura") catalog = i18nCatalog("cura")
@ -29,6 +30,11 @@ class UFPWriter(MeshWriter):
Logger.log("d", "Creating thumbnail image...") Logger.log("d", "Creating thumbnail image...")
self._snapshot = Snapshot.snapshot(width = 300, height = 300) self._snapshot = Snapshot.snapshot(width = 300, height = 300)
# This needs to be called on the main thread (Qt thread) because the serialization of material containers can
# trigger loading other containers. Because those loaded containers are QtObjects, they must be created on the
# Qt thread. The File read/write operations right now are executed on separated threads because they are scheduled
# by the Job class.
@call_on_qt_thread
def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode): def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode):
archive = VirtualFile() archive = VirtualFile()
archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly) archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)
@ -60,5 +66,50 @@ class UFPWriter(MeshWriter):
else: else:
Logger.log("d", "Thumbnail not created, cannot save it") Logger.log("d", "Thumbnail not created, cannot save it")
# Store the material.
application = Application.getInstance()
machine_manager = application.getMachineManager()
material_manager = application.getMaterialManager()
global_stack = machine_manager.activeMachine
material_extension = "xml.fdm_material"
material_mime_type = "application/x-ultimaker-material-profile"
try:
archive.addContentType(extension = material_extension, mime_type = material_mime_type)
except:
Logger.log("w", "The material extension: %s was already added", material_extension)
added_materials = []
for extruder_stack in global_stack.extruders.values():
material = extruder_stack.material
material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material"
material_file_name = "/Materials/" + material_file_name
#Same material cannot be added
if material_file_name in added_materials:
continue
material_root_id = material.getMetaDataEntry("base_file")
material_group = material_manager.getMaterialGroup(material_root_id)
if material_group is None:
Logger.log("e", "Cannot find material container with root id [%s]", material_root_id)
return False
material_container = material_group.root_material_node.getContainer()
try:
serialized_material = material_container.serialize()
except NotImplementedError:
Logger.log("e", "Unable serialize material container with root id: %s", material_root_id)
return False
material_file = archive.getStream(material_file_name)
material_file.write(serialized_material.encode("UTF-8"))
archive.addRelation(virtual_path = material_file_name,
relation_type = "http://schemas.ultimaker.org/package/2018/relationships/material",
origin = "/3D/model.gcode")
added_materials.append(material_file_name)
archive.close() archive.close()
return True return True

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides support for writing Ultimaker Format Packages.", "description": "Provides support for writing Ultimaker Format Packages.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -364,7 +364,6 @@ Cura.MachineAction
{ {
id: addressField id: addressField
width: parent.width width: parent.width
maximumLength: 40
validator: RegExpValidator validator: RegExpValidator
{ {
regExp: /[a-zA-Z0-9\.\-\_]*/ regExp: /[a-zA-Z0-9\.\-\_]*/

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"description": "Manages network connections to Ultimaker 3 printers.", "description": "Manages network connections to Ultimaker 3 printers.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -326,7 +326,7 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
if self._firmware_name is None: if self._firmware_name is None:
self.sendCommand("M115") self.sendCommand("M115")
if (b"ok " in line and b"T:" in line) or b"ok T:" in line or line.startswith(b"T:") or b"ok B:" in line or line.startswith(b"B:"): # Temperature message. 'T:' for extruder and 'B:' for bed if (b"ok " in line and b"T:" in line) or line.startswith(b"T:") or b"ok B:" in line or line.startswith(b"B:"): # Temperature message. 'T:' for extruder and 'B:' for bed
extruder_temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line) extruder_temperature_matches = re.findall(b"T(\d*): ?([\d\.]+) ?\/?([\d\.]+)?", line)
# Update all temperature values # Update all temperature values
matched_extruder_nrs = [] matched_extruder_nrs = []

View File

@ -2,7 +2,7 @@
"name": "USB printing", "name": "USB printing",
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"api": 4, "api": 5,
"description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.", "description": "Accepts G-Code and sends them to a printer. Plugin can also update firmware.",
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).", "description": "Provides machine actions for Ultimaker machines (such as bed leveling wizard, selecting upgrades, etc.).",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Ask the user once if he/she agrees with our license.", "description": "Ask the user once if he/she agrees with our license.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.1 to Cura 2.2.", "description": "Upgrades configurations from Cura 2.1 to Cura 2.2.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.2 to Cura 2.4.", "description": "Upgrades configurations from Cura 2.2 to Cura 2.4.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.5 to Cura 2.6.", "description": "Upgrades configurations from Cura 2.5 to Cura 2.6.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.6 to Cura 2.7.", "description": "Upgrades configurations from Cura 2.6 to Cura 2.7.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 2.7 to Cura 3.0.", "description": "Upgrades configurations from Cura 2.7 to Cura 3.0.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 3.0 to Cura 3.1.", "description": "Upgrades configurations from Cura 3.0 to Cura 3.1.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 3.2 to Cura 3.3.", "description": "Upgrades configurations from Cura 3.2 to Cura 3.3.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 3.3 to Cura 3.4.", "description": "Upgrades configurations from Cura 3.3 to Cura 3.4.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Upgrades configurations from Cura 3.4 to Cura 4.0.", "description": "Upgrades configurations from Cura 3.4 to Cura 4.0.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Seva Alekseyev", "author": "Seva Alekseyev",
"version": "0.5.0", "version": "0.5.0",
"description": "Provides support for reading X3D files.", "description": "Provides support for reading X3D files.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides the X-Ray view.", "description": "Provides the X-Ray view.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -3,6 +3,6 @@
"author": "Ultimaker B.V.", "author": "Ultimaker B.V.",
"version": "1.0.0", "version": "1.0.0",
"description": "Provides capabilities to read and write XML-based material profiles.", "description": "Provides capabilities to read and write XML-based material profiles.",
"api": 4, "api": 5,
"i18n-catalog": "cura" "i18n-catalog": "cura"
} }

View File

@ -17,8 +17,8 @@
"overrides": { "overrides": {
"machine_name": { "default_value": "BQ Hephestos 2" }, "machine_name": { "default_value": "BQ Hephestos 2" },
"machine_start_gcode": { "default_value": "; -- START GCODE --\nM104 S{material_print_temperature} ; Heat up extruder while leveling\nM800 ; Custom GCODE to fire start print procedure\nM109 S{material_print_temperature} ; Makes sure the temperature is correct before printing\n; -- end of START GCODE --" }, "machine_start_gcode": { "default_value": "; -- START GCODE --\nM104 S{material_print_temperature}\nG28 ; Zero-ing position\nG29 ; Auto bed-leveling\nG0 X4 Y297 Z15 F4000 ; Fast move to BQ's start position\nG90 ; Set to Absolute Positioning\nG92 E0 ; Reset extruder 0\nG1 F1800 ; Set default feedrate\nM109 S{material_print_temperature} ; Makes sure the temperature is correct before printing\n; -- end of START GCODE --" },
"machine_end_gcode": { "default_value": "; -- END GCODE --\nM801 ; Custom GCODE to fire end print procedure\n; -- end of END GCODE --" }, "machine_end_gcode": { "default_value": "; -- END GCODE --\nM801 ; Marlin G-CODE to fire end print procedure\n; -- end of END GCODE --" },
"machine_width": { "default_value": 210 }, "machine_width": { "default_value": 210 },
"machine_depth": { "default_value": 297 }, "machine_depth": { "default_value": 297 },
"machine_height": { "default_value": 220 }, "machine_height": { "default_value": 220 },

View File

@ -1819,9 +1819,9 @@
"unit": "mm", "unit": "mm",
"type": "float", "type": "float",
"default_value": 0.1, "default_value": 0.1,
"minimum_value": "resolveOrValue('layer_height')", "minimum_value": "resolveOrValue('layer_height') if infill_line_distance > 0 else -999999",
"maximum_value_warning": "0.75 * machine_nozzle_size", "maximum_value_warning": "0.75 * machine_nozzle_size",
"maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8)", "maximum_value": "resolveOrValue('layer_height') * (1.45 if spaghetti_infill_enabled else 8) if infill_line_distance > 0 else 999999",
"value": "resolveOrValue('layer_height')", "value": "resolveOrValue('layer_height')",
"enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled", "enabled": "infill_sparse_density > 0 and not spaghetti_infill_enabled",
"limit_to_extruder": "infill_extruder_nr", "limit_to_extruder": "infill_extruder_nr",
@ -3875,6 +3875,19 @@
} }
} }
}, },
"support_infill_angle":
{
"label": "Support Infill Line Direction",
"description": "Orientation of the infill pattern for supports. The support infill pattern is rotated in the horizontal plane.",
"unit": "°",
"type": "float",
"minimum_value": "-180",
"maximum_value": "180",
"default_value": 0,
"enabled": "support_enable and support_pattern != 'concentric' and support_infill_rate > 0",
"settable_per_mesh": false,
"settable_per_extruder": true
},
"support_z_distance": "support_z_distance":
{ {
"label": "Support Z Distance", "label": "Support Z Distance",

View File

@ -4,13 +4,14 @@
"inherits": "fdmprinter", "inherits": "fdmprinter",
"metadata": { "metadata": {
"visible": true, "visible": true,
"author": "fieldOfView", "author": "Peopoly",
"manufacturer": "Peopoly", "manufacturer": "Peopoly",
"file_formats": "text/x-gcode", "file_formats": "text/x-gcode",
"has_machine_quality": true, "has_machine_quality": true,
"has_materials": false, "has_materials": false,
"machine_extruder_trains": "platform": "moai.obj",
{ "platform_texture": "moai.jpg",
"machine_extruder_trains": {
"0": "peopoly_moai_extruder_0" "0": "peopoly_moai_extruder_0"
} }
}, },
@ -46,7 +47,6 @@
"machine_end_gcode": { "machine_end_gcode": {
"default_value": "M104 S0\nM140 S0\nG28 X0 Y0\nM84" "default_value": "M104 S0\nM140 S0\nG28 X0 Y0\nM84"
}, },
"line_width": { "line_width": {
"minimum_value_warning": "machine_nozzle_size" "minimum_value_warning": "machine_nozzle_size"
}, },
@ -75,7 +75,14 @@
"value": "0.1" "value": "0.1"
}, },
"top_bottom_thickness": { "top_bottom_thickness": {
"minimum_value_warning": "0.1" "minimum_value_warning": "0.1",
"value": "0.1"
},
"top_thickness": {
"minimum_value_warning": "resolveOrValue('layer_height')"
},
"bottom_thickness": {
"minimum_value_warning": "resolveOrValue('layer_height')"
}, },
"infill_sparse_thickness": { "infill_sparse_thickness": {
"maximum_value_warning": "0.5" "maximum_value_warning": "0.5"
@ -102,24 +109,23 @@
"value": "speed_print" "value": "speed_print"
}, },
"speed_travel": { "speed_travel": {
"value": "300" "value": 150
}, },
"speed_travel_layer_0": { "speed_travel_layer_0": {
"value": "300" "value": 150
}, },
"speed_layer_0": { "speed_layer_0": {
"value": "5" "value": 5
}, },
"speed_slowdown_layers": { "speed_slowdown_layers": {
"value": "2" "value": 3
}, },
"infill_overlap": { "infill_overlap": {
"value": "15" "value": 15
}, },
"adhesion_type": { "adhesion_type": {
"value": "\"none\"" "value": "'none'"
}, },
"acceleration_enabled": { "acceleration_enabled": {
"value": "False" "value": "False"
}, },
@ -139,6 +145,10 @@
"enabled": false, "enabled": false,
"value": "False" "value": "False"
}, },
"cool_fan_speed_min": {
"enabled": false,
"value": 0
},
"retraction_enable": { "retraction_enable": {
"enabled": false, "enabled": false,
"value": "False" "value": "False"
@ -148,7 +158,8 @@
"value": "'off'" "value": "'off'"
}, },
"retract_at_layer_change": { "retract_at_layer_change": {
"enabled": false "enabled": false,
"value": false
}, },
"cool_min_layer_time_fan_speed_max": { "cool_min_layer_time_fan_speed_max": {
"enabled": false "enabled": false
@ -158,6 +169,117 @@
}, },
"cool_fan_full_layer": { "cool_fan_full_layer": {
"enabled": false "enabled": false
},
"minimum_polygon_circumference": {
"value": "0.1"
},
"meshfix_maximum_resolution": {
"value": "0.005"
},
"skin_outline_count": {
"value": 0
},
"travel_compensate_overlapping_walls_enabled": {
"value": "False"
},
"travel_compensate_overlapping_walls_0_enabled": {
"value": "False"
},
"travel_compensate_overlapping_walls_x_enabled": {
"value": "False"
},
"wall_0_wipe_dist": {
"value": "machine_nozzle_size / 3"
},
"wall_thickness": {
"value": 0.5
},
"infill_sparse_density": {
"value": 70
},
"infill_pattern": {
"value": "'lines'"
},
"infill_angles": {
"value": "[0,90]"
},
"cool_min_layer_time": {
"enabled": false,
"value": 0
},
"cool_min_speed": {
"enabled": false,
"value": 0
},
"cool_lift_head": {
"enabled": false,
"value": "False"
},
"material_flow": {
"enabled": false
},
"material_flow_layer_0": {
"enabled": false
},
"speed_equalize_flow_enabled": {
"enabled": false,
"value": "False"
},
"draft_shield_enabled": {
"enabled": false,
"value": "False"
},
"z_seam_corner": {
"value": "'z_seam_corner_none'"
},
"z_seam_type": {
"value": "'shortest'"
},
"skin_no_small_gaps_heuristic": {
"value": "False"
},
"ironing_enabled": {
"enabled": false,
"value": "False"
},
"skin_overlap": {
"value": 5
},
"infill_wipe_dist": {
"value": 0
},
"expand_skins_expand_distance": {
"value": "( wall_line_width_0 + (wall_line_count - 1) * wall_line_width_x ) / 2"
},
"max_feedrate_z_override": {
"value": 0,
"enabled": false
},
"flow_rate_max_extrusion_offset": {
"enabled": false
},
"flow_rate_extrusion_offset_factor": {
"enabled": false
},
"adaptive_layer_height_enabled": {
"value": "False",
"enabled": false
},
"bridge_settings_enabled": {
"value": "False",
"enabled": false
},
"acceleration_enabled": {
"value": "False",
"enabled": false
},
"relative_extrusion": {
"value": "False",
"enabled": false
},
"coasting_enable": {
"value": "False",
"enabled": false
} }
} }
} }

View File

@ -11,6 +11,9 @@
"overrides": { "overrides": {
"extruder_nr": { "default_value": 0 }, "extruder_nr": { "default_value": 0 },
"machine_nozzle_size": { "default_value": 0.067 }, "machine_nozzle_size": { "default_value": 0.067 },
"material_diameter": { "default_value": 1.75 } "material_diameter": {
"enabled": false,
"default_value": 1.75
}
} }
} }

BIN
resources/images/moai.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

32
resources/meshes/moai.obj Normal file
View File

@ -0,0 +1,32 @@
# OBJ written from C:\Users\Flo\Desktop\Cura_FILES\moai.obj
mtllib moai.mtl
# Units millimeters
g Mesh
v 65 -65 0
v -65 -65 0
v -65 65 0
v 65 65 0
v 65 -65 0
v -65 -65 0
v -65 65 0
v 65 65 0
v -65 65 18.8383
v 65 65 18.8383
vn 0 0 1
vn 1 0 0
vn -1 0 0
vt 0.0975501 1
vt 1 1
vt 1 0.0977239
vt 0.0975501 0.0977239
vt 0.0186426 0.870052
vt 0.0736426 0.870052
vt 0.0186426 0.815052
vt 0.0214764 0.912057
vt 0.0764764 0.967057
vt 0.0214764 0.967057
usemtl red
f 1/1/1 4/2/1 3/3/1 2/4/1
f 7/5/2 9/6/2 6/7/2
f 5/8/3 10/9/3 8/10/3

View File

@ -110,28 +110,28 @@ Item
Action Action
{ {
id: view3DCameraAction; id: view3DCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","&3D View"); text: catalog.i18nc("@action:inmenu menubar:view","3D View");
onTriggered: UM.Controller.rotateView("3d", 0); onTriggered: UM.Controller.rotateView("3d", 0);
} }
Action Action
{ {
id: viewFrontCameraAction; id: viewFrontCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","&Front View"); text: catalog.i18nc("@action:inmenu menubar:view","Front View");
onTriggered: UM.Controller.rotateView("home", 0); onTriggered: UM.Controller.rotateView("home", 0);
} }
Action Action
{ {
id: viewTopCameraAction; id: viewTopCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","&Top View"); text: catalog.i18nc("@action:inmenu menubar:view","Top View");
onTriggered: UM.Controller.rotateView("y", 90); onTriggered: UM.Controller.rotateView("y", 90);
} }
Action Action
{ {
id: viewLeftSideCameraAction; id: viewLeftSideCameraAction;
text: catalog.i18nc("@action:inmenu menubar:view","&Left Side View"); text: catalog.i18nc("@action:inmenu menubar:view","Left Side View");
onTriggered: UM.Controller.rotateView("x", 90); onTriggered: UM.Controller.rotateView("x", 90);
} }
@ -229,23 +229,13 @@ Item
Action Action
{ {
id: deleteSelectionAction; id: deleteSelectionAction;
text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount); text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete Selected Model", "Delete Selected Models", UM.Selection.selectionCount);
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection; enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection;
iconName: "edit-delete"; iconName: "edit-delete";
shortcut: StandardKey.Delete; shortcut: StandardKey.Delete;
onTriggered: CuraActions.deleteSelection(); onTriggered: CuraActions.deleteSelection();
} }
Action //Also add backspace as the same function as delete because on Macintosh keyboards the button called "delete" is actually a backspace, and the user expects it to function as a delete.
{
id: backspaceSelectionAction
text: catalog.i18ncp("@action:inmenu menubar:edit", "Delete &Selected Model", "Delete &Selected Models", UM.Selection.selectionCount)
enabled: UM.Controller.toolsEnabled && UM.Selection.hasSelection
iconName: "edit-delete"
shortcut: StandardKey.Backspace
onTriggered: CuraActions.deleteSelection()
}
Action Action
{ {
id: centerSelectionAction; id: centerSelectionAction;
@ -328,7 +318,7 @@ Item
Action Action
{ {
id: selectAllAction; id: selectAllAction;
text: catalog.i18nc("@action:inmenu menubar:edit","&Select All Models"); text: catalog.i18nc("@action:inmenu menubar:edit","Select All Models");
enabled: UM.Controller.toolsEnabled; enabled: UM.Controller.toolsEnabled;
iconName: "edit-select-all"; iconName: "edit-select-all";
shortcut: "Ctrl+A"; shortcut: "Ctrl+A";
@ -338,7 +328,7 @@ Item
Action Action
{ {
id: deleteAllAction; id: deleteAllAction;
text: catalog.i18nc("@action:inmenu menubar:edit","&Clear Build Plate"); text: catalog.i18nc("@action:inmenu menubar:edit","Clear Build Plate");
enabled: UM.Controller.toolsEnabled; enabled: UM.Controller.toolsEnabled;
iconName: "edit-delete"; iconName: "edit-delete";
shortcut: "Ctrl+D"; shortcut: "Ctrl+D";
@ -348,7 +338,7 @@ Item
Action Action
{ {
id: reloadAllAction; id: reloadAllAction;
text: catalog.i18nc("@action:inmenu menubar:file","Re&load All Models"); text: catalog.i18nc("@action:inmenu menubar:file","Reload All Models");
iconName: "document-revert"; iconName: "document-revert";
shortcut: "F5" shortcut: "F5"
onTriggered: CuraApplication.reloadAll(); onTriggered: CuraApplication.reloadAll();

View File

@ -120,7 +120,7 @@ UM.MainWindow
text: catalog.i18nc("@title:menu menubar:file","&Save...") text: catalog.i18nc("@title:menu menubar:file","&Save...")
onTriggered: onTriggered:
{ {
var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/x-curaproject+xml" }; var args = { "filter_by_machine": false, "file_type": "workspace", "preferred_mimetypes": "application/vnd.ms-package.3dmanufacturing-3dmodel+xml" };
if(UM.Preferences.getValue("cura/dialog_on_project_save")) if(UM.Preferences.getValue("cura/dialog_on_project_save"))
{ {
saveWorkspaceDialog.args = args; saveWorkspaceDialog.args = args;

View File

@ -10,7 +10,7 @@ import Cura 1.0 as Cura
Menu Menu
{ {
id: menu id: menu
title: "Material" title: catalog.i18nc("@label:category menu label", "Material")
property int extruderIndex: 0 property int extruderIndex: 0
@ -32,6 +32,12 @@ Menu
extruderPosition: menu.extruderIndex extruderPosition: menu.extruderIndex
} }
MenuItem
{
text: catalog.i18nc("@label:category menu label", "Favorites")
enabled: false
visible: favoriteMaterialsModel.items.length > 0
}
Instantiator Instantiator
{ {
model: favoriteMaterialsModel model: favoriteMaterialsModel
@ -52,7 +58,7 @@ Menu
Menu Menu
{ {
id: genericMenu id: genericMenu
title: "Generic" title: catalog.i18nc("@label:category menu label", "Generic")
Instantiator Instantiator
{ {

View File

@ -0,0 +1,17 @@
[general]
version = 4
name = Coarse
definition = peopoly_moai
[metadata]
setting_version = 5
type = quality
quality_type = coarse
weight = 3
[values]
layer_height = 0.08
speed_print = 90
speed_travel = 120
speed_travel_layer_0 = 100
speed_wall = 90

View File

@ -0,0 +1,18 @@
[general]
version = 4
name = Draft
definition = peopoly_moai
[metadata]
setting_version = 5
type = quality
quality_type = draft
weight = 4
[values]
layer_height = 0.1
speed_print = 85
speed_travel = 120
speed_travel_layer_0 = 100
speed_wall = 85
speed_slowdown_layers = 2

View File

@ -0,0 +1,18 @@
[general]
version = 4
name = Extra High
definition = peopoly_moai
[metadata]
setting_version = 5
type = quality
quality_type = extra_high
weight = 0
[values]
layer_height = 0.02
speed_print = 185
speed_travel = 185
speed_travel_layer_0 = 100
speed_wall = 185
speed_slowdown_layers = 5

View File

@ -1,6 +1,6 @@
[general] [general]
version = 4 version = 4
name = Extra Fine name = High
definition = peopoly_moai definition = peopoly_moai
[metadata] [metadata]
@ -10,8 +10,9 @@ quality_type = high
weight = 1 weight = 1
[values] [values]
infill_sparse_density = 70 layer_height = 0.04
layer_height = 0.05 speed_print = 140
top_bottom_thickness = 0.4 speed_travel = 140
wall_thickness = 0.4 speed_travel_layer_0 = 100
speed_print = 150 speed_wall = 140
speed_slowdown_layers = 4

View File

@ -1,17 +0,0 @@
[general]
version = 4
name = Maximum Quality
definition = peopoly_moai
[metadata]
setting_version = 5
type = quality
quality_type = extra_high
weight = 2
[values]
infill_sparse_density = 70
layer_height = 0.025
top_bottom_thickness = 0.4
wall_thickness = 0.4
speed_print = 200

View File

@ -1,17 +1,17 @@
[general] [general]
version = 4 version = 4
name = Fine name = Normal
definition = peopoly_moai definition = peopoly_moai
[metadata] [metadata]
setting_version = 5 setting_version = 5
type = quality type = quality
quality_type = normal quality_type = normal
weight = 0 weight = 2
[values] [values]
infill_sparse_density = 70 layer_height = 0.06
layer_height = 0.1 speed_print = 120
top_bottom_thickness = 0.4 speed_travel = 120
wall_thickness = 0.4 speed_travel_layer_0 = 100
speed_print = 100 speed_wall = 120

View File

@ -12,5 +12,5 @@ hardware_type = nozzle
machine_nozzle_size = 0.4 machine_nozzle_size = 0.4
machine_nozzle_tip_outer_diameter = 1.05 machine_nozzle_tip_outer_diameter = 1.05
speed_wall = =round(speed_print / 1.25, 1) speed_wall = =round(speed_print / 1.25, 1)
speed_wall_0 = =1 if speed_wall < 10 else (speed_wall - 10) speed_wall_0 = =min(speed_wall - 10, 1)
speed_topbottom = =round(speed_print / 2.25, 1) speed_topbottom = =round(speed_print / 2.25, 1)