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-iterator.c

1100 lines
26 KiB
C
Raw Normal View History

2013-10-11 23:07:35 +00:00
/*
* 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-iterator.h"
2013-10-14 12:08:06 +00:00
#include "db-model-holder.h"
2013-10-11 23:07:35 +00:00
#define IS_READY(self) (self->model && db_model_is_ready (self->model))
static void db_iterator_model_holder_init (DbModelHolderInterface * iface);
2013-10-11 23:07:35 +00:00
/**
* SECTION:db-iterator
* @short_description: manages a iterator with its events
* @title: DbIterator
*
2013-10-14 12:08:06 +00:00
* The #DbIterator manages a connection with a data base. The function
* db_iterator_new() creates a new #DbIterator.
2013-10-11 23:07:35 +00:00
*/
2013-10-14 12:08:06 +00:00
G_DEFINE_TYPE_WITH_CODE (DbIterator, db_iterator, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (DB_TYPE_MODEL_HOLDER,
db_iterator_model_holder_init)
2013-10-14 12:08:06 +00:00
);
2013-10-11 23:07:35 +00:00
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);
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Private
static void db_iterator_unref_param (DbIterator * self, DbParam * param)
2013-10-11 23:07:35 +00:00
{
self->params = g_list_remove (self->params, param);
2013-10-11 23:07:35 +00:00
}
/*
* #DbIterator instances call this function every time line in
* the model is changed.
*/
static void db_iterator_row_num_changed (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
if (self->row_selected)
self->row = db_model_get_path (self->model, &self->iter);
else if (self->selected || !self->remember_selection)
self->row = -1;
2013-10-11 23:07:35 +00:00
g_signal_emit (self, signals[ROW_NUM_CHANGED], 0);
2013-10-11 23:07:35 +00:00
}
/*
* #DbIterator instances call this function every time the data of the params
* mustbe updated.
*/
static void db_iterator_iter_changed (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
db_iterator_row_num_changed (self);
g_signal_emit (self, signals[ITER_CHANGED], 0);
2013-10-11 23:07:35 +00:00
}
static void db_iterator_unselect (DbIterator * self)
{
if (self->selected)
{
g_hash_table_destroy (self->selected);
self->selected = NULL;
}
}
static void db_iterator_set_iter (DbIterator * self, DbIter * iter)
2013-10-11 23:07:35 +00:00
{
if (iter)
{
self->row_selected = TRUE;
self->iter = *iter;
db_iterator_iter_changed (self);
2013-10-11 23:07:35 +00:00
}
else if (self->row_selected)
2013-10-11 23:07:35 +00:00
{
self->row_selected = FALSE;
db_iterator_iter_changed (self);
2013-10-11 23:07:35 +00:00
}
db_iterator_unselect (self);
2013-10-11 23:07:35 +00:00
}
/*
* Function called when row is inserted on the model.
*/
static void db_iterator_on_model_line_inserted (DbModel * model, DbIter * iter, DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_signal_emit (self, signals[DATA_CHANGED], 0);
2013-10-11 23:07:35 +00:00
}
/*
* Function called when row is updated on the model.
*/
static void db_iterator_on_model_line_updated_after (DbModel * model, DbIter * iter, DbIterator * self)
2013-10-11 23:07:35 +00:00
{
if (self->row_selected && db_iter_compare (iter, &self->iter))
db_iterator_iter_changed (self);
2013-10-11 23:07:35 +00:00
g_signal_emit (self, signals[DATA_CHANGED], 0);
2013-10-11 23:07:35 +00:00
}
/*
* Function called when row is deleted on the model.
*/
static void db_iterator_on_model_line_deleted (DbModel * model, gint row, DbIterator * self)
2013-10-14 12:08:06 +00:00
{
if (self->row_selected && row == self->row)
2013-10-11 23:07:35 +00:00
{
DbIter iter;
if (db_model_get_iter (model, &iter, row + 1)
|| db_model_get_iter (model, &iter, row - 1))
db_iterator_set_iter (self, &iter);
2013-10-11 23:07:35 +00:00
else
db_iterator_set_iter (self, NULL);
2013-10-11 23:07:35 +00:00
}
}
static void db_iterator_on_model_line_deleted_after (DbModel * model, gint row, DbIterator * self)
2013-10-11 23:07:35 +00:00
{
if (self->row_selected || self->selected)
db_iterator_row_num_changed (self);
2013-10-11 23:07:35 +00:00
g_signal_emit (self, signals[DATA_CHANGED], 0);
2013-10-11 23:07:35 +00:00
}
/*
* Function called when model rows are reordered.
*/
static void db_iterator_on_model_lines_reordered (DbModel * model,
gint column, gint * new_order, DbIterator * self)
2013-10-11 23:07:35 +00:00
{
if (self->row_selected || self->selected)
db_iterator_row_num_changed (self);
2013-10-11 23:07:35 +00:00
}
/*
* Function called when model status changes.
*/
static void db_iterator_on_model_status_changed (DbModel * model, DbModelStatus status, DbIterator * self)
2013-10-11 23:07:35 +00:00
{
if (status == DB_MODEL_STATUS_READY)
{
DbIter iter;
gint nrows = db_model_get_nrows (model);
g_signal_emit (self, signals[STATUS_CHANGED], 0, IS_READY(self));
2013-10-11 23:07:35 +00:00
if (self->row >= 0 && self->row < nrows
&& db_model_get_iter (model, &iter, self->row))
db_iterator_set_iter (self, &iter);
2013-10-11 23:07:35 +00:00
else
db_iterator_set_iter (self, NULL);
2013-10-11 23:07:35 +00:00
}
else
{
db_iterator_set_iter (self, NULL);
g_signal_emit (self, signals[STATUS_CHANGED], 0, IS_READY(self));
2013-10-11 23:07:35 +00:00
}
}
/*
* Function called when model operations are done.
*/
static void db_iterator_on_model_operations_done (DbModel * model, DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_signal_emit (self, signals[OPERATIONS_DONE], 0);
2013-10-11 23:07:35 +00:00
}
static void db_iterator_set_model_mode (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
if (self->mode == DB_ITERATOR_MODE_ON_CHANGE)
db_model_set_mode (self->model, DB_MODEL_MODE_ON_CHANGE);
2013-10-11 23:07:35 +00:00
else
db_model_set_mode (self->model, DB_MODEL_MODE_ON_DEMAND);
2013-10-11 23:07:35 +00:00
}
/*
* Sets the model used as a data source by iterator.
*/
static void db_iterator_set_model (DbIterator * self, DbModel * model)
2013-10-11 23:07:35 +00:00
{
if (!model)
return;
if (!self->model)
2013-10-11 23:07:35 +00:00
{
self->model = g_object_ref (model);
g_object_connect (self->model
,"signal::lines-reordered", db_iterator_on_model_lines_reordered, self
,"signal::line-inserted", db_iterator_on_model_line_inserted, self
,"signal-after::line-updated", db_iterator_on_model_line_updated_after, self
,"signal::line-deleted", db_iterator_on_model_line_deleted, self
,"signal-after::line-deleted", db_iterator_on_model_line_deleted_after, self
,"signal::status-changed", db_iterator_on_model_status_changed, self
,"signal::operations-done", db_iterator_on_model_operations_done, self
2013-10-11 23:07:35 +00:00
,NULL
);
db_iterator_set_model_mode (self);
2013-10-11 23:07:35 +00:00
db_iterator_on_model_status_changed (model,
db_model_get_status (model), self);
2013-10-11 23:07:35 +00:00
}
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 * self)
2013-10-11 23:07:35 +00:00
{
if (self->row_selected)
2013-10-11 23:07:35 +00:00
return TRUE;
g_warning ("DbIterator: Row not selected");
return FALSE;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Public
/**
* db_iterator_get_row:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Gets the selected row number.
*
* Return value: the row number
**/
gint db_iterator_get_row (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), -1);
2013-10-11 23:07:35 +00:00
if (self->row_selected)
return self->row;
2013-10-11 23:07:35 +00:00
else
return -1;
}
/**
* db_iterator_get_model:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Gets the model used as a data source by iterator.
*
* Return value: (transfer none): the #DbModel
**/
DbModel * db_iterator_get_model (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), NULL);
2013-10-11 23:07:35 +00:00
return self->model;
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_is_ready:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* 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 * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), FALSE);
2013-10-11 23:07:35 +00:00
return IS_READY (self);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_get_mode:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Gets the mode in which the iterator is working.
*
* Return value: the #DbIteratorMode
**/
DbIteratorMode db_iterator_get_mode (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), 0);
2013-10-11 23:07:35 +00:00
return self->mode;
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_set_mode:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @mode: the #DbIteratorMode mode
*
* Sets the mode in which the iterator should work.
**/
void db_iterator_set_mode (DbIterator * self, DbIteratorMode mode)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
self->mode = mode;
2013-10-11 23:07:35 +00:00
if (self->model)
db_iterator_set_model_mode (self);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_get_iter:
* @self: a #DbIterator
* @iter: (allow-none) (out): return location for selected row iter, or %NULL.
2013-10-11 23:07:35 +00:00
*
* Gets the currently selected iter.
*
* Return value: %TRUE if any row is selected, %FALSE otherwise.
**/
gboolean db_iterator_get_iter (DbIterator * self, DbIter * iter)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), FALSE);
2013-10-11 23:07:35 +00:00
if (!self->row_selected)
2013-10-11 23:07:35 +00:00
return FALSE;
*iter = self->iter;
2013-10-11 23:07:35 +00:00
return TRUE;
}
/**
* db_iterator_select_iter:
* @self: a #DbIterator
* @iter: a #DbIter
*
* Adds a new #DbIter to the current selection.
*/
void db_iterator_select_iter (DbIterator * self, DbIter * iter)
{
gint pos;
g_return_if_fail (DB_IS_ITERATOR (self));
g_return_if_fail (IS_READY (self));
if (!iter)
return;
if (!self->selected)
self->selected = g_hash_table_new_full (g_int_hash, g_int_equal,
NULL, (GDestroyNotify) db_iter_free);
self->iter = *iter;
self->row_selected = FALSE;
g_signal_emit (self, signals[ROW_NUM_CHANGED], 0);
pos = db_model_get_path (self->model, iter);
if (!g_hash_table_contains (self->selected, &pos))
g_hash_table_insert (self->selected, &pos, db_iter_copy (iter));
}
2013-10-11 23:07:35 +00:00
/**
* db_iterator_move_iter:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @iter: a #DbIter
*
* Moves the iterator cursor to the specified iter, if model is ready.
**/
void db_iterator_move_iter (DbIterator * self, DbIter * iter)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
g_return_if_fail (IS_READY (self));
g_return_if_fail (self->model);
2013-10-11 23:07:35 +00:00
if (self->row_selected && db_iter_compare (&self->iter, iter))
2013-10-11 23:07:35 +00:00
return;
if (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);
}
2013-10-11 23:07:35 +00:00
db_iterator_set_iter (self, iter);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_move_first:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Moves the iterator cursor to the first row.
**/
void db_iterator_move_first (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
DbIter iter;
g_return_if_fail (DB_IS_ITERATOR (self));
g_return_if_fail (self->model);
2013-10-11 23:07:35 +00:00
if (db_model_get_iter_first (self->model, &iter))
db_iterator_move_iter (self, &iter);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_move_last:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Moves the iterator cursor to the last row.
**/
void db_iterator_move_last (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
DbIter iter;
g_return_if_fail (DB_IS_ITERATOR (self));
g_return_if_fail (self->model);
2013-10-11 23:07:35 +00:00
if (db_model_get_last (self->model, &iter))
db_iterator_move_iter (self, &iter);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_move_previous:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* 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 * self)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
if (self->row_selected)
2013-10-11 23:07:35 +00:00
{
DbIter iter = self->iter;
2013-10-11 23:07:35 +00:00
if (db_model_iter_prev (self->model, &iter))
db_iterator_move_iter (self, &iter);
2013-10-11 23:07:35 +00:00
else
g_warning (
"Can't move the cursor to the previous "
"row, because there are no more rows."
);
}
else
db_iterator_move_first (self);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_move_next:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* 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 * self)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
if (self->row_selected)
2013-10-11 23:07:35 +00:00
{
DbIter iter = self->iter;
2013-10-11 23:07:35 +00:00
if (db_model_iter_next (self->model, &iter))
db_iterator_move_iter (self, &iter);
2013-10-11 23:07:35 +00:00
else
g_warning (
"Can't move the cursor to the next "
"row, because there are no more rows."
);
}
else
db_iterator_move_first (self);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_move_to:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @move: a #DbIteratorMove
*
* Moves the iterator cursor to the predefined position.
**/
void db_iterator_move_to (DbIterator * self, DbIteratorMove move)
2013-10-11 23:07:35 +00:00
{
switch (move)
{
case DB_ITERATOR_MOVE_FIRST:
db_iterator_move_first (self);
2013-10-11 23:07:35 +00:00
break;
case DB_ITERATOR_MOVE_PREVIOUS:
db_iterator_move_previous (self);
2013-10-11 23:07:35 +00:00
break;
case DB_ITERATOR_MOVE_NEXT:
db_iterator_move_next (self);
2013-10-11 23:07:35 +00:00
break;
case DB_ITERATOR_MOVE_LAST:
db_iterator_move_last (self);
2013-10-11 23:07:35 +00:00
break;
}
}
/**
* db_iterator_insert:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Inserts a new row in the model and moves the iter to it, if inserted.
* successfully.
**/
void db_iterator_insert (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
DbIter iter;
g_return_if_fail (DB_IS_ITERATOR (self));
g_return_if_fail (self->model);
if (self->mode != DB_ITERATOR_MODE_ON_DEMAND)
{
if (db_model_get_row_operations (self->model, &self->iter) == DB_MODEL_ROW_OP_INSERT)
return;
db_model_perform_operations (self->model, FALSE);
}
2013-10-11 23:07:35 +00:00
if (db_model_insert (self->model, &iter))
db_iterator_set_iter (self, &iter);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_delete:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Deletes the currently selected row from the model, if any.
**/
void db_iterator_delete (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
if (self->row_selected)
2013-10-11 23:07:35 +00:00
{
db_model_delete (self->model, &self->iter);
2013-10-11 23:07:35 +00:00
if (self->mode != DB_ITERATOR_MODE_ON_DEMAND)
db_model_perform_operations (self->model, FALSE);
2013-10-11 23:07:35 +00:00
}
else if (self->selected)
{
GList * l, * list = g_hash_table_get_values (self->selected);
for (l = list; l; l = l->next)
db_model_delete (self->model, l->data);
if (self->mode != DB_ITERATOR_MODE_ON_DEMAND)
db_model_perform_operations (self->model, FALSE);
db_iterator_unselect (self);
}
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_refresh:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Refresh the data of the model handled by iterator.
**/
void db_iterator_refresh (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
if (self->model)
{
db_model_refresh (self->model);
db_iterator_unselect (self);
}
}
2013-10-11 23:07:35 +00:00
/**
* db_iterator_get_spec:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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 * self, gint column)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), NULL);
2013-10-11 23:07:35 +00:00
if (IS_READY (self))
return db_model_get_spec (self->model, column);
2013-10-11 23:07:35 +00:00
else
return NULL;
}
/**
* db_iterator_get_value:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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 * self, gint column)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), NULL);
2013-10-11 23:07:35 +00:00
if (self->row_selected)
return db_model_get_value (self->model, &self->iter, column, NULL);
2013-10-11 23:07:35 +00:00
return NULL;
}
/**
* db_iterator_get_column_index:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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 * self, const gchar * name)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), -1);
g_return_val_if_fail (IS_READY (self), -1);
2013-10-11 23:07:35 +00:00
return db_model_get_column_index (self->model, name);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_set_value:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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.
*
* Return value: %TRUE if the value was changed, %FALSE otherwise
2013-10-11 23:07:35 +00:00
**/
gboolean db_iterator_set_value (DbIterator * self, gint column, const GValue * value, GError ** err)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), FALSE);
2013-10-11 23:07:35 +00:00
if (db_iterator_check_row_selected (self))
return db_model_set_value (self->model, &self->iter, column, value, err);
return FALSE;
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_add_param:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @param: the param to add.
*
* Adds a #DbParam to the list of iterator params.
**/
void db_iterator_add_param (DbIterator * self, DbParam * param)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
g_return_if_fail (DB_IS_PARAM (param));
db_param_set_iterator (param, self);
2013-10-11 23:07:35 +00:00
g_object_weak_ref (G_OBJECT (param),
(GWeakNotify) db_iterator_unref_param, self);
self->params = g_list_prepend (self->params, param);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_get_param:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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 * self, const gchar * column)
{
2013-10-11 23:07:35 +00:00
GList * n;
GvnParam * param;
g_return_val_if_fail (DB_IS_ITERATOR (self), NULL);
2013-10-11 23:07:35 +00:00
g_return_val_if_fail (column, NULL);
for (n = self->params; n; n = n->next)
2013-10-11 23:07:35 +00:00
if (!g_strcmp0 (db_param_get_column_name (n->data), column))
break;
if (!n)
{
param = db_param_new (column);
db_iterator_add_param (self, DB_PARAM (param));
2013-10-11 23:07:35 +00:00
}
else
param = n->data;
return param;
}
/**
* db_iterator_get_params:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* 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 * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), NULL);
return g_list_copy (self->params);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_bind_param:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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 * self, const gchar * column, GvnParam * param)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
g_return_if_fail (GVN_IS_PARAM (self));
2013-10-11 23:07:35 +00:00
gvn_param_set_master (param,
db_iterator_get_param (self, column)
2013-10-11 23:07:35 +00:00
);
}
/**
* db_iterator_link:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @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 * self, const gchar * field, DbIterator * src, const gchar * column)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
g_return_if_fail (DB_IS_ITERATOR (src));
g_return_if_fail (field);
db_iterator_link_with_param (self, field,
2013-10-11 23:07:35 +00:00
db_iterator_get_param (src, column));
}
/**
* db_iterator_link_with_param:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
* @field: the field name in the iterator statement
* @param: the #GvnParam
*
* Links the iterator with a parameter.
**/
void db_iterator_link_with_param (DbIterator * self, const gchar * field, GvnParam * param)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
g_return_if_fail (GVN_IS_PARAM (param));
g_return_if_fail (self->model);
2013-10-11 23:07:35 +00:00
g_return_if_fail (field);
db_model_set_default_value_from_param (self->model, field, param, TRUE);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_get_nrows:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Gets the number of rows in the model pointed by the iterator.
*
* Return value: the number of rows
**/
gint db_iterator_get_nrows (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), 0);
2013-10-11 23:07:35 +00:00
if (self->model)
return db_model_get_nrows (self->model);
2013-10-11 23:07:35 +00:00
return 0;
}
/**
* db_iterator_get_update_flags:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Gets the flags that indicate how a model can be modified.
*
* Return value: the flags
**/
DbModelUpdateFlags db_iterator_get_update_flags (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), 0);
2013-10-11 23:07:35 +00:00
if (self->model)
return db_model_get_update_flags (self->model);
2013-10-11 23:07:35 +00:00
return 0;
}
/**
* db_iterator_perform_operations:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Performs all pending operations on the model.
**/
void db_iterator_perform_operations (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
if (self->model)
db_model_perform_operations (self->model, FALSE);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_reverse_operations:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Reverses all pending operations on the model.
**/
void db_iterator_reverse_operations (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_if_fail (DB_IS_ITERATOR (self));
2013-10-11 23:07:35 +00:00
if (self->model)
db_model_reverse_operations (self->model);
2013-10-11 23:07:35 +00:00
}
/**
* db_iterator_get_pending_operations:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Gets pending operations to perform in the current row.
*
* Return value: the pending operations
**/
DbModelRowOp db_iterator_get_pending_operations (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), 0);
2013-10-11 23:07:35 +00:00
if (self->model && (self->row_selected || self->selected))
return db_model_get_row_operations (self->model, &self->iter);
2013-10-11 23:07:35 +00:00
return 0;
}
/**
* db_iterator_has_pending_operations:
* @self: a #DbIterator
2013-10-11 23:07:35 +00:00
*
* Checks for pending operations to perform.
*
* Return value: %TRUE if there are pending operations, %FALSE otherwise
**/
gboolean db_iterator_has_pending_operations (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
g_return_val_if_fail (DB_IS_ITERATOR (self), FALSE);
2013-10-11 23:07:35 +00:00
if (self->model)
return db_model_has_pending_operations (self->model);
2013-10-11 23:07:35 +00:00
return FALSE;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Properties
enum
{
PROP_MODEL = 1
,PROP_MODE
,PROP_REMEMBER_SELECTION
};
static void db_iterator_set_property (DbIterator * self, guint id,
2013-10-11 23:07:35 +00:00
const GValue * value, GParamSpec * pspec)
{
switch (id)
{
case PROP_MODEL:
db_iterator_set_model (self, g_value_get_object (value));
2013-10-11 23:07:35 +00:00
break;
case PROP_MODE:
db_iterator_set_mode (self, g_value_get_enum (value));
2013-10-11 23:07:35 +00:00
break;
case PROP_REMEMBER_SELECTION:
self->remember_selection = g_value_get_boolean (value);
db_iterator_row_num_changed (self);
2013-10-11 23:07:35 +00:00
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec);
2013-10-11 23:07:35 +00:00
}
}
static void db_iterator_get_property (DbIterator * self, guint id,
2013-10-11 23:07:35 +00:00
GValue * value, GParamSpec * pspec)
{
switch (id)
{
case PROP_MODEL:
g_value_set_object (value, self->model);
2013-10-11 23:07:35 +00:00
break;
case PROP_MODE:
g_value_set_enum (value, self->mode);
2013-10-11 23:07:35 +00:00
break;
case PROP_REMEMBER_SELECTION:
g_value_set_boolean (value, self->remember_selection);
2013-10-11 23:07:35 +00:00
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, id, pspec);
2013-10-11 23:07:35 +00:00
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++ Class
static void db_iterator_init (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
self->model = NULL;
self->params = NULL;
self->row = 0;
self->row_selected = FALSE;
self->selected = NULL;
2013-10-11 23:07:35 +00:00
}
static void db_iterator_finalize (DbIterator * self)
2013-10-11 23:07:35 +00:00
{
GList * n;
for (n = self->params; n; n = n->next)
2013-10-11 23:07:35 +00:00
g_object_weak_unref (n->data,
(GWeakNotify) db_iterator_unref_param, self);
2013-10-11 23:07:35 +00:00
g_list_free (self->params);
db_iterator_unselect (self);
2013-10-11 23:07:35 +00:00
if (self->model)
2013-10-11 23:07:35 +00:00
{
g_object_disconnect (self->model
,"any_signal", db_iterator_on_model_line_inserted, self
,"any_signal", db_iterator_on_model_line_updated_after, self
,"any_signal", db_iterator_on_model_line_deleted, self
,"any_signal", db_iterator_on_model_line_deleted_after, self
,"any_signal", db_iterator_on_model_lines_reordered, self
,"any_signal", db_iterator_on_model_status_changed, self
,"any_signal", db_iterator_on_model_operations_done, self
2013-10-11 23:07:35 +00:00
,NULL
);
g_object_unref (self->model);
2013-10-11 23:07:35 +00:00
}
G_OBJECT_CLASS (db_iterator_parent_class)->finalize (G_OBJECT (self));
2013-10-11 23:07:35 +00:00
}
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;
2013-10-14 12:08:06 +00:00
/**
* DbIterator::iter-changed:
* @iterator: the object on which the signal is emitted
*
* This signal is emitted when @iter moves over the @iterator model
*/
2013-10-11 23:07:35 +00:00
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
);
2013-10-14 12:08:06 +00:00
/**
* DbIterator::data-changed:
* @iterator: the object on which the signal is emitted
*
* This signal is emitted when the model changes its data
*/
2013-10-11 23:07:35 +00:00
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
);
2013-10-14 12:08:06 +00:00
/**
* DbIterator::row-num-changed:
* @iterator: the object on which the signal is emitted
*
* This signal is emitted when the selected row changes
*/
2013-10-11 23:07:35 +00:00
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
);
2013-10-14 12:08:06 +00:00
/**
* 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
*/
2013-10-11 23:07:35 +00:00
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
);
2013-10-14 12:08:06 +00:00
/**
* 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
*/
2013-10-11 23:07:35 +00:00
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
);
2013-10-14 12:08:06 +00:00
g_object_class_override_property (k, PROP_MODEL, "model");
2013-10-11 23:07:35 +00:00
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
));
2013-10-14 12:08:06 +00:00
}
static void db_iterator_model_holder_init (DbModelHolderInterface * iface)
2013-10-14 12:08:06 +00:00
{
iface->get_model = (DbModelHolderGetModelFunc) db_iterator_get_model;
iface->set_model = (DbModelHolderSetModelFunc) db_iterator_set_model;
2013-10-11 23:07:35 +00:00
}
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;
}