/* 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; class CatalogPlugin : Plugin { List sources; private CatalogSqlite sqlite; private Gtk.Dialog dialog; public override void hello (Gtk.Window window, Osso.Context context) { string data_dir = Path.build_filename (Environment.get_user_data_dir(), "cinaest"); string filename = Path.build_filename (data_dir, "catalog.db"); // Make sure the data directory is available DirUtils.create_with_parents (data_dir, 0770); string hidden_sources = null; try { var config_file = Path.build_filename (Environment.get_user_config_dir (), "cinaest", "cinaest.cfg"); var keyfile = new KeyFile (); if (keyfile.load_from_file (config_file, KeyFileFlags.NONE) && keyfile.has_group ("CatalogPlugin")) { if (keyfile.has_key ("CatalogPlugin", "HiddenSources")) { hidden_sources = keyfile.get_string ("CatalogPlugin", "HiddenSources"); } } } catch (Error e) { if (!(e is KeyFileError.NOT_FOUND)) stdout.printf ("Error loading configuration: %s\n", e.message); } sqlite = new CatalogSqlite (filename); sources = new List (); var source = new CatalogSource ("Collection", _("Collection"), _("Personal movie list"), sqlite, !("Collection" in hidden_sources)); sources.append (source); source = new CatalogSource ("Loaned", _("Loaned movies"), _("Movies loaned to friends"), sqlite, !("Loaned" in hidden_sources)); sources.append (source); source = new WatchedSource (sqlite, !("Watched" in hidden_sources)); sources.append (source); source = new CatalogSource ("Watchlist", _("Watchlist"), _("Movies of interest"), sqlite, !("Watchlist" in hidden_sources)); sources.append (source); stdout.printf ("Catalog Plugin Loaded.\n"); } public override unowned List get_sources () { return (List) sources; } public override List get_actions (Movie movie, Gtk.Window window) { var list = new List (); list.append (new MovieAction (_("Add to catalog"), on_add_to_catalog, movie, window)); return list; } private void on_add_to_catalog (Movie movie, Gtk.Window window) { dialog = new Gtk.Dialog (); dialog.set_transient_for (window); dialog.set_title (_("Add movie to catalog - Select list")); int i = 0; var available_sources = new List (); foreach (CatalogSource s in sources) { if (!s.contains (movie) && s.table != "Watched") { available_sources.append ((MovieSource) s); i++; } } var source_list = new SourceListView (available_sources, true, window); var content = (VBox) dialog.get_content_area (); content.pack_start (source_list, true, true, 0); if (i > 5) i = 5; content.set_size_request (-1, i*70); // Connect signals source_list.source_activated.connect (on_source_activated); dialog.show_all (); int res = dialog.run (); if (res >= 0) { var source = sources.nth_data (res); if (source.table == "Loaned") { var dialog = new Gtk.Dialog (); dialog.set_title (_("Add to loaned movies")); var contact = new Hildon.Entry (SizeType.FINGER_HEIGHT); contact.set_placeholder ("Contact"); var date = new Hildon.DateButton (SizeType.FINGER_HEIGHT, ButtonArrangement.VERTICAL); date.set_title (_("Loaned on")); date.set_alignment (0.0f, 0.5f, 1.0f, 1.0f); content = (Gtk.VBox) dialog.get_content_area (); content.pack_start (contact, true, false, 0); content.pack_start (date, true, false, 0); dialog.add_button (_("Done"), Gtk.ResponseType.OK); dialog.show_all (); res = dialog.run (); dialog.destroy (); if (res == Gtk.ResponseType.OK) { source.add_movie (movie); var banner = (Banner) Banner.show_information_with_markup (window, null, _("'%s' added to list of loaned movies").printf (movie.title, source.get_name ())); banner.set_timeout (1500); } } else { source.add_movie (movie); var banner = (Banner) Banner.show_information_with_markup (window, null, _("'%s' added to list '%s'").printf (movie.title, source.get_name ())); banner.set_timeout (1500); } } dialog.destroy (); dialog = null; } private void on_source_activated (MovieSource source) { int n = sources.index ((CatalogSource) source); dialog.response (n); } public override void settings_dialog (Gtk.Window window) { var dialog = new Gtk.Dialog (); dialog.set_transient_for (window); dialog.set_title (_("Catalog plugin settings")); var button = new Hildon.Button (SizeType.FINGER_HEIGHT, ButtonArrangement.VERTICAL); button.set_title (_("Select active movie lists")); button.set_value (active_sources_text ()); button.set_style (ButtonStyle.PICKER); var content = (VBox) dialog.get_content_area (); content.pack_start (button, true, true, 0); dialog.add_button (_("Done"), ResponseType.ACCEPT); // Connect signals button.clicked.connect (() => { on_select_active_lists (button, window); }); dialog.show_all (); int res = dialog.run (); if (res == ResponseType.ACCEPT) { } dialog.destroy (); } private void on_select_active_lists (Hildon.Button button, Gtk.Window window) { dialog = new Gtk.Dialog (); dialog.set_transient_for (window); dialog.set_title (_("Select active movie lists")); var source_list = new SourceListView (sources, false, window); source_list.set_hildon_ui_mode (UIMode.EDIT); var selection = source_list.get_selection (); foreach (CatalogSource s in sources) { var iter = TreeIter (); if (s.active && source_list.get_iter (s, out iter)) { selection.select_iter (iter); } } var content = (VBox) dialog.get_content_area (); content.pack_start (source_list, true, true, 0); var i = sources.length (); if (i > 5) i = 5; content.set_size_request (-1, (int) i*70); dialog.add_button (_("Done"), ResponseType.ACCEPT); dialog.show_all (); int res = dialog.run (); if (res == ResponseType.ACCEPT) { foreach (CatalogSource s in sources) { TreeIter iter; if (source_list.get_iter (s, out iter)) { s.active = selection.iter_is_selected (iter); } } var config_file = Path.build_filename (Environment.get_user_config_dir (), "cinaest", "cinaest.cfg"); var keyfile = new KeyFile (); try { keyfile.load_from_file (config_file, KeyFileFlags.NONE); } catch (Error e) { if (!(e is KeyFileError.NOT_FOUND)) stdout.printf ("Error loading configuration: %s\n", e.message); } keyfile.set_string ("CatalogPlugin", "HiddenSources", hidden_sources_list ()); try { var file = File.new_for_path (config_file + ".part"); var stream = file.create (FileCreateFlags.REPLACE_DESTINATION, null); var data = keyfile.to_data (); stream.write (data, data.length, null); FileUtils.rename (config_file + ".part", config_file); } catch (Error e) { stdout.printf ("Failed to store configuration: %s\n", e.message); } button.set_value (active_sources_text ()); } dialog.destroy (); dialog = null; } private string active_sources_text () { string text = null; foreach (CatalogSource s in sources) { if (s.active) { if (text == null) { text = s.get_name (); } else { text += ", " + s.get_name (); } } } return text; } private string hidden_sources_list () { string list = ""; foreach (CatalogSource s in sources) { if (!s.active) { if (list == "") { list = s.table; } else { list += ", " + s.table; } } } return list; } public override unowned string get_name () { return _("Catalog"); } } class CatalogSource : MovieSource { internal string table; internal string name; internal string description; internal CatalogSqlite sqlite; public CatalogSource (string _table, string _name, string _description, CatalogSqlite _sqlite, bool _active) { GLib.Object (active: _active); table = _table; name = _name; description = _description; sqlite = _sqlite; } public override bool active { get; set construct; } 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) { sqlite.add_movie (table, movie); } public override void delete_movie (Movie movie) { sqlite.delete_movie (table, movie); } internal bool contains (Movie movie) { return sqlite.contains (table, movie); } public override unowned string get_name () { return name; } public override unowned string get_description () { return description; } public override SourceFlags get_flags () { return SourceFlags.EDITABLE; } } class WatchedSource : CatalogSource { public WatchedSource (CatalogSqlite _sqlite, bool _active) { GLib.Object (active: _active); table = "Watched"; name = _("Watched movies"); description = _("Watched / rated movies"); sqlite = _sqlite; } 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 SourceFlags get_flags () { return SourceFlags.EDITABLE | SourceFlags.RATING; } } [ModuleInit] public Type register_plugin (TypeModule module) { // types are registered automatically return typeof (CatalogPlugin); }