Esempio n. 1
0
class OpenShotApp(QApplication):
    """ This class is the primary QApplication for OpenShot.
            mode=None (normal), mode=unittest (testing)"""
    def __init__(self, *args, mode=None):
        QApplication.__init__(self, *args)

        try:
            # Import modules
            from classes import info
            from classes.logger import log, reroute_output

            # Log the session's start
            import time
            log.info("------------------------------------------------")
            log.info(time.asctime().center(48))
            log.info('Starting new session'.center(48))

            from classes import settings, project_data, updates, language, ui_util, logger_libopenshot
            import openshot

            # Re-route stdout and stderr to logger
            reroute_output()
        except ImportError as ex:
            tb = traceback.format_exc()
            log.error('OpenShotApp::Import Error: %s' % str(ex))
            QMessageBox.warning(
                None, "Import Error", "Module: %(name)s\n\n%(tb)s" % {
                    "name": ex.name,
                    "tb": tb
                })
            # Stop launching and exit
            raise
            sys.exit()
        except Exception as ex:
            log.error('OpenShotApp::Init Error: %s' % str(ex))
            sys.exit()

        # Log some basic system info
        try:
            log.info("------------------------------------------------")
            log.info(
                ("OpenShot (version %s)" % info.SETUP['version']).center(48))
            log.info("------------------------------------------------")

            log.info("openshot-qt version: %s" % info.VERSION)
            log.info("libopenshot version: %s" %
                     openshot.OPENSHOT_VERSION_FULL)
            log.info("platform: %s" % platform.platform())
            log.info("processor: %s" % platform.processor())
            log.info("machine: %s" % platform.machine())
            log.info("python version: %s" % platform.python_version())
            log.info("qt5 version: %s" % QT_VERSION_STR)
            log.info("pyqt5 version: %s" % PYQT_VERSION_STR)
        except Exception:
            pass

        # Setup application
        self.setApplicationName('openshot')
        self.setApplicationVersion(info.SETUP['version'])

        # Init settings
        self.settings = settings.SettingStore()
        self.settings.load()

        # Init and attach exception handler
        from classes import exceptions
        sys.excepthook = exceptions.ExceptionHandler

        # Init translation system
        language.init_language()

        # Detect minimum libopenshot version
        _ = self._tr
        libopenshot_version = openshot.OPENSHOT_VERSION_FULL
        if mode != "unittest" and libopenshot_version < info.MINIMUM_LIBOPENSHOT_VERSION:
            QMessageBox.warning(
                None, _("Wrong Version of libopenshot Detected"),
                _("<b>Version %(minimum_version)s is required</b>, but %(current_version)s was detected. Please update libopenshot or download our latest installer."
                  ) % {
                      "minimum_version": info.MINIMUM_LIBOPENSHOT_VERSION,
                      "current_version": libopenshot_version
                  })
            # Stop launching and exit
            sys.exit()

        # Tests of project data loading/saving
        self.project = project_data.ProjectDataStore()

        # Init Update Manager
        self.updates = updates.UpdateManager()

        # It is important that the project is the first listener if the key gets update
        self.updates.add_listener(self.project)

        # Load ui theme if not set by OS
        ui_util.load_theme()

        # Test for permission issues (and display message if needed)
        try:
            # Create test paths
            TEST_PATH_DIR = os.path.join(info.USER_PATH, 'PERMISSION')
            TEST_PATH_FILE = os.path.join(TEST_PATH_DIR, 'test.osp')
            os.makedirs(TEST_PATH_DIR, exist_ok=True)
            with open(TEST_PATH_FILE, 'w') as f:
                f.write('{}')
                f.flush()
            # Delete test paths
            os.unlink(TEST_PATH_FILE)
            os.rmdir(TEST_PATH_DIR)
        except PermissionError as ex:
            log.error(
                'Failed to create PERMISSION/test.osp file (likely permissions error): %s'
                % TEST_PATH_FILE)
            QMessageBox.warning(
                None, _("Permission Error"),
                _("%(error)s. Please delete <b>%(path)s</b> and launch OpenShot again."
                  % {
                      "error": str(ex),
                      "path": info.USER_PATH
                  }))
            # Stop launching and exit
            raise
            sys.exit()

        # Start libopenshot logging thread
        self.logger_libopenshot = logger_libopenshot.LoggerLibOpenShot()
        self.logger_libopenshot.start()

        # Track which dockable window received a context menu
        self.context_menu_object = None

        # Set Font for any theme
        if self.settings.get("theme") != "No Theme":
            # Load embedded font
            try:
                log.info(
                    "Setting font to %s" %
                    os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
                font_id = QFontDatabase.addApplicationFont(
                    os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
                font_family = QFontDatabase.applicationFontFamilies(font_id)[0]
                font = QFont(font_family)
                font.setPointSizeF(10.5)
                QApplication.setFont(font)
            except Exception as ex:
                log.error("Error setting Ubuntu-R.ttf QFont: %s" % str(ex))

        # Set Experimental Dark Theme
        if self.settings.get("theme") == "Humanity: Dark":
            # Only set if dark theme selected
            log.info("Setting custom dark theme")
            self.setStyle(QStyleFactory.create("Fusion"))

            darkPalette = self.palette()

            darkPalette.setColor(QPalette.Window, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.WindowText, Qt.white)
            darkPalette.setColor(QPalette.Base, QColor(25, 25, 25))
            darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.Light, QColor(68, 68, 68))
            darkPalette.setColor(QPalette.Text, Qt.white)
            darkPalette.setColor(QPalette.Button, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ButtonText, Qt.white)
            darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218, 192))
            darkPalette.setColor(QPalette.HighlightedText, Qt.black)
            #
            # Disabled palette
            #
            darkPalette.setColor(QPalette.Disabled, QPalette.WindowText,
                                 QColor(255, 255, 255, 128))
            darkPalette.setColor(QPalette.Disabled, QPalette.Base,
                                 QColor(68, 68, 68))
            darkPalette.setColor(QPalette.Disabled, QPalette.Text,
                                 QColor(255, 255, 255, 128))
            darkPalette.setColor(QPalette.Disabled, QPalette.Button,
                                 QColor(53, 53, 53, 128))
            darkPalette.setColor(QPalette.Disabled, QPalette.ButtonText,
                                 QColor(255, 255, 255, 128))
            darkPalette.setColor(QPalette.Disabled, QPalette.Highlight,
                                 QColor(151, 151, 151, 192))
            darkPalette.setColor(QPalette.Disabled, QPalette.HighlightedText,
                                 Qt.black)

            # Tooltips
            darkPalette.setColor(QPalette.ToolTipBase, QColor(42, 130, 218))
            darkPalette.setColor(QPalette.ToolTipText, Qt.white)

            self.setPalette(darkPalette)
            self.setStyleSheet(
                "QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }"
            )

        # Create main window
        from windows.main_window import MainWindow
        self.window = MainWindow(mode)

        # Reset undo/redo history
        self.updates.reset()
        self.window.updateStatusChanged(False, False)

        log.info('Process command-line arguments: %s' % args)
        if len(args[0]) == 2:
            path = args[0][1]
            if ".osp" in path:
                # Auto load project passed as argument
                self.window.OpenProjectSignal.emit(path)
            else:
                # Apply the default settings and Auto import media file
                self.project.load("")
                self.window.filesTreeView.add_file(path)
        else:
            # Recover backup file (this can't happen until after the Main Window has completely loaded)
            self.window.RecoverBackup.emit()

    def _tr(self, message):
        return self.translate("", message)

    # Start event loop
    def run(self):
        """ Start the primary Qt event loop for the interface """

        res = self.exec_()

        try:
            from classes.logger import log
            self.settings.save()
        except Exception as ex:
            log.error("Couldn't save user settings on exit.\n{}".format(ex))

        # return exit result
        return res
