static gchar *
get_provider_name (GoaProvider *provider,
                   GoaObject   *object)
{
  GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (provider)->priv;

  return g_strdup (tpaw_protocol_name_to_display_name (priv->protocol_name));
}
static void
goa_telepathy_provider_finalize (GObject *object)
{
  GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (object)->priv;

  g_clear_object (&priv->protocol);
  g_free (priv->protocol_name);
  g_free (priv->provider_type);

  (G_OBJECT_CLASS (goa_telepathy_provider_parent_class)->finalize) (object);
}
static gboolean
remove_account_finish (GoaProvider   *provider,
                       GAsyncResult  *res,
                       GError       **error)
{
  GoaTelepathyProvider *self = GOA_TELEPATHY_PROVIDER (provider);
  GTask *task;

  g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
  task = G_TASK (res);

  g_return_val_if_fail (g_task_get_source_tag (task) == remove_account, FALSE);

  return g_task_propagate_boolean (task, error);
}
static void
goa_telepathy_provider_set_property (GObject *object,
                                     guint property_id,
                                     const GValue *value,
                                     GParamSpec *pspec)
{
    GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (object)->priv;

    switch (property_id) {
    case PROP_PROTOCOL:
        priv->protocol = g_value_dup_object (value);
        break;
    case PROP_PROTOCOL_NAME:
        priv->protocol_name = g_value_dup_string (value);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
        break;
    }
}
static GIcon *
get_provider_icon (GoaProvider *provider,
                   GoaObject   *object)
{
  GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (provider)->priv;
  gchar *icon_name;
  gchar *icon_names[3];
  GIcon *icon;

  /* Use symbolic icons for generic protocols. Use icons for the
   * branded ones if it matches their visual identity. Otherwise do
   * not use an icon.
   */
  if (g_strcmp0 (priv->protocol_name, "irc") == 0
      || g_strcmp0 (priv->protocol_name, "jabber") == 0
      || g_strcmp0 (priv->protocol_name, "local-xmpp") == 0
      || g_strcmp0 (priv->protocol_name, "sip") == 0)
    {
      icon_name = g_strdup ("user-available-symbolic");
    }
  else if (g_strcmp0 (priv->protocol_name, "aim") == 0
           || g_strcmp0 (priv->protocol_name, "gadugadu") == 0
           || g_strcmp0 (priv->protocol_name, "silc") == 0)
    {
      icon_name = tpaw_protocol_icon_name (priv->protocol_name);
    }
  else
    {
      icon_name = g_strdup ("goa-account");
    }

  icon_names[0] = icon_name;
  /* If the icon doesn't exist, just try with the default icon. */
  icon_names[1] = "goa-account";
  icon_names[2] = NULL;
  icon = g_themed_icon_new_from_names (icon_names, -1);

  g_free (icon_name);

  return icon;
}
static void
remove_account (GoaProvider          *provider,
                GoaObject            *object,
                GCancellable         *cancellable,
                GAsyncReadyCallback   callback,
                gpointer              user_data)
{
  GoaTelepathyProvider *self = GOA_TELEPATHY_PROVIDER (provider);
  GTask *task;

  task = g_task_new (self, cancellable, callback, user_data);
  g_task_set_source_tag (task, remove_account);

  goa_tp_account_linker_remove_tp_account (tp_linker,
                                           object,
                                           cancellable,
                                           remove_account_remove_tp_account_cb,
                                           g_object_ref (task));

  g_object_unref (task);
}
static void
goa_telepathy_provider_constructed (GObject *object)
{
  GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (object)->priv;

  G_OBJECT_CLASS (goa_telepathy_provider_parent_class)->constructed (object);

  if (priv->protocol != NULL)
    {
      if (priv->protocol_name != NULL)
        g_error ("You cannot set \"protocol-name\" if you set \"protocol\"");
      priv->protocol_name = g_strdup (tpaw_protocol_get_protocol_name (priv->protocol));
    }
  else
    {
      if (priv->protocol_name == NULL)
        g_error ("You must set \"protocol-name\" or \"protocol\" on GoaTelepathyProvider");
    }

  priv->provider_type = g_strdup_printf ("%s/%s",
      GOA_TELEPATHY_NAME, priv->protocol_name);
}
static GoaObject *
add_account (GoaProvider  *provider,
             GoaClient    *client,
             GtkDialog    *dialog,
             GtkBox       *vbox,
             GError      **error)
{
  GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (provider)->priv;
  AddAccountData data;
  TpawAccountSettings *settings = NULL;
  TpawAccountWidget *account_widget = NULL;
  GtkRequisition req;
  gint response;

  settings = tpaw_protocol_create_account_settings (priv->protocol);
  if (settings == NULL)
    {
      g_set_error (&data.error,
                   GOA_ERROR,
                   GOA_ERROR_FAILED,
                   _("Failed to create a user interface for %s"),
                   priv->protocol != NULL ?
                      tpaw_protocol_get_protocol_name (priv->protocol) :
                      "(null)");
      return NULL;
    }

  memset (&data, 0, sizeof (AddAccountData));
  data.cancellable = g_cancellable_new ();
  data.loop = g_main_loop_new (NULL, FALSE);
  data.error = NULL;
  data.provider = GOA_TELEPATHY_PROVIDER (provider);
  data.dialog = dialog;
  data.vbox = vbox;

  goa_client_new (data.cancellable, goa_client_new_cb, &data);
  wait_for_account_settings_ready (settings, data.loop);

  account_widget = tpaw_account_widget_new_for_protocol (settings,
      dialog, TRUE);
  gtk_box_pack_start (GTK_BOX (vbox), GTK_WIDGET (account_widget), FALSE, FALSE, 0);
  gtk_widget_show (GTK_WIDGET (account_widget));
  g_signal_connect (account_widget, "account-created",
      G_CALLBACK (tp_account_created_cb), &data);
  g_signal_connect (account_widget, "close",
      G_CALLBACK (account_widget_close_cb), &data);

  /* The dialog now contains a lot of empty space between the account widget
   * and the buttons. We force it's vertical size to be just right to fit the
   * widget. */
  gtk_widget_get_preferred_size (GTK_WIDGET (dialog), NULL, &req);
  gtk_widget_set_size_request (GTK_WIDGET (dialog), req.width, 1);

  response = gtk_dialog_run (GTK_DIALOG (dialog));
  if (response != GTK_RESPONSE_OK && response != GTK_RESPONSE_APPLY)
    {
      g_set_error (&data.error,
                   GOA_ERROR,
                   GOA_ERROR_DIALOG_DISMISSED,
                   _("Dialog was dismissed"));
      goto out;
    }

  if (data.error != NULL)
    {
      /* An error could have been set by a callback */
      goto out;
    }

  if (data.ret == NULL && !g_cancellable_is_cancelled (data.cancellable))
    {
      /* We wait for the account to be created */
      g_main_loop_run (data.loop);
    }

out:
  if (data.error != NULL)
    g_propagate_error (error, data.error);
  else
    g_assert (data.ret != NULL);

  if (data.cancellable != NULL)
    {
      g_cancellable_cancel (data.cancellable);
      g_object_unref (data.cancellable);
    }

  if (data.goa_account_added_id)
    g_signal_handler_disconnect (data.goa_client, data.goa_account_added_id);

  g_clear_pointer (&data.loop, g_main_loop_unref);
  g_clear_object (&data.goa_client);
  g_clear_object (&data.tp_account);

  return data.ret;
}
static const gchar *
get_provider_type (GoaProvider *provider)
{
  GoaTelepathyProviderPrivate *priv = GOA_TELEPATHY_PROVIDER (provider)->priv;
  return priv->provider_type;
}