This commit is contained in:
Dan Williams 2007-02-25 19:27:37 -05:00
commit 0cad068bf4
60 changed files with 614 additions and 1921 deletions

View File

@ -112,12 +112,12 @@ lib/threadframe/Makefile
services/Makefile services/Makefile
services/presence/Makefile services/presence/Makefile
services/presence2/Makefile services/presence2/Makefile
services/nm/Makefile
services/clipboard/Makefile services/clipboard/Makefile
services/datastore/Makefile services/datastore/Makefile
shell/Makefile shell/Makefile
shell/intro/Makefile shell/intro/Makefile
shell/data/Makefile shell/data/Makefile
shell/hardware/Makefile
shell/view/Makefile shell/view/Makefile
shell/view/devices/Makefile shell/view/devices/Makefile
shell/view/frame/Makefile shell/view/frame/Makefile

View File

@ -21,13 +21,6 @@
(gtype-id "SUGAR_TYPE_KEY_GRABBER") (gtype-id "SUGAR_TYPE_KEY_GRABBER")
) )
(define-object TrayManager
(in-module "Sugar")
(parent "GObject")
(c-name "SugarTrayManager")
(gtype-id "SUGAR_TYPE_TRAY_MANAGER")
)
(define-object PushScroller (define-object PushScroller
(in-module "Sugar") (in-module "Sugar")
(parent "GObject") (parent "GObject")
@ -124,60 +117,6 @@
) )
) )
;; From sugar-tray-manager.h
(define-function tray_manager_get_type
(c-name "sugar_tray_manager_get_type")
(return-type "GType")
)
(define-function tray_manager_check_running
(c-name "sugar_tray_manager_check_running")
(return-type "gboolean")
(parameters
'("GdkScreen*" "screen")
)
)
(define-function tray_manager_new
(c-name "sugar_tray_manager_new")
(is-constructor-of "SugarTrayManager")
(return-type "SugarTrayManager*")
)
(define-method manage_screen
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_manage_screen")
(return-type "gboolean")
(parameters
'("GdkScreen*" "screen")
)
)
(define-method get_child_title
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_get_child_title")
(return-type "char*")
(parameters
'("SugarTrayManagerChild*" "child")
)
)
(define-method set_orientation
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_set_orientation")
(return-type "none")
(parameters
'("GtkOrientation" "orientation")
)
)
(define-method get_orientation
(of-object "SugarTrayManager")
(c-name "sugar_tray_manager_get_orientation")
(return-type "GtkOrientation")
)
;; From sugar-push-scroller.h ;; From sugar-push-scroller.h
(define-function push_scroller_get_type (define-function push_scroller_get_type

View File

@ -7,7 +7,6 @@ headers
#include "sugar-browser.h" #include "sugar-browser.h"
#include "sugar-key-grabber.h" #include "sugar-key-grabber.h"
#include "sugar-address-entry.h" #include "sugar-address-entry.h"
#include "sugar-tray-manager.h"
#include "sugar-push-scroller.h" #include "sugar-push-scroller.h"
#include "sugar-download-manager.h" #include "sugar-download-manager.h"
#include "sugar-download.h" #include "sugar-download.h"
@ -22,9 +21,6 @@ extern Pycairo_CAPI_t *Pycairo_CAPI;
%% %%
modulename gecko modulename gecko
%% %%
ignore
sugar_tray_manager_new
%%
import gobject.GObject as PyGObject_Type import gobject.GObject as PyGObject_Type
import gtk.Entry as PyGtkEntry_Type import gtk.Entry as PyGtkEntry_Type
import gtk.gdk.Screen as PyGdkScreen_Type import gtk.gdk.Screen as PyGdkScreen_Type

View File

@ -44,8 +44,6 @@ libsugarprivate_la_SOURCES = \
sugar-key-grabber.c \ sugar-key-grabber.c \
sugar-push-scroller.c \ sugar-push-scroller.c \
sugar-push-scroller.h \ sugar-push-scroller.h \
sugar-tray-manager.c \
sugar-tray-manager.h \
sugar-utils.c \ sugar-utils.c \
sugar-utils.h sugar-utils.h

View File

@ -1,908 +0,0 @@
/* na-tray-manager.c
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* Copyright (C) 2003-2006 Vincent Untz
*
* 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.
*
* Used to be: eggtraymanager.c
*/
#include <config.h>
#include <string.h>
#include <libintl.h>
#include "sugar-tray-manager.h"
#include <gdkconfig.h>
#include <glib/gi18n.h>
#if defined (GDK_WINDOWING_X11)
#include <gdk/gdkx.h>
#include <X11/Xatom.h>
#elif defined (GDK_WINDOWING_WIN32)
#include <gdk/gdkwin32.h>
#endif
#include <gtk/gtkinvisible.h>
#include <gtk/gtksocket.h>
#include <gtk/gtkwindow.h>
#include "sugar-marshal.h"
/* Signals */
enum
{
TRAY_ICON_ADDED,
TRAY_ICON_REMOVED,
MESSAGE_SENT,
MESSAGE_CANCELLED,
LOST_SELECTION,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_ORIENTATION
};
typedef struct
{
long id, len;
long remaining_len;
long timeout;
char *str;
#ifdef GDK_WINDOWING_X11
Window window;
#endif
} PendingMessage;
static guint manager_signals[LAST_SIGNAL] = { 0 };
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
#define SYSTEM_TRAY_ORIENTATION_HORZ 0
#define SYSTEM_TRAY_ORIENTATION_VERT 1
#ifdef GDK_WINDOWING_X11
static gboolean sugar_tray_manager_check_running_screen_x11 (GdkScreen *screen);
#endif
static void sugar_tray_manager_finalize (GObject *object);
static void sugar_tray_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void sugar_tray_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void sugar_tray_manager_unmanage (SugarTrayManager *manager);
G_DEFINE_TYPE (SugarTrayManager, sugar_tray_manager, G_TYPE_OBJECT)
static void
sugar_tray_manager_init (SugarTrayManager *manager)
{
manager->invisible = NULL;
manager->socket_table = g_hash_table_new (NULL, NULL);
}
static void
sugar_tray_manager_class_init (SugarTrayManagerClass *klass)
{
GObjectClass *gobject_class;
gobject_class = (GObjectClass *)klass;
gobject_class->finalize = sugar_tray_manager_finalize;
gobject_class->set_property = sugar_tray_manager_set_property;
gobject_class->get_property = sugar_tray_manager_get_property;
g_object_class_install_property (gobject_class,
PROP_ORIENTATION,
g_param_spec_enum ("orientation",
_("Orientation"),
_("The orientation of the tray."),
GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_HORIZONTAL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
manager_signals[TRAY_ICON_ADDED] =
g_signal_new ("tray_icon_added",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, tray_icon_added),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_SOCKET);
manager_signals[TRAY_ICON_REMOVED] =
g_signal_new ("tray_icon_removed",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, tray_icon_removed),
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
GTK_TYPE_SOCKET);
manager_signals[MESSAGE_SENT] =
g_signal_new ("message_sent",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, message_sent),
NULL, NULL,
sugar_marshal_VOID__OBJECT_STRING_LONG_LONG,
G_TYPE_NONE, 4,
GTK_TYPE_SOCKET,
G_TYPE_STRING,
G_TYPE_LONG,
G_TYPE_LONG);
manager_signals[MESSAGE_CANCELLED] =
g_signal_new ("message_cancelled",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, message_cancelled),
NULL, NULL,
sugar_marshal_VOID__OBJECT_LONG,
G_TYPE_NONE, 2,
GTK_TYPE_SOCKET,
G_TYPE_LONG);
manager_signals[LOST_SELECTION] =
g_signal_new ("lost_selection",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (SugarTrayManagerClass, lost_selection),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
#if defined (GDK_WINDOWING_X11)
/* Nothing */
#elif defined (GDK_WINDOWING_WIN32)
g_warning ("Port SugarTrayManager to Win32");
#else
g_warning ("Port SugarTrayManager to this GTK+ backend");
#endif
}
static void
sugar_tray_manager_finalize (GObject *object)
{
SugarTrayManager *manager;
manager = SUGAR_TRAY_MANAGER (object);
sugar_tray_manager_unmanage (manager);
g_list_free (manager->messages);
g_hash_table_destroy (manager->socket_table);
G_OBJECT_CLASS (sugar_tray_manager_parent_class)->finalize (object);
}
static void
sugar_tray_manager_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
SugarTrayManager *manager = SUGAR_TRAY_MANAGER (object);
switch (prop_id)
{
case PROP_ORIENTATION:
sugar_tray_manager_set_orientation (manager, g_value_get_enum (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
sugar_tray_manager_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
SugarTrayManager *manager = SUGAR_TRAY_MANAGER (object);
switch (prop_id)
{
case PROP_ORIENTATION:
g_value_set_enum (value, manager->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
SugarTrayManager *
sugar_tray_manager_new (void)
{
SugarTrayManager *manager;
manager = g_object_new (SUGAR_TYPE_TRAY_MANAGER, NULL);
return manager;
}
#ifdef GDK_WINDOWING_X11
static gboolean
sugar_tray_manager_plug_removed (GtkSocket *socket,
SugarTrayManager *manager)
{
Window *window;
window = g_object_get_data (G_OBJECT (socket), "na-tray-child-window");
g_hash_table_remove (manager->socket_table, GINT_TO_POINTER (*window));
g_object_set_data (G_OBJECT (socket), "na-tray-child-window",
NULL);
g_signal_emit (manager, manager_signals[TRAY_ICON_REMOVED], 0, socket);
/* This destroys the socket. */
return FALSE;
}
static void
sugar_tray_manager_make_socket_transparent (GtkWidget *widget,
gpointer user_data)
{
if (GTK_WIDGET_NO_WINDOW (widget))
return;
gdk_window_set_back_pixmap (widget->window, NULL, TRUE);
}
static gboolean
sugar_tray_manager_socket_exposed (GtkWidget *widget,
GdkEventExpose *event,
gpointer user_data)
{
gdk_window_clear_area (widget->window,
event->area.x, event->area.y,
event->area.width, event->area.height);
return FALSE;
}
static void
sugar_tray_manager_socket_style_set (GtkWidget *widget,
GtkStyle *previous_style,
gpointer user_data)
{
if (widget->window == NULL)
return;
sugar_tray_manager_make_socket_transparent (widget, user_data);
}
static void
sugar_tray_manager_handle_dock_request (SugarTrayManager *manager,
XClientMessageEvent *xevent)
{
GtkWidget *socket;
Window *window;
GtkRequisition req;
if (g_hash_table_lookup (manager->socket_table, GINT_TO_POINTER (xevent->data.l[2])))
{
/* We already got this notification earlier, ignore this one */
return;
}
socket = gtk_socket_new ();
gtk_widget_set_app_paintable (socket, TRUE);
//FIXME: need to find a theme where this (and expose event) is needed
gtk_widget_set_double_buffered (socket, FALSE);
/* FIXME Disabled this so that I can customize the icons background in theme.
I couldn't find a way to set a specific color for the GtkPlug.
g_signal_connect (socket, "realize",
G_CALLBACK (sugar_tray_manager_make_socket_transparent), NULL);
*/
g_signal_connect (socket, "expose_event",
G_CALLBACK (sugar_tray_manager_socket_exposed), NULL);
g_signal_connect_after (socket, "style_set",
G_CALLBACK (sugar_tray_manager_socket_style_set), NULL);
/* We need to set the child window here
* so that the client can call _get functions
* in the signal handler
*/
window = g_new (Window, 1);
*window = xevent->data.l[2];
g_object_set_data_full (G_OBJECT (socket),
"na-tray-child-window",
window, g_free);
g_signal_emit (manager, manager_signals[TRAY_ICON_ADDED], 0,
socket);
/* Add the socket only if it's been attached */
if (GTK_IS_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (socket))))
{
g_signal_connect (socket, "plug_removed",
G_CALLBACK (sugar_tray_manager_plug_removed), manager);
gtk_socket_add_id (GTK_SOCKET (socket), *window);
g_hash_table_insert (manager->socket_table, GINT_TO_POINTER (*window), socket);
/*
* Make sure the icons have a meaningfull size ...
*/
req.width = req.height = 1;
gtk_widget_size_request (socket, &req);
/*
if ((req.width < 16) || (req.height < 16))
{
gint nw = MAX (24, req.width);
gint nh = MAX (24, req.height);
g_warning (_("tray icon has requested a size of (%i x %i), resizing to (%i x %i)"),
req.width, req.height, nw, nh);
gtk_widget_set_size_request(icon, nw, nh);
}
*/
gtk_widget_show(socket);
}
else
gtk_widget_destroy (socket);
}
static void
pending_message_free (PendingMessage *message)
{
g_free (message->str);
g_free (message);
}
static GdkFilterReturn
sugar_tray_manager_handle_client_message_message_data (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XClientMessageEvent *xevent;
SugarTrayManager *manager;
GList *p;
int len;
xevent = (XClientMessageEvent *) xev;
manager = data;
/* Try to see if we can find the pending message in the list */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window)
{
/* Append the message */
len = MIN (msg->remaining_len, 20);
memcpy ((msg->str + msg->len - msg->remaining_len),
&xevent->data, len);
msg->remaining_len -= len;
if (msg->remaining_len == 0)
{
GtkSocket *socket;
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (msg->window));
if (socket)
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
socket, msg->str, msg->id, msg->timeout);
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
}
break;
}
}
return GDK_FILTER_REMOVE;
}
static void
sugar_tray_manager_handle_begin_message (SugarTrayManager *manager,
XClientMessageEvent *xevent)
{
GtkSocket *socket;
GList *p;
PendingMessage *msg;
long timeout;
long len;
long id;
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (xevent->window));
/* we don't know about this tray icon, so ignore the message */
if (!socket)
return;
/* Check if the same message is already in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window &&
xevent->data.l[4] == msg->id)
{
/* Hmm, we found it, now remove it */
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
break;
}
}
timeout = xevent->data.l[2];
len = xevent->data.l[3];
id = xevent->data.l[4];
if (len == 0)
{
g_signal_emit (manager, manager_signals[MESSAGE_SENT], 0,
socket, "", id, timeout);
}
else
{
/* Now add the new message to the queue */
msg = g_new0 (PendingMessage, 1);
msg->window = xevent->window;
msg->timeout = timeout;
msg->len = len;
msg->id = id;
msg->remaining_len = msg->len;
msg->str = g_malloc (msg->len + 1);
msg->str[msg->len] = '\0';
manager->messages = g_list_prepend (manager->messages, msg);
}
}
static void
sugar_tray_manager_handle_cancel_message (SugarTrayManager *manager,
XClientMessageEvent *xevent)
{
GList *p;
GtkSocket *socket;
/* Check if the message is in the queue and remove it if so */
for (p = manager->messages; p; p = p->next)
{
PendingMessage *msg = p->data;
if (xevent->window == msg->window &&
xevent->data.l[4] == msg->id)
{
pending_message_free (msg);
manager->messages = g_list_remove_link (manager->messages, p);
g_list_free_1 (p);
break;
}
}
socket = g_hash_table_lookup (manager->socket_table,
GINT_TO_POINTER (xevent->window));
if (socket)
{
g_signal_emit (manager, manager_signals[MESSAGE_CANCELLED], 0,
socket, xevent->data.l[2]);
}
}
static GdkFilterReturn
sugar_tray_manager_handle_client_message_opcode (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XClientMessageEvent *xevent;
SugarTrayManager *manager;
xevent = (XClientMessageEvent *) xev;
manager = data;
switch (xevent->data.l[1])
{
case SYSTEM_TRAY_REQUEST_DOCK:
/* Ignore this one since we don't know on which window this was received
* and so we can't know for which screen this is. It will be handled
* in sugar_tray_manager_window_filter() since we also receive it there */
break;
case SYSTEM_TRAY_BEGIN_MESSAGE:
sugar_tray_manager_handle_begin_message (manager, xevent);
return GDK_FILTER_REMOVE;
case SYSTEM_TRAY_CANCEL_MESSAGE:
sugar_tray_manager_handle_cancel_message (manager, xevent);
return GDK_FILTER_REMOVE;
default:
break;
}
return GDK_FILTER_CONTINUE;
}
static GdkFilterReturn
sugar_tray_manager_window_filter (GdkXEvent *xev,
GdkEvent *event,
gpointer data)
{
XEvent *xevent = (GdkXEvent *)xev;
SugarTrayManager *manager = data;
if (xevent->type == ClientMessage)
{
/* We handle this client message here. See comment in
* sugar_tray_manager_handle_client_message_opcode() for details */
if (xevent->xclient.message_type == manager->opcode_atom &&
xevent->xclient.data.l[1] == SYSTEM_TRAY_REQUEST_DOCK)
{
sugar_tray_manager_handle_dock_request (manager,
(XClientMessageEvent *) xevent);
return GDK_FILTER_REMOVE;
}
}
else if (xevent->type == SelectionClear)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
sugar_tray_manager_unmanage (manager);
}
return GDK_FILTER_CONTINUE;
}
#if 0
//FIXME investigate why this doesn't work
static gboolean
sugar_tray_manager_selection_clear_event (GtkWidget *widget,
GdkEventSelection *event,
SugarTrayManager *manager)
{
g_signal_emit (manager, manager_signals[LOST_SELECTION], 0);
sugar_tray_manager_unmanage (manager);
return FALSE;
}
#endif
#endif
static void
sugar_tray_manager_unmanage (SugarTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
guint32 timestamp;
GtkWidget *invisible;
if (manager->invisible == NULL)
return;
invisible = manager->invisible;
g_assert (GTK_IS_INVISIBLE (invisible));
g_assert (GTK_WIDGET_REALIZED (invisible));
g_assert (GDK_IS_WINDOW (invisible->window));
display = gtk_widget_get_display (invisible);
if (gdk_selection_owner_get_for_display (display, manager->selection_atom) ==
invisible->window)
{
timestamp = gdk_x11_get_server_time (invisible->window);
gdk_selection_owner_set_for_display (display,
NULL,
manager->selection_atom,
timestamp,
TRUE);
}
//FIXME: we should also use gdk_remove_client_message_filter when it's
//available
// See bug #351254
gdk_window_remove_filter (invisible->window,
sugar_tray_manager_window_filter, manager);
manager->invisible = NULL; /* prior to destroy for reentrancy paranoia */
gtk_widget_destroy (invisible);
g_object_unref (G_OBJECT (invisible));
#endif
}
static void
sugar_tray_manager_set_orientation_property (SugarTrayManager *manager)
{
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
Atom orientation_atom;
gulong data[1];
if (!manager->invisible || !manager->invisible->window)
return;
display = gtk_widget_get_display (manager->invisible);
orientation_atom = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_SYSTEM_TRAY_ORIENTATION");
data[0] = manager->orientation == GTK_ORIENTATION_HORIZONTAL ?
SYSTEM_TRAY_ORIENTATION_HORZ :
SYSTEM_TRAY_ORIENTATION_VERT;
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XWINDOW (manager->invisible->window),
orientation_atom,
XA_CARDINAL, 32,
PropModeReplace,
(guchar *) &data, 1);
#endif
}
#ifdef GDK_WINDOWING_X11
static gboolean
sugar_tray_manager_manage_screen_x11 (SugarTrayManager *manager,
GdkScreen *screen)
{
GdkDisplay *display;
Screen *xscreen;
GtkWidget *invisible;
char *selection_atom_name;
guint32 timestamp;
g_return_val_if_fail (SUGAR_IS_TRAY_MANAGER (manager), FALSE);
g_return_val_if_fail (manager->screen == NULL, FALSE);
/* If there's already a manager running on the screen
* we can't create another one.
*/
#if 0
if (sugar_tray_manager_check_running_screen_x11 (screen))
return FALSE;
#endif
display = gdk_screen_get_display (screen);
xscreen = GDK_SCREEN_XSCREEN (screen);
invisible = gtk_invisible_new_for_screen (screen);
gtk_widget_realize (invisible);
gtk_widget_add_events (invisible,
GDK_PROPERTY_CHANGE_MASK | GDK_STRUCTURE_MASK);
selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
gdk_screen_get_number (screen));
manager->selection_atom = gdk_atom_intern (selection_atom_name, FALSE);
g_free (selection_atom_name);
sugar_tray_manager_set_orientation_property (manager);
timestamp = gdk_x11_get_server_time (invisible->window);
/* Check if we could set the selection owner successfully */
if (gdk_selection_owner_set_for_display (display,
invisible->window,
manager->selection_atom,
timestamp,
TRUE))
{
XClientMessageEvent xev;
GdkAtom opcode_atom;
GdkAtom message_data_atom;
xev.type = ClientMessage;
xev.window = RootWindowOfScreen (xscreen);
xev.message_type = gdk_x11_get_xatom_by_name_for_display (display,
"MANAGER");
xev.format = 32;
xev.data.l[0] = timestamp;
xev.data.l[1] = gdk_x11_atom_to_xatom_for_display (display,
manager->selection_atom);
xev.data.l[2] = GDK_WINDOW_XWINDOW (invisible->window);
xev.data.l[3] = 0; /* manager specific data */
xev.data.l[4] = 0; /* manager specific data */
XSendEvent (GDK_DISPLAY_XDISPLAY (display),
RootWindowOfScreen (xscreen),
False, StructureNotifyMask, (XEvent *)&xev);
manager->invisible = invisible;
g_object_ref (G_OBJECT (manager->invisible));
opcode_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_OPCODE", FALSE);
manager->opcode_atom = gdk_x11_atom_to_xatom_for_display (display,
opcode_atom);
message_data_atom = gdk_atom_intern ("_NET_SYSTEM_TRAY_MESSAGE_DATA",
FALSE);
/* Add a window filter */
#if 0
/* This is for when we lose the selection of _NET_SYSTEM_TRAY_Sx */
g_signal_connect (invisible, "selection-clear-event",
G_CALLBACK (sugar_tray_manager_selection_clear_event),
manager);
#endif
/* This is for SYSTEM_TRAY_REQUEST_DOCK and SelectionClear */
gdk_window_add_filter (invisible->window,
sugar_tray_manager_window_filter, manager);
/* This is for SYSTEM_TRAY_BEGIN_MESSAGE and SYSTEM_TRAY_CANCEL_MESSAGE */
gdk_display_add_client_message_filter (display, opcode_atom,
sugar_tray_manager_handle_client_message_opcode,
manager);
/* This is for _NET_SYSTEM_TRAY_MESSAGE_DATA */
gdk_display_add_client_message_filter (display, message_data_atom,
sugar_tray_manager_handle_client_message_message_data,
manager);
return TRUE;
}
else
{
gtk_widget_destroy (invisible);
return FALSE;
}
}
#endif
gboolean
sugar_tray_manager_manage_screen (SugarTrayManager *manager,
GdkScreen *screen)
{
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
g_return_val_if_fail (manager->screen == NULL, FALSE);
#ifdef GDK_WINDOWING_X11
return sugar_tray_manager_manage_screen_x11 (manager, screen);
#else
return FALSE;
#endif
}
#ifdef GDK_WINDOWING_X11
static gboolean
sugar_tray_manager_check_running_screen_x11 (GdkScreen *screen)
{
GdkDisplay *display;
Atom selection_atom;
char *selection_atom_name;
display = gdk_screen_get_display (screen);
selection_atom_name = g_strdup_printf ("_NET_SYSTEM_TRAY_S%d",
gdk_screen_get_number (screen));
selection_atom = gdk_x11_get_xatom_by_name_for_display (display,
selection_atom_name);
g_free (selection_atom_name);
if (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display),
selection_atom) != None)
return TRUE;
else
return FALSE;
}
#endif
gboolean
sugar_tray_manager_check_running (GdkScreen *screen)
{
g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
#ifdef GDK_WINDOWING_X11
return sugar_tray_manager_check_running_screen_x11 (screen);
#else
return FALSE;
#endif
}
char *
sugar_tray_manager_get_child_title (SugarTrayManager *manager,
SugarTrayManagerChild *child)
{
char *retval = NULL;
#ifdef GDK_WINDOWING_X11
GdkDisplay *display;
Window *child_window;
Atom utf8_string, atom, type;
int result;
int format;
gulong nitems;
gulong bytes_after;
guchar *val;
g_return_val_if_fail (SUGAR_IS_TRAY_MANAGER (manager), NULL);
g_return_val_if_fail (GTK_IS_SOCKET (child), NULL);
display = gdk_screen_get_display (manager->screen);
child_window = g_object_get_data (G_OBJECT (child),
"na-tray-child-window");
utf8_string = gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING");
atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME");
gdk_error_trap_push ();
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
*child_window,
atom,
0, G_MAXLONG,
False, utf8_string,
&type, &format, &nitems,
&bytes_after, (guchar **)&val);
if (gdk_error_trap_pop () || result != Success)
return NULL;
if (type != utf8_string ||
format != 8 ||
nitems == 0)
{
if (val)
XFree (val);
return NULL;
}
if (!g_utf8_validate (val, nitems, NULL))
{
XFree (val);
return NULL;
}
retval = g_strndup (val, nitems);
XFree (val);
#endif
return retval;
}
void
sugar_tray_manager_set_orientation (SugarTrayManager *manager,
GtkOrientation orientation)
{
g_return_if_fail (SUGAR_IS_TRAY_MANAGER (manager));
if (manager->orientation != orientation)
{
manager->orientation = orientation;
sugar_tray_manager_set_orientation_property (manager);
g_object_notify (G_OBJECT (manager), "orientation");
}
}
GtkOrientation
sugar_tray_manager_get_orientation (SugarTrayManager *manager)
{
g_return_val_if_fail (SUGAR_IS_TRAY_MANAGER (manager), GTK_ORIENTATION_HORIZONTAL);
return manager->orientation;
}

