#!/usr/bin/env python # demo displaying directories only in tree widget # convert Internet Explorer Favorites shortcuts into a Netscape Bookmarks file import os import sys import string import tree import Tkdnd from Tkinter import * from tkFileDialog import * # favorites path on NT 4.0 favsroot='c:\\winnt\\profiles\\administrator\\favorites' bmpath='E:\\.netscape\\bookmarks.html' class Bookmarks: def __init__(self, filetype, path, win): # the tree's data structure self.favs={} # list of URLs and the folder they're in self.urls={} self.filetype=filetype self.path=path #try: if self.filetype == 1: self.read_IE(path) self.name='IE Favorites' elif self.filetype == 2: self.read_NS(path) self.name='Netscape Bookmarks' #except: #win.destroy() #return # create tree control win.title(self.name) self.tree=tree.Tree(win, ('',), getcontents=self.getfiles, init=self.dnd_node, rootlabel=self.name, width=400, height=300) self.tree.grid(row=0, column=0, sticky=N+E+W+S) self.tree.expand((self.name,)) # make resizeable win.grid_rowconfigure(0, weight=1) win.grid_columnconfigure(0, weight=1) # attach vertical scrollbar sb=Scrollbar(win) sb.grid(row=0, column=1, sticky=N+S) self.tree.configure(yscrollcommand=sb.set) sb.configure(command=self.tree.yview) # attach horizontal scrollbar sb=Scrollbar(win, orient=HORIZONTAL) sb.grid(row=1, column=0, sticky=E+W) self.tree.configure(xscrollcommand=sb.set) sb.configure(command=self.tree.xview) # configure tree widget for drag'n'drop self.tree.dnd_accept=self.dnd_accept # set up node for drag'n'drop def dnd_node(self, node): node.widget.tag_bind(node.label, '<1>', lambda ev, qs=self, qn=node:qs.click(ev, qn)) node.widget.tag_bind(node.symbol, '<1>', lambda ev, qs=self, qn=node:qs.click(ev, qn)) # these events help identify target node node.widget.tag_bind(node.symbol, '', lambda ev, qs=self, qn=node:qs.enter(qn)) node.widget.tag_bind(node.label, '', lambda ev, qs=self, qn=node:qs.enter(qn)) node.widget.tag_bind(node.symbol, '', self.leave) node.widget.tag_bind(node.label, '', self.leave) # remember node we just entered, and save it as target # it seems that canvas item events are suppressed during the time # the button is held down, except for the item that the drag started # on. this has the effect of not letting us highlight or otherwise # indicate current drop target. # we get lucky and get one of these events when the button is released # just after the dnd_commit() & dnd_dropped() get called def enter(self, node): if node and self.source and not self.drag: self.target = node # drag is completed here print "- drag completed\n source '%s'\n target '%s'\n" % (self.source.name, self.target.name) self.source = None # we're not over a valid target def leave(self, event): self.target=None source = None drag = None # start drag'n'drop def click(self, event, node): node.widget.move_cursor(node) # first part of Node.click() self.source = node self.dragimage = node.closed_icon print "> starting drag from '%s'" % node.name self.proto_drag = Tkdnd.dnd_start(self, event) # end drag'n'drop def dnd_end(self, target, event): if target: if self.selrect == (0,0,0,0): self.source = None # not over an item target = None print '< dnd_end - target is', target else: if not self.drag: print '< dnd_end - not a real drag' if self.source: self.source.toggle_state() # remainder of Node.click() else: print '< dnd_end - finished outside source' self.source = None self.drag = None def dnd_accept(self, source, event): return self def dnd_commit(self, source, event): print ' dnd_commit - source is', source self.dnd_leave(None, None) # create drag icon def dnd_enter(self, source, event): # attempt to get around problems in IDLE - not really working # if you uncomment this code, make sure to figure out another way # of determining if the drag was real vs. finishing out of the canvas # if self.drag: # print ' (spurious dnd_enter)' # return self.drag = self.proto_drag print ' dnd_enter - source is', source x, y=self.tree.winfo_pointerxy() x=self.tree.canvasx(x)-self.tree.winfo_rootx() y=self.tree.canvasy(y)-self.tree.winfo_rooty() self.dnd_focus = self.tree.create_rectangle( 0, 0, 0, 0, outline=self.tree.cget('insertbackground'), width=self.tree.cget('insertwidth')) self.dnd_symbol=self.tree.create_image(x, y, image=self.dragimage) self.target = None # destroy drag icon def dnd_leave(self, source, event): if event: print ' dnd_leave - source is', source self.tree.delete(self.dnd_symbol) self.tree.delete(self.dnd_focus) self.sel = [] # attempt to get around problems in IDLE with spurious dnd_enters # self.drag = None sel = [] selbounds = (0,0,0,0) selrect = (0,0,0,0) def _iteminfo(self, id): type = self.tree.type(id) s = '%s id %s bbox %s' % (type, id, self.tree.bbox(id)) if type == 'text': s = "%s\n\t\t'%s'" % (s, self.tree.itemcget(id, 'text')) return s # move drag icon def dnd_motion(self, source, event): x, y=self.tree.winfo_pointerxy() x=self.tree.canvasx(x)-self.tree.winfo_rootx() y=self.tree.canvasy(y)-self.tree.winfo_rooty() self.tree.coords(self.dnd_symbol, x, y) sel = list(self.tree.find_overlapping(0, y, self.tree.cget('width'), y)) try: sel.remove(self.dnd_symbol) except: pass # ok if not there sel = filter(lambda id, type=self.tree.type: type(id) in ('image', 'text'), sel) if sel != self.sel: bbox = map(self.tree.bbox, sel) if bbox: self.selbounds = \ (min(map(lambda box: box[0], bbox)) - 1, min(map(lambda box: box[1], bbox)) - 1, max(map(lambda box: box[2], bbox)) + 1, max(map(lambda box: box[3], bbox)) + 1) else: self.selbounds = (0,0,0,0) self.sel = sel if x > self.selbounds[2] or x < self.selbounds[0]: # pointer outside selrect = (0,0,0,0) else: selrect = self.selbounds if selrect != self.selrect: # need to draw apply(self.tree.coords, (self.dnd_focus,) + selrect) self.selrect = selrect # read IE favorites into data structure def read_IE(self, path): f=os.listdir(path) f.sort() b=[] key=tuple(string.split(path[len(self.path):], os.sep)) self.favs[key]={'contents':[], 'children':[]} for i in f: fn=os.path.join(path, i) if os.path.isfile(fn): if i[-4:] == '.url': # save for later url=open(fn).readlines()[1][4:-1] name=i[:-4] self.favs[key]['contents'].append((url, name)) self.urls[url]=key else: # descend directories first self.favs[key]['children'].append(i) self.read_IE(fn) # read Netscape HTML formatted bookmarks file into data structure def read_NS(self, path): html=map(string.strip, open(path).readlines()) key=['', ] self.favs[tuple(key)]={'contents':[], 'children':[]} for line in html: upr=string.upper(line) if upr == '

