Changeset View
Changeset View
Standalone View
Standalone View
smsapp/conversationlistmodel.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | * This file is part of KDE Telepathy Chat | ||||
3 | * | ||||
4 | * Copyright (C) 2018 Aleix Pol Gonzalez <aleixpol@kde.org> | ||||
5 | * | ||||
6 | * This library is free software; you can redistribute it and/or | ||||
7 | * modify it under the terms of the GNU Lesser General Public | ||||
8 | * License as published by the Free Software Foundation; either | ||||
9 | * version 2.1 of the License, or (at your option) any later version. | ||||
10 | * | ||||
11 | * This library is distributed in the hope that it will be useful, | ||||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
14 | * Lesser General Public License for more details. | ||||
15 | * | ||||
16 | * You should have received a copy of the GNU Lesser General Public | ||||
17 | * License along with this library; if not, write to the Free Software | ||||
18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||||
19 | */ | ||||
20 | | ||||
21 | #include "conversationlistmodel.h" | ||||
22 | | ||||
23 | #include <QLoggingCategory> | ||||
24 | #include "interfaces/conversationmessage.h" | ||||
25 | | ||||
26 | Q_LOGGING_CATEGORY(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL, "kdeconnect.sms.conversations_list") | ||||
27 | | ||||
28 | ConversationListModel::ConversationListModel(QObject* parent) | ||||
29 | : QStandardItemModel(parent) | ||||
30 | , m_conversationsInterface(nullptr) | ||||
31 | { | ||||
32 | qCCritical(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "Constructing" << this; | ||||
33 | auto roles = roleNames(); | ||||
34 | roles.insert(FromMeRole, "fromMe"); | ||||
35 | roles.insert(AddressRole, "address"); | ||||
36 | roles.insert(PersonUriRole, "personUri"); | ||||
37 | roles.insert(ConversationIdRole, "conversationId"); | ||||
38 | roles.insert(DateRole, "date"); | ||||
39 | setItemRoleNames(roles); | ||||
40 | | ||||
41 | ConversationMessage::registerDbusType(); | ||||
42 | } | ||||
43 | | ||||
44 | ConversationListModel::~ConversationListModel() | ||||
45 | { | ||||
46 | } | ||||
47 | | ||||
48 | void ConversationListModel::setDeviceId(const QString& deviceId) | ||||
49 | { | ||||
50 | qCCritical(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "setDeviceId" << deviceId << "of" << this; | ||||
51 | if (deviceId == m_deviceId) | ||||
52 | return; | ||||
53 | | ||||
54 | if (m_conversationsInterface) { | ||||
55 | disconnect(m_conversationsInterface, SIGNAL(conversationCreated(QString)), this, SLOT(handleCreatedConversation(QString))); | ||||
56 | delete m_conversationsInterface; | ||||
57 | } | ||||
58 | | ||||
59 | m_deviceId = deviceId; | ||||
60 | m_conversationsInterface = new DeviceConversationsDbusInterface(deviceId, this); | ||||
61 | connect(m_conversationsInterface, SIGNAL(conversationCreated(QString)), this, SLOT(handleCreatedConversation(QString))); | ||||
62 | connect(m_conversationsInterface, SIGNAL(conversationMessageReceived(QVariantMap, int)), this, SLOT(createRowFromMessage(QVariantMap, int))); | ||||
63 | prepareConversationsList(); | ||||
64 | | ||||
65 | m_conversationsInterface->requestAllConversationThreads(); | ||||
66 | } | ||||
67 | | ||||
68 | void ConversationListModel::prepareConversationsList() | ||||
69 | { | ||||
70 | | ||||
71 | QDBusPendingReply<QStringList> validThreadIDsReply = m_conversationsInterface->activeConversations(); | ||||
72 | | ||||
73 | setWhenAvailable(validThreadIDsReply, [this](const QStringList& convs) { | ||||
74 | clear(); | ||||
75 | for (const QString& conversationId : convs) { | ||||
76 | handleCreatedConversation(conversationId); | ||||
77 | } | ||||
78 | }, this); | ||||
79 | } | ||||
80 | | ||||
81 | void ConversationListModel::handleCreatedConversation(const QString& conversationId) | ||||
82 | { | ||||
83 | m_conversationsInterface->requestConversation(conversationId, 0, 1); | ||||
84 | } | ||||
85 | | ||||
86 | void ConversationListModel::printDBusError(const QDBusError& error) | ||||
87 | { | ||||
88 | qCWarning(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << error; | ||||
89 | } | ||||
90 | | ||||
91 | QStandardItem * ConversationListModel::conversationForThreadId(qint32 threadId) | ||||
92 | { | ||||
93 | for(int i=0, c=rowCount(); i<c; ++i) { | ||||
94 | auto it = item(i, 0); | ||||
95 | if (it->data(ConversationIdRole) == threadId) | ||||
96 | return it; | ||||
97 | } | ||||
98 | return nullptr; | ||||
99 | } | ||||
100 | | ||||
101 | void ConversationListModel::createRowFromMessage(const QVariantMap& msg, int row) | ||||
102 | { | ||||
103 | if (row != 0) | ||||
104 | return; | ||||
105 | | ||||
106 | const ConversationMessage message(msg); | ||||
107 | if (message.type() == -1) | ||||
108 | { | ||||
109 | // The Android side currently hacks in -1 if something weird comes up | ||||
110 | // TODO: Remove this hack when MMS support is implemented | ||||
111 | return; | ||||
112 | } | ||||
113 | | ||||
114 | bool toadd = false; | ||||
115 | QStandardItem* item = conversationForThreadId(message.threadID()); | ||||
116 | if (!item) { | ||||
117 | toadd = true; | ||||
118 | item = new QStandardItem(); | ||||
119 | QScopedPointer<KPeople::PersonData> personData(lookupPersonByAddress(message.address())); | ||||
120 | if (personData) | ||||
121 | { | ||||
122 | item->setText(personData->name()); | ||||
123 | item->setIcon(QIcon(personData->photo())); | ||||
124 | item->setData(personData->personUri(), PersonUriRole); | ||||
125 | } | ||||
126 | else | ||||
127 | { | ||||
128 | item->setData(QString(), PersonUriRole); | ||||
129 | item->setText(message.address()); | ||||
130 | } | ||||
131 | item->setData(message.threadID(), ConversationIdRole); | ||||
132 | } | ||||
133 | item->setData(message.address(), AddressRole); | ||||
134 | item->setData(message.type() == ConversationMessage::MessageTypeSent, FromMeRole); | ||||
135 | item->setData(message.body(), Qt::ToolTipRole); | ||||
136 | item->setData(message.date(), DateRole); | ||||
137 | | ||||
138 | if (toadd) | ||||
139 | appendRow(item); | ||||
140 | } | ||||
141 | | ||||
142 | KPeople::PersonData* ConversationListModel::lookupPersonByAddress(const QString& address) | ||||
143 | { | ||||
144 | int rowIndex = 0; | ||||
145 | for (rowIndex = 0; rowIndex < m_people.rowCount(); rowIndex++) | ||||
146 | { | ||||
147 | const QString& uri = m_people.get(rowIndex, KPeople::PersonsModel::PersonUriRole).toString(); | ||||
148 | KPeople::PersonData* person = new KPeople::PersonData(uri); | ||||
149 | | ||||
150 | const QString& email = person->email(); | ||||
151 | const QString& phoneNumber = canonicalizePhoneNumber(person->contactCustomProperty("phoneNumber").toString()); | ||||
152 | | ||||
153 | if (address == email || canonicalizePhoneNumber(address) == phoneNumber) | ||||
154 | { | ||||
155 | qCDebug(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "Matched" << address << "to" << person->name(); | ||||
156 | return person; | ||||
157 | } | ||||
158 | | ||||
159 | delete person; | ||||
160 | } | ||||
161 | | ||||
162 | return nullptr; | ||||
163 | } | ||||
164 | | ||||
165 | QString ConversationListModel::canonicalizePhoneNumber(const QString& phoneNumber) | ||||
166 | { | ||||
167 | QString toReturn(phoneNumber); | ||||
168 | toReturn = toReturn.remove(' '); | ||||
169 | toReturn = toReturn.remove('-'); | ||||
170 | toReturn = toReturn.remove('('); | ||||
171 | toReturn = toReturn.remove(')'); | ||||
172 | toReturn = toReturn.remove('+'); | ||||
173 | return toReturn; | ||||
174 | } |