source: src/mlx/gui/prefs.py@ 391:0f2e90eae832

Last change on this file since 391:0f2e90eae832 was 300:f101bd18f39d, checked in by István Váradi <ivaradi@…>, 12 years ago

Added the module comments for the GUI

File size: 34.4 KB
Line 
1
2from common import *
3
4from mlx.i18n import xstr
5import mlx.const as const
6import mlx.config as config
7
8import urlparse
9
10#------------------------------------------------------------------------------
11
12## @package mlx.gui.prefs
13#
14# The preferences dialog.
15#
16# This module implements the preferences dialog, allowing the editing of the
17# configuration of the program. The preferences are grouped into tabs, each
18# containing the necessary controls to set the various options.
19
20#------------------------------------------------------------------------------
21
22class Hotkey(gtk.HBox):
23 """A widget to handle a hotkey."""
24
25 # Constant to denote that the status of the Ctrl modifier is changed
26 CHANGED_CTRL = 1
27
28 # Constant to denote that the status of the Shift modifier is changed
29 CHANGED_SHIFT = 2
30
31 # Constant to denote that the value of the key is changed
32 CHANGED_KEY = 3
33
34 def __init__(self, labelText, tooltips):
35 """Construct the hotkey widget.
36
37 labelText is the text for the label before the hotkey.
38
39 The tooltips parameter is an array of the tooltips for:
40 - the hotkey combo box,
41 - the control check box, and
42 - the shift check box."""
43 super(Hotkey, self).__init__()
44
45 label = gtk.Label(labelText)
46 label.set_use_underline(True)
47 labelAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
48 xscale = 0.0, yscale = 0.0)
49 labelAlignment.set_padding(padding_top = 0, padding_bottom = 0,
50 padding_left = 0, padding_right = 4)
51 labelAlignment.add(label)
52 self.pack_start(labelAlignment, False, False, 0)
53
54 self._ctrl = gtk.CheckButton("Ctrl")
55 self._ctrl.set_tooltip_text(tooltips[1])
56 self._ctrl.connect("toggled", self._ctrlToggled)
57 self.pack_start(self._ctrl, False, False, 4)
58
59 self._shift = gtk.CheckButton("Shift")
60 self._shift.set_tooltip_text(tooltips[2])
61 self._shift.connect("toggled", self._shiftToggled)
62 self.pack_start(self._shift, False, False, 4)
63
64 self._hotkeyModel = gtk.ListStore(str)
65 for keyCode in range(ord("0"), ord("9")+1) + range(ord("A"), ord("Z")+1):
66 self._hotkeyModel.append([chr(keyCode)])
67
68 self._hotkey = gtk.ComboBox(model = self._hotkeyModel)
69 cell = gtk.CellRendererText()
70 self._hotkey.pack_start(cell, True)
71 self._hotkey.add_attribute(cell, 'text', 0)
72 self._hotkey.set_tooltip_text(tooltips[0])
73 self._hotkey.connect("changed", self._keyChanged)
74 self.pack_start(self._hotkey, False, False, 4)
75
76 label.set_mnemonic_widget(self._hotkey)
77
78 self._setting = False
79
80 @property
81 def ctrl(self):
82 """Get whether the Ctrl modifier is selected."""
83 return self._ctrl.get_active()
84
85 @ctrl.setter
86 def ctrl(self, ctrl):
87 """Get whether the Ctrl modifier is selected."""
88 self._setting = True
89 self._ctrl.set_active(ctrl)
90 self._setting = False
91
92 @property
93 def shift(self):
94 """Get whether the Shift modifier is selected."""
95 return self._shift.get_active()
96
97 @shift.setter
98 def shift(self, shift):
99 """Get whether the Shift modifier is selected."""
100 self._setting = True
101 self._shift.set_active(shift)
102 self._setting = False
103
104 @property
105 def key(self):
106 """Get the value of the key."""
107 return self._hotkeyModel.get_value(self._hotkey.get_active_iter(), 0)
108
109 @key.setter
110 def key(self, key):
111 """Set the value of the key."""
112 self._setting = True
113
114 hotkeyModel = self._hotkeyModel
115 iter = hotkeyModel.get_iter_first()
116 while iter is not None and \
117 hotkeyModel.get_value(iter, 0)!=key:
118 iter = hotkeyModel.iter_next(iter)
119
120 if iter is None:
121 iter = hotkeyModel.get_iter_first()
122
123 self._hotkey.set_active_iter(iter)
124
125 self._setting = False
126
127 def set(self, hotkey):
128 """Set the hotkey widget from the given hotkey."""
129 self.ctrl = hotkey.ctrl
130 self.shift = hotkey.shift
131 self.key = hotkey.key
132
133 def get(self):
134 """Get a hotkey corresponding to the settings in the widghet."""
135
136 key = self._hotkeyModel.get_value(self._hotkey.get_active_iter(), 0)
137
138 return config.Hotkey(ctrl = self.ctrl, shift = self.shift,
139 key = self.key)
140
141 def _ctrlToggled(self, checkButton):
142 """Called when the status of the Ctrl modifier has changed."""
143 if not self._setting:
144 self.emit("hotkey-changed", Hotkey.CHANGED_CTRL)
145
146 def _shiftToggled(self, checkButton):
147 """Called when the status of the Shift modifier has changed."""
148 if not self._setting:
149 self.emit("hotkey-changed", Hotkey.CHANGED_SHIFT)
150
151 def _keyChanged(self, comboBox):
152 """Called when the value of the key has changed."""
153 if not self._setting:
154 self.emit("hotkey-changed", Hotkey.CHANGED_KEY)
155
156 def __eq__(self, other):
157 """Determine if the two hotkeys are equal."""
158 return self.ctrl==other.ctrl and self.shift==other.shift and \
159 self.key==other.key
160
161#------------------------------------------------------------------------------
162
163gobject.signal_new("hotkey-changed", Hotkey, gobject.SIGNAL_RUN_FIRST,
164 None, (int,))
165
166#------------------------------------------------------------------------------
167
168class Preferences(gtk.Dialog):
169 """The preferences dialog."""
170 def __init__(self, gui):
171 """Construct the dialog."""
172 super(Preferences, self).__init__(WINDOW_TITLE_BASE + " " +
173 xstr("prefs_title"),
174 gui.mainWindow,
175 DIALOG_MODAL)
176
177 self.add_button(xstr("button_cancel"), RESPONSETYPE_REJECT)
178 self.add_button(xstr("button_ok"), RESPONSETYPE_ACCEPT)
179 self.set_resizable(False)
180
181 self._gui = gui
182 self._settingFromConfig = False
183
184 contentArea = self.get_content_area()
185
186 notebook = gtk.Notebook()
187 contentArea.pack_start(notebook, True, True, 4)
188
189 general = self._buildGeneral()
190 label = gtk.Label(xstr("prefs_tab_general"))
191 label.set_use_underline(True)
192 label.set_tooltip_text(xstr("prefs_tab_general_tooltip"))
193 notebook.append_page(general, label)
194
195 messages = self._buildMessages()
196 label = gtk.Label(xstr("prefs_tab_messages"))
197 label.set_use_underline(True)
198 label.set_tooltip_text(xstr("prefs_tab_message_tooltip"))
199 notebook.append_page(messages, label)
200
201 sounds = self._buildSounds()
202 label = gtk.Label(xstr("prefs_tab_sounds"))
203 label.set_use_underline(True)
204 label.set_tooltip_text(xstr("prefs_tab_sounds_tooltip"))
205 notebook.append_page(sounds, label)
206
207 advanced = self._buildAdvanced()
208 label = gtk.Label(xstr("prefs_tab_advanced"))
209 label.set_use_underline(True)
210 label.set_tooltip_text(xstr("prefs_tab_advanced_tooltip"))
211 notebook.append_page(advanced, label)
212
213 def run(self, config):
214 """Run the preferences dialog.
215
216 The dialog will be set up from data in the given configuration. If the
217 changes are accepted by the user, the configuration is updated and saved."""
218 self._fromConfig(config)
219
220 self.show_all()
221 response = super(Preferences, self).run()
222 self.hide()
223
224 if response==RESPONSETYPE_ACCEPT:
225 self._toConfig(config)
226 config.save()
227
228 def _fromConfig(self, config):
229 """Setup the dialog from the given configuration."""
230 self._settingFromConfig = True
231
232 self._setLanguage(config.language)
233 self._hideMinimizedWindow.set_active(config.hideMinimizedWindow)
234 self._quitOnClose.set_active(config.quitOnClose)
235 self._onlineGateSystem.set_active(config.onlineGateSystem)
236 self._onlineACARS.set_active(config.onlineACARS)
237 self._flareTimeFromFS.set_active(config.flareTimeFromFS)
238 self._syncFSTime.set_active(config.syncFSTime)
239 self._usingFS2Crew.set_active(config.usingFS2Crew)
240
241 self._setSmoothing(self._iasSmoothingEnabled, self._iasSmoothingLength,
242 config.iasSmoothingLength)
243 self._setSmoothing(self._vsSmoothingEnabled, self._vsSmoothingLength,
244 config.vsSmoothingLength)
245
246 pirepDirectory = config.pirepDirectory
247 self._pirepDirectory.set_text("" if pirepDirectory is None
248 else pirepDirectory)
249
250 for messageType in const.messageTypes:
251 level = config.getMessageTypeLevel(messageType)
252 button = self._msgFSCheckButtons[messageType]
253 button.set_active(level == const.MESSAGELEVEL_FS or
254 level == const.MESSAGELEVEL_BOTH)
255 button = self._msgSoundCheckButtons[messageType]
256 button.set_active(level == const.MESSAGELEVEL_SOUND or
257 level == const.MESSAGELEVEL_BOTH)
258
259 self._enableSounds.set_active(config.enableSounds)
260 self._pilotControlsSounds.set_active(config.pilotControlsSounds)
261 self._pilotHotkey.set(config.pilotHotkey)
262 self._enableApproachCallouts.set_active(config.enableApproachCallouts)
263 self._speedbrakeAtTD.set_active(config.speedbrakeAtTD)
264
265 self._enableChecklists.set_active(config.enableChecklists)
266 self._checklistHotkey.set(config.checklistHotkey)
267
268 self._autoUpdate.set_active(config.autoUpdate)
269 if not config.autoUpdate:
270 self._warnedAutoUpdate = True
271
272 self._updateURL.set_text(config.updateURL)
273
274 self._settingFromConfig = False
275
276 def _toConfig(self, config):
277 """Setup the given config from the settings in the dialog."""
278 config.language = self._getLanguage()
279 config.hideMinimizedWindow = self._hideMinimizedWindow.get_active()
280 config.quitOnClose = self._quitOnClose.get_active()
281 config.onlineGateSystem = self._onlineGateSystem.get_active()
282 config.onlineACARS = self._onlineACARS.get_active()
283 config.flareTimeFromFS = self._flareTimeFromFS.get_active()
284 config.syncFSTime = self._syncFSTime.get_active()
285 config.usingFS2Crew = self._usingFS2Crew.get_active()
286 config.iasSmoothingLength = self._getSmoothing(self._iasSmoothingEnabled,
287 self._iasSmoothingLength)
288 config.vsSmoothingLength = self._getSmoothing(self._vsSmoothingEnabled,
289 self._vsSmoothingLength)
290 config.pirepDirectory = text2unicode(self._pirepDirectory.get_text())
291
292 for messageType in const.messageTypes:
293 fsButtonActive = self._msgFSCheckButtons[messageType].get_active()
294 soundButtonActive = self._msgSoundCheckButtons[messageType].get_active()
295 if fsButtonActive:
296 level = const.MESSAGELEVEL_BOTH if soundButtonActive \
297 else const.MESSAGELEVEL_FS
298 elif soundButtonActive:
299 level = const.MESSAGELEVEL_SOUND
300 else:
301 level = const.MESSAGELEVEL_NONE
302 config.setMessageTypeLevel(messageType, level)
303
304 config.enableSounds = self._enableSounds.get_active()
305 config.pilotControlsSounds = self._pilotControlsSounds.get_active()
306 config.pilotHotkey = self._pilotHotkey.get()
307 config.enableApproachCallouts = self._enableApproachCallouts.get_active()
308 config.speedbrakeAtTD = self._speedbrakeAtTD.get_active()
309
310 config.enableChecklists = self._enableChecklists.get_active()
311 config.checklistHotkey = self._checklistHotkey.get()
312
313 config.autoUpdate = self._autoUpdate.get_active()
314 config.updateURL = self._updateURL.get_text()
315
316 def _buildGeneral(self):
317 """Build the page for the general settings."""
318 mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
319 xscale = 1.0, yscale = 0.0)
320 mainAlignment.set_padding(padding_top = 0, padding_bottom = 8,
321 padding_left = 4, padding_right = 4)
322 mainBox = gtk.VBox()
323 mainAlignment.add(mainBox)
324
325 guiBox = self._createFrame(mainBox, xstr("prefs_frame_gui"))
326
327 languageBox = gtk.HBox()
328 guiBox.pack_start(languageBox, False, False, 4)
329
330 label = gtk.Label(xstr("prefs_language"))
331 label.set_use_underline(True)
332
333 languageBox.pack_start(label, False, False, 4)
334
335 self._languageList = gtk.ListStore(str, str)
336 for language in const.languages:
337 self._languageList.append([xstr("prefs_lang_" + language),
338 language])
339
340 self._languageComboBox = languageComboBox = \
341 gtk.ComboBox(model = self._languageList)
342 cell = gtk.CellRendererText()
343 languageComboBox.pack_start(cell, True)
344 languageComboBox.add_attribute(cell, 'text', 0)
345 languageComboBox.set_tooltip_text(xstr("prefs_language_tooltip"))
346 languageComboBox.connect("changed", self._languageChanged)
347 languageBox.pack_start(languageComboBox, False, False, 4)
348
349 label.set_mnemonic_widget(languageComboBox)
350
351 self._changingLanguage = False
352 self._warnedRestartNeeded = False
353
354 self._hideMinimizedWindow = gtk.CheckButton(xstr("prefs_hideMinimizedWindow"))
355 self._hideMinimizedWindow.set_use_underline(True)
356 self._hideMinimizedWindow.set_tooltip_text(xstr("prefs_hideMinimizedWindow_tooltip"))
357 guiBox.pack_start(self._hideMinimizedWindow, False, False, 4)
358
359 self._quitOnClose = gtk.CheckButton(xstr("prefs_quitOnClose"))
360 self._quitOnClose.set_use_underline(True)
361 self._quitOnClose.set_tooltip_text(xstr("prefs_quitOnClose_tooltip"))
362 guiBox.pack_start(self._quitOnClose, False, False, 4)
363
364 onlineBox = self._createFrame(mainBox, xstr("prefs_frame_online"))
365
366 self._onlineGateSystem = gtk.CheckButton(xstr("prefs_onlineGateSystem"))
367 self._onlineGateSystem.set_use_underline(True)
368 self._onlineGateSystem.set_tooltip_text(xstr("prefs_onlineGateSystem_tooltip"))
369 onlineBox.pack_start(self._onlineGateSystem, False, False, 4)
370
371 self._onlineACARS = gtk.CheckButton(xstr("prefs_onlineACARS"))
372 self._onlineACARS.set_use_underline(True)
373 self._onlineACARS.set_tooltip_text(xstr("prefs_onlineACARS_tooltip"))
374 onlineBox.pack_start(self._onlineACARS, False, False, 4)
375
376 simulatorBox = self._createFrame(mainBox, xstr("prefs_frame_simulator"))
377
378 self._flareTimeFromFS = gtk.CheckButton(xstr("prefs_flaretimeFromFS"))
379 self._flareTimeFromFS.set_use_underline(True)
380 self._flareTimeFromFS.set_tooltip_text(xstr("prefs_flaretimeFromFS_tooltip"))
381 simulatorBox.pack_start(self._flareTimeFromFS, False, False, 4)
382
383 self._syncFSTime = gtk.CheckButton(xstr("prefs_syncFSTime"))
384 self._syncFSTime.set_use_underline(True)
385 self._syncFSTime.set_tooltip_text(xstr("prefs_syncFSTime_tooltip"))
386 simulatorBox.pack_start(self._syncFSTime, False, False, 4)
387
388 self._usingFS2Crew = gtk.CheckButton(xstr("prefs_usingFS2Crew"))
389 self._usingFS2Crew.set_use_underline(True)
390 self._usingFS2Crew.set_tooltip_text(xstr("prefs_usingFS2Crew_tooltip"))
391 simulatorBox.pack_start(self._usingFS2Crew, False, False, 4)
392
393 (iasSmoothingBox, self._iasSmoothingEnabled,
394 self._iasSmoothingLength) = \
395 self._createSmoothingBox(xstr("prefs_iasSmoothingEnabled"),
396 xstr("prefs_iasSmoothingEnabledTooltip"))
397 simulatorBox.pack_start(iasSmoothingBox, False, False, 4)
398
399 (vsSmoothingBox, self._vsSmoothingEnabled,
400 self._vsSmoothingLength) = \
401 self._createSmoothingBox(xstr("prefs_vsSmoothingEnabled"),
402 xstr("prefs_vsSmoothingEnabledTooltip"))
403 simulatorBox.pack_start(vsSmoothingBox, False, False, 4)
404
405 pirepBox = gtk.HBox()
406 mainBox.pack_start(pirepBox, False, False, 8)
407
408 label = gtk.Label(xstr("prefs_pirepDirectory"))
409 label.set_use_underline(True)
410 pirepBox.pack_start(label, False, False, 4)
411
412 self._pirepDirectory = gtk.Entry()
413 self._pirepDirectory.set_tooltip_text(xstr("prefs_pirepDirectory_tooltip"))
414 label.set_mnemonic_widget(self._pirepDirectory)
415 pirepBox.pack_start(self._pirepDirectory, True, True, 4)
416
417 self._pirepDirectoryButton = gtk.Button(xstr("button_browse"))
418 self._pirepDirectoryButton.connect("clicked",
419 self._pirepDirectoryButtonClicked)
420 pirepBox.pack_start(self._pirepDirectoryButton, False, False, 4)
421
422 return mainAlignment
423
424 def _createFrame(self, mainBox, label):
425 """Create a frame with an inner alignment and VBox.
426
427 Return the vbox."""
428 frame = gtk.Frame(label = label)
429 mainBox.pack_start(frame, False, False, 4)
430 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
431 xscale = 1.0, yscale = 0.0)
432 alignment.set_padding(padding_top = 4, padding_bottom = 0,
433 padding_left = 0, padding_right = 0)
434 frame.add(alignment)
435 vbox = gtk.VBox()
436 alignment.add(vbox)
437
438 return vbox
439
440 def _createSmoothingBox(self, checkBoxLabel, checkBoxTooltip,
441 maxSeconds = 10):
442 """Create a HBox that contains entry fields for smoothing some value."""
443 smoothingBox = gtk.HBox()
444
445 smoothingEnabled = gtk.CheckButton(checkBoxLabel)
446 smoothingEnabled.set_use_underline(True)
447 smoothingEnabled.set_tooltip_text(checkBoxTooltip)
448
449 smoothingBox.pack_start(smoothingEnabled, False, False, 0)
450
451 smoothingLength = gtk.SpinButton()
452 smoothingLength.set_numeric(True)
453 smoothingLength.set_range(2, maxSeconds)
454 smoothingLength.set_increments(1, 1)
455 smoothingLength.set_alignment(1.0)
456 smoothingLength.set_width_chars(2)
457
458 smoothingBox.pack_start(smoothingLength, False, False, 0)
459
460 smoothingBox.pack_start(gtk.Label(xstr("prefs_smoothing_seconds")),
461 False, False, 4)
462
463 smoothingEnabled.connect("toggled", self._smoothingToggled,
464 smoothingLength)
465 smoothingLength.set_sensitive(False)
466
467 return (smoothingBox, smoothingEnabled, smoothingLength)
468
469 def _setLanguage(self, language):
470 """Set the language to the given one."""
471 iter = self._languageList.get_iter_first()
472 while iter is not None:
473 (lang,) = self._languageList.get(iter, 1)
474 if (not language and lang=="$system") or \
475 lang==language:
476 self._changingLanguage = True
477 self._languageComboBox.set_active_iter(iter)
478 self._changingLanguage = False
479 break
480 else:
481 iter = self._languageList.iter_next(iter)
482
483 def _getLanguage(self):
484 """Get the language selected by the user."""
485 iter = self._languageComboBox.get_active_iter()
486 (lang,) = self._languageList.get(iter, 1)
487 return "" if lang=="$system" else lang
488
489 def _languageChanged(self, comboBox):
490 """Called when the language has changed."""
491 if not self._changingLanguage and not self._warnedRestartNeeded:
492 dialog = gtk.MessageDialog(parent = self,
493 type = MESSAGETYPE_INFO,
494 message_format = xstr("prefs_restart"))
495 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
496 dialog.set_title(self.get_title())
497 dialog.format_secondary_markup(xstr("prefs_language_restart_sec"))
498 dialog.run()
499 dialog.hide()
500 self._warnedRestartNeeded = True
501
502 def _smoothingToggled(self, smoothingEnabled, smoothingLength):
503 """Called when a smoothing enabled check box is toggled."""
504 sensitive = smoothingEnabled.get_active()
505 smoothingLength.set_sensitive(sensitive)
506 if sensitive:
507 smoothingLength.grab_focus()
508
509 def _setSmoothing(self, smoothingEnabled, smoothingLength, smoothing):
510 """Set the smoothing controls from the given value.
511
512 If the value is less than 2, smoothing is disabled. The smoothing
513 length is the absolute value of the value."""
514 smoothingEnabled.set_active(smoothing>=2)
515 smoothingLength.set_value(abs(smoothing))
516
517 def _getSmoothing(self, smoothingEnabled, smoothingLength):
518 """Get the smoothing value from the given controls.
519
520 The returned value is the value of smoothingLength multiplied by -1, if
521 smoothing is disabled."""
522 value = smoothingLength.get_value_as_int()
523 if not smoothingEnabled.get_active():
524 value *= -1
525 return value
526
527 def _pirepDirectoryButtonClicked(self, button):
528 """Called when the PIREP directory button is clicked."""
529 dialog = gtk.FileChooserDialog(title = WINDOW_TITLE_BASE + " - " +
530 xstr("prefs_pirepDirectory_browser_title"),
531 action = FILE_CHOOSER_ACTION_SELECT_FOLDER,
532 buttons = (gtk.STOCK_CANCEL, RESPONSETYPE_CANCEL,
533 gtk.STOCK_OK, RESPONSETYPE_OK),
534 parent = self)
535 dialog.set_modal(True)
536 dialog.set_transient_for(self)
537
538 directory = self._pirepDirectory.get_text()
539 if directory:
540 dialog.select_filename(directory)
541
542 result = dialog.run()
543 dialog.hide()
544
545 if result==RESPONSETYPE_OK:
546 self._pirepDirectory.set_text(text2unicode(dialog.get_filename()))
547
548 def _buildMessages(self):
549 """Build the page for the message settings."""
550
551 mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
552 xscale = 0.0, yscale = 0.0)
553 mainAlignment.set_padding(padding_top = 16, padding_bottom = 8,
554 padding_left = 4, padding_right = 4)
555 mainBox = gtk.VBox()
556 mainAlignment.add(mainBox)
557
558 table = gtk.Table(len(const.messageTypes) + 1, 3)
559 table.set_row_spacings(8)
560 table.set_col_spacings(32)
561 table.set_homogeneous(False)
562 mainBox.pack_start(table, False, False, 4)
563
564 label = gtk.Label(xstr("prefs_msgs_fs"))
565 label.set_justify(JUSTIFY_CENTER)
566 label.set_alignment(0.5, 1.0)
567 table.attach(label, 1, 2, 0, 1)
568
569 label = gtk.Label(xstr("prefs_msgs_sound"))
570 label.set_justify(JUSTIFY_CENTER)
571 label.set_alignment(0.5, 1.0)
572 table.attach(label, 2, 3, 0, 1)
573
574 self._msgFSCheckButtons = {}
575 self._msgSoundCheckButtons = {}
576 row = 1
577 for messageType in const.messageTypes:
578 messageTypeStr = const.messageType2string(messageType)
579 label = gtk.Label(xstr("prefs_msgs_type_" + messageTypeStr))
580 label.set_justify(JUSTIFY_CENTER)
581 label.set_use_underline(True)
582 label.set_alignment(0.5, 0.5)
583 table.attach(label, 0, 1, row, row+1)
584
585 fsCheckButton = gtk.CheckButton()
586 alignment = gtk.Alignment(xscale = 0.0, yscale = 0.0,
587 xalign = 0.5, yalign = 0.5)
588 alignment.add(fsCheckButton)
589 table.attach(alignment, 1, 2, row, row+1)
590 self._msgFSCheckButtons[messageType] = fsCheckButton
591
592 soundCheckButton = gtk.CheckButton()
593 alignment = gtk.Alignment(xscale = 0.0, yscale = 0.0,
594 xalign = 0.5, yalign = 0.5)
595 alignment.add(soundCheckButton)
596 table.attach(alignment, 2, 3, row, row+1)
597 self._msgSoundCheckButtons[messageType] = soundCheckButton
598
599 mnemonicWidget = gtk.Label("")
600 table.attach(mnemonicWidget, 3, 4, row, row+1)
601 label.set_mnemonic_widget(mnemonicWidget)
602 mnemonicWidget.connect("mnemonic-activate",
603 self._msgLabelActivated,
604 messageType)
605
606 row += 1
607
608 return mainAlignment
609
610 def _msgLabelActivated(self, button, cycle_group, messageType):
611 """Called when the mnemonic of a label is activated.
612
613 It cycles the corresponding options."""
614 fsCheckButton = self._msgFSCheckButtons[messageType]
615 soundCheckButton = self._msgSoundCheckButtons[messageType]
616
617 num = 1 if fsCheckButton.get_active() else 0
618 num += 2 if soundCheckButton.get_active() else 0
619 num += 1
620
621 fsCheckButton.set_active((num&0x01)==0x01)
622 soundCheckButton.set_active((num&0x02)==0x02)
623
624 return True
625
626 def _buildSounds(self):
627 """Build the page for the sounds."""
628 mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
629 xscale = 1.0, yscale = 1.0)
630 mainAlignment.set_padding(padding_top = 8, padding_bottom = 8,
631 padding_left = 4, padding_right = 4)
632
633 mainBox = gtk.VBox()
634 mainAlignment.add(mainBox)
635
636 backgroundFrame = gtk.Frame(label = xstr("prefs_sounds_frame_bg"))
637 mainBox.pack_start(backgroundFrame, False, False, 4)
638
639 backgroundAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
640 xscale = 1.0, yscale = 0.0)
641 backgroundAlignment.set_padding(padding_top = 4, padding_bottom = 4,
642 padding_left = 4, padding_right = 4)
643 backgroundFrame.add(backgroundAlignment)
644
645 backgroundBox = gtk.VBox()
646 backgroundAlignment.add(backgroundBox)
647
648 self._enableSounds = gtk.CheckButton(xstr("prefs_sounds_enable"))
649 self._enableSounds.set_use_underline(True)
650 self._enableSounds.set_tooltip_text(xstr("prefs_sounds_enable_tooltip"))
651 self._enableSounds.connect("toggled", self._enableSoundsToggled)
652 alignment = gtk.Alignment(xalign = 0.0, yalign = 0.5,
653 xscale = 1.0, yscale = 0.0)
654 alignment.add(self._enableSounds)
655 backgroundBox.pack_start(alignment, False, False, 4)
656
657 self._pilotControlsSounds = gtk.CheckButton(xstr("prefs_sounds_pilotControls"))
658 self._pilotControlsSounds.set_use_underline(True)
659 self._pilotControlsSounds.set_tooltip_text(xstr("prefs_sounds_pilotControls_tooltip"))
660 self._pilotControlsSounds.connect("toggled", self._pilotControlsSoundsToggled)
661 backgroundBox.pack_start(self._pilotControlsSounds, False, False, 4)
662
663 self._pilotHotkey = Hotkey(xstr("prefs_sounds_pilotHotkey"),
664 [xstr("prefs_sounds_pilotHotkey_tooltip"),
665 xstr("prefs_sounds_pilotHotkeyCtrl_tooltip"),
666 xstr("prefs_sounds_pilotHotkeyShift_tooltip")])
667
668 backgroundBox.pack_start(self._pilotHotkey, False, False, 4)
669
670 self._enableApproachCallouts = gtk.CheckButton(xstr("prefs_sounds_approachCallouts"))
671 self._enableApproachCallouts.set_use_underline(True)
672 self._enableApproachCallouts.set_tooltip_text(xstr("prefs_sounds_approachCallouts_tooltip"))
673 backgroundBox.pack_start(self._enableApproachCallouts, False, False, 4)
674
675 self._speedbrakeAtTD = gtk.CheckButton(xstr("prefs_sounds_speedbrakeAtTD"))
676 self._speedbrakeAtTD.set_use_underline(True)
677 self._speedbrakeAtTD.set_tooltip_text(xstr("prefs_sounds_speedbrakeAtTD_tooltip"))
678 backgroundBox.pack_start(self._speedbrakeAtTD, False, False, 4)
679
680 checklistFrame = gtk.Frame(label = xstr("prefs_sounds_frame_checklists"))
681 mainBox.pack_start(checklistFrame, False, False, 4)
682
683 checklistAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
684 xscale = 1.0, yscale = 0.0)
685 checklistAlignment.set_padding(padding_top = 4, padding_bottom = 4,
686 padding_left = 4, padding_right = 4)
687 checklistFrame.add(checklistAlignment)
688
689 checklistBox = gtk.VBox()
690 checklistAlignment.add(checklistBox)
691
692 self._enableChecklists = gtk.CheckButton(xstr("prefs_sounds_enableChecklists"))
693 self._enableChecklists.set_use_underline(True)
694 self._enableChecklists.set_tooltip_text(xstr("prefs_sounds_enableChecklists_tooltip"))
695 self._enableChecklists.connect("toggled", self._enableChecklistsToggled)
696 checklistBox.pack_start(self._enableChecklists, False, False, 4)
697
698 self._checklistHotkey = Hotkey(xstr("prefs_sounds_checklistHotkey"),
699 [xstr("prefs_sounds_checklistHotkey_tooltip"),
700 xstr("prefs_sounds_checklistHotkeyCtrl_tooltip"),
701 xstr("prefs_sounds_checklistHotkeyShift_tooltip")])
702
703 checklistBox.pack_start(self._checklistHotkey, False, False, 4)
704
705 self._enableSoundsToggled(self._enableSounds)
706 self._enableChecklistsToggled(self._enableChecklists)
707
708 self._pilotHotkey.connect("hotkey-changed", self._reconcileHotkeys,
709 self._checklistHotkey)
710 self._checklistHotkey.connect("hotkey-changed", self._reconcileHotkeys,
711 self._pilotHotkey)
712
713 return mainAlignment
714
715 def _enableSoundsToggled(self, button):
716 """Called when the enable sounds button is toggled."""
717 active = button.get_active()
718 self._pilotControlsSounds.set_sensitive(active)
719 self._pilotControlsSoundsToggled(self._pilotControlsSounds)
720 self._enableApproachCallouts.set_sensitive(active)
721 self._speedbrakeAtTD.set_sensitive(active)
722
723 def _pilotControlsSoundsToggled(self, button):
724 """Called when the enable sounds button is toggled."""
725 active = button.get_active() and self._enableSounds.get_active()
726 self._pilotHotkey.set_sensitive(active)
727 if active and self._checklistHotkey.get_sensitive():
728 self._reconcileHotkeys(self._checklistHotkey, Hotkey.CHANGED_SHIFT,
729 self._pilotHotkey)
730
731 def _enableChecklistsToggled(self, button):
732 """Called when the enable checklists button is toggled."""
733 active = button.get_active()
734 self._checklistHotkey.set_sensitive(active)
735 if active and self._pilotHotkey.get_sensitive():
736 self._reconcileHotkeys(self._pilotHotkey, Hotkey.CHANGED_SHIFT,
737 self._checklistHotkey)
738
739 def _reconcileHotkeys(self, changedHotkey, what, otherHotkey):
740 """Reconcile the given hotkeys so that they are different.
741
742 changedHotkey is the hotkey that has changed. what is one of the
743 Hotkey.CHANGED_XXX constants denoting what has changed. otherHotkey is
744 the other hotkey that must be reconciled.
745
746 If the other hotkey is not sensitive or is not equal to the changed
747 one, nothing happens.
748
749 Otherwise, if the status of the Ctrl modifier has changed, the status
750 of the Ctrl modifier on the other hotkey will be negated. Similarly, if
751 the Shift modifier has changed. If the key has changed, the Shift
752 modifier is negated in the other hotkey."""
753 if otherHotkey.get_sensitive() and changedHotkey==otherHotkey:
754 if what==Hotkey.CHANGED_CTRL:
755 otherHotkey.ctrl = not changedHotkey.ctrl
756 elif what==Hotkey.CHANGED_SHIFT or what==Hotkey.CHANGED_KEY:
757 otherHotkey.shift = not changedHotkey.shift
758
759 def _buildAdvanced(self):
760 """Build the page for the advanced settings."""
761
762 mainAlignment = gtk.Alignment(xalign = 0.0, yalign = 0.0,
763 xscale = 1.0, yscale = 0.0)
764 mainAlignment.set_padding(padding_top = 16, padding_bottom = 8,
765 padding_left = 4, padding_right = 4)
766 mainBox = gtk.VBox()
767 mainAlignment.add(mainBox)
768
769 self._autoUpdate = gtk.CheckButton(xstr("prefs_update_auto"))
770 mainBox.pack_start(self._autoUpdate, False, False, 4)
771
772 self._autoUpdate.set_use_underline(True)
773 self._autoUpdate.connect("toggled", self._autoUpdateToggled)
774 self._autoUpdate.set_tooltip_text(xstr("prefs_update_auto_tooltip"))
775 self._warnedAutoUpdate = False
776
777 updateURLBox = gtk.HBox()
778 mainBox.pack_start(updateURLBox, False, False, 4)
779 label = gtk.Label(xstr("prefs_update_url"))
780 label.set_use_underline(True)
781 updateURLBox.pack_start(label, False, False, 4)
782
783 self._updateURL = gtk.Entry()
784 label.set_mnemonic_widget(self._updateURL)
785 self._updateURL.set_width_chars(40)
786 self._updateURL.set_tooltip_text(xstr("prefs_update_url_tooltip"))
787 self._updateURL.connect("changed", self._updateURLChanged)
788 updateURLBox.pack_start(self._updateURL, True, True, 4)
789
790 return mainAlignment
791
792 def _setOKButtonSensitivity(self):
793 """Set the sensitive state of the OK button."""
794 sensitive = False
795 try:
796 result = urlparse.urlparse(self._updateURL.get_text())
797 sensitive = result.scheme!="" and (result.netloc + result.path)!=""
798 except:
799 pass
800
801 okButton = self.get_widget_for_response(RESPONSETYPE_ACCEPT)
802 okButton.set_sensitive(sensitive)
803
804 def _autoUpdateToggled(self, button):
805 """Called when the auto update check button is toggled."""
806 if not self._settingFromConfig and not self._warnedAutoUpdate and \
807 not self._autoUpdate.get_active():
808 dialog = gtk.MessageDialog(parent = self,
809 type = MESSAGETYPE_INFO,
810 message_format = xstr("prefs_update_auto_warning"))
811 dialog.add_button(xstr("button_ok"), RESPONSETYPE_OK)
812 dialog.set_title(self.get_title())
813 dialog.run()
814 dialog.hide()
815 self._warnedAutoUpdate = True
816
817 def _updateURLChanged(self, entry):
818 """Called when the update URL is changed."""
819 self._setOKButtonSensitivity()
820
Note: See TracBrowser for help on using the repository browser.