root/branch/NetworkInventory/umit/gui/OptionBuilder.py @ 4300

Revision 4300, 14.4 kB (checked in by gpolo, 4 years ago)

Merged revisions 4291-4299 via svnmerge from
http://svn.umitproject.org/svnroot/umit/trunk

........

r4291 | gpolo | 2009-03-05 22:10:12 -0300 (Thu, 05 Mar 2009) | 1 line


Added classifier for python 2.4

........

r4292 | gpolo | 2009-03-05 22:12:32 -0300 (Thu, 05 Mar 2009) | 1 line


Added missing commas.

........

r4293 | gpolo | 2009-03-06 13:03:40 -0300 (Fri, 06 Mar 2009) | 1 line


typo fix.

........

r4294 | gpolo | 2009-03-06 13:07:45 -0300 (Fri, 06 Mar 2009) | 3 lines


Avoiding a "GtkWarning?: gtk_label_set_label: assertion `str != NULL'
failed" when not giving a value to text.

........

r4295 | gpolo | 2009-03-06 13:10:00 -0300 (Fri, 06 Mar 2009) | 1 line


Adjusted example to work with the current paths.

........

r4296 | gpolo | 2009-03-06 13:11:51 -0300 (Fri, 06 Mar 2009) | 1 line


Removed bad sys.exit (which didn't even work since sys was never imported here).

........

r4297 | gpolo | 2009-03-06 13:17:37 -0300 (Fri, 06 Mar 2009) | 1 line


Fixed bad widget packing.

........

r4298 | gpolo | 2009-03-06 13:38:11 -0300 (Fri, 06 Mar 2009) | 1 line


Misc tweaks, also removed the broken example.

........

r4299 | gpolo | 2009-03-06 13:50:40 -0300 (Fri, 06 Mar 2009) | 1 line


read_file is gone for more than one year, removed its use here. This code doesn't replace the previous read_file func.

........

Line 
1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2005-2006 Insecure.Com LLC.
4# Copyright (C) 2007-2008 Adriano Monteiro Marques
5#
6# Author: Adriano Monteiro Marques <adriano@umitproject.org>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
22import os
23import sys
24import gtk
25from xml.dom import minidom
26
27from higwidgets.higboxes import HIGHBox
28from higwidgets.higlabels import HIGEntryLabel
29from higwidgets.higbuttons import HIGButton
30
31from umit.gui.ScriptManager import ScriptChooserDialog
32from umit.gui.FileChoosers import AllFilesFileChooserDialog
33
34from umit.core.NmapOptions import NmapOptions
35from umit.core.I18N import _
36from umit.core.Utils import amiroot
37from umit.core.OptionsConf import options_file
38
39
40class OptionTab(object):
41    def __init__(self, root_tab, options, constructor, update_func):
42        actions = {
43                'option_list':self.__parse_option_list,
44                'option_check':self.__parse_option_check}
45
46        self.options = options
47        self.constructor = constructor
48        self.update_func = update_func
49        self.widgets_list = []
50
51        options_used = self.constructor.get_options()
52
53        # Cannot use list comprehhension because text nodes raise exception
54        # when tagName is called
55        for option_element in root_tab.childNodes:
56            try:option_element.tagName
57            except:pass
58            else:
59                if option_element.tagName in actions.keys():
60                    self.widgets_list.append(
61                            actions[option_element.tagName](option_element,
62                                options_used))
63
64    def __parse_option_list(self, option_list, options_used):
65        options = option_list.getElementsByTagName(u'option')
66
67        label = HIGEntryLabel(option_list.getAttribute(u'label'))
68        opt_list = OptionList()
69
70        for opt in options:
71            opt_list.append(self.options.get_option(opt.getAttribute(u'name')))
72
73        for i, row in enumerate(opt_list.list):
74            if row[0] in options_used:
75                opt_list.set_active(i)
76
77        return label, opt_list
78
79    def _disable_option(self, need_root):
80        """
81        enable / disable option if non-root user.
82        """
83        return not amiroot() and need_root
84
85
86    def __with_icon(self, hint):
87        """
88        Return true or false: if is a option with icon or without.
89        """
90        return hint!=""
91
92    def __parse_option_check(self, option_check, options_used):
93        option = option_check.getAttribute(u'option')
94        arg_type = self.options.get_arg_type(option)
95        label = option_check.getAttribute(u'label')
96        opt_parse = self.options.get_option(option)
97        opt_hint = self.options.get_hint(option)
98        need_root = self.options.get_need_root(option)
99        with_icon = self.__with_icon(opt_hint)
100        if with_icon:
101            check = OptionCheckIcon(label, opt_parse, opt_hint )
102
103        else:
104            check = OptionCheck(label, opt_parse)
105        check.set_active(option in options_used)
106        if self._disable_option(need_root):
107            check.disable_widget()
108        type_mapping = {
109                "str": OptionEntry,
110                "int": OptionIntSpin,
111                "float": OptionFloatSpin,
112                "level": OptionLevelSpin,
113                "path": OptionFile,
114                "interface": OptionInterface,
115                "scriptlist": OptionScriptList}
116
117        additional = None
118        if type_mapping.has_key(arg_type):
119            value = options_used.get(option, None)
120            if value:
121                additional = type_mapping[arg_type](value)
122            else:
123                additional = type_mapping[arg_type]()
124        check.connect('toggled', self.update_check, additional)
125
126        return check, additional
127
128    def fill_table(self, table, expand_fill = True):
129        yopt = (0, gtk.EXPAND | gtk.FILL)[expand_fill]
130        for y, widget in enumerate(self.widgets_list):
131            if widget[1] == None:
132                table.attach(widget[0], 0, 2, y, y+1, yoptions=yopt)
133            else:
134                table.attach(widget[0], 0, 1, y, y+1, yoptions=yopt)
135                table.attach(widget[1], 1, 2, y, y+1, yoptions=yopt)
136
137        for widget in self.widgets_list:
138            te = type(widget[1])
139            if te == type(OptionList()):
140                widget[1].connect('changed',self.update_list_option)
141            elif te == type(OptionIntSpin()) or\
142                 te == type(OptionFloatSpin()) or\
143                 te == type(OptionEntry()):
144                widget[1].connect('changed', self.update_entry, widget[0])
145            elif te == type(OptionLevelSpin()):
146                widget[1].connect('changed', self.update_level, widget[0])
147            elif te == type(OptionFile()):
148                widget[1].entry.connect('changed', self.update_entry, widget[0])
149            elif te == type(OptionInterface()):
150                widget[1].child.connect('changed', self.update_entry, widget[0])
151
152    def update_check(self, check, extra):
153        if check.get_active():
154            te = type(extra)
155            if te == type(OptionEntry()) or\
156               te == type(OptionIntSpin()) or\
157               te == type(OptionFloatSpin()):
158                self.update_entry(extra, check)
159            elif te == type(OptionLevelSpin()):
160                self.update_level(extra, check)
161            elif te == type(OptionFile()):
162                self.update_entry(extra.entry, check)
163            elif te == type(OptionInterface()):
164                self.update_entry(extra.child, check)
165            else:
166                self.constructor.add_option(check.option['name'])
167        else:
168            self.constructor.remove_option(check.option['name'])
169
170        self.update_command()
171
172    def update_entry(self, widget, check):
173        if not check.get_active():
174            check.set_active(True)
175
176        self.constructor.remove_option(check.option['name'])
177        self.constructor.add_option(check.option['name'], widget.get_text())
178
179        self.update_command()
180
181    def update_level(self, widget, check):
182        if not check.get_active():
183            check.set_active(True)
184
185        try:
186            self.constructor.remove_option(check.option['name'])
187            if int(widget.get_text()) == 0:
188                check.set_active(False)
189            else:
190                self.constructor.add_option(
191                        check.option['name'],
192                        level=int(widget.get_text()))
193        except:pass
194
195        self.update_command()
196
197    def update_list_option(self, widget):
198        try:widget.last_selected
199        except:pass
200        else:
201            self.constructor.remove_option(widget.last_selected)
202
203        option_name = widget.options[widget.get_active()]['name']
204
205        self.constructor.add_option(option_name)
206        widget.last_selected = option_name
207
208        self.update_command()
209
210    def update_command(self):
211        if self.update_func:
212            self.update_func()
213
214
215class OptionBuilder(object):
216    def __init__(self, xml_file, constructor, update_func):
217        """ OptionBuilder(xml_file, constructor)
218
219        xml_file is a UI description xml-file
220        constructor is a CommandConstructor instance
221        """
222        xml_desc = open(xml_file)
223        self.xml = minidom.parse(xml_desc)
224        # Closing file to avoid problems with file descriptors
225        xml_desc.close()
226
227        self.constructor = constructor
228        self.update_func = update_func
229
230        self.root_tag = "interface"
231
232        self.xml = self.xml.getElementsByTagName(self.root_tag)[0]
233        self.options = NmapOptions(options_file)
234
235        self.groups = self.__parse_groups()
236        self.section_names = self.__parse_section_names()
237        self.tabs = self.__parse_tabs()
238
239
240    def __parse_section_names(self):
241        dic = {}
242        for group in self.groups:
243            grp = self.xml.getElementsByTagName(group)[0]
244            dic[group] = grp.getAttribute(u'label')
245        return dic
246
247    def __parse_groups(self):
248        return [g_name.getAttribute(u'name') for g_name in \
249                  self.xml.getElementsByTagName(u'groups')[0].\
250                  getElementsByTagName(u'group')]
251
252    def __parse_tabs(self):
253        dic = {}
254        for tab_name in self.groups:
255            dic[tab_name] = OptionTab(
256                    self.xml.getElementsByTagName(tab_name)[0],
257                    self.options,
258                    self.constructor,
259                    self.update_func)
260        return dic
261
262
263class OptionWidget:
264    def enable_widget(self):
265        self.set_sensitive(True)
266
267    def disable_widget(self):
268        self.set_sensitive(False)
269
270class OptionInterface(gtk.ComboBoxEntry, OptionWidget):
271    def __init__(self):
272        self.list = gtk.ListStore(str)
273        gtk.ComboBoxEntry.__init__(self, self.list)
274
275        cell = gtk.CellRendererText()
276        self.pack_start(cell, True)
277        self.add_attribute(cell, 'text', 0)
278
279class OptionList(gtk.ComboBox, OptionWidget):
280    def __init__(self):
281        self.list = gtk.ListStore(str)
282        gtk.ComboBox.__init__(self, self.list)
283
284        cell = gtk.CellRendererText()
285        self.pack_start(cell, True)
286        self.add_attribute(cell, 'text', 0)
287
288        self.options = []
289
290    def append(self, option):
291        self.list.append([option[u'name']])
292        self.options.append(option)
293
294class OptionCheckIcon(HIGHBox, OptionWidget):
295    def __init__(self, label=None, option=None, hint=None):
296
297        HIGHBox.__init__(self)
298
299        self.cbutton = OptionCheck(label,option)
300        self.option = option
301        self.hint = Hint(hint)
302        self.pack_start(self.cbutton, False, False)
303        self.pack_start(self.hint, False, False, 5)
304
305    def connect(self, action, func, additional):
306        """
307        connect checkbox
308        """
309        self.cbutton.connect(action, func, additional)
310
311    def set_active(self, value):
312        """
313        set enable or disable checkbox
314        """
315        self.cbutton.set_active(value)
316
317    def get_active(self):
318        return self.cbutton.get_active()
319
320    def get_checkbox(self):
321        """
322        Returns checkbox
323        example, to do connection
324        """
325        return self.cbutton
326
327    def get_option(self):
328        return self.cbutton.get_option()
329
330class OptionScriptList(HIGHBox, OptionWidget, object):
331    def __init__(self):
332        HIGHBox.__init__(self)
333
334        self.entry = OptionEntry()
335        self.button = HIGButton(stock=gtk.STOCK_EDIT)
336
337        self._pack_expand_fill(self.entry)
338        self._pack_noexpand_nofill(self.button)
339
340        self.button.connect('clicked', self.open_dialog_cb)
341
342    def open_dialog_cb(self, widget):
343        dialog = ScriptChooserDialog(self.entry.get_text())
344        if dialog.run() == gtk.RESPONSE_OK:
345            self.entry.set_text(dialog.get_scripts())
346        dialog.destroy()
347
348class OptionCheck(gtk.CheckButton, OptionWidget):
349    def __init__(self, label=None, option=None):
350        gtk.CheckButton.__init__(self, label)
351
352        self.option = option
353
354    def get_option(self):
355        return self.option
356
357
358class OptionEntry(gtk.Entry, OptionWidget):
359    def __init__(self, param = ""):
360        gtk.Entry.__init__(self)
361        self.set_text(param)
362
363class OptionLevelSpin(gtk.SpinButton, OptionWidget):
364    def __init__(self, initial=0):
365        gtk.SpinButton.__init__(self,gtk.Adjustment(int(initial),0,10,1),0.0,0)
366
367class OptionIntSpin(gtk.SpinButton, OptionWidget):
368    def __init__(self, initial=1):
369        gtk.SpinButton.__init__(self,
370                                gtk.Adjustment(int(initial),0,10**100,1),
371                                0.0,0)
372
373class OptionFloatSpin(gtk.SpinButton, OptionWidget):
374    def __init__(self, initial=1):
375        gtk.SpinButton.__init__(self,
376                                gtk.Adjustment(float(initial),0,10**100,1),
377                                0.1,2)
378
379class OptionFile(HIGHBox, OptionWidget, object):
380    def __init__(self, param=""):
381        HIGHBox.__init__(self)
382
383        self.entry = OptionEntry()
384        self.button = HIGButton(stock=gtk.STOCK_OPEN)
385
386        self._pack_expand_fill(self.entry)
387        self._pack_noexpand_nofill(self.button)
388
389        self.entry.set_text(param)
390        self.button.connect('clicked', self.open_dialog_cb)
391
392    def open_dialog_cb(self, widget):
393        dialog = AllFilesFileChooserDialog(_("Choose file"))
394        if dialog.run() == gtk.RESPONSE_OK:
395            self.entry.set_text(dialog.get_filename())
396        dialog.destroy()
397
398    def get_filename(self):
399        return "\ ".join(self.entry.get_text().split(" "))
400
401    def set_filename(self, filename):
402        self.entry.set_text(" ".join(filename.split("\ ")))
403
404    filename = property(get_filename, set_filename)
405class Hint(gtk.EventBox, object):
406    def __init__(self, hint):
407        gtk.EventBox.__init__(self)
408        self.hint = hint
409
410        self.hint_image = gtk.Image()
411        self.hint_image.set_from_stock(
412                gtk.STOCK_DIALOG_INFO,
413                gtk.ICON_SIZE_SMALL_TOOLBAR)
414
415        self.add(self.hint_image)
416        self.add_events(gtk.gdk.BUTTON_MOTION_MASK)
417        self.connect("button-press-event", self.show_hint)
418
419
420    def show_hint(self, widget, event=None):
421        hint_window = HintWindow(self.hint)
422        hint_window.show_all()
423
424
425class HintWindow(gtk.Window):
426
427    def __init__(self, hint):
428        gtk.Window.__init__(self, gtk.WINDOW_POPUP)
429        self.set_position(gtk.WIN_POS_MOUSE)
430        bg_color = gtk.gdk.color_parse("#fbff99")
431
432        self.modify_bg(gtk.STATE_NORMAL, bg_color)
433
434        self.event = gtk.EventBox()
435        self.event.modify_bg(gtk.STATE_NORMAL, bg_color)
436        self.event.set_border_width(10)
437        self.event.connect("button-press-event", self.close)
438        self.hint_label = gtk.Label(hint)
439        self.hint_label.set_use_markup(True)
440        self.hint_label.set_line_wrap(True)
441
442        self.event.add(self.hint_label)
443        self.add(self.event)
444
445    def close(self, widget, event=None):
446        self.destroy()
Note: See TracBrowser for help on using the browser.