source: src/mlx/gui/flightlist.py@ 818:e58b0fa0408a

Last change on this file since 818:e58b0fa0408a was 818:e58b0fa0408a, checked in by István Váradi <ivaradi@…>, 8 years ago

The default column descriptors are moved to the FlightList (re #307).

File size: 7.3 KB
Line 
1# A widget which is a generic list of flights
2
3#-----------------------------------------------------------------------------
4
5from mlx.gui.common import *
6
7#-----------------------------------------------------------------------------
8
9class ColumnDescriptor(object):
10 """A descriptor for a column in the list."""
11 def __init__(self, attribute, heading, type = str,
12 convertFn = None, renderer = gtk.CellRendererText(),
13 extraColumnAttributes = None, sortable = False):
14 """Construct the descriptor."""
15 self._attribute = attribute
16 self._heading = heading
17 self._type = type
18 self._convertFn = convertFn
19 self._renderer = renderer
20 self._extraColumnAttributes = extraColumnAttributes
21 self._sortable = sortable
22
23 def appendType(self, types):
24 """Append the type of this column to the given list of types."""
25 types.append(self._type)
26
27 def getViewColumn(self, index):
28 """Get a new column object for a tree view.
29
30 @param index is the 0-based index of the column."""
31 if self._extraColumnAttributes is None:
32 if isinstance(self._renderer, gtk.CellRendererText):
33 extraColumnAttributes = {"text" : index}
34 else:
35 extraColumnAttributes = {}
36 else:
37 extraColumnAttributes = self._extraColumnAttributes
38
39 column = gtk.TreeViewColumn(self._heading, self._renderer,
40 text = index)
41 column.set_expand(True)
42 if self._sortable:
43 column.set_sort_column_id(index)
44 column.set_sort_indicator(True)
45
46 return column
47
48 def getValueFrom(self, flight):
49 """Get the value from the given flight."""
50 value = getattr(flight, self._attribute)
51 return self._type(value) if self._convertFn is None \
52 else self._convertFn(value)
53
54#-----------------------------------------------------------------------------
55
56class FlightList(gtk.Alignment):
57 """Construct the flight list.
58
59 This is a complete widget with a scroll window. It is alignment centered
60 horizontally and expandable vertically."""
61
62 defaultColumnDescriptors = [
63 ColumnDescriptor("callsign", xstr("flightsel_no")),
64 ColumnDescriptor("departureTime", xstr("flightsel_deptime"),
65 sortable = True),
66 ColumnDescriptor("departureICAO", xstr("flightsel_from"),
67 sortable = True),
68 ColumnDescriptor("arrivalICAO", xstr("flightsel_to"), sortable = True)
69 ]
70
71 def __init__(self, columnDescriptors = defaultColumnDescriptors,
72 popupMenuProducer = None, widthRequest = None):
73 """Construct the flight list with the given column descriptors."""
74
75 self._columnDescriptors = columnDescriptors
76 self._popupMenuProducer = popupMenuProducer
77 self._popupMenu = None
78
79 types = [int]
80 for columnDescriptor in self._columnDescriptors:
81 columnDescriptor.appendType(types)
82
83 self._model = gtk.ListStore(*types)
84 self._model.set_sort_column_id(2, SORT_ASCENDING)
85 self._view = gtk.TreeView(self._model)
86
87 flightIndexColumn = gtk.TreeViewColumn()
88 flightIndexColumn.set_visible(False)
89 self._view.append_column(flightIndexColumn)
90
91 index = 1
92 for columnDescriptor in self._columnDescriptors:
93 column = columnDescriptor.getViewColumn(index)
94 self._view.append_column(column)
95 index += 1
96
97 self._view.connect("row-activated", self._rowActivated)
98 self._view.connect("button-press-event", self._buttonPressEvent)
99
100 selection = self._view.get_selection()
101 selection.connect("changed", self._selectionChanged)
102
103 scrolledWindow = gtk.ScrolledWindow()
104 scrolledWindow.add(self._view)
105 if widthRequest is not None:
106 scrolledWindow.set_size_request(widthRequest, -1)
107 # FIXME: these should be constants in common.py
108 scrolledWindow.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
109 else gtk.POLICY_AUTOMATIC,
110 gtk.PolicyType.AUTOMATIC if pygobject
111 else gtk.POLICY_AUTOMATIC)
112 scrolledWindow.set_shadow_type(gtk.ShadowType.IN if pygobject
113 else gtk.SHADOW_IN)
114
115 super(FlightList, self).__init__(xalign = 0.5, yalign = 0.0,
116 xscale = 0.0, yscale = 1.0)
117 self.add(scrolledWindow)
118
119 @property
120 def selectedIndex(self):
121 """Get the index of the selected entry, if any."""
122 selection = self._view.get_selection()
123 (model, iter) = selection.get_selected()
124 if iter is None:
125 return None
126 else:
127 index = model.get_value(iter, 0)
128 return index
129
130 @property
131 def hasFlights(self):
132 """Determine if there are any flights in the list."""
133 return self._model.get_iter_root() is not None
134
135 def clear(self):
136 """Clear the model."""
137 self._model.clear()
138
139 def addFlight(self, flight):
140 """Add the given booked flight."""
141 values = [self._model.iter_n_children(None)]
142 for columnDescriptor in self._columnDescriptors:
143 values.append(columnDescriptor.getValueFrom(flight))
144 self._model.append(values)
145
146 def removeFlight(self, index):
147 """Remove the flight with the given index."""
148 model = self._model
149 idx = 0
150 iter = model.get_iter_first()
151 while iter is not None:
152 nextIter = model.iter_next(iter)
153 if model.get_value(iter, 0)==index:
154 model.remove(iter)
155 else:
156 model.set_value(iter, 0, idx)
157 idx += 1
158 iter = nextIter
159
160 def _rowActivated(self, flightList, path, column):
161 """Called when a row is selected."""
162 self.emit("row-activated", self.selectedIndex)
163
164 def _buttonPressEvent(self, widget, event):
165 """Called when a mouse button is pressed or released."""
166 if event.type!=EVENT_BUTTON_PRESS or event.button!=3 or \
167 self._popupMenuProducer is None:
168 return
169
170 (path, _, _, _) = self._view.get_path_at_pos(int(event.x),
171 int(event.y))
172 selection = self._view.get_selection()
173 selection.unselect_all()
174 selection.select_path(path)
175
176 if self._popupMenu is None:
177 self._popupMenu = self._popupMenuProducer()
178 menu = self._popupMenu
179 if pygobject:
180 menu.popup(None, None, None, None, event.button, event.time)
181 else:
182 menu.popup(None, None, None, event.button, event.time)
183
184 def _selectionChanged(self, selection):
185 """Called when the selection has changed."""
186 self.emit("selection-changed", self.selectedIndex)
187
188#-------------------------------------------------------------------------------
189
190gobject.signal_new("row-activated", FlightList, gobject.SIGNAL_RUN_FIRST,
191 None, (int,))
192
193gobject.signal_new("selection-changed", FlightList, gobject.SIGNAL_RUN_FIRST,
194 None, (object,))
195
196#-----------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.