[totem] Added basic support for listing channels and categories asynchronously



commit 655fe75d7c3c8bfa78972802c3ceb717443b174b
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Apr 26 11:13:06 2009 +0100

    Added basic support for listing channels and categories asynchronously
---
 src/plugins/iplayer/iplayer.py |   59 +++++++++++++++++++++++++++++++++++----
 src/plugins/iplayer/iplayer.ui |   28 +++++++++++++++++--
 2 files changed, 78 insertions(+), 9 deletions(-)

diff --git a/src/plugins/iplayer/iplayer.py b/src/plugins/iplayer/iplayer.py
index 6fc95aa..111ef40 100644
--- a/src/plugins/iplayer/iplayer.py
+++ b/src/plugins/iplayer/iplayer.py
@@ -1,24 +1,71 @@
-# -*- coding: utf-8 -*-
-
 import totem
 import gobject
 import gtk
+import iplayer2
+import threading
 
 class IplayerPlugin (totem.Plugin):
-	def __init__(self):
+	def __init__ (self):
 		totem.Plugin.__init__ (self)
 		self.debug = True
 		self.totem = None
 
 	def activate (self, totem_object):
 		# Build the interface
-		self.builder = self.load_interface ("iplayer.ui", True, totem_object.get_main_window (), self)
-		container = self.builder.get_object ('iplayer_vbox')
+		builder = self.load_interface ("iplayer.ui", True, totem_object.get_main_window (), self)
+		container = builder.get_object ('iplayer_vbox')
+		self.tree_store = builder.get_object ('iplayer_programme_store')
 
 		self.totem = totem_object
 		container.show_all ()
 
-		self.totem.add_sidebar_page("iplayer", _("BBC iPlayer"), container)
+		self.tv = iplayer2.feed ('tv')
+		# TODO: Radio support
+		#self.radio = feed ('radio')
+
+		self.totem.add_sidebar_page ("iplayer", _("BBC iPlayer"), container)
+
+		self.populate_channel_list ()
 
 	def deactivate (self, totem_object):
 		totem_object.remove_sidebar_page ("iplayer")
+
+	def populate_channel_list (self):
+		# Add all the channels as top-level rows in the tree store
+		channels = self.tv.channels ()
+		for channel_id, title in channels.items ():
+			parent_iter = self.tree_store.append (None, [title, channel_id, None])
+
+		# Add the channels' categories in a thread, since they each require a network request
+		parent_path = self.tree_store.get_path (parent_iter)
+		thread = PopulateChannelsThread (self, parent_path, self.tv, self.tree_store)
+        	thread.start ()
+
+	def _populate_channel_list_cb (self, parent_path, values):
+		# Callback from PopulateChannelsThread to add stuff to the tree store
+		parent_iter = self.tree_store.get_iter (parent_path)
+		self.tree_store.append (parent_iter, values)
+		return False
+
+class PopulateChannelsThread (threading.Thread):
+	# Class to populate the channel list from the Internet
+	def __init__ (self, plugin, parent_path, feed, tree_model):
+		self.plugin = plugin
+		self.feed = feed
+		self.tree_model = tree_model
+		threading.Thread.__init__ (self)
+
+	def run (self):
+		tree_iter = self.tree_model.get_iter_first ()
+		while (tree_iter != None):
+			channel_id = self.tree_model.get_value (tree_iter, 1)
+			parent_path = self.tree_model.get_path (tree_iter)
+
+			# Add this channel's categories as sub-rows
+			# We have to pass a path because the model could theoretically be modified
+			# while the idle function is waiting in the queue, invalidating an iter
+			for name, category_id in self.feed.get (channel_id).categories ():
+				gobject.idle_add (self.plugin._populate_channel_list_cb, parent_path, [name, category_id, None])
+
+			tree_iter = self.tree_model.iter_next (tree_iter)
+
diff --git a/src/plugins/iplayer/iplayer.ui b/src/plugins/iplayer/iplayer.ui
index 6d16a2b..8d858a6 100644
--- a/src/plugins/iplayer/iplayer.ui
+++ b/src/plugins/iplayer/iplayer.ui
@@ -1,12 +1,11 @@
 <?xml version="1.0"?>
 <!--*- mode: xml -*-->
 <interface>
-<object class="GtkListStore" id="iplayer_programme_list_store">
+<object class="GtkTreeStore" id="iplayer_programme_store">
 	<columns>
-		<column type="GdkPixbuf"/><!--Thumbnail-->
 		<column type="gchararray"/><!--Title-->
+		<column type="gchararray"/><!--Summary-->
 		<column type="gchararray"/><!--MRL-->
-		<column type="GObject"/><!--Video entry; TODO: should be GDataYouTubeVideo, see bug #576285-->
 	</columns>
 </object>
 
@@ -14,5 +13,28 @@
 	<property name="border-width">5</property>
 	<property name="homogeneous">False</property>
 	<property name="spacing">6</property>
+	<child>
+		<object class="GtkScrolledWindow" id="iplayer_scrolled_window">
+			<property name="hscrollbar-policy">GTK_POLICY_AUTOMATIC</property>
+			<property name="vscrollbar-policy">GTK_POLICY_AUTOMATIC</property>
+			<child>
+				<object class="GtkTreeView" id="iplayer_programme_list">
+					<property name="model">iplayer_programme_store</property>
+					<property name="expander-column">iplayer_title_column</property>
+					<property name="headers-visible">False</property>
+					<child>
+						<object class="GtkTreeViewColumn" id="iplayer_title_column">
+							<child>
+								<object class="GtkCellRendererText" id="iplayer_title_cell_renderer"/>
+								<attributes>
+									<attribute name="text">0</attribute>
+								</attributes>
+							</child>
+						</object>
+					</child>
+				</object>
+			</child>
+		</object>
+	</child>
 </object>
 </interface>



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