diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index a6327de3b6..8a014c17bc 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -28,6 +28,6 @@ This fixes... OR This improves... -->
- [ ] 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 uploaded any files required to test this change
\ No newline at end of file
+- [ ] I have uploaded any files required to test this change
diff --git a/.gitignore b/.gitignore
index 45cf4400f6..048bb915c7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,3 +101,4 @@ graph_info.json
Ultimaker-Cura.spec
.run/
/printer-linter/src/printerlinter.egg-info/
+/resources/qml/Dialogs/AboutDialogVersionsList.qml
diff --git a/AboutDialogVersionsList.qml.jinja b/AboutDialogVersionsList.qml.jinja
new file mode 100644
index 0000000000..0503469660
--- /dev/null
+++ b/AboutDialogVersionsList.qml.jinja
@@ -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 : "
Conan Installs
", 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 : "Python Installs
", version : '' });
+ for (var n in python_installs)
+ {
+ developerInfo.append({ name : python_installs[n][0], version : python_installs[n][1] });
+ }
+
+ }
+}
+
diff --git a/conanfile.py b/conanfile.py
index 46e143cc10..438e3f07b7 100644
--- a/conanfile.py
+++ b/conanfile.py
@@ -21,7 +21,7 @@ class CuraConan(ConanFile):
description = "3D printer / slicing GUI built on top of the Uranium framework"
topics = ("conan", "python", "pyqt6", "qt", "qml", "3d-printing", "slicer")
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"
# FIXME: Remove specific branch once merged to main
@@ -138,6 +138,29 @@ class CuraConan(ConanFile):
return "'x86_64'"
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):
with open(os.path.join(self.recipe_folder, "CuraVersion.py.jinja"), "r") as f:
cura_version_py = Template(f.read())
@@ -307,6 +330,7 @@ class CuraConan(ConanFile):
vr.generate()
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:
entitlements_file = "'{}'".format(os.path.join(self.source_folder, "packaging", "MacOS", "cura.entitlements"))
diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py
index e6214d7073..e2f20355c7 100644
--- a/cura/CrashHandler.py
+++ b/cura/CrashHandler.py
@@ -22,7 +22,7 @@ except ImportError:
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.QtGui import QDesktopServices
+from PyQt6.QtGui import QDesktopServices, QTextCursor
from UM.Application import Application
from UM.Logger import Logger
@@ -309,7 +309,7 @@ class CrashHandler:
trace = "".join(trace_list)
text_area.setText(trace)
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)
group.setLayout(layout)
@@ -400,7 +400,7 @@ class CrashHandler:
text_area.setText(logdata)
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)
group.setLayout(layout)
diff --git a/cura/Machines/Models/IntentSelectionModel.py b/cura/Machines/Models/IntentSelectionModel.py
index 603244a12b..3df94e4ad8 100644
--- a/cura/Machines/Models/IntentSelectionModel.py
+++ b/cura/Machines/Models/IntentSelectionModel.py
@@ -71,15 +71,15 @@ class IntentSelectionModel(ListModel):
def _update(self) -> None:
Logger.log("d", "Updating {model_class_name}.".format(model_class_name = self.__class__.__name__))
-
- global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
+ cura_application = cura.CuraApplication.CuraApplication.getInstance()
+ global_stack = cura_application.getGlobalContainerStack()
if global_stack is None:
self.setItems([])
Logger.log("d", "No active GlobalStack, set quality profile model as empty.")
return
# 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.")
self.setItems([])
return
@@ -101,17 +101,18 @@ class IntentSelectionModel(ListModel):
else:
# 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 = cura.CuraApplication.CuraApplication \
- .getInstance() \
- .getContainerRegistry() \
- .findContainersMetadata(type="intent", definition=global_stack.definition.getId(),
- intent_category=category)[0]
+
+
+
+ intent_metadata = cura_application.getContainerRegistry().findContainersMetadata(type="intent",
+ definition=global_stack.findInstanceContainerDefinitionId(global_stack.definition),
+ intent_category=category)[0]
intent_name = intent_metadata.get("name", category.title())
icon = intent_metadata.get("icon", None)
description = intent_metadata.get("description", None)
- if icon is not None:
+ if icon is not None and icon != '':
try:
icon = QUrl.fromLocalFile(
Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.ImageFiles, icon))
diff --git a/cura/Settings/CuraContainerStack.py b/cura/Settings/CuraContainerStack.py
index 41502f8874..b5b8a1b721 100755
--- a/cura/Settings/CuraContainerStack.py
+++ b/cura/Settings/CuraContainerStack.py
@@ -359,7 +359,7 @@ class CuraContainerStack(ContainerStack):
return self.definition
@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.
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
return machine_definition.id #type: ignore
- return cls._findInstanceContainerDefinitionId(definitions[0])
+ return cls.findInstanceContainerDefinitionId(definitions[0])
def getExtruderPositionValueWithDefault(self, key):
"""getProperty for extruder positions, with translation from -1 to default extruder number"""
diff --git a/plugins/Marketplace/RemotePackageList.py b/plugins/Marketplace/RemotePackageList.py
index d06d2c64c5..f8826ff395 100644
--- a/plugins/Marketplace/RemotePackageList.py
+++ b/plugins/Marketplace/RemotePackageList.py
@@ -21,6 +21,7 @@ catalog = i18nCatalog("cura")
class RemotePackageList(PackageList):
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:
super().__init__(parent)
@@ -28,6 +29,7 @@ class RemotePackageList(PackageList):
self._package_type_filter = ""
self._requested_search_string = ""
self._current_search_string = ""
+ self._search_sort = "sort_by"
self._search_type = "search"
self._request_url = self._initialRequestUrl()
self._ongoing_requests["get_packages"] = None
@@ -102,6 +104,8 @@ class RemotePackageList(PackageList):
request_url += f"&package_type={self._package_type_filter}"
if 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
def _parseResponse(self, reply: "QNetworkReply") -> None:
diff --git a/resources/definitions/fdmprinter.def.json b/resources/definitions/fdmprinter.def.json
index 915a550a33..d1c532a32d 100644
--- a/resources/definitions/fdmprinter.def.json
+++ b/resources/definitions/fdmprinter.def.json
@@ -1289,7 +1289,7 @@
"hole_xy_offset":
{
"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",
"type": "float",
"minimum_value_warning": "-1",
diff --git a/resources/qml/Dialogs/AboutDialog.qml b/resources/qml/Dialogs/AboutDialog.qml
index 4ccf58d0b4..ae2bd44d74 100644
--- a/resources/qml/Dialogs/AboutDialog.qml
+++ b/resources/qml/Dialogs/AboutDialog.qml
@@ -1,10 +1,10 @@
// Copyright (c) 2022 UltiMaker
// 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 UM 1.5 as UM
+import UM 1.6 as UM
import Cura 1.5 as Cura
UM.Dialog
@@ -21,6 +21,14 @@ UM.Dialog
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
{
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
{
//: Close about dialog button
diff --git a/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml b/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml
index 64beeb9834..408db66f3a 100644
--- a/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml
+++ b/resources/qml/MachineSettings/NumericTextFieldWithUnit.qml
@@ -76,6 +76,11 @@ UM.TooltipArea
anchors.left: fieldLabel.right
anchors.leftMargin: spacing
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")
selectedTextColor: UM.Theme.getColor("setting_control_text")
padding: 0
diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml
index 2183ef7d5e..07e9c1ffaa 100644
--- a/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml
+++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedAdhesionSelector.qml
@@ -17,7 +17,7 @@ RecommendedSettingSection
enableSectionSwitchVisible: platformAdhesionType.properties.enabled === "True"
enableSectionSwitchChecked: platformAdhesionType.properties.value !== "skirt" && platformAdhesionType.properties.value !== "none"
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 {}
diff --git a/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml b/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml
index 50b5dc7357..0f4efc8498 100644
--- a/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml
+++ b/resources/qml/PrintSetupSelector/Recommended/RecommendedPrintSetup.qml
@@ -111,7 +111,6 @@ Flickable
anchors.right: parent.right
text: catalog.i18nc("@button", "Show Custom")
textFont: UM.Theme.getFont("medium_bold")
- outlineColor: "transparent"
onClicked: onModeChanged()
}
}
diff --git a/resources/setting_visibility/basic.cfg b/resources/setting_visibility/basic.cfg
index 927989fee3..0193eb26ba 100644
--- a/resources/setting_visibility/basic.cfg
+++ b/resources/setting_visibility/basic.cfg
@@ -45,6 +45,7 @@ support_extruder_nr
support_type
support_angle
support_offset
+support_structure
[platform_adhesion]
prime_blob_enable