Esempio n. 2
0
class OpenShotApp(QApplication):
    """ This class is the primary QApplication for OpenShot """
    def __init__(self, *args):
        QApplication.__init__(self, *args)

        # Log some basic system info
        try:
            v = openshot.GetVersion()
            log.info("openshot-qt version: %s" % info.VERSION)
            log.info("libopenshot version: %s" % v.ToString())
            log.info("platform: %s" % platform.platform())
            log.info("processor: %s" % platform.processor())
            log.info("machine: %s" % platform.machine())
            log.info("python version: %s" % platform.python_version())
            log.info("qt5 version: %s" % QT_VERSION_STR)
            log.info("pyqt5 version: %s" % PYQT_VERSION_STR)
        except:
            pass

        # Setup appication
        self.setApplicationName('openshot')
        self.setApplicationVersion(info.SETUP['version'])

        # Init settings
        self.settings = settings.SettingStore()
        try:
            self.settings.load()
        except Exception as ex:
            log.error("Couldn't load user settings. Exiting.\n{}".format(ex))
            exit()

        # Init translation system
        language.init_language()

        # Tests of project data loading/saving
        self.project = project_data.ProjectDataStore()

        # Init Update Manager
        self.updates = updates.UpdateManager()

        # It is important that the project is the first listener if the key gets update
        self.updates.add_listener(self.project)

        # Load ui theme if not set by OS
        ui_util.load_theme()

        # Track which dockable window received a context menu
        self.context_menu_object = None

        # Set unique install id (if blank)
        if not self.settings.get("unique_install_id"):
            self.settings.set("unique_install_id", str(uuid4()))

            # Track 1st launch metric
            import classes.metrics
            classes.metrics.track_metric_screen("initial-launch-screen")

        # Set Font for any theme
        if self.settings.get("theme") != "No Theme":
            # Load embedded font
            log.info("Setting font to %s" %
                     os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
            font_id = QFontDatabase.addApplicationFont(
                os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
            font_family = QFontDatabase.applicationFontFamilies(font_id)[0]
            font = QFont(font_family)
            font.setPointSizeF(10.5)
            QApplication.setFont(font)

        # Set Experimental Dark Theme
        if self.settings.get("theme") == "Humanity: Dark":
            # Only set if dark theme selected
            log.info("Setting custom dark theme")
            self.setStyle(QStyleFactory.create("Fusion"))

            darkPalette = self.palette()
            darkPalette.setColor(QPalette.Window, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.WindowText, Qt.white)
            darkPalette.setColor(QPalette.Base, QColor(25, 25, 25))
            darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ToolTipBase, Qt.white)
            darkPalette.setColor(QPalette.ToolTipText, Qt.white)
            darkPalette.setColor(QPalette.Text, Qt.white)
            darkPalette.setColor(QPalette.Button, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ButtonText, Qt.white)
            darkPalette.setColor(QPalette.BrightText, Qt.red)
            darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218))
            darkPalette.setColor(QPalette.HighlightedText, Qt.black)
            self.setPalette(darkPalette)
            self.setStyleSheet(
                "QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }"
            )

        # Create main window
        from windows.main_window import MainWindow
        self.window = MainWindow()
        self.window.show()

        log.info('Process command-line arguments: %s' % args)
        if len(args[0]) == 2:
            path = args[0][1]
            if ".osp" in path:
                # Auto load project passed as argument
                self.window.open_project(path)
            else:
                # Auto import media file
                self.window.filesTreeView.add_file(path)

        # Reset undo/redo history
        self.updates.reset()
        self.window.updateStatusChanged(False, False)

    def _tr(self, message):
        return self.translate("", message)

    # Start event loop
    def run(self):
        """ Start the primary Qt event loop for the interface """

        res = self.exec_()

        try:
            self.settings.save()
        except Exception as ex:
            log.error("Couldn't save user settings on exit.\n{}".format(ex))

        # return exit result
        return res
