This repository has been archived on 2024-07-15. You can view files and clone it, but cannot push or open issues or pull requests.
hedera/db/db-simple-iterator.c

432 lines
12 KiB
C

/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "db-simple-iterator.h"
#include "db-model-holder.h"
#include "db-param.h"
static void db_simple_iterator_set_iter (DbSimpleIterator * self, DbIter * iter);
static void db_simple_iterator_model_holder_init (DbModelHolderInterface * iface);
static void db_simple_iterator_iterator_init (DbIteratorInterface * iface);
/**
* SECTION:db-simple-iterator
* @short_description: manages a iterator with its events
* @title: DbSimpleIterator
*
* The #DbSimpleIterator manages a connection with a data base. The function
* db_simple_iterator_new() creates a new #DbSimpleIterator.
*/
G_DEFINE_TYPE_WITH_CODE (DbSimpleIterator, db_simple_iterator, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (DB_TYPE_MODEL_HOLDER,
db_simple_iterator_model_holder_init)
G_IMPLEMENT_INTERFACE (DB_TYPE_ITERATOR,
db_simple_iterator_iterator_init)
);
/**
* DbSimpleIterator:
* @params: (element-type Db.Param):
**/
/**
* db_simple_iterator_new:
* @model: the #DbModel used by iterator.
*
* Creates a new #DbSimpleIterator.
*
* Return value: (transfer full): a #DbSimpleIterator.
**/
DbIterator * db_simple_iterator_new (DbModel * model)
{
return g_object_new (DB_TYPE_SIMPLE_ITERATOR, "model", model, NULL);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private
static void db_simple_iterator_unref_param (DbSimpleIterator * self, DbParam * param)
{
self->params = g_list_remove (self->params, param);
}
/*
* #DbSimpleIterator instances call this function every time line in
* the model is changed.
*/
static void db_simple_iterator_row_num_changed (DbSimpleIterator * self)
{
if (self->iter)
self->row = db_model_get_path (self->model, self->iter);
else if (!self->remember_selection)
self->row = 0;
db_iterator_row_num_changed (DB_ITERATOR (self));
}
/*
* #DbSimpleIterator instances call this function every time the data of the
* params must be updated.
*/
static void db_simple_iterator_iter_changed (DbSimpleIterator * self)
{
db_simple_iterator_row_num_changed (self);
db_iterator_iter_changed (DB_ITERATOR (self));
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ DbModelHolder methods
static void db_simple_iterator_set_model_mode (DbSimpleIterator * self)
{
if (self->mode == DB_ITERATOR_MODE_ON_CHANGE)
db_model_set_mode (self->model, DB_MODEL_MODE_ON_CHANGE);
else
db_model_set_mode (self->model, DB_MODEL_MODE_ON_DEMAND);
}
/*
* Function called when row is inserted on the model.
*/
static void db_simple_iterator_on_model_line_inserted (DbModel * model, DbIter * iter, DbSimpleIterator * self)
{
db_iterator_data_changed (DB_ITERATOR (self));
}
/*
* Function called when row is updated on the model.
*/
static void db_simple_iterator_on_model_line_updated_after (DbModel * model, DbIter * iter, DbSimpleIterator * self)
{
if (self->iter && db_iter_compare (iter, self->iter))
db_simple_iterator_iter_changed (self);
db_iterator_data_changed (DB_ITERATOR (self));
}
/*
* Function called when row is deleted on the model.
*/
static void db_simple_iterator_on_model_line_deleted (DbModel * model, gint row, DbSimpleIterator * self)
{
if (self->iter && row == self->row)
{
DbIter iter;
if (db_model_get_iter (model, &iter, row + 1)
|| db_model_get_iter (model, &iter, row - 1))
db_simple_iterator_set_iter (self, &iter);
else
db_simple_iterator_set_iter (self, NULL);
}
}
static void db_simple_iterator_on_model_line_deleted_after (DbModel * model, gint row, DbSimpleIterator * self)
{
if (self->iter)
db_simple_iterator_row_num_changed (self);
db_iterator_data_changed (DB_ITERATOR (self));
}
/*
* Function called when model rows are reordered.
*/
static void db_simple_iterator_on_model_lines_reordered (DbModel * model,
gint column, gint * new_order, DbSimpleIterator * self)
{
if (self->iter)
db_simple_iterator_row_num_changed (self);
}
/*
* Function called when model status changes.
*/
static void db_simple_iterator_on_model_status_changed (DbModel * model, DbModelStatus status, DbSimpleIterator * self)
{
if (status == DB_MODEL_STATUS_READY)
{
DbIter iter;
db_iterator_status_changed (DB_ITERATOR (self), TRUE);
if (self->row >= 0 && self->row < db_model_get_nrows (model)
&& db_model_get_iter (model, &iter, self->row))
db_simple_iterator_set_iter (self, &iter);
else
db_simple_iterator_set_iter (self, NULL);
}
else
{
db_iterator_status_changed (DB_ITERATOR (self), FALSE);
db_simple_iterator_set_iter (self, NULL);
}
}
/*
* Function called when model operations are done.
*/
static void db_simple_iterator_on_model_operations_done (DbModel * model, DbSimpleIterator * self)
{
db_iterator_operations_done (DB_ITERATOR (self));
}
static DbModel * db_simple_iterator_get_model (DbSimpleIterator * self)
{
g_return_val_if_fail (DB_IS_SIMPLE_ITERATOR (self), NULL);
return self->model;
}
static void db_simple_iterator_set_model (DbSimpleIterator * self, DbModel * model)
{
if (!model)
return;
if (!self->model)
{
self->model = g_object_ref (model);
g_object_connect (self->model
,"signal::line-inserted", db_simple_iterator_on_model_line_inserted, self
,"signal-after::line-updated", db_simple_iterator_on_model_line_updated_after, self
,"signal::line-deleted", db_simple_iterator_on_model_line_deleted, self
,"signal-after::line-deleted", db_simple_iterator_on_model_line_deleted_after, self
,"signal::lines-reordered", db_simple_iterator_on_model_lines_reordered, self
,"signal::status-changed", db_simple_iterator_on_model_status_changed, self
,"signal::operations-done", db_simple_iterator_on_model_operations_done, self
,NULL
);
db_simple_iterator_set_model_mode (self);
db_simple_iterator_on_model_status_changed (model,
db_model_get_status (model), self);
}
else
g_warning ("DbSimpleIterator: Can't reassign the 'model' property");
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ DbIterator methods
static gint db_simple_iterator_get_row (DbSimpleIterator * self)
{
g_return_val_if_fail (DB_IS_SIMPLE_ITERATOR (self), -1);
if (self->iter)
return self->row;
else
return -1;
}
static DbIteratorMode db_simple_iterator_get_mode (DbSimpleIterator * self)
{
g_return_val_if_fail (DB_IS_SIMPLE_ITERATOR (self), 0);
return self->mode;
}
static void db_simple_iterator_set_mode (DbSimpleIterator * self, DbIteratorMode mode)
{
g_return_if_fail (DB_IS_SIMPLE_ITERATOR (self));
self->mode = mode;
if (self->model)
db_simple_iterator_set_model_mode (self);
}
static gboolean db_simple_iterator_get_iter (DbSimpleIterator * self, DbIter ** iter)
{
g_return_val_if_fail (DB_IS_SIMPLE_ITERATOR (self), FALSE);
if (!self->iter)
return FALSE;
*iter = self->iter;
return TRUE;
}
static void db_simple_iterator_set_iter (DbSimpleIterator * self, DbIter * iter)
{
if (iter)
{
db_iter_free (self->iter);
self->iter = db_iter_copy (iter);
db_simple_iterator_iter_changed (self);
}
else if (self->iter)
{
if (!self->remember_selection)
self->row = 0;
db_iter_free (self->iter);
self->iter = NULL;
db_simple_iterator_iter_changed (self);
}
}
static gboolean db_simple_iterator_move_iter (DbSimpleIterator * self, DbIter * iter)
{
g_return_val_if_fail (DB_IS_SIMPLE_ITERATOR (self), FALSE);
if (self->iter && db_iter_compare (self->iter, iter))
return FALSE;
if (self->iter && self->mode != DB_ITERATOR_MODE_ON_DEMAND)
{
if (db_model_get_row_operations (self->model, self->iter) == DB_MODEL_ROW_OP_INSERT)
db_model_reverse_operations (self->model);
db_model_perform_operations (self->model, FALSE);
}
db_simple_iterator_set_iter (self, iter);
return TRUE;
}
static GList * db_simple_iterator_get_param_list (DbSimpleIterator * self)
{
g_return_val_if_fail (DB_IS_SIMPLE_ITERATOR (self), NULL);
return self->params;
}
static void db_simple_iterator_delete_selection (DbSimpleIterator * self)
{
g_return_if_fail (DB_IS_SIMPLE_ITERATOR (self));
if (self->model && self->iter)
db_model_delete (self->model, self->iter);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties
enum
{
PROP_MODEL = 1
,PROP_MODE
,PROP_REMEMBER_SELECTION
};
static void db_simple_iterator_set_property (DbSimpleIterator * self, guint id,
const GValue * value, GParamSpec * pspec)
{
switch (id)
{
case PROP_MODEL:
db_simple_iterator_set_model (self, g_value_get_object (value));
break;
case PROP_MODE:
db_simple_iterator_set_mode (self, g_value_get_enum (value));
break;
case PROP_REMEMBER_SELECTION:
self->remember_selection = g_value_get_boolean (value);
db_simple_iterator_row_num_changed (self);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec);
}
}
static void db_simple_iterator_get_property (DbSimpleIterator * self, guint id,
GValue * value, GParamSpec * pspec)
{
switch (id)
{
case PROP_MODEL:
g_value_set_object (value, self->model);
break;
case PROP_MODE:
g_value_set_enum (value, self->mode);
break;
case PROP_REMEMBER_SELECTION:
g_value_set_boolean (value, self->remember_selection);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec);
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class
static void db_simple_iterator_init (DbSimpleIterator * self)
{
self->params = NULL;
self->iter = NULL;
self->row = 0;
self->model = NULL;
}
static void db_simple_iterator_finalize (DbSimpleIterator * self)
{
GList * n;
for (n = self->params; n; n = n->next)
g_object_weak_unref (n->data,
(GWeakNotify) db_simple_iterator_unref_param, self);
g_list_free (self->params);
db_iter_free (self->iter);
self->iter = NULL;
if (self->model)
{
g_object_disconnect (self->model
,"any_signal", db_simple_iterator_on_model_line_inserted, self
,"any_signal", db_simple_iterator_on_model_line_updated_after, self
,"any_signal", db_simple_iterator_on_model_line_deleted, self
,"any_signal", db_simple_iterator_on_model_line_deleted_after, self
,"any_signal", db_simple_iterator_on_model_lines_reordered, self
,"any_signal", db_simple_iterator_on_model_status_changed, self
,"any_signal", db_simple_iterator_on_model_operations_done, self
,NULL
);
g_object_unref (self->model);
}
G_OBJECT_CLASS (db_simple_iterator_parent_class)->finalize (G_OBJECT (self));
}
static void db_simple_iterator_class_init (DbSimpleIteratorClass * klass)
{
GObjectClass * k = G_OBJECT_CLASS (klass);
k->set_property = (GObjectSetPropertyFunc) db_simple_iterator_set_property;
k->get_property = (GObjectGetPropertyFunc) db_simple_iterator_get_property;
k->finalize = (GObjectFinalizeFunc) db_simple_iterator_finalize;
g_object_class_override_property (k, PROP_MODEL, "data-model");
g_object_class_override_property (k, PROP_MODE, "mode");
g_object_class_override_property (k, PROP_REMEMBER_SELECTION, "remember-selection");
}
static void db_simple_iterator_model_holder_init (DbModelHolderInterface * iface)
{
iface->get_model = (DbModelHolderGetModelFunc) db_simple_iterator_get_model;
iface->set_model = (DbModelHolderSetModelFunc) db_simple_iterator_set_model;
}
static void db_simple_iterator_iterator_init (DbIteratorInterface * iface)
{
iface->get_mode = (DbIteratorGetMode) db_simple_iterator_get_mode;
iface->set_mode = (DbIteratorSetMode) db_simple_iterator_set_mode;
iface->get_row = (DbIteratorGetRow) db_simple_iterator_get_row;
iface->get_iter = (DbIteratorGetIter) db_simple_iterator_get_iter;
iface->set_iter = (DbIteratorSetIter) db_simple_iterator_set_iter;
iface->move_iter = (DbIteratorMoveIter) db_simple_iterator_move_iter;
iface->get_param_list = (DbIteratorGetParamList) db_simple_iterator_get_param_list;
iface->delete_selection = (DbIteratorDeleteSelection) db_simple_iterator_delete_selection;
}