1 /* This file is part of Beifahrer.
3 * Copyright (C) 2010 Philipp Zabel
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.
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.
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/>.
22 public class LiftListWindow : StackableWindow {
23 public const string GCONF_KEY_PRELOAD = "/apps/beifahrer/preload";
37 TreeSortable sortable;
40 TreeViewColumn route_column;
46 Gtk.Button goto_website;
48 public LiftListWindow (AdacMitfahrclub _adac) {
53 set_title ("Beifahrer");
55 var menu = new AppMenu ();
56 var sort_by_time = new RadioButton.with_label (null, _("Time"));
57 sort_by_time.set_mode (false);
59 var sort_by_price = new RadioButton.with_label_from_widget (sort_by_time, _("Price"));
60 sort_by_price.set_mode (false);
61 sort_by_price.show ();
62 menu.add_filter (sort_by_time);
63 menu.add_filter (sort_by_price);
64 goto_website = new Gtk.Button.with_label (_("Show website"));
65 menu.append (goto_website);
68 gconf = GConf.Client.get_default ();
69 store = new ListStore (7, typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (string), typeof (Lift));
70 sortable = new TreeModelSort.with_model (store);
71 sortable.set_sort_func (Columns.DATETIME, datetime_sort_func);
72 sortable.set_sort_func (Columns.PRICE, price_sort_func);
74 alignment = new Alignment (0.0f, 0.0f, 1.0f, 1.0f);
75 alignment.top_padding = MARGIN_HALF;
76 alignment.left_padding = MARGIN_DOUBLE;
77 alignment.right_padding = MARGIN_DOUBLE;
79 tree = (TreeView) Hildon.gtk_tree_view_new_with_model (UIMode.NORMAL, sortable);
80 Hildon.gtk_widget_set_theme_size (tree, SizeType.FINGER_HEIGHT);
82 tree.set_headers_visible (false);
83 tree.set_rules_hint (true);
85 // Tree selection object
86 var selection = tree.get_selection ();
87 selection.set_mode (SelectionMode.SINGLE);
89 // Source - destination / driver column
90 var route_column = new TreeViewColumn ();
91 route_column.set_title (_("Route"));
92 route_column.set_reorderable (false);
93 route_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
94 route_column.set_expand (true);
95 tree.append_column (route_column);
97 var vbox_renderer = new CellRendererVBox ();
99 var renderer = new CellRendererText ();
100 renderer.yalign = 1.0f;
101 renderer.set_fixed_size (-1, 32);
102 vbox_renderer.append (renderer, true);
103 vbox_renderer.set_data ("route-renderer", renderer);
105 // Add secondary text to column (driver name, route details)
106 renderer = new CellRendererText ();
108 renderer.set_fixed_size (-1, 32);
109 renderer.ellipsize = Pango.EllipsizeMode.END;
110 Pango.AttrList attr_list = new Pango.AttrList ();
111 var style = Gtk.rc_get_style_by_paths (Gtk.Settings.get_default (), "SmallSystemFont", null, typeof (void));
113 var attr_font_desc = new Pango.AttrFontDesc (style.font_desc.copy ());
114 attr_list.insert ((owned) attr_font_desc);
117 this.ensure_style ();
118 if (this.style.lookup_color ("SecondaryTextColor", out color)) {
119 Pango.Attribute attr_color = Pango.attr_foreground_new (color.red, color.green, color.blue);
120 attr_list.insert ((owned) attr_color);
122 renderer.attributes = attr_list;
123 vbox_renderer.append (renderer, true);
124 vbox_renderer.set_data ("secondary-renderer", renderer);
126 route_column.pack_start (vbox_renderer, true);
127 route_column.set_cell_data_func (vbox_renderer, vbox_data_func);
129 // Date and time column
130 var datetime_column = new TreeViewColumn.with_attributes ("DateTime", new CellRendererText (), "text", Columns.DATETIME);
131 datetime_column.set_reorderable (false);
132 datetime_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
133 datetime_column.set_expand (true);
134 tree.append_column (datetime_column);
136 // Free places column
137 var places_column = new TreeViewColumn.with_attributes ("Places", new CellRendererText (), "text", Columns.PLACES);
138 places_column.set_reorderable (false);
139 places_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
140 places_column.set_expand (true);
141 tree.append_column (places_column);
144 var price_column = new TreeViewColumn.with_attributes ("Price", new CellRendererText (), "text", Columns.PRICE);
145 price_column.set_reorderable (false);
146 price_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
147 price_column.set_expand (true);
148 tree.append_column (price_column);
150 // Smoker/Non-smoker column
151 var smoke_column = new TreeViewColumn.with_attributes ("Smoker", new CellRendererPixbuf (), "icon-name", Columns.SMOKER);
152 smoke_column.set_reorderable (false);
153 smoke_column.set_sizing (TreeViewColumnSizing.AUTOSIZE);
154 smoke_column.set_expand (false);
155 tree.append_column (smoke_column);
157 var pannable = new PannableArea ();
160 no_lifts = new Label (_("No lifts"));
161 Hildon.helper_set_logical_font (no_lifts, "LargeSystemFont");
162 Hildon.helper_set_logical_color (no_lifts, RcFlags.FG, StateType.NORMAL, "SecondaryTextColor");
163 no_lifts.set_size_request (-1, 6 * 70);
164 no_lifts.set_alignment ((float) 0.5, (float) 0.42);
166 var vbox = new VBox (false, 0);
167 vbox.pack_start (pannable, true, true, 0);
168 vbox.pack_start (no_lifts, false, false, 0);
170 alignment.add (vbox);
173 alignment.show_all ();
175 route_column.set_visible (!BeifahrerProgram.orientation.portrait);
177 tree.row_activated.connect (this.on_row_activated);
178 Gdk.Screen.get_default ().size_changed.connect (this.on_orientation_changed);
179 goto_website.clicked.connect (on_goto_website_clicked);
180 sort_by_time.toggled.connect (button => {
181 if (button.get_active ())
182 sortable.set_sort_column_id (Columns.DATETIME, Gtk.SortType.ASCENDING);
184 sort_by_price.toggled.connect (button => {
185 if (button.get_active ())
186 sortable.set_sort_column_id (Columns.PRICE, Gtk.SortType.ASCENDING);
190 private int datetime_sort_func (TreeModel model, TreeIter a, TreeIter b) {
193 model.get (a, Columns.LIFT, out la);
194 model.get (b, Columns.LIFT, out lb);
195 int year = la.time.year - lb.time.year;
198 int month = la.time.month - lb.time.month;
201 int day = la.time.day - lb.time.day;
204 int hour = la.time.hour - lb.time.hour;
205 // Negative hour means no exact time available
206 // - sort those entries last
207 if (la.time.hour < 0) {
211 if (lb.time.hour < 0) {
217 int minute = la.time.minute - lb.time.minute;
221 private int price_sort_func (TreeModel model, TreeIter a, TreeIter b) {
224 model.get (a, Columns.PRICE, out pa);
225 model.get (b, Columns.PRICE, out pb);
226 if (pa == null && pb != null)
228 if (pa != null && pb == null)
230 return strcmp (pa, pb);
233 private void vbox_data_func (CellLayout cell_layout, CellRenderer cell, TreeModel model, TreeIter iter) {
235 CellRendererText renderer;
237 model.get (iter, Columns.ROUTE, out text);
238 renderer = cell.get_data ("route-renderer");
239 renderer.text = text;
241 model.get (iter, Columns.SECONDARY, out text);
242 renderer = cell.get_data ("secondary-renderer");
243 renderer.text = text;
246 public async void find_lifts (string city_from, int radius_from, string city_to, int radius_to, Date date, int tolerance = 0) {
248 set_title ("%s - %s".printf (city_from, city_to));
249 Hildon.gtk_window_set_progress_indicator (this, 1);
251 url = adac.get_lift_list_url (city_from, radius_from, city_to, radius_to, date, tolerance);
254 goto_website.show ();
255 var lift_list = yield adac.get_lift_list (city_from, radius_from, city_to, radius_to, date, tolerance);
256 foreach (Lift lift in lift_list) {
257 string icon_name = null;
258 if (LiftFlags.SMOKER in lift.flags)
259 icon_name = "beifahrer_smoker";
260 else if (LiftFlags.NON_SMOKER in lift.flags)
261 icon_name = "beifahrer_non_smoker";
262 string datetime = "%02d.%02d.%04d".printf (lift.time.day, lift.time.month, lift.time.year);
263 if (lift.time.hour >= 0)
264 datetime += ", %d:%02d".printf (lift.time.hour, lift.time.minute);
265 store.insert_with_values (out iter, -1, Columns.ROUTE, lift.city_from + " - " + lift.city_to,
266 Columns.SECONDARY, "",
267 Columns.DATETIME, datetime,
268 Columns.PLACES, _("%d pl.").printf (lift.places),
269 Columns.PRICE, lift.price,
270 Columns.SMOKER, icon_name,
272 // (LiftFlags.WOMEN_ONLY,ADAC_MEMBER in lift.flags)
274 if (lift_list.length () > 6)
275 alignment.right_padding = MARGIN_DEFAULT;
276 if (lift_list.length () == 0)
279 bool preload = false;
281 preload = gconf.get_bool (GCONF_KEY_PRELOAD);
285 if (store.get_iter_first (out iter)) do {
287 store.@get (iter, Columns.LIFT, out lift2);
290 if (lift2.description == null) {
291 yield adac.update_lift_details (lift2);
292 store.@set (iter, Columns.SECONDARY, lift2.name);
294 } while (store.iter_next (ref iter));
297 Hildon.gtk_window_set_progress_indicator (this, 0);
300 void on_goto_website_clicked () {
301 BeifahrerProgram.open_browser (this, url);
304 private void on_row_activated (TreeView tree, TreePath /*_*/path, TreeViewColumn column) {
305 TreeModel model = tree.model;
309 if (model.get_iter (out iter, path)) {
310 model.get (iter, Columns.LIFT, out lift);
312 var window = new LiftDetailWindow (adac, lift);
317 private void on_orientation_changed (Gdk.Screen screen) {
318 route_column.set_visible (!BeifahrerProgram.orientation.portrait);