itkdb-gtk 0.0.3__py3-none-any.whl → 0.20.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. itkdb_gtk/{sendShipments.py → CreateShipments.py} +74 -78
  2. itkdb_gtk/{getShipments.py → GetShipments.py} +99 -106
  3. itkdb_gtk/GlueWeight.py +45 -66
  4. itkdb_gtk/ITkDB.desktop +8 -0
  5. itkdb_gtk/ITkDB.svg +380 -0
  6. itkdb_gtk/ITkDBlogin.py +10 -6
  7. itkdb_gtk/ITkDButils.py +295 -57
  8. itkdb_gtk/PanelVisualInspection.py +590 -0
  9. itkdb_gtk/QRScanner.py +120 -0
  10. itkdb_gtk/SensorUtils.py +492 -0
  11. itkdb_gtk/ShowAttachments.py +267 -0
  12. itkdb_gtk/ShowComments.py +94 -0
  13. itkdb_gtk/ShowDefects.py +103 -0
  14. itkdb_gtk/UploadModuleIV.py +566 -0
  15. itkdb_gtk/UploadMultipleTests.py +746 -0
  16. itkdb_gtk/UploadTest.py +509 -0
  17. itkdb_gtk/VisualInspection.py +297 -0
  18. itkdb_gtk/WireBondGui.py +1304 -0
  19. itkdb_gtk/__init__.py +38 -12
  20. itkdb_gtk/dashBoard.py +292 -33
  21. itkdb_gtk/dbGtkUtils.py +356 -75
  22. itkdb_gtk/findComponent.py +242 -0
  23. itkdb_gtk/findVTRx.py +36 -0
  24. itkdb_gtk/readGoogleSheet.py +1 -2
  25. itkdb_gtk/untrash_component.py +35 -0
  26. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/METADATA +21 -12
  27. itkdb_gtk-0.20.1.dist-info/RECORD +30 -0
  28. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/WHEEL +1 -1
  29. itkdb_gtk-0.20.1.dist-info/entry_points.txt +12 -0
  30. itkdb_gtk/checkComponent.py +0 -131
  31. itkdb_gtk/groundingTest.py +0 -225
  32. itkdb_gtk/readAVSdata.py +0 -565
  33. itkdb_gtk/uploadPetalInformation.py +0 -604
  34. itkdb_gtk/uploadTest.py +0 -384
  35. itkdb_gtk-0.0.3.dist-info/RECORD +0 -19
  36. itkdb_gtk-0.0.3.dist-info/entry_points.txt +0 -7
  37. {itkdb_gtk-0.0.3.dist-info → itkdb_gtk-0.20.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,590 @@
1
+ #!/usr/bin/env python3
2
+ """PB/Hybrid panel Visual inspection GUI.."""
3
+ import sys
4
+ import copy
5
+ from pathlib import Path
6
+
7
+ try:
8
+ import itkdb_gtk
9
+
10
+ except ImportError:
11
+ cwd = Path(__file__).parent.parent
12
+ sys.path.append(cwd.as_posix())
13
+
14
+ from itkdb_gtk import dbGtkUtils, ITkDBlogin, ITkDButils, QRScanner
15
+ from itkdb_gtk.ShowComments import ShowComments
16
+ from itkdb_gtk.ShowDefects import ShowDefects
17
+ from itkdb_gtk.UploadTest import create_json_data_editor
18
+
19
+
20
+ import gi
21
+ gi.require_version("Gtk", "3.0")
22
+ from gi.repository import Gtk, Gdk, Gio, GObject
23
+
24
+
25
+ class TestJson(GObject.Object):
26
+ """To store test JSOn."""
27
+ __gtype_name__ = "TestJson"
28
+
29
+ def __init__(self, js=None):
30
+ super().__init__()
31
+ self.js = copy.deepcopy(js)
32
+
33
+ def set_js(self, js):
34
+ """SEts the dictionary"""
35
+ self.js = copy.deepcopy(js)
36
+
37
+
38
+ class PanelVisualInspection(dbGtkUtils.ITkDBWindow):
39
+ """PB/Hybryd panel visual inspection GUI."""
40
+ SN, ORDER, PASSED, N_FILES, F_LIST, TEST_J, ALL = range(7)
41
+ F_DEFECT, F_NAME, F_PATH = range(3)
42
+
43
+ def __init__(self, session, title="PanelVisualInspection", help_link=None):
44
+ super().__init__(title=title,
45
+ session=session,
46
+ show_search="Find object with given SN.",
47
+ help_link=help_link)
48
+
49
+ self.institute = self.pdb_user["institutions"][0]["code"]
50
+ self.global_image = None
51
+ self.global_link = None
52
+
53
+ # action button in header
54
+ button = Gtk.Button()
55
+ icon = Gio.ThemedIcon(name="document-send-symbolic")
56
+ image = Gtk.Image.new_from_gicon(icon, Gtk.IconSize.BUTTON)
57
+ button.add(image)
58
+ button.set_tooltip_text("Click to upload ALL tests.")
59
+ button.connect("clicked", self.upload_tests)
60
+ self.hb.pack_end(button)
61
+
62
+ grid = Gtk.Grid(column_spacing=5, row_spacing=1)
63
+ self.mainBox.pack_start(grid, False, False, 5)
64
+
65
+ irow = 0
66
+ receiver = self.create_institute_combo(only_user=True)
67
+ receiver.connect("changed", self.on_institute)
68
+ receiver.set_tooltip_text("Select the Institute making the test.")
69
+ dbGtkUtils.set_combo_iter(receiver, self.institute)
70
+
71
+ lbl = Gtk.Label(label="Institute")
72
+ lbl.set_xalign(0)
73
+ grid.attach(lbl, 0, irow, 1, 1)
74
+ grid.attach(receiver, 1, irow, 1, 1)
75
+
76
+ irow += 1
77
+ lbl = Gtk.Label(label="Serial Number")
78
+ lbl.set_xalign(0)
79
+ grid.attach(lbl, 0, irow, 1, 1)
80
+
81
+ self.SN = dbGtkUtils.TextEntry(small=True)
82
+ self.SN.connect("text_changed", self.SN_ready)
83
+ self.SN.widget.set_tooltip_text("Enter SN of PWD or Hybrid panel.")
84
+ grid.attach(self.SN.widget, 1, irow, 1, 1)
85
+
86
+ self.panel_type = Gtk.Label(label="")
87
+ grid.attach(self.panel_type, 2, irow, 1, 1)
88
+
89
+ irow += 1
90
+ lbl = Gtk.Label(label="Date")
91
+ lbl.set_xalign(0)
92
+ grid.attach(lbl, 0, irow, 1, 1)
93
+
94
+ self.date = dbGtkUtils.TextEntry(small=True)
95
+ grid.attach(self.date.widget, 1, irow, 1, 1)
96
+ self.date.entry.set_text(ITkDButils.get_db_date())
97
+ self.date.connect("text_changed", self.new_date)
98
+
99
+ irow += 1
100
+ self.fC = Gtk.FileChooserButton()
101
+ self.fC.connect("file-set", self.on_global_image)
102
+
103
+ lbl = Gtk.Label(label="Global Image")
104
+ lbl.set_xalign(0)
105
+ grid.attach(lbl, 0, irow, 1, 1)
106
+ grid.attach(self.fC, 1, irow, 1, 1)
107
+
108
+
109
+ # Paned object
110
+ paned = Gtk.Paned(orientation=Gtk.Orientation.VERTICAL)
111
+ paned.set_size_request(-1, 200)
112
+ self.mainBox.pack_start(paned, True, True, 5)
113
+
114
+ # the list of attachments
115
+ tree_view = self.create_tree_view()
116
+ paned.add1(tree_view)
117
+
118
+ # The text view
119
+ paned.add2(self.message_panel.frame)
120
+
121
+
122
+ self.show_all()
123
+ self.scanner = QRScanner.QRScanner(self.get_qrcode)
124
+
125
+ def on_global_image(self, *args):
126
+ """We choose the global image."""
127
+ fnam = self.fC.get_filename()
128
+ if fnam is None or not Path(fnam).exists():
129
+ dbGtkUtils.complain("Could not find image", fnam, parent=self)
130
+ return
131
+
132
+ self.global_image = Path(fnam).expanduser().resolve()
133
+
134
+
135
+
136
+ def on_institute(self, combo):
137
+ """A new recipient has been chosen."""
138
+ name = self.get_institute_from_combo(combo)
139
+ if name:
140
+ self.institute = name
141
+
142
+ def new_date(self, entry, value):
143
+ """new date given at input."""
144
+ d = dbGtkUtils.parse_date_as_string(value)
145
+ if d is not None:
146
+ self.date.set_text(d)
147
+
148
+ def create_model(self):
149
+ """Create tree view model."""
150
+ return Gtk.ListStore(str, int, bool, int, Gtk.ListStore, TestJson)
151
+
152
+ def create_file_model(self):
153
+ """Create model for file list"""
154
+ return Gtk.ListStore(str, str, str)
155
+
156
+ def create_tree_view(self, size=150):
157
+ """Create the TreeView with the children."""
158
+ model = self.create_model()
159
+ self.tree = Gtk.TreeView(model=model)
160
+ self.tree.connect("button-press-event", self.button_pressed)
161
+
162
+ scrolled = Gtk.ScrolledWindow()
163
+ scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
164
+ scrolled.add(self.tree)
165
+ scrolled.set_size_request(-1, size)
166
+
167
+ renderer = Gtk.CellRendererText()
168
+ column = Gtk.TreeViewColumn("SN", renderer, text=PanelVisualInspection.SN)
169
+ self.tree.append_column(column)
170
+
171
+ renderer = Gtk.CellRendererText()
172
+ column = Gtk.TreeViewColumn("position", renderer, text=PanelVisualInspection.ORDER)
173
+ self.tree.append_column(column)
174
+
175
+ renderer = Gtk.CellRendererToggle()
176
+ renderer.set_property("activatable", True)
177
+ renderer.set_property("radio", True)
178
+ renderer.set_padding(5, 0)
179
+
180
+ _, y = renderer.get_alignment()
181
+ renderer.set_alignment(0, y)
182
+ # renderer.set_property("inconsistent", True)
183
+ renderer.connect("toggled", self.btn_toggled)
184
+
185
+ column = Gtk.TreeViewColumn("Passed", renderer, active=PanelVisualInspection.PASSED)
186
+ self.tree.append_column(column)
187
+
188
+ renderer = Gtk.CellRendererText()
189
+ column = Gtk.TreeViewColumn("N. Images", renderer, text=PanelVisualInspection.N_FILES)
190
+ self.tree.append_column(column)
191
+
192
+ return scrolled
193
+
194
+ def btn_toggled(self, renderer, path, *args):
195
+ """Toggled."""
196
+ model = self.tree.get_model()
197
+ val = not model[path][PanelVisualInspection.PASSED]
198
+ model[path][PanelVisualInspection.PASSED] = val
199
+ model[path][PanelVisualInspection.TEST_J].js["passed"] = val
200
+
201
+ def get_iter_at_position(self, tree, event):
202
+ """Get the model and iterator at position."""
203
+ # Create popup menu
204
+ select = tree.get_selection()
205
+ model, lv_iter = select.get_selected()
206
+ values = None
207
+ if lv_iter:
208
+ values = model[lv_iter]
209
+
210
+ else:
211
+ P = tree.get_path_at_pos(event.x, event.y)
212
+ if P:
213
+ lv_iter = model.get_iter(P[0])
214
+ values = model[lv_iter]
215
+
216
+ return model, lv_iter, values
217
+
218
+
219
+ def button_pressed(self, tree, event):
220
+ """Button pressed on tree view."""
221
+ # Create popup menu
222
+ model, lv_iter, values = self.get_iter_at_position(tree, event)
223
+ if not values:
224
+ return
225
+
226
+ # double click shows attachments
227
+ if event.button == 1 and event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
228
+ #self.write_message("This is a double click.\n")
229
+ self.on_upload_image(None, (model, lv_iter, values))
230
+ return
231
+
232
+ if event.button != 3:
233
+ return
234
+
235
+ menu = Gtk.Menu()
236
+
237
+ item_show = Gtk.MenuItem(label="Upload Image")
238
+ item_show.connect("activate", self.on_upload_image, (model, lv_iter, values))
239
+ menu.append(item_show)
240
+
241
+ item_show_json = Gtk.MenuItem(label="Show JSOn")
242
+ item_show_json.connect("activate", self.on_show_json, (model, lv_iter, values))
243
+ menu.append(item_show_json)
244
+
245
+ item_show_com = Gtk.MenuItem(label="Edit Comments")
246
+ item_show_com.connect("activate", self.on_show_comments, (model, lv_iter, values))
247
+ menu.append(item_show_com)
248
+
249
+ item_show_def = Gtk.MenuItem(label="Edit Defects")
250
+ item_show_def.connect("activate", self.on_show_defects, (model, lv_iter, values))
251
+ menu.append(item_show_def)
252
+
253
+ menu.show_all()
254
+ menu.popup_at_pointer(event)
255
+
256
+ def on_upload_image(self, item, data):
257
+ """Add defects with images.."""
258
+
259
+ model, lv_iter, val = data
260
+
261
+ irow = 0
262
+ tree = Gtk.TreeView(model=val[self.F_LIST])
263
+ tree.connect("button-press-event", self.on_file_pressed)
264
+
265
+ btn = Gtk.Button(label="Add image")
266
+ btn.set_tooltip_text("Click to add a new image.")
267
+ btn.connect("clicked", self.on_add_image, val[PanelVisualInspection.F_LIST])
268
+
269
+ scrolled = Gtk.ScrolledWindow()
270
+ scrolled.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
271
+ scrolled.add(tree)
272
+ scrolled.set_size_request(-1, 150)
273
+
274
+ renderer = Gtk.CellRendererText()
275
+ column = Gtk.TreeViewColumn("Description", renderer, text=PanelVisualInspection.F_DEFECT)
276
+ tree.append_column(column)
277
+
278
+ renderer = Gtk.CellRendererText()
279
+ column = Gtk.TreeViewColumn("File", renderer, text=PanelVisualInspection.F_NAME)
280
+ tree.append_column(column)
281
+
282
+ dlg = Gtk.Dialog(title="Add Image")
283
+ dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
284
+ Gtk.STOCK_OK, Gtk.ResponseType.OK)
285
+ box = dlg.get_content_area()
286
+ box.add(btn)
287
+ box.add(scrolled)
288
+ dlg.show_all()
289
+ rc = dlg.run()
290
+ if rc == Gtk.ResponseType.OK:
291
+ f_model = tree.get_model()
292
+ n_files = f_model.iter_n_children()
293
+ model.set_value(lv_iter, PanelVisualInspection.F_LIST, f_model)
294
+ model.set_value(lv_iter, PanelVisualInspection.N_FILES, n_files)
295
+
296
+ dlg.hide()
297
+ dlg.destroy()
298
+
299
+ self.write_message("Defects added\n")
300
+
301
+ def on_file_pressed(self, tree, event):
302
+ """Called when right button clicked in add image dialog.
303
+
304
+ Opens a pop-up menu to delete the selected entry."""
305
+ # double click shows attachments
306
+ if event.button == 1 and event.type == Gdk.EventType.DOUBLE_BUTTON_PRESS:
307
+ self.write_message("This is a double click.\n")
308
+ return
309
+
310
+
311
+ if event.button != 3:
312
+ return
313
+
314
+ model, lv_iter, values = self.get_iter_at_position(tree, event)
315
+ if not values:
316
+ return
317
+ menu = Gtk.Menu()
318
+
319
+ item_show = Gtk.MenuItem(label="Delete")
320
+ item_show.connect("activate", self.on_delete_image, (model, lv_iter, values))
321
+ menu.append(item_show)
322
+
323
+ menu.show_all()
324
+ menu.popup_at_pointer(event)
325
+
326
+ def on_delete_image(self, item, data):
327
+ """Delete a defect and image"""
328
+ model, lv_iter, _ = data
329
+ model.remove(lv_iter)
330
+
331
+ def on_add_image(self, btn, model):
332
+ """Adds a new image."""
333
+ dlg = Gtk.Dialog(title="Add Image")
334
+
335
+ dlg.add_buttons(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
336
+ Gtk.STOCK_OK, Gtk.ResponseType.OK)
337
+ box = dlg.get_content_area()
338
+ grid = Gtk.Grid(column_spacing=5, row_spacing=1)
339
+ box.add(grid)
340
+
341
+ irow = 0
342
+ lbl = Gtk.Label(label="Description")
343
+ lbl.set_xalign(0)
344
+ grid.attach(lbl, 0, irow, 1, 1)
345
+
346
+ desc = Gtk.Entry()
347
+ grid.attach(desc, 1, irow, 1, 1)
348
+
349
+ irow += 1
350
+ lbl = Gtk.Label(label="Image")
351
+ lbl.set_xalign(0)
352
+ grid.attach(lbl, 0, irow, 1, 1)
353
+
354
+ fC = Gtk.FileChooserButton()
355
+ grid.attach(fC, 1, irow, 1, 1)
356
+
357
+ dlg.show_all()
358
+
359
+ rc = dlg.run()
360
+ if rc == Gtk.ResponseType.OK:
361
+ D = desc.get_text()
362
+ P = Path(fC.get_filename()).expanduser().resolve()
363
+ model.append([D, P.name, P.as_posix()])
364
+
365
+ dlg.hide()
366
+ dlg.destroy()
367
+
368
+ def on_show_json(self, item, data):
369
+ """Test JSon."""
370
+ model, lv_iter, val = data
371
+ payload = val[PanelVisualInspection.TEST_J].js
372
+ value, dlg = create_json_data_editor(payload)
373
+ rc = dlg.run()
374
+ if rc == Gtk.ResponseType.OK:
375
+ payload = value.values
376
+ model.set_value(lv_iter, PanelVisualInspection.TEST_J, TestJson(payload))
377
+
378
+ dlg.hide()
379
+ dlg.destroy()
380
+
381
+ def on_show_comments(self, item, data):
382
+ """Show comments"""
383
+ model, lv_iter, val = data
384
+ js = val[PanelVisualInspection.TEST_J].js
385
+ SC = ShowComments("Test Comments", js["comments"], self)
386
+ rc = SC.run()
387
+ if rc == Gtk.ResponseType.OK:
388
+ js["comments"] = SC.comments
389
+ model.set_value(lv_iter, PanelVisualInspection.TEST_J, TestJson(js))
390
+
391
+ SC.hide()
392
+ SC.destroy()
393
+
394
+ def on_show_defects(self, item, data):
395
+ """Show comments"""
396
+ model, lv_iter, val = data
397
+ js = val[PanelVisualInspection.TEST_J].js
398
+ SD = ShowDefects("Test Defects", js["defects"], self)
399
+ rc = SD.run()
400
+ if rc == Gtk.ResponseType.OK:
401
+ js["defects"] = SD.defects
402
+ model.set_value(lv_iter, PanelVisualInspection.TEST_J, TestJson(js))
403
+
404
+ SD.hide()
405
+ SD.destroy()
406
+
407
+ def SN_ready(self, *args):
408
+ """SN is ready in the TextEnttry."""
409
+ SN = self.SN.get_text()
410
+ # GEt children.
411
+ panel = ITkDButils.get_DB_component(self.session, SN)
412
+ if panel is None:
413
+ self.write_message(ITkDButils.get_db_response())
414
+ return
415
+
416
+ SN = panel["serialNumber"]
417
+ args[0].set_text(SN)
418
+ is_PWB = False
419
+ defaults = {
420
+ "institution": self.institute,
421
+ "runNumber": "1",
422
+ "date": self.date.get_text()
423
+ }
424
+ component_type = None
425
+ test_code = None
426
+ if "USED" in SN:
427
+ # Powerboard Carrier
428
+ if not SN[6].isdigit():
429
+ dbGtkUtils.complain("Not a Powerboard Carrier",
430
+ "{}: wrong SN for a powerboard carrier".format(SN))
431
+ self.SN.widget.set_text("")
432
+ return
433
+
434
+ self.panel_type.set_text("PWB carrier")
435
+ is_PWB = True
436
+ component_type = "PWB"
437
+ test_code = "PICTURE"
438
+
439
+ elif "USET" in SN:
440
+ # Hybrid test panel
441
+ component_type = "HYBRID_TEST_PANEL"
442
+ test_code = "VISUAL_INSPECTION"
443
+
444
+ if not SN[6].isdigit or int(SN[6])>5:
445
+ dbGtkUtils.complain("Not a Hybrid Test Panel",
446
+ "{}: wrong SN for a hybrid test panel".format(SN))
447
+ self.SN.widget.set_text("")
448
+ return
449
+
450
+ self.panel_type.set_text("HYB test panel")
451
+
452
+ else:
453
+ dbGtkUtils.complain("Invalid SN.",
454
+ "{}\nNot a PWB carrier not HYB test panel.".format(SN))
455
+ self.SN.widget.set_text("")
456
+ return
457
+
458
+ # GEt children.
459
+ skltn = ITkDButils.get_test_skeleton(self.session, component_type, test_code, defaults)
460
+ model = self.create_model()
461
+ for child in panel["children"]:
462
+ if child["component"] is not None:
463
+ child_SN = child["component"]["serialNumber"]
464
+ skltn["component"] = child_SN
465
+ if is_PWB:
466
+ position = child["order"]
467
+ else:
468
+ position = -1
469
+ for P in child["properties"]:
470
+ if P["code"] == "HYBRID_POSITION":
471
+ if P["value"] is not None:
472
+ position = int(P["value"])
473
+ break
474
+
475
+ model.append([child_SN, position, True, 0, self.create_file_model(), TestJson(skltn)])
476
+
477
+ self.tree.set_model(model)
478
+
479
+
480
+ def upload_tests(self, *args):
481
+ """Upload the current test."""
482
+ SN = self.SN.get_text()
483
+
484
+ model = self.tree.get_model()
485
+ lv_iter = model.get_iter_first()
486
+ n_items = 0
487
+ global_link = None
488
+ while lv_iter:
489
+ values = model[lv_iter]
490
+ payload = values[PanelVisualInspection.TEST_J].js
491
+
492
+ attachments = []
493
+ if global_link is None:
494
+ if self.global_image is not None:
495
+ A = ITkDButils.Attachment(path=self.global_image, title="Global Image", desc="Image of whole panel")
496
+ attachments.append(A)
497
+
498
+ im_model = values[PanelVisualInspection.F_LIST]
499
+ im_iter = im_model.get_iter_first()
500
+ idef = 1
501
+ while im_iter:
502
+ defect, name, path = im_model[im_iter]
503
+ A = ITkDButils.Attachment(path=path, title="Defect {}".format(idef), desc=defect)
504
+ attachments.append(A)
505
+ idef += 1
506
+ im_iter = im_model.iter_next(im_iter)
507
+
508
+ rc = ITkDButils.upload_test(self.session, payload, attachments, check_runNumber=True)
509
+ if rc:
510
+ ipos = rc.find("The following details may help:")
511
+ msg = rc[ipos:]
512
+ dbGtkUtils.complain("Failed uploading test {}-{}".format(payload["component"], payload["testType"]), msg)
513
+ self.write_message(msg+"\n")
514
+
515
+ else:
516
+ self.write_message("Upload {}-{} successfull\n".format(payload["component"], payload["testType"]))
517
+ if global_link is None:
518
+ try:
519
+ if self.global_image is not None:
520
+ global_link = ITkDButils.attachment_urls[self.global_image.name]
521
+ except KeyError:
522
+ pass
523
+
524
+ if payload["testType"] == "PICTURE":
525
+ rc = ITkDButils.set_test_run_parameter(self.session,
526
+ ITkDButils.uploaded_test_runs[0],
527
+ "COMMENT", "Picture of PW carrier")
528
+
529
+ rc = ITkDButils.set_test_run_parameter(self.session,
530
+ ITkDButils.uploaded_test_runs[0],
531
+ "LINK_TO_PICTURE", global_link)
532
+ if rc:
533
+ ipos = rc.find("The following details may help:")
534
+ msg = rc[ipos:]
535
+ dbGtkUtils.complain("Failed updating LINK_TO_PICTURE {}-{}".format(payload["component"],
536
+ payload["testType"]), msg)
537
+ self.write_message(msg+'\n')
538
+
539
+ elif payload["testType"] == "VISUAL_INSPECTION":
540
+ rc = ITkDButils.create_test_run_comment(self.session,
541
+ ITkDButils.uploaded_test_runs[0],
542
+ ["Link to global image:\n {}".format(global_link)])
543
+ if rc:
544
+ ipos = rc.find("The following details may help:")
545
+ msg = rc[ipos:]
546
+ dbGtkUtils.complain("Failed adding global link as comment: {}-{}".format(payload["component"],
547
+ payload["testType"]), msg)
548
+ self.write_message(msg+"\n")
549
+ else:
550
+ self.write_message("Image: {}\n".format(global_link))
551
+
552
+
553
+ n_items += 1
554
+ lv_iter = model.iter_next(lv_iter)
555
+
556
+
557
+ def get_qrcode(self,txt):
558
+ """Read SN from scanner."""
559
+ self.write_message("SN: {}\n".format(txt))
560
+ self.SN_ready(txt, self.SN.widget)
561
+
562
+
563
+ def main():
564
+ """Main entry."""
565
+ # DB login
566
+ HELP_LINK="https://itkdb-gtk.docs.cern.ch/panelVisualInspection.html"
567
+
568
+ dlg = ITkDBlogin.ITkDBlogin()
569
+ client = dlg.get_client()
570
+ if client is None:
571
+ print("Could not connect to DB with provided credentials.")
572
+ dlg.die()
573
+ sys.exit()
574
+
575
+ client.user_gui = dlg
576
+
577
+ gTest = PanelVisualInspection(client, help_link=HELP_LINK)
578
+
579
+ gTest.present()
580
+ gTest.connect("destroy", Gtk.main_quit)
581
+ try:
582
+ Gtk.main()
583
+
584
+ except KeyboardInterrupt:
585
+ print("Arrrgggg!!!")
586
+
587
+ dlg.die()
588
+
589
+ if __name__ == "__main__":
590
+ main()
itkdb_gtk/QRScanner.py ADDED
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+ """A set of utilities for teh warp scanner."""
3
+ import pathlib
4
+ import serial
5
+ import serial.tools.list_ports as list_ports
6
+
7
+ import gi
8
+ gi.require_version("Gtk", "3.0")
9
+ from gi.repository import GLib
10
+
11
+ class QRScanner:
12
+ """Contains information to detect the scanner."""
13
+ def __init__(self, callback):
14
+ self.reader = None
15
+ self.callback = callback
16
+ self.timer_id = None
17
+ self.source_id = None
18
+ self.init_scanner()
19
+
20
+ def init_scanner(self):
21
+ """Sets the scanner."""
22
+ self.setup_scanner()
23
+ if self.reader is None:
24
+ self.timer_id = GLib.timeout_add(500, self.find_scanner)
25
+ else:
26
+ print("Found scanner in {}".format(self.reader.name))
27
+
28
+ def find_scanner(self, *args):
29
+ """Check if the scanner is there."""
30
+ # if the reader is there, stop the timeput
31
+ if self.reader is not None:
32
+ return False
33
+
34
+ # Try to setup the scanner
35
+ self.setup_scanner()
36
+ if self.reader is not None:
37
+ self.timer_id = None
38
+ print("Found scanner in {}".format(self.reader.name))
39
+ return False
40
+ else:
41
+ return True
42
+
43
+
44
+ def setup_scanner(self):
45
+ """Setup scanner and callback function."""
46
+ if self.reader is not None:
47
+ return
48
+
49
+ self.reader = None
50
+ device_signature = '05f9:4204|1a86:7523'
51
+ candidates = list(list_ports.grep(device_signature))
52
+ if not candidates:
53
+ return
54
+
55
+ self.reader = serial.Serial(candidates[0].device, 9600)
56
+ self.source_id = GLib.unix_fd_add_full(
57
+ GLib.PRIORITY_DEFAULT,
58
+ self.reader.fileno(),
59
+ GLib.IOCondition.IN | GLib.IOCondition.ERR | GLib.IOCondition.NVAL,
60
+ self.get_line,
61
+ self.callback,
62
+ )
63
+
64
+
65
+ def finish_timeout(self):
66
+ """Finishes the timeout."""
67
+ GLib.source_remove(self.source_id)
68
+ self.source_id = None
69
+
70
+ self.reader.close()
71
+ self.reader = None
72
+
73
+ # re-start the search of the scanner
74
+ self.timer_id = GLib.timeout_add(500, self.find_scanner)
75
+
76
+ def get_line(self, fd, state, callback):
77
+ """Has to info to read."""
78
+ if state == GLib.IOCondition.IN:
79
+ try:
80
+ available = self.reader.in_waiting
81
+ while True:
82
+ delta = self.reader.in_waiting - available
83
+ if not delta:
84
+ break
85
+
86
+ # Get data from serial device passed in via
87
+ data = self.reader.read_until(expected='\r', size=self.reader.in_waiting).strip()
88
+ txt = data.decode('utf-8')
89
+ if callback:
90
+ callback(txt)
91
+
92
+ except OSError:
93
+ if not pathlib.Path(self.reader.name).exists():
94
+ print("Device unplugged.")
95
+ self.finish_timeout()
96
+ return False
97
+
98
+ return True
99
+
100
+
101
+ else:
102
+ self.finish_timeout()
103
+ return False
104
+
105
+ def get_text_from_scanner(txt):
106
+ """Callback where the scanners sends the text."""
107
+ print("### {}".format(txt))
108
+
109
+ def test_scanner():
110
+ """Test the thing."""
111
+ scanner = QRScanner(get_text_from_scanner)
112
+
113
+ loop = GLib.MainLoop()
114
+ try:
115
+ loop.run()
116
+ except KeyboardInterrupt:
117
+ loop.quit()
118
+
119
+ if __name__ == "__main__":
120
+ test_scanner()