Nightly update. There's some cleanup on the bottom pane.
On 9/18/06, Edward Duffy <[EMAIL PROTECTED]> wrote:
On 9/18/06, Jamie McCracken <[EMAIL PROTECTED]> wrote:
> Edward Duffy wrote:
> > Just another quick addition...does this interface for adding tags make
> > sense? I kinda like it, but I can see it being confusing at first....
> >
> > On 9/17/06, Edward Duffy <[EMAIL PROTECTED]> wrote:
> >> Here's an update where I've started some work on the bottom pane.
> >> It's still going to need some serious love, but some of the idea's in
> >> Jamie's Sep 14 email are starting to be incorporated.
> >>
>
> hey that rocks :)
>
> love the tags + button too
>
Thanks. Now it just needs a recent pop-under that shows available tags
(like Epiphany)
> There are a few minor things
>
> There should be 3 columns as follows:
>
I was thinking about having this dynamic based on the size of the
window and the size of the columns, but this sounds much cleaner (and
easier!).
> 1) as now + include all basic matadata here like tags, rank, file size
> etc (I dont think we need to display permissions). The column should
> wrap so that tags dont infringe on other cols
I gave the entire bottom row to tags because I wasn't sure how many
tags most people associate with a file. I don't think I've used
anymore than 2, but I thought it might look funny if it wrapped...even
more so now with a text entry and two buttons (when you're adding a
tag).
>
> 2) The middle column should be for service specific metadata (like Music
> stuff for music files). For plain files this column should be invisible
>
easy
> 3) The last column should show a few lines of the so text contents in a
> scrollable fashion. If no contents then this column will be invsible
>
Sure..there's a method to do this already, I beleive.
> also we should have a button to view/edit all metadata for a file in a grid
that shouldn't be too bad..there's enough introspection information in
there that should make this pretty straight forward. Is there any
error checking on tracker's end? ie, does it make sure that File.Rank
is an integer from 1 to 10?
>
> Going to be fun converting that to C.
yeah, i feel sorry for that poor bastard. ;)
>
>
>
> --
> Mr Jamie McCracken
> http://jamiemcc.livejournal.com/
>
#!/usr/bin/env python
import os
import os.path
import sys
import gtk
import pango
import gconf
import dbus
import md5
import urllib
from getopt import getopt
SERVICES = [
( 'Files', 'system-file-manager' ),
( 'Folders', 'folder' ),
( 'Applications', 'application-x-executable' ),
( 'Conversations', 'face-smile-big' ),
( 'Contacts', 'x-office-address-book' ),
( 'Development Files', 'applications-development' ),
( 'Documents', 'x-office-document' ),
( 'Emails', 'email' ),
( 'Images', 'image-x-generic' ),
( 'Music', 'audio-x-generic' ),
( 'Text Files', 'text-x-generic' ),
( 'Videos', 'video-x-generic' ),
]
DISPLAY_METADATA = {
'Files' : [ 'file.name', 'file.format', 'file.path', 'file.size', 'file.rank', ],
'Music' : [ 'audio.artist', 'audio.album', 'audio.trackno', 'audio.title', 'audio.codec' ],
'Documents' : [ 'doc.title', 'doc.author', 'doc.subject' ],
'Images' : [ 'image.title', 'image.height', 'image.width' ],
}
def FileSizeFormat(hbox, size):
label = gtk.Label()
size = int(size)
if size < 2**10:
label.set_text('%d bytes' % size)
elif size < 2**20:
label.set_text('%3.1f KB' % (size / 2.**10))
elif size < 2**30:
label.set_text('%3.1f MB' % (size / 2.**20))
elif size < 2**40:
label.set_text('%3.1f GB' % (size / 2.**30))
hbox.pack_start(label, expand=False, fill=False)
def FileRankFormat(hbox, rank):
if not rank:
rank='7'
i = 0
rank = float(rank) / 2.
while rank > 0.5:
hbox.pack_start(gtk.image_new_from_icon_name('weather-clear', gtk.ICON_SIZE_MENU), expand=False, fill=False)
i += 1
rank -= 1
if rank == 0.5:
hbox.pack_start(gtk.image_new_from_icon_name('weather-few-clouds', gtk.ICON_SIZE_MENU), expand=False, fill=False)
i += 1
while i < 5:
hbox.pack_start(gtk.image_new_from_icon_name('weather-overcast', gtk.ICON_SIZE_MENU), expand=False, fill=False)
i += 1
def ImageSizeFormat(hbox, size):
hbox.pack_start(gtk.Label(size + ' px'), expand=False, fill=False)
METADATA_LABELS = {
'audio.trackno':'Track #'
}
METADATA_FORMATTERS = {
'file.size':FileSizeFormat,
'file.rank':FileRankFormat,
'image.height':ImageSizeFormat,
'image.width':ImageSizeFormat,
}
class Tracker:
def __init__(self):
bus = dbus.SessionBus()
obj = bus.get_object('org.freedesktop.Tracker',
'/org/freedesktop/tracker')
self.tracker = dbus.Interface(obj, 'org.freedesktop.Tracker')
self.files = dbus.Interface(obj, 'org.freedesktop.Tracker.Files')
self.search = dbus.Interface(obj, 'org.freedesktop.Tracker.Search')
self.keywords = dbus.Interface(obj, 'org.freedesktop.Tracker.Keywords')
self.metadata = dbus.Interface(obj, 'org.freedesktop.Tracker.Metadata')
def __getattr__(self, attr):
return getattr(self.tracker, attr)
class TrackerGUI:
def __init__(self):
self.gconf = gconf.client_get_default()
self.icon_theme = gtk.icon_theme_get_default()
self.tracker = Tracker()
self.layout = 1
self.max_results = 20
opts,args = getopt(sys.argv[1:], '', ['layout=', 'max-hits='])
for a,v in opts:
if a == '--layout':
self.layout = int(v)
elif a == '--max-hits':
self.max_results = int(v)
self.window = gtk.Window()
self.window.set_title('Tracker')
main_vbox = gtk.VBox()
#main_vbox.set_border_width(12)
main_vbox.set_spacing(6)
hbox = gtk.HBox()
hbox.set_spacing(6)
hbox.set_border_width(12)
label = gtk.Label('_Search:')
hbox.pack_start(label, expand=False, fill=False)
self.search_entry = gtk.Entry()
hbox.pack_start(self.search_entry, expand=True, fill=True)
label.props.use_underline = True
label.set_mnemonic_widget(self.search_entry)
if self.layout == 1:
self.service_combobox = gtk.ComboBox()
store = gtk.ListStore(gtk.gdk.Pixbuf, str)
self.service_combobox.set_model(store)
cell = gtk.CellRendererPixbuf()
self.service_combobox.pack_start(cell, False)
self.service_combobox.add_attribute(cell, 'pixbuf', 0)
cell = gtk.CellRendererText()
self.service_combobox.pack_start(cell, False)
self.service_combobox.add_attribute(cell, 'text', 1)
for label, icon_name in SERVICES:
pixbuf = self.icon_theme.load_icon(icon_name,
gtk.ICON_SIZE_MENU, gtk.ICON_LOOKUP_USE_BUILTIN)
store.append([pixbuf, label])
self.service_combobox.set_active(0)
hbox.pack_start(self.service_combobox, expand=False, fill=True)
self.search_button = gtk.Button(stock='gtk-find')
self.search_button.set_data('offset', 0)
hbox.pack_start(self.search_button, expand=False, fill=False)
main_vbox.pack_start(hbox, expand=False, fill=False)
hbox = gtk.HBox()
if self.layout == 2:
self.service_treeview = gtk.TreeView()
store = gtk.ListStore(gtk.gdk.Pixbuf, str)
self.service_treeview.set_model(store)
#self.service_treeview.set_sensitive(False)
self.service_treeview.set_headers_visible(False)
self.service_treeview.set_row_separator_func(lambda model,iter: model[iter][1] == '')
cell = gtk.CellRendererPixbuf()
col = gtk.TreeViewColumn('', cell, pixbuf=0)
self.service_treeview.append_column(col)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn('', cell, text=1)
self.service_treeview.append_column(col)
for label, icon_name in SERVICES:
pixbuf = self.icon_theme.load_icon(icon_name,
gtk.ICON_SIZE_MENU, gtk.ICON_LOOKUP_USE_BUILTIN)
store.append([pixbuf, label])
store.append([None,''])
tags = self.tracker.keywords.GetList('Files')
for tag,count in tags.items():
store.append([None, tag])
selection = self.service_treeview.get_selection()
selection.select_iter(store.get_iter_first())
selection.connect('changed', self.on_service_selection_changed)
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
sw.set_shadow_type(gtk.SHADOW_IN)
sw.add(self.service_treeview)
hbox.pack_start(sw, expand=False, fill=True)
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
sw.set_shadow_type(gtk.SHADOW_IN)
if self.layout in (1,2,3,):
self.icon_view = gtk.IconView()
store = gtk.ListStore(gtk.gdk.Pixbuf, str, str)
self.icon_view.set_model(store)
self.icon_view.set_pixbuf_column(0)
self.icon_view.set_text_column(1)
sw.add(self.icon_view)
elif self.layout == 4:
self.results_tree = gtk.TreeView()
store = gtk.TreeStore(gtk.gdk.Pixbuf, str, str)
self.results_tree.set_model(store)
self.results_tree.set_headers_visible(False)
cell = gtk.CellRendererPixbuf()
col = gtk.TreeViewColumn('', cell, pixbuf=0)
self.results_tree.append_column(col)
cell = gtk.CellRendererText()
col = gtk.TreeViewColumn('', cell, text=1)
self.results_tree.append_column(col)
self._fill_in_services(store)
sw.add(self.results_tree)
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
if self.layout == 3:
self.notebook = gtk.Notebook()
label = gtk.Label('Files')
self.notebook.append_page(sw, label)
main_vbox.pack_start(self.notebook, expand=True, fill=True)
else:
self.result_label = gtk.Label('')
hb = gtk.HBox()
hb.set_border_width(6)
hb.pack_start(self.result_label, expand=False, fill=False)
vb = gtk.VBox()
vb.pack_start(hb, expand=False, fill=False)
vb.pack_start(sw, expand=True, fill=True)
hbox.pack_start(vb, expand=True, fill=True)
main_vbox.pack_start(hbox, expand=True, fill=True)
if self.layout != 4:
hbox = gtk.HBox()
hbox.set_spacing(6)
self.last_button = gtk.Button(stock='gtk-goto-last')
self.last_button.set_sensitive(False)
hbox.pack_end(self.last_button, expand=False, fill=False)
self.next_button = gtk.Button(stock='gtk-go-forward')
self.next_button.get_children()[0].get_children()[0].get_children()[1].set_text('Next')
self.next_button.set_sensitive(False)
hbox.pack_end(self.next_button, expand=False, fill=False)
image = gtk.image_new_from_stock('gtk-go-back', gtk.ICON_SIZE_BUTTON)
self.previous_button = gtk.Button()
self.previous_button.add(image)
self.previous_button.set_sensitive(False)
hbox.pack_end(self.previous_button, expand=False, fill=False)
image = gtk.image_new_from_stock('gtk-goto-first', gtk.ICON_SIZE_BUTTON)
self.first_button = gtk.Button()
self.first_button.add(image)
self.first_button.set_sensitive(False)
self.first_button.set_data('offset', 0)
hbox.pack_end(self.first_button, expand=False, fill=False)
main_vbox.pack_start(hbox, expand=False, fill=False)
self.bottom_pane = gtk.HBox()
self.bottom_pane_content = gtk.HBox()
self.bottom_pane.pack_start(self.bottom_pane_content, expand=True, fill=True)
self.hide_bottom_pane_button = gtk.Button()
image = gtk.image_new_from_stock('gtk-close', gtk.ICON_SIZE_MENU)
self.hide_bottom_pane_button.add(image)
self.hide_bottom_pane_button.set_relief(gtk.RELIEF_NONE)
vbox = gtk.VBox()
vbox.pack_start(self.hide_bottom_pane_button, expand=False, fill=False)
self.bottom_pane.pack_start(vbox, expand=False, fill=False)
vbox = gtk.VBox()
vbox.pack_start(main_vbox, expand=True, fill=True)
vbox.pack_start(self.bottom_pane, expand=False, fill=True)
self.statusbar = gtk.Statusbar()
vbox.pack_start(self.statusbar, expand=False, fill=False)
self.window.add(vbox)
self.search_entry.connect('activate', lambda e: self.search_button.emit('clicked'))
self.search_button.connect('clicked', self.get_search_stats)
if self.layout == 3:
self.search_button.connect('clicked', self.build_service_tabs)
if self.layout == 4:
self.search_button.connect('clicked', self.on_complete_search)
self.results_tree.get_selection().connect('changed', self.on_result_selected)
else:
self.icon_view.connect('selection-changed', self.on_result_selected)
self.search_button.connect('clicked', self.on_search)
self.first_button.connect('clicked', self.on_search)
self.next_button.connect('clicked', self.on_search)
self.previous_button.connect('clicked', self.on_search)
self.last_button.connect('clicked', self.on_search)
self.hide_bottom_pane_button.connect('clicked', lambda *e: self.bottom_pane.hide())
self.window.connect('destroy', gtk.main_quit)
self.window.resize(640, 480)
self.window.show_all()
self.result_label.hide()
def get_search_stats(self, button):
self.search_stats = { }
done = False
offset = 0
query = self.search_entry.get_text()
while not done:
if query.startswith('tag:'):
results = self.tracker.keywords.Search(-1, 'Files', [query[4:]], offset, 512)
else:
results = self.tracker.search.Text(-1, 'Files', query, offset, 512, False)
for r in results:
service = self.tracker.files.GetServiceType(r)
self.search_stats.setdefault(service, 0)
self.search_stats[service] += 1
offset += len(results)
done = (len(results) < 512)
self.search_stats['Files'] = offset
self.last_button.set_data('offset', offset - offset % self.max_results)
self.last_button.set_sensitive(True)
print self.search_stats
def on_search(self, button):
query = self.search_entry.get_text()
offset = button.get_data('offset')
if self.layout == 1:
service = SERVICES[self.service_combobox.get_active()][0]
elif self.layout == 2:
store, iter = self.service_treeview.get_selection().get_selected()
service = store[iter][1]
elif self.layout == 3:
service = self.notebook.get_tab_label(self.icon_view.get_parent()).get_text()
if query.startswith('tag:'):
results = self.tracker.keywords.Search(-1, service,
[ query[4:] ], offset, self.max_results + 1)
else:
results = self.tracker.search.Text(-1, service,
query, offset, self.max_results + 1, False)
self.result_label.set_markup('Showing results <b>%d</b> - <b>%d</b> of <b>%d</b>.'
% (offset + 1,
offset + min(len(results), self.max_results),
self.search_stats[service]))
self.result_label.show()
if self.layout in (1,2,3,):
store = self.icon_view.get_model()
store.clear()
for r in results[:self.max_results]:
basename = os.path.basename(r)
pixbuf = self._get_file_thumbnail_pixbuf(r) or self._get_mime_thumbnail(r)
store.append([ pixbuf, basename, r ])
self.icon_view.get_parent().get_vscrollbar().get_adjustment().value = 0
self.first_button.set_sensitive(True)
if offset > 0:
self.previous_button.set_sensitive(True)
self.previous_button.set_data('offset', offset - self.max_results)
else:
self.previous_button.set_sensitive(False)
if len(results) == self.max_results + 1:
self.next_button.set_sensitive(True)
self.next_button.set_data('offset', offset + self.max_results)
else:
self.next_button.set_sensitive(False)
def on_complete_search(self, button):
query = self.search_entry.get_text()
store = self.results_tree.get_model()
store.clear()
self._fill_in_services(store)
iter = store.get_iter_first()
while iter:
service = store[iter][1]
done = False
offset = 0
while not done:
if query.startswith('tag:'):
results = self.tracker.keywords.Search(-1, service,
[ query[4:] ], offset, self.max_results + 1)
else:
results = self.tracker.search.Text(-1, service, query, offset, 256, False)
offset += len(results)
for r in results:
pixbuf = self._get_file_thumbnail_pixbuf(r) or self._get_mime_thumbnail(r)
h = pixbuf.get_height()
w = pixbuf.get_width()
scale = max(h,w)
h = int(h * 24. / scale)
w = int(w * 24. / scale)
pixbuf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_BILINEAR)
store.append(iter, [pixbuf, r, r])
done = (len(results) < 256)
iter = store.iter_next(iter)
def on_service_selection_changed(self, selection):
self.on_search(self.search_button)
def _get_file_thumbnail_pixbuf(self, f):
uri = 'file://' + urllib.pathname2url(f)
thumb = md5.new()
thumb.update(uri)
thumb = os.path.expanduser('~/.thumbnails/normal/%s.png' % thumb.hexdigest())
try:
return gtk.gdk.pixbuf_new_from_file(thumb)
except:
return None
def _get_mime_thumbnail(self, f):
return self.icon_theme.load_icon('image-loading', 32, gtk.ICON_LOOKUP_USE_BUILTIN)
def _fill_in_services(self, store):
for label, icon_name in SERVICES:
pixbuf = self.icon_theme.load_icon(icon_name,
gtk.ICON_SIZE_MENU, gtk.ICON_LOOKUP_USE_BUILTIN)
store.append(None, [pixbuf, label, ''])
def build_service_tabs(self, button):
query = self.search_entry.get_text()
services = set()
done = False
offset = 0
while not done:
results = self.tracker.search.Text(-1, 'Files', query, offset, 256, False)
print len(results),'results.',results
for r in results:
print r, self.tracker.files.GetServiceType(r)
#services.add(self.tracker.files.GetServiceType(r))
offset += len(results)
done = (len(results) < 256)
print 'done:',done
print services
def on_result_selected(self, arg):
self._clear_container(self.bottom_pane_content)
if isinstance(arg, gtk.IconView):
store = arg.get_model()
selected = arg.get_selected_items()[0]
path = store[selected][2]
else:
model, iter = arg.get_selected()
path = model[iter][2]
if not path:
return
service = self.tracker.files.GetServiceType(path)
self.statusbar.push(0, '%s [%s]' % (path,service))
main_hbox = gtk.HBox() # 4 columns
main_hbox.set_homogeneous(True)
# Column #1: Thumbnail
# TODO
# Column #2: General File Properties
keys = DISPLAY_METADATA['Files']
metadata = self.tracker.metadata.Get('Files', path, keys)
table = gtk.Table(len(keys) + 2, 2, False)
table.set_col_spacings(6)
table.set_row_spacings(6)
label = gtk.Label('')
label.set_markup('<span size="x-large">%s</span>' % metadata[0])
label.set_selectable(True)
label.set_ellipsize(pango.ELLIPSIZE_END)
hbox = gtk.HBox()
hbox.pack_start(label, expand=True, fill=True)
table.attach(hbox, 0, 2, 0, 1, gtk.FILL | gtk.EXPAND, gtk.FILL)
for n,(k,m) in enumerate(zip(keys,metadata)[1:]):
# Build Key
label = gtk.Label('')
if k in METADATA_LABELS:
label.set_markup('<b>%s:</b>' % METADATA_LABELS[k])
else:
label.set_markup('<b>%s:</b>' % k.split('.')[1].title())
hbox = gtk.HBox()
hbox.pack_end(label, expand=False, fill=False)
table.attach(hbox, 0, 1, n+1, n+2, gtk.FILL, gtk.FILL)
# Build Value
hbox = gtk.HBox()
if k in METADATA_FORMATTERS:
METADATA_FORMATTERS[k](hbox, m)
else:
label = gtk.Label(m)
label.set_selectable(True)
label.set_ellipsize(pango.ELLIPSIZE_END)
hbox.pack_start(label, fill=True, expand=True)
table.attach(hbox, 1, 2, n+1, n+2, gtk.FILL | gtk.EXPAND, gtk.FILL)
# Tag row widgets
label = gtk.Label('')
label.set_markup('<b>Tags:</b>')
hbox = gtk.HBox()
hbox.pack_end(label, expand=False, fill=False)
table.attach(hbox, 0, 1, n+2, n+3, gtk.FILL, gtk.FILL)
hbox1 = gtk.HBox()
add_button = gtk.Button()
image = gtk.image_new_from_stock('gtk-add', gtk.ICON_SIZE_BUTTON)
add_button.add(image)
add_button.set_relief(gtk.RELIEF_NONE)
hbox1.pack_start(add_button, expand=False, fill=False)
tags = self.tracker.keywords.Get('Files', path)
first = True
for tag in tags:
if not first:
hbox1.pack_start(gtk.Label(','), expand=False, fill=False)
label = gtk.Label()
label.set_markup('<span foreground="blue"><u>%s</u></span>' % tag)
btn = gtk.Button()
btn.add(label)
btn.set_relief(gtk.RELIEF_NONE)
btn.connect('clicked', self.on_tag_selected)
hbox1.pack_start(btn, expand=False, fill=False)
first = False
hbox2 = gtk.HBox()
completion = gtk.EntryCompletion()
completion.set_model(self._create_tag_model())
completion.set_text_column(0)
tag_entry = gtk.Entry()
tag_entry.set_completion(completion)
hbox2.pack_start(tag_entry, expand=False, fill=False)
accept_button = gtk.Button()
image = gtk.image_new_from_stock('gtk-apply', gtk.ICON_SIZE_BUTTON)
accept_button.add(image)
accept_button.set_relief(gtk.RELIEF_NONE)
hbox2.pack_start(accept_button, expand=False, fill=False)
cancel_button = gtk.Button()
image = gtk.image_new_from_stock('gtk-cancel', gtk.ICON_SIZE_BUTTON)
cancel_button.add(image)
cancel_button.set_relief(gtk.RELIEF_NONE)
hbox2.pack_start(cancel_button, expand=False, fill=False)
hbox = gtk.HBox()
hbox.pack_start(hbox1, expand=True, fill=True)
hbox.pack_start(hbox2, expand=True, fill=True)
table.attach(hbox, 1, 2, n+2, n+3, gtk.FILL, gtk.FILL)
main_hbox.pack_start(table, expand=True, fill=True)
# Tag widget signals
tag_entry.connect('activate', lambda e: accept_button.emit('clicked'))
add_button.connect('clicked', lambda b: (hbox1.hide(), hbox2.show(), tag_entry.grab_focus()))
accept_button.connect('clicked', self.on_accept_tag_add, hbox1, hbox2, path, arg)
cancel_button.connect('clicked', lambda b: (hbox1.show(), hbox2.hide(), tag_entry.set_text('')))
# Column #3: Type specific metadata
if service in DISPLAY_METADATA and DISPLAY_METADATA[service]:
keys = DISPLAY_METADATA[service]
metadata = self.tracker.metadata.Get('Files', path, keys)
table = gtk.Table(len(keys), 2, False)
table.set_col_spacings(6)
table.set_row_spacings(6)
for n,(k,m) in enumerate(zip(keys,metadata)):
# Build Key
label = gtk.Label('')
if k in METADATA_LABELS:
label.set_markup('<b>%s:</b>' % METADATA_LABELS[k])
else:
label.set_markup('<b>%s:</b>' % k.split('.')[1].title())
hbox = gtk.HBox()
hbox.pack_end(label, expand=False, fill=False)
table.attach(hbox, 0, 1, n, n+1, gtk.FILL, gtk.FILL)
# Build Value
hbox = gtk.HBox()
if k in METADATA_FORMATTERS:
METADATA_FORMATTERS[k](hbox, m)
else:
label = gtk.Label(m)
label.set_selectable(True)
label.set_ellipsize(pango.ELLIPSIZE_END)
hbox.pack_start(label, fill=True, expand=True)
table.attach(hbox, 1, 2, n, n+1, gtk.FILL | gtk.EXPAND, gtk.FILL)
main_hbox.pack_start(table, expand=True, fill=True)
# Column #4: Sample contents
query = self.search_entry.get_text()
if not query.startswith('tag:'):
contents = metadata = self.tracker.metadata.Get('Files', path, ['file.content'])
if contents:
contents = contents[0].replace('\n', '\\n')
idx = contents.lower().find(query.lower())
if idx > -1:
start = max(0, idx - 75)
end = min(len(contents), start + 150)
text = gtk.TextView()
text.get_buffer().set_text(contents[start:end])
# .replace('<', '<')
# .replace('>', '>')
# .replace(query, '<b>%s</b>' % query))
text.set_wrap_mode(gtk.WRAP_WORD)
vbox = gtk.VBox()
vbox.pack_start(text, expand=False, fill=False)
frame = gtk.Frame('Contents')
frame.add(vbox)
main_hbox.pack_start(frame, expand=True, fill=True)
main_hbox.set_spacing(12)
main_hbox.show_all()
hbox2.hide()
self.bottom_pane_content.pack_start(main_hbox, expand=True, fill=True)
def _clear_container(self, widget, parent=None):
if isinstance(widget, gtk.Container):
widget.foreach(self._clear_container, widget)
if parent:
parent.remove(widget)
def _create_tag_model(self):
store = gtk.ListStore(str)
tags = self.tracker.keywords.GetList('Files')
for tag,count in tags.items():
store.append([tag])
return store
def on_tag_selected(self, button):
tag = button.get_children()[0].get_text()
self.search_entry.set_text('tag:%s' % tag)
self.search_button.emit('clicked')
def on_accept_tag_add(self, accept_button, hbox1, hbox2, path, selection):
tag = hbox2.get_children()[0].get_text()
self.tracker.keywords.Add('Files', path, [ tag ])
self.on_result_selected(selection)
gui = TrackerGUI()
gtk.main()
_______________________________________________
tracker-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/tracker-list