/* 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; using Hildon; public class MovieListWindow : StackableWindow { private MovieListMenu menu; private Hildon.EditToolbar edit_toolbar; private Hildon.Entry search_field; private Toolbar search_bar; private uint source_id; private MovieListView movie_list; private MovieFilter filter; private MovieListStore store; private Label no_movies; private bool search_bar_visible; private MovieWindow movie_window; private Alignment alignment; private int count; private MovieSource source; private bool portrait_mode; private bool auto_open_movie_window; public MovieListWindow (MovieSource source_, string? title = null, int year = 0) { source = source_; set_title (source.get_name ()); auto_open_movie_window = (title != null); // View menu menu = new MovieListMenu (this); menu.source = source; set_main_menu (menu); // Search bar search_field = new Hildon.Entry (SizeType.FINGER_HEIGHT); var search_field_item = new ToolItem (); search_field_item.set_expand (true); search_field_item.add (search_field); var icon_theme = Gtk.IconTheme.get_default (); var pixbuf = icon_theme.load_icon ("general_close", 48, Gtk.IconLookupFlags.NO_SVG); var close_image = new Image.from_pixbuf (pixbuf); var close_button = new ToolButton (close_image, _("Close")); search_bar = new Toolbar (); search_bar.insert (search_field_item, 0); search_bar.insert (close_button, 1); search_bar.show_all (); add_toolbar (search_bar); // Movie list - connected to menu for sorting movie_list = new MovieListView (this, source.get_name () == _("Watched movies")); menu.store = movie_list.store; store = movie_list.store; store.source = source; no_movies = new Label (_("No movies")); Hildon.helper_set_logical_font (no_movies, "LargeSystemFont"); Hildon.helper_set_logical_color (no_movies, RcFlags.FG, StateType.NORMAL, "SecondaryTextColor"); no_movies.set_size_request (-1, 6 * 70); no_movies.set_alignment ((float) 0.5, (float) 0.42); var vbox = new VBox (false, 0); vbox.pack_start (movie_list, true, true, 0); vbox.pack_start (no_movies, false, false, 0); alignment = new Alignment (0.0f, 0.0f, 1.0f, 1.0f); alignment.top_padding = MARGIN_HALF; // Reduced padding in portrait mode to fit 3 posters in width int padding = portrait_mode ? MARGIN_DEFAULT : MARGIN_DOUBLE; alignment.left_padding = padding; alignment.right_padding = padding; alignment.add (vbox); add (alignment); edit_toolbar = new Hildon.EditToolbar.with_text (_("Select movies"), _("Delete")); set_edit_toolbar (edit_toolbar); // Connect signals menu.filter_changed.connect (on_filter_changed); edit_toolbar.button_clicked.connect (on_delete_button_clicked); edit_toolbar.arrow_clicked.connect (leave_edit_mode); search_field.changed.connect (on_search_field_changed); 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.row_deleted.connect (on_row_deleted); store.row_inserted.connect (on_row_inserted); Gdk.Screen.get_default ().size_changed.connect (on_orientation_changed); store.search_finished.connect (on_search_finished); store.notify["update-running"].connect (on_update_running_changed); search_field.set_flags (WidgetFlags.CAN_DEFAULT); search_field.grab_default (); alignment.show_all (); edit_toolbar.hide (); search_bar_visible = false; search_bar.hide (); filter = new MovieFilter (); menu.filter = filter; filter.title = (title != null) ? title : ""; if (year != 0) { filter.year_min = year; filter.year_max = year; } if (SourceFlags.NOEMPTY in source.get_flags ()) { no_movies.hide (); search_bar_visible = true; search_bar.show (); search_field.grab_focus (); return; } if (store.start_search (filter)) { no_movies.hide (); } else { movie_list.hide (); } } private void on_filter_changed () { var markup = new StringBuilder (); if (filter.year_min != 0 || filter.year_max != 0) markup.append (_(" - years")); if (filter.rating_min != 0) markup.append (_(" - rating")); if (filter.genres.field != 0) markup.append (_(" - genres")); if (markup.str.length > 0) { Gdk.Color color; this.ensure_style (); if (this.style.lookup_color ("ActiveTextColor", out color)) { markup.prepend ("".printf (color.to_string ())); markup.append (""); } markup.prepend (source.get_name ()); set_markup (markup.str); } else { set_markup (source.get_name ()); } start_search (); } public void on_delete_movies_clicked () { fullscreen (); edit_toolbar.show (); movie_list.set_hildon_ui_mode (UIMode.EDIT); movie_list.unselect_all (); } private void on_delete_button_clicked () { var movies = movie_list.get_selected_movies (); int count = (int) movies.length (); if (count == 0) { Banner.show_information (this, null, _("No movies selected")); leave_edit_mode (); return; } var dialog = new Note.confirmation (this, ngettext ("Delete %d movie?", "Delete %d movies?", count).printf (count)); var res = dialog.run (); if (res == Gtk.ResponseType.OK) { // Remove selected movies foreach (Movie movie in movies) { store.remove (movie); } // Switch to "No movies" label if the store is emptied TreeIter iter; if (!store.get_iter_first (out iter)) { movie_list.hide (); no_movies.show (); } } dialog.destroy (); leave_edit_mode (); } private void leave_edit_mode () { movie_list.set_hildon_ui_mode (UIMode.NORMAL); edit_toolbar.hide (); unfullscreen (); } private void on_close_button_clicked () { search_field.set_text (""); search_bar_visible = false; search_bar.hide (); } private bool on_key_press_event (Widget widget, Gdk.EventKey event) { if (event.str != "") { if (!search_bar_visible) { search_bar_visible = true; search_bar.show (); } search_field.grab_focus (); } return false; } private void on_search_field_changed () { // With every change we reset the timer to 500ms if (source_id != 0) { Source.remove (source_id); } source_id = Timeout.add (500, start_search); } private bool start_search () { filter.title = search_field.get_text (); if (store.start_search (filter)) { movie_list.show (); no_movies.hide (); } // One-shot only return false; } private void on_orientation_changed (Gdk.Screen screen) { if (CinaestProgram.orientation.portrait == portrait_mode) return; portrait_mode = CinaestProgram.orientation.portrait; // Reduced padding in portrait mode to fit 3 posters in width int padding = portrait_mode ? MARGIN_DEFAULT : MARGIN_DOUBLE; alignment.left_padding = padding; // Make space for the pannable area's scroll position indicator if (count > movies_per_screen ()) padding -= MARGIN_DEFAULT; alignment.right_padding = padding; } private void on_search_finished (int movies) { int padding = portrait_mode ? MARGIN_DEFAULT : MARGIN_DOUBLE; // Make space for the pannable area's scroll position indicator if (count > movies_per_screen ()) padding -= MARGIN_DEFAULT; alignment.right_padding = padding; if (count == 1 && auto_open_movie_window) { TreeIter iter; if (store.get_iter_first (out iter)) { Movie movie; store.get (iter, MovieListStore.Columns.MOVIE, out movie); on_movie_activated (movie); } } } private int movies_per_screen () { if (portrait_mode) { // 3x3 full posters or 10 full list items, // 10 full list items in list mode without search bar return (search_bar_visible || movie_list.poster_mode) ? 9 : 10; } else { if (search_bar_visible) { // 5x1 full posters or 5 list items return 5; } else { // 5x2 posters or 6 list items return movie_list.poster_mode ? 10 : 6; } } } private void on_movie_activated (Movie movie) { if (movie_window != null) return; movie_window = new MovieWindow.with_movie (movie, store); movie_window.destroy.connect (() => { movie_window = null; }); get_stack ().push_1 (movie_window); } private void on_row_deleted (TreePath path) { if (--count == 0) { no_movies.show (); movie_list.hide (); } } private void on_row_inserted (TreePath path, TreeIter iter) { if (count++ == 0) { no_movies.hide (); movie_list.show (); } } private void on_update_running_changed (GLib.Object source, ParamSpec spec) { TreeIter iter; Hildon.gtk_window_set_progress_indicator (this, (int) store.update_running); // Update finished, but store still empty? if (!store.update_running && !store.get_iter_first (out iter)) { movie_list.hide (); no_movies.show (); } } public unowned MovieListView get_movie_list_view () { return movie_list; } }