static void
update_data_model_real (GdaDataModelDir *model, const gchar *rel_path)
{
	GDir *dir;
	GError *error = NULL;
	const gchar *raw_filename;
	gchar *complete_dir;

	complete_dir = g_build_path (G_DIR_SEPARATOR_S, model->priv->basedir, rel_path, NULL);
	dir = g_dir_open (complete_dir, 0, &error);
	if (!dir) {
		add_error (model, error && error->message ? error->message : _("No detail"));
		g_error_free (error);
		g_free (complete_dir);
		return;
	}

	raw_filename = g_dir_read_name (dir);
	while (raw_filename) {
		gchar *complete_filename;
		complete_filename = g_build_filename (complete_dir, raw_filename, NULL);

		if (g_file_test (complete_filename, G_FILE_TEST_IS_DIR)) {
			/* the . and .. directories are omitted by g_dir_read_name() */
			/* ignore hidden directories */
			if (*raw_filename != '.') {
				gchar *path;

				path = g_build_path (G_DIR_SEPARATOR_S, rel_path, raw_filename, NULL);
				update_data_model_real (model, path);
				g_free (path);
			}
		}
		else {
			/* ignore hidden files */
			if (*raw_filename != '.') {
				gchar *utf8_filename;
                				FileRow *row;
#ifndef G_OS_WIN32
				/* FIXME: correctly do the conversion */
				utf8_filename = g_strdup (raw_filename);
#else
				utf8_filename = g_strdup (raw_filename);
#endif

				model->priv->upd_row ++;

				if (model->priv->upd_row < (int)model->priv->rows->len) {
					row = g_ptr_array_index (model->priv->rows, model->priv->upd_row);
					file_row_clean (row);
				}
				else
					row = file_row_new ();
				row->reldir = g_strdup (rel_path);
#ifndef G_OS_WIN32
				row->raw_filename_value = g_strdup (raw_filename);
#else
				row->raw_filename_value = NULL; /* no need top copy on Windows */
#endif
				g_value_take_string (row->filename_value = gda_value_new (G_TYPE_STRING),
						     utf8_filename);

				/* file size */
				update_file_size (row, complete_filename);

				/* other attributes, computed only when needed */
				row->mime_value = NULL;
				row->md5sum_value = NULL;
				row->data_value = NULL;

				/* add row */
				if (model->priv->upd_row < (int)model->priv->rows->len)
					gda_data_model_row_updated ((GdaDataModel *) model, model->priv->upd_row);
				else {
					g_ptr_array_add (model->priv->rows, row);
					gda_data_model_row_inserted ((GdaDataModel *) model,
								     model->priv->rows->len - 1);
				}
			}
		}
		g_free (complete_filename);

		raw_filename = g_dir_read_name (dir);
	}

	g_free (complete_dir);
	g_dir_close (dir);
}
static void
model_row_inserted_cb (G_GNUC_UNUSED GdaDataModel *mod, gint row, GdaDataAccessWrapper *model)
{
	gda_data_model_row_inserted ((GdaDataModel*) model, row);
}
static gint
gda_data_model_dir_append_values (GdaDataModel *model, const GList *values, GError **error)
{
	GdaDataModelDir *imodel;
	const gchar *dirname = NULL, *filename = NULL;
	GdaBinary *bin_data = NULL;

	GList *list;
	gint col;
	g_return_val_if_fail (GDA_IS_DATA_MODEL_DIR (model), -1);
	imodel = (GdaDataModelDir *) model;
	g_return_val_if_fail (imodel->priv, -1);


	if (!values)
		return -1;
	for (col = 0, list = (GList *) values; list; list = list->next, col++) {
		GValue *value = (GValue *) list->data;
		if (!value || gda_value_is_null (value))
			continue;

		switch (col) {
		case COL_SIZE:
		case COL_MIME:
		case COL_MD5SUM:
		default:
			add_error (imodel, _("Column cannot be set"));
			g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
				     "%s",
				     _("Column cannot be set"));
			return -1;
		case COL_DIRNAME:
			if (G_VALUE_TYPE (value) == G_TYPE_STRING) {
				gint len, base_len;
				base_len = strlen (imodel->priv->basedir);
				dirname = g_value_get_string (value);
				len = strlen (dirname);
				if ((len < base_len) ||
				    (strncmp (dirname, imodel->priv->basedir, base_len))) {
					add_error (imodel, _("New path must be a subpath of the base directory"));
					g_set_error (error, GDA_DATA_MODEL_ERROR,
						     GDA_DATA_MODEL_ACCESS_ERROR,
						     "%s",
						     _("New path must be a subpath of the base directory"));
					return -1;
				}
			}
			break;
		case COL_FILENAME:
			if (G_VALUE_TYPE (value) == G_TYPE_STRING)
				filename = g_value_get_string (value);
			break;
		case COL_DATA:
			if (G_VALUE_TYPE (value) == GDA_TYPE_BLOB)
				bin_data = (GdaBinary *) gda_value_get_blob (value);
			else if (G_VALUE_TYPE (value) == GDA_TYPE_BINARY)
				bin_data = (GdaBinary *) gda_value_get_binary (value);
			break;
		}
	}

	if (dirname && filename && *filename) {
		if (!g_mkdir_with_parents (dirname, 0755)) {
			gchar *complete_filename;
			gboolean bin_to_free = FALSE;
			complete_filename = g_build_filename (dirname, filename, NULL);
			if (!bin_data) {
				bin_data = g_new0 (GdaBinary, 1);
				bin_to_free = TRUE;
			}
			if (g_file_set_contents (complete_filename, (gchar *) bin_data->data,
						 bin_data->binary_length, NULL)) {
				FileRow *row;

				row = file_row_new ();
				row->reldir = g_strdup (dirname + strlen (imodel->priv->basedir));
#ifndef G_OS_WIN32
				row->raw_filename_value = g_strdup (filename);
#else
				row->raw_filename_value = NULL; /* no need top copy on Windows */
#endif
				g_value_set_string (row->filename_value = gda_value_new (G_TYPE_STRING),
						    filename);

				/* file size */
				update_file_size (row, complete_filename);

				/* other attributes, computed only when needed */
				row->mime_value = NULL;
				row->md5sum_value = NULL;
				row->data_value = NULL;
				if (bin_to_free)
					g_free (bin_data);
				g_ptr_array_add (imodel->priv->rows, row);
				gda_data_model_row_inserted (model, imodel->priv->rows->len - 1);
				return imodel->priv->rows->len - 1;
			}
			else {
#ifndef G_OS_WIN32
				g_rmdir (dirname);
#endif
				gchar *str;
				str = g_strdup_printf (_("Cannot set contents of filename '%s'"), complete_filename);
				add_error (imodel, str);
				g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
					     "%s", str);
				g_free (str);
				if (bin_to_free)
					g_free (bin_data);
				return -1;
			}
		}
		else {
			gchar *str;
			str = g_strdup_printf (_("Cannot create directory '%s'"), dirname);
			add_error (imodel, str);
			g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
				     "%s", str);
			g_free (str);
			return -1;
		}
	}
	else {
		add_error (imodel, _("Cannot add row: filename missing"));
		g_set_error (error, GDA_DATA_MODEL_ERROR, GDA_DATA_MODEL_ACCESS_ERROR,
			     "%s", _("Cannot add row: filename missing"));
		return -1;
	}

	return -1;
}