Re: My first Conduit module



Hi John, tanks for commit this.
After read your comments  I start some improves in youtube module, and now I have another patch :), with some improves like a config screen.
And I already think in another improves to do in this module and  I will do this in the next days.

Thanks
Renato Filho






On 9/2/07, John Stowers <john stowers gmail com> wrote:


On 9/2/07, Renato Araujo <renatox gmail com> wrote:
Hi all,

After some talk in conduit irc channel I decided start my first dataprovider for study the conduit api.

I wold like submit my provider for you, to give me some feedbacks and talk about this.

Thanks. I committed the dp because it works, and is usable even at this early stage. Well done!

My first module synchronize is  the youtube most watched videos of the day.

The natural extension to this would be to provide a configuration dialog to allow the user to select between
 * n number of most watched vids
 * n new vids
 * vids posted by a certain user
 * etc

First I start read the the tutorial about "create a writing A custom dataProvider" on wiki page, after this I copy the FeedModule and start my module, I fond some differences between the implementation and the tutorial.

This is my question:  In the method "get", this receive the string LUID, generate by "get_all" method, in the tutorial you use the "get_num_items" to get the total of items and pass the integer index to method "get". What is the correct way to do this, or both are correct?

Your implementation is correct, the docs were out of date. I have now updated them and also updated the ExampleModule dataprovider in the help directory.

Basically get_num_items is no longer compulsory, get_all should return a list of UIDs, and get then accepts the UIDs returned by get_all.

Style wise I like to have private functions prefixed with _, eg
extract_video_url -> _extract_video_url

Also, see the discussion about selection of UID for the dataprovider ( http://www.conduit-project.org/wiki/WritingADataProvider), i.e. it should not be too closely tied to the dp configuration

Welcome to conduit!

John

BR
Renato Filho




_______________________________________________
Conduit-list mailing list
Conduit-list gnome org
http://mail.gnome.org/mailman/listinfo/conduit-list




Index: m4/intltool.m4
===================================================================
--- m4/intltool.m4	(revision 825)
+++ m4/intltool.m4	(working copy)
@@ -23,7 +23,7 @@
 ## the same distribution terms that you use for the rest of that program.
 
 dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml])
-# serial 36 IT_PROG_INTLTOOL
+# serial 35 IT_PROG_INTLTOOL
 AC_DEFUN([IT_PROG_INTLTOOL],
 [AC_PREREQ([2.50])dnl
 
@@ -36,7 +36,7 @@
 esac
 
 if test -n "$1"; then
-    AC_MSG_CHECKING([for intltool >= $1])
+    AC_MSG_CHECKING(for intltool >= $1)
 
     INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'`
     INTLTOOL_APPLIED_VERSION=`awk -F\" '/\\$VERSION / { print $ 2; }' ${ac_aux_dir}/intltool-update.in`
@@ -65,7 +65,6 @@
   INTLTOOL_SCHEMAS_RULE='%.schemas:   %.schemas.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
     INTLTOOL_THEME_RULE='%.theme:     %.theme.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
     INTLTOOL_SERVICE_RULE='%.service: %.service.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
-   INTLTOOL_POLICY_RULE='%.policy:    %.policy.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
 
 AC_SUBST(INTLTOOL_DESKTOP_RULE)
 AC_SUBST(INTLTOOL_DIRECTORY_RULE)
@@ -85,7 +84,6 @@
 AC_SUBST(INTLTOOL_SCHEMAS_RULE)
 AC_SUBST(INTLTOOL_THEME_RULE)
 AC_SUBST(INTLTOOL_SERVICE_RULE)
-AC_SUBST(INTLTOOL_POLICY_RULE)
 
 # Use the tools built into the package, not the ones that are installed.
 AC_SUBST(INTLTOOL_EXTRACT, '$(top_builddir)/intltool-extract')
@@ -108,16 +106,19 @@
    fi
 fi
 
+AC_PATH_PROG(INTLTOOL_ICONV, iconv, iconv)
+AC_PATH_PROG(INTLTOOL_MSGFMT, msgfmt, msgfmt)
+AC_PATH_PROG(INTLTOOL_MSGMERGE, msgmerge, msgmerge)
+AC_PATH_PROG(INTLTOOL_XGETTEXT, xgettext, xgettext)
+
 # Substitute ALL_LINGUAS so we can use it in po/Makefile
 AC_SUBST(ALL_LINGUAS)
 
 # Set DATADIRNAME correctly if it is not set yet
 # (copied from glib-gettext.m4)
 if test -z "$DATADIRNAME"; then
-  AC_LINK_IFELSE(
-    [AC_LANG_PROGRAM([[]],
-                     [[extern int _nl_msg_cat_cntr;
-                       return _nl_msg_cat_cntr]])],
+  AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
+                 return _nl_msg_cat_cntr],
     [DATADIRNAME=share],
     [case $host in
     *-*-solaris*)
@@ -158,6 +159,10 @@
 for file in intltool-extract intltool-merge intltool-update; do
   sed -e "s|@INTLTOOL_EXTRACT@|`pwd`/intltool-extract|g" \
       -e "s|@INTLTOOL_LIBDIR@|${INTLTOOL_LIBDIR}|g" \
+      -e "s|@INTLTOOL_ICONV@|${INTLTOOL_ICONV}|g" \
+      -e "s|@INTLTOOL_MSGFMT@|${INTLTOOL_MSGFMT}|g" \
+      -e "s|@INTLTOOL_MSGMERGE@|${INTLTOOL_MSGMERGE}|g" \
+      -e "s|@INTLTOOL_XGETTEXT@|${INTLTOOL_XGETTEXT}|g" \
       -e "s|@INTLTOOL_PERL@|${INTLTOOL_PERL}|g" \
 	< ${ac_aux_dir}/${file}.in > ${file}.out
   if cmp -s ${file} ${file}.out 2>/dev/null; then
@@ -172,7 +177,9 @@
 ],
 [INTLTOOL_PERL='${INTLTOOL_PERL}' ac_aux_dir='${ac_aux_dir}'
 prefix="$prefix" exec_prefix="$exec_prefix" INTLTOOL_LIBDIR="$libdir" 
-INTLTOOL_EXTRACT='${INTLTOOL_EXTRACT}'])
+INTLTOOL_EXTRACT='${INTLTOOL_EXTRACT}' INTLTOOL_ICONV='${INTLTOOL_ICONV}'
+INTLTOOL_MSGFMT='${INTLTOOL_MSGFMT}' INTLTOOL_MSGMERGE='${INTLTOOL_MSGMERGE}'
+INTLTOOL_XGETTEXT='${INTLTOOL_XGETTEXT}'])
 
 ])
 