View File

@ -1,98 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* na-tray-manager.h
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* Copyright (C) 2003-2006 Vincent Untz
*
* 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.
*
* Used to be: eggtraymanager.h
*/
#ifndef __SUGAR_TRAY_MANAGER_H__
#define __SUGAR_TRAY_MANAGER_H__
#include <gtk/gtkwidget.h>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
G_BEGIN_DECLS
#define SUGAR_TYPE_TRAY_MANAGER (sugar_tray_manager_get_type ())
#define SUGAR_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SUGAR_TYPE_TRAY_MANAGER, SugarTrayManager))
#define SUGAR_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SUGAR_TYPE_TRAY_MANAGER, SugarTrayManagerClass))
#define SUGAR_IS_TRAY_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SUGAR_TYPE_TRAY_MANAGER))
#define SUGAR_IS_TRAY_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SUGAR_TYPE_TRAY_MANAGER))
#define SUGAR_TRAY_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SUGAR_TYPE_TRAY_MANAGER, SugarTrayManagerClass))
typedef struct _SugarTrayManager SugarTrayManager;
typedef struct _SugarTrayManagerClass SugarTrayManagerClass;
typedef struct _SugarTrayManagerChild SugarTrayManagerChild;
struct _SugarTrayManager
{
GObject parent_instance;
#ifdef GDK_WINDOWING_X11
GdkAtom selection_atom;
Atom opcode_atom;
#endif
GtkWidget *invisible;
GdkScreen *screen;
GtkOrientation orientation;
GList *messages;
GHashTable *socket_table;
};
struct _SugarTrayManagerClass
{
GObjectClass parent_class;
void (* tray_icon_added) (SugarTrayManager *manager,
SugarTrayManagerChild *child);
void (* tray_icon_removed) (SugarTrayManager *manager,
SugarTrayManagerChild *child);
void (* message_sent) (SugarTrayManager *manager,
SugarTrayManagerChild *child,
const gchar *message,
glong id,
glong timeout);
void (* message_cancelled) (SugarTrayManager *manager,
SugarTrayManagerChild *child,
glong id);
void (* lost_selection) (SugarTrayManager *manager);
};
GType sugar_tray_manager_get_type (void);
gboolean sugar_tray_manager_check_running (GdkScreen *screen);
SugarTrayManager *sugar_tray_manager_new (void);
gboolean sugar_tray_manager_manage_screen (SugarTrayManager *manager,
GdkScreen *screen);
char *sugar_tray_manager_get_child_title (SugarTrayManager *manager,
SugarTrayManagerChild *child);
void sugar_tray_manager_set_orientation (SugarTrayManager *manager,
GtkOrientation orientation);
GtkOrientation sugar_tray_manager_get_orientation (SugarTrayManager *manager);
G_END_DECLS
#endif /* __SUGAR_TRAY_MANAGER_H__ */

