Completed
Push — master ( 7beec5...72ed44 )
by Marek
17s queued 14s
created

OptionsDlg.onChangePassword()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 4
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
#
2
#  Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/]
3
#
4
#  This file is part of Outer Space.
5
#
6
#  Outer Space is free software; you can redistribute it and/or modify
7
#  it under the terms of the GNU General Public License as published by
8
#  the Free Software Foundation; either version 2 of the License, or
9
#  (at your option) any later version.
10
#
11
#  Outer Space is distributed in the hope that it will be useful,
12
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#  GNU General Public License for more details.
15
#
16
#  You should have received a copy of the GNU General Public License
17
#  along with Outer Space; if not, write to the Free Software
18
#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
21
import os
22
import os.path
23
import gettext
24
import re
25
26
import pygame
27
import pygameui as ui
28
from osci import client, gdata, res
29
import ige.ospace.Const as Const
30
from ige import log
31
import resources
32
33
from ChangePasswordDlg import ChangePasswordDlg
34
35
class OptionsDlg:
36
    """Displays options dialog.
37
38
    Dialog can change display flags, display resolution, client language
39
    and proxy settings.
40
    Proxy can have one of following formats:
41
    http://username:password@host:port
42
    http://username@host:port
43
    http://host:port
44
    http://host
45
    where port must be integer value.
46
    Options are saved to file imediately, after users press OK button.
47
    """
48
49
50
    def __init__(self, app):
51
        self.app = app
52
        self.changePasswordDlg = ChangePasswordDlg(app)
53
        self.languages = {}
54
        self.languages['en']=_('English')
55
        self.languages['cs']=_('Czech')
56
        self.languages['fr']=_('French')
57
        self.languages['de']=_('German')
58
        self.resolutions = ["FULLSCREEN", "800x600", "1024x768", "1280x800", "1280x1024", "1366x768", "1440x900","1400x1050","1600x900","1680x1050","1600x1200","1920x1080","1920x1200"]
59
        self.curLang = gdata.config.client.language
60
        self.createUI()
61
62
    def display(self, caller = None, message = None):
63
        self.caller = caller
64
        if message is not None:
65
            self.win.setStatus(message)
66
        self.show()
67
        # show window
68
        if not self.win.visible:
69
            self.win.show()
70
71
    def hide(self):
72
        self.win.setStatus(_("Ready."))
73
        self.win.hide()
74
75
    def update(self):
76
        if self.win.visible:
77
            self.show()
78
79
    def show(self):
80
        # reading resolution info
81
        if gdata.config.display.resolution != None:
82
            resolution = gdata.config.display.resolution
83
            self.win.vResolution2.text = resolution
84
85
        self.win.vResolution.text = _("Select Mode")
86
        self.win.vResolution.action = "onSelectResolution"
87
88
        # reading client language
89
        if gdata.config.client.language != None:
90
            lang = gdata.config.client.language
91
            try:
92
                self.win.vLangSel.text = self.languages[lang]
93
            except:
94
                self.win.vLangSel.text = lang
95
96
        # reading proxy settings
97
        if gdata.config.proxy.http != None:
98
            proxy = gdata.config.proxy.http
99
            m = re.match('^http://(.*?):(.*?)@(.*?):(\d+)', proxy)
100
            host = ''
101
            port = ''
102
            username = ''
103
            password = ''
104
            if m == None:
105
                m = re.match('^http://(.*?)@(.*?):(\d+)', proxy)
106
                if m == None:
107
                    m = re.match('^http://(.*?):(\d+)', proxy)
108
                    if m == None:
109
                        m = re.match('^http://(.*?)', proxy)
110
                        if m != None:
111
                            host = m.group(1)
112
                    else:
113
                        host = m.group(1)
114
                        port = m.group(2)
115
                else:
116
                    username = m.group(1)
117
                    host = m.group(2)
118
                    port = m.group(3)
119
            else:
120
                username = m.group(1)
121
                password = m.group(2)
