Movie list, plugins: detect if there are more results than the limit
authorPhilipp Zabel <philipp.zabel@gmail.com>
Wed, 25 Nov 2009 16:12:28 +0000 (17:12 +0100)
committerPhilipp Zabel <philipp.zabel@gmail.com>
Sat, 9 Jan 2010 13:14:47 +0000 (14:14 +0100)
Increase the internal SQL limit in the IMDb plugin to limit+1 and let
the SQL query return the number of results - this way we can detect if
there are more results than the limit and show a notice to the user.

src/imdb/imdb-sqlite.vala
src/movie-list-store.vala
src/movie-list-window.vala
src/plugin-interface.vala
src/plugins/catalog-plugin.vala
src/plugins/google-parser.vala
src/plugins/google-plugin.vala
src/plugins/imdb-plugin.vala

index 7371725..5cf2154 100644 (file)
@@ -271,7 +271,7 @@ class IMDbSqlite : Object {
                if (filter.genres.field != 0) {
                        sql += sep + "Genres&%d = %d".printf (filter.genres.field, filter.genres.field);
                }
-               sql += " ORDER BY Votes DESC LIMIT %d;".printf (limit);
+               sql += " ORDER BY Votes DESC LIMIT %d;".printf (limit + 1);
 
                stdout.printf("SQL: \"%s\"\n", sql);
 
@@ -279,10 +279,13 @@ class IMDbSqlite : Object {
                if (rc != Sqlite.OK) {
                        stderr.printf ("SQL error: %d, %s\n", rc, db.errmsg ());
                        db.progress_handler (0, null);
-                       return 1;
+                       return 0;
                }
 
+               int n = 0;
                do {
+                       if (++n > limit)
+                               break;
                        Idle.add (query.callback);
                        yield;
                        rc = stmt.step ();
@@ -302,7 +305,7 @@ class IMDbSqlite : Object {
                } while (rc == Sqlite.ROW);
 
                db.progress_handler (0, null);
-               return 0;
+               return n;
        }
 
        private string movie_aka (string title, string match) {
index f9a78ad..b77c138 100644 (file)
@@ -44,6 +44,8 @@ public class MovieListStore : ListStore, TreeModel {
        public bool update_running { get; set; }
        private Cancellable cancellable;
 
+       public signal void search_finished (int movies);
+
        construct {
                set_column_types (base_type);
                no_poster = null;
@@ -130,9 +132,11 @@ public class MovieListStore : ListStore, TreeModel {
 
                clear ();
 
-               if (source != null)
+               if (source != null) {
                        // FIXME - arbitrary limit
-                       yield source.get_movies (filter, receive_movie, 100, cancellable);
+                       int n = yield source.get_movies (filter, receive_movie, 100, cancellable);
+                       search_finished (n);
+               }
 
                update_running = false;
                if (cancellable.is_cancelled ()) {
index 1bcc7ec..aeb1081 100644 (file)
@@ -85,6 +85,7 @@ public class MovieListWindow : StackableWindow {
                close_button.clicked.connect (on_close_button_clicked);
                key_press_event.connect (on_key_press_event);
                movie_list.movie_activated.connect (on_movie_activated);
+               store.search_finished.connect (on_search_finished);
 
                store.notify["update-running"].connect (on_update_running_changed);
 
@@ -205,6 +206,12 @@ public class MovieListWindow : StackableWindow {
                return false;
        }
 
+       private void on_search_finished (int movies) {
+               if (movies > 100) {
+                       Banner.show_information (this, null, _("More results available - refine search to reduce the dataset"));
+               }
+       }
+
        private void on_movie_activated (Movie movie) {
                var window = new MovieWindow.with_movie (movie, store);
 
index 631e6ee..cac2937 100644 (file)
@@ -32,7 +32,7 @@ public abstract class MovieSource : Object {
 
        public delegate void ReceiveMovieFunction (Movie movie);
 
-       public abstract async void get_movies (MovieFilter filter, ReceiveMovieFunction callback, int limit, GLib.Cancellable? cancellable);
+       public abstract async int get_movies (MovieFilter filter, ReceiveMovieFunction callback, int limit, GLib.Cancellable? cancellable);
 
        public abstract void add_movie (Movie movie);
        public abstract void delete_movie (Movie movie);
index 38958f3..550a810 100644 (file)
@@ -257,8 +257,9 @@ class CatalogSource : MovieSource {
 
        public override bool active { get; set construct; }
 
-       public override async void get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
-               yield sqlite.query (table, filter, callback, limit, cancellable);
+       public override async int get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
+               int n = yield sqlite.query (table, filter, callback, limit, cancellable);
+               return n;
        }
 
        public override void add_movie (Movie movie) {
index fa71710..3eb638f 100644 (file)
@@ -288,7 +288,9 @@ public class GoogleParser : Object {
                last_cinema.phone = phone;
        }
 
-       public void parse (ref char[] buf) throws Error {
+       public int parse (ref char[] buf) throws Error {
+               int movies = 0;
+
                current = buf;
                next_tag ();
                while (location == null && current[0] != 0) {
@@ -311,6 +313,7 @@ public class GoogleParser : Object {
                        while (current[i++] != '>');
                        if (((string) current).has_prefix ("<div class=movie>")) {
                                parse_movie ();
+                               movies++;
                        } else if (((string) current).has_prefix("<div class=theater>")) {
                                parse_cinema ();
                        } else {
@@ -318,9 +321,11 @@ public class GoogleParser : Object {
                        }
                        next_tag ();
                }
+
+               return movies;
        }
 
-       public async void query (MovieFilter filter, string? location, MovieSource.ReceiveMovieFunction callback, Cancellable? cancellable) {
+       public async int query (MovieFilter filter, string? location, MovieSource.ReceiveMovieFunction callback, Cancellable? cancellable) {
                _get_callback = callback;
                _filter = filter;
                if (filter.title.chr(filter.title.length, '*') != null) {
@@ -346,14 +351,16 @@ public class GoogleParser : Object {
                                nread = yield stream.read_async ((char *)buf + total, 256*1024 - total, Priority.DEFAULT_IDLE, cancellable);
                                total += nread;
                                if (cancellable.is_cancelled ())
-                                       return;
+                                       return 0;
                                if (nread == 0)
                                        break;
                        }
                        buf[total] = 0;
-                       parse (ref buf);
+                       return parse (ref buf);
                } catch (Error e) {
                        stderr.printf ("Error: %s\n", e.message);
                }
+
+               return 0;
        }
 }
index 060dd1b..b37a36e 100644 (file)
@@ -228,13 +228,15 @@ class GoogleSource : MovieSource {
                GLib.Object (active: true);
        }
 
-       public override async void get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
+       public override async int get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
                var parser = new GoogleParser ();
 
-               yield parser.query (filter, location, callback, cancellable);
+               int n = yield parser.query (filter, location, callback, cancellable);
                if (location == null) {
                        location = parser.location;
                }
+
+               return n;
        }
 
        public override void add_movie (Movie movie) {
index e60e6c3..298cb54 100644 (file)
@@ -163,7 +163,7 @@ class IMDBSource : MovieSource {
        }
 
        MovieSource.ReceiveMovieFunction _get_callback;
-       public override async void get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
+       public override async int get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
                // IMDb has too many movies
                if (filter.title == "" && filter.year_min == 0 && filter.year_max == 0 && filter.genres.field == 0 && filter.rating_min == 0)
                        return;
@@ -171,7 +171,8 @@ class IMDBSource : MovieSource {
                                             "cinaest", "imdb.db", null));
 
                _get_callback = callback;
-               yield sqlite.query (filter, receive_movie, limit, cancellable);
+               int n = yield sqlite.query (filter, receive_movie, limit, cancellable);
+               return n;
        }
 
        private void receive_movie (string title, string? aka, int year, int rating, int genres) {