source: src/mlx/gui/gui.py@ 129:dcca616a78ca

Last change on this file since 129:dcca616a78ca was 128:e14fcd9d9215, checked in by István Váradi <ivaradi@…>, 13 years ago

Various small fixes

File size: 26.5 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 self._weightHelp.disable()
393
394 def addFlightLogLine(self, timeStr, line):
395 """Write the given message line to the log."""
396 gobject.idle_add(self._writeLog,
397 GUI._formatFlightLogLine(timeStr, line),
398 self._logView)
399
400 def updateFlightLogLine(self, index, timeStr, line):
401 """Update the line with the given index."""
402 gobject.idle_add(self._updateFlightLogLine, index,
403 GUI._formatFlightLogLine(timeStr, line))
404
405 def _updateFlightLogLine(self, index, line):
406 """Replace the contents of the given line in the log."""
407 buffer = self._logView.get_buffer()
408 startIter = buffer.get_iter_at_line(index)
409 endIter = buffer.get_iter_at_line(index + 1)
410 buffer.delete(startIter, endIter)
411 buffer.insert(startIter, line)
412 self._logView.scroll_mark_onscreen(buffer.get_insert())
413
414 def check(self, flight, aircraft, logger, oldState, state):
415 """Update the data."""
416 gobject.idle_add(self._monitorWindow.setData, state)
417 gobject.idle_add(self._statusbar.updateTime, state.timestamp)
418
419 def resetFlightStatus(self):
420 """Reset the status of the flight."""
421 self._statusbar.resetFlightStatus()
422 self._statusbar.updateTime()
423 self._statusIcon.resetFlightStatus()
424
425 def setStage(self, stage):
426 """Set the stage of the flight."""
427 gobject.idle_add(self._setStage, stage)
428
429 def _setStage(self, stage):
430 """Set the stage of the flight."""
431 self._statusbar.setStage(stage)
432 self._statusIcon.setStage(stage)
433 self._wizard.setStage(stage)
434 if stage==const.STAGE_END:
435 self._disconnect()
436
437 def setRating(self, rating):
438 """Set the rating of the flight."""
439 gobject.idle_add(self._setRating, rating)
440
441 def _setRating(self, rating):
442 """Set the rating of the flight."""
443 self._statusbar.setRating(rating)
444 self._statusIcon.setRating(rating)
445
446 def setNoGo(self, reason):
447 """Set the rating of the flight to No-Go with the given reason."""
448 gobject.idle_add(self._setNoGo, reason)
449
450 def _setNoGo(self, reason):
451 """Set the rating of the flight."""
452 self._statusbar.setNoGo(reason)
453 self._statusIcon.setNoGo(reason)
454
455 def _handleMainWindowState(self, window, event):
456 """Hande a change in the state of the window"""
457 iconified = gdk.WindowState.ICONIFIED if pygobject \
458 else gdk.WINDOW_STATE_ICONIFIED
459 if (event.changed_mask&iconified)!=0 and (event.new_window_state&iconified)!=0:
460 self.hideMainWindow(savePosition = False)
461
462 def hideMainWindow(self, savePosition = True):
463 """Hide the main window and save its position."""
464 if savePosition:
465 (self._mainWindowX, self._mainWindowY) = \
466 self._mainWindow.get_window().get_root_origin()
467 else:
468 self._mainWindowX = self._mainWindowY = None
469 self._mainWindow.hide()
470 self._statusIcon.mainWindowHidden()
471 return True
472
473 def showMainWindow(self):
474 """Show the main window at its former position."""
475 if self._mainWindowX is not None and self._mainWindowY is not None:
476 self._mainWindow.move(self._mainWindowX, self._mainWindowY)
477
478 self._mainWindow.show()
479 self._mainWindow.deiconify()
480
481 self._statusIcon.mainWindowShown()
482
483 def toggleMainWindow(self):
484 """Toggle the main window."""
485 if self._mainWindow.get_visible():
486 self.hideMainWindow()
487 else:
488 self.showMainWindow()
489
490 def hideMonitorWindow(self, savePosition = True):
491 """Hide the monitor window."""
492 if savePosition:
493 (self._monitorWindowX, self._monitorWindowY) = \
494 self._monitorWindow.get_window().get_root_origin()
495 else:
496 self._monitorWindowX = self._monitorWindowY = None
497 self._monitorWindow.hide()
498 self._statusIcon.monitorWindowHidden()
499 if self._showMonitorMenuItem.get_active():
500 self._selfToggling = True
501 self._showMonitorMenuItem.set_active(False)
502 return True
503
504 def showMonitorWindow(self):
505 """Show the monitor window."""
506 if self._monitorWindowX is not None and self._monitorWindowY is not None:
507 self._monitorWindow.move(self._monitorWindowX, self._monitorWindowY)
508 self._monitorWindow.show_all()
509 self._statusIcon.monitorWindowShown()
510 if not self._showMonitorMenuItem.get_active():
511 self._selfToggling = True
512 self._showMonitorMenuItem.set_active(True)
513
514 def _toggleMonitorWindow(self, menuItem):
515 if self._selfToggling:
516 self._selfToggling = False
517 elif self._monitorWindow.get_visible():
518 self.hideMonitorWindow()
519 else:
520 self.showMonitorWindow()
521
522 def restart(self):
523 """Quit and restart the application."""
524 self.toRestart = True
525 self._quit(force = True)
526
527 def flushStdIO(self):
528 """Flush any text to the standard error that could not be logged."""
529 if self._stdioText:
530 sys.__stderr__.write(self._stdioText)
531
532 def writeStdIO(self, text):
533 """Write the given text into standard I/O log."""
534 with self._stdioLock:
535 self._stdioText += text
536
537 gobject.idle_add(self._writeStdIO)
538
539 def beginBusy(self, message):
540 """Begin a period of background processing."""
541 self._wizard.set_sensitive(False)
542 self._weightHelp.set_sensitive(False)
543 self._mainWindow.get_window().set_cursor(self._busyCursor)
544 self._statusbar.updateBusyState(message)
545
546 def endBusy(self):
547 """End a period of background processing."""
548 self._mainWindow.get_window().set_cursor(None)
549 self._weightHelp.set_sensitive(True)
550 self._wizard.set_sensitive(True)
551 self._statusbar.updateBusyState(None)
552
553 def initializeWeightHelp(self):
554 """Initialize the weight help tab."""
555 self._weightHelp.reset()
556 self._weightHelp.enable()
557
558 def getFleet(self, callback = None, force = False):
559 """Get the fleet.
560
561 If force is False, and we already have a fleet retrieved,
562 that one will be used."""
563 if self._fleet is None or force:
564 self._fleetCallback = callback
565 self.beginBusy(xstr("fleet_busy"))
566 self.webHandler.getFleet(self._fleetResultCallback)
567 else:
568 callback(self._fleet)
569
570 def _fleetResultCallback(self, returned, result):
571 """Called when the fleet has been queried."""
572 gobject.idle_add(self._handleFleetResult, returned, result)
573
574 def _handleFleetResult(self, returned, result):
575 """Handle the fleet result."""
576 self.endBusy()
577 if returned:
578 self._fleet = result.fleet
579 else:
580 self._fleet = None
581
582 dialog = gtk.MessageDialog(parent = self.mainWindow,
583 type = MESSAGETYPE_ERROR,
584 message_format = xstr("fleet_failed"))
585 dialog.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
586 dialog.set_title(WINDOW_TITLE_BASE)
587 dialog.run()
588 dialog.hide()
589
590 if self._fleetCallback is not None:
591 self._fleetCallback(self._fleet)
592 self._fleetCallback = None
593 self._fleetGateStatus.handleFleet(self._fleet)
594
595 def _writeStdIO(self):
596 """Perform the real writing."""
597 with self._stdioLock:
598 text = self._stdioText
599 self._stdioText = ""
600 if not text: return
601
602 lines = text.splitlines()
603 if text[-1]=="\n":
604 text = ""
605 else:
606 text = lines[-1]
607 lines = lines[:-1]
608
609 for line in lines:
610 #print >> sys.__stdout__, line
611 self._writeLog(line + "\n", self._debugLogView)
612
613 if text:
614 #print >> sys.__stdout__, text,
615 self._writeLog(text, self._debugLogView)
616
617 def connectSimulator(self, aircraftType):
618 """Connect to the simulator for the first time."""
619 self._logger.reset()
620
621 self._flight = flight.Flight(self._logger, self)
622 self._flight.aircraftType = aircraftType
623 self._flight.aircraft = acft.Aircraft.create(self._flight)
624 self._flight.aircraft._checkers.append(self)
625
626 if self._simulator is None:
627 self._simulator = fs.createSimulator(const.SIM_MSFS9, self)
628
629 self._flight.simulator = self._simulator
630
631 self.beginBusy(xstr("connect_busy"))
632 self._statusbar.updateConnection(self._connecting, self._connected)
633
634 self._connecting = True
635 self._simulator.connect(self._flight.aircraft)
636
637 def startMonitoring(self):
638 """Start monitoring."""
639 if not self._monitoring:
640 self.simulator.startMonitoring()
641 self._monitoring = True
642
643 def stopMonitoring(self):
644 """Stop monitoring."""
645 if self._monitoring:
646 self.simulator.stopMonitoring()
647 self._monitoring = False
648
649 def _buildMenuBar(self, accelGroup):
650 """Build the main menu bar."""
651 menuBar = gtk.MenuBar()
652
653 fileMenuItem = gtk.MenuItem(xstr("menu_file"))
654 fileMenu = gtk.Menu()
655 fileMenuItem.set_submenu(fileMenu)
656 menuBar.append(fileMenuItem)
657
658 quitMenuItem = gtk.ImageMenuItem(gtk.STOCK_QUIT)
659 quitMenuItem.set_use_stock(True)
660 quitMenuItem.set_label(xstr("menu_file_quit"))
661 quitMenuItem.add_accelerator("activate", accelGroup,
662 ord(xstr("menu_file_quit_key")),
663 CONTROL_MASK, ACCEL_VISIBLE)
664 quitMenuItem.connect("activate", self._quit)
665 fileMenu.append(quitMenuItem)
666
667 toolsMenuItem = gtk.MenuItem(xstr("menu_tools"))
668 toolsMenu = gtk.Menu()
669 toolsMenuItem.set_submenu(toolsMenu)
670 menuBar.append(toolsMenuItem)
671
672 prefsMenuItem = gtk.ImageMenuItem(gtk.STOCK_PREFERENCES)
673 prefsMenuItem.set_use_stock(True)
674 prefsMenuItem.set_label(xstr("menu_tools_prefs"))
675 prefsMenuItem.add_accelerator("activate", accelGroup,
676 ord(xstr("menu_tools_prefs_key")),
677 CONTROL_MASK, ACCEL_VISIBLE)
678 prefsMenuItem.connect("activate", self._editPreferences)
679 toolsMenu.append(prefsMenuItem)
680
681 viewMenuItem = gtk.MenuItem(xstr("menu_view"))
682 viewMenu = gtk.Menu()
683 viewMenuItem.set_submenu(viewMenu)
684 menuBar.append(viewMenuItem)
685
686 self._showMonitorMenuItem = gtk.CheckMenuItem()
687 self._showMonitorMenuItem.set_label(xstr("menu_view_monitor"))
688 self._showMonitorMenuItem.set_use_underline(True)
689 self._showMonitorMenuItem.set_active(False)
690 self._showMonitorMenuItem.add_accelerator("activate", accelGroup,
691 ord(xstr("menu_view_monitor_key")),
692 CONTROL_MASK, ACCEL_VISIBLE)
693 self._showMonitorMenuItem.connect("toggled", self._toggleMonitorWindow)
694 viewMenu.append(self._showMonitorMenuItem)
695
696 showDebugMenuItem = gtk.CheckMenuItem()
697 showDebugMenuItem.set_label(xstr("menu_view_debug"))
698 showDebugMenuItem.set_use_underline(True)
699 showDebugMenuItem.set_active(False)
700 showDebugMenuItem.add_accelerator("activate", accelGroup,
701 ord(xstr("menu_view_debug_key")),
702 CONTROL_MASK, ACCEL_VISIBLE)
703 showDebugMenuItem.connect("toggled", self._toggleDebugLog)
704 viewMenu.append(showDebugMenuItem)
705
706 return menuBar
707
708 def _toggleDebugLog(self, menuItem):
709 """Toggle the debug log."""
710 if menuItem.get_active():
711 label = gtk.Label(xstr("tab_debug_log"))
712 label.set_use_underline(True)
713 label.set_tooltip_text(xstr("tab_debug_log_tooltip"))
714 self._debugLogPage = self._notebook.append_page(self._debugLogWidget, label)
715 self._notebook.set_current_page(self._debugLogPage)
716 else:
717 self._notebook.remove_page(self._debugLogPage)
718
719 def _buildLogWidget(self):
720 """Build the widget for the log."""
721 alignment = gtk.Alignment(xscale = 1.0, yscale = 1.0)
722
723 alignment.set_padding(padding_top = 8, padding_bottom = 8,
724 padding_left = 16, padding_right = 16)
725
726 logScroller = gtk.ScrolledWindow()
727 # FIXME: these should be constants in common
728 logScroller.set_policy(gtk.PolicyType.AUTOMATIC if pygobject
729 else gtk.POLICY_AUTOMATIC,
730 gtk.PolicyType.AUTOMATIC if pygobject
731 else gtk.POLICY_AUTOMATIC)
732 logScroller.set_shadow_type(gtk.ShadowType.IN if pygobject
733 else gtk.SHADOW_IN)
734 logView = gtk.TextView()
735 logView.set_editable(False)
736 logScroller.add(logView)
737
738 logBox = gtk.VBox()
739 logBox.pack_start(logScroller, True, True, 0)
740 logBox.set_size_request(-1, 200)
741
742 alignment.add(logBox)
743
744 return (alignment, logView)
745
746 def _writeLog(self, msg, logView):
747 """Write the given message to the log."""
748 buffer = logView.get_buffer()
749 buffer.insert(buffer.get_end_iter(), msg)
750 logView.scroll_mark_onscreen(buffer.get_insert())
751
752 def _quit(self, what = None, force = False):
753 """Quit from the application."""
754 if force:
755 result=RESPONSETYPE_YES
756 else:
757 dialog = gtk.MessageDialog(parent = self._mainWindow,
758 type = MESSAGETYPE_QUESTION,
759 message_format = xstr("quit_question"))
760
761 dialog.add_button(xstr("button_no"), RESPONSETYPE_NO)
762 dialog.add_button(xstr("button_yes"), RESPONSETYPE_YES)
763
764 dialog.set_title(WINDOW_TITLE_BASE)
765 result = dialog.run()
766 dialog.hide()
767
768 if result==RESPONSETYPE_YES:
769 self._statusIcon.destroy()
770 return gtk.main_quit()
771
772 def _notebookPageSwitch(self, notebook, page, page_num):
773 """Called when the current page of the notebook has changed."""
774 if page_num==0:
775 gobject.idle_add(self._wizard.grabDefault)
776 else:
777 self._mainWindow.set_default(None)
778
779 def _editPreferences(self, menuItem):
780 """Callback for editing the preferences."""
781 self._preferences.run(self.config)
Note: See TracBrowser for help on using the repository browser.