122
                host = m.group(3)
123
                port = m.group(4)
124
125
            self.win.vProxyHost.text = host
126
            self.win.vProxyPort.text = port
127
            self.win.vProxyUsername.text = username
128
            self.win.vProxyPassword.text = password
129
130
        self.win.vTheme.text = _("Select Theme")
131
        self.win.vTheme2.text = gdata.config.client.theme
132
        self.win.vTheme.action = "onSelectTheme"
133
134
        # reading defaults
135
        if gdata.config.defaults.reportfinalization != None:
136
            val = gdata.config.defaults.reportfinalization
137
            self.win.vReportFin.checked = val == 'yes'
138
139
        if gdata.config.defaults.showredirects != None:
140
            val = gdata.config.defaults.showredirects
141
            self.win.vRedirects.checked = val == 'yes'
142
143
        if gdata.config.defaults.showcoords != None:
144
            val = gdata.config.defaults.showcoords
145
            self.win.vCoords.checked = val == 'yes'
146
147
        if gdata.config.defaults.highlights != None:
148
            val = gdata.config.defaults.highlights
149
            self.win.vHighlights.checked = val == 'yes'
150
151
        if gdata.config.defaults.displayhelp != None:
152
            val = gdata.config.defaults.displayhelp
153
            self.win.vDisplayHelp.checked = val == 'yes'
154
155
        if gdata.config.defaults.showminimap != None:
156
            val = gdata.config.defaults.showminimap
157
            self.win.vShowMinimap.checked = val == 'yes'
158
159
        if gdata.config.defaults.showgatesystems != None:
160
            val = gdata.config.defaults.showgatesystems
161
            self.win.vShowGateSystems.checked = val == 'yes'
162
163
        if gdata.config.defaults.showmapgrid != None:
164
            val = gdata.config.defaults.showmapgrid
165
            self.win.vShowMapGrid.checked = val == 'yes'
166
167
        if gdata.config.defaults.showmapscanners != None:
168
            val = gdata.config.defaults.showmapscanners
169
            self.win.vShowMapScanners.checked = val == 'yes'
170
171
        if gdata.config.defaults.showfleetlines != None:
172
            val = gdata.config.defaults.showfleetlines
173
            self.win.vShowMapFleetLines.checked = val == 'yes'
174
175
        if gdata.config.defaults.alternateviewmode != None:
176
            val = gdata.config.defaults.alternateviewmode
177
            self.win.vShowAlternateView.checked = val == 'yes'
178
179
        if gdata.config.defaults.showPlayerZones != None:
180
            val = gdata.config.defaults.showplayerzones
181
            self.win.vShowPlayerZones.checked = val == 'yes'
182
183
        # login defaults
184
        self.win.vAutoLogin.enabled = False
185
        if gdata.savePassword:
186
            self.win.vSavePassword.enabled = True
187
            self.win.vSavePassword.checked = True
188
            self.win.vAutoLogin.enabled = True
189
        elif (gdata.config.game.lastpasswordcrypted != None) and (gdata.config.game.lastpasswordcrypted != ''):
190
            self.win.vSavePassword.enabled = True
191
            self.win.vSavePassword.checked = False
192
        else:
193
            self.win.vSavePassword.enabled = False
194
            self.win.vSavePassword.checked = False
195
196
        if gdata.config.game.autologin != None:
197
            val = gdata.config.game.autologin
198
            if self.win.vAutoLogin.enabled:
199
                self.win.vAutoLogin.checked = val == 'yes'
200
201
        # sounds/music
202
        if gdata.config.defaults.sound != None:
203
            val = gdata.config.defaults.sound
204
        else:
205
            val = "no"
206
        self.win.vSoundEnabled.checked = val == "yes"
207
        self.win.vSoundVolume.slider.min = 0
208
        self.win.vSoundVolume.slider.max = 110
209
        if gdata.config.defaults.soundvolume != None:
210
            val = float(gdata.config.defaults.soundvolume)
