/* * Copyright (C) 2012 - 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 "sql-batch.h" #include "sql-value.h" /** * SECTION: sql-batch * @Short_description: binds identifiers with #SqlObject * @Title: SqlBatch * * The #SqlBatch is a collection of identifiers bound to #SqlObject in * an SQL statement. These identifiers are replaced by the value represented * by the #SqlObject when the statement is renderend. **/ G_DEFINE_TYPE (SqlBatch, sql_batch, G_TYPE_INITIALLY_UNOWNED); enum { CHANGED ,LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; SqlBatch * sql_batch_new () { return g_object_new (SQL_TYPE_BATCH, NULL); } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Private static void sql_batch_item_changed (SqlObject * item, SqlBatch * self) { if (!self->frozen) sql_batch_changed (self); } static void sql_batch_free_item (SqlBatch * self, SqlObject * item) { if (item) { g_signal_handlers_disconnect_by_func (item, sql_batch_item_changed, self); g_object_unref (item); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Public /** * sql_batch_is_ready: * @self: a #SqlBatch * * Checks if @self and all of its elements are ready to be rendered. * * Return value: %TRUE if ready, %FALSE otherwise. **/ gboolean sql_batch_is_ready (SqlBatch * self) { gpointer item; GHashTableIter iter; g_return_val_if_fail (SQL_IS_BATCH (self), FALSE); g_hash_table_iter_init (&iter, self->items); while (g_hash_table_iter_next (&iter, NULL, &item)) if (!item || !sql_object_is_ready (item)) return FALSE; return TRUE; } /** * sql_batch_get: * @self: a #SqlBatch * @id: the id of the #SqlHolder * * Gets a held object by its id. * * Return value: (transfer none): the #SqlObject if an object with that id * exists, %NULL otherwise **/ SqlObject * sql_batch_get (SqlBatch * self, const gchar * id) { g_return_val_if_fail (SQL_IS_BATCH (self), NULL); g_return_val_if_fail (id, NULL); if (self->items) return g_hash_table_lookup (self->items, id); return NULL; } /** * sql_batch_add: * @self: a #SqlBatch * @id: the id of the #SqlHolder * @item: the #SqlObject * * Adds a new item to the batch. **/ void sql_batch_add (SqlBatch * self, const gchar * id, SqlObject * item) { g_return_if_fail (SQL_IS_BATCH (self)); g_return_if_fail (id); g_return_if_fail (SQL_IS_OBJECT (item) || !item); sql_batch_remove (self, id); if (item) { g_object_ref_sink (item); g_signal_connect (item, "changed", G_CALLBACK (sql_batch_item_changed), self); } g_hash_table_replace (self->items, g_strdup (id), item); sql_batch_item_changed (NULL, self); } /** * sql_batch_add_param: * @self: a #SqlBatch * @id: the id assigned to the item * @param: the parameter **/ void sql_batch_add_from_param (SqlBatch * self, const gchar * id, GvnParam * param) { g_return_if_fail (SQL_IS_BATCH (self)); g_return_if_fail (id); g_return_if_fail (GVN_IS_PARAM (param)); sql_batch_add (self, id, sql_value_new_with_param (param)); } /** * sql_batch_add_value: * @self: a #SqlBatch * @id: the id assigned to the item * @value: the value **/ void sql_batch_add_from_value (SqlBatch * self, const gchar * id, const GValue * value) { g_return_if_fail (SQL_IS_BATCH (self)); g_return_if_fail (id); g_return_if_fail (G_IS_VALUE (value)); sql_batch_add (self, id, sql_value_new_with_value (value)); } /** * sql_batch_remove: * @self: a #SqlBatch * @id: the id of the #SqlHolder * * Removes a held object from the batch. **/ void sql_batch_remove (SqlBatch * self, const gchar * id) { g_return_val_if_fail (SQL_IS_BATCH (self), NULL); g_return_val_if_fail (id, NULL); SqlObject * item = sql_batch_get (self, id); if (item) { sql_batch_free_item (self, item); g_hash_table_remove (self->items, id); } } /** * sql_batch_merge: * @self: a #SqlBatch * @batch: a #SqlBatch * * Meges the batch with another batch. **/ void sql_batch_merge (SqlBatch * self, SqlBatch * batch) { GHashTableIter iter; gpointer key, value; g_return_if_fail (SQL_IS_BATCH (self)); g_return_if_fail (SQL_IS_BATCH (batch) || !batch); if (!batch) return; g_hash_table_iter_init (&iter, batch->items); while (g_hash_table_iter_next (&iter, &key, &value)) sql_batch_add (self, key, value); } /** * sql_batch_changed: * @self: a #SqlBatch * * Emits the changed signal on #SqlBatch. **/ void sql_batch_changed (SqlBatch * self) { g_return_if_fail (SQL_IS_BATCH (self)); g_signal_emit (self, signals[CHANGED], 0); } /** * sql_batch_freeze: * @self: a #SqlBatch * * Freezes the changed signal on #SqlBatch. **/ void sql_batch_freeze (SqlBatch * self) { g_return_if_fail (SQL_IS_BATCH (self)); self->frozen = TRUE; } /** * sql_batch_unfreeze: * @self: a #SqlBatch * * Unfreezes the changed signal on #SqlBatch. **/ void sql_batch_unfreeze (SqlBatch * self) { g_return_if_fail (SQL_IS_BATCH (self)); self->frozen = FALSE; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class static void sql_batch_init (SqlBatch * self) { self->items = g_hash_table_new_full ( g_str_hash ,g_str_equal ,g_free ,NULL ); self->frozen = FALSE; } static void sql_batch_finalize (SqlBatch * self) { gpointer item; GHashTableIter iter; g_hash_table_iter_init (&iter, self->items); while (g_hash_table_iter_next (&iter, NULL, &item)) sql_batch_free_item (self, item); g_hash_table_destroy (self->items); G_OBJECT_CLASS (sql_batch_parent_class)->finalize (G_OBJECT (self)); } static void sql_batch_class_init (SqlBatchClass * klass) { G_OBJECT_CLASS (klass)->finalize = (GObjectFinalizeFunc) sql_batch_finalize; /** * SqlBatch::changed: * @self: the object which emit the signal. * * This signal is emitted every time the batch or one of its attributes * is modified. */ signals[CHANGED] = g_signal_new ("changed", SQL_TYPE_BATCH, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); }