First commit
[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 }