From 004e5e331b89484f2448ab81d0e97cfc3b47af18 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 21 Sep 2007 11:11:35 +0000 Subject: [PATCH] Fix ref count error for account objects. 2007-09-21 Xavier Claessens * libempathy-gtk/empathy-contact-list-view.c: Fix ref count error for account objects. * libempathy/empathy-contact-manager.c: Disconnect signals from MissionControl object when finalising the contact manager. * configure.ac: * megaphone/src/megaphone-applet.c: * megaphone/src/Makefile.am: * megaphone/src/megaphone-applet.h: * megaphone/data/GNOME_Megaphone_Applet.schemas.in: * megaphone/data/Makefile.am: * megaphone/data/GNOME_Megaphone_Applet.server.in.in: * megaphone/data/GNOME_Megaphone_Applet.xml: * megaphone/Makefile.am: * nothere/src/nothere-applet.c: * nothere/src/Makefile.am: * nothere/src/nothere-applet.h: * nothere/data/Makefile.am: * nothere/data/GNOME_NotHere_Applet.server.in.in: * nothere/data/GNOME_NotHere_Applet.xml: * nothere/Makefile.am: * Makefile.am: * po/POTFILES.in: * po/POTFILES.skip: Add Megaphone and Nothere applets. Fixes bug #464954 (Raphael Slinckx, Xavier Claessens). svn path=/trunk/; revision=303 --- ChangeLog | 29 + Makefile.am | 8 + configure.ac | 69 ++- libempathy-gtk/empathy-contact-list-view.c | 1 - libempathy/empathy-contact-manager.c | 5 + megaphone/Makefile.am | 2 + .../data/GNOME_Megaphone_Applet.schemas.in | 20 + .../data/GNOME_Megaphone_Applet.server.in.in | 25 + megaphone/data/GNOME_Megaphone_Applet.xml | 9 + megaphone/data/Makefile.am | 35 ++ megaphone/src/Makefile.am | 17 + megaphone/src/megaphone-applet.c | 572 ++++++++++++++++++ megaphone/src/megaphone-applet.h | 53 ++ nothere/Makefile.am | 2 + .../data/GNOME_NotHere_Applet.server.in.in | 25 + nothere/data/GNOME_NotHere_Applet.xml | 7 + nothere/data/Makefile.am | 35 ++ nothere/src/Makefile.am | 17 + nothere/src/nothere-applet.c | 120 ++++ nothere/src/nothere-applet.h | 52 ++ po/POTFILES.in | 11 +- po/POTFILES.skip | 3 + 22 files changed, 1112 insertions(+), 5 deletions(-) create mode 100644 megaphone/Makefile.am create mode 100644 megaphone/data/GNOME_Megaphone_Applet.schemas.in create mode 100644 megaphone/data/GNOME_Megaphone_Applet.server.in.in create mode 100644 megaphone/data/GNOME_Megaphone_Applet.xml create mode 100644 megaphone/data/Makefile.am create mode 100644 megaphone/src/Makefile.am create mode 100644 megaphone/src/megaphone-applet.c create mode 100644 megaphone/src/megaphone-applet.h create mode 100644 nothere/Makefile.am create mode 100644 nothere/data/GNOME_NotHere_Applet.server.in.in create mode 100644 nothere/data/GNOME_NotHere_Applet.xml create mode 100644 nothere/data/Makefile.am create mode 100644 nothere/src/Makefile.am create mode 100644 nothere/src/nothere-applet.c create mode 100644 nothere/src/nothere-applet.h diff --git a/ChangeLog b/ChangeLog index d90001b4..f7330eb4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2007-09-21 Xavier Claessens + + * libempathy-gtk/empathy-contact-list-view.c: Fix ref count error for + account objects. + + * libempathy/empathy-contact-manager.c: Disconnect signals from + MissionControl object when finalising the contact manager. + + * configure.ac: + * megaphone/src/megaphone-applet.c: + * megaphone/src/Makefile.am: + * megaphone/src/megaphone-applet.h: + * megaphone/data/GNOME_Megaphone_Applet.schemas.in: + * megaphone/data/Makefile.am: + * megaphone/data/GNOME_Megaphone_Applet.server.in.in: + * megaphone/data/GNOME_Megaphone_Applet.xml: + * megaphone/Makefile.am: + * nothere/src/nothere-applet.c: + * nothere/src/Makefile.am: + * nothere/src/nothere-applet.h: + * nothere/data/Makefile.am: + * nothere/data/GNOME_NotHere_Applet.server.in.in: + * nothere/data/GNOME_NotHere_Applet.xml: + * nothere/Makefile.am: + * Makefile.am: + * po/POTFILES.in: + * po/POTFILES.skip: Add Megaphone and Nothere applets. Fixes bug + #464954 (Raphael Slinckx, Xavier Claessens). + 2007-09-20 Xavier Claessens * libempathy-gtk/empathy-status-icon.c: diff --git a/Makefile.am b/Makefile.am index 9c336a52..f809c102 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,13 @@ SUBDIRS = po data libempathy libempathy-gtk src doc +if HAVE_MEGAPHONE +SUBDIRS += megaphone +endif + +if HAVE_NOTHERE +SUBDIRS += nothere +endif + if HAVE_PYTHON SUBDIRS += python endif diff --git a/configure.ac b/configure.ac index 6c88627b..a3e865f2 100644 --- a/configure.ac +++ b/configure.ac @@ -46,9 +46,10 @@ IT_PROG_INTLTOOL([0.35.0]) GTK_DOC_CHECK([1.3]) GLIB_REQUIRED=2.12.0 -GTK_REQUIRED=2.10.0 +GTK_REQUIRED=2.12.0 GCONF_REQUIRED=1.2.0 LIBGLADE_REQUIRED=2.0.0 +LIBPANELAPPLET_REQUIRED=2.10.0 TELEPATHY_REQUIRED=0.0.57 MISSION_CONTROL_REQUIRED=4.33 @@ -144,6 +145,65 @@ if test "x$enable_aspell" = "xyes" -a "x$have_aspell" != "xyes"; then fi +dnl ----------------------------------------------------------- +dnl Megaphone +dnl ----------------------------------------------------------- +AC_ARG_ENABLE(megaphone, + AS_HELP_STRING([--enable-megaphone=@<:@no/yes/auto@:>@], + [build megaphone applet]), , + enable_megaphone=auto) + +if test "x$enable_megaphone" != "xno"; then + PKG_CHECK_MODULES(MEGAPHONE, + [ + libpanelapplet-2.0 >= $LIBPANELAPPLET_REQUIRED + glib-2.0 >= $GLIB_REQUIRED + gtk+-2.0 >= $GTK_REQUIRED + gconf-2.0 >= $GCONF_REQUIRED + libglade-2.0 >= $LIBGLADE_REQUIRED + gnome-vfs-2.0 + libtelepathy >= $TELEPATHY_REQUIRED + libmissioncontrol >= $MISSION_CONTROL_REQUIRED + ], have_megaphone="yes", have_megaphone="no") +else + have_megaphone=no +fi + +if test "x$enable_megaphone" = "xyes" -a "x$have_megaphone" != "xyes"; then + AC_MSG_ERROR([Couldn't find megaphone dependencies.]) +fi + +AM_CONDITIONAL(HAVE_MEGAPHONE, test "x$have_megaphone" = "xyes") + +dnl ----------------------------------------------------------- +dnl Nothere +dnl ----------------------------------------------------------- +AC_ARG_ENABLE(nothere, + AS_HELP_STRING([--enable-nothere=@<:@no/yes/auto@:>@], + [build nothere applet]), , + enable_nothere=no) + +if test "x$enable_nothere" != "xno"; then + PKG_CHECK_MODULES(NOTHERE, + [ + libpanelapplet-2.0 >= $LIBPANELAPPLET_REQUIRED + glib-2.0 >= $GLIB_REQUIRED + gtk+-2.0 >= $GTK_REQUIRED + gconf-2.0 >= $GCONF_REQUIRED + libglade-2.0 >= $LIBGLADE_REQUIRED + libtelepathy >= $TELEPATHY_REQUIRED + libmissioncontrol >= $MISSION_CONTROL_REQUIRED + ], have_nothere="yes", have_nothere="no") +else + have_nothere=no +fi + +if test "x$enable_nothere" = "xyes" -a "x$have_nothere" != "xyes"; then + AC_MSG_ERROR([Couldn't find nothere dependencies.]) +fi + +AM_CONDITIONAL(HAVE_NOTHERE, test "x$have_nothere" = "xyes") + dnl ----------------------------------------------------------- dnl Python Bindings dnl ----------------------------------------------------------- @@ -200,7 +260,12 @@ AC_OUTPUT([ libempathy-gtk/Makefile libempathy-gtk/libempathy-gtk.pc src/Makefile - doc/Makefile + megaphone/Makefile + megaphone/src/Makefile + megaphone/data/Makefile + nothere/Makefile + nothere/src/Makefile + nothere/data/Makefile doc/Makefile doc/libempathy/Makefile doc/libempathy-gtk/Makefile python/Makefile diff --git a/libempathy-gtk/empathy-contact-list-view.c b/libempathy-gtk/empathy-contact-list-view.c index d4b222e4..27688602 100644 --- a/libempathy-gtk/empathy-contact-list-view.c +++ b/libempathy-gtk/empathy-contact-list-view.c @@ -777,7 +777,6 @@ contact_list_view_drag_data_received (GtkWidget *widget, g_object_unref (account); } g_object_unref (factory); - g_object_unref (account); g_strfreev (strv); if (!contact) { diff --git a/libempathy/empathy-contact-manager.c b/libempathy/empathy-contact-manager.c index 575814fa..e11f829e 100644 --- a/libempathy/empathy-contact-manager.c +++ b/libempathy/empathy-contact-manager.c @@ -189,6 +189,11 @@ contact_manager_finalize (GObject *object) { EmpathyContactManagerPriv *priv = GET_PRIV (object); + dbus_g_proxy_disconnect_signal (DBUS_G_PROXY (priv->mc), + "AccountStatusChanged", + G_CALLBACK (contact_manager_status_changed_cb), + object); + g_hash_table_foreach (priv->lists, contact_manager_disconnect_foreach, object); diff --git a/megaphone/Makefile.am b/megaphone/Makefile.am new file mode 100644 index 00000000..85d5f752 --- /dev/null +++ b/megaphone/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = src data + diff --git a/megaphone/data/GNOME_Megaphone_Applet.schemas.in b/megaphone/data/GNOME_Megaphone_Applet.schemas.in new file mode 100644 index 00000000..bf6822d4 --- /dev/null +++ b/megaphone/data/GNOME_Megaphone_Applet.schemas.in @@ -0,0 +1,20 @@ + + + + + /schemas/apps/megaphone-applet/prefs/contact_id + /apps/megaphone-applet/prefs/contact_id + megaphone + string + + + The contact to display in the applet. Empty means no contact is displayed. + + + + + + + + + diff --git a/megaphone/data/GNOME_Megaphone_Applet.server.in.in b/megaphone/data/GNOME_Megaphone_Applet.server.in.in new file mode 100644 index 00000000..2d1c3ac1 --- /dev/null +++ b/megaphone/data/GNOME_Megaphone_Applet.server.in.in @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/megaphone/data/GNOME_Megaphone_Applet.xml b/megaphone/data/GNOME_Megaphone_Applet.xml new file mode 100644 index 00000000..8a139707 --- /dev/null +++ b/megaphone/data/GNOME_Megaphone_Applet.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/megaphone/data/Makefile.am b/megaphone/data/Makefile.am new file mode 100644 index 00000000..3dbde679 --- /dev/null +++ b/megaphone/data/Makefile.am @@ -0,0 +1,35 @@ +# Panel applet bonobo stuff +serverdir = $(libdir)/bonobo/servers +server_in_files = GNOME_Megaphone_Applet.server.in +server_DATA = $(server_in_files:.server.in=.server) + + +# GConf Schemas +schemadir = $(GCONF_SCHEMA_FILE_DIR) +schema_in_files = GNOME_Megaphone_Applet.schemas.in +schema_DATA = $(schema_in_files:.schemas.in=.schemas) + +# Misc data +resourcesdir = $(pkgdatadir) +resources_DATA = \ + GNOME_Megaphone_Applet.xml +# megaphone-applet.glade + +megaphonebindir = $(libexecdir) + +# Build rules +@INTLTOOL_SERVER_RULE@ +@INTLTOOL_SCHEMAS_RULE@ + +$(server_in_files): $(server_in_files:.server.in=.server.in.in) + sed -e "s|\@LIBEXECDIR\@|$(megaphonebindir)|" $< > $@ + +DISTCLEANFILES = \ + $(server_DATA) \ + $(server_in_files) \ + $(schema_DATA) + +EXTRA_DIST = \ + GNOME_Megaphone_Applet.server.in.in \ + $(resources_DATA) \ + $(schema_in_files) diff --git a/megaphone/src/Makefile.am b/megaphone/src/Makefile.am new file mode 100644 index 00000000..d5876943 --- /dev/null +++ b/megaphone/src/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DPKGDATADIR=\""$(pkgdatadir)"\" \ + -DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DIMAGEDIR=\"$(datadir)/empathy\" \ + $(MEGAPHONE_CFLAGS) $(WARN_CFLAGS) + +libexec_PROGRAMS = megaphone-applet +megaphone_applet_SOURCES = \ + megaphone-applet.c megaphone-applet.h + +megaphone_applet_LDFLAGS = \ + $(MEGAPHONE_LIBS) + +megaphone_applet_LDADD = \ + $(top_builddir)/libempathy/libempathy.la \ + $(top_builddir)/libempathy-gtk/libempathy-gtk.la diff --git a/megaphone/src/megaphone-applet.c b/megaphone/src/megaphone-applet.c new file mode 100644 index 00000000..63e72fc3 --- /dev/null +++ b/megaphone/src/megaphone-applet.c @@ -0,0 +1,572 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Raphaël Slinckx + * Copyright (C) 2007 Collabora Ltd. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Raphaël Slinckx + * Xavier Claessens + */ + +#include "config.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "megaphone-applet.h" + +#define DEBUG_DOMAIN "MegaphoneApplet" + +#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MEGAPHONE_TYPE_APPLET, MegaphoneAppletPriv)) + +typedef struct _MegaphoneAppletPriv MegaphoneAppletPriv; + +struct _MegaphoneAppletPriv { + EmpathyContactFactory *factory; + GtkWidget *image; + gint image_size; + EmpathyContact *contact; + GConfClient *gconf; + guint gconf_cnxn; +}; + +static void megaphone_applet_finalize (GObject *object); +static void megaphone_applet_size_allocate_cb (GtkWidget *widget, + GtkAllocation *allocation, + MegaphoneApplet *applet); +static gboolean megaphone_applet_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + MegaphoneApplet *applet); +static void megaphone_applet_information_cb (BonoboUIComponent *uic, + MegaphoneApplet *applet, + const gchar *verb_name); +static void megaphone_applet_preferences_cb (BonoboUIComponent *uic, + MegaphoneApplet *applet, + const gchar *verb_name); +static void megaphone_applet_about_cb (BonoboUIComponent *uic, + MegaphoneApplet *applet, + const gchar *verb_name); + +G_DEFINE_TYPE(MegaphoneApplet, megaphone_applet, PANEL_TYPE_APPLET) + +static const BonoboUIVerb megaphone_applet_menu_verbs [] = { + BONOBO_UI_UNSAFE_VERB ("information", megaphone_applet_information_cb), + BONOBO_UI_UNSAFE_VERB ("preferences", megaphone_applet_preferences_cb), + BONOBO_UI_UNSAFE_VERB ("about", megaphone_applet_about_cb), + BONOBO_UI_VERB_END +}; + +static const char* authors[] = { + "Raphaël Slinckx ", + "Xavier Claessens ", + NULL +}; + +static void +megaphone_applet_class_init (MegaphoneAppletClass *class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (class); + + object_class->finalize = megaphone_applet_finalize; + + g_type_class_add_private (object_class, sizeof (MegaphoneAppletPriv)); +} + +static void +megaphone_applet_init (MegaphoneApplet *applet) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + + priv->factory = empathy_contact_factory_new (); + priv->gconf = gconf_client_get_default (); + + /* Image holds the contact avatar */ + priv->image = gtk_image_new (); + gtk_widget_show (priv->image); + gtk_container_add (GTK_CONTAINER (applet), priv->image); + + /* We want transparency */ + panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR); + panel_applet_set_background_widget (PANEL_APPLET (applet), GTK_WIDGET (applet)); + + /* Listen for clicks on the applet to dispatch a channel */ + g_signal_connect (applet, "button-press-event", + G_CALLBACK (megaphone_applet_button_press_event_cb), + applet); + + /* Allow to resize our avatar when needed */ + g_signal_connect (applet, "size-allocate", + G_CALLBACK (megaphone_applet_size_allocate_cb), + applet); +} + +static void +megaphone_applet_finalize (GObject *object) +{ + MegaphoneAppletPriv *priv = GET_PRIV (object); + + if (priv->contact) { + g_object_unref (priv->contact); + } + g_object_unref (priv->factory); + + if (priv->gconf_cnxn != 0) { + gconf_client_notify_remove (priv->gconf, priv->gconf_cnxn); + } + g_object_unref (priv->gconf); + + G_OBJECT_CLASS (megaphone_applet_parent_class)->finalize (object); +} + +static gchar * +megaphone_applet_get_avatar_file (MegaphoneApplet *applet) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + const gchar *id; + gchar *escaped_avatar; + gchar *avatar_path; + gchar *avatar_file; + + id = empathy_contact_get_id (priv->contact); + escaped_avatar = gnome_vfs_escape_slashes (id); + + avatar_path = g_build_filename (g_get_home_dir (), + ".gnome2", + PACKAGE_NAME, + "megaphone", + NULL); + g_mkdir_with_parents (avatar_path, 0700); + + avatar_file = g_build_filename (avatar_path, escaped_avatar, NULL); + + g_free (avatar_path); + g_free (escaped_avatar); + + return avatar_file; +} + +static void +megaphone_applet_update_avatar (MegaphoneApplet *applet) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + GdkPixbuf *avatar; + gchar *avatar_file; + + if (priv->contact == NULL) { + empathy_debug (DEBUG_DOMAIN, "Update image size: %i", + priv->image_size - 2); + gtk_image_set_pixel_size (GTK_IMAGE (priv->image), + priv->image_size - 2); + return; + } + + empathy_debug (DEBUG_DOMAIN, "Update avatar: %s %i", + empathy_contact_get_id (priv->contact), + priv->image_size - 2); + + /* Compute the avatar cache file name */ + avatar_file = megaphone_applet_get_avatar_file (applet); + + /* Fetch existing avatar */ + avatar = empathy_pixbuf_avatar_from_contact_scaled (priv->contact, + priv->image_size - 2, + priv->image_size - 2); + if (avatar == NULL) { + /* Try to load a cached avatar */ + avatar = gdk_pixbuf_new_from_file (avatar_file, NULL); + if (avatar == NULL) { + GtkIconTheme *icon_theme; + + /* Load the default icon when no avatar is found */ + icon_theme = gtk_icon_theme_get_default (); + avatar = gtk_icon_theme_load_icon (icon_theme, + "stock_contact", + priv->image_size - 2, + 0, NULL); + } + } else { + /* Cache avatar */ + gdk_pixbuf_save (avatar, avatar_file, "png", NULL, NULL); + } + g_free (avatar_file); + + /* Now some desaturation if the contact is offline */ + if (!empathy_contact_is_online (priv->contact)) { + GdkPixbuf *offline_avatar; + + offline_avatar = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, + 8, + gdk_pixbuf_get_height (avatar), + gdk_pixbuf_get_width (avatar)); + gdk_pixbuf_saturate_and_pixelate (avatar, + offline_avatar, + 0.0, + TRUE); + g_object_unref (avatar); + avatar = offline_avatar; + } + + gtk_image_set_from_pixbuf (GTK_IMAGE (priv->image), avatar); + g_object_unref (avatar); +} + +static void +megaphone_applet_update_contact (MegaphoneApplet *applet) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + const gchar *name; + const gchar *status; + gchar *tip; + + if (priv->contact == NULL) { + return; + } + + empathy_debug (DEBUG_DOMAIN, "Update contact: %s", + empathy_contact_get_id (priv->contact)); + + megaphone_applet_update_avatar (applet); + + name = empathy_contact_get_name (priv->contact); + status = empathy_contact_get_status (priv->contact); + tip = g_strdup_printf ("%s: %s", name, status); + + gtk_widget_set_tooltip_markup (GTK_WIDGET (applet), tip); + g_free (tip); +} + +static void +megaphone_applet_set_contact (MegaphoneApplet *applet, + const gchar *str) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + McAccount *account = NULL; + gchar **strv = NULL; + + empathy_debug (DEBUG_DOMAIN, "Setting new contact %s", str); + + /* Release old contact, if any */ + if (priv->contact) { + g_signal_handlers_disconnect_by_func (priv->contact, + megaphone_applet_update_contact, + applet); + g_object_unref (priv->contact), + priv->contact = NULL; + } + + /* Lookup the new contact */ + if (str) { + strv = g_strsplit (str, "/", 2); + account = mc_account_lookup (strv[0]); + } + if (account) { + priv->contact = empathy_contact_factory_get_from_id (priv->factory, + account, + strv[1]); + g_object_unref (account); + } + g_strfreev (strv); + + /* Take hold of the new contact if any */ + if (priv->contact) { + /* Listen for updates on the contact, and force a first update */ + g_signal_connect_swapped (priv->contact, "notify", + G_CALLBACK (megaphone_applet_update_contact), + applet); + megaphone_applet_update_contact (applet); + } else { + gtk_image_set_from_icon_name (GTK_IMAGE (priv->image), + GTK_STOCK_PREFERENCES, + GTK_ICON_SIZE_MENU); + gtk_widget_set_tooltip_markup (GTK_WIDGET (applet), + "Please configure a contact."); + } +} + +static void +megaphone_applet_preferences_response_cb (GtkWidget *dialog, + gint response, + MegaphoneApplet *applet) +{ + if (response == GTK_RESPONSE_ACCEPT) { + EmpathyContactListView *contact_list; + EmpathyContact *contact; + + /* Retrieve the selected contact, if any and set it up in gconf. + * GConf will notify us from the change and we will adjust ourselves */ + contact_list = g_object_get_data (G_OBJECT (dialog), "contact-list"); + contact = empathy_contact_list_view_get_selected (contact_list); + if (contact) { + McAccount *account; + const gchar *account_id; + const gchar *contact_id; + gchar *str; + + account = empathy_contact_get_account (contact); + account_id = mc_account_get_unique_name (account); + contact_id = empathy_contact_get_id (contact); + + str = g_strconcat (account_id, "/", contact_id, NULL); + panel_applet_gconf_set_string (PANEL_APPLET (applet), + "contact_id", str, + NULL); + g_free (str); + } + } + gtk_widget_destroy (dialog); +} + +static void +megaphone_applet_show_preferences (MegaphoneApplet *applet) +{ + GtkWidget *dialog; + GtkWidget *scroll; + EmpathyContactListView *contact_list; + EmpathyContactListStore *contact_store; + EmpathyContactManager *contact_manager; + + dialog = gtk_dialog_new_with_buttons ("Select contact...", + NULL, 0, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, + GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + NULL); + + /* Show all contacts, even offline and sort alphabetically */ + contact_manager = empathy_contact_manager_new (); + contact_store = empathy_contact_list_store_new (EMPATHY_CONTACT_LIST (contact_manager)); + g_object_set (contact_store, + "is-compact", TRUE, + "show-avatars", TRUE, + "show-offline", TRUE, + "sort-criterium", EMPATHY_CONTACT_LIST_STORE_SORT_NAME, + NULL); + contact_list = empathy_contact_list_view_new (contact_store); + gtk_tree_view_expand_all (GTK_TREE_VIEW (contact_list)); + g_object_unref (contact_manager); + g_object_unref (contact_store); + gtk_widget_show (GTK_WIDGET (contact_list)); + + gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 500); + scroll = gtk_scrolled_window_new (NULL, NULL); + gtk_container_add (GTK_CONTAINER (scroll), GTK_WIDGET (contact_list)); + gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), scroll); + gtk_widget_show (scroll); + + g_object_set_data (G_OBJECT (dialog), "contact-list", contact_list); + + g_signal_connect (dialog, "response", + G_CALLBACK (megaphone_applet_preferences_response_cb), + applet); + + gtk_widget_show (dialog); +} + +static void +megaphone_applet_information_cb (BonoboUIComponent *uic, + MegaphoneApplet *applet, + const gchar *verb_name) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + + /* FIXME: We should grey out the menu item if there are no available contact */ + if (priv->contact) { + empathy_contact_information_dialog_show (priv->contact, NULL, FALSE); + } +} + +static void +megaphone_applet_preferences_cb (BonoboUIComponent *uic, + MegaphoneApplet *applet, + const gchar *verb_name) +{ + megaphone_applet_show_preferences (applet); +} + +static void +megaphone_applet_about_cb (BonoboUIComponent *uic, + MegaphoneApplet *applet, + const gchar *verb_name) +{ + gtk_show_about_dialog (NULL, + "name", "Megaphone", + "version", PACKAGE_VERSION, + "copyright", "Raphaël Slinckx 2007\nCollabora Ltd 2007", + "comments", _("Talk!"), + "authors", authors, + "logo-icon-name", "stock_people", + NULL); +} + +static gboolean +megaphone_applet_button_press_event_cb (GtkWidget *widget, + GdkEventButton *event, + MegaphoneApplet *applet) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + MissionControl *mc; + + /* Only react on left-clicks */ + if (event->button != 1 || event->type != GDK_BUTTON_PRESS) { + return FALSE; + } + + /* If the contact is unavailable we display the preferences dialog */ + if (priv->contact == NULL) { + megaphone_applet_show_preferences (applet); + return TRUE; + } + + empathy_debug (DEBUG_DOMAIN, "Requesting text channel for contact %s (%d)", + empathy_contact_get_id (priv->contact), + empathy_contact_get_handle (priv->contact)); + + mc = empathy_mission_control_new (); + mission_control_request_channel (mc, + empathy_contact_get_account (priv->contact), + TP_IFACE_CHANNEL_TYPE_TEXT, + empathy_contact_get_handle (priv->contact), + TP_HANDLE_TYPE_CONTACT, + NULL, NULL); + g_object_unref (mc); + + return TRUE; +} + +static void +megaphone_applet_size_allocate_cb (GtkWidget *widget, + GtkAllocation *allocation, + MegaphoneApplet *applet) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + gint size; + PanelAppletOrient orient; + + orient = panel_applet_get_orient (PANEL_APPLET (widget)); + if (orient == PANEL_APPLET_ORIENT_LEFT || + orient == PANEL_APPLET_ORIENT_RIGHT) { + size = allocation->width; + } else { + size = allocation->height; + } + + if (size != priv->image_size) { + priv->image_size = size; + megaphone_applet_update_avatar (applet); + } +} + +static void +megaphone_applet_gconf_notify_cb (GConfClient *client, + guint cnxn_id, + GConfEntry *entry, + MegaphoneApplet *applet) +{ + const gchar *key; + GConfValue *value; + + key = gconf_entry_get_key (entry); + value = gconf_entry_get_value (entry); + empathy_debug (DEBUG_DOMAIN, "GConf notification for key '%s'", key); + + if (value && g_str_has_suffix (key, "/contact_id")) { + megaphone_applet_set_contact (applet, + gconf_value_get_string (value)); + } +} + +static gboolean +megaphone_applet_factory (PanelApplet *applet, + const gchar *iid, + gpointer data) +{ + MegaphoneAppletPriv *priv = GET_PRIV (applet); + gchar *pref_dir; + gchar *contact_id; + + /* Ensure it's us! */ + if (strcmp (iid, "OAFIID:GNOME_Megaphone_Applet") != 0) { + return FALSE; + } + + empathy_debug (DEBUG_DOMAIN, "Starting up new instance!"); + + /* Set up the right-click menu */ + panel_applet_setup_menu_from_file (applet, + PKGDATADIR, + "GNOME_Megaphone_Applet.xml", + NULL, + megaphone_applet_menu_verbs, + applet); + + /* Define the schema to be used for each applet instance's preferences */ + panel_applet_add_preferences (applet, + "/schemas/apps/megaphone-applet/prefs", + NULL); + + /* We watch the preferences directory */ + pref_dir = panel_applet_gconf_get_full_key (applet, ""); + pref_dir[strlen (pref_dir)-1] = '\0'; + gconf_client_add_dir (priv->gconf, pref_dir, + GCONF_CLIENT_PRELOAD_ONELEVEL, + NULL); + gconf_client_notify_add (priv->gconf, pref_dir, + (GConfClientNotifyFunc) megaphone_applet_gconf_notify_cb, + applet, + NULL, NULL); + g_free (pref_dir); + + /* Initial setup with the pre-existing gconf key, or contact_id=NULL if no previous pref */ + contact_id = panel_applet_gconf_get_string (PANEL_APPLET (applet), "contact_id", NULL); + megaphone_applet_set_contact (MEGAPHONE_APPLET (applet), contact_id); + g_free (contact_id); + + /* Let's go! */ + gtk_widget_show (GTK_WIDGET (applet)); + + return TRUE; +} + +PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_Megaphone_Applet_Factory", + MEGAPHONE_TYPE_APPLET, + "Megaphone", PACKAGE_VERSION, + megaphone_applet_factory, + NULL); + diff --git a/megaphone/src/megaphone-applet.h b/megaphone/src/megaphone-applet.h new file mode 100644 index 00000000..bae671d8 --- /dev/null +++ b/megaphone/src/megaphone-applet.h @@ -0,0 +1,53 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Raphaël Slinckx + * Copyright (C) 2007 Collabora Ltd. + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Raphaël Slinckx + * Xavier Claessens + */ + +#ifndef __MEGAPHONE_APPLET_H__ +#define __MEGAPHONE_APPLET_H__ + +#include + +G_BEGIN_DECLS + +#define MEGAPHONE_TYPE_APPLET (megaphone_applet_get_type ()) +#define MEGAPHONE_APPLET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MEGAPHONE_TYPE_APPLET, MegaphoneApplet)) +#define MEGAPHONE_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MEGAPHONE_TYPE_APPLET, MegaphoneAppletClass)) +#define MEGAPHONE_IS_APPLET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MEGAPHONE_TYPE_APPLET)) +#define MEGAPHONE_IS_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MEGAPHONE_TYPE_APPLET)) +#define MEGAPHONE_APPLET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MEGAPHONE_TYPE_APPLET, MegaphoneAppletClass)) + +typedef struct _MegaphoneApplet MegaphoneApplet; +typedef struct _MegaphoneAppletClass MegaphoneAppletClass; + +struct _MegaphoneApplet { + PanelApplet applet; +}; + +struct _MegaphoneAppletClass { + PanelAppletClass parent_class; +}; + +GType megaphone_applet_get_type (void); + +G_END_DECLS + +#endif /* __MEGAPHONE_APPLET_H__ */ diff --git a/nothere/Makefile.am b/nothere/Makefile.am new file mode 100644 index 00000000..85d5f752 --- /dev/null +++ b/nothere/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = src data + diff --git a/nothere/data/GNOME_NotHere_Applet.server.in.in b/nothere/data/GNOME_NotHere_Applet.server.in.in new file mode 100644 index 00000000..e76ad14d --- /dev/null +++ b/nothere/data/GNOME_NotHere_Applet.server.in.in @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nothere/data/GNOME_NotHere_Applet.xml b/nothere/data/GNOME_NotHere_Applet.xml new file mode 100644 index 00000000..5d425f10 --- /dev/null +++ b/nothere/data/GNOME_NotHere_Applet.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/nothere/data/Makefile.am b/nothere/data/Makefile.am new file mode 100644 index 00000000..4aa92147 --- /dev/null +++ b/nothere/data/Makefile.am @@ -0,0 +1,35 @@ +# Panel applet bonobo stuff +serverdir = $(libdir)/bonobo/servers +server_in_files = GNOME_NotHere_Applet.server.in +server_DATA = $(server_in_files:.server.in=.server) + + +# GConf Schemas +#schemadir = $(GCONF_SCHEMA_FILE_DIR) +#schema_in_files = GNOME_NotHere_Applet.schemas.in +#schema_DATA = $(schema_in_files:.schemas.in=.schemas) + +# Misc data +resourcesdir = $(pkgdatadir) +resources_DATA = \ + GNOME_NotHere_Applet.xml +# nothere-applet.glade + +notherebindir = $(libexecdir) + +# Build rules +@INTLTOOL_SERVER_RULE@ +@INTLTOOL_SCHEMAS_RULE@ + +$(server_in_files): $(server_in_files:.server.in=.server.in.in) + sed -e "s|\@LIBEXECDIR\@|$(notherebindir)|" $< > $@ + +DISTCLEANFILES = \ + $(server_DATA) \ + $(server_in_files) +# $(schema_DATA) + +EXTRA_DIST = \ + GNOME_NotHere_Applet.server.in.in \ + $(resources_DATA) +# $(schema_in_files) diff --git a/nothere/src/Makefile.am b/nothere/src/Makefile.am new file mode 100644 index 00000000..b4b016af --- /dev/null +++ b/nothere/src/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -DPKGDATADIR=\""$(pkgdatadir)"\" \ + -DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \ + -DIMAGEDIR=\"$(datadir)/empathy\" \ + $(NOTHERE_CFLAGS) $(WARN_CFLAGS) + +libexec_PROGRAMS = nothere-applet +nothere_applet_SOURCES = \ + nothere-applet.c nothere-applet.h + +nothere_applet_LDFLAGS = \ + $(NOTHERE_LIBS) + +nothere_applet_LDADD = \ + $(top_builddir)/libempathy/libempathy.la \ + $(top_builddir)/libempathy-gtk/libempathy-gtk.la diff --git a/nothere/src/nothere-applet.c b/nothere/src/nothere-applet.c new file mode 100644 index 00000000..5d225698 --- /dev/null +++ b/nothere/src/nothere-applet.c @@ -0,0 +1,120 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Raphaël Slinckx + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Raphaël Slinckx + */ + +#include "config.h" + +#include + +#include +#include +#include + +#include +#include + +#include "nothere-applet.h" + +G_DEFINE_TYPE(NotHereApplet, nothere_applet, PANEL_TYPE_APPLET) + +static void nothere_applet_destroy (GtkObject *object); +static void nothere_applet_about_cb (BonoboUIComponent *uic, + NotHereApplet *applet, + const gchar *verb_name); + +static const BonoboUIVerb nothere_applet_menu_verbs [] = { + BONOBO_UI_UNSAFE_VERB ("about", nothere_applet_about_cb), + BONOBO_UI_VERB_END +}; + +static const char* authors[] = { + "Raphaël Slinckx ", + NULL +}; + +static void +nothere_applet_class_init (NotHereAppletClass *class) +{ + GTK_OBJECT_CLASS (class)->destroy = nothere_applet_destroy; +} + +static void +nothere_applet_init (NotHereApplet *applet) +{ + applet->presence_chooser = empathy_presence_chooser_new (); + gtk_widget_show (applet->presence_chooser); + + gtk_container_add (GTK_CONTAINER (applet), applet->presence_chooser); + + panel_applet_set_flags (PANEL_APPLET (applet), PANEL_APPLET_EXPAND_MINOR); + panel_applet_set_background_widget (PANEL_APPLET (applet), GTK_WIDGET (applet)); +} + +static void +nothere_applet_destroy (GtkObject *object) +{ + NotHereApplet *applet = NOTHERE_APPLET (object); + + applet->presence_chooser = NULL; + + (* GTK_OBJECT_CLASS (nothere_applet_parent_class)->destroy) (object); +} + +static void +nothere_applet_about_cb (BonoboUIComponent *uic, + NotHereApplet *applet, + const gchar *verb_name) +{ + gtk_show_about_dialog (NULL, + "name", "Presence", + "version", PACKAGE_VERSION, + "copyright", "Copyright \xc2\xa9 2007 Raphaël Slinckx", + "comments", _("Set your own presence"), + "authors", authors, + "logo-icon-name", "stock_people", + NULL); +} + +static gboolean +nothere_applet_factory (PanelApplet *applet, + const gchar *iid, + gpointer data) +{ + if (strcmp (iid, "OAFIID:GNOME_NotHere_Applet") != 0) { + return FALSE; + } + + /* Set up the menu */ + panel_applet_setup_menu_from_file (applet, + PKGDATADIR, + "GNOME_NotHere_Applet.xml", + NULL, + nothere_applet_menu_verbs, + applet); + + gtk_widget_show (GTK_WIDGET (applet)); + return TRUE; +} + +PANEL_APPLET_BONOBO_FACTORY ("OAFIID:GNOME_NotHere_Applet_Factory", + NOTHERE_TYPE_APPLET, + "Presence", PACKAGE_VERSION, + nothere_applet_factory, + NULL); diff --git a/nothere/src/nothere-applet.h b/nothere/src/nothere-applet.h new file mode 100644 index 00000000..37e5d91a --- /dev/null +++ b/nothere/src/nothere-applet.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2007 Raphaël Slinckx + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Raphaël Slinckx + */ + +#ifndef __NOTHERE_APPLET_H__ +#define __NOTHERE_APPLET_H__ + +#include + +G_BEGIN_DECLS + +#define NOTHERE_TYPE_APPLET (nothere_applet_get_type ()) +#define NOTHERE_APPLET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NOTHERE_TYPE_APPLET, NotHereApplet)) +#define NOTHERE_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NOTHERE_TYPE_APPLET, NotHereAppletClass)) +#define NOTHERE_IS_APPLET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NOTHERE_TYPE_APPLET)) +#define NOTHERE_IS_APPLET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NOTHERE_TYPE_APPLET)) +#define NOTHERE_APPLET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NOTHERE_TYPE_APPLET, NotHereAppletClass)) + +typedef struct _NotHereApplet NotHereApplet; +typedef struct _NotHereAppletClass NotHereAppletClass; + +struct _NotHereApplet { + PanelApplet applet; + GtkWidget *presence_chooser; +}; + +struct _NotHereAppletClass { + PanelAppletClass parent_class; +}; + +GType nothere_applet_get_type (void); + +G_END_DECLS + +#endif /* __NOTHERE_APPLET_H__ */ diff --git a/po/POTFILES.in b/po/POTFILES.in index e2e3a625..9929e33d 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,8 +1,6 @@ # List of source files containing translatable strings. # Please keep this file sorted alphabetically. - - data/empathy.desktop.in.in data/empathy.schemas.in @@ -49,4 +47,13 @@ libempathy-gtk/empathy-status-icon.c libempathy-gtk/empathy-status-icon.glade libempathy-gtk/empathy-theme-manager.c +megaphone/data/GNOME_Megaphone_Applet.schemas.in +megaphone/data/GNOME_Megaphone_Applet.server.in.in +megaphone/data/GNOME_Megaphone_Applet.xml +megaphone/src/megaphone-applet.c + +nothere/data/GNOME_NotHere_Applet.server.in.in +nothere/data/GNOME_NotHere_Applet.xml +nothere/src/nothere-applet.c + src/empathy.c diff --git a/po/POTFILES.skip b/po/POTFILES.skip index bfcb0d54..126726d7 100644 --- a/po/POTFILES.skip +++ b/po/POTFILES.skip @@ -1,3 +1,6 @@ # Please keep this file sorted alphabetically. data/empathy.desktop.in +megaphone/data/GNOME_Megaphone_Applet.server.in +nothere/data/GNOME_NotHere_Applet.server.in + -- 2.39.2