/* * 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-iterator.h" #define IS_READY(obj) (obj->model && db_model_get_status (obj->model) == DB_MODEL_STATUS_READY) /** * SECTION:db-iterator * @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 * * * */ G_DEFINE_TYPE (DbIterator, db_iterator, G_TYPE_OBJECT); enum { ITER_CHANGED ,DATA_CHANGED ,ROW_NUM_CHANGED ,STATUS_CHANGED ,OPERATIONS_DONE ,LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = {0}; /** * db_iterator_new: * @model: the #DbModel used by iterator. * * Creates a new #DbIterator. * * Return value: a #DbIterator. **/ 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) { obj->params = g_list_remove (obj->params, param); } /* * #DbIterator instances call this function every time line in * the model is changed. */ static void db_iterator_row_num_changed (DbIterator * obj) { if (obj->row_selected) obj->row = db_model_get_path (obj->model, &obj->iter); else if (!obj->remember_selection) obj->row = -1; g_signal_emit (obj, signals[ROW_NUM_CHANGED], 0); } /* * #DbIterator instances call this function every time the data of the params * mustbe updated. */ static void db_iterator_iter_changed (DbIterator * obj) { db_iterator_row_num_changed (obj); g_signal_emit (obj, signals[ITER_CHANGED], 0); } static void db_iterator_set_iter (DbIterator * obj, DbIter * iter) { if (iter) { obj->row_selected = TRUE; obj->iter = *iter; db_iterator_iter_changed (obj); } else if (obj->row_selected) { obj->row_selected = FALSE; db_iterator_iter_changed (obj); } } /* * Function called when row is inserted on the model. */ static void db_iterator_on_model_line_inserted (DbModel * model, DbIter * iter, DbIterator * obj) { g_signal_emit (obj, signals[DATA_CHANGED], 0); } /* * Function called when row is updated on the model. */ static void db_iterator_on_model_line_updated_after (DbModel * model, DbIter * iter, DbIterator * obj) { if (obj->row_selected && db_iter_compare (iter, &obj->iter)) db_iterator_iter_changed (obj); g_signal_emit (obj, signals[DATA_CHANGED], 0); } /* * 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; if (db_model_get_iter (model, &iter, row + 1) || db_model_get_iter (model, &iter, row - 1)) db_iterator_set_iter (obj, &iter); else db_iterator_set_iter (obj, NULL); } } static void db_iterator_on_model_line_deleted_after (DbModel * model, gint row, DbIterator * obj) { if (obj->row_selected) db_iterator_row_num_changed (obj); g_signal_emit (obj, signals[DATA_CHANGED], 0); } /* * Function called when model rows are reordered. */ static void db_iterator_on_model_lines_reordered (DbModel * model, gint column, gint * new_order, DbIterator * obj) { if (obj->row_selected) db_iterator_row_num_changed (obj); } /* * Function called when model status changes. */ static void db_iterator_on_model_status_changed (DbModel * model, DbModelStatus status, DbIterator * obj) { if (status == DB_MODEL_STATUS_READY) { DbIter iter; gint nrows = db_model_get_nrows (model); g_signal_emit (obj, signals[STATUS_CHANGED], 0, IS_READY(obj)); if (obj->row >= 0 && obj->row < nrows && db_model_get_iter (model, &iter, obj->row)) db_iterator_set_iter (obj, &iter); else db_iterator_set_iter (obj, NULL); } else { db_iterator_set_iter (obj, NULL); g_signal_emit (obj, signals[STATUS_CHANGED], 0, IS_READY(obj)); } } /* * Function called when model operations are done. */ static void db_iterator_on_model_operations_done (DbModel * model, DbIterator * obj) { g_signal_emit (obj, signals[OPERATIONS_DONE], 0); } static void db_iterator_set_model_mode (DbIterator * obj) { if (obj->mode == DB_ITERATOR_MODE_ON_CHANGE) db_model_set_mode (obj->model, DB_MODEL_MODE_ON_CHANGE); else db_model_set_mode (obj->model, DB_MODEL_MODE_ON_DEMAND); } /* * Sets the model used as a data source by iterator. */ static void db_iterator_set_model (DbIterator * obj, DbModel * model) { if (!model) return; if (!obj->model) { obj->model = g_object_ref (model); g_object_connect (obj->model ,"signal::lines-reordered", db_iterator_on_model_lines_reordered, obj ,"signal::line-inserted", db_iterator_on_model_line_inserted, obj ,"signal-after::line-updated", db_iterator_on_model_line_updated_after, obj ,"signal::line-deleted", db_iterator_on_model_line_deleted, obj ,"signal-after::line-deleted", db_iterator_on_model_line_deleted_after, obj ,"signal::status-changed", db_iterator_on_model_status_changed, obj ,"signal::operations-done", db_iterator_on_model_operations_done, obj ,NULL ); db_iterator_set_model_mode (obj); db_iterator_on_model_status_changed (model, db_model_get_status (model), obj); } else g_warning ("DbIterator: Can't reassign the 'model' property"); } /* * Check if the iterator has any selected row, otherwise issues a message. */ static gboolean db_iterator_check_row_selected (DbIterator * obj) { if (obj->row_selected) return TRUE; g_warning ("DbIterator: Row not selected"); 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 /** * db_iterator_get_row: * @obj: a #DbIterator * * Gets the selected row number. * * Return value: the row number **/ gint db_iterator_get_row (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), -1); if (obj->row_selected) return obj->row; else return -1; } /** * db_iterator_get_model: * @obj: a #DbIterator * * Gets the model used as a data source by iterator. * * Return value: (transfer none): the #DbModel **/ DbModel * db_iterator_get_model (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), NULL); 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 * * Gets if the iterator is ready. * * Return value: %TRUE if the iterator and its model are ready, %FALSE otherwise. **/ gboolean db_iterator_is_ready (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), FALSE); return IS_READY (obj); } /** * db_iterator_get_mode: * @obj: a #DbIterator * * Gets the mode in which the iterator is working. * * Return value: the #DbIteratorMode **/ DbIteratorMode db_iterator_get_mode (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), 0); return obj->mode; } /** * db_iterator_set_mode: * @obj: a #DbIterator * @mode: the #DbIteratorMode mode * * Sets the mode in which the iterator should work. **/ void db_iterator_set_mode (DbIterator * obj, DbIteratorMode mode) { g_return_if_fail (DB_IS_ITERATOR (obj)); obj->mode = mode; if (obj->model) db_iterator_set_model_mode (obj); } /** * db_iterator_get_iter: * @obj: a #DbIterator * @iter: (allow-none): return location for selected row iter, or %NULL. * * Gets the currently selected iter. * * Return value: %TRUE if any row is selected, %FALSE otherwise. **/ gboolean db_iterator_get_iter (DbIterator * obj, DbIter * iter) { g_return_val_if_fail (DB_IS_ITERATOR (obj), FALSE); if (!obj->row_selected) return FALSE; *iter = obj->iter; return TRUE; } /** * db_iterator_move_iter: * @obj: a #DbIterator * @iter: a #DbIter * * Moves the iterator cursor to the specified iter, if model is ready. **/ void db_iterator_move_iter (DbIterator * obj, DbIter * iter) { g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (IS_READY (obj)); g_return_if_fail (obj->model); if (obj->row_selected && db_iter_compare (&obj->iter, iter)) return; if (obj->mode != DB_ITERATOR_MODE_ON_DEMAND) db_model_perform_operations (obj->model, FALSE); db_iterator_set_iter (obj, iter); } /** * db_iterator_move_first: * @obj: a #DbIterator * * Moves the iterator cursor to the first row. **/ void db_iterator_move_first (DbIterator * obj) { DbIter iter; g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (obj->model); if (db_model_get_iter_first (obj->model, &iter)) db_iterator_move_iter (obj, &iter); } /** * db_iterator_move_last: * @obj: a #DbIterator * * Moves the iterator cursor to the last row. **/ void db_iterator_move_last (DbIterator * obj) { DbIter iter; g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (obj->model); if (db_model_get_last (obj->model, &iter)) db_iterator_move_iter (obj, &iter); } /** * db_iterator_move_previous: * @obj: a #DbIterator * * Moves the iterator cursor to the previous row, or displays a message if no * exists. If no selected row, attempts to move the cursor to the first row. **/ void db_iterator_move_previous (DbIterator * obj) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (obj->row_selected) { DbIter iter = obj->iter; if (db_model_iter_prev (obj->model, &iter)) db_iterator_move_iter (obj, &iter); else g_warning ( "Can't move the cursor to the previous " "row, because there are no more rows." ); } else db_iterator_move_first (obj); } /** * db_iterator_move_next: * @obj: a #DbIterator * * Moves the iterator cursor to the next row, or displays a message if no exists. * If no selected row, attempts to move the cursor to the first row. **/ void db_iterator_move_next (DbIterator * obj) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (obj->row_selected) { DbIter iter = obj->iter; if (db_model_iter_next (obj->model, &iter)) db_iterator_move_iter (obj, &iter); else g_warning ( "Can't move the cursor to the next " "row, because there are no more rows." ); } else db_iterator_move_first (obj); } /** * db_iterator_move_to: * @obj: a #DbIterator * @move: a #DbIteratorMove * * Moves the iterator cursor to the predefined position. **/ void db_iterator_move_to (DbIterator * obj, DbIteratorMove move) { switch (move) { case DB_ITERATOR_MOVE_FIRST: db_iterator_move_first (obj); break; case DB_ITERATOR_MOVE_PREVIOUS: db_iterator_move_previous (obj); break; case DB_ITERATOR_MOVE_NEXT: db_iterator_move_next (obj); break; case DB_ITERATOR_MOVE_LAST: db_iterator_move_last (obj); break; } } /** * db_iterator_insert: * @obj: a #DbIterator * * Inserts a new row in the model and moves the iter to it, if inserted. * successfully. **/ void db_iterator_insert (DbIterator * obj) { DbIter iter; g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (obj->model); if (obj->mode != DB_ITERATOR_MODE_ON_DEMAND) db_model_perform_operations (obj->model, FALSE); if (db_model_insert (obj->model, &iter)) db_iterator_set_iter (obj, &iter); } /** * db_iterator_delete: * @obj: a #DbIterator * * Deletes the currently selected row from the model, if any. **/ void db_iterator_delete (DbIterator * obj) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (db_iterator_check_row_selected (obj)) { db_model_delete (obj->model, &obj->iter); if (obj->mode != DB_ITERATOR_MODE_ON_DEMAND) db_model_perform_operations (obj->model, FALSE); } } /** * db_iterator_refresh: * @obj: a #DbIterator * * Refresh the data of the model handled by iterator. **/ void db_iterator_refresh (DbIterator * obj) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (obj->model) db_model_refresh (obj->model); }; /** * db_iterator_get_spec: * @obj: a #DbIterator * @column: the column index. * * Gets the spec from the model of the specified column index. * * Return value: (transfer none) (allow-none): a #GvnParamSpec or %NULL if * can't get it because the model isn't ready. **/ const GvnParamSpec * db_iterator_get_spec (DbIterator * obj, gint column) { g_return_val_if_fail (DB_IS_ITERATOR (obj), NULL); if (IS_READY (obj)) return db_model_get_spec (obj->model, column); else return NULL; } /** * db_iterator_get_value: * @obj: a #DbIterator * @column: the column index. * * Gets the value of the specified column index. * * Return value: (transfer none) (allow-none): the value or %NULL if * can't get it because the model isn't ready. **/ const GValue * db_iterator_get_value (DbIterator * obj, gint column) { g_return_val_if_fail (DB_IS_ITERATOR (obj), NULL); if (obj->row_selected) return db_model_get_value (obj->model, &obj->iter, column, NULL); return NULL; } /** * db_iterator_get_column_index: * @obj: a #DbIterator * @name: the name of a column of iterator. * * Retrieves the position in the query of the column called @name. * * Return value: the position of the column with name @name or -1 if there isn't * a column called name or if name is %NULL. **/ gint db_iterator_get_column_index (DbIterator * obj, const gchar * name) { g_return_val_if_fail (DB_IS_ITERATOR (obj), -1); g_return_val_if_fail (IS_READY (obj), -1); return db_model_get_column_index (obj->model, name); } /** * db_iterator_set_value: * @obj: a #DbIterator * @column: the column index. * @value: a #GValue with the new value. * @err: (out) (allow-none): the return location for a #GError or %NULL. * * Sets the value of the specified column index. **/ void db_iterator_set_value (DbIterator * obj, gint column, const GValue * value, GError ** err) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (db_iterator_check_row_selected (obj)) db_model_set_value (obj->model, &obj->iter, column, value, err); } /** * db_iterator_add_param: * @obj: a #DbIterator * @param: the param to add. * * Adds a #DbParam to the list of iterator params. **/ void db_iterator_add_param (DbIterator * obj, DbParam * param) { g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (DB_IS_PARAM (param)); db_param_set_iterator (param, obj); g_object_weak_ref (G_OBJECT (param), (GWeakNotify) db_iterator_unref_param, obj); obj->params = g_list_prepend (obj->params, param); } /** * db_iterator_get_param: * @obj: a #DbIterator * @column: the column name * * Creates a parameter for the specified column index and returns it. * * Return value: (transfer none): a #GvnParam **/ GvnParam * db_iterator_get_param (DbIterator * obj, const gchar * column) { GList * n; GvnParam * param; g_return_val_if_fail (DB_IS_ITERATOR (obj), NULL); g_return_val_if_fail (column, NULL); for (n = obj->params; n; n = n->next) if (!g_strcmp0 (db_param_get_column_name (n->data), column)) break; if (!n) { param = db_param_new (column); db_iterator_add_param (obj, DB_PARAM (param)); } else param = n->data; return param; } /** * db_iterator_get_params: * @obj: a #DbIterator * * Gets a list of params linked with the iterator. The returned list shoud be freed. * * Return value: (element-type Db.Param) (transfer container): the #GList **/ GList * db_iterator_get_params (DbIterator * obj) { return g_list_copy (obj->params); } /** * db_iterator_bind_param: * @obj: a #DbIterator * @column: the column index. * @param: the column index. * * Binds the param to the specified column index. If you want to link the same * param several times you should use the db_iterator_get_param function. **/ void db_iterator_bind_param (DbIterator * obj, const gchar * column, GvnParam * param) { g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (GVN_IS_PARAM (obj)); gvn_param_set_master (param, db_iterator_get_param (obj, column) ); } /** * db_iterator_link: * @obj: a #DbIterator * @field: the field name in the iterator statement * @src: the source #DbIterator * @column: the column number of @src * * Links the iterator with another iterator parameter. **/ void db_iterator_link (DbIterator * obj, const gchar * field, DbIterator * src, const gchar * column) { g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (DB_IS_ITERATOR (src)); g_return_if_fail (field); db_iterator_link_with_param (obj, field, db_iterator_get_param (src, column)); } /** * db_iterator_link_with_param: * @obj: a #DbIterator * @field: the field name in the iterator statement * @param: the #GvnParam * * Links the iterator with a parameter. **/ void db_iterator_link_with_param (DbIterator * obj, const gchar * field, GvnParam * param) { g_return_if_fail (DB_IS_ITERATOR (obj)); g_return_if_fail (GVN_IS_PARAM (param)); g_return_if_fail (obj->model); g_return_if_fail (field); db_model_set_default_value_from_param (obj->model, field, param); } /** * db_iterator_get_nrows: * @obj: a #DbIterator * * Gets the number of rows in the model pointed by the iterator. * * Return value: the number of rows **/ gint db_iterator_get_nrows (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), 0); if (obj->model) return db_model_get_nrows (obj->model); return 0; } /** * db_iterator_get_update_flags: * @obj: a #DbIterator * * Gets the flags that indicate how a model can be modified. * * Return value: the flags **/ DbModelUpdateFlags db_iterator_get_update_flags (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), 0); if (obj->model) return db_model_get_update_flags (obj->model); return 0; } /** * db_iterator_perform_operations: * @obj: a #DbIterator * * Performs all pending operations on the model. **/ void db_iterator_perform_operations (DbIterator * obj) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (obj->model) db_model_perform_operations (obj->model, FALSE); } /** * db_iterator_reverse_operations: * @obj: a #DbIterator * * Reverses all pending operations on the model. **/ void db_iterator_reverse_operations (DbIterator * obj) { g_return_if_fail (DB_IS_ITERATOR (obj)); if (obj->model) db_model_reverse_operations (obj->model); } /** * db_iterator_get_pending_operations: * @obj: a #DbIterator * * Gets pending operations to perform in the current row. * * Return value: the pending operations **/ DbModelRowOp db_iterator_get_pending_operations (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), 0); if (obj->model && obj->row_selected) return db_model_get_row_operations (obj->model, &obj->iter); return 0; } /** * db_iterator_has_pending_operations: * @obj: a #DbIterator * * Checks for pending operations to perform. * * Return value: %TRUE if there are pending operations, %FALSE otherwise **/ gboolean db_iterator_has_pending_operations (DbIterator * obj) { g_return_val_if_fail (DB_IS_ITERATOR (obj), FALSE); if (obj->model) return db_model_has_pending_operations (obj->model); return FALSE; } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties 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, const GValue * value, GParamSpec * pspec) { switch (id) { case PROP_MODEL: db_iterator_set_model (obj, g_value_get_object (value)); break; case PROP_MODE: db_iterator_set_mode (obj, g_value_get_enum (value)); break; 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); } } static void db_iterator_get_property (DbIterator * obj, guint id, GValue * value, GParamSpec * pspec) { switch (id) { case PROP_MODEL: g_value_set_object (value, obj->model); break; case PROP_MODE: g_value_set_enum (value, obj->mode); break; case PROP_REMEMBER_SELECTION: g_value_set_boolean (value, obj->remember_selection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, id, pspec); } } //+++++++++++++++++++++++++++++++++++++++++++++++++++ Class static void db_iterator_init (DbIterator * obj) { obj->model = NULL; 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) { GList * n; for (n = obj->params; n; n = n->next) g_object_weak_unref (n->data, (GWeakNotify) db_iterator_unref_param, obj); g_list_free (obj->params); if (obj->model) { g_object_disconnect (obj->model ,"any_signal", db_iterator_on_model_line_inserted, obj ,"any_signal", db_iterator_on_model_line_updated_after, obj ,"any_signal", db_iterator_on_model_line_deleted, obj ,"any_signal", db_iterator_on_model_line_deleted_after, obj ,"any_signal", db_iterator_on_model_lines_reordered, obj ,"any_signal", db_iterator_on_model_status_changed, obj ,"any_signal", db_iterator_on_model_operations_done, obj ,NULL ); 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)); } static void db_iterator_class_init (DbIteratorClass * klass) { GObjectClass * k = G_OBJECT_CLASS (klass); k->set_property = (GObjectSetPropertyFunc) db_iterator_set_property; k->get_property = (GObjectGetPropertyFunc) db_iterator_get_property; k->finalize = (GObjectFinalizeFunc) db_iterator_finalize; 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 ); 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 ); 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 ); 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 ); 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_install_property (k, PROP_MODE, g_param_spec_enum ("mode" ,_("Mode") ,_("The mode in which the iterator is working") ,DB_TYPE_ITERATOR_MODE ,DB_ITERATOR_MODE_ON_CHANGE ,G_PARAM_CONSTRUCT | G_PARAM_READWRITE )); g_object_class_install_property (k, PROP_REMEMBER_SELECTION, g_param_spec_boolean ("remember-selection" ,_("Remember selection") ,_("Wether to rememeber the selection when model is refreshed") ,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 )); } GType db_iterator_mode_get_type () { static GType type = 0; if (type == 0) { static const GEnumValue values[] = { {DB_ITERATOR_MODE_ON_CHANGE, "DB_ITERATOR_MODE_ON_CHANGE", "on-change"} ,{DB_ITERATOR_MODE_ON_ITER, "DB_ITERATOR_MODE_ON_ITER", "on-iter"} ,{DB_ITERATOR_MODE_ON_DEMAND, "DB_ITERATOR_MODE_ON_DEMAND", "on-demand"} ,{0, NULL, NULL} }; type = g_enum_register_static (g_intern_static_string ("DbIteratorMode"), values); } return type; }