Requesting information from the user inside a GTK main loop
I am learning Python by building a simple PyGTK application that fetches data from some SVN repositories, using pysvn. The pysvn Client has a callback you can specify that it calls when Subversion needs authentication inform开发者_如何学JAVAation for a repository. When that happens, I would like to open a dialog to ask the user for the credentials.
The problem is, it seems the callback is called inside the GTK main loop, so it's basically called on every tick. Is there a way to prevent this? Perhaps by opening the dialog in a new thread? But then how do I return the tuple with the user data to the callback so it can return it to the pysvn.Client?
This is the way we do it in RabbitVCS. Essentially, the main application creates the dialog and runs it using the PyGTK gtk.Dialog run() method.
Breaking it down, from the main app we have (see action.py):
def get_login(self, realm, username, may_save):
# ...other code omitted...
gtk.gdk.threads_enter()
dialog = rabbitvcs.ui.dialog.Authentication(
realm,
may_save
)
result = dialog.run()
gtk.gdk.threads_leave()
return result
This "get_login" function is the one that is given as the callback to the PySVN client instance.
Note the threads_enter() and threads_leave() methods! These allow GTK to use Python threads, but note that the GIL may be locked by other extensions.
What this does is create a dialog (already laid out using Glade), and the run() method on that class is a wrapper for the PyGTK method (see dialog.py):
def run(self):
returner = None
self.dialog = self.get_widget("Authentication")
result = self.dialog.run()
login = self.get_widget("auth_login").get_text()
password = self.get_widget("auth_password").get_text()
save = self.get_widget("auth_save").get_active()
self.dialog.destroy()
if result == gtk.RESPONSE_OK:
return (True, login, password, save)
else:
return (False, "", "", False)
The RabbitVCS UI code is probably far more convoluted that you would need, but it might help to poke around. Those "get_widget" calls are convenience methods to get the widget from the Glade tree. If you are not using Glade, you will have references to the widgets directly.
I hope it helps :)
精彩评论