| /* |
| * Copyright (C) 2020 by Savoir-faire Linux |
| * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> |
| * Author: Anthony L�onard <anthony.leonard@savoirfairelinux.com> |
| * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com> |
| * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> |
| * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> |
| * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> |
| * |
| * This program 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. |
| * |
| * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| #include "conversationsadapter.h" |
| |
| #include "utils.h" |
| |
| ConversationsAdapter::ConversationsAdapter(QObject *parent) |
| : QmlAdapterBase(parent) |
| {} |
| |
| ConversationsAdapter::~ConversationsAdapter() {} |
| |
| void |
| ConversationsAdapter::initQmlObject() |
| { |
| conversationSmartListModel_ = new SmartListModel(LRCInstance::getCurrAccId(), this); |
| |
| QMetaObject::invokeMethod(qmlObj_, "setModel", |
| Q_ARG(QVariant, QVariant::fromValue(conversationSmartListModel_))); |
| |
| connect(&LRCInstance::behaviorController(), |
| &BehaviorController::showChatView, |
| [this](const QString &accountId, lrc::api::conversation::Info convInfo) { |
| emit showChatView(accountId, convInfo.uid); |
| }); |
| connect(&LRCInstance::instance(), |
| &LRCInstance::currentAccountChanged, |
| this, |
| &ConversationsAdapter::slotAccountChanged); |
| |
| connectConversationModel(); |
| } |
| |
| void |
| ConversationsAdapter::slotAccountChanged() |
| { |
| connectConversationModel(); |
| } |
| |
| void |
| ConversationsAdapter::backToWelcomePage() |
| { |
| deselectConversation(); |
| QMetaObject::invokeMethod(qmlObj_, "backToWelcomePage"); |
| } |
| |
| void |
| ConversationsAdapter::selectConversation(const QString &accountId, |
| const QString &convUid, |
| bool preventSendingSignal) |
| { |
| auto &accInfo = LRCInstance::getAccountInfo(accountId); |
| const auto convInfo = accInfo.conversationModel->getConversationForUID(convUid); |
| |
| selectConversation(convInfo, preventSendingSignal); |
| } |
| |
| void |
| ConversationsAdapter::selectConversation(const QString &convUid) |
| { |
| auto* convModel = LRCInstance::getCurrentConversationModel(); |
| if (convModel == nullptr) { |
| return; |
| } |
| |
| const auto &conversation = convModel->getConversationForUID(convUid); |
| |
| if (selectConversation(conversation, false)) { |
| |
| // If it is calling, show callview (can use showChatView signal, since it will be determined on qml). |
| if (!conversation.uid.isEmpty() |
| && LRCInstance::getCurrentCallModel()->hasCall(conversation.callId)) { |
| emit showChatView(LRCInstance::getCurrAccId(), conversation.uid); |
| } |
| } |
| } |
| |
| bool |
| ConversationsAdapter::selectConversation(const lrc::api::conversation::Info &item, |
| bool preventSendingSignal) |
| { |
| // accInfo.conversationModel->selectConversation(item.uid) only emit ui |
| // behavior control signals, but sometimes we do not want that, |
| // preventSendingSignal boolean can help us to determine. |
| if (LRCInstance::getCurrentConvUid() == item.uid) { |
| return false; |
| } else if (item.participants.size() > 0) { |
| auto &accInfo = LRCInstance::getAccountInfo(item.accountId); |
| LRCInstance::setSelectedConvId(item.uid); |
| if (!preventSendingSignal) |
| accInfo.conversationModel->selectConversation(item.uid); |
| accInfo.conversationModel->clearUnreadInteractions(item.uid); |
| return true; |
| } |
| } |
| |
| void |
| ConversationsAdapter::deselectConversation() |
| { |
| if (LRCInstance::getCurrentConvUid().isEmpty()) { |
| return; |
| } |
| |
| auto currentConversationModel = LRCInstance::getCurrentConversationModel(); |
| |
| if (currentConversationModel == nullptr) { |
| return; |
| } |
| |
| currentConversationModel->selectConversation(""); |
| LRCInstance::setSelectedConvId(); |
| } |
| |
| void |
| ConversationsAdapter::accountChangedSetUp(const QString &accountId) |
| { |
| // Should be called when current account is changed. |
| auto &accountInfo = LRCInstance::accountModel().getAccountInfo(accountId); |
| currentTypeFilter_ = accountInfo.profileInfo.type; |
| LRCInstance::getCurrentConversationModel()->setFilter(accountInfo.profileInfo.type); |
| updateConversationsFilterWidget(); |
| |
| connectConversationModel(); |
| } |
| |
| void |
| ConversationsAdapter::updateConversationsFilterWidget() |
| { |
| // Update status of "Conversations" and "Invitations". |
| auto invites = LRCInstance::getCurrentAccountInfo().contactModel->pendingRequestCount(); |
| if (invites == 0 && currentTypeFilter_ == lrc::api::profile::Type::PENDING) { |
| currentTypeFilter_ = lrc::api::profile::Type::RING; |
| LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); |
| } |
| showConversationTabs(invites); |
| } |
| |
| void |
| ConversationsAdapter::setConversationFilter(const QString &type) |
| { |
| // Set conversation filter according to type, |
| // type needs to be recognizable by lrc::api::profile::to_type. |
| if (type.isEmpty()) { |
| if (LRCInstance::getCurrentAccountInfo().profileInfo.type == lrc::api::profile::Type::RING) |
| setConversationFilter(lrc::api::profile::Type::RING); |
| else |
| setConversationFilter(lrc::api::profile::Type::SIP); |
| } else { |
| setConversationFilter(lrc::api::profile::to_type(type)); |
| } |
| } |
| |
| void |
| ConversationsAdapter::setConversationFilter(lrc::api::profile::Type filter) |
| { |
| if (currentTypeFilter_ == filter) { |
| return; |
| } |
| currentTypeFilter_ = filter; |
| LRCInstance::getCurrentConversationModel()->setFilter(currentTypeFilter_); |
| } |
| |
| bool |
| ConversationsAdapter::connectConversationModel() |
| { |
| // Signal connections |
| auto currentConversationModel = LRCInstance::getCurrentConversationModel(); |
| |
| QObject::disconnect(modelSortedConnection_); |
| QObject::disconnect(modelUpdatedConnection_); |
| QObject::disconnect(filterChangedConnection_); |
| QObject::disconnect(newConversationConnection_); |
| QObject::disconnect(conversationRemovedConnection_); |
| QObject::disconnect(conversationClearedConnection); |
| QObject::disconnect(newInteractionConnection_); |
| QObject::disconnect(interactionRemovedConnection_); |
| QObject::disconnect(searchStatusChangedConnection_); |
| QObject::disconnect(searchResultUpdatedConnection_); |
| |
| modelSortedConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::modelSorted, |
| [this]() { |
| conversationSmartListModel_->fillConversationsList(); |
| updateConversationsFilterWidget(); |
| QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); |
| auto* convModel = LRCInstance::getCurrentConversationModel(); |
| const auto conversation = convModel->getConversationForUID(LRCInstance::getCurrentConvUid()); |
| |
| if (conversation.uid.isEmpty() || conversation.participants.isEmpty()) { |
| return; |
| } |
| const auto contactURI = conversation.participants[0]; |
| if (contactURI.isEmpty() |
| || convModel->owner.contactModel->getContact(contactURI).profileInfo.type |
| == lrc::api::profile::Type::TEMPORARY) { |
| return; |
| } |
| QMetaObject::invokeMethod(qmlObj_, "modelSorted", Q_ARG(QVariant, contactURI)); |
| }); |
| |
| modelUpdatedConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::conversationUpdated, |
| [this](const QString &convUid) { |
| conversationSmartListModel_->updateConversation(convUid); |
| updateConversationsFilterWidget(); |
| QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); |
| }); |
| |
| filterChangedConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::filterChanged, |
| [this]() { |
| conversationSmartListModel_->fillConversationsList(); |
| QMetaObject::invokeMethod(qmlObj_, |
| "updateSmartList", |
| Q_ARG(QVariant, LRCInstance::getCurrAccId())); |
| updateConversationsFilterWidget(); |
| QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); |
| }); |
| |
| newConversationConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::newConversation, |
| [this](const QString &convUid) { |
| conversationSmartListModel_->fillConversationsList(); |
| QMetaObject::invokeMethod(qmlObj_, |
| "updateSmartList", |
| Q_ARG(QVariant, LRCInstance::getCurrAccId())); |
| updateConversationForNewContact(convUid); |
| }); |
| |
| conversationRemovedConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::conversationRemoved, |
| [this]() { |
| conversationSmartListModel_->fillConversationsList(); |
| backToWelcomePage(); |
| }); |
| |
| conversationClearedConnection = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::conversationCleared, |
| [this](const QString &convUid) { |
| // If currently selected, switch to welcome screen (deselecting current smartlist item ). |
| if (convUid != LRCInstance::getCurrentConvUid()) { |
| return; |
| } |
| backToWelcomePage(); |
| }); |
| |
| newInteractionConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::newInteraction, |
| [this] { |
| conversationSmartListModel_->fillConversationsList(); |
| updateConversationsFilterWidget(); |
| QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); |
| }); |
| |
| searchStatusChangedConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::searchStatusChanged, |
| [this](const QString &status) { |
| emit showSearchStatus(status); |
| }); |
| |
| searchResultUpdatedConnection_ = QObject::connect(currentConversationModel, |
| &lrc::api::ConversationModel::searchResultUpdated, |
| [this]() { |
| conversationSmartListModel_->fillConversationsList(); |
| QMetaObject::invokeMethod(qmlObj_, "updateSmartList", |
| Q_ARG(QVariant, LRCInstance::getCurrAccId())); |
| QMetaObject::invokeMethod(qmlObj_, "updateConversationSmartListView"); |
| }); |
| |
| currentConversationModel->setFilter(""); |
| return true; |
| } |
| |
| void |
| ConversationsAdapter::updateConversationForNewContact(const QString &convUid) |
| { |
| auto* convModel = LRCInstance::getCurrentConversationModel(); |
| if (convModel == nullptr) { |
| return; |
| } |
| const auto selectedUid = LRCInstance::getCurrentConvUid(); |
| const auto conversation = convModel->getConversationForUID(convUid); |
| if (!conversation.uid.isEmpty() && !conversation.participants.isEmpty()) { |
| try { |
| const auto contact = convModel->owner.contactModel->getContact(conversation.participants[0]); |
| if (!contact.profileInfo.uri.isEmpty() && contact.profileInfo.uri == selectedUid) { |
| LRCInstance::setSelectedConvId(convUid); |
| convModel->selectConversation(convUid); |
| } |
| } catch (...) { |
| return; |
| } |
| } |
| } |