~ubuntu-branches/ubuntu/oneiric/rhythmbox/oneiric

« back to all changes in this revision

Viewing changes to sources/rb-sourcelist-model.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2006-06-26 19:06:10 UTC
  • mto: (2.1.1 lenny) (1.1.37 upstream)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20060626190610-08x8lgvvfs0gr619
Tags: upstream-0.9.5
ImportĀ upstreamĀ versionĀ 0.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 *
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.
21
21
 *
22
22
 */
23
23
 
37
37
 
38
38
struct RBSourceListModelPrivate
39
39
{
 
40
        GtkTreeRowReference *groups[RB_SOURCELIST_GROUP_LAST];
40
41
};
41
42
 
42
43
#define RB_SOURCELIST_MODEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_SOURCELIST_MODEL, RBSourceListModelPrivate))
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,
 
57
                                                    GtkTreeIter *iter,
 
58
                                                    RBSourceListModel *sourcelist);
55
59
static gboolean rb_sourcelist_model_drag_data_received (RbTreeDragDest *drag_dest,
56
60
                                                        GtkTreePath *dest,
57
61
                                                        GtkTreeViewDropPosition pos,
76
80
                                                   GtkSelectionData *selection_data);
77
81
static gboolean rb_sourcelist_model_row_draggable (RbTreeDragSource *drag_source,
78
82
                                                   GList *path_list);
 
83
static void rb_sourcelist_model_row_inserted_cb (GtkTreeModel *model, 
 
84
                                                 GtkTreePath *path, 
 
85
                                                 GtkTreeIter *iter, 
 
86
                                                 RBSourceListModel *sourcelist);
 
87
static void rb_sourcelist_model_row_deleted_cb (GtkTreeModel *model,
 
88
                                                GtkTreePath *path,
 
89
                                                RBSourceListModel *sourcelist);
79
90
 
80
91
 
81
92
static guint rb_sourcelist_model_signals[LAST_SIGNAL] = { 0 };
168
179
        rb_tree_dnd_add_drag_source_support (treeview,
169
180
                                             GDK_BUTTON1_MASK,
170
181
                                             sourcelist_targets, n_targets,
171
 
                                             GDK_ACTION_MOVE | GDK_ACTION_COPY);
 
182
                                             GDK_ACTION_COPY);
172
183
}
173
184
                
174
185
static void
180
191
static void
181
192
rb_sourcelist_model_finalize (GObject *object)
182
193
{
 
194
        RBSourceListModel *model;
 
195
        int i;
 
196
 
 
197
        g_return_if_fail (RB_IS_SOURCELIST_MODEL (object));
 
198
        model = RB_SOURCELIST_MODEL (object);
 
199
 
 
200
        for (i = 0; i < RB_SOURCELIST_GROUP_LAST; i++) {
 
201
                gtk_tree_row_reference_free (model->priv->groups[i]);
 
202
        }
 
203
 
183
204
        G_OBJECT_CLASS (rb_sourcelist_model_parent_class)->finalize (object);
184
205
}
185
206
 
186
 
static gboolean
187
 
rb_sourcelist_is_row_visible (GtkTreeModel *model,
188
 
                              GtkTreeIter *iter,
189
 
                              gpointer data)
190
 
{
191
 
        RBSource *source;
192
 
 
193
 
        gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
194
 
                            RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
195
 
        
196
 
        if (source != NULL) {
197
 
                gboolean visible;       
198
 
                g_object_get (G_OBJECT (source), "visibility", &visible, NULL);
199
 
 
200
 
                return visible;
201
 
        } else {
202
 
                return FALSE;
203
 
        }
204
 
}
205
 
 
206
 
 
207
207
GtkTreeModel *
208
208
rb_sourcelist_model_new (void)
209
209
{
210
210
        RBSourceListModel *model;
211
211
        GtkTreeStore *store;
 
212
        int i;
212
213
        GType *column_types = g_new (GType, RB_SOURCELIST_MODEL_N_COLUMNS);
213
214
 
214
215
        column_types[RB_SOURCELIST_MODEL_COLUMN_PLAYING] = G_TYPE_BOOLEAN;
216
217
        column_types[RB_SOURCELIST_MODEL_COLUMN_NAME] = G_TYPE_STRING;
217
218
        column_types[RB_SOURCELIST_MODEL_COLUMN_SOURCE] = G_TYPE_POINTER;
218
219
        column_types[RB_SOURCELIST_MODEL_COLUMN_ATTRIBUTES] = PANGO_TYPE_ATTR_LIST;
 
220
        column_types[RB_SOURCELIST_MODEL_COLUMN_VISIBILITY] = G_TYPE_BOOLEAN;
219
221
        store = gtk_tree_store_newv (RB_SOURCELIST_MODEL_N_COLUMNS, 
220
222
                                     column_types);
221
223
 
223
225
                                                   "child-model", store,
224
226
                                                   "virtual-root", NULL,
225
227
                                                   NULL));
 
