Example #1
0
        print(obj)


if __name__ == '__main__':
    import sys
    from Curves import BezierCurve
    from Generators import JsonGenerator

    app = QGuiApplication(sys.argv)

    qmlRegisterType(ConsoleOutput, 'PyConsole', 1, 0, 'PyConsole')
    qmlRegisterType(BezierCurve, 'Curves', 1, 0, 'BezierCurve')
    qmlRegisterType(JsonGenerator, 'Generators', 1, 0, 'JsonGenerator')

    view = QQuickView()
    context = view.rootContext()

    view.engine().quit.connect(app.quit)
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    view.setSource(QUrl.fromLocalFile('../view/visionai.qml'))
    view.show()

    for error in view.errors():
        print(error.toString())

    status = app.exec_()

    for error in view.errors():
        print(error.toString())

    sys.exit(status)
Example #2
0
if __name__ == '__main__':
    import sys
    from Curves import BezierCurve
    from Generators import JsonGenerator

    app = QGuiApplication(sys.argv)

    qmlRegisterType(ConsoleOutput, 'PyConsole', 1, 0, 'PyConsole')
    qmlRegisterType(BezierCurve, 'Curves', 1, 0, 'BezierCurve')
    qmlRegisterType(JsonGenerator, 'Generators', 1, 0, 'JsonGenerator')

    view = QQuickView()
    context = view.rootContext()

    view.engine().quit.connect(app.quit)
    view.setResizeMode(QQuickView.SizeRootObjectToView)
    view.setSource(
        QUrl.fromLocalFile('../view/visionai.qml')
    )
    view.show()

    for error in view.errors():
        print(error.toString())

    status = app.exec_()

    for error in view.errors():
        print(error.toString())

    sys.exit(status)
Example #3
0
class PreviewTab(QWidget):
    """Preview of QML component given by 'source' argument. If any file in the
    source's directory or one of its subdirectories is changed, the view is
    updated unless paused. Potential errors in the QML code are displayed in
    red."""
    def __init__(self, source=None, parent=None, import_paths=None):
        super().__init__(parent=parent)

        self.updating_paused = False

        self.qml_view = QQuickView()

        engine = self.qml_view.engine()
        import_paths = import_paths or []
        for import_path in import_paths:
            engine.addImportPath(import_path)

        # idea from
        # https://www.ics.com/blog/combining-qt-widgets-and-qml-qwidgetcreatewindowcontainer
        self.container = QWidget.createWindowContainer(self.qml_view, self)

        self.error_info = QLabel()
        self.error_info.setWordWrap(True)

        self.qml_source = QUrl() if source is None else QUrl(source)
        self.update_source()

        self.pause_button = QPushButton("Pause")
        self.pause_button.setCheckable(True)

        layout = QVBoxLayout()
        layout.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.error_info)
        layout.addWidget(self.container)
        layout.addWidget(self.pause_button)

        self.setLayout(layout)

        # Observations using the QFileSystemWatcher in various settings:
        # A) fileChanged signal and qml file paths
        #   Collected all *.qml files in the directory of the source and all
        #   subdirectories and added to the watcher. Now the first change would
        #   trigger the signal but none of the following
        # B) additionally connecting directoryChanged signal
        #   same issue
        # C) both signals, (sub)directory file paths
        #   Collected all subdirectories of the source directory and added it to
        #   the watcher, along with the source directory itself. Works as
        #   expected
        # D) directoryChanged signal, (sub)directory file paths
        #   same as C) without fileChanged signal, works as expected
        # Eventual solution: D
        # This implementation also helped me:
        # https://github.com/penk/qml-livereload/blob/master/main.cpp
        self.watcher = QFileSystemWatcher()
        source_dir = os.path.dirname(source)
        source_paths = glob.glob(os.path.join(source_dir, "*/"),
                                 recursive=True)
        source_paths.append(source_dir)
        failed_paths = self.watcher.addPaths(source_paths)
        if failed_paths:
            print("Failed to watch paths: {}".format(", ".join(failed_paths)))

        self.pause_button.clicked.connect(self.toggle_updating)
        self.qml_view.statusChanged.connect(self.check_status)
        self.watcher.directoryChanged.connect(self.update_source)

    def toggle_updating(self, clicked):
        """Callback for pause button."""
        self.pause_button.setText("Resume" if clicked else "Pause")
        self.updating_paused = clicked

        # Update when resuming in case of the source having changed
        if not self.updating_paused:
            self.update_source()

    def update_source(self, _=None):
        """Method and callback to update the QML view source. The second
        argument is required to have a slot matching the directoryChanged()
        interface.
        This immediately returns if updating is paused.
        """
        if self.updating_paused:
            return

        # idea from
        # https://stackoverflow.com/questions/17337493/how-to-reload-qml-file-to-qquickview
        self.qml_view.setSource(QUrl())
        self.qml_view.engine().clearComponentCache()
        # avoid error: No such file or directory
        QThread.msleep(50)
        self.qml_view.setSource(self.qml_source)
        self.container.setMinimumSize(self.qml_view.size())
        self.container.setMaximumSize(self.qml_view.size())
        # avoid error label making the window too wide
        self.error_info.setMaximumWidth(self.container.maximumWidth())

    def check_status(self, status):
        if status == QQuickView.Error:
            self.error_info.setText("<font color='red'>{}</font>".format(
                self.qml_view.errors()[-1].toString()))
        else:
            self.error_info.clear()

    def shutdown(self):
        """Shutdown tab to prepare for removal. Manually delete QML related
        members to free resources. Otherwise error messages are printed even
        after closing the tab, indicating that the QML engine still runs in the
        background.
        """
        del self.container
        del self.qml_view