Implementing your own data model: GNOME Data Access 5 manual

## Implementing your own data model

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.

Implementing a new GdaDataModel is simply a matter of creating a new GObject which implements the GdaDataModel 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 GObject's documentation, or online.

### Virtual methods

The interface's methods which can and/or need to be implemented are defined below.

#### i_get_n_rows() - optional

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.

#### i_get_n_columns() - required

This method, returns the total number of columns in the data model, or -1 if unknown.

#### i_describe_column() - required

This method describes a column; it returns (without any ownership to the caller) a GdaColumn for each existing column, or NULL otherwise.

#### i_get_access_flags() - required

This method defines how the data model may be accessed (randomly, only using a cursor, ...)

#### i_get_value_at() - required for random access

This method is used to access the contents of a data model, specifically a GValue 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 gda_data_model_get_value_at() for more information about the lifetime of the returned GValue.

#### i_get_attributes_at() - optional

This method returns, for a (column,row) position in the data model, the attributes of the adressed "cell".

#### i_create_iter() - optional

This method can be implemented to create specific GdaDataModelIter or to customize them.

#### i_iter_at_row() - optional

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).

#### i_iter_next() - required for cursor based access

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.

#### i_iter_prev() - optional for cursor based access

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.

#### i_set_value_at() - optional

This method needs to be defined if the data model allows each value in a (column,row) position to be modified individually.

#### i_iter_set_value() - optional

This method can be defined if a specific treatment is required when a modification made to a GdaDataModelIter is propagated to the data model. It should seldom, if ever, be necessary to implement it.

#### i_set_values() - optional

This method needs to be defined if the data model allows modifications to be made for one complete row at a time. See the gda_data_model_set_values() method for more information about the arguments

#### i_append_values() - optional

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 gda_data_model_append_values() for more information.

#### i_append_row() - optional

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).

#### i_remove_row() - optional

This method should be implemented if the data model needs to support row removal.

#### i_find_row() - optional

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.

#### i_set_notify() - optional

This method should be implemented if the data model needs to honor the gda_data_model_freeze() and gda_data_model_thaw() methods. If this method is not implemented, then these two methods will have no effect.

#### i_get_notify() - optional

This method should be implemented if the data model needs to honor the gda_data_model_freeze() and gda_data_model_thaw() methods. If this method is not implemented, then these two methods will have no effect.

#### i_send_hint() - optional

This method should be implemented if the data model needs to be able to treat hints, see gda_data_model_send_hint() for more information

#### i_get_exceptions() - optional

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 gda_data_model_get_exceptions() method.

### Signalling changes

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:

- a row which has already been accessed is modified or removed

- the total number of rows changes, and that number has already been obtained and was known (i.e. different than -1)

To signal changes, one of the following methods has to be used:

- gda_data_model_row_inserted(): to be called after a row has been inserted

- gda_data_model_row_updated(): to be called after a row has been updated

- gda_data_model_row_removed(): to be called after a row has been removed

- gda_data_model_reset(): 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)

Moreover, when the data model's access flags have changed, the implementation should signal it by emitting the "access-changed" signal.