Lift list view: add sorting by time or price
[beifahrer] / src / lift-list-window.vala
1 /* This file is part of Beifahrer.
2  *
3  * Copyright (C) 2010 Philipp Zabel
4  *
5  * Beifahrer 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.
9  *
10  * Beifahrer 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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Beifahrer. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using Gtk;
20 using Hildon;
21
22 public class LiftListWindow : StackableWindow {
23         public const string GCONF_KEY_PRELOAD = "/apps/beifahrer/preload";
24
25         AdacMitfahrclub adac;
26         ListStore store;
27         TreeSortable sortable;
28         Alignment alignment;
29         TreeView tree;
30         TreeViewColumn route_column;
31         Label no_lifts;
32         GConf.Client gconf;
33         bool preload = false;
34         string url;
35
36         Gtk.Button goto_website;
37
38         public LiftListWindow (AdacMitfahrclub _adac) {
39                 adac = _adac;
40         }
41
42         construct {
43                 set_title ("Beifahrer");
44
45                 var menu = new AppMenu ();
46                 var sort_by_time = new RadioButton.with_label (null, _("Time"));
47                 sort_by_time.set_mode (false);
48                 sort_by_time.show ();
49                 var sort_by_price = new RadioButton.with_label_from_widget (sort_by_time, _("Price"));
50                 sort_by_price.set_mode (false);
51                 sort_by_price.show ();
52                 menu.add_filter (sort_by_time);
53                 menu.add_filter (sort_by_price);
54                 goto_website = new Gtk.Button.with_label (_("Show website"));
55                 menu.append (goto_website);
56                 set_main_menu (menu);
57
58                 gconf = GConf.Client.get_default ();
59                 store = new ListStore (6, typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (Lift));
60                 sortable = new TreeModelSort.with_model (store);
61
62                 alignment = new Alignment (0.0f, 0.0f, 1.0f, 1.0f);
63                 alignment.top_padding = MARGIN_HALF;
64                 alignment.left_padding = MARGIN_DOUBLE;
65                 alignment.right_padding = MARGIN_DOUBLE;
66
67                 tree = (TreeView) Hildon.gtk_tree_view_new_with_model (UIMode.NORMAL, sortable);
68                 Hildon.gtk_widget_set_theme_size (tree, SizeType.FINGER_HEIGHT);
69
70                 tree.set_headers_visible (false);
71                 tree.set_rules_hint (true);
72
73                 // Tree selection object
74                 var selection = tree.get_selection ();
75                 selection.set_mode (SelectionMode.SINGLE);
76
77                 // Source and destination column
78                 route_column = new TreeViewColumn.with_attributes ("Route", new CellRendererText (), "markup", 0);
79                 route_column.set_reorderable (false);
80                 route_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
81                 route_column.set_expand (true);
82                 tree.append_column (route_column);
83
84                 // Date and time column
85                 var datetime_column = new TreeViewColumn.with_attributes ("DateTime", new CellRendererText (), "text", 1);
86                 datetime_column.set_reorderable (false);
87                 datetime_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
88                 datetime_column.set_expand (true);
89                 tree.append_column (datetime_column);
90
91                 // Free places column
92                 var places_column = new TreeViewColumn.with_attributes ("Places", new CellRendererText (), "text", 2);
93                 places_column.set_reorderable (false);
94                 places_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
95                 places_column.set_expand (true);
96                 tree.append_column (places_column);
97
98                 // Price column
99                 var price_column = new TreeViewColumn.with_attributes ("Price", new CellRendererText (), "text", 3);
100                 price_column.set_reorderable (false);
101                 price_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
102                 price_column.set_expand (true);
103                 tree.append_column (price_column);
104
105                 // Smoker/Non-smoker column
106                 var smoke_column = new TreeViewColumn.with_attributes ("Smoker", new CellRendererPixbuf (), "icon-name", 4);
107                 smoke_column.set_reorderable (false);
108                 smoke_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
109                 smoke_column.set_expand (false);
110                 tree.append_column (smoke_column);
111
112                 var pannable = new PannableArea ();
113                 pannable.add (tree);
114
115                 no_lifts = new Label (_("No lifts"));
116                 Hildon.helper_set_logical_font (no_lifts, "LargeSystemFont");
117                 Hildon.helper_set_logical_color (no_lifts, RcFlags.FG, StateType.NORMAL, "SecondaryTextColor");
118                 no_lifts.set_size_request (-1, 6 * 70);
119                 no_lifts.set_alignment ((float) 0.5, (float) 0.42);
120
121                 var vbox = new VBox (false, 0);
122                 vbox.pack_start (pannable, true, true, 0);
123                 vbox.pack_start (no_lifts, false, false, 0);
124
125                 alignment.add (vbox);
126                 add (alignment);
127
128                 alignment.show_all ();
129                 no_lifts.hide ();
130                 route_column.set_visible (!BeifahrerProgram.orientation.portrait);
131
132                 tree.row_activated.connect (this.on_row_activated);
133                 Gdk.Screen.get_default ().size_changed.connect (this.on_orientation_changed);
134                 goto_website.clicked.connect (on_goto_website_clicked);
135                 sort_by_time.toggled.connect (button => {
136                         if (button.get_active ())
137                                 sortable.set_sort_column_id (1, Gtk.SortType.ASCENDING);
138                 });
139                 sort_by_price.toggled.connect (button => {
140                         if (button.get_active ())
141                                 sortable.set_sort_column_id (3, Gtk.SortType.ASCENDING);
142                 });
143         }
144
145         public async void find_lifts (string city_from, int radius_from, string city_to, int radius_to, Date date, int tolerance = 0) {
146                 TreeIter iter;
147                 set_title ("%s - %s".printf (city_from, city_to));
148                 Hildon.gtk_window_set_progress_indicator (this, 1);
149
150                 url = adac.get_lift_list_url (city_from, radius_from, city_to, radius_to, date, tolerance);
151                 if (url == null)
152                         return;
153                 goto_website.show ();
154                 var lift_list = yield adac.get_lift_list (city_from, radius_from, city_to, radius_to, date, tolerance);
155                 foreach (Lift lift in lift_list) {
156                         string icon_name = null;
157                         if (LiftFlags.SMOKER in lift.flags)
158                                 icon_name = "beifahrer_smoker";
159                         else if (LiftFlags.NON_SMOKER in lift.flags)
160                                 icon_name = "beifahrer_non_smoker";
161                         string datetime = "%02d.%02d.%04d".printf (lift.time.day, lift.time.month, lift.time.year);
162                         if (lift.time.hour >= 0)
163                                 datetime += ", %d:%02d".printf (lift.time.hour, lift.time.minute);
164                         store.insert_with_values (out iter, -1, 0, lift.city_from + " - " + lift.city_to,
165                                                                 1, datetime,
166                                                                 2, _("%d pl.").printf (lift.places),
167                                                                 3, lift.price,
168                                                                 4, icon_name,
169                                                                 5, lift);
170                         // (LiftFlags.WOMEN_ONLY,ADAC_MEMBER in lift.flags)
171                 }
172                 if (lift_list.length () > 6)
173                         alignment.right_padding = MARGIN_DEFAULT;
174                 if (lift_list.length () == 0)
175                         no_lifts.show ();
176
177                 bool preload = false;
178                 try {
179                         preload = gconf.get_bool (GCONF_KEY_PRELOAD);
180                 } catch (Error e) {
181                 }
182                 if (preload) {
183                         if (store.get_iter_first (out iter)) do {
184                                 Lift lift2;
185                                 store.@get (iter, 5, out lift2);
186                                 if (lift2 == null)
187                                         continue;
188                                 if (lift2.description == null) {
189                                         yield adac.update_lift_details (lift2);
190                                         store.@set (iter, 0, lift2.city_from + " - " + lift2.city_to + "\n<small>" + lift2.name + "</small>");
191                                 }
192                         } while (store.iter_next (ref iter));
193                 }
194
195                 Hildon.gtk_window_set_progress_indicator (this, 0);
196         }
197
198         void on_goto_website_clicked () {
199                 BeifahrerProgram.open_browser (this, url);
200         }
201
202         private void on_row_activated (TreeView tree, TreePath /*_*/path, TreeViewColumn column) {
203                 TreeModel model = tree.model;
204                 TreeIter iter;
205                 Lift lift;
206
207                 if (model.get_iter (out iter, path)) {
208                         model.get (iter, 5, out lift);
209
210                         var window = new LiftDetailWindow (adac, lift);
211                         window.show ();
212                 }
213         }
214
215         private void on_orientation_changed (Gdk.Screen screen) {
216                 route_column.set_visible (!BeifahrerProgram.orientation.portrait);
217         }
218 }