source: src/mlx/gui/common.py@ 401:15ad3c16ee11

Last change on this file since 401:15ad3c16ee11 was 401:15ad3c16ee11, checked in by István Váradi <ivaradi@…>, 11 years ago

The exception strings are converted from UTF-8 to unicode for proper logging (re #170)

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