Debian packaging: 0.0.4-1
[beifahrer] / src / query-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 QueryWindow : StackableWindow {
23         public const string GCONF_KEY_ARRIVAL = "/apps/beifahrer/arrival";
24         public const string GCONF_KEY_DEPARTURE = "/apps/beifahrer/departure";
25         public const string GCONF_KEY_USE_LOCATION = "/apps/beifahrer/use_location";
26
27         AdacMitfahrclub adac;
28         CityButton departure_button;
29         CityButton arrival_button;
30         DateButton date;
31         TouchSelector tolerance_selector;
32         Location.GPSDControl control;
33         Location.GPSDevice device;
34         GConf.Client gconf;
35         bool use_location = true;
36         bool want_location;
37
38         construct {
39                 set_title ("Beifahrer");
40
41                 var menu = new AppMenu ();
42                 var my_info = new Gtk.Button.with_label (_("My information"));
43                 var my_offers = new Gtk.Button.with_label (_("My offers"));
44                 var settings = new Gtk.Button.with_label (_("Settings"));
45                 menu.append (my_info);
46                 menu.append (my_offers);
47                 menu.append (settings);
48                 menu.show_all ();
49                 set_main_menu (menu);
50
51                 adac = new AdacMitfahrclub ();
52                 gconf = GConf.Client.get_default ();
53
54                 try {
55                         adac.set_credentials (gconf.get_string ("/apps/beifahrer/adac/username"),
56                                               gconf.get_string ("/apps/beifahrer/adac/password"));
57                 } catch (Error e) {
58                 }
59
60                 tolerance_selector = new TouchSelector.text ();
61                 for (int days = 0; days <= 4; days += 1)
62                         tolerance_selector.append_text (_("+/- %d days").printf (days));
63
64                 var alignment = new Alignment (0.0f, 0.0f, 1.0f, 1.0f);
65                 alignment.top_padding = MARGIN_HALF;
66                 alignment.left_padding = MARGIN_DOUBLE;
67                 alignment.right_padding = MARGIN_DOUBLE;
68                 var table = new Table (5, 2, false);
69
70                 departure_button = new CityButton (SizeType.FINGER_HEIGHT,
71                                                    ButtonArrangement.VERTICAL, adac.get_city_list ());
72                 departure_button.set_title (_("Departure"));
73                 departure_button.set_value (_("Please select"));
74                 departure_button.set_alignment (0.0f, 0.0f, 0.5f, 0.5f);
75                 table.attach (departure_button, 0, 2, 0, 1, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
76
77                 try {
78                         departure_button.set_active (gconf.get_int ("/apps/beifahrer/departure"));
79                 } catch (Error e) {
80                 }
81
82                 arrival_button = new CityButton (SizeType.FINGER_HEIGHT,
83                                                  ButtonArrangement.VERTICAL, adac.get_city_list ());
84                 arrival_button.set_title (_("Arrival"));
85                 arrival_button.set_value (_("Please select"));
86                 arrival_button.set_alignment (0.0f, 0.0f, 0.5f, 0.5f);
87                 table.attach (arrival_button, 0, 2, 1, 2, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
88
89                 try {
90                         arrival_button.set_active (gconf.get_int ("/apps/beifahrer/arrival"));
91                 } catch (Error e) {
92                 }
93
94                 var switch_button = new Gtk.Button.with_label (_("Switch departure and arrival"));
95                 Hildon.gtk_widget_set_theme_size (switch_button, SizeType.FINGER_HEIGHT);
96                 switch_button.set_alignment (0.0f, 0.5f);
97                 table.attach (switch_button, 0, 2, 2, 3, AttachOptions.FILL, AttachOptions.FILL, 0, 0);
98
99                 date = new DateButton (SizeType.FINGER_HEIGHT,
100                                        ButtonArrangement.VERTICAL);
101                 date.set_alignment (0.0f, 0.0f, 0.5f, 0.5f);
102                 table.attach (date, 0, 1, 3, 4, AttachOptions.FILL | AttachOptions.EXPAND, AttachOptions.FILL, 0, 0);
103
104                 var button = new PickerButton (SizeType.FINGER_HEIGHT,
105                                            ButtonArrangement.VERTICAL);
106                 button.set_selector (tolerance_selector);
107                 button.set_title (_("Tolerance"));
108                 button.set_value (_("+/- 0 days"));
109                 button.set_alignment (0.0f, 0.0f, 0.5f, 0.5f);
110                 table.attach (button, 1, 2, 3, 4, AttachOptions.FILL, AttachOptions.FILL, 0, 0);
111
112                 var search_button = new Gtk.Button.with_label (_("Search"));
113                 Hildon.gtk_widget_set_theme_size (search_button, SizeType.FINGER_HEIGHT);
114                 table.attach (search_button, 0, 2, 4, 5, AttachOptions.FILL, AttachOptions.FILL, 0, 0);
115
116                 alignment.add (table);
117                 add (alignment);
118
119                 switch_button.clicked.connect (on_switch_button_clicked);
120                 search_button.clicked.connect (on_search_button_clicked);
121                 my_info.clicked.connect (on_my_info_clicked);
122                 my_offers.clicked.connect (on_my_offers_clicked);
123                 settings.clicked.connect (on_settings_clicked);
124
125                 show_all ();
126
127                 control = Location.GPSDControl.get_default ();
128                 control.preferred_method = Location.METHOD_ACWP;
129                 control.preferred_interval = Location.GPSDControlInterval.@1S;
130                 control.error.connect (() => { print ("control error\n"); });
131                 control.error_verbose.connect ((e) => {
132                         switch (e) {
133                         case Location.GPSDControlError.USER_REJECTED_DIALOG:
134                                 print ("\tuser rejected dialog\n");
135                                 break;
136                         case Location.GPSDControlError.USER_REJECTED_SETTINGS:
137                                 print ("\tuser rejected settings\n");
138                                 break;
139                         case Location.GPSDControlError.BT_GPS_NOT_AVAILABLE:
140                                 print ("\tbt gps not available\n");
141                                 break;
142                         case Location.GPSDControlError.METHOD_NOT_ALLOWED_IN_OFFLINE_MODE:
143                                 print ("\tmethod not allowed in offline mode\n");
144                                 break;
145                         case Location.GPSDControlError.SYSTEM:
146                                 Banner.show_information (this, null, _("No GPS available!"));
147                                 break;
148                         }
149                 });
150                 control.gpsd_running.connect (() => { print ("control running\n"); });
151                 control.gpsd_stopped.connect (() => { print ("control stopped\n"); });
152
153                 try {
154                         use_location = gconf.get_bool (GCONF_KEY_USE_LOCATION);
155                 } catch (Error e) {
156                 }
157                 want_location = use_location;
158                 if (want_location)
159                         control.start ();
160
161                 device = (Location.GPSDevice) GLib.Object.@new (typeof (Location.GPSDevice), null);
162                 device.changed.connect (on_location_changed);
163                 device.connected.connect (() => { print ("device connected\n"); });
164                 device.disconnected.connect (() => { print ("device disconnected\n"); });
165
166                 // In case the device already has a fix:
167                 on_location_changed ();
168         }
169
170         void on_location_changed () requires (device.fix != null) {
171                 if (!want_location || device.status == Location.GPSDeviceStatus.NO_FIX)
172                         return;
173
174                 if (Location.GPS_DEVICE_LATLONG_SET in (int) device.fix.fields) {
175                         print ("fix: lat=%f, lon=%f\n", device.fix.latitude, device.fix.longitude);
176
177                         unowned City city = adac.find_nearest_city (device.fix.latitude, device.fix.longitude);
178                         if (city != null) {
179                                 int n = adac.get_city_list ().index (city);
180                                 int n_from = departure_button.get_active ();
181                                 int n_to = arrival_button.get_active ();
182
183                                 print ("city(%d): %s (%d)\n", n, city.name, city.number);
184
185                                 if (n != n_from) {
186                                         departure_button.set_active (n);
187
188                                         // If we are at the previous point of arrival, prepare for return trip
189                                         if (n == n_to)
190                                                 arrival_button.set_active (n_from);
191                                 }
192                         }
193
194                         control.stop ();
195                         want_location = false;
196                 }
197         }
198
199         void on_search_button_clicked (Gtk.Button button) {
200                 int n;
201
202                 n = departure_button.get_active ();
203                 if (n == -1)
204                         return;
205                 string city_from = adac.get_city_list ().nth_data (n).name;
206                 try {
207                         if (gconf.get_int (GCONF_KEY_DEPARTURE) != n)
208                                 gconf.set_int (GCONF_KEY_DEPARTURE, n);
209                 } catch (Error e) {
210                 }
211
212                 n = arrival_button.get_active ();
213                 if (n == -1)
214                         return;
215                 string city_to = adac.get_city_list ().nth_data (n).name;
216                 try {
217                         if (gconf.get_int (GCONF_KEY_ARRIVAL) != n)
218                                 gconf.set_int (GCONF_KEY_ARRIVAL, n);
219                 } catch (Error e) {
220                 }
221
222                 uint year, month, day;
223                 date.get_date (out year, out month, out day);
224                 var date = Date ();
225                 date.set_day ((DateDay) day);
226                 date.set_month ((DateMonth) (month + DateMonth.JANUARY));
227                 date.set_year ((DateYear) year);
228
229                 int tolerance = tolerance_selector.get_active (0);
230
231                 var window = new LiftListWindow (adac);
232                 window.show ();
233                 window.find_lifts.begin (city_from, departure_button.get_radius (), city_to, arrival_button.get_radius (), date, tolerance);
234         }
235
236         // Switch departure and arrival
237         void on_switch_button_clicked () {
238                 int n = departure_button.get_active ();
239                 departure_button.set_active (arrival_button.get_active ());
240                 arrival_button.set_active (n);
241                 n = departure_button.get_radius ();
242                 departure_button.set_radius (arrival_button.get_radius ());
243                 arrival_button.set_radius (n);
244         }
245
246         void on_my_info_clicked () {
247                 var window = new MyInformationWindow (adac);
248                 window.show ();
249         }
250
251         void on_my_offers_clicked () {
252                 var window = new MyOffersWindow (adac);
253                 window.show ();
254                 window.get_my_offers.begin ();
255         }
256
257         void on_settings_clicked () {
258                 var dialog = new SettingsDialog (this);
259                 dialog.response.connect (on_settings_response);
260                 dialog.show ();
261         }
262
263         void on_settings_response (int response_id) {
264                 bool old_use_location = use_location;
265                 use_location = gconf.get_bool (GCONF_KEY_USE_LOCATION);
266                 if (!old_use_location && use_location) {
267                         want_location = true;
268                         control.start ();
269                 }
270         }
271 }