source: src/mlx/gui/delaycodes.py

python3
Last change on this file was 1146:0321756c76fe, checked in by István Váradi <ivaradi@…>, 13 days ago

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

File size: 14.4 KB
RevLine 
[433]1# Module to handle the GUI aspects of the table of the delay codes
2
3#------------------------------------------------------------------------------
4
[919]5from .dcdata import CAPTION, DELAYCODE, getTable
[439]6
[433]7from mlx.gui.common import *
8
[436]9import mlx.const as const
10
[433]11#------------------------------------------------------------------------------
12
[996]13class Viewport(Gtk.Viewport):
[994]14 """Viewport implementation that alleviates the problem with improper
15 resizing by the VBox."""
16 def __init__(self):
17 """Construct the viewport."""
[996]18 Gtk.Viewport.__init__(self)
[994]19 self._recursive = False
20 self._vboxHeight = None
[433]21
[994]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
[433]26
[994]27 def do_size_allocate(self, allocation):
28 """Called when the viewport's size is allocated.
[433]29
[994]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
[996]36 Gtk.Viewport.do_size_allocate(self, allocation)
[433]37
[996]38class DelayCodeTableBase(Gtk.VBox, Gtk.Scrollable):
[994]39 """PyGObject-specific base class for the delay code table."""
40 __gproperties__ = {
[996]41 "vscroll-policy" : ( Gtk.ScrollablePolicy,
[994]42 "vscroll-policy",
43 "The vertical scrolling policy",
[996]44 Gtk.ScrollablePolicy.MINIMUM,
[995]45 GObject.PARAM_READWRITE ),
[996]46 "vadjustment" : ( Gtk.Adjustment,
[994]47 "vadjustment",
48 "The vertical adjustment",
[995]49 GObject.PARAM_READWRITE ),
[996]50 "hscroll-policy" : ( Gtk.ScrollablePolicy,
[994]51 "hscroll-policy",
52 "The horizontal scrolling policy",
[996]53 Gtk.ScrollablePolicy.MINIMUM,
[995]54 GObject.PARAM_READWRITE ),
[996]55 "hadjustment" : ( Gtk.Adjustment,
[994]56 "hadjustment",
57 "The horizontal adjustment",
[995]58 GObject.PARAM_READWRITE ) }
[433]59
60
[994]61 @staticmethod
62 def _createViewport():
63 """Create an instance of the viewport class used by this base class."""
64 return Viewport()
[433]65
[994]66 def __init__(self):
67 """Construct the delay code table."""
68 super(DelayCodeTableBase, self).__init__()
[433]69
[994]70 def do_size_allocate(self, allocation):
71 """Allocate the size for the table and its children.
[433]72
[994]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)
[996]76 Gtk.VBox.do_size_allocate(self, allocation)
[994]77 self.allocate_column_sizes(allocation)
[433]78
[994]79 def do_get_property(self, prop):
80 """Get the value of one of the properties defined above.
[433]81
[994]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,))
[435]94
[994]95 def do_set_property(self, prop, value):
96 """Set the value of the adjustment properties defined above.
[433]97
[994]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,))
[433]107
[994]108 def setStyle(self):
109 """Set the style of the event box from the treeview."""
[433]110
[996]111class Alignment(Gtk.Alignment):
[994]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
[433]119
[994]120 def do_size_allocate(self, allocation):
121 """Called with the new size allocation."""
122 self.allocatedWidth = allocation.width
[996]123 Gtk.Alignment.do_size_allocate(self, allocation)
[435]124
[996]125class TreeView(Gtk.TreeView):
[994]126 def do_size_allocate(self, allocation):
127 allocation.height += 1
[996]128 Gtk.TreeView.do_size_allocate(self, allocation)
[435]129
130#------------------------------------------------------------------------------
131
[996]132class CheckButton(Gtk.CheckButton):
[437]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
[439]142# CAPTION = 1
[435]143
[439]144# DELAYCODE = 2
[435]145
[439]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")) ] )
[436]160
[439]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# ])
[435]173
[433]174#------------------------------------------------------------------------------
175
176class DelayCodeTable(DelayCodeTableBase):
177 """The delay code table."""
[555]178 def __init__(self, info):
[433]179 """Construct the delay code table."""
180 super(DelayCodeTable, self).__init__()
181
[555]182 self._info = info
183
[437]184 self._delayCodeData = None
185
[996]186 self._treeView = TreeView(Gtk.ListStore(str, str))
[435]187 self._treeView.set_rules_hint(True)
188
[436]189 self.pack_start(self._treeView, False, False, 0)
190
191 self._alignments = []
[437]192 self._checkButtons = []
[1146]193 self._codesToExplain = []
[436]194
[996]195 self._eventBox = Gtk.EventBox()
[436]196
197 self._table = None
198
199 self._viewport = self._createViewport()
200 self._viewport.add(self._eventBox)
[999]201 self._viewport.set_shadow_type(Gtk.ShadowType.NONE)
[436]202
203 self.pack_start(self._viewport, True, True, 0)
204
205 self._previousWidth = 0
206
[437]207 @property
[1146]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
[437]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:
[1146]225 codeExtractor = self._delayCodeData[0][1]
226 for row in self._delayCodeRows:
227 codes.append(codeExtractor(row))
[437]228
229 return codes
230
[555]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
[436]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
[438]246 lastIndex = len(self._alignments) - 1
[436]247 for alignment in self._alignments:
248 column = self._treeView.get_column(index)
[438]249 width = alignment.allocatedWidth
250 width += 8 if (index==0 or index==lastIndex) else 16
[436]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."""
[439]256 self._delayCodeData = data = getTable(aircraftType)
257 if data is None:
258 return
[437]259
[436]260 columns = self._treeView.get_columns()
261 for column in columns:
262 self._treeView.remove_column(column)
263
[437]264 (_extractor, headers, rows) = data
[436]265 numColumns = len(headers) + 1
266 numRows = len(rows)
267
[996]268 column = Gtk.TreeViewColumn("", Gtk.CellRendererText())
[999]269 column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
[433]270 self._treeView.append_column(column)
271
[435]272 for header in headers:
[996]273 column = Gtk.TreeViewColumn(header, Gtk.CellRendererText())
[999]274 column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
[435]275 self._treeView.append_column(column)
276
[996]277 self._table = Gtk.Table(numRows, numColumns)
[435]278 self._table.set_homogeneous(False)
279 self._table.set_col_spacings(16)
280 self._table.set_row_spacings(4)
[436]281 self._eventBox.add(self._table)
282
283 self._alignments = []
[437]284 self._checkButtons = []
[435]285
286 firstDelayCodeRow = True
287 for i in range(0, numRows):
288 (type, elements) = rows[i]
289 if type==CAPTION:
[996]290 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
[435]291 xscale = 1.0)
[996]292 label = Gtk.Label("<b>" + elements + "</b>")
[435]293 label.set_use_markup(True)
294 label.set_alignment(0.0, 0.5)
295 alignment.add(label)
[438]296 self._table.attach(alignment, 1, numColumns, i, i+1,
[999]297 yoptions = Gtk.AttachOptions.FILL)
[435]298 self._table.set_row_spacing(i, 8)
299 elif type==DELAYCODE:
[437]300 checkButton = CheckButton(elements)
[555]301 checkButton.connect("toggled", self._delayCodesChanged)
[437]302 self._checkButtons.append(checkButton)
[435]303 alignment = Alignment(xalign = 0.5, yalign = 0.5, xscale = 1.0)
[437]304 alignment.add(checkButton)
[438]305 self._table.attach(alignment, 0, 1, i, i+1,
[999]306 xoptions = Gtk.AttachOptions.FILL,
307 yoptions = Gtk.AttachOptions.FILL)
[435]308 if firstDelayCodeRow:
309 self._alignments.append(alignment)
310
[438]311 for j in range(0, numColumns-1):
[996]312 label = Gtk.Label(elements[j])
[439]313 label.set_alignment(0.0, 0.5)
[435]314 alignment = Alignment(xalign = 0.5, yalign = 0.5,
315 xscale = 1.0)
316 alignment.add(label)
[999]317 xoptions = Gtk.AttachOptions.FILL
318 if j==(numColumns-2): xoptions |= Gtk.AttachOptions.EXPAND
[438]319 self._table.attach(alignment, j+1, j+2, i, i+1,
[999]320 xoptions = xoptions,
321 yoptions = Gtk.AttachOptions.FILL)
[435]322 if firstDelayCodeRow:
323 self._alignments.append(alignment)
324 firstDelayCodeRow = False
[433]325
326 self._previousWidth = 0
[436]327 self.show_all()
[433]328
[436]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)
[768]334 if self._table is not None:
335 self._eventBox.remove(self._table)
[436]336 self._table = None
337 self.show_all()
[433]338
[840]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
[555]349 def _delayCodesChanged(self, button):
350 """Called when one of the delay codes have changed."""
[1146]351 delayCodeRows = self._delayCodeRows
352 numDelayCodes = len(delayCodeRows)
[1035]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
[1146]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
[555]377 self._info.delayCodesChanged()
378
[433]379#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.