Esempio n. 3
0
class OpenShotApp(QApplication):
    """ This class is the primary QApplication for OpenShot """

    def __init__(self, *args):
        QApplication.__init__(self, *args)

        # Log some basic system info
        try:
            v = openshot.GetVersion()
            log.info("openshot-qt version: %s" % info.VERSION)
            log.info("libopenshot version: %s" % v.ToString())
            log.info("platform: %s" % platform.platform())
            log.info("processor: %s" % platform.processor())
            log.info("machine: %s" % platform.machine())
            log.info("python version: %s" % platform.python_version())
            log.info("qt5 version: %s" % QT_VERSION_STR)
            log.info("pyqt5 version: %s" % PYQT_VERSION_STR)
        except:
            pass

        # Setup appication
        self.setApplicationName('openshot')
        self.setApplicationVersion(info.SETUP['version'])

        # Init settings
        self.settings = settings.SettingStore()
        try:
            self.settings.load()
        except Exception as ex:
            log.error("Couldn't load user settings. Exiting.\n{}".format(ex))
            exit()

        # Init translation system
        language.init_language()

        # Tests of project data loading/saving
        self.project = project_data.ProjectDataStore()

        # Init Update Manager
        self.updates = updates.UpdateManager()

        # It is important that the project is the first listener if the key gets update
        self.updates.add_listener(self.project)

        # Load ui theme if not set by OS
        ui_util.load_theme()

        # Start libopenshot logging thread
        self.logger_libopenshot = logger_libopenshot.LoggerLibOpenShot()
        self.logger_libopenshot.start()

        # Track which dockable window received a context menu
        self.context_menu_object = None

        # Set unique install id (if blank)
        if not self.settings.get("unique_install_id"):
            self.settings.set("unique_install_id", str(uuid4()))

            # Track 1st launch metric
            import classes.metrics
            classes.metrics.track_metric_screen("initial-launch-screen")

        # Set Font for any theme
        if self.settings.get("theme") != "No Theme":
            # Load embedded font
            try:
                log.info("Setting font to %s" % os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
                font_id = QFontDatabase.addApplicationFont(os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
                font_family = QFontDatabase.applicationFontFamilies(font_id)[0]
                font = QFont(font_family)
                font.setPointSizeF(10.5)
                QApplication.setFont(font)
            except Exception as ex:
                log.error("Error setting Ubuntu-R.ttf QFont: %s" % str(ex))

        # Set Experimental Dark Theme
        if self.settings.get("theme") == "Humanity: Dark":
            # Only set if dark theme selected
            log.info("Setting custom dark theme")
            self.setStyle(QStyleFactory.create("Fusion"))

            darkPalette = self.palette()
            darkPalette.setColor(QPalette.Window, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.WindowText, Qt.white)
            darkPalette.setColor(QPalette.Base, QColor(25, 25, 25))
            darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ToolTipBase, Qt.white)
            darkPalette.setColor(QPalette.ToolTipText, Qt.white)
            darkPalette.setColor(QPalette.Text, Qt.white)
            darkPalette.setColor(QPalette.Button, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ButtonText, Qt.white)
            darkPalette.setColor(QPalette.BrightText, Qt.red)
            darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218))
            darkPalette.setColor(QPalette.HighlightedText, Qt.black)
            darkPalette.setColor(QPalette.Disabled, QPalette.Text, QColor(104, 104, 104))
            self.setPalette(darkPalette)
            self.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }")

        # Create main window
        from windows.main_window import MainWindow
        self.window = MainWindow()

        log.info('Process command-line arguments: %s' % args)
        if len(args[0]) == 2:
            path = args[0][1]
            if ".osp" in path:
                # Auto load project passed as argument
                self.window.open_project(path)
            else:
                # Auto import media file
                self.window.filesTreeView.add_file(path)

        # Reset undo/redo history
        self.updates.reset()
        self.window.updateStatusChanged(False, False)

    def _tr(self, message):
        return self.translate("", message)

    # Start event loop
    def run(self):
        """ Start the primary Qt event loop for the interface """

        res = self.exec_()

        try:
            self.settings.save()
        except Exception as ex:
            log.error("Couldn't save user settings on exit.\n{}".format(ex))

        # return exit result
        return res
