1- import multiprocessing
2- import queue
3- import time
1+ import sys
2+ from PyQt4 import QtGui
43
5- from PyQt4 import QtGui , QtCore
4+ from dls_barcode . config import BarcodeConfigDialog
65
7- from dls_barcode .config import BarcodeConfig , BarcodeConfigDialog
8- from dls_barcode .camera import CameraScanner , CameraSwitch , NoNewBarcodeMessage , ScanErrorMessage
96from dls_barcode .gui .scan_button import ScanButton
10- from dls_util import Beeper
11- from dls_util .file import FileManager
7+
128from .barcode_table import BarcodeTable
139from .image_frame import ImageFrame
1410from .record_table import ScanRecordTable
1511from .message_box import MessageBox
1612from .message_factory import MessageFactory
1713from .menu_bar import MenuBar
1814
19- RESULT_TIMER_PERIOD = 1000 # ms
20- VIEW_TIMER_PERIOD = 1 # ms
21- MESSAGE_TIMER_PERIOD = 1 # ms
22-
2315
2416class DiamondBarcodeMainWindow (QtGui .QMainWindow ):
2517 """ Main GUI window for the Barcode Scanner App.
2618 """
27- def __init__ (self , config_file , version ):
19+
20+ def __init__ (self , config , version ):
2821 super (DiamondBarcodeMainWindow , self ).__init__ ()
2922
30- self ._config = BarcodeConfig ( config_file , FileManager ())
23+ self ._config = config
3124 self ._version = version
25+ self ._cleanup = None
26+ self ._initialise_scanner = None
27+ self ._camera_capture_alive = None
3228
3329 # UI elements
3430 self ._record_table = None
3531 self ._barcode_table = None
3632 self ._image_frame = None
3733 self ._scan_button = None
3834
39- # Scan elements
40- self ._camera_scanner = None
41- self ._camera_switch = None
42-
4335 self ._init_ui ()
4436
45- # Queue that holds new results generated in continuous scanning mode
46- self ._result_queue = multiprocessing .Queue ()
47- self ._view_queue = multiprocessing .Queue ()
48- self ._message_queue = multiprocessing .Queue ()
49- self ._initialise_scanner ()
50- self ._reset_msg_timer ()
51-
52- # Timer that controls how often new scan results are looked for
53- self ._result_timer = QtCore .QTimer ()
54- self ._result_timer .timeout .connect (self ._read_result_queue )
55- self ._result_timer .start (RESULT_TIMER_PERIOD )
56-
57- self ._view_timer = QtCore .QTimer ()
58- self ._view_timer .timeout .connect (self ._read_view_queue )
59- self ._view_timer .start (VIEW_TIMER_PERIOD )
60-
61- self ._message_timer = QtCore .QTimer ()
62- self ._message_timer .timeout .connect (self ._read_message_queue )
63- self ._message_timer .start (MESSAGE_TIMER_PERIOD )
64-
65- self ._restart_live_capture_from_side ()
66-
6737 def _init_ui (self ):
6838 """ Create the basic elements of the user interface.
6939 """
@@ -73,19 +43,19 @@ def _init_ui(self):
7343 self .setWindowTitle ('Diamond Puck Barcode Scanner' )
7444 self .setWindowIcon (self ._window_icon )
7545
76- self ._menu_bar = MenuBar (self .menuBar (), self ._version , self . _cleanup , self . _on_options_action_clicked , self . _on_about_action_clicked )
46+ self ._menu_bar = MenuBar (self .menuBar (), self ._version )
7747
7848 # Barcode table - lists all the barcodes in a record
7949 self ._barcode_table = BarcodeTable (self ._config )
8050
8151 # Scan button - start/stop scan
82- self ._scan_button = ScanButton ('Start/stop scan' , self . _on_scan_action_clicked )
52+ self ._scan_button = ScanButton ('Start/stop scan' )
8353
8454 # Image frame - displays image of the currently selected scan record
8555 self ._image_frame = ImageFrame ("Plate Image" )
8656
8757 # Scan record table - lists all the records in the store
88- self ._record_table = ScanRecordTable (self ._barcode_table , self ._image_frame , self ._config , self . _to_run_on_table_clicked )
58+ self ._record_table = ScanRecordTable (self ._barcode_table , self ._image_frame , self ._config )
8959
9060 # Message display
9161 self ._message_box = MessageBox ()
@@ -116,18 +86,28 @@ def _init_ui(self):
11686
11787 self .show ()
11888
89+ def set_actions_triger (self , cleanup , initialise_scanner , camera_capture_alive ):
90+ self ._cleanup = cleanup
91+ self ._initialise_scanner = initialise_scanner
92+ self ._camera_capture_alive = camera_capture_alive
93+ self ._scan_button .click_action (self ._on_scan_action_clicked )
94+ self ._menu_bar .exit_action_triggered (self ._cleanup )
95+ self ._menu_bar .about_action_trigerred (self ._on_about_action_clicked )
96+ self ._menu_bar .optiones_action_triggered (self ._on_options_action_clicked )
97+ self ._record_table .cell_pressed_action_triggered (self ._to_run_on_table_clicked )
98+
11999 def _to_run_on_table_clicked (self ):
120100 self ._cleanup ()
121101 self ._scan_button .setStartLayout ()
122102
123103 def _on_about_action_clicked (self ):
124104 QtGui .QMessageBox .about (self , 'About' , "Version: " + self ._version )
125105
106+
126107 def _on_scan_action_clicked (self ):
127108 print ("MAIN: Scan menu clicked" )
128109 if not self ._camera_capture_alive ():
129110 self ._initialise_scanner ()
130- self ._restart_live_capture_from_side ()
131111 self ._scan_button .setDelayedStopLayout ()
132112 else :
133113 self ._cleanup ()
@@ -144,122 +124,20 @@ def closeEvent(self, event):
144124 self ._cleanup ()
145125 event .accept ()
146126
147- def _cleanup (self ):
148- if not self ._camera_capture_alive ():
149- return
150-
151- self ._camera_scanner .kill ()
152- self ._camera_scanner = None
153- self ._camera_switch = None
154-
155- def _initialise_scanner (self ):
156- self ._camera_scanner = CameraScanner (self ._result_queue , self ._view_queue , self ._message_queue , self ._config )
157- self ._camera_switch = CameraSwitch (self ._camera_scanner , self ._config .top_camera_timeout )
127+ def displayScanCompleteMessage (self ):
128+ self ._message_box .display (MessageFactory .scan_completed_message ())
158129
159- def _camera_capture_alive (self ):
160- return self ._camera_scanner is not None and self . _camera_switch is not None
130+ def displayScanErrorMessage (self , scanner_msg ):
131+ self ._message_box . display ( MessageFactory . from_scanner_message ( scanner_msg ))
161132
162- def _read_view_queue (self ):
163- if self ._view_queue .empty ():
164- return
165-
166- try :
167- image = self ._view_queue .get (False )
168- except queue .Empty :
169- return
133+ def displayScanTimeoutMessage (self ):
134+ self ._message_box .display (MessageFactory .scan_timeout_message ())
170135
136+ def displayPuckImage (self , image ):
171137 self ._image_frame .display_puck_image (image )
172138
173- def _read_message_queue (self ):
174- if self ._message_queue .empty ():
175- return
176-
177- try :
178- scanner_msg = self ._message_queue .get (False )
179- except queue .Empty :
180- return
181-
182- if self ._camera_switch .is_side ():
183- if not self ._msg_timer_is_running ():
184- # The result queue is read at a slower rate - use a timer to give it time to process a new barcode
185- self ._start_msg_timer ()
186- elif self ._has_msg_timer_timeout () and isinstance (scanner_msg , NoNewBarcodeMessage ):
187- self ._message_box .display (MessageFactory .scan_completed_message ())
188- elif isinstance (scanner_msg , ScanErrorMessage ):
189- self ._message_box .display (MessageFactory .from_scanner_message (scanner_msg ))
190- self ._reset_msg_timer ()
191- else :
192- self ._reset_msg_timer ()
193-
194- def _reset_msg_timer (self ):
195- self ._record_msg_timer = None
196-
197- def _start_msg_timer (self ):
198- self ._record_msg_timer = time .time ()
199-
200- def _msg_timer_is_running (self ):
201- return self ._record_msg_timer is not None
202-
203- def _has_msg_timer_timeout (self ):
204- timeout = 2 * RESULT_TIMER_PERIOD / 1000
205- return self ._msg_timer_is_running () and time .time () - self ._record_msg_timer > timeout
206-
207- def _read_result_queue (self ):
208- """ Called every second; read any new results from the scan results queue, store them and display them.
209- """
210- if not self ._camera_capture_alive ():
211- return
212-
213- if self ._camera_switch .is_side ():
214- self ._read_side_scan ()
215- else :
216- self ._read_top_scan ()
217-
218- def _read_side_scan (self ):
219- if self ._result_queue .empty ():
220- return
221-
222- # Get the result
223- plate , holder_image = self ._result_queue .get (False )
224- if not plate .is_full_valid ():
225- return
226-
227- # Barcode successfully read
228- Beeper .beep ()
229- print ("MAIN: puck barcode recorded" )
230- holder_barcode = plate .barcodes ()[0 ]
231- if not self ._record_table .is_latest_holder_barcode (holder_barcode ):
232- self ._latest_holder_barcode = holder_barcode
233- self ._latest_holder_image = holder_image
234- self ._restart_live_capture_from_top ()
235-
236- def _read_top_scan (self ):
237- if self ._result_queue .empty ():
238- if self ._camera_switch .is_top_scan_timeout ():
239- self ._message_box .display (MessageFactory .scan_timeout_message ())
240- print ("\n *** Scan timeout ***" )
241- self ._restart_live_capture_from_side ()
242- return
243-
244- # Get the result
245- plate , pins_image = self ._result_queue .get (False )
246-
247- # Add new record to the table - side is the _latest_holder_barcode read first, top is the plate
248- self ._record_table .add_record_frame (self ._latest_holder_barcode , plate , self ._latest_holder_image , pins_image )
249- if not plate .is_full_valid ():
250- return
251-
252- # Barcodes successfully read
253- Beeper .beep ()
254- print ("Scan Completed" , self ._camera_switch .get_scan_time ())
255- self ._restart_live_capture_from_side ()
256-
257- def _restart_live_capture_from_top (self ):
258- self ._camera_switch .restart_live_capture_from_top ()
259-
260- def _restart_live_capture_from_side (self ):
261- self ._reset_msg_timer ()
262- self ._camera_switch .restart_live_capture_from_side ()
263-
264-
139+ def addRecordFrame (self , latest_holder_barcode , plate , latest_holder_image , pins_image ):
140+ self ._record_table .add_record_frame (latest_holder_barcode , plate , latest_holder_image , pins_image )
265141
142+ def isLatestHolderBarcode (self , holder_barcode ):
143+ return self ._record_table .is_latest_holder_barcode (holder_barcode )
0 commit comments