blob: 3324a2b7dfeded898b24f31358ccf0b5a42cd5c7 [file] [log] [blame]
Stepan Salenikovicha3557452015-02-20 14:14:12 -05001/*
2 * Copyright (C) 2015 Savoir-Faire Linux Inc.
3 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30
31#include "gtkqtreemodel.h"
32#include <gtk/gtk.h>
33#include <QtCore/QAbstractItemModel>
34#include <QtCore/QDebug>
35#include "gtkaccessproxymodel.h"
36
37typedef union _int_ptr_t
38{
39 gint value;
40 gpointer ptr;
41} int_ptr_t;
42
43typedef struct _QIter {
44 gint stamp;
45 int_ptr_t row;
46 int_ptr_t column;
47 quintptr id;
48 gpointer user_data;
49} QIter;
50
51typedef struct _GtkQTreeModelPrivate GtkQTreeModelPrivate;
52
53struct _GtkQTreeModel
54{
55 GObject parent;
56
57 /* private */
58 GtkQTreeModelPrivate *priv;
59};
60
61struct _GtkQTreeModelClass
62{
63 GObjectClass parent_class;
64};
65
66struct _GtkQTreeModelPrivate
67{
68 GType *column_headers;
69 gint *column_roles;
70
71 gint stamp;
72 gint n_columns;
73
74 GtkAccessProxyModel *model;
75};
76
77/* static prototypes */
78
79/* GtkTreeModel prototypes */
80static void gtk_q_tree_model_tree_model_init (GtkTreeModelIface * );
81static void gtk_q_tree_model_finalize (GObject * );
82static GtkTreeModelFlags gtk_q_tree_model_get_flags (GtkTreeModel * );
83static gint gtk_q_tree_model_get_n_columns (GtkTreeModel * );
84static GType gtk_q_tree_model_get_column_type (GtkTreeModel *,
85 gint );
86static gboolean gtk_q_tree_model_get_iter (GtkTreeModel *,
87 GtkTreeIter *,
88 GtkTreePath * );
89static GtkTreePath * gtk_q_tree_model_get_path (GtkTreeModel *,
90 GtkTreeIter * );
91static void gtk_q_tree_model_get_value (GtkTreeModel *,
92 GtkTreeIter *,
93 gint,
94 GValue * );
95static gboolean gtk_q_tree_model_iter_next (GtkTreeModel *,
96 GtkTreeIter * );
97static gboolean gtk_q_tree_model_iter_previous (GtkTreeModel *,
98 GtkTreeIter * );
99static gboolean gtk_q_tree_model_iter_children (GtkTreeModel *,
100 GtkTreeIter *,
101 GtkTreeIter * );
102static gboolean gtk_q_tree_model_iter_has_child (GtkTreeModel *,
103 GtkTreeIter * );
104static gint gtk_q_tree_model_iter_n_children (GtkTreeModel *,
105 GtkTreeIter * );
106static gboolean gtk_q_tree_model_iter_nth_child (GtkTreeModel *,
107 GtkTreeIter *,
108 GtkTreeIter *,
109 gint );
110static gboolean gtk_q_tree_model_iter_parent (GtkTreeModel *,
111 GtkTreeIter *,
112 GtkTreeIter * );
113
114/* implementation prototypes */
115static void qmodelindex_to_iter (const QModelIndex &,
116 GtkTreeIter * );
117// static void gtk_q_tree_model_increment_stamp (GtkQTreeModel * );
118
119static gint gtk_q_tree_model_length (GtkQTreeModel * );
120
121static void gtk_q_tree_model_set_n_columns (GtkQTreeModel *,
122 gint );
123static void gtk_q_tree_model_set_column_type (GtkQTreeModel *,
124 gint,
125 gint,
126 GType );
127
128/* End private prototypes */
129
130/* define type, inherit from GObject, define implemented interface(s) */
131G_DEFINE_TYPE_WITH_CODE (GtkQTreeModel, gtk_q_tree_model, G_TYPE_OBJECT,
132 G_ADD_PRIVATE (GtkQTreeModel)
133 G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
134 gtk_q_tree_model_tree_model_init))
135
136#define GTK_Q_TREEMODEL_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_Q_TREE_MODEL, GtkQTreeModelPrivate))
137
138#define Q_ITER(iter) ((QIter *)iter)
139
140static void
141gtk_q_tree_model_class_init(GtkQTreeModelClass *klass)
142{
143 G_OBJECT_CLASS(klass)->finalize = gtk_q_tree_model_finalize;
144}
145
146static void
147gtk_q_tree_model_tree_model_init(GtkTreeModelIface *iface)
148{
149 iface->get_flags = gtk_q_tree_model_get_flags;
150 iface->get_n_columns = gtk_q_tree_model_get_n_columns;
151 iface->get_column_type = gtk_q_tree_model_get_column_type;
152 iface->get_iter = gtk_q_tree_model_get_iter;
153 iface->get_path = gtk_q_tree_model_get_path;
154 iface->get_value = gtk_q_tree_model_get_value;
155 iface->iter_next = gtk_q_tree_model_iter_next;
156 iface->iter_previous = gtk_q_tree_model_iter_previous;
157 iface->iter_children = gtk_q_tree_model_iter_children;
158 iface->iter_has_child = gtk_q_tree_model_iter_has_child;
159 iface->iter_n_children = gtk_q_tree_model_iter_n_children;
160 iface->iter_nth_child = gtk_q_tree_model_iter_nth_child;
161 iface->iter_parent = gtk_q_tree_model_iter_parent;
162}
163
164static void
165gtk_q_tree_model_init(GtkQTreeModel *q_tree_model)
166{
167 GtkQTreeModelPrivate *priv = GTK_Q_TREEMODEL_GET_PRIVATE(q_tree_model);
168 q_tree_model->priv = priv;
169
170 priv->stamp = g_random_int();
171 priv->model = NULL;
172}
173
174/**
175 * gtk_q_tree_model_get_qmodel
176 * returns the original model from which this GtkQTreeModel is created
177 */
178QAbstractItemModel *
179gtk_q_tree_model_get_qmodel(GtkQTreeModel *q_tree_model)
180{
181 GtkQTreeModelPrivate *priv = GTK_Q_TREEMODEL_GET_PRIVATE(q_tree_model);
182 return priv->model->sourceModel();
183}
184
185/**
186 * gtk_q_tree_model_get_source_idx
187 * Returns the index of the original model used to create this GtkQTreeModel from
188 * the given iter, if there is one.
189 */
190QModelIndex
191gtk_q_tree_model_get_source_idx(GtkQTreeModel *q_tree_model, GtkTreeIter *iter)
192{
193 GtkQTreeModelPrivate *priv = GTK_Q_TREEMODEL_GET_PRIVATE(q_tree_model);
194 /* get the call */
195 QIter *qiter = Q_ITER(iter);
196 GtkAccessProxyModel *proxy_model = priv->model;
197 QModelIndex proxy_idx = proxy_model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
198 if (proxy_idx.isValid()) {
199 /* we have the proxy model idx, now get the actual idx so we can get the call object */
200 g_debug("got valid model index");
201 return proxy_model->mapToSource(proxy_idx);
202 } else {
203 g_debug("returning invlaid model index");
204 return QModelIndex();
205 }
206}
207
208/**
209 * Takes a QModelIndex from the original QAbstractItemModel and returns a valid GtkTreeIter in the corresponding
210 * GtkQTreeModel
211 */
212gboolean
213gtk_q_tree_model_source_index_to_iter(GtkQTreeModel *q_tree_model, const QModelIndex &idx, GtkTreeIter *iter)
214{
215 GtkQTreeModelPrivate *priv = GTK_Q_TREEMODEL_GET_PRIVATE(q_tree_model);
216
217 /* make sure its an iter from the right model */
218 g_return_val_if_fail(idx.model() == priv->model->sourceModel(), FALSE);
219
220 /* make sure iter is valid */
221 iter->stamp = priv->stamp;
222
223 /* the the proxy_idx from the source idx */
224 QModelIndex proxy_idx = priv->model->mapFromSource(idx);
225
226 /* map the proxy idx to iter */
227 Q_ITER(iter)->row.value = proxy_idx.row();
228 Q_ITER(iter)->column.value = proxy_idx.row();
229 Q_ITER(iter)->id = proxy_idx.internalId();
230 return TRUE;
231}
232
233/**
234 * gtk_q_tree_model_new:
235 * @model: QAbstractItemModel to which this model will bind.
236 * @n_columns: number of columns in the list store
237 * @...: all #GType follwed by the #Role pair for each column.
238 *
239 * Return value: a new #GtkQTreeModel
240 */
241GtkQTreeModel *
242gtk_q_tree_model_new(QAbstractItemModel *model, size_t n_columns, ...)
243{
244 GtkQTreeModel *retval;
245 va_list args;
246 gint i;
247
248 g_return_val_if_fail(n_columns > 0, NULL);
249
250 retval = (GtkQTreeModel *)g_object_new(GTK_TYPE_Q_TREE_MODEL, NULL);
251 gtk_q_tree_model_set_n_columns(retval, n_columns);
252
253 /* get proxy model from given model */
254 GtkAccessProxyModel* proxy_model = new GtkAccessProxyModel();
255 proxy_model->setSourceModel(model);
256 retval->priv->model = proxy_model;
257 gint stamp = retval->priv->stamp;
258
259 n_columns = 2*n_columns;
260 va_start (args, n_columns);
261
262 for (i = 0; i < (gint)(n_columns/2); i++) {
263 /* first get the role of the QModel */
264 gint role = va_arg(args, gint);
265
266 /* then get the type the role will be interpreted as */
267 GType type = va_arg(args, GType);
268
269 /* TODO: check if its a type supported by our model
270 * if (! _gtk_tree_data_list_check_type (type))
271 * {
272 * g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
273 * g_object_unref (retval);
274 * va_end (args);
275 *
276 * return NULL;
277 * }
278 */
279
280 gtk_q_tree_model_set_column_type (retval, i, role, type);
281 }
282
283 va_end (args);
284
285 gtk_q_tree_model_length(retval);
286
287 /* connect signals */
288 QObject::connect(
289 model,
290 &QAbstractItemModel::rowsInserted,
291 [=](const QModelIndex & parent, int first, int last) {
292 for( int row = first; row <= last; row++) {
293 GtkTreeIter *iter = g_new0(GtkTreeIter, 1);
294 QModelIndex idx = retval->priv->model->index(row, 0, parent);
295 iter->stamp = stamp;
296 qmodelindex_to_iter(idx, iter);
297 GtkTreePath *path = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), iter);
298 gtk_tree_model_row_inserted(GTK_TREE_MODEL(retval), path, iter);
299 }
300 }
301 );
302
303 QObject::connect(
304 model,
305 &QAbstractItemModel::rowsAboutToBeMoved,
306 [=](const QModelIndex & sourceParent, int sourceStart, int sourceEnd, G_GNUC_UNUSED const QModelIndex & destinationParent, int destinationRow) {
307 g_debug("rows about to be moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
308 /* first remove the row from old location
309 * then insert them at the new location on the "rowsMoved signal */
310 for( int row = sourceStart; row <= sourceEnd; row++) {
311 QModelIndex idx = retval->priv->model->index(row, 0, sourceParent);
312 GtkTreeIter iter_old;
313 qmodelindex_to_iter(idx, &iter_old);
314 GtkTreePath *path_old = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), &iter_old);
315 gtk_tree_model_row_deleted(GTK_TREE_MODEL(retval), path_old);
316 }
317 }
318 );
319
320 QObject::connect(
321 model,
322 &QAbstractItemModel::rowsMoved,
323 [=](G_GNUC_UNUSED const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow) {
324 g_debug("rows moved, start: %d, end: %d, moved to: %d", sourceStart, sourceEnd, destinationRow);
325 /* these rows should have been removed in the "rowsAboutToBeMoved" handler
326 * now insert them in the new location */
327 for( int row = sourceStart; row <= sourceEnd; row++) {
328 GtkTreeIter *iter_new = g_new0(GtkTreeIter, 1);
329 QModelIndex idx = retval->priv->model->index(destinationRow, 0, destinationParent);
330 iter_new->stamp = stamp;
331 qmodelindex_to_iter(idx, iter_new);
332 GtkTreePath *path_new = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), iter_new);
333 gtk_tree_model_row_inserted(GTK_TREE_MODEL(retval), path_new, iter_new);
334 destinationRow++;
335 }
336 }
337 );
338
339 QObject::connect(
340 model,
341 &QAbstractItemModel::rowsAboutToBeRemoved,
342 [=](const QModelIndex & parent, int first, int last) {
343 for( int row = first; row <= last; row++) {
344 QModelIndex idx = retval->priv->model->index(row, 0, parent);
345 GtkTreeIter iter;
346 iter.stamp = stamp;
347 qmodelindex_to_iter(idx, &iter);
348 GtkTreePath *path = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), &iter);
349 gtk_tree_model_row_deleted(GTK_TREE_MODEL(retval), path);
350 }
351 }
352 );
353
354 QObject::connect(
355 model,
356 &QAbstractItemModel::dataChanged,
357 [=](const QModelIndex & topLeft, const QModelIndex & bottomRight, G_GNUC_UNUSED const QVector<int> & roles = QVector<int> ()) {
358 /* we have to assume only one column */
359 int first = topLeft.row();
360 int last = bottomRight.row();
361 if (topLeft.column() != bottomRight.column() ) {
362 g_warning("more than one column is not supported!");
363 }
364 /* the first idx IS topLeft, the reset are his siblings */
365 GtkTreeIter *iter = g_new0(GtkTreeIter, 1);
366 QModelIndex idx = topLeft;
367 iter->stamp = stamp;
368 qmodelindex_to_iter(idx, iter);
369 GtkTreePath *path = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), iter);
370 gtk_tree_model_row_changed(GTK_TREE_MODEL(retval), path, iter);
371 for( int row = first + 1; row <= last; row++) {
372 iter = g_new0(GtkTreeIter, 1);
373 idx = topLeft.sibling(row, 0);
374 iter->stamp = stamp;
375 qmodelindex_to_iter(idx, iter);
376 path = gtk_q_tree_model_get_path(GTK_TREE_MODEL(retval), iter);
377 gtk_tree_model_row_changed(GTK_TREE_MODEL(retval), path, iter);
378 }
379 }
380 );
381
382 return retval;
383}
384
385static gint
386gtk_q_tree_model_length(GtkQTreeModel *q_tree_model)
387{
388 GtkQTreeModelPrivate *priv = q_tree_model->priv;
389 return priv->model->rowCount();
390}
391
392static void
393gtk_q_tree_model_set_n_columns(GtkQTreeModel *q_tree_model,
394 gint n_columns)
395{
396 GtkQTreeModelPrivate *priv = q_tree_model->priv;
397 int i;
398
399 if (priv->n_columns == n_columns)
400 return;
401
402 priv->column_headers = g_renew (GType, priv->column_headers, n_columns);
403 for (i = priv->n_columns; i < n_columns; i++)
404 priv->column_headers[i] = G_TYPE_INVALID;
405 priv->n_columns = n_columns;
406
407 priv->column_roles = g_renew (gint, priv->column_roles, n_columns);
408 for (i = priv->n_columns; i < n_columns; i++)
409 priv->column_roles[i] = -1;
410}
411
412static void
413gtk_q_tree_model_set_column_type(GtkQTreeModel *q_tree_model,
414 gint column,
415 gint role,
416 GType type)
417{
418 GtkQTreeModelPrivate *priv = q_tree_model->priv;
419
420 /* TODO: check if its a type supported by our model
421 * if (!_gtk_tree_data_list_check_type (type))
422 * {
423 * g_warning ("%s: Invalid type %s\n", G_STRLOC, g_type_name (type));
424 * return;
425 * }
426 */
427
428 priv->column_headers[column] = type;
429 priv->column_roles[column] = role;
430}
431
432
433static void
434gtk_q_tree_model_finalize(GObject *object)
435{
436 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (object);
437 GtkQTreeModelPrivate *priv = q_tree_model->priv;
438
439 g_free(priv->column_headers);
440 g_free(priv->column_roles);
441
442 /* delete the created proxy model */
443 delete priv->model;
444
445 G_OBJECT_CLASS(gtk_q_tree_model_parent_class)->finalize (object);
446}
447
448static gboolean
449iter_is_valid(GtkTreeIter *iter,
450 GtkQTreeModel *q_tree_model)
451{
452 gboolean retval;
453 g_return_val_if_fail(iter != NULL, FALSE);
454 QIter *qiter = Q_ITER(iter);
455 retval = q_tree_model->priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id).isValid();
456 return retval;
457}
458
459static void
460qmodelindex_to_iter(const QModelIndex &idx, GtkTreeIter *iter)
461{
462 Q_ITER(iter)->row.value = idx.row();
463 Q_ITER(iter)->column.value = idx.row();
464 Q_ITER(iter)->id = idx.internalId();
465}
466
467static gboolean
468validate_index(gint stamp, const QModelIndex &idx, GtkTreeIter *iter)
469{
470 if (idx.isValid()) {
471 iter->stamp = stamp;
472 qmodelindex_to_iter(idx, iter);
473 } else {
474 iter->stamp = 0;
475 return FALSE;
476 }
477 return TRUE;
478}
479
480/* Start Fulfill the GtkTreeModel requirements */
481
482/* flags supported by this interface */
483static GtkTreeModelFlags
484gtk_q_tree_model_get_flags(G_GNUC_UNUSED GtkTreeModel *tree_model)
485{
486 // TODO: possibly return based on the model?
487 return (GtkTreeModelFlags)(GTK_TREE_MODEL_ITERS_PERSIST);
488}
489
490/* number of columns supported by this tree model */
491static gint
492gtk_q_tree_model_get_n_columns(GtkTreeModel *tree_model)
493{
494 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL(tree_model);
495 GtkQTreeModelPrivate *priv = q_tree_model->priv;
496
497 return priv->model->columnCount();
498}
499
500/* get given column type */
501static GType
502gtk_q_tree_model_get_column_type(GtkTreeModel *tree_model,
503 gint index)
504{
505 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
506 GtkQTreeModelPrivate *priv = q_tree_model->priv;
507
508 g_return_val_if_fail (index < gtk_q_tree_model_get_n_columns(tree_model), G_TYPE_INVALID);
509
510 return priv->column_headers[index];
511}
512
513/* Sets @iter to a valid iterator pointing to @path. If @path does
514 * not exist, @iter is set to an invalid iterator and %FALSE is returned.
515 */
516static gboolean
517gtk_q_tree_model_get_iter(GtkTreeModel *tree_model,
518 GtkTreeIter *iter,
519 GtkTreePath *path)
520{
521 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
522 GtkQTreeModelPrivate *priv = q_tree_model->priv;
523
524 /* GtkTreePath is a list of indices, each one indicates
525 * the child of the previous one.
526 * Since GtkTreeModel only has rows (columns are only used to
527 * store data in each item), each index is basically the row
528 * at the given tree level.
529 * To get the iter, we want to get the QModelIndex. To get
530 * the QModelIndex we simply start at the first level and
531 * traverse the model the number of layers equal to the number
532 * of indices in the path.
533 */
534 gint depth;
535 gint* indices = gtk_tree_path_get_indices_with_depth(path, &depth);
536 QModelIndex idx = priv->model->index(indices[0], 0);
537 for(int layer = 1; layer < depth; layer++ ) {
538 /* check if previous iter is valid */
539 if (!idx.isValid()) {
540 break;
541 } else {
542 idx = idx.child(indices[layer], 0);
543 }
544 }
545
546 if (!idx.isValid()) {
547 iter->stamp = 0;
548 return FALSE;
549 } else {
550 /* we have a valid QModelIndex; turn it into an iter */
551 iter->stamp = priv->stamp;
552 qmodelindex_to_iter(idx, iter);
553 }
554
555 return TRUE;
556}
557
558/* Returns a newly-created #GtkTreePath referenced by @iter.
559 *
560 * This path should be freed with gtk_tree_path_free().
561 */
562static GtkTreePath *
563gtk_q_tree_model_get_path(GtkTreeModel *tree_model,
564 GtkTreeIter *iter)
565{
566 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
567 GtkQTreeModelPrivate *priv = q_tree_model->priv;
568 GtkTreePath *path;
569
570 g_return_val_if_fail (iter->stamp == priv->stamp, NULL);
571 g_return_val_if_fail (iter_is_valid(iter, q_tree_model), NULL);
572
573 /* To get the path, we have to traverse from the child all the way up */
574 path = gtk_tree_path_new();
575 QIter *qiter = Q_ITER(iter);
576 QModelIndex idx = priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
577 while( idx.isValid() ){
578 gtk_tree_path_prepend_index(path, idx.row());
579 idx = idx.parent();
580 }
581 return path;
582}
583
584static inline GType
585get_fundamental_type(GType type)
586{
587 GType result;
588
589 result = G_TYPE_FUNDAMENTAL (type);
590
591 if (result == G_TYPE_INTERFACE) {
592 if (g_type_is_a (type, G_TYPE_OBJECT))
593 result = G_TYPE_OBJECT;
594 }
595
596 return result;
597}
598
599/* Initializes and sets @value to that at @column. */
600static void
601gtk_q_tree_model_get_value(GtkTreeModel *tree_model,
602 GtkTreeIter *iter,
603 gint column,
604 GValue *value)
605{
606 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
607 GtkQTreeModelPrivate *priv = q_tree_model->priv;
608
609 g_return_if_fail (column < priv->n_columns);
610 g_return_if_fail (iter_is_valid(iter, q_tree_model));
611
612 /* get the data */
613 QIter *qiter = Q_ITER(iter);
614 QModelIndex idx = priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
615 int role = priv->column_roles[column];
616 QVariant var = priv->model->data(idx, role);
617 GType type = priv->column_headers[column];
618 g_value_init (value, type);
619 switch (get_fundamental_type (type))
620 {
621 /* TODO: implement the rest of the data types the we plan to support
622 * otherwise get rid of the code and make sure un-implemented types
623 * are not allowed
624 */
625 case G_TYPE_BOOLEAN:
626 g_value_set_boolean (value, (gboolean) var.toBool());
627 break;
628 // case G_TYPE_CHAR:
629 // g_value_set_schar (value, (gchar) list->data.v_char);
630 // break;
631 // case G_TYPE_UCHAR:
632 // g_value_set_uchar (value, (guchar) list->data.v_uchar);
633 // break;
634 case G_TYPE_INT:
635 g_value_set_int (value, (gint) var.toInt());
636 break;
637 case G_TYPE_UINT:
638 g_value_set_uint (value, (guint) var.toUInt());
639 break;
640 // case G_TYPE_LONG:
641 // g_value_set_long (value, list->data.v_long);
642 // break;
643 // case G_TYPE_ULONG:
644 // g_value_set_ulong (value, list->data.v_ulong);
645 // break;
646 // case G_TYPE_INT64:
647 // g_value_set_int64 (value, list->data.v_int64);
648 // break;
649 // case G_TYPE_UINT64:
650 // g_value_set_uint64 (value, list->data.v_uint64);
651 // break;
652 // case G_TYPE_ENUM:
653 // g_value_set_enum (value, list->data.v_int);
654 // break;
655 // case G_TYPE_FLAGS:
656 // g_value_set_flags (value, list->data.v_uint);
657 // break;
658 // case G_TYPE_FLOAT:
659 // g_value_set_float (value, (gfloat) list->data.v_float);
660 // break;
661 // case G_TYPE_DOUBLE:
662 // g_value_set_double (value, (gdouble) list->data.v_double);
663 // break;
664 case G_TYPE_STRING:
665 g_value_set_string(value, (gchar *)var.toString().toLocal8Bit().data());
666 break;
667 // case G_TYPE_POINTER:
668 // g_value_set_pointer (value, (gpointer) list->data.v_pointer);
669 // break;
670 // case G_TYPE_BOXED:
671 // g_value_set_boxed (value, (gpointer) list->data.v_pointer);
672 // break;
673 // case G_TYPE_VARIANT:
674 // g_value_set_variant (value, (gpointer) list->data.v_pointer);
675 // break;
676 // case G_TYPE_OBJECT:
677 // g_value_set_object (value, (GObject *) list->data.v_pointer);
678 // break;
679 default:
680 g_warning ("%s: Unsupported type (%s) retrieved.", G_STRLOC, g_type_name (value->g_type));
681 break;
682 }
683
684 return;
685}
686
687/* Sets @iter to point to the node following it at the current level.
688 *
689 * If there is no next @iter, %FALSE is returned and @iter is set
690 * to be invalid.
691 */
692static gboolean
693gtk_q_tree_model_iter_next(GtkTreeModel *tree_model,
694 GtkTreeIter *iter)
695{
696 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
697 GtkQTreeModelPrivate *priv = q_tree_model->priv;
698
699 g_return_val_if_fail (iter_is_valid(iter, q_tree_model), FALSE);
700
701 QIter *qiter = Q_ITER(iter);
702 QModelIndex idx = priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
703 idx = idx.sibling(idx.row()+1, idx.column());
704
705 /* validate */
706 if (validate_index(priv->stamp, idx, iter) ) {
707 GtkTreePath *path = gtk_q_tree_model_get_path(tree_model, iter);
708 gtk_tree_path_free(path);
709 return TRUE;
710 } else {
711 return FALSE;
712 }
713}
714
715/* Sets @iter to point to the previous node at the current level.
716 *
717 * If there is no previous @iter, %FALSE is returned and @iter is
718 * set to be invalid.
719 */
720static gboolean
721gtk_q_tree_model_iter_previous(GtkTreeModel *tree_model,
722 GtkTreeIter *iter)
723{
724 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
725 GtkQTreeModelPrivate *priv = q_tree_model->priv;
726
727 g_return_val_if_fail (iter_is_valid(iter, q_tree_model), FALSE);
728
729 QIter *qiter = Q_ITER(iter);
730 QModelIndex idx = priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
731 idx = idx.sibling(idx.row()-1, idx.column());
732
733 /* validate */
734 return validate_index(priv->stamp, idx, iter);
735}
736
737/* Sets @iter to point to the first child of @parent.
738 *
739 * If @parent has no children, %FALSE is returned and @iter is
740 * set to be invalid. @parent will remain a valid node after this
741 * function has been called.
742 *
743 * If @parent is %NULL returns the first node
744 */
745static gboolean
746gtk_q_tree_model_iter_children(GtkTreeModel *tree_model,
747 GtkTreeIter *iter,
748 GtkTreeIter *parent)
749{
750 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
751 GtkQTreeModelPrivate *priv = q_tree_model->priv;
752 QModelIndex idx;
753
754 /* make sure parent if valid node if its not NULL */
755 if (parent)
756 g_return_val_if_fail(iter_is_valid(parent, q_tree_model), FALSE);
757
758 if (parent) {
759 /* get first child */
760 QIter *qparent = Q_ITER(parent);
761 idx = priv->model->indexFromId(qparent->row.value, qparent->column.value, qparent->id);
762 idx = idx.child(0, 0);
763 } else {
764 /* parent is NULL, get the first node */
765 idx = priv->model->index(0, 0);
766 }
767
768 /* validate child */
769 return validate_index(priv->stamp, idx, iter);
770}
771
772/* Returns %TRUE if @iter has children, %FALSE otherwise. */
773static gboolean
774gtk_q_tree_model_iter_has_child (GtkTreeModel *tree_model,
775 GtkTreeIter *iter)
776{
777 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
778 GtkQTreeModelPrivate *priv = q_tree_model->priv;
779 g_return_val_if_fail(iter_is_valid(iter, q_tree_model), FALSE);
780
781 QIter *qiter = Q_ITER(iter);
782 QModelIndex idx = priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
783 return priv->model->hasChildren(idx);
784}
785
786/* Returns the number of children that @iter has.
787 *
788 * As a special case, if @iter is %NULL, then the number
789 * of toplevel nodes is returned.
790 */
791static gint
792gtk_q_tree_model_iter_n_children (GtkTreeModel *tree_model,
793 GtkTreeIter *iter)
794{
795 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
796 GtkQTreeModelPrivate *priv = q_tree_model->priv;
797
798 if (iter == NULL)
799 return gtk_q_tree_model_length(q_tree_model);
800
801 g_return_val_if_fail(iter_is_valid(iter, q_tree_model), -1);
802 QIter *qiter = Q_ITER(iter);
803 QModelIndex idx = priv->model->indexFromId(qiter->row.value, qiter->column.value, qiter->id);
804 return priv->model->rowCount(idx);
805}
806
807/* Sets @iter to be the child of @parent, using the given index.
808 *
809 * The first index is 0. If @n is too big, or @parent has no children,
810 * @iter is set to an invalid iterator and %FALSE is returned. @parent
811 * will remain a valid node after this function has been called. As a
812 * special case, if @parent is %NULL, then the @n<!-- -->th root node
813 * is set.
814 */
815static gboolean
816gtk_q_tree_model_iter_nth_child(GtkTreeModel *tree_model,
817 GtkTreeIter *iter,
818 GtkTreeIter *parent,
819 gint n)
820{
821 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
822 GtkQTreeModelPrivate *priv = q_tree_model->priv;
823 QModelIndex idx;
824
825 if (parent) {
826 g_return_val_if_fail(iter_is_valid(parent, q_tree_model), FALSE);
827
828 /* get the nth child */
829 QIter *qparent = Q_ITER(parent);
830 idx = priv->model->indexFromId(qparent->row.value, qparent->column.value, qparent->id);
831 idx = idx.child(n, 0);
832 } else {
833 idx = priv->model->index(n, 0);
834 }
835
836 /* validate */
837 return validate_index(priv->stamp, idx, iter);
838}
839
840/* Sets @iter to be the parent of @child.
841 *
842 * If @child is at the toplevel, and doesn't have a parent, then
843 * @iter is set to an invalid iterator and %FALSE is returned.
844 * @child will remain a valid node after this function has been
845 * called.
846 */
847static gboolean
848gtk_q_tree_model_iter_parent(GtkTreeModel *tree_model,
849 GtkTreeIter *iter,
850 GtkTreeIter *child)
851{
852 GtkQTreeModel *q_tree_model = GTK_Q_TREE_MODEL (tree_model);
853 GtkQTreeModelPrivate *priv = q_tree_model->priv;
854 QModelIndex idx;
855
856 g_return_val_if_fail(iter_is_valid(child, q_tree_model), FALSE);
857
858 QIter *qchild = Q_ITER(child);
859 idx = priv->model->indexFromId(qchild->row.value, qchild->column.value, qchild->id);
860 idx = idx.parent();
861
862 /* validate */
863 return validate_index(priv->stamp, idx, iter);
864}
865
866/* End Fulfill the GtkTreeModel requirements */