Re: Python API of "old" Gecko Version



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



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]