source: src/mlx/gui/common.py@ 895:929448cde3f5

Last change on this file since 895:929448cde3f5 was 895:929448cde3f5, checked in by István Váradi <ivaradi@…>, 6 years ago

The Ilyushin Il-62 is supported to some degree.

File size: 23.1 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
10import time
11import calendar
12
13#-----------------------------------------------------------------------------
14
15## @package mlx.gui.common
16#
17# Common definitions and utilities for the GUI
18#
19# The main purpose of this module is to provide common definitions for things
20# that are named differently in Gtk+ 2 and 3. This way the other parts of the
21# GUI have to check the version in use very rarely. The variable \c pygobject
22# tells which version is being used. If it is \c True, Gtk+ 3 is used via the
23# PyGObject interface. Otherwise Gtk+ 2 is used, which is the default on
24# Windows or when the \c FORCE_PYGTK environment variable is set.
25#
26# Besides this there are some common utility classes and functions.
27
28#-----------------------------------------------------------------------------
29
30appIndicator = False
31
32if not pygobject:
33 print "Using PyGTK"
34 pygobject = False
35 import pygtk
36 pygtk.require("2.0")
37 import gtk.gdk as gdk
38 import gtk
39 import pango
40
41 try:
42 import appindicator
43 appIndicator = True
44 except Exception, e:
45 pass
46
47 MESSAGETYPE_ERROR = gtk.MESSAGE_ERROR
48 MESSAGETYPE_QUESTION = gtk.MESSAGE_QUESTION
49 MESSAGETYPE_INFO = gtk.MESSAGE_INFO
50
51 RESPONSETYPE_NONE = gtk.RESPONSE_NONE
52 RESPONSETYPE_OK = gtk.RESPONSE_OK
53 RESPONSETYPE_YES = gtk.RESPONSE_YES
54 RESPONSETYPE_NO = gtk.RESPONSE_NO
55 RESPONSETYPE_ACCEPT = gtk.RESPONSE_ACCEPT
56 RESPONSETYPE_REJECT = gtk.RESPONSE_REJECT
57 RESPONSETYPE_CANCEL = gtk.RESPONSE_CANCEL
58
59 ACCEL_VISIBLE = gtk.ACCEL_VISIBLE
60 CONTROL_MASK = gdk.CONTROL_MASK
61 DIALOG_MODAL = gtk.DIALOG_MODAL
62 WRAP_WORD = gtk.WRAP_WORD
63
64 JUSTIFY_CENTER = gtk.JUSTIFY_CENTER
65 JUSTIFY_LEFT = gtk.JUSTIFY_LEFT
66
67 CONTROL_MASK = gdk.CONTROL_MASK
68 SHIFT_MASK = gdk.SHIFT_MASK
69 BUTTON1_MASK = gdk.BUTTON1_MASK
70
71 SCROLL_UP = gdk.SCROLL_UP
72 SCROLL_DOWN = gdk.SCROLL_DOWN
73
74 SPIN_USER_DEFINED = gtk.SPIN_USER_DEFINED
75
76 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER
77 FILE_CHOOSER_ACTION_OPEN = gtk.FILE_CHOOSER_ACTION_OPEN
78 FILE_CHOOSER_ACTION_SAVE = gtk.FILE_CHOOSER_ACTION_SAVE
79
80 SELECTION_MULTIPLE = gtk.SELECTION_MULTIPLE
81
82 SHADOW_IN = gtk.SHADOW_IN
83 SHADOW_NONE = gtk.SHADOW_NONE
84
85 POLICY_AUTOMATIC = gtk.POLICY_AUTOMATIC
86 POLICY_NEVER = gtk.POLICY_NEVER
87 POLICY_ALWAYS = gtk.POLICY_ALWAYS
88
89 WEIGHT_NORMAL = pango.WEIGHT_NORMAL
90 WEIGHT_BOLD = pango.WEIGHT_BOLD
91
92 WINDOW_STATE_ICONIFIED = gdk.WINDOW_STATE_ICONIFIED
93 WINDOW_STATE_WITHDRAWN = gdk.WINDOW_STATE_WITHDRAWN
94
95 SORT_ASCENDING = gtk.SORT_ASCENDING
96 SORT_DESCENDING = gtk.SORT_DESCENDING
97
98 EVENT_BUTTON_PRESS = gdk.BUTTON_PRESS
99
100 TREE_VIEW_COLUMN_FIXED = gtk.TREE_VIEW_COLUMN_FIXED
101
102 FILL = gtk.FILL
103 EXPAND = gtk.EXPAND
104
105 UPDATE_IF_VALID = gtk.UPDATE_IF_VALID
106
107 SELECTION_MULTIPLE = gtk.SELECTION_MULTIPLE
108
109 WINDOW_POPUP = gtk.WINDOW_POPUP
110
111 pixbuf_new_from_file = gdk.pixbuf_new_from_file
112
113 def text2unicode(text):
114 """Convert the given text, returned by a Gtk widget, to Unicode."""
115 return unicode(text)
116
117 def text2str(text):
118 """Convert the given text, returned by xstr to a string."""
119 return str(text)
120
121else: # pygobject
122 from gi.repository import Gdk as gdk
123 from gi.repository import GdkPixbuf as gdkPixbuf
124 from gi.repository import Gtk as gtk
125 from gi.repository import AppIndicator3 as appindicator
126 from gi.repository import Pango as pango
127
128 appIndicator = True
129
130
131 MESSAGETYPE_ERROR = gtk.MessageType.ERROR
132 MESSAGETYPE_QUESTION = gtk.MessageType.QUESTION
133 MESSAGETYPE_INFO = gtk.MessageType.INFO
134 RESPONSETYPE_NONE = gtk.ResponseType.NONE
135 RESPONSETYPE_OK = gtk.ResponseType.OK
136 RESPONSETYPE_YES = gtk.ResponseType.YES
137 RESPONSETYPE_NO = gtk.ResponseType.NO
138 RESPONSETYPE_ACCEPT = gtk.ResponseType.ACCEPT
139 RESPONSETYPE_REJECT = gtk.ResponseType.REJECT
140 RESPONSETYPE_CANCEL = gtk.ResponseType.CANCEL
141 ACCEL_VISIBLE = gtk.AccelFlags.VISIBLE
142 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
143 DIALOG_MODAL = gtk.DialogFlags.MODAL
144 WRAP_WORD = gtk.WrapMode.WORD
145 JUSTIFY_CENTER = gtk.Justification.CENTER
146 JUSTIFY_LEFT = gtk.Justification.LEFT
147
148 CONTROL_MASK = gdk.ModifierType.CONTROL_MASK
149 SHIFT_MASK = gdk.ModifierType.SHIFT_MASK
150 BUTTON1_MASK = gdk.ModifierType.BUTTON1_MASK
151
152 SCROLL_UP = gdk.ScrollDirection.UP
153 SCROLL_DOWN = gdk.ScrollDirection.DOWN
154
155 SPIN_USER_DEFINED = gtk.SpinType.USER_DEFINED
156
157 FILE_CHOOSER_ACTION_SELECT_FOLDER = gtk.FileChooserAction.SELECT_FOLDER
158 FILE_CHOOSER_ACTION_OPEN = gtk.FileChooserAction.OPEN
159 FILE_CHOOSER_ACTION_SAVE = gtk.FileChooserAction.SAVE
160
161 SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
162
163 SHADOW_IN = gtk.ShadowType.IN
164 SHADOW_NONE = gtk.ShadowType.NONE
165
166 POLICY_AUTOMATIC = gtk.PolicyType.AUTOMATIC
167 POLICY_NEVER = gtk.PolicyType.NEVER
168 POLICY_ALWAYS = gtk.PolicyType.ALWAYS
169
170 WEIGHT_NORMAL = pango.Weight.NORMAL
171 WEIGHT_BOLD = pango.Weight.BOLD
172
173 WINDOW_STATE_ICONIFIED = gdk.WindowState.ICONIFIED
174 WINDOW_STATE_WITHDRAWN = gdk.WindowState.WITHDRAWN
175
176 SORT_ASCENDING = gtk.SortType.ASCENDING
177 SORT_DESCENDING = gtk.SortType.DESCENDING
178
179 EVENT_BUTTON_PRESS = gdk.EventType.BUTTON_PRESS
180
181 TREE_VIEW_COLUMN_FIXED = gtk.TreeViewColumnSizing.FIXED
182
183 FILL = gtk.AttachOptions.FILL
184 EXPAND = gtk.AttachOptions.EXPAND
185
186 UPDATE_IF_VALID = gtk.SpinButtonUpdatePolicy.IF_VALID
187
188 SELECTION_MULTIPLE = gtk.SelectionMode.MULTIPLE
189
190 pixbuf_new_from_file = gdkPixbuf.Pixbuf.new_from_file
191
192 import codecs
193 _utf8Decoder = codecs.getdecoder("utf-8")
194
195 def text2unicode(str):
196 """Convert the given text, returned by a Gtk widget, to Unicode."""
197 return _utf8Decoder(str)[0]
198
199 def text2str(text):
200 """Convert the given text, returned by xstr to a string."""
201 return _utf8Decoder(text)[0]
202
203import cairo
204
205#------------------------------------------------------------------------------
206
207class FlightStatusHandler(object):
208 """Base class for objects that handle the flight status in some way."""
209 def __init__(self):
210 self._stage = None
211 self._rating = 100
212 self._noGoReason = None
213
214 def resetFlightStatus(self):
215 """Reset the flight status."""
216 self._stage = None
217 self._rating = 100
218 self._noGoReason = None
219 self._updateFlightStatus()
220
221 def setStage(self, stage):
222 """Set the stage of the flight."""
223 if stage!=self._stage:
224 self._stage = stage
225 self._updateFlightStatus()
226
227 def setRating(self, rating):
228 """Set the rating to the given value."""
229 if rating!=self._rating:
230 self._rating = rating
231 if self._noGoReason is None:
232 self._updateFlightStatus()
233
234 def setNoGo(self, reason):
235 """Set a No-Go condition with the given reason."""
236 if self._noGoReason is None:
237 self._noGoReason = reason
238 self._updateFlightStatus()
239
240#------------------------------------------------------------------------------
241
242class IntegerEntry(gtk.Entry):
243 """An entry that allows only either an empty value, or an integer."""
244 def __init__(self, defaultValue = None):
245 """Construct the entry."""
246 gtk.Entry.__init__(self)
247
248 self.set_alignment(1.0)
249
250 self._defaultValue = defaultValue
251 self._currentInteger = defaultValue
252 self._selfSetting = False
253 self._set_text()
254
255 self.connect("changed", self._handle_changed)
256
257 def get_int(self):
258 """Get the integer."""
259 return self._currentInteger
260
261 def reset(self):
262 """Reset the integer."""
263 self.set_int(None)
264
265 def set_int(self, value):
266 """Set the integer."""
267 if value!=self._currentInteger:
268 self._currentInteger = value
269 self.emit("integer-changed", self._currentInteger)
270 self._set_text()
271
272 def _handle_changed(self, widget):
273 """Handle the changed signal."""
274 if self._selfSetting:
275 return
276 text = self.get_text()
277 if text=="":
278 self.set_int(self._defaultValue)
279 else:
280 try:
281 self.set_int(int(text))
282 except:
283 self._set_text()
284
285 def _set_text(self):
286 """Set the text value from the current integer."""
287 self._selfSetting = True
288 self.set_text("" if self._currentInteger is None
289 else str(self._currentInteger))
290 self._selfSetting = False
291
292#------------------------------------------------------------------------------
293
294class TimeEntry(gtk.Entry):
295 """Widget to display and edit a time value in HH:MM format."""
296 def __init__(self):
297 """Construct the entry"""
298 super(TimeEntry, self).__init__(max = 5)
299
300 self.connect("insert-text", self._insertText)
301 self.connect("delete-text", self._deleteText)
302 self.connect("focus-out-event", self._focusOutEvent)
303
304 @property
305 def hour(self):
306 """Get the hour from the current text"""
307 text = self.get_text()
308 if not text or text==":":
309 return 0
310
311 words = text.split(":")
312 if len(words)==1:
313 return 0
314 elif len(words)>=2:
315 return 0 if len(words[0])==0 else int(words[0])
316 else:
317 return 0
318
319 @property
320 def minute(self):
321 """Get the hour from the current text"""
322 text = self.get_text()
323 if not text or text==":":
324 return 0
325
326 words = text.split(":")
327 if len(words)==1:
328 return 0 if len(words[0])==0 else int(words[0])
329 elif len(words)>=2:
330 return 0 if len(words[1])==0 else int(words[1])
331 else:
332 return 0
333
334 @property
335 def minutes(self):
336 """Get the time in minutes, i.e. hour*60+minute."""
337 return self.hour * 60 + self.minute
338
339 def setTimestamp(self, timestamp):
340 """Set the hour and minute from the given timestamp in UTC."""
341 tm = time.gmtime(timestamp)
342 self.set_text("%02d:%02d" % (tm.tm_hour, tm.tm_min))
343
344 def getTimestampFrom(self, timestamp):
345 """Get the timestamp by replacing the hour and minute from the given
346 timestamp with what is set in this widget."""
347 tm = time.gmtime(timestamp)
348 ts = calendar.timegm((tm.tm_year, tm.tm_mon, tm.tm_mday,
349 self.hour, self.minute, 0,
350 tm.tm_wday, tm.tm_yday, tm.tm_isdst))
351
352 if ts > (timestamp + (16*60*60)):
353 ts -= 24*60*60
354 elif (ts + 16*60*60) < timestamp:
355 ts += 24*60*60
356
357 return ts
358
359 def _focusOutEvent(self, widget, event):
360 """Reformat the text to match pattern HH:MM"""
361 text = "%02d:%02d" % (self.hour, self.minute)
362 if text!=self.get_text():
363 self.set_text(text)
364
365 def _insertText(self, entry, text, length, position):
366 """Called when some text is inserted into the entry."""
367 text=text[:length]
368 currentText = self.get_text()
369 position = self.get_position()
370 newText = currentText[:position] + text + currentText[position:]
371 self._checkText(newText, "insert-text")
372
373 def _deleteText(self, entry, start, end):
374 """Called when some text is erased from the entry."""
375 currentText = self.get_text()
376 newText = currentText[:start] + currentText[end:]
377 self._checkText(newText, "delete-text")
378
379 def _checkText(self, newText, signal):
380 """Check the given text.
381
382 If it is not suitable, stop the emission of the signal to prevent the
383 change from appearing."""
384 if not newText or newText==":":
385 return
386
387 words = newText.split(":")
388 if (len(words)==1 and
389 len(words[0])<=2 and (len(words[0])==0 or
390 (words[0].isdigit() and int(words[0])<60))) or \
391 (len(words)==2 and
392 len(words[0])<=2 and (len(words[0])==0 or
393 (words[0].isdigit() and int(words[0])<24)) and
394 len(words[1])<=2 and (len(words[1])==0 or
395 (words[1].isdigit() and int(words[1])<60))):
396 pass
397 else:
398 gtk.gdk.display_get_default().beep()
399 self.stop_emission(signal)
400
401#------------------------------------------------------------------------------
402
403class CredentialsDialog(gtk.Dialog):
404 """A dialog window to ask for a user name and a password."""
405 def __init__(self, gui, userName, password,
406 titleLabel, cancelButtonLabel, okButtonLabel,
407 userNameLabel, userNameTooltip,
408 passwordLabel, passwordTooltip,
409 infoText = None,
410 rememberPassword = None,
411 rememberLabel = None, rememberTooltip = None):
412 """Construct the dialog."""
413 super(CredentialsDialog, self).__init__(WINDOW_TITLE_BASE + " - " +
414 titleLabel,
415 gui.mainWindow,
416 DIALOG_MODAL)
417 self.add_button(cancelButtonLabel, RESPONSETYPE_CANCEL)
418 self.add_button(okButtonLabel, RESPONSETYPE_OK)
419
420 contentArea = self.get_content_area()
421
422 contentAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
423 xscale = 0.0, yscale = 0.0)
424 contentAlignment.set_padding(padding_top = 4, padding_bottom = 16,
425 padding_left = 8, padding_right = 8)
426
427 contentArea.pack_start(contentAlignment, False, False, 0)
428
429 contentVBox = gtk.VBox()
430 contentAlignment.add(contentVBox)
431
432 if infoText is not None:
433 label = gtk.Label(infoText)
434 label.set_alignment(0.0, 0.0)
435
436 contentVBox.pack_start(label, False, False, 0)
437
438 tableAlignment = gtk.Alignment(xalign = 0.5, yalign = 0.5,
439 xscale = 0.0, yscale = 0.0)
440 tableAlignment.set_padding(padding_top = 24, padding_bottom = 0,
441 padding_left = 0, padding_right = 0)
442
443 table = gtk.Table(3, 2)
444 table.set_row_spacings(4)
445 table.set_col_spacings(16)
446 table.set_homogeneous(False)
447
448 tableAlignment.add(table)
449 contentVBox.pack_start(tableAlignment, True, True, 0)
450
451 label = gtk.Label(userNameLabel)
452 label.set_use_underline(True)
453 label.set_alignment(0.0, 0.5)
454 table.attach(label, 0, 1, 0, 1)
455
456 self._userName = gtk.Entry()
457 self._userName.set_width_chars(16)
458 # FIXME: enabled the OK button only when there is something in thr
459 # user name and password fields
460 #self._userName.connect("changed",
461 # lambda button: self._updateForwardButton())
462 self._userName.set_tooltip_text(userNameTooltip)
463 self._userName.set_text(userName)
464 table.attach(self._userName, 1, 2, 0, 1)
465 label.set_mnemonic_widget(self._userName)
466
467 label = gtk.Label(passwordLabel)
468 label.set_use_underline(True)
469 label.set_alignment(0.0, 0.5)
470 table.attach(label, 0, 1, 1, 2)
471
472 self._password = gtk.Entry()
473 self._password.set_visibility(False)
474 #self._password.connect("changed",
475 # lambda button: self._updateForwardButton())
476 self._password.set_tooltip_text(passwordTooltip)
477 self._password.set_text(password)
478 table.attach(self._password, 1, 2, 1, 2)
479 label.set_mnemonic_widget(self._password)
480
481 if rememberPassword is not None:
482 self._rememberButton = gtk.CheckButton(rememberLabel)
483 self._rememberButton.set_use_underline(True)
484 self._rememberButton.set_tooltip_text(rememberTooltip)
485 self._rememberButton.set_active(rememberPassword)
486 table.attach(self._rememberButton, 1, 2, 2, 3, ypadding = 8)
487 else:
488 self._rememberButton = None
489
490 @property
491 def userName(self):
492 """Get the user name entered."""
493 return self._userName.get_text()
494
495 @property
496 def password(self):
497 """Get the password entered."""
498 return self._password.get_text()
499
500 @property
501 def rememberPassword(self):
502 """Get whether the password is to be remembered."""
503 return None if self._rememberButton is None \
504 else self._rememberButton.get_active()
505
506 def run(self):
507 """Run the dialog."""
508 self.show_all()
509
510 response = super(CredentialsDialog, self).run()
511
512 self.hide()
513
514 return response
515
516#------------------------------------------------------------------------------
517
518gobject.signal_new("integer-changed", IntegerEntry, gobject.SIGNAL_RUN_FIRST,
519 None, (object,))
520
521#------------------------------------------------------------------------------
522
523PROGRAM_NAME = "MAVA Logger X"
524
525WINDOW_TITLE_BASE = PROGRAM_NAME + " " + _const.VERSION
526if secondaryInstallation:
527 WINDOW_TITLE_BASE += " (" + xstr("secondary") + ")"
528
529#------------------------------------------------------------------------------
530
531# A mapping of aircraft types to their screen names
532aircraftNames = { _const.AIRCRAFT_B736 : xstr("aircraft_b736"),
533 _const.AIRCRAFT_B737 : xstr("aircraft_b737"),
534 _const.AIRCRAFT_B738 : xstr("aircraft_b738"),
535 _const.AIRCRAFT_B738C : xstr("aircraft_b738c"),
536 _const.AIRCRAFT_B732 : xstr("aircraft_b732"),
537 _const.AIRCRAFT_B733 : xstr("aircraft_b733"),
538 _const.AIRCRAFT_B734 : xstr("aircraft_b734"),
539 _const.AIRCRAFT_B735 : xstr("aircraft_b735"),
540 _const.AIRCRAFT_DH8D : xstr("aircraft_dh8d"),
541 _const.AIRCRAFT_B762 : xstr("aircraft_b762"),
542 _const.AIRCRAFT_B763 : xstr("aircraft_b763"),
543 _const.AIRCRAFT_CRJ2 : xstr("aircraft_crj2"),
544 _const.AIRCRAFT_F70 : xstr("aircraft_f70"),
545 _const.AIRCRAFT_DC3 : xstr("aircraft_dc3"),
546 _const.AIRCRAFT_T134 : xstr("aircraft_t134"),
547 _const.AIRCRAFT_T154 : xstr("aircraft_t154"),
548 _const.AIRCRAFT_YK40 : xstr("aircraft_yk40"),
549 _const.AIRCRAFT_B462 : xstr("aircraft_b462"),
550 _const.AIRCRAFT_IL62 : xstr("aircraft_il62") }
551
552#------------------------------------------------------------------------------
553
554aircraftFamilyNames = {
555 _const.AIRCRAFT_FAMILY_B737NG: xstr("aircraft_family_b737ng"),
556
557 _const.AIRCRAFT_FAMILY_B737CL: xstr("aircraft_family_b737cl"),
558
559 _const.AIRCRAFT_FAMILY_DH8D: xstr("aircraft_family_dh8d"),
560
561 _const.AIRCRAFT_FAMILY_B767: xstr("aircraft_family_b767"),
562
563 _const.AIRCRAFT_FAMILY_CRJ2: xstr("aircraft_family_crj2"),
564
565 _const.AIRCRAFT_FAMILY_F70: xstr("aircraft_family_f70"),
566
567 _const.AIRCRAFT_FAMILY_DC3: xstr("aircraft_family_dc3"),
568
569 _const.AIRCRAFT_FAMILY_T134: xstr("aircraft_family_t134"),
570
571 _const.AIRCRAFT_FAMILY_T154: xstr("aircraft_family_t154"),
572
573 _const.AIRCRAFT_FAMILY_YK40: xstr("aircraft_family_yk40"),
574
575 _const.AIRCRAFT_FAMILY_B462: xstr("aircraft_family_b462"),
576
577 _const.AIRCRAFT_FAMILY_IL62: xstr("aircraft_family_il62")
578}
579
580#------------------------------------------------------------------------------
581
582def formatFlightLogLine(timeStr, line):
583 """Format the given flight log line."""
584 """Format the given line for flight logging."""
585 if timeStr is not None:
586 line = timeStr + ": " + line
587 return line + "\n"
588
589#------------------------------------------------------------------------------
590
591def addFaultTag(buffer):
592 """Add a tag named 'fault' to the given buffer."""
593 buffer.create_tag("fault", foreground="red", weight=WEIGHT_BOLD)
594
595#------------------------------------------------------------------------------
596
597def appendTextBuffer(buffer, text, isFault = False):
598 """Append the given line at the end of the given text buffer.
599
600 If isFault is set, use the tag named 'fault'."""
601 insertTextBuffer(buffer, buffer.get_end_iter(), text, isFault)
602
603#------------------------------------------------------------------------------
604
605def insertTextBuffer(buffer, iter, text, isFault = False):
606 """Insert the given line into the given text buffer at the given iterator.
607
608 If isFault is set, use the tag named 'fault' else use the tag named
609 'normal'."""
610 line = iter.get_line()
611
612 buffer.insert(iter, text)
613
614 iter0 = buffer.get_iter_at_line(line)
615 iter1 = buffer.get_iter_at_line(line+1)
616 if isFault:
617 buffer.apply_tag_by_name("fault", iter0, iter1)
618 else:
619 buffer.remove_all_tags(iter0, iter1)
620
621#------------------------------------------------------------------------------
622
623def askYesNo(question, parent = None, title = WINDOW_TITLE_BASE):
624 """Ask a Yes/No question.
625
626 Return a boolean indicating the answer."""
627 dialog = gtk.MessageDialog(parent = parent,
628 type = MESSAGETYPE_QUESTION,
629 message_format = question)
630
631 dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
632 dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
633
634 dialog.set_title(title)
635 result = dialog.run()
636 dialog.hide()
637
638 return result==RESPONSETYPE_YES
639
640#------------------------------------------------------------------------------
641
642def errorDialog(message, parent = None, secondary = None,
643 title = WINDOW_TITLE_BASE):
644 """Display an error dialog box with the given message."""
645 dialog = gtk.MessageDialog(parent = parent,
646 type = MESSAGETYPE_ERROR,
647 message_format = message)
648 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
649 dialog.set_title(title)
650 if secondary is not None:
651 dialog.format_secondary_markup(secondary)
652
653 dialog.run()
654 dialog.hide()
655
656#------------------------------------------------------------------------------
657
658def communicationErrorDialog(parent = None, title = WINDOW_TITLE_BASE):
659 """Display a communication error dialog."""
660 errorDialog(xstr("error_communication"), parent = parent,
661 secondary = xstr("error_communication_secondary"),
662 title = title)
663
664#------------------------------------------------------------------------------
665
666def createFlightTypeComboBox():
667 flightTypeModel = gtk.ListStore(str, int)
668 for type in _const.flightTypes:
669 name = "flighttype_" + _const.flightType2string(type)
670 flightTypeModel.append([xstr(name), type])
671
672 flightType = gtk.ComboBox(model = flightTypeModel)
673 renderer = gtk.CellRendererText()
674 flightType.pack_start(renderer, True)
675 flightType.add_attribute(renderer, "text", 0)
676
677 return flightType
678
679#------------------------------------------------------------------------------
680
681def getTextViewText(textView):
682 """Get the text from the given text view."""
683 buffer = textView.get_buffer()
684 return buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), True)
685
686#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.