diff options
author | Matt Porter <mporter@konsulko.com> | 2018-06-25 11:01:11 -0400 |
---|---|---|
committer | Matt Porter <mporter@konsulko.com> | 2018-06-25 11:01:11 -0400 |
commit | 389b5994553fdae59d484068d542910efee79e9c (patch) | |
tree | d987b1aec2fed4da44e0b4776be4cea8dfde22be /pbap/pbap.cpp | |
parent | e8b328e0516d8ead9af13c8379a6cd1dbbb8a9e9 (diff) |
Reorg binding-specific modules into subdirectories
Move binding-specific code into per-binding subdirectories.
This separates the core message engine code and simplifies adding
new binding-specific modules.
Bug-AGL: SPEC-1525
Change-Id: I8fc545e3af375e2ed9e79a41363b7ade97e9b20a
Signed-off-by: Matt Porter <mporter@konsulko.com>
Diffstat (limited to 'pbap/pbap.cpp')
-rw-r--r-- | pbap/pbap.cpp | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/pbap/pbap.cpp b/pbap/pbap.cpp new file mode 100644 index 0000000..43db8bd --- /dev/null +++ b/pbap/pbap.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <QMetaEnum> +#include <QtQml/QQmlEngine> + +#include <vcard/vcard.h> + +#include "message.h" +#include "messageengine.h" +#include "pbap.h" +#include "pbapmessage.h" +#include "responsemessage.h" + +PhoneNumber::PhoneNumber(QString number, QString type) +{ + m_number = number; + m_type = stringToEnum(type); +} + +PhoneNumber::~PhoneNumber() +{ +} + +int PhoneNumber::stringToEnum(QString key) +{ + const QMetaObject* metaObject = PhoneNumber::metaObject(); + int enumIndex = metaObject->indexOfEnumerator("PhoneNumberType"); + QMetaEnum mEnum = metaObject->enumerator(enumIndex); + + int value = mEnum.keyToValue(key.toUtf8().data()); + return (value < 0) ? 0 : value; +} + +Contact::Contact(QString name, QList<QObject *>numbers) +{ + m_name = name; + m_numbers = numbers; +} + +Contact::~Contact() +{ +} + +RecentCall::RecentCall(QString name, QString number, QString datetime, QString type) +{ + m_name = name; + m_number = number; + m_datetime = datetime; + m_type = stringToEnum(type); +} + +RecentCall::~RecentCall() +{ +} + +int RecentCall::stringToEnum(QString key) +{ + const QMetaObject* metaObject = RecentCall::metaObject(); + int enumIndex = metaObject->indexOfEnumerator("RecentCallType"); + QMetaEnum mEnum = metaObject->enumerator(enumIndex); + + int value = mEnum.keyToValue(key.toUtf8().data()); + return (value < 0) ? 0 : value; +} + +Pbap::Pbap (QUrl &url, QQmlContext *context, QObject * parent) : + QObject(parent), + m_mloop(nullptr) +{ + m_mloop = new MessageEngine(url); + m_context = context; + m_context->setContextProperty("RecentCallModel", QVariant::fromValue(m_calls)); + qmlRegisterUncreatableType<RecentCall>("RecentCall", 1, 0, "RecentCall", "Enum"); + + QObject::connect(m_mloop, &MessageEngine::connected, this, &Pbap::onConnected); + QObject::connect(m_mloop, &MessageEngine::disconnected, this, &Pbap::onDisconnected); + QObject::connect(m_mloop, &MessageEngine::messageReceived, this, &Pbap::onMessageReceived); +} + +Pbap::~Pbap() +{ + delete m_mloop; +} + +void Pbap::refreshContacts(int max_entries) +{ + PbapMessage *tmsg = new PbapMessage(); + QJsonObject parameter; + + if (max_entries >= 0) + parameter.insert("max_entries", max_entries); + + tmsg->createRequest("contacts", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Pbap::refreshCalls(int max_entries) +{ + PbapMessage *tmsg = new PbapMessage(); + QJsonObject parameter; + + parameter.insert("list", "cch"); + if (max_entries >= 0) + parameter.insert("max_entries", max_entries); + + tmsg->createRequest("history", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Pbap::search(QString number) +{ + PbapMessage *tmsg = new PbapMessage(); + QJsonObject parameter; + + if (!number.isEmpty()) + parameter.insert("number", number); + parameter.insert("max_entries", 1); + + tmsg->createRequest("search", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); +} + +void Pbap::updateContacts(QString vcards) +{ + QString name, number, type; + + QList<vCard> contacts_vcards = vCard::fromByteArray(vcards.toUtf8()); + + for (auto vcard : contacts_vcards) { + vCardProperty name_prop = vcard.property(VC_FORMATTED_NAME); + QStringList values = name_prop.values(); + name = values.at(vCardProperty::DefaultValue); + /* + * libvcard has no member function to return a list of named + * properties, so we iterate over all properties and parse + * each identified VC_TELEPHONE property in the vCard. + */ + QList<QObject *> numbers; + vCardPropertyList properties = vcard.properties(); + for (auto property : properties) { + if (property.isValid() && (property.name() == VC_TELEPHONE)) { + QStringList values = property.values(); + number = values.at(0); + vCardParamList params = property.params(); + // The first parameter is always the phone number type + type = params.at(0).value(); + numbers.append(new PhoneNumber(number, type)); + } + } + m_contacts.append(new Contact(name, numbers)); + } + refreshCalls(100); +} + +#define VC_DATETIME "X-IRMC-CALL-DATETIME" + +void Pbap::updateCalls(QString vcards) +{ + QString name, number, datetime, type; + + QList<vCard> history_vcards = vCard::fromByteArray(vcards.toUtf8()); + + for (auto vcard : history_vcards) { + vCardProperty number_prop = vcard.property(VC_TELEPHONE); + if (number_prop.isValid()) { + QStringList values = number_prop.values(); + number = values.at(0); + } + vCardProperty name_prop = vcard.property(VC_FORMATTED_NAME); + QStringList values = name_prop.values(); + name = values.at(0); + // For calls with an empty name, fetch the name from contacts + if (name.isEmpty()) { + bool found = false; + for (auto contact_obj : m_contacts) { + Contact *contact = qobject_cast<Contact *>(contact_obj); + QList<QObject *>numbers = contact->numbers(); + for (auto number_obj : numbers) { + PhoneNumber *phone_number = qobject_cast<PhoneNumber *>(number_obj); + if (number.endsWith(phone_number->number())) { + name = contact->name(); + found = true; + break; + } + } + if (found == true) + break; + } + if (!found) + name = number; + } + vCardProperty datetime_prop = vcard.property(VC_DATETIME); + if (datetime_prop.isValid()) { + vCardParamList params = datetime_prop.params(); + QStringList values = datetime_prop.values(); + type = params.at(0).value(); + datetime = values.at(0); + // Convert the PBAP date/time to ISO 8601 format + datetime.insert(4, '-'); + datetime.insert(7, '-'); + datetime.insert(13, ':'); + datetime.insert(16, ':'); + } + m_calls.append(new RecentCall(name, number, datetime, type)); + } + + // Refresh model + m_context->setContextProperty("RecentCallModel", QVariant::fromValue(m_calls)); +} + +void Pbap::sendSearchResults(QJsonArray results) +{ + QString name; + + if (results.empty()) + name = "Not Found"; + else + name = results.at(0).toObject().value("name").toString(); + + emit searchResults(name); +} + +void Pbap::onConnected() +{ + QStringListIterator eventIterator(events); + PbapMessage *tmsg; + + while (eventIterator.hasNext()) { + tmsg = new PbapMessage(); + QJsonObject parameter; + parameter.insert("value", eventIterator.next()); + tmsg->createRequest("subscribe", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); + } +} + +void Pbap::onDisconnected() +{ + QStringListIterator eventIterator(events); + PbapMessage *tmsg; + + while (eventIterator.hasNext()) { + tmsg = new PbapMessage(); + QJsonObject parameter; + parameter.insert("value", eventIterator.next()); + tmsg->createRequest("unsubscribe", parameter); + m_mloop->sendMessage(tmsg); + tmsg->deleteLater(); + } +} + +void Pbap::onMessageReceived(MessageType type, Message *msg) +{ + if (msg->isEvent() && type == PbapEventMessage) { + PbapMessage *tmsg = qobject_cast<PbapMessage*>(msg); + + if (tmsg->isStatusEvent()) { + emit statusChanged(tmsg->connected()); + if (tmsg->connected() == true) { + refreshContacts(-1); + } + } + } else if (msg->isReply() && type == ResponseRequestMessage) { + ResponseMessage *tmsg = qobject_cast<ResponseMessage*>(msg); + + if (tmsg->requestVerb() == "contacts") { + updateContacts(tmsg->replyData().value("vcards").toString()); + } else if (tmsg->requestVerb() == "history") { + updateCalls(tmsg->replyData().value("vcards").toString()); + } else if (tmsg->requestVerb() == "search") { + sendSearchResults(tmsg->replyData().value("results").toArray()); + } + } + + msg->deleteLater(); +} |