~ubuntu-branches/ubuntu/quantal/sunpinyin/quantal

« back to all changes in this revision

Viewing changes to wrapper/ibus/setup/main.py

  • Committer: Package Import Robot
  • Author(s): YunQiang Su
  • Date: 2012-04-11 03:06:40 UTC
  • mfrom: (1.1.4) (1.2.8 sid)
  • Revision ID: package-import@ubuntu.com-20120411030640-8mxepz5e6wffy87c
Tags: 2.0.3+git20120404-1
* Medium urgency for fixing RC bug.
* New upstream commit: fix FTBFS with gcc-4.7 (Closes: #667385).
* Add Multi-Arch: same to libsunpinyin3, -dev and -dbg.
* Add YunQiang Su to uploaders.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: utf-8 -*-
2
 
3
 
# Copyright (c) 2009 Leo Zheng <zym361@gmail.com>, Kov Chai <tchaikov@gmail.com>
4
 
# *
5
 
# The contents of this file are subject to the terms of either the GNU Lesser
6
 
# General Public License Version 2.1 only ("LGPL") or the Common Development and
7
 
# Distribution License ("CDDL")(collectively, the "License"). You may not use this
8
 
# file except in compliance with the License. You can obtain a copy of the CDDL at
9
 
# http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
10
 
# http://www.opensource.org/licenses/lgpl-license.php. See the License for the 
11
 
# specific language governing permissions and limitations under the License. When
12
 
# distributing the software, include this License Header Notice in each file and
13
 
# include the full text of the License in the License file as well as the
14
 
# following notice:
15
 
16
 
# NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
17
 
# (CDDL)
18
 
# For Covered Software in this distribution, this License shall be governed by the
19
 
# laws of the State of California (excluding conflict-of-law provisions).
20
 
# Any litigation relating to this License shall be subject to the jurisdiction of
21
 
# the Federal Courts of the Northern District of California and the state courts
22
 
# of the State of California, with venue lying in Santa Clara County, California.
23
 
24
 
# Contributor(s):
25
 
26
 
# If you wish your version of this file to be governed by only the CDDL or only
27
 
# the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
28
 
# include this software in this distribution under the [CDDL or LGPL Version 2.1]
29
 
# license." If you don't indicate a single choice of license, a recipient has the
30
 
# option to distribute your version of this file under either the CDDL or the LGPL
31
 
# Version 2.1, or to extend the choice of license to its licensees as provided
32
 
# above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
33
 
# Version 2 license, then the option applies only if the new code is made subject
34
 
# to such option by the copyright holder. 
35
 
#
36
 
 
37
 
import sys
38
 
import os
39
 
from os import path
40
 
import gtk
41
 
import ibus
42
 
import gettext
43
 
import locale
44
 
 
45
 
GETTEXT_PACKAGE="ibus-sunpinyin"
46
 
_ = lambda msg: gettext.gettext(msg)
47
 
 
48
 
XML_FILE = path.join(path.dirname(__file__), "setup.xml")
49
 
SEPARATOR = "/"
50
 
 
51
 
class Logger:
52
 
    @staticmethod
53
 
    def pr(message):
54
 
        print >> sys.stderr, message
55
 
        
56
 
class Option(object):
57
 
    """Option serves as an interface of ibus.config
58
 
 
59
 
    it is used to synchronize the configuration with setting on user interface
60
 
    """
61
 
    config = ibus.Bus().get_config()
62
 
    
63
 
    def __init__(self, name, default):
64
 
        self.name = name
65
 
        self.default = default
66
 
    
67
 
    def read(self):
68
 
        section, key = self.__get_config_name()
69
 
        return self.config.get_value(section, key, self.default)
70
 
 
71
 
    def write(self, v):
72
 
        section, key = self.__get_config_name()
73
 
        return self.config.set_value(section, key, type(self.default)(v))
74
 
 
75
 
   
76
 
    def __get_config_name(self):
77
 
        keys = self.name.rsplit(SEPARATOR ,1)
78
 
        if len(keys) == 2:
79
 
            return SEPARATOR.join(("engine/SunPinyin", keys[0])), keys[1]
80
 
        else:
81
 
            assert len(keys) == 1
82
 
            return "engine/SunPinyin", keys[0]
83
 
 
84
 
class TrivalOption(Option):
85
 
    """option represented using a simple gtk widget
86
 
    """
87
 
    def __init__(self, name, default, owner):
88
 
        super(TrivalOption, self).__init__(name, default)
89
 
        self.xml = owner
90
 
        self.widget = owner.get_object(name)
91
 
        assert self.widget is not None, "%s not found in gtkbuilder" % name
92
 
 
93
 
    def init_ui(self):
94
 
        self.init()
95
 
        self.read_config()
96
 
 
97
 
    def init(self):
98
 
        pass
99
 
    
100
 
    def read_config(self):
101
 
        """update user inferface with ibus.config
102
 
        """
103
 
        self.v = self.read()
104
 
        self.__set_value(self.v)
105
 
 
106
 
    def write_config(self):
107
 
        v = self.save_ui_setting()
108
 
        self.write(v)
109
 
        
110
 
    def save_ui_setting(self):
111
 
        """save user interface settings into self.v
112
 
        """
113
 
        self.v = self.__get_value()
114
 
        return self.v
115
 
    
116
 
    def is_changed(self):
117
 
        return self.v != self.__get_value()
118
 
 
119
 
    def __get_value(self):
120
 
        try:
121
 
            return self.widget.get_value()
122
 
        except:
123
 
            return self.widget.get_active()
124
 
 
125
 
    def __set_value(self, v):
126
 
        try:
127
 
            self.widget.set_value(v)
128
 
        except:
129
 
            self.widget.set_active(v)
130
 
            
131
 
class CheckBoxOption(TrivalOption):
132
 
    def __init__(self, name, default, owner):
133
 
        super(CheckBoxOption, self).__init__(name, default, owner)
134
 
 
135
 
class ComboBoxOption(TrivalOption):
136
 
    def __init__(self, name, default, options, owner):
137
 
        try:
138
 
            default = int(default)
139
 
        except ValueError:
140
 
            default = options.index(default)
141
 
        super(ComboBoxOption, self).__init__(name, default, owner)
142
 
        self.options = options
143
 
        
144
 
    def init(self):
145
 
        model = gtk.ListStore(str)
146
 
        for v in self.options:
147
 
            model.append([str(v)])
148
 
        self.widget.set_model(model)
149
 
 
150
 
    def __get_value(self):
151
 
        active = self.widget.get_active()
152
 
        try:
153
 
            # if the options are numbers, save the liternal of active option as
154
 
            # a number
155
 
            return int(self.options[active])
156
 
        except ValueError:
157
 
            # otherwise save its index
158
 
            return active
159
 
    
160
 
    def __set_value(self, v):
161
 
        try:
162
 
            # if the options are just numbers, we treat 'self.v' as the literal
163
 
            # of option
164
 
            dummy = int(self.options[0])
165
 
            active = self.options.index(v)
166
 
        except ValueError:
167
 
            active = v
168
 
        self.widget.set_active(active)
169
 
        
170
 
class RadioOption(Option):
171
 
    """option represented using multiple Raidio buttons
172
 
    """
173
 
    def __init__(self, name, default, options, owner):
174
 
        super(RadioOption, self).__init__(name, default)
175
 
        self.options = options
176
 
        self.xml = owner
177
 
 
178
 
    def init_ui(self):
179
 
        self.read_config()
180
 
        
181
 
    def read_config(self):
182
 
        self.v = self.read()
183
 
        name = SEPARATOR.join([self.name, self.v])
184
 
        button = self.xml.get_object(name)
185
 
        assert button is not None, "button: %r not found" % name
186
 
        button.set_active(True)
187
 
 
188
 
    def write_config(self):
189
 
        active_opt = None
190
 
        for opt in self.options:
191
 
            radio_name = SEPARATOR.join([self.name, opt])
192
 
            radio = self.xml.get_object(radio_name)
193
 
            if radio.get_active():
194
 
                active_opt = opt
195
 
                break
196
 
        assert active_opt is not None
197
 
        self.write(active_opt)
198
 
 
199
 
class MappingInfo:
200
 
    def __init__(self, name, mapping):
201
 
        self.name = name
202
 
        self.mapping = mapping
203
 
        
204
 
class MappingOption(object):
205
 
    """an option which presents some sort of mapping, e.g. fuzzy pinyin mapping
206
 
 
207
 
    it is not directly related to a config option like TrivalOption does, but
208
 
    we always have a checkbox in UI for each of it so user can change it easily.
209
 
    """
210
 
    def __init__(self, name, mappings, owner):
211
 
        self.name = name
212
 
        self.widget = owner.get_object(name)
213
 
        self.mappings = mappings
214
 
        
215
 
    def get_mappings(self):
216
 
        if self.widget.get_active():
217
 
            return [':'.join(self.mappings)]
218
 
        else:
219
 
            return []
220
 
 
221
 
    def set_active(self, enabled):
222
 
        self.widget.set_active(enabled)
223
 
 
224
 
    def get_active(self):
225
 
        return self.widget.get_active()
226
 
    
227
 
    is_enabled = property(get_active, set_active)
228
 
 
229
 
    def key(self):
230
 
        return self.mappings[0]
231
 
    
232
 
class MultiMappingOption(Option):
233
 
    def __init__(self, name, options, default=[]):
234
 
        Option.__init__(self, name, default)
235
 
        self.options = options
236
 
        self.saved_pairs = default
237
 
        
238
 
    def read_config(self):
239
 
        if not self.saved_pairs:
240
 
            self.saved_pairs = self.read()
241
 
        keys = set([pair.split(':')[0] for pair in self.saved_pairs])
242
 
        for opt in self.options:
243
 
            opt.is_enabled = (opt.key() in keys)
244
 
            # throw away unknown pair
245
 
    
246
 
    def write_config(self):
247
 
        # ignore empty settings
248
 
        if self.saved_pairs:
249
 
            self.write(self.saved_pairs)
250
 
        
251
 
    def save_ui_setting(self):
252
 
        self.saved_pairs = sum([opt.get_mappings() for opt in self.options
253
 
                                if opt.is_enabled], [])
254
 
        return self.saved_pairs
255
 
    
256
 
    def set_active_all(self, enabled):
257
 
        for opt in self.options:
258
 
            opt.is_enabled = enabled
259
 
            
260
 
class MultiCheckDialog (object):
261
 
    """ a modal dialog box with 'choose all' and 'choose none' button
262
 
    
263
 
    TODO: another option is to use radio button
264
 
    """
265
 
    def __init__ (self, ui_name, config_name, mappings, option_klass=MappingOption):
266
 
        self.ui_name = ui_name
267
 
        self.config_name = config_name
268
 
        self.mappings = mappings
269
 
        self.option_klass = option_klass
270
 
        self.saved_settings = []
271
 
        self.mapping_options = None
272
 
        
273
 
    def get_setup_name(self):
274
 
        """assuming the name of dialog looks like 'dlg_fuzzy_setup'
275
 
        """
276
 
        return '_'.join(['dlg', self.ui_name, 'setup'])
277
 
    
278
 
    def __init_ui(self):
279
 
        dlg_name = self.get_setup_name()
280
 
        self.__xml = gtk.Builder()
281
 
        self.__xml.add_objects_from_file(XML_FILE, dlg_name)
282
 
        self.__dlg = self.__xml.get_object(dlg_name)
283
 
        assert self.__dlg is not None, "dialog %s not found in %s" % (dlg_name, XML_FILE)
284
 
        handlers = {'_'.join(["on", self.ui_name, "select_all_clicked"]) : self.on_button_check_all_clicked,
285
 
                    '_'.join(["on", self.ui_name, "unselect_all_clicked"]) : self.on_button_uncheck_all_clicked,
286
 
                    '_'.join(["on", self.ui_name, "ok_clicked"]) : self.on_button_ok_clicked,
287
 
                    '_'.join(["on", self.ui_name, "cancel_clicked"]) : self.on_button_cancel_clicked}
288
 
        self.__xml.connect_signals(handlers)
289
 
 
290
 
        options = [self.option_klass(m.name, m.mapping, self.__xml) 
291
 
                   for m in self.mappings]
292
 
        self.mapping_options = MultiMappingOption(self.config_name, options, self.saved_settings)
293
 
 
294
 
    def dummy(self):
295
 
        """a dummy func, i don't initialize myself upon other's request.
296
 
        instead, i will do it by myself.
297
 
        """
298
 
        pass
299
 
 
300
 
    init_ui = read_config = dummy
301
 
    
302
 
    def run(self):
303
 
        self.__init_ui()
304
 
        self.__read_config()
305
 
        self.__dlg.run()
306
 
        
307
 
    def __read_config(self):
308
 
        self.mapping_options.read_config()
309
 
        
310
 
    def __save_ui_settings(self):
311
 
        """save to in-memory storage, will flush to config if not canceled in main_window
312
 
        """
313
 
        self.saved_settings = self.mapping_options.save_ui_setting()
314
 
 
315
 
    def write_config(self):
316
 
        if self.mapping_options is not None:
317
 
            self.mapping_options.write_config()
318
 
            
319
 
    def on_button_check_all_clicked(self, button):
320
 
        self.mapping_options.set_active_all(True)
321
 
        
322
 
    def on_button_uncheck_all_clicked(self, button):
323
 
        self.mapping_options.set_active_all(False)
324
 
    
325
 
    def on_button_ok_clicked(self, button):
326
 
        """update given options with settings in UI, these settings will be
327
 
        written to config if user push 'OK' or 'Apply' in the main window
328
 
        """
329
 
        self.__save_ui_settings()
330
 
        self.__dlg.destroy()
331
 
        
332
 
    def on_button_cancel_clicked(self, button):
333
 
        self.__dlg.destroy()
334
 
 
335
 
class FuzzySetupDialog (MultiCheckDialog):
336
 
    def __init__(self):
337
 
        mappings = [MappingInfo('QuanPin/Fuzzy/ShiSi', ('sh','s')),
338
 
                    MappingInfo('QuanPin/Fuzzy/ZhiZi', ('zh','z')),
339
 
                    MappingInfo('QuanPin/Fuzzy/ChiCi', ('ch','c')),
340
 
                    MappingInfo('QuanPin/Fuzzy/ShiSi', ('sh','s')),
341
 
                    MappingInfo('QuanPin/Fuzzy/AnAng', ('an','ang')),
342
 
                    MappingInfo('QuanPin/Fuzzy/OnOng', ('on','ong')),
343
 
                    MappingInfo('QuanPin/Fuzzy/EnEng', ('en','eng')),
344
 
                    MappingInfo('QuanPin/Fuzzy/InIng', ('in','ing')),
345
 
                    MappingInfo('QuanPin/Fuzzy/EngOng', ('eng','ong')),
346
 
                    MappingInfo('QuanPin/Fuzzy/IanIang', ('ian','iang')),
347
 
                    MappingInfo('QuanPin/Fuzzy/UanUang', ('uan','uang')),
348
 
                    MappingInfo('QuanPin/Fuzzy/NeLe', ('n','l')),
349
 
                    MappingInfo('QuanPin/Fuzzy/FoHe', ('f','h')),
350
 
                    MappingInfo('QuanPin/Fuzzy/LeRi', ('l','r')),
351
 
                    MappingInfo('QuanPin/Fuzzy/KeGe', ('k','g'))]
352
 
        MultiCheckDialog.__init__(self,
353
 
                                  ui_name = 'fuzzy',
354
 
                                  config_name = 'QuanPin/Fuzzy/Pinyins',
355
 
                                  mappings = mappings)
356
 
        
357
 
class CorrectionSetupDialog (MultiCheckDialog):
358
 
    def __init__(self):
359
 
        mappings = [MappingInfo('QuanPin/AutoCorrection/GnNg', ('gn','ng')),
360
 
                    MappingInfo('QuanPin/AutoCorrection/UenUn', ('uen','un')),
361
 
                    MappingInfo('QuanPin/AutoCorrection/ImgIng', ('img','ing')),
362
 
                    MappingInfo('QuanPin/AutoCorrection/IouIu', ('iou','iu')),
363
 
                    MappingInfo('QuanPin/AutoCorrection/UeiUi', ('uei','ui'))]
364
 
        MultiCheckDialog.__init__(self,
365
 
                                  ui_name = 'correction',
366
 
                                  config_name = 'QuanPin/AutoCorrection/Pinyins',
367
 
                                  mappings = mappings)
368
 
 
369
 
class PunctMapping(MappingOption):
370
 
    def __init__(self, name, mappings, owner):
371
 
        MappingOption.__init__(self, name, mappings, owner)
372
 
        if mappings:
373
 
            self.widget.set_sensitive(True)
374
 
            self.init_keys_values(mappings)
375
 
        else:
376
 
            self.widget.set_sensitive(False)
377
 
            
378
 
    def init_keys_values(self, mappings):
379
 
        self.keys = [m[0] for m in mappings]
380
 
        values_with_closing = [v or k for k, v in mappings]
381
 
        self.values = []
382
 
        for v in values_with_closing:
383
 
            try:
384
 
                self.values.append(v[0])
385
 
            except:
386
 
                self.values.append(v)
387
 
        self.keys.reverse()
388
 
        self.values.reverse()
389
 
 
390
 
    def get_mappings(self):
391
 
        if self.widget.get_active():
392
 
            pairs = []
393
 
            for k,vs in self.mappings:
394
 
                try:
395
 
                    for v in vs:
396
 
                        pairs.append(':'.join([k,v]))
397
 
                except:
398
 
                    v = vs
399
 
                    if v is None:
400
 
                        continue
401
 
                    pairs.append(':'.join([k,v]))
402
 
            return pairs
403
 
        else:
404
 
            return []
405
 
 
406
 
    def set_active(self, enabled):
407
 
        if not self.mappings: return
408
 
        if enabled:
409
 
            self.widget.set_label('\n'.join(self.values))
410
 
        else:
411
 
            self.widget.set_label('\n'.join(self.keys))
412
 
        self.widget.set_active(enabled)
413
 
 
414
 
    is_enabled = property(MappingOption.get_active, set_active)
415
 
    
416
 
    def key(self):
417
 
        for k, v in self.mappings:
418
 
            if v is not None:
419
 
                return k
420
 
        else:
421
 
            return None
422
 
 
423
 
class PunctMappingSetupDialog (MultiCheckDialog):
424
 
    # TODO: the UI should looks like a virtual keyboard,
425
 
    #       user are allowed to choose the mappings to all punctuation keys.
426
 
    def __init__(self):
427
 
        mappings = [MappingInfo('togglebutton1', [('`',None), ('~',u'~')]),
428
 
                    MappingInfo('togglebutton2', []),
429
 
                    MappingInfo('togglebutton3', [('2',None), ('@',u'@')]),
430
 
                    MappingInfo('togglebutton4', [('3',None), ('#',u'#')]),
431
 
                    MappingInfo('togglebutton5', [('4',None), ('$',u'¥' )]),
432
 
                    MappingInfo('togglebutton6', [('5',None), ('%',u'%')]),
433
 
                    MappingInfo('togglebutton7', [('6',None), ('^',u'…')]),
434
 
                    MappingInfo('togglebutton8', [('7',None), ('&',u'&')]),
435
 
                    MappingInfo('togglebutton9', [('8',None), ('*',u'*')]),
436
 
                    MappingInfo('togglebutton10', [('9',None), ('*',u'(')]),
437
 
                    MappingInfo('togglebutton11', [('0',None), ('*',u')')]),
438
 
                    MappingInfo('togglebutton12', [('-',u'-'), ('_',u'——')]),
439
 
                    MappingInfo('togglebutton13', [('=',u'='), ('+',u'+')]),
440
 
                    MappingInfo('togglebutton14', [('\\',None), ('|',u'‖')]),
441
 
                    MappingInfo('togglebutton27', [('[',u'〔'), ('{',u'{')]),
442
 
                    MappingInfo('togglebutton28', [(']',u'〕'), ('}',u'}')]),
443
 
                    MappingInfo('togglebutton39', []),
444
 
                    MappingInfo('togglebutton40', []),
445
 
                    MappingInfo('togglebutton50', [(',',None), ('<',u'〈')]),
446
 
                    MappingInfo('togglebutton51', [('.',u'·'), ('>',u'〉')]),
447
 
                    MappingInfo('togglebutton52', [('/',u'/'), ('?',None)])]
448
 
                    #'\'',(u'‘',u'’'),
449
 
        MultiCheckDialog.__init__(self, ui_name="punctmapping",
450
 
                                  config_name="General/PunctMapping/Mappings",
451
 
                                  mappings=mappings,
452
 
                                  option_klass=PunctMapping)
453
 
 
454
 
class MainWindow():
455
 
    SPECIAL_OBJECTS = [
456
 
        'pymodel', 'memory_adjustment', 'candidate_adjustment',
457
 
        'max_best_adjustment', 'max_tail_candidate_adjustment',
458
 
        ]
459
 
 
460
 
    def __init__ (self):
461
 
        self.__bus = ibus.Bus()
462
 
        self.__config = self.__bus.get_config()
463
 
        
464
 
        
465
 
    def run(self):
466
 
        self.__init_ui("main_window")
467
 
        self.__read_config()
468
 
        gtk.main()
469
 
        
470
 
    def __init_ui(self, name):
471
 
        self.__init_gettext()
472
 
        xml_file = path.join(path.dirname(__file__), XML_FILE)
473
 
        self.__xml = gtk.Builder()
474
 
        self.__xml.add_objects_from_file(xml_file, self.SPECIAL_OBJECTS)
475
 
        self.__xml.add_objects_from_file(xml_file, [name])
476
 
        self.__xml.connect_signals(self)
477
 
        self.__init_options()
478
 
        self.window = self.__xml.get_object(name)
479
 
        self.window.show_all()
480
 
 
481
 
    def __init_gettext(self):
482
 
        locale.setlocale(locale.LC_ALL, "")
483
 
        localedir = os.getenv("IBUS_LOCALEDIR")
484
 
        gettext.bindtextdomain(GETTEXT_PACKAGE, localedir)
485
 
        gettext.bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8")
486
 
 
487
 
    def __init_options(self):
488
 
        self.__fuzzy_setup = FuzzySetupDialog()
489
 
        self.__correction_setup = CorrectionSetupDialog()
490
 
        self.__punctmapping_setup = PunctMappingSetupDialog()
491
 
        
492
 
        self.__options = [
493
 
            TrivalOption("General/MemoryPower", 3, self.__xml),
494
 
            TrivalOption("General/PageSize", 10, self.__xml),
495
 
            TrivalOption("General/MaxBest", 1, self.__xml),
496
 
            TrivalOption("General/MaxTailCandidate", 0, self.__xml),
497
 
            
498
 
            RadioOption("General/InitialStatus/Mode", 'Chinese', ['Chinese', 'English'], self.__xml),
499
 
            RadioOption("General/InitialStatus/Punct", 'Full', ['Full', 'Half'], self.__xml),
500
 
            RadioOption("General/InitialStatus/Letter", 'Half', ['Full', 'Half'], self.__xml),
501
 
            RadioOption("General/Charset", 'GBK', ['GB2312', 'GBK', 'GB18030'], self.__xml),
502
 
            CheckBoxOption("General/PunctMapping/Enabled", False, self.__xml),
503
 
                                
504
 
            RadioOption("Keyboard/ModeSwitch", 'Shift', ['Shift', 'Control'], self.__xml),
505
 
            RadioOption("Keyboard/PunctSwitch", 'None', ['ControlComma',
506
 
                                                         'ControlPeriod',
507
 
                                                         'None'], self.__xml),
508
 
            CheckBoxOption("Keyboard/Page/MinusEquals", False, self.__xml),
509
 
            CheckBoxOption("Keyboard/Page/Brackets", False, self.__xml),
510
 
            CheckBoxOption("Keyboard/Page/CommaPeriod", False, self.__xml),
511
 
            CheckBoxOption("Keyboard/CancelBackspace", True, self.__xml),
512
 
            CheckBoxOption("Keyboard/SmartPunct", True, self.__xml),
513
 
            
514
 
            RadioOption("Pinyin/Scheme", 'QuanPin', ['QuanPin', 'ShuangPin'], self.__xml),
515
 
            ComboBoxOption("Pinyin/ShuangPinType", 'MS2003', ['MS2003',
516
 
                                                              'ABC',
517
 
                                                              'ZiRanMa',
518
 
                                                              'Pinyin++',
519
 
                                                              'ZiGuang',
520
 
                                                              'XiaoHe'], self.__xml),
521
 
            CheckBoxOption("QuanPin/Fuzzy/Enabled", False, self.__xml),
522
 
            CheckBoxOption("QuanPin/AutoCorrection/Enabled", False, self.__xml),
523
 
            CheckBoxOption("QuanPin/FuzzySegs/Enabled", False, self.__xml),
524
 
            CheckBoxOption("QuanPin/InnerFuzzy/Enabled", False, self.__xml),
525
 
            
526
 
            self.__fuzzy_setup,
527
 
            self.__correction_setup,
528
 
            self.__punctmapping_setup,
529
 
        ]
530
 
 
531
 
    def __get_option(self, name):
532
 
        for opt in self.__options:
533
 
            if opt.name == name:
534
 
                return opt
535
 
        else:
536
 
            return None
537
 
        
538
 
    def __read_config(self):
539
 
        for opt in self.__options:
540
 
            opt.init_ui()
541
 
            opt.read_config()
542
 
        self.on_chk_fuzzy_enabled_toggled(None)
543
 
        self.on_chk_correction_enabled_toggled(None)
544
 
        self.on_chk_punctmapping_enabled_toggled(None)
545
 
        self.on_radio_shuangpin_toggled(None)
546
 
        
547
 
    def __write_config(self):
548
 
        for opt in self.__options:
549
 
            opt.write_config()
550
 
 
551
 
    def __update_enabling_button(self, checkbox_name, button_name):
552
 
        """enable a setup button when checked, disable it otherwise
553
 
        """
554
 
        checkbox = self.__xml.get_object(checkbox_name)
555
 
        assert checkbox is not None, "checkbox: %s not found" % checkbox_name
556
 
        button = self.__xml.get_object(button_name)
557
 
        assert button is not None, "button: %s not found" % button_name
558
 
        button_enabled = checkbox.get_active()
559
 
        button.set_sensitive(button_enabled)
560
 
 
561
 
    def on_radio_shuangpin_toggled(self, button):
562
 
        radio = self.__xml.get_object("Pinyin/Scheme/ShuangPin")
563
 
        enabled = radio.get_active()
564
 
        combo = self.__xml.get_object("Pinyin/ShuangPinType")
565
 
        combo.set_sensitive(enabled)
566
 
        
567
 
    def on_chk_fuzzy_enabled_toggled(self, button):
568
 
        self.__update_enabling_button("QuanPin/Fuzzy/Enabled",
569
 
                                      "button_fuzzy_setup")
570
 
        
571
 
    def on_button_fuzzy_setup_clicked(self, button):
572
 
        self.__fuzzy_setup.run()
573
 
        
574
 
    def on_chk_correction_enabled_toggled(self, button):
575
 
        self.__update_enabling_button("QuanPin/AutoCorrection/Enabled",
576
 
                                      "button_correction_setup")
577
 
 
578
 
    def on_chk_smartseg_enabled_toggled(self, button):
579
 
        self.__update_enabling_button("QuanPin/FuzzySegs/Enabled",
580
 
                                      "QuanPin/InnerFuzzy/Enabled")
581
 
 
582
 
    def on_button_correction_setup_clicked(self, button):
583
 
        self.__correction_setup.run()
584
 
        
585
 
    def on_chk_punctmapping_enabled_toggled(self, button):
586
 
        self.__update_enabling_button("General/PunctMapping/Enabled",
587
 
                                      "button_punctmapping_setup")
588
 
    
589
 
    def on_button_punctmapping_setup_clicked(self, button):
590
 
        self.__punctmapping_setup.run()
591
 
    
592
 
    def on_main_ok_clicked(self, button):
593
 
        self.__write_config()
594
 
        self.__quit()
595
 
        
596
 
    def on_main_apply_clicked(self, button):
597
 
        self.__write_config()
598
 
 
599
 
    def on_main_cancel_clicked(self, button):
600
 
        self.__quit()
601
 
 
602
 
    def __quit(self):
603
 
        gtk.main_quit()
604
 
    
605
 
if __name__ == "__main__":
606
 
    MainWindow().run()