Merge branch 'master' of git+ssh://dev.laptop.org/git/sugar
This commit is contained in:
+4
-28
@@ -2,9 +2,7 @@ SUBDIRS = activity bundle clipboard graphics objects presence datastore
|
||||
|
||||
sugardir = $(pythondir)/sugar
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
env.py \
|
||||
logger.py \
|
||||
ltihooks.py \
|
||||
network.py \
|
||||
profile.py \
|
||||
@@ -13,37 +11,19 @@ sugar_PYTHON = \
|
||||
|
||||
pkgpyexecdir = $(pythondir)/sugar
|
||||
|
||||
pkgpyexec_LTLIBRARIES = _sugarext.la _sugaruiext.la
|
||||
|
||||
_sugarext_la_CFLAGS = \
|
||||
$(LIB_CFLAGS) \
|
||||
$(LIB_BINDINGS_CFLAGS) \
|
||||
$(PYTHON_INCLUDES) \
|
||||
-I$(top_srcdir)/lib
|
||||
|
||||
_sugarext_la_LDFLAGS = -module -avoid-version
|
||||
_sugarext_la_LIBADD = \
|
||||
$(LIB_BINDINGS_LIBS) \
|
||||
$(top_builddir)/lib/libsugar.la
|
||||
|
||||
_sugarext_la_SOURCES = \
|
||||
_sugarextmodule.c
|
||||
|
||||
nodist__sugarext_la_SOURCES = _sugarext.c
|
||||
|
||||
_sugarext.c: _sugarext.defs _sugarext.override
|
||||
pkgpyexec_LTLIBRARIES = _sugaruiext.la
|
||||
|
||||
_sugaruiext_la_CFLAGS = \
|
||||
$(LIBUI_CFLAGS) \
|
||||
$(LIBUI_BINDINGS_CFLAGS) \
|
||||
$(PYTHON_INCLUDES) \
|
||||
-I$(top_srcdir)/lib/ui
|
||||
-I$(top_srcdir)/lib
|
||||
|
||||
_sugaruiext_la_LDFLAGS = -module -avoid-version
|
||||
_sugaruiext_la_LIBADD = \
|
||||
$(LIBUI_BINDINGS_LIBS) \
|
||||
$(LIBUI_LIBS) \
|
||||
$(top_builddir)/lib/ui/libsugarui.la
|
||||
$(top_builddir)/lib/libsugarui.la
|
||||
|
||||
_sugaruiext_la_SOURCES = \
|
||||
_sugaruiextmodule.c
|
||||
@@ -52,13 +32,9 @@ nodist__sugaruiext_la_SOURCES = _sugaruiext.c
|
||||
|
||||
_sugaruiext.c: _sugaruiext.defs _sugaruiext.override
|
||||
|
||||
CLEANFILES = \
|
||||
_sugarext.c \
|
||||
_sugaruiext.c
|
||||
CLEANFILES = _sugaruiext.c
|
||||
|
||||
EXTRA_DIST = \
|
||||
_sugarext.override \
|
||||
_sugarext.defs \
|
||||
_sugaruiext.defs \
|
||||
_sugaruiext.override
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
"""OLPC Sugar User Interface"""
|
||||
|
||||
# Copyright (C) 2006-2007, Red Hat, Inc.
|
||||
#
|
||||
# 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 os
|
||||
|
||||
from sugar import ltihooks
|
||||
|
||||
if os.path.isfile(os.path.join(os.path.dirname(__file__), 'Makefile.am')):
|
||||
ltihooks.install()
|
||||
@@ -1,41 +0,0 @@
|
||||
; functions
|
||||
|
||||
(define-function get_mime_type_from_file_name
|
||||
(c-name "sugar_mime_get_mime_type_from_file_name")
|
||||
(return-type "const-char*")
|
||||
(parameters
|
||||
'("const-char*" "filename")
|
||||
)
|
||||
)
|
||||
|
||||
(define-function get_mime_type_for_file
|
||||
(c-name "sugar_mime_get_mime_type_for_file")
|
||||
(return-type "const-char*")
|
||||
(parameters
|
||||
'("const-char*" "filename")
|
||||
)
|
||||
)
|
||||
|
||||
(define-function get_prgname
|
||||
(c-name "g_get_prgname")
|
||||
(return-type "const-char*")
|
||||
)
|
||||
|
||||
(define-function get_application_name
|
||||
(c-name "g_get_application_name")
|
||||
(return-type "const-char*")
|
||||
)
|
||||
|
||||
(define-function set_prgname
|
||||
(c-name "g_set_prgname")
|
||||
(parameters
|
||||
'("const-char*" "name")
|
||||
)
|
||||
)
|
||||
|
||||
(define-function set_application_name
|
||||
(c-name "g_set_application_name")
|
||||
(parameters
|
||||
'("const-char*" "name")
|
||||
)
|
||||
)
|
||||
@@ -1,32 +0,0 @@
|
||||
/* -*- Mode: C; c-basic-offset: 4 -*- */
|
||||
%%
|
||||
headers
|
||||
#include <Python.h>
|
||||
#include "xdgmime.h"
|
||||
#include <glib.h>
|
||||
%%
|
||||
modulename _sugarext
|
||||
%%
|
||||
ignore-glob
|
||||
*_get_type
|
||||
_*
|
||||
%%
|
||||
override sugar_mime_get_mime_type_for_file kwargs
|
||||
static PyObject *
|
||||
_wrap_sugar_mime_get_mime_type_for_file(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *kwlist[] = { "filename", NULL };
|
||||
char *filename;
|
||||
const gchar *ret;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s:get_mime_type_for_file", kwlist, &filename))
|
||||
return NULL;
|
||||
|
||||
ret = sugar_mime_get_mime_type_for_file(filename, NULL);
|
||||
|
||||
if (ret)
|
||||
return PyString_FromString(ret);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
%%
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2007, Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* include this first, before NO_IMPORT_PYGOBJECT is defined */
|
||||
#include <pygobject.h>
|
||||
|
||||
extern PyMethodDef py_sugarext_functions[];
|
||||
|
||||
DL_EXPORT(void)
|
||||
init_sugarext(void)
|
||||
{
|
||||
PyObject *m, *d;
|
||||
|
||||
init_pygobject ();
|
||||
|
||||
m = Py_InitModule ("_sugarext", py_sugarext_functions);
|
||||
d = PyModule_GetDict (m);
|
||||
|
||||
if (PyErr_Occurred ()) {
|
||||
Py_FatalError ("can't initialise module _sugarext");
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ from sugar.graphics.toolcombobox import ToolComboBox
|
||||
from sugar.datastore import datastore
|
||||
from sugar import wm
|
||||
from sugar import profile
|
||||
from sugar import _sugarext
|
||||
from sugar import _sugarbaseext
|
||||
|
||||
SCOPE_PRIVATE = "private"
|
||||
SCOPE_INVITE_ONLY = "invite" # shouldn't be shown in UI, it's implicit when you invite somebody
|
||||
@@ -261,6 +261,7 @@ class Activity(Window, gtk.Container):
|
||||
|
||||
self.connect('realize', self._realize_cb)
|
||||
self.connect('delete-event', self._delete_event_cb)
|
||||
self.connect('window-state-event', self._window_state_event_cb)
|
||||
|
||||
self._active = False
|
||||
self._activity_id = handle.activity_id
|
||||
@@ -344,6 +345,9 @@ class Activity(Window, gtk.Container):
|
||||
else:
|
||||
logging.debug("Unknown share scope %r" % share_scope)
|
||||
|
||||
def _window_state_event_cb(self, window, event):
|
||||
logging.info(event.new_window_state)
|
||||
|
||||
def do_set_property(self, pspec, value):
|
||||
if pspec.name == 'active':
|
||||
if self._active != value:
|
||||
@@ -363,7 +367,7 @@ class Activity(Window, gtk.Container):
|
||||
return self._activity_id
|
||||
|
||||
def get_bundle_id(self):
|
||||
return _sugarext.get_prgname()
|
||||
return _sugarbaseext.get_prgname()
|
||||
|
||||
def set_canvas(self, canvas):
|
||||
Window.set_canvas(self, canvas)
|
||||
@@ -634,7 +638,7 @@ class Activity(Window, gtk.Container):
|
||||
def get_bundle_name():
|
||||
"""Return the bundle name for the current process' bundle
|
||||
"""
|
||||
return _sugarext.get_application_name()
|
||||
return _sugarbaseext.get_application_name()
|
||||
|
||||
def get_bundle_path():
|
||||
"""Return the bundle path for the current process' bundle
|
||||
|
||||
@@ -28,7 +28,7 @@ from sugar.activity.activityhandle import ActivityHandle
|
||||
from sugar.bundle.contentbundle import ContentBundle
|
||||
from sugar.bundle.activitybundle import ActivityBundle
|
||||
from sugar.bundle.contentbundle import ContentBundle
|
||||
from sugar.objects import mime
|
||||
from sugar import mime
|
||||
|
||||
class DSMetadata(gobject.GObject):
|
||||
__gsignals__ = {
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
# Copyright (C) 2007 Red Hat, Inc.
|
||||
#
|
||||
# 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 sys
|
||||
import os
|
||||
import logging
|
||||
import time
|
||||
|
||||
# Let's keep this self contained so that it can be easily
|
||||
# pasted in external sugar service like the datastore.
|
||||
|
||||
def get_logs_dir():
|
||||
profile = os.environ.get('SUGAR_PROFILE', 'default')
|
||||
logs_dir = os.path.join(os.path.expanduser('~'),
|
||||
'.sugar', profile, 'logs')
|
||||
return logs_dir
|
||||
|
||||
def set_level(level):
|
||||
levels = { 'error' : logging.ERROR,
|
||||
'warning' : logging.WARNING,
|
||||
'debug' : logging.DEBUG,
|
||||
'info' : logging.INFO }
|
||||
if levels.has_key(level):
|
||||
logging.getLogger('').setLevel(levels[level])
|
||||
|
||||
def start(log_filename=None):
|
||||
logging.basicConfig(level=logging.WARNING,
|
||||
format="%(created)f %(levelname)s %(message)s")
|
||||
|
||||
if os.environ.has_key('SUGAR_LOGGER_LEVEL'):
|
||||
set_level(os.environ['SUGAR_LOGGER_LEVEL'])
|
||||
|
||||
if log_filename and not sys.stdin.isatty():
|
||||
log_path = os.path.join(get_logs_dir(), log_filename + '.log')
|
||||
log_file = open(log_path, 'w')
|
||||
|
||||
os.dup2(log_file.fileno(), sys.stdout.fileno())
|
||||
os.dup2(log_file.fileno(), sys.stderr.fileno())
|
||||
@@ -1,6 +1,5 @@
|
||||
sugardir = $(pythondir)/sugar/objects
|
||||
sugar_PYTHON = \
|
||||
__init__.py \
|
||||
mime.py \
|
||||
objecttype.py
|
||||
|
||||
|
||||
@@ -14,5 +14,3 @@
|
||||
# License along with this library; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
|
||||
from sugar.objects import mime
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
# Copyright (C) 2006-2007, Red Hat, Inc.
|
||||
# Copyright (C) 2007, One Laptop Per Child
|
||||
#
|
||||
# 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 logging
|
||||
|
||||
from sugar import _sugarext
|
||||
|
||||
def get_for_file(file_name):
|
||||
mime_type = _sugarext.get_mime_type_for_file(file_name)
|
||||
if mime_type == 'application/octet-stream':
|
||||
if _file_looks_like_text(file_name):
|
||||
return 'text/plain'
|
||||
else:
|
||||
return 'application/octet-stream'
|
||||
return mime_type
|
||||
|
||||
def get_from_file_name(file_name):
|
||||
return _sugarext.get_mime_type_from_file_name(file_name)
|
||||
|
||||
_extensions_cache = {}
|
||||
def get_primary_extension(mime_type):
|
||||
if _extensions_cache.has_key(mime_type):
|
||||
return _extensions_cache[mime_type]
|
||||
|
||||
f = open('/etc/mime.types')
|
||||
while True:
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
cols = line.replace('\t', ' ').split(' ')
|
||||
if mime_type == cols[0]:
|
||||
for col in cols[1:]:
|
||||
if col:
|
||||
col = col.replace('\n', '')
|
||||
_extensions_cache[mime_type] = col
|
||||
return col
|
||||
|
||||
_extensions_cache[mime_type] = None
|
||||
return None
|
||||
|
||||
def choose_most_significant(mime_types):
|
||||
logging.debug('Choosing between %r.' % mime_types)
|
||||
if not mime_types:
|
||||
return ''
|
||||
|
||||
if 'text/uri-list' in mime_types:
|
||||
return 'text/uri-list'
|
||||
|
||||
for mime_category in ['image/', 'application/']:
|
||||
for mime_type in mime_types:
|
||||
|
||||
if mime_type.startswith(mime_category):
|
||||
# skip mozilla private types (second component starts with '_'
|
||||
# or ends with '-priv')
|
||||
if mime_type.split('/')[1].startswith('_') or \
|
||||
mime_type.split('/')[1].endswith('-priv'):
|
||||
continue
|
||||
|
||||
# take out the specifier after ';' that mozilla likes to add
|
||||
mime_type = mime_type.split(';')[0]
|
||||
logging.debug('Choosed %r!' % mime_type)
|
||||
return mime_type
|
||||
|
||||
if 'text/x-moz-url' in mime_types:
|
||||
logging.debug('Choosed text/x-moz-url!')
|
||||
return 'text/x-moz-url'
|
||||
|
||||
if 'text/html' in mime_types:
|
||||
logging.debug('Choosed text/html!')
|
||||
return 'text/html'
|
||||
|
||||
if 'text/plain' in mime_types:
|
||||
logging.debug('Choosed text/plain!')
|
||||
return 'text/plain'
|
||||
|
||||
logging.debug('Returning first: %r.' % mime_types[0])
|
||||
return mime_types[0]
|
||||
|
||||
def split_uri_list(uri_list):
|
||||
result = []
|
||||
|
||||
splitted = uri_list.split('\n')
|
||||
for uri in splitted:
|
||||
result.append(uri.strip())
|
||||
|
||||
return result
|
||||
|
||||
def _file_looks_like_text(file_name):
|
||||
f = open(file_name, 'r')
|
||||
try:
|
||||
sample = f.read(256)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
if '\000' in sample:
|
||||
return False
|
||||
|
||||
for encoding in ('ascii', 'latin_1', 'utf_8', 'utf_16'):
|
||||
try:
|
||||
string = unicode(sample, encoding)
|
||||
return True
|
||||
except Exception, e:
|
||||
pass
|
||||
|
||||
return False
|
||||
+35
-13
@@ -26,9 +26,8 @@ _logger = logging.getLogger('sugar.presence.activity')
|
||||
class Activity(gobject.GObject):
|
||||
"""UI interface for an Activity in the presence service
|
||||
|
||||
Activities in the presence service represent other user's
|
||||
shared activities and your own activities (XXX shared or
|
||||
otherwise?)
|
||||
Activities in the presence service represent your and other user's
|
||||
shared activities.
|
||||
|
||||
Properties:
|
||||
id
|
||||
@@ -69,8 +68,10 @@ class Activity(gobject.GObject):
|
||||
self._ps_del_object = del_obj_cb
|
||||
bobj = bus.get_object(self._PRESENCE_SERVICE, object_path)
|
||||
self._activity = dbus.Interface(bobj, self._ACTIVITY_DBUS_INTERFACE)
|
||||
self._activity.connect_to_signal('BuddyJoined', self._buddy_joined_cb)
|
||||
self._activity.connect_to_signal('BuddyLeft', self._buddy_left_cb)
|
||||
self._activity.connect_to_signal('BuddyHandleJoined',
|
||||
self._buddy_handle_joined_cb)
|
||||
self._activity.connect_to_signal('BuddyLeft',
|
||||
self._buddy_left_cb)
|
||||
self._activity.connect_to_signal('NewChannel', self._new_channel_cb)
|
||||
self._activity.connect_to_signal('PropertiesChanged',
|
||||
self._properties_changed_cb,
|
||||
@@ -90,6 +91,9 @@ class Activity(gobject.GObject):
|
||||
self._tags = None
|
||||
self._private = True
|
||||
self._joined = False
|
||||
# Cache for get_buddy_by_handle, maps handles to buddy object paths
|
||||
self._handle_to_buddy_path = {}
|
||||
self._buddy_path_to_handle = {}
|
||||
|
||||
def _get_properties_reply_cb(self, new_props):
|
||||
self._properties_changed_cb(new_props)
|
||||
@@ -178,8 +182,10 @@ class Activity(gobject.GObject):
|
||||
self.emit('buddy-joined', self._ps_new_object(object_path))
|
||||
return False
|
||||
|
||||
def _buddy_joined_cb(self, object_path):
|
||||
def _buddy_handle_joined_cb(self, object_path, handle):
|
||||
gobject.idle_add(self._emit_buddy_joined_signal, object_path)
|
||||
self._handle_to_buddy_path[handle] = object_path
|
||||
self._buddy_path_to_handle[object_path] = handle
|
||||
|
||||
def _emit_buddy_left_signal(self, object_path):
|
||||
"""Generate buddy-left GObject signal with presence Buddy object
|
||||
@@ -191,6 +197,8 @@ class Activity(gobject.GObject):
|
||||
|
||||
def _buddy_left_cb(self, object_path):
|
||||
gobject.idle_add(self._emit_buddy_left_signal, object_path)
|
||||
handle = self._buddy_path_to_handle.pop(object_path)
|
||||
self._handle_to_buddy_path.pop(handle, None)
|
||||
|
||||
def _emit_new_channel_signal(self, object_path):
|
||||
"""Generate new-channel GObject signal with channel object path
|
||||
@@ -214,6 +222,18 @@ class Activity(gobject.GObject):
|
||||
buddies.append(self._ps_new_object(item))
|
||||
return buddies
|
||||
|
||||
def get_buddy_by_handle(self, handle):
|
||||
"""Retrieve the Buddy object given a telepathy handle.
|
||||
|
||||
buddy object paths are cached in self._handle_to_buddy_path,
|
||||
so we can get the buddy without calling PS.
|
||||
"""
|
||||
object_path = self._handle_to_buddy_path.get(handle, None)
|
||||
if object_path:
|
||||
buddy = self._ps_new_object(object_path)
|
||||
return buddy
|
||||
return None
|
||||
|
||||
def invite(self, buddy, message, response_cb):
|
||||
"""Invite the given buddy to join this activity.
|
||||
|
||||
@@ -244,9 +264,13 @@ class Activity(gobject.GObject):
|
||||
def get_channels(self):
|
||||
"""Retrieve communications channel descriptions for the activity
|
||||
|
||||
Returns (bus name, connection, channels) for the activity
|
||||
|
||||
XXX what are those values?
|
||||
Returns a tuple containing:
|
||||
- the D-Bus well-known service name of the connection
|
||||
(FIXME: this is redundant; in Telepathy it can be derived
|
||||
from that of the connection)
|
||||
- the D-Bus object path of the connection
|
||||
- a list of D-Bus object paths representing the channels
|
||||
associated with this activity
|
||||
"""
|
||||
(bus_name, connection, channels) = self._activity.GetChannels()
|
||||
return bus_name, connection, channels
|
||||
@@ -256,10 +280,8 @@ class Activity(gobject.GObject):
|
||||
self.emit("joined", False, "left activity")
|
||||
|
||||
def _leave_error_cb(self, err):
|
||||
"""Callback for error in async leaving of shared activity.
|
||||
|
||||
XXX Add logging!"""
|
||||
pass
|
||||
"""Callback for error in async leaving of shared activity."""
|
||||
_logger.debug('Failed to leave activity: %s', err)
|
||||
|
||||
def leave(self):
|
||||
"""Leave this shared activity"""
|
||||
|
||||
Reference in New Issue
Block a user