d53da0a7b44ea00fa165fadb3950f068f58c3ac3
[jenirok] / src / daemon / calllistener.cpp
1 /*
2  * This file is part of Jenirok.
3  *
4  * Jenirok is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Jenirok is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Jenirok.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18
19 #include <QtCore/QDebug>
20 #include <QtCore/QTimer>
21 #include <QtSql/QSqlQuery>
22 #include <QtSql/QSqlError>
23 #include "calllistener.h"
24 #include "settings.h"
25 #include "cache.h"
26 #include "contactmanager.h"
27
28 namespace
29 {
30     const QString CALL_SERVICE_NAME = "com.nokia.csd";
31     const QString CALL_SERVICE_PATH = "/com/nokia/csd/call";
32     const QString CALL_SERVICE_INTERFACE = "com.nokia.csd.Call";
33     const QString CALL_SERVICE_INSTANCE_NAME = "com.nokia.csd.Call.Instance";
34     const QString CALL_SIGNAL_INCOMING = "Coming";
35     const QString CALL_SIGNAL_RELEASE = "Release";
36     const QString CALL_SIGNAL_TERMINATED = "Terminated";
37 }
38
39 QDBusConnection CallListener::systemBus_ = QDBusConnection::systemBus();
40
41 CallListener::CallListener(): eniro_(0), connectionManager_(0),
42 closeConnection_(false), initialized_(false), box_(0), label_(0),
43 retries_(-1), site_(Eniro::FI)
44 {
45 }
46
47 CallListener::~CallListener()
48 {
49     end();
50 }
51
52 void CallListener::begin()
53 {
54     systemBus_.connect(CALL_SERVICE_NAME,
55                        CALL_SERVICE_PATH,
56                        CALL_SERVICE_INTERFACE,
57                        CALL_SIGNAL_INCOMING,
58                        this,
59                        SLOT(incomingCall(QDBusObjectPath, QString)));
60
61     systemBus_.connect(CALL_SERVICE_NAME,
62                        CALL_SERVICE_PATH,
63                        CALL_SERVICE_INTERFACE,
64                        CALL_SIGNAL_RELEASE,
65                        this,
66                        SLOT(callTerminate()));
67
68     site_ = Eniro::stringToSite(Settings::instance()->get("site"));
69     Settings::close();
70
71     qDebug() << "Starting...";
72
73 }
74
75 void CallListener::end()
76 {
77     systemBus_.disconnect(CALL_SERVICE_NAME,
78                           CALL_SERVICE_PATH,
79                           CALL_SERVICE_INTERFACE,
80                           CALL_SIGNAL_INCOMING,
81                           this,
82                           SLOT(incomingCall(QDBusObjectPath, QString)));
83
84     systemBus_.disconnect(CALL_SERVICE_NAME,
85                           CALL_SERVICE_PATH,
86                           CALL_SERVICE_INTERFACE,
87                           CALL_SIGNAL_RELEASE,
88                           this,
89                           SLOT(callTerminate()));
90
91     searchClose();
92
93 }
94
95 void CallListener::search(Eniro::SearchDetails const& details)
96 {
97     qDebug() << "Search called";
98
99     searchInit();
100
101     Eniro::Result result;
102
103     if(Cache::instance().findItem(details.query, result))
104     {
105
106         qDebug() << "Found from cache";
107
108         showDelayedResult(createResult(result.name,
109                                        result.street,
110                                        result.city), BANNER_DELAY);
111     }
112     else
113     {
114         retries_ = 0;
115         currentSearch_ = details.query;
116
117         if(!connectionManager_->isConnected())
118         {
119             connectionManager_->connect();
120             closeConnection_ = true;
121         }
122         else
123         {
124             closeConnection_ = false;
125         }
126
127         showDelayedResult(tr("Searching..."), BANNER_DELAY);
128
129         qDebug() << "Starting to search...";
130
131         eniro_->search(details);
132     }
133
134 }
135
136 void CallListener::requestFinished(QVector <Eniro::Result> const& results,
137                                    Eniro::SearchDetails const& details,
138                                    bool error)
139 {
140     // If box is not visible, the call must have been terminated already
141     if(!initialized_ || !box_->isVisible())
142     {
143         return;
144     }
145
146     QString message;
147
148     if(error)
149     {
150         qDebug() << "Error: " << eniro_->errorString();
151
152         if(retries_ < NUMBER_OF_RETRIES && retries_ >= 0)
153         {
154             retries_++;
155             eniro_->search(Eniro::SearchDetails(currentSearch_));
156             return;
157         }
158         else
159         {
160             timedMessage_ = "";
161             message = tr("Search failed:") + " " + eniro_->errorString() + ".";
162             showResult(message);
163         }
164     }
165     else
166     {
167         timedMessage_ = "";
168
169         if(results.size() == 0)
170         {
171             message = tr("Phone number was not found");
172             showResult(message);
173         }
174         else
175         {
176             message = createResult(results.at(0).name, results.at(0).street,
177                                    results.at(0).city);
178             showResult(message);
179             Eniro::Result result = results.at(0);
180             result.number = details.query;
181             Cache::instance().addItem(result);
182         }
183     }
184
185     retries_ = -1;
186     currentSearch_ = "";
187
188     if(closeConnection_ && connectionManager_)
189     {
190         connectionManager_->disconnect(true);
191         closeConnection_ = false;
192     }
193 }
194
195 QString CallListener::createResult(QString const& name, QString const& street, QString const& city)
196 {
197     QString result = "<b>" + name + "</b>";
198
199     if(!street.isEmpty() || !city.isEmpty())
200     {
201         result += "<br>";
202
203         if(!street.isEmpty())
204         {
205             result += street + ", ";
206         }
207
208         result += city;
209     }
210
211     return result;
212 }
213
214 void CallListener::showResult(QString const& text)
215 {
216     if(!initialized_)
217     {
218         return;
219     }
220
221     label_->setText("<font color='black'>" + text + "</font>");
222
223     if(box_->isVisible())
224     {
225         box_->hide();
226     }
227
228     box_->show();
229 }
230
231 void CallListener::incomingCall(QDBusObjectPath path, QString number)
232 {
233     qDebug() << "Incoming: " << number;
234
235     ContactManager cm;
236
237     if(!cm.numberExists(number))
238     {
239         qDebug() << "Number doesn't exist";
240
241         systemBus_.connect(CALL_SERVICE_NAME,
242                            path.path(),
243                            CALL_SERVICE_INSTANCE_NAME,
244                            CALL_SIGNAL_TERMINATED,
245                            this,
246                            SLOT(callTerminate()));
247
248         search(Eniro::SearchDetails(number));
249     }
250     else
251     {
252         qDebug() << "Number exists";
253     }
254 }
255
256 void CallListener::callTerminate()
257 {
258     if(initialized_ && box_ && box_->isVisible())
259     {
260         box_->hide();
261     }
262
263     if(closeConnection_ && connectionManager_)
264     {
265         connectionManager_->disconnect(true);
266         closeConnection_ = false;
267     }
268
269     searchClose();
270 }
271
272 void CallListener::showDelayedResult(QString const& text, int delay)
273 {
274     timedMessage_ = text;
275     QTimer::singleShot(delay, this, SLOT(showTimedMessage()));
276 }
277
278 void CallListener::showTimedMessage()
279 {
280     if(timedMessage_.size() == 0 || !initialized_)
281     {
282         return;
283     }
284
285     showResult(timedMessage_);
286
287     timedMessage_ = "";
288 }
289
290 void CallListener::searchInit()
291 {
292     qDebug() << "Initializing search...";
293
294     connectionManager_ = new ConnectionManager;
295
296     eniro_ = new Eniro(site_);
297     eniro_->setMaxResults(1);
298     eniro_->setFindNumber(false);
299     eniro_->setTimeout(REQUEST_TIMEOUT);
300
301     connect(eniro_, SIGNAL(requestFinished(QVector <Eniro::Result> const&,
302                                            Eniro::SearchDetails const&, bool)),
303                                            this, SLOT(requestFinished(QVector <Eniro::Result> const&,
304                                                                       Eniro::SearchDetails const&, bool)));
305     box_ = new InformationBox;
306     label_ = new QLabel("", box_);
307     label_->setMargin(8);
308     box_->setWidget(label_);
309     initialized_ = true;
310 }
311
312 void CallListener::searchClose()
313 {
314     initialized_ = false;
315
316     qDebug() << "Closing search...";
317
318     if(eniro_)
319     {
320         disconnect(eniro_, SIGNAL(requestFinished(QVector <Eniro::Result> const&,
321                                                   Eniro::SearchDetails const&, bool)),
322                                                   this, SLOT(requestFinished(QVector <Eniro::Result> const&,
323                                                                              Eniro::SearchDetails const&, bool)));
324     }
325
326     delete connectionManager_;
327     connectionManager_ = 0;
328     delete eniro_;
329     eniro_ = 0;
330     delete box_;
331     box_ = 0;
332 }