source: src/mlx/gui/prefs.py@ 277:33fbad0ca891

Last change on this file since 277:33fbad0ca891 was 270:1d28c6212e4b, checked in by István Váradi <ivaradi@…>, 12 years ago

Added support to enable/disable the approach callouts

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