root/trunk/winshow.py
| Revision 196 (by manatlan, 12/12/07 10:58:34) |
|---|
# -*- 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. ## import gtk,gc,pango,gobject,os from __main__ import Buffer,GladeApp,JBrout from commongtk import WinKeyTag #TODO: add ops : add/del from basket #TODO: add ops : rotate #TODO: add ops : delete photo #TODO: add ops : external tools class WinShow(GladeApp): glade=os.path.join(os.path.dirname(__file__), 'jbrout.glade') window="WinShow" def init(self,storeTags, ln,idx,showInfo=True,isModify=False): self.ln=[]+ln self.idx=idx self.selected=[] # to be able to handle a new selection (reselect with space) self.removed=[] self.isBasketUpdate=False self.needInfo=showInfo self.isModify=isModify PixbufCache._file=None PixbufCache._cache=None #/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ ################### def filename(column, cell, model, iter): cell.set_property('text', model.get_value(iter, 0)) cell.set_property('foreground', model.get_value(iter, 2)) cell.set_property('xalign', 0) #~ cell.set_property('xpad', 1) def pixbuf(column, cell, model, iter): node=model.get_value(iter,1) if node.__class__.__name__ == "TagNode": if model.get_value(iter, 3)==0: cell.set_property('pixbuf', Buffer.pbCheckEmpty) elif model.get_value(iter, 3)==1: cell.set_property('pixbuf', Buffer.pbCheckInclude) elif model.get_value(iter, 3)==2: cell.set_property('pixbuf', Buffer.pbCheckExclude) else: cell.set_property('pixbuf', Buffer.pbCheckDisabled) else: cell.set_property('pixbuf', None) cell.set_property('width', 16) cell.set_property('xalign', 0) cellpb = gtk.CellRendererPixbuf() cell = gtk.CellRendererText() column = gtk.TreeViewColumn() column.pack_start(cellpb, False) column.pack_start(cell, True) column.set_cell_data_func(cellpb, pixbuf) column.set_cell_data_func(cell, filename) ################### self.tv_tags.append_column(column) treeselection = self.tv_tags.get_selection() treeselection.set_mode(gtk.SELECTION_NONE) self.tv_tags.set_model( storeTags ) self.tv_tags.set_enable_search(False) self.tv_tags.set_state(gtk.CAN_FOCUS) storeTags.expander(self.tv_tags) storeTags.cleanSelections() #/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ self.viewer = ImageShow() self.hpShow.add2(self.viewer) image=gtk.Image() image.set_from_pixbuf(Buffer.pbBasket) image.show() self.basket.set_icon_widget(image) self.toolbar.set_style(gtk.TOOLBAR_ICONS) self.main_widget.show_all() self.main_widget.fullscreen() self.draw() def on_eb_scroll_event(self,widget,b): if int(b.direction)==1: self.idx+=1 else: self.idx-=1 self.draw() def on_WinShow_key_press_event(self, widget, b): key= gtk.gdk.keyval_name(b.keyval).lower() if (key == "page_up") or (key == "up") or (key == "left"): self.idx-=1 self.draw() if (key == "page_down") or (key == "down") or (key == "right"): self.idx+=1 self.draw() elif key=="home": self.idx=0 self.draw() elif key=="end": self.idx=len(self.ln) -1 self.draw() elif key=="escape": self.quit(); elif key=="space": # add/remove this photo to selection node=self.ln[self.idx] if node in self.selected: self.selected.remove(node) else: self.selected.append(node) self.draw() #~ elif b.keyval == 65451: # + #~ self.zoom=min(self.zoom+1,10) #~ self.show() #~ elif b.keyval == 65453: # - #~ self.zoom=max(self.zoom-1,1) #~ self.show() elif key=="backspace": # clear selection self.selected=[] self.draw() elif key=="delete": # delete self.on_delete_clicked(None) # and call draw elif key=="insert": self.needInfo = not self.needInfo self.draw() else: currentNode = self.ln[self.idx] if self.isModify and not currentNode.isReadOnly: if b.keyval<255 and b.string.strip()!="": wk=WinKeyTag(_("Apply to this photo"),b.string,JBrout.tags.getAllTags()) ret=wk.loop() self.main_widget.fullscreen() if ret: tag = ret[0] currentNode.addTag(tag) self.draw() return 0 def draw(self): if self.idx >= len(self.ln): self.idx = len(self.ln)-1 if self.idx < 0: self.idx = 0 try: node = self.ln[self.idx] except IndexError: self.quit() return try: info = node.getInfo() ltags=info["tags"] folder=node.folderName resolution=info["resolution"] tags=", ".join(ltags) comment=info["comment"] exifdate=cd2rd(info["exifdate"]) # filedate=cd2rd(info["filedate"]) filesize=format_file_size_for_display(info["filesize"]) msg = _(""" %(exifdate)s %(resolution)s, %(filesize)s %(folder)s TAGS : %(tags)s COMMENT : %(comment)s """) % locals() except Exception,m: msg = "" ltags=[] print m if self.isModify and not node.isReadOnly: self.delete.show() else: self.delete.hide() model=self.tv_tags.get_model() model.setSelected(ltags) d=Display() d.node = None self.viewer.display=d # prevent toggle event self.basket.set_active(node.isInBasket) if self.needInfo: self.vb_info.show() else: self.vb_info.hide() d=Display() d.node = node d.image = PixbufCache().get(node.file) d.title = "%d/%d"%(self.idx+1,len(self.ln)) try: self.lbl_info.set_text(msg) except Exception,m: self.lbl_info.set_text("") print "*ERROR* bad characters in jpeg info : ",m d.isSelected = (node in self.selected) d.nbSelected = len(self.selected) self.viewer.show( d ) gc.collect() def on_WinShow_delete_event(self,*args): self.quit() def on_WinShow_button_press_event(self,*args): self.quit() def on_tv_tags_button_press_event(self, widget, *args): event=args[0] tup= widget.get_path_at_pos( int(event.x), int(event.y) ) if self.isModify: if tup: path,obj,x,y = tup if path: model = widget.get_model() iterTo = model.get_iter(path) node = model.get(iterTo) # let's find the x beginning of the cell xcell = widget.get_cell_area(path, widget.get_column(0) ).x if node.__class__.__name__ == "TagNode": if x>xcell: # click on the cell (not on the arrow) if event.button==1: currentNode = self.viewer.display.node if currentNode: # TODO : test if readonly # TODO : test jbrout.modify cv = model.get_value(iterTo,3) # TODO : really bad way ! should be better done if cv == 1: currentNode.delTag(node.name) else: # add tag currentNode.addTag(node.name) self.draw() return 1 # stop the propagation of the event return 0 # let the event propagation def on_tv_tags_row_activated(self, widget, *args): treeselection = widget.get_selection() model, iter0 = treeselection.get_selected() if iter0: model.switch(iter0) def on_delete_clicked(self,*args): if self.isModify: node = self.ln[self.idx] #currentNode = self.viewer.display.node self.ln.remove(node) self.removed.append(node) self.draw() def on_basket_toggled(self,widget): currentNode = self.viewer.display.node if currentNode: if widget.get_active(): currentNode.addToBasket() else: currentNode.removeFromBasket() self.isBasketUpdate=True class ImageShow(gtk.DrawingArea): def __init__(self): super(gtk.DrawingArea, self).__init__() self.connect("expose_event", self.expose) self.display = None def expose(self, widget, event): context = widget.window.cairo_create() # set a clip region for the expose event context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) context.clip() self.draw(context) return False def draw(self, context): fond=(0,0,0,0.4) rect = self.get_allocation() context.set_source_rgb(0,0,0) context.paint() if self.display: if self.display.image: context.save() pb,x,y=render(self.display.image,rect.width,rect.height) context.set_source_pixbuf(pb,x,y) context.paint() context.restore() if self.display.title: context.set_source_rgba(*fond) context.rectangle(0,0,200,30) context.fill() title = self.display.title if self.display.isSelected: context.set_source_rgb(1,1,0) title+="*" else: context.set_source_rgb(1,1,1) context.move_to(20,20) context.set_font_size(20) context.show_text(title) if self.display.nbSelected>0: context.set_source_rgb(1,1,0) context.rel_move_to(5,0) context.set_font_size(12) context.show_text(_("(%d selected)") % self.display.nbSelected) #if self.display.info: # wx=200 # wy=400 # context.set_source_rgba(*fond) # context.rectangle(rect.width-wx,rect.height-wy,wx,wy) # context.fill() # # context.move_to(rect.width-wx+5,rect.height-wy+5) # context.set_source_rgb(1,1,1) # # layout=context.create_layout () # layout.set_text(self.display.info) # layout.set_font_description(pango.FontDescription ("courier 8")) # layout.set_width((wx-5)*1000) # layout.set_wrap(1) # context.show_layout(layout) def show(self,d): # store instance display self.display = d # and trig expose event to redraw all rect = self.get_allocation() self.queue_draw_area(0,0,rect.width,rect.height) def cd2rd(f): #yyyymmddhhiiss -> dd/mm/yyyy hh:ii:ss if f: if len(f) == 14: return f[6:8]+"/"+f[4:6]+"/"+f[:4]+" "+f[8:10]+":"+f[10:12]+":"+f[12:14] else: return f[6:8]+"/"+f[4:6]+"/"+f[:4] else: return f def format_file_size_for_display(file_size): KILOBYTE_FACTOR = 1024.0 MEGABYTE_FACTOR = 1024.0 ** 2 GIGABYTE_FACTOR = 1024.0 ** 3 if file_size < KILOBYTE_FACTOR: return _('%u bytes') % file_size if file_size < MEGABYTE_FACTOR: return _('%.1f KB') % (file_size/KILOBYTE_FACTOR) if file_size < GIGABYTE_FACTOR: return _('%.1f MB') % (file_size/MEGABYTE_FACTOR) return _('%.1f GB') % (file_size/GIGABYTE_FACTOR) def fit(orig_width, orig_height, dest_width, dest_height,zoom): if orig_width == 0 or orig_height == 0: return 0, 0 scale = min(dest_width/orig_width, dest_height/orig_height) if scale > 1: scale = 1 scale*=zoom fit_width = scale * orig_width fit_height = scale * orig_height return int(fit_width), int(fit_height) def render(pb,maxw,maxh): """ resize pixbuf 'pb' to fit in box maxw*maxh return the new pixbuf and x,y to center it """ (wx,wy) = pb.get_width(),pb.get_height() dwx,dwy = fit(wx,wy,float(maxw),float(maxh),1) pb = pb.scale_simple(dwx,dwy,gtk.gdk.INTERP_NEAREST) x,y=(maxw/2)-(dwx/2),(maxh/2)-(dwy/2) return pb,x,y class Display(object): """ container class to pass params """ pass node=None class PixbufCache(object): """ class to cache pixbuf by filename""" _cache=None _file=None def get(self,file): if file != PixbufCache._file: PixbufCache._file = file if os.path.isfile(file): PixbufCache._cache=gtk.gdk.pixbuf_new_from_file(file) else: PixbufCache._cache=None return PixbufCache._cache if __name__ == "__main__": # self test pass
Note: See TracBrowser for help on using the browser.
