conduit r1265 - in trunk: . conduit/modules/FspotModule



Author: thomasvm
Date: Sun Jan 27 19:48:42 2008
New Revision: 1265
URL: http://svn.gnome.org/viewvc/conduit?rev=1265&view=rev

Log:
2008-01-24  Thomas Van Machelen <thomas vanmachelen gmail com>:
	* conduit/modules/FspotModule.py:
	* conduit/modules/FspotDbusModule.py: Move the dbus dataprovider in
	the FspotModule.py file, remove the old file.  No longer load the
	FSpotSource dataprovider, but always load the FSpotDBusTwoWay and
	error on refresh when the dbus interface is not there.  This more or
	less fixes #512146.  (Thx for J. Stowers for the original patch)


Removed:
   trunk/conduit/modules/FspotModule/FspotDbusModule.py
Modified:
   trunk/ChangeLog
   trunk/conduit/modules/FspotModule/FspotModule.py

Modified: trunk/conduit/modules/FspotModule/FspotModule.py
==============================================================================
--- trunk/conduit/modules/FspotModule/FspotModule.py	(original)
+++ trunk/conduit/modules/FspotModule/FspotModule.py	Sun Jan 27 19:48:42 2008
@@ -1,37 +1,279 @@
 import os
 import gobject
+import dbus
 import logging
 log = logging.getLogger("modules.Fspot")
 
-try:
-    #python 2.4
-    from pysqlite2 import dbapi2 as sqlite
-except ImportError:
-    #python 2.5
-    from sqlite3 import dbapi2 as sqlite
-
 import conduit
 import conduit.Utils as Utils
 import conduit.Exceptions as Exceptions
 import conduit.dataproviders.DataProvider as DataProvider
 import conduit.datatypes.Photo as Photo
+from conduit.datatypes import Rid
+import conduit.dataproviders.Image as Image
 
 from gettext import gettext as _
 
 MODULES = {
-	"FspotSource" : { "type": "dataprovider" }
+	"FSpotDbusTwoWay" :     { "type": "dataprovider"    },
+	# "FspotSource" : { "type": "dataprovider" }
 }
 
 NAME_IDX = 0
 ID_IDX = 1
 
-PHOTO_DB = os.path.join(os.path.expanduser("~"),".gnome2", "f-spot", "photos.db")
-
 # check if path exists
