17
17
* You should have received a copy of the GNU General Public
18
18
* License along with this program; if not, write to the
19
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
* Boston, MA 02111-1307, USA.
19
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20
* Boston, MA 02110-1301 USA.
52
53
static void rb_sourcelist_model_drag_dest_init (RbTreeDragDestIface *iface);
53
54
static void rb_sourcelist_model_drag_source_init (RbTreeDragSourceIface *iface);
54
55
static void rb_sourcelist_model_finalize (GObject *object);
56
static gboolean rb_sourcelist_model_is_row_visible (GtkTreeModel *model,
58
RBSourceListModel *sourcelist);
55
59
static gboolean rb_sourcelist_model_drag_data_received (RbTreeDragDest *drag_dest,
57
61
GtkTreeViewDropPosition pos,
76
80
GtkSelectionData *selection_data);
77
81
static gboolean rb_sourcelist_model_row_draggable (RbTreeDragSource *drag_source,
83
static void rb_sourcelist_model_row_inserted_cb (GtkTreeModel *model,
86
RBSourceListModel *sourcelist);
87
static void rb_sourcelist_model_row_deleted_cb (GtkTreeModel *model,
89
RBSourceListModel *sourcelist);
81
92
static guint rb_sourcelist_model_signals[LAST_SIGNAL] = { 0 };
181
192
rb_sourcelist_model_finalize (GObject *object)
194
RBSourceListModel *model;
197
g_return_if_fail (RB_IS_SOURCELIST_MODEL (object));
198
model = RB_SOURCELIST_MODEL (object);
200
for (i = 0; i < RB_SOURCELIST_GROUP_LAST; i++) {
201
gtk_tree_row_reference_free (model->priv->groups[i]);
183
204
G_OBJECT_CLASS (rb_sourcelist_model_parent_class)->finalize (object);
187
rb_sourcelist_is_row_visible (GtkTreeModel *model,
193
gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
194
RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
196
if (source != NULL) {
198
g_object_get (G_OBJECT (source), "visibility", &visible, NULL);
208
208
rb_sourcelist_model_new (void)
210
210
RBSourceListModel *model;
211
211
GtkTreeStore *store;
212
213
GType *column_types = g_new (GType, RB_SOURCELIST_MODEL_N_COLUMNS);
214
215
column_types[RB_SOURCELIST_MODEL_COLUMN_PLAYING] = G_TYPE_BOOLEAN;
223
225
"child-model", store,
224
226
"virtual-root", NULL,
229
/* create marker rows used to separate source groups */
230
for (i = 0; i < RB_SOURCELIST_GROUP_LAST; i++) {
234
gtk_tree_store_append (store, &iter, NULL);
235
gtk_tree_store_set (store, &iter,
236
RB_SOURCELIST_MODEL_COLUMN_NAME, "",
237
RB_SOURCELIST_MODEL_COLUMN_SOURCE, NULL,
238
RB_SOURCELIST_MODEL_COLUMN_VISIBILITY, FALSE,
241
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
242
model->priv->groups[i] = gtk_tree_row_reference_new (GTK_TREE_MODEL (store), path);
243
gtk_tree_path_free (path);
246
/* ensure the group markers get updated as sources are added and removed */
247
g_signal_connect_object (G_OBJECT (store), "row-inserted",
248
G_CALLBACK (rb_sourcelist_model_row_inserted_cb),
250
g_signal_connect_object (G_OBJECT (store), "row-deleted",
251
G_CALLBACK (rb_sourcelist_model_row_deleted_cb),
227
254
gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model),
228
rb_sourcelist_is_row_visible,
255
(GtkTreeModelFilterVisibleFunc) rb_sourcelist_model_is_row_visible,
231
258
g_free (column_types);
264
real_row_is_separator (RBSourceListModel *model, GtkTreeIter *iter)
268
GtkTreeModel *real_model;
269
GtkTreePath *group_path;
271
real_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
272
path = gtk_tree_model_get_path (real_model, iter);
274
/* -1 here because the last group marker is always the last row in
275
* the model, and therefore can never be shown.
277
for (i = 0; i < RB_SOURCELIST_GROUP_LAST-1; i++) {
278
group_path = rb_sourcelist_model_get_group_path (model, i);
280
if (gtk_tree_path_compare (path, group_path) == 0) {
281
/* okay, we know this is a group marker.
282
* if the next row is not a group marker,
283
* then we should show this row as a separator.
285
gboolean separator = FALSE;
287
gtk_tree_path_next (path);
289
gtk_tree_path_free (group_path);
290
group_path = rb_sourcelist_model_get_group_path (model, i+1);
291
separator = (gtk_tree_path_compare (path, group_path) != 0);
293
gtk_tree_path_free (group_path);
294
gtk_tree_path_free (path);
297
gtk_tree_path_free (group_path);
300
gtk_tree_path_free (path);
306
rb_sourcelist_model_is_row_visible (GtkTreeModel *model,
308
RBSourceListModel *sourcelist)
312
gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
313
RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
315
if (source != NULL) {
317
g_object_get (G_OBJECT (source), "visibility", &visible, NULL);
321
return real_row_is_separator (sourcelist, iter);
326
rb_sourcelist_model_row_is_separator (GtkTreeModel *model,
328
RBSourceListModel *sourcelist)
330
GtkTreeIter real_iter;
333
/* rows with actual sources are never separators */
334
gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
335
RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
339
gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (sourcelist),
342
return real_row_is_separator (sourcelist, &real_iter);
347
get_group_for_path (RBSourceListModel *model, GtkTreePath *path)
349
GtkTreePath *group_path;
350
gboolean found = FALSE;
353
for (i=0; i < RB_SOURCELIST_GROUP_LAST; i++) {
354
group_path = rb_sourcelist_model_get_group_path (model, i);
355
g_assert (group_path);
357
found = (gtk_tree_path_compare (group_path, path) == 1);
358
gtk_tree_path_free (group_path);
364
g_assert_not_reached ();
237
368
rb_sourcelist_model_drag_data_received (RbTreeDragDest *drag_dest,
238
369
GtkTreePath *dest,
239
370
GtkTreeViewDropPosition pos,
290
425
gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
291
426
&real_iter, &iter);
292
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (model),
294
gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
295
&real_dest_iter, &dest_iter);
429
gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (model),
432
gtk_tree_model_get (GTK_TREE_MODEL (real_model), &real_iter,
433
RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source,
435
g_object_get (G_OBJECT (source), "sourcelist-group", &group, NULL);
437
/* restrict sources to within their group */
438
dest_group = get_group_for_path (model, real_dest);
439
if (dest_group < group) {
440
gtk_tree_path_free (real_dest);
441
real_dest = rb_sourcelist_model_get_group_path (model, group-1);
442
pos = GTK_TREE_VIEW_DROP_AFTER;
443
} else if (dest_group > group) {
444
gtk_tree_path_free (real_dest);
445
real_dest = rb_sourcelist_model_get_group_path (model, group);
446
pos = GTK_TREE_VIEW_DROP_BEFORE;
449
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (real_model),
450
&real_dest_iter, real_dest)) {
296
452
if (pos == GTK_TREE_VIEW_DROP_AFTER)
297
453
gtk_tree_store_move_after (GTK_TREE_STORE (real_model),
298
454
&real_iter, &real_dest_iter);
300
456
gtk_tree_store_move_before (GTK_TREE_STORE (real_model),
301
457
&real_iter, &real_dest_iter);
303
460
gtk_tree_store_move_before (GTK_TREE_STORE (real_model),
304
461
&real_iter, NULL);
464
gtk_tree_path_free (real_dest);
465
gtk_tree_path_free (path);
305
466
g_free (path_str);
357
518
GtkTreeIter iter;
358
519
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (model), &iter, dest)) {
359
520
RBSource *source;
521
RBSourceListGroup group;
360
522
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
361
523
RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
363
/* currently, only playlists are reorderable; if this gets more
364
* complex, we should add 'rb_source_can_reorder' (or similar)
367
return RB_IS_PLAYLIST_SOURCE (source);
527
g_object_get (G_OBJECT (source), "sourcelist-group", &group, NULL);
529
/* fixed and transient sources are not reorderable, everything else is */
530
return (group != RB_SOURCELIST_GROUP_FIXED &&
531
group != RB_SOURCELIST_GROUP_TRANSIENT);
460
624
if (gtk_tree_model_get_iter (model, &iter, path)) {
461
625
RBSource *source;
626
RBSourceListGroup group;
463
628
gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
464
629
RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
631
g_object_get (G_OBJECT (source), "sourcelist-group", &group, NULL);
466
return rb_source_can_rename (source);
633
return (group != RB_SOURCELIST_GROUP_FIXED &&
634
group != RB_SOURCELIST_GROUP_TRANSIENT);
722
rb_sourcelist_model_row_inserted_cb (GtkTreeModel *model,
725
RBSourceListModel *sourcelist)
727
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (sourcelist));
731
rb_sourcelist_model_row_deleted_cb (GtkTreeModel *model,
733
RBSourceListModel *sourcelist)
735
gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (sourcelist));
739
rb_sourcelist_model_get_group_path (RBSourceListModel *sourcelist,
740
RBSourceListGroup group)
742
return gtk_tree_row_reference_get_path (sourcelist->priv->groups[group]);