211
        else:
212
            val = 100
213
        self.win.vSoundVolume.slider.position = val
214
        # disabled because of a bug in pygame
215
        self.win.vSoundEnabled.enabled = False
216
        self.win.vSoundVolume.enabled = False
217
218
        if gdata.config.defaults.music != None:
219
            val = gdata.config.defaults.music
220
        else:
221
            val = "no"
222
        self.win.vMusicEnabled.checked = val == "yes"
223
        self.win.vMusicVolume.slider.min = 0
224
        self.win.vMusicVolume.slider.max = 110
225
        if gdata.config.defaults.musicvolume != None:
226
            val = float(gdata.config.defaults.musicvolume)
227
        else:
228
            val = 100
229
        self.win.vMusicVolume.slider.position = val
230
        # disabled because of a bug in pygame
231
        self.win.vMusicEnabled.enabled = False
232
        self.win.vMusicVolume.enabled = False
233
234
        self.win.vChangePassword.enabled = client.db is not None
235
236
    def onCancel(self, widget, action, data):
237
        self.hide()
238
        if self.caller:
239
            self.caller.display()
240
241
    def onOK(self, widget, action, data):
242
        # set client language
243
        gdata.config.client.language = self.curLang
244
245
        # set proxy
246
        host = self.win.vProxyHost.text
247
        port = self.win.vProxyPort.text
248
        username = self.win.vProxyUsername.text
249
        password = self.win.vProxyPassword.text
250
251
        proxy = ''
252
        # host must be always present
253
        if len(host) > 0:
254
            proxy += host
255
            if len(port) > 0:
256
                proxy += ':'
257
                proxy += port
258
            if len(password) > 0 and len(username):
259
                proxy = username + ':' + password + '@' + proxy
260
            elif len(username) > 0:
261
                proxy = username + '@' + proxy
262
263
            if len(proxy) > 0:
264
                proxy = 'http://' + proxy
265
266
        if len(proxy) > 0:
267
            gdata.config.proxy.http = proxy
268
        else:
269
            # if host not present, delete proxy section
270
            gdata.config.proxy = None
271
272
        # defaults
273
        if self.win.vReportFin.checked:
274
            gdata.config.defaults.reportfinalization = 'yes'
275
        else:
276
            gdata.config.defaults.reportfinalization = 'no'
277
278
        if self.win.vRedirects.checked:
279
            gdata.config.defaults.showredirects = 'yes'
280
        else:
281
            gdata.config.defaults.showredirects = 'no'
282
283
        if self.win.vCoords.checked:
284
            gdata.config.defaults.showcoords = 'yes'
285
        else:
286
            gdata.config.defaults.showcoords = 'no'
287
288
        if self.win.vHighlights.checked:
289
            gdata.config.defaults.highlights = 'yes'
290
        else:
291
            gdata.config.defaults.highlights = 'no'
292
293
        if self.win.vDisplayHelp.checked:
294
            gdata.config.defaults.displayhelp = 'yes'
295
        else:
296
            gdata.config.defaults.displayhelp = 'no'
297
298
        if self.win.vShowMinimap.checked:
299
            gdata.config.defaults.showminimap = 'yes'
300
        else:
301
            gdata.config.defaults.showminimap = 'no'
302
303
        if self.win.vShowGateSystems.checked:
304
            gdata.config.defaults.showgatesystems = 'yes'
305
        else:
306
            gdata.config.defaults.showgatesystems = 'no'
307
308
        if self.win.vShowMapGrid.checked:
309
            gdata.config.defaults.showmapgrid = 'yes'
310
        else:
311
            gdata.config.defaults.showmapgrid = 'no'
312
313
        if self.win.vShowMapScanners.checked:
314
            gdata.config.defaults.showmapscanners = 'yes'
315
        else:
316
            gdata.config.defaults.showmapscanners = 'no'
317
318
        if self.win.vShowMapFleetLines.checked:
