diff options
Diffstat (limited to 'libempathy')
-rw-r--r-- | libempathy/Makefile.am | 2 | ||||
-rw-r--r-- | libempathy/action-chain-internal.h | 51 | ||||
-rw-r--r-- | libempathy/action-chain.c | 192 | ||||
-rw-r--r-- | libempathy/empathy-contact.c | 96 | ||||
-rw-r--r-- | libempathy/empathy-message.c | 42 |
5 files changed, 355 insertions, 28 deletions
diff --git a/libempathy/Makefile.am b/libempathy/Makefile.am index 48846311f..56ea9e780 100644 --- a/libempathy/Makefile.am +++ b/libempathy/Makefile.am @@ -28,6 +28,7 @@ BUILT_SOURCES = \ noinst_LTLIBRARIES = libempathy.la libempathy_headers = \ + action-chain-internal.h \ empathy-account-settings.h \ empathy-auth-factory.h \ empathy-channel-factory.h \ @@ -69,6 +70,7 @@ libempathy_headers = \ libempathy_la_SOURCES = \ $(libempathy_headers) \ + action-chain.c \ empathy-account-settings.c \ empathy-auth-factory.c \ empathy-channel-factory.c \ diff --git a/libempathy/action-chain-internal.h b/libempathy/action-chain-internal.h new file mode 100644 index 000000000..14750c938 --- /dev/null +++ b/libempathy/action-chain-internal.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Cosimo Alfarano <cosimo.alfarano@collabora.co.uk> + */ + +#ifndef __TPL_ACTION_CHAIN_H__ +#define __TPL_ACTION_CHAIN_H__ + +#include <glib-object.h> +#include <gio/gio.h> + +typedef struct { + GQueue *chain; + GSimpleAsyncResult *simple; + gboolean running; +} TplActionChain; + +TplActionChain *_tpl_action_chain_new_async (GObject *obj, + GAsyncReadyCallback cb, + gpointer user_data); +void _tpl_action_chain_free (TplActionChain *self); +typedef void (*TplPendingAction) (TplActionChain *ctx, gpointer user_data); +void _tpl_action_chain_append (TplActionChain *self, TplPendingAction func, + gpointer user_data); +void _tpl_action_chain_prepend (TplActionChain *self, TplPendingAction func, + gpointer user_data); +void _tpl_action_chain_start (TplActionChain *self); +void _tpl_action_chain_continue (TplActionChain *self); +void _tpl_action_chain_terminate (TplActionChain *self, const GError *error); +void _tpl_action_chain_clear (TplActionChain *self); + +gpointer _tpl_action_chain_get_object (TplActionChain *self); +gboolean _tpl_action_chain_new_finish (GObject *source, + GAsyncResult *result, GError **error); + +#endif // __TPL_ACTION_CHAIN_H__ diff --git a/libempathy/action-chain.c b/libempathy/action-chain.c new file mode 100644 index 000000000..b6bf25ab9 --- /dev/null +++ b/libempathy/action-chain.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2009 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Cosimo Alfarano <cosimo.alfarano@collabora.co.uk> + */ + +#include "config.h" +#include "action-chain-internal.h" + +typedef struct { + TplPendingAction action; + gpointer user_data; +} TplActionLink; + + +TplActionChain * +_tpl_action_chain_new_async (GObject *obj, + GAsyncReadyCallback cb, + gpointer user_data) +{ + TplActionChain *ret = g_slice_new0 (TplActionChain); + + ret->chain = g_queue_new (); + ret->simple = g_simple_async_result_new (obj, cb, user_data, + _tpl_action_chain_new_async); + + g_object_set_data (G_OBJECT (ret->simple), "chain", ret); + + return ret; +} + + +static void +link_free (TplActionLink *l) +{ + g_slice_free (TplActionLink, l); +} + + +void +_tpl_action_chain_free (TplActionChain *self) +{ + g_queue_foreach (self->chain, (GFunc) link_free, NULL); + g_queue_free (self->chain); + g_object_unref (self->simple); + g_slice_free (TplActionChain, self); +} + + +gpointer // FIXME GObject * +_tpl_action_chain_get_object (TplActionChain *self) +{ + GObject *obj; + + g_return_val_if_fail (self != NULL && self->simple != NULL, NULL); + + obj = g_async_result_get_source_object (G_ASYNC_RESULT (self->simple)); + g_object_unref (obj); /* don't want the extra ref */ + + return obj; +} + + +void +_tpl_action_chain_prepend (TplActionChain *self, + TplPendingAction func, + gpointer user_data) +{ + TplActionLink *l; + + l = g_slice_new0 (TplActionLink); + l->action = func; + l->user_data = user_data; + + g_queue_push_head (self->chain, l); +} + + +void +_tpl_action_chain_append (TplActionChain *self, + TplPendingAction func, + gpointer user_data) +{ + TplActionLink *l; + + l = g_slice_new0 (TplActionLink); + l->action = func; + l->user_data = user_data; + + g_queue_push_tail (self->chain, l); +} + +void +_tpl_action_chain_start (TplActionChain *self) +{ + g_return_if_fail (!g_queue_is_empty (self->chain)); + + if (self->running) + return; + + _tpl_action_chain_continue (self); +} + +void +_tpl_action_chain_continue (TplActionChain *self) +{ + if (g_queue_is_empty (self->chain)) + { + self->running = FALSE; + g_simple_async_result_complete (self->simple); + } + else + { + TplActionLink *l = g_queue_pop_head (self->chain); + + self->running = TRUE; + l->action (self, l->user_data); + link_free (l); + if (g_queue_is_empty (self->chain)) + self->running = FALSE; + } +} + + +void +_tpl_action_chain_clear (TplActionChain *self) +{ + g_queue_foreach (self->chain, (GFunc) link_free, NULL); + g_queue_clear (self->chain); +} + +void +_tpl_action_chain_terminate (TplActionChain *self, + const GError *error) +{ + GSimpleAsyncResult *simple = self->simple; + + g_assert (error != NULL); + + g_simple_async_result_set_from_error (simple, error); + g_simple_async_result_complete (simple); +} + + +/** + * _tpl_action_chain_new_finish: + * @source: the #GObject pass to _tpl_action_chain_new_async() + * @result: the #GAsyncResult pass in callback + * @error: a pointer to a #GError that will be set on error, or NULL to ignore + * + * Get the result from running the action chain (%TRUE if the chain completed + * successfully, %FALSE with @error set if it was terminated). + * + * This function also frees the chain. + * + * Returns: %TRUE on success, %FALSE with @error set on error. + */ +gboolean +_tpl_action_chain_new_finish (GObject *source, + GAsyncResult *result, + GError **error) +{ + TplActionChain *chain; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, source, + _tpl_action_chain_new_async), FALSE); + + chain = g_object_get_data (G_OBJECT (result), "chain"); + + g_return_val_if_fail (chain != NULL, FALSE); + + if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error)) + return FALSE; + + _tpl_action_chain_free (chain); + return TRUE; +} diff --git a/libempathy/empathy-contact.c b/libempathy/empathy-contact.c index 55bc40bdd..8cca70944 100644 --- a/libempathy/empathy-contact.c +++ b/libempathy/empathy-contact.c @@ -190,14 +190,12 @@ contact_dispose (GObject *object) { EmpathyContactPriv *priv = GET_PRIV (object); - if (priv->tp_contact) + if (priv->tp_contact != NULL) { - g_hash_table_remove (contacts_table, priv->tp_contact); g_signal_handlers_disconnect_by_func (priv->tp_contact, tp_contact_notify_cb, object); - g_object_unref (priv->tp_contact); } - priv->tp_contact = NULL; + tp_clear_object (&priv->tp_contact); if (priv->account) g_object_unref (priv->account); @@ -631,14 +629,48 @@ contact_set_property (GObject *object, }; } +static void +remove_tp_contact (gpointer data, + GObject *object) +{ + g_hash_table_remove (contacts_table, data); +} + static EmpathyContact * empathy_contact_new (TpContact *tp_contact) { + EmpathyContact *retval; + g_return_val_if_fail (TP_IS_CONTACT (tp_contact), NULL); - return g_object_new (EMPATHY_TYPE_CONTACT, + retval = g_object_new (EMPATHY_TYPE_CONTACT, "tp-contact", tp_contact, NULL); + + g_object_weak_ref (G_OBJECT (retval), remove_tp_contact, tp_contact); + + return retval; +} + +typedef struct +{ + TplEntity *entity; + TpAccount *account; +} FindContactData; + +static gboolean +contact_is_tpl_entity (gpointer key, + gpointer value, + gpointer user_data) +{ + EmpathyContact *contact = value; + FindContactData *data = user_data; + + return !tp_strdiff (empathy_contact_get_id (contact), + tpl_entity_get_identifier (data->entity)) && + !tp_strdiff (tp_proxy_get_object_path (data->account), + tp_proxy_get_object_path ( + empathy_contact_get_account (contact))); } EmpathyContact * @@ -647,17 +679,49 @@ empathy_contact_from_tpl_contact (TpAccount *account, { EmpathyContact *retval; gboolean is_user; + EmpathyContact *existing_contact = NULL; g_return_val_if_fail (TPL_IS_ENTITY (tpl_entity), NULL); - is_user = (TPL_ENTITY_SELF == tpl_entity_get_entity_type (tpl_entity)); + if (contacts_table != NULL) + { + FindContactData data; - retval = g_object_new (EMPATHY_TYPE_CONTACT, - "id", tpl_entity_get_identifier (tpl_entity), - "alias", tpl_entity_get_alias (tpl_entity), - "account", account, - "is-user", is_user, - NULL); + data.entity = tpl_entity; + data.account = account; + + existing_contact = g_hash_table_find (contacts_table, + contact_is_tpl_entity, &data); + } + + if (existing_contact != NULL) + { + EmpathyContactPriv *priv; + + retval = g_object_new (EMPATHY_TYPE_CONTACT, + "tp-contact", empathy_contact_get_tp_contact (existing_contact), + NULL); + + priv = GET_PRIV (retval); + + /* contact_set_property() calls empathy_contact_set_alias(), which + * tries to set the alias on the FolksPersona, but we don't want to + * do that when creating an EmpathyContact from a TplEntity. So just + * set priv->alias instead of passing it to g_object_new() instead. */ + g_free (priv->alias); + priv->alias = g_strdup (tpl_entity_get_alias (tpl_entity)); + } + else + { + is_user = (TPL_ENTITY_SELF == tpl_entity_get_entity_type (tpl_entity)); + + retval = g_object_new (EMPATHY_TYPE_CONTACT, + "id", tpl_entity_get_identifier (tpl_entity), + "alias", tpl_entity_get_alias (tpl_entity), + "account", account, + "is-user", is_user, + NULL); + } if (!EMP_STR_EMPTY (tpl_entity_get_avatar_token (tpl_entity))) contact_load_avatar_cache (retval, @@ -697,16 +761,16 @@ const gchar * empathy_contact_get_alias (EmpathyContact *contact) { EmpathyContactPriv *priv; - const gchar *alias; + const gchar *alias = NULL; g_return_val_if_fail (EMPATHY_IS_CONTACT (contact), NULL); priv = GET_PRIV (contact); - if (priv->tp_contact != NULL) - alias = tp_contact_get_alias (priv->tp_contact); - else + if (!EMP_STR_EMPTY (priv->alias)) alias = priv->alias; + else if (priv->tp_contact != NULL) + alias = tp_contact_get_alias (priv->tp_contact); if (!EMP_STR_EMPTY (alias)) return alias; diff --git a/libempathy/empathy-message.c b/libempathy/empathy-message.c index 25ec498ce..d30ce3645 100644 --- a/libempathy/empathy-message.c +++ b/libempathy/empathy-message.c @@ -26,6 +26,8 @@ #include <string.h> +#include <glib/gi18n-lib.h> + #include <telepathy-glib/util.h> #include <telepathy-glib/account.h> #include <telepathy-glib/account-manager.h> @@ -33,6 +35,9 @@ #include <telepathy-logger/entity.h> #include <telepathy-logger/event.h> #include <telepathy-logger/text-event.h> +#ifdef HAVE_CALL_LOGS +# include <telepathy-logger/call-event.h> +#endif #include "empathy-message.h" #include "empathy-utils.h" @@ -304,6 +309,7 @@ empathy_message_from_tpl_log_event (TplEvent *logevent) TplEntity *sender = NULL; gchar *body= NULL; EmpathyContact *contact; + TpChannelTextMessageType type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL; g_return_val_if_fail (TPL_IS_EVENT (logevent), NULL); @@ -323,24 +329,36 @@ empathy_message_from_tpl_log_event (TplEvent *logevent) tpl_event_get_account_path (logevent)); g_object_unref (acc_man); - /* TODO Currently only TplTextEvent exists as subclass of TplEvent, in - * future more TplEvent will exist and EmpathyMessage should probably - * be enhanced to support other types of log entries (ie TplCallEvent). - * - * For now we just check (simply) that we are dealing with the only supported type, - * then there will be a if/then/else or switch handling all the supported - * cases. - */ - if (!TPL_IS_TEXT_EVENT (logevent)) + if (TPL_IS_TEXT_EVENT (logevent)) { + body = g_strdup (tpl_text_event_get_message ( + TPL_TEXT_EVENT (logevent))); + + type = tpl_text_event_get_message_type (TPL_TEXT_EVENT (logevent)); + } +#ifdef HAVE_CALL_LOGS + else if (TPL_IS_CALL_EVENT (logevent)) { + TplCallEvent *call = TPL_CALL_EVENT (logevent); + if (tpl_call_event_get_end_reason (call) == TPL_CALL_END_REASON_NO_ANSWER) + body = g_strdup_printf (_("Missed call from %s"), + tpl_entity_get_alias (tpl_event_get_sender (logevent))); + else if (tpl_entity_get_entity_type (tpl_event_get_sender (logevent)) == TPL_ENTITY_SELF) + body = g_strdup_printf (_("Called %s"), + tpl_entity_get_alias (tpl_event_get_receiver (logevent))); + else + body = g_strdup_printf (_("Call from %s"), + tpl_entity_get_alias (tpl_event_get_sender (logevent))); + } +#endif + else { + /* Unknown event type */ return NULL; + } - body = g_strdup (tpl_text_event_get_message ( - TPL_TEXT_EVENT (logevent))); receiver = tpl_event_get_receiver (logevent); sender = tpl_event_get_sender (logevent); retval = g_object_new (EMPATHY_TYPE_MESSAGE, - "type", tpl_text_event_get_message_type (TPL_TEXT_EVENT (logevent)), + "type", type, "body", body, "is-backlog", TRUE, "timestamp", tpl_event_get_timestamp (logevent), |