Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/gnome_plugins
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2011-02-18 00:44:23 (GMT)
committer Walter Bender <walter.bender@gmail.com>2011-02-18 00:44:23 (GMT)
commit244bb8735a88530dbcefd6e8e25b1db69a0a95ec (patch)
treec4916a90584afe884b3baa02058d80f8e5b16ca6 /gnome_plugins
parentb52d6ddf14d6aa2ba01ecc60076383f03a2a8cbe (diff)
new plugin management method
Diffstat (limited to 'gnome_plugins')
-rw-r--r--gnome_plugins/__init__.py0
-rw-r--r--gnome_plugins/collaboration_plugin.py348
-rw-r--r--gnome_plugins/plugin.py34
-rw-r--r--gnome_plugins/uploader_plugin.py209
4 files changed, 591 insertions, 0 deletions
diff --git a/gnome_plugins/__init__.py b/gnome_plugins/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gnome_plugins/__init__.py
diff --git a/gnome_plugins/collaboration_plugin.py b/gnome_plugins/collaboration_plugin.py
new file mode 100644
index 0000000..54abdc8
--- /dev/null
+++ b/gnome_plugins/collaboration_plugin.py
@@ -0,0 +1,348 @@
+#!/usr/bin/env python
+#Copyright (c) 2011 Walter Bender
+#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import sys
+sys.path.append("..")
+
+import dbus
+from gettext import gettext as _
+import gobject
+import gtk
+
+from plugin import Plugin
+
+from util.menubuilder import MenuBuilder
+from util.configfile import ConfigFile
+from util.configwizard import ConfigWizard
+
+import telepathy
+from collaboration.neighborhood import get_neighborhood
+from collaboration.connectionmanager import get_connection_manager
+from collaboration.activity import Activity
+from collaboration import telepathyclient
+from collaboration.tubeconn import TubeConnection
+
+from TurtleArt.tacollaboration import Collaboration
+
+import traceback
+
+CONNECTION_INTERFACE_ACTIVITY_PROPERTIES = \
+ 'org.laptop.Telepathy.ActivityProperties'
+
+
+class Collaboration_plugin(Plugin):
+
+ __gsignals__ = {
+ 'joined': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ()),
+ 'shared': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ()),
+ }
+
+ def __init__(self, parent):
+ Plugin.__init__(self)
+
+ self._parent = parent
+ self._neighborhood = None
+ self._title = _('My Turtle Art session')
+ self._bundle_id = "org.laptop.TurtleArt"
+ # This could be hashed from the file path (if resuming)
+ self._activity_id = "1234567"
+ self._nick = ""
+ self._setup_has_been_called = False
+
+ def _setup_config_file(self, config_file_path):
+ self._config_file_path = config_file_path
+ self._collaboration_config_values = ConfigFile(self._config_file_path)
+ self._valid_config_values = {
+ 'nick': {'type': 'text'},
+ 'account_id': {'type': 'text'},
+ 'password': {'type': 'text'},
+ 'server': {'type': 'text'},
+ 'port': {'type': 'integer'},
+ 'register': {'type': 'boolean'},
+ 'colors': {'type': 'text'}
+ }
+
+ def _connect_cb(self, button):
+ """ Enable connection """
+ self._collaboration_config_values.set_valid_keys(
+ self._valid_config_values)
+ self._collaboration_config_values.connect(
+ 'configuration-loaded', self._connect_to_neighborhood)
+ self._collaboration_config_values.connect(
+ 'configuration-saved', self._connect_to_neighborhood)
+ self._collaboration_config_values.load()
+ self.setup()
+
+ def setup(self):
+ self._collaboration = Collaboration(self.tw, self)
+ self._collaboration.setup()
+ # Do we know if we were successful?
+ self._setup_has_been_called = True
+ # TODO:
+ # use set_sensitive to enable Share and Configuration menuitems
+
+ def set_tw(self, turtleart_window):
+ self.tw = turtleart_window
+ self.tw.nick = self._get_nick()
+ self._setup_config_file(self._parent.get_config_home())
+
+ def get_menu(self):
+ menu = gtk.Menu()
+
+ MenuBuilder.make_menu_item(menu, _('Enable collaboration'),
+ self._connect_cb)
+
+ self._activities_submenu = gtk.Menu()
+ activities_menu = MenuBuilder.make_sub_menu(self._activities_submenu,
+ _('Activities'))
+ menu.append(activities_menu)
+
+ self._buddies_submenu = gtk.Menu()
+ buddies_menu = MenuBuilder.make_sub_menu(self._buddies_submenu,
+ _('Buddies'))
+ menu.append(buddies_menu)
+
+ MenuBuilder.make_menu_item(menu, _('Share'), self._share_cb)
+ MenuBuilder.make_menu_item(menu, _('Configuration'),
+ self._config_neighborhood_cb)
+
+ neighborhood_menu = MenuBuilder.make_sub_menu(menu, _('Neighborhood'))
+
+ return neighborhood_menu
+
+ def get_colors(self):
+ return self._colors
+
+ def _get_nick(self):
+ return self._nick
+
+ def _get_activity_id(self):
+ return self._activity_id
+
+ def _get_bundle_id(self):
+ return self._bundle_id
+
+ def _get_title(self):
+ return self._title
+
+ def _connect_to_neighborhood(self, config_file_obj):
+ if self._neighborhood is not None:
+ return
+
+ params = {}
+ params['nickname'] = self._collaboration_config_values.get('nick')
+ params['account_id'] = self._collaboration_config_values.get(
+ 'account_id')
+ params['server'] = self._collaboration_config_values.get('server')
+ params['port'] = self._collaboration_config_values.get('port')
+ params['password'] = self._collaboration_config_values.get('password')
+ params['register'] = self._collaboration_config_values.get('register')
+ if params['server'] == '':
+ raise RuntimeError('Invalid server address')
+
+ self._nick = self._collaboration_config_values.get('nick')
+ # Tell the parent activity that the nick may have changed
+ self._parent.nick_changed(self._nick)
+
+ self._colors = self._collaboration_config_values.get('colors')
+ # Tell the parent activity that the colors may have changed
+ self._parent.color_changed(self._colors)
+
+ self._activities = {}
+ self._buddies = {}
+
+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+
+ self._client_handler = telepathyclient.get_instance()
+ if self._client_handler == None:
+ raise RuntimeError('Telepathy client unavailable')
+ self._neighborhood = get_neighborhood(params)
+ self._neighborhood.connect('activity-added', self._activity_added_cb)
+ self._neighborhood.connect('activity-removed',
+ self._activity_removed_cb)
+ self._neighborhood.connect('buddy-added', self._buddy_added_cb)
+ self._neighborhood.connect('buddy-removed', self._buddy_removed_cb)
+
+ # TODO:
+ # - show nick of sharer
+ # - show icon with color of sharer
+ def _activity_added_cb(self, model, activity_model):
+ self._activities[activity_model.props.name] = activity_model
+ self._recreate_available_activities_menu()
+
+ def _activity_removed_cb(self, model, activity_model):
+ try:
+ self._activities.pop(activity_model.props.name)
+ except:
+ print 'Failed to remove activity %s' % activity_model.props.name
+
+ self._recreate_available_activities_menu()
+
+ def _buddy_added_cb(self, activity, buddy):
+ self._buddies[buddy.get_key()] = buddy
+ self._recreate_available_buddies_menu()
+
+ def _buddy_removed_cb(self, activity, buddy):
+ try:
+ self._buddies.pop(buddy.get_key())
+ except:
+ print "Couldn't remove buddy %s" % buddy.get_key()
+ self._recreate_available_buddies_menu()
+
+ # TODO: we should have a list of available actions over
+ # a given buddy. I.e.: a) chat with him b) make friend
+ # c) invite to current activity
+ #
+ def _recreate_available_buddies_menu(self):
+ for child in self._buddies_submenu.get_children():
+ self._buddies_submenu.remove(child)
+
+ for buddy in self._buddies.values():
+ key = buddy.get_key()
+ if key is None:
+ key = ''
+ n = buddy.get_nick() + '|' + key[0:15]
+ MenuBuilder.make_menu_item(self._buddies_submenu, n,
+ self._buddy_actions_cb, buddy)
+
+ def _buddy_actions_cb(self, widget, buddy):
+ print 'do something with %s' % buddy.get_nick()
+
+ # TODO:
+ # we need an extra menu branch with a) 'Join' button b) List of buddies
+ def _recreate_available_activities_menu(self):
+ for child in self._activities_submenu.get_children():
+ self._activities_submenu.remove(child)
+
+ for activity in self._activities.values():
+ n = activity.props.name
+ MenuBuilder.make_menu_item(self._activities_submenu, n,
+ self._join_activity_cb, activity)
+
+ def _join_activity_cb(self, widget, activity):
+ print 'Lets try to join...'
+
+ connection_manager = get_connection_manager()
+ account_path, connection = \
+ connection_manager.get_preferred_connection()
+ if connection is None:
+ print('No active connection available')
+ return
+
+ properties = {}
+ properties['id'] = activity.activity_id
+ properties['color'] = activity.get_color()
+ print 'room handle according to activity %s' % activity.room_handle
+ properties['private'] = True
+
+ try:
+ room_handle = connection.GetActivity(activity.activity_id,
+ dbus_interface=CONNECTION_INTERFACE_ACTIVITY_PROPERTIES)
+ print('room_handle = %s' % str(room_handle))
+ self._joined_activity = Activity(
+ account_path, connection, room_handle, properties=properties)
+ # FIXME: this should be unified, no need to keep 2 references
+ self._shared_activity = self._joined_activity
+ except:
+ traceback.print_exc(file=sys.stdout)
+
+ if self._joined_activity.props.joined:
+ raise RuntimeError('Activity %s is already shared.' %
+ activity.activity_id)
+
+ _join_id = self._joined_activity.connect('joined', self.__joined_cb)
+ self._joined_activity.join()
+
+ def __joined_cb(self, activity, success, err):
+ print "We've joined an activity"
+ self.emit('joined')
+
+ def _config_neighborhood_cb(self, widget):
+ if not self._setup_has_been_called:
+ return
+ config_w = ConfigWizard(self._config_file_path)
+ config_items = [
+ {'item_label': _('Nickname'), 'item_type': 'text',
+ 'item_name': 'nick'},
+ {'item_label': _('Account ID'), 'item_type': 'text',
+ 'item_name': 'account_id'},
+ {'item_label': _('Server'), 'item_type': 'text',
+ 'item_name': 'server'},
+ {'item_label': _('Port'), 'item_type': 'text',
+ 'item_name': 'port'},
+ {'item_label': _('Password'), 'item_type': 'text',
+ 'item_name': 'password'},
+ {'item_label': _('Register'), 'item_type': 'boolean',
+ 'item_name': 'register'},
+ {'item_label': _('Colors'), 'item_type': 'text',
+ 'item_name': 'colors'}
+ ]
+ config_w.set_config_items(config_items)
+ config_w.set_config_file_obj(self._collaboration_config_values)
+ config_w.show()
+
+ def _share_cb(self, button):
+ if not self._setup_has_been_called:
+ return
+ properties = {}
+ properties['id'] = self._get_activity_id()
+ properties['type'] = self._get_bundle_id()
+ properties['name'] = self._get_title()
+ properties['color'] = self.get_colors()
+ properties['private'] = False
+
+ connection_manager = get_connection_manager()
+ account_path, connection = \
+ connection_manager.get_preferred_connection()
+
+ if connection is None:
+ print('No active connection available')
+ return
+
+ try:
+ self._parent._shared_activity = Activity(account_path,
+ connection,
+ properties=properties)
+ # FIXME: this should be unified, no need to keep 2 references
+ self._shared_activity = self._parent._shared_activity
+ except:
+ traceback.print_exc(file=sys.stdout)
+
+ if self._parent._shared_parent.props.joined:
+ raise RuntimeError('Activity %s is already shared.' %
+ self._parent._get_activity_id())
+
+ self._parent._shared_parent.share(self.__share_activity_cb,
+ self.__share_activity_error_cb)
+
+ def __share_activity_cb(self, activity):
+ """Finish sharing the activity"""
+ self.emit('shared')
+
+ def __share_activity_error_cb(self, activity, error):
+ """Notify with GObject event of unsuccessful sharing of activity"""
+ print '%s got error: %s' % (activity, error)
+
+if __name__ == '__main__':
+ print 'testing collaboration'
diff --git a/gnome_plugins/plugin.py b/gnome_plugins/plugin.py
new file mode 100644
index 0000000..590c9bc
--- /dev/null
+++ b/gnome_plugins/plugin.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+#Copyright (c) 2011 Walter Bender
+#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+import gobject
+
+
+class Plugin(gobject.GObject):
+ def __init__(self):
+ gobject.GObject.__init__(self)
+
+ def get_menu(self):
+ raise RuntimeError("You need to define get__menu for your plugin.")
+
+ def set_tw(self, turtle_window=None):
+ raise RuntimeError("You need to define set_tw for your plugin.")
diff --git a/gnome_plugins/uploader_plugin.py b/gnome_plugins/uploader_plugin.py
new file mode 100644
index 0000000..06224fa
--- /dev/null
+++ b/gnome_plugins/uploader_plugin.py
@@ -0,0 +1,209 @@
+#!/usr/bin/env python
+#Copyright (c) 2011 Walter Bender
+#Copyright (c) 2010 Jamie Boisture
+#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
+
+#Permission is hereby granted, free of charge, to any person obtaining a copy
+#of this software and associated documentation files (the "Software"), to deal
+#in the Software without restriction, including without limitation the rights
+#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+#copies of the Software, and to permit persons to whom the Software is
+#furnished to do so, subject to the following conditions:
+
+#The above copyright notice and this permission notice shall be included in
+#all copies or substantial portions of the Software.
+
+#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+#THE SOFTWARE.
+
+#!/usr/bin/python
+
+try:
+ import pycurl
+ import xmlrpclib
+ _UPLOAD_AVAILABLE = True
+except ImportError, e:
+ print "Import Error: %s. Project upload is disabled." % (e)
+ _UPLOAD_AVAILABLE = False
+
+import os
+import gtk
+
+from plugin import Plugin
+from util.menubuilder import MenuBuilder
+
+from gettext import gettext as _
+
+
+class Uploader_plugin(Plugin):
+ MAX_FILE_SIZE = 950000
+ UPLOAD_SERVER = 'http://turtleartsite.appspot.com'
+
+ def __init__(self, parent, upload_server=None, max_file_size=None):
+ self._parent = parent
+ self.uploading = False
+
+ if upload_server is None:
+ self._upload_server = self.UPLOAD_SERVER
+
+ if max_file_size is None:
+ self._max_file_size = self.MAX_FILE_SIZE
+ else:
+ self._max_file_size = max_file_size
+
+ def set_tw(self, turtleart_window):
+ self.tw = turtleart_window
+
+ def get_menu(self):
+ menu = gtk.Menu()
+ MenuBuilder.make_menu_item(menu, _('Upload to Web'),
+ self.do_upload_to_web)
+ upload_menu = MenuBuilder.make_sub_menu(menu, _('Upload'))
+ return upload_menu
+
+ def enabled(self):
+ return _UPLOAD_AVAILABLE
+
+ def do_upload_to_web(self, widget=None):
+ if self.uploading:
+ return
+
+ self.uploading = False
+ self.pop_up = gtk.Window()
+ self.pop_up.set_default_size(600, 400)
+ self.pop_up.connect('delete_event', self._stop_uploading)
+ table = gtk.Table(8, 1, False)
+ self.pop_up.add(table)
+
+ login_label = gtk.Label(_('You must have an account at \
+http://turtleartsite.sugarlabs.org to upload your project.'))
+ table.attach(login_label, 0, 1, 0, 1)
+ self.login_message = gtk.Label('')
+ table.attach(self.login_message, 0, 1, 1, 2)
+
+ self.Hbox1 = gtk.HBox()
+ table.attach(self.Hbox1, 0, 1, 2, 3, xpadding=5, ypadding=3)
+ self.username_entry = gtk.Entry()
+ username_label = gtk.Label(_('Username:') + ' ')
+ username_label.set_size_request(150, 25)
+ username_label.set_alignment(1.0, 0.5)
+ self.username_entry.set_size_request(450, 25)
+ self.Hbox1.add(username_label)
+ self.Hbox1.add(self.username_entry)
+
+ self.Hbox2 = gtk.HBox()
+ table.attach(self.Hbox2, 0, 1, 3, 4, xpadding=5, ypadding=3)
+ self.password_entry = gtk.Entry()
+ password_label = gtk.Label(_('Password:') + ' ')
+ self.password_entry.set_visibility(False)
+ password_label.set_size_request(150, 25)
+ password_label.set_alignment(1.0, 0.5)
+ self.password_entry.set_size_request(450, 25)
+ self.Hbox2.add(password_label)
+ self.Hbox2.add(self.password_entry)
+
+ self.Hbox3 = gtk.HBox()
+ table.attach(self.Hbox3, 0, 1, 4, 5, xpadding=5, ypadding=3)
+ self.title_entry = gtk.Entry()
+ title_label = gtk.Label(_('Title:') + ' ')
+ title_label.set_size_request(150, 25)
+ title_label.set_alignment(1.0, 0.5)
+ self.title_entry.set_size_request(450, 25)
+ self.Hbox3.add(title_label)
+ self.Hbox3.add(self.title_entry)
+
+ self.Hbox4 = gtk.HBox()
+ table.attach(self.Hbox4, 0, 1, 5, 6, xpadding=5, ypadding=3)
+ self.description_entry = gtk.TextView()
+ description_label = gtk.Label(_('Description:') + ' ')
+ description_label.set_size_request(150, 25)
+ description_label.set_alignment(1.0, 0.5)
+ self.description_entry.set_wrap_mode(gtk.WRAP_WORD)
+ self.description_entry.set_size_request(450, 50)
+ self.Hbox4.add(description_label)
+ self.Hbox4.add(self.description_entry)
+
+ self.Hbox5 = gtk.HBox()
+ table.attach(self.Hbox5, 0, 1, 6, 7, xpadding=5, ypadding=3)
+ self.submit_button = gtk.Button(_('Submit to Web'))
+ self.submit_button.set_size_request(300, 25)
+ self.submit_button.connect('pressed', self._do_remote_logon)
+ self.Hbox5.add(self.submit_button)
+ self.cancel_button = gtk.Button(_('Cancel'))
+ self.cancel_button.set_size_request(300, 25)
+ self.cancel_button.connect('pressed', self._stop_uploading)
+ self.Hbox5.add(self.cancel_button)
+
+ self.pop_up.show_all()
+
+ def _stop_uploading(self, widget, event=None):
+ """ Hide the popup when the upload is complte """
+ self.uploading = False
+ self.pop_up.hide()
+
+ def _do_remote_logon(self, widget):
+ """ Log into the upload server """
+ username = self.username_entry.get_text()
+ password = self.password_entry.get_text()
+ server = xmlrpclib.ServerProxy(self._upload_server + '/call/xmlrpc')
+ logged_in = server.login_remote(username, password)
+ if logged_in:
+ upload_key = logged_in
+ self._do_submit_to_web(upload_key)
+ else:
+ self.login_message.set_text(_('Login failed'))
+
+ def _do_submit_to_web(self, key):
+ """ Submit project to the server """
+ title = self.title_entry.get_text()
+ description = self.description_entry.get_buffer().get_text(
+ *self.description_entry.get_buffer().get_bounds())
+ tafile, imagefile = self.tw.save_for_upload(title)
+
+ # Set a maximum file size for image to be uploaded.
+ if int(os.path.getsize(imagefile)) > self._max_file_size:
+ import Image
+ while int(os.path.getsize(imagefile)) > self._max_file_size:
+ big_file = Image.open(imagefile)
+ smaller_file = big_file.resize(int(0.9 * big_file.size[0]),
+ int(0.9 * big_file.size[1]),
+ Image.ANTIALIAS)
+ smaller_file.save(imagefile, quality=100)
+
+ c = pycurl.Curl()
+ c.setopt(c.POST, 1)
+ c.setopt(c.FOLLOWLOCATION, 1)
+ c.setopt(c.URL, self._upload_server + '/upload')
+ c.setopt(c.HTTPHEADER, ["Expect:"])
+ c.setopt(c.HTTPPOST, [('file', (c.FORM_FILE, tafile)),
+ ('newimage', (c.FORM_FILE, imagefile)),
+ ('small_image', (c.FORM_FILE, imagefile)),
+ ('title', title),
+ ('description', description),
+ ('upload_key', key), ('_formname',
+ 'image_create')])
+ c.perform()
+ error_code = c.getinfo(c.HTTP_CODE)
+ c.close
+ os.remove(imagefile)
+ os.remove(tafile)
+ if error_code == 400:
+ self.login_message.set_text(_('Failed to upload!'))
+ else:
+ self.pop_up.hide()
+ self.uploading = False
+
+if __name__ == "__main__":
+ # TODO: create test data...
+ u = Uploader(None)
+ if u.enabled():
+ print "Uploader is enabled... trying to upload"
+ u.do_upload_to_web()
+ gtk.main()
+ else:
+ print "Uploader is not enabled... exiting"