source: src/mlx/gui/gui.py@ 124:6633722f7f86

Last change on this file since 124:6633722f7f86 was 124:6633722f7f86, checked in by István Váradi <ivaradi@…>, 13 years ago

The buttons are now explicitly defined for message dialogs to avoid language problems

File size: 26.4 KB
Line 
1# The main file for the GUI
2
3from statusicon import StatusIcon
4from statusbar import Statusbar
5from info import FlightInfo
6from update import Updater
7from mlx.gui.common import *
8from mlx.gui.flight import Wizard
9from mlx.gui.monitor import MonitorWindow
10from mlx.gui.weighthelp import WeightHelp
11from mlx.gui.gates import FleetGateStatus
12from mlx.gui.prefs import Preferences
13
14import mlx.const as const
15import mlx.fs as fs
16import mlx.flight as flight
17import mlx.logger as logger
18import mlx.acft as acft
19import mlx.web as web
20from mlx.i18n import xstr
21
22import time
23import threading
24import sys
25
26#------------------------------------------------------------------------------
27
28class GUI(fs.ConnectionListener):
29 """The main GUI class."""
30 @staticmethod
31 def _formatFlightLogLine(timeStr, line):
32 """Format the given line for flight logging."""
33 if timeStr is not None:
34 line = timeStr + ": " + line
35 return line + "\n"
36
37 def __init__(self, programDirectory, config):
38 """Construct the GUI."""
39 gobject.threads_init()
40
41 self._programDirectory = programDirectory
42 self.config = config
43 self._connecting = False
44 self._reconnecting = False
45 self._connected = False
46 self._logger = logger.Logger(self)
47 self._flight = None
48 self._simulator = None
49 self._monitoring = False
50 self._fleet = None
51 self._fleetCallback = None
52
53 self._stdioLock = threading.Lock()
54 self._stdioText = ""
55
56 self.webHandler = web.Handler()
57 self.webHandler.start()
58
59 self.toRestart = False
60
61 def build(self, iconDirectory):
62 """Build the GUI."""
63
64 self._mainWindow = window = gtk.Window()
65 window.set_title(WINDOW_TITLE_BASE)
66 window.set_icon_from_file(os.path.join(iconDirectory, "logo.ico"))
67 window.connect("delete-event",
68 lambda a, b: self.hideMainWindow())
69 window.connect("window-state-event", self._handleMainWindowState)
70 accelGroup = gtk.AccelGroup()
71 window.add_accel_group(accelGroup)
72
73 mainVBox = gtk.VBox()
74 window.add(mainVBox)
75
76 self._preferences = Preferences(self)
77
78 menuBar = self._buildMenuBar(accelGroup)
79 mainVBox.pack_start(menuBar, False, False, 0)
80
81 self._notebook = gtk.Notebook()
82 mainVBox.pack_start(self._notebook, True, True, 4)
83
84 self._wizard = Wizard(self)
85 label = gtk.Label(xstr("tab_flight"))
86 label.set_use_underline(True)
87 label.set_tooltip_text(xstr("tab_flight_tooltip"))
88 self._notebook.append_page(self._wizard, label)
89
90 self._flightInfo = FlightInfo(self)
91 label = gtk.Label(xstr("tab_flight_info"))
92 label.set_use_underline(True)
93 label.set_tooltip_text(xstr("tab_flight_info_tooltip"))
94 self._notebook.append_page(self._flightInfo, label)
95 self._flightInfo.disable()
96
97 self._weightHelp = WeightHelp(self)
98 label = gtk.Label(xstr("tab_weight_help"))
99 label.set_use_underline(True)
100 label.set_tooltip_text(xstr("tab_weight_help_tooltip"))
101 self._notebook.append_page(self._weightHelp, label)
102
103 (logWidget, self._logView) = self._buildLogWidget()
104 label = gtk.Label(xstr("tab_log"))
105 label.set_use_underline(True)
106 label.set_tooltip_text(xstr("tab_log_tooltip"))
107 self._notebook.append_page(logWidget, label)
108
109 self._fleetGateStatus = FleetGateStatus(self)
110 label = gtk.Label(xstr("tab_gates"))
111 label.set_use_underline(True)
112 label.set_tooltip_text(xstr("tab_gates_tooltip"))
113 self._notebook.append_page(self._fleetGateStatus, label)
114
115 (self._debugLogWidget, self._debugLogView) = self._buildLogWidget()
116 self._debugLogWidget.show_all()
117
118 mainVBox.pack_start(gtk.HSeparator(), False, False, 0)
119
120 self._statusbar = Statusbar()
121 mainVBox.pack_start(self._statusbar, False, False, 0)
122
123 self._notebook.connect("switch-page", self._notebookPageSwitch)
124
125 self._monitorWindow = MonitorWindow(self, iconDirectory)
126 self._monitorWindow.add_accel_group(accelGroup)
127 self._monitorWindowX = None
128 self._monitorWindowY = None
129 self._selfToggling = False
130
131 window.show_all()
132 self._wizard.grabDefault()
133 self._weightHelp.reset()
134 self._weightHelp.disable()
135
136 self._statusIcon = StatusIcon(iconDirectory, self)
137
138 self._busyCursor = gdk.Cursor(gdk.CursorType.WATCH if pygobject
139 else gdk.WATCH)
140
141 @property
142 def mainWindow(self):
143 """Get the main window of the GUI."""
144 return self._mainWindow
145
146 @property
147 def logger(self):
148 """Get the logger used by us."""
149 return self._logger
150
151 @property
152 def simulator(self):
153 """Get the simulator used by us."""
154 return self._simulator
155
156 @property
157 def flight(self):
158 """Get the flight being performed."""
159 return self._flight
160
161 @property
162 def bookedFlight(self):
163 """Get the booked flight selected, if any."""
164 return self._wizard.bookedFlight
165
166 @property
167 def cargoWeight(self):
168 """Get the cargo weight."""
169 return self._wizard.cargoWeight
170
171 @property
172 def zfw(self):
173 """Get Zero-Fuel Weight calculated for the current flight."""
174 return self._wizard.zfw
175
176 @property
177 def filedCruiseAltitude(self):
178 """Get cruise altitude filed for the current flight."""
179 return self._wizard.filedCruiseAltitude
180
181 @property
182 def cruiseAltitude(self):
183 """Get cruise altitude set for the current flight."""
184 return self._wizard.cruiseAltitude
185
186 @property
187 def route(self):
188 """Get the flight route."""
189 return self._wizard.route
190
191 @property
192 def departureMETAR(self):
193 """Get the METAR of the deprature airport."""
194 return self._wizard.departureMETAR
195
196 @property
197 def arrivalMETAR(self):
198 """Get the METAR of the deprature airport."""
199 return self._wizard.arrivalMETAR
200
201 @property
202 def departureRunway(self):
203 """Get the name of the departure runway."""
204 return self._wizard.departureRunway
205
206 @property
207 def sid(self):
208 """Get the SID."""
209 return self._wizard.sid
210
211 @property
212 def v1(self):
213 """Get the V1 speed calculated for the flight."""
214 return self._wizard.v1
215
216 @property
217 def vr(self):
218 """Get the Vr speed calculated for the flight."""
219 return self._wizard.vr
220
221 @property
222 def v2(self):
223 """Get the V2 speed calculated for the flight."""
224 return self._wizard.v2
225
226 @property
227 def arrivalRunway(self):
228 """Get the arrival runway."""
229 return self._wizard.arrivalRunway
230
231 @property
232 def star(self):
233 """Get the STAR."""
234 return self._wizard.star
235
236 @property
237 def transition(self):
238 """Get the transition."""
239 return self._wizard.transition
240
241 @property
242 def approachType(self):
243 """Get the approach type."""
244 return self._wizard.approachType
245
246 @property
247 def vref(self):
248 """Get the Vref speed calculated for the flight."""
249 return self._wizard.vref
250
251 @property
252 def flightType(self):
253 """Get the flight type."""
254 return self._wizard.flightType
255
256 @property
257 def online(self):
258 """Get whether the flight was online or not."""
259 return self._wizard.online
260
261 @property
262 def comments(self):
263 """Get the comments."""
264 return self._flightInfo.comments
265
266 @property
267 def flightDefects(self):
268 """Get the flight defects."""
269 return self._flightInfo.flightDefects
270
271 @property
272 def delayCodes(self):
273 """Get the delay codes."""
274 return self._flightInfo.delayCodes
275
276 def run(self):
277 """Run the GUI."""
278 if self.config.autoUpdate:
279 self._updater = Updater(self,
280 self._programDirectory,
281 self.config.updateURL,
282 self._mainWindow)
283 self._updater.start()
284
285 gtk.main()
286
287 self._disconnect()
288
289 def connected(self, fsType, descriptor):
290 """Called when we have connected to the simulator."""
291 self._connected = True
292 self._logger.untimedMessage("Connected to the simulator %s" % (descriptor,))
293 gobject.idle_add(self._handleConnected, fsType, descriptor)
294
295 def _handleConnected(self, fsType, descriptor):
296 """Called when the connection to the simulator has succeeded."""
297 self._statusbar.updateConnection(self._connecting, self._connected)
298 self.endBusy()
299 if not self._reconnecting:
300 self._wizard.connected(fsType, descriptor)
301 self._reconnecting = False
302
303 def connectionFailed(self):
304 """Called when the connection failed."""
305 self._logger.untimedMessage("Connection to the simulator failed")
306 gobject.idle_add(self._connectionFailed)
307
308 def _connectionFailed(self):
309 """Called when the connection failed."""
310 self.endBusy()
311 self._statusbar.updateConnection(self._connecting, self._connected)
312
313 dialog = gtk.MessageDialog(parent = self._mainWindow,
314 type = MESSAGETYPE_ERROR,
315 message_format = xstr("conn_failed"))
316
317 dialog.set_title(WINDOW_TITLE_BASE)
318 dialog.format_secondary_markup(xstr("conn_failed_sec"))
319
320 dialog.add_button(xstr("button_cancel"), 0)
321 dialog.add_button(xstr("button_tryagain"), 1)
322 dialog.set_default_response(1)
323
324 result = dialog.run()
325 dialog.hide()
326 if result == 1:
327 self.beginBusy(xstr("connect_busy"))
328 self._simulator.reconnect()
329 else:
330 self.reset()
331
332 def disconnected(self):
333 """Called when we have disconnected from the simulator."""
334 self._connected = False
335 self._logger.untimedMessage("Disconnected from the simulator")
336
337 gobject.idle_add(self._disconnected)
338
339 def _disconnected(self):
340 """Called when we have disconnected from the simulator unexpectedly."""
341 self._statusbar.updateConnection(self._connecting, self._connected)
342
343 dialog = gtk.MessageDialog(type = MESSAGETYPE_ERROR,
344 message_format = xstr("conn_broken"),
345 parent = self._mainWindow)
346 dialog.set_title(WINDOW_TITLE_BASE)
347 dialog.format_secondary_markup(xstr("conn_broken_sec"))
348
349 dialog.add_button(xstr("button_cancel"), 0)
350 dialog.add_button(xstr("button_reconnect"), 1)
351 dialog.set_default_response(1)
352
353 result = dialog.run()
354 dialog.hide()
355 if result == 1:
356 self.beginBusy(xstr("connect_busy"))
357 self._reconnecting = True
358 self._simulator.reconnect()
359 else:
360 self.reset()
361
362 def enableFlightInfo(self):
363 """Enable the flight info tab."""
364 self._flightInfo.enable()
365
366 def reset(self):
367 """Reset the GUI."""
368 self._disconnect()
369
370 self._flightInfo.reset()
371 self._flightInfo.disable()
372 self.resetFlightStatus()
373
374 self._weightHelp.reset()
375 self._weightHelp.disable()
376 self._wizard.reset()
377 self._notebook.set_current_page(0)
378
379 self._logView.get_buffer().set_text("")
380
381 def _disconnect(self):
382 """Disconnect from the simulator if connected."""
383 self.stopMonitoring()
384
385 if self._connected:
386 self._flight.simulator.disconnect()
387 self._connected = False
388
389 self._connecting = False
390 self._reconnecting = False
391 self._statusbar.updateConnection(False, False)
392
393 def addFlightLogLine(self, timeStr, line):
394 """Write the given message line to the log."""
395 gobject.idle_add(self._writeLog,
396 GUI._formatFlightLogLine(timeStr, line),
397 self._logView)
398
399 def updateFlightLogLine(self, index, timeStr, line):
400 """Update the line with the given index."""
401 gobject.idle_add(self._updateFlightLogLine, index,
402 GUI._formatFlightLogLine(timeStr, line))
403
404 def _updateFlightLogLine(self, index, line):
405 """Replace the contents of the given line in the log."""
406 buffer = self._logView.get_buffer()
407 startIter = buffer.get_iter_at_line(index)
408 endIter = buffer.get_iter_at_line(index + 1)
409 buffer.delete(startIter, endIter)
410 buffer.insert(startIter, line)
411 self._logView.scroll_mark_onscreen(buffer.get_insert())
412
413 def check(self, flight, aircraft, logger, oldState, state):
414 """Update the data."""
415 gobject.idle_add(self._monitorWindow.setData, state)
416 gobject.idle_add(self._statusbar.updateTime, state.timestamp)
417
418 def resetFlightStatus(self):
419 """Reset the status of the flight."""
420 self._statusbar.resetFlightStatus()
421 self._statusbar.updateTime()
422 self._statusIcon.resetFlightStatus()
423
424 def setStage(self, stage):
425 """Set the stage of the flight."""
426 gobject.idle_add(self._setStage, stage)
427
428 def _setStage(self, stage):
429 """Set the stage of the flight."""
430 self._statusbar.setStage(stage)
431 self._statusIcon.setStage(stage)
432 self._wizard.setStage(stage)
433 if stage==const.STAGE_END:
434 self._disconnect()
435
436 def setRating(self, rating):
437 """Set the rating of the flight."""
438 gobject.idle_add(self._setRating, rating)
439
440 def _setRating(self, rating):
441 """Set the rating of the flight."""
442 self._statusbar.setRating(rating)
443 self._statusIcon.setRating(rating)
444
445 def setNoGo(self, reason):
446 """Set the rating of the flight to No-Go with the given reason."""
447 gobject.idle_add(self._setNoGo, reason)
448
449 def _setNoGo(self, reason):
450 """Set the rating of the flight."""
451 self._statusbar.setNoGo(reason)
452 self._statusIcon.setNoGo(reason)
453
454 def _handleMainWindowState(self, window, event):
455 """Hande a change in the state of the window"""
456 iconified = gdk.WindowState.ICONIFIED if pygobject \
457 else gdk.WINDOW_STATE_ICONIFIED
458 if (event.changed_mask&iconified)!=0 and (event.new_window_state&iconified)!=0:
459 self.hideMainWindow(savePosition = False)
460
461 def hideMainWindow(self, savePosition = True):
462 """Hide the main window and save its position."""
463 if savePosition:
464 (self._mainWindowX, self._mainWindowY) = \
465 self._mainWindow.get_window().get_root_origin()
466 else:
467 self._mainWindowX = self._mainWindowY = None
468 self._mainWindow.hide()
469 self._statusIcon.mainWindowHidden()
470 return True
471
472 def showMainWindow(self):
473 """Show the main window at its former position."""
474 if self._mainWindowX is not None and self._mainWindowY is not None:
475 self._mainWindow.move(self._mainWindowX, self._mainWindowY)
476
477 self._mainWindow.show()
478 self._mainWindow.deiconify()
479
480 self._statusIcon.mainWindowShown()
481
482 def toggleMainWindow(self):
483 """Toggle the main window."""
484 if self._mainWindow.get_visible():
485 self.hideMainWindow()
486 else:
487 self.showMainWindow()
488
489 def hideMonitorWindow(self, savePosition = True):
490 """Hide the monitor window."""
491 if savePosition:
492 (self._monitorWindowX, self._monitorWindowY) = \
493 self._monitorWindow.get_window().get_root_origin()
494 else:
495 self._monitorWindowX = self._monitorWindowY = None
496 self._monitorWindow.hide()
497 self._statusIcon.monitorWindowHidden()
498 if self._showMonitorMenuItem.get_active():
499 self._selfToggling = True
500 self._showMonitorMenuItem.set_active(False)
501 return True
502
503 def showMonitorWindow(self):
504 """Show the monitor window."""
505 if self._monitorWindowX is not None and self._monitorWindowY is not None:
506 self._monitorWindow.move(self._monitorWindowX, self._monitorWindowY)
507 self._monitorWindow.show_all()
508 self._statusIcon.monitorWindowShown()
509 if not self._showMonitorMenuItem.get_active():
510 self._selfToggling = True
511 self._showMonitorMenuItem.set_active(True)
512
513 def _toggleMonitorWindow(self, menuItem):
514 if self._selfToggling:
515 self._selfToggling = False
516 elif self._monitorWindow.get_visible():
517 self.hideMonitorWindow()
518 else:
519 self.showMonitorWindow()
520
521 def restart(self):
522 """Quit and restart the application."""
523 self.toRestart = True
524 self._quit(force = True)
525
526 def flushStdIO(self):
527 """Flush any text to the standard error that could not be logged."""
528 if self._stdioText:
529 sys.__stderr__.write(self._stdioText)
530
531 def writeStdIO(self, text):
532 """Write the given text into standard I/O log."""
533 with self._stdioLock:
534 self._stdioText += text
535
536 gobject.idle_add(self._writeStdIO)
537
538 def beginBusy(self, message):
539 """Begin a period of background processing."""
540 self._wizard.set_sensitive(False)
541 self._weightHelp.set_sensitive(False)
542 self._mainWindow.get_window().set_cursor(self._busyCursor)
543 self._statusbar.updateBusyState(message)
544
545 def endBusy(self):
546 """End a period of background processing."""
547 self._mainWindow.get_window().set_cursor(None)
548 self._weightHelp.set_sensitive(True)
549 self._wizard.set_sensitive(True)
550 self._statusbar.updateBusyState(None)
551
552 def initializeWeightHelp(self):
553 """Initialize the weight help tab."""
554 self._weightHelp.reset()
555 self._weightHelp.enable()
556
557 def getFleet(self, callback = None, force = False):
558 """Get the fleet.
559
560 If force is False, and we already have a fleet retrieved,
561 that one will be used."""
562 if self._fleet is None or force:
563 self._fleetCallback = callback
564 self.beginBusy(xstr("fleet_busy"))
565 self.webHandler.getFleet(self._fleetResultCallback)
566 else:
567 callback(self._fleet)
568
569 def _fleetResultCallback(self, returned, result):
570 """Called when the fleet has been queried."""
571 gobject.idle_add(self._handleFleetResult, returned, result)
572
573 def _handleFleetResult(self, returned, result):
574 """Handle the fleet result."""
575 self.endBusy()
576 if returned:
577 self._fleet = result.fleet
578 else:
579 self._fleet = None
580
581 dialog = gtk.MessageDialog(parent = self.mainWindow,
582 type = MESSAGETYPE_ERROR,
583 message_format = xstr("fleet_failed"))
584 dialog.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
585 dialog.set_title(WINDOW_TITLE_BASE)
586 dialog.run()
587 dialog.hide()
588
589 if self._fleetCallback is not None:
590 self._fleetCallback(self._fleet)
591 self._fleetCallback = None
592 self._fleetGateStatus.handleFleet(self._fleet)
593
594 def _writeStdIO(self):
595 """Perform the real writing."""
596 with self._stdioLock:
597 text = self._stdioText
598 self._stdioText = ""
599 if not text: return
600
601 lines = text.splitlines()
602 if text[-1]=="\n":
603 text = ""
604 else:
605 text = lines[-1]
606 lines = lines[:-1]
607
608 for line in lines:
609 #print >> sys.__stdout__, line
610 self._writeLog(line + "\n", self._debugLogView)
611
612 if text:
613 #print >> sys.__stdout__, text,
614 self._writeLog(text, self._debugLogView)
615
616 def connectSimulator(self, aircraftType):
617 """Connect to the simulator for the first time."""
618 self._logger.reset()
619
620 self._flight = flight.Flight(self._logger, self)
621 self._flight.aircraftType = aircraftType
622 self._flight.aircraft = acft.Aircraft.create(self._flight)
623 self._flight.aircraft._checkers.append(self)
624
625 if self._simulator is None:
626 self._simulator = fs.createSimulator(const.SIM_MSFS9, self)
627
628 self._flight.simulator = self._simulator
629
630 self.beginBusy(xstr("connect_busy"))
631 self._statusbar.updateConnection(self._connecting, self._connected)
632
633 self._connecting = True
634 self._simulator.connect(self._flight.aircraft)
635
636 def startMonitoring(self):
637 """Start monitoring."""
638 if not self._monitoring:
639 self.simulator.startMonitoring()
640 self._monitoring = True
641
642 def stopMonitoring(self):
643 """Stop monitoring."""
644 if self._monitoring:
645 self.simulator.stopMonitoring()
646 self._monitoring = False
647
648 def _buildMenuBar(self, accelGroup):
649 """Build the main menu bar."""
650 menuBar = gtk.MenuBar()
651
652 fileMenuItem = gtk.MenuItem(xstr("menu_file"))
653 fileMenu = gtk.Menu()
654 fileMenuItem.set_submenu(fileMenu)
655 menuBar.append(fileMenuItem)
656
657 quitMenuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
658 quitMenuItem.set_use_stock(True)
659 quitMenuItem.set_label(xstr("menu_file_quit"))
660 quitMenuItem.add_accelerator("activate", accelGroup,
661 ord(xstr("menu_file_quit_key")),
662 CONTROL_MASK, ACCEL_VISIBLE)
663 quitMenuItem.connect("activate", self._quit)
664 fileMenu.append(quitMenuItem)
665
666 toolsMenuItem = gtk.MenuItem(xstr("menu_tools"))
667 toolsMenu = gtk.Menu()
668 toolsMenuItem.set_submenu(toolsMenu)
669 menuBar.append(toolsMenuItem)
670
671 prefsMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
672 prefsMenuItem.set_use_stock(True)
673 prefsMenuItem.set_label(xstr("menu_tools_prefs"))
674 prefsMenuItem.add_accelerator("activate", accelGroup,
675 ord(xstr("menu_tools_prefs_key")),
676 CONTROL_MASK, ACCEL_VISIBLE)
677 prefsMenuItem.connect("activate", self._editPreferences)
678 toolsMenu.append(prefsMenuItem)
679
680 viewMenuItem = gtk.MenuItem(xstr("menu_view"))
681 viewMenu = gtk.Menu()
682 viewMenuItem.set_submenu(viewMenu)
683 menuBar.append(viewMenuItem)
684
685 self._showMonitorMenuItem = gtk.CheckMenuItem()
686 self._showMonitorMenuItem.set_label(xstr("menu_view_monitor"))
687 self._showMonitorMenuItem.set_use_underline(True)
688 self._showMonitorMenuItem.set_active(False)
689 self._showMonitorMenuItem.add_accelerator("activate", accelGroup,
690 ord(xstr("menu_view_monitor_key")),
691 CONTROL_MASK, ACCEL_VISIBLE)
692 self._showMonitorMenuItem.connect("toggled", self._toggleMonitorWindow)
693 viewMenu.append(self._showMonitorMenuItem)
694
695 showDebugMenuItem = gtk.CheckMenuItem()
696 showDebugMenuItem.set_label(xstr("menu_view_debug"))
697 showDebugMenuItem.set_use_underline(True)
698 showDebugMenuItem.set_active(False)
699 showDebugMenuItem.add_accelerator("activate", accelGroup,
700 ord(xstr("menu_view_debug_key")),
701 CONTROL_MASK, ACCEL_VISIBLE)
702 showDebugMenuItem.connect("toggled", self._toggleDebugLog)
703 viewMenu.append(showDebugMenuItem)
704
705 return menuBar
706
707 def _toggleDebugLog(self, menuItem):
708 """Toggle the debug log."""
709 if menuItem.get_active():
710 label = gtk.Label(xstr("tab_debug_log"))
711 label.set_use_underline(True)
712 label.set_tooltip_text(xstr("tab_debug_log_tooltip"))
713 self._debugLogPage = self._notebook.append_page(self._debugLogWidget, label)
714 self._notebook.set_current_page(self._debugLogPage)
715 else:
716 self._notebook.remove_page(self._debugLogPage)
717
718 def _buildLogWidget(self):
719 """Build the widget for the log."""
720 alignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
721
722 alignment.set_padding(padding_top = 8, padding_bottom = 8,
723 padding_left = 16, padding_right = 16)
724
725 logScroller = gtk.ScrolledWindow()
726 # FIXME: these should be constants in common
727 logScroller.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
728 else gtk.POLICY_AUTOMATIC,
729 gtk.PolicyType.AUTOMATIC if pygobject
730 else gtk.POLICY_AUTOMATIC)
731 logScroller.set_shadow_type(gtk.ShadowType.IN if pygobject
732 else gtk.SHADOW_IN)
733 logView = gtk.TextView()
734 logView.set_editable(False)
735 logScroller.add(logView)
736
737 logBox = gtk.VBox()
738 logBox.pack_start(logScroller, True, True, 0)
739 logBox.set_size_request(-1, 200)
740
741 alignment.add(logBox)
742
743 return (alignment, logView)
744
745 def _writeLog(self, msg, logView):
746 """Write the given message to the log."""
747 buffer = logView.get_buffer()
748 buffer.insert(buffer.get_end_iter(), msg)
749 logView.scroll_mark_onscreen(buffer.get_insert())
750
751 def _quit(self, what = None, force = False):
752 """Quit from the application."""
753 if force:
754 result=RESPONSETYPE_YES
755 else:
756 dialog = gtk.MessageDialog(parent = self._mainWindow,
757 type = MESSAGETYPE_QUESTION,
758 message_format = xstr("quit_question"))
759
760 dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
761 dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
762
763 dialog.set_title(WINDOW_TITLE_BASE)
764 result = dialog.run()
765 dialog.hide()
766
767 if result==RESPONSETYPE_YES:
768 self._statusIcon.destroy()
769 return gtk.main_quit()
770
771 def _notebookPageSwitch(self, notebook, page, page_num):
772 """Called when the current page of the notebook has changed."""
773 if page_num==0:
774 gobject.idle_add(self._wizard.grabDefault)
775 else:
776 self._mainWindow.set_default(None)
777
778 def _editPreferences(self, menuItem):
779 """Callback for editing the preferences."""
780 self._preferences.run(self.config)
Note: See TracBrowser for help on using the repository browser.