Am Fr, 25.07.2008 um 13:37 schrieb "Diego Escalante Urrelo"
<diegoe gnome org>:
> I tried to port it too, but just forgot about finishing it :)
>
> >From my half ported t-o-t-v:
> self.treemodel.insert(page_num, [tab, tab.get_property("title"),
> tab.get_icon()])
> tab.connect('notify::title', self.update_tab_title)
thanks - that helped!
I managed to port it - but with one drawback:
embed (a child from the notebook and the widget you get from
attach_tab()) is of type __main__.MozillaEmbed but I can't use that to
create a ListStore. At the moment I create it with:
gtk.ListStore(first_child_of_notebook.__class__,str,gtk.gdk.Pixbuf)
but this has the problem that the first child does not exist where I
first start the browser and the plugin is called via attach_window(). So
I have to wait for the first call to attach_tab().
I saw in the code, that MozillaEmbed is a struct - is there any
elegant way to get this into python?
cu
/Steffen
PS: first ugly version attached - I made 2 improvements:
1) middle click to close
2) scroll to change the "tab"
At the moment it is "without" a license - I'm trying to contact the
author for the original license!
There bug with a disappearing website when enabling or disabling the
extension - just change to another tab and everything is fine!
--
/"\
\ / ASCII Ribbon Campaign | "The best way to predict
X * NO HTML/RTF in e-mail | the future is to invent it."
/ \ * NO MSWord docs in e-mail| -- Alan Kay
import gtk
import pango
import epiphany
import gconf
base_gconf_path="/apps/epiphany/general/"
class TreeviewTabs:
treeview_popup_xml = """
<ui>
<popup name="TabsOnTreeviewPopup">
<menuitem action="TabsOnTreeviewLeft"/>
<menuitem action="TabsOnTreeviewRight" />
</popup>
</ui>
"""
actiongroupdef = [
('TabsOnTreeviewLeft', None, 'Left Sidebar', None, 'Move sidebar to the left', False),
('TabsOnTreeviewRight', None, 'Right Sidebar', None, 'Move sidebar to the right', True)
]
def __init__(self, window, gconf, always_show_tabs_bar, sidebar_on_right):
self.window = window
self.notebook = window.get_notebook()
self.no_update = False
self.no_update_left = False
self.no_update_right = False
self.gconf = gconf
self.always_show_tabs_bar = always_show_tabs_bar
self.sidebar_on_right = sidebar_on_right
self.sidebar_width = self.gconf.get_int(base_gconf_path+"sidebar_width")
self.fertig = False
self.treemodel = gtk.ListStore(int, str, gtk.gdk.Pixbuf)
def toggle_sidebar_side_cb(self, first, second):
self.gconf.set_bool(base_gconf_path+"sidebar_on_right", first.get_current_value())
def on_selection_change(self, treeselection):
treemodel, iter = treeselection.get_selected()
if iter and not self.no_update:
path = treemodel.get_path(iter)
self.notebook.set_current_page(self.get_pos(path))
def move_tab(self, treemodel, path, iter):
tab = self.treemodel.get_value(iter, 0)
self.notebook.reorder_child(tab, self.get_pos(path))
def setup_drag(self):
self.TARGETS = [
('TVEXT_TREE_MODEL_ROW_INTERNAL', gtk.TARGET_SAME_WIDGET, 0),
('TVEXT_TREE_MODEL_ROW_EXTERNAL', 0, 1),
('text/plain', 0, 2),
('TEXT', 0, 3),
('STRING', 0, 4)
]
self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, self.TARGETS,
gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
self.treeview.enable_model_drag_dest(self.TARGETS, gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)
self.treeview.connect("drag_data_get", self.drag_data_get_data)
self.treeview.connect("drag_data_received", self.drag_data_received_data)
def drag_data_get_data(self, treeview, context, selection, info, etime):
treeselection = treeview.get_selection()
model, iter = treeselection.get_selected()
if info == 0:
data = model.get_string_from_iter(iter)
selection.set(selection.target, 8, data)
elif info == 1:
data = str(model.get_value(iter, 0).get_address())
selection.set(selection.target, 8, data)
self.window.get_active_tab().get_embed().close()
else:
data = str(model.get_value(iter, 0).get_address())
selection.set_text(data)
def get_pos(self, path):
return list(path)[0]
def drag_data_received_data(self, treeview, context, x, y, selection, info, etime):
data = selection.data
drop_info = treeview.get_dest_row_at_pos(x, y)
model = treeview.get_model()
if info == 0:
# Internal move
iter = model.get_iter_from_string(data)
rowdata = model.get_value(iter, 0), model.get_value(iter, 1), model.get_value(iter, 2)
if drop_info:
path, position = drop_info
if (position == gtk.TREE_VIEW_DROP_AFTER or
position == gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
old_pos = self.get_pos(model.get_path(iter))
if old_pos >= self.get_pos(path):
path = model.get_path(model.iter_next(model.get_iter(path)))
self.move_tab(model, path, iter)
else:
dest = model.iter_nth_child(None, model.iter_n_children(None)-1)
self.move_tab(model, model.get_path(dest), iter)
else:
if drop_info:
path, position = drop_info
iter = model.get_iter(path)
source_tab = model.get_value(iter, 0)
new_tab = self.window.open(data, source_tab, 2)
tabrow = self.find_tab_row(new_tab)
if (position == gtk.TREE_VIEW_DROP_AFTER or
position == gtk.TREE_VIEW_DROP_INTO_OR_AFTER):
iter = model.iter_next(iter)
path = model.get_path(iter)
self.move_tab(model, path, tabrow)
self.notebook.set_current_page( self.get_pos(path))
else:
iter = model.iter_nth_child(None, model.iter_n_children(None)-1)
source_tab = model.get_value(iter, 0)
self.window.open(data, source_tab, 2)
path = model.get_path(iter)
self.notebook.set_current_page(self.get_pos(path)+1)
if info == 1:
context.finish(True, True, etime)
def treeview_click_cb(self, treeview, event):
if event.button == 3:
pos_info = treeview.get_dest_row_at_pos(int(event.x), int(event.y))
if pos_info:
path, position = pos_info
self.notebook.set_current_page(self.get_pos(path))
self.show_tab_popup(event.get_time())
return True
else:
self.show_sidebar_popup(event.get_time())
def treeview_middleclick_cb(self, treeview, event):
if event.button == 2:
pos_info = treeview.get_dest_row_at_pos(int(event.x), int(event.y))
if pos_info:
path, position = pos_info
e = self.notebook.get_nth_page(self.get_pos(path))
e.close()
return True
def treeview_scroll_cb(self, treeview, event):
if event.direction == gtk.gdk.SCROLL_UP:
self.notebook.prev_page()
if event.direction == gtk.gdk.SCROLL_DOWN:
self.notebook.next_page()
return True
def build_custom(self,class_of_embed):
self.custom_part = gtk.HPaned()
self.custom_part.pack2(gtk.HPaned(), True)
self.treemodel = gtk.ListStore(class_of_embed, str, gtk.gdk.Pixbuf)
self.treeview = gtk.TreeView(self.treemodel)
self.treeview.set_headers_visible(False)
self.treeview.get_selection().set_mode(gtk.SELECTION_BROWSE)
self.setup_drag()
# self.treeview.set_reorderable(True)
title_cell = gtk.CellRendererText()
title_cell.set_property("ellipsize", pango.ELLIPSIZE_END)
icon_cell = gtk.CellRendererPixbuf()
self.column = gtk.TreeViewColumn('Tab icon')
self.column.pack_start(icon_cell, False)
self.column.set_attributes(icon_cell, pixbuf=2)
self.column.pack_start(title_cell)
self.column.set_attributes(title_cell, text=1)
self.treeview.append_column(self.column)
self.treeview.connect('button-press-event', self.treeview_click_cb)
self.treeview.connect('button-release-event', self.treeview_middleclick_cb)
self.treeview.connect('scroll-event', self.treeview_scroll_cb)
self.treeview.get_selection().connect('changed', self.on_selection_change)
self.treemodel.connect('row-changed', self.move_tab)
scrolled = gtk.ScrolledWindow()
scrolled.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
scrolled.set_shadow_type(gtk.SHADOW_IN)
scrolled.add(self.treeview)
label = gtk.Label("Opened Pages")
label.set_justify(gtk.JUSTIFY_LEFT)
label.set_ellipsize(pango.ELLIPSIZE_END)
label.set_alignment(0.0, 0.5)
label.set_padding(3, 0)
close_button = gtk.Button()
close_button.set_relief(gtk.RELIEF_NONE)
close_image = gtk.image_new_from_stock(gtk.STOCK_CLOSE,
gtk.ICON_SIZE_MENU)
close_button.set_image(close_image)
close_button.connect("clicked", self.close_clicked)
title_hbox = gtk.HBox()
title_hbox.pack_start(label, True)
title_hbox.pack_end(close_button, False)
self.vbox = gtk.VBox()
self.vbox.pack_start(title_hbox, False)
self.vbox.pack_start(scrolled, True)
self.spacer = gtk.Alignment(xscale=1.0, yscale=1.0)
self.spacer.add(self.vbox)
self.spacer_update()
self.secondary_pack(self.spacer)
self.main_pack(self.notebook)
self.custom_part.show()
self.custom_part.get_child2().show()
self.custom_part.connect("notify::position", self.sidebar_width_changed1_cb)
self.custom_part.get_child2().connect("notify::position", self.sidebar_width_changed2_cb)
# Best way I found to be informed when the window has finalized its size
self.rs_hack = self.custom_part.get_child2().connect("notify::max-position",
self.right_sidebar_hack_cb)
def right_sidebar_hack_cb(self, paned, position):
self.sidebar_width_update()
self.custom_part.get_child2().disconnect(self.rs_hack)
def window_focus_cb(self, window, value):
# The saved width is the width of the last focused window
if window.is_active():
self.sidebar_width_save()
def sidebar_width_changed1_cb(self, paned, position):
if not self.no_update:
self.sidebar_width = paned.get_position()
self.sidebar_width_save()
def sidebar_width_changed2_cb(self, paned, position):
if not self.no_update:
paned = self.custom_part.get_child2()
self.sidebar_width = paned.get_allocation().width-paned.get_position()-6
self.sidebar_width_save()
def sidebar_width_save(self):
self.gconf.set_int(base_gconf_path+"sidebar_width", self.sidebar_width)
def sidebar_width_update(self):
self.no_update = True
if self.sidebar_on_right:
paned = self.custom_part.get_child2()
paned.set_position(self.window.get_allocation().width-self.sidebar_width-6)
else:
self.custom_part.set_position(self.sidebar_width)
self.no_update = False
def spacer_update(self):
if self.sidebar_on_right:
self.spacer.set_padding(0, 4, 0, 4)
else:
self.spacer.set_padding(0, 4, 4, 0)
def separator_update(self):
hbchilds = self.custom_part.get_child2().get_child1().get_children()
if self.sidebar_on_right:
hbchilds[0].hide()
hbchilds[2].show()
else:
hbchilds[0].show()
hbchilds[2].hide()
def main_pack(self, widget):
hbox = gtk.HBox()
sep1 = gtk.VSeparator()
sep2 = gtk.VSeparator()
hbox.pack_start(sep1, False)
hbox.pack_start(widget, True)
hbox.pack_start(sep2, False)
self.custom_part.get_child2().pack1(hbox, True, True)
hbox.show_all()
self.separator_update()
def secondary_pack(self, widget):
if self.sidebar_on_right:
self.custom_part.get_child2().pack2(widget, False, False)
else:
self.custom_part.pack1(widget, False, False)
widget.show_all()
def secondary_unpack(self):
widget = self.get_secondary()
widget.get_parent().remove(widget)
return widget
def get_main(self):
return self.custom_part.get_child2().get_child1().get_children()[1]
def get_secondary(self):
if self.sidebar_on_right:
return self.custom_part.get_child2().get_child2()
else:
return self.custom_part.get_child1()
def get_separator(self):
if self.sidebar_on_right:
return self.custom_part.get_child2().get_child1().get_children()[2]
else:
return self.custom_part.get_child2().get_child1().get_children()[0]
def show_tab_popup(self,etime):
popupmenu = self.uimanager.get_widget("/EphyNotebookPopup")
popupmenu.popup(None, None, None, 2, etime)
def show_sidebar_popup(self, etime):
popupmenu = self.uimanager.get_widget("/TabsOnTreeviewPopup")
popupmenu.popup(None, None, None, 2, etime)
def close_clicked(self, button):
self.window.get_active_tab().get_embed().close()
def show_sidebar(self):
self.get_secondary().show()
self.get_separator().show()
self.force_hidden_tabs(self.notebook, True)
def hide_sidebar(self):
self.get_secondary().hide()
self.get_separator().hide()
def update_tab_order(self, notebook, child, page_num):
tabrow = self.find_tab_row(child)
if tabrow:
dest = self.treemodel.iter_nth_child(None, page_num)
old_num = self.get_pos(self.treemodel.get_path(tabrow))
if old_num > page_num:
self.treemodel.move_before(tabrow, dest)
else:
self.treemodel.move_after(tabrow, dest)
# Workaround for bug: #169116
# def workaround_embed(self):
# if self.window.get_active_tab():
# self.window.get_active_tab().get_embed().hide()
# self.window.get_active_tab().get_embed().show()
def attach_window(self):
pass
def attach_window2(self):
winvbox = self.window.get_children()[0]
page = self.notebook.get_nth_page(0)
self.notebook.get_parent().remove(self.notebook)
self.build_custom(page.__class__)
winvbox.pack_start(self.custom_part, True)
winvbox.reorder_child(self.custom_part, 1)
self.notebook.connect('switch_page', self.update_current_tab)
self.notebook.connect('page_reordered', self.update_tab_order)
self.fhidden_cb_handle = self.notebook.connect('notify::show-tabs', self.force_hidden_tabs)
#self.workaround_embed()
self.uimanager = self.window.get_ui_manager()
self.ui_id = self.uimanager.add_ui_from_string(self.treeview_popup_xml)
self.actiongroup = gtk.ActionGroup('TabsOnTreeview')
self.actiongroup.add_radio_actions(self.actiongroupdef, self.sidebar_on_right, self.toggle_sidebar_side_cb)
self.uimanager.insert_action_group(self.actiongroup, 0)
self.sidebar_width_update()
self.window.connect("notify::is-active", self.window_focus_cb)
def force_hidden_tabs(self, notebook, visible):
if visible:
notebook.set_show_tabs(False)
def detach_window(self):
winvbox = self.window.get_children()[0]
self.notebook.get_parent().remove(self.notebook)
self.custom_part.get_parent().remove(self.custom_part)
winvbox.pack_start(self.notebook, True)
winvbox.reorder_child(self.notebook, 1)
self.notebook.disconnect(self.fhidden_cb_handle)
self.notebook.set_show_tabs(True)
self.notebook.show()
# self.workaround_embed()
self.uimanager.remove_ui(self.ui_id)
self.uimanager.remove_action_group(self.actiongroup)
self.uimanager.ensure_update()
def update_current_tab(self, notebook, page, page_num):
self.no_update = True
self.treeview.set_cursor(int(page_num))
self.no_update = False
def find_tab_row(self, embed):
iter = self.treemodel.get_iter_first()
while iter:
if self.treemodel.get_value(iter, 0) == embed:
return iter
iter = self.treemodel.iter_next(iter)
return None
def update_tab_title(self, embed,data):
tabrow = self.find_tab_row(embed)
if tabrow:
self.treemodel.set_value(tabrow, 1, embed.get_property("title"))
def update_tab_favicon(self, embed, pspec):
tabrow = self.find_tab_row(embed)
if tabrow:
self.treemodel.set_value(tabrow, 2, embed.get_icon())
def attach_tab(self, embed):
if not self.fertig:
self.fertig=True
self.attach_window2()
page_num = self.notebook.page_num(embed)
self.treemodel.insert(page_num, [embed, embed.get_property("title"),
embed.get_icon()])
embed.connect('notify::title', self.update_tab_title)
embed.connect('notify::icon', self.update_tab_favicon)
if self.notebook.get_n_pages() == 1 and not self.always_show_tabs_bar:
self.hide_sidebar()
else:
self.show_sidebar()
def detach_tab(self, embed):
if self.find_tab_row(embed):
self.treemodel.remove(self.find_tab_row(embed))
if self.notebook.get_n_pages() < 2 and not self.always_show_tabs_bar:
self.hide_sidebar()
def set_always_show_tabs_bar(self, active):
self.always_show_tabs_bar = active
if not active and self.notebook.get_n_pages() < 2 :
self.hide_sidebar()
else:
self.show_sidebar()
def set_sidebar_on_right(self, value):
secondary = self.secondary_unpack()
self.sidebar_on_right = value
self.secondary_pack(secondary)
self.spacer_update()
self.separator_update()
self.sidebar_width_update()
toggle = self.uimanager.get_widget("/TabsOnTreeviewPopup/TabsOnTreeviewRight")
toggle.set_active(self.sidebar_on_right)
class TreeviewTabsDispatch:
def __init__(self):
self.winlist = {}
self.gconf = gconf.client_get_default()
self.always_show_tabs_bar = self.gconf.get_bool("/apps/epiphany/general/always_show_tabs_bar")
self.sidebar_on_right = self.gconf.get_bool(base_gconf_path+"sidebar_on_right")
self.gconf.notify_add("/apps/epiphany/general/always_show_tabs_bar",
self.always_show_tabs_bar_cb)
self.gconf.notify_add(base_gconf_path+"sidebar_on_right",
self.sidebar_on_right_cb)
def always_show_tabs_bar_cb(self, client, a_number, entry, a_list):
active = entry.value.get_bool()
for window in self.winlist:
self.winlist[window].set_always_show_tabs_bar(active)
self.always_show_tabs_bar = active
def sidebar_on_right_cb(self, client, a_number, entry, a_list):
active = entry.value.get_bool()
for window in self.winlist:
self.winlist[window].set_sidebar_on_right(active)
self.sidebar_on_right = active
def attach_window(self, window):
self.winlist[window] = TreeviewTabs(window, self.gconf,
self.always_show_tabs_bar, self.sidebar_on_right)
self.winlist[window].attach_window()
def attach_tab(self, window, embed):
self.winlist[window].attach_tab(embed)
def detach_tab(self, window, embed):
self.winlist[window].detach_tab(embed)
def detach_window(self, window):
self.winlist[window].detach_window()
del self.winlist[window]
treeview_extension = TreeviewTabsDispatch()
attach_window = treeview_extension.attach_window
detach_window = treeview_extension.detach_window
attach_tab = treeview_extension.attach_tab
detach_tab = treeview_extension.detach_tab
Attachment:
tabs_on_treeview.ephy-extension
Description: Binary data
Attachment:
signature.asc
Description: PGP signature