source: src/mlx/gui/prefs.py@ 198:b75c849e59d8

Last change on this file since 198:b75c849e59d8 was 197:93f89e9049be, checked in by István Váradi <ivaradi@…>, 13 years ago

Added support for smoothed IAS and VS values

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