2 * This file is part of Jenirok.
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.
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.
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/>.
19 #include <QtCore/QDebug>
20 #include <QtCore/QTimer>
21 #include "calllistener.h"
24 #include "contactmanager.h"
25 #include "connectionmanager.h"
26 #include "sourcecoreconfig.h"
31 const QString CALL_SERVICE_NAME = "com.nokia.csd";
32 const QString CALL_SERVICE_PATH = "/com/nokia/csd/call";
33 const QString CALL_SERVICE_INTERFACE = "com.nokia.csd.Call";
34 const QString CALL_SERVICE_INSTANCE_NAME = "com.nokia.csd.Call.Instance";
35 const QString CALL_SIGNAL_INCOMING = "Coming";
36 const QString CALL_SIGNAL_RELEASE = "Release";
37 const QString CALL_SIGNAL_TERMINATED = "Terminated";
40 QDBusConnection CallListener::systemBus_ = QDBusConnection::systemBus();
42 CallListener::CallListener(): source_(0),
43 closeConnection_(false), initialized_(false), box_(0), label_(0),
44 retries_(-1), timer_(0)
48 CallListener::~CallListener()
54 bool CallListener::begin()
56 if(Settings::instance()->getConnectionType() == Settings::ALWAYS_ASK)
58 qDebug() << "Bad connection settings, unable to start";
62 sourceId_ = Source::stringToId(Settings::instance()->get("source"));
63 QMap<QString, QString> tmpConfig;
64 SourceCoreConfig* config = SourceCoreConfig::getCoreConfig(sourceId_);
65 config->getConfig(tmpConfig);
66 sourceConfig_ = tmpConfig;
69 systemBus_.connect(CALL_SERVICE_NAME,
71 CALL_SERVICE_INTERFACE,
74 SLOT(incomingCall(QDBusObjectPath, QString)));
76 systemBus_.connect(CALL_SERVICE_NAME,
78 CALL_SERVICE_INTERFACE,
81 SLOT(callTerminate()));
83 qDebug() << "Starting...";
89 void CallListener::end()
91 systemBus_.disconnect(CALL_SERVICE_NAME,
93 CALL_SERVICE_INTERFACE,
96 SLOT(incomingCall(QDBusObjectPath, QString)));
98 systemBus_.disconnect(CALL_SERVICE_NAME,
100 CALL_SERVICE_INTERFACE,
103 SLOT(callTerminate()));
106 sourceConfig_.clear();
110 void CallListener::search(Source::SearchDetails const& details)
112 qDebug() << "Search called";
116 Source::Result result;
118 if(Cache::instance().findItem(details.query, result))
121 qDebug() << "Found from cache";
123 showDelayedResult(createResult(result.name,
125 result.city), BANNER_DELAY);
130 currentSearch_ = details.query;
132 if(!handleConnection())
134 qDebug() << "Unable to connect";
138 showDelayedResult(tr("Searching..."), BANNER_DELAY);
140 qDebug() << "Starting to search...";
142 source_->search(details);
147 void CallListener::requestFinished(QVector <Source::Result> const& results,
148 Source::SearchDetails const& details,
153 closeConnection_ = false;
154 ConnectionManager cm;
158 // If box is not visible, the call must have been terminated already
159 if(!initialized_ || !box_->isVisible())
168 qDebug() << "Error: " << source_->errorString();
170 if(retries_ < SEARCH_RETRIES && retries_ >= 0)
173 source_->search(Source::SearchDetails(currentSearch_, "", Source::BOTH));
180 Source::Error error = source_->error();
184 case Source::TIMEOUT:
185 errorString = tr("Request timed out");
188 errorString = source_->errorString();
192 showError(tr("Searching failed:") + " " + errorString + ".");
199 if(results.size() == 0)
201 message = tr("Phone number was not found");
206 message = createResult(results.at(0).name, results.at(0).street,
209 Source::Result result = results.at(0);
210 result.number = details.query;
211 Cache::instance().addItem(result);
219 QString CallListener::createResult(QString const& name, QString const& street, QString const& city)
221 QString result = "<b>" + name + "</b>";
223 if(!street.isEmpty() || !city.isEmpty())
227 if(!street.isEmpty())
229 result += street + ", ";
238 void CallListener::showResult(QString const& text)
245 label_->setText("<font color='black'>" + text + "</font>");
247 if(box_->isVisible())
255 void CallListener::incomingCall(QDBusObjectPath path, QString number)
259 qDebug() << "Unknown caller without number";
265 if(!cm.numberExists(number))
267 qDebug() << "Number doesn't exist: " << number;
269 systemBus_.connect(CALL_SERVICE_NAME,
271 CALL_SERVICE_INSTANCE_NAME,
272 CALL_SIGNAL_TERMINATED,
274 SLOT(callTerminate()));
276 search(Source::SearchDetails(number, "", Source::BOTH));
280 qDebug() << "Number exists: " << number;
284 void CallListener::callTerminate()
286 if(box_ && box_->isVisible())
294 void CallListener::showDelayedResult(QString const& text, int delay)
296 timedMessage_ = text;
297 QTimer::singleShot(delay, this, SLOT(showTimedMessage()));
300 void CallListener::showTimedMessage()
302 if(timedMessage_.size() == 0 || !initialized_)
307 showResult(timedMessage_);
312 void CallListener::searchInit()
314 qDebug() << "Initializing search...";
318 qDebug() << "Already initialized";
322 source_ = Source::getSource(sourceId_);
323 SourceCoreConfig* config = SourceCoreConfig::getCoreConfig(sourceId_);
324 config->loadFromConfig(sourceConfig_);
325 config->apply(source_);
327 source_->setMaxResults(1);
328 source_->setFindNumber(false);
329 source_->setTimeout(REQUEST_TIMEOUT);
331 connect(source_, SIGNAL(requestFinished(QVector <Source::Result> const&,
332 Source::SearchDetails const&, bool)),
333 this, SLOT(requestFinished(QVector <Source::Result> const&,
334 Source::SearchDetails const&, bool)));
335 box_ = new InformationBox;
336 label_ = new QLabel("", box_);
337 label_->setMargin(8);
338 label_->setWordWrap(true);
339 box_->setWidget(label_);
343 void CallListener::searchClose()
350 initialized_ = false;
352 qDebug() << "Closing search...";
356 disconnect(source_, SIGNAL(requestFinished(QVector <Source::Result> const&,
357 Source::SearchDetails const&, bool)),
358 this, SLOT(requestFinished(QVector <Source::Result> const&,
359 Source::SearchDetails const&, bool)));
370 closeConnection_ = false;
371 ConnectionManager cm;
376 bool CallListener::handleConnection()
383 ConnectionManager cm;
387 closeConnection_ = false;
391 closeConnection_ = true;
393 Settings::ConnectionType configType = Settings::instance()->getConnectionType();
395 if(configType == Settings::ALWAYS_ASK)
397 showError(tr("Automatic connecting is not allowed by settings."), BANNER_DELAY);
401 showDelayedResult(tr("Connecting..."), BANNER_DELAY);
403 ConnectionManager::Connection best;
405 ConnectionManager::ConnectionType lookupType = ConnectionManager::NO_TYPE;
410 lookupType = ConnectionManager::WLAN;
413 lookupType = ConnectionManager::GPRS;
416 lookupType = ConnectionManager::NO_TYPE;
423 int maxScans = GPRS_SCANS;
425 if(lookupType != ConnectionManager::GPRS)
427 maxScans = WLAN_SCANS;
430 while(cretries < CONNECTION_LOOKUP_RETRIES)
439 if(cm.getBestConnection(best, lookupType))
447 // If there is only gprs connection available,
448 // make sure that we are on 3g network
449 if(found && (best.type != ConnectionManager::GPRS || is3g()))
456 sleep(WAIT_BETWEEN_RETRIES);
459 qDebug() << "No connections found, retrying...";
465 if(cretries >= CONNECTION_LOOKUP_RETRIES)
467 showError(tr("No available 3G or WLAN networks found."));
473 while(retries < CONNECT_RETRIES)
480 qDebug() << "Connecting to " << best.name;
482 if(cm.connect(best.id))
486 else if(cm.error() == ConnectionManager::INVALID_IAP)
488 showError(tr("Selected access point doesn't exist."));
494 qDebug() << "Unable to connect, retrying...";
496 if(retries < CONNECT_RETRIES)
498 sendRetrySignal(best.id, initialized_);
503 if(retries >= CONNECT_RETRIES)
505 sendRetrySignal(best.id, false);
509 showError(tr("Unable to connect to network."));
518 void CallListener::showError(QString const& msg, int timeout)
520 qDebug() << "Error: " << msg;
522 if(!initialized_ || !box_)
527 box_->setTimeout(ERROR_BANNER_TIMEOUT);
531 showDelayedResult(msg, timeout);
539 bool CallListener::is3g()
541 QDBusMessage msg = QDBusMessage::createMethodCall("com.nokia.phone.net",
542 "/com/nokia/phone/net",
544 "get_registration_status");
546 QDBusMessage rep = systemBus_.call(msg);
548 if(rep.type() == QDBusMessage::ErrorMessage)
550 qDebug() << "Unable to get network status";
554 uint status = rep.arguments().value(6).toUInt();
556 if(status & 0x10 || status & 0x08)
564 void CallListener::sendRetrySignal(QString const& iap, bool retry)
566 QDBusMessage msg = QDBusMessage::createSignal("/com/nokia/icd_ui",
570 QList<QVariant> arguments;
571 arguments.append(QVariant(iap));
572 arguments.append(QVariant(retry));
573 msg.setArguments(arguments);
575 QDBusConnection::systemBus().send(msg);
577 qDebug() << "Retry signal sent";
580 void CallListener::timerEvent(QTimerEvent* event)
587 void CallListener::sleep(int ms)
594 timer_ = startTimer(ms);
598 QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents);