9071713375fcaa78f63d9dad4bd4a609b23298ad
[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 <QtSql/QSqlQuery>
21 #include "calllistener.h"
22 #include "settings.h"
23 #include "db.h"
24
25 namespace
26 {
27     const QString CALL_SERVICE_NAME = "com.nokia.csd";
28     const QString CALL_SERVICE_PATH = "/com/nokia/csd/call";
29     const QString CALL_SERVICE_INTERFACE = "com.nokia.csd.Call";
30     const QString CALL_SERVICE_INSTANCE_NAME = "com.nokia.csd.Call.Instance";
31     const QString CALL_SIGNAL_INCOMING = "Coming";
32     const QString CALL_SIGNAL_RELEASE = "Release";
33     const QString CALL_SIGNAL_TERMINATED = "Terminated";
34 }
35
36 QDBusConnection CallListener::systemBus_ = QDBusConnection::systemBus();
37
38 CallListener::CallListener(): eniro_(0), contactManager_(0), box_(0), label_(0)
39 {
40 }
41
42 CallListener::~CallListener()
43 {
44     end();
45 }
46
47 void CallListener::begin()
48 {
49     systemBus_.connect(CALL_SERVICE_NAME,
50                        CALL_SERVICE_PATH,
51                        CALL_SERVICE_INTERFACE,
52                        CALL_SIGNAL_INCOMING,
53                        this,
54                        SLOT(incomingCall(QDBusObjectPath, QString)));
55
56     systemBus_.connect(CALL_SERVICE_NAME,
57                        CALL_SERVICE_PATH,
58                        CALL_SERVICE_INTERFACE,
59                        CALL_SIGNAL_RELEASE,
60                        this,
61                        SLOT(callTerminate()));
62
63     contactManager_ = new ContactManager;
64
65     eniro_ = new Eniro(Eniro::stringToSite(Settings::instance()->get("site")));
66
67     eniro_->setMaxResults(1);
68     eniro_->setFindNumber(false);
69
70     connect(eniro_, SIGNAL(requestFinished(QVector <Eniro::Result> const&,
71                                            Eniro::SearchDetails const&, bool)),
72                                            this, SLOT(requestFinished(QVector <Eniro::Result> const&,
73                                                                       Eniro::SearchDetails const&, bool)));
74
75     box_ = new InformationBox();
76     label_ = new QLabel("", box_);
77     label_->setMargin(10);
78     box_->setWidget(label_);
79
80 }
81
82 void CallListener::end()
83 {
84     systemBus_.disconnect(CALL_SERVICE_NAME,
85                           CALL_SERVICE_PATH,
86                           CALL_SERVICE_INTERFACE,
87                           CALL_SIGNAL_INCOMING,
88                           this,
89                           SLOT(incomingCall(QDBusObjectPath, QString)));
90
91     systemBus_.disconnect(CALL_SERVICE_NAME,
92                           CALL_SERVICE_PATH,
93                           CALL_SERVICE_INTERFACE,
94                           CALL_SIGNAL_RELEASE,
95                           this,
96                           SLOT(callTerminate()));
97
98     delete eniro_;
99     eniro_ = 0;
100     delete box_;
101     box_ = 0;
102     delete label_;
103     label_ = 0;
104 }
105
106 void CallListener::search(Eniro::SearchDetails const& details)
107 {
108     label_->setText(tr("Searching..."));
109     box_->show();
110
111     DB::connect();
112
113     QSqlQuery query;
114     query.prepare("SELECT name, street, city FROM cache WHERE number = :number");
115     query.bindValue(":number", details.query);
116
117     if(query.exec() && query.next())
118     {
119         showResult(createResult(query.value(0).toString(),
120                                 query.value(1).toString(),
121                                 query.value(2).toString()));
122
123     }
124     else
125     {
126         eniro_->search(details);
127     }
128
129     DB::disconnect();
130
131 }
132
133 void CallListener::requestFinished(QVector <Eniro::Result> const& results,
134                                    Eniro::SearchDetails const& details,
135                                    bool error)
136 {
137     qDebug() << "Found: " << results.size();
138
139     // If box is not visible, the call must have been terminated already
140     if(!box_->isVisible())
141     {
142         return;
143     }
144
145     QString message;
146
147     if(error)
148     {
149         qDebug() << "Error: " << eniro_->errorString();
150         message = tr("Search failed:") + " " + eniro_->errorString();
151     }
152     else if(results.size() == 0)
153     {
154         message = tr("Phone number was not found");
155     }
156     else
157     {
158         message = createResult(results.at(0).name, results.at(0).street, results.at(0).city);
159         QSqlQuery query;
160
161         DB::connect();
162
163         query.prepare("INSERT INTO cache(number, name, street, city) VALUES(:number, :name, :street, :city)");
164         query.bindValue(":number", details.query);
165         query.bindValue(":name", results.at(0).name);
166         query.bindValue(":street", results.at(0).street);
167         query.bindValue(":city", results.at(0).city);
168
169         if(!query.exec())
170         {
171             qDebug() << "Unable to save cache";
172         }
173
174         QString cacheSize = Settings::instance()->get("cache_size");
175
176         // Delete old entries from cache
177         if(cacheSize.toInt() > 0)
178         {
179             if(!query.exec("DELETE c1 FROM cache AS c1 LEFT JOIN (SELECT id FROM cache ORDER BY id DESC LIMIT " + cacheSize + ") AS c2 ON c1.id = c2.id WHERE c2.id IS NULL"))
180             {
181                 qDebug() << "Unable to delete old cache entries";
182             }
183         }
184
185         DB::disconnect();
186     }
187
188     showResult(message);
189
190 }
191
192 QString CallListener::createResult(QString const& name, QString const& street, QString const& city)
193 {
194     QString result = "<b>" + name + "</b>";
195
196     if(!street.isEmpty() || !city.isEmpty())
197     {
198         result += "<br>";
199
200         if(!street.isEmpty())
201         {
202             result += street + ", ";
203         }
204
205         result += city;
206     }
207
208     return result;
209 }
210
211 void CallListener::showResult(QString const& text)
212 {
213     label_->setText(text);
214     box_->hide();
215     box_->show();
216 }
217
218 void CallListener::incomingCall(QDBusObjectPath path, QString number)
219 {
220     qDebug() << number;
221
222     if(!contactManager_->numberExists(number))
223     {
224
225         systemBus_.connect(CALL_SERVICE_NAME,
226                            path.path(),
227                            CALL_SERVICE_INSTANCE_NAME,
228                            CALL_SIGNAL_TERMINATED,
229                            this,
230                            SLOT(callTerminate()));
231
232         search(Eniro::SearchDetails(number));
233     }
234 }
235
236 void CallListener::callTerminate()
237 {
238     box_->hide();
239 }