source: src/mlx/gui/delaycodes.py@ 1152:637b6594838d

python3
Last change on this file since 1152:637b6594838d was 1146:0321756c76fe, checked in by István Váradi <ivaradi@…>, 7 months ago

Support for delay codes that require explanations (re #386)

File size: 14.4 KB
Line 
1# Module to handle the GUI aspects of the table of the delay codes
2
3#------------------------------------------------------------------------------
4
5from .dcdata import CAPTION, DELAYCODE, getTable
6
7from mlx.gui.common import *
8
9import mlx.const as const
10
11#------------------------------------------------------------------------------
12
13class Viewport(Gtk.Viewport):
14 """Viewport implementation that alleviates the problem with improper
15 resizing by the VBox."""
16 def __init__(self):
17 """Construct the viewport."""
18 Gtk.Viewport.__init__(self)
19 self._recursive = False
20 self._vboxHeight = None
21
22 def setVBOXHeight(self, vboxHeight):
23 """Set the height of the VBox which will be used to calculate the
24 viewport's height."""
25 self._vboxHeight = vboxHeight
26
27 def do_size_allocate(self, allocation):
28 """Called when the viewport's size is allocated.
29
30 The height in the allocation object is modified so that it is only
31 so high to fit into the VBox."""
32 if self._vboxHeight is not None:
33 allocation.y += 1
34 allocation.height = self._vboxHeight - allocation.y
35 self._vboxHeight = None
36 Gtk.Viewport.do_size_allocate(self, allocation)
37
38class DelayCodeTableBase(Gtk.VBox, Gtk.Scrollable):
39 """PyGObject-specific base class for the delay code table."""
40 __gproperties__ = {
41 "vscroll-policy" : ( Gtk.ScrollablePolicy,
42 "vscroll-policy",
43 "The vertical scrolling policy",
44 Gtk.ScrollablePolicy.MINIMUM,
45 GObject.PARAM_READWRITE ),
46 "vadjustment" : ( Gtk.Adjustment,
47 "vadjustment",
48 "The vertical adjustment",
49 GObject.PARAM_READWRITE ),
50 "hscroll-policy" : ( Gtk.ScrollablePolicy,
51 "hscroll-policy",
52 "The horizontal scrolling policy",
53 Gtk.ScrollablePolicy.MINIMUM,
54 GObject.PARAM_READWRITE ),
55 "hadjustment" : ( Gtk.Adjustment,
56 "hadjustment",
57 "The horizontal adjustment",
58 GObject.PARAM_READWRITE ) }
59
60
61 @staticmethod
62 def _createViewport():
63 """Create an instance of the viewport class used by this base class."""
64 return Viewport()
65
66 def __init__(self):
67 """Construct the delay code table."""
68 super(DelayCodeTableBase, self).__init__()
69
70 def do_size_allocate(self, allocation):
71 """Allocate the size for the table and its children.
72
73 This sets up the VBox height in the viewport and then calls the
74 do_size_allocate() function of VBox()."""
75 self._viewport.setVBOXHeight(allocation.height)
76 Gtk.VBox.do_size_allocate(self, allocation)
77 self.allocate_column_sizes(allocation)
78
79 def do_get_property(self, prop):
80 """Get the value of one of the properties defined above.
81
82 The request is forwarded to the viewport."""
83 if prop.name=="vscroll-policy":
84 return self._viewport.get_vscroll_policy()
85 elif prop.name=="hscroll-policy":
86 return self._viewport.get_hscroll_policy()
87 elif prop.name=="vadjustment":
88 return self._viewport.get_vadjustment()
89 elif prop.name=="hadjustment":
90 return self._viewport.get_hadjustment()
91 else:
92 raise AttributeError("mlx.gui.delaycodes.DelayCodeTableBase: property %s is not handled in do_get_property" %
93 (prop.name,))
94
95 def do_set_property(self, prop, value):
96 """Set the value of the adjustment properties defined above.
97
98 The adjustments are forwarded to the viewport."""
99 if prop.name=="vadjustment":
100 self._viewport.set_vadjustment(value)
101 elif prop.name=="hadjustment":
102 self._viewport.set_hadjustment(value)
103 self._treeView.set_hadjustment(value)
104 else:
105 raise AttributeError("mlx.gui.delaycodes.DelayCodeTableBase: property %s is not handled in do_set_property" %
106 (prop.name,))
107
108 def setStyle(self):
109 """Set the style of the event box from the treeview."""
110
111class Alignment(Gtk.Alignment):
112 """An alignment that remembers the width it was given."""
113 def __init__(self, xalign = 0.0, yalign=0.0,
114 xscale = 0.0, yscale = 0.0 ):
115 """Construct the alignment."""
116 super(Alignment, self).__init__(xalign = xalign, yalign = yalign,
117 xscale = xscale, yscale = yscale)
118 self.allocatedWidth = 0
119
120 def do_size_allocate(self, allocation):
121 """Called with the new size allocation."""
122 self.allocatedWidth = allocation.width
123 Gtk.Alignment.do_size_allocate(self, allocation)
124
125class TreeView(Gtk.TreeView):
126 def do_size_allocate(self, allocation):
127 allocation.height += 1
128 Gtk.TreeView.do_size_allocate(self, allocation)
129
130#------------------------------------------------------------------------------
131
132class CheckButton(Gtk.CheckButton):
133 """A check button that contains a reference to a row in the delay code
134 data table."""
135 def __init__(self, delayCodeRow):
136 """Construct the check button."""
137 super(CheckButton, self).__init__()
138 self.delayCodeRow = delayCodeRow
139
140#------------------------------------------------------------------------------
141
142# CAPTION = 1
143
144# DELAYCODE = 2
145
146# _data1 = ( lambda row: row[0].strip(),
147# ["Num", "Code", "Title", "Description"],
148# [ (CAPTION, "Others"),
149# (DELAYCODE, (" 6", "OA ", "NO GATES/STAND AVAILABLE",
150# "Due to own airline activity")),
151# (DELAYCODE, ("9", "SG", "SCHEDULED GROUND TIME",
152# "Planned turnaround time less than declared minimum")),
153# (CAPTION, "Passenger and baggage"),
154# (DELAYCODE, ("11", "PD", "LATE CHECK-IN",
155# "Check-in reopened for late passengers")),
156# (DELAYCODE, ("12", "PL", "LATE CHECK-IN",
157# "Check-in not completed by flight closure time")),
158# (DELAYCODE, ("13", "PE", "CHECK-IN ERROR",
159# "Error with passenger or baggage details")) ] )
160
161# _data2 = ( lambda row: row[0].strip(),
162# ["MA", "IATA", "Description"],
163# [ (CAPTION, "Passenger and baggage"),
164# (DELAYCODE, (" 012", "01 ",
165# "Late shipping of parts and/or materials")),
166# (DELAYCODE, (" 111", "11",
167# "Check-in reopened for late passengers")),
168# (DELAYCODE, (" 121", "12",
169# "Check-in not completed by flight closure time")),
170# (DELAYCODE, (" 132", "13",
171# "Error with passenger or baggage details"))
172# ])
173
174#------------------------------------------------------------------------------
175
176class DelayCodeTable(DelayCodeTableBase):
177 """The delay code table."""
178 def __init__(self, info):
179 """Construct the delay code table."""
180 super(DelayCodeTable, self).__init__()
181
182 self._info = info
183
184 self._delayCodeData = None
185
186 self._treeView = TreeView(Gtk.ListStore(str, str))
187 self._treeView.set_rules_hint(True)
188
189 self.pack_start(self._treeView, False, False, 0)
190
191 self._alignments = []
192 self._checkButtons = []
193 self._codesToExplain = []
194
195 self._eventBox = Gtk.EventBox()
196
197 self._table = None
198
199 self._viewport = self._createViewport()
200 self._viewport.add(self._eventBox)
201 self._viewport.set_shadow_type(Gtk.ShadowType.NONE)
202
203 self.pack_start(self._viewport, True, True, 0)
204
205 self._previousWidth = 0
206
207 @property
208 def _delayCodeRows(self):
209 """Get a list of the row indexes in the delay code data table of
210 the delay codes that are enabled."""
211 rows = []
212
213 for checkButton in self._checkButtons:
214 if checkButton.get_active():
215 rows.append(checkButton.delayCodeRow)
216
217 return rows
218
219 @property
220 def delayCodes(self):
221 """Get a list of the delay codes checked by the user."""
222 codes = []
223
224 if self._delayCodeData is not None:
225 codeExtractor = self._delayCodeData[0][1]
226 for row in self._delayCodeRows:
227 codes.append(codeExtractor(row))
228
229 return codes
230
231 @property
232 def hasDelayCode(self):
233 """Determine if there is at least one delay code selected."""
234 if self._delayCodeData is not None:
235 for checkButton in self._checkButtons:
236 if checkButton.get_active():
237 return True
238
239 return False
240
241 def allocate_column_sizes(self, allocation):
242 """Allocate the column sizes."""
243 if allocation.width!=self._previousWidth:
244 self._previousWidth = allocation.width
245 index = 0
246 lastIndex = len(self._alignments) - 1
247 for alignment in self._alignments:
248 column = self._treeView.get_column(index)
249 width = alignment.allocatedWidth
250 width += 8 if (index==0 or index==lastIndex) else 16
251 column.set_fixed_width(width)
252 index += 1
253
254 def setType(self, aircraftType):
255 """Setup the delay code table according to the given aircraft type."""
256 self._delayCodeData = data = getTable(aircraftType)
257 if data is None:
258 return
259
260 columns = self._treeView.get_columns()
261 for column in columns:
262 self._treeView.remove_column(column)
263
264 (_extractor, headers, rows) = data
265 numColumns = len(headers) + 1
266 numRows = len(rows)
267
268 column = Gtk.TreeViewColumn("", Gtk.CellRendererText())
269 column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
270 self._treeView.append_column(column)
271
272 for header in headers:
273 column = Gtk.TreeViewColumn(header, Gtk.CellRendererText())
274 column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
275 self._treeView.append_column(column)
276
277 self._table = Gtk.Table(numRows, numColumns)
278 self._table.set_homogeneous(False)
279 self._table.set_col_spacings(16)
280 self._table.set_row_spacings(4)
281 self._eventBox.add(self._table)
282
283 self._alignments = []
284 self._checkButtons = []
285
286 firstDelayCodeRow = True
287 for i in range(0, numRows):
288 (type, elements) = rows[i]
289 if type==CAPTION:
290 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
291 xscale = 1.0)
292 label = Gtk.Label("<b>" + elements + "</b>")
293 label.set_use_markup(True)
294 label.set_alignment(0.0, 0.5)
295 alignment.add(label)
296 self._table.attach(alignment, 1, numColumns, i, i+1,
297 yoptions = Gtk.AttachOptions.FILL)
298 self._table.set_row_spacing(i, 8)
299 elif type==DELAYCODE:
300 checkButton = CheckButton(elements)
301 checkButton.connect("toggled", self._delayCodesChanged)
302 self._checkButtons.append(checkButton)
303 alignment = Alignment(xalign = 0.5, yalign = 0.5, xscale = 1.0)
304 alignment.add(checkButton)
305 self._table.attach(alignment, 0, 1, i, i+1,
306 xoptions = Gtk.AttachOptions.FILL,
307 yoptions = Gtk.AttachOptions.FILL)
308 if firstDelayCodeRow:
309 self._alignments.append(alignment)
310
311 for j in range(0, numColumns-1):
312 label = Gtk.Label(elements[j])
313 label.set_alignment(0.0, 0.5)
314 alignment = Alignment(xalign = 0.5, yalign = 0.5,
315 xscale = 1.0)
316 alignment.add(label)
317 xoptions = Gtk.AttachOptions.FILL
318 if j==(numColumns-2): xoptions |= Gtk.AttachOptions.EXPAND
319 self._table.attach(alignment, j+1, j+2, i, i+1,
320 xoptions = xoptions,
321 yoptions = Gtk.AttachOptions.FILL)
322 if firstDelayCodeRow:
323 self._alignments.append(alignment)
324 firstDelayCodeRow = False
325
326 self._previousWidth = 0
327 self.show_all()
328
329 def reset(self):
330 """Reset the delay code table."""
331 columns = self._treeView.get_columns()
332 for column in columns:
333 self._treeView.remove_column(column)
334 if self._table is not None:
335 self._eventBox.remove(self._table)
336 self._table = None
337 self.show_all()
338
339 def activateCode(self, code):
340 """Check the checkbox for the given code."""
341 index = 0
342 for (type, data) in self._delayCodeData[2]:
343 if type==DELAYCODE:
344 if code==data[0].strip():
345 self._checkButtons[index].set_active(True)
346 break
347 index += 1
348
349 def _delayCodesChanged(self, button):
350 """Called when one of the delay codes have changed."""
351 delayCodeRows = self._delayCodeRows
352 numDelayCodes = len(delayCodeRows)
353 if numDelayCodes>=4:
354 for checkButton in self._checkButtons:
355 if not checkButton.get_active():
356 checkButton.set_sensitive(False)
357 else:
358 for checkButton in self._checkButtons:
359 checkButton.set_sensitive(True)
360
361 codeExtractor = self._delayCodeData[0][0]
362 isExplanationRequired = self._delayCodeData[0][2]
363 codesToExplain = []
364 for row in delayCodeRows:
365 if isExplanationRequired(row):
366 code = codeExtractor(row)
367 codesToExplain.append(code)
368 if code not in self._codesToExplain:
369 self._info.addFault("dc_" + code,
370 xstr("info_delay_explain") % (code,))
371
372 for code in self._codesToExplain:
373 if code not in codesToExplain:
374 self._info.clearFault("dc_" + code)
375 self._codesToExplain = codesToExplain
376
377 self._info.delayCodesChanged()
378
379#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.