From f27ff465c18bdd3b931f8372283cddd35ac0675d Mon Sep 17 00:00:00 2001 From: Andrea Zagli Date: Sun, 13 Sep 2015 12:07:42 +0200 Subject: [PATCH] Added ZakCgiFormElementSelect. --- src/Makefile.am | 2 + src/formelementselect.c | 319 ++++++++++++++++++++++++++++++++++++++++ src/formelementselect.h | 62 ++++++++ tests/form.c | 7 + 4 files changed, 390 insertions(+) create mode 100644 src/formelementselect.c create mode 100644 src/formelementselect.h diff --git a/src/Makefile.am b/src/Makefile.am index 10235f3..49d9a1c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,6 +12,7 @@ libzakcgi_la_SOURCES = commons.c \ formelementcheck.c \ formelementhidden.c \ formelementpassword.c \ + formelementselect.c \ formelementtext.c \ formelementtextarea.c \ formelementsubmit.c \ @@ -29,6 +30,7 @@ libzakcgi_include_HEADERS = \ formelementcheck.h \ formelementhidden.h \ formelementpassword.h \ + formelementselect.h \ formelementtext.h \ formelementtextarea.h \ formelementsubmit.h \ diff --git a/src/formelementselect.c b/src/formelementselect.c new file mode 100644 index 0000000..94dadce --- /dev/null +++ b/src/formelementselect.c @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2015 Andrea Zagli + * + * 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 + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include "commons.h" +#include "tag.h" +#include "formelementselect.h" + +static void zak_cgi_form_element_select_class_init (ZakCgiFormElementSelectClass *class); +static void zak_cgi_form_element_select_init (ZakCgiFormElementSelect *zak_cgi_form_element_select); + +static gchar *zak_cgi_form_element_select_render (ZakCgiFormElement *element); + +static gboolean zak_cgi_form_element_select_is_valid (ZakCgiFormElement *element); + +static void zak_cgi_form_element_select_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void zak_cgi_form_element_select_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static void zak_cgi_form_element_select_dispose (GObject *gobject); +static void zak_cgi_form_element_select_finalize (GObject *gobject); + +#define ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ZAK_CGI_TYPE_FORM_ELEMENT_SELECT, ZakCgiFormElementSelectPrivate)) + +typedef struct _ZakCgiFormElementSelectPrivate ZakCgiFormElementSelectPrivate; +struct _ZakCgiFormElementSelectPrivate + { + GHashTable *ht_options; + }; + +G_DEFINE_TYPE (ZakCgiFormElementSelect, zak_cgi_form_element_select, ZAK_CGI_TYPE_FORM_ELEMENT) + +static void +zak_cgi_form_element_select_class_init (ZakCgiFormElementSelectClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + ZakCgiFormElementClass *elem_class = ZAK_CGI_FORM_ELEMENT_CLASS (klass); + + object_class->set_property = zak_cgi_form_element_select_set_property; + object_class->get_property = zak_cgi_form_element_select_get_property; + object_class->dispose = zak_cgi_form_element_select_dispose; + object_class->finalize = zak_cgi_form_element_select_finalize; + + elem_class->render = zak_cgi_form_element_select_render; + elem_class->is_valid = zak_cgi_form_element_select_is_valid; + + g_type_class_add_private (object_class, sizeof (ZakCgiFormElementSelectPrivate)); +} + +static void +zak_cgi_form_element_select_init (ZakCgiFormElementSelect *zak_cgi_form_element_select) +{ + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (zak_cgi_form_element_select); + + priv->ht_options = g_hash_table_new (g_str_hash, g_str_equal); +} + +/** + * zak_cgi_form_element_select_new: + * @id: + * @validation_regex: + * @...: + * + * Returns: the newly created #ZakCgiFormElementSelect object. + */ +ZakCgiFormElement +*zak_cgi_form_element_select_new (const gchar *id, + const gchar *validation_regex, + ...) +{ + va_list ap; + + ZakCgiFormElementSelect *zak_cgi_form_element_select; + + zak_cgi_form_element_select = ZAK_CGI_FORM_ELEMENT_SELECT (g_object_new (zak_cgi_form_element_select_get_type (), NULL)); + + va_start (ap, validation_regex); + + ZAK_CGI_FORM_ELEMENT_CLASS (zak_cgi_form_element_select_parent_class)->construct (ZAK_CGI_FORM_ELEMENT (zak_cgi_form_element_select), + id, + validation_regex, + zak_cgi_commons_valist_to_ghashtable (ap)); + + return ZAK_CGI_FORM_ELEMENT (zak_cgi_form_element_select); +} + +/** + * zak_cgi_form_element_select_add_option: + * @element: + * @value: + * @content: + * @...: + * + */ +void +zak_cgi_form_element_select_add_option (ZakCgiFormElementSelect *element, + const gchar *value, + const gchar *content, + ...) +{ + va_list ap; + GHashTable *ht_attrs; + + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (element); + + va_start (ap, content); + ht_attrs = zak_cgi_commons_valist_to_ghashtable (ap); + if (ht_attrs == NULL) + { + g_hash_table_new (g_str_hash, g_str_equal); + } + g_hash_table_replace (ht_attrs, "zak-cgi-content", g_strdup (content)); + + g_hash_table_replace (priv->ht_options, g_strdup (value), ht_attrs); +} + +static gchar +*zak_cgi_form_element_select_render (ZakCgiFormElement *element) +{ + gchar *ret; + + GHashTableIter iter; + gpointer key; + gpointer value; + GString *options; + GHashTable *ht_options_attrs; + + GHashTable *ht_attrs; + + GValue *gval; + + ZakCgiFormElementClass *klass; + + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (element); + + klass = (ZakCgiFormElementClass *)g_type_class_peek_parent (ZAK_CGI_FORM_ELEMENT_SELECT_GET_CLASS (ZAK_CGI_FORM_ELEMENT_SELECT (element))); + + gval = zak_cgi_form_element_get_value (element); + + /* list options */ + options = g_string_new ("\n"); + g_hash_table_iter_init (&iter, priv->ht_options); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + ht_options_attrs = (GHashTable *)value; + g_hash_table_replace (ht_options_attrs, "value", g_strdup ((gchar *)key)); + + if (gval != NULL) + { + if (g_strcmp0 (g_value_get_string (gval), (gchar *)key) == 0) + { + g_hash_table_replace (ht_options_attrs, "selected", g_strdup ("selected")); + } + } + + g_string_append (options, + zak_cgi_tag_tag_ht ("option", NULL, ht_options_attrs)); + g_string_append (options, "\n"); + } + + ht_attrs = klass->get_ht_attrs (element); + + g_hash_table_replace (ht_attrs, "zak-cgi-content", g_strdup (options->str)); + ret = zak_cgi_tag_tag_ht ("select", zak_cgi_form_element_get_id (element), ht_attrs); + + g_string_free (options, TRUE); + + return ret; +} + +static gboolean +zak_cgi_form_element_select_check_value (const gchar *validation_regex, GValue *value) +{ + gboolean ret; + + GRegex *regex; + GError *error; + + if (G_VALUE_HOLDS (value, G_TYPE_STRING)) + { + error = NULL; + regex = g_regex_new (validation_regex, 0, 0, &error); + if (regex == NULL + || error != NULL) + { + syslog (LOG_MAKEPRI(LOG_SYSLOG, LOG_DEBUG), "Error on creating regex: %s.", + error->message != NULL ? error->message : "no details"); + return FALSE; + } + + ret = g_regex_match ((const GRegex *)regex, g_value_get_string (value), 0, NULL); + } + else + { + ret = FALSE; + } + + return ret; +} + +static gboolean +zak_cgi_form_element_select_is_valid (ZakCgiFormElement *element) +{ + gboolean ret; + + GValue *gval; + + gchar *str_regex; + + gval = zak_cgi_form_element_get_value (element); + + g_object_get (G_OBJECT (element), + "validation-regex", &str_regex, + NULL); + + if (G_VALUE_HOLDS (gval, G_TYPE_PTR_ARRAY)) + { + guint i; + GPtrArray *ar = (GPtrArray *)g_value_get_boxed (gval); + for (i = 0; i < ar->len; i++) + { + if (!zak_cgi_form_element_select_check_value (str_regex, (GValue *)g_ptr_array_index (ar, i))) + { + ret = FALSE; + break; + } + } + } + else + { + ret = zak_cgi_form_element_select_check_value (str_regex, gval); + } + + return ret; +} + +/* PRIVATE */ +static void +zak_cgi_form_element_select_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + ZakCgiFormElementSelect *zak_cgi_form_element_select = (ZakCgiFormElementSelect *)object; + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (zak_cgi_form_element_select); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +zak_cgi_form_element_select_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + ZakCgiFormElementSelect *zak_cgi_form_element_select = (ZakCgiFormElementSelect *)object; + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (zak_cgi_form_element_select); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +zak_cgi_form_element_select_dispose (GObject *gobject) +{ + ZakCgiFormElementSelect *zak_cgi_form_element_select = (ZakCgiFormElementSelect *)gobject; + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (zak_cgi_form_element_select); + + + + GObjectClass *parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (gobject)); + parent_class->dispose (gobject); +} + +static void +zak_cgi_form_element_select_finalize (GObject *gobject) +{ + ZakCgiFormElementSelect *zak_cgi_form_element_select = (ZakCgiFormElementSelect *)gobject; + ZakCgiFormElementSelectPrivate *priv = ZAK_CGI_FORM_ELEMENT_SELECT_GET_PRIVATE (zak_cgi_form_element_select); + + + + GObjectClass *parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (gobject)); + parent_class->finalize (gobject); +} diff --git a/src/formelementselect.h b/src/formelementselect.h new file mode 100644 index 0000000..d7ae039 --- /dev/null +++ b/src/formelementselect.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2015 Andrea Zagli + * + * 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 __ZAK_CGI_FORM_ELEMENT_SELECT_H__ +#define __ZAK_CGI_FORM_ELEMENT_SELECT_H__ + + +#include + +#include "formelement.h" + + +G_BEGIN_DECLS + + +#define ZAK_CGI_TYPE_FORM_ELEMENT_SELECT (zak_cgi_form_element_select_get_type ()) +#define ZAK_CGI_FORM_ELEMENT_SELECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ZAK_CGI_TYPE_FORM_ELEMENT_SELECT, ZakCgiFormElementSelect)) +#define ZAK_CGI_FORM_ELEMENT_SELECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), ZAK_CGI_TYPE_FORM_ELEMENT_SELECT, ZakCgiFormElementSelectClass)) +#define ZAK_CGI_IS_FORM_ELEMENT_SELECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ZAK_CGI_TYPE_FORM_ELEMENT_SELECT)) +#define ZAK_CGI_IS_FORM_ELEMENT_SELECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ZAK_CGI_TYPE_FORM_ELEMENT_SELECT)) +#define ZAK_CGI_FORM_ELEMENT_SELECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), ZAK_CGI_TYPE_FORM_ELEMENT_SELECT, ZakCgiFormElementSelectClass)) + +typedef struct _ZakCgiFormElementSelect ZakCgiFormElementSelect; +typedef struct _ZakCgiFormElementSelectClass ZakCgiFormElementSelectClass; + +struct _ZakCgiFormElementSelect + { + ZakCgiFormElement parent_instance; + }; + +struct _ZakCgiFormElementSelectClass + { + ZakCgiFormElementClass parent_class; + }; + + +GType zak_cgi_form_element_select_get_type (void); + +ZakCgiFormElement *zak_cgi_form_element_select_new (const gchar *id, const gchar *validation_regex, ...); + +void zak_cgi_form_element_select_add_option (ZakCgiFormElementSelect *element, const gchar *value, const gchar *content, ...); + + +G_END_DECLS + + +#endif /* __ZAK_CGI_FORM_ELEMENT_SELECT_H__ */ diff --git a/tests/form.c b/tests/form.c index 9de748e..a0cbac9 100644 --- a/tests/form.c +++ b/tests/form.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,12 @@ main (int argc, char *argv[]) zak_cgi_form_element_set_label (element, "The text area", NULL); zak_cgi_form_add_element (form, element); + element = zak_cgi_form_element_select_new ("slc", NULL, NULL); + zak_cgi_form_element_select_add_option (ZAK_CGI_FORM_ELEMENT_SELECT (element), "1", "first", NULL); + zak_cgi_form_element_select_add_option (ZAK_CGI_FORM_ELEMENT_SELECT (element), "2", "second", NULL); + zak_cgi_form_element_select_add_option (ZAK_CGI_FORM_ELEMENT_SELECT (element), "3", "third", NULL); + zak_cgi_form_add_element (form, element); + element = zak_cgi_form_element_hidden_new ("hdn", "aaa", NULL); zak_cgi_form_add_element (form, element); -- 2.49.0