Fixed searchclients to handle new Google URLs correctly; added GUI
[movie-schedule] / src / control / locationcontroller.cpp
1 // Copyright 2010 Jochen Becher
2 //
3 // This file is part of MovieSchedule.
4 //
5 // MovieSchedule 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 // MovieSchedule 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 MovieSchedule.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "locationcontroller.h"
19
20 #include "ui/locationdialog.h"
21 #include "searchclients/gpsclient.h"
22 #include "data/settings.h"
23 #include "ui/mainwindow.h"
24
25 static const char *MSG_LOCATION_NOT_FOUND = QT_TRANSLATE_NOOP("LocationController", "Unable to detect current city.");
26
27 LocationController::LocationController(MainWindow *main_window, Settings *settings) :
28     QObject(0),
29     _main_window(main_window),
30     _settings(settings),
31     _active_search_task_id(GpsClient::INVALID_SEARCH_TASK_ID)
32 {
33 }
34
35 void LocationController::OpenLocationDialog()
36 {
37     LocationDialog *location_dialog = new LocationDialog(_main_window);
38     connect(location_dialog, SIGNAL(Search(Location)), this, SLOT(SearchLocationFromCityDatabase(Location)));
39     connect(location_dialog, SIGNAL(SearchPreviousLocation(Location)), this, SLOT(SearchLocation(Location)));
40     connect(location_dialog, SIGNAL(SearchGPS()), this, SLOT(SearchGPS()));
41     connect(location_dialog, SIGNAL(Cancel()), this, SLOT(CancelLocation()));
42     location_dialog->SetLocation(_settings->GetLocation());
43     location_dialog->SetPreviousLocations(_settings->GetPreviousLocations());
44     location_dialog->SetGPSEnabled(true || _settings->IsGPSEnabled());
45     location_dialog->show();
46     // location_dialog deletes itself
47 }
48
49 void LocationController::CancelAllGpsSearchs()
50 {
51     _active_search_task_id = GpsClient::INVALID_SEARCH_TASK_ID;
52     GpsClient::CancelAllRunningSearchs();
53 }
54
55 void LocationController::SearchLocationFromCityDatabase(Location location)
56 {
57     // TODO check city database
58     SearchLocation(location);
59 }
60
61 void LocationController::SearchLocation(Location location)
62 {
63     location = CleanLocation(location);
64     RememberLocation(location);
65     emit Search(location);
66 }
67
68 void LocationController::SearchGPS()
69 {
70     GpsClient *client = new GpsClient();
71     connect(client, SIGNAL(SearchStarted(int)), this, SLOT(GpsSearchStarted(int)));
72     connect(client, SIGNAL(PositionUpdate(int)), this, SLOT(GpsPositionUpdate(int)));
73     connect(client, SIGNAL(SearchForTownStarted(int)), this, SLOT(GpsSearchForTownStarted(int)));
74     connect(client, SIGNAL(TownUpdate(int,QString)), this, SLOT(GpsTownUpdate(int,QString)));
75     connect(client, SIGNAL(SearchError(int)), this, SLOT(GpsSearchError(int)));
76     connect(client, SIGNAL(SearchFinished(int,bool)), this, SLOT(GpsSearchFinished(int,bool)));
77     _active_search_task_id = client->GetSearchTaskId();
78     client->SearchLocation();
79     // gps client deletes itself
80 }
81
82 void LocationController::CancelLocation()
83 {
84     // nothing to do
85 }
86
87 Location LocationController::CleanLocation(const Location &location)
88 {
89     // TODO clash with city database?
90     QString name = location.GetLocationName().trimmed();
91     if (name.size() > 0) {
92         if (name[0].isLower()) {
93             name[0] = name[0].toUpper();
94         }
95     }
96     Location cleaned_location;
97     cleaned_location.SetLocationName(name);
98     return cleaned_location;
99 }
100
101 void LocationController::RememberLocation(const Location &location)
102 {
103     if (!location.IsValid()) {
104         return;
105     }
106     Settings::Locations locations = _settings->GetPreviousLocations();
107     QMutableListIterator<Location> it(locations);
108     while (it.hasNext()) {
109         const Location &prev_location = it.next();
110         if (prev_location == location) {
111             it.remove();
112         }
113     }
114     locations.push_front(location);
115     while (locations.size() > 5) {
116         locations.pop_back();
117     }
118     _settings->SetPreviousLocations(locations);
119 }
120
121 void LocationController::GpsSearchStarted(int search_task_id)
122 {
123     if (_active_search_task_id != search_task_id) {
124         return;
125     }
126     _main_window->SetBusy(true);
127 }
128
129 void LocationController::GpsPositionUpdate(int search_task_id)
130 {
131     if (_active_search_task_id != search_task_id) {
132         return;
133     }
134 }
135
136 void LocationController::GpsSearchForTownStarted(int search_task_id)
137 {
138     if (_active_search_task_id != search_task_id) {
139         return;
140     }
141 }
142
143 void LocationController::GpsTownUpdate(int search_task_id, QString town)
144 {
145     if (_active_search_task_id != search_task_id) {
146         return;
147     }
148     Location location;
149     location.SetLocationName(town);
150     SearchLocation(location);
151 }
152
153 void LocationController::GpsSearchError(int search_task_id)
154 {
155     if (_active_search_task_id != search_task_id) {
156         return;
157     }
158     _main_window->SetError(tr(MSG_LOCATION_NOT_FOUND));
159 }
160
161 void LocationController::GpsSearchFinished(int search_task_id, bool success)
162 {
163     if (_active_search_task_id != search_task_id) {
164         return;
165     }
166     // In case of success SearchLocation() is started which will
167     // unset busy state on its end
168     if (!success) {
169         _main_window->SetBusy(false);
170     }
171 }