Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar

This commit is contained in:
Simon McVittie 2007-08-14 20:24:01 +01:00
commit d93122bf5e
26 changed files with 412 additions and 35 deletions

View File

@ -16,3 +16,5 @@ EXTRA_DIST = \
intltool-merge.in \
intltool-update.in \
intltool-extract.in
DISTCHECK_CONFIGURE_FLAGS = --disable-update-mimedb

5
NEWS
View File

@ -1,3 +1,8 @@
* #2751 Add keybindings for max/min brightness/volume
Snapshot 040c94d181
* #2099 Tweak a color pair as requested by Walter. (marco)
* Draw an invoker that is connected with the palette for toolbuttons. (benzea)
* Fix traceback when reading in saved WPA2 network configs (dcbw)
* #2475 Retrieve correctly the file path for files in removable devices. (tomeu)

View File

@ -38,6 +38,12 @@ AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package])
AM_GLIB_GNU_GETTEXT
AC_ARG_ENABLE(update-mimedb,
AC_HELP_STRING([--disable-update-mimedb],
[disable the update-mime-database after install [default=no]]),,
enable_update_mimedb=yes)
AM_CONDITIONAL(ENABLE_UPDATE_MIMEDB, test x$enable_update_mimedb = xyes)
AC_CONFIG_FILES([bin/sugar], [chmod +x sugar])
AC_OUTPUT([
@ -62,6 +68,8 @@ shell/model/devices/network/Makefile
services/console/lib/Makefile
services/console/lib/graphics/Makefile
services/console/lib/procmem/Makefile
services/console/lib/net/Makefile
services/console/lib/ui/Makefile
services/console/Makefile
services/console/interface/Makefile
services/console/interface/xo/Makefile
@ -71,6 +79,7 @@ services/console/interface/memphis/plugins/Makefile
services/console/interface/memphis/plugins/memphis_init/Makefile
services/console/interface/memphis/plugins/cpu/Makefile
services/console/interface/memphis/Makefile
services/console/interface/network/Makefile
services/console/interface/logviewer/Makefile
services/console/interface/terminal/Makefile
sugar/Makefile

View File

@ -23,14 +23,18 @@ mimedir = $(datadir)/mime/packages
mime_DATA = $(mime_xml_files)
install-data-hook:
if ENABLE_UPDATE_MIMEDB
if [ -z "$$DESTDIR" ]; then \
update-mime-database "$(datadir)/mime"; \
fi
endif
uninstall-hook:
if ENABLE_UPDATE_MIMEDB
if [ -z "$$DESTDIR" ]; then \
update-mime-database "$(datadir)/mime"; \
fi
endif
EXTRA_DIST = $(sugar_DATA) $(mime_xml_in_files) em.py gtkrc.em
CLEANFILES = $(GTKRC_FILES)
CLEANFILES = $(GTKRC_FILES) $(mime_xml_files)

View File

@ -16,6 +16,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# Latest source available at git://dev.laptop.org/sugar
import os
import sys
import re
@ -64,7 +66,9 @@ def cmd_build_snapshot():
print 'Build %s...' % tarball
os.spawnlp(os.P_WAIT, 'make', 'make', 'distcheck')
retcode = subprocess.call(['make', 'distcheck'])
if retcode:
sys.exit(0)
os.rename('%s-%s.tar.bz2' % (name, version), tarball)

View File

@ -2,7 +2,9 @@ shell/intro/intro.py
shell/view/BuddyMenu.py
shell/view/clipboardmenu.py
shell/view/frame/zoombox.py
services/clipboard/objecttypeservice.py
services/shell/objecttypeservice.py
shell/hardware/keydialog.py
shell/view/home/activitiesdonut.py
shell/view/Shell.py
shell/view/clipboardicon.py
shell/view/home/HomeBox.py

1
po/POTFILES.skip Normal file
View File

@ -0,0 +1 @@
data/sugar.xml.in

View File

@ -50,6 +50,7 @@ class Console:
self.notebook = gtk.Notebook()
self._load_interface('xo', 'XO Resources')
self._load_interface('network', 'Network')
self._load_interface('memphis', 'Memphis')
self._load_interface('logviewer', 'Log Viewer')
self._load_interface('terminal', 'Terminal')

View File

@ -1,4 +1,4 @@
SUBDIRS = memphis logviewer terminal xo
SUBDIRS = memphis network logviewer terminal xo
sugardir = $(pkgdatadir)/services/console/interface
sugar_PYTHON = \

View File

@ -0,0 +1,4 @@
sugardir = $(pkgdatadir)/services/console/interface/network
sugar_PYTHON = \
__init__.py \
network.py

View File

@ -0,0 +1 @@
from network import Interface

View File

@ -0,0 +1,103 @@
# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>
#
# This library 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 of the License, or (at your option) any later version.
#
# This library 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 library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import gobject
from net.device import Device
from ui.treeview import TreeView
class NetworkView(TreeView):
def __init__(self):
col_names = []
col_names.append({'index': 0, 'name': 'Interface'})
col_names.append({'index': 1, 'name': 'IP Address'})
col_names.append({'index': 2, 'name': 'NetMask'})
col_names.append({'index': 3, 'name': 'MAC Address'})
col_names.append({'index': 4, 'name': 'Bytes Recv'})
col_names.append({'index': 5, 'name': 'Bytes Sent'})
col_names.append({'index': 6, 'name': 'Packets Recv'})
col_names.append({'index': 7, 'name': 'Packets Sent'})
self._iface_iter = []
cols_type = [str, str, str, str, str, str, str, str]
TreeView.__init__(self, cols_type, col_names)
self._dev = Device()
self.show_all()
gobject.timeout_add(1500, self._update_data)
def _update_data(self):
interfaces = self._dev.get_interfaces()
for iface in interfaces:
info = self._dev.get_iface_info(iface['interface'])
row = []
row.append({'index':0, 'info': iface['interface']})
if info[0]:
row.append({'index':1, 'info': info[0]})
if info[1]:
row.append({'index':2, 'info': info[1]})
if info[2]:
row.append({'index':3, 'info': info[2]})
row.append({'index': 4, 'info': iface['bytes_sent']})
row.append({'index': 5, 'info': iface['packets_sent']})
row.append({'index': 6, 'info': iface['bytes_recv']})
row.append({'index': 7, 'info': iface['packets_recv']})
iter = self._get_iface_iter(iface['interface'])
if not iter:
iter = self.add_row(row)
self._set_iface_iter(iter, iface['interface'])
else:
self.update_row(iter, row)
self._clear_down_interfaces(interfaces)
return True
def _set_iface_iter(self, iter, iface):
self._iface_iter.append([iter, iface])
def _remove_iface_iter(self, search_iter):
i = 0
for [iter, interface] in self._iface_iter:
if iter == search_iter:
del self._iface_iter[i]
return
i+=1
def _get_iface_iter(self, iface):
for [iter, interface] in self._iface_iter:
if iface == interface:
return iter
return None
def _clear_down_interfaces(self, interfaces):
for [iter, iface] in self._iface_iter:
found = False
for dev in interfaces:
if dev['interface']==iface:
found = True
break
if not found:
self.remove_row(iter)
self._remove_iface_iter(iter)
class Interface(object):
def __init__(self):
self.widget = NetworkView()

View File

@ -1,4 +1,4 @@
SUBDIRS = procmem graphics
SUBDIRS = procmem graphics net ui
sugardir = $(pkgdatadir)/shell/console/lib
sugar_PYTHON =

View File

@ -0,0 +1,7 @@
sugardir = $(pkgdatadir)/services/console/lib/net
sugar_PYTHON = \
__init__.py \
device.py

View File

View File

@ -0,0 +1,91 @@
# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>
#
# 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 socket
import fcntl
import struct
import string
class Device:
def __init__(self):
self._dev = self.get_interfaces()
def get_interfaces(self):
netdevfile = "/proc/net/dev"
dev = []
try:
infile = file(netdevfile, "r")
except:
print "Error trying " + netdevfile
skip = 0
for line in infile:
# Skip first two lines
skip += 1
if skip <= 2:
continue
iface = string.split(line, ":",1)
arr = string.split(iface[1])
info = {'interface': iface[0].strip(), \
'bytes_recv': arr[0],\
'bytes_sent': arr[8],\
'packets_recv': arr[1],
'packets_sent': arr[9]}
dev.append(info)
return dev
def get_iface_info(self, ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
hwaddr = []
try:
ip = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x8915, \
struct.pack('256s', ifname[:15]))[20:24])
except:
ip = None
try:
netmask = socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0x891b, \
struct.pack('256s', ifname[:15]))[20:24])
except:
netmask = None
try:
mac = []
info = fcntl.ioctl(s.fileno(), 0x8927, \
struct.pack('256s', ifname[:15]))
for char in info[18:24]:
hdigit = hex(ord(char))[2:]
if len(hdigit):
mac.append(hdigit)
except:
mac = None
mac_string = self.mac_to_string(mac)
return [ip, netmask, mac_string]
def mac_to_string(self, hexa):
string = ''
for value in hexa:
if len(string)==0:
string = value
else:
string += ':'+value
return string