-if not os.path.exists(PHOTO_DB):
-    raise Exceptions.NotSupportedError("No F-Spot database found")
+# PHOTO_DB = os.path.join(os.path.expanduser("~"),".gnome2", "f-spot", "photos.db")
+# 
+# if not os.path.exists(PHOTO_DB):
+#     raise Exceptions.NotSupportedError("No F-Spot database found")
+ 
+class FSpotDbusTwoWay(Image.ImageTwoWay):
+    _name_ = _("F-Spot Photos")
+    _description_ = _("Sync your F-Spot photos")
+    _category_ = conduit.dataproviders.CATEGORY_PHOTOS
+    _icon_ = "f-spot"
+
+    SERVICE_PATH = "org.gnome.FSpot"
+    PHOTOREMOTE_IFACE = "org.gnome.FSpot.PhotoRemoteControl"
+    PHOTOREMOTE_PATH = "/org/gnome/FSpot/PhotoRemoteControl"
+
+    TAGREMOTE_IFACE = "org.gnome.FSpot.TagRemoteControl"
+    TAGREMOTE_PATH = "/org/gnome/FSpot/TagRemoteControl"
+
+    def __init__(self, *args):
+        Image.ImageTwoWay.__init__(self)
+        self.need_configuration(True)
+
+        self.enabledTags = []
+        self.photos = []
+        self.has_roll = False
+        self.photo_remote = None
+        self.tag_remote = None
+
+        self._connect_to_fspot()
+
+        self._hookup_signal_handlers()
+
+    def _connect_to_fspot(self):
+        bus = dbus.SessionBus()
+        if Utils.dbus_service_available(FSpotDbusTwoWay.SERVICE_PATH, bus):
+            if self.photo_remote == None:
+                try:
+                    remote_object = bus.get_object(FSpotDbusTwoWay.SERVICE_PATH, FSpotDbusTwoWay.PHOTOREMOTE_PATH)
+                    self.photo_remote = dbus.Interface(remote_object, FSpotDbusTwoWay.PHOTOREMOTE_IFACE)
+                except dbus.exceptions.DBusException:
+                    print "*"*34
+                    self.photo_remote = None
+
+            if self.tag_remote == None:
+                try:
+                    remote_object = bus.get_object(FSpotDbusTwoWay.SERVICE_PATH, FSpotDbusTwoWay.TAGREMOTE_PATH)
+                    self.tag_remote = dbus.Interface(remote_object, FSpotDbusTwoWay.TAGREMOTE_IFACE)
+                except dbus.exceptions.DBusException:
+                    print "#"*34
+                    self.tag_remote = None
+
+        #need both tag and photo remote to be OK
+        return self.tag_remote != None and self.photo_remote != None
+
+    def _hookup_signal_handlers(self):
+        """
+        This makes sure the photo remotes are set to none when f-spot is closed.
+        """
+        bus = dbus.SessionBus()
+        bus.add_signal_receiver(self.handle_photoremote_down, dbus_interface=FSpotDbusTwoWay.PHOTOREMOTE_IFACE, signal_name="RemoteDown") 
+
+    def _get_all_tags(self):
+        return self.tag_remote.GetTagNames ()
+
+    def initialize(self):
+        return True
+        
+    def refresh(self):
+        Image.ImageTwoWay.refresh(self)
+        self.photos = []
+        if self._connect_to_fspot():
+            self.photos = self.photo_remote.Query (self.enabledTags)
+        else:
+            raise Exceptions.RefreshError("FSpot not available")
+        
+    def get_all(self):
+        """
+        return the list of photo id's
+        """
+        Image.ImageTwoWay.get_all(self)
+        return [str(photo_id) for photo_id in self.photos]
+
+    def get(self, LUID):
+        """
+        Get the File object for a file with a given id
+        """
+        Image.ImageTwoWay.get(self, LUID)
+
+        properties = self.photo_remote.GetPhotoProperties (LUID)
+        
+        #FIXME: Oh python-dbus, why wont you marshall dbus.String to str...
+        photouri =  str(properties['Uri'])
+        tags =      str(properties['Tags']).split(',')
+
+        f = Photo.Photo(URI=photouri)
+        f.set_UID(LUID)
+        f.set_open_URI(photouri)
+        f.set_tags(tags)
+        return f
+
+    def _upload_photo (self, uploadInfo):
+        """
+        Import a file into the f-spot catalog
+        """
+        # Check if remote is read only
+        if self.photo_remote.IsReadOnly ():
+            raise Exceptions.SyncronizeError (_("F-Spot DBus interface is operating in read only mode"))
+
+        # create roll if necessary
+        if not self.has_roll:
+            self.prepare_roll ()
+
+        # start with enabled tags from gui, they exist in fspot for sure
+        tags = list(self.enabledTags)
+
+        # add tags from upload info
+        for tag in uploadInfo.tags:
+            try:
+                self.tag_remote.GetTagByName (tag)
+            except:
+                self.tag_remote.CreateTag (tag)
+            tags.append (tag)
+
+        # import the photo
+        try:
+            id = self.photo_remote.ImportPhoto (uploadInfo.url, True, tags)
+            return Rid(uid=str(id))
+        except:
+            raise Exceptions.SynchronizeError ('Import Failed')
+
+    def delete(self, LUID):
+        """
+        Remove the photo from the f-spot catalog
+        TODO: add support for deleting from drive also
+        """
+        try:
+            self.photo_remote.RemovePhoto (LUID)
+        except Exception, ex: # the photo is probably gone in f-spot
+            log.warn("Delete failed (%s)", ex)
+    
+    def finish(self, aborted, error, conflict):
+        """
+        Round up, and don't forget the finish the import roll
+        """
+        Image.ImageTwoWay.finish(self)
+        self.photos = []
+        self.finish_roll ()
+
+    def prepare_roll (self):
+        self.photo_remote.PrepareRoll ()
+        self.has_roll = True
+
+    def finish_roll (self):
+        if not self.has_roll:
+            return
+
+        self.photo_remote.FinishRoll ()
+        self.has_roll = False
+
+    def handle_photoremote_down(self):
+        self.photo_remote = None
+        self.tag_remote = None
+
+    def configure(self, window):
+        import gtk
+        def col1_toggled_cb(cell, path, model ):
+            #not because we get this cb before change state
+            checked = not cell.get_active()
+
+            model[path][1] = checked
+            val = model[path][NAME_IDX]
+
+            if checked and val not in self.enabledTags:
+                self.enabledTags.append(val)
+            elif not checked and val in self.enabledTags:
+                self.enabledTags.remove(val)
+
+            log.debug("Toggle '%s'(%s) to: %s" % (model[path][NAME_IDX], val, checked))
+            return
+
+        #Fspot must be running
+        if not self._connect_to_fspot():
+            return
+
+        tree = Utils.dataprovider_glade_get_widget(
+                        __file__, 
+                        "config.glade",
+						"FspotConfigDialog"
+						)
+        tagtreeview = tree.get_widget("tagtreeview")
+        #Build a list of all the tags
+        list_store = gtk.ListStore(gobject.TYPE_STRING,    #NAME_IDX
+                                   gobject.TYPE_BOOLEAN,   #active
+                                  )
+        #Fill the list store
+        i = 0
+        for tag in self._get_all_tags():
+            list_store.append((tag,tag in self.enabledTags))
+            i += 1
+        #Set up the treeview
+        tagtreeview.set_model(list_store)
+        #column 1 is the tag name
+        tagtreeview.append_column(  gtk.TreeViewColumn(_("Tag Name"), 
+                                    gtk.CellRendererText(), 
+                                    text=NAME_IDX)
+                                    )
+        #column 2 is a checkbox for selecting the tag to sync
+        renderer1 = gtk.CellRendererToggle()
+        renderer1.set_property('activatable', True)
+        renderer1.connect( 'toggled', col1_toggled_cb, list_store )
+        tagtreeview.append_column(  gtk.TreeViewColumn(_("Enabled"), 
+                                    renderer1, 
+                                    active=1)
+                                    )
+
+        dlg = tree.get_widget("FspotConfigDialog")
+        dlg.set_transient_for(window)
+
+        response = dlg.run()
+        if response == True:
+            self.set_configured(True)
+        dlg.destroy()
+
+    def set_configuration(self, config):
+        self.enabledTags = []
+        for tag in config.get("tags", []):
+            self.enabledTags.append(str(tag))
+
+        self.set_configured(True)
+            
+    def get_configuration(self):
+        return {"tags": self.enabledTags}
+
+    def is_configured (self):
+        return True
+
+    def get_UID(self):
+        return Utils.get_user_string()
 
 class FspotSource(DataProvider.DataSource):
+    """
+    This is the obsolete class that queried the default f-spot db
+    for photos; this is now obsolete by the use of the above dbus
+    based f-spot twoway dataprovider
+    """
+    try:
+        #python 2.4
+        from pysqlite2 import dbapi2 as sqlite
+    except ImportError:
+        #python 2.5
+        from sqlite3 import dbapi2 as sqlite
 
     _name_ = _("F-Spot Photos")
     _description_ = _("Sync your F-Spot photos")



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