source: src/mlx/config.py@ 189:2d89178707a0

Last change on this file since 189:2d89178707a0 was 183:97e7e9479e0a, checked in by István Váradi <ivaradi@…>, 13 years ago

Added the Using FS2Crew option

File size: 23.2 KB
Line 
1# Configuration and related stuff
2# -*- encoding: utf-8 -*-
3
4#-------------------------------------------------------------------------------
5
6import const
7
8import os
9import sys
10import ConfigParser
11
12#-------------------------------------------------------------------------------
13
14configPath = os.path.join(os.path.expanduser("~"),
15 "mlx.config" if os.name=="nt" else ".mlxrc")
16
17#-------------------------------------------------------------------------------
18
19if os.name=="nt":
20 _languageMap = { "en_GB" : "eng",
21 "hu_HU" : "hun" }
22
23#-------------------------------------------------------------------------------
24
25class Hotkey(object):
26 """A hotkey."""
27 def __init__(self, ctrl = False, shift = False, key = "0"):
28 """Construct the hotkey."""
29 self.ctrl = ctrl
30 self.shift = shift
31 self.key = key
32
33 def set(self, s):
34 """Set the hotkey from the given string."""
35 self.ctrl = "C" in s[:-1]
36 self.shift = "S" in s[:-1]
37 self.key = s[-1]
38
39 def __eq__(self, other):
40 """Check if the given hotkey is equal to the other one."""
41 return self.ctrl == other.ctrl and self.shift == other.shift and \
42 self.key == other.key
43
44 def __str__(self):
45 """Construct the hotkey to a string."""
46 s = ""
47 if self.ctrl: s += "C"
48 if self.shift: s += "S"
49 s += self.key
50 return s
51
52#-------------------------------------------------------------------------------
53
54class Checklist(object):
55 """A checklist for a certain aircraft type."""
56 # The name of the section of the checklists
57 SECTION="checklists"
58
59 @staticmethod
60 def fromConfig(config, aircraftType):
61 """Create a checklist for the given aircraft type from the given
62 config."""
63 baseName = "checklist." + const.icaoCodes[aircraftType] + "."
64 fileList = []
65 while True:
66 option = baseName + str(len(fileList))
67 if config.has_option(Checklist.SECTION, option):
68 fileList.append(config.get(Checklist.SECTION, option))
69 else:
70 break
71
72 return Checklist(fileList)
73
74 def __init__(self, fileList = None):
75 """Construct the check list with the given file list."""
76 self._fileList = [] if fileList is None else fileList[:]
77
78 def clone(self):
79 """Clone the checklist."""
80 return Checklist(self._fileList)
81
82 def toConfig(self, config, aircraftType):
83 """Add this checklist to the given config."""
84 baseName = "checklist." + const.icaoCodes[aircraftType] + "."
85 for index in range(0, len(self._fileList)):
86 option = baseName + str(index)
87 config.set(Checklist.SECTION, option,
88 self._fileList[index])
89
90 def __eq__(self, other):
91 """Determine if the checklist is equal to the given other one."""
92 return self._fileList == other._fileList
93
94 def __len__(self):
95 """Get the length of the file list."""
96 return len(self._fileList)
97
98 def __getitem__(self, index):
99 """Get the file with the given index."""
100 return self._fileList[index]
101
102 def __iter__(self):
103 """Iterate over the files."""
104 return iter(self._fileList)
105
106#-------------------------------------------------------------------------------
107
108class Config(object):
109 """Our configuration."""
110 DEFAULT_UPDATE_URL = "http://mlx.varadiistvan.hu/update"
111
112 _messageTypesSection = "messageTypes"
113
114 def __init__(self):
115 """Construct the configuration with default values."""
116
117 self._pilotID = ""
118 self._password = ""
119 self._rememberPassword = False
120
121 self._language = ""
122 self._hideMinimizedWindow = True
123 self._onlineGateSystem = True
124 self._onlineACARS = True
125 self._flareTimeFromFS = False
126 self._syncFSTime = False
127 self._usingFS2Crew = False
128
129 self._pirepDirectory = None
130
131 self._enableSounds = True
132
133 self._pilotControlsSounds = True
134 self._pilotHotkey = Hotkey(ctrl = True, shift = False, key = "0")
135
136 #self._approachCallOuts = False
137 self._speedbrakeAtTD = True
138
139 self._enableChecklists = False
140 self._checklistHotkey = Hotkey(ctrl = True, shift = True, key = "0")
141
142 self._autoUpdate = True
143 self._updateURL = Config.DEFAULT_UPDATE_URL
144
145 self._messageTypeLevels = {}
146
147 self._checklists = {}
148 for aircraftType in const.aircraftTypes:
149 self._checklists[aircraftType] = Checklist()
150
151 self._modified = False
152
153 @property
154 def pilotID(self):
155 """Get the pilot ID."""
156 return self._pilotID
157
158 @pilotID.setter
159 def pilotID(self, pilotID):
160 """Set the pilot ID."""
161 if pilotID!=self._pilotID:
162 self._pilotID = pilotID
163 self._modified = True
164
165 @property
166 def password(self):
167 """Get the password."""
168 return self._password
169
170 @password.setter
171 def password(self, password):
172 """Set the password."""
173 if password!=self._password:
174 self._password = password
175 self._modified = True
176
177 @property
178 def rememberPassword(self):
179 """Get if we should remember the password."""
180 return self._rememberPassword
181
182 @rememberPassword.setter
183 def rememberPassword(self, rememberPassword):
184 """Set if we should remember the password."""
185 if rememberPassword!=self._rememberPassword:
186 self._rememberPassword = rememberPassword
187 self._modified = True
188
189 @property
190 def language(self):
191 """Get the language to use."""
192 return self._language
193
194 @language.setter
195 def language(self, language):
196 """Set the language to use."""
197 if language!=self._language:
198 self._language = language
199 self._modified = True
200
201 @property
202 def hideMinimizedWindow(self):
203 """Get whether a minimized window should be hidden."""
204 return self._hideMinimizedWindow
205
206 @hideMinimizedWindow.setter
207 def hideMinimizedWindow(self, hideMinimizedWindow):
208 """Set whether a minimized window should be hidden."""
209 if hideMinimizedWindow!=self._hideMinimizedWindow:
210 self._hideMinimizedWindow = hideMinimizedWindow
211 self._modified = True
212
213 @property
214 def onlineGateSystem(self):
215 """Get whether the online gate system should be used."""
216 return self._onlineGateSystem
217
218 @onlineGateSystem.setter
219 def onlineGateSystem(self, onlineGateSystem):
220 """Set whether the online gate system should be used."""
221 if onlineGateSystem!=self._onlineGateSystem:
222 self._onlineGateSystem = onlineGateSystem
223 self._modified = True
224
225 @property
226 def onlineACARS(self):
227 """Get whether the online ACARS system should be used."""
228 return self._onlineACARS
229
230 @onlineACARS.setter
231 def onlineACARS(self, onlineACARS):
232 """Set whether the online ACARS system should be used."""
233 if onlineACARS!=self._onlineACARS:
234 self._onlineACARS = onlineACARS
235 self._modified = True
236
237 @property
238 def flareTimeFromFS(self):
239 """Get whether the flare time should be calculated from the time values
240 returned by the simulator."""
241 return self._flareTimeFromFS
242
243 @flareTimeFromFS.setter
244 def flareTimeFromFS(self, flareTimeFromFS):
245 """Set whether the flare time should be calculated from the time values
246 returned by the simulator."""
247 if flareTimeFromFS!=self._flareTimeFromFS:
248 self._flareTimeFromFS = flareTimeFromFS
249 self._modified = True
250
251 @property
252 def syncFSTime(self):
253 """Get whether the simulator's time should be synchronized with the
254 machine's clock."""
255 return self._syncFSTime
256
257 @syncFSTime.setter
258 def syncFSTime(self, syncFSTime):
259 """Set whether the simulator's time should be synchronized with the
260 machine's clock."""
261 if syncFSTime!=self._syncFSTime:
262 self._syncFSTime = syncFSTime
263 self._modified = True
264
265 @property
266 def usingFS2Crew(self):
267 """Get whether the FS2Crew addon is being used."""
268 return self._usingFS2Crew
269
270 @usingFS2Crew.setter
271 def usingFS2Crew(self, usingFS2Crew):
272 """Set whether the FS2Crew addon is being used."""
273 if usingFS2Crew!=self._usingFS2Crew:
274 self._usingFS2Crew = usingFS2Crew
275 self._modified = True
276
277 @property
278 def pirepDirectory(self):
279 """Get the directory offered by default when saving a PIREP."""
280 return self._pirepDirectory
281
282 @pirepDirectory.setter
283 def pirepDirectory(self, pirepDirectory):
284 """Get the directory offered by default when saving a PIREP."""
285 if pirepDirectory!=self._pirepDirectory and \
286 (pirepDirectory!="" or self._pirepDirectory is not None):
287 self._pirepDirectory = None if pirepDirectory=="" \
288 else pirepDirectory
289 self._modified = True
290
291 def getMessageTypeLevel(self, messageType):
292 """Get the level for the given message type."""
293 return self._messageTypeLevels[messageType] \
294 if messageType in self._messageTypeLevels \
295 else const.MESSAGELEVEL_NONE
296
297 def isMessageTypeFS(self, messageType):
298 """Determine if the given message type is displayed in the
299 simulator."""
300 level = self.getMessageTypeLevel(messageType)
301 return level==const.MESSAGELEVEL_FS or \
302 level==const.MESSAGELEVEL_BOTH
303
304 def setMessageTypeLevel(self, messageType, level):
305 """Set the level of the given message type."""
306 if messageType not in self._messageTypeLevels or \
307 self._messageTypeLevels[messageType]!=level:
308 self._messageTypeLevels[messageType] = level
309 self._modified = True
310
311 @property
312 def enableSounds(self):
313 """Get whether background sounds are enabled."""
314 return self._enableSounds
315
316 @enableSounds.setter
317 def enableSounds(self, enableSounds):
318 """Set whether background sounds are enabled."""
319 if enableSounds!=self._enableSounds:
320 self._enableSounds = enableSounds
321 self._modified = True
322
323 @property
324 def pilotControlsSounds(self):
325 """Get whether the pilot controls the background sounds."""
326 return self._pilotControlsSounds
327
328 @pilotControlsSounds.setter
329 def pilotControlsSounds(self, pilotControlsSounds):
330 """Set whether the pilot controls the background sounds."""
331 if pilotControlsSounds!=self._pilotControlsSounds:
332 self._pilotControlsSounds = pilotControlsSounds
333 self._modified = True
334
335 @property
336 def pilotHotkey(self):
337 """Get the pilot's hotkey."""
338 return self._pilotHotkey
339
340 @pilotHotkey.setter
341 def pilotHotkey(self, pilotHotkey):
342 """Set the pilot's hotkey."""
343 if pilotHotkey!=self._pilotHotkey:
344 self._pilotHotkey = pilotHotkey
345 self._modified = True
346
347 # @property
348 # def approachCallOuts(self):
349 # """Get whether the approach callouts should be played."""
350 # return self._approachCallOuts
351
352 # @approachCallOuts.setter
353 # def approachCallOuts(self, approachCallOuts):
354 # """Set whether the approach callouts should be played."""
355 # if approachCallOuts!=self._approachCallOuts:
356 # self._approachCallOuts = approachCallOuts
357 # self._modified = True
358
359 @property
360 def speedbrakeAtTD(self):
361 """Get whether the speedbrake sounds should be played at touchdown."""
362 return self._speedbrakeAtTD
363
364 @speedbrakeAtTD.setter
365 def speedbrakeAtTD(self, speedbrakeAtTD):
366 """Set whether the speedbrake sounds should be played at touchdown."""
367 if speedbrakeAtTD!=self._speedbrakeAtTD:
368 self._speedbrakeAtTD = speedbrakeAtTD
369 self._modified = True
370
371 @property
372 def enableChecklists(self):
373 """Get whether aircraft-specific checklists should be played."""
374 return self._enableChecklists
375
376 @enableChecklists.setter
377 def enableChecklists(self, enableChecklists):
378 """Get whether aircraft-specific checklists should be played."""
379 if enableChecklists!=self._enableChecklists:
380 self._enableChecklists = enableChecklists
381 self._modified = True
382
383 @property
384 def checklistHotkey(self):
385 """Get the checklist hotkey."""
386 return self._checklistHotkey
387
388 @checklistHotkey.setter
389 def checklistHotkey(self, checklistHotkey):
390 """Set the checklist hotkey."""
391 if checklistHotkey!=self._checklistHotkey:
392 self._checklistHotkey = checklistHotkey
393 self._modified = True
394
395 @property
396 def autoUpdate(self):
397 """Get if an automatic update is needed."""
398 return self._autoUpdate
399
400 @autoUpdate.setter
401 def autoUpdate(self, autoUpdate):
402 """Set if an automatic update is needed."""
403 if autoUpdate!=self._autoUpdate:
404 self._autoUpdate = autoUpdate
405 self._modified = True
406
407 @property
408 def updateURL(self):
409 """Get the update URL."""
410 return self._updateURL
411
412 @updateURL.setter
413 def updateURL(self, updateURL):
414 """Set the update URL."""
415 if updateURL!=self._updateURL:
416 self._updateURL = updateURL
417 self._modified = True
418
419 def getChecklist(self, aircraftType):
420 """Get the checklist for the given aircraft type."""
421 return self._checklists[aircraftType]
422
423 def setChecklist(self, aircraftType, checklist):
424 """Set the checklist for the given aircraft type."""
425 if checklist!=self._checklists[aircraftType]:
426 self._checklists[aircraftType] = checklist.clone()
427 self._modified = True
428
429 def load(self):
430 """Load the configuration from its default location."""
431 config = ConfigParser.RawConfigParser()
432 config.read(configPath)
433
434 self._pilotID = self._get(config, "login", "id", "")
435 self._password = self._get(config, "login", "password", "")
436 self._rememberPassword = self._getBoolean(config, "login",
437 "rememberPassword", False)
438
439 self._language = self._get(config, "general", "language", "")
440 self._hideMinimizedWindow = self._getBoolean(config, "general",
441 "hideMinimizedWindow",
442 True)
443 self._onlineGateSystem = self._getBoolean(config, "general",
444 "onlineGateSystem",
445 True)
446 self._onlineACARS = self._getBoolean(config, "general",
447 "onlineACARS", True)
448 self._flareTimeFromFS = self._getBoolean(config, "general",
449 "flareTimeFromFS",
450 False)
451 self._syncFSTime = self._getBoolean(config, "general",
452 "syncFSTime",
453 False)
454 self._usingFS2Crew = self._getBoolean(config, "general",
455 "usingFS2Crew",
456 False)
457 self._pirepDirectory = self._get(config, "general",
458 "pirepDirectory", None)
459
460 self._messageTypeLevels = {}
461 for messageType in const.messageTypes:
462 self._messageTypeLevels[messageType] = \
463 self._getMessageTypeLevel(config, messageType)
464
465 self._enableSounds = self._getBoolean(config, "sounds",
466 "enable", True)
467 self._pilotControlsSounds = self._getBoolean(config, "sounds",
468 "pilotControls", True)
469 self._pilotHotkey.set(self._get(config, "sounds",
470 "pilotHotkey", "C0"))
471 #self._approachCallOuts = self._getBoolean(config, "sounds",
472 # "approachCallOuts", False)
473 self._speedbrakeAtTD = self._getBoolean(config, "sounds",
474 "speedbrakeAtTD", True)
475
476 self._enableChecklists = self._getBoolean(config, "sounds",
477 "enableChecklists", False)
478 self._checklistHotkey.set(self._get(config, "sounds",
479 "checklistHotkey", "CS0"))
480
481 self._autoUpdate = self._getBoolean(config, "update", "auto", True)
482 self._updateURL = self._get(config, "update", "url",
483 Config.DEFAULT_UPDATE_URL)
484
485 for aircraftType in const.aircraftTypes:
486 self._checklists[aircraftType] = \
487 Checklist.fromConfig(config, aircraftType)
488
489 self._modified = False
490
491 def save(self):
492 """Save the configuration file if it has been modified."""
493 if not self._modified:
494 return
495
496 config = ConfigParser.RawConfigParser()
497
498 config.add_section("login")
499 config.set("login", "id", self._pilotID)
500 config.set("login", "password", self._password)
501 config.set("login", "rememberPassword",
502 "yes" if self._rememberPassword else "no")
503
504 config.add_section("general")
505 if self._language:
506 config.set("general", "language", self._language)
507 config.set("general", "hideMinimizedWindow",
508 "yes" if self._hideMinimizedWindow else "no")
509 config.set("general", "onlineGateSystem",
510 "yes" if self._onlineGateSystem else "no")
511 config.set("general", "onlineACARS",
512 "yes" if self._onlineACARS else "no")
513 config.set("general", "flareTimeFromFS",
514 "yes" if self._flareTimeFromFS else "no")
515 config.set("general", "syncFSTime",
516 "yes" if self._syncFSTime else "no")
517 config.set("general", "usingFS2Crew",
518 "yes" if self._usingFS2Crew else "no")
519
520 if self._pirepDirectory is not None:
521 config.set("general", "pirepDirectory", self._pirepDirectory)
522
523 config.add_section(Config._messageTypesSection)
524 for messageType in const.messageTypes:
525 if messageType in self._messageTypeLevels:
526 option = self._getMessageTypeLevelOptionName(messageType)
527 level = self._messageTypeLevels[messageType]
528 config.set(Config._messageTypesSection, option,
529 const.messageLevel2string(level))
530
531 config.add_section("sounds")
532 config.set("sounds", "enable",
533 "yes" if self._enableSounds else "no")
534 config.set("sounds", "pilotControls",
535 "yes" if self._pilotControlsSounds else "no")
536 config.set("sounds", "pilotHotkey", str(self._pilotHotkey))
537 #config.set("sounds", "approachCallOuts",
538 # "yes" if self._approachCallOuts else "no")
539 config.set("sounds", "speedbrakeAtTD",
540 "yes" if self._speedbrakeAtTD else "no")
541
542 config.set("sounds", "enableChecklists",
543 "yes" if self._enableChecklists else "no")
544 config.set("sounds", "checklistHotkey",
545 str(self._checklistHotkey))
546
547 config.add_section("update")
548 config.set("update", "auto",
549 "yes" if self._autoUpdate else "no")
550 config.set("update", "url", self._updateURL)
551
552 config.add_section(Checklist.SECTION)
553 for aircraftType in const.aircraftTypes:
554 self._checklists[aircraftType].toConfig(config, aircraftType)
555
556 try:
557 fd = os.open(configPath, os.O_CREAT|os.O_TRUNC|os.O_WRONLY,
558 0600)
559 with os.fdopen(fd, "wt") as f:
560 config.write(f)
561 self._modified = False
562 except Exception, e:
563 print >> sys.stderr, "Failed to update config: " + str(e)
564
565 def _getBoolean(self, config, section, option, default):
566 """Get the given option as a boolean, if found in the given config,
567 otherwise the default."""
568 return config.getboolean(section, option) \
569 if config.has_option(section, option) \
570 else default
571
572 def _get(self, config, section, option, default):
573 """Get the given option as a string, if found in the given config,
574 otherwise the default."""
575 return config.get(section, option) \
576 if config.has_option(section, option) \
577 else default
578
579 def _getMessageTypeLevel(self, config, messageType):
580 """Get the message type level for the given message type."""
581 option = self._getMessageTypeLevelOptionName(messageType)
582 if config.has_option(Config._messageTypesSection, option):
583 value = config.get(Config._messageTypesSection, option)
584 return const.string2messageLevel(value)
585 elif messageType in [const.MESSAGETYPE_LOGGER_ERROR,
586 const.MESSAGETYPE_FAULT,
587 const.MESSAGETYPE_NOGO,
588 const.MESSAGETYPE_GATE_SYSTEM,
589 const.MESSAGETYPE_HELP]:
590 return const.MESSAGELEVEL_BOTH
591 else:
592 return const.MESSAGELEVEL_FS
593
594 def _getMessageTypeLevelOptionName(self, messageType):
595 """Get the option name for the given message type level."""
596 return const.messageType2string(messageType)
597
598 def setupLocale(self):
599 """Setup the locale based on the language set.
600
601 Return True if a specific language was set, False otherwise."""
602 import locale
603 if self._language:
604 print "Setting up locale for", self._language
605 os.environ["LANGUAGE"] = self._language
606 langAndEncoding = self._language + "." + locale.getpreferredencoding()
607 os.environ["LANG"] = langAndEncoding
608 os.environ["LC_MESSAGES"] = langAndEncoding
609 os.environ["LC_COLLATE"] = langAndEncoding
610 os.environ["LC_CTYPE"] = langAndEncoding
611 os.environ["LC_MONETARY"] = langAndEncoding
612 os.environ["LC_NUMERIC"] = langAndEncoding
613 os.environ["LC_TIME"] = langAndEncoding
614 return True
615 else:
616 return False
617
618 def getLanguage(self):
619 """Get the language to be used."""
620 import locale
621 if self._language:
622 if os.name=="nt":
623 if self._language in _languageMap:
624 locale.setlocale(locale.LC_ALL, _languageMap[self._language])
625 else:
626 locale.setlocale(locale.LC_ALL, "")
627 else:
628 locale.setlocale(locale.LC_ALL, (self._language,
629 locale.getpreferredencoding()))
630 return self._language
631 else:
632 locale.setlocale(locale.LC_ALL, "")
633 return locale.getdefaultlocale()[0]
634
635#-------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.