def __init__(self, parent = None):
        # Initialization of the superclass
        super(MainWindow, self).__init__(parent)
        
        qInstallMessageHandler(qt_message_handler)
        
        self.backend = Backend()

        # Expose the Python "Backend" object to QML
        self.engine = QQmlApplicationEngine()  
        self.context = self.engine.rootContext()
        self.context.setContextProperty("backend", self.backend)
        
        # Load the GUI
        self.engine.load(os.path.join(os.path.dirname(__file__), "SpecPXA_QML.qml"))
        if not self.engine.rootObjects():
            sys.exit(-1)
        
        self.win = self.engine.rootObjects()[0]
        
        # Execute a function if "Start" button clicked
        startbutton = self.win.findChild(QObject, "startbutton")
        startbutton.startclicked.connect(self.startclicked)
        
        # Execute a function if "Stop" button clicked
        stopbutton = self.win.findChild(QObject, "stopbutton")
        stopbutton.stopclicked.connect(self.stopclicked)
Exemple #2
0
    def __init__(self):
        super().__init__()
        self.load(os.path.join(os.getcwd(), "view.qml"))
        qInstallMessageHandler(qt_message_handler)
        self.rootContext().setContextProperty("MainWindow", self)

        if os.name == "nt":
            self.prefix = "file:///"
        else:
            self.prefix = "file://"
        self.tmp_dir = "tmp"
        if not os.path.exists("tmp"):
            os.makedirs("tmp")
        self.fileName = None
        self.colorImage = None
        self.image = None
        self.bwImage = None
        self.model = None
        self.modelFolderName = None

        if self.rootObjects():
            self.window = self.rootObjects()[0]
            self.imageField = self.window.findChild(QObject, "imagePreview")
            self.modelText = self.window.findChild(QObject, "modelPreview")
        else:
            sys.exit(-1)
def main():
    qInstallMessageHandler(lambda x, y, msg: print(msg))

    argv = sys.argv

    # Trick to set the style / not found how to do it in pythonic way
    #argv.extend(["-style", "universal"])
    app = QGuiApplication(argv)

    qmlRegisterType(FigureCanvasQTAgg, "Backend", 1, 0, "FigureCanvasByPython")

    view = QQuickView()
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    view.setSource(QUrl(str(pathlib.Path(__file__).parent / 'Figure.qml')))
    view.show()

    win = view.rootObject()
    qml_figure_canvas = win.findChild(QObject, "figure")
    fig = qml_figure_canvas.getFigure()
    print(fig)
    ax = fig.add_subplot(111)
    x = np.linspace(-5, 5)
    ax.plot(x, np.sin(x))

    rc = app.exec_()
    # There is some trouble arising when deleting all the objects here
    # but I have not figure out how to solve the error message.
    # It looks like 'app' is destroyed before some QObject
    sys.exit(rc)
Exemple #4
0
    def __init__(self, args):
        QtArgs = [args[0], '-style', 'fusion'] + args[1:]  # force Fusion style by default
        super(MeshroomApp, self).__init__(QtArgs)

        self.setOrganizationName('AliceVision')
        self.setApplicationName('Meshroom')
        self.setAttribute(Qt.AA_EnableHighDpiScaling)
        self.setApplicationVersion(meshroom.__version__)

        font = self.font()
        font.setPointSize(9)
        self.setFont(font)

        pwd = os.path.dirname(__file__)
        self.setWindowIcon(QIcon(os.path.join(pwd, "img/meshroom.svg")))

        # QML engine setup
        qmlDir = os.path.join(pwd, "qml")
        url = os.path.join(qmlDir, "main.qml")
        self.engine = QmlInstantEngine()
        self.engine.addFilesFromDirectory(qmlDir, recursive=True)
        self.engine.setWatching(os.environ.get("MESHROOM_INSTANT_CODING", False))
        # whether to output qml warnings to stderr (disable by default)
        self.engine.setOutputWarningsToStandardError(MessageHandler.outputQmlWarnings)
        qInstallMessageHandler(MessageHandler.handler)

        self.engine.addImportPath(qmlDir)
        components.registerTypes()

        # expose available node types that can be instantiated
        self.engine.rootContext().setContextProperty("_nodeTypes", sorted(nodesDesc.keys()))

        # instantiate Reconstruction object
        r = Reconstruction(parent=self)
        self.engine.rootContext().setContextProperty("_reconstruction", r)

        # those helpers should be available from QML Utils module as singletons, but:
        #  - qmlRegisterUncreatableType is not yet available in PySide2
        #  - declaring them as singleton in qmldir file causes random crash at exit
        # => expose them as context properties instead
        self.engine.rootContext().setContextProperty("Filepath", FilepathHelper(parent=self))
        self.engine.rootContext().setContextProperty("Scene3DHelper", Scene3DHelper(parent=self))
        self.engine.rootContext().setContextProperty("Clipboard", ClipboardHelper(parent=self))

        # additional context properties
        self.engine.rootContext().setContextProperty("_PaletteManager", PaletteManager(self.engine, parent=self))
        self.engine.rootContext().setContextProperty("MeshroomApp", self)

        # request any potential computation to stop on exit
        self.aboutToQuit.connect(r.stopChildThreads)

        parser = argparse.ArgumentParser(prog=args[0], description='Launch Meshroom UI.')
        parser.add_argument('--project', metavar='MESHROOM_FILE', type=str, required=False,
                            help='Meshroom project file (e.g. myProject.mg).')
        args = parser.parse_args(args[1:])
        if args.project:
            r.loadUrl(QUrl.fromLocalFile(args.project))

        self.engine.load(os.path.normpath(url))
