source: src/mlx/gui/delaycodes.py@ 968:1128dfecb282

python3
Last change on this file since 968:1128dfecb282 was 965:63e290b4ba1e, checked in by István Váradi <ivaradi@…>, 6 years ago

The heading of the delay code table appears properly (re #347)

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