source: src/mlx/gui/common.py@ 562:1d03568e5f67

Last change on this file since 562:1d03568e5f67 was 554:b585c74956cb, checked in by István Váradi <ivaradi@…>, 11 years ago

The cruise level is initialized to 0 so that the Next button is disabled unless a valid value is entered (re #223)

File size: 11.3 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 \c 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 UPDATE_IF_VALID = gtk.UPDATE_IF_VALID
96
97 pixbuf_new_from_file = gdk.pixbuf_new_from_file
98
99 def text2unicode(text):
100 """Convert the given text, returned by a Gtk widget, to Unicode."""
101 return unicode(text)
102
103 def text2str(text):
104 """Convert the given text, returned by xstr to a string."""
105 return str(text)
106
107else:
108 print "Using PyGObject"
109 pygobject = True
110 from gi.repository import Gdk as gdk
111 from gi.repository import GdkPixbuf as gdkPixbuf
112 from gi.repository import Gtk as gtk
113 from gi.repository import GObject as gobject
114 from gi.repository import AppIndicator3 as appindicator
115 from gi.repository import Pango as pango
116 appIndicator = True
117
118 MESSAGETYPE_ERROR = gtk.MessageType.ERROR
119 MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
120 MESSAGETYPE_INFO = gtk.MessageType.INFO
121 RESPONSETYPE_OK = gtk.ResponseType.OK
122 RESPONSETYPE_YES = gtk.ResponseType.YES
123 RESPONSETYPE_NO = gtk.ResponseType.NO
124 RESPONSETYPE_ACCEPT = gtk.ResponseType.ACCEPT
125 RESPONSETYPE_REJECT = gtk.ResponseType.REJECT
126 RESPONSETYPE_CANCEL = gtk.ResponseType.CANCEL
127 ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
128 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
129 DIALOG_MODAL = gtk.DialogFlags.MODAL
130 WRAP_WORD = gtk.WrapMode.WORD
131 JUSTIFY_CENTER = gtk.Justification.CENTER
132
133 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
134 SHIFT_MASK = gdk.ModifierType.SHIFT_MASK
135 BUTTON1_MASK = gdk.ModifierType.BUTTON1_MASK
136
137 SCROLL_UP = gdk.ScrollDirection.UP
138 SCROLL_DOWN = gdk.ScrollDirection.DOWN
139
140 SPIN_USER_DEFINED = gtk.SpinType.USER_DEFINED
141
142 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FileChooserAction.SELECT_FOLDER
143 FILE_CHOOSER_ACTION_OPEN = gtk.FileChooserAction.OPEN
144 FILE_CHOOSER_ACTION_SAVE = gtk.FileChooserAction.SAVE
145
146 SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
147
148 SHADOW_IN = gtk.ShadowType.IN
149 SHADOW_NONE = gtk.ShadowType.NONE
150
151 POLICY_AUTOMATIC = gtk.PolicyType.AUTOMATIC
152
153 WEIGHT_NORMAL = pango.Weight.NORMAL
154 WEIGHT_BOLD = pango.Weight.BOLD
155
156 WINDOW_STATE_ICONIFIED = gdk.WindowState.ICONIFIED
157 WINDOW_STATE_WITHDRAWN = gdk.WindowState.WITHDRAWN
158
159 SORT_ASCENDING = gtk.SortType.ASCENDING
160 SORT_DESCENDING = gtk.SortType.DESCENDING
161
162 EVENT_BUTTON_PRESS = gdk.EventType.BUTTON_PRESS
163
164 TREE_VIEW_COLUMN_FIXED = gtk.TreeViewColumnSizing.FIXED
165
166 FILL = gtk.AttachOptions.FILL
167 EXPAND = gtk.AttachOptions.EXPAND
168
169 UPDATE_IF_VALID = gtk.SpinButtonUpdatePolicy.IF_VALID
170
171 pixbuf_new_from_file = gdkPixbuf.Pixbuf.new_from_file
172
173 import codecs
174 _utf8Decoder = codecs.getdecoder("utf-8")
175
176 def text2unicode(str):
177 """Convert the given text, returned by a Gtk widget, to Unicode."""
178 return _utf8Decoder(str)[0]
179
180 def text2str(text):
181 """Convert the given text, returned by xstr to a string."""
182 return _utf8Decoder(text)[0]
183
184import cairo
185
186#------------------------------------------------------------------------------
187
188class FlightStatusHandler(object):
189 """Base class for objects that handle the flight status in some way."""
190 def __init__(self):
191 self._stage = None
192 self._rating = 100
193 self._noGoReason = None
194
195 def resetFlightStatus(self):
196 """Reset the flight status."""
197 self._stage = None
198 self._rating = 100
199 self._noGoReason = None
200 self._updateFlightStatus()
201
202 def setStage(self, stage):
203 """Set the stage of the flight."""
204 if stage!=self._stage:
205 self._stage = stage
206 self._updateFlightStatus()
207
208 def setRating(self, rating):
209 """Set the rating to the given value."""
210 if rating!=self._rating:
211 self._rating = rating
212 if self._noGoReason is None:
213 self._updateFlightStatus()
214
215 def setNoGo(self, reason):
216 """Set a No-Go condition with the given reason."""
217 if self._noGoReason is None:
218 self._noGoReason = reason
219 self._updateFlightStatus()
220
221#------------------------------------------------------------------------------
222
223class IntegerEntry(gtk.Entry):
224 """An entry that allows only either an empty value, or an integer."""
225 def __init__(self, defaultValue = None):
226 """Construct the entry."""
227 gtk.Entry.__init__(self)
228
229 self.set_alignment(1.0)
230
231 self._defaultValue = defaultValue
232 self._currentInteger = defaultValue
233 self._selfSetting = False
234 self._set_text()
235
236 self.connect("changed", self._handle_changed)
237
238 def get_int(self):
239 """Get the integer."""
240 return self._currentInteger
241
242 def reset(self):
243 """Reset the integer."""
244 self.set_int(None)
245
246 def set_int(self, value):
247 """Set the integer."""
248 if value!=self._currentInteger:
249 self._currentInteger = value
250 self.emit("integer-changed", self._currentInteger)
251 self._set_text()
252
253 def _handle_changed(self, widget):
254 """Handle the changed signal."""
255 if self._selfSetting:
256 return
257 text = self.get_text()
258 if text=="":
259 self.set_int(self._defaultValue)
260 else:
261 try:
262 self.set_int(int(text))
263 except:
264 self._set_text()
265
266 def _set_text(self):
267 """Set the text value from the current integer."""
268 self._selfSetting = True
269 self.set_text("" if self._currentInteger is None
270 else str(self._currentInteger))
271 self._selfSetting = False
272
273#------------------------------------------------------------------------------
274
275gobject.signal_new("integer-changed", IntegerEntry, gobject.SIGNAL_RUN_FIRST,
276 None, (object,))
277
278#------------------------------------------------------------------------------
279
280PROGRAM_NAME = "MAVA Logger X"
281
282WINDOW_TITLE_BASE = PROGRAM_NAME + " " + _const.VERSION
283if secondaryInstallation:
284 WINDOW_TITLE_BASE += " (" + xstr("secondary") + ")"
285
286#------------------------------------------------------------------------------
287
288# A mapping of aircraft types to their screen names
289aircraftNames = { _const.AIRCRAFT_B736 : xstr("aircraft_b736"),
290 _const.AIRCRAFT_B737 : xstr("aircraft_b737"),
291 _const.AIRCRAFT_B738 : xstr("aircraft_b738"),
292 _const.AIRCRAFT_B738C : xstr("aircraft_b738c"),
293 _const.AIRCRAFT_B733 : xstr("aircraft_b733"),
294 _const.AIRCRAFT_B734 : xstr("aircraft_b734"),
295 _const.AIRCRAFT_B735 : xstr("aircraft_b735"),
296 _const.AIRCRAFT_DH8D : xstr("aircraft_dh8d"),
297 _const.AIRCRAFT_B762 : xstr("aircraft_b762"),
298 _const.AIRCRAFT_B763 : xstr("aircraft_b763"),
299 _const.AIRCRAFT_CRJ2 : xstr("aircraft_crj2"),
300 _const.AIRCRAFT_F70 : xstr("aircraft_f70"),
301 _const.AIRCRAFT_DC3 : xstr("aircraft_dc3"),
302 _const.AIRCRAFT_T134 : xstr("aircraft_t134"),
303 _const.AIRCRAFT_T154 : xstr("aircraft_t154"),
304 _const.AIRCRAFT_YK40 : xstr("aircraft_yk40"),
305 _const.AIRCRAFT_B462 : xstr("aircraft_b462") }
306
307#------------------------------------------------------------------------------
308
309def formatFlightLogLine(timeStr, line):
310 """Format the given flight log line."""
311 """Format the given line for flight logging."""
312 if timeStr is not None:
313 line = timeStr + ": " + line
314 return line + "\n"
315
316#------------------------------------------------------------------------------
317
318def addFaultTag(buffer):
319 """Add a tag named 'fault' to the given buffer."""
320 buffer.create_tag("fault", foreground="red", weight=WEIGHT_BOLD)
321
322#------------------------------------------------------------------------------
323
324def appendTextBuffer(buffer, text, isFault = False):
325 """Append the given line at the end of the given text buffer.
326
327 If isFault is set, use the tag named 'fault'."""
328 insertTextBuffer(buffer, buffer.get_end_iter(), text, isFault)
329
330#------------------------------------------------------------------------------
331
332def insertTextBuffer(buffer, iter, text, isFault = False):
333 """Insert the given line into the given text buffer at the given iterator.
334
335 If isFault is set, use the tag named 'fault' else use the tag named
336 'normal'."""
337 line = iter.get_line()
338
339 buffer.insert(iter, text)
340
341 iter0 = buffer.get_iter_at_line(line)
342 iter1 = buffer.get_iter_at_line(line+1)
343 if isFault:
344 buffer.apply_tag_by_name("fault", iter0, iter1)
345 else:
346 buffer.remove_all_tags(iter0, iter1)
347
348#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.