Exemple #5
0
def run(args, field):
    qInstallMessageHandler(msg_handler)

    if "QT_QUICK_CONTROLS_STYLE" not in os.environ:
        os.environ["QT_QUICK_CONTROLS_STYLE"] = "Fusion"

    app = QGuiApplication(args)
    eng = QQmlApplicationEngine()
    eng.rootContext().setContextProperty("field", field)
    eng.load(QUrl("ui.qml"))
    app.exec_()
def main():
    qInstallMessageHandler(lambda x, y, msg: print(msg))

    argv = sys.argv

    # Trick to set the style / not found how to do it in pythonic way
    #argv.extend(["-style", "universal"])

    app = QApplication(argv)

    qmlRegisterType(FigureCanvasQTAgg, "Backend", 1, 0, "FigureCanvasByPython")
    qmlRegisterType(FigureCanvasQTAggToolbar, "Backend", 1, 0,
                    "FigureToolbarByPython")

    # this should work in the future
    # qmlRegisterType(
    #     QUrl.fromLocalFile( str(pathlib.Path(backend_qquick5agg.__file__)/'SubplotTool.qml')),
    #     "Backend", 1, 0, "SubplotTool")

    imgProvider = MatplotlibIconProvider()

    # !! You must specified the QApplication as parent of QQmlApplicationEngine
    # otherwise a segmentation fault is raised when exiting the app
    engine = QQmlApplicationEngine(parent=app)
    engine.addImageProvider("mplIcons", imgProvider)

    context = engine.rootContext()
    data_model = DataSeriesModel()
    context.setContextProperty("dataModel", data_model)
    mainApp = Form(data=data_model)
    context.setContextProperty("draw_mpl", mainApp)

    engine.load(
        QUrl(str(pathlib.Path(__file__).parent / 'main_mpl_qtquick_main.qml')))

    win = engine.rootObjects()[0]

    figure = win.findChild(QObject, "figure")
    mainApp.figure = figure.getFigure()

    rc = app.exec_()
    # There is some trouble arising when deleting all the objects here
    # but I have not figure out how to solve the error message.
    # It looks like 'app' is destroyed before some QObject
    sys.exit(rc)
Exemple #7
0
def setup_logging(initial_verbosity):
    module_log_handler = logging.StreamHandler()
    module_log_handler.setFormatter(logging.Formatter("%(levelname)s %(module)s %(funcName)s %(message)s"))
    module_logger.addHandler(module_log_handler)
    module_logger.setLevel(logging.INFO)  # set this again later after getting QSettings

    # Apparently Windows version of PySide2 doesn't have QML logging feature turn on so we fill this gap
    if platform.system() == 'Windows':
        qml_log_handler = logging.StreamHandler()
        qml_log_handler.setFormatter(logging.Formatter("[QML] %(levelname)s %(message)s"))
        qml_logger.addHandler(qml_log_handler)
        qInstallMessageHandler(qt_message_handler)

    # Use "singleton" real logger for all projects just wrapping it into the LoggingAdapter for every project
    projects_logger.setLevel(logging.DEBUG if initial_verbosity else logging.INFO)
    projects_logger_handler.setFormatter(_projects_logger_formatter)
    projects_logger.addHandler(projects_logger_handler)

    set_verbosity(initial_verbosity)  # set initial verbosity settings based on the saved state
