source: src/mlx/gui/common.py@ 681:6d454f3c68c8

Last change on this file since 681:6d454f3c68c8 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
RevLine 
[575]1
2from mlx.common import *
[28]3
[105]4import mlx.const as _const
[175]5from mlx.i18n import xstr
[105]6
[373]7from mlx.util import secondaryInstallation
8
[28]9import os
10
[300]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
[474]19# GUI have to check the version in use very rarely. The variable \c pygobject
[300]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#
[302]24# Besides this there are some common utility classes and functions.
[300]25
26#-----------------------------------------------------------------------------
27
[28]28appIndicator = False
29
[575]30if not pygobject:
[28]31 print "Using PyGTK"
32 pygobject = False
33 import pygtk
[29]34 import gtk.gdk as gdk
[28]35 import gtk
[44]36 import pango
[575]37
[28]38 try:
39 import appindicator
40 appIndicator = True
41 except Exception, e:
42 pass
[42]43
44 MESSAGETYPE_ERROR = gtk.MESSAGE_ERROR
[76]45 MESSAGETYPE_QUESTION = gtk.MESSAGE_QUESTION
[97]46 MESSAGETYPE_INFO = gtk.MESSAGE_INFO
[175]47
[124]48 RESPONSETYPE_OK = gtk.RESPONSE_OK
[76]49 RESPONSETYPE_YES = gtk.RESPONSE_YES
[124]50 RESPONSETYPE_NO = gtk.RESPONSE_NO
[123]51 RESPONSETYPE_ACCEPT = gtk.RESPONSE_ACCEPT
52 RESPONSETYPE_REJECT = gtk.RESPONSE_REJECT
[149]53 RESPONSETYPE_CANCEL = gtk.RESPONSE_CANCEL
[175]54
[93]55 ACCEL_VISIBLE = gtk.ACCEL_VISIBLE
56 CONTROL_MASK = gdk.CONTROL_MASK
[123]57 DIALOG_MODAL = gtk.DIALOG_MODAL
[127]58 WRAP_WORD = gtk.WRAP_WORD
[604]59
[132]60 JUSTIFY_CENTER = gtk.JUSTIFY_CENTER
[604]61 JUSTIFY_LEFT = gtk.JUSTIFY_LEFT
[97]62
[144]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
[149]72 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
[151]73 FILE_CHOOSER_ACTION_OPEN = gtk.FILE_CHOOSER_ACTION_OPEN
74 FILE_CHOOSER_ACTION_SAVE = gtk.FILE_CHOOSER_ACTION_SAVE
[149]75
[175]76 SELECTION_MULTIPLE = gtk.SELECTION_MULTIPLE
77
[220]78 SHADOW_IN = gtk.SHADOW_IN
[433]79 SHADOW_NONE = gtk.SHADOW_NONE
[220]80
81 POLICY_AUTOMATIC = gtk.POLICY_AUTOMATIC
[604]82 POLICY_NEVER = gtk.POLICY_NEVER
83 POLICY_ALWAYS = gtk.POLICY_ALWAYS
[220]84
[362]85 WEIGHT_NORMAL = pango.WEIGHT_NORMAL
[226]86 WEIGHT_BOLD = pango.WEIGHT_BOLD
87
[246]88 WINDOW_STATE_ICONIFIED = gdk.WINDOW_STATE_ICONIFIED
89 WINDOW_STATE_WITHDRAWN = gdk.WINDOW_STATE_WITHDRAWN
90
[264]91 SORT_ASCENDING = gtk.SORT_ASCENDING
92 SORT_DESCENDING = gtk.SORT_DESCENDING
93
[277]94 EVENT_BUTTON_PRESS = gdk.BUTTON_PRESS
95
[433]96 TREE_VIEW_COLUMN_FIXED = gtk.TREE_VIEW_COLUMN_FIXED
97
[438]98 FILL = gtk.FILL
99 EXPAND = gtk.EXPAND
100
[554]101 UPDATE_IF_VALID = gtk.UPDATE_IF_VALID
102
[227]103 pixbuf_new_from_file = gdk.pixbuf_new_from_file
104
[97]105 def text2unicode(text):
106 """Convert the given text, returned by a Gtk widget, to Unicode."""
107 return unicode(text)
[276]108
109 def text2str(text):
110 """Convert the given text, returned by xstr to a string."""
111 return str(text)
[401]112
[575]113else: # pygobject
[29]114 from gi.repository import Gdk as gdk
[227]115 from gi.repository import GdkPixbuf as gdkPixbuf
[28]116 from gi.repository import Gtk as gtk
117 from gi.repository import AppIndicator3 as appindicator
[44]118 from gi.repository import Pango as pango
[575]119
[28]120 appIndicator = True
[401]121
[575]122
[42]123 MESSAGETYPE_ERROR = gtk.MessageType.ERROR
[76]124 MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
[97]125 MESSAGETYPE_INFO = gtk.MessageType.INFO
[124]126 RESPONSETYPE_OK = gtk.ResponseType.OK
[76]127 RESPONSETYPE_YES = gtk.ResponseType.YES
[124]128 RESPONSETYPE_NO = gtk.ResponseType.NO
[123]129 RESPONSETYPE_ACCEPT = gtk.ResponseType.ACCEPT
130 RESPONSETYPE_REJECT = gtk.ResponseType.REJECT
[149]131 RESPONSETYPE_CANCEL = gtk.ResponseType.CANCEL
[93]132 ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
133 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
[123]134 DIALOG_MODAL = gtk.DialogFlags.MODAL
[127]135 WRAP_WORD = gtk.WrapMode.WORD
[132]136 JUSTIFY_CENTER = gtk.Justification.CENTER
[604]137 JUSTIFY_LEFT = gtk.Justification.LEFT
[42]138
[144]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
[149]148 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FileChooserAction.SELECT_FOLDER
[151]149 FILE_CHOOSER_ACTION_OPEN = gtk.FileChooserAction.OPEN
150 FILE_CHOOSER_ACTION_SAVE = gtk.FileChooserAction.SAVE
[149]151
[175]152 SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
153
[220]154 SHADOW_IN = gtk.ShadowType.IN
[433]155 SHADOW_NONE = gtk.ShadowType.NONE
[220]156
157 POLICY_AUTOMATIC = gtk.PolicyType.AUTOMATIC
[604]158 POLICY_NEVER = gtk.PolicyType.NEVER
159 POLICY_ALWAYS = gtk.PolicyType.ALWAYS
[220]160
[362]161 WEIGHT_NORMAL = pango.Weight.NORMAL
[226]162 WEIGHT_BOLD = pango.Weight.BOLD
163
[246]164 WINDOW_STATE_ICONIFIED = gdk.WindowState.ICONIFIED
165 WINDOW_STATE_WITHDRAWN = gdk.WindowState.WITHDRAWN
166
[264]167 SORT_ASCENDING = gtk.SortType.ASCENDING
168 SORT_DESCENDING = gtk.SortType.DESCENDING
169
[277]170 EVENT_BUTTON_PRESS = gdk.EventType.BUTTON_PRESS
171
[433]172 TREE_VIEW_COLUMN_FIXED = gtk.TreeViewColumnSizing.FIXED
173
[438]174 FILL = gtk.AttachOptions.FILL
175 EXPAND = gtk.AttachOptions.EXPAND
176
[554]177 UPDATE_IF_VALID = gtk.SpinButtonUpdatePolicy.IF_VALID
178
[227]179 pixbuf_new_from_file = gdkPixbuf.Pixbuf.new_from_file
180
[97]181 import codecs
182 _utf8Decoder = codecs.getdecoder("utf-8")
[401]183
[97]184 def text2unicode(str):
185 """Convert the given text, returned by a Gtk widget, to Unicode."""
186 return _utf8Decoder(str)[0]
187
[276]188 def text2str(text):
189 """Convert the given text, returned by xstr to a string."""
190 return _utf8Decoder(text)[0]
191
[28]192import cairo
193
[32]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()
[401]209
[32]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#------------------------------------------------------------------------------
[84]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
[86]237 self.set_alignment(1.0)
238
[84]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
[241]250 def reset(self):
251 """Reset the integer."""
252 self.set_int(None)
253
[84]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()
[401]260
[84]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
[401]280
[84]281#------------------------------------------------------------------------------
282
283gobject.signal_new("integer-changed", IntegerEntry, gobject.SIGNAL_RUN_FIRST,
284 None, (object,))
285
286#------------------------------------------------------------------------------
[105]287
[227]288PROGRAM_NAME = "MAVA Logger X"
289
[232]290WINDOW_TITLE_BASE = PROGRAM_NAME + " " + _const.VERSION
[373]291if secondaryInstallation:
292 WINDOW_TITLE_BASE += " (" + xstr("secondary") + ")"
[105]293
294#------------------------------------------------------------------------------
[175]295
296# A mapping of aircraft types to their screen names
[191]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"),
[443]312 _const.AIRCRAFT_YK40 : xstr("aircraft_yk40"),
313 _const.AIRCRAFT_B462 : xstr("aircraft_b462") }
[175]314
315#------------------------------------------------------------------------------
[221]316
[226]317def formatFlightLogLine(timeStr, line):
[221]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#------------------------------------------------------------------------------
[226]325
326def addFaultTag(buffer):
327 """Add a tag named 'fault' to the given buffer."""
[362]328 buffer.create_tag("fault", foreground="red", weight=WEIGHT_BOLD)
[226]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'."""
[345]336 insertTextBuffer(buffer, buffer.get_end_iter(), text, isFault)
[226]337
338#------------------------------------------------------------------------------
[345]339
340def insertTextBuffer(buffer, iter, text, isFault = False):
341 """Insert the given line into the given text buffer at the given iterator.
342
[362]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)
[345]351 if isFault:
[362]352 buffer.apply_tag_by_name("fault", iter0, iter1)
[345]353 else:
[362]354 buffer.remove_all_tags(iter0, iter1)
[345]355
356#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.