1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * arch-tag: Implementation of widget to display RhythmDB properties
5 * Copyright (C) 2003 Colin Walters <walters@verbum.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <glib/gi18n.h>
29 #include <gdk/gdkkeysyms.h>
31 #include <libgnomevfs/gnome-vfs-utils.h>
33 #include "rb-property-view.h"
34 #include "rb-dialog.h"
37 #include "rhythmdb-property-model.h"
38 #include "rb-stock-icons.h"
39 #include "eel-gconf-extensions.h"
42 static void rb_property_view_class_init (RBPropertyViewClass
*klass
);
43 static void rb_property_view_init (RBPropertyView
*view
);
44 static void rb_property_view_finalize (GObject
*object
);
45 static void rb_property_view_set_property (GObject
*object
,
49 static void rb_property_view_get_property (GObject
*object
,
53 static GObject
* rb_property_view_constructor (GType type
, guint n_construct_properties
,
54 GObjectConstructParam
*construct_properties
);
55 static void rb_property_view_row_activated_cb (GtkTreeView
*treeview
,
57 GtkTreeViewColumn
*column
,
58 RBPropertyView
*view
);
59 static void rb_property_view_selection_changed_cb (GtkTreeSelection
*selection
,
60 RBPropertyView
*view
);
61 static void rb_property_view_pre_row_deleted_cb (RhythmDBPropertyModel
*model
,
62 RBPropertyView
*view
);
63 static void rb_property_view_post_row_deleted_cb (GtkTreeModel
*model
,
65 RBPropertyView
*view
);
66 static gboolean
rb_property_view_popup_menu_cb (GtkTreeView
*treeview
,
67 RBPropertyView
*view
);
68 static gboolean
rb_property_view_button_press_cb (GtkTreeView
*tree
,
69 GdkEventButton
*event
,
70 RBPropertyView
*view
);
72 struct RBPropertyViewPrivate
76 RhythmDBPropType propid
;
78 RhythmDBPropertyModel
*prop_model
;
83 GtkTreeSelection
*selection
;
86 gboolean handling_row_deletion
;
89 #define RB_PROPERTY_VIEW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_PROPERTY_VIEW, RBPropertyViewPrivate))
111 static guint rb_property_view_signals
[LAST_SIGNAL
] = { 0 };
120 static const GtkTargetEntry targets_album
[] = {
121 { "text/x-rhythmbox-album", 0, TARGET_ALBUMS
},
122 { "text/uri-list", 0, TARGET_URIS
},
124 static const GtkTargetEntry targets_genre
[] = {
125 { "text/x-rhythmbox-genre", 0, TARGET_GENRE
},
126 { "text/uri-list", 0, TARGET_URIS
},
128 static const GtkTargetEntry targets_artist
[] = {
129 { "text/x-rhythmbox-artist", 0, TARGET_ARTISTS
},
130 { "text/uri-list", 0, TARGET_URIS
},
133 G_DEFINE_TYPE (RBPropertyView
, rb_property_view
, GTK_TYPE_SCROLLED_WINDOW
)
136 rb_property_view_class_init (RBPropertyViewClass
*klass
)
138 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
140 object_class
->finalize
= rb_property_view_finalize
;
141 object_class
->constructor
= rb_property_view_constructor
;
143 object_class
->set_property
= rb_property_view_set_property
;
144 object_class
->get_property
= rb_property_view_get_property
;
146 g_object_class_install_property (object_class
,
148 g_param_spec_object ("db",
152 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
154 g_object_class_install_property (object_class
,
156 g_param_spec_enum ("prop",
159 RHYTHMDB_TYPE_PROP_TYPE
,
161 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
163 g_object_class_install_property (object_class
,
165 g_param_spec_string ("title",
169 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
170 g_object_class_install_property (object_class
,
172 g_param_spec_object ("property-model",
174 "RhythmDBPropertyModel",
175 RHYTHMDB_TYPE_PROPERTY_MODEL
,
177 g_object_class_install_property (object_class
,
179 g_param_spec_boolean ("draggable",
183 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
185 rb_property_view_signals
[PROPERTY_ACTIVATED
] =
186 g_signal_new ("property-activated",
187 G_OBJECT_CLASS_TYPE (object_class
),
189 G_STRUCT_OFFSET (RBPropertyViewClass
, property_activated
),
191 g_cclosure_marshal_VOID__STRING
,
196 rb_property_view_signals
[PROPERTY_SELECTED
] =
197 g_signal_new ("property-selected",
198 G_OBJECT_CLASS_TYPE (object_class
),
200 G_STRUCT_OFFSET (RBPropertyViewClass
, property_selected
),
202 g_cclosure_marshal_VOID__STRING
,
207 rb_property_view_signals
[PROPERTIES_SELECTED
] =
208 g_signal_new ("properties-selected",
209 G_OBJECT_CLASS_TYPE (object_class
),
211 G_STRUCT_OFFSET (RBPropertyViewClass
, properties_selected
),
213 g_cclosure_marshal_VOID__POINTER
,
218 rb_property_view_signals
[SELECTION_RESET
] =
219 g_signal_new ("property-selection-reset",
220 G_OBJECT_CLASS_TYPE (object_class
),
222 G_STRUCT_OFFSET (RBPropertyViewClass
, selection_reset
),
224 g_cclosure_marshal_VOID__VOID
,
227 rb_property_view_signals
[SHOW_POPUP
] =
228 g_signal_new ("show_popup",
229 G_OBJECT_CLASS_TYPE (object_class
),
231 G_STRUCT_OFFSET (RBPropertyViewClass
, show_popup
),
233 g_cclosure_marshal_VOID__VOID
,
237 g_type_class_add_private (klass
, sizeof (RBPropertyViewPrivate
));
241 rb_property_view_init (RBPropertyView
*view
)
243 view
->priv
= RB_PROPERTY_VIEW_GET_PRIVATE (view
);
247 rb_property_view_set_model_internal (RBPropertyView
*view
,
248 RhythmDBPropertyModel
*model
)
250 if (view
->priv
->prop_model
!= NULL
) {
251 g_signal_handlers_disconnect_by_func (view
->priv
->prop_model
,
252 G_CALLBACK (rb_property_view_pre_row_deleted_cb
),
254 g_signal_handlers_disconnect_by_func (view
->priv
->prop_model
,
255 G_CALLBACK (rb_property_view_post_row_deleted_cb
),
257 g_object_unref (view
->priv
->prop_model
);
260 view
->priv
->prop_model
= model
;
262 if (view
->priv
->prop_model
!= NULL
) {
265 g_object_ref (view
->priv
->prop_model
);
267 gtk_tree_view_set_model (GTK_TREE_VIEW (view
->priv
->treeview
),
268 GTK_TREE_MODEL (view
->priv
->prop_model
));
270 g_signal_connect_object (view
->priv
->prop_model
,
272 G_CALLBACK (rb_property_view_pre_row_deleted_cb
),
275 g_signal_connect_object (view
->priv
->prop_model
,
277 G_CALLBACK (rb_property_view_post_row_deleted_cb
),
281 g_signal_handlers_block_by_func (view
->priv
->selection
,
282 G_CALLBACK (rb_property_view_selection_changed_cb
),
285 gtk_tree_selection_unselect_all (view
->priv
->selection
);
287 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (view
->priv
->prop_model
), &iter
))
288 gtk_tree_selection_select_iter (view
->priv
->selection
, &iter
);
290 g_signal_handlers_unblock_by_func (view
->priv
->selection
,
291 G_CALLBACK (rb_property_view_selection_changed_cb
),
297 rb_property_view_finalize (GObject
*object
)
299 RBPropertyView
*view
;
301 g_return_if_fail (object
!= NULL
);
302 g_return_if_fail (RB_IS_PROPERTY_VIEW (object
));
304 view
= RB_PROPERTY_VIEW (object
);
306 g_return_if_fail (view
->priv
!= NULL
);
308 rb_property_view_set_model_internal (view
, NULL
);
310 g_free (view
->priv
->title
);
312 G_OBJECT_CLASS (rb_property_view_parent_class
)->finalize (object
);
316 rb_property_view_set_property (GObject
*object
,
321 RBPropertyView
*view
= RB_PROPERTY_VIEW (object
);
325 view
->priv
->db
= g_value_get_object (value
);
328 view
->priv
->propid
= g_value_get_enum (value
);
331 view
->priv
->title
= g_value_dup_string (value
);
334 rb_property_view_set_model_internal (view
, g_value_get_object (value
));
337 view
->priv
->draggable
= g_value_get_boolean (value
);
340 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
346 rb_property_view_get_property (GObject
*object
,
351 RBPropertyView
*view
= RB_PROPERTY_VIEW (object
);
355 g_value_set_object (value
, view
->priv
->db
);
358 g_value_set_enum (value
, view
->priv
->propid
);
361 g_value_set_string (value
, view
->priv
->title
);
364 g_value_set_object (value
, view
->priv
->prop_model
);
367 g_value_set_boolean (value
, view
->priv
->draggable
);
370 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
376 rb_property_view_new (RhythmDB
*db
,
380 RBPropertyView
*view
;
382 view
= RB_PROPERTY_VIEW (g_object_new (RB_TYPE_PROPERTY_VIEW
,
385 "hscrollbar_policy", GTK_POLICY_AUTOMATIC
,
386 "vscrollbar_policy", GTK_POLICY_ALWAYS
,
387 "shadow_type", GTK_SHADOW_IN
,
394 g_return_val_if_fail (view
->priv
!= NULL
, NULL
);
400 rb_property_view_set_selection_mode (RBPropertyView
*view
,
401 GtkSelectionMode mode
)
403 g_return_if_fail (RB_IS_PROPERTY_VIEW (view
));
404 g_return_if_fail (mode
== GTK_SELECTION_SINGLE
|| mode
== GTK_SELECTION_MULTIPLE
);
406 gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (view
->priv
->treeview
)),
411 rb_property_view_reset (RBPropertyView
*view
)
413 RhythmDBPropertyModel
*model
;
415 g_return_if_fail (RB_IS_PROPERTY_VIEW (view
));
417 model
= rhythmdb_property_model_new (view
->priv
->db
, view
->priv
->propid
);
419 rb_property_view_set_model_internal (view
, model
);
420 g_object_unref (model
);
423 RhythmDBPropertyModel
*
424 rb_property_view_get_model (RBPropertyView
*view
)
426 RhythmDBPropertyModel
*model
;
428 g_return_val_if_fail (RB_IS_PROPERTY_VIEW (view
), NULL
);
430 model
= view
->priv
->prop_model
;
436 rb_property_view_set_model (RBPropertyView
*view
,
437 RhythmDBPropertyModel
*model
)
439 g_return_if_fail (RB_IS_PROPERTY_VIEW (view
));
441 rb_property_view_set_model_internal (view
, model
);
445 rb_property_view_pre_row_deleted_cb (RhythmDBPropertyModel
*model
,
446 RBPropertyView
*view
)
448 view
->priv
->handling_row_deletion
= TRUE
;
449 rb_debug ("pre row deleted");
453 rb_property_view_post_row_deleted_cb (GtkTreeModel
*model
,
455 RBPropertyView
*view
)
457 view
->priv
->handling_row_deletion
= FALSE
;
458 rb_debug ("post row deleted");
459 if (gtk_tree_selection_count_selected_rows (view
->priv
->selection
) == 0) {
460 GtkTreeIter first_iter
;
461 rb_debug ("no rows selected, signalling reset");
462 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (view
->priv
->prop_model
), &first_iter
)) {
463 g_signal_handlers_block_by_func (G_OBJECT (view
->priv
->selection
),
464 G_CALLBACK (rb_property_view_selection_changed_cb
),
466 gtk_tree_selection_select_iter (view
->priv
->selection
, &first_iter
);
467 g_signal_emit (G_OBJECT (view
), rb_property_view_signals
[SELECTION_RESET
], 0);
468 g_signal_handlers_unblock_by_func (G_OBJECT (view
->priv
->selection
),
469 G_CALLBACK (rb_property_view_selection_changed_cb
),
476 rb_property_view_get_num_properties (RBPropertyView
*view
)
478 g_return_val_if_fail (RB_IS_PROPERTY_VIEW (view
), 0);
480 return gtk_tree_model_iter_n_children (GTK_TREE_MODEL (view
->priv
->prop_model
),
485 rb_property_view_cell_data_func (GtkTreeViewColumn
*column
,
486 GtkCellRenderer
*renderer
,
487 GtkTreeModel
*tree_model
,
489 RBPropertyView
*view
)
496 gtk_tree_model_get (GTK_TREE_MODEL (tree_model
), iter
,
497 RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE
, &title
,
498 RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY
, &is_all
,
499 RHYTHMDB_PROPERTY_MODEL_COLUMN_NUMBER
, &number
, -1);
505 nodes
= gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree_model
), NULL
);
506 /* Subtract one for the All node */
509 switch (view
->priv
->propid
) {
510 case RHYTHMDB_PROP_ARTIST
:
511 fmt
= ngettext ("All %d artist (%d)", "All %d artists (%d)", nodes
);
513 case RHYTHMDB_PROP_ALBUM
:
514 fmt
= ngettext ("All %d album (%d)", "All %d albums (%d)", nodes
);
516 case RHYTHMDB_PROP_GENRE
:
517 fmt
= ngettext ("All %d genre (%d)", "All %d genres (%d)", nodes
);
520 fmt
= _("All %d (%d)");
524 str
= g_strdup_printf (fmt
, nodes
, number
);
526 str
= g_strdup_printf (_("%s (%d)"), title
, number
);
529 g_object_set (G_OBJECT (renderer
), "text", str
,
530 "weight", G_UNLIKELY (is_all
) ? PANGO_WEIGHT_BOLD
: PANGO_WEIGHT_NORMAL
,
537 rb_property_view_constructor (GType type
,
538 guint n_construct_properties
,
539 GObjectConstructParam
*construct_properties
)
541 GtkTreeViewColumn
*column
;
542 GtkCellRenderer
*renderer
;
544 RBPropertyView
*view
;
545 RBPropertyViewClass
*klass
;
547 klass
= RB_PROPERTY_VIEW_CLASS (g_type_class_peek (RB_TYPE_PROPERTY_VIEW
));
549 view
= RB_PROPERTY_VIEW (G_OBJECT_CLASS (rb_property_view_parent_class
)->
550 constructor (type
, n_construct_properties
, construct_properties
));
552 view
->priv
->prop_model
= rhythmdb_property_model_new (view
->priv
->db
, view
->priv
->propid
);
553 view
->priv
->treeview
= GTK_WIDGET (gtk_tree_view_new_with_model (GTK_TREE_MODEL (view
->priv
->prop_model
)));
555 if (view
->priv
->draggable
)
556 rhythmdb_property_model_enable_drag (view
->priv
->prop_model
,
557 GTK_TREE_VIEW (view
->priv
->treeview
));
559 g_signal_connect_object (G_OBJECT (view
->priv
->treeview
),
561 G_CALLBACK (rb_property_view_row_activated_cb
),
565 view
->priv
->selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
->priv
->treeview
));
566 g_signal_connect_object (G_OBJECT (view
->priv
->selection
),
568 G_CALLBACK (rb_property_view_selection_changed_cb
),
571 g_signal_connect_object (G_OBJECT (view
->priv
->treeview
),
573 G_CALLBACK (rb_property_view_popup_menu_cb
),
577 g_signal_connect_object (G_OBJECT (view
->priv
->treeview
),
578 "button_press_event",
579 G_CALLBACK (rb_property_view_button_press_cb
),
583 gtk_container_add (GTK_CONTAINER (view
), view
->priv
->treeview
);
585 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view
->priv
->treeview
), TRUE
);
586 gtk_tree_selection_set_mode (view
->priv
->selection
, GTK_SELECTION_SINGLE
);
588 column
= gtk_tree_view_column_new ();
589 renderer
= gtk_cell_renderer_text_new ();
590 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
591 gtk_tree_view_column_set_cell_data_func (column
, renderer
,
592 (GtkTreeCellDataFunc
) rb_property_view_cell_data_func
,
594 gtk_tree_view_column_set_title (column
, view
->priv
->title
);
595 gtk_tree_view_column_set_sizing (column
, GTK_TREE_VIEW_COLUMN_FIXED
);
596 gtk_tree_view_append_column (GTK_TREE_VIEW (view
->priv
->treeview
),
599 return G_OBJECT (view
);
603 rb_property_view_row_activated_cb (GtkTreeView
*treeview
,
605 GtkTreeViewColumn
*column
,
606 RBPropertyView
*view
)
612 rb_debug ("row activated");
613 g_return_if_fail (gtk_tree_model_get_iter (GTK_TREE_MODEL (view
->priv
->prop_model
),
616 gtk_tree_model_get (GTK_TREE_MODEL (view
->priv
->prop_model
), &iter
,
617 RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE
, &val
,
618 RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY
, &is_all
, -1);
620 rb_debug ("emitting property activated");
621 g_signal_emit (G_OBJECT (view
), rb_property_view_signals
[PROPERTY_ACTIVATED
], 0,
622 is_all
? NULL
: val
);
628 rb_property_view_set_selection (RBPropertyView
*view
,
631 g_return_if_fail (RB_IS_PROPERTY_VIEW (view
));
633 view
->priv
->handling_row_deletion
= TRUE
;
635 gtk_tree_selection_unselect_all (view
->priv
->selection
);
637 for (; vals
; vals
= vals
->next
) {
640 if (rhythmdb_property_model_iter_from_string (view
->priv
->prop_model
, vals
->data
, &iter
)) {
643 gtk_tree_selection_select_iter (view
->priv
->selection
, &iter
);
644 path
= gtk_tree_model_get_path (GTK_TREE_MODEL (view
->priv
->prop_model
), &iter
);
646 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (view
->priv
->treeview
),
649 gtk_tree_path_free (path
);
655 view
->priv
->handling_row_deletion
= FALSE
;
656 rb_property_view_selection_changed_cb (view
->priv
->selection
, view
);
660 rb_property_view_selection_changed_cb (GtkTreeSelection
*selection
,
661 RBPropertyView
*view
)
663 char *selected_prop
= NULL
;
664 gboolean is_all
= TRUE
;
668 if (view
->priv
->handling_row_deletion
)
671 rb_debug ("selection changed");
672 if (gtk_tree_selection_get_mode (selection
) == GTK_SELECTION_MULTIPLE
) {
673 GList
*selected_rows
, *tem
;
674 GList
*selected_properties
= NULL
;
676 selected_rows
= gtk_tree_selection_get_selected_rows (view
->priv
->selection
, &model
);
677 for (tem
= selected_rows
; tem
; tem
= tem
->next
) {
678 g_assert (gtk_tree_model_get_iter (model
, &iter
, tem
->data
));
679 gtk_tree_model_get (model
, &iter
,
680 RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE
, &selected_prop
,
681 RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY
, &is_all
, -1);
683 g_list_free (selected_properties
);
684 selected_properties
= NULL
;
687 selected_properties
= g_list_prepend (selected_properties
,
688 g_strdup (selected_prop
));
691 g_list_foreach (selected_rows
, (GFunc
) gtk_tree_path_free
, NULL
);
692 g_list_free (selected_rows
);
695 g_signal_handlers_block_by_func (G_OBJECT (view
->priv
->selection
),
696 G_CALLBACK (rb_property_view_selection_changed_cb
),
698 gtk_tree_selection_unselect_all (selection
);
699 if (gtk_tree_model_get_iter_first (model
, &iter
))
700 gtk_tree_selection_select_iter (selection
, &iter
);
701 g_signal_handlers_unblock_by_func (G_OBJECT (view
->priv
->selection
),
702 G_CALLBACK (rb_property_view_selection_changed_cb
),
705 g_signal_emit (G_OBJECT (view
), rb_property_view_signals
[PROPERTIES_SELECTED
], 0,
706 selected_properties
);
707 rb_list_deep_free (selected_properties
);
709 if (gtk_tree_selection_get_selected (view
->priv
->selection
, &model
, &iter
)) {
710 gtk_tree_model_get (model
, &iter
,
711 RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE
, &selected_prop
,
712 RHYTHMDB_PROPERTY_MODEL_COLUMN_PRIORITY
, &is_all
, -1);
713 g_signal_emit (G_OBJECT (view
), rb_property_view_signals
[PROPERTY_SELECTED
], 0,
714 is_all
? NULL
: selected_prop
);
718 g_free (selected_prop
);
722 rb_property_view_popup_menu_cb (GtkTreeView
*treeview
,
723 RBPropertyView
*view
)
725 g_signal_emit (G_OBJECT (view
), rb_property_view_signals
[SHOW_POPUP
], 0);
730 rb_property_view_append_column_custom (RBPropertyView
*view
,
731 GtkTreeViewColumn
*column
)
733 g_return_if_fail (RB_IS_PROPERTY_VIEW (view
));
735 gtk_tree_view_append_column (GTK_TREE_VIEW (view
->priv
->treeview
), column
);
739 rb_property_view_button_press_cb (GtkTreeView
*tree
,
740 GdkEventButton
*event
,
741 RBPropertyView
*view
)
744 if (event
->button
== 3) {
745 GtkTreeSelection
*selection
;
748 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
->priv
->treeview
));
750 gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view
->priv
->treeview
), event
->x
, event
->y
, &path
, NULL
, NULL
, NULL
);
752 gtk_tree_selection_unselect_all (selection
);
759 model
= gtk_tree_view_get_model (GTK_TREE_VIEW (view
->priv
->treeview
));
760 if (gtk_tree_model_get_iter (model
, &iter
, path
)) {
761 gtk_tree_model_get (model
, &iter
,
762 RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE
, &val
, -1);
763 lst
= g_list_prepend (lst
, (gpointer
) val
);
764 rb_property_view_set_selection (view
, lst
);
768 g_signal_emit (G_OBJECT (view
), rb_property_view_signals
[SHOW_POPUP
], 0);
776 rb_property_view_set_search_func (RBPropertyView
*view
,
777 GtkTreeViewSearchEqualFunc func
,
779 GtkDestroyNotify notify
)
781 g_return_if_fail (RB_IS_PROPERTY_VIEW (view
));
783 gtk_tree_view_set_search_equal_func (GTK_TREE_VIEW (view
->priv
->treeview
),