def _getAllBroadcast(self): ipconfig_process = subprocess.Popen('ifconfig' if Platform.isLinux() or Platform.isOSX() else 'ipconfig', stdout=subprocess.PIPE, shell=True) output = ipconfig_process.stdout.read().decode('utf-8', 'ignore') allIPlist = re.findall('\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}', output) allIP = '' for j in allIPlist: if j.count('255.255') < 1: allIP += j + ' ' ipList = gethostbyname_ex(gethostname()) if len(ipList) == 3: ipList = ipList[2] broadcast = [] for i in range(len(allIPlist)): ipaddr = allIPlist[i] if ipaddr in ipList and ipaddr != '127.0.0.1' and i + 1 <= len(allIPlist): if Platform.isLinux() or Platform.isOSX(): broadcast.append(allIPlist[(i + 1)]) else: broadcast.append(self._generate_broad_addr(ipaddr, allIPlist[(i + 1)])) if not broadcast: Logger.log("w", "Cann't find valid boradcast,use all IP") broadcast = allIPlist return broadcast
def cura_app_mock(): # Taken from cura_app.py import Arcus import Savitar if Platform.isLinux(): try: import ctypes from ctypes.util import find_library libGL = find_library("GL") ctypes.CDLL(libGL, ctypes.RTLD_GLOBAL) except: pass if Platform.isLinux() and getattr(sys, "frozen", False): old_env = os.environ.get("LD_LIBRARY_PATH", "") # This is where libopenctm.so is in the AppImage. search_path = os.path.join(CuraApplication.getInstallPrefix(), "bin") path_list = old_env.split(":") if search_path not in path_list: path_list.append(search_path) os.environ["LD_LIBRARY_PATH"] = ":".join(path_list) import trimesh.exchange.load os.environ["LD_LIBRARY_PATH"] = old_env sys.argv.clear() sys.argv.append("smartslicetests") sys.argv.append("--headless") return CuraApplication()
def get_cura_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/" + CuraAppName) elif Platform.isLinux(): return os.path.expanduser("~/.local/share/" + CuraAppName) elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/" + CuraAppName)
def setBlenderPath(self, outdated=False): """Tries to set the path to blender automatically, if unsuccessful the user can set it manually. :param outdated: Flag if the found blender version is outdated. """ # Stops here because blender path from settings file is correct. if not outdated_blender_version or outdated: # Supports multi-platform if Platform.isWindows(): temp_blender_path = glob.glob( 'C:/Program Files/Blender Foundation/**/*.exe') blender_path = temp_blender_path[len(temp_blender_path) - 1].replace('\\', '/') elif Platform.isOSX(): blender_path = '/Applications/Blender.app/Contents/MacOS/Blender' elif Platform.isLinux(): blender_path = '/usr/bin/blender' else: blender_path = None # If unsuccessful the user can set it manually. if not os.path.exists(blender_path): self._openFileDialog() else: # Adds blender path in settings file. Application.getInstance().getPreferences().setValue( 'cura_blender/blender_path', blender_path) self.verifyBlenderPath(manual=False)
def get_cura_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/continuum-test") elif Platform.isLinux(): return os.path.expanduser("~/.local/share/continuum-test") elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/continuum-test")
def register(app): if Platform.isWindows() or Platform.isLinux() or Platform.isOSX(): from . import OpenSCADReader # @UnresolvedImport return {"mesh_reader": OpenSCADReader.OpenSCADReader()} else: Logger.logException("i", "Unsupported OS!") return {}
def get_cura_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Local/cura/") elif Platform.isLinux(): return os.path.expanduser("~/.local/share/cura") elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/cura")
def restore(self) -> bool: if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None): # We can restore without the minimum required information. Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.") self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup without having proper data or meta data.")) return False current_version = self._application.getVersion() version_to_restore = self.meta_data.get("cura_release", "master") if current_version < version_to_restore: # Cannot restore version newer than current because settings might have changed. Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version)) self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup that is higher than the current version.")) return False version_data_dir = Resources.getDataStoragePath() archive = ZipFile(io.BytesIO(self.zip_file), "r") extracted = self._extractArchive(archive, version_data_dir) # Under Linux, preferences are stored elsewhere, so we copy the file to there. if Platform.isLinux(): preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file) shutil.move(backup_preferences_file, preferences_file) return extracted
def get_cura_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/" + CuraAppName) elif Platform.isLinux(): return os.path.expanduser("~/.local/share/" + CuraAppName) elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/" + CuraAppName)
def get_cura_dir_for_stdoutputs() -> str: if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/cura/") elif Platform.isLinux(): return os.path.expanduser("~/.local/share/cura") elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/cura")
def get_cura_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Local/cura/") elif Platform.isLinux(): return os.path.expanduser("~/.local/share/cura") elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/cura")
def register(app): if Platform.isWindows(): from . import BigtreeWindowsRemovableDrivePlugin return { "output_device": BigtreeWindowsRemovableDrivePlugin. BigtreeWindowsRemovableDrivePlugin() } elif Platform.isOSX(): from . import BigtreeOSXRemovableDrivePlugin return { "output_device": BigtreeOSXRemovableDrivePlugin.BigtreeOSXRemovableDrivePlugin() } elif Platform.isLinux(): from . import BigtreeLinuxRemovableDrivePlugin return { "output_device": BigtreeLinuxRemovableDrivePlugin.BigtreeLinuxRemovableDrivePlugin( ) } else: Logger.log( "e", "Unsupported system, thus no removable device hotplugging support available." ) return {}
def makeFromCurrent(self) -> None: """Create a back-up from the current user config folder.""" cura_release = self._application.getVersion() version_data_dir = Resources.getDataStoragePath() Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir) # obfuscate sensitive secrets secrets = self._obfuscate() # Ensure all current settings are saved. self._application.saveSettings() # We copy the preferences file to the user data directory in Linux as it's in a different location there. # When restoring a backup on Linux, we move it back. if Platform.isLinux( ): #TODO: This should check for the config directory not being the same as the data directory, rather than hard-coding that to Linux systems. preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath( Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join( version_data_dir, "{}.cfg".format(preferences_file_name)) if os.path.exists(preferences_file) and ( not os.path.exists(backup_preferences_file) or not os.path.samefile(preferences_file, backup_preferences_file)): Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file) shutil.copyfile(preferences_file, backup_preferences_file) # Create an empty buffer and write the archive to it. buffer = io.BytesIO() archive = self._makeArchive(buffer, version_data_dir) if archive is None: return files = archive.namelist() # Count the metadata items. We do this in a rather naive way at the moment. machine_count = max( len([s for s in files if "machine_instances/" in s]) - 1, 0 ) # If people delete their profiles but not their preferences, it can still make a backup, and report -1 profiles. Server crashes on this. material_count = max( len([s for s in files if "materials/" in s]) - 1, 0) profile_count = max( len([s for s in files if "quality_changes/" in s]) - 1, 0) plugin_count = len([s for s in files if "plugin.json" in s]) # Store the archive and metadata so the BackupManager can fetch them when needed. self.zip_file = buffer.getvalue() self.meta_data = { "cura_release": cura_release, "machine_count": str(machine_count), "material_count": str(material_count), "profile_count": str(profile_count), "plugin_count": str(plugin_count) } # Restore the obfuscated settings self._illuminate(**secrets)
def restore(self) -> bool: if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None): # We can restore without the minimum required information. Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.") self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup without having proper data or meta data.")) return False current_version = self._application.getVersion() version_to_restore = self.meta_data.get("cura_release", "master") if current_version < version_to_restore: # Cannot restore version newer than current because settings might have changed. Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version)) self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup that is higher than the current version.")) return False version_data_dir = Resources.getDataStoragePath() archive = ZipFile(io.BytesIO(self.zip_file), "r") extracted = self._extractArchive(archive, version_data_dir) # Under Linux, preferences are stored elsewhere, so we copy the file to there. if Platform.isLinux(): preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file) shutil.move(backup_preferences_file, preferences_file) return extracted
def get_steslicer_dir_path(): if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/steslicer") elif Platform.isLinux(): return os.path.expanduser("~/.local/share/steslicer") elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/steslicer")
def getDefaultFirmwareName(self) -> str: """Get default firmware file name if one is specified in the firmware""" machine_has_heated_bed = self.getProperty("machine_heated_bed", "value") baudrate = 250000 if Platform.isLinux(): # Linux prefers a baudrate of 115200 here because older versions of # pySerial did not support a baudrate of 250000 baudrate = 115200 # If a firmware file is available, it should be specified in the definition for the printer hex_file = self.getMetaDataEntry("firmware_file", None) if machine_has_heated_bed: hex_file = self.getMetaDataEntry("firmware_hbk_file", hex_file) if not hex_file: Logger.log("w", "There is no firmware for machine %s.", self.getBottom().id) return "" try: return Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate)) except FileNotFoundError: Logger.log("w", "Firmware file %s not found.", hex_file) return ""
def _getDataStorageRootPath(cls): # Returns the path where we store different versions of app data data_path = None if Platform.isLinux(): try: data_path = os.environ["XDG_DATA_HOME"] except KeyError: data_path = os.path.expanduser("~/.local/share") return data_path
def _getDataStorageRootPath(cls) -> Optional[str]: # Returns the path where we store different versions of app data data_path = None if Platform.isLinux(): try: data_path = os.environ["XDG_DATA_HOME"] except KeyError: data_path = os.path.expanduser("~/.local/share") return data_path
def restore(self) -> bool: """Restore this back-up. :return: Whether we had success or not. """ if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None): # We can restore without the minimum required information. Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.") self._showMessage(self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup without having proper data or meta data."), message_type = Message.MessageType.ERROR) return False current_version = Version(self._application.getVersion()) version_to_restore = Version(self.meta_data.get("cura_release", "master")) if current_version < version_to_restore: # Cannot restore version newer than current because settings might have changed. Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version)) self._showMessage(self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup that is higher than the current version."), message_type = Message.MessageType.ERROR) return False # Get the current secrets and store since the back-up doesn't contain those secrets = self._obfuscate() version_data_dir = Resources.getDataStoragePath() try: archive = ZipFile(io.BytesIO(self.zip_file), "r") except LookupError as e: Logger.log("d", f"The following error occurred while trying to restore a Cura backup: {str(e)}") Message(self.catalog.i18nc("@info:backup_failed", "The following error occurred while trying to restore a Cura backup:") + str(e), title = self.catalog.i18nc("@info:title", "Backup"), message_type = Message.MessageType.ERROR).show() return False extracted = self._extractArchive(archive, version_data_dir) # Under Linux, preferences are stored elsewhere, so we copy the file to there. if Platform.isLinux(): preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file) shutil.move(backup_preferences_file, preferences_file) # Read the preferences from the newly restored configuration (or else the cached Preferences will override the restored ones) self._application.readPreferencesFromConfiguration() # Restore the obfuscated settings self._illuminate(**secrets) return extracted
def get_cura_dir_path(): if Platform.isWindows(): appdata_path = os.getenv("APPDATA") if not appdata_path: #Defensive against the environment variable missing (should never happen). appdata_path = "." return os.path.join(appdata_path, CuraAppName) elif Platform.isLinux(): return os.path.expanduser("~/.local/share/" + CuraAppName) elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/" + CuraAppName)
def _getPossibleDataStorageRootPathList(cls) -> List[str]: data_root_list = [] # Returns all possible root paths for storing app configurations (in old and new versions) if Platform.isLinux(): data_root_list.append(os.path.join(Resources._getDataStorageRootPath(), cls.ApplicationIdentifier)) else: # on Windows and Mac, data and config are saved in the same place data_root_list = Resources._getPossibleConfigStorageRootPathList() return data_root_list
def __init__(self): super().__init__() self._application = Application.getInstance() self._i18n_catalog = None settings_definition_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), "arcwelder_settings.def.json") try: with open(settings_definition_path, "r", encoding="utf-8") as f: self._settings_dict = json.load(f, object_pairs_hook=OrderedDict) except: Logger.logException( "e", "Could not load arc welder settings definition") return if Platform.isWindows(): arcwelder_executable = "bin/win64/ArcWelder.exe" elif Platform.isLinux(): arcwelder_executable = "bin/linux/ArcWelder" elif Platform.isOSX(): arcwelder_executable = "bin/osx/ArcWelder" self._arcwelder_path = os.path.join( os.path.dirname(os.path.abspath(__file__)), arcwelder_executable) try: os.chmod( self._arcwelder_path, stat.S_IXUSR | stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH | stat.S_IWUSR) # Make sure we have the rights to run this. except: Logger.logException("e", "Could modify rights of ArcWelder executable") return version_output = subprocess.check_output( [self._arcwelder_path, "--version"]).decode(locale.getpreferredencoding()) match = re.search("version: (.*)", version_output) if match: Logger.log("d", "Using ArcWelder %s" % match.group(1)) else: Logger.log("w", "Could not determine ArcWelder version") self._application.getPreferences().addPreference( "arcwelderplugin/settings_made_visible", False) ContainerRegistry.getInstance().containerLoadComplete.connect( self._onContainerLoadComplete) self._application.getOutputDeviceManager().writeStarted.connect( self._filterGcode)
def register(app): if Platform.isWindows(): from . import WindowsRemovableDrivePlugin return { "output_device": WindowsRemovableDrivePlugin.WindowsRemovableDrivePlugin() } elif Platform.isOSX(): from . import OSXRemovableDrivePlugin return { "output_device": OSXRemovableDrivePlugin.OSXRemovableDrivePlugin() } elif Platform.isLinux(): from . import LinuxRemovableDrivePlugin return { "output_device": LinuxRemovableDrivePlugin.LinuxRemovableDrivePlugin() } else: Logger.log("e", "Unsupported system, thus no removable device hotplugging support available.") return { }
def _getCacheStorageRootPath(cls): # Returns the path where we store different versions of app configurations cache_path = None if Platform.isWindows(): cache_path = os.getenv("LOCALAPPDATA") elif Platform.isOSX(): cache_path = None elif Platform.isLinux(): try: cache_path = os.environ["XDG_CACHE_HOME"] except KeyError: cache_path = os.path.expanduser("~/.cache") return cache_path
def _getCacheStorageRootPath(cls) -> Optional[str]: # Returns the path where we store different versions of app configurations cache_path = None if Platform.isWindows(): cache_path = os.getenv("LOCALAPPDATA") elif Platform.isOSX(): cache_path = None elif Platform.isLinux(): try: cache_path = os.environ["XDG_CACHE_HOME"] except KeyError: cache_path = os.path.expanduser("~/.cache") return cache_path
def _getConfigStorageRootPath(cls): # Returns the path where we store different versions of app configurations config_path = None if Platform.isWindows(): config_path = os.getenv("APPDATA") elif Platform.isOSX(): config_path = os.path.expanduser("~/Library/Application Support") elif Platform.isLinux(): try: config_path = os.environ["XDG_CONFIG_HOME"] except KeyError: config_path = os.path.expanduser("~/.config") else: config_path = "." return config_path
def _getConfigStorageRootPath(cls): # Returns the path where we store different versions of app configurations config_path = None if Platform.isWindows(): config_path = os.getenv("APPDATA") elif Platform.isOSX(): config_path = os.path.expanduser("~/Library/Application Support") elif Platform.isLinux(): try: config_path = os.environ["XDG_CONFIG_HOME"] except KeyError: config_path = os.path.expanduser("~/.config") else: config_path = "." return config_path
def _openFileDialog(self): """The user can set the path to blender manually. Gets called when blender isn't found in the expected place.""" global verified_blender_path message = Message(text=catalog.i18nc( '@info', 'Set your blender path manually.'), title=catalog.i18nc('@info:title', 'Blender not found')) message.show() dialog = QFileDialog() dialog.setAcceptMode(QFileDialog.AcceptOpen) # Supports multi-platform if Platform.isWindows(): dialog.setDirectory('C:/Program Files') dialog.setNameFilters(["Blender (*.exe)"]) elif Platform.isOSX(): dialog.setDirectory('/Applications') elif Platform.isLinux(): dialog.setDirectory('/usr/bin') else: dialog.setDirectory('') dialog.setFileMode(QFileDialog.ExistingFile) dialog.setViewMode(QFileDialog.Detail) # Opens the file explorer and checks if file is selected. if dialog.exec_(): message.hide() # Gets the selected blender path from file explorer. Application.getInstance().getPreferences().setValue( 'cura_blender/blender_path', ''.join(dialog.selectedFiles())) verified_blender_path = False self.verifyBlenderPath(manual=True) message = Message(text=catalog.i18nc( '@info', Application.getInstance().getPreferences().getValue( 'cura_blender/blender_path')), title=catalog.i18nc('@info:title', 'New Blenderpath set')) message.show() else: message.hide() message = Message(text=catalog.i18nc( '@info', 'No blender path was selected.'), title=catalog.i18nc('@info:title', 'Blender not found')) message.show()
def supportedPluginExtensions(self) -> List[str]: file_types = [] all_types = [] if Platform.isLinux(): for ext, desc in self._supported_file_types.items(): file_types.append("{0} (*.{1} *.{2})".format(desc, ext.lower(), ext.upper())) all_types.append("*.{0} *.{1}".format(ext.lower(), ext.upper())) else: for ext, desc in self._supported_file_types.items(): file_types.append("{0} (*.{1})".format(desc, ext)) all_types.append("*.{0}".format(ext)) file_types.sort() file_types.insert(0, i18n_catalog.i18nc("@item:inlistbox", "All Supported Types ({0})", " ".join(all_types))) file_types.append(i18n_catalog.i18nc("@item:inlistbox", "All Files (*)")) return file_types
def supportedPluginExtensions(self) -> List[str]: file_types = [] all_types = [] if Platform.isLinux(): for ext, desc in self._supported_file_types.items(): file_types.append("{0} (*.{1} *.{2})".format(desc, ext.lower(), ext.upper())) all_types.append("*.{0} *.{1}".format(ext.lower(), ext.upper())) else: for ext, desc in self._supported_file_types.items(): file_types.append("{0} (*.{1})".format(desc, ext)) all_types.append("*.{0}".format(ext)) file_types.sort() file_types.insert(0, i18n_catalog.i18nc("@item:inlistbox", "All Supported Types ({0})", " ".join(all_types))) file_types.append(i18n_catalog.i18nc("@item:inlistbox", "All Files (*)")) return file_types
def _getConfigStorageRootPath(cls) -> str: # Returns the path where we store different versions of app configurations if Platform.isWindows(): config_path = os.getenv("APPDATA") if not config_path: # Protect if the getenv function returns None (it should never happen) config_path = "." elif Platform.isOSX(): config_path = os.path.expanduser("~/Library/Application Support") elif Platform.isLinux(): try: config_path = os.environ["XDG_CONFIG_HOME"] except KeyError: config_path = os.path.expanduser("~/.config") else: config_path = "." return config_path
def _getConfigStorageRootPath(cls) -> str: # Returns the path where we store different versions of app configurations if Platform.isWindows(): config_path = os.getenv("APPDATA") if not config_path: # Protect if the getenv function returns None (it should never happen) config_path = "." elif Platform.isOSX(): config_path = os.path.expanduser("~/Library/Application Support") elif Platform.isLinux(): try: config_path = os.environ["XDG_CONFIG_HOME"] except KeyError: config_path = os.path.expanduser("~/.config") else: config_path = "." return config_path
def makeFromCurrent(self) -> None: cura_release = CuraApplication.getInstance().getVersion() version_data_dir = Resources.getDataStoragePath() Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir) # Ensure all current settings are saved. CuraApplication.getInstance().saveSettings() # We copy the preferences file to the user data directory in Linux as it's in a different location there. # When restoring a backup on Linux, we move it back. if Platform.isLinux(): preferences_file_name = CuraApplication.getInstance( ).getApplicationName() preferences_file = Resources.getPath( Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join( version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file) shutil.copyfile(preferences_file, backup_preferences_file) # Create an empty buffer and write the archive to it. buffer = io.BytesIO() archive = self._makeArchive(buffer, version_data_dir) if archive is None: return files = archive.namelist() # Count the metadata items. We do this in a rather naive way at the moment. machine_count = len([s for s in files if "machine_instances/" in s]) - 1 material_count = len([s for s in files if "materials/" in s]) - 1 profile_count = len([s for s in files if "quality_changes/" in s]) - 1 plugin_count = len([s for s in files if "plugin.json" in s]) # Store the archive and metadata so the BackupManager can fetch them when needed. self.zip_file = buffer.getvalue() self.meta_data = { "cura_release": cura_release, "machine_count": str(machine_count), "material_count": str(material_count), "profile_count": str(profile_count), "plugin_count": str(plugin_count) }
def makeFromCurrent(self) -> None: cura_release = self._application.getVersion() version_data_dir = Resources.getDataStoragePath() Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir) # Ensure all current settings are saved. self._application.saveSettings() # We copy the preferences file to the user data directory in Linux as it's in a different location there. # When restoring a backup on Linux, we move it back. if Platform.isLinux(): #TODO: This should check for the config directory not being the same as the data directory, rather than hard-coding that to Linux systems. preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) if os.path.exists(preferences_file) and (not os.path.exists(backup_preferences_file) or not os.path.samefile(preferences_file, backup_preferences_file)): Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file) shutil.copyfile(preferences_file, backup_preferences_file) # Create an empty buffer and write the archive to it. buffer = io.BytesIO() archive = self._makeArchive(buffer, version_data_dir) if archive is None: return files = archive.namelist() # Count the metadata items. We do this in a rather naive way at the moment. machine_count = len([s for s in files if "machine_instances/" in s]) - 1 material_count = len([s for s in files if "materials/" in s]) - 1 profile_count = len([s for s in files if "quality_changes/" in s]) - 1 plugin_count = len([s for s in files if "plugin.json" in s]) # Store the archive and metadata so the BackupManager can fetch them when needed. self.zip_file = buffer.getvalue() self.meta_data = { "cura_release": cura_release, "machine_count": str(machine_count), "material_count": str(material_count), "profile_count": str(profile_count), "plugin_count": str(plugin_count) }
def getDefaultFirmwareName(self) -> str: machine_has_heated_bed = self.getProperty("machine_heated_bed", "value") baudrate = 250000 if Platform.isLinux(): # Linux prefers a baudrate of 115200 here because older versions of # pySerial did not support a baudrate of 250000 baudrate = 115200 # If a firmware file is available, it should be specified in the definition for the printer hex_file = self.getMetaDataEntry("firmware_file", None) if machine_has_heated_bed: hex_file = self.getMetaDataEntry("firmware_hbk_file", hex_file) if not hex_file: Logger.log("w", "There is no firmware for machine %s.", self.getBottom().id) return "" try: return Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate)) except FileNotFoundError: Logger.log("w", "Firmware file %s not found.", hex_file) return ""
def restore(self) -> bool: """ Restore this backups :return: A boolean whether we had success or not. """ if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None): # We can restore without the minimum required information. Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.") self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup without having proper data or meta data.")) return False current_version = CuraApplication.getInstance().getVersion() version_to_restore = self.meta_data.get("cura_release", "master") if current_version != version_to_restore: # Cannot restore version older or newer than current because settings might have changed. # Restoring this will cause a lot of issues so we don't allow this for now. self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup that does not match your current version.")) return False version_data_dir = Resources.getDataStoragePath() archive = ZipFile(io.BytesIO(self.zip_file), "r") extracted = self._extractArchive(archive, version_data_dir) # Under Linux, preferences are stored elsewhere, so we copy the file to there. if Platform.isLinux(): preferences_file_name = CuraApplication.getInstance().getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file) shutil.move(backup_preferences_file, preferences_file) return extracted
def __init__(self): super().__init__() # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. executable_name = "CuraEngine" if Platform.isWindows(): executable_name += ".exe" default_engine_location = executable_name if os.path.exists(os.path.join(Application.getInstallPrefix(), "bin", executable_name)): default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", executable_name) if hasattr(sys, "frozen"): default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name) if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError("There is something wrong with your Linux installation.") for pathdir in os.getenv("PATH").split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath break if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") 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) self._scene = Application.getInstance().getController().getScene() self._scene.sceneChanged.connect(self._onSceneChanged) self._pause_slicing = False # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() self._stored_layer_data = [] self._stored_optimized_layer_data = [] # Triggers for when to (re)start slicing: self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() self._active_extruder_stack = None cura.Settings.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged() # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # This timer will group them up, and only slice for the last setting changed signal. # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction. self._change_timer = QTimer() self._change_timer.setInterval(500) self._change_timer.setSingleShot(True) self._change_timer.timeout.connect(self.slice) # Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage self._start_slice_job = None self._slicing = False # Are we currently slicing? self._restart = False # Back-end is currently restarting? self._enabled = True # Should we be slicing? Slicing might be paused when, for instance, the user is dragging the mesh around. self._always_restart = True # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness. self._process_layers_job = None # The currently active job to process layers, or None if it is not processing layers. self._backend_log_max_lines = 20000 # Maximum number of lines to buffer self._error_message = None # Pop-up message that shows errors. self.backendQuit.connect(self._onBackendQuit) self.backendConnected.connect(self._onBackendConnected) # When a tool operation is in progress, don't slice. So we need to listen for tool operations. Application.getInstance().getController().toolOperationStarted.connect(self._onToolOperationStarted) Application.getInstance().getController().toolOperationStopped.connect(self._onToolOperationStopped) self._slice_start_time = None
def __init__(self): super().__init__() # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. executable_name = "CuraEngine" if Platform.isWindows(): executable_name += ".exe" default_engine_location = executable_name if os.path.exists(os.path.join(Application.getInstallPrefix(), "bin", executable_name)): default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", executable_name) if hasattr(sys, "frozen"): default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name) if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError("There is something wrong with your Linux installation.") for pathdir in os.getenv("PATH").split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath break if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") 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) self._scene = Application.getInstance().getController().getScene() self._scene.sceneChanged.connect(self._onSceneChanged) # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() self._stored_layer_data = [] self._stored_optimized_layer_data = [] # Triggers for when to (re)start slicing: self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() self._active_extruder_stack = None cura.Settings.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged() # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # This timer will group them up, and only slice for the last setting changed signal. # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction. self._change_timer = QTimer() self._change_timer.setInterval(500) self._change_timer.setSingleShot(True) self._change_timer.timeout.connect(self.slice) # Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage self._start_slice_job = None self._slicing = False # Are we currently slicing? self._restart = False # Back-end is currently restarting? self._enabled = True # Should we be slicing? Slicing might be paused when, for instance, the user is dragging the mesh around. self._always_restart = True # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness. self._process_layers_job = None # The currently active job to process layers, or None if it is not processing layers. self._backend_log_max_lines = 20000 # Maximum number of lines to buffer self._error_message = None # Pop-up message that shows errors. self.backendQuit.connect(self._onBackendQuit) self.backendConnected.connect(self._onBackendConnected) # When a tool operation is in progress, don't slice. So we need to listen for tool operations. Application.getInstance().getController().toolOperationStarted.connect(self._onToolOperationStarted) Application.getInstance().getController().toolOperationStopped.connect(self._onToolOperationStopped) self._slice_start_time = None
if Platform.isWindows(): return os.path.expanduser("~/AppData/Roaming/" + CuraAppName) elif Platform.isLinux(): return os.path.expanduser("~/.local/share/" + CuraAppName) elif Platform.isOSX(): return os.path.expanduser("~/Library/Logs/" + CuraAppName) if hasattr(sys, "frozen"): dirpath = get_cura_dir_path() os.makedirs(dirpath, exist_ok = True) sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding = "utf-8") sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w", encoding = "utf-8") # WORKAROUND: GITHUB-88 GITHUB-385 GITHUB-612 if Platform.isLinux(): # Needed for platform.linux_distribution, which is not available on Windows and OSX # For Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826 # The workaround is only needed on Ubuntu+NVidia drivers. Other drivers are not affected, but fine with this fix. try: import ctypes from ctypes.util import find_library libGL = find_library("GL") ctypes.CDLL(libGL, ctypes.RTLD_GLOBAL) except: # GLES-only systems (e.g. ARM Mali) do not have libGL, ignore error pass # When frozen, i.e. installer version, don't let PYTHONPATH mess up the search path for DLLs. if Platform.isWindows() and hasattr(sys, "frozen"): try: del os.environ["PYTHONPATH"]
def __init__(self) -> None: """Starts the back-end plug-in. This registers all the signal listeners and prepares for communication with the back-end in general. CuraEngineBackend is exposed to qml as well. """ super().__init__() # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. executable_name = "CuraEngine" if Platform.isWindows(): executable_name += ".exe" default_engine_location = executable_name search_path = [ os.path.abspath(os.path.dirname(sys.executable)), os.path.abspath( os.path.join(os.path.dirname(sys.executable), "bin")), os.path.abspath(os.path.join(os.path.dirname(sys.executable), "..")), os.path.join(CuraApplication.getInstallPrefix(), "bin"), os.path.dirname(os.path.abspath(sys.executable)), ] for path in search_path: engine_path = os.path.join(path, executable_name) if os.path.isfile(engine_path): default_engine_location = engine_path break if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError( "There is something wrong with your Linux installation.") for pathdir in cast(str, os.getenv("PATH")).split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath break application = CuraApplication.getInstance() #type: CuraApplication self._multi_build_plate_model = None #type: Optional[MultiBuildPlateModel] self._machine_error_checker = None #type: Optional[MachineErrorChecker] if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") Logger.log("i", "Found CuraEngine at: %s", default_engine_location) default_engine_location = os.path.abspath(default_engine_location) application.getPreferences().addPreference("backend/location", default_engine_location) # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False #type: bool self._onActiveViewChanged() self._stored_layer_data = [] # type: List[Arcus.PythonMessage] self._stored_optimized_layer_data = { } # type: Dict[int, List[Arcus.PythonMessage]] # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob self._scene = application.getController().getScene() #type: Scene self._scene.sceneChanged.connect(self._onSceneChanged) # Triggers for auto-slicing. Auto-slicing is triggered as follows: # - auto-slicing is started with a timer # - whenever there is a value change, we start the timer # - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the # auto-slicing timer when that error check is finished # If there is an error check, stop the auto-slicing timer, and only wait for the error check to be finished # to start the auto-slicing timer again. # self._global_container_stack = None #type: Optional[ContainerStack] # Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers[ "cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers[ "cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers[ "cura.proto.GCodePrefix"] = self._onGCodePrefixMessage self._message_handlers[ "cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates self._message_handlers[ "cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage self._start_slice_job = None #type: Optional[StartSliceJob] self._start_slice_job_build_plate = None #type: Optional[int] self._slicing = False #type: bool # Are we currently slicing? self._restart = False #type: bool # Back-end is currently restarting? self._tool_active = False #type: bool # If a tool is active, some tasks do not have to do anything self._always_restart = True #type: bool # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness. self._process_layers_job = None #type: Optional[ProcessSlicedLayersJob] # The currently active job to process layers, or None if it is not processing layers. self._build_plates_to_be_sliced = [ ] #type: List[int] # what needs slicing? self._engine_is_fresh = True #type: bool # Is the newly started engine used before or not? self._backend_log_max_lines = 20000 #type: int # Maximum number of lines to buffer self._error_message = None #type: Optional[Message] # Pop-up message that shows errors. self._last_num_objects = defaultdict( int ) #type: Dict[int, int] # Count number of objects to see if there is something changed self._postponed_scene_change_sources = [ ] #type: List[SceneNode] # scene change is postponed (by a tool) self._slice_start_time = None #type: Optional[float] self._is_disabled = False #type: bool application.getPreferences().addPreference("general/auto_slice", False) self._use_timer = False #type: bool # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # This timer will group them up, and only slice for the last setting changed signal. # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction. self._change_timer = QTimer() #type: QTimer self._change_timer.setSingleShot(True) self._change_timer.setInterval(500) self.determineAutoSlicing() application.getPreferences().preferenceChanged.connect( self._onPreferencesChanged) application.initializationFinished.connect(self.initialize)
def __init__(self, parent=None): super().__init__(parent=parent) # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. executable_name = "CuraEngine" if Platform.isWindows(): executable_name += ".exe" default_engine_location = executable_name if os.path.exists( os.path.join(Application.getInstallPrefix(), "bin", executable_name)): default_engine_location = os.path.join( Application.getInstallPrefix(), "bin", executable_name) if hasattr(sys, "frozen"): default_engine_location = os.path.join( os.path.dirname(os.path.abspath(sys.executable)), executable_name) if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError( "There is something wrong with your Linux installation.") for pathdir in os.getenv("PATH").split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath break if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") 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) # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False Application.getInstance().getController().activeViewChanged.connect( self._onActiveViewChanged) Application.getInstance().getBuildPlateModel( ).activeBuildPlateChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() self._stored_layer_data = [] self._stored_optimized_layer_data = { } # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob self._scene = Application.getInstance().getController().getScene() self._scene.sceneChanged.connect(self._onSceneChanged) # Triggers for auto-slicing. Auto-slicing is triggered as follows: # - auto-slicing is started with a timer # - whenever there is a value change, we start the timer # - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the # auto-slicing timer when that error check is finished # If there is an error check, it will set the "_is_error_check_scheduled" flag, stop the auto-slicing timer, # and only wait for the error check to be finished to start the auto-slicing timer again. # self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect( self._onGlobalStackChanged) Application.getInstance().getExtruderManager().extrudersAdded.connect( self._onGlobalStackChanged) self._onGlobalStackChanged() Application.getInstance().stacksValidationFinished.connect( self._onStackErrorCheckFinished) # A flag indicating if an error check was scheduled # If so, we will stop the auto-slice timer and start upon the error check self._is_error_check_scheduled = False # Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers[ "cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers[ "cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers[ "cura.proto.GCodePrefix"] = self._onGCodePrefixMessage self._message_handlers[ "cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates self._message_handlers[ "cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage self._start_slice_job = None self._start_slice_job_build_plate = None self._slicing = False # Are we currently slicing? self._restart = False # Back-end is currently restarting? self._tool_active = False # If a tool is active, some tasks do not have to do anything self._always_restart = True # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness. self._process_layers_job = None # The currently active job to process layers, or None if it is not processing layers. self._build_plates_to_be_sliced = [] # what needs slicing? self._engine_is_fresh = True # Is the newly started engine used before or not? self._backend_log_max_lines = 20000 # Maximum number of lines to buffer self._error_message = None # Pop-up message that shows errors. self._last_num_objects = defaultdict( int ) # Count number of objects to see if there is something changed self._postponed_scene_change_sources = [ ] # scene change is postponed (by a tool) self.backendQuit.connect(self._onBackendQuit) self.backendConnected.connect(self._onBackendConnected) # When a tool operation is in progress, don't slice. So we need to listen for tool operations. Application.getInstance().getController().toolOperationStarted.connect( self._onToolOperationStarted) Application.getInstance().getController().toolOperationStopped.connect( self._onToolOperationStopped) self._slice_start_time = None Preferences.getInstance().addPreference("general/auto_slice", True) self._use_timer = False # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # This timer will group them up, and only slice for the last setting changed signal. # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction. self._change_timer = QTimer() self._change_timer.setSingleShot(True) self._change_timer.setInterval(500) self.determineAutoSlicing() Preferences.getInstance().preferenceChanged.connect( self._onPreferencesChanged)
#!/usr/bin/env python3 # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. import os import sys import platform import faulthandler from UM.Platform import Platform #WORKAROUND: GITHUB-88 GITHUB-385 GITHUB-612 if Platform.isLinux( ): # Needed for platform.linux_distribution, which is not available on Windows and OSX # For Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826 if platform.linux_distribution()[0] in ( "debian", "Ubuntu", "LinuxMint" ): # TODO: Needs a "if X11_GFX == 'nvidia'" here. The workaround is only needed on Ubuntu+NVidia drivers. Other drivers are not affected, but fine with this fix. import ctypes from ctypes.util import find_library libGL = find_library("GL") ctypes.CDLL(libGL, ctypes.RTLD_GLOBAL) # When frozen, i.e. installer version, don't let PYTHONPATH mess up the search path for DLLs. if Platform.isWindows() and hasattr(sys, "frozen"): try: del os.environ["PYTHONPATH"] except KeyError: pass #WORKAROUND: GITHUB-704 GITHUB-708
def __init__(self, parent = None): super().__init__(parent = parent) # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. executable_name = "CuraEngine" if Platform.isWindows(): executable_name += ".exe" default_engine_location = executable_name if os.path.exists(os.path.join(Application.getInstallPrefix(), "bin", executable_name)): default_engine_location = os.path.join(Application.getInstallPrefix(), "bin", executable_name) if hasattr(sys, "frozen"): default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name) if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError("There is something wrong with your Linux installation.") for pathdir in os.getenv("PATH").split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath break if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") 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) # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False Application.getInstance().getController().activeViewChanged.connect(self._onActiveViewChanged) self._onActiveViewChanged() self._stored_layer_data = [] self._stored_optimized_layer_data = [] self._scene = Application.getInstance().getController().getScene() self._scene.sceneChanged.connect(self._onSceneChanged) # Triggers for auto-slicing. Auto-slicing is triggered as follows: # - auto-slicing is started with a timer # - whenever there is a value change, we start the timer # - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the # auto-slicing timer when that error check is finished # If there is an error check, it will set the "_is_error_check_scheduled" flag, stop the auto-slicing timer, # and only wait for the error check to be finished to start the auto-slicing timer again. # self._global_container_stack = None Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() Application.getInstance().stacksValidationFinished.connect(self._onStackErrorCheckFinished) # A flag indicating if an error check was scheduled # If so, we will stop the auto-slice timer and start upon the error check self._is_error_check_scheduled = False # Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage self._start_slice_job = None self._slicing = False # Are we currently slicing? self._restart = False # Back-end is currently restarting? self._tool_active = False # If a tool is active, some tasks do not have to do anything self._always_restart = True # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness. self._process_layers_job = None # The currently active job to process layers, or None if it is not processing layers. self._need_slicing = False self._engine_is_fresh = True # Is the newly started engine used before or not? self._backend_log_max_lines = 20000 # Maximum number of lines to buffer self._error_message = None # Pop-up message that shows errors. self._last_num_objects = 0 # Count number of objects to see if there is something changed self._postponed_scene_change_sources = [] # scene change is postponed (by a tool) self.backendQuit.connect(self._onBackendQuit) self.backendConnected.connect(self._onBackendConnected) # When a tool operation is in progress, don't slice. So we need to listen for tool operations. Application.getInstance().getController().toolOperationStarted.connect(self._onToolOperationStarted) Application.getInstance().getController().toolOperationStopped.connect(self._onToolOperationStopped) self._slice_start_time = None Preferences.getInstance().addPreference("general/auto_slice", True) self._use_timer = False # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # This timer will group them up, and only slice for the last setting changed signal. # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction. self._change_timer = QTimer() self._change_timer.setSingleShot(True) self._change_timer.setInterval(500) self.determineAutoSlicing() Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged)
return os.path.expanduser("~/Library/Logs/" + CuraAppName) # Do not redirect stdout and stderr to files if we are running CLI. if hasattr(sys, "frozen") and "cli" not in os.path.basename( sys.argv[0]).lower(): dirpath = get_cura_dir_path() os.makedirs(dirpath, exist_ok=True) sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w", encoding="utf-8") sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w", encoding="utf-8") # WORKAROUND: GITHUB-88 GITHUB-385 GITHUB-612 if Platform.isLinux( ): # Needed for platform.linux_distribution, which is not available on Windows and OSX # For Ubuntu: https://bugs.launchpad.net/ubuntu/+source/python-qt4/+bug/941826 # The workaround is only needed on Ubuntu+NVidia drivers. Other drivers are not affected, but fine with this fix. try: import ctypes from ctypes.util import find_library libGL = find_library("GL") ctypes.CDLL(libGL, ctypes.RTLD_GLOBAL) except: # GLES-only systems (e.g. ARM Mali) do not have libGL, ignore error pass # When frozen, i.e. installer version, don't let PYTHONPATH mess up the search path for DLLs. if Platform.isWindows() and hasattr(sys, "frozen"): try: del os.environ["PYTHONPATH"]
def __init__(self) -> None: super().__init__() # Find out where the engine is located, and how it is called. # This depends on how Cura is packaged and which OS we are running on. executable_name = "CuraEngine" if Platform.isWindows(): executable_name += ".exe" default_engine_location = executable_name if os.path.exists(os.path.join(CuraApplication.getInstallPrefix(), "bin", executable_name)): default_engine_location = os.path.join(CuraApplication.getInstallPrefix(), "bin", executable_name) if hasattr(sys, "frozen"): default_engine_location = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), executable_name) if Platform.isLinux() and not default_engine_location: if not os.getenv("PATH"): raise OSError("There is something wrong with your Linux installation.") for pathdir in cast(str, os.getenv("PATH")).split(os.pathsep): execpath = os.path.join(pathdir, executable_name) if os.path.exists(execpath): default_engine_location = execpath break self._application = CuraApplication.getInstance() #type: CuraApplication self._multi_build_plate_model = None #type: Optional[MultiBuildPlateModel] self._machine_error_checker = None #type: Optional[MachineErrorChecker] if not default_engine_location: raise EnvironmentError("Could not find CuraEngine") Logger.log("i", "Found CuraEngine at: %s", default_engine_location) default_engine_location = os.path.abspath(default_engine_location) self._application.getPreferences().addPreference("backend/location", default_engine_location) # Workaround to disable layer view processing if layer view is not active. self._layer_view_active = False #type: bool self._onActiveViewChanged() self._stored_layer_data = [] # type: List[Arcus.PythonMessage] self._stored_optimized_layer_data = {} # type: Dict[int, List[Arcus.PythonMessage]] # key is build plate number, then arrays are stored until they go to the ProcessSlicesLayersJob self._scene = self._application.getController().getScene() #type: Scene self._scene.sceneChanged.connect(self._onSceneChanged) # Triggers for auto-slicing. Auto-slicing is triggered as follows: # - auto-slicing is started with a timer # - whenever there is a value change, we start the timer # - sometimes an error check can get scheduled for a value change, in that case, we ONLY want to start the # auto-slicing timer when that error check is finished # If there is an error check, stop the auto-slicing timer, and only wait for the error check to be finished # to start the auto-slicing timer again. # self._global_container_stack = None #type: Optional[ContainerStack] # Listeners for receiving messages from the back-end. self._message_handlers["cura.proto.Layer"] = self._onLayerMessage self._message_handlers["cura.proto.LayerOptimized"] = self._onOptimizedLayerMessage self._message_handlers["cura.proto.Progress"] = self._onProgressMessage self._message_handlers["cura.proto.GCodeLayer"] = self._onGCodeLayerMessage self._message_handlers["cura.proto.GCodePrefix"] = self._onGCodePrefixMessage self._message_handlers["cura.proto.PrintTimeMaterialEstimates"] = self._onPrintTimeMaterialEstimates self._message_handlers["cura.proto.SlicingFinished"] = self._onSlicingFinishedMessage self._start_slice_job = None #type: Optional[StartSliceJob] self._start_slice_job_build_plate = None #type: Optional[int] self._slicing = False #type: bool # Are we currently slicing? self._restart = False #type: bool # Back-end is currently restarting? self._tool_active = False #type: bool # If a tool is active, some tasks do not have to do anything self._always_restart = True #type: bool # Always restart the engine when starting a new slice. Don't keep the process running. TODO: Fix engine statelessness. self._process_layers_job = None #type: Optional[ProcessSlicedLayersJob] # The currently active job to process layers, or None if it is not processing layers. self._build_plates_to_be_sliced = [] #type: List[int] # what needs slicing? self._engine_is_fresh = True #type: bool # Is the newly started engine used before or not? self._backend_log_max_lines = 20000 #type: int # Maximum number of lines to buffer self._error_message = None #type: Optional[Message] # Pop-up message that shows errors. self._last_num_objects = defaultdict(int) #type: Dict[int, int] # Count number of objects to see if there is something changed self._postponed_scene_change_sources = [] #type: List[SceneNode] # scene change is postponed (by a tool) self._slice_start_time = None #type: Optional[float] self._is_disabled = False #type: bool self._application.getPreferences().addPreference("general/auto_slice", False) self._use_timer = False #type: bool # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. # This timer will group them up, and only slice for the last setting changed signal. # TODO: Properly group propertyChanged signals by whether they are triggered by the same user interaction. self._change_timer = QTimer() #type: QTimer self._change_timer.setSingleShot(True) self._change_timer.setInterval(500) self.determineAutoSlicing() self._application.getPreferences().preferenceChanged.connect(self._onPreferencesChanged) self._application.initializationFinished.connect(self.initialize)