/* * Copyright 2013 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 . * * Authors: * Lars Uebernickel */ #include "im-menu.h" #include "im-accounts-service.h" struct _ImMenuPrivate { GMenu *toplevel_menu; GMenu *menu; ImApplicationList *applist; gboolean on_greeter; ImAccountsService *as; }; G_DEFINE_TYPE_WITH_PRIVATE (ImMenu, im_menu, G_TYPE_OBJECT) enum { PROP_0, PROP_APPLICATION_LIST, PROP_ON_GREETER, NUM_PROPERTIES }; static void im_menu_finalize (GObject *object) { ImMenuPrivate *priv = im_menu_get_instance_private (IM_MENU (object)); g_object_unref (priv->toplevel_menu); g_object_unref (priv->menu); g_object_unref (priv->applist); g_object_unref (priv->as); G_OBJECT_CLASS (im_menu_parent_class)->finalize (object); } static void im_menu_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { ImMenuPrivate *priv = im_menu_get_instance_private (IM_MENU (object)); switch (property_id) { case PROP_APPLICATION_LIST: g_value_set_object (value, priv->applist); break; case PROP_ON_GREETER: g_value_set_boolean (value, priv->on_greeter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void im_menu_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { ImMenuPrivate *priv = im_menu_get_instance_private (IM_MENU (object)); switch (property_id) { case PROP_APPLICATION_LIST: /* construct only */ priv->applist = g_value_dup_object (value); break; case PROP_ON_GREETER: priv->on_greeter = g_value_get_boolean (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void im_menu_class_init (ImMenuClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); object_class->finalize = im_menu_finalize; object_class->get_property = im_menu_get_property; object_class->set_property = im_menu_set_property; g_object_class_install_property (object_class, PROP_APPLICATION_LIST, g_param_spec_object ("application-list", "", "", IM_TYPE_APPLICATION_LIST, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ON_GREETER, g_param_spec_boolean ("on-greeter", "", "", FALSE, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void im_menu_init (ImMenu *menu) { ImMenuPrivate *priv = im_menu_get_instance_private (menu); GMenuItem *root; priv->toplevel_menu = g_menu_new (); priv->menu = g_menu_new (); priv->on_greeter = FALSE; priv->as = im_accounts_service_ref_default(); root = g_menu_item_new (NULL, "indicator.messages"); g_menu_item_set_attribute (root, "x-ayatana-type", "s", "org.ayatana.indicator.root"); g_menu_item_set_attribute (root, "action-namespace", "s", "indicator"); g_menu_item_set_submenu (root, G_MENU_MODEL (priv->menu)); g_menu_append_item (priv->toplevel_menu, root); g_object_unref (root); } ImApplicationList * im_menu_get_application_list (ImMenu *menu) { ImMenuPrivate *priv; g_return_val_if_fail (IM_IS_MENU (menu), FALSE); priv = im_menu_get_instance_private (menu); return priv->applist; } gboolean im_menu_export (ImMenu *menu, GDBusConnection *connection, const gchar *object_path, GError **error) { ImMenuPrivate *priv; g_return_val_if_fail (IM_IS_MENU (menu), FALSE); priv = im_menu_get_instance_private (menu); return g_dbus_connection_export_menu_model (connection, object_path, G_MENU_MODEL (priv->toplevel_menu), error) > 0; } void im_menu_prepend_section (ImMenu *menu, GMenuModel *section) { ImMenuPrivate *priv; g_return_if_fail (IM_IS_MENU (menu)); g_return_if_fail (G_IS_MENU_MODEL (section)); priv = im_menu_get_instance_private (menu); g_menu_prepend_section (priv->menu, NULL, section); } void im_menu_append_section (ImMenu *menu, GMenuModel *section) { ImMenuPrivate *priv; g_return_if_fail (IM_IS_MENU (menu)); g_return_if_fail (G_IS_MENU_MODEL (section)); priv = im_menu_get_instance_private (menu); g_menu_append_section (priv->menu, NULL, section); } /* * Inserts @item into @menu by comparing its * "x-messaging-menu-sort-string" with those found in existing menu * items between positions @first and @last. * * If @last is negative, it is counted from the end of @menu. */ void im_menu_insert_item_sorted (ImMenu *menu, GMenuItem *item, gint first, gint last) { ImMenuPrivate *priv; gint position = first; gchar *sort_string; g_return_if_fail (IM_IS_MENU (menu)); g_return_if_fail (G_IS_MENU_ITEM (item)); priv = im_menu_get_instance_private (menu); if (last < 0) last = g_menu_model_get_n_items (G_MENU_MODEL (priv->menu)) + last; g_return_if_fail (first <= last); if (g_menu_item_get_attribute (item, "x-messaging-menu-sort-string", "s", &sort_string)) { while (position < last) { gchar *item_sort; if (g_menu_model_get_item_attribute(G_MENU_MODEL(priv->menu), position, "x-messaging-menu-sort-string", "s", &item_sort)) { gint cmp; cmp = g_utf8_collate(sort_string, item_sort); g_free (item_sort); if (cmp < 0) break; } position++; } } g_menu_insert_item (priv->menu, position, item); } /* Whether the menu should show extra data on it. Depends on the greeter status and user settings */ gboolean im_menu_show_data (ImMenu *menu) { g_return_val_if_fail (IM_IS_MENU (menu), FALSE); ImMenuPrivate *priv = im_menu_get_instance_private (IM_MENU (menu)); if (!priv->on_greeter) return TRUE; return im_accounts_service_get_show_on_greeter(priv->as); }