601 lines
16 KiB
C
601 lines
16 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 "vn-list-model.h"
|
||
|
|
||
|
typedef struct
|
||
|
{
|
||
|
gchar * detail;
|
||
|
gpointer callback;
|
||
|
}
|
||
|
GvnSignalInfo;
|
||
|
|
||
|
/*
|
||
|
* gvn_object_link:
|
||
|
* @obj: instance
|
||
|
* @prop: property of @obj to be set to @prop_value
|
||
|
* @prop_value: the value to set on @prop
|
||
|
* @info: an array of GvnSignalInfo
|
||
|
*
|
||
|
* Connects the signals of an object passed on @prop_value to the callbacks
|
||
|
* listed in a GvnSignalInfo array.
|
||
|
*/
|
||
|
void _gvn_object_link (gpointer self, gpointer * prop, gpointer prop_value, GvnSignalInfo * info)
|
||
|
{
|
||
|
gint i;
|
||
|
|
||
|
if (*prop)
|
||
|
{
|
||
|
for (i = 0; info[i].detail; i++)
|
||
|
g_signal_handlers_disconnect_by_func (*prop, info[i].callback, self);
|
||
|
|
||
|
g_object_unref (*prop);
|
||
|
}
|
||
|
|
||
|
if (prop_value)
|
||
|
{
|
||
|
for (i = 0; info[i].detail; i++)
|
||
|
if (g_str_has_suffix (info[i].detail, ".after"))
|
||
|
{
|
||
|
gchar ** split = g_strsplit (info[i].detail, ".", 0);
|
||
|
g_signal_connect_after (prop_value, split[0], info[i].callback, self);
|
||
|
g_strfreev (split);
|
||
|
}
|
||
|
else
|
||
|
g_signal_connect (prop_value, info[i].detail, info[i].callback, self);
|
||
|
|
||
|
*prop = g_object_ref_sink (prop_value);
|
||
|
}
|
||
|
else
|
||
|
*prop = NULL;
|
||
|
}
|
||
|
|
||
|
#define gvn_object_link(self, prop, prop_value, info) (_gvn_object_link (self, (void**) prop, prop_value, info))
|
||
|
|
||
|
static void vn_list_model_tree_model_init (GtkTreeModelIface * iface);
|
||
|
static void vn_list_model_tree_sortable_init (GtkTreeSortableIface * iface);
|
||
|
|
||
|
G_DEFINE_TYPE_WITH_CODE (VnListModel, vn_list_model, G_TYPE_OBJECT,
|
||
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
|
||
|
vn_list_model_tree_model_init)
|
||
|
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_SORTABLE,
|
||
|
vn_list_model_tree_sortable_init)
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* vn_list_model_new:
|
||
|
* @model: a #DbModel
|
||
|
*
|
||
|
* Creates a new #VnListModel with @model as the data model.
|
||
|
*
|
||
|
* Return value: (transfer full): a #VnListModel.
|
||
|
**/
|
||
|
VnListModel * vn_list_model_new (DbModel * model)
|
||
|
{
|
||
|
return g_object_new (VN_TYPE_LIST_MODEL, "model", model, NULL);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* vn_list_model_get_model:
|
||
|
* @obj: a #VnListModel
|
||
|
*
|
||
|
* Passes the #DbModel used internally by @model.
|
||
|
*
|
||
|
* Return value: (transfer none): a #DbModel.
|
||
|
**/
|
||
|
DbModel * vn_list_model_get_model (VnListModel * self)
|
||
|
{
|
||
|
g_return_val_if_fail (VN_IS_LIST_MODEL (self), NULL);
|
||
|
|
||
|
return self->model;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* vn_list_model_use_null_row:
|
||
|
* @self: a #VnListModel
|
||
|
* @use: wether to use a null row
|
||
|
*
|
||
|
* Sets wether to use a null row at the end of the model. This row can't be
|
||
|
* modified, its purpose is to set a #NULL option in selection widgets, like
|
||
|
* #VnCombo.
|
||
|
**/
|
||
|
void vn_list_model_use_null_row (VnListModel * self, gboolean use)
|
||
|
{
|
||
|
g_return_if_fail (VN_IS_LIST_MODEL (self));
|
||
|
|
||
|
self->null_row = use;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* vn_gtk_tree_iter_from_db_iter:
|
||
|
* @dest_iter: the #GtkTreeIter to set using the data on @src_iter
|
||
|
* @src_iter: a valid #DbIter
|
||
|
*
|
||
|
* Sets a #GtkTreeIter with the data of a #DbIter. This function is mostly used
|
||
|
* internally.
|
||
|
**/
|
||
|
void gtk_tree_iter_from_db_iter (GtkTreeIter * dest_iter, const DbIter * src_iter)
|
||
|
{
|
||
|
dest_iter->stamp = src_iter->stamp;
|
||
|
dest_iter->user_data = src_iter->data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* vn_gtk_tree_iter_to_db_iter:
|
||
|
* @src_iter: a valid #GtkTreeIter
|
||
|
* @dest_iter: the #DbIter to set using the data on @src_iter
|
||
|
*
|
||
|
* Sets a with #DbIter the data of a #GtkTreeIter. This function is mostly used
|
||
|
* internally.
|
||
|
**/
|
||
|
void gtk_tree_iter_to_db_iter (const GtkTreeIter * src_iter, DbIter * dest_iter)
|
||
|
{
|
||
|
dest_iter->stamp = src_iter->stamp;
|
||
|
dest_iter->data = src_iter->user_data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* vn_list_model_iter_is_valid:
|
||
|
* @iter: a #GtkTreeIter
|
||
|
* @model: a #GtkTreeModel
|
||
|
*
|
||
|
* Checks if @iter is a valid #GtkTreeIter pointing inside #GtkTreeModel.
|
||
|
**/
|
||
|
gboolean vn_list_model_iter_is_valid (GtkTreeIter * iter, GtkTreeModel * model)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
|
||
|
g_return_val_if_fail (GTK_IS_TREE_MODEL (model), FALSE);
|
||
|
|
||
|
gtk_tree_iter_to_db_iter (iter, &dbiter);
|
||
|
return db_model_iter_is_valid (&dbiter, VN_LIST_MODEL (model)->model);
|
||
|
}
|
||
|
|
||
|
static gint vn_list_model_get_nrows (GtkTreeModel * self)
|
||
|
{
|
||
|
gint nrows = db_model_get_nrows (VN_LIST_MODEL (self)->model);
|
||
|
|
||
|
return VN_LIST_MODEL (self)->null_row ? nrows + 1 : nrows;
|
||
|
}
|
||
|
|
||
|
//++++ Broadcast of GtkTreeModel and GtkTreeSortable signals:
|
||
|
|
||
|
static void vn_list_model_on_line_updated (DbModel * model, DbIter * dbiter, GtkTreeModel * self)
|
||
|
{
|
||
|
GtkTreeIter iter;
|
||
|
GtkTreePath * path;
|
||
|
gint p = db_model_get_path (model, dbiter);
|
||
|
p = VN_LIST_MODEL (self)->null_row ? p + 1 : p;
|
||
|
gtk_tree_iter_from_db_iter (&iter, dbiter);
|
||
|
|
||
|
path = gtk_tree_path_new ();
|
||
|
gtk_tree_path_append_index (path, p);
|
||
|
|
||
|
gtk_tree_model_row_changed (self, path, &iter);
|
||
|
|
||
|
gtk_tree_path_free (path);
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_on_line_inserted (DbModel * model, DbIter * dbiter, GtkTreeModel * self)
|
||
|
{
|
||
|
GtkTreeIter iter;
|
||
|
GtkTreePath * path;
|
||
|
gint p = db_model_get_path (model, dbiter);
|
||
|
p = VN_LIST_MODEL (self)->null_row ? p + 1 : p;
|
||
|
gtk_tree_iter_from_db_iter (&iter, dbiter);
|
||
|
|
||
|
path = gtk_tree_path_new ();
|
||
|
gtk_tree_path_append_index (path, p);
|
||
|
|
||
|
gtk_tree_model_row_inserted (self, path, &iter);
|
||
|
|
||
|
gtk_tree_path_free (path);
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_on_line_deleted (DbModel * model, gint pos, GtkTreeModel * self)
|
||
|
{
|
||
|
GtkTreePath * path = gtk_tree_path_new ();
|
||
|
|
||
|
gtk_tree_path_append_index (path,
|
||
|
VN_LIST_MODEL (self)->null_row ? pos + 1 : pos);
|
||
|
|
||
|
if (gtk_tree_path_get_indices (path))
|
||
|
gtk_tree_model_row_deleted (self, path);
|
||
|
|
||
|
gtk_tree_path_free (path);
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_on_lines_reordered (DbModel * model, guint col, gint * new_order, GtkTreeModel * self)
|
||
|
{
|
||
|
GtkTreePath * path = gtk_tree_path_new ();
|
||
|
gtk_tree_model_rows_reordered (self, path, NULL, new_order);
|
||
|
gtk_tree_path_free (path);
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_on_sort_changed (DbModel * model, GtkTreeSortable * self)
|
||
|
{
|
||
|
g_signal_emit_by_name (self, "sort-column-changed");
|
||
|
}
|
||
|
|
||
|
//++++ Implementation of GtkTreeModel methods (using DbModel methods)
|
||
|
|
||
|
static GtkTreeModelFlags vn_list_model_get_flags (GtkTreeModel * self)
|
||
|
{
|
||
|
return GTK_TREE_MODEL_ITERS_PERSIST | GTK_TREE_MODEL_LIST_ONLY;
|
||
|
}
|
||
|
|
||
|
static gint vn_list_model_get_ncols (GtkTreeModel * self)
|
||
|
{
|
||
|
return db_model_get_ncols (VN_LIST_MODEL (self)->model);
|
||
|
}
|
||
|
|
||
|
static GType vn_list_model_get_column_type (GtkTreeModel * self, gint index_)
|
||
|
{
|
||
|
return db_model_get_column_type (VN_LIST_MODEL (self)->model, index_);
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_get_iter (GtkTreeModel * self, GtkTreeIter * iter,
|
||
|
GtkTreePath * path)
|
||
|
{
|
||
|
gboolean ok = FALSE;
|
||
|
gint p = gtk_tree_path_get_indices (path)[0];
|
||
|
p = VN_LIST_MODEL (self)->null_row ? p - 1 : p;
|
||
|
|
||
|
if (p >= 0)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
ok = db_model_get_iter (VN_LIST_MODEL (self)->model, &dbiter, p);
|
||
|
|
||
|
if (ok)
|
||
|
gtk_tree_iter_from_db_iter (iter, &dbiter);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iter->user_data = self;
|
||
|
ok = TRUE;
|
||
|
}
|
||
|
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
static GtkTreePath * vn_list_model_get_path (GtkTreeModel * self, GtkTreeIter * iter)
|
||
|
{
|
||
|
gint p;
|
||
|
GtkTreePath * path;
|
||
|
|
||
|
if (iter->user_data != self)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
|
||
|
gtk_tree_iter_to_db_iter (iter, &dbiter);
|
||
|
|
||
|
p = db_model_get_path (VN_LIST_MODEL (self)->model, &dbiter);
|
||
|
p = VN_LIST_MODEL (self)->null_row ? p + 1 : p;
|
||
|
}
|
||
|
else
|
||
|
p = 0;
|
||
|
|
||
|
path = gtk_tree_path_new ();
|
||
|
gtk_tree_path_append_index (path, p);
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_get_value (GtkTreeModel * self, GtkTreeIter * iter,
|
||
|
gint column, GValue * value)
|
||
|
{
|
||
|
GValue * v = NULL;
|
||
|
|
||
|
if (iter->user_data != self)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
gtk_tree_iter_to_db_iter (iter, &dbiter);
|
||
|
v = (GValue *) db_model_get_value (VN_LIST_MODEL (self)->model, &dbiter, column, NULL);
|
||
|
}
|
||
|
|
||
|
if (v)
|
||
|
{
|
||
|
g_value_init (value, G_VALUE_TYPE (v));
|
||
|
g_value_copy (v, value);
|
||
|
}
|
||
|
else
|
||
|
g_value_init (value, GVN_TYPE_NULL);
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_iter_next (GtkTreeModel * self, GtkTreeIter * iter)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
gboolean ret_val;
|
||
|
|
||
|
if (iter->user_data != self)
|
||
|
{
|
||
|
gtk_tree_iter_to_db_iter (iter, &dbiter);
|
||
|
ret_val = db_model_iter_next (VN_LIST_MODEL (self)->model, &dbiter);
|
||
|
}
|
||
|
else
|
||
|
ret_val = db_model_get_iter_first (VN_LIST_MODEL (self)->model, &dbiter);
|
||
|
|
||
|
gtk_tree_iter_from_db_iter (iter, &dbiter);
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_iter_previous (GtkTreeModel * self, GtkTreeIter * iter)
|
||
|
{
|
||
|
if (iter->user_data != self)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
DbModel * model = VN_LIST_MODEL (self)->model;
|
||
|
|
||
|
gtk_tree_iter_to_db_iter (iter, &dbiter);
|
||
|
|
||
|
if (db_model_iter_prev (model, &dbiter))
|
||
|
{
|
||
|
iter->user_data = dbiter.data;
|
||
|
return TRUE;
|
||
|
}
|
||
|
else if (db_model_get_iter_first (model, &dbiter)
|
||
|
&& iter->user_data == dbiter.data)
|
||
|
{
|
||
|
iter->user_data = self;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_iter_children (GtkTreeModel * self, GtkTreeIter * iter,
|
||
|
GtkTreeIter * parent)
|
||
|
{
|
||
|
if (parent == NULL)
|
||
|
{
|
||
|
gboolean ret_val;
|
||
|
|
||
|
if (!VN_LIST_MODEL (self)->null_row)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
ret_val = db_model_get_iter_first (VN_LIST_MODEL (self)->model, &dbiter);
|
||
|
|
||
|
if (ret_val)
|
||
|
gtk_tree_iter_from_db_iter (iter, &dbiter);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
iter->user_data = self;
|
||
|
ret_val = TRUE;
|
||
|
}
|
||
|
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_iter_has_child (GtkTreeModel * self, GtkTreeIter * iter)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static gint vn_list_model_iter_n_children (GtkTreeModel * self, GtkTreeIter * iter)
|
||
|
{
|
||
|
if (iter == NULL)
|
||
|
{
|
||
|
gint nrows = vn_list_model_get_nrows (self);
|
||
|
return VN_LIST_MODEL (self)->null_row ? nrows + 1 : nrows;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_iter_nth_child (GtkTreeModel * self, GtkTreeIter * iter
|
||
|
,GtkTreeIter * parent, gint n)
|
||
|
{
|
||
|
if (parent == NULL)
|
||
|
{
|
||
|
DbIter dbiter;
|
||
|
gboolean ok = db_model_get_iter (VN_LIST_MODEL (self)->model,
|
||
|
&dbiter, VN_LIST_MODEL (self)->null_row ? n - 1 : n);
|
||
|
|
||
|
if (ok)
|
||
|
{
|
||
|
gtk_tree_iter_from_db_iter (iter, &dbiter);
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_iter_parent (GtkTreeModel * self, GtkTreeIter * iter,
|
||
|
GtkTreeIter * child)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//++++ Implementation of GtkTreeSortable methods (using DbModel methods)
|
||
|
|
||
|
static gboolean vn_list_model_get_sort_column_id (GtkTreeSortable * self,
|
||
|
gint * sort_column_id,
|
||
|
GtkSortType * order)
|
||
|
{
|
||
|
return db_model_get_sort_column_id (VN_LIST_MODEL (self)->model
|
||
|
,sort_column_id, (DbSortType *) order);
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_set_sort_column_id (GtkTreeSortable * self, gint sort_column_id,
|
||
|
GtkSortType order)
|
||
|
{
|
||
|
DbSortType db_order;
|
||
|
|
||
|
if (order == GTK_SORT_ASCENDING)
|
||
|
db_order = DB_SORT_ASCENDING;
|
||
|
else
|
||
|
db_order = DB_SORT_DESCENDING;
|
||
|
|
||
|
db_model_set_sort_column_id (VN_LIST_MODEL (self)->model, sort_column_id, db_order);
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_set_sort_func (GtkTreeSortable *sortable, gint sort_column_id,
|
||
|
GtkTreeIterCompareFunc sort_func, gpointer user_data, GDestroyNotify destroy)
|
||
|
{
|
||
|
g_warning ("Function vn_list_model_set_sort_func not implemented");
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_set_default_sort_func (GtkTreeSortable *sortable,
|
||
|
GtkTreeIterCompareFunc sort_func, gpointer user_data, GDestroyNotify destroy)
|
||
|
{
|
||
|
g_warning ("Function vn_list_model_set_default_sort_func not implemented");
|
||
|
}
|
||
|
|
||
|
static gboolean vn_list_model_has_default_sort_func (GtkTreeSortable * self)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Properties
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
PROP_MODEL = 1
|
||
|
,PROP_NULL_ROW
|
||
|
}
|
||
|
VnListModelProp;
|
||
|
|
||
|
/*Experimental way to connect a property object signals using gvn_object_link*/
|
||
|
GvnSignalInfo signal_info[] =
|
||
|
{
|
||
|
{"line-updated.after", vn_list_model_on_line_updated
|
||
|
},{"line-inserted", vn_list_model_on_line_inserted
|
||
|
},{"line-deleted.after", vn_list_model_on_line_deleted
|
||
|
},{"lines-reordered", vn_list_model_on_lines_reordered
|
||
|
},{"sort-changed", vn_list_model_on_sort_changed
|
||
|
},{NULL}
|
||
|
};
|
||
|
|
||
|
static void vn_list_model_set_property (VnListModel * self, guint property_id,
|
||
|
const GValue * value, GParamSpec * pspec)
|
||
|
{
|
||
|
switch (property_id)
|
||
|
{
|
||
|
case PROP_MODEL:
|
||
|
gvn_object_link (self, &self->model, g_value_get_object (value), signal_info);
|
||
|
/*g_object_ref_sink (self->model);
|
||
|
g_object_connect (self->model
|
||
|
,"signal-after::line-updated", vn_list_model_on_line_updated, obj
|
||
|
,"signal::line-inserted", vn_list_model_on_line_inserted, obj
|
||
|
,"signal-after::line-deleted", vn_list_model_on_line_deleted, obj
|
||
|
,"signal::lines-reordered", vn_list_model_on_lines_reordered, obj
|
||
|
,"signal::sort-changed", vn_list_model_on_sort_changed, self, NULL);*/
|
||
|
break;
|
||
|
case PROP_NULL_ROW:
|
||
|
vn_list_model_use_null_row (self, g_value_get_boolean (value));
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_get_property (VnListModel * self, guint property_id,
|
||
|
GValue * value, GParamSpec * pspec)
|
||
|
{
|
||
|
switch (property_id)
|
||
|
{
|
||
|
case PROP_MODEL:
|
||
|
g_value_set_object (value, self->model);
|
||
|
break;
|
||
|
case PROP_NULL_ROW:
|
||
|
g_value_set_boolean (value, self->null_row);
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (self, property_id, pspec);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Class
|
||
|
|
||
|
static void vn_list_model_init (VnListModel * self)
|
||
|
{
|
||
|
self->model = NULL;
|
||
|
self->null_row = FALSE;
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_finalize (VnListModel * self)
|
||
|
{
|
||
|
gvn_object_link (self, &self->model, NULL, signal_info);
|
||
|
/*
|
||
|
g_object_disconnect (self->model
|
||
|
,"any_signal", vn_list_model_on_line_updated, obj
|
||
|
,"any_signal", vn_list_model_on_line_inserted, obj
|
||
|
,"any_signal", vn_list_model_on_line_deleted, obj
|
||
|
,"any_signal", vn_list_model_on_lines_reordered, obj
|
||
|
,"any_signal", vn_list_model_on_sort_changed, self, NULL);
|
||
|
|
||
|
g_object_unref (self->model);
|
||
|
*/
|
||
|
G_OBJECT_CLASS (vn_list_model_parent_class)->finalize (G_OBJECT (self));
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_class_init (VnListModelClass * k)
|
||
|
{
|
||
|
GObjectClass * klass = G_OBJECT_CLASS (k);
|
||
|
klass->set_property = (GObjectSetPropertyFunc) vn_list_model_set_property;
|
||
|
klass->get_property = (GObjectGetPropertyFunc) vn_list_model_get_property;
|
||
|
klass->finalize = (GObjectFinalizeFunc) vn_list_model_finalize;
|
||
|
|
||
|
g_object_class_install_property (klass, PROP_MODEL,
|
||
|
g_param_spec_object ("model"
|
||
|
,"Model"
|
||
|
,"The #DbModel with the data used by the #VnListModel"
|
||
|
,DB_TYPE_MODEL
|
||
|
,G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE
|
||
|
));
|
||
|
|
||
|
g_object_class_install_property (klass, PROP_NULL_ROW,
|
||
|
g_param_spec_boolean ("null-row"
|
||
|
,_("Null row")
|
||
|
,_("Whether the list model will add a null row or not")
|
||
|
,FALSE
|
||
|
,G_PARAM_READWRITE
|
||
|
));
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_tree_model_init (GtkTreeModelIface * iface)
|
||
|
{
|
||
|
iface->get_flags = vn_list_model_get_flags;
|
||
|
iface->get_n_columns = vn_list_model_get_ncols;
|
||
|
iface->get_column_type = vn_list_model_get_column_type;
|
||
|
iface->get_iter = vn_list_model_get_iter;
|
||
|
iface->get_path = vn_list_model_get_path;
|
||
|
iface->get_value = vn_list_model_get_value;
|
||
|
iface->iter_next = vn_list_model_iter_next;
|
||
|
iface->iter_previous = vn_list_model_iter_previous;
|
||
|
|
||
|
iface->iter_children = vn_list_model_iter_children;
|
||
|
iface->iter_has_child = vn_list_model_iter_has_child;
|
||
|
iface->iter_n_children = vn_list_model_iter_n_children;
|
||
|
iface->iter_nth_child = vn_list_model_iter_nth_child;
|
||
|
iface->iter_parent = vn_list_model_iter_parent;
|
||
|
}
|
||
|
|
||
|
static void vn_list_model_tree_sortable_init (GtkTreeSortableIface * iface)
|
||
|
{
|
||
|
iface->get_sort_column_id = vn_list_model_get_sort_column_id;
|
||
|
iface->set_sort_column_id = vn_list_model_set_sort_column_id;
|
||
|
iface->set_sort_func = vn_list_model_set_sort_func;
|
||
|
iface->set_default_sort_func = vn_list_model_set_default_sort_func;
|
||
|
iface->has_default_sort_func = vn_list_model_has_default_sort_func;
|
||
|
}
|