talkatu/talkatu

Parents 4e2c0fb2c676
Children 97a4fcd3ba67
Remove contents from attachments and instead use local and remote uris
--- a/talkatu/talkatuattachment.c Wed Feb 05 00:45:30 2020 -0600
+++ b/talkatu/talkatuattachment.c Thu Feb 06 23:07:39 2020 -0600
@@ -1,6 +1,6 @@
/*
* talkatu
- * Copyright (C) 2017-2019 Gary Kramlich <grim@reaperworld.com>
+ * Copyright (C) 2017-2020 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -45,10 +45,12 @@
GObject parent;
guint64 id;
+ gchar *content_type;
- gchar *content_type;
- gchar *filename;
- GBytes *contents;
+ gchar *local_uri;
+ gchar *remote_uri;
+
+ guint64 size;
GdkPixbuf *preview;
gboolean preview_ready;
@@ -60,8 +62,9 @@
PROP_0 = 0,
PROP_ID,
PROP_CONTENT_TYPE,
- PROP_FILENAME,
- PROP_CONTENTS,
+ PROP_LOCAL_URI,
+ PROP_REMOTE_URI,
+ PROP_SIZE,
N_PROPERTIES,
};
static GParamSpec *properties[N_PROPERTIES];
@@ -70,16 +73,13 @@
* Private Setters
*****************************************************************************/
static void
-talkatu_attachment_set_id(TalkatuAttachment *attachment, guint64 id) {
- attachment->id = id;
-
- g_object_notify_by_pspec(G_OBJECT(attachment), properties[PROP_ID]);
-}
-
-static void
talkatu_attachment_set_content_type(TalkatuAttachment *attachment,
const gchar *content_type)
{
+ if(attachment->content_type == content_type) {
+ return;
+ }
+
g_clear_pointer(&attachment->content_type, g_free);
attachment->content_type = g_strdup(content_type);
@@ -88,31 +88,6 @@
properties[PROP_CONTENT_TYPE]);
}
-static void
-talkatu_attachment_set_filename(TalkatuAttachment *attachment,
- const gchar *filename)
-{
- g_clear_pointer(&attachment->filename, g_free);
-
- attachment->filename = g_strdup(filename);
-
- g_object_notify_by_pspec(G_OBJECT(attachment),
- properties[PROP_FILENAME]);
-}
-
-static void
-talkatu_attachment_set_contents(TalkatuAttachment *attachment,
- GBytes *contents)
-{
- g_clear_pointer(&attachment->contents, g_bytes_unref);
-
- if(contents != NULL) {
- attachment->contents = g_bytes_ref(contents);
- }
-
- g_object_notify_by_pspec(G_OBJECT(attachment), properties[PROP_CONTENTS]);
-}
-
/******************************************************************************
* GObject Implementation
*****************************************************************************/
@@ -127,11 +102,14 @@
case PROP_CONTENT_TYPE:
g_value_set_string(value, talkatu_attachment_get_content_type(attachment));
break;
- case PROP_FILENAME:
- g_value_set_string(value, talkatu_attachment_get_filename(attachment));
+ case PROP_LOCAL_URI:
+ g_value_set_string(value, talkatu_attachment_get_local_uri(attachment));
break;
- case PROP_CONTENTS:
- g_value_set_boxed(value, talkatu_attachment_get_contents(attachment));
+ case PROP_REMOTE_URI:
+ g_value_set_string(value, talkatu_attachment_get_remote_uri(attachment));
+ break;
+ case PROP_SIZE:
+ g_value_set_uint64(value, talkatu_attachment_get_size(attachment));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
@@ -150,11 +128,14 @@
case PROP_CONTENT_TYPE:
talkatu_attachment_set_content_type(attachment, g_value_get_string(value));
break;
- case PROP_FILENAME:
- talkatu_attachment_set_filename(attachment, g_value_get_string(value));
+ case PROP_LOCAL_URI:
+ talkatu_attachment_set_local_uri(attachment, g_value_get_string(value));
break;
- case PROP_CONTENTS:
- talkatu_attachment_set_contents(attachment, g_value_get_boxed(value));
+ case PROP_REMOTE_URI:
+ talkatu_attachment_set_remote_uri(attachment, g_value_get_string(value));
+ break;
+ case PROP_SIZE:
+ talkatu_attachment_set_size(attachment, g_value_get_uint64(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
@@ -167,8 +148,8 @@
TalkatuAttachment *attachment = TALKATU_ATTACHMENT(obj);
g_clear_pointer(&attachment->content_type, g_free);
- g_clear_pointer(&attachment->filename, g_free);
- g_clear_pointer(&attachment->contents, g_bytes_unref);
+ g_clear_pointer(&attachment->local_uri, g_free);
+ g_clear_pointer(&attachment->remote_uri, g_free);
g_clear_object(&attachment->preview);
G_OBJECT_CLASS(talkatu_attachment_parent_class)->finalize(obj);
@@ -190,7 +171,7 @@
properties[PROP_ID] = g_param_spec_uint64(
"id", "id", "The identifier of the attachment",
0, G_MAXUINT64, 0,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS
);
properties[PROP_CONTENT_TYPE] = g_param_spec_string(
@@ -199,16 +180,22 @@
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS
);
- properties[PROP_FILENAME] = g_param_spec_string(
- "filename", "filename", "The filename of the attachment",
- "unknown",
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS
+ properties[PROP_LOCAL_URI] = g_param_spec_string(
+ "local-uri", "local-uri", "The local URI of the attachment",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS
);
- properties[PROP_CONTENTS] = g_param_spec_boxed(
- "contents", "contents", "The contents stored in a GBytes",
- G_TYPE_BYTES,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS
+ properties[PROP_REMOTE_URI] = g_param_spec_string(
+ "remote-uri", "remote-uri", "The remote URI of the attachment",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS
+ );
+
+ properties[PROP_SIZE] = g_param_spec_uint64(
+ "size", "size", "The file size of the attachment in bytes",
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS
);
g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
@@ -222,75 +209,24 @@
* talkatu_attachment_new:
* @id: The identifier of the attachment.
* @content_type: The content type of the attachment.
- * @filename: The filename of the attachment.
- * @contents: A #GBytes that contains the data of the attachment.
*
- * Creates a new attachment with @content_type and @contents.
+ * Creates a new attachment with @content_type.
*
* Returns: (transfer full): The new #TalkatuAttachment.
*/
TalkatuAttachment *
-talkatu_attachment_new(guint64 id, const gchar *content_type,
- const gchar *filename, GBytes *contents)
-{
+talkatu_attachment_new(guint64 id, const gchar *content_type) {
g_return_val_if_fail(content_type != NULL, NULL);
- g_return_val_if_fail(filename != NULL, NULL);
- g_return_val_if_fail(contents != NULL, NULL);
return TALKATU_ATTACHMENT(g_object_new(
TALKATU_TYPE_ATTACHMENT,
"id", id,
"content-type", content_type,
- "filename", filename,
- "contents", contents,
NULL
));
}
/**
- * talkatu_attachment_new_from_pixbuf:
- * @id: The identifier of the attachment.
- * @filename: The filename of the attachment.
- * @pixbuf: The #GdkPixbuf to create an attachment for.
- *
- * Creates a new #TalkatuAttachment containing @pixbuf.
- *
- * Returns: (transfer full): The new #TalkatuAttachment.
- */
-TalkatuAttachment *
-talkatu_attachment_new_from_pixbuf(guint64 id, const gchar *filename,
- GdkPixbuf *pixbuf)
-{
- TalkatuAttachment *attachment = NULL;
- GBytes *contents = NULL;
- GError *error = NULL;
- gchar *data = NULL;
- gsize data_sz;
-
- g_return_val_if_fail(filename != NULL, NULL);
- g_return_val_if_fail(GDK_IS_PIXBUF(pixbuf), NULL);
-
- if(!gdk_pixbuf_save_to_buffer(pixbuf, &data, &data_sz, "png", &error, NULL)) {
- g_warning(_("Failed to convert the pixbuf to a png image: %s"),
- error->message ? error->message : _("unknown error"));
-
- return NULL;
- }
-
- /* TODO: adjust filename for the forced png format since we don't know the
- * original format of the image.
- */
-
- contents = g_bytes_new_take(data, data_sz);
-
- attachment = talkatu_attachment_new(id, "image/png", filename, contents);
-
- g_bytes_unref(contents);
-
- return attachment;
-}
-
-/**
* talkatu_attachment_get_id:
* @attachment: The #TalkatuAttachment instance.
*
@@ -323,6 +259,26 @@
}
/**
+ * talkatu_attachment_set_id:
+ * @attachment: The #TalkatuAttachment instance.
+ * @id: The new ID for @attachment.
+ *
+ * Sets the ID of @attachment to @id.
+ */
+void
+talkatu_attachment_set_id(TalkatuAttachment *attachment, guint64 id) {
+ g_return_if_fail(TALKATU_IS_ATTACHMENT(attachment));
+
+ if(attachment->id == id) {
+ return;
+ }
+
+ attachment->id = id;
+
+ g_object_notify_by_pspec(G_OBJECT(attachment), properties[PROP_ID]);
+}
+
+/**
* talkatu_attachment_get_content_type:
* @attachment: The #TalkatuAttachment instance.
*
@@ -338,18 +294,90 @@
}
/**
- * talkatu_attachment_get_filename:
+ * talkatu_attachment_get_local_uri:
* @attachment: The #TalkatuAttachment instance.
*
- * Returns the filename of the attachment.
+ * Get's the local URI if any for @attachment.
*
- * Returns: The filename of @attachment.
+ * Returns: (nullable): The local URI for @attachment.
*/
const gchar *
-talkatu_attachment_get_filename(TalkatuAttachment *attachment) {
+talkatu_attachment_get_local_uri(TalkatuAttachment *attachment) {
g_return_val_if_fail(TALKATU_IS_ATTACHMENT(attachment), NULL);
- return attachment->filename;
+ return attachment->local_uri;
+}
+
+/**
+ * talkatu_attachment_set_local_uri:
+ * @attachment: The #TalkatuAttachment instance.
+ * @local_uri: The new local URI.
+ *
+ * Sets the local URI of @attachment.
+ */
+void
+talkatu_attachment_set_local_uri(TalkatuAttachment *attachment,
+ const gchar *local_uri)
+{
+ g_return_if_fail(TALKATU_IS_ATTACHMENT(attachment));
+
+ if(attachment->local_uri == local_uri) {
+ return;
+ }
+
+ g_free(attachment->local_uri);
+
+ if(local_uri != NULL) {
+ gchar *scheme = g_uri_parse_scheme(local_uri);
+ if(scheme == NULL) {
+ attachment->local_uri = g_filename_to_uri(local_uri, NULL, NULL);
+ } else {
+ g_free(scheme);
+ attachment->local_uri = g_strdup(local_uri);
+ }
+ } else {
+ attachment->local_uri = NULL;
+ }
+
+ g_object_notify_by_pspec(G_OBJECT(attachment), properties[PROP_LOCAL_URI]);
+}
+
+/**
+ * talkatu_attachment_get_remote_uri:
+ * @attachment: The #TalkatuAttachment instance.
+ *
+ * Get's the remote URI if any for @attachment.
+ *
+ * Returns: (nullable): The remote URI for @attachment.
+ */
+const gchar *
+talkatu_attachment_get_remote_uri(TalkatuAttachment *attachment) {
+ g_return_val_if_fail(TALKATU_IS_ATTACHMENT(attachment), NULL);
+
+ return attachment->remote_uri;
+}
+
+/**
+ * talkatu_attachment_set_remote_uri:
+ * @attachment: The #TalkatuAttachment instance.
+ * @remote_uri: The new remote URI.
+ *
+ * Sets the remote URI of @attachment.
+ */
+void
+talkatu_attachment_set_remote_uri(TalkatuAttachment *attachment,
+ const gchar *remote_uri)
+{
+ g_return_if_fail(TALKATU_IS_ATTACHMENT(attachment));
+
+ if(attachment->remote_uri == remote_uri) {
+ return;
+ }
+
+ g_free(attachment->remote_uri);
+ attachment->remote_uri = g_strdup(remote_uri);
+
+ g_object_notify_by_pspec(G_OBJECT(attachment), properties[PROP_REMOTE_URI]);
}
/**
@@ -360,37 +388,62 @@
*
* Returns: The size of @attachment.
*/
-gsize
+guint64
talkatu_attachment_get_size(TalkatuAttachment *attachment) {
g_return_val_if_fail(TALKATU_IS_ATTACHMENT(attachment), -1);
- return g_bytes_get_size(attachment->contents);
+ return attachment->size;
+}
+
+/**
+ * talkatu_attachment_set_size:
+ * @attachment: The #TalkatuAttachment instance.
+ * @size: The new size of @attachment.
+ *
+ * Sets the size of @attachment to @size.
+ */
+void
+talkatu_attachment_set_size(TalkatuAttachment *attachment, guint64 size) {
+ g_return_if_fail(TALKATU_IS_ATTACHMENT(attachment));
+
+ attachment->size = size;
+
+ g_object_notify_by_pspec(G_OBJECT(attachment), properties[PROP_SIZE]);
}
/**
- * talkatu_attachment_get_contents:
+ * talkatu_attachment_get_filename:
* @attachment: The #TalkatuAttachment instance.
*
- * Returns a new reference to the contents of @attachment.
+ * Gets the base filename for @attachment. Remote URI will be check before
+ * local URI, but the basename of one of those is what will be returned.
*
- * Returns: (transfer full): The contents of @attachment.
+ * Returns: (transfer full): The filename for @attachment.
*/
-GBytes *
-talkatu_attachment_get_contents(TalkatuAttachment *attachment) {
+gchar *
+talkatu_attachment_get_filename(TalkatuAttachment *attachment) {
g_return_val_if_fail(TALKATU_IS_ATTACHMENT(attachment), NULL);
- if(attachment->contents != NULL) {
- return g_bytes_ref(attachment->contents);
+ if(attachment->remote_uri != NULL &&
+ g_utf8_strlen(attachment->remote_uri, -1) > 0)
+ {
+ return g_path_get_basename(attachment->remote_uri);
}
- return NULL;
+ if(attachment->local_uri != NULL &&
+ g_utf8_strlen(attachment->local_uri, -1) > 0)
+ {
+ return g_path_get_basename(attachment->local_uri);
+ }
+
+ return g_strdup("unknown");
}
/**
* talkatu_attachment_get_preview:
* @attachment: The #TalkatuAttachment instance.
*
- * Create a #GdkPixbuf as a preview for @attachment.
+ * Create a #GIcon as a preview for @attachment.
*
* Returns: (transfer full): A preview image of @attachment.
*/
@@ -401,7 +454,7 @@
g_return_val_if_fail(TALKATU_IS_ATTACHMENT(attachment), NULL);
if(g_str_has_prefix(attachment->content_type, "image/")) {
- return g_bytes_icon_new(attachment->contents);
+ name = "image-x-generic";
} else if(g_str_has_prefix(attachment->content_type, "text/")) {
name = "text-x-generic";
} else if(g_str_has_prefix(attachment->content_type, "audio/")) {
--- a/talkatu/talkatuattachment.h Wed Feb 05 00:45:30 2020 -0600
+++ b/talkatu/talkatuattachment.h Thu Feb 06 23:07:39 2020 -0600
@@ -1,6 +1,6 @@
/*
* talkatu
- * Copyright (C) 2017-2019 Gary Kramlich <grim@reaperworld.com>
+ * Copyright (C) 2017-2020 Gary Kramlich <grim@reaperworld.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -33,16 +33,24 @@
typedef void (*TalkatuAttachmentForeachFunc)(TalkatuAttachment *attachment, gpointer data);
-TalkatuAttachment *talkatu_attachment_new(guint64 id, const gchar *content_type, const gchar *filename, GBytes *contents);
-TalkatuAttachment *talkatu_attachment_new_from_pixbuf(guint64 id, const gchar *filename, GdkPixbuf *pixbuf);
+TalkatuAttachment *talkatu_attachment_new(guint64 id, const gchar *content_type);
guint64 talkatu_attachment_get_id(TalkatuAttachment *attachment);
guint64 *talkatu_attachment_get_hash_key(TalkatuAttachment *attachment);
+void talkatu_attachment_set_id(TalkatuAttachment *attachment, guint64 id);
const gchar *talkatu_attachment_get_content_type(TalkatuAttachment *attachment);
-const gchar *talkatu_attachment_get_filename(TalkatuAttachment *attachment);
+
+const gchar *talkatu_attachment_get_local_uri(TalkatuAttachment *attachment);
+void talkatu_attachment_set_local_uri(TalkatuAttachment *attachment, const gchar *local_uri);
+
+const gchar *talkatu_attachment_get_remote_uri(TalkatuAttachment *attachment);
+void talkatu_attachment_set_remote_uri(TalkatuAttachment *attachment, const gchar *remote_uri);
+
gsize talkatu_attachment_get_size(TalkatuAttachment *attachment);
-GBytes *talkatu_attachment_get_contents(TalkatuAttachment *attachment);
+void talkatu_attachment_set_size(TalkatuAttachment *attachment, gsize size);
+
+gchar *talkatu_attachment_get_filename(TalkatuAttachment *attachment);
GIcon *talkatu_attachment_get_preview(TalkatuAttachment *attachment);
--- a/talkatu/talkatuattachmentdialog.c Wed Feb 05 00:45:30 2020 -0600
+++ b/talkatu/talkatuattachmentdialog.c Thu Feb 06 23:07:39 2020 -0600
@@ -70,6 +70,7 @@
if(TALKATU_IS_ATTACHMENT(attachment)) {
GIcon *preview = talkatu_attachment_get_preview(attachment);
+ gchar *filename = NULL;
if(G_IS_ICON(preview)) {
gtk_image_set_from_gicon(GTK_IMAGE(dialog->preview), preview,
@@ -77,8 +78,9 @@
g_object_unref(G_OBJECT(preview));
}
- gtk_label_set_text(GTK_LABEL(dialog->filename),
- talkatu_attachment_get_filename(attachment));
+ filename = talkatu_attachment_get_filename(attachment);
+ gtk_label_set_text(GTK_LABEL(dialog->filename), filename);
+ g_free(filename);
}
}
}
--- a/talkatu/talkatuattachmentpreview.c Wed Feb 05 00:45:30 2020 -0600
+++ b/talkatu/talkatuattachmentpreview.c Thu Feb 06 23:07:39 2020 -0600
@@ -75,6 +75,7 @@
if(g_set_object(&preview->attachment, attachment)) {
if(TALKATU_IS_ATTACHMENT(attachment)) {
GIcon *icon = talkatu_attachment_get_preview(attachment);
+ gchar *filename = NULL;
gchar *filesize = NULL;
if(G_IS_ICON(icon)) {
@@ -83,8 +84,9 @@
g_object_unref(G_OBJECT(icon));
}
- gtk_label_set_text(GTK_LABEL(preview->filename),
- talkatu_attachment_get_filename(preview->attachment));
+ filename = talkatu_attachment_get_filename(preview->attachment);
+ gtk_label_set_text(GTK_LABEL(preview->filename), filename);
+ g_free(filename);
filesize = g_format_size(talkatu_attachment_get_size(preview->attachment));
gtk_label_set_text(GTK_LABEL(preview->filesize), filesize);
--- a/talkatu/talkatuinput.c Wed Feb 05 00:45:30 2020 -0600
+++ b/talkatu/talkatuinput.c Thu Feb 06 23:07:39 2020 -0600
@@ -15,7 +15,9 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
+#include <glib.h>
#include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
#include <gspell/gspell.h>
@@ -424,22 +426,73 @@
gpointer data)
{
TalkatuAttachment *attachment = NULL;
+ GFile *file = NULL;
+ GFileInfo *info = NULL;
+ GFileIOStream *stream = NULL;
+ GOutputStream *ostream = NULL;
GtkWidget *dialog = NULL, *input = NULL;
GtkTextBuffer *buffer = NULL;
- gchar *comment = NULL;
+ GError *error = NULL;
+ gchar *comment = NULL, *filename = NULL;
+ gboolean saved = FALSE;
+ guint64 size;
+
+ /* save the image on clipboard to a temp file so we can reference it in the
+ * attachment.
+ */
+ file = g_file_new_tmp("talkatu-clipboard-XXXXXX.png", &stream, &error);
+ if(error != NULL) {
+ g_warning("failed to create temp file: %s", error->message);
+ g_error_free(error);
+
+ return;
+ }
+
+ ostream = g_io_stream_get_output_stream(G_IO_STREAM(stream));
+
+ saved = gdk_pixbuf_save_to_stream(pixbuf, ostream, "png", NULL, &error,
+ NULL);
+ if(!saved) {
+ g_object_unref(G_OBJECT(file));
+ g_warning("failed to save an image from the clipboard: %s",
+ error->message);
+ g_error_free(error);
+
+ return;
+ }
+
+ if(!g_output_stream_close(ostream, NULL, &error)) {
+ g_warning("failed to save an image from the clipboard: %s",
+ error->message);
+ g_error_free(error);
+
+ return;
+ }
+
+ info = g_file_query_info(file, G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE, NULL, NULL);
+ size = g_file_info_get_attribute_uint64(info,
+ G_FILE_ATTRIBUTE_STANDARD_SIZE);
+ g_object_unref(G_OBJECT(info));
+
+ /* now create the message and it's attachment */
input = GTK_WIDGET(data);
buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(input));
comment = talkatu_markup_get_html(buffer, NULL);
- attachment = talkatu_attachment_new_from_pixbuf(G_GUINT64_CONSTANT(0),
- "unknown.png", pixbuf);
+ attachment = talkatu_attachment_new(G_GUINT64_CONSTANT(0), "image/png");
+ talkatu_attachment_set_local_uri(attachment, filename);
+ g_free(filename);
+
+ talkatu_attachment_set_size(attachment, size);
dialog = talkatu_attachment_dialog_new(attachment, comment);
g_signal_connect(G_OBJECT(dialog), "response",
G_CALLBACK(talkatu_input_attachment_response_cb), input);
gtk_widget_show_all(dialog);
+ g_object_unref(G_OBJECT(file));
g_free(comment);
}