source: src/mlx/gui/common.py@ 452:c838eb728031

Last change on this file since 452:c838eb728031 was 443:acbe605bb814, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support for the BAe 146-200 aircraft type (re #182)

File size: 11.2 KB
Line 
1
2import mlx.const as _const
3from mlx.i18n import xstr
4
5from mlx.util import secondaryInstallation
6
7import os
8
9#-----------------------------------------------------------------------------
10
11## @package mlx.gui.common
12#
13# Common definitions and utilities for the GUI
14#
15# The main purpose of this module is to provide common definitions for things
16# that are named differently in Gtk+ 2 and 3. This way the other parts of the
17# GUI have to check the version in use very rarely. The variable \ref pygobject
18# tells which version is being used. If it is \c True, Gtk+ 3 is used via the
19# PyGObject interface. Otherwise Gtk+ 2 is used, which is the default on
20# Windows or when the \c FORCE_PYGTK environment variable is set.
21#
22# Besides this there are some common utility classes and functions.
23
24#-----------------------------------------------------------------------------
25
26appIndicator = False
27
28if os.name=="nt" or "FORCE_PYGTK" in os.environ:
29 print "Using PyGTK"
30 pygobject = False
31 import pygtk
32 import gtk.gdk as gdk
33 import gtk
34 import gobject
35 import pango
36 try:
37 import appindicator
38 appIndicator = True
39 except Exception, e:
40 pass
41
42 MESSAGETYPE_ERROR = gtk.MESSAGE_ERROR
43 MESSAGETYPE_QUESTION = gtk.MESSAGE_QUESTION
44 MESSAGETYPE_INFO = gtk.MESSAGE_INFO
45
46 RESPONSETYPE_OK = gtk.RESPONSE_OK
47 RESPONSETYPE_YES = gtk.RESPONSE_YES
48 RESPONSETYPE_NO = gtk.RESPONSE_NO
49 RESPONSETYPE_ACCEPT = gtk.RESPONSE_ACCEPT
50 RESPONSETYPE_REJECT = gtk.RESPONSE_REJECT
51 RESPONSETYPE_CANCEL = gtk.RESPONSE_CANCEL
52
53 ACCEL_VISIBLE = gtk.ACCEL_VISIBLE
54 CONTROL_MASK = gdk.CONTROL_MASK
55 DIALOG_MODAL = gtk.DIALOG_MODAL
56 WRAP_WORD = gtk.WRAP_WORD
57 JUSTIFY_CENTER = gtk.JUSTIFY_CENTER
58
59 CONTROL_MASK = gdk.CONTROL_MASK
60 SHIFT_MASK = gdk.SHIFT_MASK
61 BUTTON1_MASK = gdk.BUTTON1_MASK
62
63 SCROLL_UP = gdk.SCROLL_UP
64 SCROLL_DOWN = gdk.SCROLL_DOWN
65
66 SPIN_USER_DEFINED = gtk.SPIN_USER_DEFINED
67
68 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
69 FILE_CHOOSER_ACTION_OPEN = gtk.FILE_CHOOSER_ACTION_OPEN
70 FILE_CHOOSER_ACTION_SAVE = gtk.FILE_CHOOSER_ACTION_SAVE
71
72 SELECTION_MULTIPLE = gtk.SELECTION_MULTIPLE
73
74 SHADOW_IN = gtk.SHADOW_IN
75 SHADOW_NONE = gtk.SHADOW_NONE
76
77 POLICY_AUTOMATIC = gtk.POLICY_AUTOMATIC
78
79 WEIGHT_NORMAL = pango.WEIGHT_NORMAL
80 WEIGHT_BOLD = pango.WEIGHT_BOLD
81
82 WINDOW_STATE_ICONIFIED = gdk.WINDOW_STATE_ICONIFIED
83 WINDOW_STATE_WITHDRAWN = gdk.WINDOW_STATE_WITHDRAWN
84
85 SORT_ASCENDING = gtk.SORT_ASCENDING
86 SORT_DESCENDING = gtk.SORT_DESCENDING
87
88 EVENT_BUTTON_PRESS = gdk.BUTTON_PRESS
89
90 TREE_VIEW_COLUMN_FIXED = gtk.TREE_VIEW_COLUMN_FIXED
91
92 FILL = gtk.FILL
93 EXPAND = gtk.EXPAND
94
95 pixbuf_new_from_file = gdk.pixbuf_new_from_file
96
97 def text2unicode(text):
98 """Convert the given text, returned by a Gtk widget, to Unicode."""
99 return unicode(text)
100
101 def text2str(text):
102 """Convert the given text, returned by xstr to a string."""
103 return str(text)
104
105else:
106 print "Using PyGObject"
107 pygobject = True
108 from gi.repository import Gdk as gdk
109 from gi.repository import GdkPixbuf as gdkPixbuf
110 from gi.repository import Gtk as gtk
111 from gi.repository import GObject as gobject
112 from gi.repository import AppIndicator3 as appindicator
113 from gi.repository import Pango as pango
114 appIndicator = True
115
116 MESSAGETYPE_ERROR = gtk.MessageType.ERROR
117 MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
118 MESSAGETYPE_INFO = gtk.MessageType.INFO
119 RESPONSETYPE_OK = gtk.ResponseType.OK
120 RESPONSETYPE_YES = gtk.ResponseType.YES
121 RESPONSETYPE_NO = gtk.ResponseType.NO
122 RESPONSETYPE_ACCEPT = gtk.ResponseType.ACCEPT
123 RESPONSETYPE_REJECT = gtk.ResponseType.REJECT
124 RESPONSETYPE_CANCEL = gtk.ResponseType.CANCEL
125 ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
126 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
127 DIALOG_MODAL = gtk.DialogFlags.MODAL
128 WRAP_WORD = gtk.WrapMode.WORD
129 JUSTIFY_CENTER = gtk.Justification.CENTER
130
131 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
132 SHIFT_MASK = gdk.ModifierType.SHIFT_MASK
133 BUTTON1_MASK = gdk.ModifierType.BUTTON1_MASK
134
135 SCROLL_UP = gdk.ScrollDirection.UP
136 SCROLL_DOWN = gdk.ScrollDirection.DOWN
137
138 SPIN_USER_DEFINED = gtk.SpinType.USER_DEFINED
139
140 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FileChooserAction.SELECT_FOLDER
141 FILE_CHOOSER_ACTION_OPEN = gtk.FileChooserAction.OPEN
142 FILE_CHOOSER_ACTION_SAVE = gtk.FileChooserAction.SAVE
143
144 SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
145
146 SHADOW_IN = gtk.ShadowType.IN
147 SHADOW_NONE = gtk.ShadowType.NONE
148
149 POLICY_AUTOMATIC = gtk.PolicyType.AUTOMATIC
150
151 WEIGHT_NORMAL = pango.Weight.NORMAL
152 WEIGHT_BOLD = pango.Weight.BOLD
153
154 WINDOW_STATE_ICONIFIED = gdk.WindowState.ICONIFIED
155 WINDOW_STATE_WITHDRAWN = gdk.WindowState.WITHDRAWN
156
157 SORT_ASCENDING = gtk.SortType.ASCENDING
158 SORT_DESCENDING = gtk.SortType.DESCENDING
159
160 EVENT_BUTTON_PRESS = gdk.EventType.BUTTON_PRESS
161
162 TREE_VIEW_COLUMN_FIXED = gtk.TreeViewColumnSizing.FIXED
163
164 FILL = gtk.AttachOptions.FILL
165 EXPAND = gtk.AttachOptions.EXPAND
166
167 pixbuf_new_from_file = gdkPixbuf.Pixbuf.new_from_file
168
169 import codecs
170 _utf8Decoder = codecs.getdecoder("utf-8")
171
172 def text2unicode(str):
173 """Convert the given text, returned by a Gtk widget, to Unicode."""
174 return _utf8Decoder(str)[0]
175
176 def text2str(text):
177 """Convert the given text, returned by xstr to a string."""
178 return _utf8Decoder(text)[0]
179
180import cairo
181
182#------------------------------------------------------------------------------
183
184class FlightStatusHandler(object):
185 """Base class for objects that handle the flight status in some way."""
186 def __init__(self):
187 self._stage = None
188 self._rating = 100
189 self._noGoReason = None
190
191 def resetFlightStatus(self):
192 """Reset the flight status."""
193 self._stage = None
194 self._rating = 100
195 self._noGoReason = None
196 self._updateFlightStatus()
197
198 def setStage(self, stage):
199 """Set the stage of the flight."""
200 if stage!=self._stage:
201 self._stage = stage
202 self._updateFlightStatus()
203
204 def setRating(self, rating):
205 """Set the rating to the given value."""
206 if rating!=self._rating:
207 self._rating = rating
208 if self._noGoReason is None:
209 self._updateFlightStatus()
210
211 def setNoGo(self, reason):
212 """Set a No-Go condition with the given reason."""
213 if self._noGoReason is None:
214 self._noGoReason = reason
215 self._updateFlightStatus()
216
217#------------------------------------------------------------------------------
218
219class IntegerEntry(gtk.Entry):
220 """An entry that allows only either an empty value, or an integer."""
221 def __init__(self, defaultValue = None):
222 """Construct the entry."""
223 gtk.Entry.__init__(self)
224
225 self.set_alignment(1.0)
226
227 self._defaultValue = defaultValue
228 self._currentInteger = defaultValue
229 self._selfSetting = False
230 self._set_text()
231
232 self.connect("changed", self._handle_changed)
233
234 def get_int(self):
235 """Get the integer."""
236 return self._currentInteger
237
238 def reset(self):
239 """Reset the integer."""
240 self.set_int(None)
241
242 def set_int(self, value):
243 """Set the integer."""
244 if value!=self._currentInteger:
245 self._currentInteger = value
246 self.emit("integer-changed", self._currentInteger)
247 self._set_text()
248
249 def _handle_changed(self, widget):
250 """Handle the changed signal."""
251 if self._selfSetting:
252 return
253 text = self.get_text()
254 if text=="":
255 self.set_int(self._defaultValue)
256 else:
257 try:
258 self.set_int(int(text))
259 except:
260 self._set_text()
261
262 def _set_text(self):
263 """Set the text value from the current integer."""
264 self._selfSetting = True
265 self.set_text("" if self._currentInteger is None
266 else str(self._currentInteger))
267 self._selfSetting = False
268
269#------------------------------------------------------------------------------
270
271gobject.signal_new("integer-changed", IntegerEntry, gobject.SIGNAL_RUN_FIRST,
272 None, (object,))
273
274#------------------------------------------------------------------------------
275
276PROGRAM_NAME = "MAVA Logger X"
277
278WINDOW_TITLE_BASE = PROGRAM_NAME + " " + _const.VERSION
279if secondaryInstallation:
280 WINDOW_TITLE_BASE += " (" + xstr("secondary") + ")"
281
282#------------------------------------------------------------------------------
283
284# A mapping of aircraft types to their screen names
285aircraftNames = { _const.AIRCRAFT_B736 : xstr("aircraft_b736"),
286 _const.AIRCRAFT_B737 : xstr("aircraft_b737"),
287 _const.AIRCRAFT_B738 : xstr("aircraft_b738"),
288 _const.AIRCRAFT_B738C : xstr("aircraft_b738c"),
289 _const.AIRCRAFT_B733 : xstr("aircraft_b733"),
290 _const.AIRCRAFT_B734 : xstr("aircraft_b734"),
291 _const.AIRCRAFT_B735 : xstr("aircraft_b735"),
292 _const.AIRCRAFT_DH8D : xstr("aircraft_dh8d"),
293 _const.AIRCRAFT_B762 : xstr("aircraft_b762"),
294 _const.AIRCRAFT_B763 : xstr("aircraft_b763"),
295 _const.AIRCRAFT_CRJ2 : xstr("aircraft_crj2"),
296 _const.AIRCRAFT_F70 : xstr("aircraft_f70"),
297 _const.AIRCRAFT_DC3 : xstr("aircraft_dc3"),
298 _const.AIRCRAFT_T134 : xstr("aircraft_t134"),
299 _const.AIRCRAFT_T154 : xstr("aircraft_t154"),
300 _const.AIRCRAFT_YK40 : xstr("aircraft_yk40"),
301 _const.AIRCRAFT_B462 : xstr("aircraft_b462") }
302
303#------------------------------------------------------------------------------
304
305def formatFlightLogLine(timeStr, line):
306 """Format the given flight log line."""
307 """Format the given line for flight logging."""
308 if timeStr is not None:
309 line = timeStr + ": " + line
310 return line + "\n"
311
312#------------------------------------------------------------------------------
313
314def addFaultTag(buffer):
315 """Add a tag named 'fault' to the given buffer."""
316 buffer.create_tag("fault", foreground="red", weight=WEIGHT_BOLD)
317
318#------------------------------------------------------------------------------
319
320def appendTextBuffer(buffer, text, isFault = False):
321 """Append the given line at the end of the given text buffer.
322
323 If isFault is set, use the tag named 'fault'."""
324 insertTextBuffer(buffer, buffer.get_end_iter(), text, isFault)
325
326#------------------------------------------------------------------------------
327
328def insertTextBuffer(buffer, iter, text, isFault = False):
329 """Insert the given line into the given text buffer at the given iterator.
330
331 If isFault is set, use the tag named 'fault' else use the tag named
332 'normal'."""
333 line = iter.get_line()
334
335 buffer.insert(iter, text)
336
337 iter0 = buffer.get_iter_at_line(line)
338 iter1 = buffer.get_iter_at_line(line+1)
339 if isFault:
340 buffer.apply_tag_by_name("fault", iter0, iter1)
341 else:
342 buffer.remove_all_tags(iter0, iter1)
343
344#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.