mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-12-01 06:41:06 -07:00
CURA-5402 hopefully solved merge conflicts
This commit is contained in:
commit
96f2e6e1ed
96 changed files with 1612 additions and 838 deletions
|
|
@ -27,14 +27,6 @@ from cura.Machines.QualityManager import getMachineDefinitionIDForQualitySearch
|
|||
MYPY = False
|
||||
|
||||
|
||||
MimeTypeDatabase.addMimeType(
|
||||
MimeType(
|
||||
name = "application/x-cura-project-file",
|
||||
comment = "Cura Project File",
|
||||
suffixes = ["curaproject.3mf"]
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
if not MYPY:
|
||||
import xml.etree.cElementTree as ET
|
||||
|
|
@ -42,10 +34,20 @@ except ImportError:
|
|||
Logger.log("w", "Unable to load cElementTree, switching to slower version")
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
|
||||
## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes!
|
||||
class ThreeMFReader(MeshReader):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, application):
|
||||
super().__init__(application)
|
||||
|
||||
MimeTypeDatabase.addMimeType(
|
||||
MimeType(
|
||||
name = "application/vnd.ms-package.3dmanufacturing-3dmodel+xml",
|
||||
comment="3MF",
|
||||
suffixes=["3mf"]
|
||||
)
|
||||
)
|
||||
|
||||
self._supported_extensions = [".3mf"]
|
||||
self._root = None
|
||||
self._base_name = ""
|
||||
|
|
@ -158,7 +160,7 @@ class ThreeMFReader(MeshReader):
|
|||
um_node.addDecorator(sliceable_decorator)
|
||||
return um_node
|
||||
|
||||
def read(self, file_name):
|
||||
def _read(self, file_name):
|
||||
result = []
|
||||
self._object_count = 0 # Used to name objects as there is no node name yet.
|
||||
# The base object of 3mf is a zipped archive.
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
from configparser import ConfigParser
|
||||
import zipfile
|
||||
import os
|
||||
import threading
|
||||
from typing import List, Tuple
|
||||
|
||||
|
||||
|
|
@ -21,7 +20,7 @@ from UM.Settings.ContainerStack import ContainerStack
|
|||
from UM.Settings.DefinitionContainer import DefinitionContainer
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.MimeTypeDatabase import MimeTypeDatabase
|
||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||
from UM.Job import Job
|
||||
from UM.Preferences import Preferences
|
||||
|
||||
|
|
@ -84,6 +83,15 @@ class ExtruderInfo:
|
|||
class ThreeMFWorkspaceReader(WorkspaceReader):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
MimeTypeDatabase.addMimeType(
|
||||
MimeType(
|
||||
name="application/x-cura-project-file",
|
||||
comment="Cura Project File",
|
||||
suffixes=["curaproject.3mf"]
|
||||
)
|
||||
)
|
||||
|
||||
self._supported_extensions = [".3mf"]
|
||||
self._dialog = WorkspaceDialog()
|
||||
self._3mf_mesh_reader = None
|
||||
|
|
@ -456,7 +464,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
num_visible_settings = len(visible_settings_string.split(";"))
|
||||
active_mode = temp_preferences.getValue("cura/active_mode")
|
||||
if not active_mode:
|
||||
active_mode = Preferences.getInstance().getValue("cura/active_mode")
|
||||
active_mode = Application.getInstance().getPreferences().getValue("cura/active_mode")
|
||||
except KeyError:
|
||||
# If there is no preferences file, it's not a workspace, so notify user of failure.
|
||||
Logger.log("w", "File %s is not a valid workspace.", file_name)
|
||||
|
|
@ -575,7 +583,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
temp_preferences.deserialize(serialized)
|
||||
|
||||
# Copy a number of settings from the temp preferences to the global
|
||||
global_preferences = Preferences.getInstance()
|
||||
global_preferences = application.getInstance().getPreferences()
|
||||
|
||||
visible_settings = temp_preferences.getValue("general/visible_settings")
|
||||
if visible_settings is None:
|
||||
|
|
|
|||
|
|
@ -13,8 +13,10 @@ from . import ThreeMFWorkspaceReader
|
|||
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Platform import Platform
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
||||
def getMetaData() -> Dict:
|
||||
# Workarround for osx not supporting double file extensions correctly.
|
||||
if Platform.isOSX():
|
||||
|
|
@ -42,7 +44,7 @@ def getMetaData() -> Dict:
|
|||
|
||||
def register(app):
|
||||
if "3MFReader.ThreeMFReader" in sys.modules:
|
||||
return {"mesh_reader": ThreeMFReader.ThreeMFReader(),
|
||||
return {"mesh_reader": ThreeMFReader.ThreeMFReader(app),
|
||||
"workspace_reader": ThreeMFWorkspaceReader.ThreeMFWorkspaceReader()}
|
||||
else:
|
||||
return {}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ class ThreeMFWorkspaceWriter(WorkspaceWriter):
|
|||
self._writeContainerToArchive(container, archive)
|
||||
|
||||
# Write preferences to archive
|
||||
original_preferences = Preferences.getInstance() #Copy only the preferences that we use to the workspace.
|
||||
original_preferences = Application.getInstance().getPreferences() #Copy only the preferences that we use to the workspace.
|
||||
temp_preferences = Preferences()
|
||||
for preference in {"general/visible_settings", "cura/active_mode", "cura/categories_expanded"}:
|
||||
temp_preferences.addPreference(preference, None)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Extension import Extension
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Application import Application
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Version import Version
|
||||
|
|
@ -29,7 +28,7 @@ class ChangeLog(Extension, QObject,):
|
|||
|
||||
self._change_logs = None
|
||||
Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
|
||||
Preferences.getInstance().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium
|
||||
Application.getInstance().getPreferences().addPreference("general/latest_version_changelog_shown", "2.0.0") #First version of CURA with uranium
|
||||
self.addMenuItem(catalog.i18nc("@item:inmenu", "Show Changelog"), self.showChangelog)
|
||||
|
||||
def getChangeLogs(self):
|
||||
|
|
@ -79,12 +78,12 @@ class ChangeLog(Extension, QObject,):
|
|||
if not self._current_app_version:
|
||||
return #We're on dev branch.
|
||||
|
||||
if Preferences.getInstance().getValue("general/latest_version_changelog_shown") == "master":
|
||||
if Application.getInstance().getPreferences().getValue("general/latest_version_changelog_shown") == "master":
|
||||
latest_version_shown = Version("0.0.0")
|
||||
else:
|
||||
latest_version_shown = Version(Preferences.getInstance().getValue("general/latest_version_changelog_shown"))
|
||||
latest_version_shown = Version(Application.getInstance().getPreferences().getValue("general/latest_version_changelog_shown"))
|
||||
|
||||
Preferences.getInstance().setValue("general/latest_version_changelog_shown", Application.getInstance().getVersion())
|
||||
Application.getInstance().getPreferences().setValue("general/latest_version_changelog_shown", Application.getInstance().getVersion())
|
||||
|
||||
# Do not show the changelog when there is no global container stack
|
||||
# This implies we are running Cura for the first time.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,127 @@
|
|||
|
||||
|
||||
[3.4.0]
|
||||
|
||||
*Toolbox
|
||||
The plugin browser has been remodeled into the Toolbox. Navigation now involves graphical elements such as tiles, which can be clicked for further details.
|
||||
|
||||
*Upgradable bundled resources
|
||||
It is now possible to have multiple versions of bundled resources installed: the bundled version and the downloaded upgrade. If an upgrade in the form of a package is present, the bundled version will not be loaded. If it's not present, Ultimaker Cura will revert to the bundled version.
|
||||
|
||||
*Package manager recognizes bundled resources
|
||||
Bundled packages are now made visible to the CuraPackageMangager. This means the resources are included by default, as well as the "wrapping" of a package, (e.g. package.json) so that the CuraPackageManger and Toolbox recognize them as being installed.
|
||||
|
||||
*Retraction combing max distance
|
||||
New setting for maximum combing travel distance. Combing travel moves longer than this value will use retraction. Contributed by smartavionics.
|
||||
|
||||
*Infill support
|
||||
When enabled, infill will be generated only where it is needed using a specialized support generation algorithm for the internal support structures of a part. Contributed by BagelOrb.
|
||||
|
||||
*Print outside perimeter before holes
|
||||
This prioritizes outside perimeters before printing holes. By printing holes as late as possible, there is a reduced risk of travel moves dislodging them from the build plate. This setting should only have an effect if printing outer before inner walls. Contributed by smartavionics.
|
||||
|
||||
*Disable omitting retractions in support
|
||||
Previous versions had no option to disable omitting retraction moves when printing supports, which could cause issues with third-party machines or materials. An option has been added to disable this. Contributed by BagelOrb.
|
||||
|
||||
*Support wall line count
|
||||
Added setting to configure how many walls to print around supports. Contributed by BagelOrb.
|
||||
|
||||
*Maximum combing resolution
|
||||
Combing travel moves are kept at least 1.5 mm long to prevent buffer underruns.
|
||||
|
||||
*Avoid supports when traveling
|
||||
Added setting to avoid supports when performing travel moves. This minimizes the risk of the print head hitting support material.
|
||||
|
||||
*Rewrite cross infill
|
||||
Experimental setting that allows you to input a path to an image to manipulate the cross infill density. This will overlay that image on your model. Contributed by BagelOrb.
|
||||
|
||||
*Backup and restore
|
||||
Added functionality to backup and restore settings and profiles to cloud using the Cura Backups plugin.
|
||||
|
||||
*Auto-select model after import
|
||||
User can now set preferences for the behavior of selecting a newly imported model or not.
|
||||
|
||||
*Settings filter timeout
|
||||
The settings filter is triggered on enter or after a 500ms timeout when typing a setting to filter.
|
||||
|
||||
*Event measurements
|
||||
Added time measurement to logs for occurrences, including startup time, file load time, number of items on the build plate when slicing, slicing time, and time and performance when moving items on the build plate, for benchmarking purposes.
|
||||
|
||||
*Send anonymous data
|
||||
Disable button on the ‘Send anonymous data’ popup has changed to a ‘more info’ button, with further options to enable/disable anonymous data messages.
|
||||
|
||||
*Configuration error assistant
|
||||
Detect and show potential configuration file errors to users, e.g. incorrect files and duplicate files in material or quality profiles, there are several places to check. Information is stored and communicated to the user to prevent crashing in future.
|
||||
|
||||
*Disable ensure models are kept apart
|
||||
Disable "Ensure models are kept apart" by default due to to a change in preference files.
|
||||
|
||||
*Prepare and monitor QML files
|
||||
Created two separate QML files for the Prepare and Monitor stages.
|
||||
|
||||
*Hide bed temperature
|
||||
Option to hide bed temperature when no heated bed is present. Contributed by ngraziano.
|
||||
|
||||
*Reprap/Marlin GCODE flavor
|
||||
RepRap firmware now lists values for all extruders in the "Filament used" GCODE comment. Contributed by smartavionics.
|
||||
|
||||
*AutoDesk Inventor integration
|
||||
Open AutoDesk inventor files (parts, assemblies, drawings) directly into Ultimaker Cura. Contributed by thopiekar.
|
||||
|
||||
*Blender integration
|
||||
Open Blender files directly into Ultimaker Cura. Contributed by thopiekar.
|
||||
|
||||
*OpenSCAD integration
|
||||
Open OpenSCAD files directly into Ultimaker Cura. Contributed by thopiekar.
|
||||
|
||||
*FreeCAD integration
|
||||
Open FreeCAD files directly into Ultimaker Cura. Contributed by thopiekar.
|
||||
|
||||
*OctoPrint plugin
|
||||
New version of the OctoPrint plugin for Ultimaker Cura. Contributed by fieldOfView.
|
||||
|
||||
*Cura Backups
|
||||
Backup and restore your configuration, including settings, materials and plugins, for use across different systems.
|
||||
|
||||
*MakePrintable
|
||||
New version of the MakePrintable plugin.
|
||||
|
||||
*Compact Prepare sidebar
|
||||
Plugin that replaces the sidebar with a more compact variation of the original sidebar. Nozzle and material dropdowns are combined into a single line, the “Check compatibility” link is removed, extruder selection buttons are downsized, recommended and custom mode selection buttons are moved to a combobox at the top, and margins are tweaked. Contributed by fieldOfView.
|
||||
|
||||
*PauseAtHeight plugin
|
||||
Bug fixes and improvements for PauseAtHeight plugin. Plugin now accounts for raft layers when choosing “Pause of layer no.” Now positions the nozzle at x and y values of the next layer when resuming. Contributed by JPFrancoia.
|
||||
|
||||
*Bug fixes
|
||||
- Prime tower purge fix. Prime tower purge now starts away from the center, minimizing the chance of overextrusion and nozzle obstructions. Contributed by BagelOrb.
|
||||
- Extruder 2 temp via USB. Fixed a bug where temperatures can’t be read for a second extruder via USB. Contributed by kirilledelman.
|
||||
- Move to next object position before bed heat. Print one at a time mode caused waiting for the bed temperature to reach the first layer temperature while the nozzle was still positioned on the top of the last part. This has been fixed so that the nozzle moves to the location of the next part before waiting for heat up. Contributed by smartavionics.
|
||||
- Non-GCODE USB. Fixed a bug where the USB port doesn’t open if printer doesn't support GCODE. Contributed by ohrn.
|
||||
- Improved wall overlap compensation. Minimizes unexpected behavior on overlap lines, providing smoother results. Contributed by BagelOrb.
|
||||
- Configuration/sync. Fixes minor issues with the configuration/sync menu, such as text rendering on some OSX systems and untranslatable text. Contributed by fieldOfView.
|
||||
- Print job name reslice. Fixed behavior where print job name changes back to origin when reslicing.
|
||||
- Discard/keep. Customized settings don't give an 'discard or keep' dialog when changing material.
|
||||
- Message box styling. Fixed bugs related to message box styling, such as the progress bar overlapping the button in the ‘Sending Data’ popup.
|
||||
- Curaproject naming. Fixed bug related to two "curaprojects" in the file name when saving a project.
|
||||
- No support on first layers. Fixed a bug related to no support generated causing failed prints when model is floating above build plate.
|
||||
- False incompatible configuration. Fixed a bug where PrintCore and materials were flagged even though the configurations are compatible.
|
||||
- Spiralize contour overlaps. Fixed a bug related to spiralize contour overlaps.
|
||||
- Model saved outside build volume. Fixed a bug that would saved a model to file (GCODE) outside the build volume.
|
||||
- Filament diameter line width. Adjust filament diameter to calculate line width in the GCODE parser.
|
||||
- Holes in model surfaces. Fixed a bug where illogical travel moves leave holes in the model surface.
|
||||
- Nozzle legacy file variant. Fixed crashes caused by loading legacy nozzle variant files.
|
||||
- Brim wall order. Fixed a bug related to brim wall order. Contributed by smartavionics.
|
||||
- GCODE reader gaps. Fixed a GCODE reader bug that can create a gap at the start of a spiralized layer.
|
||||
- Korean translation. Fixed some typos in Korean translation.
|
||||
- ARM/Mali systems. Graphics pipeline for ARM/Mali fixed. Contributed by jwalt.
|
||||
- NGC Writer. Fixed missing author for NGC Writer plugin.
|
||||
- Support blocker legacy GPU. Fixes depth picking on older GPUs that do not support the 4.1 shading model which caused the support blocker to put cubes in unexpected locations. Contributed by fieldOfView.
|
||||
|
||||
*Third-party printers
|
||||
- Felix Tec4 printer. Updated definitions for Felix Tec4. Contributed by kerog777.
|
||||
- Deltacomb. Updated definitions for Deltacomb. Contributed by kaleidoscopeit.
|
||||
- Rigid3D Mucit. Added definitions for Rigid3D Mucit. Contributed by Rigid3D.
|
||||
|
||||
[3.3.0]
|
||||
|
||||
*Profile for the Ultimaker S5
|
||||
|
|
@ -66,7 +190,7 @@ Generate a cube mesh to prevent support material generation in specific areas of
|
|||
*Real bridging - smartavionics
|
||||
New experimental feature that detects bridges, adjusting the print speed, slow and fan speed to enhance print quality on bridging parts.
|
||||
|
||||
*Updated CuraEngine executable - thopiekar & Ultimaker B.V. ❤️
|
||||
*Updated CuraEngine executable - thopiekar & Ultimaker B.V.
|
||||
The CuraEngine executable contains a dedicated icon, author and license info on Windows now. The icon has been designed by Ultimaker B.V.
|
||||
|
||||
*Use RapidJSON and ClipperLib from system libraries
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
from UM.Backend.Backend import Backend, BackendState
|
||||
from UM.Application import Application
|
||||
from UM.Scene.SceneNode import SceneNode
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Signal import Signal
|
||||
from UM.Logger import Logger
|
||||
from UM.Message import Message
|
||||
|
|
@ -72,7 +71,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
Logger.log("i", "Found CuraEngine at: %s", default_engine_location)
|
||||
|
||||
default_engine_location = os.path.abspath(default_engine_location)
|
||||
Preferences.getInstance().addPreference("backend/location", default_engine_location)
|
||||
Application.getInstance().getPreferences().addPreference("backend/location", default_engine_location)
|
||||
|
||||
# Workaround to disable layer view processing if layer view is not active.
|
||||
self._layer_view_active = False
|
||||
|
|
@ -121,7 +120,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._slice_start_time = None
|
||||
self._is_disabled = False
|
||||
|
||||
Preferences.getInstance().addPreference("general/auto_slice", False)
|
||||
Application.getInstance().getPreferences().addPreference("general/auto_slice", False)
|
||||
|
||||
self._use_timer = False
|
||||
# When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired.
|
||||
|
|
@ -131,7 +130,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self._change_timer.setSingleShot(True)
|
||||
self._change_timer.setInterval(500)
|
||||
self.determineAutoSlicing()
|
||||
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
|
||||
Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
|
||||
|
||||
self._application.initializationFinished.connect(self.initialize)
|
||||
|
||||
|
|
@ -170,7 +169,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
# \return list of commands and args / parameters.
|
||||
def getEngineCommand(self):
|
||||
json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json")
|
||||
return [Preferences.getInstance().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]
|
||||
return [Application.getInstance().getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, ""]
|
||||
|
||||
## Emitted when we get a message containing print duration and material amount.
|
||||
# This also implies the slicing has finished.
|
||||
|
|
@ -275,7 +274,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
self.processingProgress.emit(0)
|
||||
Logger.log("d", "Attempting to kill the engine process")
|
||||
|
||||
if Application.getInstance().getCommandLineOption("external-backend", False):
|
||||
if Application.getInstance().getUseExternalBackend():
|
||||
return
|
||||
|
||||
if self._process is not None:
|
||||
|
|
@ -408,7 +407,7 @@ class CuraEngineBackend(QObject, Backend):
|
|||
enable_timer = True
|
||||
self._is_disabled = False
|
||||
|
||||
if not Preferences.getInstance().getValue("general/auto_slice"):
|
||||
if not Application.getInstance().getPreferences().getValue("general/auto_slice"):
|
||||
enable_timer = False
|
||||
for node in DepthFirstIterator(self._scene.getRoot()):
|
||||
if node.callDecoration("isBlockSlicing"):
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import gc
|
|||
from UM.Job import Job
|
||||
from UM.Application import Application
|
||||
from UM.Mesh.MeshData import MeshData
|
||||
from UM.Preferences import Preferences
|
||||
from UM.View.GL.OpenGLContext import OpenGLContext
|
||||
|
||||
from UM.Message import Message
|
||||
|
|
@ -199,7 +198,7 @@ class ProcessSlicedLayersJob(Job):
|
|||
material_color_map[0, :] = color
|
||||
|
||||
# We have to scale the colors for compatibility mode
|
||||
if OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode")):
|
||||
if OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode")):
|
||||
line_type_brightness = 0.5 # for compatibility mode
|
||||
else:
|
||||
line_type_brightness = 1.0
|
||||
|
|
|
|||
|
|
@ -287,14 +287,9 @@ class StartSliceJob(Job):
|
|||
# \return A dictionary of replacement tokens to the values they should be
|
||||
# replaced with.
|
||||
def _buildReplacementTokens(self, stack) -> dict:
|
||||
default_extruder_position = int(Application.getInstance().getMachineManager().defaultExtruderPosition)
|
||||
result = {}
|
||||
for key in stack.getAllKeys():
|
||||
setting_type = stack.definition.getProperty(key, "type")
|
||||
value = stack.getProperty(key, "value")
|
||||
if setting_type == "extruder" and value == -1:
|
||||
# replace with the default value
|
||||
value = default_extruder_position
|
||||
result[key] = value
|
||||
Job.yieldThread()
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ from PyQt5.QtCore import QUrl
|
|||
from PyQt5.QtGui import QDesktopServices
|
||||
|
||||
from UM.Extension import Extension
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Logger import Logger
|
||||
from UM.Application import Application
|
||||
from UM.i18n import i18nCatalog
|
||||
from cura.Settings.GlobalStack import GlobalStack
|
||||
|
||||
|
|
@ -27,12 +26,12 @@ class FirmwareUpdateChecker(Extension):
|
|||
|
||||
# Initialize the Preference called `latest_checked_firmware` that stores the last version
|
||||
# checked for the UM3. In the future if we need to check other printers' firmware
|
||||
Preferences.getInstance().addPreference("info/latest_checked_firmware", "")
|
||||
Application.getInstance().getPreferences().addPreference("info/latest_checked_firmware", "")
|
||||
|
||||
# Listen to a Signal that indicates a change in the list of printers, just if the user has enabled the
|
||||
# 'check for updates' option
|
||||
Preferences.getInstance().addPreference("info/automatic_update_check", True)
|
||||
if Preferences.getInstance().getValue("info/automatic_update_check"):
|
||||
Application.getInstance().getPreferences().addPreference("info/automatic_update_check", True)
|
||||
if Application.getInstance().getPreferences().getValue("info/automatic_update_check"):
|
||||
ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded)
|
||||
|
||||
self._download_url = None
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Application import Application
|
||||
from UM.Message import Message
|
||||
from UM.Logger import Logger
|
||||
|
|
@ -51,11 +50,11 @@ class FirmwareUpdateCheckerJob(Job):
|
|||
current_version = reader(current_version_file).readline().rstrip()
|
||||
|
||||
# If it is the first time the version is checked, the checked_version is ''
|
||||
checked_version = Preferences.getInstance().getValue("info/latest_checked_firmware")
|
||||
checked_version = Application.getInstance().getPreferences().getValue("info/latest_checked_firmware")
|
||||
|
||||
# If the checked_version is '', it's because is the first time we check firmware and in this case
|
||||
# we will not show the notification, but we will store it for the next time
|
||||
Preferences.getInstance().setValue("info/latest_checked_firmware", current_version)
|
||||
Application.getInstance().getPreferences().setValue("info/latest_checked_firmware", current_version)
|
||||
Logger.log("i", "Reading firmware version of %s: checked = %s - latest = %s", machine_name, checked_version, current_version)
|
||||
|
||||
# The first time we want to store the current version, the notification will not be shown,
|
||||
|
|
@ -63,13 +62,26 @@ class FirmwareUpdateCheckerJob(Job):
|
|||
# notify the user when no new firmware version is available.
|
||||
if (checked_version != "") and (checked_version != current_version):
|
||||
Logger.log("i", "SHOWING FIRMWARE UPDATE MESSAGE")
|
||||
message = Message(i18n_catalog.i18nc("@info Don't translate {machine_name}, since it gets replaced by a printer name!", "New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(machine_name = machine_name),
|
||||
title = i18n_catalog.i18nc("@info:title The %s gets replaced with the printer name.", "New %s firmware available") % machine_name)
|
||||
message.addAction("download", i18n_catalog.i18nc("@action:button", "How to update"), "[no_icon]", "[no_description]")
|
||||
|
||||
message = Message(i18n_catalog.i18nc(
|
||||
"@info Don't translate {machine_name}, since it gets replaced by a printer name!",
|
||||
"New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format(
|
||||
machine_name=machine_name),
|
||||
title=i18n_catalog.i18nc(
|
||||
"@info:title The %s gets replaced with the printer name.",
|
||||
"New %s firmware available") % machine_name)
|
||||
|
||||
message.addAction("download",
|
||||
i18n_catalog.i18nc("@action:button", "How to update"),
|
||||
"[no_icon]",
|
||||
"[no_description]",
|
||||
button_style=Message.ActionButtonStyle.LINK,
|
||||
button_align=Message.ActionButtonStyle.BUTTON_ALIGN_LEFT)
|
||||
|
||||
|
||||
# If we do this in a cool way, the download url should be available in the JSON file
|
||||
if self._set_download_url_callback:
|
||||
self._set_download_url_callback("https://ultimaker.com/en/resources/23129-updating-the-firmware?utm_source=cura&utm_medium=software&utm_campaign=hw-update")
|
||||
self._set_download_url_callback("https://ultimaker.com/en/resources/20500-upgrade-firmware")
|
||||
message.actionTriggered.connect(self._callback)
|
||||
message.show()
|
||||
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ from UM.PluginRegistry import PluginRegistry
|
|||
# If you're zipping g-code, you might as well use gzip!
|
||||
class GCodeGzReader(MeshReader):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, application):
|
||||
super().__init__(application)
|
||||
self._supported_extensions = [".gcode.gz"]
|
||||
|
||||
def read(self, file_name):
|
||||
def _read(self, file_name):
|
||||
with open(file_name, "rb") as file:
|
||||
file_data = file.read()
|
||||
uncompressed_gcode = gzip.decompress(file_data).decode("utf-8")
|
||||
|
|
|
|||
|
|
@ -21,4 +21,4 @@ def getMetaData():
|
|||
|
||||
def register(app):
|
||||
app.addNonSliceableExtension(".gz")
|
||||
return { "mesh_reader": GCodeGzReader.GCodeGzReader() }
|
||||
return { "mesh_reader": GCodeGzReader.GCodeGzReader(app) }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from UM.Math.Vector import Vector
|
|||
from UM.Message import Message
|
||||
from cura.Scene.CuraSceneNode import CuraSceneNode
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Preferences import Preferences
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
||||
|
|
@ -47,7 +46,7 @@ class FlavorParser:
|
|||
self._current_layer_thickness = 0.2 # default
|
||||
self._filament_diameter = 2.85 # default
|
||||
|
||||
Preferences.getInstance().addPreference("gcodereader/show_caution", True)
|
||||
Application.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
|
||||
|
||||
def _clearValues(self) -> None:
|
||||
self._extruder_number = 0
|
||||
|
|
@ -462,7 +461,7 @@ class FlavorParser:
|
|||
|
||||
Logger.log("d", "GCode loading finished")
|
||||
|
||||
if Preferences.getInstance().getValue("gcodereader/show_caution"):
|
||||
if Application.getInstance().getPreferences().getValue("gcodereader/show_caution"):
|
||||
caution_message = Message(catalog.i18nc(
|
||||
"@info:generic",
|
||||
"Make sure the g-code is suitable for your printer and printer configuration before sending the file to it. The g-code representation may not be accurate."),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
from UM.FileHandler.FileReader import FileReader
|
||||
from UM.Mesh.MeshReader import MeshReader
|
||||
from UM.i18n import i18nCatalog
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Application import Application
|
||||
from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType
|
||||
|
||||
catalog = i18nCatalog("cura")
|
||||
|
|
@ -27,12 +27,12 @@ class GCodeReader(MeshReader):
|
|||
_flavor_readers_dict = {"RepRap" : RepRapFlavorParser.RepRapFlavorParser(),
|
||||
"Marlin" : MarlinFlavorParser.MarlinFlavorParser()}
|
||||
|
||||
def __init__(self):
|
||||
super(GCodeReader, self).__init__()
|
||||
def __init__(self, application):
|
||||
super(GCodeReader, self).__init__(application)
|
||||
self._supported_extensions = [".gcode", ".g"]
|
||||
self._flavor_reader = None
|
||||
|
||||
Preferences.getInstance().addPreference("gcodereader/show_caution", True)
|
||||
Application.getInstance().getPreferences().addPreference("gcodereader/show_caution", True)
|
||||
|
||||
def preReadFromStream(self, stream, *args, **kwargs):
|
||||
for line in stream.split("\n"):
|
||||
|
|
@ -57,7 +57,7 @@ class GCodeReader(MeshReader):
|
|||
def readFromStream(self, stream):
|
||||
return self._flavor_reader.processGCodeStream(stream)
|
||||
|
||||
def read(self, file_name):
|
||||
def _read(self, file_name):
|
||||
with open(file_name, "r", encoding = "utf-8") as file:
|
||||
file_data = file.read()
|
||||
return self.readFromStream(file_data)
|
||||
|
|
|
|||
|
|
@ -23,4 +23,4 @@ def getMetaData():
|
|||
def register(app):
|
||||
app.addNonSliceableExtension(".gcode")
|
||||
app.addNonSliceableExtension(".g")
|
||||
return { "mesh_reader": GCodeReader.GCodeReader() }
|
||||
return { "mesh_reader": GCodeReader.GCodeReader(app) }
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ from cura.Scene.CuraSceneNode import CuraSceneNode as SceneNode
|
|||
|
||||
|
||||
class ImageReader(MeshReader):
|
||||
def __init__(self):
|
||||
super(ImageReader, self).__init__()
|
||||
def __init__(self, application):
|
||||
super(ImageReader, self).__init__(application)
|
||||
self._supported_extensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png"]
|
||||
self._ui = ImageReaderUI(self)
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class ImageReader(MeshReader):
|
|||
return MeshReader.PreReadResult.cancelled
|
||||
return MeshReader.PreReadResult.accepted
|
||||
|
||||
def read(self, file_name):
|
||||
def _read(self, file_name):
|
||||
size = max(self._ui.getWidth(), self._ui.getDepth())
|
||||
return self._generateSceneNode(file_name, size, self._ui.peak_height, self._ui.base_height, self._ui.smoothing, 512, self._ui.image_color_invert)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,4 +33,4 @@ def getMetaData():
|
|||
}
|
||||
|
||||
def register(app):
|
||||
return { "mesh_reader": ImageReader.ImageReader() }
|
||||
return { "mesh_reader": ImageReader.ImageReader(app) }
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class ModelChecker(QObject, Extension):
|
|||
|
||||
self._caution_message = Message("", #Message text gets set when the message gets shown, to display the models in question.
|
||||
lifetime = 0,
|
||||
title = catalog.i18nc("@info:title", "Model Checker Warning"))
|
||||
title = catalog.i18nc("@info:title", "3D Model Assistant"))
|
||||
|
||||
Application.getInstance().initializationFinished.connect(self._pluginsInitialized)
|
||||
Application.getInstance().getController().getScene().sceneChanged.connect(self._onChanged)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ from UM.Tool import Tool
|
|||
from UM.Scene.Selection import Selection
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator
|
||||
from cura.Settings.ExtruderManager import ExtruderManager
|
||||
from UM.Settings.SettingInstance import SettingInstance
|
||||
|
|
@ -27,7 +26,7 @@ class PerObjectSettingsTool(Tool):
|
|||
|
||||
Selection.selectionChanged.connect(self.propertyChanged)
|
||||
|
||||
Preferences.getInstance().preferenceChanged.connect(self._onPreferenceChanged)
|
||||
Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferenceChanged)
|
||||
self._onPreferenceChanged("cura/active_mode")
|
||||
|
||||
Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
|
||||
|
|
@ -106,7 +105,7 @@ class PerObjectSettingsTool(Tool):
|
|||
|
||||
def _onPreferenceChanged(self, preference):
|
||||
if preference == "cura/active_mode":
|
||||
self._advanced_mode = Preferences.getInstance().getValue(preference) == 1
|
||||
self._advanced_mode = Application.getInstance().getPreferences().getValue(preference) == 1
|
||||
self._updateEnabled()
|
||||
|
||||
def _onGlobalContainerChanged(self):
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ from UM.Mesh.MeshBuilder import MeshBuilder
|
|||
from UM.Message import Message
|
||||
from UM.Platform import Platform
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Resources import Resources
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Scene.Selection import Selection
|
||||
|
|
@ -81,30 +80,30 @@ class SimulationView(View):
|
|||
self._show_travel_moves = False
|
||||
self._nozzle_node = None
|
||||
|
||||
Preferences.getInstance().addPreference("view/top_layer_count", 5)
|
||||
Preferences.getInstance().addPreference("view/only_show_top_layers", False)
|
||||
Preferences.getInstance().addPreference("view/force_layer_view_compatibility_mode", False)
|
||||
Application.getInstance().getPreferences().addPreference("view/top_layer_count", 5)
|
||||
Application.getInstance().getPreferences().addPreference("view/only_show_top_layers", False)
|
||||
Application.getInstance().getPreferences().addPreference("view/force_layer_view_compatibility_mode", False)
|
||||
|
||||
Preferences.getInstance().addPreference("layerview/layer_view_type", 0)
|
||||
Preferences.getInstance().addPreference("layerview/extruder_opacities", "")
|
||||
Application.getInstance().getPreferences().addPreference("layerview/layer_view_type", 0)
|
||||
Application.getInstance().getPreferences().addPreference("layerview/extruder_opacities", "")
|
||||
|
||||
Preferences.getInstance().addPreference("layerview/show_travel_moves", False)
|
||||
Preferences.getInstance().addPreference("layerview/show_helpers", True)
|
||||
Preferences.getInstance().addPreference("layerview/show_skin", True)
|
||||
Preferences.getInstance().addPreference("layerview/show_infill", True)
|
||||
Application.getInstance().getPreferences().addPreference("layerview/show_travel_moves", False)
|
||||
Application.getInstance().getPreferences().addPreference("layerview/show_helpers", True)
|
||||
Application.getInstance().getPreferences().addPreference("layerview/show_skin", True)
|
||||
Application.getInstance().getPreferences().addPreference("layerview/show_infill", True)
|
||||
|
||||
Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
|
||||
Application.getInstance().getPreferences().preferenceChanged.connect(self._onPreferencesChanged)
|
||||
self._updateWithPreferences()
|
||||
|
||||
self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count"))
|
||||
self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers"))
|
||||
self._solid_layers = int(Application.getInstance().getPreferences().getValue("view/top_layer_count"))
|
||||
self._only_show_top_layers = bool(Application.getInstance().getPreferences().getValue("view/only_show_top_layers"))
|
||||
self._compatibility_mode = self._evaluateCompatibilityMode()
|
||||
|
||||
self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled"),
|
||||
title = catalog.i18nc("@info:title", "Simulation View"))
|
||||
|
||||
def _evaluateCompatibilityMode(self):
|
||||
return OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode"))
|
||||
return OpenGLContext.isLegacyOpenGL() or bool(Application.getInstance().getPreferences().getValue("view/force_layer_view_compatibility_mode"))
|
||||
|
||||
def _resetSettings(self):
|
||||
self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed, 3 is layer thickness
|
||||
|
|
@ -543,23 +542,23 @@ class SimulationView(View):
|
|||
self._top_layers_job = None
|
||||
|
||||
def _updateWithPreferences(self):
|
||||
self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count"))
|
||||
self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers"))
|
||||
self._solid_layers = int(Application.getInstance().getPreferences().getValue("view/top_layer_count"))
|
||||
self._only_show_top_layers = bool(Application.getInstance().getPreferences().getValue("view/only_show_top_layers"))
|
||||
self._compatibility_mode = self._evaluateCompatibilityMode()
|
||||
|
||||
self.setSimulationViewType(int(float(Preferences.getInstance().getValue("layerview/layer_view_type"))));
|
||||
self.setSimulationViewType(int(float(Application.getInstance().getPreferences().getValue("layerview/layer_view_type"))));
|
||||
|
||||
for extruder_nr, extruder_opacity in enumerate(Preferences.getInstance().getValue("layerview/extruder_opacities").split("|")):
|
||||
for extruder_nr, extruder_opacity in enumerate(Application.getInstance().getPreferences().getValue("layerview/extruder_opacities").split("|")):
|
||||
try:
|
||||
opacity = float(extruder_opacity)
|
||||
except ValueError:
|
||||
opacity = 1.0
|
||||
self.setExtruderOpacity(extruder_nr, opacity)
|
||||
|
||||
self.setShowTravelMoves(bool(Preferences.getInstance().getValue("layerview/show_travel_moves")))
|
||||
self.setShowHelpers(bool(Preferences.getInstance().getValue("layerview/show_helpers")))
|
||||
self.setShowSkin(bool(Preferences.getInstance().getValue("layerview/show_skin")))
|
||||
self.setShowInfill(bool(Preferences.getInstance().getValue("layerview/show_infill")))
|
||||
self.setShowTravelMoves(bool(Application.getInstance().getPreferences().getValue("layerview/show_travel_moves")))
|
||||
self.setShowHelpers(bool(Application.getInstance().getPreferences().getValue("layerview/show_helpers")))
|
||||
self.setShowSkin(bool(Application.getInstance().getPreferences().getValue("layerview/show_skin")))
|
||||
self.setShowInfill(bool(Application.getInstance().getPreferences().getValue("layerview/show_infill")))
|
||||
|
||||
self._startUpdateTopLayers()
|
||||
self.preferencesChanged.emit()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from PyQt5.QtCore import pyqtSlot, QObject
|
|||
|
||||
from UM.Extension import Extension
|
||||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
||||
from UM.Message import Message
|
||||
from UM.i18n import i18nCatalog
|
||||
|
|
@ -34,22 +33,23 @@ class SliceInfo(QObject, Extension):
|
|||
QObject.__init__(self, parent)
|
||||
Extension.__init__(self)
|
||||
Application.getInstance().getOutputDeviceManager().writeStarted.connect(self._onWriteStarted)
|
||||
Preferences.getInstance().addPreference("info/send_slice_info", True)
|
||||
Preferences.getInstance().addPreference("info/asked_send_slice_info", False)
|
||||
Application.getInstance().getPreferences().addPreference("info/send_slice_info", True)
|
||||
Application.getInstance().getPreferences().addPreference("info/asked_send_slice_info", False)
|
||||
|
||||
self._more_info_dialog = None
|
||||
self._example_data_content = None
|
||||
|
||||
if not Preferences.getInstance().getValue("info/asked_send_slice_info"):
|
||||
if not Application.getInstance().getPreferences().getValue("info/asked_send_slice_info"):
|
||||
self.send_slice_info_message = Message(catalog.i18nc("@info", "Cura collects anonymized usage statistics."),
|
||||
lifetime = 0,
|
||||
dismissable = False,
|
||||
title = catalog.i18nc("@info:title", "Collecting Data"))
|
||||
|
||||
self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None,
|
||||
description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."))
|
||||
self.send_slice_info_message.addAction("MoreInfo", name = catalog.i18nc("@action:button", "More info"), icon = None,
|
||||
description = catalog.i18nc("@action:tooltip", "See more information on what data Cura sends."), button_style = Message.ActionButtonStyle.LINK)
|
||||
|
||||
self.send_slice_info_message.addAction("Dismiss", name = catalog.i18nc("@action:button", "Allow"), icon = None,
|
||||
description = catalog.i18nc("@action:tooltip", "Allow Cura to send anonymized usage statistics to help prioritize future improvements to Cura. Some of your preferences and settings are sent, the Cura version and a hash of the models you're slicing."))
|
||||
self.send_slice_info_message.actionTriggered.connect(self.messageActionTriggered)
|
||||
self.send_slice_info_message.show()
|
||||
|
||||
|
|
@ -62,7 +62,7 @@ class SliceInfo(QObject, Extension):
|
|||
## Perform action based on user input.
|
||||
# Note that clicking "Disable" won't actually disable the data sending, but rather take the user to preferences where they can disable it.
|
||||
def messageActionTriggered(self, message_id, action_id):
|
||||
Preferences.getInstance().setValue("info/asked_send_slice_info", True)
|
||||
Application.getInstance().getPreferences().setValue("info/asked_send_slice_info", True)
|
||||
if action_id == "MoreInfo":
|
||||
self.showMoreInfoDialog()
|
||||
self.send_slice_info_message.hide()
|
||||
|
|
@ -88,11 +88,11 @@ class SliceInfo(QObject, Extension):
|
|||
|
||||
@pyqtSlot(bool)
|
||||
def setSendSliceInfo(self, enabled: bool):
|
||||
Preferences.getInstance().setValue("info/send_slice_info", enabled)
|
||||
Application.getInstance().getPreferences().setValue("info/send_slice_info", enabled)
|
||||
|
||||
def _onWriteStarted(self, output_device):
|
||||
try:
|
||||
if not Preferences.getInstance().getValue("info/send_slice_info"):
|
||||
if not Application.getInstance().getPreferences().getValue("info/send_slice_info"):
|
||||
Logger.log("d", "'info/send_slice_info' is turned off.")
|
||||
return # Do nothing, user does not want to send data
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ class SliceInfo(QObject, Extension):
|
|||
data["schema_version"] = 0
|
||||
data["cura_version"] = application.getVersion()
|
||||
|
||||
active_mode = Preferences.getInstance().getValue("cura/active_mode")
|
||||
active_mode = Application.getInstance().getPreferences().getValue("cura/active_mode")
|
||||
if active_mode == 0:
|
||||
data["active_mode"] = "recommended"
|
||||
else:
|
||||
|
|
@ -122,7 +122,7 @@ class SliceInfo(QObject, Extension):
|
|||
machine_settings_changed_by_user = True
|
||||
|
||||
data["machine_settings_changed_by_user"] = machine_settings_changed_by_user
|
||||
data["language"] = Preferences.getInstance().getValue("general/language")
|
||||
data["language"] = Application.getInstance().getPreferences().getValue("general/language")
|
||||
data["os"] = {"type": platform.system(), "version": platform.version()}
|
||||
|
||||
data["active_machine"] = {"definition_id": global_stack.definition.getId(),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
|
|||
from UM.Scene.Selection import Selection
|
||||
from UM.Resources import Resources
|
||||
from UM.Application import Application
|
||||
from UM.Preferences import Preferences
|
||||
from UM.View.RenderBatch import RenderBatch
|
||||
from UM.Settings.Validator import ValidatorState
|
||||
from UM.Math.Color import Color
|
||||
|
|
@ -23,7 +22,7 @@ class SolidView(View):
|
|||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
Preferences.getInstance().addPreference("view/show_overhang", True)
|
||||
Application.getInstance().getPreferences().addPreference("view/show_overhang", True)
|
||||
|
||||
self._enabled_shader = None
|
||||
self._disabled_shader = None
|
||||
|
|
@ -65,7 +64,7 @@ class SolidView(View):
|
|||
support_extruder_nr = global_container_stack.getExtruderPositionValueWithDefault("support_extruder_nr")
|
||||
support_angle_stack = Application.getInstance().getExtruderManager().getExtruderStack(support_extruder_nr)
|
||||
|
||||
if support_angle_stack is not None and Preferences.getInstance().getValue("view/show_overhang"):
|
||||
if support_angle_stack is not None and Application.getInstance().getPreferences().getValue("view/show_overhang"):
|
||||
angle = support_angle_stack.getProperty("support_angle", "value")
|
||||
# Make sure the overhang angle is valid before passing it to the shader
|
||||
# Note: if the overhang angle is set to its default value, it does not need to get validated (validationState = None)
|
||||
|
|
|
|||
|
|
@ -31,8 +31,9 @@ Item
|
|||
frameVisible: false
|
||||
selectionMode: 0
|
||||
model: packageData.supported_configs
|
||||
headerDelegate: Item
|
||||
headerDelegate: Rectangle
|
||||
{
|
||||
color: UM.Theme.getColor("sidebar")
|
||||
height: UM.Theme.getSize("toolbox_chart_row").height
|
||||
Label
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ Column
|
|||
// Don't allow installing while another download is running
|
||||
enabled: installed || !(toolbox.isDownloading && toolbox.activePackage != model)
|
||||
opacity: enabled ? 1.0 : 0.5
|
||||
visible: !updateButton.visible // Don't show when the update button is visible
|
||||
}
|
||||
|
||||
ToolboxProgressButton
|
||||
|
|
@ -55,7 +56,7 @@ Column
|
|||
// Don't allow installing while another download is running
|
||||
enabled: !(toolbox.isDownloading && toolbox.activePackage != model)
|
||||
opacity: enabled ? 1.0 : 0.5
|
||||
visible: installed && canUpdate
|
||||
visible: canUpdate
|
||||
}
|
||||
Connections
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ Column
|
|||
height: childrenRect.height
|
||||
width: parent.width
|
||||
spacing: UM.Theme.getSize("default_margin").height
|
||||
/* Hidden for 3.4
|
||||
Label
|
||||
{
|
||||
id: heading
|
||||
|
|
@ -20,6 +21,7 @@ Column
|
|||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("medium")
|
||||
}
|
||||
*/
|
||||
GridLayout
|
||||
{
|
||||
id: grid
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ ScrollView
|
|||
spacing: UM.Theme.getSize("default_margin").height
|
||||
padding: UM.Theme.getSize("wide_margin").height
|
||||
height: childrenRect.height + 2 * padding
|
||||
|
||||
ToolboxDownloadsShowcase
|
||||
{
|
||||
id: showcase
|
||||
|
|
@ -29,6 +30,7 @@ ScrollView
|
|||
width: parent.width
|
||||
height: UM.Theme.getSize("default_lining").height
|
||||
}
|
||||
|
||||
ToolboxDownloadsGrid
|
||||
{
|
||||
id: allPlugins
|
||||
|
|
|
|||
|
|
@ -19,10 +19,11 @@ Column
|
|||
color: UM.Theme.getColor("text_medium")
|
||||
font: UM.Theme.getFont("medium")
|
||||
}
|
||||
Row
|
||||
Grid
|
||||
{
|
||||
height: childrenRect.height
|
||||
spacing: UM.Theme.getSize("wide_margin").width
|
||||
columns: 3
|
||||
anchors
|
||||
{
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ Item
|
|||
toolbox.viewPage = "overview"
|
||||
}
|
||||
}
|
||||
|
||||
ToolboxTabButton
|
||||
{
|
||||
text: catalog.i18nc("@title:tab", "Materials")
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Item
|
|||
{
|
||||
color: UM.Theme.getColor("lining")
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("default_lining").height
|
||||
height: Math.floor(UM.Theme.getSize("default_lining").height)
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
Row
|
||||
|
|
@ -40,14 +40,14 @@ Item
|
|||
Column
|
||||
{
|
||||
id: pluginInfo
|
||||
topPadding: UM.Theme.getSize("default_margin").height / 2
|
||||
topPadding: Math.floor(UM.Theme.getSize("default_margin").height / 2)
|
||||
property var color: model.type === "plugin" && !isEnabled ? UM.Theme.getColor("lining") : UM.Theme.getColor("text")
|
||||
width: tileRow.width - (authorInfo.width + pluginActions.width + 2 * tileRow.spacing + ((disableButton.visible) ? disableButton.width + tileRow.spacing : 0))
|
||||
width: Math.floor(tileRow.width - (authorInfo.width + pluginActions.width + 2 * tileRow.spacing + ((disableButton.visible) ? disableButton.width + tileRow.spacing : 0)))
|
||||
Label
|
||||
{
|
||||
text: model.name
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("toolbox_property_label").height
|
||||
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
|
||||
wrapMode: Text.WordWrap
|
||||
font: UM.Theme.getFont("default_bold")
|
||||
color: pluginInfo.color
|
||||
|
|
@ -81,7 +81,7 @@ Item
|
|||
}
|
||||
}
|
||||
width: parent.width
|
||||
height: UM.Theme.getSize("toolbox_property_label").height
|
||||
height: Math.floor(UM.Theme.getSize("toolbox_property_label").height)
|
||||
wrapMode: Text.WordWrap
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
|
|
|||
|
|
@ -13,6 +13,16 @@ Column
|
|||
width: UM.Theme.getSize("toolbox_action_button").width
|
||||
spacing: UM.Theme.getSize("narrow_margin").height
|
||||
|
||||
Label
|
||||
{
|
||||
visible: !model.is_installed
|
||||
text: catalog.i18nc("@label", "Will install upon restarting")
|
||||
color: UM.Theme.getColor("lining")
|
||||
font: UM.Theme.getFont("default")
|
||||
wrapMode: Text.WordWrap
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
ToolboxProgressButton
|
||||
{
|
||||
id: updateButton
|
||||
|
|
@ -39,7 +49,7 @@ Column
|
|||
{
|
||||
id: removeButton
|
||||
text: canDowngrade ? catalog.i18nc("@action:button", "Downgrade") : catalog.i18nc("@action:button", "Uninstall")
|
||||
visible: !model.is_bundled
|
||||
visible: !model.is_bundled && model.is_installed
|
||||
enabled: !toolbox.isDownloading
|
||||
style: ButtonStyle
|
||||
{
|
||||
|
|
|
|||
|
|
@ -150,7 +150,7 @@ Item
|
|||
{
|
||||
id: loader
|
||||
visible: active
|
||||
source: "../images/loading.gif"
|
||||
source: visible ? "../images/loading.gif" : ""
|
||||
width: UM.Theme.getSize("toolbox_loader").width
|
||||
height: UM.Theme.getSize("toolbox_loader").height
|
||||
anchors.right: button.left
|
||||
|
|
|
|||
|
|
@ -29,8 +29,9 @@ class PackagesModel(ListModel):
|
|||
self.addRoleName(Qt.UserRole + 12, "last_updated")
|
||||
self.addRoleName(Qt.UserRole + 13, "is_bundled")
|
||||
self.addRoleName(Qt.UserRole + 14, "is_enabled")
|
||||
self.addRoleName(Qt.UserRole + 15, "has_configs")
|
||||
self.addRoleName(Qt.UserRole + 16, "supported_configs")
|
||||
self.addRoleName(Qt.UserRole + 15, "is_installed") # Scheduled pkgs are included in the model but should not be marked as actually installed
|
||||
self.addRoleName(Qt.UserRole + 16, "has_configs")
|
||||
self.addRoleName(Qt.UserRole + 17, "supported_configs")
|
||||
|
||||
# List of filters for queries. The result is the union of the each list of results.
|
||||
self._filter = {} # type: Dict[str, str]
|
||||
|
|
@ -73,6 +74,7 @@ class PackagesModel(ListModel):
|
|||
"last_updated": package["last_updated"] if "last_updated" in package else None,
|
||||
"is_bundled": package["is_bundled"] if "is_bundled" in package else False,
|
||||
"is_enabled": package["is_enabled"] if "is_enabled" in package else False,
|
||||
"is_installed": package["is_installed"] if "is_installed" in package else False,
|
||||
"has_configs": has_configs,
|
||||
"supported_configs": configs_model
|
||||
})
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ i18n_catalog = i18nCatalog("cura")
|
|||
## The Toolbox class is responsible of communicating with the server through the API
|
||||
class Toolbox(QObject, Extension):
|
||||
|
||||
DEFAULT_PACKAGES_API_ROOT = "https://api.ultimaker.com"
|
||||
DEFAULT_CLOUD_API_ROOT = "https://api.ultimaker.com"
|
||||
DEFAULT_CLOUD_API_VERSION = 1
|
||||
|
||||
def __init__(self, parent=None) -> None:
|
||||
super().__init__(parent)
|
||||
|
|
@ -36,14 +37,11 @@ class Toolbox(QObject, Extension):
|
|||
self._application = Application.getInstance()
|
||||
self._package_manager = None
|
||||
self._plugin_registry = Application.getInstance().getPluginRegistry()
|
||||
self._packages_api_root = self._getPackagesApiRoot()
|
||||
self._packages_version = self._getPackagesVersion()
|
||||
self._api_version = 1
|
||||
self._api_url = "{api_root}/cura-packages/v{api_version}/cura/v{package_version}".format(
|
||||
api_root = self._packages_api_root,
|
||||
api_version = self._api_version,
|
||||
package_version = self._packages_version
|
||||
)
|
||||
|
||||
self._sdk_version = None
|
||||
self._cloud_api_version = None
|
||||
self._cloud_api_root = None
|
||||
self._api_url = None
|
||||
|
||||
# Network:
|
||||
self._get_packages_request = None
|
||||
|
|
@ -64,21 +62,19 @@ class Toolbox(QObject, Extension):
|
|||
)
|
||||
)
|
||||
]
|
||||
self._request_urls = {
|
||||
"authors": QUrl("{base_url}/authors".format(base_url = self._api_url)),
|
||||
"packages": QUrl("{base_url}/packages".format(base_url = self._api_url)),
|
||||
"plugins_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url)),
|
||||
"materials_showcase": QUrl("{base_url}/showcase".format(base_url = self._api_url))
|
||||
}
|
||||
self._request_urls = {}
|
||||
self._to_update = [] # Package_ids that are waiting to be updated
|
||||
self._old_plugin_ids = []
|
||||
|
||||
# Data:
|
||||
self._metadata = {
|
||||
"authors": [],
|
||||
"packages": [],
|
||||
"plugins_showcase": [],
|
||||
"plugins_available": [],
|
||||
"plugins_installed": [],
|
||||
"materials_showcase": [],
|
||||
"materials_available": [],
|
||||
"materials_installed": []
|
||||
}
|
||||
|
||||
|
|
@ -161,22 +157,52 @@ class Toolbox(QObject, Extension):
|
|||
# this is initialized. Therefore, we wait until the application is ready.
|
||||
def _onAppInitialized(self) -> None:
|
||||
self._package_manager = Application.getInstance().getPackageManager()
|
||||
self._sdk_version = self._getSDKVersion()
|
||||
self._cloud_api_version = self._getCloudAPIVersion()
|
||||
self._cloud_api_root = self._getCloudAPIRoot()
|
||||
self._api_url = "{cloud_api_root}/cura-packages/v{cloud_api_version}/cura/v{sdk_version}".format(
|
||||
cloud_api_root=self._cloud_api_root,
|
||||
cloud_api_version=self._cloud_api_version,
|
||||
sdk_version=self._sdk_version
|
||||
)
|
||||
self._request_urls = {
|
||||
"authors": QUrl("{base_url}/authors".format(base_url=self._api_url)),
|
||||
"packages": QUrl("{base_url}/packages".format(base_url=self._api_url)),
|
||||
"plugins_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)),
|
||||
"plugins_available": QUrl("{base_url}/packages?package_type=plugin".format(base_url=self._api_url)),
|
||||
"materials_showcase": QUrl("{base_url}/showcase".format(base_url=self._api_url)),
|
||||
"materials_available": QUrl("{base_url}/packages?package_type=material".format(base_url=self._api_url))
|
||||
}
|
||||
|
||||
# Get the API root for the packages API depending on Cura version settings.
|
||||
def _getPackagesApiRoot(self) -> str:
|
||||
def _getCloudAPIRoot(self) -> str:
|
||||
if not hasattr(cura, "CuraVersion"):
|
||||
return self.DEFAULT_PACKAGES_API_ROOT
|
||||
if not hasattr(cura.CuraVersion, "CuraPackagesApiRoot"):
|
||||
return self.DEFAULT_PACKAGES_API_ROOT
|
||||
return cura.CuraVersion.CuraPackagesApiRoot
|
||||
return self.DEFAULT_CLOUD_API_ROOT
|
||||
if not hasattr(cura.CuraVersion, "CuraCloudAPIRoot"):
|
||||
return self.DEFAULT_CLOUD_API_ROOT
|
||||
if not cura.CuraVersion.CuraCloudAPIRoot:
|
||||
return self.DEFAULT_CLOUD_API_ROOT
|
||||
return cura.CuraVersion.CuraCloudAPIRoot
|
||||
|
||||
# Get the cloud API version from CuraVersion
|
||||
def _getCloudAPIVersion(self) -> int:
|
||||
if not hasattr(cura, "CuraVersion"):
|
||||
return self.DEFAULT_CLOUD_API_VERSION
|
||||
if not hasattr(cura.CuraVersion, "CuraCloudAPIVersion"):
|
||||
return self.DEFAULT_CLOUD_API_VERSION
|
||||
if not cura.CuraVersion.CuraCloudAPIVersion:
|
||||
return self.DEFAULT_CLOUD_API_VERSION
|
||||
return cura.CuraVersion.CuraCloudAPIVersion
|
||||
|
||||
# Get the packages version depending on Cura version settings.
|
||||
def _getPackagesVersion(self) -> int:
|
||||
def _getSDKVersion(self) -> int:
|
||||
if not hasattr(cura, "CuraVersion"):
|
||||
return self._plugin_registry.APIVersion
|
||||
if not hasattr(cura.CuraVersion, "CuraPackagesVersion"):
|
||||
if not hasattr(cura.CuraVersion, "CuraSDKVersion"):
|
||||
return self._plugin_registry.APIVersion
|
||||
return cura.CuraVersion.CuraPackagesVersion
|
||||
if not cura.CuraVersion.CuraSDKVersion:
|
||||
return self._plugin_registry.APIVersion
|
||||
return cura.CuraVersion.CuraSDKVersion
|
||||
|
||||
@pyqtSlot()
|
||||
def browsePackages(self) -> None:
|
||||
|
|
@ -212,15 +238,52 @@ class Toolbox(QObject, Extension):
|
|||
dialog = Application.getInstance().createQmlComponent(path, {"toolbox": self})
|
||||
return dialog
|
||||
|
||||
|
||||
def _convertPluginMetadata(self, plugin: dict) -> dict:
|
||||
formatted = {
|
||||
"package_id": plugin["id"],
|
||||
"package_type": "plugin",
|
||||
"display_name": plugin["plugin"]["name"],
|
||||
"package_version": plugin["plugin"]["version"],
|
||||
"sdk_version": plugin["plugin"]["api"],
|
||||
"author": {
|
||||
"author_id": plugin["plugin"]["author"],
|
||||
"display_name": plugin["plugin"]["author"]
|
||||
},
|
||||
"is_installed": True,
|
||||
"description": plugin["plugin"]["description"]
|
||||
}
|
||||
return formatted
|
||||
|
||||
@pyqtSlot()
|
||||
def _updateInstalledModels(self) -> None:
|
||||
|
||||
# This is moved here to avoid code duplication and so that after installing plugins they get removed from the
|
||||
# list of old plugins
|
||||
old_plugin_ids = self._plugin_registry.getInstalledPlugins()
|
||||
installed_package_ids = self._package_manager.getAllInstalledPackageIDs()
|
||||
|
||||
self._old_plugin_ids = []
|
||||
self._old_plugin_metadata = []
|
||||
|
||||
for plugin_id in old_plugin_ids:
|
||||
if plugin_id not in installed_package_ids:
|
||||
Logger.log('i', 'Found a plugin that was installed with the old plugin browser: %s', plugin_id)
|
||||
|
||||
old_metadata = self._plugin_registry.getMetaData(plugin_id)
|
||||
new_metadata = self._convertPluginMetadata(old_metadata)
|
||||
|
||||
self._old_plugin_ids.append(plugin_id)
|
||||
self._old_plugin_metadata.append(new_metadata)
|
||||
|
||||
all_packages = self._package_manager.getAllInstalledPackagesInfo()
|
||||
if "plugin" in all_packages:
|
||||
self._metadata["plugins_installed"] = all_packages["plugin"]
|
||||
self._metadata["plugins_installed"] = all_packages["plugin"] + self._old_plugin_metadata
|
||||
self._models["plugins_installed"].setMetadata(self._metadata["plugins_installed"])
|
||||
self.metadataChanged.emit()
|
||||
if "material" in all_packages:
|
||||
self._metadata["materials_installed"] = all_packages["material"]
|
||||
# TODO: ADD MATERIALS HERE ONCE MATERIALS PORTION OF TOOLBOX IS LIVE
|
||||
self._models["materials_installed"].setMetadata(self._metadata["materials_installed"])
|
||||
self.metadataChanged.emit()
|
||||
|
||||
|
|
@ -250,8 +313,6 @@ class Toolbox(QObject, Extension):
|
|||
if remote_package:
|
||||
download_url = remote_package["download_url"]
|
||||
Logger.log("d", "Updating package [%s]..." % plugin_id)
|
||||
if self._package_manager.isUserInstalledPackage(plugin_id):
|
||||
self.uninstall(plugin_id)
|
||||
self.startDownload(download_url)
|
||||
else:
|
||||
Logger.log("e", "Could not update package [%s] because there is no remote package info available.", plugin_id)
|
||||
|
|
@ -306,6 +367,9 @@ class Toolbox(QObject, Extension):
|
|||
# --------------------------------------------------------------------------
|
||||
@pyqtSlot(str, result = bool)
|
||||
def canUpdate(self, package_id: str) -> bool:
|
||||
if self.isOldPlugin(package_id):
|
||||
return True
|
||||
|
||||
local_package = self._package_manager.getInstalledPackageInfo(package_id)
|
||||
if local_package is None:
|
||||
return False
|
||||
|
|
@ -318,19 +382,21 @@ class Toolbox(QObject, Extension):
|
|||
remote_version = Version(remote_package["package_version"])
|
||||
return remote_version > local_version
|
||||
|
||||
@pyqtSlot(str, result=bool)
|
||||
@pyqtSlot(str, result = bool)
|
||||
def canDowngrade(self, package_id: str) -> bool:
|
||||
# If the currently installed version is higher than the bundled version (if present), the we can downgrade
|
||||
# this package.
|
||||
local_package = self._package_manager.getInstalledPackageInfo(package_id)
|
||||
if local_package is None:
|
||||
return False
|
||||
|
||||
remote_package = self.getRemotePackage(package_id)
|
||||
if remote_package is None:
|
||||
bundled_package = self._package_manager.getBundledPackageInfo(package_id)
|
||||
if bundled_package is None:
|
||||
return False
|
||||
|
||||
local_version = Version(local_package["package_version"])
|
||||
remote_version = Version(remote_package["package_version"])
|
||||
return remote_version < local_version
|
||||
bundled_version = Version(bundled_package["package_version"])
|
||||
return bundled_version < local_version
|
||||
|
||||
@pyqtSlot(str, result = bool)
|
||||
def isInstalled(self, package_id: str) -> bool:
|
||||
|
|
@ -342,6 +408,13 @@ class Toolbox(QObject, Extension):
|
|||
return True
|
||||
return False
|
||||
|
||||
# Check for plugins that were installed with the old plugin browser
|
||||
@pyqtSlot(str, result = bool)
|
||||
def isOldPlugin(self, plugin_id: str) -> bool:
|
||||
if plugin_id in self._old_plugin_ids:
|
||||
return True
|
||||
return False
|
||||
|
||||
def loadingComplete(self) -> bool:
|
||||
populated = 0
|
||||
for list in self._metadata.items():
|
||||
|
|
@ -383,7 +456,10 @@ class Toolbox(QObject, Extension):
|
|||
|
||||
def resetDownload(self) -> None:
|
||||
if self._download_reply:
|
||||
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
||||
try:
|
||||
self._download_reply.downloadProgress.disconnect(self._onDownloadProgress)
|
||||
except TypeError: #Raised when the method is not connected to the signal yet.
|
||||
pass #Don't need to disconnect.
|
||||
self._download_reply.abort()
|
||||
self._download_reply = None
|
||||
self._download_request = None
|
||||
|
|
|
|||
|
|
@ -148,6 +148,10 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
def selectPrinter(self, target_printer: str = "") -> None:
|
||||
self._sending_job.send(target_printer)
|
||||
|
||||
@pyqtSlot()
|
||||
def cancelPrintSelection(self) -> None:
|
||||
self._sending_gcode = False
|
||||
|
||||
## Greenlet to send a job to the printer over the network.
|
||||
#
|
||||
# This greenlet gets called asynchronously in requestWrite. It is a
|
||||
|
|
@ -388,7 +392,7 @@ class ClusterUM3OutputDevice(NetworkedPrinterOutputDevice):
|
|||
self._updatePrintJob(print_job, print_job_data)
|
||||
|
||||
if print_job.state != "queued": # Print job should be assigned to a printer.
|
||||
if print_job.state in ["failed", "finished", "aborted"]:
|
||||
if print_job.state in ["failed", "finished", "aborted", "none"]:
|
||||
# Print job was already completed, so don't attach it to a printer.
|
||||
printer = None
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ UM.Dialog
|
|||
onClicked: {
|
||||
base.visible = false;
|
||||
printerSelectionCombobox.currentIndex = 0
|
||||
OutputDevice.cancelPrintSelection()
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
|||
from UM.Logger import Logger
|
||||
from UM.Application import Application
|
||||
from UM.Signal import Signal, signalemitter
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Version import Version
|
||||
|
||||
from . import ClusterUM3OutputDevice, LegacyUM3OutputDevice
|
||||
|
|
@ -54,7 +53,7 @@ class UM3OutputDevicePlugin(OutputDevicePlugin):
|
|||
self._cluster_api_prefix = "/cluster-api/v" + self._cluster_api_version + "/"
|
||||
|
||||
# Get list of manual instances from preferences
|
||||
self._preferences = Preferences.getInstance()
|
||||
self._preferences = Application.getInstance().getPreferences()
|
||||
self._preferences.addPreference("um3networkprinting/manual_instances",
|
||||
"") # A comma-separated list of ip adresses or hostnames
|
||||
|
||||
|
|
|
|||
|
|
@ -379,13 +379,14 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
|
|||
|
||||
def resumePrint(self):
|
||||
self._paused = False
|
||||
self._sendNextGcodeLine() #Send one line of g-code next so that we'll trigger an "ok" response loop even if we're not polling temperatures.
|
||||
|
||||
def cancelPrint(self):
|
||||
self._gcode_position = 0
|
||||
self._gcode.clear()
|
||||
self._printers[0].updateActivePrintJob(None)
|
||||
self._is_printing = False
|
||||
self._is_paused = False
|
||||
self._paused = False
|
||||
|
||||
# Turn off temperatures, fan and steppers
|
||||
self._sendCommand("M140 S0")
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Signal import Signal, signalemitter
|
||||
from UM.Application import Application
|
||||
from UM.Resources import Resources
|
||||
import threading
|
||||
import platform
|
||||
import time
|
||||
import serial.tools.list_ports
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.Resources import Resources
|
||||
from UM.Signal import Signal, signalemitter
|
||||
from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin
|
||||
from UM.i18n import i18nCatalog
|
||||
|
||||
|
|
@ -12,12 +18,6 @@ from cura.PrinterOutputDevice import ConnectionState
|
|||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
from . import USBPrinterOutputDevice
|
||||
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
|
||||
|
||||
import threading
|
||||
import platform
|
||||
import time
|
||||
import serial.tools.list_ports
|
||||
|
||||
i18n_catalog = i18nCatalog("cura")
|
||||
|
||||
|
|
@ -28,8 +28,14 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
|
|||
addUSBOutputDeviceSignal = Signal()
|
||||
progressChanged = pyqtSignal()
|
||||
|
||||
def __init__(self, parent = None):
|
||||
def __init__(self, application, parent = None):
|
||||
if USBPrinterOutputDeviceManager.__instance is not None:
|
||||
raise RuntimeError("Try to create singleton '%s' more than once" % self.__class__.__name__)
|
||||
USBPrinterOutputDeviceManager.__instance = self
|
||||
|
||||
super().__init__(parent = parent)
|
||||
self._application = application
|
||||
|
||||
self._serial_port_list = []
|
||||
self._usb_output_devices = {}
|
||||
self._usb_output_devices_model = None
|
||||
|
|
@ -38,11 +44,11 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
|
|||
|
||||
self._check_updates = True
|
||||
|
||||
Application.getInstance().applicationShuttingDown.connect(self.stop)
|
||||
self._application.applicationShuttingDown.connect(self.stop)
|
||||
# Because the model needs to be created in the same thread as the QMLEngine, we use a signal.
|
||||
self.addUSBOutputDeviceSignal.connect(self.addOutputDevice)
|
||||
|
||||
Application.getInstance().globalContainerStackChanged.connect(self.updateUSBPrinterOutputDevices)
|
||||
self._application.globalContainerStackChanged.connect(self.updateUSBPrinterOutputDevices)
|
||||
|
||||
# The method updates/reset the USB settings for all connected USB devices
|
||||
def updateUSBPrinterOutputDevices(self):
|
||||
|
|
@ -69,7 +75,7 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
|
|||
|
||||
def _updateThread(self):
|
||||
while self._check_updates:
|
||||
container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
container_stack = self._application.getGlobalContainerStack()
|
||||
if container_stack is None:
|
||||
time.sleep(5)
|
||||
continue
|
||||
|
|
@ -81,19 +87,10 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
|
|||
self._addRemovePorts(port_list)
|
||||
time.sleep(5)
|
||||
|
||||
## Return the singleton instance of the USBPrinterManager
|
||||
@classmethod
|
||||
def getInstance(cls, engine = None, script_engine = None):
|
||||
# Note: Explicit use of class name to prevent issues with inheritance.
|
||||
if USBPrinterOutputDeviceManager._instance is None:
|
||||
USBPrinterOutputDeviceManager._instance = cls()
|
||||
|
||||
return USBPrinterOutputDeviceManager._instance
|
||||
|
||||
@pyqtSlot(result = str)
|
||||
def getDefaultFirmwareName(self):
|
||||
# Check if there is a valid global container stack
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
global_container_stack = self._application.getGlobalContainerStack()
|
||||
if not global_container_stack:
|
||||
Logger.log("e", "There is no global container stack. Can not update firmware.")
|
||||
self._firmware_view.close()
|
||||
|
|
@ -182,4 +179,8 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin):
|
|||
|
||||
return list(base_list)
|
||||
|
||||
_instance = None # type: "USBPrinterOutputDeviceManager"
|
||||
__instance = None
|
||||
|
||||
@classmethod
|
||||
def getInstance(cls, *args, **kwargs) -> "USBPrinterOutputDeviceManager":
|
||||
return cls.__instance
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ def register(app):
|
|||
# We are violating the QT API here (as we use a factory, which is technically not allowed).
|
||||
# but we don't really have another means for doing this (and it seems to you know -work-)
|
||||
qmlRegisterSingletonType(USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager, "Cura", 1, 0, "USBPrinterManager", USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager.getInstance)
|
||||
return {"output_device": USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager.getInstance()}
|
||||
return {"output_device": USBPrinterOutputDeviceManager.USBPrinterOutputDeviceManager(app)}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,26 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from UM.Extension import Extension
|
||||
from UM.Preferences import Preferences
|
||||
from UM.Application import Application
|
||||
from UM.PluginRegistry import PluginRegistry
|
||||
from UM.Logger import Logger
|
||||
|
||||
from cura.CuraApplication import CuraApplication
|
||||
import os
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSlot
|
||||
|
||||
import os.path
|
||||
from UM.Extension import Extension
|
||||
from UM.Logger import Logger
|
||||
|
||||
|
||||
class UserAgreement(QObject, Extension):
|
||||
def __init__(self):
|
||||
def __init__(self, application):
|
||||
super(UserAgreement, self).__init__()
|
||||
self._application = application
|
||||
self._user_agreement_window = None
|
||||
self._user_agreement_context = None
|
||||
Application.getInstance().engineCreatedSignal.connect(self._onEngineCreated)
|
||||
Preferences.getInstance().addPreference("general/accepted_user_agreement", False)
|
||||
self._application.engineCreatedSignal.connect(self._onEngineCreated)
|
||||
|
||||
self._application.getPreferences().addPreference("general/accepted_user_agreement", False)
|
||||
|
||||
def _onEngineCreated(self):
|
||||
if not Preferences.getInstance().getValue("general/accepted_user_agreement"):
|
||||
if not self._application.getPreferences().getValue("general/accepted_user_agreement"):
|
||||
self.showUserAgreement()
|
||||
|
||||
def showUserAgreement(self):
|
||||
|
|
@ -35,14 +33,14 @@ class UserAgreement(QObject, Extension):
|
|||
def didAgree(self, user_choice):
|
||||
if user_choice:
|
||||
Logger.log("i", "User agreed to the user agreement")
|
||||
Preferences.getInstance().setValue("general/accepted_user_agreement", True)
|
||||
self._application.getPreferences().setValue("general/accepted_user_agreement", True)
|
||||
self._user_agreement_window.hide()
|
||||
else:
|
||||
Logger.log("i", "User did NOT agree to the user agreement")
|
||||
Preferences.getInstance().setValue("general/accepted_user_agreement", False)
|
||||
CuraApplication.getInstance().quit()
|
||||
CuraApplication.getInstance().setNeedToShowUserAgreement(False)
|
||||
self._application.getPreferences().setValue("general/accepted_user_agreement", False)
|
||||
self._application.quit()
|
||||
self._application.setNeedToShowUserAgreement(False)
|
||||
|
||||
def createUserAgreementWindow(self):
|
||||
path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "UserAgreement.qml")
|
||||
self._user_agreement_window = Application.getInstance().createQmlComponent(path, {"manager": self})
|
||||
path = os.path.join(self._application.getPluginRegistry().getPluginPath(self.getPluginId()), "UserAgreement.qml")
|
||||
self._user_agreement_window = self._application.createQmlComponent(path, {"manager": self})
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ def getMetaData():
|
|||
return {}
|
||||
|
||||
def register(app):
|
||||
return {"extension": UserAgreement.UserAgreement()}
|
||||
return {"extension": UserAgreement.UserAgreement(app)}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,12 @@ class MachineInstance:
|
|||
user_profile["values"] = {}
|
||||
|
||||
version_upgrade_manager = UM.VersionUpgradeManager.VersionUpgradeManager.getInstance()
|
||||
user_storage = os.path.join(Resources.getDataStoragePath(), next(iter(version_upgrade_manager.getStoragePaths("user"))))
|
||||
user_version_to_paths_dict = version_upgrade_manager.getStoragePaths("user")
|
||||
paths_set = set()
|
||||
for paths in user_version_to_paths_dict.values():
|
||||
paths_set |= paths
|
||||
|
||||
user_storage = os.path.join(Resources.getDataStoragePath(), next(iter(paths_set)))
|
||||
user_profile_file = os.path.join(user_storage, urllib.parse.quote_plus(self._name) + "_current_settings.inst.cfg")
|
||||
if not os.path.exists(user_storage):
|
||||
os.makedirs(user_storage)
|
||||
|
|
@ -135,4 +140,4 @@ class MachineInstance:
|
|||
|
||||
output = io.StringIO()
|
||||
config.write(output)
|
||||
return [self._filename], [output.getvalue()]
|
||||
return [self._filename], [output.getvalue()]
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import io #To serialise the preference files afterwards.
|
|||
|
||||
from UM.VersionUpgrade import VersionUpgrade #We're inheriting from this.
|
||||
|
||||
_renamed_settings = {
|
||||
"infill_hollow": "infill_support_enabled"
|
||||
}
|
||||
|
||||
## Upgrades configurations from the state they were in at version 3.3 to the
|
||||
# state they should be in at version 3.4.
|
||||
|
|
@ -38,6 +41,17 @@ class VersionUpgrade33to34(VersionUpgrade):
|
|||
# Update version number.
|
||||
parser["general"]["version"] = "4"
|
||||
|
||||
if "values" in parser:
|
||||
#If infill_hollow was enabled and the overhang angle was adjusted, copy that overhang angle to the new infill support angle.
|
||||
if "infill_hollow" in parser["values"] and parser["values"]["infill_hollow"] and "support_angle" in parser["values"]:
|
||||
parser["values"]["infill_support_angle"] = parser["values"]["support_angle"]
|
||||
|
||||
#Renamed settings.
|
||||
for original, replacement in _renamed_settings.items():
|
||||
if original in parser["values"]:
|
||||
parser["values"][replacement] = parser["values"][original]
|
||||
del parser["values"][original]
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
return [filename], [result.getvalue()]
|
||||
|
|
@ -21,7 +21,7 @@ def getMetaData():
|
|||
},
|
||||
"quality_changes": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
"location": {"./quality"}
|
||||
"location": {"./quality_changes"}
|
||||
},
|
||||
"user": {
|
||||
"get_version": upgrade.getCfgVersion,
|
||||
|
|
|
|||
|
|
@ -38,14 +38,14 @@ class Shape:
|
|||
self.name = name
|
||||
|
||||
class X3DReader(MeshReader):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
def __init__(self, application):
|
||||
super().__init__(application)
|
||||
self._supported_extensions = [".x3d"]
|
||||
self._namespaces = {}
|
||||
|
||||
# Main entry point
|
||||
# Reads the file, returns a SceneNode (possibly with nested ones), or None
|
||||
def read(self, file_name):
|
||||
def _read(self, file_name):
|
||||
try:
|
||||
self.defs = {}
|
||||
self.shapes = []
|
||||
|
|
|
|||
|
|
@ -16,4 +16,4 @@ def getMetaData():
|
|||
}
|
||||
|
||||
def register(app):
|
||||
return { "mesh_reader": X3DReader.X3DReader() }
|
||||
return { "mesh_reader": X3DReader.X3DReader(app) }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (c) 2017 Ultimaker B.V.
|
||||
# Copyright (c) 2018 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import copy
|
||||
|
|
@ -12,10 +12,10 @@ import xml.etree.ElementTree as ET
|
|||
from UM.Resources import Resources
|
||||
from UM.Logger import Logger
|
||||
from cura.CuraApplication import CuraApplication
|
||||
|
||||
import UM.Dictionary
|
||||
from UM.Settings.InstanceContainer import InstanceContainer
|
||||
from UM.Settings.ContainerRegistry import ContainerRegistry
|
||||
from UM.ConfigurationErrorMessage import ConfigurationErrorMessage
|
||||
|
||||
from .XmlMaterialValidator import XmlMaterialValidator
|
||||
|
||||
|
|
@ -540,7 +540,9 @@ class XmlMaterialProfile(InstanceContainer):
|
|||
|
||||
validation_message = XmlMaterialValidator.validateMaterialMetaData(meta_data)
|
||||
if validation_message is not None:
|
||||
raise Exception("Not valid material profile: %s" % (validation_message))
|
||||
ConfigurationErrorMessage.getInstance().addFaultyContainers(self.getId())
|
||||
Logger.log("e", "Not a valid material profile: {message}".format(message = validation_message))
|
||||
return
|
||||
|
||||
property_values = {}
|
||||
properties = data.iterfind("./um:properties/*", self.__namespaces)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue