Coverage for /home/pi/Software/model-railway-signalling/model_railway_signals/editor/configure_signal_tab2.py: 100%
267 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 17:29 +0100
« prev ^ index » next coverage.py v7.2.7, created at 2024-04-05 17:29 +0100
1#------------------------------------------------------------------------------------
2# Functions and sub Classes for the Edit Signal "Interlocking" Tab
3#
4# Makes the following external API calls to other editor modules:
5#########################################################################################################
6# Note that we need to use the 'objects.section_exists' function as the the library 'section_exists'
7# function will not work in edit mode as the Track Section library objects don't exist in edit mode
8# To be addressed in a future software update when the Track Sections functionality is re-factored
9#########################################################################################################
10# objects.section_exists(id) - To see if the track section exists (local) ##########################
11#
12# Makes the following external API calls to library modules:
13# signals_common.sig_exists(id) - To see if the instrument exists (local or remote)
14# points.point_exists(id) - To see if the point exists (local)
15# block_instruments.instrument_exists(id) - To see if the instrument exists (local or remote)
16# track_sections.section_exists(id) - To see if the track section exists ####################
17#
18# Inherits the following common editor base classes (from common):
19# common.check_box
20# common.int_item_id_entry_box
21# common.str_int_item_id_entry_box
22# common.signal_route_selections
23# common.point_interlocking_entry
24#
25#------------------------------------------------------------------------------------
27import tkinter as Tk
29from . import common
30from . import objects ##################################################################################
32from ..library import points
33from ..library import signals_common
34from ..library import block_instruments
35from ..library import track_sections
37#------------------------------------------------------------------------------------
38# Class for a route interlocking group (comprising 6 points, a signal and an instrument)
39# Uses the common point_interlocking_entry class for each point entry
40# Public class instance methods provided are:
41# "validate" - validate the current entry box values and return True/false
42# "set_route" - will set the route elements (points, sig_ahead and inst_ahead)
43# Note that we also need the current item id for validation of the sig_ahead
44# "get_route" - returns the last "valid" values (points, sig_ahead and inst_ahead)
45# "enable_route" - enables all points, sig_ahead and inst_ahead selections
46# "disable_route" - disables all points, sig_ahead and inst_ahead selections
47# "enable_sig_ahead" - enables the Sig ahead selections (if the route is enabled)
48# "disable_sig_ahead" - disables the Sig ahead selections
49# "enable_block_ahead" - enables the block ahead selections (if the route is enabled)
50# "disable_block_ahead" - disables the block ahead selections
51#------------------------------------------------------------------------------------
53class interlocking_route_group:
54 def __init__(self, parent_frame, label:str):
55 # These are the 'item exists' functions for validation
56 signal_exists_function = signals_common.sig_exists
57 instrument_exists_function = block_instruments.instrument_exists
58 point_exists_function = points.point_exists
59 # Create a frame for this UI element (always packed into the parent frame)
60 self.frame = Tk.Frame(parent_frame)
61 self.frame.pack()
62 # Create the lable and the point interlocking entry elements (these are
63 # packed LEFT in the frame by the parent class when created)
64 self.label = Tk.Label(self.frame, anchor='w', width=5, text=label)
65 self.label.pack(side = Tk.LEFT)
66 tool_tip = "Specify any points that need to be set and locked before the signal can be cleared for the route"
67 self.p1 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip)
68 self.p2 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip)
69 self.p3 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip)
70 self.p4 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip)
71 self.p5 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip)
72 self.p6 = common.point_interlocking_entry(self.frame, point_exists_function, tool_tip)
73 # Create the signal ahead and instrument ahead elements (always packed)
74 self.label1 = Tk.Label(self.frame, text=" Sig:")
75 self.label1.pack(side=Tk.LEFT)
76 self.sig = common.str_int_item_id_entry_box(self.frame, exists_function=signal_exists_function,
77 tool_tip = "Specify the next signal along the specified route - This "+
78 "can be a local signal ID or a remote signal ID (in the form 'Node-ID') "+
79 " which has been subscribed to via MQTT networking")
80 self.sig.pack(side=Tk.LEFT)
81 self.label2 = Tk.Label(self.frame, text=" Blk:")
82 self.label2.pack(side=Tk.LEFT)
83 self.block = common.int_item_id_entry_box(self.frame, exists_function=instrument_exists_function,
84 tool_tip="Specify the ID of the Block Instrument on the local schematic which "+
85 "controls access to the block section along the specified route")
86 self.block.pack(side=Tk.LEFT)
88 def validate(self):
89 # Validate everything - to highlight ALL validation errors in the UI
90 valid = True
91 if not self.p1.validate(): valid = False
92 if not self.p2.validate(): valid = False
93 if not self.p3.validate(): valid = False
94 if not self.p4.validate(): valid = False
95 if not self.p5.validate(): valid = False
96 if not self.p6.validate(): valid = False
97 if not self.sig.validate(): valid = False
98 if not self.block.validate(): valid = False
99 return(valid)
101 def enable_sig_ahead(self):
102 self.sig.enable1()
104 def disable_sig_ahead(self):
105 self.sig.disable1()
107 def enable_block_ahead(self):
108 self.block.enable1()
110 def disable_block_ahead(self):
111 self.block.disable1()
113 def enable_route(self):
114 self.p1.enable()
115 self.p2.enable()
116 self.p3.enable()
117 self.p4.enable()
118 self.p5.enable()
119 self.p6.enable()
120 self.sig.enable()
121 self.block.enable()
123 def disable_route(self):
124 self.p1.disable()
125 self.p2.disable()
126 self.p3.disable()
127 self.p4.disable()
128 self.p5.disable()
129 self.p6.disable()
130 self.sig.disable()
131 self.block.disable()
133 def set_route(self, interlocking_route:[[int,bool],str,int], item_id:int):
134 # A route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id]
135 # Each point element in the point list comprises [point_id, point_state]
136 # Note that the sig ID can be a local or remote Signal (so a string)
137 self.p1.set_value(interlocking_route[0][0])
138 self.p2.set_value(interlocking_route[0][1])
139 self.p3.set_value(interlocking_route[0][2])
140 self.p4.set_value(interlocking_route[0][3])
141 self.p5.set_value(interlocking_route[0][4])
142 self.p6.set_value(interlocking_route[0][5])
143 # Note we pass in the current signal_id for validation (to prevent selection)
144 self.sig.set_value(interlocking_route[1], item_id)
145 self.block.set_value(interlocking_route[2])
147 def get_route(self):
148 # A route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id]
149 # Each point element in the point list comprises [point_id, point_state]
150 # Note that the sig ID can be a local or remote Signal (so a string)
151 route = [ [ self.p1.get_value(),
152 self.p2.get_value(),
153 self.p3.get_value(),
154 self.p4.get_value(),
155 self.p5.get_value(),
156 self.p6.get_value() ],
157 self.sig.get_value(),
158 self.block.get_value() ]
159 return (route)
161#------------------------------------------------------------------------------------
162# Class for a route interlocking frame
163# Uses the base interlocking_route_group class from above
164# "validate" - validate the current entry box values and return True/false
165# "set_routes" - will set all route selections (points, sigs_ahead & insts_ahead)
166# Note that we also need the current item id for validation of the sig_ahead
167# "get_routes" - returns the last "valid" values (points, sigs_ahead & insts_ahead)
168# "enable_sig_ahead" - enables the Sig ahead selections (if the route is enabled)
169# "disable_sig_ahead" - disables the Sig ahead selections
170# "enable_block_ahead" - enables the block ahead selections (if the route is enabled)
171# "disable_block_ahead" - disables the block ahead selections
172#------------------------------------------------------------------------------------
174class interlocking_route_frame:
175 def __init__(self, parent_window, parent_object):
176 # Create a Label Frame for the UI element (packed by the creating function/class)
177 self.frame = Tk.LabelFrame(parent_window, text= "Signal routes and point interlocking")
178 # Create the route elements (sign, sub, dist) - these are packed in class instancees
179 self.main = interlocking_route_group(self.frame, "Main")
180 self.lh1 = interlocking_route_group(self.frame, "LH1")
181 self.lh2 = interlocking_route_group(self.frame, "LH2")
182 self.rh1 = interlocking_route_group(self.frame, "RH1")
183 self.rh2 = interlocking_route_group(self.frame, "RH2")
185 def validate(self):
186 # Validate everything - to highlight ALL validation errors in the UI
187 valid = True
188 if not self.main.validate(): valid = False
189 if not self.lh1.validate(): valid = False
190 if not self.lh2.validate(): valid = False
191 if not self.rh1.validate(): valid = False
192 if not self.rh2.validate(): valid = False
193 return(valid)
195 def set_routes(self, interlocking_frame:[[[[int,bool],],str,int]], item_id:int):
196 # An interlocking frame comprises a list of routes: [main, lh1, lh2, rh1, rh2]
197 # Each route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id]
198 # Each point element in the point list comprises [point_id, point_state]
199 # Note that the sig ID can be a local or remote Signal (so a string)
200 # Note also we pass in the current signal_id for validation (to prevent selection)
201 self.main.set_route(interlocking_frame[0], item_id)
202 self.lh1.set_route(interlocking_frame[1], item_id)
203 self.lh2.set_route(interlocking_frame[2], item_id)
204 self.rh1.set_route(interlocking_frame[3], item_id)
205 self.rh2.set_route(interlocking_frame[4], item_id)
207 def get_routes(self):
208 # An interlocking frame comprises a list of routes: [main, lh1, lh2, rh1, rh2]
209 # Each route comprises: [[p1, p2, p3, p4, p5, p6, p7], sig_id, instrument_id]
210 # Each point element in the point list comprises [point_id, point_state]
211 # Note that the sig ID can be a local or remote Signal (so a string)
212 return ( [ self.main.get_route(),
213 self.lh1.get_route(),
214 self.lh2.get_route(),
215 self.rh1.get_route(),
216 self.rh2.get_route() ] )
218 def enable_sig_ahead(self):
219 self.main.enable_sig_ahead()
220 self.lh1.enable_sig_ahead()
221 self.lh2.enable_sig_ahead()
222 self.rh1.enable_sig_ahead()
223 self.rh2.enable_sig_ahead()
225 def disable_sig_ahead(self):
226 self.main.disable_sig_ahead()
227 self.lh1.disable_sig_ahead()
228 self.lh2.disable_sig_ahead()
229 self.rh1.disable_sig_ahead()
230 self.rh2.disable_sig_ahead()
232 def enable_block_ahead(self):
233 self.main.enable_block_ahead()
234 self.lh1.enable_block_ahead()
235 self.lh2.enable_block_ahead()
236 self.rh1.enable_block_ahead()
237 self.rh2.enable_block_ahead()
239 def disable_block_ahead(self):
240 self.main.disable_block_ahead()
241 self.lh1.disable_block_ahead()
242 self.lh2.disable_block_ahead()
243 self.rh1.disable_block_ahead()
244 self.rh2.disable_block_ahead()
246#------------------------------------------------------------------------------------
247# Class for a conflicting signal UI Element (for interlocking)
248# uses multiple instances of the common signal_route_selection_element
249# Public class instance methods provided by this class are:
250# "set_values" - Populates the list of interlocked signals and their routes
251# Note that we also need the current item id for validation
252# "get_values" - Returns the list of interlocked signals and their routes
253# "enable_route" - Enables/loads all selections for the route
254# "disable_route" - Disables/blanks all selections for the route
255# "validate" - Validates all Entry boxes (Signals exist and not current ID)
256#------------------------------------------------------------------------------------
258class conflicting_signals_element():
259 def __init__(self, parent_frame, parent_object, label:str):
260 # Theis is the functions used to validate that the entered signal ID exists
261 exists_function = signals_common.sig_exists
262 # Create the Label Frame for the UI element (packed/unpacked on enable/disable)
263 self.frame = Tk.LabelFrame(parent_frame, text=label+" - interlocking with conflicting signals")
264 self.frame.pack(padx=2, pady=2, fill='x')
265 # create two frames - each frame will hold two conflicting signals
266 self.subframe1 = Tk.Frame(self.frame)
267 self.subframe1.pack()
268 self.subframe2 = Tk.Frame(self.frame)
269 self.subframe2.pack()
270 tool_tip = "Specify any signals/routes that would conflict with this signal route"
271 self.sig1 = common.signal_route_selections(self.subframe1, read_only=False,
272 tool_tip = tool_tip,exists_function=exists_function)
273 self.sig1.frame.pack(side=Tk.LEFT, padx=5)
274 self.sig2 = common.signal_route_selections(self.subframe1, read_only=False,
275 tool_tip = tool_tip, exists_function=exists_function)
276 self.sig2.frame.pack(side=Tk.LEFT, padx=5)
277 self.sig3 = common.signal_route_selections(self.subframe2, read_only=False,
278 tool_tip = tool_tip, exists_function=exists_function)
279 self.sig3.frame.pack(side=Tk.LEFT, padx=5)
280 self.sig4 = common.signal_route_selections(self.subframe2, read_only=False,
281 tool_tip = tool_tip, exists_function=exists_function)
282 self.sig4.frame.pack(side=Tk.LEFT, padx=5)
284 def validate(self):
285 # Validate everything - to highlight ALL validation errors in the UI
286 valid = True
287 if not self.sig1.validate(): valid = False
288 if not self.sig2.validate(): valid = False
289 if not self.sig3.validate(): valid = False
290 if not self.sig4.validate(): valid = False
291 return(valid)
293 def enable_route(self):
294 self.sig1.enable()
295 self.sig2.enable()
296 self.sig3.enable()
297 self.sig4.enable()
299 def disable_route(self):
300 self.sig1.disable()
301 self.sig2.disable()
302 self.sig3.disable()
303 self.sig4.disable()
305 def set_values(self, sig_route:[[int,[bool,bool,bool,bool,bool]],], item_id):
306 # each sig_route comprises [sig1, sig2, sig3, sig4]
307 # each signal comprises [sig_id, [main, lh1, lh2, rh1, rh2]]
308 # Where each route element is a boolean value (True or False)
309 self.sig1.set_values(sig_route[0], item_id)
310 self.sig2.set_values(sig_route[1], item_id)
311 self.sig3.set_values(sig_route[2], item_id)
312 self.sig4.set_values(sig_route[3], item_id)
314 def get_values(self):
315 # each sig_route comprises [sig1, sig2, sig3, sig4]
316 # each signal comprises [sig_id, [main, lh1, lh2, rh1, rh2]]
317 # Where each route element is a boolean value (True or False)
318 return ( [self.sig1.get_values(),
319 self.sig2.get_values(),
320 self.sig3.get_values(),
321 self.sig4.get_values()] )
323#------------------------------------------------------------------------------------
324# Class for a conflicting signal frame UI Element (for interlocking)
325# uses multiple instances of the common signal_route_selection_element
326# Public class instance methods provided by this class are:
327# "set_values" - Populates the table of interlocked signal routes
328# Note that we also need the current item id for validation
329# "get_values" - Returns the table of interlocked signal routes
330# "validate" - Validates all entries (Signals exist and not the current ID)
331#------------------------------------------------------------------------------------
333class conflicting_signals_frame():
334 def __init__(self, parent_frame, parent_object):
335 # Create the Label Frame for the UI element (packed by the creating function/class)
336 self.frame = Tk.LabelFrame(parent_frame, text="Conflicting signals not locked by the above point selections")
337 self.main = conflicting_signals_element(self.frame, parent_object, "MAIN Route")
338 self.lh1 = conflicting_signals_element(self.frame, parent_object, "LH1 Route")
339 self.lh2 = conflicting_signals_element(self.frame, parent_object, "LH2 Route")
340 self.rh1 = conflicting_signals_element(self.frame, parent_object, "RH1 Route")
341 self.rh2 = conflicting_signals_element(self.frame, parent_object, "RH2 Route")
343 def validate(self):
344 # Validate everything - to highlight ALL validation errors in the UI
345 valid = True
346 if not self.main.validate(): valid = False
347 if not self.lh1.validate(): valid = False
348 if not self.lh2.validate(): valid = False
349 if not self.rh1.validate(): valid = False
350 if not self.rh2.validate(): valid = False
351 return(valid)
353 def set_values(self, sig_interlocking_routes:[[[int,[bool,bool,bool,bool,bool]],],], item_id:int):
354 # sig_interlocking_routes comprises a list of sig_routes [main,lh1,lh2,rh1,rh2]
355 # each sig_route comprises a list of interlocked signals [sig1, sig2, sig3, sig4]
356 # each interlocked signal entry comprises [sig_id, [main, lh1, lh2, rh1, rh2]]
357 # sig_id is the interlocked signal and the interlocked routes are True/False
358 self.main.set_values(sig_interlocking_routes[0], item_id)
359 self.lh1.set_values(sig_interlocking_routes[1], item_id)
360 self.lh2.set_values(sig_interlocking_routes[2], item_id)
361 self.rh1.set_values(sig_interlocking_routes[3], item_id)
362 self.rh2.set_values(sig_interlocking_routes[4], item_id)
364 def get_values(self):
365 # sig_interlocking_routes comprises a list of sig_routes [main,lh1,lh2,rh1,rh2]
366 # each sig_route comprises a list of interlocked signals [sig1, sig2, sig3, sig4]
367 # each interlocked signal entry comprises [sig_id, [main, lh1, lh2, rh1, rh2]]
368 # sig_id is the interlocked signal and the interlocked routes are True/False
369 return ( [self.main.get_values(),
370 self.lh1.get_values(),
371 self.lh2.get_values(),
372 self.rh1.get_values(),
373 self.rh2.get_values() ] )
375#------------------------------------------------------------------------------------
376# Class for a interlocked track sections group UI Element (for interlocking)
377# Provides a label frame containing 3 track section entry boxes for a signal route
378# Public class instance methods provided by this class are:
379# "set_route" - Populates the list of interlocked track sections for the group
380# "get_route" - Returns the list of interlocked track sections for the route
381# "enable_route" - Enables/loads all selections for the route
382# "disable_route" - Disables/blanks all selections for the route
383# "validate" - Validates all Entries (Track Section exists on schematic)
384#------------------------------------------------------------------------------------
386class interlocked_sections_group:
387 def __init__(self, parent_frame, label:str):
388 self.frame = Tk.LabelFrame(parent_frame, text=label)
389 self.frame.pack(side=Tk.LEFT, padx=8, pady=2)
390 tool_tip = "Specify any track sections along the route that will lock this signal when occupied by another train"
391 #########################################################################################################
392 # Note that we need to use the 'objects.section_exists' function as the the library 'section_exists'
393 # function will not work in edit mode as the Track Section library objects don't exist in edit mode
394 # To be addressed in a future software update when the Track Sections functionality is re-factored
395 #########################################################################################################
396 self.t1 = common.int_item_id_entry_box(self.frame, exists_function=objects.section_exists, tool_tip=tool_tip)
397 self.t1.pack(side = Tk.LEFT)
398 self.t2 = common.int_item_id_entry_box(self.frame, exists_function=objects.section_exists, tool_tip=tool_tip)
399 self.t2.pack(side = Tk.LEFT)
400 self.t3 = common.int_item_id_entry_box(self.frame, exists_function=objects.section_exists, tool_tip=tool_tip)
401 self.t3.pack(side = Tk.LEFT)
403 def validate(self):
404 # Validate everything - to highlight ALL validation failures in the UI
405 valid = True
406 if not self.t1.validate(): valid = False
407 if not self.t2.validate(): valid = False
408 if not self.t3.validate(): valid = False
409 return(valid)
411 def enable_route(self):
412 self.t1.enable()
413 self.t2.enable()
414 self.t3.enable()
416 def disable_route(self):
417 self.t1.disable()
418 self.t2.disable()
419 self.t3.disable()
421 def set_route(self, interlocked_route:[int,int,int]):
422 # An interlocked_route comprises: [t1,t2,t3] Where each element is
423 # the ID of a track section the signal is to be interlocked with
424 self.t1.set_value(interlocked_route[0])
425 self.t2.set_value(interlocked_route[1])
426 self.t3.set_value(interlocked_route[2])
428 def get_route(self):
429 # An interlocked_route comprises: [t1,t2,t3] Where each element is
430 # the ID of a track section the signal is to be interlocked with
431 interlocked_route = [ self.t1.get_value(), self.t2.get_value(), self.t3.get_value() ]
432 return(interlocked_route)
434#------------------------------------------------------------------------------------
435# Class for a interlocked track sections frame UI Element
436# uses multiple instances of the interlocked_sections_group class
437# Public class instance methods provided by this class are:
438# "set_routes" - Populates the list of interlocked track sections for each route
439# "get_routes" - Returns the list of interlocked track sections for each route
440# "validate" - Validates all Entries(Track sections exist on the schematic)
441#------------------------------------------------------------------------------------
443class interlocked_sections_frame():
444 def __init__(self, parent_frame):
445 # Create the Label Frame for the UI element (packed by the creating function/class)
446 self.frame = Tk.LabelFrame(parent_frame, text="Interlock with occupied track sections")
447 # Create a subframe to pack everything into so the contents are centered
448 self.subframe = Tk.Frame(self.frame)
449 self.subframe.pack()
450 # Create the Interlocked group UI elements (one for each signal route)
451 self.main = interlocked_sections_group(self.subframe, "Main")
452 self.lh1 = interlocked_sections_group(self.subframe, "LH1")
453 self.lh2 = interlocked_sections_group(self.subframe, "LH2")
454 self.rh1 = interlocked_sections_group(self.subframe, "RH1")
455 self.rh2 = interlocked_sections_group(self.subframe, "RH2")
457 def validate(self):
458 # Validate everything - to highlight ALL validation failures in the UI
459 valid = True
460 if not self.main.validate(): valid = False
461 if not self.lh1.validate(): valid = False
462 if not self.lh2.validate(): valid = False
463 if not self.rh1.validate(): valid = False
464 if not self.rh2.validate(): valid = False
465 return(valid)
467 def set_routes(self, interlocked_sections):
468 # interlocked_sections comprises a list of routes: [MAIN, LH1, LH2, RH1, RH2]
469 # Each route element contains a list of interlocked sections for that route [t1,t2,t3]
470 # Each entry is the ID of a track section the signal is to be interlocked with
471 self.main.set_route(interlocked_sections[0])
472 self.lh1.set_route(interlocked_sections[1])
473 self.lh2.set_route(interlocked_sections[2])
474 self.rh1.set_route(interlocked_sections[3])
475 self.rh2.set_route(interlocked_sections[4])
477 def get_routes(self):
478 # Returned list comprises a list of routes: [MAIN, LH1, LH2, RH1, RH2]
479 # Each route element contains a list of interlocked sections for that route [t1,t2,t3]
480 # Each entry is the ID of a track section the signal is to be interlocked with
481 return ( [self.main.get_route(),
482 self.lh1.get_route(),
483 self.lh2.get_route(),
484 self.rh1.get_route(),
485 self.rh2.get_route() ] )
487#------------------------------------------------------------------------------------
488# Class for the Distant 'interlock with home signals ahead" ui element
489# Inherits from common.check_box class (get_value/set_value/enable/disable)
490# Only enabled if the signal type is a distant signal (semaphore or colour light)
491#------------------------------------------------------------------------------------
493class interlock_with_signals_ahead(common.check_box):
494 def __init__(self, parent_frame):
495 # Create the Label Frame for the UI element (packed by the creating function/class)
496 self.frame = Tk.LabelFrame(parent_frame, text="Distant signal interlocking")
497 super().__init__(self.frame, label="Interlock distant with all home signals ahead",
498 tool_tip="Select to lock the distant signal at CAUTION if any home signals "+
499 "on the route ahead are at DANGER (if the distant signal is CLEAR it "+
500 "will remain unlocked so it can be returned to CAUTION at any time)")
501 self.pack()
503#------------------------------------------------------------------------------------
504# Top level Class for the Signal Interlocking Tab
505#------------------------------------------------------------------------------------
507class signal_interlocking_tab:
508 def __init__(self, parent_tab, parent_object):
509 self.interlocking = interlocking_route_frame(parent_tab, parent_object)
510 self.interlocking.frame.pack(padx=2, pady=2, fill='x')
511 self.interlocked_sections = interlocked_sections_frame(parent_tab)
512 self.interlocked_sections.frame.pack(padx=2, pady=2, fill='x')
513 self.conflicting_sigs = conflicting_signals_frame(parent_tab, parent_object)
514 self.conflicting_sigs.frame.pack(padx=2, pady=2, fill='x')
515 self.interlock_ahead = interlock_with_signals_ahead(parent_tab)
516 self.interlock_ahead.frame.pack(padx=2, pady=2, fill='x')
518#############################################################################################