319
            gdata.config.defaults.showfleetlines = 'yes'
320
        else:
321
            gdata.config.defaults.showfleetlines = 'no'
322
323
        if self.win.vShowAlternateView.checked:
324
            gdata.config.defaults.alternateviewmode = 'yes'
325
        else:
326
            gdata.config.defaults.alternateviewmode = 'no'
327
328
329
        if self.win.vShowPlayerZones.checked:
330
            gdata.config.defaults.showplayerzones = 'yes'
331
        else:
332
            gdata.config.defaults.showplayerzones = 'no'
333
334
335
336
        if self.win.vAutoLogin.checked:
337
            gdata.config.game.autologin = 'yes'
338
        else:
339
            gdata.config.game.autologin = 'no'
340
341
        if self.win.vSavePassword.checked:
342
            gdata.savePassword = True
343
        else:
344
            gdata.savePassword = False
345
            gdata.config.game.lastpasswordcrypted = None
346
347
        gdata.config.defaults.sound = ("no", "yes")[int(self.win.vSoundEnabled.checked)]
348
        gdata.config.defaults.soundvolume = self.win.vSoundVolume.slider.position
349
        gdata.config.defaults.music = ("no", "yes")[int(self.win.vMusicEnabled.checked)]
350
        gdata.config.defaults.musicvolume = self.win.vMusicVolume.slider.position
351
        ui.SkinableTheme.enableMusic(self.win.vMusicEnabled.checked)
352
        ui.SkinableTheme.enableSound(self.win.vSoundEnabled.checked)
353
354
        self.hide()
355
        if self.caller:
356
            self.caller.display()    # Redisplay login dlg
357
        elif gdata.mainGameDlg:
358
            gdata.mainGameDlg.update(configUpdated=True) # redraw screen (highlights etc)
359
360
361
    def onSmallRes(self, widget, action, data):
362
        self.win.vLargeRes.pressed = 0
363
        self.win.vMediumRes.pressed = 0
364
365
    def onMediumRes(self, widget, action, data):
366
        self.win.vSmallRes.pressed = 0
367
        self.win.vLargeRes.pressed = 0
368
369
    def onLargeRes(self, widget, action, data):
370
        self.win.vSmallRes.pressed = 0
371
        self.win.vMediumRes.pressed = 0
372
373
    def onEnglish(self, widget, action, data):
374
        self.win.vCzech.pressed = 0
375
        self.win.vEnglish.pressed = 1
376
377
    def onCzech(self, widget, action, data):
378
        self.win.vEnglish.pressed = 0
379
        self.win.vCzech.pressed = 1
380
381
    def onSelectTheme(self, widget, action, data):
382
        items = []
383
        themeDir = resources.get("themes")
384
        for term in os.listdir(themeDir):
385
            if os.path.isfile(os.path.join(themeDir, term, "config.ini")) and not term.startswith("."):
386
                item = ui.Item(term, tTheme = term)
387
                items.append(item)
388
        self.twin.vThemes.items = items
389
        self.twin.vThemes.itemsChanged()
390
        self.twin.show()
391
392
    def onThemeCancel(self, widget, action, data):
393
        self.twin.hide()
394
395
    def onThemeSelected(self, widget, action, data):
396
        self.recipientObjID = []
397
        text = ""
398
        if not self.twin.vThemes.selection:
399
            return
400
        curTheme = self.twin.vThemes.selection[0].tTheme
401
        # set theme for ui
402
        ui.SkinableTheme.setSkin(os.path.join(resources.get("themes"), curTheme))
403
        res.prepareUIIcons(ui.SkinableTheme.themeIcons)
404
        ui.SkinableTheme.loadMusic(gdata.config.defaults.mymusic)
405
        ui.SkinableTheme.playMusic()
406
        # update foreground colors
407
        gdata.sevColors[gdata.CRI] = (ui.SkinableTheme.themeCritical)
408
        gdata.sevColors[gdata.MAJ] = (ui.SkinableTheme.themeMajor)
