summaryrefslogtreecommitdiff
path: root/saltoqd
diff options
context:
space:
mode:
authorJavier <dev.git@javispedro.com>2015-03-29 04:45:23 +0200
committerJavier <dev.git@javispedro.com>2015-03-29 04:45:23 +0200
commit4b508d6344f76ce69055ee8eb79bf43cc89ad69c (patch)
treed565a32595b34e7ef42906bc2348d91122cad911 /saltoqd
parenta1a3ea825275671b105f5c0417e25a3c0a59ed25 (diff)
downloadsaltoq-4b508d6344f76ce69055ee8eb79bf43cc89ad69c.tar.gz
saltoq-4b508d6344f76ce69055ee8eb79bf43cc89ad69c.zip
support recent comms and contacts
Diffstat (limited to 'saltoqd')
-rw-r--r--saltoqd/commmanager.cpp164
-rw-r--r--saltoqd/commmanager.h5
-rw-r--r--saltoqd/contactsmanager.cpp111
-rw-r--r--saltoqd/contactsmanager.h31
-rw-r--r--saltoqd/obexconnection.cpp11
-rw-r--r--saltoqd/obexconnection.h1
-rw-r--r--saltoqd/saltoqd.pro10
-rw-r--r--saltoqd/storagemanager.cpp2
-rw-r--r--saltoqd/toqmanager.cpp10
-rw-r--r--saltoqd/toqmanager.h2
10 files changed, 295 insertions, 52 deletions
diff --git a/saltoqd/commmanager.cpp b/saltoqd/commmanager.cpp
index dc17e7d..f54bb89 100644
--- a/saltoqd/commmanager.cpp
+++ b/saltoqd/commmanager.cpp
@@ -1,17 +1,19 @@
#include <QtCore/QJsonArray>
+#include <CommHistory/ConversationModel>
+#include "contactsmanager.h"
#include "commmanager.h"
using namespace CommHistory;
static const int RECORD_LIMIT = 20;
+static const int PER_GROUP_LIMIT = 10;
-CommManager::CommManager(StorageManager *storage, ToqManager *toq) :
- QObject(toq), _toq(toq), _storage(storage),
+CommManager::CommManager(StorageManager *storage, ContactsManager *contacts, ToqManager *toq) :
+ QObject(toq), _toq(toq), _contacts(contacts), _storage(storage),
_calls(new CallModel(this)),
_convs(new GroupModel(this)),
_refreshTimer(new QTimer(this))
{
- _calls->setTreeMode(false);
_calls->setQueryMode(EventModel::AsyncQuery);
_calls->setSorting(CallModel::SortByTime);
_calls->setResolveContacts(true);
@@ -21,7 +23,7 @@ CommManager::CommManager(StorageManager *storage, ToqManager *toq) :
_convs->setLimit(RECORD_LIMIT);
_refreshTimer->setSingleShot(true);
- _refreshTimer->setInterval(1000);
+ _refreshTimer->setInterval(2000);
connect(_calls, SIGNAL(modelReady(bool)),
this, SLOT(scheduleRefresh()));
@@ -34,6 +36,12 @@ CommManager::CommManager(StorageManager *storage, ToqManager *toq) :
connect(_convs, SIGNAL(modelReady(bool)),
this, SLOT(scheduleRefresh()));
+ connect(_convs, SIGNAL(modelReset()),
+ this, SLOT(scheduleRefresh()));
+ connect(_convs, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(scheduleRefresh()));
+ connect(_convs, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(scheduleRefresh()));
connect(_refreshTimer, &QTimer::timeout,
this, &CommManager::refresh);
@@ -60,60 +68,150 @@ void CommManager::refresh()
int rows = _calls->rowCount();
for (int i = 0; i < rows; i++) {
- Event e = _calls->event(i);
+ QModelIndex index = _calls->index(i, 0);
+ Event e = _calls->event(index);
+ QList<Event::Contact> contacts = e.contacts();
+ QString name;
+ if (!contacts.empty()) {
+ name = contacts.first().second;
+ }
+ if (name.isEmpty()) {
+ name = e.remoteUid();
+ }
+ if (name.isEmpty()) {
+ name = tr("Private number");
+ }
QDateTime dt = e.startTime();
QJsonObject obj;
- obj.insert("Name", e.contactName());
- obj.insert("ContactId", QJsonValue());
+ obj.insert("Name", name);
+ obj.insert("ContactId", _contacts->getRecordIdForContact(e.contactId()));
+
QJsonArray records;
- QJsonObject record;
- record.insert("CommsType", QLatin1String("Call"));
- record.insert("ReceivedTime", qint64(dt.toTime_t()));
- record.insert("CallerId", e.contactName());
- record.insert("ItemId", e.id());
- QJsonObject details;
- details.insert("Duration", e.startTime().secsTo(e.endTime()));
- details.insert("PhoneType", QLatin1String("Other")); // TODO
- switch (e.direction()) {
- case Event::Inbound:
- details.insert("Direction", QLatin1String("Incoming"));
- break;
- case Event::Outbound:
- details.insert("Direction", QLatin1String("Outgoing"));
- break;
- default:
- details.insert("Direction", QLatin1String("Unknown"));
- break;
+ if (_calls->hasChildren(index)) {
+ const int subrows = _calls->rowCount(index);
+ for (int j = 0; j < subrows; j++) {
+ QModelIndex index2 = _calls->index(j, 0, index);
+ const Event e = _calls->event(index2);
+ QJsonObject record;
+ record.insert("CommsType", QLatin1String("Call"));
+ record.insert("ReceivedTime", qint64(e.startTime().toTime_t()));
+ record.insert("CallerId", e.remoteUid());
+ record.insert("ItemId", e.id());
+ QJsonObject details;
+ details.insert("Duration", e.startTime().secsTo(e.endTime()));
+ details.insert("PhoneType", QLatin1String("Other")); // TODO
+ switch (e.direction()) {
+ case Event::Inbound:
+ details.insert("Direction", QLatin1String("Incoming"));
+ break;
+ case Event::Outbound:
+ details.insert("Direction", QLatin1String("Outgoing"));
+ break;
+ default:
+ details.insert("Direction", QLatin1String("Unknown"));
+ break;
+ }
+ details.insert("IsMissedCall", e.isMissedCall());
+ record.insert("CommsDetails", details);
+ records.append(record);
+ }
}
- details.insert("IsMissedCall", e.isMissedCall());
- record.insert("CommsDetails", details);
- records.append(record);
+
obj.insert("CommsRecords", records);
events.insert(dt, obj);
}
+ QScopedPointer<ConversationModel> conv(new ConversationModel);
+ conv->setTreeMode(false);
+ conv->setLimit(PER_GROUP_LIMIT);
+ conv->setQueryMode(EventModel::SyncQuery);
+
rows = _convs->rowCount();
for (int i = 0; i < rows; i++) {
Group g = _convs->group(_convs->index(i, 0));
- qDebug() << "Chat" << g.contactName();
+
+ QList<Event::Contact> contacts = g.contacts();
+ QString name;
+ if (!contacts.empty()) {
+ name = contacts.first().second;
+ }
+ if (name.isEmpty() && !g.remoteUids().isEmpty()) {
+ name = g.remoteUids().first();
+ }
+ if (name.isEmpty()) {
+ name = tr("Unknown contact");
+ }
+
+ QJsonObject obj;
+ obj.insert("Name", name);
+ obj.insert("ContactId", _contacts->getRecordIdForContact(g.contactId()));
+
+ QJsonArray records;
+
+ if (conv->getEvents(g.id())) {
+ const int subrows = conv->rowCount();
+ for (int j = 0; j < subrows; j++) {
+ Event e = conv->event(j);
+ QJsonObject record;
+ record.insert("CommsType", QLatin1String("Text"));
+ record.insert("ReceivedTime", qint64(e.startTime().toTime_t()));
+ record.insert("CallerId", e.remoteUid());
+ record.insert("ItemId", e.id());
+ QJsonObject details;
+ details.insert("Message", e.freeText());
+ details.insert("privileged", int(0)); // TODO
+ switch (e.direction()) {
+ case Event::Inbound:
+ details.insert("Direction", int(1));
+ break;
+ case Event::Outbound:
+ details.insert("Direction", int(2));
+ break;
+ default:
+ details.insert("Direction", int(0));
+ break;
+ }
+ details.insert("IsRead", e.isRead());
+ record.insert("CommsDetails", details);
+ records.append(record);
+ }
+ } else {
+ qWarning() << "Failed to get events for group id" << g.id();
+ QJsonObject record;
+ record.insert("CommsType", QLatin1String("Text"));
+ record.insert("ReceivedTime", qint64(g.startTime().toTime_t()));
+ record.insert("CallerId", g.remoteUids().first());
+ record.insert("ItemId", g.id());
+ QJsonObject details;
+ details.insert("Message", g.lastMessageText());
+ details.insert("privileged", int(0)); // TODO
+ details.insert("Direction", int(0));
+ details.insert("IsRead", g.unreadMessages() == 0);
+ record.insert("CommsDetails", details);
+ records.append(record);
+ }
+
+ obj.insert("CommsRecords", records);
+
+ events.insert(g.endTime(), obj);
}
QJsonArray records;
int i = 0;
- auto it = events.begin();
- while (it != events.end()) {
+ auto it = events.end();
+ while (it != events.begin()) {
+ --it;
+
QJsonObject record;
record.insert("RecordId", i);
record.insert("RecordPayload", it.value());
records.append(record);
- ++it;
if (++i >= RECORD_LIMIT) break;
}
-
QString storeName("Phub.Phone.RecentComms");
QJsonObject store;
store.insert("Name", storeName);
diff --git a/saltoqd/commmanager.h b/saltoqd/commmanager.h
index 05d2147..b4604bb 100644
--- a/saltoqd/commmanager.h
+++ b/saltoqd/commmanager.h
@@ -5,11 +5,13 @@
#include <CommHistory/CallModel>
#include <CommHistory/GroupModel>
+class ContactsManager;
+
class CommManager : public QObject
{
Q_OBJECT
public:
- explicit CommManager(StorageManager *storage, ToqManager *toq);
+ explicit CommManager(StorageManager *storage, ContactsManager *contacts, ToqManager *toq);
public slots:
void scheduleRefresh();
@@ -21,6 +23,7 @@ private slots:
private:
ToqManager *_toq;
+ ContactsManager *_contacts;
StorageManager *_storage;
CommHistory::CallModel *_calls;
diff --git a/saltoqd/contactsmanager.cpp b/saltoqd/contactsmanager.cpp
new file mode 100644
index 0000000..2bc79d2
--- /dev/null
+++ b/saltoqd/contactsmanager.cpp
@@ -0,0 +1,111 @@
+#include "contactsmanager.h"
+#include <QtContacts/QtContacts>
+#include <qtcontacts-extensions_impl.h>
+
+QTCONTACTS_USE_NAMESPACE
+
+ContactsManager::ContactsManager(StorageManager *storage, ToqManager *toq) :
+ QObject(toq), _toq(toq), _storage(storage),
+ _contacts(new QContactManager(this)),
+ _refreshTimer(new QTimer(this))
+{
+ connect(_contacts, &QContactManager::contactsAdded,
+ this, &ContactsManager::scheduleRefresh);
+ connect(_contacts, &QContactManager::dataChanged,
+ this, &ContactsManager::scheduleRefresh);
+
+ connect(_refreshTimer, &QTimer::timeout,
+ this, &ContactsManager::refresh);
+
+ _refreshTimer->setSingleShot(true);
+ _refreshTimer->setInterval(2000);
+ _refreshTimer->start();
+}
+
+qint64 ContactsManager::getRecordIdForContact(uint contactId)
+{
+ return contactId;
+}
+
+void ContactsManager::scheduleRefresh()
+{
+ if (!_refreshTimer->isActive()) {
+ _refreshTimer->start();
+ }
+}
+
+void ContactsManager::refresh()
+{
+ qDebug() << "Refreshing contacts";
+
+ QContactSortOrder order;
+ order.setBlankPolicy(QContactSortOrder::BlanksLast);
+ order.setCaseSensitivity(Qt::CaseInsensitive);
+ order.setDetailType(QContactDetail::TypeDisplayLabel, QContactDisplayLabel::FieldLabel);
+
+ QList<QContact> contacts = _contacts->contacts(order);
+
+ QJsonArray records;
+ for (const QContact &contact : contacts) {
+ QJsonObject payload;
+ QContactName cName = contact.detail<QContactName>();
+ QContactDisplayLabel cDisplay = contact.detail<QContactDisplayLabel>();
+ QContactFavorite cFav = contact.detail<QContactFavorite>();
+ QJsonObject name;
+ name.insert("Initial", cName.prefix());
+ name.insert("First", cName.firstName());
+ name.insert("Middle", cName.middleName());
+ name.insert("Last", cName.lastName());
+ name.insert("Display", cDisplay.label());
+ QJsonArray phones;
+ for (const QContactPhoneNumber &cPhone : contact.details<QContactPhoneNumber>()) {
+ QJsonObject phone;
+ QString type;
+ if (!cPhone.subTypes().isEmpty()) {
+ if (cPhone.subTypes().first() == QContactPhoneNumber::SubTypeMobile) {
+ type = "Mobile";
+ }
+ }
+ if (type.isEmpty() && !cPhone.contexts().isEmpty()) {
+ switch (cPhone.contexts().first()) {
+ case QContactDetail::ContextHome:
+ type = "Home";
+ break;
+ case QContactDetail::ContextWork:
+ type = "Work";
+ break;
+ default:
+ break;
+ }
+ }
+ if (type.isEmpty()) {
+ type = "Other";
+ }
+ phone.insert("Type", type);
+ phone.insert("Number", cPhone.number());
+ phones.append(phone);
+ }
+ payload.insert("Name", name);
+ payload.insert("PhoneNumber", phones);
+ payload.insert("IsFav", cFav.isFavorite());
+ QJsonObject record;
+ record.insert("RecordId", getRecordIdForContact(QtContactsSqliteExtensions::internalContactId(contact.id())));
+ record.insert("RecordPayload", payload);
+ records.append(record);
+ }
+
+ QString storeName("Phub.Phone.Contacts");
+ QJsonObject store;
+ store.insert("Name", storeName);
+ store.insert("Records", records);
+
+ QJsonObject root;
+ root.insert("DataStore", store);
+
+ QJsonDocument doc(root);
+ qDebug() << doc.toJson();
+
+ _storage->updateStore(storeName, root);
+
+ emit changed();
+}
diff --git a/saltoqd/contactsmanager.h b/saltoqd/contactsmanager.h
new file mode 100644
index 0000000..0b39d40
--- /dev/null
+++ b/saltoqd/contactsmanager.h
@@ -0,0 +1,31 @@
+#ifndef CONTACTSMANAGER_H
+#define CONTACTSMANAGER_H
+
+#include <QtContacts/QContactManager>
+#include "storagemanager.h"
+
+class ContactsManager : public QObject
+{
+ Q_OBJECT
+public:
+ explicit ContactsManager(StorageManager *storage, ToqManager *toq);
+
+ qint64 getRecordIdForContact(uint contactId);
+
+public slots:
+ void scheduleRefresh();
+
+signals:
+ void changed();
+
+private slots:
+ void refresh();
+
+private:
+ ToqManager *_toq;
+ StorageManager *_storage;
+ QtContacts::QContactManager *_contacts;
+ QTimer *_refreshTimer;
+};
+
+#endif // CONTACTSMANAGER_H
diff --git a/saltoqd/obexconnection.cpp b/saltoqd/obexconnection.cpp
index 28aa4e2..5fab0ab 100644
--- a/saltoqd/obexconnection.cpp
+++ b/saltoqd/obexconnection.cpp
@@ -7,13 +7,6 @@ ObexTransfer::ObexTransfer(obex_t *obex, obex_object_t *obj, QObject *parent) :
{
}
-ObexTransfer::~ObexTransfer()
-{
- if (_obj) {
- OBEX_ObjectDelete(_obex, _obj);
- }
-}
-
void ObexTransfer::cancel()
{
// TODO
@@ -21,8 +14,10 @@ void ObexTransfer::cancel()
ObexConnection::ObexConnection(ToqConnection *conn, QObject *parent) :
QObject(parent), _conn(conn),
+ _socket(0),
_reconnectTimer(new QTimer(this)),
- _obex(0), _connected(false), _busy(false)
+ _obex(0),
+ _connected(false), _busy(false)
{
connect(_conn, &ToqConnection::connected,
this, &ObexConnection::handleToqConnected);
diff --git a/saltoqd/obexconnection.h b/saltoqd/obexconnection.h
index 431af9b..45345c9 100644
--- a/saltoqd/obexconnection.h
+++ b/saltoqd/obexconnection.h
@@ -16,7 +16,6 @@ class ObexTransfer : public QObject
friend class ObexConnection;
explicit ObexTransfer(obex_t *obex, obex_object_t *obj, QObject *parent);
- ~ObexTransfer();
public slots:
void cancel();
diff --git a/saltoqd/saltoqd.pro b/saltoqd/saltoqd.pro
index 8b656ba..8661518 100644
--- a/saltoqd/saltoqd.pro
+++ b/saltoqd/saltoqd.pro
@@ -1,11 +1,11 @@
TEMPLATE = app
CONFIG += console
QT -= qml
-QT += dbus bluetooth
+QT += dbus bluetooth contacts
CONFIG += c++11 link_pkgconfig
-PKGCONFIG += zlib commhistory-qt5 openobex
+PKGCONFIG += zlib commhistory-qt5 openobex qtcontacts-sqlite-qt5-extensions
INCLUDEPATH += /usr/include/commhistory-qt5
SOURCES += main.cpp \
@@ -20,7 +20,8 @@ SOURCES += main.cpp \
voicecallmanager.cpp \
fmsmanager.cpp \
weathermanager.cpp \
- obexconnection.cpp
+ obexconnection.cpp \
+ contactsmanager.cpp
HEADERS += \
toqconnection.h \
@@ -34,7 +35,8 @@ HEADERS += \
voicecallmanager.h \
fmsmanager.h \
weathermanager.h \
- obexconnection.h
+ obexconnection.h \
+ contactsmanager.h
DBUS_ADAPTORS += org.freedesktop.Notifications.xml
diff --git a/saltoqd/storagemanager.cpp b/saltoqd/storagemanager.cpp
index fe53cd6..257faf1 100644
--- a/saltoqd/storagemanager.cpp
+++ b/saltoqd/storagemanager.cpp
@@ -101,8 +101,6 @@ void StorageManager::updateStore(const QString &storeName, const QJsonObject &js
QJsonDocument doc(json);
QByteArray data = doc.toJson(QJsonDocument::Compact);
- qDebug() << "Store" << storeName << ":" << QString::fromUtf8(data);
-
quint32 checksum = ToqConnection::checksum(data);
if (store.checksum != checksum) {
store.contents = data;
diff --git a/saltoqd/toqmanager.cpp b/saltoqd/toqmanager.cpp
index 27331da..3f850d1 100644
--- a/saltoqd/toqmanager.cpp
+++ b/saltoqd/toqmanager.cpp
@@ -7,10 +7,13 @@
#include "fmsmanager.h"
#include "storagemanager.h"
#include "musicmanager.h"
+#include "contactsmanager.h"
#include "commmanager.h"
#include "voicecallmanager.h"
#include "weathermanager.h"
+static const bool PROTO_DEBUG = true;
+
ToqManager::ToqManager(const QBluetoothAddress &address, QObject *parent) :
QObject(parent),
_conn(new ToqConnection(address, this)),
@@ -20,7 +23,8 @@ ToqManager::ToqManager(const QBluetoothAddress &address, QObject *parent) :
_fmsManager(new FmsManager(_obex, this)),
_storageManager(new StorageManager(_obex, this)),
_musicManager(new MusicManager(this)),
- _commManager(new CommManager(_storageManager, this)),
+ _contactsManager(new ContactsManager(_storageManager, this)),
+ _commManager(new CommManager(_storageManager, _contactsManager, this)),
_voiceCallManager(new VoiceCallManager(this)),
_weatherManager(new WeatherManager(_fmsManager, this))
{
@@ -40,7 +44,7 @@ void ToqManager::setEndpointListener(ToqConnection::Endpoint ep, EndpointHandler
void ToqManager::sendMessage(const ToqConnection::Message &msg)
{
- if (1) {
+ if (PROTO_DEBUG) {
QString json = QString::fromUtf8(msg.payload.toJson(QJsonDocument::Compact));
qDebug() << "Sending message to" << ToqConnection::nameOfEndpoint(msg.destination) << "from" << ToqConnection::nameOfEndpoint(msg.source) << "type" << msg.type << json;
}
@@ -73,7 +77,7 @@ void ToqManager::handleToqMessage(const ToqConnection::Message &msg)
{
EndpointHandler *handler = _handlers.value(msg.destination, 0);
- if (1) {
+ if (PROTO_DEBUG) {
QString json = QString::fromUtf8(msg.payload.toJson(QJsonDocument::Compact));
qDebug() << "Received message to" << ToqConnection::nameOfEndpoint(msg.destination) << "from" << ToqConnection::nameOfEndpoint(msg.destination) << "type" << msg.type << json;
}
diff --git a/saltoqd/toqmanager.h b/saltoqd/toqmanager.h
index d3265a8..b1fe4a5 100644
--- a/saltoqd/toqmanager.h
+++ b/saltoqd/toqmanager.h
@@ -11,6 +11,7 @@ class SystemManager;
class FmsManager;
class StorageManager;
class MusicManager;
+class ContactsManager;
class CommManager;
class VoiceCallManager;
class WeatherManager;
@@ -55,6 +56,7 @@ private:
FmsManager *_fmsManager;
StorageManager *_storageManager;
MusicManager *_musicManager;
+ ContactsManager *_contactsManager;
CommManager *_commManager;
VoiceCallManager *_voiceCallManager;
WeatherManager *_weatherManager;