840d8497cd9ce43d3c35d431702644fe27365610
[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
27 namespace
28 {
29     const QString CALL_SERVICE_NAME = "com.nokia.csd";
30     const QString CALL_SERVICE_PATH = "/com/nokia/csd/call";
31     const QString CALL_SERVICE_INTERFACE = "com.nokia.csd.Call";
32     const QString CALL_SERVICE_INSTANCE_NAME = "com.nokia.csd.Call.Instance";
33     const QString CALL_SIGNAL_INCOMING = "Coming";
34     const QString CALL_SIGNAL_RELEASE = "Release";
35     const QString CALL_SIGNAL_TERMINATED = "Terminated";
36 }
37
38 QDBusConnection CallListener::systemBus_ = QDBusConnection::systemBus();
39
40 CallListener::CallListener(): eniro_(0), contactManager_(0),
41 connectionManager_(0), closeConnection_(false), box_(0), label_(0),
42 retries_(-1)
43 {
44 }
45
46 CallListener::~CallListener()
47 {
48     end();
49 }
50
51 void CallListener::begin()
52 {
53     systemBus_.connect(CALL_SERVICE_NAME,
54                        CALL_SERVICE_PATH,
55                        CALL_SERVICE_INTERFACE,
56                        CALL_SIGNAL_INCOMING,
57                        this,
58                        SLOT(incomingCall(QDBusObjectPath, QString)));
59
60     systemBus_.connect(CALL_SERVICE_NAME,
61                        CALL_SERVICE_PATH,
62                        CALL_SERVICE_INTERFACE,
63                        CALL_SIGNAL_RELEASE,
64                        this,
65                        SLOT(callTerminate()));
66
67     contactManager_ = new ContactManager;
68
69     eniro_ = new Eniro(Eniro::stringToSite(Settings::instance()->get("site")));
70
71     eniro_->setMaxResults(1);
72     eniro_->setFindNumber(false);
73     eniro_->setTimeout(REQUEST_TIMEOUT);
74
75     connect(eniro_, SIGNAL(requestFinished(QVector <Eniro::Result> const&,
76                                            Eniro::SearchDetails const&, bool)),
77                                            this, SLOT(requestFinished(QVector <Eniro::Result> const&,
78                                                                       Eniro::SearchDetails const&, bool)));
79
80     box_ = new InformationBox();
81     label_ = new QLabel("", box_);
82     label_->setMargin(8);
83     box_->setWidget(label_);
84
85     qDebug() << "Starting...";
86
87 }
88
89 void CallListener::end()
90 {
91     systemBus_.disconnect(CALL_SERVICE_NAME,
92                           CALL_SERVICE_PATH,
93                           CALL_SERVICE_INTERFACE,
94                           CALL_SIGNAL_INCOMING,
95                           this,
96                           SLOT(incomingCall(QDBusObjectPath, QString)));
97
98     systemBus_.disconnect(CALL_SERVICE_NAME,
99                           CALL_SERVICE_PATH,
100                           CALL_SERVICE_INTERFACE,
101                           CALL_SIGNAL_RELEASE,
102                           this,
103                           SLOT(callTerminate()));
104
105     delete contactManager_;
106     contactManager_ = 0;
107     delete connectionManager_;
108     connectionManager_ = 0;
109     delete eniro_;
110     eniro_ = 0;
111     delete box_;
112     box_ = 0;
113     delete label_;
114     label_ = 0;
115 }
116
117 void CallListener::search(Eniro::SearchDetails const& details)
118 {
119     qDebug() << "Search called";
120
121     Eniro::Result result;
122
123     if(Cache::instance().findItem(details.query, result))
124     {
125
126         showDelayedResult(createResult(result.name,
127                                        result.street,
128                                        result.city), BANNER_DELAY);
129     }
130     else
131     {
132         retries_ = 0;
133         currentSearch_ = details.query;
134
135         if(connectionManager_)
136         {
137             delete connectionManager_;
138             connectionManager_ = 0;
139         }
140
141         connectionManager_ = new ConnectionManager;
142
143         if(!connectionManager_->isConnected())
144         {
145             connectionManager_->connect();
146             closeConnection_ = true;
147         }
148         else
149         {
150             closeConnection_ = false;
151         }
152
153         showDelayedResult(tr("Searching..."), 200);
154         eniro_->search(details);
155     }
156
157 }
158
159 void CallListener::requestFinished(QVector <Eniro::Result> const& results,
160                                    Eniro::SearchDetails const& details,
161                                    bool error)
162 {
163     // If box is not visible, the call must have been terminated already
164     if(!box_->isVisible())
165     {
166         return;
167     }
168
169     QString message;
170
171     if(error)
172     {
173         qDebug() << "Error: " << eniro_->errorString();
174
175         if(retries_ < NUMBER_OF_RETRIES && retries_ >= 0)
176         {
177             retries_++;
178             eniro_->search(Eniro::SearchDetails(currentSearch_));
179             return;
180         }
181         else
182         {
183             message = tr("Search failed:") + " " + eniro_->errorString() + ".";
184         }
185     }
186     else if(results.size() == 0)
187     {
188         message = tr("Phone number was not found");
189     }
190     else
191     {
192         message = createResult(results.at(0).name, results.at(0).street,
193                                results.at(0).city);
194         Eniro::Result result = results.at(0);
195         result.number = details.query;
196         Cache::instance().addItem(result);
197     }
198
199     retries_ = -1;
200     currentSearch_ = "";
201     timedMessage_ = "";
202
203     showResult(message);
204
205     if(closeConnection_ && connectionManager_)
206     {
207         connectionManager_->disconnect(true);
208         closeConnection_ = false;
209     }
210
211     delete connectionManager_;
212     connectionManager_ = 0;
213
214 }
215
216 QString CallListener::createResult(QString const& name, QString const& street, QString const& city)
217 {
218     QString result = "<b>" + name + "</b>";
219
220     if(!street.isEmpty() || !city.isEmpty())
221     {
222         result += "<br>";
223
224         if(!street.isEmpty())
225         {
226             result += street + ", ";
227         }
228
229         result += city;
230     }
231
232     return result;
233 }
234
235 void CallListener::showResult(QString const& text)
236 {
237     label_->setText("<font color='black'>" + text + "</font>");
238
239     if(box_->isVisible())
240     {
241         box_->hide();
242     }
243
244     box_->show();
245 }
246
247 void CallListener::incomingCall(QDBusObjectPath path, QString number)
248 {
249     qDebug() << "Incoming: " << number;
250
251     if(!contactManager_->numberExists(number))
252     {
253         qDebug() << "Number doesn't exist";
254
255         systemBus_.connect(CALL_SERVICE_NAME,
256                            path.path(),
257                            CALL_SERVICE_INSTANCE_NAME,
258                            CALL_SIGNAL_TERMINATED,
259                            this,
260                            SLOT(callTerminate()));
261
262         qDebug() << "Going to search";
263
264         search(Eniro::SearchDetails(number));
265     }
266     else
267     {
268         qDebug() << "Number exists";
269     }
270 }
271
272 void CallListener::callTerminate()
273 {
274     if(box_->isVisible())
275     {
276         box_->hide();
277     }
278
279     if(closeConnection_ && connectionManager_)
280     {
281         connectionManager_->disconnect(true);
282         closeConnection_ = false;
283     }
284
285     delete connectionManager_;
286     connectionManager_ = 0;
287 }
288
289 void CallListener::showDelayedResult(QString const& text, int delay)
290 {
291     timedMessage_ = text;
292     QTimer::singleShot(delay, this, SLOT(showTimedMessage()));
293 }
294
295 void CallListener::showTimedMessage()
296 {
297     if(timedMessage_.size() == 0)
298     {
299         return;
300     }
301
302     showResult(timedMessage_);
303
304     timedMessage_ = "";
305 }