1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001 Anders Carlsson, Jonathan Blanford
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library 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 GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include "eggcolumnmodel.h"
25 static void update_columns (GtkTreeView
*tree_view
, EggColumnModel
*column_model
);
38 static GObjectClass
*parent_class
= NULL
;
42 egg_column_model_get_n_columns (GtkTreeModel
*tree_model
)
48 egg_column_model_get_column_type (GtkTreeModel
*tree_model
,
54 return G_TYPE_BOOLEAN
;
58 return GTK_TYPE_TREE_VIEW_COLUMN
;
60 return G_TYPE_INVALID
;
65 egg_column_model_get_iter (GtkTreeModel
*tree_model
,
69 EggColumnModel
*column_model
= (EggColumnModel
*) tree_model
;
73 i
= gtk_tree_path_get_indices (path
)[0];
74 list
= g_list_nth (column_model
->columns
, i
);
81 iter
->stamp
= column_model
->stamp
;
82 iter
->user_data
= list
;
88 egg_column_model_get_path (GtkTreeModel
*tree_model
,
91 EggColumnModel
*column_model
= (EggColumnModel
*) tree_model
;
96 g_return_val_if_fail (EGG_IS_COLUMN_MODEL (tree_model
), NULL
);
97 g_return_val_if_fail (iter
->stamp
== EGG_COLUMN_MODEL (tree_model
)->stamp
, NULL
);
99 for (list
= column_model
->columns
; list
; list
= list
->next
)
101 if (list
== (GList
*)iter
->user_data
)
109 path
= gtk_tree_path_new ();
110 gtk_tree_path_append_index (path
, i
);
117 egg_column_model_iter_has_child (GtkTreeModel
*tree_model
,
120 g_return_val_if_fail (EGG_IS_COLUMN_MODEL (tree_model
), FALSE
);
121 g_return_val_if_fail (iter
->stamp
== EGG_COLUMN_MODEL (tree_model
)->stamp
, FALSE
);
127 egg_column_model_get_value (GtkTreeModel
*tree_model
,
132 GtkTreeViewColumn
*view_column
;
134 g_return_if_fail (EGG_IS_COLUMN_MODEL (tree_model
));
135 g_return_if_fail (column
< N_COLUMNS
);
136 g_return_if_fail (column
>= 0);
137 g_return_if_fail (iter
->stamp
== EGG_COLUMN_MODEL (tree_model
)->stamp
);
139 view_column
= GTK_TREE_VIEW_COLUMN (((GList
*)iter
->user_data
)->data
);
143 g_value_init (value
, G_TYPE_BOOLEAN
);
144 g_value_set_boolean (value
, gtk_tree_view_column_get_visible (view_column
));
147 g_value_init (value
, G_TYPE_STRING
);
148 g_value_set_string (value
, gtk_tree_view_column_get_title (view_column
));
151 g_value_init (value
, GTK_TYPE_TREE_VIEW_COLUMN
);
152 g_value_set_object (value
, view_column
);
155 g_assert_not_reached ();
162 egg_column_model_iter_next (GtkTreeModel
*tree_model
,
165 EggColumnModel
*column_model
;
167 g_return_val_if_fail (EGG_IS_COLUMN_MODEL (tree_model
), FALSE
);
168 g_return_val_if_fail (iter
->stamp
== EGG_COLUMN_MODEL (tree_model
)->stamp
, FALSE
);
170 column_model
= EGG_COLUMN_MODEL (tree_model
);
172 iter
->user_data
= ((GList
*)iter
->user_data
)->next
;
174 return (iter
->user_data
!= NULL
);
178 egg_column_model_iter_n_children (GtkTreeModel
*tree_model
,
181 g_return_val_if_fail (EGG_IS_COLUMN_MODEL (tree_model
), 0);
185 g_return_val_if_fail (iter
->stamp
== EGG_COLUMN_MODEL (tree_model
)->stamp
, 0);
189 return g_list_length (EGG_COLUMN_MODEL (tree_model
)->columns
);
193 egg_column_model_iter_nth_child (GtkTreeModel
*tree_model
,
198 EggColumnModel
*column_model
;
200 g_return_val_if_fail (EGG_IS_COLUMN_MODEL (tree_model
), FALSE
);
202 column_model
= EGG_COLUMN_MODEL (tree_model
);
205 g_return_val_if_fail (parent
->stamp
== EGG_COLUMN_MODEL (tree_model
)->stamp
, FALSE
);
209 iter
->user_data
= g_list_nth ((GList
*)column_model
->columns
, n
);
211 if (iter
->user_data
== NULL
)
214 iter
->stamp
= column_model
->stamp
;
220 * Gtk complains withouth this function, so add a dummy one.
223 egg_column_model_iter_children(GtkTreeModel
* tree_model
,
224 GtkTreeIter
* iter
, GtkTreeIter
* parent
)
230 egg_column_model_tree_model_init (GtkTreeModelIface
*iface
)
232 iface
->get_n_columns
= egg_column_model_get_n_columns
;
233 iface
->get_column_type
= egg_column_model_get_column_type
;
234 iface
->get_iter
= egg_column_model_get_iter
;
235 iface
->get_path
= egg_column_model_get_path
;
236 iface
->get_value
= egg_column_model_get_value
;
237 iface
->iter_has_child
= egg_column_model_iter_has_child
;
238 iface
->iter_next
= egg_column_model_iter_next
;
239 iface
->iter_nth_child
= egg_column_model_iter_nth_child
;
240 iface
->iter_n_children
= egg_column_model_iter_n_children
;
241 iface
->iter_children
= egg_column_model_iter_children
;
245 egg_column_model_drag_data_get (GtkTreeDragSource
*drag_source
, GtkTreePath
*path
, GtkSelectionData
*selection_data
)
248 if (gtk_selection_data_set_tree_row (selection_data
,
249 GTK_TREE_MODEL (drag_source
),
260 egg_column_model_drag_data_delete (GtkTreeDragSource
*drag_source
, GtkTreePath
*path
)
266 egg_column_model_drag_source_init (GtkTreeDragSourceIface
*iface
)
268 iface
->drag_data_get
= egg_column_model_drag_data_get
;
269 iface
->drag_data_delete
= egg_column_model_drag_data_delete
;
273 egg_column_model_row_drop_possible (GtkTreeDragDest
*drag_dest
,
274 GtkTreePath
*dest_path
,
275 GtkSelectionData
*selection_data
)
279 g_return_val_if_fail (EGG_IS_COLUMN_MODEL (drag_dest
), FALSE
);
281 if (gtk_tree_path_get_depth (dest_path
) != 1)
284 indices
= gtk_tree_path_get_indices (dest_path
);
286 if ((guint
)indices
[0] <= g_list_length (((EggColumnModel
*)drag_dest
)->columns
))
293 egg_column_model_drag_dest_init (GtkTreeDragDestIface
*iface
)
295 iface
->row_drop_possible
= egg_column_model_row_drop_possible
;
299 egg_column_model_init (EggColumnModel
*model
)
303 model
->stamp
= g_random_int ();
305 while (model
->stamp
== 0);
309 egg_column_model_finalize (GObject
*object
)
311 EggColumnModel
*model
;
313 model
= (EggColumnModel
*)object
;
315 g_list_free (model
->columns
);
317 g_signal_handlers_disconnect_by_func (G_OBJECT (model
->tree_view
), (void*)update_columns
, model
);
319 G_OBJECT_CLASS (parent_class
)->finalize (object
);
323 egg_column_model_class_init (EggColumnModelClass
*klass
)
325 GObjectClass
*object_class
;
327 object_class
= (GObjectClass
*)klass
;
329 parent_class
= (GObjectClass
*)g_type_class_peek_parent (klass
);
331 object_class
->finalize
= egg_column_model_finalize
;
335 egg_column_model_get_type (void)
337 static GType object_type
= 0;
341 static const GTypeInfo object_info
=
343 sizeof (EggColumnModelClass
),
346 (GClassInitFunc
) egg_column_model_class_init
,
349 sizeof (EggColumnModel
),
351 (GInstanceInitFunc
) egg_column_model_init
,
354 static const GInterfaceInfo tree_model_info
=
356 (GInterfaceInitFunc
) egg_column_model_tree_model_init
,
361 static const GInterfaceInfo drag_source_info
=
363 (GInterfaceInitFunc
) egg_column_model_drag_source_init
,
368 static const GInterfaceInfo drag_dest_info
=
370 (GInterfaceInitFunc
) egg_column_model_drag_dest_init
,
375 object_type
= g_type_register_static (G_TYPE_OBJECT
, "EggColumnModel", &object_info
, (GTypeFlags
)0);
376 g_type_add_interface_static (object_type
,
379 g_type_add_interface_static (object_type
,
380 GTK_TYPE_TREE_DRAG_SOURCE
,
382 g_type_add_interface_static (object_type
,
383 GTK_TYPE_TREE_DRAG_DEST
,
391 update_columns (GtkTreeView
*tree_view
,
392 EggColumnModel
*column_model
)
394 GList
*old_columns
= column_model
->columns
;
395 gint old_length
, length
;
398 column_model
->columns
= gtk_tree_view_get_columns (column_model
->tree_view
);
400 /* As the view tells us one change at a time, we can do this hack. */
401 length
= g_list_length (column_model
->columns
);
402 old_length
= g_list_length (old_columns
);
404 if (length
!= old_length
)
409 /* Find out where they differ */
410 for (a
= old_columns
, b
= column_model
->columns
; a
&& b
; a
= a
->next
, b
= b
->next
) {
411 if (a
->data
!= b
->data
)
416 path
= gtk_tree_path_new ();
417 gtk_tree_path_append_index (path
, i
);
419 if (length
< old_length
)
421 column_model
->stamp
++;
422 gtk_tree_model_row_deleted (GTK_TREE_MODEL (column_model
), path
);
428 iter
.stamp
= column_model
->stamp
;
430 gtk_tree_model_row_inserted (GTK_TREE_MODEL (column_model
), path
, &iter
);
433 gtk_tree_path_free (path
);
442 new_order
= g_new (int, length
);
443 a
= old_columns
; b
= column_model
->columns
;
445 while (a
->data
== b
->data
) {
457 if (a
->next
->data
== b
->data
)
460 while (b
->data
!= a
->data
)
465 for (i
= 0; i
< m
; i
++)
467 for (i
= m
; i
< m
+n
; i
++)
470 for (i
= m
+ n
+1; i
< length
; i
++)
476 while (a
->data
!= b
->data
)
481 for (i
= 0; i
< m
; i
++)
484 for (i
= m
+1; i
< m
+ n
+ 1; i
++)
485 new_order
[i
] = i
- 1;
486 for (i
= m
+ n
+ 1; i
< length
; i
++)
490 path
= gtk_tree_path_new ();
491 gtk_tree_model_rows_reordered (GTK_TREE_MODEL (column_model
),
495 gtk_tree_path_free (path
);
500 g_list_free (old_columns
);
504 egg_column_model_new (GtkTreeView
*tree_view
)
506 EggColumnModel
*model
;
508 model
= (EggColumnModel
*)g_object_new (egg_column_model_get_type (), NULL
);
510 model
->tree_view
= tree_view
;
511 model
->columns
= gtk_tree_view_get_columns (tree_view
);
513 g_signal_connect (G_OBJECT (tree_view
), "columns_changed",
514 G_CALLBACK (update_columns
), model
);
520 egg_column_model_set_column_visible (EggColumnModel
*model
, GtkTreeIter
*iter
, gboolean visible
)
522 GtkTreeViewColumn
*column
;
524 gchar
*string
= NULL
;
527 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (model
), iter
);
529 column
= (GtkTreeViewColumn
*)((GList
*)iter
->user_data
)->data
;
530 data
= g_object_get_data(G_OBJECT(column
), "colid");
531 colid
= GPOINTER_TO_INT(data
);
533 gtk_tree_view_column_set_visible (column
, visible
);
534 gtk_tree_model_row_changed (GTK_TREE_MODEL (model
), path
, iter
);
537 string
= g_strdup_printf("%i", colid
);
538 cfg_set_single_value_as_int(config
, "current-playlist-column-enable",string
, visible
);
540 gtk_tree_path_free (path
);
544 egg_column_model_get_column_visible (EggColumnModel
*model
, GtkTreeIter
*iter
)
546 GtkTreeViewColumn
*column
;
549 g_return_val_if_fail (model
->stamp
== iter
->stamp
, FALSE
);
551 column
= (GtkTreeViewColumn
*)((GList
*)iter
->user_data
)->data
;
553 return gtk_tree_view_column_get_visible (column
);
557 egg_column_model_is_column_first (EggColumnModel
*model
, GtkTreeIter
*iter
)
559 g_return_val_if_fail (model
->stamp
== iter
->stamp
, FALSE
);
561 return (((GList
*)iter
->user_data
)->prev
== NULL
);
565 egg_column_model_is_column_last (EggColumnModel
*model
, GtkTreeIter
*iter
)
567 g_return_val_if_fail (model
->stamp
== iter
->stamp
, FALSE
);
569 return (((GList
*)iter
->user_data
)->next
== NULL
);
573 egg_column_model_move_down_column (EggColumnModel
*model
, GtkTreeIter
*iter
)
575 GtkTreeViewColumn
*column
, *base_column
;
578 g_return_if_fail (model
->stamp
== iter
->stamp
);
579 g_return_if_fail (((GList
*)iter
->user_data
)->next
!= NULL
);
581 node
= (GList
*)iter
->user_data
;
583 column
= (GtkTreeViewColumn
*)node
->data
;
584 base_column
= (GtkTreeViewColumn
*)node
->next
->data
;
586 gtk_tree_view_move_column_after (model
->tree_view
, column
, base_column
);
590 egg_column_model_move_up_column (EggColumnModel
*model
, GtkTreeIter
*iter
)
592 GtkTreeViewColumn
*column
, *base_column
;
595 g_return_if_fail (model
->stamp
== iter
->stamp
);
596 g_return_if_fail (((GList
*)iter
->user_data
)->prev
!= NULL
);
598 node
= (GList
*)iter
->user_data
;
600 column
= (GtkTreeViewColumn
*)node
->prev
->data
;
601 base_column
= (GtkTreeViewColumn
*)node
->data
;
603 gtk_tree_view_move_column_after (model
->tree_view
, column
, base_column
);