source: src/mlx/gui/prefs.py@ 241:dea155dd3ac0

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

Fixed the handling of filenames acquired via file choosers

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