': # end of subsection key=key[:-1] if upr[:7] == '

Favorites

x1=string.find(line, '">')+2 x2=string.find(line, '') name=line[x1:x2] self.favs[tuple(key)]['children'].append(name) key.append(name) self.favs[tuple(key)]={'contents':[], 'children':[]} if upr[:12] == '
', 5)+1 x2=string.find(line, '') name=line[x1:x2] self.favs[tuple(key)]['contents'].append((url, name)) self.urls[url]=tuple(key) def getfiles(self, node): dirs=[] for i in self.favs[node.id]['children']: dirs.append((i, node.id+(i,), tree.shut_icon, tree.open_icon)) for i in self.favs[node.id]['contents']: icon=tree.file_icon for j in forest: if j != self: if not j.urls.has_key(i[0]): # color red if missing from another window icon=red_icon break if j.urls[i[0]] != node.id: # green if in different place icon=green_icon dirs.append((i[1], '', icon, None)) return dirs def open_favs(): # try to guess favorites path based on OS if sys.platform[:5] == 'linux': # very system specific path='/win95/windows/Favorites' if sys.platform == 'win32': # hope they didn't rename their windows directory path='c:\\windows\\Favorites' try: if os.environ['OS'] == 'Windows_NT': # NT makes it easy path=os.environ['USERPROFILE']+os.sep+'Favorites' except: pass forest.append(Bookmarks(1, path, Toplevel(root))) def open_nsbm(): if os.name == 'posix': # pretty standard, I hope path='%s/.netscape/bookmarks.html' % os.environ['HOME'] if sys.platform == 'win32': path='c:\\program files\\netscape\\users\\gcash\\bookmark.htm' #path=askopenfilename(title='Netscape Bookmark File', # filetypes=[('HTML Files', '.htm .html'), # ('All Files', '*')], # initialfile='bookmark.htm', # initialdir=path) forest.append(Bookmarks(2, path, Toplevel(root))) forest=[] root=Tk() root.title('Bookmark Editor') Button(root, text='Open IE Favorites', command=open_favs).pack() Button(root, text='Open Netscape Bookmarks', command=open_nsbm).pack() Button(root, text='Exit', command=root.quit).pack() # green_icon=PhotoImage(file='icons/prev.gif') # red_icon=PhotoImage(file='icons/next.gif') root.mainloop()