409
        gdata.sevColors[gdata.MIN] = (ui.SkinableTheme.themeMinor)
410
        gdata.sevColors[gdata.NONE] = (ui.SkinableTheme.themeNone)
411
        gdata.sevColors[gdata.DISABLED] = (ui.SkinableTheme.themeDisabled)
412
        # all OK? (no exception) -> store settings
413
        gdata.config.client.theme = curTheme
414
        self.win.vTheme2.text = curTheme
415
        self.twin.hide()
416
417
    def onSelectLanguage(self, widget, action, data):
418
        items = []
419
        items.append(ui.Item(self.languages['en'],tLanguage = 'en'))
420
        langDir = resources.get('translations')
421
        for term in os.listdir(langDir):
422
            if os.path.isfile(os.path.join(langDir, term,"LC_MESSAGES", "OSPACE.mo")) and not term.startswith("."):
423
                if self.languages.has_key(term):
424
                    item = ui.Item(self.languages[term], tLanguage = term)
425
                else:
426
                    item = ui.Item(term, tLanguage = term)
427
                items.append(item)
428
        self.lwin.vLanguages.items = items
429
        self.lwin.vLanguages.itemsChanged()
430
        self.lwin.show()
431
432
    def onLanguageCancel(self, widget, action, data):
433
        self.lwin.hide()
434
435
    def onLanguageSelected(self, widget, action, data):
436
        self.recipientObjID = []
437
        text = ""
438
        if not self.lwin.vLanguages.selection:
439
            return
440
        self.curLang = self.lwin.vLanguages.selection[0].tLanguage
441
        self.lwin.hide()
442
        if self.curLang == 'en':
443
            tran = gettext.NullTranslations()
444
        else:
445
            tran = gettext.translation('OSPACE', resources.get('translations'), languages = [self.curLang])
446
        tran.install(unicode = 1)
447
        try:
448
            self.win.vLangSel.text = self.languages[self.curLang]
449
        except:
450
            self.win.vLangSel.text = self.curLang
451
        self.win.setStatus(_("You should restart client to change the language."))
452
453
454
    def onSelectResolution(self, widget, action, data):
455
        items = []
456
        for mode in self.resolutions:
457
            items.append(ui.Item(mode,tRes = mode))
458
        self.reswin.vResolutions.items = items
459
        self.reswin.vResolutions.itemsChanged()
460
        self.reswin.show()
461
462
    def onResolutionCancel(self, widget, action, data):
463
        self.reswin.hide()
464
465
    def onResolutionSelected(self, widget, action, data):
466
        if not self.reswin.vResolutions.selection:
467
            return
468
        curMode = self.reswin.vResolutions.selection[0].tRes
469
        if curMode != "FULLSCREEN":
470
            try:
471
                width,height = curMode.split('x')
472
            except:
473
                self.win.setStatus(_("The mode you selected is not properly formatted."))
474
        gdata.config.display.resolution = curMode
475
        self.win.vResolution2.text = curMode
476
        self.reswin.hide()
477
        self.win.setStatus(_("You have to restart client to change the resolution."))
478
479
    def onChangeMusicVolume(self, widget, action, data):
480
        ui.SkinableTheme.setMusicVolume(float(self.win.vMusicVolume.slider.position) / 100.0)
481
482
    def onChangeSoundVolume(self, widget, action, data):
483
        ui.SkinableTheme.enableSound(self.win.vSoundEnabled.checked)
484
        ui.SkinableTheme.setVolume(self.win.vSoundVolume.slider.position / 100.0)
485
486
    def onChangeSavePassword(self, widget, action, data):
487
        if self.win.vSavePassword.checked:
488
            self.win.vAutoLogin.enabled = True
489
        else:
490
            self.win.vAutoLogin.enabled = False
491
            self.win.vAutoLogin.checked = False
492
493
    def onChangePassword(self, widget, action, data):
494
        self.changePasswordDlg.display(self)
