forked from gnuradio/gnuradio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraphicitem.py
199 lines (169 loc) · 7.68 KB
/
graphicitem.py
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2020 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
#
from PyQt5.QtWidgets import QLabel
from PyQt5.QtGui import QPixmap, QPainter
from PyQt5.QtCore import Qt as Qtc
from PyQt5.QtCore import QSize
import os
import sys
from gnuradio import gr
import pmt
class GrGraphicItem(gr.sync_block, QLabel):
"""
This block displays the selected graphic item. You can pass a
filename as a string in a message to change the image on the fly.
overlays can also be added by passing in a message with a
dictionary of a list of dictionaries in the car portion of the
message. Each dictionary should have the following keys:
'filename','x','y', and an optional 'scalefactor'.
Setting the x/y attributes to -1,-1 will remove an overlay.
Otherwise items are indexed by filename and can be animated
throughout the background image.
"""
def __init__(self, image_file, scaleImage=True, fixedSize=False, setWidth=0, setHeight=0):
gr.sync_block.__init__(self, name="GrGraphicsItem",
in_sig=None, out_sig=None)
QLabel.__init__(self)
if not os.path.isfile(image_file):
gr.log.error("ERROR: Unable to find file " + image_file)
sys.exit(1)
try:
self.pixmap = QPixmap(image_file)
self.originalPixmap = QPixmap(image_file)
except OSError as e:
gr.log.error("ERROR: " + e.strerror)
sys.exit(1)
self.image_file = image_file
self.scaleImage = scaleImage
self.fixedSize = fixedSize
self.setWidth = setWidth
self.setHeight = setHeight
super().setPixmap(self.pixmap)
super().setMinimumSize(1, 1)
self.overlays = {}
self.message_port_register_in(pmt.intern("filename"))
self.set_msg_handler(pmt.intern("filename"), self.msgHandler)
self.message_port_register_in(pmt.intern("overlay"))
self.set_msg_handler(pmt.intern("overlay"), self.overlayHandler)
def overlayHandler(self, msg):
try:
overlayitem = pmt.to_python(pmt.car(msg))
if overlayitem is None:
gr.log.error('Overlay message contains None in the car portion '
'of the message. Please pass in a dictionary or list of dictionaries in this '
'portion of the message. Each dictionary should have the following keys: '
'filename,x,y. Use x=y=-1 to remove an overlay item.')
return
if type(overlayitem) is dict:
itemlist = []
itemlist.append(overlayitem)
elif type(overlayitem) is list:
itemlist = overlayitem
else:
gr.log.error("Overlay message type is not correct. Please pass in "
"a dictionary or list of dictionaries in this portion of the message. Each "
"dictionary should have the following keys: filename,x,y. Use x=y=-1 to "
"remove an overlay item.")
return
# Check each dict item to make sure it's valid.
for curitem in itemlist:
if type(curitem) == dict:
if 'filename' not in curitem:
gr.log.error(
"Dictionary item did not contain the 'filename' key.")
gr.log.error("Received " + str(curitem))
continue
if 'x' not in curitem:
gr.log.error("The dictionary for filename " +
curitem['filename'] + " did not contain an 'x' key.")
gr.log.error("Received " + str(curitem))
continue
if 'y' not in curitem:
gr.log.error("The dictionary for filename " +
curitem['filename'] + " did not contain an 'y' key.")
gr.log.error("Received " + str(curitem))
continue
if not os.path.isfile(curitem['filename']):
gr.log.error("Unable to find overlay file " +
curitem['filename'])
gr.log.error("Received " + str(curitem))
continue
# Now either add/update our list or remove the item.
if curitem['x'] == -1 and curitem['y'] == -1:
try:
# remove item
del self.overlays[curitem['filename']]
except:
pass
else:
self.overlays[curitem['filename']] = curitem
self.updateGraphic()
except Exception as e:
gr.log.error("Error with overlay message conversion: %s" % str(e))
def updateGraphic(self):
if (len(self.overlays.keys()) == 0):
try:
super().setPixmap(self.pixmap)
except Exception as e:
gr.log.error("Error updating graphic: %s" % str(e))
return
else:
# Need to deal with overlays
tmpPxmap = self.pixmap.copy(self.pixmap.rect())
painter = QPainter(tmpPxmap)
for curkey in self.overlays.keys():
curOverlay = self.overlays[curkey]
try:
newOverlay = QPixmap(curkey)
if 'scalefactor' in curOverlay:
scale = curOverlay['scalefactor']
w = newOverlay.width()
h = newOverlay.height()
newOverlay = newOverlay.scaled(int(w * scale), int(h * scale),
Qtc.KeepAspectRatio)
painter.drawPixmap(
curOverlay['x'], curOverlay['y'], newOverlay)
except Exception as e:
gr.log.error("Error adding overlay: %s" % str(e))
return
painter.end()
super().setPixmap(tmpPxmap)
def msgHandler(self, msg):
try:
new_val = pmt.to_python(pmt.cdr(msg))
image_file = new_val
if type(new_val) == str:
if not os.path.isfile(image_file):
gr.log.error("ERROR: Unable to find file " + image_file)
return
try:
self.pixmap = QPixmap(image_file)
self.image_file = image_file
except OSError as e:
gr.log.error("ERROR: " + e.strerror)
return
self.updateGraphic()
else:
gr.log.error("Value received was not an int or "
"a bool: %s" % str(type(new_val)))
except Exception as e:
gr.log.error("Error with message conversion: %s" % str(e))
def minimumSizeHint(self):
return QSize(self.pixmap.width(), self.pixmap.height())
def resizeEvent(self, event):
if self.scaleImage:
w = super().width()
h = super().height()
self.pixmap = self.originalPixmap.scaled(w, h, Qtc.KeepAspectRatio)
elif self.fixedSize and self.setWidth > 0 and self.setHeight > 0:
self.pixmap = self.originalPixmap.scaled(self.setWidth, self.setHeight,
Qtc.KeepAspectRatio)
self.updateGraphic()