From: Andrea Zagli <azagli@libero.it>
Date: Wed, 8 Jun 2011 15:34:17 +0000 (+0200)
Subject: Resources management.
X-Git-Tag: v0.0.1~14
X-Git-Url: https://saetta.ns0.it/gitweb?a=commitdiff_plain;h=eddfbc712b0cf8a3b9254fe8dd6fb08feaff54a7;p=zakautho%2Fgui

Resources management.
---

diff --git a/data/autoz-gui/gui/autoz-gui.ui b/data/autoz-gui/gui/autoz-gui.ui
index 087108c..dae033a 100644
--- a/data/autoz-gui/gui/autoz-gui.ui
+++ b/data/autoz-gui/gui/autoz-gui.ui
@@ -80,6 +80,7 @@
                         <property name="visible">True</property>
                         <property name="label" translatable="yes">Re_sources</property>
                         <property name="use_underline">True</property>
+                        <signal name="activate" handler="on_mnu_view_resources_activate"/>
                       </object>
                     </child>
                     <child>
@@ -288,6 +289,7 @@
     <property name="title" translatable="yes">Role - Autoz GUI</property>
     <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
+    <property name="default_width">500</property>
     <property name="destroy_with_parent">True</property>
     <child>
       <object class="GtkVBox" id="vbox3">
@@ -426,6 +428,8 @@
     <property name="title" translatable="yes">Roles - Autoz GUI</property>
     <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
+    <property name="default_width">550</property>
+    <property name="default_height">400</property>
     <property name="destroy_with_parent">True</property>
     <child>
       <object class="GtkVBox" id="vbox5">
@@ -590,6 +594,7 @@
     <property name="title" translatable="yes">Resource - Autoz GUI</property>
     <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
+    <property name="default_width">500</property>
     <property name="destroy_with_parent">True</property>
     <child>
       <object class="GtkVBox" id="vbox4">
@@ -644,7 +649,7 @@
               <object class="GtkEntry" id="entry2">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-                <property name="max_length">30</property>
+                <property name="max_length">255</property>
                 <property name="invisible_char">&#x2022;</property>
               </object>
               <packing>
@@ -712,6 +717,8 @@
     <property name="title" translatable="yes">Resources - Autoz GUI</property>
     <property name="modal">True</property>
     <property name="window_position">center-on-parent</property>
+    <property name="default_width">550</property>
+    <property name="default_height">400</property>
     <property name="destroy_with_parent">True</property>
     <child>
       <object class="GtkVBox" id="vbox7">
diff --git a/src/Makefile.am b/src/Makefile.am
index 9d9ea20..57a2a40 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,10 @@ autoz_gui_SOURCES = \
                 main.c \
                 openauditds.c \
                 openauditds.h \
+                resource.c \
+                resource.h \
+                resources.c \
+                resources.h \
                 role.c \
                 role.h \
                 roles.c \
diff --git a/src/main.c b/src/main.c
index fd655b5..dc437c4 100644
--- a/src/main.c
+++ b/src/main.c
@@ -30,6 +30,7 @@
 #include "commons.h"
 #include "openauditds.h"
 #include "roles.h"
+#include "resources.h"
 
 G_MODULE_EXPORT void on_mnu_file_close_activate (GtkMenuItem *menuitem,
                             gpointer user_data);
@@ -162,6 +163,19 @@ on_mnu_view_roles_activate (GtkMenuItem *menuitem,
 	main_set_vbx_body_child (vbx);
 }
 
+G_MODULE_EXPORT void
+on_mnu_view_resources_activate (GtkMenuItem *menuitem,
+                            gpointer user_data)
+{
+	GtkWidget *vbx;
+
+	Resources *m = resources_new (commons, FALSE);
+
+	vbx = resources_get_widget (m);
+
+	main_set_vbx_body_child (vbx);
+}
+
 G_MODULE_EXPORT void
 on_mnu_help_about_activate (GtkMenuItem *menuitem,
                             gpointer user_data)
