source: src/mlx/gui/common.py@ 604:0ec6a6f58f08

Last change on this file since 604:0ec6a6f58f08 was 604:0ec6a6f58f08, checked in by István Váradi <ivaradi@…>, 9 years ago

Added a new widget to list the faults and provide space for the user to enter an explanation (re #248).

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