source: src/mlx/gui/delaycodes.py@ 1063:b2b67f680d11

python3
Last change on this file since 1063:b2b67f680d11 was 1035:463c2477d842, checked in by István Váradi <ivaradi@…>, 3 years ago

At most 4 delay codes can be selected (re #357)

File size: 13.5 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
194 self._eventBox = Gtk.EventBox()
195
196 self._table = None
197
198 self._viewport = self._createViewport()
199 self._viewport.add(self._eventBox)
200 self._viewport.set_shadow_type(Gtk.ShadowType.NONE)
201
202 self.pack_start(self._viewport, True, True, 0)
203
204 self._previousWidth = 0
205
206 @property
207 def delayCodes(self):
208 """Get a list of the delay codes checked by the user."""
209 codes = []
210
211 if self._delayCodeData is not None:
212 codeExtractor = self._delayCodeData[0]
213 for checkButton in self._checkButtons:
214 if checkButton.get_active():
215 codes.append(codeExtractor(checkButton.delayCodeRow))
216
217 return codes
218
219 @property
220 def hasDelayCode(self):
221 """Determine if there is at least one delay code selected."""
222 if self._delayCodeData is not None:
223 for checkButton in self._checkButtons:
224 if checkButton.get_active():
225 return True
226
227 return False
228
229 def allocate_column_sizes(self, allocation):
230 """Allocate the column sizes."""
231 if allocation.width!=self._previousWidth:
232 self._previousWidth = allocation.width
233 index = 0
234 lastIndex = len(self._alignments) - 1
235 for alignment in self._alignments:
236 column = self._treeView.get_column(index)
237 width = alignment.allocatedWidth
238 width += 8 if (index==0 or index==lastIndex) else 16
239 column.set_fixed_width(width)
240 index += 1
241
242 def setType(self, aircraftType):
243 """Setup the delay code table according to the given aircraft type."""
244 self._delayCodeData = data = getTable(aircraftType)
245 if data is None:
246 return
247
248 columns = self._treeView.get_columns()
249 for column in columns:
250 self._treeView.remove_column(column)
251
252 (_extractor, headers, rows) = data
253 numColumns = len(headers) + 1
254 numRows = len(rows)
255
256 column = Gtk.TreeViewColumn("", Gtk.CellRendererText())
257 column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
258 self._treeView.append_column(column)
259
260 for header in headers:
261 column = Gtk.TreeViewColumn(header, Gtk.CellRendererText())
262 column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
263 self._treeView.append_column(column)
264
265 self._table = Gtk.Table(numRows, numColumns)
266 self._table.set_homogeneous(False)
267 self._table.set_col_spacings(16)
268 self._table.set_row_spacings(4)
269 self._eventBox.add(self._table)
270
271 self._alignments = []
272 self._checkButtons = []
273
274 firstDelayCodeRow = True
275 for i in range(0, numRows):
276 (type, elements) = rows[i]
277 if type==CAPTION:
278 alignment = Gtk.Alignment(xalign = 0.0, yalign = 0.5,
279 xscale = 1.0)
280 label = Gtk.Label("<b>" + elements + "</b>")
281 label.set_use_markup(True)
282 label.set_alignment(0.0, 0.5)
283 alignment.add(label)
284 self._table.attach(alignment, 1, numColumns, i, i+1,
285 yoptions = Gtk.AttachOptions.FILL)
286 self._table.set_row_spacing(i, 8)
287 elif type==DELAYCODE:
288 checkButton = CheckButton(elements)
289 checkButton.connect("toggled", self._delayCodesChanged)
290 self._checkButtons.append(checkButton)
291 alignment = Alignment(xalign = 0.5, yalign = 0.5, xscale = 1.0)
292 alignment.add(checkButton)
293 self._table.attach(alignment, 0, 1, i, i+1,
294 xoptions = Gtk.AttachOptions.FILL,
295 yoptions = Gtk.AttachOptions.FILL)
296 if firstDelayCodeRow:
297 self._alignments.append(alignment)
298
299 for j in range(0, numColumns-1):
300 label = Gtk.Label(elements[j])
301 label.set_alignment(0.0, 0.5)
302 alignment = Alignment(xalign = 0.5, yalign = 0.5,
303 xscale = 1.0)
304 alignment.add(label)
305 xoptions = Gtk.AttachOptions.FILL
306 if j==(numColumns-2): xoptions |= Gtk.AttachOptions.EXPAND
307 self._table.attach(alignment, j+1, j+2, i, i+1,
308 xoptions = xoptions,
309 yoptions = Gtk.AttachOptions.FILL)
310 if firstDelayCodeRow:
311 self._alignments.append(alignment)
312 firstDelayCodeRow = False
313
314 self._previousWidth = 0
315 self.show_all()
316
317 def reset(self):
318 """Reset the delay code table."""
319 columns = self._treeView.get_columns()
320 for column in columns:
321 self._treeView.remove_column(column)
322 if self._table is not None:
323 self._eventBox.remove(self._table)
324 self._table = None
325 self.show_all()
326
327 def activateCode(self, code):
328 """Check the checkbox for the given code."""
329 index = 0
330 for (type, data) in self._delayCodeData[2]:
331 if type==DELAYCODE:
332 if code==data[0].strip():
333 self._checkButtons[index].set_active(True)
334 break
335 index += 1
336
337 def _delayCodesChanged(self, button):
338 """Called when one of the delay codes have changed."""
339 numDelayCodes = len(self.delayCodes)
340 if numDelayCodes>=4:
341 for checkButton in self._checkButtons:
342 if not checkButton.get_active():
343 checkButton.set_sensitive(False)
344 else:
345 for checkButton in self._checkButtons:
346 checkButton.set_sensitive(True)
347
348 self._info.delayCodesChanged()
349
350#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.