Exemple #8
0
    def __init__(self):
        """App constructor"""
        self.streamingAPI = CHOSEN_STREAMING_API

        print(self.streamingAPI)

        QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
        sys_argv = sys.argv
        sys_argv += ['--style', 'fusion']
        app = QApplication(sys_argv)
        QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)

        # Set up the application window
        pwd = os.path.dirname(__file__)
        qmlDir = os.path.join(pwd, "UIPkg")
        self.engine = QmlInstantEngine()
        self.engine.addFilesFromDirectory(qmlDir, recursive=True)
        self.engine.setWatching(
            os.environ.get("MESHROOM_INSTANT_CODING", False))

        # whether to output qml warnings to stderr (disable by default)
        self.engine.setOutputWarningsToStandardError(
            MessageHandler.outputQmlWarnings)
        qInstallMessageHandler(MessageHandler.handler)

        ctx = self.engine.rootContext()

        # Create a Backend object to communicate with QML
        self.backend = Backend()
        ctx.setContextProperty("backend", self.backend)
        ctx.setContextProperty("preview", self.backend.preview)
        ctx.setContextProperty("acquisition", self.backend.acquisition)

        self.engine.addImageProvider("imageProvider",
                                     self.backend.preview.imageProvider)

        # Apply palette
        darkPalette = Palette(self.engine)

        # Run app
        self.engine.load("UIPkg/App.qml")
        sys.exit(app.exec_())
Exemple #9
0
    def __init__(
        self,
        plugin_path=['/usr/lib/mozilla/plugins', ],
        defaults=None,
        display_size=(1600, 900),
    ):
        self.logger = logger.getChild('application')

        if (
            sys.platform.startswith('linux') and
            'DISPLAY' not in os.environ
        ):
            try:
                self.xvfb = Xvfb(
                    width=display_size[0],
                    height=display_size[1],
                )
                self.xvfb.start()

            except OSError:
                raise Error('Xvfb is required to a ghost run outside ' +
                            'an X instance')

        self.logger.info('Initializing QT application')
        Ghost._app = QApplication.instance() or QApplication(['ghost'])

        qInstallMessageHandler(QTMessageProxy(logging.getLogger('qt')))

        if plugin_path:
            for p in plugin_path:
                Ghost._app.addLibraryPath(p)

        self.display_size = display_size
        _defaults = dict(viewport_size=display_size)
        _defaults.update(defaults or dict())
        self.defaults = _defaults
