diff options
author | Jonas Smedegaard <dr@jones.dk> | 2008-12-04 02:03:07 (GMT) |
---|---|---|
committer | Jonas Smedegaard <dr@jones.dk> | 2008-12-04 02:03:07 (GMT) |
commit | e3325cd40f04996107509e065e79008c4f1d2f61 (patch) | |
tree | 582edfd11a0e9c029260f00f6c208205eac18037 | |
parent | 08d72b085f4ea5c0a8f993044f7d4d997a1a7cee (diff) |
Revert "Imported Upstream version 0.83.3"upstream
This reverts commit 08d72b085f4ea5c0a8f993044f7d4d997a1a7cee.
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | Makefile.in | 5 | ||||
-rw-r--r-- | aclocal.m4 | 40 | ||||
-rw-r--r-- | bin/Makefile.am | 14 | ||||
-rw-r--r-- | bin/Makefile.in | 32 | ||||
-rw-r--r-- | bin/sugar | 9 | ||||
-rw-r--r-- | bin/sugar-backup | 11 | ||||
-rw-r--r-- | bin/sugar-control-panel | 6 | ||||
-rw-r--r-- | bin/sugar-control-panel.in (copied from src/jarabe/util/telepathy/__init__.py) | 15 | ||||
-rw-r--r-- | bin/sugar-emulator | 107 | ||||
-rw-r--r-- | bin/sugar-emulator.in (renamed from src/jarabe/util/telepathy/__init__.py) | 15 | ||||
-rw-r--r-- | bin/sugar-launch | 17 | ||||
-rw-r--r-- | bin/sugar-session | 180 | ||||
-rw-r--r-- | bin/sugar-shell (copied from extensions/cpsection/network/__init__.py) | 21 | ||||
-rw-r--r-- | bin/sugar-shell-service (renamed from src/jarabe/config.py) | 24 | ||||
-rw-r--r-- | bin/sugar-shell-service.in (copied from extensions/cpsection/network/__init__.py) | 19 | ||||
-rw-r--r-- | bin/sugar-shell.in (copied from extensions/cpsection/network/__init__.py) | 21 | ||||
-rw-r--r-- | bin/sugar-ui-check | 161 | ||||
-rw-r--r-- | bin/sugar.in | 18 | ||||
-rwxr-xr-x | configure | 218 | ||||
-rw-r--r-- | configure.ac | 59 | ||||
-rw-r--r-- | data/Makefile.am | 34 | ||||
-rw-r--r-- | data/Makefile.in | 110 | ||||
-rw-r--r-- | data/activities.defaults | 33 | ||||
-rw-r--r-- | data/gtkrc.em | 5 | ||||
-rw-r--r-- | data/icons/Makefile.am | 1 | ||||
-rw-r--r-- | data/icons/Makefile.in | 4 | ||||
-rw-r--r-- | data/icons/activity-journal.svg | 11 | ||||
-rw-r--r-- | data/nm-user-settings.conf | 34 | ||||
-rw-r--r-- | data/sugar-xo.gtkrc (renamed from data/sugar-100.gtkrc) | 3 | ||||
-rw-r--r-- | data/sugar.gtkrc (renamed from data/sugar-72.gtkrc) | 3 | ||||
-rw-r--r-- | data/sugar.schemas.in | 160 | ||||
-rw-r--r-- | extensions/Makefile.am | 1 | ||||
-rw-r--r-- | extensions/cpsection/Makefile.am | 4 | ||||
-rw-r--r-- | extensions/cpsection/aboutme/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/aboutme/Makefile.in | 394 | ||||
-rw-r--r-- | extensions/cpsection/aboutme/__init__.py | 28 | ||||
-rw-r--r-- | extensions/cpsection/aboutxo/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/aboutxo/Makefile.in | 394 | ||||
-rw-r--r-- | extensions/cpsection/aboutxo/__init__.py | 22 | ||||
-rw-r--r-- | extensions/cpsection/datetime/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/datetime/__init__.py | 21 | ||||
-rw-r--r-- | extensions/cpsection/frame/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/frame/__init__.py | 21 | ||||
-rw-r--r-- | extensions/cpsection/language/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/language/Makefile.in | 394 | ||||
-rw-r--r-- | extensions/cpsection/language/__init__.py | 22 | ||||
-rw-r--r-- | extensions/cpsection/language/view.py | 237 | ||||
-rw-r--r-- | extensions/cpsection/network/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/network/Makefile.in | 394 | ||||
-rw-r--r-- | extensions/cpsection/network/model.py | 123 | ||||
-rw-r--r-- | extensions/cpsection/power/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/cpsection/power/__init__.py | 23 | ||||
-rw-r--r-- | extensions/deviceicon/Makefile.am | 8 | ||||
-rw-r--r-- | extensions/deviceicon/Makefile.in | 396 | ||||
-rw-r--r-- | extensions/deviceicon/__init__.py | 0 | ||||
-rw-r--r-- | extensions/deviceicon/battery.py | 252 | ||||
-rw-r--r-- | extensions/deviceicon/network.py | 377 | ||||
-rw-r--r-- | extensions/deviceicon/volume.py | 111 | ||||
-rw-r--r-- | extensions/globalkey/Makefile.am | 6 | ||||
-rw-r--r-- | extensions/globalkey/__init__.py | 0 | ||||
-rw-r--r-- | extensions/globalkey/screenshot.py | 72 | ||||
-rw-r--r-- | extensions/globalkey/viewsource.py | 363 | ||||
-rw-r--r-- | po/POTFILES.in | 93 | ||||
-rw-r--r-- | po/ar.po | 193 | ||||
-rw-r--r-- | po/de.po | 566 | ||||
-rw-r--r-- | po/en.po | 566 | ||||
-rw-r--r-- | po/es.po | 217 | ||||
-rw-r--r-- | po/fr.po | 556 | ||||
-rw-r--r-- | po/ht.po | 436 | ||||
-rw-r--r-- | po/it.po | 500 | ||||
-rw-r--r-- | po/ja.po | 500 | ||||
-rw-r--r-- | po/mn.po | 131 | ||||
-rw-r--r-- | po/nl.po | 557 | ||||
-rw-r--r-- | po/pt.po | 145 | ||||
-rw-r--r-- | po/si.po | 936 | ||||
-rw-r--r-- | po/tr.po | 882 | ||||
-rw-r--r-- | service/Makefile.am | 33 | ||||
-rw-r--r-- | service/Makefile.in (renamed from src/jarabe/controlpanel/Makefile.in) | 90 | ||||
-rw-r--r-- | service/__init__.py (copied from src/jarabe/view/__init__.py) | 2 | ||||
-rw-r--r-- | service/activityregistryservice.py | 166 | ||||
-rw-r--r-- | service/bundleregistry.py (renamed from src/jarabe/model/bundleregistry.py) | 81 | ||||
-rw-r--r-- | service/clipboardobject.py (renamed from src/jarabe/frame/clipboardobject.py) | 38 | ||||
-rw-r--r-- | service/clipboardservice.py | 212 | ||||
-rw-r--r-- | service/config.py (renamed from src/jarabe/util/__init__.py) | 6 | ||||
-rw-r--r-- | service/config.py.in (copied from src/jarabe/model/__init__.py) | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | service/main.py (copied from extensions/cpsection/network/__init__.py) | 30 | ||||
-rw-r--r-- | service/org.laptop.ActivityRegistry.service.in | 4 | ||||
-rw-r--r-- | service/org.laptop.Clipboard.service.in | 4 | ||||
-rw-r--r-- | src/Makefile.am | 13 | ||||
-rw-r--r-- | src/Makefile.in | 75 | ||||
-rw-r--r-- | src/config.py (renamed from src/jarabe/frame/__init__.py) | 14 | ||||
-rw-r--r-- | src/config.py.in (renamed from src/jarabe/config.py.in) | 5 | ||||
-rw-r--r-- | src/controlpanel/Makefile.am (renamed from src/jarabe/controlpanel/Makefile.am) | 4 | ||||
-rw-r--r-- | src/controlpanel/Makefile.in (copied from src/jarabe/util/Makefile.in) | 22 | ||||
-rw-r--r-- | src/controlpanel/__init__.py (copied from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/controlpanel/cmd.py (renamed from src/jarabe/controlpanel/cmd.py) | 37 | ||||
-rw-r--r-- | src/controlpanel/gui.py (renamed from src/jarabe/controlpanel/gui.py) | 105 | ||||
-rw-r--r-- | src/controlpanel/inlinealert.py (renamed from src/jarabe/controlpanel/inlinealert.py) | 0 | ||||
-rw-r--r-- | src/controlpanel/model/Makefile.am | 10 | ||||
-rw-r--r-- | src/controlpanel/model/Makefile.in (renamed from src/jarabe/util/telepathy/Makefile.in) | 21 | ||||
-rw-r--r-- | src/controlpanel/model/__init__.py (copied from src/jarabe/view/__init__.py) | 3 | ||||
-rw-r--r-- | src/controlpanel/model/aboutme.py (renamed from extensions/cpsection/aboutme/model.py) | 35 | ||||
-rw-r--r-- | src/controlpanel/model/aboutxo.py (renamed from extensions/cpsection/aboutxo/model.py) | 19 | ||||
-rw-r--r-- | src/controlpanel/model/datetime.py (renamed from extensions/cpsection/datetime/model.py) | 12 | ||||
-rw-r--r-- | src/controlpanel/model/frame.py (renamed from extensions/cpsection/frame/model.py) | 31 | ||||
-rw-r--r-- | src/controlpanel/model/language.py (renamed from extensions/cpsection/language/model.py) | 98 | ||||
-rw-r--r-- | src/controlpanel/model/network.py | 101 | ||||
-rw-r--r-- | src/controlpanel/model/power.py (renamed from extensions/cpsection/power/model.py) | 24 | ||||
-rw-r--r-- | src/controlpanel/sectionview.py (renamed from src/jarabe/controlpanel/sectionview.py) | 0 | ||||
-rw-r--r-- | src/controlpanel/toolbar.py (renamed from src/jarabe/controlpanel/toolbar.py) | 0 | ||||
-rw-r--r-- | src/controlpanel/view/Makefile.am | 16 | ||||
-rw-r--r-- | src/controlpanel/view/Makefile.in (renamed from extensions/cpsection/power/Makefile.in) | 22 | ||||
-rw-r--r-- | src/controlpanel/view/__init__.py (copied from src/jarabe/view/__init__.py) | 3 | ||||
-rw-r--r-- | src/controlpanel/view/aboutme.py (renamed from extensions/cpsection/aboutme/view.py) | 29 | ||||
-rw-r--r-- | src/controlpanel/view/aboutxo.py (renamed from extensions/cpsection/aboutxo/view.py) | 23 | ||||
-rw-r--r-- | src/controlpanel/view/datetime.py (copied from extensions/cpsection/datetime/view.py) | 8 | ||||
-rw-r--r-- | src/controlpanel/view/frame.py (renamed from extensions/cpsection/frame/view.py) | 14 | ||||
-rw-r--r-- | src/controlpanel/view/language.py (renamed from extensions/cpsection/datetime/view.py) | 100 | ||||
-rw-r--r-- | src/controlpanel/view/network.py (renamed from extensions/cpsection/network/view.py) | 17 | ||||
-rw-r--r-- | src/controlpanel/view/power.py (renamed from extensions/cpsection/power/view.py) | 11 | ||||
-rwxr-xr-x | src/emulator.py | 147 | ||||
-rw-r--r-- | src/hardware/Makefile.am | 13 | ||||
-rw-r--r-- | src/hardware/Makefile.in (renamed from src/jarabe/journal/Makefile.in) | 83 | ||||
-rw-r--r-- | src/hardware/NetworkManagerInfo.conf | 26 | ||||
-rw-r--r-- | src/hardware/__init__.py (renamed from src/jarabe/desktop/__init__.py) | 0 | ||||
-rw-r--r-- | src/hardware/hardwaremanager.py | 123 | ||||
-rw-r--r-- | src/hardware/keydialog.py (renamed from src/jarabe/desktop/keydialog.py) | 194 | ||||
-rw-r--r-- | src/hardware/nmclient.py | 795 | ||||
-rw-r--r-- | src/hardware/nminfo.py | 556 | ||||
-rw-r--r-- | src/hardware/schoolserver.py (renamed from src/jarabe/desktop/schoolserver.py) | 12 | ||||
-rw-r--r-- | src/intro/Makefile.am | 10 | ||||
-rw-r--r-- | src/intro/Makefile.in (renamed from src/jarabe/intro/Makefile.in) | 20 | ||||
-rw-r--r-- | src/intro/__init__.py (renamed from extensions/cpsection/__init__.py) | 0 | ||||
-rw-r--r-- | src/intro/colorpicker.py (renamed from src/jarabe/intro/colorpicker.py) | 0 | ||||
-rw-r--r-- | src/intro/default-picture.png (renamed from src/jarabe/intro/default-picture.png) | bin | 10442 -> 10442 bytes | |||
-rw-r--r-- | src/intro/glive.py | 200 | ||||
-rw-r--r-- | src/intro/intro.py (renamed from src/jarabe/intro/window.py) | 68 | ||||
-rw-r--r-- | src/jarabe/Makefile.am | 14 | ||||
-rw-r--r-- | src/jarabe/desktop/Makefile.in | 408 | ||||
-rw-r--r-- | src/jarabe/desktop/homewindow.py | 143 | ||||
-rw-r--r-- | src/jarabe/desktop/meshbox.py | 854 | ||||
-rw-r--r-- | src/jarabe/frame/clipboard.py | 149 | ||||
-rw-r--r-- | src/jarabe/frame/devicestray.py | 53 | ||||
-rw-r--r-- | src/jarabe/intro/Makefile.am | 9 | ||||
-rw-r--r-- | src/jarabe/intro/__init__.py | 21 | ||||
-rw-r--r-- | src/jarabe/journal/Makefile.am | 17 | ||||
-rw-r--r-- | src/jarabe/journal/__init__.py | 0 | ||||
-rw-r--r-- | src/jarabe/journal/collapsedentry.py | 383 | ||||
-rw-r--r-- | src/jarabe/journal/detailview.py | 133 | ||||
-rw-r--r-- | src/jarabe/journal/expandedentry.py | 383 | ||||
-rw-r--r-- | src/jarabe/journal/journalactivity.py | 342 | ||||
-rw-r--r-- | src/jarabe/journal/journalentrybundle.py | 91 | ||||
-rw-r--r-- | src/jarabe/journal/journaltoolbox.py | 422 | ||||
-rw-r--r-- | src/jarabe/journal/keepicon.py | 59 | ||||
-rw-r--r-- | src/jarabe/journal/listview.py | 460 | ||||
-rw-r--r-- | src/jarabe/journal/misc.py | 199 | ||||
-rw-r--r-- | src/jarabe/journal/modalalert.py | 97 | ||||
-rw-r--r-- | src/jarabe/journal/objectchooser.py | 199 | ||||
-rw-r--r-- | src/jarabe/journal/palettes.py | 119 | ||||
-rw-r--r-- | src/jarabe/journal/query.py | 266 | ||||
-rw-r--r-- | src/jarabe/journal/volumestoolbar.py | 138 | ||||
-rw-r--r-- | src/jarabe/model/Makefile.am | 16 | ||||
-rw-r--r-- | src/jarabe/model/Makefile.in | 405 | ||||
-rw-r--r-- | src/jarabe/model/neighborhood.py | 273 | ||||
-rw-r--r-- | src/jarabe/model/network.py | 363 | ||||
-rw-r--r-- | src/jarabe/model/notifications.py | 95 | ||||
-rw-r--r-- | src/jarabe/model/screen.py | 64 | ||||
-rw-r--r-- | src/jarabe/model/shell.py | 577 | ||||
-rw-r--r-- | src/jarabe/model/sound.py | 58 | ||||
-rw-r--r-- | src/jarabe/model/volume.py | 253 | ||||
-rw-r--r-- | src/jarabe/util/Makefile.am | 6 | ||||
-rw-r--r-- | src/jarabe/util/telepathy/Makefile.am | 4 | ||||
-rw-r--r-- | src/jarabe/util/telepathy/connection_watcher.py | 110 | ||||
-rw-r--r-- | src/jarabe/view/Makefile.am | 11 | ||||
-rw-r--r-- | src/jarabe/view/Makefile.in | 400 | ||||
-rw-r--r-- | src/jarabe/view/pulsingicon.py | 229 | ||||
-rw-r--r-- | src/logsmanager.py | 56 | ||||
-rw-r--r-- | src/main.py | 153 | ||||
-rw-r--r-- | src/model/BuddyModel.py (renamed from src/jarabe/model/buddy.py) | 0 | ||||
-rw-r--r-- | src/model/Friends.py (renamed from src/jarabe/model/friends.py) | 16 | ||||
-rw-r--r-- | src/model/Invites.py (renamed from src/jarabe/model/invites.py) | 2 | ||||
-rw-r--r-- | src/model/Makefile.am | 14 | ||||
-rw-r--r-- | src/model/Makefile.in (renamed from extensions/cpsection/Makefile.in) | 26 | ||||
-rw-r--r-- | src/model/MeshModel.py | 237 | ||||
-rw-r--r-- | src/model/Owner.py (renamed from src/jarabe/model/owner.py) | 21 | ||||
-rw-r--r-- | src/model/__init__.py (renamed from src/jarabe/model/__init__.py) | 0 | ||||
-rw-r--r-- | src/model/accesspointmodel.py | 80 | ||||
-rw-r--r-- | src/model/devices/Makefile.am | 10 | ||||
-rw-r--r-- | src/model/devices/Makefile.in (renamed from src/jarabe/Makefile.in) | 35 | ||||
-rw-r--r-- | src/model/devices/__init__.py (renamed from src/jarabe/view/__init__.py) | 0 | ||||
-rw-r--r-- | src/model/devices/battery.py | 97 | ||||
-rw-r--r-- | src/model/devices/device.py (copied from src/jarabe/frame/frameinvoker.py) | 39 | ||||
-rw-r--r-- | src/model/devices/devicesmodel.py | 144 | ||||
-rw-r--r-- | src/model/devices/network/Makefile.am | 6 | ||||
-rw-r--r-- | src/model/devices/network/Makefile.in (renamed from extensions/globalkey/Makefile.in) | 16 | ||||
-rw-r--r-- | src/model/devices/network/__init__.py (copied from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/model/devices/network/mesh.py | 86 | ||||
-rw-r--r-- | src/model/devices/network/wired.py (renamed from src/jarabe/__init__.py) | 22 | ||||
-rw-r--r-- | src/model/devices/network/wireless.py | 102 | ||||
-rw-r--r-- | src/model/devices/speaker.py | 65 | ||||
-rw-r--r-- | src/model/homeactivity.py | 240 | ||||
-rw-r--r-- | src/model/homemodel.py | 286 | ||||
-rw-r--r-- | src/model/shellmodel.py | 104 | ||||
-rw-r--r-- | src/session.py (renamed from src/jarabe/model/session.py) | 5 | ||||
-rw-r--r-- | src/shellservice.py (renamed from src/jarabe/view/service.py) | 57 | ||||
-rw-r--r-- | src/view/ActivityHost.py | 63 | ||||
-rw-r--r-- | src/view/BuddyIcon.py (renamed from src/jarabe/view/buddyicon.py) | 2 | ||||
-rw-r--r-- | src/view/BuddyMenu.py (renamed from src/jarabe/view/buddymenu.py) | 31 | ||||
-rw-r--r-- | src/view/Makefile.am | 17 | ||||
-rw-r--r-- | src/view/Makefile.in (renamed from src/jarabe/util/Makefile.in) | 29 | ||||
-rw-r--r-- | src/view/OverlayWindow.py | 70 | ||||
-rw-r--r-- | src/view/Shell.py | 272 | ||||
-rw-r--r-- | src/view/__init__.py (copied from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/view/clipboardicon.py (renamed from src/jarabe/frame/clipboardicon.py) | 123 | ||||
-rw-r--r-- | src/view/clipboardmenu.py (renamed from src/jarabe/frame/clipboardmenu.py) | 143 | ||||
-rw-r--r-- | src/view/devices/Makefile.am | 9 | ||||
-rw-r--r-- | src/view/devices/Makefile.in (renamed from extensions/Makefile.in) | 74 | ||||
-rw-r--r-- | src/view/devices/__init__.py (copied from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/view/devices/battery.py | 130 | ||||
-rw-r--r-- | src/view/devices/deviceview.py (copied from extensions/cpsection/network/__init__.py) | 13 | ||||
-rw-r--r-- | src/view/devices/network/Makefile.am | 6 | ||||
-rw-r--r-- | src/view/devices/network/Makefile.in (renamed from extensions/cpsection/frame/Makefile.in) | 18 | ||||
-rw-r--r-- | src/view/devices/network/__init__.py (copied from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/view/devices/network/mesh.py | 174 | ||||
-rw-r--r-- | src/view/devices/network/wired.py (renamed from extensions/cpsection/network/__init__.py) | 12 | ||||
-rw-r--r-- | src/view/devices/network/wireless.py | 191 | ||||
-rw-r--r-- | src/view/devices/speaker.py (renamed from extensions/deviceicon/speaker.py) | 83 | ||||
-rw-r--r-- | src/view/frame/Makefile.am (renamed from src/jarabe/frame/Makefile.am) | 6 | ||||
-rw-r--r-- | src/view/frame/Makefile.in (renamed from src/jarabe/frame/Makefile.in) | 15 | ||||
-rw-r--r-- | src/view/frame/__init__.py (copied from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/view/frame/activitiestray.py (renamed from src/jarabe/frame/activitiestray.py) | 130 | ||||
-rw-r--r-- | src/view/frame/clipboardpanelwindow.py (renamed from src/jarabe/frame/clipboardpanelwindow.py) | 18 | ||||
-rw-r--r-- | src/view/frame/clipboardtray.py (renamed from src/jarabe/frame/clipboardtray.py) | 55 | ||||
-rw-r--r-- | src/view/frame/devicestray.py | 66 | ||||
-rw-r--r-- | src/view/frame/eventarea.py (renamed from src/jarabe/frame/eventarea.py) | 33 | ||||
-rw-r--r-- | src/view/frame/frame.py (renamed from src/jarabe/frame/frame.py) | 76 | ||||
-rw-r--r-- | src/view/frame/frameinvoker.py (renamed from src/jarabe/frame/frameinvoker.py) | 0 | ||||
-rw-r--r-- | src/view/frame/framewindow.py (renamed from src/jarabe/frame/framewindow.py) | 0 | ||||
-rw-r--r-- | src/view/frame/friendstray.py (renamed from src/jarabe/frame/friendstray.py) | 20 | ||||
-rw-r--r-- | src/view/frame/notification.py (renamed from src/jarabe/frame/notification.py) | 2 | ||||
-rw-r--r-- | src/view/frame/zoomtoolbar.py (renamed from src/jarabe/frame/zoomtoolbar.py) | 35 | ||||
-rw-r--r-- | src/view/home/FriendView.py (renamed from src/jarabe/desktop/friendview.py) | 10 | ||||
-rw-r--r-- | src/view/home/FriendsBox.py (renamed from src/jarabe/desktop/groupbox.py) | 39 | ||||
-rw-r--r-- | src/view/home/HomeBox.py (renamed from src/jarabe/desktop/homebox.py) | 72 | ||||
-rw-r--r-- | src/view/home/HomeWindow.py | 153 | ||||
-rw-r--r-- | src/view/home/Makefile.am (renamed from src/jarabe/desktop/Makefile.am) | 16 | ||||
-rw-r--r-- | src/view/home/Makefile.in (renamed from extensions/cpsection/datetime/Makefile.in) | 29 | ||||
-rw-r--r-- | src/view/home/MeshBox.py | 646 | ||||
-rw-r--r-- | src/view/home/MyIcon.py (renamed from src/jarabe/desktop/myicon.py) | 8 | ||||
-rw-r--r-- | src/view/home/__init__.py (renamed from src/jarabe/controlpanel/__init__.py) | 0 | ||||
-rw-r--r-- | src/view/home/activitieslist.py (renamed from src/jarabe/desktop/activitieslist.py) | 123 | ||||
-rw-r--r-- | src/view/home/favoriteslayout.py (renamed from src/jarabe/desktop/favoriteslayout.py) | 66 | ||||
-rw-r--r-- | src/view/home/favoritesview.py (renamed from src/jarabe/desktop/favoritesview.py) | 259 | ||||
-rw-r--r-- | src/view/home/grid.py (renamed from src/jarabe/desktop/grid.py) | 2 | ||||
-rwxr-xr-x | src/view/home/proc_smaps.py (renamed from src/jarabe/desktop/proc_smaps.py) | 0 | ||||
-rw-r--r-- | src/view/home/snowflakelayout.py (renamed from src/jarabe/desktop/snowflakelayout.py) | 0 | ||||
-rw-r--r-- | src/view/home/spreadlayout.py (renamed from src/jarabe/desktop/spreadlayout.py) | 2 | ||||
-rw-r--r-- | src/view/home/transitionbox.py (renamed from src/jarabe/desktop/transitionbox.py) | 15 | ||||
-rw-r--r-- | src/view/keyhandler.py (renamed from src/jarabe/view/keyhandler.py) | 103 | ||||
-rw-r--r-- | src/view/launchwindow.py (renamed from src/jarabe/view/launcher.py) | 43 | ||||
-rw-r--r-- | src/view/palettes.py (renamed from src/jarabe/view/palettes.py) | 51 | ||||
-rw-r--r-- | src/view/pulsingicon.py | 239 | ||||
-rw-r--r-- | src/view/tabbinghandler.py (renamed from src/jarabe/view/tabbinghandler.py) | 54 |
264 files changed, 10452 insertions, 18299 deletions
diff --git a/Makefile.am b/Makefile.am index 9e252af..11777bc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = bin data po src extensions +SUBDIRS = bin data po src service DISTCLEANFILES = \ intltool-extract \ diff --git a/Makefile.in b/Makefile.in index 69d046b..3e014c6 100644 --- a/Makefile.in +++ b/Makefile.in @@ -89,9 +89,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -208,7 +205,7 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = bin data po src extensions +SUBDIRS = bin data po src service DISTCLEANFILES = \ intltool-extract \ intltool-merge \ @@ -19,46 +19,6 @@ You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically `autoreconf'.])]) -dnl AM_GCONF_SOURCE_2 -dnl Defines GCONF_SCHEMA_CONFIG_SOURCE which is where you should install schemas -dnl (i.e. pass to gconftool-2 -dnl Defines GCONF_SCHEMA_FILE_DIR which is a filesystem directory where -dnl you should install foo.schemas files -dnl - -AC_DEFUN([AM_GCONF_SOURCE_2], -[ - if test "x$GCONF_SCHEMA_INSTALL_SOURCE" = "x"; then - GCONF_SCHEMA_CONFIG_SOURCE=`gconftool-2 --get-default-source` - else - GCONF_SCHEMA_CONFIG_SOURCE=$GCONF_SCHEMA_INSTALL_SOURCE - fi - - AC_ARG_WITH(gconf-source, - [ --with-gconf-source=sourceaddress Config database for installing schema files.],GCONF_SCHEMA_CONFIG_SOURCE="$withval",) - - AC_SUBST(GCONF_SCHEMA_CONFIG_SOURCE) - AC_MSG_RESULT([Using config source $GCONF_SCHEMA_CONFIG_SOURCE for schema installation]) - - if test "x$GCONF_SCHEMA_FILE_DIR" = "x"; then - GCONF_SCHEMA_FILE_DIR='$(sysconfdir)/gconf/schemas' - fi - - AC_ARG_WITH(gconf-schema-file-dir, - [ --with-gconf-schema-file-dir=dir Directory for installing schema files.],GCONF_SCHEMA_FILE_DIR="$withval",) - - AC_SUBST(GCONF_SCHEMA_FILE_DIR) - AC_MSG_RESULT([Using $GCONF_SCHEMA_FILE_DIR as install directory for schema files]) - - AC_ARG_ENABLE(schemas-install, - [ --disable-schemas-install Disable the schemas installation], - [case ${enableval} in - yes|no) ;; - *) AC_MSG_ERROR(bad value ${enableval} for --enable-schemas-install) ;; - esac]) - AM_CONDITIONAL([GCONF_SCHEMAS_INSTALL], [test "$enable_schemas_install" != no]) -]) - # Copyright (C) 1995-2002 Free Software Foundation, Inc. # Copyright (C) 2001-2003,2004 Red Hat, Inc. # diff --git a/bin/Makefile.am b/bin/Makefile.am index 05a9215..ca6ddef 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -1,14 +1,14 @@ -python_scripts = \ +bin_SCRIPTS = \ + sugar \ sugar-activity \ + sugar-backup \ sugar-control-panel \ sugar-emulator \ sugar-install-bundle \ sugar-launch \ - sugar-session \ - sugar-ui-check + sugar-shell \ + sugar-shell-service -bin_SCRIPTS = \ - sugar \ - $(python_scripts) +EXTRA_DIST = $(bin_SCRIPTS) sugar.in -EXTRA_DIST = $(python_scripts) sugar.in +DISTCLEANFILES = sugar diff --git a/bin/Makefile.in b/bin/Makefile.in index 6d65492..8c1ac15 100644 --- a/bin/Makefile.in +++ b/bin/Makefile.in @@ -32,13 +32,16 @@ PRE_UNINSTALL = : POST_UNINSTALL = : subdir = bin DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/sugar-control-panel.in $(srcdir)/sugar-emulator.in \ + $(srcdir)/sugar-shell-service.in $(srcdir)/sugar-shell.in \ $(srcdir)/sugar.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = sugar +CONFIG_CLEAN_FILES = sugar sugar-control-panel sugar-emulator \ + sugar-shell sugar-shell-service am__installdirs = "$(DESTDIR)$(bindir)" binSCRIPT_INSTALL = $(INSTALL_SCRIPT) SCRIPTS = $(bin_SCRIPTS) @@ -68,9 +71,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -187,20 +187,19 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -python_scripts = \ +bin_SCRIPTS = \ + sugar \ sugar-activity \ + sugar-backup \ sugar-control-panel \ sugar-emulator \ sugar-install-bundle \ sugar-launch \ - sugar-session \ - sugar-ui-check - -bin_SCRIPTS = \ - sugar \ - $(python_scripts) + sugar-shell \ + sugar-shell-service -EXTRA_DIST = $(python_scripts) sugar.in +EXTRA_DIST = $(bin_SCRIPTS) sugar.in +DISTCLEANFILES = sugar all: all-am .SUFFIXES: @@ -235,6 +234,14 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh sugar: $(top_builddir)/config.status $(srcdir)/sugar.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +sugar-control-panel: $(top_builddir)/config.status $(srcdir)/sugar-control-panel.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +sugar-emulator: $(top_builddir)/config.status $(srcdir)/sugar-emulator.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +sugar-shell: $(top_builddir)/config.status $(srcdir)/sugar-shell.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +sugar-shell-service: $(top_builddir)/config.status $(srcdir)/sugar-shell-service.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @@ -314,6 +321,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" diff --git a/bin/sugar b/bin/sugar new file mode 100644 index 0000000..88e478a --- /dev/null +++ b/bin/sugar @@ -0,0 +1,9 @@ +#!/bin/sh + +export SUGAR_THEME=sugar-xo + +if [ -f /etc/olpc-security ] ; then + exec dbus-launch --exit-with-session --config-file=/etc/dbus-1/session-olpc.conf sugar-shell +else + exec dbus-launch --exit-with-session sugar-shell +fi diff --git a/bin/sugar-backup b/bin/sugar-backup new file mode 100644 index 0000000..c90da63 --- /dev/null +++ b/bin/sugar-backup @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import sys +import time + +i = 0 +while i <= 100: + time.sleep(0.5) + sys.stdout.write('%d\n' % i) + sys.stdout.flush() + i += 5 diff --git a/bin/sugar-control-panel b/bin/sugar-control-panel index a97e3c0..a440a85 100644 --- a/bin/sugar-control-panel +++ b/bin/sugar-control-panel @@ -17,11 +17,9 @@ import sys -from jarabe import config +sys.path.insert(0, '/home/marco/sucrose-0.82/install/share/sugar/shell') -sys.path.append(config.ext_path) - -from jarabe.controlpanel.cmd import main +from controlpanel.cmd import main main() diff --git a/src/jarabe/util/telepathy/__init__.py b/bin/sugar-control-panel.in index 387d09c..922f95c 100644 --- a/src/jarabe/util/telepathy/__init__.py +++ b/bin/sugar-control-panel.in @@ -1,7 +1,5 @@ -"""OLPC Sugar Jarabe utility telepathy modules -""" - -# Copyright (C) 2008, One Laptop Per Child +#!/usr/bin/env python +# Copyright (C) 2008, Red Hat, Inc. # # 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 @@ -17,3 +15,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import sys + +sys.path.insert(0, '@prefix@/share/sugar/shell') + +from controlpanel.cmd import main + +main() + + diff --git a/bin/sugar-emulator b/bin/sugar-emulator index 4daba14..dfc5e9c8 100644 --- a/bin/sugar-emulator +++ b/bin/sugar-emulator @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2006-2008, Red Hat, Inc. +# Copyright (C) 2008, Red Hat, Inc. # # 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,109 +15,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import os -import subprocess -import time -from optparse import OptionParser +import sys -import gtk -import gobject +sys.path.insert(0, '/home/marco/sucrose-0.82/install/share/sugar/shell') -from sugar import env +from emulator import main -def _run_xephyr(display, dpi, dimensions): - cmd = [ 'Xephyr' ] - cmd.append(':%d' % display) - cmd.append('-ac') - - if dimensions is not None: - cmd.append('-screen') - cmd.append(dimensions) - elif gtk.gdk.screen_width() < 1200 or gtk.gdk.screen_height() < 900: - cmd.append('-fullscreen') - else: - cmd.append('-screen') - cmd.append('%dx%d' % (1200, 900)) - - if dpi is None: - dpi = gtk.settings_get_default().get_property('gtk-xft-dpi') / 1024 - if dpi > 0: - cmd.append('-dpi') - cmd.append('%d' % dpi) - - result = gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) - pid = result[0] - - os.environ['DISPLAY'] = ":%d" % (display) - os.environ['SUGAR_EMULATOR_PID'] = str(pid) - -def _check_xephyr(display): - result = subprocess.call(['xdpyinfo', '-display', ':%d' % display], - stdout=open(os.devnull, "w"), - stderr=open(os.devnull, "w")) - return result == 0 - -def _start_xephyr(dpi, dimensions): - for display in range(100, 110): - if not _check_xephyr(display): - _run_xephyr(display, dpi, dimensions) - - tries = 10 - while tries > 0: - if _check_xephyr(display): - return - else: - tries -= 1 - time.sleep(0.1) - -def _start_matchbox(): - cmd = ['matchbox-window-manager'] - - cmd.extend(['-use_titlebar', 'no']) - cmd.extend(['-theme', 'sugar']) - - gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) - -def _setup_env(): - os.environ['SUGAR_EMULATOR'] = 'yes' - os.environ['GABBLE_LOGFILE'] = os.path.join( - env.get_profile_path(), 'logs', 'telepathy-gabble.log') - os.environ['SALUT_LOGFILE'] = os.path.join( - env.get_profile_path(), 'logs', 'telepathy-salut.log') - os.environ['STREAM_ENGINE_LOGFILE'] = os.path.join( - env.get_profile_path(), 'logs', 'telepathy-stream-engine.log') - -def main(): - """Script-level operations""" - - parser = OptionParser() - parser.add_option('-d', '--dpi', dest='dpi', type="int", - help='Emulator dpi') - parser.add_option('-s', '--scaling', dest='scaling', - help='Sugar scaling in %') - parser.add_option('-i', '--dimensions', dest='dimensions', - help='Emulator dimensions (ex. 1200x900)') - (options, args) = parser.parse_args() - - _setup_env() - - _start_xephyr(options.dpi, options.dimensions) - - if options.scaling: - os.environ['SUGAR_SCALING'] = options.scaling - - command = ['dbus-launch', 'dbus-launch', '--exit-with-session'] - - if not args: - command.append('sugar') - else: - _start_matchbox() - - if args[0].endswith('.py'): - command.append('python') +main() - command.append(args[0]) - - os.execlp(*command) -main() diff --git a/src/jarabe/util/telepathy/__init__.py b/bin/sugar-emulator.in index 387d09c..1ee6fc5 100644 --- a/src/jarabe/util/telepathy/__init__.py +++ b/bin/sugar-emulator.in @@ -1,7 +1,5 @@ -"""OLPC Sugar Jarabe utility telepathy modules -""" - -# Copyright (C) 2008, One Laptop Per Child +#!/usr/bin/env python +# Copyright (C) 2008, Red Hat, Inc. # # 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 @@ -17,3 +15,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import sys + +sys.path.insert(0, '@prefix@/share/sugar/shell') + +from emulator import main + +main() + + diff --git a/bin/sugar-launch b/bin/sugar-launch index 68fe613..7765ff1 100644 --- a/bin/sugar-launch +++ b/bin/sugar-launch @@ -18,11 +18,10 @@ import os import sys -import dbus from optparse import OptionParser from sugar.activity import activityfactory -from sugar.bundle.activitybundle import ActivityBundle +from sugar.activity.registry import get_registry usage = "usage: %prog [options] activity" parser = OptionParser(usage) @@ -31,17 +30,15 @@ parser.add_option("-d", "--debug", action="store_true", dest="debug", (options, args) = parser.parse_args() if len(args) == 0: - print 'You need to specify the activity bundle_id.' + print 'You need to specify the activity name or part of it.' sys.exit(1) -bus = dbus.SessionBus() -proxy = bus.get_object('org.laptop.Shell', '/org/laptop/Shell') -path = dbus.Interface(proxy, 'org.laptop.Shell').GetBundlePath(args[0]) -if not path: - print 'Cannot find %s bundle.' % args[0] - sys.exit(1) +registry = get_registry() +activities = registry.find_activity(args[0]) +if len(activities) == 0: + print 'Activity not found.' -activity = ActivityBundle(path) +activity = activities[0] cmd_args = activityfactory.get_command(activity) def _which(exec_file): diff --git a/bin/sugar-session b/bin/sugar-session deleted file mode 100644 index 12e1f9e..0000000 --- a/bin/sugar-session +++ /dev/null @@ -1,180 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2006, Red Hat, Inc. -# -# 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 - -import os -import sys -import time - -if os.environ.get('SUGAR_LOGGER_LEVEL', '') == 'debug': - print '%r STARTUP: Starting the shell' % time.time() - sys.stdout.flush() - -import shutil -import gettext -import logging - -import gconf -import gtk -import gobject -import dbus.glib - -gtk.gdk.threads_init() -dbus.glib.threads_init() - -from sugar import logger -from sugar import env - -from jarabe.desktop.homewindow import HomeWindow -from jarabe.model import sound -from jarabe.view import launcher -from jarabe import intro -from jarabe import config - -def cleanup_logs(): - """Clean up the log directory, moving old logs into a numbered backup - directory. We only keep `_MAX_BACKUP_DIRS` of these backup directories - around; the rest are removed.""" - logs_dir = env.get_logs_path() - if not os.path.isdir(logs_dir): - os.makedirs(logs_dir) - - backup_logs = [] - backup_dirs = [] - for f in os.listdir(logs_dir): - path = os.path.join(logs_dir, f) - if os.path.isfile(path): - backup_logs.append(f) - elif os.path.isdir(path): - backup_dirs.append(path) - - if len(backup_dirs) > 3: - backup_dirs.sort() - root = backup_dirs[0] - for f in os.listdir(root): - os.remove(os.path.join(root, f)) - os.rmdir(root) - - if len(backup_logs) > 0: - name = str(int(time.time())) - backup_dir = os.path.join(logs_dir, name) - os.mkdir(backup_dir) - for log in backup_logs: - source_path = os.path.join(logs_dir, log) - dest_path = os.path.join(backup_dir, log) - os.rename(source_path, dest_path) - -def start_datastore(): - from sugar.datastore import datastore - - # Mount the datastore in internal flash - ds_path = env.get_profile_path('datastore') - try: - datastore.mount(ds_path, [], timeout=120) - except Exception, e: - # Don't explode if there's corruption; move the data out of the way - # and attempt to create a store from scratch. - logging.error(e) - shutil.move(ds_path, os.path.abspath(ds_path) + str(time.time())) - datastore.mount(ds_path, [], timeout=120) - -def start_ui_service(): - from jarabe.view.service import UIService - - ui_service = UIService() - ui_service.start() - -def start_session_manager(): - from jarabe.model.session import get_session_manager - - session_manager = get_session_manager() - session_manager.start() - -def unfreeze_dcon_cb(): - logging.debug('STARTUP: unfreeze_dcon_cb') - from jarabe.model import screen - - screen.set_dcon_freeze(0) - -def setup_frame_cb(): - logging.debug('STARTUP: setup_frame_cb') - from jarabe import frame - frame.get_view() - -def setup_keyhandler_cb(): - logging.debug('STARTUP: setup_keyhandler_cb') - from jarabe.view import keyhandler - from jarabe import frame - keyhandler.setup(frame.get_view()) - -def setup_journal_cb(): - logging.debug('STARTUP: setup_journal_cb') - from jarabe.journal import journalactivity - journalactivity.start() - -def show_software_updates_cb(home_window): - logging.debug('STARTUP: show_software_updates_cb') - if os.path.isfile(os.path.expanduser('~/.sugar-update')): - home_window.get_home_box().show_software_updates_alert() - -def setup_notification_service_cb(): - from jarabe.model import notifications - notifications.init() - -def main(): - cleanup_logs() - logger.start('shell') - - intro.check_profile() - - client = gconf.client_get_default() - timezone = client.get_string('/desktop/sugar/date/timezone') - - if timezone is not '': - os.environ['TZ'] = timezone - - start_datastore() - start_ui_service() - start_session_manager() - - sound.restore() - - sys.path.append(config.ext_path) - - gettext.bindtextdomain('sugar', config.locale_path) - gettext.textdomain('sugar') - - icons_path = os.path.join(config.data_path, 'icons') - gtk.icon_theme_get_default().append_search_path(icons_path) - - launcher.setup() - - home_window = HomeWindow() - home_window.show() - - gobject.idle_add(unfreeze_dcon_cb) - gobject.idle_add(setup_frame_cb) - gobject.idle_add(setup_keyhandler_cb) - gobject.idle_add(setup_journal_cb) - gobject.idle_add(setup_notification_service_cb) - gobject.idle_add(show_software_updates_cb, home_window) - - try: - gtk.main() - except KeyboardInterrupt: - print 'Ctrl+C pressed, exiting...' - -main() diff --git a/extensions/cpsection/network/__init__.py b/bin/sugar-shell index 8fea274..b11c33e 100644 --- a/extensions/cpsection/network/__init__.py +++ b/bin/sugar-shell @@ -1,4 +1,5 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +#!/usr/bin/env python +# Copyright (C) 2008, Red Hat, Inc. # # 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 @@ -14,12 +15,20 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from gettext import gettext as _ +import os +import sys -CLASS = 'Network' -ICON = 'module-network' -TITLE = _('Network') -KEYWORDS = ['network', 'jabber', 'radio', 'server'] +if os.environ.has_key('SUGAR_THEME'): + theme = os.environ['SUGAR_THEME'] +else: + theme = 'sugar' +os.environ['GTK2_RC_FILES'] = '/home/marco/sucrose-0.82/install/share/sugar/data/%s.gtkrc' % theme + +sys.path.insert(0, '/home/marco/sucrose-0.82/install/share/sugar/shell') + +from main import main + +main() diff --git a/src/jarabe/config.py b/bin/sugar-shell-service index fdfa516..5df21a8 100644 --- a/src/jarabe/config.py +++ b/bin/sugar-shell-service @@ -1,4 +1,5 @@ -# Copyright (C) 2008 Red Hat, Inc. +#!/usr/bin/env python +# Copyright (C) 2008, Red Hat, Inc. # # 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 @@ -14,13 +15,18 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# pylint: disable-msg=C0301 +import sys +from os import environ + +if not environ.has_key('SUGAR_ACTIVITIES'): + environ['SUGAR_ACTIVITIES'] = '/home/marco/sucrose-0.82/install/share/sugar/activities:' \ + '/home/marco/sucrose-0.82/install/lib64/sugar/activities:' \ + '/home/marco/sucrose-0.82/install/lib/sugar/activities' + +sys.path.insert(0, '/home/marco/sucrose-0.82/install/share/sugar/service') + +from main import main + +main() -prefix = '/home/erikos/sugar-jhbuild/install/' -data_path = '/home/erikos/sugar-jhbuild/install//share/sugar/data' -shell_path = '/home/erikos/sugar-jhbuild/install//share/sugar/shell' -locale_path = '/home/erikos/sugar-jhbuild/install//share/locale' -ext_path = '/home/erikos/sugar-jhbuild/install//share/sugar/extensions' -activities_path = "/home/erikos/sugar-jhbuild/install//share/sugar/activities" -version = '0.83.x' diff --git a/extensions/cpsection/network/__init__.py b/bin/sugar-shell-service.in index 8fea274..49c2764 100644 --- a/extensions/cpsection/network/__init__.py +++ b/bin/sugar-shell-service.in @@ -1,4 +1,5 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +#!/usr/bin/env python +# Copyright (C) 2008, Red Hat, Inc. # # 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 @@ -14,12 +15,18 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from gettext import gettext as _ +import sys +from os import environ -CLASS = 'Network' -ICON = 'module-network' -TITLE = _('Network') -KEYWORDS = ['network', 'jabber', 'radio', 'server'] +if not environ.has_key('SUGAR_ACTIVITIES'): + environ['SUGAR_ACTIVITIES'] = '@prefix@/share/sugar/activities:' \ + '@prefix@/lib64/sugar/activities:' \ + '@prefix@/lib/sugar/activities' +sys.path.insert(0, '@prefix@/share/sugar/service') + +from main import main + +main() diff --git a/extensions/cpsection/network/__init__.py b/bin/sugar-shell.in index 8fea274..55a25a7 100644 --- a/extensions/cpsection/network/__init__.py +++ b/bin/sugar-shell.in @@ -1,4 +1,5 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +#!/usr/bin/env python +# Copyright (C) 2008, Red Hat, Inc. # # 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 @@ -14,12 +15,20 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from gettext import gettext as _ +import os +import sys -CLASS = 'Network' -ICON = 'module-network' -TITLE = _('Network') -KEYWORDS = ['network', 'jabber', 'radio', 'server'] +if os.environ.has_key('SUGAR_THEME'): + theme = os.environ['SUGAR_THEME'] +else: + theme = 'sugar' +os.environ['GTK2_RC_FILES'] = '@prefix@/share/sugar/data/%s.gtkrc' % theme + +sys.path.insert(0, '@prefix@/share/sugar/shell') + +from main import main + +main() diff --git a/bin/sugar-ui-check b/bin/sugar-ui-check deleted file mode 100644 index 4d71796..0000000 --- a/bin/sugar-ui-check +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python -# Copyright (C) 2008, Red Hat, Inc. -# -# 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 - -import logging -import os -import sys -import subprocess -import time - -import dbus -import gobject -import gtk -import wnck - -from sugar import wm - -from jarabe.model.shell import get_sugar_window_type -from sugar.bundle.activitybundle import ActivityBundle -from jarabe import config - -checks_queue = [] -checks_failed = [] -checks_succeeded = [] - -def get_dbus_version(): - p = subprocess.Popen(['dbus-daemon', '--version'], stdout=subprocess.PIPE) - - output = p.communicate()[0] - first_line = output.split('\n')[0] - - return first_line.split(' ')[-1] - -class Check(object): - def __init__(self): - self.name = None - self.succeeded = False - self.start_time = None - self.max_time = None - self.timeout = None - - def start(self): - logging.info('Start %s check.' % self.name) - - self.start_time = time.time() - - def get_failed(self): - if self.max_time and self.start_time: - if time.time() - self.start_time > self.max_time: - return True - return False - - failed = property(get_failed) - -class ShellCheck(Check): - def __init__(self): - Check.__init__(self) - - self.name = 'Shell' - self.max_time = 30 - - def start(self): - Check.start(self) - - screen = wnck.screen_get_default() - screen.connect('window-opened', self._window_opened_cb) - - def _window_opened_cb(self, screen, window): - if window.get_window_type() == wnck.WINDOW_DESKTOP: - self.succeeded = True - -class ActivityCheck(Check): - def __init__(self, bundle_id): - Check.__init__(self) - - self.name = bundle_id - self.max_time = 120 - - def start(self): - Check.start(self) - - self.launch_activity() - - screen = wnck.screen_get_default() - screen.connect('window-opened', self._window_opened_cb) - - def launch_activity(self): - from sugar.activity import activityfactory - - bus = dbus.SessionBus() - proxy = bus.get_object('org.laptop.Shell', '/org/laptop/Shell') - iface = dbus.Interface(proxy, 'org.laptop.Shell') - path = iface.GetBundlePath(self.name) - - if path: - activityfactory.create(ActivityBundle(path)) - else: - logging.error('Cannot find activity %s.' % self.name) - - def _window_opened_cb(self, screen, window): - if wm.get_bundle_id(window) == self.name and \ - get_sugar_window_type(window) != 'launcher': - self.succeeded = True - -def _timeout_cb(): - check = checks_queue[0] - if check.failed: - logging.info('%s check failed.' % (check.name)) - checks_failed.append(checks_queue.pop(0)) - elif check.succeeded: - logging.info('%s check succeeded.' % (check.name)) - checks_succeeded.append(checks_queue.pop(0)) - else: - return True - - if len(checks_queue) > 0: - checks_queue[0].start() - else: - gtk.main_quit() - - return True - -def main(): - os.environ['GTK2_RC_FILES'] = os.path.join(config.data_path, 'sugar-100.gtkrc') - - logging.basicConfig(level=logging.INFO, - format='%(asctime)s %(levelname)s %(message)s') - - checks_queue.append(ShellCheck()) - - if get_dbus_version() >= '1.2.1': - # FIXME needs to get a list of the installed activities - checks_queue.append(ActivityCheck('org.laptop.Log')) - checks_queue.append(ActivityCheck('org.laptop.Chat')) - checks_queue.append(ActivityCheck('org.laptop.WebActivity')) - checks_queue.append(ActivityCheck('org.laptop.Pippy')) - checks_queue.append(ActivityCheck('org.laptop.Terminal')) - checks_queue.append(ActivityCheck('org.laptop.AbiWordActivity')) - - checks_queue[0].start() - gobject.timeout_add(500, _timeout_cb) - - gtk.main() - - if len(checks_failed) > 0: - sys.exit(1) - -main() diff --git a/bin/sugar.in b/bin/sugar.in index c802b77..88e478a 100644 --- a/bin/sugar.in +++ b/bin/sugar.in @@ -1,17 +1,9 @@ #!/bin/sh -if test -z "$SUGAR_SCALING"; then - export SUGAR_SCALING=100 -fi - -export GTK2_RC_FILES="@prefix@/share/sugar/data/sugar-$SUGAR_SCALING.gtkrc" +export SUGAR_THEME=sugar-xo -if ! test -f "$GTK2_RC_FILES"; then - echo "sugar: ERROR: Gtk theme for scaling $SUGAR_SCALING not available." - exit 1 +if [ -f /etc/olpc-security ] ; then + exec dbus-launch --exit-with-session --config-file=/etc/dbus-1/session-olpc.conf sugar-shell +else + exec dbus-launch --exit-with-session sugar-shell fi - -matchbox-window-manager -use_titlebar no -theme sugar \ - -kbdconfig @prefix@/share/sugar/data/kbdconfig & - -sugar-session @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for Sugar 0.83.3. +# Generated by GNU Autoconf 2.61 for Sugar 0.82.8. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. @@ -572,8 +572,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='Sugar' PACKAGE_TARNAME='sugar' -PACKAGE_VERSION='0.83.3' -PACKAGE_STRING='Sugar 0.83.3' +PACKAGE_VERSION='0.82.8' +PACKAGE_STRING='Sugar 0.82.8' PACKAGE_BUGREPORT='' ac_unique_file="configure.ac" @@ -748,11 +748,6 @@ POSUB MKINSTALLDIRS ENABLE_UPDATE_MIMEDB_TRUE ENABLE_UPDATE_MIMEDB_FALSE -GCONFTOOL -GCONF_SCHEMA_CONFIG_SOURCE -GCONF_SCHEMA_FILE_DIR -GCONF_SCHEMAS_INSTALL_TRUE -GCONF_SCHEMAS_INSTALL_FALSE LIBOBJS LTLIBOBJS' ac_subst_files='' @@ -1270,7 +1265,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures Sugar 0.83.3 to adapt to many kinds of systems. +\`configure' configures Sugar 0.82.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1336,7 +1331,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Sugar 0.83.3:";; + short | recursive ) echo "Configuration of Sugar 0.82.8:";; esac cat <<\_ACEOF @@ -1347,13 +1342,6 @@ Optional Features: --enable-dependency-tracking do not reject slow dependency extractors --disable-update-mimedb disable the update-mime-database after install default=no - --disable-schemas-install Disable the schemas installation - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-gconf-source=sourceaddress Config database for installing schema files. - --with-gconf-schema-file-dir=dir Directory for installing schema files. Some influential environment variables: PKG_CONFIG path to pkg-config utility @@ -1432,7 +1420,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Sugar configure 0.83.3 +Sugar configure 0.82.8 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1446,7 +1434,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Sugar $as_me 0.83.3, which was +It was created by Sugar $as_me 0.82.8, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -1805,7 +1793,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu -SUCROSE_VERSION="0.83.x" +SUCROSE_VERSION="0.82.1" am__api_version='1.10' @@ -2145,7 +2133,7 @@ fi # Define the identity of the package. PACKAGE='sugar' - VERSION='0.83.3' + VERSION='0.82.8' cat >>confdefs.h <<_ACEOF @@ -2556,12 +2544,12 @@ if test -n "$SHELL_CFLAGS"; then pkg_cv_SHELL_CFLAGS="$SHELL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"pygtk-2.0 gtk+-2.0 gconf-2.0\"") >&5 - ($PKG_CONFIG --exists --print-errors "pygtk-2.0 gtk+-2.0 gconf-2.0") 2>&5 + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"pygtk-2.0 gtk+-2.0\"") >&5 + ($PKG_CONFIG --exists --print-errors "pygtk-2.0 gtk+-2.0") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then - pkg_cv_SHELL_CFLAGS=`$PKG_CONFIG --cflags "pygtk-2.0 gtk+-2.0 gconf-2.0" 2>/dev/null` + pkg_cv_SHELL_CFLAGS=`$PKG_CONFIG --cflags "pygtk-2.0 gtk+-2.0" 2>/dev/null` else pkg_failed=yes fi @@ -2572,12 +2560,12 @@ if test -n "$SHELL_LIBS"; then pkg_cv_SHELL_LIBS="$SHELL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ - { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"pygtk-2.0 gtk+-2.0 gconf-2.0\"") >&5 - ($PKG_CONFIG --exists --print-errors "pygtk-2.0 gtk+-2.0 gconf-2.0") 2>&5 + { (echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"pygtk-2.0 gtk+-2.0\"") >&5 + ($PKG_CONFIG --exists --print-errors "pygtk-2.0 gtk+-2.0") 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then - pkg_cv_SHELL_LIBS=`$PKG_CONFIG --libs "pygtk-2.0 gtk+-2.0 gconf-2.0" 2>/dev/null` + pkg_cv_SHELL_LIBS=`$PKG_CONFIG --libs "pygtk-2.0 gtk+-2.0" 2>/dev/null` else pkg_failed=yes fi @@ -2595,14 +2583,14 @@ else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then - SHELL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "pygtk-2.0 gtk+-2.0 gconf-2.0" 2>&1` + SHELL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "pygtk-2.0 gtk+-2.0" 2>&1` else - SHELL_PKG_ERRORS=`$PKG_CONFIG --print-errors "pygtk-2.0 gtk+-2.0 gconf-2.0" 2>&1` + SHELL_PKG_ERRORS=`$PKG_CONFIG --print-errors "pygtk-2.0 gtk+-2.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SHELL_PKG_ERRORS" >&5 - { { echo "$as_me:$LINENO: error: Package requirements (pygtk-2.0 gtk+-2.0 gconf-2.0) were not met: + { { echo "$as_me:$LINENO: error: Package requirements (pygtk-2.0 gtk+-2.0) were not met: $SHELL_PKG_ERRORS @@ -2613,7 +2601,7 @@ Alternatively, you may set the environment variables SHELL_CFLAGS and SHELL_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. " >&5 -echo "$as_me: error: Package requirements (pygtk-2.0 gtk+-2.0 gconf-2.0) were not met: +echo "$as_me: error: Package requirements (pygtk-2.0 gtk+-2.0) were not met: $SHELL_PKG_ERRORS @@ -6350,114 +6338,10 @@ else fi -# Verify that gconftool is installed -# -# Extract the first word of "gconftool-2", so it can be a program name with args. -set dummy gconftool-2; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_path_GCONFTOOL+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $GCONFTOOL in - [\\/]* | ?:[\\/]*) - ac_cv_path_GCONFTOOL="$GCONFTOOL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_GCONFTOOL="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - - test -z "$ac_cv_path_GCONFTOOL" && ac_cv_path_GCONFTOOL="no" - ;; -esac -fi -GCONFTOOL=$ac_cv_path_GCONFTOOL -if test -n "$GCONFTOOL"; then - { echo "$as_me:$LINENO: result: $GCONFTOOL" >&5 -echo "${ECHO_T}$GCONFTOOL" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - -if test "$GCONFTOOL" = no; then - { { echo "$as_me:$LINENO: error: gconftool-2 executable not found in your path - should be installed with GConf" >&5 -echo "$as_me: error: gconftool-2 executable not found in your path - should be installed with GConf" >&2;} - { (exit 1); exit 1; }; } -fi - - - if test "x$GCONF_SCHEMA_INSTALL_SOURCE" = "x"; then - GCONF_SCHEMA_CONFIG_SOURCE=`gconftool-2 --get-default-source` - else - GCONF_SCHEMA_CONFIG_SOURCE=$GCONF_SCHEMA_INSTALL_SOURCE - fi - - -# Check whether --with-gconf-source was given. -if test "${with_gconf_source+set}" = set; then - withval=$with_gconf_source; GCONF_SCHEMA_CONFIG_SOURCE="$withval" -fi - - - - { echo "$as_me:$LINENO: result: Using config source $GCONF_SCHEMA_CONFIG_SOURCE for schema installation" >&5 -echo "${ECHO_T}Using config source $GCONF_SCHEMA_CONFIG_SOURCE for schema installation" >&6; } - - if test "x$GCONF_SCHEMA_FILE_DIR" = "x"; then - GCONF_SCHEMA_FILE_DIR='$(sysconfdir)/gconf/schemas' - fi - - -# Check whether --with-gconf-schema-file-dir was given. -if test "${with_gconf_schema_file_dir+set}" = set; then - withval=$with_gconf_schema_file_dir; GCONF_SCHEMA_FILE_DIR="$withval" -fi - - - - { echo "$as_me:$LINENO: result: Using $GCONF_SCHEMA_FILE_DIR as install directory for schema files" >&5 -echo "${ECHO_T}Using $GCONF_SCHEMA_FILE_DIR as install directory for schema files" >&6; } - - # Check whether --enable-schemas-install was given. -if test "${enable_schemas_install+set}" = set; then - enableval=$enable_schemas_install; case ${enableval} in - yes|no) ;; - *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for --enable-schemas-install" >&5 -echo "$as_me: error: bad value ${enableval} for --enable-schemas-install" >&2;} - { (exit 1); exit 1; }; } ;; - esac -fi - - if test "$enable_schemas_install" != no; then - GCONF_SCHEMAS_INSTALL_TRUE= - GCONF_SCHEMAS_INSTALL_FALSE='#' -else - GCONF_SCHEMAS_INSTALL_TRUE='#' - GCONF_SCHEMAS_INSTALL_FALSE= -fi +ac_config_files="$ac_config_files bin/sugar bin/sugar-control-panel bin/sugar-emulator bin/sugar-shell bin/sugar-shell-service service/config.py src/config.py" - - -ac_config_files="$ac_config_files bin/sugar src/jarabe/config.py" - - -ac_config_files="$ac_config_files Makefile bin/Makefile data/Makefile data/icons/Makefile extensions/Makefile extensions/cpsection/Makefile extensions/cpsection/aboutme/Makefile extensions/cpsection/aboutxo/Makefile extensions/cpsection/datetime/Makefile extensions/cpsection/frame/Makefile extensions/cpsection/language/Makefile extensions/cpsection/network/Makefile extensions/cpsection/power/Makefile extensions/deviceicon/Makefile extensions/globalkey/Makefile src/Makefile src/jarabe/Makefile src/jarabe/controlpanel/Makefile src/jarabe/desktop/Makefile src/jarabe/frame/Makefile src/jarabe/intro/Makefile src/jarabe/journal/Makefile src/jarabe/view/Makefile src/jarabe/model/Makefile src/jarabe/util/Makefile src/jarabe/util/telepathy/Makefile po/Makefile.in" +ac_config_files="$ac_config_files Makefile bin/Makefile data/Makefile data/icons/Makefile service/Makefile src/Makefile src/controlpanel/Makefile src/controlpanel/model/Makefile src/controlpanel/view/Makefile src/intro/Makefile src/hardware/Makefile src/view/Makefile src/view/devices/Makefile src/view/devices/network/Makefile src/view/frame/Makefile src/view/home/Makefile src/model/Makefile src/model/devices/Makefile src/model/devices/network/Makefile po/Makefile.in" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -6610,13 +6494,6 @@ echo "$as_me: error: conditional \"ENABLE_UPDATE_MIMEDB\" was never defined. Usually this means the macro was only invoked conditionally." >&2;} { (exit 1); exit 1; }; } fi -if test -z "${GCONF_SCHEMAS_INSTALL_TRUE}" && test -z "${GCONF_SCHEMAS_INSTALL_FALSE}"; then - { { echo "$as_me:$LINENO: error: conditional \"GCONF_SCHEMAS_INSTALL\" was never defined. -Usually this means the macro was only invoked conditionally." >&5 -echo "$as_me: error: conditional \"GCONF_SCHEMAS_INSTALL\" was never defined. -Usually this means the macro was only invoked conditionally." >&2;} - { (exit 1); exit 1; }; } -fi : ${CONFIG_STATUS=./config.status} ac_clean_files_save=$ac_clean_files @@ -6917,7 +6794,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by Sugar $as_me 0.83.3, which was +This file was extended by Sugar $as_me 0.82.8, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -6964,7 +6841,7 @@ Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -Sugar config.status 0.83.3 +Sugar config.status 0.82.8 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -7077,33 +6954,31 @@ do "intltool") CONFIG_COMMANDS="$CONFIG_COMMANDS intltool" ;; "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "bin/sugar") CONFIG_FILES="$CONFIG_FILES bin/sugar" ;; - "src/jarabe/config.py") CONFIG_FILES="$CONFIG_FILES src/jarabe/config.py" ;; + "bin/sugar-control-panel") CONFIG_FILES="$CONFIG_FILES bin/sugar-control-panel" ;; + "bin/sugar-emulator") CONFIG_FILES="$CONFIG_FILES bin/sugar-emulator" ;; + "bin/sugar-shell") CONFIG_FILES="$CONFIG_FILES bin/sugar-shell" ;; + "bin/sugar-shell-service") CONFIG_FILES="$CONFIG_FILES bin/sugar-shell-service" ;; + "service/config.py") CONFIG_FILES="$CONFIG_FILES service/config.py" ;; + "src/config.py") CONFIG_FILES="$CONFIG_FILES src/config.py" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "bin/Makefile") CONFIG_FILES="$CONFIG_FILES bin/Makefile" ;; "data/Makefile") CONFIG_FILES="$CONFIG_FILES data/Makefile" ;; "data/icons/Makefile") CONFIG_FILES="$CONFIG_FILES data/icons/Makefile" ;; - "extensions/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/Makefile" ;; - "extensions/cpsection/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/Makefile" ;; - "extensions/cpsection/aboutme/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/aboutme/Makefile" ;; - "extensions/cpsection/aboutxo/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/aboutxo/Makefile" ;; - "extensions/cpsection/datetime/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/datetime/Makefile" ;; - "extensions/cpsection/frame/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/frame/Makefile" ;; - "extensions/cpsection/language/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/language/Makefile" ;; - "extensions/cpsection/network/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/network/Makefile" ;; - "extensions/cpsection/power/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/cpsection/power/Makefile" ;; - "extensions/deviceicon/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/deviceicon/Makefile" ;; - "extensions/globalkey/Makefile") CONFIG_FILES="$CONFIG_FILES extensions/globalkey/Makefile" ;; + "service/Makefile") CONFIG_FILES="$CONFIG_FILES service/Makefile" ;; "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; - "src/jarabe/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/Makefile" ;; - "src/jarabe/controlpanel/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/controlpanel/Makefile" ;; - "src/jarabe/desktop/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/desktop/Makefile" ;; - "src/jarabe/frame/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/frame/Makefile" ;; - "src/jarabe/intro/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/intro/Makefile" ;; - "src/jarabe/journal/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/journal/Makefile" ;; - "src/jarabe/view/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/view/Makefile" ;; - "src/jarabe/model/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/model/Makefile" ;; - "src/jarabe/util/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/util/Makefile" ;; - "src/jarabe/util/telepathy/Makefile") CONFIG_FILES="$CONFIG_FILES src/jarabe/util/telepathy/Makefile" ;; + "src/controlpanel/Makefile") CONFIG_FILES="$CONFIG_FILES src/controlpanel/Makefile" ;; + "src/controlpanel/model/Makefile") CONFIG_FILES="$CONFIG_FILES src/controlpanel/model/Makefile" ;; + "src/controlpanel/view/Makefile") CONFIG_FILES="$CONFIG_FILES src/controlpanel/view/Makefile" ;; + "src/intro/Makefile") CONFIG_FILES="$CONFIG_FILES src/intro/Makefile" ;; + "src/hardware/Makefile") CONFIG_FILES="$CONFIG_FILES src/hardware/Makefile" ;; + "src/view/Makefile") CONFIG_FILES="$CONFIG_FILES src/view/Makefile" ;; + "src/view/devices/Makefile") CONFIG_FILES="$CONFIG_FILES src/view/devices/Makefile" ;; + "src/view/devices/network/Makefile") CONFIG_FILES="$CONFIG_FILES src/view/devices/network/Makefile" ;; + "src/view/frame/Makefile") CONFIG_FILES="$CONFIG_FILES src/view/frame/Makefile" ;; + "src/view/home/Makefile") CONFIG_FILES="$CONFIG_FILES src/view/home/Makefile" ;; + "src/model/Makefile") CONFIG_FILES="$CONFIG_FILES src/model/Makefile" ;; + "src/model/devices/Makefile") CONFIG_FILES="$CONFIG_FILES src/model/devices/Makefile" ;; + "src/model/devices/network/Makefile") CONFIG_FILES="$CONFIG_FILES src/model/devices/network/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;; @@ -7343,16 +7218,11 @@ POSUB!$POSUB$ac_delim MKINSTALLDIRS!$MKINSTALLDIRS$ac_delim ENABLE_UPDATE_MIMEDB_TRUE!$ENABLE_UPDATE_MIMEDB_TRUE$ac_delim ENABLE_UPDATE_MIMEDB_FALSE!$ENABLE_UPDATE_MIMEDB_FALSE$ac_delim -GCONFTOOL!$GCONFTOOL$ac_delim -GCONF_SCHEMA_CONFIG_SOURCE!$GCONF_SCHEMA_CONFIG_SOURCE$ac_delim -GCONF_SCHEMA_FILE_DIR!$GCONF_SCHEMA_FILE_DIR$ac_delim -GCONF_SCHEMAS_INSTALL_TRUE!$GCONF_SCHEMAS_INSTALL_TRUE$ac_delim -GCONF_SCHEMAS_INSTALL_FALSE!$GCONF_SCHEMAS_INSTALL_FALSE$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 45; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 40; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/configure.ac b/configure.ac index 1104c4f..028b807 100644 --- a/configure.ac +++ b/configure.ac @@ -1,18 +1,18 @@ -AC_INIT([Sugar],[0.83.3],[],[sugar]) +AC_INIT([Sugar],[0.82.8],[],[sugar]) AC_PREREQ([2.59]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_SRCDIR([configure.ac]) -SUCROSE_VERSION="0.83.x" +SUCROSE_VERSION="0.82.1" AC_SUBST(SUCROSE_VERSION) AM_INIT_AUTOMAKE([1.9 foreign dist-bzip2 no-dist-gzip]) AM_PATH_PYTHON -PKG_CHECK_MODULES(SHELL, pygtk-2.0 gtk+-2.0 gconf-2.0) +PKG_CHECK_MODULES(SHELL, pygtk-2.0 gtk+-2.0) # Setup GETTEXT # @@ -29,20 +29,14 @@ AC_ARG_ENABLE(update-mimedb, enable_update_mimedb=yes) AM_CONDITIONAL(ENABLE_UPDATE_MIMEDB, test x$enable_update_mimedb = xyes) -# Verify that gconftool is installed -# -AC_PATH_PROG(GCONFTOOL, gconftool-2, no) - -if test "$GCONFTOOL" = no; then - AC_MSG_ERROR([gconftool-2 executable not found in your path - should be installed with GConf]) -fi - -AM_GCONF_SOURCE_2 - - AC_CONFIG_FILES([ bin/sugar -src/jarabe/config.py +bin/sugar-control-panel +bin/sugar-emulator +bin/sugar-shell +bin/sugar-shell-service +service/config.py +src/config.py ]) AC_OUTPUT([ @@ -50,27 +44,20 @@ Makefile bin/Makefile data/Makefile data/icons/Makefile -extensions/Makefile -extensions/cpsection/Makefile -extensions/cpsection/aboutme/Makefile -extensions/cpsection/aboutxo/Makefile -extensions/cpsection/datetime/Makefile -extensions/cpsection/frame/Makefile -extensions/cpsection/language/Makefile -extensions/cpsection/network/Makefile -extensions/cpsection/power/Makefile -extensions/deviceicon/Makefile -extensions/globalkey/Makefile +service/Makefile src/Makefile -src/jarabe/Makefile -src/jarabe/controlpanel/Makefile -src/jarabe/desktop/Makefile -src/jarabe/frame/Makefile -src/jarabe/intro/Makefile -src/jarabe/journal/Makefile -src/jarabe/view/Makefile -src/jarabe/model/Makefile -src/jarabe/util/Makefile -src/jarabe/util/telepathy/Makefile +src/controlpanel/Makefile +src/controlpanel/model/Makefile +src/controlpanel/view/Makefile +src/intro/Makefile +src/hardware/Makefile +src/view/Makefile +src/view/devices/Makefile +src/view/devices/network/Makefile +src/view/frame/Makefile +src/view/home/Makefile +src/model/Makefile +src/model/devices/Makefile +src/model/devices/network/Makefile po/Makefile.in ]) diff --git a/data/Makefile.am b/data/Makefile.am index 585f071..cdf9dc5 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,12 +1,12 @@ SUBDIRS = icons -sugar-72.gtkrc: gtkrc.em - $(srcdir)/em.py -D scaling=\'72\' $(srcdir)/gtkrc.em > \ - $(top_builddir)/data/sugar-72.gtkrc +sugar.gtkrc: gtkrc.em + $(srcdir)/em.py -D theme=\'sugar\' $(srcdir)/gtkrc.em > \ + $(top_builddir)/data/sugar.gtkrc -sugar-100.gtkrc: gtkrc.em - $(srcdir)/em.py -D scaling=\'100\' $(srcdir)/gtkrc.em > \ - $(top_builddir)/data/sugar-100.gtkrc +sugar-xo.gtkrc: gtkrc.em + $(srcdir)/em.py -D theme=\'sugar-xo\' $(srcdir)/gtkrc.em > \ + $(top_builddir)/data/sugar-xo.gtkrc sugardir = $(pkgdatadir)/data sugar_DATA = \ @@ -16,8 +16,8 @@ sugar_DATA = \ $(GTKRC_FILES) GTKRC_FILES = \ - sugar-72.gtkrc \ - sugar-100.gtkrc + sugar.gtkrc \ + sugar-xo.gtkrc xsessionsdir = $(datadir)/xsessions xsessions_DATA = sugar.desktop @@ -29,9 +29,6 @@ mime_xml_files = $(mime_xml_in_files:.xml.in=.xml) mimedir = $(datadir)/mime/packages mime_DATA = $(mime_xml_files) -nmservicedir = $(sysconfdir)/dbus-1/system.d/ -nmservice_DATA = nm-user-settings.conf - install-data-hook: if ENABLE_UPDATE_MIMEDB if [ -z "$$DESTDIR" ]; then \ @@ -46,16 +43,5 @@ if ENABLE_UPDATE_MIMEDB fi endif -@INTLTOOL_SCHEMAS_RULE@ - -schemadir = $(GCONF_SCHEMA_FILE_DIR) -schema_in_files = sugar.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) - -install-data-local: $(schema_DATA) -if GCONF_SCHEMAS_INSTALL - GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule sugar.schemas 2>&1 > /dev/null -endif - -EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(nmservice_DATA) $(mime_xml_in_files) em.py gtkrc.em $(schema_in_files) -CLEANFILES = $(GTKRC_FILES) $(mime_xml_files) $(schema_DATA) +EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(mime_xml_in_files) em.py gtkrc.em +CLEANFILES = $(GTKRC_FILES) $(mime_xml_files) diff --git a/data/Makefile.in b/data/Makefile.in index 16d7f7e..dcbb82f 100644 --- a/data/Makefile.in +++ b/data/Makefile.in @@ -53,16 +53,12 @@ am__vpath_adj = case $$p in \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(mimedir)" "$(DESTDIR)$(nmservicedir)" \ - "$(DESTDIR)$(schemadir)" "$(DESTDIR)$(sugardir)" \ +am__installdirs = "$(DESTDIR)$(mimedir)" "$(DESTDIR)$(sugardir)" \ "$(DESTDIR)$(xsessionsdir)" mimeDATA_INSTALL = $(INSTALL_DATA) -nmserviceDATA_INSTALL = $(INSTALL_DATA) -schemaDATA_INSTALL = $(INSTALL_DATA) sugarDATA_INSTALL = $(INSTALL_DATA) xsessionsDATA_INSTALL = $(INSTALL_DATA) -DATA = $(mime_DATA) $(nmservice_DATA) $(schema_DATA) $(sugar_DATA) \ - $(xsessions_DATA) +DATA = $(mime_DATA) $(sugar_DATA) $(xsessions_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags @@ -92,9 +88,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -220,8 +213,8 @@ sugar_DATA = \ $(GTKRC_FILES) GTKRC_FILES = \ - sugar-72.gtkrc \ - sugar-100.gtkrc + sugar.gtkrc \ + sugar-xo.gtkrc xsessionsdir = $(datadir)/xsessions xsessions_DATA = sugar.desktop @@ -229,13 +222,8 @@ mime_xml_in_files = sugar.xml.in mime_xml_files = $(mime_xml_in_files:.xml.in=.xml) mimedir = $(datadir)/mime/packages mime_DATA = $(mime_xml_files) -nmservicedir = $(sysconfdir)/dbus-1/system.d/ -nmservice_DATA = nm-user-settings.conf -schemadir = $(GCONF_SCHEMA_FILE_DIR) -schema_in_files = sugar.schemas.in -schema_DATA = $(schema_in_files:.schemas.in=.schemas) -EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(nmservice_DATA) $(mime_xml_in_files) em.py gtkrc.em $(schema_in_files) -CLEANFILES = $(GTKRC_FILES) $(mime_xml_files) $(schema_DATA) +EXTRA_DIST = $(sugar_DATA) $(xsessions_DATA) $(mime_xml_in_files) em.py gtkrc.em +CLEANFILES = $(GTKRC_FILES) $(mime_xml_files) all: all-recursive .SUFFIXES: @@ -285,40 +273,6 @@ uninstall-mimeDATA: echo " rm -f '$(DESTDIR)$(mimedir)/$$f'"; \ rm -f "$(DESTDIR)$(mimedir)/$$f"; \ done -install-nmserviceDATA: $(nmservice_DATA) - @$(NORMAL_INSTALL) - test -z "$(nmservicedir)" || $(MKDIR_P) "$(DESTDIR)$(nmservicedir)" - @list='$(nmservice_DATA)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - echo " $(nmserviceDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(nmservicedir)/$$f'"; \ - $(nmserviceDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(nmservicedir)/$$f"; \ - done - -uninstall-nmserviceDATA: - @$(NORMAL_UNINSTALL) - @list='$(nmservice_DATA)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(nmservicedir)/$$f'"; \ - rm -f "$(DESTDIR)$(nmservicedir)/$$f"; \ - done -install-schemaDATA: $(schema_DATA) - @$(NORMAL_INSTALL) - test -z "$(schemadir)" || $(MKDIR_P) "$(DESTDIR)$(schemadir)" - @list='$(schema_DATA)'; for p in $$list; do \ - if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ - f=$(am__strip_dir) \ - echo " $(schemaDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(schemadir)/$$f'"; \ - $(schemaDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(schemadir)/$$f"; \ - done - -uninstall-schemaDATA: - @$(NORMAL_UNINSTALL) - @list='$(schema_DATA)'; for p in $$list; do \ - f=$(am__strip_dir) \ - echo " rm -f '$(DESTDIR)$(schemadir)/$$f'"; \ - rm -f "$(DESTDIR)$(schemadir)/$$f"; \ - done install-sugarDATA: $(sugar_DATA) @$(NORMAL_INSTALL) test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" @@ -532,7 +486,7 @@ check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: - for dir in "$(DESTDIR)$(mimedir)" "$(DESTDIR)$(nmservicedir)" "$(DESTDIR)$(schemadir)" "$(DESTDIR)$(sugardir)" "$(DESTDIR)$(xsessionsdir)"; do \ + for dir in "$(DESTDIR)$(mimedir)" "$(DESTDIR)$(sugardir)" "$(DESTDIR)$(xsessionsdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive @@ -578,8 +532,7 @@ info: info-recursive info-am: -install-data-am: install-data-local install-mimeDATA \ - install-nmserviceDATA install-schemaDATA install-sugarDATA \ +install-data-am: install-mimeDATA install-sugarDATA \ install-xsessionsDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook @@ -616,8 +569,7 @@ ps: ps-recursive ps-am: -uninstall-am: uninstall-mimeDATA uninstall-nmserviceDATA \ - uninstall-schemaDATA uninstall-sugarDATA \ +uninstall-am: uninstall-mimeDATA uninstall-sugarDATA \ uninstall-xsessionsDATA @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook @@ -630,27 +582,24 @@ uninstall-am: uninstall-mimeDATA uninstall-nmserviceDATA \ ctags-recursive distclean distclean-generic distclean-tags \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-hook \ - install-data-local install-dvi install-dvi-am install-exec \ - install-exec-am install-html install-html-am install-info \ - install-info-am install-man install-mimeDATA \ - install-nmserviceDATA install-pdf install-pdf-am install-ps \ - install-ps-am install-schemaDATA install-strip \ - install-sugarDATA install-xsessionsDATA installcheck \ - installcheck-am installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ - pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ - uninstall-hook uninstall-mimeDATA uninstall-nmserviceDATA \ - uninstall-schemaDATA uninstall-sugarDATA \ - uninstall-xsessionsDATA - - -sugar-72.gtkrc: gtkrc.em - $(srcdir)/em.py -D scaling=\'72\' $(srcdir)/gtkrc.em > \ - $(top_builddir)/data/sugar-72.gtkrc - -sugar-100.gtkrc: gtkrc.em - $(srcdir)/em.py -D scaling=\'100\' $(srcdir)/gtkrc.em > \ - $(top_builddir)/data/sugar-100.gtkrc + install-dvi install-dvi-am install-exec install-exec-am \ + install-html install-html-am install-info install-info-am \ + install-man install-mimeDATA install-pdf install-pdf-am \ + install-ps install-ps-am install-strip install-sugarDATA \ + install-xsessionsDATA installcheck installcheck-am installdirs \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am uninstall-hook \ + uninstall-mimeDATA uninstall-sugarDATA uninstall-xsessionsDATA + + +sugar.gtkrc: gtkrc.em + $(srcdir)/em.py -D theme=\'sugar\' $(srcdir)/gtkrc.em > \ + $(top_builddir)/data/sugar.gtkrc + +sugar-xo.gtkrc: gtkrc.em + $(srcdir)/em.py -D theme=\'sugar-xo\' $(srcdir)/gtkrc.em > \ + $(top_builddir)/data/sugar-xo.gtkrc @INTLTOOL_XML_RULE@ install-data-hook: @@ -662,11 +611,6 @@ uninstall-hook: @ENABLE_UPDATE_MIMEDB_TRUE@ if [ -z "$$DESTDIR" ]; then \ @ENABLE_UPDATE_MIMEDB_TRUE@ update-mime-database "$(datadir)/mime"; \ @ENABLE_UPDATE_MIMEDB_TRUE@ fi - -@INTLTOOL_SCHEMAS_RULE@ - -install-data-local: $(schema_DATA) -@GCONF_SCHEMAS_INSTALL_TRUE@ GCONF_CONFIG_SOURCE=$(GCONF_SCHEMA_CONFIG_SOURCE) $(GCONFTOOL) --makefile-install-rule sugar.schemas 2>&1 > /dev/null # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/data/activities.defaults b/data/activities.defaults index b726355..fe229a1 100644 --- a/data/activities.defaults +++ b/data/activities.defaults @@ -1,30 +1,19 @@ # Activities to be automatically added to the ring after an upgrade -com.garycmartin.Moon -com.jotaro.ImplodeActivity -com.laptop.Ruler -edu.mit.media.ScratchActivity +org.laptop.Chat +org.laptop.WebActivity org.laptop.AbiWordActivity -org.laptop.AcousticMeasure -org.laptop.Analyze +org.laptop.RecordActivity +org.laptop.Oficina +org.laptop.TamTamMini +org.vpri.EtoysActivity +org.laptop.TurtleArtActivity +org.laptop.Pippy org.laptop.Calculate -org.laptop.Chat -org.laptop.HelpActivity -org.laptop.Log +org.laptop.Terminal org.laptop.MeasureActivity +org.laptop.AcousticMeasure org.laptop.Memorize -org.laptop.Oficina -org.laptop.Pippy -org.laptop.RecordActivity -org.laptop.TamTamEdit org.laptop.TamTamJam -org.laptop.TamTamMini +org.laptop.TamTamEdit org.laptop.TamTamSynthLab -org.laptop.Terminal -org.laptop.TurtleArtActivity -org.laptop.WebActivity -org.laptop.WikipediaActivityEN -org.laptop.sugar.ReadActivity -org.vpri.EtoysActivity -vu.lux.olpc.Maze -vu.lux.olpc.Speak diff --git a/data/gtkrc.em b/data/gtkrc.em index f355141..a19b519 100644 --- a/data/gtkrc.em +++ b/data/gtkrc.em @@ -1,15 +1,14 @@ @{ -if scaling == '72': +if theme == 'sugar': font_name = 'Sans Serif 10' icon_sizes = 'gtk-large-toolbar=40,40' else: font_name = 'Sans Serif 7' icon_sizes = 'gtk-large-toolbar=55,55' }@ -gtk-theme-name = "sugar-@scaling" +gtk-theme-name = "@theme" gtk-icon-theme-name = "sugar" gtk-font-name = "@font_name" gtk-cursor-theme-name = "sugar" gtk-toolbar-style = GTK_TOOLBAR_ICONS gtk-icon-sizes = "@icon_sizes" -gtk-cursor-blink-timeout = 3 diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am index ac26247..8209ca3 100644 --- a/data/icons/Makefile.am +++ b/data/icons/Makefile.am @@ -1,7 +1,6 @@ sugardir = $(pkgdatadir)/data/icons sugar_DATA = \ - activity-journal.svg \ module-about_me.svg \ module-about_my_xo.svg \ module-date_and_time.svg \ diff --git a/data/icons/Makefile.in b/data/icons/Makefile.in index d475dbf..bb9dcda 100644 --- a/data/icons/Makefile.in +++ b/data/icons/Makefile.in @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -194,7 +191,6 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ sugardir = $(pkgdatadir)/data/icons sugar_DATA = \ - activity-journal.svg \ module-about_me.svg \ module-about_my_xo.svg \ module-date_and_time.svg \ diff --git a/data/icons/activity-journal.svg b/data/icons/activity-journal.svg deleted file mode 100644 index 1ae35db..0000000 --- a/data/icons/activity-journal.svg +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [ - <!ENTITY stroke_color "#666666"> - <!ENTITY fill_color "#ffffff"> -]><svg enable-background="new 0 0 55 55" height="55px" id="Layer_1" version="1.1" viewBox="0 0 55 55" width="55px" x="0px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="0px"><g display="block" id="activity-journal"> - <path d="M45.866,44.669 c0,2.511-1.528,4.331-4.332,4.331H12.077V6h29.458c2.15,0,4.332,2.154,4.332,4.33L45.866,44.669L45.866,44.669z" fill="&fill_color;" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/> - - <line fill="none" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" x1="21.341" x2="21.341" y1="6.121" y2="48.881"/> - <path d="M7.384,14.464 c0,0,2.084,0.695,4.17,0.695c2.086,0,4.173-0.695,4.173-0.695" fill="none" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/> - <path d="M7.384,28.021 c0,0,1.912,0.695,4.345,0.695s3.999-0.695,3.999-0.695" fill="none" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/> - <path d="M7.384,41.232 c0,0,1.736,0.695,4.518,0.695c2.781,0,3.825-0.695,3.825-0.695" fill="none" stroke="&stroke_color;" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5"/> -</g></svg>
\ No newline at end of file diff --git a/data/nm-user-settings.conf b/data/nm-user-settings.conf deleted file mode 100644 index af7c642..0000000 --- a/data/nm-user-settings.conf +++ /dev/null @@ -1,34 +0,0 @@ -<!DOCTYPE busconfig PUBLIC - "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" - "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -<busconfig> - <policy user="root"> - <allow own="org.freedesktop.NetworkManagerUserSettings"/> - - <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> - <allow send_interface="org.freedesktop.NetworkManagerSettings"/> - - <!-- Only root can get secrets --> - <allow send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/> - </policy> - <policy at_console="true"> - <allow own="org.freedesktop.NetworkManagerUserSettings"/> - - <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> - <allow send_interface="org.freedesktop.NetworkManagerSettings"/> - - <!-- Only root can get secrets --> - <deny send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/> - </policy> - <policy context="default"> - <deny own="org.freedesktop.NetworkManagerUserSettings"/> - - <allow send_destination="org.freedesktop.NetworkManagerUserSettings"/> - <allow send_interface="org.freedesktop.NetworkManagerSettings"/> - <!-- Only root can get secrets --> - <deny send_interface="org.freedesktop.NetworkManagerSettings.Secrets"/> - </policy> - - <limit name="max_replies_per_connection">512</limit> -</busconfig> - diff --git a/data/sugar-100.gtkrc b/data/sugar-xo.gtkrc index dced036..62831ad 100644 --- a/data/sugar-100.gtkrc +++ b/data/sugar-xo.gtkrc @@ -1,7 +1,6 @@ -gtk-theme-name = "sugar-100" +gtk-theme-name = "sugar-xo" gtk-icon-theme-name = "sugar" gtk-font-name = "Sans Serif 7" gtk-cursor-theme-name = "sugar" gtk-toolbar-style = GTK_TOOLBAR_ICONS gtk-icon-sizes = "gtk-large-toolbar=55,55" -gtk-cursor-blink-timeout = 3 diff --git a/data/sugar-72.gtkrc b/data/sugar.gtkrc index dd53b81..473396f 100644 --- a/data/sugar-72.gtkrc +++ b/data/sugar.gtkrc @@ -1,7 +1,6 @@ -gtk-theme-name = "sugar-72" +gtk-theme-name = "sugar" gtk-icon-theme-name = "sugar" gtk-font-name = "Sans Serif 10" gtk-cursor-theme-name = "sugar" gtk-toolbar-style = GTK_TOOLBAR_ICONS gtk-icon-sizes = "gtk-large-toolbar=40,40" -gtk-cursor-blink-timeout = 3 diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in deleted file mode 100644 index e704013..0000000 --- a/data/sugar.schemas.in +++ /dev/null @@ -1,160 +0,0 @@ -<?xml version="1.0"?> -<gconfschemafile> - <schemalist> - <schema> - <key>/schemas/desktop/sugar/user/nick</key> - <applyto>/desktop/sugar/user/nick</applyto> - <owner>sugar</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>User Name</short> - <long>User name that is used throughout the desktop.</long> - </locale> - </schema> - <schema> - <key>/schemas/desktop/sugar/user/color</key> - <applyto>/desktop/sugar/user/color</applyto> - <owner>sugar</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>User Color</short> - <long>Color for the XO icon that is used throughout the - desktop. The string is composed of the stroke color and fill - color, format is that of rbg colors. Example: #AC32FF,#9A5200 - </long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/sound/volume</key> - <applyto>/desktop/sugar/sound/volume</applyto> - <owner>sugar</owner> - <type>int</type> - <default>80</default> - <locale name="C"> - <short>Volume Level</short> - <long>Volume level for the sound device.</long> - </locale> - </schema> - <schema> - <key>/schemas/desktop/sugar/sound/mute</key> - <applyto>/desktop/sugar/sound/mute</applyto> - <owner>sugar</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Sound Muted</short> - <long>Setting for muting the sound device.</long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/backup_url</key> - <applyto>/desktop/sugar/backup_url</applyto> - <owner>sugar</owner> - <type>string</type> - <default></default> - <locale name="C"> - <short>Backup URL</short> - <long>Url where the backup is saved to.</long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/date/timezone</key> - <applyto>/desktop/sugar/date/timezone</applyto> - <owner>sugar</owner> - <type>string</type> - <default>"UTC"</default> - <locale name="C"> - <short>Timezone</short> - <long>Timezone setting for the system.</long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/desktop/favorites_layout</key> - <applyto>/desktop/sugar/desktop/favorites_layout</applyto> - <owner>sugar</owner> - <type>string</type> - <default>"ring-layout"</default> - <locale name="C"> - <short>Favorites Layout</short> - <long>Layout of the favorites view.</long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/frame/edge_delay</key> - <applyto>/desktop/sugar/frame/edge_delay</applyto> - <owner>sugar</owner> - <type>int</type> - <default>1000</default> - <locale name="C"> - <short>Edge Delay</short> - <long>Delay for the activation of the frame using the edges.</long> - </locale> - </schema> - <schema> - <key>/schemas/desktop/sugar/frame/corner_delay</key> - <applyto>/desktop/sugar/frame/corner_delay</applyto> - <owner>sugar</owner> - <type>int</type> - <default>0</default> - <locale name="C"> - <short>Corner Delay</short> - <long>Delay for the activation of the frame using the corners.</long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/collaboration/jabber_server</key> - <applyto>/desktop/sugar/collaboration/jabber_server</applyto> - <owner>sugar</owner> - <type>string</type> - <default>""</default> - <locale name="C"> - <short>Jabber Server</short> - <long>Url of the jabber server to use.</long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/power/automatic</key> - <applyto>/desktop/sugar/power/automatic</applyto> - <owner>sugar</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Power Automatic</short> - <long>Power Automatic.</long> - </locale> - </schema> - <schema> - <key>/schemas/desktop/sugar/power/extreme</key> - <applyto>/desktop/sugar/power/extreme</applyto> - <owner>sugar</owner> - <type>bool</type> - <default>false</default> - <locale name="C"> - <short>Power Extreme</short> - <long>Power Extreme. </long> - </locale> - </schema> - - <schema> - <key>/schemas/desktop/sugar/collaboration/publish_gadget</key> - <applyto>/desktop/sugar/collaboration/publish_gadget</applyto> - <owner>sugar</owner> - <type>bool</type> - <default>true</default> - <locale name="C"> - <short>Publish to Gadget</short> - <long>If TRUE, Sugar will make us searchable for the other users of the Jabber server.</long> - </locale> - </schema> - - </schemalist> -</gconfschemafile> diff --git a/extensions/Makefile.am b/extensions/Makefile.am deleted file mode 100644 index d4ab534..0000000 --- a/extensions/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = cpsection deviceicon globalkey diff --git a/extensions/cpsection/Makefile.am b/extensions/cpsection/Makefile.am deleted file mode 100644 index 0e69fd1..0000000 --- a/extensions/cpsection/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -SUBDIRS = aboutme aboutxo datetime frame language network power - -sugardir = $(pkgdatadir)/extensions/cpsection -sugar_PYTHON = __init__.py diff --git a/extensions/cpsection/aboutme/Makefile.am b/extensions/cpsection/aboutme/Makefile.am deleted file mode 100644 index 9ca91d2..0000000 --- a/extensions/cpsection/aboutme/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/aboutme - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/aboutme/Makefile.in b/extensions/cpsection/aboutme/Makefile.in deleted file mode 100644 index 0b6e7aa..0000000 --- a/extensions/cpsection/aboutme/Makefile.in +++ /dev/null @@ -1,394 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = extensions/cpsection/aboutme -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/aboutme -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/aboutme/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/aboutme/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/extensions/cpsection/aboutme/__init__.py b/extensions/cpsection/aboutme/__init__.py deleted file mode 100644 index 98843e1..0000000 --- a/extensions/cpsection/aboutme/__init__.py +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 gettext import gettext as _ -import gconf - -from sugar.graphics.xocolor import XoColor - -CLASS = 'AboutMe' -ICON = 'module-about_me' -TITLE = _('About Me') -client = gconf.client_get_default() -COLOR = XoColor(client.get_string('/desktop/sugar/user/color')) - - diff --git a/extensions/cpsection/aboutxo/Makefile.am b/extensions/cpsection/aboutxo/Makefile.am deleted file mode 100644 index 3f71af0..0000000 --- a/extensions/cpsection/aboutxo/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/aboutxo - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/aboutxo/Makefile.in b/extensions/cpsection/aboutxo/Makefile.in deleted file mode 100644 index 3857790..0000000 --- a/extensions/cpsection/aboutxo/Makefile.in +++ /dev/null @@ -1,394 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = extensions/cpsection/aboutxo -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/aboutxo -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/aboutxo/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/aboutxo/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/extensions/cpsection/aboutxo/__init__.py b/extensions/cpsection/aboutxo/__init__.py deleted file mode 100644 index 4dc2cb2..0000000 --- a/extensions/cpsection/aboutxo/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 gettext import gettext as _ - -CLASS = 'AboutXO' -ICON = 'module-about_my_xo' -TITLE = _('About my XO') - diff --git a/extensions/cpsection/datetime/Makefile.am b/extensions/cpsection/datetime/Makefile.am deleted file mode 100644 index b5b518e..0000000 --- a/extensions/cpsection/datetime/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/datetime - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/datetime/__init__.py b/extensions/cpsection/datetime/__init__.py deleted file mode 100644 index fc9be45..0000000 --- a/extensions/cpsection/datetime/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 gettext import gettext as _ - -CLASS = 'TimeZone' -ICON = 'module-date_and_time' -TITLE = _('Date & Time') diff --git a/extensions/cpsection/frame/Makefile.am b/extensions/cpsection/frame/Makefile.am deleted file mode 100644 index 1e09c04..0000000 --- a/extensions/cpsection/frame/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/frame - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/frame/__init__.py b/extensions/cpsection/frame/__init__.py deleted file mode 100644 index a93f9c7..0000000 --- a/extensions/cpsection/frame/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 gettext import gettext as _ - -CLASS = 'Frame' -ICON = 'module-frame' -TITLE = _('Frame') diff --git a/extensions/cpsection/language/Makefile.am b/extensions/cpsection/language/Makefile.am deleted file mode 100644 index 209fc32..0000000 --- a/extensions/cpsection/language/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/language - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/language/Makefile.in b/extensions/cpsection/language/Makefile.in deleted file mode 100644 index cc0b03b..0000000 --- a/extensions/cpsection/language/Makefile.in +++ /dev/null @@ -1,394 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = extensions/cpsection/language -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/language -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/language/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/language/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/extensions/cpsection/language/__init__.py b/extensions/cpsection/language/__init__.py deleted file mode 100644 index a8f9f08..0000000 --- a/extensions/cpsection/language/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 gettext import gettext as _ - -CLASS = 'Language' -ICON = 'module-language' -TITLE = _('Language') - diff --git a/extensions/cpsection/language/view.py b/extensions/cpsection/language/view.py deleted file mode 100644 index 12fe0c9..0000000 --- a/extensions/cpsection/language/view.py +++ /dev/null @@ -1,237 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 - -import gtk -import gobject -import gettext - -from sugar.graphics import style -from sugar.graphics.icon import Icon - -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert - -_translate_language = lambda msg: gettext.dgettext('iso_639', msg) -_translate_country = lambda msg: gettext.dgettext('iso_3166', msg) - -CLASS = 'Language' -ICON = 'module-language' -TITLE = gettext.gettext('Language') - -class Language(SectionView): - def __init__(self, model, alerts): - SectionView.__init__(self) - - self._model = model - self.restart_alerts = alerts - self._lang_sid = 0 - self._selected_lang_count = 0 - self._labels = [] - self._stores = [] - self._comboboxes = [] - self._add_remove_boxes = [] - self._changed = False - self._cursor_change_handler = None - - self._available_locales = self._model.read_all_languages() - self._selected_locales = self._model.get_languages() - - self.set_border_width(style.DEFAULT_SPACING * 2) - self.set_spacing(style.DEFAULT_SPACING) - - self._table = gtk.Table(rows=1, columns=3, homogeneous=False) - self.pack_start(self._table, False) - self._table.show() - - self._lang_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING) - self.pack_start(self._lang_alert_box, False) - - self._lang_alert = InlineAlert() - self._lang_alert_box.pack_start(self._lang_alert) - if 'lang' in self.restart_alerts: - self._lang_alert.props.msg = self.restart_msg - self._lang_alert.show() - self._lang_alert_box.show() - - self.setup() - - def _add_row(self, locale_code=None): - '''Adds a row to the table''' - - self._selected_lang_count += 1 - - self._table.resize(self._selected_lang_count, 3) - - label = gtk.Label(str=str(self._selected_lang_count)) - self._labels.append(label) - self._attach_to_table(label, 0, 1, padding=1) - label.show() - - - store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - for language, country, code in self._available_locales: - description = '%s (%s)' % (_translate_language(language), \ - _translate_country(country)) - store.append([code, description]) - - combobox = gtk.ComboBox(model=store) - cell = gtk.CellRendererText() - combobox.pack_start(cell) - combobox.add_attribute(cell, 'text', 1) - - if locale_code: - for row in store: - lang = locale_code.split('.')[0] - lang_column = row[0].split('.')[0] - if lang in lang_column: - combobox.set_active_iter(row.iter) - break - else: - combobox.set_active(1) - - combobox.connect('changed', self.__combobox_changed_cb) - - self._stores.append(store) - self._comboboxes.append(combobox) - self._attach_to_table(combobox, 1, 2, yoptions=gtk.SHRINK) - - add_remove_box = self._create_add_remove_box() - self._add_remove_boxes.append(add_remove_box) - self._attach_to_table(add_remove_box, 2, 3) - - add_remove_box.show_all() - - if self._selected_lang_count > 1: - previous_add_removes = self._add_remove_boxes[-2] - previous_add_removes.hide_all() - - combobox.show() - - def _attach_to_table(self, widget, row, column, padding=20, \ - yoptions=gtk.FILL): - self._table.attach(widget, row, column, \ - self._selected_lang_count - 1, self._selected_lang_count, \ - xoptions=gtk.FILL, yoptions=yoptions, xpadding=padding, \ - ypadding=padding) - - def _delete_last_row(self): - '''Deletes the last row of the table''' - - self._selected_lang_count -= 1 - - label, add_remove_box, combobox, store = self._get_last_row() - - label.destroy() - add_remove_box.destroy() - combobox.destroy() - del(store) - - self._table.resize(self._selected_lang_count, 3) - - self._add_remove_boxes[-1].show_all() - - def _get_last_row(self): - label = self._labels.pop() - add_remove_box = self._add_remove_boxes.pop() - combobox = self._comboboxes.pop() - store = self._stores.pop() - - return label, add_remove_box, combobox, store - - def setup(self): - for locale in self._selected_locales: - self._add_row(locale_code=locale) - - def undo(self): - self._model.undo() - self._lang_alert.hide() - - def _create_add_remove_box(self): - '''Creates gtk.Hbox with add/remove buttons''' - add_icon = Icon(icon_name='list-add') - - add_button = gtk.Button() - add_button.set_image(add_icon) - add_button.connect('clicked', - self.__add_button_clicked_cb) - - remove_icon = Icon(icon_name='list-remove') - remove_button = gtk.Button() - remove_button.set_image(remove_icon) - remove_button.connect('clicked', - self.__remove_button_clicked_cb) - - if self._selected_lang_count == 1: - remove_button.set_sensitive(False) - - add_remove_box = gtk.HButtonBox() - add_remove_box.set_layout(gtk.BUTTONBOX_START) - add_remove_box.set_spacing(10) - add_remove_box.pack_start(add_button) - add_remove_box.pack_start(remove_button) - - return add_remove_box - - def __add_button_clicked_cb(self, button): - self._add_row() - self._check_change() - - def __remove_button_clicked_cb(self, button): - self._delete_last_row() - self._check_change() - - def __combobox_changed_cb(self, button): - self._check_change() - - def _check_change(self): - selected_langs = self._get_selected_langs() - self._changed = (selected_langs != self._selected_locales) - - if self._changed == False: - # The user reverted back to the original config - self.needs_restart = False - if 'lang' in self.restart_alerts: - self.restart_alerts.remove('lang') - self._lang_alert.hide() - if self._lang_sid: - gobject.source_remove(self._lang_sid) - self._model.undo() - return False - - if self._lang_sid: - gobject.source_remove(self._lang_sid) - self._lang_sid = gobject.timeout_add(self._APPLY_TIMEOUT, - self.__lang_timeout_cb, - selected_langs) - - def _get_selected_langs(self): - new_codes = [] - for combobox in self._comboboxes: - iter = combobox.get_active_iter() - model = combobox.get_model() - lang_code = model.get(iter, 0)[0] - new_codes.append(lang_code) - - return new_codes - - def __lang_timeout_cb(self, codes): - self._lang_sid = 0 - self._model.set_languages(codes) - self.restart_alerts.append('lang') - self.needs_restart = True - self._lang_alert.props.msg = self.restart_msg - self._lang_alert.show() - return False diff --git a/extensions/cpsection/network/Makefile.am b/extensions/cpsection/network/Makefile.am deleted file mode 100644 index 35fd27c..0000000 --- a/extensions/cpsection/network/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/network - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/network/Makefile.in b/extensions/cpsection/network/Makefile.in deleted file mode 100644 index da8149c..0000000 --- a/extensions/cpsection/network/Makefile.in +++ /dev/null @@ -1,394 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = extensions/cpsection/network -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/network -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/network/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/network/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/extensions/cpsection/network/model.py b/extensions/cpsection/network/model.py deleted file mode 100644 index bfd008a..0000000 --- a/extensions/cpsection/network/model.py +++ /dev/null @@ -1,123 +0,0 @@ -# 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 -# - -import dbus -from gettext import gettext as _ -import gconf - -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' - -KEYWORDS = ['network', 'jabber', 'radio', 'server'] - -class ReadError(Exception): - def __init__(self, value): - self.value = value - def __str__(self): - return repr(self.value) - -def get_jabber(): - client = gconf.client_get_default() - return client.get_string('/desktop/sugar/collaboration/jabber_server') - -def print_jabber(): - print get_jabber() - -def set_jabber(server): - """Set the jabber server - server : e.g. 'olpc.collabora.co.uk' - """ - client = gconf.client_get_default() - client.set_string('/desktop/sugar/collaboration/jabber_server', server) - return 1 - -def get_radio(): - bus = dbus.SystemBus() - try: - obj = bus.get_object(_NM_SERVICE, _NM_PATH) - nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - except dbus.DBusException: - raise ReadError('%s service not available', _NM_SERVICE) - - state = nm_props.Get(_NM_IFACE, 'WirelessEnabled') - if state in (0, 1): - return state - else: - raise ReadError(_('State is unknown.')) - -def print_radio(): - print ('off', 'on')[get_radio()] - -def set_radio(state): - """Turn Radio 'on' or 'off' - state : 'on/off' - """ - if state == 'on' or state == 1: - bus = dbus.SystemBus() - try: - obj = bus.get_object(_NM_SERVICE, _NM_PATH) - nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - except dbus.DBusException: - raise ReadError('%s service not available', _NM_SERVICE) - nm_props.Set(_NM_IFACE, 'WirelessEnabled', True) - elif state == 'off' or state == 0: - bus = dbus.SystemBus() - try: - obj = bus.get_object(_NM_SERVICE, _NM_PATH) - nm_props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - except dbus.DBusException: - raise ReadError('%s service not available', _NM_SERVICE) - nm_props.Set(_NM_IFACE, 'WirelessEnabled', False) - else: - raise ValueError(_("Error in specified radio argument use on/off.")) - - return 0 - -def clear_registration(): - """Clear the registration with the schoolserver - """ - client = gconf.client_get_default() - client.set_string('/desktop/sugar/backup_url', '') - return 1 - -def clear_networks(): - """Clear saved passwords and network configurations. - """ - pass - -def get_publish_information(): - client = gconf.client_get_default() - publish = client.get_bool('/desktop/sugar/collaboration/publish_gadget') - return publish - -def print_publish_information(): - print get_publish_information() - -def set_publish_information(value): - """ If set to true, Sugar will make you searchable for - the other users of the Jabber server. - value: 0/1 - """ - try: - value = (False, True)[int(value)] - except: - raise ValueError(_("Error in specified argument use 0/1.")) - - client = gconf.client_get_default() - client.set_bool('/desktop/sugar/collaboration/publish_gadget', value) - return 0 diff --git a/extensions/cpsection/power/Makefile.am b/extensions/cpsection/power/Makefile.am deleted file mode 100644 index 325260c..0000000 --- a/extensions/cpsection/power/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/cpsection/power - -sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py diff --git a/extensions/cpsection/power/__init__.py b/extensions/cpsection/power/__init__.py deleted file mode 100644 index 8b2e85f..0000000 --- a/extensions/cpsection/power/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2008, OLPC -# -# 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 gettext import gettext as _ - -CLASS = 'Power' -ICON = 'module-power' -TITLE = _('Power') -KEYWORDS = ['automatic', 'extreme', 'power', 'suspend', 'battery'] - diff --git a/extensions/deviceicon/Makefile.am b/extensions/deviceicon/Makefile.am deleted file mode 100644 index 8a2e765..0000000 --- a/extensions/deviceicon/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/deviceicon - -sugar_PYTHON = \ - __init__.py \ - battery.py \ - network.py \ - speaker.py \ - volume.py diff --git a/extensions/deviceicon/Makefile.in b/extensions/deviceicon/Makefile.in deleted file mode 100644 index 56b6554..0000000 --- a/extensions/deviceicon/Makefile.in +++ /dev/null @@ -1,396 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = extensions/deviceicon -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/deviceicon -sugar_PYTHON = \ - __init__.py \ - battery.py \ - network.py \ - speaker.py \ - volume.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/deviceicon/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/deviceicon/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/extensions/deviceicon/__init__.py b/extensions/deviceicon/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/extensions/deviceicon/__init__.py +++ /dev/null diff --git a/extensions/deviceicon/battery.py b/extensions/deviceicon/battery.py deleted file mode 100644 index c25d124..0000000 --- a/extensions/deviceicon/battery.py +++ /dev/null @@ -1,252 +0,0 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. -# -# 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 - -import logging -from gettext import gettext as _ -import gconf - -import gobject -import gtk -import dbus - -from sugar.graphics import style -from sugar.graphics.icon import get_icon_state -from sugar.graphics.tray import TrayIcon -from sugar.graphics.palette import Palette -from sugar.graphics.xocolor import XoColor - -from jarabe.frame.frameinvoker import FrameWidgetInvoker - -_ICON_NAME = 'battery' - -_STATUS_CHARGING = 0 -_STATUS_DISCHARGING = 1 -_STATUS_FULLY_CHARGED = 2 -_STATUS_NOT_PRESENT = 3 - -_LEVEL_PROP = 'battery.charge_level.percentage' -_CHARGING_PROP = 'battery.rechargeable.is_charging' -_DISCHARGING_PROP = 'battery.rechargeable.is_discharging' -_PRESENT_PROP = 'battery.present' - -class DeviceView(TrayIcon): - - FRAME_POSITION_RELATIVE = 1000 - - def __init__(self, udi): - client = gconf.client_get_default() - self._color = XoColor(client.get_string('/desktop/sugar/user/color')) - - TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color) - - self._model = DeviceModel(udi) - self.palette = BatteryPalette(_('My Battery')) - self.set_palette(self.palette) - self.palette.props.invoker = FrameWidgetInvoker(self) - self.palette.set_group_id('frame') - - self._model.connect('notify::level', - self._battery_status_changed_cb) - self._model.connect('notify::charging', - self._battery_status_changed_cb) - self._model.connect('notify::discharging', - self._battery_status_changed_cb) - self._model.connect('notify::present', - self._battery_status_changed_cb) - self._update_info() - - def _update_info(self): - name = _ICON_NAME - current_level = self._model.props.level - xo_color = self._color - badge_name = None - - if not self._model.props.present: - status = _STATUS_NOT_PRESENT - badge_name = None - xo_color = XoColor('%s,%s' % (style.COLOR_WHITE.get_svg(), - style.COLOR_WHITE.get_svg())) - elif self._model.props.charging: - status = _STATUS_CHARGING - name += '-charging' - xo_color = XoColor('%s,%s' % (style.COLOR_WHITE.get_svg(), - style.COLOR_WHITE.get_svg())) - elif self._model.props.discharging: - status = _STATUS_DISCHARGING - if current_level <= 15: - badge_name = 'emblem-warning' - else: - status = _STATUS_FULLY_CHARGED - - self.icon.props.icon_name = get_icon_state(name, current_level, step=-5) - self.icon.props.xo_color = xo_color - self.icon.props.badge_name = badge_name - - self.palette.set_level(current_level) - self.palette.set_status(status) - - def _battery_status_changed_cb(self, pspec, param): - self._update_info() - -class BatteryPalette(Palette): - - def __init__(self, primary_text): - Palette.__init__(self, primary_text) - - self._level = 0 - self._progress_bar = gtk.ProgressBar() - self._progress_bar.set_size_request( - style.zoom(style.GRID_CELL_SIZE * 4), -1) - self._progress_bar.show() - self._status_label = gtk.Label() - self._status_label.show() - - vbox = gtk.VBox() - vbox.pack_start(self._progress_bar) - vbox.pack_start(self._status_label) - vbox.show() - - self._progress_widget = vbox - self.set_content(self._progress_widget) - - def set_level(self, percent): - self._level = percent - fraction = percent / 100.0 - self._progress_bar.set_fraction(fraction) - - def set_status(self, status): - current_level = self._level - secondary_text = '' - status_text = '%s%%' % current_level - - progress_widget = self._progress_widget - if status == _STATUS_NOT_PRESENT: - secondary_text = _('Removed') - progress_widget = None - elif status == _STATUS_CHARGING: - secondary_text = _('Charging') - elif status == _STATUS_DISCHARGING: - if current_level <= 15: - secondary_text = _('Very little power remaining') - else: - #TODO: make this less of an wild/educated guess - minutes_remaining = int(current_level / 0.59) - remaining_hourpart = minutes_remaining / 60 - remaining_minpart = minutes_remaining % 60 - secondary_text = _('%(hour)d:%(min).2d remaining' - % { 'hour': remaining_hourpart, - 'min': remaining_minpart}) - else: - secondary_text = _('Charged') - self.set_content(progress_widget) - - self.props.secondary_text = secondary_text - self._status_label.set_text(status_text) - -class DeviceModel(gobject.GObject): - __gproperties__ = { - 'level' : (int, None, None, 0, 100, 0, - gobject.PARAM_READABLE), - 'charging' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'discharging' : (bool, None, None, False, - gobject.PARAM_READABLE), - 'present' : (bool, None, None, False, - gobject.PARAM_READABLE) - } - - def __init__(self, udi): - gobject.GObject.__init__(self) - - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - proxy = bus.get_object('org.freedesktop.Hal', udi, - follow_name_owner_changes=True) - self._battery = dbus.Interface(proxy, 'org.freedesktop.Hal.Device') - bus.add_signal_receiver(self._battery_changed, - 'PropertyModified', - 'org.freedesktop.Hal.Device', - 'org.freedesktop.Hal', - udi) - - self._level = self._get_level() - self._charging = self._get_charging() - self._discharging = self._get_discharging() - self._present = self._get_present() - - def _get_level(self): - try: - return self._battery.GetProperty(_LEVEL_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _LEVEL_PROP) - return 0 - - def _get_charging(self): - try: - return self._battery.GetProperty(_CHARGING_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _CHARGING_PROP) - return False - - def _get_discharging(self): - try: - return self._battery.GetProperty(_DISCHARGING_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _DISCHARGING_PROP) - return False - - def _get_present(self): - try: - return self._battery.GetProperty(_PRESENT_PROP) - except dbus.DBusException: - logging.error('Cannot access %s' % _PRESENT_PROP) - return False - - def do_get_property(self, pspec): - if pspec.name == 'level': - return self._level - if pspec.name == 'charging': - return self._charging - if pspec.name == 'discharging': - return self._discharging - if pspec.name == 'present': - return self._present - - def get_type(self): - return 'battery' - - def _battery_changed(self, num_changes, changes_list): - for change in changes_list: - if change[0] == _LEVEL_PROP: - self._level = self._get_level() - self.notify('level') - elif change[0] == _CHARGING_PROP: - self._charging = self._get_charging() - self.notify('charging') - elif change[0] == _DISCHARGING_PROP: - self._discharging = self._get_discharging() - self.notify('discharging') - elif change[0] == _PRESENT_PROP: - self._present = self._get_present() - self.notify('present') - -def setup(tray): - bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) - proxy = bus.get_object('org.freedesktop.Hal', - '/org/freedesktop/Hal/Manager') - hal_manager = dbus.Interface(proxy, 'org.freedesktop.Hal.Manager') - - for udi in hal_manager.FindDeviceByCapability('battery'): - tray.add_device(DeviceView(udi)) diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py deleted file mode 100644 index e1b784c..0000000 --- a/extensions/deviceicon/network.py +++ /dev/null @@ -1,377 +0,0 @@ -# -# 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 gettext import gettext as _ -import logging -import sha - -import gtk -import gobject -import dbus - -from sugar.graphics.icon import get_icon_state -from sugar.graphics import style -from sugar.graphics.palette import Palette -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics import xocolor - -from jarabe.model import network -from jarabe.frame.frameinvoker import FrameWidgetInvoker -from jarabe.view.pulsingicon import PulsingIcon - -_ICON_NAME = 'network-wireless' - -IP_ADDRESS_TEXT_TEMPLATE = _("IP address: %s") - -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' -_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - -_NM_DEVICE_STATE_UNKNOWN = 0 -_NM_DEVICE_STATE_UNMANAGED = 1 -_NM_DEVICE_STATE_UNAVAILABLE = 2 -_NM_DEVICE_STATE_DISCONNECTED = 3 -_NM_DEVICE_STATE_PREPARE = 4 -_NM_DEVICE_STATE_CONFIG = 5 -_NM_DEVICE_STATE_NEED_AUTH = 6 -_NM_DEVICE_STATE_IP_CONFIG = 7 -_NM_DEVICE_STATE_ACTIVATED = 8 -_NM_DEVICE_STATE_FAILED = 9 - -def frequency_to_channel(frequency): - ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4, - 2432: 5, 2437: 6, 2442: 7, 2447: 8, - 2452: 9, 2457: 10, 2462: 11, 2467: 12, - 2472: 13} - return ftoc[frequency] - -class WirelessPalette(Palette): - __gtype_name__ = 'SugarWirelessPalette' - - __gsignals__ = { - 'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) - } - - def __init__(self, primary_text): - Palette.__init__(self, label=primary_text) - - self._disconnect_item = None - - self._channel_label = gtk.Label() - self._channel_label.props.xalign = 0.0 - self._channel_label.show() - - self._ip_address_label = gtk.Label() - - self._info = gtk.VBox() - - def _padded(child, xalign=0, yalign=0.5): - padder = gtk.Alignment(xalign=xalign, yalign=yalign, - xscale=1, yscale=0.33) - padder.set_padding(style.DEFAULT_SPACING, - style.DEFAULT_SPACING, - style.DEFAULT_SPACING, - style.DEFAULT_SPACING) - padder.add(child) - return padder - - self._info.pack_start(_padded(self._channel_label)) - self._info.pack_start(_padded(self._ip_address_label)) - self._info.show_all() - - self._disconnect_item = gtk.MenuItem(_('Disconnect...')) - self._disconnect_item.connect('activate', self.__disconnect_activate_cb) - self.menu.append(self._disconnect_item) - - self.set_disconnected() - - def set_connecting(self): - self.props.secondary_text = _('Connecting...') - - def set_connected(self, frequency, iaddress): - self.set_content(self._info) - self.props.secondary_text = _('Connected') - self._set_channel(frequency) - self._set_ip_address(iaddress) - self._disconnect_item.show() - - def set_disconnected(self): - self.props.primary_text = '' - self.props.secondary_text = _('Not connected') - self.set_content(None) - self._disconnect_item.hide() - - def __disconnect_activate_cb(self, menuitem): - self.emit('deactivate-connection') - - def _inet_ntoa(self, iaddress): - address = ['%s' % ((iaddress >> i) % 256) for i in [0, 8, 16, 24]] - return ".".join(address) - - def _set_channel(self, frequency): - try: - channel = frequency_to_channel(frequency) - except KeyError: - channel = 0 - self._channel_label.set_text("%s: %d" % (_("Channel"), channel)) - - def _set_ip_address(self, ip_address): - if ip_address is not None: - ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % \ - self._inet_ntoa(ip_address) - else: - ip_address_text = "" - self._ip_address_label.set_text(ip_address_text) - - -class WirelessDeviceView(ToolButton): - - FRAME_POSITION_RELATIVE = 300 - - def __init__(self, device): - ToolButton.__init__(self) - - self._bus = dbus.SystemBus() - self._device = device - self._flags = 0 - self._name = '' - self._strength = 0 - self._frequency = 0 - self._device_state = None - self._color = None - self._active_ap_op = None - - self._icon = PulsingIcon() - self._icon.props.icon_name = get_icon_state(_ICON_NAME, 0) - self._inactive_color = xocolor.XoColor( \ - "%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), - style.COLOR_TRANSPARENT.get_svg())) - self._icon.props.pulse_color = self._inactive_color - self._icon.props.base_color = self._inactive_color - - self.set_icon_widget(self._icon) - self._icon.show() - - self._palette = WirelessPalette(self._name) - self._palette.connect('deactivate-connection', - self.__deactivate_connection) - self.set_palette(self._palette) - self._palette.props.invoker = FrameWidgetInvoker(self) - self._palette.set_group_id('frame') - - self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', - reply_handler=self.__get_active_ap_reply_cb, - error_handler=self.__get_active_ap_error_cb) - - self._bus.add_signal_receiver(self.__state_changed_cb, - signal_name='StateChanged', - path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) - - def disconnect(self): - self._bus.remove_signal_receiver(self.__state_changed_cb, - signal_name='StateChanged', - path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) - - def __get_active_ap_reply_cb(self, active_ap_op): - if self._active_ap_op != active_ap_op: - if self._active_ap_op is not None: - self._bus.remove_signal_receiver( - self.__ap_properties_changed_cb, - signal_name='PropertiesChanged', - path=self._active_ap_op, - dbus_interface=_NM_ACCESSPOINT_IFACE) - if active_ap_op == '/': - self._active_ap_op = None - return - self._active_ap_op = active_ap_op - active_ap = self._bus.get_object(_NM_SERVICE, active_ap_op) - props = dbus.Interface(active_ap, 'org.freedesktop.DBus.Properties') - - props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, - reply_handler=self.__get_all_props_reply_cb, - error_handler=self.__get_all_props_error_cb) - - self._bus.add_signal_receiver(self.__ap_properties_changed_cb, - signal_name='PropertiesChanged', - path=self._active_ap_op, - dbus_interface=_NM_ACCESSPOINT_IFACE) - - def __get_active_ap_error_cb(self, err): - logging.debug('Error getting the active access point: %s', err) - - def __state_changed_cb(self, new_state, old_state, reason): - self._device_state = new_state - self._update_state() - - self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', - reply_handler=self.__get_active_ap_reply_cb, - error_handler=self.__get_active_ap_error_cb) - - def __ap_properties_changed_cb(self, properties): - self._update_properties(properties) - - def _update_properties(self, properties): - if 'Ssid' in properties: - self._name = properties['Ssid'] - if 'Strength' in properties: - self._strength = properties['Strength'] - if 'Flags' in properties: - self._flags = properties['Flags'] - if 'Frequency' in properties: - self._frequency = properties['Frequency'] - - sh = sha.new() - data = self._name + hex(self._flags) - sh.update(data) - h = hash(sh.digest()) - idx = h % len(xocolor.colors) - - self._color = xocolor.XoColor('%s,%s' % (xocolor.colors[idx][0], - xocolor.colors[idx][1])) - self._update() - - def __get_all_props_reply_cb(self, properties): - self._update_properties(properties) - - def __get_all_props_error_cb(self, err): - logging.debug('Error getting the access point properties: %s', err) - - def _update(self): - if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: - self._icon.props.badge_name = "emblem-locked" - else: - self._icon.props.badge_name = None - - self._palette.props.primary_text = self._name - - self._update_state() - self._update_color() - - def _update_state(self): - if self._active_ap_op is not None: - state = self._device_state - else: - state = network.DEVICE_STATE_UNKNOWN - - if state == network.DEVICE_STATE_ACTIVATED: - icon_name = '%s-connected' % _ICON_NAME - else: - icon_name = _ICON_NAME - - icon_name = get_icon_state(icon_name, self._strength) - if icon_name: - self._icon.props.icon_name = icon_name - - if state == network.DEVICE_STATE_PREPARE or \ - state == network.DEVICE_STATE_CONFIG or \ - state == network.DEVICE_STATE_NEED_AUTH or \ - state == network.DEVICE_STATE_IP_CONFIG: - self._palette.set_connecting() - self._icon.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: - props = dbus.Interface(self._device, - 'org.freedesktop.DBus.Properties') - address = props.Get(_NM_DEVICE_IFACE, 'Ip4Address') - self._palette.set_connected(self._frequency, address) - self._icon.props.pulsing = False - else: - self._palette.set_disconnected() - self._icon.props.pulsing = False - self._icon.props.base_color = self._inactive_color - self._icon.props.badge_name = None - self._name = '' - - def _update_color(self): - self._icon.props.base_color = self._color - - def __deactivate_connection(self, palette, data=None): - if self._active_ap_op is not None: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - netmgr_props = dbus.Interface( - netmgr, 'org.freedesktop.DBus.Properties') - active_connections_o = netmgr_props.Get(_NM_IFACE, - 'ActiveConnections') - - for conn_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - ap_op = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') - if ap_op == self._active_ap_op: - netmgr.DeactivateConnection(conn_o) - break - -class NetworkManagerObserver(object): - def __init__(self, tray): - self._bus = dbus.SystemBus() - self._devices = {} - self._netmgr = None - self._tray = tray - - try: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - self._netmgr = dbus.Interface(obj, _NM_IFACE) - except dbus.DBusException: - logging.debug('%s service not available', _NM_SERVICE) - return - - self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb, - error_handler=self.__get_devices_error_cb) - - self._bus.add_signal_receiver(self.__device_added_cb, - signal_name='DeviceAdded', - dbus_interface=_NM_IFACE) - self._bus.add_signal_receiver(self.__device_removed_cb, - signal_name='DeviceRemoved', - dbus_interface=_NM_IFACE) - - def __get_devices_reply_cb(self, devices): - for device_op in devices: - self._check_device(device_op) - - def __get_devices_error_cb(self, err): - logging.error('Failed to get devices: %s', err) - - def _check_device(self, device_op): - nm_device = self._bus.get_object(_NM_SERVICE, device_op) - props = dbus.Interface(nm_device, 'org.freedesktop.DBus.Properties') - - device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if device_type == network.DEVICE_TYPE_802_11_WIRELESS: - device = WirelessDeviceView(nm_device) - self._devices[device_op] = device - self._tray.add_device(device) - - def __device_added_cb(self, device_op): - self._check_device(device_op) - - def __device_removed_cb(self, device_op): - if device_op in self._devices: - device = self._devices[device_op] - device.disconnect() - self._tray.remove_device(device) - del self._devices[device_op] - -def setup(tray): - device_observer = NetworkManagerObserver(tray) diff --git a/extensions/deviceicon/volume.py b/extensions/deviceicon/volume.py deleted file mode 100644 index 7db84ad..0000000 --- a/extensions/deviceicon/volume.py +++ /dev/null @@ -1,111 +0,0 @@ -# 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 - -import os -import statvfs -from gettext import gettext as _ - -import gtk - -from sugar.graphics.tray import TrayIcon -from sugar.graphics.palette import Palette -from sugar.graphics.menuitem import MenuItem -from sugar.graphics.icon import Icon - -from jarabe.model import volume - -_icons = {} - -class DeviceView(TrayIcon): - - FRAME_POSITION_RELATIVE = 800 - - def __init__(self, model): - TrayIcon.__init__(self, icon_name=model.icon_name, - xo_color=model.icon_color) - self._model = model - - def create_palette(self): - return VolumePalette(self._model) - -class VolumePalette(Palette): - def __init__(self, model): - Palette.__init__(self, label=model.name, - secondary_text=model.mount_point) - self._model = model - - vbox = gtk.VBox() - self.set_content(vbox) - vbox.show() - - self._progress_bar = gtk.ProgressBar() - vbox.add(self._progress_bar) - self._progress_bar.show() - - self._free_space_label = gtk.Label() - self._free_space_label.set_alignment(0.5, 0.5) - vbox.add(self._free_space_label) - self._free_space_label.show() - - self.connect('popup', self.__popup_cb) - - menu_item = MenuItem(_('Unmount')) - - icon = Icon(icon_name='media-eject', icon_size=gtk.ICON_SIZE_MENU) - menu_item.set_image(icon) - icon.show() - - menu_item.connect('activate', self.__unmount_activate_cb) - self.menu.append(menu_item) - menu_item.show() - - def __unmount_activate_cb(self, menu_item): - self._model.unmount() - - def __popup_cb(self, palette): - stat = os.statvfs(self._model.mount_point) - free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] - total_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BLOCKS] - - fraction = (total_space - free_space) / float(total_space) - self._progress_bar.props.fraction = fraction - self._free_space_label.props.label = _('%(free_space)d MB Free') % \ - {'free_space': free_space / (1024 * 1024)} - -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(vol, tray): - icon = DeviceView(vol) - _icons[vol] = icon - tray.add_device(icon) - -def _remove_device(vol, tray): - icon = _icons[vol] - tray.remove_device(icon) - del _icons[vol] diff --git a/extensions/globalkey/Makefile.am b/extensions/globalkey/Makefile.am deleted file mode 100644 index 69afac2..0000000 --- a/extensions/globalkey/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -sugardir = $(pkgdatadir)/extensions/globalkey - -sugar_PYTHON = \ - __init__.py \ - screenshot.py \ - viewsource.py diff --git a/extensions/globalkey/__init__.py b/extensions/globalkey/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/extensions/globalkey/__init__.py +++ /dev/null diff --git a/extensions/globalkey/screenshot.py b/extensions/globalkey/screenshot.py deleted file mode 100644 index 1304eae..0000000 --- a/extensions/globalkey/screenshot.py +++ /dev/null @@ -1,72 +0,0 @@ -# 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 - -import os -import tempfile -import time -from gettext import gettext as _ - -import gtk -import gconf -import dbus - -from sugar.datastore import datastore -from sugar.graphics import style - -BOUND_KEYS = ['<alt>1'] - -def handle_key_press(key): - file_path = os.path.join(tempfile.gettempdir(), '%i' % time.time()) - - window = gtk.gdk.get_default_root_window() - width, height = window.get_size() - x_orig, y_orig = window.get_origin() - - screenshot = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=False, - bits_per_sample=8, width=width, - height=height) - screenshot.get_from_drawable(window, window.get_colormap(), x_orig, - y_orig, 0, 0, width, height) - screenshot.save(file_path, "png") - - client = gconf.client_get_default() - color = client.get_string('/desktop/sugar/user/color') - - jobject = datastore.create() - try: - jobject.metadata['title'] = _('Screenshot') - jobject.metadata['keep'] = '0' - jobject.metadata['buddies'] = '' - jobject.metadata['preview'] = _get_preview_data(screenshot) - jobject.metadata['icon-color'] = color - jobject.metadata['mime_type'] = 'image/png' - jobject.file_path = file_path - datastore.write(jobject, transfer_ownership=True) - finally: - jobject.destroy() - del jobject - -def _get_preview_data(screenshot): - preview = screenshot.scale_simple(style.zoom(300), style.zoom(225), - gtk.gdk.INTERP_BILINEAR) - preview_data = [] - def save_func(buf, data): - data.append(buf) - - preview.save_to_callback(save_func, 'png', user_data=preview_data) - - return dbus.ByteArray(''.join(preview_data)) - diff --git a/extensions/globalkey/viewsource.py b/extensions/globalkey/viewsource.py deleted file mode 100644 index 7a6e37d..0000000 --- a/extensions/globalkey/viewsource.py +++ /dev/null @@ -1,363 +0,0 @@ -# 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 - -import os -import logging -import traceback -from gettext import gettext as _ - -import gobject -import pango -import gtk -import gtksourceview2 -import dbus - -from sugar.graphics import style -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.radiotoolbutton import RadioToolButton -from sugar import mime - -from jarabe.model import shell - -BOUND_KEYS = ['0xEC', '<alt><shift>v'] - -_SOURCE_FONT = pango.FontDescription('Monospace %d' % style.zoom(6)) - -_logger = logging.getLogger('ViewSource') -map_activity_to_window = {} - -def handle_key_press(key): - shell_model = shell.get_model() - activity = shell_model.get_active_activity() - - service = activity.get_service() - if service is not None: - try: - service.HandleViewSource() - return - except dbus.DBusException, e: - expected_exceptions = ['org.freedesktop.DBus.Error.UnknownMethod', - 'org.freedesktop.DBus.Python.NotImplementedError'] - if e.get_dbus_name() not in expected_exceptions: - logging.error(traceback.format_exc()) - except Exception: - logging.error(traceback.format_exc()) - - window_xid = activity.get_xid() - if window_xid is None: - _logger.error('Activity without a window xid') - return - - if window_xid in map_activity_to_window: - _logger.debug('Viewsource window already open for %s %s' % \ - (window_xid, bundle_path)) - return - - bundle_path = activity.get_bundle_path() - - document_path = None - if service is not None: - try: - document_path = service.GetDocumentPath() - except dbus.DBusException, e: - expected_exceptions = ['org.freedesktop.DBus.Error.UnknownMethod', - 'org.freedesktop.DBus.Python.NotImplementedError'] - if e.get_dbus_name() not in expected_exceptions: - logging.error(traceback.format_exc()) - except Exception: - logging.error(traceback.format_exc()) - - if bundle_path is None and document_path is None: - _logger.debug('Activity without bundle_path nor document_path') - return - - view_source = ViewSource(window_xid, bundle_path, document_path, - activity.get_title()) - map_activity_to_window[window_xid] = view_source - view_source.show() - -class ViewSource(gtk.Window): - __gtype_name__ = 'SugarViewSource' - - def __init__(self, window_xid, bundle_path, document_path, title): - gtk.Window.__init__(self) - - logging.debug('ViewSource paths: %r %r' % (bundle_path, document_path)) - - self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - self.set_decorated(False) - self.set_position(gtk.WIN_POS_CENTER_ALWAYS) - self.set_border_width(style.LINE_WIDTH) - - width = gtk.gdk.screen_width() - style.GRID_CELL_SIZE * 2 - height = gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 2 - self.set_size_request(width, height) - - self._parent_window_xid = window_xid - - self.connect('realize', self.__realize_cb) - self.connect('destroy', self.__destroy_cb, document_path) - self.connect('key-press-event', self.__key_press_event_cb) - - vbox = gtk.VBox() - self.add(vbox) - vbox.show() - - toolbar = Toolbar(title, bundle_path, document_path) - vbox.pack_start(toolbar, expand=False) - toolbar.connect('stop-clicked', self.__stop_clicked_cb) - toolbar.connect('source-selected', self.__source_selected_cb) - toolbar.show() - - pane = gtk.HPaned() - vbox.pack_start(pane) - pane.show() - - self._file_viewer = FileViewer(bundle_path) - self._file_viewer.connect('file-selected', self.__file_selected_cb) - pane.add1(self._file_viewer) - self._file_viewer.show() - - self._source_display = SourceDisplay() - #self._source_display.set_size_request(self._calculate_char_width(80), -1) - pane.pack2(self._source_display) - self._source_display.show() - - def _calculate_char_width(self, char_count): - widget = gtk.Label('') - context = widget.get_pango_context() - pango_font = context.load_font(_SOURCE_FONT) - metrics = pango_font.get_metrics() - return pango.PIXELS(metrics.get_approximate_char_width()) * char_count - - def __realize_cb(self, widget): - self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - self.window.set_accept_focus(True) - - parent = gtk.gdk.window_foreign_new(self._parent_window_xid) - self.window.set_transient_for(parent) - - def __stop_clicked_cb(self, widget): - self.destroy() - - def __source_selected_cb(self, widget, path): - if os.path.isfile(path): - self._source_display.file_path = path - self._file_viewer.hide() - else: - self._file_viewer.set_path(path) - self._file_viewer.show() - - def __destroy_cb(self, window, document_path): - del map_activity_to_window[self._parent_window_xid] - if document_path is not None and os.path.exists(document_path): - os.unlink(document_path) - - def __key_press_event_cb(self, window, event): - keyname = gtk.gdk.keyval_name(event.keyval) - if keyname == 'Escape': - self.destroy() - - def __file_selected_cb(self, file_viewer, file_path): - if file_path is not None and os.path.isfile(file_path): - self._source_display.file_path = file_path - else: - self._source_display.file_path = None - -class Toolbar(gtk.Toolbar): - __gtype_name__ = 'SugarViewSourceToolbar' - - __gsignals__ = { - 'stop-clicked': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([])), - 'source-selected': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([str])), - } - - def __init__(self, title, bundle_path, document_path): - gtk.Toolbar.__init__(self) - - text = _('View source: %r') % title - label = gtk.Label() - label.set_markup('<b>%s</b>' % text) - label.set_alignment(0, 0.5) - self._add_widget(label) - - if bundle_path is not None and document_path is not None and \ - os.path.exists(bundle_path) and os.path.exists(document_path): - activity_button = RadioToolButton(named_icon='printer') - activity_button.props.tooltip = _('Activity') - activity_button.connect('toggled', self.__button_toggled_cb, bundle_path) - self.insert(activity_button, -1) - activity_button.show() - - document_button = RadioToolButton(named_icon='view-radial') - document_button.props.tooltip = _('Document') - document_button.props.group = activity_button - document_button.connect('toggled', self.__button_toggled_cb, document_path) - self.insert(document_button, -1) - document_button.show() - - separator = gtk.SeparatorToolItem() - separator.props.draw = False - separator.set_expand(True) - self.insert(separator, -1) - separator.show() - - stop = ToolButton(icon_name='dialog-cancel') - stop.set_tooltip(_('Close')) - stop.connect('clicked', self.__stop_clicked_cb) - stop.show() - self.insert(stop, -1) - stop.show() - - def _add_widget(self, widget, expand=False): - tool_item = gtk.ToolItem() - tool_item.set_expand(expand) - - tool_item.add(widget) - widget.show() - - self.insert(tool_item, -1) - tool_item.show() - - def __stop_clicked_cb(self, button): - self.emit('stop-clicked') - - def __button_toggled_cb(self, button, path): - if button.props.active: - self.emit('source-selected', path) - -class FileViewer(gtk.ScrolledWindow): - __gtype_name__ = 'SugarFileViewer' - - __gsignals__ = { - 'file-selected': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([str])), - } - - def __init__(self, path): - gtk.ScrolledWindow.__init__(self) - - self.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC - self.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC - self.set_size_request(style.GRID_CELL_SIZE * 3, -1) - - self._path = None - - self._tree_view = gtk.TreeView() - self.add(self._tree_view) - self._tree_view.show() - - self._tree_view.props.headers_visible = False - selection = self._tree_view.get_selection() - selection.connect('changed', self.__selection_changed_cb) - - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn() - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - self._tree_view.append_column(column) - self._tree_view.set_search_column(0) - - self.set_path(path) - - def set_path(self, path): - self.emit('file-selected', None) - if self._path == path: - return - self._path = path - self._tree_view.set_model(gtk.TreeStore(str, str)) - self._add_dir_to_model(path) - - def _add_dir_to_model(self, dir_path, parent=None): - model = self._tree_view.get_model() - for f in os.listdir(dir_path): - full_path = os.path.join(dir_path, f) - if os.path.isdir(full_path): - new_iter = model.append(parent, [f, full_path]) - self._add_dir_to_model(full_path, new_iter) - else: - model.append(parent, [f, full_path]) - - def __selection_changed_cb(self, selection): - model, tree_iter = selection.get_selected() - if tree_iter is None: - file_path = None - else: - file_path = model.get_value(tree_iter, 1) - self.emit('file-selected', file_path) - -class SourceDisplay(gtk.ScrolledWindow): - __gtype_name__ = 'SugarSourceDisplay' - - def __init__(self): - gtk.ScrolledWindow.__init__(self) - - self.props.hscrollbar_policy = gtk.POLICY_AUTOMATIC - self.props.vscrollbar_policy = gtk.POLICY_AUTOMATIC - - self._buffer = gtksourceview2.Buffer() - self._buffer.set_highlight_syntax(True) - - self._source_view = gtksourceview2.View(self._buffer) - self._source_view.set_editable(False) - self._source_view.set_cursor_visible(True) - self._source_view.set_show_line_numbers(True) - self._source_view.set_show_right_margin(True) - self._source_view.set_right_margin_position(80) - #self._source_view.set_highlight_current_line(True) #FIXME: Ugly color - self._source_view.modify_font(_SOURCE_FONT) - self.add(self._source_view) - self._source_view.show() - - self._file_path = None - - def _set_file_path(self, file_path): - if file_path == self._file_path: - return - self._file_path = file_path - - if self._file_path is None: - self._buffer.set_text('') - return - - mime_type = mime.get_for_file(self._file_path) - logging.debug('Detected mime type: %r' % mime_type) - - language_manager = gtksourceview2.language_manager_get_default() - detected_language = None - for language_id in language_manager.get_language_ids(): - language = language_manager.get_language(language_id) - if mime_type in language.get_mime_types(): - detected_language = language - break - - if detected_language is not None: - logging.debug('Detected language: %r' % \ - detected_language.get_name()) - - self._buffer.set_language(detected_language) - self._buffer.set_text(open(self._file_path, 'r').read()) - - def _get_file_path(self): - return self._file_path - - file_path = property(_get_file_path, _set_file_path) - diff --git a/po/POTFILES.in b/po/POTFILES.in index b0bdaa6..dc44f2d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,59 +1,36 @@ -extensions/cpsection/aboutme/__init__.py -extensions/cpsection/aboutme/model.py -extensions/cpsection/aboutme/view.py -extensions/cpsection/aboutxo/__init__.py -extensions/cpsection/aboutxo/model.py -extensions/cpsection/aboutxo/view.py -extensions/cpsection/datetime/__init__.py -extensions/cpsection/datetime/model.py -extensions/cpsection/datetime/view.py -extensions/cpsection/frame/__init__.py -extensions/cpsection/frame/model.py -extensions/cpsection/frame/view.py -extensions/cpsection/language/__init__.py -extensions/cpsection/language/model.py -extensions/cpsection/language/view.py -extensions/cpsection/network/__init__.py -extensions/cpsection/network/model.py -extensions/cpsection/network/view.py -extensions/cpsection/power/__init__.py -extensions/cpsection/power/model.py -extensions/cpsection/power/view.py -extensions/deviceicon/battery.py -extensions/deviceicon/network.py -extensions/deviceicon/speaker.py -extensions/deviceicon/volume.py -extensions/globalkey/screenshot.py -extensions/globalkey/viewsource.py -data/sugar.schemas.in -src/jarabe/controlpanel/cmd.py -src/jarabe/controlpanel/gui.py -src/jarabe/controlpanel/sectionview.py -src/jarabe/controlpanel/toolbar.py -src/jarabe/desktop/favoriteslayout.py -src/jarabe/desktop/favoritesview.py -src/jarabe/desktop/homebox.py -src/jarabe/desktop/keydialog.py -src/jarabe/desktop/meshbox.py -src/jarabe/desktop/schoolserver.py -src/jarabe/frame/activitiestray.py -src/jarabe/frame/clipboardmenu.py -src/jarabe/frame/clipboardobject.py -src/jarabe/frame/devicestray.py -src/jarabe/frame/zoomtoolbar.py -src/jarabe/intro/window.py -src/jarabe/journal/collapsedentry.py -src/jarabe/journal/detailview.py -src/jarabe/journal/expandedentry.py -src/jarabe/journal/journalactivity.py -src/jarabe/journal/journaltoolbox.py -src/jarabe/journal/listview.py -src/jarabe/journal/misc.py -src/jarabe/journal/modalalert.py -src/jarabe/journal/objectchooser.py -src/jarabe/journal/palettes.py -src/jarabe/journal/volumestoolbar.py -src/jarabe/view/buddymenu.py -src/jarabe/view/keyhandler.py -src/jarabe/view/palettes.py +src/intro/intro.py +src/view/BuddyMenu.py +src/view/clipboardmenu.py +src/hardware/keydialog.py +src/hardware/schoolserver.py +src/view/Shell.py +src/view/clipboardicon.py +src/view/home/HomeBox.py +src/view/home/MeshBox.py +src/view/devices/battery.py +src/view/devices/speaker.py +src/view/devices/network/wireless.py +src/view/frame/zoomtoolbar.py +src/controlpanel/cmd.py +src/controlpanel/toolbar.py +src/controlpanel/sectionview.py +src/controlpanel/gui.py +src/controlpanel/model/aboutme.py +src/controlpanel/model/aboutxo.py +src/controlpanel/model/datetime.py +src/controlpanel/model/frame.py +src/controlpanel/model/language.py +src/controlpanel/model/network.py +src/controlpanel/model/power.py +src/controlpanel/view/aboutme.py +src/controlpanel/view/aboutxo.py +src/controlpanel/view/datetime.py +src/controlpanel/view/frame.py +src/controlpanel/view/language.py +src/controlpanel/view/network.py +src/controlpanel/view/power.py +src/view/devices/network/mesh.py +src/view/frame/activitiestray.py +src/view/home/favoritesview.py +src/view/palettes.py @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: sugar\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-01 18:31-0400\n" -"PO-Revision-Date: 2008-09-01 19:07-0400\n" +"POT-Creation-Date: 2008-09-19 00:30-0400\n" +"PO-Revision-Date: 2008-09-19 16:02-0400\n" "Last-Translator: Khaled Hosny <khaledhosny@eglug.org>\n" "Language-Team: Arabic <doc@arabeyes.org>\n" "MIME-Version: 1.0\n" @@ -19,35 +19,35 @@ msgstr "" "Nplurals=6; Plural=N==0 ? 0: n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 " ": n%100>=11 && n%100<=99 ? 4 : 5;\n" -#: ../src/intro/window.py:93 ../src/controlpanel/view/aboutme.py:100 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "الاسم:" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "انقر لتغيير اللون:" -#: ../src/intro/window.py:175 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "السابق" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "تمّ" -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "التالي" -#: ../src/view/BuddyMenu.py:58 +#: ../src/view/BuddyMenu.py:60 msgid "Remove friend" msgstr "أزل صديق" -#: ../src/view/BuddyMenu.py:61 +#: ../src/view/BuddyMenu.py:63 msgid "Make friend" msgstr "اصنع صديق" -#: ../src/view/BuddyMenu.py:90 +#: ../src/view/BuddyMenu.py:92 #, python-format msgid "Invite to %s" msgstr "ادع٠إلى %s" @@ -68,7 +68,7 @@ msgstr "اÙتØ" #. TODO: Implement stopping downloads #. self._stop_item.connect('activate', self._stop_item_activate_cb) #. self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:85 msgid "Keep" msgstr "اØÙظ" @@ -105,71 +105,59 @@ msgstr "تعذّر الاتصال بالخادوم." msgid "The server could not complete the request." msgstr "لم يستطع الخادوم إكمال الطلب." -#: ../src/view/Shell.py:261 +#: ../src/view/Shell.py:251 msgid "Screenshot" msgstr "لقطة شاشة" -#: ../src/view/home/HomeBox.py:81 +#: ../src/view/home/HomeBox.py:79 msgid "Confirm erase" msgstr "أكّد المسØ" -#: ../src/view/home/HomeBox.py:83 +#: ../src/view/home/HomeBox.py:81 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "أكّد المسØ: أتريد Ù…Ø³Ø %s نهائيا؟" -#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 +#: ../src/view/home/HomeBox.py:88 ../src/view/palettes.py:120 msgid "Erase" msgstr "امسØ" -#: ../src/view/home/HomeBox.py:120 +#: ../src/view/home/HomeBox.py:118 msgid "Software Update" msgstr "تØديث البرمجيات" -#: ../src/view/home/HomeBox.py:121 +#: ../src/view/home/HomeBox.py:119 msgid "Update your activities to ensure compatibility with your new software" msgstr "Øدّث نشاطاتك لتضمن التواÙقية مع البرمجيات الجديدة" -#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:123 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "ألغÙ" -#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:276 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/gui.py:286 msgid "Later" msgstr "لاØقا" -#: ../src/view/home/HomeBox.py:130 +#: ../src/view/home/HomeBox.py:128 msgid "Check now" msgstr "التمس الآن" -#: ../src/view/home/HomeBox.py:266 +#: ../src/view/home/HomeBox.py:262 msgid "List view" msgstr "منظور القائمة" -#: ../src/view/home/HomeBox.py:267 +#: ../src/view/home/HomeBox.py:263 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:325 +#: ../src/view/home/HomeBox.py:321 msgid "Favorites view" msgstr "المنظور المÙضل" -#: ../src/view/home/HomeBox.py:326 +#: ../src/view/home/HomeBox.py:322 msgid "<Ctrl>1" msgstr "<Ctrl>1" -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/HomeBox.py:334 -msgid "Freeform" -msgstr "ØÙر" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/HomeBox.py:341 -msgid "Ring" -msgstr "Øلقة" - #: ../src/view/home/MeshBox.py:97 msgid "Connect" msgstr "اتصل" @@ -196,9 +184,10 @@ msgstr "يجري الاتصال..." msgid "Connected" msgstr "Ù…Ùتّصل" -#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "شبكة عÙروÙيّة" @@ -206,8 +195,8 @@ msgstr "شبكة عÙروÙيّة" # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:119 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "اÙصÙÙ„..." @@ -244,19 +233,24 @@ msgstr "مشØون" msgid "My Speakers" msgstr "سماعاتي" -#: ../src/view/devices/speaker.py:125 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" msgstr "اÙتØ" -#: ../src/view/devices/speaker.py:128 +#: ../src/view/devices/speaker.py:122 msgid "Mute" msgstr "أصمÙت" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "عنوان الإنترنت: %s" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "Ù…Ùصول" -#: ../src/view/devices/network/wireless.py:137 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "قناة" @@ -293,9 +287,7 @@ msgstr "" msgid "sugar-control-panel: %s" msgstr "" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 +#: ../src/controlpanel/cmd.py:33 msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -309,27 +301,27 @@ msgid "" " " msgstr "" -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "تØتاج لإعادة تشغيل «سÙكّر» لتÙطبق التغييرات.\n" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 msgid "Ok" msgstr "Øسنا" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:278 msgid "Changes require restart" msgstr "تتطلب التغييرات إعادة التشغيل" -#: ../src/controlpanel/gui.py:267 +#: ../src/controlpanel/gui.py:277 msgid "Warning" msgstr "تØذير" -#: ../src/controlpanel/gui.py:271 +#: ../src/controlpanel/gui.py:281 msgid "Cancel changes" msgstr "ألغ٠التغييرات" -#: ../src/controlpanel/gui.py:280 +#: ../src/controlpanel/gui.py:290 msgid "Restart now" msgstr "أعÙد التشغيل الآن" @@ -369,7 +361,7 @@ msgstr "خطأ ÙÙŠ الألوان المØددة." msgid "Not available" msgstr "غير Ù…ÙتاØ" -#: ../src/controlpanel/model/datetime.py:85 +#: ../src/controlpanel/model/datetime.py:89 msgid "Error timezone does not exist." msgstr "خطأ: المنطقة الزمنية لا وجود لها." @@ -381,25 +373,21 @@ msgstr "يجب أن تكون القيمة عددا صØÙŠØا." msgid "Could not access ~/.i18n. Create standard settings." msgstr "تعذّر الوصول إلى â€~/.i18n‬. سأنشئ إعدادات قياسية." -#: ../src/controlpanel/model/language.py:110 +#: ../src/controlpanel/model/language.py:114 #, python-format msgid "Language for code=%s could not be determined." msgstr "لا يمكن تØديد لغة الرمز=%s." -#: ../src/controlpanel/model/language.py:127 +#: ../src/controlpanel/model/language.py:131 #, python-format msgid "Sorry I do not speak '%s'." msgstr "آسÙØŒ لا أتØدث '%s'." -#: ../src/controlpanel/model/network.py:48 -msgid "You must enter a server." -msgstr "يجب أن تÙدخÙÙ„ خادوما." - -#: ../src/controlpanel/model/network.py:63 +#: ../src/controlpanel/model/network.py:62 msgid "State is unknown." msgstr "الØالة مجهولة." -#: ../src/controlpanel/model/network.py:83 +#: ../src/controlpanel/model/network.py:82 msgid "Error in specified radio argument use on/off." msgstr "خطأ ÙÙŠ معامل الإذاعة المØدد، استخدم Ù…ÙÙعّل/Ù…Ùعطّل." @@ -456,7 +444,7 @@ msgid "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "Øقوق النشر Ù…ØÙوظة 2008 لجمعية Øاسوب Ù…Øمول لكل Ø·ÙÙ„Ø› ردهات؛ والمساهمين." -#: ../src/controlpanel/view/aboutxo.py:166 +#: ../src/controlpanel/view/aboutxo.py:167 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -467,7 +455,7 @@ msgstr "" "لرخصة جنو للتأميم عامّة الأغراض، ويمكنك تعديلها Ùˆ/أو توزيع نسخ منها ÙˆÙÙ‚ شروط " "معينة مذكورة هنا." -#: ../src/controlpanel/view/aboutxo.py:178 +#: ../src/controlpanel/view/aboutxo.py:179 msgid "Full license:" msgstr "الترخيص كاملا:" @@ -517,19 +505,31 @@ msgstr "اللغة" msgid "Network" msgstr "الشبكة" -#: ../src/controlpanel/view/network.py:53 +#: ../src/controlpanel/view/network.py:54 msgid "Wireless" msgstr "اللاسلكي" -#: ../src/controlpanel/view/network.py:61 -msgid "Radio:" -msgstr "الإذاعة:" +#: ../src/controlpanel/view/network.py:62 +msgid "Turn of the wireless radio to save battery life" +msgstr "أغلق الإذاعة اللاسلكية لإطالة عمر البطارية" -#: ../src/controlpanel/view/network.py:94 +#: ../src/controlpanel/view/network.py:75 +msgid "Radio" +msgstr "الإذاعة" + +#: ../src/controlpanel/view/network.py:91 +msgid "Discard network history if you have trouble connecting to the network" +msgstr "تجاهل تأريخ الشبكة إذا كانت لديك مشاكل ÙÙŠ الاتصال بالشبكة" + +#: ../src/controlpanel/view/network.py:100 +msgid "Discard network history" +msgstr "تجاهل تأريخ الشبكة" + +#: ../src/controlpanel/view/network.py:113 msgid "Mesh" msgstr "الشبكة العروية" -#: ../src/controlpanel/view/network.py:103 +#: ../src/controlpanel/view/network.py:122 msgid "Server:" msgstr "الخادوم" @@ -547,34 +547,34 @@ msgstr "إدارة آلية للطاقة (تطيل من عمر البطارية) #: ../src/controlpanel/view/power.py:89 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Extreme power management (disables wireless radio, increases battery life)" msgstr "إدارة قصوى للطاقة (تعطّل اللاسلكي وتطيل عمر البطارية)" -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "اتصل ببوابة شبكة مدرسة" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "يبØØ« عن بوابة شبكة مدرسة..." -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" msgstr "اتصل ببوابة شبكة XO" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." msgstr "يبØØ« عن بوابة شبكة XO..." -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "اتصل بشبكة بسيطة" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "يبدأ شبكة بسيطة" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "شبكة مجهولة" @@ -582,36 +582,36 @@ msgstr "شبكة مجهولة" msgid "Decline" msgstr "ارÙض" -#: ../src/view/home/favoritesview.py:286 +#: ../src/view/home/favoritesview.py:296 msgid "Registration Failed" msgstr "Ùشل التسجيل" -#: ../src/view/home/favoritesview.py:287 +#: ../src/view/home/favoritesview.py:297 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:289 +#: ../src/view/home/favoritesview.py:299 msgid "Registration Successful" msgstr "Ù†Ø¬Ø Ø§Ù„ØªØ³Ø¬ÙŠÙ„" -#: ../src/view/home/favoritesview.py:290 +#: ../src/view/home/favoritesview.py:300 msgid "You are now registered with your school server." msgstr "الآن، أنت مسجّل ÙÙŠ خادوم مدرستك." -#: ../src/view/home/favoritesview.py:407 +#: ../src/view/home/favoritesview.py:420 msgid "Control Panel" msgstr "لوØØ© التØكم" -#: ../src/view/home/favoritesview.py:418 +#: ../src/view/home/favoritesview.py:425 msgid "Restart" msgstr "أعد التشغيل" -#: ../src/view/home/favoritesview.py:423 +#: ../src/view/home/favoritesview.py:430 msgid "Shutdown" msgstr "أطÙئ" -#: ../src/view/home/favoritesview.py:429 +#: ../src/view/home/favoritesview.py:436 msgid "Register" msgstr "سجّل" @@ -627,23 +627,34 @@ msgstr "Ù‚Ù" msgid "Start" msgstr "ابدأ" -#: ../src/view/palettes.py:132 +#: ../src/view/palettes.py:138 msgid "Remove favorite" msgstr "اØذ٠المÙضلة" -#: ../src/view/palettes.py:136 +#: ../src/view/palettes.py:142 msgid "Make favorite" msgstr "اصنع Ù…Ùضلة" -#: ../src/view/palettes.py:185 +#: ../src/view/palettes.py:191 msgid "Show contents" msgstr "أظهر المØتويات" -#: ../src/view/palettes.py:209 +#: ../src/view/palettes.py:215 #, python-format msgid "%(free_space)d MB Free" msgstr "%(free_space)d Ù….بايت خالية" +# TRANS: label for the freeform layout in the favorites view +#~ msgid "Freeform" +#~ msgstr "ØÙر" + +# TRANS: label for the ring layout in the favorites view +#~ msgid "Ring" +#~ msgstr "Øلقة" + +#~ msgid "You must enter a server." +#~ msgstr "يجب أن تÙدخÙÙ„ خادوما." + #~ msgid "<Ctrl>R" #~ msgstr "<Ctrl>Ø" @@ -4,8 +4,8 @@ msgid "" msgstr "" "Project-Id-Version: sugar\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-11-14 12:15-0500\n" +"POT-Creation-Date: 2008-09-01 18:31-0400\n" +"PO-Revision-Date: 2008-09-07 17:38-0400\n" "Last-Translator: Markus Schlager <m.slg@gmx.de>\n" "Language-Team: German <fedora-trans-de@redhat.com>\n" "MIME-Version: 1.0\n" @@ -14,45 +14,44 @@ msgstr "" "X-Generator: Pootle 1.1.0rc2\n" "X-Poedit-Language: German\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "Name:" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "Klicken zum Wechseln der Farbe:" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Zurück" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Fertig" -# (Markus S.) war 'Nächste' -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:165 msgid "Next" -msgstr "Vor" +msgstr "Nächste" -#: ../src/view/BuddyMenu.py:60 +#: ../src/view/BuddyMenu.py:58 msgid "Remove friend" msgstr "Freund entfernen" -#: ../src/view/BuddyMenu.py:63 +#: ../src/view/BuddyMenu.py:61 msgid "Make friend" msgstr "Freunde werden" -#: ../src/view/BuddyMenu.py:92 +#: ../src/view/BuddyMenu.py:90 #, python-format msgid "Invite to %s" msgstr "Einladen zu %s" -#: ../src/view/clipboardmenu.py:51 +#: ../src/view/clipboardmenu.py:48 msgid "Remove" msgstr "Entfernen" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" msgstr "Öffnen" @@ -60,20 +59,22 @@ msgstr "Öffnen" # TODO: Implement stopping downloads # self._stop_item.connect('activate', self._stop_item_activate_cb) # self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 msgid "Keep" msgstr "Behalten" -#: ../src/view/clipboardmenu.py:83 +#: ../src/view/clipboardmenu.py:84 msgid "Open with" msgstr "Öffnen mit" -# (Markus S.) 'clipping', nicht 'clipped' -#: ../src/view/clipboardmenu.py:228 +#: ../src/view/clipboardmenu.py:216 #, python-format -#, fuzzy -msgid "%s clipping" -msgstr "%s ausgeschnitten" +msgid "Clipboard object: %s." +msgstr "Zwischenablage-Objekt: %s." #: ../src/hardware/keydialog.py:150 msgid "Key Type:" @@ -99,62 +100,73 @@ msgstr "Kann nicht mit dem Server verbinden." msgid "The server could not complete the request." msgstr "Der Server konnte die Anforderung nicht erfüllen." -#: ../src/view/Shell.py:251 +#: ../src/view/Shell.py:262 msgid "Screenshot" msgstr "Bildschirmfoto" -#: ../src/view/home/HomeBox.py:78 +#: ../src/view/home/HomeBox.py:81 msgid "Confirm erase" msgstr "Löschen bestätigen" -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:83 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "Löschen bestätigen: Willst du %s wirklich dauerhaft löschen?" -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 +#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 msgid "Erase" msgstr "Löschen" -#: ../src/view/home/HomeBox.py:117 +#: ../src/view/home/HomeBox.py:120 msgid "Software Update" msgstr "Software-Aktualisierung" -#: ../src/view/home/HomeBox.py:118 +#: ../src/view/home/HomeBox.py:121 msgid "Update your activities to ensure compatibility with your new software" msgstr "" "Aktualisiere deine Aktivitäten, um die Kompatibilität mit deiner neuen " "Software sicher zu stellen." -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "Abbrechen" -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 +#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:276 msgid "Later" msgstr "Später" -#: ../src/view/home/HomeBox.py:127 +#: ../src/view/home/HomeBox.py:130 msgid "Check now" msgstr "Jetzt prüfen" -#: ../src/view/home/HomeBox.py:261 +#: ../src/view/home/HomeBox.py:266 msgid "List view" msgstr "Listenansicht" -#: ../src/view/home/HomeBox.py:262 +#: ../src/view/home/HomeBox.py:267 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:320 +#: ../src/view/home/HomeBox.py:325 msgid "Favorites view" msgstr "Favoritenansicht" -#: ../src/view/home/HomeBox.py:321 +#: ../src/view/home/HomeBox.py:326 msgid "<Ctrl>1" msgstr "<Ctrl>1" +# TRANS: label for the freeform layout in the favorites view +#. TRANS: label for the freeform layout in the favorites view +#: ../src/view/home/HomeBox.py:334 +msgid "Freeform" +msgstr "Freie Form" + +# TRANS: label for the ring layout in the favorites view +#. TRANS: label for the ring layout in the favorites view +#: ../src/view/home/HomeBox.py:341 +msgid "Ring" +msgstr "Ring" + #: ../src/view/home/MeshBox.py:97 msgid "Connect" msgstr "Verbinden" @@ -176,19 +188,20 @@ msgstr "Trenne Verbindung..." # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:159 +#: ../src/view/home/MeshBox.py:152 msgid "Connecting..." msgstr "Verbinde..." # TODO: show the channel number #. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 +#: ../src/view/home/MeshBox.py:159 msgid "Connected" msgstr "Verbunden" -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "Maschennetzwerk" @@ -196,18 +209,16 @@ msgstr "Maschennetzwerk" # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "Verbindung trennen..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 msgid "Resume" msgstr "Wiederaufnehmen" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" msgstr "Mitmachen" @@ -236,19 +247,24 @@ msgstr "Aufgeladen" msgid "My Speakers" msgstr "Meine Lautsprecher" -#: ../src/view/devices/speaker.py:125 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" msgstr "Laut schalten" -#: ../src/view/devices/speaker.py:128 +#: ../src/view/devices/speaker.py:122 msgid "Mute" msgstr "Stumm schalten" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "IP-Addresse: %s" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "Nicht verbunden" -#: ../src/view/devices/network/wireless.py:143 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "Kanal" @@ -260,10 +276,9 @@ msgstr "Umgebung" msgid "Group" msgstr "Gruppe" -# (Markus S.) war 'Zuhause', vgl. stuffer-sheet #: ../src/view/frame/zoomtoolbar.py:41 msgid "Home" -msgstr "Startbildschirm" +msgstr "Zuhause" #: ../src/view/frame/zoomtoolbar.py:43 msgid "Activity" @@ -275,7 +290,7 @@ msgid "" "sugar-control-panel: WARNING, found more than one option with the same name: " "%s module: %r" msgstr "" -"sugar-control-panel: WARNUNG, mehr als eine Option mit demselben Namen: %s " +"sugar-control-panel: WARNUNG, mehr als eine Option mit demselben Namen: %s " "und Modul: %r gefunden" #: ../src/controlpanel/cmd.py:28 @@ -289,9 +304,7 @@ msgid "sugar-control-panel: %s" msgstr "sugar-control-panel: %s" # (Markus S.) war 'Benutzung: sugar-control-panel [ option ] key [ args ... ] \n'; 'Parameter' war 'Key'. -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 +#: ../src/controlpanel/cmd.py:33 msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -313,112 +326,161 @@ msgstr "" " -g Parameter Den aktuellen Wert für diesen Parameter auslesen\n" " -s Parameter Den aktuellen Wert für diesen Parameter festlegen\n" " -c Parameter Den aktuellen Wert für diesen Parameter zurücksetzen\n" -" " +" " -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "Um die Änderungen zu übernehmen, muss Sugar neu gestartet werden.\n" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 msgid "Ok" msgstr "Ok" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:268 msgid "Changes require restart" msgstr "Neustart zur Ãœbernahme der Änderungen notwendig" -#: ../src/controlpanel/gui.py:264 +#: ../src/controlpanel/gui.py:267 msgid "Warning" msgstr "Warnung" -#: ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/gui.py:271 msgid "Cancel changes" msgstr "Änderungen aufheben" -#: ../src/controlpanel/gui.py:277 +#: ../src/controlpanel/gui.py:280 msgid "Restart now" msgstr "Jetzt neustarten" -#: ../src/controlpanel/aboutme/model.py:44 +#: ../src/controlpanel/model/aboutme.py:44 msgid "You must enter a name." msgstr "Bitte einen Namen eingeben" -#: ../src/controlpanel/aboutme/model.py:69 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format msgid "stroke: color=%s hue=%s" msgstr "Linie: Farbe=%s Farbton=%s" -#: ../src/controlpanel/aboutme/model.py:72 +#: ../src/controlpanel/model/aboutme.py:72 #, python-format msgid "stroke: %s" msgstr "Linie: %s" -#: ../src/controlpanel/aboutme/model.py:74 +#: ../src/controlpanel/model/aboutme.py:74 #, python-format msgid "fill: color=%s hue=%s" msgstr "Füllung: Farbe=%s Farbton=%s" -#: ../src/controlpanel/aboutme/model.py:76 +#: ../src/controlpanel/model/aboutme.py:76 #, python-format msgid "fill: %s" msgstr "Füllung: %s" -#: ../src/controlpanel/aboutme/model.py:87 +#: ../src/controlpanel/model/aboutme.py:87 msgid "Error in specified color modifiers." msgstr "Fehler in den angegebenen Farbänderungen." -#: ../src/controlpanel/aboutme/model.py:90 +#: ../src/controlpanel/model/aboutme.py:90 msgid "Error in specified colors." msgstr "Fehler in den angegebenen Farben." -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 +#: ../src/controlpanel/model/aboutxo.py:24 +msgid "Not available" +msgstr "Nicht verfügbar" + +#: ../src/controlpanel/model/datetime.py:85 +msgid "Error timezone does not exist." +msgstr "Fehler: unbekannte Zeitzone." + +#: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 +msgid "Value must be an integer." +msgstr "Der Wert muss ganzzahlig sein." + +#: ../src/controlpanel/model/language.py:28 +msgid "Could not access ~/.i18n. Create standard settings." +msgstr "Zugriff auf %s nicht möglich. Erzeuge daher Standardeinstellungen." + +#: ../src/controlpanel/model/language.py:110 +#, python-format +msgid "Language for code=%s could not be determined." +msgstr "Sprache für Code=%s konnte nicht ermittelt werden." + +#: ../src/controlpanel/model/language.py:127 +#, python-format +msgid "Sorry I do not speak '%s'." +msgstr "Entschuldigung, ich spreche nicht '%s'." + +#: ../src/controlpanel/model/network.py:48 +msgid "You must enter a server." +msgstr "Bitte einen Server angeben" + +#: ../src/controlpanel/model/network.py:63 +msgid "State is unknown." +msgstr "Status ist nicht bekannt." + +# (Markus S.) vgl. http://lists.laptop.org/pipermail/localization/2008-July/001232.html +#: ../src/controlpanel/model/network.py:83 +msgid "Error in specified radio argument use on/off." +msgstr "Fehler im angegebenen radio-Parameter (Funknetz) -- on/off verwenden." + +# (Markus S.) vgl. http://lists.laptop.org/pipermail/localization/2008-July/001232.html +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." +msgstr "" +"Fehler im automatischen pm-Parameter (Energieverwaltung) --on/off verwenden." + +# (Markus S.) vgl. http://lists.laptop.org/pipermail/localization/2008-July/001232.html +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." +msgstr "Fehler im extremen pm-Parameter (Energieverwaltung) -- on/off benutzen." + +#: ../src/controlpanel/view/aboutme.py:32 msgid "About Me" msgstr "Ãœber mich" -#: ../src/controlpanel/aboutme/view.py:134 +#: ../src/controlpanel/view/aboutme.py:134 msgid "Click to change your color:" msgstr "Klicken, um deine Farbe zu wechseln:" -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "Nicht verfügbar" +#: ../src/controlpanel/view/aboutxo.py:28 +msgid "About my XO" +msgstr "Ãœber meinen XO" -#: ../src/controlpanel/aboutxo/view.py:55 +#: ../src/controlpanel/view/aboutxo.py:59 msgid "Identity" msgstr "Identität" -#: ../src/controlpanel/aboutxo/view.py:64 +#: ../src/controlpanel/view/aboutxo.py:68 msgid "Serial Number:" msgstr "Seriennummer:" -#: ../src/controlpanel/aboutxo/view.py:87 +#: ../src/controlpanel/view/aboutxo.py:91 msgid "Software" msgstr "Software" -#: ../src/controlpanel/aboutxo/view.py:96 +#: ../src/controlpanel/view/aboutxo.py:100 msgid "Build:" msgstr "Version:" -#: ../src/controlpanel/aboutxo/view.py:111 +#: ../src/controlpanel/view/aboutxo.py:115 msgid "Sugar:" msgstr "Sugar:" -#: ../src/controlpanel/aboutxo/view.py:126 +#: ../src/controlpanel/view/aboutxo.py:130 msgid "Firmware:" msgstr "Firmware:" -#: ../src/controlpanel/aboutxo/view.py:148 +#: ../src/controlpanel/view/aboutxo.py:152 msgid "Copyright and License" msgstr "Copyright und Lizenz" -#: ../src/controlpanel/aboutxo/view.py:156 +#: ../src/controlpanel/view/aboutxo.py:160 msgid "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." -#: ../src/controlpanel/aboutxo/view.py:163 +#: ../src/controlpanel/view/aboutxo.py:166 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -430,247 +492,158 @@ msgstr "" "darin festgelegten Bedingungen ist es erlaubt, die Software zu verändern " "und/oder Kopien davon zu erstellen und zu verteilen." -#: ../src/controlpanel/aboutxo/view.py:175 +#: ../src/controlpanel/view/aboutxo.py:178 msgid "Full license:" msgstr "Vollständige Lizenz:" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "Ãœber meinen XO" - -#: ../src/controlpanel/datetime/model.py:89 -msgid "Error timezone does not exist." -msgstr "Fehler: unbekannte Zeitzone." +#: ../src/controlpanel/view/datetime.py:29 +msgid "Date & Time" +msgstr "Datum & Uhrzeit" -#: ../src/controlpanel/datetime/view.py:68 +#: ../src/controlpanel/view/datetime.py:72 msgid "Timezone" msgstr "Zeitzone" -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "Datum & Uhrzeit" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "Der Wert muss ganzzahlig sein." +#: ../src/controlpanel/view/frame.py:28 +#, fuzzy +msgid "Frame" +msgstr "Frame" -#: ../src/controlpanel/frame/view.py:26 +#: ../src/controlpanel/view/frame.py:30 msgid "never" msgstr "nie" # (Markus S.) ' unmittelbar'? -#: ../src/controlpanel/frame/view.py:27 +#: ../src/controlpanel/view/frame.py:31 msgid "instantaneous" msgstr "sofort" -#: ../src/controlpanel/frame/view.py:28 +#: ../src/controlpanel/view/frame.py:32 #, python-format msgid "%s seconds" msgstr "%s Sekunden" -#: ../src/controlpanel/frame/view.py:52 +#: ../src/controlpanel/view/frame.py:56 msgid "Activation Delay" msgstr "Aktivierungsverzögerung" -#: ../src/controlpanel/frame/view.py:76 +#: ../src/controlpanel/view/frame.py:80 msgid "Corner" msgstr "Ecke" -#: ../src/controlpanel/frame/view.py:111 +#: ../src/controlpanel/view/frame.py:115 msgid "Edge" msgstr "Kante" -# (Markus S.) 'Rahmen'? (Vorschlag von hmeyer) -#: ../src/controlpanel/frame/__init__.py:21 -#, fuzzy -msgid "Frame" -msgstr "Frame" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "Zugriff auf %s nicht möglich. Erzeuge daher Standardeinstellungen." - -#: ../src/controlpanel/language/model.py:114 -#, python-format -msgid "Language for code=%s could not be determined." -msgstr "Sprache für Code=%s konnte nicht ermittelt werden." - -#: ../src/controlpanel/language/model.py:131 -#, python-format -msgid "Sorry I do not speak '%s'." -msgstr "Entschuldigung, ich spreche nicht '%s'." - -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 +#: ../src/controlpanel/view/language.py:29 +#: ../src/controlpanel/view/language.py:74 msgid "Language" msgstr "Sprache" -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "Status ist nicht bekannt." - -# (Markus S.) vgl. http://lists.laptop.org/pipermail/localization/2008-July/001232.html -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "Fehler im angegebenen radio-Parameter (Funknetz) -- on/off verwenden." - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 +#: ../src/controlpanel/view/network.py:28 msgid "Network" msgstr "Netzwerk" -#: ../src/controlpanel/network/view.py:54 +#: ../src/controlpanel/view/network.py:53 msgid "Wireless" msgstr "Drahtlosnetzwerk" -#: ../src/controlpanel/network/view.py:62 -msgid "Turn of the wireless radio to save battery life" -msgstr "Schalte das Funknetz aus, um die Lebensdauer der Batterie zu erhöhen" - # (Markus S,) war 'Radio:' -#: ../src/controlpanel/network/view.py:75 -#, fuzzy -msgid "Radio" -msgstr "Funknetz" - -#: ../src/controlpanel/network/view.py:91 -msgid "Discard network history if you have trouble connecting to the network" -msgstr "" -"Verwirf die Netzwerk-Chronik, wenn du Schwierigkeiten hast, dich mit dem " -"Netzwerk zu verbinden" - -#: ../src/controlpanel/network/view.py:100 -msgid "Discard network history" -msgstr "Netzwerk-Chronik verwerfen" +#: ../src/controlpanel/view/network.py:61 +msgid "Radio:" +msgstr "Funknetz:" # (Markus S.) 'Zelle'? -#: ../src/controlpanel/network/view.py:113 +#: ../src/controlpanel/view/network.py:94 msgid "Mesh" msgstr "Masche" -#: ../src/controlpanel/network/view.py:122 +#: ../src/controlpanel/view/network.py:103 msgid "Server:" msgstr "Server:" -# (Markus S.) vgl. http://lists.laptop.org/pipermail/localization/2008-July/001232.html -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "" -"Fehler im automatischen pm-Parameter (Energieverwaltung) --on/off verwenden." - -# (Markus S.) vgl. http://lists.laptop.org/pipermail/localization/2008-July/001232.html -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "Fehler im extremen pm-Parameter (Energieverwaltung) -- on/off benutzen." +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "Energieversorgung" -#: ../src/controlpanel/power/view.py:47 +#: ../src/controlpanel/view/power.py:51 msgid "Power management" msgstr "Energieverwaltung" -#: ../src/controlpanel/power/view.py:57 +#: ../src/controlpanel/view/power.py:61 msgid "Automatic power management (increases battery life)" msgstr "Automatische Energieverwaltung (erhöht die Lebensdauer der Batterie)" -#: ../src/controlpanel/power/view.py:85 +#: ../src/controlpanel/view/power.py:89 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Extreme power management (disables wireless radio, increases battery life)" msgstr "" "Extreme Energieverwaltung (deaktiviert das Funknetz, erhöht die Lebensdauer " "der Batterie)" -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "Energieversorgung" - -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "Verbunden mit einem Schul-Maschennetzwerk-Portal" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "Suche Schul-Maschennetzwerk-Portal..." -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" -msgstr "Verbunden mit einem XO-Maschennetzwerk-Portal" +msgstr "Verbunden mit einem XO Maschennetzwerk-Portal" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." -msgstr "Suche XO-Maschennetzwerk-Portal..." +msgstr "Suche XO Maschennetzwerk-Portal..." -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "Verbunden mit einem einfachen Maschennetzwerk" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "Starte ein einfaches Maschennetzwerk" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "Unbekanntes Maschennetzwerk" -#: ../src/view/frame/activitiestray.py:211 +#: ../src/view/frame/activitiestray.py:210 msgid "Decline" msgstr "Ablehnen" -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "Freie Form" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "Ring" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "Spirale" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "Rechteck" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "Dreieck" - -#: ../src/view/home/favoritesview.py:295 +#: ../src/view/home/favoritesview.py:287 msgid "Registration Failed" msgstr "Registrierung fehlgeschlagen" -#: ../src/view/home/favoritesview.py:296 +#: ../src/view/home/favoritesview.py:288 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:298 +#: ../src/view/home/favoritesview.py:290 msgid "Registration Successful" msgstr "Registrierung erfolgreich" -#: ../src/view/home/favoritesview.py:299 +#: ../src/view/home/favoritesview.py:291 msgid "You are now registered with your school server." msgstr "Du bist nun bei deinem Schulserver registriert." -#: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "Einstellungen" +# (Markus S.) war 'Kontrollfeld' +#: ../src/view/home/favoritesview.py:407 +msgid "Control Panel" +msgstr "Kontrollleiste" -#: ../src/view/home/favoritesview.py:425 +#: ../src/view/home/favoritesview.py:418 msgid "Restart" msgstr "Neustart" -#: ../src/view/home/favoritesview.py:430 +#: ../src/view/home/favoritesview.py:423 msgid "Shutdown" msgstr "Ausschalten" -#: ../src/view/home/favoritesview.py:436 +#: ../src/view/home/favoritesview.py:429 msgid "Register" msgstr "Registrieren" @@ -682,155 +655,27 @@ msgstr "Starte..." msgid "Stop" msgstr "Stopp" -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 +#: ../src/view/palettes.py:104 msgid "Start" msgstr "Start" -#: ../src/view/palettes.py:138 +#: ../src/view/palettes.py:132 msgid "Remove favorite" msgstr "Favorit entfernen" -#: ../src/view/palettes.py:142 +#: ../src/view/palettes.py:136 msgid "Make favorite" msgstr "Zum Favorit machen" -#: ../src/view/palettes.py:191 +#: ../src/view/palettes.py:185 msgid "Show contents" msgstr "Inhalte anzeigen" -#: ../src/view/palettes.py:215 +#: ../src/view/palettes.py:209 #, python-format msgid "%(free_space)d MB Free" msgstr "%(free_space)d MB frei" -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "Suchen" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "Beliebiges Datum" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "Heute" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "Seit gestern" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "Vergangene Woche" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "Vergangener Monat" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "Vergangenes Jahr" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "Alle" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "Meine Freunde" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "Meine Klasse" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "Alles" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "Kopieren" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "Ohne Titel" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "Journal" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "Keine Vorschau" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "Teilnehmer:" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "Beschreibung:" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "Stichwörter:" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "Ein Objekt auswählen" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "Schließen" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "Einbindung lösen" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "Kein Datum" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "Dein Journal ist leer." - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "Keine passenden Einträge" - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "Dein Journal ist voll." - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." -msgstr "" -"Lösche bitte einige alte Journal-Einträge, um Platz für neue zu schaffen." - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "Journal anzeigen" - -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "Zwischenablage-Objekt: %s." - -#~ msgid "You must enter a server." -#~ msgstr "Bitte einen Server angeben" - -# (Markus S.) war 'Kontrollfeld' -#~ msgid "Control Panel" -#~ msgstr "Kontrollleiste" - #~ msgid "<Ctrl>R" #~ msgstr "<Ctrl>R" @@ -932,6 +777,9 @@ msgstr "Journal anzeigen" #~ msgid "Redo" #~ msgstr "Wiederholen" +#~ msgid "Copy" +#~ msgstr "Kopieren" + #~ msgid "Paste" #~ msgstr "Einfügen" @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-01-18 18:19+0000\n" +"POT-Creation-Date: 2008-09-19 00:30-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -16,44 +16,44 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Translate Toolkit 1.0.1\n" -#: ../shell/intro/intro.py:67 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "" -#: ../shell/intro/intro.py:96 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "" -#: ../shell/intro/intro.py:146 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "" -#: ../shell/intro/intro.py:160 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "" -#: ../shell/intro/intro.py:163 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "" -#: ../shell/view/BuddyMenu.py:59 +#: ../src/view/BuddyMenu.py:60 msgid "Remove friend" msgstr "" -#: ../shell/view/BuddyMenu.py:62 +#: ../src/view/BuddyMenu.py:63 msgid "Make friend" msgstr "" -#: ../shell/view/BuddyMenu.py:84 +#: ../src/view/BuddyMenu.py:92 #, python-format msgid "Invite to %s" msgstr "" -#: ../shell/view/clipboardmenu.py:58 +#: ../src/view/clipboardmenu.py:48 msgid "Remove" msgstr "" -#: ../shell/view/clipboardmenu.py:63 +#: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" msgstr "" @@ -61,360 +61,566 @@ msgstr "" #. TODO: Implement stopping downloads #. self._stop_item.connect('activate', self._stop_item_activate_cb) #. self.append_menu_item(self._stop_item) -#: ../shell/view/clipboardmenu.py:73 -msgid "Add to journal" +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:85 +msgid "Keep" +msgstr "" + +#: ../src/view/clipboardmenu.py:84 +msgid "Open with" msgstr "" -#: ../shell/view/clipboardmenu.py:213 +#: ../src/view/clipboardmenu.py:216 #, python-format msgid "Clipboard object: %s." msgstr "" -#: ../shell/hardware/keydialog.py:149 +#: ../src/hardware/keydialog.py:150 msgid "Key Type:" msgstr "" -#: ../shell/hardware/keydialog.py:169 +#: ../src/hardware/keydialog.py:170 msgid "Authentication Type:" msgstr "" -#: ../shell/hardware/keydialog.py:250 +#: ../src/hardware/keydialog.py:251 msgid "Encryption Type:" msgstr "" -#: ../shell/view/home/activitiesdonut.py:90 -msgid "Starting..." +#: ../src/hardware/schoolserver.py:17 +msgid "Cannot obtain data needed for registration." msgstr "" -#: ../shell/view/home/activitiesdonut.py:104 ../shell/view/home/MeshBox.py:295 -msgid "Resume" +#: ../src/hardware/schoolserver.py:31 +msgid "Cannot connect to the server." msgstr "" -#: ../shell/view/home/activitiesdonut.py:111 -#: ../lib/sugar/activity/activity.py:132 -msgid "Stop" +#: ../src/hardware/schoolserver.py:36 +msgid "The server could not complete the request." msgstr "" -#: ../shell/view/Shell.py:285 +#: ../src/view/Shell.py:251 msgid "Screenshot" msgstr "" -#: ../shell/view/home/HomeBox.py:159 -msgid "Reboot" +#: ../src/view/home/HomeBox.py:79 +msgid "Confirm erase" msgstr "" -#: ../shell/view/home/HomeBox.py:164 -msgid "Shutdown" +#: ../src/view/home/HomeBox.py:81 +#, python-format +msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "" -#: ../shell/view/home/HomeBox.py:170 -msgid "Register" +#: ../src/view/home/HomeBox.py:88 ../src/view/palettes.py:120 +msgid "Erase" msgstr "" -#. Only show disconnect when there's a mesh device, because mesh takes -#. priority over the normal wireless device. NM doesn't have a "disconnect" -#. method for a device either (for various reasons) so this doesn't -#. have a good mapping -#: ../shell/view/home/MeshBox.py:90 ../shell/view/home/MeshBox.py:197 -#: ../shell/view/devices/network/wireless.py:113 -#: ../shell/view/devices/network/mesh.py:83 -msgid "Disconnect..." +#: ../src/view/home/HomeBox.py:118 +msgid "Software Update" +msgstr "" + +#: ../src/view/home/HomeBox.py:119 +msgid "Update your activities to ensure compatibility with your new software" +msgstr "" + +#: ../src/view/home/HomeBox.py:123 ../src/controlpanel/toolbar.py:115 +msgid "Cancel" +msgstr "" + +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/gui.py:286 +msgid "Later" +msgstr "" + +#: ../src/view/home/HomeBox.py:128 +msgid "Check now" +msgstr "" + +#: ../src/view/home/HomeBox.py:262 +msgid "List view" msgstr "" -#: ../shell/view/home/MeshBox.py:195 ../shell/view/devices/network/mesh.py:37 -#: ../shell/view/devices/network/mesh.py:62 -#: ../shell/view/devices/network/mesh.py:66 +#: ../src/view/home/HomeBox.py:263 +msgid "<Ctrl>2" +msgstr "" + +#: ../src/view/home/HomeBox.py:321 +msgid "Favorites view" +msgstr "" + +#: ../src/view/home/HomeBox.py:322 +msgid "<Ctrl>1" +msgstr "" + +#: ../src/view/home/MeshBox.py:97 +msgid "Connect" +msgstr "" + +#: ../src/view/home/MeshBox.py:106 +msgid "Disconnect" +msgstr "" + +#: ../src/view/home/MeshBox.py:118 +msgid "Disconnecting..." +msgstr "" + +#: ../src/view/home/MeshBox.py:152 +msgid "Connecting..." +msgstr "" + +#. TODO: show the channel number +#: ../src/view/home/MeshBox.py:159 +msgid "Connected" +msgstr "" + +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "" -#: ../shell/view/home/MeshBox.py:300 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 +msgid "Disconnect..." +msgstr "" + +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 +msgid "Resume" +msgstr "" + +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" msgstr "" -#: ../shell/view/devices/battery.py:38 -msgid "My Battery life" +#: ../src/view/devices/battery.py:45 +msgid "My Battery" +msgstr "" + +#: ../src/view/devices/battery.py:114 +msgid "Charging" +msgstr "" + +#: ../src/view/devices/battery.py:117 +msgid "Very little power remaining" +msgstr "" + +#: ../src/view/devices/battery.py:123 +#, python-format +msgid "%(hour)d:%(min).2d remaining" +msgstr "" + +#: ../src/view/devices/battery.py:127 +msgid "Charged" msgstr "" -#: ../shell/view/devices/battery.py:94 -msgid "Battery charging" +#: ../src/view/devices/speaker.py:44 +msgid "My Speakers" msgstr "" -#: ../shell/view/devices/battery.py:96 -msgid "Battery discharging" +#: ../src/view/devices/speaker.py:119 +msgid "Unmute" msgstr "" -#: ../shell/view/devices/battery.py:98 -msgid "Battery fully charged" +#: ../src/view/devices/speaker.py:122 +msgid "Mute" msgstr "" -#: ../shell/view/devices/network/wireless.py:61 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "" -#: ../shell/view/devices/network/wireless.py:131 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "" -#: ../shell/view/frame/zoomtoolbar.py:42 +#: ../src/view/frame/zoomtoolbar.py:37 msgid "Neighborhood" msgstr "" -#: ../shell/view/frame/zoomtoolbar.py:54 +#: ../src/view/frame/zoomtoolbar.py:39 msgid "Group" msgstr "" -#: ../shell/view/frame/zoomtoolbar.py:66 +#: ../src/view/frame/zoomtoolbar.py:41 msgid "Home" msgstr "" -#: ../shell/view/frame/zoomtoolbar.py:78 +#: ../src/view/frame/zoomtoolbar.py:43 msgid "Activity" msgstr "" -#: ../lib/sugar/activity/activity.py:115 -msgid "Share with:" +#: ../src/controlpanel/cmd.py:26 +#, python-format +msgid "" +"sugar-control-panel: WARNING, found more than one option with the same name: " +"%s module: %r" msgstr "" -#: ../lib/sugar/activity/activity.py:117 -msgid "Private" +#: ../src/controlpanel/cmd.py:28 +#, python-format +msgid "sugar-control-panel: key=%s not an available option" msgstr "" -#: ../lib/sugar/activity/activity.py:118 -msgid "My Neighborhood" +#: ../src/controlpanel/cmd.py:29 +#, python-format +msgid "sugar-control-panel: %s" msgstr "" -#: ../lib/sugar/activity/activity.py:126 -msgid "Keep" +#: ../src/controlpanel/cmd.py:33 +msgid "" +"Usage: sugar-control-panel [ option ] key [ args ... ] \n" +" Control for the sugar environment. \n" +" Options: \n" +" -h show this help message and exit \n" +" -l list all the available options \n" +" -h key show information about this key \n" +" -g key get the current value of the key \n" +" -s key set the current value for the key \n" +" -c key clear the current value for the key \n" +" " +msgstr "" + +#: ../src/controlpanel/cmd.py:46 +msgid "To apply your changes you have to restart sugar.\n" +msgstr "" + +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 +msgid "Ok" +msgstr "" + +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:278 +msgid "Changes require restart" msgstr "" -#: ../lib/sugar/activity/activity.py:245 -msgid "Undo" +#: ../src/controlpanel/gui.py:277 +msgid "Warning" msgstr "" -#: ../lib/sugar/activity/activity.py:250 -msgid "Redo" +#: ../src/controlpanel/gui.py:281 +msgid "Cancel changes" msgstr "" -#: ../lib/sugar/activity/activity.py:260 -msgid "Copy" +#: ../src/controlpanel/gui.py:290 +msgid "Restart now" msgstr "" -#: ../lib/sugar/activity/activity.py:265 -msgid "Paste" +#: ../src/controlpanel/model/aboutme.py:44 +msgid "You must enter a name." msgstr "" -#: ../lib/sugar/activity/activity.py:454 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format -msgid "%s Activity" +msgid "stroke: color=%s hue=%s" msgstr "" -#: ../lib/sugar/activity/activity.py:824 -msgid "Keep error" +#: ../src/controlpanel/model/aboutme.py:72 +#, python-format +msgid "stroke: %s" msgstr "" -#: ../lib/sugar/activity/activity.py:825 -msgid "Keep error: all changes will be lost" +#: ../src/controlpanel/model/aboutme.py:74 +#, python-format +msgid "fill: color=%s hue=%s" msgstr "" -#: ../lib/sugar/activity/activity.py:828 -msgid "Don't stop" +#: ../src/controlpanel/model/aboutme.py:76 +#, python-format +msgid "fill: %s" msgstr "" -#: ../lib/sugar/activity/activity.py:831 -msgid "Stop anyway" +#: ../src/controlpanel/model/aboutme.py:87 +msgid "Error in specified color modifiers." msgstr "" -#: ../lib/sugar/graphics/alert.py:164 ../lib/sugar/graphics/alert.py:206 -msgid "Cancel" +#: ../src/controlpanel/model/aboutme.py:90 +msgid "Error in specified colors." msgstr "" -#: ../lib/sugar/graphics/alert.py:168 -msgid "Ok" +#: ../src/controlpanel/model/aboutxo.py:24 +msgid "Not available" msgstr "" -#: ../lib/sugar/graphics/alert.py:216 -msgid "Continue" +#: ../src/controlpanel/model/datetime.py:89 +msgid "Error timezone does not exist." msgstr "" -#: ../lib/sugar/graphics/alert.py:244 -msgid "OK" +#: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 +msgid "Value must be an integer." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:175 -#, python-format -msgid "%d year" +#: ../src/controlpanel/model/language.py:28 +msgid "Could not access ~/.i18n. Create standard settings." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:175 +#: ../src/controlpanel/model/language.py:114 #, python-format -msgid "%d years" +msgid "Language for code=%s could not be determined." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:176 +#: ../src/controlpanel/model/language.py:131 #, python-format -msgid "%d month" +msgid "Sorry I do not speak '%s'." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:176 -#, python-format -msgid "%d months" +#: ../src/controlpanel/model/network.py:62 +msgid "State is unknown." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:177 -#, python-format -msgid "%d week" +#: ../src/controlpanel/model/network.py:82 +msgid "Error in specified radio argument use on/off." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:177 -#, python-format -msgid "%d weeks" +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:178 -#, python-format -msgid "%d day" +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:178 -#, python-format -msgid "%d days" +#: ../src/controlpanel/view/aboutme.py:32 +msgid "About Me" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:179 -#, python-format -msgid "%d hour" +#: ../src/controlpanel/view/aboutme.py:134 +msgid "Click to change your color:" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:179 -#, python-format -msgid "%d hours" +#: ../src/controlpanel/view/aboutxo.py:28 +msgid "About my XO" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:180 -#, python-format -msgid "%d minute" +#: ../src/controlpanel/view/aboutxo.py:59 +msgid "Identity" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:180 -#, python-format -msgid "%d minutes" +#: ../src/controlpanel/view/aboutxo.py:68 +msgid "Serial Number:" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:181 -#, python-format -msgid "%d second" +#: ../src/controlpanel/view/aboutxo.py:91 +msgid "Software" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:181 -#, python-format -msgid "%d seconds" +#: ../src/controlpanel/view/aboutxo.py:100 +msgid "Build:" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:191 -msgid " and " +#: ../src/controlpanel/view/aboutxo.py:115 +msgid "Sugar:" msgstr "" -#: ../lib/sugar/graphics/objectchooser.py:193 -msgid ", " +#: ../src/controlpanel/view/aboutxo.py:130 +msgid "Firmware:" msgstr "" -#: ../shell/controlpanel/control.py:213 -msgid "To apply your changes you have to restart sugar.\n" +#: ../src/controlpanel/view/aboutxo.py:152 +msgid "Copyright and License" msgstr "" -#: ../shell/controlpanel/control.py:267 -msgid "Error in specified color modifiers." +#: ../src/controlpanel/view/aboutxo.py:160 +msgid "" +"© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "" -#: ../shell/controlpanel/control.py:270 -msgid "Error in specified colors." +#: ../src/controlpanel/view/aboutxo.py:167 +msgid "" +"Sugar is the graphical user interface that you are looking at. Sugar is free " +"software, covered by the GNU General Public License, and you are welcome to " +"change it and/or distribute copies of it under certain conditions described " +"therein." msgstr "" -#: ../shell/controlpanel/control.py:307 -msgid "off" +#: ../src/controlpanel/view/aboutxo.py:179 +msgid "Full license:" msgstr "" -#: ../shell/controlpanel/control.py:309 -msgid "on" +#: ../src/controlpanel/view/datetime.py:29 +msgid "Date & Time" msgstr "" -#: ../shell/controlpanel/control.py:310 -msgid "State is unknown." +#: ../src/controlpanel/view/datetime.py:72 +msgid "Timezone" msgstr "" -#: ../shell/controlpanel/control.py:332 -msgid "Error in specified radio argument use on/off." +#: ../src/controlpanel/view/frame.py:28 +msgid "Frame" msgstr "" -#: ../shell/controlpanel/control.py:336 -msgid "Permission denied. You need to be root to run this method." +#: ../src/controlpanel/view/frame.py:30 +msgid "never" msgstr "" -#: ../shell/controlpanel/control.py:366 -msgid "Error in reading timezone" +#: ../src/controlpanel/view/frame.py:31 +msgid "instantaneous" msgstr "" -#: ../shell/controlpanel/control.py:397 +#: ../src/controlpanel/view/frame.py:32 #, python-format -msgid "Error copying timezone (from %s): %s" +msgid "%s seconds" msgstr "" -#: ../shell/controlpanel/control.py:402 -#, python-format -msgid "Changing permission of timezone: %s" +#: ../src/controlpanel/view/frame.py:56 +msgid "Activation Delay" msgstr "" -#: ../shell/controlpanel/control.py:412 -msgid "Error timezone does not exist." +#: ../src/controlpanel/view/frame.py:80 +msgid "Corner" msgstr "" -#: ../shell/controlpanel/control.py:417 ../shell/controlpanel/control.py:436 -#, python-format -msgid "Could not access %s. Create standard settings." +#: ../src/controlpanel/view/frame.py:115 +msgid "Edge" msgstr "" -#: ../shell/controlpanel/control.py:463 -#, python-format -msgid "Language for code=%s could not be determined." +#: ../src/controlpanel/view/language.py:29 +#: ../src/controlpanel/view/language.py:74 +msgid "Language" msgstr "" -#: ../shell/controlpanel/control.py:473 -#, python-format -msgid "Sorry I do not speak '%s'." +#: ../src/controlpanel/view/network.py:28 +msgid "Network" +msgstr "" + +#: ../src/controlpanel/view/network.py:54 +msgid "Wireless" +msgstr "" + +#: ../src/controlpanel/view/network.py:62 +msgid "Turn of the wireless radio to save battery life" +msgstr "Turn off the wireless radio to save battery life" + +#: ../src/controlpanel/view/network.py:75 +msgid "Radio" +msgstr "" + +#: ../src/controlpanel/view/network.py:91 +msgid "Discard network history if you have trouble connecting to the network" +msgstr "" + +#: ../src/controlpanel/view/network.py:100 +msgid "Discard network history" +msgstr "" + +#: ../src/controlpanel/view/network.py:113 +msgid "Mesh" msgstr "" -#: ../shell/view/devices/network/mesh.py:105 +#: ../src/controlpanel/view/network.py:122 +msgid "Server:" +msgstr "" + +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "" + +#: ../src/controlpanel/view/power.py:51 +msgid "Power management" +msgstr "" + +#: ../src/controlpanel/view/power.py:61 +msgid "Automatic power management (increases battery life)" +msgstr "Automatic power management (experimental, increases battery life)" + +#: ../src/controlpanel/view/power.py:89 +msgid "" +"Extreme power management (disables wireless radio, increases battery life)" +msgstr "" + +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "" -#: ../shell/view/devices/network/mesh.py:107 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "" -#: ../shell/view/devices/network/mesh.py:110 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" msgstr "" -#: ../shell/view/devices/network/mesh.py:112 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." msgstr "" -#: ../shell/view/devices/network/mesh.py:115 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "" -#: ../shell/view/devices/network/mesh.py:117 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "" -#: ../shell/view/devices/network/mesh.py:124 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "" -#: ../shell/view/home/HomeBox.py:175 ../shell/view/home/HomeBox.py:216 -msgid "About this XO" +#: ../src/view/frame/activitiestray.py:210 +msgid "Decline" msgstr "" -#: ../shell/view/home/HomeBox.py:222 -msgid "Not available" +#: ../src/view/home/favoritesview.py:296 +msgid "Registration Failed" +msgstr "" + +#: ../src/view/home/favoritesview.py:297 +#, python-format +msgid "%s" +msgstr "" + +#: ../src/view/home/favoritesview.py:299 +msgid "Registration Successful" +msgstr "" + +#: ../src/view/home/favoritesview.py:300 +msgid "You are now registered with your school server." +msgstr "" + +#: ../src/view/home/favoritesview.py:420 +msgid "Control Panel" +msgstr "" + +#: ../src/view/home/favoritesview.py:425 +msgid "Restart" +msgstr "" + +#: ../src/view/home/favoritesview.py:430 +msgid "Shutdown" +msgstr "" + +#: ../src/view/home/favoritesview.py:436 +msgid "Register" +msgstr "" + +#: ../src/view/palettes.py:42 +msgid "Starting..." +msgstr "" + +#: ../src/view/palettes.py:72 +msgid "Stop" +msgstr "" + +#: ../src/view/palettes.py:104 +msgid "Start" +msgstr "" + +#: ../src/view/palettes.py:138 +msgid "Remove favorite" +msgstr "" + +#: ../src/view/palettes.py:142 +msgid "Make favorite" +msgstr "" + +#: ../src/view/palettes.py:191 +msgid "Show contents" +msgstr "" + +#: ../src/view/palettes.py:215 +#, python-format +msgid "%(free_space)d MB Free" msgstr "" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: olpc-sugar\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-07-23 07:44-0400\n" -"PO-Revision-Date: 2008-07-24 12:27-0400\n" +"POT-Creation-Date: 2008-09-01 18:31-0400\n" +"PO-Revision-Date: 2008-08-28 19:35-0400\n" "Last-Translator: Rafael Ortiz <rafael@laptop.org>\n" "Language-Team: Fedora Spanish <fedora-trans-es@redhat.com>\n" "MIME-Version: 1.0\n" @@ -22,19 +22,19 @@ msgstr "" msgid "Name:" msgstr "Nombre:" -#: ../src/intro/intro.py:94 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "Clic para cambiar de color:" -#: ../src/intro/intro.py:145 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Atrás" -#: ../src/intro/intro.py:159 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Hecho" -#: ../src/intro/intro.py:162 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "Siguiente" @@ -46,10 +46,10 @@ msgstr "Eliminar amigo" msgid "Make friend" msgstr "Agregar amigo" -#: ../src/view/BuddyMenu.py:91 +#: ../src/view/BuddyMenu.py:90 #, python-format msgid "Invite to %s" -msgstr "invitar a %s" +msgstr "Invitar a %s" #: ../src/view/clipboardmenu.py:48 msgid "Remove" @@ -67,7 +67,7 @@ msgstr "Abrir" #. TODO: Implement stopping downloads #. self._stop_item.connect('activate', self._stop_item_activate_cb) #. self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:86 +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 msgid "Keep" msgstr "Guardar" @@ -92,48 +92,80 @@ msgstr "Tipo de Autenticación:" msgid "Encryption Type:" msgstr "Tipo de Encriptación:" -#: ../src/view/Shell.py:240 +#: ../src/hardware/schoolserver.py:17 +msgid "Cannot obtain data needed for registration." +msgstr "No se pueden obtener los datos necesarios para el registro" + +#: ../src/hardware/schoolserver.py:31 +msgid "Cannot connect to the server." +msgstr "No se puede conectar al servidor" + +#: ../src/hardware/schoolserver.py:36 +msgid "The server could not complete the request." +msgstr "El servidor no pudo completar la petición " + +#: ../src/view/Shell.py:262 msgid "Screenshot" msgstr "Captura de pantalla" -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:81 msgid "Confirm erase" msgstr "Confirmar borrado" -#: ../src/view/home/HomeBox.py:82 +#: ../src/view/home/HomeBox.py:83 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" -msgstr "Confirmar borrado:Quiere borrar permanentemente%s?" +msgstr "Confirmar borrado: Quiere borrar permanentemente %s?" -#: ../src/view/home/HomeBox.py:89 ../src/view/palettes.py:120 +#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 msgid "Erase" msgstr "Borrar" -#: ../src/view/home/HomeBox.py:215 +#: ../src/view/home/HomeBox.py:120 +msgid "Software Update" +msgstr "Actualización de Software" + +#: ../src/view/home/HomeBox.py:121 +msgid "Update your activities to ensure compatibility with your new software" +msgstr "Actualice sus actividades para asegurar compatibilidad con su nuevo software." + +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 +msgid "Cancel" +msgstr "Cancelar" + +#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:276 +msgid "Later" +msgstr "Después" + +#: ../src/view/home/HomeBox.py:130 +msgid "Check now" +msgstr "Probar ahora" + +#: ../src/view/home/HomeBox.py:266 msgid "List view" msgstr "Vista en lista" -#: ../src/view/home/HomeBox.py:216 -#, fuzzy +#: ../src/view/home/HomeBox.py:267 msgid "<Ctrl>2" -msgstr "<Ctrl>L" +msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:273 +#: ../src/view/home/HomeBox.py:325 msgid "Favorites view" msgstr "Vista de Favoritos" -#: ../src/view/home/HomeBox.py:274 -#, fuzzy +#: ../src/view/home/HomeBox.py:326 msgid "<Ctrl>1" -msgstr "<Ctrl>L" +msgstr "<Ctrl>1" +# TRANS: label for the freeform layout in the favorites view #. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/HomeBox.py:282 +#: ../src/view/home/HomeBox.py:334 msgid "Freeform" msgstr "Forma libre" +# TRANS: label for the ring layout in the favorites view #. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/HomeBox.py:289 +#: ../src/view/home/HomeBox.py:341 msgid "Ring" msgstr "Anillo" @@ -164,9 +196,10 @@ msgstr "Conectando..." msgid "Connected" msgstr "Conectado" -#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "Red Malla" @@ -174,8 +207,8 @@ msgstr "Red Malla" # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:119 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "Desconectando..." @@ -214,7 +247,6 @@ msgstr "Mis parlantes" # la traducción la tome del AlsaMixer de Gnome. #: ../src/view/devices/speaker.py:119 -#, fuzzy msgid "Unmute" msgstr "Dar voz" @@ -222,27 +254,32 @@ msgstr "Dar voz" msgid "Mute" msgstr "Silenciar" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "Desconectado" -#: ../src/view/devices/network/wireless.py:137 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "Canal" -#: ../src/view/frame/zoomtoolbar.py:34 +#: ../src/view/frame/zoomtoolbar.py:37 msgid "Neighborhood" msgstr "Vecindario" -#: ../src/view/frame/zoomtoolbar.py:36 +#: ../src/view/frame/zoomtoolbar.py:39 msgid "Group" msgstr "Grupo" -#: ../src/view/frame/zoomtoolbar.py:38 +#: ../src/view/frame/zoomtoolbar.py:41 msgid "Home" msgstr "Hogar" -#: ../src/view/frame/zoomtoolbar.py:40 +#: ../src/view/frame/zoomtoolbar.py:43 msgid "Activity" msgstr "Actividad" @@ -266,6 +303,7 @@ msgid "sugar-control-panel: %s" msgstr "sugar-control-panel: %s" #: ../src/controlpanel/cmd.py:33 +#, fuzzy msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -275,6 +313,7 @@ msgid "" " -h key show information about this key \n" " -g key get the current value of the key \n" " -s key set the current value for the key \n" +" -c key clear the current value for the key \n" " " msgstr "" "Uso: sugar-control-panel [opción] clave [args ...] \n" @@ -287,35 +326,27 @@ msgstr "" " -s clave establece el valor actual para la clave \n" " " -#: ../src/controlpanel/cmd.py:45 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "Para aplicar sus cambios tiene que reiniciar sugar.\n" -#: ../src/controlpanel/toolbar.py:115 -msgid "Cancel" -msgstr "Cancelar" - -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:294 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 msgid "Ok" msgstr "Ok" -#: ../src/controlpanel/sectionview.py:34 ../src/controlpanel/gui.py:260 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:268 msgid "Changes require restart" msgstr "Los cambios requieren reiniciar" -#: ../src/controlpanel/gui.py:259 +#: ../src/controlpanel/gui.py:267 msgid "Warning" msgstr "Advertencia" -#: ../src/controlpanel/gui.py:263 +#: ../src/controlpanel/gui.py:271 msgid "Cancel changes" msgstr "Cancelar cambios" -#: ../src/controlpanel/gui.py:267 -msgid "Later" -msgstr "Después" - -#: ../src/controlpanel/gui.py:271 +#: ../src/controlpanel/gui.py:280 msgid "Restart now" msgstr "Reiniciar ahora" @@ -368,12 +399,12 @@ msgid "Could not access ~/.i18n. Create standard settings." msgstr "" "No se puede acceder a ~/.i18n. Crear configuración internacional estándar." -#: ../src/controlpanel/model/language.py:104 +#: ../src/controlpanel/model/language.py:110 #, python-format msgid "Language for code=%s could not be determined." msgstr "El lenguaje del código=%s no pudo ser determinado." -#: ../src/controlpanel/model/language.py:121 +#: ../src/controlpanel/model/language.py:127 #, python-format msgid "Sorry I do not speak '%s'." msgstr "Lo siento yo no hablo '%s'." @@ -403,35 +434,59 @@ msgid "About Me" msgstr "Acerca de mÃ." #: ../src/controlpanel/view/aboutme.py:134 -#, fuzzy msgid "Click to change your color:" -msgstr "Clic para cambiar sus colores:" +msgstr "Clic para cambiar su color:" -#: ../src/controlpanel/view/aboutxo.py:26 +#: ../src/controlpanel/view/aboutxo.py:28 msgid "About my XO" msgstr "Acerca de mi XO" -#: ../src/controlpanel/view/aboutxo.py:47 +#: ../src/controlpanel/view/aboutxo.py:59 msgid "Identity" msgstr "Identidad" -#: ../src/controlpanel/view/aboutxo.py:56 +#: ../src/controlpanel/view/aboutxo.py:68 msgid "Serial Number:" msgstr "Número de Serie:" -#: ../src/controlpanel/view/aboutxo.py:79 +#: ../src/controlpanel/view/aboutxo.py:91 msgid "Software" msgstr "Software" -#: ../src/controlpanel/view/aboutxo.py:88 -#, fuzzy +# Por ahora.. +#: ../src/controlpanel/view/aboutxo.py:100 msgid "Build:" -msgstr "Ensamble" +msgstr "Ensamble:" + +#: ../src/controlpanel/view/aboutxo.py:115 +msgid "Sugar:" +msgstr "" -#: ../src/controlpanel/view/aboutxo.py:103 +#: ../src/controlpanel/view/aboutxo.py:130 msgid "Firmware:" msgstr "Firmware" +#: ../src/controlpanel/view/aboutxo.py:152 +msgid "Copyright and License" +msgstr "" + +#: ../src/controlpanel/view/aboutxo.py:160 +msgid "" +"© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." +msgstr "" + +#: ../src/controlpanel/view/aboutxo.py:166 +msgid "" +"Sugar is the graphical user interface that you are looking at. Sugar is free " +"software, covered by the GNU General Public License, and you are welcome to " +"change it and/or distribute copies of it under certain conditions described " +"therein." +msgstr "" + +#: ../src/controlpanel/view/aboutxo.py:178 +msgid "Full license:" +msgstr "" + #: ../src/controlpanel/view/datetime.py:29 msgid "Date & Time" msgstr "Fecha y Hora" @@ -513,34 +568,32 @@ msgstr "" "Manejo extremo de energÃa (deshabilita el radio wireless, incrementa la vida " "de la baterÃa)" -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "Conectado a un enlace escolar de red malla" # "portal malla de colegio", en Castellano de España suena fatal... ¿Realmente se quiere decir malla? -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "Buscando un enlace escolar de red malla..." -#: ../src/view/devices/network/mesh.py:116 -#, fuzzy +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" -msgstr "Conectado a un enlace individual de red malla" +msgstr "Conectado a un Portal Malla XO" -#: ../src/view/devices/network/mesh.py:118 -#, fuzzy +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." -msgstr "Buscando un enlace individual de red malla..." +msgstr "Buscando un Portal Malla XO..." -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "Conectado a una Red Malla Simple" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "Empezando una Red Malla Simple" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "Red Malla Desconocida" @@ -548,36 +601,36 @@ msgstr "Red Malla Desconocida" msgid "Decline" msgstr "Rechazar" -#: ../src/view/home/favoritesview.py:285 +#: ../src/view/home/favoritesview.py:287 msgid "Registration Failed" msgstr "Registro Fallido" -#: ../src/view/home/favoritesview.py:286 +#: ../src/view/home/favoritesview.py:288 #, python-format msgid "%s" -msgstr "" +msgstr "%s" -#: ../src/view/home/favoritesview.py:288 +#: ../src/view/home/favoritesview.py:290 msgid "Registration Successful" msgstr "Registro Exitoso" -#: ../src/view/home/favoritesview.py:289 +#: ../src/view/home/favoritesview.py:291 msgid "You are now registered with your school server." msgstr "Ahora estas registrado en el servidor de colegio" -#: ../src/view/home/favoritesview.py:405 +#: ../src/view/home/favoritesview.py:407 msgid "Control Panel" msgstr "Panel de Control" -#: ../src/view/home/favoritesview.py:416 +#: ../src/view/home/favoritesview.py:418 msgid "Restart" msgstr "Reiniciar" -#: ../src/view/home/favoritesview.py:421 +#: ../src/view/home/favoritesview.py:423 msgid "Shutdown" msgstr "Apagar" -#: ../src/view/home/favoritesview.py:427 +#: ../src/view/home/favoritesview.py:429 msgid "Register" msgstr "Registro" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: sugar\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-09-27 05:45-0400\n" +"POT-Creation-Date: 2008-09-01 18:31-0400\n" +"PO-Revision-Date: 2008-09-10 00:12-0400\n" "Last-Translator: samy boutayeb <s.boutayeb@free.fr>\n" "Language-Team: French <traduc@traduc.org>\n" "MIME-Version: 1.0\n" @@ -15,44 +15,44 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Pootle 1.1.0rc2\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "Nom :" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "Cliquer pour changer de couleur :" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Précédent" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Accepter" -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "Suivant" -#: ../src/view/BuddyMenu.py:60 +#: ../src/view/BuddyMenu.py:58 msgid "Remove friend" msgstr "Retirer de mes amis" -#: ../src/view/BuddyMenu.py:63 +#: ../src/view/BuddyMenu.py:61 msgid "Make friend" msgstr "Ajouter à mes amis" -#: ../src/view/BuddyMenu.py:92 +#: ../src/view/BuddyMenu.py:90 #, python-format msgid "Invite to %s" msgstr "Inviter à %s" -#: ../src/view/clipboardmenu.py:51 +#: ../src/view/clipboardmenu.py:48 msgid "Remove" msgstr "Retirer" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" msgstr "Ouvrir" @@ -60,18 +60,22 @@ msgstr "Ouvrir" # TODO: Implement stopping downloads # self._stop_item.connect('activate', self._stop_item_activate_cb) # self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 msgid "Keep" msgstr "Conserver" -#: ../src/view/clipboardmenu.py:83 +#: ../src/view/clipboardmenu.py:84 msgid "Open with" msgstr "Ouvrir avec" -#: ../src/view/clipboardmenu.py:228 +#: ../src/view/clipboardmenu.py:216 #, python-format -msgid "%s clipping" -msgstr "%s coupure" +msgid "Clipboard object: %s." +msgstr "Objet dans le presse-papier : %s." #: ../src/hardware/keydialog.py:150 msgid "Key Type:" @@ -87,71 +91,82 @@ msgstr "Type d'encryptage :" #: ../src/hardware/schoolserver.py:17 msgid "Cannot obtain data needed for registration." -msgstr "Impossible d'obtenir les données nécessaires à l'enregistrement." +msgstr "Impossible d'obtenir certaines données nécessaires à l'enregistrement." #: ../src/hardware/schoolserver.py:31 msgid "Cannot connect to the server." -msgstr "Impossible de se connecter au serveur." +msgstr "Impossible de se connecter au serveu." #: ../src/hardware/schoolserver.py:36 msgid "The server could not complete the request." msgstr "Le serveur n'a pas pu achever la requête." -#: ../src/view/Shell.py:251 +#: ../src/view/Shell.py:262 msgid "Screenshot" msgstr "Capture d'écran" -#: ../src/view/home/HomeBox.py:78 +#: ../src/view/home/HomeBox.py:81 msgid "Confirm erase" msgstr "Confirmer la suppression" # Conformer la suppression : faut-il supprimer %s définitivement ? -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:83 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "Confirmer la suppression : faut-il supprimer %s définitivement ?" -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 +#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 msgid "Erase" msgstr "Supprimer" -#: ../src/view/home/HomeBox.py:117 +#: ../src/view/home/HomeBox.py:120 msgid "Software Update" msgstr "Mise à jour logicielle" -#: ../src/view/home/HomeBox.py:118 +#: ../src/view/home/HomeBox.py:121 msgid "Update your activities to ensure compatibility with your new software" msgstr "Actualiser les activités pour assurer la compatibilité logicielle" -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "Annuler" -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 +#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:276 msgid "Later" msgstr "Plus tard" -#: ../src/view/home/HomeBox.py:127 +#: ../src/view/home/HomeBox.py:130 msgid "Check now" msgstr "Vérifier maintenant" -#: ../src/view/home/HomeBox.py:261 +#: ../src/view/home/HomeBox.py:266 msgid "List view" msgstr "Écran liste" -#: ../src/view/home/HomeBox.py:262 +#: ../src/view/home/HomeBox.py:267 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:320 +#: ../src/view/home/HomeBox.py:325 msgid "Favorites view" msgstr "Écran favoris" -#: ../src/view/home/HomeBox.py:321 +#: ../src/view/home/HomeBox.py:326 msgid "<Ctrl>1" msgstr "<Ctrl>1" +# TRANS: label for the freeform layout in the favorites view +#. TRANS: label for the freeform layout in the favorites view +#: ../src/view/home/HomeBox.py:334 +msgid "Freeform" +msgstr "Libre" + +# TRANS: label for the ring layout in the favorites view +#. TRANS: label for the ring layout in the favorites view +#: ../src/view/home/HomeBox.py:341 +msgid "Ring" +msgstr "Concentrique" + #: ../src/view/home/MeshBox.py:97 msgid "Connect" msgstr "Connecter" @@ -168,19 +183,20 @@ msgstr "Déconnecter" msgid "Disconnecting..." msgstr "Déconnexion..." -#: ../src/view/home/MeshBox.py:159 +#: ../src/view/home/MeshBox.py:152 msgid "Connecting..." msgstr "Connexion..." # TODO: show the channel number #. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 +#: ../src/view/home/MeshBox.py:159 msgid "Connected" msgstr "Connecté" -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "Réseau maillé" @@ -188,18 +204,16 @@ msgstr "Réseau maillé" # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "Déconnexion..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 msgid "Resume" msgstr "Reprendre" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" msgstr "Rejoindre" @@ -228,19 +242,24 @@ msgstr "Charge complète" msgid "My Speakers" msgstr "Haut-parleurs" -#: ../src/view/devices/speaker.py:125 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" msgstr "Activer le son" -#: ../src/view/devices/speaker.py:128 +#: ../src/view/devices/speaker.py:122 msgid "Mute" msgstr "Mettre en sourdine" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "Adresse IP : %s" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "Déconnecté" -#: ../src/view/devices/network/wireless.py:143 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "Canal" @@ -279,9 +298,7 @@ msgstr "sugar-control-panel: key=%s n'est pas une option disponible" msgid "sugar-control-panel: %s" msgstr "sugar-control-panel: %s" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 +#: ../src/controlpanel/cmd.py:33 msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -294,121 +311,166 @@ msgid "" " -c key clear the current value for the key \n" " " msgstr "" -"Usage: sugar-control-panel [ option ] clé [ args ... ] \n" +"Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Contrôle de l'environnement sugar. \n" " Options: \n" " -h afficher ce message d'aide et quitter \n" " -l afficher la liste des options disponibles \n" -" -h clé afficher les informations sur cette clé \n" -" -g clé obtenir la valeur actuelle associée à cette clé \n" -" -s clé définir la valeur actuelle de cette clé \n" +" -h clef afficher les informations sur cette clé \n" +" -g clef obtenir la valeur actuelle associée à cette clé \n" +" -s clef définir la valeur actuelle de cette clé \n" " " -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "Redémarrer sugar pour que les changements prennent effet.\n" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 msgid "Ok" msgstr "Ok" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:268 msgid "Changes require restart" msgstr "Relancer pour valider" -#: ../src/controlpanel/gui.py:264 +#: ../src/controlpanel/gui.py:267 msgid "Warning" msgstr "Attention" -#: ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/gui.py:271 msgid "Cancel changes" msgstr "Abandonner" -#: ../src/controlpanel/gui.py:277 +#: ../src/controlpanel/gui.py:280 msgid "Restart now" msgstr "Maintenant" -#: ../src/controlpanel/aboutme/model.py:44 +#: ../src/controlpanel/model/aboutme.py:44 msgid "You must enter a name." msgstr "Vous devez indiquer un nom." -#: ../src/controlpanel/aboutme/model.py:69 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format msgid "stroke: color=%s hue=%s" msgstr "stroke: color=%s hue=%s" -#: ../src/controlpanel/aboutme/model.py:72 +#: ../src/controlpanel/model/aboutme.py:72 #, python-format msgid "stroke: %s" msgstr "stroke: %s" -#: ../src/controlpanel/aboutme/model.py:74 +#: ../src/controlpanel/model/aboutme.py:74 #, python-format msgid "fill: color=%s hue=%s" msgstr "fill: color=%s hue=%s" -#: ../src/controlpanel/aboutme/model.py:76 +#: ../src/controlpanel/model/aboutme.py:76 #, python-format msgid "fill: %s" msgstr "fill: %s" -#: ../src/controlpanel/aboutme/model.py:87 +#: ../src/controlpanel/model/aboutme.py:87 msgid "Error in specified color modifiers." msgstr "Erreur dans les modificateurs de couleur spécifiés." -#: ../src/controlpanel/aboutme/model.py:90 +#: ../src/controlpanel/model/aboutme.py:90 msgid "Error in specified colors." msgstr "Erreur dans les couleurs spécifiées." -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 +#: ../src/controlpanel/model/aboutxo.py:24 +msgid "Not available" +msgstr "Non disponible" + +#: ../src/controlpanel/model/datetime.py:85 +msgid "Error timezone does not exist." +msgstr "Erreur : la zone temporelle n'existe pas." + +#: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 +msgid "Value must be an integer." +msgstr "La valeur doit être un entier." + +#: ../src/controlpanel/model/language.py:28 +msgid "Could not access ~/.i18n. Create standard settings." +msgstr "Accès impossible à ~/.i18n. Création de paramètres par défaut." + +#: ../src/controlpanel/model/language.py:110 +#, python-format +msgid "Language for code=%s could not be determined." +msgstr "La langue associée au code = %s n'a pas pu être déterminée." + +#: ../src/controlpanel/model/language.py:127 +#, python-format +msgid "Sorry I do not speak '%s'." +msgstr "Désolé je ne parle pas '%s'." + +#: ../src/controlpanel/model/network.py:48 +msgid "You must enter a server." +msgstr "Vous devez indiquer un serveur." + +#: ../src/controlpanel/model/network.py:63 +msgid "State is unknown." +msgstr "État inconnu." + +#: ../src/controlpanel/model/network.py:83 +msgid "Error in specified radio argument use on/off." +msgstr "Argument 'radio' spécifié incorrect. Utiliser marche/arrêt." + +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." +msgstr "Erreur dans l'argument gestion de l'alimentation automatique" + +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." +msgstr "Erreur dans l'argument gestion de l'alimentation extrême" + +#: ../src/controlpanel/view/aboutme.py:32 msgid "About Me" msgstr "Moi" -#: ../src/controlpanel/aboutme/view.py:134 +#: ../src/controlpanel/view/aboutme.py:134 msgid "Click to change your color:" msgstr "Cliquer pour changer de couleur :" -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "Non disponible" +#: ../src/controlpanel/view/aboutxo.py:28 +msgid "About my XO" +msgstr "Mon XO" -#: ../src/controlpanel/aboutxo/view.py:55 +#: ../src/controlpanel/view/aboutxo.py:59 msgid "Identity" msgstr "Identité" -#: ../src/controlpanel/aboutxo/view.py:64 +#: ../src/controlpanel/view/aboutxo.py:68 msgid "Serial Number:" msgstr "Numéro de série :" -#: ../src/controlpanel/aboutxo/view.py:87 +#: ../src/controlpanel/view/aboutxo.py:91 msgid "Software" msgstr "Logiciel" -#: ../src/controlpanel/aboutxo/view.py:96 +#: ../src/controlpanel/view/aboutxo.py:100 msgid "Build:" msgstr "Version :" -#: ../src/controlpanel/aboutxo/view.py:111 +#: ../src/controlpanel/view/aboutxo.py:115 msgid "Sugar:" msgstr "Sugar :" -#: ../src/controlpanel/aboutxo/view.py:126 +#: ../src/controlpanel/view/aboutxo.py:130 msgid "Firmware:" msgstr "Micrologiciel :" -#: ../src/controlpanel/aboutxo/view.py:148 +#: ../src/controlpanel/view/aboutxo.py:152 msgid "Copyright and License" msgstr "Copyright et licence" -#: ../src/controlpanel/aboutxo/view.py:156 +#: ../src/controlpanel/view/aboutxo.py:160 msgid "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "" "© 2008 One Laptop per Child Association Inc ; Red Hat Inc ; et " "contributeurs." -#: ../src/controlpanel/aboutxo/view.py:163 +#: ../src/controlpanel/view/aboutxo.py:166 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -420,237 +482,153 @@ msgstr "" "License). Vous êtes autorisé à le modifier et/ou à en distribuer des copies " "aux conditions spécifiées." -#: ../src/controlpanel/aboutxo/view.py:175 +#: ../src/controlpanel/view/aboutxo.py:178 msgid "Full license:" msgstr "Licence complète :" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "Mon XO" - -#: ../src/controlpanel/datetime/model.py:89 -msgid "Error timezone does not exist." -msgstr "Erreur : la zone temporelle n'existe pas." +#: ../src/controlpanel/view/datetime.py:29 +msgid "Date & Time" +msgstr "Date & heure" -#: ../src/controlpanel/datetime/view.py:68 +#: ../src/controlpanel/view/datetime.py:72 msgid "Timezone" msgstr "Fuseau horaire" -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "Date & heure" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "La valeur doit être un entier." +#: ../src/controlpanel/view/frame.py:28 +msgid "Frame" +msgstr "Cadre" -#: ../src/controlpanel/frame/view.py:26 +#: ../src/controlpanel/view/frame.py:30 msgid "never" msgstr "jamais" -#: ../src/controlpanel/frame/view.py:27 +#: ../src/controlpanel/view/frame.py:31 msgid "instantaneous" msgstr "immédiat" -#: ../src/controlpanel/frame/view.py:28 +#: ../src/controlpanel/view/frame.py:32 #, python-format msgid "%s seconds" msgstr "%s secondes" -#: ../src/controlpanel/frame/view.py:52 +#: ../src/controlpanel/view/frame.py:56 msgid "Activation Delay" msgstr "Délai d'activation" -#: ../src/controlpanel/frame/view.py:76 +#: ../src/controlpanel/view/frame.py:80 msgid "Corner" msgstr "Coin" -#: ../src/controlpanel/frame/view.py:111 +#: ../src/controlpanel/view/frame.py:115 msgid "Edge" msgstr "Bord" -#: ../src/controlpanel/frame/__init__.py:21 -msgid "Frame" -msgstr "Cadre" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "Accès impossible à ~/.i18n. Création de paramètres par défaut." - -#: ../src/controlpanel/language/model.py:114 -#, python-format -msgid "Language for code=%s could not be determined." -msgstr "La langue associée au code = %s n'a pas pu être déterminée." - -#: ../src/controlpanel/language/model.py:131 -#, python-format -msgid "Sorry I do not speak '%s'." -msgstr "Désolé je ne parle pas '%s'." - -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 +#: ../src/controlpanel/view/language.py:29 +#: ../src/controlpanel/view/language.py:74 msgid "Language" msgstr "Langue" -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "État inconnu." - -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "Argument 'radio' spécifié incorrect. Utiliser marche/arrêt." - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 +#: ../src/controlpanel/view/network.py:28 msgid "Network" msgstr "Réseau" -#: ../src/controlpanel/network/view.py:54 +#: ../src/controlpanel/view/network.py:53 msgid "Wireless" msgstr "Réseau sans fil" -#: ../src/controlpanel/network/view.py:62 -msgid "Turn of the wireless radio to save battery life" -msgstr "Désactiver la radio sans fil pour prolonger la batterie" - -#: ../src/controlpanel/network/view.py:75 -msgid "Radio" -msgstr "Radio" - -#: ../src/controlpanel/network/view.py:91 -msgid "Discard network history if you have trouble connecting to the network" -msgstr "" -"Ignorer l'historique du réseau si vous avez du mal à vous connecter au " -"réseau" +#: ../src/controlpanel/view/network.py:61 +msgid "Radio:" +msgstr "Radio :" -#: ../src/controlpanel/network/view.py:100 -msgid "Discard network history" -msgstr "Ignorer l'historique du réseau" - -#: ../src/controlpanel/network/view.py:113 +#: ../src/controlpanel/view/network.py:94 msgid "Mesh" msgstr "Réseau maillé" -#: ../src/controlpanel/network/view.py:122 +#: ../src/controlpanel/view/network.py:103 msgid "Server:" msgstr "Serveur :" -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "Erreur dans l'argument gestion de l'alimentation automatique" - -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "Erreur dans l'argument gestion de l'alimentation extrême" +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "Alimentation" -#: ../src/controlpanel/power/view.py:47 +#: ../src/controlpanel/view/power.py:51 msgid "Power management" msgstr "Gestion de l'alimentation" -#: ../src/controlpanel/power/view.py:57 +#: ../src/controlpanel/view/power.py:61 msgid "Automatic power management (increases battery life)" msgstr "Gestion automatique de l'alimentation (prolonge la batterie)" -#: ../src/controlpanel/power/view.py:85 +#: ../src/controlpanel/view/power.py:89 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Extreme power management (disables wireless radio, increases battery life)" msgstr "" "Gestion extrême de l'alimentation (désactive la radio sans fil, prolonge la " -"durée de vie de la batterie)" - -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "Alimentation" +"batterie)" -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "Connecté au portail du réseau maillé d'école" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "Recherche un portail de réseau maillé d'école..." -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" msgstr "Connecté au portail de réseau maillé de XO" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." msgstr "Recherche un portail de réseau maillé de XO..." -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "Connecté à un réseau maillé simple" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "Démarre un réseau maillé simple" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "Réseau maillé inconnu" -#: ../src/view/frame/activitiestray.py:211 +#: ../src/view/frame/activitiestray.py:210 msgid "Decline" msgstr "Refuser" -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "Libre" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "Concentrique" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "Spirale" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "Boîte" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "Triangle" - -#: ../src/view/home/favoritesview.py:295 +#: ../src/view/home/favoritesview.py:287 msgid "Registration Failed" msgstr "Echec de l'enregistrement" -#: ../src/view/home/favoritesview.py:296 +#: ../src/view/home/favoritesview.py:288 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:298 +#: ../src/view/home/favoritesview.py:290 msgid "Registration Successful" msgstr "Enregistrement réussi" -#: ../src/view/home/favoritesview.py:299 +#: ../src/view/home/favoritesview.py:291 msgid "You are now registered with your school server." msgstr "Vous êtes maintenant enregistré sur le serveur de l'école" -#: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "Configuration" +#: ../src/view/home/favoritesview.py:407 +msgid "Control Panel" +msgstr "Panneau de contrôle" -#: ../src/view/home/favoritesview.py:425 +#: ../src/view/home/favoritesview.py:418 msgid "Restart" msgstr "Redémarrer" -#: ../src/view/home/favoritesview.py:430 +#: ../src/view/home/favoritesview.py:423 msgid "Shutdown" msgstr "Éteindre" -#: ../src/view/home/favoritesview.py:436 +#: ../src/view/home/favoritesview.py:429 msgid "Register" msgstr "S'enregistrer" @@ -662,161 +640,33 @@ msgstr "Démarrage..." msgid "Stop" msgstr "Arrêter" -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 +#: ../src/view/palettes.py:104 msgid "Start" msgstr "Lancer" -#: ../src/view/palettes.py:138 +#: ../src/view/palettes.py:132 msgid "Remove favorite" msgstr "Retirer le favori" -#: ../src/view/palettes.py:142 +#: ../src/view/palettes.py:136 msgid "Make favorite" msgstr "Ajouter aux favoris" -#: ../src/view/palettes.py:191 +#: ../src/view/palettes.py:185 msgid "Show contents" msgstr "Afficher les contenus" -#: ../src/view/palettes.py:215 +#: ../src/view/palettes.py:209 #, python-format msgid "%(free_space)d MB Free" msgstr "%(free_space)d Mo de libre" -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "Rechercher" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "N'importe quand" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "Aujourd'hui" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "Depuis hier" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "Depuis une semaine" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "Depuis un mois" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "Depuis une année" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "Tout le monde" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "Mes amis" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "Ma classe" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "Tout" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "Copier" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "Sans titre" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "Log" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "Pas de prévisualisation" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "Participants :" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "Description :" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "Étiquettes :" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "Choisir un objet" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "Fermer" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "Démonter" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "Sans date" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "Le journal est vide" - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "Aucune entrée correspondante" - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "Votre journal est plein" - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." -msgstr "" -"Effacer des entrées anciennes du Journal pour libérer de la place pour les " -"nouvelles entrées." - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "Montre le Journal" - -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "Objet dans le presse-papier : %s." - -#~ msgid "You must enter a server." -#~ msgstr "Vous devez indiquer un serveur." - -#~ msgid "Control Panel" -#~ msgstr "Panneau de contrôle" - #~ msgid "© 2008 One Laptop per Child Assocation " #~ msgstr "© 2008 One Laptop per Child Assocation " #, fuzzy #~ msgid "Sugar is the graphical user interface that " -#~ msgstr "Sugar est l'interface utilisateur graphique que" +#~ msgstr "Sugar est l'interface utiliateur graphique que" #~ msgid "<Ctrl>R" #~ msgstr "<Ctrl>R" @@ -921,6 +771,9 @@ msgstr "Montre le Journal" #~ msgid "Share" #~ msgstr "Partager" +#~ msgid "Close" +#~ msgstr "Fermer" + #, python-format #~ msgid "%s Activity" #~ msgstr "Activité %s" @@ -940,6 +793,9 @@ msgstr "Montre le Journal" #~ msgid "Redo" #~ msgstr "Répéter" +#~ msgid "Copy" +#~ msgstr "Copier" + #~ msgid "Paste" #~ msgstr "Coller" @@ -6,9 +6,9 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-06-21 00:30-0400\n" -"PO-Revision-Date: 2008-03-12 09:14-0400\n" -"Last-Translator: Jude Augusma <jayme2901@yahoo.com>\n" +"POT-Creation-Date: 2008-08-19 17:12-0400\n" +"PO-Revision-Date: 2008-08-18 16:47-0400\n" +"Last-Translator: lacrete <le_teaseur@hotmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,36 +17,36 @@ msgstr "" #: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" -msgstr "Non" +msgstr "Non:" -#: ../src/intro/intro.py:94 +#: ../src/intro/intro.py:97 msgid "Click to change color:" -msgstr "Klike pou chanje koulè" +msgstr "Klike pou chanje koulè:" -#: ../src/intro/intro.py:145 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Retounen" -#: ../src/intro/intro.py:159 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Fini" -#: ../src/intro/intro.py:162 +#: ../src/intro/intro.py:165 msgid "Next" -msgstr "Prochen" +msgstr "Pwochen" #: ../src/view/BuddyMenu.py:58 msgid "Remove friend" -msgstr "Retire zanmi" +msgstr "Retire zanmi " #: ../src/view/BuddyMenu.py:61 msgid "Make friend" -msgstr "Fè zanmi" +msgstr "Fè zanmi " #: ../src/view/BuddyMenu.py:91 #, python-format msgid "Invite to %s" -msgstr "Envite sou %s" +msgstr "Envite nan %s" #: ../src/view/clipboardmenu.py:48 msgid "Remove" @@ -54,73 +54,119 @@ msgstr "Retire" #: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" -msgstr "Louvri" +msgstr "Ouvri" #. self._stop_item = MenuItem(_('Stop download'), 'stock-close') #. TODO: Implement stopping downloads #. self._stop_item.connect('activate', self._stop_item_activate_cb) #. self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:63 +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 msgid "Keep" -msgstr "" +msgstr "Kenbe" #: ../src/view/clipboardmenu.py:84 msgid "Open with" -msgstr "" +msgstr "Ouvri ak" -#: ../src/view/clipboardmenu.py:212 +#: ../src/view/clipboardmenu.py:216 #, python-format msgid "Clipboard object: %s." msgstr "Objè ekritwa: %s." #: ../src/hardware/keydialog.py:150 msgid "Key Type:" -msgstr "Tip kle:" +msgstr "kalite kle:" #: ../src/hardware/keydialog.py:170 msgid "Authentication Type:" -msgstr "Tip otantifikasyon:" +msgstr "Kalite otantifikasyon:" #: ../src/hardware/keydialog.py:251 msgid "Encryption Type:" -msgstr "Tip kod sekrè" +msgstr "Kalite kod sekrè" + +#: ../src/hardware/schoolserver.py:17 +msgid "Cannot obtain data needed for registration." +msgstr "" + +#: ../src/hardware/schoolserver.py:31 +msgid "Cannot connect to the server." +msgstr "" -#: ../src/view/Shell.py:262 +#: ../src/hardware/schoolserver.py:36 +msgid "The server could not complete the request." +msgstr "" + +#: ../src/view/Shell.py:240 msgid "Screenshot" msgstr "Ekran projektwa" -#: ../src/view/home/HomeBox.py:147 -msgid "List view" -msgstr "" +#: ../src/view/home/HomeBox.py:81 +msgid "Confirm erase" +msgstr "Konfime sa ou efase a" -#: ../src/view/home/HomeBox.py:148 -msgid "<Ctrl>L" +#: ../src/view/home/HomeBox.py:83 +#, python-format +msgid "Confirm erase: Do you want to permanently erase %s?" +msgstr "Konfime sa ou efase a: ou vle retire'l net %s?" + +#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 +msgid "Erase" +msgstr "Efase" + +#: ../src/view/home/HomeBox.py:120 +msgid "Software Update" msgstr "" -#: ../src/view/home/HomeBox.py:204 -msgid "Favorites view" +#: ../src/view/home/HomeBox.py:121 +msgid "Update your activities to ensure compatibility with your new software" msgstr "" -#: ../src/view/home/HomeBox.py:205 -msgid "<Ctrl>R" +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 +msgid "Cancel" +msgstr "Anile" + +#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:275 +msgid "Later" +msgstr "Pi ta" + +#: ../src/view/home/HomeBox.py:130 +msgid "Check now" msgstr "" +#: ../src/view/home/HomeBox.py:266 +msgid "List view" +msgstr "Gade lis" + +#: ../src/view/home/HomeBox.py:267 +msgid "<Ctrl>2" +msgstr "<Ctrl>2" + +#: ../src/view/home/HomeBox.py:325 +msgid "Favorites view" +msgstr "Fas prefere" + +#: ../src/view/home/HomeBox.py:326 +msgid "<Ctrl>1" +msgstr "<Ctrl>1" + +# TRANS: label for the freeform layout in the favorites view #. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/HomeBox.py:211 +#: ../src/view/home/HomeBox.py:334 msgid "Freeform" -msgstr "" +msgstr "Fòm lib" +# TRANS: label for the ring layout in the favorites view #. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/HomeBox.py:218 +#: ../src/view/home/HomeBox.py:341 msgid "Ring" -msgstr "" +msgstr "Zanno" #: ../src/view/home/MeshBox.py:97 msgid "Connect" -msgstr "" +msgstr "Konekte" #: ../src/view/home/MeshBox.py:106 -#, fuzzy msgid "Disconnect" msgstr "Dekonekte" @@ -129,101 +175,99 @@ msgstr "Dekonekte" # method for a device either (for various reasons) so this doesn't # have a good mapping #: ../src/view/home/MeshBox.py:118 -#, fuzzy msgid "Disconnecting..." -msgstr "Dekonekte..." +msgstr "An dekoneksyon..." # Only show disconnect when there's a mesh device, because mesh takes # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping #: ../src/view/home/MeshBox.py:152 -#, fuzzy msgid "Connecting..." -msgstr "Dekonekte..." +msgstr "An koneksyon..." #. TODO: show the channel number #: ../src/view/home/MeshBox.py:159 msgid "Connected" -msgstr "" +msgstr "Konekte" -#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:38 -#: ../src/view/devices/network/mesh.py:65 -#: ../src/view/devices/network/mesh.py:69 +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:41 +#: ../src/view/devices/network/mesh.py:68 +#: ../src/view/devices/network/mesh.py:72 msgid "Mesh Network" -msgstr "Rezo " +msgstr "Rezo maye" # Only show disconnect when there's a mesh device, because mesh takes # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:116 -#: ../src/view/devices/network/mesh.py:86 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:119 +#: ../src/view/devices/network/mesh.py:89 msgid "Disconnect..." msgstr "Dekonekte..." -#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:60 +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 msgid "Resume" msgstr "Repwann" -#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:219 +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" -msgstr "Rankontre" +msgstr "Rejwen'n" -#: ../src/view/devices/battery.py:42 +#: ../src/view/devices/battery.py:45 msgid "My Battery" -msgstr "" +msgstr "Batri-m" -#: ../src/view/devices/battery.py:111 +#: ../src/view/devices/battery.py:114 msgid "Charging" -msgstr "" +msgstr "Ap chaje" -#: ../src/view/devices/battery.py:114 +#: ../src/view/devices/battery.py:117 msgid "Very little power remaining" -msgstr "" +msgstr "Yon ti kras chaj ki rete" -#: ../src/view/devices/battery.py:120 +#: ../src/view/devices/battery.py:123 #, python-format msgid "%(hour)d:%(min).2d remaining" -msgstr "" +msgstr "%(hour)d:%(min).2d ki rete" -#: ../src/view/devices/battery.py:124 +#: ../src/view/devices/battery.py:127 msgid "Charged" -msgstr "" +msgstr "Fin chaje" -#: ../src/view/devices/speaker.py:40 +#: ../src/view/devices/speaker.py:44 msgid "My Speakers" -msgstr "" +msgstr "Opalè m' yo" -#: ../src/view/devices/speaker.py:104 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" -msgstr "" +msgstr "Aktive son an" -#: ../src/view/devices/speaker.py:107 +#: ../src/view/devices/speaker.py:122 msgid "Mute" -msgstr "" +msgstr "Dezaktive son an" -#: ../src/view/devices/network/wireless.py:64 +#: ../src/view/devices/network/wireless.py:67 msgid "Disconnected" msgstr "Dekonekte" -#: ../src/view/devices/network/wireless.py:134 +#: ../src/view/devices/network/wireless.py:137 msgid "Channel" msgstr "Chanèl" -#: ../src/view/frame/zoomtoolbar.py:34 +#: ../src/view/frame/zoomtoolbar.py:37 msgid "Neighborhood" msgstr "Vwazinaj" -#: ../src/view/frame/zoomtoolbar.py:36 +#: ../src/view/frame/zoomtoolbar.py:39 msgid "Group" msgstr "Gwoup" -#: ../src/view/frame/zoomtoolbar.py:38 +#: ../src/view/frame/zoomtoolbar.py:41 msgid "Home" msgstr "Lakay" -#: ../src/view/frame/zoomtoolbar.py:40 +#: ../src/view/frame/zoomtoolbar.py:43 msgid "Activity" msgstr "Aktivite" @@ -233,6 +277,8 @@ msgid "" "sugar-control-panel: WARNING, found more than one option with the same name: " "%s module: %r" msgstr "" +"Sugar-control-panel: Atansyon, yo jwenn plizyè opsyon ak yon menm non: %s " +"modil: %r" #: ../src/controlpanel/cmd.py:28 #, python-format @@ -245,6 +291,7 @@ msgid "sugar-control-panel: %s" msgstr "Sugar-kontwòl-panèl: %s" #: ../src/controlpanel/cmd.py:33 +#, fuzzy msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -254,81 +301,74 @@ msgid "" " -h key show information about this key \n" " -g key get the current value of the key \n" " -s key set the current value for the key \n" +" -c key clear the current value for the key \n" " " msgstr "" "Sèvi: Sugar-Kontwòl-panèl [opsyon] kle [args ... ]\n" -" Kontwòl pou anvironman sugar. \n" -" opsyon: \n" -" -h montre mesaj èd sa epi soti \n" -" -l fè lis tout opsyon disponib yo \n" -" -h kle montre enfòmasyon sou kle sa \n" -" -g kle pwan valè kouran kle-a \n" -" -s kle fikse valè Kouran pou kle-a \n" -" " - -#: ../src/controlpanel/cmd.py:45 +"\tKontwòl pou anvironman sugar. \n" +"\topsyon: \n" +"\t-h\tmontre mesaj èd sa epi soti \n" +"\t-l\tfè lis tout opsyon disponib yo \n" +"\t-h kle\tmontre enfòmasyon sou kle sa \n" +"\t-g kle\tpwan valè kouran kle-a \n" +"\t-s kle\tfikse valè Kouran pou kle-a \n" +"\t" + +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "Pou aplike chanjman ou yo ou bezwen reyinisyalize program nan.\n" -#: ../src/controlpanel/toolbar.py:115 -msgid "Cancel" -msgstr "" - -#: ../src/controlpanel/toolbar.py:121 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 msgid "Ok" -msgstr "" +msgstr "Ok" -#: ../src/controlpanel/sectionview.py:34 ../src/controlpanel/gui.py:250 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:267 msgid "Changes require restart" -msgstr "" +msgstr "Redemare pou aplike chanjman yo" -#: ../src/controlpanel/gui.py:249 +#: ../src/controlpanel/gui.py:266 msgid "Warning" -msgstr "" +msgstr "Avètisman" -#: ../src/controlpanel/gui.py:253 +#: ../src/controlpanel/gui.py:270 msgid "Cancel changes" -msgstr "" - -#: ../src/controlpanel/gui.py:257 -msgid "Later" -msgstr "" +msgstr "Anile chanjman yo" -#: ../src/controlpanel/gui.py:261 +#: ../src/controlpanel/gui.py:279 msgid "Restart now" -msgstr "" +msgstr "Redemare kounye a menm" #: ../src/controlpanel/model/aboutme.py:44 msgid "You must enter a name." -msgstr "" +msgstr "Ou dwe rantre yon non." -#: ../src/controlpanel/model/aboutme.py:67 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format msgid "stroke: color=%s hue=%s" -msgstr "" +msgstr "stroke:_ koulè=%s hue=%s" -#: ../src/controlpanel/model/aboutme.py:70 +#: ../src/controlpanel/model/aboutme.py:72 #, python-format msgid "stroke: %s" -msgstr "" +msgstr "stroke:_ %s" -#: ../src/controlpanel/model/aboutme.py:72 +#: ../src/controlpanel/model/aboutme.py:74 #, python-format msgid "fill: color=%s hue=%s" -msgstr "" +msgstr "fill:_ koulè=%s hue=%s" -#: ../src/controlpanel/model/aboutme.py:74 +#: ../src/controlpanel/model/aboutme.py:76 #, python-format msgid "fill: %s" -msgstr "" +msgstr "fill: _ %s" -#: ../src/controlpanel/model/aboutme.py:85 +#: ../src/controlpanel/model/aboutme.py:87 msgid "Error in specified color modifiers." -msgstr "Erè nan modifikatè endike koulè yo" +msgstr "Erè nan modifikatè koulè espesifye yo" -#: ../src/controlpanel/model/aboutme.py:88 +#: ../src/controlpanel/model/aboutme.py:90 msgid "Error in specified colors." -msgstr "Erè nan koulè endike yo" +msgstr "Erè nan koulè espesifye yo" #: ../src/controlpanel/model/aboutxo.py:24 msgid "Not available" @@ -340,12 +380,11 @@ msgstr "Erè lè lokal pa egziste." #: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 msgid "Value must be an integer." -msgstr "" +msgstr "Valè-a dwe yon antye." #: ../src/controlpanel/model/language.py:28 -#, fuzzy msgid "Could not access ~/.i18n. Create standard settings." -msgstr "Pa ka rantre %s. Kreye reglaj estanda" +msgstr "Aksè enposib ~/.i18n. Kreye paramèt pa defo yo" #: ../src/controlpanel/model/language.py:104 #, python-format @@ -355,11 +394,11 @@ msgstr "Lang pou kod=%s pa ka tèmine." #: ../src/controlpanel/model/language.py:121 #, python-format msgid "Sorry I do not speak '%s'." -msgstr "Mwen regrèt mwen pa pale '%s'." +msgstr "Dezole mwen pa pale '%s'." #: ../src/controlpanel/model/network.py:48 msgid "You must enter a server." -msgstr "" +msgstr "Ou dwe endike yon sèvè." #: ../src/controlpanel/model/network.py:63 msgid "State is unknown." @@ -367,179 +406,224 @@ msgstr "Yo pa konnen eta l'" #: ../src/controlpanel/model/network.py:83 msgid "Error in specified radio argument use on/off." -msgstr "Erè nan itilizasyon limen/etenn agiman radio endike-a. " +msgstr "Agiman radio espesifye-a pa kòrèk sèvi limen/etenn. " + +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." +msgstr "Agiman pou jere alimantasyon otomatik la pa kòrèk sèvi ak limen/etenn" + +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." +msgstr "Agiman pou gere alimantasyon ak dèyo pa kòrèk sèvi ak limen/etenn" #: ../src/controlpanel/view/aboutme.py:32 msgid "About Me" -msgstr "" +msgstr "Enfòmasyon pèsonèl" #: ../src/controlpanel/view/aboutme.py:134 -#, fuzzy msgid "Click to change your color:" msgstr "Klike pou chanje koulè" #: ../src/controlpanel/view/aboutxo.py:26 msgid "About my XO" -msgstr "" +msgstr "Enfòmasyon sou XO mwen" #: ../src/controlpanel/view/aboutxo.py:47 msgid "Identity" -msgstr "" +msgstr "Idantite" #: ../src/controlpanel/view/aboutxo.py:56 msgid "Serial Number:" -msgstr "" +msgstr "Nimero seri:" #: ../src/controlpanel/view/aboutxo.py:79 msgid "Software" -msgstr "" +msgstr "Pwogram" #: ../src/controlpanel/view/aboutxo.py:88 msgid "Build:" -msgstr "" +msgstr "Bati:" #: ../src/controlpanel/view/aboutxo.py:103 msgid "Firmware:" -msgstr "" +msgstr "Mikrolojisyèl:" #: ../src/controlpanel/view/datetime.py:29 msgid "Date & Time" -msgstr "" +msgstr "Dat ak lè" #: ../src/controlpanel/view/datetime.py:72 msgid "Timezone" -msgstr "" +msgstr "Lè lokal" #: ../src/controlpanel/view/frame.py:28 msgid "Frame" -msgstr "" +msgstr "Ankadreman" #: ../src/controlpanel/view/frame.py:30 msgid "never" -msgstr "" +msgstr "Jamè" #: ../src/controlpanel/view/frame.py:31 msgid "instantaneous" -msgstr "" +msgstr "imediat" #: ../src/controlpanel/view/frame.py:32 #, python-format msgid "%s seconds" -msgstr "" +msgstr "%s segond" #: ../src/controlpanel/view/frame.py:56 msgid "Activation Delay" -msgstr "" +msgstr "Reta aktivasyon" #: ../src/controlpanel/view/frame.py:80 msgid "Corner" -msgstr "" +msgstr "Kwen" #: ../src/controlpanel/view/frame.py:115 msgid "Edge" -msgstr "" +msgstr "Bò" #: ../src/controlpanel/view/language.py:29 #: ../src/controlpanel/view/language.py:74 msgid "Language" -msgstr "" +msgstr "Lang" #: ../src/controlpanel/view/network.py:28 msgid "Network" -msgstr "" +msgstr "Rezo" #: ../src/controlpanel/view/network.py:53 msgid "Wireless" -msgstr "" +msgstr "San fil" #: ../src/controlpanel/view/network.py:61 msgid "Radio:" -msgstr "" +msgstr "Radio" #: ../src/controlpanel/view/network.py:94 msgid "Mesh" -msgstr "" +msgstr "Rezo maye" #: ../src/controlpanel/view/network.py:103 msgid "Server:" -msgstr "" +msgstr "Sèvè:" + +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "Alimantasyon" + +#: ../src/controlpanel/view/power.py:51 +msgid "Power management" +msgstr "Jere alimantasyon" -#: ../src/view/devices/network/mesh.py:108 +#: ../src/controlpanel/view/power.py:61 +msgid "Automatic power management (increases battery life)" +msgstr "automatic power management(ogmante tan batri a ap bay)" + +#: ../src/controlpanel/view/power.py:89 +msgid "" +"Extreme power management (disables wireless radio, increases battery life)" +msgstr "(retire posibilite capte ond wireless, ogmante tan batri a ap bay)" + +#: ../src/view/devices/network/mesh.py:111 msgid "Connected to a School Mesh Portal" -msgstr "Konekte sou rezo lekòl la" +msgstr "Konekte sou pòtay rezo lekòl la" -#: ../src/view/devices/network/mesh.py:110 +#: ../src/view/devices/network/mesh.py:113 msgid "Looking for a School Mesh Portal..." -msgstr "Ap chache rezo lekòl la" +msgstr "Ap chache pòtay rezo lekòl la" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:116 msgid "Connected to an XO Mesh Portal" -msgstr "Konekte sou yon rezo XO" +msgstr "Konekte sou pòtal yon rezo XO" -#: ../src/view/devices/network/mesh.py:115 +#: ../src/view/devices/network/mesh.py:118 msgid "Looking for an XO Mesh Portal..." msgstr "Ap chache yon rezo XO..." -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:121 msgid "Connected to a Simple Mesh" msgstr "Konekte sou yon senp rezo" -#: ../src/view/devices/network/mesh.py:120 +#: ../src/view/devices/network/mesh.py:123 msgid "Starting a Simple Mesh" msgstr "Kòmanse yon senp rezo" -#: ../src/view/devices/network/mesh.py:127 +#: ../src/view/devices/network/mesh.py:130 msgid "Unknown Mesh" -msgstr "Rezo non idantifye" +msgstr "Rezo maye inkoni" -#: ../src/view/frame/activitiestray.py:224 +#: ../src/view/frame/activitiestray.py:210 msgid "Decline" -msgstr "" +msgstr "Refize" + +#: ../src/view/home/favoritesview.py:287 +msgid "Registration Failed" +msgstr "enskripsyon an pa feÌ€t" + +# se yon kòd enfòmatik li pa dwe chanje +#: ../src/view/home/favoritesview.py:288 +#, python-format +msgid "%s" +msgstr "%s" -#: ../src/view/home/favoritesview.py:351 +#: ../src/view/home/favoritesview.py:290 +msgid "Registration Successful" +msgstr "enskripsyon an feÌ€t" + +#: ../src/view/home/favoritesview.py:291 +msgid "You are now registered with your school server." +msgstr "ou pa enskri avek seÌ€veÌ€ lekol ou a" + +#: ../src/view/home/favoritesview.py:407 msgid "Control Panel" -msgstr "" +msgstr "Pano kontwòl" -#: ../src/view/home/favoritesview.py:362 +#: ../src/view/home/favoritesview.py:418 msgid "Restart" -msgstr "" +msgstr "Redemare" -#: ../src/view/home/favoritesview.py:367 +#: ../src/view/home/favoritesview.py:423 msgid "Shutdown" -msgstr "Fèmen" +msgstr "Eten'n" -#: ../src/view/home/favoritesview.py:373 +#: ../src/view/home/favoritesview.py:429 msgid "Register" msgstr "Enskri" -#: ../src/view/palettes.py:41 +#: ../src/view/palettes.py:42 msgid "Starting..." -msgstr "ap louvri" +msgstr "Demaraj...." -#: ../src/view/palettes.py:71 +#: ../src/view/palettes.py:72 msgid "Stop" msgstr "Stope, rete" -#: ../src/view/palettes.py:96 +#: ../src/view/palettes.py:104 msgid "Start" -msgstr "" +msgstr "Demare" -#: ../src/view/palettes.py:119 +#: ../src/view/palettes.py:132 msgid "Remove favorite" -msgstr "" +msgstr "Siprime favori" -#: ../src/view/palettes.py:123 +#: ../src/view/palettes.py:136 msgid "Make favorite" -msgstr "" +msgstr "Ajoute nan favori" -#: ../src/view/palettes.py:169 +#: ../src/view/palettes.py:185 msgid "Show contents" -msgstr "" +msgstr "Afiche kontni yo" -#: ../src/view/palettes.py:193 +#: ../src/view/palettes.py:209 #, python-format msgid "%(free_space)d MB Free" -msgstr "" +msgstr "%(free_space)d MB vid" + +#~ msgid "<Ctrl>R" +#~ msgstr "<Ctrl>R" #~ msgid "off" #~ msgstr "Etenn" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-10-09 08:42-0400\n" +"POT-Creation-Date: 2008-09-19 00:30-0400\n" +"PO-Revision-Date: 2008-09-19 17:32-0400\n" "Last-Translator: Carlo Falciola <cfalciola@yahoo.it>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -15,23 +15,23 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Pootle 1.1.0rc2\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "Nome:" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "Seleziona per cambiare colore:" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Indietro" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Fatto" -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "Prossimo" @@ -48,11 +48,11 @@ msgstr "Aggiungi agli amici" msgid "Invite to %s" msgstr "Invito per %s" -#: ../src/view/clipboardmenu.py:51 +#: ../src/view/clipboardmenu.py:48 msgid "Remove" msgstr "Rimuovi" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" msgstr "Apri" @@ -60,18 +60,22 @@ msgstr "Apri" # TODO: Implement stopping downloads # self._stop_item.connect('activate', self._stop_item_activate_cb) # self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:85 msgid "Keep" msgstr "Memorizza" -#: ../src/view/clipboardmenu.py:83 +#: ../src/view/clipboardmenu.py:84 msgid "Open with" msgstr "Apri con" -#: ../src/view/clipboardmenu.py:228 +#: ../src/view/clipboardmenu.py:216 #, python-format -msgid "%s clipping" -msgstr "ritaglio %s" +msgid "Clipboard object: %s." +msgstr "Oggetto Clipboard: %s." #: ../src/hardware/keydialog.py:150 msgid "Key Type:" @@ -101,56 +105,55 @@ msgstr "Il server non può completare la richiesta." msgid "Screenshot" msgstr "Schermata" -#: ../src/view/home/HomeBox.py:78 +#: ../src/view/home/HomeBox.py:79 msgid "Confirm erase" msgstr "Conferma cancellazione" -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:81 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "" "Conferma cancellazione: Sei sicuro di voler eliminare definitivamente %s?" -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 +#: ../src/view/home/HomeBox.py:88 ../src/view/palettes.py:120 msgid "Erase" -msgstr "Elimina" +msgstr "Cancella" -#: ../src/view/home/HomeBox.py:117 +#: ../src/view/home/HomeBox.py:118 msgid "Software Update" msgstr "Aggiornamento software" -#: ../src/view/home/HomeBox.py:118 +#: ../src/view/home/HomeBox.py:119 msgid "Update your activities to ensure compatibility with your new software" msgstr "" "Aggiorna le tue attività perchè siano compatibili con il tuo sistema " "aggiornato." -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:123 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "Annulla" -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/gui.py:286 msgid "Later" msgstr "Dopo" -#: ../src/view/home/HomeBox.py:127 +#: ../src/view/home/HomeBox.py:128 msgid "Check now" msgstr "Verifica adesso" -#: ../src/view/home/HomeBox.py:261 +#: ../src/view/home/HomeBox.py:262 msgid "List view" msgstr "Vista Elenco" -#: ../src/view/home/HomeBox.py:262 +#: ../src/view/home/HomeBox.py:263 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:320 +#: ../src/view/home/HomeBox.py:321 msgid "Favorites view" msgstr "Visualizza i Preferiti" -#: ../src/view/home/HomeBox.py:321 +#: ../src/view/home/HomeBox.py:322 msgid "<Ctrl>1" msgstr "<Ctrl>1" @@ -170,20 +173,21 @@ msgstr "Disconnetti" msgid "Disconnecting..." msgstr "Disconnessione..." -#: ../src/view/home/MeshBox.py:159 +#: ../src/view/home/MeshBox.py:152 msgid "Connecting..." msgstr "Connessione..." # TODO: show the channel number #. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 +#: ../src/view/home/MeshBox.py:159 msgid "Connected" msgstr "Connesso" # A complete translation in italian: "rete a maglie" becames a tautology -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "Rete Mesh" @@ -191,18 +195,16 @@ msgstr "Rete Mesh" # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "Disconnessione..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 msgid "Resume" msgstr "Riprendi" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" msgstr "Associa" @@ -231,19 +233,24 @@ msgstr "Carica" msgid "My Speakers" msgstr "I miei Altoparlanti" -#: ../src/view/devices/speaker.py:125 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" msgstr "riAttiva" -#: ../src/view/devices/speaker.py:128 +#: ../src/view/devices/speaker.py:122 msgid "Mute" msgstr "Silenzia" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "indirizzo IP: %s" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "Disconnesso" -#: ../src/view/devices/network/wireless.py:143 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "Canale" @@ -284,9 +291,7 @@ msgstr "sugar-control-panel: key=%s non è una opzione disponibile" msgid "sugar-control-panel: %s" msgstr "sugar-control-panel: %s" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 +#: ../src/controlpanel/cmd.py:33 msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -309,7 +314,7 @@ msgstr "" " -s key assegna il valore corrente alla \"key\" \n" " " -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "Per applicare le modifiche è necessario riavviare sugar.\n" @@ -317,102 +322,144 @@ msgstr "Per applicare le modifiche è necessario riavviare sugar.\n" msgid "Ok" msgstr "Ok" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:278 msgid "Changes require restart" msgstr "Le modifiche rendono necessario un riavvio" -#: ../src/controlpanel/gui.py:264 +#: ../src/controlpanel/gui.py:277 msgid "Warning" msgstr "Attenzione" -#: ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/gui.py:281 msgid "Cancel changes" msgstr "Annulla modifiche" -#: ../src/controlpanel/gui.py:277 +#: ../src/controlpanel/gui.py:290 msgid "Restart now" msgstr "Riavvia adesso" -#: ../src/controlpanel/aboutme/model.py:44 +#: ../src/controlpanel/model/aboutme.py:44 msgid "You must enter a name." msgstr "Devi inserire un nome." -#: ../src/controlpanel/aboutme/model.py:69 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format msgid "stroke: color=%s hue=%s" msgstr "linea: colore=%s tinta=%s" -#: ../src/controlpanel/aboutme/model.py:72 +#: ../src/controlpanel/model/aboutme.py:72 #, python-format msgid "stroke: %s" msgstr "linea: %s" -#: ../src/controlpanel/aboutme/model.py:74 +#: ../src/controlpanel/model/aboutme.py:74 #, python-format msgid "fill: color=%s hue=%s" msgstr "riempimento: colore=%s tinta=%s" -#: ../src/controlpanel/aboutme/model.py:76 +#: ../src/controlpanel/model/aboutme.py:76 #, python-format msgid "fill: %s" msgstr "riempimento: %s" -#: ../src/controlpanel/aboutme/model.py:87 +#: ../src/controlpanel/model/aboutme.py:87 msgid "Error in specified color modifiers." msgstr "Errore nella variazione dei colori richiesta" -#: ../src/controlpanel/aboutme/model.py:90 +#: ../src/controlpanel/model/aboutme.py:90 msgid "Error in specified colors." msgstr "Errore nella definizione dei colori." -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 +#: ../src/controlpanel/model/aboutxo.py:24 +msgid "Not available" +msgstr "Non disponibile" + +#: ../src/controlpanel/model/datetime.py:89 +msgid "Error timezone does not exist." +msgstr "Errore, timezone non esistente." + +#: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 +msgid "Value must be an integer." +msgstr "Valore deve essere un intero." + +#: ../src/controlpanel/model/language.py:28 +msgid "Could not access ~/.i18n. Create standard settings." +msgstr "Impossibile accedere a ~/.i18n. Creazione configurazione standard." + +#: ../src/controlpanel/model/language.py:114 +#, python-format +msgid "Language for code=%s could not be determined." +msgstr "Linguaggio con codice=%s sconosciuto." + +#: ../src/controlpanel/model/language.py:131 +#, python-format +msgid "Sorry I do not speak '%s'." +msgstr "Spiacente, ma non parlo '%s'." + +#: ../src/controlpanel/model/network.py:62 +msgid "State is unknown." +msgstr "Stato sconosciuto." + +#: ../src/controlpanel/model/network.py:82 +msgid "Error in specified radio argument use on/off." +msgstr "Errore nel campo specificato, utilizzare on/off." + +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." +msgstr "" +"Errore nel campo Gestione Automatica Risparmio Energetico, utilizza on/off" + +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." +msgstr "Errore nel campo Gestione Estrema Risparmio Energetico, utilizza on/off" + +#: ../src/controlpanel/view/aboutme.py:32 msgid "About Me" msgstr "Informazioni su" -#: ../src/controlpanel/aboutme/view.py:134 +#: ../src/controlpanel/view/aboutme.py:134 msgid "Click to change your color:" msgstr "Seleziona per cambiare il tuo colore:" -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "Non disponibile" +#: ../src/controlpanel/view/aboutxo.py:28 +msgid "About my XO" +msgstr "Informazioni sul mio XO" -#: ../src/controlpanel/aboutxo/view.py:55 +#: ../src/controlpanel/view/aboutxo.py:59 msgid "Identity" msgstr "Identità " -#: ../src/controlpanel/aboutxo/view.py:64 +#: ../src/controlpanel/view/aboutxo.py:68 msgid "Serial Number:" msgstr "Numero di Serie:" -#: ../src/controlpanel/aboutxo/view.py:87 +#: ../src/controlpanel/view/aboutxo.py:91 msgid "Software" msgstr "Software" -#: ../src/controlpanel/aboutxo/view.py:96 +#: ../src/controlpanel/view/aboutxo.py:100 msgid "Build:" msgstr "Build:" -#: ../src/controlpanel/aboutxo/view.py:111 +#: ../src/controlpanel/view/aboutxo.py:115 msgid "Sugar:" msgstr "Sugar:" -#: ../src/controlpanel/aboutxo/view.py:126 +#: ../src/controlpanel/view/aboutxo.py:130 msgid "Firmware:" msgstr "Firmware:" -#: ../src/controlpanel/aboutxo/view.py:148 +#: ../src/controlpanel/view/aboutxo.py:152 msgid "Copyright and License" msgstr "Copyright e Licenza" -#: ../src/controlpanel/aboutxo/view.py:156 +#: ../src/controlpanel/view/aboutxo.py:160 msgid "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; e Contributori." -#: ../src/controlpanel/aboutxo/view.py:163 +#: ../src/controlpanel/view/aboutxo.py:167 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -424,232 +471,160 @@ msgstr "" "chiunque è il benvenuto per apportare modifiche e migliorie e/o distribuirne " "copie, alle condizioni descritte nella licenza medesima." -#: ../src/controlpanel/aboutxo/view.py:175 +#: ../src/controlpanel/view/aboutxo.py:179 msgid "Full license:" msgstr "Testo della Licenza:" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "Informazioni sul mio XO" - -#: ../src/controlpanel/datetime/model.py:89 -msgid "Error timezone does not exist." -msgstr "Errore, timezone non esistente." +#: ../src/controlpanel/view/datetime.py:29 +msgid "Date & Time" +msgstr "Data e Ora" -#: ../src/controlpanel/datetime/view.py:68 +#: ../src/controlpanel/view/datetime.py:72 msgid "Timezone" msgstr "Timezone" -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "Data e Ora" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "Valore deve essere un intero." +#: ../src/controlpanel/view/frame.py:28 +msgid "Frame" +msgstr "Cornice" -#: ../src/controlpanel/frame/view.py:26 +#: ../src/controlpanel/view/frame.py:30 msgid "never" msgstr "mai" -#: ../src/controlpanel/frame/view.py:27 +#: ../src/controlpanel/view/frame.py:31 msgid "instantaneous" msgstr "istantaneamente" -#: ../src/controlpanel/frame/view.py:28 +#: ../src/controlpanel/view/frame.py:32 #, python-format msgid "%s seconds" -msgstr "%s secondi" +msgstr "%d secondi" -#: ../src/controlpanel/frame/view.py:52 +#: ../src/controlpanel/view/frame.py:56 msgid "Activation Delay" msgstr "Ritardo attivazione" -#: ../src/controlpanel/frame/view.py:76 +#: ../src/controlpanel/view/frame.py:80 msgid "Corner" msgstr "Angolo" -#: ../src/controlpanel/frame/view.py:111 +#: ../src/controlpanel/view/frame.py:115 msgid "Edge" msgstr "Margine" -#: ../src/controlpanel/frame/__init__.py:21 -msgid "Frame" -msgstr "Cornice" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "Impossibile accedere a ~/.i18n. Creazione configurazione standard." - -#: ../src/controlpanel/language/model.py:114 -#, python-format -msgid "Language for code=%s could not be determined." -msgstr "Linguaggio con codice=%s sconosciuto." - -#: ../src/controlpanel/language/model.py:131 -#, python-format -msgid "Sorry I do not speak '%s'." -msgstr "Spiacente, ma non parlo '%s'." - -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 +#: ../src/controlpanel/view/language.py:29 +#: ../src/controlpanel/view/language.py:74 msgid "Language" msgstr "Lingua" -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "Stato sconosciuto." - -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "Errore nel campo specificato, utilizzare on/off." - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 +#: ../src/controlpanel/view/network.py:28 msgid "Network" msgstr "Network" -#: ../src/controlpanel/network/view.py:54 +#: ../src/controlpanel/view/network.py:54 msgid "Wireless" msgstr "Wireless" -#: ../src/controlpanel/network/view.py:62 +#: ../src/controlpanel/view/network.py:62 msgid "Turn of the wireless radio to save battery life" -msgstr "Spegni il trasmettitore wireless per risparmiare energia" +msgstr "Spegni il trasmettitore radio di rete per risparmiare la batteria" -#: ../src/controlpanel/network/view.py:75 +#: ../src/controlpanel/view/network.py:75 msgid "Radio" msgstr "Radio" -#: ../src/controlpanel/network/view.py:91 +#: ../src/controlpanel/view/network.py:91 msgid "Discard network history if you have trouble connecting to the network" msgstr "" -"Elimina la storia delle connessioni di rete effettuate nel caso di problemi " -"di connessione" +"Elimina lo storico delle connessioni di rete se hai problemi di connessione" -#: ../src/controlpanel/network/view.py:100 +#: ../src/controlpanel/view/network.py:100 msgid "Discard network history" -msgstr "Elimina la storia delle connessioni di rete" +msgstr "Elimina lo storico delle connessioni" -#: ../src/controlpanel/network/view.py:113 +#: ../src/controlpanel/view/network.py:113 msgid "Mesh" msgstr "Mesh" -#: ../src/controlpanel/network/view.py:122 +#: ../src/controlpanel/view/network.py:122 msgid "Server:" msgstr "Server:" -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "" -"Errore nel campo Gestione Automatica Risparmio Energetico, utilizza on/off" - -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "Errore nel campo Gestione Estrema Risparmio Energetico, utilizza on/off" +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "Energia" -#: ../src/controlpanel/power/view.py:47 +#: ../src/controlpanel/view/power.py:51 msgid "Power management" msgstr "Gestione Risparmio Energetico (power management)" -#: ../src/controlpanel/power/view.py:57 +#: ../src/controlpanel/view/power.py:61 msgid "Automatic power management (increases battery life)" msgstr "" "Gestione Automatica Risparmio Energetico (incrementa la durata delle " "batterie)" -#: ../src/controlpanel/power/view.py:85 +#: ../src/controlpanel/view/power.py:89 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Extreme power management (disables wireless radio, increases battery life)" msgstr "" "Gestione Risparmio Energetico Estrema (spegne la connessione radio wireless, " "incrementa la durata delle batterie)" -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "Energia" - -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "Connesso ad un Portale Mesh di scuola" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "Ricerca di un Portale Mesh di scuola..." -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" msgstr "Connesso ad un Portale Mesh XO" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." msgstr "Sto cercando un Portale Mesh XO..." # Diretto? -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "Connesso ad un Mesh Semplice" # Diretto? -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "Attivazione Mesh Semplice" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "Mesh sconosciuto" -#: ../src/view/frame/activitiestray.py:211 +#: ../src/view/frame/activitiestray.py:210 msgid "Decline" msgstr "Rinuncia" -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "Formato libero" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "Anello" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "Spirale" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "Scatola" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "Triangolo" - -#: ../src/view/home/favoritesview.py:295 +#: ../src/view/home/favoritesview.py:296 msgid "Registration Failed" msgstr "Registrazione Fallita" -#: ../src/view/home/favoritesview.py:296 +#: ../src/view/home/favoritesview.py:297 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:298 +#: ../src/view/home/favoritesview.py:299 msgid "Registration Successful" msgstr "Registrazione Effettuata" -#: ../src/view/home/favoritesview.py:299 +#: ../src/view/home/favoritesview.py:300 msgid "You are now registered with your school server." msgstr "Ora sei registrato sul tuo server di scuola" #: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "Configurazioni" +msgid "Control Panel" +msgstr "Pannello di Controllo" #: ../src/view/home/favoritesview.py:425 msgid "Restart" @@ -671,9 +646,7 @@ msgstr "Inizio..." msgid "Stop" msgstr "Chiudi" -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 +#: ../src/view/palettes.py:104 msgid "Start" msgstr "Avvia" @@ -694,132 +667,17 @@ msgstr "Mostra i contenuti" msgid "%(free_space)d MB Free" msgstr "%(free_space)d MB Liberi" -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "Cerca" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "Sempre" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "Oggi" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "Da ieri" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "Settimana scorsa" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "Mese scorso" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "Anno scorso" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "Tutti" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "I miei amici" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "La mia classe" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "Qualsiasi" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "Copia" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "Senza titolo" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "Diario" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "Nessuna anteprima" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "Partecipanti:" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "Descrizione:" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "Etichette:" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "Scegli un oggetto" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "Chiudi" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "Rimuovi" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "Nessuna data" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "Il tuo Diario è vuoto" - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "Non ci sono dati corrispondenti " - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "Il tuo Diario è pieno" - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." -msgstr "" -"Per favore cancella alcune registrazioni vecchie dal Diario per far spazio " -"alle nuove." - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "Apri il Diario" +# TRANS: label for the freeform layout in the favorites view +#~ msgid "Freeform" +#~ msgstr "Formato libero" -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "Oggetto Clipboard: %s." +# TRANS: label for the ring layout in the favorites view +#~ msgid "Ring" +#~ msgstr "Anello" #~ msgid "You must enter a server." #~ msgstr "Devi inserire un server." -#~ msgid "Control Panel" -#~ msgstr "Pannello di Controllo" - #~ msgid "© 2008 One Laptop per Child Assocation " #~ msgstr "© 2008 One Laptop per Child Association " @@ -951,6 +809,9 @@ msgstr "Apri il Diario" #~ msgid "Stop download" #~ msgstr "Sospendi il trasferimento" +#~ msgid "Close" +#~ msgstr "Chiudi" + #~ msgid "No options" #~ msgstr "Nessuna opzione" @@ -972,6 +833,9 @@ msgstr "Apri il Diario" #~ msgid "Redo" #~ msgstr "Ripeti" +#~ msgid "Copy" +#~ msgstr "Copia" + #~ msgid "Paste" #~ msgstr "Incolla" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-10-09 11:39-0400\n" +"POT-Creation-Date: 2008-09-19 00:30-0400\n" +"PO-Revision-Date: 2008-09-20 01:13-0400\n" "Last-Translator: korakurider <korakurider@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -15,23 +15,23 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Pootle 1.1.0rc2\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "åå‰:" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "クリックã—ã¦è‰²ã‚’変更:" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "戻る" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "完了" -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "進む" @@ -48,11 +48,11 @@ msgstr "ãŠå‹ã ã¡ã‚’登録" msgid "Invite to %s" msgstr "%s ã«æ‹›å¾…ã™ã‚‹" -#: ../src/view/clipboardmenu.py:51 +#: ../src/view/clipboardmenu.py:48 msgid "Remove" msgstr "削除" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" msgstr "é–‹ã" @@ -60,18 +60,22 @@ msgstr "é–‹ã" # TODO: Implement stopping downloads # self._stop_item.connect('activate', self._stop_item_activate_cb) # self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:85 msgid "Keep" msgstr "ジャーナルã«ä¿å˜" -#: ../src/view/clipboardmenu.py:83 +#: ../src/view/clipboardmenu.py:84 msgid "Open with" msgstr "次ã®ã‚‚ã®ã§é–‹ã:" -#: ../src/view/clipboardmenu.py:228 +#: ../src/view/clipboardmenu.py:216 #, python-format -msgid "%s clipping" -msgstr "%sã®ã‚¯ãƒªãƒƒãƒ”ング" +msgid "Clipboard object: %s." +msgstr "クリップボードã®ã‚ªãƒ–ジェクト: %s." #: ../src/hardware/keydialog.py:150 msgid "Key Type:" @@ -101,53 +105,52 @@ msgstr "サーãƒãƒ¼ã¯è¦æ±‚ã®å‡¦ç†ã‚’完了ã§ãã¾ã›ã‚“ã§ã—ãŸ" msgid "Screenshot" msgstr "スクリーンショット" -#: ../src/view/home/HomeBox.py:78 +#: ../src/view/home/HomeBox.py:79 msgid "Confirm erase" msgstr "消去ã®ç¢ºèª" -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:81 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "消去ã®ç¢ºèªï¼š %s を完全ã«æ¶ˆåŽ»ã—ã¾ã™ã‹ï¼Ÿ" -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 +#: ../src/view/home/HomeBox.py:88 ../src/view/palettes.py:120 msgid "Erase" msgstr "消去ã™ã‚‹" -#: ../src/view/home/HomeBox.py:117 +#: ../src/view/home/HomeBox.py:118 msgid "Software Update" msgstr "ソフトウェアã®æ›´æ–°" -#: ../src/view/home/HomeBox.py:118 +#: ../src/view/home/HomeBox.py:119 msgid "Update your activities to ensure compatibility with your new software" msgstr "æ–°ã—ã„ソフトウェアã¨ã®äº’æ›æ€§ã‚’ä¿ã¤ãŸã‚ã€ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを更新ã—ã¦ãã ã•ã„" -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:123 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "ä¸æ¢" -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/gui.py:286 msgid "Later" msgstr "ã‚ã¨ã§" -#: ../src/view/home/HomeBox.py:127 +#: ../src/view/home/HomeBox.py:128 msgid "Check now" msgstr "今ã™ã調ã¹ã‚‹" -#: ../src/view/home/HomeBox.py:261 +#: ../src/view/home/HomeBox.py:262 msgid "List view" msgstr "リスト表示" -#: ../src/view/home/HomeBox.py:262 +#: ../src/view/home/HomeBox.py:263 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:320 +#: ../src/view/home/HomeBox.py:321 msgid "Favorites view" msgstr "ãŠæ°—ã«å…¥ã‚Š" -#: ../src/view/home/HomeBox.py:321 +#: ../src/view/home/HomeBox.py:322 msgid "<Ctrl>1" msgstr "<Ctrl>1" @@ -171,19 +174,19 @@ msgstr "切æ–ã—ã¦ã„ã¾ã™..." # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:159 +#: ../src/view/home/MeshBox.py:152 msgid "Connecting..." msgstr "接続ã—ã¦ã„ã¾ã™..." -# TODO: show the channel number #. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 +#: ../src/view/home/MeshBox.py:159 msgid "Connected" msgstr "接続ã—ã¾ã—ãŸ" -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "メッシュãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" @@ -191,18 +194,16 @@ msgstr "メッシュãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" # priority over the normal wireless device. NM doesn't have a "disconnect" # method for a device either (for various reasons) so this doesn't # have a good mapping -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "切æ–..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 msgid "Resume" msgstr "å†é–‹" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" msgstr "å‚åŠ " @@ -231,19 +232,24 @@ msgstr "充電済ã¿" msgid "My Speakers" msgstr "ç§ã®ã‚¹ãƒ”ーカー" -#: ../src/view/devices/speaker.py:125 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" msgstr "音を出ã™" -#: ../src/view/devices/speaker.py:128 +#: ../src/view/devices/speaker.py:122 msgid "Mute" msgstr "音を消ã™" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "IPアドレス: %s" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "切æ–ã•ã‚Œã¾ã—ãŸ" -#: ../src/view/devices/network/wireless.py:143 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«" @@ -280,9 +286,7 @@ msgstr "sugar-control-panel: key=%s ã¯æœ‰åŠ¹ãªã‚ªãƒ—ションã§ã¯ã‚ã‚Šã¾ã msgid "sugar-control-panel: %s" msgstr "sugar-control-panel: %s" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 +#: ../src/controlpanel/cmd.py:33 msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -296,17 +300,17 @@ msgid "" " " msgstr "" "使ã„æ–¹: sugar-control-panel [ option ] key [ args ... ] \n" -"Sugarã®ç’°å¢ƒã‚’è¨å®šã™ã‚‹ã€‚ \n" -"Options: \n" -"-h ã“ã®ãƒ˜ãƒ«ãƒ—メッセージを表示ã—ã¦çµ‚了ã™ã‚‹\n" -"-l å…¨ã¦ã®æœ‰åŠ¹ãªã‚ªãƒ—ションを表示\n" -"-h key ã“ã®ã‚ーã«ã¤ã„ã¦ã®æƒ…å ±ã‚’è¡¨ç¤º\n" -"-g key ã“ã®ã‚ーã®ç¾åœ¨ã®è¨å®šå€¤ã‚’å–å¾—\n" -"-s key ã“ã®ã‚ーã®å€¤ã‚’è¨å®š \n" -"-c key ã“ã®ã‚ーã®è¨å®šã‚’消去\n" +" Sugarã®ç’°å¢ƒã‚’è¨å®šã™ã‚‹ã€‚ \n" +" Options: \n" +" -h ã“ã®ãƒ˜ãƒ«ãƒ—メッセージを表示ã—ã¦çµ‚了ã™ã‚‹\n" +" -l å…¨ã¦ã®æœ‰åŠ¹ãªã‚ªãƒ—ションを表示\n" +" -h key ã“ã®ã‚ーã«ã¤ã„ã¦ã®æƒ…å ±ã‚’è¡¨ç¤º\n" +" -g key ã“ã®ã‚ーã®ç¾åœ¨ã®è¨å®šå€¤ã‚’å–å¾—\n" +" -s key ã“ã®ã‚ーã®å€¤ã‚’è¨å®š \n" +" -c key ã“ã®ã‚ーã®è¨å®šã‚’消去\n" " " -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "変更をé©ç”¨ã™ã‚‹ã«ã¯sugarã‚’å†èµ·å‹•ã—ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã‚“。\n" @@ -314,103 +318,144 @@ msgstr "変更をé©ç”¨ã™ã‚‹ã«ã¯sugarã‚’å†èµ·å‹•ã—ãªã‘ã‚Œã°ã„ã‘ã¾ã›ã msgid "Ok" msgstr "了解" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:278 msgid "Changes require restart" msgstr "変更ã«ã¯å†èµ·å‹•ãŒå¿…è¦ã§ã™" -#: ../src/controlpanel/gui.py:264 +#: ../src/controlpanel/gui.py:277 msgid "Warning" msgstr "注æ„" -#: ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/gui.py:281 msgid "Cancel changes" msgstr "変更をå–ã‚Šã‚„ã‚ã‚‹" -#: ../src/controlpanel/gui.py:277 +#: ../src/controlpanel/gui.py:290 msgid "Restart now" msgstr "今ã™ãå†èµ·å‹•" -#: ../src/controlpanel/aboutme/model.py:44 +#: ../src/controlpanel/model/aboutme.py:44 msgid "You must enter a name." msgstr "åå‰ã®å…¥åŠ›ãŒå¿…è¦ã§ã™" -#: ../src/controlpanel/aboutme/model.py:69 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format msgid "stroke: color=%s hue=%s" msgstr "ç·š: 色=%s 色相=%s" -#: ../src/controlpanel/aboutme/model.py:72 +#: ../src/controlpanel/model/aboutme.py:72 #, python-format msgid "stroke: %s" msgstr "ç·š: %s" -#: ../src/controlpanel/aboutme/model.py:74 +#: ../src/controlpanel/model/aboutme.py:74 #, python-format msgid "fill: color=%s hue=%s" msgstr "å¡—ã‚Šã¤ã¶ã—: 色=%s 色相=%s" -#: ../src/controlpanel/aboutme/model.py:76 +#: ../src/controlpanel/model/aboutme.py:76 #, python-format msgid "fill: %s" msgstr "å¡—ã‚Šã¤ã¶ã—: %s" -#: ../src/controlpanel/aboutme/model.py:87 +#: ../src/controlpanel/model/aboutme.py:87 msgid "Error in specified color modifiers." msgstr "カラーモディファイアã®æŒ‡å®šã§ã‚¨ãƒ©ãƒ¼" -#: ../src/controlpanel/aboutme/model.py:90 +#: ../src/controlpanel/model/aboutme.py:90 msgid "Error in specified colors." msgstr "色ã®æŒ‡å®šã§ã‚¨ãƒ©ãƒ¼" -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 +#: ../src/controlpanel/model/aboutxo.py:24 +msgid "Not available" +msgstr "ä¸æ˜Žã§ã™" + +#: ../src/controlpanel/model/datetime.py:89 +msgid "Error timezone does not exist." +msgstr "エラー:ãã®ã‚¿ã‚¤ãƒ ゾーンã¯å˜åœ¨ã—ã¾ã›ã‚“。" + +#: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 +msgid "Value must be an integer." +msgstr "値ã¯æ•´æ•°ã§ãªãã¦ã¯ãªã‚Šã¾ã›ã‚“" + +#: ../src/controlpanel/model/language.py:28 +msgid "Could not access ~/.i18n. Create standard settings." +msgstr "~/.i18nã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚標準è¨å®šã‚’作ã£ã¦ãã ã•ã„。" + +#: ../src/controlpanel/model/language.py:114 +#, python-format +msgid "Language for code=%s could not be determined." +msgstr "コード%sã®è¨€èªžãŒä¸æ˜Žã§ã™ã€‚" + +#: ../src/controlpanel/model/language.py:131 +#, python-format +msgid "Sorry I do not speak '%s'." +msgstr "ã”ã‚ã‚“ãªã•ã„。'%s'ã¯è©±ã›ã¾ã›ã‚“。" + +#: ../src/controlpanel/model/network.py:62 +msgid "State is unknown." +msgstr "状態ãŒä¸æ˜Žã§ã™" + +#: ../src/controlpanel/model/network.py:82 +msgid "Error in specified radio argument use on/off." +msgstr "radio引数指定ã§ã‚¨ãƒ©ãƒ¼ã€on/offを使ã£ã¦ãã ã•ã„。" + +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." +msgstr "automatic_pm 引数指定ã§ã‚¨ãƒ©ãƒ¼ã€ on/offを指定ã—ã¦ãã ã•ã„" + +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." +msgstr "extreme_pm 引数指定ã®ã‚¨ãƒ©ãƒ¼ã€ on/offを指定ã—ã¦ãã ã•ã„。" + +#: ../src/controlpanel/view/aboutme.py:32 msgid "About Me" msgstr "ç§ã«ã¤ã„ã¦" -#: ../src/controlpanel/aboutme/view.py:134 +#: ../src/controlpanel/view/aboutme.py:134 msgid "Click to change your color:" msgstr "クリックã—ã¦è‰²ã‚’変更:" -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "ä¸æ˜Žã§ã™" +#: ../src/controlpanel/view/aboutxo.py:28 +msgid "About my XO" +msgstr "ç§ã®XOã«ã¤ã„ã¦" -#: ../src/controlpanel/aboutxo/view.py:55 +#: ../src/controlpanel/view/aboutxo.py:59 msgid "Identity" msgstr "個体ã®è˜åˆ¥" -#: ../src/controlpanel/aboutxo/view.py:64 +#: ../src/controlpanel/view/aboutxo.py:68 msgid "Serial Number:" msgstr "シリアル番å·:" -#: ../src/controlpanel/aboutxo/view.py:87 +#: ../src/controlpanel/view/aboutxo.py:91 msgid "Software" msgstr "ソフトウェア" -#: ../src/controlpanel/aboutxo/view.py:96 +#: ../src/controlpanel/view/aboutxo.py:100 msgid "Build:" msgstr "ビルド:" -#: ../src/controlpanel/aboutxo/view.py:111 +#: ../src/controlpanel/view/aboutxo.py:115 msgid "Sugar:" msgstr "Sugar:" -#: ../src/controlpanel/aboutxo/view.py:126 +#: ../src/controlpanel/view/aboutxo.py:130 msgid "Firmware:" msgstr "ファームウェア:" -#: ../src/controlpanel/aboutxo/view.py:148 +#: ../src/controlpanel/view/aboutxo.py:152 msgid "Copyright and License" msgstr "著作権ã¨ãƒ©ã‚¤ã‚»ãƒ³ã‚¹" -#: ../src/controlpanel/aboutxo/view.py:156 +#: ../src/controlpanel/view/aboutxo.py:160 msgid "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "" "(C) 2008 One Laptop per Child Association Inc; Red Hat Inc; and " "Contributors." -#: ../src/controlpanel/aboutxo/view.py:163 +#: ../src/controlpanel/view/aboutxo.py:167 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -420,223 +465,153 @@ msgstr "" "Sugarã¯ã€ã‚ãªãŸãŒè¦‹ã¦ã„るグラフィカルユーザインターフェースã§ã™ã€‚Sugarã¯ãƒ•ãƒªãƒ¼ã‚½ãƒ•ãƒˆã‚¦ã‚§ã‚¢ã§ã€GNU General Public Licen" "se(一般公衆利用許諾契約書)ã«ã‚ˆã‚‹ä¿è·å¯¾è±¡ã§ã™ã€‚ã“ã“ã«è¨˜è¼‰ã•ã‚Œã¦ã„ã‚‹æ¡ä»¶ã®ç¯„囲ã§ã€Sugarを変更ã—ãŸã‚Šã‚³ãƒ”ーをé…布ã™ã‚‹ã“ã¨ãŒè‡ªç”±ã«è¡Œãˆã¾ã™ã€‚" -#: ../src/controlpanel/aboutxo/view.py:175 +#: ../src/controlpanel/view/aboutxo.py:179 msgid "Full license:" msgstr "ライセンス全文:" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "ç§ã®XOã«ã¤ã„ã¦" - -#: ../src/controlpanel/datetime/model.py:89 -msgid "Error timezone does not exist." -msgstr "エラー:ãã®ã‚¿ã‚¤ãƒ ゾーンã¯å˜åœ¨ã—ã¾ã›ã‚“。" +#: ../src/controlpanel/view/datetime.py:29 +msgid "Date & Time" +msgstr "日付・時刻" -#: ../src/controlpanel/datetime/view.py:68 +#: ../src/controlpanel/view/datetime.py:72 msgid "Timezone" msgstr "タイムゾーン" -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "日付・時刻" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "値ã¯æ•´æ•°ã§ãªãã¦ã¯ãªã‚Šã¾ã›ã‚“" +#: ../src/controlpanel/view/frame.py:28 +msgid "Frame" +msgstr "フレーム" -#: ../src/controlpanel/frame/view.py:26 +#: ../src/controlpanel/view/frame.py:30 msgid "never" msgstr "表示ã—ãªã„" -#: ../src/controlpanel/frame/view.py:27 +#: ../src/controlpanel/view/frame.py:31 msgid "instantaneous" msgstr "ã™ãã«è¡¨ç¤º" -#: ../src/controlpanel/frame/view.py:28 +#: ../src/controlpanel/view/frame.py:32 #, python-format msgid "%s seconds" msgstr "%s 秒" -#: ../src/controlpanel/frame/view.py:52 +#: ../src/controlpanel/view/frame.py:56 msgid "Activation Delay" msgstr "表示ã™ã‚‹ã¾ã§ã®æ™‚é–“" -#: ../src/controlpanel/frame/view.py:76 +#: ../src/controlpanel/view/frame.py:80 msgid "Corner" msgstr "ç”»é¢ã®ï¼”ã™ã¿" -#: ../src/controlpanel/frame/view.py:111 +#: ../src/controlpanel/view/frame.py:115 msgid "Edge" msgstr "ç”»é¢ã®ãµã¡" -#: ../src/controlpanel/frame/__init__.py:21 -msgid "Frame" -msgstr "フレーム" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "~/.i18nã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚標準è¨å®šã‚’作ã£ã¦ãã ã•ã„。" - -#: ../src/controlpanel/language/model.py:114 -#, python-format -msgid "Language for code=%s could not be determined." -msgstr "コード%sã®è¨€èªžãŒä¸æ˜Žã§ã™ã€‚" - -#: ../src/controlpanel/language/model.py:131 -#, python-format -msgid "Sorry I do not speak '%s'." -msgstr "ã”ã‚ã‚“ãªã•ã„。'%s'ã¯è©±ã›ã¾ã›ã‚“。" - -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 +#: ../src/controlpanel/view/language.py:29 +#: ../src/controlpanel/view/language.py:74 msgid "Language" msgstr "言語" -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "状態ãŒä¸æ˜Žã§ã™" - -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "radio引数指定ã§ã‚¨ãƒ©ãƒ¼ã€on/offを使ã£ã¦ãã ã•ã„。" - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 +#: ../src/controlpanel/view/network.py:28 msgid "Network" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯" -#: ../src/controlpanel/network/view.py:54 +#: ../src/controlpanel/view/network.py:54 msgid "Wireless" msgstr "ç„¡ç·š" -#: ../src/controlpanel/network/view.py:62 +#: ../src/controlpanel/view/network.py:62 msgid "Turn of the wireless radio to save battery life" msgstr "é›»æ± ã‚’ç¯€ç´„ã™ã‚‹ãŸã‚ã€ç„¡ç·šã‚’æ¢ã‚ã‚‹" -#: ../src/controlpanel/network/view.py:75 +#: ../src/controlpanel/view/network.py:75 msgid "Radio" msgstr "電波" -#: ../src/controlpanel/network/view.py:91 +#: ../src/controlpanel/view/network.py:91 msgid "Discard network history if you have trouble connecting to the network" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šã§å•é¡ŒãŒã‚ã‚‹å ´åˆã€æŽ¥ç¶šå±¥æ´ã‚’ç ´æ£„ã—ã¾ã™" -#: ../src/controlpanel/network/view.py:100 +#: ../src/controlpanel/view/network.py:100 msgid "Discard network history" msgstr "ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯æŽ¥ç¶šå±¥æ´ã‚’ç ´æ£„" -#: ../src/controlpanel/network/view.py:113 +#: ../src/controlpanel/view/network.py:113 msgid "Mesh" msgstr "メッシュ" -#: ../src/controlpanel/network/view.py:122 +#: ../src/controlpanel/view/network.py:122 msgid "Server:" msgstr "サーãƒãƒ¼:" -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "automatic_pm 引数指定ã§ã‚¨ãƒ©ãƒ¼ã€ on/offを指定ã—ã¦ãã ã•ã„" - -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "extreme_pm 引数指定ã®ã‚¨ãƒ©ãƒ¼ã€ on/offを指定ã—ã¦ãã ã•ã„。" +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "é›»æº" -#: ../src/controlpanel/power/view.py:47 +#: ../src/controlpanel/view/power.py:51 msgid "Power management" msgstr "é›»æºã®ç®¡ç†" -#: ../src/controlpanel/power/view.py:57 +#: ../src/controlpanel/view/power.py:61 msgid "Automatic power management (increases battery life)" msgstr "自動的ãªé›»æºç®¡ç†ï¼ˆé›»æ± ãŒé•·æŒã¡ã—ã¾ã™ï¼‰" -#: ../src/controlpanel/power/view.py:85 +#: ../src/controlpanel/view/power.py:89 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Extreme power management (disables wireless radio, increases battery life)" msgstr "最大ã®é›»æºç®¡ç†ï¼ˆç„¡ç·šã®é›»æ³¢ã‚’åœã‚ã¦ã€é›»æ± ã‚’é•·æŒã¡ã•ã›ã¾ã™ï¼‰" -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "é›»æº" - -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "スクールメッシュãƒãƒ¼ã‚¿ãƒ«ã«æŽ¥ç¶šã—ã¾ã—ãŸã€‚" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "スクールメッシュãƒãƒ¼ã‚¿ãƒ«ã‚’探ã—ã¦ã„ã¾ã™..." -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" msgstr "XOメッシュãƒãƒ¼ã‚¿ãƒ«ã«æŽ¥ç¶šã—ã¾ã—ãŸ" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." msgstr "XOメッシュãƒãƒ¼ã‚¿ãƒ«ã‚’探ã—ã¦ã„ã¾ã™..." -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "シンプルメッシュã«æŽ¥ç¶šã—ã¾ã—ãŸ" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "シンプルメッシュを開始ã—ã¦ã„ã¾ã™" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "ä¸æ˜Žãªãƒ¡ãƒƒã‚·ãƒ¥" -#: ../src/view/frame/activitiestray.py:211 +#: ../src/view/frame/activitiestray.py:210 msgid "Decline" msgstr "æ–ã‚‹" -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "自由ã«ä¸¦ã¹ã‚‹" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "円ã«ä¸¦ã¹ã‚‹" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "渦巻ãã«ä¸¦ã¹ã‚‹" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "箱型ã«ä¸¦ã¹ã‚‹" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "三角形ã«ä¸¦ã¹ã‚‹" - -#: ../src/view/home/favoritesview.py:295 +#: ../src/view/home/favoritesview.py:296 msgid "Registration Failed" msgstr "登録失敗" -#: ../src/view/home/favoritesview.py:296 +#: ../src/view/home/favoritesview.py:297 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:298 +#: ../src/view/home/favoritesview.py:299 msgid "Registration Successful" msgstr "登録æˆåŠŸ" -#: ../src/view/home/favoritesview.py:299 +#: ../src/view/home/favoritesview.py:300 msgid "You are now registered with your school server." msgstr "ã‚ãªãŸã¯ã‚¹ã‚¯ãƒ¼ãƒ«ã‚µãƒ¼ãƒãƒ¼ã«ç™»éŒ²ã•ã‚Œã¾ã—ãŸ" #: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "è¨å®š" +msgid "Control Panel" +msgstr "コントãƒãƒ¼ãƒ«ãƒ‘ãƒãƒ«" #: ../src/view/home/favoritesview.py:425 msgid "Restart" @@ -658,9 +633,7 @@ msgstr "èµ·å‹•ä¸..." msgid "Stop" msgstr "åœæ¢" -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 +#: ../src/view/palettes.py:104 msgid "Start" msgstr "開始" @@ -681,130 +654,17 @@ msgstr "内容を表示" msgid "%(free_space)d MB Free" msgstr "%(free_space)d MB 空ã" -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "検索" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "ã™ã¹ã¦ã®æœŸé–“" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "今日" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "昨日ã‹ã‚‰å¾Œ" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "éŽåŽ»ï¼‘週間" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "éŽåŽ»ï¼‘ヶ月" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "éŽåŽ»ï¼‘å¹´" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "誰ã§ã‚‚" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "ç§ã®å‹ã ã¡" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "ç§ã®ã‚¯ãƒ©ã‚¹" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "ã™ã¹ã¦ã®ç¨®é¡ž" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "コピー" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "タイトル無ã—" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "ジャーナル" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "プレビュー無ã—" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "å‚åŠ è€…:" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "説明:" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "ã‚¿ã‚°:" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "オブジェクトをé¸ã¶" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "é–‰ã˜ã‚‹" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "å–ã‚Šã¯ãšã™" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "日付無ã—" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "ジャーナルãŒç©ºã§ã™" - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "ã‚ã¦ã¯ã¾ã‚‹ã‚‚ã®ãŒç„¡ã„ã§ã™" - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "ジャーナルãŒæº€æ¯ã§ã™" - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." -msgstr "æ–°ã—ã„ã‚‚ã®ãŒå…¥ã‚‹ã‚ˆã†ã€ã‚¸ãƒ£ãƒ¼ãƒŠãƒ«ã®ä¸èº«ã®å¤ã„ã‚‚ã®ã‚’ã©ã‚Œã‹å‰Šé™¤ã—ã¦ãã ã•ã„" - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "ジャーナルを表示" +# TRANS: label for the freeform layout in the favorites view +#~ msgid "Freeform" +#~ msgstr "自由ã«ä¸¦ã¹ã‚‹" -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "クリップボードã®ã‚ªãƒ–ジェクト: %s." +# TRANS: label for the ring layout in the favorites view +#~ msgid "Ring" +#~ msgstr "円ã«ä¸¦ã¹ã‚‹" #~ msgid "You must enter a server." #~ msgstr "サーãƒãƒ¼ã®æŒ‡å®šãŒå¿…è¦ã§ã™" -#~ msgid "Control Panel" -#~ msgstr "コントãƒãƒ¼ãƒ«ãƒ‘ãƒãƒ«" - #, fuzzy #~ msgid "off" #~ msgstr "オフ" @@ -873,6 +733,10 @@ msgstr "ジャーナルを表示" #~ msgstr "ã‚„ã‚Šç›´ã™" #, fuzzy +#~ msgid "Copy" +#~ msgstr "コピー" + +#, fuzzy #~ msgid "Paste" #~ msgstr "ペースト" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-07-23 07:44-0400\n" -"PO-Revision-Date: 2008-08-07 01:30-0400\n" +"POT-Creation-Date: 2008-08-19 17:12-0400\n" +"PO-Revision-Date: 2008-09-18 17:06-0400\n" "Last-Translator: Odontsetseg Bat-Erdene <obat-erdene@suffolk.edu>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -19,19 +19,19 @@ msgstr "" msgid "Name:" msgstr "ÐÑÑ€:" -#: ../src/intro/intro.py:94 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "Ðнд дарж өнгөө Ñолино уу" -#: ../src/intro/intro.py:145 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Буцах" -#: ../src/intro/intro.py:159 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Боллоо" -#: ../src/intro/intro.py:162 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "Дараах" @@ -64,7 +64,7 @@ msgstr "ÐÑÑÑ…" #. TODO: Implement stopping downloads #. self._stop_item.connect('activate', self._stop_item_activate_cb) #. self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:86 +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 msgid "Keep" msgstr "Хадгалах" @@ -89,48 +89,80 @@ msgstr "ÐÑвтрÑÑ… нууцлалын төрөл:" msgid "Encryption Type:" msgstr "Ðууцлалын төрөл:" +#: ../src/hardware/schoolserver.py:17 +msgid "Cannot obtain data needed for registration." +msgstr "БүртгүүлÑÑ…Ñд Ñ…ÑÑ€ÑгтÑй мÑдÑÑлÑл аваж чадахгүй." + +#: ../src/hardware/schoolserver.py:31 +msgid "Cannot connect to the server." +msgstr "Серверт холбогдож чадахгүй байна." + +#: ../src/hardware/schoolserver.py:36 +msgid "The server could not complete the request." +msgstr "Сервер Ñ…Ò¯ÑÑлт биÑлүүлÑж чадаагүй." + #: ../src/view/Shell.py:240 msgid "Screenshot" msgstr "ДÑлгÑцний зураг" -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:81 msgid "Confirm erase" msgstr "Ðрилгахыг зөвшөөрөх" -#: ../src/view/home/HomeBox.py:82 +#: ../src/view/home/HomeBox.py:83 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "Ðрилгахыг зөвшөөрөх: Та %s бүр мөÑөн арилгахыг Ñ…Ò¯Ñч байна уу?" -#: ../src/view/home/HomeBox.py:89 ../src/view/palettes.py:120 +#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 msgid "Erase" msgstr "Ðрилгах" -#: ../src/view/home/HomeBox.py:215 +#: ../src/view/home/HomeBox.py:120 +msgid "Software Update" +msgstr "Хангамж ШинÑчлÑÑ…" + +#: ../src/view/home/HomeBox.py:121 +msgid "Update your activities to ensure compatibility with your new software" +msgstr "Ð¨Ð¸Ð½Ñ Ñ…Ð°Ð½Ð³Ð°Ð¼Ð¶Ð¸Ð´ тохируулахыг батлахын тулд үйл ажилагаануудаа шинÑчлÑÑ…" + +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 +msgid "Cancel" +msgstr "Болих" + +#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:275 +msgid "Later" +msgstr "Дараа" + +#: ../src/view/home/HomeBox.py:130 +msgid "Check now" +msgstr "Одоо шалгах" + +#: ../src/view/home/HomeBox.py:266 msgid "List view" msgstr "ЖагÑаалтыг харах" -#: ../src/view/home/HomeBox.py:216 +#: ../src/view/home/HomeBox.py:267 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:273 +#: ../src/view/home/HomeBox.py:325 msgid "Favorites view" msgstr "Дуртай зүйлÑийг үзÑÑ…" -#: ../src/view/home/HomeBox.py:274 +#: ../src/view/home/HomeBox.py:326 msgid "<Ctrl>1" msgstr "<Ctrl>1" # TRANS: label for the freeform layout in the favorites view #. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/HomeBox.py:282 +#: ../src/view/home/HomeBox.py:334 msgid "Freeform" msgstr "Дурын Ñ…ÑлбÑÑ€" # TRANS: label for the ring layout in the favorites view #. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/HomeBox.py:289 +#: ../src/view/home/HomeBox.py:341 msgid "Ring" msgstr "Цагираг" @@ -201,7 +233,7 @@ msgstr "ЦÑнÑг маш бага байна" #: ../src/view/devices/battery.py:123 #, python-format msgid "%(hour)d:%(min).2d remaining" -msgstr "%(цаг)d:%(мин).2d үлдлÑÑ" +msgstr "%(hour)d:%(min).2d үлдлÑÑ" #: ../src/view/devices/battery.py:127 msgid "Charged" @@ -227,19 +259,19 @@ msgstr "СалгагдÑан" msgid "Channel" msgstr "Суваг" -#: ../src/view/frame/zoomtoolbar.py:34 +#: ../src/view/frame/zoomtoolbar.py:37 msgid "Neighborhood" msgstr "Хөршүүд" -#: ../src/view/frame/zoomtoolbar.py:36 +#: ../src/view/frame/zoomtoolbar.py:39 msgid "Group" msgstr "БүлÑг" -#: ../src/view/frame/zoomtoolbar.py:38 +#: ../src/view/frame/zoomtoolbar.py:41 msgid "Home" msgstr "Ðүүр хуудаÑ" -#: ../src/view/frame/zoomtoolbar.py:40 +#: ../src/view/frame/zoomtoolbar.py:43 msgid "Activity" msgstr "Үйл ажиллагаа" @@ -270,47 +302,40 @@ msgid "" " -h key show information about this key \n" " -g key get the current value of the key \n" " -s key set the current value for the key \n" +" -c key clear the current value for the key \n" " " msgstr "" -"Ð¥ÑÑ€ÑглÑÑ: sugar-удирдах-Ñамбар [ Ñонголт ] товч [ аргумент ... ] \n" -"Sugar-ийн орчны Ñ…Ñналт. \n" -"Сонголтууд: \n" -"-Ñ… ÐÐ½Ñ Ñ‚ÑƒÑламжын мÑдÑÑ Ò¯Ð·Ò¯Ò¯Ð»ÑÑ… ба гаргах\n" -"-л Боломжит Ñонголтын үзүүлÑлтүүд \n" -"-Ñ… товч Товчны тухай мÑдÑÑлÑл \n" -"-а товч Товчны одоогийн ач холбогдлыг мÑдÑÑ… \n" -"-Ñ‹ товч Товчны одоогийн ач холбогдлыг тохируулах \n" -" " - -#: ../src/controlpanel/cmd.py:45 +"Ð¥ÑÑ€ÑглÑÑ: sugar-удирдах-Ñамбар [ Ñонголт ] товч [ аргумент ... ] \r\n" +" Sugar-ийн орчны Ñ…Ñналт. \r\n" +" Сонголтууд: \r\n" +" -Ñ… ÐÐ½Ñ Ñ‚ÑƒÑламжын мÑдÑÑ Ò¯Ð·Ò¯Ò¯Ð»ÑÑ… ба гаргах\r\n" +" -л Боломжит Ñонголтын үзүүлÑлтүүд \r\n" +" -Ñ… товч Товчны тухай мÑдÑÑлÑл \r\n" +" -а товч Товчны одоогийн ач холбогдлыг мÑдÑÑ… \r\n" +" -Ñ‹ товч Товчны одоогийн ач холбогдлыг тохируулах \r\n" +" " + +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" msgstr "Өөрчлөлтийг идÑвхжүүлÑхийн тулд та дахин ÑхлүүлÑÑ… шаардлагатай.\n" -#: ../src/controlpanel/toolbar.py:115 -msgid "Cancel" -msgstr "Болих" - -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:294 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 msgid "Ok" msgstr "Тийм" -#: ../src/controlpanel/sectionview.py:34 ../src/controlpanel/gui.py:260 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:267 msgid "Changes require restart" msgstr "Өөрчлөхийн тулд дахин ÑхлүүлÑÑ… Ñ…ÑÑ€ÑгтÑй" -#: ../src/controlpanel/gui.py:259 +#: ../src/controlpanel/gui.py:266 msgid "Warning" msgstr "Ðнхаар" -#: ../src/controlpanel/gui.py:263 +#: ../src/controlpanel/gui.py:270 msgid "Cancel changes" msgstr "Өөрчлөлтийг цуцлах" -#: ../src/controlpanel/gui.py:267 -msgid "Later" -msgstr "Дараа" - -#: ../src/controlpanel/gui.py:271 +#: ../src/controlpanel/gui.py:279 msgid "Restart now" msgstr "Одоо ÑхлүүлÑÑ… Ò¯Ò¯" @@ -536,36 +561,36 @@ msgstr "Үл мÑдÑгдÑÑ… тархалтын ÑүлжÑÑ" msgid "Decline" msgstr "Үл зөвшөөрөх" -#: ../src/view/home/favoritesview.py:285 +#: ../src/view/home/favoritesview.py:287 msgid "Registration Failed" msgstr "БүртгÑл бүтÑлгүйтлÑÑ" -#: ../src/view/home/favoritesview.py:286 +#: ../src/view/home/favoritesview.py:288 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:288 +#: ../src/view/home/favoritesview.py:290 msgid "Registration Successful" msgstr "БүртгÑл амжилттай" -#: ../src/view/home/favoritesview.py:289 +#: ../src/view/home/favoritesview.py:291 msgid "You are now registered with your school server." msgstr "Та одоо Ñургуулийн Ñерверт бүртгÑгдлÑÑ." -#: ../src/view/home/favoritesview.py:405 +#: ../src/view/home/favoritesview.py:407 msgid "Control Panel" msgstr "Удирдах Самбар" -#: ../src/view/home/favoritesview.py:416 +#: ../src/view/home/favoritesview.py:418 msgid "Restart" msgstr "Дахин ÑхлүүлÑÑ…" -#: ../src/view/home/favoritesview.py:421 +#: ../src/view/home/favoritesview.py:423 msgid "Shutdown" msgstr "Унтраах" -#: ../src/view/home/favoritesview.py:427 +#: ../src/view/home/favoritesview.py:429 msgid "Register" msgstr "БүртгүүлÑÑ…" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-10-01 09:38-0400\n" +"POT-Creation-Date: 2008-09-01 18:31-0400\n" +"PO-Revision-Date: 2008-09-02 15:10-0400\n" "Last-Translator: Myckel Habets <myckel@sdf.lonestar.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -15,44 +15,44 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Pootle 1.1.0rc2\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../src/intro/intro.py:65 ../src/controlpanel/view/aboutme.py:100 msgid "Name:" msgstr "Naam:" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:97 msgid "Click to change color:" msgstr "Klik om de kleur te veranderen:" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../src/intro/intro.py:148 msgid "Back" msgstr "Terug" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:162 ../src/controlpanel/toolbar.py:61 msgid "Done" msgstr "Klaar" -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:165 msgid "Next" msgstr "Volgende" -#: ../src/view/BuddyMenu.py:60 +#: ../src/view/BuddyMenu.py:58 msgid "Remove friend" msgstr "Verwijder vriend" -#: ../src/view/BuddyMenu.py:63 +#: ../src/view/BuddyMenu.py:61 msgid "Make friend" msgstr "Maak vriend" -#: ../src/view/BuddyMenu.py:92 +#: ../src/view/BuddyMenu.py:90 #, python-format msgid "Invite to %s" msgstr "Nodig uit voor %s" -#: ../src/view/clipboardmenu.py:51 +#: ../src/view/clipboardmenu.py:48 msgid "Remove" msgstr "Verwijderen" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../src/view/clipboardmenu.py:53 ../src/view/clipboardmenu.py:79 msgid "Open" msgstr "Openen" @@ -61,18 +61,22 @@ msgstr "Openen" # TODO: Implement stopping downloads # self._stop_item.connect('activate', self._stop_item_activate_cb) # self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 msgid "Keep" msgstr "Bewaar" -#: ../src/view/clipboardmenu.py:83 +#: ../src/view/clipboardmenu.py:84 msgid "Open with" msgstr "Openen met" -#: ../src/view/clipboardmenu.py:228 +#: ../src/view/clipboardmenu.py:216 #, python-format -msgid "%s clipping" -msgstr "%s in klembord zetten" +msgid "Clipboard object: %s." +msgstr "Klembord object: %s." #: ../src/hardware/keydialog.py:150 msgid "Key Type:" @@ -88,73 +92,83 @@ msgstr "Encryptie type:" #: ../src/hardware/schoolserver.py:17 msgid "Cannot obtain data needed for registration." -msgstr "" -"Kan vereiste gegevens die nodig zijn voor de registratie niet verkrijgen." +msgstr "Kan vereiste gegevens voor registratie niet verkrijgen." #: ../src/hardware/schoolserver.py:31 msgid "Cannot connect to the server." -msgstr "Kan niet met de server verbinden." +msgstr "Kan niet met server verbinden." #: ../src/hardware/schoolserver.py:36 msgid "The server could not complete the request." msgstr "De server kon de aanvraag niet voltooien." -#: ../src/view/Shell.py:251 +#: ../src/view/Shell.py:262 msgid "Screenshot" msgstr "Schermafdruk" -#: ../src/view/home/HomeBox.py:78 +#: ../src/view/home/HomeBox.py:81 msgid "Confirm erase" msgstr "Bevestig wissen" -#: ../src/view/home/HomeBox.py:80 +#: ../src/view/home/HomeBox.py:83 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "Bevestig wissen: Wilt u permanent %s wissen?" -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 +#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 msgid "Erase" msgstr "Wissen" -#: ../src/view/home/HomeBox.py:117 +#: ../src/view/home/HomeBox.py:120 msgid "Software Update" msgstr "Software update" -#: ../src/view/home/HomeBox.py:118 +#: ../src/view/home/HomeBox.py:121 msgid "Update your activities to ensure compatibility with your new software" msgstr "" -"Update je activiteiten om zeker ervan te zijn dat ze met je nieuwe software " +"Update je activiteiten om er zeker van te zijn dat ze met je nieuwe software " "compatibel zijn." -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "Annuleren" -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 +#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:276 msgid "Later" msgstr "Later" -#: ../src/view/home/HomeBox.py:127 +#: ../src/view/home/HomeBox.py:130 msgid "Check now" msgstr "Controleer nu" -#: ../src/view/home/HomeBox.py:261 +#: ../src/view/home/HomeBox.py:266 msgid "List view" msgstr "Lijstweergave" -#: ../src/view/home/HomeBox.py:262 +#: ../src/view/home/HomeBox.py:267 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:320 +#: ../src/view/home/HomeBox.py:325 msgid "Favorites view" msgstr "Favorietenweergave" -#: ../src/view/home/HomeBox.py:321 +#: ../src/view/home/HomeBox.py:326 msgid "<Ctrl>1" msgstr "<Ctrl>1" +# TRANS: label for the freeform layout in the favorites view +#. TRANS: label for the freeform layout in the favorites view +#: ../src/view/home/HomeBox.py:334 +msgid "Freeform" +msgstr "VrijeVorm" + +# TRANS: label for the ring layout in the favorites view +#. TRANS: label for the ring layout in the favorites view +#: ../src/view/home/HomeBox.py:341 +msgid "Ring" +msgstr "Ring" + #: ../src/view/home/MeshBox.py:97 msgid "Connect" msgstr "Verbinden" @@ -167,34 +181,32 @@ msgstr "Verbinding verbreken" msgid "Disconnecting..." msgstr "Verbinding verbreken..." -#: ../src/view/home/MeshBox.py:159 +#: ../src/view/home/MeshBox.py:152 msgid "Connecting..." msgstr "Verbinden..." -# TODO: show the channel number #. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 +#: ../src/view/home/MeshBox.py:159 msgid "Connected" msgstr "Verbonden" -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 +#. only temporarily +#: ../src/view/home/MeshBox.py:211 ../src/view/devices/network/mesh.py:51 +#: ../src/view/devices/network/mesh.py:92 +#: ../src/view/devices/network/mesh.py:96 msgid "Mesh Network" msgstr "Mesh netwerk" -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/MeshBox.py:214 ../src/view/devices/network/wireless.py:160 +#: ../src/view/devices/network/mesh.py:125 msgid "Disconnect..." msgstr "Verbinding verbreken..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 +#: ../src/view/home/MeshBox.py:302 ../src/view/palettes.py:61 msgid "Resume" msgstr "Hervatten" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../src/view/home/MeshBox.py:307 ../src/view/frame/activitiestray.py:205 msgid "Join" msgstr "Bijvoegen" @@ -223,19 +235,24 @@ msgstr "Opgeladen" msgid "My Speakers" msgstr "Mijn Speakers" -#: ../src/view/devices/speaker.py:125 +#: ../src/view/devices/speaker.py:119 msgid "Unmute" msgstr "Ontdempen" -#: ../src/view/devices/speaker.py:128 +#: ../src/view/devices/speaker.py:122 msgid "Mute" msgstr "Dempen" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:37 +#, python-format +msgid "IP address: %s" +msgstr "IP adres: %s" + +#: ../src/view/devices/network/wireless.py:86 msgid "Disconnected" msgstr "Verbinding verbroken" -#: ../src/view/devices/network/wireless.py:143 +#: ../src/view/devices/network/wireless.py:178 msgid "Channel" msgstr "Kanaal" @@ -274,9 +291,7 @@ msgstr "sugar-control-panel: sleutel=%s is geen beschikbare optie" msgid "sugar-control-panel: %s" msgstr "sugar-control-panel: %s" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 +#: ../src/controlpanel/cmd.py:33 msgid "" "Usage: sugar-control-panel [ option ] key [ args ... ] \n" " Control for the sugar environment. \n" @@ -300,111 +315,156 @@ msgstr "" " -c sleutel wis de huidige waarde van de sleutel \n" " " -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" -msgstr "Om je veranderingen toe te passen moet je sugar herstarten.\n" +msgstr "Om uw veranderingen toe te passen moet u sugar herstarten.\r\n" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 msgid "Ok" msgstr "Ok" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:268 msgid "Changes require restart" msgstr "Verandering vereist een herstart" -#: ../src/controlpanel/gui.py:264 +#: ../src/controlpanel/gui.py:267 msgid "Warning" msgstr "Waarschuwing" -#: ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/gui.py:271 msgid "Cancel changes" msgstr "Veranderingen annuleren" -#: ../src/controlpanel/gui.py:277 +#: ../src/controlpanel/gui.py:280 msgid "Restart now" msgstr "Herstart nu" -#: ../src/controlpanel/aboutme/model.py:44 +#: ../src/controlpanel/model/aboutme.py:44 msgid "You must enter a name." -msgstr "Je moet een naam invoeren." +msgstr "U moet een naam invoeren." -#: ../src/controlpanel/aboutme/model.py:69 +#: ../src/controlpanel/model/aboutme.py:69 #, python-format msgid "stroke: color=%s hue=%s" msgstr "streep: kleur=%s tint=%s" -#: ../src/controlpanel/aboutme/model.py:72 +#: ../src/controlpanel/model/aboutme.py:72 #, python-format msgid "stroke: %s" msgstr "streep: %s" -#: ../src/controlpanel/aboutme/model.py:74 +#: ../src/controlpanel/model/aboutme.py:74 #, python-format msgid "fill: color=%s hue=%s" msgstr "vulling: kleur=%s tint=%s" -#: ../src/controlpanel/aboutme/model.py:76 +#: ../src/controlpanel/model/aboutme.py:76 #, python-format msgid "fill: %s" msgstr "vulling: %s" -#: ../src/controlpanel/aboutme/model.py:87 +#: ../src/controlpanel/model/aboutme.py:87 msgid "Error in specified color modifiers." msgstr "Fout in opgegeven kleurenmodificaties." -#: ../src/controlpanel/aboutme/model.py:90 +#: ../src/controlpanel/model/aboutme.py:90 msgid "Error in specified colors." msgstr "Fout in opgegeven kleuren." -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 +#: ../src/controlpanel/model/aboutxo.py:24 +msgid "Not available" +msgstr "Niet beschikbaar" + +#: ../src/controlpanel/model/datetime.py:85 +msgid "Error timezone does not exist." +msgstr "Fout tijdzone bestaat niet." + +#: ../src/controlpanel/model/frame.py:38 ../src/controlpanel/model/frame.py:60 +msgid "Value must be an integer." +msgstr "Waarde moet een geheel getal zijn." + +#: ../src/controlpanel/model/language.py:28 +msgid "Could not access ~/.i18n. Create standard settings." +msgstr "Kon niet bij ~/.i18n komen. Standaard instellingen aanmaken." + +#: ../src/controlpanel/model/language.py:110 +#, python-format +msgid "Language for code=%s could not be determined." +msgstr "Taal voor code=%s kon niet bepaald worden." + +#: ../src/controlpanel/model/language.py:127 +#, python-format +msgid "Sorry I do not speak '%s'." +msgstr "Sorry, I spreek geen '%s'." + +#: ../src/controlpanel/model/network.py:48 +msgid "You must enter a server." +msgstr "U moet een server opgeven." + +#: ../src/controlpanel/model/network.py:63 +msgid "State is unknown." +msgstr "Status is onbekend." + +#: ../src/controlpanel/model/network.py:83 +msgid "Error in specified radio argument use on/off." +msgstr "Fout in opgegeven keuze argument gebruik aan/uit." + +#: ../src/controlpanel/model/power.py:57 +msgid "Error in automatic pm argument, use on/off." +msgstr "Fout in automatisch energiebeheer argument, gebruik on/off." + +#: ../src/controlpanel/model/power.py:86 +msgid "Error in extreme pm argument, use on/off." +msgstr "Fout in extreem energiebeheer argument, gebruik on/off." + +#: ../src/controlpanel/view/aboutme.py:32 msgid "About Me" msgstr "Over mij" -#: ../src/controlpanel/aboutme/view.py:134 +#: ../src/controlpanel/view/aboutme.py:134 msgid "Click to change your color:" msgstr "Klik om de kleur te veranderen:" -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "Niet beschikbaar" +#: ../src/controlpanel/view/aboutxo.py:28 +msgid "About my XO" +msgstr "Over mijn XO" -#: ../src/controlpanel/aboutxo/view.py:55 +#: ../src/controlpanel/view/aboutxo.py:59 msgid "Identity" msgstr "Identiteit" -#: ../src/controlpanel/aboutxo/view.py:64 +#: ../src/controlpanel/view/aboutxo.py:68 msgid "Serial Number:" msgstr "Serienummer:" -#: ../src/controlpanel/aboutxo/view.py:87 +#: ../src/controlpanel/view/aboutxo.py:91 msgid "Software" msgstr "Software" -#: ../src/controlpanel/aboutxo/view.py:96 +#: ../src/controlpanel/view/aboutxo.py:100 msgid "Build:" msgstr "Bouw:" -#: ../src/controlpanel/aboutxo/view.py:111 +#: ../src/controlpanel/view/aboutxo.py:115 msgid "Sugar:" msgstr "Sugar:" -#: ../src/controlpanel/aboutxo/view.py:126 +#: ../src/controlpanel/view/aboutxo.py:130 msgid "Firmware:" msgstr "Firmware:" -#: ../src/controlpanel/aboutxo/view.py:148 +#: ../src/controlpanel/view/aboutxo.py:152 msgid "Copyright and License" msgstr "Copyright en licentie" -#: ../src/controlpanel/aboutxo/view.py:156 +#: ../src/controlpanel/view/aboutxo.py:160 msgid "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." msgstr "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; en anderen die " "bijgedragen hebben." -#: ../src/controlpanel/aboutxo/view.py:163 +#: ../src/controlpanel/view/aboutxo.py:166 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -412,241 +472,157 @@ msgid "" "therein." msgstr "" "Sugar is de grafische gebruikersinterface waar je momenteel naar kijkt. " -"Sugar is vrije software, uitgegeven onder de GNU General Public License, en " -"je mag het aanpassen en/of kopieën distribueren onder de condities zoals " -"vermeld in de licentie." +"Sugar is vrije software, uitgegeven onder de GNU General Public License, en " +"u mag het aanpassen en/of kopieën distribueren onder de condities vermeld " +"in de licentie." -#: ../src/controlpanel/aboutxo/view.py:175 +#: ../src/controlpanel/view/aboutxo.py:178 msgid "Full license:" msgstr "Volledige licentie:" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "Over mijn XO" - -#: ../src/controlpanel/datetime/model.py:89 -msgid "Error timezone does not exist." -msgstr "Fout tijdzone bestaat niet." +#: ../src/controlpanel/view/datetime.py:29 +msgid "Date & Time" +msgstr "Datum en Tijd" -#: ../src/controlpanel/datetime/view.py:68 +#: ../src/controlpanel/view/datetime.py:72 msgid "Timezone" msgstr "Tijdzone" -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "Datum en Tijd" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "Waarde moet een geheel getal zijn." +#: ../src/controlpanel/view/frame.py:28 +msgid "Frame" +msgstr "Kader" -#: ../src/controlpanel/frame/view.py:26 +#: ../src/controlpanel/view/frame.py:30 msgid "never" -msgstr "nooit" +msgstr "Nooit" -#: ../src/controlpanel/frame/view.py:27 +#: ../src/controlpanel/view/frame.py:31 msgid "instantaneous" msgstr "direct" -#: ../src/controlpanel/frame/view.py:28 +#: ../src/controlpanel/view/frame.py:32 #, python-format msgid "%s seconds" msgstr "%s seconden" -#: ../src/controlpanel/frame/view.py:52 +#: ../src/controlpanel/view/frame.py:56 msgid "Activation Delay" msgstr "Activatievertraging" -#: ../src/controlpanel/frame/view.py:76 +#: ../src/controlpanel/view/frame.py:80 msgid "Corner" msgstr "Hoek" -#: ../src/controlpanel/frame/view.py:111 +#: ../src/controlpanel/view/frame.py:115 msgid "Edge" msgstr "Ribbe" -#: ../src/controlpanel/frame/__init__.py:21 -msgid "Frame" -msgstr "Kader" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "Kon niet bij ~/.i18n komen. Standaard instellingen aanmaken." - -#: ../src/controlpanel/language/model.py:114 -#, python-format -msgid "Language for code=%s could not be determined." -msgstr "Taal voor code=%s kon niet bepaald worden." - -#: ../src/controlpanel/language/model.py:131 -#, python-format -msgid "Sorry I do not speak '%s'." -msgstr "Sorry, I spreek geen '%s'." - -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 +#: ../src/controlpanel/view/language.py:29 +#: ../src/controlpanel/view/language.py:74 msgid "Language" msgstr "Taal" -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "Status is onbekend." - -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "Fout in opgegeven keuze argument gebruik aan/uit." - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 +#: ../src/controlpanel/view/network.py:28 msgid "Network" msgstr "Netwerk" -#: ../src/controlpanel/network/view.py:54 +#: ../src/controlpanel/view/network.py:53 msgid "Wireless" msgstr "Draadloos" -#: ../src/controlpanel/network/view.py:62 -msgid "Turn of the wireless radio to save battery life" -msgstr "Draadloze zender uitzetten om de batterij te besparen" +#: ../src/controlpanel/view/network.py:61 +msgid "Radio:" +msgstr "Radio:" -#: ../src/controlpanel/network/view.py:75 -msgid "Radio" -msgstr "Zender" - -#: ../src/controlpanel/network/view.py:91 -msgid "Discard network history if you have trouble connecting to the network" -msgstr "" -"Gooi de netwerkgeschiedenis weg als je problemen hebt om met het netwerk te " -"verbinden" - -#: ../src/controlpanel/network/view.py:100 -msgid "Discard network history" -msgstr "Netwerkgeschiedenis weggooien" - -#: ../src/controlpanel/network/view.py:113 +#: ../src/controlpanel/view/network.py:94 msgid "Mesh" msgstr "Mesh" -#: ../src/controlpanel/network/view.py:122 +#: ../src/controlpanel/view/network.py:103 msgid "Server:" msgstr "Server:" -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "Fout in automatisch energiebeheer argument, gebruik on/off." - -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "Fout in extreem energiebeheer argument, gebruik on/off." +#: ../src/controlpanel/view/power.py:27 +msgid "Power" +msgstr "Energie" -#: ../src/controlpanel/power/view.py:47 +#: ../src/controlpanel/view/power.py:51 msgid "Power management" msgstr "Energiebeheer" -#: ../src/controlpanel/power/view.py:57 +#: ../src/controlpanel/view/power.py:61 msgid "Automatic power management (increases battery life)" msgstr "Automatisch energiebeheer (verhoogt gebruiksduur accu)" -#: ../src/controlpanel/power/view.py:85 +#: ../src/controlpanel/view/power.py:89 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Extreme power management (disables wireless radio, increases battery life)" msgstr "" -"Extreem energiebeheer (deactiveert draadloze zender, verhoogt gebruiksduur " +"Extreem energiebeheer (deactiveert draadloze radio, verhoogt gebruiksduur " "accu)" -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "Energie" - -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:154 msgid "Connected to a School Mesh Portal" msgstr "Verbonden met een School Mesh Portaal" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:156 msgid "Looking for a School Mesh Portal..." msgstr "Zoeken naar een School Mesh Portaal..." -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:159 msgid "Connected to an XO Mesh Portal" msgstr "Verbonden met een XO Mesh Portaal" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:161 msgid "Looking for an XO Mesh Portal..." msgstr "Zoeken naar een XO Mesh Portaal..." -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:164 msgid "Connected to a Simple Mesh" msgstr "Verbinden met een Eenvoudige Mesh" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:166 msgid "Starting a Simple Mesh" msgstr "Start een Eenvoudige Mesh" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:173 msgid "Unknown Mesh" msgstr "Onbekende Mesh" -#: ../src/view/frame/activitiestray.py:211 +#: ../src/view/frame/activitiestray.py:210 msgid "Decline" msgstr "Weigeren" -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "VrijeVorm" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "Ring" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "Spiraal" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "Vierkant" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "Driehoek" - -#: ../src/view/home/favoritesview.py:295 +#: ../src/view/home/favoritesview.py:287 msgid "Registration Failed" msgstr "Registratie mislukt" -#: ../src/view/home/favoritesview.py:296 +#: ../src/view/home/favoritesview.py:288 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:298 +#: ../src/view/home/favoritesview.py:290 msgid "Registration Successful" msgstr "Registratie succesvol uitgevoerd" -#: ../src/view/home/favoritesview.py:299 +#: ../src/view/home/favoritesview.py:291 msgid "You are now registered with your school server." msgstr "Je bent nu geregistreerd bij je schoolserver." -#: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "Instellingen" +#: ../src/view/home/favoritesview.py:407 +msgid "Control Panel" +msgstr "Configuratiepaneel" -#: ../src/view/home/favoritesview.py:425 +#: ../src/view/home/favoritesview.py:418 msgid "Restart" msgstr "Herstarten" -#: ../src/view/home/favoritesview.py:430 +#: ../src/view/home/favoritesview.py:423 msgid "Shutdown" msgstr "Afsluiten" -#: ../src/view/home/favoritesview.py:436 +#: ../src/view/home/favoritesview.py:429 msgid "Register" msgstr "Registreren" @@ -658,153 +634,27 @@ msgstr "Beginnen..." msgid "Stop" msgstr "Stop" -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 +#: ../src/view/palettes.py:104 msgid "Start" msgstr "Start" -#: ../src/view/palettes.py:138 +#: ../src/view/palettes.py:132 msgid "Remove favorite" msgstr "Verwijder favoriet" -#: ../src/view/palettes.py:142 +#: ../src/view/palettes.py:136 msgid "Make favorite" msgstr "Maak favoriet" -#: ../src/view/palettes.py:191 +#: ../src/view/palettes.py:185 msgid "Show contents" msgstr "Inhoud weergeven" -#: ../src/view/palettes.py:215 +#: ../src/view/palettes.py:209 #, python-format msgid "%(free_space)d MB Free" msgstr "%(free_space)d MB vrij" -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "Zoeken" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "Ieder tijdstip" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "Vandaag" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "Sinds gisteren" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "Afgelopen week" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "Afgelopen maand" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "Afgelopen jaar" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "Iedereen" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "Mijn vrienden" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "Mijn klas" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "Alles" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "Kopieer" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "Naamloos" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "Dagboek" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "Geen voorbeeld" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "Deelnemers:" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "Omschrijving:" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "Labels:" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "Kies een object" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "Sluiten" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "Loskoppelen" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "Geen datum" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "Je dagboek is leeg" - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "Geen overeenkomende ingangen " - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "Je dagboek is vol" - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." -msgstr "Verwijder a.u.b. oude dagboekingangen om ruimte te maken voor nieuwe." - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "Dagboek weergeven" - -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "Klembord object: %s." - -#~ msgid "You must enter a server." -#~ msgstr "U moet een server opgeven." - -#~ msgid "Control Panel" -#~ msgstr "Configuratiepaneel" - #~ msgid "<Ctrl>R" #~ msgstr "<Ctrl>R" @@ -826,6 +676,9 @@ msgstr "Dagboek weergeven" #~ msgid "Redo" #~ msgstr "Doe opnieuw" +#~ msgid "Copy" +#~ msgstr "Kopieer" + #~ msgid "Paste" #~ msgstr "Plak" @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-01 18:31-0400\n" -"PO-Revision-Date: 2008-09-02 10:35-0400\n" +"POT-Creation-Date: 2008-09-19 00:30-0400\n" +"PO-Revision-Date: 2008-09-19 14:58-0400\n" "Last-Translator: Eduardo H. Silva <HoboPrimate@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" @@ -35,15 +35,15 @@ msgstr "Finalizar" msgid "Next" msgstr "Próximo" -#: ../src/view/BuddyMenu.py:58 +#: ../src/view/BuddyMenu.py:60 msgid "Remove friend" msgstr "Remover amigo" -#: ../src/view/BuddyMenu.py:61 +#: ../src/view/BuddyMenu.py:63 msgid "Make friend" msgstr "Fazer amigo" -#: ../src/view/BuddyMenu.py:90 +#: ../src/view/BuddyMenu.py:92 #, python-format msgid "Invite to %s" msgstr "Convidar para %s" @@ -64,7 +64,7 @@ msgstr "Abrir" #. TODO: Implement stopping downloads #. self._stop_item.connect('activate', self._stop_item_activate_cb) #. self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:87 +#: ../src/view/clipboardmenu.py:63 ../src/view/home/HomeBox.py:85 msgid "Keep" msgstr "Guardar" @@ -101,71 +101,61 @@ msgstr "Não foi possÃvel ligar ao servidor." msgid "The server could not complete the request." msgstr "Não foi possÃvel ao servidor completar o pedido." -#: ../src/view/Shell.py:262 +#: ../src/view/Shell.py:251 msgid "Screenshot" msgstr "Imagem do Ecrã" -#: ../src/view/home/HomeBox.py:81 +#: ../src/view/home/HomeBox.py:79 msgid "Confirm erase" msgstr "Confirmação de apagar" -#: ../src/view/home/HomeBox.py:83 +#: ../src/view/home/HomeBox.py:81 #, python-format msgid "Confirm erase: Do you want to permanently erase %s?" msgstr "Confirmação de apagar: Queres apagar permanentemente %s?" -#: ../src/view/home/HomeBox.py:90 ../src/view/palettes.py:120 +#: ../src/view/home/HomeBox.py:88 ../src/view/palettes.py:120 msgid "Erase" msgstr "Apagar" -#: ../src/view/home/HomeBox.py:120 +#: ../src/view/home/HomeBox.py:118 msgid "Software Update" msgstr "Actualização do Software" -#: ../src/view/home/HomeBox.py:121 +#: ../src/view/home/HomeBox.py:119 msgid "Update your activities to ensure compatibility with your new software" msgstr "" "Actualiza as tuas actividades para assegurar compatibilidade com o teu novo " "software" -#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/toolbar.py:115 +#: ../src/view/home/HomeBox.py:123 ../src/controlpanel/toolbar.py:115 msgid "Cancel" msgstr "Cancelar" -#: ../src/view/home/HomeBox.py:127 ../src/controlpanel/gui.py:276 +#: ../src/view/home/HomeBox.py:125 ../src/controlpanel/gui.py:286 msgid "Later" msgstr "Mais tarde" -#: ../src/view/home/HomeBox.py:130 +#: ../src/view/home/HomeBox.py:128 msgid "Check now" msgstr "Verificar agora" -#: ../src/view/home/HomeBox.py:266 +#: ../src/view/home/HomeBox.py:262 msgid "List view" msgstr "Vista de Lista" -#: ../src/view/home/HomeBox.py:267 +#: ../src/view/home/HomeBox.py:263 msgid "<Ctrl>2" msgstr "<Ctrl>2" -#: ../src/view/home/HomeBox.py:325 +#: ../src/view/home/HomeBox.py:321 msgid "Favorites view" msgstr "Vista de Favoritos" -#: ../src/view/home/HomeBox.py:326 +#: ../src/view/home/HomeBox.py:322 msgid "<Ctrl>1" msgstr "<Ctrl>1" -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/HomeBox.py:334 -msgid "Freeform" -msgstr "Livre" - -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/HomeBox.py:341 -msgid "Ring" -msgstr "Anel" - #: ../src/view/home/MeshBox.py:97 msgid "Connect" msgstr "Ligar" @@ -326,25 +316,25 @@ msgstr "" #: ../src/controlpanel/cmd.py:46 msgid "To apply your changes you have to restart sugar.\n" -msgstr "Para aplicar as mudanças tens que reiniciar o sugar.\n" +msgstr "Para aplicar as alterações tens que reiniciar o sugar.\n" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:296 +#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 msgid "Ok" msgstr "Ok" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:268 +#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:278 msgid "Changes require restart" -msgstr "As mudanças necessitam que reinicies" +msgstr "As alterações feitas necessitam que reinicies" -#: ../src/controlpanel/gui.py:267 +#: ../src/controlpanel/gui.py:277 msgid "Warning" msgstr "Aviso" -#: ../src/controlpanel/gui.py:271 +#: ../src/controlpanel/gui.py:281 msgid "Cancel changes" -msgstr "Cancelar mudanças" +msgstr "Cancelar alterações" -#: ../src/controlpanel/gui.py:280 +#: ../src/controlpanel/gui.py:290 msgid "Restart now" msgstr "Reiniciar agora" @@ -384,7 +374,7 @@ msgstr "Erro nas cores especificadas." msgid "Not available" msgstr "Não disponÃvel" -#: ../src/controlpanel/model/datetime.py:85 +#: ../src/controlpanel/model/datetime.py:89 msgid "Error timezone does not exist." msgstr "Erro: fuso horário não existe." @@ -396,25 +386,21 @@ msgstr "Valor tem que ser um número inteiro." msgid "Could not access ~/.i18n. Create standard settings." msgstr "Não foi possÃvel aceder a ~/.i18n. Cria definições normais." -#: ../src/controlpanel/model/language.py:110 +#: ../src/controlpanel/model/language.py:114 #, python-format msgid "Language for code=%s could not be determined." msgstr "Não foi possÃvel determinar a linguagem para o código=%s." -#: ../src/controlpanel/model/language.py:127 +#: ../src/controlpanel/model/language.py:131 #, python-format msgid "Sorry I do not speak '%s'." msgstr "Desculpa, eu não falo '%s'." -#: ../src/controlpanel/model/network.py:48 -msgid "You must enter a server." -msgstr "Precisas de introduzir um servidor." - -#: ../src/controlpanel/model/network.py:63 +#: ../src/controlpanel/model/network.py:62 msgid "State is unknown." msgstr "O estado é desconhecido." -#: ../src/controlpanel/model/network.py:83 +#: ../src/controlpanel/model/network.py:82 msgid "Error in specified radio argument use on/off." msgstr "Erro no argumento de rádio especificado, utiliza on/off." @@ -472,7 +458,7 @@ msgid "" msgstr "" "© 2008 One Laptop per Child Association Inc; Red Hat Inc; e Contribuidores." -#: ../src/controlpanel/view/aboutxo.py:166 +#: ../src/controlpanel/view/aboutxo.py:167 msgid "" "Sugar is the graphical user interface that you are looking at. Sugar is free " "software, covered by the GNU General Public License, and you are welcome to " @@ -481,10 +467,10 @@ msgid "" msgstr "" "O Sugar é a interface gráfica de utilizador que estás a utilizar. O Sugar é " "software livre, licenciado sob a GNU General Public License, e és bem vindo " -"a fazer mudanças a ele e/ou distribuir cópias dele, segundo certas condições " -"descritas a seguir." +"a fazer alterações a ele e/ou a distribuir cópias dele, segundo certas " +"condições descritas a seguir." -#: ../src/controlpanel/view/aboutxo.py:178 +#: ../src/controlpanel/view/aboutxo.py:179 msgid "Full license:" msgstr "Licença Completa:" @@ -534,19 +520,33 @@ msgstr "Linguagem" msgid "Network" msgstr "Rede" -#: ../src/controlpanel/view/network.py:53 +#: ../src/controlpanel/view/network.py:54 msgid "Wireless" msgstr "Rede sem fios" -#: ../src/controlpanel/view/network.py:61 -msgid "Radio:" -msgstr "Rádio:" +#: ../src/controlpanel/view/network.py:62 +msgid "Turn of the wireless radio to save battery life" +msgstr "Desliga o rádio da rede sem fios para aumentar o tempo de bateria" + +#: ../src/controlpanel/view/network.py:75 +msgid "Radio" +msgstr "Rádio" -#: ../src/controlpanel/view/network.py:94 +#: ../src/controlpanel/view/network.py:91 +msgid "Discard network history if you have trouble connecting to the network" +msgstr "" +"Descarta o histórico da configuração de rede se tiveres problemas em ligar-" +"te à rede" + +#: ../src/controlpanel/view/network.py:100 +msgid "Discard network history" +msgstr "Descartar histórico da configuração de rede" + +#: ../src/controlpanel/view/network.py:113 msgid "Mesh" msgstr "Mesh" -#: ../src/controlpanel/view/network.py:103 +#: ../src/controlpanel/view/network.py:122 msgid "Server:" msgstr "Servidor:" @@ -601,36 +601,36 @@ msgstr "Mesh Desconhecida" msgid "Decline" msgstr "Recusar" -#: ../src/view/home/favoritesview.py:287 +#: ../src/view/home/favoritesview.py:296 msgid "Registration Failed" msgstr "O Registro Falhou" -#: ../src/view/home/favoritesview.py:288 +#: ../src/view/home/favoritesview.py:297 #, python-format msgid "%s" msgstr "%s" -#: ../src/view/home/favoritesview.py:290 +#: ../src/view/home/favoritesview.py:299 msgid "Registration Successful" msgstr "O Registro teve Sucesso" -#: ../src/view/home/favoritesview.py:291 +#: ../src/view/home/favoritesview.py:300 msgid "You are now registered with your school server." msgstr "Estás agora registrado com o teu servidor de escola." -#: ../src/view/home/favoritesview.py:407 +#: ../src/view/home/favoritesview.py:420 msgid "Control Panel" msgstr "Painel de Controlo" -#: ../src/view/home/favoritesview.py:418 +#: ../src/view/home/favoritesview.py:425 msgid "Restart" msgstr "Reiniciar" -#: ../src/view/home/favoritesview.py:423 +#: ../src/view/home/favoritesview.py:430 msgid "Shutdown" msgstr "Desligar" -#: ../src/view/home/favoritesview.py:429 +#: ../src/view/home/favoritesview.py:436 msgid "Register" msgstr "Registrar" @@ -646,23 +646,32 @@ msgstr "Parar" msgid "Start" msgstr "Iniciar" -#: ../src/view/palettes.py:132 +#: ../src/view/palettes.py:138 msgid "Remove favorite" msgstr "Remover favorito" -#: ../src/view/palettes.py:136 +#: ../src/view/palettes.py:142 msgid "Make favorite" msgstr "Tornar favorito" -#: ../src/view/palettes.py:185 +#: ../src/view/palettes.py:191 msgid "Show contents" msgstr "Mostrar os conteúdos" -#: ../src/view/palettes.py:209 +#: ../src/view/palettes.py:215 #, python-format msgid "%(free_space)d MB Free" msgstr "%(free_space)d MB Livres" +#~ msgid "Freeform" +#~ msgstr "Livre" + +#~ msgid "Ring" +#~ msgstr "Anel" + +#~ msgid "You must enter a server." +#~ msgstr "Precisas de introduzir um servidor." + #~ msgid "© 2008 One Laptop per Child Assocation " #~ msgstr "© 2008 One Laptop per Child Association" @@ -1,899 +1,341 @@ -# translation of sugar.po to Sinhala -# Rashan Anushka <rashan.uoc@gmail.com>, 2008. +# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. msgid "" msgstr "" -"Project-Id-Version: sugar\n" +"Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-09-30 07:45-0400\n" +"POT-Creation-Date: 2008-01-18 18:19+0000\n" +"PO-Revision-Date: 2008-02-07 08:42-0500\n" "Last-Translator: Rashan Anushka <rashan.uoc@gmail.com>\n" -"Language-Team: Sinhala <si@li.org>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Pootle 1.1.0rc2\n" +"X-Generator: Pootle 1.0.2\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../shell/intro/intro.py:67 msgid "Name:" msgstr "නම:" -#: ../src/intro/window.py:125 +#: ../shell/intro/intro.py:96 msgid "Click to change color:" msgstr "පà·à¶§ වෙනස් කිරීමට ක්ලික් කරන්න:" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../shell/intro/intro.py:146 msgid "Back" msgstr "ආපසු" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../shell/intro/intro.py:160 msgid "Done" -msgstr "කළà·" +msgstr "" -#: ../src/intro/window.py:192 +#: ../shell/intro/intro.py:163 msgid "Next" msgstr "ඊළඟ" -#: ../src/view/BuddyMenu.py:60 +#: ../shell/view/BuddyMenu.py:59 msgid "Remove friend" msgstr "මිà¶à·”ර෠ඉවà¶à·Š කරන්න" -#: ../src/view/BuddyMenu.py:63 +#: ../shell/view/BuddyMenu.py:62 msgid "Make friend" msgstr "මිà¶à·”රු වන්න" -#: ../src/view/BuddyMenu.py:92 +#: ../shell/view/BuddyMenu.py:84 #, python-format msgid "Invite to %s" msgstr "%s ට අඬගහන්න" -#: ../src/view/clipboardmenu.py:51 +#: ../shell/view/clipboardmenu.py:58 msgid "Remove" msgstr "ඉවà¶à·Š කරන්න" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../shell/view/clipboardmenu.py:63 msgid "Open" msgstr "විවෘචකරන්න" -# self._stop_item = MenuItem(_('Stop download'), 'stock-close') -# TODO: Implement stopping downloads -# self._stop_item.connect('activate', self._stop_item_activate_cb) -# self.append_menu_item(self._stop_item) -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 -msgid "Keep" -msgstr "à¶à¶¶à·à¶œà¶±à·Šà¶±" - -#: ../src/view/clipboardmenu.py:83 -msgid "Open with" -msgstr "විවෘචකළ යුà¶à·Šà¶à·š" +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../shell/view/clipboardmenu.py:73 +msgid "Add to journal" +msgstr "ජර්නලයට එක් කරන්න" -#: ../src/view/clipboardmenu.py:228 +#: ../shell/view/clipboardmenu.py:213 #, python-format -msgid "%s clipping" -msgstr "කප්පà·à¶¯à·”à·€ %s" +msgid "Clipboard object: %s." +msgstr "" -#: ../src/hardware/keydialog.py:150 +#: ../shell/hardware/keydialog.py:149 msgid "Key Type:" msgstr "යà¶à·”රු වර්ගය:" -#: ../src/hardware/keydialog.py:170 +#: ../shell/hardware/keydialog.py:169 msgid "Authentication Type:" msgstr "à·ƒà¶à·Šâ€à¶ºà·à¶´à¶± වර්ගය:" -#: ../src/hardware/keydialog.py:251 +#: ../shell/hardware/keydialog.py:250 msgid "Encryption Type:" msgstr "සංකේà¶à¶± වර්ගය:" -#: ../src/hardware/schoolserver.py:17 -msgid "Cannot obtain data needed for registration." -msgstr "ලියà·à¶´à¶¯à·’ංචිය සඳහ෠අවà·à·Šâ€à¶º දà¶à·Šà¶ ලබ෠ගචනොහà·à¶š." +#: ../shell/view/home/activitiesdonut.py:90 +msgid "Starting..." +msgstr "ආරම්භවේ..." -#: ../src/hardware/schoolserver.py:31 -msgid "Cannot connect to the server." -msgstr "සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ සම්බන්ධ විය නොහà·à¶š." +#: ../shell/view/home/activitiesdonut.py:104 ../shell/view/home/MeshBox.py:295 +msgid "Resume" +msgstr "නà·à·€à¶ ආරම්භ කරන්න" -#: ../src/hardware/schoolserver.py:36 -msgid "The server could not complete the request." -msgstr "සේවà·à¶¯à·à¶ºà¶šà¶ºà¶§ අයදුම සම්පූර්ණ කළ නොහà·à¶š." +#: ../shell/view/home/activitiesdonut.py:111 +#: ../lib/sugar/activity/activity.py:132 +msgid "Stop" +msgstr "නවà¶à·Šà·€à¶±à·Šà¶±" -#: ../src/view/Shell.py:251 +#: ../shell/view/Shell.py:285 msgid "Screenshot" -msgstr "à¶à·’රසටහන" - -#: ../src/view/home/HomeBox.py:78 -msgid "Confirm erase" -msgstr "මක෠දà·à¶¸à·“ම ස්ථීර කරන්න" - -#: ../src/view/home/HomeBox.py:80 -#, python-format -msgid "Confirm erase: Do you want to permanently erase %s?" -msgstr "මක෠දà·à¶¸à·“ම ස්ථීරයි: ඔබට %s සදහටම මක෠දà·à¶¸à·“මට අවà·à·Šâ€à¶ºà¶ºà¶¯?" - -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 -msgid "Erase" -msgstr "මකන්න" - -#: ../src/view/home/HomeBox.py:117 -msgid "Software Update" -msgstr "මෘදුකà·à¶‚ග යà·à·€à¶à·Šà¶šà·à¶½ කිරීම" - -#: ../src/view/home/HomeBox.py:118 -msgid "Update your activities to ensure compatibility with your new software" -msgstr "ඔබගේ නව මෘදුකà·à¶‚ගය සමඟ අනුකූලà¶à·à·€ සඳහ෠ඔබගේ ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸à·Š යà·à·€à¶à·Šà¶šà·à¶½ කරන්න" - -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 -msgid "Cancel" -msgstr "අවලංගු කරන්න" - -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 -msgid "Later" -msgstr "පසුව" - -#: ../src/view/home/HomeBox.py:127 -msgid "Check now" -msgstr "දà·à¶±à·Š පරික්ෂ෠කරන්න" - -#: ../src/view/home/HomeBox.py:261 -msgid "List view" -msgstr "ලà·à¶ºà·’ස්à¶à·” දසුන" +msgstr "" -#: ../src/view/home/HomeBox.py:262 -msgid "<Ctrl>2" -msgstr "<Ctrl>2" +#: ../shell/view/home/HomeBox.py:159 +msgid "Reboot" +msgstr "යළි අරඹන්න" -#: ../src/view/home/HomeBox.py:320 -msgid "Favorites view" -msgstr "කà·à¶¸à¶à·’ දසුන" +#: ../shell/view/home/HomeBox.py:164 +msgid "Shutdown" +msgstr "වස෠දමන්න" -#: ../src/view/home/HomeBox.py:321 -msgid "<Ctrl>1" -msgstr "<Ctrl>1" +#: ../shell/view/home/HomeBox.py:170 +msgid "Register" +msgstr "ලියà·à¶´à¶¯à·’ංචි කරන්න" -#: ../src/view/home/MeshBox.py:97 -msgid "Connect" -msgstr "සම්බන්ධ වෙන්න" +#: ../shell/view/home/HomeBox.py:175 ../shell/view/home/HomeBox.py:216 +msgid "About this XO" +msgstr "මෙම XO ගà·à¶±" -#: ../src/view/home/MeshBox.py:106 -msgid "Disconnect" -msgstr "විසන්ධි වන්න" - -# Only show disconnect when there's a mesh device, because mesh takes -# priority over the normal wireless device. NM doesn't have a "disconnect" -# method for a device either (for various reasons) so this doesn't -# have a good mapping -#: ../src/view/home/MeshBox.py:118 -msgid "Disconnecting..." -msgstr "විසන්ධිවේ..." - -# Only show disconnect when there's a mesh device, because mesh takes -# priority over the normal wireless device. NM doesn't have a "disconnect" -# method for a device either (for various reasons) so this doesn't -# have a good mapping -#: ../src/view/home/MeshBox.py:159 -msgid "Connecting..." -msgstr "සම්බන්ධවේ..." - -# TODO: show the channel number -#. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 -msgid "Connected" -msgstr "සම්බන්ධ විය" - -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 -msgid "Mesh Network" -msgstr "දà·à¶½à·à·ƒ ජà·à¶½à¶º" +#: ../shell/view/home/HomeBox.py:222 +msgid "Not available" +msgstr "නොපවà¶à·“" -# Only show disconnect when there's a mesh device, because mesh takes -# priority over the normal wireless device. NM doesn't have a "disconnect" -# method for a device either (for various reasons) so this doesn't -# have a good mapping -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#. Only show disconnect when there's a mesh device, because mesh takes +#. priority over the normal wireless device. NM doesn't have a "disconnect" +#. method for a device either (for various reasons) so this doesn't +#. have a good mapping +#: ../shell/view/home/MeshBox.py:90 ../shell/view/home/MeshBox.py:197 +#: ../shell/view/devices/network/wireless.py:113 +#: ../shell/view/devices/network/mesh.py:83 msgid "Disconnect..." msgstr "විසන්ධි කරන්න..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 -msgid "Resume" -msgstr "නà·à·€à¶ ආරම්භ කරන්න" +#: ../shell/view/home/MeshBox.py:195 ../shell/view/devices/network/mesh.py:37 +#: ../shell/view/devices/network/mesh.py:62 +#: ../shell/view/devices/network/mesh.py:66 +msgid "Mesh Network" +msgstr "දà·à¶½à·à·ƒ ජà·à¶½à¶º" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../shell/view/home/MeshBox.py:300 msgid "Join" msgstr "සම්බන්ධ වෙන්න" -#: ../src/view/devices/battery.py:45 -msgid "My Battery" -msgstr "මගේ බà·à¶§à¶»à·’ය" +#: ../shell/view/devices/battery.py:38 +msgid "My Battery life" +msgstr "මගේ බà·à¶§à¶»à·’ ආයු කà·à¶½à¶º" -#: ../src/view/devices/battery.py:114 -msgid "Charging" -msgstr "ආරà·à¶´à¶±à¶º වේ" +#: ../shell/view/devices/battery.py:94 +msgid "Battery charging" +msgstr "බà·à¶§à¶»à·’ය ආරà·à¶´à¶«à¶º වේ" -#: ../src/view/devices/battery.py:117 -msgid "Very little power remaining" -msgstr "ඉà¶à· සුළු බලයක් පවà¶à·“" +#: ../shell/view/devices/battery.py:96 +msgid "Battery discharging" +msgstr "බà·à¶§à¶»à·’ය විසර්ජනය වේ" -#: ../src/view/devices/battery.py:123 -#, python-format -msgid "%(hour)d:%(min).2d remaining" -msgstr "%(hour)d:%(min).2d ඉà¶à·’රියි" - -#: ../src/view/devices/battery.py:127 -msgid "Charged" -msgstr "ආරà·à¶´à·’à¶à¶ºà·’" - -#: ../src/view/devices/speaker.py:44 -msgid "My Speakers" -msgstr "මගේ ස්පීකරය" +#: ../shell/view/devices/battery.py:98 +msgid "Battery fully charged" +msgstr "බà·à¶§à¶»à·’ය සම්පූර්ණයෙන්ම ආරà·à¶´à·’à¶à¶ºà·’" -#: ../src/view/devices/speaker.py:125 -msgid "Unmute" -msgstr "නිෂ්à·à¶¶à·Šà¶°à¶à·à·€ නවà¶à¶±à·Šà¶±" - -#: ../src/view/devices/speaker.py:128 -msgid "Mute" -msgstr "නිà·à·Šà·à¶¶à·Šà¶¯ කරන්න" - -#: ../src/view/devices/network/wireless.py:67 +#: ../shell/view/devices/network/wireless.py:61 msgid "Disconnected" msgstr "විසන්ධිවී ඇà¶" -#: ../src/view/devices/network/wireless.py:143 +#: ../shell/view/devices/network/wireless.py:131 msgid "Channel" msgstr "නà·à¶½à·’කà·à·€" -#: ../src/view/frame/zoomtoolbar.py:37 +#: ../shell/view/frame/zoomtoolbar.py:42 msgid "Neighborhood" msgstr "වටපිටà·à·€" -#: ../src/view/frame/zoomtoolbar.py:39 +#: ../shell/view/frame/zoomtoolbar.py:54 msgid "Group" msgstr "සමූහය" -#: ../src/view/frame/zoomtoolbar.py:41 +#: ../shell/view/frame/zoomtoolbar.py:66 msgid "Home" msgstr "නිවස" -#: ../src/view/frame/zoomtoolbar.py:43 +#: ../shell/view/frame/zoomtoolbar.py:78 msgid "Activity" msgstr "ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸" -#: ../src/controlpanel/cmd.py:26 -#, python-format -msgid "" -"sugar-control-panel: WARNING, found more than one option with the same name: " -"%s module: %r" -msgstr "" -"sugar-control-panel: අවවà·à¶¯à¶ºà¶ºà·’, එකම නම (%s) සහිචවිකල්ප කිහිපයක් හමු විය.: " -"මොඩියුලය: %r" - -#: ../src/controlpanel/cmd.py:28 -#, python-format -msgid "sugar-control-panel: key=%s not an available option" -msgstr "sugar-control-panel: key=%s පවà¶à·’න විකල්පයක් නොවේ" - -#: ../src/controlpanel/cmd.py:29 -#, python-format -msgid "sugar-control-panel: %s" -msgstr "sugar-control-panel: %s" +#: ../lib/sugar/activity/activity.py:115 +msgid "Share with:" +msgstr "සමඟ බෙදà·à¶œà¶±à·Šà¶±:" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 -msgid "" -"Usage: sugar-control-panel [ option ] key [ args ... ] \n" -" Control for the sugar environment. \n" -" Options: \n" -" -h show this help message and exit \n" -" -l list all the available options \n" -" -h key show information about this key \n" -" -g key get the current value of the key \n" -" -s key set the current value for the key \n" -" -c key clear the current value for the key \n" -" " -msgstr "" -"භà·à·€à·’à¶à·à·€: sugar-control-panel [ විකල්පය ] key [ à¶à¶»à·Šà¶š ... ] \n" -" à·à·”ගර් පරිසරය සඳහ෠පà·à¶½à¶±à¶º. \n" -" විකල්ප: \n" -" -h මෙම උදව් පණිවිඩය පෙන්ව෠පිටවන්න\n" -" -l සියළු විකල්ප ලà·à¶ºà·’ස්à¶à·”ගචකරන්න\n" -" -h key key ගà·à¶± විස්à¶à¶» පෙන්වන්න \n" -" -g key key à·„à·’ පවà¶à·’න අගය පෙන්වන්න \n" -" -s key key à·„à·’ අගය සිටුචම් කරන්න \n" -" " - -#: ../src/controlpanel/cmd.py:48 -msgid "To apply your changes you have to restart sugar.\n" -msgstr "ඔබගේ වෙනස්කිරීම් බලපෑම සඳහ෠ෂුගර් යළි ඇරඹිය යුà¶à·”ය.\n" +#: ../lib/sugar/activity/activity.py:117 +msgid "Private" +msgstr "පුද්ගලික" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 -msgid "Ok" -msgstr "හරි" +#: ../lib/sugar/activity/activity.py:118 +msgid "My Neighborhood" +msgstr "මගේ වටපිටà·à·€" -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 -msgid "Changes require restart" -msgstr "වෙනස්කිරීම සඳහ෠යළි ඇරඹුමක් අවà·à·Šâ€à¶ºà·€à·š" +#: ../lib/sugar/activity/activity.py:126 +msgid "Keep" +msgstr "à¶à¶¶à·à¶œà¶±à·Šà¶±" -#: ../src/controlpanel/gui.py:264 -msgid "Warning" -msgstr "අවවà·à¶¯à¶ºà¶ºà·’" +#: ../lib/sugar/activity/activity.py:245 +msgid "Undo" +msgstr "පෙර ලෙස" -#: ../src/controlpanel/gui.py:268 -msgid "Cancel changes" -msgstr "වෙනස් කිරීම් අවලංගු කරන්න" +#: ../lib/sugar/activity/activity.py:250 +msgid "Redo" +msgstr "නà·à·€à¶ කරන්න" -#: ../src/controlpanel/gui.py:277 -msgid "Restart now" -msgstr "දà·à¶±à·Š යළි ආරම්භ කරන්න" +#: ../lib/sugar/activity/activity.py:260 +msgid "Copy" +msgstr "පිටපà¶à·Š කරන්න" -#: ../src/controlpanel/aboutme/model.py:44 -msgid "You must enter a name." -msgstr "ඔබ විසින් නමක් ඇà¶à·”ලà¶à·Š කළ යුà¶à·”ය." +#: ../lib/sugar/activity/activity.py:265 +msgid "Paste" +msgstr "අලවන්න" -#: ../src/controlpanel/aboutme/model.py:69 +#: ../lib/sugar/activity/activity.py:454 #, python-format -msgid "stroke: color=%s hue=%s" -msgstr "පහර: වර්ණය=%s පà·à·„à·à¶º=%s" +msgid "%s Activity" +msgstr "%s ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸" -#: ../src/controlpanel/aboutme/model.py:72 -#, python-format -msgid "stroke: %s" -msgstr "පහර: %s" +#: ../lib/sugar/activity/activity.py:824 +msgid "Keep error" +msgstr "නබ෠ගà·à¶±à·“මේ දà·à·‚යකි" -#: ../src/controlpanel/aboutme/model.py:74 -#, python-format -msgid "fill: color=%s hue=%s" -msgstr "පිරවුම: වර්ණය=%s පà·à·„à·à¶º=%s" +#: ../lib/sugar/activity/activity.py:825 +msgid "Keep error: all changes will be lost" +msgstr "à¶à¶¶à· ගà·à¶±à·“මේ දà·à·‚යකි: සියළු වෙනස් කිරීම් නà·à¶à·’වනු ඇà¶" -#: ../src/controlpanel/aboutme/model.py:76 -#, python-format -msgid "fill: %s" -msgstr "පිරවුම: %s" +#: ../lib/sugar/activity/activity.py:828 +msgid "Don't stop" +msgstr "නවà¶à·Šà·€à¶±à·Šà¶± එපà·" -#: ../src/controlpanel/aboutme/model.py:87 -msgid "Error in specified color modifiers." -msgstr "à·ƒà·à¶´à¶ºà·– වර්ණ විකරණකà·à¶»à¶šà¶ºà·š දà·à·‚යකි" +#: ../lib/sugar/activity/activity.py:831 +msgid "Stop anyway" +msgstr "කෙසේ හ෠නවà¶à·Šà·€à¶±à·Šà¶±" -#: ../src/controlpanel/aboutme/model.py:90 -msgid "Error in specified colors." -msgstr "à·ƒà·à¶´à¶ºà·– වර්ණවල දà·à·‚යකි" +#: ../lib/sugar/graphics/alert.py:164 ../lib/sugar/graphics/alert.py:206 +msgid "Cancel" +msgstr "අවලංගු කරන්න" -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 -msgid "About Me" -msgstr "මම ගà·à¶±" +#: ../lib/sugar/graphics/alert.py:168 +msgid "Ok" +msgstr "හරි" -#: ../src/controlpanel/aboutme/view.py:134 -msgid "Click to change your color:" -msgstr "ඔබගේ පà·à¶§ වෙනස් කිරීමට ක්ලික් කරන්න:" +#: ../lib/sugar/graphics/alert.py:216 +msgid "Continue" +msgstr "පවà¶à·Šà·€à·à¶œà·™à¶± යන්න" -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "නොපවà¶à·“" +#: ../lib/sugar/graphics/alert.py:244 +msgid "OK" +msgstr "හරි" -#: ../src/controlpanel/aboutxo/view.py:55 -msgid "Identity" -msgstr "අනන්â€à¶ºà¶à·à·€" +#: ../shell/controlpanel/control.py:213 +msgid "To apply your changes you have to restart sugar.\n" +msgstr "ඔබගේ වෙනස්කිරීම් බලපෑම සඳහ෠ෂුගර් යළි ඇරඹිය යුà¶à·”ය.\n" -#: ../src/controlpanel/aboutxo/view.py:64 -msgid "Serial Number:" -msgstr "අනුක්â€à¶»à¶¸à·’ක අංකය:" +#: ../shell/controlpanel/control.py:267 +msgid "Error in specified color modifiers." +msgstr "à·ƒà·à¶´à¶ºà·– වර්ණ විකරණකà·à¶»à¶šà¶ºà·š දà·à·‚යකි" -#: ../src/controlpanel/aboutxo/view.py:87 -msgid "Software" -msgstr "මෘදුකà·à¶‚ගය" +#: ../shell/controlpanel/control.py:270 +msgid "Error in specified colors." +msgstr "à·ƒà·à¶´à¶ºà·– වර්ණවල දà·à·‚යකි" -#: ../src/controlpanel/aboutxo/view.py:96 -msgid "Build:" -msgstr "ගොඩ නà·à¶Ÿà·”ම:" +#: ../shell/controlpanel/control.py:307 +msgid "off" +msgstr "අක්â€à¶»à·“ය කරන්න" -#: ../src/controlpanel/aboutxo/view.py:111 -msgid "Sugar:" -msgstr "à·à·”ගර්:" +#: ../shell/controlpanel/control.py:309 +msgid "on" +msgstr "සක්â€à¶»à·“ය කරන්න" -#: ../src/controlpanel/aboutxo/view.py:126 -msgid "Firmware:" -msgstr "ස්ථීරà·à¶‚ගය:" +#: ../shell/controlpanel/control.py:310 +msgid "State is unknown." +msgstr "à¶à¶à·Šà¶à·Šà·€à¶º නොදනී." -#: ../src/controlpanel/aboutxo/view.py:148 -msgid "Copyright and License" -msgstr "කà¶à·” හිමිකම හ෠වරපà¶" +#: ../shell/controlpanel/control.py:332 +msgid "Error in specified radio argument use on/off." +msgstr "à·ƒà·à¶´à¶ºà·– විකල්ප විස්à¶à·à¶»à¶šà¶ºà·š දà·à·‚යකි සක්â€à¶»à·“යයි/අක්â€à¶»à·“යයි භà·à·€à·’à¶à· කරන්න" -#: ../src/controlpanel/aboutxo/view.py:156 -msgid "" -"© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." -msgstr "" -"© 2008 One Laptop per Child Association Inc; Red Hat Inc; හ෠සහදà·à¶ºà¶šà¶ºà·’න්." +#: ../shell/controlpanel/control.py:336 +msgid "Permission denied. You need to be root to run this method." +msgstr "අවසර දිය නොහà·à¶š. මෙම විධිය ක්â€à¶»à·’යà·à¶à·Šà¶¸à¶š කිරීමට ඔබ root විය යුà¶à·”ය." -#: ../src/controlpanel/aboutxo/view.py:163 -msgid "" -"Sugar is the graphical user interface that you are looking at. Sugar is free " -"software, covered by the GNU General Public License, and you are welcome to " -"change it and/or distribute copies of it under certain conditions described " -"therein." -msgstr "" -"à·à·”ගර් යනු ඔබ බල෠සිටින මෙම චිà¶à·Šâ€à¶»à¶š පරිà·à·“ලක අà¶à·”රුමුහුණà¶à¶ºà·’. à·à·”ගර් GNU à·ƒà·à¶°à·à¶»à¶« " -"පොදු වරපචමගින් ආවරණය වන නිදහස් මෘදුකà·à¶‚ගයක් වන අà¶à¶» එහි සඳහන් ඇà¶à·à¶¸à·Š කොන්දේසි " -"වලට යටà¶à·Šà·€ මෙය වෙනස් කිරීමට à·„à·/හ෠පිටපà¶à·Š බෙදà·à·„à·à¶»à·“මට ඔබට à·„à·à¶šà·’ය." +#: ../shell/controlpanel/control.py:366 +msgid "Error in reading timezone" +msgstr "වේල෠කලà·à¶´à¶º කියවීමේ දà·à·‚යකි" -#: ../src/controlpanel/aboutxo/view.py:175 -msgid "Full license:" -msgstr "සම්පූර්ණ වරපà¶:" +#: ../shell/controlpanel/control.py:397 +#, python-format +msgid "Error copying timezone (from %s): %s" +msgstr "වේල෠කලà·à¶´à¶º පිටපà¶à·Š කිරීමේ දà·à·‚යකි (%s ගෙන්): %s" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "මගේ XO ගà·à¶±" +#: ../shell/controlpanel/control.py:402 +#, python-format +msgid "Changing permission of timezone: %s" +msgstr "වේල෠කලà·à¶´à¶ºà·š අවසර වෙනස් කෙරේ: %s" -#: ../src/controlpanel/datetime/model.py:89 +#: ../shell/controlpanel/control.py:412 msgid "Error timezone does not exist." msgstr "දà·à·‚යකි වේලà·à¶šà¶½à·à¶´à¶º නොපවà¶à·“." -#: ../src/controlpanel/datetime/view.py:68 -msgid "Timezone" -msgstr "වේල෠කලà·à¶´à¶º" - -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "දිනය හ෠වේලà·à·€" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "අගය නිඛිලයක් විය යුà¶à·”ය." - -#: ../src/controlpanel/frame/view.py:26 -msgid "never" -msgstr "කිසිම දිනෙක" - -#: ../src/controlpanel/frame/view.py:27 -msgid "instantaneous" -msgstr "ක්ෂණිකව" - -#: ../src/controlpanel/frame/view.py:28 +#: ../shell/controlpanel/control.py:417 ../shell/controlpanel/control.py:436 #, python-format -msgid "%s seconds" -msgstr "à¶à¶à·Šà¶´à¶» %s" - -#: ../src/controlpanel/frame/view.py:52 -msgid "Activation Delay" -msgstr "සක්â€à¶»à·’යනය ප්â€à¶»à¶¸à·à¶¯à¶º" - -#: ../src/controlpanel/frame/view.py:76 -msgid "Corner" -msgstr "මුල්ල" - -#: ../src/controlpanel/frame/view.py:111 -msgid "Edge" -msgstr "අයින" - -#: ../src/controlpanel/frame/__init__.py:21 -msgid "Frame" -msgstr "කවුළුව" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "~/.i18n වෙචප්â€à¶»à·€à·šà· විය නොහà·à¶š. සම්මචසිටුවම් à·ƒà·à¶¯à¶±à·Šà¶±." +msgid "Could not access %s. Create standard settings." +msgstr "%s වෙචප්â€à¶»à·€à·šà· විය නොහà·à¶š. සම්මචසිටුවම් à·ƒà·à¶¯à¶±à·Šà¶±." -#: ../src/controlpanel/language/model.py:114 +#: ../shell/controlpanel/control.py:463 #, python-format msgid "Language for code=%s could not be determined." -msgstr "කේà¶à¶º=%s වන භà·à·‚à·à·€ නිර්ණය කළ නොහà·à¶š." +msgstr "code=%s වන භà·à·‚à·à·€ නිර්ණය කළ නොහà·à¶š." -#: ../src/controlpanel/language/model.py:131 +#: ../shell/controlpanel/control.py:473 #, python-format msgid "Sorry I do not speak '%s'." msgstr "සමà·à·€à¶±à·Šà¶± මම '%s' කථ෠නොකරමි." -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 -msgid "Language" -msgstr "භà·à·‚à·à·€" - -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "à¶à¶à·Šà¶à·Šà·€à¶º නොදනී." - -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "à·ƒà·à¶´à¶ºà·– විකල්ප විස්à¶à·à¶»à¶šà¶ºà·š දà·à·‚යකි. සක්â€à¶»à·“යයි/අක්â€à¶»à·“යයි භà·à·€à·’à¶à· කරන්න." - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 -msgid "Network" -msgstr "ජà·à¶½à¶º" - -#: ../src/controlpanel/network/view.py:54 -msgid "Wireless" -msgstr "රà·à·„à·à¶±à·Š රහිà¶" - -#: ../src/controlpanel/network/view.py:62 -msgid "Turn of the wireless radio to save battery life" -msgstr "බà·à¶§à¶»à·’ ආයු කà·à¶½à¶º සුරà·à¶šà·“ම සඳහ෠රà·à·„à·à¶±à·Š රහිචරේඩියà·à·€ නිව෠දමන්න" - -#: ../src/controlpanel/network/view.py:75 -msgid "Radio" -msgstr "රේඩියà·à·€" - -#: ../src/controlpanel/network/view.py:91 -msgid "Discard network history if you have trouble connecting to the network" -msgstr "ොබට ජà·à¶½à¶ºà¶§ සම්බන්ධ වීමේ ගà·à¶§à·…à·” ඇà¶à·’නම් ජà·à¶½ ඉà¶à·’à·„à·à·ƒà¶º ඉවà¶à¶½à¶±à·Šà¶±" - -#: ../src/controlpanel/network/view.py:100 -msgid "Discard network history" -msgstr "ජà·à¶½ ඉà¶à·’à·„à·à·ƒà¶º ඉවà¶à¶½à¶±à·Šà¶±" - -#: ../src/controlpanel/network/view.py:113 -msgid "Mesh" -msgstr "දà·à¶½à·à·ƒ" - -#: ../src/controlpanel/network/view.py:122 -msgid "Server:" -msgstr "සේවà·à¶¯à·à¶ºà¶šà¶º:" - -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "ස්වයංක්â€à¶»à·“ය pm විස්à¶à·à¶»à¶šà¶ºà·š දà·à·‚යකි, සක්â€à¶»à·“යයි/අක්â€à¶»à·“යයි භà·à·€à·’à¶à· කරන්න." - -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "ආන්à¶à·’ක pm විස්à¶à·à¶»à¶šà¶ºà·š දà·à·‚යකි, සක්â€à¶»à·“යයි/අක්â€à¶»à·“යයි භà·à·€à·’à¶à· කරන්න." - -#: ../src/controlpanel/power/view.py:47 -msgid "Power management" -msgstr "බල කළමණà·à¶šà¶»à¶±à¶º" - -#: ../src/controlpanel/power/view.py:57 -msgid "Automatic power management (increases battery life)" -msgstr "ස්වයංක්â€à¶»à·“ය බල කළමණà·à¶šà¶»à¶±à¶º (බà·à¶§à¶»à·’ ආයු කà·à¶½à¶º à·€à·à¶©à·’ කරයි)" - -#: ../src/controlpanel/power/view.py:85 -msgid "" -"Extreme power management (disableswireless radio, increases battery life)" -msgstr "" -"උපරිම බල කළමණà·à¶šà¶»à¶±à¶º ( රà·à·„à·à¶±à·Š රහිචරේඩියà·à·€ අක්â€à¶»à·’ය කරයි, බà·à¶§à¶»à·’ ආයු කà·à¶½à¶º à·€à·à¶©à·’ " -"කරයි)" - -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "à·à¶šà·Šà¶à·’ය" - -#: ../src/view/devices/network/mesh.py:111 +#: ../shell/view/devices/network/mesh.py:105 msgid "Connected to a School Mesh Portal" msgstr "පà·à·ƒà¶½à·Š දà·à¶½à·à·ƒà·Š බිහිදොරකට සම්බන්ධ විය" -#: ../src/view/devices/network/mesh.py:113 +#: ../shell/view/devices/network/mesh.py:107 msgid "Looking for a School Mesh Portal..." msgstr "පà·à·ƒà¶½à·Š දà·à¶½à·à·ƒà·Š බිහිදොරක් සොයයි..." -#: ../src/view/devices/network/mesh.py:116 +#: ../shell/view/devices/network/mesh.py:110 msgid "Connected to an XO Mesh Portal" msgstr "XO දà·à¶½à·à·ƒà·Š බිහිදොරකට සම්බන්ධ විය" -#: ../src/view/devices/network/mesh.py:118 +#: ../shell/view/devices/network/mesh.py:112 msgid "Looking for an XO Mesh Portal..." msgstr "XO දà·à¶½à·à·ƒà·Š බිහිදොරක් සොයයි..." -#: ../src/view/devices/network/mesh.py:121 +#: ../shell/view/devices/network/mesh.py:115 msgid "Connected to a Simple Mesh" msgstr "සරල දà·à¶½à·à·ƒà·Š බිහිදොරකට සම්බන්ධ විය" -#: ../src/view/devices/network/mesh.py:123 +#: ../shell/view/devices/network/mesh.py:117 msgid "Starting a Simple Mesh" msgstr "සරල දà·à¶½à·à·ƒà·Š බිහිදොරක් ආරම්භ කෙරේ" -#: ../src/view/devices/network/mesh.py:130 +#: ../shell/view/devices/network/mesh.py:124 msgid "Unknown Mesh" msgstr "නොදන්න෠දà·à¶½à·à·ƒà¶šà·’" - -#: ../src/view/frame/activitiestray.py:211 -msgid "Decline" -msgstr "ක්â€à¶»à¶¸à¶ºà·™à¶±à·Š පිරිහෙනවà·" - -# TRANS: label for the freeform layout in the favorites view -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "නිදහස් පà·à¶»à·Šà¶¸à¶º" - -# TRANS: label for the ring layout in the favorites view -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "කවය" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "සර්පිලය" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "පෙට්ටිය" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "à¶à·Šâ€à¶»à·’කà·à¶«à¶º" - -#: ../src/view/home/favoritesview.py:295 -msgid "Registration Failed" -msgstr "ලියà·à¶´à¶¯à·’ංචිය අසමà¶à·Š විය" - -#: ../src/view/home/favoritesview.py:296 -#, python-format -msgid "%s" -msgstr "%s" - -#: ../src/view/home/favoritesview.py:298 -msgid "Registration Successful" -msgstr "ලියà·à¶´à¶¯à·’ංචිය à·ƒà·à¶»à·Šà¶®à¶š විය" - -#: ../src/view/home/favoritesview.py:299 -msgid "You are now registered with your school server." -msgstr "ඔබ දà·à¶±à·Š ඔබගේ පà·à·ƒà¶½à·Š සේවà·à¶¯à·à¶ºà¶šà¶º සමඟ ලියà·à¶´à¶¯à·’ංචි වී ඇà¶." - -#: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "සිටුවම්" - -#: ../src/view/home/favoritesview.py:425 -msgid "Restart" -msgstr "යළි ආරම්භ කරන්න" - -#: ../src/view/home/favoritesview.py:430 -msgid "Shutdown" -msgstr "වස෠දමන්න" - -#: ../src/view/home/favoritesview.py:436 -msgid "Register" -msgstr "ලියà·à¶´à¶¯à·’ංචි කරන්න" - -#: ../src/view/palettes.py:42 -msgid "Starting..." -msgstr "ආරම්භවේ..." - -#: ../src/view/palettes.py:72 -msgid "Stop" -msgstr "නවà¶à·Šà·€à¶±à·Šà¶±" - -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 -msgid "Start" -msgstr "ආරම්භ කරන්න" - -#: ../src/view/palettes.py:138 -msgid "Remove favorite" -msgstr "අභිරුචිය ඉවà¶à·Š කරන්න" - -#: ../src/view/palettes.py:142 -msgid "Make favorite" -msgstr "අභිරුචියක් කරන්න" - -#: ../src/view/palettes.py:191 -msgid "Show contents" -msgstr "අන්à¶à¶»à·Šà¶œà¶à¶º පෙන්වන්න" - -#: ../src/view/palettes.py:215 -#, python-format -msgid "%(free_space)d MB Free" -msgstr "%(free_space)d MB ඉà¶à·’රියි" - -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "සෙවිමට" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "ඕනෑම වෙලà·à·€à¶š" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "අද" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "ඊයේ සිට" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "පසුගිය à·ƒà¶à·’ය" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "පසුගිය මà·à·ƒà¶º" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "පසුගිය වසර" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "ඕනෑම අයෙක්" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "මà·à¶œà·š මිà¶à·”රන්" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "මà·à¶œà·š පන්à¶à·’ය" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "ඕනෑ දෙයක්" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "පිටපà¶à·Š කරන්න" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "à·à·“ර්ෂ පà·à¶¨ නොමà·à¶à·’" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "ජ'නලය" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "පූර්වදර්à·à¶±à¶ºà¶šà·Š නà·à¶" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "සහභà·à¶œà·’වන්නන්:" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "විස්à¶à¶»à¶º:" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "à·„à·à¶³à·”නුම් වදන්:" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "වස්à¶à·”වක් à¶à·à¶»à¶±à·Šà¶±" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "චසà·à¶¯à¶¸à¶±à·Šà¶±" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "ගලවන්න" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "දිනයක් නà·à¶" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "ඔබගේ ජර්නලය හිස්ය" - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "ගà·à·…පෙන නිවේà·à¶± නොමà·à¶ " - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "ඔබගේ ජර්නලය සම්පූර්ණයෙන් පිරී ඇà¶" - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." -msgstr "" -"කරුණà·à¶šà¶» නව නිවේà·à¶± සඳහ෠ඉඩ ලබ෠ගà·à¶±à·“මට පà·à¶»à¶«à·’ ජර්නල නිවේà·à¶± කිහිපයක් මක෠දමන්න." - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "ජර්නලය පෙන්වන්න" - -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "පසුරු පුවරු වස්à¶à·”à·€: %s." - -#~ msgid "You must enter a server." -#~ msgstr "ඔබ විසින් සේවà·à¶¯à·à¶ºà¶šà¶ºà¶šà·Š ඇà¶à·”ලà¶à·Š කළ යුà¶à·”ය." - -#~ msgid "Control Panel" -#~ msgstr "පà·à¶½à¶š පුවරුව" - -#~ msgid "<Ctrl>R" -#~ msgstr "<Ctrl>R" - -#~ msgid "off" -#~ msgstr "අක්â€à¶»à·“ය කරන්න" - -#~ msgid "on" -#~ msgstr "සක්â€à¶»à·“ය කරන්න" - -#~ msgid "Permission denied. You need to be root to run this method." -#~ msgstr "අවසර දිය නොහà·à¶š. මෙම විධිය ක්â€à¶»à·’යà·à¶à·Šà¶¸à¶š කිරීමට ඔබ root විය යුà¶à·”ය." - -#~ msgid "Error in reading timezone" -#~ msgstr "වේල෠කලà·à¶´à¶º කියවීමේ දà·à·‚යකි" - -#, python-format -#~ msgid "Error copying timezone (from %s): %s" -#~ msgstr "වේල෠කලà·à¶´à¶º පිටපà¶à·Š කිරීමේ දà·à·‚යකි (%s ගෙන්): %s" - -#, python-format -#~ msgid "Changing permission of timezone: %s" -#~ msgstr "වේල෠කලà·à¶´à¶ºà·š අවසර වෙනස් කෙරේ: %s" - -#~ msgid "About this XO" -#~ msgstr "මෙම XO ගà·à¶±" - -# self._stop_item = MenuItem(_('Stop download'), 'stock-close') -# TODO: Implement stopping downloads -# self._stop_item.connect('activate', self._stop_item_activate_cb) -# self.append_menu_item(self._stop_item) -#~ msgid "Add to journal" -#~ msgstr "ජර්නලයට එක් කරන්න" - -#~ msgid "Reboot" -#~ msgstr "යළි අරඹන්න" - -#~ msgid "My Battery life" -#~ msgstr "මගේ බà·à¶§à¶»à·’ ආයු කà·à¶½à¶º" - -#~ msgid "Battery charging" -#~ msgstr "බà·à¶§à¶»à·’ය ආරà·à¶´à¶«à¶º වේ" - -#~ msgid "Battery discharging" -#~ msgstr "බà·à¶§à¶»à·’ය විසර්ජනය වේ" - -#~ msgid "Battery fully charged" -#~ msgstr "බà·à¶§à¶»à·’ය සම්පූර්ණයෙන්ම ආරà·à¶´à·’à¶à¶ºà·’" - -#~ msgid "Share with:" -#~ msgstr "සමඟ බෙදà·à¶œà¶±à·Šà¶±:" - -#~ msgid "Private" -#~ msgstr "පුද්ගලික" - -#~ msgid "My Neighborhood" -#~ msgstr "මගේ වටපිටà·à·€" - -#~ msgid "Undo" -#~ msgstr "පෙර ලෙස" - -#~ msgid "Redo" -#~ msgstr "නà·à·€à¶ කරන්න" - -#~ msgid "Paste" -#~ msgstr "අලවන්න" - -#, python-format -#~ msgid "%s Activity" -#~ msgstr "%s ක්â€à¶»à·’යà·à¶šà·à¶»à¶šà¶¸" - -#~ msgid "Keep error" -#~ msgstr "නබ෠ගà·à¶±à·“මේ දà·à·‚යකි" - -#~ msgid "Keep error: all changes will be lost" -#~ msgstr "à¶à¶¶à· ගà·à¶±à·“මේ දà·à·‚යකි: සියළු වෙනස් කිරීම් නà·à¶à·’වනු ඇà¶" - -#~ msgid "Don't stop" -#~ msgstr "නවà¶à·Šà·€à¶±à·Šà¶± එපà·" - -#~ msgid "Stop anyway" -#~ msgstr "කෙසේ හ෠නවà¶à·Šà·€à¶±à·Šà¶±" - -#~ msgid "Continue" -#~ msgstr "පවà¶à·Šà·€à·à¶œà·™à¶± යන්න" - -#~ msgid "OK" -#~ msgstr "හරි" @@ -6,834 +6,292 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-09-25 00:30-0400\n" -"PO-Revision-Date: 2008-09-26 09:38-0400\n" -"Last-Translator: abdullah kocabas <abdullah.kocabas@abcdizustu.com>\n" +"POT-Creation-Date: 2008-02-09 00:30-0500\n" +"PO-Revision-Date: 2008-02-22 23:10-0500\n" +"Last-Translator: Serkan Cabi <serkancabi@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Pootle 1.1.0rc2\n" +"X-Generator: Pootle 1.0.2\n" -#: ../src/intro/window.py:93 ../src/controlpanel/aboutme/view.py:100 +#: ../src/intro/intro.py:67 msgid "Name:" msgstr "Ä°sim:" -#: ../src/intro/window.py:125 +#: ../src/intro/intro.py:96 msgid "Click to change color:" msgstr "Renk deÄŸiÅŸtirmek için tıkla:" -#: ../src/intro/window.py:175 ../src/journal/detailview.py:119 +#: ../src/intro/intro.py:146 msgid "Back" msgstr "Geri" -#: ../src/intro/window.py:189 ../src/controlpanel/toolbar.py:61 +#: ../src/intro/intro.py:160 msgid "Done" -msgstr "Kapat" +msgstr "Bitti" -#: ../src/intro/window.py:192 +#: ../src/intro/intro.py:163 msgid "Next" msgstr "Ä°leri" -#: ../src/view/BuddyMenu.py:60 +#: ../src/view/BuddyMenu.py:59 msgid "Remove friend" -msgstr "Arkadaşı Kaldır" +msgstr "Arkadaşı sil" -#: ../src/view/BuddyMenu.py:63 +#: ../src/view/BuddyMenu.py:62 msgid "Make friend" -msgstr "ArkadaÅŸ Ekle" +msgstr "ArkadaÅŸ ol" -#: ../src/view/BuddyMenu.py:92 +#: ../src/view/BuddyMenu.py:84 #, python-format msgid "Invite to %s" -msgstr "Davet et %s" +msgstr "%s için davet et" -#: ../src/view/clipboardmenu.py:51 +#: ../src/view/clipboardmenu.py:58 msgid "Remove" msgstr "Kaldır" -#: ../src/view/clipboardmenu.py:56 ../src/view/clipboardmenu.py:78 +#: ../src/view/clipboardmenu.py:63 msgid "Open" msgstr "Aç" -#: ../src/view/clipboardmenu.py:61 ../src/view/home/HomeBox.py:84 -msgid "Keep" -msgstr "Kaydet" - -#: ../src/view/clipboardmenu.py:83 -msgid "Open with" -msgstr "Birlikte Aç" +#. self._stop_item = MenuItem(_('Stop download'), 'stock-close') +#. TODO: Implement stopping downloads +#. self._stop_item.connect('activate', self._stop_item_activate_cb) +#. self.append_menu_item(self._stop_item) +#: ../src/view/clipboardmenu.py:73 +msgid "Add to journal" +msgstr "Günlüğe ekle" -#: ../src/view/clipboardmenu.py:228 +#: ../src/view/clipboardmenu.py:213 #, python-format -msgid "%s clipping" -msgstr "%s Kırp" +msgid "Clipboard object: %s." +msgstr "Pano nesnesi: %s" -#: ../src/hardware/keydialog.py:150 +#: ../src/hardware/keydialog.py:149 msgid "Key Type:" -msgstr "TuÅŸ ÇeÅŸidi:" +msgstr "TuÅŸ çeÅŸidi:" -#: ../src/hardware/keydialog.py:170 +#: ../src/hardware/keydialog.py:169 msgid "Authentication Type:" -msgstr "Kimlik Denetleme ÇeÅŸidi:" +msgstr "Kimlik denetleme çeÅŸidi:" -#: ../src/hardware/keydialog.py:251 +#: ../src/hardware/keydialog.py:250 msgid "Encryption Type:" -msgstr "Åžifreleme ÇeÅŸidi:" +msgstr "Åžifreleme çeÅŸidi:" -#: ../src/hardware/schoolserver.py:17 -msgid "Cannot obtain data needed for registration." -msgstr "Kayıt İçin Gerekli Bilgileri SaÄŸlayamıyor" +#: ../src/view/home/activitiesdonut.py:90 +msgid "Starting..." +msgstr "BaÅŸlıyor..." -#: ../src/hardware/schoolserver.py:31 -msgid "Cannot connect to the server." -msgstr "Sunucuya BaÄŸlanamıyor" +#: ../src/view/home/activitiesdonut.py:104 ../src/view/home/MeshBox.py:295 +msgid "Resume" +msgstr "Devam et" -#: ../src/hardware/schoolserver.py:36 -msgid "The server could not complete the request." -msgstr "Sunucu Ä°steÄŸi Tamamlayamıyor" +#: ../src/view/home/activitiesdonut.py:111 +msgid "Stop" +msgstr "Dur" -#: ../src/view/Shell.py:251 +#: ../src/view/Shell.py:285 msgid "Screenshot" msgstr "Ekran Resmi" -#: ../src/view/home/HomeBox.py:78 -msgid "Confirm erase" -msgstr "Silmeyi Onayla" +#: ../src/view/home/HomeBox.py:159 +msgid "Reboot" +msgstr "Yeniden BaÅŸlat" -#: ../src/view/home/HomeBox.py:80 -#, python-format -msgid "Confirm erase: Do you want to permanently erase %s?" -msgstr "Silme Onayı: %s i tamamen silmek mi istiyorsunuz?" - -#: ../src/view/home/HomeBox.py:87 ../src/view/palettes.py:120 -#: ../src/journal/journaltoolbox.py:335 ../src/journal/palettes.py:75 -msgid "Erase" -msgstr "Silme" - -#: ../src/view/home/HomeBox.py:117 -msgid "Software Update" -msgstr "Yazılım Güncelleme" - -#: ../src/view/home/HomeBox.py:118 -msgid "Update your activities to ensure compatibility with your new software" -msgstr "Aktivitelerinizi yeni yazılıma uygun hale getirmek için güncelleyiniz" - -#: ../src/view/home/HomeBox.py:122 ../src/controlpanel/toolbar.py:115 -msgid "Cancel" -msgstr "Ä°ptal" - -#: ../src/view/home/HomeBox.py:124 ../src/controlpanel/gui.py:273 -msgid "Later" -msgstr "Daha Sonra" - -#: ../src/view/home/HomeBox.py:127 -msgid "Check now" -msgstr "Åžimdi Kontrol Et" - -#: ../src/view/home/HomeBox.py:261 -msgid "List view" -msgstr "Liste Görünümü" - -#: ../src/view/home/HomeBox.py:262 -msgid "<Ctrl>2" -msgstr "<Ctrl>2" - -#: ../src/view/home/HomeBox.py:320 -msgid "Favorites view" -msgstr "Favoriler Görünümü" - -#: ../src/view/home/HomeBox.py:321 -msgid "<Ctrl>1" -msgstr "<Ctrl>1" - -#: ../src/view/home/MeshBox.py:97 -msgid "Connect" -msgstr "BaÄŸlan" - -#: ../src/view/home/MeshBox.py:106 -msgid "Disconnect" -msgstr "BaÄŸlantıyı kes" - -# Only show disconnect when there's a mesh device, because mesh takes -# priority over the normal wireless device. NM doesn't have a "disconnect" -# method for a device either (for various reasons) so this doesn't -# have a good mapping -#: ../src/view/home/MeshBox.py:118 -msgid "Disconnecting..." -msgstr "BaÄŸlantı kesiliyor..." - -#: ../src/view/home/MeshBox.py:159 -msgid "Connecting..." -msgstr "BaÄŸlanıyor..." - -# TODO: show the channel number -#. TODO: show the channel number -#: ../src/view/home/MeshBox.py:166 -msgid "Connected" -msgstr "BaÄŸlı" - -#: ../src/view/home/MeshBox.py:218 ../src/view/devices/network/mesh.py:41 -#: ../src/view/devices/network/mesh.py:68 -#: ../src/view/devices/network/mesh.py:72 -msgid "Mesh Network" -msgstr "Mesh Ağı" - -# Only show disconnect when there's a mesh device, because mesh takes -# priority over the normal wireless device. NM doesn't have a "disconnect" -# method for a device either (for various reasons) so this doesn't -# have a good mapping -#: ../src/view/home/MeshBox.py:221 ../src/view/devices/network/wireless.py:125 -#: ../src/view/devices/network/mesh.py:89 +#: ../src/view/home/HomeBox.py:164 +msgid "Shutdown" +msgstr "Kapat" + +#: ../src/view/home/HomeBox.py:170 +#, fuzzy +msgid "Register" +msgstr "Kayıt" + +#: ../src/view/home/HomeBox.py:175 ../src/view/home/HomeBox.py:216 +msgid "About this XO" +msgstr "Bu XO hakkında" + +#: ../src/view/home/HomeBox.py:222 +#, fuzzy +msgid "Not available" +msgstr "Uygun deÄŸil" + +#. Only show disconnect when there's a mesh device, because mesh takes +#. priority over the normal wireless device. NM doesn't have a "disconnect" +#. method for a device either (for various reasons) so this doesn't +#. have a good mapping +#: ../src/view/home/MeshBox.py:90 ../src/view/home/MeshBox.py:197 +#: ../src/view/devices/network/wireless.py:113 +#: ../src/view/devices/network/mesh.py:83 msgid "Disconnect..." msgstr "BaÄŸlantıyı kes..." -#. TRANS: Action label for resuming an activity. -#: ../src/view/home/MeshBox.py:309 ../src/view/palettes.py:61 -#: ../src/journal/journaltoolbox.py:399 ../src/journal/palettes.py:57 -msgid "Resume" -msgstr "Devam Et" +#: ../src/view/home/MeshBox.py:195 ../src/view/devices/network/mesh.py:37 +#: ../src/view/devices/network/mesh.py:62 +#: ../src/view/devices/network/mesh.py:66 +msgid "Mesh Network" +msgstr "Örgüsel AÄŸ" -#: ../src/view/home/MeshBox.py:314 ../src/view/frame/activitiestray.py:206 +#: ../src/view/home/MeshBox.py:300 msgid "Join" msgstr "Katıl" -#: ../src/view/devices/battery.py:45 -msgid "My Battery" -msgstr "Pil Durumu" - -#: ../src/view/devices/battery.py:114 -msgid "Charging" -msgstr "Åžarj" - -#: ../src/view/devices/battery.py:117 -msgid "Very little power remaining" -msgstr "Çok az ÅŸarj kaldı" - -#: ../src/view/devices/battery.py:123 -#, python-format -msgid "%(hour)d:%(min).2d remaining" -msgstr "%(hour)d:%(min).2d kaldı" - -#: ../src/view/devices/battery.py:127 -msgid "Charged" -msgstr "Åžarj edildi" +#: ../src/view/devices/battery.py:38 +msgid "My Battery life" +msgstr "Pil ömrüm" -#: ../src/view/devices/speaker.py:44 -msgid "My Speakers" -msgstr "Hoparlör" +#: ../src/view/devices/battery.py:94 +msgid "Battery charging" +msgstr "Pil doluyor" -#: ../src/view/devices/speaker.py:125 -msgid "Unmute" -msgstr "Sesi açık" +#: ../src/view/devices/battery.py:96 +msgid "Battery discharging" +msgstr "Pil boÅŸalıyor" -#: ../src/view/devices/speaker.py:128 -msgid "Mute" -msgstr "Sessiz" +#: ../src/view/devices/battery.py:98 +msgid "Battery fully charged" +msgstr "Pil tam dolu" -#: ../src/view/devices/network/wireless.py:67 +#: ../src/view/devices/network/wireless.py:61 msgid "Disconnected" msgstr "BaÄŸlantı kesildi" -#: ../src/view/devices/network/wireless.py:143 +#: ../src/view/devices/network/wireless.py:131 msgid "Channel" msgstr "Kanal" -#: ../src/view/frame/zoomtoolbar.py:37 +#: ../src/view/frame/zoomtoolbar.py:42 msgid "Neighborhood" -msgstr "KomÅŸular" +msgstr "KomÅŸuluk" -#: ../src/view/frame/zoomtoolbar.py:39 +#: ../src/view/frame/zoomtoolbar.py:54 msgid "Group" msgstr "Grup" -#: ../src/view/frame/zoomtoolbar.py:41 +#: ../src/view/frame/zoomtoolbar.py:66 msgid "Home" msgstr "Ana ekran" -#: ../src/view/frame/zoomtoolbar.py:43 +#: ../src/view/frame/zoomtoolbar.py:78 msgid "Activity" -msgstr "Aktivite" - -#: ../src/controlpanel/cmd.py:26 -#, python-format -msgid "" -"sugar-control-panel: WARNING, found more than one option with the same name: " -"%s module: %r" -msgstr "" -"sugar-kontrol-paneli: UYARI, aynı isimle birden fazla seçenek buldu: %s " -"birim: %r" - -#: ../src/controlpanel/cmd.py:28 -#, python-format -msgid "sugar-control-panel: key=%s not an available option" -msgstr "sugar-kontrol-panel: anahtar=%s geçerli bir seçenek deÄŸil" - -#: ../src/controlpanel/cmd.py:29 -#, python-format -msgid "sugar-control-panel: %s" -msgstr "sugar-kontrol-panel: %s" +msgstr "Etkinlik" -#. TRANS: Translators, there's a empty line at the end of this string, -#. which must appear in the translated string (msgstr) as well. -#: ../src/controlpanel/cmd.py:35 -msgid "" -"Usage: sugar-control-panel [ option ] key [ args ... ] \n" -" Control for the sugar environment. \n" -" Options: \n" -" -h show this help message and exit \n" -" -l list all the available options \n" -" -h key show information about this key \n" -" -g key get the current value of the key \n" -" -s key set the current value for the key \n" -" -c key clear the current value for the key \n" -" " -msgstr "" -"Kullanım: sugar-kontrol-paneli [ seçenek ] anahtar [ args ... ] \n" -"Sugar ortamı için kontrol \n" -"Seçenekler:\n" -"-h Bu yardım mesajını göster ve çık \n" -"-l Tüm uygun seçenekleri listele \n" -"-h anahtarı Bu anahtar hakkındaki bilgileri göster \n" -"-g anahtarı Bu anahtarın son deÄŸerini al \n" -"-s anahtarı Bu anahtarın son deÄŸerini kur \n" -"\t" - -#: ../src/controlpanel/cmd.py:48 +#: ../src/controlpanel/control.py:219 msgid "To apply your changes you have to restart sugar.\n" -msgstr "DeÄŸiÅŸikliklerinizin etkinleÅŸmesi için bilgisayarı tekrar baÅŸlatmanız " -"gerekiyor\n" +msgstr "DeÄŸiÅŸikliklerin etkinleÅŸmesi için yeniden baÅŸlatın.\n" -#: ../src/controlpanel/toolbar.py:121 ../src/view/home/favoritesview.py:305 -msgid "Ok" -msgstr "Tamam" - -#: ../src/controlpanel/sectionview.py:42 ../src/controlpanel/gui.py:265 -msgid "Changes require restart" -msgstr "DeÄŸiÅŸiklikler bilgisayarın tekrar baÅŸlatılmasını gerektiriyor" - -#: ../src/controlpanel/gui.py:264 -msgid "Warning" -msgstr "Uyarı" - -#: ../src/controlpanel/gui.py:268 -msgid "Cancel changes" -msgstr "DeÄŸiÅŸiklikleri Ä°ptal Et" - -#: ../src/controlpanel/gui.py:277 -msgid "Restart now" -msgstr "Åžimdi Tekrar BaÅŸlat" - -#: ../src/controlpanel/aboutme/model.py:44 -msgid "You must enter a name." -msgstr "Bir isim girmeniz gerekiyor" - -#: ../src/controlpanel/aboutme/model.py:69 -#, python-format -msgid "stroke: color=%s hue=%s" -msgstr "fırça darbesi:_ renk=%s renk=%s" - -#: ../src/controlpanel/aboutme/model.py:72 -#, python-format -msgid "stroke: %s" -msgstr "fırça darbesi:_ %s" - -#: ../src/controlpanel/aboutme/model.py:74 -#, python-format -msgid "fill: color=%s hue=%s" -msgstr "doldurma:_ renk=%s renk=%s" - -#: ../src/controlpanel/aboutme/model.py:76 -#, python-format -msgid "fill: %s" -msgstr "doldurma:_ %s" - -#: ../src/controlpanel/aboutme/model.py:87 +#: ../src/controlpanel/control.py:273 msgid "Error in specified color modifiers." -msgstr "Belirtilen renk deÄŸiÅŸtiricilerinde hata" +msgstr "Belirtilen renk deÄŸiÅŸtiricilerinde hata." -#: ../src/controlpanel/aboutme/model.py:90 +#: ../src/controlpanel/control.py:276 msgid "Error in specified colors." -msgstr "Belirtilen renklerde hata" +msgstr "Belirtilen renklerde hata." -#: ../src/controlpanel/aboutme/view.py:32 -#: ../src/controlpanel/aboutme/__init__.py:22 -msgid "About Me" -msgstr "Benim Hakkımda" - -#: ../src/controlpanel/aboutme/view.py:134 -msgid "Click to change your color:" -msgstr "Renk deÄŸiÅŸtirmek için tıklayınız:" - -#: ../src/controlpanel/aboutxo/model.py:24 -msgid "Not available" -msgstr "Mevcut deÄŸil" +#: ../src/controlpanel/control.py:312 +msgid "off" +msgstr "kapalı" -#: ../src/controlpanel/aboutxo/view.py:55 -msgid "Identity" -msgstr "Kimlik" +#: ../src/controlpanel/control.py:314 +msgid "on" +msgstr "açık" -#: ../src/controlpanel/aboutxo/view.py:64 -msgid "Serial Number:" -msgstr "Seri Numarası:" - -#: ../src/controlpanel/aboutxo/view.py:87 -msgid "Software" -msgstr "Yazılım" - -#: ../src/controlpanel/aboutxo/view.py:96 -msgid "Build:" -msgstr "Yapı:" - -#: ../src/controlpanel/aboutxo/view.py:111 -msgid "Sugar:" -msgstr "Sugar:" - -#: ../src/controlpanel/aboutxo/view.py:126 -msgid "Firmware:" -msgstr "Aygıt Yazılımı:" +#: ../src/controlpanel/control.py:316 +msgid "State is unknown." +msgstr "Durum bilinmiyor." -#: ../src/controlpanel/aboutxo/view.py:148 -msgid "Copyright and License" -msgstr "Telif Hakkı ve Lisans" +#: ../src/controlpanel/control.py:336 +msgid "Error in specified radio argument use on/off." +msgstr "" -#: ../src/controlpanel/aboutxo/view.py:156 -msgid "" -"© 2008 One Laptop per Child Association Inc; Red Hat Inc; and Contributors." +#: ../src/controlpanel/control.py:340 +msgid "Permission denied. You need to be root to run this method." msgstr "" -"© 2008 One Laptop per Child Association Inc; Red Hat Inc; ve Destekçiler" -#: ../src/controlpanel/aboutxo/view.py:163 -msgid "" -"Sugar is the graphical user interface that you are looking at. Sugar is free " -"software, covered by the GNU General Public License, and you are welcome to " -"change it and/or distribute copies of it under certain conditions described " -"therein." +#: ../src/controlpanel/control.py:370 +msgid "Error in reading timezone" msgstr "" -"Sugar gördüğünüz grafiksel kullanıcı arayüzüdür. Sugar, GNU General Public " -"Lisansı'na sahip, ücretsiz bir yazılımdır. Ä°stediÄŸiniz takdirde yazılımı " -"deÄŸiÅŸtirebilir ve/veya burada açıklanan belli koÅŸullar altında kopyasını " -"dağıtabilirsiniz." -#: ../src/controlpanel/aboutxo/view.py:175 -msgid "Full license:" -msgstr "Tam Lisans:" +#: ../src/controlpanel/control.py:401 +#, python-format +msgid "Error copying timezone (from %s): %s" +msgstr "" -#: ../src/controlpanel/aboutxo/__init__.py:21 -msgid "About my XO" -msgstr "XO Bilgisayarım Hakkında" +#: ../src/controlpanel/control.py:406 +#, python-format +msgid "Changing permission of timezone: %s" +msgstr "" -#: ../src/controlpanel/datetime/model.py:89 +#: ../src/controlpanel/control.py:416 msgid "Error timezone does not exist." -msgstr "Hatalı zaman dilimi yok" - -#: ../src/controlpanel/datetime/view.py:68 -msgid "Timezone" -msgstr "Saat Dilimi" - -#: ../src/controlpanel/datetime/__init__.py:21 -msgid "Date & Time" -msgstr "Tarih ve Zaman" - -#: ../src/controlpanel/frame/model.py:38 ../src/controlpanel/frame/model.py:60 -msgid "Value must be an integer." -msgstr "DeÄŸer bir tamsayı olmalı" - -#: ../src/controlpanel/frame/view.py:26 -msgid "never" -msgstr "asla" - -#: ../src/controlpanel/frame/view.py:27 -msgid "instantaneous" -msgstr "anlık" +msgstr "" -#: ../src/controlpanel/frame/view.py:28 +#: ../src/controlpanel/control.py:421 ../src/controlpanel/control.py:440 #, python-format -msgid "%s seconds" -msgstr "%s saniyeler" - -#: ../src/controlpanel/frame/view.py:52 -msgid "Activation Delay" -msgstr "Aktivasyon Gecikmesi" - -#: ../src/controlpanel/frame/view.py:76 -msgid "Corner" -msgstr "Köşe" - -#: ../src/controlpanel/frame/view.py:111 -msgid "Edge" -msgstr "Kenar" - -#: ../src/controlpanel/frame/__init__.py:21 -msgid "Frame" -msgstr "Çerçeve" - -#: ../src/controlpanel/language/model.py:28 -msgid "Could not access ~/.i18n. Create standard settings." -msgstr "~/.i18n e girilemiyor. Standart ayarları oluÅŸturunuz" +msgid "Could not access %s. Create standard settings." +msgstr "" -#: ../src/controlpanel/language/model.py:114 +#: ../src/controlpanel/control.py:467 #, python-format msgid "Language for code=%s could not be determined." -msgstr "kod=%s için dil tanımlanamadı" +msgstr "" -#: ../src/controlpanel/language/model.py:131 +#: ../src/controlpanel/control.py:477 #, python-format msgid "Sorry I do not speak '%s'." -msgstr "Ãœzgünüm, %s konuÅŸmuyorum" - -#: ../src/controlpanel/language/view.py:70 -#: ../src/controlpanel/language/__init__.py:21 -msgid "Language" -msgstr "Dil" - -#: ../src/controlpanel/network/model.py:62 -msgid "State is unknown." -msgstr "Durum bilinmiyor" - -#: ../src/controlpanel/network/model.py:82 -msgid "Error in specified radio argument use on/off." -msgstr "Belirtilen baÄŸlantı noktasında hata vardır, açma kapama yapınız" - -#: ../src/controlpanel/network/view.py:28 -#: ../src/controlpanel/network/__init__.py:21 -msgid "Network" -msgstr "AÄŸ" - -#: ../src/controlpanel/network/view.py:54 -msgid "Wireless" -msgstr "Kablosuz BaÄŸlantı" - -#: ../src/controlpanel/network/view.py:62 -msgid "Turn of the wireless radio to save battery life" -msgstr "Pil ömrünü arttırmak için kablosuz baÄŸlantı özelliÄŸini kapatınız." - -#: ../src/controlpanel/network/view.py:75 -msgid "Radio" -msgstr "BaÄŸlantı " - -#: ../src/controlpanel/network/view.py:91 -msgid "Discard network history if you have trouble connecting to the network" -msgstr "AÄŸa baÄŸlanmada sorun yaşıyorsanız aÄŸ geçmiÅŸini silebilirsiniz." - -#: ../src/controlpanel/network/view.py:100 -msgid "Discard network history" -msgstr "AÄŸ geçmiÅŸini siliniz." - -#: ../src/controlpanel/network/view.py:113 -msgid "Mesh" -msgstr "Mesh" - -#: ../src/controlpanel/network/view.py:122 -msgid "Server:" -msgstr "Sunucu:" - -#: ../src/controlpanel/power/model.py:55 -msgid "Error in automatic pm argument, use on/off." -msgstr "Otomatik pm deÄŸiÅŸkeninde hata vardır, açma kapama yapınız" - -#: ../src/controlpanel/power/model.py:84 -msgid "Error in extreme pm argument, use on/off." -msgstr "En uçtaki pm deÄŸiÅŸkeninde hata vardır, açma kapama yapınız" - -#: ../src/controlpanel/power/view.py:47 -msgid "Power management" -msgstr "Güç Kontrolü" - -#: ../src/controlpanel/power/view.py:57 -msgid "Automatic power management (increases battery life)" -msgstr "Otomatik güç kontrolü (pil ömrünü uzatır)" +msgstr "" -#: ../src/controlpanel/power/view.py:85 +#: ../src/controlpanel/cmd.py:27 msgid "" -"Extreme power management (disableswireless radio, increases battery life)" +"Usage: sugar-control-panel [ option ] key [ args ... ] \n" +" Control for the sugar environment. \n" +" Options: \n" +" -h show this help message and exit \n" +" -l list all the available options \n" +" -h key show information about this key \n" +" -g key get the current value of the key \n" +" -s key set the current value for the key \n" +" " msgstr "" -"Aşırı güç kontrolü (kablosuz baÄŸlantı özelliÄŸini etkisiz kılar, ÅŸarj ömrünü " -"uzatır)" -#: ../src/controlpanel/power/__init__.py:21 -msgid "Power" -msgstr "Güç" +#: ../src/controlpanel/cmd.py:55 ../src/controlpanel/cmd.py:67 +#: ../src/controlpanel/cmd.py:74 +#, python-format +msgid "sugar-control-panel: key=%s not an available option" +msgstr "" + +#: ../src/controlpanel/cmd.py:80 +#, python-format +msgid "sugar-control-panel: %s" +msgstr "" -#: ../src/view/devices/network/mesh.py:111 +#: ../src/view/devices/network/mesh.py:105 msgid "Connected to a School Mesh Portal" -msgstr "Okul Mesh Ağı Portalı'na baÄŸlandı." +msgstr "" -#: ../src/view/devices/network/mesh.py:113 +#: ../src/view/devices/network/mesh.py:107 msgid "Looking for a School Mesh Portal..." -msgstr "Okul Mesh Ağı Portalı arıyor..." +msgstr "" -#: ../src/view/devices/network/mesh.py:116 +#: ../src/view/devices/network/mesh.py:110 msgid "Connected to an XO Mesh Portal" -msgstr "XO Mesh Ağı Portalı'na baÄŸlandı." +msgstr "" -#: ../src/view/devices/network/mesh.py:118 +#: ../src/view/devices/network/mesh.py:112 msgid "Looking for an XO Mesh Portal..." -msgstr "XO Mesh AÄŸ Portalı arıyor..." +msgstr "" -#: ../src/view/devices/network/mesh.py:121 +#: ../src/view/devices/network/mesh.py:115 msgid "Connected to a Simple Mesh" -msgstr "Sadece Mesh Ağına baÄŸlandı." +msgstr "" -#: ../src/view/devices/network/mesh.py:123 +#: ../src/view/devices/network/mesh.py:117 msgid "Starting a Simple Mesh" -msgstr "Sadece Mesh Ağı baÅŸlatıyor." +msgstr "" -#: ../src/view/devices/network/mesh.py:130 +#: ../src/view/devices/network/mesh.py:124 msgid "Unknown Mesh" -msgstr "Bilinmeyen Mesh Ağı" - -#: ../src/view/frame/activitiestray.py:211 -msgid "Decline" -msgstr "Azalmak" - -#. TRANS: label for the freeform layout in the favorites view -#: ../src/view/home/favoriteslayout.py:107 -msgid "Freeform" -msgstr "dağınık görünüm" - -#. TRANS: label for the ring layout in the favorites view -#: ../src/view/home/favoriteslayout.py:189 -msgid "Ring" -msgstr "çember görünümü" - -#. TRANS: label for the spiral layout in the favorites view -#: ../src/view/home/favoriteslayout.py:334 -msgid "Spiral" -msgstr "sarmal" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:401 -msgid "Box" -msgstr "kutu" - -#. TRANS: label for the box layout in the favorites view -#: ../src/view/home/favoriteslayout.py:442 -msgid "Triangle" -msgstr "üçgen" - -#: ../src/view/home/favoritesview.py:295 -msgid "Registration Failed" -msgstr "Kayıt BaÅŸarısız" - -#: ../src/view/home/favoritesview.py:296 -#, python-format -msgid "%s" -msgstr "%s" - -#: ../src/view/home/favoritesview.py:298 -msgid "Registration Successful" -msgstr "Kayıt BaÅŸarılı" - -#: ../src/view/home/favoritesview.py:299 -msgid "You are now registered with your school server." -msgstr "Åžu an okul sunucunuza kayıt oldunuz" - -#: ../src/view/home/favoritesview.py:420 -msgid "Settings" -msgstr "Ayarlar" - -#: ../src/view/home/favoritesview.py:425 -msgid "Restart" -msgstr "Yeniden BaÅŸlat" - -#: ../src/view/home/favoritesview.py:430 -msgid "Shutdown" -msgstr "Kapat" - -#: ../src/view/home/favoritesview.py:436 -msgid "Register" -msgstr "Kaydol" - -#: ../src/view/palettes.py:42 -msgid "Starting..." -msgstr "BaÅŸlıyor..." - -#: ../src/view/palettes.py:72 -msgid "Stop" -msgstr "Durdur" - -#. TRANS: Action label for starting an entry. -#: ../src/view/palettes.py:104 ../src/journal/journaltoolbox.py:402 -#: ../src/journal/palettes.py:59 -msgid "Start" -msgstr "BaÅŸlat" - -#: ../src/view/palettes.py:138 -msgid "Remove favorite" -msgstr "Favorilerimden kaldır" - -#: ../src/view/palettes.py:142 -msgid "Make favorite" -msgstr "Favorilerime ekle" - -#: ../src/view/palettes.py:191 -msgid "Show contents" -msgstr "İçeriklerini göster" - -#: ../src/view/palettes.py:215 -#, python-format -msgid "%(free_space)d MB Free" -msgstr "%(free_space)d MB boÅŸ" - -#: ../src/journal/journaltoolbox.py:62 -msgid "Search" -msgstr "Arama" - -#: ../src/journal/journaltoolbox.py:119 -msgid "Anytime" -msgstr "Herhangi bir zaman" - -#: ../src/journal/journaltoolbox.py:121 -msgid "Today" -msgstr "Bugün" - -#: ../src/journal/journaltoolbox.py:123 -msgid "Since yesterday" -msgstr "Dünden itibaren" - -#. TRANS: Filter entries modified during the last 7 days. -#: ../src/journal/journaltoolbox.py:125 -msgid "Past week" -msgstr "Geçen hafta" - -#. TRANS: Filter entries modified during the last 30 days. -#: ../src/journal/journaltoolbox.py:127 -msgid "Past month" -msgstr "Geçen ay" - -#. TRANS: Filter entries modified during the last 356 days. -#: ../src/journal/journaltoolbox.py:129 -msgid "Past year" -msgstr "Geçen yıl" - -#: ../src/journal/journaltoolbox.py:136 -msgid "Anyone" -msgstr "Herhangi biri" - -#: ../src/journal/journaltoolbox.py:138 -msgid "My friends" -msgstr "ArkadaÅŸlarım" - -#: ../src/journal/journaltoolbox.py:139 -msgid "My class" -msgstr "Sınıfım" - -#. TRANS: Item in a combo box that filters by entry type. -#: ../src/journal/journaltoolbox.py:255 -msgid "Anything" -msgstr "Herhangi bir ÅŸey" - -#. TODO: Add "Start with" menu item -#: ../src/journal/journaltoolbox.py:325 ../src/journal/palettes.py:67 -msgid "Copy" -msgstr "Kopyala" - -#: ../src/journal/collapsedentry.py:248 ../src/journal/expandedentry.py:176 -#: ../src/journal/palettes.py:51 -msgid "Untitled" -msgstr "Ä°simsiz" - -#: ../src/journal/journalactivity.py:119 ../src/journal/volumesmanager.py:57 -msgid "Journal" -msgstr "Günlük" - -#: ../src/journal/expandedentry.py:222 -msgid "No preview" -msgstr "Ön izleme yok" - -#: ../src/journal/expandedentry.py:241 -msgid "Participants:" -msgstr "Katılımcılar:" - -#: ../src/journal/expandedentry.py:266 -msgid "Description:" -msgstr "Tanım:" - -#: ../src/journal/expandedentry.py:292 -msgid "Tags:" -msgstr "Etiketler:" - -#: ../src/journal/objectchooser.py:134 -msgid "Choose an object" -msgstr "Bir nesne seçiniz" - -#: ../src/journal/objectchooser.py:139 -msgid "Close" -msgstr "Kapat" - -#: ../src/journal/volumestoolbar.py:93 -msgid "Unmount" -msgstr "BaÄŸlantıyı kaldır" - -#: ../src/journal/misc.py:95 -msgid "No date" -msgstr "Tarih yok" - -#: ../src/journal/listview.py:39 -msgid "Your Journal is empty" -msgstr "Günlüğünüz boÅŸ" - -#: ../src/journal/listview.py:40 -msgid "No matching entries " -msgstr "EÅŸleÅŸen bir giriÅŸ yok_" - -#: ../src/journal/modalalert.py:59 -msgid "Your Journal is full" -msgstr "Günlüğünüz dolu" - -#: ../src/journal/modalalert.py:63 -msgid "Please delete some old Journal entries to make space for new ones." msgstr "" -"Yeni giriÅŸler yapabilmek için lütfen günlükteki eski kayıtlardan bir kısmını " -"siliniz" - -#: ../src/journal/modalalert.py:75 -msgid "Show Journal" -msgstr "Günlüğü göster" - -#~ msgid "Add to journal" -#~ msgstr "Günlüğe ekleyiniz." - -#, python-format -#~ msgid "Clipboard object: %s." -#~ msgstr "Pano nesnesi: %s" - -#~ msgid "Reboot" -#~ msgstr "Yeniden baÅŸlatınız." - -#~ msgid "About this XO" -#~ msgstr "Bu XO hakkında" - -#~ msgid "My Battery life" -#~ msgstr "Pil ömrüm" - -#~ msgid "Battery charging" -#~ msgstr "Pil doluyor." - -#~ msgid "Battery discharging" -#~ msgstr "Pil boÅŸalıyor." - -#~ msgid "Battery fully charged" -#~ msgstr "Pil tam dolu" - -#~ msgid "off" -#~ msgstr "kapalı" - -#~ msgid "on" -#~ msgstr "açık" - -#~ msgid "Permission denied. You need to be root to run this method." -#~ msgstr "" -#~ "Ä°zin reddedildi. Bu metodu çalıştırmak için merkezden olmanız gerekmektedir." - -#~ msgid "Error in reading timezone" -#~ msgstr "Saat diliminde hata vardır." - -#, python-format -#~ msgid "Error copying timezone (from %s): %s" -#~ msgstr "Saat dilimini %s'ten kopyalarken hata oluÅŸmuÅŸtur: %s" - -#, python-format -#~ msgid "Changing permission of timezone: %s" -#~ msgstr "Saat dilimini deÄŸiÅŸtirme izni: %s" diff --git a/service/Makefile.am b/service/Makefile.am new file mode 100644 index 0000000..fa8e66f --- /dev/null +++ b/service/Makefile.am @@ -0,0 +1,33 @@ +servicedir = $(datadir)/dbus-1/services + +service_in_files = \ + org.laptop.ActivityRegistry.service.in \ + org.laptop.Clipboard.service.in + +service_DATA = \ + org.laptop.ActivityRegistry.service \ + org.laptop.Clipboard.service + +org.laptop.ActivityRegistry.service: org.laptop.ActivityRegistry.service.in Makefile + @sed -e "s|\@bindir\@|$(bindir)|" $< > $@ + +org.laptop.Clipboard.service: org.laptop.Clipboard.service.in Makefile + @sed -e "s|\@bindir\@|$(bindir)|" $< > $@ + +org.laptop.ObjectTypeRegistry.service: org.laptop.ObjectTypeRegistry.service.in Makefile + @sed -e "s|\@bindir\@|$(bindir)|" $< > $@ + +sugardir = $(pkgdatadir)/service + +sugar_PYTHON = \ + __init__.py \ + activityregistryservice.py \ + bundleregistry.py \ + clipboardobject.py \ + clipboardservice.py \ + config.py \ + main.py + +DISTCLEANFILES = $(service_DATA) + +EXTRA_DIST = $(service_in_files) diff --git a/src/jarabe/controlpanel/Makefile.in b/service/Makefile.in index 3433507..7c95d05 100644 --- a/src/jarabe/controlpanel/Makefile.in +++ b/service/Makefile.in @@ -13,6 +13,7 @@ # PARTICULAR PURPOSE. @SET_MAKE@ + VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -29,15 +30,15 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/controlpanel +subdir = service DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) + $(srcdir)/config.py.in $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = config.py SOURCES = DIST_SOURCES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -46,9 +47,11 @@ am__vpath_adj = case $$p in \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" +am__installdirs = "$(DESTDIR)$(sugardir)" "$(DESTDIR)$(servicedir)" sugarPYTHON_INSTALL = $(INSTALL_DATA) py_compile = $(top_srcdir)/py-compile +serviceDATA_INSTALL = $(INSTALL_DATA) +DATA = $(service_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ @@ -73,9 +76,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,15 +192,27 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/controlpanel +servicedir = $(datadir)/dbus-1/services +service_in_files = \ + org.laptop.ActivityRegistry.service.in \ + org.laptop.Clipboard.service.in + +service_DATA = \ + org.laptop.ActivityRegistry.service \ + org.laptop.Clipboard.service + +sugardir = $(pkgdatadir)/service sugar_PYTHON = \ __init__.py \ - cmd.py \ - gui.py \ - inlinealert.py \ - sectionview.py \ - toolbar.py - + activityregistryservice.py \ + bundleregistry.py \ + clipboardobject.py \ + clipboardservice.py \ + config.py \ + main.py + +DISTCLEANFILES = $(service_DATA) +EXTRA_DIST = $(service_in_files) all: all-am .SUFFIXES: @@ -213,9 +225,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/controlpanel/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign service/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/controlpanel/Makefile + $(AUTOMAKE) --foreign service/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -233,6 +245,8 @@ $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +config.py: $(top_builddir)/config.status $(srcdir)/config.py.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-sugarPYTHON: $(sugar_PYTHON) @$(NORMAL_INSTALL) test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" @@ -261,6 +275,23 @@ uninstall-sugarPYTHON: rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ done +install-serviceDATA: $(service_DATA) + @$(NORMAL_INSTALL) + test -z "$(servicedir)" || $(MKDIR_P) "$(DESTDIR)$(servicedir)" + @list='$(service_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(serviceDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(servicedir)/$$f'"; \ + $(serviceDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(servicedir)/$$f"; \ + done + +uninstall-serviceDATA: + @$(NORMAL_UNINSTALL) + @list='$(service_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(servicedir)/$$f'"; \ + rm -f "$(DESTDIR)$(servicedir)/$$f"; \ + done tags: TAGS TAGS: @@ -296,9 +327,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile +all-am: Makefile $(DATA) installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ + for dir in "$(DESTDIR)$(sugardir)" "$(DESTDIR)$(servicedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -321,6 +352,7 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @@ -343,7 +375,7 @@ info: info-am info-am: -install-data-am: install-sugarPYTHON +install-data-am: install-serviceDATA install-sugarPYTHON install-dvi: install-dvi-am @@ -377,7 +409,7 @@ ps: ps-am ps-am: -uninstall-am: uninstall-sugarPYTHON +uninstall-am: uninstall-serviceDATA uninstall-sugarPYTHON .MAKE: install-am install-strip @@ -387,11 +419,21 @@ uninstall-am: uninstall-sugarPYTHON install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON + install-serviceDATA install-strip install-sugarPYTHON \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am uninstall uninstall-am uninstall-serviceDATA \ + uninstall-sugarPYTHON + + +org.laptop.ActivityRegistry.service: org.laptop.ActivityRegistry.service.in Makefile + @sed -e "s|\@bindir\@|$(bindir)|" $< > $@ + +org.laptop.Clipboard.service: org.laptop.Clipboard.service.in Makefile + @sed -e "s|\@bindir\@|$(bindir)|" $< > $@ +org.laptop.ObjectTypeRegistry.service: org.laptop.ObjectTypeRegistry.service.in Makefile + @sed -e "s|\@bindir\@|$(bindir)|" $< > $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/src/jarabe/view/__init__.py b/service/__init__.py index a9dd95a..52b82c8 100644 --- a/src/jarabe/view/__init__.py +++ b/service/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +# Copyright (C) 2007, 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 diff --git a/service/activityregistryservice.py b/service/activityregistryservice.py new file mode 100644 index 0000000..c8a8efa --- /dev/null +++ b/service/activityregistryservice.py @@ -0,0 +1,166 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# Copyright (C) 2007 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 + +import dbus +import dbus.service + +import bundleregistry + +_ACTIVITY_REGISTRY_SERVICE_NAME = 'org.laptop.ActivityRegistry' +_ACTIVITY_REGISTRY_IFACE = 'org.laptop.ActivityRegistry' +_ACTIVITY_REGISTRY_PATH = '/org/laptop/ActivityRegistry' + +class ActivityRegistry(dbus.service.Object): + def __init__(self): + bus = dbus.SessionBus() + bus_name = dbus.service.BusName(_ACTIVITY_REGISTRY_SERVICE_NAME, + bus=bus) + dbus.service.Object.__init__(self, bus_name, _ACTIVITY_REGISTRY_PATH) + + bundle_registry = bundleregistry.get_registry() + bundle_registry.connect('bundle-added', self._bundle_added_cb) + bundle_registry.connect('bundle-removed', self._bundle_removed_cb) + bundle_registry.connect('bundle-changed', self._bundle_changed_cb) + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='s', out_signature='b', + utf8_strings=True) + def AddBundle(self, bundle_path): + '''Register the activity bundle with the global registry + + bundle_path -- path to the root directory of the activity bundle, + that is, the directory with activity/activity.info as a + child of the directory. + + The bundleregistry.BundleRegistry is responsible for setting + up a set of d-bus service mappings for each available activity. + ''' + registry = bundleregistry.get_registry() + return registry.add_bundle(bundle_path) + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='s', out_signature='b', + utf8_strings=True) + def RemoveBundle(self, bundle_path): + '''Unregister the activity bundle with the global registry + + bundle_path -- path to the activity bundle root directory + ''' + registry = bundleregistry.get_registry() + return registry.remove_bundle(bundle_path) + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='', out_signature='aa{sv}') + def GetActivities(self): + result = [] + registry = bundleregistry.get_registry() + for bundle in registry: + result.append(self._bundle_to_dict(bundle)) + return result + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='s', out_signature='a{sv}') + def GetActivity(self, bundle_id): + registry = bundleregistry.get_registry() + bundle = registry.get_bundle(bundle_id) + if not bundle: + return {} + + return self._bundle_to_dict(bundle) + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='s', out_signature='aa{sv}') + def FindActivity(self, name): + result = [] + key = name.lower() + + for bundle in bundleregistry.get_registry(): + name = bundle.get_name().lower() + bundle_id = bundle.get_bundle_id().lower() + if name.find(key) != -1 or bundle_id.find(key) != -1: + result.append(self._bundle_to_dict(bundle)) + + return result + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='s', out_signature='aa{sv}') + def GetActivitiesForType(self, mime_type): + result = [] + registry = bundleregistry.get_registry() + for bundle in registry.get_activities_for_type(mime_type): + result.append(self._bundle_to_dict(bundle)) + return result + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='sib', out_signature='') + def SetActivityFavorite(self, bundle_id, version, favorite): + registry = bundleregistry.get_registry() + registry.set_bundle_favorite(bundle_id, version, favorite) + + @dbus.service.method(_ACTIVITY_REGISTRY_IFACE, + in_signature='sidd', out_signature='') + def SetActivityPosition(self, bundle_id, version, x, y): + registry = bundleregistry.get_registry() + registry.set_bundle_position(bundle_id, version, float(x), float(y)) + + @dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}') + def ActivityAdded(self, activity_info): + pass + + @dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}') + def ActivityRemoved(self, activity_info): + pass + + @dbus.service.signal(_ACTIVITY_REGISTRY_IFACE, signature='a{sv}') + def ActivityChanged(self, activity_info): + pass + + def _bundle_to_dict(self, bundle): + registry = bundleregistry.get_registry() + favorite = registry.is_bundle_favorite(bundle.get_bundle_id(), + bundle.get_activity_version()) + x, y = registry.get_bundle_position(bundle.get_bundle_id(), + bundle.get_activity_version()) + return {'name': bundle.get_name(), + 'icon': bundle.get_icon(), + 'bundle_id': bundle.get_bundle_id(), + 'version': bundle.get_activity_version(), + 'path': bundle.get_path(), + 'command': bundle.get_command(), + 'show_launcher': bundle.get_show_launcher(), + 'favorite': favorite, + 'installation_time': bundle.get_installation_time(), + 'position_x': x, + 'position_y': y} + + def _bundle_added_cb(self, bundle_registry, bundle): + self.ActivityAdded(self._bundle_to_dict(bundle)) + + def _bundle_removed_cb(self, bundle_registry, bundle): + self.ActivityRemoved(self._bundle_to_dict(bundle)) + + def _bundle_changed_cb(self, bundle_registry, bundle): + self.ActivityChanged(self._bundle_to_dict(bundle)) + +_instance = None + +def get_instance(): + global _instance + if not _instance: + _instance = ActivityRegistry() + return _instance + diff --git a/src/jarabe/model/bundleregistry.py b/service/bundleregistry.py index 75b8ee4..dd26f56 100644 --- a/src/jarabe/model/bundleregistry.py +++ b/service/bundleregistry.py @@ -17,17 +17,15 @@ import os import logging import traceback -import sys import gobject -import cjson +import simplejson from sugar.bundle.activitybundle import ActivityBundle -from sugar.bundle.bundle import MalformedBundleException, \ - AlreadyInstalledException, RegistrationException +from sugar.bundle.bundle import MalformedBundleException from sugar import env -from jarabe import config +import config class BundleRegistry(gobject.GObject): """Service that tracks the available activity bundles""" @@ -42,14 +40,12 @@ class BundleRegistry(gobject.GObject): } def __init__(self): - logging.debug('STARTUP: Loading the bundle registry') gobject.GObject.__init__(self) self._mime_defaults = self._load_mime_defaults() self._bundles = [] - user_path = env.get_user_activities_path() - for activity_dir in [user_path, config.activities_path]: + for activity_dir in self._get_activity_directories(): self._scan_directory(activity_dir) self._last_defaults_mtime = -1 @@ -57,12 +53,21 @@ class BundleRegistry(gobject.GObject): try: self._load_favorites() - except Exception: + except Exception, e: logging.error('Error while loading favorite_activities\n%s.' \ % traceback.format_exc()) self._merge_default_favorites() + def _get_activity_directories(self): + directories = [] + if os.environ.has_key('SUGAR_ACTIVITIES'): + directories.extend(os.environ['SUGAR_ACTIVITIES'].split(':')) + + directories.append(env.get_user_activities_path()) + + return directories + def _load_mime_defaults(self): defaults = {} @@ -89,7 +94,7 @@ class BundleRegistry(gobject.GObject): def _load_favorites(self): favorites_path = env.get_profile_path('favorite_activities') if os.path.exists(favorites_path): - favorites_data = cjson.decode(open(favorites_path).read()) + favorites_data = simplejson.load(open(favorites_path)) favorite_bundles = favorites_data['favorites'] if not isinstance(favorite_bundles, dict): @@ -100,8 +105,7 @@ class BundleRegistry(gobject.GObject): raise ValueError('Invalid format in %s.' % favorites_path) first_value = favorite_bundles.values()[0] - if first_value is not None and \ - not isinstance(first_value, dict): + if first_value is not None and not isinstance(first_value, dict): raise ValueError('Invalid format in %s.' % favorites_path) self._last_defaults_mtime = float(favorites_data['defaults-mtime']) @@ -187,12 +191,9 @@ class BundleRegistry(gobject.GObject): return False def _add_bundle(self, bundle_path): - logging.debug('STARTUP: Adding bundle %r' % bundle_path) try: bundle = ActivityBundle(bundle_path) except MalformedBundleException: - logging.error('Error loading bundle %r:\n%s' % (bundle_path, - ''.join(traceback.format_exception(*sys.exc_info())))) return None self._bundles.append(bundle) @@ -286,55 +287,7 @@ class BundleRegistry(gobject.GObject): path = env.get_profile_path('favorite_activities') favorites_data = {'defaults-mtime': self._last_defaults_mtime, 'favorites': self._favorite_bundles} - open(path, 'w').write(cjson.encode(favorites_data)) - - def is_installed(self, bundle): - return self.get_bundle(bundle.get_bundle_id()) is not None - - def install(self, bundle): - activities_path = env.get_user_activities_path() - if self.is_installed(bundle): - raise AlreadyInstalledException - - install_dir = env.get_user_activities_path() - install_path = bundle.install(install_dir) - - if not self.add_bundle(install_path): - raise RegistrationException - - def uninstall(self, bundle, force=False): - act = self.get_bundle(bundle.get_bundle_id()) - if not force and \ - act.get_activity_version() != bundle.get_activity_version(): - logging.warning('Not uninstalling, different bundle present') - return - elif not act.get_path().startswith(env.get_user_activities_path()): - logging.warning('Not uninstalling system activity') - return - - install_path = act.get_path() - - bundle.uninstall(install_path, force) - - if not self.remove_bundle(install_path): - raise RegistrationException - - def upgrade(self, bundle): - act = self.get_bundle(bundle.get_bundle_id()) - if act is None: - logging.warning('Activity not installed') - elif act.get_path().startswith(env.get_user_activities_path()): - try: - self.uninstall(bundle, force=True) - except Exception: - logging.error('Uninstall failed, still trying to install ' \ - 'newer bundle:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - else: - logging.warning('Unable to uninstall system activity, ' \ - 'installing upgraded version in user activities') - - self.install(bundle) + simplejson.dump(favorites_data, open(path, 'w'), indent=1) _instance = None diff --git a/src/jarabe/frame/clipboardobject.py b/service/clipboardobject.py index 0a595d0..06b606c 100644 --- a/src/jarabe/frame/clipboardobject.py +++ b/service/clipboardobject.py @@ -18,11 +18,11 @@ import os import logging import urlparse -from gettext import gettext as _ from sugar import mime -from sugar.bundle.activitybundle import ActivityBundle -class ClipboardObject(object): +import bundleregistry + +class ClipboardObject: def __init__(self, object_path, name): self._id = object_path @@ -40,30 +40,30 @@ class ClipboardObject(object): def get_name(self): name = self._name if not name: - mime_type = mime.get_mime_description(self.get_mime_type()) - - if not mime_type: - mime_type = 'Data' - name = _('%s clipping') % mime_type - + name = mime.get_mime_description(self.get_mime_type()) + if not name: + name = '' return name def get_icon(self): return mime.get_mime_icon(self.get_mime_type()) def get_preview(self): - for mime_type in ['text/plain']: - if mime_type in self._formats: - return self._formats[mime_type].get_data() + # TODO: should previews really be here? + #return self._get_type_info().get_preview() return '' - def is_bundle(self): - # A bundle will have only one format. - if not self._formats: - return False + def get_activities(self): + mime_type = self.get_mime_type() + if not mime_type: + return '' + + registry = bundleregistry.get_registry() + activities = registry.get_activities_for_type(self.get_mime_type()) + if activities: + return [activity.get_bundle_id() for activity in activities] else: - return self._formats.keys()[0] in [ActivityBundle.MIME_TYPE, - ActivityBundle.DEPRECATED_MIME_TYPE] + return '' def get_percent(self): return self._percent @@ -94,7 +94,7 @@ class ClipboardObject(object): return format -class Format(object): +class Format: def __init__(self, mime_type, data, on_disk): self.owns_disk_data = False diff --git a/service/clipboardservice.py b/service/clipboardservice.py new file mode 100644 index 0000000..4378db0 --- /dev/null +++ b/service/clipboardservice.py @@ -0,0 +1,212 @@ +# Copyright (C) 2006, Red Hat, Inc. +# +# 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 + +import logging +import os +import shutil +import urlparse +import tempfile + +import dbus +import dbus.service + +from sugar import mime + +from clipboardobject import ClipboardObject, Format + +NAME_KEY = 'NAME' +PERCENT_KEY = 'PERCENT' +ICON_KEY = 'ICON' +PREVIEW_KEY = 'PREVIEW' +ACTIVITIES_KEY = 'ACTIVITIES' +FORMATS_KEY = 'FORMATS' + +TYPE_KEY = 'TYPE' +DATA_KEY = 'DATA' +ON_DISK_KEY = 'ON_DISK' + +_CLIPBOARD_DBUS_INTERFACE = "org.laptop.Clipboard" +_CLIPBOARD_OBJECT_PATH = "/org/laptop/Clipboard" +_CLIPBOARD_OBJECTS_PATH = _CLIPBOARD_OBJECT_PATH + "/Objects/" + +class ClipboardService(dbus.service.Object): + + def __init__(self): + self._objects = {} + self._next_id = 0 + + bus = dbus.SessionBus() + bus_name = dbus.service.BusName(_CLIPBOARD_DBUS_INTERFACE, bus=bus) + dbus.service.Object.__init__(self, bus_name, + _CLIPBOARD_OBJECT_PATH) + + def _get_next_object_id(self): + self._next_id += 1 + return self._next_id + + # dbus methods + @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, + in_signature="s", out_signature="o") + def add_object(self, name): + logging.debug('ClipboardService.add_object') + op = _CLIPBOARD_OBJECTS_PATH + "%d" % self._get_next_object_id() + self._objects[op] = ClipboardObject(op, name) + self.object_added(dbus.ObjectPath(op), name) + logging.debug('Added object ' + op + ' with name ' + name) + return dbus.ObjectPath(op) + + @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, + in_signature="ssayb", out_signature="", + byte_arrays=True) + def add_object_format(self, object_path, format_type, data, on_disk): + logging.debug('ClipboardService.add_object_format') + cb_object = self._objects[str(object_path)] + + if format_type == 'XdndDirectSave0': + format = Format('text/uri-list', data + '\r\n', on_disk) + format.owns_disk_data = True + cb_object.add_format(format) + elif on_disk and cb_object.get_percent() == 100: + new_uri = self._copy_file(data) + cb_object.add_format(Format(format_type, new_uri, on_disk)) + logging.debug('Added format of type ' + format_type + + ' with path at ' + new_uri) + else: + cb_object.add_format(Format(format_type, data, on_disk)) + logging.debug('Added in-memory format of type ' + format_type + '.') + + self.object_state_changed(object_path, {NAME_KEY: cb_object.get_name(), + PERCENT_KEY: cb_object.get_percent(), + ICON_KEY: cb_object.get_icon(), + PREVIEW_KEY: cb_object.get_preview(), + ACTIVITIES_KEY: cb_object.get_activities()}) + + @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, + in_signature="o", out_signature="") + def delete_object(self, object_path): + cb_object = self._objects.pop(str(object_path)) + cb_object.destroy() + self.object_deleted(object_path) + logging.debug('Deleted object with object_id ' + object_path) + + @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, + in_signature="oi", out_signature="") + def set_object_percent(self, object_path, percent): + cb_object = self._objects[str(object_path)] + if percent < 0 or percent > 100: + raise ValueError("invalid percentage") + if cb_object.get_percent() > percent: + raise ValueError("invalid percentage; less than current percent") + if cb_object.get_percent() == percent: + # ignore setting same percentage + return + + cb_object.set_percent(percent) + + if percent == 100: + formats = cb_object.get_formats() + for format_name, format in formats.iteritems(): + if format.is_on_disk() and not format.owns_disk_data: + new_uri = self._copy_file(format.get_data()) + format.set_data(new_uri) + + # Add a text/plain format to objects that are text but lack it + if 'text/plain' not in formats.keys(): + if 'UTF8_STRING' in formats.keys(): + self.add_object_format( + object_path, 'text/plain', + data=formats['UTF8_STRING'].get_data(), on_disk=False) + elif 'text/unicode' in formats.keys(): + self.add_object_format( + object_path, 'text/plain', + data=formats['UTF8_STRING'].get_data(), on_disk=False) + + self.object_state_changed(object_path, {NAME_KEY: cb_object.get_name(), + PERCENT_KEY: percent, + ICON_KEY: cb_object.get_icon(), + PREVIEW_KEY: cb_object.get_preview(), + ACTIVITIES_KEY: cb_object.get_activities()}) + + @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, + in_signature="o", out_signature="a{sv}") + def get_object(self, object_path): + logging.debug('ClipboardService.get_object') + + if not self._objects.has_key(str(object_path)): + return dbus.Dictionary({}, signature='sv') + + cb_object = self._objects[str(object_path)] + formats = cb_object.get_formats() + format_types = dbus.Array([], signature='s') + + for key in formats.keys(): + format_types.append(key) + + result_dict = {NAME_KEY: cb_object.get_name(), + PERCENT_KEY: cb_object.get_percent(), + ICON_KEY: cb_object.get_icon(), + PREVIEW_KEY: cb_object.get_preview(), + ACTIVITIES_KEY: cb_object.get_activities(), + FORMATS_KEY: format_types} + return dbus.Dictionary(result_dict) + + @dbus.service.method(_CLIPBOARD_DBUS_INTERFACE, + in_signature="os", out_signature="a{sv}") + def get_object_data(self, object_path, format_type): + logging.debug('ClipboardService.get_object_data') + cb_object = self._objects[str(object_path)] + format = cb_object.get_formats()[format_type] + result_dict = {TYPE_KEY: format.get_type(), + DATA_KEY: dbus.ByteArray(format.get_data()), + ON_DISK_KEY: format.is_on_disk()} + return dbus.Dictionary(result_dict) + + # dbus signals + @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="os") + def object_added(self, object_path, name): + pass + + @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="o") + def object_deleted(self, object_path): + pass + + @dbus.service.signal(_CLIPBOARD_DBUS_INTERFACE, signature="oa{sv}") + def object_state_changed(self, object_path, values): + pass + + def _copy_file(self, original_uri): + uri = urlparse.urlparse(original_uri) + path, file_name = os.path.split(uri.path) + + root, ext = os.path.splitext(file_name) + if not ext or ext == '.': + mime_type = mime.get_for_file(uri.path) + ext = '.' + mime.get_primary_extension(mime_type) + + f, new_file_path = tempfile.mkstemp(ext, root) + del f + shutil.copyfile(uri.path, new_file_path) + os.chmod(new_file_path, 0644) + + return 'file://' + new_file_path + +_instance = None + +def get_instance(): + global _instance + if not _instance: + _instance = ClipboardService() + return _instance diff --git a/src/jarabe/util/__init__.py b/service/config.py index 1610dd0..1ebe7ff 100644 --- a/src/jarabe/util/__init__.py +++ b/service/config.py @@ -1,7 +1,4 @@ -"""OLPC Sugar Jarabe utility modules -""" - -# Copyright (C) 2008, One Laptop Per Child +# Copyright (C) 2008 Red Hat, Inc. # # 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 @@ -17,3 +14,4 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +data_path = '/home/marco/sucrose-0.82/install/share/sugar/data' diff --git a/src/jarabe/model/__init__.py b/service/config.py.in index a9dd95a..c617d7e 100644 --- a/src/jarabe/model/__init__.py +++ b/service/config.py.in @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +# Copyright (C) 2008 Red Hat, Inc. # # 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 @@ -14,3 +14,4 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +data_path = '@prefix@/share/sugar/data' diff --git a/extensions/cpsection/network/__init__.py b/service/main.py index 8fea274..4883f82 100644..100755 --- a/extensions/cpsection/network/__init__.py +++ b/service/main.py @@ -1,4 +1,5 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +# Copyright (C) 2006, Red Hat, Inc. +# Copyright (C) 2007, 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 @@ -14,12 +15,29 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from gettext import gettext as _ +import logging -CLASS = 'Network' -ICON = 'module-network' -TITLE = _('Network') -KEYWORDS = ['network', 'jabber', 'radio', 'server'] +import gobject +import dbus.glib + +from sugar import logger +import activityregistryservice +import clipboardservice +def main(): + logger.start('shellservice') + logging.info('Starting shell service.') + + gobject.threads_init() + dbus.glib.threads_init() + + clipboardservice.get_instance() + activityregistryservice.get_instance() + + loop = gobject.MainLoop() + try: + loop.run() + except KeyboardInterrupt: + print 'Ctrl+C pressed, exiting...' diff --git a/service/org.laptop.ActivityRegistry.service.in b/service/org.laptop.ActivityRegistry.service.in new file mode 100644 index 0000000..ab6647c --- /dev/null +++ b/service/org.laptop.ActivityRegistry.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name = org.laptop.ActivityRegistry +Exec = @bindir@/sugar-shell-service + diff --git a/service/org.laptop.Clipboard.service.in b/service/org.laptop.Clipboard.service.in new file mode 100644 index 0000000..7ce3f6e --- /dev/null +++ b/service/org.laptop.Clipboard.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name = org.laptop.Clipboard +Exec = @bindir@/sugar-shell-service + diff --git a/src/Makefile.am b/src/Makefile.am index 83571a4..daf31ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1 +1,12 @@ -SUBDIRS = jarabe +SUBDIRS = controlpanel hardware model view intro + +sugardir = $(pkgdatadir)/shell +sugar_PYTHON = \ + config.py \ + emulator.py \ + logsmanager.py \ + main.py \ + session.py \ + shellservice.py + +EXTRA_DIST = $(bin_SCRIPTS) $(conf_DATA) diff --git a/src/Makefile.in b/src/Makefile.in index b000ddc..7227b90 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -30,13 +30,14 @@ NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : subdir = src -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(srcdir)/config.py.in $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = config.py SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ @@ -46,6 +47,15 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(sugardir)" +sugarPYTHON_INSTALL = $(INSTALL_DATA) +py_compile = $(top_srcdir)/py-compile RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags @@ -75,9 +85,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -194,7 +201,17 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = jarabe +SUBDIRS = controlpanel hardware model view intro +sugardir = $(pkgdatadir)/shell +sugar_PYTHON = \ + config.py \ + emulator.py \ + logsmanager.py \ + main.py \ + session.py \ + shellservice.py + +EXTRA_DIST = $(bin_SCRIPTS) $(conf_DATA) all: all-recursive .SUFFIXES: @@ -227,6 +244,36 @@ $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +config.py: $(top_builddir)/config.status $(srcdir)/config.py.in + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ +install-sugarPYTHON: $(sugar_PYTHON) + @$(NORMAL_INSTALL) + test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" + @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ + if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ + if test -f $$b$$p; then \ + f=$(am__strip_dir) \ + dlist="$$dlist $$f"; \ + echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ + $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ + else :; fi; \ + done; \ + if test -n "$$dlist"; then \ + if test -z "$(DESTDIR)"; then \ + PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ + else \ + PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ + fi; \ + else :; fi + +uninstall-sugarPYTHON: + @$(NORMAL_UNINSTALL) + @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ + f=$(am__strip_dir) \ + rm -f "$(DESTDIR)$(sugardir)/$$f"; \ + rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ + rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ + done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -406,6 +453,9 @@ check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: + for dir in "$(DESTDIR)$(sugardir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive @@ -448,7 +498,7 @@ info: info-recursive info-am: -install-data-am: +install-data-am: install-sugarPYTHON install-dvi: install-dvi-recursive @@ -482,7 +532,7 @@ ps: ps-recursive ps-am: -uninstall-am: +uninstall-am: uninstall-sugarPYTHON .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ install-strip @@ -495,10 +545,11 @@ uninstall-am: install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ - tags-recursive uninstall uninstall-am + install-strip install-sugarPYTHON installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-sugarPYTHON # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/jarabe/frame/__init__.py b/src/config.py index d7aec3d..3b3a8a6 100644 --- a/src/jarabe/frame/__init__.py +++ b/src/config.py @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +# Copyright (C) 2008 Red Hat, Inc. # # 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 @@ -14,12 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from jarabe.frame.frame import Frame +prefix = '/home/marco/sucrose-0.82/install' +data_path = '/home/marco/sucrose-0.82/install/share/sugar/data' +shell_path = '/home/marco/sucrose-0.82/install/share/sugar/shell' +version = '0.82.1' -_view = None - -def get_view(): - global _view - if not _view: - _view = Frame() - return _view diff --git a/src/jarabe/config.py.in b/src/config.py.in index 6c418e9..f8e776f 100644 --- a/src/jarabe/config.py.in +++ b/src/config.py.in @@ -14,13 +14,8 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# pylint: disable-msg=C0301 - prefix = '@prefix@' data_path = '@prefix@/share/sugar/data' shell_path = '@prefix@/share/sugar/shell' -locale_path = '@prefix@/share/locale' -ext_path = '@prefix@/share/sugar/extensions' -activities_path = "@prefix@/share/sugar/activities" version = '@SUCROSE_VERSION@' diff --git a/src/jarabe/controlpanel/Makefile.am b/src/controlpanel/Makefile.am index fb796d7..5acd9a1 100644 --- a/src/jarabe/controlpanel/Makefile.am +++ b/src/controlpanel/Makefile.am @@ -1,4 +1,6 @@ -sugardir = $(pythondir)/jarabe/controlpanel +SUBDIRS = model view + +sugardir = $(pkgdatadir)/shell/controlpanel sugar_PYTHON = \ __init__.py \ cmd.py \ diff --git a/src/jarabe/util/Makefile.in b/src/controlpanel/Makefile.in index b149fcd..e00cc18 100644 --- a/src/jarabe/util/Makefile.in +++ b/src/controlpanel/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/util +subdir = src/controlpanel DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -85,9 +85,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -204,12 +201,15 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = \ - telepathy - -sugardir = $(pythondir)/jarabe/util +SUBDIRS = model view +sugardir = $(pkgdatadir)/shell/controlpanel sugar_PYTHON = \ - __init__.py + __init__.py \ + cmd.py \ + gui.py \ + inlinealert.py \ + sectionview.py \ + toolbar.py all: all-recursive @@ -223,9 +223,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/util/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/controlpanel/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/util/Makefile + $(AUTOMAKE) --foreign src/controlpanel/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/jarabe/controlpanel/__init__.py b/src/controlpanel/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/controlpanel/__init__.py diff --git a/src/jarabe/controlpanel/cmd.py b/src/controlpanel/cmd.py index 12de1e2..ae5d298 100644 --- a/src/jarabe/controlpanel/cmd.py +++ b/src/controlpanel/cmd.py @@ -18,10 +18,8 @@ import sys import getopt import os from gettext import gettext as _ -import traceback -import logging -from jarabe import config +import config _RESTART = 1 @@ -32,8 +30,6 @@ _general_error = _("sugar-control-panel: %s") def cmd_help(): '''Print the help to the screen''' - # TRANS: Translators, there's a empty line at the end of this string, - # which must appear in the translated string (msgstr) as well. print _('Usage: sugar-control-panel [ option ] key [ args ... ] \n\ Control for the sugar environment. \n\ Options: \n\ @@ -51,25 +47,20 @@ def note_restart(): 'Hit ctrl+alt+erase on the keyboard to trigger a restart.') def load_modules(): - '''Build a list of pointers to available modules and import them. + '''Build a list of pointers to available modules in the model directory + and load them. ''' + subpath = ['controlpanel', 'model'] + file_names = os.listdir(os.path.join(config.shell_path, '/'.join(subpath))) + modules = [] - - path = os.path.join(config.ext_path, 'cpsection') - folder = os.listdir(path) - - for item in folder: - if os.path.isdir(os.path.join(path, item)) and \ - os.path.exists(os.path.join(path, item, 'model.py')): - try: - module = __import__('.'.join(('cpsection', item, 'model')), - globals(), locals(), ['model']) - except Exception: - logging.error('Exception while loading extension:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - else: - modules.append(module) - + for file_name in file_names: + if file_name.endswith('.py') and file_name != '__init__.py': + module_name = os.path.splitext(file_name)[0] + module = __import__('.'.join(subpath) + '.' + + module_name, globals(), locals(), + [module_name]) + modules.append(module) return modules def main(): @@ -101,7 +92,7 @@ def main(): if option in ("-l"): for module in modules: methods = dir(module) - print '%s:' % module.__name__.split('.')[1] + print '%s:' % module.__name__.split('.')[-1] for method in methods: if method.startswith('get_'): print ' %s' % method[4:] diff --git a/src/jarabe/controlpanel/gui.py b/src/controlpanel/gui.py index 2f8da51..527f3b7 100644 --- a/src/jarabe/controlpanel/gui.py +++ b/src/controlpanel/gui.py @@ -14,23 +14,20 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import gtk import os +import gobject import logging from gettext import gettext as _ -import sys -import traceback - -import gobject -import gtk from sugar.graphics.icon import Icon from sugar.graphics import style from sugar.graphics.alert import Alert +import config +from session import get_session_manager -from jarabe.model.session import get_session_manager -from jarabe.controlpanel.toolbar import MainToolbar -from jarabe.controlpanel.toolbar import SectionToolbar -from jarabe import config +from controlpanel.toolbar import MainToolbar +from controlpanel.toolbar import SectionToolbar _logger = logging.getLogger('ControlPanel') _MAX_COLUMNS = 5 @@ -197,18 +194,10 @@ class ControlPanel(gtk.Window): self._section_toolbar.show() self._current_option = option - - mod = __import__('.'.join(('cpsection', option, 'view')), - globals(), locals(), ['view']) - view_class = getattr(mod, self._options[option]['view'], None) - - mod = __import__('.'.join(('cpsection', option, 'model')), - globals(), locals(), ['model']) - model = ModelWrapper(mod) - + view_class = self._options[option]['view'] + model = self._options[option]['model'] self._section_view = view_class(model, - self._options[option]['alerts']) - + self._options[option]['alerts']) self._set_canvas(self._section_view) self._section_view.show() self._section_view.connect('notify::is-valid', @@ -224,39 +213,55 @@ class ControlPanel(gtk.Window): self._section_view.auto_close = True def _get_options(self): - '''Get the available option information from the extensions + '''Get the available option information from the subfolders + model and view. ''' options = {} - path = os.path.join(config.ext_path, 'cpsection') - folder = os.listdir(path) - - for item in folder: - if os.path.isdir(os.path.join(path, item)) and \ - os.path.exists(os.path.join(path, item, '__init__.py')): - try: - mod = __import__('.'.join(('cpsection', item)), - globals(), locals(), [item]) - view_class = getattr(mod, 'CLASS', None) - if view_class is not None: - options[item] = {} - options[item]['alerts'] = [] - options[item]['view'] = view_class - options[item]['icon'] = getattr(mod, 'ICON', item) - options[item]['title'] = getattr(mod, 'TITLE', item) - options[item]['color'] = getattr(mod, 'COLOR', None) - keywords = getattr(mod, 'KEYWORDS', []) - keywords.append(options[item]['title'].lower()) - if item not in keywords: - keywords.append(item) - else: - _logger.error('There is no CLASS constant specifieds ' \ - 'in the view file \'%s\'.' % item) - except Exception: - logging.error('Exception while loading extension:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - - return options + subpath = ['controlpanel', 'view'] + names = os.listdir(os.path.join(config.shell_path, '/'.join(subpath))) + + for name in names: + if name.endswith('.py') and name != '__init__.py': + tmp = os.path.splitext(name)[0] + mod = __import__('.'.join(subpath) + '.' + tmp, globals(), + locals(), [tmp]) + view_class_str = getattr(mod, 'CLASS', None) + if view_class_str: + view_class = getattr(mod, view_class_str, None) + if not view_class: + _logger.error('The CLASS constant \'%s\' does not ' \ + 'match a class name.' % view_class) + else: + options[tmp] = {} + options[tmp]['alerts'] = [] + options[tmp]['view'] = view_class + options[tmp]['icon'] = getattr(mod, 'ICON', tmp) + options[tmp]['title'] = getattr(mod, 'TITLE', + tmp) + options[tmp]['color'] = getattr(mod, 'COLOR', + None) + else: + _logger.error('There is no CLASS constant specified in ' \ + 'the view file \'%s\'.' % tmp) + + subpath = ['controlpanel', 'model'] + names = os.listdir(os.path.join(config.shell_path, '/'.join(subpath))) + + for name in names: + if name.endswith('.py') and name != '__init__.py': + tmp = os.path.splitext(name)[0] + if tmp in options: + mod = __import__('.'.join(subpath) + '.' + tmp, + globals(), locals(), [tmp]) + keywords = getattr(mod, 'KEYWORDS', []) + keywords.append(options[tmp]['title'].lower()) + if tmp not in keywords: + keywords.append(tmp) + options[tmp]['model'] = ModelWrapper(mod) + options[tmp]['keywords'] = keywords + + return options def __cancel_clicked_cb(self, widget): self._section_view.undo() diff --git a/src/jarabe/controlpanel/inlinealert.py b/src/controlpanel/inlinealert.py index 619a379..619a379 100644 --- a/src/jarabe/controlpanel/inlinealert.py +++ b/src/controlpanel/inlinealert.py diff --git a/src/controlpanel/model/Makefile.am b/src/controlpanel/model/Makefile.am new file mode 100644 index 0000000..20c27a9 --- /dev/null +++ b/src/controlpanel/model/Makefile.am @@ -0,0 +1,10 @@ +sugardir = $(pkgdatadir)/shell/controlpanel/model +sugar_PYTHON = \ + __init__.py \ + aboutme.py \ + aboutxo.py \ + datetime.py \ + frame.py \ + language.py \ + network.py \ + power.py diff --git a/src/jarabe/util/telepathy/Makefile.in b/src/controlpanel/model/Makefile.in index 36fc7a7..ba3f6e2 100644 --- a/src/jarabe/util/telepathy/Makefile.in +++ b/src/controlpanel/model/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/util/telepathy +subdir = src/controlpanel/model DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,10 +189,16 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/util/telepathy +sugardir = $(pkgdatadir)/shell/controlpanel/model sugar_PYTHON = \ - __init__.py \ - connection_watcher.py + __init__.py \ + aboutme.py \ + aboutxo.py \ + datetime.py \ + frame.py \ + language.py \ + network.py \ + power.py all: all-am @@ -209,9 +212,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/util/telepathy/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/controlpanel/model/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/util/telepathy/Makefile + $(AUTOMAKE) --foreign src/controlpanel/model/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/jarabe/view/__init__.py b/src/controlpanel/model/__init__.py index a9dd95a..2b0f269 100644 --- a/src/jarabe/view/__init__.py +++ b/src/controlpanel/model/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +# 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 @@ -13,4 +13,5 @@ # 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/extensions/cpsection/aboutme/model.py b/src/controlpanel/model/aboutme.py index 8500799..3818792 100644 --- a/extensions/cpsection/aboutme/model.py +++ b/src/controlpanel/model/aboutme.py @@ -16,7 +16,9 @@ # from gettext import gettext as _ -import gconf + +from sugar import profile +from sugar.graphics.xocolor import XoColor _COLORS = {'red': {'dark':'#b20008', 'medium':'#e6000a', 'light':'#ffadce'}, 'orange': {'dark':'#9a5200', 'medium':'#c97e00', 'light':'#ffc169'}, @@ -29,8 +31,7 @@ _COLORS = {'red': {'dark':'#b20008', 'medium':'#e6000a', 'light':'#ffadce'}, _MODIFIERS = ('dark', 'medium', 'light') def get_nick(): - client = gconf.client_get_default() - return client.get_string("/desktop/sugar/user/nick") + return profile.get_nick_name() def print_nick(): print get_nick() @@ -41,18 +42,18 @@ def set_nick(nick): """ if not nick: raise ValueError(_("You must enter a name.")) + pro = profile.get_profile() if not isinstance(nick, unicode): nick = unicode(nick, 'utf-8') - client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/nick", nick) + pro.nick_name = nick + pro.save() return 1 -def get_color(): - client = gconf.client_get_default() - return client.get_string("/desktop/sugar/user/color") +def get_color(): + return profile.get_color() def print_color(): - color_string = get_color() + color_string = get_color().to_string() tmp = color_string.split(',') stroke_tuple = None @@ -97,19 +98,19 @@ def set_color(stroke, fill, stroke_modifier='medium', fill_modifier='medium'): color = _COLORS[stroke][stroke_modifier] + ',' \ + _COLORS[fill][fill_modifier] - - client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/color", color) + pro = profile.get_profile() + pro.color = XoColor(color) + pro.save() return 1 -def get_color_xo(): - client = gconf.client_get_default() - return client.get_string("/desktop/sugar/user/color") +def get_color_xo(): + return profile.get_color() def set_color_xo(color): """Set a color with an XoColor This method is used by the graphical user interface """ - client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/color", color) + pro = profile.get_profile() + pro.color = color + pro.save() return 1 diff --git a/extensions/cpsection/aboutxo/model.py b/src/controlpanel/model/aboutxo.py index 4b5b27e..10815ef 100644 --- a/extensions/cpsection/aboutxo/model.py +++ b/src/controlpanel/model/aboutxo.py @@ -18,7 +18,6 @@ import os import logging import re -import subprocess from gettext import gettext as _ _logger = logging.getLogger('ControlPanel - AboutXO') @@ -63,22 +62,6 @@ def get_firmware_number(): def print_firmware_number(): print get_firmware_number() -def get_wireless_firmware(): - try: - info = subprocess.Popen(["/usr/sbin/ethtool", "-i", "eth0"], - stdout=subprocess.PIPE).stdout.readlines() - except OSError: - return _not_available - try: - wireless_firmware = [line for line in info - if line.startswith('firmware')][0].split()[1] - except IndexError: - wireless_firmware = _not_available - return wireless_firmware - -def print_wireless_firmware(): - print get_wireless_firmware() - def _read_file(path): if os.access(path, os.R_OK) == 0: return None @@ -94,7 +77,7 @@ def _read_file(path): return None def get_license(): - license_file = "/usr/share/licenses/common-licenses/GPLv2" + license_file = "/usr/share/licenses/common-licenses/GPL-2" lang = os.environ['LANG'] if lang.endswith("UTF-8"): lang = lang[:-6] diff --git a/extensions/cpsection/datetime/model.py b/src/controlpanel/model/datetime.py index 76064e4..4a4c560 100644 --- a/extensions/cpsection/datetime/model.py +++ b/src/controlpanel/model/datetime.py @@ -22,7 +22,8 @@ import os from gettext import gettext as _ -import gconf + +from sugar import profile _zone_tab = '/usr/share/zoneinfo/zone.tab' @@ -68,8 +69,8 @@ def read_all_timezones(fn=_zone_tab): return timezones def get_timezone(): - client = gconf.client_get_default() - return client.get_string('/desktop/sugar/date/timezone') + pro = profile.get_profile() + return pro.timezone def print_timezone(): print get_timezone() @@ -81,8 +82,9 @@ def set_timezone(timezone): timezones = read_all_timezones() if timezone in timezones: os.environ['TZ'] = timezone - client = gconf.client_get_default() - client.set_string('/desktop/sugar/date/timezone', timezone) + pro = profile.get_profile() + pro.timezone = timezone + pro.save() else: raise ValueError(_("Error timezone does not exist.")) return 1 diff --git a/extensions/cpsection/frame/model.py b/src/controlpanel/model/frame.py index 9eea9ad..0e19703 100644 --- a/extensions/cpsection/frame/model.py +++ b/src/controlpanel/model/frame.py @@ -16,12 +16,12 @@ # from gettext import gettext as _ -import gconf + +from sugar import profile def get_corner_delay(): - client = gconf.client_get_default() - corner_delay = client.get_int('/desktop/sugar/frame/corner_delay') - return corner_delay + pro = profile.get_profile() + return pro.hot_corners_delay def print_corner_delay(): print get_corner_delay() @@ -35,15 +35,15 @@ def set_corner_delay(delay): try: int(delay) except ValueError: - raise ValueError(_("Value must be an integer.")) - client = gconf.client_get_default() - client.set_int('/desktop/sugar/frame/corner_delay', int(delay)) - return 0 + raise ValueError(_("Value must be an integer.")) + pro = profile.get_profile() + pro.hot_corners_delay = int(delay) + pro.save() + return 1 def get_edge_delay(): - client = gconf.client_get_default() - edge_delay = client.get_int('/desktop/sugar/frame/edge_delay') - return edge_delay + pro = profile.get_profile() + return pro.warm_edges_delay def print_edge_delay(): print get_edge_delay() @@ -57,7 +57,8 @@ def set_edge_delay(delay): try: int(delay) except ValueError: - raise ValueError(_("Value must be an integer.")) - client = gconf.client_get_default() - client.set_int('/desktop/sugar/frame/edge_delay', int(delay)) - return 0 + raise ValueError(_("Value must be an integer.")) + pro = profile.get_profile() + pro.warm_edges_delay = int(delay) + pro.save() + return 1 diff --git a/extensions/cpsection/language/model.py b/src/controlpanel/model/language.py index d539e7c..404d9dd 100644 --- a/extensions/cpsection/language/model.py +++ b/src/controlpanel/model/language.py @@ -53,98 +53,82 @@ def read_all_languages(): return locales def _initialize(): - if set_languages.__doc__ is None: + if set_language.__doc__ is None: # when running under 'python -OO', all __doc__ fields are None, # so += would fail -- and this function would be unnecessary anyway. return languages = read_all_languages() - set_languages.__doc__ += '\n' + set_language.__doc__ += '\n' for lang in languages: - set_languages.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' + + set_language.__doc__ += '%s \n' % (lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_')) -def _write_i18n(langs): - colon = ':' - langstr = colon.join(langs) +def _write_i18n(lang): path = os.path.join(os.environ.get("HOME"), '.i18n') - if not os.access(path, os.W_OK): + if os.access(path, os.W_OK) == 0: print _standard_msg fd = open(path, 'w') fd.write('LANG="%s"\n' % _default_lang) - fd.write('LANGUAGE="%s"\n' % _default_lang) fd.close() else: - fd = open(path, 'w') - fd.write('LANG="%s"\n' % langs[0]) - fd.write('LANGUAGE="%s"\n' % langstr) - fd.close() + fd = open(path, 'r') + lines = fd.readlines() + fd.close() + for i in range(len(lines)): + if lines[i][:5] == "LANG=": + lines[i] = 'LANG="%s"\n' % lang + fd = open(path, 'w') + fd.writelines(lines) + fd.close() -def get_languages(): +def get_language(): path = os.path.join(os.environ.get("HOME"), '.i18n') - if not os.access(path, os.R_OK): + if os.access(path, os.R_OK) == 0: print _standard_msg fd = open(path, 'w') fd.write('LANG="%s"\n' % _default_lang) - fd.write('LANGUAGE="%s"\n' % _default_lang) fd.close() - return [_default_lang] + return _default_lang fd = open(path, "r") lines = fd.readlines() fd.close() - langlist = None + lang = None for line in lines: - if line.startswith("LANGUAGE="): - lang = line[9:].replace('"', '') + if line[:5] == "LANG=": + lang = line[5:].replace('"', '') lang = lang.strip() - langlist = lang.split(':') - elif line.startswith("LANG="): - lang = line[9:].replace('"', '') - # There might be cases where .i18n may not contain a LANGUAGE field - if langlist == None: - return [lang] - else: - return langlist + return lang -def print_languages(): - codes = get_languages() +def print_language(): + code = get_language() languages = read_all_languages() - for code in codes: - found_lang = False - for lang in languages: - if lang[2].split('.')[0] == code.split('.')[0]: - print lang[0].replace(' ', '_') + '/' + \ - lang[1].replace(' ', '_') - found_lang = True - break - if not found_lang: - print (_("Language for code=%s could not be determined.") % code) + for lang in languages: + if lang[2].split('.')[0] == code.split('.')[0]: + print lang[0].replace(' ', '_') + '/' + lang[1].replace(' ', '_') + return + print (_("Language for code=%s could not be determined.") % code) -def set_languages(languages): +def set_language(language): """Set the system language. languages : """ - if isinstance(languages, str): - # This came from the commandline - #TODO: Support multiple languages from the command line - if languages.endswith('utf8'): - _write_i18n(languages) - return 1 - else: - langs = read_all_languages() - for lang, territory, locale in langs: - code = lang.replace(' ', '_') + '/' \ - + territory.replace(' ', '_') - if code == languages: - _write_i18n(locale) - return 1 - print (_("Sorry I do not speak \'%s\'.") % languages) - else: - _write_i18n(languages) + if language.endswith('utf8'): + _write_i18n(language) + return 1 + else: + languages = read_all_languages() + for lang, territory, locale in languages: + code = lang.replace(' ', '_') + '/' \ + + territory.replace(' ', '_') + if code == language: + _write_i18n(locale) + return 1 + print (_("Sorry I do not speak \'%s\'.") % language) # inilialize the docstrings for the language _initialize() diff --git a/src/controlpanel/model/network.py b/src/controlpanel/model/network.py new file mode 100644 index 0000000..cbe0473 --- /dev/null +++ b/src/controlpanel/model/network.py @@ -0,0 +1,101 @@ +# 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 +# + +import dbus +from gettext import gettext as _ + +from sugar import profile +from hardware import hardwaremanager + +NM_SERVICE_NAME = 'org.freedesktop.NetworkManager' +NM_SERVICE_PATH = '/org/freedesktop/NetworkManager' +NM_SERVICE_IFACE = 'org.freedesktop.NetworkManager' +NM_ASLEEP = 1 + +KEYWORDS = ['network', 'jabber', 'radio', 'server'] + +class ReadError(Exception): + def __init__(self, value): + self.value = value + def __str__(self): + return repr(self.value) + +def get_jabber(): + pro = profile.get_profile() + return pro.jabber_server + +def print_jabber(): + print get_jabber() + +def set_jabber(server): + """Set the jabber server + server : e.g. 'olpc.collabora.co.uk' + """ + pro = profile.get_profile() + pro.jabber_server = server + pro.jabber_registered = False + pro.save() + return 1 + +def get_radio(): + bus = dbus.SystemBus() + proxy = bus.get_object(NM_SERVICE_NAME, NM_SERVICE_PATH) + nm = dbus.Interface(proxy, NM_SERVICE_IFACE) + state = nm.getWirelessEnabled() + if state in (0, 1): + return state + else: + raise ReadError(_('State is unknown.')) + +def print_radio(): + print ('off', 'on')[get_radio()] + +def set_radio(state): + """Turn Radio 'on' or 'off' + state : 'on/off' + """ + if state == 'on' or state == 1: + bus = dbus.SystemBus() + proxy = bus.get_object(NM_SERVICE_NAME, NM_SERVICE_PATH) + nm = dbus.Interface(proxy, NM_SERVICE_IFACE) + nm.setWirelessEnabled(True) + elif state == 'off' or state == 0: + bus = dbus.SystemBus() + proxy = bus.get_object(NM_SERVICE_NAME, NM_SERVICE_PATH) + nm = dbus.Interface(proxy, NM_SERVICE_IFACE) + nm.setWirelessEnabled(False) + else: + raise ValueError(_("Error in specified radio argument use on/off.")) + + return 0 + +def clear_registration(): + """Clear the registration with the schoolserver + """ + pro = profile.get_profile() + pro.backup1 = None + pro.save() + return 1 + +def clear_networks(): + """Clear saved passwords and network configurations. + """ + network_manager = hardwaremanager.get_network_manager() + if not network_manager: + return + network_manager.nminfo.delete_all_networks() + return 1 diff --git a/extensions/cpsection/power/model.py b/src/controlpanel/model/power.py index c76035d..bcf84f3 100644 --- a/extensions/cpsection/power/model.py +++ b/src/controlpanel/model/power.py @@ -16,14 +16,16 @@ # from gettext import gettext as _ -import gconf +from sugar import profile import dbus OHM_SERVICE_NAME = 'org.freedesktop.ohm' OHM_SERVICE_PATH = '/org/freedesktop/ohm/Keystore' OHM_SERVICE_IFACE = 'org.freedesktop.ohm.Keystore' +KEYWORDS = ['automatic', 'extreme', 'power', 'suspend', 'battery'] + class ReadError(Exception): def __init__(self, value): self.value = value @@ -31,8 +33,9 @@ class ReadError(Exception): return repr(self.value) def get_automatic_pm(): - client = gconf.client_get_default() - return client.get_bool('/desktop/sugar/power/automatic') + pro = profile.get_profile() + ret = pro.automatic_pm + return ret def print_automatic_pm(): print ('off', 'on')[get_automatic_pm()] @@ -53,13 +56,15 @@ def set_automatic_pm(enabled): else: raise ValueError(_("Error in automatic pm argument, use on/off.")) - client = gconf.client_get_default() - client.set_bool('/desktop/sugar/power/automatic', enabled) + pro = profile.get_profile() + pro.automatic_pm = enabled + pro.save() return 0 def get_extreme_pm(): - client = gconf.client_get_default() - return client.get_bool('/desktop/sugar/power/extreme') + pro = profile.get_profile() + ret = pro.extreme_pm + return ret def print_extreme_pm(): print ('off', 'on')[get_extreme_pm()] @@ -80,6 +85,7 @@ def set_extreme_pm(enabled): else: raise ValueError(_("Error in extreme pm argument, use on/off.")) - client = gconf.client_get_default() - client.set_bool('/desktop/sugar/power/extreme', enabled) + pro = profile.get_profile() + pro.extreme_pm = enabled + pro.save() return 0 diff --git a/src/jarabe/controlpanel/sectionview.py b/src/controlpanel/sectionview.py index 7b76aa1..7b76aa1 100644 --- a/src/jarabe/controlpanel/sectionview.py +++ b/src/controlpanel/sectionview.py diff --git a/src/jarabe/controlpanel/toolbar.py b/src/controlpanel/toolbar.py index 6bb8328..6bb8328 100644 --- a/src/jarabe/controlpanel/toolbar.py +++ b/src/controlpanel/toolbar.py diff --git a/src/controlpanel/view/Makefile.am b/src/controlpanel/view/Makefile.am new file mode 100644 index 0000000..a4d2a53 --- /dev/null +++ b/src/controlpanel/view/Makefile.am @@ -0,0 +1,16 @@ +sugardir = $(pkgdatadir)/shell/controlpanel/view +sugar_PYTHON = \ + __init__.py \ + aboutme.py \ + aboutxo.py \ + datetime.py \ + frame.py \ + language.py \ + network.py \ + power.py + + + + + + diff --git a/extensions/cpsection/power/Makefile.in b/src/controlpanel/view/Makefile.in index 9b2ea7d..8787134 100644 --- a/extensions/cpsection/power/Makefile.in +++ b/src/controlpanel/view/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = extensions/cpsection/power +subdir = src/controlpanel/view DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,11 +189,16 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/power +sugardir = $(pkgdatadir)/shell/controlpanel/view sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py + __init__.py \ + aboutme.py \ + aboutxo.py \ + datetime.py \ + frame.py \ + language.py \ + network.py \ + power.py all: all-am @@ -210,9 +212,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/power/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/controlpanel/view/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/power/Makefile + $(AUTOMAKE) --foreign src/controlpanel/view/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/jarabe/view/__init__.py b/src/controlpanel/view/__init__.py index a9dd95a..2b0f269 100644 --- a/src/jarabe/view/__init__.py +++ b/src/controlpanel/view/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2006-2007, Red Hat, Inc. +# 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 @@ -13,4 +13,5 @@ # 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/extensions/cpsection/aboutme/view.py b/src/controlpanel/view/aboutme.py index cabd66a..a871871 100644 --- a/extensions/cpsection/aboutme/view.py +++ b/src/controlpanel/view/aboutme.py @@ -21,9 +21,15 @@ from gettext import gettext as _ from sugar.graphics.icon import Icon from sugar.graphics import style from sugar.graphics.xocolor import XoColor +from sugar import profile -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert +from controlpanel.sectionview import SectionView +from controlpanel.inlinealert import InlineAlert + +CLASS = 'AboutMe' +ICON = 'module-about_me' +COLOR = profile.get_color() +TITLE = _('About Me') class EventIcon(gtk.EventBox): __gtype_name__ = "SugarEventIcon" @@ -43,7 +49,7 @@ class ColorPicker(EventIcon): __gsignals__ = { 'color-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([str])) + ([object])) } def __init__(self, xocolor=None): EventIcon.__init__(self) @@ -58,7 +64,7 @@ class ColorPicker(EventIcon): def _set_random_colors(self): xocolor = XoColor() self.icon.props.xo_color = xocolor - self.emit('color-changed', xocolor.to_string()) + self.emit('color-changed', xocolor) class AboutMe(SectionView): def __init__(self, model, alerts): @@ -154,8 +160,7 @@ class AboutMe(SectionView): def setup(self): self._nick_entry.set_text(self._model.get_nick()) - color = XoColor(self._model.get_color_xo()) - self._color_picker.icon.props.xo_color = color + self._color_picker.icon.props.xo_color = self._model.get_color_xo() self._color_valid = True self._nick_valid = True @@ -193,12 +198,13 @@ class AboutMe(SectionView): self._model.set_nick(widget.get_text()) except ValueError, detail: self._nick_alert.props.msg = detail - self._nick_valid = False + self._nick_valid = False else: self._nick_alert.props.msg = self.restart_msg - self._nick_valid = True + self._nick_valid = True self.needs_restart = True self.restart_alerts.append('nick') + self._validate() self._nick_alert.show() return False @@ -212,4 +218,9 @@ class AboutMe(SectionView): self._validate() self._color_alert.show() - return False + + + + + + diff --git a/extensions/cpsection/aboutxo/view.py b/src/controlpanel/view/aboutxo.py index bd2f27f..4c1d299 100644 --- a/extensions/cpsection/aboutxo/view.py +++ b/src/controlpanel/view/aboutxo.py @@ -18,10 +18,14 @@ import gtk from gettext import gettext as _ -from jarabe import config +import config from sugar.graphics import style -from jarabe.controlpanel.sectionview import SectionView +from controlpanel.sectionview import SectionView + +CLASS = 'AboutXO' +ICON = 'module-about_my_xo' +TITLE = _('About my XO') class AboutXO(SectionView): def __init__(self, model, alerts=None): @@ -137,21 +141,6 @@ class AboutXO(SectionView): box_software.pack_start(box_firmware, expand=False) box_firmware.show() - box_wireless_fw = gtk.HBox(spacing=style.DEFAULT_SPACING) - label_wireless_fw = gtk.Label(_('Wireless Firmware:')) - label_wireless_fw.set_alignment(1, 0) - label_wireless_fw.modify_fg(gtk.STATE_NORMAL, - style.COLOR_SELECTION_GREY.get_gdk_color()) - box_wireless_fw.pack_start(label_wireless_fw, expand=False) - self._group.add_widget(label_wireless_fw) - label_wireless_fw.show() - label_wireless_fw_no = gtk.Label(self._model.get_wireless_firmware()) - label_wireless_fw_no.set_alignment(0, 0) - box_wireless_fw.pack_start(label_wireless_fw_no, expand=False) - label_wireless_fw_no.show() - box_software.pack_start(box_wireless_fw, expand=False) - box_wireless_fw.show() - self._vbox.pack_start(box_software, expand=False) box_software.show() diff --git a/extensions/cpsection/datetime/view.py b/src/controlpanel/view/datetime.py index 58719b4..f178515 100644 --- a/extensions/cpsection/datetime/view.py +++ b/src/controlpanel/view/datetime.py @@ -21,8 +21,12 @@ from gettext import gettext as _ from sugar.graphics import style from sugar.graphics import iconentry -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert +from controlpanel.sectionview import SectionView +from controlpanel.inlinealert import InlineAlert + +CLASS = 'TimeZone' +ICON = 'module-date_and_time' +TITLE = _('Date & Time') class TimeZone(SectionView): def __init__(self, model, alerts): diff --git a/extensions/cpsection/frame/view.py b/src/controlpanel/view/frame.py index cbe43bb..09b973e 100644 --- a/extensions/cpsection/frame/view.py +++ b/src/controlpanel/view/frame.py @@ -20,13 +20,17 @@ from gettext import gettext as _ from sugar.graphics import style -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert +from controlpanel.sectionview import SectionView +from controlpanel.inlinealert import InlineAlert + +CLASS = 'Frame' +ICON = 'module-frame' +TITLE = _('Frame') _never = _('never') _instantaneous = _('instantaneous') _seconds_label = _('%s seconds') -_MAX_DELAY = 1000 +_MAX_DELAY = 1000.0 class Frame(SectionView): def __init__(self, model, alerts): @@ -193,7 +197,7 @@ class Frame(SectionView): def __corner_delay_format_cb(self, scale, value): if value == _MAX_DELAY: return _never - elif value == 0: + elif value == 0.0: return _instantaneous else: return _seconds_label % (value / _MAX_DELAY) @@ -226,7 +230,7 @@ class Frame(SectionView): def __edge_delay_format_cb(self, scale, value): if value == _MAX_DELAY: return _never - elif value == 0: + elif value == 0.0: return _instantaneous else: return _seconds_label % (value / _MAX_DELAY) diff --git a/extensions/cpsection/datetime/view.py b/src/controlpanel/view/language.py index 58719b4..db2042e 100644 --- a/extensions/cpsection/datetime/view.py +++ b/src/controlpanel/view/language.py @@ -21,16 +21,20 @@ from gettext import gettext as _ from sugar.graphics import style from sugar.graphics import iconentry -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert +from controlpanel.sectionview import SectionView +from controlpanel.inlinealert import InlineAlert -class TimeZone(SectionView): +CLASS = 'Language' +ICON = 'module-language' +TITLE = _('Language') + +class Language(SectionView): def __init__(self, model, alerts): SectionView.__init__(self) self._model = model self.restart_alerts = alerts - self._zone_sid = 0 + self._lang_sid = 0 self._cursor_change_handler = None self.set_border_width(style.DEFAULT_SPACING * 2) @@ -47,64 +51,68 @@ class TimeZone(SectionView): self._entry.modify_base(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color()) self.pack_start(self._entry, False) - self._entry.show() + self._entry.show() self._scrolled_window = gtk.ScrolledWindow() self._scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) self._scrolled_window.set_shadow_type(gtk.SHADOW_IN) - self._store = gtk.ListStore(gobject.TYPE_STRING) - zones = model.read_all_timezones() - for zone in zones: - self._store.append([zone]) + self._store = gtk.ListStore(gobject.TYPE_STRING, + gobject.TYPE_STRING) + locales = model.read_all_languages() + for locale in locales: + self._store.append([locale[2], '%s (%s)' % + (locale[0], locale[1])]) self._treeview = gtk.TreeView(self._store) self._treeview.set_search_entry(self._entry) self._treeview.set_search_equal_func(self._search) - self._treeview.set_search_column(0) + self._treeview.set_search_column(1) self._scrolled_window.add(self._treeview) self._treeview.show() - self._timezone_column = gtk.TreeViewColumn(_('Timezone')) + self._language_column = gtk.TreeViewColumn(_('Language')) self._cell = gtk.CellRendererText() - self._timezone_column.pack_start(self._cell, True) - self._timezone_column.add_attribute(self._cell, 'text', 0) - self._timezone_column.set_sort_column_id(0) - self._treeview.append_column(self._timezone_column) + self._language_column.pack_start(self._cell, True) + self._language_column.add_attribute(self._cell, 'text', 1) + self._language_column.set_sort_column_id(1) + self._treeview.append_column(self._language_column) self.pack_start(self._scrolled_window) self._scrolled_window.show() - self._zone_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING) - self.pack_start(self._zone_alert_box, False) + self._lang_alert_box = gtk.HBox(spacing=style.DEFAULT_SPACING) + self.pack_start(self._lang_alert_box, False) - self._zone_alert = InlineAlert() - self._zone_alert_box.pack_start(self._zone_alert) - if 'zone' in self.restart_alerts: - self._zone_alert.props.msg = self.restart_msg - self._zone_alert.show() - self._zone_alert_box.show() + self._lang_alert = InlineAlert() + self._lang_alert_box.pack_start(self._lang_alert) + if 'lang' in self.restart_alerts: + self._lang_alert.props.msg = self.restart_msg + self._lang_alert.show() + self._lang_alert_box.show() self.setup() def setup(self): - zone = self._model.get_timezone() + lang_code = self._model.get_language() for row in self._store: - if zone == row[0]: - self._treeview.set_cursor(row.path, self._timezone_column, + lang = lang_code.split('.')[0] + lang_column = row[0].split('.')[0] + if lang in lang_column: + self._treeview.set_cursor(row.path, self._language_column, False) - self._treeview.scroll_to_cell(row.path, self._timezone_column, - True, 0.5, 0.5) + self._treeview.scroll_to_cell(row.path, self._language_column, + True, 0.5, 0.5) break self.needs_restart = False self._cursor_change_handler = self._treeview.connect( \ - "cursor-changed", self.__zone_changed_cd) + "cursor-changed", self.__lang_changed_cd) def undo(self): self._treeview.disconnect(self._cursor_change_handler) self._model.undo() - self._zone_alert.hide() + self._lang_alert.hide() def __realize_cb(self, widget): self._entry.grab_focus() @@ -115,24 +123,24 @@ class TimeZone(SectionView): return False return True - def __zone_changed_cd(self, treeview, data=None): - list_, row = treeview.get_selection().get_selected() - if not row: + def __lang_changed_cd(self, treeview, data=None): + row = treeview.get_selection().get_selected() + if not row[1]: return False - if self._model.get_timezone() == self._store.get_value(row, 0): + if self._model.get_language() == self._store.get_value(row[1], 0): return False - - if self._zone_sid: - gobject.source_remove(self._zone_sid) - self._zone_sid = gobject.timeout_add(self._APPLY_TIMEOUT, - self.__zone_timeout_cb, row) - return True - def __zone_timeout_cb(self, row): - self._zone_sid = 0 - self._model.set_timezone(self._store.get_value(row, 0)) - self.restart_alerts.append('zone') + if self._lang_sid: + gobject.source_remove(self._lang_sid) + self._lang_sid = gobject.timeout_add(self._APPLY_TIMEOUT, + self.__lang_timeout_cb, + self._store.get_value(row[1], 0)) + + def __lang_timeout_cb(self, code): + self._lang_sid = 0 + self._model.set_language(code) + self.restart_alerts.append('lang') self.needs_restart = True - self._zone_alert.props.msg = self.restart_msg - self._zone_alert.show() + self._lang_alert.props.msg = self.restart_msg + self._lang_alert.show() return False diff --git a/extensions/cpsection/network/view.py b/src/controlpanel/view/network.py index 9a7f387..2b19656 100644 --- a/extensions/cpsection/network/view.py +++ b/src/controlpanel/view/network.py @@ -20,8 +20,8 @@ from gettext import gettext as _ from sugar.graphics import style -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert +from controlpanel.sectionview import SectionView +from controlpanel.inlinealert import InlineAlert CLASS = 'Network' ICON = 'module-network' @@ -59,7 +59,7 @@ class Network(SectionView): box_wireless.set_border_width(style.DEFAULT_SPACING * 2) box_wireless.set_spacing(style.DEFAULT_SPACING) - radio_info = gtk.Label(_("Turn off the wireless radio to save " + radio_info = gtk.Label(_("Turn of the wireless radio to save " "battery life")) radio_info.set_alignment(0, 0) radio_info.set_line_wrap(True) @@ -110,7 +110,7 @@ class Network(SectionView): self.pack_start(separator_mesh, False) separator_mesh.show() - label_mesh = gtk.Label(_('Collaboration')) + label_mesh = gtk.Label(_('Mesh')) label_mesh.set_alignment(0, 0) self.pack_start(label_mesh, expand=False) label_mesh.show() @@ -118,15 +118,6 @@ class Network(SectionView): box_mesh.set_border_width(style.DEFAULT_SPACING * 2) box_mesh.set_spacing(style.DEFAULT_SPACING) - server_info = gtk.Label(_("The server is the equivalent of what" - " room you are in; people on the same server" - " will be able to see each other, even when" - " they aren't on the same network.")) - server_info.set_alignment(0, 0) - server_info.set_line_wrap(True) - box_mesh.pack_start(server_info, expand=False) - server_info.show() - box_server = gtk.HBox(spacing=style.DEFAULT_SPACING) label_server = gtk.Label(_('Server:')) label_server.set_alignment(1, 0.5) diff --git a/extensions/cpsection/power/view.py b/src/controlpanel/view/power.py index 8f1ed56..f4d817b 100644 --- a/extensions/cpsection/power/view.py +++ b/src/controlpanel/view/power.py @@ -19,8 +19,12 @@ from gettext import gettext as _ from sugar.graphics import style -from jarabe.controlpanel.sectionview import SectionView -from jarabe.controlpanel.inlinealert import InlineAlert +from controlpanel.sectionview import SectionView +from controlpanel.inlinealert import InlineAlert + +CLASS = 'Power' +ICON = 'module-power' +TITLE = _('Power') class Power(SectionView): def __init__(self, model, alerts): @@ -82,8 +86,7 @@ class Power(SectionView): box_extreme_pm = gtk.HBox(spacing=style.DEFAULT_SPACING) label_extreme_pm = gtk.Label( - _('Extreme power management (disables' \ - 'wireless radio, increases battery life)')) + _('Extreme power management (disables wireless radio, increases battery life)')) label_extreme_pm.set_alignment(0, 0.5) self._extreme_button = gtk.CheckButton() self._extreme_button.set_alignment(0, 0) diff --git a/src/emulator.py b/src/emulator.py new file mode 100755 index 0000000..39acd2b --- /dev/null +++ b/src/emulator.py @@ -0,0 +1,147 @@ +# Copyright (C) 2006, Red Hat, Inc. +# +# 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 + +import os +import sys +import socket +import logging +from optparse import OptionParser + +log = logging.getLogger( 'sugar-emulator' ) +log.setLevel( logging.DEBUG ) + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +from sugar import env + +def _get_display_number(): + """Find a free display number trying to connect to 6000+ ports""" + log.info("Attempting to find free port for X11 (Xephyr)") + retries = 20 + display_number = 1 + display_is_free = False + + while not display_is_free and retries > 0: + lockstr = "/tmp/.X%d-lock" % display_number + if not os.path.exists(lockstr): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect(('127.0.0.1', 6000 + display_number)) + s.close() + except socket.error: + display_is_free = True + break + + display_number += 1 + retries -= 1 + + if display_is_free: + log.info( + ' Found free port: #%s (%s)', + display_number, display_number+6000 + ) + return display_number + else: + logging.error('Cannot find a free display.') + sys.exit(0) + +def _start_xephyr(dpi=None): + display = _get_display_number() + log.info('Starting the Xephyr nested X display on display %s', display) + + cmd = [ 'Xephyr' ] + cmd.append(':%d' % display) + cmd.append('-ac') + + if gtk.gdk.screen_width() < 1200 or gtk.gdk.screen_height() < 900: + cmd.append('-fullscreen') + else: + cmd.append('-screen') + cmd.append('%dx%d' % (1200, 900)) + + if not dpi: + dpi = gtk.settings_get_default().get_property('gtk-xft-dpi') / 1024 + if dpi > 0: + cmd.append('-dpi') + cmd.append('%d' % dpi) + + log.debug('Xephyr command: %s', " ".join( cmd )) + result = gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) + pid = result[0] + + os.environ['DISPLAY'] = ":%d" % (display) + os.environ['SUGAR_EMULATOR_PID'] = str(pid) + +def _start_matchbox(): + log.info('Starting the matchbox window manager') + cmd = ['matchbox-window-manager'] + + cmd.extend(['-use_titlebar', 'no']) + cmd.extend(['-theme', 'sugar']) + + log.debug('Matchbox command: %s', " ".join( cmd)) + gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) + +def _setup_env(): + os.environ['SUGAR_EMULATOR'] = 'yes' + os.environ['GABBLE_LOGFILE'] = os.path.join( + env.get_profile_path(), 'logs', 'telepathy-gabble.log') + os.environ['SALUT_LOGFILE'] = os.path.join( + env.get_profile_path(), 'logs', 'telepathy-salut.log') + os.environ['STREAM_ENGINE_LOGFILE'] = os.path.join( + env.get_profile_path(), 'logs', 'telepathy-stream-engine.log') + +def main(): + """Script-level operations""" + + parser = OptionParser() + parser.add_option('-x', '--xo-style', dest='xo_style', + action='store_true', help='use the XO style') + (options, args) = parser.parse_args() + + logging.basicConfig() + + _setup_env() + + if options.xo_style: + _start_xephyr(dpi=201) + else: + _start_xephyr() + + if options.xo_style: + os.environ['SUGAR_THEME'] = 'sugar-xo' + os.environ['SUGAR_XO_STYLE'] = 'yes' + else: + os.environ['SUGAR_XO_STYLE'] = 'no' + + command = ['dbus-launch', 'dbus-launch', '--exit-with-session'] + + if not args: + command.append('sugar-shell') + else: + _start_matchbox() + + if args[0].endswith('.py'): + command.append('python') + + command.append(args[0]) + + log.info("Attempting to launch sugar to replace this process: %s" + % " ".join(command)) + os.execlp( *command ) diff --git a/src/hardware/Makefile.am b/src/hardware/Makefile.am new file mode 100644 index 0000000..8cd9c77 --- /dev/null +++ b/src/hardware/Makefile.am @@ -0,0 +1,13 @@ +sugardir = $(pkgdatadir)/shell/hardware +sugar_PYTHON = \ + __init__.py \ + hardwaremanager.py \ + keydialog.py \ + nmclient.py \ + nminfo.py \ + schoolserver.py + +dbusservicedir = $(sysconfdir)/dbus-1/system.d/ +dbusservice_DATA = NetworkManagerInfo.conf + +EXTRA_DIST = $(dbusservice_DATA) diff --git a/src/jarabe/journal/Makefile.in b/src/hardware/Makefile.in index f838b24..df3dc24 100644 --- a/src/jarabe/journal/Makefile.in +++ b/src/hardware/Makefile.in @@ -13,6 +13,7 @@ # PARTICULAR PURPOSE. @SET_MAKE@ + VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ @@ -29,7 +30,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/journal +subdir = src/hardware DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -46,9 +47,12 @@ am__vpath_adj = case $$p in \ *) f=$$p;; \ esac; am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" +am__installdirs = "$(DESTDIR)$(sugardir)" \ + "$(DESTDIR)$(dbusservicedir)" sugarPYTHON_INSTALL = $(INSTALL_DATA) py_compile = $(top_srcdir)/py-compile +dbusserviceDATA_INSTALL = $(INSTALL_DATA) +DATA = $(dbusservice_DATA) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ @@ -73,9 +77,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,24 +193,18 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/journal +sugardir = $(pkgdatadir)/shell/hardware sugar_PYTHON = \ __init__.py \ - collapsedentry.py \ - detailview.py \ - expandedentry.py \ - journalactivity.py \ - journalentrybundle.py \ - journaltoolbox.py \ - keepicon.py \ - listview.py \ - misc.py \ - modalalert.py \ - objectchooser.py \ - palettes.py \ - query.py \ - volumestoolbar.py - + hardwaremanager.py \ + keydialog.py \ + nmclient.py \ + nminfo.py \ + schoolserver.py + +dbusservicedir = $(sysconfdir)/dbus-1/system.d/ +dbusservice_DATA = NetworkManagerInfo.conf +EXTRA_DIST = $(dbusservice_DATA) all: all-am .SUFFIXES: @@ -222,9 +217,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/journal/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/hardware/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/journal/Makefile + $(AUTOMAKE) --foreign src/hardware/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -270,6 +265,23 @@ uninstall-sugarPYTHON: rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ done +install-dbusserviceDATA: $(dbusservice_DATA) + @$(NORMAL_INSTALL) + test -z "$(dbusservicedir)" || $(MKDIR_P) "$(DESTDIR)$(dbusservicedir)" + @list='$(dbusservice_DATA)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(dbusserviceDATA_INSTALL) '$$d$$p' '$(DESTDIR)$(dbusservicedir)/$$f'"; \ + $(dbusserviceDATA_INSTALL) "$$d$$p" "$(DESTDIR)$(dbusservicedir)/$$f"; \ + done + +uninstall-dbusserviceDATA: + @$(NORMAL_UNINSTALL) + @list='$(dbusservice_DATA)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(dbusservicedir)/$$f'"; \ + rm -f "$(DESTDIR)$(dbusservicedir)/$$f"; \ + done tags: TAGS TAGS: @@ -305,9 +317,9 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile +all-am: Makefile $(DATA) installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ + for dir in "$(DESTDIR)$(sugardir)" "$(DESTDIR)$(dbusservicedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-am @@ -352,7 +364,7 @@ info: info-am info-am: -install-data-am: install-sugarPYTHON +install-data-am: install-dbusserviceDATA install-sugarPYTHON install-dvi: install-dvi-am @@ -386,20 +398,21 @@ ps: ps-am ps-am: -uninstall-am: uninstall-sugarPYTHON +uninstall-am: uninstall-dbusserviceDATA uninstall-sugarPYTHON .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic distclean \ distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON + install install-am install-data install-data-am \ + install-dbusserviceDATA install-dvi install-dvi-am \ + install-exec install-exec-am install-html install-html-am \ + install-info install-info-am install-man install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + install-sugarPYTHON installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am \ + uninstall-dbusserviceDATA uninstall-sugarPYTHON # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/hardware/NetworkManagerInfo.conf b/src/hardware/NetworkManagerInfo.conf new file mode 100644 index 0000000..4fb8270 --- /dev/null +++ b/src/hardware/NetworkManagerInfo.conf @@ -0,0 +1,26 @@ +<!DOCTYPE busconfig PUBLIC + "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <policy user="root"> + <allow own="org.freedesktop.NetworkManagerInfo"/> + + <allow send_destination="org.freedesktop.NetworkManagerInfo"/> + <allow send_interface="org.freedesktop.NetworkManagerInfo"/> + </policy> + <policy at_console="true"> + <allow own="org.freedesktop.NetworkManagerInfo"/> + + <allow send_destination="org.freedesktop.NetworkManagerInfo"/> + <allow send_interface="org.freedesktop.NetworkManagerInfo"/> + </policy> + <policy context="default"> + <deny own="org.freedesktop.NetworkManagerInfo"/> + + <deny send_destination="org.freedesktop.NetworkManagerInfo"/> + <deny send_interface="org.freedesktop.NetworkManagerInfo"/> + </policy> + + <limit name="max_replies_per_connection">512</limit> +</busconfig> + diff --git a/src/jarabe/desktop/__init__.py b/src/hardware/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/desktop/__init__.py +++ b/src/hardware/__init__.py diff --git a/src/hardware/hardwaremanager.py b/src/hardware/hardwaremanager.py new file mode 100644 index 0000000..c4f9f75 --- /dev/null +++ b/src/hardware/hardwaremanager.py @@ -0,0 +1,123 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import logging + +import dbus +import gobject + +from hardware.nmclient import NMClient +from sugar.profile import get_profile +from sugar import env +from sugar import _sugarext + +_HARDWARE_MANAGER_INTERFACE = 'org.freedesktop.ohm.Keystore' +_HARDWARE_MANAGER_SERVICE = 'org.freedesktop.ohm' +_HARDWARE_MANAGER_OBJECT_PATH = '/org/freedesktop/ohm/Keystore' + +COLOR_MODE = 0 +B_AND_W_MODE = 1 + +VOL_CHANGE_INCREMENT_RECOMMENDATION = 10 + +class HardwareManager(gobject.GObject): + __gsignals__ = { + 'muted-changed' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN])), + 'volume-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_INT, gobject.TYPE_INT])), + } + + def __init__(self): + gobject.GObject.__init__(self) + + bus = dbus.SystemBus() + proxy = bus.get_object(_HARDWARE_MANAGER_SERVICE, + _HARDWARE_MANAGER_OBJECT_PATH, + follow_name_owner_changes=True) + self._service = dbus.Interface(proxy, _HARDWARE_MANAGER_INTERFACE) + + self._volume = _sugarext.VolumeAlsa() + + def get_muted(self): + return self._volume.get_mute() + + def get_volume(self): + return self._volume.get_volume() + + def set_volume(self, new_volume): + old_volume = self._volume.get_volume() + self._volume.set_volume(new_volume) + + self.emit('volume-changed', old_volume, new_volume) + + def set_muted(self, new_state): + old_state = self._volume.get_mute() + self._volume.set_mute(new_state) + + self.emit('muted-changed', old_state, new_state) + + def startup(self): + if env.is_emulator() is False: + profile = get_profile() + self.set_volume(profile.sound_volume) + + def shutdown(self): + if env.is_emulator() is False: + profile = get_profile() + profile.sound_volume = self.get_volume() + profile.save() + + def set_dcon_freeze(self, frozen): + try: + self._service.SetKey("display.dcon_freeze", frozen) + except dbus.DBusException: + logging.error('Cannot unfreeze the DCON') + + def set_display_mode(self, mode): + try: + self._service.SetKey("display.dcon_mode", mode) + except dbus.DBusException: + logging.error('Cannot change DCON mode') + + def set_display_brightness(self, level): + try: + self._service.SetKey("backlight.hardware_brightness", level) + except dbus.DBusException: + logging.error('Cannot set display brightness') + + def get_display_brightness(self): + try: + return self._service.GetKey("backlight.hardware_brightness") + except dbus.DBusException: + logging.error('Cannot get display brightness') + return 0 + +def get_manager(): + return _manager + +def get_network_manager(): + return _network_manager + +_manager = HardwareManager() + +try: + _network_manager = NMClient() +except dbus.DBusException, e: + _network_manager = None + logging.info('Network manager service not found.') diff --git a/src/jarabe/desktop/keydialog.py b/src/hardware/keydialog.py index f5995e6..92f6776 100644 --- a/src/jarabe/desktop/keydialog.py +++ b/src/hardware/keydialog.py @@ -1,3 +1,5 @@ +# vi: ts=4 ai noet +# # Copyright (C) 2006-2007 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify @@ -18,13 +20,35 @@ import md5 from gettext import gettext as _ import gtk -import dbus - -from jarabe.model import network -from jarabe.model.network import Secrets -IW_AUTH_ALG_OPEN_SYSTEM = 'open' -IW_AUTH_ALG_SHARED_KEY = 'shared' +IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001 +IW_AUTH_ALG_SHARED_KEY = 0x00000002 + +IW_AUTH_WPA_VERSION_DISABLED = 0x00000001 +IW_AUTH_WPA_VERSION_WPA = 0x00000002 +IW_AUTH_WPA_VERSION_WPA2 = 0x00000004 + +NM_802_11_CAP_NONE = 0x00000000 +NM_802_11_CAP_PROTO_NONE = 0x00000001 +NM_802_11_CAP_PROTO_WEP = 0x00000002 +NM_802_11_CAP_PROTO_WPA = 0x00000004 +NM_802_11_CAP_PROTO_WPA2 = 0x00000008 +NM_802_11_CAP_KEY_MGMT_PSK = 0x00000040 +NM_802_11_CAP_KEY_MGMT_802_1X = 0x00000080 +NM_802_11_CAP_CIPHER_WEP40 = 0x00001000 +NM_802_11_CAP_CIPHER_WEP104 = 0x00002000 +NM_802_11_CAP_CIPHER_TKIP = 0x00004000 +NM_802_11_CAP_CIPHER_CCMP = 0x00008000 + +NM_AUTH_TYPE_WPA_PSK_AUTO = 0x00000000 +IW_AUTH_CIPHER_NONE = 0x00000001 +IW_AUTH_CIPHER_WEP40 = 0x00000002 +IW_AUTH_CIPHER_TKIP = 0x00000004 +IW_AUTH_CIPHER_CCMP = 0x00000008 +IW_AUTH_CIPHER_WEP104 = 0x00000010 + +IW_AUTH_KEY_MGMT_802_1X = 0x1 +IW_AUTH_KEY_MGMT_PSK = 0x2 def string_is_hex(key): is_hex = True @@ -56,28 +80,20 @@ def hash_passphrase(passphrase): passphrase = md5.new(passphrase).digest() return string_to_hex(passphrase)[:26] -class CanceledKeyRequestError(dbus.DBusException): - def __init__(self): - dbus.DBusException.__init__(self) - self._dbus_error_name = network.NM_SETTINGS_IFACE + '.CanceledError' - class KeyDialog(gtk.Dialog): - def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): + def __init__(self, net, async_cb, async_err_cb): gtk.Dialog.__init__(self, flags=gtk.DIALOG_MODAL) self.set_title("Wireless Key Required") - self._response = response + self._net = net + self._async_cb = async_cb + self._async_err_cb = async_err_cb self._entry = None - self._ssid = ssid - self._flags = flags - self._wpa_flags = wpa_flags - self._rsn_flags = rsn_flags - self._dev_caps = dev_caps self.set_has_separator(False) label = gtk.Label("A wireless encryption key is required for\n" \ - " the wireless network '%s'." % self._ssid) + " the wireless network '%s'." % net.get_ssid()) self.vbox.pack_start(label) self.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, @@ -87,6 +103,7 @@ class KeyDialog(gtk.Dialog): def add_key_entry(self): self._entry = gtk.Entry() + #self._entry.props.visibility = False self._entry.connect('changed', self._update_response_sensitivity) self._entry.connect('activate', self._entry_activate_cb) self.vbox.pack_start(self._entry) @@ -102,17 +119,19 @@ class KeyDialog(gtk.Dialog): def create_security(self): raise NotImplementedError - def get_response_object(self): - return self._response + def get_network(self): + return self._net + + def get_callbacks(self): + return (self._async_cb, self._async_err_cb) WEP_PASSPHRASE = 1 WEP_HEX = 2 WEP_ASCII = 3 class WEPKeyDialog(KeyDialog): - def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): - KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags, - dev_caps, response) + def __init__(self, net, async_cb, async_err_cb): + KeyDialog.__init__(self, net, async_cb, async_err_cb) # WEP key type self.key_store = gtk.ListStore(str, int) @@ -137,7 +156,7 @@ class WEPKeyDialog(KeyDialog): self.add_key_entry() # WEP authentication mode - self.auth_store = gtk.ListStore(str, str) + self.auth_store = gtk.ListStore(str, int) self.auth_store.append(["Open System", IW_AUTH_ALG_OPEN_SYSTEM]) self.auth_store.append(["Shared Key", IW_AUTH_ALG_SHARED_KEY]) @@ -171,19 +190,24 @@ class WEPKeyDialog(KeyDialog): it = self.auth_combo.get_active_iter() (auth_alg, ) = self.auth_store.get(it, 1) - return (key, auth_alg) + we_cipher = None + if len(key) == 26: + we_cipher = IW_AUTH_CIPHER_WEP104 + elif len(key) == 10: + we_cipher = IW_AUTH_CIPHER_WEP40 + + return (we_cipher, key, auth_alg) def print_security(self): - (key, auth_alg) = self._get_security() + (we_cipher, key, auth_alg) = self._get_security() + print "Cipher: %d" % we_cipher print "Key: %s" % key print "Auth: %d" % auth_alg def create_security(self): - (key, auth_alg) = self._get_security() - secrets = Secrets() - secrets.wep_key = key - secrets.auth_alg = auth_alg - return secrets + (we_cipher, key, auth_alg) = self._get_security() + from nminfo import Security + return Security.new_from_args(we_cipher, (key, auth_alg)) def _update_response_sensitivity(self, ignored=None): key = self._entry.get_text() @@ -206,13 +230,16 @@ class WEPKeyDialog(KeyDialog): self.set_response_sensitive(gtk.RESPONSE_OK, valid) class WPAKeyDialog(KeyDialog): - def __init__(self, ssid, flags, wpa_flags, rsn_flags, dev_caps, response): - KeyDialog.__init__(self, ssid, flags, wpa_flags, rsn_flags, - dev_caps, response) + def __init__(self, net, async_cb, async_err_cb): + KeyDialog.__init__(self, net, async_cb, async_err_cb) self.add_key_entry() - self.store = gtk.ListStore(str) - self.store.append([_("WPA & WPA2 Personal")]) + self.store = gtk.ListStore(str, int) + self.store.append(["Automatic", NM_AUTH_TYPE_WPA_PSK_AUTO]) + if net.get_caps() & NM_802_11_CAP_CIPHER_CCMP: + self.store.append(["AES-CCMP", IW_AUTH_CIPHER_CCMP]) + if net.get_caps() & NM_802_11_CAP_CIPHER_TKIP: + self.store.append(["TKIP", IW_AUTH_CIPHER_TKIP]) self.combo = gtk.ComboBox(self.store) cell = gtk.CellRendererText() @@ -221,14 +248,14 @@ class WPAKeyDialog(KeyDialog): self.combo.set_active(0) self.hbox = gtk.HBox() - self.hbox.pack_start(gtk.Label(_("Wireless Security:"))) + self.hbox.pack_start(gtk.Label(_("Encryption Type:"))) self.hbox.pack_start(self.combo) self.hbox.show_all() self.vbox.pack_start(self.hbox) def _get_security(self): - ssid = self._ssid + ssid = self.get_network().get_ssid() key = self._entry.get_text() is_hex = string_is_hex(key) @@ -238,29 +265,42 @@ class WPAKeyDialog(KeyDialog): real_key = key elif len(key) >= 8 and len(key) <= 63: # passphrase - from subprocess import Popen, PIPE - p = Popen(['/usr/sbin/wpa_passphrase', ssid, key], stdout=PIPE) - for line in p.stdout: + import commands + command = "/usr/sbin/wpa_passphrase '%s' '%s'" % (ssid, key) + (s, o) = commands.getstatusoutput(command) + if s != 0: + raise RuntimeError("Error hashing passphrase: %s" % o) + lines = o.split("\n") + for line in lines: if line.strip().startswith("psk="): real_key = line.strip()[4:] - if p.wait() != 0: - raise RuntimeError("Error hashing passphrase") if real_key and len(real_key) != 64: real_key = None if not real_key: raise RuntimeError("Invalid key") - return real_key + it = self.combo.get_active_iter() + (we_cipher, ) = self.store.get(it, 1) + + wpa_ver = IW_AUTH_WPA_VERSION_WPA + caps = self.get_network().get_caps() + if caps & NM_802_11_CAP_PROTO_WPA2: + wpa_ver = IW_AUTH_WPA_VERSION_WPA2 + + return (we_cipher, real_key, wpa_ver) def print_security(self): - key = self._get_security() + (we_cipher, key, wpa_ver) = self._get_security() + print "Cipher: %d" % we_cipher print "Key: %s" % key + print "WPA Ver: %d" % wpa_ver def create_security(self): - secrets = Secrets() - secrets.psk = self._get_security() - return secrets + (we_cipher, key, wpa_ver) = self._get_security() + from nminfo import Security + return Security.new_from_args(we_cipher, + (key, wpa_ver, IW_AUTH_KEY_MGMT_PSK)) def _update_response_sensitivity(self, ignored=None): key = self._entry.get_text() @@ -276,37 +316,41 @@ class WPAKeyDialog(KeyDialog): self.set_response_sensitive(gtk.RESPONSE_OK, valid) return False -def create(ssid, flags, wpa_flags, rsn_flags, dev_caps, response): - if wpa_flags == network.NM_802_11_AP_SEC_NONE and \ - rsn_flags == network.NM_802_11_AP_SEC_NONE: - key_dialog = WEPKeyDialog(ssid, flags, wpa_flags, rsn_flags, - dev_caps, response) +def new_key_dialog(net, async_cb, async_err_cb): + caps = net.get_caps() + if (caps & NM_802_11_CAP_CIPHER_TKIP or caps & NM_802_11_CAP_CIPHER_CCMP) \ + and (caps & NM_802_11_CAP_PROTO_WPA or \ + caps & NM_802_11_CAP_PROTO_WPA2): + return WPAKeyDialog(net, async_cb, async_err_cb) + elif (caps & NM_802_11_CAP_CIPHER_WEP40 or \ + caps & NM_802_11_CAP_CIPHER_WEP104) and \ + (caps & NM_802_11_CAP_PROTO_WEP): + return WEPKeyDialog(net, async_cb, async_err_cb) else: - key_dialog = WPAKeyDialog(ssid, flags, wpa_flags, rsn_flags, - dev_caps, response) + raise RuntimeError("Unhandled network capabilities %x" % caps) + - key_dialog.connect("response", _key_dialog_response_cb) - key_dialog.connect("destroy", _key_dialog_destroy_cb) - key_dialog.show_all() -def _key_dialog_destroy_cb(key_dialog, data=None): - _key_dialog_response_cb(key_dialog, gtk.RESPONSE_CANCEL) +class FakeNet(object): + def get_ssid(self): + return "olpcwpa" -def _key_dialog_response_cb(key_dialog, response_id): - response = key_dialog.get_response_object() - secrets = None + def get_caps(self): + return NM_802_11_CAP_CIPHER_CCMP | NM_802_11_CAP_CIPHER_TKIP | \ + NM_802_11_CAP_PROTO_WPA + +def response_cb(widget, response_id): if response_id == gtk.RESPONSE_OK: - secrets = key_dialog.create_security() - - if response_id in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_NONE]: - # key dialog dialog was canceled; send the error back to NM - response.set_error(CanceledKeyRequestError()) - elif response_id == gtk.RESPONSE_OK: - if not secrets: - raise RuntimeError("Invalid security arguments.") - response.set_secrets(secrets) + print dialog.print_security() else: - raise RuntimeError("Unhandled key dialog response %d" % response_id) + print "canceled" + widget.hide() + widget.destroy() + - key_dialog.destroy() +if __name__ == "__main__": + fake_net = FakeNet() + dialog = new_key_dialog(fake_net, None, None) + dialog.connect("response", response_cb) + dialog.run() diff --git a/src/hardware/nmclient.py b/src/hardware/nmclient.py new file mode 100644 index 0000000..c517391 --- /dev/null +++ b/src/hardware/nmclient.py @@ -0,0 +1,795 @@ +# +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import logging + +import dbus +import dbus.glib +import dbus.decorators +import gobject + +from hardware import nminfo +from sugar.graphics import xocolor + +IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001 +IW_AUTH_ALG_SHARED_KEY = 0x00000002 + +NM_DEVICE_STAGE_STRINGS = ("Unknown", + "Prepare", + "Config", + "Need Users Key", + "IP Config", + "IP Config Get", + "IP Config Commit", + "Activated", + "Failed", + "Canceled" + ) + +NM_SERVICE = 'org.freedesktop.NetworkManager' +NM_IFACE = 'org.freedesktop.NetworkManager' +NM_IFACE_DEVICES = 'org.freedesktop.NetworkManager.Devices' +NM_PATH = '/org/freedesktop/NetworkManager' + +DEVICE_TYPE_UNKNOWN = 0 +DEVICE_TYPE_802_3_ETHERNET = 1 +DEVICE_TYPE_802_11_WIRELESS = 2 +DEVICE_TYPE_802_11_MESH_OLPC = 3 + +NM_DEVICE_CAP_NONE = 0x00000000 +NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001 +NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002 +NM_DEVICE_CAP_WIRELESS_SCAN = 0x00000004 + +sys_bus = dbus.SystemBus() + +NM_802_11_CAP_NONE = 0x00000000 +NM_802_11_CAP_PROTO_NONE = 0x00000001 +NM_802_11_CAP_PROTO_WEP = 0x00000002 +NM_802_11_CAP_PROTO_WPA = 0x00000004 +NM_802_11_CAP_PROTO_WPA2 = 0x00000008 +NM_802_11_CAP_KEY_MGMT_PSK = 0x00000040 +NM_802_11_CAP_KEY_MGMT_802_1X = 0x00000080 +NM_802_11_CAP_CIPHER_WEP40 = 0x00001000 +NM_802_11_CAP_CIPHER_WEP104 = 0x00002000 +NM_802_11_CAP_CIPHER_TKIP = 0x00004000 +NM_802_11_CAP_CIPHER_CCMP = 0x00008000 + +NETWORK_STATE_CONNECTING = 0 +NETWORK_STATE_CONNECTED = 1 +NETWORK_STATE_NOTCONNECTED = 2 + +DEVICE_STATE_ACTIVATING = 0 +DEVICE_STATE_ACTIVATED = 1 +DEVICE_STATE_INACTIVE = 2 + +IW_MODE_ADHOC = 1 +IW_MODE_INFRA = 2 + +class Network(gobject.GObject): + __gsignals__ = { + 'initialized' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_BOOLEAN])), + 'strength-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'state-changed' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])) + } + + def __init__(self, client, op): + gobject.GObject.__init__(self) + self._client = client + self._op = op + self._ssid = None + self._mode = None + self._strength = 0 + self._caps = 0 + self._valid = False + self._favorite = False + self._state = NETWORK_STATE_NOTCONNECTED + + obj = sys_bus.get_object(NM_SERVICE, self._op) + net = dbus.Interface(obj, NM_IFACE_DEVICES) + net.getProperties(reply_handler=self._update_reply_cb, + error_handler=self._update_error_cb) + + def _update_reply_cb(self, *props): + self._ssid = props[1] + self._strength = props[3] + self._mode = props[6] + self._caps = props[7] + if self._caps & NM_802_11_CAP_PROTO_WPA or \ + self._caps & NM_802_11_CAP_PROTO_WPA2: + if not (self._caps & NM_802_11_CAP_KEY_MGMT_PSK): + # 802.1x is not supported at this time + logging.debug("Net(%s): ssid '%s' dropping because 802.1x" \ + "is unsupported" % (self._op, self._ssid)) + self._valid = False + self.emit('initialized', self._valid) + return + if self._mode != IW_MODE_INFRA: + # Don't show Ad-Hoc networks; they usually don't DHCP and therefore + # won't work well here. This also works around the bug where + # we show our own mesh SSID on the Mesh view when in mesh mode + logging.debug("Net(%s): ssid '%s' is adhoc; not showing" % + (self._op, self._ssid)) + self._valid = False + self.emit('initialized', self._valid) + return + + fav_nets = [] + if self._client.nminfo: + fav_nets = self._client.nminfo.get_networks( + nminfo.NETWORK_TYPE_ALLOWED) + if self._ssid in fav_nets: + self._favorite = True + + self._valid = True + logging.debug("Net(%s): caps 0x%X" % (self._ssid, self._caps)) + self.emit('initialized', self._valid) + + def _update_error_cb(self, err): + logging.debug("Net(%s): failed to update. (%s)" % (self._op, err)) + self._valid = False + self.emit('initialized', self._valid) + + def get_colors(self): + import sha + sh = sha.new() + data = self._ssid + hex(self._caps) + hex(self._mode) + sh.update(data) + h = hash(sh.digest()) + idx = h % len(xocolor.colors) + # stroke, fill + return (xocolor.colors[idx][0], xocolor.colors[idx][1]) + + def get_ssid(self): + return self._ssid + + def get_caps(self): + return self._caps + + def get_mode(self): + return self._mode + + def get_state(self): + return self._state + + def set_state(self, state): + if state == self._state: + return + self._state = state + if self._valid: + self.emit('state-changed') + + def get_op(self): + return self._op + + def get_strength(self): + return self._strength + + def set_strength(self, strength): + if strength == self._strength: + return + self._strength = strength + if self._valid: + self.emit('strength-changed') + + def is_valid(self): + return self._valid + + def is_favorite(self): + return self._favorite + +class Device(gobject.GObject): + __gsignals__ = { + 'initialized': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'init-failed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'ssid-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'strength-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'state-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'activation-stage-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + 'network-appeared': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'network-disappeared': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'ip-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])), + } + + def __init__(self, client, op): + gobject.GObject.__init__(self) + self._client = client + self._op = op + self._iface = None + self._type = DEVICE_TYPE_UNKNOWN + self._udi = None + self._active = False + self._act_stage = 0 + self._strength = 0 + self._freq = 0.0 + self._link = False + self._valid = False + self._networks = {} + self._caps = 0 + self._state = DEVICE_STATE_INACTIVE + self._active_network = None + self._active_net_sigid = 0 + self._ip_address = None + + obj = sys_bus.get_object(NM_SERVICE, self._op) + self.dev = dbus.Interface(obj, NM_IFACE_DEVICES) + self.dev.getProperties(reply_handler=self._update_reply_cb, + error_handler=self._update_error_cb) + + def _is_activating(self): + if self._active and self._act_stage >= 1 and self._act_stage <= 6: + return True + return False + + def _is_activated(self): + if self._active and self._act_stage == 7: + return True + return False + + # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2 + def _getproperties_for_ip_only_reply_cb(self, *props): + current_ip = props[6] + if current_ip != self._ip_address: + self._ip_address = current_ip + if self._valid: + self.emit('ip-changed') + + # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2 + def _getproperties_for_ip_only_error_cb(self, err): + logging.warning("Device(%s): failed to update. (%s)" % (self._op, err)) + + def _update_reply_cb(self, *props): + self._iface = props[1] + self._type = props[2] + self._udi = props[3] + self._active = props[4] + self._act_stage = props[5] + self._link = props[15] + self._caps = props[17] + + if self._type == DEVICE_TYPE_802_11_WIRELESS: + old_strength = self._strength + self._strength = props[14] + if self._strength != old_strength: + if self._valid: + self.emit('strength-changed') + self._update_networks(props[20], props[19]) + elif self._type == DEVICE_TYPE_802_11_MESH_OLPC: + old_strength = self._strength + self._strength = props[14] + if self._strength != old_strength: + if self._valid: + self.emit('strength-changed') + + self._valid = True + + # 6248: remove for NM0.7; http://dev.laptop.org/ticket/6248#comment:2 + if props[6] != self._ip_address: + self._ip_address = props[6] + self.emit('ip-changed') + + if self._is_activating(): + self.set_state(DEVICE_STATE_ACTIVATING) + elif self._is_activated(): + self.set_state(DEVICE_STATE_ACTIVATED) + else: + self.set_state(DEVICE_STATE_INACTIVE) + + self.emit('initialized') + + def _update_networks(self, net_ops, active_op): + for op in net_ops: + net = Network(self._client, op) + self._networks[op] = net + net.connect('initialized', lambda *args: + self._net_initialized_cb(active_op, *args)) + + def _update_error_cb(self, err): + logging.debug("Device(%s): failed to update. (%s)" % (self._op, err)) + self._valid = False + self.emit('init-failed') + + def _net_initialized_cb(self, active_op, net, valid): + net_op = net.get_op() + if not self._networks.has_key(net_op): + return + + if not valid: + # init failure + del self._networks[net_op] + return + + # init success + if self._valid: + self.emit('network-appeared', net) + if active_op and net_op == active_op: + self.set_active_network(net) + + def get_op(self): + return self._op + + def get_networks(self): + ret = [] + for net in self._networks.values(): + if net.is_valid(): + ret.append(net) + return ret + + def get_network(self, op): + if self._networks.has_key(op) and self._networks[op].is_valid(): + return self._networks[op] + return None + + def get_network_ops(self): + ret = [] + for net in self._networks.values(): + if net.is_valid(): + ret.append(net.get_op()) + return ret + + def get_mesh_step(self): + if self._type != DEVICE_TYPE_802_11_MESH_OLPC: + raise RuntimeError("Only valid for mesh devices") + try: + step = self.dev.getMeshStep(timeout=3) + except dbus.DBusException: + step = 0 + return step + + def get_frequency(self): + try: + freq = self.dev.getFrequency(timeout=3) + except dbus.DBusException: + freq = 0.0 + # Hz -> GHz + self._freq = freq / 1000000000.0 + return self._freq + + def get_ip_address(self): + return self._ip_address + + def get_strength(self): + return self._strength + + def set_strength(self, strength): + if strength == self._strength: + return False + + if strength >= 0 and strength <= 100: + self._strength = strength + else: + self._strength = 0 + + if self._valid: + self.emit('strength-changed') + + def network_appeared(self, network): + # NM may emit NetworkAppeared messages before the initialization-time + # getProperties call completes. This means that we are in danger of + # instantiating the "appeared" network here, and then instantiating + # the same network later on when getProperties completes + # (_update_reply_cb calls _update_networks). + # We avoid this race by confirming that getProperties has completed + # before listening to any NetworkAppeared messages. We assume that + # any networks that get reported as appeared in this race window + # will be included in the getProperties response. + if not self._valid: + return + + if self._networks.has_key(network): + return + net = Network(self._client, network) + self._networks[network] = net + net.connect('initialized', lambda *args: + self._net_initialized_cb(None, *args)) + + def network_disappeared(self, network): + if not self._networks.has_key(network): + return + + if self._valid: + self.emit('network-disappeared', self._networks[network]) + + del self._networks[network] + + def set_active_network(self, network): + if self._active_network == network: + return + + # Make sure the old one doesn't get a stuck state + if self._active_network: + self._active_network.set_state(NETWORK_STATE_NOTCONNECTED) + self._active_network.disconnect(self._active_net_sigid) + + self._active_network = network + + if self._active_network: + self._active_net_sigid = self._active_network.connect( + "initialized", self._active_net_initialized) + + # don't emit ssid-changed for networks that are not yet valid + if self._valid: + if self._active_network and self._active_network.is_valid(): + self.emit('ssid-changed') + elif not self._active_network: + self.emit('ssid-changed') + + def _active_net_initialized(self, net, user_data=None): + if self._active_network and self._active_network.is_valid(): + self.emit('ssid-changed') + + def _get_active_net_cb(self, state, net_op): + if not self._networks.has_key(net_op): + self.set_active_network(None) + return + + self.set_active_network(self._networks[net_op]) + + _device_to_network_state = { + DEVICE_STATE_ACTIVATING : NETWORK_STATE_CONNECTING, + DEVICE_STATE_ACTIVATED : NETWORK_STATE_CONNECTED, + DEVICE_STATE_INACTIVE : NETWORK_STATE_NOTCONNECTED + } + + network_state = _device_to_network_state[state] + self._active_network.set_state(network_state) + + def _get_active_net_error_cb(self, err): + logging.debug("Couldn't get active network: %s" % err) + self.set_active_network(None) + + def get_state(self): + return self._state + + def set_state(self, state): + if state == self._state: + return + + if state == DEVICE_STATE_INACTIVE: + self._act_stage = 0 + + self._state = state + if self._valid: + self.emit('state-changed') + + if self._type == DEVICE_TYPE_802_11_WIRELESS: + if state == DEVICE_STATE_INACTIVE: + self.set_active_network(None) + else: + self.dev.getActiveNetwork( + reply_handler=lambda *args: + self._get_active_net_cb(state, *args), + error_handler=self._get_active_net_error_cb) + + if state == DEVICE_STATE_ACTIVATED: + # 6248: reimplement for NM0.7 + # see http://dev.laptop.org/ticket/6248#comment:2 + self.dev.getProperties( + reply_handler=self._getproperties_for_ip_only_reply_cb, + error_handler=self._getproperties_for_ip_only_error_cb) + + def set_activation_stage(self, stage): + if stage == self._act_stage: + return + self._act_stage = stage + if self._valid: + self.emit('activation-stage-changed') + + # 6248: reimplement for NM0.7 + # see http://dev.laptop.org/ticket/6248#comment:2 + self.dev.getProperties( + reply_handler=self._getproperties_for_ip_only_reply_cb, + error_handler=self._getproperties_for_ip_only_error_cb) + + def get_activation_stage(self): + return self._act_stage + + def get_ssid(self): + if self._active_network and self._active_network.is_valid(): + return self._active_network.get_ssid() + elif not self._active_network: + return None + + def get_active_network(self): + return self._active_network + + def get_type(self): + return self._type + + def is_valid(self): + return self._valid + + def set_carrier(self, on): + self._link = on + + def get_capabilities(self): + return self._caps + +class NMClient(gobject.GObject): + __gsignals__ = { + 'device-added' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'device-activated' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'device-activating': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'device-removed' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) + } + + def __init__(self): + gobject.GObject.__init__(self) + + self.nminfo = None + self._nm_present = False + self._nm_proxy = None + self._nm_obj = None + self._sig_handlers = None + self._update_timer = 0 + self._devices = {} + + self.nminfo = nminfo.NMInfo(self) + + self._setup_dbus() + if self._nm_present: + self._get_initial_devices() + + def get_devices(self): + return self._devices.values() + + def _get_initial_devices_reply_cb(self, ops): + for op in ops: + self._add_device(op) + + def _dev_initialized_cb(self, dev): + self.emit('device-added', dev) + + def _dev_init_failed_cb(self, dev): + # Device failed to initialize, likely due to dbus errors or something + op = dev.get_op() + self._remove_device(op) + + def _get_initial_devices_error_cb(self, err): + logging.debug("Error updating devices (%s)" % err) + + def _get_initial_devices(self): + self._nm_obj.getDevices( + reply_handler=self._get_initial_devices_reply_cb, + error_handler=self._get_initial_devices_error_cb) + + def _add_device(self, dev_op): + if self._devices.has_key(dev_op): + return + dev = Device(self, dev_op) + self._devices[dev_op] = dev + dev.connect('init-failed', self._dev_init_failed_cb) + dev.connect('initialized', self._dev_initialized_cb) + dev.connect('state-changed', self._dev_state_changed_cb) + + def _remove_device(self, dev_op): + if not self._devices.has_key(dev_op): + return + dev = self._devices[dev_op] + if dev.is_valid(): + self.emit('device-removed', dev) + del self._devices[dev_op] + + def _dev_state_changed_cb(self, dev): + op = dev.get_op() + if not self._devices.has_key(op) or not dev.is_valid(): + return + if dev.get_state() == DEVICE_STATE_ACTIVATING: + self.emit('device-activating', dev) + elif dev.get_state() == DEVICE_STATE_ACTIVATED: + self.emit('device-activated', dev) + + def get_device(self, dev_op): + if not self._devices.has_key(dev_op): + return None + return self._devices[dev_op] + + def _setup_dbus(self): + self._sig_handlers = { + 'StateChange': self.state_changed_sig_handler, + 'DeviceAdded': self.device_added_sig_handler, + 'DeviceRemoved': self.device_removed_sig_handler, + 'DeviceActivationStage': self.device_activation_stage_sig_handler, + 'DeviceActivating': self.device_activating_sig_handler, + 'DeviceNowActive': self.device_now_active_sig_handler, + 'DeviceNoLongerActive': self.device_no_longer_active_sig_handler, + 'DeviceActivationFailed': \ + self.device_activation_failed_sig_handler, + 'DeviceCarrierOn': self.device_carrier_on_sig_handler, + 'DeviceCarrierOff': self.device_carrier_off_sig_handler, + 'DeviceStrengthChanged': \ + self.wireless_device_strength_changed_sig_handler, + 'WirelessNetworkAppeared': \ + self.wireless_network_appeared_sig_handler, + 'WirelessNetworkDisappeared': \ + self.wireless_network_disappeared_sig_handler, + 'WirelessNetworkStrengthChanged': \ + self.wireless_network_strength_changed_sig_handler + } + + try: + self._nm_proxy = sys_bus.get_object(NM_SERVICE, NM_PATH, + follow_name_owner_changes=True) + self._nm_obj = dbus.Interface(self._nm_proxy, NM_IFACE) + except dbus.DBusException, e: + logging.debug("Could not connect to NetworkManager: %s" % e) + self._nm_present = False + return + + sys_bus.add_signal_receiver(self.name_owner_changed_sig_handler, + signal_name="NameOwnerChanged", + dbus_interface="org.freedesktop.DBus") + + for (signal, handler) in self._sig_handlers.items(): + sys_bus.add_signal_receiver(handler, signal_name=signal, + dbus_interface=NM_IFACE) + + # Find out whether or not NMI is running + try: + bus_object = sys_bus.get_object('org.freedesktop.DBus', + '/org/freedesktop/DBus') + name_ = bus_object.GetNameOwner( \ + "org.freedesktop.NetworkManagerInfo", + dbus_interface='org.freedesktop.DBus') + self._nm_present = True + except dbus.DBusException: + self._nm_present = False + + def set_active_device(self, device, network=None, + mesh_freq=None, mesh_start=None): + ssid = "" + if network: + ssid = network.get_ssid() + if device.get_type() == DEVICE_TYPE_802_11_MESH_OLPC: + if mesh_freq or mesh_start: + if mesh_freq and not mesh_start: + self._nm_obj.setActiveDevice(device.get_op(), + dbus.Double(mesh_freq)) + elif mesh_start and not mesh_freq: + self._nm_obj.setActiveDevice(device.get_op(), + dbus.Double(0.0), + dbus.UInt32(mesh_start)) + else: + self._nm_obj.setActiveDevice(device.get_op(), + dbus.Double(mesh_freq), + dbus.UInt32(mesh_start)) + else: + self._nm_obj.setActiveDevice(device.get_op()) + else: + self._nm_obj.setActiveDevice(device.get_op(), ssid) + + def state_changed_sig_handler(self, new_state): + logging.debug('NM State Changed to %d' % new_state) + + def device_activation_stage_sig_handler(self, device, stage): + logging.debug('Device Activation Stage "%s" for device %s' + % (NM_DEVICE_STAGE_STRINGS[stage], device)) + if not self._devices.has_key(device): + logging.debug('DeviceActivationStage, device %s does not exist' + % (device)) + return + self._devices[device].set_activation_stage(stage) + + def device_activating_sig_handler(self, device): + logging.debug('DeviceActivating for %s' % (device)) + if not self._devices.has_key(device): + logging.debug('DeviceActivating, device %s does not exist' + % (device)) + return + self._devices[device].set_state(DEVICE_STATE_ACTIVATING) + + def device_now_active_sig_handler(self, device, ssid=None): + logging.debug('DeviceNowActive for %s' % (device)) + if not self._devices.has_key(device): + logging.debug('DeviceNowActive, device %s does not exist' + % (device)) + return + self._devices[device].set_state(DEVICE_STATE_ACTIVATED) + + def device_no_longer_active_sig_handler(self, device): + logging.debug('DeviceNoLongerActive for %s' % (device)) + if not self._devices.has_key(device): + logging.debug('DeviceNoLongerActive, device %s does not exist' + % (device)) + return + self._devices[device].set_state(DEVICE_STATE_INACTIVE) + + def device_activation_failed_sig_handler(self, device, ssid=None): + logging.debug('DeviceActivationFailed for %s' % (device)) + if not self._devices.has_key(device): + logging.debug('DeviceActivationFailed, device %s does not exist' + % (device)) + return + self._devices[device].set_state(DEVICE_STATE_INACTIVE) + + def name_owner_changed_sig_handler(self, name, old, new): + if name != NM_SERVICE: + return + if (old and len(old)) and (not new and not len(new)): + # NM went away + self._nm_present = False + devs = self._devices.keys() + for op in devs: + self._remove_device(op) + self._devices = {} + elif (not old and not len(old)) and (new and len(new)): + # NM started up + self._nm_present = True + self._get_initial_devices() + + def device_added_sig_handler(self, device): + logging.debug('DeviceAdded for %s' % (device)) + self._add_device(device) + + def device_removed_sig_handler(self, device): + logging.debug('DeviceRemoved for %s' % (device)) + self._remove_device(device) + + def wireless_network_appeared_sig_handler(self, device, network): + if not self._devices.has_key(device): + return + self._devices[device].network_appeared(network) + + def wireless_network_disappeared_sig_handler(self, device, network): + if not self._devices.has_key(device): + return + self._devices[device].network_disappeared(network) + + def wireless_device_strength_changed_sig_handler(self, device, strength): + if not self._devices.has_key(device): + return + self._devices[device].set_strength(strength) + + def wireless_network_strength_changed_sig_handler(self, device, + network, strength): + if not self._devices.has_key(device): + return + net = self._devices[device].get_network(network) + if net: + net.set_strength(strength) + + def device_carrier_on_sig_handler(self, device): + if not self._devices.has_key(device): + return + self._devices[device].set_carrier(True) + + def device_carrier_off_sig_handler(self, device): + if not self._devices.has_key(device): + return + self._devices[device].set_carrier(False) diff --git a/src/hardware/nminfo.py b/src/hardware/nminfo.py new file mode 100644 index 0000000..9f427e0 --- /dev/null +++ b/src/hardware/nminfo.py @@ -0,0 +1,556 @@ +# vi: ts=4 ai noet +# +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import dbus +import dbus.service +import time +import os +import binascii +import ConfigParser +import logging + +import nmclient +import keydialog +import gtk +from sugar import env + +IW_AUTH_KEY_MGMT_802_1X = 0x1 +IW_AUTH_KEY_MGMT_PSK = 0x2 + +IW_AUTH_WPA_VERSION_DISABLED = 0x00000001 +IW_AUTH_WPA_VERSION_WPA = 0x00000002 +IW_AUTH_WPA_VERSION_WPA2 = 0x00000004 + +NM_AUTH_TYPE_WPA_PSK_AUTO = 0x00000000 +IW_AUTH_CIPHER_NONE = 0x00000001 +IW_AUTH_CIPHER_WEP40 = 0x00000002 +IW_AUTH_CIPHER_TKIP = 0x00000004 +IW_AUTH_CIPHER_CCMP = 0x00000008 +IW_AUTH_CIPHER_WEP104 = 0x00000010 + +IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001 +IW_AUTH_ALG_SHARED_KEY = 0x00000002 + +NM_INFO_IFACE = 'org.freedesktop.NetworkManagerInfo' +NM_INFO_PATH = '/org/freedesktop/NetworkManagerInfo' + + +class NoNetworks(dbus.DBusException): + def __init__(self): + dbus.DBusException.__init__(self) + self._dbus_error_name = NM_INFO_IFACE + '.NoNetworks' + +class CanceledKeyRequestError(dbus.DBusException): + def __init__(self): + dbus.DBusException.__init__(self) + self._dbus_error_name = NM_INFO_IFACE + '.CanceledError' + + +class NetworkInvalidError(Exception): + pass + + +class NMConfig(ConfigParser.ConfigParser): + def get_bool(self, section, name): + opt = self.get(section, name) + if type(opt) == str: + if opt.lower() == 'yes' or opt.lower() == 'true': + return True + elif opt.lower() == 'no' or opt.lower() == 'false': + return False + raise ValueError("Invalid format for %s/%s. Should be one of" \ + " [yes, no, true, false]." % (section, name)) + + def get_list(self, section, name): + opt = self.get(section, name) + if type(opt) != str or not len(opt): + return [] + try: + return opt.split() + except Exception: + raise ValueError("Invalid format for %s/%s. Should be a" \ + " space-separate list." % (section, name)) + + def get_int(self, section, name): + opt = self.get(section, name) + try: + return int(opt) + except ValueError: + raise ValueError("Invalid format for %s/%s. Should be a" \ + " valid integer." % (section, name)) + + def get_float(self, section, name): + opt = self.get(section, name) + try: + return float(opt) + except ValueError: + raise ValueError("Invalid format for %s/%s. Should be a" \ + " valid float." % (section, name)) + + +NETWORK_TYPE_UNKNOWN = 0 +NETWORK_TYPE_ALLOWED = 1 +NETWORK_TYPE_INVALID = 2 + + +class Security(object): + def __init__(self, we_cipher): + self._we_cipher = we_cipher + self._key = None + self._auth_alg = None + + def read_from_config(self, cfg, name): + pass + + def read_from_args(self, args): + pass + + def new_from_config(cfg, name): + security = None + we_cipher = cfg.get_int(name, "we_cipher") + if we_cipher == IW_AUTH_CIPHER_NONE: + security = Security(we_cipher) + elif we_cipher == IW_AUTH_CIPHER_WEP40 or \ + we_cipher == IW_AUTH_CIPHER_WEP104: + security = WEPSecurity(we_cipher) + elif we_cipher == NM_AUTH_TYPE_WPA_PSK_AUTO or \ + we_cipher == IW_AUTH_CIPHER_CCMP or \ + we_cipher == IW_AUTH_CIPHER_TKIP: + security = WPASecurity(we_cipher) + else: + raise ValueError("Unsupported security combo") + security.read_from_config(cfg, name) + return security + new_from_config = staticmethod(new_from_config) + + def new_from_args(we_cipher, args): + security = None + try: + if we_cipher == IW_AUTH_CIPHER_NONE: + security = Security(we_cipher) + elif we_cipher == IW_AUTH_CIPHER_WEP40 or \ + we_cipher == IW_AUTH_CIPHER_WEP104: + security = WEPSecurity(we_cipher) + elif we_cipher == NM_AUTH_TYPE_WPA_PSK_AUTO or \ + we_cipher == IW_AUTH_CIPHER_CCMP or \ + we_cipher == IW_AUTH_CIPHER_TKIP: + security = WPASecurity(we_cipher) + else: + raise ValueError("Unsupported security combo") + security.read_from_args(args) + except ValueError, e: + logging.debug("Error reading security information: %s" % e) + del security + return None + return security + new_from_args = staticmethod(new_from_args) + + def get_properties(self): + return [dbus.Int32(self._we_cipher)] + + def write_to_config(self, section, config): + config.set(section, "we_cipher", self._we_cipher) + + +class WEPSecurity(Security): + def read_from_args(self, args): + if len(args) != 2: + raise ValueError("not enough arguments") + key = args[0] + auth_alg = args[1] + if isinstance(key, unicode): + key = key.encode() + if not isinstance(key, str): + raise ValueError("wrong argument type for key") + if not isinstance(auth_alg, int): + raise ValueError("wrong argument type for auth_alg") + self._key = key + self._auth_alg = auth_alg + + def read_from_config(self, cfg, name): + # Key should be a hex encoded string + self._key = cfg.get(name, "key") + if self._we_cipher == IW_AUTH_CIPHER_WEP40 and len(self._key) != 10: + raise ValueError("Key length not right for 40-bit WEP") + if self._we_cipher == IW_AUTH_CIPHER_WEP104 and len(self._key) != 26: + raise ValueError("Key length not right for 104-bit WEP") + + try: + binascii.a2b_hex(self._key) + except TypeError: + raise ValueError("Key was not a hexadecimal string.") + + self._auth_alg = cfg.get_int(name, "auth_alg") + if self._auth_alg != IW_AUTH_ALG_OPEN_SYSTEM and \ + self._auth_alg != IW_AUTH_ALG_SHARED_KEY: + raise ValueError("Invalid authentication algorithm %d" + % self._auth_alg) + + def get_properties(self): + args = Security.get_properties(self) + args.append(dbus.String(self._key)) + args.append(dbus.Int32(self._auth_alg)) + return args + + def write_to_config(self, section, config): + Security.write_to_config(self, section, config) + config.set(section, "key", self._key) + config.set(section, "auth_alg", self._auth_alg) + +class WPASecurity(Security): + def __init__(self, we_cipher): + Security.__init__(self, we_cipher) + self._wpa_ver = None + self._key_mgmt = None + + def read_from_args(self, args): + if len(args) != 3: + raise ValueError("not enough arguments") + key = args[0] + if isinstance(key, unicode): + key = key.encode() + if not isinstance(key, str): + raise ValueError("wrong argument type for key") + + wpa_ver = args[1] + if not isinstance(wpa_ver, int): + raise ValueError("wrong argument type for WPA version") + + key_mgmt = args[2] + if not isinstance(key_mgmt, int): + raise ValueError("wrong argument type for WPA key management") + if not key_mgmt & IW_AUTH_KEY_MGMT_PSK: + raise ValueError("Key management types other than" \ + " PSK are not supported") + + self._key = key + self._wpa_ver = wpa_ver + self._key_mgmt = key_mgmt + + def read_from_config(self, cfg, name): + # Key should be a hex encoded string + self._key = cfg.get(name, "key") + if len(self._key) != 64: + raise ValueError("Key length not right for WPA-PSK") + + try: + binascii.a2b_hex(self._key) + except TypeError: + raise ValueError("Key was not a hexadecimal string.") + + self._wpa_ver = cfg.get_int(name, "wpa_ver") + if self._wpa_ver != IW_AUTH_WPA_VERSION_WPA and \ + self._wpa_ver != IW_AUTH_WPA_VERSION_WPA2: + raise ValueError("Invalid WPA version %d" % self._wpa_ver) + + self._key_mgmt = cfg.get_int(name, "key_mgmt") + if not self._key_mgmt & IW_AUTH_KEY_MGMT_PSK: + raise ValueError("Invalid WPA key management option %d" + % self._key_mgmt) + + def get_properties(self): + args = Security.get_properties(self) + args.append(dbus.String(self._key)) + args.append(dbus.Int32(self._wpa_ver)) + args.append(dbus.Int32(self._key_mgmt)) + return args + + def write_to_config(self, section, config): + Security.write_to_config(self, section, config) + config.set(section, "key", self._key) + config.set(section, "wpa_ver", self._wpa_ver) + config.set(section, "key_mgmt", self._key_mgmt) + + +class Network: + def __init__(self, ssid): + self.ssid = ssid + self.timestamp = int(time.time()) + self.bssids = [] + self.we_cipher = 0 + self._security = None + + def get_properties(self): + bssid_list = dbus.Array([], signature="s") + for item in self.bssids: + bssid_list.append(dbus.String(item)) + args = [dbus.String(self.ssid), dbus.Int32(self.timestamp), + dbus.Boolean(True), bssid_list] + args += self._security.get_properties() + return tuple(args) + + def get_security(self): + return self._security.get_properties() + + def set_security(self, security): + self._security = security + + def read_from_args(self, auto, bssid, we_cipher, args): + if auto == False: + self.timestamp = int(time.time()) + if not bssid in self.bssids: + self.bssids.append(bssid) + + self._security = Security.new_from_args(we_cipher, args) + if not self._security: + raise NetworkInvalidError("Invalid security information") + + def read_from_config(self, config): + try: + self.timestamp = config.get_int(self.ssid, "timestamp") + except (ConfigParser.NoOptionError, ValueError), e: + raise NetworkInvalidError(e) + + try: + self._security = Security.new_from_config(config, self.ssid) + except Exception, e: + raise NetworkInvalidError(e) + + # The following don't need to be present + try: + self.bssids = config.get_list(self.ssid, "bssids") + except (ConfigParser.NoOptionError, ValueError), e: + logging.debug("Error reading bssids: %s" % e) + + def write_to_config(self, config): + try: + config.add_section(self.ssid) + config.set(self.ssid, "timestamp", self.timestamp) + if len(self.bssids) > 0: + opt = " " + opt = opt.join(self.bssids) + config.set(self.ssid, "bssids", opt) + self._security.write_to_config(self.ssid, config) + except Exception, e: + logging.debug("Error writing '%s': %s" % (self.ssid, e)) + + +class NotFoundError(dbus.DBusException): + pass +class UnsupportedError(dbus.DBusException): + pass + +class NMInfoDBusServiceHelper(dbus.service.Object): + def __init__(self, parent): + self._parent = parent + bus = dbus.SystemBus() + + # If NMI is already around, don't grab the NMI service + bus_object = bus.get_object('org.freedesktop.DBus', + '/org/freedesktop/DBus') + name = None + try: + name = bus_object.GetNameOwner( \ + "org.freedesktop.NetworkManagerInfo", + dbus_interface='org.freedesktop.DBus') + except dbus.DBusException: + logging.debug("Error getting owner of NMI") + if name: + logging.info("NMI service already owned by %s, won't claim it." + % name) + + bus_name = dbus.service.BusName(NM_INFO_IFACE, bus=bus) + dbus.service.Object.__init__(self, bus_name, NM_INFO_PATH) + + @dbus.service.method(NM_INFO_IFACE, in_signature='i', out_signature='as') + def getNetworks(self, net_type): + ssids = self._parent.get_networks(net_type) + if len(ssids) > 0: + return dbus.Array(ssids) + + raise NoNetworks() + + @dbus.service.method(NM_INFO_IFACE, in_signature='si', + async_callbacks=('async_cb', 'async_err_cb')) + def getNetworkProperties(self, ssid, net_type, async_cb, async_err_cb): + self._parent.get_network_properties(ssid, net_type, + async_cb, async_err_cb) + + @dbus.service.method(NM_INFO_IFACE) + def updateNetworkInfo(self, ssid, bauto, bssid, cipher, *args): + self._parent.update_network_info(ssid, bauto, bssid, cipher, args) + + @dbus.service.method(NM_INFO_IFACE, + async_callbacks=('async_cb', 'async_err_cb')) + def getKeyForNetwork(self, dev_path, net_path, ssid, attempt, + new_key, async_cb, async_err_cb): + self._parent.get_key_for_network(dev_path, net_path, ssid, + attempt, new_key, async_cb, async_err_cb) + + @dbus.service.method(NM_INFO_IFACE) + def cancelGetKeyForNetwork(self): + self._parent.cancel_get_key_for_network() + +class NMInfo(object): + def __init__(self, client): + profile_path = env.get_profile_path() + self._cfg_file = os.path.join(profile_path, "nm", "networks.cfg") + self._nmclient = client + self._allowed_networks = self._read_config() + self._dbus_helper = NMInfoDBusServiceHelper(self) + self._key_dialog = None + + def save_config(self): + self._write_config(self._allowed_networks) + + def _read_config(self): + if not os.path.exists(os.path.dirname(self._cfg_file)): + os.makedirs(os.path.dirname(self._cfg_file), 0755) + if not os.path.exists(self._cfg_file): + self._write_config({}) + return {} + + config = NMConfig() + config.read(self._cfg_file) + networks = {} + for name in config.sections(): + try: + net = Network(name) + net.read_from_config(config) + networks[name] = net + except Exception, e: + logging.error("Error when processing config for" \ + " the network %s: %r" % (name, e)) + + del config + return networks + + def _write_config(self, networks): + fp = open(self._cfg_file, 'w') + config = NMConfig() + for net in networks.values(): + net.write_to_config(config) + config.write(fp) + fp.close() + del config + + def get_networks(self, net_type): + if net_type != NETWORK_TYPE_ALLOWED: + raise ValueError("Bad network type") + nets = [] + for net in self._allowed_networks.values(): + nets.append(net.ssid) + logging.debug("Returning networks: %s" % nets) + return nets + + def get_network_properties(self, ssid, net_type, async_cb, async_err_cb): + if not isinstance(ssid, unicode): + async_err_cb(ValueError("Invalid arguments; ssid must be unicode.")) + if net_type != NETWORK_TYPE_ALLOWED: + async_err_cb(ValueError("Bad network type")) + if not self._allowed_networks.has_key(ssid): + async_err_cb(NotFoundError("Network '%s' not found." % ssid)) + network = self._allowed_networks[ssid] + props = network.get_properties() + + # DBus workaround: the normal method return handler wraps + # the returned arguments in a tuple and then converts that to a + # struct, but NetworkManager expects a plain list of arguments. + # It turns out that the async callback method return code _doesn't_ + # wrap the returned arguments in a tuple, so as a workaround use + # the async callback stuff here even though we're not doing it + # asynchronously. + async_cb(*props) + + def update_network_info(self, ssid, auto, bssid, we_cipher, args): + if not isinstance(ssid, unicode): + raise ValueError("Invalid arguments; ssid must be unicode.") + if self._allowed_networks.has_key(ssid): + del self._allowed_networks[ssid] + net = Network(ssid) + try: + net.read_from_args(auto, bssid, we_cipher, args) + logging.debug("Updated network information for '%s'." % ssid) + self._allowed_networks[ssid] = net + self.save_config() + except NetworkInvalidError, e: + logging.debug("Error updating network information: %s" % e) + del net + + def get_key_for_network(self, dev_op, net_op, ssid, attempt, + new_key, async_cb, async_err_cb): + if not isinstance(ssid, unicode): + raise ValueError("Invalid arguments; ssid must be unicode.") + if self._allowed_networks.has_key(ssid) and not new_key: + # We've got the info already + net = self._allowed_networks[ssid] + async_cb(tuple(net.get_security())) + return + + # Otherwise, ask the user for it + net = None + dev = self._nmclient.get_device(dev_op) + if not dev: + async_err_cb(NotFoundError("Device was unknown.")) + return + + if dev.get_type() == nmclient.DEVICE_TYPE_802_3_ETHERNET: + # We don't support wired 802.1x yet... + async_err_cb(UnsupportedError("Device type is unsupported by NMI.")) + return + + net = dev.get_network(net_op) + if not net: + async_err_cb(NotFoundError("Network was unknown.")) + return + + self._key_dialog = keydialog.new_key_dialog(net, async_cb, async_err_cb) + self._key_dialog.connect("response", self._key_dialog_response_cb) + self._key_dialog.connect("destroy", self._key_dialog_destroy_cb) + self._key_dialog.show_all() + + def _key_dialog_destroy_cb(self, widget, data=None): + if widget != self._key_dialog: + return + self._key_dialog_response_cb(widget, gtk.RESPONSE_CANCEL) + + def _key_dialog_response_cb(self, widget, response_id): + if widget != self._key_dialog: + return + + (async_cb, async_err_cb) = self._key_dialog.get_callbacks() + security = None + if response_id == gtk.RESPONSE_OK: + security = self._key_dialog.create_security() + self._key_dialog = None + widget.destroy() + + if response_id in [gtk.RESPONSE_CANCEL, gtk.RESPONSE_NONE]: + # key dialog dialog was canceled; send the error back to NM + async_err_cb(CanceledKeyRequestError()) + elif response_id == gtk.RESPONSE_OK: + if not security: + raise RuntimeError("Invalid security arguments.") + props = security.get_properties() + a = tuple(props) + async_cb(*a) + else: + raise RuntimeError("Unhandled key dialog response %d" % response_id) + + def cancel_get_key_for_network(self): + # Close the wireless key dialog and just have it return + # with the 'canceled' argument set to true + if not self._key_dialog: + return + self._key_dialog_destroy_cb(self._key_dialog) + + # this method is invoked directly in-process (not by DBus). + def delete_all_networks(self): + self._allowed_networks = {} + self.save_config() + diff --git a/src/jarabe/desktop/schoolserver.py b/src/hardware/schoolserver.py index f5e5db4..a9ed60b 100644 --- a/src/jarabe/desktop/schoolserver.py +++ b/src/hardware/schoolserver.py @@ -3,7 +3,6 @@ from gettext import gettext as _ from xmlrpclib import ServerProxy, Error import socket import os -import gconf from sugar.profile import get_profile @@ -24,12 +23,9 @@ def register_laptop(url=REGISTER_URL): profile = get_profile() - client = gconf.client_get_default() - nick = client.get_string('/desktop/sugar/user/nick') - server = ServerProxy(url) try: - data = server.register(sn, nick, uuid, profile.pubkey) + data = server.register(sn, profile.nick_name, uuid, profile.pubkey) except (Error, socket.error), e: logging.error('Registration: cannot connect to server: %s' % e) raise RegisterError(_('Cannot connect to the server.')) @@ -39,9 +35,9 @@ def register_laptop(url=REGISTER_URL): data['error']) raise RegisterError(_('The server could not complete the request.')) - client.set_string('/desktop/sugar/collaboration/jabber_server', - data['jabberserver']) - client.set_string('/desktop/sugar/backup_url', data['backupurl']) + profile.jabber_server = data['jabberserver'] + profile.backup1 = data['backupurl'] + profile.save() return True diff --git a/src/intro/Makefile.am b/src/intro/Makefile.am new file mode 100644 index 0000000..3b92ea0 --- /dev/null +++ b/src/intro/Makefile.am @@ -0,0 +1,10 @@ +imagedir = $(pkgdatadir)/shell/intro +image_DATA = default-picture.png + +EXTRA_DIST = $(conf_DATA) $(image_DATA) +sugardir = $(pkgdatadir)/shell/intro +sugar_PYTHON = \ + __init__.py \ + colorpicker.py \ + intro.py \ + glive.py diff --git a/src/jarabe/intro/Makefile.in b/src/intro/Makefile.in index 57c1858..f8ad7d1 100644 --- a/src/jarabe/intro/Makefile.in +++ b/src/intro/Makefile.in @@ -30,7 +30,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/intro +subdir = src/intro DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -76,9 +76,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -195,14 +192,15 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -imagedir = $(pythondir)/jarabe/intro +imagedir = $(pkgdatadir)/shell/intro image_DATA = default-picture.png EXTRA_DIST = $(conf_DATA) $(image_DATA) -sugardir = $(pythondir)/jarabe/intro +sugardir = $(pkgdatadir)/shell/intro sugar_PYTHON = \ - __init__.py \ - colorpicker.py \ - window.py + __init__.py \ + colorpicker.py \ + intro.py \ + glive.py all: all-am @@ -216,9 +214,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/intro/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/intro/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/intro/Makefile + $(AUTOMAKE) --foreign src/intro/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/extensions/cpsection/__init__.py b/src/intro/__init__.py index e69de29..e69de29 100644 --- a/extensions/cpsection/__init__.py +++ b/src/intro/__init__.py diff --git a/src/jarabe/intro/colorpicker.py b/src/intro/colorpicker.py index a939857..a939857 100644 --- a/src/jarabe/intro/colorpicker.py +++ b/src/intro/colorpicker.py diff --git a/src/jarabe/intro/default-picture.png b/src/intro/default-picture.png Binary files differindex e26b9b0..e26b9b0 100644 --- a/src/jarabe/intro/default-picture.png +++ b/src/intro/default-picture.png diff --git a/src/intro/glive.py b/src/intro/glive.py new file mode 100644 index 0000000..a2ddbae --- /dev/null +++ b/src/intro/glive.py @@ -0,0 +1,200 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +import gtk +import pygtk +pygtk.require('2.0') + +import pygst +pygst.require('0.10') +import gst +import gst.interfaces + +import gobject +gobject.threads_init() + +class Glive(gobject.GObject): + __gsignals__ = { + 'new-picture': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'sink' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) + } + + def __init__(self, parent, width, height): + gobject.GObject.__init__(self) + self._parent = parent + + #check out the halfpipe, d00d. + self.pipeline = gst.Pipeline() + + self.v4l2src = gst.element_factory_make("v4l2src", "v4l2src") + self.t = gst.element_factory_make("tee", "tee") + self.t_src_pad = self.t.get_request_pad( "src%d" ) + self.vscale = gst.element_factory_make("videoscale", "videoscale") + self.ximagesink = gst.element_factory_make("ximagesink", "ximagesink") + + self.pipeline.add(self.v4l2src) + self.pipeline.add(self.t) + self.pipeline.add(self.vscale) + self.pipeline.add(self.ximagesink) + + self.v4l2src.link(self.t) + + videoscale_structure = gst.Structure("video/x-raw-rgb") + videoscale_structure['width'] = width + videoscale_structure['height'] = height + videoscale_structure['bpp'] = 16 + videoscale_structure['depth'] = 16 + videoscale_caps = gst.Caps(videoscale_structure) + self.t_src_pad.link(self.vscale.get_pad("sink")) + self.vscale.link(self.ximagesink, videoscale_caps) + #self.vscale.link(self.ximagesink) + + self.queue = gst.element_factory_make("queue", "queue") + self.queue.set_property("leaky", True) + self.queue.set_property("max-size-buffers", 1) + self.qsrc = self.queue.get_pad( "src" ) + self.qsink = self.queue.get_pad("sink") + self.ffmpeg = gst.element_factory_make( \ + "ffmpegcolorspace", "ffmpegcolorspace") + self.jpgenc = gst.element_factory_make("jpegenc", "jpegenc") + self.filesink = gst.element_factory_make("fakesink", "fakesink") + self.filesink.connect( "handoff", self.copyframe ) + self.filesink.set_property("signal-handoffs", True) + self.pipeline.add(self.queue, self.ffmpeg, self.jpgenc, self.filesink) + + #only link at snapshot time + #self.t.link(self.queue) + self.queue.link(self.ffmpeg) + self.ffmpeg.link(self.jpgenc) + self.jpgenc.link(self.filesink) + self.exposureOpen = False + + self._bus = self.pipeline.get_bus() + self._CONNECT_SYNC = -1 + self._CONNECT_MSG = -1 + self.doPostBusStuff() + + def copyframe(self, fsink, buf, pad, user_data=None): + #for some reason, we get two back to back buffers, even though we + #ask for only one. + if (self.exposureOpen): + self.exposureOpen = False + piccy = gtk.gdk.pixbuf_loader_new_with_mime_type("image/jpeg") + piccy.write(buf) + piccy.close() + pixbuf = piccy.get_pixbuf() + del piccy + + self.t.unlink(self.queue) + self.queue.set_property("leaky", True) + + gobject.idle_add(self.loadPic, pixbuf) + + def loadPic( self, pixbuf ): + self.emit('new-picture', pixbuf) + + def takeSnapshot( self ): + if (self.exposureOpen): + return + else: + self.exposureOpen = True + self.t.link(self.queue) + + def doPostBusStuff(self): + self._bus.enable_sync_message_emission() + self._bus.add_signal_watch() + self._CONNECT_SYNC = self._bus.connect('sync-message::element', + self.on_sync_message) + self._CONNECT_MSG = self._bus.connect('message', self.on_message) + + def on_sync_message(self, bus, message): + if message.structure is None: + return + if message.structure.get_name() == 'prepare-xwindow-id': + self.emit('sink', message.src) + message.src.set_property('force-aspect-ratio', True) + + def on_message(self, bus, message): + t = message.type + if (t == gst.MESSAGE_ERROR): + if (self.on_eos): + self.on_eos() + elif (t == gst.MESSAGE_EOS): + if (self.on_eos): + self.on_eos() + + def on_eos( self ): + pass + + def stop(self): + self.pipeline.set_state(gst.STATE_NULL) + + def play(self): + self.pipeline.set_state(gst.STATE_PLAYING) + + def pause(self): + self.pipeline.set_state(gst.STATE_PAUSED) + + +class LiveVideoSlot(gtk.EventBox): + __gsignals__ = { + 'pixbuf': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) + } + + def __init__(self, width, height): + gtk.EventBox.__init__(self) + + self.imagesink = None + self.playa = None + self._width = width + self._height = height + + self.unset_flags(gtk.DOUBLE_BUFFERED) + self.connect('focus-in-event', self.focus_in) + self.connect('focus-out-event', self.focus_out) + self.connect("button-press-event", self._button_press_event_cb) + self.connect("expose-event", self._expose_event_cb) + + def _expose_event_cb(self, widget, event): + if not self.playa: + self.playa = Glive(self, self._width, self._height) + self.playa.connect('new-picture', self._new_picture_cb) + self.playa.connect('sink', self._new_sink_cb) + + def _new_picture_cb(self, playa, pixbuf): + self.emit('pixbuf', pixbuf) + + def _new_sink_cb(self, playa, sink): + if (self.imagesink != None): + assert self.window.xid + self.imagesink = None + del self.imagesink + self.imagesink = sink + self.imagesink.set_xwindow_id(self.window.xid) + + def _button_press_event_cb(self, widget, event): + self.takeSnapshot() + + def focus_in(self, widget, event, args=None): + self.play() + + def focus_out(self, widget, event, args=None): + self.stop() + + def play( self ): + self.playa.play() + + def pause( self ): + self.playa.pause() + + def stop( self ): + self.playa.stop() + + def takeSnapshot( self ): + self.playa.takeSnapshot() diff --git a/src/jarabe/intro/window.py b/src/intro/intro.py index 3975900..342ce1d 100644 --- a/src/jarabe/intro/window.py +++ b/src/intro/intro.py @@ -15,50 +15,23 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os -import logging from gettext import gettext as _ -import gconf import gtk import gobject import hippo +import logging from sugar import env from sugar.graphics import style from sugar.graphics.icon import Icon from sugar.graphics.entry import CanvasEntry -from sugar.graphics.xocolor import XoColor +from sugar.profile import get_profile -from jarabe.intro import colorpicker +import colorpicker _BACKGROUND_COLOR = style.COLOR_WHITE -def create_profile(name, color=None, pixbuf=None): - if not pixbuf: - path = os.path.join(os.path.dirname(__file__), 'default-picture.png') - pixbuf = gtk.gdk.pixbuf_new_from_file(path) - - if not color: - color = XoColor() - - icon_path = os.path.join(env.get_profile_path(), "buddy-icon.jpg") - pixbuf.save(icon_path, "jpeg", {"quality":"85"}) - - client = gconf.client_get_default() - client.set_string("/desktop/sugar/user/nick", name) - client.set_string("/desktop/sugar/user/color", color.to_string()) - - # Generate keypair - import commands - keypath = os.path.join(env.get_profile_path(), "owner.key") - if not os.path.isfile(keypath): - cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % keypath - (s, o) = commands.getstatusoutput(cmd) - if s != 0: - logging.error("Could not generate key pair: %d %s" % (s, o)) - else: - logging.error("Keypair exists, skip generation.") - class _Page(hippo.CanvasBox): __gproperties__ = { 'valid' : (bool, None, None, False, @@ -137,7 +110,8 @@ class _ColorPage(_Page): class _IntroBox(hippo.CanvasBox): __gsignals__ = { 'done': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT])) + ([gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, + gobject.TYPE_PYOBJECT])) } PAGE_NAME = 0 @@ -232,10 +206,12 @@ class _IntroBox(hippo.CanvasBox): self.done() def done(self): + path = os.path.join(os.path.dirname(__file__), 'default-picture.png') + pixbuf = gtk.gdk.pixbuf_new_from_file(path) name = self._name_page.get_name() color = self._color_page.get_color() - self.emit('done', name, color) + self.emit('done', pixbuf, name, color) class IntroWindow(gtk.Window): def __init__(self): @@ -250,14 +226,32 @@ class IntroWindow(gtk.Window): self._canvas.show() self.connect('key-press-event', self.__key_press_cb) - def _done_cb(self, box, name, color): + def _done_cb(self, box, pixbuf, name, color): self.hide() - gobject.idle_add(self._create_profile_cb, name, color) + gobject.idle_add(self._create_profile, pixbuf, name, color) + + def _create_profile(self, pixbuf, name, color): + # Save the buddy icon + icon_path = os.path.join(env.get_profile_path(), "buddy-icon.jpg") + pixbuf.save(icon_path, "jpeg", {"quality":"85"}) + + profile = get_profile() + profile.nick_name = name + profile.color = color + profile.save() + + # Generate keypair + import commands + keypath = os.path.join(env.get_profile_path(), "owner.key") + if not os.path.isfile(keypath): + cmd = "ssh-keygen -q -t dsa -f %s -C '' -N ''" % keypath + (s, o) = commands.getstatusoutput(cmd) + if s != 0: + logging.error("Could not generate key pair: %d %s" % (s, o)) + else: + logging.error("Keypair exists, skip generation.") - def _create_profile_cb(self, name, color): - create_profile(name, color) gtk.main_quit() - return False def __key_press_cb(self, widget, event): diff --git a/src/jarabe/Makefile.am b/src/jarabe/Makefile.am deleted file mode 100644 index 42bf075..0000000 --- a/src/jarabe/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -SUBDIRS = \ - controlpanel \ - desktop \ - frame \ - journal \ - model \ - view \ - intro \ - util - -sugardir = $(pythondir)/jarabe -sugar_PYTHON = \ - __init__.py \ - config.py diff --git a/src/jarabe/desktop/Makefile.in b/src/jarabe/desktop/Makefile.in deleted file mode 100644 index 2975df2..0000000 --- a/src/jarabe/desktop/Makefile.in +++ /dev/null @@ -1,408 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = src/jarabe/desktop -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/desktop -sugar_PYTHON = \ - __init__.py \ - activitieslist.py \ - favoritesview.py \ - favoriteslayout.py \ - friendview.py \ - grid.py \ - groupbox.py \ - homebox.py \ - homewindow.py \ - keydialog.py \ - meshbox.py \ - myicon.py \ - proc_smaps.py \ - schoolserver.py \ - snowflakelayout.py \ - spreadlayout.py \ - transitionbox.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/desktop/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/desktop/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/jarabe/desktop/homewindow.py b/src/jarabe/desktop/homewindow.py deleted file mode 100644 index bbb0db1..0000000 --- a/src/jarabe/desktop/homewindow.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 - -import logging - -import gtk - -from sugar.graphics import style -from sugar.graphics import palettegroup - -from jarabe.desktop.meshbox import MeshBox -from jarabe.desktop.homebox import HomeBox -from jarabe.desktop.groupbox import GroupBox -from jarabe.desktop.transitionbox import TransitionBox -from jarabe.model.shell import ShellModel -from jarabe.model import shell - -_HOME_PAGE = 0 -_GROUP_PAGE = 1 -_MESH_PAGE = 2 -_TRANSITION_PAGE = 3 - -class HomeWindow(gtk.Window): - def __init__(self): - logging.debug('STARTUP: Loading the desktop window') - gtk.Window.__init__(self) - - accel_group = gtk.AccelGroup() - self.set_data('sugar-accel-group', accel_group) - self.add_accel_group(accel_group) - - self._active = False - - self.set_default_size(gtk.gdk.screen_width(), - gtk.gdk.screen_height()) - - self.realize() - self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP) - self.connect('visibility-notify-event', - self._visibility_notify_event_cb) - - self._home_box = HomeBox() - self._group_box = GroupBox() - self._mesh_box = MeshBox() - self._transition_box = TransitionBox() - - self.add(self._home_box) - self._home_box.show() - - self._transition_box.connect('completed', - self._transition_completed_cb) - - shell.get_model().zoom_level_changed.connect( - self.__zoom_level_changed_cb) - - def _deactivate_view(self, level): - group = palettegroup.get_group("default") - group.popdown() - if level == ShellModel.ZOOM_HOME: - self._home_box.suspend() - elif level == ShellModel.ZOOM_MESH: - self._mesh_box.suspend() - - def _activate_view(self, level): - if level == ShellModel.ZOOM_HOME: - self._home_box.resume() - elif level == ShellModel.ZOOM_MESH: - self._mesh_box.resume() - - def _visibility_notify_event_cb(self, window, event): - if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED: - self._deactivate_view() - else: - self._activate_view() - - def __zoom_level_changed_cb(self, **kwargs): - old_level = kwargs['old_level'] - new_level = kwargs['new_level'] - - self._deactivate_view(old_level) - self._activate_view(new_level) - - if old_level != ShellModel.ZOOM_ACTIVITY and \ - new_level != ShellModel.ZOOM_ACTIVITY: - self.remove(self.get_child()) - self.add(self._transition_box) - self._transition_box.show() - - if new_level == ShellModel.ZOOM_HOME: - end_size = style.XLARGE_ICON_SIZE - elif new_level == ShellModel.ZOOM_GROUP: - end_size = style.LARGE_ICON_SIZE - elif new_level == ShellModel.ZOOM_MESH: - end_size = style.STANDARD_ICON_SIZE - - if old_level == ShellModel.ZOOM_HOME: - start_size = style.XLARGE_ICON_SIZE - elif old_level == ShellModel.ZOOM_GROUP: - start_size = style.LARGE_ICON_SIZE - elif old_level == ShellModel.ZOOM_MESH: - start_size = style.STANDARD_ICON_SIZE - - self._transition_box.start_transition(start_size, end_size) - else: - self._update_view(new_level) - - def _transition_completed_cb(self, transition_box): - self._update_view(shell.get_model().zoom_level) - - def _update_view(self, level): - if level == ShellModel.ZOOM_ACTIVITY: - return - - current_child = self.get_child() - self.remove(current_child) - - if level == ShellModel.ZOOM_HOME: - self.add(self._home_box) - self._home_box.show() - self._home_box.focus_search_entry() - elif level == ShellModel.ZOOM_GROUP: - self.add(self._group_box) - self._group_box.show() - elif level == ShellModel.ZOOM_MESH: - self.add(self._mesh_box) - self._mesh_box.show() - self._mesh_box.focus_search_entry() - - def get_home_box(self): - return self._home_box diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py deleted file mode 100644 index d70f115..0000000 --- a/src/jarabe/desktop/meshbox.py +++ /dev/null @@ -1,854 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 gettext import gettext as _ -import logging -import sha - -import dbus -import hippo -import gobject -import gtk - -from sugar.graphics.icon import CanvasIcon, Icon -from sugar.graphics.xocolor import XoColor -from sugar.graphics import xocolor -from sugar.graphics import style -from sugar.graphics.icon import get_icon_state -from sugar.graphics import palette -from sugar.graphics import iconentry -from sugar.graphics.menuitem import MenuItem -from sugar.activity.activityhandle import ActivityHandle -from sugar.activity import activityfactory -from sugar.util import unique_id - -from jarabe.model import neighborhood -from jarabe.view.buddyicon import BuddyIcon -from jarabe.view.pulsingicon import CanvasPulsingIcon -from jarabe.desktop.snowflakelayout import SnowflakeLayout -from jarabe.desktop.spreadlayout import SpreadLayout -from jarabe.desktop import keydialog -from jarabe.model import bundleregistry -from jarabe.model import network -from jarabe.model.network import Settings -from jarabe.model.network import WirelessSecurity - -_NM_SERVICE = 'org.freedesktop.NetworkManager' -_NM_IFACE = 'org.freedesktop.NetworkManager' -_NM_PATH = '/org/freedesktop/NetworkManager' -_NM_DEVICE_IFACE = 'org.freedesktop.NetworkManager.Device' -_NM_WIRELESS_IFACE = 'org.freedesktop.NetworkManager.Device.Wireless' -_NM_ACCESSPOINT_IFACE = 'org.freedesktop.NetworkManager.AccessPoint' -_NM_ACTIVE_CONN_IFACE = 'org.freedesktop.NetworkManager.Connection.Active' - -_ICON_NAME = 'network-wireless' - -class AccessPointView(CanvasPulsingIcon): - def __init__(self, device, model): - CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE, - cache=True) - self._bus = dbus.SystemBus() - self._device = device - self._model = model - self._palette_icon = None - self._disconnect_item = None - self._connect_item = None - self._greyed_out = False - self._name = '' - self._strength = 0 - self._flags = 0 - self._wpa_flags = 0 - self._rsn_flags = 0 - self._mode = 0 - self._device_caps = 0 - self._device_state = None - self._connection = None - self._active = True - self._color = None - - self.connect('activated', self._activate_cb) - - pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), - style.COLOR_TRANSPARENT.get_svg())) - self.props.pulse_color = pulse_color - - self._palette = self._create_palette() - self.set_palette(self._palette) - - model_props = dbus.Interface(model, 'org.freedesktop.DBus.Properties') - model_props.GetAll(_NM_ACCESSPOINT_IFACE, byte_arrays=True, - reply_handler=self.__get_all_props_reply_cb, - error_handler=self.__get_all_props_error_cb) - - self._bus.add_signal_receiver(self.__ap_properties_changed_cb, - signal_name='PropertiesChanged', - path=model.object_path, - dbus_interface=_NM_ACCESSPOINT_IFACE) - - self._device.Get(_NM_DEVICE_IFACE, 'State', - reply_handler=self.__get_device_state_reply_cb, - error_handler=self.__get_device_state_error_cb) - self._device.Get(_NM_WIRELESS_IFACE, 'WirelessCapabilities', - reply_handler=self.__get_device_caps_reply_cb, - error_handler=self.__get_device_caps_error_cb) - self._device.Get(_NM_WIRELESS_IFACE, 'ActiveAccessPoint', - reply_handler=self.__get_active_ap_reply_cb, - error_handler=self.__get_active_ap_error_cb) - - self._bus.add_signal_receiver(self.__device_state_changed_cb, - signal_name='StateChanged', - path=device.object_path, - dbus_interface=_NM_DEVICE_IFACE) - self._bus.add_signal_receiver(self.__wireless_properties_changed_cb, - signal_name='PropertiesChanged', - path=device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) - - def _create_palette(self): - icon_name = get_icon_state(_ICON_NAME, self._strength) - self._palette_icon = Icon(icon_name=icon_name, - icon_size=style.STANDARD_ICON_SIZE, - badge_name=self.props.badge_name) - - p = palette.Palette(primary_text=self._name, - icon=self._palette_icon) - - self._connect_item = MenuItem(_('Connect'), 'dialog-ok') - self._connect_item.connect('activate', self._activate_cb) - p.menu.append(self._connect_item) - - self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject') - self._disconnect_item.connect('activate', - self._disconnect_activate_cb) - p.menu.append(self._disconnect_item) - - return p - - def __device_state_changed_cb(self, new_state, old_state, reason): - self._device_state = new_state - self._update_state() - - def __ap_properties_changed_cb(self, properties): - self._update_properties(properties) - - def __wireless_properties_changed_cb(self, properties): - if 'ActiveAccessPoint' in properties: - ap = properties['ActiveAccessPoint'] - self._active = (ap == self._model.object_path) - self._update_state() - - def _update_properties(self, properties): - if 'Ssid' in properties: - self._name = properties['Ssid'] - if 'Strength' in properties: - self._strength = properties['Strength'] - if 'Flags' in properties: - self._flags = properties['Flags'] - if 'WpaFlags' in properties: - self._wpa_flags = properties['WpaFlags'] - if 'RsnFlags' in properties: - self._rsn_flags = properties['RsnFlags'] - if 'Mode' in properties: - self._mode = properties['Mode'] - - sh = sha.new() - data = self._name + hex(self._flags) - sh.update(data) - h = hash(sh.digest()) - idx = h % len(xocolor.colors) - - self._color = XoColor('%s,%s' % (xocolor.colors[idx][0], - xocolor.colors[idx][1])) - - self._update() - - def __get_active_ap_reply_cb(self, ap): - self._active = (ap == self._model.object_path) - self._update_state() - - def __get_active_ap_error_cb(self, err): - logging.debug('Error getting the active access point: %s', err) - - def __get_device_caps_reply_cb(self, caps): - self._device_caps = caps - - def __get_device_caps_error_cb(self, err): - logging.debug('Error getting the wireless device properties: %s', err) - - def __get_device_state_reply_cb(self, state): - self._device_state = state - self._update() - - def __get_device_state_error_cb(self, err): - logging.debug('Error getting the access point properties: %s', err) - - def __get_all_props_reply_cb(self, properties): - self._update_properties(properties) - - def __get_all_props_error_cb(self, err): - logging.debug('Error getting the access point properties: %s', err) - - def _update(self): - if self._flags == network.NM_802_11_AP_FLAGS_PRIVACY: - self.props.badge_name = "emblem-locked" - self._palette_icon.props.badge_name = "emblem-locked" - else: - self.props.badge_name = None - self._palette_icon.props.badge_name = None - - self._palette.props.primary_text = self._name - - self._update_state() - self._update_color() - - def _update_state(self): - if self._active: - state = self._device_state - else: - state = network.DEVICE_STATE_UNKNOWN - - if state == network.DEVICE_STATE_ACTIVATED: - icon_name = '%s-connected' % _ICON_NAME - else: - icon_name = _ICON_NAME - - icon_name = get_icon_state(icon_name, self._strength) - if icon_name: - self.props.icon_name = icon_name - icon = self._palette.props.icon - icon.props.icon_name = icon_name - - if state == network.DEVICE_STATE_PREPARE or \ - state == network.DEVICE_STATE_CONFIG or \ - state == network.DEVICE_STATE_NEED_AUTH or \ - state == network.DEVICE_STATE_IP_CONFIG: - if self._disconnect_item: - self._disconnect_item.show() - self._connect_item.hide() - self._palette.props.secondary_text = _('Connecting...') - self.props.pulsing = True - elif state == network.DEVICE_STATE_ACTIVATED: - if self._disconnect_item: - self._disconnect_item.show() - self._connect_item.hide() - self._palette.props.secondary_text = _('Connected') - self.props.pulsing = False - else: - if self._disconnect_item: - self._disconnect_item.hide() - self._connect_item.show() - self._palette.props.secondary_text = None - self.props.pulsing = False - - def _update_color(self): - if self._greyed_out: - self.props.pulsing = False - self.props.base_color = XoColor('#D5D5D5,#D5D5D5') - else: - self.props.base_color = self._color - - self._palette_icon.props.xo_color = self._color - - def _disconnect_activate_cb(self, item): - pass - - - def _add_ciphers_from_flags(self, flags, pairwise): - ciphers = [] - if pairwise: - if flags & network.NM_802_11_AP_SEC_PAIR_TKIP: - ciphers.append("tkip") - if flags & network.NM_802_11_AP_SEC_PAIR_CCMP: - ciphers.append("ccmp") - else: - if flags & network.NM_802_11_AP_SEC_GROUP_WEP40: - ciphers.append("wep40") - if flags & network.NM_802_11_AP_SEC_GROUP_WEP104: - ciphers.append("wep104") - if flags & network.NM_802_11_AP_SEC_GROUP_TKIP: - ciphers.append("tkip") - if flags & network.NM_802_11_AP_SEC_GROUP_CCMP: - ciphers.append("ccmp") - return ciphers - - def _get_security(self): - if not (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ - (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ - (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): - # No security - return None - - if (self._flags & network.NM_802_11_AP_FLAGS_PRIVACY) and \ - (self._wpa_flags == network.NM_802_11_AP_SEC_NONE) and \ - (self._rsn_flags == network.NM_802_11_AP_SEC_NONE): - # Static WEP, Dynamic WEP, or LEAP - wireless_security = WirelessSecurity() - wireless_security.key_mgmt = 'none' - return wireless_security - - if (self._mode != network.NM_802_11_MODE_INFRA): - # Stuff after this point requires infrastructure - logging.error('The infrastructure mode is not supoorted' - ' by your wireless device.') - return None - - if (self._rsn_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ - (self._device_caps & network.NM_802_11_DEVICE_CAP_RSN): - # WPA2 PSK first - pairwise = self._add_ciphers_from_flags(self._rsn_flags, True) - group = self._add_ciphers_from_flags(self._rsn_flags, False) - wireless_security = WirelessSecurity() - wireless_security.key_mgmt = 'wpa-psk' - wireless_security.proto = 'rsn' - wireless_security.pairwise = pairwise - wireless_security.group = group - return wireless_security - - if (self._wpa_flags & network.NM_802_11_AP_SEC_KEY_MGMT_PSK) and \ - (self._device_caps & network.NM_802_11_DEVICE_CAP_WPA): - # WPA PSK - pairwise = self._add_ciphers_from_flags(self._wpa_flags, True) - group = self._add_ciphers_from_flags(self._wpa_flags, False) - wireless_security = WirelessSecurity() - wireless_security.key_mgmt = 'wpa-psk' - wireless_security.proto = 'wpa' - wireless_security.pairwise = pairwise - wireless_security.group = group - return wireless_security - - def _activate_cb(self, icon): - connection = network.find_connection(self._name) - if connection is None: - settings = Settings() - settings.connection.id = 'Auto ' + self._name - settings.connection.uuid = unique_id() - settings.connection.type = '802-11-wireless' - settings.wireless.ssid = self._name - - wireless_security = self._get_security() - settings.wireless_security = wireless_security - - connection = network.add_connection(self._name, settings) - - if wireless_security is None: - self._connection = connection - - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - netmgr = dbus.Interface(obj, _NM_IFACE) - - netmgr.ActivateConnection(network.SETTINGS_SERVICE, connection.path, - self._device.object_path, - self._model.object_path, - reply_handler=self.__activate_reply_cb, - error_handler=self.__activate_error_cb) - - def __activate_reply_cb(self, connection): - if self._connection: - self._connection.save() - logging.debug('Connection activated: %s', connection) - - def __activate_error_cb(self, err): - logging.debug('Failed to activate connection: %s', err) - - def set_filter(self, query): - self._greyed_out = self._name.lower().find(query) == -1 - self._update_state() - self._update_color() - - def create_keydialog(self, response): - keydialog.create(self._name, self._flags, self._wpa_flags, - self._rsn_flags, self._device_caps, response) - - def disconnect(self): - self._bus.remove_signal_receiver(self.__ap_properties_changed_cb, - signal_name='PropertiesChanged', - path=self._model.object_path, - dbus_interface=_NM_ACCESSPOINT_IFACE) - - self._bus.remove_signal_receiver(self.__device_state_changed_cb, - signal_name='StateChanged', - path=self._device.object_path, - dbus_interface=_NM_DEVICE_IFACE) - self._bus.remove_signal_receiver(self.__wireless_properties_changed_cb, - signal_name='PropertiesChanged', - path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) - -class ActivityView(hippo.CanvasBox): - def __init__(self, model): - hippo.CanvasBox.__init__(self) - - self._model = model - self._icons = {} - self._palette = None - - self._layout = SnowflakeLayout() - self.set_layout(self._layout) - - self._icon = self._create_icon() - self._layout.add(self._icon, center=True) - - self._update_palette() - - activity = self._model.activity - activity.connect('notify::name', self._name_changed_cb) - activity.connect('notify::color', self._color_changed_cb) - activity.connect('notify::private', self._private_changed_cb) - activity.connect('joined', self._joined_changed_cb) - #FIXME: 'joined' signal not working, see #5032 - - def _create_icon(self): - icon = CanvasIcon(file_name=self._model.get_icon_name(), - xo_color=self._model.get_color(), cache=True, - size=style.STANDARD_ICON_SIZE) - icon.connect('activated', self._clicked_cb) - return icon - - def _create_palette(self): - p_icon = Icon(file=self._model.get_icon_name(), - xo_color=self._model.get_color()) - p_icon.props.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR - p = palette.Palette(None, primary_text=self._model.activity.props.name, - icon=p_icon) - - private = self._model.activity.props.private - joined = self._model.activity.props.joined - - if joined: - item = MenuItem(_('Resume'), 'activity-start') - item.connect('activate', self._clicked_cb) - item.show() - p.menu.append(item) - elif not private: - item = MenuItem(_('Join'), 'activity-start') - item.connect('activate', self._clicked_cb) - item.show() - p.menu.append(item) - - return p - - def _update_palette(self): - self._palette = self._create_palette() - self._icon.set_palette(self._palette) - - def has_buddy_icon(self, key): - return self._icons.has_key(key) - - def add_buddy_icon(self, key, icon): - self._icons[key] = icon - self._layout.add(icon) - - def remove_buddy_icon(self, key): - icon = self._icons[key] - del self._icons[key] - icon.destroy() - - def _clicked_cb(self, item): - bundle_id = self._model.get_bundle_id() - - handle = ActivityHandle(self._model.get_id()) - - bundle = bundleregistry.get_registry().get_bundle(bundle_id) - activityfactory.create(bundle, handle) - - def set_filter(self, query): - text_to_check = self._model.activity.props.name.lower() + \ - self._model.activity.props.type.lower() - if text_to_check.find(query) == -1: - self._icon.props.stroke_color = '#D5D5D5' - self._icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg() - else: - self._icon.props.xo_color = self._model.get_color() - - for icon in self._icons.itervalues(): - if hasattr(icon, 'set_filter'): - icon.set_filter(query) - - def _name_changed_cb(self, activity, pspec): - self._update_palette() - - def _color_changed_cb(self, activity, pspec): - self._layout.remove(self._icon) - self._icon = self._create_icon() - self._layout.add(self._icon, center=True) - self._icon.set_palette(self._palette) - - def _private_changed_cb(self, activity, pspec): - self._update_palette() - - def _joined_changed_cb(self, widget, event): - logging.debug('ActivityView._joined_changed_cb') - -_AUTOSEARCH_TIMEOUT = 1000 - -class MeshToolbar(gtk.Toolbar): - __gtype_name__ = 'MeshToolbar' - - __gsignals__ = { - 'query-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([str])) - } - - def __init__(self): - gtk.Toolbar.__init__(self) - - self._query = None - self._autosearch_timer = None - - self._add_separator() - - tool_item = gtk.ToolItem() - self.insert(tool_item, -1) - tool_item.show() - - self.search_entry = iconentry.IconEntry() - self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, - 'system-search') - self.search_entry.add_clear_button() - self.search_entry.set_width_chars(25) - self.search_entry.connect('activate', self._entry_activated_cb) - self.search_entry.connect('changed', self._entry_changed_cb) - tool_item.add(self.search_entry) - self.search_entry.show() - - self._add_separator(expand=True) - - def _add_separator(self, expand=False): - separator = gtk.SeparatorToolItem() - separator.props.draw = False - if expand: - separator.set_expand(True) - else: - separator.set_size_request(style.GRID_CELL_SIZE, - style.GRID_CELL_SIZE) - self.insert(separator, -1) - separator.show() - - def _entry_activated_cb(self, entry): - if self._autosearch_timer: - gobject.source_remove(self._autosearch_timer) - new_query = entry.props.text - if self._query != new_query: - self._query = new_query - self.emit('query-changed', self._query) - - def _entry_changed_cb(self, entry): - if not entry.props.text: - entry.activate() - return - - if self._autosearch_timer: - gobject.source_remove(self._autosearch_timer) - self._autosearch_timer = gobject.timeout_add(_AUTOSEARCH_TIMEOUT, - self._autosearch_timer_cb) - - def _autosearch_timer_cb(self): - logging.debug('_autosearch_timer_cb') - self._autosearch_timer = None - self.search_entry.activate() - return False - -class DeviceObserver(object): - def __init__(self, box, device): - self._box = box - self._bus = dbus.SystemBus() - self._device = device - - wireless = dbus.Interface(self._device, _NM_WIRELESS_IFACE) - wireless.GetAccessPoints(reply_handler=self._get_access_points_reply_cb, - error_handler=self._get_access_points_error_cb) - - self._bus.add_signal_receiver(self.__access_point_added_cb, - signal_name='AccessPointAdded', - path=device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) - self._bus.add_signal_receiver(self.__access_point_removed_cb, - signal_name='AccessPointRemoved', - path=device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) - - def _get_access_points_reply_cb(self, access_points_o): - for ap_o in access_points_o: - ap = self._bus.get_object(_NM_SERVICE, ap_o) - self._box.add_access_point(self._device, ap) - - def _get_access_points_error_cb(self, err): - logging.error('Failed to get access points: %s', err) - - def __access_point_added_cb(self, access_point_o): - ap = self._bus.get_object(_NM_SERVICE, access_point_o) - self._box.add_access_point(self._device, ap) - - def __access_point_removed_cb(self, access_point_o): - self._box.remove_access_point(access_point_o) - - def disconnect(self): - self._bus.remove_signal_receiver(self.__access_point_added_cb, - signal_name='AccessPointAdded', - path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) - self._bus.remove_signal_receiver(self.__access_point_removed_cb, - signal_name='AccessPointRemoved', - path=self._device.object_path, - dbus_interface=_NM_WIRELESS_IFACE) - -class NetworkManagerObserver(object): - def __init__(self, box): - self._box = box - self._bus = dbus.SystemBus() - self._devices = {} - self._netmgr = None - - def listen(self): - try: - obj = self._bus.get_object(_NM_SERVICE, _NM_PATH) - self._netmgr = dbus.Interface(obj, _NM_IFACE) - except dbus.DBusException: - logging.debug('%s service not available', _NM_SERVICE) - return - - self._netmgr.GetDevices(reply_handler=self.__get_devices_reply_cb, - error_handler=self.__get_devices_error_cb) - - self._bus.add_signal_receiver(self.__device_added_cb, - signal_name='DeviceAdded', - dbus_interface=_NM_IFACE) - self._bus.add_signal_receiver(self.__device_removed_cb, - signal_name='DeviceRemoved', - dbus_interface=_NM_IFACE) - - settings = network.get_settings() - if settings is not None: - settings.secrets_request.connect(self.__secrets_request_cb) - - def __secrets_request_cb(self, **kwargs): - # FIXME It would be better to do all of this async, but I cannot think - # of a good way to. NM could really use some love here. - - netmgr_props = dbus.Interface( - self._netmgr, 'org.freedesktop.DBus.Properties') - active_connections_o = netmgr_props.Get(_NM_IFACE, 'ActiveConnections') - - for conn_o in active_connections_o: - obj = self._bus.get_object(_NM_IFACE, conn_o) - props = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') - ap_o = props.Get(_NM_ACTIVE_CONN_IFACE, 'SpecificObject') - - ap_view = self._box.access_points[ap_o] - ap_view.create_keydialog(kwargs['response']) - - def __get_devices_reply_cb(self, devices_o): - for dev_o in devices_o: - self._check_device(dev_o) - - def __get_devices_error_cb(self, err): - logging.error('Failed to get devices: %s', err) - - def _check_device(self, device_o): - device = self._bus.get_object(_NM_SERVICE, device_o) - props = dbus.Interface(device, 'org.freedesktop.DBus.Properties') - - device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType') - if device_type == network.DEVICE_TYPE_802_11_WIRELESS: - self._devices[device_o] = DeviceObserver(self._box, device) - - def _get_device_path_error_cb(self, err): - logging.error('Failed to get device type: %s', err) - - def __device_added_cb(self, device_o): - self._check_device(device_o) - - def __device_removed_cb(self, device_o): - if device_o in self._devices: - observer = self._devices[device_o] - observer.disconnect() - del self._devices[device_o] - -class MeshBox(gtk.VBox): - __gtype_name__ = 'SugarMeshBox' - - def __init__(self): - logging.debug("STARTUP: Loading the mesh view") - - gobject.GObject.__init__(self) - - self.access_points = {} - - self._model = neighborhood.get_model() - self._buddies = {} - self._activities = {} - self._mesh = {} - self._buddy_to_activity = {} - self._suspended = True - self._query = '' - self._owner_icon = None - - self._toolbar = MeshToolbar() - self._toolbar.connect('query-changed', self._toolbar_query_changed_cb) - self.pack_start(self._toolbar, expand=False) - self._toolbar.show() - - canvas = hippo.Canvas() - self.add(canvas) - canvas.show() - - self._layout_box = hippo.CanvasBox( \ - background_color=style.COLOR_WHITE.get_int()) - canvas.set_root(self._layout_box) - - self._layout = SpreadLayout() - self._layout_box.set_layout(self._layout) - - for buddy_model in self._model.get_buddies(): - self._add_alone_buddy(buddy_model) - - self._model.connect('buddy-added', self._buddy_added_cb) - self._model.connect('buddy-removed', self._buddy_removed_cb) - self._model.connect('buddy-moved', self._buddy_moved_cb) - - for activity_model in self._model.get_activities(): - self._add_activity(activity_model) - - self._model.connect('activity-added', self._activity_added_cb) - self._model.connect('activity-removed', self._activity_removed_cb) - - netmgr_observer = NetworkManagerObserver(self) - netmgr_observer.listen() - - def do_size_allocate(self, allocation): - width = allocation.width - height = allocation.height - - min_w_, icon_width = self._owner_icon.get_width_request() - min_h_, icon_height = self._owner_icon.get_height_request(icon_width) - x = (width - icon_width) / 2 - y = (height - icon_height) / 2 - style.GRID_CELL_SIZE - self._layout.move(self._owner_icon, x, y) - - gtk.VBox.do_size_allocate(self, allocation) - - def _buddy_added_cb(self, model, buddy_model): - self._add_alone_buddy(buddy_model) - - def _buddy_removed_cb(self, model, buddy_model): - self._remove_buddy(buddy_model) - - def _buddy_moved_cb(self, model, buddy_model, activity_model): - # Owner doesn't move from the center - if buddy_model.is_owner(): - return - self._move_buddy(buddy_model, activity_model) - - def _activity_added_cb(self, model, activity_model): - self._add_activity(activity_model) - - def _activity_removed_cb(self, model, activity_model): - self._remove_activity(activity_model) - - def _add_alone_buddy(self, buddy_model): - icon = BuddyIcon(buddy_model) - if buddy_model.is_owner(): - self._owner_icon = icon - self._layout.add(icon) - - if hasattr(icon, 'set_filter'): - icon.set_filter(self._query) - - self._buddies[buddy_model.get_buddy().object_path()] = icon - - def _remove_alone_buddy(self, buddy_model): - icon = self._buddies[buddy_model.get_buddy().object_path()] - self._layout.remove(icon) - del self._buddies[buddy_model.get_buddy().object_path()] - icon.destroy() - - def _remove_buddy(self, buddy_model): - object_path = buddy_model.get_buddy().object_path() - if self._buddies.has_key(object_path): - self._remove_alone_buddy(buddy_model) - else: - for activity in self._activities.values(): - if activity.has_buddy_icon(object_path): - activity.remove_buddy_icon(object_path) - - def _move_buddy(self, buddy_model, activity_model): - self._remove_buddy(buddy_model) - - if activity_model == None: - self._add_alone_buddy(buddy_model) - elif activity_model.get_id() in self._activities: - activity = self._activities[activity_model.get_id()] - - icon = BuddyIcon(buddy_model, style.STANDARD_ICON_SIZE) - activity.add_buddy_icon(buddy_model.get_buddy().object_path(), icon) - - if hasattr(icon, 'set_filter'): - icon.set_filter(self._query) - - def _add_activity(self, activity_model): - icon = ActivityView(activity_model) - self._layout.add(icon) - - if hasattr(icon, 'set_filter'): - icon.set_filter(self._query) - - self._activities[activity_model.get_id()] = icon - - def _remove_activity(self, activity_model): - icon = self._activities[activity_model.get_id()] - self._layout.remove(icon) - del self._activities[activity_model.get_id()] - icon.destroy() - - def add_access_point(self, device, ap): - icon = AccessPointView(device, ap) - self._layout.add(icon) - - if hasattr(icon, 'set_filter'): - icon.set_filter(self._query) - - self.access_points[ap.object_path] = icon - - def remove_access_point(self, ap_o): - if ap_o in self.access_points: - icon = self.access_points[ap_o] - icon.disconnect() - self._layout.remove(icon) - del self.access_points[ap_o] - else: - logging.error('Can not remove access point %s' % ap_o) - - def suspend(self): - if not self._suspended: - self._suspended = True - for ap in self.access_points.values(): - ap.props.paused = True - - def resume(self): - if self._suspended: - self._suspended = False - for ap in self.access_points.values(): - ap.props.paused = False - - def _toolbar_query_changed_cb(self, toolbar, query): - self._query = query.lower() - for icon in self._layout_box.get_children(): - if hasattr(icon, 'set_filter'): - icon.set_filter(self._query) - - def focus_search_entry(self): - self._toolbar.search_entry.grab_focus() diff --git a/src/jarabe/frame/clipboard.py b/src/jarabe/frame/clipboard.py deleted file mode 100644 index 0e3e125..0000000 --- a/src/jarabe/frame/clipboard.py +++ /dev/null @@ -1,149 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# 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 - -import logging -import os -import shutil -import urlparse -import tempfile - -import gobject - -from sugar import mime - -from jarabe.frame.clipboardobject import ClipboardObject, Format - -class Clipboard(gobject.GObject): - - __gsignals__ = { - 'object-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([object])), - 'object-deleted': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([int])), - 'object-state-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([object])) - } - - def __init__(self): - gobject.GObject.__init__(self) - - self._objects = {} - self._next_id = 0 - - def _get_next_object_id(self): - self._next_id += 1 - return self._next_id - - def add_object(self, name): - logging.debug('Clipboard.add_object') - object_id = self._get_next_object_id() - self._objects[object_id] = ClipboardObject(object_id, name) - self.emit('object-added', self._objects[object_id]) - return object_id - - def add_object_format(self, object_id, format_type, data, on_disk): - logging.debug('Clipboard.add_object_format') - cb_object = self._objects[object_id] - - if format_type == 'XdndDirectSave0': - format = Format('text/uri-list', data + '\r\n', on_disk) - format.owns_disk_data = True - cb_object.add_format(format) - elif on_disk and cb_object.get_percent() == 100: - new_uri = self._copy_file(data) - cb_object.add_format(Format(format_type, new_uri, on_disk)) - logging.debug('Added format of type ' + format_type - + ' with path at ' + new_uri) - else: - cb_object.add_format(Format(format_type, data, on_disk)) - logging.debug('Added in-memory format of type ' + format_type + '.') - - self.emit('object-state-changed', cb_object) - - def delete_object(self, object_id): - cb_object = self._objects.pop(object_id) - cb_object.destroy() - self.emit('object-deleted', object_id) - logging.debug('Deleted object with object_id %r' % object_id) - - def set_object_percent(self, object_id, percent): - cb_object = self._objects[object_id] - if percent < 0 or percent > 100: - raise ValueError("invalid percentage") - if cb_object.get_percent() > percent: - raise ValueError("invalid percentage; less than current percent") - if cb_object.get_percent() == percent: - # ignore setting same percentage - return - - cb_object.set_percent(percent) - - if percent == 100: - self._process_object(cb_object) - - self.emit('object-state-changed', cb_object) - - def _process_object(self, cb_object): - formats = cb_object.get_formats() - for format_name, format in formats.iteritems(): - if format.is_on_disk() and not format.owns_disk_data: - new_uri = self._copy_file(format.get_data()) - format.set_data(new_uri) - - # Add a text/plain format to objects that are text but lack it - if 'text/plain' not in formats.keys(): - if 'UTF8_STRING' in formats.keys(): - self.add_object_format( - cb_object.get_id(), 'text/plain', - data=formats['UTF8_STRING'].get_data(), on_disk=False) - elif 'text/unicode' in formats.keys(): - self.add_object_format( - cb_object.get_id(), 'text/plain', - data=formats['UTF8_STRING'].get_data(), on_disk=False) - - def get_object(self, object_id): - logging.debug('Clipboard.get_object') - return self._objects[object_id] - - def get_object_data(self, object_id, format_type): - logging.debug('Clipboard.get_object_data') - cb_object = self._objects[object_id] - format = cb_object.get_formats()[format_type] - return format - - def _copy_file(self, original_uri): - uri = urlparse.urlparse(original_uri) - path_, file_name = os.path.split(uri.path) - - root, ext = os.path.splitext(file_name) - if not ext or ext == '.': - mime_type = mime.get_for_file(uri.path) - ext = '.' + mime.get_primary_extension(mime_type) - - f_, new_file_path = tempfile.mkstemp(ext, root) - del f_ - shutil.copyfile(uri.path, new_file_path) - os.chmod(new_file_path, 0644) - - return 'file://' + new_file_path - -_instance = None - -def get_instance(): - global _instance - if not _instance: - _instance = Clipboard() - return _instance diff --git a/src/jarabe/frame/devicestray.py b/src/jarabe/frame/devicestray.py deleted file mode 100644 index 47a7bf5..0000000 --- a/src/jarabe/frame/devicestray.py +++ /dev/null @@ -1,53 +0,0 @@ -# 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 - -import os -import sys -import traceback -import logging - -from sugar.graphics import tray - -from jarabe import config - -class DevicesTray(tray.HTray): - def __init__(self): - tray.HTray.__init__(self, align=tray.ALIGN_TO_END) - - for f in os.listdir(os.path.join(config.ext_path, 'deviceicon')): - if f.endswith('.py') and not f.startswith('__'): - module_name = f[:-3] - try: - mod = __import__('deviceicon.' + module_name, globals(), - locals(), [module_name]) - mod.setup(self) - except Exception: - logging.error('Exception while loading extension:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - - def add_device(self, view): - index = 0 - relative_index = getattr(view, "FRAME_POSITION_RELATIVE", -1) - for item in self.get_children(): - current_relative_index = getattr(item, "FRAME_POSITION_RELATIVE", 0) - if current_relative_index >= relative_index: - break - index += 1 - self.add_item(view, index=index) - view.show() - - def remove_device(self, view): - self.remove_item(view) diff --git a/src/jarabe/intro/Makefile.am b/src/jarabe/intro/Makefile.am deleted file mode 100644 index a9fb96b..0000000 --- a/src/jarabe/intro/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -imagedir = $(pythondir)/jarabe/intro -image_DATA = default-picture.png - -EXTRA_DIST = $(conf_DATA) $(image_DATA) -sugardir = $(pythondir)/jarabe/intro -sugar_PYTHON = \ - __init__.py \ - colorpicker.py \ - window.py diff --git a/src/jarabe/intro/__init__.py b/src/jarabe/intro/__init__.py deleted file mode 100644 index 204f686..0000000 --- a/src/jarabe/intro/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -import os - -import gtk - -from sugar import env -from sugar.profile import get_profile - -from jarabe.intro.window import IntroWindow -from jarabe.intro.window import create_profile - -def check_profile(): - profile = get_profile() - - path = os.path.join(env.get_profile_path(), 'config') - if os.path.exists(path): - profile.convert_profile() - - if not profile.is_valid(): - win = IntroWindow() - win.show_all() - gtk.main() diff --git a/src/jarabe/journal/Makefile.am b/src/jarabe/journal/Makefile.am deleted file mode 100644 index a8ef90f..0000000 --- a/src/jarabe/journal/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -sugardir = $(pythondir)/jarabe/journal -sugar_PYTHON = \ - __init__.py \ - collapsedentry.py \ - detailview.py \ - expandedentry.py \ - journalactivity.py \ - journalentrybundle.py \ - journaltoolbox.py \ - keepicon.py \ - listview.py \ - misc.py \ - modalalert.py \ - objectchooser.py \ - palettes.py \ - query.py \ - volumestoolbar.py diff --git a/src/jarabe/journal/__init__.py b/src/jarabe/journal/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/src/jarabe/journal/__init__.py +++ /dev/null diff --git a/src/jarabe/journal/collapsedentry.py b/src/jarabe/journal/collapsedentry.py deleted file mode 100644 index c2cc9c8..0000000 --- a/src/jarabe/journal/collapsedentry.py +++ /dev/null @@ -1,383 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging -from gettext import gettext as _ - -import gobject -import gtk -import hippo -import cjson - -from sugar.graphics.icon import CanvasIcon -from sugar.graphics.xocolor import XoColor -from sugar.graphics import style -from sugar.datastore import datastore -from sugar.graphics.entry import CanvasEntry - -from jarabe.journal.keepicon import KeepIcon -from jarabe.journal.palettes import ObjectPalette, BuddyPalette -from jarabe.journal import misc - -class BuddyIcon(CanvasIcon): - def __init__(self, buddy, **kwargs): - CanvasIcon.__init__(self, **kwargs) - self._buddy = buddy - - def create_palette(self): - return BuddyPalette(self._buddy) - -class BuddyList(hippo.CanvasBox): - def __init__(self, model, width): - hippo.CanvasBox.__init__(self, - orientation=hippo.ORIENTATION_HORIZONTAL, - box_width=width, - xalign=hippo.ALIGNMENT_START) - self.set_model(model) - - def set_model(self, model): - for item in self.get_children(): - self.remove(item) - - for buddy in model[0:3]: - nick_, color = buddy - icon = BuddyIcon(buddy, - icon_name='computer-xo', - xo_color=XoColor(color), - cache=True) - self.append(icon) - -class EntryIcon(CanvasIcon): - def __init__(self, **kwargs): - CanvasIcon.__init__(self, **kwargs) - self._jobject = None - - def set_jobject(self, jobject): - self._jobject = jobject - self.props.file_name = misc.get_icon_name(jobject) - self.palette = None - - def create_palette(self): - if self.show_palette: - return ObjectPalette(self._jobject) - else: - return None - - show_palette = gobject.property(type=bool, default=False) - -class BaseCollapsedEntry(hippo.CanvasBox): - __gtype_name__ = 'BaseCollapsedEntry' - - _DATE_COL_WIDTH = style.GRID_CELL_SIZE * 3 - _BUDDIES_COL_WIDTH = style.GRID_CELL_SIZE * 3 - _PROGRESS_COL_WIDTH = style.GRID_CELL_SIZE * 5 - - def __init__(self): - hippo.CanvasBox.__init__(self, - spacing=style.DEFAULT_SPACING, - padding_top=style.DEFAULT_PADDING, - padding_bottom=style.DEFAULT_PADDING, - padding_left=style.DEFAULT_PADDING * 2, - padding_right=style.DEFAULT_PADDING * 2, - box_height=style.GRID_CELL_SIZE, - orientation=hippo.ORIENTATION_HORIZONTAL) - - self._jobject = None - self._is_selected = False - - self.keep_icon = self._create_keep_icon() - self.append(self.keep_icon) - - self.icon = self._create_icon() - self.append(self.icon) - - self.title = self._create_title() - self.append(self.title, hippo.PACK_EXPAND) - - self.buddies_list = self._create_buddies_list() - self.append(self.buddies_list) - - self.date = self._create_date() - self.append(self.date) - - # Progress controls - self.progress_bar = self._create_progress_bar() - self.append(self.progress_bar) - - self.cancel_button = self._create_cancel_button() - self.append(self.cancel_button) - - def _create_keep_icon(self): - keep_icon = KeepIcon(False) - keep_icon.connect('button-release-event', - self.__keep_icon_button_release_event_cb) - return keep_icon - - def _create_date(self): - date = hippo.CanvasText(text='', - xalign=hippo.ALIGNMENT_START, - font_desc=style.FONT_NORMAL.get_pango_desc(), - box_width=self._DATE_COL_WIDTH) - return date - - def _create_icon(self): - icon = EntryIcon(size=style.STANDARD_ICON_SIZE, cache=True) - return icon - - def _create_title(self): - # TODO: We'd prefer to ellipsize in the middle - title = hippo.CanvasText(text='', - xalign=hippo.ALIGNMENT_START, - font_desc=style.FONT_BOLD.get_pango_desc(), - size_mode=hippo.CANVAS_SIZE_ELLIPSIZE_END) - return title - - def _create_buddies_list(self): - return BuddyList([], self._BUDDIES_COL_WIDTH) - - def _create_progress_bar(self): - progress_bar = gtk.ProgressBar() - return hippo.CanvasWidget(widget=progress_bar, - yalign=hippo.ALIGNMENT_CENTER, - box_width=self._PROGRESS_COL_WIDTH) - - def _create_cancel_button(self): - button = CanvasIcon(icon_name='activity-stop', - size=style.SMALL_ICON_SIZE, - box_width=style.GRID_CELL_SIZE) - button.connect('button-release-event', - self._cancel_button_release_event_cb) - return button - - def _decode_buddies(self): - if self.jobject.metadata.has_key('buddies') and \ - self.jobject.metadata['buddies']: - buddies = cjson.decode(self._jobject.metadata['buddies']).values() - else: - buddies = [] - return buddies - - def update_visibility(self): - in_process = self.is_in_progress() - - self.buddies_list.set_visible(not in_process) - self.date.set_visible(not in_process) - - self.progress_bar.set_visible(in_process) - self.cancel_button.set_visible(in_process) - - # TODO: determine the appearance of in-progress entries - def _update_color(self): - if self.is_in_progress(): - self.props.background_color = style.COLOR_WHITE.get_int() - else: - self.props.background_color = style.COLOR_WHITE.get_int() - - def is_in_progress(self): - return self._jobject.metadata.has_key('progress') and \ - int(self._jobject.metadata['progress']) < 100 - - def get_keep(self): - keep = int(self._jobject.metadata.get('keep', 0)) - return keep == 1 - - def __keep_icon_button_release_event_cb(self, button, event): - logging.debug('__keep_icon_button_release_event_cb') - jobject = datastore.get(self._jobject.object_id) - try: - if self.get_keep(): - jobject.metadata['keep'] = 0 - else: - jobject.metadata['keep'] = 1 - datastore.write(jobject, update_mtime=False) - finally: - jobject.destroy() - - self.keep_icon.props.keep = self.get_keep() - self._update_color() - - return True - - def _cancel_button_release_event_cb(self, button, event): - logging.debug('_cancel_button_release_event_cb') - datastore.delete(self._jobject.object_id) - return True - - def set_selected(self, is_selected): - self._is_selected = is_selected - self._update_color() - - def set_jobject(self, jobject): - self._jobject = jobject - self._is_selected = False - - self.keep_icon.props.keep = self.get_keep() - - self.date.props.text = misc.get_date(jobject) - - self.icon.set_jobject(jobject) - if jobject.is_activity_bundle(): - self.icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg() - self.icon.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() - else: - if jobject.metadata.has_key('icon-color') and \ - jobject.metadata['icon-color']: - self.icon.props.xo_color = XoColor( \ - jobject.metadata['icon-color']) - else: - self.icon.props.xo_color = None - - if jobject.metadata.get('title', ''): - title_text = jobject.metadata['title'] - else: - title_text = _('Untitled') - self.title.props.text = title_text - - self.buddies_list.set_model(self._decode_buddies()) - - if jobject.metadata.has_key('progress'): - self.progress_bar.props.widget.props.fraction = \ - int(jobject.metadata['progress']) / 100.0 - - self.update_visibility() - self._update_color() - - def get_jobject(self): - return self._jobject - - jobject = property(get_jobject, set_jobject) - - def update_date(self): - self.date.props.text = misc.get_date(self._jobject) - -class CollapsedEntry(BaseCollapsedEntry): - __gtype_name__ = 'CollapsedEntry' - - __gsignals__ = { - 'detail-clicked': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([])) - } - - def __init__(self): - BaseCollapsedEntry.__init__(self) - - self.icon.props.show_palette = True - self.icon.connect('button-release-event', - self.__icon_button_release_event_cb) - - self.title.connect('button_release_event', - self.__title_button_release_event_cb) - - self._title_entry = self._create_title_entry() - self.insert_after(self._title_entry, self.title, hippo.PACK_EXPAND) - self._title_entry.set_visible(False) - - self._detail_button = self._create_detail_button() - self._detail_button.connect('motion-notify-event', - self.__detail_button_motion_notify_event_cb) - self.append(self._detail_button) - - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - self.reverse() - - def _create_title_entry(self): - title_entry = CanvasEntry() - title_entry.set_background(style.COLOR_WHITE.get_html()) - title_entry.props.widget.connect('focus-out-event', - self.__title_entry_focus_out_event_cb) - title_entry.props.widget.connect('activate', - self.__title_entry_activate_cb) - title_entry.connect('key-press-event', - self.__title_entry_key_press_event_cb) - return title_entry - - def _create_detail_button(self): - button = CanvasIcon(icon_name='go-right', - size=style.SMALL_ICON_SIZE, - box_width=style.GRID_CELL_SIZE * 3 / 5, - fill_color=style.COLOR_BUTTON_GREY.get_svg()) - button.connect('button-release-event', - self.__detail_button_release_event_cb) - return button - - def update_visibility(self): - BaseCollapsedEntry.update_visibility(self) - self._detail_button.set_visible(not self.is_in_progress()) - - def set_jobject(self, jobject): - BaseCollapsedEntry.set_jobject(self, jobject) - self._title_entry.props.text = self.title.props.text - - jobject = property(BaseCollapsedEntry.get_jobject, set_jobject) - - def __detail_button_release_event_cb(self, button, event): - logging.debug('_detail_button_release_event_cb') - if not self.is_in_progress(): - self.emit('detail-clicked') - return True - - def __detail_button_motion_notify_event_cb(self, button, event): - if event.detail == hippo.MOTION_DETAIL_ENTER: - button.props.fill_color = style.COLOR_TOOLBAR_GREY.get_svg() - elif event.detail == hippo.MOTION_DETAIL_LEAVE: - button.props.fill_color = style.COLOR_BUTTON_GREY.get_svg() - - def __icon_button_release_event_cb(self, button, event): - logging.debug('__icon_button_release_event_cb') - misc.resume(self.jobject) - return True - - def __title_button_release_event_cb(self, button, event): - self.title.set_visible(False) - self._title_entry.set_visible(True) - self._title_entry.props.widget.grab_focus() - - def __title_entry_focus_out_event_cb(self, entry, event): - self._apply_title_change(entry.props.text) - - def __title_entry_activate_cb(self, entry): - self._apply_title_change(entry.props.text) - - def __title_entry_key_press_event_cb(self, entry, event): - if event.key == hippo.KEY_ESCAPE: - self._cancel_title_change() - - def _apply_title_change(self, title): - self._title_entry.set_visible(False) - self.title.set_visible(True) - - if title == '': - self._cancel_title_change() - elif self.title.props.text != title: - self.title.props.text = title - self._jobject.metadata['title'] = title - self._jobject.metadata['title_set_by_user'] = '1' - datastore.write(self._jobject, update_mtime=False, - reply_handler=self._datastore_write_cb, - error_handler=self._datastore_write_error_cb) - - def _cancel_title_change(self): - self._title_entry.props.text = self.title.props.text - self._title_entry.set_visible(False) - self.title.set_visible(True) - - def _datastore_write_cb(self): - pass - - def _datastore_write_error_cb(self, error): - logging.error('CollapsedEntry._datastore_write_error_cb: %r' % error) - diff --git a/src/jarabe/journal/detailview.py b/src/jarabe/journal/detailview.py deleted file mode 100644 index 5748d6f..0000000 --- a/src/jarabe/journal/detailview.py +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging -from gettext import gettext as _ - -import gobject -import gtk -import hippo - -from sugar.graphics import style -from sugar.graphics.icon import CanvasIcon -from sugar.datastore import datastore - -from jarabe.journal.expandedentry import ExpandedEntry - -class DetailView(gtk.VBox): - __gtype_name__ = 'DetailView' - - __gproperties__ = { - 'jobject' : (object, None, None, - gobject.PARAM_READWRITE) - } - - __gsignals__ = { - 'go-back-clicked': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) - } - - def __init__(self, **kwargs): - self._jobject = None - self._expanded_entry = None - - canvas = hippo.Canvas() - - self._root = hippo.CanvasBox() - self._root.props.background_color = style.COLOR_PANEL_GREY.get_int() - canvas.set_root(self._root) - - back_bar = BackBar() - back_bar.connect('button-release-event', - self.__back_bar_release_event_cb) - self._root.append(back_bar) - - gobject.GObject.__init__(self, **kwargs) - - self.pack_start(canvas) - canvas.show() - - def _fav_icon_activated_cb(self, fav_icon): - keep = not self._expanded_entry.get_keep() - self._expanded_entry.set_keep(keep) - fav_icon.props.keep = keep - - def __back_bar_release_event_cb(self, back_bar, event): - self.emit('go-back-clicked') - return False - - def _update_view(self): - if self._expanded_entry: - self._root.remove(self._expanded_entry) - - # Work around pygobject bug #479227 - self._expanded_entry.remove_all() - import gc - gc.collect() - if self._jobject: - self._expanded_entry = ExpandedEntry(self._jobject.object_id) - self._root.append(self._expanded_entry, hippo.PACK_EXPAND) - - def refresh(self): - logging.debug('DetailView.refresh') - if self._jobject: - self._jobject = datastore.get(self._jobject.object_id) - self._update_view() - - def do_set_property(self, pspec, value): - if pspec.name == 'jobject': - self._jobject = value - self._update_view() - else: - raise AssertionError - - def do_get_property(self, pspec): - if pspec.name == 'jobject': - return self._jobject - else: - raise AssertionError - - -class BackBar(hippo.CanvasBox): - def __init__(self): - hippo.CanvasBox.__init__(self, - orientation=hippo.ORIENTATION_HORIZONTAL, - border=style.LINE_WIDTH, - background_color=style.COLOR_PANEL_GREY.get_int(), - border_color=style.COLOR_SELECTION_GREY.get_int(), - padding=style.DEFAULT_PADDING, - padding_left=style.DEFAULT_SPACING, - spacing=style.DEFAULT_SPACING) - - icon = CanvasIcon(icon_name='go-previous', - size=style.SMALL_ICON_SIZE, - fill_color=style.COLOR_TOOLBAR_GREY.get_svg()) - self.append(icon) - - label = hippo.CanvasText(text=_('Back'), - font_desc=style.FONT_NORMAL.get_pango_desc()) - self.append(label) - - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - self.reverse() - - self.connect('motion-notify-event', self.__motion_notify_event_cb) - - def __motion_notify_event_cb(self, box, event): - if event.detail == hippo.MOTION_DETAIL_ENTER: - box.props.background_color = style.COLOR_SELECTION_GREY.get_int() - elif event.detail == hippo.MOTION_DETAIL_LEAVE: - box.props.background_color = style.COLOR_PANEL_GREY.get_int() - return False diff --git a/src/jarabe/journal/expandedentry.py b/src/jarabe/journal/expandedentry.py deleted file mode 100644 index 9f99d3a..0000000 --- a/src/jarabe/journal/expandedentry.py +++ /dev/null @@ -1,383 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging -from gettext import gettext as _ -import StringIO - -import hippo -import cairo -import gobject -import gtk -import cjson - -from sugar.graphics import style -from sugar.graphics.icon import CanvasIcon -from sugar.graphics.xocolor import XoColor -from sugar.graphics.entry import CanvasEntry -from sugar.datastore import datastore - -from jarabe.journal.keepicon import KeepIcon -from jarabe.journal.palettes import ObjectPalette, BuddyPalette -from jarabe.journal import misc - -class Separator(hippo.CanvasBox, hippo.CanvasItem): - def __init__(self, orientation): - hippo.CanvasBox.__init__(self, - background_color=style.COLOR_PANEL_GREY.get_int()) - - if orientation == hippo.ORIENTATION_VERTICAL: - self.props.box_width = style.LINE_WIDTH - else: - self.props.box_height = style.LINE_WIDTH - -class CanvasTextView(hippo.CanvasWidget): - def __init__(self, text, **kwargs): - hippo.CanvasWidget.__init__(self, **kwargs) - self.text_view_widget = gtk.TextView() - self.text_view_widget.props.buffer.props.text = text - self.text_view_widget.props.left_margin = style.DEFAULT_SPACING - self.text_view_widget.props.right_margin = style.DEFAULT_SPACING - self.text_view_widget.props.wrap_mode = gtk.WRAP_WORD - self.text_view_widget.show() - - # TODO: These fields should expand vertically instead of scrolling - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_shadow_type(gtk.SHADOW_OUT) - scrolled_window.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - scrolled_window.add(self.text_view_widget) - - self.props.widget = scrolled_window - -class BuddyList(hippo.CanvasBox): - def __init__(self, model): - hippo.CanvasBox.__init__(self, xalign=hippo.ALIGNMENT_START, - orientation=hippo.ORIENTATION_HORIZONTAL) - - for buddy in model: - nick_, color = buddy - hbox = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL) - icon = CanvasIcon(icon_name='computer-xo', - xo_color=XoColor(color), - size=style.STANDARD_ICON_SIZE) - icon.set_palette(BuddyPalette(buddy)) - hbox.append(icon) - self.append(hbox) - -class ExpandedEntry(hippo.CanvasBox): - def __init__(self, object_id): - hippo.CanvasBox.__init__(self) - self.props.orientation = hippo.ORIENTATION_VERTICAL - self.props.background_color = style.COLOR_WHITE.get_int() - self.props.padding_top = style.DEFAULT_SPACING * 3 - - self._jobject = datastore.get(object_id) - self._update_title_sid = None - - # Create header - header = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, - padding=style.DEFAULT_PADDING, - padding_right=style.GRID_CELL_SIZE, - spacing=style.DEFAULT_SPACING) - self.append(header) - - # Create two column body - - body = hippo.CanvasBox(orientation=hippo.ORIENTATION_HORIZONTAL, - spacing=style.DEFAULT_SPACING * 3, - padding_left=style.GRID_CELL_SIZE, - padding_right=style.GRID_CELL_SIZE, - padding_top=style.DEFAULT_SPACING * 3) - - self.append(body, hippo.PACK_EXPAND) - - first_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, - spacing=style.DEFAULT_SPACING) - body.append(first_column) - - second_column = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, - spacing=style.DEFAULT_SPACING) - body.append(second_column, hippo.PACK_EXPAND) - - # Header - - self._keep_icon = self._create_keep_icon() - header.append(self._keep_icon) - - self._icon = self._create_icon() - header.append(self._icon) - - self._title = self._create_title() - header.append(self._title, hippo.PACK_EXPAND) - - # TODO: create a version list popup instead of a date label - self._date = self._create_date() - header.append(self._date) - - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - header.reverse() - - # First column - - self._preview = self._create_preview() - first_column.append(self._preview) - - # Second column - - description_box, self._description = self._create_description() - second_column.append(description_box) - - tags_box, self._tags = self._create_tags() - second_column.append(tags_box) - - self._buddy_list = self._create_buddy_list() - second_column.append(self._buddy_list) - - def _create_keep_icon(self): - keep = int(self._jobject.metadata.get('keep', 0)) == 1 - keep_icon = KeepIcon(keep) - keep_icon.connect('activated', self._keep_icon_activated_cb) - return keep_icon - - def _create_icon(self): - icon = CanvasIcon(file_name=misc.get_icon_name(self._jobject)) - icon.connect_after('button-release-event', - self._icon_button_release_event_cb) - - if self._jobject.is_activity_bundle(): - icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg() - icon.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() - else: - if self._jobject.metadata.has_key('icon-color') and \ - self._jobject.metadata['icon-color']: - icon.props.xo_color = XoColor( \ - self._jobject.metadata['icon-color']) - - icon.set_palette(ObjectPalette(self._jobject)) - - return icon - - def _create_title(self): - title = CanvasEntry() - title.set_background(style.COLOR_WHITE.get_html()) - title.props.text = self._jobject.metadata.get('title', _('Untitled')) - title.props.widget.connect('focus-out-event', - self._title_focus_out_event_cb) - return title - - def _create_date(self): - date = hippo.CanvasText(xalign=hippo.ALIGNMENT_START, - font_desc=style.FONT_NORMAL.get_pango_desc(), - text = misc.get_date(self._jobject)) - return date - - def _create_preview(self): - width = style.zoom(320) - height = style.zoom(240) - box = hippo.CanvasBox() - - if self._jobject.metadata.has_key('preview') and \ - len(self._jobject.metadata['preview']) > 4: - - if self._jobject.metadata['preview'][1:4] == 'PNG': - preview_data = self._jobject.metadata['preview'] - else: - # TODO: We are close to be able to drop this. - import base64 - preview_data = base64.b64decode( - self._jobject.metadata['preview']) - - png_file = StringIO.StringIO(preview_data) - try: - surface = cairo.ImageSurface.create_from_png(png_file) - has_preview = True - except Exception, e: - logging.error('Error while loading the preview: %r' % e) - has_preview = False - else: - has_preview = False - - if has_preview: - preview_box = hippo.CanvasImage(image=surface, - border=style.LINE_WIDTH, - border_color=style.COLOR_BUTTON_GREY.get_int(), - xalign=hippo.ALIGNMENT_CENTER, - yalign=hippo.ALIGNMENT_CENTER, - scale_width=width, - scale_height=height) - else: - preview_box = hippo.CanvasText(text=_('No preview'), - font_desc=style.FONT_NORMAL.get_pango_desc(), - xalign=hippo.ALIGNMENT_CENTER, - yalign=hippo.ALIGNMENT_CENTER, - border=style.LINE_WIDTH, - border_color=style.COLOR_BUTTON_GREY.get_int(), - color=style.COLOR_BUTTON_GREY.get_int(), - box_width=width, - box_height=height) - preview_box.connect_after('button-release-event', - self._preview_box_button_release_event_cb) - box.append(preview_box) - return box - - def _create_buddy_list(self): - - vbox = hippo.CanvasBox() - vbox.props.spacing = style.DEFAULT_SPACING - - text = hippo.CanvasText(text=_('Participants:'), - font_desc=style.FONT_NORMAL.get_pango_desc()) - text.props.color = style.COLOR_BUTTON_GREY.get_int() - - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - text.props.xalign = hippo.ALIGNMENT_END - else: - text.props.xalign = hippo.ALIGNMENT_START - - vbox.append(text) - - if self._jobject.metadata.has_key('buddies') and \ - self._jobject.metadata['buddies']: - buddies = cjson.decode(self._jobject.metadata['buddies']).values() - vbox.append(BuddyList(buddies)) - return vbox - else: - return vbox - - def _create_description(self): - vbox = hippo.CanvasBox() - vbox.props.spacing = style.DEFAULT_SPACING - - text = hippo.CanvasText(text=_('Description:'), - font_desc=style.FONT_NORMAL.get_pango_desc()) - text.props.color = style.COLOR_BUTTON_GREY.get_int() - - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - text.props.xalign = hippo.ALIGNMENT_END - else: - text.props.xalign = hippo.ALIGNMENT_START - - vbox.append(text) - - description = self._jobject.metadata.get('description', '') - text_view = CanvasTextView(description, - box_height=style.GRID_CELL_SIZE * 2) - vbox.append(text_view, hippo.PACK_EXPAND) - - text_view.text_view_widget.props.accepts_tab = False - text_view.text_view_widget.connect('focus-out-event', - self._description_focus_out_event_cb) - - return vbox, text_view - - def _create_tags(self): - vbox = hippo.CanvasBox() - vbox.props.spacing = style.DEFAULT_SPACING - - text = hippo.CanvasText(text=_('Tags:'), - font_desc=style.FONT_NORMAL.get_pango_desc()) - text.props.color = style.COLOR_BUTTON_GREY.get_int() - - if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - text.props.xalign = hippo.ALIGNMENT_END - else: - text.props.xalign = hippo.ALIGNMENT_START - - vbox.append(text) - - tags = self._jobject.metadata.get('tags', '') - text_view = CanvasTextView(tags, box_height=style.GRID_CELL_SIZE * 2) - vbox.append(text_view, hippo.PACK_EXPAND) - - text_view.text_view_widget.props.accepts_tab = False - text_view.text_view_widget.connect('focus-out-event', - self._tags_focus_out_event_cb) - - return vbox, text_view - - def _title_notify_text_cb(self, entry, pspec): - if not self._update_title_sid: - self._update_title_sid = gobject.timeout_add(1000, - self._update_title_cb) - - def _datastore_write_cb(self): - pass - - def _datastore_write_error_cb(self, error): - logging.error('ExpandedEntry._datastore_write_error_cb: %r' % error) - - def _title_focus_out_event_cb(self, entry, event): - self._update_entry() - - def _description_focus_out_event_cb(self, text_view, event): - self._update_entry() - - def _tags_focus_out_event_cb(self, text_view, event): - self._update_entry() - - def _update_entry(self): - needs_update = False - - old_title = self._jobject.metadata.get('title', None) - if old_title != self._title.props.text: - self._icon.palette.props.primary_text = self._title.props.text - self._jobject.metadata['title'] = self._title.props.text - self._jobject.metadata['title_set_by_user'] = '1' - needs_update = True - - old_tags = self._jobject.metadata.get('tags', None) - new_tags = self._tags.text_view_widget.props.buffer.props.text - if old_tags != new_tags: - self._jobject.metadata['tags'] = new_tags - needs_update = True - - old_description = self._jobject.metadata.get('description', None) - new_description = \ - self._description.text_view_widget.props.buffer.props.text - if old_description != new_description: - self._jobject.metadata['description'] = new_description - needs_update = True - - if needs_update: - datastore.write(self._jobject, update_mtime=False, - reply_handler=self._datastore_write_cb, - error_handler=self._datastore_write_error_cb) - - self._update_title_sid = None - - def get_keep(self): - return self._jobject.metadata.has_key('keep') and \ - self._jobject.metadata['keep'] == 1 - - def _keep_icon_activated_cb(self, keep_icon): - if self.get_keep(): - self._jobject.metadata['keep'] = 0 - else: - self._jobject.metadata['keep'] = 1 - datastore.write(self._jobject, update_mtime=False) - - keep_icon.props.keep = self.get_keep() - - def _icon_button_release_event_cb(self, button, event): - logging.debug('_icon_button_release_event_cb') - misc.resume(self._jobject) - return True - - def _preview_box_button_release_event_cb(self, button, event): - logging.debug('_preview_box_button_release_event_cb') - misc.resume(self._jobject) - return True - diff --git a/src/jarabe/journal/journalactivity.py b/src/jarabe/journal/journalactivity.py deleted file mode 100644 index 0513382..0000000 --- a/src/jarabe/journal/journalactivity.py +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# Copyright (C) 2007, 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 - -import logging -from gettext import gettext as _ -import sys -import traceback -import uuid - -import gtk -import dbus -import statvfs -import os - -from sugar.graphics.window import Window -from sugar.bundle.bundle import ZipExtractException, RegistrationException -from sugar.datastore import datastore -from sugar import env -from sugar.activity import activityfactory -from sugar import wm - -from jarabe.model import bundleregistry -from jarabe.journal.journaltoolbox import MainToolbox, DetailToolbox -from jarabe.journal.listview import ListView -from jarabe.journal.detailview import DetailView -from jarabe.journal.volumestoolbar import VolumesToolbar -from jarabe.journal import misc -from jarabe.journal.journalentrybundle import JournalEntryBundle -from jarabe.journal.objectchooser import ObjectChooser -from jarabe.journal.modalalert import ModalAlert - -DS_DBUS_SERVICE = 'org.laptop.sugar.DataStore' -DS_DBUS_INTERFACE = 'org.laptop.sugar.DataStore' -DS_DBUS_PATH = '/org/laptop/sugar/DataStore' - -J_DBUS_SERVICE = 'org.laptop.Journal' -J_DBUS_INTERFACE = 'org.laptop.Journal' -J_DBUS_PATH = '/org/laptop/Journal' - -_SPACE_TRESHOLD = 52428800 -_BUNDLE_ID = 'org.laptop.JournalActivity' - -class JournalActivityDBusService(dbus.service.Object): - def __init__(self, parent): - self._parent = parent - session_bus = dbus.SessionBus() - bus_name = dbus.service.BusName(J_DBUS_SERVICE, - bus=session_bus, replace_existing=False, allow_replacement=False) - logging.debug('bus_name: %r', bus_name) - dbus.service.Object.__init__(self, bus_name, J_DBUS_PATH) - - @dbus.service.method(J_DBUS_INTERFACE, - in_signature='', out_signature='') - def FocusSearch(self): - """Become visible and give focus to the search entry - """ - self._parent.present() - self._parent.show_main_view() - self._parent.search_grab_focus() - - @dbus.service.method(J_DBUS_INTERFACE, - in_signature='s', out_signature='') - def ShowObject(self, object_id): - """Pop-up journal and show object with object_id""" - - logging.debug('Trying to show object %s', object_id) - - if self._parent.show_object(object_id): - self._parent.present() - - def _chooser_response_cb(self, chooser, response_id, chooser_id): - logging.debug('JournalActivityDBusService._chooser_response_cb') - if response_id == gtk.RESPONSE_ACCEPT: - object_id = chooser.get_selected_object_id() - self.ObjectChooserResponse(chooser_id, object_id) - else: - self.ObjectChooserCancelled(chooser_id) - chooser.destroy() - del chooser - - @dbus.service.method(J_DBUS_INTERFACE, in_signature='i', out_signature='s') - def ChooseObject(self, parent_xid): - chooser_id = uuid.uuid4().hex - if parent_xid > 0: - parent = gtk.gdk.window_foreign_new(parent_xid) - else: - parent = None - chooser = ObjectChooser(parent) - chooser.connect('response', self._chooser_response_cb, chooser_id) - chooser.show() - - return chooser_id - - @dbus.service.signal(J_DBUS_INTERFACE, signature="ss") - def ObjectChooserResponse(self, chooser_id, object_id): - pass - - @dbus.service.signal(J_DBUS_INTERFACE, signature="s") - def ObjectChooserCancelled(self, chooser_id): - pass - -class JournalActivity(Window): - def __init__(self): - logging.debug("STARTUP: Loading the journal") - Window.__init__(self) - - self.set_title(_('Journal')) - - self._main_view = None - self._secondary_view = None - self._list_view = None - self._detail_view = None - self._main_toolbox = None - self._detail_toolbox = None - - self._setup_main_view() - self._setup_secondary_view() - - self.add_events(gtk.gdk.ALL_EVENTS_MASK | - gtk.gdk.VISIBILITY_NOTIFY_MASK) - self._realized_sid = self.connect('realize', self.__realize_cb) - self.connect('visibility-notify-event', - self.__visibility_notify_event_cb) - self.connect('window-state-event', self.__window_state_event_cb) - self.connect('key-press-event', self._key_press_event_cb) - self.connect('focus-in-event', self._focus_in_event_cb) - - bus = dbus.SessionBus() - data_store = dbus.Interface( - bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH), DS_DBUS_INTERFACE) - data_store.connect_to_signal('Created', self.__data_store_created_cb) - data_store.connect_to_signal('Updated', self.__data_store_updated_cb) - data_store.connect_to_signal('Deleted', self.__data_store_deleted_cb) - - self._dbus_service = JournalActivityDBusService(self) - - self.iconify() - - self._critical_space_alert = None - self._check_available_space() - - def __realize_cb(self, window): - wm.set_bundle_id(window.window, _BUNDLE_ID) - activity_id = activityfactory.create_activity_id() - wm.set_activity_id(window.window, str(activity_id)) - self.disconnect(self._realized_sid) - self._realized_sid = None - - def can_close(self): - return False - - def _setup_main_view(self): - self._main_toolbox = MainToolbox() - self._main_view = gtk.VBox() - - self._list_view = ListView() - self._list_view.connect('detail-clicked', self.__detail_clicked_cb) - self._main_view.pack_start(self._list_view) - self._list_view.show() - - volumes_toolbar = VolumesToolbar() - volumes_toolbar.connect('volume-changed', self._volume_changed_cb) - self._main_view.pack_start(volumes_toolbar, expand=False) - - search_toolbar = self._main_toolbox.search_toolbar - search_toolbar.connect('query-changed', self._query_changed_cb) - search_toolbar.set_volume_id(datastore.mounts()[0]['id']) - - def _setup_secondary_view(self): - self._secondary_view = gtk.VBox() - - self._detail_toolbox = DetailToolbox() - entry_toolbar = self._detail_toolbox.entry_toolbar - - self._detail_view = DetailView() - self._detail_view.connect('go-back-clicked', self.__go_back_clicked_cb) - self._secondary_view.pack_end(self._detail_view) - self._detail_view.show() - - def _key_press_event_cb(self, widget, event): - keyname = gtk.gdk.keyval_name(event.keyval) - logging.info(keyname) - logging.info(event.state) - if keyname == 'Escape': - self.show_main_view() - - def __detail_clicked_cb(self, list_view, entry): - self._show_secondary_view(entry.jobject) - - def __go_back_clicked_cb(self, detail_view): - self.show_main_view() - - def _query_changed_cb(self, toolbar, query): - self._list_view.update_with_query(query) - self.show_main_view() - - def show_main_view(self): - if self.toolbox != self._main_toolbox: - self.set_toolbox(self._main_toolbox) - self._main_toolbox.show() - - if self.canvas != self._main_view: - self.set_canvas(self._main_view) - self._main_view.show() - - def _show_secondary_view(self, jobject): - try: - self._detail_toolbox.entry_toolbar.set_jobject(jobject) - except Exception: - logging.error('Exception while displaying entry:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - - self.set_toolbox(self._detail_toolbox) - self._detail_toolbox.show() - - try: - self._detail_view.props.jobject = jobject - except Exception: - logging.error('Exception while displaying entry:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - - self.set_canvas(self._secondary_view) - self._secondary_view.show() - - def show_object(self, object_id): - jobject = datastore.get(object_id) - if jobject is None: - return False - else: - self._show_secondary_view(jobject) - return True - - def _volume_changed_cb(self, volume_toolbar, volume_id): - logging.debug('Selected volume: %r.' % volume_id) - self._main_toolbox.search_toolbar.set_volume_id(volume_id) - self._main_toolbox.set_current_toolbar(0) - - def __data_store_created_cb(self, uid): - jobject = datastore.get(uid) - if jobject is None: - return - try: - self._check_for_bundle(jobject) - finally: - jobject.destroy() - self._main_toolbox.search_toolbar.refresh_filters() - self._check_available_space() - - def __data_store_updated_cb(self, uid): - jobject = datastore.get(uid) - if jobject is None: - return - try: - self._check_for_bundle(jobject) - finally: - jobject.destroy() - self._check_available_space() - - def __data_store_deleted_cb(self, uid): - if self.canvas == self._secondary_view and \ - uid == self._detail_view.props.jobject.object_id: - self.show_main_view() - - def _focus_in_event_cb(self, window, event): - self.search_grab_focus() - self._list_view.update_dates() - - def _check_for_bundle(self, jobject): - registry = bundleregistry.get_registry() - - bundle = misc.get_bundle(jobject) - if bundle is None: - return - - if registry.is_installed(bundle): - return - try: - registry.install(bundle) - except (ZipExtractException, RegistrationException), e: - logging.warning('Could not install bundle %s: %r' % - (jobject.file_path, e)) - return - - if jobject.metadata['mime_type'] == JournalEntryBundle.MIME_TYPE: - datastore.delete(jobject.object_id) - - def search_grab_focus(self): - search_toolbar = self._main_toolbox.search_toolbar - search_toolbar.give_entry_focus() - - def __window_state_event_cb(self, window, event): - logging.debug('window_state_event_cb %r' % self) - if event.changed_mask & gtk.gdk.WINDOW_STATE_ICONIFIED: - state = event.new_window_state - visible = not state & gtk.gdk.WINDOW_STATE_ICONIFIED - self._list_view.set_is_visible(visible) - - def __visibility_notify_event_cb(self, window, event): - logging.debug('visibility_notify_event_cb %r' % self) - visible = event.state != gtk.gdk.VISIBILITY_FULLY_OBSCURED - self._list_view.set_is_visible(visible) - - def _check_available_space(self): - ''' Check available space on device - - If the available space is below 50MB an alert will be - shown which encourages to delete old journal entries. - ''' - - if self._critical_space_alert: - return - stat = os.statvfs(env.get_profile_path()) - free_space = stat[statvfs.F_BSIZE] * stat[statvfs.F_BAVAIL] - if free_space < _SPACE_TRESHOLD: - self._critical_space_alert = ModalAlert() - self._critical_space_alert.connect('destroy', - self.__alert_closed_cb) - self._critical_space_alert.show() - - def __alert_closed_cb(self, data): - self.show_main_view() - self.present() - self._critical_space_alert = None - -def start(): - journal = JournalActivity() - journal.show() - diff --git a/src/jarabe/journal/journalentrybundle.py b/src/jarabe/journal/journalentrybundle.py deleted file mode 100644 index b3efe92..0000000 --- a/src/jarabe/journal/journalentrybundle.py +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright (C) 2007, 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 - -import os -import tempfile -import shutil - -import cjson - -import dbus -from sugar.datastore import datastore -from sugar.bundle.bundle import Bundle, MalformedBundleException - -class JournalEntryBundle(Bundle): - """A Journal entry bundle - - See http://wiki.laptop.org/go/Journal_entry_bundles for details - """ - - MIME_TYPE = 'application/vnd.olpc-journal-entry' - - _zipped_extension = '.xoj' - _unzipped_extension = None - _infodir = None - - def __init__(self, path): - Bundle.__init__(self, path) - - def install(self): - if os.environ.has_key('SUGAR_ACTIVITY_ROOT'): - install_dir = os.path.join(os.environ['SUGAR_ACTIVITY_ROOT'], - 'data') - else: - install_dir = tempfile.gettempdir() - bundle_dir = os.path.join(install_dir, self._zip_root_dir) - uid = self._zip_root_dir - self._unzip(install_dir) - try: - metadata = self._read_metadata(bundle_dir) - jobject = datastore.create() - try: - for key, value in metadata.iteritems(): - jobject.metadata[key] = value - - preview = self._read_preview(uid, bundle_dir) - if preview is not None: - jobject.metadata['preview'] = dbus.ByteArray(preview) - - jobject.metadata['uid'] = '' - jobject.file_path = os.path.join(bundle_dir, uid) - datastore.write(jobject) - finally: - jobject.destroy() - finally: - shutil.rmtree(bundle_dir, ignore_errors=True) - - def _read_metadata(self, bundle_dir): - metadata_path = os.path.join(bundle_dir, '_metadata.json') - if not os.path.exists(metadata_path): - raise MalformedBundleException( - 'Bundle must contain the file "_metadata.json"') - return cjson.decode(open(metadata_path, 'r').read()) - - def _read_preview(self, uid, bundle_dir): - preview_path = os.path.join(bundle_dir, 'preview', uid) - if not os.path.exists(preview_path): - return '' - f = open(preview_path, 'r') - try: - preview_data = f.read() - finally: - f.close() - return preview_data - - def is_installed(self): - # These bundles can be reinstalled as many times as desired. - return False - diff --git a/src/jarabe/journal/journaltoolbox.py b/src/jarabe/journal/journaltoolbox.py deleted file mode 100644 index 637965f..0000000 --- a/src/jarabe/journal/journaltoolbox.py +++ /dev/null @@ -1,422 +0,0 @@ -# Copyright (C) 2007, 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 gettext import gettext as _ -import logging -from datetime import datetime, timedelta -import os -import gconf - -import gobject -import gtk - -from sugar.graphics.toolbox import Toolbox -from sugar.graphics.toolcombobox import ToolComboBox -from sugar.graphics.toolbutton import ToolButton -from sugar.graphics.combobox import ComboBox -from sugar.graphics.menuitem import MenuItem -from sugar.graphics.icon import Icon -from sugar.graphics.xocolor import XoColor -from sugar.graphics import iconentry -from sugar.graphics import style -from sugar import mime -from sugar.datastore import datastore - -from jarabe.model import bundleregistry -from jarabe.model import volume -from jarabe.journal import misc - -_AUTOSEARCH_TIMEOUT = 1000 - -_ACTION_ANYTIME = 0 -_ACTION_TODAY = 1 -_ACTION_SINCE_YESTERDAY = 2 -_ACTION_PAST_WEEK = 3 -_ACTION_PAST_MONTH = 4 -_ACTION_PAST_YEAR = 5 - -_ACTION_ANYTHING = 0 - -_ACTION_EVERYBODY = 0 -_ACTION_MY_FRIENDS = 1 -_ACTION_MY_CLASS = 2 - -class MainToolbox(Toolbox): - def __init__(self): - Toolbox.__init__(self) - - self.search_toolbar = SearchToolbar() - self.search_toolbar.set_size_request(-1, style.GRID_CELL_SIZE) - self.add_toolbar(_('Search'), self.search_toolbar) - self.search_toolbar.show() - - #self.manage_toolbar = ManageToolbar() - #self.add_toolbar(_('Manage'), self.manage_toolbar) - #self.manage_toolbar.show() - -class SearchToolbar(gtk.Toolbar): - __gtype_name__ = 'SearchToolbar' - - __gsignals__ = { - 'query-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([object])) - } - - def __init__(self): - gtk.Toolbar.__init__(self) - - self._volume_id = None - - self._search_entry = iconentry.IconEntry() - self._search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, - 'system-search') - self._search_entry.connect('activate', self._search_entry_activated_cb) - self._search_entry.connect('changed', self._search_entry_changed_cb) - self._search_entry.add_clear_button() - self._autosearch_timer = None - self._add_widget(self._search_entry, expand=True) - - self._what_search_combo = ComboBox() - self._what_combo_changed_sid = self._what_search_combo.connect( - 'changed', self._combo_changed_cb) - tool_item = ToolComboBox(self._what_search_combo) - self.insert(tool_item, -1) - tool_item.show() - - self._when_search_combo = self._get_when_search_combo() - tool_item = ToolComboBox(self._when_search_combo) - self.insert(tool_item, -1) - tool_item.show() - - # TODO: enable it when the DS supports saving the buddies. - #self._with_search_combo = self._get_with_search_combo() - #tool_item = ToolComboBox(self._with_search_combo) - #self.insert(tool_item, -1) - #tool_item.show() - - self._query = self._build_query() - - self.refresh_filters() - - def give_entry_focus(self): - self._search_entry.grab_focus() - - def _get_when_search_combo(self): - when_search = ComboBox() - when_search.append_item(_ACTION_ANYTIME, _('Anytime')) - when_search.append_separator() - when_search.append_item(_ACTION_TODAY, _('Today')) - when_search.append_item(_ACTION_SINCE_YESTERDAY, - _('Since yesterday')) - # TRANS: Filter entries modified during the last 7 days. - when_search.append_item(_ACTION_PAST_WEEK, _('Past week')) - # TRANS: Filter entries modified during the last 30 days. - when_search.append_item(_ACTION_PAST_MONTH, _('Past month')) - # TRANS: Filter entries modified during the last 356 days. - when_search.append_item(_ACTION_PAST_YEAR, _('Past year')) - when_search.set_active(0) - when_search.connect('changed', self._combo_changed_cb) - return when_search - - def _get_with_search_combo(self): - with_search = ComboBox() - with_search.append_item(_ACTION_EVERYBODY, _('Anyone')) - with_search.append_separator() - with_search.append_item(_ACTION_MY_FRIENDS, _('My friends')) - with_search.append_item(_ACTION_MY_CLASS, _('My class')) - with_search.append_separator() - - # TODO: Ask the model for buddies. - with_search.append_item(3, 'Dan', 'theme:xo') - - with_search.set_active(0) - with_search.connect('changed', self._combo_changed_cb) - return with_search - - def _add_widget(self, widget, expand=False): - tool_item = gtk.ToolItem() - tool_item.set_expand(expand) - - tool_item.add(widget) - widget.show() - - self.insert(tool_item, -1) - tool_item.show() - - def _build_query(self): - query = {} - if self._volume_id: - query['mountpoints'] = [self._volume_id] - if self._what_search_combo.props.value: - value = self._what_search_combo.props.value - generic_type = mime.get_generic_type(value) - if generic_type: - mime_types = generic_type.mime_types - query['mime_type'] = mime_types - else: - query['activity'] = self._what_search_combo.props.value - if self._when_search_combo.props.value: - date_from, date_to = self._get_date_range() - query['mtime'] = {'start': date_from, 'end': date_to} - if self._search_entry.props.text: - text = self._search_entry.props.text.strip() - - if not text.startswith('"'): - query_text = '' - words = text.split(' ') - for word in words: - if word: - if query_text: - query_text += ' ' - query_text += word + '*' - else: - query_text = text - - if query_text: - query['query'] = query_text - - return query - - def _get_date_range(self): - today_start = datetime.today().replace(hour=0, minute=0, second=0) - right_now = datetime.today() - if self._when_search_combo.props.value == _ACTION_TODAY: - date_range = (today_start, right_now) - elif self._when_search_combo.props.value == _ACTION_SINCE_YESTERDAY: - date_range = (today_start - timedelta(1), right_now) - elif self._when_search_combo.props.value == _ACTION_PAST_WEEK: - date_range = (today_start - timedelta(7), right_now) - elif self._when_search_combo.props.value == _ACTION_PAST_MONTH: - date_range = (today_start - timedelta(30), right_now) - elif self._when_search_combo.props.value == _ACTION_PAST_YEAR: - date_range = (today_start - timedelta(356), right_now) - - return (date_range[0].isoformat(), - date_range[1].isoformat()) - - def _combo_changed_cb(self, combo): - new_query = self._build_query() - if self._query != new_query: - self._query = new_query - self.emit('query-changed', self._query) - - def _search_entry_activated_cb(self, search_entry): - if self._autosearch_timer: - gobject.source_remove(self._autosearch_timer) - new_query = self._build_query() - if self._query != new_query: - self._query = new_query - self.emit('query-changed', self._query) - - def _search_entry_changed_cb(self, search_entry): - if not search_entry.props.text: - search_entry.activate() - return - - if self._autosearch_timer: - gobject.source_remove(self._autosearch_timer) - self._autosearch_timer = gobject.timeout_add(_AUTOSEARCH_TIMEOUT, - self._autosearch_timer_cb) - - def _autosearch_timer_cb(self): - logging.debug('_autosearch_timer_cb') - self._autosearch_timer = None - self._search_entry.activate() - return False - - def set_volume_id(self, volume_id): - self._volume_id = volume_id - new_query = self._build_query() - if self._query != new_query: - self._query = new_query - self.emit('query-changed', self._query) - - def refresh_filters(self): - current_value = self._what_search_combo.props.value - current_value_index = 0 - - self._what_search_combo.handler_block(self._what_combo_changed_sid) - try: - self._what_search_combo.remove_all() - # TRANS: Item in a combo box that filters by entry type. - self._what_search_combo.append_item(_ACTION_ANYTHING, _('Anything')) - - registry = bundleregistry.get_registry() - appended_separator = False - for service_name in datastore.get_unique_values('activity'): - activity_info = registry.get_bundle(service_name) - if not activity_info is None: - if not appended_separator: - self._what_search_combo.append_separator() - appended_separator = True - - if os.path.exists(activity_info.get_icon()): - self._what_search_combo.append_item(service_name, - activity_info.get_name(), - file_name=activity_info.get_icon()) - else: - self._what_search_combo.append_item(service_name, - activity_info.get_name(), - icon_name='application-octet-stream') - - if service_name == current_value: - current_value_index = \ - len(self._what_search_combo.get_model()) - 1 - - self._what_search_combo.append_separator() - - types = mime.get_all_generic_types() - for generic_type in types : - self._what_search_combo.append_item( - generic_type.type_id, generic_type.name, generic_type.icon) - if generic_type.type_id == current_value: - current_value_index = \ - len(self._what_search_combo.get_model()) - 1 - - self._what_search_combo.set_active(current_value_index) - finally: - self._what_search_combo.handler_unblock( - self._what_combo_changed_sid) - -class ManageToolbar(gtk.Toolbar): - __gtype_name__ = 'ManageToolbar' - - def __init__(self): - gtk.Toolbar.__init__(self) - -class DetailToolbox(Toolbox): - def __init__(self): - Toolbox.__init__(self) - - self.entry_toolbar = EntryToolbar() - self.add_toolbar('', self.entry_toolbar) - self.entry_toolbar.show() - -class EntryToolbar(gtk.Toolbar): - def __init__(self): - gtk.Toolbar.__init__(self) - - self._jobject = None - - self._resume = ToolButton('activity-start') - self._resume.connect('clicked', self._resume_clicked_cb) - self.add(self._resume) - self._resume.show() - - self._copy = ToolButton() - - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - icon = Icon(icon_name='edit-copy', xo_color=color) - self._copy.set_icon_widget(icon) - icon.show() - - self._copy.set_tooltip(_('Copy')) - self._copy.connect('clicked', self._copy_clicked_cb) - self.add(self._copy) - self._copy.show() - - separator = gtk.SeparatorToolItem() - self.add(separator) - separator.show() - - erase_button = ToolButton('list-remove') - erase_button.set_tooltip(_('Erase')) - erase_button.connect('clicked', self._erase_button_clicked_cb) - self.add(erase_button) - erase_button.show() - - def set_jobject(self, jobject): - self._jobject = jobject - self._refresh_copy_palette() - self._refresh_resume_palette() - - def _resume_clicked_cb(self, button): - if self._jobject: - misc.resume(self._jobject) - - def _copy_clicked_cb(self, button): - clipboard = gtk.Clipboard() - clipboard.set_with_data([('text/uri-list', 0, 0)], - self._clipboard_get_func_cb, - self._clipboard_clear_func_cb) - - def _clipboard_get_func_cb(self, clipboard, selection_data, info, data): - selection_data.set_uris(['file://' + self._jobject.file_path]) - - def _clipboard_clear_func_cb(self, clipboard, data): - pass - - def _erase_button_clicked_cb(self, button): - registry = bundleregistry.get_registry() - - if self._jobject: - bundle = misc.get_bundle(self._jobject) - if bundle is not None and registry.is_installed(bundle): - registry.uninstall(bundle) - datastore.delete(self._jobject.object_id) - - def _resume_menu_item_activate_cb(self, menu_item, service_name): - if self._jobject: - misc.resume(self._jobject, service_name) - - def _copy_menu_item_activate_cb(self, menu_item, vol): - if self._jobject: - datastore.copy(self._jobject, vol.id) - - def _refresh_copy_palette(self): - palette = self._copy.get_palette() - - for menu_item in palette.menu.get_children(): - palette.menu.remove(menu_item) - menu_item.destroy() - - volumes_manager = volume.get_volumes_manager() - for vol in volumes_manager.get_volumes(): - if self._jobject.metadata['mountpoint'] == vol.id: - continue - 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, - vol) - palette.menu.append(menu_item) - menu_item.show() - - def _refresh_resume_palette(self): - if self._jobject.metadata.get('activity_id', ''): - # TRANS: Action label for resuming an activity. - self._resume.set_tooltip(_('Resume')) - else: - # TRANS: Action label for starting an entry. - self._resume.set_tooltip(_('Start')) - - palette = self._resume.get_palette() - - for menu_item in palette.menu.get_children(): - palette.menu.remove(menu_item) - menu_item.destroy() - - for activity_info in misc.get_activities(self._jobject): - menu_item = MenuItem(activity_info.get_name()) - menu_item.set_image(Icon(file=activity_info.get_icon(), - icon_size=gtk.ICON_SIZE_MENU)) - menu_item.connect('activate', self._resume_menu_item_activate_cb, - activity_info.get_bundle_id()) - palette.menu.append(menu_item) - menu_item.show() diff --git a/src/jarabe/journal/keepicon.py b/src/jarabe/journal/keepicon.py deleted file mode 100644 index c6dc470..0000000 --- a/src/jarabe/journal/keepicon.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2006, Red Hat, Inc. -# -# 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 - -import gobject -import hippo -import gconf - -from sugar.graphics.icon import CanvasIcon -from sugar.graphics import style -from sugar.graphics.xocolor import XoColor - -class KeepIcon(CanvasIcon): - def __init__(self, keep): - CanvasIcon.__init__(self, icon_name='emblem-favorite', - box_width=style.GRID_CELL_SIZE * 3 / 5, - size=style.SMALL_ICON_SIZE) - self.connect('motion-notify-event', self.__motion_notify_event_cb) - - self._keep = None - self.set_keep(keep) - - def set_keep(self, keep): - if keep == self._keep: - return - - self._keep = keep - if keep: - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - self.props.xo_color = color - else: - self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() - self.props.fill_color = style.COLOR_TRANSPARENT.get_svg() - - def get_keep(self): - return self._keep - - keep = gobject.property(type=int, default=0, getter=get_keep, - setter=set_keep) - - def __motion_notify_event_cb(self, icon, event): - if not self._keep: - if event.detail == hippo.MOTION_DETAIL_ENTER: - icon.props.fill_color = style.COLOR_BUTTON_GREY.get_svg() - elif event.detail == hippo.MOTION_DETAIL_LEAVE: - icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg() diff --git a/src/jarabe/journal/listview.py b/src/jarabe/journal/listview.py deleted file mode 100644 index befc7f4..0000000 --- a/src/jarabe/journal/listview.py +++ /dev/null @@ -1,460 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging -import traceback -import sys -from gettext import gettext as _ - -import hippo -import gobject -import gtk -import dbus - -from sugar.graphics import style -from sugar.graphics.icon import CanvasIcon - -from jarabe.journal.collapsedentry import CollapsedEntry -from jarabe.journal import query - -DS_DBUS_SERVICE = 'org.laptop.sugar.DataStore' -DS_DBUS_INTERFACE = 'org.laptop.sugar.DataStore' -DS_DBUS_PATH = '/org/laptop/sugar/DataStore' - -UPDATE_INTERVAL = 300000 - -EMPTY_JOURNAL = _("Your Journal is empty") -NO_MATCH = _("No matching entries ") - -class BaseListView(gtk.HBox): - __gtype_name__ = 'BaseListView' - - def __init__(self): - self._query = {} - self._result_set = None - self._entries = [] - self._page_size = 0 - self._last_value = -1 - self._reflow_sid = 0 - - gtk.HBox.__init__(self) - self.set_flags(gtk.HAS_FOCUS|gtk.CAN_FOCUS) - self.connect('key-press-event', self._key_press_event_cb) - - self._box = hippo.CanvasBox( - orientation=hippo.ORIENTATION_VERTICAL, - background_color=style.COLOR_WHITE.get_int()) - - self._canvas = hippo.Canvas() - self._canvas.set_root(self._box) - - self.pack_start(self._canvas) - self._canvas.show() - - self._vadjustment = gtk.Adjustment(value=0, lower=0, upper=0, - step_incr=1, page_incr=0, - page_size=0) - self._vadjustment.connect('value-changed', - self._vadjustment_value_changed_cb) - self._vadjustment.connect('changed', self._vadjustment_changed_cb) - - self._vscrollbar = gtk.VScrollbar(self._vadjustment) - self.pack_end(self._vscrollbar, expand=False, fill=False) - self._vscrollbar.show() - - self.connect('scroll-event', self._scroll_event_cb) - self.connect('destroy', self.__destroy_cb) - - # DND stuff - self._pressed_button = None - self._press_start_x = None - self._press_start_y = None - self._last_clicked_entry = None - self._canvas.drag_source_set(0, [], 0) - self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK | - gtk.gdk.POINTER_MOTION_HINT_MASK) - self._canvas.connect_after("motion_notify_event", - self._canvas_motion_notify_event_cb) - self._canvas.connect("button_press_event", - self._canvas_button_press_event_cb) - self._canvas.connect("drag_end", self._drag_end_cb) - self._canvas.connect("drag_data_get", self._drag_data_get_cb) - - # Auto-update stuff - self._fully_obscured = True - self._dirty = False - self._refresh_idle_handler = None - self._update_dates_timer = None - - bus = dbus.SessionBus() - datastore = dbus.Interface( - bus.get_object(DS_DBUS_SERVICE, DS_DBUS_PATH), DS_DBUS_INTERFACE) - self._datastore_created_handler = \ - datastore.connect_to_signal('Created', - self.__datastore_created_cb) - self._datastore_updated_handler = \ - datastore.connect_to_signal('Updated', - self.__datastore_updated_cb) - - self._datastore_deleted_handler = \ - datastore.connect_to_signal('Deleted', - self.__datastore_deleted_cb) - - def __destroy_cb(self, widget): - self._datastore_created_handler.remove() - self._datastore_updated_handler.remove() - self._datastore_deleted_handler.remove() - - if self._result_set: - self._result_set.destroy() - - def _vadjustment_changed_cb(self, vadjustment): - if vadjustment.props.upper > self._page_size: - self._vscrollbar.show() - else: - self._vscrollbar.hide() - - def _vadjustment_value_changed_cb(self, vadjustment): - gobject.idle_add(self._do_scroll) - - def _do_scroll(self, force=False): - import time - t = time.time() - - value = int(self._vadjustment.props.value) - - if value == self._last_value and not force: - return - self._last_value = value - - self._result_set.seek(value) - jobjects = self._result_set.read(self._page_size) - - if self._result_set.length != self._vadjustment.props.upper: - self._vadjustment.props.upper = self._result_set.length - self._vadjustment.changed() - - self._refresh_view(jobjects) - self._dirty = False - - logging.debug('_do_scroll %r %r\n' % (value, (time.time() - t))) - - return False - - def _refresh_view(self, jobjects): - logging.debug('ListView %r' % self) - # Indicate when the Journal is empty - if len(jobjects) == 0: - self._show_message(EMPTY_JOURNAL) - return - - # Refresh view and create the entries if they don't exist yet. - for i in range(0, self._page_size): - try: - if i < len(jobjects): - if i >= len(self._entries): - entry = self.create_entry() - self._box.append(entry) - self._entries.append(entry) - entry.jobject = jobjects[i] - else: - entry = self._entries[i] - entry.jobject = jobjects[i] - entry.set_visible(True) - elif i < len(self._entries): - entry = self._entries[i] - entry.set_visible(False) - except Exception: - logging.error('Exception while displaying entry:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - - def create_entry(self): - """ Create a descendant of BaseCollapsedEntry - """ - raise NotImplementedError - - def update_with_query(self, query_dict): - logging.debug('ListView.update_with_query') - self._query = query_dict - if self._page_size > 0: - self.refresh() - - def refresh(self): - if self._result_set: - self._result_set.destroy() - self._result_set = query.find(self._query) - self._vadjustment.props.upper = self._result_set.length - self._vadjustment.changed() - - self._vadjustment.props.value = min(self._vadjustment.props.value, - self._result_set.length - self._page_size) - if self._result_set.length == 0: - if self._query.get('query', '') or \ - self._query.get('mime_type', '') or \ - self._query.get('mtime', ''): - self._show_message(NO_MATCH) - else: - self._show_message(EMPTY_JOURNAL) - else: - self._clear_message() - self._do_scroll(force=True) - - def _scroll_event_cb(self, hbox, event): - if event.direction == gtk.gdk.SCROLL_UP: - if self._vadjustment.props.value > self._vadjustment.props.lower: - self._vadjustment.props.value -= 1 - elif event.direction == gtk.gdk.SCROLL_DOWN: - max_value = self._result_set.length - self._page_size - if self._vadjustment.props.value < max_value: - self._vadjustment.props.value += 1 - - def do_focus(self, direction): - if not self.is_focus(): - self.grab_focus() - return True - return False - - def _key_press_event_cb(self, widget, event): - keyname = gtk.gdk.keyval_name(event.keyval) - - if keyname == 'Up': - if self._vadjustment.props.value > self._vadjustment.props.lower: - self._vadjustment.props.value -= 1 - elif keyname == 'Down': - max_value = self._result_set.length - self._page_size - if self._vadjustment.props.value < max_value: - self._vadjustment.props.value += 1 - elif keyname == 'Page_Up' or keyname == 'KP_Page_Up': - new_position = max(0, - self._vadjustment.props.value - self._page_size) - if new_position != self._vadjustment.props.value: - self._vadjustment.props.value = new_position - elif keyname == 'Page_Down' or keyname == 'KP_Page_Down': - new_position = min(self._result_set.length - self._page_size, - self._vadjustment.props.value + self._page_size) - if new_position != self._vadjustment.props.value: - self._vadjustment.props.value = new_position - elif keyname == 'Home' or keyname == 'KP_Home': - new_position = 0 - if new_position != self._vadjustment.props.value: - self._vadjustment.props.value = new_position - elif keyname == 'End' or keyname == 'KP_End': - new_position = max(0, self._result_set.length - self._page_size) - if new_position != self._vadjustment.props.value: - self._vadjustment.props.value = new_position - else: - return False - - return True - - def do_size_allocate(self, allocation): - gtk.HBox.do_size_allocate(self, allocation) - new_page_size = int(allocation.height / style.GRID_CELL_SIZE) - - logging.debug("do_size_allocate: %r" % new_page_size) - - if new_page_size != self._page_size: - self._page_size = new_page_size - self._queue_reflow() - - def _queue_reflow(self): - if not self._reflow_sid: - self._reflow_sid = gobject.idle_add(self._reflow_idle_cb) - - def _reflow_idle_cb(self): - self._box.clear() - self._entries = [] - - self._vadjustment.props.page_size = self._page_size - self._vadjustment.props.page_increment = self._page_size - self._vadjustment.changed() - - if self._result_set is None: - self._result_set = query.find(self._query) - - max_value = max(0, self._result_set.length - self._page_size) - if self._vadjustment.props.value > max_value: - self._vadjustment.props.value = max_value - else: - self._do_scroll(force=True) - - self._reflow_sid = 0 - - def _show_message(self, message): - box = hippo.CanvasBox(orientation=hippo.ORIENTATION_VERTICAL, - background_color=style.COLOR_WHITE.get_int(), - yalign=hippo.ALIGNMENT_CENTER) - icon = CanvasIcon(size=style.LARGE_ICON_SIZE, - icon_name='activity-journal', - stroke_color = style.COLOR_BUTTON_GREY.get_svg(), - fill_color = style.COLOR_TRANSPARENT.get_svg()) - text = hippo.CanvasText(text=message, - xalign=hippo.ALIGNMENT_CENTER, - font_desc=style.FONT_NORMAL.get_pango_desc(), - color = style.COLOR_BUTTON_GREY.get_int()) - - box.append(icon) - box.append(text) - self._canvas.set_root(box) - - def _clear_message(self): - self._canvas.set_root(self._box) - - # TODO: Dnd methods. This should be merged somehow inside hippo-canvas. - def _canvas_motion_notify_event_cb(self, widget, event): - if not self._pressed_button: - return True - - # if the mouse button is not pressed, no drag should occurr - if not event.state & gtk.gdk.BUTTON1_MASK: - self._pressed_button = None - return True - - logging.debug("motion_notify_event_cb") - - if event.is_hint: - x, y, state_ = event.window.get_pointer() - else: - x = event.x - y = event.y - - if widget.drag_check_threshold(int(self._press_start_x), - int(self._press_start_y), - int(x), - int(y)): - context_ = widget.drag_begin([('text/uri-list', 0, 0), - ('journal-object-id', 0, 0)], - gtk.gdk.ACTION_COPY, - 1, - event) - return True - - def _drag_end_cb(self, widget, drag_context): - logging.debug("drag_end_cb") - self._pressed_button = None - self._press_start_x = None - self._press_start_y = None - self._last_clicked_entry = None - - def _drag_data_get_cb(self, widget, context, selection, target_type, - event_time): - logging.debug("drag_data_get_cb: requested target " + selection.target) - - jobject = self._last_clicked_entry.jobject - if selection.target == 'text/uri-list': - selection.set(selection.target, 8, jobject.file_path) - elif selection.target == 'journal-object-id': - selection.set(selection.target, 8, jobject.object_id) - - def _canvas_button_press_event_cb(self, widget, event): - logging.debug("button_press_event_cb") - - if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS: - self._last_clicked_entry = \ - self._get_entry_at_coords(event.x, event.y) - if self._last_clicked_entry: - self._pressed_button = event.button - self._press_start_x = event.x - self._press_start_y = event.y - - return False - - def _get_entry_at_coords(self, x, y): - for entry in self._box.get_children(): - entry_x, entry_y = entry.get_context().translate_to_widget(entry) - entry_width, entry_height = entry.get_allocation() - - if (x >= entry_x ) and (x <= entry_x + entry_width) and \ - (y >= entry_y ) and (y <= entry_y + entry_height): - return entry - return None - - def update_dates(self): - logging.debug('ListView.update_dates') - for entry in self._entries: - entry.update_date() - - def __datastore_created_cb(self, uid): - self._set_dirty() - - def __datastore_updated_cb(self, uid): - self._set_dirty() - - def __datastore_deleted_cb(self, uid): - self._set_dirty() - - def _set_dirty(self): - if self._fully_obscured: - self._dirty = True - else: - self._schedule_refresh() - - def _schedule_refresh(self): - if self._refresh_idle_handler is None: - logging.debug('Add refresh idle callback') - self._refresh_idle_handler = \ - gobject.idle_add(self.__refresh_idle_cb) - - def __refresh_idle_cb(self): - self.refresh() - if self._refresh_idle_handler is not None: - logging.debug('Remove refresh idle callback') - gobject.source_remove(self._refresh_idle_handler) - self._refresh_idle_handler = None - return False - - def set_is_visible(self, visible): - logging.debug('canvas_visibility_notify_event_cb %r' % visible) - if visible: - self._fully_obscured = False - if self._dirty: - self._schedule_refresh() - if self._update_dates_timer is None: - logging.debug('Adding date updating timer') - self._update_dates_timer = \ - gobject.timeout_add(UPDATE_INTERVAL, - self.__update_dates_timer_cb) - else: - self._fully_obscured = True - if self._update_dates_timer is not None: - logging.debug('Remove date updating timer') - gobject.source_remove(self._update_dates_timer) - self._update_dates_timer = None - - def __update_dates_timer_cb(self): - self.update_dates() - return True - -class ListView(BaseListView): - __gtype_name__ = 'ListView' - - __gsignals__ = { - 'detail-clicked': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([object])) - } - - def __init__(self): - BaseListView.__init__(self) - - def create_entry(self): - entry = CollapsedEntry() - entry.connect('detail-clicked', self.__entry_activated_cb) - return entry - - def __entry_activated_cb(self, entry): - self.emit('detail-clicked', entry) - diff --git a/src/jarabe/journal/misc.py b/src/jarabe/journal/misc.py deleted file mode 100644 index 19322ad..0000000 --- a/src/jarabe/journal/misc.py +++ /dev/null @@ -1,199 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging -import time -import traceback -import sys -import os -from gettext import gettext as _ - -import gtk - -from sugar.activity import activityfactory -from sugar.activity.activityhandle import ActivityHandle -from sugar import mime -from sugar.bundle.activitybundle import ActivityBundle -from sugar.bundle.contentbundle import ContentBundle -from sugar.bundle.bundle import MalformedBundleException -from sugar import util - -from jarabe.model import bundleregistry -from jarabe.journal.journalentrybundle import JournalEntryBundle - -def _get_icon_file_name(icon_name): - icon_theme = gtk.icon_theme_get_default() - info = icon_theme.lookup_icon(icon_name, gtk.ICON_SIZE_LARGE_TOOLBAR, 0) - if not info: - # display standard icon when icon for mime type is not found - info = icon_theme.lookup_icon('application-octet-stream', - gtk.ICON_SIZE_LARGE_TOOLBAR, 0) - fname = info.get_filename() - del info - return fname - -_icon_cache = util.LRU(50) - -def get_icon_name(jobject): - - cache_key = (jobject.object_id, jobject.metadata.get('timestamp', None)) - if cache_key in _icon_cache: - return _icon_cache[cache_key] - - file_name = None - - if jobject.is_activity_bundle() and jobject.file_path: - try: - bundle = ActivityBundle(jobject.file_path) - file_name = bundle.get_icon() - except Exception: - logging.warning('Could not read bundle:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - file_name = _get_icon_file_name('application-octet-stream') - - if not file_name and jobject.metadata['activity']: - service_name = jobject.metadata['activity'] - activity_info = bundleregistry.get_registry().get_bundle(service_name) - if activity_info: - file_name = activity_info.get_icon() - - mime_type = jobject.metadata['mime_type'] - if not file_name and mime_type: - icon_name = mime.get_mime_icon(mime_type) - if icon_name: - file_name = _get_icon_file_name(icon_name) - - if not file_name or not os.path.exists(file_name): - file_name = _get_icon_file_name('application-octet-stream') - - _icon_cache[cache_key] = file_name - - return file_name - -def get_date(jobject): - """ Convert from a string in iso format to a more human-like format. """ - if jobject.metadata.has_key('timestamp'): - timestamp = float(jobject.metadata['timestamp']) - return util.timestamp_to_elapsed_string(timestamp) - elif jobject.metadata.has_key('mtime'): - ti = time.strptime(jobject.metadata['mtime'], "%Y-%m-%dT%H:%M:%S") - return util.timestamp_to_elapsed_string(time.mktime(ti)) - else: - return _('No date') - -def get_bundle(jobject): - try: - if jobject.is_activity_bundle() and jobject.file_path: - return ActivityBundle(jobject.file_path) - elif jobject.is_content_bundle() and jobject.file_path: - return ContentBundle(jobject.file_path) - elif jobject.metadata['mime_type'] == JournalEntryBundle.MIME_TYPE \ - and jobject.file_path: - return JournalEntryBundle(jobject.file_path) - else: - return None - except MalformedBundleException, e: - logging.warning('Incorrect bundle: %r' % e) - return None - -def _get_activities_for_mime(mime_type): - registry = bundleregistry.get_registry() - result = registry.get_activities_for_type(mime_type) - if not result: - for parent_mime in mime.get_mime_parents(mime_type): - result.extend(registry.get_activities_for_type(parent_mime)) - return result - -def get_activities(jobject): - activities = [] - - bundle_id = jobject.metadata.get('activity', '') - if bundle_id: - activity_info = bundleregistry.get_registry().get_bundle(bundle_id) - if activity_info: - activities.append(activity_info) - - mime_type = jobject.metadata.get('mime_type', '') - if mime_type: - activities_info = _get_activities_for_mime(mime_type) - for activity_info in activities_info: - if activity_info.get_bundle_id() != bundle_id: - activities.append(activity_info) - - return activities - -def resume(jobject, bundle_id=None): - registry = bundleregistry.get_registry() - - if jobject.is_activity_bundle() and not bundle_id: - - logging.debug('Creating activity bundle') - bundle = ActivityBundle(jobject.file_path) - if not registry.is_installed(bundle): - logging.debug('Installing activity bundle') - registry.install(bundle) - else: - logging.debug('Upgrading activity bundle') - registry.upgrade(bundle) - - logging.debug('activityfactory.creating bundle with id %r', - bundle.get_bundle_id()) - installed_bundle = registry.get_bundle(bundle.get_bundle_id()) - if installed_bundle: - activityfactory.create(installed_bundle) - else: - logging.error('Bundle %r is not installed.', - bundle.get_bundle_id()) - - elif jobject.is_content_bundle() and not bundle_id: - - logging.debug('Creating content bundle') - bundle = ContentBundle(jobject.file_path) - if not bundle.is_installed(): - logging.debug('Installing content bundle') - bundle.install() - - activities = _get_activities_for_mime('text/html') - if len(activities) == 0: - logging.warning('No activity can open HTML content bundles') - return - - uri = bundle.get_start_uri() - logging.debug('activityfactory.creating with uri %s', uri) - - activity_bundle = registry.get_bundle(activities[0].get_bundle_id()) - activityfactory.create_with_uri(activity_bundle, bundle.get_start_uri()) - else: - if bundle_id is None: - activities = get_activities(jobject) - if not activities: - logging.warning('No activity can open this object, %s.' % - jobject.metadata.get('mime_type', None)) - return - bundle_id = activities[0].get_bundle_id() - - bundle = registry.get_bundle(bundle_id) - - activity_id = jobject.metadata['activity_id'] - object_id = jobject.object_id - - if activity_id: - handle = ActivityHandle(object_id=object_id, - activity_id=activity_id) - activityfactory.create(bundle, handle) - else: - activityfactory.create_with_object_id(bundle, object_id) - diff --git a/src/jarabe/journal/modalalert.py b/src/jarabe/journal/modalalert.py deleted file mode 100644 index a5a86ab..0000000 --- a/src/jarabe/journal/modalalert.py +++ /dev/null @@ -1,97 +0,0 @@ -# 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 - -import gtk -from gettext import gettext as _ -import gconf - -from sugar.graphics.icon import Icon -from sugar.graphics import style -from sugar.graphics.xocolor import XoColor - -class ModalAlert(gtk.Window): - - __gtype_name__ = 'SugarModalAlert' - - def __init__(self): - gtk.Window.__init__(self) - - self.set_border_width(style.LINE_WIDTH) - offset = style.GRID_CELL_SIZE - width = gtk.gdk.screen_width() - offset * 2 - height = gtk.gdk.screen_height() - offset * 2 - self.set_size_request(width, height) - self.set_position(gtk.WIN_POS_CENTER_ALWAYS) - self.set_decorated(False) - self.set_resizable(False) - self.set_modal(True) - - self._main_view = gtk.EventBox() - self._vbox = gtk.VBox() - self._vbox.set_spacing(style.DEFAULT_SPACING) - self._vbox.set_border_width(style.GRID_CELL_SIZE * 2) - self._main_view.modify_bg(gtk.STATE_NORMAL, - style.COLOR_BLACK.get_gdk_color()) - self._main_view.add(self._vbox) - self._vbox.show() - - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - - icon = Icon(icon_name='activity-journal', - pixel_size=style.XLARGE_ICON_SIZE, - xo_color=color) - self._vbox.pack_start(icon, False) - icon.show() - - self._title = gtk.Label() - self._title.modify_fg(gtk.STATE_NORMAL, - style.COLOR_WHITE.get_gdk_color()) - self._title.set_markup('<b>%s</b>' % _('Your Journal is full')) - self._vbox.pack_start(self._title, False) - self._title.show() - - self._message = gtk.Label(_('Please delete some old Journal' - ' entries to make space for new ones.')) - self._message.modify_fg(gtk.STATE_NORMAL, - style.COLOR_WHITE.get_gdk_color()) - self._vbox.pack_start(self._message, False) - self._message.show() - - alignment = gtk.Alignment(xalign=0.5, yalign=0.5) - self._vbox.pack_start(alignment, expand=False) - alignment.show() - - self._show_journal = gtk.Button() - self._show_journal.set_label(_('Show Journal')) - alignment.add(self._show_journal) - self._show_journal.show() - self._show_journal.connect('clicked', self.__show_journal_cb) - - self.add(self._main_view) - self._main_view.show() - - self.connect("realize", self.__realize_cb) - - def __realize_cb(self, widget): - self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - self.window.set_accept_focus(True) - - def __show_journal_cb(self, button): - '''The opener will listen on the destroy signal - ''' - self.destroy() - diff --git a/src/jarabe/journal/objectchooser.py b/src/jarabe/journal/objectchooser.py deleted file mode 100644 index 947141d..0000000 --- a/src/jarabe/journal/objectchooser.py +++ /dev/null @@ -1,199 +0,0 @@ -# Copyright (C) 2007, 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 gettext import gettext as _ -import logging - -import gobject -import gtk -import hippo - -from sugar.graphics import style -from sugar.graphics.toolbutton import ToolButton -from sugar.datastore import datastore - -from jarabe.journal.listview import ListView -from jarabe.journal.collapsedentry import BaseCollapsedEntry -from jarabe.journal.journaltoolbox import SearchToolbar -from jarabe.journal.volumestoolbar import VolumesToolbar - -class ObjectChooser(gtk.Window): - - __gtype_name__ = 'ObjectChooser' - - __gsignals__ = { - 'response': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([int])) - } - - def __init__(self, parent=None): - gtk.Window.__init__(self) - self.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) - self.set_decorated(False) - self.set_position(gtk.WIN_POS_CENTER_ALWAYS) - self.set_border_width(style.LINE_WIDTH) - - self._selected_object_id = None - - self.add_events(gtk.gdk.VISIBILITY_NOTIFY_MASK) - self.connect('visibility-notify-event', - self.__visibility_notify_event_cb) - self.connect('delete-event', self.__delete_event_cb) - self.connect('key-press-event', self.__key_press_event_cb) - if parent is not None: - self.connect('realize', self.__realize_cb, parent) - - vbox = gtk.VBox() - self.add(vbox) - vbox.show() - - title_box = TitleBox() - title_box.connect('volume-changed', self.__volume_changed_cb) - title_box.close_button.connect('clicked', - self.__close_button_clicked_cb) - title_box.set_size_request(-1, style.GRID_CELL_SIZE) - vbox.pack_start(title_box, expand=False) - title_box.show() - - separator = gtk.HSeparator() - vbox.pack_start(separator, expand=False) - separator.show() - - self._toolbar = SearchToolbar() - self._toolbar.connect('query-changed', self.__query_changed_cb) - self._toolbar.set_size_request(-1, style.GRID_CELL_SIZE) - vbox.pack_start(self._toolbar, expand=False) - self._toolbar.show() - - self._list_view = ChooserListView() - self._list_view.connect('entry-activated', self.__entry_activated_cb) - vbox.pack_start(self._list_view) - self._list_view.show() - - self._toolbar.set_volume_id(datastore.mounts()[0]['id']) - - width = gtk.gdk.screen_width() - style.GRID_CELL_SIZE * 2 - height = gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 2 - self.set_size_request(width, height) - - def __realize_cb(self, chooser, parent): - self.window.set_transient_for(parent) - # TODO: Should we disconnect the signal here? - - def __entry_activated_cb(self, list_view, entry): - self._selected_object_id = entry.jobject.object_id - self.emit('response', gtk.RESPONSE_ACCEPT) - - def __delete_event_cb(self, chooser, event): - self.emit('response', gtk.RESPONSE_DELETE_EVENT) - - def __key_press_event_cb(self, widget, event): - keyname = gtk.gdk.keyval_name(event.keyval) - if keyname == 'Escape': - self.emit('response', gtk.RESPONSE_DELETE_EVENT) - - def __close_button_clicked_cb(self, button): - self.emit('response', gtk.RESPONSE_DELETE_EVENT) - - def get_selected_object_id(self): - return self._selected_object_id - - def __query_changed_cb(self, toolbar, query): - self._list_view.update_with_query(query) - - def __volume_changed_cb(self, volume_toolbar, volume_id): - logging.debug('Selected volume: %r.' % volume_id) - self._toolbar.set_volume_id(volume_id) - - def __visibility_notify_event_cb(self, window, event): - logging.debug('visibility_notify_event_cb %r' % self) - visible = event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED - self._list_view.set_is_visible(visible) - -class TitleBox(VolumesToolbar): - __gtype_name__ = 'TitleBox' - - def __init__(self): - VolumesToolbar.__init__(self) - - label = gtk.Label() - label.set_markup('<b>%s</b>' % _('Choose an object')) - label.set_alignment(0, 0.5) - self._add_widget(label, expand=True) - - self.close_button = ToolButton(icon_name='dialog-cancel') - self.close_button.set_tooltip(_('Close')) - self.insert(self.close_button, -1) - self.close_button.show() - - def _add_widget(self, widget, expand=False): - tool_item = gtk.ToolItem() - tool_item.set_expand(expand) - - tool_item.add(widget) - widget.show() - - self.insert(tool_item, -1) - tool_item.show() - -class ChooserCollapsedEntry(BaseCollapsedEntry): - __gtype_name__ = 'ChooserCollapsedEntry' - - __gsignals__ = { - 'entry-activated': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([])) - } - - def __init__(self): - BaseCollapsedEntry.__init__(self) - - self.connect_after('button-release-event', - self.__button_release_event_cb) - self.connect('motion-notify-event', self.__motion_notify_event_cb) - - def __button_release_event_cb(self, entry, event): - self.emit('entry-activated') - return True - - def __motion_notify_event_cb(self, entry, event): - if event.detail == hippo.MOTION_DETAIL_ENTER: - self.props.background_color = style.COLOR_PANEL_GREY.get_int() - elif event.detail == hippo.MOTION_DETAIL_LEAVE: - self.props.background_color = style.COLOR_WHITE.get_int() - return False - -class ChooserListView(ListView): - __gtype_name__ = 'ChooserListView' - - __gsignals__ = { - 'entry-activated': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([object])) - } - - def __init__(self): - ListView.__init__(self) - - def create_entry(self): - entry = ChooserCollapsedEntry() - entry.connect('entry-activated', self.__entry_activated_cb) - return entry - - def __entry_activated_cb(self, entry): - self.emit('entry-activated', entry) - diff --git a/src/jarabe/journal/palettes.py b/src/jarabe/journal/palettes.py deleted file mode 100644 index 9ca1190..0000000 --- a/src/jarabe/journal/palettes.py +++ /dev/null @@ -1,119 +0,0 @@ -# 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 gettext import gettext as _ -import logging -import gconf - -import gtk - -from sugar.graphics import style -from sugar.graphics.palette import Palette -from sugar.graphics.menuitem import MenuItem -from sugar.graphics.icon import Icon -from sugar.datastore import datastore -from sugar.graphics.xocolor import XoColor - -from jarabe.model import bundleregistry -from jarabe.journal import misc - -class ObjectPalette(Palette): - def __init__(self, jobject): - - self._jobject = jobject - - activity_icon = Icon(icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - activity_icon.props.file = misc.get_icon_name(jobject) - if jobject.metadata.has_key('icon-color') and \ - jobject.metadata['icon-color']: - activity_icon.props.xo_color = \ - XoColor(jobject.metadata['icon-color']) - else: - activity_icon.props.xo_color = \ - XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), - style.COLOR_TRANSPARENT.get_svg())) - - if jobject.metadata.has_key('title'): - title = jobject.metadata['title'] - else: - title = _('Untitled') - - Palette.__init__(self, primary_text=title, - icon=activity_icon) - - if jobject.metadata.get('activity_id', ''): - resume_label = _('Resume') - else: - resume_label = _('Start') - menu_item = MenuItem(resume_label, 'activity-start') - menu_item.connect('activate', self.__start_activate_cb) - self.menu.append(menu_item) - menu_item.show() - - # TODO: Add "Start with" menu item - - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - menu_item = MenuItem(_('Copy')) - icon = Icon(icon_name='edit-copy', xo_color=color, - icon_size=gtk.ICON_SIZE_MENU) - menu_item.set_image(icon) - menu_item.connect('activate', self.__copy_activate_cb) - self.menu.append(menu_item) - menu_item.show() - - menu_item = MenuItem(_('Erase'), 'list-remove') - menu_item.connect('activate', self.__erase_activate_cb) - self.menu.append(menu_item) - menu_item.show() - - def __start_activate_cb(self, menu_item): - misc.resume(self._jobject) - - def __copy_activate_cb(self, menu_item): - clipboard = gtk.Clipboard() - clipboard.set_with_data([('text/uri-list', 0, 0)], - self.__clipboard_get_func_cb, - self.__clipboard_clear_func_cb) - - def __clipboard_get_func_cb(self, clipboard, selection_data, info, data): - logging.debug('__clipboard_get_func_cb %r' % self._jobject.file_path) - selection_data.set_uris(['file://' + self._jobject.file_path]) - - def __clipboard_clear_func_cb(self, clipboard, data): - pass - - def __erase_activate_cb(self, menu_item): - registry = bundleregistry.get_registry() - - bundle = misc.get_bundle(self._jobject) - if bundle is not None and registry.is_installed(bundle): - registry.uninstall(bundle) - datastore.delete(self._jobject.object_id) - -class BuddyPalette(Palette): - def __init__(self, buddy): - self._buddy = buddy - - nick, colors = buddy - buddy_icon = Icon(icon_name='computer-xo', - icon_size=style.STANDARD_ICON_SIZE, - xo_color=XoColor(colors)) - - Palette.__init__(self, primary_text=nick, - icon=buddy_icon) - - # TODO: Support actions on buddies, like make friend, invite, etc. diff --git a/src/jarabe/journal/query.py b/src/jarabe/journal/query.py deleted file mode 100644 index 04d9b16..0000000 --- a/src/jarabe/journal/query.py +++ /dev/null @@ -1,266 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging - -from sugar.datastore import datastore - -# Properties the journal cares about. -PROPERTIES = ['uid', 'title', 'mtime', 'timestamp', 'keep', 'buddies', - 'icon-color', 'mime_type', 'progress', 'activity', 'mountpoint', - 'activity_id'] - -class _Cache(object): - - __gtype_name__ = 'query_Cache' - - def __init__(self, jobjects=None): - self._array = [] - self._dict = {} - if jobjects is not None: - self.append_all(jobjects) - - def prepend_all(self, jobjects): - for jobject in jobjects[::-1]: - self._array.insert(0, jobject) - self._dict[jobject.object_id] = jobject - - def append_all(self, jobjects): - for jobject in jobjects: - self._array.append(jobject) - self._dict[jobject.object_id] = jobject - - def remove_all(self, jobjects): - jobjects = jobjects[:] - for jobject in jobjects: - obj = self._dict[jobject.object_id] - self._array.remove(obj) - del self._dict[obj.object_id] - obj.destroy() - - def __len__(self): - return len(self._array) - - def __getitem__(self, key): - if isinstance(key, basestring): - return self._dict[key] - else: - return self._array[key] - - def destroy(self): - self._destroy_jobjects(self._array) - self._array = [] - self._dict = {} - - def _destroy_jobjects(self, jobjects): - for jobject in jobjects: - jobject.destroy() - -class ResultSet(object): - - _CACHE_LIMIT = 80 - - def __init__(self, query, sorting): - self._total_count = -1 - self._position = -1 - self._query = query - self._sorting = sorting - - self._offset = 0 - self._cache = _Cache() - - def destroy(self): - self._cache.destroy() - - def get_length(self): - if self._total_count == -1: - jobjects, self._total_count = datastore.find(self._query, - sorting=self._sorting, - limit=ResultSet._CACHE_LIMIT, - properties=PROPERTIES) - self._cache.append_all(jobjects) - self._offset = 0 - return self._total_count - - length = property(get_length) - - def seek(self, position): - self._position = position - - def read(self, max_count): - logging.debug('ResultSet.read position: %r' % self._position) - - if max_count * 5 > ResultSet._CACHE_LIMIT: - raise RuntimeError( - 'max_count (%i) too big for ResultSet._CACHE_LIMIT' - ' (%i).' % (max_count, ResultSet._CACHE_LIMIT)) - - if self._position == -1: - self.seek(0) - - if self._position < self._offset: - remaining_forward_entries = 0 - else: - remaining_forward_entries = self._offset + len(self._cache) - \ - self._position - - if self._position > self._offset + len(self._cache): - remaining_backwards_entries = 0 - else: - remaining_backwards_entries = self._position - self._offset - - last_cached_entry = self._offset + len(self._cache) - - if (remaining_forward_entries <= 0 and - remaining_backwards_entries <= 0) or \ - max_count > ResultSet._CACHE_LIMIT: - - # Total cache miss: remake it - offset = max(0, self._position - max_count) - logging.debug('remaking cache, offset: %r limit: %r' % \ - (offset, max_count * 2)) - jobjects, self._total_count = datastore.find(self._query, - sorting=self._sorting, - offset=offset, - limit=ResultSet._CACHE_LIMIT, - properties=PROPERTIES) - - self._cache.remove_all(self._cache) - self._cache.append_all(jobjects) - self._offset = offset - - elif remaining_forward_entries < 2 * max_count and \ - last_cached_entry < self._total_count: - - # Add one page to the end of cache - logging.debug('appending one more page, offset: %r' % \ - last_cached_entry) - jobjects, self._total_count = datastore.find(self._query, - sorting=self._sorting, - offset=last_cached_entry, - limit=max_count, - properties=PROPERTIES) - # update cache - self._cache.append_all(jobjects) - - # apply the cache limit - objects_excess = len(self._cache) - ResultSet._CACHE_LIMIT - if objects_excess > 0: - self._offset += objects_excess - self._cache.remove_all(self._cache[:objects_excess]) - - elif remaining_backwards_entries < 2 * max_count and self._offset > 0: - - # Add one page to the beginning of cache - limit = min(self._offset, max_count) - self._offset = max(0, self._offset - max_count) - - logging.debug('prepending one more page, offset: %r limit: %r' % - (self._offset, limit)) - jobjects, self._total_count = datastore.find(self._query, - sorting=self._sorting, - offset=self._offset, - limit=limit, - properties=PROPERTIES) - - # update cache - self._cache.prepend_all(jobjects) - - # apply the cache limit - objects_excess = len(self._cache) - ResultSet._CACHE_LIMIT - if objects_excess > 0: - self._cache.remove_all(self._cache[-objects_excess:]) - else: - logging.debug('cache hit and no need to grow the cache') - - first_pos = self._position - self._offset - last_pos = self._position - self._offset + max_count - return self._cache[first_pos:last_pos] - -def find(query, sorting=None): - if sorting is None: - sorting = ['-mtime'] - result_set = ResultSet(query, sorting) - return result_set - -def test(): - TOTAL_ITEMS = 1000 - SCREEN_SIZE = 10 - - def mock_debug(string): - print "\tDEBUG: %s" % string - logging.debug = mock_debug - - def mock_find(query, sorting=None, limit=None, offset=None, - properties=None): - if properties is None: - properties = [] - - print "mock_find %r %r" % (offset, (offset + limit)) - - if limit is None or offset is None: - raise RuntimeError("Unimplemented test.") - - result = [] - for index in range(offset, offset + limit): - obj = datastore.DSObject(index, datastore.DSMetadata({}), '') - result.append(obj) - - return result, TOTAL_ITEMS - datastore.find = mock_find - - result_set = find({}) - - print "Get first page" - objects = result_set.read(SCREEN_SIZE) - print [obj.object_id for obj in objects] - assert range(0, SCREEN_SIZE) == [obj.object_id for obj in objects] - print "" - - print "Scroll to 5th item" - result_set.seek(5) - objects = result_set.read(SCREEN_SIZE) - print [obj.object_id for obj in objects] - assert range(5, SCREEN_SIZE + 5) == [obj.object_id for obj in objects] - print "" - - print "Scroll back to beginning" - result_set.seek(0) - objects = result_set.read(SCREEN_SIZE) - print [obj.object_id for obj in objects] - assert range(0, SCREEN_SIZE) == [obj.object_id for obj in objects] - print "" - - print "Hit PgDn five times" - for i in range(0, 5): - result_set.seek((i + 1) * SCREEN_SIZE) - objects = result_set.read(SCREEN_SIZE) - print [obj.object_id for obj in objects] - assert range((i + 1) * SCREEN_SIZE, (i + 2) * SCREEN_SIZE) == \ - [obj.object_id for obj in objects] - print "" - - print "Hit PgUp five times" - for i in range(0, 5)[::-1]: - result_set.seek(i * SCREEN_SIZE) - objects = result_set.read(SCREEN_SIZE) - print [obj.object_id for obj in objects] - assert range(i * SCREEN_SIZE, (i + 1) * SCREEN_SIZE) == \ - [obj.object_id for obj in objects] - print "" - -if __name__ == "__main__": - test() diff --git a/src/jarabe/journal/volumestoolbar.py b/src/jarabe/journal/volumestoolbar.py deleted file mode 100644 index b29f325..0000000 --- a/src/jarabe/journal/volumestoolbar.py +++ /dev/null @@ -1,138 +0,0 @@ -# Copyright (C) 2007, 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 - -import logging -from gettext import gettext as _ - -import gobject -import gtk - -from sugar.datastore import datastore -from sugar.graphics.radiotoolbutton import RadioToolButton -from sugar.graphics.palette import Palette - -from jarabe.model import volume - -class VolumesToolbar(gtk.Toolbar): - __gtype_name__ = 'VolumesToolbar' - - __gsignals__ = { - 'volume-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([str])) - } - - def __init__(self): - gtk.Toolbar.__init__(self) - self._volume_buttons = [] - self._volume_added_hid = None - self._volume_removed_hid = None - - self.connect('destroy', self.__destroy_cb) - - # 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 = 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 = 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 vol in volumes_manager.get_volumes(): - self._add_button(vol) - - def _volume_added_cb(self, volumes_manager, vol): - self._add_button(vol) - - def _volume_removed_cb(self, volumes_manager, vol): - self._remove_button(vol) - - 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(vol.name) - - button = VolumeButton(vol, group) - button.set_palette(palette) - button.connect('toggled', self._button_toggled_cb, vol) - if self._volume_buttons: - position = self.get_item_index(self._volume_buttons[-1]) + 1 - else: - position = 0 - self.insert(button, position) - button.show() - - self._volume_buttons.append(button) - - if vol.can_unmount: - menu_item = gtk.MenuItem(_('Unmount')) - 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, vol): - if button.props.active: - self.emit('volume-changed', vol.id) - - def _unmount_activated_cb(self, menu_item, vol): - logging.debug('VolumesToolbar._unmount_activated_cb: %r', vol.udi) - vol.unmount() - - def _remove_button(self, vol): - for button in self.get_children(): - if button.volume.id == vol.id: - self._volume_buttons.remove(button) - self.remove(button) - self.get_children()[0].props.active = True - - if len(self.get_children()) < 2: - self.hide() - return - -class VolumeButton(RadioToolButton): - def __init__(self, vol, group): - RadioToolButton.__init__(self) - self.props.named_icon = vol.icon_name - self.props.xo_color = vol.icon_color - self.props.group = group - - self.volume = vol - self.drag_dest_set(gtk.DEST_DEFAULT_ALL, - [('journal-object-id', 0, 0)], - gtk.gdk.ACTION_COPY) - self.connect('drag-data-received', self._drag_data_received_cb) - - def _drag_data_received_cb(self, widget, drag_context, x, y, selection_data, - info, timestamp): - jobject = datastore.get(selection_data.data) - datastore.copy(jobject, self.volume.id) diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am deleted file mode 100644 index 71ba988..0000000 --- a/src/jarabe/model/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -sugardir = $(pythondir)/jarabe/model -sugar_PYTHON = \ - __init__.py \ - buddy.py \ - bundleregistry.py \ - friends.py \ - invites.py \ - owner.py \ - neighborhood.py \ - network.py \ - notifications.py \ - shell.py \ - screen.py \ - session.py \ - sound.py \ - volume.py diff --git a/src/jarabe/model/Makefile.in b/src/jarabe/model/Makefile.in deleted file mode 100644 index 9c680e2..0000000 --- a/src/jarabe/model/Makefile.in +++ /dev/null @@ -1,405 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = src/jarabe/model -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/model -sugar_PYTHON = \ - __init__.py \ - buddy.py \ - bundleregistry.py \ - friends.py \ - invites.py \ - owner.py \ - neighborhood.py \ - network.py \ - notifications.py \ - shell.py \ - screen.py \ - session.py \ - sound.py \ - volume.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/model/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/model/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/jarabe/model/neighborhood.py b/src/jarabe/model/neighborhood.py deleted file mode 100644 index f4ef9ac..0000000 --- a/src/jarabe/model/neighborhood.py +++ /dev/null @@ -1,273 +0,0 @@ -# Copyright (C) 2006-2007 Red Hat, Inc. -# -# 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 - -import gobject -import gconf -import logging - -from sugar.graphics.xocolor import XoColor -from sugar.presence import presenceservice -from sugar import activity - -from jarabe.model.buddy import BuddyModel -from jarabe.model import bundleregistry -from jarabe.util.telepathy import connection_watcher - -from dbus import PROPERTIES_IFACE -from telepathy.interfaces import CONNECTION_INTERFACE_REQUESTS -from telepathy.interfaces import CHANNEL_INTERFACE -from telepathy.client import Channel - -CONN_INTERFACE_GADGET = 'org.laptop.Telepathy.Gadget' -CHAN_INTERFACE_VIEW = 'org.laptop.Telepathy.Channel.Interface.View' -CHAN_INTERFACE_BUDBY_VIEW = 'org.laptop.Telepathy.Channel.Type.BuddyView' -CHAN_INTERFACE_ACTIVITY_VIEW = 'org.laptop.Telepathy.Channel.Type.ActivityView' - -NB_RANDOM_BUDDIES = 20 -NB_RANDOM_ACTIVITIES = 40 - -class ActivityModel: - def __init__(self, act, bundle): - self.activity = act - self.bundle = bundle - - def get_id(self): - return self.activity.props.id - - def get_icon_name(self): - return self.bundle.get_icon() - - def get_color(self): - return XoColor(self.activity.props.color) - - def get_bundle_id(self): - return self.bundle.get_bundle_id() - -class Neighborhood(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])), - 'buddy-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), - 'buddy-moved': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT, - gobject.TYPE_PYOBJECT])), - 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])) - } - - def __init__(self): - gobject.GObject.__init__(self) - - self._activities = {} - self._buddies = {} - - self._pservice = presenceservice.get_instance() - self._pservice.connect("activity-appeared", - self._activity_appeared_cb) - self._pservice.connect('activity-disappeared', - self._activity_disappeared_cb) - self._pservice.connect("buddy-appeared", - self._buddy_appeared_cb) - self._pservice.connect("buddy-disappeared", - self._buddy_disappeared_cb) - - # Add any buddies the PS knows about already - self._pservice.get_buddies_async(reply_handler=self._get_buddies_cb) - - self._pservice.get_activities_async( - reply_handler=self._get_activities_cb) - - self._conn_watcher = connection_watcher.ConnectionWatcher() - self._conn_watcher.connect('connection-added', self.__conn_addded_cb) - - for conn in self._conn_watcher.get_connections(): - self.__conn_addded_cb(self._conn_watcher, conn) - - gconf_client = gconf.client_get_default() - gconf_client.add_dir('/desktop/sugar/collaboration', - gconf.CLIENT_PRELOAD_NONE) - gconf_client.notify_add('/desktop/sugar/collaboration/publish_gadget', - self.__publish_gadget_changed_cb) - - def __conn_addded_cb(self, watcher, conn): - if CONN_INTERFACE_GADGET not in conn: - return - - conn[CONN_INTERFACE_GADGET].connect_to_signal('GadgetDiscovered', - lambda: self._gadget_discovered(conn)) - - gadget_discovered = conn[PROPERTIES_IFACE].Get(CONN_INTERFACE_GADGET, - 'GadgetAvailable') - if gadget_discovered: - self._gadget_discovered(conn) - - def _gadget_discovered(self, conn): - gconf_client = gconf.client_get_default() - key = '/desktop/sugar/collaboration/publish_gadget' - publish = gconf_client.get_bool(key) - logging.debug("Gadget discovered on connection %s." - " Publish our status: %r" % - (conn.service_name.split('.')[-1], publish)) - conn[CONN_INTERFACE_GADGET].Publish(publish) - - self._request_random_buddies(conn, NB_RANDOM_BUDDIES) - self._request_random_activities(conn, NB_RANDOM_ACTIVITIES) - - def _request_random_buddies(self, conn, nb): - logging.debug("Request %d random buddies" % nb) - - path, props_ = conn[CONNECTION_INTERFACE_REQUESTS].CreateChannel( - { 'org.freedesktop.Telepathy.Channel.ChannelType': - 'org.laptop.Telepathy.Channel.Type.BuddyView', - 'org.laptop.Telepathy.Channel.Interface.View.MaxSize': nb - }) - - view = Channel(conn.service_name, path) - view[CHANNEL_INTERFACE].connect_to_signal('Closed', - lambda: self.__respawnable_view_closed_cb( - lambda: self._request_random_buddies(conn, nb))) - - def _request_random_activities(self, conn, nb): - logging.debug("Request %d random activities" % nb) - - path, props_ = conn[CONNECTION_INTERFACE_REQUESTS].CreateChannel( - { 'org.freedesktop.Telepathy.Channel.ChannelType': - 'org.laptop.Telepathy.Channel.Type.ActivityView', - 'org.laptop.Telepathy.Channel.Interface.View.MaxSize': nb - }) - - view = Channel(conn.service_name, path) - view[CHANNEL_INTERFACE].connect_to_signal('Closed', - lambda: self.__respawnable_view_closed_cb( - lambda: self._request_random_activities(conn, nb))) - - def __publish_gadget_changed_cb(self, client_, cnxn_id_, entry, - user_data=None): - if entry.value.type == gconf.VALUE_BOOL: - publish = entry.value.get_bool() - - for conn in self._conn_watcher.get_connections(): - if CONN_INTERFACE_GADGET not in conn: - continue - - gadget_discovered = conn[PROPERTIES_IFACE].Get( - CONN_INTERFACE_GADGET, 'GadgetAvailable') - if gadget_discovered: - logging.debug("publish_gadget gconf key changed." - " Publish our status on %s: %r" % - (conn.service_name.split('.')[-1], publish)) - conn[CONN_INTERFACE_GADGET].Publish(publish) - - def __respawnable_view_closed_cb(self, request_fct): - # Views are closed if the Gadget component is restarted. As we always - # want to have the random views opened, we re-request them if they are - # closed. - logging.debug('View closed. Re-request it') - request_fct() - - def _get_buddies_cb(self, buddy_list): - for buddy in buddy_list: - self._buddy_appeared_cb(self._pservice, buddy) - - def _get_activities_cb(self, activity_list): - for act in activity_list: - self._check_activity(act) - - def get_activities(self): - return self._activities.values() - - def get_buddies(self): - return self._buddies.values() - - def _buddy_activity_changed_cb(self, model, cur_activity): - if not self._buddies.has_key(model.get_buddy().object_path()): - return - if cur_activity and self._activities.has_key(cur_activity.props.id): - activity_model = self._activities[cur_activity.props.id] - self.emit('buddy-moved', model, activity_model) - else: - self.emit('buddy-moved', model, None) - - def _buddy_appeared_cb(self, pservice, buddy): - if self._buddies.has_key(buddy.object_path()): - return - - model = BuddyModel(buddy=buddy) - model.connect('current-activity-changed', - self._buddy_activity_changed_cb) - self._buddies[buddy.object_path()] = model - self.emit('buddy-added', model) - - cur_activity = buddy.props.current_activity - if cur_activity: - self._buddy_activity_changed_cb(model, cur_activity) - - def _buddy_disappeared_cb(self, pservice, buddy): - if not self._buddies.has_key(buddy.object_path()): - return - self.emit('buddy-removed', self._buddies[buddy.object_path()]) - del self._buddies[buddy.object_path()] - - def _activity_appeared_cb(self, pservice, act): - self._check_activity(act) - - def _check_activity(self, presence_activity): - registry = bundleregistry.get_registry() - bundle = registry.get_bundle(presence_activity.props.type) - if not bundle: - return - if self.has_activity(presence_activity.props.id): - return - self.add_activity(bundle, presence_activity) - - def has_activity(self, activity_id): - return self._activities.has_key(activity_id) - - def get_activity(self, activity_id): - if self.has_activity(activity_id): - return self._activities[activity_id] - else: - return None - - def add_activity(self, bundle, act): - model = ActivityModel(act, bundle) - self._activities[model.get_id()] = model - self.emit('activity-added', model) - - for buddy in self._pservice.get_buddies(): - cur_activity = buddy.props.current_activity - object_path = buddy.object_path() - if cur_activity == activity and object_path in self._buddies: - buddy_model = self._buddies[object_path] - self.emit('buddy-moved', buddy_model, model) - - def _activity_disappeared_cb(self, pservice, act): - if self._activities.has_key(act.props.id): - activity_model = self._activities[act.props.id] - self.emit('activity-removed', activity_model) - del self._activities[act.props.id] - -_model = None - -def get_model(): - global _model - if _model is None: - _model = Neighborhood() - return _model diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py deleted file mode 100644 index d793deb..0000000 --- a/src/jarabe/model/network.py +++ /dev/null @@ -1,363 +0,0 @@ -# Copyright (C) 2008 Red Hat, Inc. -# -# 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 - -import logging -import os - -import dbus -import ConfigParser - -from sugar import dispatch -from sugar import env - -DEVICE_TYPE_802_11_WIRELESS = 2 - -DEVICE_STATE_UNKNOWN = 0 -DEVICE_STATE_UNMANAGED = 1 -DEVICE_STATE_UNAVAILABLE = 2 -DEVICE_STATE_DISCONNECTED = 3 -DEVICE_STATE_PREPARE = 4 -DEVICE_STATE_CONFIG = 5 -DEVICE_STATE_NEED_AUTH = 6 -DEVICE_STATE_IP_CONFIG = 7 -DEVICE_STATE_ACTIVATED = 8 -DEVICE_STATE_FAILED = 9 - -NM_802_11_AP_FLAGS_NONE = 0x00000000 -NM_802_11_AP_FLAGS_PRIVACY = 0x00000001 - -NM_802_11_AP_SEC_NONE = 0x00000000 -NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001 -NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002 -NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004 -NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008 -NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010 -NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020 -NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040 -NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080 -NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100 -NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200 - -NM_802_11_MODE_UNKNOWN = 0 -NM_802_11_MODE_ADHOC = 1 -NM_802_11_MODE_INFRA = 2 - -NM_802_11_DEVICE_CAP_NONE = 0x00000000 -NM_802_11_DEVICE_CAP_CIPHER_WEP40 = 0x00000001 -NM_802_11_DEVICE_CAP_CIPHER_WEP104 = 0x00000002 -NM_802_11_DEVICE_CAP_CIPHER_TKIP = 0x00000004 -NM_802_11_DEVICE_CAP_CIPHER_CCMP = 0x00000008 -NM_802_11_DEVICE_CAP_WPA = 0x00000010 -NM_802_11_DEVICE_CAP_RSN = 0x00000020 - -SETTINGS_SERVICE = 'org.freedesktop.NetworkManagerUserSettings' - -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_settings = None -_conn_counter = 0 - -class WirelessSecurity(object): - def __init__(self): - self.key_mgmt = None - self.proto = None - self.group = None - self.pairwise = None - - def get_dict(self): - wireless_security = {} - - if self.key_mgmt is not None: - wireless_security['key-mgmt'] = self.key_mgmt - if self.proto is not None: - wireless_security['proto'] = self.proto - if self.pairwise is not None: - wireless_security['pairwise'] = self.pairwise - if self.group is not None: - wireless_security['group'] = self.group - - return wireless_security - -class Wireless(object): - def __init__(self): - self.ssid = None - - def get_dict(self): - return {'ssid': self.ssid} - -class Connection(object): - def __init__(self): - self.id = None - self.uuid = None - self.type = None - - def get_dict(self): - return {'id': self.id, - 'uuid': self.uuid, - 'type': self.type} - -class Settings(object): - def __init__(self): - self.connection = Connection() - self.wireless = Wireless() - self.wireless_security = None - - def get_dict(self): - settings = {} - settings['connection'] = self.connection.get_dict() - settings['802-11-wireless'] = self.wireless.get_dict() - if self.wireless_security is not None: - settings['802-11-wireless-security'] = \ - self.wireless_security.get_dict() - return settings - -class Secrets(object): - def __init__(self): - self.wep_key = None - self.psk = None - self.auth_alg = None - - def get_dict(self): - secrets = {} - - if self.wep_key is not None: - secrets['wep-key0'] = self.wep_key - if self.psk is not None: - secrets['psk'] = self.psk - if self.auth_alg is not None: - secrets['auth-alg'] = self.auth_alg - - return {'802-11-wireless-security': secrets} - -class NMSettings(dbus.service.Object): - def __init__(self): - bus = dbus.SystemBus() - bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus) - dbus.service.Object.__init__(self, bus_name, NM_SETTINGS_PATH) - - self.connections = {} - self.secrets_request = dispatch.Signal() - - @dbus.service.method(dbus_interface=NM_SETTINGS_IFACE, - in_signature='', out_signature='ao') - def ListConnections(self): - return self.connections.values() - - @dbus.service.signal(NM_SETTINGS_IFACE, signature='o') - def NewConnection(self, connection_path): - pass - - def add_connection(self, ssid, conn): - self.connections[ssid] = conn - conn.secrets_request.connect(self.__secrets_request_cb) - self.NewConnection(conn.path) - - def __secrets_request_cb(self, sender, **kwargs): - self.secrets_request.send(self, connection=sender, - response=kwargs['response']) - -class SecretsResponse(object): - ''' 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 - self._error_cb = error_cb - - def set_secrets(self, secrets): - self._connection.set_secrets(secrets) - self._reply_cb(secrets.get_dict()) - - def set_error(self, error): - self._error_cb(error) - -class NMSettingsConnection(dbus.service.Object): - def __init__(self, path, settings, secrets): - bus = dbus.SystemBus() - bus_name = dbus.service.BusName(SETTINGS_SERVICE, bus=bus) - dbus.service.Object.__init__(self, bus_name, path) - - self.path = path - self.secrets_request = dispatch.Signal() - - self._settings = settings - self._secrets = secrets - - def set_secrets(self, secrets): - self._secrets = secrets - self.save() - - def save(self): - profile_path = env.get_profile_path() - config_path = os.path.join(profile_path, 'nm', 'connections.cfg') - - config = ConfigParser.ConfigParser() - try: - try: - if not config.read(config_path): - logging.error('Error reading the nm config file') - return - except ConfigParser.ParsingError, e: - logging.error('Error reading the nm config file: %s' % e) - return - identifier = self._settings.connection.id - - if identifier not in config.sections(): - config.add_section(identifier) - config.set(identifier, 'type', self._settings.connection.type) - config.set(identifier, 'ssid', self._settings.wireless.ssid) - config.set(identifier, 'uuid', self._settings.connection.uuid) - - if self._settings.wireless_security is not None: - if self._settings.wireless_security.key_mgmt is not None: - config.set(identifier, 'key-mgmt', - self._settings.wireless_security.key_mgmt) - if self._settings.wireless_security.proto is not None: - config.set(identifier, 'proto', - self._settings.wireless_security.proto) - if self._settings.wireless_security.pairwise is not None: - config.set(identifier, 'pairwise', - self._settings.wireless_security.pairwise) - if self._settings.wireless_security.group is not None: - config.set(identifier, 'group', - self._settings.wireless_security.group) - if self._secrets is not None: - if self._settings.wireless_security.key_mgmt == 'none': - config.set(identifier, 'key', self._secrets.wep_key) - config.set(identifier, 'auth-alg', self._secrets.auth_alg) - elif self._settings.wireless_security.key_mgmt == 'wpa-psk': - config.set(identifier, 'key', self._secrets.psk) - except ConfigParser.Error, e: - logging.error('Error constructing %s: %s' % (identifier, e)) - else: - f = open(config_path, 'w') - try: - config.write(f) - except ConfigParser.Error, e: - logging.error('Can not write %s error: %s' % (config_path, e)) - f.close() - - @dbus.service.method(dbus_interface=NM_CONNECTION_IFACE, - in_signature='', out_signature='a{sa{sv}}') - def GetSettings(self): - return self._settings.get_dict() - - @dbus.service.method(dbus_interface=NM_SECRETS_IFACE, - async_callbacks=('reply', 'error'), - in_signature='sasb', out_signature='a{sa{sv}}') - def GetSecrets(self, setting_name, hints, request_new, reply, error): - logging.debug('Secrets requested for connection %s request_new=%s' - % (self.path, request_new)) - - if request_new or self._secrets is None: - # 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, e: - logging.error('Error requesting the secrets via dialog: %s' % e) - else: - reply(self._secrets.get_dict()) - -def get_settings(): - global _nm_settings - if _nm_settings is None: - try: - _nm_settings = NMSettings() - except dbus.DBusException, e: - logging.error('Cannot create the UserSettings service %s.', e) - load_connections() - return _nm_settings - -def find_connection(ssid): - connections = get_settings().connections - if ssid in connections: - return connections[ssid] - else: - return None - -def add_connection(ssid, settings, secrets=None): - global _conn_counter - - path = NM_SETTINGS_PATH + '/' + str(_conn_counter) - _conn_counter += 1 - - conn = NMSettingsConnection(path, settings, secrets) - _nm_settings.add_connection(ssid, conn) - return conn - -def load_connections(): - profile_path = env.get_profile_path() - config_path = os.path.join(profile_path, 'nm', 'connections.cfg') - - config = ConfigParser.ConfigParser() - - 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() - - try: - if not config.read(config_path): - logging.error('Error reading the nm config file') - return - except ConfigParser.ParsingError, e: - logging.error('Error reading the nm config file: %s' % e) - return - - for section in config.sections(): - try: - settings = Settings() - settings.connection.id = section - ssid = config.get(section, 'ssid') - settings.wireless.ssid = dbus.ByteArray(ssid) - uuid = config.get(section, 'uuid') - settings.connection.uuid = uuid - nmtype = config.get(section, 'type') - settings.connection.type = nmtype - - secrets = None - if config.has_option(section, 'key-mgmt'): - secrets = Secrets() - settings.wireless_security = WirelessSecurity() - mgmt = config.get(section, 'key-mgmt') - settings.wireless_security.key_mgmt = mgmt - key = config.get(section, 'key') - if mgmt == 'none': - secrets.wep_key = key - auth_alg = config.get(section, 'auth-alg') - secrets.auth_alg = auth_alg - elif mgmt == 'wpa-psk': - secrets.psk = key - if config.has_option(section, 'proto'): - value = config.get(section, 'proto') - settings.wireless_security.proto = value - if config.has_option(section, 'group'): - value = config.get(section, 'group') - settings.wireless_security.group = value - if config.has_option(section, 'pairwise'): - value = config.get(section, 'pairwise') - settings.wireless_security.pairwise = value - except ConfigParser.Error, e: - logging.error('Error reading section: %s' % e) - else: - add_connection(ssid, settings, secrets) diff --git a/src/jarabe/model/notifications.py b/src/jarabe/model/notifications.py deleted file mode 100644 index da5c590..0000000 --- a/src/jarabe/model/notifications.py +++ /dev/null @@ -1,95 +0,0 @@ -# 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 - -import sys -import logging - -import dbus - -from sugar import dispatch - -from jarabe import config - -_DBUS_SERVICE = "org.freedesktop.Notifications" -_DBUS_IFACE = "org.freedesktop.Notifications" -_DBUS_PATH = "/org/freedesktop/Notifications" - -class NotificationService(dbus.service.Object): - def __init__(self): - bus = dbus.SessionBus() - bus_name = dbus.service.BusName(_DBUS_SERVICE, bus=bus) - dbus.service.Object.__init__(self, bus_name, _DBUS_PATH) - - self._notification_counter = 0 - self.notification_received = dispatch.Signal() - self.notification_cancelled = dispatch.Signal() - - @dbus.service.method(_DBUS_IFACE, - in_signature='susssava{sv}i', out_signature='u') - def Notify(self, app_name, replaces_id, app_icon, summary, body, actions, - hints, expire_timeout): - - logging.debug('Received notification: %r' % ([app_name, replaces_id, - app_icon, summary, body, actions, hints, expire_timeout])) - - if replaces_id > 0: - notification_id = replaces_id - else: - if self._notification_counter == sys.maxint: - self._notification_counter = 1 - else: - self._notification_counter += 1 - notification_id = self._notification_counter - - self.notification_received.send(self, app_name=app_name, - replaces_id=replaces_id, app_icon=app_icon, summary=summary, - body=body, actions=actions, hints=hints, - expire_timeout=expire_timeout) - - return notification_id - - @dbus.service.method(_DBUS_IFACE, in_signature='u', out_signature='') - def CloseNotification(self, notification_id): - self.notification_cancelled.send(self, notification_id=notification_id) - - @dbus.service.method(_DBUS_IFACE, in_signature='', out_signature='as') - def GetCapabilities(self): - return [] - - @dbus.service.method(_DBUS_IFACE, in_signature='', out_signature='sss') - def GetServerInformation(self, name, vendor, version): - return 'Sugar Shell', 'Sugar', config.version - - - @dbus.service.signal(_DBUS_IFACE, signature="uu") - def NotificationClosed(self, notification_id, reason): - pass - - @dbus.service.signal(_DBUS_IFACE, signature="us") - def ActionInvoked(self, notification_id, action_key): - pass - -_instance = None - -def get_service(): - global _instance - if not _instance: - _instance = NotificationService() - return _instance - -def init(): - get_service() - diff --git a/src/jarabe/model/screen.py b/src/jarabe/model/screen.py deleted file mode 100644 index 9aadcc3..0000000 --- a/src/jarabe/model/screen.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (C) 2006-2008 Red Hat, Inc. -# -# 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 - -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' - -COLOR_MODE = 0 -B_AND_W_MODE = 1 - -_ohm_service = None - -def _get_ohm(): - if _ohm_service: - return _ohm_service - - bus = dbus.SystemBus() - proxy = bus.get_object(_HARDWARE_MANAGER_SERVICE, - _HARDWARE_MANAGER_OBJECT_PATH, - follow_name_owner_changes=True) - - return dbus.Interface(proxy, _HARDWARE_MANAGER_INTERFACE) - -def set_dcon_freeze(frozen): - try: - _get_ohm().SetKey("display.dcon_freeze", frozen) - except dbus.DBusException: - logging.error('Cannot unfreeze the DCON') - -def set_display_mode(mode): - try: - _get_ohm().SetKey("display.dcon_mode", mode) - except dbus.DBusException: - logging.error('Cannot change DCON mode') - -def set_display_brightness(level): - try: - _get_ohm().SetKey("backlight.hardware_brightness", level) - except dbus.DBusException: - logging.error('Cannot set display brightness') - -def get_display_brightness(): - try: - return _get_ohm().GetKey("backlight.hardware_brightness") - except dbus.DBusException: - logging.error('Cannot get display brightness') - return 0 diff --git a/src/jarabe/model/shell.py b/src/jarabe/model/shell.py deleted file mode 100644 index fe3ad36..0000000 --- a/src/jarabe/model/shell.py +++ /dev/null @@ -1,577 +0,0 @@ -# Copyright (C) 2006-2007 Owen Williams. -# Copyright (C) 2006-2008 Red Hat, Inc. -# -# 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 - -import logging -import time -import os - -import gconf -import wnck -import gobject -import gtk -import dbus - -from sugar import wm -from sugar import dispatch -from sugar.graphics.xocolor import XoColor -from sugar.presence import presenceservice - -from jarabe.model.bundleregistry import get_registry -from jarabe import config - -_SERVICE_NAME = "org.laptop.Activity" -_SERVICE_PATH = "/org/laptop/Activity" -_SERVICE_INTERFACE = "org.laptop.Activity" - -def get_sugar_window_type(wnck_window): - window = gtk.gdk.window_foreign_new(wnck_window.get_xid()) - prop_info = window.property_get('_SUGAR_WINDOW_TYPE', 'STRING') - if prop_info is None: - return None - else: - return prop_info[2] - -class Activity(gobject.GObject): - """Activity which appears in the "Home View" of the Sugar shell - - This class stores the Sugar Shell's metadata regarding a - given activity/application in the system. It interacts with - the sugar.activity.* modules extensively in order to - accomplish its tasks. - """ - - __gtype_name__ = 'SugarHomeActivity' - - __gproperties__ = { - 'launching' : (bool, None, None, False, - gobject.PARAM_READWRITE), - } - - def __init__(self, activity_info, activity_id, window=None): - """Initialise the HomeActivity - - activity_info -- sugar.activity.registry.ActivityInfo instance, - provides the information required to actually - create the new instance. This is, in effect, - the "type" of activity being created. - activity_id -- unique identifier for this instance - of the activity type - window -- Main WnckWindow of the activity - """ - gobject.GObject.__init__(self) - - self._window = None - self._service = None - self._activity_id = activity_id - self._activity_info = activity_info - self._launch_time = time.time() - self._launching = False - - if window is not None: - self.set_window(window) - - self._retrieve_service() - - self._name_owner_changed_handler = None - if not self._service: - 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") - - 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. - """ - if not window: - raise ValueError("window must be valid") - self._window = window - - def get_service(self): - """Get the activity service - - Note that non-native Sugar applications will not have - such a service, so the return value will be None in - those cases. - """ - - return self._service - - def get_title(self): - """Retrieve the application's root window's suggested title""" - if self._window: - return self._window.get_name() - else: - return '' - - def get_icon_path(self): - """Retrieve the activity's icon (file) name""" - if self.is_journal(): - return os.path.join(config.data_path, 'icons/activity-journal.svg') - elif self._activity_info: - return self._activity_info.get_icon() - else: - return None - - def get_icon_color(self): - """Retrieve the appropriate icon colour for this activity - - Uses activity_id to index into the PresenceService's - set of activity colours, if the PresenceService does not - have an entry (implying that this is not a Sugar-shared application) - uses the local user's profile colour for the icon. - """ - pservice = presenceservice.get_instance() - - # HACK to suppress warning in logs when activity isn't found - # (if it's locally launched and not shared yet) - activity = None - for act in pservice.get_activities(): - if self._activity_id == act.props.id: - activity = act - break - - if activity != None: - return XoColor(activity.props.color) - else: - client = gconf.client_get_default() - return XoColor(client.get_string("/desktop/sugar/user/color")) - - def get_activity_id(self): - """Retrieve the "activity_id" passed in to our constructor - - This is a "globally likely unique" identifier generated by - sugar.util.unique_id - """ - return self._activity_id - - def get_xid(self): - """Retrieve the X-windows ID of our root window""" - return self._window.get_xid() - - def get_window(self): - """Retrieve the X-windows root window of this application - - This was stored by the set_window method, which was - called by HomeModel._add_activity, which was called - via a callback that looks for all 'window-opened' - events. - - HomeModel currently uses a dbus service query on the - activity to determine to which HomeActivity the newly - launched window belongs. - """ - return self._window - - def get_type(self): - """Retrieve the activity bundle id for future reference""" - if self._window is None: - return None - else: - return wm.get_bundle_id(self._window) - - def is_journal(self): - """Returns boolean if the activity is of type JournalActivity""" - return self.get_type() == 'org.laptop.JournalActivity' - - def get_launch_time(self): - """Return the time at which the activity was first launched - - Format is floating-point time.time() value - (seconds since the epoch) - """ - return self._launch_time - - def get_pid(self): - """Returns the activity's PID""" - return self._window.get_pid() - - def get_bundle_path(self): - """Returns the activity's bundle directory""" - if self._activity_info is None: - return None - else: - return self._activity_info.get_path() - - 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() - return False - - def do_set_property(self, pspec, value): - if pspec.name == 'launching': - self._launching = value - - def do_get_property(self, pspec): - if pspec.name == 'launching': - return self._launching - - def _get_service_name(self): - if self._activity_id: - return _SERVICE_NAME + self._activity_id - else: - return None - - def _retrieve_service(self): - if not self._activity_id: - return - - try: - bus = dbus.SessionBus() - proxy = bus.get_object(self._get_service_name(), - _SERVICE_PATH + "/" + self._activity_id) - self._service = dbus.Interface(proxy, _SERVICE_INTERFACE) - except dbus.DBusException: - self._service = None - - def _name_owner_changed_cb(self, name, old, new): - if name == self._get_service_name(): - self._retrieve_service() - self.set_active(True) - self._name_owner_changed_handler.remove() - self._name_owner_changed_handler = None - - def set_active(self, state): - """Propagate the current state to the activity object""" - if self._service is not None: - self._service.SetActive(state, - reply_handler=self._set_active_success, - error_handler=self._set_active_error) - - def _set_active_success(self): - pass - - def _set_active_error(self, err): - logging.error("set_active() failed: %s" % err) - -class ShellModel(gobject.GObject): - """Model of the shell (activity management) - - The ShellModel is basically the point of registration - for all running activities within Sugar. It traps - events that tell the system there is a new activity - being created (generated by the activity factories), - or removed, as well as those which tell us that the - currently focussed activity has changed. - - The HomeModel tracks a set of HomeActivity instances, - which are tracking the window to activity mappings - the activity factories have set up. - """ - - __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])), - 'active-activity-changed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([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])) - } - - ZOOM_MESH = 0 - ZOOM_GROUP = 1 - ZOOM_HOME = 2 - ZOOM_ACTIVITY = 3 - - def __init__(self): - gobject.GObject.__init__(self) - - self._screen = wnck.screen_get_default() - self._screen.connect('window-opened', self._window_opened_cb) - self._screen.connect('window-closed', self._window_closed_cb) - self._screen.connect('active-window-changed', - self._active_window_changed_cb) - - self.zoom_level_changed = dispatch.Signal() - - self._desktop_level = self.ZOOM_HOME - self._zoom_level = self.ZOOM_HOME - self._current_activity = None - self._activities = [] - self._active_activity = None - self._tabbing_activity = None - self._pservice = presenceservice.get_instance() - - self._screen.toggle_showing_desktop(True) - - def _update_zoom_level(self, window): - if window.get_window_type() == wnck.WINDOW_NORMAL: - new_level = self.ZOOM_ACTIVITY - else: - new_level = self._desktop_level - - if self._zoom_level != new_level: - old_level = self._zoom_level - self._zoom_level = new_level - self.zoom_level_changed.send(self, old_level=old_level, - new_level=new_level) - - def _set_zoom_level(self, new_level): - old_level = self.zoom_level - if old_level == new_level: - return - - self._zoom_level = new_level - if new_level is not self.ZOOM_ACTIVITY: - self._desktop_level = new_level - - self.zoom_level_changed.send(self, old_level=old_level, - new_level=new_level) - - show_desktop = new_level is not self.ZOOM_ACTIVITY - self._screen.toggle_showing_desktop(show_desktop) - - def _get_zoom_level(self): - return self._zoom_level - - zoom_level = property(_get_zoom_level, _set_zoom_level) - - def _get_activities_with_window(self): - ret = [] - for i in self._activities: - if i.get_window() is not None: - ret.append(i) - return ret - - def get_previous_activity(self, current=None): - if not current: - current = self._active_activity - - activities = self._get_activities_with_window() - i = activities.index(current) - if len(activities) == 0: - return None - elif i - 1 >= 0: - return activities[i - 1] - else: - return activities[len(activities) - 1] - - def get_next_activity(self, current=None): - if not current: - current = self._active_activity - - activities = self._get_activities_with_window() - i = activities.index(current) - if len(activities) == 0: - return None - elif i + 1 < len(activities): - return activities[i + 1] - else: - return activities[0] - - def get_active_activity(self): - """Returns the activity that the user is currently working in""" - return self._active_activity - - def get_tabbing_activity(self): - """Returns the activity that is currently highlighted during tabbing""" - return self._tabbing_activity - - 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) - - def _set_active_activity(self, home_activity): - if self._active_activity == home_activity: - return - - if home_activity: - home_activity.set_active(True) - - if self._active_activity: - self._active_activity.set_active(False) - - self._active_activity = home_activity - self.emit('active-activity-changed', self._active_activity) - - def __iter__(self): - return iter(self._activities) - - def __len__(self): - return len(self._activities) - - def __getitem__(self, i): - return self._activities[i] - - def index(self, obj): - return self._activities.index(obj) - - def _window_opened_cb(self, screen, window): - if window.get_window_type() == wnck.WINDOW_NORMAL: - home_activity = None - - activity_id = wm.get_activity_id(window) - - service_name = wm.get_bundle_id(window) - if service_name: - registry = get_registry() - activity_info = registry.get_bundle(service_name) - else: - activity_info = None - - if activity_id: - home_activity = self.get_activity_by_id(activity_id) - - if not home_activity: - home_activity = Activity(activity_info, activity_id, window) - self._add_activity(home_activity) - else: - home_activity.set_window(window) - - if get_sugar_window_type(window) != 'launcher': - home_activity.props.launching = False - 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)) - - 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: - self._remove_activity_by_xid(window.get_xid()) - - def _get_activity_by_xid(self, xid): - for home_activity in self._activities: - if home_activity.get_xid() == xid: - return home_activity - return None - - def get_activity_by_id(self, activity_id): - for home_activity in self._activities: - if home_activity.get_activity_id() == activity_id: - return home_activity - return None - - def _active_window_changed_cb(self, screen, previous_window=None): - window = screen.get_active_window() - if window is None: - return - - if window.get_window_type() != wnck.WINDOW_DIALOG: - while window.get_transient() is not None: - window = window.get_transient() - - act = self._get_activity_by_xid(window.get_xid()) - if act is not None: - self._set_active_activity(act) - - self._update_zoom_level(window) - - def _add_activity(self, home_activity): - self._activities.append(home_activity) - self.emit('activity-added', home_activity) - - def _remove_activity(self, home_activity): - if home_activity == self._active_activity: - windows = wnck.screen_get_default().get_windows_stacked() - windows.reverse() - for window in windows: - new_activity = self._get_activity_by_xid(window.get_xid()) - if new_activity is not None: - self._set_active_activity(new_activity) - break - else: - logging.error('No activities are running') - self._set_active_activity(None) - - 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) - if not activity_info: - raise ValueError("Activity service name '%s'" \ - " was not found in the bundle registry." - % service_name) - home_activity = Activity(activity_info, activity_id) - home_activity.props.launching = True - self._add_activity(home_activity) - - self._set_active_activity(home_activity) - - self.emit('launch-started', home_activity) - - # FIXME: better learn about finishing processes by receiving a signal. - # Now just check whether an activity has a window after ~90sec - gobject.timeout_add(90000, self._check_activity_launched, activity_id) - - 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, home_activity.get_type())) - home_activity.props.launching = False - self._remove_activity(home_activity) - else: - logging.error('Model for activity id %s does not exist.' - % activity_id) - - self.emit('launch-failed', home_activity) - - def _check_activity_launched(self, activity_id): - home_activity = self.get_activity_by_id(activity_id) - - if not home_activity: - logging.debug('Activity %s has been closed already.' % activity_id) - return False - - if home_activity.props.launching: - logging.debug('Activity %s still launching, assuming it failed...' - % activity_id) - self.notify_launch_failed(activity_id) - 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 deleted file mode 100644 index 65090a4..0000000 --- a/src/jarabe/model/sound.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (C) 2006-2008 Red Hat, Inc. -# -# 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 - -import gconf - -from sugar import env -from sugar import _sugarext -from sugar import dispatch - -VOLUME_STEP = 10 - -muted_changed = dispatch.Signal() -volume_changed = dispatch.Signal() - -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) - - volume_changed.send(None) - save() - -def set_muted(new_state): - old_state = _volume.get_mute() - _volume.set_mute(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/volume.py b/src/jarabe/model/volume.py deleted file mode 100644 index 6afa6a6..0000000 --- a/src/jarabe/model/volume.py +++ /dev/null @@ -1,253 +0,0 @@ -# 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 -# 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 - -import logging - -import gobject -import dbus - -from sugar import profile - -HAL_SERVICE_NAME = 'org.freedesktop.Hal' -HAL_MANAGER_PATH = '/org/freedesktop/Hal/Manager' -HAL_MANAGER_IFACE = 'org.freedesktop.Hal.Manager' -HAL_DEVICE_IFACE = 'org.freedesktop.Hal.Device' -HAL_VOLUME_IFACE = 'org.freedesktop.Hal.Device.Volume' - -MOUNT_OPTION_UID = 500 -MOUNT_OPTION_UMASK = 000 - -_volumes_manager = None - -class VolumesManager(gobject.GObject): - - __gtype_name__ = 'VolumesManager' - - __gsignals__ = { - 'volume-added': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([object])), - 'volume-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, - ([object])) - } - - def __init__(self): - gobject.GObject.__init__(self) - - self._volumes = {} - - bus = dbus.SystemBus() - proxy = bus.get_object(HAL_SERVICE_NAME, HAL_MANAGER_PATH) - self._hal_manager = dbus.Interface(proxy, HAL_MANAGER_IFACE) - self._hal_manager.connect_to_signal('DeviceAdded', - self._hal_device_added_cb) - - for udi in self._hal_manager.FindDeviceByCapability('volume'): - if self._is_device_relevant(udi): - try: - self._add_hal_device(udi) - except Exception, e: - logging.error('Exception when mounting device %r: %r' % \ - (udi, e)) - - def get_volumes(self): - return self._volumes.values() - - def _hal_device_added_cb(self, udi): - bus = dbus.SystemBus() - device_object = bus.get_object(HAL_SERVICE_NAME, udi) - device = dbus.Interface(device_object, HAL_DEVICE_IFACE) - if device.QueryCapability('volume'): - logging.debug('VolumesManager._hal_device_added_cb: %r', udi) - if self._is_device_relevant(udi): - self._add_hal_device(udi) - - def _is_device_relevant(self, udi): - bus = dbus.SystemBus() - device_object = bus.get_object(HAL_SERVICE_NAME, udi) - device = dbus.Interface(device_object, HAL_DEVICE_IFACE) - - # Ignore volumes without a filesystem. - if device.GetProperty('volume.fsusage') != 'filesystem': - return False - # Ignore root. - if device.GetProperty('volume.mount_point') == '/': - return False - - storage_udi = device.GetProperty('block.storage_device') - obj = bus.get_object(HAL_SERVICE_NAME, storage_udi) - storage_device = dbus.Interface(obj, HAL_DEVICE_IFACE) - - # Ignore non-removable storage. - if not storage_device.GetProperty('storage.hotpluggable'): - return False - - return True - - def _add_hal_device(self, udi): - logging.debug('VolumeToolbar._add_hal_device: %r' % udi) - - bus = dbus.SystemBus() - device_object = bus.get_object(HAL_SERVICE_NAME, udi) - device = dbus.Interface(device_object, HAL_DEVICE_IFACE) - - # listen to mount/unmount - device.connect_to_signal('PropertyModified', - lambda *args: self._hal_device_property_modified_cb(udi, *args)) - - bus.add_signal_receiver(self._hal_device_removed_cb, - 'DeviceRemoved', - HAL_MANAGER_IFACE, HAL_SERVICE_NAME, - HAL_MANAGER_PATH, arg0=udi) - - if device.GetProperty('volume.is_mounted'): - self._add_volume(udi) - return - - label = device.GetProperty('volume.label') - fs_type = device.GetProperty('volume.fstype') - valid_options = device.GetProperty('volume.mount.valid_options') - options = [] - - if 'uid=' in valid_options: - options.append('uid=%i' % MOUNT_OPTION_UID) - - if 'umask=' in valid_options: - options.append('umask=%i' % MOUNT_OPTION_UMASK) - - if 'noatime' in valid_options: - options.append('noatime') - - if 'utf8' in valid_options: - options.append('utf8') - - if 'iocharset=' in valid_options: - options.append('iocharset=utf8') - - mount_point = label - if not mount_point: - mount_point = device.GetProperty('volume.uuid') - - volume = dbus.Interface(device_object, HAL_VOLUME_IFACE) - - # Try 100 times to get a mount point - mounted = False - i = 0 - while not mounted: - try: - if i > 0: - volume.Mount('%s_%d' % (mount_point, i), fs_type, options) - else: - volume.Mount(mount_point, fs_type, options) - mounted = True - except dbus.DBusException, e: - s = 'org.freedesktop.Hal.Device.Volume.MountPointNotAvailable' - if i < 100 and e.get_dbus_name() == s: - i += 1 - else: - raise - - def _hal_device_property_modified_cb(self, udi, count, changes): - if 'volume.is_mounted' in [change[0] for change in changes]: - logging.debug('VolumesManager._hal_device_property_modified: %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): - # 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) - return - - if is_mounted: - if udi not in self._volumes: - self._add_volume(udi) - else: - 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) - - volume_name = device.GetProperty('volume.label') - if not volume_name: - volume_name = device.GetProperty('volume.uuid') - - mount_point = device.GetProperty('volume.mount_point') - - volume = Volume(volume_name, - self._get_icon_for_volume(device), - profile.get_color(), - udi, - mount_point) - self._volumes[udi] = volume - - 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) - if udi in self._volumes: - self._remove_volume(udi) - - def _get_icon_for_volume(self, device): - bus = dbus.SystemBus() - storage_udi = device.GetProperty('block.storage_device') - obj = bus.get_object(HAL_SERVICE_NAME, storage_udi) - storage_device = dbus.Interface(obj, HAL_DEVICE_IFACE) - - storage_drive_type = storage_device.GetProperty('storage.drive_type') - if storage_drive_type == 'sd_mmc': - return 'media-flash-sd-mmc' - else: - return 'media-flash-usb' - -class Volume(object): - def __init__(self, name, icon_name, icon_color, udi, mount_point): - self.name = name - self.icon_name = icon_name - self.icon_color = icon_color - self.udi = udi - self.mount_point = mount_point - - def unmount(self): - 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 - if _volumes_manager is None: - _volumes_manager = VolumesManager() - return _volumes_manager - diff --git a/src/jarabe/util/Makefile.am b/src/jarabe/util/Makefile.am deleted file mode 100644 index 4046fe8..0000000 --- a/src/jarabe/util/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -SUBDIRS = \ - telepathy - -sugardir = $(pythondir)/jarabe/util -sugar_PYTHON = \ - __init__.py diff --git a/src/jarabe/util/telepathy/Makefile.am b/src/jarabe/util/telepathy/Makefile.am deleted file mode 100644 index d40349d..0000000 --- a/src/jarabe/util/telepathy/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -sugardir = $(pythondir)/jarabe/util/telepathy -sugar_PYTHON = \ - __init__.py \ - connection_watcher.py diff --git a/src/jarabe/util/telepathy/connection_watcher.py b/src/jarabe/util/telepathy/connection_watcher.py deleted file mode 100644 index 4a4c6e0..0000000 --- a/src/jarabe/util/telepathy/connection_watcher.py +++ /dev/null @@ -1,110 +0,0 @@ -# This should eventually land in telepathy-python, so has the same license: -# Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# FIXME: this sould go upstream, in telepathy-python - -import logging - -import dbus -import dbus.mainloop.glib -import gobject - -from telepathy.client import Connection -from telepathy.interfaces import CONN_INTERFACE -from telepathy.constants import CONNECTION_STATUS_CONNECTED, \ - CONNECTION_STATUS_DISCONNECTED - -class ConnectionWatcher(gobject.GObject): - __gsignals__ = { - 'connection-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])), - 'connection-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, - ([gobject.TYPE_PYOBJECT])) - } - - def __init__(self, bus=None): - gobject.GObject.__init__(self) - - if bus is None: - self.bus = dbus.Bus() - else: - self.bus = bus - - # D-Bus path -> Connection - self._connections = {} - - self.bus.add_signal_receiver(self._status_changed_cb, - dbus_interface=CONN_INTERFACE, signal_name='StatusChanged', - path_keyword='path') - - for conn in Connection.get_connections(bus): - conn.call_when_ready(self._conn_ready_cb) - - def _status_changed_cb(self, *args, **kwargs): - path = kwargs['path'] - if not path.startswith('/org/freedesktop/Telepathy/Connection/'): - return - - status, reason_ = args - service_name = path.replace('/', '.')[1:] - - if status == CONNECTION_STATUS_CONNECTED: - self._add_connection(service_name, path) - elif status == CONNECTION_STATUS_DISCONNECTED: - self._remove_connection(service_name, path) - - def _conn_ready_cb(self, conn): - if conn.object_path in self._connections: - return - - self._connections[conn.object_path] = conn - self.emit('connection-added', conn) - - def _add_connection(self, service_name, path): - if path in self._connections: - return - - try: - Connection(service_name, path, ready_handler=self._conn_ready_cb) - except dbus.exceptions.DBusException: - logging.debug('%s is propably already gone.', service_name) - - def _remove_connection(self, service_name, path): - conn = self._connections.pop(path, None) - if conn is None: - return - - self.emit('connection-removed', conn) - - def get_connections(self): - return self._connections.values() - -if __name__ == '__main__': - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - - def connection_added_cb(conn_watcher, conn): - print "new connection", conn.service_name - - def connection_removed_cb(conn_watcher, conn): - print "removed connection", conn.service_name - - watcher = ConnectionWatcher() - watcher.connect('connection-added', connection_added_cb) - watcher.connect('connection-removed', connection_removed_cb) - - loop = gobject.MainLoop() - loop.run() diff --git a/src/jarabe/view/Makefile.am b/src/jarabe/view/Makefile.am deleted file mode 100644 index 21e7a91..0000000 --- a/src/jarabe/view/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -sugardir = $(pythondir)/jarabe/view -sugar_PYTHON = \ - __init__.py \ - buddyicon.py \ - buddymenu.py \ - keyhandler.py \ - launcher.py \ - palettes.py \ - pulsingicon.py \ - service.py \ - tabbinghandler.py diff --git a/src/jarabe/view/Makefile.in b/src/jarabe/view/Makefile.in deleted file mode 100644 index dc8c69c..0000000 --- a/src/jarabe/view/Makefile.in +++ /dev/null @@ -1,400 +0,0 @@ -# Makefile.in generated by automake 1.10.1 from Makefile.am. -# @configure_input@ - -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. -# This Makefile.in is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY, to the extent permitted by law; without -# even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. - -@SET_MAKE@ -VPATH = @srcdir@ -pkgdatadir = $(datadir)/@PACKAGE@ -pkglibdir = $(libdir)/@PACKAGE@ -pkgincludedir = $(includedir)/@PACKAGE@ -am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd -install_sh_DATA = $(install_sh) -c -m 644 -install_sh_PROGRAM = $(install_sh) -c -install_sh_SCRIPT = $(install_sh) -c -INSTALL_HEADER = $(INSTALL_DATA) -transform = $(program_transform_name) -NORMAL_INSTALL = : -PRE_INSTALL = : -POST_INSTALL = : -NORMAL_UNINSTALL = : -PRE_UNINSTALL = : -POST_UNINSTALL = : -subdir = src/jarabe/view -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(sugar_PYTHON) -ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac -am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ - $(ACLOCAL_M4) -mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = -SOURCES = -DIST_SOURCES = -am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; -am__vpath_adj = case $$p in \ - $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ - *) f=$$p;; \ - esac; -am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; -am__installdirs = "$(DESTDIR)$(sugardir)" -sugarPYTHON_INSTALL = $(INSTALL_DATA) -py_compile = $(top_srcdir)/py-compile -DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) -ACLOCAL = @ACLOCAL@ -ALL_LINGUAS = @ALL_LINGUAS@ -AMTAR = @AMTAR@ -AUTOCONF = @AUTOCONF@ -AUTOHEADER = @AUTOHEADER@ -AUTOMAKE = @AUTOMAKE@ -AWK = @AWK@ -CATALOGS = @CATALOGS@ -CATOBJEXT = @CATOBJEXT@ -CC = @CC@ -CCDEPMODE = @CCDEPMODE@ -CFLAGS = @CFLAGS@ -CPP = @CPP@ -CPPFLAGS = @CPPFLAGS@ -CYGPATH_W = @CYGPATH_W@ -DATADIRNAME = @DATADIRNAME@ -DEFS = @DEFS@ -DEPDIR = @DEPDIR@ -ECHO_C = @ECHO_C@ -ECHO_N = @ECHO_N@ -ECHO_T = @ECHO_T@ -EGREP = @EGREP@ -EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ -GMOFILES = @GMOFILES@ -GMSGFMT = @GMSGFMT@ -GREP = @GREP@ -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_SCRIPT = @INSTALL_SCRIPT@ -INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ -INSTOBJEXT = @INSTOBJEXT@ -INTLLIBS = @INTLLIBS@ -INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@ -INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@ -INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@ -INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ -INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@ -INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@ -INTLTOOL_MERGE = @INTLTOOL_MERGE@ -INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@ -INTLTOOL_PERL = @INTLTOOL_PERL@ -INTLTOOL_POLICY_RULE = @INTLTOOL_POLICY_RULE@ -INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@ -INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@ -INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@ -INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@ -INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@ -INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@ -INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@ -INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@ -INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@ -INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ -INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@ -INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@ -INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@ -LDFLAGS = @LDFLAGS@ -LIBOBJS = @LIBOBJS@ -LIBS = @LIBS@ -LTLIBOBJS = @LTLIBOBJS@ -MAKEINFO = @MAKEINFO@ -MKDIR_P = @MKDIR_P@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -MSGFMT = @MSGFMT@ -MSGFMT_OPTS = @MSGFMT_OPTS@ -MSGMERGE = @MSGMERGE@ -OBJEXT = @OBJEXT@ -PACKAGE = @PACKAGE@ -PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ -PACKAGE_NAME = @PACKAGE_NAME@ -PACKAGE_STRING = @PACKAGE_STRING@ -PACKAGE_TARNAME = @PACKAGE_TARNAME@ -PACKAGE_VERSION = @PACKAGE_VERSION@ -PATH_SEPARATOR = @PATH_SEPARATOR@ -PKG_CONFIG = @PKG_CONFIG@ -POFILES = @POFILES@ -POSUB = @POSUB@ -PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@ -PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@ -PYTHON = @PYTHON@ -PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ -PYTHON_PLATFORM = @PYTHON_PLATFORM@ -PYTHON_PREFIX = @PYTHON_PREFIX@ -PYTHON_VERSION = @PYTHON_VERSION@ -SET_MAKE = @SET_MAKE@ -SHELL = @SHELL@ -SHELL_CFLAGS = @SHELL_CFLAGS@ -SHELL_LIBS = @SHELL_LIBS@ -STRIP = @STRIP@ -SUCROSE_VERSION = @SUCROSE_VERSION@ -USE_NLS = @USE_NLS@ -VERSION = @VERSION@ -XGETTEXT = @XGETTEXT@ -abs_builddir = @abs_builddir@ -abs_srcdir = @abs_srcdir@ -abs_top_builddir = @abs_top_builddir@ -abs_top_srcdir = @abs_top_srcdir@ -ac_ct_CC = @ac_ct_CC@ -am__include = @am__include@ -am__leading_dot = @am__leading_dot@ -am__quote = @am__quote@ -am__tar = @am__tar@ -am__untar = @am__untar@ -bindir = @bindir@ -build_alias = @build_alias@ -builddir = @builddir@ -datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ -exec_prefix = @exec_prefix@ -host_alias = @host_alias@ -htmldir = @htmldir@ -includedir = @includedir@ -infodir = @infodir@ -install_sh = @install_sh@ -libdir = @libdir@ -libexecdir = @libexecdir@ -localedir = @localedir@ -localstatedir = @localstatedir@ -mandir = @mandir@ -mkdir_p = @mkdir_p@ -oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ -pkgpyexecdir = @pkgpyexecdir@ -pkgpythondir = @pkgpythondir@ -prefix = @prefix@ -program_transform_name = @program_transform_name@ -psdir = @psdir@ -pyexecdir = @pyexecdir@ -pythondir = @pythondir@ -sbindir = @sbindir@ -sharedstatedir = @sharedstatedir@ -srcdir = @srcdir@ -sysconfdir = @sysconfdir@ -target_alias = @target_alias@ -top_builddir = @top_builddir@ -top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/view -sugar_PYTHON = \ - __init__.py \ - buddyicon.py \ - buddymenu.py \ - keyhandler.py \ - launcher.py \ - palettes.py \ - pulsingicon.py \ - service.py \ - tabbinghandler.py - -all: all-am - -.SUFFIXES: -$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) - @for dep in $?; do \ - case '$(am__configure_deps)' in \ - *$$dep*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ - && exit 0; \ - exit 1;; \ - esac; \ - done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/view/Makefile'; \ - cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/view/Makefile -.PRECIOUS: Makefile -Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status - @case '$?' in \ - *config.status*) \ - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ - *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ - esac; - -$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh - -$(top_srcdir)/configure: $(am__configure_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -$(ACLOCAL_M4): $(am__aclocal_m4_deps) - cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -install-sugarPYTHON: $(sugar_PYTHON) - @$(NORMAL_INSTALL) - test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ - if test -f $$b$$p; then \ - f=$(am__strip_dir) \ - dlist="$$dlist $$f"; \ - echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ - $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ - else :; fi; \ - done; \ - if test -n "$$dlist"; then \ - if test -z "$(DESTDIR)"; then \ - PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ - else \ - PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ - fi; \ - else :; fi - -uninstall-sugarPYTHON: - @$(NORMAL_UNINSTALL) - @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ - f=$(am__strip_dir) \ - rm -f "$(DESTDIR)$(sugardir)/$$f"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ - rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ - done -tags: TAGS -TAGS: - -ctags: CTAGS -CTAGS: - - -distdir: $(DISTFILES) - @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ - list='$(DISTFILES)'; \ - dist_files=`for file in $$list; do echo $$file; done | \ - sed -e "s|^$$srcdirstrip/||;t" \ - -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ - case $$dist_files in \ - */*) $(MKDIR_P) `echo "$$dist_files" | \ - sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ - sort -u` ;; \ - esac; \ - for file in $$dist_files; do \ - if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ - if test -d $$d/$$file; then \ - dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ - if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ - cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ - fi; \ - cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ - else \ - test -f $(distdir)/$$file \ - || cp -p $$d/$$file $(distdir)/$$file \ - || exit 1; \ - fi; \ - done -check-am: all-am -check: check-am -all-am: Makefile -installdirs: - for dir in "$(DESTDIR)$(sugardir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ - done -install: install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am - -install-am: all-am - @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am - -installcheck: installcheck-am -install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install -mostlyclean-generic: - -clean-generic: - -distclean-generic: - -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) - -maintainer-clean-generic: - @echo "This command is intended for maintainers to use" - @echo "it deletes files that may require special tools to rebuild." -clean: clean-am - -clean-am: clean-generic mostlyclean-am - -distclean: distclean-am - -rm -f Makefile -distclean-am: clean-am distclean-generic - -dvi: dvi-am - -dvi-am: - -html: html-am - -info: info-am - -info-am: - -install-data-am: install-sugarPYTHON - -install-dvi: install-dvi-am - -install-exec-am: - -install-html: install-html-am - -install-info: install-info-am - -install-man: - -install-pdf: install-pdf-am - -install-ps: install-ps-am - -installcheck-am: - -maintainer-clean: maintainer-clean-am - -rm -f Makefile -maintainer-clean-am: distclean-am maintainer-clean-generic - -mostlyclean: mostlyclean-am - -mostlyclean-am: mostlyclean-generic - -pdf: pdf-am - -pdf-am: - -ps: ps-am - -ps-am: - -uninstall-am: uninstall-sugarPYTHON - -.MAKE: install-am install-strip - -.PHONY: all all-am check check-am clean clean-generic distclean \ - distclean-generic distdir dvi dvi-am html html-am info info-am \ - install install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip install-sugarPYTHON installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \ - uninstall-am uninstall-sugarPYTHON - -# Tell versions [3.59,3.63) of GNU make to not export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/src/jarabe/view/pulsingicon.py b/src/jarabe/view/pulsingicon.py deleted file mode 100644 index e04b117..0000000 --- a/src/jarabe/view/pulsingicon.py +++ /dev/null @@ -1,229 +0,0 @@ -# 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 - -import math - -import gobject - -from sugar.graphics.icon import Icon, CanvasIcon -from sugar.graphics.style import Color - -_INTERVAL = 100 -_STEP = math.pi / 10 # must be a fraction of pi, for clean caching - -class Pulser(object): - def __init__(self, icon): - self._pulse_hid = None - self._icon = icon - self._level = 0 - self._phase = 0 - - def start(self, restart=False): - if restart: - self._phase = 0 - if self._pulse_hid is None: - self._pulse_hid = gobject.timeout_add(_INTERVAL, self.__pulse_cb) - - def stop(self): - if self._pulse_hid is not None: - gobject.source_remove(self._pulse_hid) - self._pulse_hid = None - self._icon.xo_color = self._icon.base_color - - def update(self): - if self._icon.pulsing: - base_color = self._icon.base_color - pulse_color = self._icon.pulse_color - - base_stroke = self._get_as_rgba(base_color.get_stroke_color()) - pulse_stroke = self._get_as_rgba(pulse_color.get_stroke_color()) - base_fill = self._get_as_rgba(base_color.get_fill_color()) - pulse_fill = self._get_as_rgba(pulse_color.get_fill_color()) - - self._icon.stroke_color = \ - self._get_color(base_stroke, pulse_stroke).get_svg() - self._icon.fill_color = \ - self._get_color(base_fill, pulse_fill).get_svg() - else: - self._icon.xo_color = self._icon.base_color - - def _get_as_rgba(self, html_color): - if html_color == 'none': - return Color('#FFFFFF', alpha=1.0).get_rgba() - else: - return Color(html_color).get_rgba() - - def _get_color(self, orig_color, target_color): - next_point = (orig_color[0] + - self._level * (target_color[0] - orig_color[0]), - orig_color[1] + - self._level * (target_color[1] - orig_color[1]), - orig_color[2] + - self._level * (target_color[2] - orig_color[2])) - - return Color('#%02x%02x%02x' % (int(next_point[0] * 255), - int(next_point[1] * 255), - int(next_point[2] * 255))) - - def __pulse_cb(self): - self._phase += _STEP - self._level = (math.sin(self._phase) + 1) / 2 - self.update() - - return True - -class PulsingIcon(Icon): - __gtype_name__ = 'SugarPulsingIcon' - - def __init__(self, **kwargs): - self._pulser = Pulser(self) - self._base_color = None - self._pulse_color = None - self._paused = False - self._pulsing = False - - Icon.__init__(self, **kwargs) - - self._palette = None - self.connect('destroy', self.__destroy_cb) - - def set_pulse_color(self, pulse_color): - self._pulse_color = pulse_color - self._pulser.update() - - def get_pulse_color(self): - return self._pulse_color - - pulse_color = gobject.property( - type=object, getter=get_pulse_color, setter=set_pulse_color) - - def set_base_color(self, base_color): - self._base_color = base_color - self._pulser.update() - - def get_base_color(self): - return self._base_color - - base_color = gobject.property( - type=object, getter=get_base_color, setter=set_base_color) - - def set_paused(self, paused): - self._paused = paused - - if self._paused: - self._pulser.stop() - else: - self._pulser.start(restart=False) - - def get_paused(self): - return self._paused - - paused = gobject.property( - type=bool, default=False, getter=get_paused, setter=set_paused) - - def set_pulsing(self, pulsing): - self._pulsing = pulsing - - if self._pulsing: - self._pulser.start(restart=True) - else: - self._pulser.stop() - - def get_pulsing(self): - return self._pulsing - - pulsing = gobject.property( - type=bool, default=False, getter=get_pulsing, setter=set_pulsing) - - def _get_palette(self): - return self._palette - - def _set_palette(self, palette): - if self._palette is not None: - self._palette.props.invoker = None - self._palette = palette - - palette = property(_get_palette, _set_palette) - - def __destroy_cb(self, icon): - self._pulser.stop() - if self._palette is not None: - self._palette.destroy() - -class CanvasPulsingIcon(CanvasIcon): - __gtype_name__ = 'SugarCanvasPulsingIcon' - - def __init__(self, **kwargs): - self._pulser = Pulser(self) - self._base_color = None - self._pulse_color = None - self._paused = False - self._pulsing = False - - CanvasIcon.__init__(self, **kwargs) - - self.connect('destroy', self.__destroy_cb) - - def __destroy_cb(self, box): - self._pulser.stop() - - def set_pulse_color(self, pulse_color): - self._pulse_color = pulse_color - self._pulser.update() - - def get_pulse_color(self): - return self._pulse_color - - pulse_color = gobject.property( - type=object, getter=get_pulse_color, setter=set_pulse_color) - - def set_base_color(self, base_color): - self._base_color = base_color - self._pulser.update() - - def get_base_color(self): - return self._base_color - - base_color = gobject.property( - type=object, getter=get_base_color, setter=set_base_color) - - def set_paused(self, paused): - self._paused = paused - - if self._paused: - self._pulser.stop() - else: - self._pulser.start(restart=False) - - def get_paused(self): - return self._paused - - paused = gobject.property( - type=bool, default=False, getter=get_paused, setter=set_paused) - - def set_pulsing(self, pulsing): - self._pulsing = pulsing - - if self._pulsing: - self._pulser.start(restart=True) - else: - self._pulser.stop() - - def get_pulsing(self): - return self._pulsing - - pulsing = gobject.property( - type=bool, default=False, getter=get_pulsing, setter=set_pulsing) diff --git a/src/logsmanager.py b/src/logsmanager.py new file mode 100644 index 0000000..f0fa981 --- /dev/null +++ b/src/logsmanager.py @@ -0,0 +1,56 @@ +# Copyright (C) 2007 Red Hat, Inc. +# +# 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 + +import os +import time + +from sugar import env + +_MAX_BACKUP_DIRS = 3 +"""The maximum number of "old" log directories we should keep around.""" + +def setup(): + """Clean up the log directory, moving old logs into a numbered backup + directory. We only keep `_MAX_BACKUP_DIRS` of these backup directories + around; the rest are removed.""" + logs_dir = env.get_logs_path() + if not os.path.isdir(logs_dir): + os.makedirs(logs_dir) + + backup_logs = [] + backup_dirs = [] + for f in os.listdir(logs_dir): + path = os.path.join(logs_dir, f) + if os.path.isfile(path): + backup_logs.append(f) + elif os.path.isdir(path): + backup_dirs.append(path) + + if len(backup_dirs) > _MAX_BACKUP_DIRS: + backup_dirs.sort() + root = backup_dirs[0] + for f in os.listdir(root): + os.remove(os.path.join(root, f)) + os.rmdir(root) + + if len(backup_logs) > 0: + name = str(int(time.time())) + backup_dir = os.path.join(logs_dir, name) + os.mkdir(backup_dir) + for log in backup_logs: + source_path = os.path.join(logs_dir, log) + dest_path = os.path.join(backup_dir, log) + os.rename(source_path, dest_path) diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..1bb91af --- /dev/null +++ b/src/main.py @@ -0,0 +1,153 @@ +# Copyright (C) 2006, Red Hat, Inc. +# +# 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 + +import os +import gettext + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +gtk.gdk.threads_init() + +from sugar import logger +from sugar.profile import get_profile + +import view.Shell +from shellservice import ShellService +from hardware import hardwaremanager +from intro import intro +from session import get_session_manager +import logsmanager +import config + +def _start_matchbox(): + cmd = ['matchbox-window-manager'] + + cmd.extend(['-use_titlebar', 'no']) + cmd.extend(['-theme', 'sugar']) + cmd.extend(['-kbdconfig', os.path.join(config.data_path, 'kbdconfig')]) + + gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH) + +def _setup_translations(): + locale_path = os.path.join(config.prefix, 'share', 'locale') + domain = 'sugar' + + gettext.bindtextdomain(domain, locale_path) + gettext.textdomain(domain) + +def check_cm(bus_name): + try: + import dbus + bus = dbus.SessionBus() + bus_object = bus.get_object('org.freedesktop.DBus', + '/org/freedesktop/DBus') + name_ = bus_object.GetNameOwner(bus_name, + dbus_interface='org.freedesktop.DBus') + except dbus.DBusException: + return False + return True + +def _shell_started_cb(): + # Unfreeze the display + hw_manager = hardwaremanager.get_manager() + hw_manager.set_dcon_freeze(0) + +def _software_update_cb(): + '''Ask the homeview to display an alert about available software updates + ''' + shell = view.Shell.get_instance() + home_box = shell.home_window.get_home_box() + home_box.show_software_updates_alert() + +def main(): + gobject.idle_add(_shell_started_cb) + + try: + logsmanager.setup() + except Exception, e: + # logs setup is not critical; it should not prevent sugar from + # starting if (for example) the disk is full or read-only. + print 'Log setup failed: %s' % e + + logger.start('shell') + + _start_matchbox() + _setup_translations() + + hw_manager = hardwaremanager.get_manager() + hw_manager.startup() + + icons_path = os.path.join(config.data_path, 'icons') + gtk.icon_theme_get_default().append_search_path(icons_path) + + # Do initial setup if needed + if not get_profile().is_valid(): + win = intro.IntroWindow() + win.show_all() + gtk.main() + + # set timezone + if get_profile().timezone is not None: + os.environ['TZ'] = get_profile().timezone + + if os.environ.has_key("SUGAR_TP_DEBUG"): + # Allow the user time to start up telepathy connection managers + # using the Sugar DBus bus address + import time + from telepathy.client import ManagerRegistry + + registry = ManagerRegistry() + registry.LoadManagers() + + debug_flags = os.environ["SUGAR_TP_DEBUG"].split(',') + for cm_name in debug_flags: + if cm_name not in ["gabble", "salut"]: + continue + + try: + cm = registry.services[cm_name] + except KeyError: + print RuntimeError("%s connection manager not found!" % cm_name) + + while not check_cm(cm['busname']): + print "Waiting for %s on: DBUS_SESSION_BUS_ADDRESS=%s" % \ + (cm_name, os.environ["DBUS_SESSION_BUS_ADDRESS"]) + try: + time.sleep(5) + except KeyboardInterrupt: + print "Got Ctrl+C, continuing..." + break + + # TODO: move initializations from the Shell constructor to a start() method + view.Shell.get_instance() + ShellService() + + session_manager = get_session_manager() + session_manager.start() + + # dlo trac #7495: open 'software update' control panel after an upgrade + # to update activities. + update_trigger_file = os.path.expanduser('~/.sugar-update') + if os.path.isfile(update_trigger_file): + gobject.idle_add(_software_update_cb) + + try: + gtk.main() + except KeyboardInterrupt: + print 'Ctrl+C pressed, exiting...' diff --git a/src/jarabe/model/buddy.py b/src/model/BuddyModel.py index b51b808..b51b808 100644 --- a/src/jarabe/model/buddy.py +++ b/src/model/BuddyModel.py diff --git a/src/jarabe/model/friends.py b/src/model/Friends.py index 27a11dd..6fc3e97 100644 --- a/src/jarabe/model/friends.py +++ b/src/model/Friends.py @@ -14,22 +14,22 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +import dbus import os -import logging from ConfigParser import ConfigParser import gobject -import dbus -from jarabe.model.buddy import BuddyModel +from model.BuddyModel import BuddyModel from sugar import env +import logging 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])) + gobject.TYPE_NONE, ([str])), } def __init__(self): @@ -112,11 +112,3 @@ class Friends(gobject.GObject): psi.SyncFriends(keys, reply_handler=friends_synced, error_handler=friends_synced_error) - -_model = None - -def get_model(): - global _model - if _model is None: - _model = Friends() - return _model diff --git a/src/jarabe/model/invites.py b/src/model/Invites.py index 5229e43..8bcffd2 100644 --- a/src/jarabe/model/invites.py +++ b/src/model/Invites.py @@ -66,7 +66,7 @@ class Invites(gobject.GObject): 'invite-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([object])), 'invite-removed': (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([object])) + gobject.TYPE_NONE, ([object])), } def __init__(self): diff --git a/src/model/Makefile.am b/src/model/Makefile.am new file mode 100644 index 0000000..0b7d14c --- /dev/null +++ b/src/model/Makefile.am @@ -0,0 +1,14 @@ +SUBDIRS = devices + +sugardir = $(pkgdatadir)/shell/model +sugar_PYTHON = \ + __init__.py \ + accesspointmodel.py \ + BuddyModel.py \ + Friends.py \ + Invites.py \ + Owner.py \ + MeshModel.py \ + shellmodel.py \ + homeactivity.py \ + homemodel.py diff --git a/extensions/cpsection/Makefile.in b/src/model/Makefile.in index 262e3b2..876e3ef 100644 --- a/extensions/cpsection/Makefile.in +++ b/src/model/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = extensions/cpsection +subdir = src/model DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -85,9 +85,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -204,9 +201,20 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = aboutme aboutxo datetime frame language network power -sugardir = $(pkgdatadir)/extensions/cpsection -sugar_PYTHON = __init__.py +SUBDIRS = devices +sugardir = $(pkgdatadir)/shell/model +sugar_PYTHON = \ + __init__.py \ + accesspointmodel.py \ + BuddyModel.py \ + Friends.py \ + Invites.py \ + Owner.py \ + MeshModel.py \ + shellmodel.py \ + homeactivity.py \ + homemodel.py + all: all-recursive .SUFFIXES: @@ -219,9 +227,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/model/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/Makefile + $(AUTOMAKE) --foreign src/model/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/model/MeshModel.py b/src/model/MeshModel.py new file mode 100644 index 0000000..fa33035 --- /dev/null +++ b/src/model/MeshModel.py @@ -0,0 +1,237 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gobject + +from sugar.graphics.xocolor import XoColor +from sugar.presence import presenceservice +from sugar import activity + +from model.BuddyModel import BuddyModel +from model.accesspointmodel import AccessPointModel +from hardware import hardwaremanager +from hardware import nmclient + +class ActivityModel: + def __init__(self, act, bundle): + self.activity = act + self.bundle = bundle + + def get_id(self): + return self.activity.props.id + + def get_icon_name(self): + return self.bundle.icon + + def get_color(self): + return XoColor(self.activity.props.color) + + def get_bundle_id(self): + return self.bundle.bundle_id + +class MeshModel(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])), + 'buddy-added': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + 'buddy-moved': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT, + gobject.TYPE_PYOBJECT])), + 'buddy-removed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + 'access-point-added': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + 'access-point-removed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + 'mesh-added': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), + 'mesh-removed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ([])) + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._activities = {} + self._buddies = {} + self._access_points = {} + self._mesh = None + + self._pservice = presenceservice.get_instance() + self._pservice.connect("activity-appeared", + self._activity_appeared_cb) + self._pservice.connect('activity-disappeared', + self._activity_disappeared_cb) + self._pservice.connect("buddy-appeared", + self._buddy_appeared_cb) + self._pservice.connect("buddy-disappeared", + self._buddy_disappeared_cb) + + # Add any buddies the PS knows about already + self._pservice.get_buddies_async(reply_handler=self._get_buddies_cb) + + self._pservice.get_activities_async( + reply_handler=self._get_activities_cb) + + network_manager = hardwaremanager.get_network_manager() + if network_manager: + for nm_device in network_manager.get_devices(): + self._add_network_device(nm_device) + network_manager.connect('device-added', + self._nm_device_added_cb) + network_manager.connect('device-removed', + self._nm_device_removed_cb) + + def _get_buddies_cb(self, buddy_list): + for buddy in buddy_list: + self._buddy_appeared_cb(self._pservice, buddy) + + def _get_activities_cb(self, activity_list): + for act in activity_list: + self._check_activity(act) + + def _nm_device_added_cb(self, manager, nm_device): + self._add_network_device(nm_device) + + def _nm_device_removed_cb(self, manager, nm_device): + self._remove_network_device(nm_device) + + def _nm_network_appeared_cb(self, nm_device, nm_network): + self._add_access_point(nm_device, nm_network) + + def _nm_network_disappeared_cb(self, nm_device, nm_network): + if self._access_points.has_key(nm_network.get_op()): + ap = self._access_points[nm_network.get_op()] + self._remove_access_point(ap) + + def _add_network_device(self, nm_device): + dtype = nm_device.get_type() + if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS: + for nm_network in nm_device.get_networks(): + self._add_access_point(nm_device, nm_network) + + nm_device.connect('network-appeared', + self._nm_network_appeared_cb) + nm_device.connect('network-disappeared', + self._nm_network_disappeared_cb) + elif dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: + self._mesh = nm_device + self.emit('mesh-added', self._mesh) + + def _remove_network_device(self, nm_device): + if nm_device == self._mesh: + self._mesh = None + self.emit('mesh-removed') + elif nm_device.get_type() == nmclient.DEVICE_TYPE_802_11_WIRELESS: + aplist = self._access_points.values() + for ap in aplist: + if ap.get_nm_device() == nm_device: + self._remove_access_point(ap) + + def _add_access_point(self, nm_device, nm_network): + model = AccessPointModel(nm_device, nm_network) + self._access_points[model.get_id()] = model + self.emit('access-point-added', model) + + def _remove_access_point(self, ap): + if not self._access_points.has_key(ap.get_id()): + return + self.emit('access-point-removed', ap) + del self._access_points[ap.get_id()] + + def get_mesh(self): + return self._mesh + + def get_access_points(self): + return self._access_points.values() + + def get_activities(self): + return self._activities.values() + + def get_buddies(self): + return self._buddies.values() + + def _buddy_activity_changed_cb(self, model, cur_activity): + if not self._buddies.has_key(model.get_key()): + return + if cur_activity and self._activities.has_key(cur_activity.props.id): + activity_model = self._activities[cur_activity.props.id] + self.emit('buddy-moved', model, activity_model) + else: + self.emit('buddy-moved', model, None) + + def _buddy_appeared_cb(self, pservice, buddy): + if self._buddies.has_key(buddy.props.key): + return + + model = BuddyModel(buddy=buddy) + model.connect('current-activity-changed', + self._buddy_activity_changed_cb) + self._buddies[buddy.props.key] = model + self.emit('buddy-added', model) + + cur_activity = buddy.props.current_activity + if cur_activity: + self._buddy_activity_changed_cb(model, cur_activity) + + def _buddy_disappeared_cb(self, pservice, buddy): + if not self._buddies.has_key(buddy.props.key): + return + self.emit('buddy-removed', self._buddies[buddy.props.key]) + del self._buddies[buddy.props.key] + + def _activity_appeared_cb(self, pservice, act): + self._check_activity(act) + + def _check_activity(self, presence_activity): + registry = activity.get_registry() + bundle = registry.get_activity(presence_activity.props.type) + if not bundle: + return + if self.has_activity(presence_activity.props.id): + return + self.add_activity(bundle, presence_activity) + + def has_activity(self, activity_id): + return self._activities.has_key(activity_id) + + def get_activity(self, activity_id): + if self.has_activity(activity_id): + return self._activities[activity_id] + else: + return None + + def add_activity(self, bundle, act): + model = ActivityModel(act, bundle) + self._activities[model.get_id()] = model + self.emit('activity-added', model) + + for buddy in self._pservice.get_buddies(): + cur_activity = buddy.props.current_activity + key = buddy.props.key + if cur_activity == activity and self._buddies.has_key(key): + buddy_model = self._buddies[key] + self.emit('buddy-moved', buddy_model, model) + + def _activity_disappeared_cb(self, pservice, act): + if self._activities.has_key(act.props.id): + activity_model = self._activities[act.props.id] + self.emit('activity-removed', activity_model) + del self._activities[act.props.id] diff --git a/src/jarabe/model/owner.py b/src/model/Owner.py index bdfd9a8..934a8fc 100644 --- a/src/jarabe/model/owner.py +++ b/src/model/Owner.py @@ -17,17 +17,17 @@ import gobject import os -import cjson -import gconf +import simplejson from telepathy.interfaces import CHANNEL_TYPE_TEXT from sugar import env +from sugar import profile from sugar.presence import presenceservice from sugar import util -from jarabe.model.invites import Invites +from model.Invites import Invites -class Owner(gobject.GObject): +class ShellOwner(gobject.GObject): """Class representing the owner of this machine/instance. This class runs in the shell and serves up the buddy icon and other stuff. It's the server portion of the Owner, paired with the client portion in Buddy.py. @@ -46,8 +46,7 @@ class Owner(gobject.GObject): def __init__(self): gobject.GObject.__init__(self) - client = gconf.client_get_default() - self._nick = client.get_string("/desktop/sugar/user/nick") + self._nick = profile.get_nick_name() self._icon = None self._icon_hash = "" @@ -98,16 +97,8 @@ class Owner(gobject.GObject): bundle_id = 'org.laptop.Chat' else: bundle_id = 'org.laptop.VideoChat' - tp_channel = cjson.encode([bus_name, connection, channel]) + tp_channel = simplejson.dumps([bus_name, connection, channel]) self._invites.add_private_invite(tp_channel, bundle_id) def _activity_disappeared_cb(self, pservice, activity): self._invites.remove_activity(activity.props.id) - -_model = None - -def get_model(): - global _model - if _model is None: - _model = Owner() - return _model diff --git a/src/jarabe/model/__init__.py b/src/model/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/model/__init__.py +++ b/src/model/__init__.py diff --git a/src/model/accesspointmodel.py b/src/model/accesspointmodel.py new file mode 100644 index 0000000..f464f75 --- /dev/null +++ b/src/model/accesspointmodel.py @@ -0,0 +1,80 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gobject + +from hardware import nmclient + +STATE_CONNECTING = 0 +STATE_CONNECTED = 1 +STATE_NOTCONNECTED = 2 + +_nm_state_to_state = { + nmclient.NETWORK_STATE_CONNECTED : STATE_CONNECTED, + nmclient.NETWORK_STATE_CONNECTING : STATE_CONNECTING, + nmclient.NETWORK_STATE_NOTCONNECTED : STATE_NOTCONNECTED +} + +class AccessPointModel(gobject.GObject): + __gproperties__ = { + 'name' : (str, None, None, None, + gobject.PARAM_READABLE), + 'strength' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'state' : (int, None, None, STATE_CONNECTING, + STATE_NOTCONNECTED, 0, gobject.PARAM_READABLE), + 'capabilities' : (int, None, None, 0, 0x7FFFFFFF, 0, + gobject.PARAM_READABLE), + 'mode' : (int, None, None, 0, 6, 0, gobject.PARAM_READABLE) + } + + def __init__(self, nm_device, nm_network): + gobject.GObject.__init__(self) + self._nm_network = nm_network + self._nm_device = nm_device + + self._nm_network.connect('strength-changed', + self._strength_changed_cb) + self._nm_network.connect('state-changed', + self._state_changed_cb) + + def _strength_changed_cb(self, nm_network): + self.notify('strength') + + def _state_changed_cb(self, nm_network): + self.notify('state') + + def get_id(self): + return self._nm_network.get_op() + + def get_nm_device(self): + return self._nm_device + + def get_nm_network(self): + return self._nm_network + + def do_get_property(self, pspec): + if pspec.name == 'strength': + return self._nm_network.get_strength() + elif pspec.name == 'name': + return self._nm_network.get_ssid() + elif pspec.name == 'state': + nm_state = self._nm_network.get_state() + return _nm_state_to_state[nm_state] + elif pspec.name == 'capabilities': + return self._nm_network.get_caps() + elif pspec.name == 'mode': + return self._nm_network.get_mode() diff --git a/src/model/devices/Makefile.am b/src/model/devices/Makefile.am new file mode 100644 index 0000000..274f1e7 --- /dev/null +++ b/src/model/devices/Makefile.am @@ -0,0 +1,10 @@ +SUBDIRS = network + +sugardir = $(pkgdatadir)/shell/model/devices +sugar_PYTHON = \ + __init__.py \ + battery.py \ + device.py \ + devicesmodel.py \ + speaker.py + diff --git a/src/jarabe/Makefile.in b/src/model/devices/Makefile.in index 16bfa5f..3537a15 100644 --- a/src/jarabe/Makefile.in +++ b/src/model/devices/Makefile.in @@ -29,15 +29,15 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe +subdir = src/model/devices DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ - $(srcdir)/config.py.in $(sugar_PYTHON) + $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d -CONFIG_CLEAN_FILES = config.py +CONFIG_CLEAN_FILES = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ @@ -85,9 +85,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -204,20 +201,14 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = \ - controlpanel \ - desktop \ - frame \ - journal \ - model \ - view \ - intro \ - util - -sugardir = $(pythondir)/jarabe +SUBDIRS = network +sugardir = $(pkgdatadir)/shell/model/devices sugar_PYTHON = \ - __init__.py \ - config.py + __init__.py \ + battery.py \ + device.py \ + devicesmodel.py \ + speaker.py all: all-recursive @@ -231,9 +222,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/model/devices/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/Makefile + $(AUTOMAKE) --foreign src/model/devices/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -251,8 +242,6 @@ $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh -config.py: $(top_builddir)/config.status $(srcdir)/config.py.in - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ install-sugarPYTHON: $(sugar_PYTHON) @$(NORMAL_INSTALL) test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" diff --git a/src/jarabe/view/__init__.py b/src/model/devices/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/view/__init__.py +++ b/src/model/devices/__init__.py diff --git a/src/model/devices/battery.py b/src/model/devices/battery.py new file mode 100644 index 0000000..7b52d4c --- /dev/null +++ b/src/model/devices/battery.py @@ -0,0 +1,97 @@ +# Copyright (C) 2006-2007, Red Hat, Inc. +# +# 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 + +import logging + +import gobject +import dbus + +from model.devices import device + +_LEVEL_PROP = 'battery.charge_level.percentage' +_CHARGING_PROP = 'battery.rechargeable.is_charging' +_DISCHARGING_PROP = 'battery.rechargeable.is_discharging' + +class Device(device.Device): + __gproperties__ = { + 'level' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'charging' : (bool, None, None, False, + gobject.PARAM_READABLE), + 'discharging' : (bool, None, None, False, + gobject.PARAM_READABLE) + } + + def __init__(self, udi): + device.Device.__init__(self, udi) + + bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) + proxy = bus.get_object('org.freedesktop.Hal', udi, + follow_name_owner_changes=True) + self._battery = dbus.Interface(proxy, 'org.freedesktop.Hal.Device') + bus.add_signal_receiver(self._battery_changed, + 'PropertyModified', + 'org.freedesktop.Hal.Device', + 'org.freedesktop.Hal', + udi) + + self._level = self._get_level() + self._charging = self._get_charging() + self._discharging = self._get_discharging() + + def _get_level(self): + try: + return self._battery.GetProperty(_LEVEL_PROP) + except dbus.DBusException: + logging.error('Cannot access %s' % _LEVEL_PROP) + return 0 + + def _get_charging(self): + try: + return self._battery.GetProperty(_CHARGING_PROP) + except dbus.DBusException: + logging.error('Cannot access %s' % _CHARGING_PROP) + return False + + def _get_discharging(self): + try: + return self._battery.GetProperty(_DISCHARGING_PROP) + except dbus.DBusException: + logging.error('Cannot access %s' % _DISCHARGING_PROP) + return False + + def do_get_property(self, pspec): + if pspec.name == 'level': + return self._level + if pspec.name == 'charging': + return self._charging + if pspec.name == 'discharging': + return self._discharging + + def get_type(self): + return 'battery' + + def _battery_changed(self, num_changes, changes_list): + for change in changes_list: + if change[0] == _LEVEL_PROP: + self._level = self._get_level() + self.notify('level') + elif change[0] == _CHARGING_PROP: + self._charging = self._get_charging() + self.notify('charging') + elif change[0] == _DISCHARGING_PROP: + self._discharging = self._get_discharging() + self.notify('discharging') diff --git a/src/jarabe/frame/frameinvoker.py b/src/model/devices/device.py index e4a13e1..3273da9 100644 --- a/src/jarabe/frame/frameinvoker.py +++ b/src/model/devices/device.py @@ -1,4 +1,5 @@ -# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com> +# +# Copyright (C) 2007, Red Hat, Inc. # # 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 @@ -14,23 +15,31 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import gtk +import gobject +from hardware import nmclient -from sugar.graphics import style -from sugar.graphics.palette import WidgetInvoker +from sugar import util -def _get_screen_area(): - frame_thickness = style.GRID_CELL_SIZE +STATE_ACTIVATING = 0 +STATE_ACTIVATED = 1 +STATE_INACTIVE = 2 - x = y = frame_thickness - width = gtk.gdk.screen_width() - frame_thickness - height = gtk.gdk.screen_height() - frame_thickness +nm_state_to_state = { + nmclient.DEVICE_STATE_ACTIVATING : STATE_ACTIVATING, + nmclient.DEVICE_STATE_ACTIVATED : STATE_ACTIVATED, + nmclient.DEVICE_STATE_INACTIVE : STATE_INACTIVE +} - return gtk.gdk.Rectangle(x, y, width, height) +class Device(gobject.GObject): + def __init__(self, device_id=None): + gobject.GObject.__init__(self) + if device_id: + self._id = device_id + else: + self._id = util.unique_id() -class FrameWidgetInvoker(WidgetInvoker): - def __init__(self, widget): - WidgetInvoker.__init__(self, widget, widget.child) + def get_type(self): + return 'unknown' - self._position_hint = self.ANCHORED - self._screen_area = _get_screen_area() + def get_id(self): + return self._id diff --git a/src/model/devices/devicesmodel.py b/src/model/devices/devicesmodel.py new file mode 100644 index 0000000..f328109 --- /dev/null +++ b/src/model/devices/devicesmodel.py @@ -0,0 +1,144 @@ +# +# Copyright (C) 2007, Red Hat, Inc. +# +# 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 + +import logging +import gobject +import dbus + +from model.devices import device +from model.devices.network import wireless +from model.devices.network import mesh +from model.devices import battery +from model.devices import speaker +from hardware import hardwaremanager +from hardware import nmclient + +class DevicesModel(gobject.GObject): + __gsignals__ = { + 'device-appeared' : (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])), + 'device-disappeared': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([gobject.TYPE_PYOBJECT])) + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._devices = {} + self._sigids = {} + + self._observe_hal_manager() + self._observe_network_manager() + + try: + self.add_device(speaker.Device()) + except Exception, speaker_fail_msg: + logging.error("could not initialize speaker device: %s" % + speaker_fail_msg) + + def _observe_hal_manager(self): + bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) + proxy = bus.get_object('org.freedesktop.Hal', + '/org/freedesktop/Hal/Manager') + hal_manager = dbus.Interface(proxy, 'org.freedesktop.Hal.Manager') + + for udi in hal_manager.FindDeviceByCapability('battery'): + self.add_device(battery.Device(udi)) + + def _observe_network_manager(self): + network_manager = hardwaremanager.get_network_manager() + if not network_manager: + return + + for dev in network_manager.get_devices(): + self._check_network_device(dev) + + network_manager.connect('device-added', + self._network_device_added_cb) + network_manager.connect('device-activating', + self._network_device_activating_cb) + network_manager.connect('device-activated', + self._network_device_activated_cb) + network_manager.connect('device-removed', + self._network_device_removed_cb) + + def _network_device_added_cb(self, network_manager, nm_device): + state = nm_device.get_state() + if state == nmclient.DEVICE_STATE_ACTIVATING \ + or state == nmclient.DEVICE_STATE_ACTIVATED: + self._check_network_device(nm_device) + + def _network_device_activating_cb(self, network_manager, nm_device): + self._check_network_device(nm_device) + + def _network_device_activated_cb(self, network_manager, nm_device): + pass + + def _network_device_removed_cb(self, network_manager, nm_device): + if self._devices.has_key(str(nm_device.get_op())): + self.remove_device(self._get_network_device(nm_device)) + + def _check_network_device(self, nm_device): + if not nm_device.is_valid(): + logging.debug("Device %s not valid" % nm_device.get_op()) + return + + dtype = nm_device.get_type() + if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS \ + or dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: + self._add_network_device(nm_device) + + def _get_network_device(self, nm_device): + return self._devices[str(nm_device.get_op())] + + def _network_device_state_changed_cb(self, dev, param): + if dev.props.state == device.STATE_INACTIVE: + self.remove_device(dev) + + def _add_network_device(self, nm_device): + if self._devices.has_key(str(nm_device.get_op())): + logging.debug("Tried to add device %s twice" % nm_device.get_op()) + return + + dtype = nm_device.get_type() + if dtype == nmclient.DEVICE_TYPE_802_11_WIRELESS: + dev = wireless.Device(nm_device) + self.add_device(dev) + sigid = dev.connect('notify::state', + self._network_device_state_changed_cb) + self._sigids[dev] = sigid + if dtype == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: + dev = mesh.Device(nm_device) + self.add_device(dev) + sigid = dev.connect('notify::state', + self._network_device_state_changed_cb) + self._sigids[dev] = sigid + + def __iter__(self): + return iter(self._devices.values()) + + def add_device(self, dev): + self._devices[dev.get_id()] = dev + self.emit('device-appeared', dev) + + def remove_device(self, dev): + self.emit('device-disappeared', self._devices[dev.get_id()]) + dev.disconnect(self._sigids[dev]) + del self._sigids[dev] + del self._devices[dev.get_id()] diff --git a/src/model/devices/network/Makefile.am b/src/model/devices/network/Makefile.am new file mode 100644 index 0000000..04074e5 --- /dev/null +++ b/src/model/devices/network/Makefile.am @@ -0,0 +1,6 @@ +sugardir = $(pkgdatadir)/shell/model/devices/network +sugar_PYTHON = \ + __init__.py \ + mesh.py \ + wired.py \ + wireless.py diff --git a/extensions/globalkey/Makefile.in b/src/model/devices/network/Makefile.in index 13c63e4..cf6ff13 100644 --- a/extensions/globalkey/Makefile.in +++ b/src/model/devices/network/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = extensions/globalkey +subdir = src/model/devices/network DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,11 +189,12 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/globalkey +sugardir = $(pkgdatadir)/shell/model/devices/network sugar_PYTHON = \ __init__.py \ - screenshot.py \ - viewsource.py + mesh.py \ + wired.py \ + wireless.py all: all-am @@ -210,9 +208,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/globalkey/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/model/devices/network/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/globalkey/Makefile + $(AUTOMAKE) --foreign src/model/devices/network/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/jarabe/controlpanel/__init__.py b/src/model/devices/network/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/model/devices/network/__init__.py diff --git a/src/model/devices/network/mesh.py b/src/model/devices/network/mesh.py new file mode 100644 index 0000000..ec2ca7b --- /dev/null +++ b/src/model/devices/network/mesh.py @@ -0,0 +1,86 @@ +# +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gobject + +from model.devices import device + +class Device(device.Device): + __gproperties__ = { + 'strength' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'state' : (int, None, None, device.STATE_ACTIVATING, + device.STATE_INACTIVE, 0, gobject.PARAM_READABLE), + 'activation-stage': (int, None, None, 0, 7, 0, gobject.PARAM_READABLE), + 'frequency': (float, None, None, 0, 2.72, 0, gobject.PARAM_READABLE), + 'mesh-step': (int, None, None, 0, 4, 0, gobject.PARAM_READABLE), + 'ip-address' : (str, None, None, None, gobject.PARAM_READABLE), + } + + def __init__(self, nm_device): + device.Device.__init__(self) + self._nm_device = nm_device + self._nm_device.connect('ip-changed', self._ip_changed_cb) + self.notify('ip-address') + + self._nm_device.connect('strength-changed', + self._strength_changed_cb) + self._nm_device.connect('state-changed', + self._state_changed_cb) + self._nm_device.connect('activation-stage-changed', + self._activation_stage_changed_cb) + + def _strength_changed_cb(self, nm_device): + self.notify('strength') + + def _state_changed_cb(self, nm_device): + self.notify('state') + + def _ip_changed_cb(self, nm_device): + self.notify('ip-address') + + def _activation_stage_changed_cb(self, nm_device): + self.notify('activation-stage') + + def do_get_property(self, pspec): + if pspec.name == 'strength': + return self._nm_device.get_strength() + elif pspec.name == 'state': + nm_state = self._nm_device.get_state() + return device.nm_state_to_state[nm_state] + elif pspec.name == 'activation-stage': + return self._nm_device.get_activation_stage() + elif pspec.name == 'frequency': + return self._nm_device.get_frequency() + elif pspec.name == 'mesh-step': + return self._nm_device.get_mesh_step() + elif pspec.name == 'ip-address': + return self.get_ip_address() + + def get_ip_address(self): + if self._nm_device is not None: + return self._nm_device.get_ip_address() + + def get_type(self): + return 'network.mesh' + + def get_id(self): + return str(self._nm_device.get_op()) + + def get_nm_device(self): + return self._nm_device + diff --git a/src/jarabe/__init__.py b/src/model/devices/network/wired.py index 41b4b1c..aa0ba00 100644 --- a/src/jarabe/__init__.py +++ b/src/model/devices/network/wired.py @@ -1,13 +1,3 @@ -"""OLPC Sugar Graphical "Shell" Interface - -Provides the shell-level operations for managing -the OLPC laptop computers. It interacts heavily -with (and depends upon) the Sugar UI libraries. - -This is a "graphical" shell, the name does not -refer to a command-line "shell" interface. -""" - # Copyright (C) 2006-2007, Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify @@ -24,3 +14,15 @@ refer to a command-line "shell" interface. # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +from model.devices import device + +class Device(device.Device): + def __init__(self, nm_device): + device.Device.__init__(self) + self._nm_device = nm_device + + def get_id(self): + return str(self._nm_device.get_op()) + + def get_type(self): + return 'network.wired' diff --git a/src/model/devices/network/wireless.py b/src/model/devices/network/wireless.py new file mode 100644 index 0000000..b2efb49 --- /dev/null +++ b/src/model/devices/network/wireless.py @@ -0,0 +1,102 @@ +# +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gobject + +from model.devices import device + +def freq_to_channel(freq): + ftoc = { 2.412: 1, 2.417: 2, 2.422: 3, 2.427: 4, + 2.432: 5, 2.437: 6, 2.442: 7, 2.447: 8, + 2.452: 9, 2.457: 10, 2.462: 11, 2.467: 12, + 2.472: 13 + } + return ftoc[freq] + +def channel_to_freq(channel): + ctof = { 1: 2.412, 2: 2.417, 3: 2.422, 4: 2.427, + 5: 2.432, 6: 2.437, 7: 2.442, 8: 2.447, + 9: 2.452, 10: 2.457, 11: 2.462, 12: 2.467, + 13: 2.472 + } + return ctof[channel] + +class Device(device.Device): + __gproperties__ = { + 'name' : (str, None, None, None, + gobject.PARAM_READABLE), + 'strength' : (int, None, None, 0, 100, 0, + gobject.PARAM_READABLE), + 'state' : (int, None, None, device.STATE_ACTIVATING, + device.STATE_INACTIVE, 0, gobject.PARAM_READABLE), + 'frequency': (float, None, None, 0.0, 9999.99, 0.0, + gobject.PARAM_READABLE), + 'ip-address' : (str, None, None, None, gobject.PARAM_READABLE), + } + + def __init__(self, nm_device): + device.Device.__init__(self) + self._nm_device = nm_device + + self._nm_device.connect('strength-changed', + self._strength_changed_cb) + self._nm_device.connect('ssid-changed', + self._ssid_changed_cb) + self._nm_device.connect('state-changed', + self._state_changed_cb) + self._nm_device.connect('ip-changed', self._ip_changed_cb) + + def _strength_changed_cb(self, nm_device): + self.notify('strength') + + def _ssid_changed_cb(self, nm_device): + self.notify('name') + + def _state_changed_cb(self, nm_device): + self.notify('state') + + def _ip_changed_cb(self, nm_device): + self.notify('ip-address') + + def do_get_property(self, pspec): + if pspec.name == 'strength': + return self._nm_device.get_strength() + elif pspec.name == 'name': + import logging + logging.debug('wireless.Device.props.name: %s' % + self._nm_device.get_ssid()) + return self._nm_device.get_ssid() + elif pspec.name == 'state': + nm_state = self._nm_device.get_state() + return device.nm_state_to_state[nm_state] + elif pspec.name == 'frequency': + return self._nm_device.get_frequency() + elif pspec.name == 'ip-address': + return self._nm_device.get_ip_address() + + def get_type(self): + return 'network.wireless' + + def get_id(self): + return str(self._nm_device.get_op()) + + def get_active_network_colors(self): + net = self._nm_device.get_active_network() + if not net: + return (None, None) + return net.get_colors() + diff --git a/src/model/devices/speaker.py b/src/model/devices/speaker.py new file mode 100644 index 0000000..c2a3a18 --- /dev/null +++ b/src/model/devices/speaker.py @@ -0,0 +1,65 @@ +# Copyright (C) 2008 Martin Dengler +# +# 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 + +import gobject + +from hardware import hardwaremanager +from model.devices import device + +class Device(device.Device): + __gproperties__ = { + 'level' : (int, None, None, 0, 100, 0, gobject.PARAM_READWRITE), + 'muted' : (bool, None, None, False, gobject.PARAM_READWRITE), + } + + def __init__(self): + device.Device.__init__(self) + self._manager = hardwaremanager.get_manager() + self._manager.connect('muted-changed', self.__muted_changed_cb) + self._manager.connect('volume-changed', self.__volume_changed_cb) + + def __muted_changed_cb(self, sender_, old_state_, new_state_): + self.notify('muted') + + def __volume_changed_cb(self, sender_, old_volume_, new_volume_): + self.notify('level') + + def _get_level(self): + return self._manager.get_volume() + + def _set_level(self, new_volume): + self._manager.set_volume(new_volume) + + def _get_muted(self): + return self._manager.get_muted() + + def _set_muted(self, mute): + self._manager.set_muted(mute) + + def get_type(self): + return 'speaker' + + def do_get_property(self, pspec): + if pspec.name == "level": + return self._get_level() + elif pspec.name == "muted": + return self._get_muted() + + def do_set_property(self, pspec, value): + if pspec.name == "level": + self._set_level(value) + elif pspec.name == "muted": + self._set_muted(value) diff --git a/src/model/homeactivity.py b/src/model/homeactivity.py new file mode 100644 index 0000000..6df4ddd --- /dev/null +++ b/src/model/homeactivity.py @@ -0,0 +1,240 @@ +# Copyright (C) 2006-2007 Owen Williams. +# +# 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 + +import time +import logging + +import gobject +import dbus + +from sugar.graphics.xocolor import XoColor +from sugar.presence import presenceservice +from sugar import profile + +_SERVICE_NAME = "org.laptop.Activity" +_SERVICE_PATH = "/org/laptop/Activity" +_SERVICE_INTERFACE = "org.laptop.Activity" + +class HomeActivity(gobject.GObject): + """Activity which appears in the "Home View" of the Sugar shell + + This class stores the Sugar Shell's metadata regarding a + given activity/application in the system. It interacts with + the sugar.activity.* modules extensively in order to + accomplish its tasks. + """ + + __gtype_name__ = 'SugarHomeActivity' + + __gproperties__ = { + 'launching' : (bool, None, None, False, + gobject.PARAM_READWRITE), + } + + def __init__(self, activity_info, activity_id): + """Initialise the HomeActivity + + activity_info -- sugar.activity.registry.ActivityInfo instance, + provides the information required to actually + create the new instance. This is, in effect, + the "type" of activity being created. + activity_id -- unique identifier for this instance + of the activity type + """ + gobject.GObject.__init__(self) + + self._window = None + self._xid = None + self._pid = None + self._service = None + self._activity_id = activity_id + self._activity_info = activity_info + self._launch_time = time.time() + self._launching = False + + self._retrieve_service() + + self._name_owner_changed_handler = None + if not self._service: + 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") + + 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. + """ + if not window: + raise ValueError("window must be valid") + + self._window = window + self._xid = window.get_xid() + self._pid = window.get_pid() + + def get_service(self): + """Get the activity service + + Note that non-native Sugar applications will not have + such a service, so the return value will be None in + those cases. + """ + + return self._service + + def get_title(self): + """Retrieve the application's root window's suggested title""" + if self._window: + return self._window.get_name() + else: + return '' + + def get_icon_path(self): + """Retrieve the activity's icon (file) name""" + if self._activity_info: + return self._activity_info.icon + else: + return None + + def get_icon_color(self): + """Retrieve the appropriate icon colour for this activity + + Uses activity_id to index into the PresenceService's + set of activity colours, if the PresenceService does not + have an entry (implying that this is not a Sugar-shared application) + uses the local user's profile.get_color() to determine the + colour for the icon. + """ + pservice = presenceservice.get_instance() + + # HACK to suppress warning in logs when activity isn't found + # (if it's locally launched and not shared yet) + activity = None + for act in pservice.get_activities(): + if self._activity_id == act.props.id: + activity = act + break + + if activity != None: + return XoColor(activity.props.color) + else: + return profile.get_color() + + def get_activity_id(self): + """Retrieve the "activity_id" passed in to our constructor + + This is a "globally likely unique" identifier generated by + sugar.util.unique_id + """ + return self._activity_id + + def get_xid(self): + """Retrieve the X-windows ID of our root window""" + return self._xid + + def get_window(self): + """Retrieve the X-windows root window of this application + + This was stored by the set_window method, which was + called by HomeModel._add_activity, which was called + via a callback that looks for all 'window-opened' + events. + + HomeModel currently uses a dbus service query on the + activity to determine to which HomeActivity the newly + launched window belongs. + """ + return self._window + + def get_type(self): + """Retrieve the activity bundle id for future reference""" + if self._activity_info: + return self._activity_info.bundle_id + else: + return None + + def is_journal(self): + """Returns boolean if the activity is of type JournalActivity""" + return self.get_type() == 'org.laptop.JournalActivity' + + def get_launch_time(self): + """Return the time at which the activity was first launched + + Format is floating-point time.time() value + (seconds since the epoch) + """ + return self._launch_time + + def get_pid(self): + """Returns the activity's PID""" + return self._pid + + def equals(self, activity): + if self._activity_id and activity.get_activity_id(): + return self._activity_id == activity.get_activity_id() + if self._xid and activity.get_xid(): + return self._xid == activity.get_xid() + return False + + def do_set_property(self, pspec, value): + if pspec.name == 'launching': + self._launching = value + + def do_get_property(self, pspec): + if pspec.name == 'launching': + return self._launching + + def _get_service_name(self): + if self._activity_id: + return _SERVICE_NAME + self._activity_id + else: + return None + + def _retrieve_service(self): + if not self._activity_id: + return + + try: + bus = dbus.SessionBus() + proxy = bus.get_object(self._get_service_name(), + _SERVICE_PATH + "/" + self._activity_id) + self._service = dbus.Interface(proxy, _SERVICE_INTERFACE) + except dbus.DBusException: + self._service = None + + def _name_owner_changed_cb(self, name, old, new): + if name == self._get_service_name(): + self._retrieve_service() + self.set_active(True) + self._name_owner_changed_handler.remove() + self._name_owner_changed_handler = None + + def set_active(self, state): + """Propagate the current state to the activity object""" + if self._service is not None: + self._service.SetActive(state, + reply_handler=self._set_active_success, + error_handler=self._set_active_error) + + def _set_active_success(self): + pass + + def _set_active_error(self, err): + logging.error("set_active() failed: %s" % err) + diff --git a/src/model/homemodel.py b/src/model/homemodel.py new file mode 100644 index 0000000..aab99c0 --- /dev/null +++ b/src/model/homemodel.py @@ -0,0 +1,286 @@ +# Copyright (C) 2006-2007 Owen Williams. +# +# 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 + +import logging + +import gobject +import wnck +import gtk + +from sugar import wm +from sugar import activity + +from model.homeactivity import HomeActivity + +def _get_sugar_window_type(wnck_window): + window = gtk.gdk.window_foreign_new(wnck_window.get_xid()) + prop_info = window.property_get('_SUGAR_WINDOW_TYPE', 'STRING') + if prop_info is None: + return None + else: + return prop_info[2] + +class HomeModel(gobject.GObject): + """Model of the "Home" view (activity management) + + The HomeModel is basically the point of registration + for all running activities within Sugar. It traps + events that tell the system there is a new activity + being created (generated by the activity factories), + or removed, as well as those which tell us that the + currently focussed activity has changed. + + The HomeModel tracks a set of HomeActivity instances, + which are tracking the window to activity mappings + the activity factories have set up. + """ + __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])), + 'active-activity-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([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])) + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._activities = [] + self._active_activity = None + self._tabbing_activity = None + + screen = wnck.screen_get_default() + screen.connect('window-opened', self._window_opened_cb) + screen.connect('window-closed', self._window_closed_cb) + screen.connect('active-window-changed', + self._active_window_changed_cb) + + def _get_activities_with_window(self): + ret = [] + for i in self._activities: + if i.get_window() is not None: + ret.append(i) + return ret + + def get_previous_activity(self, current=None): + if not current: + current = self._active_activity + + activities = self._get_activities_with_window() + i = activities.index(current) + if len(activities) == 0: + return None + elif i - 1 >= 0: + return activities[i - 1] + else: + return activities[len(activities) - 1] + + def get_next_activity(self, current=None): + if not current: + current = self._active_activity + + activities = self._get_activities_with_window() + i = activities.index(current) + if len(activities) == 0: + return None + elif i + 1 < len(activities): + return activities[i + 1] + else: + return activities[0] + + def get_active_activity(self): + """Returns the activity that the user is currently working in""" + return self._active_activity + + def get_tabbing_activity(self): + """Returns the activity that is currently highlighted during tabbing""" + return self._tabbing_activity + + 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) + + def _set_active_activity(self, home_activity): + if self._active_activity == home_activity: + return + + if home_activity: + home_activity.set_active(True) + + if self._active_activity: + self._active_activity.set_active(False) + + self._active_activity = home_activity + self.emit('active-activity-changed', self._active_activity) + + def __iter__(self): + return iter(self._activities) + + def __len__(self): + return len(self._activities) + + def __getitem__(self, i): + return self._activities[i] + + def index(self, obj): + return self._activities.index(obj) + + def _window_opened_cb(self, screen, window): + if window.get_window_type() == wnck.WINDOW_NORMAL: + home_activity = None + + activity_id = wm.get_activity_id(window) + + service_name = wm.get_bundle_id(window) + if service_name: + registry = activity.get_registry() + activity_info = registry.get_activity(service_name) + else: + activity_info = None + + if activity_id: + home_activity = self._get_activity_by_id(activity_id) + + if not home_activity: + home_activity = HomeActivity(activity_info, activity_id) + self._add_activity(home_activity) + + home_activity.set_window(window) + + if _get_sugar_window_type(window) != 'launcher': + home_activity.props.launching = False + self.emit('launch-completed', home_activity) + + 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: + self._remove_activity_by_xid(window.get_xid()) + + def _get_activity_by_xid(self, xid): + for home_activity in self._activities: + if home_activity.get_xid() == xid: + return home_activity + return None + + def _get_activity_by_id(self, activity_id): + for home_activity in self._activities: + if home_activity.get_activity_id() == activity_id: + return home_activity + return None + + def _active_window_changed_cb(self, screen, previous_window=None): + window = screen.get_active_window() + if window is None: + return + + if window.get_window_type() != wnck.WINDOW_DIALOG: + while window.get_transient() is not None: + window = window.get_transient() + + act = self._get_activity_by_xid(window.get_xid()) + if act is not None: + self._set_active_activity(act) + + def _add_activity(self, home_activity): + self._activities.append(home_activity) + self.emit('activity-added', home_activity) + + def _remove_activity(self, home_activity): + if home_activity == self._active_activity: + windows = wnck.screen_get_default().get_windows_stacked() + windows.reverse() + for window in windows: + new_activity = self._get_activity_by_xid(window.get_xid()) + if new_activity is not None: + self._set_active_activity(new_activity) + break + else: + logging.error('No activities are running') + self._set_active_activity(None) + + 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 = activity.get_registry() + activity_info = registry.get_activity(service_name) + if not activity_info: + raise ValueError("Activity service name '%s'" \ + " was not found in the bundle registry." + % service_name) + home_activity = HomeActivity(activity_info, activity_id) + home_activity.props.launching = True + self._add_activity(home_activity) + + self._set_active_activity(home_activity) + + self.emit('launch-started', home_activity) + + # FIXME: better learn about finishing processes by receiving a signal. + # Now just check whether an activity has a window after ~90sec + gobject.timeout_add(90000, self._check_activity_launched, activity_id) + + 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, home_activity.get_type())) + home_activity.props.launching = False + self._remove_activity(home_activity) + else: + logging.error('Model for activity id %s does not exist.' + % activity_id) + + self.emit('launch-failed', home_activity) + + def _check_activity_launched(self, activity_id): + home_activity = self._get_activity_by_id(activity_id) + + if not home_activity: + logging.debug('Activity %s has been closed already.' % activity_id) + return False + + if home_activity.props.launching: + logging.debug('Activity %s still launching, assuming it failed...' + % activity_id) + self.notify_launch_failed(activity_id) + return False diff --git a/src/model/shellmodel.py b/src/model/shellmodel.py new file mode 100644 index 0000000..d1d8db8 --- /dev/null +++ b/src/model/shellmodel.py @@ -0,0 +1,104 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import wnck +import gobject + +from sugar.presence import presenceservice +from model.Friends import Friends +from model.MeshModel import MeshModel +from model.homemodel import HomeModel +from model.Owner import ShellOwner +from model.devices.devicesmodel import DevicesModel + +class ShellModel(gobject.GObject): + ZOOM_MESH = 0 + ZOOM_FRIENDS = 1 + ZOOM_HOME = 2 + ZOOM_ACTIVITY = 3 + + __gproperties__ = { + 'zoom-level' : (int, None, None, + 0, 3, ZOOM_HOME, + gobject.PARAM_READABLE) + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._current_activity = None + self._zoom_level = self.ZOOM_HOME + self._showing_desktop = True + + self._pservice = presenceservice.get_instance() + + self._owner = ShellOwner() + + self._friends = Friends() + self._mesh = MeshModel() + self._home = HomeModel() + self._devices = DevicesModel() + + self._screen = wnck.screen_get_default() + self._screen.connect('showing-desktop-changed', + self._showing_desktop_changed_cb) + + def set_zoom_level(self, level): + self._zoom_level = level + self.notify('zoom-level') + + def get_zoom_level(self): + if self._screen.get_showing_desktop(): + return self._zoom_level + else: + return self.ZOOM_ACTIVITY + + def do_get_property(self, pspec): + if pspec.name == 'zoom-level': + return self.get_zoom_level() + + def get_mesh(self): + return self._mesh + + def get_friends(self): + return self._friends + + def get_invites(self): + return self._owner.get_invites() + + def get_home(self): + return self._home + + def get_owner(self): + return self._owner + + def get_devices(self): + return self._devices + + def _showing_desktop_changed_cb(self, screen): + showing_desktop = self._screen.get_showing_desktop() + if self._showing_desktop != showing_desktop: + self._showing_desktop = showing_desktop + self.notify('zoom-level') + +_instance = None + +def get_instance(): + global _instance + if not _instance: + _instance = ShellModel() + return _instance + diff --git a/src/jarabe/model/session.py b/src/session.py index 8927260..1594fb5 100644 --- a/src/jarabe/model/session.py +++ b/src/session.py @@ -22,6 +22,8 @@ import signal from sugar import session from sugar import env +from hardware import hardwaremanager + _session_manager = None class SessionManager(session.SessionManager): @@ -48,6 +50,9 @@ class SessionManager(session.SessionManager): def shutdown_completed(self): session.SessionManager.shutdown_completed(self) + hw_manager = hardwaremanager.get_manager() + hw_manager.shutdown() + bus = dbus.SystemBus() proxy = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/devices/computer') diff --git a/src/jarabe/view/service.py b/src/shellservice.py index a2439ce..706f2f2 100644 --- a/src/jarabe/view/service.py +++ b/src/shellservice.py @@ -15,14 +15,11 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA """D-bus service providing access to the shell's functionality""" -import os - import dbus -import gtk +import os -from jarabe.model import shell -from jarabe.model import owner -from jarabe.model import bundleregistry +from view import Shell +from model import shellmodel _DBUS_SERVICE = "org.laptop.Shell" _DBUS_SHELL_IFACE = "org.laptop.Shell" @@ -31,7 +28,7 @@ _DBUS_PATH = "/org/laptop/Shell" _DBUS_RAINBOW_IFACE = "org.laptop.security.Rainbow" -class UIService(dbus.service.Object): +class ShellService(dbus.service.Object): """Provides d-bus service to script the shell's operations Uses a shell_model object to observe events such as changes to: @@ -53,36 +50,28 @@ class UIService(dbus.service.Object): _rainbow = None def __init__(self): - bus = dbus.SessionBus() - bus_name = dbus.service.BusName(_DBUS_SERVICE, bus=bus) - dbus.service.Object.__init__(self, bus_name, _DBUS_PATH) + self._shell = Shell.get_instance() + self._shell_model = shellmodel.get_instance() - self._shell_model = shell.get_model() + self._owner = self._shell_model.get_owner() + self._owner.connect('nick-changed', self._owner_nick_changed_cb) + self._owner.connect('icon-changed', self._owner_icon_changed_cb) + self._owner.connect('color-changed', self._owner_color_changed_cb) - def start(self): - owner_model = owner.get_model() - owner_model.connect('nick-changed', self._owner_nick_changed_cb) - owner_model.connect('icon-changed', self._owner_icon_changed_cb) - owner_model.connect('color-changed', self._owner_color_changed_cb) + self._home_model = self._shell_model.get_home() + self._home_model.connect('active-activity-changed', + self._cur_activity_changed_cb) - self._shell_model.connect('active-activity-changed', - self._cur_activity_changed_cb) - - @dbus.service.method(_DBUS_SHELL_IFACE, - in_signature="s", out_signature="s") - def GetBundlePath(self, bundle_id): - bundle = bundleregistry.get_registry().get_bundle(bundle_id) - if bundle: - return bundle.get_path() - else: - return '' + bus = dbus.SessionBus() + bus_name = dbus.service.BusName(_DBUS_SERVICE, bus=bus) + dbus.service.Object.__init__(self, bus_name, _DBUS_PATH) @dbus.service.method(_DBUS_SHELL_IFACE, in_signature="s", out_signature="b") def ActivateActivity(self, activity_id): - activity = self._shell_model.get_activity_by_id(activity_id) - if activity: - activity.get_window().activate(gtk.get_current_event_time()) + host = self._shell.get_activity(activity_id) + if host: + host.present() return True return False @@ -90,12 +79,14 @@ class UIService(dbus.service.Object): @dbus.service.method(_DBUS_SHELL_IFACE, in_signature="ss", out_signature="") def NotifyLaunch(self, bundle_id, activity_id): - shell.get_model().notify_launch(activity_id, bundle_id) + home = self._shell.get_model().get_home() + home.notify_launch(activity_id, bundle_id) @dbus.service.method(_DBUS_SHELL_IFACE, in_signature="s", out_signature="") def NotifyLaunchFailure(self, activity_id): - shell.get_model().notify_launch_failed(activity_id) + home = self._shell.get_model().get_home() + home.notify_launch_failed(activity_id) @dbus.service.signal(_DBUS_OWNER_IFACE, signature="s") def ColorChanged(self, color): @@ -135,7 +126,7 @@ class UIService(dbus.service.Object): activity_id, dbus_interface=_DBUS_RAINBOW_IFACE) - def _cur_activity_changed_cb(self, shell_model, new_activity): + def _cur_activity_changed_cb(self, owner, new_activity): new_id = "" if new_activity: new_id = new_activity.get_activity_id() diff --git a/src/view/ActivityHost.py b/src/view/ActivityHost.py new file mode 100644 index 0000000..9f37c96 --- /dev/null +++ b/src/view/ActivityHost.py @@ -0,0 +1,63 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gtk +import logging + +import OverlayWindow + +class ActivityHost: + def __init__(self, model): + self._model = model + self._window = model.get_window() + self._gdk_window = gtk.gdk.window_foreign_new(self.get_xid()) + + try: + self._overlay_window = OverlayWindow.OverlayWindow(self._gdk_window) + except RuntimeError: + self._overlay_window = None + + def get_id(self): + return self._model.get_activity_id() + + def get_xid(self): + return self._window.get_xid() + + def get_model(self): + return self._model + + def invite(self, buddy_model): + service = self._model.get_service() + if service: + buddy = buddy_model.get_buddy() + service.Invite(buddy.props.key) + else: + logging.error('Invite failed, activity service not ') + + def toggle_fullscreen(self): + fullscreen = not self._window.is_fullscreen() + self._window.set_fullscreen(fullscreen) + + def present(self): + self._window.activate(gtk.get_current_event_time()) + + def close(self): + # The "1" is a fake timestamp as with present() + self._window.close(1) + + def show_dialog(self, dialog): + dialog.show() + dialog.window.set_transient_for(self._gdk_window) diff --git a/src/jarabe/view/buddyicon.py b/src/view/BuddyIcon.py index 13edb2c..b921fa5 100644 --- a/src/jarabe/view/buddyicon.py +++ b/src/view/BuddyIcon.py @@ -17,7 +17,7 @@ from sugar.graphics.icon import CanvasIcon from sugar.graphics import style -from jarabe.view.buddymenu import BuddyMenu +from view.BuddyMenu import BuddyMenu class BuddyIcon(CanvasIcon): def __init__(self, buddy, size=style.STANDARD_ICON_SIZE): diff --git a/src/jarabe/view/buddymenu.py b/src/view/BuddyMenu.py index fc1fdbe..427ac3d 100644 --- a/src/jarabe/view/buddymenu.py +++ b/src/view/BuddyMenu.py @@ -14,7 +14,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import logging from gettext import gettext as _ import gtk @@ -23,8 +22,8 @@ from sugar.graphics.palette import Palette from sugar.graphics.menuitem import MenuItem from sugar.graphics.icon import Icon -from jarabe.model import shell -from jarabe.model import friends +from model import shellmodel +import view.Shell class BuddyMenu(Palette): def __init__(self, buddy): @@ -45,15 +44,19 @@ class BuddyMenu(Palette): if not buddy.is_owner(): self._add_items() + def _get_home_model(self): + return shellmodel.get_instance().get_home() + def __destroy_cb(self, menu): if self._active_activity_changed_hid is not None: - home_model = shell.get_model() + home_model = self._get_home_model() home_model.disconnect(self._active_activity_changed_hid) self._buddy.disconnect_by_func(self._buddy_icon_changed_cb) self._buddy.disconnect_by_func(self._buddy_nick_changed_cb) def _add_items(self): - if friends.get_model().has_buddy(self._buddy): + friends = shellmodel.get_instance().get_friends() + if friends.has_buddy(self._buddy): menu_item = MenuItem(_('Remove friend'), 'list-remove') menu_item.connect('activate', self._remove_friend_cb) else: @@ -67,7 +70,7 @@ class BuddyMenu(Palette): self._invite_menu.connect('activate', self._invite_friend_cb) self.menu.append(self._invite_menu) - home_model = shell.get_model() + home_model = self._get_home_model() self._active_activity_changed_hid = home_model.connect( 'active-activity-changed', self._cur_activity_changed_cb) activity = home_model.get_active_activity() @@ -105,16 +108,14 @@ class BuddyMenu(Palette): self.set_primary_text(nick) def _make_friend_cb(self, menuitem): - friends.get_model().make_friend(self._buddy) + friends = shellmodel.get_instance().get_friends() + friends.make_friend(self._buddy) def _remove_friend_cb(self, menuitem): - friends.get_model().remove(self._buddy) + friends = shellmodel.get_instance().get_friends() + friends.remove(self._buddy) def _invite_friend_cb(self, menuitem): - activity = shell.get_model().get_active_activity() - service = activity.get_service() - if service: - buddy = self._buddy.get_buddy() - service.Invite(buddy.props.key) - else: - logging.error('Invite failed, activity service not ') + activity = view.Shell.get_instance().get_current_activity() + activity.invite(self._buddy) + diff --git a/src/view/Makefile.am b/src/view/Makefile.am new file mode 100644 index 0000000..d905b7a --- /dev/null +++ b/src/view/Makefile.am @@ -0,0 +1,17 @@ +SUBDIRS = devices frame home + +sugardir = $(pkgdatadir)/shell/view +sugar_PYTHON = \ + __init__.py \ + ActivityHost.py \ + BuddyIcon.py \ + BuddyMenu.py \ + clipboardicon.py \ + clipboardmenu.py \ + keyhandler.py \ + launchwindow.py \ + pulsingicon.py \ + tabbinghandler.py \ + OverlayWindow.py \ + palettes.py \ + Shell.py diff --git a/src/jarabe/util/Makefile.in b/src/view/Makefile.in index b149fcd..0525c9b 100644 --- a/src/jarabe/util/Makefile.in +++ b/src/view/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/util +subdir = src/view DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -85,9 +85,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -204,12 +201,22 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = \ - telepathy - -sugardir = $(pythondir)/jarabe/util +SUBDIRS = devices frame home +sugardir = $(pkgdatadir)/shell/view sugar_PYTHON = \ - __init__.py + __init__.py \ + ActivityHost.py \ + BuddyIcon.py \ + BuddyMenu.py \ + clipboardicon.py \ + clipboardmenu.py \ + keyhandler.py \ + launchwindow.py \ + pulsingicon.py \ + tabbinghandler.py \ + OverlayWindow.py \ + palettes.py \ + Shell.py all: all-recursive @@ -223,9 +230,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/util/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/view/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/util/Makefile + $(AUTOMAKE) --foreign src/view/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/view/OverlayWindow.py b/src/view/OverlayWindow.py new file mode 100644 index 0000000..15bcb49 --- /dev/null +++ b/src/view/OverlayWindow.py @@ -0,0 +1,70 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gtk +import cairo + +def _grab_pixbuf(window=None): + if not window: + screen = gtk.gdk.screen_get_default() + window = screen.get_root_window() + color_map = gtk.gdk.colormap_get_system() + (x, y, w, h, bpp_) = window.get_geometry() + return gtk.gdk.pixbuf_get_from_drawable(None, window, color_map, + x, y, 0, 0, w, h) + +class OverlayWindow(gtk.Window): + def __init__(self, lower_window): + gtk.Window.__init__(self) + self._lower_window = lower_window + + self._img = gtk.Image() + self.add(self._img) + + self.realize() + + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) + self.window.set_accept_focus(False) + self.window.set_transient_for(lower_window) + + self.set_decorated(False) + self.set_position(gtk.WIN_POS_CENTER_ALWAYS) + self.set_default_size(gtk.gdk.screen_width(), gtk.gdk.screen_height()) + self.set_app_paintable(True) + + # self.connect('expose-event', self._expose_cb) + + def appear(self): + pbuf = _grab_pixbuf(self._lower_window) + #pbuf.saturate_and_pixelate(pbuf, 0.5, False) + w = pbuf.get_width() + h = pbuf.get_height() + pbuf2 = pbuf.composite_color_simple(w, h, gtk.gdk.INTERP_NEAREST, + 100, 1024, 0, 0) + self._img.set_from_pixbuf(pbuf2) + self.show_all() + + def disappear(self): + self._img.set_from_pixbuf(None) + self.hide() + + def _expose_cb(self, widget, event): + cr = widget.window.cairo_create() + cr.set_source_rgba(0.0, 0.0, 0.0, 0.4) # Transparent + cr.set_operator(cairo.OPERATOR_SOURCE) + cr.paint() + return False + diff --git a/src/view/Shell.py b/src/view/Shell.py new file mode 100644 index 0000000..41778d0 --- /dev/null +++ b/src/view/Shell.py @@ -0,0 +1,272 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 gettext import gettext as _ +from sets import Set +import logging +import tempfile +import os +import time +import shutil + +import gobject +import gtk +import wnck +import dbus + +from sugar.activity.activityhandle import ActivityHandle +from sugar import activity +from sugar.activity import activityfactory +from sugar.datastore import datastore +from sugar import profile +from sugar import env + +from view.ActivityHost import ActivityHost +from view.frame import frame +from view.keyhandler import KeyHandler +from view.home.HomeWindow import HomeWindow +from view.launchwindow import LaunchWindow +from model import shellmodel + +# #3903 - this constant can be removed and assumed to be 1 when dbus-python +# 0.82.3 is the only version used +if dbus.version >= (0, 82, 3): + DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND = 1 +else: + DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND = 1000 + +class Shell(gobject.GObject): + def __init__(self): + gobject.GObject.__init__(self) + + self._model = shellmodel.get_instance() + self._hosts = {} + self._launchers = {} + self._screen = wnck.screen_get_default() + self._screen_rotation = 0 + + self._key_handler = KeyHandler() + + self._frame = frame.get_instance() + + self.home_window = HomeWindow() + self.home_window.show() + + home_model = self._model.get_home() + home_model.connect('launch-started', self.__launch_started_cb) + home_model.connect('launch-failed', self.__launch_failed_cb) + home_model.connect('launch-completed', self.__launch_completed_cb) + home_model.connect('activity-removed', self._activity_removed_cb) + + gobject.idle_add(self._start_journal_idle) + + def _start_journal_idle(self): + # Mount the datastore in internal flash + ds_path = env.get_profile_path('datastore') + try: + datastore.mount(ds_path, [], timeout=120 * \ + DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND) + except Exception: + # Don't explode if there's corruption; move the data out of the way + # and attempt to create a store from scratch. + shutil.move(ds_path, os.path.abspath(ds_path) + str(time.time())) + datastore.mount(ds_path, [], timeout=120 * \ + DBUS_PYTHON_TIMEOUT_UNITS_PER_SECOND) + + # Checking for the bundle existence will also ensure + # that the shell service is started up. + registry = activity.get_registry() + if registry.get_activity('org.laptop.JournalActivity'): + self.start_activity('org.laptop.JournalActivity') + + def __launch_started_cb(self, home_model, home_activity): + if home_activity.is_journal(): + return + + launch_window = LaunchWindow(home_activity) + launch_window.show() + + self._launchers[home_activity.get_activity_id()] = launch_window + self._model.set_zoom_level(shellmodel.ShellModel.ZOOM_ACTIVITY) + + def __launch_failed_cb(self, home_model, home_activity): + if not home_activity.is_journal(): + self._destroy_launcher(home_activity) + + def __launch_completed_cb(self, home_model, home_activity): + activity_host = ActivityHost(home_activity) + self._hosts[activity_host.get_xid()] = activity_host + + if not home_activity.is_journal(): + self._destroy_launcher(home_activity) + + def _destroy_launcher(self, home_activity): + activity_id = home_activity.get_activity_id() + + if activity_id in self._launchers: + self._launchers[activity_id].destroy() + del self._launchers[activity_id] + else: + logging.error('Launcher for %s is missing' % activity_id) + + def _activity_removed_cb(self, home_model, home_activity): + xid = home_activity.get_xid() + if self._hosts.has_key(xid): + del self._hosts[xid] + + def _get_host_from_activity_model(self, activity_model): + host = None + if activity_model is not None: + xid = activity_model.get_xid() + if xid: + host = self._hosts[activity_model.get_xid()] + return host + + def get_model(self): + return self._model + + def get_frame(self): + return self._frame + + def join_activity(self, bundle_id, activity_id): + activity_host = self.get_activity(activity_id) + if activity_host: + activity_host.present() + return + + # Get the service name for this activity, if + # we have a bundle on the system capable of handling + # this activity type + registry = activity.get_registry() + bundle = registry.get_activity(bundle_id) + if not bundle: + logging.error("Couldn't find activity for type %s" % bundle_id) + return + + handle = ActivityHandle(activity_id) + activityfactory.create(bundle_id, handle) + + def start_activity(self, activity_type): + activityfactory.create(activity_type) + + def start_activity_with_uri(self, activity_type, uri): + activityfactory.create_with_uri(activity_type, uri) + + def take_activity_screenshot(self): + if self._model.get_zoom_level() != shellmodel.ShellModel.ZOOM_ACTIVITY: + return + if self.get_frame().visible: + return + + home_model = self._model.get_home() + active_activity = home_model.get_active_activity() + if active_activity is not None: + service = active_activity.get_service() + if service is not None: + try: + service.TakeScreenshot(timeout=2.0) + except dbus.DBusException, e: + logging.debug('Error raised by TakeScreenshot(): %s', e) + + def set_zoom_level(self, level): + if level == self._model.get_zoom_level(): + return + + if level == shellmodel.ShellModel.ZOOM_ACTIVITY: + host = self.get_current_activity() + if host is not None: + host.present() + else: + self._model.set_zoom_level(level) + self._screen.toggle_showing_desktop(True) + + def toggle_activity_fullscreen(self): + if self._model.get_zoom_level() == shellmodel.ShellModel.ZOOM_ACTIVITY: + self.get_current_activity().toggle_fullscreen() + + def activate_previous_activity(self): + home_model = self._model.get_home() + previous_activity = home_model.get_previous_activity() + if previous_activity: + previous_activity.get_window().activate( + gtk.get_current_event_time()) + + def activate_next_activity(self): + home_model = self._model.get_home() + next_activity = home_model.get_next_activity() + if next_activity: + next_activity.get_window().activate(gtk.get_current_event_time()) + + def close_current_activity(self): + if self._model.get_zoom_level() != shellmodel.ShellModel.ZOOM_ACTIVITY: + return + + home_model = self._model.get_home() + active_activity = home_model.get_active_activity() + if active_activity.is_journal(): + return + + self.get_current_activity().close() + + def get_current_activity(self): + home_model = self._model.get_home() + active_activity = home_model.get_active_activity() + return self._get_host_from_activity_model(active_activity) + + def get_activity(self, activity_id): + for host in self._hosts.values(): + if host.get_id() == activity_id: + return host + return None + + def take_screenshot(self): + file_path = os.path.join(tempfile.gettempdir(), '%i' % time.time()) + + window = gtk.gdk.get_default_root_window() + width, height = window.get_size() + x_orig, y_orig = window.get_origin() + + screenshot = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, has_alpha=False, + bits_per_sample=8, width=width, + height=height) + screenshot.get_from_drawable(window, window.get_colormap(), x_orig, + y_orig, 0, 0, width, height) + screenshot.save(file_path, "png") + try: + jobject = datastore.create() + try: + jobject.metadata['title'] = _('Screenshot') + jobject.metadata['keep'] = '0' + jobject.metadata['buddies'] = '' + jobject.metadata['preview'] = '' + jobject.metadata['icon-color'] = profile.get_color().to_string() + jobject.metadata['mime_type'] = 'image/png' + jobject.file_path = file_path + datastore.write(jobject) + finally: + jobject.destroy() + del jobject + finally: + os.remove(file_path) + +_instance = None + +def get_instance(): + global _instance + if not _instance: + _instance = Shell() + return _instance + diff --git a/src/jarabe/controlpanel/__init__.py b/src/view/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/view/__init__.py diff --git a/src/jarabe/frame/clipboardicon.py b/src/view/clipboardicon.py index ff63ad9..bd99b3a 100644 --- a/src/jarabe/frame/clipboardicon.py +++ b/src/view/clipboardicon.py @@ -16,76 +16,83 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import logging -import gconf - import gtk from sugar.graphics.radiotoolbutton import RadioToolButton from sugar.graphics.icon import Icon from sugar.graphics.xocolor import XoColor -from sugar.graphics import style +from sugar.clipboard import clipboardservice +from sugar.bundle.activitybundle import ActivityBundle +from sugar import profile -from jarabe.frame import clipboard -from jarabe.frame.clipboardmenu import ClipboardMenu -from jarabe.frame.frameinvoker import FrameWidgetInvoker -from jarabe.frame.notification import NotificationIcon -import jarabe.frame +from view.clipboardmenu import ClipboardMenu +from view.frame.frameinvoker import FrameWidgetInvoker +from view.frame.notification import NotificationIcon +import view.frame.frame class ClipboardIcon(RadioToolButton): __gtype_name__ = 'SugarClipboardIcon' - def __init__(self, cb_object, group): + def __init__(self, object_id, name, group): RadioToolButton.__init__(self, group=group) - - self.props.palette_invoker = FrameWidgetInvoker(self) - - self._cb_object = cb_object + self._object_id = object_id + self._name = name + self._percent = 0 + self._preview = None + self._activity = None self.owns_clipboard = False self.props.sensitive = False self.props.active = False self._notif_icon = None - self._current_percent = None self._icon = Icon() - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - self._icon.props.xo_color = color + self._icon.props.xo_color = profile.get_color() self.set_icon_widget(self._icon) self._icon.show() - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() cb_service.connect('object-state-changed', self._object_state_changed_cb) + obj = cb_service.get_object(self._object_id) + + self.palette = ClipboardMenu(self._object_id, self._name, self._percent, + self._preview, self._activity, + self._is_bundle(obj['FORMATS'])) + self.palette.props.invoker = FrameWidgetInvoker(self) child = self.get_child() child.connect('drag_data_get', self._drag_data_get_cb) self.connect('notify::active', self._notify_active_cb) - def create_palette(self): - palette = ClipboardMenu(self._cb_object) - palette.set_group_id('frame') - return palette + def _is_bundle(self, formats): + # A bundle will have only one format. + return formats and formats[0] in [ActivityBundle.MIME_TYPE, + ActivityBundle.DEPRECATED_MIME_TYPE] def get_object_id(self): - return self._cb_object.get_id() + return self._object_id - def _drag_data_get_cb(self, widget, context, selection, target_type, - event_time): + def _drag_data_get_cb(self, widget, context, selection, + targetType, eventTime): logging.debug('_drag_data_get_cb: requested target ' + selection.target) - data = self._cb_object.get_formats()[selection.target].get_data() + + cb_service = clipboardservice.get_instance() + data = cb_service.get_object_data(self._object_id, + selection.target)['DATA'] + selection.set(selection.target, 8, data) def _put_in_clipboard(self): logging.debug('ClipboardIcon._put_in_clipboard') - if self._cb_object.get_percent() < 100: + if self._percent < 100: raise ValueError('Object is not complete,' \ ' cannot be put into the clipboard.') targets = self._get_targets() if targets: - x_clipboard = gtk.Clipboard() - if not x_clipboard.set_with_data(targets, + clipboard = gtk.Clipboard() + if not clipboard.set_with_data(targets, self._clipboard_data_get_cb, self._clipboard_clear_cb, targets): @@ -93,38 +100,54 @@ class ClipboardIcon(RadioToolButton): else: self.owns_clipboard = True - def _clipboard_data_get_cb(self, x_clipboard, selection, info, targets): + def _clipboard_data_get_cb(self, clipboard, selection, info, targets): if not selection.target in [target[0] for target in targets]: logging.warning('ClipboardIcon._clipboard_data_get_cb: asked %s' \ ' but only have %r.' % (selection.target, targets)) return - data = self._cb_object.get_formats()[selection.target].get_data() + cb_service = clipboardservice.get_instance() + data = cb_service.get_object_data(self._object_id, + selection.target)['DATA'] + selection.set(selection.target, 8, data) - def _clipboard_clear_cb(self, x_clipboard, targets): + def _clipboard_clear_cb(self, clipboard, targets): logging.debug('ClipboardIcon._clipboard_clear_cb') self.owns_clipboard = False - def _object_state_changed_cb(self, cb_service, cb_object): - if cb_object != self._cb_object: + def _object_state_changed_cb(self, cb_service, object_id, name, percent, + icon_name, preview, activity): + + if object_id != self._object_id: return - if cb_object.get_icon(): - self._icon.props.icon_name = cb_object.get_icon() + cb_service = clipboardservice.get_instance() + obj = cb_service.get_object(self._object_id) + + if icon_name: + self._icon.props.icon_name = icon_name else: self._icon.props.icon_name = 'application-octet-stream' child = self.get_child() - child.connect('drag-begin', self._drag_begin_cb) child.drag_source_set(gtk.gdk.BUTTON1_MASK, self._get_targets(), gtk.gdk.ACTION_COPY) + child.drag_source_set_icon_name(self._icon.props.icon_name) + + self._name = name + self._preview = preview + self._activity = activity + self.palette.set_state(name, percent, preview, activity, + self._is_bundle(obj['FORMATS'])) - if cb_object.get_percent() == 100: + old_percent = self._percent + self._percent = percent + if self._percent == 100: self.props.sensitive = True # Clipboard object became complete. Make it the active one. - if self._current_percent < 100 and cb_object.get_percent() == 100: + if old_percent < 100 and self._percent == 100: self.props.active = True self._notif_icon = NotificationIcon() @@ -132,18 +155,9 @@ class ClipboardIcon(RadioToolButton): self._notif_icon.props.xo_color = \ XoColor('%s,%s' % (self._icon.props.stroke_color, self._icon.props.fill_color)) - frame = jarabe.frame.get_view() + frame = view.frame.frame.get_instance() frame.add_notification(self._notif_icon, - gtk.CORNER_BOTTOM_LEFT) - self._current_percent = cb_object.get_percent() - - def _drag_begin_cb(self, widget, context): - # TODO: We should get the pixbuf from the icon, with colors, etc. - icon_theme = gtk.icon_theme_get_default() - pixbuf = icon_theme.load_icon(self._icon.props.icon_name, - style.STANDARD_ICON_SIZE, 0) - context.set_icon_pixbuf(pixbuf, hot_x=pixbuf.props.width / 2, - hot_y=pixbuf.props.height / 2) + view.frame.frame.BOTTOM_LEFT) def _notify_active_cb(self, widget, pspec): if self.props.active: @@ -152,7 +166,14 @@ class ClipboardIcon(RadioToolButton): self.owns_clipboard = False def _get_targets(self): + cb_service = clipboardservice.get_instance() + + attrs = cb_service.get_object(self._object_id) + format_types = attrs[clipboardservice.FORMATS_KEY] + targets = [] - for format_type in self._cb_object.get_formats().keys(): + for format_type in format_types: targets.append((format_type, 0, 0)) + return targets + diff --git a/src/jarabe/frame/clipboardmenu.py b/src/view/clipboardmenu.py index 0a5e615..3ffe111 100644 --- a/src/jarabe/frame/clipboardmenu.py +++ b/src/view/clipboardmenu.py @@ -19,34 +19,30 @@ import tempfile import urlparse import os import logging -import gconf import gtk from sugar.graphics.palette import Palette from sugar.graphics.menuitem import MenuItem from sugar.graphics.icon import Icon -from sugar.graphics.xocolor import XoColor +from sugar.clipboard import clipboardservice from sugar.datastore import datastore from sugar import mime - -from jarabe.frame import clipboard -from jarabe.journal import misc -from jarabe.model import bundleregistry +from sugar import profile +from sugar import activity class ClipboardMenu(Palette): - def __init__(self, cb_object): - Palette.__init__(self, text_maxlen=100) + def __init__(self, object_id, name, percent, preview, + activities, installable): + Palette.__init__(self, name) - self._cb_object = cb_object + self._object_id = object_id + self._percent = percent + self._activities = activities self.set_group_id('frame') - cb_service = clipboard.get_instance() - cb_service.connect('object-state-changed', - self._object_state_changed_cb) - self._progress_bar = None self._remove_item = MenuItem(_('Remove'), 'list-remove') @@ -59,24 +55,27 @@ class ClipboardMenu(Palette): self.menu.append(self._open_item) self._open_item.show() + #self._stop_item = MenuItem(_('Stop download'), 'stock-close') + # TODO: Implement stopping downloads + #self._stop_item.connect('activate', self._stop_item_activate_cb) + #self.append_menu_item(self._stop_item) + self._journal_item = MenuItem(_('Keep')) - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - icon = Icon(icon_name='document-save', icon_size=gtk.ICON_SIZE_MENU, - xo_color=color) + icon = Icon(icon_name='document-save', icon_size=gtk.ICON_SIZE_MENU, + xo_color=profile.get_color()) self._journal_item.set_image(icon) self._journal_item.connect('activate', self._journal_item_activate_cb) self.menu.append(self._journal_item) self._journal_item.show() - self._update() + self._update_items_visibility(installable) + self._update_open_submenu() def _update_open_submenu(self): - activities = self._get_activities() - logging.debug('_update_open_submenu: %r' % activities) + logging.debug('_update_open_submenu: %r' % self._activities) child = self._open_item.get_child() - if activities is None or len(activities) <= 1: + if self._activities is None or len(self._activities) <= 1: child.set_text(_('Open')) if self._open_item.get_submenu() is not None: self._open_item.remove_submenu() @@ -92,54 +91,42 @@ class ClipboardMenu(Palette): for item in submenu.get_children(): submenu.remove(item) - for service_name in activities: - registry = bundleregistry.get_registry() - activity_info = registry.get_bundle(service_name) + for service_name in self._activities: + registry = activity.get_registry() + activity_info = registry.get_activity(service_name) if not activity_info: logging.warning('Activity %s is unknown.' % service_name) - item = gtk.MenuItem(activity_info.get_name()) + item = gtk.MenuItem(activity_info.name) item.connect('activate', self._open_submenu_item_activate_cb, service_name) submenu.append(item) item.show() - def _update_items_visibility(self): - activities = self._get_activities() - installable = self._cb_object.is_bundle() - percent = self._cb_object.get_percent() - - if percent == 100 and (activities or installable): + def _update_items_visibility(self, installable): + if self._percent == 100 and (self._activities or installable): self._remove_item.props.sensitive = True self._open_item.props.sensitive = True + #self._stop_item.props.sensitive = False self._journal_item.props.sensitive = True - elif percent == 100 and (not activities and not installable): + elif self._percent == 100 and \ + (not self._activities and not installable): self._remove_item.props.sensitive = True self._open_item.props.sensitive = False + #self._stop_item.props.sensitive = False self._journal_item.props.sensitive = True else: self._remove_item.props.sensitive = True self._open_item.props.sensitive = False + # TODO: reenable the stop item when we implement stoping downloads. + #self._stop_item.props.sensitive = True self._journal_item.props.sensitive = False self._update_progress_bar() - def _get_activities(self): - mime_type = self._cb_object.get_mime_type() - if not mime_type: - return '' - - registry = bundleregistry.get_registry() - activities = registry.get_activities_for_type(mime_type) - if activities: - return [info.get_bundle_id() for info in activities] - else: - return '' - def _update_progress_bar(self): - percent = self._cb_object.get_percent() - if percent == 100.0: + if self._percent == 100.0: if self._progress_bar: self._progress_bar = None self.set_content(None) @@ -149,44 +136,36 @@ class ClipboardMenu(Palette): self._progress_bar.show() self.set_content(self._progress_bar) - self._progress_bar.props.fraction = percent / 100.0 - self._progress_bar.props.text = '%.2f %%' % percent - - def _object_state_changed_cb(self, cb_service, cb_object): - if cb_object != self._cb_object: - return - self._update() + self._progress_bar.props.fraction = self._percent / 100.0 + self._progress_bar.props.text = '%.2f %%' % self._percent - def _update(self): - self.props.primary_text = self._cb_object.get_name() - preview = self._cb_object.get_preview() - if preview: - self.props.secondary_text = preview + def set_state(self, name, percent, preview, activities, installable): + self.set_primary_text(name) + self._percent = percent + self._activities = activities self._update_progress_bar() - self._update_items_visibility() + self._update_items_visibility(installable) self._update_open_submenu() def _open_item_activate_cb(self, menu_item): logging.debug('_open_item_activate_cb') - percent = self._cb_object.get_percent() - if percent < 100 or menu_item.get_submenu() is not None: + if self._percent < 100 or menu_item.get_submenu() is not None: return jobject = self._copy_to_journal() - misc.resume(jobject, self._activities[0]) + jobject.resume(self._activities[0]) jobject.destroy() def _open_submenu_item_activate_cb(self, menu_item, service_name): logging.debug('_open_submenu_item_activate_cb') - percent = self._cb_object.get_percent() - if percent < 100: + if self._percent < 100: return jobject = self._copy_to_journal() - misc.resume(jobject, service_name) + jobject.resume(service_name) jobject.destroy() def _remove_item_activate_cb(self, menu_item): - cb_service = clipboard.get_instance() - cb_service.delete_object(self._cb_object.get_id()) + cb_service = clipboardservice.get_instance() + cb_service.delete_object(self._object_id) def _journal_item_activate_cb(self, menu_item): logging.debug('_journal_item_activate_cb') @@ -202,46 +181,46 @@ class ClipboardMenu(Palette): return file_path def _copy_to_journal(self): - formats = self._cb_object.get_formats().keys() - most_significant_mime_type = mime.choose_most_significant(formats) - format = self._cb_object.get_formats()[most_significant_mime_type] + cb_service = clipboardservice.get_instance() + obj = cb_service.get_object(self._object_id) + + format = mime.choose_most_significant(obj['FORMATS']) + data = cb_service.get_object_data(self._object_id, format) transfer_ownership = False - if most_significant_mime_type == 'text/uri-list': - uris = mime.split_uri_list(format.get_data()) + if format == 'text/uri-list': + uris = mime.split_uri_list(data['DATA']) if len(uris) == 1 and uris[0].startswith('file://'): file_path = urlparse.urlparse(uris[0]).path transfer_ownership = False mime_type = mime.get_for_file(file_path) else: - file_path = self._write_to_temp_file(format.get_data()) + file_path = self._write_to_temp_file(data['DATA']) transfer_ownership = True mime_type = 'text/uri-list' else: - if format.is_on_disk(): - file_path = urlparse.urlparse(format.get_data()).path + if data['ON_DISK']: + file_path = urlparse.urlparse(data['DATA']).path transfer_ownership = False mime_type = mime.get_for_file(file_path) else: - file_path = self._write_to_temp_file(format.get_data()) + file_path = self._write_to_temp_file(data['DATA']) transfer_ownership = True sniffed_mime_type = mime.get_for_file(file_path) if sniffed_mime_type == 'application/octet-stream': - mime_type = most_significant_mime_type + mime_type = format else: mime_type = sniffed_mime_type - name = self._cb_object.get_name() jobject = datastore.create() - jobject.metadata['title'] = _('%s clipping') % name + jobject.metadata['title'] = _('Clipboard object: %s.') % obj['NAME'] jobject.metadata['keep'] = '0' jobject.metadata['buddies'] = '' jobject.metadata['preview'] = '' - client = gconf.client_get_default() - color = client.get_string('/desktop/sugar/user/color') - jobject.metadata['icon-color'] = color + jobject.metadata['icon-color'] = profile.get_color().to_string() jobject.metadata['mime_type'] = mime_type jobject.file_path = file_path datastore.write(jobject, transfer_ownership=transfer_ownership) return jobject + diff --git a/src/view/devices/Makefile.am b/src/view/devices/Makefile.am new file mode 100644 index 0000000..2b19443 --- /dev/null +++ b/src/view/devices/Makefile.am @@ -0,0 +1,9 @@ +SUBDIRS = network + +sugardir = $(pkgdatadir)/shell/view/devices +sugar_PYTHON = \ + __init__.py \ + battery.py \ + deviceview.py \ + speaker.py + diff --git a/extensions/Makefile.in b/src/view/devices/Makefile.in index 114900c..718b268 100644 --- a/extensions/Makefile.in +++ b/src/view/devices/Makefile.in @@ -29,8 +29,9 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = extensions -DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +subdir = src/view/devices +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ + $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -46,6 +47,15 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(sugardir)" +sugarPYTHON_INSTALL = $(INSTALL_DATA) +py_compile = $(top_srcdir)/py-compile RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive ETAGS = etags @@ -75,9 +85,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -194,7 +201,14 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = cpsection deviceicon globalkey +SUBDIRS = network +sugardir = $(pkgdatadir)/shell/view/devices +sugar_PYTHON = \ + __init__.py \ + battery.py \ + deviceview.py \ + speaker.py + all: all-recursive .SUFFIXES: @@ -207,9 +221,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/view/devices/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/Makefile + $(AUTOMAKE) --foreign src/view/devices/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ @@ -227,6 +241,34 @@ $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-sugarPYTHON: $(sugar_PYTHON) + @$(NORMAL_INSTALL) + test -z "$(sugardir)" || $(MKDIR_P) "$(DESTDIR)$(sugardir)" + @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ + if test -f "$$p"; then b=; else b="$(srcdir)/"; fi; \ + if test -f $$b$$p; then \ + f=$(am__strip_dir) \ + dlist="$$dlist $$f"; \ + echo " $(sugarPYTHON_INSTALL) '$$b$$p' '$(DESTDIR)$(sugardir)/$$f'"; \ + $(sugarPYTHON_INSTALL) "$$b$$p" "$(DESTDIR)$(sugardir)/$$f"; \ + else :; fi; \ + done; \ + if test -n "$$dlist"; then \ + if test -z "$(DESTDIR)"; then \ + PYTHON=$(PYTHON) $(py_compile) --basedir "$(sugardir)" $$dlist; \ + else \ + PYTHON=$(PYTHON) $(py_compile) --destdir "$(DESTDIR)" --basedir "$(sugardir)" $$dlist; \ + fi; \ + else :; fi + +uninstall-sugarPYTHON: + @$(NORMAL_UNINSTALL) + @list='$(sugar_PYTHON)'; dlist=''; for p in $$list; do\ + f=$(am__strip_dir) \ + rm -f "$(DESTDIR)$(sugardir)/$$f"; \ + rm -f "$(DESTDIR)$(sugardir)/$${f}c"; \ + rm -f "$(DESTDIR)$(sugardir)/$${f}o"; \ + done # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -406,6 +448,9 @@ check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: + for dir in "$(DESTDIR)$(sugardir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive @@ -448,7 +493,7 @@ info: info-recursive info-am: -install-data-am: +install-data-am: install-sugarPYTHON install-dvi: install-dvi-recursive @@ -482,7 +527,7 @@ ps: ps-recursive ps-am: -uninstall-am: +uninstall-am: uninstall-sugarPYTHON .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) install-am \ install-strip @@ -495,10 +540,11 @@ uninstall-am: install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - installdirs-am maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \ - tags-recursive uninstall uninstall-am + install-strip install-sugarPYTHON installcheck installcheck-am \ + installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \ + uninstall-sugarPYTHON # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/src/jarabe/controlpanel/__init__.py b/src/view/devices/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/view/devices/__init__.py diff --git a/src/view/devices/battery.py b/src/view/devices/battery.py new file mode 100644 index 0000000..07fe09b --- /dev/null +++ b/src/view/devices/battery.py @@ -0,0 +1,130 @@ +# Copyright (C) 2006-2007, Red Hat, Inc. +# +# 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 gettext import gettext as _ + +import gtk + +from sugar import profile +from sugar.graphics import style +from sugar.graphics.icon import get_icon_state +from sugar.graphics.tray import TrayIcon +from sugar.graphics.palette import Palette +from sugar.graphics.xocolor import XoColor + +from view.frame.frameinvoker import FrameWidgetInvoker + +_ICON_NAME = 'battery' + +_STATUS_CHARGING = 0 +_STATUS_DISCHARGING = 1 +_STATUS_FULLY_CHARGED = 2 + +class DeviceView(TrayIcon): + + FRAME_POSITION_RELATIVE = 1000 + + def __init__(self, model): + TrayIcon.__init__(self, icon_name=_ICON_NAME, + xo_color=profile.get_color()) + + self._model = model + self.palette = BatteryPalette(_('My Battery')) + self.set_palette(self.palette) + self.palette.props.invoker = FrameWidgetInvoker(self) + self.palette.set_group_id('frame') + + model.connect('notify::level', self._battery_status_changed_cb) + model.connect('notify::charging', self._battery_status_changed_cb) + model.connect('notify::discharging', self._battery_status_changed_cb) + self._update_info() + + def _update_info(self): + name = _ICON_NAME + current_level = self._model.props.level + xo_color = profile.get_color() + badge_name = None + + if self._model.props.charging: + status = _STATUS_CHARGING + name += '-charging' + xo_color = XoColor('%s,%s' % (style.COLOR_WHITE.get_svg(), + style.COLOR_WHITE.get_svg())) + elif self._model.props.discharging: + status = _STATUS_DISCHARGING + if current_level <= 15: + badge_name = 'emblem-warning' + else: + status = _STATUS_FULLY_CHARGED + + self.icon.props.icon_name = get_icon_state(name, current_level, step=-5) + self.icon.props.xo_color = xo_color + self.icon.props.badge_name = badge_name + + self.palette.set_level(current_level) + self.palette.set_status(status) + + def _battery_status_changed_cb(self, pspec, param): + self._update_info() + +class BatteryPalette(Palette): + + def __init__(self, primary_text): + Palette.__init__(self, primary_text) + + self._level = 0 + self._progress_bar = gtk.ProgressBar() + self._progress_bar.set_size_request( + style.zoom(style.GRID_CELL_SIZE * 4), -1) + self._progress_bar.show() + self._status_label = gtk.Label() + self._status_label.show() + + vbox = gtk.VBox() + vbox.pack_start(self._progress_bar) + vbox.pack_start(self._status_label) + vbox.show() + + self.set_content(vbox) + + def set_level(self, percent): + self._level = percent + fraction = percent / 100.0 + self._progress_bar.set_fraction(fraction) + + def set_status(self, status): + current_level = self._level + secondary_text = '' + status_text = '%s%%' % current_level + + if status == _STATUS_CHARGING: + secondary_text = _('Charging') + elif status == _STATUS_DISCHARGING: + if current_level <= 15: + secondary_text = _('Very little power remaining') + else: + #TODO: make this less of an wild/educated guess + minutes_remaining = int(current_level / 0.59) + remaining_hourpart = minutes_remaining / 60 + remaining_minpart = minutes_remaining % 60 + secondary_text = _('%(hour)d:%(min).2d remaining' + % { 'hour': remaining_hourpart, + 'min': remaining_minpart}) + else: + secondary_text = _('Charged') + + self.props.secondary_text = secondary_text + self._status_label.set_text(status_text) diff --git a/extensions/cpsection/network/__init__.py b/src/view/devices/deviceview.py index 8fea274..90ebbf5 100644 --- a/extensions/cpsection/network/__init__.py +++ b/src/view/devices/deviceview.py @@ -14,12 +14,13 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from gettext import gettext as _ - -CLASS = 'Network' -ICON = 'module-network' -TITLE = _('Network') -KEYWORDS = ['network', 'jabber', 'radio', 'server'] +def create(model): + name = 'view.devices.' + model.get_type() + mod = __import__(name) + components = name.split('.') + for comp in components[1:]: + mod = getattr(mod, comp) + return mod.DeviceView(model) diff --git a/src/view/devices/network/Makefile.am b/src/view/devices/network/Makefile.am new file mode 100644 index 0000000..0d215f0 --- /dev/null +++ b/src/view/devices/network/Makefile.am @@ -0,0 +1,6 @@ +sugardir = $(pkgdatadir)/shell/view/devices/network +sugar_PYTHON = \ + __init__.py \ + mesh.py \ + wired.py \ + wireless.py diff --git a/extensions/cpsection/frame/Makefile.in b/src/view/devices/network/Makefile.in index 56ff3ad..388045d 100644 --- a/extensions/cpsection/frame/Makefile.in +++ b/src/view/devices/network/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = extensions/cpsection/frame +subdir = src/view/devices/network DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,11 +189,12 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/frame +sugardir = $(pkgdatadir)/shell/view/devices/network sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py + __init__.py \ + mesh.py \ + wired.py \ + wireless.py all: all-am @@ -210,9 +208,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/frame/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/view/devices/network/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/frame/Makefile + $(AUTOMAKE) --foreign src/view/devices/network/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/jarabe/controlpanel/__init__.py b/src/view/devices/network/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/view/devices/network/__init__.py diff --git a/src/view/devices/network/mesh.py b/src/view/devices/network/mesh.py new file mode 100644 index 0000000..40746ce --- /dev/null +++ b/src/view/devices/network/mesh.py @@ -0,0 +1,174 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# 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 gettext import gettext as _ + +import gtk + +from sugar import profile +from sugar.graphics import style +from sugar.graphics.palette import Palette +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.xocolor import XoColor + +from model.devices import device +from model.devices.network import wireless +from hardware import hardwaremanager +from view.devices.network.wireless import IP_ADDRESS_TEXT_TEMPLATE +from view.frame.frameinvoker import FrameWidgetInvoker +from view.pulsingicon import PulsingIcon + +class DeviceView(ToolButton): + + FRAME_POSITION_RELATIVE = 400 + + def __init__(self, model): + ToolButton.__init__(self) + + self._model = model + + self._icon = PulsingIcon() + self._icon.props.icon_name = 'network-mesh' + pulse_color = XoColor("%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), + style.COLOR_TRANSPARENT.get_svg())) + self._icon.props.pulse_color = pulse_color + self._icon.props.base_color = pulse_color # only temporarily + + self.palette = MeshPalette(_("Mesh Network"), model) + self.set_palette(self.palette) + self.palette.props.invoker = FrameWidgetInvoker(self) + self.palette.set_group_id('frame') + + model.connect('notify::state', self._state_changed_cb) + model.connect('notify::activation-stage', self._state_changed_cb) + model.connect('notify::ip-address', self._ip_address_changed_cb) + + self._update_state() + self._update_ip_address() + self.set_icon_widget(self._icon) + self._icon.show() + + def _ip_address_changed_cb(self, model, pspec): + self._update_ip_address() + + def _state_changed_cb(self, model, pspec): + self._update_state() + + def _update_ip_address(self): + self.palette.set_ip_address(self._model.props.ip_address) + + def _update_state(self): + # FIXME Change icon colors once we have real icons + state = self._model.props.state + self.palette.update_state(state) + + self._icon.props.pulsing = state == device.STATE_ACTIVATING + if state == device.STATE_ACTIVATING: + self._icon.props.base_color = \ + XoColor("%s,%s" % (style.COLOR_INACTIVE_STROKE.get_svg(), + style.COLOR_INACTIVE_FILL.get_svg())) + elif state == device.STATE_ACTIVATED: + self._icon.props.base_color = profile.get_color() + elif state == device.STATE_INACTIVE: + self._icon.props.base_color = \ + XoColor("%s,%s" % (style.COLOR_INACTIVE_STROKE.get_svg(), + style.COLOR_INACTIVE_FILL.get_svg())) + + if state == device.STATE_INACTIVE: + self.palette.set_primary_text(_("Mesh Network")) + else: + chan = wireless.freq_to_channel(self._model.props.frequency) + if chan > 0: + self.palette.set_primary_text(_("Mesh Network") + " %d" % chan) + self.palette.set_mesh_step(self._model.props.mesh_step, state) + +class MeshPalette(Palette): + def __init__(self, primary_text, model): + Palette.__init__(self, primary_text, menu_after_content=True) + self._model = model + + self._step_label = gtk.Label() + self._step_label.show() + + self._ip_address_label = gtk.Label() + def _padded(child, xalign=0, yalign=0.5): + padder = gtk.Alignment(xalign=xalign, yalign=yalign, + xscale=1, yscale=0.33) + padder.set_padding(style.DEFAULT_SPACING, + style.DEFAULT_SPACING, + style.DEFAULT_SPACING, + style.DEFAULT_SPACING) + padder.add(child) + return padder + + vbox = gtk.VBox() + vbox.pack_start(_padded(self._step_label)) + vbox.pack_start(_padded(self._ip_address_label)) + vbox.show_all() + + self.set_content(vbox) + + self._disconnect_item = gtk.MenuItem(_('Disconnect...')) + self._disconnect_item.connect('activate', self._disconnect_activate_cb) + self.menu.append(self._disconnect_item) + + def update_state(self, state): + if state == device.STATE_ACTIVATED: + self._disconnect_item.show() + else: + self._disconnect_item.hide() + + def _disconnect_activate_cb(self, menuitem): + # Disconnection for an mesh means activating the default mesh device + # again without a channel + network_manager = hardwaremanager.get_network_manager() + nm_device = self._model.get_nm_device() + if network_manager and nm_device: + network_manager.set_active_device(nm_device) + + def set_ip_address(self, ip_address): + if ip_address is not None and ip_address != "0.0.0.0": + ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % ip_address + else: + ip_address_text = "" + self._ip_address_label.set_text(ip_address_text) + + def set_mesh_step(self, step, state): + label = "" + if step == 1: + if state == device.STATE_ACTIVATED: + label = _("Connected to a School Mesh Portal") + elif state == device.STATE_ACTIVATING: + label = _("Looking for a School Mesh Portal...") + elif step == 3: + if state == device.STATE_ACTIVATED: + label = _("Connected to an XO Mesh Portal") + elif state == device.STATE_ACTIVATING: + label = _("Looking for an XO Mesh Portal...") + elif step == 4: + if state == device.STATE_ACTIVATED: + label = _("Connected to a Simple Mesh") + elif state == device.STATE_ACTIVATING: + label = _("Starting a Simple Mesh") + + if len(label): + self._step_label.set_text(label) + else: + import logging + logging.debug("Unhandled mesh step %d" % step) + self._step_label.set_text(_("Unknown Mesh")) + diff --git a/extensions/cpsection/network/__init__.py b/src/view/devices/network/wired.py index 8fea274..6843e0d 100644 --- a/extensions/cpsection/network/__init__.py +++ b/src/view/devices/network/wired.py @@ -14,12 +14,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -from gettext import gettext as _ - -CLASS = 'Network' -ICON = 'module-network' -TITLE = _('Network') -KEYWORDS = ['network', 'jabber', 'radio', 'server'] +from view.devices import deviceview +class DeviceView(deviceview.DeviceView): + FRAME_POSITION_RELATIVE = 300 + def __init__(self, model): + deviceview.DeviceView.__init__(self, model) + self.props.icon_name = 'network-wired' diff --git a/src/view/devices/network/wireless.py b/src/view/devices/network/wireless.py new file mode 100644 index 0000000..5bef0bb --- /dev/null +++ b/src/view/devices/network/wireless.py @@ -0,0 +1,191 @@ +# +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 gettext import gettext as _ + +import gtk + +from sugar.graphics.icon import get_icon_state +from sugar.graphics import style +from sugar.graphics.palette import Palette +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.xocolor import XoColor + +from model.devices.network import wireless +from model.devices import device +from hardware import hardwaremanager +from hardware import nmclient +from view.frame.frameinvoker import FrameWidgetInvoker +from view.pulsingicon import PulsingIcon + +_ICON_NAME = 'network-wireless' + +IP_ADDRESS_TEXT_TEMPLATE = _("IP address: %s") + +class DeviceView(ToolButton): + + FRAME_POSITION_RELATIVE = 300 + + def __init__(self, model): + ToolButton.__init__(self) + self._model = model + + self._icon = PulsingIcon() + self._icon.props.icon_name = _ICON_NAME + pulse_color = XoColor("%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(), + style.COLOR_TRANSPARENT.get_svg())) + self._icon.props.pulse_color = pulse_color + self._icon.props.base_color = pulse_color # only temporarily + self._inactive_color = XoColor("%s,%s" % ( + style.COLOR_INACTIVE_STROKE.get_html(), + style.COLOR_INACTIVE_FILL.get_html())) + + meshdev = None + network_manager = hardwaremanager.get_network_manager() + for dev in network_manager.get_devices(): + if dev.get_type() == nmclient.DEVICE_TYPE_802_11_MESH_OLPC: + meshdev = dev + break + + self._counter = 0 + self.palette = WirelessPalette(self._get_palette_primary_text(), + meshdev) + self.set_palette(self.palette) + self.palette.props.invoker = FrameWidgetInvoker(self) + self.palette.set_group_id('frame') + self.palette.set_frequency(self._model.props.frequency) + + model.connect('notify::name', self._name_changed_cb) + model.connect('notify::ip-address', self._ip_address_changed_cb) + model.connect('notify::strength', self._strength_changed_cb) + model.connect('notify::state', self._state_changed_cb) + + self._update_icon() + self._update_state() + self._update_ip_address() + + self.set_icon_widget(self._icon) + self._icon.show() + + def _get_palette_primary_text(self): + if self._model.props.state == device.STATE_INACTIVE: + return _("Disconnected") + return self._model.props.name + + def _strength_changed_cb(self, model, pspec): + self._update_icon() + # Only update frequency periodically + if self._counter % 4 == 0: + self.palette.set_frequency(self._model.props.frequency) + self._counter += 1 + + def _ip_address_changed_cb(self, model, pspec): + self._update_ip_address() + + def _name_changed_cb(self, model, pspec): + self.palette.set_primary_text(self._get_palette_primary_text()) + self._update_state() + + def _state_changed_cb(self, model, pspec): + self._update_icon() + self._update_state() + self.palette.set_primary_text(self._get_palette_primary_text()) + + def _update_icon(self): + # keep this code in sync with view/home/MeshBox.py + strength = self._model.props.strength + if self._model.props.state == device.STATE_INACTIVE: + strength = 0 + if self._model.props.state == device.STATE_ACTIVATED: + icon_name = '%s-connected' % _ICON_NAME + else: + icon_name = _ICON_NAME + icon_name = get_icon_state(icon_name, strength) + if icon_name: + self._icon.props.icon_name = icon_name + + def _update_state(self): + # FIXME Change icon colors once we have real icons + state = self._model.props.state + self._icon.props.pulsing = state == device.STATE_ACTIVATING + if state == device.STATE_ACTIVATING: + fill = style.COLOR_INACTIVE_FILL.get_svg() + stroke = style.COLOR_INACTIVE_STROKE.get_svg() + elif state == device.STATE_ACTIVATED: + (stroke, fill) = self._model.get_active_network_colors() + elif state == device.STATE_INACTIVE: + fill = style.COLOR_INACTIVE_FILL.get_svg() + stroke = style.COLOR_INACTIVE_STROKE.get_svg() + self._icon.props.base_color = XoColor("%s,%s" % (stroke, fill)) + + def _update_ip_address(self): + self.palette.set_ip_address(self._model.props.ip_address) + +class WirelessPalette(Palette): + def __init__(self, primary_text, meshdev): + Palette.__init__(self, primary_text, menu_after_content=True) + self._meshdev = meshdev + + self._chan_label = gtk.Label() + self._chan_label.props.xalign = 0.0 + self._chan_label.show() + + self._ip_address_label = gtk.Label() + + vbox = gtk.VBox() + + def _padded(child, xalign=0, yalign=0.5): + padder = gtk.Alignment(xalign=xalign, yalign=yalign, + xscale=1, yscale=0.33) + padder.set_padding(style.DEFAULT_SPACING, + style.DEFAULT_SPACING, + style.DEFAULT_SPACING, + style.DEFAULT_SPACING) + padder.add(child) + return padder + + vbox.pack_start(_padded(self._chan_label)) + vbox.pack_start(_padded(self._ip_address_label)) + vbox.show_all() + + if meshdev: + disconnect_item = gtk.MenuItem(_('Disconnect...')) + disconnect_item.connect('activate', self._disconnect_activate_cb) + self.menu.append(disconnect_item) + disconnect_item.show() + + self.set_content(vbox) + + def _disconnect_activate_cb(self, menuitem): + # Disconnection for an AP means activating the default mesh device + network_manager = hardwaremanager.get_network_manager() + if network_manager and self._meshdev: + network_manager.set_active_device(self._meshdev) + + def set_frequency(self, freq): + try: + chan = wireless.freq_to_channel(freq) + except KeyError: + chan = 0 + self._chan_label.set_text("%s: %d" % (_("Channel"), chan)) + + def set_ip_address(self, ip_address): + if ip_address is not None and ip_address != "0.0.0.0": + ip_address_text = IP_ADDRESS_TEXT_TEMPLATE % ip_address + else: + ip_address_text = "" + self._ip_address_label.set_text(ip_address_text) diff --git a/extensions/deviceicon/speaker.py b/src/view/devices/speaker.py index 5497873..df4995c 100644 --- a/extensions/deviceicon/speaker.py +++ b/src/view/devices/speaker.py @@ -15,11 +15,11 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from gettext import gettext as _ -import gconf -import gobject import gtk +from hardware import hardwaremanager +from sugar import profile from sugar.graphics import style from sugar.graphics.icon import get_icon_state, Icon from sugar.graphics.menuitem import MenuItem @@ -27,8 +27,7 @@ from sugar.graphics.tray import TrayIcon from sugar.graphics.palette import Palette from sugar.graphics.xocolor import XoColor -from jarabe.frame.frameinvoker import FrameWidgetInvoker -from jarabe.model import sound +from view.frame.frameinvoker import FrameWidgetInvoker _ICON_NAME = 'speaker' @@ -36,31 +35,26 @@ class DeviceView(TrayIcon): FRAME_POSITION_RELATIVE = 800 - def __init__(self): - client = gconf.client_get_default() - self._color = XoColor(client.get_string('/desktop/sugar/user/color')) + def __init__(self, model): + TrayIcon.__init__(self, + icon_name=_ICON_NAME, + xo_color=profile.get_color()) - TrayIcon.__init__(self, icon_name=_ICON_NAME, xo_color=self._color) - - self._model = DeviceModel() - self.palette = SpeakerPalette(_('My Speakers'), model=self._model) + self._model = model + self.palette = SpeakerPalette(_('My Speakers'), model=model) self.palette.props.invoker = FrameWidgetInvoker(self) self.palette.set_group_id('frame') - self._model.connect('notify::level', self.__speaker_status_changed_cb) - self._model.connect('notify::muted', self.__speaker_status_changed_cb) - + model.connect('notify::level', self.__speaker_status_changed_cb) + model.connect('notify::muted', self.__speaker_status_changed_cb) self.connect('expose-event', self.__expose_event_cb) - self._icon_widget.connect('button-press-event', - self.__update_mute_status) - self._update_info() def _update_info(self): name = _ICON_NAME current_level = self._model.props.level - xo_color = self._color + xo_color = profile.get_color() if self._model.props.muted: name += '-muted' @@ -70,9 +64,6 @@ class DeviceView(TrayIcon): self.icon.props.icon_name = get_icon_state(name, current_level, step=-1) self.icon.props.xo_color = xo_color - def __update_mute_status(self, *args): - self._model.props.muted = not self._model.props.muted - def __expose_event_cb(self, *args): self._update_info() @@ -92,7 +83,7 @@ class SpeakerPalette(Palette): self.set_content(vbox) vbox.show() - vol_step = sound.VOLUME_STEP + vol_step = hardwaremanager.VOL_CHANGE_INCREMENT_RECOMMENDATION self._adjustment = gtk.Adjustment(value=self._model.props.level, lower=0, upper=100 + vol_step, @@ -161,51 +152,3 @@ class SpeakerPalette(Palette): def __popup_cb(self, palette_): self._update_level() self._update_muted() - -class DeviceModel(gobject.GObject): - __gproperties__ = { - 'level' : (int, None, None, 0, 100, 0, gobject.PARAM_READWRITE), - 'muted' : (bool, None, None, False, gobject.PARAM_READWRITE), - } - - def __init__(self): - gobject.GObject.__init__(self) - - sound.muted_changed.connect(self.__muted_changed_cb) - sound.volume_changed.connect(self.__volume_changed_cb) - - def __muted_changed_cb(self, **kwargs): - self.notify('muted') - - def __volume_changed_cb(self, **kwargs): - self.notify('level') - - def _get_level(self): - return sound.get_volume() - - def _set_level(self, new_volume): - sound.set_volume(new_volume) - - def _get_muted(self): - return sound.get_muted() - - def _set_muted(self, mute): - sound.set_muted(mute) - - def get_type(self): - return 'speaker' - - def do_get_property(self, pspec): - if pspec.name == "level": - return self._get_level() - elif pspec.name == "muted": - return self._get_muted() - - def do_set_property(self, pspec, value): - if pspec.name == "level": - self._set_level(value) - elif pspec.name == "muted": - self._set_muted(value) - -def setup(tray): - tray.add_device(DeviceView()) diff --git a/src/jarabe/frame/Makefile.am b/src/view/frame/Makefile.am index e5c445f..4d5b96b 100644 --- a/src/jarabe/frame/Makefile.am +++ b/src/view/frame/Makefile.am @@ -1,11 +1,7 @@ -sugardir = $(pythondir)/jarabe/frame +sugardir = $(pkgdatadir)/shell/view/frame sugar_PYTHON = \ __init__.py \ activitiestray.py \ - clipboard.py \ - clipboardicon.py \ - clipboardmenu.py \ - clipboardobject.py \ clipboardpanelwindow.py \ clipboardtray.py \ devicestray.py \ diff --git a/src/jarabe/frame/Makefile.in b/src/view/frame/Makefile.in index aa8e795..f0c7ddc 100644 --- a/src/jarabe/frame/Makefile.in +++ b/src/view/frame/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = src/jarabe/frame +subdir = src/view/frame DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,14 +189,10 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pythondir)/jarabe/frame +sugardir = $(pkgdatadir)/shell/view/frame sugar_PYTHON = \ __init__.py \ activitiestray.py \ - clipboard.py \ - clipboardicon.py \ - clipboardmenu.py \ - clipboardobject.py \ clipboardpanelwindow.py \ clipboardtray.py \ devicestray.py \ @@ -223,9 +216,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/jarabe/frame/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/view/frame/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign src/jarabe/frame/Makefile + $(AUTOMAKE) --foreign src/view/frame/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/jarabe/controlpanel/__init__.py b/src/view/frame/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/view/frame/__init__.py diff --git a/src/jarabe/frame/activitiestray.py b/src/view/frame/activitiestray.py index 8821236..1311f07 100644 --- a/src/jarabe/frame/activitiestray.py +++ b/src/view/frame/activitiestray.py @@ -17,8 +17,6 @@ import logging from gettext import gettext as _ -import gconf - import gtk from sugar.graphics import style @@ -29,25 +27,20 @@ from sugar.graphics.toolbutton import ToolButton from sugar.graphics.icon import Icon from sugar.graphics.palette import Palette, WidgetInvoker from sugar.graphics.menuitem import MenuItem -from sugar.activity.activityhandle import ActivityHandle -from sugar.activity import activityfactory - -from jarabe.model import shell -from jarabe.model import neighborhood -from jarabe.model import owner -from jarabe.model import bundleregistry -from jarabe.view.palettes import JournalPalette, CurrentActivityPalette -from jarabe.view.pulsingicon import PulsingIcon -from jarabe.frame.frameinvoker import FrameWidgetInvoker -from jarabe.frame.notification import NotificationIcon -import jarabe.frame +from sugar import activity +from sugar import profile + +from model import shellmodel +from view.palettes import JournalPalette, CurrentActivityPalette +from view.pulsingicon import PulsingIcon +from view.frame.frameinvoker import FrameWidgetInvoker +from view.frame.notification import NotificationIcon +import view.frame.frame class ActivityButton(RadioToolButton): def __init__(self, home_activity, group): RadioToolButton.__init__(self, group=group) - self.set_palette_invoker(FrameWidgetInvoker(self)) - self._home_activity = home_activity self._icon = PulsingIcon() @@ -62,6 +55,14 @@ class ActivityButton(RadioToolButton): self.set_icon_widget(self._icon) self._icon.show() + if self._home_activity.is_journal(): + palette = JournalPalette(self._home_activity) + else: + palette = CurrentActivityPalette(self._home_activity) + palette.props.invoker = FrameWidgetInvoker(self) + palette.set_group_id('frame') + self.set_palette(palette) + if home_activity.props.launching: self._icon.props.pulsing = True self._notify_launching_hid = home_activity.connect( \ @@ -70,14 +71,6 @@ class ActivityButton(RadioToolButton): self._notify_launching_hid = None self._notif_icon = None - def create_palette(self): - if self._home_activity.is_journal(): - palette = JournalPalette(self._home_activity) - else: - palette = CurrentActivityPalette(self._home_activity) - palette.set_group_id('frame') - self.set_palette(palette) - def __notify_launching_cb(self, home_activity, pspec): if not home_activity.props.launching: self._icon.props.pulsing = False @@ -100,7 +93,7 @@ class BaseInviteButton(ToolButton): def __clicked_cb(self, button): if self._notif_icon is not None: - frame = jarabe.frame.get_view() + frame = view.frame.frame.get_instance() frame.remove_notification(self._notif_icon) self._notif_icon = None self._launch() @@ -110,14 +103,14 @@ class BaseInviteButton(ToolButton): raise NotImplementedError def __destroy_cb(self, button): - frame = jarabe.frame.get_view() + frame = view.frame.frame.get_instance() frame.remove_notification(self._notif_icon) class ActivityInviteButton(BaseInviteButton): """Invite to shared activity""" def __init__(self, invite): BaseInviteButton.__init__(self, invite) - mesh = neighborhood.get_model() + mesh = shellmodel.get_instance().get_mesh() activity_model = mesh.get_activity(invite.get_activity_id()) self._activity_model = activity_model self._bundle_id = activity_model.get_bundle_id() @@ -147,17 +140,16 @@ class ActivityInviteButton(BaseInviteButton): palette.set_group_id('frame') self._notif_icon.palette = palette - frame = jarabe.frame.get_view() + frame = view.frame.frame.get_instance() frame.add_notification(self._notif_icon, - gtk.CORNER_TOP_LEFT) + view.frame.frame.TOP_LEFT) def _launch(self): """Join the activity in the invite.""" - registry = bundleregistry.get_registry() - bundle = registry.get_bundle(self._bundle_id) + shell = view.Shell.get_instance() + shell.join_activity(self._activity_model.get_bundle_id(), + self._activity_model.get_id()) - handle = ActivityHandle(self._activity_model.get_id()) - activityfactory.create(bundle, handle) class PrivateInviteButton(BaseInviteButton): """Invite to a private one to one channel""" @@ -166,15 +158,11 @@ class PrivateInviteButton(BaseInviteButton): self._private_channel = invite.get_private_channel() self._bundle_id = invite.get_bundle_id() - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - - self._icon.props.xo_color = color - registry = bundleregistry.get_registry() - self._bundle = registry.get_bundle(self._bundle_id) - - if self._bundle: - self._icon.props.file = self._bundle.get_icon() + self._icon.props.xo_color = profile.get_color() + registry = activity.get_registry() + activity_info = registry.get_activity(self._bundle_id) + if activity_info: + self._icon.props.file = activity_info.icon else: self._icon.props.icon_name = 'image-missing' self.set_icon_widget(self._icon) @@ -185,10 +173,11 @@ class PrivateInviteButton(BaseInviteButton): palette.set_group_id('frame') self.set_palette(palette) - self._notif_icon.props.xo_color = color - - if self._bundle: - self._notif_icon.props.icon_filename = self._bundle.get_icon() + self._notif_icon.props.xo_color = profile.get_color() + registry = activity.get_registry() + activity_info = registry.get_activity(self._bundle_id) + if activity_info: + self._notif_icon.props.icon_filename = activity_info.icon else: self._notif_icon.props.icon_name = 'image-missing' @@ -197,13 +186,16 @@ class PrivateInviteButton(BaseInviteButton): palette.set_group_id('frame') self._notif_icon.palette = palette - frame = jarabe.frame.get_view() + frame = view.frame.frame.get_instance() frame.add_notification(self._notif_icon, - gtk.CORNER_TOP_LEFT) + view.frame.frame.TOP_LEFT) def _launch(self): """Start the activity with private channel.""" - activityfactory.create_with_uri(self._bundle, self._private_channel) + shell = view.Shell.get_instance() + shell.start_activity_with_uri(self._bundle_id, + self._private_channel) + class BaseInvitePalette(Palette): """Palette for frame or notification icon for invites.""" @@ -239,24 +231,25 @@ class ActivityInvitePalette(BaseInvitePalette): def __init__(self, invite): BaseInvitePalette.__init__(self) - mesh = neighborhood.get_model() + mesh = shellmodel.get_instance().get_mesh() activity_model = mesh.get_activity(invite.get_activity_id()) self._activity_model = activity_model self._bundle_id = activity_model.get_bundle_id() - registry = bundleregistry.get_registry() - self._bundle = registry.get_bundle(self._bundle_id) - if self._bundle: - self.set_primary_text(self._bundle.get_name()) + registry = activity.get_registry() + activity_info = registry.get_activity(self._bundle_id) + if activity_info: + self.set_primary_text(activity_info.name) else: self.set_primary_text(self._bundle_id) def _join(self): - handle = ActivityHandle(self._activity_model.get_id()) - activityfactory.create(self._bundle, handle) + shell = view.Shell.get_instance() + shell.join_activity(self._activity_model.get_bundle_id(), + self._activity_model.get_id()) def _decline(self): - invites = owner.get_model().get_invites() + invites = shellmodel.get_instance().get_invites() activity_id = self._activity_model.get_id() invites.remove_activity(activity_id) @@ -270,21 +263,22 @@ class PrivateInvitePalette(BaseInvitePalette): self._private_channel = invite.get_private_channel() self._bundle_id = invite.get_bundle_id() - registry = bundleregistry.get_registry() - self._bundle = registry.get_bundle(self._bundle_id) - if self._bundle: - self.set_primary_text(self._bundle.get_name()) + registry = activity.get_registry() + activity_info = registry.get_activity(self._bundle_id) + if activity_info: + self.set_primary_text(activity_info.name) else: self.set_primary_text(self._bundle_id) def _join(self): - activityfactory.create_with_uri(self._bundle, self._private_channel) - - invites = owner.get_model().get_invites() + shell = view.Shell.get_instance() + shell.start_activity_with_uri(self._bundle_id, + self._private_channel) + invites = shellmodel.get_instance().get_invites() invites.remove_private_channel(self._private_channel) def _decline(self): - invites = owner.get_model().get_invites() + invites = shellmodel.get_instance().get_invites() invites.remove_private_channel(self._private_channel) @@ -296,7 +290,7 @@ class ActivitiesTray(HTray): self._invite_to_item = {} self._freeze_button_clicks = False - self._home_model = shell.get_model() + self._home_model = shellmodel.get_instance().get_home() self._home_model.connect('activity-added', self.__activity_added_cb) self._home_model.connect('activity-removed', self.__activity_removed_cb) self._home_model.connect('active-activity-changed', @@ -304,7 +298,7 @@ class ActivitiesTray(HTray): self._home_model.connect('tabbing-activity-changed', self.__tabbing_activity_changed_cb) - self._invites = owner.get_model().get_invites() + self._invites = shellmodel.get_instance().get_invites() for invite in self._invites: self._add_invite(invite) self._invites.connect('invite-added', self.__invite_added_cb) @@ -381,7 +375,7 @@ class ActivitiesTray(HTray): """Add an invite (SugarInvite or PrivateInvite)""" item = None if hasattr(invite, 'get_activity_id'): - mesh = neighborhood.get_model() + mesh = shellmodel.get_instance().get_mesh() activity_model = mesh.get_activity(invite.get_activity_id()) if activity_model is not None: item = ActivityInviteButton(invite) diff --git a/src/jarabe/frame/clipboardpanelwindow.py b/src/view/frame/clipboardpanelwindow.py index 7093199..10b234b 100644 --- a/src/jarabe/frame/clipboardpanelwindow.py +++ b/src/view/frame/clipboardpanelwindow.py @@ -20,10 +20,9 @@ from urlparse import urlparse import gtk import hippo -from jarabe.frame.framewindow import FrameWindow -from jarabe.frame.clipboardtray import ClipboardTray - -from jarabe.frame import clipboard +from view.frame.framewindow import FrameWindow +from view.frame.clipboardtray import ClipboardTray +from sugar.clipboard import clipboardservice class ClipboardPanelWindow(FrameWindow): def __init__(self, frame, orientation): @@ -44,27 +43,26 @@ class ClipboardPanelWindow(FrameWindow): # Receiving dnd drops self.drag_dest_set(0, [], 0) self.connect("drag_motion", self._clipboard_tray.drag_motion_cb) - self.connect("drag_leave", self._clipboard_tray.drag_leave_cb) self.connect("drag_drop", self._clipboard_tray.drag_drop_cb) self.connect("drag_data_received", self._clipboard_tray.drag_data_received_cb) - def _owner_change_cb(self, x_clipboard, event): + def _owner_change_cb(self, clipboard, event): logging.debug("owner_change_cb") if self._clipboard_tray.owns_clipboard(): return - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() key = cb_service.add_object(name="") cb_service.set_object_percent(key, percent=0) - targets = x_clipboard.wait_for_targets() + targets = clipboard.wait_for_targets() for target in targets: if target not in ('TIMESTAMP', 'TARGETS', 'MULTIPLE', 'SAVE_TARGETS'): logging.debug('Asking for target %s.' % target) - selection = x_clipboard.wait_for_contents(target) + selection = clipboard.wait_for_contents(target) if not selection: logging.warning('no data for selection target %s.' % target) continue @@ -79,7 +77,7 @@ class ClipboardPanelWindow(FrameWindow): logging.debug('adding type ' + selection.type + '.') - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() if selection.type == 'text/uri-list': uris = selection.get_uris() diff --git a/src/jarabe/frame/clipboardtray.py b/src/view/frame/clipboardtray.py index 40f0a32..b5ba093 100644 --- a/src/jarabe/frame/clipboardtray.py +++ b/src/view/frame/clipboardtray.py @@ -21,13 +21,13 @@ import tempfile import gtk from sugar import util +from sugar.clipboard import clipboardservice from sugar.graphics import tray from sugar.graphics import style -from jarabe.frame import clipboard -from jarabe.frame.clipboardicon import ClipboardIcon +from view.clipboardicon import ClipboardIcon -class _ContextMap(object): +class _ContextMap: """Maps a drag context to the clipboard object involved in the dragging.""" def __init__(self): self._context_map = {} @@ -65,7 +65,7 @@ class ClipboardTray(tray.VTray): self._icons = {} self._context_map = _ContextMap() - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() cb_service.connect('object-added', self._object_added_cb) cb_service.connect('object-deleted', self._object_deleted_cb) @@ -79,9 +79,9 @@ class ClipboardTray(tray.VTray): if not selection.data: return - logging.debug('ClipboardTray: adding type %r' % selection.type) + logging.debug('ClipboardTray: adding type ' + selection.type) - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() if selection.type == 'text/uri-list': uris = selection.data.split('\n') if len(uris) > 1: @@ -98,55 +98,39 @@ class ClipboardTray(tray.VTray): selection.data, on_disk=False) - def _object_added_cb(self, cb_service, cb_object): + def _object_added_cb(self, cb_service, object_id, name): if self._icons: group = self._icons.values()[0] else: group = None - icon = ClipboardIcon(cb_object, group) + icon = ClipboardIcon(object_id, name, group) self.add_item(icon) icon.show() - self._icons[cb_object.get_id()] = icon + self._icons[object_id] = icon objects_to_delete = self.get_children()[:-self.MAX_ITEMS] for icon in objects_to_delete: logging.debug('ClipboardTray: deleting surplus object') - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() cb_service.delete_object(icon.get_object_id()) - logging.debug('ClipboardTray: %r was added' % cb_object.get_id()) + logging.debug('ClipboardTray: ' + object_id + ' was added.') def _object_deleted_cb(self, cb_service, object_id): icon = self._icons[object_id] self.remove_item(icon) del self._icons[object_id] - logging.debug('ClipboardTray: %r was deleted' % object_id) + logging.debug('ClipboardTray: ' + object_id + ' was deleted.') def drag_motion_cb(self, widget, context, x, y, time): logging.debug('ClipboardTray._drag_motion_cb') - - if self._internal_drag(context): - context.drag_status(gtk.gdk.ACTION_MOVE, time) - else: - context.drag_status(gtk.gdk.ACTION_COPY, time) - self.props.drag_active = True - + context.drag_status(gtk.gdk.ACTION_COPY, time) return True - def drag_leave_cb(self, widget, context, time): - self.props.drag_active = False - def drag_drop_cb(self, widget, context, x, y, time): logging.debug('ClipboardTray._drag_drop_cb') - - if self._internal_drag(context): - # TODO: We should move the object within the clipboard here - if not self._context_map.has_context(context): - context.drop_finish(False, gtk.get_current_event_time()) - return False - - cb_service = clipboard.get_instance() + cb_service = clipboardservice.get_instance() object_id = cb_service.add_object(name="") self._context_map.add_context(context, object_id, len(context.targets)) @@ -195,8 +179,8 @@ class ClipboardTray(tray.VTray): prop_type, format_, dest = \ window.property_get('XdndDirectSave0', 'text/plain') - clipboardservice = clipboard.get_instance() - clipboardservice.add_object_format( \ + clipboard = clipboardservice.get_instance() + clipboard.add_object_format( \ object_id, 'XdndDirectSave0', dest, on_disk=True) else: self._add_selection(object_id, selection) @@ -207,10 +191,3 @@ class ClipboardTray(tray.VTray): if not self._context_map.has_context(context): context.drop_finish(True, gtk.get_current_event_time()) - def _internal_drag(self, context): - view_ancestor = context.get_source_widget().get_ancestor(gtk.Viewport) - if view_ancestor is self._viewport: - return True - else: - return False - diff --git a/src/view/frame/devicestray.py b/src/view/frame/devicestray.py new file mode 100644 index 0000000..b4ec8ca --- /dev/null +++ b/src/view/frame/devicestray.py @@ -0,0 +1,66 @@ +# 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 + +import logging + +from sugar.graphics import tray + +from view.devices import deviceview +from model import shellmodel + +_logger = logging.getLogger('DevicesTray') + +class DevicesTray(tray.HTray): + def __init__(self): + tray.HTray.__init__(self, align=tray.ALIGN_TO_END) + self._device_icons = {} + + devices_model = shellmodel.get_instance().get_devices() + + for device in devices_model: + self._add_device(device) + + devices_model.connect('device-appeared', + self.__device_appeared_cb) + devices_model.connect('device-disappeared', + self.__device_disappeared_cb) + + def _add_device(self, device): + try: + view = deviceview.create(device) + index = 0 + for item in self.get_children(): + index = self.get_item_index(item) + view_pos = getattr(view, "FRAME_POSITION_RELATIVE", -1) + item_pos = getattr(item, "FRAME_POSITION_RELATIVE", 0) + if view_pos < item_pos: + break + self.add_item(view, index=index) + view.show() + self._device_icons[device.get_id()] = view + except Exception, message: + _logger.warn("Not able to add icon for device [%r], because of " + "an error (%s). Continuing." % (device, message)) + + def _remove_device(self, device): + self.remove_item(self._device_icons[device.get_id()]) + del self._device_icons[device.get_id()] + + def __device_appeared_cb(self, model, device): + self._add_device(device) + + def __device_disappeared_cb(self, model, device): + self._remove_device(device) diff --git a/src/jarabe/frame/eventarea.py b/src/view/frame/eventarea.py index 5b31b24..0eba150 100644 --- a/src/jarabe/frame/eventarea.py +++ b/src/view/frame/eventarea.py @@ -17,7 +17,8 @@ import gtk import gobject import wnck -import gconf + +from sugar import profile _MAX_DELAY = 1000 @@ -35,47 +36,43 @@ class EventArea(gobject.GObject): self._windows = [] self._hover = False self._sids = {} - client = gconf.client_get_default() - self._edge_delay = client.get_int('/desktop/sugar/frame/edge_delay') - self._corner_delay = client.get_int('/desktop/sugar/frame/corner_delay') + pro = profile.get_profile() + self._hot_delay = int(pro.hot_corners_delay) + self._warm_delay = int(pro.warm_edges_delay) right = gtk.gdk.screen_width() - 1 bottom = gtk.gdk.screen_height() -1 width = gtk.gdk.screen_width() - 2 height = gtk.gdk.screen_height() - 2 - if self._edge_delay != _MAX_DELAY: - invisible = self._create_invisible(1, 0, width, 1, - self._edge_delay) + if self._warm_delay != _MAX_DELAY: + invisible = self._create_invisible(1, 0, width, 1, self._warm_delay) self._windows.append(invisible) invisible = self._create_invisible(1, bottom, width, 1, - self._edge_delay) + self._warm_delay) self._windows.append(invisible) invisible = self._create_invisible(0, 1, 1, height, - self._edge_delay) + self._warm_delay) self._windows.append(invisible) invisible = self._create_invisible(right, 1, 1, height, - self._edge_delay) + self._warm_delay) self._windows.append(invisible) - if self._corner_delay != _MAX_DELAY: - invisible = self._create_invisible(0, 0, 1, 1, - self._corner_delay) + if self._hot_delay != _MAX_DELAY: + invisible = self._create_invisible(0, 0, 1, 1, self._hot_delay) self._windows.append(invisible) - invisible = self._create_invisible(right, 0, 1, 1, - self._corner_delay) + invisible = self._create_invisible(right, 0, 1, 1, self._hot_delay) self._windows.append(invisible) - invisible = self._create_invisible(0, bottom, 1, 1, - self._corner_delay) + invisible = self._create_invisible(0, bottom, 1, 1, self._hot_delay) self._windows.append(invisible) invisible = self._create_invisible(right, bottom, 1, 1, - self._corner_delay) + self._hot_delay) self._windows.append(invisible) screen = wnck.screen_get_default() diff --git a/src/jarabe/frame/frame.py b/src/view/frame/frame.py index 6ba8814..c3f0de9 100644 --- a/src/jarabe/frame/frame.py +++ b/src/view/frame/frame.py @@ -23,17 +23,16 @@ import hippo from sugar.graphics import animator from sugar.graphics import style from sugar.graphics import palettegroup -from sugar import profile - -from jarabe.frame.eventarea import EventArea -from jarabe.frame.activitiestray import ActivitiesTray -from jarabe.frame.zoomtoolbar import ZoomToolbar -from jarabe.frame.friendstray import FriendsTray -from jarabe.frame.devicestray import DevicesTray -from jarabe.frame.framewindow import FrameWindow -from jarabe.frame.clipboardpanelwindow import ClipboardPanelWindow -from jarabe.frame.notification import NotificationIcon, NotificationWindow -from jarabe.model import notifications + +import view.Shell +from view.frame.eventarea import EventArea +from view.frame.activitiestray import ActivitiesTray +from view.frame.zoomtoolbar import ZoomToolbar +from view.frame.friendstray import FriendsTray +from view.frame.devicestray import DevicesTray +from view.frame.framewindow import FrameWindow +from view.frame.clipboardpanelwindow import ClipboardPanelWindow +from view.frame.notification import NotificationIcon, NotificationWindow TOP_RIGHT = 0 TOP_LEFT = 1 @@ -96,7 +95,6 @@ class Frame(object): MODE_NON_INTERACTIVE = 2 def __init__(self): - logging.debug("STARTUP: Loading the frame") self.mode = None self._palette_group = palettegroup.get_group('frame') @@ -127,17 +125,9 @@ class Frame(object): self._notif_by_icon = {} - notification_service = notifications.get_service() - notification_service.notification_received.connect( - self.__notification_received_cb) - notification_service.notification_cancelled.connect( - self.__notification_cancelled_cb) - def is_visible(self): return self.current_position != 0.0 - visible = property(is_visible, None) - def hide(self): if self._animator: self._animator.stop() @@ -286,22 +276,20 @@ class Frame(object): def notify_key_press(self): self._key_listener.key_press() - def add_notification(self, icon, corner=gtk.CORNER_TOP_LEFT, - duration=_NOTIFICATION_DURATION): - + def add_notification(self, icon, corner=TOP_LEFT): if not isinstance(icon, NotificationIcon): raise TypeError('icon must be a NotificationIcon.') window = NotificationWindow() screen = gtk.gdk.screen_get_default() - if corner == gtk.CORNER_TOP_LEFT: + if corner == TOP_LEFT: window.move(0, 0) - elif corner == gtk.CORNER_TOP_RIGHT: + elif corner == TOP_RIGHT: window.move(screen.get_width() - style.GRID_CELL_SIZE, 0) - elif corner == gtk.CORNER_BOTTOM_LEFT: + elif corner == BOTTOM_LEFT: window.move(0, screen.get_height() - style.GRID_CELL_SIZE) - elif corner == gtk.CORNER_BOTTOM_RIGHT: + elif corner == BOTTOM_RIGHT: window.move(screen.get_width() - style.GRID_CELL_SIZE, screen.get_height() - style.GRID_CELL_SIZE) else: @@ -313,7 +301,7 @@ class Frame(object): self._notif_by_icon[icon] = window - gobject.timeout_add(duration, + gobject.timeout_add(_NOTIFICATION_DURATION, lambda: self.remove_notification(icon)) def remove_notification(self, icon): @@ -328,31 +316,13 @@ class Frame(object): window.destroy() del self._notif_by_icon[icon] - def __notification_received_cb(self, **kwargs): - logging.debug('__notification_received_cb %r' % kwargs) - icon = NotificationIcon() - - hints = kwargs['hints'] - - icon_file_name = hints.get('x-sugar-icon-file-name', '') - if icon_file_name: - icon.props.icon_filename = icon_file_name - else: - icon.props.icon_name = 'application-octet-stream' - - icon_colors = hints.get('x-sugar-icon-colors', '') - if not icon_colors: - icon_colors = profile.get_color() - icon.props.xo_color = icon_colors - - duration = kwargs.get('expire_timeout', -1) - if duration == -1: - duration = _NOTIFICATION_DURATION + visible = property(is_visible, None) - self.add_notification(icon, gtk.CORNER_TOP_RIGHT, duration) +_instance = None - def __notification_cancelled_cb(self, **kwargs): - # Do nothing for now. Our notification UI is so simple, there's no - # point yet. - pass +def get_instance(): + global _instance + if not _instance: + _instance = Frame() + return _instance diff --git a/src/jarabe/frame/frameinvoker.py b/src/view/frame/frameinvoker.py index e4a13e1..e4a13e1 100644 --- a/src/jarabe/frame/frameinvoker.py +++ b/src/view/frame/frameinvoker.py diff --git a/src/jarabe/frame/framewindow.py b/src/view/frame/framewindow.py index 623d162..623d162 100644 --- a/src/jarabe/frame/framewindow.py +++ b/src/view/frame/framewindow.py diff --git a/src/jarabe/frame/friendstray.py b/src/view/frame/friendstray.py index 7e15f14..7236d75 100644 --- a/src/jarabe/frame/friendstray.py +++ b/src/view/frame/friendstray.py @@ -17,10 +17,11 @@ from sugar.presence import presenceservice from sugar.graphics.tray import VTray, TrayIcon -from jarabe.view.buddymenu import BuddyMenu -from jarabe.frame.frameinvoker import FrameWidgetInvoker -from jarabe.model import shell -from jarabe.model.buddy import BuddyModel +import view.Shell +from view.BuddyMenu import BuddyMenu +from view.frame.frameinvoker import FrameWidgetInvoker +from model import shellmodel +from model.BuddyModel import BuddyModel class FriendIcon(TrayIcon): def __init__(self, buddy): @@ -47,13 +48,14 @@ class FriendsTray(VTray): self.__activity_appeared_cb) self._owner = self._pservice.get_owner() - + # Add initial activities the PS knows about self._pservice.get_activities_async( \ reply_handler=self._get_activities_cb) - shell.get_model().connect('active-activity-changed', - self._active_activity_changed_cb) + home_model = shellmodel.get_instance().get_home() + home_model.connect('active-activity-changed', + self._active_activity_changed_cb) def _get_activities_cb(self, activities_list): for act in activities_list: @@ -85,8 +87,8 @@ class FriendsTray(VTray): self._buddies = {} def __activity_appeared_cb(self, pservice, activity_ps): - activity = shell.get_model().get_active_activity() - if activity and activity_ps.props.id == activity.get_activity_id(): + activity = view.Shell.get_instance().get_current_activity() + if activity and activity_ps.props.id == activity.get_id(): self._set_activity_ps(activity_ps, True) def _set_activity_ps(self, activity_ps, shared_activity): diff --git a/src/jarabe/frame/notification.py b/src/view/frame/notification.py index 68107ba..8a779f3 100644 --- a/src/jarabe/frame/notification.py +++ b/src/view/frame/notification.py @@ -20,7 +20,7 @@ import gtk from sugar.graphics import style from sugar.graphics.xocolor import XoColor -from jarabe.view.pulsingicon import PulsingIcon +from view.pulsingicon import PulsingIcon class NotificationIcon(gtk.EventBox): __gtype_name__ = 'SugarNotificationIcon' diff --git a/src/jarabe/frame/zoomtoolbar.py b/src/view/frame/zoomtoolbar.py index 43cc358..ed8d048 100644 --- a/src/jarabe/frame/zoomtoolbar.py +++ b/src/view/frame/zoomtoolbar.py @@ -22,8 +22,9 @@ import gtk from sugar.graphics.palette import Palette from sugar.graphics.radiotoolbutton import RadioToolButton -from jarabe.frame.frameinvoker import FrameWidgetInvoker -from jarabe.model import shell +import view.Shell +from view.frame.frameinvoker import FrameWidgetInvoker +from model import shellmodel class ZoomToolbar(gtk.Toolbar): def __init__(self): @@ -33,17 +34,17 @@ class ZoomToolbar(gtk.Toolbar): self.set_direction(gtk.TEXT_DIR_LTR) self._mesh_button = self._add_button('zoom-neighborhood', - _('Neighborhood'), shell.ShellModel.ZOOM_MESH) + _('Neighborhood'), shellmodel.ShellModel.ZOOM_MESH) self._groups_button = self._add_button('zoom-groups', - _('Group'), shell.ShellModel.ZOOM_GROUP) + _('Group'), shellmodel.ShellModel.ZOOM_FRIENDS) self._home_button = self._add_button('zoom-home', - _('Home'), shell.ShellModel.ZOOM_HOME) + _('Home'), shellmodel.ShellModel.ZOOM_HOME) self._activity_button = self._add_button('zoom-activity', - _('Activity'), shell.ShellModel.ZOOM_ACTIVITY) + _('Activity'), shellmodel.ShellModel.ZOOM_ACTIVITY) - shell_model = shell.get_model() - self._set_zoom_level(shell_model.zoom_level) - shell_model.zoom_level_changed.connect(self.__zoom_level_changed_cb) + shell_model = shellmodel.get_instance() + self._set_zoom_level(shell_model.props.zoom_level) + shell_model.connect('notify::zoom-level', self.__notify_zoom_level_cb) def _add_button(self, icon_name, label, zoom_level): if self.get_children(): @@ -66,21 +67,21 @@ class ZoomToolbar(gtk.Toolbar): def __level_clicked_cb(self, button, level): if not button.get_active(): return + if shellmodel.get_instance().props.zoom_level != level: + view.Shell.get_instance().set_zoom_level(level) - shell.get_model().zoom_level = level - - def __zoom_level_changed_cb(self, **kwargs): - self._set_zoom_level(kwargs['new_level']) + def __notify_zoom_level_cb(self, model, pspec): + self._set_zoom_level(model.props.zoom_level) def _set_zoom_level(self, new_level): logging.debug('new zoom level: %r' % new_level) - if new_level == shell.ShellModel.ZOOM_MESH: + if new_level == shellmodel.ShellModel.ZOOM_MESH: self._mesh_button.props.active = True - elif new_level == shell.ShellModel.ZOOM_GROUP: + elif new_level == shellmodel.ShellModel.ZOOM_FRIENDS: self._groups_button.props.active = True - elif new_level == shell.ShellModel.ZOOM_HOME: + elif new_level == shellmodel.ShellModel.ZOOM_HOME: self._home_button.props.active = True - elif new_level == shell.ShellModel.ZOOM_ACTIVITY: + elif new_level == shellmodel.ShellModel.ZOOM_ACTIVITY: self._activity_button.props.active = True else: raise ValueError('Invalid zoom level: %r' % (new_level)) diff --git a/src/jarabe/desktop/friendview.py b/src/view/home/FriendView.py index 4c5f1c8..be2f46f 100644 --- a/src/jarabe/desktop/friendview.py +++ b/src/view/home/FriendView.py @@ -19,9 +19,9 @@ import hippo from sugar.graphics.icon import CanvasIcon from sugar.graphics import style from sugar.presence import presenceservice +from sugar import activity -from jarabe.view.buddyicon import BuddyIcon -from jarabe.model import bundleregistry +from view.BuddyIcon import BuddyIcon class FriendView(hippo.CanvasBox): def __init__(self, buddy, **kwargs): @@ -47,10 +47,10 @@ class FriendView(hippo.CanvasBox): self._buddy.connect('color-changed', self._buddy_color_changed_cb) def _get_new_icon_name(self, ps_activity): - registry = bundleregistry.get_registry() - activity_info = registry.get_bundle(ps_activity.props.type) + registry = activity.get_registry() + activity_info = registry.get_activity(ps_activity.props.type) if activity_info: - return activity_info.get_icon() + return activity_info.icon return None def _remove_activity_icon(self): diff --git a/src/jarabe/desktop/groupbox.py b/src/view/home/FriendsBox.py index b77ae6e..c45c1c6 100644 --- a/src/jarabe/desktop/groupbox.py +++ b/src/view/home/FriendsBox.py @@ -14,27 +14,22 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import logging - import gobject import gtk import hippo -import gconf +from sugar import profile from sugar.graphics import style from sugar.graphics.icon import CanvasIcon, Icon from sugar.graphics.palette import Palette -from sugar.graphics.xocolor import XoColor -from jarabe.model import friends -from jarabe.desktop.friendview import FriendView -from jarabe.desktop.spreadlayout import SpreadLayout +from model import shellmodel +from view.home.FriendView import FriendView +from view.home.spreadlayout import SpreadLayout -class GroupBox(hippo.Canvas): - __gtype_name__ = 'SugarGroupBox' +class FriendsBox(hippo.Canvas): + __gtype_name__ = 'SugarFriendsBox' def __init__(self): - logging.debug("STARTUP: Loading the group view") - gobject.GObject.__init__(self) self._box = hippo.CanvasBox() @@ -46,29 +41,24 @@ class GroupBox(hippo.Canvas): self._layout = SpreadLayout() self._box.set_layout(self._layout) - client = gconf.client_get_default() - color = XoColor(client.get_string("/desktop/sugar/user/color")) - self._owner_icon = CanvasIcon(icon_name='computer-xo', cache=True, - xo_color=color) + xo_color=profile.get_color()) self._owner_icon.props.size = style.LARGE_ICON_SIZE palette_icon = Icon(icon_name='computer-xo', - xo_color=color) + xo_color=profile.get_color()) palette_icon.props.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR - - nick = client.get_string("/desktop/sugar/user/nick") - palette = Palette(None, primary_text=nick, icon=palette_icon) - + palette = Palette(None, primary_text=profile.get_nick_name(), + icon=palette_icon) self._owner_icon.set_palette(palette) self._layout.add(self._owner_icon) - friends_model = friends.get_model() + friends = shellmodel.get_instance().get_friends() - for friend in friends_model: + for friend in friends: self.add_friend(friend) - friends_model.connect('friend-added', self._friend_added_cb) - friends_model.connect('friend-removed', self._friend_removed_cb) + friends.connect('friend-added', self._friend_added_cb) + friends.connect('friend-removed', self._friend_removed_cb) def add_friend(self, buddy_info): icon = FriendView(buddy_info) @@ -96,3 +86,4 @@ class GroupBox(hippo.Canvas): self._layout.move(self._owner_icon, x, y) hippo.Canvas.do_size_allocate(self, allocation) + diff --git a/src/jarabe/desktop/homebox.py b/src/view/home/HomeBox.py index 2ffda09..0655253 100644 --- a/src/jarabe/desktop/homebox.py +++ b/src/view/home/HomeBox.py @@ -17,29 +17,30 @@ from gettext import gettext as _ import logging import os -import gconf import gobject import gtk from sugar.graphics import style from sugar.graphics import iconentry +from sugar.graphics.menuitem import MenuItem from sugar.graphics.radiotoolbutton import RadioToolButton from sugar.graphics.alert import Alert from sugar.graphics.icon import Icon +from sugar import profile +from sugar import activity +from sugar.bundle.activitybundle import ActivityBundle -from jarabe.model import bundleregistry -from jarabe.desktop import favoritesview -from jarabe.desktop.activitieslist import ActivitiesList +from view.home import favoritesview +from view.home.activitieslist import ActivitiesList _FAVORITES_VIEW = 0 _LIST_VIEW = 1 -_FAVORITES_KEY = "/desktop/sugar/desktop/favorites_layout" _AUTOSEARCH_TIMEOUT = 1000 def _convert_layout_constant(profile_constant): - for layoutid, layoutclass in favoritesview.LAYOUT_MAP.items(): + for layoutid, layoutclass in favoritesview._LAYOUT_MAP.items(): if profile_constant == layoutclass.profile_key: return layoutid logging.warning('Incorrect favorites_layout value: %r' % \ @@ -50,12 +51,11 @@ class HomeBox(gtk.VBox): __gtype_name__ = 'SugarHomeBox' def __init__(self): - logging.debug("STARTUP: Loading the home view") - gobject.GObject.__init__(self) self._favorites_view = favoritesview.FavoritesView() self._list_view = ActivitiesList() + self._enable_xo_palette = False self._favorites_view.connect('erase-activated', self.__erase_activated_cb) @@ -67,20 +67,19 @@ class HomeBox(gtk.VBox): self.pack_start(self._toolbar, expand=False) self._toolbar.show() - client = gconf.client_get_default() - layout_constant = client.get_string(_FAVORITES_KEY) - layout = _convert_layout_constant(layout_constant) + profile_layout_constant = profile.get_profile().favorites_layout + layout = _convert_layout_constant(profile_layout_constant) self._set_view(_FAVORITES_VIEW, layout) def __erase_activated_cb(self, view, bundle_id): - registry = bundleregistry.get_registry() - activity_info = registry.get_bundle(bundle_id) + registry = activity.get_registry() + activity_info = registry.get_activity(bundle_id) alert = Alert() alert.props.title = _('Confirm erase') alert.props.msg = \ _('Confirm erase: Do you want to permanently erase %s?') \ - % activity_info.get_name() + % activity_info.name cancel_icon = Icon(icon_name='dialog-cancel') alert.add_button(gtk.RESPONSE_CANCEL, _('Keep'), cancel_icon) @@ -106,9 +105,9 @@ class HomeBox(gtk.VBox): else: self._favorites_view.remove_alert() if response_id == gtk.RESPONSE_OK: - registry = bundleregistry.get_registry() - bundle = registry.get_bundle(bundle_id) - registry.uninstall(bundle) + registry = activity.get_registry() + activity_info = registry.get_activity(bundle_id) + ActivityBundle(activity_info.path).uninstall() def show_software_updates_alert(self): alert = Alert() @@ -149,7 +148,7 @@ class HomeBox(gtk.VBox): update_trigger_file) if response_id == gtk.RESPONSE_OK: - from jarabe.controlpanel.gui import ControlPanel + from controlpanel.gui import ControlPanel panel = ControlPanel() panel.set_transient_for(self.get_toplevel()) panel.show() @@ -163,12 +162,11 @@ class HomeBox(gtk.VBox): def __toolbar_view_changed_cb(self, toolbar, view, layout): self._set_view(view, layout) if layout is not None: - client = gconf.client_get_default() - layout_profile = client.get_string(_FAVORITES_KEY) - layout = _convert_layout_constant(layout_profile) - profile_key = favoritesview.LAYOUT_MAP[layout].profile_key - if profile_key != layout: - client.set_string(_FAVORITES_KEY, profile_key) + current_profile = profile.get_profile() + profile_key = favoritesview._LAYOUT_MAP[layout].profile_key + if profile_key != current_profile.favorites_layout: + current_profile.favorites_layout = profile_key + current_profile.save() else: logging.warning('Incorrect layout requested: %r' % layout) @@ -179,6 +177,9 @@ class HomeBox(gtk.VBox): self._favorites_view.layout = layout + if self._enable_xo_palette: + self._favorites_view.enable_xo_palette() + if self._favorites_view not in self.get_children(): self.add(self._favorites_view) self._favorites_view.show() @@ -205,6 +206,11 @@ class HomeBox(gtk.VBox): #return self._donut.has_activities() return False + def enable_xo_palette(self): + self._enable_xo_palette = True + if self._favorites_view is not None: + self._favorites_view.enable_xo_palette() + def focus_search_entry(self): self._toolbar.search_entry.grab_focus() @@ -241,7 +247,6 @@ class HomeToolbar(gtk.Toolbar): self.search_entry.connect('activate', self.__entry_activated_cb) self.search_entry.connect('changed', self.__entry_changed_cb) tool_item.add(self.search_entry) - self.search_entry.set_sensitive(False) self.search_entry.show() self._add_separator(expand=True) @@ -266,12 +271,8 @@ class HomeToolbar(gtk.Toolbar): def __view_button_toggled_cb(self, button, view): if button.props.active: if view == _FAVORITES_VIEW: - self.search_entry.set_text('') - self.search_entry.set_sensitive(False) self.emit('view-changed', view, button.layout) else: - self.search_entry.set_sensitive(True) - self.search_entry.grab_focus() self.emit('view-changed', view, None) def _add_separator(self, expand=False): @@ -321,24 +322,25 @@ class FavoritesButton(RadioToolButton): self.props.accelerator = _('<Ctrl>1') self.props.group = None - client = gconf.client_get_default() - layout_constant = client.get_string(_FAVORITES_KEY) - self._layout = _convert_layout_constant(layout_constant) + profile_layout_constant = profile.get_profile().favorites_layout + self._layout = _convert_layout_constant(profile_layout_constant) self._update_icon() # someday, this will be a gtk.Table() layouts_grid = gtk.HBox() layout_item = None - for layoutid, layoutclass in sorted(favoritesview.LAYOUT_MAP.items()): + for layoutid, layoutclass in sorted(favoritesview._LAYOUT_MAP.items()): layout_item = RadioToolButton(icon_name=layoutclass.icon_name, group=layout_item, active=False) if layoutid == self._layout: layout_item.set_active(True) - layouts_grid.pack_start(layout_item, fill=False) + layouts_grid.add(layout_item) layout_item.connect('toggled', self.__layout_activate_cb, layoutid) layouts_grid.show_all() self.props.palette.set_content(layouts_grid) + self.props.palette._update_separators() + def __layout_activate_cb(self, menu_item, layout): if not menu_item.get_active(): @@ -354,7 +356,7 @@ class FavoritesButton(RadioToolButton): self.emit('toggled') def _update_icon(self): - self.props.named_icon = favoritesview.LAYOUT_MAP[self._layout]\ + self.props.named_icon = favoritesview._LAYOUT_MAP[self._layout]\ .icon_name def _get_layout(self): diff --git a/src/view/home/HomeWindow.py b/src/view/home/HomeWindow.py new file mode 100644 index 0000000..316d572 --- /dev/null +++ b/src/view/home/HomeWindow.py @@ -0,0 +1,153 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 + +import gtk + +from sugar.graphics import style +from sugar.graphics import palettegroup + +from view.home.MeshBox import MeshBox +from view.home.HomeBox import HomeBox +from view.home.FriendsBox import FriendsBox +from view.home.transitionbox import TransitionBox +from model.shellmodel import ShellModel +from model import shellmodel + +_HOME_PAGE = 0 +_FRIENDS_PAGE = 1 +_MESH_PAGE = 2 +_TRANSITION_PAGE = 3 + +class HomeWindow(gtk.Window): + def __init__(self): + gtk.Window.__init__(self) + + accel_group = gtk.AccelGroup() + self.set_data('sugar-accel-group', accel_group) + self.add_accel_group(accel_group) + + self._active = False + self._level = ShellModel.ZOOM_HOME + + self.set_default_size(gtk.gdk.screen_width(), + gtk.gdk.screen_height()) + + self.realize() + self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DESKTOP) + self.connect('visibility-notify-event', + self._visibility_notify_event_cb) + + self._enter_sid = self.connect('enter-notify-event', + self._enter_notify_event_cb) + self._leave_sid = self.connect('leave-notify-event', + self._leave_notify_event_cb) + self._motion_sid = self.connect('motion-notify-event', + self._motion_notify_event_cb) + + self._home_box = HomeBox() + self._friends_box = FriendsBox() + self._mesh_box = MeshBox() + self._transition_box = TransitionBox() + + self._activate_view() + self.add(self._home_box) + self._home_box.show() + + self._transition_box.connect('completed', + self._transition_completed_cb) + + model = shellmodel.get_instance() + model.connect('notify::zoom-level', self.__zoom_level_changed_cb) + + def _enter_notify_event_cb(self, window, event): + if event.x != gtk.gdk.screen_width() / 2 or \ + event.y != gtk.gdk.screen_height() / 2: + self._mouse_moved() + + def _leave_notify_event_cb(self, window, event): + self._mouse_moved() + + def _motion_notify_event_cb(self, window, event): + self._mouse_moved() + + # We want to enable the XO palette only when the user + # moved away from the default mouse position (screen center). + def _mouse_moved(self): + self._home_box.enable_xo_palette() + self.disconnect(self._leave_sid) + self.disconnect(self._motion_sid) + self.disconnect(self._enter_sid) + + def _deactivate_view(self): + group = palettegroup.get_group("default") + group.popdown() + if self._level == ShellModel.ZOOM_HOME: + self._home_box.suspend() + elif self._level == ShellModel.ZOOM_MESH: + self._mesh_box.suspend() + + def _activate_view(self): + if self._level == ShellModel.ZOOM_HOME: + self._home_box.resume() + elif self._level == ShellModel.ZOOM_MESH: + self._mesh_box.resume() + + def _visibility_notify_event_cb(self, window, event): + if event.state == gtk.gdk.VISIBILITY_FULLY_OBSCURED: + self._deactivate_view() + else: + self._activate_view() + + def __zoom_level_changed_cb(self, model, pspec): + level = model.props.zoom_level + if level == ShellModel.ZOOM_ACTIVITY: + return + + self._deactivate_view() + self._level = level + self._activate_view() + + self.remove(self.get_child()) + self.add(self._transition_box) + self._transition_box.show() + + if self._level == ShellModel.ZOOM_HOME: + size = style.XLARGE_ICON_SIZE + elif self._level == ShellModel.ZOOM_FRIENDS: + size = style.LARGE_ICON_SIZE + elif self._level == ShellModel.ZOOM_MESH: + size = style.STANDARD_ICON_SIZE + + self._transition_box.set_size(size) + + def _transition_completed_cb(self, transition_box): + current_child = self.get_child() + self.remove(current_child) + + if self._level == ShellModel.ZOOM_HOME: + self.add(self._home_box) + self._home_box.show() + self._home_box.focus_search_entry() + elif self._level == ShellModel.ZOOM_FRIENDS: + self.add(self._friends_box) + self._friends_box.show() + elif self._level == ShellModel.ZOOM_MESH: + self.add(self._mesh_box) + self._mesh_box.show() + self._mesh_box.focus_search_entry() + + def get_home_box(self): + return self._home_box diff --git a/src/jarabe/desktop/Makefile.am b/src/view/home/Makefile.am index 94d8ab9..b323589 100644 --- a/src/jarabe/desktop/Makefile.am +++ b/src/view/home/Makefile.am @@ -1,19 +1,17 @@ -sugardir = $(pythondir)/jarabe/desktop +sugardir = $(pkgdatadir)/shell/view/home sugar_PYTHON = \ __init__.py \ activitieslist.py \ favoritesview.py \ favoriteslayout.py \ - friendview.py \ grid.py \ - groupbox.py \ - homebox.py \ - homewindow.py \ - keydialog.py \ - meshbox.py \ - myicon.py \ + FriendView.py \ + FriendsBox.py \ + HomeBox.py \ + HomeWindow.py \ + MeshBox.py \ + MyIcon.py \ proc_smaps.py \ - schoolserver.py \ snowflakelayout.py \ spreadlayout.py \ transitionbox.py diff --git a/extensions/cpsection/datetime/Makefile.in b/src/view/home/Makefile.in index da557c4..75c0d6c 100644 --- a/extensions/cpsection/datetime/Makefile.in +++ b/src/view/home/Makefile.in @@ -29,7 +29,7 @@ POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : -subdir = extensions/cpsection/datetime +subdir = src/view/home DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(sugar_PYTHON) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -73,9 +73,6 @@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ -GCONFTOOL = @GCONFTOOL@ -GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ -GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ @@ -192,11 +189,23 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -sugardir = $(pkgdatadir)/extensions/cpsection/datetime +sugardir = $(pkgdatadir)/shell/view/home sugar_PYTHON = \ - __init__.py \ - model.py \ - view.py + __init__.py \ + activitieslist.py \ + favoritesview.py \ + favoriteslayout.py \ + grid.py \ + FriendView.py \ + FriendsBox.py \ + HomeBox.py \ + HomeWindow.py \ + MeshBox.py \ + MyIcon.py \ + proc_smaps.py \ + snowflakelayout.py \ + spreadlayout.py \ + transitionbox.py all: all-am @@ -210,9 +219,9 @@ $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign extensions/cpsection/datetime/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/view/home/Makefile'; \ cd $(top_srcdir) && \ - $(AUTOMAKE) --foreign extensions/cpsection/datetime/Makefile + $(AUTOMAKE) --foreign src/view/home/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ diff --git a/src/view/home/MeshBox.py b/src/view/home/MeshBox.py new file mode 100644 index 0000000..8cf8af6 --- /dev/null +++ b/src/view/home/MeshBox.py @@ -0,0 +1,646 @@ +# Copyright (C) 2006-2007 Red Hat, Inc. +# +# 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 gettext import gettext as _ +import logging + +import hippo +import gobject +import gtk + +from sugar.graphics.icon import CanvasIcon, Icon +from sugar.graphics.xocolor import XoColor +from sugar.graphics import style +from sugar.graphics.icon import get_icon_state +from sugar.graphics import palette +from sugar.graphics import iconentry +from sugar.graphics.menuitem import MenuItem +from sugar import profile + +from model import accesspointmodel +from model.devices.network import wireless +from model import shellmodel +from hardware import hardwaremanager +from hardware import nmclient +from view.BuddyIcon import BuddyIcon +from view.pulsingicon import CanvasPulsingIcon +from view.home.snowflakelayout import SnowflakeLayout +from view.home.spreadlayout import SpreadLayout +import view.Shell + +from hardware.nmclient import NM_802_11_CAP_PROTO_WEP, \ + NM_802_11_CAP_PROTO_WPA, NM_802_11_CAP_PROTO_WPA2 + + +_ICON_NAME = 'network-wireless' + +class AccessPointView(CanvasPulsingIcon): + def __init__(self, model, mesh_device=None): + CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE, + cache=True) + self._model = model + self._meshdev = mesh_device + self._disconnect_item = None + self._connect_item = None + self._greyed_out = False + + self.connect('activated', self._activate_cb) + + model.connect('notify::strength', self._strength_changed_cb) + model.connect('notify::name', self._name_changed_cb) + model.connect('notify::state', self._state_changed_cb) + + pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), + style.COLOR_TRANSPARENT.get_svg())) + self.props.pulse_color = pulse_color + + # Update badge + caps = model.props.capabilities + if model.get_nm_network().is_favorite(): + self.props.badge_name = "emblem-favorite" + elif (caps & NM_802_11_CAP_PROTO_WEP) or \ + (caps & NM_802_11_CAP_PROTO_WPA) or \ + (caps & NM_802_11_CAP_PROTO_WPA2): + self.props.badge_name = "emblem-locked" + + self._palette = self._create_palette() + self.set_palette(self._palette) + + self._update_icon() + self._update_name() + self._update_state() + + def _create_palette(self): + icon_name = get_icon_state(_ICON_NAME, self._model.props.strength) + palette_icon = Icon(icon_name=icon_name, + icon_size=style.STANDARD_ICON_SIZE, + badge_name=self.props.badge_name) + ap_color = self._model.get_nm_network().get_colors() + palette_icon.props.xo_color = XoColor('%s,%s' % ap_color) + + p = palette.Palette(primary_text=self._model.props.name, + icon=palette_icon) + + self._connect_item = MenuItem(_('Connect'), 'dialog-ok') + self._connect_item.connect('activate', self._activate_cb) + p.menu.append(self._connect_item) + + # Only show disconnect when there's a mesh device, because mesh takes + # priority over the normal wireless device. NM doesn't have a + # "disconnect" method for a device either (for various reasons) + # so this doesn't have a good mapping + if self._meshdev: + self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject') + self._disconnect_item.connect('activate', + self._disconnect_activate_cb) + p.menu.append(self._disconnect_item) + + return p + + def _disconnect_activate_cb(self, menuitem): + # Disconnection for an AP means activating the default mesh device + network_manager = hardwaremanager.get_network_manager() + if network_manager and self._meshdev: + network_manager.set_active_device(self._meshdev) + self._palette.props.secondary_text = _('Disconnecting...') + self.props.pulsing = False + + def _strength_changed_cb(self, model, pspec): + self._update_icon() + + def _name_changed_cb(self, model, pspec): + self._update_name() + + def _state_changed_cb(self, model, pspec): + self._update_icon() + self._update_state() + + def _activate_cb(self, icon): + network_manager = hardwaremanager.get_network_manager() + if network_manager: + device = self._model.get_nm_device() + network = self._model.get_nm_network() + network_manager.set_active_device(device, network) + + def _update_name(self): + self._palette.props.primary_text = self._model.props.name + + def _update_icon(self): + # keep this code in sync with view/devices/network/wireless.py + strength = self._model.props.strength + if self._model.props.state == accesspointmodel.STATE_CONNECTED: + icon_name = '%s-connected' % _ICON_NAME + else: + icon_name = _ICON_NAME + icon_name = get_icon_state(icon_name, strength) + if icon_name: + self.props.icon_name = icon_name + icon = self._palette.props.icon + icon.props.icon_name = icon_name + + def _update_state(self): + if self._model.props.state == accesspointmodel.STATE_CONNECTING: + if self._disconnect_item: + self._disconnect_item.show() + self._connect_item.hide() + self._palette.props.secondary_text = _('Connecting...') + self.props.pulsing = True + elif self._model.props.state == accesspointmodel.STATE_CONNECTED: + if self._disconnect_item: + self._disconnect_item.show() + self._connect_item.hide() + # TODO: show the channel number + self._palette.props.secondary_text = _('Connected') + self.props.pulsing = False + elif self._model.props.state == accesspointmodel.STATE_NOTCONNECTED: + if self._disconnect_item: + self._disconnect_item.hide() + self._connect_item.show() + # TODO: show the channel number + self._palette.props.secondary_text = None + self.props.pulsing = False + + if self._greyed_out: + self.props.pulsing = False + self.props.base_color = XoColor('#D5D5D5,#D5D5D5') + else: + self.props.base_color = XoColor('%s,%s' % \ + self._model.get_nm_network().get_colors()) + + def set_filter(self, query): + self._greyed_out = self._model.props.name.lower().find(query) == -1 + self._update_state() + +_MESH_ICON_NAME = 'network-mesh' + +class MeshDeviceView(CanvasPulsingIcon): + def __init__(self, nm_device, channel): + if not channel in [1, 6, 11]: + raise ValueError("Invalid channel %d" % channel) + + CanvasPulsingIcon.__init__(self, size=style.STANDARD_ICON_SIZE, + icon_name=_MESH_ICON_NAME, cache=True) + + self._nm_device = nm_device + self.channel = channel + self.props.badge_name = "badge-channel-%d" % self.channel + self._greyed_out = False + + self._disconnect_item = None + self._palette = self._create_palette() + self.set_palette(self._palette) + + pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(), + style.COLOR_TRANSPARENT.get_svg())) + self.props.pulse_color = pulse_color + + self.connect('activated', self._activate_cb) + + self._nm_device.connect('state-changed', self._state_changed_cb) + self._nm_device.connect('activation-stage-changed', + self._state_changed_cb) + self._update_state() + + def _create_palette(self): + p = palette.Palette(_("Mesh Network") + " " + str(self.channel), + menu_after_content=True) + + self._disconnect_item = gtk.MenuItem(_('Disconnect...')) + self._disconnect_item.connect('activate', self._disconnect_activate_cb) + p.menu.append(self._disconnect_item) + + state = self._nm_device.get_state() + chan = wireless.freq_to_channel(self._nm_device.get_frequency()) + if state == nmclient.DEVICE_STATE_ACTIVATED and chan == self.channel: + self._disconnect_item.show() + return p + + def _disconnect_activate_cb(self, menuitem): + network_manager = hardwaremanager.get_network_manager() + if network_manager: + network_manager.set_active_device(self._nm_device) + + def _activate_cb(self, icon): + network_manager = hardwaremanager.get_network_manager() + if network_manager: + freq = wireless.channel_to_freq(self.channel) + network_manager.set_active_device(self._nm_device, mesh_freq=freq) + + def _state_changed_cb(self, model): + self._update_state() + + def _update_state(self): + state = self._nm_device.get_state() + chan = wireless.freq_to_channel(self._nm_device.get_frequency()) + if state == nmclient.DEVICE_STATE_ACTIVATING and chan == self.channel: + self._disconnect_item.hide() + self.props.pulsing = True + elif state == nmclient.DEVICE_STATE_ACTIVATED and chan == self.channel: + self._disconnect_item.show() + self.props.pulsing = False + elif state == nmclient.DEVICE_STATE_INACTIVE or chan != self.channel: + self._disconnect_item.hide() + self.props.pulsing = False + + if self._greyed_out: + self.props.pulsing = False + self.props.base_color = XoColor('#D5D5D5,#D5D5D5') + else: + self.props.base_color = profile.get_color() + + def set_filter(self, query): + self._greyed_out = (query != '') + self._update_state() + +class ActivityView(hippo.CanvasBox): + def __init__(self, model): + hippo.CanvasBox.__init__(self) + + self._model = model + self._icons = {} + self._palette = None + + self._layout = SnowflakeLayout() + self.set_layout(self._layout) + + self._icon = self._create_icon() + self._layout.add(self._icon, center=True) + + self._update_palette() + + activity = self._model.activity + activity.connect('notify::name', self._name_changed_cb) + activity.connect('notify::color', self._color_changed_cb) + activity.connect('notify::private', self._private_changed_cb) + activity.connect('joined', self._joined_changed_cb) + #FIXME: 'joined' signal not working, see #5032 + + def _create_icon(self): + icon = CanvasIcon(file_name=self._model.get_icon_name(), + xo_color=self._model.get_color(), cache=True, + size=style.STANDARD_ICON_SIZE) + icon.connect('activated', self._clicked_cb) + return icon + + def _create_palette(self): + p_icon = Icon(file=self._model.get_icon_name(), + xo_color=self._model.get_color()) + p_icon.props.icon_size = gtk.ICON_SIZE_LARGE_TOOLBAR + p = palette.Palette(None, primary_text=self._model.activity.props.name, + icon=p_icon) + + private = self._model.activity.props.private + joined = self._model.activity.props.joined + + if joined: + item = MenuItem(_('Resume'), 'activity-start') + item.connect('activate', self._clicked_cb) + item.show() + p.menu.append(item) + elif not private: + item = MenuItem(_('Join'), 'activity-start') + item.connect('activate', self._clicked_cb) + item.show() + p.menu.append(item) + + return p + + def _update_palette(self): + self._palette = self._create_palette() + self._icon.set_palette(self._palette) + + def has_buddy_icon(self, key): + return self._icons.has_key(key) + + def add_buddy_icon(self, key, icon): + self._icons[key] = icon + self._layout.add(icon) + + def remove_buddy_icon(self, key): + icon = self._icons[key] + del self._icons[key] + icon.destroy() + + def _clicked_cb(self, item): + bundle_id = self._model.get_bundle_id() + view.Shell.get_instance().join_activity(bundle_id, self._model.get_id()) + + def set_filter(self, query): + text_to_check = self._model.activity.props.name.lower() + \ + self._model.activity.props.type.lower() + if text_to_check.find(query) == -1: + self._icon.props.stroke_color = '#D5D5D5' + self._icon.props.fill_color = style.COLOR_TRANSPARENT.get_svg() + else: + self._icon.props.xo_color = self._model.get_color() + + for icon in self._icons.itervalues(): + if hasattr(icon, 'set_filter'): + icon.set_filter(query) + + def _name_changed_cb(self, activity, pspec): + self._update_palette() + + def _color_changed_cb(self, activity, pspec): + self._layout.remove(self._icon) + self._icon = self._create_icon() + self._layout.add(self._icon, center=True) + self._icon.set_palette(self._palette) + + def _private_changed_cb(self, activity, pspec): + self._update_palette() + + def _joined_changed_cb(self, widget, event): + logging.debug('ActivityView._joined_changed_cb: AAAA!!!!') + +_AUTOSEARCH_TIMEOUT = 1000 + +class MeshToolbar(gtk.Toolbar): + __gtype_name__ = 'MeshToolbar' + + __gsignals__ = { + 'query-changed': (gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, + ([str])) + } + + def __init__(self): + gtk.Toolbar.__init__(self) + + self._query = None + self._autosearch_timer = None + + self._add_separator() + + tool_item = gtk.ToolItem() + self.insert(tool_item, -1) + tool_item.show() + + self.search_entry = iconentry.IconEntry() + self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY, + 'system-search') + self.search_entry.add_clear_button() + self.search_entry.set_width_chars(25) + self.search_entry.connect('activate', self._entry_activated_cb) + self.search_entry.connect('changed', self._entry_changed_cb) + tool_item.add(self.search_entry) + self.search_entry.show() + + self._add_separator(expand=True) + + def _add_separator(self, expand=False): + separator = gtk.SeparatorToolItem() + separator.props.draw = False + if expand: + separator.set_expand(True) + else: + separator.set_size_request(style.GRID_CELL_SIZE, + style.GRID_CELL_SIZE) + self.insert(separator, -1) + separator.show() + + def _entry_activated_cb(self, entry): + if self._autosearch_timer: + gobject.source_remove(self._autosearch_timer) + new_query = entry.props.text + if self._query != new_query: + self._query = new_query + self.emit('query-changed', self._query) + + def _entry_changed_cb(self, entry): + if not entry.props.text: + entry.activate() + return + + if self._autosearch_timer: + gobject.source_remove(self._autosearch_timer) + self._autosearch_timer = gobject.timeout_add(_AUTOSEARCH_TIMEOUT, + self._autosearch_timer_cb) + + def _autosearch_timer_cb(self): + logging.debug('_autosearch_timer_cb') + self._autosearch_timer = None + self.search_entry.activate() + return False + +class MeshBox(gtk.VBox): + __gtype_name__ = 'SugarMeshBox' + def __init__(self): + gobject.GObject.__init__(self) + + self._model = shellmodel.get_instance().get_mesh() + self._buddies = {} + self._activities = {} + self._access_points = {} + self._mesh = {} + self._buddy_to_activity = {} + self._suspended = True + self._query = '' + self._owner_icon = None + + self._toolbar = MeshToolbar() + self._toolbar.connect('query-changed', self._toolbar_query_changed_cb) + self.pack_start(self._toolbar, expand=False) + self._toolbar.show() + + canvas = hippo.Canvas() + self.add(canvas) + canvas.show() + + self._layout_box = hippo.CanvasBox( \ + background_color=style.COLOR_WHITE.get_int()) + canvas.set_root(self._layout_box) + + self._layout = SpreadLayout() + self._layout_box.set_layout(self._layout) + + for buddy_model in self._model.get_buddies(): + self._add_alone_buddy(buddy_model) + + self._model.connect('buddy-added', self._buddy_added_cb) + self._model.connect('buddy-removed', self._buddy_removed_cb) + self._model.connect('buddy-moved', self._buddy_moved_cb) + + for activity_model in self._model.get_activities(): + self._add_activity(activity_model) + + self._model.connect('activity-added', self._activity_added_cb) + self._model.connect('activity-removed', self._activity_removed_cb) + + for ap_model in self._model.get_access_points(): + self._add_access_point(ap_model) + + self._model.connect('access-point-added', + self._access_point_added_cb) + self._model.connect('access-point-removed', + self._access_point_removed_cb) + + if self._model.get_mesh(): + self.__mesh_added_cb(self._model, self._model.get_mesh()) + + self._model.connect('mesh-added', self.__mesh_added_cb) + self._model.connect('mesh-removed', self.__mesh_removed_cb) + + def __mesh_added_cb(self, model, meshdev): + self._add_mesh_icon(meshdev, 1) + self._add_mesh_icon(meshdev, 6) + self._add_mesh_icon(meshdev, 11) + + def __mesh_removed_cb(self, model): + self._remove_mesh_icon(1) + self._remove_mesh_icon(6) + self._remove_mesh_icon(11) + + def do_size_allocate(self, allocation): + width = allocation.width + height = allocation.height + + min_w_, icon_width = self._owner_icon.get_width_request() + min_h_, icon_height = self._owner_icon.get_height_request(icon_width) + x = (width - icon_width) / 2 + y = (height - icon_height) / 2 - style.GRID_CELL_SIZE + self._layout.move(self._owner_icon, x, y) + + gtk.VBox.do_size_allocate(self, allocation) + + def _buddy_added_cb(self, model, buddy_model): + self._add_alone_buddy(buddy_model) + + def _buddy_removed_cb(self, model, buddy_model): + self._remove_buddy(buddy_model) + + def _buddy_moved_cb(self, model, buddy_model, activity_model): + # Owner doesn't move from the center + if buddy_model.is_owner(): + return + self._move_buddy(buddy_model, activity_model) + + def _activity_added_cb(self, model, activity_model): + self._add_activity(activity_model) + + def _activity_removed_cb(self, model, activity_model): + self._remove_activity(activity_model) + + def _access_point_added_cb(self, model, ap_model): + self._add_access_point(ap_model) + + def _access_point_removed_cb(self, model, ap_model): + self._remove_access_point(ap_model) + + def _add_mesh_icon(self, meshdev, channel): + if self._mesh.has_key(channel): + self._remove_mesh_icon(channel) + if not meshdev: + return + self._mesh[channel] = MeshDeviceView(meshdev, channel) + self._layout.add(self._mesh[channel]) + + def _remove_mesh_icon(self, channel): + if not self._mesh.has_key(channel): + return + self._layout.remove(self._mesh[channel]) + del self._mesh[channel] + + def _add_alone_buddy(self, buddy_model): + icon = BuddyIcon(buddy_model) + if buddy_model.is_owner(): + self._owner_icon = icon + self._layout.add(icon) + + if hasattr(icon, 'set_filter'): + icon.set_filter(self._query) + + self._buddies[buddy_model.get_key()] = icon + + def _remove_alone_buddy(self, buddy_model): + icon = self._buddies[buddy_model.get_key()] + self._layout.remove(icon) + del self._buddies[buddy_model.get_key()] + icon.destroy() + + def _remove_buddy(self, buddy_model): + key = buddy_model.get_key() + if self._buddies.has_key(key): + self._remove_alone_buddy(buddy_model) + else: + for activity in self._activities.values(): + if activity.has_buddy_icon(key): + activity.remove_buddy_icon(key) + + def _move_buddy(self, buddy_model, activity_model): + self._remove_buddy(buddy_model) + + if activity_model == None: + self._add_alone_buddy(buddy_model) + elif activity_model.get_id() in self._activities: + activity = self._activities[activity_model.get_id()] + + icon = BuddyIcon(buddy_model, style.STANDARD_ICON_SIZE) + activity.add_buddy_icon(buddy_model.get_key(), icon) + + if hasattr(icon, 'set_filter'): + icon.set_filter(self._query) + + def _add_activity(self, activity_model): + icon = ActivityView(activity_model) + self._layout.add(icon) + + if hasattr(icon, 'set_filter'): + icon.set_filter(self._query) + + self._activities[activity_model.get_id()] = icon + + def _remove_activity(self, activity_model): + icon = self._activities[activity_model.get_id()] + self._layout.remove(icon) + del self._activities[activity_model.get_id()] + icon.destroy() + + def _add_access_point(self, ap_model): + meshdev = self._model.get_mesh() + icon = AccessPointView(ap_model, meshdev) + self._layout.add(icon) + + if hasattr(icon, 'set_filter'): + icon.set_filter(self._query) + + self._access_points[ap_model.get_id()] = icon + + def _remove_access_point(self, ap_model): + icon = self._access_points[ap_model.get_id()] + self._layout.remove(icon) + del self._access_points[ap_model.get_id()] + + def suspend(self): + if not self._suspended: + self._suspended = True + for ap in self._access_points.values(): + ap.props.paused = True + + def resume(self): + if self._suspended: + self._suspended = False + for ap in self._access_points.values(): + ap.props.paused = False + + def _toolbar_query_changed_cb(self, toolbar, query): + self._query = query.lower() + for icon in self._layout_box.get_children(): + if hasattr(icon, 'set_filter'): + icon.set_filter(self._query) + + def focus_search_entry(self): + self._toolbar.search_entry.grab_focus() diff --git a/src/jarabe/desktop/myicon.py b/src/view/home/MyIcon.py index 4a4ad95..af0f6ce 100644 --- a/src/jarabe/desktop/myicon.py +++ b/src/view/home/MyIcon.py @@ -14,15 +14,11 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import gconf - from sugar.graphics.icon import CanvasIcon -from sugar.graphics.xocolor import XoColor +from sugar import profile class MyIcon(CanvasIcon): def __init__(self, size): - client = gconf.client_get_default() - color = XoColor(client.get_string("/desktop/sugar/user/color")) CanvasIcon.__init__(self, size=size, icon_name='computer-xo', - xo_color=color) + xo_color=profile.get_color()) diff --git a/src/jarabe/controlpanel/__init__.py b/src/view/home/__init__.py index a9dd95a..a9dd95a 100644 --- a/src/jarabe/controlpanel/__init__.py +++ b/src/view/home/__init__.py diff --git a/src/jarabe/desktop/activitieslist.py b/src/view/home/activitieslist.py index 5b19331..4222d38 100644 --- a/src/jarabe/desktop/activitieslist.py +++ b/src/view/home/activitieslist.py @@ -14,33 +14,28 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import logging - import gobject import gtk import hippo -import gconf +from sugar import profile +from sugar import activity from sugar import util from sugar.graphics import style from sugar.graphics.icon import CanvasIcon -from sugar.graphics.xocolor import XoColor -from sugar.activity import activityfactory -from jarabe.model import bundleregistry -from jarabe.view.palettes import ActivityPalette +import view.Shell +from view.palettes import ActivityPalette class ActivitiesList(gtk.VBox): __gtype_name__ = 'SugarActivitiesList' __gsignals__ = { 'erase-activated' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([str])) + gobject.TYPE_NONE, ([str])), } def __init__(self): - logging.debug('STARTUP: Loading the activities list') - gobject.GObject.__init__(self) scrolled_window = gtk.ScrolledWindow() @@ -61,22 +56,27 @@ class ActivitiesList(gtk.VBox): self._box.props.background_color = style.COLOR_WHITE.get_int() canvas.set_root(self._box) - gobject.idle_add(self.__connect_to_bundle_registry_cb) + registry = activity.get_registry() + registry.get_activities_async(reply_handler=self._get_activities_cb) + registry.connect('activity-added', self.__activity_added_cb) + registry.connect('activity-removed', self.__activity_removed_cb) + + def _get_activities_cb(self, activity_list): + gobject.idle_add(self._add_activity_list, activity_list) - def __connect_to_bundle_registry_cb(self): - registry = bundleregistry.get_registry() - for info in registry: + def _add_activity_list(self, activity_list): + info = activity_list.pop() + if info.bundle_id != 'org.laptop.JournalActivity': self._add_activity(info) - registry.connect('bundle-added', self.__activity_added_cb) - registry.connect('bundle-removed', self.__activity_removed_cb) + return len(activity_list) > 0 def __activity_added_cb(self, activity_registry, activity_info): self._add_activity(activity_info) def __activity_removed_cb(self, activity_registry, activity_info): for entry in self._box.get_children(): - if entry.get_bundle_id() == activity_info.get_bundle_id() and \ - entry.get_version() == activity_info.get_activity_version(): + if entry.get_bundle_id() == activity_info.bundle_id and \ + entry.get_version() == activity_info.version: self._box.remove(entry) return @@ -97,10 +97,10 @@ class ActivitiesList(gtk.VBox): for entry in self._box.get_children(): entry.set_visible(entry.matches(query)) - def __key_press_event_cb(self, scrolled_window, event): + def __key_press_event_cb(self, widget, event): keyname = gtk.gdk.keyval_name(event.keyval) - vadjustment = scrolled_window.props.vadjustment + vadjustment = self.props.vadjustment if keyname == 'Up': if vadjustment.props.value > vadjustment.props.lower: vadjustment.props.value -= vadjustment.props.step_increment @@ -131,30 +131,27 @@ class ActivityIcon(CanvasIcon): __gsignals__ = { 'erase-activated' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([str])) + gobject.TYPE_NONE, ([str])), } def __init__(self, activity_info): CanvasIcon.__init__(self, size=style.STANDARD_ICON_SIZE, cache=True, - file_name=activity_info.get_icon()) + file_name=activity_info.icon) self._activity_info = activity_info self._uncolor() self.connect('hovering-changed', self.__hovering_changed_event_cb) self.connect('button-release-event', self.__button_release_event_cb) - client = gconf.client_get_default() - self._xocolor = XoColor(client.get_string("/desktop/sugar/user/color")) - def create_palette(self): palette = ActivityPalette(self._activity_info) palette.connect('erase-activated', self.__erase_activated_cb) return palette def __erase_activated_cb(self, palette): - self.emit('erase-activated', self._activity_info.get_bundle_id()) + self.emit('erase-activated', self._activity_info.bundle_id) def _color(self): - self.props.xo_color = self._xocolor + self.props.xo_color = profile.get_color() def _uncolor(self): self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() @@ -170,6 +167,7 @@ class ActivityIcon(CanvasIcon): self.palette.popdown(immediate=True) self._uncolor() + class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem): __gtype_name__ = 'SugarActivityEntry' @@ -186,16 +184,14 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem): box_height=style.GRID_CELL_SIZE, orientation=hippo.ORIENTATION_HORIZONTAL) - registry = bundleregistry.get_registry() - registry.connect('bundle-changed', self.__activity_changed_cb) + registry = activity.get_registry() + registry.connect('activity-changed', self.__activity_changed_cb) - self._bundle = activity_info - self._bundle_id = activity_info.get_bundle_id() - self._version = activity_info.get_activity_version() - self._favorite = registry.is_bundle_favorite(self._bundle_id, - self._version) - self._title = activity_info.get_name() - self._installation_time = activity_info.get_installation_time() + self._bundle_id = activity_info.bundle_id + self._version = activity_info.version + self._favorite = activity_info.favorite + self._title = activity_info.name + self._installation_time = activity_info.installation_time self._favorite_icon = FavoriteIcon(self._favorite) self._favorite_icon.connect('notify::favorite', @@ -208,17 +204,17 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem): self.append(self.icon) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: - align = hippo.ALIGNMENT_END + align = hippo.ALIGNMENT_END else: - align = hippo.ALIGNMENT_START + align = hippo.ALIGNMENT_START - title = hippo.CanvasText(text=activity_info.get_name(), + title = hippo.CanvasText(text=activity_info.name, xalign=align, font_desc=style.FONT_BOLD.get_pango_desc(), box_width=ActivityEntry._TITLE_COL_WIDTH) self.append(title) - version = hippo.CanvasText(text=activity_info.get_activity_version(), + version = hippo.CanvasText(text=activity_info.version, xalign=hippo.ALIGNMENT_END, font_desc=style.FONT_NORMAL.get_pango_desc(), box_width=ActivityEntry._VERSION_COL_WIDTH) @@ -227,7 +223,7 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem): expander = hippo.CanvasBox() self.append(expander, hippo.PACK_EXPAND) - timestamp = activity_info.get_installation_time() + timestamp = activity_info.installation_time date = hippo.CanvasText( text=util.timestamp_to_elapsed_string(timestamp), xalign=align, @@ -239,23 +235,19 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem): self.reverse() def __favorite_changed_cb(self, favorite_icon, pspec): - registry = bundleregistry.get_registry() - registry.set_bundle_favorite(self._bundle_id, self._version, + registry = activity.get_registry() + registry.set_activity_favorite(self._bundle_id, self._version, favorite_icon.props.favorite) def __activity_changed_cb(self, activity_registry, activity_info): - if self._bundle_id == activity_info.get_bundle_id() and \ - self._version == activity_info.get_activity_version(): - self._title = activity_info.get_name() - - registry = bundleregistry.get_registry() - self._favorite = registry.is_bundle_favorite(self._bundle_id, - self._version) - + if self._bundle_id == activity_info.bundle_id and \ + self._version == activity_info.version: + self._title = activity_info.name + self._favorite = activity_info.favorite self._favorite_icon.props.favorite = self._favorite def __icon_button_release_event_cb(self, icon, event): - activityfactory.create(self._bundle) + view.Shell.get_instance().start_activity(self._bundle_id) def get_bundle_id(self): return self._bundle_id @@ -272,33 +264,42 @@ class ActivityEntry(hippo.CanvasBox, hippo.CanvasItem): return self._title.lower().find(query) > -1 class FavoriteIcon(CanvasIcon): + __gproperties__ = { + 'favorite' : (bool, None, None, False, + gobject.PARAM_READWRITE) + } + def __init__(self, favorite): CanvasIcon.__init__(self, icon_name='emblem-favorite', box_width=style.GRID_CELL_SIZE*3/5, size=style.SMALL_ICON_SIZE) self._favorite = None - self.set_favorite(favorite) + self._set_favorite(favorite) self.connect('button-release-event', self.__release_event_cb) self.connect('motion-notify-event', self.__motion_notify_event_cb) - def set_favorite(self, favorite): + def _set_favorite(self, favorite): if favorite == self._favorite: return self._favorite = favorite if favorite: - client = gconf.client_get_default() - color = XoColor(client.get_string('/desktop/sugar/user/color')) - self.props.xo_color = color + self.props.xo_color = profile.get_color() else: self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() self.props.fill_color = style.COLOR_WHITE.get_svg() - def get_favorite(self): - return self._favorite + def do_set_property(self, pspec, value): + if pspec.name == 'favorite': + self._set_favorite(value) + else: + CanvasIcon.do_set_property(self, pspec, value) - favorite = gobject.property( - type=bool, default=False, getter=get_favorite, setter=set_favorite) + def do_get_property(self, pspec): + if pspec.name == 'favorite': + return self._favorite + else: + return CanvasIcon.do_get_property(self, pspec) def __release_event_cb(self, icon, event): self.props.favorite = not self.props.favorite diff --git a/src/jarabe/desktop/favoriteslayout.py b/src/view/home/favoriteslayout.py index b286126..937f370 100644 --- a/src/jarabe/desktop/favoriteslayout.py +++ b/src/view/home/favoriteslayout.py @@ -24,9 +24,9 @@ import gtk import hippo from sugar.graphics import style +from sugar import activity -from jarabe.model import bundleregistry -from jarabe.desktop.grid import Grid +from view.home.grid import Grid _logger = logging.getLogger('FavoritesLayout') @@ -56,6 +56,7 @@ class FavoritesLayout(gobject.GObject, hippo.CanvasLayout): return 0 def append(self, icon, locked=False): + self.box.insert_sorted(icon, 0, self.compare_activities) if hasattr(icon, 'fixed_position'): relative_x, relative_y = icon.fixed_position if relative_x >= 0 and relative_y >= 0: @@ -68,6 +69,7 @@ class FavoritesLayout(gobject.GObject, hippo.CanvasLayout): def remove(self, icon): if icon in self.fixed_positions: del self.fixed_positions[icon] + self.box.remove(icon) def move_icon(self, icon, x, y, locked=False): if icon not in self.box.get_children(): @@ -76,7 +78,7 @@ class FavoritesLayout(gobject.GObject, hippo.CanvasLayout): if hasattr(icon, 'get_bundle_id') and hasattr(icon, 'get_version'): min_width_, width = self.box.get_width_request() min_height_, height = self.box.get_height_request(width) - registry = bundleregistry.get_registry() + registry = activity.get_registry() registry.set_activity_position( icon.get_bundle_id(), icon.get_version(), x * width / float(_BASE_SCALE), @@ -101,10 +103,6 @@ class RandomLayout(FavoritesLayout): profile_key = 'random-layout' """String used in profile to represent this view.""" - # TRANS: label for the freeform layout in the favorites view - palette_name = _('Freeform') - """String used to identify this layout in home view dropdown palette.""" - def __init__(self): FavoritesLayout.__init__(self) @@ -183,9 +181,6 @@ class RingLayout(FavoritesLayout): """Name of icon used in home view dropdown palette.""" profile_key = 'ring-layout' """String used in profile to represent this view.""" - # TRANS: label for the ring layout in the favorites view - palette_name = _('Ring') - """String used to identify this layout in home view dropdown palette.""" def __init__(self): FavoritesLayout.__init__(self) @@ -328,10 +323,6 @@ class SunflowerLayout(RingLayout): profile_key = 'spiral-layout' """String used in profile to represent this view.""" - # TRANS: label for the spiral layout in the favorites view - palette_name = _('Spiral') - """String used to identify this layout in home view dropdown palette.""" - def __init__(self): RingLayout.__init__(self) self.skipped_indices = [] @@ -343,13 +334,11 @@ class SunflowerLayout(RingLayout): def adjust_index(self, i): """Skip floret indices which end up outside the desired bounding box.""" for idx in self.skipped_indices: - if i < idx: - break + if i < idx: break i += 1 return i - def _calculate_position(self, radius, icon_size, oindex, children_count, - sin=math.sin, cos=math.cos): + def _calculate_position(self, radius, icon_size, oindex, children_count): """Calculate the position of sunflower floret number 'oindex'. If the result is outside the bounding box, use the next index which is inside the bounding box.""" @@ -370,9 +359,9 @@ class SunflowerLayout(RingLayout): # x,y are the top-left corner of the icon, so remove icon_size # from width/height to compensate. y has an extra GRID_CELL_SIZE/2 # removed to make room for the "active activity" icon. - x = r * cos(phi) + (width - icon_size) / 2 - y = r * sin(phi) + (height - icon_size - \ - (style.GRID_CELL_SIZE / 2) ) / 2 + x = r * math.cos(phi) + (width - icon_size) / 2 + y = r * math.sin(phi) + (height - icon_size - \ + (style.GRID_CELL_SIZE / 2) ) / 2 # skip allocations outside the allocation box. # give up once we can't fit @@ -395,27 +384,19 @@ class BoxLayout(RingLayout): profile_key = 'box-layout' """String used in profile to represent this view.""" - # TRANS: label for the box layout in the favorites view - palette_name = _('Box') - """String used to identify this layout in home view dropdown palette.""" - def __init__(self): RingLayout.__init__(self) - def _calculate_position(self, radius, icon_size, index, children_count, - sin=None, cos=None): + def _calculate_position(self, radius, icon_size, index, children_count): # use "orthogonal" versions of cos and sin in order to square the # circle and turn the 'ring view' into a 'box view' def cos_d(d): while d < 0: d += 360 - if d < 45: - return 1 - if d < 135: - return (90 - d) / 45. - if d < 225: - return -1 + if d < 45: return 1 + if d < 135: return (90 - d) / 45. + if d < 225: return -1 return cos_d(360 - d) # mirror around 180 cos = lambda r: cos_d(math.degrees(r)) @@ -436,10 +417,6 @@ class TriangleLayout(RingLayout): profile_key = 'triangle-layout' """String used in profile to represent this view.""" - # TRANS: label for the box layout in the favorites view - palette_name = _('Triangle') - """String used to identify this layout in home view dropdown palette.""" - def __init__(self): RingLayout.__init__(self) @@ -450,18 +427,15 @@ class TriangleLayout(RingLayout): RingLayout._calculate_radius_and_icon_size(self, children_count) return max(radius, _MINIMUM_RADIUS + style.MEDIUM_ICON_SIZE), icon_size - def _calculate_position(self, radius, icon_size, index, children_count, - sin=math.sin, cos=math.cos): + def _calculate_position(self, radius, icon_size, index, children_count): # tweak cos and sin in order to make the 'ring' into an equilateral # triangle. def cos_d(d): while d < -90: d += 360 - if d <= 30: - return (d + 90) / 120. - if d <= 90: - return (90 - d) / 60. + if d <= 30: return (d + 90) / 120. + if d <= 90: return (90 - d) / 60. return -cos_d(180 - d) # mirror around 90 sqrt_3 = math.sqrt(3) @@ -469,10 +443,8 @@ class TriangleLayout(RingLayout): def sin_d(d): while d < -90: d += 360 - if d <= 30: - return ((d + 90) / 120.) * sqrt_3 - 1 - if d <= 90: - return sqrt_3 - 1 + if d <= 30: return ((d + 90) / 120.) * sqrt_3 - 1 + if d <= 90: return sqrt_3 - 1 return sin_d(180 - d) # mirror around 90 cos = lambda r: cos_d(math.degrees(r)) diff --git a/src/jarabe/desktop/favoritesview.py b/src/view/home/favoritesview.py index 3af8d51..c1fce27 100644 --- a/src/jarabe/desktop/favoritesview.py +++ b/src/view/home/favoritesview.py @@ -17,7 +17,6 @@ import logging from gettext import gettext as _ -import gconf import gobject import gtk @@ -28,36 +27,36 @@ from sugar.graphics.palette import Palette from sugar.graphics.icon import Icon, CanvasIcon from sugar.graphics.menuitem import MenuItem from sugar.graphics.alert import Alert -from sugar.graphics.xocolor import XoColor -from sugar.activity import activityfactory - -from jarabe.view.palettes import JournalPalette -from jarabe.view.palettes import CurrentActivityPalette, ActivityPalette -from jarabe.model import shell -from jarabe.model import bundleregistry -from jarabe.controlpanel.gui import ControlPanel -from jarabe.model.session import get_session_manager - -from jarabe.desktop import schoolserver -from jarabe.desktop.schoolserver import RegisterError -from jarabe.desktop.myicon import MyIcon -from jarabe.desktop import favoriteslayout +from sugar.profile import get_profile +from sugar import activity + +import view.Shell +from view.palettes import JournalPalette +from view.palettes import CurrentActivityPalette, ActivityPalette +from view.home.MyIcon import MyIcon +from view.home import favoriteslayout +from model import shellmodel +from model.shellmodel import ShellModel +from hardware import schoolserver +from hardware.schoolserver import RegisterError +from controlpanel.gui import ControlPanel +from session import get_session_manager _logger = logging.getLogger('FavoritesView') _ICON_DND_TARGET = ('activity-icon', gtk.TARGET_SAME_WIDGET, 0) # enumerate the various layout types we will display in the dropdown palette. -# add a constant for your layout here, and add it to the LAYOUT_MAP to get +# add a constant for your layout here, and add it to the _LAYOUT_MAP to get # it to appear in the palette. RING_LAYOUT, BOX_LAYOUT, TRIANGLE_LAYOUT, SUNFLOWER_LAYOUT, RANDOM_LAYOUT = \ xrange(5) -LAYOUT_MAP = {RING_LAYOUT: favoriteslayout.RingLayout, - #BOX_LAYOUT: favoriteslayout.BoxLayout, - #TRIANGLE_LAYOUT: favoriteslayout.TriangleLayout, - #SUNFLOWER_LAYOUT: favoriteslayout.SunflowerLayout, - RANDOM_LAYOUT: favoriteslayout.RandomLayout} +_LAYOUT_MAP = {RING_LAYOUT: favoriteslayout.RingLayout, + #BOX_LAYOUT: favoriteslayout.BoxLayout, + #TRIANGLE_LAYOUT: favoriteslayout.TriangleLayout, + #SUNFLOWER_LAYOUT: favoriteslayout.SunflowerLayout, + RANDOM_LAYOUT: favoriteslayout.RandomLayout} """Map numeric layout identifiers to uninstantiated subclasses of `FavoritesLayout` which implement the layouts. Additional information about the layout can be accessed with fields of the class.""" @@ -67,36 +66,32 @@ class FavoritesView(hippo.Canvas): __gsignals__ = { 'erase-activated' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([str])) + gobject.TYPE_NONE, ([str])), } def __init__(self, **kwargs): - logging.debug('STARTUP: Loading the favorites view') - gobject.GObject.__init__(self, **kwargs) # DND stuff self._pressed_button = None self._press_start_x = None self._press_start_y = None - self._hot_x = None - self._hot_y = None self._last_clicked_icon = None self._box = hippo.CanvasBox() self._box.props.background_color = style.COLOR_WHITE.get_int() self.set_root(self._box) - self._my_icon = _MyIcon(style.XLARGE_ICON_SIZE) - self._my_icon.connect('register-activate', self.__register_activate_cb) - self._box.append(self._my_icon) - - self._current_activity = CurrentActivityIcon() - self._box.append(self._current_activity) - + self._my_icon = None + self._current_activity = None self._layout = None self._alert = None + registry = activity.get_registry() + registry.connect('activity-added', self.__activity_added_cb) + registry.connect('activity-removed', self.__activity_removed_cb) + registry.connect('activity-changed', self.__activity_changed_cb) + # More DND stuff self.add_events(gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.POINTER_MOTION_HINT_MASK) @@ -107,34 +102,23 @@ class FavoritesView(hippo.Canvas): self.connect('drag-drop', self.__drag_drop_cb) self.connect('drag-data-received', self.__drag_data_received_cb) - gobject.idle_add(self.__connect_to_bundle_registry_cb) - - def __connect_to_bundle_registry_cb(self): - registry = bundleregistry.get_registry() - - for info in registry: - if registry.is_bundle_favorite(info.get_bundle_id(), - info.get_activity_version()): - self._add_activity(info) - - registry.connect('bundle-added', self.__activity_added_cb) - registry.connect('bundle-removed', self.__activity_removed_cb) - registry.connect('bundle-changed', self.__activity_changed_cb) - def _add_activity(self, activity_info): icon = ActivityIcon(activity_info) icon.connect('erase-activated', self.__erase_activated_cb) icon.props.size = style.STANDARD_ICON_SIZE - self._box.insert_sorted(icon, 0, self._layout.compare_activities) self._layout.append(icon) def __erase_activated_cb(self, activity_icon, bundle_id): self.emit('erase-activated', bundle_id) + def _get_activities_cb(self, activity_list): + for info in activity_list: + if info.favorite and info.bundle_id != "org.laptop.JournalActivity": + self._add_activity(info) + def __activity_added_cb(self, activity_registry, activity_info): - registry = bundleregistry.get_registry() - if registry.is_bundle_favorite(activity_info.get_bundle_id(), - activity_info.get_activity_version()): + if activity_info.favorite and \ + activity_info.bundle_id != "org.laptop.JournalActivity": self._add_activity(activity_info) def _find_activity_icon(self, bundle_id, version): @@ -145,23 +129,19 @@ class FavoritesView(hippo.Canvas): return None def __activity_removed_cb(self, activity_registry, activity_info): - icon = self._find_activity_icon(activity_info.get_bundle_id(), - activity_info.get_activity_version()) + icon = self._find_activity_icon(activity_info.bundle_id, + activity_info.version) if icon is not None: self._layout.remove(icon) - self._box.remove(icon) def __activity_changed_cb(self, activity_registry, activity_info): - if activity_info.get_bundle_id() == 'org.laptop.JournalActivity': + if activity_info.bundle_id == 'org.laptop.JournalActivity': return - icon = self._find_activity_icon(activity_info.get_bundle_id(), - activity_info.get_activity_version()) + icon = self._find_activity_icon(activity_info.bundle_id, + activity_info.version) if icon is not None: self._box.remove(icon) - - registry = bundleregistry.get_registry() - if registry.is_bundle_favorite(activity_info.get_bundle_id(), - activity_info.get_activity_version()): + if activity_info.favorite: self._add_activity(activity_info) def do_size_allocate(self, allocation): @@ -184,6 +164,12 @@ class FavoritesView(hippo.Canvas): hippo.Canvas.do_size_allocate(self, allocation) + def enable_xo_palette(self): + self._my_icon.enable_palette() + if self._my_icon.register_menu is not None: + self._my_icon.register_menu.connect('activate', + self.__register_activate_cb) + # TODO: Dnd methods. This should be merged somehow inside hippo-canvas. def __button_press_event_cb(self, widget, event): if event.button == 1 and event.type == gtk.gdk.BUTTON_PRESS: @@ -236,9 +222,8 @@ class FavoritesView(hippo.Canvas): # TODO: we should get the pixbuf from the widget, so it has colors, etc pixbuf = gtk.gdk.pixbuf_new_from_file(icon_file_name) - self._hot_x = pixbuf.props.width / 2 - self._hot_y = pixbuf.props.height / 2 - context.set_icon_pixbuf(pixbuf, self._hot_x, self._hot_y) + hot_spot = style.zoom(10) + context.set_icon_pixbuf(pixbuf, hot_spot, hot_spot) def __drag_motion_cb(self, widget, context, x, y, time): if self._last_clicked_icon is not None: @@ -251,14 +236,11 @@ class FavoritesView(hippo.Canvas): if self._last_clicked_icon is not None: self.drag_get_data(context, _ICON_DND_TARGET[0]) - self._layout.move_icon(self._last_clicked_icon, - x - self._hot_x, y - self._hot_y) + self._layout.move_icon(self._last_clicked_icon, x, y) self._pressed_button = None self._press_start_x = None self._press_start_y = None - self._hot_x = None - self._hot_y = None self._last_clicked_icon = None return True @@ -270,33 +252,28 @@ class FavoritesView(hippo.Canvas): context.drop_finish(success=True, time=time) def _set_layout(self, layout): - if layout not in LAYOUT_MAP: + if layout not in _LAYOUT_MAP: raise ValueError('Unknown favorites layout: %r' % layout) + if type(self._layout) != _LAYOUT_MAP[layout]: + self._box.clear() + self._layout = _LAYOUT_MAP[layout]() + self._box.set_layout(self._layout) - if type(self._layout) == LAYOUT_MAP[layout]: - return + self._my_icon = _MyIcon(style.XLARGE_ICON_SIZE) + self._layout.append(self._my_icon, locked=True) - self._layout = LAYOUT_MAP[layout]() - self._box.set_layout(self._layout) + self._current_activity = CurrentActivityIcon() + self._layout.append(self._current_activity, locked=True) - #TODO: compatibility hack while sort() gets added to the hippo python - # bindings - if hasattr(self._box, 'sort'): - self._box.sort(self._layout.compare_activities) + registry = activity.get_registry() + registry.get_activities_async(reply_handler=self._get_activities_cb) - for icon in self._box.get_children(): - if icon not in [self._my_icon, self._current_activity]: - self._layout.append(icon) - - self._layout.append(self._my_icon, locked=True) - self._layout.append(self._current_activity, locked=True) - - if self._layout.allow_dnd(): - self.drag_source_set(0, [], 0) - self.drag_dest_set(0, [], 0) - else: - self.drag_source_unset() - self.drag_dest_unset() + if self._layout.allow_dnd(): + self.drag_source_set(0, [], 0) + self.drag_dest_set(0, [], 0) + else: + self.drag_source_unset() + self.drag_dest_unset() layout = property(None, _set_layout) @@ -311,7 +288,7 @@ class FavoritesView(hippo.Canvas): self._box.remove(self._alert) self._alert = None - def __register_activate_cb(self, icon): + def __register_activate_cb(self, menuitem): alert = Alert() try: schoolserver.register_laptop() @@ -320,9 +297,9 @@ class FavoritesView(hippo.Canvas): alert.props.msg = _('%s') % e else: alert.props.title = _('Registration Successful') - alert.props.msg = _('You are now registered ' \ - 'with your school server.') - self._my_icon.remove_register_menu() + alert.props.msg = _('You are now registered with your school server.') + palette = self._my_icon.get_palette() + palette.menu.remove(menuitem) ok_icon = Icon(icon_name='dialog-ok') alert.add_button(gtk.RESPONSE_OK, _('Ok'), ok_icon) @@ -338,31 +315,26 @@ class ActivityIcon(CanvasIcon): __gsignals__ = { 'erase-activated' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([str])) + gobject.TYPE_NONE, ([str])), } def __init__(self, activity_info): - CanvasIcon.__init__(self, cache=True, - file_name=activity_info.get_icon()) - + CanvasIcon.__init__(self, cache=True, file_name=activity_info.icon) self._activity_info = activity_info self._uncolor() self.connect('hovering-changed', self.__hovering_changed_event_cb) self.connect('button-release-event', self.__button_release_event_cb) - client = gconf.client_get_default() - self._xocolor = XoColor(client.get_string("/desktop/sugar/user/color")) - def create_palette(self): palette = ActivityPalette(self._activity_info) palette.connect('erase-activated', self.__erase_activated_cb) return palette def __erase_activated_cb(self, palette): - self.emit('erase-activated', self._activity_info.get_bundle_id()) + self.emit('erase-activated', self._activity_info.bundle_id) def _color(self): - self.props.xo_color = self._xocolor + self.props.xo_color = get_profile().color def _uncolor(self): self.props.stroke_color = style.COLOR_BUTTON_GREY.get_svg() @@ -377,15 +349,14 @@ class ActivityIcon(CanvasIcon): def __button_release_event_cb(self, icon, event): self.palette.popdown(immediate=True) self._uncolor() - - activityfactory.create(self._activity_info) + view.Shell.get_instance().start_activity(self._activity_info.bundle_id) def get_bundle_id(self): - return self._activity_info.get_bundle_id() + return self._activity_info.bundle_id bundle_id = property(get_bundle_id, None) def get_version(self): - return self._activity_info.get_activity_version() + return self._activity_info.version version = property(get_version, None) def _get_installation_time(self): @@ -399,11 +370,10 @@ class ActivityIcon(CanvasIcon): class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem): def __init__(self): CanvasIcon.__init__(self, cache=True) - self._home_model = shell.get_model() - self._home_activity = self._home_model.get_active_activity() + self._home_model = shellmodel.get_instance().get_home() - if self._home_activity is not None: - self._update() + if self._home_model.get_active_activity() is not None: + self._update(self._home_model.get_active_activity()) self._home_model.connect('active-activity-changed', self.__active_activity_changed_cb) @@ -413,55 +383,41 @@ class CurrentActivityIcon(CanvasIcon, hippo.CanvasItem): def __button_release_event_cb(self, icon, event): self._home_model.get_active_activity().get_window().activate(1) - def _update(self): - self.props.file_name = self._home_activity.get_icon_path() - self.props.xo_color = self._home_activity.get_icon_color() + def _update(self, home_activity): + self.props.file_name = home_activity.get_icon_path() + self.props.xo_color = home_activity.get_icon_color() self.props.size = style.STANDARD_ICON_SIZE if self.palette is not None: self.palette.destroy() self.palette = None - def create_palette(self): - if self._home_activity.is_journal(): - palette = JournalPalette(self._home_activity) + if home_activity.is_journal(): + palette = JournalPalette(home_activity) else: - palette = CurrentActivityPalette(self._home_activity) - return palette + palette = CurrentActivityPalette(home_activity) + self.set_palette(palette) def __active_activity_changed_cb(self, home_model, home_activity): - self._home_activity = home_activity - self._update() + self._update(home_activity) class _MyIcon(MyIcon): - __gtype_name__ = 'SugarFavoritesMyIcon' - - __gsignals__ = { - 'register-activate' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) - } def __init__(self, scale): MyIcon.__init__(self, scale) self._power_manager = None - self._palette_enabled = False - self._register_menu = None - - def create_palette(self): - if not self._palette_enabled: - self._palette_enabled = True - return - - client = gconf.client_get_default() - nick = client.get_string("/desktop/sugar/user/nick") - color = XoColor(client.get_string("/desktop/sugar/user/color")) + self._profile = get_profile() + self.register_menu = None + def enable_palette(self): palette_icon = Icon(icon_name='computer-xo', icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR, - xo_color=color) - palette = Palette(nick, icon=palette_icon) + xo_color=self._profile.color) + palette = Palette(self._profile.nick_name, + #secondary_text='Sample secondary label', + icon=palette_icon) - item = MenuItem(_('Settings'), 'preferences-system') + item = MenuItem(_('Control Panel'), 'preferences-system') item.connect('activate', self.__controlpanel_activate_cb) palette.menu.append(item) item.show() @@ -476,14 +432,12 @@ class _MyIcon(MyIcon): palette.menu.append(item) item.show() - backup_url = client.get_string('/desktop/sugar/backup_url') - if not backup_url: - self._register_menu = MenuItem(_('Register'), 'media-record') - self._register_menu.connect('activate', self.__register_activate_cb) - palette.menu.append(self._register_menu) - self._register_menu.show() - - return palette + if not self._profile.is_registered(): + self.register_menu = MenuItem(_('Register'), 'media-record') + palette.menu.append(self.register_menu) + self.register_menu.show() + + self.set_palette(palette) def _reboot_activate_cb(self, menuitem): session_manager = get_session_manager() @@ -500,10 +454,3 @@ class _MyIcon(MyIcon): panel = ControlPanel() panel.set_transient_for(self.get_toplevel()) panel.show() - - def __register_activate_cb(self, menuitem): - self.emit('register-activate') - - def remove_register_menu(self): - self.palette.remove(self._register_menu) - diff --git a/src/jarabe/desktop/grid.py b/src/view/home/grid.py index eb7fabc..97f9229 100644 --- a/src/jarabe/desktop/grid.py +++ b/src/view/home/grid.py @@ -156,7 +156,7 @@ class Grid(_sugarext.Grid): return weight def __solve_collisions_cb(self): - for i_ in range(_MAX_COLLISIONS_PER_REFRESH): + for i in range(_MAX_COLLISIONS_PER_REFRESH): collision = self._collisions.pop(0) old_rect = self._child_rects[collision] diff --git a/src/jarabe/desktop/proc_smaps.py b/src/view/home/proc_smaps.py index 090a4cf..090a4cf 100755 --- a/src/jarabe/desktop/proc_smaps.py +++ b/src/view/home/proc_smaps.py diff --git a/src/jarabe/desktop/snowflakelayout.py b/src/view/home/snowflakelayout.py index 5782cff..5782cff 100644 --- a/src/jarabe/desktop/snowflakelayout.py +++ b/src/view/home/snowflakelayout.py diff --git a/src/jarabe/desktop/spreadlayout.py b/src/view/home/spreadlayout.py index ffc5bc7..0faabca 100644 --- a/src/jarabe/desktop/spreadlayout.py +++ b/src/view/home/spreadlayout.py @@ -20,7 +20,7 @@ import gtk from sugar.graphics import style -from jarabe.desktop.grid import Grid +from view.home.grid import Grid _CELL_SIZE = 4.0 diff --git a/src/jarabe/desktop/transitionbox.py b/src/view/home/transitionbox.py index a554415..fb351f8 100644 --- a/src/jarabe/desktop/transitionbox.py +++ b/src/view/home/transitionbox.py @@ -20,7 +20,7 @@ import gobject from sugar.graphics import style from sugar.graphics import animator -from jarabe.desktop.myicon import MyIcon +from view.home.MyIcon import MyIcon class _Animation(animator.Animation): def __init__(self, icon, start_size, end_size): @@ -74,10 +74,12 @@ class TransitionBox(hippo.Canvas): self._box.props.background_color = style.COLOR_WHITE.get_int() self.set_root(self._box) + self._size = style.XLARGE_ICON_SIZE + self._layout = _Layout() self._box.set_layout(self._layout) - self._my_icon = MyIcon(style.XLARGE_ICON_SIZE) + self._my_icon = MyIcon(self._size) self._box.append(self._my_icon) self._animator = animator.Animator(0.3) @@ -86,9 +88,10 @@ class TransitionBox(hippo.Canvas): def _animation_completed_cb(self, anim): self.emit('completed') - def start_transition(self, start_size, end_size): - self._my_icon.props.size = start_size - + def set_size(self, size): self._animator.remove_all() - self._animator.add(_Animation(self._my_icon, start_size, end_size)) + self._animator.add(_Animation(self._my_icon, self._size, size)) self._animator.start() + + self._size = size + diff --git a/src/jarabe/view/keyhandler.py b/src/view/keyhandler.py index 4a50e70..993d09d 100644 --- a/src/jarabe/view/keyhandler.py +++ b/src/view/keyhandler.py @@ -19,30 +19,26 @@ import signal import logging import subprocess import errno -import traceback -import sys import dbus import gtk from sugar._sugarext import KeyGrabber -from jarabe.model import screen -from jarabe.model import sound -from jarabe.model import shell -from jarabe.view.tabbinghandler import TabbingHandler -from jarabe.model.shell import ShellModel -from jarabe import config +from hardware import hardwaremanager +import view.Shell +from view.tabbinghandler import TabbingHandler +from model.shellmodel import ShellModel _BRIGHTNESS_STEP = 2 -_VOLUME_STEP = sound.VOLUME_STEP +_VOLUME_STEP = hardwaremanager.VOL_CHANGE_INCREMENT_RECOMMENDATION _BRIGHTNESS_MAX = 15 _VOLUME_MAX = 100 _TABBING_MODIFIER = gtk.gdk.MOD1_MASK _actions_table = { 'F1' : 'zoom_mesh', - 'F2' : 'zoom_group', + 'F2' : 'zoom_friends', 'F3' : 'zoom_home', 'F4' : 'zoom_activity', 'F9' : 'brightness_down', @@ -53,6 +49,7 @@ _actions_table = { 'F12' : 'volume_up', '<alt>F11' : 'volume_min', '<alt>F12' : 'volume_max', + '<alt>1' : 'screenshot', '0x93' : 'frame', '0xEB' : 'rotate', '<alt>Tab' : 'next_window', @@ -76,8 +73,7 @@ SPEECH_DBUS_PATH = '/org/laptop/Speech' SPEECH_DBUS_INTERFACE = 'org.laptop.Speech' class KeyHandler(object): - def __init__(self, frame): - self._frame = frame + def __init__(self): self._screen_rotation = 0 self._key_pressed = None self._keycode_pressed = 0 @@ -90,49 +86,39 @@ class KeyHandler(object): self._key_grabber.connect('key-released', self._key_released_cb) - self._tabbing_handler = TabbingHandler(self._frame, _TABBING_MODIFIER) - - for f in os.listdir(os.path.join(config.ext_path, 'globalkey')): - if f.endswith('.py') and not f.startswith('__'): - module_name = f[:-3] - try: - logging.debug('Loading module %r' % module_name) - module = __import__('globalkey.' + module_name, globals(), - locals(), [module_name]) - for key in module.BOUND_KEYS: - if key in _actions_table: - raise ValueError('Key %r is already bound' % key) - _actions_table[key] = module - except Exception: - logging.error('Exception while loading extension:\n' + \ - ''.join(traceback.format_exception(*sys.exc_info()))) - - self._key_grabber.grab_keys(_actions_table.keys()) + self._tabbing_handler = TabbingHandler(_TABBING_MODIFIER) + + for key in _actions_table.keys(): + self._key_grabber.grab(key) def _change_volume(self, step=None, value=None): + hw_manager = hardwaremanager.get_manager() + if step is not None: - volume = sound.get_volume() + step + volume = hw_manager.get_volume() + step elif value is not None: volume = value volume = min(max(0, volume), _VOLUME_MAX) - sound.set_volume(volume) - sound.set_muted(volume == 0) + hw_manager.set_volume(volume) + hw_manager.set_muted(volume == 0) def _change_brightness(self, step=None, value=None): + hw_manager = hardwaremanager.get_manager() + if step is not None: - level = screen.get_display_brightness() + step + level = hw_manager.get_display_brightness() + step elif value is not None: level = value level = min(max(0, level), _BRIGHTNESS_MAX) - screen.set_display_brightness(level) + hw_manager.set_display_brightness(level) if level == 0: - screen.set_display_mode(screen.B_AND_W_MODE) + hw_manager.set_display_mode(hardwaremanager.B_AND_W_MODE) else: - screen.set_display_mode(screen.COLOR_MODE) + hw_manager.set_display_mode(hardwaremanager.COLOR_MODE) def _get_speech_proxy(self): if self._speech_proxy is None: @@ -163,23 +149,19 @@ class KeyHandler(object): self._tabbing_handler.next_activity() def handle_close_window(self): - active_activity = shell.get_model().get_active_activity() - if active_activity.is_journal(): - return - - active_activity.get_window().close() + view.Shell.get_instance().close_current_activity() def handle_zoom_mesh(self): - shell.get_model().zoom_level = ShellModel.ZOOM_MESH + view.Shell.get_instance().set_zoom_level(ShellModel.ZOOM_MESH) - def handle_zoom_group(self): - shell.get_model().zoom_level = ShellModel.ZOOM_GROUP + def handle_zoom_friends(self): + view.Shell.get_instance().set_zoom_level(ShellModel.ZOOM_FRIENDS) def handle_zoom_home(self): - shell.get_model().zoom_level = ShellModel.ZOOM_HOME + view.Shell.get_instance().set_zoom_level(ShellModel.ZOOM_HOME) def handle_zoom_activity(self): - shell.get_model().zoom_level = ShellModel.ZOOM_ACTIVITY + view.Shell.get_instance().set_zoom_level(ShellModel.ZOOM_ACTIVITY) def handle_brightness_max(self): self._change_brightness(value=_BRIGHTNESS_MAX) @@ -205,8 +187,12 @@ class KeyHandler(object): def handle_volume_down(self): self._change_volume(step=-_VOLUME_STEP) + def handle_screenshot(self): + view.Shell.get_instance().take_screenshot() + def handle_frame(self): - self._frame.notify_key_press() + view.Shell.get_instance().get_frame().notify_key_press() + def handle_rotate(self): """ @@ -258,7 +244,7 @@ class KeyHandler(object): bus = dbus.SessionBus() obj = bus.get_object(J_DBUS_SERVICE, J_DBUS_PATH) journal = dbus.Interface(obj, J_DBUS_INTERFACE) - journal.FocusSearch() + journal.FocusSearch({}) def handle_open_search(self): self.focus_journal_search() @@ -279,13 +265,8 @@ class KeyHandler(object): self._tabbing_handler.stop() return True - if hasattr(action, 'handle_key_press'): - action.handle_key_press(key) - elif isinstance(action, basestring): - method = getattr(self, 'handle_' + action) - method() - else: - raise TypeError('Invalid action %r' % action) + method = getattr(self, 'handle_' + action) + method() return True else: @@ -307,13 +288,3 @@ class KeyHandler(object): return True return False -_instance = None - -def setup(frame): - global _instance - - if _instance: - del _instance - - _instance = KeyHandler(frame) - diff --git a/src/jarabe/view/launcher.py b/src/view/launchwindow.py index cc9e2a7..d954abc 100644 --- a/src/jarabe/view/launcher.py +++ b/src/view/launchwindow.py @@ -14,8 +14,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import logging - import gtk import hippo import gobject @@ -25,8 +23,8 @@ from sugar.graphics import style from sugar.graphics import animator from sugar.graphics.xocolor import XoColor -from jarabe.model import shell -from jarabe.view.pulsingicon import CanvasPulsingIcon +from model import shellmodel +from view.pulsingicon import CanvasPulsingIcon class LaunchWindow(hippo.CanvasWindow): def __init__(self, home_activity): @@ -77,14 +75,13 @@ class LaunchBox(hippo.CanvasBox): self._animator = animator.Animator(1.0) - self._home = shell.get_model() + self._home = shellmodel.get_instance().get_home() self._home.connect('active-activity-changed', self.__active_activity_changed_cb) self.connect('destroy', self.__destroy_cb) def __destroy_cb(self, box): - self._activity_icon.props.pulsing = False self._home.disconnect_by_func(self.__active_activity_changed_cb) def zoom_in(self): @@ -114,37 +111,3 @@ class _Animation(animator.Animation): def next_frame(self, current): d = (self.end_size - self.start_size) * current self._icon.props.size = self.start_size + d - -_launchers = {} - -def setup(): - model = shell.get_model() - model.connect('launch-started', __launch_started_cb) - model.connect('launch-failed', __launch_failed_cb) - model.connect('launch-completed', __launch_completed_cb) - -def __launch_started_cb(home_model, home_activity): - if home_activity.is_journal(): - return - - launch_window = LaunchWindow(home_activity) - launch_window.show() - - _launchers[home_activity.get_activity_id()] = launch_window - -def __launch_failed_cb(home_model, home_activity): - if not home_activity.is_journal(): - _destroy_launcher(home_activity) - -def __launch_completed_cb(home_model, home_activity): - if not home_activity.is_journal(): - _destroy_launcher(home_activity) - -def _destroy_launcher(home_activity): - activity_id = home_activity.get_activity_id() - - if activity_id in _launchers: - _launchers[activity_id].destroy() - del _launchers[activity_id] - else: - logging.error('Launcher for %s is missing' % activity_id) diff --git a/src/jarabe/view/palettes.py b/src/view/palettes.py index 5ba2cc2..416ff0f 100644 --- a/src/jarabe/view/palettes.py +++ b/src/view/palettes.py @@ -17,20 +17,20 @@ import os import statvfs from gettext import gettext as _ -import gconf import gobject import gtk from sugar import env +from sugar import profile +from sugar import activity from sugar.graphics.palette import Palette from sugar.graphics.menuitem import MenuItem from sugar.graphics.icon import Icon from sugar.graphics import style from sugar.graphics.xocolor import XoColor -from sugar.activity import activityfactory -from jarabe.model import bundleregistry +import view.Shell class BasePalette(Palette): def __init__(self, home_activity): @@ -86,26 +86,20 @@ class ActivityPalette(Palette): __gsignals__ = { 'erase-activated' : (gobject.SIGNAL_RUN_FIRST, - gobject.TYPE_NONE, ([])) + gobject.TYPE_NONE, ([])), } def __init__(self, activity_info): - client = gconf.client_get_default() - color = XoColor(client.get_string("/desktop/sugar/user/color")) - activity_icon = Icon(file=activity_info.get_icon(), - xo_color=color, + activity_icon = Icon(file=activity_info.icon, + xo_color=profile.get_color(), icon_size=gtk.ICON_SIZE_LARGE_TOOLBAR) - Palette.__init__(self, primary_text=activity_info.get_name(), + Palette.__init__(self, primary_text=activity_info.name, icon=activity_icon) - registry = bundleregistry.get_registry() - - self._bundle = activity_info - self._bundle_id = activity_info.get_bundle_id() - self._version = activity_info.get_activity_version() - self._favorite = registry.is_bundle_favorite(self._bundle_id, - self._version) + self._bundle_id = activity_info.bundle_id + self._version = activity_info.version + self._favorite = activity_info.favorite menu_item = MenuItem(_('Start'), 'activity-start') menu_item.connect('activate', self.__start_activate_cb) @@ -128,8 +122,8 @@ class ActivityPalette(Palette): self.menu.append(menu_item) menu_item.show() - registry = bundleregistry.get_registry() - self._activity_changed_sid = registry.connect('bundle_changed', + registry = activity.get_registry() + self._activity_changed_sid = registry.connect('activity_changed', self.__activity_changed_cb) self._update_favorite_item() @@ -146,26 +140,23 @@ class ActivityPalette(Palette): style.COLOR_TRANSPARENT.get_svg())) else: label.set_text(_('Make favorite')) - client = gconf.client_get_default() - xo_color = XoColor(client.get_string("/desktop/sugar/user/color")) + xo_color = profile.get_color() self._favorite_icon.props.xo_color = xo_color def __start_activate_cb(self, menu_item): - activityfactory.create(self._bundle) + view.Shell.get_instance().start_activity(self._bundle_id) def __change_favorite_activate_cb(self, menu_item): - registry = bundleregistry.get_registry() - registry.set_bundle_favorite(self._bundle_id, - self._version, - not self._favorite) + registry = activity.get_registry() + registry.set_activity_favorite(self._bundle_id, + self._version, + not self._favorite) def __activity_changed_cb(self, activity_registry, activity_info): - if activity_info.get_bundle_id() == self._bundle_id and \ - activity_info.get_activity_version() == self._version: - registry = bundleregistry.get_registry() - self._favorite = registry.is_bundle_favorite(self._bundle_id, - self._version) + if activity_info.bundle_id == self._bundle_id and \ + activity_info.version == self._version: + self._favorite = activity_info.favorite self._update_favorite_item() def __erase_activate_cb(self, menu_item): diff --git a/src/view/pulsingicon.py b/src/view/pulsingicon.py new file mode 100644 index 0000000..c733043 --- /dev/null +++ b/src/view/pulsingicon.py @@ -0,0 +1,239 @@ +# 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 + +import math + +import gobject + +from sugar.graphics.icon import Icon, CanvasIcon +from sugar.graphics.style import Color + +_INTERVAL = 100 +_STEP = math.pi / 10 # must be a fraction of pi, for clean caching + +def _get_as_rgba(self, html_color): + if html_color == 'none': + return Color('#FFFFFF', alpha=1.0).get_rgba() + else: + return Color(html_color).get_rgba() + +def _update_colors(self): + if self._pulsing: + base_stroke = self._get_as_rgba(self._base_color.get_stroke_color()) + pulse_stroke = self._get_as_rgba(self._pulse_color.get_stroke_color()) + base_fill = self._get_as_rgba(self._base_color.get_fill_color()) + pulse_fill = self._get_as_rgba(self._pulse_color.get_fill_color()) + + self.props.stroke_color = \ + self._get_color(base_stroke, pulse_stroke).get_svg() + self.props.fill_color = \ + self._get_color(base_fill, pulse_fill).get_svg() + else: + self.props.xo_color = self._base_color + +def _get_color(self, orig_color, target_color): + next_point = (orig_color[0] + + self._level * (target_color[0] - orig_color[0]), + orig_color[1] + + self._level * (target_color[1] - orig_color[1]), + orig_color[2] + + self._level * (target_color[2] - orig_color[2])) + return Color('#%02x%02x%02x' % (int(next_point[0] * 255), + int(next_point[1] * 255), + int(next_point[2] * 255))) + +class PulsingIcon(Icon): + __gtype_name__ = 'SugarPulsingIcon' + + __gproperties__ = { + 'base-color' : (object, None, None, gobject.PARAM_READWRITE), + 'pulse-color' : (object, None, None, gobject.PARAM_READWRITE), + 'pulsing' : (bool, None, None, False, gobject.PARAM_READWRITE), + 'paused' : (bool, None, None, False, gobject.PARAM_READWRITE) + } + + def __init__(self, **kwargs): + self._base_color = None + self._pulse_color = None + self._pulse_hid = None + self._paused = False + self._pulsing = False + self._level = 0 + self._phase = 0 + + Icon.__init__(self, **kwargs) + + self._palette = None + self.connect('destroy', self.__destroy_cb) + + def __destroy_cb(self, icon): + if self._palette is not None: + self._palette.destroy() + + # Hack for sharing code between CanvasPulsingIcon and PulsingIcon + _get_as_rgba = _get_as_rgba + _update_colors = _update_colors + _get_color = _get_color + + def _start_pulsing(self, restart=False): + if restart: + self._phase = 0 + if self._pulse_hid is None: + self._pulse_hid = gobject.timeout_add(_INTERVAL, self.__pulse_cb) + + def _stop_pulsing(self): + if self._pulse_hid is not None: + gobject.source_remove(self._pulse_hid) + self._pulse_hid = None + self.props.xo_color = self._base_color + + def __pulse_cb(self): + self._phase += _STEP + self._level = (math.sin(self._phase) + 1) / 2 + self._update_colors() + + return True + + def do_set_property(self, pspec, value): + if pspec.name == 'base-color': + if self._base_color != value: + self._base_color = value + self._update_colors() + elif pspec.name == 'pulse-color': + if self._pulse_color != value: + self._pulse_color = value + self._update_colors() + elif pspec.name == 'pulsing': + if self._pulsing != value: + self._pulsing = value + if self._pulsing: + self._start_pulsing(restart=True) + else: + self._stop_pulsing() + elif pspec.name == 'paused': + if self._paused != value: + self._paused = value + if self._paused: + self._stop_pulsing() + else: + self._start_pulsing(restart=False) + else: + Icon.do_set_property(self, pspec, value) + + def do_get_property(self, pspec): + if pspec.name == 'base-color': + return self._base_color + elif pspec.name == 'pulse-color': + return self._pulse_color + elif pspec.name == 'pulsing': + return self._pulsing + elif pspec.name == 'paused': + return self._paused + else: + return Icon.do_get_property(self, pspec) + + def _get_palette(self): + return self._palette + + def _set_palette(self, palette): + if self._palette is not None: + self._palette.props.invoker = None + self._palette = palette + + palette = property(_get_palette, _set_palette) + +class CanvasPulsingIcon(CanvasIcon): + __gtype_name__ = 'SugarCanvasPulsingIcon' + + __gproperties__ = { + 'base-color' : (object, None, None, gobject.PARAM_WRITABLE), + 'pulse-color' : (object, None, None, gobject.PARAM_WRITABLE), + 'pulsing' : (bool, None, None, False, gobject.PARAM_WRITABLE), + 'paused' : (bool, None, None, False, gobject.PARAM_WRITABLE) + } + + def __init__(self, **kwargs): + self._base_color = None + self._pulse_color = None + self._pulse_hid = None + self._paused = False + self._pulsing = False + self._level = 0 + self._phase = 0 + + CanvasIcon.__init__(self, **kwargs) + + # Hack for sharing code between CanvasPulsingIcon and PulsingIcon + _get_as_rgba = _get_as_rgba + _update_colors = _update_colors + _get_color = _get_color + + def _start_pulsing(self, restart=False): + if restart: + self._phase = 0 + if self._pulse_hid is None: + self._pulse_hid = gobject.timeout_add(_INTERVAL, self.__pulse_cb) + + def _stop_pulsing(self): + if self._pulse_hid is not None: + gobject.source_remove(self._pulse_hid) + self._pulse_hid = None + self.props.xo_color = self._base_color + + def __pulse_cb(self): + self._phase += _STEP + self._level = (math.sin(self._phase) + 1) / 2 + self._update_colors() + + return True + + def do_set_property(self, pspec, value): + if pspec.name == 'base-color': + if self._base_color != value: + self._base_color = value + self._update_colors() + elif pspec.name == 'pulse-color': + if self._pulse_color != value: + self._pulse_color = value + self._update_colors() + elif pspec.name == 'pulsing': + if self._pulsing != value: + self._pulsing = value + if self._pulsing: + self._start_pulsing(restart=True) + else: + self._stop_pulsing() + elif pspec.name == 'paused': + if self._paused != value: + self._paused = value + if self._paused: + self._stop_pulsing() + else: + self._start_pulsing(restart=False) + else: + CanvasIcon.do_set_property(self, pspec, value) + + def do_get_property(self, pspec): + if pspec.name == 'base-color': + return self._base_color + elif pspec.name == 'pulse-color': + return self._pulse_color + elif pspec.name == 'pulsing': + return self._pulsing + elif pspec.name == 'paused': + return self._paused + else: + return CanvasIcon.do_get_property(self, pspec) diff --git a/src/jarabe/view/tabbinghandler.py b/src/view/tabbinghandler.py index b1c85c6..e3153b0 100644 --- a/src/jarabe/view/tabbinghandler.py +++ b/src/view/tabbinghandler.py @@ -18,16 +18,18 @@ import logging import gtk import gobject -from jarabe.model import shell +import view.Shell +from view.frame import frame +from model import shellmodel _RAISE_DELAY = 250 class TabbingHandler(object): - def __init__(self, frame, modifier): - self._frame = frame + def __init__(self, modifier): self._tabbing = False self._modifier = modifier self._timeout = None + self._frame = frame.get_instance() def _start_tabbing(self): if not self._tabbing: @@ -55,6 +57,8 @@ class TabbingHandler(object): self._tabbing = False else: + shell = view.Shell.get_instance() + self._frame.show(self._frame.MODE_NON_INTERACTIVE) def __timeout_cb(self): @@ -72,7 +76,8 @@ class TabbingHandler(object): self._timeout = None def _activate_current(self): - home_model = shell.get_model() + shell_model = shellmodel.get_instance() + home_model = shell_model.get_home() activity = home_model.get_tabbing_activity() if activity and activity.get_window(): activity.get_window().activate(1) @@ -85,20 +90,21 @@ class TabbingHandler(object): first_switch = False if self._tabbing: - shell_model = shell.get_model() - zoom_level = shell_model.zoom_level - zoom_activity = (zoom_level == shell.ShellModel.ZOOM_ACTIVITY) + shell_model = shellmodel.get_instance() + home_model = shell_model.get_home() + zoom_level = shell_model.get_zoom_level() + zoom_activity = (zoom_level == shellmodel.ShellModel.ZOOM_ACTIVITY) if not zoom_activity and first_switch: - activity = shell_model.get_active_activity() + activity = home_model.get_active_activity() else: - activity = shell_model.get_tabbing_activity() - activity = shell_model.get_next_activity(current=activity) + activity = home_model.get_tabbing_activity() + activity = home_model.get_next_activity(current=activity) - shell_model.set_tabbing_activity(activity) + home_model.set_tabbing_activity(activity) self._start_timeout() else: - self._activate_next_activity() + view.Shell.get_instance().activate_next_activity() def previous_activity(self): if not self._tabbing: @@ -108,25 +114,21 @@ class TabbingHandler(object): first_switch = False if self._tabbing: - shell_model = shell.get_model() - zoom_level = shell_model.zoom_level - zoom_activity = (zoom_level == shell.ShellModel.ZOOM_ACTIVITY) + shell_model = shellmodel.get_instance() + home_model = shell_model.get_home() + zoom_level = shell_model.get_zoom_level() + zoom_activity = (zoom_level == shellmodel.ShellModel.ZOOM_ACTIVITY) if not zoom_activity and first_switch: - activity = shell_model.get_active_activity() + activity = home_model.get_active_activity() else: - activity = shell_model.get_tabbing_activity() - activity = shell_model.get_previous_activity(current=activity) + activity = home_model.get_tabbing_activity() + activity = home_model.get_previous_activity(current=activity) - shell_model.set_tabbing_activity(activity) + home_model.set_tabbing_activity(activity) self._start_timeout() else: - self._activate_next_activity() - - def _activate_next_activity(self): - next_activity = shell.get_model().get_next_activity() - if next_activity: - next_activity.get_window().activate(gtk.get_current_event_time()) + view.Shell.get_instance().activate_next_activity() def stop(self): gtk.gdk.keyboard_ungrab() @@ -138,7 +140,7 @@ class TabbingHandler(object): self._cancel_timeout() self._activate_current() - home_model = shell.get_model() + home_model = shellmodel.get_instance().get_home() home_model.set_tabbing_activity(None) def is_tabbing(self): |