1 /* This file is part of Cinaest.
3 * Copyright (C) 2009 Philipp Zabel
5 * Cinaest is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * Cinaest is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Cinaest. If not, see <http://www.gnu.org/licenses/>.
22 class CatalogPlugin : Plugin {
23 List<CatalogSource> sources;
24 private CatalogSqlite sqlite;
25 private Gtk.Dialog dialog;
27 public override void hello (Gtk.Window window, Osso.Context context) {
28 string data_dir = Path.build_filename (Environment.get_user_data_dir(), "cinaest");
29 string filename = Path.build_filename (data_dir, "catalog.db");
31 // Make sure the data directory is available
32 DirUtils.create_with_parents (data_dir, 0770);
34 string hidden_sources = null;
36 var config_file = Path.build_filename (Environment.get_user_config_dir (), "cinaest", "cinaest.cfg");
37 var keyfile = new KeyFile ();
38 if (keyfile.load_from_file (config_file, KeyFileFlags.NONE)
39 && keyfile.has_group ("CatalogPlugin")) {
40 if (keyfile.has_key ("CatalogPlugin", "HiddenSources")) {
41 hidden_sources = keyfile.get_string ("CatalogPlugin", "HiddenSources");
45 if (!(e is KeyFileError.NOT_FOUND))
46 stdout.printf ("Error loading configuration: %s\n", e.message);
49 sqlite = new CatalogSqlite (filename);
50 sources = new List<CatalogSource> ();
52 var source = new CatalogSource ("Collection", _("Collection"), _("Personal movie list"), sqlite, !("Collection" in hidden_sources));
53 sources.append (source);
55 source = new CatalogSource ("Loaned", _("Loaned movies"), _("Movies loaned to friends"), sqlite, !("Loaned" in hidden_sources));
56 sources.append (source);
58 source = new CatalogSource ("Watched", _("Watched movies"), _("Watched / rated movies"), sqlite, !("Watched" in hidden_sources));
59 sources.append (source);
61 source = new CatalogSource ("Watchlist", _("Watchlist"), _("Movies of interest"), sqlite, !("Watchlist" in hidden_sources));
62 sources.append (source);
64 stdout.printf ("Catalog Plugin Loaded.\n");
67 public override unowned List<MovieSource> get_sources () {
68 return (List<MovieSource>) sources;
71 public override List<MovieAction> get_actions (Movie movie, Gtk.Window window) {
72 var list = new List<MovieAction> ();
74 list.append (new MovieAction (_("Add to catalog"), on_add_to_catalog, movie, window));
79 private void on_add_to_catalog (Movie movie, Gtk.Window window) {
80 dialog = new Gtk.Dialog ();
81 dialog.set_transient_for (window);
82 dialog.set_title (_("Add movie to catalog - Select list"));
85 var available_sources = new List<MovieSource> ();
86 foreach (CatalogSource s in sources) {
87 if (!s.contains (movie)) {
88 available_sources.append ((MovieSource) s);
93 var source_list = new SourceListView (available_sources, true, window);
95 var content = (VBox) dialog.get_content_area ();
96 content.pack_start (source_list, true, true, 0);
99 content.set_size_request (-1, i*70);
102 source_list.source_activated.connect (on_source_activated);
105 int res = dialog.run ();
107 var source = sources.nth_data (res);
109 if (source.table == "Loaned") {
110 var dialog = new Gtk.Dialog ();
111 dialog.set_title (_("Add to loaned movies"));
113 var contact = new Hildon.Entry (SizeType.FINGER_HEIGHT);
114 contact.set_placeholder ("Contact");
115 var date = new Hildon.DateButton (SizeType.FINGER_HEIGHT, ButtonArrangement.VERTICAL);
116 date.set_title (_("Loaned on"));
117 date.set_alignment (0.0f, 0.5f, 1.0f, 1.0f);
119 content = (Gtk.VBox) dialog.get_content_area ();
120 content.pack_start (contact, true, false, 0);
121 content.pack_start (date, true, false, 0);
123 dialog.add_button (_("Done"), Gtk.ResponseType.OK);
127 if (res == Gtk.ResponseType.OK) {
128 source.add_movie (movie);
130 var banner = (Banner) Banner.show_information_with_markup (window, null, _("'%s' added to list of loaned movies").printf (movie.title, source.get_name ()));
131 banner.set_timeout (1500);
133 } else if (source.table == "Watched") {
134 var dialog = new Gtk.Dialog ();
135 dialog.set_title (_("Add to watched movies"));
137 var rating = new RatingWidget ();
138 var date = new Hildon.DateButton (SizeType.FINGER_HEIGHT, ButtonArrangement.VERTICAL);
139 date.set_title (_("Watched on"));
140 date.set_alignment (0.0f, 0.5f, 1.0f, 1.0f);
142 content = (Gtk.VBox) dialog.get_content_area ();
143 content.pack_start (rating, true, false, 0);
144 content.pack_start (date, true, false, 0);
146 dialog.add_button (_("Done"), Gtk.ResponseType.OK);
150 if (res == Gtk.ResponseType.OK) {
151 if (rating.get_rating () > 0)
152 movie.rating = 10 * rating.get_rating ();
153 source.add_movie (movie);
155 var banner = (Banner) Banner.show_information_with_markup (window, null, _("'%s' added to list of watched movies").printf (movie.title, source.get_name ()));
156 banner.set_timeout (1500);
159 source.add_movie (movie);
161 var banner = (Banner) Banner.show_information_with_markup (window, null, _("'%s' added to list '%s'").printf (movie.title, source.get_name ()));
162 banner.set_timeout (1500);
169 private void on_source_activated (MovieSource source) {
170 int n = sources.index ((CatalogSource) source);
175 public override void settings_dialog (Gtk.Window window) {
176 var dialog = new Gtk.Dialog ();
177 dialog.set_transient_for (window);
178 dialog.set_title (_("Catalog plugin settings"));
180 var button = new Hildon.Button (SizeType.FINGER_HEIGHT, ButtonArrangement.VERTICAL);
181 button.set_title (_("Select active movie lists"));
182 button.set_value (active_sources_text ());
183 button.set_style (ButtonStyle.PICKER);
185 var content = (VBox) dialog.get_content_area ();
186 content.pack_start (button, true, true, 0);
188 dialog.add_button (_("Done"), ResponseType.ACCEPT);
191 button.clicked.connect (() => { on_select_active_lists (button, window); });
194 int res = dialog.run ();
195 if (res == ResponseType.ACCEPT) {
200 private void on_select_active_lists (Hildon.Button button, Gtk.Window window) {
201 dialog = new Gtk.Dialog ();
202 dialog.set_transient_for (window);
203 dialog.set_title (_("Select active movie lists"));
205 var source_list = new SourceListView (sources, false, window);
206 source_list.set_hildon_ui_mode (UIMode.EDIT);
208 var selection = source_list.get_selection ();
209 foreach (CatalogSource s in sources) {
210 var iter = TreeIter ();
212 if (s.active && source_list.get_iter (s, out iter)) {
213 selection.select_iter (iter);
217 var content = (VBox) dialog.get_content_area ();
218 content.pack_start (source_list, true, true, 0);
219 var i = sources.length ();
222 content.set_size_request (-1, (int) i*70);
224 dialog.add_button (_("Done"), ResponseType.ACCEPT);
227 int res = dialog.run ();
228 if (res == ResponseType.ACCEPT) {
229 foreach (CatalogSource s in sources) {
232 if (source_list.get_iter (s, out iter)) {
233 s.active = selection.iter_is_selected (iter);
237 var config_file = Path.build_filename (Environment.get_user_config_dir (), "cinaest", "cinaest.cfg");
238 var keyfile = new KeyFile ();
240 keyfile.load_from_file (config_file, KeyFileFlags.NONE);
242 if (!(e is KeyFileError.NOT_FOUND))
243 stdout.printf ("Error loading configuration: %s\n", e.message);
245 keyfile.set_string ("CatalogPlugin", "HiddenSources", hidden_sources_list ());
248 var file = File.new_for_path (config_file + ".part");
249 var stream = file.create (FileCreateFlags.REPLACE_DESTINATION, null);
250 var data = keyfile.to_data ();
252 stream.write (data, data.length, null);
253 FileUtils.rename (config_file + ".part", config_file);
255 stdout.printf ("Failed to store configuration: %s\n", e.message);
258 button.set_value (active_sources_text ());
264 private string active_sources_text () {
267 foreach (CatalogSource s in sources) {
270 text = s.get_name ();
272 text += ", " + s.get_name ();
279 private string hidden_sources_list () {
282 foreach (CatalogSource s in sources) {
287 list += ", " + s.table;
294 public override unowned string get_name () {
299 class CatalogSource : MovieSource {
300 internal string table;
302 private string description;
303 private CatalogSqlite sqlite;
305 public CatalogSource (string _table, string _name, string _description, CatalogSqlite _sqlite, bool _active) {
306 GLib.Object (active: _active);
309 description = _description;
313 public override bool active { get; set construct; }
315 public override async int get_movies (MovieFilter filter, MovieSource.ReceiveMovieFunction callback, int limit, Cancellable? cancellable) {
316 int n = yield sqlite.query (table, filter, callback, limit, cancellable);
320 public override void add_movie (Movie movie) {
321 sqlite.add_movie (table, movie);
324 public override void delete_movie (Movie movie) {
325 sqlite.delete_movie (table, movie);
328 internal bool contains (Movie movie) {
329 return sqlite.contains (table, movie);
332 public override unowned string get_name () {
336 public override unowned string get_description () {
340 public override SourceFlags get_flags () {
341 return SourceFlags.EDITABLE;
346 public Type register_plugin (TypeModule module) {
347 // types are registered automatically
348 return typeof (CatalogPlugin);