diff --git a/AUTHORS b/AUTHORS
index 8efb161..3374dca 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,3 @@
Alejandro Tomas Colombini Gomez
Juan Ferrer Toribio
Javier Gallego Ferris
-Jordi Cuquerella
diff --git a/Makefile.decl b/Makefile.decl
index 850631c..b801e0e 100644
--- a/Makefile.decl
+++ b/Makefile.decl
@@ -57,13 +57,13 @@ vn_datadir = $(hedera_datadir)/vn
vn_imagedir = $(vn_datadir)/image
vn_guidir = $(vn_datadir)/gui
+module_querydir = $(hedera_datadir)/module/sql
+
if ENABLE_INSTALL
vn_xmldir = $(datadir)/xml/$(PACKAGE)
- module_querydir = $(hedera_datadir)/module/sql
module_datadir = $(hedera_datadir)/module
else
vn_xmldir = $(vn_datadir)/schema
- module_querydir = $(hedera_datadir)/module/sql
module_datadir = $(hedera_datadir)/module/data
endif
diff --git a/build/m4/vn-dev.m4 b/build/m4/vn-dev.m4
new file mode 100644
index 0000000..abc1825
--- /dev/null
+++ b/build/m4/vn-dev.m4
@@ -0,0 +1,68 @@
+dnl
+dnl Copyright (C) 2012 - Juan Ferrer Toribio
+dnl
+dnl This program is free software: you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation, either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program. If not, see .
+dnl
+
+# serial 2 vn-dev
+
+AC_DEFUN([VN_BUILD_OPTIONS],
+[
+ case $CFLAGS in
+ *-W*) ;;
+ *)CFLAGS+=" -Wall ";;
+ esac
+
+ # Check for debug mode
+ AC_MSG_CHECKING([whether to build with debug information...])
+ AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug],
+ [Enable debug data generation [default = no]])],
+ [ENABLE_DEBUG="$enableval"],
+ [ENABLE_DEBUG=no])
+ AC_MSG_RESULT([$ENABLE_DEBUG])
+
+ case $CFLAGS in
+ *-g*) ;;
+ *)
+ if test x"$ENABLE_DEBUG" = x"yes"; then
+ CFLAGS+=" -ggdb "
+ fi
+ ;;
+ esac
+
+ # Check if the package must be configured to be installed
+ AC_MSG_CHECKING([whether to configure to install...])
+ AC_ARG_ENABLE([install],
+ [AS_HELP_STRING([--enable-install],
+ [Enable install configuration [default = yes]])],
+ [ENABLE_INSTALL="$enableval"],
+ [ENABLE_INSTALL=yes])
+ AC_MSG_RESULT([$installit])
+ AM_CONDITIONAL(ENABLE_INSTALL, [test x"$ENABLE_INSTALL" = x"yes"])
+
+ case $CFLAGS in
+ *-O*) ;;
+ *)
+ if test x"$ENABLE_INSTALL" = x"yes"; then
+ CFLAGS+=" -O3"
+ fi
+ ;;
+ esac
+
+ AC_SUBST([ENABLE_DEBUG])
+ AC_SUBST([ENABLE_INSTALL])
+ AC_SUBST([CFLAGS])
+])
+
diff --git a/configure.ac b/configure.ac
index d3454e2..5df77c7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,7 @@
AC_INIT([hedera], [1.0])
+dnl Set compiler flags empty by default
+: ${CFLAGS=''}
AC_CONFIG_AUX_DIR([build])
AC_CONFIG_MACRO_DIR([build/m4])
@@ -8,17 +10,32 @@ LT_INIT([dlopen])
AC_PREREQ([2.69])
AM_SILENT_RULES([yes])
-# Checks for programs
+# Checks for the C compiler
AC_PROG_CC
+# Check for additional packages
PKG_CHECK_MODULES([glib], [glib-2.0])
PKG_CHECK_MODULES([gdome], [gdome2])
PKG_CHECK_MODULES([gtk], [gtk+-3.0])
-PKG_CHECK_MODULES([gladeui], gladeui-2.0)
+PKG_CHECK_MODULES([gladeui], [gladeui-2.0])
+PKG_CHECK_MODULES([gtksourceview], [gtksourceview-3.0]
+ ,[SOURCEVIEW=yes]
+ ,[echo $gtksourceview_PKG_ERRORS])
+
+AM_CONDITIONAL(HAVE_SOURCEVIEW, [test -n $SOURCEVIEW])
GTK_DOC_CHECK([1.14],[--flavour no-tmpl])
+
+# Internationalization
IT_PROG_INTLTOOL([0.40.1], [no-xml])
+GETTEXT_PACKAGE=hedera
+AC_SUBST([GETTEXT_PACKAGE])
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [GETTEXT package name])
+ALL_LINGUAS="es ca nl"
+AM_GLIB_GNU_GETTEXT
+AM_XGETTEXT_OPTION([-k_ -kQ_:1g -kN_ -kC_:1c,2 -kNC_:1c,2])
+
# Checks for Ragel State Machine Compiler
AC_PATH_PROG(RAGEL, [ragel], [no])
if test x"$RAGEL" = x"no" ; then
@@ -49,51 +66,11 @@ fi
AM_CONDITIONAL(ENABLE_VALA, [test x"$ENABLE_VALA" = x"yes" -a x"$VAPIGEN" != x"no"])
-# Internationalization
-GETTEXT_PACKAGE=hedera
-AC_SUBST([GETTEXT_PACKAGE])
-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [GETTEXT package name])
-ALL_LINGUAS="es ca nl"
-AM_GLIB_GNU_GETTEXT
-AM_XGETTEXT_OPTION([-k_ -kQ_:1g -kN_ -kC_:1c,2 -kNC_:1c,2])
-
# GSettings configuration
GLIB_GSETTINGS
-CFLAGS=" -Wall"
-
-# Check for debug mode
-AC_MSG_CHECKING([whether to build with debug information...])
-AC_ARG_ENABLE([debug],
- [AS_HELP_STRING([--enable-debug],
- [Enable debug data generation [default = no]])],
- [ENABLE_DEBUG="$enableval"],
- [ENABLE_DEBUG=no])
-AC_MSG_RESULT([$ENABLE_DEBUG])
-
-if test x"$ENABLE_DEBUG" = x"yes"; then
- CFLAGS+=" -ggdb"
-fi
-
-# Check if it will be installed
-AC_MSG_CHECKING([whether to configure to install...])
-AC_ARG_ENABLE([install],
- [AS_HELP_STRING([--enable-install],
- [Enable install configuration [default = yes]])],
- [ENABLE_INSTALL="$enableval"],
- [ENABLE_INSTALL=yes])
-AC_MSG_RESULT([$installit])
-AM_CONDITIONAL(ENABLE_INSTALL, [test x"$ENABLE_INSTALL" = x"yes"])
-
-if test x"$ENABLE_INSTALL" = x"yes"; then
- CFLAGS+=" -O3"
-else
- CFLAGS+=" -O0"
-fi
-
-AC_SUBST([CPPFLAGS])
-AC_SUBST([CFLAGS])
-AC_SUBST([LDFLAGS])
+# Sets the default build options for Vn projects
+VN_BUILD_OPTIONS
# Portability check disabled for GTK-DOC (can be changed if needed)
AM_INIT_AUTOMAKE([-Wno-portability])
@@ -117,9 +94,9 @@ AC_CONFIG_FILES([
module/Makefile
module/src/Makefile
module/data/Makefile
- module/sql/Makefile
main/Makefile
main/vn-hedera.desktop
+ main/vn-hedera-debug.desktop
vapi/Makefile
glade/Makefile
docs/Makefile
diff --git a/db/db-conn.c b/db/db-conn.c
index cd9126e..b481f1a 100644
--- a/db/db-conn.c
+++ b/db/db-conn.c
@@ -239,7 +239,7 @@ static void db_conn_add_request (DbConn * obj, DbRequest * request)
* @plugin: the plugin name
* @err: return address of a #GError or #NULL
*
- * Tryes to load a plugin.
+ * Tries to load a plugin.
*
* Return vale: %TRUE if plugin was loaded successfully, %FALSE ortherwise
**/
@@ -892,14 +892,15 @@ SqlString * db_conn_create_stmt_from_file (DbConn * obj, const gchar * query_fil
g_return_val_if_fail (DB_IS_CONN (obj), NULL);
g_return_val_if_fail (query_file, NULL);
-
+
file = g_strconcat (query_file, ".sql", NULL);
-
- for (i = 0; obj->query_dirs &&obj->query_dirs[i] && !stmt; i++)
+
+ if (obj->query_dirs)
+ for (i = 0; obj->query_dirs[i] && !stmt; i++)
{
gchar * buffer;
gchar * path = g_build_filename (obj->query_dirs[i], file, NULL);
-
+
if (g_file_get_contents (path, &buffer, NULL, NULL))
{
stmt = sql_string_new (buffer);
@@ -908,9 +909,9 @@ SqlString * db_conn_create_stmt_from_file (DbConn * obj, const gchar * query_fil
g_free (path);
}
-
+
if (!stmt)
- g_warning ("DbConn: Can't create statement from file: %s", query_file);
+ g_warning ("DbConn: Can't create statement from file: %s", file);
g_free (file);
return stmt;
diff --git a/db/db-file-loader.c b/db/db-file-loader.c
index e2f62eb..0bf4cf3 100644
--- a/db/db-file-loader.c
+++ b/db/db-file-loader.c
@@ -565,7 +565,7 @@ static void db_file_loader_cancel (DbFileLoader * obj, const gchar * name)
g_hash_table_iter_init (&iter, obj->priv->downloading);
- while (g_hash_table_iter_next (&iter, (gpointer*) &file, NULL))
+ while (g_hash_table_iter_next (&iter, (gpointer *) &file, NULL))
if (!name || !g_strcmp0 (file->name, name))
{
g_cancellable_cancel (file->cancel);
diff --git a/db/db-iterator.c b/db/db-iterator.c
index 8585dbf..d984a93 100644
--- a/db/db-iterator.c
+++ b/db/db-iterator.c
@@ -16,6 +16,7 @@
*/
#include "db-iterator.h"
+#include "db-model-holder.h"
#define IS_READY(obj) (obj->model && db_model_get_status (obj->model) == DB_MODEL_STATUS_READY)
@@ -24,29 +25,16 @@
* @short_description: manages a iterator with its events
* @title: DbIterator
*
- * The DbIterator manages a connection with a data base.
- * There are different ways to create an DbIterator:
- *
- *
- *
- * db_iterator_new(): This constructor just needs a #DbModel object
- *
- *
- *
- *
- * db_iterator_new_with_stmt(): This one needs a #DbConn with the connection and
- * a #SqlStmt object
- *
- *
- *
- *
- * db_iterator_new_with_sql(): This one needs a #DbConn with the connection and
- * the sql string
- *
- *
- *
+ * The #DbIterator manages a connection with a data base. The function
+ * db_iterator_new() creates a new #DbIterator.
*/
-G_DEFINE_TYPE (DbIterator, db_iterator, G_TYPE_OBJECT);
+
+static void db_iterator_model_holder_interface_init (DbModelHolderInterface * iface);
+
+G_DEFINE_TYPE_WITH_CODE (DbIterator, db_iterator, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (DB_TYPE_MODEL_HOLDER,
+ db_iterator_model_holder_interface_init)
+);
enum {
ITER_CHANGED
@@ -72,48 +60,6 @@ DbIterator * db_iterator_new (DbModel * model)
return g_object_new (DB_TYPE_ITERATOR, "model", model, NULL);
}
-/**
- * db_iterator_new_with_stmt:
- * @conn: the connection used to create the model.
- * @stmt: the #SqlStmt statement used to create the model.
- *
- * Creates a new #DbIterator. #SqlStmt must be a #SqlSelect or a #SqlString
- * object with a valid SELECT statement.
- *
- * Return value: a #DbIterator.
- **/
-DbIterator * db_iterator_new_with_stmt (DbConn * conn, SqlStmt * stmt)
-{
- DbIterator * obj;
- DbModel * model;
-
- g_return_val_if_fail (DB_IS_CONN (conn) || !conn, NULL);
- g_return_val_if_fail (SQL_IS_STMT (stmt) || !stmt, NULL);
-
- model = db_model_new (conn, stmt);
- obj = g_object_new (DB_TYPE_ITERATOR, "model", model, NULL);
- g_object_unref (model);
-
- return obj;
-}
-
-/**
- * db_iterator_new_with_sql:
- * @conn: the connection used to create the model.
- * @sql: the sql string used to create the model.
- *
- * Creates a new #DbIterator. sql must be a valid SELECT statement.
- *
- * Return value: a #DbIterator.
- **/
-DbIterator * db_iterator_new_with_sql (DbConn * conn, const gchar * sql)
-{
- g_return_val_if_fail (sql, NULL);
- g_return_val_if_fail (DB_IS_CONN (conn) || !conn, NULL);
-
- return g_object_new (DB_TYPE_ITERATOR, "sql", sql, "conn", conn, NULL);
-}
-
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private
static void db_iterator_unref_param (DbIterator * obj, DbParam * param)
@@ -183,7 +129,7 @@ static void db_iterator_on_model_line_updated_after (DbModel * model, DbIter * i
* Function called when row is deleted on the model.
*/
static void db_iterator_on_model_line_deleted (DbModel * model, gint row, DbIterator * obj)
-{
+{
if (obj->row_selected && row == obj->row)
{
DbIter iter;
@@ -296,31 +242,6 @@ static gboolean db_iterator_check_row_selected (DbIterator * obj)
return FALSE;
}
-/*
- * Attempts to create a model, if have enough information, and assigns it to
- * the iterator.
- */
-static void db_iterator_try_create_model (DbIterator * obj)
-{
- DbModel * new_model = NULL;
-
- if (obj->conn)
- {
- if (obj->sql)
- {
- if (obj->use_file)
- new_model = db_model_new_with_file (obj->conn, obj->sql);
- else
- new_model = db_model_new_with_sql (obj->conn, obj->sql);
- }
- if (obj->stmt)
- new_model = db_model_new (obj->conn, obj->stmt);
- }
-
- if (new_model)
- db_iterator_set_model (obj, new_model);
-}
-
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public
/**
@@ -356,40 +277,6 @@ DbModel * db_iterator_get_model (DbIterator * obj)
return obj->model;
}
-/**
- * db_iterator_get_conn:
- * @obj: a #DbIterator
- *
- * Gets connection used by the @obj model.
- *
- * Return value: (transfer none): the #DbConn
- **/
-DbConn * db_iterator_get_conn (DbIterator * obj)
-{
- g_return_val_if_fail (DB_IS_ITERATOR (obj), NULL);
-
- if (obj->model)
- db_model_get_conn (obj->model);
-
- return NULL;
-}
-
-/**
- * db_iterator_set_conn:
- * @obj: a #DbIterator
- * @conn: the #DbConn
- *
- * Sets the connection used by the @obj model.
- **/
-void db_iterator_set_conn (DbIterator * obj, DbConn * conn)
-{
- g_return_if_fail (DB_IS_ITERATOR (obj));
- g_return_if_fail (DB_IS_CONN (conn));
- g_return_if_fail (obj->model);
-
- db_model_set_conn (obj->model, conn);
-}
-
/**
* db_iterator_is_ready:
* @obj: a #DbIterator
@@ -948,10 +835,6 @@ enum
PROP_MODEL = 1
,PROP_MODE
,PROP_REMEMBER_SELECTION
- ,PROP_CONN
- ,PROP_STMT
- ,PROP_SQL
- ,PROP_USE_FILE
};
static void db_iterator_set_property (DbIterator * obj, guint id,
@@ -968,25 +851,6 @@ static void db_iterator_set_property (DbIterator * obj, guint id,
case PROP_REMEMBER_SELECTION:
obj->remember_selection = g_value_get_boolean (value);
break;
- case PROP_CONN:
- g_clear_object (&obj->conn);
- obj->conn = g_value_dup_object (value);
- db_iterator_try_create_model (obj);
- break;
- case PROP_STMT:
- g_clear_object (&obj->stmt);
- obj->stmt = g_value_dup_object (value);
- db_iterator_try_create_model (obj);
- break;
- case PROP_SQL:
- g_free (obj->sql);
- obj->sql = g_value_dup_string (value);
- db_iterator_try_create_model (obj);
- break;
- case PROP_USE_FILE:
- obj->use_file = g_value_get_boolean (value);
- db_iterator_try_create_model (obj);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
}
@@ -1019,10 +883,6 @@ static void db_iterator_init (DbIterator * obj)
obj->params = NULL;
obj->row = 0;
obj->row_selected = FALSE;
- obj->conn = NULL;
- obj->stmt = NULL;
- obj->sql = NULL;
- obj->use_file = FALSE;
}
static void db_iterator_finalize (DbIterator * obj)
@@ -1049,10 +909,6 @@ static void db_iterator_finalize (DbIterator * obj)
);
g_object_unref (obj->model);
}
-
- g_clear_object (&obj->conn);
- g_clear_object (&obj->stmt);
- g_free (obj->sql);
G_OBJECT_CLASS (db_iterator_parent_class)->finalize (G_OBJECT (obj));
}
@@ -1064,34 +920,66 @@ static void db_iterator_class_init (DbIteratorClass * klass)
k->get_property = (GObjectGetPropertyFunc) db_iterator_get_property;
k->finalize = (GObjectFinalizeFunc) db_iterator_finalize;
+ /**
+ * DbIterator::iter-changed:
+ * @iterator: the object on which the signal is emitted
+ * @iter: a #DbIter
+ *
+ * This signal is emitted when @iter moves over the @iterator model
+ */
signals[ITER_CHANGED] = g_signal_new ("iter-changed",
DB_TYPE_ITERATOR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0
);
+
+ /**
+ * DbIterator::data-changed:
+ * @iterator: the object on which the signal is emitted
+ *
+ * This signal is emitted when the model changes its data
+ */
signals[DATA_CHANGED] = g_signal_new ("data-changed",
DB_TYPE_ITERATOR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0
);
+
+ /**
+ * DbIterator::row-num-changed:
+ * @iterator: the object on which the signal is emitted
+ *
+ * This signal is emitted when the selected row changes
+ */
signals[ROW_NUM_CHANGED] = g_signal_new ("row-num-changed",
DB_TYPE_ITERATOR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0
);
+
+ /**
+ * DbIterator::status-changed:
+ * @iterator: the object on which the signal is emitted
+ * @ready: #TRUE if @iterator is ready, #FALSE otherwise
+ *
+ * This signal is emitted when the status of the iterator changes
+ */
signals[STATUS_CHANGED] = g_signal_new ("status-changed",
DB_TYPE_ITERATOR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN
);
+
+ /**
+ * DbIterator::operations-done:
+ * @iterator: the object on which the signal is emitted
+ *
+ * This signal is emitted when all pending operations are performed over the
+ * model of @iterator
+ */
signals[OPERATIONS_DONE] = g_signal_new ("operations-done",
DB_TYPE_ITERATOR, G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0
);
- g_object_class_install_property (k, PROP_MODEL,
- g_param_spec_object ("model"
- ,_("Model")
- ,_("The DbModel handled by the iterator")
- ,DB_TYPE_MODEL
- ,G_PARAM_READWRITE
- ));
+ g_object_class_override_property (k, PROP_MODEL, "model");
+
g_object_class_install_property (k, PROP_MODE,
g_param_spec_enum ("mode"
,_("Mode")
@@ -1107,34 +995,12 @@ static void db_iterator_class_init (DbIteratorClass * klass)
,TRUE
,G_PARAM_CONSTRUCT | G_PARAM_READWRITE
));
- g_object_class_install_property (k, PROP_CONN,
- g_param_spec_object ("conn"
- ,_("Connection")
- ,_("The connection used by the model")
- ,DB_TYPE_CONN
- ,G_PARAM_WRITABLE
- ));
- g_object_class_install_property (k, PROP_STMT,
- g_param_spec_object ("stmt"
- ,_("Statement")
- ,_("The statement used to create the model")
- ,SQL_TYPE_STMT
- ,G_PARAM_WRITABLE
- ));
- g_object_class_install_property (k, PROP_SQL,
- g_param_spec_string ("sql"
- ,_("SQL")
- ,_("The SQL query used to create the model")
- , NULL
- ,G_PARAM_WRITABLE
- ));
- g_object_class_install_property (k, PROP_USE_FILE,
- g_param_spec_boolean ("use-file"
- ,_("Use file")
- ,_("Wether to interpret the sql property as query file")
- ,FALSE
- ,G_PARAM_CONSTRUCT | G_PARAM_WRITABLE
- ));
+}
+
+static void db_iterator_model_holder_interface_init (DbModelHolderInterface * iface)
+{
+ iface->get_model = (DbModelHolderGetModelFunc) db_iterator_get_model;
+ iface->set_model = (DbModelHolderSetModelFunc) db_iterator_set_model;
}
GType db_iterator_mode_get_type ()
diff --git a/db/db-iterator.h b/db/db-iterator.h
index d17a0ce..f39e963 100644
--- a/db/db-iterator.h
+++ b/db/db-iterator.h
@@ -81,11 +81,6 @@ struct _DbIterator
gint row;
gboolean row_selected;
gboolean remember_selection;
-
- DbConn * conn;
- SqlStmt * stmt;
- gchar * sql;
- gboolean use_file;
};
struct _DbIteratorClass
@@ -98,11 +93,6 @@ GType db_iterator_get_type ();
GType db_iterator_mode_get_type () G_GNUC_CONST;
DbIterator * db_iterator_new (DbModel * model);
-DbIterator * db_iterator_new_with_stmt (DbConn * conn, SqlStmt * stmt);
-DbIterator * db_iterator_new_with_sql (DbConn * conn, const gchar * sql);
-DbModel * db_iterator_get_model (DbIterator * obj);
-DbConn * db_iterator_get_conn (DbIterator * obj);
-void db_iterator_set_conn (DbIterator * obj, DbConn * conn);
gboolean db_iterator_is_ready (DbIterator * obj);
DbIteratorMode db_iterator_get_mode (DbIterator * obj);
void db_iterator_set_mode (DbIterator * obj, DbIteratorMode mode);
diff --git a/db/db-model-holder.c b/db/db-model-holder.c
index ef7db6e..bfc759f 100644
--- a/db/db-model-holder.c
+++ b/db/db-model-holder.c
@@ -19,15 +19,17 @@
/**
* SECTION: db-model-holder
- * @Short_description:
+ * @Short_description: interface for objects that use a model
* @Title: DbModelHolder
* @See_also: #DbModel
*
* This interface should be implemented from any class that uses a #DbModel as
- * datasource.
+ * data source. This interface offers a #DbModel as a virtual property that has
+ * to be overwritten by the classes implementing it, as well as the
+ * db_model_holder_get_model() and db_model_holder_set_model() methods.
**/
-G_DEFINE_INTERFACE (DbModelHolder, db_model_holder, G_TYPE_INTERFACE);
+G_DEFINE_INTERFACE (DbModelHolder, db_model_holder, G_TYPE_INVALID);
/**
* db_model_holder_get_model:
@@ -35,7 +37,7 @@ G_DEFINE_INTERFACE (DbModelHolder, db_model_holder, G_TYPE_INTERFACE);
*
* Gets the model used by holder.
*
- * Return value: the #DbModel
+ * Return value:(transfer none): the #DbModel
**/
DbModel * db_model_holder_get_model (DbModelHolder * obj)
{
@@ -45,7 +47,7 @@ DbModel * db_model_holder_get_model (DbModelHolder * obj)
}
/**
- * db_model_holder_get_model:
+ * db_model_holder_set_model:
* @obj: a #DbModelHolder
* @model: the #DbModel
*
@@ -54,18 +56,19 @@ DbModel * db_model_holder_get_model (DbModelHolder * obj)
void db_model_holder_set_model (DbModelHolder * obj, DbModel * model)
{
g_return_if_fail (DB_IS_MODEL_HOLDER (obj));
+ g_return_if_fail (DB_IS_MODEL (obj));
DB_MODEL_HOLDER_GET_INTERFACE (obj)->set_model (obj, model);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class
-static void db_model_holder_default_init (DbModelHolderInterface * klass)
-{
- g_object_interface_install_property (klass,
+static void db_model_holder_default_init (DbModelHolderInterface * iface)
+{
+ g_object_interface_install_property (iface,
g_param_spec_object ("model"
- ,"Model"
- ,"The model used by the holder"
+ ,_("Model")
+ ,_("The model used by the holder")
,DB_TYPE_MODEL
,G_PARAM_READWRITE
));
diff --git a/db/db-model-holder.h b/db/db-model-holder.h
index 1a475ea..99a5dba 100644
--- a/db/db-model-holder.h
+++ b/db/db-model-holder.h
@@ -15,34 +15,34 @@
* along with this program. If not, see .
*/
-#ifndef DB_MODEL_HOLDER_H
-#define DB_MODEL_HOLDER_H
+#ifndef DB_MODEL_HOLDER_H
+#define DB_MODEL_HOLDER_H
#include "db-model.h"
-
-#define DB_TYPE_MODEL_HOLDER (db_model_holder_get_type ())
-#define DB_MODEL_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DB_TYPE_MODEL_HOLDER, DbModelHolder))
-#define DB_IS_MODEL_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DB_TYPE_MODEL_HOLDER))
+
+#define DB_TYPE_MODEL_HOLDER (db_model_holder_get_type ())
+#define DB_MODEL_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DB_TYPE_MODEL_HOLDER, DbModelHolder))
+#define DB_IS_MODEL_HOLDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DB_TYPE_MODEL_HOLDER))
#define DB_MODEL_HOLDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), DB_TYPE_MODEL_HOLDER, DbModelHolderInterface))
-
-typedef struct _DbModelHolder DbModelHolder;
+
+typedef struct _DbModelHolder DbModelHolder;
typedef struct _DbModelHolderInterface DbModelHolderInterface;
typedef DbModel * (* DbModelHolderGetModelFunc) (DbModelHolder * obj);
typedef void (* DbModelHolderSetModelFunc) (DbModelHolder * obj, DbModel * sql);
-struct _DbModelHolder {};
-
-struct _DbModelHolderInterface
+struct _DbModelHolder;
+
+struct _DbModelHolderInterface
{
- /* */
+ /* */
GTypeInterface parent;
DbModelHolderGetModelFunc get_model;
DbModelHolderSetModelFunc set_model;
-};
-
+};
+
GType db_model_holder_get_type ();
DbModel * db_model_holder_get_model (DbModelHolder * obj);
void db_model_holder_set_model (DbModelHolder * obj, DbModel * model);
-
-#endif
\ No newline at end of file
+
+#endif
diff --git a/db/db-model.c b/db/db-model.c
index 912eb4d..f8a4c3a 100644
--- a/db/db-model.c
+++ b/db/db-model.c
@@ -25,11 +25,11 @@
* SECTION: db-model
* @Short_description: data vinculed to a SELECT query sent to the database
* @Title: DbModel
- * @See_also: #DbIterator, #DbConn
+ * @See_also: #DbConn, #DbModelHolder
*
* The #DbModel class gets an SQL query statement to retrieve the data from the
- * database connected by a #DbConn. It is normally used undirectly, using instead
- * #DbForm.
+ * database connected by a #DbConn. It is normally used undirectly, using
+ * a #DbIterator or another #DbModelHolder instead.
**/
/*
@@ -60,6 +60,7 @@ struct _DbModelPrivate
GHashTable * row_ops;
gint updated_col;
GValue * updated_value;
+ DbRow * null_row;
GHashTable * column_index;
GSList * pending_request;
@@ -93,8 +94,8 @@ G_DEFINE_TYPE (DbModel, db_model, G_TYPE_OBJECT)
/**
* db_model_new:
- * @conn: a #DbConn
- * @stmt: an #SqlStmt
+ * @conn:(allow-none): a #DbConn
+ * @stmt:(allow-none): an #SqlStmt
*
* Returns the newly created #DbModel, filled with the data retrieved from the
* database with @stmt and through @conn.
@@ -108,7 +109,7 @@ DbModel * db_model_new (DbConn * conn, SqlStmt * stmt)
/**
* db_model_new_with_sql:
- * @conn: a #DbConn
+ * @conn:(allow-none): a #DbConn
* @sql: a string containing an SQL statement
*
* Returns the newly created #DbModel, filled with the data retrieved from the
@@ -124,7 +125,7 @@ DbModel * db_model_new_with_sql (DbConn * conn, const gchar * sql)
/**
* db_model_new_with_file:
- * @conn: a #DbConn
+ * @conn:(allow-none): a #DbConn
* @file: the path to the file containing the SQL query to fill the model
*
* Returns a newly created #DbModel, filled with the data retrieved from @file.
@@ -238,6 +239,14 @@ typedef struct
}
DbModelPKey;
+typedef struct
+{
+ gint col;
+ gint order;
+ DbRow * null_row;
+}
+SortInfo;
+
enum
{
DB_MODEL_UNSORTED_SORT_COLUMN_ID = -2,
@@ -387,7 +396,7 @@ static void db_model_on_data_ready (DbRequest * request, DbModel * obj)
for (i = 0; i < priv->result->ncols; i++)
{
- // Set fields editable if *all* primary keys are selected FIXME
+ //FIXME Set fields editable iff ALL primary keys are selected
if (priv->column[i].info & DB_COLUMN_PRI_KEY
&& !g_slist_find_custom (t, priv->column[i].table, (GCompareFunc) g_strcmp0))
for (j = 0; j < priv->result->ncols; j++)
@@ -709,7 +718,7 @@ static gboolean db_model_set_row_operation (DbModel * obj,
// if (!db_operation_add_updated (op, col))
// return FALSE;
}
- else
+ else
return FALSE;
return TRUE;
@@ -940,7 +949,7 @@ static void db_model_set_join_fields (DbModel * obj, SqlJoin * join,
static void db_model_post_process_query (DbModel * obj)
{
// TODO When parser gets fully functional, these 3 lines won't be needed,
-// because obj->stmt will be a parsed stmt:
+// because obj>priv->stmt will be a parsed stmt:
gchar * rend = db_conn_render (obj->priv->conn, obj->priv->stmt, NULL);
SqlObject * stmt = sql_parser_parse (rend);
/*gchar * rend2 = NULL;
@@ -953,11 +962,11 @@ g_free (rend2);*/
{
DbModelField * lfield, * rfield;
SqlJoin * join;
- GList * n;
+ GSList * n;
SqlSelect * select = SQL_SELECT (stmt);
gboolean calculate_join = FALSE;
- for (n = sql_list_get_items (SQL_DML (select)->targets); n; n = n->next)
+ for (n = SQL_DML (select)->target; n; n = n->next)
if ((join = n->data)
&& SQL_IS_JOIN (join)
&& SQL_IS_TABLE (join->target_left)
@@ -965,7 +974,6 @@ g_free (rend2);*/
&& SQL_IS_OPERATION (join->condition))
{
// DbJoin and ColDef creation
- GList * operators;
SqlOperation * op = SQL_OPERATION (join->condition);
SqlField * lsql_field = NULL, * rsql_field = NULL;
@@ -979,20 +987,19 @@ g_free (rend2);*/
if (op->type == SQL_OPERATION_TYPE_AND)
{
- GList * l;
+ GSList * l;
- for (l = sql_list_get_items (op->operators); l; l = l->next)
+ for (l = op->expr; l; l = l->next)
{
SqlOperation * subop;
- operators = sql_list_get_items (subop->operators);
if (SQL_IS_OPERATION (subop = l->data)
&& subop->type == SQL_OPERATION_TYPE_EQUAL
- && operators->data // Left Field
- && operators->next && operators->next->data) // Right Field
+ && subop->expr->data // Left Field
+ && subop->expr->next && subop->expr->next->data) // Right Field
{
- lsql_field = SQL_FIELD (operators->data);
- rsql_field = SQL_FIELD (operators->next->data);
+ lsql_field = SQL_FIELD (subop->expr->data);
+ rsql_field = SQL_FIELD (subop->expr->next->data);
db_model_set_join_fields (obj, join,
lsql_field, rsql_field, lfield, rfield);
@@ -1010,25 +1017,20 @@ g_free (rend2);*/
}
}
}
- else
+ else if (op->type == SQL_OPERATION_TYPE_EQUAL && op->expr->data
+ && op->expr->next && op->expr->next->data)
{
- operators = sql_list_get_items (op->operators);
+ lsql_field = SQL_FIELD (op->expr->data);
+ rsql_field = SQL_FIELD (op->expr->next->data);
- if (op->type == SQL_OPERATION_TYPE_EQUAL && operators->data
- && operators->next && operators->next->data)
- {
- lsql_field = SQL_FIELD (operators->data);
- rsql_field = SQL_FIELD (operators->next->data);
+ db_model_set_join_fields (obj, join,
+ lsql_field, rsql_field, lfield, rfield);
- db_model_set_join_fields (obj, join,
- lsql_field, rsql_field, lfield, rfield);
+ calculate_join = TRUE;
- calculate_join = TRUE;
-
- if (join->type != SQL_JOIN_TYPE_INNER)
- db_model_calculate_col_def
- (obj, join ,lsql_field, rsql_field);
- }
+ if (join->type != SQL_JOIN_TYPE_INNER)
+ db_model_calculate_col_def
+ (obj, join ,lsql_field, rsql_field);
}
if (calculate_join)
@@ -1140,7 +1142,10 @@ static gint db_model_value_compare0 (const GValue * a, const GValue * b)
{
gchar * a_str = g_utf8_casefold (g_value_get_string (a), -1);
gchar * b_str = g_utf8_casefold (g_value_get_string (b), -1);
- return g_utf8_collate (a_str, b_str);
+ gint res = g_utf8_collate (a_str, b_str);
+ g_free (a_str);
+ g_free (b_str);
+ return res;
}
default:
if (a_type == G_TYPE_DATE)
@@ -1164,21 +1169,24 @@ static gint db_model_value_compare0 (const GValue * a, const GValue * b)
return 1;
}
-static gint db_model_valcmp_asc (gpointer * a, gpointer * b, gpointer col)
+static inline gint db_model_valcmp (gpointer * a, gpointer * b, SortInfo * info)
{
+ gint order;
DbRow * first = *a;
DbRow * second = *b;
- return db_model_value_compare0 (&first->value[GPOINTER_TO_INT (col)]
- ,&second->value[GPOINTER_TO_INT (col)]);
-}
-static gint db_model_valcmp_desc (gpointer * a, gpointer * b, gpointer col)
-{
- DbRow * first = *a;
- DbRow * second = *b;
- return -db_model_value_compare0 (&(first->value)[GPOINTER_TO_INT (col)]
- ,&(second->value)[GPOINTER_TO_INT (col)]);
+ if (first == info->null_row)
+ order = -1;
+ else if (second == info->null_row)
+ order = 1;
+ else
+ {
+ gint dir = info->order == DB_SORT_ASCENDING ? 1 : -1;
+ order = dir * db_model_value_compare0 (&first->value[info->col]
+ ,&second->value[info->col]);
+ }
+ return order;
}
static void db_model_set_status (DbModel * obj, DbModelStatus status)
@@ -1206,19 +1214,19 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col)
DbModelPrivate * priv = obj->priv;
if (priv->join
- && gvn_param_spec_get_editable (priv->column[col].spec)
- && !gvn_value_is_null (DB_ROW_FIELD (iter->data, col)))
+ && gvn_param_spec_get_editable (priv->column[col].spec))
+// && !gvn_value_is_null (DB_ROW_FIELD (iter->data, col))))XXX WHY WAS THIS HERE? it IS tested in set_value
{
gint i;
GSList * n;
gboolean send_request = FALSE, end = FALSE;
- SqlList * stmts = g_object_ref_sink (sql_list_new (SQL_TYPE_MULTI_STMT));
-
+ SqlMultiStmt * multi_stmt = sql_multi_stmt_new ();
/*FIXME
for (i = 0; i < obj->ncols; i++)
// Check for multi-field pkeys to be fully set
// need to know the total number of pkey fields
- if (i != col && obj->column[i].info & DB_COLUMN_PRI_KEY
+ if (i != col
+ && obj->column[i].info & DB_COLUMN_PRI_KEY
&& gvn_value_is_null (DB_ROW_FIELD (iter->data, i))
&& !g_strcmp0 (obj->column[i].table, obj->column[col].table))
{
@@ -1230,9 +1238,10 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col)
for (n = priv->join; n; n = n->next)
{
gint j;
- SqlObject * where, * select;
+ SqlSelect * select;
+ SqlOperation * where;
DbModelField * main_field = NULL, * other_field = NULL;
- DbJoin * join = n->data;
+ DbJoin * join = (DbJoin *) n->data;
if (join->left->main)
{
@@ -1257,39 +1266,38 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col)
if (!send_request)
continue; // Continue to the next DbJoin in the list
- select = sql_select_new ();
-
- sql_object_add_child (select, "targets", sql_table_new (other_field->table));
-
- where = sql_operation_new (SQL_OPERATION_TYPE_AND);
+ select = sql_select_new ();
+ sql_dml_add_target (SQL_DML (select),
+ sql_table_new (other_field->table));
+ where = sql_operation_new (SQL_OPERATION_TYPE_AND);
for (i = 0; i < priv->result->ncols; i++)
if (!g_strcmp0 (priv->column[i].table, other_field->table))
- {
- sql_object_add_child (select, "exprs",
- sql_field_new (priv->column[i].name, other_field->table, NULL));
- }
+ sql_select_add_expr (select, sql_field_new
+ (priv->column[i].name, other_field->table, NULL));
else if (!g_strcmp0 (priv->column[i].table, main_field->table))
- {
- for (j = 0; j < main_field->name->len; j++)
+ for (j = 0; j < main_field->name->len; j++)
if (!g_strcmp0 (priv->column[i].name,
- g_ptr_array_index (main_field->name, j)))
+ g_ptr_array_index (main_field->name, j)))
{
- SqlObject * equal = sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
+ SqlOperation * equal =
+ sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
- sql_object_add_child (equal, "operators",
- sql_field_new (g_ptr_array_index (other_field->name, j)
- ,other_field->table, NULL));
+ sql_operation_add_expr (equal, sql_field_new
+ (g_ptr_array_index (other_field->name, j)
+ ,other_field->table, NULL
+ ));
- sql_object_add_child (equal, "operators",
- sql_value_new_with_value (DB_ROW_FIELD (iter->data, i)));
+ sql_operation_add_expr (equal,
+ sql_value_new_with_value
+ (DB_ROW_FIELD (iter->data, i)));
- sql_object_add_child (where, "operators", equal);
+ sql_operation_add_expr (where, SQL_EXPR (equal));
}
- }
- sql_object_set (select, "where", where);
- sql_list_add (stmts, select);
+ sql_dml_set_where (SQL_DML (select), SQL_EXPR (where));
+
+ sql_multi_stmt_add_stmt (multi_stmt, SQL_STMT (select));
}
if (send_request)
@@ -1303,7 +1311,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col)
join_data->col = col;
request = db_conn_query_with_stmt_async (priv->conn
- ,g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL)
+ ,SQL_STMT (multi_stmt)
,(DbRequestDoneCallback) db_model_on_join_query_done
,join_data
,(GDestroyNotify) join_data_free
@@ -1311,7 +1319,7 @@ static void db_model_manage_join (DbModel * obj, DbIter * iter, gint col)
db_model_add_pending_request (obj, request);
}
- g_object_unref (stmts);
+ g_object_unref (multi_stmt);
}
}
@@ -1367,7 +1375,9 @@ static void db_model_clear (DbModel * obj)
priv->result = NULL;
priv->column = NULL;
priv->data = NULL;
-
+
+ priv->null_row = NULL;
+
g_free (priv->main_table);
priv->main_table = NULL;
priv->update_flags = 0;
@@ -1428,15 +1438,23 @@ static gboolean db_model_table_row_all_null (DbModel * obj, DbRow * row, gint co
**/
void db_model_set_conn (DbModel * obj, DbConn * conn)
{
+ DbModelPrivate * priv;
+
g_return_if_fail (DB_IS_MODEL (obj));
g_return_if_fail (DB_IS_CONN (conn) || !conn);
+ priv = obj->priv;
+
if (conn)
{
- if (!obj->priv->conn)
+ if (!priv->conn)
{
- obj->priv->conn = g_object_ref (conn);
- db_model_on_stmt_changed (obj->priv->stmt, obj);
+ priv->conn = g_object_ref (conn);
+
+ if (priv->use_file && priv->sql)
+ priv->stmt = SQL_STMT (db_conn_create_stmt_from_file (conn, priv->sql));
+
+ db_model_on_stmt_changed (priv->stmt, obj);
}
else
g_warning ("DbModel: The connection can only be set once");
@@ -1459,6 +1477,71 @@ DbConn * db_model_get_conn (DbModel * obj)
return obj->priv->conn;
}
+/**
+ * db_model_set_sql:
+ * @obj: a #DbModel
+ * @sql: a value for the "sql property
+ *
+ * Sets the "sql" property to @sql.
+ **/
+void db_model_set_sql (DbModel * obj, const gchar * sql)
+{
+ SqlString * string = NULL;
+
+ if (!sql)
+ return;
+
+ g_return_if_fail (DB_IS_MODEL (obj));
+
+ g_free (obj->priv->sql);
+ obj->priv->sql = g_strdup (sql);
+
+ if (obj->priv->use_file)
+ {
+ if (obj->priv->conn)
+ string = db_conn_create_stmt_from_file (obj->priv->conn, sql);
+ }
+ else
+ string = sql_string_new (sql);
+
+ db_model_set_stmt (obj, SQL_STMT (string));
+}
+
+/**
+ * db_model_set_stmt:
+ * @obj: a #DbModel
+ * @stmt: the #SqlStmt
+ *
+ * Sets the "stmt" property of the model.
+ **/
+void db_model_set_stmt (DbModel * obj, SqlStmt * stmt)
+{
+ if (!stmt)
+ return;
+
+ g_return_if_fail (!obj->priv->stmt);
+ g_return_if_fail (SQL_IS_STRING (stmt) || SQL_IS_SELECT (stmt));
+
+ obj->priv->stmt = g_object_ref_sink (stmt);
+ g_signal_connect (stmt, "changed", G_CALLBACK (db_model_on_stmt_changed), obj);
+ db_model_on_stmt_changed (stmt, obj);
+}
+
+/**
+ * db_model_get_stmt:
+ * @obj: a #DbModel
+ *
+ * Returns the #SqlStmt which queries to the database about the data of @obj.
+ *
+ * Return value: (transfer none): the #SqlStmt property of @obj
+ **/
+const SqlStmt * db_model_get_stmt (DbModel * obj)
+{
+ g_return_val_if_fail (DB_IS_MODEL (obj), NULL);
+
+ return obj->priv->stmt;
+}
+
/**
* db_model_get_spec:
* @obj: a #DbModel
@@ -1713,27 +1796,27 @@ void db_model_set_default_value_from_column (DbModel * obj,
* @obj: a #DbModel
* @dst_field: the field to be set
* @param: a #GvnParam
- * @id: an identifier string for @param
*
- * Get the default value for @dst_field from @param.
+ *
**/
void db_model_set_default_value_from_param (DbModel * obj,
- const gchar * dst_field, GvnParam * param, const gchar * id)
+ const gchar * dst_field, GvnParam * param)
{
- SqlObject * op, * value;
+ SqlExpr * value;
+ SqlOperation * op;
g_return_if_fail (DB_IS_MODEL (obj));
g_return_if_fail (GVN_IS_PARAM (param));
g_return_if_fail (dst_field);
op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
- sql_object_add_child (op, "operators", sql_field_new (dst_field, NULL, NULL));
+ sql_operation_add_expr (op, sql_field_new (dst_field, NULL, NULL));
value = sql_value_new ();
sql_value_set_param (SQL_VALUE (value), param);
- sql_object_add_child (op, "operators", value);
+ sql_operation_add_expr (op, value);
- sql_object_add_held_object (SQL_OBJECT (obj->priv->stmt), id, op);
+ sql_string_add_expr (SQL_STRING (obj->priv->stmt), SQL_EXPR (op));
DbParamDef * def = g_new (DbParamDef, 1);
def->dst = g_strdup (dst_field);
@@ -1745,17 +1828,16 @@ void db_model_set_default_value_from_param (DbModel * obj,
/**
* db_model_add_param:
* @obj: a #DbModel
- * @id: an identifier string for @param
* @param: the #GvnParam to add
*
* Links the statement in the model to @param.
**/
-void db_model_add_param (DbModel * obj, const gchar * id, GvnParam * param)
+void db_model_add_param (DbModel * obj, GvnParam * param)
{
g_return_if_fail (DB_IS_MODEL (obj));
g_return_if_fail (GVN_IS_PARAM (param));
- sql_string_add_param (SQL_STRING (obj->priv->stmt), id, param);
+ sql_string_add_param (SQL_STRING (obj->priv->stmt), param);
}
/**
@@ -1795,68 +1877,6 @@ const gchar * db_model_get_main_table (DbModel * obj)
return obj->priv->main_table;
}
-/**
- * db_model_get_stmt:
- * @obj: a #DbModel
- *
- * Returns the #SqlStmt which queries to the database about the data of @obj.
- *
- * Return value: (transfer none): the #SqlStmt property of @obj
- **/
-const SqlStmt * db_model_get_stmt (DbModel * obj)
-{
- g_return_val_if_fail (DB_IS_MODEL (obj), NULL);
-
- return obj->priv->stmt;
-}
-
-/**
- * db_model_set_stmt:
- * @obj: a #DbModel
- * @stmt: the #SqlStmt
- *
- * Sets the "stmt" property of the model.
- **/
-void db_model_set_stmt (DbModel * obj, SqlStmt * stmt)
-{
- if (!stmt)
- return;
-
- g_return_if_fail (!obj->priv->stmt);
- g_return_if_fail (SQL_IS_STRING (stmt) || SQL_IS_SELECT (stmt));
-
- obj->priv->stmt = g_object_ref_sink (stmt);
- g_signal_connect (stmt, "changed", G_CALLBACK (db_model_on_stmt_changed), obj);
- db_model_on_stmt_changed (stmt, obj);
-}
-
-/**
- * db_model_set_sql:
- * @obj: a #DbModel
- * @sql: a value for the "sql property
- *
- * Sets the "sql" property to @sql.
- **/
-void db_model_set_sql (DbModel * obj, const gchar * sql)
-{
- SqlString * string;
-
- if (!sql)
- return;
-
- g_return_if_fail (DB_IS_MODEL (obj));
-
- g_free (obj->priv->sql);
- obj->priv->sql = g_strdup (sql);
-
- if (obj->priv->use_file)
- string = db_conn_create_stmt_from_file (obj->priv->conn, sql);
- else
- string = sql_string_new (sql);
-
- db_model_set_stmt (obj, SQL_STMT (string));
-}
-
/**
* db_model_get:
* @obj: a #DbModel
@@ -1939,6 +1959,9 @@ void db_model_set (DbModel * obj, DbIter * iter, ...)
g_return_if_fail (DB_IS_MODEL (obj));
g_return_if_fail (obj->priv->result);
g_return_if_fail (iter != NULL);
+
+ if (iter->data == obj->priv->null_row)
+ return;
va_start (va, iter);
@@ -2025,14 +2048,19 @@ gboolean db_model_set_value (DbModel * obj, DbIter * iter, gint col, const GValu
}
else
{
- g_return_val_if_fail (0 <= col && col < priv->result->ncols, FALSE);
-
GValue new_value = {0};
DbRow * row = iter->data;
DbOperation * operation = g_hash_table_lookup (priv->row_ops, row);
DbModelRowOp row_op = operation ? operation->type : 0;
GvnParamSpec * spec = priv->column[col].spec;
+ g_return_val_if_fail (0 <= col && col < priv->result->ncols, FALSE);
+
+ if (iter->data == obj->priv->null_row)
+ {
+ return FALSE;
+ }
+
if (!gvn_param_spec_validate (spec, value, err))
{
return FALSE;
@@ -2131,7 +2159,7 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter)
DbParamDef * param_def = p->data;
if (!g_strcmp0 (param_def->dst, priv->column[i].name))
- {
+ {
def = gvn_param_get_value (param_def->param);
g_value_init (&row->value[i], G_VALUE_TYPE (def));
gvn_value_copy (def, &row->value[i]);
@@ -2139,7 +2167,17 @@ gboolean db_model_insert (DbModel * obj, DbIter * iter)
}
if (!def)
- g_value_init (&row->value[i], GVN_TYPE_NULL);
+ {
+ def = gvn_param_spec_get_default (priv->column[i].spec);
+
+ if (def && G_VALUE_TYPE (def) != SQL_TYPE_FUNCTION)
+ {
+ g_value_init (&row->value[i], G_VALUE_TYPE (def));
+ gvn_value_copy (def, &row->value[i]);
+ }
+ else
+ g_value_init (&row->value[i], GVN_TYPE_NULL);
+ }
}
g_ptr_array_add (priv->data, row);
@@ -2183,8 +2221,11 @@ void db_model_delete (DbModel * obj, DbIter * iter)
return;
}
- if (!db_model_set_row_operation
- (obj, g_ptr_array_index (obj->priv->data, DB_ROW_POSITION (iter->data)),
+ if (iter->data == obj->priv->null_row)
+ return;
+
+ if (!db_model_set_row_operation (obj,
+ g_ptr_array_index (obj->priv->data, DB_ROW_POSITION (iter->data)),
DB_MODEL_ROW_OP_DELETE, 0))
return;
@@ -2194,6 +2235,68 @@ void db_model_delete (DbModel * obj, DbIter * iter)
db_model_perform_operations (obj, FALSE);
}
+/**
+ * db_model_use_null_row:
+ * @obj: a #DbModel
+ * @use: wether to use a null row
+ *
+ * Sets wether to use a null row at the end of the model. This row can't be
+ * modified by the methods @db_model_delete or @db_model_set_value, the only way
+ * to remove it is to call @db_model_use_null_row again passing #FALSE.
+ **/
+void db_model_use_null_row (DbModel * obj, gboolean use)
+{
+ DbModelPrivate * priv;
+
+ g_return_if_fail (DB_IS_MODEL (obj));
+
+ priv = obj->priv;
+
+ if (MODEL_NOT_READY(obj) || !priv->result
+ || ((priv->null_row != NULL) == use))
+ return;
+
+ if (use)
+ {
+ if (!priv->null_row)
+ {
+ gint i;
+ DbIter iter;
+ DbModelPrivate * priv = obj->priv;
+ DbRow * curr, * row = db_row_new (priv->result->ncols, 0);
+ gpointer * data = priv->data->pdata;
+
+ for (i = 0; i < row->len; i++)
+ g_value_init (&row->value[i], GVN_TYPE_NULL);
+
+ priv->null_row = row;
+ iter.data = row;
+ iter.stamp = priv->stamp;
+
+ priv->result->nrows++;
+ g_ptr_array_set_size (priv->data, priv->result->nrows);
+ curr = data[0];
+ data[0] = row;
+
+ for (i = 1; i < priv->result->nrows; i++)
+ {
+ DbRow * next = data[i];
+ DB_ROW_POSITION (curr)++;
+ data[i] = curr;
+ curr = next;
+ }
+
+ g_signal_emit (obj, db_model_signal[LINE_INSERTED], 0, &iter);
+ }
+ }
+ else if (priv->null_row)
+ {
+ g_signal_emit (obj, db_model_signal[LINE_DELETED], 0,
+ DB_ROW_POSITION (priv->null_row));
+ priv->null_row = NULL;
+ }
+}
+
/**
* db_model_order_by:
* @obj: a #DbModel
@@ -2206,6 +2309,7 @@ void db_model_delete (DbModel * obj, DbIter * iter)
void db_model_order_by (DbModel * obj, gint col, DbSortType order)
{
DbModelPrivate * priv;
+ SortInfo info;
g_return_if_fail (DB_IS_MODEL (obj));
priv = obj->priv;
g_return_if_fail (priv->result && col >= -2 && col < priv->result->ncols);
@@ -2217,8 +2321,8 @@ void db_model_order_by (DbModel * obj, gint col, DbSortType order)
gint r_ind, i = 0;
if ((priv->order == order && priv->sort_column_id == col)
- || !priv->data
- || col == DB_MODEL_UNSORTED_SORT_COLUMN_ID)
+ || !priv->data
+ || col == DB_MODEL_UNSORTED_SORT_COLUMN_ID)
return;
if (col == DB_MODEL_DEFAULT_SORT_COLUMN_ID
@@ -2229,14 +2333,13 @@ void db_model_order_by (DbModel * obj, gint col, DbSortType order)
priv->sort_column_id = col;
g_signal_emit (obj, db_model_signal[SORT_CHANGED], 0, NULL);
- if (order == DB_SORT_DESCENDING)
- g_ptr_array_sort_with_data (priv->data
- ,(GCompareDataFunc) db_model_valcmp_desc
- ,GINT_TO_POINTER (col));
- else
- g_ptr_array_sort_with_data (priv->data
- ,(GCompareDataFunc) db_model_valcmp_asc
- ,GINT_TO_POINTER (col));
+ info.col = col;
+ info.null_row = priv->null_row;
+ info.order = order;
+
+ g_ptr_array_sort_with_data (priv->data
+ ,(GCompareDataFunc) db_model_valcmp
+ ,&info);
for (r_ind = 0; r_ind < priv->result->nrows; r_ind++)
{
@@ -2376,13 +2479,12 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
gint i;
DbRow * row;
DbOperation * op_elem;
- GList * l = NULL;
GSList * sl = NULL;
- SqlObject * multi = NULL,
- * equal_op, * val = NULL,
- * insert, * set,
- * select, * where = NULL;
- SqlList * stmts;
+ SqlOperation * op = NULL,
+ * equal_op;
+ SqlExpr * val = NULL;
+ SqlSelect * select;
+ SqlMultiStmt * multi;
DbRequest * request;
GQueue * req_ops = NULL;
@@ -2403,7 +2505,7 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
if (priv->operation->length > 1)
transaction = TRUE;
- stmts = sql_list_new (SQL_TYPE_STMT);
+ multi = sql_multi_stmt_new ();
while ((op_elem = g_queue_pop_head (priv->operation)))
{
@@ -2423,65 +2525,66 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
if (!transaction)
{
- g_object_unref (stmts);
- stmts = NULL;
+ g_object_unref (multi);
+ multi = NULL;
}
}
else
{
- SqlObject * delete = sql_delete_new ();
- sql_object_add_child (delete, "targets",
- sql_table_new (priv->main_table, NULL));
+ SqlDelete * delete = sql_delete_new ();
- where = sql_operation_new (SQL_OPERATION_TYPE_AND);
+ sql_dml_add_target
+ (SQL_DML (delete), sql_table_new (priv->main_table));
+
+ op = sql_operation_new (SQL_OPERATION_TYPE_AND);
DbModelPKey * pkey =
db_model_get_primary_key (obj, priv->main_table);
for (i = 0; i < pkey->count; i++)
{
- equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
+ equal_op =
+ SQL_OPERATION (sql_operation_new (SQL_OPERATION_TYPE_EQUAL));
- sql_object_add_child (equal_op, "operators",
+ sql_operation_add_expr (equal_op,
sql_field_new (priv->column[pkey->index[i]].name, NULL, NULL));
- sql_object_add_child (equal_op, "operators",
- sql_value_new_with_value (&row->value[pkey->index[i]]));
- sql_object_add_child (where, "operators", equal_op);
+ sql_operation_add_expr (equal_op,
+ sql_value_new_with_value (&row->value[pkey->index[i]]));
+ sql_operation_add_expr (op, SQL_EXPR (equal_op));
}
db_model_pkey_free (pkey);
- sql_object_set (delete, "where", where);
-
- sql_list_add (stmts, delete);
+ sql_dml_set_where (SQL_DML (delete), SQL_EXPR (op));
+ sql_multi_stmt_add_stmt (multi, SQL_STMT (delete));
render_ops = TRUE;
}
}
else if (op_elem->type & DB_MODEL_ROW_OP_INSERT) // INSERT
{
- SqlObject * target = sql_table_new (priv->main_table);
+ SqlInsert * insert;
+ SqlTarget * table = sql_table_new (priv->main_table);
- insert = g_object_new (SQL_TYPE_INSERT, "table", target, NULL);
- set = g_object_new (SQL_TYPE_SET, NULL);
- sql_object_add_child (insert, "values", set);
+ insert = sql_insert_new ();
+ sql_insert_add_row (insert);
+ sql_insert_set_table (insert, SQL_TABLE (table));
select = sql_select_new ();
- sql_object_add_child (select, "targets", target);
- where = sql_operation_new (SQL_OPERATION_TYPE_AND);
+ sql_dml_add_target (SQL_DML (select), table);
+
+ op = sql_operation_new (SQL_OPERATION_TYPE_AND);
for (i = 0; i < row->len; i++)
if (!g_strcmp0 (priv->column[i].table, priv->main_table))
{
gboolean cont = FALSE;
- SqlObject * field = NULL;
+ SqlExpr * field;
- l = sql_list_get_items (SQL_INSERT (insert)->fields);
-
- for (; l; l = l->next)
- if (!g_strcmp0 (((SqlField*) l->data)->name, priv->column[i].name)
- && ((!((SqlField*) l->data)->target)
- || !g_strcmp0 (((SqlField*) l->data)->target, priv->column[i].table)))
+ for (sl = insert->field; sl; sl = sl->next)
+ if (!g_strcmp0 (((SqlField*) sl->data)->name, priv->column[i].name)
+ && ((!((SqlField*) sl->data)->target)
+ || !g_strcmp0 (((SqlField*) sl->data)->target, priv->column[i].table)))
{
cont = TRUE;
break;
@@ -2490,26 +2593,26 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
if (cont)
continue;
+ field = sql_field_new (priv->column[i].name, NULL, NULL);
+ sql_insert_add_field (insert, SQL_FIELD (field));
+
val = sql_value_new_with_value (&row->value[i]);
+ sql_insert_add_expr (insert,
+ gvn_value_is_null (&row->value[i]) ? NULL : val);
- sql_object_add_child (insert, "fields",
- sql_field_new (priv->column[i].name, NULL, NULL));
- sql_object_add_child (set,
- "exprs", gvn_value_is_null (&row->value[i]) ? NULL : val);
-
- sql_object_add_child (select, "exprs",
- sql_field_new (priv->column[i].name,
- priv->column[i].table, NULL));
+ sql_select_add_expr (select,
+ sql_field_new (priv->column[i].name, priv->column[i].table, NULL));
// Set the filter conditions
if (priv->column[i].info & DB_COLUMN_PRI_KEY)
{
gboolean unset = FALSE;
GValue value = {0};
- SqlObject * eq_value;
+ SqlExpr * eq_value;
- equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
- sql_object_add_child (equal_op, "operators", field);
+ equal_op = SQL_OPERATION
+ (sql_operation_new (SQL_OPERATION_TYPE_EQUAL));
+ sql_operation_add_expr (equal_op, field);
def = gvn_param_spec_get_default (priv->column[i].spec);
@@ -2520,9 +2623,9 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
else if (def && G_IS_VALUE (def))
{
if (G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION)
- eq_value = g_value_get_object (def);
+ eq_value = SQL_EXPR (g_value_get_object (def));
else
- eq_value = sql_value_new_with_value (def);
+ eq_value = sql_value_new_with_value (def);
}
else
{
@@ -2531,26 +2634,26 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
unset = TRUE;
}
- sql_object_add_child (equal_op, "operators", eq_value);
+ sql_operation_add_expr (equal_op, eq_value);
if (unset)
g_value_unset (&value);
- sql_object_add_child (where, "operators", equal_op);
+ sql_operation_add_expr (op, SQL_EXPR (equal_op));
}
}
- sql_object_set (select, "where", where);
+ sql_dml_set_where (SQL_DML (select), SQL_EXPR(op));
+ if (priv->param_default)
for (sl = priv->param_default; sl; sl = sl->next)
{
gboolean cont = FALSE;
+ GSList * m;
DbParamDef * param_def = sl->data;
- l = sql_list_get_items (SQL_INSERT (insert)->fields);
-
- for (; l; l = l->next)
- if (!g_strcmp0 (((SqlField*) l->data)->name, param_def->dst))
+ for (m = insert->field; m; m = m->next)
+ if (!g_strcmp0 (((SqlField*) m->data)->name, param_def->dst))
{
cont = TRUE;
break;
@@ -2561,13 +2664,13 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
val = sql_value_new_with_value
(gvn_param_get_value (param_def->param));
- sql_object_add_child (insert, "fields",
- sql_field_new (param_def->dst, NULL, NULL));
- sql_object_add_child (set, "exprs", val);
+ sql_insert_add_field (insert,
+ SQL_FIELD (sql_field_new (param_def->dst, NULL, NULL)));
+ sql_insert_add_expr (insert, val);
}
- sql_list_add (stmts, insert);
- sql_list_add (stmts, select);
+ sql_multi_stmt_add_stmt (multi, SQL_STMT (insert));
+ sql_multi_stmt_add_stmt (multi, SQL_STMT (select));
render_ops = TRUE;
}
else if (op_elem->type & DB_MODEL_ROW_OP_UPDATE) // UPDATE
@@ -2575,7 +2678,8 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
// Depending on the field, generate an UPDATE or INSERT+SELECT
GSList * m;
GValue * new_value;
- SqlObject * update = NULL;
+ SqlUpdate * update = NULL;
+ SqlInsert * insert = NULL;
GSList * prev_tables = NULL;
GSList * prev_updates = NULL;
gboolean insert_set = FALSE;
@@ -2598,9 +2702,8 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
if (!is_added)
{
- where = sql_operation_new (SQL_OPERATION_TYPE_AND);
- update = g_object_new (SQL_TYPE_UPDATE,
- "where", where, NULL);
+ update = sql_update_new ();
+ op = sql_operation_new (SQL_OPERATION_TYPE_AND);
}
else
{
@@ -2609,19 +2712,17 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
for (l = prev_updates; l; l = l->next)
if (SQL_IS_UPDATE (l->data)
- && SQL_IS_TABLE (t = sql_list_get_items (SQL_DML (l->data)->targets)->data)
+ && SQL_IS_TABLE (t = SQL_DML (l->data)->target->data)
&& !g_strcmp0 (SQL_TABLE (t)->name, priv->column[i].table))
{
- update = l->data;
+ update = SQL_UPDATE (l->data);
break;
}
}
- sql_object_add_child (update, "sets",
- g_object_new (SQL_TYPE_UPDATE_SET,
- "field", sql_field_new (priv->column[i].name, NULL, NULL),
- "expr", sql_value_new_with_value (new_value),
- NULL));
+ sql_update_add_set (update, SQL_FIELD
+ (sql_field_new (priv->column[i].name, NULL, NULL)),
+ sql_value_new_with_value (new_value));
if (!is_added)
{
@@ -2629,8 +2730,8 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
DbModelPKey * pkey =
db_model_get_primary_key (obj, priv->column[i].table);
- sql_object_add_child (update, "targets",
- sql_table_new (priv->column[i].table));
+ sql_dml_add_target
+ (SQL_DML (update), sql_table_new (priv->column[i].table));
for (j = 0; j < pkey->count; j++)
{
@@ -2654,20 +2755,20 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
- sql_object_add_child (equal_op, "operators",
- sql_field_new (priv->column[key_col].name,
- priv->column[key_col].table, NULL));
+ sql_operation_add_expr (SQL_OPERATION (equal_op)
+ ,sql_field_new (priv->column[key_col].name
+ ,priv->column[key_col].table, NULL));
val = sql_value_new_with_value (primary);
- sql_object_add_child (equal_op, "operators", val);
- if (where)
- sql_object_add_child (where, "operators", equal_op);
+ sql_operation_add_expr (equal_op, val);
+
+ if (op)
+ sql_operation_add_expr (op, SQL_EXPR (equal_op));
}
- sql_object_set (update, "where", where);
-
- sql_list_add (stmts, update);
+ sql_dml_set_where (SQL_DML (update), SQL_EXPR (op));
+ sql_multi_stmt_add_stmt (multi, SQL_STMT (update));
db_model_pkey_free (pkey);
}
@@ -2684,14 +2785,11 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
select = sql_select_new ();
}
- if (!SQL_INSERT (insert)->table)
+ if (!insert->table)
{
- SqlObject * table = sql_table_new (priv->column[i].table);
- sql_object_set (insert, "table", table);
- sql_object_add_child (select, "targets", table);
-
- set = g_object_new (SQL_TYPE_SET, NULL);
- sql_object_add_child (insert, "values", set);
+ SqlTarget * table = sql_table_new (priv->column[i].table);
+ sql_insert_set_table (insert, SQL_TABLE (table));
+ sql_dml_add_target (SQL_DML (select), table);
insert_set = TRUE;
@@ -2704,21 +2802,19 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
priv->column[col_def].table))
continue;
- sql_object_add_child (insert, "fields",
- sql_field_new (dst, NULL, NULL));
-
- sql_object_add_child (set, "exprs"
- ,sql_value_new_with_value (DB_ROW_FIELD (row, col_def)));
+ sql_insert_add_field (insert, SQL_FIELD
+ (sql_field_new (dst, NULL, NULL)));
+ sql_insert_add_expr (insert,
+ sql_value_new_with_value (DB_ROW_FIELD (row, col_def)));
}
}
if (insert_set)
{
val = sql_value_new_with_value (new_value);
-
- sql_object_add_child (insert, "fields",
- sql_field_new (priv->column[i].name, NULL, NULL));
- sql_object_add_child (set, "exprs", val);
+ sql_insert_add_field (insert, SQL_FIELD
+ (sql_field_new (priv->column[i].name, NULL, NULL)));
+ sql_insert_add_expr (insert, val);
}
}
}
@@ -2728,15 +2824,15 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
if (insert)
{
- where = sql_operation_new (SQL_OPERATION_TYPE_AND);
+ op = sql_operation_new (SQL_OPERATION_TYPE_AND);
for (i = 0; i < row->len; i++)
- if (!g_strcmp0 (SQL_TABLE (sql_list_get_items (SQL_DML (select)->targets)->data)->name
+ if (!g_strcmp0 (SQL_TABLE (SQL_DML (select)->target->data)->name
,priv->column[i].table))
{
- SqlObject * field = SQL_OBJECT
+ SqlExpr * field = SQL_EXPR
(sql_field_new (priv->column[i].name, NULL, NULL));
- sql_object_add_child (select, "fields", field);
+ sql_select_add_expr (select, field);
if (priv->column[i].info & DB_COLUMN_PRI_KEY)
{
@@ -2746,27 +2842,26 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
|| (def && G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION))
{
equal_op = sql_operation_new (SQL_OPERATION_TYPE_EQUAL);
-
- sql_object_add_child (equal_op, "operators", field);
+ sql_operation_add_expr (equal_op, field);
if (gvn_value_is_null (&row->value[i]))
{
if (def && G_VALUE_TYPE (def) == SQL_TYPE_FUNCTION)
- sql_object_add_child (equal_op, "operators",
- g_value_get_object (def));
+ sql_operation_add_expr (equal_op,
+ SQL_EXPR (g_value_get_object (def)));
}
else
- sql_object_add_child (equal_op, "operators", val);
+ sql_operation_add_expr (equal_op, val);
- sql_object_add_child (where, "operators", equal_op);
+ sql_operation_add_expr (op, SQL_EXPR (equal_op));
}
}
}
- sql_object_set (select, "where", where);
+ sql_dml_set_where (SQL_DML (select), SQL_EXPR (op));
- sql_list_add (stmts, insert);
- sql_list_add (stmts, select);
+ sql_multi_stmt_add_stmt (multi, SQL_STMT (insert));
+ sql_multi_stmt_add_stmt (multi, SQL_STMT (select));
}
render_ops = TRUE;
@@ -2788,7 +2883,6 @@ void db_model_perform_operations (DbModel * obj, gboolean retry)
DbModelRequest * data = g_new (DbModelRequest, 1);
data->obj = g_object_ref (obj);
data->operations = req_ops;
- multi = g_object_new (SQL_TYPE_MULTI_STMT, "stmts", stmts, NULL);
request = db_conn_query_with_stmt_async (priv->conn
,SQL_STMT (multi)
@@ -2860,7 +2954,7 @@ gboolean db_model_iter_is_valid (DbIter * iter, DbModel * obj)
{
g_return_val_if_fail (DB_IS_MODEL (obj), FALSE);
- return (iter && iter->data && obj->priv->stamp == iter->stamp);
+ return (iter && VALID_ITER (iter, obj));
}
// GtkTreeModel implementation methods.
@@ -2935,14 +3029,13 @@ gint db_model_get_path (DbModel * obj, DbIter * iter)
gboolean db_model_get_iter (DbModel * obj, DbIter * iter, gint path)
{
g_return_val_if_fail (DB_IS_MODEL (obj), FALSE);
-
if ((0 > path
|| (obj->priv->result && path >= obj->priv->result->nrows))
|| MODEL_NOT_READY (obj))
return FALSE;
iter->stamp = obj->priv->stamp;
- iter->data = g_ptr_array_index (obj->priv->data, (guint) path);
+ iter->data = g_ptr_array_index (obj->priv->data, path);
if (iter->data)
return TRUE;
@@ -2965,14 +3058,8 @@ gboolean db_model_get_iter_first (DbModel * obj, DbIter * iter)
|| !obj->priv->result || !obj->priv->result->nrows)
return FALSE;
- if (obj->priv->data)
- {
- iter->stamp = obj->priv->stamp;
- iter->data = g_ptr_array_index (obj->priv->data, 0);
- }
- else
- return FALSE;
-
+ iter->stamp = obj->priv->stamp;
+ iter->data = g_ptr_array_index (obj->priv->data, 0);
return TRUE;
}
@@ -2987,15 +3074,20 @@ gboolean db_model_get_iter_first (DbModel * obj, DbIter * iter)
**/
gboolean db_model_iter_prev (DbModel * obj, DbIter * iter)
{
+ DbModelPrivate * priv;
+
g_return_val_if_fail (DB_IS_MODEL (obj), FALSE);
- if (MODEL_NOT_READY(obj)
- || !obj->priv->result || !obj->priv->result->nrows)
+
+ priv = obj->priv;
+
+ if (MODEL_NOT_READY(obj)
+ || !priv->result || !priv->result->nrows)
return FALSE;
g_return_val_if_fail (VALID_ITER (iter, obj), FALSE);
if ((iter->data = g_ptr_array_index
- (obj->priv->data, (guint) DB_ROW_POSITION (iter->data) - 1)))
+ (priv->data, (guint) DB_ROW_POSITION (iter->data) - 1)))
return TRUE;
return FALSE;
}
@@ -3011,6 +3103,7 @@ gboolean db_model_iter_prev (DbModel * obj, DbIter * iter)
**/
gboolean db_model_iter_next (DbModel * obj, DbIter * iter)
{
+ gint pos;
g_return_val_if_fail (DB_IS_MODEL (obj), FALSE);
if (MODEL_NOT_READY(obj)
|| !obj->priv->result || !obj->priv->result->nrows)
@@ -3018,7 +3111,7 @@ gboolean db_model_iter_next (DbModel * obj, DbIter * iter)
g_return_val_if_fail (VALID_ITER (iter, obj), FALSE);
- gint pos = DB_ROW_POSITION (iter->data);
+ pos = DB_ROW_POSITION (iter->data);
if (pos < obj->priv->result->nrows-1)
{
@@ -3026,7 +3119,7 @@ gboolean db_model_iter_next (DbModel * obj, DbIter * iter)
return TRUE;
}
- iter->stamp = (iter->stamp)? 0 : 1;
+ iter->stamp = (iter->stamp) ? 0 : 1;
iter->data = NULL;
return FALSE;
}
@@ -3085,8 +3178,8 @@ typedef enum
{
PROP_CONN = 1
,PROP_STMT
- ,PROP_SQL
,PROP_USE_FILE
+ ,PROP_SQL
,PROP_MAIN_TABLE
,PROP_UPDATE_FLAGS
,PROP_RESULT_POS
@@ -3104,12 +3197,12 @@ static void db_model_set_property (DbModel * obj, guint property_id,
case PROP_STMT:
db_model_set_stmt (obj, g_value_get_object (value));
break;
- case PROP_SQL:
- db_model_set_sql (obj, g_value_get_string (value));
- break;
case PROP_USE_FILE:
obj->priv->use_file = g_value_get_boolean (value);
break;
+ case PROP_SQL:
+ db_model_set_sql (obj, g_value_get_string (value));
+ break;
case PROP_MAIN_TABLE:
db_model_request_main_table (obj, g_value_get_string (value));
break;
@@ -3135,12 +3228,12 @@ static void db_model_get_property (DbModel * obj, guint property_id,
case PROP_STMT:
g_value_set_object (value, obj->priv->stmt);
break;
- case PROP_SQL:
- g_value_set_string (value, obj->priv->sql);
- break;
case PROP_USE_FILE:
g_value_set_boolean (value, obj->priv->use_file);
break;
+ case PROP_SQL:
+ g_value_set_string (value, obj->priv->sql);
+ break;
case PROP_MAIN_TABLE:
g_value_set_string (value, obj->priv->main_table);
break;
@@ -3181,7 +3274,7 @@ static void db_model_init (DbModel *obj)
obj->priv->column_default = NULL;
obj->priv->param_default = NULL;
obj->priv->pending_request = NULL;
-
+ obj->priv->null_row = NULL;
obj->priv->stamp = g_random_int ();
obj->priv->fresh = TRUE;
@@ -3229,7 +3322,7 @@ static void db_model_finalize (DbModel * obj)
g_free (((DbParamDef *) n->data)->dst);
g_free (n->data);
}
-
+
g_slist_free (obj->priv->param_default);
parent->finalize (G_OBJECT (obj));
@@ -3246,7 +3339,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::status-changed:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
* @status: the current status of @model
*
* This signal is emitted every time the status of @model changes.
@@ -3259,7 +3352,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::line-inserted:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
* @iter: a #DbIter
*
* This signal is emitted when a new row is inserted into @model. The inserted
@@ -3273,7 +3366,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::line-deleted:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
* @position: the position of the deleted line
*
* Every time a row of @model is deleted, this signal is emitted.
@@ -3286,7 +3379,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::line-toggled:
- * @model: the instance that received the signal
+ * @model: the object on which the signal is emitted
* @iter: a #DbIter
*
* Emitted to tell that the line is going to be deleted,
@@ -3300,7 +3393,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::line-updated:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
* @iter: a #DbIter
*
* This signal is emitted when any value in a row of @model is set.
@@ -3313,7 +3406,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::lines-reordered:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
* @col: the sort column
* @new_order: (array) (element-type gint): an array mapped with the new
* positions over the old ones
@@ -3332,7 +3425,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::sort-changed:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
*
* This signal is emitted when a new column is selected as sort criteria for
* @model.
@@ -3345,7 +3438,7 @@ static void db_model_class_init (DbModelClass *k)
/**
* DbModel::operations-done:
- * @model: the object which received the signal
+ * @model: the object on which the signal is emitted
* @success: whether the operation has failed or succeded
*
* When an operation on the model is performed on the DB, this signal
@@ -3359,66 +3452,66 @@ static void db_model_class_init (DbModelClass *k)
g_object_class_install_property (klass, PROP_CONN,
g_param_spec_object ("conn"
- ,_("Connection")
- ,_("The DbConn that manages the connection to the database")
- ,DB_TYPE_CONN
- ,G_PARAM_READWRITE
+ ,_("Connection")
+ ,_("The DbConn that manages the connection to the database")
+ ,DB_TYPE_CONN
+ ,G_PARAM_READWRITE
));
g_object_class_install_property (klass, PROP_STMT,
g_param_spec_object ("stmt"
- ,_("Statement")
- ,_("The statement which retrieves the data")
- ,SQL_TYPE_STMT
- ,G_PARAM_READWRITE
- ));
-
- g_object_class_install_property (klass, PROP_SQL,
- g_param_spec_string ("sql"
- ,_("SQL")
- ,_("Depending on the \"use-file\" property this will "
- "be the path to a file with queries for the "
- "model or a SQL string")
- ,NULL
- ,G_PARAM_READWRITE
+ ,_("Statement")
+ ,_("The statement which retrieves the data")
+ ,SQL_TYPE_STMT
+ ,G_PARAM_READWRITE
));
g_object_class_install_property (klass, PROP_USE_FILE,
g_param_spec_boolean ("use-file"
- ,_("Use file")
- ,_("If this is set to TRUE, the \"sql\" property will "
- "hold the name of a file containing a query, if "
- "set to FALSE, \"sql\" is used as an SQL string")
- ,FALSE
- ,G_PARAM_READWRITE
+ ,_("Use file")
+ ,_("If this is set to TRUE, the \"sql\" property will "
+ "hold the name of a file containing a query, if "
+ "set to FALSE, \"sql\" is used as an SQL string")
+ ,FALSE
+ ,G_PARAM_READWRITE
+ ));
+
+ g_object_class_install_property (klass, PROP_SQL,
+ g_param_spec_string ("sql"
+ ,_("SQL")
+ ,_("Depending on the \"use-file\" property this will "
+ "be the path to a file with queries for the "
+ "model or a SQL string")
+ ,NULL
+ ,G_PARAM_READWRITE
));
g_object_class_install_property (klass, PROP_MAIN_TABLE,
g_param_spec_string ("main-table"
- ,_("Main Table")
- ,_("The main table of the model")
- ,NULL
- ,G_PARAM_READWRITE
+ ,_("Main Table")
+ ,_("The main table of the model")
+ ,NULL
+ ,G_PARAM_READWRITE
));
g_object_class_install_property (klass, PROP_UPDATE_FLAGS,
g_param_spec_flags ("update-flags"
- ,_("Update flags")
- ,_("The flags that indicate how a model can be modified")
- ,DB_TYPE_MODEL_UPDATE_FLAGS
- ,DB_MODEL_ALL
- ,G_PARAM_READWRITE
+ ,_("Update flags")
+ ,_("The flags that indicate how a model can be modified")
+ ,DB_TYPE_MODEL_UPDATE_FLAGS
+ ,DB_MODEL_ALL
+ ,G_PARAM_READWRITE
));
g_object_class_install_property (klass, PROP_RESULT_POS,
g_param_spec_uint ("result-pos"
- ,_("Result position")
- ,_("The position where the query that will fill the "
- "model will be placed in a multi-query")
- ,0
- ,G_MAXUINT32
- ,0
- ,G_PARAM_READWRITE
+ ,_("Result position")
+ ,_("The position where the query that will fill the "
+ "model will be placed in a multi-query")
+ ,0
+ ,G_MAXUINT32
+ ,0
+ ,G_PARAM_READWRITE
));
}
diff --git a/db/db-model.h b/db/db-model.h
index 26385ee..506dffa 100644
--- a/db/db-model.h
+++ b/db/db-model.h
@@ -206,6 +206,7 @@ void db_model_unset_update_flags (DbModel * obj
void db_model_set_mode (DbModel * obj, DbModelMode mode);
DbModelMode db_model_get_mode (DbModel * obj);
void db_model_toggle_mode (DbModel * obj);
+void db_model_use_null_row (DbModel * obj, gboolean use);
gboolean db_model_get_last (DbModel * obj, DbIter * iter);
void db_model_get (DbModel * obj
,DbIter * iter
@@ -248,12 +249,11 @@ void db_model_add_join_columns (DbModel * obj
void db_model_set_default_value_from_column (DbModel * obj
,const gchar * dst_field
,gint src_column);
+
void db_model_set_default_value_from_param (DbModel * obj
,const gchar * dst_field
- ,GvnParam * param
- ,const gchar * id);
+ ,GvnParam * param);
void db_model_add_param (DbModel * obj
- ,const gchar * id
,GvnParam * param);
//GtkTreeModel-like methods
diff --git a/db/db-param.c b/db/db-param.c
index 4f2230a..9e90e47 100644
--- a/db/db-param.c
+++ b/db/db-param.c
@@ -17,6 +17,14 @@
#include "db-param.h"
+/**
+ * SECTION: db-param
+ * @Short_description: representation of the value of a field
+ * @Title: DbParam
+ *
+ * This class represents the value of a field in a #DbIterator.
+ **/
+
G_DEFINE_TYPE (DbParam, db_param, GVN_TYPE_PARAM);
/**
diff --git a/db/db-result.h b/db/db-result.h
index 08643d5..0a1c7ab 100644
--- a/db/db-result.h
+++ b/db/db-result.h
@@ -30,7 +30,7 @@ typedef struct _DbColumn DbColumn;
* DbResult:
* @nrows: Number of rows.
* @ncols: Number of columns.
- * @data: Has a #GList.
+ * @data: (element-type DbRow): Has a #GList.
* @column: Has a #DbColumn.
*
* Has the information of a row.
diff --git a/db/db.h b/db/db.h
index 4757877..a42ba00 100644
--- a/db/db.h
+++ b/db/db.h
@@ -20,6 +20,7 @@
#include
#include "db-iter.h"
+#include "db-model-holder.h"
#include "db-model.h"
#include "db-request.h"
#include "db-conn.h"
diff --git a/debian/changelog b/debian/changelog
index 1cb12cd..f0e0d82 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-libhedera (1.0-1) stable; urgency=low
+libhedera (1.0-6) stable; urgency=low
* Initial Release.
diff --git a/debian/control b/debian/control
index fb0d285..30a76fc 100644
--- a/debian/control
+++ b/debian/control
@@ -20,23 +20,25 @@ Description: Database access and widget provider library (runtime)
queries.
.
The library also has a modular system to add and remove the different widgets
- in run time.
+ in run time. And includes Glade integration, to design the programs in an
+ easiest, graphical way.
.
This package contains the executable and data files.
Package: libhedera-dev
Section: libdevel
Architecture: amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, libhedera1 (= ${binary:Version})
-Suggests: libgtk-3-doc, libgtk-3-dbg, devhelp, valac (>= 0.16)
-Recommends: glade (>= 3.4), anjuta (>= 3.4)
+Depends: ${shlibs:Depends}, ${misc:Depends}, libhedera1 (= ${binary:Version}),
+ libgtk-3-dev
+Suggests: libgtk-3-doc, libgtk-3-0-dbg, devhelp, valac (>= 0.16)
+Recommends: glade (>= 3.4), anjuta (>= 3.4), libgtksourceview-3.0-1
Description: Database access and widget provider library (development)
The hedera library provides and lets you create widgets bound to SQL queries
and manages the different operations made over the data retrieved from these
queries.
.
The library also has a modular system to add and remove the different widgets
- in run time. And it includes Glade integration, to design the programs in an
+ in run time. And includes Glade integration, to design the programs in an
easiest, graphical way.
.
This package contains development files to compile C and Vala programs that
@@ -46,14 +48,15 @@ Description: Database access and widget provider library (development)
Package: libhedera1
Section: libs
Architecture: amd64
-Depends: ${shlibs:Depends}, ${misc:Depends}, libgtk-3-0, libgtk-3-dev
+Depends: ${shlibs:Depends}, ${misc:Depends}, libgtk-3-0
Description: Database access and widget provider library (core)
The hedera library provides and lets you create widgets bound to SQL queries
and manages the different operations made over the data retrieved from these
queries.
.
The library also has a modular system to add and remove the different widgets
- in run time.
+ in run time. And includes Glade integration, to design the programs in an
+ easiest, graphical way.
.
This package contains the core of the library. It also provides the plugins to
connect a PostgreSQL or MySQL database.
@@ -68,6 +71,7 @@ Description: Database access and widget provider library (debug)
queries.
.
The library also has a modular system to add and remove the different widgets
- in run time.
+ in run time. And includes Glade integration, to design the programs in an
+ easiest, graphical way.
.
This package contains the debugging symbols for hedera.
diff --git a/debian/hedera.dirs b/debian/hedera.dirs
index cd6f5f3..f2e7c37 100644
--- a/debian/hedera.dirs
+++ b/debian/hedera.dirs
@@ -1,8 +1,8 @@
usr/bin
usr/lib/hedera/module
-usr/share/hedera/vn/image
usr/share/hedera/vn
+usr/share/hedera/vn/image
usr/share/hedera/module
usr/share/hedera/module/sql
-usr/share/applications
-usr/share/ca-certificates/verdnatura.es
\ No newline at end of file
+usr/share/hedera/module/sql/example
+usr/share/applications
\ No newline at end of file
diff --git a/debian/hedera.install b/debian/hedera.install
index baa912c..d83224a 100644
--- a/debian/hedera.install
+++ b/debian/hedera.install
@@ -1,7 +1,8 @@
usr/bin/*
usr/lib/hedera/module/*.so
-usr/share/hedera/vn/image/*
usr/share/hedera/vn/*
+usr/share/hedera/vn/image/*
usr/share/hedera/module/*
-usr/share/applications/*
-usr/share/ca-certificates/verdnatura.es/*
\ No newline at end of file
+usr/share/hedera/module/sql/*
+usr/share/hedera/module/sql/example/*
+usr/share/applications/*
\ No newline at end of file
diff --git a/debian/libhedera-dev.dirs b/debian/libhedera-dev.dirs
index 8ee5a77..4317d72 100644
--- a/debian/libhedera-dev.dirs
+++ b/debian/libhedera-dev.dirs
@@ -7,7 +7,7 @@ usr/include/hedera/vn/field
usr/include/hedera/vn/column
usr/lib/hedera
usr/lib/glade/modules
-usr/lib/girepository-1.0
+#usr/lib/girepository-1.0
usr/share/gir-1.0
usr/share/glade/catalogs
usr/share/pkgconfig
diff --git a/debian/libhedera-dev.install b/debian/libhedera-dev.install
index 4938212..54beaff 100644
--- a/debian/libhedera-dev.install
+++ b/debian/libhedera-dev.install
@@ -17,7 +17,7 @@ usr/lib/hedera/libvnfield.so
usr/lib/hedera/libvncolumn.a
usr/lib/hedera/libvncolumn.so
usr/lib/glade/modules/libgladevn.so
-usr/lib/girepository-1.0/*
+#usr/lib/girepository-1.0/*
usr/share/gir-1.0/*
usr/share/glade/catalogs/*
usr/share/pkgconfig/*
diff --git a/docs/reference/hedera/hedera-docs.sgml b/docs/reference/hedera/hedera-docs.sgml
index 7c596be..9af016d 100644
--- a/docs/reference/hedera/hedera-docs.sgml
+++ b/docs/reference/hedera/hedera-docs.sgml
@@ -95,6 +95,7 @@
DbLib
+
diff --git a/glade/Makefile.am b/glade/Makefile.am
index 56b9ac0..37540dd 100644
--- a/glade/Makefile.am
+++ b/glade/Makefile.am
@@ -4,20 +4,31 @@ gladevn_lib_LTLIBRARIES = libgladevn.la
AM_CPPFLAGS = \
-I$(top_srcdir) \
- $(gladeui_CFLAGS)
+ $(gladeui_CFLAGS) \
+ $(DEFINES) \
+ $(gtksourceview_CFLAGS)
libgladevn_la_LIBADD = \
$(top_builddir)/vn/libvn.la \
- $(gladeui_LIBS)
+ $(gladeui_LIBS) \
+ $(gtksourceview_LIBS)
libgladevn_la_LDFLAGS = -avoid-version
libgladevn_la_SOURCES = \
glade-vn.h \
glade-vn.c \
- glade-vn-batch.c
+ glade-vn-batch.c \
+ glade-db-sql.c \
+ glade-db-model.c
gladevn_data_DATA = vn.xml
+if HAVE_SOURCEVIEW
+DEFINES = -D_HAVE_GTKSOURCEVIEW
+else
+DEFINES =
+endif
+
EXTRA_DIST = $(gladevn_data_DATA)
install-data-hook:
rm -f $(DESTDIR)$(gladevn_libdir)/libgladevn.la
- rm -f $(DESTDIR)$(gladevn_libdir)/libgladevn.a
\ No newline at end of file
+ rm -f $(DESTDIR)$(gladevn_libdir)/libgladevn.a
diff --git a/glade/glade-db-model.c b/glade/glade-db-model.c
new file mode 100644
index 0000000..e223c5d
--- /dev/null
+++ b/glade/glade-db-model.c
@@ -0,0 +1,364 @@
+/*
+ * Copyright (C) 2013 - Juan Ferrer Toribio
+ *
+ * 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "glade-vn.h"
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++ DbModel GladeEditorProperty
+
+typedef struct
+{
+ GladeEditorProperty parent;
+
+ GtkWidget * button;
+ GtkWidget * entry;
+ gboolean connected;
+ GladeWidget * widget;
+}
+GladeEPropModel;
+
+GLADE_MAKE_EPROP (GladeEPropModel, glade_eprop_model)
+#define GLADE_TYPE_EPROP_MODEL (glade_eprop_model_get_type())
+#define GLADE_EPROP_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_EPROP_MODEL, GladeEPropModel))
+#define GLADE_EPROP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_EPROP_MODEL, GladeEPropModelClass))
+#define GLADE_IS_EPROP_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_EPROP_MODEL))
+#define GLADE_IS_EPROP_MODEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_EPROP_MODEL))
+#define GLADE_EPROP_MODEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_EPROP_MODEL, GladeEPropModelClass))
+
+static void glade_eprop_model_name_changed (GladeProject * project,
+ GladeWidget * widget, GladeEPropModel * obj)
+{
+ if (widget && obj->widget)
+ {
+ gtk_entry_set_text (GTK_ENTRY (obj->entry),
+ glade_widget_get_name (widget));
+ }
+}
+
+static GladeWidget * glade_model_create (GladeProperty * prop)
+{
+ gboolean use = FALSE;
+ VnBatch * batch;
+ GladeWidget * batch_w;
+ GladeProject * project = glade_widget_get_project (glade_property_get_widget (prop));
+ const GList * l, * n, * objects = glade_project_get_objects (project);
+
+ for (n = objects; n; n = n->next)
+ if (VN_IS_BATCH (n->data))
+ {
+ batch = n->data;
+ use = TRUE;
+
+ for (l = vn_batch_get_objects (batch); l; l = l->next)
+ if (!DB_IS_MODEL (l->data))
+ {
+ use = FALSE;
+ break;
+ }
+
+ if (use)
+ break;
+ }
+
+ if (!use)
+ batch_w = glade_command_create
+ (glade_widget_adaptor_get_by_type (VN_TYPE_BATCH), NULL, NULL, project);
+ else
+ batch_w = glade_widget_get_from_gobject (batch);
+
+ return glade_command_create
+ (glade_widget_adaptor_get_by_type (DB_TYPE_MODEL), batch_w, NULL, project);
+}
+
+/*
+ * glade_eprop_model_show_dialog:
+ * @button:(allow-none): a #GtkButton or @NULL
+ * @object: a #GladeEditorPropery or a #GladeWidget
+ *
+ * Opens a dialog to edit a #DbModel.
+ * Can be called by a #GladeEditorProperty or by the "edit" action of a
+ * #GladeWidgetAdaptor directly (in which case @button is %NULL and @obj is a
+ * #GladeWidget).
+ **/
+static void glade_eprop_model_show_dialog (GtkButton * button, GObject * object)
+{
+ gboolean created = FALSE;
+ GObject * o;
+ GtkWidget * box;
+ GtkDialog * dialog;
+ GladeWidget * widget;
+ GladeWidgetAdaptor * adaptor;
+ GladeEditable * editor;
+ GladeProperty * p = NULL;
+ GladeEditorProperty * eprop = NULL;
+
+ if (GLADE_IS_EDITOR_PROPERTY (object))
+ {
+ eprop = GLADE_EDITOR_PROPERTY (object);
+ p = glade_editor_property_get_property (eprop);
+ o = g_value_get_object (glade_property_inline_value (p));
+
+ if (o && DB_IS_MODEL (o))
+ widget = glade_widget_get_from_gobject (o);
+ else
+ {
+ GValue val = G_VALUE_INIT;
+
+ glade_command_push_group
+ (_("Create and set a model for a DbModelHolder"));
+
+ widget = glade_model_create (p);
+ created = TRUE;
+ g_value_init (&val, DB_TYPE_MODEL);
+ g_value_set_object (&val, glade_widget_get_object (widget));
+ glade_command_set_property_value (p, &val);
+ g_value_unset (&val);
+
+ glade_command_pop_group ();
+
+ glade_project_selection_set (glade_widget_get_project (widget),
+ glade_widget_get_object (glade_property_get_widget (p)),
+ TRUE);
+
+ if (!GLADE_EPROP_MODEL (eprop)->connected)
+ {
+ g_signal_connect (glade_widget_get_project
+ (glade_property_get_widget (p)), "widget-name-changed",
+ G_CALLBACK (glade_eprop_model_name_changed), eprop);
+ GLADE_EPROP_MODEL (eprop)->connected = TRUE;
+ }
+ }
+ }
+ else
+ widget = GLADE_WIDGET (object);
+
+ adaptor = glade_widget_get_adaptor (widget);
+ editor = glade_widget_adaptor_create_editable (adaptor, GLADE_PAGE_GENERAL);
+ glade_editable_load (editor, widget);
+
+ dialog = GTK_DIALOG (gtk_dialog_new_with_buttons
+ (eprop ? _("Model configuration") : _("DbModel properties configuration")
+ ,GTK_WINDOW (glade_app_get_window ())
+ ,GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ ,GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
+ ,GTK_STOCK_CLEAR, GTK_RESPONSE_REJECT
+ ,GTK_STOCK_OK, GTK_RESPONSE_OK
+ ,NULL
+ ));
+ gtk_dialog_set_alternative_button_order (dialog,
+ GTK_RESPONSE_OK, GTK_RESPONSE_REJECT, GTK_RESPONSE_CANCEL, -1);
+ gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300);
+
+ if (!eprop)
+ gtk_widget_hide (gtk_dialog_get_widget_for_response
+ (dialog, GTK_RESPONSE_REJECT));
+
+ box = gtk_alignment_new (0,0,1,1);
+ gtk_alignment_set_padding (GTK_ALIGNMENT (box), 8, 8, 8, 8);
+ gtk_container_add (GTK_CONTAINER (box), GTK_WIDGET (editor));
+ gtk_widget_show_all (box);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (dialog)),
+ box, TRUE, TRUE, 0);
+
+ switch (gtk_dialog_run (dialog))
+ {
+ case GTK_RESPONSE_OK:
+ {
+ if (eprop)
+ {
+ gtk_entry_set_text (GTK_ENTRY (GLADE_EPROP_MODEL (eprop)->entry),
+ glade_widget_get_name (widget));
+ GLADE_EPROP_MODEL (eprop)->widget = widget;
+ }
+
+ break;
+ }
+ case GTK_RESPONSE_REJECT:
+ {
+ if (eprop)
+ {
+ glade_command_set_property (p, NULL);
+ GLADE_EPROP_MODEL (eprop)->widget = NULL;
+ }
+
+ break;
+ }
+ case GTK_RESPONSE_CANCEL:
+ {
+ if (created)
+ {
+ GList * list = g_list_append (NULL, widget);
+ GladeWidget * batch = glade_widget_get_parent (widget);
+
+ if (vn_batch_get_length
+ VN_BATCH (glade_widget_get_object (batch)) == 1)
+ list = g_list_prepend (list, batch);
+
+ glade_command_delete (list);
+ g_list_free (list);
+ GLADE_EPROP_MODEL (eprop)->widget = NULL;
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void glade_eprop_model_show_object_dialog (GtkButton * button,
+ GladeEditorProperty * eprop)
+{
+ GladeProperty * p = glade_editor_property_get_property (eprop);
+ // Widget to which the property belongs (e.g. Model Holder)
+ GladeWidget * widget = glade_property_get_widget (p);
+ GladeProject * project = glade_widget_get_project (widget);
+ GObject * object = g_value_get_object (glade_property_inline_value (p));
+ // Widget representing the property itself (i.e. DbModel)
+ widget = object ? glade_widget_get_from_gobject (object) : NULL;
+ GLADE_EPROP_MODEL (eprop)->widget = widget;
+
+ if (glade_editor_property_show_object_dialog (project,
+ _("Select a DbModel for the property"), NULL,
+ DB_TYPE_MODEL, NULL, &widget))
+ {
+ if (widget)
+ {
+ GValue val = G_VALUE_INIT;
+ g_value_init (&val, DB_TYPE_MODEL);
+ g_value_set_object (&val, glade_widget_get_object (widget));
+ glade_command_set_property_value (p, &val);
+ g_value_unset (&val);
+ }
+ else
+ glade_command_set_property (p, NULL);
+ }
+}
+
+static GtkWidget * glade_eprop_model_create_input (GladeEditorProperty * eprop)
+{
+ GtkWidget * hbox, * box, * object_button;
+ GladeEPropModel * obj = GLADE_EPROP_MODEL (eprop);
+
+ obj->button = gtk_button_new_with_label (_("New Model"));
+ g_signal_connect (G_OBJECT (obj->button), "clicked",
+ G_CALLBACK (glade_eprop_model_show_dialog), eprop);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+ obj->entry = gtk_entry_new ();
+ gtk_editable_set_editable (GTK_EDITABLE (obj->entry), FALSE);
+ gtk_widget_set_hexpand (obj->entry, TRUE);
+ gtk_container_add (GTK_CONTAINER (hbox), obj->entry);
+
+ object_button = gtk_button_new_with_label ("...");
+ gtk_container_add (GTK_CONTAINER (hbox), object_button);
+ g_signal_connect (G_OBJECT (object_button), "clicked",
+ G_CALLBACK (glade_eprop_model_show_object_dialog), eprop);
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_container_add (GTK_CONTAINER (box), hbox);
+ gtk_container_add (GTK_CONTAINER (box), obj->button);
+ gtk_widget_show_all (box);
+
+ obj->widget = NULL;
+/* project = glade_widget_get_project (glade_property_get_widget
+ (glade_editor_property_get_property (eprop)));
+ */
+
+ return box;
+}
+
+static void glade_eprop_model_load (GladeEditorProperty * eprop, GladeProperty * property)
+{
+ gchar * label;
+ const gchar * text;
+ GObject * object;
+ GladeEditorPropertyClass * parent_class =
+ g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
+ parent_class->load (eprop, property);
+
+ if (property == NULL)
+ return;
+
+ if ((object = g_value_get_object (glade_property_inline_value (property))))
+ {
+ label = _("Edit Model");
+ text = glade_widget_get_name (glade_widget_get_from_gobject (object));
+ }
+ else
+ {
+ label = _("New Model");
+ text = "";
+ }
+
+ gtk_button_set_label (GTK_BUTTON (GLADE_EPROP_MODEL (eprop)->button), label);
+ gtk_entry_set_text (GTK_ENTRY (GLADE_EPROP_MODEL (eprop)->entry), text);
+}
+
+static void glade_eprop_model_finalize (GObject * object)
+{
+ GObjectClass * parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (object));
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++ DbModel Action Callback
+
+void glade_db_model_action_activate (GladeWidgetAdaptor * adaptor,
+ DbModel * model, const gchar * path)
+{
+ glade_eprop_model_show_dialog (NULL,
+ (GObject *) glade_widget_get_from_gobject (model));
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++ DbModelHolder GladeWidgetAdaptor
+
+GladeEditorProperty * glade_db_model_holder_create_eprop (GladeWidgetAdaptor * adaptor,
+ GladePropertyClass * klass, gboolean use_command)
+{
+ GladeEditorProperty * eprop;
+ GParamSpec * pspec = glade_property_class_get_pspec (klass);
+
+ if (pspec->value_type == DB_TYPE_MODEL)
+ {
+ eprop = g_object_new (GLADE_TYPE_EPROP_MODEL,
+ "property-class", klass,
+ "use-command", use_command, NULL);
+ }
+ else
+ eprop = GWA_GET_CLASS (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
+
+ return eprop;
+}
+
+void glade_db_model_write_widget (GladeWidgetAdaptor * adaptor,
+ GladeWidget * widget, GladeXmlContext * context, GladeXmlNode * node)
+{
+ GladeProperty * prop;
+
+ if (!glade_xml_node_verify (node, GLADE_XML_TAG_WIDGET))
+ return;
+
+ prop = glade_widget_get_property (widget, "use-file");
+ glade_property_write (prop, context, node);
+
+ prop = glade_widget_get_property (widget, "sql");
+ glade_property_write (prop, context, node);
+
+ GWA_GET_CLASS (G_TYPE_OBJECT)->write_widget (adaptor, widget, context, node);
+}
diff --git a/glade/glade-db-sql.c b/glade/glade-db-sql.c
new file mode 100644
index 0000000..e65d2d2
--- /dev/null
+++ b/glade/glade-db-sql.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2013 - Juan Ferrer Toribio
+ *
+ * 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 3 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "glade-vn.h"
+
+#ifdef _HAVE_GTKSOURCEVIEW
+#include
+#include
+#include
+#include
+#endif
+
+#define NEW_SQL _("New SQL statement")
+
+//+++++++++++++++++++++++++++++++++++++++++++++++++++ GladeEPropSql
+
+typedef struct
+{
+ GladeEditorProperty parent;
+
+ GtkWidget * button;
+ GtkWidget * entry;
+ gint width;
+ gint height;
+}
+GladeEPropSql;
+
+GLADE_MAKE_EPROP (GladeEPropSql, glade_eprop_sql)
+#define GLADE_TYPE_EPROP_SQL (glade_eprop_sql_get_type())
+#define GLADE_EPROP_SQL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_EPROP_SQL, GladeEPropSql))
+#define GLADE_EPROP_SQL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GLADE_TYPE_EPROP_SQL, GladeEPropSqlClass))
+#define GLADE_IS_EPROP_SQL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_EPROP_SQL))
+#define GLADE_IS_EPROP_SQL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GLADE_TYPE_EPROP_SQL))
+#define GLADE_EPROP_SQL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GLADE_EPROP_SQL, GladeEPropSqlClass))
+
+static void glade_eprop_sql_show_dialog (GtkButton * button, GladeEditorProperty * eprop)
+{
+ gpointer text, buffer;
+ const gchar * sql;
+ GladeEPropSql * obj = GLADE_EPROP_SQL (eprop);
+ PangoFontDescription * font;
+ GtkWidget * scroll;
+ GladeProperty * p = glade_editor_property_get_property (eprop);
+ GtkDialog * dialog = GTK_DIALOG (gtk_dialog_new_with_buttons
+ (_("SQL Editor")
+ ,GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (eprop)))
+ ,GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ ,GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL
+ ,GTK_STOCK_CLEAR, GTK_RESPONSE_REJECT
+ ,GTK_STOCK_OK, GTK_RESPONSE_OK
+ ,NULL
+ ));
+
+ gtk_dialog_set_alternative_button_order (dialog,
+ GTK_RESPONSE_OK, GTK_RESPONSE_REJECT, GTK_RESPONSE_CANCEL, -1);
+ gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), obj->width, obj->height);
+
+ scroll = gtk_scrolled_window_new (gtk_adjustment_new (0,0,0,0,0,0),
+ gtk_adjustment_new (0,0,0,0,0,0));
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scroll), GTK_SHADOW_IN);
+ gtk_widget_set_margin_top (scroll, 6);
+ gtk_widget_set_margin_right (scroll, 6);
+ gtk_widget_set_margin_bottom (scroll, 6);
+ gtk_widget_set_margin_left (scroll, 6);
+ gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (dialog)),
+ scroll, TRUE, TRUE, 6);
+
+#ifdef _HAVE_GTKSOURCEVIEW
+ GtkSourceLanguageManager * lm = gtk_source_language_manager_new ();
+ GtkSourceLanguage * lang = gtk_source_language_manager_get_language (lm, "sql");
+ text = gtk_source_view_new ();
+ gtk_source_view_set_tab_width (text, 4);
+ gtk_source_view_set_show_line_numbers (text, TRUE);
+ gtk_source_view_set_highlight_current_line (text, TRUE);
+ buffer = gtk_text_view_get_buffer (text);
+ gtk_source_buffer_set_language (buffer, lang);
+ gtk_source_buffer_set_highlight_matching_brackets (buffer, TRUE);
+#else
+ text = gtk_text_view_new ();
+ buffer = gtk_text_view_get_buffer (text);
+#endif
+
+ font = pango_font_description_from_string ("Monospace");
+ gtk_widget_override_font (text, font);
+ pango_font_description_free (font);
+
+ sql = g_value_get_string (glade_property_inline_value (p));
+
+ if (sql)
+ gtk_text_buffer_set_text (buffer, sql, -1);
+
+ gtk_container_add (GTK_CONTAINER (scroll), text);
+ gtk_widget_show_all (scroll);
+
+ switch (gtk_dialog_run (dialog))
+ {
+ case GTK_RESPONSE_OK:
+ {
+ GValue val = G_VALUE_INIT;
+ GtkTextIter * start = g_new (GtkTextIter, 1),
+ * end = g_new (GtkTextIter, 1);
+ g_value_init (&val, G_TYPE_STRING);
+ gtk_text_buffer_get_bounds (buffer, start, end);
+
+ sql = gtk_text_buffer_get_text (buffer, start, end, TRUE);
+ g_value_set_string (&val, sql);
+ glade_command_set_property_value (p, &val);
+
+ g_value_unset (&val);
+ g_free (start);
+ g_free (end);
+ break;
+ }
+ case GTK_RESPONSE_REJECT:
+ {
+ GValue val = G_VALUE_INIT;
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, "");
+ glade_command_set_property_value (p, &val);
+ g_value_unset (&val);
+ break;
+ }
+ case GTK_RESPONSE_CANCEL:
+ default:
+ break;
+ }
+
+ obj->width = gtk_widget_get_allocated_width (GTK_WIDGET (dialog));
+ obj->height = gtk_widget_get_allocated_height (GTK_WIDGET (dialog));
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void glade_eprop_sql_entry_text_changed (GtkEntry * entry,
+ GladeEditorProperty * eprop)
+{
+ const gchar * text = gtk_entry_get_text (entry);
+ GladeProperty * p = glade_editor_property_get_property (eprop);
+
+ if (text)
+ {
+ GValue val = G_VALUE_INIT;
+ g_value_init (&val, G_TYPE_STRING);
+ g_value_set_string (&val, text);
+
+ glade_command_set_property_value (p, &val);
+
+ g_value_unset (&val);
+ }
+}
+
+static GtkWidget * glade_eprop_sql_create_input (GladeEditorProperty * eprop)
+{
+ GladeEPropSql * obj = GLADE_EPROP_SQL (eprop);
+ GtkWidget * box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+
+ obj->entry = gtk_entry_new ();
+ gtk_widget_set_hexpand (obj->entry, TRUE);
+ g_signal_connect (obj->entry, "changed",
+ G_CALLBACK (glade_eprop_sql_entry_text_changed), obj);
+ gtk_container_add (GTK_CONTAINER (box), obj->entry);
+
+ obj->button = gtk_button_new_with_label ("...");
+ g_signal_connect (obj->button, "clicked",
+ G_CALLBACK (glade_eprop_sql_show_dialog), obj);
+ gtk_widget_set_tooltip_text (obj->button, _("Open the SQL Editor"));
+ gtk_container_add (GTK_CONTAINER (box), obj->button);
+
+ gtk_widget_show_all (box);
+
+ obj->width = 750;
+ obj->height = 550;
+
+ return box;
+}
+
+static void glade_eprop_sql_load (GladeEditorProperty * eprop, GladeProperty * property)
+{
+ const gchar * sql;
+ GladeEPropSql * obj = GLADE_EPROP_SQL (eprop);
+
+ GladeEditorPropertyClass * parent_class =
+ g_type_class_peek_parent (GLADE_EDITOR_PROPERTY_GET_CLASS (eprop));
+ parent_class->load (eprop, property);
+
+ if (!property)
+ return;
+
+ if ((sql = g_value_get_string (glade_property_inline_value (property))))
+ gtk_entry_set_text (GTK_ENTRY (obj->entry), sql);
+}
+
+static void glade_eprop_sql_finalize (GObject * object)
+{
+ GObjectClass * parent_class = g_type_class_peek_parent (G_OBJECT_GET_CLASS (object));
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+//++++++++++++++++++++++++++++++++++++++++++++++++++ DbModel GladeWidgetAdaptor
+
+GladeEditorProperty * glade_db_sql_create_eprop (GladeWidgetAdaptor * adaptor,
+ GladePropertyClass * klass, gboolean use_command)
+{
+ GladeEditorProperty * eprop;
+ GParamSpec * pspec = glade_property_class_get_pspec (klass);
+
+ if (!g_strcmp0 (pspec->name, "sql"))
+ {
+ eprop = g_object_new (GLADE_TYPE_EPROP_SQL,
+ "property-class", klass,
+ "use-command", use_command, NULL);
+ }
+ else
+ eprop = GWA_GET_CLASS (G_TYPE_OBJECT)->create_eprop (adaptor, klass, use_command);
+
+ return eprop;
+}
diff --git a/glade/glade-vn-batch.c b/glade/glade-vn-batch.c
index 409e8f3..25f82a3 100644
--- a/glade/glade-vn-batch.c
+++ b/glade/glade-vn-batch.c
@@ -65,5 +65,5 @@ void glade_vn_batch_replace_child (GladeWidgetAdaptor * adaptor,
GList * glade_vn_batch_get_children (GladeWidgetAdaptor * adaptor,
VnBatch * group)
{
- return vn_batch_get_objects (group);
+ return vn_batch_get_objects_list (group);
}
diff --git a/glade/vn.xml b/glade/vn.xml
index cffdac7..11186c6 100644
--- a/glade/vn.xml
+++ b/glade/vn.xml
@@ -16,15 +16,28 @@
-
+
+
+
+
+
+
+ glade_db_model_action_activate
+ glade_db_sql_create_eprop
+ glade_db_model_write_widget
-
+
-
-
+
+
+ GParamObject
+ DbModel
+
+
+ glade_db_model_holder_create_eprop
@@ -47,27 +60,32 @@
-
-
+
+
-
+
-
+
-
-
+
+
+ GParamObject
+ DbModel
+
+
+ glade_db_model_holder_create_eprop
-
+
-
-
+
+
@@ -79,17 +97,31 @@
-
-
+
+
+ GParamObject
+ DbModel
+
+
+
+
+ glade_db_model_holder_create_eprop
-
-
+
+
+ GParamObject
+ DbModel
+
+
+
+
+ glade_db_model_holder_create_eprop
@@ -105,7 +137,7 @@
-
+
glade_vn_batch_add_verify
glade_vn_batch_add_child
@@ -117,7 +149,6 @@
-
@@ -125,7 +156,7 @@
-
+
@@ -134,7 +165,8 @@
-
+
+
diff --git a/main/Makefile.am b/main/Makefile.am
index c60c904..064198b 100644
--- a/main/Makefile.am
+++ b/main/Makefile.am
@@ -9,6 +9,7 @@ AM_CPPFLAGS = \
hedera_bin_LDFLAGS = -Wl,--export-dynamic
hedera_bin_SOURCES = main.c
hedera_bin_LDADD = \
+ $(gtk_LIBS) \
$(top_builddir)/gvn/libgvn.la \
$(top_builddir)/db/libdb.la \
$(top_builddir)/vn/libvn.la
@@ -21,12 +22,9 @@ $(hedera_bin_SCRIPTS): $(SCRIPT)
pkgconfig_DATA = hedera.pc
-desktop_DATA = vn-hedera.desktop
-
-HOST=verdnatura.es
-certdir = $(datadir)/ca-certificates/$(HOST)
-cert_DATA = cacert.pem
-syscertdir = $(sysconfdir)/ssl/certs
+desktop_DATA = \
+ vn-hedera.desktop \
+ vn-hedera-debug.desktop
man_MANS = hedera.1
@@ -37,9 +35,5 @@ EXTRA_DIST = \
DISTCLEANFILES = \
$(hedera_bin_SCRIPTS) \
hedera.pc \
- vn-hedera.desktop
-
-install-data-hook:
- mkdir -p $(DESTDIR)$(syscertdir)
- (cd $(DESTDIR)$(syscertdir) && \
- $(LN_S) -f $(DESTDIR)$(certdir)/$(cert_DATA) $(HOST).pem)
+ vn-hedera.desktop \
+ vn-hedera-debug.desktop
diff --git a/main/hedera.1 b/main/hedera.1
index bbf6193..085dbdb 100644
--- a/main/hedera.1
+++ b/main/hedera.1
@@ -7,9 +7,13 @@ hedera \- modular management system
.SH SYNOPSIS
.B hedera
-.\"RI [ options ]
+.RB [\-\-lib-dir|\-l
+.IR path \|]
+.RB [\-\-data-dir|\-l
+.IR path \|]
+.RB [\-\-query-dir|\-l
+.IR path \|]
.br
-
.SH DESCRIPTION
.B hedera
is an enterprise management and administration application. It features modular
@@ -26,9 +30,12 @@ will look for the modules in /usr/lib/hedera/module and for its corresponding
data (GUI files, configuration...) in /usr/share/hedera/module but more
directories can be added by setting
.B VN_MODULE_LIB_PATH
-(for the binaries) and
+(for the binaries),
.B VN_MODULE_DATA_PATH
-(for the additional data). These environment variables are intended for testing
+(for the additional data) and
+.B VN_MODULE_QUERY_PATH
+(for SQL query files) that can also be set automatically passing the
+corresponding options. These environment variables are intended for testing
during the developement and the expected is to use the modules installed.
.PP
The format for the configuration files for the modules and some information on
@@ -37,7 +44,25 @@ for
.B hedera.
.SH OPTIONS
-
+.TP
+.BI \-l\ path ,\ \-\-lib-dir\ path
+Sets the value of the
+.B VN_MODULE_LIB_PATH
+variable. This option can be used mutiple times to specify more than one search
+path for the module libraries.
+.TP
+.BI \-d\ path ,\ \-\-data-dir\ path
+Sets the value of the
+.B VN_MODULE_DATA_PATH
+variable. This option can be used mutiple times to specify more than one search
+path for the module data files.
+.TP
+.BI \-q\ path ,\ \-\-query-dir\ path
+Sets the value of the
+.B VN_MODULE_QUERY_PATH
+variable. This option can be used mutiple times to specify more than one search
+path for the module query files.
+.br
.SH EXAMPLE
Given a module project in the home directory,
.B hedera
@@ -47,4 +72,4 @@ should be called like this to load the module without installing it:
.SH AUTHORS
Copyright (C) 2012 Juan Ferrer Toribio .
.PP
-Manual page written by Alejandro T. Colombini.
\ No newline at end of file
+Manual page written by Alejandro T. Colombini.
diff --git a/main/hedera.sh.in b/main/hedera.sh.in
index b7acf53..f645026 100644
--- a/main/hedera.sh.in
+++ b/main/hedera.sh.in
@@ -1,10 +1,26 @@
#!/bin/bash
-if [ -x @bindir@/vn-updater-gui ]
+UPDATE=1
+
+while getopts ":u" OPTION
+do
+ case $OPTION in
+ u)
+ UPDATE=0
+ ;;
+ \?|:)
+ echo "Usage: $0 [-u]"
+ exit 1
+ ;;
+ esac
+done
+
+if [ "$UPDATE" -eq "1" -a -x @bindir@/vn-updater-gui ]
then
echo "Running updater..."
@bindir@/vn-updater-gui
fi
export LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN=1
-exec @bindir@/hedera-bin
+
+exec hedera-bin
diff --git a/main/vn-hedera-debug.desktop.in b/main/vn-hedera-debug.desktop.in
new file mode 100644
index 0000000..6cd7923
--- /dev/null
+++ b/main/vn-hedera-debug.desktop.in
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Name=Hedera (Development)
+GenericName=Office Tool
+Comment=Runtime for the Hedera system (Development)
+Exec=hedera -u
+Icon=@prefix@/share/@PACKAGE@/vn/image/icon-debug.svg
+Terminal=true
+Type=Application
+Categories=GNOME;GTK;Development;
+StartupNotify=true
+Version=@VERSION@
diff --git a/main/vn-hedera.desktop.in b/main/vn-hedera.desktop.in
index e949638..c88b49a 100644
--- a/main/vn-hedera.desktop.in
+++ b/main/vn-hedera.desktop.in
@@ -3,7 +3,7 @@ Name=Hedera
GenericName=Office Tool
Comment=Runtime for the Hedera system
Exec=hedera
-Icon=@prefix@/share/hedera/vn/image/icon.svg
+Icon=@prefix@/share/@PACKAGE@/vn/image/icon.svg
Terminal=false
Type=Application
Categories=GNOME;GTK;Office;
diff --git a/module/Makefile.am b/module/Makefile.am
index b2980bc..b1c3b83 100644
--- a/module/Makefile.am
+++ b/module/Makefile.am
@@ -1,5 +1,5 @@
+include $(top_srcdir)/Makefile.decl
SUBDIRS = \
src \
- data \
- sql
+ data
\ No newline at end of file
diff --git a/module/data/consulter.glade b/module/data/consulter.glade
index 34a0453..b2638a9 100644
--- a/module/data/consulter.glade
+++ b/module/data/consulter.glade
@@ -1,7 +1,7 @@
-
+
False
diff --git a/vn/image/icon-debug.svg b/vn/image/icon-debug.svg
new file mode 100644
index 0000000..979f5ba
--- /dev/null
+++ b/vn/image/icon-debug.svg
@@ -0,0 +1,419 @@
+
+
+
+
\ No newline at end of file
diff --git a/vn/image/icon.svg b/vn/image/icon.svg
index 010caec..6f0807d 100644
--- a/vn/image/icon.svg
+++ b/vn/image/icon.svg
@@ -18,541 +18,391 @@
viewBox="0 0 150.00001 116.64392"
enable-background="new 0 0 272.352 211.738"
xml:space="preserve"
- inkscape:version="0.48.1 r9760"
+ inkscape:version="0.48.4 r9939"
sodipodi:docname="icon.svg">image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+ id="metadata262">image/svg+xml
\ No newline at end of file
diff --git a/vn/vn-batch.c b/vn/vn-batch.c
index 1938ee6..95d621c 100644
--- a/vn/vn-batch.c
+++ b/vn/vn-batch.c
@@ -40,6 +40,7 @@ void vn_batch_add (VnBatch * obj, GObject * child)
g_return_if_fail (G_IS_OBJECT (child));
obj->objects = g_list_prepend (obj->objects, child);
+ obj->count++;
}
/**
@@ -54,6 +55,23 @@ void vn_batch_remove (VnBatch * obj, GObject * child)
g_return_if_fail (VN_IS_BATCH (obj));
obj->objects = g_list_remove (obj->objects, child);
+ obj->count--;
+}
+
+/**
+ * vn_batch_get_objects_list:
+ * @obj: a #VnBatch
+ *
+ * Returns all the #GObjects in @obj, copying the list.
+ *
+ * Return value: (transfer container) (element-type GObject): a #GList with all
+ * the objects, that must be freed with #g_list_free
+ **/
+GList * vn_batch_get_objects_list (VnBatch * obj)
+{
+ g_return_val_if_fail (VN_IS_BATCH (obj), NULL);
+
+ return g_list_copy (obj->objects);
}
/**
@@ -62,14 +80,29 @@ void vn_batch_remove (VnBatch * obj, GObject * child)
*
* Returns all the #GObjects in @obj.
*
- * Return value: (transfer container) (element-type GObject): a #GList with all
- * the objects, that must be freed with #g_list_free
+ * Return value: (transfer none) (element-type GObject): a #GList with all
+ * the objects, that must not be freed
**/
-GList * vn_batch_get_objects (VnBatch * obj)
+const GList * vn_batch_get_objects (VnBatch * obj)
{
g_return_val_if_fail (VN_IS_BATCH (obj), NULL);
- return g_list_copy (obj->objects);
+ return obj->objects;
+}
+
+/**
+ * vn_batch_get_length:
+ * @obj: a #VnBatch
+ *
+ * Returns the number of childs currently contained in @obj.
+ *
+ * Return value: the number of childs
+ **/
+guint vn_batch_get_length (VnBatch * obj)
+{
+ g_return_val_if_fail (VN_IS_BATCH (obj), 0);
+
+ return obj->count;
}
static void vn_batch_buildable_add_child (GtkBuildable * obj,
@@ -83,6 +116,7 @@ static void vn_batch_buildable_add_child (GtkBuildable * obj,
static void vn_batch_init (VnBatch * obj)
{
obj->objects = NULL;
+ obj->count = 0;
}
static void vn_batch_finalize (VnBatch * obj)
diff --git a/vn/vn-batch.h b/vn/vn-batch.h
index dd38fb6..7a6deae 100644
--- a/vn/vn-batch.h
+++ b/vn/vn-batch.h
@@ -31,10 +31,15 @@
typedef struct _VnBatch VnBatch;
typedef struct _VnBatchClass VnBatchClass;
+/**
+ * VnBatch:
+ * @objects: (element-type GObject):
+ **/
struct _VnBatch
{
GObject parent;
GList * objects;
+ guint count;
};
struct _VnBatchClass
@@ -44,10 +49,12 @@ struct _VnBatchClass
GType vn_batch_get_type ();
-void vn_batch_add (VnBatch * obj
- ,GObject * child);
-void vn_batch_remove (VnBatch * obj
- ,GObject * child);
-GList * vn_batch_get_objects (VnBatch * obj);
+void vn_batch_add (VnBatch * obj
+ ,GObject * child);
+void vn_batch_remove (VnBatch * obj
+ ,GObject * child);
+const GList * vn_batch_get_objects (VnBatch * obj);
+GList * vn_batch_get_objects_list (VnBatch * obj);
+guint vn_batch_get_length (VnBatch * obj);
#endif
\ No newline at end of file
diff --git a/vn/vn-builder.c b/vn/vn-builder.c
index 931cb63..99388eb 100644
--- a/vn/vn-builder.c
+++ b/vn/vn-builder.c
@@ -67,13 +67,9 @@ guint vn_builder_load_file (VnBuilder * obj, DbConn * conn, const gchar * filena
GSList * objects = gtk_builder_get_objects (builder);
for (n = objects; n; n = n->next)
- if (VN_IS_COMBO (n->data)
- || VN_IS_COMPLETION (n->data)
- || VN_IS_COLUMN_COMBO (n->data)
- || DB_IS_MODEL (n->data)
- || DB_IS_ITERATOR (n->data))
- g_object_set (n->data, "conn", conn, NULL);
-
+ if (DB_IS_MODEL (n->data))
+ db_model_set_conn (n->data, conn);
+
g_slist_free (objects);
}
diff --git a/vn/vn-column.c b/vn/vn-column.c
index 7a122e4..93e61b3 100644
--- a/vn/vn-column.c
+++ b/vn/vn-column.c
@@ -31,12 +31,12 @@ static void vn_column_value_changed (VnColumn * obj, const gchar * path, const G
&iter, obj->column_index, value, NULL);
}
-static void vn_column_data_func (GtkTreeViewColumn * col, GtkCellRenderer * cell,
+static void vn_column_data_func (GtkTreeViewColumn * col, GtkCellRenderer * cell,
GtkTreeModel * model, GtkTreeIter * iter, VnColumn * obj)
{
- gchar * background;
+ GdkRGBA * background;
DbIter dbiter;
- DbModel * dbmodel;
+ DbModelRowOp ops;
GValue value = {0};
gtk_tree_model_get_value (model, iter, obj->column_index, &value);
@@ -44,18 +44,19 @@ static void vn_column_data_func (GtkTreeViewColumn * col, GtkCellRenderer * cell
g_value_unset (&value);
vn_gtk_tree_iter_to_db_iter (iter, &dbiter);
- g_object_get (model, "model", &dbmodel, NULL);
- DbModelRowOp ops = db_model_get_row_operations (dbmodel, &dbiter);
- g_object_unref (dbmodel);
+ ops = db_model_get_row_operations (
+ vn_model_get_model (VN_MODEL (model))
+ ,&dbiter
+ );
if (ops & DB_MODEL_ROW_OP_DELETE)
- background = "#fcc";
+ background = obj->red;
else if (ops & DB_MODEL_ROW_OP_INSERT || ops & DB_MODEL_ROW_OP_UPDATE)
- background = "#cfc";
+ background = obj->green;
else
background = NULL;
- g_object_set (cell, "cell-background", background, NULL);
+ g_object_set (cell, "cell-background-rgba", background, NULL);
}
static void vn_column_set_renderer (VnColumn * obj, GtkCellRenderer * cell)
@@ -86,7 +87,7 @@ static void vn_column_update_column_index (VnColumn * obj)
gtk_tree_view_column_set_sort_column_id (
GTK_TREE_VIEW_COLUMN (obj), obj->column_index);
}
- }
+ }
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public
@@ -163,7 +164,7 @@ void vn_column_set_column_index (VnColumn * obj, gint index)
*
* Gets if the column can be edited by the user.
*
- * Return value: %TRUE if its editable, %FALSE otherwhise
+ * Return value: %TRUE if it's editable, %FALSE otherwhise
**/
gboolean vn_column_get_editable (VnColumn * obj)
{
@@ -177,7 +178,7 @@ gboolean vn_column_get_editable (VnColumn * obj)
* @obj: the #VnColumn
* @editable: a %gboolean indicating whether the column value is editable
*
- * Sets if the column could be edited by the user.
+ * Sets if the column can be edited by the user.
**/
void vn_column_set_editable (VnColumn * obj, gboolean editable)
{
@@ -187,6 +188,38 @@ void vn_column_set_editable (VnColumn * obj, gboolean editable)
VN_COLUMN_GET_CLASS (obj)->set_editable (obj, editable);
}
+/**
+ * vn_column_get_null:
+ * @obj: the #VnColumn
+ *
+ * Gets if the column can be set to null by the user.
+ *
+ * Return value: %TRUE if it can be, %FALSE otherwhise
+ **/
+gboolean vn_column_get_null (VnColumn * obj)
+{
+ g_return_val_if_fail (VN_IS_COLUMN (obj), FALSE);
+
+ return obj->null;
+}
+
+/**
+ * vn_column_set_null:
+ * @obj: the #VnColumn
+ * @null: a %gboolean indicating whether the column value can be null
+ *
+ * Sets if the column can be set to null by the user.
+ **/
+void vn_column_set_null (VnColumn * obj, gboolean null)
+{
+ g_return_if_fail (VN_IS_COLUMN (obj));
+
+ obj->null = null;
+
+ if (VN_COLUMN_GET_CLASS (obj)->set_null)
+ VN_COLUMN_GET_CLASS (obj)->set_null (obj, null);
+}
+
/**
* vn_column_get_model:
* @obj: the #VnColumn
@@ -257,7 +290,7 @@ void vn_column_model_changed (VnColumn * obj)
VnColumnClass * klass;
g_return_if_fail (VN_IS_COLUMN (obj));
-
+
klass = VN_COLUMN_GET_CLASS (obj);
vn_column_update_column_index (obj);
@@ -272,6 +305,7 @@ enum
PROP_COLUMN_INDEX = 1
,PROP_COLUMN_NAME
,PROP_EDITABLE
+ ,PROP_NULL
};
static void vn_column_set_property (VnColumn * obj, guint id,
@@ -288,6 +322,9 @@ static void vn_column_set_property (VnColumn * obj, guint id,
case PROP_EDITABLE:
vn_column_set_editable (obj, g_value_get_boolean (value));
break;
+ case PROP_NULL:
+ vn_column_set_null (obj, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
}
@@ -307,6 +344,9 @@ static void vn_column_get_property (VnColumn * obj, guint id,
case PROP_EDITABLE:
g_value_set_boolean (value, obj->editable);
break;
+ case PROP_NULL:
+ g_value_set_boolean (value, obj->null);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec);
}
@@ -318,10 +358,17 @@ static void vn_column_init (VnColumn * obj)
{
obj->column_index = -1;
obj->column_name = NULL;
+ obj->red = g_new (GdkRGBA, 1);
+ gdk_rgba_parse (obj->red, "#fcc");
+ obj->green = g_new (GdkRGBA, 1);
+ gdk_rgba_parse (obj->green, "#cfc");
}
static void vn_column_finalize (VnColumn * obj)
{
+ gdk_rgba_free (obj->red);
+ gdk_rgba_free (obj->green);
+
G_OBJECT_CLASS (vn_column_parent_class)->finalize (G_OBJECT (obj));
}
@@ -356,4 +403,11 @@ static void vn_column_class_init (VnColumnClass * klass)
,FALSE
,G_PARAM_CONSTRUCT | G_PARAM_READWRITE
));
+ g_object_class_install_property (k, PROP_NULL,
+ g_param_spec_boolean ("null"
+ ,_("Null")
+ ,_("Whether the field value can be of type GVN_TYPE_NULL")
+ ,FALSE
+ ,G_PARAM_CONSTRUCT | G_PARAM_READWRITE
+ ));
}
diff --git a/vn/vn-column.h b/vn/vn-column.h
index 09a3447..8431702 100644
--- a/vn/vn-column.h
+++ b/vn/vn-column.h
@@ -36,6 +36,7 @@ typedef void (*VnColumnSetValueFunc) (VnColumn * obj, GtkTreeModel * model, Gtk
typedef void (*VnColumnValuechangedFunc) (VnColumn * obj, const gchar * path, const GValue * value);
typedef void (*VnColumnSetRendererFunc) (VnColumn * obj, GtkCellRenderer * cell);
typedef void (*VnColumnSetEditableFunc) (VnColumn * obj, gboolean editable);
+typedef void (*VnColumnSetNullFunc) (VnColumn * obj, gboolean null);
typedef void (*VnColumnModelChangedFunc) (VnColumn * obj);
struct _VnColumn
@@ -45,6 +46,9 @@ struct _VnColumn
gint column_index;
gchar * column_name;
gboolean editable;
+ gboolean null;
+ GdkRGBA * red;
+ GdkRGBA * green;
VnColumnSetValueFunc set_value;
};
@@ -55,6 +59,7 @@ struct _VnColumnClass
VnColumnValuechangedFunc value_changed;
VnColumnSetRendererFunc set_renderer;
VnColumnSetEditableFunc set_editable;
+ VnColumnSetNullFunc set_null;
VnColumnModelChangedFunc model_changed;
};
@@ -65,6 +70,8 @@ gint vn_column_get_column_index (VnColumn * obj);
void vn_column_set_column_index (VnColumn * obj, gint index);
gboolean vn_column_get_editable (VnColumn * obj);
void vn_column_set_editable (VnColumn * obj, gboolean editable);
+gboolean vn_column_get_null (VnColumn * obj);
+void vn_column_set_null (VnColumn * obj, gboolean null);
DbModel * vn_column_get_model (VnColumn * obj);
gboolean vn_column_get_iter (VnColumn * obj, const gchar * path, DbIter * iter);
void vn_column_model_changed (VnColumn * obj);
diff --git a/vn/vn-form.c b/vn/vn-form.c
index f83435e..4c70485 100644
--- a/vn/vn-form.c
+++ b/vn/vn-form.c
@@ -53,20 +53,14 @@ void vn_form_open (VnForm * obj)
{
gchar * buffer;
gchar * ui_file = g_strdup_printf ("%s/%s.ui", dir, obj->name);
- GError * err = NULL;
- if (g_file_get_contents (ui_file, &buffer, NULL, &err))
+ if (g_file_get_contents (ui_file, &buffer, NULL, NULL))
{
obj->ui = buffer;
g_object_ref (obj->actions);
}
else
- {
- g_warning ("VnForm: Actions were defined for %s but no UI "
- "definition was found.", obj->name);
- g_error_free (err);
obj->actions = NULL;
- }
g_free (ui_file);
}
diff --git a/vn/vn-grid.c b/vn/vn-grid.c
index 4e24e07..9ffa82e 100644
--- a/vn/vn-grid.c
+++ b/vn/vn-grid.c
@@ -91,19 +91,21 @@ static void vn_grid_on_iter_changed (DbIterator * iterator, GtkTreeView * obj)
gtk_tree_selection_unselect_all (selection);
}
+static void vn_grid_on_model_changed (VnGrid * obj, GParamSpec * spec, gpointer data)
+{
+ GList * n, * columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (obj));
+
+ for (n = columns; n; n = n->next)
+ if (VN_IS_COLUMN (n->data))
+ vn_column_model_changed (n->data);
+
+ g_list_free (columns);
+}
+
static void vn_grid_on_status_changed (DbIterator * iterator, gboolean ready, VnGrid * obj)
{
- GList * n;
- GList * columns;
-
- obj->model = db_iterator_get_model (iterator);
- columns = gtk_tree_view_get_columns (GTK_TREE_VIEW (obj));
-
- for (n = columns; n; n = n->next)
- if (VN_IS_COLUMN (n->data))
- vn_column_model_changed (n->data);
-
- g_list_free (columns);
+ obj->model = db_model_holder_get_model (DB_MODEL_HOLDER (iterator));
+ vn_grid_on_model_changed (obj, NULL, NULL);
if (ready)
{
@@ -205,7 +207,7 @@ DbModel * vn_grid_get_model (VnGrid * obj)
* Return value: (transfer none): the #VnColumn assigned to the new column.
**/
VnColumn * vn_grid_insert_column (VnGrid * obj, gint position, gint column_index,
- const gchar * title, GType column_type, gboolean editable, gboolean expand)
+ const gchar * title, GType column_type, gboolean editable, gboolean expand)
{
GtkTreeViewColumn * column;
@@ -223,6 +225,7 @@ VnColumn * vn_grid_insert_column (VnGrid * obj, gint position, gint column_index
,"editable" ,editable
,NULL
);
+
gtk_tree_view_append_column (GTK_TREE_VIEW (obj), column);
return VN_COLUMN (column);
}
@@ -295,7 +298,7 @@ VnGridProp;
static void vn_grid_set_property (VnGrid * obj, guint id,
const GValue * value, GParamSpec * pspec)
-{
+{
switch (id)
{
case PROP_ITERATOR:
@@ -329,11 +332,16 @@ static void vn_grid_init (VnGrid * obj)
gtk_tree_view_get_selection (GTK_TREE_VIEW (obj)),
GTK_SELECTION_SINGLE
);
+
+ g_signal_connect (obj, "notify::model",
+ G_CALLBACK (vn_grid_on_model_changed), NULL);
}
static void vn_grid_finalize (VnGrid * obj)
{
vn_grid_set_iterator (obj, NULL);
+ g_signal_handlers_disconnect_by_func (obj, vn_grid_on_model_changed, NULL);
+
G_OBJECT_CLASS (vn_grid_parent_class)->finalize (G_OBJECT (obj));
}
@@ -351,4 +359,4 @@ static void vn_grid_class_init (VnGridClass * k)
,DB_TYPE_ITERATOR
,G_PARAM_READWRITE
));
-}
+}
\ No newline at end of file
diff --git a/vn/vn-gui.c b/vn/vn-gui.c
index f7cd705..402e041 100644
--- a/vn/vn-gui.c
+++ b/vn/vn-gui.c
@@ -1362,8 +1362,8 @@ static void vn_gui_set_property (VnGui * obj, guint id,
switch (id)
{
case PROP_CONN:
- {
- gchar * query_path = g_build_path (G_SEARCHPATH_SEPARATOR_S
+ {
+ gchar * query_path = g_build_path (G_SEARCHPATH_SEPARATOR_S
,_VN_MODULE_QUERY_DIR
,g_getenv ("VN_MODULE_QUERY_PATH")
,NULL
@@ -1392,7 +1392,7 @@ static void vn_gui_set_property (VnGui * obj, guint id,
obj->app_title[0] = g_ascii_toupper (obj->app_title[0]);
config_dir = g_build_filename (g_get_user_config_dir (), app_name, NULL);
- g_mkdir_with_parents (config_dir, 0600);
+ g_mkdir_with_parents (config_dir, 0700);
obj->config_file = g_build_filename (config_dir, "gui.ini", NULL);
g_free (config_dir);
diff --git a/vn/vn-login.c b/vn/vn-login.c
index 520597b..d1536f8 100644
--- a/vn/vn-login.c
+++ b/vn/vn-login.c
@@ -88,6 +88,7 @@ static void vn_login_show (VnLogin * obj)
obj->pass = vn_builder_get (builder, "password");
obj->remember = vn_builder_get (builder, "remember");
obj->connect = vn_builder_get (builder, "connect");
+ obj->stop = vn_builder_get (builder, "stop");
obj->settings_button = vn_builder_get (builder, "settings");
obj->spinner = vn_builder_get (builder, "spinner");
obj->settings_dialog = vn_builder_get (builder, "settings-dialog");
@@ -123,6 +124,7 @@ static void vn_login_show (VnLogin * obj)
gtk_widget_show_all (GTK_WIDGET (obj->window));
gtk_widget_grab_focus (GTK_WIDGET (obj->user));
gtk_widget_hide (obj->spinner);
+ gtk_widget_hide (obj->stop);
if (autologin)
gtk_button_clicked (obj->connect);
@@ -140,9 +142,17 @@ static void vn_login_set_loading (VnLogin * obj, gboolean loading)
gtk_widget_set_sensitive (GTK_WIDGET (obj->remember), !loading);
if (loading)
+ {
gtk_widget_show (obj->spinner);
+ gtk_widget_show (obj->stop);
+ gtk_widget_hide (GTK_WIDGET (obj->connect));
+ }
else
+ {
gtk_widget_hide (obj->spinner);
+ gtk_widget_hide (obj->stop);
+ gtk_widget_show (GTK_WIDGET (obj->connect));
+ }
}
/*
@@ -367,6 +377,11 @@ void vn_login_cb_connect_clicked (GtkButton * button, VnLogin * obj)
(GThreadFunc) vn_login_thread, connect_data);
}
+void vn_login_cb_stop_clicked (GtkButton * button, VnLogin * obj)
+{
+
+}
+
/*
* Closes the application when login window is destroyed.
*/
diff --git a/vn/vn-login.h b/vn/vn-login.h
index a40d813..8960a3a 100644
--- a/vn/vn-login.h
+++ b/vn/vn-login.h
@@ -46,6 +46,7 @@ struct _VnLogin
GtkEntry * pass;
GtkToggleButton * remember;
GtkButton * connect;
+ GtkWidget * stop;
GtkButton * settings_button;
GtkWidget * spinner;
diff --git a/vn/vn-model.c b/vn/vn-model.c
index ff48c1f..debf93d 100644
--- a/vn/vn-model.c
+++ b/vn/vn-model.c
@@ -23,13 +23,27 @@
*
* Creates a new #VnModel with @model as the data model.
*
- * Return value: (transfer full): a #VnModel.
+ * Return value: (transfer full): a #VnModel.
**/
VnModel * vn_model_new (DbModel * model)
{
return g_object_new (VN_TYPE_MODEL, "model", model, NULL);
}
+/**
+ * vn_model_get_model:
+ * @obj: a #VnModel
+ *
+ * Passes the #DbModel used internally by @model.
+ *
+ * Return value: (transfer none): a #DbModel.
+ **/
+DbModel * vn_model_get_model (VnModel * obj)
+{
+ g_return_val_if_fail (VN_IS_MODEL (obj), NULL);
+
+ return obj->model;
+}
/**
* vn_gtk_tree_iter_from_db_iter:
* @dest_iter: the #GtkTreeIter to set using the data on @src_iter
diff --git a/vn/vn-model.h b/vn/vn-model.h
index 1783fb8..0fa87cd 100644
--- a/vn/vn-model.h
+++ b/vn/vn-model.h
@@ -51,6 +51,7 @@ struct _VnModelClass
GType vn_model_get_type ();
VnModel * vn_model_new (DbModel * model);
+DbModel * vn_model_get_model (VnModel * obj);
gboolean vn_model_iter_is_valid (GtkTreeIter * iter, GtkTreeModel * model);
void vn_gtk_tree_iter_from_db_iter (GtkTreeIter * dest_iter
,const DbIter * src_iter);