diff --git a/src/resource.c b/src/resource.c
new file mode 100644
index 0000000..5561d57
--- /dev/null
+++ b/src/resource.c
@@ -0,0 +1,323 @@
+/* 
+ * Copyright (C) 2011 Andrea Zagli <azagli@libero.it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <libgda-ui/libgda-ui.h>
+#include <sql-parser/gda-sql-parser.h>
+
+#include "resource.h"
+
+static void resource_class_init (ResourceClass *klass);
+static void resource_init (Resource *resource);
+
+static void resource_load (Resource *resource);
+static void resource_save (Resource *resource);
+
+static void resource_set_property (GObject *object,
+                                     guint property_id,
+                                     const GValue *value,
+                                     GParamSpec *pspec);
+static void resource_get_property (GObject *object,
+                                     guint property_id,
+                                     GValue *value,
+                                     GParamSpec *pspec);
+
+static void resource_on_btn_cancel_clicked (GtkButton *button,
+                                    gpointer user_data);
+static void resource_on_btn_save_clicked (GtkButton *button,
+                                  gpointer user_data);
+
+#define RESOURCE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RESOURCE, ResourcePrivate))
+
+typedef struct _ResourcePrivate ResourcePrivate;
+struct _ResourcePrivate
+	{
+		Commons *commons;
+
+		GtkWidget *w;
+
+		gint id;
+	};
+
+G_DEFINE_TYPE (Resource, resource, G_TYPE_OBJECT)
+
+static void
+resource_class_init (ResourceClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (ResourcePrivate));
+
+	object_class->set_property = resource_set_property;
+	object_class->get_property = resource_get_property;
+
+	/**
+	 * Resource::updated:
+	 * @resource:
+	 *
+	 */
+	klass->updated_signal_id = g_signal_new ("updated",
+	                                               G_TYPE_FROM_CLASS (object_class),
+	                                               G_SIGNAL_RUN_LAST,
+	                                               0,
+	                                               NULL,
+	                                               NULL,
+	                                               g_cclosure_marshal_VOID__VOID,
+	                                               G_TYPE_NONE,
+	                                               0);
+}
+
+static void
+resource_init (Resource *resource)
+{
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+}
+
+/**
+ * resource_new:
+ * @commons:
+ * @id:
+ *
+ * Returns: the newly created #Resource object.
+ */
+Resource
+*resource_new (Commons *commons, gint id)
+{
+	GError *error;
+
+	Resource *a = RESOURCE (g_object_new (resource_get_type (), NULL));
+
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (a);
+
+	priv->commons = commons;
+
+	error = NULL;
+	gtk_builder_add_objects_from_file (priv->commons->gtkbuilder, priv->commons->guifile,
+	                                   g_strsplit ("w_resource", "|", -1),
+	                                   &error);
+	if (error != NULL)
+		{
+			g_warning ("Error: %s.", error->message);
+			return NULL;
+		}
+
+	priv->w = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_resource"));
+
+	g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button5"),
+	                  "clicked", G_CALLBACK (resource_on_btn_cancel_clicked), (gpointer *)a);
+	g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button6"),
+	                  "clicked", G_CALLBACK (resource_on_btn_save_clicked), (gpointer *)a);
+
+	priv->id = id;
+	if (priv->id == 0)
+		{
+			gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (priv->commons->gtkbuilder, "label5")), "");
+		}
+	else
+		{
+			gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (priv->commons->gtkbuilder, "label5")), g_strdup_printf ("%d", priv->id));
+			resource_load (a);
+		}
+
+	return a;
+}
+
+/**
+ * resource_get_widget:
+ * @resource:
+ *
+ */
+GtkWidget
+*resource_get_widget (Resource *resource)
+{
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+
+	return priv->w;
+}
+
+/* PRIVATE */
+static void
+resource_load (Resource *resource)
+{
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+
+	GError *error;
+	gchar *sql;
+	GdaStatement *stmt;
+	GdaDataModel *dm;
+
+	sql = g_strdup_printf ("SELECT resource_id FROM %sresources WHERE id = %d",
+	                       priv->commons->prefix,
+	                       priv->id);
+	stmt = gda_sql_parser_parse_string (priv->commons->gdaparser, sql, NULL, NULL);
+	g_free (sql);
+	dm = gda_connection_statement_execute_select (priv->commons->gdacon, stmt, NULL, &error);
+	g_object_unref (stmt);
+	if (dm != NULL && gda_data_model_get_n_rows (dm) == 1)
+		{
+			gtk_entry_set_text (GTK_ENTRY (gtk_builder_get_object (priv->commons->gtkbuilder, "entry2")),
+			                    gda_value_stringify (gda_data_model_get_value_at (dm, 0, 0, NULL)));
+		}
+	else
+		{
+			GtkWidget *dialog;
+			dialog = gtk_message_dialog_new (GTK_WINDOW (priv->w),
+			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+			                                 GTK_MESSAGE_WARNING,
+			                                 GTK_BUTTONS_OK,
+			                                 "Record %d doesn't exist.", priv->id);
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+		}
+}
+
+static void
+resource_save (Resource *resource)
+{
+	const GdaDsnInfo *info;
+	GError *error;
+	gchar *sql;
+	GdaStatement *stmt;
+	GdaDataModel *dm;
+	GtkWidget *dialog;
+
+	ResourceClass *klass = RESOURCE_GET_CLASS (resource);
+
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+
+	if (priv->id == 0)
+		{
+			/* find the new id */
+			guint new_id;
+
+			new_id = 0;
+			sql = g_strdup_printf ("SELECT COALESCE (MAX (id), 0) FROM %sresources", priv->commons->prefix);
+			stmt = gda_sql_parser_parse_string (priv->commons->gdaparser, sql, NULL, NULL);
+			g_free (sql);
+			dm = gda_connection_statement_execute_select (priv->commons->gdacon, stmt, NULL, &error);
+			g_object_unref (stmt);
+			if (dm != NULL && gda_data_model_get_n_rows (dm) == 1)
+				{
+					new_id = g_value_get_int (gda_data_model_get_value_at (dm, 0, 0, NULL));
+				}
+			new_id++;
+
+			sql = g_strdup_printf ("INSERT INTO %sresources (id, resource_id)"
+			                       " VALUES (%d, '%s',)",
+			                       priv->commons->prefix,
+			                       new_id,
+			                       gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (priv->commons->gtkbuilder, "entry2"))));
+			stmt = gda_sql_parser_parse_string (priv->commons->gdaparser, sql, NULL, NULL);
+		}
+	else
+		{
+			sql = g_strdup_printf ("UPDATE %sresources"
+			                       " SET"
+			                       " resource_id = '%s'"
+			                       " WHERE id = %d",
+			                       priv->commons->prefix,
+			                       gtk_entry_get_text (GTK_ENTRY (gtk_builder_get_object (priv->commons->gtkbuilder, "entry2"))),
+			                       priv->id);
+			stmt = gda_sql_parser_parse_string (priv->commons->gdaparser, sql, NULL, NULL);
+		}
+	g_free (sql);
+
+	error = NULL;
+	if (gda_connection_statement_execute_non_select (priv->commons->gdacon, stmt, NULL, NULL, &error) == 1)
+		{
+			g_object_unref (stmt);
+
+			g_signal_emit (resource, klass->updated_signal_id, 0);
+
+			if (priv->id == 0)
+				{
+					priv->id = strtol (gtk_label_get_text (GTK_LABEL (gtk_builder_get_object (priv->commons->gtkbuilder, "label5"))), NULL, 10);
+				}
+
+			dialog = gtk_message_dialog_new (GTK_WINDOW (priv->w),
+			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+			                                 GTK_MESSAGE_INFO,
+			                                 GTK_BUTTONS_OK,
+			                                 "Saved with success.");
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+		}
+	else
+		{
+			if (priv->id == 0)
+				{
+					gtk_label_set_text (GTK_LABEL (gtk_builder_get_object (priv->commons->gtkbuilder, "label5")), "");
+				}
+
+			dialog = gtk_message_dialog_new (GTK_WINDOW (priv->w),
+			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+			                                 GTK_MESSAGE_WARNING,
+			                                 GTK_BUTTONS_OK,
+			                                 "Error on saving.\n\n%s",
+			                                 (error != NULL && error->message != NULL ? error->message : "No details."));
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+		}
+}
+
+static void
+resource_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	Resource *resource = RESOURCE (object);
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+
+	switch (property_id)
+		{
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+				break;
+		}
+}
+
+static void
+resource_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	Resource *resource = RESOURCE (object);
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+
+	switch (property_id)
+		{
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+				break;
+		}
+}
+
+/* CALLBACK */
+static void
+resource_on_btn_cancel_clicked (GtkButton *button,
+                        gpointer user_data)
+{
+	Resource *resource = (Resource *)user_data;
+
+	ResourcePrivate *priv = RESOURCE_GET_PRIVATE (resource);
+
+	gtk_widget_destroy (priv->w);
+}
+
+static void
+resource_on_btn_save_clicked (GtkButton *button,
+                      gpointer user_data)
+{
+	resource_save ((Resource *)user_data);
+}
diff --git a/src/resource.h b/src/resource.h
new file mode 100644
index 0000000..93270ac
--- /dev/null
+++ b/src/resource.h
@@ -0,0 +1,65 @@
+/* 
+ * Copyright (C) 2011 Andrea Zagli <azagli@libero.it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __RESOURCE_H__
+#define __RESOURCE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include "commons.h"
+
+G_BEGIN_DECLS
+
+
+#define TYPE_RESOURCE                 (resource_get_type ())
+#define RESOURCE(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RESOURCE, Resource))
+#define RESOURCE_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RESOURCE, ResourceClass))
+#define IS_RESOURCE(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RESOURCE))
+#define IS_RESOURCE_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RESOURCE))
+#define RESOURCE_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RESOURCE, ResourceClass))
+
+
+typedef struct _Resource Resource;
+typedef struct _ResourceClass ResourceClass;
+
+struct _Resource
+	{
+		GObject parent;
+	};
+
+struct _ResourceClass
+	{
+		GObjectClass parent_class;
+
+		guint updated_signal_id;
+	};
+
+GType resource_get_type (void) G_GNUC_CONST;
+
+Resource *resource_new (Commons *commons, gint id);
+
+GtkWidget *resource_get_widget (Resource *resource);
+
+
+G_END_DECLS
+
+#endif /* __RESOURCE_H__ */
diff --git a/src/resources.c b/src/resources.c
new file mode 100644
index 0000000..94e028b
--- /dev/null
+++ b/src/resources.c
@@ -0,0 +1,390 @@
+/* 
+ * Copyright (C) 2011 Andrea Zagli <azagli@libero.it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <string.h>
+
+#include <sql-parser/gda-sql-parser.h>
+
+#include "resources.h"
+#include "resource.h"
+
+static void resources_class_init (ResourcesClass *klass);
+static void resources_init (Resources *resources);
+
+static void resources_load (Resources *resources);
+static void resources_edit (Resources *resources);
+
+static void resources_on_resource_updated (gpointer instance, gpointer user_data);
+
+static void resources_set_property (GObject *object,
+                                     guint property_id,
+                                     const GValue *value,
+                                     GParamSpec *pspec);
+static void resources_get_property (GObject *object,
+                                     guint property_id,
+                                     GValue *value,
+                                     GParamSpec *pspec);
+
+static void resources_on_btn_new_clicked (GtkButton *button,
+                      gpointer user_data);
+static void resources_on_btn_edit_clicked (GtkButton *button,
+                      gpointer user_data);
+static void resources_on_btn_delete_clicked (GtkButton *button,
+                        gpointer user_data);
+static void resources_on_trv_resources_row_activated (GtkTreeView *tree_view,
+                                             GtkTreePath *tree_path,
+                                             GtkTreeViewColumn *column,
+                                             gpointer user_data);
+
+#define RESOURCES_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_RESOURCES, ResourcesPrivate))
+
+enum
+{
+	COL_ID,
+	COL_NAME
+};
+
+typedef struct _ResourcesPrivate ResourcesPrivate;
+struct _ResourcesPrivate
+	{
+		Commons *commons;
+
+		GtkWidget *widget;
+
+		GtkTreeSelection *selection;
+		GtkListStore *lstore_resources;
+	};
+
+G_DEFINE_TYPE (Resources, resources, G_TYPE_OBJECT)
+
+static void
+resources_class_init (ResourcesClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (object_class, sizeof (ResourcesPrivate));
+
+	object_class->set_property = resources_set_property;
+	object_class->get_property = resources_get_property;
+}
+
+static void
+resources_init (Resources *resources)
+{
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+}
+
+/**
+ * resources_new:
+ * @commons:
+ * @selection:
+ *
+ * Returns: the newly created #Resources object.
+ */
+Resources
+*resources_new (Commons *commons, gboolean selection)
+{
+	GError *error;
+
+	Resources *a = RESOURCES (g_object_new (resources_get_type (), NULL));
+
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (a);
+
+	priv->commons = commons;
+
+	error = NULL;
+	gtk_builder_add_objects_from_file (priv->commons->gtkbuilder, priv->commons->guifile,
+	                                   g_strsplit (g_strconcat ("lstore_resources",
+	                                                            (selection ? "|w_resources" : "|vbox7"),
+	                                                            NULL),
+	                                               "|", -1),
+	                                   &error);
+	if (error != NULL)
+		{
+			g_warning ("Error: %s.", error->message);
+			return NULL;
+		}
+
+	priv->widget = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, (selection ? "w_resources" : "vbox7")));
+	priv->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (priv->commons->gtkbuilder, "treeview1")));
+	priv->lstore_resources = GTK_LIST_STORE (gtk_builder_get_object (priv->commons->gtkbuilder, "lstore_resources"));
+
+	g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button11"),
+	                  "clicked", G_CALLBACK (resources_on_btn_new_clicked), (gpointer)a);
+	g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button12"),
+	                  "clicked", G_CALLBACK (resources_on_btn_edit_clicked), (gpointer)a);
+	g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button14"),
+	                  "clicked", G_CALLBACK (resources_on_btn_delete_clicked), (gpointer)a);
+	g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "treeview1"),
+	                  "row-activated", G_CALLBACK (resources_on_trv_resources_row_activated), (gpointer)a);
+
+	if (!selection)
+		{
+			gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "button15")));
+			gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "button16")));
+		}
+
+	resources_load (a);
+
+	return a;
+}
+
+/**
+ * resources_get_widget:
+ * @resources:
+ *
+ */
+GtkWidget
+*resources_get_widget (Resources *resources)
+{
+	ResourcesPrivate *priv;
+
+	g_return_val_if_fail (IS_RESOURCES (resources), NULL);
+
+	priv = RESOURCES_GET_PRIVATE (resources);
+
+	return priv->widget;
+}
+
+/* PRIVATE */
+static void
+resources_load (Resources *resources)
+{
+	GtkTreeIter iter;
+
+	gchar *sql;
+
+	GdaStatement *stmt;
+	GError *error;
+	GdaDataModel *dm;
+
+	gint rows;
+	gint row;
+
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+
+	gtk_list_store_clear (priv->lstore_resources);
+
+	sql = g_strdup_printf ("SELECT id, resource_id"
+	                       " FROM %sresources"
+	                       " ORDER BY resource_id",
+	                       priv->commons->prefix);
+	stmt = gda_sql_parser_parse_string (priv->commons->gdaparser, sql, NULL, NULL);
+	g_free (sql);
+	dm = gda_connection_statement_execute_select (priv->commons->gdacon, stmt, NULL, &error);
+	g_object_unref (stmt);
+	if (dm != NULL)
+		{
+			rows = gda_data_model_get_n_rows (dm);
+			for (row = 0; row < rows; row++)
+				{
+					gtk_list_store_append (priv->lstore_resources, &iter);
+					gtk_list_store_set (priv->lstore_resources, &iter,
+					                    COL_ID, g_value_get_int (gda_data_model_get_value_at (dm, 0, row, NULL)),
+					                    COL_NAME, gda_value_stringify (gda_data_model_get_value_at (dm, 1, row, NULL)),
+					                    -1);
+				}
+
+			g_object_unref (dm);
+		}
+	else
+		{
+			/* TODO */
+		}
+}
+
+static void
+resources_edit (Resources *resources)
+{
+	GtkTreeIter iter;
+	guint id;
+
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+
+	if (gtk_tree_selection_get_selected (priv->selection, NULL, &iter))
+		{
+			GtkWidget *w;
+
+			gtk_tree_model_get (GTK_TREE_MODEL (priv->lstore_resources), &iter,
+			                    COL_ID, &id,
+			                    -1);
+
+			Resource *c = resource_new (priv->commons, id);
+
+			g_signal_connect (G_OBJECT (c), "updated",
+			                  G_CALLBACK (resources_on_resource_updated), (gpointer)resources);
+
+			w = resource_get_widget (c);
+			gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")));
+			gtk_widget_show_all (w);
+		}
+	else
+		{
+			GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")),
+			                                            GTK_DIALOG_DESTROY_WITH_PARENT,
+			                                            GTK_MESSAGE_WARNING,
+			                                            GTK_BUTTONS_OK,
+			                                            "Select a role.");
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+		}
+}
+
+static void
+resources_on_resource_updated (gpointer instance, gpointer user_data)
+{
+	resources_load ((Resources *)user_data);
+}
+
+static void
+resources_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+	Resources *resources = RESOURCES (object);
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+
+	switch (property_id)
+		{
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+				break;
+		}
+}
+
+static void
+resources_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+	Resources *resources = RESOURCES (object);
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+
+	switch (property_id)
+		{
+			default:
+				G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+				break;
+		}
+}
+
+/* CALLBACK */
+static void
+resources_on_btn_new_clicked (GtkButton *button,
+                      gpointer user_data)
+{
+	GtkWidget *w;
+
+	Resources *resources = (Resources *)user_data;
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+
+	Resource *c = resource_new (priv->commons, 0);
+
+	g_signal_connect (G_OBJECT (c), "updated",
+	                  G_CALLBACK (resources_on_resource_updated), (gpointer)resources);
+
+	w = resource_get_widget (c);
+	gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")));
+	gtk_widget_show_all (w);
+}
+
+static void
+resources_on_btn_edit_clicked (GtkButton *button,
+                      gpointer user_data)
+{
+	resources_edit ((Resources *)user_data);
+}
+
+static void
+resources_on_btn_delete_clicked (GtkButton *button,
+                        gpointer user_data)
+{
+	GtkWidget *dialog;
+	gboolean risp;
+
+	GtkTreeIter iter;
+	guint id;
+
+	Resources *resources = (Resources *)user_data;
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE (resources);
+
+	if (gtk_tree_selection_get_selected (priv->selection, NULL, &iter))
+		{
+			dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")),
+			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+			                                 GTK_MESSAGE_QUESTION,
+			                                 GTK_BUTTONS_YES_NO,
+			                                 "Are you sure to want to delete the selected resource?");
+			risp = gtk_dialog_run (GTK_DIALOG (dialog));
+			if (risp == GTK_RESPONSE_YES)
+				{
+					GError *error;
+					GdaStatement *stmt;
+
+					gtk_tree_model_get (GTK_TREE_MODEL (priv->lstore_resources), &iter,
+					                    COL_ID, &id,
+					                    -1);
+
+					error = NULL;
+					stmt = gda_sql_parser_parse_string (priv->commons->gdaparser,
+					                                    g_strdup_printf ("DELETE %sresources WHERE id = %d", priv->commons->prefix, id),
+					                                    NULL, NULL);
+
+					if (stmt != NULL)
+						{
+							dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")),
+							                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+							                                 GTK_MESSAGE_WARNING,
+							                                 GTK_BUTTONS_OK,
+							                                 "You must select a resource.");
+							return;
+						}
+
+					if (gda_connection_statement_execute_non_select (priv->commons->gdacon, stmt, NULL, NULL, &error) <= 0)
+						{
+							dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")),
+							                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+							                                 GTK_MESSAGE_WARNING,
+							                                 GTK_BUTTONS_OK,
+							                                 "Error on saving.\n\n%s",
+							                                 (error != NULL && error->message != NULL ? error->message : "No details."));
+						}
+
+					resources_load (resources);
+				}
+			gtk_widget_destroy (dialog);
+		}
+	else
+		{
+			dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")),
+			                                 GTK_DIALOG_DESTROY_WITH_PARENT,
+			                                 GTK_MESSAGE_WARNING,
+			                                 GTK_BUTTONS_OK,
+			                                 "Select a resource.");
+			gtk_dialog_run (GTK_DIALOG (dialog));
+			gtk_widget_destroy (dialog);
+		}
+}
+
+static void
+resources_on_trv_resources_row_activated (GtkTreeView *tree_view,
+                                             GtkTreePath *tree_path,
+                                             GtkTreeViewColumn *column,
+                                             gpointer user_data)
+{
+	ResourcesPrivate *priv = RESOURCES_GET_PRIVATE ((Resources *)user_data);
+
+	resources_edit ((Resources *)user_data);
+}
diff --git a/src/resources.h b/src/resources.h
new file mode 100644
index 0000000..21ab8e8
--- /dev/null
+++ b/src/resources.h
@@ -0,0 +1,63 @@
+/* 
+ * Copyright (C) 2011 Andrea Zagli <azagli@libero.it>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __RESOURCES_H__
+#define __RESOURCES_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <gtk/gtk.h>
+
+#include "commons.h"
+
+G_BEGIN_DECLS
+
+
+#define TYPE_RESOURCES                 (resources_get_type ())
+#define RESOURCES(obj)                 (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RESOURCES, Resources))
+#define RESOURCES_CLASS(klass)         (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RESOURCES, ResourcesClass))
+#define IS_RESOURCES(obj)              (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RESOURCES))
+#define IS_RESOURCES_CLASS(klass)      (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RESOURCES))
+#define RESOURCES_GET_CLASS(obj)       (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RESOURCES, ResourcesClass))
+
+
+typedef struct _Resources Resources;
+typedef struct _ResourcesClass ResourcesClass;
+
+struct _Resources
+	{
+		GObject parent;
+	};
+
+struct _ResourcesClass
+	{
+		GObjectClass parent_class;
+	};
+
+GType resources_get_type (void) G_GNUC_CONST;
+
+Resources *resources_new (Commons *commons, gboolean selection);
+
+GtkWidget *resources_get_widget (Resources *resources);
+
+
+G_END_DECLS
+
+#endif /* __RESOURCES_H__ */