Exemple #10
0
    def __init__(self, args):
        QtArgs = [args[0], '-style', 'fusion'
                  ] + args[1:]  # force Fusion style by default

        parser = argparse.ArgumentParser(prog=args[0],
                                         description='Launch Meshroom UI.',
                                         add_help=True)

        parser.add_argument(
            'project',
            metavar='PROJECT',
            type=str,
            nargs='?',
            help=
            'Meshroom project file (e.g. myProject.mg) or folder with images to reconstruct.'
        )
        parser.add_argument(
            '-i',
            '--import',
            metavar='IMAGES/FOLDERS',
            type=str,
            nargs='*',
            help='Import images or folder with images to reconstruct.')
        parser.add_argument(
            '-I',
            '--importRecursive',
            metavar='FOLDERS',
            type=str,
            nargs='*',
            help=
            'Import images to reconstruct from specified folder and sub-folders.'
        )
        parser.add_argument('-s',
                            '--save',
                            metavar='PROJECT.mg',
                            type=str,
                            default='',
                            help='Save the created scene.')
        parser.add_argument(
            '-p',
            '--pipeline',
            metavar='MESHROOM_FILE/photogrammetry/hdri',
            type=str,
            default=os.environ.get("MESHROOM_DEFAULT_PIPELINE",
                                   "photogrammetry"),
            help=
            'Override the default Meshroom pipeline with this external graph.')
        parser.add_argument(
            "--verbose",
            help="Verbosity level",
            default='warning',
            choices=['fatal', 'error', 'warning', 'info', 'debug', 'trace'],
        )

        args = parser.parse_args(args[1:])

        logStringToPython = {
            'fatal': logging.FATAL,
            'error': logging.ERROR,
            'warning': logging.WARNING,
            'info': logging.INFO,
            'debug': logging.DEBUG,
            'trace': logging.DEBUG,
        }
        logging.getLogger().setLevel(logStringToPython[args.verbose])

        QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)

        super(MeshroomApp, self).__init__(QtArgs)

        self.setOrganizationName('AliceVision')
        self.setApplicationName('Meshroom')
        self.setApplicationVersion(meshroom.__version_name__)

        font = self.font()
        font.setPointSize(9)
        self.setFont(font)

        pwd = os.path.dirname(__file__)
        self.setWindowIcon(QIcon(os.path.join(pwd, "img/meshroom.svg")))

        # QML engine setup
        qmlDir = os.path.join(pwd, "qml")
        url = os.path.join(qmlDir, "main.qml")
        self.engine = QmlInstantEngine()
        self.engine.addFilesFromDirectory(qmlDir, recursive=True)
        self.engine.setWatching(
            os.environ.get("MESHROOM_INSTANT_CODING", False))
        # whether to output qml warnings to stderr (disable by default)
        self.engine.setOutputWarningsToStandardError(
            MessageHandler.outputQmlWarnings)
        qInstallMessageHandler(MessageHandler.handler)

        self.engine.addImportPath(qmlDir)
        components.registerTypes()

        # expose available node types that can be instantiated
        self.engine.rootContext().setContextProperty("_nodeTypes",
                                                     sorted(nodesDesc.keys()))

        # instantiate Reconstruction object
        r = Reconstruction(defaultPipeline=args.pipeline, parent=self)
        self.engine.rootContext().setContextProperty("_reconstruction", r)

        # those helpers should be available from QML Utils module as singletons, but:
        #  - qmlRegisterUncreatableType is not yet available in PySide2
        #  - declaring them as singleton in qmldir file causes random crash at exit
        # => expose them as context properties instead
        self.engine.rootContext().setContextProperty(
            "Filepath", FilepathHelper(parent=self))
        self.engine.rootContext().setContextProperty(
            "Scene3DHelper", Scene3DHelper(parent=self))
        self.engine.rootContext().setContextProperty(
            "Clipboard", ClipboardHelper(parent=self))

        # additional context properties
        self.engine.rootContext().setContextProperty(
            "_PaletteManager", PaletteManager(self.engine, parent=self))
        self.engine.rootContext().setContextProperty("MeshroomApp", self)

        # request any potential computation to stop on exit
        self.aboutToQuit.connect(r.stopChildThreads)

        if args.project and not os.path.isfile(args.project):
            raise RuntimeError(
                "Meshroom Command Line Error: 'PROJECT' argument should be a Meshroom project file (.mg).\n"
                "Invalid value: '{}'".format(args.project))

        if args.project:
            r.load(args.project)
        else:
            r.new()

        # import is a python keyword, so we have to access the attribute by a string
        if getattr(args, "import", None):
            r.importImagesFromFolder(getattr(args, "import"), recursive=False)

        if args.importRecursive:
            r.importImagesFromFolder(args.importRecursive, recursive=True)

        if args.save:
            if os.path.isfile(args.save):
                raise RuntimeError(
                    "Meshroom Command Line Error: Cannot save the new Meshroom project as the file (.mg) already exists.\n"
                    "Invalid value: '{}'".format(args.save))
            projectFolder = os.path.dirname(args.save)
            if not os.path.isdir(projectFolder):
                if not os.path.isdir(os.path.dirname(projectFolder)):
                    raise RuntimeError(
                        "Meshroom Command Line Error: Cannot save the new Meshroom project file (.mg) as the parent of the folder does not exists.\n"
                        "Invalid value: '{}'".format(args.save))
                os.mkdir(projectFolder)
            r.saveAs(args.save)

        self.engine.load(os.path.normpath(url))
Exemple #11
0
def main():  # call this before application starts
    from PySide2.QtCore import qInstallMessageHandler
    qInstallMessageHandler(log)
