/* This file is part of Cinaest. * * Copyright (C) 2009 Philipp Zabel * * Cinaest is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Cinaest is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Cinaest. If not, see . */ using Gtk; public class MovieListStore : ListStore, TreeModel { public enum Columns { TITLE, YEAR, RATING, POSTER, MOVIE, N_COLUMNS } private GLib.Type[] types = { typeof (string), typeof (int), typeof (int), typeof (Gdk.Pixbuf), typeof (Movie) }; private GLib.Type[] base_type = { typeof (Movie) }; private Gdk.Pixbuf no_poster; private MoviePoster.Factory poster_factory; public MovieSource source; private MovieFilter filter; public bool update_running { get; set; } private Cancellable cancellable; construct { set_column_types (base_type); no_poster = null; source = null; update_running = false; poster_factory = MoviePoster.Factory.get_instance (); } public void add (Movie movie, out TreeIter iter) { TreeIter iter1; append (out iter1); base.set (iter1, 0, movie); movie.notify.connect (this.on_movie_changed); iter = iter1; } private void on_movie_changed (GLib.Object source, GLib.ParamSpec spec) { var movie = (Movie) source; TreeIter iter; if (get_iter_from_movie (out iter, movie)) { TreePath path = get_path (iter); base.row_changed (path, iter); } } public bool get_iter_from_movie (out TreeIter iter, Movie movie_a) { if (get_iter_first (out iter)) { do { Movie movie_b; get (iter, Columns.MOVIE, out movie_b); if (movie_a == movie_b) return true; } while (iter_next (ref iter)); } return false; } public bool start_search (MovieFilter _filter) { if (update_running) { stdout.printf ("aborting search ...\n"); cancellable.cancel (); poster_factory.clear_queue (); return false; } if (cancellable == null || cancellable.is_cancelled ()) cancellable = new Cancellable (); filter = _filter; stdout.printf ("begin search\n"); search_async.begin (); update_running = true; return true; } // Asynchronous update method private async void search_async () { stdout.printf ("search started: \"%s\"\n", filter.title); clear (); if (source != null) // FIXME - arbitrary limit yield source.get_movies (filter, receive_movie, 100, cancellable); update_running = false; if (cancellable.is_cancelled ()) { stdout.printf ("search aborted, starting new\n"); cancellable.reset (); if (cancellable.is_cancelled ()) { stdout.printf ("OW WEY\n"); } start_search (filter); } else { stdout.printf ("search stopped\n"); } } private void receive_movie (Movie movie) { TreeIter iter; if (cancellable.is_cancelled ()) return; add (movie, out iter); try { poster_factory.queue_thumbnail (movie, 64, 64, false, receive_poster_thumbnail); } catch (Error e) { warning ("Failed to queue poster request: %s\n", e.message); } } private void receive_poster_thumbnail (Gdk.Pixbuf pixbuf, Movie movie) { var poster = new Poster (); poster.thumbnail = pixbuf; movie.poster = poster; } // Implement TreeModel interface public virtual GLib.Type get_column_type (int index_) { return_val_if_fail (index_ >= 0 && index_ < Columns.N_COLUMNS, 0); return types[index_]; } public virtual int get_n_columns () { return Columns.N_COLUMNS; } public virtual void get_value (TreeIter iter, int column, out GLib.Value value) { Movie movie; // FIXME if (no_poster == null) try { no_poster = new Gdk.Pixbuf.from_file ("/usr/share/icons/hicolor/64x64/hildon/general_video.png"); } catch (Error e) { critical ("Missing general_video icon: %s\n", e.message); } return_if_fail (column >= 0 && column < Columns.N_COLUMNS); // Get the Movie from our parent's storage Value val; base.get_value (iter, 0, out val); movie = (Movie) val.get_object (); value.init (get_column_type (column)); switch (column) { case Columns.TITLE: if (movie != null) { value.set_string (movie.title); } else { value.set_string (""); } break; case Columns.YEAR: if (movie != null) { value.set_int (movie.year); } else { value.set_int (-1); } break; case Columns.RATING: if (movie != null) { value.set_int (movie.rating); } else { value.set_int (-1); } break; case Columns.POSTER: if ((movie.poster != null) && (movie.poster.thumbnail != null)) value.set_object (movie.poster.thumbnail); else value.set_object (no_poster); break; case Columns.MOVIE: value.set_object (movie); break; default: assert_not_reached (); } } }