495
496
    def createUI(self):
497
        screenWidth, screenHeight = gdata.scrnSize
498
        # size of dialog in layout metrics (for SimpleGridLM)
499
        cols = 33
500
        rows = 18
501
        # dialog width and height in pixels
502
        width = cols * 20 + 5
503
        height = rows * 20 + 4
504
        #creating dialog window
505
        self.win = ui.Window(self.app,
506
            modal = 1,
507
            escKeyClose = 1,
508
            movable = 0,
509
            title = _("Options"),
510
            rect = ui.Rect((screenWidth - width) / 2, (screenHeight - height) / 2, width, height),
511
            layoutManager = ui.SimpleGridLM(),
512
            tabChange = True
513
        )
514
        self.win.subscribeAction('*', self)
515
        # first row is window title
516
        rows -= 1
517
518
        # Resolution
519
        ui.Title(self.win, layout = (1, 1, 5, 1), text = _('Resolution'),
520
            align = ui.ALIGN_NONE, font = 'normal-bold')
521
522
        ui.Button(self.win, layout = (1, 2, 5, 1), id = "vResolution", align = ui.ALIGN_W)
523
        ui.ActiveLabel(self.win, layout = (1, 3, 5, 1), id = "vResolution2")
524
        width = 304  # 15 * 20 + 4
525
        height = 264 # 13 * 20 + 4
526
        self.reswin = ui.Window(self.app,
527
            modal = 1,
528
            escKeyClose = 1,
529
            titleOnly = 0,
530
            movable = 0,
531
            title = _("Select resolution"),
532
            rect = ui.Rect((screenWidth - width) / 2, (screenHeight - height) / 2, width, height),
533
            layoutManager = ui.SimpleGridLM(),
534
        )
535
        self.reswin.subscribeAction('*', self)
536
        # rename
537
        ui.Listbox(self.reswin, layout = (0, 0, 15, 11), id = 'vResolutions', columnLabels = 0,
538
            columns = ((None, 'text', 0, ui.ALIGN_W),), multiselection = 0)
539
        # status bar + submit/cancel
540
        ui.TitleButton(self.reswin, layout = (10, 11, 5, 1), text = _("Select"), action = 'onResolutionSelected')
541
        ui.TitleButton(self.reswin, layout = (5, 11, 5, 1), text = _("Cancel"), action = 'onResolutionCancel')
542
        ui.Title(self.reswin, id = 'vStatusBar', layout = (0, 11, 5, 1), align = ui.ALIGN_W)
543
544
        # Languages
545
        ui.Title(self.win, layout = (1, 5, 5, 1), text = _('Language'),
546
            align = ui.ALIGN_NONE, font = 'normal-bold')
547
        try:
548
            longLang = self.languages[self.curLang]
549
        except:
550
            longLang = self.curLang
551
        ui.Button(self.win, layout = (1, 6, 5, 1), text = longLang, id = 'vLangSel', action = 'onSelectLanguage')
552
        lcols = 12
553
        lrows = 6
554
        width = lcols * 20 + 4
555
        height = lrows * 20 + 4
556
        self.lwin = ui.Window(self.app,
557
            modal = 1,
558
            escKeyClose = 1,
559
            titleOnly = 0,
560
            movable = 0,
561
            title = _("Select language"),
562
            rect = ui.Rect((screenWidth - width) / 2, (screenHeight - height) / 2, width, height),
563
            layoutManager = ui.SimpleGridLM(),
564
        )
565
        self.lwin.subscribeAction('*', self)
566
        # rename
567
        ui.Listbox(self.lwin, layout = (0, 0, lcols, lrows-2), id = 'vLanguages', columnLabels = 0,
568
            columns = ((None, 'text', 0, ui.ALIGN_W),), multiselection = 0, sortedBy=('text', 1))
569
        # status bar + submit/cancel
570
        ui.TitleButton(self.lwin, layout = (lcols-5, lrows-2, 5, 1), text = _("Select"), action = 'onLanguageSelected')
