1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
<?xml version="1.0"?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"[
<!ENTITY LIBGDA "<application>Libgda</application>">
]>
<sect1 id="gda-data-model-writing">
<title>Implementing your own data model</title>
<para>
You may need at some point to implement your own data model because the implementations in
&LIBGDA; don't suit your needs. This section is dedicated to explaining to you how this can be done.
</para>
<para>
Implementing a new <link linkend="GdaDataModel">GdaDataModel</link> is simply a matter of
creating a new GObject which implements the <link linkend="GdaDataModel">GdaDataModel</link>
interface, which is described below. Thos new class needs to inherit GObject, but needs not
be direct descendant of it. The way to subclass an object using GLib
is not covered in this documentation, for this matter reref to
<link linkend="howto-gobject-code">GObject's documentation</link>, or
<ulink url="http://developer.gnome.org/gobject/stable/howto-gobject.html">online</ulink>.
</para>
<sect2 id="gda-data-model-writing-virtual-methods">
<title>Virtual methods</title>
<para>
The interface's methods which can and/or need to be implemented are defined below.
</para>
<sect3 id="i_get_n_rows">
<title>i_get_n_rows() - optional</title>
<para>This method, if implemented, returns the total number of rows in the data model, or -1 if
unknown. If it's not implemented, then it is assumed that -1 is returned in all cases.</para>
</sect3>
<sect3 id="i_get_n_columns">
<title>i_get_n_columns() - required</title>
<para>This method, returns the total number of columns in the data model, or -1 if unknown.</para>
</sect3>
<sect3 id="i_describe_column">
<title>i_describe_column() - required</title>
<para>This method describes a column; it returns (without any ownership to the caller) a
<link linkend="GdaColumn">GdaColumn</link> for each existing column, or NULL otherwise.</para>
</sect3>
<sect3 id="i_get_access_flags">
<title>i_get_access_flags() - required</title>
<para>This method defines how the data model may be accessed (randomly, only using a cursor, ...)</para>
</sect3>
<sect3 id="i_get_value_at">
<title>i_get_value_at() - required for random access</title>
<para>This method is used to access the contents of a data model, specifically
a <link linkend="GValue">GValue</link> is returned for each (column,row) position.
It must return NULL if the data model experienced an error for the specific (column,row)
position. See <link linkend="gda-data-model-get-value-at">gda_data_model_get_value_at()</link>
for more information about the lifetime of the returned GValue.</para>
</sect3>
<sect3 id="i_get_attributes_at">
<title>i_get_attributes_at() - optional</title>
<para>This method returns, for a (column,row) position in the data model, the attributes
of the adressed "cell".</para>
</sect3>
<sect3 id="i_create_iter">
<title>i_create_iter() - optional</title>
<para>This method can be implemented to create specific
<link linkend="GdaDataModelIter">GdaDataModelIter</link> or to customize them.</para>
</sect3>
<sect3 id="i_iter_at_row">
<title>i_iter_at_row() - optional</title>
<para>This method can be implemented if a specific implementation allows an iterator
to be moved quickly to a specific row (faster than iterating from row to row to the
requested row).</para>
</sect3>
<sect3 id="i_iter_next">
<title>i_iter_next() - required for cursor based access</title>
<para>This method is called to move an iterator to the next row; it's not necessary to
implement it if the data models supports random access.</para>
</sect3>
<sect3 id="i_iter_prev">
<title>i_iter_prev() - optional for cursor based access</title>
<para>This method is called to move an iterator to the previous row. It is only necessary to
implement it if the data model does not support random access and supports moving the
cursor backward.</para>
</sect3>
<sect3 id="i_set_value_at">
<title>i_set_value_at() - optional</title>
<para>This method needs to be defined if the data model allows each value in a (column,row) position
to be modified individually.
</para>
</sect3>
<sect3 id="i_iter_set_value">
<title>i_iter_set_value() - optional</title>
<para>This method can be defined if a specific treatment is required when a modification made
to a <link linkend="GdaDataModelIter">GdaDataModelIter</link> is propagated to the data model.
It should seldom, if ever, be necessary to implement it.</para>
</sect3>
<sect3 id="i_set_values">
<title>i_set_values() - optional</title>
<para>This method needs to be defined if the data model allows modifications to be made for
one complete row at a time. See the
<link linkend="gda-data-model-set-values">gda_data_model_set_values()</link> method for
more information about the arguments</para>
</sect3>
<sect3 id="i_append_values">
<title>i_append_values() - optional</title>
<para>This method can be implemented if the data model needs to support adding a row and defining the
values to be added in the same operation.
See <link linkend="gda-data-model-append-values">gda_data_model_append_values()</link> for
more information.</para>
</sect3>
<sect3 id="i_append_row">
<title>i_append_row() - optional</title>
<para>This method needs to be defined if the data model needs to support adding an empty row (i.e.
without any value specified in the new row).</para>
</sect3>
<sect3 id="i_remove_row">
<title>i_remove_row() - optional</title>
<para>This method should be implemented if the data model needs to support row removal.</para>
</sect3>
<sect3 id="i_find_row">
<title>i_find_row() - optional</title>
<para>This method can be implemented if the data model implements an indexing scheme which
allows it to find rows from values quickly than by analysing each row after another to
find the requested values.</para>
</sect3>
<sect3 id="i_set_notify">
<title>i_set_notify() - optional</title>
<para>This method should be implemented if the data model needs to honor the
<link linkend="gda-data-model-freeze">gda_data_model_freeze()</link> and
<link linkend="gda-data-model-thaw">gda_data_model_thaw()</link> methods. If
this method is not implemented, then these two methods will have no effect.
</para>
</sect3>
<sect3 id="i_get_notify">
<title>i_get_notify() - optional</title>
<para>This method should be implemented if the data model needs to honor the
<link linkend="gda-data-model-freeze">gda_data_model_freeze()</link> and
<link linkend="gda-data-model-thaw">gda_data_model_thaw()</link> methods. If
this method is not implemented, then these two methods will have no effect.</para>
</sect3>
<sect3 id="i_send_hint">
<title>i_send_hint() - optional</title>
<para>This method should be implemented if the data model needs to be able to treat
hints, see <link linkend="gda-data-model-send-hint">gda_data_model_send_hint()</link> for
more information</para>
</sect3>
<sect3 id="i_get_exceptions">
<title>i_get_exceptions() - optional</title>
<para>This method needs to be implemented if the data model keeps exceptions about the errors
it has encountered and may "export" these exceptions using the
<link linkend="gda-data-model-get-exceptions">gda_data_model_get_exceptions()</link> method.</para>
</sect3>
</sect2>
<sect2 id="gda-data-model-writing-signalling">
<title>Signalling changes</title>
<para>
When the data model changes, it needs to signal its changes. However, only the changes from
the initial state need to be notified, in situations such as:
<itemizedlist>
<listitem><para>a row which has already been accessed is modified or removed</para></listitem>
<listitem><para>the total number of rows changes, and that number has already been obtained and
was known (i.e. different than -1)</para></listitem>
</itemizedlist>
</para>
<para>
To signal changes, one of the following methods has to be used:
<itemizedlist>
<listitem><para><link linkend="gda-data-model-row-inserted">gda_data_model_row_inserted()</link>: to be called after a row has been inserted</para></listitem>
<listitem><para><link linkend="gda-data-model-row-updated">gda_data_model_row_updated()</link>: to be called after a row has been updated</para></listitem>
<listitem><para><link linkend="gda-data-model-row-removed">gda_data_model_row_removed()</link>: to be called after a row has been removed</para></listitem>
<listitem><para><link linkend="gda-data-model-reset">gda_data_model_reset()</link>: to be called
when the data model has changed in a way it's not possible or desirable to signal all the changes
using any combination of the above methods (for example when the whole contents has changed, or
when the number and/or types of columns has changed)</para></listitem>
</itemizedlist>
</para>
<para>
Moreover, when the data model's access flags have changed, the implementation should signal it by
emitting the <link linkend="GdaDataModel-access-changed">"access-changed"</link> signal.
</para>
</sect2>
</sect1>
|