-
Notifications
You must be signed in to change notification settings - Fork 0
/
APP_Sallet_VISOR.py
263 lines (209 loc) · 11.6 KB
/
APP_Sallet_VISOR.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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
import os
import sys
from kivy.app import App
from kivy.core.window import Window
from kivy.clock import Clock
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics.texture import Texture
import cv2
from pyzbar import pyzbar
class OperationAreaBox(BoxLayout):
pass
class OpAreaIntro(OperationAreaBox):
def on_fileclick(self, inst):
print(inst.selection[0])
def btnclck_constr_qr(self, inst):
print(inst.state)
def btnclck_constr_txt(self, inst):
print(inst.state)
def btnclck_constr_stp(self, inst):
print(inst.state)
class ScanArea(BoxLayout):
def __init__(self, **kwargs):
super(ScanArea, self).__init__(**kwargs)
self.orientation = 'horizontal'
self.cam = cv2.VideoCapture(0)
self.cam.set(3, 800) # size settings, do not seem to be having an effect on Windows or Ubuntu system
self.cam.set(4, 600) # size settings, do not seem to be having an effect on Windows or Ubuntu system
self.fps = 24 # frames per sec.c
self.schedule = None # an empty cast, to be created on scanning start
self.collected_strings = [] # list of string data read from QR codes
self.counter = 0
def start_scanning(self):
App.get_running_app().root.ids.screen_scan.ids.opareascan.ids.labelinfo.text = "Scanned the following:\n"
self.schedule = Clock.schedule_interval(self.update, 1.0 / self.fps)
def stop_scanning(self):
self.schedule.cancel()
for _ in self.collected_strings:
print(_)
def update(self, dt):
ret, frame = self.cam.read() # ret: bool, frame seems to be a numpy data of the screen
if ret:
buf1 = cv2.flip(frame, 0)
buf = buf1.tobytes()
image_texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
image_texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
self.ids.img.texture = image_texture
barcodes = pyzbar.decode(frame) # lloking for codes in the frame...
if not barcodes:
scan_img = cv2.putText(frame, 'S', (50, 75), cv2.FONT_HERSHEY_DUPLEX, 1.5, (0, 255, 0), 2)
scan_buf = cv2.flip(scan_img, 0)
scan_buf = scan_buf.tobytes()
scan_texture = Texture.create(size=(scan_img.shape[1], scan_img.shape[0]), colorfmt='bgr')
scan_texture.blit_buffer(scan_buf, colorfmt='bgr', bufferfmt='ubyte')
self.ids.img.texture = scan_texture
else:
for barcode in barcodes:
(x, y, w, h) = barcode.rect
rectangle_img = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 7)
rectangle_buf = cv2.flip(rectangle_img, 0)
rectangle_buf = rectangle_buf.tobytes()
rectangle_texture = Texture.create(size=(rectangle_img.shape[1], rectangle_img.shape[0]),
colorfmt='bgr')
rectangle_texture.blit_buffer(rectangle_buf, colorfmt='bgr', bufferfmt='ubyte')
self.ids.img.texture = rectangle_texture
actual_text = str(barcode.data.decode("utf-8"))
if actual_text not in self.collected_strings:
self.counter += 1
self.collected_strings.append(actual_text)
App.get_running_app().root.ids.screen_scan.ids.opareascan.ids.labelinfo.text +=\
"\n{:<3}: {:>20}".format(self.counter, actual_text[:20])
class OpAreaScan(OperationAreaBox):
def __init__(self, **kwargs):
super(OpAreaScan, self).__init__(**kwargs)
def on_toggle_scan_qr(self, inst):
if inst.state == "normal":
self.ids.scan_area.stop_scanning()
inst.text = "scanning stopped"
else:
self.ids.scan_area.start_scanning()
inst.text = "scanning..."
print("toggled camera on/off")
class OpAreaPub(OperationAreaBox):
def __init__(self, **kwargs):
super(OpAreaPub, self).__init__(**kwargs)
def btnclck_publish(self, inst):
print("TX is being published")
class AppObjScreenManager(ScreenManager):
def __init__(self, **kwargs):
super(AppObjScreenManager, self).__init__(**kwargs)
self.statedict = {
"screen_intro": {
"seq": 0,
'inst': 'button_nav_intro',
'down': ['button_nav_intro'],
'normal': ["button_nav_scan", "button_nav_tx", "button_nav_pub", "button_nav_utxo"]},
"screen_scan": {
"seq": 1,
'inst': 'button_nav_scan',
'down': ['button_nav_scan'],
'normal': ["button_nav_intro", "button_nav_tx", "button_nav_pub", "button_nav_utxo"]},
"screen_tx": {
"seq": 2,
'inst': 'button_nav_tx',
'down': ['button_nav_tx'],
'normal': ["button_nav_intro", "button_nav_scan", "button_nav_pub", "button_nav_utxo"]},
"screen_pub": {
"seq": 3,
'inst': 'button_nav_pub',
'down': ['button_nav_pub'],
'normal': ["button_nav_intro", "button_nav_scan", "button_nav_tx", "button_nav_utxo"]},
"screen_utxo": {
"seq": 4,
'inst': 'button_nav_utxo',
'down': ['button_nav_utxo'],
'normal': ["button_nav_intro", "button_nav_scan", "button_nav_tx", "button_nav_pub"]}
}
class NavBar(BoxLayout):
"""=== Class name: NavBar ==========================================================================================
This Layout can be used across all screens. Class handles complications of now yet drawn instances.
It sets appearance for instances only appearing on screen.
============================================================================================== by Sziller ==="""
@ staticmethod
def on_release_navbar(inst):
"""=== Method name: on_toggle_navbar ===========================================================================
Method manages multiple screen selection by Toggle button set.
All Toggle Buttons call this same function. Their Class names are stored in the <buttons> list.
Only one button of the entire set is down at a given time. Function is extendable.
Once a given button is 'down', it becomes inactive, all other buttons are activated and set to "normal" state.
The reason of the logic is as follows:
Screen manager is the unit taking care of actual screen swaps, also it stores actually shown screen name.
However, at the itme of instantiation of the Screen Manager's ids are still not accessible.
So we refer to ScreenManager's id's only on user action.
:var inst: - the instance (button) activating the Method.
========================================================================================== by Sziller ==="""
old_seq: int = 0
for k, v in App.get_running_app().root.statedict.items():
if k == App.get_running_app().root.current_screen.name:
old_seq = v["seq"]
break
new_seq = App.get_running_app().root.statedict[inst.target]["seq"]
App.get_running_app().change_screen(screen_name=inst.target, screen_direction={True: "left", False: "right"}
[old_seq - new_seq < 0])
for buttinst in App.get_running_app().root.current_screen.ids.navbar.ids:
if buttinst in App.get_running_app().root.statedict[inst.target]['normal']:
App.get_running_app().root.current_screen.ids.navbar.ids[buttinst].disabled = False
App.get_running_app().root.current_screen.ids.navbar.ids[buttinst].state = "normal"
if buttinst in App.get_running_app().root.statedict[inst.target]['down']:
App.get_running_app().root.current_screen.ids.navbar.ids[buttinst].disabled = True
App.get_running_app().root.current_screen.ids.navbar.ids[buttinst].state = "down"
class AppObj(App):
"""=== Class name: AppObj ========================================================================================
Child of built in class: App
This is the Parent application for a project.
Instantiation should - contrary to what is used on the net - happen by assigning it to a variable name.
:param window_content:
============================================================================================== by Sziller ==="""
def __init__(self,
window_content: str,
app_title: str = "Sziller's App",
app_icon: str = "",
csm: float = 1.0):
super(AppObj, self).__init__()
self.title = app_title
self.icon = app_icon
self.window_content = window_content
self.content_size_multiplier = csm
self.external_var: list = []
def change_screen(self, screen_name, screen_direction="left"):
"""=== Method name: change_screen ==============================================================================
Use this screenchanger instead of the built-in method for more customizability and to enable further
actions before changing the screen.
Also, if screenchanging first needs to be validated, use this method!
========================================================================================== by Sziller ==="""
smng = self.root # 'root' refers to the only one root instance in your App. Here it is the actual ROOT
smng.current = screen_name
smng.transition.direction = screen_direction
def build(self):
return self.window_content
if __name__ == "__main__":
from kivy.lang import Builder # to freely pick kivy files
# use presets to
display_settings = {0: {'fullscreen': False, 'run': Window.maximize}, # cover screen with titlebar accessible
1: {'fullscreen': True, 'run': Window.maximize}, # Fullscreen mode
2: {'fullscreen': False, 'size': (480, 640)}, # Portrait Raspberry Display
3: {'fullscreen': False, 'size': (640, 480)}, # Landscape Raspberry Display
4: {'fullscreen': False, 'size': (480, 960)}, # Portrait Cellphone
5: {'fullscreen': False, 'size': (960, 480)}, # Landscape Cellphone
6: {'fullscreen': False, 'size': (800, 800)}, # Qubic layout
}
style_code = 6
Window.fullscreen = display_settings[style_code]['fullscreen']
if 'size' in display_settings[style_code].keys(): Window.size = display_settings[style_code]['size']
if 'run' in display_settings[style_code].keys(): display_settings[style_code]['run']()
Window.top = 40
Window.left = 40
try:
content = Builder.load_file(str(sys.argv[1]))
except IndexError:
content = Builder.load_file("app_sallet_visor.kv")
application_title_in_window_head = "SalletVISOR"
application_window_icon = "caution.png"
content_size_multiplier = 1
application = AppObj(window_content=content,
app_title=application_title_in_window_head,
app_icon=application_window_icon,
csm=content_size_multiplier)
data_from_app = application.external_var
application.run()