Index: conduit/dataproviders/YouTubeModule/YouTubeModule.py
===================================================================
--- conduit/dataproviders/YouTubeModule/YouTubeModule.py	(revision 825)
+++ conduit/dataproviders/YouTubeModule/YouTubeModule.py	(working copy)
@@ -29,14 +29,6 @@
     "YouTubeSource" : { "type": "dataprovider" }    
 }
 
-class YouTubeEntry:
-    Title = ""
-    Url = ""
-    def __init__ (self, title, url):
-        self.Title = title
-        self.Url = url
-
-
 class YouTubeSource(DataProvider.DataSource):
 
     _name_ = _("YouTube")
@@ -47,37 +39,109 @@
     _out_type_ = "file"
     _icon_ = "youtube"
 
+    #feeds_url
+    _const_feed_most_viewed_ = "http://gdata.youtube.com/feeds/standardfeeds/most_viewed?time=today";
+    _const_feed_top_rated_ = "http://gdata.youtube.com/feeds/standardfeeds/top_rated?time=today";
+    _const_feed_upload_by_ = "http://gdata.youtube.com/feeds/videos?author=%s";
+    _const_feed_favorites_ = "http://gdata.youtube.com/feeds/users/%s/favorites";
+
+    #Config args
+    max = 0
+    #filter type {0 = mostviewed, 1 = toprated, 2 = user}
+    filter_type = 0
+    #filter user type {0 = upload, 1 = favorites}
+    user_filter_type = 0
+    username = ""
+    
+
     def __init__(self, *args):
         DataProvider.DataSource.__init__(self)
-        
-        self.feedUrl = "http://gdata.youtube.com/feeds/standardfeeds/top_rated?time=today";
-        #self.feedUrl = ""
         self.entries = None
 
     def initialize(self):
         return True
 
     def configure(self, window):
-        return None
+        tree = Utils.dataprovider_glade_get_widget (
+                __file__,
+                "config.glade",
+                "YouTubeSourceConfigDialog") 
 
