Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/src/jarabe/model
diff options
context:
space:
mode:
Diffstat (limited to 'src/jarabe/model')
-rw-r--r--src/jarabe/model/__init__.py1
-rw-r--r--src/jarabe/model/adhoc.py12
-rw-r--r--src/jarabe/model/buddy.py10
-rw-r--r--src/jarabe/model/bundleregistry.py86
-rw-r--r--src/jarabe/model/filetransfer.py26
-rw-r--r--src/jarabe/model/friends.py22
-rw-r--r--src/jarabe/model/invites.py22
-rw-r--r--src/jarabe/model/mimeregistry.py1
-rw-r--r--src/jarabe/model/neighborhood.py112
-rw-r--r--src/jarabe/model/network.py336
-rw-r--r--src/jarabe/model/notifications.py21
-rw-r--r--src/jarabe/model/olpcmesh.py20
-rw-r--r--src/jarabe/model/screen.py6
-rw-r--r--src/jarabe/model/session.py9
-rw-r--r--src/jarabe/model/shell.py165
-rw-r--r--src/jarabe/model/sound.py11
-rw-r--r--src/jarabe/model/telepathyclient.py5
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