/* ev-metadata.c * this file is part of evince, a gnome document viewer * * Copyright (C) 2009 Carlos Garcia Campos * * Evince is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Evince 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 * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include "ev-metadata.h" struct _EvMetadata { GObject base; GFile *file; GHashTable *items; }; struct _EvMetadataClass { GObjectClass base_class; }; G_DEFINE_TYPE (EvMetadata, ev_metadata, G_TYPE_OBJECT) #define EV_METADATA_NAMESPACE "metadata::evince" static void ev_metadata_finalize (GObject *object) { EvMetadata *metadata = EV_METADATA (object); if (metadata->items) { g_hash_table_destroy (metadata->items); metadata->items = NULL; } if (metadata->file) { g_object_unref (metadata->file); metadata->file = NULL; } G_OBJECT_CLASS (ev_metadata_parent_class)->finalize (object); } static void ev_metadata_init (EvMetadata *metadata) { metadata->items = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } static void ev_metadata_class_init (EvMetadataClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); gobject_class->finalize = ev_metadata_finalize; } static void ev_metadata_load (EvMetadata *metadata) { GFileInfo *info; gchar **attrs; gint i; GError *error = NULL; info = g_file_query_info (metadata->file, "metadata::*", 0, NULL, &error); if (!info) { g_warning ("%s", error->message); g_error_free (error); return; } if (!g_file_info_has_namespace (info, "metadata")) { g_object_unref (info); return; } attrs = g_file_info_list_attributes (info, "metadata"); for (i = 0; attrs[i]; i++) { GFileAttributeType type; gpointer value; const gchar *key; if (!g_str_has_prefix (attrs[i], EV_METADATA_NAMESPACE)) continue; if (!g_file_info_get_attribute_data (info, attrs[i], &type, &value, NULL)) { continue; } key = attrs[i] + strlen (EV_METADATA_NAMESPACE"::"); if (type == G_FILE_ATTRIBUTE_TYPE_STRING) { g_hash_table_insert (metadata->items, g_strdup (key), g_strdup (value)); } } g_strfreev (attrs); g_object_unref (info); } EvMetadata * ev_metadata_new (GFile *file) { EvMetadata *metadata; g_return_val_if_fail (G_IS_FILE (file), NULL); metadata = EV_METADATA (g_object_new (EV_TYPE_METADATA, NULL)); metadata->file = g_object_ref (file); ev_metadata_load (metadata); return metadata; } gboolean ev_metadata_get_string (EvMetadata *metadata, const gchar *key, gchar **value) { gchar *v; v = g_hash_table_lookup (metadata->items, key); if (!v) return FALSE; *value = v; return TRUE; } static void metadata_set_callback (GObject *file, GAsyncResult *result, EvMetadata *metadata) { GError *error = NULL; if (!g_file_set_attributes_finish (G_FILE (file), result, NULL, &error)) { g_warning ("%s", error->message); g_error_free (error); } } gboolean ev_metadata_set_string (EvMetadata *metadata, const gchar *key, const gchar *value) { GFileInfo *info; gchar *gio_key; info = g_file_info_new (); gio_key = g_strconcat (EV_METADATA_NAMESPACE"::", key, NULL); if (value) { g_file_info_set_attribute_string (info, gio_key, value); } else { g_file_info_set_attribute (info, gio_key, G_FILE_ATTRIBUTE_TYPE_INVALID, NULL); } g_free (gio_key); g_hash_table_insert (metadata->items, g_strdup (key), g_strdup (value)); g_file_set_attributes_async (metadata->file, info, 0, G_PRIORITY_DEFAULT, NULL, (GAsyncReadyCallback)metadata_set_callback, metadata); g_object_unref (info); return TRUE; } gboolean ev_metadata_get_int (EvMetadata *metadata, const gchar *key, gint *value) { gchar *string_value; gchar *endptr; gint int_value; if (!ev_metadata_get_string (metadata, key, &string_value)) return FALSE; int_value = g_ascii_strtoull (string_value, &endptr, 0); if (int_value == 0 && string_value == endptr) return FALSE; *value = int_value; return TRUE; } gboolean ev_metadata_set_int (EvMetadata *metadata, const gchar *key, gint value) { gchar string_value[32]; g_snprintf (string_value, sizeof (string_value), "%d", value); return ev_metadata_set_string (metadata, key, string_value); } gboolean ev_metadata_get_double (EvMetadata *metadata, const gchar *key, gdouble *value) { gchar *string_value; gchar *endptr; gdouble double_value; if (!ev_metadata_get_string (metadata, key, &string_value)) return FALSE; double_value = g_ascii_strtod (string_value, &endptr); if (double_value == 0. && string_value == endptr) return FALSE; *value = double_value; return TRUE; } gboolean ev_metadata_set_double (EvMetadata *metadata, const gchar *key, gdouble value) { gchar string_value[G_ASCII_DTOSTR_BUF_SIZE]; g_ascii_dtostr (string_value, G_ASCII_DTOSTR_BUF_SIZE, value); return ev_metadata_set_string (metadata, key, string_value); } gboolean ev_metadata_get_boolean (EvMetadata *metadata, const gchar *key, gboolean *value) { gint int_value; if (!ev_metadata_get_int (metadata, key, &int_value)) return FALSE; *value = int_value; return TRUE; } gboolean ev_metadata_set_boolean (EvMetadata *metadata, const gchar *key, gboolean value) { return ev_metadata_set_string (metadata, key, value ? "1" : "0"); } gboolean ev_is_metadata_supported_for_file (GFile *file) { GFileAttributeInfoList *namespaces; gint i; gboolean retval = FALSE; namespaces = g_file_query_writable_namespaces (file, NULL, NULL); if (!namespaces) return retval; for (i = 0; i < namespaces->n_infos; i++) { if (strcmp (namespaces->infos[i].name, "metadata") == 0) { retval = TRUE; break; } } g_file_attribute_info_list_unref (namespaces); return retval; }