View File

@ -1 +1 @@
SUBDIRS = presence presence2 nm clipboard datastore console SUBDIRS = presence presence2 clipboard datastore console

View File

@ -1,15 +0,0 @@
sugardir = $(pkgdatadir)/services/nm
sugar_PYTHON = \
__init__.py \
nmclient.py \
nminfo.py \
bubble.py \
style.py \
wepkeydialog.py
bin_SCRIPTS = sugar-nm-applet
dbusservicedir = $(sysconfdir)/dbus-1/system.d/
dbusservice_DATA = NetworkManagerInfo.conf
EXTRA_DIST = $(dbusservice_DATA) $(bin_SCRIPTS)

View File

@ -1,26 +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.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>

View File

@ -1,132 +0,0 @@
# Copyright (C) 2006, 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 math
import gobject
import gtk
import hippo
class Bubble(hippo.CanvasBox, hippo.CanvasItem):
__gtype_name__ = 'NetworkBubble'
__gproperties__ = {
'fill-color': (object, None, None,
gobject.PARAM_READWRITE),
'stroke-color': (object, None, None,
gobject.PARAM_READWRITE),
'progress-color': (object, None, None,
gobject.PARAM_READWRITE),
'percent' : (object, None, None,
gobject.PARAM_READWRITE),
}
def __init__(self, **kwargs):
self._stroke_color = 0xFFFFFFFF
self._fill_color = 0xFFFFFFFF
self._progress_color = 0x000000FF
self._percent = 0
self._radius = 8
hippo.CanvasBox.__init__(self, **kwargs)
def do_set_property(self, pspec, value):
if pspec.name == 'fill-color':
self._fill_color = value
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'stroke-color':
self._stroke_color = value
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'progress-color':
self._progress_color = value
self.emit_paint_needed(0, 0, -1, -1)
elif pspec.name == 'percent':
self._percent = value
self.emit_paint_needed(0, 0, -1, -1)
def do_get_property(self, pspec):
if pspec.name == 'fill-color':
return self._fill_color
elif pspec.name == 'stroke-color':
return self._stroke_color
elif pspec.name == 'progress-color':
return self._progress_color
elif pspec.name == 'percent':
return self._percent
def _int_to_rgb(self, int_color):
red = (int_color >> 24) & 0x000000FF
green = (int_color >> 16) & 0x000000FF
blue = (int_color >> 8) & 0x000000FF
alpha = int_color & 0x000000FF
return (red / 255.0, green / 255.0, blue / 255.0)
def do_paint_below_children(self, cr, damaged_box):
[width, height] = self.get_allocation()
line_width = 3.0
x = line_width
y = line_width
width -= line_width * 2
height -= line_width * 2
cr.move_to(x + self._radius, y);
cr.arc(x + width - self._radius, y + self._radius,
self._radius, math.pi * 1.5, math.pi * 2);
cr.arc(x + width - self._radius, x + height - self._radius,
self._radius, 0, math.pi * 0.5);
cr.arc(x + self._radius, y + height - self._radius,
self._radius, math.pi * 0.5, math.pi);
cr.arc(x + self._radius, y + self._radius, self._radius,
math.pi, math.pi * 1.5);
color = self._int_to_rgb(self._fill_color)
cr.set_source_rgb(*color)
cr.fill_preserve();
color = self._int_to_rgb(self._stroke_color)
cr.set_source_rgb(*color)
cr.set_line_width(line_width)
cr.stroke();
if self._percent > 0:
self._paint_progress_bar(cr, x, y, width, height, line_width)
def _paint_progress_bar(self, cr, x, y, width, height, line_width):
prog_x = x + line_width
prog_y = y + line_width
prog_width = (width - (line_width * 2)) * (self._percent / 100.0)
prog_height = (height - (line_width * 2))
x = prog_x
y = prog_y
width = prog_width
height = prog_height
cr.move_to(x + self._radius, y);
cr.arc(x + width - self._radius, y + self._radius,
self._radius, math.pi * 1.5, math.pi * 2);
cr.arc(x + width - self._radius, x + height - self._radius,
self._radius, 0, math.pi * 0.5);
cr.arc(x + self._radius, y + height - self._radius,
self._radius, math.pi * 0.5, math.pi);
cr.arc(x + self._radius, y + self._radius, self._radius,
math.pi, math.pi * 1.5);
color = self._int_to_rgb(self._progress_color)
cr.set_source_rgb(*color)
cr.fill_preserve();

View File

@ -1,59 +0,0 @@
# Copyright (C) 2006, 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 logging
import gtk
### Deprecated: we should drop this once we removed stylesheets ###
_styles = {}
screen_factor = gtk.gdk.screen_width() / 1200.0
space_unit = 9 * screen_factor
separator_thickness = 3 * screen_factor
standard_icon_scale = 1.0 * screen_factor
small_icon_scale = 0.5 * screen_factor
medium_icon_scale = 1.5 * screen_factor
large_icon_scale = 2.0 * screen_factor
xlarge_icon_scale = 3.0 * screen_factor
default_font_size = 9.0 * screen_factor
def load_stylesheet(module):
for objname in dir(module):
if not objname.startswith('_'):
obj = getattr(module, objname)
if isinstance(obj, dict):
register_stylesheet(objname.replace('_', '.'), obj)
def register_stylesheet(name, style):
_styles[name] = style
def apply_stylesheet(item, stylesheet_name):
if _styles.has_key(stylesheet_name):
style_sheet = _styles[stylesheet_name]
for name in style_sheet.keys():
item.set_property(name, style_sheet[name])
else:
logging.debug('Stylesheet %s not found.' % stylesheet_name)
def get_font_description(style, relative_size):
base_size = 18 * screen_factor
return '%s %dpx' % (style, int(base_size * relative_size))

View File

@ -1,38 +0,0 @@
#!/usr/bin/env python
# vi: ts=4 ai noet
#
# 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 sys
import logging
import pygtk
pygtk.require('2.0')
from sugar import logger
from sugar import env
sys.path.insert(0, env.get_services_dir())
from nm import nmclient
logger.start('nm-applet')
logging.info('Starting network applet')
app = nmclient.NMClientApp()
app.run()

View File

@ -1,4 +1,4 @@
SUBDIRS = data model view intro SUBDIRS = data hardware model view intro
bin_SCRIPTS = \ bin_SCRIPTS = \
sugar-activity \ sugar-activity \

View File

@ -0,0 +1,7 @@
sugardir = $(pkgdatadir)/shell/hardware
sugar_PYTHON = \
__init__.py \
hardwaremanager.py \
nmclient.py \
nminfo.py \
wepkeydialog.py

View File

@ -18,20 +18,23 @@ import logging
import dbus import dbus
HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager' from hardware.nmclient import NMClient
HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager' from _sugar import AudioManager
HARDWARE_MANAGER_OBJECT_PATH = '/org/laptop/HardwareManager'
_HARDWARE_MANAGER_INTERFACE = 'org.laptop.HardwareManager'
_HARDWARE_MANAGER_SERVICE = 'org.laptop.HardwareManager'
_HARDWARE_MANAGER_OBJECT_PATH = '/org/laptop/HardwareManager'
COLOR_MODE = 0
B_AND_W_MODE = 1
class HardwareManager(object): class HardwareManager(object):
COLOR_MODE = 0
B_AND_W_MODE = 1
def __init__(self): def __init__(self):
try: try:
bus = dbus.SystemBus() bus = dbus.SystemBus()
proxy = bus.get_object(HARDWARE_MANAGER_SERVICE, proxy = bus.get_object(_HARDWARE_MANAGER_SERVICE,
HARDWARE_MANAGER_OBJECT_PATH) _HARDWARE_MANAGER_OBJECT_PATH)
self._service = dbus.Interface(proxy, HARDWARE_MANAGER_INTERFACE) self._service = dbus.Interface(proxy, _HARDWARE_MANAGER_INTERFACE)
except dbus.DBusException: except dbus.DBusException:
self._service = None self._service = None
logging.error('Hardware manager service not found.') logging.error('Hardware manager service not found.')
@ -56,3 +59,16 @@ class HardwareManager(object):
self._service.set_keyboard_brightness(False) self._service.set_keyboard_brightness(False)
else: else:
self._service.set_keyboard_brightness(True) self._service.set_keyboard_brightness(True)
def get_hardware_manager():
return _hardware_manager
def get_audio_manager():
return _audio_manager
def get_network_manager():
return _network_manager
_hardware_manager = HardwareManager()
_audio_manager = AudioManager()
_network_manager = NMClient()

View File