Esempio n. 4
0
class OpenShotApp(QApplication):
    """ This class is the primary QApplication for OpenShot.
            mode=None (normal), mode=unittest (testing) """

    def __init__(self, *args, mode=None):
        QApplication.__init__(self, *args)

        # Log some basic system info
        try:
            v = openshot.GetVersion()
            log.info("openshot-qt version: %s" % info.VERSION)
            log.info("libopenshot version: %s" % v.ToString())
            log.info("platform: %s" % platform.platform())
            log.info("processor: %s" % platform.processor())
            log.info("machine: %s" % platform.machine())
            log.info("python version: %s" % platform.python_version())
            log.info("qt5 version: %s" % QT_VERSION_STR)
            log.info("pyqt5 version: %s" % PYQT_VERSION_STR)
        except:
            pass

        # Setup application
        self.setApplicationName('openshot')
        self.setApplicationVersion(info.SETUP['version'])

        # Init settings
        self.settings = settings.SettingStore()
        self.settings.load()

        # Init and attach exception handler
        from classes import exceptions
        sys.excepthook = exceptions.ExceptionHandler

        # Init translation system
        language.init_language()

        # Detect minimum libopenshot version
        _ = self._tr
        libopenshot_version = openshot.GetVersion().ToString()
        if mode != "unittest" and libopenshot_version < info.MINIMUM_LIBOPENSHOT_VERSION:
            QMessageBox.warning(None, _("Wrong Version of libopenshot Detected"),
                                      _("<b>Version %(minimum_version)s is required</b>, but %(current_version)s was detected. Please update libopenshot or download our latest installer.") %
                                {"minimum_version": info.MINIMUM_LIBOPENSHOT_VERSION, "current_version": libopenshot_version})
            # Stop launching and exit
            sys.exit()

        # Tests of project data loading/saving
        self.project = project_data.ProjectDataStore()

        # Init Update Manager
        self.updates = updates.UpdateManager()

        # It is important that the project is the first listener if the key gets update
        self.updates.add_listener(self.project)

        # Load ui theme if not set by OS
        ui_util.load_theme()

        # Start libopenshot logging thread
        self.logger_libopenshot = logger_libopenshot.LoggerLibOpenShot()
        self.logger_libopenshot.start()

        # Track which dockable window received a context menu
        self.context_menu_object = None

        # Set Font for any theme
        if self.settings.get("theme") != "No Theme":
            # Load embedded font
            try:
                log.info("Setting font to %s" % os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
                font_id = QFontDatabase.addApplicationFont(os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf"))
                font_family = QFontDatabase.applicationFontFamilies(font_id)[0]
                font = QFont(font_family)
                font.setPointSizeF(10.5)
                QApplication.setFont(font)
            except Exception as ex:
                log.error("Error setting Ubuntu-R.ttf QFont: %s" % str(ex))

        # Set Experimental Dark Theme
        if self.settings.get("theme") == "Humanity: Dark":
            # Only set if dark theme selected
            log.info("Setting custom dark theme")
            self.setStyle(QStyleFactory.create("Fusion"))

            darkPalette = self.palette()
            darkPalette.setColor(QPalette.Window, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.WindowText, Qt.white)
            darkPalette.setColor(QPalette.Base, QColor(25, 25, 25))
            darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ToolTipBase, Qt.white)
            darkPalette.setColor(QPalette.ToolTipText, Qt.white)
            darkPalette.setColor(QPalette.Text, Qt.white)
            darkPalette.setColor(QPalette.Button, QColor(53, 53, 53))
            darkPalette.setColor(QPalette.ButtonText, Qt.white)
            darkPalette.setColor(QPalette.BrightText, Qt.red)
            darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218))
            darkPalette.setColor(QPalette.HighlightedText, Qt.black)
            darkPalette.setColor(QPalette.Disabled, QPalette.Text, QColor(104, 104, 104))
            self.setPalette(darkPalette)
            self.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }")

        # Create main window
        from windows.main_window import MainWindow
        self.window = MainWindow(mode)

        # Reset undo/redo history
        self.updates.reset()
        self.window.updateStatusChanged(False, False)

        log.info('Process command-line arguments: %s' % args)
        if len(args[0]) == 2:
            path = args[0][1]
            if ".osp" in path:
                # Auto load project passed as argument
                self.window.OpenProjectSignal.emit(path)
            else:
                # Auto import media file
                self.window.filesTreeView.add_file(path)
        else:
            # Recover backup file (this can't happen until after the Main Window has completely loaded)
            self.window.RecoverBackup.emit()

    def _tr(self, message):
        return self.translate("", message)

    # Start event loop
    def run(self):
        """ Start the primary Qt event loop for the interface """

        res = self.exec_()

        try:
            self.settings.save()
        except Exception as ex:
            log.error("Couldn't save user settings on exit.\n{}".format(ex))

        # return exit result
        return res
