root/trunk/listview.py
| Revision 138 (by manatlan, 11/30/06 14:04:41) |
|---|
# -*- coding: utf-8 -*- ## ## Copyright (C) 2005 manatlan manatlan[at]gmail(dot)com ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published ## by the Free Software Foundation; version 2 only. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## # example table.py import pygtk pygtk.require('2.0') import gtk import gobject from common import cd2d, cd2rd, format_file_size_for_display class ListView(gtk.EventBox): # static __nbx=1 __nby=1 sort_mode = 0 reversed_sort = False choix = [_("Tags"),_("Comment"),_("Album"),_("Date"),_("Name")] __choix = 0 __focus=0 #~ __gsignals__ = {'refreshItem' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT,) ) } #~ # userevent "refreshItem" #~ def do_refreshItem(self,a): pass #~ def refreshI(self,e,num): #~ for item in self.__items: #~ if num == self.__yoff + self.__items.index(item): #~ item.refresh() def refreshItem(self,num): #~ print ">>>>>>>>> recept a refresh for",num for item in self.__items: if num == self.__yoff + self.__items.index(item): item.refresh() #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= class Item(gtk.EventBox): text_size=20 def __init__(self,pere): # num de la case gtk.EventBox.__init__(self) self.pere = pere #tbl = gtk.Table(2, 1, False) #tbl.set_size_request(160,190) vbox = gtk.VBox() vbox.set_size_request(self.pere.size, self.pere.size+ListView.Item.text_size) self.__img = gtk.Image() self.__lbl = gtk.Label("-") #~ self.__lbl.set_single_line_mode(True) self.__lbl.set_line_wrap(True) #tbl.attach(self.__img,0,1,0,1,gtk.EXPAND,gtk.EXPAND) #tbl.attach(self.__lbl,0,1,1,2,gtk.SHRINK,gtk.SHRINK) vbox.pack_start(self.__img, True, True) vbox.pack_end(self.__lbl, False, False) self.__lbl.set_size_request(self.pere.size,-1) self.__lbl.set_justify(gtk.JUSTIFY_CENTER) #~ self.__img.set_state(gtk.CAN_FOCUS) #~ self.__lbl.set_state(gtk.CAN_FOCUS) #tbl.show() vbox.show() self.set_flags(gtk.CAN_FOCUS) #self.add(tbl) self.add(vbox) self.connect("button_press_event", self.onClick) self.connect("button_release_event", self.onClickRelease) target = [ ('STRING', 0, 111), #~ ('text/plain', 0, 222), # ('application/x-rootwin-drop', 0, 333) ] #~ self.set_state(gtk.CAN_FOCUS) #~ tbl.set_state(gtk.CAN_FOCUS) #~ self.__img.set_state(gtk.CAN_FOCUS) #~ self.__lbl.set_state(gtk.CAN_FOCUS) if self.pere.dragNdropPossible: self.drag_source_set(gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON2_MASK, target, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) self.drag_dest_set(gtk.DEST_DEFAULT_ALL, target, gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE) self.connect("drag_data_received", self.drag_data_received_data) def drag_data_received_data(self,widget,*args): item = self.pere._whichItemAmI(self) if item>=0: self.pere._onDrop( item , *args) def onClick(self,w,event): item = self.pere._whichItemAmI(self) if item>=0: self.pere.onItemClick( item , event) def onClickRelease(self,w,event): item = self.pere._whichItemAmI(self) if item>=0: self.pere.onItemClickRelease( item , event) def refresh(self): item = self.pere._whichItemAmI(self) self.__lbl.set_state(gtk.STATE_NORMAL) # to correct a *bug* of gtk/states if item>=0: #~ if self.pere.isSelected( item ): #~ img = self.pere.getImage(item, selected = True) #~ else: #~ img = self.pere.getImage(item) img = self.pere.getImage(item) nom = self.pere._getTitle( item ) self.__img.set_from_pixbuf(img) self.__lbl.set_text( nom ) self.__img.show() self.__lbl.show() if self.pere.isFocused( item ): pass #self.__lbl.set_text( "["+nom+"]" ) # to present the cursor if self.pere.isSelected( item ): #self.__img.set_sensitive(False) self.set_state(gtk.STATE_SELECTED) else: #~ self.__img.set_sensitive(True) self.set_state(gtk.STATE_NORMAL) else: self.__img.hide() self.__lbl.hide() self.set_state(gtk.STATE_NORMAL) #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= def __init__(self,parent,size,dragNdropPossible=False): #~ gobject.GObject.__init__(self) gtk.EventBox.__init__(self) self.parentWin = parent self.size=size self.dragNdropPossible = dragNdropPossible #~ self.connect("refreshItem",self.refreshI) self.list=[] self.__focus=0 self.__selected=[0] self.__yoff = 0 self.tbl = gtk.Table(self.__nby, self.__nbx, False) self.tbl.set_col_spacings(1) self.tbl.set_flags(gtk.CAN_FOCUS) #~ self.btn_up = gtk.Button("^") #~ self.btn_up.connect("clicked", self.moveFocus, "page_up") #~ self.btn_up.show() #~ self.btn_down = gtk.Button("v") #~ self.btn_down.connect("clicked", self.moveFocus, "page_down") #~ self.btn_down.show() #~ self.btn_up.unset_flags(gtk.CAN_FOCUS) #~ self.btn_down.unset_flags(gtk.CAN_FOCUS) self.vscroll = gtk.VScrollbar() self.vscroll.set_update_policy(gtk.UPDATE_DISCONTINUOUS) self.vscroll.connect("value_changed",self.onScroll) self.vscroll.connect("scroll_event", self.onScrollMouse) self.build() #~ if initChoix!=None: #~ self.combo = gtk.combo_box_new_text() #~ for i in ListView.choix: #~ self.combo.append_text(i) #~ self.combo.connect('changed', self.on_combo_change) #~ self.combo.set_active(initChoix) #~ self.combo.unset_flags(gtk.CAN_FOCUS) #~ self.combo.show() #~ else: #~ self.combo = None self.tbl.show() #~ ascenceur = gtk.Table(1,2,False) #~ ascenceur.attach(self.btn_up,0,1,0,1,xoptions=gtk.FILL) #~ ascenceur.attach(self.btn_down,0,1,1,2,xoptions=gtk.FILL) #~ ascenceur.show() paned = gtk.Table(2,1) paned.attach(self.tbl,0,1,0,1,yoptions=gtk.FILL)#,xoptions=gtk.EXPAND) paned.attach(self.vscroll,1,2,0,1,xoptions=gtk.FILL) paned.show() #~ total = gtk.Table(1,2,False) #~ total.attach(paned,0,1,0,1) #~ if self.combo: #~ total.attach(self.combo,0,1,1,2,yoptions=gtk.FILL) #~ total.show() self.add(paned) #~ self.resize=False #~ ascenceur.resize=False #~ paned.resize=False self.connect("key_press_event", self.onKeyDown) self.connect("scroll_event", self.onScrollMouse) self.hid = self.connect_after("size_request", self.onSizeRequest) self.hid = self.connect_after("size_allocate", self.onSizeAllocate) #~ self.set_state(gtk.CAN_FOCUS) #~ tbl.set_state(gtk.CAN_FOCUS) self.width,self.height = 100,100 self.refresh() def changeSize(self,newSize): self.size=newSize self.init(self.list) def onSizeAllocate(self,e,alloc): self.width,self.height = alloc.width,alloc.height def onSizeRequest(self,a,req): req.width=560 # min width req.height=400 # min width return False def sort_list(self, rearrange_selection = True): # new if not self.list: return if rearrange_selection: nodes = [self.list[x] for x in self.__selected] if self.sort_mode == 0: # name self.list.sort(lambda x,y: cmp(x.name, y.name)) elif self.sort_mode == 1: # size self.list.sort(lambda x,y: cmp(x.filesize, y.filesize)) elif self.sort_mode == 2: # time self.list.sort(lambda x,y: cmp(x.date, y.date)) if self.reversed_sort: self.list.reverse() if rearrange_selection: self.__selected = [self.list.index(x) for x in nodes] def init(self, list): self.resizer(self.width,self.height) self.list = list self.__focus=0 self.sort_list(rearrange_selection = False) self.__selected=[0] self.__yoff = 0 if len(list)<=self.__nbx*self.__nby: self.vscroll.hide() else: self.vscroll.show() self.vscroll.set_range(0,(len(list)-(self.__nbx*(self.__nby -1))-1)/self.__nbx) self.vscroll.set_increments(1,self.__nby) self.refresh() def onScroll(self,a): self.__yoff=int(self.vscroll.get_value() * self.__nbx) self.refresh() def build(self): self.__items = [] for y in range(0,self.__nby): for x in range(0,self.__nbx): item = ListView.Item( self ) self.tbl.attach(item, x, x+1, y, y+1 ) #yoptions=gtk.FILL) item.show() self.__items.append(item) def resizer(self,w,h): self.__nbx = int(w/self.size) self.__nby = int(h/(self.size+ListView.Item.text_size)) self.rebuild() def rebuild(self): self.tbl.resize(self.__nby,self.__nbx) for i in self.__items: i.destroy() del(i) del(self.__items) self.build() self.refresh() #~ def on_combo_change(self,combo): #~ self.refresh() def onKeyDown(self, widget, event): keyname = gtk.gdk.keyval_name(event.keyval).lower() if keyname in ('page_up', 'page_down', 'down', 'up', 'right', 'left', 'home', 'end'): self.moveFocus(None, keyname) return True elif keyname == 'a' and event.get_state() & gtk.gdk.CONTROL_MASK: # ctrl-a self.__selected = range(len(self.list)) self.refresh() return True return False def onScrollMouse(self, a,b): #~ print int(b.direction) if int(b.direction)==1: if self.__yoff+len(self.__items)< len(self.list): self.__yoff+=self.__nbx else: self.__yoff-=self.__nbx if self.__yoff<0: self.__yoff=0 self.refresh() def onItemClickRelease(self,i,event): """ button_release_event""" self.mouseClick(i,event) def onItemClick(self,i,event): """ button_press_event""" if event.button == 1: if event.type == gtk.gdk.BUTTON_PRESS: if event.get_state() & gtk.gdk.CONTROL_MASK: if i in self.__selected: self.__selected.remove(i) else: self.__selected.append(i) elif event.get_state() & gtk.gdk.SHIFT_MASK: l = self.__focus for j in range(min(l,i),1+max(l,i)): if j not in self.__selected: self.__selected.append(j) else: self.__selected=[i] elif event.type == gtk.gdk._2BUTTON_PRESS: self.__selected=[i] self.__focus = i self.refresh() elif event.button ==2: self.__focus=i if i in self.__selected: self.__selected.remove(i) else: self.__selected.append(i) self.refresh() elif event.button ==3: if i not in self.__selected: self.__selected = [i] self.__focus = i self.refresh() self.setFocus() self.mouseClick(i,event) def refresh(self): self.vscroll.set_value(self.__yoff/self.__nbx) for item in self.__items: item.refresh() self.onRefresh(self.__focus,len(self.__selected)) def moveFocus(self, widget, data=None): if data == 'page_up': self.__focus -=self.__nbx*self.__nby elif data == 'page_down': self.__focus +=self.__nbx*self.__nby elif data == "home": self.__focus = 0 elif data == "end": self.__focus = len(self.list) -1 elif data == "right": self.__focus +=1 elif data == "left": self.__focus -=1 elif data == "down": self.__focus +=self.__nbx elif data == "up": self.__focus -=self.__nbx if self.__focus >= len(self.list): self.__focus = len(self.list)-1 if self.__focus < 0: self.__focus = 0 self.__selected = [self.__focus] idx = self.__focus nbc = self.__nbx * self.__nby #~ if idx>=(self.__yoff+nbc ) or idx<self.__yoff: #~ self.__yoff=(idx/nbc) * nbc if idx>=(self.__yoff+nbc ): self.__yoff+=self.__nbx * ( 1 + ((idx - (self.__yoff+nbc) ) / self.__nbx)) if idx<self.__yoff: self.__yoff-=self.__nbx * ( 1 + ((self.__yoff - idx - 1) / self.__nbx)) self.refresh() #self.setFocus() def remove(self,nitem): ret=self.list.remove(nitem) self.refresh() return ret def _whichItemAmI(self, idx): item = self.__yoff + self.__items.index(idx) if item in range(0,len(self.list)): return item def isFocused(self, item): return item == self.__focus def isSelected(self, item): return item in self.__selected def setFocus(self): self.tbl.grab_focus() def getSelected(self): return [ p for k,p in enumerate(self.list) if k in self.__selected ] def select(self,idx): self.__focus=idx self.moveFocus(self,"") def setAff(self,i): assert i in range(1,len(self.choix)+1) self.__choix = i - 1 self.refresh() def setSort(self, i): #new self.sort_mode = i self.sort_list() self.refresh() def setReversedSort(self, reversed): #new self.reversed_sort = reversed self.sort_list() self.refresh() def _getTitle(self,item): return self.getTitle(item,self.__choix) def _onDrop(self,item,*args): if item not in self.__selected: self.focus=item self.__selected=[item] self.refresh() return self.onDrop(item,*args) # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # to override !!!!!!!!!!!!!!!!!!!!!!!!!!!!! # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= def getTitle(self, item, choix): return "" def getImage(self, item): return None def onRefresh(self, focusedItem, nbSelected): return None # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= # to extend !!!!!!!!!!!!!!!!!!!!!!!!!!!!! # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= def mouseClick(self,item,button,x,y): return False def onDrop(self,item,*args): return False #~ gobject.type_register(ListView) class Selecteur(ListView): def getTitle(self, item): return self.list[item] def getImage(self, item): return None def mouseClick(self,i,event): if int(event.button)==3: entries =[ (gtk.STOCK_ADD, self.on_add_clicked,1), (gtk.STOCK_REMOVE, self.on_delete_clicked,1), ("Edit", self.on_edit_clicked,1), ] menu = gtk.Menu() for stock_id,callback,sensitivity in entries: item = gtk.ImageMenuItem(stock_id) if callback: item.connect("activate",callback) item.set_sensitive(sensitivity) item.show() menu.append(item) menu.popup(None,None,None,event.button,0) def on_add_clicked(self,b):pass def on_delete_clicked(self,b):pass def on_edit_clicked(self,b):pass class Table: # This callback quits the program def delete_event(self, widget, event, data=None): gtk.main_quit() return False def __init__(self): # Create a new window self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) # Set the window title self.window.set_title("Table") # Set a handler for delete_event that immediately # exits GTK. self.window.connect("delete_event", self.delete_event) # Sets the border width of the window. self.window.set_border_width(5) table = Selecteur( [ "item %d"%i for i in range(57)] ) self.window.add(table) table.show() self.window.show() def main(): gtk.main() return 0 if __name__ == "__main__": Table() main()
Note: See TracBrowser for help on using the browser.