228
        
 
229
        /* create marker rows used to separate source groups */
 
230
        for (i = 0; i < RB_SOURCELIST_GROUP_LAST; i++) {
 
231
                GtkTreeIter iter;
 
232
                GtkTreePath *path;
 
233
 
 
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,
 
239
                                    -1);
 
240
 
 
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);
 
244
        }
 
245
 
 
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), 
 
249
                                 model, 0);
 
250
        g_signal_connect_object (G_OBJECT (store), "row-deleted",
 
251
                                 G_CALLBACK (rb_sourcelist_model_row_deleted_cb), 
 
252
                                 model, 0);
226
253
 
227
254
        gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (model), 
228
 
                                                rb_sourcelist_is_row_visible, 
229
 
                                                NULL, NULL);
 
255
                                                (GtkTreeModelFilterVisibleFunc) rb_sourcelist_model_is_row_visible, 
 
256
                                                model, NULL);
230
257
 
231
258
        g_free (column_types);
232
259
 
234
261
}
235
262
 
236
263
static gboolean
 
264
real_row_is_separator (RBSourceListModel *model, GtkTreeIter *iter)
 
265
{
 
266
        int i;
 
267
        GtkTreePath *path;
 
268
        GtkTreeModel *real_model;
 
269
        GtkTreePath *group_path;
 
270
 
 
271
        real_model = gtk_tree_model_filter_get_model (GTK_TREE_MODEL_FILTER (model));
 
272
        path = gtk_tree_model_get_path (real_model, iter);
 
273
 
 
274
        /* -1 here because the last group marker is always the last row in
 
275
         * the model, and therefore can never be shown.
 
276
         */
 
277
        for (i = 0; i < RB_SOURCELIST_GROUP_LAST-1; i++) {
 
278
                group_path = rb_sourcelist_model_get_group_path (model, i);
 
279
 
 
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.
 
284
                         */
 
285
                        gboolean separator = FALSE;
 
286
 
 
287
                        gtk_tree_path_next (path);
 
288
 
 
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);
 
292
 
 
293
                        gtk_tree_path_free (group_path);
 
294
                        gtk_tree_path_free (path);
 
295
                        return separator;
 
296
                }
 
297
                gtk_tree_path_free (group_path);
 
298
        }
 
299
 
 
300
        gtk_tree_path_free (path);
 
301
 
 
302
        return FALSE;
 
303
}
 
304
 
 
305
static gboolean
 
306
rb_sourcelist_model_is_row_visible (GtkTreeModel *model,
 
307
                                    GtkTreeIter *iter,
 
308
                                    RBSourceListModel *sourcelist)
 
309
{
 
310
        RBSource *source;
 
311
 
 
312
        gtk_tree_model_get (GTK_TREE_MODEL (model), iter,
 
313
                            RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
 
314
        
 
315
        if (source != NULL) {
 
316
                gboolean visible;       
 
317
                g_object_get (G_OBJECT (source), "visibility", &visible, NULL);
 
318
 
 
319
                return visible;
 
320
        } else {
 
321
                return real_row_is_separator (sourcelist, iter);
 
322
        }
 
323
}
 
324
 
 
325
gboolean
 
326
rb_sourcelist_model_row_is_separator (GtkTreeModel *model,
 
327
                                      GtkTreeIter *iter,
 
328
                                      RBSourceListModel *sourcelist)
 
329
{
 
330
        GtkTreeIter real_iter;
 
331
        RBSource *source; 
 
332
 
 
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);
 
336
        if (source != NULL)
 
337
                return FALSE;
 
338
 
 
339
        gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (sourcelist), 
 
340
                                                          &real_iter, 
 
341
                                                          iter);
 
342
        return real_row_is_separator (sourcelist, &real_iter);
 
343
}
 
344
 
 
345
 
 
346
static int
 
347
get_group_for_path (RBSourceListModel *model, GtkTreePath *path)
 
348
{
 
349
        GtkTreePath *group_path;
 
350
        gboolean found = FALSE;
 
351
        int i;
 
352
 
 
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);
 
356
 
 
357
                found = (gtk_tree_path_compare (group_path, path) == 1);
 
358
                gtk_tree_path_free (group_path);
 
359
 
 
360
                if (found)
 
361
                        return i;
 
362
        }
 
363
 
 
364
        g_assert_not_reached ();
 
365
}
 
366
 
 
367
static gboolean
237
368
rb_sourcelist_model_drag_data_received (RbTreeDragDest *drag_dest,
238
369
                                        GtkTreePath *dest,
239
370
                                        GtkTreeViewDropPosition pos,
272
403
 
273
404
        if (selection_data->type == gdk_atom_intern ("application/x-rhythmbox-source", TRUE)) {
274
405
                GtkTreePath *path;
 
406
                GtkTreePath *real_dest;
275
407
                char *path_str;
276
408
                GtkTreeIter iter, real_iter;
277
 
                GtkTreeIter dest_iter, real_dest_iter;
 
409
                GtkTreeIter real_dest_iter;
278
410
                GtkTreeModel *real_model;
 
411
                RBSource *source;
 
412
                RBSourceListGroup group;
 
413
                int dest_group;
279
414
 
280
415
                if (!dest)
281
416
                        return FALSE;
289
424
                                         &iter, path);
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),
293
 
                                             &dest_iter, dest)) {
294
 
                        gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (model),
295
 
                                                                          &real_dest_iter, &dest_iter);
 
