root/branch/k0p/umitInterfaceEditor/PageNotebook.py @ 1393

Revision 1393, 19.7 kB (checked in by kop-labs, 6 years ago)

Fixed bug when save OptionList?

Line 
1#!/usr/bin/env python
2# Copyright (C) 2005 Insecure.Com LLC.
3# Authors:
4#  Adriano Monteiro Marques <py.adriano@gmail.com>
5#  Luis Antonio Bastiao Silva <luis.kop@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21import gtk
22from umitGUI.OptionBuilder import *
23from umitInterfaceEditor.Command import Command, TwiceCommand, command_manager
24from higwidgets.higboxes import HIGVBox
25from umitInterfaceEditor.selectborder.WrapperWidgets import NotebookLabel, SpecialHBox
26from umitCore.Logging import log
27from umitCore.I18N import _
28from higwidgets.higtables import HIGTable
29from higwidgets.higscrollers import HIGScrolledWindow
30from higwidgets.higlabels import HIGSectionLabel, HIGEntryLabel
31
32from umitInterfaceEditor.ProfileCore import ProfileOption, option_to_profileoption
33
34TARGET_STRING = 0
35TARGET_ROOTWIN = 1
36
37target = [
38    ('STRING', 0, TARGET_STRING),
39    ('text/plain', 0, TARGET_STRING),
40    ('application/x-rootwin-drop', 0, TARGET_ROOTWIN)
41]
42
43
44#Global variables
45SPACE_TABLE = 6
46
47
48
49# XXX : Should be put in other file to using by OptionBuilder too
50type_mapping = { 
51    "str": OptionEntry,
52    "int": OptionIntSpin,
53    "float": OptionFloatSpin,
54    "level": OptionLevelSpin, 
55    "path": OptionFile,
56    "interface": OptionInterface, 
57    "scriptlist": OptionScriptList
58    }
59
60class CommandAddRemoveVoidplace(TwiceCommand, Command):
61    '''
62    Add or Remove A voidplace on the Editor-Mode
63   
64    '''
65    def __init__(self, table, widget, coords, state): 
66        TwiceCommand.__init__(self, state)
67        Command.__init__(self, _('Add/Remove Voidplace'))
68        self._box = table
69        self._table = table.get_table()
70       
71        self._widget = widget
72        self._x,self._y = coords[widget] 
73        #self._spacing = self._table.get_row_spacing(self._x)
74        self._spacing = SPACE_TABLE
75    def _add(self):
76
77       
78        #self._widget.do_draw()
79        label = self._widget.get_children()[0]
80        label = gtk.Label()
81
82        label.show()
83       
84        self._widget.set_size_request(-1, 23)
85        self._widget.show()
86        self._widget.set_view(True)
87
88        if self._widget.is_voidplace():
89            self._widget.show_voidplace()
90       
91        self._widget.set_view(True)
92        #self._table.attach(self._widget, 0,2,self._x,self._y)
93        self._table.set_row_spacing(self._x,self._spacing)
94        #self._widget.do_voidplace()
95        #self._widget.do_voidplace()
96
97        log.debug('CommandVoidplace: add voidplace')
98       
99    _execute_1 = _add
100    def _remove(self):
101       
102        if self._widget != None and self._widget.is_voidplace():
103            log.debug('CommandVoidplace: remove voidplace')
104            self._widget.hide_voidplace()
105            self._widget.set_select(False)
106            self._widget.hide()
107            self._widget.set_view(False)
108            self._table.set_row_spacing(self._x,0)
109            self._widget.set_size_request(-1, 0)
110            pass
111            #self._widget.unload_voidplace()
112            #self._table.remove(self._widget)
113           
114    _execute_2 = _remove
115   
116
117
118class CommandVoidPlaceAttach(TwiceCommand, Command):
119    '''
120    Add a new widget (voidplace) at the last position
121   
122    '''
123    def __init__(self,table, widget, coords, state):
124        self._last = table.get_last()
125        self._box = table
126        if self._last != None :
127            x, y = coords[self._last] 
128        else: 
129            x, y = -1,0
130        coords[widget] = [+1 , y+1]
131        TwiceCommand.__init__(self, state)
132        Command.__init__(self, _('Add/Remove Voidplace'))
133        self._table = table.get_table()
134        self._box.set_last(widget)
135        self._widget = widget
136        self._x,self._y = coords[widget] 
137        self._coords = coords
138        #self._spacing = self._table.get_row_spacing(x-1)
139        self._spacing = SPACE_TABLE
140    def _attach(self):
141        self._table.resize(self._y, 2)
142        log.debug('<<< Attach Add Voidplace')
143        self._table.set_row_spacing(self._x,self._spacing)
144
145        self._table.attach(self._widget, 0, 2, self._x, self._y)
146        self._widget.show_all()
147        self._widget.do_voidplace()
148        self._widget.set_view(True)
149       
150
151       
152       
153    _execute_1 = _attach
154    def _unattach(self):
155        #if self._widget != None and self._widget.is_voidplace():
156            #log.debug('<<< remove voidplace unattach')
157            #self._widget.hide_voidplace()
158            #self._widget.set_select(False)
159            #self._widget.hide()
160            #self._table.set_row_spacing(self._x,0)
161        self._widget.unload_voidplace()
162        self._table.remove(self._widget)
163        del self._coords[self._widget]
164    _execute_2 = _unattach
165
166class CommandMove(TwiceCommand, Command):
167    '''
168    Move items to down or up
169    #Trick:
170    - Add other colums to save row and do a swap. Use a temporary widget.
171    '''
172    def __init__(self, widget_container, widget, coords , profilecore,  state):
173        TwiceCommand.__init__(self, state)
174        Command.__init__(self, _('Move item'))
175        self._parent = widget_container
176        self._section_name = widget_container.get_name()
177        self._table = widget_container.get_table()
178        self._move = widget
179        self._coords = coords
180        self._profilecore = profilecore
181        self._x, self._y = self._coords[widget]
182        self._name = widget.get_name()
183        if self._name == None:
184            self._voidplace = True 
185        else :
186            self._voidplace = False
187       
188       
189       
190    def _determine_child(self, list, num): 
191        result = None 
192        x, y = self._coords[self._move]
193        x = x + num
194        y = y + num
195        for i in list : 
196            x_tmp, y_tmp = self._coords[i]
197            if x_tmp == x and y_tmp == y  :
198                result= i
199                break 
200        return result
201    def _get_next(self):
202         
203        childs = self._table.get_children()
204        return self._determine_child(childs, 1)
205    def _get_prev(self): 
206       
207        childs = self._table.get_children()
208        childs.reverse()
209        return self._determine_child(childs,-1) 
210    def _swap(self, widget1, widget2):
211        x1, y1 = self._coords[widget1]
212        x2, y2 = self._coords[widget2]
213        list_vp = []
214        if widget1.is_voidplace():
215            widget1.unload_voidplace()
216            list_vp.append(widget1)
217           
218        if widget2.is_voidplace():
219            list_vp.append(widget2)
220            widget2.unload_voidplace()
221
222       
223        widget1.set_select(False)
224        widget2.set_select(False)
225        w_tmp = gtk.Label('tmp')
226        self._table.attach(w_tmp, 1,2, x1, y1)
227        self._table.remove(widget1)
228        self._table.attach(widget1, 0,2, x2, y2)
229        self._table.remove(widget2)
230        self._table.attach(widget2, 0,2, x1, y1)
231        self._table.remove(w_tmp)
232       
233        self._coords[widget1] = [x2, y2]
234        self._coords[widget2] = [x1,y1]
235        #self._move = widget2
236        for i in list_vp:
237            i.do_voidplace()
238            #i.do_resize_voidplace()
239           
240           
241    def _move_up(self):
242       
243        widget_swap = self._get_prev()
244        if not self._voidplace : 
245            self._profilecore.move_option_up(self._section_name, 
246                                         self._name,
247                                         widget_swap.get_name())
248        self._swap(self._move, widget_swap)
249        #widget_swap.do_resize_voidplace()
250        self._parent.send_signal()
251        self._move.do_draw()
252        log.debug('<<< Moving item up')
253    _execute_1 = _move_up
254   
255    def _move_down(self):
256       
257        widget_swap = self._get_next()
258        if not self._voidplace : 
259            self._profilecore.move_option_down(self._section_name, 
260                                           self._name, 
261                                           widget_swap.get_name())
262        self._swap( widget_swap, self._move)
263        #x, y = self._coords[widget_swap]
264        #self._move.set_select(False)
265        #widget_swap.set_select(False)
266
267        #w_tmp = gtk.Label('tmp')
268        #self._table.attach(w_tmp, 1,2, x, y)
269        #self._table.remove(widget_swap)
270        #self._table.attach(widget_swap, 0,2, self._x, self._x+1)
271        #self._table.remove(self._move)
272       
273        #self._table.attach(self._move, 0,2, x, y)
274        #self._table.remove(w_tmp)
275       
276        #self._coords[widget_swap] = [self._x, self._y]
277        #self._coords[self._move] = [x,y]
278        self._parent.send_signal()
279        self._move.do_draw()
280        log.debug('<<< Moving item down')
281       
282    _execute_2 = _move_down
283
284
285class CommandAddRemoveOption(TwiceCommand, Command):
286    '''
287    Add or Remove Option from BoxEditable
288    ###
289    trik : state is a inicial value if it is remove or add.
290    '''
291    def __init__(self, widget_container, widget_option,profilecore, state):
292        TwiceCommand.__init__(self, state)
293        Command.__init__(self, _('Add/Remove Option'))
294        self._widget = widget_container
295        self._widget_option = widget_option
296        self._profilecore = profilecore
297       
298   
299    def _add_option(self):
300        widget_option = self._widget_option
301        widget = self._widget
302        childs = widget.get_children()
303        widget.remove(childs[0])
304        if widget.is_voidplace():
305            widget.unload_voidplace()
306        for k in widget_option:
307            widget.pack_start(k)
308            k.show_all()
309        #widget_option.show() # XXX - may be need
310       
311        #Profile Core modifications:
312        po = self._widget.get_profileoption()
313        self._profilecore.add_from_profileoption(po)
314       
315       
316       
317        log.debug('Adding option')
318    _execute_1 = _add_option
319    def _remove_option(self):
320       
321        widget = self._widget
322        childs = widget.get_children()
323        for i in childs:
324            widget.remove(i)
325        t = gtk.Label('-')
326        t.set_size_request(-1, 23)
327        t.show()
328       
329        widget.pack_start(t)
330        widget.do_voidplace()
331       
332
333        #Profile Core modifications:
334        po = self._widget.get_profileoption()
335        self._profilecore.remove_opt(po.get_section(), po.get_label())
336       
337       
338       
339       
340        log.debug('Removing option, Adding Void Place')
341    _execute_2 = _remove_option
342
343
344class CommandPageNotebook(TwiceCommand, Command):
345    '''
346    Add Page at Notebook or Remove
347    '''
348    def __init__(self, notebook, page, number, profilecore, state):
349        TwiceCommand.__init__(self, state)
350        Command.__init__(self, _('Add/Remove Page'))
351        self._notebook = notebook
352        self._page = page
353        self._number = number
354        self._profilecore = profilecore
355        self._name = self._page.get_name()
356
357   
358   
359    def _add_page(self):
360        log.debug('<<< Add new page')
361        label = self._notebook.create_label(self._name)
362        self._notebook.sections_widgets_list.append(label)
363        self._notebook.sections_widgets[label] = self._notebook.get_n_pages()
364       
365        self._notebook.insert_page(self._page, label, self._number)
366        #self._notebook.append_page(self._page, label)
367        self._page.show_all()
368        label.voidplace()
369        label.show_all()
370    _execute_1 = _add_page
371    def _remove_page(self):
372        #self._notebook._old_select.unload_voidplace()
373        label_tmp =self._notebook.get_tab_label(
374            self._notebook.get_nth_page(self._number))
375        label_tmp.unload_voidplace()
376        num = self._notebook.sections_widgets[label_tmp]
377        del self._notebook.sections_widgets[label_tmp]
378        for i in range(num, len(self._notebook.sections_widgets)):
379            print i
380            widget_tmp = self._notebook.sections_widgets_list[i+1]
381            self._notebook.sections_widgets[widget_tmp] = self._notebook.sections_widgets[widget_tmp] - 1 
382       
383        self._notebook.sections_widgets_list.pop(num)
384        self._notebook.remove_page(self._number)
385   
386    _execute_2 = _remove_page
387   
388
389class BoxEditable(HIGVBox):
390    def __init__(self, section_name, profile, listoptions, notebook_parent, new=False):
391        """
392        A Box Editable contains a options of each tab
393        @param section_name: section name <tab>
394        @type section_name: str
395        @param profile: A class that view and modify xml file
396        @type profile: ProfileCore
397        @param listoptions: The List of Options to update XML (I guess to confirm)
398        @type listoptions: ListOptions
399        @param notebook_parent: Notebook
400        @type notebook_parent: Notebook or Subclass
401        @param new: It's a new tab or not
402        @type new: bool
403        """
404           
405        HIGVBox.__init__(self)
406        self._coords = {}
407        self._parent = notebook_parent
408        self._last = None 
409        #Profile Core do a manage at profile_editor.xml file
410        self._profilecore = None 
411       
412        self._profile = profile
413        self._listoptions = listoptions
414        self._table = HIGTable()
415        self._section_name = section_name
416        if not new :
417            self._options = self._profile.get_section(section_name)
418        self._table.set_border_width(3)
419        c = self.get_colormap()
420        color = c.alloc_color(0,0,0)   
421        self._table.modify_fg(gtk.STATE_NORMAL,color )
422        #self._fill_table()
423       
424        box_tmp = HIGVBox()
425        box_tmp.pack_start(self._table, False, False)
426        self._sw = HIGScrolledWindow()
427        #self._sw.set_size_request(400,200)
428        vp = gtk.Viewport()
429        vp.add(box_tmp)
430        vp.set_shadow_type(gtk.SHADOW_NONE)
431        self._sw.add(vp)
432        self.pack_start(self._sw, True, True)
433        self._old_selected = None 
434        self._x = 0
435        self._y = 0 
436       
437       
438        self.connect('button-press-event', self._bp)
439    #Private API
440    def _bp(self, widget,event):
441        pass
442
443    def _fill_table(self):
444        k = 0
445        for i in self._options:
446            t = SpecialHBox()
447            type = i.get_type()
448            if type== 'option_check':
449               
450                name_option = i.get_option()
451                hint = self._listoptions.get_hint(name_option)
452                tmp_widget = OptionCheckIcon(i.get_label(),name_option,hint)
453                t.pack_start(tmp_widget)
454                arg_type = self._listoptions.get_arg_type(name_option)
455                if arg_type!= '':
456                    additional = type_mapping[arg_type]()
457                    t.pack_start(additional)
458                po = ProfileOption('option_check', i.get_label(),name_option, 
459                                   arg_type,None)
460                po.set_section(self.get_name())
461                t.set_profileoption(po)
462               
463               
464            elif type == 'option_list': 
465                eventbox = gtk.EventBox()
466                label = HIGEntryLabel(i.get_label())
467               
468                eventbox.add(label)
469                tmp_widget = OptionList()
470                list = []
471                for j in i.get_option_list():
472                    d = {}
473                    d['name'] = j
474                    tmp_widget.append(d)
475                    list.append(j)
476                po = ProfileOption('option_list', i.get_label(),i.get_label(), 
477                                   None,list)
478                po.set_section(self.get_name())
479                t.set_profileoption(po)
480                t.pack_start(eventbox)         
481                t.pack_start(tmp_widget)
482                #t.drag_source_set(gtk.gdk.BUTTON1_MASK |
483                                                  #gtk.gdk.BUTTON3_MASK,
484                                                  #target,
485                                                  #gtk.gdk.ACTION_COPY |
486                                                  #gtk.gdk.ACTION_MOVE)
487                #t.connect('drag_data_get', self.source_drag_data_get)
488           
489            #XXX : I think that is very important ( I only comment to get focus)
490            t.set_flags( t.flags() |  gtk.CAN_FOCUS)
491            t.connect('button-press-event', self._button_press_event)
492            t.connect('key-press-event', self._key_press_event)
493            t.set_name(i.get_label())
494            t.connect('drag_data_received', self.drag_received)
495            t.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
496                                gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
497           
498            self._table.attach(t, 0,2, k,k+1)
499            self._coords[t] = [k, k+1]
500            self._x = k
501            self._y = k+1
502            k =k +1
503            self._last = t
504       
505   
506       
507    def _key_press_event(self, widget, event):
508        print "key pressed"
509        _keyval = gtk.gdk.keyval_name(event.keyval)
510        if _keyval == "Delete" and self._old_selected!=None :
511            if not widget.is_voidplace(): 
512                # remove widgets like checkbuttons or others and put voidplace
513                childs = widget.get_children()
514                cmd = CommandAddRemoveOption(widget,childs,
515                                             self._profilecore, False)
516                widget.set_select(False)
517                command_manager.add_command(cmd)
518                log.debug(' Remove Widgets like CheckButtons or others and put voidplace')
519               
520            else:
521                # remove voidplace and delete the widget from table/box
522                #XXX
523                cmd = CommandAddRemoveVoidplace(self, 
524                                                widget, self._coords, False)
525                #widget.unload_voidplace()
526                command_manager.add_command(cmd)
527                log.debug('Remove voidplace and delete the widget from table')
528               
529        #self._table.remove(widget)
530        #childs = self._table.get_children()
531        #for i in childs:
532            #if i.is_voidplace():
533                #i.do_resize_voidplace()
534    def _button_press_event(self,widget, event):
535        widget.set_select(True) 
536        self._parent.select(False)
537        if widget == self._old_selected :
538            log.debug('Do nothing')
539            if widget.is_voidplace():
540                widget.do_draw()
541            widget.grab_focus()
542            return 
543        widget.do_draw()
544        if self._old_selected != None:
545            self._old_selected.set_select(False)
546        log.debug('drawing')
547        self._old_selected = widget
548        widget.grab_focus()
549        self._parent.emit('changed', 'Options', self._parent.get_current_page())
550
551    #Public API
552    def get_name(self):
553        return self._section_name
554   
555    def can_move_up(self):
556       
557        widget = self._old_selected
558        x = 0 
559        if widget!= None :
560            x,y = self._coords[widget]
561        return x != 0
562    def can_move_down(self):
563       
564        widget = self._old_selected
565        y = len(self._coords)
566        if widget!= None :
567            x,y = self._coords[widget]
568        return y != (len(self._coords))
569    def send_signal(self):
570        self._parent.emit('changed', 'Options', self._parent.get_current_page())
571    def create_item(self):
572        t = SpecialHBox()
573        e = gtk.EventBox()
574        label = gtk.Label('-')
575        label.set_size_request(-1, 23)
576        #e.add(label)
577        t.pack_start(label)
578        t.set_flags( t.flags() |  gtk.CAN_FOCUS)
579        t.connect('button-press-event', self._button_press_event)
580        t.connect('key-press-event', self._key_press_event)
581        t.connect('drag_data_received', self.drag_received)
582        t.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
583                            gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
584        return t
585    def add_voidplace(self, position):
586        # Create SpecialHBox with Voidplace
587        t = self.create_item()
588        cmd = CommandVoidPlaceAttach(self, t, self._coords, True)
589        command_manager.add_command(cmd)
590       
591        #if position == -1 :
592            #x, y = self._x,self._y
593            #self._table.attach()
594        #else:
595            ## Choose the position
596            #pass
597   
598    def move_item_down(self):
599        '''
600        Move selected item to down
601        '''
602        assert self.can_move_down()
603       
604        cmd = CommandMove(self, self._old_selected, self._coords, self._profilecore, False)
605        command_manager.add_command(cmd)
606        self.send_signal()
607    def move_item_up(self):
608        '''
609        Move selected item to up
610        '''
611        assert self.can_move_up()
612       
613        cmd = CommandMove(self, self._old_selected, self._coords, self._profilecore, True)
614        command_manager.add_command(cmd)
615        self.send_signal()
616   
617   
618    def set_profile_core(self, profile_core):
619        self._profilecore = profile_core
620   
621    def option_builder(self, option_name, type):
622        '''
623        construct a widget with the name of the option
624        @return: A widget
625        @rtype: Widget like OptionCheck or others
626        '''
627        result = []
628        hint = self._listoptions.get_hint(option_name)
629        #label, option_name, hint
630        tmp_widget = OptionCheckIcon(option_name,option_name,hint) 
631        result.append(tmp_widget)
632        arg_type = self._listoptions.get_arg_type(option_name)
633        if arg_type!= '':
634            additional = type_mapping[arg_type]()
635            result.append(additional)
636        return result
637       
638       
639       
640       
641    def _is_widget(self, name):
642        return name[0:4] == '_wid'
643    def _create_option_list(self, widget):
644        eventbox = gtk.EventBox()
645        name = 'New Option List'
646        label = HIGEntryLabel(name)
647       
648        eventbox.add(label)
649        tmp_widget = OptionList()
650        list = []
651        void = {'name':''}
652        j = 'None'
653        d = {}
654        d['name'] = j
655        tmp_widget.append(void)
656        tmp_widget.append(d)
657        list.append(j)
658        po = ProfileOption('option_list',name ,None, 
659                           None,list)
660        po.set_section(self.get_name())
661        widget.set_profileoption(po)
662        widgets = [] 
663        widgets.append(eventbox)
664        widgets.append(tmp_widget)
665        widget.set_name(name)
666        return widgets
667
668   
669    def drag_received(self,w, context, x, y, data, info, time):
670        if not w.is_voidplace(): 
671            return 
672        option_name = data.data
673        if self._is_widget(option_name) :
674            if option_name == '_widget_option_list':
675               
676                widgets = self._create_option_list( w)
677                cmd = CommandAddRemoveOption(w,widgets, self._profile,
678                                             True)
679                command_manager.add_command(cmd)
680               
681            return
682        name = data.data
683       
684        opt = self._listoptions.get_option_class(name)
685        profileoption = option_to_profileoption(opt)
686        profileoption.set_section(self.get_name())
687        arg_type = self._listoptions.get_arg_type(data.data)
688        widgets = self.option_builder(option_name, arg_type)
689        w.set_profileoption(profileoption)
690        #Remove child
691        #childs = w.get_children()
692        #w.remove(childs[0])
693        #Add
694
695        #for child in widgets:
696            #t = gtk.Label('fsck')
697            #tmp_w.pack_start(child)
698            #child.show_all()
699       
700        #w.unload_voidplace()
701        cmd = CommandAddRemoveOption(w, widgets, self._profilecore, True)
702        command_manager.add_command(cmd)
703       
704    def get_table(self):
705        return self._table
706    def set_last(self, last):
707        self._last = last
708    def get_last(self):
709        return self._last
710    def source_drag_data_get(self, btn, context, selection_data, info, time):
711        selection_data.set(selection_data.target, 8, "I'm Data!")   
Note: See TracBrowser for help on using the browser.