Esempio n. 5
0
class OpenShotApp(QApplication):
    """ This class is the primary QApplication for OpenShot.
            mode=None (normal), mode=unittest (testing)"""
    def __init__(self, *args, mode=None):
        QApplication.__init__(self, *args)
        self.mode = mode or "normal"
        self.args = super().arguments()
        self.errors = []

        try:
            # Import modules
            from classes import info, sentry
            from classes.logger import log, reroute_output

            # Log the session's start
            if mode != "unittest":
                import time
                log.info("-" * 48)
                log.info(time.asctime().center(48))
                log.info('Starting new session'.center(48))

            log.debug("Starting up in {} mode".format(self.mode))
            log.debug("Command line: {}".format(self.args))

            from classes import settings, project_data, updates
            import openshot

            # Re-route stdout and stderr to logger
            if mode != "unittest":
                reroute_output()

        except ImportError as ex:
            tb = traceback.format_exc()
            log.error('OpenShotApp::Import Error', exc_info=1)
            self.errors.append(
                StartupError("Import Error",
                             "Module: %(name)s\n\n%(tb)s" % {
                                 "name": ex.name,
                                 "tb": tb
                             },
                             level="error"))
            # Stop launching
            raise
        except Exception:
            log.error('OpenShotApp::Init Error', exc_info=1)
            sys.exit()

        self.info = info

        # Log some basic system info
        self.log = log
        self.show_environment(info, openshot)
        if self.mode != "unittest":
            self.check_libopenshot_version(info, openshot)

        # Init data objects
        self.settings = settings.SettingStore(parent=self)
        self.settings.load()
        self.project = project_data.ProjectDataStore()
        self.updates = updates.UpdateManager()
        # It is important that the project is the first listener if the key gets update
        self.updates.add_listener(self.project)
        self.updates.reset()

        # Set location of OpenShot program (for libopenshot)
        openshot.Settings.Instance().PATH_OPENSHOT_INSTALL = info.PATH

        # Check to disable sentry
        if not self.settings.get('send_metrics'):
            sentry.disable_tracing()

    def show_environment(self, info, openshot):
        log = self.log
        try:
            log.info("-" * 48)
            log.info(
                ("OpenShot (version %s)" % info.SETUP['version']).center(48))
            log.info("-" * 48)

            log.info("openshot-qt version: %s" % info.VERSION)
            log.info("libopenshot version: %s" %
                     openshot.OPENSHOT_VERSION_FULL)
            log.info("platform: %s" % platform.platform())
            log.info("processor: %s" % platform.processor())
            log.info("machine: %s" % platform.machine())
            log.info("python version: %s" % platform.python_version())
            log.info("qt5 version: %s" % QT_VERSION_STR)
            log.info("pyqt5 version: %s" % PYQT_VERSION_STR)

            # Look for frozen version info
            version_path = os.path.join(info.PATH, "settings", "version.json")
            if os.path.exists(version_path):
                with open(version_path, "r", encoding="UTF-8") as f:
                    version_info = json.loads(f.read())
                    log.info(
                        "Frozen version info from build server:\n%s" %
                        json.dumps(version_info, indent=4, sort_keys=True))

        except Exception:
            log.debug("Error displaying dependency/system details", exc_info=1)

    def check_libopenshot_version(self, info, openshot):
        """Detect minimum libopenshot version"""
        _ = self._tr
        ver = openshot.OPENSHOT_VERSION_FULL
        min_ver = info.MINIMUM_LIBOPENSHOT_VERSION
        if ver >= min_ver:
            return True

        self.errors.append(
            StartupError(
                _("Wrong Version of libopenshot Detected"),
                _("<b>Version %(minimum_version)s is required</b>, "
                  "but %(current_version)s was detected. "
                  "Please update libopenshot or download our latest installer."
                  ) % {
                      "minimum_version": min_ver,
                      "current_version": ver,
                  },
                level="error",
            ))

    def gui(self):
        from classes import language, sentry, ui_util, logger_libopenshot
        from PyQt5.QtGui import QFont, QFontDatabase as QFD

        _ = self._tr
        info = self.info
        log = self.log

        # Init translation system
        language.init_language()
        sentry.set_tag("locale", info.CURRENT_LANGUAGE)

        # Load ui theme if not set by OS
        ui_util.load_theme()

        # Test for permission issues (and display message if needed)
        try:
            log.debug("Testing write access to user directory")
            # Create test paths
            TEST_PATH_DIR = os.path.join(info.USER_PATH, 'PERMISSION')
            TEST_PATH_FILE = os.path.join(TEST_PATH_DIR, 'test.osp')
            os.makedirs(TEST_PATH_DIR, exist_ok=True)
            with open(TEST_PATH_FILE, 'w') as f:
                f.write('{}')
                f.flush()
            # Delete test paths
            os.unlink(TEST_PATH_FILE)
            os.rmdir(TEST_PATH_DIR)
        except PermissionError as ex:
            log.error('Failed to create file %s', TEST_PATH_FILE, exc_info=1)
            self.errors.append(
                StartupError(
                    _("Permission Error"),
                    _("%(error)s. Please delete <b>%(path)s</b> and launch OpenShot again."
                      ) % {
                          "error": str(ex),
                          "path": info.USER_PATH,
                      },
                    level="error",
                ))

        # Display any outstanding startup messages
        self.show_errors()

        # Start libopenshot logging thread
        self.logger_libopenshot = logger_libopenshot.LoggerLibOpenShot()
        self.logger_libopenshot.start()

        # Track which dockable window received a context menu
        self.context_menu_object = None

        # Set Font for any theme
        log.debug("Loading UI theme")
        if self.settings.get("theme") != "No Theme":
            # Load embedded font
            font_path = os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")
            if os.path.exists(font_path):
                log.info("Setting font to %s", font_path)
                try:
                    font_id = QFD.addApplicationFont(font_path)
                    font_family = QFD.applicationFontFamilies(font_id)[0]
                    font = QFont(font_family)
                    font.setPointSizeF(10.5)
                    QApplication.setFont(font)
                except Exception:
                    log.warning("Error setting Ubuntu-R.ttf QFont", exc_info=1)

        # Set Dark Theme, if selected
        if self.settings.get("theme") == "Humanity: Dark":
            log.info("Setting custom dark theme")
            self.setStyle(QStyleFactory.create("Fusion"))
            darkPalette = ui_util.make_dark_palette(self.palette())
            self.setPalette(darkPalette)
            self.setStyleSheet(
                "QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }"
            )

        # Create main window
        from windows.main_window import MainWindow
        log.debug("Creating main interface window")
        self.window = MainWindow(mode=self.mode)

        # Clear undo/redo history
        self.window.updateStatusChanged(False, False)

        # Connect our exit signals
        self.aboutToQuit.connect(self.cleanup)

        args = self.args
        if len(args) < 2:
            # Recover backup file (this can't happen until after the Main Window has completely loaded)
            self.window.RecoverBackup.emit()
            return

        log.info('Process command-line arguments: %s' % args)

        # Auto load project if passed as argument
        if args[1].endswith(".osp"):
            self.window.OpenProjectSignal.emit(args[1])
            return

        # Start a new project and auto import any media files
        self.project.load("")
        for arg in args[1:]:
            self.window.filesView.add_file(arg)

    def settings_load_error(self, filepath=None):
        """Use QMessageBox to warn the user of a settings load issue"""
        _ = self._tr
        self.errors.append(
            StartupError(
                _("Settings Error"),
                _("Error loading settings file: %(file_path)s. Settings will be reset."
                  ) % {"file_path": filepath},
                level="warning",
            ))

    def get_settings(self):
        if not hasattr(self, "settings"):
            return None
        return self.settings

    def show_errors(self):
        count = len(self.errors)
        if count > 0:
            self.log.warning("Displaying %d startup messages", count)
        while self.errors:
            error = self.errors.pop(0)
            error.show()

    def _tr(self, message):
        return self.translate("", message)

    @pyqtSlot()
    def cleanup(self):
        """aboutToQuit signal handler for application exit"""
        self.log.debug("Saving settings in app.cleanup")
        try:
            self.settings.save()
        except Exception:
            self.log.error("Couldn't save user settings on exit.", exc_info=1)