source: src/mlx/gui/gui.py@ 118:aaa1bc00131b

Last change on this file since 118:aaa1bc00131b was 118:aaa1bc00131b, checked in by István Váradi <ivaradi@…>, 12 years ago

Implemented the gates tab

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