View File

@ -0,0 +1,5 @@
sugardir = $(pkgdatadir)/services/console/lib/ui
sugar_PYTHON = \
__init__.py \
treeview.py

View File

View File

@ -0,0 +1,73 @@
# Copyright (C) 2007, Eduardo Silva <edsiper@gmail.com>
#
# This library 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 of the License, or (at your option) any later version.
#
# This library 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 library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import gtk
class TreeView(gtk.ScrolledWindow):
iters = [] # Iters index
# Create a window with a treeview object
#
# cols = List of dicts, ex:
#
# cols = []
# cols.append({'index': integer_index_position, 'name': string_col_name})
def __init__(self, cols_def, cols_name):
gtk.ScrolledWindow.__init__(self)
self._iters = []
self._treeview = gtk.TreeView()
# Creating column data types
self._store = gtk.TreeStore(*cols_def)
# Columns definition
cell = gtk.CellRendererText()
tv_cols = []
i=0
for col in cols_name:
col_tv = gtk.TreeViewColumn(col['name'], cell, text=i)
col_tv.set_reorderable(True)
col_tv.set_resizable(True)
tv_cols.append(col_tv)
i+=1
# Setting treeview properties
self._treeview.set_model(self._store)
self._treeview.set_enable_search(True)
self._treeview.set_rules_hint(True)
for col in tv_cols:
self._treeview.append_column(col)
self.add(self._treeview)
def add_row(self, cols_data):
iter = self._store.insert_after(None, None)
for col in cols_data:
print col['index'],col['info']
self._store.set_value(iter, int(col['index']) , col['info'])
self.iters.append(iter)
return iter
def update_row(self, iter, cols_data):
for col in cols_data:
self._store.set_value(iter, int(col['index']) , str(col['info']))
def remove_row(self, iter):
self._store.remove(iter)

