source: src/mlx/config.py@ 415:77d406d7d593

Last change on this file since 415:77d406d7d593 was 402:b668511b4ac8, checked in by István Váradi <ivaradi@…>, 12 years ago

Made the debug logging more detailed by adding the printout of the configuration and a few other stuff (re #170)

File size: 34.2 KB
Line 
1# -*- encoding: utf-8 -*-
2
3import const
4from util import secondaryInstallation, utf2unicode
5
6import os
7import sys
8import traceback
9import ConfigParser
10
11## @package mlx.config
12#
13# The handling of the configuration.
14#
15# The \ref Config class contains the main configuration and is capable of
16# loading and saving the configuration. It contains getters and setters for the
17# configuration options.
18#
19# Some parts of the configuration are not simple data items, like strings or
20# booleans, but more complicated data. These have their own class, like \ref
21# ApproachCallouts or \ref Checklist.
22
23#-------------------------------------------------------------------------------
24
25configPath = os.path.join(os.path.expanduser("~"),
26 "mlx.config" if os.name=="nt" else ".mlxrc") + \
27 ("-secondary" if secondaryInstallation else "")
28
29#-------------------------------------------------------------------------------
30
31if os.name=="nt":
32 _languageMap = { "en_GB" : "eng",
33 "hu_HU" : "hun" }
34
35#-------------------------------------------------------------------------------
36
37class Hotkey(object):
38 """A hotkey."""
39 def __init__(self, ctrl = False, shift = False, key = "0"):
40 """Construct the hotkey."""
41 self.ctrl = ctrl
42 self.shift = shift
43 self.key = key
44
45 def set(self, s):
46 """Set the hotkey from the given string."""
47 self.ctrl = "C" in s[:-1]
48 self.shift = "S" in s[:-1]
49 self.key = s[-1]
50
51 def __eq__(self, other):
52 """Check if the given hotkey is equal to the other one."""
53 return self.ctrl == other.ctrl and self.shift == other.shift and \
54 self.key == other.key
55
56 def __ne__(self, other):
57 """Check if the given hotkey is not equal to the other one."""
58 return not self==other
59
60 def __str__(self):
61 """Construct the hotkey to a string."""
62 s = ""
63 if self.ctrl: s += "C"
64 if self.shift: s += "S"
65 s += self.key
66 return s
67
68#-------------------------------------------------------------------------------
69
70class Checklist(object):
71 """A checklist for a certain aircraft type."""
72 # The name of the section of the checklists
73 SECTION="checklists"
74
75 @staticmethod
76 def fromConfig(config, aircraftType):
77 """Create a checklist for the given aircraft type from the given
78 config."""
79 baseName = "checklist." + const.icaoCodes[aircraftType] + "."
80 fileList = []
81 while True:
82 option = baseName + str(len(fileList))
83 if config.has_option(Checklist.SECTION, option):
84 fileList.append(config.get(Checklist.SECTION, option))
85 else:
86 break
87
88 return Checklist(fileList)
89
90 def __init__(self, fileList = None):
91 """Construct the check list with the given file list."""
92 self._fileList = [] if fileList is None else fileList[:]
93
94 def clone(self):
95 """Clone the checklist."""
96 return Checklist(self._fileList)
97
98 def toConfig(self, config, aircraftType):
99 """Add this checklist to the given config."""
100 baseName = "checklist." + const.icaoCodes[aircraftType] + "."
101 for index in range(0, len(self._fileList)):
102 option = baseName + str(index)
103 config.set(Checklist.SECTION, option,
104 self._fileList[index])
105
106 def __eq__(self, other):
107 """Determine if the checklist is equal to the given other one."""
108 return self._fileList == other._fileList
109
110 def __ne__(self, other):
111 """Determine if the checklist is not equal to the given other one."""
112 return not self==other
113
114 def __len__(self):
115 """Get the length of the file list."""
116 return len(self._fileList)
117
118 def __getitem__(self, index):
119 """Get the file with the given index."""
120 return self._fileList[index]
121
122 def __iter__(self):
123 """Iterate over the files."""
124 return iter(self._fileList)
125
126#-------------------------------------------------------------------------------
127
128class ApproachCallouts(object):
129 """The approach callouts for a certain aircraft type."""
130 # The name of the section of the approach callouts
131 SECTION="callouts"
132
133 @staticmethod
134 def fromConfig(config, aircraftType):
135 """Create a checklist for the given aircraft type from the given
136 config."""
137 baseName = "callouts." + const.icaoCodes[aircraftType] + "."
138 mapping = {}
139 while True:
140 option = baseName + str(len(mapping))
141 if config.has_option(ApproachCallouts.SECTION, option):
142 value = config.get(ApproachCallouts.SECTION, option)
143 (altitude, path) = value.split(",")
144 altitude = int(altitude.strip())
145 path = path.strip()
146 mapping[altitude] = path
147 else:
148 break
149
150 return ApproachCallouts(mapping)
151
152 def __init__(self, mapping = None):
153 """Construct the check list with the given mapping of altitudes to
154 files."""
155 self._mapping = {} if mapping is None else mapping.copy()
156
157 def clone(self):
158 """Clone the callout information."""
159 return ApproachCallouts(self._mapping)
160
161 def toConfig(self, config, aircraftType):
162 """Add this checklist to the given config."""
163 baseName = "callouts." + const.icaoCodes[aircraftType] + "."
164 index = 0
165 for (altitude, path) in self._mapping.iteritems():
166 option = baseName + str(index)
167 config.set(ApproachCallouts.SECTION, option,
168 "%d, %s" % (altitude, path))
169 index += 1
170
171 def getAltitudes(self, descending = True):
172 """Get the altitudes in decreasing order by default."""
173 altitudes = self._mapping.keys()
174 altitudes.sort(reverse = descending)
175 return altitudes
176
177 def __nonzero__(self):
178 """Return if there is anything in the mapping."""
179 return not not self._mapping
180
181 def __eq__(self, other):
182 """Determine if the approach callout mapping is equal to the given
183 other one."""
184 return self._mapping == other._mapping
185
186 def __ne__(self, other):
187 """Determine if the approach callout mapping is not equal to the given
188 other one."""
189 return not self==other
190
191 def __len__(self):
192 """Get the number of elements in the mapping."""
193 return len(self._mapping)
194
195 def __getitem__(self, altitude):
196 """Get the file that is associated with the given altitude.
197
198 If no such file found, return None."""
199 return self._mapping[altitude] if altitude in self._mapping else None
200
201 def __iter__(self):
202 """Iterate over the pairs of altitudes and paths in decreasing order of
203 the altitude."""
204 altitudes = self.getAltitudes()
205
206 for altitude in altitudes:
207 yield (altitude, self._mapping[altitude])
208
209#-------------------------------------------------------------------------------
210
211class Config(object):
212 """Our configuration."""
213 DEFAULT_UPDATE_URL = "http://mlx.varadiistvan.hu/update"
214
215 _messageTypesSection = "messageTypes"
216
217 def __init__(self):
218 """Construct the configuration with default values."""
219
220 self._pilotID = ""
221 self._password = ""
222 self._rememberPassword = False
223
224 self._language = ""
225 self._hideMinimizedWindow = True
226 self._quitOnClose = False
227 self._onlineGateSystem = not secondaryInstallation
228 self._onlineACARS = not secondaryInstallation
229 self._flareTimeFromFS = False
230 self._syncFSTime = False
231 self._usingFS2Crew = False
232 self._iasSmoothingLength = -2
233 self._vsSmoothingLength = -2
234
235 self._pirepDirectory = None
236 self._pirepAutoSave = False
237
238 self._enableSounds = not secondaryInstallation
239
240 self._pilotControlsSounds = True
241 self._pilotHotkey = Hotkey(ctrl = True, shift = False, key = "0")
242
243 self._enableApproachCallouts = False
244 self._speedbrakeAtTD = True
245
246 self._enableChecklists = False
247 self._checklistHotkey = Hotkey(ctrl = True, shift = True, key = "0")
248
249 self._autoUpdate = True
250 self._updateURL = Config.DEFAULT_UPDATE_URL
251 if secondaryInstallation:
252 self._updateURL += "/exp"
253
254 self._messageTypeLevels = {}
255
256 self._checklists = {}
257 self._approachCallouts = {}
258 for aircraftType in const.aircraftTypes:
259 self._checklists[aircraftType] = Checklist()
260 self._approachCallouts[aircraftType] = ApproachCallouts()
261
262 self._modified = False
263
264 @property
265 def pilotID(self):
266 """Get the pilot ID."""
267 return self._pilotID
268
269 @pilotID.setter
270 def pilotID(self, pilotID):
271 """Set the pilot ID."""
272 if pilotID!=self._pilotID:
273 self._pilotID = pilotID
274 self._modified = True
275
276 @property
277 def password(self):
278 """Get the password."""
279 return self._password
280
281 @password.setter
282 def password(self, password):
283 """Set the password."""
284 if password!=self._password:
285 self._password = password
286 self._modified = True
287
288 @property
289 def rememberPassword(self):
290 """Get if we should remember the password."""
291 return self._rememberPassword
292
293 @rememberPassword.setter
294 def rememberPassword(self, rememberPassword):
295 """Set if we should remember the password."""
296 if rememberPassword!=self._rememberPassword:
297 self._rememberPassword = rememberPassword
298 self._modified = True
299
300 @property
301 def language(self):
302 """Get the language to use."""
303 return self._language
304
305 @language.setter
306 def language(self, language):
307 """Set the language to use."""
308 if language!=self._language:
309 self._language = language
310 self._modified = True
311
312 @property
313 def hideMinimizedWindow(self):
314 """Get whether a minimized window should be hidden."""
315 return self._hideMinimizedWindow
316
317 @hideMinimizedWindow.setter
318 def hideMinimizedWindow(self, hideMinimizedWindow):
319 """Set whether a minimized window should be hidden."""
320 if hideMinimizedWindow!=self._hideMinimizedWindow:
321 self._hideMinimizedWindow = hideMinimizedWindow
322 self._modified = True
323
324 @property
325 def quitOnClose(self):
326 """Get whether the application should quit when the close button is
327 clicked."""
328 return self._quitOnClose
329
330 @quitOnClose.setter
331 def quitOnClose(self, quitOnClose):
332 """Set whether the application should quit when the close button is
333 clicked."""
334 if quitOnClose!=self._quitOnClose:
335 self._quitOnClose = quitOnClose
336 self._modified = True
337
338 @property
339 def onlineGateSystem(self):
340 """Get whether the online gate system should be used."""
341 return self._onlineGateSystem
342
343 @onlineGateSystem.setter
344 def onlineGateSystem(self, onlineGateSystem):
345 """Set whether the online gate system should be used."""
346 if onlineGateSystem!=self._onlineGateSystem:
347 self._onlineGateSystem = onlineGateSystem
348 self._modified = True
349
350 @property
351 def onlineACARS(self):
352 """Get whether the online ACARS system should be used."""
353 return self._onlineACARS
354
355 @onlineACARS.setter
356 def onlineACARS(self, onlineACARS):
357 """Set whether the online ACARS system should be used."""
358 if onlineACARS!=self._onlineACARS:
359 self._onlineACARS = onlineACARS
360 self._modified = True
361
362 @property
363 def flareTimeFromFS(self):
364 """Get whether the flare time should be calculated from the time values
365 returned by the simulator."""
366 return self._flareTimeFromFS
367
368 @flareTimeFromFS.setter
369 def flareTimeFromFS(self, flareTimeFromFS):
370 """Set whether the flare time should be calculated from the time values
371 returned by the simulator."""
372 if flareTimeFromFS!=self._flareTimeFromFS:
373 self._flareTimeFromFS = flareTimeFromFS
374 self._modified = True
375
376 @property
377 def syncFSTime(self):
378 """Get whether the simulator's time should be synchronized with the
379 machine's clock."""
380 return self._syncFSTime
381
382 @syncFSTime.setter
383 def syncFSTime(self, syncFSTime):
384 """Set whether the simulator's time should be synchronized with the
385 machine's clock."""
386 if syncFSTime!=self._syncFSTime:
387 self._syncFSTime = syncFSTime
388 self._modified = True
389
390 @property
391 def usingFS2Crew(self):
392 """Get whether the FS2Crew addon is being used."""
393 return self._usingFS2Crew
394
395 @usingFS2Crew.setter
396 def usingFS2Crew(self, usingFS2Crew):
397 """Set whether the FS2Crew addon is being used."""
398 if usingFS2Crew!=self._usingFS2Crew:
399 self._usingFS2Crew = usingFS2Crew
400 self._modified = True
401
402 @property
403 def iasSmoothingLength(self):
404 """Get the number of samples over which the IAS is averaged for the
405 smoothed IAS calculation. It may be negative, in which case smoothing
406 is disabled, but we nevertheless store the number of seconds in case it
407 may become useful later."""
408 return self._iasSmoothingLength
409
410 @property
411 def realIASSmoothingLength(self):
412 """Get the real smoothing length of IAS."""
413 return max(self._iasSmoothingLength, 1)
414
415 @iasSmoothingLength.setter
416 def iasSmoothingLength(self, iasSmoothingLength):
417 """Set the number of samples over which the IAS is averaged for the
418 smoothed IAS calculation."""
419 if iasSmoothingLength!=self._iasSmoothingLength:
420 self._iasSmoothingLength = iasSmoothingLength
421 self._modified = True
422
423 @property
424 def vsSmoothingLength(self):
425 """Get the number of samples over which the VS is averaged for the
426 smoothed VS calculation. It may be negative, in which case smoothing
427 is disabled, but we nevertheless store the number of seconds in case it
428 may become useful later."""
429 return self._vsSmoothingLength
430
431 @property
432 def realVSSmoothingLength(self):
433 """Get the real smoothing length of VS."""
434 return max(self._vsSmoothingLength, 1)
435
436 @vsSmoothingLength.setter
437 def vsSmoothingLength(self, vsSmoothingLength):
438 """Set the number of samples over which the VS is averaged for the
439 smoothed VS calculation."""
440 if vsSmoothingLength!=self._vsSmoothingLength:
441 self._vsSmoothingLength = vsSmoothingLength
442 self._modified = True
443
444 @property
445 def pirepDirectory(self):
446 """Get the directory offered by default when saving a PIREP."""
447 return self._pirepDirectory
448
449 @pirepDirectory.setter
450 def pirepDirectory(self, pirepDirectory):
451 """Get the directory offered by default when saving a PIREP."""
452 if pirepDirectory!=self._pirepDirectory and \
453 (pirepDirectory!="" or self._pirepDirectory is not None):
454 self._pirepDirectory = None if pirepDirectory=="" \
455 else pirepDirectory
456 if self._pirepDirectory is None:
457 self._pirepAutoSave = False
458 self._modified = True
459
460 @property
461 def pirepAutoSave(self):
462 """Get whether the PIREP should be saved automatically when it becomes
463 saveable."""
464 return self._pirepAutoSave
465
466 @pirepAutoSave.setter
467 def pirepAutoSave(self, pirepAutoSave):
468 """Set whether the PIREP should be saved automatically when it becomes
469 saveable."""
470 pirepAutoSave = pirepAutoSave and self._pirepDirectory is not None
471 if pirepAutoSave!=self._pirepAutoSave:
472 self._pirepAutoSave = pirepAutoSave
473 self._modified = True
474
475 def getMessageTypeLevel(self, messageType):
476 """Get the level for the given message type."""
477 return self._messageTypeLevels[messageType] \
478 if messageType in self._messageTypeLevels \
479 else const.MESSAGELEVEL_NONE
480
481 def isMessageTypeFS(self, messageType):
482 """Determine if the given message type is displayed in the
483 simulator."""
484 level = self.getMessageTypeLevel(messageType)
485 return level==const.MESSAGELEVEL_FS or \
486 level==const.MESSAGELEVEL_BOTH
487
488 def setMessageTypeLevel(self, messageType, level):
489 """Set the level of the given message type."""
490 if messageType not in self._messageTypeLevels or \
491 self._messageTypeLevels[messageType]!=level:
492 self._messageTypeLevels[messageType] = level
493 self._modified = True
494
495 @property
496 def enableSounds(self):
497 """Get whether background sounds are enabled."""
498 return self._enableSounds
499
500 @enableSounds.setter
501 def enableSounds(self, enableSounds):
502 """Set whether background sounds are enabled."""
503 if enableSounds!=self._enableSounds:
504 self._enableSounds = enableSounds
505 self._modified = True
506
507 @property
508 def pilotControlsSounds(self):
509 """Get whether the pilot controls the background sounds."""
510 return self._pilotControlsSounds
511
512 @pilotControlsSounds.setter
513 def pilotControlsSounds(self, pilotControlsSounds):
514 """Set whether the pilot controls the background sounds."""
515 if pilotControlsSounds!=self._pilotControlsSounds:
516 self._pilotControlsSounds = pilotControlsSounds
517 self._modified = True
518
519 @property
520 def pilotHotkey(self):
521 """Get the pilot's hotkey."""
522 return self._pilotHotkey
523
524 @pilotHotkey.setter
525 def pilotHotkey(self, pilotHotkey):
526 """Set the pilot's hotkey."""
527 if pilotHotkey!=self._pilotHotkey:
528 self._pilotHotkey = pilotHotkey
529 self._modified = True
530
531 @property
532 def enableApproachCallouts(self):
533 """Get whether the approach callouts should be played."""
534 return self._enableApproachCallouts
535
536 @enableApproachCallouts.setter
537 def enableApproachCallouts(self, enableApproachCallouts):
538 """Set whether the approach callouts should be played."""
539 if enableApproachCallouts!=self._enableApproachCallouts:
540 self._enableApproachCallouts = enableApproachCallouts
541 self._modified = True
542
543 @property
544 def speedbrakeAtTD(self):
545 """Get whether the speedbrake sounds should be played at touchdown."""
546 return self._speedbrakeAtTD
547
548 @speedbrakeAtTD.setter
549 def speedbrakeAtTD(self, speedbrakeAtTD):
550 """Set whether the speedbrake sounds should be played at touchdown."""
551 if speedbrakeAtTD!=self._speedbrakeAtTD:
552 self._speedbrakeAtTD = speedbrakeAtTD
553 self._modified = True
554
555 @property
556 def enableChecklists(self):
557 """Get whether aircraft-specific checklists should be played."""
558 return self._enableChecklists
559
560 @enableChecklists.setter
561 def enableChecklists(self, enableChecklists):
562 """Get whether aircraft-specific checklists should be played."""
563 if enableChecklists!=self._enableChecklists:
564 self._enableChecklists = enableChecklists
565 self._modified = True
566
567 @property
568 def checklistHotkey(self):
569 """Get the checklist hotkey."""
570 return self._checklistHotkey
571
572 @checklistHotkey.setter
573 def checklistHotkey(self, checklistHotkey):
574 """Set the checklist hotkey."""
575 if checklistHotkey!=self._checklistHotkey:
576 self._checklistHotkey = checklistHotkey
577 self._modified = True
578
579 @property
580 def autoUpdate(self):
581 """Get if an automatic update is needed."""
582 return self._autoUpdate
583
584 @autoUpdate.setter
585 def autoUpdate(self, autoUpdate):
586 """Set if an automatic update is needed."""
587 if autoUpdate!=self._autoUpdate:
588 self._autoUpdate = autoUpdate
589 self._modified = True
590
591 @property
592 def updateURL(self):
593 """Get the update URL."""
594 return self._updateURL
595
596 @updateURL.setter
597 def updateURL(self, updateURL):
598 """Set the update URL."""
599 if updateURL!=self._updateURL:
600 self._updateURL = updateURL
601 self._modified = True
602
603 def getChecklist(self, aircraftType):
604 """Get the checklist for the given aircraft type."""
605 return self._checklists[aircraftType]
606
607 def setChecklist(self, aircraftType, checklist):
608 """Set the checklist for the given aircraft type."""
609 if checklist!=self._checklists[aircraftType]:
610 self._checklists[aircraftType] = checklist.clone()
611 self._modified = True
612
613 def getApproachCallouts(self, aircraftType):
614 """Get the approach callouts for the given aircraft type."""
615 return self._approachCallouts[aircraftType]
616
617 def setApproachCallouts(self, aircraftType, approachCallouts):
618 """Set the approach callouts for the given aircraft type."""
619 if not approachCallouts==self._approachCallouts[aircraftType]:
620 self._approachCallouts[aircraftType] = approachCallouts.clone()
621 self._modified = True
622
623 def load(self):
624 """Load the configuration from its default location."""
625 try:
626 config = ConfigParser.RawConfigParser()
627 config.read(configPath)
628 except:
629 traceback.print_exc()
630 return
631
632 self._pilotID = self._get(config, "login", "id", "")
633 self._password = self._get(config, "login", "password", "")
634 self._rememberPassword = self._getBoolean(config, "login",
635 "rememberPassword", False)
636
637 self._language = self._get(config, "general", "language", "")
638
639 self._hideMinimizedWindow = self._getBoolean(config, "general",
640 "hideMinimizedWindow",
641 True)
642 self._quitOnClose = self._getBoolean(config, "general",
643 "quitOnClose", False)
644
645 self._onlineGateSystem = self._getBoolean(config, "general",
646 "onlineGateSystem",
647 not secondaryInstallation)
648 self._onlineACARS = self._getBoolean(config, "general",
649 "onlineACARS",
650 not secondaryInstallation)
651 self._flareTimeFromFS = self._getBoolean(config, "general",
652 "flareTimeFromFS",
653 False)
654 self._syncFSTime = self._getBoolean(config, "general",
655 "syncFSTime",
656 False)
657 self._usingFS2Crew = self._getBoolean(config, "general",
658 "usingFS2Crew",
659 False)
660 self._iasSmoothingLength = int(self._get(config, "general",
661 "iasSmoothingLength",
662 -2))
663 self._vsSmoothingLength = int(self._get(config, "general",
664 "vsSmoothingLength",
665 -2))
666 self._pirepDirectory = self._get(config, "general",
667 "pirepDirectory", None)
668
669 self._pirepAutoSave = self._get(config, "general",
670 "pirepAutoSave", False)
671 self._pirepAutoSave = self._pirepAutoSave and \
672 self._pirepAutoSave is not None
673
674 self._messageTypeLevels = {}
675 for messageType in const.messageTypes:
676 self._messageTypeLevels[messageType] = \
677 self._getMessageTypeLevel(config, messageType)
678
679 self._enableSounds = self._getBoolean(config, "sounds", "enable",
680 not secondaryInstallation)
681 self._pilotControlsSounds = self._getBoolean(config, "sounds",
682 "pilotControls", True)
683 self._pilotHotkey.set(self._get(config, "sounds",
684 "pilotHotkey", "C0"))
685 self._enableApproachCallouts = \
686 self._getBoolean(config, "sounds", "enableApproachCallouts", False)
687 self._speedbrakeAtTD = self._getBoolean(config, "sounds",
688 "speedbrakeAtTD", True)
689
690 self._enableChecklists = self._getBoolean(config, "sounds",
691 "enableChecklists", False)
692 self._checklistHotkey.set(self._get(config, "sounds",
693 "checklistHotkey", "CS0"))
694
695 self._autoUpdate = self._getBoolean(config, "update", "auto", True)
696 self._updateURL = self._get(config, "update", "url",
697 Config.DEFAULT_UPDATE_URL +
698 ("/exp" if secondaryInstallation else ""))
699
700 for aircraftType in const.aircraftTypes:
701 self._checklists[aircraftType] = \
702 Checklist.fromConfig(config, aircraftType)
703 self._approachCallouts[aircraftType] = \
704 ApproachCallouts.fromConfig(config, aircraftType)
705
706 self._modified = False
707
708 def save(self):
709 """Save the configuration file if it has been modified."""
710 if not self._modified:
711 return
712
713 config = ConfigParser.RawConfigParser()
714
715 config.add_section("login")
716 config.set("login", "id", self._pilotID)
717 config.set("login", "password", self._password)
718 config.set("login", "rememberPassword",
719 "yes" if self._rememberPassword else "no")
720
721 config.add_section("general")
722 if self._language:
723 config.set("general", "language", self._language)
724 config.set("general", "hideMinimizedWindow",
725 "yes" if self._hideMinimizedWindow else "no")
726 config.set("general", "quitOnClose",
727 "yes" if self._quitOnClose else "no")
728 config.set("general", "onlineGateSystem",
729 "yes" if self._onlineGateSystem else "no")
730 config.set("general", "onlineACARS",
731 "yes" if self._onlineACARS else "no")
732 config.set("general", "flareTimeFromFS",
733 "yes" if self._flareTimeFromFS else "no")
734 config.set("general", "syncFSTime",
735 "yes" if self._syncFSTime else "no")
736 config.set("general", "usingFS2Crew",
737 "yes" if self._usingFS2Crew else "no")
738 config.set("general", "iasSmoothingLength",
739 str(self._iasSmoothingLength))
740 config.set("general", "vsSmoothingLength",
741 str(self._vsSmoothingLength))
742
743 if self._pirepDirectory is not None:
744 config.set("general", "pirepDirectory", self._pirepDirectory)
745 config.set("general", "pirepAutoSave",
746 "yes" if self._pirepAutoSave else "no")
747
748 config.add_section(Config._messageTypesSection)
749 for messageType in const.messageTypes:
750 if messageType in self._messageTypeLevels:
751 option = self._getMessageTypeLevelOptionName(messageType)
752 level = self._messageTypeLevels[messageType]
753 config.set(Config._messageTypesSection, option,
754 const.messageLevel2string(level))
755
756 config.add_section("sounds")
757 config.set("sounds", "enable",
758 "yes" if self._enableSounds else "no")
759 config.set("sounds", "pilotControls",
760 "yes" if self._pilotControlsSounds else "no")
761 config.set("sounds", "pilotHotkey", str(self._pilotHotkey))
762 config.set("sounds", "enableApproachCallouts",
763 "yes" if self._enableApproachCallouts else "no")
764 config.set("sounds", "speedbrakeAtTD",
765 "yes" if self._speedbrakeAtTD else "no")
766
767 config.set("sounds", "enableChecklists",
768 "yes" if self._enableChecklists else "no")
769 config.set("sounds", "checklistHotkey",
770 str(self._checklistHotkey))
771
772 config.add_section("update")
773 config.set("update", "auto",
774 "yes" if self._autoUpdate else "no")
775 config.set("update", "url", self._updateURL)
776
777 config.add_section(Checklist.SECTION)
778 config.add_section(ApproachCallouts.SECTION)
779 for aircraftType in const.aircraftTypes:
780 self._checklists[aircraftType].toConfig(config, aircraftType)
781 self._approachCallouts[aircraftType].toConfig(config, aircraftType)
782
783 try:
784 fd = os.open(configPath, os.O_CREAT|os.O_TRUNC|os.O_WRONLY,
785 0600)
786 with os.fdopen(fd, "wt") as f:
787 config.write(f)
788 self._modified = False
789
790 print "Configuration saved:"
791 self.log()
792
793 except Exception, e:
794 print >> sys.stderr, "Failed to update config: " + \
795 utf2unicode(str(e))
796
797 def _getBoolean(self, config, section, option, default):
798 """Get the given option as a boolean, if found in the given config,
799 otherwise the default."""
800 return config.getboolean(section, option) \
801 if config.has_option(section, option) \
802 else default
803
804 def _get(self, config, section, option, default):
805 """Get the given option as a string, if found in the given config,
806 otherwise the default."""
807 return config.get(section, option) \
808 if config.has_option(section, option) \
809 else default
810
811 def _getMessageTypeLevel(self, config, messageType):
812 """Get the message type level for the given message type."""
813 option = self._getMessageTypeLevelOptionName(messageType)
814 if config.has_option(Config._messageTypesSection, option):
815 value = config.get(Config._messageTypesSection, option)
816 return const.string2messageLevel(value)
817 elif secondaryInstallation:
818 return const.MESSAGELEVEL_NONE
819 elif messageType in [const.MESSAGETYPE_LOGGER_ERROR,
820 const.MESSAGETYPE_FAULT,
821 const.MESSAGETYPE_NOGO,
822 const.MESSAGETYPE_GATE_SYSTEM,
823 const.MESSAGETYPE_HELP]:
824 return const.MESSAGELEVEL_BOTH
825 else:
826 return const.MESSAGELEVEL_FS
827
828 def _getMessageTypeLevelOptionName(self, messageType):
829 """Get the option name for the given message type level."""
830 return const.messageType2string(messageType)
831
832 def setupLocale(self):
833 """Setup the locale based on the language set.
834
835 Return True if a specific language was set, False otherwise."""
836 import locale
837 if self._language:
838 print "Setting up locale for", self._language
839 os.environ["LANGUAGE"] = self._language
840 langAndEncoding = self._language + "." + locale.getpreferredencoding()
841 os.environ["LANG"] = langAndEncoding
842 os.environ["LC_MESSAGES"] = langAndEncoding
843 os.environ["LC_COLLATE"] = langAndEncoding
844 os.environ["LC_CTYPE"] = langAndEncoding
845 os.environ["LC_MONETARY"] = langAndEncoding
846 os.environ["LC_NUMERIC"] = langAndEncoding
847 os.environ["LC_TIME"] = langAndEncoding
848 return True
849 else:
850 return False
851
852 def getLanguage(self):
853 """Get the language to be used."""
854 import locale
855 if self._language:
856 if os.name=="nt":
857 if self._language in _languageMap:
858 locale.setlocale(locale.LC_ALL, _languageMap[self._language])
859 else:
860 locale.setlocale(locale.LC_ALL, "")
861 else:
862 locale.setlocale(locale.LC_ALL, (self._language,
863 locale.getpreferredencoding()))
864 return self._language
865 else:
866 locale.setlocale(locale.LC_ALL, "")
867 return locale.getdefaultlocale()[0]
868
869 def log(self):
870 """Log the configuration by printing the values"""
871 print " pilot ID:", self._pilotID
872 print " rememberPassword:", self._rememberPassword
873
874 print " language:", self._language
875
876 print " hideMinimizedWindow:", self._hideMinimizedWindow
877 print " quitOnClose:", self._quitOnClose
878
879 print " onlineGateSystem:", self._onlineGateSystem
880 print " onlineACARS:", self._onlineACARS
881
882 print " flareTimeFromFS:", self._flareTimeFromFS
883 print " syncFSTime:", self._syncFSTime
884 print " usingFS2Crew:", self._usingFS2Crew
885
886 print " iasSmoothingLength:", self._iasSmoothingLength
887 print " vsSmoothingLength:", self._vsSmoothingLength
888
889 print " pirepDirectory:", self._pirepDirectory
890 print " pirepAutoSave:", self._pirepAutoSave
891
892 print " enableSounds:", self._enableSounds
893
894 print " pilotControlsSounds:", self._pilotControlsSounds
895 print " pilotHotkey:", str(self._pilotHotkey)
896
897 print " enableApproachCallouts:", self._enableApproachCallouts
898 print " speedbrakeAtTD:", self._speedbrakeAtTD
899
900 print " enableChecklists:", self._enableChecklists
901 print " checklistHotkey:", str(self._checklistHotkey)
902
903 print " autoUpdate:", self._autoUpdate
904 print " updateURL:", self._updateURL
905
906 print " messageTypeLevels:"
907 for (type, level) in self._messageTypeLevels.iteritems():
908 print " %s: %s" % (const.messageType2string(type),
909 const.messageLevel2string(level))
910
911 print " checklists:"
912 for (type, checklist) in self._checklists.iteritems():
913 print " %s:" % (const.icaoCodes[type],)
914 for path in checklist:
915 print " " + path
916
917 print " approachCallouts:"
918 for (type, approachCallouts) in self._approachCallouts.iteritems():
919 print " %s:" % (const.icaoCodes[type],)
920 for (altitude, path) in approachCallouts:
921 print " %d: %s" % (altitude, path)
922
923#-------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.