File: image.py

package info (click to toggle)
python-qtpynodeeditor 0.2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 604 kB
  • sloc: python: 5,038; makefile: 14; sh: 1
file content (157 lines) | stat: -rw-r--r-- 4,687 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import logging

from qtpy import QtCore, QtGui, QtWidgets
from qtpy.QtCore import Qt

import qtpynodeeditor
from qtpynodeeditor import NodeData, NodeDataModel, NodeDataType, PortType


class PixmapData(NodeData):
    data_type = NodeDataType(id='Pixmap', name='PixmapData')

    def __init__(self, pixmap):
        self.pixmap = pixmap


class ImageLoaderModel(NodeDataModel):
    caption = 'Image Source'
    num_ports = {PortType.input: 0,
                 PortType.output: 1,
                 }
    data_type = PixmapData

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._pixmap = None
        self._label = QtWidgets.QLabel('Click to load image')
        self._label.setAlignment(Qt.AlignVCenter | Qt.AlignCenter)

        font = self._label.font()
        font.setBold(True)
        font.setItalic(True)
        self._label.setFont(font)

        self._label.setFixedSize(200, 200)
        self._label.installEventFilter(self)

    def eventFilter(self, obj, event):
        def set_pixmap():
            w, h = self._label.width(), self._label.height()
            self._label.setPixmap(self._pixmap.scaled(w, h, Qt.KeepAspectRatio))

        if obj is not self._label:
            return False

        if event.type() == QtCore.QEvent.MouseButtonPress:
            file_name, _ = QtWidgets.QFileDialog.getOpenFileName(
                None, "Open Image", QtCore.QDir.homePath(),
                "Image files (*.png *.jpg *.bmp)")
            try:
                self._pixmap = QtGui.QPixmap(file_name)
            except Exception as ex:
                print(f'Failed to load image {file_name}: {ex}')
                return False

            set_pixmap()
            self.data_updated.emit(0)
            return True

        elif event.type() == QtCore.QEvent.Resize:
            if self._pixmap is not None:
                set_pixmap()

        return False

    def resizable(self):
        return True

    def out_data(self, port):
        return PixmapData(self._pixmap)

    def embedded_widget(self):
        return self._label


class ImageShowModel(NodeDataModel):
    caption = 'Image Display'
    num_ports = {PortType.input: 1,
                 PortType.output: 1,
                 }
    data_type = PixmapData

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._node_data = None
        self._label = QtWidgets.QLabel('Image will appear here')
        self._label.setAlignment(Qt.AlignVCenter | Qt.AlignCenter)

        font = self._label.font()
        font.setBold(True)
        font.setItalic(True)
        self._label.setFont(font)

        self._label.setFixedSize(200, 200)
        self._label.installEventFilter(self)

    def resizable(self):
        return True

    def eventFilter(self, obj, event):
        if obj is self._label and event.type() == QtCore.QEvent.Resize:
            if (self._node_data and
                    self._node_data.data_type == PixmapData.data_type and
                    self._node_data.pixmap):
                w, h = self._label.width(), self._label.height()
                pixmap = self._node_data.pixmap
                self._label.setPixmap(pixmap.scaled(w, h, Qt.KeepAspectRatio))

        return False

    def set_in_data(self, node_data, port):
        self._node_data = node_data
        if (self._node_data and
                self._node_data.data_type == PixmapData.data_type and
                self._node_data.pixmap):
            w, h = self._label.width(), self._label.height()
            pixmap = node_data.pixmap.scaled(w, h, Qt.KeepAspectRatio)
        else:
            pixmap = QtGui.QPixmap()

        self._label.setPixmap(pixmap)
        self.data_updated.emit(0)

    def out_data(self, port):
        return self._node_data

    def embedded_widget(self):
        return self._label


def main(app):
    registry = qtpynodeeditor.DataModelRegistry()
    registry.register_model(ImageShowModel, category='My Category')
    registry.register_model(ImageLoaderModel, category='My Category')
    scene = qtpynodeeditor.FlowScene(registry=registry)

    view = qtpynodeeditor.FlowView(scene)
    view.setWindowTitle("Image example")
    view.resize(800, 600)

    node_loader = scene.create_node(ImageLoaderModel)
    node_show = scene.create_node(ImageShowModel)

    scene.create_connection(
        node_loader[PortType.output][0],
        node_show[PortType.input][0],
    )

    return scene, view, [node_loader, node_show]


if __name__ == '__main__':
    logging.basicConfig(level='DEBUG')
    app = QtWidgets.QApplication([])
    scene, view, nodes = main(app)
    view.show()
    app.exec_()