Back to index

libindicate  12.10.0
indicator.c
Go to the documentation of this file.
00001 /*
00002 A library to allow applictions to provide simple indications of
00003 information to be displayed to users of the application through the
00004 interface shell.
00005 
00006 Copyright 2009 Canonical Ltd.
00007 
00008 Authors:
00009     Ted Gould <ted@canonical.com>
00010 
00011 This program is free software: you can redistribute it and/or modify it 
00012 under the terms of either or both of the following licenses:
00013 
00014 1) the GNU Lesser General Public License version 3, as published by the 
00015 Free Software Foundation; and/or
00016 2) the GNU Lesser General Public License version 2.1, as published by 
00017 the Free Software Foundation.
00018 
00019 This program is distributed in the hope that it will be useful, but 
00020 WITHOUT ANY WARRANTY; without even the implied warranties of 
00021 MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR 
00022 PURPOSE.  See the applicable version of the GNU Lesser General Public 
00023 License for more details.
00024 
00025 You should have received a copy of both the GNU Lesser General Public 
00026 License version 3 and version 2.1 along with this program.  If not, see 
00027 <http://www.gnu.org/licenses/>
00028 */
00029 
00030 #include <glib.h>
00031 #include "indicator.h"
00032 #include "server.h"
00033 
00034 /* Signals */
00035 enum {
00036        HIDE,
00037        SHOW,
00038        USER_DISPLAY,
00039        MODIFIED,
00040        DISPLAYED,
00041        LAST_SIGNAL
00042 };
00043 
00044 static guint signals[LAST_SIGNAL] = { 0 };
00045 
00046 typedef struct _IndicateIndicatorPrivate IndicateIndicatorPrivate;
00047 struct _IndicateIndicatorPrivate
00048 {
00049        guint id;
00050        gboolean is_visible;
00051        IndicateServer * server;
00052        GHashTable * properties;
00053        gboolean is_displayed;
00054 };
00055 
00056 #define INDICATE_INDICATOR_GET_PRIVATE(o) \
00057           (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATE_TYPE_INDICATOR, IndicateIndicatorPrivate))
00058 
00059 G_DEFINE_TYPE (IndicateIndicator, indicate_indicator, G_TYPE_OBJECT);
00060 
00061 static void indicate_indicator_finalize (GObject * object);
00062 static void set_property (IndicateIndicator * indicator, const gchar * key, GVariant * data);
00063 static GVariant * get_property (IndicateIndicator * indicator, const gchar * key);
00064 static GPtrArray * list_properties (IndicateIndicator * indicator);
00065 
00066 
00067 /* Functions */
00068 static void
00069 indicate_indicator_class_init (IndicateIndicatorClass * class)
00070 {
00071        /* g_debug("Indicator Class Initialized."); */
00072 
00073        GObjectClass * gobj;
00074        gobj = G_OBJECT_CLASS(class);
00075 
00076        g_type_class_add_private (class, sizeof (IndicateIndicatorPrivate));
00077 
00078        gobj->finalize = indicate_indicator_finalize;
00079 
00088        signals[USER_DISPLAY] = g_signal_new(INDICATE_INDICATOR_SIGNAL_DISPLAY,
00089                                             G_TYPE_FROM_CLASS(class),
00090                                             G_SIGNAL_RUN_LAST,
00091                                             G_STRUCT_OFFSET(IndicateIndicatorClass, user_display),
00092                                             NULL, NULL,
00093                                             g_cclosure_marshal_VOID__UINT,
00094                                             G_TYPE_NONE, 1, G_TYPE_UINT);
00104        signals[HIDE] = g_signal_new(INDICATE_INDICATOR_SIGNAL_HIDE,
00105                                             G_TYPE_FROM_CLASS(class),
00106                                             G_SIGNAL_RUN_LAST,
00107                                             G_STRUCT_OFFSET(IndicateIndicatorClass, hide),
00108                                             NULL, NULL,
00109                                             g_cclosure_marshal_VOID__VOID,
00110                                             G_TYPE_NONE, 0);
00120        signals[SHOW] = g_signal_new(INDICATE_INDICATOR_SIGNAL_SHOW,
00121                                             G_TYPE_FROM_CLASS(class),
00122                                             G_SIGNAL_RUN_LAST,
00123                                             G_STRUCT_OFFSET(IndicateIndicatorClass, show),
00124                                             NULL, NULL,
00125                                             g_cclosure_marshal_VOID__VOID,
00126                                             G_TYPE_NONE, 0);
00137        signals[MODIFIED] = g_signal_new(INDICATE_INDICATOR_SIGNAL_MODIFIED,
00138                                             G_TYPE_FROM_CLASS(class),
00139                                             G_SIGNAL_RUN_LAST,
00140                                             G_STRUCT_OFFSET(IndicateIndicatorClass, modified),
00141                                             NULL, NULL,
00142                                             g_cclosure_marshal_VOID__STRING,
00143                                             G_TYPE_NONE, 1, G_TYPE_STRING);
00153        signals[DISPLAYED] = g_signal_new(INDICATE_INDICATOR_SIGNAL_DISPLAYED,
00154                                             G_TYPE_FROM_CLASS(class),
00155                                             G_SIGNAL_RUN_LAST,
00156                                             G_STRUCT_OFFSET(IndicateIndicatorClass, displayed),
00157                                             NULL, NULL,
00158                                             g_cclosure_marshal_VOID__BOOLEAN,
00159                                             G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
00160 
00161        class->set_property = set_property;
00162        class->get_property = get_property;
00163        class->list_properties = list_properties;
00164 
00165        return;
00166 }
00167 
00168 /* A small little function to both clear the insides of a 
00169    value as well as the memory it itself uses. */
00170 static void 
00171 _g_variant_unref (gpointer data)
00172 {
00173        if (data == NULL) return;
00174        GVariant * value = (GVariant*)data;
00175        g_variant_unref(value);
00176        return;
00177 }
00178 
00179 static void
00180 indicate_indicator_init (IndicateIndicator * indicator)
00181 {
00182        /* g_debug("Indicator Object Initialized."); */
00183        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00184 
00185        priv->is_visible = FALSE;
00186        priv->is_displayed = FALSE;
00187 
00188        priv->properties = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _g_variant_unref);
00189 
00190        priv->server = indicate_server_ref_default();
00191        priv->id = indicate_server_get_next_id(priv->server);
00192 
00193        indicate_server_add_indicator(priv->server, indicator);
00194 
00195        return;
00196 }
00197 
00198 static void
00199 indicate_indicator_finalize (GObject * obj)
00200 {
00201        IndicateIndicator * indicator = INDICATE_INDICATOR(obj);
00202        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00203 
00204        indicate_server_remove_indicator(priv->server, indicator);
00205        g_object_unref(priv->server);
00206        priv->server = NULL;
00207 
00208        G_OBJECT_CLASS (indicate_indicator_parent_class)->finalize (obj);
00209        return;
00210 }
00211 
00227 IndicateIndicator *
00228 indicate_indicator_new (void)
00229 {
00230        IndicateIndicator * indicator = g_object_new(INDICATE_TYPE_INDICATOR, NULL);
00231        return indicator;
00232 }
00233 
00244 IndicateIndicator *
00245 indicate_indicator_new_with_server (IndicateServer * server)
00246 {
00247        g_return_val_if_fail(server != NULL, NULL);
00248 
00249        IndicateIndicator * indicator = g_object_new(INDICATE_TYPE_INDICATOR, NULL);
00250 
00251        indicate_indicator_set_server (indicator, server);
00252 
00253        return indicator;
00254 }
00255 
00264 void
00265 indicate_indicator_set_server (IndicateIndicator * indicator, IndicateServer * server)
00266 {
00267        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00268 
00269        if (server != NULL) {
00270               g_object_ref(server);
00271        }
00272 
00273        if (priv->server != NULL) {
00274               indicate_server_remove_indicator (priv->server, indicator);
00275               g_object_unref(priv->server);
00276        }
00277 
00278        priv->server = server;
00279        if (server != NULL) {
00280               indicate_server_add_indicator (server, indicator);
00281        }
00282 
00283        return;
00284 }
00285 
00286 
00295 void
00296 indicate_indicator_show (IndicateIndicator * indicator)
00297 {
00298        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00299 
00300        if (priv->is_visible) {
00301               return;
00302        }
00303 
00304        if (priv->server) {
00305               indicate_server_show(priv->server);
00306        }
00307 
00308        priv->is_visible = TRUE;
00309        g_signal_emit(indicator, signals[SHOW], 0, TRUE);
00310 
00311        return;
00312 }
00313 
00321 void
00322 indicate_indicator_hide (IndicateIndicator * indicator)
00323 {
00324        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00325 
00326        if (!priv->is_visible) {
00327               return;
00328        }
00329 
00330        priv->is_visible = FALSE;
00331        g_signal_emit(indicator, signals[HIDE], 0, TRUE);
00332        priv->is_displayed = FALSE;
00333        g_signal_emit(G_OBJECT(indicator), signals[DISPLAYED], 0, priv->is_displayed, TRUE);
00334 
00335        return;
00336 }
00337 
00346 gboolean
00347 indicate_indicator_is_visible (IndicateIndicator * indicator)
00348 {
00349        g_return_val_if_fail(INDICATE_IS_INDICATOR(indicator), FALSE);
00350        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00351        return priv->is_visible;
00352 }
00353 
00363 guint
00364 indicate_indicator_get_id (IndicateIndicator * indicator)
00365 {
00366        g_return_val_if_fail(INDICATE_IS_INDICATOR(indicator), 0);
00367        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00368        return priv->id;
00369 }
00370 
00380 IndicateServer *
00381 indicate_indicator_get_server (IndicateIndicator * indicator)
00382 {
00383        g_return_val_if_fail(INDICATE_IS_INDICATOR(indicator), NULL);
00384        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00385        return priv->server;
00386 }
00387 
00397 void
00398 indicate_indicator_user_display (IndicateIndicator * indicator, guint timestamp)
00399 {
00400        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00401        if (!priv->is_visible) {
00402               return;
00403        }
00404 
00405        g_signal_emit(indicator, signals[USER_DISPLAY], 0, timestamp, TRUE);
00406        return;
00407 }
00408 
00421 void
00422 indicate_indicator_set_property (IndicateIndicator * indicator, const gchar * key, const gchar * data)
00423 {
00424        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00425        if (class->set_property == NULL) {
00426               return;
00427        }
00428 
00429        GVariant * variant = g_variant_new_string(data);
00430        return class->set_property(indicator, key, variant);
00431 }
00432 
00444 void
00445 indicate_indicator_set_property_time (IndicateIndicator * indicator, const gchar * key, GTimeVal * time)
00446 {
00447        gchar * timestr = g_time_val_to_iso8601(time);
00448        if (timestr != NULL) {
00449               indicate_indicator_set_property(indicator, key, timestr);
00450               g_free(timestr);
00451        }
00452        return;
00453 }
00454 
00465 void
00466 indicate_indicator_set_property_int (IndicateIndicator * indicator, const gchar * key, gint value)
00467 {
00468        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00469        if (class->set_property == NULL) {
00470               return;
00471        }
00472 
00473        GValue intval = {0};
00474        g_value_init(&intval, G_TYPE_INT);
00475        g_value_set_int(&intval, value);
00476 
00477        GVariant * variant = g_variant_new_int32(value);
00478        return class->set_property(indicator, key, variant);
00479 }
00480 
00491 void
00492 indicate_indicator_set_property_bool (IndicateIndicator * indicator, const gchar * key, gboolean value)
00493 {
00494        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00495        if (class->set_property == NULL) {
00496               return;
00497        }
00498 
00499        GVariant * variant = g_variant_new_boolean(value);
00500        return class->set_property(indicator, key, variant);
00501 }
00502 
00503 void
00504 indicate_indicator_set_property_variant (IndicateIndicator * indicator, const gchar * key, GVariant * value)
00505 {
00506        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00507        if (class->set_property == NULL) {
00508               return;
00509        }
00510 
00511        return class->set_property(indicator, key, value);
00512 }
00513 
00524 const gchar *
00525 indicate_indicator_get_property (IndicateIndicator * indicator, const gchar * key)
00526 {
00527        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00528        if (class->get_property == NULL) {
00529               return NULL;
00530        }
00531 
00532        GVariant * val = class->get_property(indicator, key);
00533        if (val == NULL) {
00534               return NULL;
00535        } else {
00536               return g_variant_get_string(val, NULL);
00537        }
00538 }
00539 
00540 GVariant *
00541 indicate_indicator_get_property_variant (IndicateIndicator * indicator, const gchar * key)
00542 {
00543        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00544        if (class->get_property == NULL) {
00545               return NULL;
00546        }
00547 
00548        return class->get_property(indicator, key);
00549 }
00550 
00551 GPtrArray *
00552 indicate_indicator_list_properties (IndicateIndicator * indicator)
00553 {
00554        IndicateIndicatorClass * class = INDICATE_INDICATOR_GET_CLASS(indicator);
00555        if (class->list_properties == NULL) {
00556               return g_ptr_array_new();
00557        }
00558 
00559        return class->list_properties(indicator);
00560 }
00561 
00562 static void
00563 set_property (IndicateIndicator * indicator, const gchar * key, GVariant * data)
00564 {
00565        g_return_if_fail(INDICATE_IS_INDICATOR(indicator));
00566 
00567        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00568 
00569        gchar * newkey = g_strdup(key);
00570        if (data != NULL) {
00571               g_variant_ref(data);
00572        }
00573 
00574        g_hash_table_replace(priv->properties, newkey, data);
00575 
00576        if (indicate_indicator_is_visible(indicator)) {
00577               /* g_debug("Indicator property modified: %s", key); */
00578               g_signal_emit(indicator, signals[MODIFIED], 0, key, TRUE);
00579        }
00580 
00581        return;
00582 }
00583 
00584 static GVariant *
00585 get_property (IndicateIndicator * indicator, const gchar * key)
00586 {
00587        g_return_val_if_fail(INDICATE_IS_INDICATOR(indicator), NULL);
00588 
00589        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00590 
00591        return (GVariant *)g_hash_table_lookup(priv->properties, key);
00592 }
00593 
00594 static GPtrArray *
00595 list_properties (IndicateIndicator * indicator)
00596 {
00597        g_return_val_if_fail(INDICATE_IS_INDICATOR(indicator), g_ptr_array_new());
00598        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00599 
00600        GList * keys = g_hash_table_get_keys(priv->properties);
00601        GPtrArray * properties = g_ptr_array_sized_new(g_list_length(keys) + 1);
00602 
00603        GList * l;
00604        for (l=keys; l!=NULL; l=l->next) {
00605               g_ptr_array_add(properties, g_strdup(l->data));
00606        }
00607 
00608        g_list_free (keys);
00609        return properties;
00610 }
00611 
00621 void
00622 indicate_indicator_set_displayed (IndicateIndicator * indicator, gboolean displayed)
00623 {
00624        g_return_if_fail(INDICATE_IS_INDICATOR(indicator));
00625        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00626 
00627        if (priv->is_displayed != displayed) {
00628               priv->is_displayed = displayed;
00629               g_signal_emit(G_OBJECT(indicator), signals[DISPLAYED], 0, displayed, TRUE);
00630        }
00631 
00632        return;
00633 }
00634 
00644 gboolean
00645 indicate_indicator_get_displayed (IndicateIndicator * indicator)
00646 {
00647        g_return_val_if_fail(INDICATE_IS_INDICATOR(indicator), FALSE);
00648        IndicateIndicatorPrivate * priv = INDICATE_INDICATOR_GET_PRIVATE(indicator);
00649        return priv->is_visible && priv->is_displayed;
00650 }
00651