diff options
Diffstat (limited to 'libmessaging-menu/messaging-menu-app.c')
-rw-r--r-- | libmessaging-menu/messaging-menu-app.c | 1433 |
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", ¶m); - 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); -} |