View File

@ -28,6 +28,8 @@ from sugar._sugaruiext import KeyGrabber
_BRIGHTNESS_STEP = 2
_VOLUME_STEP = 10
_BRIGTHNESS_MAX = 15
_VOLUME_MAX = 100
_actions_table = {
'F1' : 'zoom_mesh',
@ -36,8 +38,12 @@ _actions_table = {
'F4' : 'zoom_activity',
'F9' : 'brightness_down',
'F10' : 'brightness_up',
'<ctrl>F9' : 'brightness_min',
'<ctrl>F10' : 'brightness_max',
'F11' : 'volume_down',
'F12' : 'volume_up',
'<ctrl>F11' : 'volume_min',
'<ctrl>F12' : 'volume_max',
'<alt>1' : 'screenshot',
'<alt>equal' : 'console',
'<alt>0' : 'console',
@ -69,20 +75,28 @@ class KeyHandler(object):
for key in _actions_table.keys():
self._key_grabber.grab(key)
def _change_volume(self, step):
def _change_volume(self, step=None, value=None):
hw_manager = hardwaremanager.get_manager()
if step is not None:
volume = hw_manager.get_volume() + step
volume = min(max(0, volume), 100)
elif value is not None:
volume = value
volume = min(max(0, volume), _VOLUME_MAX)
hw_manager.set_volume(volume)
hw_manager.set_mute(volume == 0)
def _change_brightness(self, step):
def _change_brightness(self, step=None, value=None):
hw_manager = hardwaremanager.get_manager()
if step is not None:
level = hw_manager.get_display_brightness() + step
level = min(max(0, level), 15)
elif value is not None:
level = value
level = min(max(0, level), _BRIGHTNESS_MAX)
hw_manager.set_display_brightness(level)
if level == 0:
@ -102,17 +116,29 @@ class KeyHandler(object):
def handle_zoom_activity(self):
self._shell.set_zoom_level(ShellModel.ZOOM_ACTIVITY)
def handle_brightness_max(self):
self._change_brightness(value=_BRIGHTNESS_MAX)
def handle_brightness_min(self):
self._change_brightness(value=0)
def handle_volume_max(self):
self._change_volume(value=_VOLUME_MAX)
def handle_volume_min(self):
self._change_volume(value=0)
def handle_brightness_up(self):
self._change_brightness(_BRIGHTNESS_STEP)
self._change_brightness(step=_BRIGHTNESS_STEP)
def handle_brightness_down(self):
self._change_brightness(-_BRIGHTNESS_STEP)
self._change_brightness(step=-_BRIGHTNESS_STEP)
def handle_volume_up(self):
self._change_volume(_VOLUME_STEP)
self._change_volume(step=_VOLUME_STEP)
def handle_volume_down(self):
self._change_volume(-_VOLUME_STEP)
self._change_volume(step=-_VOLUME_STEP)
def handle_screenshot(self):
self._shell.take_screenshot()

View File

@ -20,6 +20,7 @@ import os
import sys
import socket
import logging
from optparse import OptionParser
log = logging.getLogger( 'sugar-emulator' )
log.setLevel( logging.DEBUG )
@ -63,7 +64,7 @@ def _get_display_number():
logging.error('Cannot find a free display.')
sys.exit(0)
def _start_xephyr():
def _start_xephyr(dpi=None):
display = _get_display_number()
log.info( 'Starting the Xephyr nested X display on display %s', display )
@ -77,10 +78,11 @@ def _start_xephyr():
cmd.append('-screen')
cmd.append('%dx%d' % (1200, 900))
dpi = gtk.settings_get_default().get_property('gtk-xft-dpi')
if not dpi:
dpi = gtk.settings_get_default().get_property('gtk-xft-dpi') / 1024
if dpi > 0:
cmd.append('-dpi')
cmd.append('%d' % int(dpi/1024))
cmd.append('%d' % dpi)
log.debug( 'Xephyr command: %s', " ".join( cmd ) )
result = gobject.spawn_async(cmd, flags=gobject.SPAWN_SEARCH_PATH)
@ -110,30 +112,49 @@ def _setup_env():
os.environ['PYTHONPATH'] = source_dir + ':' + path
log.info( 'Set PYTHONPATH=%s', os.environ['PYTHONPATH'] )
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')
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()
from sugar import env
if env.is_emulator():
gtkrc_filename = 'sugar.gtkrc'
if options.xo_style:
os.environ['SUGAR_XO_STYLE'] = 'yes'
else:
os.environ['SUGAR_XO_STYLE'] = 'no'
if options.xo_style:
gtkrc_filename = 'sugar-xo.gtkrc'
else:
gtkrc_filename = 'sugar.gtkrc'
os.environ['SUGAR_XO_STYLE'] = 'no'
os.environ['GTK2_RC_FILES'] = env.get_data_path(gtkrc_filename)
print os.environ['GTK2_RC_FILES']
if len(sys.argv) == 1:
if not args:
program = 'sugar-shell'
else:
_start_matchbox()
program = sys.argv[1]
program = args[0]
command = ['dbus-launch', 'dbus-launch', '--exit-with-session', program]
log.info( "Attempting to launch sugar to replace this process: %s", " ".join(command) )

View File

@ -305,6 +305,18 @@ class Activity(Window, gtk.Container):
def _internal_jobject_error_cb(self, err):
logging.debug("Error creating activity datastore object: %s" % err)
def get_activity_root(self):
"""
Return the appropriate location in the fs where to store activity related
data that doesn't pertain to the current execution of the activity and
thus cannot go into the DataStore.
"""
if os.environ.has_key('SUGAR_ACTIVITY_ROOT') and \
os.environ['SUGAR_ACTIVITY_ROOT']:
return os.environ['SUGAR_ACTIVITY_ROOT']
else:
return '/'
def read_file(self, file_path):
"""
Subclasses implement this method if they support resuming objects from

View File

@ -30,6 +30,7 @@ from sugar.activity.bundle import Bundle
from sugar.activity import activityhandle
from sugar import logger
from sugar import _sugarext
from sugar import env
# Work around for dbus mutex locking issue
gobject.threads_init()
@ -156,6 +157,7 @@ def run(bundle_path):
gtk.icon_theme_get_default().append_search_path(bundle.get_icons_path())
os.environ['SUGAR_BUNDLE_PATH'] = bundle_path
os.environ['SUGAR_ACTIVITY_ROOT'] = env.get_profile_path(bundle.get_service_name())
_sugarext.set_prgname(bundle.get_service_name())
_sugarext.set_application_name(bundle.get_name())

View File

@ -140,14 +140,12 @@ class DSObject(object):
activityfactory.create_with_object_id(service_name, object_id)
def destroy(self):
logging.debug('DSObject.destroy() file_path: %r.' % self._file_path)
if self._destroyed:
logging.warning('This DSObject has already been destroyed!.')
import pdb;pdb.set_trace()
return
self._destroyed = True
if self._file_path and self._owns_file:
logging.debug('Removing temp file: %r' % self._file_path)
if os.path.isfile(self._file_path):
os.remove(self._file_path)
self._owns_file = False

View File

@ -15,6 +15,8 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
import os
import gtk
import pango
@ -23,6 +25,10 @@ def _get_screen_dpi():
return float(xft_dpi / 1024)
def _compute_zoom_factor():
if os.environ.has_key('SUGAR_XO_STYLE'):
if os.environ['SUGAR_XO_STYLE'] == 'yes':
return 1.0
return gtk.gdk.screen_width() / 1200.0
def zoom(units):

View File

@ -82,7 +82,7 @@ _colors = [
['#F8E800', '#807500'], \
['#BE9E00', '#F8E800'], \
['#F8E800', '#BE9E00'], \
['#FFFA00', '#F8E800'], \
['#FFFA00', '#EDDE00'], \
['#008009', '#F8E800'], \
['#F8E800', '#008009'], \
['#00EA11', '#F8E800'], \