conduit r1414 - in trunk: . conduit conduit/modules/BoxDotNetModule conduit/modules/FlickrModule conduit/modules/GoogleModule conduit/utils
- From: jstowers svn gnome org
- To: svn-commits-list gnome org
- Subject: conduit r1414 - in trunk: . conduit conduit/modules/BoxDotNetModule conduit/modules/FlickrModule conduit/modules/GoogleModule conduit/utils
- Date: Mon, 7 Apr 2008 09:30:20 +0100 (BST)
Author: jstowers
Date: Mon Apr 7 09:30:20 2008
New Revision: 1414
URL: http://svn.gnome.org/viewvc/conduit?rev=1414&view=rev
Log:
2008-04-07 John Stowers <john stowers gmail com>
* conduit/Synchronization.py: Add run_blocking_dataprovider_function_calls()
which allows an arbitary function to be executed by the sync manager, and
get a (callback via sync-completed) when the function returns
* conduit/utils/__init__.py: Add run_dialog_non_blocking() which does
as the name suggests.
* conduit/modules/FlickrModule/FlickrModule.py:
* conduit/modules/GoogleModule/GoogleModule.py:
* conduit/modules/BoxDotNetModule/BoxDotNetModule.py:
* conduit/modules/BoxDotNetModule/config.glade: Use the above two functions
to prevent lockups when forced to login from the configure dialog.
Fixes #526292
Modified:
trunk/ChangeLog
trunk/conduit/Synchronization.py
trunk/conduit/modules/BoxDotNetModule/BoxDotNetModule.py
trunk/conduit/modules/BoxDotNetModule/config.glade
trunk/conduit/modules/FlickrModule/FlickrModule.py
trunk/conduit/modules/GoogleModule/GoogleModule.py
trunk/conduit/utils/__init__.py
Modified: trunk/conduit/Synchronization.py
==============================================================================
--- trunk/conduit/Synchronization.py (original)
+++ trunk/conduit/Synchronization.py Mon Apr 7 09:30:20 2008
@@ -131,12 +131,32 @@
for c in self.syncWorkers:
self.syncWorkers[c].join(timeout)
- def refresh_dataprovider(self, cond, dataprovider):
+ def run_blocking_dataprovider_function_calls(self, dataprovider, callback, *functions):
+ #need to get the conduit assocated with this dataprovider because the sync-completed
+ #signal is emmited from the conduit object
+ conds = []
+ conds.extend(conduit.GLOBALS.app.guiSyncSet.get_all_conduits())
+ conds.extend(conduit.GLOBALS.app.dbusSyncSet.get_all_conduits())
+ for c in conds:
+ for dpw in c.get_all_dataproviders():
+ if dataprovider == dpw.module:
+ #found it!
+ if c not in self.syncWorkers:
+ #connect the supplied callback
+ c.connect("sync-completed",callback)
+ #start the thread
+ bfcw = BlockingFunctionCallWorker(c, *functions)
+ self._start_worker_thread(c, bfcw)
+ return
+
+ log.info("Could not create BlockingFunctionCallWorker")
+
+ def refresh_dataprovider(self, cond, dataproviderWrapper):
if cond in self.syncWorkers:
- log.info("Refresh dataprovider already in progress")
+ log.info("Refresh dataproviderWrapper already in progress")
self.join_one(cond)
- threadedWorker = RefreshDataProviderWorker(cond, dataprovider)
+ threadedWorker = RefreshDataProviderWorker(cond, dataproviderWrapper)
self._start_worker_thread(cond, threadedWorker)
def refresh_conduit(self, cond):
@@ -796,7 +816,30 @@
conduit.GLOBALS.mappingDB.save()
self.cond.emit("sync-completed", self.aborted, self.did_sync_error(), self.did_sync_conflict())
-
+class BlockingFunctionCallWorker(_ThreadedWorker):
+ """
+ Calls the provided (blocking) function in a new thread. When
+ the function returns a sync-completed signal is sent
+ """
+ def __init__(self, cond, *functions):
+ _ThreadedWorker.__init__(self)
+ self.cond = cond
+ self.functions = functions
+ self.setName("%s functions" % len(self.functions))
+
+ def run(self):
+ try:
+ #FIXME: Set the status text on the dataprovider
+ for f in self.functions:
+ log.debug("FunctionCall %s beginning" % f.__name__)
+ f()
+ self.aborted = False
+ except Exception, e:
+ log.warn("FunctionCall error: %s" % e)
+ self.aborted = True
+
+ self.cond.emit("sync-completed", self.aborted, False, False)
+
class DeletedData(DataType.DataType):
"""
Simple wrapper around a deleted item. If an item has been deleted then
Modified: trunk/conduit/modules/BoxDotNetModule/BoxDotNetModule.py
==============================================================================
--- trunk/conduit/modules/BoxDotNetModule/BoxDotNetModule.py (original)
+++ trunk/conduit/modules/BoxDotNetModule/BoxDotNetModule.py Mon Apr 7 09:30:20 2008
@@ -278,16 +278,41 @@
"""
import gtk
import gobject
+ def on_login_finish(*args):
+ if self.token:
+ build_folder_store()
+ foldernamecombo.set_sensitive(True)
+ else:
+ foldernamecombo.set_sensitive(False)
+ #dlg.window.set_cursor(None)
+
+ def on_response(sender, responseID):
+ if responseID == gtk.RESPONSE_OK:
+ self.foldername = foldernamecombo.child.get_text()
+
def load_button_clicked(button):
- if not self.token:
- self._login()
-
- build_folder_store()
+ #dlg.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
+ conduit.GLOBALS.syncManager.run_blocking_dataprovider_function_calls(
+ self,
+ on_login_finish,
+ self._login)
def build_folder_store():
- self.folder_store.clear()
+ folder_store.clear()
+ folder_count = 0
+ folder_iter = None
for folder_name in self._get_folders().keys():
- self.folder_store.append((folder_name,))
+ iter = folder_store.append((folder_name,))
+ if folder_name != "" and folder_name == self.foldername:
+ folder_iter = iter
+ folder_count += 1
+
+ if folder_iter:
+ foldernamecombo.set_active_iter(folder_iter)
+ elif self.foldername:
+ foldernamecombo.child.set_text(self.foldername)
+ elif folder_count:
+ foldernamecombo.set_active(0)
tree = Utils.dataprovider_glade_get_widget(
__file__,
@@ -295,38 +320,33 @@
"BoxDotNetConfigDialog")
#get a whole bunch of widgets
- foldername_entry = tree.get_widget("foldername_entry")
+ foldernamecombo = tree.get_widget("foldernamecombo")
load_button = tree.get_widget("load_button")
+ dlg = tree.get_widget("BoxDotNetConfigDialog")
# setup combobox
- self.folder_store = gtk.ListStore(gobject.TYPE_STRING)
- foldername_entry.set_model(self.folder_store)
+ folder_store = gtk.ListStore(gobject.TYPE_STRING)
+ foldernamecombo.set_model(folder_store)
cell = gtk.CellRendererText()
- foldername_entry.pack_start(cell, True)
- foldername_entry.set_text_column(0)
+ foldernamecombo.pack_start(cell, True)
+ foldernamecombo.set_text_column(0)
# already load the folders if we're logged in
if self.token:
build_folder_store()
+ foldernamecombo.set_sensitive(True)
+ else:
+ foldernamecombo.child.set_text(self.foldername)
+ foldernamecombo.set_sensitive(False)
# load button
load_button.connect('clicked', load_button_clicked)
- #preload the widgets
- foldername_entry.child.set_text(self.foldername)
-
# run the dialog
- dlg = tree.get_widget("BoxDotNetConfigDialog")
- response = Utils.run_dialog (dlg, window)
- if response == True:
- # get the values from the widgets
- self.foldername = foldername_entry.child.get_text()
-
- del self.folder_store
- dlg.destroy()
+ Utils.run_dialog_non_blocking(dlg, on_response, window)
def is_configured (self, isSource, isTwoWay):
- return len (self.foldername) > 0
+ return len(self.foldername) > 0
def get_configuration(self):
return {
Modified: trunk/conduit/modules/BoxDotNetModule/config.glade
==============================================================================
--- trunk/conduit/modules/BoxDotNetModule/config.glade (original)
+++ trunk/conduit/modules/BoxDotNetModule/config.glade Mon Apr 7 09:30:20 2008
@@ -100,7 +100,7 @@
<property name="spacing">0</property>
<child>
- <widget class="GtkComboBoxEntry" id="foldername_entry">
+ <widget class="GtkComboBoxEntry" id="foldernamecombo">
<property name="visible">True</property>
<property name="add_tearoffs">False</property>
<property name="has_frame">True</property>
Modified: trunk/conduit/modules/FlickrModule/FlickrModule.py
==============================================================================
--- trunk/conduit/modules/FlickrModule/FlickrModule.py (original)
+++ trunk/conduit/modules/FlickrModule/FlickrModule.py Mon Apr 7 09:30:20 2008
@@ -262,27 +262,33 @@
"""
import gobject
import gtk
- def load_click(button, window, usernameEntry, photosetCombo):
- #set Window cursor to loading
- #FIXME: Doest do anything because this call blocks the mainloop
- #anyway
- window.window.set_cursor(
- gtk.gdk.Cursor(gtk.gdk.WATCH))
- self._set_username(usernameEntry.get_text())
- self._login()
+ def on_login_finish(*args):
if self.logged_in:
- build_photoset_model(photosetCombo)
- window.window.set_cursor(None)
+ build_photoset_model()
+
+ def on_response(sender, responseID):
+ if responseID == gtk.RESPONSE_OK:
+ self._set_username(username.get_text())
+ self.photoSetName = photosetCombo.get_active_text()
+ self.showPublic = publicCb.get_active()
+ self.imageSize = self._resize_combobox_get_active(resizecombobox)
+
+ def load_click(button, window, usernameEntry):
+ self._set_username(usernameEntry.get_text())
+ conduit.GLOBALS.syncManager.run_blocking_dataprovider_function_calls(
+ self,
+ on_login_finish,
+ self._login)
def username_changed(entry, load_button):
load_button.set_sensitive (len(entry.get_text()) > 0)
- def build_photoset_model(photosetCombo):
- self.photoset_store.clear()
+ def build_photoset_model():
+ photoset_store.clear()
photoset_count = 0
photoset_iter = None
for name, photoSetId in self._get_photosets():
- iter = self.photoset_store.append((name,))
+ iter = photoset_store.append((name,))
if name == self.photoSetName:
photoset_iter = iter
photoset_count += 1
@@ -304,12 +310,13 @@
username = tree.get_widget("username")
load_button = tree.get_widget('load_button')
ok_button = tree.get_widget('ok_button')
+ dlg = tree.get_widget("FlickrTwoWayConfigDialog")
resizecombobox = tree.get_widget("resizecombobox")
self._resize_combobox_build(resizecombobox, self.imageSize)
#signals
- load_button.connect('clicked', load_click, window, username, photosetCombo)
+ load_button.connect('clicked', load_click, window, username)
username.connect('changed', username_changed, load_button)
#preload the widgets
@@ -317,8 +324,8 @@
username.set_text(self.username)
#setup photoset combo
- self.photoset_store = gtk.ListStore (gobject.TYPE_STRING)
- photosetCombo.set_model(self.photoset_store)
+ photoset_store = gtk.ListStore (gobject.TYPE_STRING)
+ photosetCombo.set_model(photoset_store)
cell = gtk.CellRendererText()
photosetCombo.pack_start(cell, True)
photosetCombo.set_text_column(0)
@@ -328,18 +335,7 @@
load_button.set_sensitive(enabled)
# run dialog
- dlg = tree.get_widget("FlickrTwoWayConfigDialog")
- response = Utils.run_dialog(dlg, window)
-
- if response == True:
- #get the values from the widgets
- self._set_username(username.get_text())
- self.photoSetName = photosetCombo.get_active_text()
- self.showPublic = publicCb.get_active()
- self.imageSize = self._resize_combobox_get_active(resizecombobox)
- dlg.destroy()
-
- del self.photoset_store
+ Utils.run_dialog_non_blocking(dlg, on_response, window)
def is_configured (self, isSource, isTwoWay):
return len(self.username) > 0 and len(self.photoSetName) > 0
Modified: trunk/conduit/modules/GoogleModule/GoogleModule.py
==============================================================================
--- trunk/conduit/modules/GoogleModule/GoogleModule.py (original)
+++ trunk/conduit/modules/GoogleModule/GoogleModule.py Mon Apr 7 09:30:20 2008
@@ -639,30 +639,35 @@
"""
import gobject
import gtk
- def login_click(button, window, usernameEntry, passwordEntry, album_combo):
- #set Window cursor to loading
- #FIXME: Doest do anything because this call blocks the mainloop
- #anyway
- window.window.set_cursor(
- gtk.gdk.Cursor(gtk.gdk.WATCH))
+ def on_login_finish(*args):
+ if self.loggedIn:
+ build_album_model()
+
+ def on_response(sender, responseID):
+ if responseID == gtk.RESPONSE_OK:
+ self._set_username(username.get_text())
+ self._set_password(password.get_text())
+ self.albumName = album_combo.get_active_text()
+ self.imageSize = self._resize_combobox_get_active(resizecombobox)
+
+ def login_click(button, window, usernameEntry, passwordEntry):
self._set_username(usernameEntry.get_text())
self._set_password(passwordEntry.get_text())
- self._login()
- if self.loggedIn:
- build_album_model(album_combo)
- #album_combo.set_sensitive(True)
- window.window.set_cursor(None)
+ conduit.GLOBALS.syncManager.run_blocking_dataprovider_function_calls(
+ self,
+ on_login_finish,
+ self._login)
def username_password_changed(sender, username, password, login_button):
login_button.set_sensitive(
len(username.get_text()) > 0 and len(password.get_text()) > 0)
- def build_album_model(album_combo):
- self.album_store.clear()
+ def build_album_model():
+ album_store.clear()
album_count = 0
album_iter = None
for name, album in self._get_albums():
- iter = self.album_store.append((name,))
+ iter = album_store.append((name,))
if name == self.albumName:
album_iter = iter
album_count += 1
@@ -685,12 +690,13 @@
password = tree.get_widget('password')
album_combo = tree.get_widget('album_combobox')
login_button = tree.get_widget("login_button")
+ dlg = tree.get_widget("PicasaTwoWayConfigDialog")
resizecombobox = tree.get_widget("resize_combobox")
self._resize_combobox_build(resizecombobox, self.imageSize)
#connect to signals
- login_button.connect('clicked', login_click, window, username, password, album_combo)
+ login_button.connect('clicked', login_click, window, username, password)
username.connect('changed', username_password_changed, username, password, login_button)
password.connect('changed', username_password_changed, username, password, login_button)
@@ -699,8 +705,8 @@
password.set_text(self.password)
#setup album combo
- self.album_store = gtk.ListStore(gobject.TYPE_STRING)
- album_combo.set_model (self.album_store)
+ album_store = gtk.ListStore(gobject.TYPE_STRING)
+ album_combo.set_model (album_store)
cell = gtk.CellRendererText()
album_combo.pack_start(cell, True)
album_combo.set_text_column(0)
@@ -711,17 +717,7 @@
#album_combo.set_sensitive(enabled)
# Now run the dialog
- dlg = tree.get_widget("PicasaTwoWayConfigDialog")
- response = Utils.run_dialog (dlg, window)
- if response == True:
- self._set_username(username.get_text())
- self._set_password(password.get_text())
- self.albumName = album_combo.get_active_text()
- self.imageSize = self._resize_combobox_get_active(resizecombobox)
-
- # cleanup
- del self.album_store
- dlg.destroy()
+ Utils.run_dialog_non_blocking(dlg, on_response, window)
def get_configuration(self):
conf = GoogleBase.get_configuration(self)
Modified: trunk/conduit/utils/__init__.py
==============================================================================
--- trunk/conduit/utils/__init__.py (original)
+++ trunk/conduit/utils/__init__.py Mon Apr 7 09:30:20 2008
@@ -137,6 +137,34 @@
return dialog.run() == gtk.RESPONSE_OK
+def run_dialog_non_blocking(dialog, resp_cb, window=None):
+ """
+ Runs a given dialog, and makes it transient for
+ the given window if any
+ @param dialog: dialog
+ @param window: gtk window
+ @returns: True if the user clicked OK to exit the dialog
+ """
+ import gtk.gdk
+
+ dialog.connect("response", resp_cb)
+ dialog.connect("response", lambda dlg, resp: dlg.destroy())
+
+ if window:
+ dialog.set_transient_for(window)
+ #FIXME: Doesnt work
+ #fake modality by making window ignore key events
+ #events = window.window.get_events()
+ #window.window.set_events(
+ # events & ~(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK))
+ #connect to response signal to restore original events
+ #dialog.connect(
+ # "response",
+ # lambda dlg, resp, win, originalEvents: window.window.set_events(originalEvents),
+ # window,events)
+
+ dialog.show()
+
def md5_string(string):
"""
Returns the md5 of the supplied string in readable hexdigest string format
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]