fix perf issue #LINQT-2491)

start by looking for chat in list instead of recreating a chatcore for every event
do not create event log core if not handled
This commit is contained in:
Gaelle Braud 2026-04-15 16:39:54 +02:00
parent 7127e27278
commit 9e4d65a533
7 changed files with 127 additions and 28 deletions

View file

@ -212,12 +212,12 @@ void ChatCore::setSelf(const QSharedPointer<ChatCore> &me) {
const std::shared_ptr<const linphone::EventLog> &eventLog) {
if (mChatModel->getMonitor() != chatRoom) return;
if (!eventLog) return;
if (EventLogCore::isEventHandled(eventLog, chatRoom)) {
lDebug() << log().arg("EVENT LOG RECEIVED IN CHATROOM") << this << mChatModel->getTitle();
auto event = EventLogCore::create(eventLog, chatRoom);
if (event->isHandled()) {
mChatModelConnection->invokeToCore([this, event]() { emit eventsInserted({event}); });
}
mChatModelConnection->invokeToCore([this, event]() { emit lUpdateLastUpdatedTime(); });
mChatModelConnection->invokeToCore([this]() { emit lUpdateLastUpdatedTime(); });
});
// Chat messages
@ -322,6 +322,7 @@ void ChatCore::setSelf(const QSharedPointer<ChatCore> &me) {
mChatModelConnection->makeConnectToModel(
&ChatModel::chatMessageSending, [this](const std::shared_ptr<linphone::ChatRoom> &chatRoom,
const std::shared_ptr<const linphone::EventLog> &eventLog) {
lInfo() << "Chat message sending in chatroom" << this << mChatModel->getTitle();
auto event = EventLogCore::create(eventLog, chatRoom);
mChatModelConnection->invokeToCore([this, event]() { emit eventsInserted({event}); });
});

View file

@ -116,6 +116,11 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
auto currentAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
if (!currentAccount) {
mModelConnection->invokeToCore([this, chats]() {
for (auto &chat : getSharedList<ChatCore>()) {
if (chat) {
disconnectItem(chat);
}
}
beginResetModel();
mList.clear();
endResetModel();
@ -137,13 +142,13 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
}
mModelConnection->invokeToCore([this, chats]() {
mustBeInMainThread(getClassName());
beginResetModel();
mList.clear();
for (auto &chat : getSharedList<ChatCore>()) {
if (chat) {
disconnectItem(chat);
}
}
beginResetModel();
mList.clear();
for (auto &chat : *chats) {
connectItem(chat);
mList.append(chat);
@ -184,8 +189,15 @@ void ChatList::setSelf(QSharedPointer<ChatList> me) {
lInfo() << log().arg("Chat room to add does not match the current filter, return");
return;
}
auto identifier = Utils::coreStringToAppString(room->getIdentifier());
auto chatList = getSharedList<ChatCore>();
auto it = std::find_if(chatList.begin(), chatList.end(), [identifier](const QSharedPointer<ChatCore> item) {
return item && item->getIdentifier() == identifier;
});
if (it == chatList.end()) {
auto chatCore = ChatCore::create(room);
mModelConnection->invokeToCore([this, chatCore, sendAddSignal] { addChatInList(chatCore, sendAddSignal); });
}
};
mModelConnection->makeConnectToModel(
&CoreModel::messageReceived,
@ -239,17 +251,19 @@ int ChatList::findChatIndex(ChatGui *chatGui) {
return it == chatList.end() ? -1 : std::distance(chatList.begin(), it);
}
QSharedPointer<ChatCore> ChatList::findChatById(const QString &id) {
auto chatList = getSharedList<ChatCore>();
auto it = std::find_if(chatList.begin(), chatList.end(),
[id](const QSharedPointer<ChatCore> item) { return item->getIdentifier() == id; });
return it == chatList.end() ? nullptr : *it;
}
bool ChatList::addChatInList(QSharedPointer<ChatCore> chatCore, bool emitAddSignal) {
mustBeInMainThread(log().arg(Q_FUNC_INFO));
if (chatCore->getIdentifier().isEmpty()) {
lWarning() << "ChatRoom with invalid identifier cannot be added to the list, return";
return false;
}
auto chatList = getSharedList<ChatCore>();
auto it = std::find_if(chatList.begin(), chatList.end(), [chatCore](const QSharedPointer<ChatCore> item) {
return item && chatCore && item->getIdentifier() == chatCore->getIdentifier();
});
if (it == chatList.end()) {
connectItem(chatCore);
lInfo() << "Add ChatRoom" << chatCore->getTitle();
add(chatCore);
@ -258,7 +272,6 @@ bool ChatList::addChatInList(QSharedPointer<ChatCore> chatCore, bool emitAddSign
emit chatAdded(chatCore);
}
return true;
}
return false;
}

View file

@ -43,6 +43,7 @@ public:
void disconnectItem(QSharedPointer<ChatCore> chat);
int findChatIndex(ChatGui *chat);
QSharedPointer<ChatCore> findChatById(const QString &id);
bool addChatInList(QSharedPointer<ChatCore> chatCore, bool emitAddSignal);
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;

View file

@ -171,3 +171,49 @@ void EventLogCore::computeEvent(const std::shared_ptr<const linphone::EventLog>
mHandled = false;
}
}
bool EventLogCore::isEventHandled(const std::shared_ptr<const linphone::EventLog> &eventLog,
const std::shared_ptr<linphone::ChatRoom> &chatRoom) {
mustBeInLinphoneThread("EventLogCore::isEventHandled");
auto handled = true;
auto participantAddress = eventLog->getParticipantAddress() ? eventLog->getParticipantAddress() : nullptr;
switch (eventLog->getType()) {
case linphone::EventLog::Type::ConferenceCreated:
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne) ||
!chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference))
handled = false;
break;
case linphone::EventLog::Type::ConferenceTerminated:
if (chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::OneToOne) ||
!chatRoom->hasCapability((int)linphone::ChatRoom::Capabilities::Conference))
handled = false;
break;
case linphone::EventLog::Type::ConferenceParticipantAdded:
break;
case linphone::EventLog::Type::ConferenceParticipantRemoved:
break;
case linphone::EventLog::Type::ConferenceSecurityEvent: {
if (eventLog->getSecurityEventType() != linphone::EventLog::SecurityEventType::SecurityLevelDowngraded) {
handled = false;
}
break;
}
case linphone::EventLog::Type::ConferenceEphemeralMessageEnabled:
break;
case linphone::EventLog::Type::ConferenceEphemeralMessageLifetimeChanged:
handled = eventLog->getEphemeralMessageLifetime() != 0; // Disabled is sent in case of 0.
break;
case linphone::EventLog::Type::ConferenceEphemeralMessageDisabled:
break;
case linphone::EventLog::Type::ConferenceSubjectChanged:
break;
case linphone::EventLog::Type::ConferenceParticipantSetAdmin:
break;
case linphone::EventLog::Type::ConferenceParticipantUnsetAdmin:
break;
default:
handled = false;
}
return handled;
}

View file

@ -73,6 +73,9 @@ public:
std::shared_ptr<EventLogModel> getModel() const;
static bool isEventHandled(const std::shared_ptr<const linphone::EventLog> &eventLog,
const std::shared_ptr<linphone::ChatRoom> &chatRoom);
private:
DECLARE_ABSTRACT_OBJECT
QString mEventId;

View file

@ -461,7 +461,12 @@ void Notifier::notifyReceivedMessages(const std::shared_ptr<linphone::ChatRoom>
}
}
auto chatCore = ChatCore::create(room);
auto chatCore =
App::getInstance()->getChatList()->findChatById(Utils::coreStringToAppString(room->getIdentifier()));
if (!chatCore) {
lWarning() << "chat was not found in chat list, create one";
chatCore = ChatCore::create(room);
}
App::postCoreAsync([this, txt, chatCore, remoteAddress]() {
mustBeInMainThread(getClassName());

View file

@ -1630,7 +1630,12 @@ VariantObject *Utils::getCurrentCallChat(CallGui *call) {
if (!callModel) return QVariant();
auto linphoneChatRoom = ToolModel::lookupCurrentCallChat(callModel);
if (linphoneChatRoom) {
auto chatCore = ChatCore::create(linphoneChatRoom);
auto chatCore = App::getInstance()->getChatList()->findChatById(
Utils::coreStringToAppString(linphoneChatRoom->getIdentifier()));
if (!chatCore) {
lWarning() << "Utils::getCurrentCallChat : chat was not found in chat list, create one";
chatCore = ChatCore::create(linphoneChatRoom);
}
return chatCore ? QVariant::fromValue(new ChatGui(chatCore)) : QVariant();
} else {
// Only try to create chatroom if 1-1 call
@ -1641,7 +1646,12 @@ VariantObject *Utils::getCurrentCallChat(CallGui *call) {
if (linphoneChatRoom != nullptr) {
lInfo() << "[Utils] Chatroom created with" << callModel->getRemoteAddress()->asStringUriOnly();
auto id = linphoneChatRoom->getIdentifier();
auto chatCore = ChatCore::create(linphoneChatRoom);
auto chatCore = App::getInstance()->getChatList()->findChatById(
Utils::coreStringToAppString(linphoneChatRoom->getIdentifier()));
if (!chatCore) {
lWarning() << "Utils::getCurrentCallChat : chat was not found in chat list, create one";
chatCore = ChatCore::create(linphoneChatRoom);
}
return chatCore ? QVariant::fromValue(new ChatGui(chatCore)) : QVariant();
} else {
lWarning() << "[Utils] Failed to create 1-1 conversation with"
@ -1663,14 +1673,24 @@ VariantObject *Utils::getChatForAddress(QString address) {
linAddr->clean();
auto linphoneChatRoom = ToolModel::lookupChatForAddress(linAddr);
if (linphoneChatRoom) {
auto chatCore = ChatCore::create(linphoneChatRoom);
auto chatCore = App::getInstance()->getChatList()->findChatById(
Utils::coreStringToAppString(linphoneChatRoom->getIdentifier()));
if (!chatCore) {
lWarning() << "Utils::getChatForAddress : chat was not found in chat list, create one";
chatCore = ChatCore::create(linphoneChatRoom);
}
return chatCore ? QVariant::fromValue(new ChatGui(chatCore)) : QVariant();
} else {
lInfo() << "[Utils] Did not find existing chat room, create one";
linphoneChatRoom = ToolModel::createChatForAddress(linAddr);
if (linphoneChatRoom != nullptr) {
lInfo() << "[Utils] Chatroom created with" << linAddr->asStringUriOnly();
auto chatCore = ChatCore::create(linphoneChatRoom);
auto chatCore = App::getInstance()->getChatList()->findChatById(
Utils::coreStringToAppString(linphoneChatRoom->getIdentifier()));
if (!chatCore) {
lWarning() << "Utils::getChatForAddress : chat was not found in chat list, create one";
chatCore = ChatCore::create(linphoneChatRoom);
}
return chatCore ? QVariant::fromValue(new ChatGui(chatCore)) : QVariant();
} else {
lWarning() << "[Utils] Failed to create 1-1 conversation with" << linAddr->asStringUriOnly() << "!";
@ -1700,7 +1720,12 @@ VariantObject *Utils::createGroupChat(QString subject, QStringList participantAd
}
auto linphoneChatRoom = ToolModel::createGroupChatRoom(subject, addresses);
if (linphoneChatRoom) {
auto chatCore = ChatCore::create(linphoneChatRoom);
auto chatCore = App::getInstance()->getChatList()->findChatById(
Utils::coreStringToAppString(linphoneChatRoom->getIdentifier()));
if (!chatCore) {
lWarning() << "Utils::createGroupChat : chat was not found in chat list, create one";
chatCore = ChatCore::create(linphoneChatRoom);
}
return chatCore ? QVariant::fromValue(new ChatGui(chatCore)) : QVariant();
} else {
return QVariant();
@ -1745,7 +1770,12 @@ VariantObject *Utils::getChatForCallLog(CallHistoryGui *callLog) {
if (!model) return QVariant();
auto chatRoom = model->getChatRoom();
if (!chatRoom) return QVariant();
auto chatCore = ChatCore::create(chatRoom);
auto chatCore =
App::getInstance()->getChatList()->findChatById(Utils::coreStringToAppString(chatRoom->getIdentifier()));
if (!chatCore) {
lWarning() << "Utils::getChatForCallLog : chat was not found in chat list, create one";
chatCore = ChatCore::create(chatRoom);
}
return chatCore ? QVariant::fromValue(new ChatGui(chatCore)) : QVariant();
});
data->requestValue();