571
        ui.TitleButton(self.lwin, layout = (lcols-10, lrows-2, 5, 1), text = _("Cancel"), action = 'onLanguageCancel')
572
        ui.Title(self.lwin, id = 'vStatusBar', layout = (0, lrows-2, lcols-10, 1), align = ui.ALIGN_W)
573
574
        # Theme
575
        ui.Title(self.win, layout = (1, 9, 5, 1), text = _('Themes'),
576
            align = ui.ALIGN_NONE, font = 'normal-bold')
577
        ui.Button(self.win, layout = (1, 10, 5, 1), id = "vTheme", align = ui.ALIGN_W)
578
        ui.ActiveLabel(self.win, layout = (1, 11, 5, 1), id = "vTheme2")
579
        width = 304  # 15 * 20 + 4
580
        height = 264 # 13 * 20 + 4
581
        self.twin = ui.Window(self.app,
582
            modal = 1,
583
            escKeyClose = 1,
584
            titleOnly = 0,
585
            movable = 0,
586
            title = _("Select theme"),
587
            rect = ui.Rect((screenWidth - width) / 2, (screenHeight - height) / 2, width, height),
588
            layoutManager = ui.SimpleGridLM(),
589
        )
590
        self.twin.subscribeAction('*', self)
591
592
        # rename
593
        ui.Listbox(self.twin, layout = (0, 0, 15, 11), id = 'vThemes', columnLabels = 0,
594
            columns = ((None, 'text', 0, ui.ALIGN_W),), multiselection = 0, sortedBy=('text', 1))
595
        # status bar + submit/cancel
596
        ui.TitleButton(self.twin, layout = (10, 11, 5, 1), text = _("Select"), action = 'onThemeSelected')
597
        ui.TitleButton(self.twin, layout = (5, 11, 5, 1), text = _("Cancel"), action = 'onThemeCancel')
598
        ui.Title(self.twin, id = 'vStatusBar', layout = (0, 11, 5, 1), align = ui.ALIGN_W)
599
600
        # Defaults
601
        ui.Title(self.win, layout = (7, 7, 25, 1), text = _('Default settings'),
602
            align = ui.ALIGN_NONE, font = 'normal-bold')
603
        ui.Check(self.win, layout = (7, 8, 8, 1), text = _('Report finalization'), id = 'vReportFin',
604
            checked = 0)
605
        ui.Check(self.win, layout = (15, 8, 8, 1), text = _('Display help/tooltip'), id = 'vDisplayHelp',
606
            checked = 1)
607
        ui.Check(self.win, layout = (23, 8, 9, 1), text = _('Show coordinates'), id = 'vCoords',
608
            checked = 1)
609
        ui.Check(self.win, layout = (7 ,9 ,8 ,1), text = _('Players highlight'), id = 'vHighlights',
610
            checked = 1)
611
        ui.Check(self.win, layout = (15, 9, 8, 1), text = _('Show minimap'), id = 'vShowMinimap',
612
            checked = 1)
613
        ui.Check(self.win, layout = (23, 9, 8, 1), text = _('Show gate systems'), id = 'vShowGateSystems',
614
            checked = 1)
615
        ui.Check(self.win, layout = (7, 10, 8, 1), text = _('Show redirects'), id = 'vRedirects',
616
            checked = 1, tooltipTitle = _('Starmap hotkey:'), tooltip = _('CTRL-R'))
617
        ui.Check(self.win, layout = (15, 10, 8, 1), text = _('Show map grid'), id = 'vShowMapGrid',
618
            checked = 1, tooltipTitle = _('Starmap hotkey'), tooltip = _('CTRL-G'))
619
        ui.Check(self.win, layout = (23, 10, 8, 1), text = _('Alternate system info'), id = 'vShowAlternateView',
620
            checked = 0, tooltipTitle = _('Starmap hotkey'), tooltip = _('CTRL-A'))
