Am Dienstag, den 25.05.2010, 12:21 +0200 schrieb Jaap Karssenberg: > I'm really interested in the plugin to preview / browse attachments. > This is something I wanted to create myself, but didn't find time for > yet. Might even want this as core functionality instead of as a > plugin.
Sorry for the even later reply. Here is a very basic version of the plugin. Still a lot to do, but works for me. I use it to browse collections of pdf files (technical documentation, data sheets, etc). For more flexibility I suggest changing the zim layout to something like this: +-----------------------------+ |menu | +-----+----------------+------+ | | top pane | | | | | | | s +----------------+ s | | i | wiki editor | i | | d | | d | | e | | e | | b +----------------+ b | | a |tabs| | a | | r | bottom pane | r | | | | | +----------------------+------+
# -*- coding: utf-8 -*- # # Copyright 2010 Thorsten Hackbarth <thorsten.hackba...@gmx.de> # License: same as zim (gpl) # # 2010-06-29 # # TODO: # * integer plugin_preferences do not to work as expected (zim bug?) # * toggle: hide/show => disconect/update # * toggle: toolbar button state wrong # * toggle-btn icon # * where to store thumbnails? # in current dir: .thumb_<filename>.jpg (hide on windows?) # ~/.thumbnails/ (gnome/nautilus) # .zim/cache/ # Thumbs.db # let the user decide # * thumbnail all images? # * dont start all thumbnailing processes at a time, and make them nice 10 # * small and lagre thumbs # * textrendering: syntay-hl # * use mimtype not extension # * rethumb: thmub-size==0 or broken (e.g. shutdown while thumbnailing) # * option to remove all thumbnails # * update view when thumb-cration finished # * code cleanup # * new gui concept for zim : sidepane r/l,bottom- and top pane both with tabs (see gedit) # * show file infos in tooltip (which?) # * update icon when thumbnail is ready # * mimi-type specific icons # * evaluate imagemagick python libs # # # tooltip example # http://nullege.com/codes/show/s...@pygtk-2.14.1@examp...@pygtk-demo@de...@tooltip.py/160/gtk.gdk.Color # file info example # http://ubuntuforums.org/showthread.php?t=880967 # '''Zim plugin to display files in atachments folder.''' import gobject import gtk import pango import os import stat import time import re import logging from datetime import date as dateclass from zim.plugins import PluginClass from zim.gui import Dialog from zim.gui.widgets import Button from zim.notebook import Path from zim.stores import encode_filename from zim.fs import * from zim.errors import Error logger = logging.getLogger('zim.plugins.fileview') from zim.applications import Application from zim.gui.applications import OpenWithMenu ui_toggle_actions = ( # name, stock id, label, accelerator, tooltip, readonly ('toggle_fileview', gtk.STOCK_MISSING_IMAGE, _('Fileview'), '', 'Show Fileview',False, True), # T: menu item ) #Menubar and toolbar ui_xml = ''' <ui> <menubar name='menubar'> <menu action='view_menu'> <placeholder name="plugin_items"> <menuitem action="toggle_fileview" /> </placeholder> </menu> </menubar> <toolbar name='toolbar'> <placeholder name='tools'> <toolitem action='toggle_fileview'/> </placeholder> </toolbar> </ui> ''' ICON_SIZE_MIN=16 ICON_SIZE_MAX=256 THUMB_SIZE_MIN=16 THUMB_SIZE_MAX=1024 # TODO: chaneg size pdftopng_cmd = ('convert','-size', '480x480', '-trim','+repage','-resize','480x480>','-quality','50') #pdftopng_cmd = ('convert','-trim') #txttopng_cmd = ('dvipng', '-q', '-bg', 'Transparent', '-T', 'tight', '-o') #txttopng_cmd = ('convert', '-size', '480x480' 'caption:') pdftojpg_cmd = ('convert','-size', '480x480', '-trim','+repage','-resize','480x480>','-quality','50') class FileviewPlugin(PluginClass): plugin_info = { 'name': _('Fileview'), # T: plugin name 'description': _('''\ This shows the storage directory of the current page as icon view at bottom pane. ImageMagick dependencies: html-preview: html2ps '''), # T: plugin description 'author': 'Thorsten Hackbarth <thorsten.hackba...@gmx.de>', 'help': 'Plugins:Fileview', } plugin_preferences = ( # key, type, label, default ('icon_size', 'int', _('Icon size [px]'), [ICON_SIZE_MIN,128,ICON_SIZE_MAX]), # T: preferences option ('preview_size', 'int', _('Tooltip preview size [px]'), (THUMB_SIZE_MIN,480,THUMB_SIZE_MAX)), # T: input label ('thumb_quality', 'int', _('Preview jpeg Quality [0..100]'), (0,50,100)), # T: input label ) @classmethod def check_dependencies(klass): return [("ImageMagick",Application(pdftojpg_cmd).tryexec())] def __init__(self, ui): PluginClass.__init__(self, ui) self.bottompane_widget = None self.scrollpane = None if self.ui.ui_type == 'gtk': self.ui.add_toggle_actions(ui_toggle_actions, self) #self.ui.add_actions(ui_actions, self) self.ui.add_ui(ui_xml, self) self.ui.connect_after('open-notebook', self.do_open_notebook) def do_open_notebook(self, ui, notebook): self.do_preferences_changed() #notebook.register_hook('suggest_link', self.suggest_link) def disconnect(self): PluginClass.disconnect(self) def add_to_mainwindow(self): bottompane = self.ui.mainwindow.pageview.get_parent() if self.bottompane_widget is None: self.bottompane_widget = FileviewPluginWidget(self) self.scrollpane=gtk.ScrolledWindow() self.scrollpane.set_size_request(-1,160) self.scrollpane.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrollpane.add_with_viewport(self.bottompane_widget) bottompane.pack_end(self.scrollpane, False) #bottompane.pack_end(self.bottompane_widget, False) #bottompane.reorder_child(self.bottompane_widget, 0) self.handlerID_do_open_notebook=self.ui.connect_after('open-notebook', self.do_open_notebook) #self.bottompane_widget.show_all() self.scrollpane.show_all() def remove_from_mainwindow(self): if self.bottompane_widget is not None: #doesnt work:? self.ui.disconnect(self.handlerID_do_open_notebook) self.scrollpane.hide_all() def do_preferences_changed(self): print self.preferences['icon_size'] # bug? # # self.preferences['icon_size'] is integer after changeing it # but must be (min,val,max) for the dialog, which is strange self.add_to_mainwindow() def toggle_fileview(self, enable=None): action = self.actiongroup.get_action('toggle_fileview') if enable is None or enable != action.get_active(): action.activate() else: self.do_toggle_fileview(enable=enable) def do_toggle_fileview(self, enable=None): #~ print 'do_toggle_fileview', enable if enable is None: action = self.actiongroup.get_action('toggle_fileview') enable = action.get_active() if enable: # print "enabled" self.add_to_mainwindow() else: # print "disabled" self.remove_from_mainwindow() self.uistate['active'] = enable return False # we can be called from idle event class Fileview(gtk.IconView): '''Custom fileview widget class. Adds an 'activate' signal for what i dont know yet''' # define signals we want to use - (closure type, return type and arg types) __gsignals__ = { 'activate': (gobject.SIGNAL_RUN_LAST, None, ()), } # Need to register classes defining gobject signals gobject.type_register(Fileview) class FileviewPluginWidget(gtk.HBox): __gsignals__ = { 'modified-changed': (gobject.SIGNAL_RUN_LAST, None, ()), } def __init__(self, plugin): gtk.HBox.__init__(self) self.plugin = plugin self.fileview = Fileview() self.store = None self.store=gtk.ListStore(str, gtk.gdk.Pixbuf,str) #gtk.TextBuffer() #self.fileview.set_buffer(self.textbuffer) self.fileview.set_model(self.store) self.fileview.set_text_column(0) self.fileview.set_pixbuf_column(1) self.pack_start(self.fileview, True) self.plugin.ui.connect('open-page', self.on_open_page) self.fileview.connect_object('button-press-event',FileviewPluginWidget.on_button_press_event, self) #self.fileview.set_tooltip_column(2) # filename as tooltip self.fileview.props.has_tooltip = True # custom tooltip self.fileview.connect("query-tooltip", self.query_tooltip_icon_view_cb) def on_button_press_event(self,event): # print 'on_button_press_event' if event.button == 3: popup_menu=gtk.Menu() x = int(event.x) y = int(event.y) time = event.time #iteminfo = self.fileview.get_item_at_pos(x, y) pathinfo = self.fileview.get_path_at_pos(x, y) if pathinfo is not None: self.fileview.grab_focus() print self.store.get_value(self.store.get_iter(pathinfo),2) popup_menu.popup(None, None, None, event.button, time) self.do_populate_popup(popup_menu,pathinfo) return True return False def thumbnailfile(self,path,filename): return path+'/.thumb_'+filename+'.jpg' def do_populate_popup(self, menu,pathinfo): # print "do_populate_popup" file= File(self.store.get_value(self.store.get_iter(pathinfo),2)+os.sep+self.store.get_value(self.store.get_iter(pathinfo),0)) # open with & open folder item = gtk.MenuItem(_('Open Folder')) # T: menu item to open containing folder of files menu.prepend(item) dir = file.dir if dir.exists(): item.connect('activate', lambda o: self.plugin.ui.open_file(dir)) else: item.set_sensitive(False) item = gtk.MenuItem(_('Open With...')) menu.prepend(item) submenu = OpenWithMenu(file) item.set_submenu(submenu) menu.show_all() def query_tooltip_icon_view_cb(self, widget, x, y, keyboard_tip, tooltip): if not widget.get_tooltip_context(x, y, keyboard_tip): return False else: model, path, iter = widget.get_tooltip_context(x, y, keyboard_tip) value = model.get(iter, 0) tooltip.set_markup("<b>Filename: </b> %s \n <b>Size: </b> %s \n <b>Date: </b> %s" %(value[0],'(UNKNOWN)','(UNKNOWN)')) filename=model.get(iter, 0)[0] filepath=model.get(iter, 2)[0] filenameabs=filepath+os.sep+filename #thumbfilenameabs=model.get(iter, 3)[0] if isinstance(self.plugin.preferences['preview_size'], int): w=self.plugin.preferences['preview_size'] h=self.plugin.preferences['preview_size'] else: w=480 h=480 # TODO: textfiles: use text not thumb for preview try: pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filenameabs,w,h) tooltip.set_icon(pixbuf) except: try: thumbfilenameabs=self.thumbnailfile(filepath,filename) pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(thumbfilenameabs,w,h) tooltip.set_icon(pixbuf) except: logger.debug('No such thumbnail:%s ',filenameabs) tooltip.set_icon_from_stock(gtk.STOCK_MISSING_IMAGE, gtk.ICON_SIZE_DIALOG) widget.set_tooltip_item(tooltip, path) return True def file_to_image(self,filenameabs,thumbfilenameabs): logger.debug('file_to_image()'); extension=filenameabs.split(".")[-1].upper() print extension magickextensions=('SVG','PDF','PS','EPS','DVI','DJVU','RAW','DOT','HTML','HTM','TTF','XCF') textextensions=('SH','BAT','TXT','C','C++','CPP','H','H++','HPP','PY','PL') #'AVI','MPG','M2V','M4V','MPEG' if extension in magickextensions: # pdf to thumbnail try: #touch the thumbnail first open(thumbfilenameabs, "a") #filenameabs=path+os.sep+filename logger.debug(' trying Imagemagick') filenameabs_p1=filenameabs +'[0]' pdftopng = Application(pdftopng_cmd) pdftopng.spawn((filenameabs_p1, thumbfilenameabs)) except: logger.debug(' Error converting PDF') elif extension in textextensions: #convert -size 400x caption:@- caption_manual.gif try: #touch the thumbnail first open(thumbfilenameabs, "a") textcont='caption:' file = open(filenameabs) linecount=0; # lines: 18 at 128px # linewidth 35 at 128px while linecount<18: line = file.readline() if not line: break linecount+=1 textcont+=line[0:35] logger.debug(' trying TXT') txttopng_cmd = ('convert','-family','System','-size', '200x320', '-frame', '4' ,'-quality','40') txttopng = Application(txttopng_cmd) txttopng.spawn((textcont,thumbfilenameabs)) except: logger.warn(' Error converting TXT') def set_current_folder(self,path): self.store.clear() if isinstance(self.plugin.preferences['icon_size'],int): w = self.plugin.preferences['icon_size'] h = self.plugin.preferences['icon_size'] else: w=128 h=128 filelist = os.listdir(path) for filename in filelist: pixbuf=None # self.textbuffer.insert_at_cursor(filename+'\n') filenameabs=path+os.sep+filename thumbfilenameabs=filenameabs if os.path.isfile(filenameabs) and filename[0]!='.': #.encode('utf-8')): try: pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(filenameabs,w,h) #pixbuf = rotate_pixbuf(pixbuf) except: logger.debug('No such image: %s', filenameabs) thumbfilenameabs=self.thumbnailfile(path,filename) # ToDo: check for existance # ToDo: check age try: print "thumb check:" +thumbfilenameabs #print os.stat(thumbfilenameabs)[st_mtime] if (not os.path.isfile(thumbfilenameabs)) or (os.stat(thumbfilenameabs).st_mtime < os.stat(filenameabs).st_mtime): #print 'thumbnail does not exist or too old' self.file_to_image(filenameabs,thumbfilenameabs) #else: #print 'thumbnail up to date' pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(thumbfilenameabs,w,h) except: logger.debug('No such thumbnail:%s %s',thumbfilenameabs, filenameabs) widget = gtk.HBox() # Need *some* widget here... pixbuf = widget.render_icon(gtk.STOCK_MISSING_IMAGE,gtk.ICON_SIZE_DIALOG) if pixbuf: self.store.append( [filename,pixbuf,path] ) def on_open_page(self, ui, page, path): try: #print path #print encode_filename(page.name) self.set_current_folder(str(self.plugin.ui.notebook.get_attachments_dir(page)+os.sep)) except AssertionError: pass
_______________________________________________ Mailing list: https://launchpad.net/~zim-wiki Post to : zim-wiki@lists.launchpad.net Unsubscribe : https://launchpad.net/~zim-wiki More help : https://help.launchpad.net/ListHelp