/* * 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 "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; }