621
        ui.Check(self.win, layout = (7, 11, 8, 1), text = _('Show map scanners'), id = 'vShowMapScanners',
622
            checked = 1, tooltipTitle = _('Starmap hotkey'), tooltip = _('CTRL-S'))
623
        ui.Check(self.win, layout = (15, 11, 8, 1), text = _('Show fleet lines'), id = 'vShowMapFleetLines',
624
            checked = 1, tooltipTitle = _('Starmap hotkey'), tooltip = _('CTRL-L'))
625
        ui.Check(self.win, layout = (23, 11, 8, 1), text = _('Show player zones'), id = 'vShowPlayerZones',
626
            checked = 0, tooltipTitle = _('Starmap hotkey'), tooltip = _('CTRL-P'))
627
628
        # Login settings
629
        ui.Title(self.win, layout = (7,13, 15, 1), text = _('Login settings'),
630
            align = ui.ALIGN_NONE, font = 'normal-bold')
631
        ui.Check(self.win, layout = (15,14,8,1), text = _('Auto-login'), id = 'vAutoLogin',
632
            checked = 0)
633
        ui.Check(self.win, layout = (7,14,8,1), text = _('Remember password'), id = 'vSavePassword',
634
            checked = 0, action = "onChangeSavePassword")
635
        ui.Button(self.win, layout = (23.5, 13, 9, 1), id = "vChangePassword", text = _("Change password"), action = 'onChangePassword', align = ui.ALIGN_NONE)
636
637
        # proxy settings
638
        ui.Title(self.win, layout = (13, 1, 9, 1), text = _('Proxy'), font = 'normal-bold')
639
        ui.Label(self.win, layout = (13, 2, 4, 1), text = _('Host:'), align = ui.ALIGN_E)
640
        ui.Entry(self.win, layout = (17, 2, 5, 1), id = 'vProxyHost', align = ui.ALIGN_W, orderNo = 1)
641
        ui.Label(self.win, layout = (13, 3, 4, 1), text = _('Port:'), align = ui.ALIGN_E)
642
        ui.Entry(self.win, layout = (17, 3, 5, 1), id = 'vProxyPort', align = ui.ALIGN_W, orderNo = 2)
643
        ui.Label(self.win, layout = (13, 4, 4, 1), text = _('Username:'), align = ui.ALIGN_E)
644
        ui.Entry(self.win, layout = (17, 4, 5, 1), id = 'vProxyUsername', align = ui.ALIGN_W, orderNo = 3)
645
        ui.Label(self.win, layout = (13, 5, 4, 1), text = _('Password:'), align = ui.ALIGN_E)
646
        ui.Entry(self.win, layout = (17, 5, 5, 1), id = 'vProxyPassword', align = ui.ALIGN_W, orderNo = 4)
647
648
        # sound options
649
        ui.Title(self.win, layout = (23, 1, 9, 1), text = _('Sound / Music'), font = 'normal-bold')
650
        ui.Check(self.win, layout = (23, 2, 9, 1), text = _('Sounds'), id = 'vSoundEnabled',
651
            checked = 1)
652
        ui.Scrollbar(self.win, layout = (23, 3, 9, 1), id = 'vSoundVolume',
653
            action = "onChangeSoundVolume")
654
        ui.Check(self.win, layout = (23, 4, 9, 1), text = _('Music'), id = 'vMusicEnabled',
655
            checked = 1)
656
        ui.Scrollbar(self.win, layout = (23, 5, 9, 1), id = 'vMusicVolume',
657
            action = "onChangeMusicVolume")
658
659
        # dialog bottom line
660
        ui.Title(self.win, layout = (0, rows - 1, cols - 10, 1))
661
        ui.TitleButton(self.win, layout = (cols - 10, rows - 1, 5, 1), text = _("Cancel"), action = 'onCancel')
662
        ui.TitleButton(self.win, layout = (cols - 5, rows - 1, 5, 1), text = _("OK"), action = 'onOK')
663