+        dlg = tree.get_widget ("YouTubeSourceConfigDialog")
+        mostviewedRb = tree.get_widget("mostviewed")
+        topratedRb = tree.get_widget("toprated")
+        byuserRb = tree.get_widget("byuser")
+        user_frame = tree.get_widget("frame")
+        uploadedbyRb = tree.get_widget("uploadedby")
+        favoritesofRb = tree.get_widget("favoritesof")
+        user = tree.get_widget("user")
+        maxdownloads = tree.get_widget("maxdownloads")
+
+        byuserRb.connect("toggled", self._filter_user_toggled_cb, user_frame)
+
+        if self.filter_type == 0:
+            mostviewedRb.set_active(True)
+        elif self.filter_type == 1:
+            topratedRb.set_active(True)
+        else:
+            byuserRb.set_active(True)
+            user_frame.set_sensitive(True)
+            if self.user_filter_type == 0:
+                uploadedbyRb.set_active(True)
+            else:
+                favoritesofRb.set_active(True)
+            user.set_text(self.username)
+
+        logging.debug("Max")
+        logging.debug(self.max)
+        maxdownloads.set_value(self.max)
+
+        dlg.set_transient_for(window)
+        response = dlg.run()
+        if response == gtk.RESPONSE_OK:
+            if mostviewedRb.get_active():
+                self.filter_type = 0
+            elif topratedRb.get_active():
+                self.filter_type = 1
+            else:
+                self.filter_type = 2
+                if uploadedbyRb.get_active():
+                    self.user_filter_type = 0
+                else:
+                    self.user_filter_type = 1
+                self.username = user.get_text()
+            self.max = int(maxdownloads.get_value())
+        
+        dlg.destroy()
+
     def refresh(self):
         DataProvider.DataSource.refresh(self)
 
         self.entries = {}
         try:
-            logging.debug("Open")
-            url_info = urllib2.urlopen(self.feedUrl)
+            feedUrl = ""
+            if self.filter_type == 0:
+                feedUrl = self._const_feed_most_viewed_
+            elif self.filter_type == 1:
+                feedUrl = self._const_feed_top_rated_ 
+            else:
+                if self.user_filter_type == 0:
+                    feedUrl = (self._const_feed_upload_by_ %  self.username)
+                else:
+                    feedUrl = (self._const_feed_favorites_ % self.username)
+
+            if self.max > 0:
+                feedUrl = ("%s&max-results=%d" % (feedUrl, self.max))
+
+            logging.debug ("Retrieve URL: %s" % feedUrl)
+            url_info = urllib2.urlopen(feedUrl)
             if (url_info):
-                logging.debug("Parse")
                 doc = ElementTree.parse(url_info).getroot()
                 for entry in doc.findall("{http://www.w3.org/2005/Atom}entry";):
-
-
                     for c in entry.getchildren():
                         if (c.tag == "{http://www.w3.org/2005/Atom}title";):
                             title = c.text
                         if (c.tag =="{http://search.yahoo.com/mrss/}group";):
-                            logging.debug ("Has group")
                             for cc in c.getchildren():
                                 if (cc.tag == "{http://search.yahoo.com/mrss/}player";):
                                     url = cc.get("url")
@@ -95,7 +159,7 @@
         
         url = self.entries[LUID]
         logging.debug("Title: '%s', Url: '%s'"%(LUID, url))
-        video_url = self.extract_video_url (url)
+        video_url = self._extract_video_url (url)
         logging.debug ("URL: %s" % video_url)
 
         f = File.File (URI=video_url)
@@ -110,13 +174,23 @@
         self.files = None
 
     def get_configuration(self):
-        return None
+        return {
+            "filter_type" : self.filter_type,
+            "user_filter_type" : self.user_filter_type,
+            "username" : self.username,
+            "max" : self.max
+        }
+            
 
     def get_UID(self):
-        return self.feedUrl
+        return Utils.get_user_string()
 
+    #ui callbacks
+    def _filter_user_toggled_cb (self, toggle, frame):
+        frame.set_sensitive(toggle.get_active())
+
     # Generic extract step
-    def extract_video_url (self, url):
+    def _extract_video_url (self, url):
         regexp = re.compile(r'[,{]t:\'([^\']*)\'')
 
         try:
Index: conduit/dataproviders/YouTubeModule/Makefile.am
===================================================================
--- conduit/dataproviders/YouTubeModule/Makefile.am	(revision 825)
+++ conduit/dataproviders/YouTubeModule/Makefile.am	(working copy)
@@ -1,5 +1,8 @@
 conduit_handlersdir = $(libdir)/conduit/dataproviders/YouTubeModule
 conduit_handlers_PYTHON = YouTubeModule.py
 
+conduit_handlers_DATA = config.glade
+EXTRA_DIST = config.glade
+
 clean-local:
 	rm -rf *.pyc *.pyo

Attachment: config.glade
Description: application/glade



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