427
 
 
428
                real_dest = 
 
429
                        gtk_tree_model_filter_convert_path_to_child_path (GTK_TREE_MODEL_FILTER (model), 
 
430
                                                                          dest);
 
431
 
 
432
                gtk_tree_model_get (GTK_TREE_MODEL (real_model), &real_iter,
 
433
                                    RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, 
 
434
                                    -1);
 
435
                g_object_get (G_OBJECT (source), "sourcelist-group", &group, NULL);
 
436
 
 
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;
 
447
                }
 
448
 
 
449
                if (gtk_tree_model_get_iter (GTK_TREE_MODEL (real_model),
 
450
                                             &real_dest_iter, real_dest)) {
 
451
 
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);
299
455
                        else
300
456
                                gtk_tree_store_move_before (GTK_TREE_STORE (real_model),
301
457
                                                            &real_iter, &real_dest_iter);
302
 
                } else
 
458
 
 
459
                } else {
303
460
                        gtk_tree_store_move_before (GTK_TREE_STORE (real_model),
304
461
                                                    &real_iter, NULL);
 
462
                }
 
463
 
 
464
                gtk_tree_path_free (real_dest);
 
465
                gtk_tree_path_free (path);
305
466
                g_free (path_str);
306
467
        }
307
468
 
344
505
                gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
345
506
                                    RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
346
507
                
347
 
                return rb_source_can_cut (source);
348
 
 
 
508
                if (source)
 
509
                        return rb_source_can_paste (source);
349
510
        }
350
511
        return FALSE;
351
512
}
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);
362
 
 
363
 
                /* currently, only playlists are reorderable; if this gets more
364
 
                 * complex, we should add 'rb_source_can_reorder' (or similar)
365
 
                 * to figure it out.
366
 
                 */
367
 
                return RB_IS_PLAYLIST_SOURCE (source);
 
524
                if (source == NULL)
 
525
                        return FALSE;
 
526
 
 
527
                g_object_get (G_OBJECT (source), "sourcelist-group", &group, NULL);
 
528
 
 
529
                /* fixed and transient sources are not reorderable, everything else is */
 
530
                return (group != RB_SOURCELIST_GROUP_FIXED &&
 
531
                        group != RB_SOURCELIST_GROUP_TRANSIENT);
368
532
        }
369
533
        return FALSE;
370
534
}
459
623
 
460
624
        if (gtk_tree_model_get_iter (model, &iter, path)) {
461
625
                RBSource *source;
 
626
                RBSourceListGroup group;
462
627
 
463
628
                gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
464
629
                                    RB_SOURCELIST_MODEL_COLUMN_SOURCE, &source, -1);
 
630
        
 
631
                g_object_get (G_OBJECT (source), "sourcelist-group", &group, NULL);
465
632
 
466
 
                return rb_source_can_rename (source);
 
633
                return (group != RB_SOURCELIST_GROUP_FIXED &&
 
634
                        group != RB_SOURCELIST_GROUP_TRANSIENT);
467
635
        }
468
636
                
469
637
        return FALSE;
524
692
                        }
525
693
 
526
694
                        entry = rhythmdb_query_model_iter_to_entry (query_model, &iter);
527
 
                        g_string_append (data, entry->location);
 
695
                        g_string_append (data, rhythmdb_entry_get_string (entry, RHYTHMDB_PROP_LOCATION));
528
696
 
529
697
                } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (query_model), &iter));
530
698
                g_object_unref (G_OBJECT (query_model));
549
717
{
550
718
        return TRUE;
551
719
}
 
720
 
 
721
static void 
 
722
rb_sourcelist_model_row_inserted_cb (GtkTreeModel *model, 
 
723
                                     GtkTreePath *path, 
 
724
                                     GtkTreeIter *iter, 
 
725
                                     RBSourceListModel *sourcelist)
 
726
{
 
727
        gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (sourcelist));
 
728
}
 
729
 
 
730
static void 
 
731
rb_sourcelist_model_row_deleted_cb (GtkTreeModel *model,
 
732
                                    GtkTreePath *path,
 
733
                                    RBSourceListModel *sourcelist)
 
734
{
 
735
        gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (sourcelist));
 
736
}
 
737
 
 
738
GtkTreePath *
 
739
rb_sourcelist_model_get_group_path (RBSourceListModel *sourcelist, 
 
740
                                    RBSourceListGroup group)
 
741
{
 
742
        return gtk_tree_row_reference_get_path (sourcelist->priv->groups[group]);
 
743
}
 
744