~ubuntu-branches/ubuntu/raring/sunpinyin/raring

« 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-03-30 15:31:55 UTC
  • mfrom: (1.1.3) (1.2.7 sid)
  • Revision ID: package-import@ubuntu.com-20120330153155-qgls77sogzgtg9zp
Tags: 2.0.3+git20120222-1
* Team upload: git snapshot 20120222.
   - fix breaks if LDFLAGS in environment contains
       multiple words (Closese #646001).
   - rm patches merged to upstream:
       append-os-environ-toenv.patch
       fix-ftbfs-on-sh.patch
       remove-10-candidate-words-limitation.patch
   - refresh disable-lm-dict-compile.patch.
* Bump stardard version to 3.9.3: no modify needed.
* add libsunpinyin3-dbg and python-sunpinyin packages.
* debian/compat to 9, multiarch it.
* rewrite debian/rules with dh 7 format.

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()