/*
* This file is part of Jenirok.
*
* Jenirok is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Jenirok is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jenirok. If not, see .
*
*/
#include
#include
#include
#include
#include "calllistener.h"
#include "settings.h"
#include "cache.h"
#include "contactmanager.h"
namespace
{
const QString CALL_SERVICE_NAME = "com.nokia.csd";
const QString CALL_SERVICE_PATH = "/com/nokia/csd/call";
const QString CALL_SERVICE_INTERFACE = "com.nokia.csd.Call";
const QString CALL_SERVICE_INSTANCE_NAME = "com.nokia.csd.Call.Instance";
const QString CALL_SIGNAL_INCOMING = "Coming";
const QString CALL_SIGNAL_RELEASE = "Release";
const QString CALL_SIGNAL_TERMINATED = "Terminated";
}
QDBusConnection CallListener::systemBus_ = QDBusConnection::systemBus();
CallListener::CallListener(): eniro_(0), connectionManager_(0),
closeConnection_(false), initialized_(false), box_(0), label_(0),
retries_(-1), site_(Eniro::FI), autoconnect_(false)
{
}
CallListener::~CallListener()
{
end();
}
void CallListener::begin()
{
systemBus_.connect(CALL_SERVICE_NAME,
CALL_SERVICE_PATH,
CALL_SERVICE_INTERFACE,
CALL_SIGNAL_INCOMING,
this,
SLOT(incomingCall(QDBusObjectPath, QString)));
systemBus_.connect(CALL_SERVICE_NAME,
CALL_SERVICE_PATH,
CALL_SERVICE_INTERFACE,
CALL_SIGNAL_RELEASE,
this,
SLOT(callTerminate()));
site_ = Eniro::stringToSite(Settings::instance()->get("site"));
connectionName_ = Settings::instance()->get("connection");
autoconnect_ = (Settings::instance()->get("autoconnect") == "1");
Settings::close();
qDebug() << "Starting...";
}
void CallListener::end()
{
systemBus_.disconnect(CALL_SERVICE_NAME,
CALL_SERVICE_PATH,
CALL_SERVICE_INTERFACE,
CALL_SIGNAL_INCOMING,
this,
SLOT(incomingCall(QDBusObjectPath, QString)));
systemBus_.disconnect(CALL_SERVICE_NAME,
CALL_SERVICE_PATH,
CALL_SERVICE_INTERFACE,
CALL_SIGNAL_RELEASE,
this,
SLOT(callTerminate()));
searchClose();
}
void CallListener::search(Eniro::SearchDetails const& details)
{
qDebug() << "Search called";
searchInit();
Eniro::Result result;
if(Cache::instance().findItem(details.query, result))
{
qDebug() << "Found from cache";
showDelayedResult(createResult(result.name,
result.street,
result.city), BANNER_DELAY);
}
else
{
retries_ = 0;
currentSearch_ = details.query;
showDelayedResult(tr("Searching..."), BANNER_DELAY);
if(!handleConnection())
{
qDebug() << "Unable to connect";
return;
}
qDebug() << "Starting to search...";
eniro_->search(details);
}
}
void CallListener::requestFinished(QVector const& results,
Eniro::SearchDetails const& details,
bool error)
{
// If box is not visible, the call must have been terminated already
if(!initialized_ || !box_->isVisible())
{
return;
}
QString message;
if(error)
{
qDebug() << "Error: " << eniro_->errorString();
if(retries_ < NUMBER_OF_RETRIES && retries_ >= 0)
{
retries_++;
eniro_->search(Eniro::SearchDetails(currentSearch_));
return;
}
else
{
timedMessage_ = "";
showError(tr("Search failed:") + " " + eniro_->errorString() + ".");
}
}
else
{
timedMessage_ = "";
if(results.size() == 0)
{
message = tr("Phone number was not found");
showResult(message);
}
else
{
message = createResult(results.at(0).name, results.at(0).street,
results.at(0).city);
showResult(message);
Eniro::Result result = results.at(0);
result.number = details.query;
Cache::instance().addItem(result);
}
}
retries_ = -1;
currentSearch_ = "";
if(closeConnection_ && connectionManager_)
{
connectionManager_->disconnect(true);
closeConnection_ = false;
}
}
QString CallListener::createResult(QString const& name, QString const& street, QString const& city)
{
QString result = "" + name + "";
if(!street.isEmpty() || !city.isEmpty())
{
result += "
";
if(!street.isEmpty())
{
result += street + ", ";
}
result += city;
}
return result;
}
void CallListener::showResult(QString const& text)
{
if(!initialized_)
{
return;
}
label_->setText("" + text + "");
if(box_->isVisible())
{
box_->hide();
}
box_->show();
}
void CallListener::incomingCall(QDBusObjectPath path, QString number)
{
qDebug() << "Incoming: " << number;
ContactManager cm;
if(!cm.numberExists(number))
{
qDebug() << "Number doesn't exist";
systemBus_.connect(CALL_SERVICE_NAME,
path.path(),
CALL_SERVICE_INSTANCE_NAME,
CALL_SIGNAL_TERMINATED,
this,
SLOT(callTerminate()));
search(Eniro::SearchDetails(number));
}
else
{
qDebug() << "Number exists";
}
}
void CallListener::callTerminate()
{
if(initialized_ && box_ && box_->isVisible())
{
box_->hide();
}
if(closeConnection_ && connectionManager_)
{
connectionManager_->disconnect(true);
closeConnection_ = false;
}
searchClose();
}
void CallListener::showDelayedResult(QString const& text, int delay)
{
timedMessage_ = text;
QTimer::singleShot(delay, this, SLOT(showTimedMessage()));
}
void CallListener::showTimedMessage()
{
if(timedMessage_.size() == 0 || !initialized_)
{
return;
}
showResult(timedMessage_);
timedMessage_ = "";
}
void CallListener::searchInit()
{
qDebug() << "Initializing search...";
if(initialized_)
{
qDebug() << "Already initialized";
return;
}
connectionManager_ = new ConnectionManager;
eniro_ = new Eniro(site_);
eniro_->setMaxResults(1);
eniro_->setFindNumber(false);
eniro_->setTimeout(REQUEST_TIMEOUT);
connect(eniro_, SIGNAL(requestFinished(QVector const&,
Eniro::SearchDetails const&, bool)),
this, SLOT(requestFinished(QVector const&,
Eniro::SearchDetails const&, bool)));
box_ = new InformationBox;
label_ = new QLabel("", box_);
label_->setMargin(8);
box_->setWidget(label_);
initialized_ = true;
}
void CallListener::searchClose()
{
initialized_ = false;
qDebug() << "Closing search...";
if(eniro_)
{
disconnect(eniro_, SIGNAL(requestFinished(QVector const&,
Eniro::SearchDetails const&, bool)),
this, SLOT(requestFinished(QVector const&,
Eniro::SearchDetails const&, bool)));
}
delete connectionManager_;
connectionManager_ = 0;
delete eniro_;
eniro_ = 0;
delete box_;
box_ = 0;
label_ = 0;
}
bool CallListener::handleConnection()
{
if(!connectionManager_)
{
qDebug() << "Error: connection manager not initialized";
return false;
}
if(connectionManager_->isConnected())
{
closeConnection_ = false;
return true;
}
closeConnection_ = true;
int retries = 0;
if(autoconnect_)
{
QString conn;
if(connectionName_.size() != 0 && connectionName_ != "0")
{
conn = connectionName_;
}
else
{
ConnectionManager::Connection best;
if(!connectionManager_->getBestConnection(best))
{
showError(tr("No network connections found."));
return false;
}
conn = best.id;
}
while(retries < CONNECT_RETRIES)
{
if(connectionManager_->connect(conn))
{
break;
}
else if(connectionManager_->error() == ConnectionManager::INVALID_IAP)
{
showError(tr("Selected access point doesn't exist."));
return false;
}
retries++;
}
}
else
{
while(retries < CONNECT_RETRIES)
{
if(connectionManager_->connect())
{
break;
}
else
{
qDebug() << "Automatic connection failed";
}
retries++;
}
}
if(retries >= CONNECT_RETRIES)
{
ConnectionManager::NetworkMode mode = connectionManager_->getNetworkMode();
if(mode != ConnectionManager::NETWORK_3G &&
mode != ConnectionManager::NETWORK_3_5G)
{
showError(tr("No 3G or WLAN network available."));
}
else
{
showError(tr("Unable to connect to network."));
}
return false;
}
return true;
}
void CallListener::showError(QString const& msg)
{
qDebug() << "Error: " << msg;
box_->setTimeout(ERROR_BANNER_TIMEOUT);
showResult(msg);
}