/* * Copyright (C) 2005 Kouji TAKAO * * This program 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. * * This program 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include "gpass/error.h" #include "application.h" #include "attribute-widgets.h" #include "attribute-editor.h" static GPassViewClass *parent_class = NULL; static guint attribute_hash(gconstpointer key) { GPassAttribute *attr = GPASS_ATTRIBUTE(key); return g_str_hash(attr->name); } static gboolean attribute_equal(gconstpointer key1, gconstpointer key2) { GPassAttribute *attr1 = GPASS_ATTRIBUTE(key1); GPassAttribute *attr2 = GPASS_ATTRIBUTE(key2); if (attr1->type == attr2->type && strcmp(attr1->name, attr2->name) == 0) { return TRUE; } return FALSE; } static void gnome_attribute_editor_initialize(GTypeInstance *instance, gpointer g_class) { GPassGnomeAttributeEditor *self = GPASS_GNOME_ATTRIBUTE_EDITOR(instance); self->type_attribute = NULL; self->widgets = NULL; self->hash = NULL; } static void gnome_attribute_editor_finalize(GObject *object) { GPassGnomeAttributeEditor *self = GPASS_GNOME_ATTRIBUTE_EDITOR(object); g_list_free(self->widgets); g_hash_table_destroy(self->hash); G_OBJECT_CLASS(parent_class)->finalize(object); } static GError * gnome_attribute_editor_run(GPassView *self, GPassViewResult *result) { gtk_widget_show(self->window); self->main_loop = g_main_loop_new(NULL, FALSE); GDK_THREADS_LEAVE(); g_main_loop_run(self->main_loop); GDK_THREADS_ENTER(); g_main_loop_unref(self->main_loop); gtk_widget_hide(self->window); *result = self->result; return NULL; } static void gnome_attribute_editor_class_initialize(gpointer g_class, gpointer g_class_data) { GObjectClass *gobject_class = G_OBJECT_CLASS(g_class); GPassViewClass *view_class = GPASS_VIEW_CLASS(g_class); parent_class = g_type_class_peek_parent(g_class); gobject_class->finalize = gnome_attribute_editor_finalize; view_class->run = gnome_attribute_editor_run; } GType gpass_gnome_attribute_editor_get_type(void) { static GType type = 0; if (type == 0) { static const GTypeInfo info = { sizeof(GPassGnomeAttributeEditorClass), NULL, NULL, gnome_attribute_editor_class_initialize, NULL, NULL, sizeof(GPassGnomeAttributeEditor), 0, gnome_attribute_editor_initialize, }; type = g_type_register_static(GPASS_TYPE_VIEW, "GPassGnomeAttributeEditor", &info, 0); } return type; } static void clear_widgets(GPassGnomeAttributeEditor *self) { GtkWidget *table = glade_xml_get_widget(GPASS_VIEW(self)->xml, "attributes"); GList *p; for (p = self->widgets; p != NULL; p = g_list_next(p)) { GPassGnomeAttribute *widget = GPASS_GNOME_ATTRIBUTE(p->data); gtk_widget_hide(widget->label); gtk_container_remove(GTK_CONTAINER(table), widget->label); gtk_widget_hide(widget->widget); gtk_container_remove(GTK_CONTAINER(table), widget->widget); } g_list_free(self->widgets); self->widgets = NULL; } static GPassAttributeList * create_attributes(GPassGnomeAttributeEditor *self, const gchar *type) { GPassApplication *app = GPASS_APPLICATION(GPASS_VIEW(self)->model); GPassEntryFactoryCursor *cursor; GPassEntryClass *entry_class; GError *error; cursor = gpass_entry_factory_create_cursor(app->entry_factory); error = gpass_entry_factory_cursor_seek(cursor, type); if (error != NULL) { gpass_error_show_and_exit(error); } g_object_get(cursor, "entry_class", &entry_class, NULL); g_object_unref(cursor); return gpass_entry_class_attributes(entry_class); } static void table_attach(GtkTable *table, GPassGnomeAttribute *attr, gint position) { gtk_table_attach(table, attr->label, 0, 1, position, position + 1, GTK_FILL, GTK_FILL, 0, 0); g_object_ref(attr->label); gtk_widget_show(attr->label); gtk_table_attach(table, attr->widget, 1, 2, position, position + 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0); g_object_ref(attr->widget); gtk_widget_show(attr->widget); } static void type_attribute_on_notify(GObject *gobject, GParamSpec *arg, gpointer user_data) { GPassGnomeAttributeEditor *self = GPASS_GNOME_ATTRIBUTE_EDITOR(user_data); const gchar *type; GtkWidget *table = glade_xml_get_widget(GPASS_VIEW(self)->xml, "attributes"); gint y; GPassAttributeList *attributes; GPassAttributeListCursor *cursor; GError *error; error = gpass_gnome_attribute_get(self->type_attribute, &type); if (error != NULL) { gpass_error_show_and_exit(error); } clear_widgets(self); gtk_widget_hide(table); table_attach(GTK_TABLE(table), self->type_attribute, 0); self->widgets = g_list_append(self->widgets, self->type_attribute); y = 1; attributes = create_attributes(self, type); cursor = gpass_attribute_list_create_cursor(attributes); while (!gpass_attribute_list_cursor_is_done(cursor)) { GPassAttribute *attr; GPassGnomeAttribute *widget; GError *error; g_object_get(cursor, "attribute", &attr, NULL); widget = g_hash_table_lookup(self->hash, attr); if (widget == NULL) { widget = gpass_gnome_attribute_new(attr); g_hash_table_insert(self->hash, attr, widget); } table_attach(GTK_TABLE(table), widget, y); if (strcmp(attr->name, "creation-time") == 0 || strcmp(attr->name, "modification-time") == 0) { gtk_widget_set_sensitive(widget->widget, FALSE); } self->widgets = g_list_append(self->widgets, widget); error = gpass_attribute_list_cursor_next(cursor); if (error != NULL) { gpass_error_show_and_exit(error); } y++; } g_object_unref(cursor); g_object_unref(attributes); gtk_widget_show(table); } static void append_type_widget(GPassGnomeAttributeEditor *self, const gchar *type, gboolean has_child, gint position) { GPassApplication *app = GPASS_APPLICATION(GPASS_VIEW(self)->model); GtkWidget *table = glade_xml_get_widget(GPASS_VIEW(self)->xml, "attributes"); GPassEntryFactoryCursor *cursor = gpass_entry_factory_create_cursor(app->entry_factory); GPassAttribute *attr = g_object_new(GPASS_TYPE_ATTRIBUTE, "type", GPASS_ATTRIBUTE_TYPE_ENTRY_TYPE, "name", "type", "nick", _("Type"), "blurb", _("The entry type"), NULL); GPassGnomeAttribute *widget = gpass_gnome_attribute_new(attr); g_object_unref(attr); while (!gpass_entry_factory_cursor_is_done(cursor)) { if (has_child) { gboolean can_have_child; g_object_get(cursor, "can_have_child", &can_have_child, NULL); if (!can_have_child) { gpass_entry_factory_cursor_next(cursor); continue; } } gpass_gnome_type_attribute_append(GPASS_GNOME_TYPE_ATTRIBUTE(widget), cursor); gpass_entry_factory_cursor_next(cursor); } g_object_unref(cursor); gpass_gnome_attribute_set(widget, type); table_attach(GTK_TABLE(table), widget, position); g_signal_connect(widget, "notify", G_CALLBACK(type_attribute_on_notify), self); self->type_attribute = widget; self->widgets = g_list_append(self->widgets, widget); } void gpass_gnome_attribute_editor_set(GPassGnomeAttributeEditor *self, const gchar *type, GPassAttributeList *attributes, gboolean has_child) { GtkWidget *table = glade_xml_get_widget(GPASS_VIEW(self)->xml, "attributes"); GPassAttributeListCursor *cursor; gint y; clear_widgets(self); if (self->hash != NULL) { g_hash_table_destroy(self->hash); } self->hash = g_hash_table_new_full(attribute_hash, attribute_equal, NULL, g_object_unref); append_type_widget(self, type, has_child, 0); /* append attribute widgets */ y = 1; cursor = gpass_attribute_list_create_cursor(attributes); while (!gpass_attribute_list_cursor_is_done(cursor)) { GPassAttribute *attr; GPassGnomeAttribute *widget; GError *error; g_object_get(cursor, "attribute", &attr, NULL); widget = gpass_gnome_attribute_new(attr); table_attach(GTK_TABLE(table), widget, y); if (strcmp(attr->name, "creation-time") == 0 || strcmp(attr->name, "modification-time") == 0) { gtk_widget_set_sensitive(widget->widget, FALSE); } self->widgets = g_list_append(self->widgets, widget); g_hash_table_insert(self->hash, attr, widget); error = gpass_attribute_list_cursor_next(cursor); if (error != NULL) { gpass_error_show_and_exit(error); } y++; } g_object_unref(cursor); } void gpass_gnome_attribute_editor_get(GPassGnomeAttributeEditor *self, const gchar **type, GPassAttributeList **result) { GPassAttributeList *attributes; GPassAttributeListCursor *cursor; GError *error; error = gpass_gnome_attribute_get(self->type_attribute, type); if (error != NULL) { gpass_error_show_and_exit(error); } attributes = create_attributes(self, *type); cursor = gpass_attribute_list_create_cursor(attributes); *result = g_object_new(GPASS_TYPE_ATTRIBUTE_LIST, NULL); while (!gpass_attribute_list_cursor_is_done(cursor)) { GPassAttribute *attr; GPassGnomeAttribute *widget; g_object_get(cursor, "attribute", &attr, NULL); widget = g_hash_table_lookup(self->hash, attr); if (widget != NULL) { GPassAttribute *r; g_object_get(widget, "attribute", &r, NULL); error = gpass_attribute_list_append(*result, r); if (error != NULL) { gpass_error_show_and_exit(error); } } error = gpass_attribute_list_cursor_next(cursor); if (error != NULL) { gpass_error_show_and_exit(error); } } g_object_unref(cursor); g_object_unref(attributes); } /*********************************************************** * * Signal handlers * ***********************************************************/ void gpass_gnome_attribute_editor_on_response(GtkWidget *widget, gint response_id, gpointer user_data) { GPassGnomeAttributeEditor *self; gpass_view_self_from_widget(widget, (gpointer **) &self); if (response_id == GTK_RESPONSE_OK) { GPASS_VIEW(self)->result = GPASS_VIEW_RESULT_SUCCEED; } else { GPASS_VIEW(self)->result = GPASS_VIEW_RESULT_FAILED; } gpass_view_shutdown_main_loop(GPASS_VIEW(self)); }