aboutsummaryrefslogtreecommitdiff
path: root/libmessaging-menu/messaging-menu-app.c
diff options
context:
space:
mode:
authorŁukasz 'sil2100' Zemczak <lukasz.zemczak@canonical.com>2013-08-20 10:53:01 +0200
committerŁukasz 'sil2100' Zemczak <lukasz.zemczak@canonical.com>2013-08-20 10:53:01 +0200
commit88b2fd89ff0bc4be81acd8f6d5751dba96e295f8 (patch)
tree2f231acd79d96f697709586effbabb4928477c89 /libmessaging-menu/messaging-menu-app.c
parentb25532c6a307381f523a78b4b5fbdeb73896bb3d (diff)
downloadayatana-indicator-messages-88b2fd89ff0bc4be81acd8f6d5751dba96e295f8.tar.gz
ayatana-indicator-messages-88b2fd89ff0bc4be81acd8f6d5751dba96e295f8.tar.bz2
ayatana-indicator-messages-88b2fd89ff0bc4be81acd8f6d5751dba96e295f8.zip
Revert rev 352 as it is causing a SIGTRAP on start
Diffstat (limited to 'libmessaging-menu/messaging-menu-app.c')
-rw-r--r--libmessaging-menu/messaging-menu-app.c1433
1 files changed, 0 insertions, 1433 deletions
diff --git a/libmessaging-menu/messaging-menu-app.c b/libmessaging-menu/messaging-menu-app.c
deleted file mode 100644
index 421a09f..0000000
--- a/libmessaging-menu/messaging-menu-app.c
+++ /dev/null
@@ -1,1433 +0,0 @@
-/*
- * Copyright 2012 Canonical Ltd.
- *
- * This program is free software: you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 3, as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranties of
- * MERCHANTABILITY, SATISFACTORY QUALITY, 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, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Lars Uebernickel <lars.uebernickel@canonical.com>
- */
-
-#include "messaging-menu-app.h"
-#include "indicator-messages-service.h"
-#include "indicator-messages-application.h"
-
-#include <gio/gdesktopappinfo.h>
-#include <string.h>
-
-/**
- * SECTION:messaging-menu
- * @title: MessagingMenuApp
- * @short_description: An application section in the messaging menu
- * @include: messaging-menu.h
- *
- * A #MessagingMenuApp represents an application section in the
- * Messaging Menu. An application section is tied to an installed
- * application through a desktop file id, which must be passed to
- * messaging_menu_app_new().
- *
- * To register the application with the Messaging Menu, call
- * messaging_menu_app_register(). This signifies that the application
- * should be present in the menu and be marked as "running".
- *
- * The first menu item in an application section represents the
- * application itself, using the name and icon found in the associated
- * desktop file. Activating this item starts the application.
- *
- * Following the application item, the Messaging Menu inserts all
- * shortcut actions found in the desktop file. Actions whose
- * <code>NotShowIn</code> keyword contains "Messaging Menu" or whose
- * <code>OnlyShowIn</code> keyword does not contain "Messaging Menu"
- * will not appear (the <ulink
- * url="http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.1.html#extra-actions">
- * desktop file specification</ulink> contains a detailed explanation of
- * shortcut actions.) An application cannot add, remove, or change
- * these shortcut items while it is running.
- *
- * Next, an application section contains menu items for message sources.
- * What exactly constitutes a message source depends on the type of
- * application: an email client's message sources are folders
- * containing new messages, while those of a chat program are persons
- * that have contacted the user.
- *
- * A message source is represented in the menu by a label and optionally
- * also an icon. It can be associated with either a count, a time, or
- * an arbitrary string, which will appear on the right side of the menu
- * item.
- *
- * When the user activates a source, the source is immediately removed
- * from the menu and the "activate-source" signal is emitted.
- *
- * Applications should always expose all the message sources available.
- * However, the Messaging Menu might limit the amount of sources it
- * displays to the user.
- *
- * The Messaging Menu offers users a way to set their chat status
- * (available, away, busy, invisible, or offline) for multiple
- * applications at once. Applications that appear in the Messaging Menu
- * can integrate with this by setting the
- * "X-MessagingMenu-UsesChatSection" key in their desktop file to True.
- * Use messaging_menu_app_set_status() to signify that the application's
- * chat status has changed. When the user changes status through the
- * Messaging Menu, the ::status-changed signal will be emitted.
- *
- * If the application stops running without calling
- * messaging_menu_app_unregister(), it will be marked as "not running".
- * Its application and shortcut items stay in the menu, but all message
- * sources are removed. If messaging_menu_app_unregister() is called,
- * the application section is removed completely.
- *
- * More information about the design and recommended usage of the
- * Messaging Menu is available at <ulink
- * url="https://wiki.ubuntu.com/MessagingMenu">https://wiki.ubuntu.com/MessagingMenu</ulink>.
- */
-
-/**
- * MessagingMenuApp:
- *
- * #MessagingMenuApp is an opaque structure.
- */
-struct _MessagingMenuApp
-{
- GObject parent_instance;
-
- GDesktopAppInfo *appinfo;
- int registered; /* -1 for unknown */
- MessagingMenuStatus status;
- gboolean status_set;
- GDBusConnection *bus;
-
- GHashTable *messages;
- GList *sources;
- IndicatorMessagesApplication *app_interface;
-
- IndicatorMessagesService *messages_service;
- guint watch_id;
-
- GCancellable *cancellable;
-};
-
-G_DEFINE_TYPE (MessagingMenuApp, messaging_menu_app, G_TYPE_OBJECT);
-
-enum {
- PROP_0,
- PROP_DESKTOP_ID,
- N_PROPERTIES
-};
-
-enum {
- ACTIVATE_SOURCE,
- STATUS_CHANGED,
- N_SIGNALS
-};
-
-static GParamSpec *properties[N_PROPERTIES];
-static guint signals[N_SIGNALS];
-
-static const gchar *status_ids[] = { "available", "away", "busy", "invisible", "offline" };
-
-typedef struct
-{
- gchar *id;
- GIcon *icon;
- gchar *label;
-
- guint32 count;
- gint64 time;
- gchar *string;
- gboolean draws_attention;
-} Source;
-
-static void global_status_changed (IndicatorMessagesService *service,
- const gchar *status_str,
- gpointer user_data);
-
-/* in messaging-menu-message.c */
-GVariant * _messaging_menu_message_to_variant (MessagingMenuMessage *msg);
-
-static void
-source_free (gpointer data)
-{
- Source *source = data;
-
- if (source)
- {
- g_free (source->id);
- g_clear_object (&source->icon);
- g_free (source->label);
- g_free (source->string);
- g_slice_free (Source, source);
- }
-}
-
-static GVariant *
-source_to_variant (Source *source)
-{
- GVariant *v;
- gchar *iconstr;
-
- iconstr = source->icon ? g_icon_to_string (source->icon) : NULL;
-
- v = g_variant_new ("(sssuxsb)", source->id,
- source->label,
- iconstr ? iconstr : "",
- source->count,
- source->time,
- source->string ? source->string : "",
- source->draws_attention);
-
- g_free (iconstr);
-
- return v;
-}
-
-static gchar *
-messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)
-{
- gchar *path;
-
- if (!app->appinfo)
- return NULL;
-
- path = g_strconcat ("/com/canonical/indicator/messages/",
- g_app_info_get_id (G_APP_INFO (app->appinfo)),
- NULL);
-
- g_strcanon (path, "/ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", '_');
-
- return path;
-}
-
-static void
-messaging_menu_app_got_bus (GObject *source,
- GAsyncResult *res,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- GError *error = NULL;
- gchar *object_path;
-
- app->bus = g_bus_get_finish (res, &error);
- if (app->bus == NULL)
- {
- g_warning ("unable to connect to session bus: %s", error->message);
- g_error_free (error);
- return;
- }
-
- object_path = messaging_menu_app_get_dbus_object_path (app);
-
- if (object_path &&
- !g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (app->app_interface),
- app->bus, object_path, &error))
- {
- g_warning ("unable to export application interface: %s", error->message);
- g_clear_error (&error);
- }
-
- g_free (object_path);
-}
-
-static void
-messaging_menu_app_set_desktop_id (MessagingMenuApp *app,
- const gchar *desktop_id)
-{
- g_return_if_fail (desktop_id != NULL);
-
- /* no need to clean up, it's construct only */
- app->appinfo = g_desktop_app_info_new (desktop_id);
- if (app->appinfo == NULL)
- {
- g_warning ("could not find the desktop file for '%s'",
- desktop_id);
- }
-
- g_bus_get (G_BUS_TYPE_SESSION,
- app->cancellable,
- messaging_menu_app_got_bus,
- app);
-}
-
-static void
-messaging_menu_app_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- MessagingMenuApp *app = MESSAGING_MENU_APP (object);
-
- switch (prop_id)
- {
- case PROP_DESKTOP_ID:
- messaging_menu_app_set_desktop_id (app, g_value_get_string (value));
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- }
-}
-
-static void
-messaging_menu_app_finalize (GObject *object)
-{
- G_OBJECT_CLASS (messaging_menu_app_parent_class)->finalize (object);
-}
-
-static void
-messaging_menu_app_dispose (GObject *object)
-{
- MessagingMenuApp *app = MESSAGING_MENU_APP (object);
-
- if (app->watch_id > 0)
- {
- g_bus_unwatch_name (app->watch_id);
- app->watch_id = 0;
- }
-
- if (app->cancellable)
- {
- g_cancellable_cancel (app->cancellable);
- g_object_unref (app->cancellable);
- app->cancellable = NULL;
- }
-
- if (app->messages_service)
- {
- indicator_messages_service_call_application_stopped_running (app->messages_service,
- g_app_info_get_id (G_APP_INFO (app->appinfo)),
- NULL, NULL, NULL);
-
- g_signal_handlers_disconnect_by_func (app->messages_service,
- global_status_changed,
- app);
- g_clear_object (&app->messages_service);
- }
-
- g_clear_pointer (&app->messages, g_hash_table_unref);
-
- g_list_free_full (app->sources, source_free);
- app->sources = NULL;
-
- g_clear_object (&app->app_interface);
- g_clear_object (&app->appinfo);
- g_clear_object (&app->bus);
-
- G_OBJECT_CLASS (messaging_menu_app_parent_class)->dispose (object);
-}
-
-static void
-messaging_menu_app_class_init (MessagingMenuAppClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- object_class->set_property = messaging_menu_app_set_property;
- object_class->finalize = messaging_menu_app_finalize;
- object_class->dispose = messaging_menu_app_dispose;
-
- /**
- * MessagingMenuApp:desktop-id:
- *
- * The desktop id of the application associated with this application
- * section. Must be given when the #MessagingMenuApp is created.
- */
- properties[PROP_DESKTOP_ID] = g_param_spec_string ("desktop-id",
- "Desktop Id",
- "The desktop id of the associated application",
- NULL,
- G_PARAM_WRITABLE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties (object_class, N_PROPERTIES, properties);
-
- /**
- * MessagingMenuApp::activate-source:
- * @mmapp: the #MessagingMenuApp
- * @source_id: the source id that was activated
- *
- * Emitted when the user has activated the message source with id
- * @source_id. The source is immediately removed from the menu,
- * handlers of this signal do not need to call
- * messaging_menu_app_remove_source().
- */
- signals[ACTIVATE_SOURCE] = g_signal_new ("activate-source",
- MESSAGING_MENU_TYPE_APP,
- G_SIGNAL_RUN_FIRST |
- G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1, G_TYPE_STRING);
-
- /**
- * MessagingMenuApp::status-changed:
- * @mmapp: the #MessagingMenuApp
- * @status: a #MessagingMenuStatus
- *
- * Emitted when the chat status is changed through the messaging menu.
- *
- * Applications which are registered to use the chat status should
- * change their status to @status upon receiving this signal. Call
- * messaging_menu_app_set_status() to acknowledge that the application
- * changed its status.
- */
- signals[STATUS_CHANGED] = g_signal_new ("status-changed",
- MESSAGING_MENU_TYPE_APP,
- G_SIGNAL_RUN_FIRST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__INT,
- G_TYPE_NONE, 1, G_TYPE_INT);
-}
-
-static void
-created_messages_service (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- GError *error = NULL;
-
- app->messages_service = indicator_messages_service_proxy_new_finish (result, &error);
- if (!app->messages_service)
- {
- g_warning ("unable to connect to the mesaging menu service: %s", error->message);
- g_error_free (error);
- return;
- }
-
- g_signal_connect (app->messages_service, "status-changed",
- G_CALLBACK (global_status_changed), app);
-
- /* sync current status */
- if (app->registered == TRUE)
- messaging_menu_app_register (app);
- else if (app->registered == FALSE)
- messaging_menu_app_unregister (app);
- if (app->status_set)
- messaging_menu_app_set_status (app, app->status);
-}
-
-static void
-indicator_messages_appeared (GDBusConnection *bus,
- const gchar *name,
- const gchar *name_owner,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
-
- indicator_messages_service_proxy_new (bus,
- G_DBUS_PROXY_FLAGS_NONE,
- "com.canonical.indicator.messages",
- "/com/canonical/indicator/messages/service",
- app->cancellable,
- created_messages_service,
- app);
-}
-
-static void
-indicator_messages_vanished (GDBusConnection *bus,
- const gchar *name,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
-
- if (app->messages_service)
- {
- g_signal_handlers_disconnect_by_func (app->messages_service,
- global_status_changed,
- app);
- g_clear_object (&app->messages_service);
- }
-}
-
-static gboolean
-messaging_menu_app_list_sources (IndicatorMessagesApplication *app_interface,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- GVariantBuilder builder;
- GList *it;
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssuxsb)"));
-
- for (it = app->sources; it; it = it->next)
- g_variant_builder_add_value (&builder, source_to_variant (it->data));
-
- indicator_messages_application_complete_list_sources (app_interface,
- invocation,
- g_variant_builder_end (&builder));
-
- return TRUE;
-}
-
-static gint
-compare_source_id (gconstpointer a,
- gconstpointer b)
-{
- const Source *source = a;
- const gchar *id = b;
-
- return strcmp (source->id, id);
-}
-
-static gboolean
-messaging_menu_app_remove_source_internal (MessagingMenuApp *app,
- const gchar *source_id)
-{
- GList *node;
-
- node = g_list_find_custom (app->sources, source_id, compare_source_id);
- if (node)
- {
- source_free (node->data);
- app->sources = g_list_delete_link (app->sources, node);
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-messaging_menu_app_remove_message_internal (MessagingMenuApp *app,
- const gchar *message_id)
-{
- return g_hash_table_remove (app->messages, message_id);
-}
-
-static gboolean
-messaging_menu_app_activate_source (IndicatorMessagesApplication *app_interface,
- GDBusMethodInvocation *invocation,
- const gchar *source_id,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- GQuark q = g_quark_from_string (source_id);
-
- /* Activate implies removing the source, no need for SourceRemoved */
- if (messaging_menu_app_remove_source_internal (app, source_id))
- g_signal_emit (app, signals[ACTIVATE_SOURCE], q, source_id);
-
- indicator_messages_application_complete_activate_source (app_interface, invocation);
-
- return TRUE;
-}
-
-static gboolean
-messaging_menu_app_list_messages (IndicatorMessagesApplication *app_interface,
- GDBusMethodInvocation *invocation,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- GVariantBuilder builder;
- GHashTableIter iter;
- MessagingMenuMessage *message;
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxaa{sv}b)"));
-
- g_hash_table_iter_init (&iter, app->messages);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &message))
- g_variant_builder_add_value (&builder, _messaging_menu_message_to_variant (message));
-
- indicator_messages_application_complete_list_messages (app_interface,
- invocation,
- g_variant_builder_end (&builder));
-
- return TRUE;
-}
-
-static gboolean
-messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface,
- GDBusMethodInvocation *invocation,
- const gchar *message_id,
- const gchar *action_id,
- GVariant *params,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- MessagingMenuMessage *msg;
-
- msg = g_hash_table_lookup (app->messages, message_id);
- if (msg)
- {
- if (*action_id)
- {
- gchar *signal;
-
- signal = g_strconcat ("activate::", action_id, NULL);
-
- if (g_variant_n_children (params))
- {
- GVariant *param;
-
- g_variant_get_child (params, 0, "v", &param);
- g_signal_emit_by_name (msg, signal, action_id, param);
-
- g_variant_unref (param);
- }
- else
- g_signal_emit_by_name (msg, signal, action_id, NULL);
-
- g_free (signal);
- }
- else
- g_signal_emit_by_name (msg, "activate", NULL, NULL);
-
-
- /* Activate implies removing the message, no need for MessageRemoved */
- messaging_menu_app_remove_message_internal (app, message_id);
- }
-
- indicator_messages_application_complete_activate_message (app_interface, invocation);
-
- return TRUE;
-}
-
-static gboolean
-messaging_menu_app_dismiss (IndicatorMessagesApplication *app_interface,
- GDBusMethodInvocation *invocation,
- const gchar * const *sources,
- const gchar * const *messages,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- const gchar * const *it;
-
- for (it = sources; *it; it++)
- messaging_menu_app_remove_source_internal (app, *it);
-
- for (it = messages; *it; it++)
- messaging_menu_app_remove_message_internal (app, *it);
-
- return TRUE;
-}
-
-static void
-messaging_menu_app_init (MessagingMenuApp *app)
-{
- app->registered = -1;
- app->status_set = FALSE;
- app->bus = NULL;
-
- app->cancellable = g_cancellable_new ();
-
- app->app_interface = indicator_messages_application_skeleton_new ();
- g_signal_connect (app->app_interface, "handle-list-sources",
- G_CALLBACK (messaging_menu_app_list_sources), app);
- g_signal_connect (app->app_interface, "handle-activate-source",
- G_CALLBACK (messaging_menu_app_activate_source), app);
- g_signal_connect (app->app_interface, "handle-list-messages",
- G_CALLBACK (messaging_menu_app_list_messages), app);
- g_signal_connect (app->app_interface, "handle-activate-message",
- G_CALLBACK (messaging_menu_app_activate_message), app);
- g_signal_connect (app->app_interface, "handle-dismiss",
- G_CALLBACK (messaging_menu_app_dismiss), app);
-
- app->messages = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
-
- app->watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
- "com.canonical.indicator.messages",
- G_BUS_NAME_WATCHER_FLAGS_NONE,
- indicator_messages_appeared,
- indicator_messages_vanished,
- app,
- NULL);
-}
-
-/**
- * messaging_menu_new:
- * @desktop_id: a desktop file id. See g_desktop_app_info_new()
- *
- * Creates a new #MessagingMenuApp for the application associated with
- * @desktop_id.
- *
- * The application will not show up (nor be marked as "running") in the
- * Messaging Menu before messaging_menu_app_register() has been called.
- *
- * Returns: (transfer full): a new #MessagingMenuApp
- */
-MessagingMenuApp *
-messaging_menu_app_new (const gchar *desktop_id)
-{
- return g_object_new (MESSAGING_MENU_TYPE_APP,
- "desktop-id", desktop_id,
- NULL);
-}
-
-/**
- * messaging_menu_app_register:
- * @app: a #MessagingMenuApp
- *
- * Registers @app with the Messaging Menu.
- *
- * If the application doesn't already have a section in the Messaging
- * Menu, one will be created for it. The application will also be
- * marked as "running".
- *
- * The application will be marked as "not running" as soon as @app is
- * destroyed. The application launcher as well as shortcut actions will
- * remain in the menu. To completely remove the application section
- * from the Messaging Menu, call messaging_menu_app_unregister().
- */
-void
-messaging_menu_app_register (MessagingMenuApp *app)
-{
- gchar *object_path;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
-
- app->registered = TRUE;
-
- /* state will be synced right after connecting to the service */
- if (!app->messages_service)
- return;
-
- object_path = messaging_menu_app_get_dbus_object_path (app);
- if (!object_path)
- return;
-
- indicator_messages_service_call_register_application (app->messages_service,
- g_app_info_get_id (G_APP_INFO (app->appinfo)),
- object_path,
- app->cancellable,
- NULL, NULL);
-
- g_free (object_path);
-}
-
-/**
- * messaging_menu_app_unregister:
- * @app: a #MessagingMenuApp
- *
- * Completely removes the @app from the Messaging Menu. If the
- * application's launcher and shortcut actions should remain in the
- * menu, destroying @app with g_object_unref() suffices.
- *
- * Note: @app will remain valid and usable after this call.
- */
-void
-messaging_menu_app_unregister (MessagingMenuApp *app)
-{
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
-
- app->registered = FALSE;
-
- /* state will be synced right after connecting to the service */
- if (!app->messages_service)
- return;
-
- if (!app->appinfo)
- return;
-
- indicator_messages_service_call_unregister_application (app->messages_service,
- g_app_info_get_id (G_APP_INFO (app->appinfo)),
- app->cancellable,
- NULL, NULL);
-}
-
-/**
- * messaging_menu_app_set_status:
- * @app: a #MessagingMenuApp
- * @status: a #MessagingMenuStatus
- *
- * Notify the Messaging Menu that the chat status of @app has changed to
- * @status.
- *
- * Connect to the ::status-changed signal to receive notification about
- * the user changing their global chat status through the Messaging
- * Menu.
- *
- * This function does nothing for applications whose desktop file does
- * not include X-MessagingMenu-UsesChatSection.
- */
-void
-messaging_menu_app_set_status (MessagingMenuApp *app,
- MessagingMenuStatus status)
-{
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (status >= MESSAGING_MENU_STATUS_AVAILABLE &&
- status <= MESSAGING_MENU_STATUS_OFFLINE);
-
- app->status = status;
- app->status_set = TRUE;
-
- /* state will be synced right after connecting to the service */
- if (!app->messages_service)
- return;
-
- if (!app->appinfo)
- return;
-
- indicator_messages_service_call_set_status (app->messages_service,
- g_app_info_get_id (G_APP_INFO (app->appinfo)),
- status_ids [status],
- app->cancellable,
- NULL, NULL);
-}
-
-static int
-status_from_string (const gchar *s)
-{
- int i;
-
- if (!s)
- return -1;
-
- for (i = 0; i <= MESSAGING_MENU_STATUS_OFFLINE; i++)
- {
- if (g_str_equal (s, status_ids[i]))
- return i;
- }
-
- return -1;
-}
-
-static void
-global_status_changed (IndicatorMessagesService *service,
- const gchar *status_str,
- gpointer user_data)
-{
- MessagingMenuApp *app = user_data;
- int status;
-
- status = status_from_string (status_str);
- g_return_if_fail (status >= 0);
-
- g_signal_emit (app, signals[STATUS_CHANGED], 0, status);
-}
-
-static Source *
-messaging_menu_app_lookup_source (MessagingMenuApp *app,
- const gchar *id)
-{
- GList *node;
-
- node = g_list_find_custom (app->sources, id, compare_source_id);
-
- return node ? node->data : NULL;
-}
-
-static Source *
-messaging_menu_app_get_source (MessagingMenuApp *app,
- const gchar *id)
-{
- Source *source;
-
- source = messaging_menu_app_lookup_source (app, id);
- if (!source)
- g_warning ("a source with id '%s' doesn't exist", id);
-
- return source;
-}
-
-static void
-messaging_menu_app_notify_source_changed (MessagingMenuApp *app,
- Source *source)
-{
- indicator_messages_application_emit_source_changed (app->app_interface,
- source_to_variant (source));
-}
-
-static void
-messaging_menu_app_insert_source_internal (MessagingMenuApp *app,
- gint position,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- guint count,
- gint64 time,
- const gchar *string)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (id != NULL);
- g_return_if_fail (label != NULL);
-
- if (messaging_menu_app_lookup_source (app, id))
- {
- g_warning ("a source with id '%s' already exists", id);
- return;
- }
-
- source = g_slice_new0 (Source);
- source->id = g_strdup (id);
- source->label = g_strdup (label);
- if (icon)
- source->icon = g_object_ref (icon);
- source->count = count;
- source->time = time;
- source->string = g_strdup (string);
- app->sources = g_list_insert (app->sources, source, position);
-
- indicator_messages_application_emit_source_added (app->app_interface,
- position,
- source_to_variant (source));
-}
-
-/**
- * messaging_menu_app_insert_source:
- * @app: a #MessagingMenuApp
- * @position: the position at which to insert the source
- * @id: a unique identifier for the source to be added
- * @icon: the icon associated with the source
- * @label: a user-visible string best describing the source
- *
- * Inserts a new message source into the section representing @app. Equivalent
- * to calling messaging_menu_app_insert_source_with_time() with the current
- * time.
- *
- * It is an error to insert a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_insert_source (MessagingMenuApp *app,
- gint position,
- const gchar *id,
- GIcon *icon,
- const gchar *label)
-{
- messaging_menu_app_insert_source_with_time (app, position, id, icon, label,
- g_get_real_time ());
-}
-
-/**
- * messaging_menu_app_append_source:
- * @app: a #MessagingMenuApp
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- *
- * Appends a new message source to the end of the section representing @app.
- * Equivalent to calling messaging_menu_app_append_source_with_time() with the
- * current time.
- *
- * It is an error to add a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_append_source (MessagingMenuApp *app,
- const gchar *id,
- GIcon *icon,
- const gchar *label)
-{
- messaging_menu_app_insert_source (app, -1, id, icon, label);
-}
-
-/**
- * messaging_menu_app_insert_source_with_count:
- * @app: a #MessagingMenuApp
- * @position: the position at which to insert the source
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- * @count: the count for the source
- *
- * Inserts a new message source into the section representing @app and
- * initializes it with @count.
- *
- * To update the count, use messaging_menu_app_set_source_count().
- *
- * It is an error to insert a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_insert_source_with_count (MessagingMenuApp *app,
- gint position,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- guint count)
-{
- messaging_menu_app_insert_source_internal (app, position, id, icon, label, count, 0, "");
-}
-
-/**
- * messaging_menu_app_append_source_with_count:
- * @app: a #MessagingMenuApp
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- * @count: the count for the source
- *
- * Appends a new message source to the end of the section representing @app and
- * initializes it with @count.
- *
- * To update the count, use messaging_menu_app_set_source_count().
- *
- * It is an error to add a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void messaging_menu_app_append_source_with_count (MessagingMenuApp *app,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- guint count)
-{
- messaging_menu_app_insert_source_with_count (app, -1, id, icon, label, count);
-}
-
-/**
- * messaging_menu_app_insert_source_with_time:
- * @app: a #MessagingMenuApp
- * @position: the position at which to insert the source
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- * @time: the time when the source was created, in microseconds
- *
- * Inserts a new message source into the section representing @app and
- * initializes it with @time. Use messaging_menu_app_insert_source() to
- * insert a source with the current time.
- *
- * To change the time, use messaging_menu_app_set_source_time().
- *
- * It is an error to insert a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_insert_source_with_time (MessagingMenuApp *app,
- gint position,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- gint64 time)
-{
- messaging_menu_app_insert_source_internal (app, position, id, icon, label, 0, time, "");
-}
-
-/**
- * messaging_menu_app_append_source_with_time:
- * @app: a #MessagingMenuApp
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- * @time: the time when the source was created, in microseconds
- *
- * Appends a new message source to the end of the section representing
- * @app and initializes it with @time. Use
- * messaging_menu_app_append_source() to append a source with the
- * current time.
- *
- * To change the time, use messaging_menu_app_set_source_time().
- *
- * It is an error to insert a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_append_source_with_time (MessagingMenuApp *app,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- gint64 time)
-{
- messaging_menu_app_insert_source_with_time (app, -1, id, icon, label, time);
-}
-
-/**
- * messaging_menu_app_insert_source_with_string:
- * @app: a #MessagingMenuApp
- * @position: the position at which to insert the source
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- * @str: a string associated with the source
- *
- * Inserts a new message source into the section representing @app and
- * initializes it with @str.
- *
- * To update the string, use messaging_menu_app_set_source_string().
- *
- * It is an error to insert a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_insert_source_with_string (MessagingMenuApp *app,
- gint position,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- const gchar *str)
-{
- messaging_menu_app_insert_source_internal (app, position, id, icon, label, 0, 0, str);
-}
-
-/**
- * messaging_menu_app_append_source_with_string:
- * @app: a #MessagingMenuApp
- * @id: a unique identifier for the source to be added
- * @icon: (allow-none): the icon associated with the source
- * @label: a user-visible string best describing the source
- * @str: a string associated with the source
- *
- * Appends a new message source to the end of the section representing @app and
- * initializes it with @str.
- *
- * To update the string, use messaging_menu_app_set_source_string().
- *
- * It is an error to insert a source with an @id which already exists. Use
- * messaging_menu_app_has_source() to find out whether there is such a source.
- */
-void
-messaging_menu_app_append_source_with_string (MessagingMenuApp *app,
- const gchar *id,
- GIcon *icon,
- const gchar *label,
- const gchar *str)
-{
- messaging_menu_app_insert_source_with_string (app, -1, id, icon, label, str);
-}
-
-/**
- * messaging_menu_app_remove_source:
- * @app: a #MessagingMenuApp
- * @source_id: the id of the source to remove
- *
- * Removes the source corresponding to @source_id from the menu.
- */
-void
-messaging_menu_app_remove_source (MessagingMenuApp *app,
- const gchar *source_id)
-{
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- if (messaging_menu_app_remove_source_internal (app, source_id))
- indicator_messages_application_emit_source_removed (app->app_interface, source_id);
-}
-
-/**
- * messaging_menu_app_has_source:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- *
- * Returns: TRUE if there is a source associated with @source_id
- */
-gboolean
-messaging_menu_app_has_source (MessagingMenuApp *app,
- const gchar *source_id)
-{
- g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), FALSE);
- g_return_val_if_fail (source_id != NULL, FALSE);
-
- return messaging_menu_app_lookup_source (app, source_id) != NULL;
-}
-
-/**
- * messaging_menu_app_set_source_label:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- * @label: the new label for the source
- *
- * Changes the label of @source_id to @label.
- */
-void
-messaging_menu_app_set_source_label (MessagingMenuApp *app,
- const gchar *source_id,
- const gchar *label)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
- g_return_if_fail (label != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- g_free (source->label);
- source->label = g_strdup (label);
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_set_source_icon:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- * @icon: (allow-none): the new icon for the source
- *
- * Changes the icon of @source_id to @icon.
- */
-void
-messaging_menu_app_set_source_icon (MessagingMenuApp *app,
- const gchar *source_id,
- GIcon *icon)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- g_clear_object (&source->icon);
- if (icon)
- source->icon = g_object_ref (icon);
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_set_source_count:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- * @count: the new count for the source
- *
- * Updates the count of @source_id to @count.
- */
-void messaging_menu_app_set_source_count (MessagingMenuApp *app,
- const gchar *source_id,
- guint count)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- source->count = count;
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_set_source_time:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- * @time: the new time for the source, in microseconds
- *
- * Updates the time of @source_id to @time.
- */
-void
-messaging_menu_app_set_source_time (MessagingMenuApp *app,
- const gchar *source_id,
- gint64 time)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- source->time = time;
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_set_source_string:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- * @str: the new string for the source
- *
- * Updates the string displayed next to @source_id to @str.
- */
-void
-messaging_menu_app_set_source_string (MessagingMenuApp *app,
- const gchar *source_id,
- const gchar *str)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- g_free (source->string);
- source->string = g_strdup (str);
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_draw_attention:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- *
- * Indicates that @source_id has important unread messages. Currently, this
- * means that the messaging menu's envelope icon will turn blue.
- *
- * Use messaging_menu_app_remove_attention() to stop indicating that the source
- * needs attention.
- */
-void
-messaging_menu_app_draw_attention (MessagingMenuApp *app,
- const gchar *source_id)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- source->draws_attention = TRUE;
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_remove_attention:
- * @app: a #MessagingMenuApp
- * @source_id: a source id
- *
- * Stop indicating that @source_id needs attention.
- *
- * This function does not need to be called when the source is removed
- * with messaging_menu_app_remove_source() or the user has activated the
- * source.
- *
- * Use messaging_menu_app_draw_attention() to make @source_id draw attention
- * again.
- */
-void
-messaging_menu_app_remove_attention (MessagingMenuApp *app,
- const gchar *source_id)
-{
- Source *source;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (source_id != NULL);
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source)
- {
- source->draws_attention = FALSE;
- messaging_menu_app_notify_source_changed (app, source);
- }
-}
-
-/**
- * messaging_menu_app_append_message:
- * @app: a #MessagingMenuApp
- * @msg: the #MessagingMenuMessage to append
- * @source_id: (allow-none): the source id to which @msg is added, or NULL
- * @notify: whether a notification bubble should be shown for this
- * message
- *
- * Appends @msg to the source with id @source_id of @app. The messaging
- * menu might not display this message immediately if other messages are
- * queued before this one.
- *
- * If @source_id has a count associated with it, that count will be
- * increased by one.
- *
- * If @source_id is %NULL, @msg won't be associated with a source.
- */
-void
-messaging_menu_app_append_message (MessagingMenuApp *app,
- MessagingMenuMessage *msg,
- const gchar *source_id,
- gboolean notify)
-{
- const gchar *id;
-
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
-
- id = messaging_menu_message_get_id (msg);
-
- if (g_hash_table_lookup (app->messages, id))
- {
- g_warning ("a message with id '%s' already exists", id);
- return;
- }
-
- g_hash_table_insert (app->messages, g_strdup (id), g_object_ref (msg));
- indicator_messages_application_emit_message_added (app->app_interface,
- _messaging_menu_message_to_variant (msg));
-
- if (source_id)
- {
- Source *source;
-
- source = messaging_menu_app_get_source (app, source_id);
- if (source && source->count >= 0)
- {
- source->count++;
- messaging_menu_app_notify_source_changed (app, source);
- }
- }
-}
-
-/**
- * messaging_menu_app_get_message:
- * @app: a #MessagingMenuApp
- * @id: id of the message to retrieve
- *
- * Retrieves the message with @id, that was added with
- * messaging_menu_app_append_message().
- *
- * Returns: (transfer none) (allow-none): the #MessagingMenuApp with
- * @id, or %NULL
- */
-MessagingMenuMessage *
-messaging_menu_app_get_message (MessagingMenuApp *app,
- const gchar *id)
-{
- g_return_val_if_fail (MESSAGING_MENU_IS_APP (app), NULL);
- g_return_val_if_fail (id != NULL, NULL);
-
- return g_hash_table_lookup (app->messages, id);
-}
-
-/**
- * messaging_menu_app_remove_message:
- * @app: a #MessagingMenuApp
- * @msg: the #MessagingMenuMessage to remove
- *
- * Removes @msg from @app.
- *
- * If @source_id has a count associated with it, that count will be
- * decreased by one.
- */
-void
-messaging_menu_app_remove_message (MessagingMenuApp *app,
- MessagingMenuMessage *msg)
-{
- /* take a ref of @msg here to make sure the pointer returned by
- * _get_id() is valid for the duration of remove_message_by_id. */
- g_object_ref (msg);
- messaging_menu_app_remove_message_by_id (app, messaging_menu_message_get_id (msg));
- g_object_unref (msg);
-}
-
-/**
- * messaging_menu_app_remove_message_by_id:
- * @app: a #MessagingMenuApp
- * @id: the unique id of @msg
- *
- * Removes the message with the id @id from @app.
- *
- * If @source_id has a count associated with it, that count will be
- * decreased by one.
- */
-void
-messaging_menu_app_remove_message_by_id (MessagingMenuApp *app,
- const gchar *id)
-{
- g_return_if_fail (MESSAGING_MENU_IS_APP (app));
- g_return_if_fail (id != NULL);
-
- if (messaging_menu_app_remove_message_internal (app, id))
- indicator_messages_application_emit_message_removed (app->app_interface, id);
-}