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 LiftDetailWindow : StackableWindow {
23 private const string BROWSER_SERVICE = "com.nokia.osso_browser";
24 private const string BROWSER_PATH = "/com/nokia/osso_browser";
25 private const string BROWSER_IF = "com.nokia.osso_browser";
27 private const string CALENDAR_SERVICE = "com.nokia.calendar";
28 private const string CALENDAR_PATH = "/com/nokia/calendar";
29 private const string CALENDAR_IF = "com.nokia.calendar";
34 PannableArea pannable;
36 OssoABook.Button button_route;
37 OssoABook.Button button_calendar;
39 OssoABook.Button button_phone;
40 OssoABook.Button button_sms;
41 OssoABook.Button button_email;
46 string ics_filename = null;
48 public LiftDetailWindow (AdacMitfahrclub _adac, Lift _lift) {
52 update_lift_details ();
54 if (lift.description == null)
55 get_lift_details.begin ();
59 set_title ("Beifahrer");
61 var menu = new AppMenu ();
62 var add_contact = new Gtk.Button.with_label (_("New contact"));
64 menu.append (add_contact);
65 var goto_website = new Gtk.Button.with_label (_("Show website"));
67 menu.append (goto_website);
70 alignment = new Alignment (0.0f, 0.0f, 1.0f, 1.0f);
71 alignment.top_padding = MARGIN_HALF;
72 alignment.left_padding = MARGIN_DOUBLE;
73 alignment.right_padding = MARGIN_DOUBLE;
75 pannable = new PannableArea ();
76 pannable.hscrollbar_policy = PolicyType.NEVER;
78 vbox = new VBox (false, 0);
80 var hbox = new HBox (false, 0);
82 button_route = new OssoABook.Button (SizeType.FINGER_HEIGHT);
83 button_route.style = OssoABook.ButtonStyle.LABEL;
85 var image_eventbox = new EventBox ();
86 image_smoke = new Image ();
87 image_eventbox.add (image_smoke);
89 hbox.pack_start (button_route, true, true, 0);
90 hbox.pack_start (image_eventbox, false, false, MARGIN_DEFAULT);
92 table = new Table (7, 2, false);
94 button_calendar = new OssoABook.Button (SizeType.FINGER_HEIGHT);
95 button_calendar.set_icon_name ("general_calendar");
96 button_calendar.set_icon_visible (true);
97 button_calendar.title = _("Departure time");
99 label_driver = new Label (_("Driver:"));
100 label_driver.set_alignment (0.0f, 0.5f);
101 Hildon.gtk_widget_set_theme_size (label_driver, SizeType.FINGER_HEIGHT);
103 button_phone = new OssoABook.Button (SizeType.FINGER_HEIGHT);
104 button_phone.set_icon_name ("general_call");
105 button_phone.set_icon_visible (true);
106 button_phone.title = _("Phone");
108 button_sms = new OssoABook.Button (SizeType.FINGER_HEIGHT);
109 button_sms.set_icon_name ("general_sms");
110 button_sms.set_icon_visible (true);
111 button_sms.title = _("SMS");
113 button_email = new OssoABook.Button (SizeType.FINGER_HEIGHT);
114 button_email.set_icon_name ("general_email");
115 button_email.set_icon_visible (true);
116 button_email.title = _("E-mail");
118 label = new Label ("");
119 label.set_alignment (0.0f, 0.5f);
120 label.set_line_wrap (true);
122 label_changed = new Label ("");
123 label_changed.set_alignment (1.0f, 0.0f);
124 Hildon.helper_set_logical_color (label_changed, RcFlags.FG, StateType.NORMAL, "SecondaryTextColor");
125 Hildon.helper_set_logical_font (label_changed, "SmallSystemFont");
127 if (BeifahrerProgram.orientation.portrait) {
128 table.attach (button_calendar, 0, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
129 table.attach (label_driver, 0, 2, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, MARGIN_DEFAULT, 0);
130 table.attach (button_phone, 0, 2, 2, 3, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
131 table.attach (button_sms, 0, 2, 3, 4, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
132 table.attach (button_email, 0, 2, 4, 5, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
134 table.attach (button_calendar, 1, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
135 table.attach (label_driver, 0, 1, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, MARGIN_DEFAULT, 0);
136 table.attach (button_phone, 1, 2, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
137 table.attach (button_sms, 1, 2, 2, 3, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
138 table.attach (button_email, 1, 2, 3, 4, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
140 table.attach (label, 0, 2, 5, 6, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, MARGIN_DEFAULT, 0);
141 table.attach (label_changed, 0, 2, 6, 7, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, MARGIN_DEFAULT, 0);
143 vbox.pack_start (hbox, true, true, 0);
144 vbox.pack_start (table, true, true, 0);
146 pannable.add_with_viewport (vbox);
147 alignment.add (pannable);
149 alignment.show_all ();
150 button_email.hide ();
153 Gdk.Screen.get_default ().size_changed.connect (on_orientation_changed);
154 add_contact.clicked.connect (on_add_contact_clicked);
155 goto_website.clicked.connect (on_goto_website_clicked);
156 image_eventbox.button_press_event.connect (on_image_eventbox_button_pressed);
157 button_calendar.clicked.connect (on_button_calendar_clicked);
158 button_phone.clicked.connect (on_button_phone_clicked);
159 button_sms.clicked.connect (on_button_sms_clicked);
160 button_email.clicked.connect (on_button_email_clicked);
161 destroy.connect (on_destroy);
162 map_event.connect (on_map_event);
165 private async void get_lift_details () {
166 Hildon.gtk_window_set_progress_indicator (this, 1);
167 yield adac.update_lift_details (lift);
168 Hildon.gtk_window_set_progress_indicator (this, 0);
170 update_lift_details ();
173 private void update_lift_details () {
174 button_route.title = _("From %s to %s").printf (lift.city_from, lift.city_to);
175 if (lift.city_via.length () > 0) {
176 string route = _("via ");
177 foreach (string via in lift.city_via)
179 button_route.value = route;
181 button_route.value = "";
184 button_calendar.value = "%02d.%02d.%04d, %d:%02d".printf (lift.time.day, lift.time.month, lift.time.year, lift.time.hour, lift.time.minute);
186 label_driver.set_text (_("Driver: ") + lift.name);
187 if (lift.cell != null) {
188 button_phone.title = _("Cell");
189 string cell_number = E.normalize_phone_number (lift.cell);
190 button_phone.value = cell_number;
191 button_sms.value = cell_number;
192 } else if (lift.phone != null) {
193 button_phone.title = _("Phone");
194 string phone_number = E.normalize_phone_number (lift.phone);
195 button_phone.value = phone_number;
196 button_sms.value = phone_number;
199 if (lift.email_image_uri != null) {
200 button_email.value = _("Click to view E-mail image");
201 button_email.show ();
204 string lift_text = _("Free places: %d\n").printf (lift.places);
205 lift_text += (lift.price != null) ? _("Price: %s\n").printf (lift.price) : _("(no price given)\n");
206 if (LiftFlags.SMOKER in lift.flags) try {
207 var pixbuf = IconTheme.get_default ().load_icon ("beifahrer_smoker", 32, IconLookupFlags.NO_SVG);
208 image_smoke.pixbuf = pixbuf;
210 } else if (LiftFlags.NON_SMOKER in lift.flags) try {
211 var pixbuf = IconTheme.get_default ().load_icon ("beifahrer_non_smoker", 32, IconLookupFlags.NO_SVG);
212 image_smoke.pixbuf = pixbuf;
215 if (LiftFlags.ADAC_MEMBER in lift.flags)
216 lift_text += _("ADAC member ");
217 if (LiftFlags.WOMEN_ONLY in lift.flags)
218 lift_text += _("only women ");
219 lift_text += "\n\n" + lift.description;
221 label.set_text (lift_text);
223 if (lift.modified != null)
224 label_changed.set_text (_("\nLast changed: ") + lift.modified);
226 // Reduce right margin for scrollbar, if update_lift_details is called after mapping the window
227 if (vbox.allocation.height > pannable.allocation.height)
228 alignment.right_padding = MARGIN_DEFAULT;
231 void on_button_calendar_clicked () {
232 var ical = new StringBuilder ("BEGIN:VCALENDAR\nVERSION:2.0\nMETHOD:PUBLISH\nBEGIN:VEVENT\nUID:");
233 ical.append ("beifahrer" + lift.href); // UID
234 ical.append ("\nCLASS:PUBLIC\nSUMMARY:");
235 ical.append_printf (_("From %s to %s with %s"), lift.city_from, lift.city_to, lift.name);
236 ical.append ("\nDTSTART;TZID=Europe/Berlin:");
237 ical.append_printf ("%04d%02d%02dT%02d%02d00", lift.time.year + 2000, lift.time.month, lift.time.day, lift.time.hour, lift.time.minute);
238 ical.append ("\nDTEND;TZID=Europe/Berlin:");
239 ical.append_printf ("%04d%02d%02dT%02d%02d00", lift.time.year + 2000, lift.time.month, lift.time.day, lift.time.hour, lift.time.minute);
240 ical.append ("\nDESCRIPTION:");
241 ical.append (lift.description.replace ("\n", "\\n"));
242 ical.append ("\nEND:VEVENT\nEND:VCALENDAR\n");
244 ics_filename = Path.build_path ("/", Environment.get_tmp_dir (),
247 FileUtils.set_contents (ics_filename, ical.str);
248 } catch (FileError e) {
249 stderr.printf ("Failed to write %s: %s\n", ics_filename, e.message);
253 var error = DBus.RawError ();
254 var bus = DBus.RawBus.get (DBus.BusType.SESSION, ref error);
255 var res = HildonMime.open_file (bus, "file://" + ics_filename);
259 if (ics_filename != null)
260 FileUtils.remove (ics_filename);
263 bool on_map_event (Gdk.Event event) {
264 // Reduce right margin for scrollbar, for preloaded lift
265 if (vbox.allocation.height > pannable.allocation.height)
266 alignment.right_padding = MARGIN_DEFAULT;
270 void on_button_phone_clicked () {
272 if (lift.cell != null)
273 uri += E.normalize_phone_number (lift.cell);
274 else if (lift.phone != null)
275 uri += E.normalize_phone_number (lift.phone);
277 var action = URIAction.get_default_action_by_uri (uri);
278 if (action != null) {
282 Banner.show_information (this, null, _("Couldn't call %s URI").printf (uri));
286 Banner.show_information (this, null, _("Error: %s").printf (e.message));
291 void on_button_sms_clicked () {
293 if (lift.cell != null)
294 uri += E.normalize_phone_number (lift.cell);
295 else if (lift.phone != null)
296 uri += E.normalize_phone_number (lift.phone);
298 var action = URIAction.get_default_action_by_uri (uri);
299 if (action != null) {
303 Banner.show_information (this, null, _("Couldn't open %s URI").printf (uri));
307 Banner.show_information (this, null, _("Error: %s").printf (e.message));
312 void on_button_email_clicked () {
313 var uri = "http://mitfahrclub.adac.de";
314 uri += lift.email_image_uri;
316 var action = URIAction.get_default_action_by_uri (uri);
317 if (action != null) {
321 Banner.show_information (this, null, _("Couldn't open %s URI").printf (uri));
325 Banner.show_information (this, null, _("Error: %s").printf (e.message));
330 void on_add_contact_clicked () {
331 var contact = new OssoABook.Contact ();
332 var attr_fn = new E.VCardAttribute (null, E.EVC_FN);
333 contact.add_attribute_with_value ((owned) attr_fn, lift.name);
334 if (lift.cell != null) {
335 var attr_cell = new E.VCardAttribute (null, E.EVC_TEL);
336 var param = new E.VCardAttributeParam (E.EVC_TYPE);
337 attr_cell.add_param_with_value ((owned) param, "CELL");
338 contact.add_attribute_with_value ((owned) attr_cell, E.normalize_phone_number (lift.cell));
340 if (lift.phone != null) {
341 var attr_phone = new E.VCardAttribute (null, E.EVC_TEL);
342 var param = new E.VCardAttributeParam (E.EVC_TYPE);
343 attr_phone.add_param_with_value ((owned) param, "VOICE");
344 contact.add_attribute_with_value ((owned) attr_phone, E.normalize_phone_number (lift.phone));
346 var dialog = new OssoABook.TemporaryContactDialog.with_contact (this, contact);
350 void on_goto_website_clicked () {
351 var url = "http://mitfahrclub.adac.de" + lift.href;
354 var conn = DBus.Bus.get (DBus.BusType.SESSION);
356 dynamic DBus.Object browser = conn.get_object (BROWSER_SERVICE, BROWSER_PATH, BROWSER_IF);
357 browser.open_new_window (url, false);
359 stderr.printf ("Error: %s\n", e.message);
360 Banner.show_information (this, null, _("Failed to open browser."));
364 bool on_image_eventbox_button_pressed (Gdk.EventButton event) {
365 if (event.button != 1)
367 if (LiftFlags.SMOKER in lift.flags)
368 Banner.show_information (this, null, _("Smoker"));
369 if (LiftFlags.NON_SMOKER in lift.flags)
370 Banner.show_information (this, null, _("Non-smoker"));
374 void on_orientation_changed (Gdk.Screen screen) {
375 // Maybe this will be fixed directly in Maemo-GTK, see
376 // http://lists.maemo.org/pipermail/maemo-developers/2010-May/026332.html
377 vbox.queue_resize ();
379 table.remove (button_calendar);
380 table.remove (label_driver);
381 table.remove (button_phone);
382 table.remove (button_sms);
383 table.remove (button_email);
384 if (BeifahrerProgram.orientation.portrait) {
385 table.attach (button_calendar, 0, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
386 table.attach (label_driver, 0, 2, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, MARGIN_DEFAULT, 0);
387 table.attach (button_phone, 0, 2, 2, 3, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
388 table.attach (button_sms, 0, 2, 3, 4, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
389 table.attach (button_email, 0, 2, 4, 5, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
391 table.attach (button_calendar, 1, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
392 table.attach (label_driver, 0, 1, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, MARGIN_DEFAULT, 0);
393 table.attach (button_phone, 1, 2, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
394 table.attach (button_sms, 1, 2, 2, 3, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
395 table.attach (button_email, 1, 2, 3, 4, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);