Exemple #12
0
        :param line: line of log message statement
        :return:
        """
        logger.log(level, message, extra=(file, line))

    @staticmethod
    def qtMessageHandler(qtMsgType, qMessageLogContext, msg):
        """
        Qt message handler for handling qt messages in normal logging.

        :param qtMsgType: qt log level
        :param qMessageLogContext: qt log context
        :param msg: message as a string
        :return:
        """
        typeMap = {
            QtMsgType.QtDebugMsg: logging.DEBUG,
            QtMsgType.QtInfoMsg: logging.INFO,
            QtMsgType.QtWarningMsg: logging.WARNING,
            QtMsgType.QtCriticalMsg: logging.CRITICAL,
            QtMsgType.QtFatalMsg: logging.FATAL
        }
        logger.log(typeMap[qtMsgType],
                   msg,
                   extra=(qMessageLogContext.file if qMessageLogContext.file
                          is not None else "<qt>", qMessageLogContext.line))


qInstallMessageHandler(ConsoleLogger.qtMessageHandler)
sys.excepthook = excepthook
Exemple #13
0
    module_log_handler = logging.StreamHandler()
    module_log_handler.setFormatter(
        logging.Formatter("%(levelname)s %(funcName)s %(message)s"))
    module_logger.addHandler(module_log_handler)
    module_logger.setLevel(logging.INFO)
    module_logger.info('Starting stm32pio-gui...')

    # Apparently Windows version of PySide2 doesn't have QML logging feature turn on so we fill this gap
    # TODO: set up for other platforms too (separate console.debug, console.warn, etc.)
    if stm32pio.settings.my_os == 'Windows':
        qml_logger = logging.getLogger('qml')
        qml_log_handler = logging.StreamHandler()
        qml_log_handler.setFormatter(
            logging.Formatter("[QML] %(levelname)s %(message)s"))
        qml_logger.addHandler(qml_log_handler)
        qInstallMessageHandler(qt_message_handler)

    # Most Linux distros should be linked with the QWidgets' QApplication instead of the QGuiApplication to enable
    # QtDialogs
    if stm32pio.settings.my_os == 'Linux':
        app = QApplication(sys.argv)
    else:
        app = QGuiApplication(sys.argv)

    # Used as a settings identifier too
    app.setOrganizationName('ussserrr')
    app.setApplicationName('stm32pio')
    app.setWindowIcon(QIcon('stm32pio-gui/icons/icon.svg'))

    settings = Settings(parent=app)
    # settings.remove('app/settings')
Exemple #14
0
def main(sys_argv: List[str] = None) -> int:
    if sys_argv is None:
        sys_argv = sys.argv[1:]

    args = parse_args(sys_argv)

    module_log_handler = logging.StreamHandler()
    module_log_handler.setFormatter(
        logging.Formatter("%(levelname)s %(funcName)s %(message)s"))
    module_logger.addHandler(module_log_handler)
    module_logger.setLevel(
        logging.INFO)  # set this again later after getting QSettings
    module_logger.info('Starting stm32pio_gui...')

    def qt_message_handler(mode, context, message):
        """
        Register this logging handler for the Qt stuff if your platform doesn't provide a built-in one or if you want to
        customize it
        """
        if mode == QtInfoMsg:
            mode = logging.INFO
        elif mode == QtWarningMsg:
            mode = logging.WARNING
        elif mode == QtCriticalMsg:
            mode = logging.ERROR
        elif mode == QtFatalMsg:
            mode = logging.CRITICAL
        else:
            mode = logging.DEBUG
        qml_logger.log(mode, message)

    # Apparently Windows version of PySide2 doesn't have QML logging feature turn on so we fill this gap
    # TODO: set up for other platforms too (separate console.debug, console.warn, etc.)
    qml_logger = logging.getLogger('stm32pio_gui.qml')
    if platform.system() == 'Windows':
        qml_log_handler = logging.StreamHandler()
        qml_log_handler.setFormatter(
            logging.Formatter("[QML] %(levelname)s %(message)s"))
        qml_logger.addHandler(qml_log_handler)
        qInstallMessageHandler(qt_message_handler)

    # Most Linux distros should be "linked" with QWidgets' QApplication instead of QGuiApplication to enable QtDialogs
    if platform.system() == 'Linux':
        app = QApplication(sys.argv)
    else:
        app = QGuiApplication(sys.argv)

    # These are used as a settings identifier too
    app.setOrganizationName('ussserrr')
    app.setApplicationName('stm32pio')
    app.setWindowIcon(QIcon(str(MODULE_PATH.joinpath('icons/icon.svg'))))

    global settings

    def verbose_setter(value):
        """Use this to toggle the verbosity of all loggers at once"""
        module_logger.setLevel(logging.DEBUG if value else logging.INFO)
        qml_logger.setLevel(logging.DEBUG if value else logging.INFO)
        projects_logger.setLevel(logging.DEBUG if value else logging.INFO)
        formatter.verbosity = stm32pio.util.Verbosity.VERBOSE if value else stm32pio.util.Verbosity.NORMAL

    settings = Settings(prefix='app/settings/',
                        qs_kwargs={'parent': app},
                        external_triggers={'verbose': verbose_setter})

    # Use "singleton" real logger for all projects just wrapping it into the LoggingAdapter for every project
    projects_logger = logging.getLogger('stm32pio_gui.projects')
    projects_logger.setLevel(
        logging.DEBUG if settings.get('verbose') else logging.INFO)
    formatter = stm32pio.util.DispatchingFormatter(
        general={
            stm32pio.util.Verbosity.NORMAL:
            logging.Formatter("%(levelname)-8s %(message)s"),
            stm32pio.util.Verbosity.VERBOSE:
            logging.Formatter(
                f"%(levelname)-8s %(funcName)-{stm32pio.settings.log_fieldwidth_function}s %(message)s"
            )
        })
    projects_logger_handler.setFormatter(formatter)
    projects_logger.addHandler(projects_logger_handler)

    verbose_setter(settings.get(
        'verbose'))  # set initial verbosity settings based on the saved state

    settings.beginGroup('app')
    restored_projects_paths: List[str] = []
    for index in range(settings.beginReadArray('projects')):
        settings.setArrayIndex(index)
        restored_projects_paths.append(settings.value('path'))
    settings.endArray()
    settings.endGroup()

    engine = QQmlApplicationEngine(parent=app)

    qmlRegisterType(ProjectListItem, 'ProjectListItem', 1, 0,
                    'ProjectListItem')
    qmlRegisterType(Settings, 'Settings', 1, 0, 'Settings')

    projects_model = ProjectsList(parent=engine)
    boards_model = QStringListModel(parent=engine)

    engine.rootContext().setContextProperty('appVersion',
                                            stm32pio.app.__version__)
    engine.rootContext().setContextProperty('Logging',
                                            stm32pio.util.logging_levels)
    engine.rootContext().setContextProperty('projectsModel', projects_model)
    engine.rootContext().setContextProperty('boardsModel', boards_model)
    engine.rootContext().setContextProperty('appSettings', settings)

    engine.load(QUrl.fromLocalFile(str(MODULE_PATH.joinpath('main.qml'))))

    main_window = engine.rootObjects()[0]

    # Getting PlatformIO boards can take a long time when the PlatformIO cache is outdated but it is important to have
    # them before the projects list is restored, so we start a dedicated loading thread. We actually can add other
    # start-up operations here if there will be a need to. Use the same Worker class to spawn the thread at the pool
    def loading():
        boards = ['None'] + stm32pio.util.get_platformio_boards('platformio')
        boards_model.setStringList(boards)

    def loaded(_: str, success: bool):
        try:
            # Qt objects cannot be parented from the different thread so we restore the projects list in the main thread
            for path in restored_projects_paths:
                projects_model.addListItem(path,
                                           go_to_this=False,
                                           list_item_kwargs={
                                               'from_startup': True,
                                               'parent': projects_model
                                           })

            # At the end, append (or jump to) a CLI-provided project, if there is one
            if args is not None:
                list_item_kwargs = {
                    'from_startup': True,
                    'parent': projects_model
                }
                if args.board:
                    list_item_kwargs['project_kwargs'] = {
                        'parameters': {
                            'project': {
                                'board': args.board
                            }
                        }
                    }  # pizdec konechno...
                projects_model.addListItem(str(pathlib.Path(args.path)),
                                           go_to_this=True,
                                           list_item_kwargs=list_item_kwargs)
                projects_model.saveInSettings()
        except Exception:
            stm32pio.util.log_current_exception(module_logger)
            success = False

        main_window.backendLoaded.emit(success)  # inform the GUI

    loader = Worker(loading, logger=module_logger)
    loader.finished.connect(loaded)
    QThreadPool.globalInstance().start(loader)

    return app.exec_()