diff options
Diffstat (limited to 'src/jarabe/model')
-rw-r--r-- | src/jarabe/model/__init__.py | 1 | ||||
-rw-r--r-- | src/jarabe/model/adhoc.py | 12 | ||||
-rw-r--r-- | src/jarabe/model/buddy.py | 10 | ||||
-rw-r--r-- | src/jarabe/model/bundleregistry.py | 86 | ||||
-rw-r--r-- | src/jarabe/model/filetransfer.py | 26 | ||||
-rw-r--r-- | src/jarabe/model/friends.py | 22 | ||||
-rw-r--r-- | src/jarabe/model/invites.py | 22 | ||||
-rw-r--r-- | src/jarabe/model/mimeregistry.py | 1 | ||||
-rw-r--r-- | src/jarabe/model/neighborhood.py | 112 | ||||
-rw-r--r-- | src/jarabe/model/network.py | 336 | ||||
-rw-r--r-- | src/jarabe/model/notifications.py | 21 | ||||
-rw-r--r-- | src/jarabe/model/olpcmesh.py | 20 | ||||
-rw-r--r-- | src/jarabe/model/screen.py | 6 | ||||
-rw-r--r-- | src/jarabe/model/session.py | 9 | ||||
-rw-r--r-- | src/jarabe/model/shell.py | 165 | ||||
-rw-r--r-- | src/jarabe/model/sound.py | 11 | ||||
-rw-r--r-- | src/jarabe/model/telepathyclient.py | 5 |
17 files changed, 509 insertions, 356 deletions
diff --git a/src/jarabe/model/__init__.py b/src/jarabe/model/__init__.py index a9dd95a..85f6a24 100644 --- a/src/jarabe/model/__init__.py +++ b/src/jarabe/model/__init__.py @@ -13,4 +13,3 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - diff --git a/src/jarabe/model/adhoc.py b/src/jarabe/model/adhoc.py index ad0c941..8842a5c 100644 --- a/src/jarabe/model/adhoc.py +++ b/src/jarabe/model/adhoc.py @@ -24,6 +24,7 @@ from jarabe.model.network import Settings from sugar.util import unique_id from jarabe.model.network import IP4Config + _NM_SERVICE = 'org.freedesktop.NetworkManager' _NM_IFACE = 'org.freedesktop.NetworkManager' _NM_PATH = '/org/freedesktop/NetworkManager' @@ -32,8 +33,9 @@ _NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' _NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' _NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - _adhoc_manager_instance = None + + def get_adhoc_manager_instance(): global _adhoc_manager_instance if _adhoc_manager_instance is None: @@ -53,7 +55,7 @@ class AdHocManager(gobject.GObject): 'members-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), 'state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])) + ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])), } _AUTOCONNECT_TIMEOUT = 30 @@ -82,7 +84,7 @@ class AdHocManager(gobject.GObject): ' only be called once.') self._device = device - props = dbus.Interface(device, 'org.freedesktop.DBus.Properties') + props = dbus.Interface(device, dbus.PROPERTIES_IFACE) self._device_state = props.Get(_NM_DEVICE_IFACE, 'State') self._bus.add_signal_receiver(self.__device_state_changed_cb, @@ -158,7 +160,7 @@ class AdHocManager(gobject.GObject): def __idle_check_cb(self): if self._device_state == network.DEVICE_STATE_DISCONNECTED: - logging.debug("Connect to Ad-hoc network due to inactivity.") + logging.debug('Connect to Ad-hoc network due to inactivity.') self._autoconnect_adhoc() return False @@ -186,7 +188,7 @@ class AdHocManager(gobject.GObject): self._connect(channel) def _connect(self, channel): - name = "Ad-hoc Network %d" % channel + name = 'Ad-hoc Network %d' % channel connection = network.find_connection_by_ssid(name) if connection is None: settings = Settings() diff --git a/src/jarabe/model/buddy.py b/src/jarabe/model/buddy.py index 5f3176e..c580e68 100644 --- a/src/jarabe/model/buddy.py +++ b/src/jarabe/model/buddy.py @@ -28,8 +28,12 @@ from sugar.profile import get_profile from jarabe.util.telepathy import connection_watcher + CONNECTION_INTERFACE_BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo' +_owner_instance = None + + class BaseBuddyModel(gobject.GObject): __gtype_name__ = 'SugarBaseBuddyModel' @@ -89,6 +93,7 @@ class BaseBuddyModel(gobject.GObject): class OwnerBuddyModel(BaseBuddyModel): __gtype_name__ = 'SugarOwnerBuddyModel' + def __init__(self): BaseBuddyModel.__init__(self) @@ -180,7 +185,6 @@ class OwnerBuddyModel(BaseBuddyModel): return True -_owner_instance = None def get_owner_instance(): global _owner_instance if _owner_instance is None: @@ -190,6 +194,7 @@ def get_owner_instance(): class BuddyModel(BaseBuddyModel): __gtype_name__ = 'SugarBuddyModel' + def __init__(self, **kwargs): self._account = None @@ -225,4 +230,5 @@ class BuddyModel(BaseBuddyModel): def set_handle(self, handle): self._handle = handle - handle = gobject.property(type=object, getter=get_handle, setter=set_handle) + handle = gobject.property(type=object, getter=get_handle, + setter=set_handle) diff --git a/src/jarabe/model/bundleregistry.py b/src/jarabe/model/bundleregistry.py index 699e339..84d55c0 100644 --- a/src/jarabe/model/bundleregistry.py +++ b/src/jarabe/model/bundleregistry.py @@ -17,7 +17,6 @@ import os import logging -import traceback import gconf import gobject @@ -26,6 +25,7 @@ import simplejson from sugar.bundle.activitybundle import ActivityBundle from sugar.bundle.contentbundle import ContentBundle +from sugar.bundle.bundleversion import NormalizedVersion from jarabe.journal.journalentrybundle import JournalEntryBundle from sugar.bundle.bundle import MalformedBundleException, \ AlreadyInstalledException, RegistrationException @@ -34,16 +34,20 @@ from sugar import env from jarabe import config from jarabe.model import mimeregistry + +_instance = None + + class BundleRegistry(gobject.GObject): """Tracks the available activity bundles""" __gsignals__ = { - 'bundle-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), + 'bundle-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), 'bundle-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), 'bundle-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) + ([gobject.TYPE_PYOBJECT])), } def __init__(self): @@ -153,14 +157,16 @@ class BundleRegistry(gobject.GObject): return for bundle_id in default_activities: - max_version = -1 + max_version = '0' for bundle in self._bundles: if bundle.get_bundle_id() == bundle_id and \ - max_version < bundle.get_activity_version(): + NormalizedVersion(max_version) < \ + NormalizedVersion(bundle.get_activity_version()): max_version = bundle.get_activity_version() key = self._get_favorite_key(bundle_id, max_version) - if max_version > -1 and key not in self._favorite_bundles: + if NormalizedVersion(max_version) > NormalizedVersion('0') and \ + key not in self._favorite_bundles: self._favorite_bundles[key] = None logging.debug('After merging: %r', self._favorite_bundles) @@ -168,20 +174,10 @@ class BundleRegistry(gobject.GObject): self._write_favorites_file() def get_bundle(self, bundle_id): - """Returns a bundle given service name or substring, - returns None if there is either no match, or more than one - match by substring.""" - result = [] - key = bundle_id.lower() - + """Returns an bundle given his service name""" for bundle in self._bundles: - name = bundle.get_bundle_id() - if name == bundle_id: + if bundle.get_bundle_id() == bundle_id: return bundle - if key in name.lower(): - result.append(bundle) - if len(result) == 1: - return result[0] return None def __iter__(self): @@ -204,19 +200,18 @@ class BundleRegistry(gobject.GObject): if os.path.isdir(bundle_dir): bundles[bundle_dir] = os.stat(bundle_dir).st_mtime except Exception: - logging.error('Error while processing installed activity ' \ - 'bundle %s:\n%s' % \ - (bundle_dir, traceback.format_exc())) + logging.exception('Error while processing installed activity' + ' bundle %s:', bundle_dir) bundle_dirs = bundles.keys() bundle_dirs.sort(lambda d1, d2: cmp(bundles[d1], bundles[d2])) for folder in bundle_dirs: try: self._add_bundle(folder) - except Exception, e: - logging.error('Error while processing installed activity ' \ - 'bundle %s:\n%s' % \ - (folder, traceback.format_exc())) + except: + # pylint: disable=W0702 + logging.exception('Error while processing installed activity' + ' bundle %s:', folder) def add_bundle(self, bundle_path, install_mime_type=False): bundle = self._add_bundle(bundle_path, install_mime_type) @@ -243,8 +238,8 @@ class BundleRegistry(gobject.GObject): installed = self.get_bundle(bundle_id) if installed is not None: - if installed.get_activity_version() >= \ - bundle.get_activity_version(): + if NormalizedVersion(installed.get_activity_version()) >= \ + NormalizedVersion(bundle.get_activity_version()): logging.debug('Skip old version for %s', bundle_id) return None else: @@ -270,8 +265,7 @@ class BundleRegistry(gobject.GObject): default_bundle = None for bundle in self._bundles: - if bundle.get_mime_types() and mime_type in bundle.get_mime_types(): - + if mime_type in (bundle.get_mime_types() or []): if bundle.get_bundle_id() == default_bundle_id: default_bundle = bundle elif self.get_default_for_type(mime_type) == \ @@ -286,10 +280,7 @@ class BundleRegistry(gobject.GObject): return result def get_default_for_type(self, mime_type): - if self._mime_defaults.has_key(mime_type): - return self._mime_defaults[mime_type] - else: - return None + return self._mime_defaults.get(mime_type) def _find_bundle(self, bundle_id, version): for bundle in self._bundles: @@ -327,7 +318,8 @@ class BundleRegistry(gobject.GObject): def set_bundle_position(self, bundle_id, version, x, y): key = self._get_favorite_key(bundle_id, version) if key not in self._favorite_bundles: - raise ValueError('Bundle %s %s not favorite' % (bundle_id, version)) + raise ValueError('Bundle %s %s not favorite' % + (bundle_id, version)) if self._favorite_bundles[key] is None: self._favorite_bundles[key] = {} @@ -368,19 +360,22 @@ class BundleRegistry(gobject.GObject): for installed_bundle in self._bundles: if bundle.get_bundle_id() == installed_bundle.get_bundle_id() and \ - bundle.get_activity_version() == \ - installed_bundle.get_activity_version(): + NormalizedVersion(bundle.get_activity_version()) <= \ + NormalizedVersion(installed_bundle.get_activity_version()): return True return False - def install(self, bundle, uid=None): + def install(self, bundle, uid=None, force_downgrade=False): activities_path = env.get_user_activities_path() for installed_bundle in self._bundles: if bundle.get_bundle_id() == installed_bundle.get_bundle_id() and \ - bundle.get_activity_version() <= \ - installed_bundle.get_activity_version(): - raise AlreadyInstalledException + NormalizedVersion(bundle.get_activity_version()) <= \ + NormalizedVersion(installed_bundle.get_activity_version()): + if not force_downgrade: + raise AlreadyInstalledException + else: + self.uninstall(installed_bundle, force=True) elif bundle.get_bundle_id() == installed_bundle.get_bundle_id(): self.uninstall(installed_bundle, force=True) @@ -437,20 +432,17 @@ class BundleRegistry(gobject.GObject): try: self.uninstall(bundle, force=True) except Exception: - logging.error('Uninstall failed, still trying to install ' \ - 'newer bundle:\n' + \ - traceback.format_exc()) + logging.exception('Uninstall failed, still trying to install' + ' newer bundle:') else: - logging.warning('Unable to uninstall system activity, ' \ + logging.warning('Unable to uninstall system activity, ' 'installing upgraded version in user activities') self.install(bundle) -_instance = None def get_registry(): global _instance if not _instance: _instance = BundleRegistry() return _instance - diff --git a/src/jarabe/model/filetransfer.py b/src/jarabe/model/filetransfer.py index 0d21793..710c3a4 100644 --- a/src/jarabe/model/filetransfer.py +++ b/src/jarabe/model/filetransfer.py @@ -33,6 +33,7 @@ from sugar import dispatch from jarabe.util.telepathy import connection_watcher from jarabe.model import neighborhood + FT_STATE_NONE = 0 FT_STATE_PENDING = 1 FT_STATE_ACCEPTED = 2 @@ -52,14 +53,18 @@ FT_REASON_REMOTE_ERROR = 6 CHANNEL_TYPE_FILE_TRANSFER = \ 'org.freedesktop.Telepathy.Channel.Type.FileTransfer' +new_file_transfer = dispatch.Signal() + + # TODO Move to use splice_async() in Sugar 0.88 class StreamSplicer(gobject.GObject): - _CHUNK_SIZE = 10240 # 10K + _CHUNK_SIZE = 10240 # 10K __gsignals__ = { 'finished': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), } + def __init__(self, input_stream, output_stream): gobject.GObject.__init__(self) @@ -105,6 +110,7 @@ class StreamSplicer(gobject.GObject): gobject.PRIORITY_LOW, user_data=data) + class BaseFileTransfer(gobject.GObject): def __init__(self, connection): @@ -176,6 +182,7 @@ class BaseFileTransfer(gobject.GObject): def cancel(self): self.channel[CHANNEL].Close() + class IncomingFileTransfer(BaseFileTransfer): def __init__(self, connection, object_path, props): BaseFileTransfer.__init__(self, connection) @@ -220,6 +227,7 @@ class IncomingFileTransfer(BaseFileTransfer): self._splicer = StreamSplicer(input_stream, output_stream) self._splicer.start() + class OutgoingFileTransfer(BaseFileTransfer): def __init__(self, buddy, file_name, title, description, mime_type): @@ -283,6 +291,7 @@ class OutgoingFileTransfer(BaseFileTransfer): def cancel(self): self.channel[CHANNEL].Close() + def _new_channels_cb(connection, channels): for object_path, props in channels: if props[CHANNEL + '.ChannelType'] == CHANNEL_TYPE_FILE_TRANSFER and \ @@ -294,17 +303,21 @@ def _new_channels_cb(connection, channels): object_path, props) new_file_transfer.send(None, file_transfer=incoming_file_transfer) + def _monitor_connection(connection): logging.debug('connection added %r', connection) connection[CONNECTION_INTERFACE_REQUESTS].connect_to_signal('NewChannels', lambda channels: _new_channels_cb(connection, channels)) + def _connection_added_cb(conn_watcher, connection): _monitor_connection(connection) + def _connection_removed_cb(conn_watcher, connection): logging.debug('connection removed %r', connection) + def init(): conn_watcher = connection_watcher.get_instance() conn_watcher.connect('connection-added', _connection_added_cb) @@ -313,11 +326,13 @@ def init(): for connection in conn_watcher.get_connections(): _monitor_connection(connection) + def start_transfer(buddy, file_name, title, description, mime_type): outgoing_file_transfer = OutgoingFileTransfer(buddy, file_name, title, description, mime_type) new_file_transfer.send(None, file_transfer=outgoing_file_transfer) + def file_transfer_available(): conn_watcher = connection_watcher.get_instance() for connection in conn_watcher.get_connections(): @@ -337,18 +352,17 @@ def file_transfer_available(): return False -new_file_transfer = dispatch.Signal() if __name__ == '__main__': import tempfile - input_stream = gio.File('/home/tomeu/isos/Soas2-200904031934.iso').read() - output_stream = gio.File(tempfile.mkstemp()[1]).append_to() + test_file_name = '/home/tomeu/isos/Soas2-200904031934.iso' + test_input_stream = gio.File(test_file_name).read() + test_output_stream = gio.File(tempfile.mkstemp()[1]).append_to() # TODO: Use splice_async when it gets implemented - splicer = StreamSplicer(input_stream, output_stream) + splicer = StreamSplicer(test_input_stream, test_output_stream) splicer.start() loop = gobject.MainLoop() loop.run() - diff --git a/src/jarabe/model/friends.py b/src/jarabe/model/friends.py index 98bff96..192f683 100644 --- a/src/jarabe/model/friends.py +++ b/src/jarabe/model/friends.py @@ -27,10 +27,14 @@ from sugar.graphics.xocolor import XoColor from jarabe.model.buddy import BuddyModel from jarabe.model import neighborhood + +_model = None + + class FriendBuddyModel(BuddyModel): __gtype_name__ = 'SugarFriendBuddyModel' - _NOT_PRESENT_COLOR = "#D5D5D5,#FFFFFF" + _NOT_PRESENT_COLOR = '#D5D5D5,#FFFFFF' def __init__(self, nick, key): self._online_buddy = None @@ -45,7 +49,7 @@ class FriendBuddyModel(BuddyModel): if buddy is not None: self._set_online_buddy(buddy) - def __buddy_added_cb(self, neighborhood, buddy): + def __buddy_added_cb(self, model_, buddy): if buddy.key != self.key: return self._set_online_buddy(buddy) @@ -56,7 +60,7 @@ class FriendBuddyModel(BuddyModel): self.notify('color') self.notify('present') - def __buddy_removed_cb(self, neighborhood, buddy): + def __buddy_removed_cb(self, model_, buddy): if buddy.key != self.key: return self._online_buddy = None @@ -87,12 +91,13 @@ class FriendBuddyModel(BuddyModel): handle = gobject.property(type=object, getter=get_handle) + class Friends(gobject.GObject): __gsignals__ = { - 'friend-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'friend-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([str])) + 'friend-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'friend-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([str])), } def __init__(self): @@ -104,7 +109,7 @@ class Friends(gobject.GObject): self.load() def has_buddy(self, buddy): - return self._friends.has_key(buddy.get_key()) + return buddy.get_key() in self._friends def add_friend(self, buddy_info): self._friends[buddy_info.get_key()] = buddy_info @@ -176,7 +181,6 @@ class Friends(gobject.GObject): reply_handler=friends_synced, error_handler=friends_synced_error) -_model = None def get_model(): global _model diff --git a/src/jarabe/model/invites.py b/src/jarabe/model/invites.py index e5a4d9d..d2a2e0c 100644 --- a/src/jarabe/model/invites.py +++ b/src/jarabe/model/invites.py @@ -38,9 +38,12 @@ from jarabe.model import bundleregistry from jarabe.model import neighborhood from jarabe.journal import misc + CONNECTION_INTERFACE_ACTIVITY_PROPERTIES = \ 'org.laptop.Telepathy.ActivityProperties' +_instance = None + class ActivityInvite(object): """Invitation to a shared activity.""" @@ -96,8 +99,8 @@ class ActivityInvite(object): obj = bus.get_object(CHANNEL_DISPATCHER, self.dispatch_operation_path) dispatch_operation = dbus.Interface(obj, CHANNEL_DISPATCH_OPERATION) dispatch_operation.HandleWith(self._handler, - reply_handler=self.__handle_with_reply_cb, - error_handler=self.__handle_with_reply_cb) + reply_handler=self.__handle_with_reply_cb, + error_handler=self.__handle_with_reply_cb) def __handle_with_reply_cb(self, error=None): if error is not None: @@ -105,12 +108,13 @@ class ActivityInvite(object): else: logging.debug('__handle_with_reply_cb') + class Invites(gobject.GObject): __gsignals__ = { - 'invite-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'invite-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])) + 'invite-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'invite-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), } def __init__(self): @@ -199,8 +203,8 @@ class Invites(gobject.GObject): obj = bus.get_object(CHANNEL_DISPATCHER, dispatch_operation_path) dispatch_operation = dbus.Interface(obj, CHANNEL_DISPATCH_OPERATION) dispatch_operation.HandleWith(handler, - reply_handler=self.__handle_with_reply_cb, - error_handler=self.__handle_with_reply_cb) + reply_handler=self.__handle_with_reply_cb, + error_handler=self.__handle_with_reply_cb) def __handle_with_reply_cb(self, error=None): if error is not None: @@ -230,8 +234,6 @@ class Invites(gobject.GObject): return self._dispatch_operations.values().__iter__() -_instance = None - def get_instance(): global _instance if not _instance: diff --git a/src/jarabe/model/mimeregistry.py b/src/jarabe/model/mimeregistry.py index 537f6f3..7fb5bcf 100644 --- a/src/jarabe/model/mimeregistry.py +++ b/src/jarabe/model/mimeregistry.py @@ -21,6 +21,7 @@ import gconf _DEFAULTS_KEY = '/desktop/sugar/journal/defaults' _GCONF_INVALID_CHARS = re.compile('[^a-zA-Z0-9-_/.]') + _instance = None diff --git a/src/jarabe/model/neighborhood.py b/src/jarabe/model/neighborhood.py index 91dd059..ca4c5bf 100644 --- a/src/jarabe/model/neighborhood.py +++ b/src/jarabe/model/neighborhood.py @@ -48,6 +48,7 @@ from sugar.profile import get_profile from jarabe.model.buddy import BuddyModel, get_owner_instance from jarabe.model import bundleregistry + ACCOUNT_MANAGER_SERVICE = 'org.freedesktop.Telepathy.AccountManager' ACCOUNT_MANAGER_PATH = '/org/freedesktop/Telepathy/AccountManager' CHANNEL_DISPATCHER_SERVICE = 'org.freedesktop.Telepathy.ChannelDispatcher' @@ -65,17 +66,21 @@ Time in seconds to wait when querying contact properties. Some jabber servers will be very slow in returning these queries, so just be patient. """ +_model = None + + class ActivityModel(gobject.GObject): __gsignals__ = { - 'current-buddy-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'current-buddy-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'buddy-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), + 'current-buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'current-buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), } + def __init__(self, activity_id, room_handle): gobject.GObject.__init__(self) @@ -102,7 +107,8 @@ class ActivityModel(gobject.GObject): def set_bundle(self, bundle): self._bundle = bundle - bundle = gobject.property(type=object, getter=get_bundle, setter=set_bundle) + bundle = gobject.property(type=object, getter=get_bundle, + setter=set_bundle) def get_name(self): return self._name @@ -151,30 +157,29 @@ class ActivityModel(gobject.GObject): current_buddies = gobject.property(type=object, getter=get_current_buddies) + class _Account(gobject.GObject): __gsignals__ = { - 'activity-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object, object])), - 'activity-updated': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object, object])), - 'activity-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'buddy-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object, object, object])), - 'buddy-updated': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object, object])), - 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'buddy-joined-activity': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object, object])), - 'buddy-left-activity': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object, object])), + 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'activity-updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object, object])), + 'buddy-updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-joined-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), + 'buddy-left-activity': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object, object])), 'current-activity-updated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object, object])), - 'connected': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), - 'disconnected': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])), + 'connected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'disconnected': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), } def __init__(self, account_path): @@ -203,7 +208,8 @@ class _Account(gobject.GObject): 'AccountPropertyChanged', self.__account_property_changed_cb) def __error_handler_cb(self, function_name, error): - raise RuntimeError('Error when calling %s: %s' % (function_name, error)) + raise RuntimeError('Error when calling %s: %s' % (function_name, + error)) def __got_connection_cb(self, connection_path): logging.debug('_Account.__got_connection_cb %r', connection_path) @@ -379,7 +385,8 @@ class _Account(gobject.GObject): logging.debug('Got handle %r with nick %r, going to update', handle, alias) properties = {CONNECTION_INTERFACE_ALIASING + '/alias': alias} - self.emit('buddy-updated', self._buddy_handles[handle], properties) + self.emit('buddy-updated', self._buddy_handles[handle], + properties) def __presences_changed_cb(self, presences): logging.debug('_Account.__presences_changed_cb %r', presences) @@ -573,7 +580,8 @@ class _Account(gobject.GObject): connection.GetActivities( handle, - reply_handler=partial(self.__got_activities_cb, handle), + reply_handler=partial(self.__got_activities_cb, + handle), error_handler=partial(self.__error_handler_cb, 'BuddyInfo.GetActivities'), timeout=_QUERY_DBUS_TIMEOUT) @@ -609,21 +617,22 @@ class _Account(gobject.GObject): reply_handler=self.__set_enabled_cb, error_handler=partial(self.__error_handler_cb, 'Account.SetEnabled'), - dbus_interface='org.freedesktop.DBus.Properties') + dbus_interface=dbus.PROPERTIES_IFACE) def __set_enabled_cb(self): logging.debug('_Account.__set_enabled_cb success') + class Neighborhood(gobject.GObject): __gsignals__ = { - 'activity-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'activity-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'buddy-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])), - 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])) + 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([object])), } def __init__(self): @@ -635,7 +644,8 @@ class Neighborhood(gobject.GObject): self._server_account = None client = gconf.client_get_default() - client.add_dir('/desktop/sugar/collaboration', gconf.CLIENT_PRELOAD_NONE) + client.add_dir('/desktop/sugar/collaboration', + gconf.CLIENT_PRELOAD_NONE) client.notify_add('/desktop/sugar/collaboration/jabber_server', self.__jabber_server_changed_cb) client.add_dir('/desktop/sugar/user/nick', gconf.CLIENT_PRELOAD_NONE) @@ -732,7 +742,8 @@ class Neighborhood(gobject.GObject): client = gconf.client_get_default() nick = client.get_string('/desktop/sugar/user/nick') - server = client.get_string('/desktop/sugar/collaboration/jabber_server') + server = client.get_string('/desktop/sugar/collaboration' + '/jabber_server') key_hash = get_profile().privkey_hash params = { @@ -764,7 +775,8 @@ class Neighborhood(gobject.GObject): def _get_jabber_account_id(self): public_key_hash = sha1(get_profile().pubkey).hexdigest() client = gconf.client_get_default() - server = client.get_string('/desktop/sugar/collaboration/jabber_server') + server = client.get_string('/desktop/sugar/collaboration' + '/jabber_server') return '%s@%s' % (public_key_hash, server) def __jabber_server_changed_cb(self, client, timestamp, entry, *extra): @@ -774,7 +786,8 @@ class Neighborhood(gobject.GObject): account = bus.get_object(ACCOUNT_MANAGER_SERVICE, self._server_account.object_path) - server = client.get_string('/desktop/sugar/collaboration/jabber_server') + server = client.get_string( + '/desktop/sugar/collaboration/jabber_server') account_id = self._get_jabber_account_id() needs_reconnect = account.UpdateParameters({'server': server, 'account': account_id, @@ -830,8 +843,8 @@ class Neighborhood(gobject.GObject): return if contact_id not in self._buddies: - logging.debug('__buddy_updated_cb Unknown buddy with contact_id %r', - contact_id) + logging.debug('__buddy_updated_cb Unknown buddy with contact_id' + ' %r', contact_id) return buddy = self._buddies[contact_id] @@ -917,8 +930,8 @@ class Neighborhood(gobject.GObject): 'contact_id %r', contact_id) return if activity_id and activity_id not in self._activities: - logging.debug('__current_activity_updated_cb Unknown activity with ' - 'id %s', activity_id) + logging.debug('__current_activity_updated_cb Unknown activity with' + ' id %s', activity_id) activity_id = '' buddy = self._buddies[contact_id] @@ -987,7 +1000,6 @@ class Neighborhood(gobject.GObject): def get_activities(self): return self._activities.values() -_model = None def get_model(): global _model diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py index a7eef8c..504c723 100644 --- a/src/jarabe/model/network.py +++ b/src/jarabe/model/network.py @@ -34,6 +34,7 @@ from sugar import dispatch from sugar import env from sugar.util import unique_id + DEVICE_TYPE_802_3_ETHERNET = 1 DEVICE_TYPE_802_11_WIRELESS = 2 DEVICE_TYPE_GSM_MODEM = 3 @@ -129,11 +130,16 @@ NM_802_11_DEVICE_CAP_RSN = 0x00000020 SETTINGS_SERVICE = 'org.freedesktop.NetworkManagerUserSettings' +NM_SERVICE = 'org.freedesktop.NetworkManager' +NM_IFACE = 'org.freedesktop.NetworkManager' +NM_PATH = '/org/freedesktop/NetworkManager' +NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' NM_SETTINGS_PATH = '/org/freedesktop/NetworkManagerSettings' NM_SETTINGS_IFACE = 'org.freedesktop.NetworkManagerSettings' NM_CONNECTION_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection' NM_SECRETS_IFACE = 'org.freedesktop.NetworkManagerSettings.Connection.Secrets' NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' +NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' GSM_USERNAME_PATH = '/desktop/sugar/network/gsm/username' GSM_PASSWORD_PATH = '/desktop/sugar/network/gsm/password' @@ -147,102 +153,102 @@ _conn_counter = 0 _nm_device_state_reason_description = None + def get_error_by_reason(reason): global _nm_device_state_reason_description if _nm_device_state_reason_description is None: _nm_device_state_reason_description = { - NM_DEVICE_STATE_REASON_UNKNOWN: \ - _("The reason for the device state change \ is unknown."), - NM_DEVICE_STATE_REASON_NONE: \ - _("The state change is normal."), - NM_DEVICE_STATE_REASON_NOW_MANAGED: \ - _("The device is now managed."), - NM_DEVICE_STATE_REASON_NOW_UNMANAGED: \ - _("The device is no longer managed."), - NM_DEVICE_STATE_REASON_CONFIG_FAILED: \ - _("The device could not be readied for configuration."), - NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE : \ - _("IP configuration could not be reserved " \ - "(no available address, timeout, etc)."), - NM_DEVICE_STATE_REASON_CONFIG_EXPIRED : \ - _("The IP configuration is no longer valid."), - NM_DEVICE_STATE_REASON_NO_SECRETS : \ - _("Secrets were required, but not provided."), - NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT : \ - _("The 802.1X supplicant disconnected from "\ - "the access point or authentication server."), - NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED : \ - _("Configuration of the 802.1X supplicant failed."), - NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED : \ - _("The 802.1X supplicant quit or failed unexpectedly."), - NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT : \ - _("The 802.1X supplicant took too long to authenticate."), - NM_DEVICE_STATE_REASON_PPP_START_FAILED : \ - _("The PPP service failed to start within the allowed time."), - NM_DEVICE_STATE_REASON_PPP_DISCONNECT : \ - _("The PPP service disconnected unexpectedly."), - NM_DEVICE_STATE_REASON_PPP_FAILED : \ - _("The PPP service quit or failed unexpectedly."), - NM_DEVICE_STATE_REASON_DHCP_START_FAILED : \ - _("The DHCP service failed to start within the allowed time."), - NM_DEVICE_STATE_REASON_DHCP_ERROR : \ - _("The DHCP service reported an unexpected error."), - NM_DEVICE_STATE_REASON_DHCP_FAILED : \ - _("The DHCP service quit or failed unexpectedly."), - NM_DEVICE_STATE_REASON_SHARED_START_FAILED : \ - _("The shared connection service failed to start."), - NM_DEVICE_STATE_REASON_SHARED_FAILED : \ - _("The shared connection service quit or " \ - "failed unexpectedly."), - NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED : \ - _("The AutoIP service failed to start."), - NM_DEVICE_STATE_REASON_AUTOIP_ERROR : \ - _("The AutoIP service reported an unexpected error."), - NM_DEVICE_STATE_REASON_AUTOIP_FAILED : \ - _("The AutoIP service quit or failed unexpectedly."), - NM_DEVICE_STATE_REASON_MODEM_BUSY : \ - _("Dialing failed because the line was busy."), - NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE : \ - _("Dialing failed because there was no dial tone."), - NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER : \ - _("Dialing failed because there was no carrier."), - NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT : \ - _("Dialing timed out."), - NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED : \ - _("Dialing failed."), - NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED : \ - _("Modem initialization failed."), - NM_DEVICE_STATE_REASON_GSM_APN_FAILED : \ - _("Failed to select the specified GSM APN."), - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING : \ - _("Not searching for networks."), - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED : \ - _("Network registration was denied."), - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT : \ - _("Network registration timed out."), - NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED : \ - _("Failed to register with the requested GSM network."), - NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED : \ - _("PIN check failed."), - NM_DEVICE_STATE_REASON_FIRMWARE_MISSING : \ - _("Necessary firmware for the device may be missing."), - NM_DEVICE_STATE_REASON_REMOVED : \ - _("The device was removed."), - NM_DEVICE_STATE_REASON_SLEEPING : \ - _("NetworkManager went to sleep."), - NM_DEVICE_STATE_REASON_CONNECTION_REMOVED : \ - _("The device's active connection was removed " \ - "or disappeared."), - NM_DEVICE_STATE_REASON_USER_REQUESTED : \ - _("A user or client requested the disconnection."), - NM_DEVICE_STATE_REASON_CARRIER : \ + NM_DEVICE_STATE_REASON_UNKNOWN: + _('The reason for the device state change is unknown.'), + NM_DEVICE_STATE_REASON_NONE: + _('The state change is normal.'), + NM_DEVICE_STATE_REASON_NOW_MANAGED: + _('The device is now managed.'), + NM_DEVICE_STATE_REASON_NOW_UNMANAGED: + _('The device is no longer managed.'), + NM_DEVICE_STATE_REASON_CONFIG_FAILED: + _('The device could not be readied for configuration.'), + NM_DEVICE_STATE_REASON_CONFIG_UNAVAILABLE: + _('IP configuration could not be reserved ' + '(no available address, timeout, etc).'), + NM_DEVICE_STATE_REASON_CONFIG_EXPIRED: + _('The IP configuration is no longer valid.'), + NM_DEVICE_STATE_REASON_NO_SECRETS: + _('Secrets were required, but not provided.'), + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: + _('The 802.1X supplicant disconnected from ' + 'the access point or authentication server.'), + NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: + _('Configuration of the 802.1X supplicant failed.'), + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: + _('The 802.1X supplicant quit or failed unexpectedly.'), + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: + _('The 802.1X supplicant took too long to authenticate.'), + NM_DEVICE_STATE_REASON_PPP_START_FAILED: + _('The PPP service failed to start within the allowed time.'), + NM_DEVICE_STATE_REASON_PPP_DISCONNECT: + _('The PPP service disconnected unexpectedly.'), + NM_DEVICE_STATE_REASON_PPP_FAILED: + _('The PPP service quit or failed unexpectedly.'), + NM_DEVICE_STATE_REASON_DHCP_START_FAILED: + _('The DHCP service failed to start within the allowed time.'), + NM_DEVICE_STATE_REASON_DHCP_ERROR: + _('The DHCP service reported an unexpected error.'), + NM_DEVICE_STATE_REASON_DHCP_FAILED: + _('The DHCP service quit or failed unexpectedly.'), + NM_DEVICE_STATE_REASON_SHARED_START_FAILED: + _('The shared connection service failed to start.'), + NM_DEVICE_STATE_REASON_SHARED_FAILED: + _('The shared connection service quit or failed' + ' unexpectedly.'), + NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED: + _('The AutoIP service failed to start.'), + NM_DEVICE_STATE_REASON_AUTOIP_ERROR: + _('The AutoIP service reported an unexpected error.'), + NM_DEVICE_STATE_REASON_AUTOIP_FAILED: + _('The AutoIP service quit or failed unexpectedly.'), + NM_DEVICE_STATE_REASON_MODEM_BUSY: + _('Dialing failed because the line was busy.'), + NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE: + _('Dialing failed because there was no dial tone.'), + NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER: + _('Dialing failed because there was no carrier.'), + NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT: + _('Dialing timed out.'), + NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED: + _('Dialing failed.'), + NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: + _('Modem initialization failed.'), + NM_DEVICE_STATE_REASON_GSM_APN_FAILED: + _('Failed to select the specified GSM APN'), + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: + _('Not searching for networks.'), + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: + _('Network registration was denied.'), + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT: + _('Network registration timed out.'), + NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED: + _('Failed to register with the requested GSM network.'), + NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED: + _('PIN check failed.'), + NM_DEVICE_STATE_REASON_FIRMWARE_MISSING: + _('Necessary firmware for the device may be missing.'), + NM_DEVICE_STATE_REASON_REMOVED: + _('The device was removed.'), + NM_DEVICE_STATE_REASON_SLEEPING: + _('NetworkManager went to sleep.'), + NM_DEVICE_STATE_REASON_CONNECTION_REMOVED: + _("The device's active connection was removed " + "or disappeared."), + NM_DEVICE_STATE_REASON_USER_REQUESTED: + _('A user or client requested the disconnection.'), + NM_DEVICE_STATE_REASON_CARRIER: _("The device's carrier/link changed.")} return _nm_device_state_reason_description[reason] - def frequency_to_channel(frequency): """Returns the channel matching a given radio channel frequency. If a frequency is not in the dictionary channel 1 will be returned. @@ -258,11 +264,12 @@ def frequency_to_channel(frequency): 2452: 9, 2457: 10, 2462: 11, 2467: 12, 2472: 13} if frequency not in ftoc: - logging.warning("The frequency %s can not be mapped to a channel, " \ - "defaulting to channel 1.", frequency) + logging.warning('The frequency %s can not be mapped to a channel, ' + 'defaulting to channel 1.', frequency) return 1 return ftoc[frequency] + def is_sugar_adhoc_network(ssid): """Checks whether an access point is a sugar Ad-hoc network. @@ -294,8 +301,9 @@ class WirelessSecurity(object): wireless_security['group'] = self.group return wireless_security + class Wireless(object): - nm_name = "802-11-wireless" + nm_name = '802-11-wireless' def __init__(self): self.ssid = None @@ -318,7 +326,7 @@ class Wireless(object): class OlpcMesh(object): - nm_name = "802-11-olpc-mesh" + nm_name = '802-11-olpc-mesh' def __init__(self, channel, anycast_addr): self.channel = channel @@ -326,12 +334,12 @@ class OlpcMesh(object): def get_dict(self): ret = { - "ssid": dbus.ByteArray("olpc-mesh"), - "channel": self.channel, + 'ssid': dbus.ByteArray('olpc-mesh'), + 'channel': self.channel, } if self.anycast_addr: - ret["dhcp-anycast-address"] = dbus.ByteArray(self.anycast_addr) + ret['dhcp-anycast-address'] = dbus.ByteArray(self.anycast_addr) return ret @@ -352,6 +360,7 @@ class Connection(object): connection['timestamp'] = self.timestamp return connection + class IP4Config(object): def __init__(self): self.method = None @@ -362,6 +371,7 @@ class IP4Config(object): ip4_config['method'] = self.method return ip4_config + class Serial(object): def __init__(self): self.baud = None @@ -374,6 +384,7 @@ class Serial(object): return serial + class Ppp(object): def __init__(self): pass @@ -382,6 +393,7 @@ class Ppp(object): ppp = {} return ppp + class Gsm(object): def __init__(self): self.apn = None @@ -400,6 +412,7 @@ class Gsm(object): return gsm + class Settings(object): def __init__(self, wireless_cfg=None): self.connection = Connection() @@ -422,6 +435,7 @@ class Settings(object): settings['ipv4'] = self.ip4_config.get_dict() return settings + class Secrets(object): def __init__(self, settings): self.settings = settings @@ -447,6 +461,7 @@ class Secrets(object): return settings + class SettingsGsm(object): def __init__(self): self.connection = Connection() @@ -466,6 +481,7 @@ class SettingsGsm(object): return settings + class SecretsGsm(object): def __init__(self): self.password = None @@ -482,6 +498,7 @@ class SecretsGsm(object): secrets['puk'] = self.puk return {'gsm': secrets} + class NMSettings(dbus.service.Object): def __init__(self): bus = dbus.SystemBus() @@ -509,15 +526,19 @@ class NMSettings(dbus.service.Object): self.secrets_request.send(self, connection=sender, response=kwargs['response']) - def clear_connections(self): - for connection in self.connections.values(): - connection.Removed() - self.connections = {} + def clear_wifi_connections(self): + for uuid in self.connections.keys(): + conn = self.connections[uuid] + if conn._settings.connection.type == \ + NM_CONNECTION_TYPE_802_11_WIRELESS: + conn.Removed() + self.connections.pop(uuid) + class SecretsResponse(object): - ''' Intermediate object to report the secrets from the dialog + """Intermediate object to report the secrets from the dialog back to the connection object and which will inform NM - ''' + """ def __init__(self, connection, reply_cb, error_cb): self._connection = connection self._reply_cb = reply_cb @@ -530,6 +551,7 @@ class SecretsResponse(object): def set_error(self, error): self._error_cb(error) + class NMSettingsConnection(dbus.service.Object): def __init__(self, path, settings, secrets): bus = dbus.SystemBus() @@ -555,13 +577,13 @@ class NMSettingsConnection(dbus.service.Object): def set_connected(self): if self._settings.connection.type == NM_CONNECTION_TYPE_GSM: self._settings.connection.timestamp = int(time.time()) - else: - if not self._settings.connection.autoconnect: - self._settings.connection.autoconnect = True - self._settings.connection.timestamp = int(time.time()) - if self._settings.connection.type == NM_CONNECTION_TYPE_802_11_WIRELESS: - self.Updated(self._settings.get_dict()) - self.save() + elif not self._settings.connection.autoconnect: + self._settings.connection.autoconnect = True + self._settings.connection.timestamp = int(time.time()) + if (self._settings.connection.type == + NM_CONNECTION_TYPE_802_11_WIRELESS): + self.Updated(self._settings.get_dict()) + self.save() try: # try to flush resolver cache - SL#1940 @@ -571,10 +593,12 @@ class NMSettingsConnection(dbus.service.Object): res_init = getattr(libc, '__res_init') res_init(None) except: + # pylint: disable=W0702 logging.exception('Error calling libc.__res_init') - def set_disconnected(self): - if self._settings.connection.autoconnect: + def disable_autoconnect(self): + if self._settings.connection.type != NM_CONNECTION_TYPE_GSM and \ + self._settings.connection.autoconnect: self._settings.connection.autoconnect = False self._settings.connection.timestamp = None self.Updated(self._settings.get_dict()) @@ -582,15 +606,15 @@ class NMSettingsConnection(dbus.service.Object): def set_secrets(self, secrets): self._secrets = secrets - if self._settings.connection.type == NM_CONNECTION_TYPE_802_11_WIRELESS: + if self._settings.connection.type == \ + NM_CONNECTION_TYPE_802_11_WIRELESS: self.save() def get_settings(self): return self._settings def save(self): - profile_path = env.get_profile_path() - config_path = os.path.join(profile_path, 'nm', 'connections.cfg') + config_path = _get_wifi_connections_path() config = ConfigParser.ConfigParser() try: @@ -658,24 +682,28 @@ class NMSettingsConnection(dbus.service.Object): self.path, request_new) if self._settings.connection.type is not NM_CONNECTION_TYPE_GSM: if request_new or self._secrets is None: - # request_new is for example the case when the pw on the AP changes + # request_new is for example the case when the pw on the AP + # changes response = SecretsResponse(self, reply, error) try: self.secrets_request.send(self, response=response) except Exception: - logging.exception('Error requesting the secrets via dialog') + logging.exception('Error requesting the secrets via' + ' dialog') else: reply(self._secrets.get_dict()) else: if not request_new: reply(self._secrets.get_dict()) else: - raise Exception('The stored GSM secret has already been supplied ') + raise Exception('The stored GSM secret has already been' + ' supplied') + class AccessPoint(gobject.GObject): __gsignals__ = { 'props-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) + ([gobject.TYPE_PYOBJECT])), } def __init__(self, device, model): @@ -695,8 +723,7 @@ class AccessPoint(gobject.GObject): self.channel = 0 def initialize(self): - model_props = dbus.Interface(self.model, - 'org.freedesktop.DBus.Properties') + model_props = dbus.Interface(self.model, dbus.PROPERTIES_IFACE) model_props.GetAll(NM_ACCESSPOINT_IFACE, byte_arrays=True, reply_handler=self._ap_properties_changed_cb, error_handler=self._get_all_props_error_cb) @@ -741,7 +768,7 @@ class AccessPoint(gobject.GObject): else: fl |= 1 << 6 - hashstr = str(fl) + "@" + self.name + hashstr = str(fl) + '@' + self.name return hash(hashstr) def _update_properties(self, properties): @@ -780,6 +807,7 @@ class AccessPoint(gobject.GObject): path=self.model.object_path, dbus_interface=NM_ACCESSPOINT_IFACE) + def get_settings(): global _nm_settings if _nm_settings is None: @@ -794,6 +822,7 @@ def get_settings(): return None return _nm_settings + def find_connection_by_ssid(ssid): settings = get_settings() if settings is None: @@ -803,12 +832,14 @@ def find_connection_by_ssid(ssid): for conn_index in connections: connection = connections[conn_index] - if connection._settings.connection.type == NM_CONNECTION_TYPE_802_11_WIRELESS: - if connection._settings.wireless.ssid == ssid: - return connection + if connection._settings.connection.type == \ + NM_CONNECTION_TYPE_802_11_WIRELESS and \ + connection._settings.wireless.ssid == ssid: + return connection return None + def add_connection(uuid, settings, secrets=None): global _conn_counter @@ -819,19 +850,26 @@ def add_connection(uuid, settings, secrets=None): _nm_settings.add_connection(uuid, conn) return conn -def load_wifi_connections(): + +def _get_wifi_connections_path(): profile_path = env.get_profile_path() - config_path = os.path.join(profile_path, 'nm', 'connections.cfg') + return os.path.join(profile_path, 'nm', 'connections.cfg') - config = ConfigParser.ConfigParser() + +def _create_wifi_connections(config_path): + if not os.path.exists(os.path.dirname(config_path)): + os.makedirs(os.path.dirname(config_path), 0755) + f = open(config_path, 'w') + f.close() + + +def load_wifi_connections(): + config_path = _get_wifi_connections_path() if not os.path.exists(config_path): - if not os.path.exists(os.path.dirname(config_path)): - os.makedirs(os.path.dirname(config_path), 0755) - f = open(config_path, 'w') - config.write(f) - f.close() + _create_wifi_connections(config_path) + config = ConfigParser.ConfigParser() try: if not config.read(config_path): logging.error('Error reading the nm config file') @@ -936,12 +974,14 @@ def load_gsm_connection(): except Exception: logging.exception('Error adding gsm connection to NMSettings.') else: - logging.exception("No gsm connection was set in GConf.") + logging.warning('No gsm connection was set in GConf.') + def load_connections(): load_wifi_connections() load_gsm_connection() + def find_gsm_connection(): settings = get_settings() if settings is None: @@ -955,3 +995,39 @@ def find_gsm_connection(): logging.debug('There is no gsm connection in the NMSettings.') return None + + +def have_wifi_connections(): + return bool(get_settings().connections) + + +def clear_wifi_connections(): + if _nm_settings is not None: + _nm_settings.clear_wifi_connections() + + config_path = _get_wifi_connections_path() + _create_wifi_connections(config_path) + + +def disconnect_access_points(ap_paths): + """ + Disconnect all devices connected to any of the given access points. + """ + bus = dbus.SystemBus() + netmgr_obj = bus.get_object(NM_SERVICE, NM_PATH) + netmgr = dbus.Interface(netmgr_obj, NM_IFACE) + netmgr_props = dbus.Interface(netmgr, dbus.PROPERTIES_IFACE) + active_connection_paths = netmgr_props.Get(NM_IFACE, 'ActiveConnections') + + for conn_path in active_connection_paths: + conn_obj = bus.get_object(NM_IFACE, conn_path) + conn_props = dbus.Interface(conn_obj, dbus.PROPERTIES_IFACE) + ap_path = conn_props.Get(NM_ACTIVE_CONN_IFACE, 'SpecificObject') + if ap_path == '/' or ap_path not in ap_paths: + continue + + dev_paths = conn_props.Get(NM_ACTIVE_CONN_IFACE, 'Devices') + for dev_path in dev_paths: + dev_obj = bus.get_object(NM_SERVICE, dev_path) + dev = dbus.Interface(dev_obj, NM_DEVICE_IFACE) + dev.Disconnect() diff --git a/src/jarabe/model/notifications.py b/src/jarabe/model/notifications.py index f2e2d65..ec14056 100644 --- a/src/jarabe/model/notifications.py +++ b/src/jarabe/model/notifications.py @@ -23,9 +23,13 @@ from sugar import dispatch from jarabe import config -_DBUS_SERVICE = "org.freedesktop.Notifications" -_DBUS_IFACE = "org.freedesktop.Notifications" -_DBUS_PATH = "/org/freedesktop/Notifications" + +_DBUS_SERVICE = 'org.freedesktop.Notifications' +_DBUS_IFACE = 'org.freedesktop.Notifications' +_DBUS_PATH = '/org/freedesktop/Notifications' + +_instance = None + class NotificationService(dbus.service.Object): def __init__(self): @@ -43,7 +47,8 @@ class NotificationService(dbus.service.Object): hints, expire_timeout): logging.debug('Received notification: %r', [app_name, replaces_id, - '<app_icon>', summary, body, actions, '<hints>', expire_timeout]) + '<app_icon>', summary, body, actions, '<hints>', + expire_timeout]) if replaces_id > 0: notification_id = replaces_id @@ -73,16 +78,14 @@ class NotificationService(dbus.service.Object): def GetServerInformation(self, name, vendor, version): return 'Sugar Shell', 'Sugar', config.version - - @dbus.service.signal(_DBUS_IFACE, signature="uu") + @dbus.service.signal(_DBUS_IFACE, signature='uu') def NotificationClosed(self, notification_id, reason): pass - @dbus.service.signal(_DBUS_IFACE, signature="us") + @dbus.service.signal(_DBUS_IFACE, signature='us') def ActionInvoked(self, notification_id, action_key): pass -_instance = None def get_service(): global _instance @@ -90,6 +93,6 @@ def get_service(): _instance = NotificationService() return _instance + def init(): get_service() - diff --git a/src/jarabe/model/olpcmesh.py b/src/jarabe/model/olpcmesh.py index 60f6be4..f070100 100644 --- a/src/jarabe/model/olpcmesh.py +++ b/src/jarabe/model/olpcmesh.py @@ -24,13 +24,14 @@ from jarabe.model.network import Settings from jarabe.model.network import OlpcMesh as OlpcMeshSettings from sugar.util import unique_id + _NM_SERVICE = 'org.freedesktop.NetworkManager' _NM_IFACE = 'org.freedesktop.NetworkManager' _NM_PATH = '/org/freedesktop/NetworkManager' _NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' _NM_OLPC_MESH_IFACE = 'org.freedesktop.NetworkManager.Device.OlpcMesh' -_XS_ANYCAST = "\xc0\x27\xc0\x27\xc0\x00" +_XS_ANYCAST = '\xc0\x27\xc0\x27\xc0\x00' DEVICE_STATE_UNKNOWN = 0 DEVICE_STATE_UNMANAGED = 1 @@ -43,6 +44,7 @@ DEVICE_STATE_IP_CONFIG = 7 DEVICE_STATE_ACTIVATED = 8 DEVICE_STATE_FAILED = 9 + class OlpcMeshManager(object): def __init__(self, mesh_device): self._bus = dbus.SystemBus() @@ -56,14 +58,12 @@ class OlpcMeshManager(object): """ - props = dbus.Interface(self.mesh_device, - 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self.mesh_device, dbus.PROPERTIES_IFACE) props.Get(_NM_DEVICE_IFACE, 'State', reply_handler=self.__get_mesh_state_reply_cb, error_handler=self.__get_state_error_cb) - props = dbus.Interface(self.eth_device, - 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self.eth_device, dbus.PROPERTIES_IFACE) props.Get(_NM_DEVICE_IFACE, 'State', reply_handler=self.__get_eth_state_reply_cb, error_handler=self.__get_state_error_cb) @@ -88,8 +88,7 @@ class OlpcMeshManager(object): self._start_automesh() def _get_companion_device(self): - props = dbus.Interface(self.mesh_device, - 'org.freedesktop.DBus.Properties') + props = dbus.Interface(self.mesh_device, dbus.PROPERTIES_IFACE) eth_device_o = props.Get(_NM_OLPC_MESH_IFACE, 'Companion') return self._bus.get_object(_NM_SERVICE, eth_device_o) @@ -119,7 +118,7 @@ class OlpcMeshManager(object): def __eth_device_state_changed_cb(self, new_state, old_state, reason): """If a connection is activated on the eth device, stop trying our automatic connections. - + """ self._eth_device_state = new_state self._maybe_schedule_idle_check() @@ -147,7 +146,7 @@ class OlpcMeshManager(object): def _idle_check(self): if self._mesh_device_state == DEVICE_STATE_DISCONNECTED \ and self._eth_device_state == DEVICE_STATE_DISCONNECTED: - logging.debug("starting automesh due to inactivity") + logging.debug('starting automesh due to inactivity') self._start_automesh() return False @@ -170,7 +169,7 @@ class OlpcMeshManager(object): logging.error('Failed to activate connection: %s', err) def _activate_connection(self, channel, anycast_address=None): - logging.debug("activate channel %d anycast %r", + logging.debug('activate channel %d anycast %r', channel, anycast_address) proxy = self._bus.get_object(_NM_SERVICE, _NM_PATH) network_manager = dbus.Interface(proxy, _NM_IFACE) @@ -211,4 +210,3 @@ class OlpcMeshManager(object): self._connection_queue.append((6, _XS_ANYCAST)) self._connection_queue.append((1, _XS_ANYCAST)) self._try_next_connection_from_queue() - diff --git a/src/jarabe/model/screen.py b/src/jarabe/model/screen.py index 4403c1c..7d34d45 100644 --- a/src/jarabe/model/screen.py +++ b/src/jarabe/model/screen.py @@ -18,12 +18,14 @@ import logging import dbus + _HARDWARE_MANAGER_INTERFACE = 'org.freedesktop.ohm.Keystore' _HARDWARE_MANAGER_SERVICE = 'org.freedesktop.ohm' _HARDWARE_MANAGER_OBJECT_PATH = '/org/freedesktop/ohm/Keystore' _ohm_service = None + def _get_ohm(): global _ohm_service if _ohm_service is None: @@ -35,9 +37,9 @@ def _get_ohm(): return _ohm_service + def set_dcon_freeze(frozen): try: - _get_ohm().SetKey("display.dcon_freeze", frozen) + _get_ohm().SetKey('display.dcon_freeze', frozen) except dbus.DBusException: logging.error('Cannot unfreeze the DCON') - diff --git a/src/jarabe/model/session.py b/src/jarabe/model/session.py index e7b70cd..9b277ff 100644 --- a/src/jarabe/model/session.py +++ b/src/jarabe/model/session.py @@ -24,8 +24,10 @@ import logging from sugar import session from sugar import env + _session_manager = None + class SessionManager(session.SessionManager): MODE_LOGOUT = 0 MODE_SHUTDOWN = 1 @@ -73,14 +75,15 @@ class SessionManager(session.SessionManager): def _close_emulator(self): gtk.main_quit() - if os.environ.has_key('SUGAR_EMULATOR_PID'): + if 'SUGAR_EMULATOR_PID' in os.environ: pid = int(os.environ['SUGAR_EMULATOR_PID']) os.kill(pid, signal.SIGTERM) - # Need to call this ASAP so the atexit handlers get called before we get - # killed by the X (dis)connection + # Need to call this ASAP so the atexit handlers get called before we + # get killed by the X (dis)connection sys.exit() + def get_session_manager(): global _session_manager diff --git a/src/jarabe/model/shell.py b/src/jarabe/model/shell.py index db0e050..63f6173 100644 --- a/src/jarabe/model/shell.py +++ b/src/jarabe/model/shell.py @@ -31,9 +31,11 @@ from sugar.graphics.xocolor import XoColor from jarabe.model.bundleregistry import get_registry from jarabe.model import neighborhood -_SERVICE_NAME = "org.laptop.Activity" -_SERVICE_PATH = "/org/laptop/Activity" -_SERVICE_INTERFACE = "org.laptop.Activity" +_SERVICE_NAME = 'org.laptop.Activity' +_SERVICE_PATH = '/org/laptop/Activity' +_SERVICE_INTERFACE = 'org.laptop.Activity' + +_model = None class Activity(gobject.GObject): @@ -60,11 +62,12 @@ class Activity(gobject.GObject): the "type" of activity being created. activity_id -- unique identifier for this instance of the activity type - window -- Main WnckWindow of the activity + _windows -- WnckWindows registered for the activity. The lowest + one in the stack is the main window. """ gobject.GObject.__init__(self) - self._window = None + self._windows = [] self._service = None self._activity_id = activity_id self._activity_info = activity_info @@ -72,7 +75,7 @@ class Activity(gobject.GObject): self._launch_status = Activity.LAUNCHING if window is not None: - self.set_window(window) + self.add_window(window) self._retrieve_service() @@ -81,8 +84,8 @@ class Activity(gobject.GObject): bus = dbus.SessionBus() self._name_owner_changed_handler = bus.add_signal_receiver( self._name_owner_changed_cb, - signal_name="NameOwnerChanged", - dbus_interface="org.freedesktop.DBus") + signal_name='NameOwnerChanged', + dbus_interface='org.freedesktop.DBus') self._launch_completed_hid = get_model().connect('launch-completed', self.__launch_completed_cb) @@ -94,15 +97,19 @@ class Activity(gobject.GObject): launch_status = gobject.property(getter=get_launch_status) - def set_window(self, window): - """Set the window for the activity - - We allow resetting the window for an activity so that we - can replace the launcher once we get its real window. - """ + def add_window(self, window): + """Add a window to the windows stack.""" if not window: - raise ValueError("window must be valid") - self._window = window + raise ValueError('window must be valid') + self._windows.append(window) + + def remove_window_by_xid(self, xid): + """Remove a window from the windows stack.""" + for wnd in self._windows: + if wnd.get_xid() == xid: + self._windows.remove(wnd) + return True + return False def get_service(self): """Get the activity service @@ -116,8 +123,8 @@ class Activity(gobject.GObject): def get_title(self): """Retrieve the application's root window's suggested title""" - if self._window: - return self._window.get_name() + if self._windows: + return self._windows[0].get_name() else: return '' @@ -157,7 +164,7 @@ class Activity(gobject.GObject): return activity.props.color else: client = gconf.client_get_default() - return XoColor(client.get_string("/desktop/sugar/user/color")) + return XoColor(client.get_string('/desktop/sugar/user/color')) def get_activity_id(self): """Retrieve the "activity_id" passed in to our constructor @@ -169,31 +176,44 @@ class Activity(gobject.GObject): def get_xid(self): """Retrieve the X-windows ID of our root window""" - if self._window is not None: - return self._window.get_xid() + if self._windows: + return self._windows[0].get_xid() else: return None + def has_xid(self, xid): + """Check if an X-window with the given xid is in the windows stack""" + if self._windows: + for wnd in self._windows: + if wnd.get_xid() == xid: + return True + return False + def get_window(self): """Retrieve the X-windows root window of this application - This was stored by the set_window method, which was + This was stored by the add_window method, which was called by HomeModel._add_activity, which was called via a callback that looks for all 'window-opened' events. + We keep a stack of the windows. The lowest window in the + stack that is still valid we consider the main one. + HomeModel currently uses a dbus service query on the activity to determine to which HomeActivity the newly launched window belongs. """ - return self._window + if self._windows: + return self._windows[0] + return None def get_type(self): """Retrieve the activity bundle id for future reference""" - if self._window is None: + if not self._windows: return None else: - return wm.get_bundle_id(self._window) + return wm.get_bundle_id(self._windows[0]) def is_journal(self): """Returns boolean if the activity is of type JournalActivity""" @@ -209,7 +229,9 @@ class Activity(gobject.GObject): def get_pid(self): """Returns the activity's PID""" - return self._window.get_pid() + if not self._windows: + return None + return self._windows[0].get_pid() def get_bundle_path(self): """Returns the activity's bundle directory""" @@ -228,8 +250,8 @@ class Activity(gobject.GObject): def equals(self, activity): if self._activity_id and activity.get_activity_id(): return self._activity_id == activity.get_activity_id() - if self._window.get_xid() and activity.get_xid(): - return self._window.get_xid() == activity.get_xid() + if self._windows[0].get_xid() and activity.get_xid(): + return self._windows[0].get_xid() == activity.get_xid() return False def _get_service_name(self): @@ -245,7 +267,7 @@ class Activity(gobject.GObject): try: bus = dbus.SessionBus() proxy = bus.get_object(self._get_service_name(), - _SERVICE_PATH + "/" + self._activity_id) + _SERVICE_PATH + '/' + self._activity_id) self._service = dbus.Interface(proxy, _SERVICE_INTERFACE) except dbus.DBusException: self._service = None @@ -275,7 +297,7 @@ class Activity(gobject.GObject): pass def _set_active_error(self, err): - logging.error("set_active() failed: %s", err) + logging.error('set_active() failed: %s', err) def _set_launch_status(self, value): get_model().disconnect(self._launch_completed_hid) @@ -310,27 +332,22 @@ class ShellModel(gobject.GObject): """ __gsignals__ = { - 'activity-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'activity-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), + 'activity-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'activity-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), 'active-activity-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), + ([gobject.TYPE_PYOBJECT])), 'tabbing-activity-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'launch-started': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'launch-completed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'launch-failed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'launch-started': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'launch-completed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'launch-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), } ZOOM_MESH = 0 @@ -460,7 +477,7 @@ class ShellModel(gobject.GObject): def set_tabbing_activity(self, activity): """Sets the activity that is currently highlighted during tabbing""" self._tabbing_activity = activity - self.emit("tabbing-activity-changed", self._tabbing_activity) + self.emit('tabbing-activity-changed', self._tabbing_activity) def _set_active_activity(self, home_activity): if self._active_activity == home_activity: @@ -488,6 +505,21 @@ class ShellModel(gobject.GObject): return self._activities.index(obj) def _window_opened_cb(self, screen, window): + """Handle the callback for the 'window opened' event. + + Most activities will register 2 windows during + their lifetime: the launcher window, and the 'main' + app window. + + When the main window appears, we send a signal to + the launcher window to close. + + Some activities (notably non-native apps) open several + windows during their lifetime, switching from one to + the next as the 'main' window. We use a stack to track + them. + + """ if window.get_window_type() == wnck.WINDOW_NORMAL: home_activity = None @@ -510,29 +542,36 @@ class ShellModel(gobject.GObject): window.maximize() if not home_activity: + logging.debug('first window registered for %s' % activity_id) home_activity = Activity(activity_info, activity_id, window) self._add_activity(home_activity) else: - home_activity.set_window(window) + logging.debug('window registered for %s' % activity_id) + home_activity.add_window(window) - if wm.get_sugar_window_type(window) != 'launcher': + if wm.get_sugar_window_type(window) != 'launcher' \ + and home_activity.get_launch_status() == Activity.LAUNCHING: self.emit('launch-completed', home_activity) - startup_time = time.time() - home_activity.get_launch_time() - logging.debug('%s launched in %f seconds.', - home_activity.get_type(), startup_time) + logging.debug('%s launched in %f seconds.' % + (activity_id, startup_time)) if self._active_activity is None: self._set_active_activity(home_activity) def _window_closed_cb(self, screen, window): if window.get_window_type() == wnck.WINDOW_NORMAL: - if self._get_activity_by_xid(window.get_xid()) is not None: - self._remove_activity_by_xid(window.get_xid()) + xid = window.get_xid() + activity = self._get_activity_by_xid(xid) + if activity is not None: + activity.remove_window_by_xid(xid) + if activity.get_window() is None: + logging.debug('last window gone - remove activity %s' % activity) + self._remove_activity(activity) def _get_activity_by_xid(self, xid): for home_activity in self._activities: - if home_activity.get_xid() == xid: + if home_activity.has_xid(xid): return home_activity return None @@ -577,13 +616,6 @@ class ShellModel(gobject.GObject): self.emit('activity-removed', home_activity) self._activities.remove(home_activity) - def _remove_activity_by_xid(self, xid): - home_activity = self._get_activity_by_xid(xid) - if home_activity: - self._remove_activity(home_activity) - else: - logging.error('Model for window %d does not exist.', xid) - def notify_launch(self, activity_id, service_name): registry = get_registry() activity_info = registry.get_bundle(service_name) @@ -606,7 +638,7 @@ class ShellModel(gobject.GObject): def notify_launch_failed(self, activity_id): home_activity = self.get_activity_by_id(activity_id) if home_activity: - logging.debug("Activity %s (%s) launch failed", activity_id, + logging.debug('Activity %s (%s) launch failed', activity_id, home_activity.get_type()) if self.get_launcher(activity_id) is not None: self.emit('launch-failed', home_activity) @@ -631,11 +663,8 @@ class ShellModel(gobject.GObject): return False -_model = None - def get_model(): global _model if _model is None: _model = ShellModel() return _model - diff --git a/src/jarabe/model/sound.py b/src/jarabe/model/sound.py index 65090a4..9e1e748 100644 --- a/src/jarabe/model/sound.py +++ b/src/jarabe/model/sound.py @@ -20,17 +20,23 @@ from sugar import env from sugar import _sugarext from sugar import dispatch + VOLUME_STEP = 10 muted_changed = dispatch.Signal() volume_changed = dispatch.Signal() +_volume = _sugarext.VolumeAlsa() + + def get_muted(): return _volume.get_mute() + def get_volume(): return _volume.get_volume() + def set_volume(new_volume): old_volume = _volume.get_volume() _volume.set_volume(new_volume) @@ -38,6 +44,7 @@ def set_volume(new_volume): volume_changed.send(None) save() + def set_muted(new_state): old_state = _volume.get_mute() _volume.set_mute(new_state) @@ -45,14 +52,14 @@ def set_muted(new_state): muted_changed.send(None) save() + def save(): if env.is_emulator() is False: client = gconf.client_get_default() client.set_int('/desktop/sugar/sound/volume', get_volume()) + def restore(): if env.is_emulator() is False: client = gconf.client_get_default() set_volume(client.get_int('/desktop/sugar/sound/volume')) - -_volume = _sugarext.VolumeAlsa() diff --git a/src/jarabe/model/telepathyclient.py b/src/jarabe/model/telepathyclient.py index f4eccc3..c6fbac1 100644 --- a/src/jarabe/model/telepathyclient.py +++ b/src/jarabe/model/telepathyclient.py @@ -26,9 +26,13 @@ from telepathy.server import DBusProperties from sugar import dispatch + SUGAR_CLIENT_SERVICE = 'org.freedesktop.Telepathy.Client.Sugar' SUGAR_CLIENT_PATH = '/org/freedesktop/Telepathy/Client/Sugar' +_instance = None + + class TelepathyClient(dbus.service.Object, DBusProperties): def __init__(self): self._interfaces = set([CLIENT, CLIENT_HANDLER, @@ -91,7 +95,6 @@ class TelepathyClient(dbus.service.Object, DBusProperties): except Exception, e: logging.exception(e) -_instance = None def get_instance(): global _instance |