@ -1,4 +1,3 @@
# vi: ts=4 ai noet
# #
# Copyright (C) 2006, Red Hat, Inc. # Copyright (C) 2006, Red Hat, Inc.
# #
@ -16,27 +15,21 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import logging
import os
import dbus import dbus
import dbus.glib import dbus.glib
import dbus.decorators import dbus.decorators
import gobject import gobject
import gtk import gtk
import logging
import os
from gettext import gettext as _
import hippo from hardware.wepkeydialog import WEPKeyDialog
import style from hardware import nminfo
from sugar.graphics.timeline import Timeline
from wepkeydialog import WEPKeyDialog
from bubble import Bubble
import nminfo
IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001 IW_AUTH_ALG_OPEN_SYSTEM = 0x00000001
IW_AUTH_ALG_SHARED_KEY = 0x00000002 IW_AUTH_ALG_SHARED_KEY = 0x00000002
NM_DEVICE_STAGE_STRINGS=("Unknown", NM_DEVICE_STAGE_STRINGS=("Unknown",
"Prepare", "Prepare",
"Config", "Config",
@ -63,10 +56,8 @@ NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001
NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002 NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002
NM_DEVICE_CAP_WIRELESS_SCAN = 0x00000004 NM_DEVICE_CAP_WIRELESS_SCAN = 0x00000004
sys_bus = dbus.SystemBus() sys_bus = dbus.SystemBus()
NM_802_11_CAP_NONE = 0x00000000 NM_802_11_CAP_NONE = 0x00000000
NM_802_11_CAP_PROTO_NONE = 0x00000001 NM_802_11_CAP_PROTO_NONE = 0x00000001
NM_802_11_CAP_PROTO_WEP = 0x00000002 NM_802_11_CAP_PROTO_WEP = 0x00000002
@ -79,10 +70,14 @@ NM_802_11_CAP_CIPHER_WEP104 = 0x00002000
NM_802_11_CAP_CIPHER_TKIP = 0x00004000 NM_802_11_CAP_CIPHER_TKIP = 0x00004000
NM_802_11_CAP_CIPHER_CCMP = 0x00008000 NM_802_11_CAP_CIPHER_CCMP = 0x00008000
class Network(gobject.GObject): class Network(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'init-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) 'init-failed' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'ssid-changed' : (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([]))
} }
def __init__(self, op): def __init__(self, op):
@ -115,6 +110,9 @@ class Network(gobject.GObject):
logging.debug("Net(%s): ssid '%s', mode %d, strength %d" % (self._op, logging.debug("Net(%s): ssid '%s', mode %d, strength %d" % (self._op,
self._ssid, self._mode, self._strength)) self._ssid, self._mode, self._strength))
self.emit('strength-changed')
self.emit('ssid-changed')
def _update_error_cb(self, err): def _update_error_cb(self, err):
logging.debug("Net(%s): failed to update. (%s)" % (self._op, err)) logging.debug("Net(%s): failed to update. (%s)" % (self._op, err))
self._valid = False self._valid = False
@ -131,27 +129,28 @@ class Network(gobject.GObject):
def set_strength(self, strength): def set_strength(self, strength):
self._strength = strength self._strength = strength
self.emit('strength-changed')
def is_valid(self): def is_valid(self):
return self._valid return self._valid
def add_to_menu(self, menu, callback, dev):
strength = self._strength
if strength > 100:
strength = 100
elif strength < 0:
strength = 0
item = NetworkMenuItem(text=self._ssid, percent=strength)
item.connect('button-press-event', callback, (dev, self))
menu.add_item(item)
class Device(gobject.GObject): class Device(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'init-failed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), 'init-failed': (gobject.SIGNAL_RUN_FIRST,
'activated': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, 'activated': (gobject.SIGNAL_RUN_FIRST,
([gobject.TYPE_PYOBJECT])) gobject.TYPE_NONE, ([])),
'deactivated': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([])),
'strength-changed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'network-appeared': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT])),
'network-disappeared': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
} }
def __init__(self, op): def __init__(self, op):
@ -178,8 +177,6 @@ class Device(gobject.GObject):
self._type = props[2] self._type = props[2]
self._udi = props[3] self._udi = props[3]
self._active = props[4] self._active = props[4]
if self._active:
self.emit('activated')
self._link = props[15] self._link = props[15]
self._caps = props[17] self._caps = props[17]
@ -192,6 +189,11 @@ class Device(gobject.GObject):
self._valid = True self._valid = True
if self._active:
self.emit('activated')
else:
self.emit('deactivated')
def _update_networks(self, net_ops, active_op): def _update_networks(self, net_ops, active_op):
for op in net_ops: for op in net_ops:
net = Network(op) net = Network(op)
@ -213,41 +215,15 @@ class Device(gobject.GObject):
self._active_net = None self._active_net = None
del self._networks[net_op] del self._networks[net_op]
def _add_to_menu_wired(self, menu, callback):
item = NetworkMenuItem(_("Wired Network"), stylesheet="nm.Bubble.Wired",
hi_stylesheet="nm.Bubble.Wired.Hi",
act_stylesheet="nm.Bubble.Wired.Activated")
item.connect('button-press-event', callback, (self, None))
menu.add_item(item)
def _add_to_menu_wireless(self, menu, callback, active_only):
act_net = None
if self._active_net and self._networks.has_key(self._active_net):
act_net = self._networks[self._active_net]
# Only add the active network if active_only == True
if active_only:
if act_net:
act_net.add_to_menu(menu, callback, self)
return
# Otherwise, add all networks _except_ the active one
for net in self._networks.values():
if not net.is_valid():
continue
if act_net == net:
continue
net.add_to_menu(menu, callback, self)
def add_to_menu(self, menu, callback, active_only=False):
if self._type == DEVICE_TYPE_802_3_ETHERNET:
self._add_to_menu_wired(menu, callback)
elif self._type == DEVICE_TYPE_802_11_WIRELESS:
self._add_to_menu_wireless(menu, callback, active_only)
def get_op(self): def get_op(self):
return self._op return self._op
def get_networks(self):
return self._networks.values()
def get_active_network(self):
return self.get_network(self._active_net)
def get_network(self, op): def get_network(self, op):
if self._networks.has_key(op): if self._networks.has_key(op):
return self._networks[op] return self._networks[op]
@ -276,12 +252,16 @@ class Device(gobject.GObject):
net = Network(network) net = Network(network)
self._networks[network] = net self._networks[network] = net
net.connect('init-failed', self._net_init_failed) net.connect('init-failed', self._net_init_failed)
self.emit('network-appeared', net)
def network_disappeared(self, network): def network_disappeared(self, network):
if not self._networks.has_key(network): if not self._networks.has_key(network):
return return
if network == self._active_net: if network == self._active_net:
self._active_net = None self._active_net = None
self.emit('network-disappeared', self._networks[network])
del self._networks[network] del self._networks[network]
def get_active(self): def get_active(self):
@ -309,171 +289,31 @@ class Device(gobject.GObject):
def get_capabilities(self): def get_capabilities(self):
return self._caps return self._caps
nm_bubble_wireless = {
'fill-color' : 0x646464FF,
'stroke-color' : 0x646464FF,
'progress-color': 0x333333FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wireless_hi = {
'fill-color' : 0x979797FF,
'stroke-color' : 0x979797FF,
'progress-color': 0x666666FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wireless_activated = {
'fill-color' : 0xA7A7A7FF,
'stroke-color' : 0xA7A7A7FF,
'progress-color': 0x777777FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wired = {
'fill-color' : 0x000000FF,
'stroke-color' : 0x000000FF,
'progress-color': 0x000000FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wired_hi = {
'fill-color' : 0x333333FF,
'stroke-color' : 0x333333FF,
'progress-color': 0x000000FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_bubble_wired_activated = {
'fill-color' : 0x444444FF,
'stroke-color' : 0x444444FF,
'progress-color': 0x000000FF,
'spacing' : style.space_unit,
'padding' : style.space_unit * 1.5
}
nm_menu_item_title = {
'xalign': hippo.ALIGNMENT_START,
'padding-left': 5,
'color' : 0xFFFFFFFF,
'font' : style.get_font_description('Bold', 1.2)
}
style.register_stylesheet("nm.Bubble.Wireless", nm_bubble_wireless)
style.register_stylesheet("nm.Bubble.Wireless.Hi", nm_bubble_wireless_hi)
style.register_stylesheet("nm.Bubble.Wireless.Activated", nm_bubble_wireless_activated)
style.register_stylesheet("nm.Bubble.Wired", nm_bubble_wired)
style.register_stylesheet("nm.Bubble.Wired.Hi", nm_bubble_wired_hi)
style.register_stylesheet("nm.Bubble.Wired.Activated", nm_bubble_wired_activated)
style.register_stylesheet("nm.MenuItem.Title", nm_menu_item_title)
class NetworkMenuItem(Bubble):
def __init__(self, text, percent=0, stylesheet="nm.Bubble.Wireless",
hi_stylesheet="nm.Bubble.Wireless.Hi",
act_stylesheet="nm.Bubble.Wireless.Activated"):
Bubble.__init__(self, percent=percent)
self._hover = False
self._default_stylesheet = stylesheet
self._hi_stylesheet = hi_stylesheet
self._act_stylesheet = act_stylesheet
style.apply_stylesheet(self, stylesheet)
text_item = hippo.CanvasText(text=text)
style.apply_stylesheet(text_item, 'nm.MenuItem.Title')
self.append(text_item)
self.connect('motion-notify-event', self._motion_notify_event_cb)
# Disable active hilight for now...
#self.connect('button-press-event', self._button_press_event_cb)
def _motion_notify_event_cb(self, widget, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
if not self._hover:
self._hover = True
style.apply_stylesheet(self, self._hi_stylesheet)
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
if self._hover:
self._hover = False
style.apply_stylesheet(self, self._default_stylesheet)
return True
def _button_press_event_cb(self, widget, event):
style.apply_stylesheet(self, self._act_stylesheet)
return False
class NetworkMenu(gtk.Window):
__gsignals__ = {
'action': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([int])),
}
def __init__(self):
gtk.Window.__init__(self, gtk.WINDOW_POPUP)
canvas = hippo.Canvas()
self.add(canvas)
canvas.show()
self._root = hippo.CanvasBox()
style.apply_stylesheet(self._root, 'menu')
canvas.set_root(self._root)
def add_separator(self):
separator = hippo.CanvasBox()
style.apply_stylesheet(separator, 'menu.Separator')
self._root.append(separator)
def add_item(self, item):
self._root.append(item)
NM_STATE_UNKNOWN = 0 NM_STATE_UNKNOWN = 0
NM_STATE_ASLEEP = 1 NM_STATE_ASLEEP = 1
NM_STATE_CONNECTING = 2 NM_STATE_CONNECTING = 2
NM_STATE_CONNECTED = 3 NM_STATE_CONNECTED = 3
NM_STATE_DISCONNECTED = 4 NM_STATE_DISCONNECTED = 4
ICON_WIRED = "stock-net-wired" class NMClient(gobject.GObject):
ICON_WIRELESS_00 = "stock-net-wireless-00" __gsignals__ = {
ICON_WIRELESS_01_20 = "stock-net-wireless-01-20" 'device-activated' : (gobject.SIGNAL_RUN_FIRST,
ICON_WIRELESS_21_40 = "stock-net-wireless-21-40" gobject.TYPE_NONE,
ICON_WIRELESS_41_60 = "stock-net-wireless-41-60" ([gobject.TYPE_PYOBJECT])),
ICON_WIRELESS_61_80 = "stock-net-wireless-61-80" 'device-removed' : (gobject.SIGNAL_RUN_FIRST,
ICON_WIRELESS_81_100 = "stock-net-wireless-81-100" gobject.TYPE_NONE,
([gobject.TYPE_PYOBJECT]))
}
class NMClientApp:
def __init__(self): def __init__(self):
gobject.GObject.__init__(self)
self.nminfo = None self.nminfo = None
self._nm_present = False self._nm_present = False
self._nm_state = NM_STATE_UNKNOWN self._nm_state = NM_STATE_UNKNOWN
self._update_timer = 0 self._update_timer = 0
self._active_device = None self._active_device = None
self._devices = {} self._devices = {}
self._key_dialog = None
self._icon_theme = gtk.icon_theme_get_default()
self._icons = {}
self._cur_icon = None
try:
self._icons = self._load_icons()
except RuntimeError:
logging.debug("Couldn't find required icon resources, will exit.")
os._exit(1)
self._setup_trayicon()
self._menu = None
self._hover_menu = False
self._timeline = Timeline(self)
self._timeline.add_tag('popup', 6, 6)
self._timeline.add_tag('before_popdown', 7, 7)
self._timeline.add_tag('popdown', 8, 8)
try: try:
self.nminfo = nminfo.NMInfo(self) self.nminfo = nminfo.NMInfo(self)
@ -484,22 +324,8 @@ class NMClientApp:
self._get_nm_state() self._get_nm_state()
self._get_initial_devices() self._get_initial_devices()
def _get_one_icon_pixbuf(self, name): def get_devices(self):
info = self._icon_theme.lookup_icon(name, 75, 0) return self._devices
if not info or not info.get_filename():
raise RuntimeError
return gtk.gdk.pixbuf_new_from_file(info.get_filename())
def _load_icons(self):
icons = {}
icons[ICON_WIRED] = self._get_one_icon_pixbuf(ICON_WIRED)
icons[ICON_WIRELESS_00] = self._get_one_icon_pixbuf(ICON_WIRELESS_00)
icons[ICON_WIRELESS_01_20] = self._get_one_icon_pixbuf(ICON_WIRELESS_01_20)
icons[ICON_WIRELESS_21_40] = self._get_one_icon_pixbuf(ICON_WIRELESS_21_40)
icons[ICON_WIRELESS_41_60] = self._get_one_icon_pixbuf(ICON_WIRELESS_41_60)
icons[ICON_WIRELESS_61_80] = self._get_one_icon_pixbuf(ICON_WIRELESS_61_80)
icons[ICON_WIRELESS_81_100] = self._get_one_icon_pixbuf(ICON_WIRELESS_81_100)
return icons
def _get_nm_state(self): def _get_nm_state(self):
# Grab NM's state # Grab NM's state
@ -507,163 +333,11 @@ class NMClientApp:
error_handler=self._get_state_error_cb) error_handler=self._get_state_error_cb)
def _get_state_reply_cb(self, state): def _get_state_reply_cb(self, state):
if self._nm_state != state:
self._schedule_icon_update(immediate=True)
self._nm_state = state self._nm_state = state
def _get_state_error_cb(self, err): def _get_state_error_cb(self, err):
logging.debug("Failed to get NetworkManager state! %s" % err) logging.debug("Failed to get NetworkManager state! %s" % err)
def _get_icon(self):
act_dev = None
if self._active_device and self._devices.has_key(self._active_device):
act_dev = self._devices[self._active_device]
pixbuf = None
if not self._nm_present \
or not act_dev \
or self._nm_state == NM_STATE_UNKNOWN \
or self._nm_state == NM_STATE_ASLEEP \
or self._nm_state == NM_STATE_DISCONNECTED:
pixbuf = self._icons[ICON_WIRELESS_00]
elif act_dev.get_type() == DEVICE_TYPE_802_3_ETHERNET:
pixbuf = self._icons[ICON_WIRED]
elif act_dev.get_type() == DEVICE_TYPE_802_11_WIRELESS:
strength = act_dev.get_strength()
if strength <= 0:
pixbuf = self._icons[ICON_WIRELESS_00]
elif strength >= 1 and strength <= 20:
pixbuf = self._icons[ICON_WIRELESS_01_20]
elif strength >= 21 and strength <= 40:
pixbuf = self._icons[ICON_WIRELESS_21_40]
elif strength >= 41 and strength <= 60:
pixbuf = self._icons[ICON_WIRELESS_41_60]
elif strength >= 61 and strength <= 80:
pixbuf = self._icons[ICON_WIRELESS_61_80]
elif strength >= 81 and strength:
pixbuf = self._icons[ICON_WIRELESS_81_100]
if not pixbuf:
pixbuf = self._icons[ICON_WIRELESS_00]
return pixbuf
def _setup_trayicon(self):
pixbuf = self._get_icon()
self._trayicon = gtk.status_icon_new_from_pixbuf(pixbuf)
self._trayicon.connect("popup_menu", self._status_icon_clicked)
self._trayicon.connect("activate", self._status_icon_clicked)
self._schedule_icon_update()
def _status_icon_clicked(self, button=0, time=None):
self._timeline.play(None, 'popup')
def _get_menu_position(self, menu, item):
(screen, rect, orientation) = item.get_geometry()
[item_x, item_y, item_w, item_h] = rect
[menu_w, menu_h] = menu.size_request()
x = item_x + item_w - menu_w
y = item_y + item_h
x = min(x, screen.get_width() - menu_w)
x = max(0, x)
y = min(y, screen.get_height() - menu_h)
y = max(0, y)
return (x, y)
def do_popup(self, current, n_frames):
if self._menu:
return
self._menu = self._create_menu()
self._menu.connect('enter-notify-event',
self._menu_enter_notify_event_cb)
self._menu.connect('leave-notify-event',
self._menu_leave_notify_event_cb)
(x, y) = self._get_menu_position(self._menu, self._trayicon)
self._menu.move(x, y)
self._menu.show_all()
def do_popdown(self, current, frame):
if self._menu:
self._menu.destroy()
self._menu = None
def _popdown(self):
self._timeline.play('popdown', 'popdown')
def _menu_enter_notify_event_cb(self, widget, event):
self._hover_menu = True
self._timeline.play('popup', 'popup')
def _menu_leave_notify_event_cb(self, widget, event):
self._hover_menu = False
self._popdown()
def _create_menu(self):
menu = NetworkMenu()
# Active device goes above the separator
act_dev = None
if self._active_device and self._devices.has_key(self._active_device):
act_dev = self._devices[self._active_device]
if act_dev:
act_dev.add_to_menu(menu, self._menu_item_clicked_cb, active_only=True)
menu.add_separator()
# Wired devices first, if they don't support carrier detect
for dev in self._devices.values():
if not dev.is_valid():
continue
if dev.get_type() != DEVICE_TYPE_802_3_ETHERNET:
continue
if dev.get_capabilities() & NM_DEVICE_CAP_CARRIER_DETECT:
continue
if dev == act_dev:
continue
dev.add_to_menu(menu, self._menu_item_clicked_cb)
# Wireless devices second
for dev in self._devices.values():
if not dev.is_valid():
continue
if dev.get_type() != DEVICE_TYPE_802_11_WIRELESS:
continue
dev.add_to_menu(menu, self._menu_item_clicked_cb)
return menu
def _update_icon(self):
pixbuf = self._get_icon()
if self._cur_icon != pixbuf:
self._trayicon.set_from_pixbuf(pixbuf)
self._cur_icon = pixbuf
blink = False
if self._nm_state == NM_STATE_CONNECTING:
blink = True
self._trayicon.set_blinking(blink)
self._update_timer = 0
return False
def _schedule_icon_update(self, immediate=False):
if immediate and self._update_timer:
gobject.source_remove(self._update_timer)
self._update_timer = 0
if self._update_timer != 0:
# There is already an update scheduled
return
if immediate:
self._update_timer = gobject.idle_add(self._update_icon)
else:
self._update_timer = gobject.timeout_add(2000, self._update_icon)
def _get_initial_devices_reply_cb(self, ops): def _get_initial_devices_reply_cb(self, ops):
for op in ops: for op in ops:
self._add_device(op) self._add_device(op)
@ -699,7 +373,8 @@ class NMClientApp:
dev.disconnect('init-failed') dev.disconnect('init-failed')
dev.disconnect('strength-changed') dev.disconnect('strength-changed')
del self._devices[dev_op] del self._devices[dev_op]
self._schedule_icon_update(immediate=True)
self.emit('device-removed', dev)
def _dev_activated_cb(self, dev): def _dev_activated_cb(self, dev):
op = dev.get_op() op = dev.get_op()
@ -708,7 +383,8 @@ class NMClientApp:
if not dev.get_active(): if not dev.get_active():
return return
self._active_device = op self._active_device = op
self._schedule_icon_update(immediate=True)
self.emit('device-activated', dev)
def _dev_strength_changed_cb(self, dev, strength): def _dev_strength_changed_cb(self, dev, strength):
op = dev.get_op() op = dev.get_op()
@ -716,7 +392,6 @@ class NMClientApp:
return return
if not dev.get_active(): if not dev.get_active():
return return
self._schedule_icon_update()
def get_device(self, dev_op): def get_device(self, dev_op):
if not self._devices.has_key(dev_op): if not self._devices.has_key(dev_op):
@ -760,8 +435,7 @@ class NMClientApp:
except dbus.DBusException: except dbus.DBusException:
pass pass
def _menu_item_clicked_cb(self, widget, event, dev_data): def set_active_device(self, device, network):
(device, network) = dev_data
net_op = "" net_op = ""
if network: if network:
net_op = network.get_op() net_op = network.get_op()
@ -776,8 +450,6 @@ class NMClientApp:
else: else:
raise dbus.DBusException(e) raise dbus.DBusException(e)
self._popdown()
def get_key_for_network(self, net, async_cb, async_err_cb): def get_key_for_network(self, net, async_cb, async_err_cb):
# Throw up a dialog asking for the key here, and set # Throw up a dialog asking for the key here, and set
# the authentication algorithm to the given one, if any # the authentication algorithm to the given one, if any
@ -832,7 +504,6 @@ class NMClientApp:
def state_change_sig_handler(self, state): def state_change_sig_handler(self, state):
self._nm_state = state self._nm_state = state
self._schedule_icon_update(immediate=True)
def device_activating_sig_handler(self, device): def device_activating_sig_handler(self, device):
self._active_device = device self._active_device = device
@ -842,7 +513,6 @@ class NMClientApp:
return return
self._active_device = device self._active_device = device
self._devices[device].set_active(True, ssid) self._devices[device].set_active(True, ssid)
self._schedule_icon_update(immediate=True)
def device_no_longer_active_sig_handler(self, device): def device_no_longer_active_sig_handler(self, device):
if not self._devices.has_key(device): if not self._devices.has_key(device):
@ -850,7 +520,6 @@ class NMClientApp:
if self._active_device == device: if self._active_device == device:
self._active_device = None self._active_device = None
self._devices[device].set_active(False) self._devices[device].set_active(False)
self._schedule_icon_update(immediate=True)
def name_owner_changed_sig_handler(self, name, old, new): def name_owner_changed_sig_handler(self, name, old, new):
if name != NM_SERVICE: if name != NM_SERVICE:
@ -858,7 +527,6 @@ class NMClientApp:
if (old and len(old)) and (not new and not len(new)): if (old and len(old)) and (not new and not len(new)):
# NM went away # NM went away
self._nm_present = False self._nm_present = False
self._schedule_icon_update(immediate=True)
for op in self._devices.keys(): for op in self._devices.keys():
del self._devices[op] del self._devices[op]
self._devices = {} self._devices = {}
@ -907,11 +575,3 @@ class NMClientApp:
if not self._devices.has_key(device): if not self._devices.has_key(device):
return return
self._devices[device].set_carrier(False) self._devices[device].set_carrier(False)
def run(self):
loop = gobject.MainLoop()
try:
loop.run()
except KeyboardInterrupt:
pass

View File

@ -20,6 +20,46 @@ from sugar.graphics.xocolor import XoColor
from sugar.presence import PresenceService from sugar.presence import PresenceService
from sugar.activity import bundleregistry from sugar.activity import bundleregistry
from model.BuddyModel import BuddyModel from model.BuddyModel import BuddyModel
from hardware import hardwaremanager
class AccessPointModel(gobject.GObject):
__gproperties__ = {
'name' : (str, None, None, None,
gobject.PARAM_READABLE),
'strength' : (int, None, None, 0, 100, 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('ssid-changed',
self._essid_changed_cb)
def _strength_changed_cb(self, nm_network):
self.notify('strength')
def _essid_changed_cb(self, nm_network):
self.notify('name')
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()
class ActivityModel: class ActivityModel:
def __init__(self, activity, bundle, service): def __init__(self, activity, bundle, service):
@ -41,17 +81,22 @@ class ActivityModel:
class MeshModel(gobject.GObject): class MeshModel(gobject.GObject):
__gsignals__ = { __gsignals__ = {
'activity-added': (gobject.SIGNAL_RUN_FIRST, 'activity-added': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
'activity-removed': (gobject.SIGNAL_RUN_FIRST, 'activity-removed': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
'buddy-added': (gobject.SIGNAL_RUN_FIRST, 'buddy-added': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])), gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT])),
'buddy-moved': (gobject.SIGNAL_RUN_FIRST, 'buddy-moved': (gobject.SIGNAL_RUN_FIRST,
gobject.TYPE_NONE, ([gobject.TYPE_PYOBJECT, gobject.TYPE_NONE,
gobject.TYPE_PYOBJECT])), ([gobject.TYPE_PYOBJECT,
'buddy-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_PYOBJECT])),
gobject.TYPE_NONE, ([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]))
} }
def __init__(self): def __init__(self):
@ -59,6 +104,7 @@ class MeshModel(gobject.GObject):
self._activities = {} self._activities = {}
self._buddies = {} self._buddies = {}
self._access_points = {}
self._bundle_registry = bundleregistry.get_registry() self._bundle_registry = bundleregistry.get_registry()
self._pservice = PresenceService.get_instance() self._pservice = PresenceService.get_instance()
@ -78,6 +124,42 @@ class MeshModel(gobject.GObject):
for service in self._pservice.get_services(): for service in self._pservice.get_services():
self._check_service(service) self._check_service(service)
network_manager = hardwaremanager.get_network_manager()
for nm_device in network_manager.get_devices():
self._add_network_device(nm_device)
network_manager.connect('device-activated',
self._nm_device_activated_cb)
def _nm_device_activated_cb(self, manager, nm_device):
self._add_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):
self._remove_access_point(nm_device, nm_network)
def _add_network_device(self, nm_device):
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)
def _add_access_point(self, nm_device, nm_network):
model = AccessPointModel(nm_device, nm_network)
self._access_points[nm_network.get_op()] = model
self.emit('access-point-added', model)
def _remove_access_point(self, nm_network):
self.emit('access-point-removed',
self._access_points[nm_network.get_op()])
del self._access_points[nm_network.get_op()]
def get_access_points(self):
return self._access_points.values()
def get_activities(self): def get_activities(self):
return self._activities.values() return self._activities.values()

View File

@ -4,4 +4,5 @@ sugar_PYTHON = \
device.py \ device.py \
devicesmodel.py \ devicesmodel.py \
battery.py \ battery.py \
network.py wirednetwork.py \
wirelessnetwork.py

View File

@ -5,7 +5,7 @@ class Device(device.Device):
device.Device.__init__(self) device.Device.__init__(self)
def get_type(self): def get_type(self):
return 'network' return 'battery'
def get_level(self): def get_level(self):
return 0 return 0

View File

@ -1,7 +1,10 @@
import gobject
from sugar import util from sugar import util
class Device(object): class Device(gobject.GObject):
def __init__(self): def __init__(self):
gobject.GObject.__init__(self)
self._id = util.unique_id() self._id = util.unique_id()
def get_type(self): def get_type(self):

View File

@ -1,8 +1,11 @@
import gobject import gobject
from model.devices import device from model.devices import device
from model.devices import network from model.devices import wirednetwork
from model.devices import wirelessnetwork
from model.devices import battery from model.devices import battery
from hardware import hardwaremanager
from hardware import nmclient
class DevicesModel(gobject.GObject): class DevicesModel(gobject.GObject):
__gsignals__ = { __gsignals__ = {
@ -17,13 +20,56 @@ class DevicesModel(gobject.GObject):
def __init__(self): def __init__(self):
gobject.GObject.__init__(self) gobject.GObject.__init__(self)
self._devices = [] self._devices = {}
self.add_device(network.Device())
self.add_device(battery.Device()) self.add_device(battery.Device())
self._observe_network_manager()
def _observe_network_manager(self):
network_manager = hardwaremanager.get_network_manager()
for device in network_manager.get_devices():
self._check_network_device(device)
network_manager.connect('device-activated',
self._network_device_activated_cb)
network_manager.connect('device-removed',
self._network_device_removed_cb)
def _network_device_activated_cb(self, network_manager, nm_device):
self._check_network_device(nm_device)
def _network_device_removed_cb(self, nm_device):
self._remove_network_device(nm_device)
def _network_device_deactivated_cb(self, nm_device):
self._remove_network_device(nm_device)
def _check_network_device(self, nm_device):
if not nm_device.is_valid():
return
if nm_device.get_type() == nmclient.DEVICE_TYPE_802_11_WIRELESS:
self._add_network_device(nm_device)
def _get_network_device(self, nm_device):
return self._devices[nm_device.get_op()]
def _add_network_device(self, nm_device):
self.add_device(wirelessnetwork.Device(nm_device))
nm_device.connect('deactivated',
self._network_device_deactivated_cb)
def _remove_network_device(self, nm_device):
self.remove_device(self._get_network_device(nm_device))
def __iter__(self): def __iter__(self):
return iter(self._devices) return iter(self._devices.values())
def add_device(self, device): def add_device(self, device):
self._devices.append(device) self._devices[device.get_id()] = device
self.emit('device-appeared', device)
def remove_device(self, device):
self.emit('device-disappeared', self._devices[device.get_id()])
del self._devices[device.get_id()]

View File

@ -1,11 +0,0 @@
from model.devices import device
class Device(device.Device):
def __init__(self):
device.Device.__init__(self)
def get_type(self):
return 'network'
def get_level(self):
return 0

View File

@ -0,0 +1,12 @@
from model.devices import device
class Device(device.Device):
def __init__(self, nm_device):
device.Device.__init__(self)
self._nm_device = device
def get_id(self):
return self._nm_device.get_op()
def get_type(self):
return 'wirednetwork'

View File

@ -0,0 +1,37 @@
import gobject
from model.devices import device
class Device(device.Device):
__gproperties__ = {
'name' : (str, None, None, None,
gobject.PARAM_READABLE),
'strength' : (int, None, None, 0, 100, 0,
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)
def _strength_changed_cb(self, nm_device, strength):
self.notify('strength')
def _essid_changed_cb(self, nm_device):
self.notify('name')
def do_get_property(self, pspec):
if pspec.name == 'strength':
return self._nm_device.get_strength()
elif pspec.name == 'name':
# FIXME
return None
def get_type(self):
return 'wirelessnetwork'
def get_id(self):
return self._nm_device.get_op()

View File

@ -1,5 +1,7 @@
import dbus import dbus
from sugar.activity import bundleregistry
_DBUS_SERVICE = "org.laptop.Shell" _DBUS_SERVICE = "org.laptop.Shell"
_DBUS_INTERFACE = "org.laptop.Shell" _DBUS_INTERFACE = "org.laptop.Shell"
_DBUS_PATH = "/org/laptop/Shell" _DBUS_PATH = "/org/laptop/Shell"
@ -15,5 +17,5 @@ class ShellService(dbus.service.Object):
@dbus.service.method(_DBUS_INTERFACE, in_signature="s", out_signature="b") @dbus.service.method(_DBUS_INTERFACE, in_signature="s", out_signature="b")
def add_bundle(self, bundle_path): def add_bundle(self, bundle_path):
registry = self._shellModel.get_bundle_registry() registry = bundleregistry.get_registry()
return registry.add_bundle(bundle_path) return registry.add_bundle(bundle_path)

View File

@ -64,12 +64,6 @@ model = ShellModel()
service = ShellService(model) service = ShellService(model)
shell = Shell(model) shell = Shell(model)
# Start the NetworkManager applet
# FIXME: do this somewhere else, better planned out
args = ["sugar-nm-applet"]
flags = gobject.SPAWN_SEARCH_PATH
result = gobject.spawn_async(args, flags=flags, standard_output=False)
tbh = TracebackUtils.TracebackHelper() tbh = TracebackUtils.TracebackHelper()
try: try:
gtk.main() gtk.main()

View File

@ -35,6 +35,8 @@ class BuddyMenu(Menu):
self._shell = shell self._shell = shell
Menu.__init__(self, buddy.get_name()) Menu.__init__(self, buddy.get_name())
self.props.border = 0
self.props.padding = units.points_to_pixels(5)
pixbuf = self._get_buddy_icon_pixbuf() pixbuf = self._get_buddy_icon_pixbuf()
if pixbuf: if pixbuf:
icon_item = hippo.CanvasImage() icon_item = hippo.CanvasImage()

View File

@ -11,5 +11,4 @@ sugar_PYTHON = \
clipboardmenu.py \ clipboardmenu.py \
keyhandler.py \ keyhandler.py \
OverlayWindow.py \ OverlayWindow.py \
Shell.py \ Shell.py
hardwaremanager.py

View File

@ -26,8 +26,6 @@ from view.ActivityHost import ActivityHost
from sugar.activity import activityfactory from sugar.activity import activityfactory
from view.frame.frame import Frame from view.frame.frame import Frame
from view.keyhandler import KeyHandler from view.keyhandler import KeyHandler
from view.hardwaremanager import HardwareManager
from _sugar import AudioManager
import sugar import sugar
class Shell(gobject.GObject): class Shell(gobject.GObject):
@ -40,9 +38,6 @@ class Shell(gobject.GObject):
self._current_host = None self._current_host = None
self._screen_rotation = 0 self._screen_rotation = 0
self._hw_manager = HardwareManager()
self._audio_manager = AudioManager()
self._home_window = HomeWindow(self) self._home_window = HomeWindow(self)
self._home_window.show() self._home_window.show()
self.set_zoom_level(sugar.ZOOM_HOME) self.set_zoom_level(sugar.ZOOM_HOME)
@ -88,12 +83,6 @@ class Shell(gobject.GObject):
if self._current_host: if self._current_host:
self._current_host.set_active(True) self._current_host.set_active(True)
def get_hardware_manager(self):
return self._hw_manager
def get_audio_manager(self):
return self._audio_manager
def get_model(self): def get_model(self):
return self._model return self._model

View File

@ -4,6 +4,7 @@ from sugar.graphics.canvasicon import CanvasIcon
from view.clipboardmenu import ClipboardMenu from view.clipboardmenu import ClipboardMenu
from sugar.graphics.xocolor import XoColor from sugar.graphics.xocolor import XoColor
from sugar.graphics import units from sugar.graphics import units
from sugar.graphics import color
from sugar.activity import activityfactory from sugar.activity import activityfactory
from sugar.clipboard import clipboardservice from sugar.clipboard import clipboardservice
from sugar import util from sugar import util
@ -43,9 +44,9 @@ class ClipboardIcon(CanvasIcon):
self._menu.set_state(name, percent, preview, activity) self._menu.set_state(name, percent, preview, activity)
if activity and percent < 100: if activity and percent < 100:
self.set_property('color', XoColor("#000000,#424242")) self.props.xo_color = XoColor("#000000,#424242")
else: else:
self.set_property('color', XoColor("#000000,#FFFFFF")) self.props.xo_color = XoColor("#000000,#FFFFFF")
def _activity_create_success_cb(self, handler, activity): def _activity_create_success_cb(self, handler, activity):
activity.start(util.unique_id()) activity.start(util.unique_id())
@ -81,3 +82,9 @@ class ClipboardIcon(CanvasIcon):
def get_object_id(self): def get_object_id(self):
return self._object_id return self._object_id
def prelight(self, enter):
if enter:
self.props.background_color = color.BLACK.get_int()
else:
self.props.background_color = color.TOOLBAR_BACKGROUND.get_int()

View File

@ -13,7 +13,7 @@ class ClipboardProgressBar(ClipboardBubble):
def __init__(self, percent = 0): def __init__(self, percent = 0):
self._text_item = None self._text_item = None
ClipboardBubble.__init__(self, percent=percent) ClipboardBubble.__init__(self, percent=percent)
self._text_item = hippo.CanvasText(text=str(percent) + ' %') self._text_item = hippo.CanvasText(text=str(percent) + ' %')
self._text_item.props.color = color.LABEL_TEXT.get_int() self._text_item.props.color = color.LABEL_TEXT.get_int()
self._text_item.props.font_desc = font.DEFAULT.get_pango_desc() self._text_item.props.font_desc = font.DEFAULT.get_pango_desc()
@ -35,6 +35,7 @@ class ClipboardMenu(Menu):
def __init__(self, name, percent, preview, activity): def __init__(self, name, percent, preview, activity):
Menu.__init__(self, name) Menu.__init__(self, name)
self.props.border = 0
if percent < 100: if percent < 100:
self._progress_bar = ClipboardProgressBar(percent) self._progress_bar = ClipboardProgressBar(percent)

View File

@ -3,4 +3,5 @@ sugar_PYTHON = \
__init__.py \ __init__.py \
battery.py \ battery.py \
deviceview.py \ deviceview.py \
network.py wirednetwork.py \
wirelessnetwork.py

View File

@ -1,6 +1,6 @@
from view.devices import deviceview from view.devices import deviceview
class DeviceView(deviceview.DeviceView) class DeviceView(deviceview.DeviceView):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-close' self.props.icon_name = 'theme:stock-close'

View File

@ -3,4 +3,4 @@ from view.devices import deviceview
class DeviceView(deviceview.DeviceView): class DeviceView(deviceview.DeviceView):
def __init__(self, model): def __init__(self, model):
deviceview.DeviceView.__init__(self, model) deviceview.DeviceView.__init__(self, model)
self.props.icon_name = 'theme:stock-close' self.props.icon_name = 'theme:stock-net-wired'

View File

@ -0,0 +1,34 @@
from view.devices import deviceview
class DeviceView(deviceview.DeviceView):
def __init__(self, model):
deviceview.DeviceView.__init__(self, model)
self._model = model
model.connect('notify::name', self._name_changed_cb)
model.connect('notify::strength', self._strength_changed_cb)
self._update_name()
self._update_icon()
def _strength_changed_cb(self, model, pspec):
self._update_icon()
def _name_changed_cb(self, model, pspec):
self._update_name()
def _update_name(self):
self.props.tooltip = self._model.props.name
def _update_icon(self):
strength = self._model.props.strength
if strength < 21:
self.props.icon_name = 'theme:stock-net-wireless-00'
elif strength < 41:
self.props.icon_name = 'theme:stock-net-wireless-21-40'
elif strength < 61:
self.props.icon_name = 'theme:stock-net-wireless-41-60'
elif strength < 81:
self.props.icon_name = 'theme:stock-net-wireless-61-80'
else:
self.props.icon_name = 'theme:stock-net-wireless-81-100'

View File

@ -17,15 +17,30 @@
import hippo import hippo
from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics.canvasicon import CanvasIcon
from sugar.graphics import color
from sugar.presence import PresenceService from sugar.presence import PresenceService
from view.BuddyIcon import BuddyIcon from view.BuddyIcon import BuddyIcon
from model.BuddyModel import BuddyModel from model.BuddyModel import BuddyModel
class FriendIcon(BuddyIcon):
def __init__(self, shell, popup_context, buddy):
BuddyIcon.__init__(self, shell, popup_context, buddy)
self._popup_context = popup_context
def get_popup_context(self):
return self._popup_context
def prelight(self, enter):
if enter:
self.props.background_color = color.BLACK.get_int()
else:
self.props.background_color = color.TOOLBAR_BACKGROUND.get_int()
class FriendsBox(hippo.CanvasBox): class FriendsBox(hippo.CanvasBox):
def __init__(self, shell, menu_shell): def __init__(self, shell, popup_context):
hippo.CanvasBox.__init__(self) hippo.CanvasBox.__init__(self)
self._shell = shell self._shell = shell
self._menu_shell = menu_shell self._popup_context = popup_context
self._activity_ps = None self._activity_ps = None
self._joined_hid = -1 self._joined_hid = -1
self._left_hid = -1 self._left_hid = -1
@ -48,7 +63,7 @@ class FriendsBox(hippo.CanvasBox):
return return
model = BuddyModel(buddy=buddy) model = BuddyModel(buddy=buddy)
icon = BuddyIcon(self._shell, self._menu_shell, model) icon = FriendIcon(self._shell, self._popup_context, model)
self.append(icon) self.append(icon)
self._buddies[buddy.get_name()] = icon self._buddies[buddy.get_name()] = icon

View File

@ -8,7 +8,6 @@ sugar_PYTHON = \
eventframe.py \ eventframe.py \
frame.py \ frame.py \
ZoomBox.py \ ZoomBox.py \
notificationtray.py \
overlaybox.py \ overlaybox.py \
PanelWindow.py \ PanelWindow.py \
framepopupcontext.py framepopupcontext.py

View File

@ -22,6 +22,7 @@ from sugar.graphics import units
class PanelWindow(gtk.Window): class PanelWindow(gtk.Window):
def __init__(self, orientation): def __init__(self, orientation):
gtk.Window.__init__(self) gtk.Window.__init__(self)
self._orientation = orientation
self.set_decorated(False) self.set_decorated(False)
self.connect('realize', self._realize_cb) self.connect('realize', self._realize_cb)
@ -29,35 +30,46 @@ class PanelWindow(gtk.Window):
self._canvas = hippo.Canvas() self._canvas = hippo.Canvas()
self._bg = hippo.CanvasBox(background_color=0x414141ff, self._bg = hippo.CanvasBox(background_color=0x414141ff,
orientation=orientation) orientation=self._orientation)
padding = units.grid_to_pixels(1)
if orientation == hippo.ORIENTATION_HORIZONTAL:
self._bg.props.padding_left = padding
self._bg.props.padding_right = padding
width = gtk.gdk.screen_width()
height = units.grid_to_pixels(1)
else:
self._bg.props.padding_top = padding
self._bg.props.padding_bottom = padding
width = units.grid_to_pixels(1)
height = gtk.gdk.screen_height()
self._update_size()
self._canvas.set_root(self._bg) self._canvas.set_root(self._bg)
self.add(self._canvas) self.add(self._canvas)
self._canvas.show() self._canvas.show()
self.resize(width, height) screen = gtk.gdk.screen_get_default()
screen.connect('size-changed', self._size_changed_cb)
def get_root(self): def get_root(self):
return self._bg return self._bg
def get_canvas(self): def get_canvas(self):
return self._canvas return self._canvas
def _update_size(self):
padding = units.grid_to_pixels(1)
if self._orientation == hippo.ORIENTATION_HORIZONTAL:
self._bg.props.padding_left = padding
self._bg.props.padding_right = padding
self._bg.props.padding_top = 0
self._bg.props.padding_bottom = 0
width = gtk.gdk.screen_width()
height = units.grid_to_pixels(1)
else:
self._bg.props.padding_left = 0
self._bg.props.padding_right = 0
self._bg.props.padding_top = padding
self._bg.props.padding_bottom = padding
width = units.grid_to_pixels(1)
height = gtk.gdk.screen_height()
self.resize(width, height)
def _realize_cb(self, widget): def _realize_cb(self, widget):
self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG) self.window.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
self.window.set_accept_focus(False) self.window.set_accept_focus(False)
def _size_changed_cb(self, screen):
self._update_size()

View File

@ -26,7 +26,6 @@ from view.frame.overlaybox import OverlayBox
from view.frame.FriendsBox import FriendsBox from view.frame.FriendsBox import FriendsBox
from view.frame.PanelWindow import PanelWindow from view.frame.PanelWindow import PanelWindow
from view.frame.clipboardpanelwindow import ClipboardPanelWindow from view.frame.clipboardpanelwindow import ClipboardPanelWindow
from view.frame.notificationtray import NotificationTray
from view.frame.framepopupcontext import FramePopupContext from view.frame.framepopupcontext import FramePopupContext
from model.ShellModel import ShellModel from model.ShellModel import ShellModel
from sugar.graphics.timeline import Timeline from sugar.graphics.timeline import Timeline
@ -50,6 +49,7 @@ class Frame:
self._hover_frame = False self._hover_frame = False
self._shell = shell self._shell = shell
self._mode = Frame.INACTIVE self._mode = Frame.INACTIVE
self._current_position = 0
self._timeline = Timeline(self) self._timeline = Timeline(self)
self._timeline.add_tag('slide_in', 18, 24) self._timeline.add_tag('slide_in', 18, 24)
@ -75,6 +75,9 @@ class Frame:
shell.get_model().connect('notify::state', shell.get_model().connect('notify::state',
self._shell_state_changed_cb) self._shell_state_changed_cb)
screen = gtk.gdk.screen_get_default()
screen.connect('size-changed', self._size_changed_cb)
def _create_top_panel(self): def _create_top_panel(self):
panel = self._create_panel(hippo.ORIENTATION_HORIZONTAL) panel = self._create_panel(hippo.ORIENTATION_HORIZONTAL)
@ -83,16 +86,6 @@ class Frame:
box = ZoomBox(self._shell, self._popup_context) box = ZoomBox(self._shell, self._popup_context)
root.append(box) root.append(box)
tray = NotificationTray()
tray_box = hippo.CanvasBox(box_width=units.grid_to_pixels(1),
box_height=units.grid_to_pixels(1),
xalign=hippo.ALIGNMENT_END)
tray_widget = hippo.CanvasWidget()
tray_widget.props.widget = tray
tray_box.append(tray_widget, gtk.EXPAND)
root.append(tray_box)
box = OverlayBox(self._shell) box = OverlayBox(self._shell)
root.append(box, hippo.PACK_FIXED) root.append(box, hippo.PACK_FIXED)
@ -219,24 +212,28 @@ class Frame:
def notify_key_release(self): def notify_key_release(self):
if self._mode == Frame.TEMPORARY: if self._mode == Frame.TEMPORARY:
self._timeline.play('before_slide_out', 'slide_out') self._timeline.play('before_slide_out', 'slide_out')
def _move(self, pos): def _move(self, pos):
self._current_position = pos
self._update_position()
def _update_position(self):
screen_h = gtk.gdk.screen_height() screen_h = gtk.gdk.screen_height()
screen_w = gtk.gdk.screen_width() screen_w = gtk.gdk.screen_width()
self._move_panel(self._top_panel, pos, self._move_panel(self._top_panel, self._current_position,
0, units.grid_to_pixels(-1), 0, units.grid_to_pixels(-1),
0, 0) 0, 0)
self._move_panel(self._bottom_panel, pos, self._move_panel(self._bottom_panel, self._current_position,
0, screen_h, 0, screen_h,
0, screen_h - units.grid_to_pixels(1)) 0, screen_h - units.grid_to_pixels(1))
self._move_panel(self._left_panel, pos, self._move_panel(self._left_panel, self._current_position,
units.grid_to_pixels(-1), 0, units.grid_to_pixels(-1), 0,
0, 0) 0, 0)
self._move_panel(self._right_panel, pos, self._move_panel(self._right_panel, self._current_position,
screen_w, 0, screen_w, 0,
screen_w - units.grid_to_pixels(1), 0) screen_w - units.grid_to_pixels(1), 0)
@ -255,7 +252,10 @@ class Frame:
self._move(0) self._move(0)
if not self._event_frame.is_visible(): if not self._event_frame.is_visible():
self._event_frame.show() self._event_frame.show()
def _size_changed_cb(self, screen):
self._update_position()
def is_visible(self): def is_visible(self):
return self._top_panel.props.visible return self._top_panel.props.visible

View File

@ -36,7 +36,7 @@ class FramePopupContext(PopupContext):
left_x = item_x + item_w left_x = item_x + item_w
left_y = item_y left_y = item_y
right_x = item_x + item_w right_x = item_x - popup_w
right_y = item_y right_y = item_y
top_x = item_x top_x = item_x
top_y = item_y + item_h top_y = item_y + item_h

View File

@ -1,18 +0,0 @@
import gtk
from _sugar import TrayManager
class NotificationTray(gtk.HBox):
def __init__(self):
gtk.HBox.__init__(self)
self._manager = TrayManager()
self._manager.connect('tray-icon-added', self._icon_added_cb)
self._manager.connect('tray-icon-removed', self._icon_removed_cb)
self._manager.manage_screen(gtk.gdk.screen_get_default())
def _icon_added_cb(self, manager, icon):
self.pack_start(icon, False)
def _icon_removed_cb(self, manager, icon):
icon.destroy()

View File

@ -45,14 +45,31 @@ class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
shell_model.connect('notify::state', shell_model.connect('notify::state',
self._shell_state_changed_cb) self._shell_state_changed_cb)
self._device_icons = [] self._device_icons = {}
for device in shell_model.get_devices():
devices_model = shell_model.get_devices()
for device in devices_model:
self._add_device(device) 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): def _add_device(self, device):
view = deviceview.create(device) view = deviceview.create(device)
self.append(view, hippo.PACK_FIXED) self.append(view, hippo.PACK_FIXED)
self._device_icons.append(view) self._device_icons[device.get_id()] = view
def _remove_device(self, device):
self.remove(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)
def _shell_state_changed_cb(self, model, pspec): def _shell_state_changed_cb(self, model, pspec):
# FIXME handle all possible mode switches # FIXME handle all possible mode switches
@ -74,7 +91,7 @@ class HomeBox(hippo.CanvasBox, hippo.CanvasItem):
(height - icon_height) / 2) (height - icon_height) / 2)
i = 0 i = 0
for icon in self._device_icons: for icon in self._device_icons.values():
angle = 2 * math.pi / len(self._device_icons) * i + math.pi / 2 angle = 2 * math.pi / len(self._device_icons) * i + math.pi / 2
radius = units.grid_to_pixels(5) radius = units.grid_to_pixels(5)

View File

@ -22,8 +22,52 @@ import gobject
from sugar.graphics.spreadbox import SpreadBox from sugar.graphics.spreadbox import SpreadBox
from sugar.graphics.snowflakebox import SnowflakeBox from sugar.graphics.snowflakebox import SnowflakeBox
from sugar.graphics.canvasicon import CanvasIcon from sugar.graphics.canvasicon import CanvasIcon
from hardware import hardwaremanager
from view.BuddyIcon import BuddyIcon from view.BuddyIcon import BuddyIcon
class AccessPointView(CanvasIcon):
def __init__(self, model):
CanvasIcon.__init__(self)
self._model = model
self.connect('activated', self._activate_cb)
model.connect('notify::strength', self._strength_changed_cb)
model.connect('notify::name', self._name_changed_cb)
self._update_icon()
self._update_name()
def _strength_changed_cb(self, model, pspec):
self._update_icon()
def _name_changed_cb(self, model, pspec):
self._update_name()
def _activate_cb(self, icon):
network_manager = hardwaremanager.get_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.props.tooltip = self._model.props.name
def _update_icon(self):
strength = self._model.props.strength
if strength < 21:
self.props.icon_name = 'theme:stock-net-wireless-00'
elif strength < 41:
self.props.icon_name = 'theme:stock-net-wireless-21-40'
elif strength < 61:
self.props.icon_name = 'theme:stock-net-wireless-41-60'
elif strength < 81:
self.props.icon_name = 'theme:stock-net-wireless-61-80'
else:
self.props.icon_name = 'theme:stock-net-wireless-81-100'
class ActivityView(SnowflakeBox): class ActivityView(SnowflakeBox):
def __init__(self, shell, menu_shell, model): def __init__(self, shell, menu_shell, model):
SnowflakeBox.__init__(self) SnowflakeBox.__init__(self)
@ -63,6 +107,7 @@ class MeshBox(SpreadBox):
self._model = shell.get_model().get_mesh() self._model = shell.get_model().get_mesh()
self._buddies = {} self._buddies = {}
self._activities = {} self._activities = {}
self._access_points = {}
self._buddy_to_activity = {} self._buddy_to_activity = {}
for buddy_model in self._model.get_buddies(): for buddy_model in self._model.get_buddies():
@ -78,6 +123,14 @@ class MeshBox(SpreadBox):
self._model.connect('activity-added', self._activity_added_cb) self._model.connect('activity-added', self._activity_added_cb)
self._model.connect('activity-removed', self._activity_removed_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)
def _buddy_added_cb(self, model, buddy_model): def _buddy_added_cb(self, model, buddy_model):
self._add_alone_buddy(buddy_model) self._add_alone_buddy(buddy_model)
@ -93,6 +146,12 @@ class MeshBox(SpreadBox):
def _activity_removed_cb(self, model, activity_model): def _activity_removed_cb(self, model, activity_model):
self._remove_activity(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._add_access_point(ap_model)
def _add_alone_buddy(self, buddy_model): def _add_alone_buddy(self, buddy_model):
icon = BuddyIcon(self._shell, self._menu_shell, buddy_model) icon = BuddyIcon(self._shell, self._menu_shell, buddy_model)
self.add_item(icon) self.add_item(icon)
@ -136,3 +195,14 @@ class MeshBox(SpreadBox):
icon = self._activities[activity_model.get_id()] icon = self._activities[activity_model.get_id()]
self.remove_item(icon) self.remove_item(icon)
del self._activities[activity_model.get_id()] del self._activities[activity_model.get_id()]
def _add_access_point(self, ap_model):
icon = AccessPointView(ap_model)
self.add_item(icon)
self._access_points[ap_model.get_id()] = icon
def _remove_access_point(self, ap_model):
icon = self._access_points[ap_model.get_id()]
self.remove_item(icon)
del self._access_points[ap_model.get_id()]

View File

@ -2,7 +2,7 @@ import dbus
import gobject import gobject
from sugar import env from sugar import env
from view.hardwaremanager import HardwareManager from hardware import hardwaremanager
from model.ShellModel import ShellModel from model.ShellModel import ShellModel
from _sugar import KeyGrabber from _sugar import KeyGrabber
import sugar import sugar
@ -40,8 +40,8 @@ _actions_table = {
class KeyHandler(object): class KeyHandler(object):
def __init__(self, shell): def __init__(self, shell):
self._shell = shell self._shell = shell
self._hw_manager = shell.get_hardware_manager() self._hw_manager = hardwaremanager.get_hardware_manager()
self._audio_manager = shell.get_audio_manager() self._audio_manager = hardwaremanager.get_audio_manager()
self._screen_rotation = 0 self._screen_rotation = 0
self._key_grabber = KeyGrabber() self._key_grabber = KeyGrabber()
@ -90,10 +90,10 @@ class KeyHandler(object):
self._audio_manager.set_volume(100) self._audio_manager.set_volume(100)
def handle_color_mode(self): def handle_color_mode(self):
self._hw_manager.set_display_mode(HardwareManager.COLOR_MODE) self._hw_manager.set_display_mode(hardwaremanager.COLOR_MODE)
def handle_b_and_w_mode(self): def handle_b_and_w_mode(self):
self._hw_manager.set_display_mode(HardwareManager.B_AND_W_MODE) self._hw_manager.set_display_mode(hardwaremanager.B_AND_W_MODE)
def handle_console(self): def handle_console(self):
gobject.idle_add(self._toggle_console_visibility_cb) gobject.idle_add(self._toggle_console_visibility_cb)

View File

@ -47,8 +47,6 @@ class Activity(gtk.Window):
self._bus = ActivityService(self) self._bus = ActivityService(self)
self.present()
def get_service_name(self): def get_service_name(self):
"""Gets the activity service name.""" """Gets the activity service name."""
return os.environ['SUGAR_BUNDLE_SERVICE_NAME'] return os.environ['SUGAR_BUNDLE_SERVICE_NAME']

View File

@ -61,6 +61,7 @@ class ActivityFactoryService(dbus.service.Object):
def create(self, handle): def create(self, handle):
activity_handle = activityhandle.create_from_dict(handle) activity_handle = activityhandle.create_from_dict(handle)
activity = self._constructor(activity_handle) activity = self._constructor(activity_handle)
activity.present()
self._activities.append(activity) self._activities.append(activity)
activity.connect('destroy', self._activity_destroy_cb) activity.connect('destroy', self._activity_destroy_cb)

View File

@ -143,7 +143,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
'stroke-color' : (object, None, None, 'stroke-color' : (object, None, None,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'scale' : (float, None, None, 'scale' : (float, None, None,
0.0, 1024.0, 1.0, 0.0, 1024.0, units.STANDARD_ICON_SCALE,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
'cache' : (bool, None, None, False, 'cache' : (bool, None, None, False,
gobject.PARAM_READWRITE), gobject.PARAM_READWRITE),
@ -156,7 +156,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
def __init__(self, **kwargs): def __init__(self, **kwargs):
self._buffers = {} self._buffers = {}
self._cur_buffer = None self._cur_buffer = None
self._scale = 1.0 self._scale = units.STANDARD_ICON_SCALE
self._fill_color = None self._fill_color = None
self._stroke_color = None self._stroke_color = None
self._icon_name = None self._icon_name = None
@ -173,8 +173,8 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
hippo.CanvasBox.__init__(self, **kwargs) hippo.CanvasBox.__init__(self, **kwargs)
self.connect('motion-notify-event', self._motion_notify_event_cb) self.connect_after('button-press-event', self._button_press_event_cb)
self.connect('button-press-event', self._button_press_event_cb) self.connect_after('motion-notify-event', self._motion_notify_event_cb)
def _clear_buffers(self): def _clear_buffers(self):
cur_buf_key = self._get_current_buffer_key() cur_buf_key = self._get_current_buffer_key()
@ -314,17 +314,17 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
def _button_press_event_cb(self, item, event): def _button_press_event_cb(self, item, event):
item.emit_activated() item.emit_activated()
return False
def get_popup(self): def get_popup(self):
if self._tooltip: if self._tooltip:
tooltip_popup = Popup() tooltip_popup = Popup()
canvas_text = hippo.CanvasText(text=self._tooltip) text = hippo.CanvasText(text=self._tooltip)
canvas_text.props.background_color = color.MENU_BACKGROUND.get_int() text.props.background_color = color.MENU_BACKGROUND.get_int()
canvas_text.props.border_color = color.MENU_BORDER.get_int() text.props.color = color.LABEL_TEXT.get_int()
canvas_text.props.border = units.points_to_pixels(1) text.props.font_desc = font.DEFAULT.get_pango_desc()
canvas_text.props.color = color.LABEL_TEXT.get_int() text.props.padding = units.points_to_pixels(5)
canvas_text.props.font_desc = font.DEFAULT.get_pango_desc() tooltip_popup.append(text)
tooltip_popup.append(canvas_text)
return tooltip_popup return tooltip_popup
else: else:
@ -355,7 +355,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
[x, y] = context.translate_to_screen(self) [x, y] = context.translate_to_screen(self)
# TODO: Any better place to do this? # TODO: Any better place to do this?
popup.props.box_width = max(popup.props.box_width, popup.props.box_width = max(popup.get_width_request(),
self.get_width_request()) self.get_width_request())
[width, height] = self.get_allocation() [width, height] = self.get_allocation()
@ -364,7 +364,7 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
popup.popup(x, y) popup.popup(x, y)
popup.connect('motion-notify-event', popup.connect('motion-notify-event',
self._popup_motion_notify_event_cb) self.popup_motion_notify_event_cb)
popup.connect('action-completed', popup.connect('action-completed',
self._popup_action_completed_cb) self._popup_action_completed_cb)
@ -389,17 +389,29 @@ class CanvasIcon(hippo.CanvasBox, hippo.CanvasItem):
def _motion_notify_event_cb(self, button, event): def _motion_notify_event_cb(self, button, event):
if event.detail == hippo.MOTION_DETAIL_ENTER: if event.detail == hippo.MOTION_DETAIL_ENTER:
self._timeline.play(None, 'popup') self._timeline.play(None, 'popup')
self.prelight(enter=True)
elif event.detail == hippo.MOTION_DETAIL_LEAVE: elif event.detail == hippo.MOTION_DETAIL_LEAVE:
if not self._hover_popup: if not self._hover_popup:
self._timeline.play('before_popdown', 'popdown') self._timeline.play('before_popdown', 'popdown')
self.prelight(enter=False)
return False
def _popup_motion_notify_event_cb(self, popup, event): def popup_motion_notify_event_cb(self, popup, event):
if event.detail == hippo.MOTION_DETAIL_ENTER: if event.detail == hippo.MOTION_DETAIL_ENTER:
self._hover_popup = True self._hover_popup = True
self._timeline.play('popup', 'popup') self._timeline.play('popup', 'popup')
self.prelight(enter=True)
elif event.detail == hippo.MOTION_DETAIL_LEAVE: elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self._hover_popup = False self._hover_popup = False
self._timeline.play('popdown', 'popdown') self._timeline.play('popdown', 'popdown')
self.prelight(enter=False)
return False
def _popup_action_completed_cb(self, popup): def _popup_action_completed_cb(self, popup):
self.popdown() self.popdown()
def prelight(self, enter):
"""
Override this method for adding prelighting behavior.
"""
pass

View File

@ -12,7 +12,8 @@ _system_colors = {
'entry-border' : '#D1D1D2', 'entry-border' : '#D1D1D2',
'label-text' : '#FFFFFF', 'label-text' : '#FFFFFF',
'desktop-background' : '#E2E2E3', 'desktop-background' : '#E2E2E3',
'menu-background' : '#414141', 'menu-background' : '#000000',
'menu-background-hover' : '#424242',
'menu-separator' : '#D1D1D2', 'menu-separator' : '#D1D1D2',
'menu-border' : '#D1D1D2', 'menu-border' : '#D1D1D2',
'button-normal' : '#FFFFFF', 'button-normal' : '#FFFFFF',
@ -90,6 +91,7 @@ ENTRY_BORDER = SystemColor('entry-border')
LABEL_TEXT = SystemColor('label-text') LABEL_TEXT = SystemColor('label-text')
DESKTOP_BACKGROUND = SystemColor('desktop-background') DESKTOP_BACKGROUND = SystemColor('desktop-background')
MENU_BACKGROUND = SystemColor('menu-background') MENU_BACKGROUND = SystemColor('menu-background')
MENU_BACKGROUND_HOVER = SystemColor('menu-background-hover')
MENU_SEPARATOR = SystemColor('menu-separator') MENU_SEPARATOR = SystemColor('menu-separator')
MENU_BORDER = SystemColor('menu-border') MENU_BORDER = SystemColor('menu-border')
BUTTON_NORMAL = SystemColor('button-normal') BUTTON_NORMAL = SystemColor('button-normal')

View File

@ -21,8 +21,8 @@ import gobject
import hippo import hippo
from canvasicon import CanvasIcon from canvasicon import CanvasIcon
from xocolor import XoColor
from sugar.graphics import units from sugar.graphics import units
from sugar.graphics import color
from sugar import profile from sugar import profile
STANDARD_SIZE = 0 STANDARD_SIZE = 0
@ -44,16 +44,20 @@ class IconButton(CanvasIcon):
CanvasIcon.__init__(self, cache=True, **kwargs) CanvasIcon.__init__(self, cache=True, **kwargs)
self._prelight_color = profile.get_color() if not self.props.fill_color:
self._inactive_color = XoColor('#808080,#424242') self.props.fill_color = color.BUTTON_BACKGROUND_NORMAL
self._normal_color = XoColor('white') if not self.props.stroke_color:
self.props.stroke_color = color.BUTTON_NORMAL
if not self.props.xo_color: self.props.background_color = color.BUTTON_BACKGROUND_NORMAL.get_int()
self.props.xo_color = self._normal_color
self._normal_fill_color = self.props.fill_color
self._normal_stroke_color = self.props.stroke_color
self._normal_background_color = self.props.background_color
self._set_size(STANDARD_SIZE) self._set_size(STANDARD_SIZE)
self.connect('button-press-event', self._button_press_event_cb) self.connect('button-press-event',
self._icon_button_button_press_event_cb)
def _set_size(self, size): def _set_size(self, size):
if size == SMALL_SIZE: if size == SMALL_SIZE:
@ -73,9 +77,13 @@ class IconButton(CanvasIcon):
elif pspec.name == 'active': elif pspec.name == 'active':
self._active = value self._active = value
if self._active: if self._active:
self.props.xo_color = self._normal_color self.props.fill_color = self._normal_fill_color
self.props.stroke_color = self._normal_stroke_color
self.props.background_color = self._normal_background_color
else: else:
self.props.xo_color = self._inactive_color self.props.fill_color = color.BUTTON_BACKGROUND_INACTIVE
self.props.stroke_color = color.BUTTON_INACTIVE
self.props.background_color = color.BUTTON_BACKGROUND_INACTIVE.get_int()
else: else:
CanvasIcon.do_set_property(self, pspec, value) CanvasIcon.do_set_property(self, pspec, value)
@ -87,7 +95,17 @@ class IconButton(CanvasIcon):
else: else:
return CanvasIcon.do_get_property(self, pspec) return CanvasIcon.do_get_property(self, pspec)
def _button_press_event_cb(self, widget, event): def _icon_button_button_press_event_cb(self, widget, event):
if self._active: if self._active:
self.emit_activated() self.emit_activated()
return True return True
def prelight(self, enter):
if enter:
if self._active:
self.props.fill_color = color.BLACK
self.props.background_color = color.BLACK.get_int()
else:
if self._active:
self.props.fill_color = self._normal_fill_color
self.props.background_color = self._normal_background_color

View File

@ -56,6 +56,14 @@ class MenuItem(hippo.CanvasBox):
self._canvas_text.props.color = color.LABEL_TEXT.get_int() self._canvas_text.props.color = color.LABEL_TEXT.get_int()
self._canvas_text.props.font_desc = font.DEFAULT.get_pango_desc() self._canvas_text.props.font_desc = font.DEFAULT.get_pango_desc()
self.append(self._canvas_text) self.append(self._canvas_text)
self.connect('motion-notify-event', self._motion_notify_event_cb)
def _motion_notify_event_cb(self, menu_item, event):
if event.detail == hippo.MOTION_DETAIL_ENTER:
self.props.background_color = color.MENU_BACKGROUND_HOVER.get_int()
elif event.detail == hippo.MOTION_DETAIL_LEAVE:
self.props.background_color = color.MENU_BACKGROUND.get_int()
def do_set_property(self, pspec, value): def do_set_property(self, pspec, value):
if pspec.name == 'action-id': if pspec.name == 'action-id':

View File

@ -64,12 +64,14 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
self._round_box = RoundBox() self._round_box = RoundBox()
self._round_box.props.border_color = color.FRAME_BORDER.get_int() self._round_box.props.border_color = color.FRAME_BORDER.get_int()
self._round_box.props.spacing = units.points_to_pixels(3)
self._round_box.props.padding = units.points_to_pixels(1)
self.append(self._round_box, hippo.PACK_EXPAND) self.append(self._round_box, hippo.PACK_EXPAND)
self._canvas_text = hippo.CanvasText() self._canvas_text = hippo.CanvasText(text=_('No options'),
self._canvas_text.props.text = _('No options') color=color.LABEL_TEXT.get_int(),
self._canvas_text.props.color = color.LABEL_TEXT.get_int() font_desc=font.DEFAULT.get_pango_desc(),
self._canvas_text.props.font_desc = font.DEFAULT.get_pango_desc() xalign=hippo.ALIGNMENT_START)
self._round_box.append(self._canvas_text, hippo.PACK_EXPAND) self._round_box.append(self._canvas_text, hippo.PACK_EXPAND)
# TODO: Substitute for the right icon. # TODO: Substitute for the right icon.
@ -100,6 +102,16 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
self._menu.add_item(menu_item) self._menu.add_item(menu_item)
def do_get_width_request(self):
max_width = max(self._canvas_text.do_get_content_width_request(self._canvas_text),
self._menu.do_get_content_width_request(self._menu))
self._canvas_text.props.box_width = max_width
current_width = hippo.CanvasBox.do_get_width_request(self)
self._menu.props.box_width = current_width
return current_width
def add_separator(self): def add_separator(self):
self._menu.add_separator() self._menu.add_separator()
@ -110,11 +122,11 @@ class OptionMenu(hippo.CanvasBox, hippo.CanvasItem):
context = self._round_box.get_context() context = self._round_box.get_context()
[x, y] = context.translate_to_screen(self._round_box) [x, y] = context.translate_to_screen(self._round_box)
# TODO: Any better place to do this?
self._menu.props.box_width = self.get_width_request()
[width, height] = self._round_box.get_allocation() [width, height] = self._round_box.get_allocation()
self._menu.popup(x, y + height) self._menu.popup(x, y + height)
# Grab the pointer so the menu will popdown on mouse click.
self._menu.grab_pointer()
def _menu_action_cb(self, menu, menu_item): def _menu_action_cb(self, menu, menu_item):
action_id = menu_item.props.action_id action_id = menu_item.props.action_id

View File

@ -46,5 +46,13 @@ class Popup(hippo.CanvasBox, hippo.CanvasItem):
self._window.hide() self._window.hide()
self._visible = False self._visible = False
def grab_pointer(self):
gtk.gdk.pointer_grab(self._window.window, owner_events=False,
event_mask=gtk.gdk.BUTTON_PRESS_MASK |
gtk.gdk.BUTTON_RELEASE_MASK |
gtk.gdk.ENTER_NOTIFY_MASK |
gtk.gdk.LEAVE_NOTIFY_MASK |
gtk.gdk.POINTER_MOTION_MASK)
def _button_press_event_cb(self, menu, event): def _button_press_event_cb(self, menu, event):
self.emit('action-completed') self.emit('action-completed')

View File

@ -31,7 +31,7 @@ class RoundBox(hippo.CanvasBox, hippo.CanvasItem):
hippo.CanvasBox.__init__(self, **kwargs) hippo.CanvasBox.__init__(self, **kwargs)
# TODO: we should calculate this value depending on the height of the box. # TODO: we should calculate this value depending on the height of the box.
self._radius = units.points_to_pixels(10) self._radius = units.points_to_pixels(7)
self.props.orientation = hippo.ORIENTATION_HORIZONTAL self.props.orientation = hippo.ORIENTATION_HORIZONTAL
self.props.border_top = self._BORDER_DEFAULT self.props.border_top = self._BORDER_DEFAULT

View File

@ -85,7 +85,7 @@ class SnowflakeBox(hippo.CanvasBox, hippo.CanvasItem):
return width return width
def do_allocate(self, width, height, origin_changed): def do_allocate(self, width, height, origin_changed):
hippo.CanvasBox.do_allocate(self, width, height) hippo.CanvasBox.do_allocate(self, width, height, origin_changed)
self._layout_root() self._layout_root()

View File

@ -48,7 +48,7 @@ canvas.set_root(vbox)
toolbar = Toolbar() toolbar = Toolbar()
vbox.append(toolbar) vbox.append(toolbar)
button = IconButton('theme:stock-close') button = IconButton(icon_name='theme:stock-close')
toolbar.append(button) toolbar.append(button)
OPTION_ANYTHING = 1 OPTION_ANYTHING = 1

View File

@ -1,6 +1,6 @@
VERSION=0.63 VERSION=0.63
DATE=`date +%Y%m%d` DATE=`date +%Y%m%d`
RELEASE=2.21 RELEASE=2.22
TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2 TARBALL=sugar-$VERSION-$RELEASE.${DATE}git.tar.bz2
rm sugar-$VERSION.tar.bz2 rm sugar-$VERSION.tar.bz2

View File

@ -14,7 +14,7 @@ def get_bundle_root_dir(file_names):
bundle_root_dir = None bundle_root_dir = None
for file_name in file_names: for file_name in file_names:
if not bundle_root_dir: if not bundle_root_dir:
bundle_root_dir = file_name.partition('/')[0] bundle_root_dir = file_name.split('/')[0]
if not bundle_root_dir.endswith('.activity'): if not bundle_root_dir.endswith('.activity'):
raise 'Incorrect bundle.' raise 'Incorrect bundle.'
else: else: