Esempio n. 1
0
    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
Esempio n. 2
0
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()
Esempio n. 3
0
 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)
Esempio n. 4
0
    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)
Esempio n. 5
0
 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")
Esempio n. 6
0
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 {}
Esempio n. 7
0
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")
Esempio n. 8
0
    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
Esempio n. 9
0
 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)
Esempio n. 10
0
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")
Esempio n. 11
0
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")
Esempio n. 12
0
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 {}
Esempio n. 13
0
    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)
Esempio n. 14
0
    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
Esempio n. 15
0
 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")
Esempio n. 16
0
    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 ""
Esempio n. 17
0
 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
Esempio n. 18
0
 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
Esempio n. 19
0
    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
Esempio n. 20
0
 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)
Esempio n. 21
0
    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
Esempio n. 22
0
    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)
Esempio n. 23
0
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 { }
Esempio n. 24
0
    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
Esempio n. 25
0
    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
Esempio n. 26
0
    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
Esempio n. 27
0
    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
Esempio n. 28
0
    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()
Esempio n. 29
0
    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
Esempio n. 30
0
    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
Esempio n. 31
0
    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
Esempio n. 32
0
    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
Esempio n. 33
0
    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)
        }
Esempio n. 34
0
    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)
        }
Esempio n. 35
0
    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 ""
Esempio n. 36
0
    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
Esempio n. 37
0
    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
Esempio n. 38
0
    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
Esempio n. 39
0
        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"]
Esempio n. 40
0
    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)
Esempio n. 41
0
    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)
Esempio n. 42
0
#!/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
Esempio n. 43
0
    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)
Esempio n. 44
0
            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"]
Esempio n. 45
0
    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)