mirror of
https://git.mirrors.martin98.com/https://github.com/Ultimaker/Cura
synced 2025-08-18 04:35:53 +08:00
Merge branch 'main' into main
This commit is contained in:
commit
7613ebcaf0
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -28,6 +28,6 @@ This fixes... OR This improves... -->
|
|||||||
<!-- Check if relevant -->
|
<!-- Check if relevant -->
|
||||||
|
|
||||||
- [ ] My code follows the style guidelines of this project as described in [UltiMaker Meta](https://github.com/Ultimaker/Meta) and [Cura QML best practices](https://github.com/Ultimaker/Cura/wiki/QML-Best-Practices)
|
- [ ] My code follows the style guidelines of this project as described in [UltiMaker Meta](https://github.com/Ultimaker/Meta) and [Cura QML best practices](https://github.com/Ultimaker/Cura/wiki/QML-Best-Practices)
|
||||||
- [ ] I have read the [Contribution guide](https://github.com/Ultimaker/Cura/blob/main/contributing.md)
|
- [ ] I have read the [Contribution guide](https://github.com/Ultimaker/Cura/blob/main/CONTRIBUTING.md)
|
||||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||||
- [ ] I have uploaded any files required to test this change
|
- [ ] I have uploaded any files required to test this change
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -101,3 +101,4 @@ graph_info.json
|
|||||||
Ultimaker-Cura.spec
|
Ultimaker-Cura.spec
|
||||||
.run/
|
.run/
|
||||||
/printer-linter/src/printerlinter.egg-info/
|
/printer-linter/src/printerlinter.egg-info/
|
||||||
|
/resources/qml/Dialogs/AboutDialogVersionsList.qml
|
||||||
|
61
AboutDialogVersionsList.qml.jinja
Normal file
61
AboutDialogVersionsList.qml.jinja
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import QtQuick 2.2
|
||||||
|
import QtQuick.Controls 2.9
|
||||||
|
|
||||||
|
import UM 1.6 as UM
|
||||||
|
import Cura 1.5 as Cura
|
||||||
|
|
||||||
|
|
||||||
|
ListView
|
||||||
|
{
|
||||||
|
id: projectBuildInfoList
|
||||||
|
visible: false
|
||||||
|
anchors.top: creditsNotes.bottom
|
||||||
|
anchors.topMargin: UM.Theme.getSize("default_margin").height
|
||||||
|
width: parent.width
|
||||||
|
height: base.height - y - (2 * UM.Theme.getSize("default_margin").height + closeButton.height)
|
||||||
|
|
||||||
|
ScrollBar.vertical: UM.ScrollBar
|
||||||
|
{
|
||||||
|
id: projectBuildInfoListScrollBar
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: Row
|
||||||
|
{
|
||||||
|
spacing: UM.Theme.getSize("narrow_margin").width
|
||||||
|
UM.Label
|
||||||
|
{
|
||||||
|
text: (model.name)
|
||||||
|
width: (projectBuildInfoList.width* 0.4) | 0
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
UM.Label
|
||||||
|
{
|
||||||
|
text: (model.version)
|
||||||
|
width: (projectBuildInfoList.width *0.6) | 0
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
model: ListModel
|
||||||
|
{
|
||||||
|
id: developerInfo
|
||||||
|
}
|
||||||
|
Component.onCompleted:
|
||||||
|
{
|
||||||
|
var conan_installs = {{ conan_installs }};
|
||||||
|
var python_installs = {{ python_installs }};
|
||||||
|
developerInfo.append({ name : "<H1>Conan Installs</H1>", version : '' });
|
||||||
|
for (var n in conan_installs)
|
||||||
|
{
|
||||||
|
developerInfo.append({ name : conan_installs[n][0], version : conan_installs[n][1] });
|
||||||
|
}
|
||||||
|
developerInfo.append({ name : '', version : '' });
|
||||||
|
developerInfo.append({ name : "<H1>Python Installs</H1>", version : '' });
|
||||||
|
for (var n in python_installs)
|
||||||
|
{
|
||||||
|
developerInfo.append({ name : python_installs[n][0], version : python_installs[n][1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
26
conanfile.py
26
conanfile.py
@ -21,7 +21,7 @@ class CuraConan(ConanFile):
|
|||||||
description = "3D printer / slicing GUI built on top of the Uranium framework"
|
description = "3D printer / slicing GUI built on top of the Uranium framework"
|
||||||
topics = ("conan", "python", "pyqt6", "qt", "qml", "3d-printing", "slicer")
|
topics = ("conan", "python", "pyqt6", "qt", "qml", "3d-printing", "slicer")
|
||||||
build_policy = "missing"
|
build_policy = "missing"
|
||||||
exports = "LICENSE*", "UltiMaker-Cura.spec.jinja", "CuraVersion.py.jinja"
|
exports = "LICENSE*", "UltiMaker-Cura.spec.jinja", "CuraVersion.py.jinja", "AboutDialogVersionsList.qml.jinja"
|
||||||
settings = "os", "compiler", "build_type", "arch"
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
|
||||||
# FIXME: Remove specific branch once merged to main
|
# FIXME: Remove specific branch once merged to main
|
||||||
@ -138,6 +138,29 @@ class CuraConan(ConanFile):
|
|||||||
return "'x86_64'"
|
return "'x86_64'"
|
||||||
return "None"
|
return "None"
|
||||||
|
|
||||||
|
def _generate_about_versions(self, location):
|
||||||
|
with open(os.path.join(self.recipe_folder, "AboutDialogVersionsList.qml.jinja"), "r") as f:
|
||||||
|
cura_version_py = Template(f.read())
|
||||||
|
|
||||||
|
conan_installs = []
|
||||||
|
python_installs = []
|
||||||
|
|
||||||
|
# list of conan installs
|
||||||
|
for _, dependency in self.dependencies.host.items():
|
||||||
|
conan_installs.append([dependency.ref.name,dependency.ref.version])
|
||||||
|
|
||||||
|
#list of python installs
|
||||||
|
import pkg_resources
|
||||||
|
for package in pkg_resources.working_set:
|
||||||
|
python_installs.append([package.key, package.version])
|
||||||
|
|
||||||
|
with open(os.path.join(location, "AboutDialogVersionsList.qml"), "w") as f:
|
||||||
|
f.write(cura_version_py.render(
|
||||||
|
conan_installs = conan_installs,
|
||||||
|
python_installs = python_installs
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
def _generate_cura_version(self, location):
|
def _generate_cura_version(self, location):
|
||||||
with open(os.path.join(self.recipe_folder, "CuraVersion.py.jinja"), "r") as f:
|
with open(os.path.join(self.recipe_folder, "CuraVersion.py.jinja"), "r") as f:
|
||||||
cura_version_py = Template(f.read())
|
cura_version_py = Template(f.read())
|
||||||
@ -307,6 +330,7 @@ class CuraConan(ConanFile):
|
|||||||
vr.generate()
|
vr.generate()
|
||||||
|
|
||||||
self._generate_cura_version(os.path.join(self.source_folder, "cura"))
|
self._generate_cura_version(os.path.join(self.source_folder, "cura"))
|
||||||
|
self._generate_about_versions(os.path.join(self.source_folder, "resources/qml/Dialogs"))
|
||||||
|
|
||||||
if self.options.devtools:
|
if self.options.devtools:
|
||||||
entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements"))
|
entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements"))
|
||||||
|
@ -22,7 +22,7 @@ except ImportError:
|
|||||||
|
|
||||||
from PyQt6.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QUrl
|
from PyQt6.QtCore import QT_VERSION_STR, PYQT_VERSION_STR, QUrl
|
||||||
from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QCheckBox, QPushButton
|
from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QVBoxLayout, QLabel, QTextEdit, QGroupBox, QCheckBox, QPushButton
|
||||||
from PyQt6.QtGui import QDesktopServices
|
from PyQt6.QtGui import QDesktopServices, QTextCursor
|
||||||
|
|
||||||
from UM.Application import Application
|
from UM.Application import Application
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
@ -309,7 +309,7 @@ class CrashHandler:
|
|||||||
trace = "".join(trace_list)
|
trace = "".join(trace_list)
|
||||||
text_area.setText(trace)
|
text_area.setText(trace)
|
||||||
text_area.setReadOnly(True)
|
text_area.setReadOnly(True)
|
||||||
|
text_area.moveCursor(QTextCursor.MoveOperation.End) # Move cursor to end, so we see last bit of the exception
|
||||||
layout.addWidget(text_area)
|
layout.addWidget(text_area)
|
||||||
group.setLayout(layout)
|
group.setLayout(layout)
|
||||||
|
|
||||||
@ -400,7 +400,7 @@ class CrashHandler:
|
|||||||
|
|
||||||
text_area.setText(logdata)
|
text_area.setText(logdata)
|
||||||
text_area.setReadOnly(True)
|
text_area.setReadOnly(True)
|
||||||
|
text_area.moveCursor(QTextCursor.MoveOperation.End) # Move cursor to end, so we see last bit of the log
|
||||||
layout.addWidget(text_area)
|
layout.addWidget(text_area)
|
||||||
group.setLayout(layout)
|
group.setLayout(layout)
|
||||||
|
|
||||||
|
@ -71,15 +71,15 @@ class IntentSelectionModel(ListModel):
|
|||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
|
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
|
||||||
|
cura_application = cura.CuraApplication.CuraApplication.getInstance()
|
||||||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
global_stack = cura_application.getGlobalContainerStack()
|
||||||
if global_stack is None:
|
if global_stack is None:
|
||||||
self.setItems([])
|
self.setItems([])
|
||||||
Logger.log("d", "No active GlobalStack, set quality profile model as empty.")
|
Logger.log("d", "No active GlobalStack, set quality profile model as empty.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check for material compatibility
|
# Check for material compatibility
|
||||||
if not cura.CuraApplication.CuraApplication.getInstance().getMachineManager().activeMaterialsCompatible():
|
if not cura_application.getMachineManager().activeMaterialsCompatible():
|
||||||
Logger.log("d", "No active material compatibility, set quality profile model as empty.")
|
Logger.log("d", "No active material compatibility, set quality profile model as empty.")
|
||||||
self.setItems([])
|
self.setItems([])
|
||||||
return
|
return
|
||||||
@ -101,17 +101,18 @@ class IntentSelectionModel(ListModel):
|
|||||||
else:
|
else:
|
||||||
# There can be multiple intents with the same category, use one of these
|
# There can be multiple intents with the same category, use one of these
|
||||||
# intent-metadata's for the icon/description defintions for the intent
|
# intent-metadata's for the icon/description defintions for the intent
|
||||||
intent_metadata = cura.CuraApplication.CuraApplication \
|
|
||||||
.getInstance() \
|
|
||||||
.getContainerRegistry() \
|
|
||||||
.findContainersMetadata(type="intent", definition=global_stack.definition.getId(),
|
intent_metadata = cura_application.getContainerRegistry().findContainersMetadata(type="intent",
|
||||||
intent_category=category)[0]
|
definition=global_stack.findInstanceContainerDefinitionId(global_stack.definition),
|
||||||
|
intent_category=category)[0]
|
||||||
|
|
||||||
intent_name = intent_metadata.get("name", category.title())
|
intent_name = intent_metadata.get("name", category.title())
|
||||||
icon = intent_metadata.get("icon", None)
|
icon = intent_metadata.get("icon", None)
|
||||||
description = intent_metadata.get("description", None)
|
description = intent_metadata.get("description", None)
|
||||||
|
|
||||||
if icon is not None:
|
if icon is not None and icon != '':
|
||||||
try:
|
try:
|
||||||
icon = QUrl.fromLocalFile(
|
icon = QUrl.fromLocalFile(
|
||||||
Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.ImageFiles, icon))
|
Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.ImageFiles, icon))
|
||||||
|
@ -359,7 +359,7 @@ class CuraContainerStack(ContainerStack):
|
|||||||
return self.definition
|
return self.definition
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _findInstanceContainerDefinitionId(cls, machine_definition: DefinitionContainerInterface) -> str:
|
def findInstanceContainerDefinitionId(cls, machine_definition: DefinitionContainerInterface) -> str:
|
||||||
"""Find the ID that should be used when searching for instance containers for a specified definition.
|
"""Find the ID that should be used when searching for instance containers for a specified definition.
|
||||||
|
|
||||||
This handles the situation where the definition specifies we should use a different definition when
|
This handles the situation where the definition specifies we should use a different definition when
|
||||||
@ -379,7 +379,7 @@ class CuraContainerStack(ContainerStack):
|
|||||||
Logger.log("w", "Unable to find parent definition {parent} for machine {machine}", parent = quality_definition, machine = machine_definition.id) #type: ignore
|
Logger.log("w", "Unable to find parent definition {parent} for machine {machine}", parent = quality_definition, machine = machine_definition.id) #type: ignore
|
||||||
return machine_definition.id #type: ignore
|
return machine_definition.id #type: ignore
|
||||||
|
|
||||||
return cls._findInstanceContainerDefinitionId(definitions[0])
|
return cls.findInstanceContainerDefinitionId(definitions[0])
|
||||||
|
|
||||||
def getExtruderPositionValueWithDefault(self, key):
|
def getExtruderPositionValueWithDefault(self, key):
|
||||||
"""getProperty for extruder positions, with translation from -1 to default extruder number"""
|
"""getProperty for extruder positions, with translation from -1 to default extruder number"""
|
||||||
|
@ -21,6 +21,7 @@ catalog = i18nCatalog("cura")
|
|||||||
|
|
||||||
class RemotePackageList(PackageList):
|
class RemotePackageList(PackageList):
|
||||||
ITEMS_PER_PAGE = 20 # Pagination of number of elements to download at once.
|
ITEMS_PER_PAGE = 20 # Pagination of number of elements to download at once.
|
||||||
|
SORT_TYPE = "last_updated" # Default value to send for sort_by filter.
|
||||||
|
|
||||||
def __init__(self, parent: Optional["QObject"] = None) -> None:
|
def __init__(self, parent: Optional["QObject"] = None) -> None:
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
@ -28,6 +29,7 @@ class RemotePackageList(PackageList):
|
|||||||
self._package_type_filter = ""
|
self._package_type_filter = ""
|
||||||
self._requested_search_string = ""
|
self._requested_search_string = ""
|
||||||
self._current_search_string = ""
|
self._current_search_string = ""
|
||||||
|
self._search_sort = "sort_by"
|
||||||
self._search_type = "search"
|
self._search_type = "search"
|
||||||
self._request_url = self._initialRequestUrl()
|
self._request_url = self._initialRequestUrl()
|
||||||
self._ongoing_requests["get_packages"] = None
|
self._ongoing_requests["get_packages"] = None
|
||||||
@ -102,6 +104,8 @@ class RemotePackageList(PackageList):
|
|||||||
request_url += f"&package_type={self._package_type_filter}"
|
request_url += f"&package_type={self._package_type_filter}"
|
||||||
if self._current_search_string != "":
|
if self._current_search_string != "":
|
||||||
request_url += f"&{self._search_type}={self._current_search_string}"
|
request_url += f"&{self._search_type}={self._current_search_string}"
|
||||||
|
if self.SORT_TYPE:
|
||||||
|
request_url += f"&{self._search_sort}={self.SORT_TYPE}"
|
||||||
return request_url
|
return request_url
|
||||||
|
|
||||||
def _parseResponse(self, reply: "QNetworkReply") -> None:
|
def _parseResponse(self, reply: "QNetworkReply") -> None:
|
||||||
|
@ -1289,7 +1289,7 @@
|
|||||||
"hole_xy_offset":
|
"hole_xy_offset":
|
||||||
{
|
{
|
||||||
"label": "Hole Horizontal Expansion",
|
"label": "Hole Horizontal Expansion",
|
||||||
"description": "Amount of offset applied to all holes in each layer. Positive values increase the size of the holes, negative values reduce the size of the holes.",
|
"description": "When greater than zero, the Hole Horizontal Expansion is the amount of offset applied to all holes in each layer. Positive values increase the size of the holes, negative values reduce the size of the holes. When this setting is enabled it can be further tuned with Hole Horizontal Expansion Max Diameter.",
|
||||||
"unit": "mm",
|
"unit": "mm",
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"minimum_value_warning": "-1",
|
"minimum_value_warning": "-1",
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
// Copyright (c) 2022 UltiMaker
|
// Copyright (c) 2022 UltiMaker
|
||||||
// Cura is released under the terms of the LGPLv3 or higher.
|
// Cura is released under the terms of the LGPLv3 or higher.
|
||||||
|
|
||||||
import QtQuick 2.2
|
import QtQuick 2.4
|
||||||
import QtQuick.Controls 2.9
|
import QtQuick.Controls 2.9
|
||||||
|
|
||||||
import UM 1.5 as UM
|
import UM 1.6 as UM
|
||||||
import Cura 1.5 as Cura
|
import Cura 1.5 as Cura
|
||||||
|
|
||||||
UM.Dialog
|
UM.Dialog
|
||||||
@ -21,6 +21,14 @@ UM.Dialog
|
|||||||
|
|
||||||
backgroundColor: UM.Theme.getColor("main_background")
|
backgroundColor: UM.Theme.getColor("main_background")
|
||||||
|
|
||||||
|
property real dialogX: base.x
|
||||||
|
property real dialogY: base.y
|
||||||
|
property int shakeDetected: shakeDetector.shakeIsdetected
|
||||||
|
property UM.ShakeDetector shakeDetector: UM.ShakeDetector
|
||||||
|
{
|
||||||
|
position: Qt.point(base.x, base.y)
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle
|
Rectangle
|
||||||
{
|
{
|
||||||
id: header
|
id: header
|
||||||
@ -181,6 +189,23 @@ UM.Dialog
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AboutDialogVersionsList{
|
||||||
|
id: projectBuildInfoList
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
onShakeDetectedChanged:
|
||||||
|
{
|
||||||
|
projectsList.visible = !projectsList.visible;
|
||||||
|
projectBuildInfoList.visible = !projectBuildInfoList.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged:
|
||||||
|
{
|
||||||
|
projectsList.visible = true;
|
||||||
|
projectBuildInfoList.visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
rightButtons: Cura.TertiaryButton
|
rightButtons: Cura.TertiaryButton
|
||||||
{
|
{
|
||||||
//: Close about dialog button
|
//: Close about dialog button
|
||||||
|
@ -76,6 +76,11 @@ UM.TooltipArea
|
|||||||
anchors.left: fieldLabel.right
|
anchors.left: fieldLabel.right
|
||||||
anchors.leftMargin: spacing
|
anchors.leftMargin: spacing
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
|
// The control is set up for left to right. So we force it to that. If we don't, it will take the OS reading
|
||||||
|
// direction, which might not be left to right. This will lead to the text overlapping with the unit
|
||||||
|
horizontalAlignment: TextInput.AlignLeft
|
||||||
|
|
||||||
selectionColor: UM.Theme.getColor("text_selection")
|
selectionColor: UM.Theme.getColor("text_selection")
|
||||||
selectedTextColor: UM.Theme.getColor("setting_control_text")
|
selectedTextColor: UM.Theme.getColor("setting_control_text")
|
||||||
padding: 0
|
padding: 0
|
||||||
|
@ -17,7 +17,7 @@ RecommendedSettingSection
|
|||||||
enableSectionSwitchVisible: platformAdhesionType.properties.enabled === "True"
|
enableSectionSwitchVisible: platformAdhesionType.properties.enabled === "True"
|
||||||
enableSectionSwitchChecked: platformAdhesionType.properties.value !== "skirt" && platformAdhesionType.properties.value !== "none"
|
enableSectionSwitchChecked: platformAdhesionType.properties.value !== "skirt" && platformAdhesionType.properties.value !== "none"
|
||||||
enableSectionSwitchEnabled: recommendedPrintSetup.settingsEnabled
|
enableSectionSwitchEnabled: recommendedPrintSetup.settingsEnabled
|
||||||
tooltipText: catalog.i18nc("@label", "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards.")
|
tooltipText: catalog.i18nc("@label", "Enable printing a brim or raft. This will add a flat area around or under your object which is easy to cut off afterwards. Disabling it results in a skirt around object by default.")
|
||||||
|
|
||||||
property var curaRecommendedMode: Cura.RecommendedMode {}
|
property var curaRecommendedMode: Cura.RecommendedMode {}
|
||||||
|
|
||||||
|
@ -111,7 +111,6 @@ Flickable
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: catalog.i18nc("@button", "Show Custom")
|
text: catalog.i18nc("@button", "Show Custom")
|
||||||
textFont: UM.Theme.getFont("medium_bold")
|
textFont: UM.Theme.getFont("medium_bold")
|
||||||
outlineColor: "transparent"
|
|
||||||
onClicked: onModeChanged()
|
onClicked: onModeChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ support_extruder_nr
|
|||||||
support_type
|
support_type
|
||||||
support_angle
|
support_angle
|
||||||
support_offset
|
support_offset
|
||||||
|
support_structure
|
||||||
|
|
||||||
[platform_adhesion]
|
[platform_adhesion]
|
||||||
prime_blob_enable
|
prime_blob_enable
|
||||||
|
Loading…
x
Reference in New Issue
Block a user