root/trunk/src/advanced.py

Revision 10623, 8.9 kB (checked in by asterix, 3 weeks ago)

don't show empty group when searching in ACE. see #4465

  • Property svn:eol-style set to LF
Line 
1# -*- coding:utf-8 -*-
2## src/advanced.py
3##
4## Copyright (C) 2005 Travis Shirk <travis AT pobox.com>
5##                    Vincent Hanquez <tab AT snarc.org>
6## Copyright (C) 2005-2007 Yann Leboulanger <asterix AT lagaule.org>
7##                         Nikos Kouremenos <kourem AT gmail.com>
8## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com>
9## Copyright (C) 2006-2007 Jean-Marie Traissard <jim AT lapin.org>
10##
11## This file is part of Gajim.
12##
13## Gajim is free software; you can redistribute it and/or modify
14## it under the terms of the GNU General Public License as published
15## by the Free Software Foundation; version 3 only.
16##
17## Gajim is distributed in the hope that it will be useful,
18## but WITHOUT ANY WARRANTY; without even the implied warranty of
19## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20## GNU General Public License for more details.
21##
22## You should have received a copy of the GNU General Public License
23## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
24##
25
26import gtk
27import gtkgui_helpers
28import gobject
29
30from common import gajim
31
32(
33OPT_TYPE,
34OPT_VAL
35) = range(2)
36
37(
38C_PREFNAME,
39C_VALUE,
40C_TYPE
41) = range(3)
42
43GTKGUI_GLADE = 'manage_accounts_window.glade'
44
45def rate_limit(rate):
46        ''' call func at most *rate* times per second '''
47        def decorator(func):
48                timeout = [None]
49                def f(*args, **kwargs):
50                        if timeout[0] is not None:
51                                gobject.source_remove(timeout[0])
52                                timeout[0] = None
53                        def timeout_func():
54                                func(*args, **kwargs)
55                                timeout[0] = None
56                        timeout[0] = gobject.timeout_add(int(1000.0 / rate), timeout_func)
57                return f
58        return decorator
59
60def tree_model_iter_children(model, treeiter):
61        it = model.iter_children(treeiter)
62        while it:
63                yield it
64                it = model.iter_next(it)
65
66def tree_model_pre_order(model, treeiter):
67        yield treeiter
68        for childiter in tree_model_iter_children(model, treeiter):
69                for it in tree_model_pre_order(model, childiter):
70                        yield it
71
72try:
73        any(()) # builtin since python 2.5
74except Exception:
75        def any(iterable):
76                for element in iterable:
77                        if element:
78                                return True
79                return False
80
81class AdvancedConfigurationWindow(object):
82        def __init__(self):
83                self.xml = gtkgui_helpers.get_glade('advanced_configuration_window.glade')
84                self.window = self.xml.get_widget('advanced_configuration_window')
85                self.window.set_transient_for(
86                        gajim.interface.instances['preferences'].window)
87                self.entry = self.xml.get_widget('advanced_entry')
88                self.desc_label = self.xml.get_widget('advanced_desc_label')
89                self.restart_label = self.xml.get_widget('restart_label')
90
91                # Format:
92                # key = option name (root/subopt/opt separated by \n then)
93                # value = array(oldval, newval)
94                self.changed_opts = {}
95               
96                # For i18n
97                self.right_true_dict = {True: _('Activated'), False: _('Deactivated')} 
98                self.types = {
99                        'boolean': _('Boolean'),
100                        'integer': _('Integer'),
101                        'string': _('Text'),
102                        'color': _('Color')} 
103
104                treeview = self.xml.get_widget('advanced_treeview')
105                self.treeview = treeview
106                self.model = gtk.TreeStore(str, str, str)
107                self.fill_model()
108                self.model.set_sort_column_id(0, gtk.SORT_ASCENDING)
109                self.modelfilter = self.model.filter_new()
110                self.modelfilter.set_visible_func(self.visible_func)
111
112                renderer_text = gtk.CellRendererText()
113                col = treeview.insert_column_with_attributes(-1, _('Preference Name'),
114                        renderer_text, text = 0)
115                col.set_resizable(True)
116
117                renderer_text = gtk.CellRendererText()
118                renderer_text.connect('edited', self.on_config_edited)
119                col = treeview.insert_column_with_attributes(-1, _('Value'),
120                        renderer_text, text = 1)
121                col.set_cell_data_func(renderer_text, self.cb_value_column_data)
122
123                col.props.resizable = True
124                col.set_max_width(250)
125
126                renderer_text = gtk.CellRendererText()
127                treeview.insert_column_with_attributes(-1, _('Type'),
128                        renderer_text, text = 2)
129
130                treeview.set_model(self.modelfilter)
131
132                # connect signal for selection change
133                treeview.get_selection().connect('changed',
134                        self.on_advanced_treeview_selection_changed)
135
136                self.xml.signal_autoconnect(self)
137                self.window.show_all()
138                self.restart_label.hide()
139                gajim.interface.instances['advanced_config'] = self
140
141        def cb_value_column_data(self, col, cell, model, iter_):
142                '''check if it's boolen or holds password stuff and if yes
143                make the cellrenderertext not editable else it's editable'''
144                optname = model[iter_][C_PREFNAME]
145                opttype = model[iter_][C_TYPE]
146                if opttype == self.types['boolean'] or optname == 'password':
147                        cell.set_property('editable', False)
148                else:
149                        cell.set_property('editable', True)
150
151        def get_option_path(self, model, iter_):
152                # It looks like path made from reversed array
153                # path[0] is the true one optname
154                # path[1] is the key name
155                # path[2] is the root of tree
156                # last two is optional
157                path = [model[iter_][0].decode('utf-8')]
158                parent = model.iter_parent(iter_)
159                while parent:
160                        path.append(model[parent][0].decode('utf-8'))
161                        parent = model.iter_parent(parent)
162                return path
163
164        def on_advanced_treeview_selection_changed(self, treeselection):
165                model, iter = treeselection.get_selected()
166                # Check for GtkTreeIter
167                if iter:
168                        opt_path = self.get_option_path(model, iter)
169                        # Get text from first column in this row
170                        desc = None
171                        if len(opt_path) == 3:
172                                desc = gajim.config.get_desc_per(opt_path[2], opt_path[1],
173                                        opt_path[0])
174                        elif len(opt_path) == 1:
175                                desc = gajim.config.get_desc(opt_path[0])
176                        if desc:
177                                self.desc_label.set_text(desc)
178                        else:
179                                #we talk about option description in advanced configuration editor
180                                self.desc_label.set_text(_('(None)'))
181
182        def remember_option(self, option, oldval, newval):
183                if option in self.changed_opts:
184                        self.changed_opts[option] = (self.changed_opts[option][0], newval)
185                else:
186                        self.changed_opts[option] = (oldval, newval)
187
188        def on_advanced_treeview_row_activated(self, treeview, path, column):
189                modelpath = self.modelfilter.convert_path_to_child_path(path)
190                modelrow = self.model[modelpath]
191                option = modelrow[0].decode('utf-8')
192                if modelrow[2] == self.types['boolean']:
193                        for key in self.right_true_dict.keys():
194                                if self.right_true_dict[key] == modelrow[1]:
195                                        modelrow[1] = key
196                        newval = {'False': True, 'True': False}[modelrow[1]]
197                        if len(modelpath) > 1:
198                                optnamerow = self.model[modelpath[0]]
199                                optname = optnamerow[0].decode('utf-8')
200                                keyrow = self.model[modelpath[:2]]
201                                key = keyrow[0].decode('utf-8')
202                                gajim.config.get_desc_per(optname, key, option)
203                                self.remember_option(option + '\n' + key + '\n' + optname,
204                                        modelrow[1], newval)
205                                gajim.config.set_per(optname, key, option, newval)
206                        else:
207                                self.remember_option(option, modelrow[1], newval)
208                                gajim.config.set(option, newval)
209                        gajim.interface.save_config()
210                        modelrow[1] = self.right_true_dict[newval]
211                        self.check_for_restart()
212
213        def check_for_restart(self):
214                self.restart_label.hide()
215                for opt in self.changed_opts:
216                        opt_path = opt.split('\n')
217                        if len(opt_path)==3:
218                                restart = gajim.config.get_restart_per(opt_path[2], opt_path[1],
219                                        opt_path[0])
220                        else:
221                                restart = gajim.config.get_restart(opt_path[0])
222                        if restart:
223                                if self.changed_opts[opt][0] != self.changed_opts[opt][1]:
224                                        self.restart_label.show()
225                                        break
226
227        def on_config_edited(self, cell, path, text):
228                # convert modelfilter path to model path
229                modelpath = self.modelfilter.convert_path_to_child_path(path)
230                modelrow = self.model[modelpath]
231                option = modelrow[0].decode('utf-8')
232                text = text.decode('utf-8')
233                if len(modelpath) > 1:
234                        optnamerow = self.model[modelpath[0]]
235                        optname = optnamerow[0].decode('utf-8')
236                        keyrow = self.model[modelpath[:2]]
237                        key = keyrow[0].decode('utf-8')
238                        self.remember_option(option + '\n' + key + '\n' + optname, modelrow[1],
239                                text)
240                        gajim.config.set_per(optname, key, option, text)
241                else:
242                        self.remember_option(option, modelrow[1], text)
243                        gajim.config.set(option, text)
244                gajim.interface.save_config()
245                modelrow[1] = text
246                self.check_for_restart()
247
248        def on_advanced_configuration_window_destroy(self, widget):
249                del gajim.interface.instances['advanced_config']
250
251        def on_advanced_close_button_clicked(self, widget):
252                self.window.destroy()
253
254        def fill_model(self, node=None, parent=None):
255                for item, option in gajim.config.get_children(node):
256                        name = item[-1]
257                        if option is None: # Node
258                                newparent = self.model.append(parent, [name, '', ''])
259                                self.fill_model(item, newparent)
260                        else: # Leaf
261                                type_ = self.types[option[OPT_TYPE][0]]
262                                if name == 'password':
263                                        value = _('Hidden')
264                                else:
265                                        value = self.right_true_dict.get(option[OPT_VAL],
266                                                option[OPT_VAL])
267                                self.model.append(parent, [name, value, type_])
268
269        def visible_func(self, model, treeiter):
270                search_string  = self.entry.get_text()
271                return any(search_string in model[it][C_PREFNAME] for it in
272                        tree_model_pre_order(model, treeiter) if model[it][C_TYPE] != '')
273
274        @rate_limit(3)
275        def on_advanced_entry_changed(self, widget):
276                self.modelfilter.refilter()
277                if not widget.get_text():
278                        # Maybe the expanded rows should be remembered here ...
279                        self.treeview.collapse_all()
280                else:
281                        # ... and be restored correctly here
282                        self.treeview.expand_all()     
283
284# vim: se ts=3:
Note: See TracBrowser for help on using the browser.