Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomeu Vizoso <tomeu@tomeuvizoso.net>2008-10-13 15:31:37 (GMT)
committer Tomeu Vizoso <tomeu@tomeuvizoso.net>2008-10-13 15:31:37 (GMT)
commit2f60fb1b64741fd0c8f6507315f2e1df2a935f0a (patch)
treebd1d6aaffaa354d858f5717156d9a16a399f92a5
parenta1d9e372555402ee9d40f6164a76406605bd6beb (diff)
Move volumesmanager to jarabe.model and add a frame icon for a removable storage device.
-rw-r--r--extensions/deviceicon/Makefile.am3
-rw-r--r--extensions/deviceicon/volume.py53
-rw-r--r--src/jarabe/journal/Makefile.am1
-rw-r--r--src/jarabe/journal/journaltoolbox.py18
-rw-r--r--src/jarabe/journal/volumestoolbar.py58
-rw-r--r--src/jarabe/model/Makefile.am3
-rw-r--r--src/jarabe/model/volume.py (renamed from src/jarabe/journal/volumesmanager.py)137
7 files changed, 128 insertions, 145 deletions
diff --git a/extensions/deviceicon/Makefile.am b/extensions/deviceicon/Makefile.am
index 66268fd..865ef27 100644
--- a/extensions/deviceicon/Makefile.am
+++ b/extensions/deviceicon/Makefile.am
@@ -4,4 +4,5 @@ sugar_PYTHON = \
__init__.py \
wireless.py \
battery.py \
- speaker.py
+ speaker.py \
+ volume.py
diff --git a/extensions/deviceicon/volume.py b/extensions/deviceicon/volume.py
new file mode 100644
index 0000000..a7afe99
--- /dev/null
+++ b/extensions/deviceicon/volume.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2008 One Laptop Per Child
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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
+
+from sugar.graphics.tray import TrayIcon
+
+from jarabe.model import volume
+
+_icons = {}
+
+class DeviceView(TrayIcon):
+ FRAME_POSITION_RELATIVE = 800
+ def __init__(self, volume):
+ TrayIcon.__init__(self, icon_name=volume.icon_name,
+ xo_color=volume.icon_color)
+
+def setup(tray):
+ volumes_manager = volume.get_volumes_manager()
+
+ for vol in volumes_manager.get_volumes():
+ _add_device(vol, tray)
+
+ volumes_manager.connect('volume-added', _volume_added_cb, tray)
+ volumes_manager.connect('volume-removed', _volume_removed_cb, tray)
+
+def _volume_added_cb(volumes_manager, vol, tray):
+ _add_device(vol, tray)
+
+def _volume_removed_cb(volumes_manager, vol, tray):
+ _remove_device(vol, tray)
+
+def _add_device(volume, tray):
+ icon = DeviceView(volume)
+ _icons[volume] = icon
+ tray.add_device(icon)
+
+def _remove_device(volume, tray):
+ icon = _icons[volume]
+ tray.remove_device(icon)
+ del _icons[volume]
+
diff --git a/src/jarabe/journal/Makefile.am b/src/jarabe/journal/Makefile.am
index 11886d6..a8ef90f 100644
--- a/src/jarabe/journal/Makefile.am
+++ b/src/jarabe/journal/Makefile.am
@@ -14,5 +14,4 @@ sugar_PYTHON = \
objectchooser.py \
palettes.py \
query.py \
- volumesmanager.py \
volumestoolbar.py
diff --git a/src/jarabe/journal/journaltoolbox.py b/src/jarabe/journal/journaltoolbox.py
index 7e2709f..637965f 100644
--- a/src/jarabe/journal/journaltoolbox.py
+++ b/src/jarabe/journal/journaltoolbox.py
@@ -36,7 +36,7 @@ from sugar import mime
from sugar.datastore import datastore
from jarabe.model import bundleregistry
-from jarabe.journal import volumesmanager
+from jarabe.model import volume
from jarabe.journal import misc
_AUTOSEARCH_TIMEOUT = 1000
@@ -374,9 +374,9 @@ class EntryToolbar(gtk.Toolbar):
if self._jobject:
misc.resume(self._jobject, service_name)
- def _copy_menu_item_activate_cb(self, menu_item, volume):
+ def _copy_menu_item_activate_cb(self, menu_item, vol):
if self._jobject:
- datastore.copy(self._jobject, volume.id)
+ datastore.copy(self._jobject, vol.id)
def _refresh_copy_palette(self):
palette = self._copy.get_palette()
@@ -385,16 +385,16 @@ class EntryToolbar(gtk.Toolbar):
palette.menu.remove(menu_item)
menu_item.destroy()
- volumes_manager = volumesmanager.get_volumes_manager()
- for volume in volumes_manager.get_volumes():
- if self._jobject.metadata['mountpoint'] == volume.id:
+ volumes_manager = volume.get_volumes_manager()
+ for vol in volumes_manager.get_volumes():
+ if self._jobject.metadata['mountpoint'] == vol.id:
continue
- menu_item = MenuItem(volume.name)
- menu_item.set_image(Icon(icon_name=volume.icon_name,
+ menu_item = MenuItem(vol.name)
+ menu_item.set_image(Icon(icon_name=vol.icon_name,
icon_size=gtk.ICON_SIZE_MENU))
menu_item.connect('activate',
self._copy_menu_item_activate_cb,
- volume)
+ vol)
palette.menu.append(menu_item)
menu_item.show()
diff --git a/src/jarabe/journal/volumestoolbar.py b/src/jarabe/journal/volumestoolbar.py
index 736a130..b29f325 100644
--- a/src/jarabe/journal/volumestoolbar.py
+++ b/src/jarabe/journal/volumestoolbar.py
@@ -24,7 +24,7 @@ from sugar.datastore import datastore
from sugar.graphics.radiotoolbutton import RadioToolButton
from sugar.graphics.palette import Palette
-from jarabe.journal import volumesmanager
+from jarabe.model import volume
class VolumesToolbar(gtk.Toolbar):
__gtype_name__ = 'VolumesToolbar'
@@ -43,43 +43,45 @@ class VolumesToolbar(gtk.Toolbar):
self.connect('destroy', self.__destroy_cb)
- gobject.idle_add(self._set_up_volumes)
+ # TODO: It's unclear now how removable devices will be handled in the
+ # Journal. Disable for now.
+ #gobject.idle_add(self._set_up_volumes)
def __destroy_cb(self, widget):
- volumes_manager = volumesmanager.get_volumes_manager()
+ volumes_manager = volume.get_volumes_manager()
volumes_manager.disconnect(self._volume_added_hid)
volumes_manager.disconnect(self._volume_removed_hid)
def _set_up_volumes(self):
- volumes_manager = volumesmanager.get_volumes_manager()
+ volumes_manager = volume.get_volumes_manager()
self._volume_added_hid = \
volumes_manager.connect('volume-added', self._volume_added_cb)
self._volume_removed_hid = \
volumes_manager.connect('volume-removed',
self._volume_removed_cb)
- for volume in volumes_manager.get_volumes():
- self._add_button(volume)
+ for vol in volumes_manager.get_volumes():
+ self._add_button(vol)
- def _volume_added_cb(self, volumes_manager, volume):
- self._add_button(volume)
+ def _volume_added_cb(self, volumes_manager, vol):
+ self._add_button(vol)
- def _volume_removed_cb(self, volumes_manager, volume):
- self._remove_button(volume)
+ def _volume_removed_cb(self, volumes_manager, vol):
+ self._remove_button(vol)
- def _add_button(self, volume):
- logging.debug('VolumeToolbar._add_button: %r' % volume.name)
+ def _add_button(self, vol):
+ logging.debug('VolumeToolbar._add_button: %r' % vol.name)
if self._volume_buttons:
group = self._volume_buttons[0]
else:
group = None
- palette = Palette(volume.name)
+ palette = Palette(vol.name)
- button = VolumeButton(volume, group)
+ button = VolumeButton(vol, group)
button.set_palette(palette)
- button.connect('toggled', self._button_toggled_cb, volume)
+ button.connect('toggled', self._button_toggled_cb, vol)
if self._volume_buttons:
position = self.get_item_index(self._volume_buttons[-1]) + 1
else:
@@ -89,26 +91,26 @@ class VolumesToolbar(gtk.Toolbar):
self._volume_buttons.append(button)
- if volume.can_unmount:
+ if vol.can_unmount:
menu_item = gtk.MenuItem(_('Unmount'))
- menu_item.connect('activate', self._unmount_activated_cb, volume)
+ menu_item.connect('activate', self._unmount_activated_cb, vol)
palette.menu.append(menu_item)
menu_item.show()
if len(self.get_children()) > 1:
self.show()
- def _button_toggled_cb(self, button, volume):
+ def _button_toggled_cb(self, button, vol):
if button.props.active:
- self.emit('volume-changed', volume.id)
+ self.emit('volume-changed', vol.id)
- def _unmount_activated_cb(self, menu_item, volume):
- logging.debug('VolumesToolbar._unmount_activated_cb: %r', volume.udi)
- volume.unmount()
+ def _unmount_activated_cb(self, menu_item, vol):
+ logging.debug('VolumesToolbar._unmount_activated_cb: %r', vol.udi)
+ vol.unmount()
- def _remove_button(self, volume):
+ def _remove_button(self, vol):
for button in self.get_children():
- if button.volume.id == volume.id:
+ if button.volume.id == vol.id:
self._volume_buttons.remove(button)
self.remove(button)
self.get_children()[0].props.active = True
@@ -118,13 +120,13 @@ class VolumesToolbar(gtk.Toolbar):
return
class VolumeButton(RadioToolButton):
- def __init__(self, volume, group):
+ def __init__(self, vol, group):
RadioToolButton.__init__(self)
- self.props.named_icon = volume.icon_name
- self.props.xo_color = volume.icon_color
+ self.props.named_icon = vol.icon_name
+ self.props.xo_color = vol.icon_color
self.props.group = group
- self.volume = volume
+ self.volume = vol
self.drag_dest_set(gtk.DEST_DEFAULT_ALL,
[('journal-object-id', 0, 0)],
gtk.gdk.ACTION_COPY)
diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am
index d480f0f..a0828d6 100644
--- a/src/jarabe/model/Makefile.am
+++ b/src/jarabe/model/Makefile.am
@@ -11,4 +11,5 @@ sugar_PYTHON = \
network.py \
shell.py \
screen.py \
- sound.py
+ sound.py \
+ volume.py
diff --git a/src/jarabe/journal/volumesmanager.py b/src/jarabe/model/volume.py
index b7e1e37..7ed630f 100644
--- a/src/jarabe/journal/volumesmanager.py
+++ b/src/jarabe/model/volume.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2007, One Laptop Per Child
+# Copyright (C) 2007-2008, One Laptop Per Child
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -15,14 +15,11 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
-from gettext import gettext as _
-import gconf
import gobject
import dbus
-from sugar.graphics.xocolor import XoColor
-from sugar.datastore import datastore
+from sugar import profile
HAL_SERVICE_NAME = 'org.freedesktop.Hal'
HAL_MANAGER_PATH = '/org/freedesktop/Hal/Manager'
@@ -51,16 +48,7 @@ class VolumesManager(gobject.GObject):
def __init__(self):
gobject.GObject.__init__(self)
- self._volumes = []
-
- client = gconf.client_get_default()
- color = XoColor(client.get_string('/desktop/sugar/user/color'))
-
- # Internal flash is not in HAL
- internal_fash_id = datastore.mounts()[0]['id']
- self._volumes.append(Volume(internal_fash_id, _('Journal'),
- 'activity-journal', color,
- None, False))
+ self._volumes = {}
bus = dbus.SystemBus()
proxy = bus.get_object(HAL_SERVICE_NAME, HAL_MANAGER_PATH)
@@ -77,13 +65,7 @@ class VolumesManager(gobject.GObject):
(udi, e))
def get_volumes(self):
- return self._volumes
-
- def _get_volume_by_udi(self, udi):
- for volume in self._volumes:
- if volume.udi == udi:
- return volume
- return None
+ return self._volumes.values()
def _hal_device_added_cb(self, udi):
bus = dbus.SystemBus()
@@ -102,7 +84,7 @@ class VolumesManager(gobject.GObject):
# Ignore volumes without a filesystem.
if device.GetProperty('volume.fsusage') != 'filesystem':
return False
- # Ignore root.
+ # Ignore root.
if device.GetProperty('volume.mount_point') == '/':
return False
@@ -133,7 +115,7 @@ class VolumesManager(gobject.GObject):
HAL_MANAGER_PATH, arg0=udi)
if device.GetProperty('volume.is_mounted'):
- volume_id = self._mount_in_datastore(udi)
+ self._add_volume(udi)
return
label = device.GetProperty('volume.label')
@@ -199,96 +181,41 @@ class VolumesManager(gobject.GObject):
return
if is_mounted:
- if self._get_volume_by_udi(udi) is not None:
- # device already mounted in the datastore
- return
- volume_id = self._mount_in_datastore(udi)
+ if udi not in self._volumes:
+ self._add_volume(udi)
else:
- self.unmount_from_datastore(udi)
- return
-
- def _mount_in_datastore(self, udi):
- logging.debug('VolumeToolbar._mount_in_datastore: %r' % udi)
+ if udi in self._volumes:
+ self._remove_volume(udi)
+ def _add_volume(self, udi):
bus = dbus.SystemBus()
device_object = bus.get_object(HAL_SERVICE_NAME, udi)
device = dbus.Interface(device_object, HAL_DEVICE_IFACE)
-
- mount_point = device.GetProperty('volume.mount_point')
- ds_mounts = datastore.mounts()
- for ds_mount in ds_mounts:
- if mount_point == ds_mount['uri']:
- return ds_mount['id']
-
- mount_id = datastore.mount('inplace:' + mount_point,
- dict(title=mount_point))
- if not mount_id:
- self._unmount_hal_device(udi)
- raise RuntimeError('datastore.mount(%r, %r) failed.' % (
- 'inplace:' + mount_point,
- dict(title=mount_point)))
volume_name = device.GetProperty('volume.label')
if not volume_name:
volume_name = device.GetProperty('volume.uuid')
- client = gconf.client_get_default()
- color = XoColor(client.get_string('/desktop/sugar/user/color'))
- volume = Volume(mount_id,
- volume_name,
- self._get_icon_for_volume(udi),
- color,
- udi,
- True)
- self._volumes.append(volume)
- self.emit('volume-added', volume)
+ volume = Volume(volume_name,
+ self._get_icon_for_volume(device),
+ profile.get_color(),
+ udi)
+ self._volumes[udi] = volume
- logging.debug('mounted volume %s' % mount_point)
+ logging.debug('mounted volume %s' % udi)
+ self.emit('volume-added', volume)
+
+ def _remove_volume(self, udi):
+ volume = self._volumes[udi]
+ del self._volumes[udi]
+ self.emit('volume-removed', volume)
def _hal_device_removed_cb(self, udi):
logging.debug('VolumesManager._hal_device_removed_cb: %r', udi)
- bus = dbus.SystemBus()
- #proxy = bus.get_object(HAL_SERVICE_NAME, HAL_MANAGER_PATH)
- #hal_manager = dbus.Interface(proxy, HAL_MANAGER_IFACE)
- # TODO: Why this doesn't work?
- #if not hal_manager.DeviceExists(udi):
- # self._unmount_from_datastore(udi)
- # self._remove_button(udi)
- # return
-
- proxy = bus.get_object(HAL_SERVICE_NAME, udi)
- device = dbus.Interface(proxy, HAL_DEVICE_IFACE)
- try:
- is_mounted = device.GetProperty('volume.is_mounted')
- except dbus.DBusException, e:
- logging.debug('e: %s' % e)
- self.unmount_from_datastore(udi)
- return
-
- if is_mounted:
- self._unmount_from_datastore(udi)
- self._unmount_hal_device(udi)
-
- def unmount_from_datastore(self, udi):
- logging.debug('VolumesManager._unmount_from_datastore: %r', udi)
- volume = self._get_volume_by_udi(udi)
- if volume is not None:
- datastore.unmount(volume.id)
+ if udi in self._volumes:
+ self._remove_volume(udi)
- self._volumes.remove(volume)
- self.emit('volume-removed', volume)
-
- def unmount_hal_device(self, udi):
- logging.debug('VolumesManager._unmount_hal_device: %r', udi)
- bus = dbus.SystemBus()
- device_object = bus.get_object(HAL_SERVICE_NAME, udi)
- volume = dbus.Interface(device_object, HAL_VOLUME_IFACE)
- volume.Unmount([])
-
- def _get_icon_for_volume(self, udi):
+ def _get_icon_for_volume(self, device):
bus = dbus.SystemBus()
- device_object = bus.get_object(HAL_SERVICE_NAME, udi)
- device = dbus.Interface(device_object, HAL_DEVICE_IFACE)
-
storage_udi = device.GetProperty('block.storage_device')
obj = bus.get_object(HAL_SERVICE_NAME, storage_udi)
storage_device = dbus.Interface(obj, HAL_DEVICE_IFACE)
@@ -300,18 +227,18 @@ class VolumesManager(gobject.GObject):
return 'media-flash-usb'
class Volume(object):
- def __init__(self, volume_id, name, icon_name, icon_color, udi,
- can_unmount):
- self.id = volume_id
+ def __init__(self, name, icon_name, icon_color, udi):
self.name = name
self.icon_name = icon_name
self.icon_color = icon_color
self.udi = udi
- self.can_unmount = can_unmount
def unmount(self):
- get_volumes_manager().unmount_from_datastore(self.udi)
- get_volumes_manager().unmount_hal_device(self.udi)
+ logging.debug('Volumes.unmount: %r', self.udi)
+ bus = dbus.SystemBus()
+ device_object = bus.get_object(HAL_SERVICE_NAME, self.udi)
+ volume = dbus.Interface(device_object, HAL_VOLUME_IFACE)
+ volume.Unmount([])
def get_volumes_manager():
global _volumes_manager