conduit r1882 - in trunk: . conduit po tools/eog-plugin tools/nautilus-extension tools/totem-plugin
- From: jstowers svn gnome org
- To: svn-commits-list gnome org
- Subject: conduit r1882 - in trunk: . conduit po tools/eog-plugin tools/nautilus-extension tools/totem-plugin
- Date: Fri, 20 Feb 2009 06:23:39 +0000 (UTC)
Author: jstowers
Date: Fri Feb 20 06:23:38 2009
New Revision: 1882
URL: http://svn.gnome.org/viewvc/conduit?rev=1882&view=rev
Log:
2009-02-20 John Stowers <john stowers gmail com>
* conduit/Makefile.am:
* conduit/libconduit.py: Create a common python
library which handles a remote conduit instance
via DBus.
* tools/eog-plugin/conduit.py:
* tools/nautilus-extension/conduit.py:
* tools/totem-plugin/conduit.py: Use this new common
library for considerable code savings.
* tools/eog-plugin/config.glade:
* tools/eog-plugin/Makefile.am: Delete config.glade, it
was not used.
Added:
trunk/conduit/libconduit.py
Removed:
trunk/tools/eog-plugin/config.glade
Modified:
trunk/ChangeLog
trunk/conduit/Makefile.am
trunk/po/POTFILES.skip
trunk/tools/eog-plugin/Makefile.am
trunk/tools/eog-plugin/conduit.py
trunk/tools/nautilus-extension/conduit.py
trunk/tools/totem-plugin/conduit.py
Modified: trunk/conduit/Makefile.am
==============================================================================
--- trunk/conduit/Makefile.am (original)
+++ trunk/conduit/Makefile.am Fri Feb 20 06:23:38 2009
@@ -19,6 +19,7 @@
__init__.py \
Knowledge.py \
Logging.py \
+ libconduit.py \
Main.py \
MappingDB.py \
Module.py \
Added: trunk/conduit/libconduit.py
==============================================================================
--- (empty file)
+++ trunk/conduit/libconduit.py Fri Feb 20 06:23:38 2009
@@ -0,0 +1,306 @@
+import os
+import gobject
+import gtk
+import dbus, dbus.glib
+
+APPLICATION_DBUS_IFACE="org.conduit.Application"
+CONDUIT_DBUS_IFACE="org.conduit.Conduit"
+EXPORTER_DBUS_IFACE="org.conduit.Exporter"
+DATAPROVIDER_DBUS_IFACE="org.conduit.DataProvider"
+SYNCSET_DBUS_IFACE="org.conduit.SyncSet"
+
+SYNCSET_GUI_PATH = '/syncset/gui'
+SYNCSET_NOGUI_PATH = '/syncset/dbus'
+
+class ConduitWrapper:
+
+ CONFIG_PATH='~/.conduit/test-plugin'
+ NAME_IDX=0
+ URI_IDX=1
+ STATUS_IDX=2
+ PB_IDX=3
+
+ def __init__(self, conduit, name, store):
+ self.conduit = conduit
+ self.name = name
+ self.store = store
+ self.rowref = None
+ self.configured = False
+ self.pendingSync = False
+
+ self.conduit.connect_to_signal(
+ "SyncProgress",
+ self._on_sync_progress,
+ dbus_interface=CONDUIT_DBUS_IFACE
+ )
+ self.conduit.connect_to_signal(
+ "SyncCompleted",
+ self._on_sync_completed,
+ dbus_interface=CONDUIT_DBUS_IFACE
+ )
+ self.conduit.connect_to_signal(
+ "SyncStarted",
+ self._on_sync_started,
+ dbus_interface=CONDUIT_DBUS_IFACE
+ )
+
+ def _get_configuration(self):
+ """
+ Gets the latest configuration for a given
+ dataprovider
+ """
+ config_path = os.path.expanduser(self.CONFIG_PATH)
+
+ if not os.path.exists(os.path.join(config_path, self.name)):
+ return
+
+ f = open(os.path.join(config_path, self.name), 'r')
+ xml = f.read()
+ f.close()
+
+ return xml
+
+ def _save_configuration(self, xml):
+ """
+ Saves the configuration XML from a given dataprovider again
+ """
+ config_path = os.path.expanduser(self.CONFIG_PATH)
+
+ if not os.path.exists(config_path):
+ os.mkdir(config_path)
+
+ f = open(os.path.join(config_path, self.name), 'w')
+ f.write(xml)
+ f.close()
+
+ def _get_rowref(self):
+ if self.rowref == None:
+ self.add_rowref()
+ return self.rowref
+
+ def _configure_reply_handler(self):
+ #save the configuration
+ xml = self.conduit.SinkGetConfigurationXml()
+ self._save_configuration(xml)
+ self.configured = True
+
+ #check if a sync was waiting for the conduit (sink) to be configured
+ if self.pendingSync == True:
+ self.pendingSync = False
+ self.conduit.Sync(dbus_interface=CONDUIT_DBUS_IFACE)
+
+ def _configure_error_handler(self, error):
+ pass
+
+ def _on_sync_started(self):
+ self.store.set_value(self._get_rowref(), self.STATUS_IDX, "uploading")
+
+ def _on_sync_progress(self, progress, uids):
+ uris = [str(i) for i in uids]
+ delete = []
+
+ treeiter = self.store.iter_children(self._get_rowref())
+ while treeiter:
+ if self.store.get_value(treeiter, self.URI_IDX) in uris:
+ delete.append(treeiter)
+ treeiter = self.store.iter_next(treeiter)
+
+ for d in delete:
+ self.store.remove(d)
+
+ #for uri in uids:
+ # rowref = self._get_rowref_for_photo(str(uri))
+ # print "\t%s - %s" % (uri, rowref)
+ # print "\t",self.photoRefs
+
+ def _on_sync_completed(self, abort, error, conflict):
+ rowref = self._get_rowref()
+ if abort == False and error == False:
+ self.clear()
+ #update the status
+ self.store.set_value(rowref, self.STATUS_IDX, "finished")
+ else:
+ #show the error message in the conduit gui
+ self.store.set_value(rowref, self.STATUS_IDX, "error")
+
+ def _add_uri(self, uri):
+ return self.conduit.AddData(uri, dbus_interface=EXPORTER_DBUS_IFACE)
+
+ def _add_item(self, filename, uri, status, pixbuf):
+ rowref = self._get_rowref()
+ self.store.append(rowref,(
+ filename, #ConduitWrapper.NAME_IDX
+ uri, #ConduitWrapper.URI_IDX
+ status, #ConduitWrapper.STATUS_IDX
+ pixbuf) #ConduitWrapper.PB_IDX
+ )
+
+ def _add_rowref(self, name, uri, status, pixbuf):
+ self.rowref = self.store.append(None,(
+ name, #ConduitWrapper.NAME_IDX
+ uri, #ConduitWrapper.URI_IDX
+ status, #ConduitWrapper.STATUS_IDX
+ pixbuf) #ConduitWrapper.PB_IDX
+ )
+
+ def clear(self):
+ rowref = self._get_rowref()
+ #delete all the items from the list of items to upload
+ delete = []
+ child = self.store.iter_children(rowref)
+ while child != None:
+ delete.append(child)
+ child = self.store.iter_next(child)
+ #need to do in two steps so we dont modify the store while iterating
+ for d in delete:
+ self.store.remove(d)
+
+ def sync(self):
+ if self.configured == True:
+ self.conduit.Sync(dbus_interface=CONDUIT_DBUS_IFACE)
+ else:
+ #defer the sync until the conduit has been configured
+ self.pendingSync = True
+ #configure the sink and perform the actual synchronisation
+ #when the configuration is finished, this way the GUI doesnt
+ #block on the call
+ self.conduit.SinkConfigure(
+ reply_handler=self._configure_reply_handler,
+ error_handler=self._configure_error_handler,
+ dbus_interface=EXPORTER_DBUS_IFACE
+ )
+
+ def add_item(self, pixbuf, uri):
+ if self._add_uri(uri):
+ #add to the store
+ self._add_item(
+ filename=uri.split("/")[-1],
+ uri=uri,
+ status="",
+ pixbuf=pixbuf
+ )
+
+ def add_rowref(self):
+ raise NotImplementedError
+
+class ConduitApplicationWrapper(gobject.GObject):
+
+ __gsignals__ = {
+ "conduit-started" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, [gobject.TYPE_BOOLEAN]),
+ }
+
+ def __init__(self, conduitWrapperKlass, store=True, debug=False):
+ gobject.GObject.__init__(self)
+ self.conduitWrapperKlass = conduitWrapperKlass
+ self.debug = debug
+ self.app = None
+ self.conduits = {}
+ self.dps = []
+
+ if store:
+ #the liststore with icons of the images to be uploaded
+ self.store = gtk.TreeStore(
+ str, #ConduitWrapper.NAME_IDX
+ str, #ConduitWrapper.URI_IDX
+ str, #ConduitWrapper.STATUS_IDX
+ gtk.gdk.Pixbuf #ConduitWrapper.PB_IDX
+ )
+
+ self.dbus_iface = dbus.Interface(
+ dbus.SessionBus().get_object('org.freedesktop.DBus', '/org/freedesktop/DBus'),
+ 'org.freedesktop.DBus'
+ )
+ self.dbus_iface.connect_to_signal("NameOwnerChanged", self._on_name_owner_changed)
+
+ def _debug(self, msg):
+ if self.debug:
+ print "CON: ", msg
+
+ def _get_conduit_app(self):
+ try:
+ self.app = dbus.Interface(
+ dbus.SessionBus().get_object(APPLICATION_DBUS_IFACE,"/"),
+ APPLICATION_DBUS_IFACE
+ )
+ except dbus.exceptions.DBusException:
+ self._debug("Could not connect to conduit")
+ self.app = None
+ return self.app
+
+ def _get_available_dps(self):
+ if self.app != None:
+ self.dps = self.app.GetAllDataProviders()
+
+ def _on_name_owner_changed(self, name, oldOwner, newOwner):
+ if name == APPLICATION_DBUS_IFACE:
+ if self.dbus_iface.NameHasOwner(APPLICATION_DBUS_IFACE):
+ self._get_conduit_app()
+ self._get_available_dps()
+ self._debug("Conduit started")
+ else:
+ self._debug("Conduit stopped")
+ self.app = None
+ self.dps = []
+ self.emit("conduit-started", self.connected())
+
+ def build_conduit(self, sinkName):
+ a = self.get_dataproviders()
+ if sinkName in a:
+ realName = a[sinkName]
+ self._debug("Building exporter conduit %s (%s)" % (sinkName, realName))
+ path = self.app.BuildExporter(realName)
+ exporter = dbus.SessionBus().get_object(CONDUIT_DBUS_IFACE,path)
+ self.conduits[sinkName] = self.conduitWrapperKlass(
+ conduit=exporter,
+ name=sinkName,
+ store=self.store
+ )
+ else:
+ self._debug("Could not build Conduit %s" % sinkName)
+
+ def get_application(self):
+ return self.app
+
+ def get_dataproviders(self):
+ #Split of the key part of the name
+ a = {}
+ for n in self.dps:
+ a[n.split(":")[0]] = str(n)
+ return a
+
+ def upload(self, name, uri, pixbuf):
+ if self.connected():
+ if name not in self.conduits:
+ self.build_conduit(name)
+
+ if uri != None:
+ self.conduits[name].add_item(
+ pixbuf=pixbuf,
+ uri=uri
+ )
+
+ def connect_to_conduit(self, startConduit):
+ #check if conduit is running
+ if self.dbus_iface.NameHasOwner(APPLICATION_DBUS_IFACE):
+ self._debug("Conduit already running")
+ self._get_conduit_app()
+ self._get_available_dps()
+ return True
+ elif startConduit:
+ self._debug("Starting conduit via DBus activation")
+ self.dbus_iface.StartServiceByName(APPLICATION_DBUS_IFACE, 0)
+ return False
+
+ def sync(self):
+ if self.connected():
+ for c in self.conduits:
+ self.conduits[c].sync()
+
+ def clear(self):
+ if self.connected():
+ for c in self.conduits:
+ self.conduits[c].clear()
+
+ def connected(self):
+ return self.app != None
+
Modified: trunk/po/POTFILES.skip
==============================================================================
--- trunk/po/POTFILES.skip (original)
+++ trunk/po/POTFILES.skip Fri Feb 20 06:23:38 2009
@@ -1,9 +1,9 @@
conduit/Main.py
+conduit/libconduit.py
data/conduit.desktop.in
-tools/eog-plugin/config.glade
+tools/eog-plugin/conduit.py
tools/totem-plugin/conduit.py
tools/test-db-wrapper/main.glade
-tools/test-db-wrapper/main.glade
conduit/modules/GoogleModule/contacts-config.glade
conduit/modules/SynceModule.py
conduit/modules/SettingsModule/GConfUtils.py
Modified: trunk/tools/eog-plugin/Makefile.am
==============================================================================
--- trunk/tools/eog-plugin/Makefile.am (original)
+++ trunk/tools/eog-plugin/Makefile.am Fri Feb 20 06:23:38 2009
@@ -1,10 +1,9 @@
if ENABLE_EOG_PLUGIN
nautextdir = $(EOG_PLUGIN_DIR)
- nautext_DATA = conduit.py conduit.eog-plugin config.glade
+ nautext_DATA = conduit.py conduit.eog-plugin
endif
EXTRA_DIST = \
conduit.py \
conduit.eog-plugin \
- config.glade \
README
Modified: trunk/tools/eog-plugin/conduit.py
==============================================================================
--- trunk/tools/eog-plugin/conduit.py (original)
+++ trunk/tools/eog-plugin/conduit.py Fri Feb 20 06:23:38 2009
@@ -1,19 +1,16 @@
import os
import eog
-import gtk, gtk.glade
+import gtk
import dbus, dbus.glib
-#if this code is a bit convoluted and jumps around a lot
-#it is because I lazy initialize everything to minimise
-#the work that occurs at startup time
-
-APPLICATION_DBUS_IFACE="org.conduit.Application"
-CONDUIT_DBUS_IFACE="org.conduit.Conduit"
-EXPORTER_DBUS_IFACE="org.conduit.Exporter"
-DATAPROVIDER_DBUS_IFACE="org.conduit.DataProvider"
+try:
+ import libconduit
+except ImportError:
+ import conduit.libconduit as libconduit
+DEBUG = True
+ICON_SIZE = 24
MENU_PATH="/MainMenu/ToolsMenu/ToolsOps_2"
-
SUPPORTED_SINKS = {
"FlickrTwoWay" : "Upload to Flickr",
"PicasaTwoWay" : "Upload to Picasa",
@@ -21,263 +18,56 @@
"ShutterflySink" : "Upload to Shutterfly",
"BoxDotNetTwoWay" : "Upload to Box.net",
"FacebookSink" : "Upload to Facebook",
- "IPodPhotoSink" : "Add to iPod",
-# "TestImageSink" : "Test"
+ "IPodPhotoSink" : "Add to iPod"
}
+if DEBUG:
+ SUPPORTED_SINKS["TestImageSink"] = "Test"
-ICON_SIZE = 24
-
-CONFIG_PATH='~/.conduit/eog-plugin'
-
-PB_IDX=0
-NAME_IDX=1
-URI_IDX=2
-STATUS_IDX=3
-
-class ConduitWrapper:
- def __init__(self, conduit, name, store):
- self.conduit = conduit
- self.name = name
- self.store = store
- self.rowref = None
- self.configured = False
- self.pendingSync = False
-
- self.conduit.connect_to_signal(
- "SyncProgress",
- self._on_sync_progress,
- dbus_interface=CONDUIT_DBUS_IFACE
- )
- self.conduit.connect_to_signal(
- "SyncCompleted",
- self._on_sync_completed,
- dbus_interface=CONDUIT_DBUS_IFACE
- )
- self.conduit.connect_to_signal(
- "SyncStarted",
- self._on_sync_started,
- dbus_interface=CONDUIT_DBUS_IFACE
- )
-
- def _get_configuration(self):
- """
- Gets the latest configuration for a given
- dataprovider
- """
- config_path = os.path.expanduser(CONFIG_PATH)
-
- if not os.path.exists(os.path.join(config_path, self.name)):
- return
-
- f = open(os.path.join(config_path, self.name), 'r')
- xml = f.read ()
- f.close()
-
- return xml
-
- def _save_configuration(self, xml):
- """
- Saves the configuration xml from a given dataprovider again
- """
- config_path = os.path.expanduser(CONFIG_PATH)
-
- if not os.path.exists(config_path):
- os.mkdir(config_path)
-
- f = open(os.path.join(config_path, self.name), 'w')
- f.write(xml)
- f.close()
-
- def _get_rowref(self):
- if self.rowref == None:
- #store the rowref in the store with the icon conduit gave us
- info = self.conduit.SinkGetInformation(dbus_interface=EXPORTER_DBUS_IFACE)
- pb = gtk.gdk.pixbuf_new_from_file_at_size(info['icon_path'], ICON_SIZE, ICON_SIZE)
- desc = SUPPORTED_SINKS[self.name]
- self.rowref = self.store.append(None,(
- pb, #PB_IDX
- desc, #NAME_IDX
- "", #URI_IDX
- "ready") #STATUS_IDX
- )
- return self.rowref
-
- def _configure_reply_handler(self):
- #save the configuration
- xml = self.conduit.SinkGetConfigurationXml()
- self._save_configuration(xml)
- self.configured = True
-
- #check if a sync was waiting for the conduit (sink) to be configured
- if self.pendingSync == True:
- self.pendingSync = False
- self.conduit.Sync(dbus_interface=CONDUIT_DBUS_IFACE)
-
- def _configure_error_handler(self, error):
- pass
-
- def _on_sync_started(self):
- self.store.set_value(self._get_rowref(), STATUS_IDX, "uploading")
-
- def _on_sync_progress(self, progress, uids):
- uris = [str(i) for i in uids]
- delete = []
-
- treeiter = self.store.iter_children(self._get_rowref())
- while treeiter:
- if self.store.get_value(treeiter, URI_IDX) in uris:
- delete.append(treeiter)
- treeiter = self.store.iter_next(treeiter)
-
- for d in delete:
- self.store.remove(d)
-
- #for uri in uids:
- # rowref = self._get_rowref_for_photo(str(uri))
- # print "\t%s - %s" % (uri, rowref)
- # print "\t",self.photoRefs
-
- def _on_sync_completed(self, abort, error, conflict):
- rowref = self._get_rowref()
- if abort == False and error == False:
- self.clear()
- #update the status
- self.store.set_value(rowref, STATUS_IDX, "finished")
- else:
- #show the error message in the conduit gui
- self.store.set_value(rowref, STATUS_IDX, "error")
-
- def clear(self):
- rowref = self._get_rowref()
- #Delete all the images from the list of images to upload
- delete = []
- child = self.store.iter_children(rowref)
- while child != None:
- delete.append(child)
- child = self.store.iter_next(child)
- #need to do in two steps so we dont modify the store while
- #iterating
- for d in delete:
- self.store.remove(d)
-
- def add_photo(self, pixbuf, uri):
- ok = self.conduit.AddData(uri,dbus_interface=EXPORTER_DBUS_IFACE)
- if ok == True:
- #add to the store
- rowref = self._get_rowref()
- filename = uri.split("/")[-1]
- self.store.append(rowref,(
- pixbuf, #PB_IDX
- filename, #NAME_IDX
- uri, #URI_IDX
- "") #STATUS_IDX
- )
-
- def sync(self):
- if self.configured == True:
- self.conduit.Sync(dbus_interface=CONDUIT_DBUS_IFACE)
- else:
- #defer the sync until the conduit has been configured
- self.pendingSync = True
- # configure the sink; and perform the actual synchronisation
- # when the configuration is finished, this way the eog gui doesnt
- # block on the call
- self.conduit.SinkConfigure(
- reply_handler=self._configure_reply_handler,
- error_handler=self._configure_error_handler,
- dbus_interface=EXPORTER_DBUS_IFACE
- )
-
-class ConduitApplicationWrapper:
- def __init__(self, startConduit, addToGui):
- self.addToGui = addToGui
- self.app = None
- self.conduits = {}
- #the liststore with icons of the images to be uploaded
- self.store = gtk.TreeStore(
- gtk.gdk.Pixbuf, #PB_IDX
- str, #NAME_IDX
- str, #URI_IDX
- str #STATUS_IDX
- )
-
- if startConduit:
- self.start()
- else:
- obj = self.bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
- dbus_iface = dbus.Interface(obj, 'org.freedesktop.DBus')
- if dbus_iface.NameHasOwner(APPLICATION_DBUS_IFACE):
- self.start()
- else:
- raise Exception("Could not connect to conduit")
-
- def _build_conduit(self, sinkName):
- #Split of the key part of the name
- a = {}
- for n in self.dps:
- a[n.split(":")[0]] = str(n)
-
- if sinkName in a:
- realName = a[sinkName]
- print "Building exporter conduit %s (%s)" % (sinkName, realName)
- path = self.app.BuildExporter(realName)
- exporter = dbus.SessionBus().get_object(CONDUIT_DBUS_IFACE,path)
- self.conduits[sinkName] = ConduitWrapper(conduit=exporter, name=sinkName, store=self.store)
-
- def upload(self, name, eogImage):
- if self.connected():
- if name not in self.conduits:
- self._build_conduit(name)
-
- if eogImage != None:
- #proportionally scale the pixbuf
- thumb = eogImage.get_thumbnail()
- pb = thumb.scale_simple(ICON_SIZE,ICON_SIZE,gtk.gdk.INTERP_BILINEAR)
-
- #add the photo to the remote condui and the liststore
- self.conduits[name].add_photo(
- pixbuf=pb,
- uri=eogImage.get_uri_for_display()
- )
+class EogConduitWrapper(libconduit.ConduitWrapper):
+ CONFIG_PATH='~/.conduit/eog-plugin'
- def start(self):
- if not self.connected():
- try:
- remote_object = dbus.SessionBus().get_object(APPLICATION_DBUS_IFACE,"/")
- self.app = dbus.Interface(remote_object, APPLICATION_DBUS_IFACE)
- self.dps = self.app.GetAllDataProviders()
- except dbus.exceptions.DBusException:
- self.app = None
- print "Conduit unavailable"
-
- def sync(self):
- if self.connected():
- for c in self.conduits:
- self.conduits[c].sync()
-
- def clear(self):
- if self.connected():
- for c in self.conduits:
- self.conduits[c].clear()
-
- def connected(self):
- return self.app != None
+ def add_rowref(self):
+ #store the rowref in the store with the icon conduit gave us
+ info = self.conduit.SinkGetInformation(dbus_interface=libconduit.EXPORTER_DBUS_IFACE)
+ desc = SUPPORTED_SINKS[self.name]
+ self._add_rowref(
+ name=desc,
+ uri="",
+ status="ready",
+ pixbuf=gtk.gdk.pixbuf_new_from_file_at_size(info['icon_path'], ICON_SIZE, ICON_SIZE)
+ )
class ConduitPlugin(eog.Plugin):
def __init__(self):
- self.dir = os.path.abspath(os.path.join(__file__, ".."))
- self.gladefile = os.path.join(self.dir, "config.glade")
-
- self.conduit = ConduitApplicationWrapper(
- startConduit=True,
- addToGui=False
+ self.debug = DEBUG
+ self.conduit = libconduit.ConduitApplicationWrapper(
+ conduitWrapperKlass=EogConduitWrapper,
+ store=True,
+ debug=self.debug
)
+ self.conduit.connect("conduit-started", self._on_conduit_started)
+ self.running = self.conduit.connect_to_conduit(startConduit=True)
+
+ def _debug(self, msg):
+ if self.debug:
+ print "EOG: ", msg
+
+ def _on_conduit_started(self, sender, started):
+ self._debug("Conduit started: %s" % started)
+ self.running = started
+ self.box.set_sensitive(self.running)
def _on_upload_clicked(self, sender, window):
- currentImage = window.get_image()
+ eogImage = window.get_image()
name = sender.get_property("name")
- self.conduit.upload(name, currentImage)
+
+ if eogImage != None:
+ thumb = eogImage.get_thumbnail()
+ pb = thumb.scale_simple(ICON_SIZE,ICON_SIZE,gtk.gdk.INTERP_BILINEAR)
+ uri = eogImage.get_uri_for_display()
+
+ self.conduit.upload(name, uri, pb)
def _on_sync_clicked(self, *args):
self.conduit.sync()
@@ -300,19 +90,20 @@
#the sidebar is a treeview where
#photos to upload are grouped by the
#upload service, with a clear button and
- #a upload button below
+ #an upload button below
- box = gtk.VBox()
+ self.box = gtk.VBox()
+ self.box.set_sensitive(self.running)
view = gtk.TreeView(self.conduit.store)
view.connect("row-activated", self._on_row_activated)
view.set_headers_visible(False)
- box.pack_start(view,expand=True,fill=True)
+ self.box.pack_start(view,expand=True,fill=True)
bbox = gtk.HButtonBox()
- box.pack_start(bbox,expand=False)
+ self.box.pack_start(bbox,expand=False)
#two colums, an icon and a description/name
- col0 = gtk.TreeViewColumn("Pic", gtk.CellRendererPixbuf(), pixbuf=0)
+ col0 = gtk.TreeViewColumn("Pic", gtk.CellRendererPixbuf(), pixbuf=libconduit.ConduitWrapper.PB_IDX)
view.append_column(col0)
#second colum is the dataprovider name + status, or the filename
nameRenderer = gtk.CellRendererText()
@@ -332,7 +123,7 @@
bbox.pack_start(clearbtn,expand=True)
sidebar = window.get_sidebar()
- sidebar.add_page("Photo Uploads", box)
+ sidebar.add_page("Photo Uploads", self.box)
sidebar.show_all()
def _prepare_tools_menu(self, window):
@@ -365,29 +156,25 @@
top=False)
def _name_data_func(self, column, cell_renderer, tree_model, rowref):
- name = tree_model.get_value(rowref, NAME_IDX)
+ name = tree_model.get_value(rowref, libconduit.ConduitWrapper.NAME_IDX)
#render the headers different to the data
if tree_model.iter_depth(rowref) == 0:
- status = tree_model.get_value(rowref, STATUS_IDX)
+ status = tree_model.get_value(rowref, libconduit.ConduitWrapper.STATUS_IDX)
name = '%s <span foreground="grey" style="italic">(%s)</span>' % (name,status)
cell_renderer.set_property("markup", name)
def activate(self, window):
+ self._debug("Activate")
#the sidebar and menu integration must be done once per eog window instance
- if self.conduit.connected() == True:
- self._prepare_sidebar(window)
- self._prepare_tools_menu(window)
+ self._prepare_sidebar(window)
+ self._prepare_tools_menu(window)
def deactivate(self, window):
- pass
+ self._debug("Deactivate")
def update_ui(self, window):
- pass
+ self._debug("Update UI")
def is_configurable(self):
return False
- def create_configure_dialog(self):
- xml = gtk.glade.XML(self.gladefile, "ConfigDialog")
- dlg = xml.get_widget("ConfigDialog")
- return dlg
Modified: trunk/tools/nautilus-extension/conduit.py
==============================================================================
--- trunk/tools/nautilus-extension/conduit.py (original)
+++ trunk/tools/nautilus-extension/conduit.py Fri Feb 20 06:23:38 2009
@@ -27,37 +27,27 @@
"""
import os
-
import nautilus
import dbus, dbus.glib
-# we only operate on directories
-SUPPORTED_FORMAT = 'x-directory/normal'
-
-#dbus interfaces
-APPLICATION_DBUS_IFACE='org.conduit.Application'
-DATAPROVIDER_DBUS_IFACE="org.conduit.DataProvider"
-CONDUIT_DBUS_IFACE="org.conduit.Conduit"
-SYNCSET_DBUS_IFACE="org.conduit.SyncSet"
-
-# supported sinks
+try:
+ import libconduit
+except ImportError:
+ import conduit.libconduit as libconduit
+
+DEBUG = True
+FOLDER_TWOWAY = "FolderTwoWay"
+FOLDER_TWOWAY_CONFIG = "<configuration><folder type='string'>%s</folder><folderGroupName type='string'>Home</folderGroupName><includeHidden type='bool'>False</includeHidden></configuration>"
+CONFIG_PATH = '~/.conduit/nautilus-extension'
SUPPORTED_SINKS = {
"FlickrTwoWay" : "Upload to Flickr",
"PicasaTwoWay" : "Upload to Picasa",
"SmugMugTwoWay" : "Upload to SmugMug",
"BoxDotNetTwoWay" : "Upload to Box.net",
-# "FolderTwoWay" : "Synchronize with Another Folder"
+ "FolderTwoWay" : "Synchronize with Another Folder"
}
-
-# source dataprovider
-FOLDER_TWOWAY="FolderTwoWay"
-
-# configuration stuff
-FOLDER_TWOWAY_CONFIG ="<configuration><folder type='string'>%s</folder><folderGroupName type='string'>Home</folderGroupName><includeHidden type='bool'>False</includeHidden></configuration>"
-CONFIG_PATH='~/.conduit/nautilus-extension'
-
-# add to gui or dbus
-SYNCSET_PATH = '/syncset/gui'
+if DEBUG:
+ SUPPORTED_SINKS["TestFileSink"] = "Test"
class ItemCallbackHandler:
"""
@@ -66,7 +56,7 @@
"""
def __init__ (self, sink_name, conduitApplication):
self.sink_name = sink_name
- self.app = conduitApplication
+ self.conduitApp = conduitApplication
self.conduit = None
def activate_cb(self, menu, folder):
@@ -74,7 +64,9 @@
This is the callback method that can be attached to the
activate signal of a nautilus menu
"""
- if not self.app:
+ if self.conduitApp.connected():
+ app = self.conduitApp.get_application()
+ else:
return
# it has got to be there
@@ -85,28 +77,28 @@
uri = folder.get_uri()
# check if they needed providers are available
- dps = self.app.GetAllDataProviders()
+ dps = self.conduitApp.get_dataproviders()
if not FOLDER_TWOWAY in dps and not self.sink_name in dps:
return
# create dataproviders
- folder_twoway_path = self.app.GetDataProvider(FOLDER_TWOWAY)
- sink_path = self.app.GetDataProvider(self.sink_name)
+ folder_twoway_path = app.GetDataProvider(dps[FOLDER_TWOWAY])
+ sink_path = app.GetDataProvider(dps[self.sink_name])
bus = dbus.SessionBus()
# set up folder config
- folder_twoway = bus.get_object(DATAPROVIDER_DBUS_IFACE, folder_twoway_path)
+ folder_twoway = bus.get_object(libconduit.DATAPROVIDER_DBUS_IFACE, folder_twoway_path)
folder_twoway.SetConfigurationXml(FOLDER_TWOWAY_CONFIG % uri)
# get flickr dbus object
- self.sink = bus.get_object(DATAPROVIDER_DBUS_IFACE, sink_path)
+ self.sink = bus.get_object(libconduit.DATAPROVIDER_DBUS_IFACE, sink_path)
# now create conduit
- conduit_path = self.app.BuildConduit (folder_twoway_path, sink_path)
- self.conduit = bus.get_object(CONDUIT_DBUS_IFACE, conduit_path)
- self.conduit.connect_to_signal("SyncCompleted", self.on_sync_completed, dbus_interface=CONDUIT_DBUS_IFACE)
+ conduit_path = app.BuildConduit (folder_twoway_path, sink_path)
+ self.conduit = bus.get_object(libconduit.CONDUIT_DBUS_IFACE, conduit_path)
+ self.conduit.connect_to_signal("SyncCompleted", self.on_sync_completed, dbus_interface=libconduit.CONDUIT_DBUS_IFACE)
# check if we have configuration on disk; set it on dataprovider
xml = self.get_configuration(self.sink_name)
@@ -115,8 +107,8 @@
self.sink.SetConfigurationXml(xml)
#Get the syncset
- self.ss = bus.get_object(SYNCSET_DBUS_IFACE, SYNCSET_PATH)
- self.ss.AddConduit(self.conduit, dbus_interface=SYNCSET_DBUS_IFACE)
+ self.ss = bus.get_object(libconduit.SYNCSET_DBUS_IFACE, libconduit.SYNCSET_GUI_PATH)
+ self.ss.AddConduit(self.conduit, dbus_interface=libconduit.SYNCSET_DBUS_IFACE)
# configure the sink; and perform the actual synchronisation
# when the configuration is finished
@@ -153,7 +145,7 @@
f.close()
def on_sync_completed(self, abort, error, conflict):
- self.ss.DeleteConduit(self.conduit, dbus_interface=SYNCSET_DBUS_IFACE)
+ self.ss.DeleteConduit(self.conduit, dbus_interface=libconduit.SYNCSET_DBUS_IFACE)
print "Finished"
def _configure_reply_handler(self):
@@ -168,7 +160,7 @@
self.save_configuration(self.sink_name, xml)
# do it to me, baby, real good!
- self.conduit.Sync(dbus_interface=CONDUIT_DBUS_IFACE)
+ self.conduit.Sync(dbus_interface=libconduit.CONDUIT_DBUS_IFACE)
def _configure_error_handler(self, error):
"""
@@ -181,72 +173,53 @@
This is the actual extension
"""
def __init__(self):
- obj = dbus.SessionBus().get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
- self.dbus_iface = dbus.Interface(obj, 'org.freedesktop.DBus')
- self.dbus_iface.connect_to_signal("NameOwnerChanged", self._on_name_owner_changed)
-
- self.conduitApp = None
- self.dps = []
-
- #check if conduit is running
- self._on_name_owner_changed(APPLICATION_DBUS_IFACE,'','')
-
- def _get_conduit_app (self):
- bus = dbus.SessionBus()
- try:
- remote_object = bus.get_object(APPLICATION_DBUS_IFACE,"/")
- return dbus.Interface(remote_object, APPLICATION_DBUS_IFACE)
- except dbus.exceptions.DBusException:
- print "COULD NOT CONNECT TO CONDUIT"
- return None
-
- def _populate_available_dps(self):
- if self.conduitApp != None and self.dps == []:
- for dp in self.conduitApp.GetAllDataProviders():
- if dp in SUPPORTED_SINKS:
- self.dps.append(dp)
-
- def _on_name_owner_changed(self, name, oldOwner, newOwner):
- if name == APPLICATION_DBUS_IFACE:
- if self.dbus_iface.NameHasOwner(APPLICATION_DBUS_IFACE):
- self.conduitApp = self._get_conduit_app()
- print "Conduit Started"
- else:
- print "Conduit Stopped"
- self.conduitApp = None
-
- def get_file_items(self, window, files):
- if self.conduitApp == None:
- return
+ self.debug = DEBUG
+ self.conduit = libconduit.ConduitApplicationWrapper(
+ conduitWrapperKlass=None,
+ store=False,
+ debug=self.debug
+ )
+ self.conduit.connect("conduit-started", self._on_conduit_started)
+ self.conduit.connect_to_conduit(startConduit=False)
+ self.dps = self._get_dataproviders()
+
+ def _get_dataproviders(self):
+ #restrict dps to those we know about
+ return [dp for dp in self.conduit.get_dataproviders() if dp in SUPPORTED_SINKS]
- # more than one selected?
- if len(files) != 1:
- return
+ def _on_conduit_started(self, sender, started):
+ self.dps = self._get_dataproviders()
- file = files[0]
-
- # must be a folder
- if not file.get_mime_type () == SUPPORTED_FORMAT:
- return
-
- # add available items
- self._populate_available_dps()
- items = []
- for dp in self.dps:
- name = dp
- desc = SUPPORTED_SINKS[dp]
-
- #make the menu item
- item = nautilus.MenuItem(
- 'Conduit::synchronizeTo%s' % name,
- desc,
- '',
- 'image-x-generic')
-
- cb = ItemCallbackHandler(name, self.conduitApp)
- item.connect('activate', cb.activate_cb, file)
- items.append(item)
+ def get_file_items(self, window, files):
+ if self.conduit.connected():
+ if len(files) == 1:
+ file_ = files[0]
+ if file_.is_directory():
+ submenu = nautilus.Menu()
+ for dp in self.dps:
+ name = dp
+ desc = SUPPORTED_SINKS[dp]
+
+ #make the menu item
+ item = nautilus.MenuItem(
+ 'Conduit::SynchronizeTo%s' % name,
+ desc,
+ '',
+ 'image-x-generic'
+ )
+ cb = ItemCallbackHandler(name, self.conduit)
+ item.connect('activate', cb.activate_cb, file_)
+
+ submenu.append_item(item)
+
+ menuitem = nautilus.MenuItem(
+ 'Conduit::',
+ 'Conduit',
+ '',
+ 'conduit'
+ )
+ menuitem.set_submenu(submenu)
+ return menuitem,
- # return all items
- return items
+ return None
Modified: trunk/tools/totem-plugin/conduit.py
==============================================================================
--- trunk/tools/totem-plugin/conduit.py (original)
+++ trunk/tools/totem-plugin/conduit.py Fri Feb 20 06:23:38 2009
@@ -3,296 +3,118 @@
import gtk
import dbus, dbus.glib
-"""Based on John Stowers' plugin for EOG to upload images to Flickr via Conduit."""
-
-APPLICATION_DBUS_IFACE="org.conduit.Application"
-CONDUIT_DBUS_IFACE="org.conduit.Conduit"
-EXPORTER_DBUS_IFACE="org.conduit.Exporter"
-DATAPROVIDER_DBUS_IFACE="org.conduit.DataProvider"
+try:
+ import libconduit
+except ImportError:
+ import conduit.libconduit as libconduit
+DEBUG = True
MENU_PATH="/tmw-menubar/movie/properties"
-
SUPPORTED_SINKS = {
- "YouTubeTwoWay" : "Upload to YouTube",
-# "TestVideoSink" : "Test"
+ "YouTubeTwoWay" : "Upload to YouTube",
}
+if DEBUG:
+ SUPPORTED_SINKS["TestVideoSink"] = "Test"
-ICON_SIZE = 24
+class TotemConduitWrapper(libconduit.ConduitWrapper):
-CONFIG_PATH='~/.conduit/totem-plugin'
+ CONFIG_PATH='~/.conduit/totem-plugin'
-NAME_IDX=0
-URI_IDX=1
-STATUS_IDX=2
-
-class ConduitWrapper:
- def __init__ (self, conduit, name, store):
- self.conduit = conduit
- self.name = name
- self.store = store
- self.rowref = None
- self.configured = False
- self.pendingSync = False
-
- self.conduit.connect_to_signal ("SyncProgress",
- self._on_sync_progress,
- dbus_interface = CONDUIT_DBUS_IFACE)
- self.conduit.connect_to_signal ("SyncCompleted",
- self._on_sync_completed,
- dbus_interface = CONDUIT_DBUS_IFACE)
- self.conduit.connect_to_signal ("SyncStarted",
- self._on_sync_started,
- dbus_interface = CONDUIT_DBUS_IFACE)
-
- def _get_configuration (self):
- """Gets the latest configuration for a given
- dataprovider"""
- config_path = os.path.expanduser (CONFIG_PATH)
-
- if not os.path.exists (os.path.join (config_path, self.name)):
- return
-
- f = open (os.path.join (config_path, self.name), 'r')
- xml = f.read ()
- f.close()
-
- return xml
-
- def _save_configuration (self, xml):
- """Saves the configuration XML from a given dataprovider again"""
- config_path = os.path.expanduser (CONFIG_PATH)
-
- if not os.path.exists (config_path):
- os.mkdir (config_path)
-
- f = open (os.path.join (config_path, self.name), 'w')
- f.write (xml)
- f.close()
-
- def _get_rowref (self):
- if self.rowref == None:
- # Store the rowref in the store with the icon Conduit gave us
- info = self.conduit.SinkGetInformation (dbus_interface = EXPORTER_DBUS_IFACE)
- desc = SUPPORTED_SINKS[self.name]
- self.rowref = self.store.append (None,
- (desc, #NAME_IDX
- "", #URI_IDX
- "ready")) #STATUS_IDX
- return self.rowref
-
- def _configure_reply_handler (self):
- # Save the configuration
- xml = self.conduit.SinkGetConfigurationXml ()
- self._save_configuration (xml)
- self.configured = True
-
- # Check if a sync was waiting for the Conduit (sink) to be configured
- if self.pendingSync == True:
- self.pendingSync = False
- self.conduit.Sync (dbus_interface = CONDUIT_DBUS_IFACE)
-
- def _configure_error_handler (self, error):
- pass
-
- def _on_sync_started (self):
- self.store.set_value (self._get_rowref(), STATUS_IDX, "uploading")
-
- def _on_sync_progress (self, progress, uids):
- uris = [str(i) for i in uids]
- delete = []
-
- treeiter = self.store.iter_children (self._get_rowref ())
- while treeiter:
- if self.store.get_value (treeiter, URI_IDX) in uris:
- delete.append (treeiter)
- treeiter = self.store.iter_next (treeiter)
-
- for d in delete:
- self.store.remove (d)
-
- #for uri in uids:
- # rowref = self._get_rowref_for_photo(str(uri))
- # print "\t%s - %s" % (uri, rowref)
- # print "\t",self.photoRefs
-
- def _on_sync_completed (self, abort, error, conflict):
- rowref = self._get_rowref ()
- if abort == False and error == False:
- self.clear ()
- # Update the status
- self.store.set_value (rowref, STATUS_IDX, "finished")
- else:
- # Show the error message in the Conduit GUI
- self.store.set_value (rowref, STATUS_IDX, "error")
-
- def clear (self):
- rowref = self._get_rowref ()
- # Delete all the videos from the list of videos to upload
- delete = []
- child = self.store.iter_children (rowref)
- while child != None:
- delete.append (child)
- child = self.store.iter_next (child)
- # Need to do in two steps so we don't modify the store while iterating
- for d in delete:
- self.store.remove (d)
-
- def add_video (self, uri):
- ok = self.conduit.AddData (uri, dbus_interface = EXPORTER_DBUS_IFACE)
- if ok == True:
- # Add to the store
- rowref = self._get_rowref ()
- filename = uri.split ("/")[-1]
- self.store.append (rowref,
- (filename, # NAME_IDX
- uri, # URI_IDX
- "")) # STATUS_IDX
-
- def sync (self):
- if self.configured == True:
- self.conduit.Sync (dbus_interface = CONDUIT_DBUS_IFACE)
- else:
- # Defer the sync until the Conduit has been configured
- self.pendingSync = True
- # Configure the sink and perform the actual synchronisation
- # when the configuration is finished, this way the Totem GUI doesn't
- # block on the call
- self.conduit.SinkConfigure (reply_handler = self._configure_reply_handler,
- error_handler = self._configure_error_handler,
- dbus_interface = EXPORTER_DBUS_IFACE)
-
-class ConduitApplicationWrapper:
- def __init__ (self, startConduit, addToGui):
- self.addToGui = addToGui
- self.app = None
- self.conduits = {}
- # The liststore of videos to be uploaded
- self.store = gtk.TreeStore (str, #NAME_IDX
- str, #URI_IDX
- str) #STATUS_IDX
-
- if startConduit:
- self.start ()
- else:
- obj = self.bus.get_object ('org.freedesktop.DBus', '/org/freedesktop/DBus')
- dbus_iface = dbus.Interface (obj, 'org.freedesktop.DBus')
- if dbus_iface.NameHasOwner (APPLICATION_DBUS_IFACE):
- self.start ()
- else:
- raise Exception ("Could not connect to Conduit.")
-
- def _build_conduit (self, sinkName):
- if sinkName in self.dps:
- print "Building exporter Conduit %s" % sinkName
- path = self.app.BuildExporter (sinkName)
- exporter = dbus.SessionBus ().get_object (CONDUIT_DBUS_IFACE, path)
- self.conduits[sinkName] = ConduitWrapper (conduit = exporter, name = sinkName, store = self.store)
- else:
- print "Could not build Conduit %s" % sinkName
-
- def upload (self, name, uri):
- if self.connected ():
- if name not in self.conduits:
- self._build_conduit (name)
-
- if uri != None:
- # Add the video to the remote Conduit and the liststore
- self.conduits[name].add_video (uri)
-
- def start (self):
- if not self.connected ():
- try:
- remote_object = dbus.SessionBus ().get_object (APPLICATION_DBUS_IFACE, "/")
- self.app = dbus.Interface (remote_object, APPLICATION_DBUS_IFACE)
- self.dps = self.app.GetAllDataProviders ()
- except dbus.exceptions.DBusException:
- self.app = None
- print "Conduit unavailable"
-
- def sync (self):
- if self.connected ():
- for c in self.conduits:
- self.conduits[c].sync ()
-
- def clear (self):
- if self.connected ():
- for c in self.conduits:
- self.conduits[c].clear ()
-
- def connected (self):
- return self.app != None
-
-class ConduitPlugin (totem.Plugin):
- def __init__ (self):
- self.conduit = ConduitApplicationWrapper (startConduit = True,
- addToGui = False)
-
- def _on_upload_clicked (self, action, totem_object):
- current_uri = totem_object.get_current_mrl ()
- name = action.get_property ("name")
-
- # Add the file to the list and sync it immediately
- self.conduit.upload (name, current_uri)
- self.conduit.sync ()
-
- def _on_file_opened (self, totem_object, mrl):
- self.top_level_action.set_sensitive (True)
-
- def _on_file_closed (self, totem_object):
- self.top_level_action.set_sensitive (False)
-
- def activate (self, totem_object):
- totem_object.connect ("file-opened", self._on_file_opened)
- totem_object.connect ("file-closed", self._on_file_closed)
-
- ui_action_group = gtk.ActionGroup ("ConduitPluginActions")
- manager = totem_object.get_ui_manager ()
-
- # Make an action for each sink
- for sink_name in SUPPORTED_SINKS:
- desc = SUPPORTED_SINKS[sink_name]
- action = gtk.Action (name = sink_name,
- stock_id = "internet",
- label = desc,
- tooltip = "")
- action.connect ("activate", self._on_upload_clicked, totem_object)
- ui_action_group.add_action (action)
-
- # Create a top-level menu
- self.top_level_action = gtk.Action (name = "sync",
- stock_id = "internet",
- label = _("_Share"),
- tooltip = "")
- ui_action_group.add_action (self.top_level_action)
-
- manager.insert_action_group (ui_action_group, -1)
-
- mid = manager.new_merge_id ()
- manager.add_ui (merge_id = mid,
- path = MENU_PATH,
- name = "sync",
- action = "sync",
- type = gtk.UI_MANAGER_MENU,
- top = False)
-
- # Add each action to the menu
- for sink_name in SUPPORTED_SINKS:
- mid = manager.new_merge_id ()
- manager.add_ui (merge_id = mid,
- path = "/tmw-menubar/movie/sync/",
- name = sink_name,
- action = sink_name,
- type = gtk.UI_MANAGER_MENUITEM,
- top = False)
-
- # Make sure the menu starts disabled
- self.top_level_action.set_sensitive (False)
+ def add_rowref(self):
+ #store the rowref in the store with the icon conduit gave us
+ info = self.conduit.SinkGetInformation(dbus_interface=libconduit.EXPORTER_DBUS_IFACE)
+ desc = SUPPORTED_SINKS[self.name]
+ self._add_rowref(
+ name=desc,
+ uri="",
+ status="ready",
+ pixbuf=None
+ )
+
+class ConduitPlugin(totem.Plugin):
+ def __init__(self):
+ self.debug = DEBUG
+ self.conduit = libconduit.ConduitApplicationWrapper(
+ conduitWrapperKlass=TotemConduitWrapper,
+ store=True,
+ debug=self.debug
+ )
+ self.conduit.connect("conduit-started", self._on_conduit_started)
+ self.running = self.conduit.connect_to_conduit(startConduit=True)
+ self.opened = False
+
+ def _on_conduit_started(self, sender, started):
+ self.running = started
+ self.top_level_action.set_sensitive(self.opened and self.running)
+
+ def _on_upload_clicked(self, action, totem_object):
+ current_uri = totem_object.get_current_mrl()
+ name = action.get_property("name")
+
+ # Add the file to the list and sync it immediately
+ self.conduit.upload(name, current_uri, None)
+ self.conduit.sync()
+
+ def _on_file_opened(self, totem_object, mrl):
+ self.opened = True
+ self.top_level_action.set_sensitive(self.running)
+
+ def _on_file_closed(self, totem_object):
+ self.opened = False
+ self.top_level_action.set_sensitive(False)
+
+ def activate(self, totem_object):
+ totem_object.connect("file-opened", self._on_file_opened)
+ totem_object.connect("file-closed", self._on_file_closed)
+
+ ui_action_group = gtk.ActionGroup("ConduitPluginActions")
+ manager = totem_object.get_ui_manager()
+
+ # Make an action for each sink
+ for sink_name in SUPPORTED_SINKS:
+ desc = SUPPORTED_SINKS[sink_name]
+ action = gtk.Action(name = sink_name,
+ stock_id = "internet",
+ label = desc,
+ tooltip = "")
+ action.connect("activate", self._on_upload_clicked, totem_object)
+ ui_action_group.add_action(action)
+
+ # Create a top-level menu
+ self.top_level_action = gtk.Action(name = "sync",
+ stock_id = "internet",
+ label = _("_Share"),
+ tooltip = "")
+ ui_action_group.add_action(self.top_level_action)
+
+ manager.insert_action_group(ui_action_group, -1)
+
+ mid = manager.new_merge_id()
+ manager.add_ui(merge_id = mid,
+ path = MENU_PATH,
+ name = "sync",
+ action = "sync",
+ type = gtk.UI_MANAGER_MENU,
+ top = False)
+
+ # Add each action to the menu
+ for sink_name in SUPPORTED_SINKS:
+ mid = manager.new_merge_id()
+ manager.add_ui(merge_id = mid,
+ path = "/tmw-menubar/movie/sync/",
+ name = sink_name,
+ action = sink_name,
+ type = gtk.UI_MANAGER_MENUITEM,
+ top = False)
+
+ # Make sure the menu starts disabled
+ self.top_level_action.set_sensitive(False)
- def deactivate (self, window):
- pass
+ def deactivate(self, window):
+ pass
- def update_ui (self, window):
- pass
+ def update_ui(self, window):
+ pass
- def is_configurable (self):
- return False
+ def is_configurable(self):
+ return False
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]