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

Revision 1415, 20.2 kB (checked in by kop-labs, 6 years ago)

Fixed bug when undo/redo remove pages

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        self.label = None
358
359   
360   
361    def _add_page(self):
362        log.debug('<<< Add new page')
363        if self.label == None :
364            label = self._notebook.create_label(self._name)
365        else : 
366            label = self.label
367        self._notebook.sections_widgets_list.append(label)
368        if self._number == -1:
369            self._notebook.sections_widgets[label] = self._notebook.get_n_pages()
370        else:
371            num = self._number
372            self._notebook.sections_widgets[label] = self._number-1
373            for i in range(num-1, len(self._notebook.sections_widgets)-1):
374                widget_tmp = self._notebook.sections_widgets_list[i+1]
375                self._notebook.sections_widgets[widget_tmp] = self._notebook.sections_widgets[widget_tmp] + 1 
376               
377        self._notebook.insert_page(self._page, label, self._number)
378        #self._notebook.append_page(self._page, label)
379        self._page.show_all()
380        label.voidplace()
381        label.show_all()
382    _execute_1 = _add_page
383    def _remove_page(self):
384        #self._notebook._old_select.unload_voidplace()
385        label_tmp =self._notebook.get_tab_label(
386            self._notebook.get_nth_page(self._number))
387        label_tmp.unload_voidplace()
388        self.label = label_tmp
389        num = self._notebook.sections_widgets[label_tmp]
390        del self._notebook.sections_widgets[label_tmp]
391        for i in range(num, len(self._notebook.sections_widgets)):
392            widget_tmp = self._notebook.sections_widgets_list[i+1]
393            self._notebook.sections_widgets[widget_tmp] = self._notebook.sections_widgets[widget_tmp] - 1 
394       
395        self._notebook.sections_widgets_list.pop(num)
396        self._notebook.remove_page(self._number)
397   
398    _execute_2 = _remove_page
399   
400
401class BoxEditable(HIGVBox):
402    def __init__(self, section_name, profile, listoptions, notebook_parent, new=False):
403        """
404        A Box Editable contains a options of each tab
405        @param section_name: section name <tab>
406        @type section_name: str
407        @param profile: A class that view and modify xml file
408        @type profile: ProfileCore
409        @param listoptions: The List of Options to update XML (I guess to confirm)
410        @type listoptions: ListOptions
411        @param notebook_parent: Notebook
412        @type notebook_parent: Notebook or Subclass
413        @param new: It's a new tab or not
414        @type new: bool
415        """
416           
417        HIGVBox.__init__(self)
418        self._coords = {}
419        self._parent = notebook_parent
420        self._last = None 
421        #Profile Core do a manage at profile_editor.xml file
422        self._profilecore = None 
423       
424        self._profile = profile
425        self._listoptions = listoptions
426        self._table = HIGTable()
427        self._section_name = section_name
428        if not new :
429            self._options = self._profile.get_section(section_name)
430        self._table.set_border_width(3)
431        c = self.get_colormap()
432        color = c.alloc_color(0,0,0)   
433        self._table.modify_fg(gtk.STATE_NORMAL,color )
434        #self._fill_table()
435       
436        box_tmp = HIGVBox()
437        box_tmp.pack_start(self._table, False, False)
438        self._sw = HIGScrolledWindow()
439        #self._sw.set_size_request(400,200)
440        vp = gtk.Viewport()
441        vp.add(box_tmp)
442        vp.set_shadow_type(gtk.SHADOW_NONE)
443        self._sw.add(vp)
444        self.pack_start(self._sw, True, True)
445        self._old_selected = None 
446        self._x = 0
447        self._y = 0 
448       
449       
450        self.connect('button-press-event', self._bp)
451    #Private API
452    def _bp(self, widget,event):
453        pass
454
455    def _fill_table(self):
456        k = 0
457        for i in self._options:
458            t = SpecialHBox()
459            type = i.get_type()
460            if type== 'option_check':
461               
462                name_option = i.get_option()
463                hint = self._listoptions.get_hint(name_option)
464                tmp_widget = OptionCheckIcon(i.get_label(),name_option,hint)
465                t.pack_start(tmp_widget)
466                arg_type = self._listoptions.get_arg_type(name_option)
467                if arg_type!= '':
468                    additional = type_mapping[arg_type]()
469                    t.pack_start(additional)
470                po = ProfileOption('option_check', i.get_label(),name_option, 
471                                   arg_type,None)
472                po.set_section(self.get_name())
473                t.set_profileoption(po)
474               
475               
476            elif type == 'option_list': 
477                eventbox = gtk.EventBox()
478                label = HIGEntryLabel(i.get_label())
479               
480                eventbox.add(label)
481                tmp_widget = OptionList()
482                list = []
483                for j in i.get_option_list():
484                    d = {}
485                    d['name'] = j
486                    tmp_widget.append(d)
487                    list.append(j)
488                po = ProfileOption('option_list', i.get_label(),i.get_label(), 
489                                   None,list)
490                po.set_section(self.get_name())
491                t.set_profileoption(po)
492                t.pack_start(eventbox)         
493                t.pack_start(tmp_widget)
494                #t.drag_source_set(gtk.gdk.BUTTON1_MASK |
495                                                  #gtk.gdk.BUTTON3_MASK,
496                                                  #target,
497                                                  #gtk.gdk.ACTION_COPY |
498                                                  #gtk.gdk.ACTION_MOVE)
499                #t.connect('drag_data_get', self.source_drag_data_get)
500           
501            #XXX : I think that is very important ( I only comment to get focus)
502            t.set_flags( t.flags() |  gtk.CAN_FOCUS)
503            t.connect('button-press-event', self._button_press_event)
504            t.connect('key-press-event', self._key_press_event)
505            t.set_name(i.get_label())
506            t.connect('drag_data_received', self.drag_received)
507            t.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
508                                gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
509           
510            self._table.attach(t, 0,2, k,k+1)
511            self._coords[t] = [k, k+1]
512            self._x = k
513            self._y = k+1
514            k =k +1
515            self._last = t
516       
517   
518    def delete_on_item(self, widget):
519        if not widget.is_voidplace(): 
520            # remove widgets like checkbuttons or others and put voidplace
521            childs = widget.get_children()
522            cmd = CommandAddRemoveOption(widget,childs,
523                                         self._profilecore, False)
524            widget.set_select(False)
525            command_manager.add_command(cmd)
526            log.debug(' Remove Widgets like CheckButtons or others and put voidplace')
527           
528        else:
529            # remove voidplace and delete the widget from table/box
530            #XXX
531            cmd = CommandAddRemoveVoidplace(self, 
532                                            widget, self._coords, False)
533            #widget.unload_voidplace()
534            command_manager.add_command(cmd)
535            log.debug('Remove voidplace and delete the widget from table')
536       
537   
538   
539       
540    def _key_press_event(self, widget, event):
541        print "key pressed"
542        _keyval = gtk.gdk.keyval_name(event.keyval)
543        if _keyval == "Delete" and self._old_selected!=None :
544            self.delete_on_item(widget)
545
546               
547        #self._table.remove(widget)
548        #childs = self._table.get_children()
549        #for i in childs:
550            #if i.is_voidplace():
551                #i.do_resize_voidplace()
552    def _button_press_event(self,widget, event):
553        widget.set_select(True) 
554        self._parent.select(False)
555        if widget == self._old_selected :
556            log.debug('Do nothing')
557            if widget.is_voidplace():
558                widget.do_draw()
559            widget.grab_focus()
560            return 
561        widget.do_draw()
562        if self._old_selected != None:
563            self._old_selected.set_select(False)
564        log.debug('drawing')
565        self._old_selected = widget
566        widget.grab_focus()
567        self._parent.emit('changed', 'Options', self._parent.get_current_page())
568
569    #Public API
570    def get_name(self):
571        return self._section_name
572   
573    def can_move_up(self):
574       
575        widget = self._old_selected
576        x = 0 
577        if widget!= None :
578            x,y = self._coords[widget]
579        return x != 0
580    def can_move_down(self):
581       
582        widget = self._old_selected
583        y = len(self._coords)
584        if widget!= None :
585            x,y = self._coords[widget]
586        return y != (len(self._coords))
587    def send_signal(self):
588        self._parent.emit('changed', 'Options', self._parent.get_current_page())
589    def create_item(self):
590        t = SpecialHBox()
591        e = gtk.EventBox()
592        label = gtk.Label('-')
593        label.set_size_request(-1, 23)
594        #e.add(label)
595        t.pack_start(label)
596        t.set_flags( t.flags() |  gtk.CAN_FOCUS)
597        t.connect('button-press-event', self._button_press_event)
598        t.connect('key-press-event', self._key_press_event)
599        t.connect('drag_data_received', self.drag_received)
600        t.drag_dest_set(gtk.DEST_DEFAULT_ALL, target[:-1],
601                            gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
602        return t
603    def add_voidplace(self, position):
604        # Create SpecialHBox with Voidplace
605        t = self.create_item()
606        cmd = CommandVoidPlaceAttach(self, t, self._coords, True)
607        command_manager.add_command(cmd)
608       
609        #if position == -1 :
610            #x, y = self._x,self._y
611            #self._table.attach()
612        #else:
613            ## Choose the position
614            #pass
615   
616    def move_item_down(self):
617        '''
618        Move selected item to down
619        '''
620        assert self.can_move_down()
621       
622        cmd = CommandMove(self, self._old_selected, self._coords, self._profilecore, False)
623        command_manager.add_command(cmd)
624        self.send_signal()
625    def move_item_up(self):
626        '''
627        Move selected item to up
628        '''
629        assert self.can_move_up()
630       
631        cmd = CommandMove(self, self._old_selected, self._coords, self._profilecore, True)
632        command_manager.add_command(cmd)
633        self.send_signal()
634   
635   
636    def set_profile_core(self, profile_core):
637        self._profilecore = profile_core
638   
639    def option_builder(self, option_name, type):
640        '''
641        construct a widget with the name of the option
642        @return: A widget
643        @rtype: Widget like OptionCheck or others
644        '''
645        result = []
646        hint = self._listoptions.get_hint(option_name)
647        #label, option_name, hint
648        tmp_widget = OptionCheckIcon(option_name,option_name,hint) 
649        result.append(tmp_widget)
650        arg_type = self._listoptions.get_arg_type(option_name)
651        if arg_type!= '':
652            additional = type_mapping[arg_type]()
653            result.append(additional)
654        return result
655       
656       
657       
658       
659    def _is_widget(self, name):
660        return name[0:4] == '_wid'
661    def _create_option_list(self, widget):
662        eventbox = gtk.EventBox()
663        name = 'New Option List'
664        label = HIGEntryLabel(name)
665       
666        eventbox.add(label)
667        tmp_widget = OptionList()
668        list = []
669        void = {'name':''}
670        j = 'None'
671        d = {}
672        d['name'] = j
673        tmp_widget.append(void)
674        tmp_widget.append(d)
675        list.append(j)
676        po = ProfileOption('option_list',name ,None, 
677                           None,list)
678        po.set_section(self.get_name())
679        widget.set_profileoption(po)
680        widgets = [] 
681        widgets.append(eventbox)
682        widgets.append(tmp_widget)
683        widget.set_name(name)
684        return widgets
685
686   
687    def drag_received(self,w, context, x, y, data, info, time):
688        if not w.is_voidplace(): 
689            return 
690        option_name = data.data
691        if self._is_widget(option_name) :
692            if option_name == '_widget_option_list':
693               
694                widgets = self._create_option_list( w)
695                cmd = CommandAddRemoveOption(w,widgets, self._profile,
696                                             True)
697                command_manager.add_command(cmd)
698               
699            return
700        name = data.data
701       
702        opt = self._listoptions.get_option_class(name)
703        profileoption = option_to_profileoption(opt)
704        profileoption.set_section(self.get_name())
705        arg_type = self._listoptions.get_arg_type(data.data)
706        widgets = self.option_builder(option_name, arg_type)
707        w.set_profileoption(profileoption)
708        #Remove child
709        #childs = w.get_children()
710        #w.remove(childs[0])
711        #Add
712
713        #for child in widgets:
714            #t = gtk.Label('fsck')
715            #tmp_w.pack_start(child)
716            #child.show_all()
717       
718        #w.unload_voidplace()
719        cmd = CommandAddRemoveOption(w, widgets, self._profilecore, True)
720        command_manager.add_command(cmd)
721       
722    def get_table(self):
723        return self._table
724    def set_last(self, last):
725        self._last = last
726    def get_last(self):
727        return self._last
728    def source_drag_data_get(self, btn, context, selection_data, info, time):
729        selection_data.set(selection_data.target, 8, "I'm Data!")   
Note: See TracBrowser for help on using the browser.