Changeset View
Changeset View
Standalone View
Standalone View
smsapp/conversationlistmodel.cpp
Show All 17 Lines | |||||
18 | * License along with this library; if not, write to the Free Software | 18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | 20 | */ | ||
21 | 21 | | |||
22 | #include "conversationlistmodel.h" | 22 | #include "conversationlistmodel.h" | ||
23 | 23 | | |||
24 | #include <QLoggingCategory> | 24 | #include <QLoggingCategory> | ||
25 | #include "interfaces/conversationmessage.h" | 25 | #include "interfaces/conversationmessage.h" | ||
26 | #include "interfaces/dbusinterfaces.h" | ||||
26 | 27 | | |||
27 | Q_LOGGING_CATEGORY(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL, "kdeconnect.sms.conversations_list") | 28 | Q_LOGGING_CATEGORY(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL, "kdeconnect.sms.conversations_list") | ||
28 | 29 | | |||
29 | ConversationListModel::ConversationListModel(QObject* parent) | 30 | ConversationListModel::ConversationListModel(QObject* parent) | ||
30 | : QStandardItemModel(parent) | 31 | : QStandardItemModel(parent) | ||
31 | , m_conversationsInterface(nullptr) | 32 | , m_conversationsInterface(nullptr) | ||
32 | { | 33 | { | ||
33 | qCCritical(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "Constructing" << this; | 34 | qCDebug(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "Constructing" << this; | ||
34 | auto roles = roleNames(); | 35 | auto roles = roleNames(); | ||
35 | roles.insert(FromMeRole, "fromMe"); | 36 | roles.insert(FromMeRole, "fromMe"); | ||
36 | roles.insert(AddressRole, "address"); | 37 | roles.insert(AddressRole, "address"); | ||
37 | roles.insert(PersonUriRole, "personUri"); | 38 | roles.insert(PersonUriRole, "personUri"); | ||
38 | roles.insert(ConversationIdRole, "conversationId"); | 39 | roles.insert(ConversationIdRole, "conversationId"); | ||
39 | roles.insert(DateRole, "date"); | 40 | roles.insert(DateRole, "date"); | ||
40 | setItemRoleNames(roles); | 41 | setItemRoleNames(roles); | ||
41 | 42 | | |||
42 | ConversationMessage::registerDbusType(); | 43 | ConversationMessage::registerDbusType(); | ||
43 | } | 44 | } | ||
44 | 45 | | |||
45 | ConversationListModel::~ConversationListModel() | 46 | ConversationListModel::~ConversationListModel() | ||
46 | { | 47 | { | ||
47 | } | 48 | } | ||
48 | 49 | | |||
49 | void ConversationListModel::setDeviceId(const QString& deviceId) | 50 | void ConversationListModel::setDeviceId(const QString& deviceId) | ||
50 | { | 51 | { | ||
51 | qCCritical(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "setDeviceId" << deviceId << "of" << this; | 52 | if (deviceId == m_deviceId) { | ||
52 | if (deviceId == m_deviceId) | | |||
53 | return; | 53 | return; | ||
54 | } | ||||
55 | | ||||
56 | qCDebug(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "setDeviceId" << deviceId << "of" << this; | ||||
54 | 57 | | |||
55 | if (m_conversationsInterface) { | 58 | if (m_conversationsInterface) { | ||
56 | disconnect(m_conversationsInterface, SIGNAL(conversationCreated(QVariantMap)), this, SLOT(handleCreatedConversation(QVariantMap))); | 59 | disconnect(m_conversationsInterface, SIGNAL(conversationCreated(QVariantMap)), this, SLOT(handleCreatedConversation(QVariantMap))); | ||
57 | disconnect(m_conversationsInterface, SIGNAL(conversationUpdated(QVariantMap)), this, SLOT(handleConversationUpdated(QVariantMap))); | 60 | disconnect(m_conversationsInterface, SIGNAL(conversationUpdated(QVariantMap)), this, SLOT(handleConversationUpdated(QVariantMap))); | ||
58 | delete m_conversationsInterface; | 61 | delete m_conversationsInterface; | ||
59 | m_conversationsInterface = nullptr; | 62 | m_conversationsInterface = nullptr; | ||
60 | } | 63 | } | ||
61 | 64 | | |||
62 | m_deviceId = deviceId; | 65 | m_deviceId = deviceId; | ||
63 | 66 | | |||
64 | if (deviceId == "") { | 67 | // This method still gets called *with a valid deviceID* when the device is not connected while the component is setting up | ||
65 | // When the device is first connecting we get junk | 68 | // Detect that case and don't do anything. | ||
69 | DeviceDbusInterface device(deviceId); | ||||
70 | if (!(device.isValid() && device.isReachable())) { | ||||
sredman: What do you think about this being above the checks to delete m_conversationsInterface? That… | |||||
66 | return; | 71 | return; | ||
67 | } | 72 | } | ||
68 | 73 | | |||
69 | m_conversationsInterface = new DeviceConversationsDbusInterface(deviceId, this); | 74 | m_conversationsInterface = new DeviceConversationsDbusInterface(deviceId, this); | ||
70 | connect(m_conversationsInterface, SIGNAL(conversationCreated(QVariantMap)), this, SLOT(handleCreatedConversation(QVariantMap))); | 75 | connect(m_conversationsInterface, SIGNAL(conversationCreated(QVariantMap)), this, SLOT(handleCreatedConversation(QVariantMap))); | ||
71 | connect(m_conversationsInterface, SIGNAL(conversationUpdated(QVariantMap)), this, SLOT(handleConversationUpdated(QVariantMap))); | 76 | connect(m_conversationsInterface, SIGNAL(conversationUpdated(QVariantMap)), this, SLOT(handleConversationUpdated(QVariantMap))); | ||
72 | prepareConversationsList(); | 77 | prepareConversationsList(); | ||
73 | 78 | | |||
74 | m_conversationsInterface->requestAllConversationThreads(); | 79 | m_conversationsInterface->requestAllConversationThreads(); | ||
75 | } | 80 | } | ||
76 | 81 | | |||
77 | void ConversationListModel::prepareConversationsList() | 82 | void ConversationListModel::prepareConversationsList() | ||
78 | { | 83 | { | ||
79 | clear(); | 84 | if (!m_conversationsInterface->isValid()) { | ||
85 | qCWarning(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << "Tried to prepareConversationsList with an invalid interface!"; | ||||
86 | return; | ||||
87 | } | ||||
80 | QDBusPendingReply<QVariantList> validThreadIDsReply = m_conversationsInterface->activeConversations(); | 88 | QDBusPendingReply<QVariantList> validThreadIDsReply = m_conversationsInterface->activeConversations(); | ||
81 | 89 | | |||
82 | setWhenAvailable(validThreadIDsReply, [this](const QVariantList& convs) { | 90 | setWhenAvailable(validThreadIDsReply, [this](const QVariantList& convs) { | ||
91 | clear(); // If we clear before we receive the reply, there might be a (several second) visual gap! | ||||
83 | for (const QVariant& headMessage : convs) { | 92 | for (const QVariant& headMessage : convs) { | ||
84 | QDBusArgument data = headMessage.value<QDBusArgument>(); | 93 | QDBusArgument data = headMessage.value<QDBusArgument>(); | ||
85 | QVariantMap message; | 94 | QVariantMap message; | ||
86 | data >> message; | 95 | data >> message; | ||
87 | handleCreatedConversation(message); | 96 | handleCreatedConversation(message); | ||
88 | } | 97 | } | ||
89 | }, this); | 98 | }, this); | ||
90 | } | 99 | } | ||
91 | 100 | | |||
92 | void ConversationListModel::handleCreatedConversation(const QVariantMap& msg) | 101 | void ConversationListModel::handleCreatedConversation(const QVariantMap& msg) | ||
93 | { | 102 | { | ||
94 | createRowFromMessage(msg); | 103 | createRowFromMessage(msg); | ||
95 | } | 104 | } | ||
96 | 105 | | |||
97 | void ConversationListModel::handleConversationUpdated(const QVariantMap& msg) | 106 | void ConversationListModel::handleConversationUpdated(const QVariantMap& msg) | ||
98 | { | 107 | { | ||
99 | return; | 108 | createRowFromMessage(msg); | ||
apol: leave empty? | |||||
I left this here so I could put a breakpoint on it and decide what to do with the incoming data 😬 Working on filling out this method is my next to-do to solve bug 398818 sredman: I left this here so I could put a breakpoint on it and decide what to do with the incoming data… | |||||
100 | } | 109 | } | ||
101 | 110 | | |||
102 | void ConversationListModel::printDBusError(const QDBusError& error) | 111 | void ConversationListModel::printDBusError(const QDBusError& error) | ||
103 | { | 112 | { | ||
104 | qCWarning(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << error; | 113 | qCWarning(KDECONNECT_SMS_CONVERSATIONS_LIST_MODEL) << error; | ||
105 | } | 114 | } | ||
106 | 115 | | |||
107 | QStandardItem * ConversationListModel::conversationForThreadId(qint32 threadId) | 116 | QStandardItem * ConversationListModel::conversationForThreadId(qint32 threadId) | ||
Show All 26 Lines | 141 | if (personData) { | |||
134 | item->setIcon(QIcon(personData->photo())); | 143 | item->setIcon(QIcon(personData->photo())); | ||
135 | item->setData(personData->personUri(), PersonUriRole); | 144 | item->setData(personData->personUri(), PersonUriRole); | ||
136 | } else { | 145 | } else { | ||
137 | item->setData(QString(), PersonUriRole); | 146 | item->setData(QString(), PersonUriRole); | ||
138 | item->setText(message.address()); | 147 | item->setText(message.address()); | ||
139 | } | 148 | } | ||
140 | item->setData(message.threadID(), ConversationIdRole); | 149 | item->setData(message.threadID(), ConversationIdRole); | ||
141 | } | 150 | } | ||
151 | | ||||
152 | // Update the message if the data is newer | ||||
153 | // This will be true if a conversation receives a new message, but false when the user | ||||
154 | // does something to trigger past conversation history loading | ||||
155 | bool oldDateExists; | ||||
156 | qint64 oldDate = item->data(DateRole).toLongLong(&oldDateExists); | ||||
157 | if (!oldDateExists || message.date() >= oldDate) { | ||||
158 | // If there was no old data or incoming data is newer, update the record | ||||
142 | item->setData(message.address(), AddressRole); | 159 | item->setData(message.address(), AddressRole); | ||
143 | item->setData(message.type() == ConversationMessage::MessageTypeSent, FromMeRole); | 160 | item->setData(message.type() == ConversationMessage::MessageTypeSent, FromMeRole); | ||
144 | item->setData(message.body(), Qt::ToolTipRole); | 161 | item->setData(message.body(), Qt::ToolTipRole); | ||
145 | item->setData(message.date(), DateRole); | 162 | item->setData(message.date(), DateRole); | ||
163 | } | ||||
146 | 164 | | |||
147 | if (toadd) | 165 | if (toadd) | ||
148 | appendRow(item); | 166 | appendRow(item); | ||
149 | } | 167 | } | ||
150 | 168 | | |||
151 | KPeople::PersonData* ConversationListModel::lookupPersonByAddress(const QString& address) | 169 | KPeople::PersonData* ConversationListModel::lookupPersonByAddress(const QString& address) | ||
152 | { | 170 | { | ||
153 | int rowIndex = 0; | 171 | int rowIndex = 0; | ||
Show All 28 Lines |
What do you think about this being above the checks to delete m_conversationsInterface? That way, when the device is disconnected, you can still browse messages locally cached in the conversationDbusInterface.