time_t start_time;
gchar *unix_socket_path;
GCancellable *cancellable;
+ gboolean keep_alive;
};
enum {
tp_file->priv = priv;
}
+static void
+tp_file_check_keep_alive (EmpathyTpFile *tp_file)
+{
+ if (tp_file->priv->keep_alive &&
+ (tp_file->priv->state == EMP_FILE_TRANSFER_STATE_COMPLETED ||
+ tp_file->priv->state == EMP_FILE_TRANSFER_STATE_CANCELLED))
+ {
+ tp_file->priv->keep_alive = FALSE;
+ g_object_unref (tp_file);
+ }
+}
+
static void
tp_file_invalidated_cb (TpProxy *proxy,
guint domain,
EMP_FILE_TRANSFER_STATE_CHANGE_REASON_LOCAL_ERROR;
g_object_notify (G_OBJECT (tp_file), "state");
}
+
+ tp_file_check_keep_alive (tp_file);
}
static void
tp_file_finalize (GObject *object)
{
- EmpathyTpFile *tp_file;
-
- tp_file = EMPATHY_TP_FILE (object);
+ EmpathyTpFile *tp_file = EMPATHY_TP_FILE (object);
if (tp_file->priv->channel)
{
tp_file->priv->state_change_reason = reason;
g_object_notify (G_OBJECT (tp_file), "state");
+ tp_file_check_keep_alive (tp_file);
}
static void
};
}
+static GHashTable *ft_table = NULL;
+
+static void
+tp_file_weak_notify_cb (gpointer channel,
+ GObject *tp_file)
+{
+ g_hash_table_remove (ft_table, channel);
+}
+
/**
* empathy_tp_file_new:
* @channel: a Telepathy channel
*
- * Creates a new #EmpathyTpFile wrapping @channel.
+ * Creates a new #EmpathyTpFile wrapping @channel, or return a new ref to an
+ * existing #EmpathyTpFile for that channel.
*
* Returns: a new #EmpathyTpFile
*/
EmpathyTpFile *
empathy_tp_file_new (TpChannel *channel)
{
+ EmpathyTpFile *tp_file;
+
g_return_val_if_fail (TP_IS_CHANNEL (channel), NULL);
- return g_object_new (EMPATHY_TYPE_TP_FILE,
+ if (ft_table != NULL)
+ {
+ tp_file = g_hash_table_lookup (ft_table, channel);
+ if (tp_file != NULL) {
+ return g_object_ref (tp_file);
+ }
+ }
+ else
+ ft_table = g_hash_table_new_full (empathy_proxy_hash,
+ empathy_proxy_equal, (GDestroyNotify) g_object_unref, NULL);
+
+ tp_file = g_object_new (EMPATHY_TYPE_TP_FILE,
"channel", channel,
NULL);
+
+ g_hash_table_insert (ft_table, g_object_ref (channel), tp_file);
+ g_object_weak_ref (G_OBJECT (tp_file), tp_file_weak_notify_cb, channel);
+
+ return tp_file;
}
/**
¬hing, tp_file_method_cb, NULL, NULL, G_OBJECT (tp_file));
}
+/**
+ * empathy_tp_file_keep_alive:
+ * @tp_file: an #EmpathyTpFile
+ *
+ * Keep @tp_file alive until the file transfer is COMPLETED or CANCELLED, by
+ * adding a temporary reference.
+ */
+void
+empathy_tp_file_keep_alive (EmpathyTpFile *tp_file)
+{
+ g_return_if_fail (EMPATHY_IS_TP_FILE (tp_file));
+
+ if (tp_file->priv->keep_alive)
+ return;
+
+ tp_file->priv->keep_alive = TRUE;
+ if (tp_file->priv->state != EMP_FILE_TRANSFER_STATE_COMPLETED &&
+ tp_file->priv->state != EMP_FILE_TRANSFER_STATE_CANCELLED)
+ g_object_ref (tp_file);
+}
+
EmpathyContact *
empathy_tp_file_get_contact (EmpathyTpFile *tp_file)
{
/* I can abort if the transfer is not already finished */
abort_enabled = (state != EMP_FILE_TRANSFER_STATE_CANCELLED &&
state != EMP_FILE_TRANSFER_STATE_COMPLETED);
+
+ g_object_unref (tp_file);
}
gtk_widget_set_sensitive (ft_manager->priv->open_button, open_enabled);
}
static void
-ft_manager_remove_file_from_list (EmpathyFTManager *ft_manager,
+ft_manager_remove_file_from_model (EmpathyFTManager *ft_manager,
EmpathyTpFile *tp_file)
{
GtkTreeRowReference *row_ref;
else
empty = TRUE;
}
- g_object_unref (tp_file);
/* Select the next row */
if (!empty)
if (state == EMP_FILE_TRANSFER_STATE_COMPLETED ||
state == EMP_FILE_TRANSFER_STATE_CANCELLED)
{
- ft_manager_remove_file_from_list (self, tp_file);
+ ft_manager_remove_file_from_model (self, tp_file);
return TRUE;
}
ft_manager->priv->model), path);
gtk_tree_path_free (path);
- g_object_ref (tp_file);
- g_hash_table_insert (ft_manager->priv->tp_file_to_row_ref, tp_file,
- row_ref);
+ g_hash_table_insert (ft_manager->priv->tp_file_to_row_ref,
+ g_object_ref (tp_file), row_ref);
ft_manager_update_ft_row (ft_manager, tp_file);
uri = g_object_get_data (G_OBJECT (tp_file), "uri");
DEBUG ("Opening URI: %s", uri);
empathy_url_show (uri);
+ g_object_unref (tp_file);
}
static void
empathy_tp_file_get_filename (tp_file));
empathy_tp_file_cancel (tp_file);
+ g_object_unref (tp_file);
}
static void
ft_manager->priv = priv;
priv->tp_file_to_row_ref = g_hash_table_new_full (g_direct_hash,
- g_direct_equal, NULL, (GDestroyNotify) gtk_tree_row_reference_free);
+ g_direct_equal, (GDestroyNotify) g_object_unref,
+ (GDestroyNotify) gtk_tree_row_reference_free);
ft_manager_build_ui (ft_manager);
}