diff --git a/linphone-app/CMakeLists.txt b/linphone-app/CMakeLists.txt index d882c9dd9..921ef4aff 100644 --- a/linphone-app/CMakeLists.txt +++ b/linphone-app/CMakeLists.txt @@ -126,6 +126,9 @@ set(SOURCES src/app/providers/ImageProvider.cpp src/app/providers/ExternalImageProvider.cpp src/app/providers/ThumbnailProvider.cpp + src/app/proxyModel/ProxyListModel.cpp + #src/app/proxyModel/ProxyMapModel.cpp + #src/app/proxyModel/ProxyModel.cpp src/app/translator/DefaultTranslator.cpp src/components/assistant/AssistantModel.cpp src/components/authentication/AuthenticationNotifier.cpp @@ -138,10 +141,11 @@ set(SOURCES src/components/chat/ChatModel.cpp src/components/chat-events/ChatCallModel.cpp src/components/chat-events/ChatEvent.cpp + src/components/chat-events/ChatMessageListener.cpp src/components/chat-events/ChatMessageModel.cpp src/components/chat-events/ChatNoticeModel.cpp + src/components/chat-room/ChatRoomListener.cpp src/components/chat-room/ChatRoomModel.cpp - src/components/chat-room/ChatRoomListModel.cpp src/components/chat-room/ChatRoomProxyModel.cpp src/components/codecs/AbstractCodecsModel.cpp src/components/codecs/AudioCodecsModel.cpp @@ -154,7 +158,7 @@ set(SOURCES src/components/conferenceInfo/ConferenceInfoListModel.cpp src/components/conferenceInfo/ConferenceInfoMapModel.cpp src/components/conferenceInfo/ConferenceInfoProxyModel.cpp - src/components/conferenceScheduler/ConferenceSchedulerModel.cpp + src/components/conferenceScheduler/ConferenceSchedulerHandler.cpp src/components/contact/ContactModel.cpp src/components/contact/VcardModel.cpp src/components/contacts/ContactsImporterModel.cpp @@ -243,6 +247,9 @@ set(HEADERS src/app/providers/ImageProvider.hpp src/app/providers/ExternalImageProvider.hpp src/app/providers/ThumbnailProvider.hpp + src/app/proxyModel/ProxyListModel.hpp + #src/app/proxyModel/ProxyMapModel.hpp + #src/app/proxyModel/ProxyModel.hpp src/app/single-application/SingleApplication.hpp src/app/translator/DefaultTranslator.hpp src/components/assistant/AssistantModel.hpp @@ -256,10 +263,11 @@ set(HEADERS src/components/chat/ChatModel.hpp src/components/chat-events/ChatCallModel.hpp src/components/chat-events/ChatEvent.hpp + src/components/chat-events/ChatMessageListener.hpp src/components/chat-events/ChatMessageModel.hpp src/components/chat-events/ChatNoticeModel.hpp + src/components/chat-room/ChatRoomListener.hpp src/components/chat-room/ChatRoomModel.hpp - src/components/chat-room/ChatRoomListModel.hpp src/components/chat-room/ChatRoomProxyModel.hpp src/components/codecs/AbstractCodecsModel.hpp src/components/codecs/AudioCodecsModel.hpp @@ -273,7 +281,7 @@ set(HEADERS src/components/conferenceInfo/ConferenceInfoListModel.hpp src/components/conferenceInfo/ConferenceInfoMapModel.hpp src/components/conferenceInfo/ConferenceInfoProxyModel.hpp - src/components/conferenceScheduler/ConferenceSchedulerModel.hpp + src/components/conferenceScheduler/ConferenceSchedulerHandler.hpp src/components/contact/ContactModel.hpp src/components/contact/VcardModel.hpp src/components/contacts/ContactsImporterModel.hpp diff --git a/linphone-app/src/app/App.cpp b/linphone-app/src/app/App.cpp index adbe37554..7ece3556d 100644 --- a/linphone-app/src/app/App.cpp +++ b/linphone-app/src/app/App.cpp @@ -607,14 +607,14 @@ void App::registerTypes () { qRegisterMetaType(); qRegisterMetaType>(); qRegisterMetaType > >(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); - qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); + qRegisterMetaType>(); //qRegisterMetaType>(); LinphoneEnums::registerMetaTypes(); diff --git a/linphone-app/src/app/logger/Logger.cpp b/linphone-app/src/app/logger/Logger.cpp index c62627189..26c2ed58b 100644 --- a/linphone-app/src/app/logger/Logger.cpp +++ b/linphone-app/src/app/logger/Logger.cpp @@ -164,6 +164,7 @@ void Logger::log (QtMsgType type, const QMessageLogContext &context, const QStri mMutex.lock(); fprintf(stdout, format, dateTime.constData(), QThread::currentThread(), contextStr, localMsg.constData()); + fflush(stdout); if( level == BCTBX_LOG_FATAL) QMessageBox::critical(nullptr, "Linphone will crash", msg); // Print an error message before sending msg to bctoolbox bctbx_log(Constants::QtDomain, level, "QT: %s%s", contextStr, localMsg.constData()); diff --git a/linphone-app/src/app/proxyModel/ProxyListModel.cpp b/linphone-app/src/app/proxyModel/ProxyListModel.cpp new file mode 100644 index 000000000..d7aea9f52 --- /dev/null +++ b/linphone-app/src/app/proxyModel/ProxyListModel.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#include "ProxyListModel.hpp" + +#include + +// ============================================================================= + +ProxyListModel::ProxyListModel (QObject *parent) : QAbstractListModel(parent) { +} + +int ProxyListModel::rowCount (const QModelIndex &) const { + return mList.count(); +} + +QHash ProxyListModel::roleNames () const { + QHash roles; + roles[Qt::DisplayRole] = "modelData"; + return roles; +} + +QVariant ProxyListModel::data (const QModelIndex &index, int role) const { + int row = index.row(); + + if (!index.isValid() || row < 0 || row >= mList.count()) + return QVariant(); + + if (role == Qt::DisplayRole) + return QVariant::fromValue(mList[row].get()); + + return QVariant(); +} + +QSharedPointer ProxyListModel::getAt(const int& index) const{ + return mList[index]; +} + +// ----------------------------------------------------------------------------- + +void ProxyListModel::add(QSharedPointer item){ + int row = mList.count(); + beginInsertRows(QModelIndex(), row, row); + mList << item; + endInsertRows(); +} + +void ProxyListModel::prepend(QSharedPointer item){ + mList.prepend(item); +} + +void ProxyListModel::prepend(QList> items){ + beginInsertRows(QModelIndex(), 0, items.size()-1); + items << mList; + mList = items; + endInsertRows(); +} + +bool ProxyListModel::remove(QObject *itemToRemove) { + bool removed = false; + qInfo() << QStringLiteral("Removing ") << itemToRemove->metaObject()->className() << QStringLiteral(" : ") << itemToRemove; + int index = 0; + for(auto item : mList) + if( item.get() == itemToRemove) { + removed = removeRow(index); + break; + }else + ++index; + if( !removed) + qWarning() << QStringLiteral("Unable to remove ") << itemToRemove->metaObject()->className() << QStringLiteral(" : ") << itemToRemove; + return removed; +} + +bool ProxyListModel::remove(QSharedPointer itemToRemove){ + return remove(itemToRemove.get()); +} + +bool ProxyListModel::removeRow (int row, const QModelIndex &parent) { + return removeRows(row, 1, parent); +} + +bool ProxyListModel::removeRows (int row, int count, const QModelIndex &parent) { + int limit = row + count - 1; + + if (row < 0 || count < 0 || limit >= mList.count()) + return false; + + beginRemoveRows(parent, row, limit); + + for (int i = 0; i < count; ++i) + mList.takeAt(row); + + endRemoveRows(); + + return true; +} + +void ProxyListModel::resetData(){ + beginResetModel(); + mList.clear(); + endResetModel(); +} +// ----------------------------------------------------------------------------- diff --git a/linphone-app/src/app/proxyModel/ProxyListModel.hpp b/linphone-app/src/app/proxyModel/ProxyListModel.hpp new file mode 100644 index 000000000..effe0b493 --- /dev/null +++ b/linphone-app/src/app/proxyModel/ProxyListModel.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#ifndef _PROXY_LIST_MODEL_H_ +#define _PROXY_LIST_MODEL_H_ + + +#include +#include + +// ============================================================================= + +class ProxyListModel : public QAbstractListModel { + Q_OBJECT + +public: + ProxyListModel (QObject *parent = Q_NULLPTR); + + virtual int rowCount (const QModelIndex &index = QModelIndex()) const override; + + virtual QHash roleNames () const override; + virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; + QSharedPointer getAt(const int& index) const; + + template + QList> getSharedList(){ + QList> newList; + for(auto item : mList) + newList << item.objectCast(); + return newList; + } +// Add functions + virtual void add(QSharedPointer item); + template + void add(QSharedPointer item){ + add(item.template objectCast()); + } + //virtual void add(QList> item); + + virtual void prepend(QSharedPointer item); + template + void prepend(QSharedPointer item){ + prepend(item.template objectCast()); + } + + virtual void prepend(QList> items); + template + void prepend(QList> items){ + beginInsertRows(QModelIndex(), 0, items.size()-1); + items << mList; + mList = items; + endInsertRows(); + } + +// Remove functions + Q_INVOKABLE virtual bool remove(QObject *itemToRemove) ; + virtual bool remove(QSharedPointer itemToRemove) ; + + virtual bool removeRow (int row, const QModelIndex &parent = QModelIndex()); + virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; + + + Q_INVOKABLE virtual void resetData(); + +protected: + QList> mList; + +}; + +#endif diff --git a/linphone-app/src/app/proxyModel/ProxyMapModel.cpp b/linphone-app/src/app/proxyModel/ProxyMapModel.cpp new file mode 100644 index 000000000..e53f111b9 --- /dev/null +++ b/linphone-app/src/app/proxyModel/ProxyMapModel.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2021 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#include "ConferenceInfoMapModel.hpp" + +#include +#include +#include + +#include "app/App.hpp" +#include "components/conference/ConferenceAddModel.hpp" +#include "components/conference/ConferenceHelperModel.hpp" +#include "components/core/CoreHandlers.hpp" +#include "components/core/CoreManager.hpp" +#include "components/settings/SettingsModel.hpp" +#include "utils/Utils.hpp" + +#include "ConferenceInfoProxyModel.hpp" +#include "ConferenceInfoListModel.hpp" +#include "ConferenceInfoModel.hpp" + +// ============================================================================= + +ConferenceInfoMapModel::ConferenceInfoMapModel (QObject *parent) : QAbstractListModel(parent) { + auto conferenceInfos = CoreManager::getInstance()->getCore()->getConferenceInformationList(); + auto me = CoreManager::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress(); + for(auto conferenceInfo : conferenceInfos){ + std::list> participants = conferenceInfo->getParticipants(); + bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me); + if(!haveMe) + haveMe = (std::find_if(participants.begin(), participants.end(), [me](const std::shared_ptr& address){ + return me->weakEqual(address); + }) != participants.end()); + if(haveMe){ + auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo ); + QDate t = conferenceInfoModel->getDateTime().date(); + if( !mMappedList.contains(t)) + mMappedList[t] = new ConferenceInfoProxyModel(new ConferenceInfoListModel(), this); + mMappedList[t]->add(conferenceInfoModel); + } + } +} + +int ConferenceInfoMapModel::rowCount (const QModelIndex &) const { + return mMappedList.size(); +} + +QHash ConferenceInfoMapModel::roleNames () const { + QHash roles; + roles[Qt::DisplayRole] = "modelData"; + roles[Qt::DisplayRole + 1] = "date"; + return roles; +} + +QVariant ConferenceInfoMapModel::data (const QModelIndex &index, int role) const { + int row = index.row(); + + if (!index.isValid() || row < 0 || row >= mMappedList.size()) + return QVariant(); + auto it = mMappedList.begin() + row; + + if (role == Qt::DisplayRole) + return QVariant::fromValue(*it); + else if( role == Qt::DisplayRole+1) + return QVariant::fromValue(it.key()); + + return QVariant(); +} + +// ----------------------------------------------------------------------------- + +void ConferenceInfoMapModel::setConferenceInfoFilter (int filterMode){ + for(auto list : mMappedList){ + list->setConferenceInfoFilter(filterMode); + } +} \ No newline at end of file diff --git a/linphone-app/src/components/chat-room/ChatRoomListModel.hpp b/linphone-app/src/app/proxyModel/ProxyMapModel.hpp similarity index 72% rename from linphone-app/src/components/chat-room/ChatRoomListModel.hpp rename to linphone-app/src/app/proxyModel/ProxyMapModel.hpp index 68fe0c747..92d8c38b3 100644 --- a/linphone-app/src/components/chat-room/ChatRoomListModel.hpp +++ b/linphone-app/src/app/proxyModel/ProxyMapModel.hpp @@ -18,34 +18,33 @@ * along with this program. If not, see . */ -#ifndef _CHAT_ROOM_LIST_MODEL_H_ -#define _CHAT_ROOM_LIST_MODEL_H_ +#ifndef _CONFERENCE_INFO_MAP_MODEL_H_ +#define _CONFERENCE_INFO_MAP_MODEL_H_ #include #include +#include // ============================================================================= -class ChatRoomModel; +class ConferenceInfoProxyModel; -class ChatRoomListModel : public QAbstractListModel { - Q_OBJECT; +class ConferenceInfoMapModel : public QAbstractListModel { + Q_OBJECT public: - ChatRoomListModel (QObject *parent = Q_NULLPTR); + ConferenceInfoMapModel (QObject *parent = Q_NULLPTR); int rowCount (const QModelIndex &index = QModelIndex()) const override; QHash roleNames () const override; QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; - + + Q_INVOKABLE void setConferenceInfoFilter (int filterMode); private: - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - - QList mList; + QMap mMappedList; }; - -#endif // _CHAT_ROOM_LIST_MODEL_H_ +Q_DECLARE_METATYPE(ConferenceInfoMapModel*) +#endif diff --git a/linphone-app/src/app/proxyModel/ProxyModel.cpp b/linphone-app/src/app/proxyModel/ProxyModel.cpp new file mode 100644 index 000000000..9734c7ff2 --- /dev/null +++ b/linphone-app/src/app/proxyModel/ProxyModel.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#include "ProxyModel.hpp" + +// ============================================================================= + +using namespace std; + +ProxyModel::ProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { + mFilterMode = 0; + sort(0, Qt::DescendingOrder); +} + +ProxyModel::ProxyModel (QAbstractItemModel * model, const int& defaultFilterMode, QObject *parent) : QSortFilterProxyModel(parent) { + mFilterMode = defaultFilterMode; + setSourceModel(model); + sort(0, Qt::DescendingOrder); +} + +int ProxyModel::getFilterMode () const { + return mFilterMode; +} + +void ProxyModel::setFilterMode (int filterMode) { + if (getFilterMode() != filterMode) { + mFilterMode = filterMode; + invalidate(); + emit filterModeChanged(filterMode); + } +} + +bool ProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const { + return true; +} + +bool ProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { + Q_UNUSED(left) + Q_UNUSED(right) + return true; +} + +QVariant ProxyModel::getAt(int row){ + QModelIndex sourceIndex = mapToSource(this->index(row, 0)); + return sourceModel()->data(sourceIndex); +} + +QAbstractItemModel *ProxyModel::getModel(){ + return sourceModel(); +} + +void ProxyModel::setModel(QAbstractItemModel * model){ + setSourceModel(model); + emit modelChanged(); +} + +void ProxyModel::add(std::shared_ptr model){ + emit added(model); +} \ No newline at end of file diff --git a/linphone-app/src/app/proxyModel/ProxyModel.hpp b/linphone-app/src/app/proxyModel/ProxyModel.hpp new file mode 100644 index 000000000..0ebe9d3fa --- /dev/null +++ b/linphone-app/src/app/proxyModel/ProxyModel.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#ifndef PROXY_MODEL_H_ +#define PROXY_MODEL_H_ + +#include +#include + +// ============================================================================= + +class ProxyModel : public QSortFilterProxyModel { + Q_OBJECT + +public: + Q_PROPERTY(int filterMode READ getFilterMode WRITE setFilterMode SIGNAL filterModeChanged) + Q_PROPERTY(QAbstractItemModel * model READ getModel WRITE setModel SIGNAL modelChanged) + + ProxyModel (QObject *parent = Q_NULLPTR); + ProxyModel (QAbstractItemModel * list, const int& defaultFilterMode, QObject *parent = Q_NULLPTR); + + int getFilterMode () const; + void setFilterMode (int filterMode); + + Q_INVOKABLE QVariant getAt(int row); + QAbstractItemModel *getModel(); + void setModel(QAbstractItemModel * model); + + //void add(std::shared_ptr model); +public slots: + void add(std::shared_ptr model); + +signals: + void filterModeChanged(int); + void modelChanged(); + void added(std::shared_ptr model); + +protected: + bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; + bool lessThan (const QModelIndex &left, const QModelIndex &right) const override; + +private: + int mFilterMode; +}; + +#endif diff --git a/linphone-app/src/components/Components.hpp b/linphone-app/src/components/Components.hpp index 3da8ab581..800df778d 100644 --- a/linphone-app/src/components/Components.hpp +++ b/linphone-app/src/components/Components.hpp @@ -40,7 +40,7 @@ #include "conferenceInfo/ConferenceInfoModel.hpp" #include "conferenceInfo/ConferenceInfoListModel.hpp" #include "conferenceInfo/ConferenceInfoProxyModel.hpp" -#include "conferenceScheduler/ConferenceSchedulerModel.hpp" +#include "conferenceScheduler/ConferenceSchedulerHandler.hpp" #include "contact/ContactModel.hpp" #include "contact/VcardModel.hpp" #include "contacts/ContactsListModel.hpp" diff --git a/linphone-app/src/components/call/CallModel.cpp b/linphone-app/src/components/call/CallModel.cpp index 6f0bebbe2..ff0b64a2c 100644 --- a/linphone-app/src/components/call/CallModel.cpp +++ b/linphone-app/src/components/call/CallModel.cpp @@ -119,7 +119,7 @@ QString CallModel::getFullLocalAddress () const { ContactModel *CallModel::getContactModel() const{ QString cleanedAddress = mCall ? Utils::cleanSipAddress(Utils::coreStringToAppString(mCall->getRemoteAddress()->asString())) : ""; - return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(cleanedAddress); + return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(cleanedAddress).get(); } ChatRoomModel * CallModel::getChatRoomModel() const{ @@ -791,7 +791,7 @@ void CallModel::callEnded(){ auto chatRoom = core->searchChatRoom(params, mCall->getCallLog()->getLocalAddress() , mCall->getRemoteAddress() , participants); - std::shared_ptr chatRoomModel= CoreManager::getInstance()->getTimelineListModel()->getChatRoomModel(chatRoom, false); + QSharedPointer chatRoomModel= CoreManager::getInstance()->getTimelineListModel()->getChatRoomModel(chatRoom, false); if(chatRoomModel) chatRoomModel->callEnded(mCall); } diff --git a/linphone-app/src/components/calls/CallsListModel.cpp b/linphone-app/src/components/calls/CallsListModel.cpp index 1793d03a5..bab0d871d 100644 --- a/linphone-app/src/components/calls/CallsListModel.cpp +++ b/linphone-app/src/components/calls/CallsListModel.cpp @@ -49,9 +49,9 @@ namespace { constexpr int DelayBeforeRemoveCall = 3000; } -static inline int findCallIndex (QList &list, const shared_ptr &call) { - auto it = find_if(list.begin(), list.end(), [call](CallModel *callModel) { - return call == callModel->getCall(); +static inline int findCallIndex (QList> &list, const shared_ptr &call) { + auto it = find_if(list.begin(), list.end(), [call](QSharedPointer callModel) { + return call == callModel.objectCast()->getCall(); }); Q_ASSERT(it != list.end()); @@ -59,13 +59,13 @@ static inline int findCallIndex (QList &list, const shared_ptr &list, const CallModel &callModel) { +static inline int findCallIndex (QList> &list, const CallModel &callModel) { return ::findCallIndex(list, callModel.getCall()); } // ----------------------------------------------------------------------------- -CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) { +CallsListModel::CallsListModel (QObject *parent) : ProxyListModel(parent) { mCoreHandlers = CoreManager::getInstance()->getHandlers(); QObject::connect( mCoreHandlers.get(), &CoreHandlers::callStateChanged, @@ -73,34 +73,12 @@ CallsListModel::CallsListModel (QObject *parent) : QAbstractListModel(parent) { ); } -int CallsListModel::rowCount (const QModelIndex &) const { - return mList.count(); -} - -QHash CallsListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$call"; - return roles; -} - -QVariant CallsListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mList.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return QVariant::fromValue(mList[row]); - - return QVariant(); -} - CallModel *CallsListModel::findCallModelFromPeerAddress (const QString &peerAddress) const { std::shared_ptr address = Utils::interpretUrl(peerAddress); - auto it = find_if(mList.begin(), mList.end(), [address](CallModel *callModel) { - return callModel->getRemoteAddress()->weakEqual(address); + auto it = find_if(mList.begin(), mList.end(), [address](QSharedPointer callModel) { + return callModel.objectCast()->getRemoteAddress()->weakEqual(address); }); - return it != mList.end() ? *it : nullptr; + return it != mList.end() ? it->objectCast().get() : nullptr; } // ----------------------------------------------------------------------------- @@ -310,7 +288,7 @@ QVariantMap CallsListModel::createChatRoom(const QString& subject, const int& se shared_ptr core = CoreManager::getInstance()->getCore(); std::shared_ptr chatRoom; QList< std::shared_ptr> admins; - std::shared_ptr timeline; + QSharedPointer timeline; auto timelineList = CoreManager::getInstance()->getTimelineListModel(); QString localAddressStr = (localAddress ? Utils::coreStringToAppString(localAddress->asStringUriOnly()) : "local"); qInfo() << "ChatRoom creation of " << subject << " at " << securityLevel << " security, from " << localAddressStr << " and with " << participants; @@ -386,7 +364,6 @@ QVariantMap CallsListModel::createConference(ConferenceInfoModel * conferenceInf shared_ptr core = CoreManager::getInstance()->getCore(); std::shared_ptr conference; QList< std::shared_ptr> admins; - std::shared_ptr timeline; auto timelineList = CoreManager::getInstance()->getTimelineListModel(); qInfo() << "Conference creation of " << conferenceInfo->getSubject() << " at " << securityLevel << " security";// and with " << conferenceInfo->getConferenceInfo()->getParticipants().size(); auto conferenceScheduler = core->createConferenceScheduler(); @@ -487,26 +464,6 @@ void CallsListModel::handleCallStateChanged (const shared_ptr &c } } -bool CallsListModel::removeRow (int row, const QModelIndex &parent) { - return removeRows(row, 1, parent); -} - -bool CallsListModel::removeRows (int row, int count, const QModelIndex &parent) { - int limit = row + count - 1; - - if (row < 0 || count < 0 || limit >= mList.count()) - return false; - - beginRemoveRows(parent, row, limit); - - for (int i = 0; i < count; ++i) - mList.takeAt(row)->deleteLater(); - - endRemoveRows(); - - return true; -} - // ----------------------------------------------------------------------------- void CallsListModel::addCall (const shared_ptr &call) { @@ -521,21 +478,11 @@ void CallsListModel::addCall (const shared_ptr &call) { } } - CallModel *callModel = new CallModel(call); + QSharedPointer callModel = QSharedPointer::create(call); qInfo() << QStringLiteral("Add call:") << callModel->getFullLocalAddress() << callModel->getFullPeerAddress(); - App::getInstance()->getEngine()->setObjectOwnership(callModel, QQmlEngine::CppOwnership); + App::getInstance()->getEngine()->setObjectOwnership(callModel.get(), QQmlEngine::CppOwnership); - // This connection is (only) useful for `CallsListProxyModel`. - QObject::connect(callModel, &CallModel::isInConferenceChanged, this, [this, callModel](bool) { - int id = findCallIndex(mList, *callModel); - emit dataChanged(index(id, 0), index(id, 0)); - }); - - int row = mList.count(); - - beginInsertRows(QModelIndex(), row, row); - mList << callModel; - endInsertRows(); + add(callModel); emit layoutChanged(); } @@ -546,21 +493,18 @@ void CallsListModel::addDummyCall () { App::smartShowWindow(callsWindow); } - CallModel *callModel = new CallModel(nullptr); + QSharedPointer callModel = QSharedPointer::create(nullptr); qInfo() << QStringLiteral("Add call:") << callModel->getFullLocalAddress() << callModel->getFullPeerAddress(); - App::getInstance()->getEngine()->setObjectOwnership(callModel, QQmlEngine::CppOwnership); + App::getInstance()->getEngine()->setObjectOwnership(callModel.get(), QQmlEngine::CppOwnership); // This connection is (only) useful for `CallsListProxyModel`. - QObject::connect(callModel, &CallModel::isInConferenceChanged, this, [this, callModel](bool) { + QObject::connect(callModel.get(), &CallModel::isInConferenceChanged, this, [this, callModel](bool) { int id = findCallIndex(mList, *callModel); emit dataChanged(index(id, 0), index(id, 0)); }); - int row = mList.count(); - beginInsertRows(QModelIndex(), row, row); - mList << callModel; - endInsertRows(); + add(callModel); emit layoutChanged(); } @@ -582,9 +526,5 @@ void CallsListModel::removeCall (const shared_ptr &call) { } void CallsListModel::removeCallCb (CallModel *callModel) { - qInfo() << QStringLiteral("Removing call:") << callModel; - - int index = mList.indexOf(callModel); - if (index == -1 || !removeRow(index)) - qWarning() << QStringLiteral("Unable to remove call:") << callModel; + remove(callModel); } diff --git a/linphone-app/src/components/calls/CallsListModel.hpp b/linphone-app/src/components/calls/CallsListModel.hpp index 1ca7aa800..a0fba1517 100644 --- a/linphone-app/src/components/calls/CallsListModel.hpp +++ b/linphone-app/src/components/calls/CallsListModel.hpp @@ -22,10 +22,10 @@ #define CALLS_LIST_MODEL_H_ #include -#include #include "components/call/CallModel.hpp" #include "utils/LinphoneEnums.hpp" +#include "app/proxyModel/ProxyListModel.hpp" // ============================================================================= @@ -34,16 +34,12 @@ class CoreHandlers; class ConferenceModel; class ConferenceInfoModel; -class CallsListModel : public QAbstractListModel { +class CallsListModel : public ProxyListModel { Q_OBJECT public: CallsListModel (QObject *parent = Q_NULLPTR); - int rowCount (const QModelIndex &index = QModelIndex()) const override; - - QHash roleNames () const override; - QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; CallModel *findCallModelFromPeerAddress (const QString &peerAddress) const; void askForTransfer (CallModel *callModel); @@ -79,8 +75,6 @@ signals: void callMissed (CallModel *callModel); private: - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; void handleCallStateChanged (const std::shared_ptr &call, linphone::Call::State state); @@ -89,7 +83,6 @@ private: void removeCall (const std::shared_ptr &call); void removeCallCb (CallModel *callModel); - QList mList; QList> mConferences; std::shared_ptr mCoreHandlers; diff --git a/linphone-app/src/components/camera/Camera.cpp b/linphone-app/src/components/camera/Camera.cpp index c969250cd..8ccd49452 100644 --- a/linphone-app/src/components/camera/Camera.cpp +++ b/linphone-app/src/components/camera/Camera.cpp @@ -64,16 +64,6 @@ void Camera::resetWindowId() { CoreManager::getInstance()->getCore()->setNativeVideoWindowId(NULL); } -class SafeFramebuffer : public QQuickFramebufferObject::Renderer{ -public: - SafeFramebuffer(){} - QOpenGLFramebufferObject *createFramebufferObject (const QSize &size) override{ - return new QOpenGLFramebufferObject(size); - } - void render () override{} - void synchronize (QQuickFramebufferObject *item) override{} -}; - QQuickFramebufferObject::Renderer *Camera::createRenderer () const { QQuickFramebufferObject::Renderer * renderer = NULL; if(mIsPreview){ diff --git a/linphone-app/src/components/chat-events/ChatCallModel.cpp b/linphone-app/src/components/chat-events/ChatCallModel.cpp index e1f91ced5..64c633092 100644 --- a/linphone-app/src/components/chat-events/ChatCallModel.cpp +++ b/linphone-app/src/components/chat-events/ChatCallModel.cpp @@ -30,20 +30,21 @@ ChatCallModel::ChatCallModel ( std::shared_ptr callLog, const bool& isStart, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::CallEntry, parent) { App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mCallLog = callLog; + mIsStart = isStart; if(isStart){ mTimestamp = QDateTime::fromMSecsSinceEpoch(callLog->getStartDate() * 1000); - setIsStart(true); }else{ mTimestamp = QDateTime::fromMSecsSinceEpoch((callLog->getStartDate() + callLog->getDuration()) * 1000); - setIsStart(false); } + mIsOutgoing = (mCallLog->getDir() == linphone::Call::Dir::Outgoing); + mStatus = (LinphoneEnums::fromLinphone(mCallLog->getStatus())); } ChatCallModel::~ChatCallModel(){ } -std::shared_ptr ChatCallModel::create(std::shared_ptr callLog, const bool& isStart, QObject * parent){ - auto model = std::make_shared(callLog, isStart, parent); +QSharedPointer ChatCallModel::create(std::shared_ptr callLog, const bool& isStart, QObject * parent){ + auto model = QSharedPointer::create(callLog, isStart, parent); if(model ){ model->update(); model->mSelf = model; diff --git a/linphone-app/src/components/chat-events/ChatCallModel.hpp b/linphone-app/src/components/chat-events/ChatCallModel.hpp index bf388ca59..bd4410e7f 100644 --- a/linphone-app/src/components/chat-events/ChatCallModel.hpp +++ b/linphone-app/src/components/chat-events/ChatCallModel.hpp @@ -31,7 +31,7 @@ class ChatCallModel : public ChatEvent { Q_OBJECT public: - static std::shared_ptr create(std::shared_ptr chatLog, const bool& isStart, QObject * parent = nullptr);// Call it instead constructor + static QSharedPointer create(std::shared_ptr chatLog, const bool& isStart, QObject * parent = nullptr);// Call it instead constructor ChatCallModel (std::shared_ptr eventLog, const bool& isStart, QObject * parent = nullptr); virtual ~ChatCallModel(); @@ -62,8 +62,8 @@ signals: private: std::shared_ptr mCallLog; - std::weak_ptr mSelf; // Used to pass to functions that need a shared_ptr + QWeakPointer mSelf; // Used to pass to functions that need a shared_ptr }; -Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(QSharedPointer) Q_DECLARE_METATYPE(ChatCallModel*) #endif diff --git a/linphone-app/src/components/chat-events/ChatMessageListener.cpp b/linphone-app/src/components/chat-events/ChatMessageListener.cpp new file mode 100644 index 000000000..148205dfe --- /dev/null +++ b/linphone-app/src/components/chat-events/ChatMessageListener.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ +#include "ChatMessageListener.hpp" + + +#include + +#include +#include "ChatMessageModel.hpp" + +// ============================================================================= + + + +// ============================================================================= +ChatMessageListener::ChatMessageListener(QObject* parent) : QObject(parent){ +} + +void ChatMessageListener::onFileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer){ + emit fileTransferRecv(message, content, buffer); +} +void ChatMessageListener::onFileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer){ + emit fileTransferSendChunk(message, content, offset, size, buffer); +} +std::shared_ptr ChatMessageListener::onFileTransferSend(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size) { + emit fileTransferSend(message, content, offset, size); + return nullptr; +} +void ChatMessageListener::onFileTransferProgressIndication (const std::shared_ptr &message, const std::shared_ptr & content, size_t offset, size_t total){ + emit fileTransferProgressIndication(message, content, offset, total); +} +void ChatMessageListener::onMsgStateChanged (const std::shared_ptr &message, linphone::ChatMessage::State state){ + emit msgStateChanged(message, state); +} +void ChatMessageListener::onParticipantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state){ + emit participantImdnStateChanged(message, state); +} +void ChatMessageListener::onEphemeralMessageTimerStarted(const std::shared_ptr & message){ + emit ephemeralMessageTimerStarted(message); +} +void ChatMessageListener::onEphemeralMessageDeleted(const std::shared_ptr & message){ + emit ephemeralMessageDeleted(message); +} diff --git a/linphone-app/src/components/chat-events/ChatMessageListener.hpp b/linphone-app/src/components/chat-events/ChatMessageListener.hpp new file mode 100644 index 000000000..f2c1520b0 --- /dev/null +++ b/linphone-app/src/components/chat-events/ChatMessageListener.hpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#ifndef CHAT_MESSAGE_LISTENER_H +#define CHAT_MESSAGE_LISTENER_H + +#include "utils/LinphoneEnums.hpp" + +#include + +// ============================================================================= + + +class ChatMessageModel; + +class ChatMessageListener : public QObject, public linphone::ChatMessageListener { +Q_OBJECT +public: + ChatMessageListener(QObject * parent = nullptr); + virtual ~ChatMessageListener(){} + + virtual void onFileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer) override; + virtual void onFileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer) override; + virtual std::shared_ptr onFileTransferSend(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size) override; + virtual void onFileTransferProgressIndication (const std::shared_ptr &message, const std::shared_ptr &, size_t offset, size_t) override; + virtual void onMsgStateChanged (const std::shared_ptr &message, linphone::ChatMessage::State state) override; + virtual void onParticipantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state) override; + virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & message) override; + virtual void onEphemeralMessageDeleted(const std::shared_ptr & message) override; +signals: + void fileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer); + void fileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer); + std::shared_ptr fileTransferSend (const std::shared_ptr &,const std::shared_ptr &,size_t,size_t); + void fileTransferProgressIndication (const std::shared_ptr &message, const std::shared_ptr &, size_t offset, size_t); + void msgStateChanged (const std::shared_ptr &message, linphone::ChatMessage::State state); + void participantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state); + void ephemeralMessageTimerStarted(const std::shared_ptr & message); + void ephemeralMessageDeleted(const std::shared_ptr & message); +}; + +Q_DECLARE_METATYPE(ChatMessageListener*) +#endif diff --git a/linphone-app/src/components/chat-events/ChatMessageModel.cpp b/linphone-app/src/components/chat-events/ChatMessageModel.cpp index 2474e881e..9453eb905 100644 --- a/linphone-app/src/components/chat-events/ChatMessageModel.cpp +++ b/linphone-app/src/components/chat-events/ChatMessageModel.cpp @@ -34,6 +34,8 @@ #include #include +#include "ChatMessageListener.hpp" + #include "app/App.hpp" #include "app/paths/Paths.hpp" #include "components/contact/ContactModel.hpp" @@ -52,53 +54,20 @@ #include "utils/Utils.hpp" #include "utils/Constants.hpp" + +void ChatMessageModel::connectTo(ChatMessageListener * listener){ + connect(listener, &ChatMessageListener::fileTransferRecv, this, &ChatMessageModel::onFileTransferRecv); + connect(listener, &ChatMessageListener::fileTransferSendChunk, this, &ChatMessageModel::onFileTransferSendChunk); + connect(listener, &ChatMessageListener::fileTransferSend, this, &ChatMessageModel::onFileTransferSend); + connect(listener, &ChatMessageListener::fileTransferProgressIndication, this, &ChatMessageModel::onFileTransferProgressIndication); + connect(listener, &ChatMessageListener::msgStateChanged, this, &ChatMessageModel::onMsgStateChanged); + connect(listener, &ChatMessageListener::participantImdnStateChanged, this, &ChatMessageModel::onParticipantImdnStateChanged); + connect(listener, &ChatMessageListener::ephemeralMessageTimerStarted, this, &ChatMessageModel::onEphemeralMessageTimerStarted); + connect(listener, &ChatMessageListener::ephemeralMessageDeleted, this, &ChatMessageModel::onEphemeralMessageDeleted); + connect(listener, &ChatMessageListener::participantImdnStateChanged, this->getParticipantImdnStates().get(), &ParticipantImdnStateListModel::onParticipantImdnStateChanged); +} // ============================================================================= - - -// ============================================================================= -ChatMessageListener::ChatMessageListener(ChatMessageModel * model, QObject* parent) : QObject(parent){ - connect(this, &ChatMessageListener::fileTransferRecv, model, &ChatMessageModel::onFileTransferRecv); - connect(this, &ChatMessageListener::fileTransferSendChunk, model, &ChatMessageModel::onFileTransferSendChunk); - connect(this, &ChatMessageListener::fileTransferSend, model, &ChatMessageModel::onFileTransferSend); - connect(this, &ChatMessageListener::fileTransferProgressIndication, model, &ChatMessageModel::onFileTransferProgressIndication); - connect(this, &ChatMessageListener::msgStateChanged, model, &ChatMessageModel::onMsgStateChanged); - connect(this, &ChatMessageListener::participantImdnStateChanged, model, &ChatMessageModel::onParticipantImdnStateChanged); - connect(this, &ChatMessageListener::ephemeralMessageTimerStarted, model, &ChatMessageModel::onEphemeralMessageTimerStarted); - connect(this, &ChatMessageListener::ephemeralMessageDeleted, model, &ChatMessageModel::onEphemeralMessageDeleted); - connect(this, &ChatMessageListener::participantImdnStateChanged, model->getParticipantImdnStates().get(), &ParticipantImdnStateListModel::onParticipantImdnStateChanged); -} - - - -void ChatMessageListener::onFileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer){ - emit fileTransferRecv(message, content, buffer); -} -void ChatMessageListener::onFileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer){ - emit fileTransferSendChunk(message, content, offset, size, buffer); -} -std::shared_ptr ChatMessageListener::onFileTransferSend(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size) { - emit fileTransferSend(message, content, offset, size); - return nullptr; -} -void ChatMessageListener::onFileTransferProgressIndication (const std::shared_ptr &message, const std::shared_ptr & content, size_t offset, size_t total){ - emit fileTransferProgressIndication(message, content, offset, total); -} -void ChatMessageListener::onMsgStateChanged (const std::shared_ptr &message, linphone::ChatMessage::State state){ - emit msgStateChanged(message, state); -} -void ChatMessageListener::onParticipantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state){ - emit participantImdnStateChanged(message, state); -} -void ChatMessageListener::onEphemeralMessageTimerStarted(const std::shared_ptr & message){ - emit ephemeralMessageTimerStarted(message); -} -void ChatMessageListener::onEphemeralMessageDeleted(const std::shared_ptr & message){ - emit ephemeralMessageDeleted(message); -} - - -// ============================================================================= ChatMessageModel::AppDataManager::AppDataManager(const QString& appdata){ if(!appdata.isEmpty()){ for(QString pair : appdata.split(';')){ @@ -121,8 +90,9 @@ QString ChatMessageModel::AppDataManager::toString(){ ChatMessageModel::ChatMessageModel ( std::shared_ptr chatMessage, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::MessageEntry, parent) { App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it if(chatMessage){ - mParticipantImdnStateListModel = std::make_shared(chatMessage); - mChatMessageListener = std::make_shared(this, parent); + mParticipantImdnStateListModel = QSharedPointer::create(chatMessage); + mChatMessageListener = std::make_shared(parent); + connectTo(mChatMessageListener.get()); mChatMessage = chatMessage; mChatMessage->addListener(mChatMessageListener); if( mChatMessage->isReply()){ @@ -130,7 +100,7 @@ ChatMessageModel::ChatMessageModel ( std::shared_ptr chat if( replyMessage)// Reply message could be inexistant (for example : when locally deleted) mReplyChatMessageModel = create(replyMessage, parent); } - connect(this, &ChatMessageModel::remove, dynamic_cast(parent), &ChatRoomModel::removeEntry); + connect(this, &ChatMessageModel::remove, qobject_cast(parent), &ChatRoomModel::removeEntry); std::list> contents = chatMessage->getContents(); QString txt; @@ -144,22 +114,23 @@ ChatMessageModel::ChatMessageModel ( std::shared_ptr chat mTimestamp = QDateTime::fromMSecsSinceEpoch(chatMessage->getTime() * 1000); - mContentListModel = std::make_shared(this); + mContentListModel = QSharedPointer::create(this); } ChatMessageModel::~ChatMessageModel(){ if(mChatMessage) mChatMessage->removeListener(mChatMessageListener); } -std::shared_ptr ChatMessageModel::create(std::shared_ptr chatMessage, QObject * parent){ - auto model = std::make_shared(chatMessage, parent); +QSharedPointer ChatMessageModel::create(std::shared_ptr chatMessage, QObject * parent){ + auto model = QSharedPointer::create(chatMessage, parent); return model; } std::shared_ptr ChatMessageModel::getChatMessage(){ return mChatMessage; } -std::shared_ptr ChatMessageModel::getContentModel(std::shared_ptr content){ + +QSharedPointer ChatMessageModel::getContentModel(std::shared_ptr content){ return mContentListModel->getContentModel(content); } @@ -189,7 +160,7 @@ QString ChatMessageModel::getToSipAddress() const{ } ContactModel * ChatMessageModel::getContactModel() const{ - return mChatMessage ? CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asString())) : nullptr; + return mChatMessage ? CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(Utils::coreStringToAppString(mChatMessage->getFromAddress()->asString())).get() : nullptr; } bool ChatMessageModel::isEphemeral() const{ @@ -219,7 +190,7 @@ ParticipantImdnStateProxyModel * ChatMessageModel::getProxyImdnStates(){ return proxy; } -std::shared_ptr ChatMessageModel::getParticipantImdnStates() const{ +QSharedPointer ChatMessageModel::getParticipantImdnStates() const{ return mParticipantImdnStateListModel; } @@ -227,7 +198,7 @@ ContentProxyModel * ChatMessageModel::getContentsProxy(){ return new ContentProxyModel(this); } -std::shared_ptr ChatMessageModel::getContents() const{ +QSharedPointer ChatMessageModel::getContents() const{ return mContentListModel; } @@ -320,7 +291,7 @@ void ChatMessageModel::onFileTransferProgressIndication (const std::shared_ptrisOutgoing()) { mContentListModel->downloaded(); bool allAreDownloaded = true; - for(auto content : mContentListModel->getContents()) + for(auto content : mContentListModel->getSharedList()) allAreDownloaded &= content->mWasDownloaded; setWasDownloaded(allAreDownloaded); App::getInstance()->getNotifier()->notifyReceivedFileMessage(message, content); diff --git a/linphone-app/src/components/chat-events/ChatMessageModel.hpp b/linphone-app/src/components/chat-events/ChatMessageModel.hpp index 6fc0aca84..de028863f 100644 --- a/linphone-app/src/components/chat-events/ChatMessageModel.hpp +++ b/linphone-app/src/components/chat-events/ChatMessageModel.hpp @@ -44,41 +44,17 @@ public: #include "components/participant-imdn/ParticipantImdnStateListModel.hpp" class ChatMessageModel; +class ChatMessageListener; class ParticipantImdnStateProxyModel; class ParticipantImdnStateListModel; class ContentModel; class ContentListModel; class ContentProxyModel; -class ChatMessageListener : public QObject, public linphone::ChatMessageListener { -Q_OBJECT -public: - ChatMessageListener(ChatMessageModel * model, QObject * parent = nullptr); - virtual ~ChatMessageListener(){} - - virtual void onFileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer) override; - virtual void onFileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer) override; - virtual std::shared_ptr onFileTransferSend(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size) override; - virtual void onFileTransferProgressIndication (const std::shared_ptr &message, const std::shared_ptr &, size_t offset, size_t) override; - virtual void onMsgStateChanged (const std::shared_ptr &message, linphone::ChatMessage::State state) override; - virtual void onParticipantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state) override; - virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & message) override; - virtual void onEphemeralMessageDeleted(const std::shared_ptr & message) override; -signals: - void fileTransferRecv(const std::shared_ptr & message, const std::shared_ptr & content, const std::shared_ptr & buffer); - void fileTransferSendChunk(const std::shared_ptr & message, const std::shared_ptr & content, size_t offset, size_t size, const std::shared_ptr & buffer); - std::shared_ptr fileTransferSend (const std::shared_ptr &,const std::shared_ptr &,size_t,size_t); - void fileTransferProgressIndication (const std::shared_ptr &message, const std::shared_ptr &, size_t offset, size_t); - void msgStateChanged (const std::shared_ptr &message, linphone::ChatMessage::State state); - void participantImdnStateChanged(const std::shared_ptr & message, const std::shared_ptr & state); - void ephemeralMessageTimerStarted(const std::shared_ptr & message); - void ephemeralMessageDeleted(const std::shared_ptr & message); -}; - class ChatMessageModel : public ChatEvent { Q_OBJECT public: - static std::shared_ptr create(std::shared_ptr chatMessage, QObject * parent = nullptr);// Call it instead constructor + static QSharedPointer create(std::shared_ptr chatMessage, QObject * parent = nullptr);// Call it instead constructor ChatMessageModel (std::shared_ptr chatMessage, QObject * parent = nullptr); virtual ~ChatMessageModel(); @@ -119,7 +95,7 @@ public: std::shared_ptr getChatMessage(); - std::shared_ptr getContentModel(std::shared_ptr content); + QSharedPointer getContentModel(std::shared_ptr content); //---------------------------------------------------------------------------- @@ -135,9 +111,9 @@ public: LinphoneEnums::ChatMessageState getState() const; bool isOutgoing() const; Q_INVOKABLE ParticipantImdnStateProxyModel * getProxyImdnStates(); - std::shared_ptr getParticipantImdnStates() const; + QSharedPointer getParticipantImdnStates() const; Q_INVOKABLE ContentProxyModel * getContentsProxy(); - std::shared_ptr getContents() const; + QSharedPointer getContents() const; bool isReply() const; ChatMessageModel * getReplyChatMessageModel() const; @@ -184,15 +160,16 @@ signals: private: - std::shared_ptr mFileTransfertContent; + void connectTo(ChatMessageListener * listener); + std::shared_ptr mChatMessage; - std::shared_ptr mParticipantImdnStateListModel; - std::shared_ptr mChatMessageListener; - std::shared_ptr mContentListModel; + std::shared_ptr mChatMessageListener; // This is passed to linpĥone object and must be in shared_ptr - std::shared_ptr mReplyChatMessageModel; + QSharedPointer mContentListModel; + QSharedPointer mFileTransfertContent; + QSharedPointer mParticipantImdnStateListModel; + QSharedPointer mReplyChatMessageModel; }; Q_DECLARE_METATYPE(ChatMessageModel*) -Q_DECLARE_METATYPE(std::shared_ptr) -Q_DECLARE_METATYPE(ChatMessageListener*) +Q_DECLARE_METATYPE(QSharedPointer) #endif diff --git a/linphone-app/src/components/chat-events/ChatNoticeModel.cpp b/linphone-app/src/components/chat-events/ChatNoticeModel.cpp index d8767282d..0374d704a 100644 --- a/linphone-app/src/components/chat-events/ChatNoticeModel.cpp +++ b/linphone-app/src/components/chat-events/ChatNoticeModel.cpp @@ -31,6 +31,7 @@ ChatNoticeModel::ChatNoticeModel ( std::shared_ptr eventLog, QObject * parent) : ChatEvent(ChatRoomModel::EntryType::NoticeEntry, parent) { App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mEventLog = eventLog; + setEventLogType(LinphoneEnums::fromLinphone(mEventLog->getType())); mTimestamp = QDateTime::fromMSecsSinceEpoch(eventLog->getCreationTime() * 1000); } @@ -45,8 +46,8 @@ ChatNoticeModel::ChatNoticeModel ( NoticeType noticeType, const QDateTime& times ChatNoticeModel::~ChatNoticeModel(){ } -std::shared_ptr ChatNoticeModel::create(std::shared_ptr eventLog, QObject * parent){ - auto model = std::make_shared(eventLog, parent); +QSharedPointer ChatNoticeModel::create(std::shared_ptr eventLog, QObject * parent){ + auto model = QSharedPointer::create(eventLog, parent); if(model && model->update()){ model->mSelf = model; return model; @@ -54,8 +55,8 @@ std::shared_ptr ChatNoticeModel::create(std::shared_ptr ChatNoticeModel::create(NoticeType noticeType, const QDateTime& timestamp, const QString& txt, QObject * parent){ - auto model = std::make_shared(noticeType, timestamp, txt, parent); +QSharedPointer ChatNoticeModel::create(NoticeType noticeType, const QDateTime& timestamp, const QString& txt, QObject * parent){ + auto model = QSharedPointer::create(noticeType, timestamp, txt, parent); if(model ){ model->mSelf = model; return model; diff --git a/linphone-app/src/components/chat-events/ChatNoticeModel.hpp b/linphone-app/src/components/chat-events/ChatNoticeModel.hpp index 0b1e171e8..fd5d1d8f9 100644 --- a/linphone-app/src/components/chat-events/ChatNoticeModel.hpp +++ b/linphone-app/src/components/chat-events/ChatNoticeModel.hpp @@ -38,8 +38,8 @@ public: }; Q_ENUM(NoticeType); - static std::shared_ptr create(std::shared_ptr eventLog, QObject * parent = nullptr);// Call it instead constructor - static std::shared_ptr create(NoticeType noticeType, const QDateTime& timestamp,const QString& txt, QObject * parent = nullptr); + static QSharedPointer create(std::shared_ptr eventLog, QObject * parent = nullptr);// Call it instead constructor + static QSharedPointer create(NoticeType noticeType, const QDateTime& timestamp,const QString& txt, QObject * parent = nullptr); ChatNoticeModel (std::shared_ptr eventLog, QObject * parent = nullptr); ChatNoticeModel (NoticeType noticeType, const QDateTime& timestamp, const QString& txt, QObject * parent = nullptr); virtual ~ChatNoticeModel(); @@ -70,10 +70,10 @@ signals: private: std::shared_ptr mEventLog; - std::weak_ptr mSelf; // Used to pass to functions that need a shared_ptr + QWeakPointer mSelf; // Used to pass to functions that need a shared_ptr }; -Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(QSharedPointer) Q_DECLARE_METATYPE(ChatNoticeModel*) #endif diff --git a/linphone-app/src/components/chat-room/ChatRoomListModel.cpp b/linphone-app/src/components/chat-room/ChatRoomListModel.cpp deleted file mode 100644 index f61ce6cc9..000000000 --- a/linphone-app/src/components/chat-room/ChatRoomListModel.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021 Belledonne Communications SARL. - * - * This file is part of linphone-desktop - * (see https://www.linphone.org). - * - * 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 . - */ - -#include -#include -#include - -#include "app/App.hpp" -#include "components/conference/ConferenceAddModel.hpp" -#include "components/conference/ConferenceHelperModel.hpp" -#include "components/core/CoreHandlers.hpp" -#include "components/core/CoreManager.hpp" -#include "components/settings/SettingsModel.hpp" -#include "utils/Utils.hpp" - -#include "ChatRoomListModel.hpp" -#include "ChatRoomModel.hpp" - -// ============================================================================= - -using namespace std; - -namespace { -// Delay before removing call in ms. -constexpr int DelayBeforeRemoveCall = 3000; -} - - -// ----------------------------------------------------------------------------- - -ChatRoomListModel::ChatRoomListModel (QObject *parent) : QAbstractListModel(parent) { -} - -int ChatRoomListModel::rowCount (const QModelIndex &) const { - return mList.count(); -} - -QHash ChatRoomListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$chatRoom"; - return roles; -} - -QVariant ChatRoomListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mList.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return QVariant::fromValue(mList[row]); - - return QVariant(); -} - -// ----------------------------------------------------------------------------- - - -bool ChatRoomListModel::removeRow (int row, const QModelIndex &parent) { - return removeRows(row, 1, parent); -} - -bool ChatRoomListModel::removeRows (int row, int count, const QModelIndex &parent) { - int limit = row + count - 1; - - if (row < 0 || count < 0 || limit >= mList.count()) - return false; - - beginRemoveRows(parent, row, limit); - - for (int i = 0; i < count; ++i) - mList.takeAt(row)->deleteLater(); - - endRemoveRows(); - - return true; -} - -// ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/chat-room/ChatRoomListener.cpp b/linphone-app/src/components/chat-room/ChatRoomListener.cpp new file mode 100644 index 000000000..6b21caa18 --- /dev/null +++ b/linphone-app/src/components/chat-room/ChatRoomListener.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#include "ChatRoomListener.hpp" + +#include "../calls/CallsListModel.hpp" + +#include +#include +#include + +ChatRoomListener::ChatRoomListener(QObject * parent): QObject(parent){ +} + +//--------------------------------------------------------------------------------------------------- + +void ChatRoomListener::onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing){ + emit isComposingReceived(chatRoom, remoteAddress, isComposing); +} +void ChatRoomListener::onMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ + emit messageReceived(chatRoom, message); +} +void ChatRoomListener::onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit newEvent(chatRoom, eventLog); +} +void ChatRoomListener::onChatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit chatMessageReceived(chatRoom, eventLog); +} +void ChatRoomListener::onChatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit chatMessageSending(chatRoom, eventLog); +} +void ChatRoomListener::onChatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit chatMessageSent(chatRoom, eventLog); +} +void ChatRoomListener::onParticipantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit participantAdded(chatRoom, eventLog); +} +void ChatRoomListener::onParticipantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit participantRemoved(chatRoom, eventLog); +} +void ChatRoomListener::onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit participantAdminStatusChanged(chatRoom, eventLog); +} +void ChatRoomListener::onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState){ + emit stateChanged(chatRoom, newState); +} +void ChatRoomListener::onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit securityEvent(chatRoom, eventLog); +} +void ChatRoomListener::onSubjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit subjectChanged(chatRoom, eventLog); +} +void ChatRoomListener::onUndecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ + emit undecryptableMessageReceived(chatRoom, message); +} +void ChatRoomListener::onParticipantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit participantDeviceAdded(chatRoom, eventLog); +} +void ChatRoomListener::onParticipantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit participantDeviceRemoved(chatRoom, eventLog); +} +void ChatRoomListener::onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit conferenceJoined(chatRoom, eventLog); +} +void ChatRoomListener::onConferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit conferenceLeft(chatRoom, eventLog); +} +void ChatRoomListener::onEphemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit ephemeralEvent(chatRoom, eventLog); +} +void ChatRoomListener::onEphemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit ephemeralMessageTimerStarted(chatRoom, eventLog); +} +void ChatRoomListener::onEphemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ + emit ephemeralMessageDeleted(chatRoom, eventLog); +} +void ChatRoomListener::onConferenceAddressGeneration(const std::shared_ptr & chatRoom){ + emit conferenceAddressGeneration(chatRoom); +} +void ChatRoomListener::onParticipantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress){ + emit participantRegistrationSubscriptionRequested(chatRoom, participantAddress); +} +void ChatRoomListener::onParticipantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress){ + emit participantRegistrationUnsubscriptionRequested(chatRoom, participantAddress); +} +void ChatRoomListener::onChatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ + emit chatMessageShouldBeStored(chatRoom, message); +} +void ChatRoomListener::onChatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state){ + emit chatMessageParticipantImdnStateChanged(chatRoom, message, state); +} diff --git a/linphone-app/src/components/chat-room/ChatRoomListener.hpp b/linphone-app/src/components/chat-room/ChatRoomListener.hpp new file mode 100644 index 000000000..011d8752d --- /dev/null +++ b/linphone-app/src/components/chat-room/ChatRoomListener.hpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2022 Belledonne Communications SARL. + * + * This file is part of linphone-desktop + * (see https://www.linphone.org). + * + * 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 . + */ + +#ifndef CHATROOM_LISTENER_H_ +#define CHATROOM_LISTENER_H_ + +// ============================================================================= +#include + +#include +#include + +class ChatRoomModel; +class TimelineModel; + +class ChatRoomListener : public QObject, public linphone::ChatRoomListener { +Q_OBJECT +public: + ChatRoomListener(QObject * parent = nullptr); + virtual ~ChatRoomListener(){} + + virtual void onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing) override; + virtual void onMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; + virtual void onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onChatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onChatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onChatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onParticipantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onParticipantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState) override; + virtual void onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onSubjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onUndecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; + virtual void onParticipantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onParticipantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onConferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onEphemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onEphemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; + virtual void onConferenceAddressGeneration(const std::shared_ptr & chatRoom) override; + virtual void onParticipantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress) override; + virtual void onParticipantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress) override; + virtual void onChatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; + virtual void onChatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state) override; + +signals: + void isComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing); + void messageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message); + void newEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void chatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void chatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void chatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void participantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void participantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void participantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void stateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState); + void securityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void subjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void undecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message); + void participantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void participantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void conferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void conferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void ephemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void ephemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void ephemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + void conferenceAddressGeneration(const std::shared_ptr & chatRoom); + void participantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress); + void participantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress); + void chatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message); + void chatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state); +}; + +#endif diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.cpp b/linphone-app/src/components/chat-room/ChatRoomModel.cpp index f673f8d91..25262e47f 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.cpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2020 Belledonne Communications SARL. + * Copyright (c) 2010-2022 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -34,6 +34,8 @@ #include #include +#include "ChatRoomListener.hpp" + #include "app/App.hpp" #include "app/paths/Paths.hpp" #include "app/providers/ThumbnailProvider.hpp" @@ -74,114 +76,37 @@ using namespace std; // ----------------------------------------------------------------------------- - -ChatRoomModelListener::ChatRoomModelListener(ChatRoomModel * model, QObject* parent) : QObject(parent){ - connect(this, &ChatRoomModelListener::isComposingReceived, model, &ChatRoomModel::onIsComposingReceived); - connect(this, &ChatRoomModelListener::messageReceived, model, &ChatRoomModel::onMessageReceived); - connect(this, &ChatRoomModelListener::newEvent, model, &ChatRoomModel::onNewEvent); - connect(this, &ChatRoomModelListener::chatMessageReceived, model, &ChatRoomModel::onChatMessageReceived); - connect(this, &ChatRoomModelListener::chatMessageSending, model, &ChatRoomModel::onChatMessageSending); - connect(this, &ChatRoomModelListener::chatMessageSent, model, &ChatRoomModel::onChatMessageSent); - connect(this, &ChatRoomModelListener::participantAdded, model, &ChatRoomModel::onParticipantAdded); - connect(this, &ChatRoomModelListener::participantRemoved, model, &ChatRoomModel::onParticipantRemoved); - connect(this, &ChatRoomModelListener::participantAdminStatusChanged, model, &ChatRoomModel::onParticipantAdminStatusChanged); - connect(this, &ChatRoomModelListener::stateChanged, model, &ChatRoomModel::onStateChanged); - connect(this, &ChatRoomModelListener::securityEvent, model, &ChatRoomModel::onSecurityEvent); - connect(this, &ChatRoomModelListener::subjectChanged, model, &ChatRoomModel::onSubjectChanged); - connect(this, &ChatRoomModelListener::undecryptableMessageReceived, model, &ChatRoomModel::onUndecryptableMessageReceived); - connect(this, &ChatRoomModelListener::participantDeviceAdded, model, &ChatRoomModel::onParticipantDeviceAdded); - connect(this, &ChatRoomModelListener::participantDeviceRemoved, model, &ChatRoomModel::onParticipantDeviceRemoved); - connect(this, &ChatRoomModelListener::conferenceJoined, model, &ChatRoomModel::onConferenceJoined); - connect(this, &ChatRoomModelListener::conferenceLeft, model, &ChatRoomModel::onConferenceLeft); - connect(this, &ChatRoomModelListener::ephemeralEvent, model, &ChatRoomModel::onEphemeralEvent); - connect(this, &ChatRoomModelListener::ephemeralMessageTimerStarted, model, &ChatRoomModel::onEphemeralMessageTimerStarted); - connect(this, &ChatRoomModelListener::ephemeralMessageDeleted, model, &ChatRoomModel::onEphemeralMessageDeleted); - connect(this, &ChatRoomModelListener::conferenceAddressGeneration, model, &ChatRoomModel::onConferenceAddressGeneration); - connect(this, &ChatRoomModelListener::participantRegistrationSubscriptionRequested, model, &ChatRoomModel::onParticipantRegistrationSubscriptionRequested); - connect(this, &ChatRoomModelListener::participantRegistrationUnsubscriptionRequested, model, &ChatRoomModel::onParticipantRegistrationUnsubscriptionRequested); - connect(this, &ChatRoomModelListener::chatMessageShouldBeStored, model, &ChatRoomModel::onChatMessageShouldBeStored); - connect(this, &ChatRoomModelListener::chatMessageParticipantImdnStateChanged, model, &ChatRoomModel::onChatMessageParticipantImdnStateChanged); -} - -void ChatRoomModelListener::onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing){ - emit isComposingReceived(chatRoom, remoteAddress, isComposing); -} -void ChatRoomModelListener::onMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ - emit messageReceived(chatRoom, message); -} -void ChatRoomModelListener::onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit newEvent(chatRoom, eventLog); -} -void ChatRoomModelListener::onChatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit chatMessageReceived(chatRoom, eventLog); -} -void ChatRoomModelListener::onChatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit chatMessageSending(chatRoom, eventLog); -} -void ChatRoomModelListener::onChatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit chatMessageSent(chatRoom, eventLog); -} -void ChatRoomModelListener::onParticipantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit participantAdded(chatRoom, eventLog); -} -void ChatRoomModelListener::onParticipantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit participantRemoved(chatRoom, eventLog); -} -void ChatRoomModelListener::onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit participantAdminStatusChanged(chatRoom, eventLog); -} -void ChatRoomModelListener::onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState){ - emit stateChanged(chatRoom, newState); -} -void ChatRoomModelListener::onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit securityEvent(chatRoom, eventLog); -} -void ChatRoomModelListener::onSubjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit subjectChanged(chatRoom, eventLog); -} -void ChatRoomModelListener::onUndecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ - emit undecryptableMessageReceived(chatRoom, message); -} -void ChatRoomModelListener::onParticipantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit participantDeviceAdded(chatRoom, eventLog); -} -void ChatRoomModelListener::onParticipantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit participantDeviceRemoved(chatRoom, eventLog); -} -void ChatRoomModelListener::onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit conferenceJoined(chatRoom, eventLog); -} -void ChatRoomModelListener::onConferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit conferenceLeft(chatRoom, eventLog); -} -void ChatRoomModelListener::onEphemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit ephemeralEvent(chatRoom, eventLog); -} -void ChatRoomModelListener::onEphemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit ephemeralMessageTimerStarted(chatRoom, eventLog); -} -void ChatRoomModelListener::onEphemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog){ - emit ephemeralMessageDeleted(chatRoom, eventLog); -} -void ChatRoomModelListener::onConferenceAddressGeneration(const std::shared_ptr & chatRoom){ - emit conferenceAddressGeneration(chatRoom); -} -void ChatRoomModelListener::onParticipantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress){ - emit participantRegistrationSubscriptionRequested(chatRoom, participantAddress); -} -void ChatRoomModelListener::onParticipantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress){ - emit participantRegistrationUnsubscriptionRequested(chatRoom, participantAddress); -} -void ChatRoomModelListener::onChatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message){ - emit chatMessageShouldBeStored(chatRoom, message); -} -void ChatRoomModelListener::onChatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state){ - emit chatMessageParticipantImdnStateChanged(chatRoom, message, state); +void ChatRoomModel::connectTo(ChatRoomListener * listener){ + connect(listener, &ChatRoomListener::isComposingReceived, this, &ChatRoomModel::onIsComposingReceived); + connect(listener, &ChatRoomListener::messageReceived, this, &ChatRoomModel::onMessageReceived); + connect(listener, &ChatRoomListener::newEvent, this, &ChatRoomModel::onNewEvent); + connect(listener, &ChatRoomListener::chatMessageReceived, this, &ChatRoomModel::onChatMessageReceived); + connect(listener, &ChatRoomListener::chatMessageSending, this, &ChatRoomModel::onChatMessageSending); + connect(listener, &ChatRoomListener::chatMessageSent, this, &ChatRoomModel::onChatMessageSent); + connect(listener, &ChatRoomListener::participantAdded, this, &ChatRoomModel::onParticipantAdded); + connect(listener, &ChatRoomListener::participantRemoved, this, &ChatRoomModel::onParticipantRemoved); + connect(listener, &ChatRoomListener::participantAdminStatusChanged, this, &ChatRoomModel::onParticipantAdminStatusChanged); + connect(listener, &ChatRoomListener::stateChanged, this, &ChatRoomModel::onStateChanged); + connect(listener, &ChatRoomListener::securityEvent, this, &ChatRoomModel::onSecurityEvent); + connect(listener, &ChatRoomListener::subjectChanged, this, &ChatRoomModel::onSubjectChanged); + connect(listener, &ChatRoomListener::undecryptableMessageReceived, this, &ChatRoomModel::onUndecryptableMessageReceived); + connect(listener, &ChatRoomListener::participantDeviceAdded, this, &ChatRoomModel::onParticipantDeviceAdded); + connect(listener, &ChatRoomListener::participantDeviceRemoved, this, &ChatRoomModel::onParticipantDeviceRemoved); + connect(listener, &ChatRoomListener::conferenceJoined, this, &ChatRoomModel::onConferenceJoined); + connect(listener, &ChatRoomListener::conferenceLeft, this, &ChatRoomModel::onConferenceLeft); + connect(listener, &ChatRoomListener::ephemeralEvent, this, &ChatRoomModel::onEphemeralEvent); + connect(listener, &ChatRoomListener::ephemeralMessageTimerStarted, this, &ChatRoomModel::onEphemeralMessageTimerStarted); + connect(listener, &ChatRoomListener::ephemeralMessageDeleted, this, &ChatRoomModel::onEphemeralMessageDeleted); + connect(listener, &ChatRoomListener::conferenceAddressGeneration, this, &ChatRoomModel::onConferenceAddressGeneration); + connect(listener, &ChatRoomListener::participantRegistrationSubscriptionRequested, this, &ChatRoomModel::onParticipantRegistrationSubscriptionRequested); + connect(listener, &ChatRoomListener::participantRegistrationUnsubscriptionRequested, this, &ChatRoomModel::onParticipantRegistrationUnsubscriptionRequested); + connect(listener, &ChatRoomListener::chatMessageShouldBeStored, this, &ChatRoomModel::onChatMessageShouldBeStored); + connect(listener, &ChatRoomListener::chatMessageParticipantImdnStateChanged, this, &ChatRoomModel::onChatMessageParticipantImdnStateChanged); } // ----------------------------------------------------------------------------- -std::shared_ptr ChatRoomModel::create(std::shared_ptr chatRoom){ - std::shared_ptr model = std::make_shared(chatRoom); +QSharedPointer ChatRoomModel::create(std::shared_ptr chatRoom){ + QSharedPointer model = QSharedPointer::create(chatRoom); if(model){ model->mSelf = model; //chatRoom->addListener(model); @@ -190,17 +115,18 @@ std::shared_ptr ChatRoomModel::create(std::shared_ptr chatRoom, QObject * parent) : QAbstractListModel(parent){ +ChatRoomModel::ChatRoomModel (std::shared_ptr chatRoom, QObject * parent) : ProxyListModel(parent){ App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE CoreManager *coreManager = CoreManager::getInstance(); mCoreHandlers = coreManager->getHandlers(); mChatRoom = chatRoom; - mChatRoomModelListener = std::make_shared(this, parent); - mChatRoom->addListener(mChatRoomModelListener); + mChatRoomListener = std::make_shared(parent); + connectTo(mChatRoomListener.get()); + mChatRoom->addListener(mChatRoomListener); // Get messages. - mEntries.clear(); + mList.clear(); setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); setMissedCallsCount(0); @@ -227,13 +153,13 @@ ChatRoomModel::ChatRoomModel (std::shared_ptr chatRoom, QObj //QObject::connect(this, &ChatRoomModel::messageCountReset, coreManager, &CoreManager::eventCountChanged ); if(mChatRoom){ - mParticipantListModel = std::make_shared(this); + mParticipantListModel = QSharedPointer::create(this); connect(mParticipantListModel.get(), &ParticipantListModel::participantsChanged, this, &ChatRoomModel::fullPeerAddressChanged); auto participants = mChatRoom->getParticipants(); for(auto participant : participants){ auto contact = CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(Utils::coreStringToAppString((participant)->getAddress()->asString())); if(contact) { - connect(contact, &ContactModel::contactUpdated, this, &ChatRoomModel::fullPeerAddressChanged); + connect(contact.get(), &ContactModel::contactUpdated, this, &ChatRoomModel::fullPeerAddressChanged); } } // Get Max updatetime from chat room and last call event @@ -252,7 +178,7 @@ ChatRoomModel::ChatRoomModel (std::shared_ptr chatRoom, QObj ChatRoomModel::~ChatRoomModel () { mParticipantListModel = nullptr; if(mChatRoom ){ - mChatRoom->removeListener(mChatRoomModelListener); + mChatRoom->removeListener(mChatRoomListener); if(mDeleteChatRoom){ mDeleteChatRoom = false; if(CoreManager::getInstance()->getCore() ){ @@ -269,6 +195,7 @@ ChatRoomModel::~ChatRoomModel () { mChatRoom = nullptr; } + QHash ChatRoomModel::roleNames () const { QHash roles; roles[Roles::ChatEntry] = "$chatEntry"; @@ -276,57 +203,38 @@ QHash ChatRoomModel::roleNames () const { return roles; } -int ChatRoomModel::rowCount (const QModelIndex &) const { - return mEntries.count(); -} - QVariant ChatRoomModel::data (const QModelIndex &index, int role) const { int row = index.row(); - if (!index.isValid() || row < 0 || row >= mEntries.count()) + if (!index.isValid() || row < 0 || row >= mList.count()) return QVariant(); switch (role) { - case Roles::ChatEntry: { - ChatEvent * ce = mEntries[row].get(); - if( ce->mType == EntryType::MessageEntry) - return QVariant::fromValue(dynamic_cast(ce)); - else if( ce->mType == EntryType::NoticeEntry) - return QVariant::fromValue(dynamic_cast(ce)); - else if( ce->mType == EntryType::CallEntry) - return QVariant::fromValue(dynamic_cast(ce)); - else - return QVariant(); - } - case Roles::SectionDate: - return QVariant::fromValue(mEntries[row]->getTimestamp().date()); + case Roles::ChatEntry: return QVariant::fromValue(mList[row].get()); + case Roles::SectionDate: return QVariant::fromValue(mList[row].objectCast()->getTimestamp().date()); } return QVariant(); } -bool ChatRoomModel::removeRow (int row, const QModelIndex &) { - return removeRows(row, 1); -} - bool ChatRoomModel::removeRows (int row, int count, const QModelIndex &parent) { int limit = row + count - 1; - if (row < 0 || count < 0 || limit >= mEntries.count()) + if (row < 0 || count < 0 || limit >= mList.count()) return false; beginRemoveRows(parent, row, limit); for (int i = 0; i < count; ++i) { - mEntries[row]->deleteEvent(); - mEntries.removeAt(row); + mList[row].objectCast()->deleteEvent(); + mList.removeAt(row); } endRemoveRows(); - if (mEntries.count() == 0) + if (mList.count() == 0) emit allEntriesRemoved(mSelf.lock()); - else if (limit == mEntries.count()) + else if (limit == mList.count()) emit lastEntryRemoved(); emit focused();// Removing rows is like having focus. Don't wait asynchronous events. return true; @@ -338,7 +246,7 @@ void ChatRoomModel::removeAllEntries () { auto core = CoreManager::getInstance()->getCore(); bool standardChatEnabled = CoreManager::getInstance()->getSettingsModel()->getStandardChatEnabled(); beginResetModel(); - mEntries.clear(); + mList.clear(); mChatRoom->deleteHistory(); if( isOneToOne() && // Remove calls only if chat room is one-one and not secure (if available) ( !standardChatEnabled || !isSecure()) @@ -356,15 +264,7 @@ void ChatRoomModel::removeAllEntries () { } void ChatRoomModel::removeEntry(ChatEvent* entry){ - auto it = mEntries.begin(); - while(it != mEntries.end() && (*it).get() != entry) - ++it; - if( it != mEntries.end() ){ - int row = it - mEntries.begin(); - //mEntries.indexOf(entry); - if(row >=0) - removeRow(row); - } + remove(entry); } void ChatRoomModel::emitFullPeerAddressChanged(){ @@ -608,9 +508,10 @@ void ChatRoomModel::updateLastUpdateTime(){ if( mChatRoom ){ QDateTime lastDateTime = QDateTime::fromMSecsSinceEpoch(mChatRoom->getLastUpdateTime()*1000); QDateTime lastCallTime = lastDateTime; - for(auto e : mEntries){ - if(e->mType == CallEntry && e->getTimestamp() > lastCallTime) - lastCallTime = e->getTimestamp(); + for(auto e : mList){ + auto chatEvent = e.objectCast(); + if(chatEvent->mType == CallEntry && chatEvent->getTimestamp() > lastCallTime) + lastCallTime = chatEvent->getTimestamp(); } setLastUpdateTime(lastCallTime); } @@ -727,7 +628,7 @@ void ChatRoomModel::sendMessage (const QString &message) { _messages.back()->addContent(content); } } - auto fileContents = CoreManager::getInstance()->getChatModel()->getContentListModel()->getContents(); + auto fileContents = CoreManager::getInstance()->getChatModel()->getContentListModel()->getSharedList(); for(auto content : fileContents){ if(isBasicChatRoom && _messages.back()->getContents().size() > 0) // Basic chat rooms don't support multipart _messages.push_back(mChatRoom->createEmptyMessage()); @@ -813,7 +714,7 @@ public: ChatRoomModel::EntryType mType; std::shared_ptr mObject; - static void getLimitedSelection(QList > *resultEntries, QList& entries, const int& minEntries, ChatRoomModel * chatRoomModel) {// Sort and return a selection with at least 'minEntries' + static void getLimitedSelection(QList > *resultEntries, QList& entries, const int& minEntries, ChatRoomModel * chatRoomModel) {// Sort and return a selection with at least 'minEntries' // Sort list std::sort(entries.begin(), entries.end(), [](const EntrySorterHelper& a, const EntrySorterHelper& b) { return a.mTime < b.mTime; @@ -884,7 +785,7 @@ void ChatRoomModel::updateNewMessageNotice(const int& count){ } mUnreadMessageNotice = ChatNoticeModel::create(ChatNoticeModel::NoticeType::NoticeUnreadMessages, lastUnreadMessage, QString::number(count)); beginInsertRows(QModelIndex(), 0, 0); - mEntries.prepend(mUnreadMessageNotice); + mList.prepend(mUnreadMessageNotice); endInsertRows(); qDebug() << "New message notice timestamp to :" << lastUnreadMessage.toString(); } @@ -897,17 +798,19 @@ int ChatRoomModel::loadTillMessage(ChatMessageModel * message){ qDebug() << "Load history till message : " << message->getChatMessage()->getMessageId().c_str(); auto linphoneMessage = message->getChatMessage(); // First find on current list - auto entry = std::find_if(mEntries.begin(), mEntries.end(), [linphoneMessage](const std::shared_ptr& entry ){ - return entry->mType == ChatRoomModel::EntryType::MessageEntry && dynamic_cast(entry.get())->getChatMessage() == linphoneMessage; + auto entry = std::find_if(mList.begin(), mList.end(), [linphoneMessage](const QSharedPointer& entry ){ + auto chatEventEntry = entry.objectCast(); + return chatEventEntry->mType == ChatRoomModel::EntryType::MessageEntry && chatEventEntry.objectCast()->getChatMessage() == linphoneMessage; }); // if not find, load more entries and find it in new entries. - if( entry == mEntries.end()){ + if( entry == mList.end()){ int newEntries = loadMoreEntries(); while( newEntries > 0){// no more new entries int entryCount = 0; - entry = mEntries.begin(); + entry = mList.begin(); + auto chatEventEntry = entry->objectCast(); while(entryCount < newEntries && - ((*entry)->mType != ChatRoomModel::EntryType::MessageEntry || dynamic_cast(entry->get())->getChatMessage() != linphoneMessage) + (chatEventEntry->mType != ChatRoomModel::EntryType::MessageEntry || chatEventEntry.objectCast()->getChatMessage() != linphoneMessage) ){ ++entryCount; ++entry; @@ -919,7 +822,7 @@ int ChatRoomModel::loadTillMessage(ChatMessageModel * message){ newEntries = loadMoreEntries();// continue } }else{ - int entryCount = entry - mEntries.begin(); + int entryCount = entry - mList.begin(); qDebug() << "Find message at " << entryCount; return entryCount; } @@ -928,19 +831,13 @@ int ChatRoomModel::loadTillMessage(ChatMessageModel * message){ return -1; } -void ChatRoomModel::resetEntries(){ - beginResetModel(); - mEntries.clear(); - endResetModel(); -} - void ChatRoomModel::initEntries(){ - if( mEntries.size() > mLastEntriesStep) - resetEntries(); - if(mEntries.size() == 0) { + if( mList.size() > mLastEntriesStep) + resetData(); + if(mList.size() == 0) { qDebug() << "Internal Entries : Init"; // On call : reinitialize all entries. This allow to free up memory - QList > entries; + QList > entries; QList prepareEntries; // Get chat messages for (auto &message : mChatRoom->getHistory(mFirstLastEntriesStep)) { @@ -966,9 +863,10 @@ void ChatRoomModel::initEntries(){ qDebug() << "Internal Entries : Built"; if(entries.size() >0){ beginInsertRows(QModelIndex(),0, entries.size()-1); - mEntries = entries; - updateNewMessageNotice(mChatRoom->getUnreadMessagesCount()); + for(auto e : entries) + mList.push_back(e); endInsertRows(); + updateNewMessageNotice(mChatRoom->getUnreadMessagesCount()); } qDebug() << "Internal Entries : End"; } @@ -987,16 +885,17 @@ int ChatRoomModel::loadMoreEntries(){ int currentRowCount = rowCount(); int newEntries = 0; do{ - QList > entries; + QList > entries; QList prepareEntries; // Get current event count for each type QVector entriesCounts; entriesCounts.resize(3); - for(auto itEntries = mEntries.begin() ; itEntries != mEntries.end() ; ++itEntries){ - if( (*itEntries)->mType == MessageEntry) + for(auto itEntries = mList.begin() ; itEntries != mList.end() ; ++itEntries){ + auto chatEvent = itEntries->objectCast(); + if( chatEvent->mType == MessageEntry) ++entriesCounts[0]; - else if( (*itEntries)->mType == CallEntry){ - if(dynamic_cast((*itEntries).get())->mIsStart) + else if( chatEvent->mType == CallEntry){ + if(chatEvent.objectCast()->mIsStart) ++entriesCounts[1]; } else ++entriesCounts[2]; @@ -1004,10 +903,10 @@ int ChatRoomModel::loadMoreEntries(){ // Messages for (auto &message : mChatRoom->getHistoryRange(entriesCounts[0], entriesCounts[0]+mLastEntriesStep)){ - auto itEntries = mEntries.begin(); + auto itEntries = mList.begin(); bool haveEntry = false; - while(!haveEntry && itEntries != mEntries.end()){ - auto entry = dynamic_cast(itEntries->get()); + while(!haveEntry && itEntries != mList.end()){ + auto entry = itEntries->objectCast(); haveEntry = (entry && entry->getChatMessage() == message); ++itEntries; } @@ -1036,10 +935,10 @@ int ChatRoomModel::loadMoreEntries(){ } // Notices for (auto &eventLog : mChatRoom->getHistoryRangeEvents(entriesCounts[2], entriesCounts[2]+mLastEntriesStep)){ - auto itEntries = mEntries.begin(); + auto itEntries = mList.begin(); bool haveEntry = false; - while(!haveEntry && itEntries != mEntries.end()){ - auto entry = dynamic_cast(itEntries->get()); + while(!haveEntry && itEntries != mList.end()){ + auto entry = itEntries->objectCast(); haveEntry = (entry && entry->getEventLog() && entry->getEventLog() == eventLog); ++itEntries; } @@ -1050,7 +949,7 @@ int ChatRoomModel::loadMoreEntries(){ if(entries.size() >0){ beginInsertRows(QModelIndex(), 0, entries.size()-1); for(auto entry : entries) - mEntries.prepend(entry); + mList.prepend(entry); endInsertRows(); //emit layoutChanged(); updateLastUpdateTime(); @@ -1080,20 +979,16 @@ void ChatRoomModel::callEnded(std::shared_ptr call){ void ChatRoomModel::insertCall (const std::shared_ptr &callLog) { if(mIsInitialized){ - std::shared_ptr model = ChatCallModel::create(callLog, true, this); + QSharedPointer model = ChatCallModel::create(callLog, true, this); if(model){ - int row = mEntries.count(); + int row = mList.count(); beginInsertRows(QModelIndex(), row, row); - mEntries << model; + mList << model; endInsertRows(); if (callLog->getStatus() == linphone::Call::Status::Success) { model = ChatCallModel::create(callLog, false, this); - if(model){ - int row = mEntries.count(); - beginInsertRows(QModelIndex(), row, row); - mEntries << model; - endInsertRows(); - } + if(model) + add(model); } updateLastUpdateTime(); } @@ -1102,9 +997,9 @@ void ChatRoomModel::insertCall (const std::shared_ptr &callLo void ChatRoomModel::insertCalls (const QList > &calls) { if(mIsInitialized){ - QList > entries; + QList > entries; for(auto callLog : calls) { - std::shared_ptr model = ChatCallModel::create(callLog, true, this); + QSharedPointer model = ChatCallModel::create(callLog, true, this); if(model){ entries << model; if (callLog->getStatus() == linphone::Call::Status::Success) { @@ -1116,10 +1011,7 @@ void ChatRoomModel::insertCalls (const QList } } if(entries.size() > 0){ - beginInsertRows(QModelIndex(), 0, entries.size()-1); - entries << mEntries; - mEntries = entries; - endInsertRows(); + prepend(entries); emit layoutChanged(); } } @@ -1127,30 +1019,24 @@ void ChatRoomModel::insertCalls (const QList void ChatRoomModel::insertMessageAtEnd (const std::shared_ptr &message) { if(mIsInitialized){ - std::shared_ptr model = ChatMessageModel::create(message, this); + QSharedPointer model = ChatMessageModel::create(message, this); if(model){ setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); - int row = mEntries.count(); - beginInsertRows(QModelIndex(), row, row); - mEntries << model; - endInsertRows(); + add(model); } } } void ChatRoomModel::insertMessages (const QList > &messages) { if(mIsInitialized){ - QList > entries; + QList > entries; for(auto message : messages) { - std::shared_ptr model = ChatMessageModel::create(message, this); + QSharedPointer model = ChatMessageModel::create(message, this); if(model) entries << model; } if(entries.size() > 0){ - beginInsertRows(QModelIndex(), 0, entries.size()-1); - entries << mEntries; - mEntries = entries; - endInsertRows(); + prepend(entries); setUnreadMessagesCount(mChatRoom->getUnreadMessagesCount()); emit layoutChanged(); } @@ -1159,32 +1045,23 @@ void ChatRoomModel::insertMessages (const QList &eventLog) { if(mIsInitialized){ - std::shared_ptr model = ChatNoticeModel::create(eventLog, this); - if(model){ - int row = mEntries.count(); - beginInsertRows(QModelIndex(), row, row); - mEntries << model; - endInsertRows(); - } + QSharedPointer model = ChatNoticeModel::create(eventLog, this); + if(model) + add(model); } } void ChatRoomModel::insertNotices (const QList> &eventLogs) { if(mIsInitialized){ - QList > entries; - + QList > entries; for(auto eventLog : eventLogs) { - std::shared_ptr model = ChatNoticeModel::create(eventLog, this); + QSharedPointer model = ChatNoticeModel::create(eventLog, this); if(model) { entries << model; } } - if(entries.size() > 0){ - beginInsertRows(QModelIndex(), 0, entries.size()-1); - entries << mEntries; - mEntries = entries; - endInsertRows(); + prepend(entries); emit layoutChanged(); } } diff --git a/linphone-app/src/components/chat-room/ChatRoomModel.hpp b/linphone-app/src/components/chat-room/ChatRoomModel.hpp index a958cc86f..886ad5fb6 100644 --- a/linphone-app/src/components/chat-room/ChatRoomModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomModel.hpp @@ -22,7 +22,7 @@ #define CHAT_ROOM_MODEL_H_ #include -#include +#include "app/proxyModel/ProxyListModel.hpp" #include // ============================================================================= @@ -37,70 +37,9 @@ class ContactModel; class ChatRoomModel; class ChatMessageModel; class ChatNoticeModel; +class ChatRoomListener; -class ChatRoomModelListener : public QObject, public linphone::ChatRoomListener { -Q_OBJECT -public: - ChatRoomModelListener(ChatRoomModel * model, QObject * parent = nullptr); - virtual ~ChatRoomModelListener(){} - - virtual void onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing) override; - virtual void onMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; - virtual void onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onChatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onChatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onChatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState) override; - virtual void onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onSubjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onUndecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; - virtual void onParticipantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onConferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onEphemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onEphemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onConferenceAddressGeneration(const std::shared_ptr & chatRoom) override; - virtual void onParticipantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress) override; - virtual void onParticipantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress) override; - virtual void onChatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; - virtual void onChatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state) override; - -signals: - void isComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing); - void messageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message); - void newEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void chatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void chatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void chatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void participantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void participantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void participantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void stateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState); - void securityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void subjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void undecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message); - void participantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void participantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void conferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void conferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void ephemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void ephemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void ephemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); - void conferenceAddressGeneration(const std::shared_ptr & chatRoom); - void participantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress); - void participantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress); - void chatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message); - void chatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state); - -}; - -class ChatRoomModel : public QAbstractListModel { - class MessageHandlers; +class ChatRoomModel : public ProxyListModel { Q_OBJECT @@ -154,16 +93,13 @@ public: Q_PROPERTY(bool entriesLoading READ isEntriesLoading WRITE setEntriesLoading NOTIFY entriesLoadingChanged) - static std::shared_ptr create(std::shared_ptr chatRoom); + static QSharedPointer create(std::shared_ptr chatRoom); ChatRoomModel (std::shared_ptr chatRoom, QObject * parent = nullptr); ~ChatRoomModel (); - int rowCount (const QModelIndex &index = QModelIndex()) const override; - QHash roleNames () const override; QVariant data (const QModelIndex &index, int role) const override; - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; void removeAllEntries (); @@ -231,7 +167,6 @@ public: Q_INVOKABLE void forwardMessage(ChatMessageModel * model); void compose (); Q_INVOKABLE void resetMessageCount (); - Q_INVOKABLE void resetEntries(); void initEntries(); Q_INVOKABLE int loadMoreEntries(); // return new entries count void callEnded(std::shared_ptr call); @@ -297,7 +232,7 @@ signals: void entriesLoadingChanged(const bool& loading); void moreEntriesLoaded(const int& count); - void allEntriesRemoved (std::shared_ptr model); + void allEntriesRemoved (QSharedPointer model); void lastEntryRemoved (); void messageSent (const std::shared_ptr &message); @@ -343,6 +278,8 @@ signals: void conferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); private: + + void connectTo(ChatRoomListener * listener); void handleCallStateChanged (const std::shared_ptr &call, linphone::Call::State state); void handleCallCreated(const std::shared_ptr &call);// Count an event call @@ -350,21 +287,19 @@ private: //void handleIsComposingChanged (const std::shared_ptr &chatRoom); //void handleMessageReceived (const std::shared_ptr &message); - //bool mIsRemoteComposing = false; - std::shared_ptr mUnreadMessageNotice; - QList > mEntries; - std::shared_ptr mParticipantListModel; - std::shared_ptr mCoreHandlers; - std::shared_ptr mMessageHandlers; - QMap, QString> mComposers; // Store all addresses that are composing with its username std::shared_ptr mChatRoom; - std::shared_ptr mChatRoomModelListener; + std::shared_ptr mChatRoomListener; // This need to be a shared_ptr because of adding it to linphone + std::shared_ptr mCoreHandlers; // This need to be a shared_ptr because of adding it to linphone - std::shared_ptr mReplyModel; + QMap, QString> mComposers; // Store all addresses that are composing with its username - std::weak_ptr mSelf; + QSharedPointer mParticipantListModel; + QSharedPointer mReplyModel; + QSharedPointer mUnreadMessageNotice; + + QWeakPointer mSelf; }; -Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(QSharedPointer) #endif // CHAT_ROOM_MODEL_H_ diff --git a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp index ed0b32221..c8b5111ef 100644 --- a/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp +++ b/linphone-app/src/components/chat-room/ChatRoomProxyModel.hpp @@ -146,7 +146,7 @@ private: QString mFilterText; - std::shared_ptr mChatRoomModel; + QSharedPointer mChatRoomModel; static constexpr int EntriesChunkSize = 50; }; diff --git a/linphone-app/src/components/chat/ChatModel.cpp b/linphone-app/src/components/chat/ChatModel.cpp index b3377a105..158eb0b5f 100644 --- a/linphone-app/src/components/chat/ChatModel.cpp +++ b/linphone-app/src/components/chat/ChatModel.cpp @@ -40,10 +40,10 @@ ChatModel::ChatModel(QObject * parent ) : QObject(parent){ App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE - mContents = std::make_shared(nullptr); + mContents = QSharedPointer::create(nullptr); } -std::shared_ptr ChatModel::getContentListModel() const { +QSharedPointer ChatModel::getContentListModel() const { return mContents; } diff --git a/linphone-app/src/components/chat/ChatModel.hpp b/linphone-app/src/components/chat/ChatModel.hpp index 5197ccf7f..929d5a687 100644 --- a/linphone-app/src/components/chat/ChatModel.hpp +++ b/linphone-app/src/components/chat/ChatModel.hpp @@ -28,6 +28,8 @@ #include #include #include +#include + class ContentListModel; class ChatModel : public QObject{ @@ -36,13 +38,13 @@ public: ChatModel(QObject * parent = nullptr); // Getters - std::shared_ptr getContentListModel() const; + QSharedPointer getContentListModel() const; // Tools Q_INVOKABLE void clear(); private: - std::shared_ptr mContents; + QSharedPointer mContents; }; #endif diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp index d571cd2b6..34b30d5d4 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.cpp @@ -35,7 +35,7 @@ // ============================================================================= -ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : QAbstractListModel(parent) { +ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : ProxyListModel(parent) { //auto conferenceInfos = CoreManager::getInstance()->getCore()->getConferenceInformationList(); //for(auto conferenceInfo : conferenceInfos){ // auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo ); @@ -44,60 +44,8 @@ ConferenceInfoListModel::ConferenceInfoListModel (QObject *parent) : QAbstractLi // } } -int ConferenceInfoListModel::rowCount (const QModelIndex &) const { - return mList.size(); -} - -QHash ConferenceInfoListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$conferenceInfo"; - return roles; -} - -QVariant ConferenceInfoListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mList.size()) - return QVariant(); - auto it = mList.begin() + row; - - if (role == Qt::DisplayRole) - return QVariant::fromValue(it->get()); - - return QVariant(); -} - ConferenceInfoModel* ConferenceInfoListModel::getAt(const int& index) const { - return mList[index].get(); -} - -// ----------------------------------------------------------------------------- -void ConferenceInfoListModel::add(std::shared_ptr conferenceInfoModel){ - int row = mList.size(); - beginInsertRows(QModelIndex(), row,row); - mList << conferenceInfoModel; - endInsertRows(); -} -// Should not be called as item that need to be removed are usually a cell, not a row -bool ConferenceInfoListModel::removeRow (int row, const QModelIndex &parent) { - return removeRows(row, 1, parent); -} - -bool ConferenceInfoListModel::removeRows (int row, int count, const QModelIndex &parent) { -/* - int limit = row + count - 1; - - if (row < 0 || count < 0 || limit >= mMappedList.count()) - return false; - - beginRemoveRows(parent, row, limit); - - for (int i = 0; i < count; ++i) - mMappedList.takeAt(row)->deleteLater(); - - endRemoveRows(); - */ - return true; + return ProxyListModel::getAt(index).objectCast().get(); } // ----------------------------------------------------------------------------- diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp index f6a5528bb..95631e513 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoListModel.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Belledonne Communications SARL. + * Copyright (c) 2021-2022 Belledonne Communications SARL. * * This file is part of linphone-desktop * (see https://www.linphone.org). @@ -22,33 +22,20 @@ #define _CONFERENCE_INFO_LIST_MODEL_H_ #include -#include +#include "app/proxyModel/ProxyListModel.hpp" #include // ============================================================================= class ConferenceInfoModel; -class ConferenceInfoListModel : public QAbstractListModel { +class ConferenceInfoListModel : public ProxyListModel { Q_OBJECT public: ConferenceInfoListModel (QObject *parent = Q_NULLPTR); - int rowCount (const QModelIndex &index = QModelIndex()) const override; - - QHash roleNames () const override; - QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; ConferenceInfoModel* getAt(const int& index) const; - void add(std::shared_ptr conferenceInfoModel); - -private: - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - - QList> mList; - //QMap> mMappedList; - }; Q_DECLARE_METATYPE(QList*) #endif diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.cpp index 8ece03e55..e53f111b9 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.cpp @@ -32,6 +32,7 @@ #include "components/settings/SettingsModel.hpp" #include "utils/Utils.hpp" +#include "ConferenceInfoProxyModel.hpp" #include "ConferenceInfoListModel.hpp" #include "ConferenceInfoModel.hpp" @@ -51,7 +52,7 @@ ConferenceInfoMapModel::ConferenceInfoMapModel (QObject *parent) : QAbstractList auto conferenceInfoModel = ConferenceInfoModel::create( conferenceInfo ); QDate t = conferenceInfoModel->getDateTime().date(); if( !mMappedList.contains(t)) - mMappedList[t] = new ConferenceInfoListModel(); + mMappedList[t] = new ConferenceInfoProxyModel(new ConferenceInfoListModel(), this); mMappedList[t]->add(conferenceInfoModel); } } @@ -84,3 +85,9 @@ QVariant ConferenceInfoMapModel::data (const QModelIndex &index, int role) const } // ----------------------------------------------------------------------------- + +void ConferenceInfoMapModel::setConferenceInfoFilter (int filterMode){ + for(auto list : mMappedList){ + list->setConferenceInfoFilter(filterMode); + } +} \ No newline at end of file diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.hpp index 68d6047d6..92d8c38b3 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoMapModel.hpp @@ -27,7 +27,7 @@ // ============================================================================= -class ConferenceInfoListModel; +class ConferenceInfoProxyModel; class ConferenceInfoMapModel : public QAbstractListModel { Q_OBJECT @@ -39,9 +39,11 @@ public: QHash roleNames () const override; QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; + + Q_INVOKABLE void setConferenceInfoFilter (int filterMode); private: - QMap mMappedList; + QMap mMappedList; }; Q_DECLARE_METATYPE(ConferenceInfoMapModel*) diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp index ff7b92baf..d48b5ccc2 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.cpp @@ -45,7 +45,7 @@ #include "components/contact/ContactModel.hpp" #include "components/contact/VcardModel.hpp" #include "components/contacts/ContactsListModel.hpp" -#include "components/conferenceScheduler/ConferenceSchedulerModel.hpp" +#include "components/conferenceScheduler/ConferenceSchedulerHandler.hpp" #include "components/core/CoreHandlers.hpp" #include "components/core/CoreManager.hpp" #include "components/notifier/Notifier.hpp" @@ -73,8 +73,8 @@ using namespace std; // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- -std::shared_ptr ConferenceInfoModel::create(std::shared_ptr conferenceInfo){ - std::shared_ptr model = std::make_shared(conferenceInfo); +QSharedPointer ConferenceInfoModel::create(std::shared_ptr conferenceInfo){ + QSharedPointer model = QSharedPointer::create(conferenceInfo); if(model){ model->mSelf = model; //chatRoom->addListener(model); @@ -113,9 +113,7 @@ QDateTime ConferenceInfoModel::getDateTime() const{ } int ConferenceInfoModel::getDuration() const{ - int duration = mConferenceInfo->getDuration(); - qWarning() << "Duration: " << duration; - return duration; + return mConferenceInfo->getDuration(); } QDateTime ConferenceInfoModel::getEndDateTime() const{ @@ -203,10 +201,10 @@ void ConferenceInfoModel::createConference(const int& securityLevel, const int& qInfo() << "Conference creation of " << getSubject() << " at " << securityLevel << " security, organized by " << getOrganizer();// and with " << conferenceInfo->getConferenceInfo()->getParticipants().size(); if( true || isScheduled()){ - mConferenceSchedulerModel = ConferenceSchedulerModel::create(this); - connect(mConferenceSchedulerModel.get(), &ConferenceSchedulerModel::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent); + mConferenceSchedulerHandler = ConferenceSchedulerHandler::create(this); + connect(mConferenceSchedulerHandler.get(), &ConferenceSchedulerHandler::invitationsSent, this, &ConferenceInfoModel::onInvitationsSent); - mConferenceSchedulerModel->getConferenceScheduler()->setInfo(mConferenceInfo); + mConferenceSchedulerHandler->getConferenceScheduler()->setInfo(mConferenceInfo); }else{ auto conferenceParameters = core->createConferenceParams(nullptr); conferenceParameters->enableAudio(true); @@ -235,6 +233,6 @@ void ConferenceInfoModel::createConference(const int& securityLevel, const int& void ConferenceInfoModel::onInvitationsSent(const std::list> & failedInvitations) { - mConferenceSchedulerModel->getConferenceScheduler()->removeListener(mConferenceSchedulerModel); + mConferenceSchedulerHandler->getConferenceScheduler()->removeListener(mConferenceSchedulerHandler); emit invitationsSent(); } \ No newline at end of file diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp index a947ee9ed..30b2fd850 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoModel.hpp @@ -24,9 +24,10 @@ #include #include #include +#include class ParticipantListModel; -class ConferenceSchedulerModel; +class ConferenceSchedulerHandler; class ConferenceInfoModel : public QObject { Q_OBJECT @@ -45,7 +46,7 @@ public: //Q_PROPERTY(participants READ getParticipants WRITE setParticipants NOTIFY participantsChanged) - static std::shared_ptr create(std::shared_ptr conferenceInfo); + static QSharedPointer create(std::shared_ptr conferenceInfo); ConferenceInfoModel (QObject * parent = nullptr); ConferenceInfoModel (std::shared_ptr conferenceInfo, QObject * parent = nullptr); ~ConferenceInfoModel (); @@ -96,12 +97,13 @@ signals: private: std::shared_ptr mConferenceInfo; - std::shared_ptr mConferenceSchedulerModel = nullptr; - std::weak_ptr mSelf; // For Linphone listener + std::shared_ptr mConferenceSchedulerHandler = nullptr; + + QWeakPointer mSelf; // For Linphone listener bool mIsScheduled = true; }; -Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(QSharedPointer) Q_DECLARE_METATYPE(ConferenceInfoModel*) #endif diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp index 4ecda8630..6225f34e4 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.cpp @@ -30,12 +30,54 @@ using namespace std; ConferenceInfoProxyModel::ConferenceInfoProxyModel (QObject *parent) : QSortFilterProxyModel(parent) { + mEntryTypeFilter = ConferenceType::Scheduled; setSourceModel(new ConferenceInfoMapModel()); sort(0, Qt::DescendingOrder); } +ConferenceInfoProxyModel::ConferenceInfoProxyModel (ConferenceInfoListModel * list, QObject *parent) : QSortFilterProxyModel(parent) { + mEntryTypeFilter = ConferenceType::Scheduled; + setSourceModel(list); + sort(0, Qt::DescendingOrder); +} + +int ConferenceInfoProxyModel::getConferenceInfoFilter () { + return mEntryTypeFilter; +} + +void ConferenceInfoProxyModel::setConferenceInfoFilter (int filterMode) { + if (getConferenceInfoFilter() != filterMode) { + mEntryTypeFilter = filterMode; + invalidate(); + emit conferenceInfoFilterChanged(filterMode); + } +} + bool ConferenceInfoProxyModel::filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const { return true; +/* + bool show = false; + QModelIndex index = sourceModel()->index(sourceRow, 0, QModelIndex()); + const ConferenceInfoListModel* ics = sourceModel()->data(index).value(); + + + if( mEntryTypeFilter == ConferenceType::Ended && ics->eventModel.value() != nullptr) + show = true; + else if( mEntryTypeFilter == ChatRoomModel::EntryType::MessageEntry && eventModel.value() != nullptr) + show = true; + else if( mEntryTypeFilter == ChatRoomModel::EntryType::NoticeEntry && eventModel.value() != nullptr) + show = true; + } + if( show && mFilterText != ""){ + QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + auto eventModel = sourceModel()->data(index); + ChatMessageModel * chatModel = eventModel.value(); + if( chatModel){ + QRegularExpression search(QRegularExpression::escape(mFilterText), QRegularExpression::CaseInsensitiveOption | QRegularExpression::UseUnicodePropertiesOption); + show = chatModel->mContent.contains(search); + } + } + return show;*/ } bool ConferenceInfoProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { @@ -48,4 +90,8 @@ bool ConferenceInfoProxyModel::lessThan (const QModelIndex &left, const QModelIn QVariant ConferenceInfoProxyModel::getAt(int row){ QModelIndex sourceIndex = mapToSource(this->index(row, 0)); return sourceModel()->data(sourceIndex); +} + +void ConferenceInfoProxyModel::add(QSharedPointer conferenceInfoModel){ + qobject_cast(sourceModel())->add(conferenceInfoModel); } \ No newline at end of file diff --git a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.hpp b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.hpp index 9864b1406..6475b7eeb 100644 --- a/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.hpp +++ b/linphone-app/src/components/conferenceInfo/ConferenceInfoProxyModel.hpp @@ -22,23 +22,42 @@ #define CONFERENCE_INFO_PROXY_MODEL_H_ #include +#include #include "ConferenceInfoModel.hpp" // ============================================================================= class QWindow; +class ConferenceInfoListModel; class ConferenceInfoProxyModel : public QSortFilterProxyModel { class ChatRoomModelFilter; - Q_OBJECT - public: + + Q_PROPERTY(int conferenceInfoFilter READ getConferenceInfoFilter WRITE setConferenceInfoFilter NOTIFY conferenceInfoFilterChanged) + + enum ConferenceType { + Ended, + Scheduled, + Invitations + }; + Q_ENUM(ConferenceType) + ConferenceInfoProxyModel (QObject *parent = Q_NULLPTR); + ConferenceInfoProxyModel (ConferenceInfoListModel * list, QObject *parent = Q_NULLPTR); + + int getConferenceInfoFilter (); + Q_INVOKABLE void setConferenceInfoFilter (int filterMode); Q_INVOKABLE QVariant getAt(int row); + + void add(QSharedPointer conferenceInfoModel); + +signals: + void conferenceInfoFilterChanged(int); protected: bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; @@ -49,7 +68,8 @@ private: ConferenceInfoModel *getConferenceInfoModel() const; void setConferenceInfoModel (ConferenceInfoModel *conferenceInfoModel); - std::shared_ptr mConferenceInfoModel; + int mEntryTypeFilter; + QSharedPointer mConferenceInfoModel; }; #endif diff --git a/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerModel.cpp b/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerHandler.cpp similarity index 66% rename from linphone-app/src/components/conferenceScheduler/ConferenceSchedulerModel.cpp rename to linphone-app/src/components/conferenceScheduler/ConferenceSchedulerHandler.cpp index 01de9fed8..1374ccc80 100644 --- a/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerModel.cpp +++ b/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerHandler.cpp @@ -18,15 +18,15 @@ * along with this program. If not, see . */ -#include "ConferenceSchedulerModel.hpp" +#include "ConferenceSchedulerHandler.hpp" #include #include "app/App.hpp" #include "components/core/CoreManager.hpp" // ============================================================================= -std::shared_ptr ConferenceSchedulerModel::create( QObject *parent){ - std::shared_ptr model = std::make_shared(parent); +std::shared_ptr ConferenceSchedulerHandler::create( QObject *parent){ + std::shared_ptr model = std::make_shared(parent); if(model){ model->mSelf = model; model->mConferenceScheduler->addListener(model); @@ -35,21 +35,21 @@ std::shared_ptr ConferenceSchedulerModel::create( QObj return nullptr; } -ConferenceSchedulerModel::ConferenceSchedulerModel (QObject * parent) : QObject(parent){ +ConferenceSchedulerHandler::ConferenceSchedulerHandler (QObject * parent) : QObject(parent){ App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mConferenceScheduler = CoreManager::getInstance()->getCore()->createConferenceScheduler(); } -ConferenceSchedulerModel::~ConferenceSchedulerModel () { +ConferenceSchedulerHandler::~ConferenceSchedulerHandler () { } -std::shared_ptr ConferenceSchedulerModel::getConferenceScheduler(){ +std::shared_ptr ConferenceSchedulerHandler::getConferenceScheduler(){ return mConferenceScheduler; } -void ConferenceSchedulerModel::onStateChanged(const std::shared_ptr & conferenceScheduler, linphone::ConferenceSchedulerState state) { +void ConferenceSchedulerHandler::onStateChanged(const std::shared_ptr & conferenceScheduler, linphone::ConferenceSchedulerState state) { emit stateChanged(state); - qWarning() << "ConferenceSchedulerModel::onStateChanged : " << (int)state; + qWarning() << "ConferenceSchedulerHandler::onStateChanged : " << (int)state; if( state == linphone::ConferenceSchedulerState::Ready) { std::shared_ptr params = CoreManager::getInstance()->getCore()->createDefaultChatRoomParams(); params->setBackend(linphone::ChatRoomBackend::Basic); @@ -57,6 +57,6 @@ void ConferenceSchedulerModel::onStateChanged(const std::shared_ptr & conferenceScheduler, const std::list> & failedInvitations) { +void ConferenceSchedulerHandler::onInvitationsSent(const std::shared_ptr & conferenceScheduler, const std::list> & failedInvitations) { emit invitationsSent(failedInvitations); } \ No newline at end of file diff --git a/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerModel.hpp b/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerHandler.hpp similarity index 78% rename from linphone-app/src/components/conferenceScheduler/ConferenceSchedulerModel.hpp rename to linphone-app/src/components/conferenceScheduler/ConferenceSchedulerHandler.hpp index 110dae8ad..9bd478836 100644 --- a/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerModel.hpp +++ b/linphone-app/src/components/conferenceScheduler/ConferenceSchedulerHandler.hpp @@ -18,22 +18,22 @@ * along with this program. If not, see . */ -#ifndef CONFERENCE_SCHEDULER_MODEL_H_ -#define CONFERENCE_SCHEDULER_MODEL_H_ +#ifndef CONFERENCE_SCHEDULER_HANDLER_H_ +#define CONFERENCE_SCHEDULER_HANDLER_H_ #include #include #include -class ConferenceSchedulerModel : public QObject +class ConferenceSchedulerHandler : public QObject , public linphone::ConferenceSchedulerListener { Q_OBJECT public: - static std::shared_ptr create(QObject *parent = Q_NULLPTR); - ConferenceSchedulerModel (QObject * parent = nullptr); - ~ConferenceSchedulerModel (); + static std::shared_ptr create(QObject *parent = Q_NULLPTR); + ConferenceSchedulerHandler (QObject * parent = nullptr); + ~ConferenceSchedulerHandler (); std::shared_ptr getConferenceScheduler(); virtual void onStateChanged(const std::shared_ptr & conferenceScheduler, linphone::ConferenceSchedulerState state) override; @@ -45,10 +45,10 @@ signals: private: std::shared_ptr mConferenceScheduler; - std::weak_ptr mSelf; // Used for Linphone Listener + std::weak_ptr mSelf; // Used for Linphone Listener }; -Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(std::shared_ptr) #endif diff --git a/linphone-app/src/components/contacts/ContactsImporterListModel.cpp b/linphone-app/src/components/contacts/ContactsImporterListModel.cpp index 9b3d9206c..a0dd5dbe7 100644 --- a/linphone-app/src/components/contacts/ContactsImporterListModel.cpp +++ b/linphone-app/src/components/contacts/ContactsImporterListModel.cpp @@ -31,7 +31,7 @@ using namespace std; -ContactsImporterListModel::ContactsImporterListModel (QObject *parent) : QAbstractListModel(parent) { +ContactsImporterListModel::ContactsImporterListModel (QObject *parent) : ProxyListModel(parent) { // Init contacts with linphone friends list. mMaxContactsImporterId = -1; QQmlEngine *engine = App::getInstance()->getEngine(); @@ -53,10 +53,10 @@ ContactsImporterListModel::ContactsImporterListModel (QObject *parent) : QAbstra QString pluginID = Utils::coreStringToAppString(config->getString(section, *keyName, "")); PluginDataAPI* data = static_cast(PluginsManager::createInstance(pluginID)); if(data) { - ContactsImporterModel * model = new ContactsImporterModel(data, this); + auto model = QSharedPointer::create(data, this); // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership // The returned value must have a explicit parent or a QQmlEngine::CppOwnership. - engine->setObjectOwnership(model, QQmlEngine::CppOwnership); + engine->setObjectOwnership(model.get(), QQmlEngine::CppOwnership); model->setIdentity(id); model->loadConfiguration();// Read the configuration contacts inside the plugin addContactsImporter(model); @@ -64,38 +64,11 @@ ContactsImporterListModel::ContactsImporterListModel (QObject *parent) : QAbstra } } } - } } // GUI methods -int ContactsImporterListModel::rowCount (const QModelIndex &) const { - return mList.count(); -} - -QHash ContactsImporterListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$contactsImporter"; - return roles; -} - -QVariant ContactsImporterListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mList.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return QVariant::fromValue(mList[row]); - - return QVariant(); -} - -bool ContactsImporterListModel::removeRow (int row, const QModelIndex &parent) { - return removeRows(row, 1, parent); -} - bool ContactsImporterListModel::removeRows (int row, int count, const QModelIndex &parent) { int limit = row + count - 1; @@ -105,9 +78,7 @@ bool ContactsImporterListModel::removeRows (int row, int count, const QModelInde beginRemoveRows(parent, row, limit); for (int i = 0; i < count; ++i) { - ContactsImporterModel *contactsImporter = dynamic_cast(mList.takeAt(row)); - emit contactsImporterRemoved(contactsImporter); - contactsImporter->deleteLater(); + emit contactsImporterRemoved(mList.takeAt(row).objectCast()); } endRemoveRows(); @@ -117,27 +88,23 @@ bool ContactsImporterListModel::removeRows (int row, int count, const QModelInde // ----------------------------------------------------------------------------- -ContactsImporterModel *ContactsImporterListModel::findContactsImporterModelFromId (const int &id) const { - auto it = find_if(mList.begin(), mList.end(), [id](PluginsModel *contactsImporterModel) { - return contactsImporterModel->getIdentity() == id; +QSharedPointer ContactsImporterListModel::findContactsImporterModelFromId (const int &id) const { + auto it = find_if(mList.begin(), mList.end(), [id](QSharedPointer contactsImporterModel) { + return contactsImporterModel.objectCast()->getIdentity() == id; }); - return it != mList.end() ? dynamic_cast(*it) : nullptr; -} - -QList ContactsImporterListModel::getList(){ - return mList; + return it != mList.end() ? it->objectCast() : nullptr; } // ----------------------------------------------------------------------------- ContactsImporterModel *ContactsImporterListModel::createContactsImporter(QVariantMap data){ - ContactsImporterModel *contactsImporter = nullptr; + QSharedPointer contactsImporter = nullptr; if( data.contains("pluginID")){ PluginDataAPI * dataInstance = static_cast(PluginsManager::createInstance(data["pluginID"].toString())); if(dataInstance) { // get default values - contactsImporter = new ContactsImporterModel(dataInstance, this); - App::getInstance()->getEngine()->setObjectOwnership(contactsImporter, QQmlEngine::CppOwnership); + contactsImporter = QSharedPointer::create(dataInstance, this); + App::getInstance()->getEngine()->setObjectOwnership(contactsImporter.get(), QQmlEngine::CppOwnership); QVariantMap newData = ContactsImporterPluginsManager::getDefaultValues(data["pluginID"].toString());// Start with defaults from plugin QVariantMap InstanceFields = contactsImporter->getFields(); for(auto field = InstanceFields.begin() ; field != InstanceFields.end() ; ++field)// Insert or Update with the defaults of an instance @@ -147,64 +114,64 @@ ContactsImporterModel *ContactsImporterListModel::createContactsImporter(QVarian contactsImporter->setIdentity(++mMaxContactsImporterId); contactsImporter->setFields(newData); - int row = mList.count(); - - beginInsertRows(QModelIndex(), row, row); addContactsImporter(contactsImporter); - endInsertRows(); emit layoutChanged(); emit contactsImporterAdded(contactsImporter); } } - return contactsImporter; + return contactsImporter.get(); } -ContactsImporterModel *ContactsImporterListModel::addContactsImporter (QVariantMap data, int pId) { - ContactsImporterModel *contactsImporter = findContactsImporterModelFromId(pId); +ContactsImporterModel* ContactsImporterListModel::addContactsImporter (QVariantMap data, int pId) { + auto contactsImporter = findContactsImporterModelFromId(pId); if (contactsImporter) { contactsImporter->setFields(data); - return contactsImporter; + return contactsImporter.get(); }else return createContactsImporter(data); } void ContactsImporterListModel::removeContactsImporter (ContactsImporterModel *contactsImporter) { - int index = mList.indexOf(contactsImporter); - if (index >=0){ - if( contactsImporter->getIdentity() >=0 ){// Remove from configuration - int id = contactsImporter->getIdentity(); - string section = Utils::appStringToCoreString(PluginsManager::gPluginsConfigSection+"_"+QString::number(id)+"_"+QString::number(PluginDataAPI::CONTACTS)); - CoreManager::getInstance()->getCore()->getConfig()->cleanSection(section); - if( id == mMaxContactsImporterId)// Decrease mMaxContactsImporterId in a safe way - --mMaxContactsImporterId; - } - removeRow(index); + int index = 0; + for(auto importer : mList){ + if( importer.get() == contactsImporter){ + if( contactsImporter->getIdentity() >=0 ){// Remove from configuration + int id = contactsImporter->getIdentity(); + string section = Utils::appStringToCoreString(PluginsManager::gPluginsConfigSection+"_"+QString::number(id)+"_"+QString::number(PluginDataAPI::CONTACTS)); + CoreManager::getInstance()->getCore()->getConfig()->cleanSection(section); + if( id == mMaxContactsImporterId)// Decrease mMaxContactsImporterId in a safe way + --mMaxContactsImporterId; + } + removeRow(index); + return; + }else + ++index; } } void ContactsImporterListModel::importContacts(const int &pId){ if( pId >=0) { - ContactsImporterModel *contactsImporter = findContactsImporterModelFromId(pId); + auto contactsImporter = findContactsImporterModelFromId(pId); if( contactsImporter) contactsImporter->importContacts(); }else // Import from all current connectors for(auto importer : mList) - dynamic_cast(importer)->importContacts(); + qobject_cast(importer.get())->importContacts(); } // ----------------------------------------------------------------------------- -void ContactsImporterListModel::addContactsImporter (ContactsImporterModel *contactsImporter) { +void ContactsImporterListModel::addContactsImporter (QSharedPointer contactsImporter) { // Connect all update signals - QObject::connect(contactsImporter, &ContactsImporterModel::fieldsChanged, this, [this, contactsImporter]() { + QObject::connect(contactsImporter.get(), &ContactsImporterModel::fieldsChanged, this, [this, contactsImporter]() { emit contactsImporterUpdated(contactsImporter); }); - QObject::connect(contactsImporter, &ContactsImporterModel::identityChanged, this, [this, contactsImporter]() { + QObject::connect(contactsImporter.get(), &ContactsImporterModel::identityChanged, this, [this, contactsImporter]() { emit contactsImporterUpdated(contactsImporter); }); - mList << contactsImporter; + add(contactsImporter); } //----------------------------------------------------------------------------------- diff --git a/linphone-app/src/components/contacts/ContactsImporterListModel.hpp b/linphone-app/src/components/contacts/ContactsImporterListModel.hpp index 8d6cd3ae7..c05b5b75b 100644 --- a/linphone-app/src/components/contacts/ContactsImporterListModel.hpp +++ b/linphone-app/src/components/contacts/ContactsImporterListModel.hpp @@ -23,7 +23,7 @@ #include -#include +#include "app/proxyModel/ProxyListModel.hpp" // ============================================================================= @@ -32,23 +32,15 @@ class PluginsModel; // Store all connectors -class ContactsImporterListModel : public QAbstractListModel { - - Q_OBJECT; +class ContactsImporterListModel : public ProxyListModel { + Q_OBJECT public: ContactsImporterListModel (QObject *parent = Q_NULLPTR); - int rowCount (const QModelIndex &index = QModelIndex()) const override; + virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - QHash roleNames () const override; - QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; - - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - - ContactsImporterModel *findContactsImporterModelFromId (const int &id) const; - QList getList(); + QSharedPointer findContactsImporterModelFromId (const int &id) const; Q_INVOKABLE ContactsImporterModel *createContactsImporter(QVariantMap data); Q_INVOKABLE ContactsImporterModel *addContactsImporter (QVariantMap data, int id=-1); @@ -57,14 +49,13 @@ public: //----------------------------------------------------------------------------------- signals: - void contactsImporterAdded (ContactsImporterModel *contact); - void contactsImporterRemoved (const ContactsImporterModel *contact); - void contactsImporterUpdated (ContactsImporterModel *contact); + void contactsImporterAdded (QSharedPointer); + void contactsImporterRemoved (QSharedPointer); + void contactsImporterUpdated (QSharedPointer); private: - void addContactsImporter (ContactsImporterModel *contactsImporter); + void addContactsImporter (QSharedPointer contactsImporter); - QList mList; int mMaxContactsImporterId; // Used to ensure unicity on ID when creating a connector }; diff --git a/linphone-app/src/components/contacts/ContactsListModel.cpp b/linphone-app/src/components/contacts/ContactsListModel.cpp index 523e6a748..63423955e 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.cpp +++ b/linphone-app/src/components/contacts/ContactsListModel.cpp @@ -31,181 +31,145 @@ using namespace std; -ContactsListModel::ContactsListModel (QObject *parent) : QAbstractListModel(parent) { - mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists().front(); - // Clean friends. - { - list> toRemove; - for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) { - if (!linphoneFriend->getVcard()) - toRemove.push_back(linphoneFriend); - } - - for (const auto &linphoneFriend : toRemove) { - qWarning() << QStringLiteral("Remove one friend without vcard."); - mLinphoneFriends->removeFriend(linphoneFriend); - } - } - - // Init contacts with linphone friends list. - QQmlEngine *engine = App::getInstance()->getEngine(); - for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) { - ContactModel *contact = new ContactModel(this, linphoneFriend); - - // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership - // The returned value must have a explicit parent or a QQmlEngine::CppOwnership. - engine->setObjectOwnership(contact, QQmlEngine::CppOwnership); - - addContact(contact); - } -} - -int ContactsListModel::rowCount (const QModelIndex &) const { - return mList.count(); -} - -QHash ContactsListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$contact"; - return roles; -} - -QVariant ContactsListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mList.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return QVariant::fromValue(mList[row]); - - return QVariant(); -} - -bool ContactsListModel::removeRow (int row, const QModelIndex &parent) { - return removeRows(row, 1, parent); +ContactsListModel::ContactsListModel (QObject *parent) : ProxyListModel(parent) { + mLinphoneFriends = CoreManager::getInstance()->getCore()->getFriendsLists().front(); + // Clean friends. + { + list> toRemove; + for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) { + if (!linphoneFriend->getVcard()) + toRemove.push_back(linphoneFriend); + } + + for (const auto &linphoneFriend : toRemove) { + qWarning() << QStringLiteral("Remove one friend without vcard."); + mLinphoneFriends->removeFriend(linphoneFriend); + } + } + + // Init contacts with linphone friends list. + QQmlEngine *engine = App::getInstance()->getEngine(); + for (const auto &linphoneFriend : mLinphoneFriends->getFriends()) { + auto contact = QSharedPointer::create(this, linphoneFriend); + + // See: http://doc.qt.io/qt-5/qtqml-cppintegration-data.html#data-ownership + // The returned value must have a explicit parent or a QQmlEngine::CppOwnership. + engine->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership); + + addContact(contact); + } } bool ContactsListModel::removeRows (int row, int count, const QModelIndex &parent) { - int limit = row + count - 1; - - if (row < 0 || count < 0 || limit >= mList.count()) - return false; - - beginRemoveRows(parent, row, limit); - - for (int i = 0; i < count; ++i) { - ContactModel *contact = mList.takeAt(row); - for(auto address : contact->getVcardModel()->getSipAddresses()){ - mOptimizedSearch.remove(address.toString()); + int limit = row + count - 1; + + if (row < 0 || count < 0 || limit >= mList.count()) + return false; + + beginRemoveRows(parent, row, limit); + + for (int i = 0; i < count; ++i) { + QSharedPointer contact = mList.takeAt(row).objectCast(); + for(auto address : contact->getVcardModel()->getSipAddresses()){ + mOptimizedSearch.remove(address.toString()); + } + + mLinphoneFriends->removeFriend(contact->mLinphoneFriend); + + emit contactRemoved(contact); } - - mLinphoneFriends->removeFriend(contact->mLinphoneFriend); - - emit contactRemoved(contact); - contact->deleteLater(); - } - - endRemoveRows(); - - return true; + + endRemoveRows(); + + return true; } // ----------------------------------------------------------------------------- -ContactModel *ContactsListModel::findContactModelFromSipAddress (const QString &sipAddress) const { +QSharedPointer ContactsListModel::findContactModelFromSipAddress (const QString &sipAddress) const { if(mOptimizedSearch.contains(sipAddress)) return mOptimizedSearch[sipAddress]; else return nullptr; -/* + /* auto it = find_if(mList.begin(), mList.end(), [&sipAddress](ContactModel *contactModel) { - return contactModel->getVcardModel()->getSipAddresses().contains(sipAddress); + return contactModel->getVcardModel()->getSipAddresses().contains(sipAddress); }); return it != mList.end() ? *it : nullptr; */ } -ContactModel *ContactsListModel::findContactModelFromUsername (const QString &username) const { - auto it = find_if(mList.begin(), mList.end(), [&username](ContactModel *contactModel) { - return contactModel->getVcardModel()->getUsername() == username; - }); - return it != mList.end() ? *it : nullptr; +QSharedPointer ContactsListModel::findContactModelFromUsername (const QString &username) const { + auto it = find_if(mList.begin(), mList.end(), [&username](QSharedPointer contactModel) { + return qobject_cast(contactModel.get())->getVcardModel()->getUsername() == username; +}); + return it != mList.end() ? it->objectCast() : nullptr; } // ----------------------------------------------------------------------------- ContactModel *ContactsListModel::addContact (VcardModel *vcardModel) { - // Try to merge vcardModel to an existing contact. - ContactModel *contact = findContactModelFromUsername(vcardModel->getUsername()); - if (contact) { - contact->mergeVcardModel(vcardModel); - return contact; - } - - contact = new ContactModel(this, vcardModel); - App::getInstance()->getEngine()->setObjectOwnership(contact, QQmlEngine::CppOwnership); - - if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) { - qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel; - contact->deleteLater(); - return nullptr; - } - - qInfo() << QStringLiteral("Add contact from vcard:") << contact << vcardModel; - - // Make sure new subscribe is issued. - mLinphoneFriends->updateSubscriptions(); - - int row = mList.count(); - - beginInsertRows(QModelIndex(), row, row); - addContact(contact); - endInsertRows(); - emit layoutChanged(); - - emit contactAdded(contact); - - return contact; + // Try to merge vcardModel to an existing contact. + auto contact = findContactModelFromUsername(vcardModel->getUsername()); + if (contact) { + contact->mergeVcardModel(vcardModel); + return contact.get(); + } + + contact = QSharedPointer::create(this, vcardModel); + App::getInstance()->getEngine()->setObjectOwnership(contact.get(), QQmlEngine::CppOwnership); + + if (mLinphoneFriends->addFriend(contact->mLinphoneFriend) != linphone::FriendList::Status::OK) { + qWarning() << QStringLiteral("Unable to add contact from vcard:") << vcardModel; + return nullptr; + } + + qInfo() << QStringLiteral("Add contact from vcard:") << contact.get() << vcardModel; + + // Make sure new subscribe is issued. + mLinphoneFriends->updateSubscriptions(); + + addContact(contact); + emit layoutChanged(); + + emit contactAdded(contact); + + return contact.get(); } -void ContactsListModel::removeContact (ContactModel *contact) { - qInfo() << QStringLiteral("Removing contact:") << contact; - - int index = mList.indexOf(contact); - if (index == -1 || !removeRow(index)) - qWarning() << QStringLiteral("Unable to remove contact:") << contact; +void ContactsListModel::removeContact (ContactModel *contact){ + remove(contact); } // ----------------------------------------------------------------------------- void ContactsListModel::cleanAvatars () { - qInfo() << QStringLiteral("Delete all avatars."); - - for (const auto &contact : mList) { - VcardModel *vcardModel = contact->cloneVcardModel(); - vcardModel->setAvatar(QString("")); - contact->setVcardModel(vcardModel); - } + qInfo() << QStringLiteral("Delete all avatars."); + + for (const auto &item : mList) { + auto contact = qobject_cast(item.get()); + VcardModel *vcardModel = contact->cloneVcardModel(); + vcardModel->setAvatar(QString("")); + contact->setVcardModel(vcardModel); + } } // ----------------------------------------------------------------------------- -void ContactsListModel::addContact (ContactModel *contact) { - QObject::connect(contact, &ContactModel::contactUpdated, this, [this, contact]() { - emit contactUpdated(contact); - }); - QObject::connect(contact, &ContactModel::sipAddressAdded, this, [this, contact](const QString &sipAddress) { - mOptimizedSearch[sipAddress] = contact; - emit sipAddressAdded(contact, sipAddress); - }); - QObject::connect(contact, &ContactModel::sipAddressRemoved, this, [this, contact](const QString &sipAddress) { - mOptimizedSearch.remove(sipAddress); - emit sipAddressRemoved(contact, sipAddress); - }); - - mList << contact; - for(auto address : contact->getVcardModel()->getSipAddresses()){ +void ContactsListModel::addContact (QSharedPointer contact) { + QObject::connect(contact.get(), &ContactModel::contactUpdated, this, [this, contact]() { + emit contactUpdated(contact); + }); + QObject::connect(contact.get(), &ContactModel::sipAddressAdded, this, [this, contact](const QString &sipAddress) { + mOptimizedSearch[sipAddress] = contact; + emit sipAddressAdded(contact, sipAddress); + }); + QObject::connect(contact.get(), &ContactModel::sipAddressRemoved, this, [this, contact](const QString &sipAddress) { + mOptimizedSearch.remove(sipAddress); + emit sipAddressRemoved(contact, sipAddress); + }); + add(contact); + for(auto address : contact->getVcardModel()->getSipAddresses()){ mOptimizedSearch[address.toString()] = contact; } } diff --git a/linphone-app/src/components/contacts/ContactsListModel.hpp b/linphone-app/src/components/contacts/ContactsListModel.hpp index 7963d1015..4af9d1955 100644 --- a/linphone-app/src/components/contacts/ContactsListModel.hpp +++ b/linphone-app/src/components/contacts/ContactsListModel.hpp @@ -23,55 +23,48 @@ #include -#include +#include "app/proxyModel/ProxyListModel.hpp" // ============================================================================= namespace linphone { - class FriendList; + class FriendList; } class ContactModel; class VcardModel; -class ContactsListModel : public QAbstractListModel { - friend class SipAddressesModel; - - Q_OBJECT; - +class ContactsListModel : public ProxyListModel { + friend class SipAddressesModel; + + Q_OBJECT; + public: - ContactsListModel (QObject *parent = Q_NULLPTR); - - int rowCount (const QModelIndex &index = QModelIndex()) const override; - - QHash roleNames () const override; - QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; - - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - - ContactModel *findContactModelFromSipAddress (const QString &sipAddress) const; - ContactModel *findContactModelFromUsername (const QString &username) const; - - Q_INVOKABLE ContactModel *addContact (VcardModel *vcardModel); - Q_INVOKABLE void removeContact (ContactModel *contact); - - Q_INVOKABLE void cleanAvatars (); - + ContactsListModel (QObject *parent = Q_NULLPTR); + + bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; + + QSharedPointer findContactModelFromSipAddress (const QString &sipAddress) const; + QSharedPointer findContactModelFromUsername (const QString &username) const; + + Q_INVOKABLE ContactModel *addContact (VcardModel *vcardModel); + Q_INVOKABLE void removeContact (ContactModel *contact); + + Q_INVOKABLE void cleanAvatars (); + signals: - void contactAdded (ContactModel *contact); - void contactRemoved (const ContactModel *contact); - void contactUpdated (ContactModel *contact); - - void sipAddressAdded (ContactModel *contact, const QString &sipAddress); - void sipAddressRemoved (ContactModel *contact, const QString &sipAddress); - + void contactAdded (QSharedPointer); + void contactRemoved (QSharedPointer); + void contactUpdated (QSharedPointer); + + void sipAddressAdded (QSharedPointer, const QString &sipAddress); + void sipAddressRemoved (QSharedPointer, const QString &sipAddress); + private: - void addContact (ContactModel *contact); - - QList mList; - QMap mOptimizedSearch; - std::shared_ptr mLinphoneFriends; + void addContact (QSharedPointer contact); + + QMap> mOptimizedSearch; + std::shared_ptr mLinphoneFriends; }; #endif // CONTACTS_LIST_MODEL_H_ diff --git a/linphone-app/src/components/content/ContentListModel.cpp b/linphone-app/src/components/content/ContentListModel.cpp index 3e402f4cd..4420e9789 100644 --- a/linphone-app/src/components/content/ContentListModel.cpp +++ b/linphone-app/src/components/content/ContentListModel.cpp @@ -31,50 +31,25 @@ // ============================================================================= -ContentListModel::ContentListModel (ChatMessageModel * message) : QAbstractListModel(message) { +ContentListModel::ContentListModel (ChatMessageModel * message) : ProxyListModel(message) { mParent = message; if(message){ std::list> contents = message->getChatMessage()->getContents() ; for(auto content : contents){ - auto contentModel = std::make_shared(content, message); + auto contentModel = QSharedPointer::create(content, message); connect(this, &ContentListModel::updateTransferDataRequested, contentModel.get(), &ContentModel::updateTransferData); mList << contentModel; } } } -int ContentListModel::rowCount (const QModelIndex &index) const{ - return mList.count(); -} - int ContentListModel::count(){ return mList.count(); } -QHash ContentListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "modelData"; - return roles; -} - -QVariant ContentListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mList.count()) - return QVariant(); - - if (role == Qt::DisplayRole) - return QVariant::fromValue(mList[row].get()); - - return QVariant(); -} - -std::shared_ptr ContentListModel::add(std::shared_ptr content){ - int row = mList.count(); - auto contentModel = std::make_shared(content, mParent); - beginInsertRows(QModelIndex(), row, row); - mList << contentModel; - endInsertRows(); +QSharedPointer ContentListModel::add(std::shared_ptr content){ + auto contentModel = QSharedPointer::create(content, mParent); + ProxyListModel::add(contentModel); emit contentsChanged(); return contentModel; } @@ -120,64 +95,44 @@ void ContentListModel::remove(ContentModel * model){ } } -bool ContentListModel::removeRow (int row, const QModelIndex &parent){ - return removeRows(row, 1, parent); -} - -bool ContentListModel::removeRows (int row, int count, const QModelIndex &parent) { - int limit = row + count - 1; - - if (row < 0 || count < 0 || limit >= mList.count()) - return false; - - beginRemoveRows(parent, row, limit); - - for (int i = 0; i < count; ++i) - mList.takeAt(row); - - endRemoveRows(); - - return true; -} - void ContentListModel::clear(){ // Delete thumbnails for(auto contentModel : mList){ - contentModel->removeThumbnail(); + contentModel.objectCast()->removeThumbnail(); } - beginResetModel(); - mList.clear(); - endResetModel(); + resetData(); } void ContentListModel::removeDownloadedFiles(){ - for(auto contentModel : mList){ + for(auto model : mList){ + auto contentModel = model.objectCast(); contentModel->removeDownloadedFile(); contentModel->removeThumbnail(); } } -std::shared_ptr ContentListModel::getContentModel(std::shared_ptr content){ - for(auto c : mList) +QSharedPointer ContentListModel::getContentModel(std::shared_ptr content){ + for(auto item : mList){ + auto c = item.objectCast(); if(c->getContent() == content) return c; + } if(content->isFileTransfer() || content->isFile() || content->isFileEncrypted()){ - for(auto c : mList)// Content object can be different for file (like while data transfer) + for(auto item : mList){// Content object can be different for file (like while data transfer) + auto c = item.objectCast(); if(c->getContent()->getFilePath() == content->getFilePath()) return c; + } } return nullptr; } -QList> ContentListModel::getContents(){ - return mList; -} - void ContentListModel::updateContent(std::shared_ptr oldContent, std::shared_ptr newContent){ int row = 0; for(auto content = mList.begin() ; content != mList.end() ; ++content, ++row){ - if( (*content)->getContent() == oldContent){ - mList.replace(row, std::make_shared(newContent, (*content)->getChatMessageModel())); + auto contentModel = content->objectCast(); + if( contentModel->getContent() == oldContent){ + mList.replace(row, QSharedPointer::create(newContent, contentModel->getChatMessageModel())); emit dataChanged(index(row,0), index(row,0)); return; } @@ -190,15 +145,15 @@ void ContentListModel::updateContents(ChatMessageModel * messageModel){ beginResetModel(); for(auto content : contents){ if( count >= mList.size()){// New content - mList.insert(count, std::make_shared(content, messageModel)); - }else if(mList.at(count)->getContent() != content){ // This content is not at its place + mList.insert(count, QSharedPointer::create(content, messageModel)); + }else if(mList.at(count).objectCast()->getContent() != content){ // This content is not at its place int c = count + 1; - while( c < mList.size() && mList.at(c)->getContent() != content) + while( c < mList.size() && mList.at(c).objectCast()->getContent() != content) ++c; if( c < mList.size()){// Found => swap position mList.swap(count, c); }else{// content is new - mList.insert(count, std::make_shared(content, messageModel)); + mList.insert(count, QSharedPointer::create(content, messageModel)); } } ++count; @@ -214,5 +169,5 @@ void ContentListModel::updateAllTransferData(){ void ContentListModel::downloaded(){ for(auto content : mList) - content->createThumbnail(); + content.objectCast()->createThumbnail(); } \ No newline at end of file diff --git a/linphone-app/src/components/content/ContentListModel.hpp b/linphone-app/src/components/content/ContentListModel.hpp index 48a3eb537..5e66fe740 100644 --- a/linphone-app/src/components/content/ContentListModel.hpp +++ b/linphone-app/src/components/content/ContentListModel.hpp @@ -29,29 +29,27 @@ #include #include +#include "app/proxyModel/ProxyListModel.hpp" + class ContentModel; class ChatMessageModel; -class ContentListModel : public QAbstractListModel { +class ContentListModel : public ProxyListModel { Q_OBJECT public: ContentListModel (ChatMessageModel * message); - int rowCount (const QModelIndex &index = QModelIndex()) const override; int count(); - virtual QHash roleNames () const override; - virtual QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; - std::shared_ptr add(std::shared_ptr content); + QSharedPointer add(std::shared_ptr content); void addFile(const QString& path); Q_INVOKABLE void remove(ContentModel * model); void clear(); void removeDownloadedFiles(); - std::shared_ptr getContentModel(std::shared_ptr content);// Return the contentModel by checking Content, or if it is the same file. - QList> getContents(); + QSharedPointer getContentModel(std::shared_ptr content);// Return the contentModel by checking Content, or if it is the same file. void updateContent(std::shared_ptr oldContent, std::shared_ptr newContent); void updateContents(ChatMessageModel * messageModel); @@ -63,10 +61,7 @@ signals: void contentsChanged(); private: - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - virtual bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; - QList> mList; ChatMessageModel * mParent; }; diff --git a/linphone-app/src/components/content/ContentModel.hpp b/linphone-app/src/components/content/ContentModel.hpp index 386e3c90d..507966acb 100644 --- a/linphone-app/src/components/content/ContentModel.hpp +++ b/linphone-app/src/components/content/ContentModel.hpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "components/chat-events/ChatMessageModel.hpp" class ChatMessageModel; @@ -97,8 +98,8 @@ private: std::shared_ptr mContent; ChatMessageModel* mChatMessageModel; ChatMessageModel::AppDataManager mAppData; // Used if there is no Chat Message model set. - std::shared_ptr mConferenceInfoModel; + QSharedPointer mConferenceInfoModel; }; -Q_DECLARE_METATYPE(std::shared_ptr) +Q_DECLARE_METATYPE(QSharedPointer) #endif diff --git a/linphone-app/src/components/content/ContentProxyModel.cpp b/linphone-app/src/components/content/ContentProxyModel.cpp index 9ac520d92..691a4b9a7 100644 --- a/linphone-app/src/components/content/ContentProxyModel.cpp +++ b/linphone-app/src/components/content/ContentProxyModel.cpp @@ -51,7 +51,7 @@ void ContentProxyModel::setContentListModel(ContentListModel * model){ } void ContentProxyModel::addFile(const QString& path){ - ContentListModel* model = dynamic_cast(sourceModel()); + ContentListModel* model = qobject_cast(sourceModel()); model->addFile(path); } @@ -89,9 +89,9 @@ bool ContentProxyModel::lessThan (const QModelIndex &left, const QModelIndex &ri ); } void ContentProxyModel::remove(ContentModel * model){ - dynamic_cast(sourceModel())->remove(model); + qobject_cast(sourceModel())->remove(model); } void ContentProxyModel::clear(){ - dynamic_cast(sourceModel())->clear(); + qobject_cast(sourceModel())->clear(); } \ No newline at end of file diff --git a/linphone-app/src/components/core/CoreHandlers.hpp b/linphone-app/src/components/core/CoreHandlers.hpp index 7b8952fcb..99410b117 100644 --- a/linphone-app/src/components/core/CoreHandlers.hpp +++ b/linphone-app/src/components/core/CoreHandlers.hpp @@ -32,7 +32,7 @@ class QMutex; class CoreHandlers : public QObject, public linphone::CoreListener { - Q_OBJECT; + Q_OBJECT public: CoreHandlers (CoreManager *coreManager); @@ -158,13 +158,6 @@ private: const std::shared_ptr &core, const std::shared_ptr &linphoneFriend ) override; - - void onRegistrationStateChanged ( - const std::shared_ptr &core, - const std::shared_ptr &proxyConfig, - linphone::RegistrationState state, - const std::string &message - ) override; void onTransferStateChanged ( const std::shared_ptr &core, diff --git a/linphone-app/src/components/core/CoreManager.cpp b/linphone-app/src/components/core/CoreManager.cpp index c0dbbb8be..abdf97df7 100644 --- a/linphone-app/src/components/core/CoreManager.cpp +++ b/linphone-app/src/components/core/CoreManager.cpp @@ -31,7 +31,6 @@ #include "components/calls/CallsListModel.hpp" #include "components/chat/ChatModel.hpp" #include "components/chat-room/ChatRoomModel.hpp" -#include "components/chat-room/ChatRoomListModel.hpp" #include "components/contact/VcardModel.hpp" #include "components/contacts/ContactsListModel.hpp" #include "components/contacts/ContactsImporterListModel.hpp" @@ -94,7 +93,6 @@ CoreManager::~CoreManager(){ void CoreManager::initCoreManager(){ mCallsListModel = new CallsListModel(this); mChatModel = new ChatModel(this); - mChatRoomListModel = new ChatRoomListModel(this); mContactsListModel = new ContactsListModel(this); mContactsImporterListModel = new ContactsImporterListModel(this); mAccountSettingsModel = new AccountSettingsModel(this); @@ -295,7 +293,7 @@ void CoreManager::updateUserAgent(){ forceRefreshRegisters(); // After setting a new device name, REGISTER need to take account it. } -void CoreManager::handleChatRoomCreated(const std::shared_ptr &chatRoomModel){ +void CoreManager::handleChatRoomCreated(const QSharedPointer &chatRoomModel){ emit chatRoomModelCreated(chatRoomModel); } diff --git a/linphone-app/src/components/core/CoreManager.hpp b/linphone-app/src/components/core/CoreManager.hpp index 43ffaf06d..88986c851 100644 --- a/linphone-app/src/components/core/CoreManager.hpp +++ b/linphone-app/src/components/core/CoreManager.hpp @@ -36,7 +36,6 @@ class AccountSettingsModel; class CallsListModel; class ChatModel; class ChatRoomModel; -class ChatRoomListModel; class ContactsListModel; class ContactsImporterListModel; class CoreHandlers; @@ -72,12 +71,6 @@ public: return mHandlers; } - //std::shared_ptr getChatRoomModel (const QString &peerAddress, const QString &localAddress, const bool &isSecure); - //std::shared_ptr getChatRoomModel (ChatRoomModel * data);// Get the shared pointer. This can be done becuase of unicity of ChatRoomModel - //std::shared_ptr getChatRoomModel (std::shared_ptr chatRoom, const bool& create = true); - //bool chatRoomModelExists (const QString &sipAddress, const QString &localAddress, const bool &isSecure); - //bool chatRoomModelExists (std::shared_ptr chatRoom); - HistoryModel* getHistoryModel(); RecorderManager* getRecorderManager(); @@ -101,12 +94,6 @@ public: Q_CHECK_PTR(mCallsListModel); return mCallsListModel; } - /* Timelines - ChatRoomListModel *getChatRoomListModel () const { - Q_CHECK_PTR(mChatRoomListModel); - return mChatRoomListModel; - }*/ - ContactsListModel *getContactsListModel () const { Q_CHECK_PTR(mContactsListModel); @@ -184,12 +171,12 @@ public slots: void stopIterate(); void setLastRemoteProvisioningState(const linphone::ConfiguringState& state); void createLinphoneCore (const QString &configPath);// In order to delay creation - void handleChatRoomCreated(const std::shared_ptr &chatRoomModel); + void handleChatRoomCreated(const QSharedPointer &chatRoomModel); signals: void coreManagerInitialized (); - void chatRoomModelCreated (const std::shared_ptr &chatRoomModel); + void chatRoomModelCreated (const QSharedPointer &chatRoomModel); void historyModelCreated (HistoryModel *historyModel); void recorderManagerCreated(RecorderManager *recorderModel); @@ -219,7 +206,7 @@ private: static QString getDownloadUrl (); std::shared_ptr mCore; - std::shared_ptr mHandlers; + std::shared_ptr mHandlers; // It is used for handling linphone. Keep it to shared_ptr. bool mStarted = false; linphone::ConfiguringState mLastRemoteProvisioningState; @@ -228,7 +215,6 @@ private: ContactsListModel *mContactsListModel = nullptr; ContactsImporterListModel *mContactsImporterListModel = nullptr; TimelineListModel *mTimelineListModel = nullptr; - ChatRoomListModel *mChatRoomListModel = nullptr; ChatModel *mChatModel = nullptr; SipAddressesModel *mSipAddressesModel = nullptr; @@ -236,10 +222,7 @@ private: AccountSettingsModel *mAccountSettingsModel = nullptr; EventCountNotifier *mEventCountNotifier = nullptr; - - //QHash >, std::weak_ptr> mChatRoomModels; - //QHash, std::weak_ptr> mChatRoomModels; - //QList, std::weak_ptr>> mChatRoomModels; + HistoryModel * mHistoryModel = nullptr; LdapListModel *mLdapListModel = nullptr; RecorderManager* mRecorderManager = nullptr; diff --git a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp index fd2531aa1..7612936e1 100644 --- a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp +++ b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.cpp @@ -100,7 +100,7 @@ int AbstractEventCountNotifier::getMissedCallCountFromLocal(const QString &local } // ----------------------------------------------------------------------------- -void AbstractEventCountNotifier::handleChatRoomModelCreated (const shared_ptr &chatRoomModel) { +void AbstractEventCountNotifier::handleChatRoomModelCreated (const QSharedPointer &chatRoomModel) { ChatRoomModel *chatRoomModelPtr = chatRoomModel.get(); QObject::connect( chatRoomModelPtr, &ChatRoomModel::messageCountReset, diff --git a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp index 71a81e11c..d58bed4bb 100644 --- a/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp +++ b/linphone-app/src/components/core/event-count-notifier/AbstractEventCountNotifier.hpp @@ -21,7 +21,7 @@ #ifndef ABSTRACT_EVENT_COUNT_NOTIFIER_H_ #define ABSTRACT_EVENT_COUNT_NOTIFIER_H_ -#include +#include #include #include @@ -73,7 +73,7 @@ private: void internalnotifyEventCount (); - void handleChatRoomModelCreated (const std::shared_ptr &chatRoomModel); + void handleChatRoomModelCreated (const QSharedPointer &chatRoomModel); void handleHistoryModelCreated (HistoryModel *historyModel); QHash mMissedCalls; diff --git a/linphone-app/src/components/ldap/LdapModel.cpp b/linphone-app/src/components/ldap/LdapModel.cpp index eaf8d35ad..4eb53244c 100644 --- a/linphone-app/src/components/ldap/LdapModel.cpp +++ b/linphone-app/src/components/ldap/LdapModel.cpp @@ -35,6 +35,7 @@ using namespace std; LdapModel::LdapModel (std::shared_ptr ldap, QObject *parent ) : QObject(parent){ mLdap = ldap; + mIsValid = false; if(mLdap) mLdapParams = ldap->getParams()->clone(); else{ diff --git a/linphone-app/src/components/other/images/ImageProxyModel.cpp b/linphone-app/src/components/other/images/ImageProxyModel.cpp index b1cec6656..acdde5755 100644 --- a/linphone-app/src/components/other/images/ImageProxyModel.cpp +++ b/linphone-app/src/components/other/images/ImageProxyModel.cpp @@ -40,8 +40,6 @@ bool ImageProxyModel::filterAcceptsRow ( ) const { Q_UNUSED(sourceRow) Q_UNUSED(sourceParent) - //const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - //const ParticipantDeviceModel *device = index.data().value(); return true; } diff --git a/linphone-app/src/components/participant-imdn/ParticipantImdnStateListModel.cpp b/linphone-app/src/components/participant-imdn/ParticipantImdnStateListModel.cpp index 0283f9e01..0f80bb7cd 100644 --- a/linphone-app/src/components/participant-imdn/ParticipantImdnStateListModel.cpp +++ b/linphone-app/src/components/participant-imdn/ParticipantImdnStateListModel.cpp @@ -42,7 +42,6 @@ ParticipantImdnStateListModel::ParticipantImdnStateListModel (std::shared_ptr
  • getParticipant()){ auto deviceModel = std::make_shared(imdn); - //connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged); mList << deviceModel; } } diff --git a/linphone-app/src/components/participant-imdn/ParticipantImdnStateModel.cpp b/linphone-app/src/components/participant-imdn/ParticipantImdnStateModel.cpp index 41ff8fa88..e9785377e 100644 --- a/linphone-app/src/components/participant-imdn/ParticipantImdnStateModel.cpp +++ b/linphone-app/src/components/participant-imdn/ParticipantImdnStateModel.cpp @@ -32,8 +32,8 @@ ParticipantImdnStateModel::ParticipantImdnStateModel (const std::shared_ptr imdn, QObject * parent) : QObject(parent) { App::getInstance()->getEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE - setState(LinphoneEnums::fromLinphone(imdn->getState())); - setStateChangeTime(QDateTime::fromSecsSinceEpoch(imdn->getStateChangeTime())) ; + mState = (LinphoneEnums::fromLinphone(imdn->getState())); + mStateChangeTime = (QDateTime::fromSecsSinceEpoch(imdn->getStateChangeTime())) ; auto participant = imdn->getParticipant(); if(participant) mAddress = imdn->getParticipant()->getAddress()->clone(); diff --git a/linphone-app/src/components/participant-imdn/ParticipantImdnStateProxyModel.cpp b/linphone-app/src/components/participant-imdn/ParticipantImdnStateProxyModel.cpp index 23a5d84aa..1963645f2 100644 --- a/linphone-app/src/components/participant-imdn/ParticipantImdnStateProxyModel.cpp +++ b/linphone-app/src/components/participant-imdn/ParticipantImdnStateProxyModel.cpp @@ -39,8 +39,6 @@ bool ParticipantImdnStateProxyModel::filterAcceptsRow ( ) const { Q_UNUSED(sourceRow) Q_UNUSED(sourceParent) - //const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - //const ParticipantDeviceModel *device = index.data().value(); return true; } diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp index 8757bd6f9..13954431a 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.cpp @@ -32,10 +32,11 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (std::shared_ptr participant, QObject *parent) : QAbstractListModel(parent) { std::list> devices = participant->getDevices() ; + auto previewModel = ParticipantDeviceModel::create(nullptr, true); + mList << previewModel; for(auto device : devices){ - auto deviceModel = std::make_shared(device, false); + auto deviceModel = ParticipantDeviceModel::create(device, false); connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged); - connect(this, &ParticipantDeviceListModel::participantDeviceMediaAvailabilityChanged, deviceModel.get(), &ParticipantDeviceModel::videoEnabledChanged); mList << deviceModel; } } @@ -44,8 +45,16 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, Q if(callModel && callModel->isConference()) { mCallModel = callModel; auto conferenceModel = callModel->getConferenceModel(); + auto previewModel = ParticipantDeviceModel::create(nullptr, true); + mList << previewModel; + std::list> devices = conferenceModel->getConference()->getParticipantDeviceList(); + for(auto device : devices){ + auto deviceModel = ParticipantDeviceModel::create(device, false); + connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged); + mList << deviceModel; + } /* - mList << std::make_shared(callModel, true);// Add Me in device list + mList << ParticipantDeviceModel::create(callModel, true);// Add Me in device list qWarning() << "Me devices : " << conferenceModel->getConference()->getMe()->getDevices().size(); // auto meDevices = conferenceModel->getConference()->getMe()->getDevices(); // if(meDevices.size() > 0) @@ -56,7 +65,6 @@ ParticipantDeviceListModel::ParticipantDeviceListModel (CallModel * callModel, Q */ connect(conferenceModel.get(), &ConferenceModel::participantDeviceAdded, this, &ParticipantDeviceListModel::onParticipantDeviceAdded); connect(conferenceModel.get(), &ConferenceModel::participantDeviceRemoved, this, &ParticipantDeviceListModel::onParticipantDeviceRemoved); - connect(conferenceModel.get(), &ConferenceModel::participantDeviceMediaAvailabilityChanged, this, &ParticipantDeviceListModel::onParticipantDeviceMediaAvailabilityChanged); connect(conferenceModel.get(), &ConferenceModel::conferenceStateChanged, this, &ParticipantDeviceListModel::onConferenceStateChanged); } } @@ -73,13 +81,14 @@ int ParticipantDeviceListModel::count(){ void ParticipantDeviceListModel::updateDevices(std::shared_ptr participant){ std::list> devices = participant->getDevices() ; + auto previewModel = ParticipantDeviceModel::create(nullptr, true); beginResetModel(); qWarning() << "Update devices from participant"; mList.clear(); + mList << previewModel; for(auto device : devices){ - auto deviceModel = std::make_shared(device, false); + auto deviceModel = ParticipantDeviceModel::create(device, false); connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged); - connect(this, &ParticipantDeviceListModel::participantDeviceMediaAvailabilityChanged, deviceModel.get(), &ParticipantDeviceModel::videoEnabledChanged); mList << deviceModel; } endResetModel(); @@ -88,6 +97,7 @@ void ParticipantDeviceListModel::updateDevices(std::shared_ptr>& devices, const bool& isMe){ +/* QList> devicesToAdd; //auto meDevices = mCallModel->getConferenceModel()->getConference()->getMe()->getDevices(); for(auto device : devices){ @@ -100,9 +110,8 @@ void ParticipantDeviceListModel::updateDevices(const std::listgetDevice()->getAddress(); }); if(exist == mList.end()){ - auto deviceModel = std::make_shared(device, isMe); + auto deviceModel = ParticipantDeviceModel::create(device, isMe); connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged); - connect(this, &ParticipantDeviceListModel::participantDeviceMediaAvailabilityChanged, deviceModel.get(), &ParticipantDeviceModel::videoEnabledChanged); devicesToAdd << deviceModel; } //} @@ -115,6 +124,7 @@ void ParticipantDeviceListModel::updateDevices(const std::list ParticipantDeviceListModel::roleNames () const { @@ -168,10 +178,9 @@ void ParticipantDeviceListModel::onParticipantDeviceAdded(const std::shared_ptr< for(auto realParticipantDevice : devices){ if( realParticipantDevice == participantDevice){ int row = mList.count(); - beginInsertRows(QModelIndex(), row, row); - auto deviceModel = std::make_shared(realParticipantDevice, false); + auto deviceModel = ParticipantDeviceModel::create(realParticipantDevice, false); connect(this, &ParticipantDeviceListModel::securityLevelChanged, deviceModel.get(), &ParticipantDeviceModel::onSecurityLevelChanged); - connect(this, &ParticipantDeviceListModel::participantDeviceMediaAvailabilityChanged, deviceModel.get(), &ParticipantDeviceModel::videoEnabledChanged); + beginInsertRows(QModelIndex(), row, row); mList << deviceModel; endInsertRows(); emit countChanged(); @@ -205,9 +214,6 @@ void ParticipantDeviceListModel::onParticipantDeviceLeft(const std::shared_ptr & participantDevice) { - emit participantDeviceMediaAvailabilityChanged(); -} void ParticipantDeviceListModel::onConferenceStateChanged(linphone::Conference::State newState){ if(newState == linphone::Conference::State::Created){ if(mCallModel && mCallModel->isConference()) { @@ -221,7 +227,7 @@ void ParticipantDeviceListModel::onConferenceStateChanged(linphone::Conference:: if(devices.size() > 0 && mList.size() == 1){ //qWarning() << "Adding Me in list. Count=" << mList.size(); beginInsertRows(QModelIndex(), 0, 0); - mList.push_front(std::make_shared(mCallModel, true));// Add Me in device list + mList.push_front(ParticipantDeviceModel::create(mCallModel, true));// Add Me in device list endInsertRows(); emit countChanged(); emit layoutChanged(); diff --git a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp index 57340dae3..93068e961 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceListModel.hpp @@ -55,13 +55,11 @@ public slots: void onParticipantDeviceRemoved(const std::shared_ptr & participantDevice); void onParticipantDeviceJoined(const std::shared_ptr & participantDevice); void onParticipantDeviceLeft(const std::shared_ptr & participantDevice); - void onParticipantDeviceMediaAvailabilityChanged(const std::shared_ptr & participantDevice); void onConferenceStateChanged(linphone::Conference::State newState); signals: void securityLevelChanged(std::shared_ptr device); void countChanged(); - void participantDeviceMediaAvailabilityChanged(); private: bool removeRow (int row, const QModelIndex &parent = QModelIndex()); diff --git a/linphone-app/src/components/participant/ParticipantDeviceModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceModel.cpp index 4fd231596..39a4b6885 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceModel.cpp @@ -33,13 +33,34 @@ ParticipantDeviceModel::ParticipantDeviceModel (std::shared_ptrgetEngine()->setObjectOwnership(this, QQmlEngine::CppOwnership);// Avoid QML to destroy it when passing by Q_INVOKABLE mIsMe = isMe; mCall = call; - connect(call, &CallModel::statusChanged, this, &ParticipantDeviceModel::videoEnabledChanged); + if( call) + connect(call, &CallModel::statusChanged, this, &ParticipantDeviceModel::videoEnabledChanged); +}*/ + +std::shared_ptr ParticipantDeviceModel::create(std::shared_ptr device, const bool& isMe, QObject *parent){ + std::shared_ptr model = std::make_shared(device, isMe, parent); + if(model){ + model->mSelf = model; + if(device) + device->addListener(model); + return model; + } + return nullptr; } +/* +std::shared_ptr ParticipantDeviceModel::create(CallModel * call, const bool& isMe, QObject *parent){ + std::shared_ptr model = std::make_shared(call, isMe, parent); + if(model){ + model->mSelf = model; + return model; + } + return nullptr; +}*/ // ----------------------------------------------------------------------------- @@ -81,4 +102,19 @@ bool ParticipantDeviceModel::isMe() const{ void ParticipantDeviceModel::onSecurityLevelChanged(std::shared_ptr device){ if(!device || mParticipantDevice && mParticipantDevice->getAddress()->weakEqual(device)) emit securityLevelChanged(); +} + +//-------------------------------------------------------------------- +void ParticipantDeviceModel::onIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking) { +} +void ParticipantDeviceModel::onIsMuted(const std::shared_ptr & participantDevice, bool isMuted) { +} +void ParticipantDeviceModel::onConferenceJoined(const std::shared_ptr & participantDevice) { +} +void ParticipantDeviceModel::onConferenceLeft(const std::shared_ptr & participantDevice) { +} +void ParticipantDeviceModel::onStreamCapabilityChanged(const std::shared_ptr & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) { +} +void ParticipantDeviceModel::onStreamAvailabilityChanged(const std::shared_ptr & participantDevice, bool available, linphone::StreamType streamType) { + emit videoEnabledChanged(); } \ No newline at end of file diff --git a/linphone-app/src/components/participant/ParticipantDeviceModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceModel.hpp index 98a01664d..63ab70b8f 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceModel.hpp @@ -30,12 +30,16 @@ class CallModel; -class ParticipantDeviceModel : public QObject { +class ParticipantDeviceModel : public QObject, public linphone::ParticipantDeviceListener { Q_OBJECT + public: ParticipantDeviceModel (std::shared_ptr device, const bool& isMe = false, QObject *parent = nullptr); - ParticipantDeviceModel (CallModel * call, const bool& isMe = true, QObject *parent = nullptr); + //ParticipantDeviceModel (CallModel * call, const bool& isMe = true, QObject *parent = nullptr); + + static std::shared_ptr create(std::shared_ptr device, const bool& isMe = false, QObject *parent = nullptr); + //static std::shared_ptr create(CallModel * call, const bool& isMe = true, QObject *parent = nullptr); Q_PROPERTY(QString name READ getName CONSTANT) Q_PROPERTY(QString address READ getAddress CONSTANT) @@ -54,6 +58,14 @@ public: std::shared_ptr getDevice(); //void deviceSecurityLevelChanged(std::shared_ptr device); + virtual void onIsSpeakingChanged(const std::shared_ptr & participantDevice, bool isSpeaking) override; + virtual void onIsMuted(const std::shared_ptr & participantDevice, bool isMuted) override; + virtual void onConferenceJoined(const std::shared_ptr & participantDevice) override; + virtual void onConferenceLeft(const std::shared_ptr & participantDevice) override; + virtual void onStreamCapabilityChanged(const std::shared_ptr & participantDevice, linphone::MediaDirection direction, linphone::StreamType streamType) override; + + + virtual void onStreamAvailabilityChanged(const std::shared_ptr & participantDevice, bool available, linphone::StreamType streamType) override; public slots: void onSecurityLevelChanged(std::shared_ptr device); @@ -67,7 +79,7 @@ private: std::shared_ptr mParticipantDevice; CallModel * mCall; - + std::weak_ptr mSelf; }; //Q_DECLARE_METATYPE(ParticipantModel *); diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp index 2e77e1ff8..8501407cb 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.cpp @@ -39,9 +39,10 @@ bool ParticipantDeviceProxyModel::filterAcceptsRow ( ) const { Q_UNUSED(sourceRow) Q_UNUSED(sourceParent) - //const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - //const ParticipantDeviceModel *device = index.data().value(); - return true; + const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); + const ParticipantDeviceModel *device = index.data().value(); + + return device && (isShowMe() || !device->isMe()); } bool ParticipantDeviceProxyModel::lessThan (const QModelIndex &left, const QModelIndex &right) const { @@ -63,12 +64,16 @@ CallModel * ParticipantDeviceProxyModel::getCallModel() const{ } int ParticipantDeviceProxyModel::getCount() const{ - ParticipantDeviceListModel* devices = dynamic_cast(sourceModel()); + ParticipantDeviceListModel* devices = qobject_cast(sourceModel()); if(devices) return devices->rowCount(); else return 0; } + +bool ParticipantDeviceProxyModel::isShowMe() const{ + return mShowMe; +} void ParticipantDeviceProxyModel::setCallModel(CallModel * callModel){ mCallModel = callModel; @@ -83,4 +88,11 @@ void ParticipantDeviceProxyModel::setParticipant(ParticipantModel * participant) connect(sourceModel, &ParticipantDeviceListModel::countChanged, this, &ParticipantDeviceProxyModel::countChanged); setSourceModel(sourceModel); emit countChanged(); +} + +void ParticipantDeviceProxyModel::setShowMe(const bool& show){ + if( mShowMe != show) { + mShowMe = show; + emit showMeChanged(); + } } \ No newline at end of file diff --git a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp index 7feebd1c9..fe2e4d504 100644 --- a/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp +++ b/linphone-app/src/components/participant/ParticipantDeviceProxyModel.hpp @@ -40,19 +40,24 @@ class ParticipantDeviceProxyModel : public QSortFilterProxyModel { public: Q_PROPERTY(CallModel * callModel READ getCallModel WRITE setCallModel NOTIFY callModelChanged) Q_PROPERTY(int count READ getCount NOTIFY countChanged) + Q_PROPERTY(bool showMe READ isShowMe WRITE setShowMe NOTIFY showMeChanged) + ParticipantDeviceProxyModel (QObject *parent = nullptr); Q_INVOKABLE ParticipantDeviceModel* getAt(int row); CallModel * getCallModel() const; Q_INVOKABLE int getCount() const; + bool isShowMe() const; void setCallModel(CallModel * callModel); void setParticipant(ParticipantModel * participant); + void setShowMe(const bool& show); signals: void callModelChanged(); void countChanged(); + void showMeChanged(); protected: virtual bool filterAcceptsRow (int sourceRow, const QModelIndex &sourceParent) const override; @@ -60,7 +65,7 @@ protected: std::shared_ptr mDevices; CallModel * mCallModel; - + bool mShowMe = false; }; #endif diff --git a/linphone-app/src/components/participant/ParticipantModel.cpp b/linphone-app/src/components/participant/ParticipantModel.cpp index 535ebbacc..0b01707e5 100644 --- a/linphone-app/src/components/participant/ParticipantModel.cpp +++ b/linphone-app/src/components/participant/ParticipantModel.cpp @@ -45,7 +45,7 @@ ParticipantModel::ParticipantModel (shared_ptr linphonePa // ----------------------------------------------------------------------------- ContactModel *ParticipantModel::getContactModel() const{ - return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(getSipAddress()); + return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(getSipAddress()).get(); } int ParticipantModel::getSecurityLevel() const{ diff --git a/linphone-app/src/components/participant/ParticipantProxyModel.cpp b/linphone-app/src/components/participant/ParticipantProxyModel.cpp index 4aa07211e..09cab38d5 100644 --- a/linphone-app/src/components/participant/ParticipantProxyModel.cpp +++ b/linphone-app/src/components/participant/ParticipantProxyModel.cpp @@ -46,12 +46,12 @@ ChatRoomModel *ParticipantProxyModel::getChatRoomModel() const{ } ParticipantListModel * ParticipantProxyModel::getParticipantListModel() const{ - return dynamic_cast(sourceModel()); + return qobject_cast(sourceModel()); } QStringList ParticipantProxyModel::getSipAddresses() const{ QStringList participants; - ParticipantListModel * list = dynamic_cast(sourceModel()); + ParticipantListModel * list = qobject_cast(sourceModel()); for(int i = 0 ; i < list->rowCount() ; ++i) participants << list->getAt(i)->getSipAddress(); return participants; @@ -59,14 +59,14 @@ QStringList ParticipantProxyModel::getSipAddresses() const{ QVariantList ParticipantProxyModel::getParticipants() const{ QVariantList participants; - ParticipantListModel * list = dynamic_cast(sourceModel()); + ParticipantListModel * list = qobject_cast(sourceModel()); for(int i = 0 ; i < list->rowCount() ; ++i) participants << QVariant::fromValue(list->getAt(i)); return participants; } int ParticipantProxyModel::getCount() const{ - return dynamic_cast(sourceModel())->rowCount(); + return qobject_cast(sourceModel())->rowCount(); } bool ParticipantProxyModel::getShowMe() const{ @@ -102,7 +102,7 @@ void ParticipantProxyModel::setShowMe(const bool& show){ } void ParticipantProxyModel::addAddress(const QString& address){ - ParticipantListModel * participantsModel = dynamic_cast(sourceModel()); + ParticipantListModel * participantsModel = qobject_cast(sourceModel()); if(!participantsModel->contains(address)){ std::shared_ptr participant = std::make_shared(nullptr); participant->setSipAddress(address); @@ -122,7 +122,7 @@ void ParticipantProxyModel::removeModel(ParticipantModel * participant){ QString sipAddress = participant->getSipAddress(); if(mChatRoomModel && mChatRoomModel->getChatRoom() && participant->getParticipant() ) mChatRoomModel->getChatRoom()->removeParticipant(participant->getParticipant()); // Remove already added - ParticipantListModel * participantsModel = dynamic_cast(sourceModel()); + ParticipantListModel * participantsModel = qobject_cast(sourceModel()); participantsModel->remove(participant); emit countChanged(); emit addressRemoved(sipAddress); diff --git a/linphone-app/src/components/participant/ParticipantProxyModel.hpp b/linphone-app/src/components/participant/ParticipantProxyModel.hpp index 8a042b3f4..6830a7a6d 100644 --- a/linphone-app/src/components/participant/ParticipantProxyModel.hpp +++ b/linphone-app/src/components/participant/ParticipantProxyModel.hpp @@ -71,11 +71,6 @@ signals: void addressRemoved(QString sipAddress); private: - /* - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override;*/ - - //std::shared_ptr mParticipantListModel; ChatRoomModel *mChatRoomModel; bool mShowMe = true; }; diff --git a/linphone-app/src/components/search/SearchResultModel.cpp b/linphone-app/src/components/search/SearchResultModel.cpp index 7ee8bef32..c0ab8ef25 100644 --- a/linphone-app/src/components/search/SearchResultModel.cpp +++ b/linphone-app/src/components/search/SearchResultModel.cpp @@ -48,7 +48,7 @@ std::shared_ptr SearchResultModel::getAddress() const{ } ContactModel * SearchResultModel::getContactModel() const{ - return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(getAddressStringUriOnly()); + return CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(getAddressStringUriOnly()).get(); } diff --git a/linphone-app/src/components/search/SearchSipAddressesProxyModel.cpp b/linphone-app/src/components/search/SearchSipAddressesProxyModel.cpp index 96359c8a5..5bb1d6cd6 100644 --- a/linphone-app/src/components/search/SearchSipAddressesProxyModel.cpp +++ b/linphone-app/src/components/search/SearchSipAddressesProxyModel.cpp @@ -42,7 +42,7 @@ SearchSipAddressesProxyModel::SearchSipAddressesProxyModel (QObject *parent) : Q // ----------------------------------------------------------------------------- SearchSipAddressesModel * SearchSipAddressesProxyModel::getModel(){ - return dynamic_cast(sourceModel()); + return qobject_cast(sourceModel()); } void SearchSipAddressesProxyModel::setFilter (const QString &pattern){ diff --git a/linphone-app/src/components/settings/AccountSettingsModel.cpp b/linphone-app/src/components/settings/AccountSettingsModel.cpp index cedcbbe1b..775697c72 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.cpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.cpp @@ -69,6 +69,7 @@ AccountSettingsModel::AccountSettingsModel (QObject *parent) : QObject(parent) { QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::fullSipAddressChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::registrationStateChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::conferenceURIChanged); + QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::videoConferenceURIChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::primaryDisplayNameChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::primaryUsernameChanged); QObject::connect(this, &AccountSettingsModel::accountSettingsUpdated, this, &AccountSettingsModel::primarySipAddressChanged); @@ -157,6 +158,8 @@ QVariantMap AccountSettingsModel::getAccountDescription (const shared_ptrgetConferenceFactoryUri()); + auto address = accountParams->getAudioVideoConferenceFactoryAddress(); + map["videoConferenceUri"] = address ? Utils::coreStringToAppString(address->asString()) : ""; map["contactParams"] = Utils::coreStringToAppString(accountParams->getContactParameters()); map["avpfInterval"] = accountParams->getAvpfRrInterval(); map["registerEnabled"] = accountParams->registerEnabled(); @@ -197,6 +200,17 @@ QString AccountSettingsModel::getConferenceURI() const{ return account ? Utils::coreStringToAppString(account->getParams()->getConferenceFactoryUri()) : ""; } +QString AccountSettingsModel::getVideoConferenceURI() const{ + shared_ptr core = CoreManager::getInstance()->getCore(); + shared_ptr account = core->getDefaultAccount(); + if(account) { + auto address = account->getParams()->getAudioVideoConferenceFactoryAddress(); + return address ? Utils::coreStringToAppString(address->asString()) : ""; + }else + return ""; +} + + void AccountSettingsModel::setDefaultAccount (const shared_ptr &account) { shared_ptr core = CoreManager::getInstance()->getCore(); if (mSelectedAccount != account) { @@ -302,9 +316,13 @@ bool AccountSettingsModel::addOrUpdateAccount( routes.push_back(Utils::interpretUrl(data["route"].toString())); accountParams->setRoutesAddresses(routes); } - QString conferenceURI = data["conferenceUri"].toString(); - if(!conferenceURI.isEmpty()) - accountParams->setConferenceFactoryUri(Utils::appStringToCoreString(conferenceURI)); + QString txt = data["conferenceUri"].toString(); + if(!txt.isEmpty()) + accountParams->setConferenceFactoryUri(Utils::appStringToCoreString(txt)); + txt = data["videoConferenceUri"].toString(); + if(!txt.isEmpty()) + accountParams->setAudioVideoConferenceFactoryAddress(Utils::interpretUrl(txt)); + if(data.contains("contactParams")) accountParams->setContactParameters(Utils::appStringToCoreString(data["contactParams"].toString())); if(data.contains("avpfInterval")) diff --git a/linphone-app/src/components/settings/AccountSettingsModel.hpp b/linphone-app/src/components/settings/AccountSettingsModel.hpp index e3c9f1801..778990392 100644 --- a/linphone-app/src/components/settings/AccountSettingsModel.hpp +++ b/linphone-app/src/components/settings/AccountSettingsModel.hpp @@ -40,6 +40,7 @@ class AccountSettingsModel : public QObject { Q_PROPERTY(RegistrationState registrationState READ getRegistrationState NOTIFY registrationStateChanged) Q_PROPERTY(QString conferenceURI READ getConferenceURI NOTIFY conferenceURIChanged) + Q_PROPERTY(QString videoConferenceURI READ getVideoConferenceURI NOTIFY videoConferenceURIChanged) // Default info. Q_PROPERTY(QString primaryDisplayName READ getPrimaryDisplayName WRITE setPrimaryDisplayName NOTIFY primaryDisplayNameChanged) @@ -70,6 +71,7 @@ public: Q_INVOKABLE QVariantMap getAccountDescription (const std::shared_ptr &account); QString getConferenceURI() const; + QString getVideoConferenceURI() const; Q_INVOKABLE void setDefaultAccount (const std::shared_ptr &account = nullptr); Q_INVOKABLE void setDefaultAccountFromSipAddress (const QString &sipAddress); @@ -95,6 +97,7 @@ signals: void fullSipAddressChanged(); void registrationStateChanged(); void conferenceURIChanged(); + void videoConferenceURIChanged(); void primaryDisplayNameChanged(); void primaryUsernameChanged(); @@ -102,8 +105,6 @@ signals: void accountsChanged(); - - void accountSettingsUpdated (); void defaultAccountChanged(); void publishPresenceChanged(); diff --git a/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp b/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp index 0925dc971..cf714e3ed 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp +++ b/linphone-app/src/components/sip-addresses/SipAddressObserver.cpp @@ -27,7 +27,7 @@ SipAddressObserver::SipAddressObserver (const QString &peerAddress, const QStrin mLocalAddress = localAddress; } -void SipAddressObserver::setContact (ContactModel *contact) { +void SipAddressObserver::setContact (QSharedPointer contact) { if (contact == mContact) return; diff --git a/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp b/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp index 8bec1502d..cb3175da1 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp +++ b/linphone-app/src/components/sip-addresses/SipAddressObserver.hpp @@ -23,6 +23,8 @@ #include "components/presence/Presence.hpp" +#include + // ============================================================================= class ContactModel; @@ -50,7 +52,7 @@ public: int securityLevel = 1; signals: - void contactChanged (ContactModel *contact); + void contactChanged (QSharedPointer); void presenceStatusChanged (const Presence::PresenceStatus &presenceStatus); void unreadMessageCountChanged (int unreadMessageCount); @@ -66,10 +68,10 @@ private: // --------------------------------------------------------------------------- ContactModel *getContact () const { - return mContact; + return mContact.get(); } - void setContact (ContactModel *contact); + void setContact (QSharedPointer contact); // --------------------------------------------------------------------------- @@ -90,7 +92,7 @@ private: QString mPeerAddress; QString mLocalAddress; - ContactModel *mContact = nullptr; + QSharedPointer mContact; Presence::PresenceStatus mPresenceStatus = Presence::PresenceStatus::Offline; int mUnreadMessageCount = 0; }; diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp index 6d2ec9ea8..b7a284cfb 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.cpp @@ -45,7 +45,7 @@ using namespace std; static inline QVariantMap buildVariantMap (const SipAddressesModel::SipAddressEntry &sipAddressEntry) { return QVariantMap{ { "sipAddress", sipAddressEntry.sipAddress }, - { "contactModel", QVariant::fromValue(sipAddressEntry.contact) }, + { "contactModel", QVariant::fromValue(sipAddressEntry.contact.get()) }, { "presenceStatus", sipAddressEntry.presenceStatus }, { "__localToConferenceEntry", QVariant::fromValue(&sipAddressEntry.localAddressToConferenceEntry) } }; @@ -120,7 +120,7 @@ QVariantMap SipAddressesModel::find (const QString &sipAddress) const { ContactModel *SipAddressesModel::mapSipAddressToContact (const QString &sipAddress) const { QString cleanedAddress = Utils::cleanSipAddress(sipAddress); auto it = mPeerAddressToSipAddressEntry.find(cleanedAddress); - return it == mPeerAddressToSipAddressEntry.end() ? nullptr : it->contact; + return it == mPeerAddressToSipAddressEntry.end() ? nullptr : it->contact.get(); } // ----------------------------------------------------------------------------- @@ -268,7 +268,7 @@ bool SipAddressesModel::removeRows (int row, int count, const QModelIndex &paren // ----------------------------------------------------------------------------- -void SipAddressesModel::handleChatRoomModelCreated (const shared_ptr &chatRoomModel) { +void SipAddressesModel::handleChatRoomModelCreated (const QSharedPointer &chatRoomModel) { ChatRoomModel *ptr = chatRoomModel.get(); QObject::connect(ptr, &ChatRoomModel::allEntriesRemoved, this, [this, ptr] { @@ -289,30 +289,30 @@ void SipAddressesModel::handleHistoryModelCreated (HistoryModel *historyModel) { handleAllCallCountReset(); }); } -void SipAddressesModel::handleContactAdded (ContactModel *contact) { +void SipAddressesModel::handleContactAdded (QSharedPointer contact) { for (const auto &sipAddress : contact->getVcardModel()->getSipAddresses()) { addOrUpdateSipAddress(sipAddress.toString(), contact); } } -void SipAddressesModel::handleContactRemoved (const ContactModel *contact) { +void SipAddressesModel::handleContactRemoved (QSharedPointer contact) { for (const auto &sipAddress : contact->getVcardModel()->getSipAddresses()) removeContactOfSipAddress(sipAddress.toString()); } -void SipAddressesModel::handleSipAddressAdded (ContactModel *contact, const QString &sipAddress) { +void SipAddressesModel::handleSipAddressAdded (QSharedPointer contact, const QString &sipAddress) { ContactModel *mappedContact = mapSipAddressToContact(sipAddress); if (mappedContact) { - qWarning() << "Unable to map sip address" << sipAddress << "to" << contact << "- already used by" << mappedContact; + qWarning() << "Unable to map sip address" << sipAddress << "to" << contact.get() << "- already used by" << mappedContact; return; } addOrUpdateSipAddress(sipAddress, contact); } -void SipAddressesModel::handleSipAddressRemoved (ContactModel *contact, const QString &sipAddress) { +void SipAddressesModel::handleSipAddressRemoved (QSharedPointer contact, const QString &sipAddress) { ContactModel *mappedContact = mapSipAddressToContact(sipAddress); - if (contact != mappedContact) { - qWarning() << "Unable to remove sip address" << sipAddress << "of" << contact << "- already used by" << mappedContact; + if (contact.get() != mappedContact) { + qWarning() << "Unable to remove sip address" << sipAddress << "of" << contact.get() << "- already used by" << mappedContact; return; } @@ -467,7 +467,7 @@ void SipAddressesModel::handleIsComposingChanged (const shared_ptr contact) { const QString &sipAddress = sipAddressEntry.sipAddress; sipAddressEntry.contact = contact; @@ -547,10 +547,10 @@ void SipAddressesModel::removeContactOfSipAddress (const QString &sipAddress) { } // Try to map other contact on this sip address. - ContactModel *contactModel = CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(sipAddress); + auto contactModel = CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(sipAddress); updateObservers(sipAddress, contactModel); - qInfo() << QStringLiteral("Map new contact on sip address: `%1`.").arg(sipAddress) << contactModel; + qInfo() << QStringLiteral("Map new contact on sip address: `%1`.").arg(sipAddress) << contactModel.get(); addOrUpdateSipAddress(*it, contactModel); int row = mRefs.indexOf(&(*it)); @@ -630,7 +630,7 @@ void SipAddressesModel::initSipAddressesFromCalls () { void SipAddressesModel::initSipAddressesFromContacts () { for (auto &contact : CoreManager::getInstance()->getContactsListModel()->mList) - handleContactAdded(contact); + handleContactAdded(contact.objectCast()); } void SipAddressesModel::initRefs () { @@ -640,7 +640,7 @@ void SipAddressesModel::initRefs () { // ----------------------------------------------------------------------------- -void SipAddressesModel::updateObservers (const QString &sipAddress, ContactModel *contact) { +void SipAddressesModel::updateObservers (const QString &sipAddress, QSharedPointer contact) { for (auto &observer : mObservers.values(sipAddress)) observer->setContact(contact); } diff --git a/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp b/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp index adc7c17e1..31acf8a55 100644 --- a/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp +++ b/linphone-app/src/components/sip-addresses/SipAddressesModel.hpp @@ -23,6 +23,7 @@ #include #include +#include #include "SipAddressObserver.hpp" @@ -47,7 +48,7 @@ public: struct SipAddressEntry { QString sipAddress; - ContactModel *contact; + QSharedPointer contact; Presence::PresenceStatus presenceStatus; QHash localAddressToConferenceEntry; }; @@ -96,14 +97,14 @@ private: // --------------------------------------------------------------------------- - void handleChatRoomModelCreated (const std::shared_ptr &chatRoomModel); + void handleChatRoomModelCreated (const QSharedPointer &chatRoomModel); void handleHistoryModelCreated (HistoryModel *historyModel) ; - void handleContactAdded (ContactModel *contact); - void handleContactRemoved (const ContactModel *contact); + void handleContactAdded (QSharedPointer contact); + void handleContactRemoved (QSharedPointer contact); - void handleSipAddressAdded (ContactModel *contact, const QString &sipAddress); - void handleSipAddressRemoved (ContactModel *contact, const QString &sipAddress); + void handleSipAddressAdded (QSharedPointer contact, const QString &sipAddress); + void handleSipAddressRemoved (QSharedPointer contact, const QString &sipAddress); void handleMessageReceived (const std::shared_ptr &message); void handleCallStateChanged (const std::shared_ptr &call, linphone::Call::State state); @@ -122,7 +123,7 @@ private: // A sip address exists in this list if a contact is linked to it, or a call, or a message. - void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, ContactModel *contact); + void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, QSharedPointer contact); void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const std::shared_ptr &call); void addOrUpdateSipAddress (SipAddressEntry &sipAddressEntry, const std::shared_ptr &message); @@ -144,7 +145,7 @@ private: void initRefs (); - void updateObservers (const QString &sipAddress, ContactModel *contact); + void updateObservers (const QString &sipAddress, QSharedPointer contact); void updateObservers (const QString &sipAddress, const Presence::PresenceStatus &presenceStatus); void updateObservers (const QString &peerAddress, const QString &localAddress, int messageCount, int missedCallCount); diff --git a/linphone-app/src/components/timeline/TimelineListModel.cpp b/linphone-app/src/components/timeline/TimelineListModel.cpp index b22efadcc..c4c9b1d61 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.cpp +++ b/linphone-app/src/components/timeline/TimelineListModel.cpp @@ -38,7 +38,7 @@ // ============================================================================= -TimelineListModel::TimelineListModel (QObject *parent) : QAbstractListModel(parent) { +TimelineListModel::TimelineListModel (QObject *parent) : ProxyListModel(parent) { mSelectedCount = 0; CoreHandlers* coreHandlers= CoreManager::getInstance()->getHandlers().get(); connect(coreHandlers, &CoreHandlers::chatRoomStateChanged, this, &TimelineListModel::onChatRoomStateChanged); @@ -55,10 +55,6 @@ TimelineListModel::TimelineListModel (QObject *parent) : QAbstractListModel(pare // ----------------------------------------------------------------------------- -TimelineModel * TimelineListModel::getAt(const int& index){ - return mTimelines[index].get(); -} - void TimelineListModel::reset(){ updateTimelines (); } @@ -68,54 +64,25 @@ void TimelineListModel::update(){ } void TimelineListModel::selectAll(const bool& selected){ - for(auto it = mTimelines.begin() ; it != mTimelines.end() ; ++it) - (*it)->setSelected(selected); -} -int TimelineListModel::rowCount (const QModelIndex &) const { - return mTimelines.count(); -} - -QHash TimelineListModel::roleNames () const { - QHash roles; - roles[Qt::DisplayRole] = "$timelines"; - return roles; -} - -QVariant TimelineListModel::data (const QModelIndex &index, int role) const { - int row = index.row(); - - if (!index.isValid() || row < 0 || row >= mTimelines.count()) - return QVariant(); - - if (role == Qt::DisplayRole)// && !mTimelines[row]->getChatRoomModel()->mDeleteChatRoom) - return QVariant::fromValue(mTimelines[row].get()); - - return QVariant(); + for(auto it = mList.begin() ; it != mList.end() ; ++it) + it->objectCast()->setSelected(selected); } // ----------------------------------------------------------------------------- - - -// ----------------------------------------------------------------------------- - -bool TimelineListModel::removeRow (int row, const QModelIndex &parent) { - return removeRows(row, 1, parent); -} - bool TimelineListModel::removeRows (int row, int count, const QModelIndex &parent) { - QVector > oldTimelines; + QVector > oldTimelines; oldTimelines.reserve(count); int limit = row + count - 1; - if (row < 0 || count < 0 || limit >= mTimelines.count()) + if (row < 0 || count < 0 || limit >= mList.count()) return false; beginRemoveRows(parent, row, limit); for (int i = 0; i < count; ++i){ - auto timeline = mTimelines.takeAt(row); - timeline->getChatRoomModel()->getChatRoom()->removeListener(timeline); + auto timeline = mList.takeAt(row).objectCast(); + timeline->disconnectChatRoomListener(); oldTimelines.push_back(timeline); } @@ -131,15 +98,16 @@ bool TimelineListModel::removeRows (int row, int count, const QModelIndex &paren // ----------------------------------------------------------------------------- -std::shared_ptr TimelineListModel::getTimeline(std::shared_ptr chatRoom, const bool &create){ +QSharedPointer TimelineListModel::getTimeline(std::shared_ptr chatRoom, const bool &create){ if(chatRoom){ - for(auto it = mTimelines.begin() ; it != mTimelines.end() ; ++it){ - if( (*it)->getChatRoomModel()->getChatRoom() == chatRoom){ - return *it; + for(auto it = mList.begin() ; it != mList.end() ; ++it){ + auto timeline = it->objectCast(); + if( timeline->getChatRoomModel()->getChatRoom() == chatRoom){ + return timeline; } } if(create){ - std::shared_ptr model = TimelineModel::create(chatRoom); + QSharedPointer model = TimelineModel::create(chatRoom); if(model){ //std::shared_ptr model = std::make_shared(chatRoom); connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); @@ -155,7 +123,7 @@ std::shared_ptr TimelineListModel::getTimeline(std::shared_ptr
  • TimelineListModel::getTimeline(std::shared_ptr conference, const bool &create){ if(chatRoom){ - for(auto it = mTimelines.begin() ; it != mTimelines.end() ; ++it){ + for(auto it = mList.begin() ; it != mList.end() ; ++it){ if( (*it)->isConference() && (*it)->getConferenceModel()->getConference() == conference){ return *it; } @@ -178,8 +146,8 @@ QVariantList TimelineListModel::getLastChatRooms(const int& maxCount) const{ QDateTime currentDateTime = QDateTime::currentDateTime(); bool doTest = true; - for(auto timeline : mTimelines){ - auto chatRoom = timeline->getChatRoomModel(); + for(auto timeline : mList){ + auto chatRoom = timeline.objectCast()->getChatRoomModel(); if(chatRoom && chatRoom->isCurrentAccount() && chatRoom->isOneToOne() && !chatRoom->haveEncryption()) { sortedData.insert(chatRoom->mLastUpdateTime.secsTo(currentDateTime),chatRoom); } @@ -200,14 +168,15 @@ QVariantList TimelineListModel::getLastChatRooms(const int& maxCount) const{ return contacts; } -std::shared_ptr TimelineListModel::getChatRoomModel(std::shared_ptr chatRoom, const bool& create){ +QSharedPointer TimelineListModel::getChatRoomModel(std::shared_ptr chatRoom, const bool& create){ if(chatRoom ){ - for(auto timeline : mTimelines){ - if(timeline->mChatRoomModel->getChatRoom() == chatRoom) - return timeline->mChatRoomModel; + for(auto timeline : mList){ + auto model = timeline.objectCast()->mChatRoomModel; + if(model->getChatRoom() == chatRoom) + return model; } if(create){ - std::shared_ptr model = TimelineModel::create(chatRoom); + QSharedPointer model = TimelineModel::create(chatRoom); if(model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); @@ -221,18 +190,15 @@ std::shared_ptr TimelineListModel::getChatRoomModel(std::shared_p return nullptr; } -std::shared_ptr TimelineListModel::getChatRoomModel(ChatRoomModel * chatRoom){ - for(auto timeline : mTimelines){ - if(timeline->mChatRoomModel.get() == chatRoom) - return timeline->mChatRoomModel; +QSharedPointer TimelineListModel::getChatRoomModel(ChatRoomModel * chatRoom){ + for(auto timeline : mList){ + auto model = timeline.objectCast()->mChatRoomModel; + if(model == chatRoom) + return model; } return nullptr; } -int TimelineListModel::getCount() const{ - return mTimelines.size(); -} - //------------------------------------------------------------------------------------------------- void TimelineListModel::setSelectedCount(int selectedCount){ @@ -247,9 +213,9 @@ void TimelineListModel::onSelectedHasChanged(bool selected){ if(selected) { if(mSelectedCount >= 1){// We have more selection than wanted : count select first and unselect after : the final signal will be send only on limit setSelectedCount(mSelectedCount+1);// It will not send a change signal - for(auto it = mTimelines.begin() ; it != mTimelines.end() ; ++it) + for(auto it = mList.begin() ; it != mList.end() ; ++it) if(it->get() != sender()) - (*it)->setSelected(false); + it->objectCast()->setSelected(false); }else setSelectedCount(mSelectedCount+1); emit selectedChanged(qobject_cast(sender())); @@ -270,11 +236,11 @@ void TimelineListModel::updateTimelines () { }); //Remove no more chat rooms - auto itTimeline = mTimelines.begin(); - while(itTimeline != mTimelines.end()) { + auto itTimeline = mList.begin(); + while(itTimeline != mList.end()) { auto itDbTimeline = allChatRooms.begin(); if(*itTimeline) { - auto chatRoomModel = (*itTimeline)->getChatRoomModel(); + auto chatRoomModel = itTimeline->objectCast()->getChatRoomModel(); if(chatRoomModel) { auto timeline = chatRoomModel->getChatRoom(); if( timeline ) { @@ -288,14 +254,14 @@ void TimelineListModel::updateTimelines () { }else itDbTimeline = allChatRooms.end(); if( itDbTimeline == allChatRooms.end()){ - int index = itTimeline - mTimelines.begin(); + int index = itTimeline - mList.begin(); if(index>0){ --itTimeline; removeRow(index); ++itTimeline; }else{ removeRow(0); - itTimeline = mTimelines.begin(); + itTimeline = mList.begin(); } }else ++itTimeline; @@ -308,7 +274,7 @@ void TimelineListModel::updateTimelines () { auto haveTimeline = getTimeline(dbChatRoom, false); if(!haveTimeline && dbChatRoom){// Create a new Timeline if needed - std::shared_ptr model = TimelineModel::create(dbChatRoom, callLogs); + QSharedPointer model = TimelineModel::create(dbChatRoom, callLogs); if( model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); @@ -319,29 +285,19 @@ void TimelineListModel::updateTimelines () { CoreManager::getInstance()->updateUnreadMessageCount(); } -void TimelineListModel::add (std::shared_ptr timeline){ +void TimelineListModel::add (QSharedPointer timeline){ connect(timeline->getChatRoomModel(), &ChatRoomModel::lastUpdateTimeChanged, this, &TimelineListModel::updated); - int row = mTimelines.count(); - beginInsertRows(QModelIndex(), row, row); - mTimelines << timeline; - endInsertRows(); + ProxyListModel::add(timeline); emit layoutChanged(); emit countChanged(); } -void TimelineListModel::remove (TimelineModel* model) { -} -void TimelineListModel::remove(std::shared_ptr model){ - int index = mTimelines.indexOf(model); - if (index >=0){ - removeRow(index); - } -} -void TimelineListModel::removeChatRoomModel(std::shared_ptr model){ +void TimelineListModel::removeChatRoomModel(QSharedPointer model){ if(!model || (model->getChatRoom()->isEmpty() && (model->isReadOnly() || !model->isGroupEnabled()))){ - auto itTimeline = mTimelines.begin(); - while(itTimeline != mTimelines.end()) { - if((*itTimeline)->mChatRoomModel == model){ + auto itTimeline = mList.begin(); + while(itTimeline != mList.end()) { + auto timeline = itTimeline->objectCast(); + if(timeline->mChatRoomModel == model){ if(model) model->deleteChatRoom(); remove(*itTimeline); @@ -364,7 +320,7 @@ void TimelineListModel::select(ChatRoomModel * chatRoomModel){ void TimelineListModel::onChatRoomStateChanged(const std::shared_ptr &chatRoom,linphone::ChatRoom::State state){ if( state == linphone::ChatRoom::State::Created && !getTimeline(chatRoom, false)){// Create a new Timeline if needed - std::shared_ptr model = TimelineModel::create(chatRoom); + QSharedPointer model = TimelineModel::create(chatRoom); if(model){ connect(model.get(), SIGNAL(selectedChanged(bool)), this, SLOT(onSelectedHasChanged(bool))); connect(model->getChatRoomModel(), &ChatRoomModel::allEntriesRemoved, this, &TimelineListModel::removeChatRoomModel); @@ -399,8 +355,6 @@ void TimelineListModel::onCallCreated(const std::shared_ptr &cal bool createSecureChatRoom = false; SettingsModel * settingsModel = CoreManager::getInstance()->getSettingsModel(); - - if( settingsModel->getSecureChatEnabled() && (!settingsModel->getStandardChatEnabled() || (settingsModel->getStandardChatEnabled() && isEncrypted)) ){ @@ -413,7 +367,8 @@ void TimelineListModel::onCallCreated(const std::shared_ptr &cal , nullptr//callLog->getRemoteAddress() , participants); if(chatRoom){ - for(auto timeline : mTimelines){ + for(auto item : mList){ + auto timeline = item.objectCast(); if( chatRoom == timeline->mChatRoomModel->getChatRoom()){ found = true; if(isOutgoing)// If outgoing, we switch to this chat room diff --git a/linphone-app/src/components/timeline/TimelineListModel.hpp b/linphone-app/src/components/timeline/TimelineListModel.hpp index 32de49cee..54a6e96da 100644 --- a/linphone-app/src/components/timeline/TimelineListModel.hpp +++ b/linphone-app/src/components/timeline/TimelineListModel.hpp @@ -22,49 +22,44 @@ #define TIMELINE_LIST_MODEL_H_ #include +#include + +#include "app/proxyModel/ProxyListModel.hpp" #include "components/chat-room/ChatRoomModel.hpp" + class TimelineModel; // ============================================================================= -class TimelineListModel : public QAbstractListModel { +class TimelineListModel : public ProxyListModel { Q_OBJECT public: Q_PROPERTY(int selectedCount MEMBER mSelectedCount WRITE setSelectedCount NOTIFY selectedCountChanged) - Q_PROPERTY(int count READ getCount NOTIFY countChanged) + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) TimelineListModel (QObject *parent = Q_NULLPTR); void reset(); void selectAll(const bool& selected); TimelineModel * getAt(const int& index); - std::shared_ptr getTimeline(std::shared_ptr chatRoom, const bool &create); + QSharedPointer getTimeline(std::shared_ptr chatRoom, const bool &create); //std::shared_ptr getTimeline(std::shared_ptr chatRoom, const bool &create); Q_INVOKABLE QVariantList getLastChatRooms(const int& maxCount) const; - std::shared_ptr getChatRoomModel(std::shared_ptr chatRoom, const bool &create); - std::shared_ptr getChatRoomModel(ChatRoomModel * chatRoom); - int getCount() const; + QSharedPointer getChatRoomModel(std::shared_ptr chatRoom, const bool &create); + QSharedPointer getChatRoomModel(ChatRoomModel * chatRoom); - int rowCount (const QModelIndex &index = QModelIndex()) const override; - - QHash roleNames () const override; - QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const override; - - void add (std::shared_ptr timeline); // Use to add a timeline that is not in Linphone list (like empty chat rooms that were hide by configuration) -// Remove a chatroom - Q_INVOKABLE void remove (TimelineModel *importer); - void remove(std::shared_ptr model); - + void add (QSharedPointer timeline); // Use to add a timeline that is not in Linphone list (like empty chat rooms that were hide by configuration) + Q_INVOKABLE void select(ChatRoomModel * chatRoomModel); - int mSelectedCount; + void setSelectedCount(int selectedCount); + int mSelectedCount; bool mAutoSelectAfterCreation = false;// Request to select the next chat room after creation - void setSelectedCount(int selectedCount); public slots: void update(); - void removeChatRoomModel(std::shared_ptr model); + void removeChatRoomModel(QSharedPointer model); void onSelectedHasChanged(bool selected); void onChatRoomStateChanged(const std::shared_ptr &chatRoom,linphone::ChatRoom::State state); void onCallStateChanged (const std::shared_ptr &call, linphone::Call::State state) ; @@ -80,12 +75,9 @@ signals: void updated(); private: - bool removeRow (int row, const QModelIndex &parent = QModelIndex()); - bool removeRows (int row, int count, const QModelIndex &parent = QModelIndex()) override; + virtual bool removeRows (int row, int count, const QModelIndex &parent) override; void updateTimelines(); - - QList> mTimelines; }; #endif // TIMELINE_LIST_MODEL_H_ diff --git a/linphone-app/src/components/timeline/TimelineModel.cpp b/linphone-app/src/components/timeline/TimelineModel.cpp index f11d1a4bc..f737e36bc 100644 --- a/linphone-app/src/components/timeline/TimelineModel.cpp +++ b/linphone-app/src/components/timeline/TimelineModel.cpp @@ -22,6 +22,7 @@ #include "components/settings/AccountSettingsModel.hpp" #include "components/sip-addresses/SipAddressesModel.hpp" #include "components/chat-room/ChatRoomModel.hpp" +#include "components/chat-room/ChatRoomListener.hpp" #include "utils/Utils.hpp" #include "app/App.hpp" @@ -34,14 +35,40 @@ #include #include +void TimelineModel::connectTo(ChatRoomListener * listener){ + connect(listener, &ChatRoomListener::isComposingReceived, this, &TimelineModel::onIsComposingReceived); + connect(listener, &ChatRoomListener::messageReceived, this, &TimelineModel::onMessageReceived); + connect(listener, &ChatRoomListener::newEvent, this, &TimelineModel::onNewEvent); + connect(listener, &ChatRoomListener::chatMessageReceived, this, &TimelineModel::onChatMessageReceived); + connect(listener, &ChatRoomListener::chatMessageSending, this, &TimelineModel::onChatMessageSending); + connect(listener, &ChatRoomListener::chatMessageSent, this, &TimelineModel::onChatMessageSent); + connect(listener, &ChatRoomListener::participantAdded, this, &TimelineModel::onParticipantAdded); + connect(listener, &ChatRoomListener::participantRemoved, this, &TimelineModel::onParticipantRemoved); + connect(listener, &ChatRoomListener::participantAdminStatusChanged, this, &TimelineModel::onParticipantAdminStatusChanged); + connect(listener, &ChatRoomListener::stateChanged, this, &TimelineModel::onStateChanged); + connect(listener, &ChatRoomListener::securityEvent, this, &TimelineModel::onSecurityEvent); + connect(listener, &ChatRoomListener::subjectChanged, this, &TimelineModel::onSubjectChanged); + connect(listener, &ChatRoomListener::undecryptableMessageReceived, this, &TimelineModel::onUndecryptableMessageReceived); + connect(listener, &ChatRoomListener::participantDeviceAdded, this, &TimelineModel::onParticipantDeviceAdded); + connect(listener, &ChatRoomListener::participantDeviceRemoved, this, &TimelineModel::onParticipantDeviceRemoved); + connect(listener, &ChatRoomListener::conferenceJoined, this, &TimelineModel::onConferenceJoined); + connect(listener, &ChatRoomListener::conferenceLeft, this, &TimelineModel::onConferenceLeft); + connect(listener, &ChatRoomListener::ephemeralEvent, this, &TimelineModel::onEphemeralEvent); + connect(listener, &ChatRoomListener::ephemeralMessageTimerStarted, this, &TimelineModel::onEphemeralMessageTimerStarted); + connect(listener, &ChatRoomListener::ephemeralMessageDeleted, this, &TimelineModel::onEphemeralMessageDeleted); + connect(listener, &ChatRoomListener::conferenceAddressGeneration, this, &TimelineModel::onConferenceAddressGeneration); + connect(listener, &ChatRoomListener::participantRegistrationSubscriptionRequested, this, &TimelineModel::onParticipantRegistrationSubscriptionRequested); + connect(listener, &ChatRoomListener::participantRegistrationUnsubscriptionRequested, this, &TimelineModel::onParticipantRegistrationUnsubscriptionRequested); + connect(listener, &ChatRoomListener::chatMessageShouldBeStored, this, &TimelineModel::onChatMessageShouldBeStored); + connect(listener, &ChatRoomListener::chatMessageParticipantImdnStateChanged, this, &TimelineModel::onChatMessageParticipantImdnStateChanged); +} // ============================================================================= -std::shared_ptr TimelineModel::create(std::shared_ptr chatRoom, const std::list>& callLogs, QObject *parent){ +QSharedPointer TimelineModel::create(std::shared_ptr chatRoom, const std::list>& callLogs, QObject *parent){ if((!chatRoom || chatRoom->getState() != linphone::ChatRoom::State::Terminated) && (!CoreManager::getInstance()->getTimelineListModel() || !CoreManager::getInstance()->getTimelineListModel()->getTimeline(chatRoom, false)) ) { - std::shared_ptr model = std::make_shared(chatRoom, parent); + QSharedPointer model = QSharedPointer::create(chatRoom, parent); if(model && model->getChatRoomModel()){ - model->mSelf = model; - chatRoom->addListener(model); + // Get Max updatetime from chat room and last call event auto timelineChatRoom = model->getChatRoomModel(); std::shared_ptr lastCall = nullptr; @@ -85,6 +112,11 @@ TimelineModel::TimelineModel (std::shared_ptr chatRoom, QObj QObject::connect(this, &TimelineModel::selectedChanged, this, &TimelineModel::updateUnreadCount); QObject::connect(CoreManager::getInstance()->getAccountSettingsModel(), &AccountSettingsModel::defaultAccountChanged, this, &TimelineModel::onDefaultAccountChanged); } + if(chatRoom){ + mChatRoomListener = std::make_shared(this); + connectTo(mChatRoomListener.get()); + chatRoom->addListener(mChatRoomListener); + } mSelected = false; } @@ -132,7 +164,7 @@ void TimelineModel::setSelected(const bool& selected){ << ", isReadOnly:" << mChatRoomModel->isReadOnly() << ", state:" << mChatRoomModel->getState(); }else - mChatRoomModel->resetEntries();// Cleanup leaving chat room + mChatRoomModel->resetData();// Cleanup leaving chat room emit selectedChanged(mSelected); } } @@ -146,6 +178,13 @@ void TimelineModel::onDefaultAccountChanged(){ if( mSelected && !mChatRoomModel->isCurrentAccount()) setSelected(false); } + +void TimelineModel::disconnectChatRoomListener(){ + if( mChatRoomModel && mChatRoomListener){ + mChatRoomModel->getChatRoom()->removeListener(mChatRoomListener); + } +} + //---------------------------------------------------------- //------ CHAT ROOM HANDLERS //---------------------------------------------------------- diff --git a/linphone-app/src/components/timeline/TimelineModel.hpp b/linphone-app/src/components/timeline/TimelineModel.hpp index 61b7b2c81..fe53cc52a 100644 --- a/linphone-app/src/components/timeline/TimelineModel.hpp +++ b/linphone-app/src/components/timeline/TimelineModel.hpp @@ -25,18 +25,20 @@ // ============================================================================= #include #include +#include #include #include "../contact/ContactModel.hpp" class ChatRoomModel; +class ChatRoomListener; -class TimelineModel : public QObject, public linphone::ChatRoomListener { +class TimelineModel : public QObject { Q_OBJECT public: - static std::shared_ptr create(std::shared_ptr chatRoom, const std::list>& callLogs = std::list>(), QObject *parent = Q_NULLPTR); + static QSharedPointer create(std::shared_ptr chatRoom, const std::list>& callLogs = std::list>(), QObject *parent = Q_NULLPTR); TimelineModel (std::shared_ptr chatRoom, QObject *parent = Q_NULLPTR); virtual ~TimelineModel(); @@ -62,35 +64,37 @@ public: void setSelected(const bool& selected); Q_INVOKABLE ChatRoomModel* getChatRoomModel() const; + + void disconnectChatRoomListener(); bool mSelected; - std::shared_ptr mChatRoomModel; + QSharedPointer mChatRoomModel; - virtual void onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing) override; - virtual void onMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; - virtual void onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onChatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onChatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onChatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState) override; - virtual void onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onSubjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onUndecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; - virtual void onParticipantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onParticipantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onConferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onEphemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onEphemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog) override; - virtual void onConferenceAddressGeneration(const std::shared_ptr & chatRoom) override; - virtual void onParticipantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress) override; - virtual void onParticipantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress) override; - virtual void onChatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message) override; - virtual void onChatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state) override; + virtual void onIsComposingReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & remoteAddress, bool isComposing); + virtual void onMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message); + virtual void onNewEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onChatMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onChatMessageSending(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onChatMessageSent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onParticipantAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onParticipantRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onParticipantAdminStatusChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onStateChanged(const std::shared_ptr & chatRoom, linphone::ChatRoom::State newState); + virtual void onSecurityEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onSubjectChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onUndecryptableMessageReceived(const std::shared_ptr & chatRoom, const std::shared_ptr & message); + virtual void onParticipantDeviceAdded(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onParticipantDeviceRemoved(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onConferenceJoined(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onConferenceLeft(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onEphemeralEvent(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onEphemeralMessageTimerStarted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onEphemeralMessageDeleted(const std::shared_ptr & chatRoom, const std::shared_ptr & eventLog); + virtual void onConferenceAddressGeneration(const std::shared_ptr & chatRoom); + virtual void onParticipantRegistrationSubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress); + virtual void onParticipantRegistrationUnsubscriptionRequested(const std::shared_ptr & chatRoom, const std::shared_ptr & participantAddress); + virtual void onChatMessageShouldBeStored(const std::shared_ptr & chatRoom, const std::shared_ptr & message); + virtual void onChatMessageParticipantImdnStateChanged(const std::shared_ptr & chatRoom, const std::shared_ptr & message, const std::shared_ptr & state); public slots: void updateUnreadCount(); @@ -108,8 +112,9 @@ signals: private: - std::weak_ptr mSelf; + void connectTo(ChatRoomListener * listener); + std::shared_ptr mChatRoomListener; }; -#endif // TIMELINE_MODEL_H_ +#endif diff --git a/linphone-app/src/components/timeline/TimelineProxyModel.cpp b/linphone-app/src/components/timeline/TimelineProxyModel.cpp index 591291604..5629c6e22 100644 --- a/linphone-app/src/components/timeline/TimelineProxyModel.cpp +++ b/linphone-app/src/components/timeline/TimelineProxyModel.cpp @@ -47,12 +47,12 @@ TimelineProxyModel::TimelineProxyModel (QObject *parent) : QSortFilterProxyModel connect(model, &TimelineListModel::countChanged, this, &TimelineProxyModel::countChanged); QObject::connect(accountSettingsModel, &AccountSettingsModel::defaultAccountChanged, this, [this]() { - dynamic_cast(sourceModel())->update(); + qobject_cast(sourceModel())->update(); invalidate(); //updateCurrentSelection(); }); QObject::connect(coreManager->getSipAddressesModel(), &SipAddressesModel::sipAddressReset, this, [this]() { - dynamic_cast(sourceModel())->reset(); + qobject_cast(sourceModel())->reset(); invalidate();// Invalidate and reload GUI if the model has been reset //updateCurrentSelection(); }); @@ -63,12 +63,8 @@ TimelineProxyModel::TimelineProxyModel (QObject *parent) : QSortFilterProxyModel // ----------------------------------------------------------------------------- -int TimelineProxyModel::getCount() const{ - return dynamic_cast(sourceModel())->getCount(); -} - void TimelineProxyModel::unselectAll(){ - dynamic_cast(sourceModel())->selectAll(false); + qobject_cast(sourceModel())->selectAll(false); } void TimelineProxyModel::setFilterFlags(const int& filterFlags){ diff --git a/linphone-app/src/components/timeline/TimelineProxyModel.hpp b/linphone-app/src/components/timeline/TimelineProxyModel.hpp index 7b188c0c4..bab182b4d 100644 --- a/linphone-app/src/components/timeline/TimelineProxyModel.hpp +++ b/linphone-app/src/components/timeline/TimelineProxyModel.hpp @@ -49,10 +49,8 @@ public: Q_PROPERTY(int filterFlags MEMBER mFilterFlags WRITE setFilterFlags NOTIFY filterFlagsChanged) Q_PROPERTY(QString filterText MEMBER mFilterText WRITE setFilterText NOTIFY filterTextChanged) - Q_PROPERTY(int count READ getCount NOTIFY countChanged) + Q_PROPERTY(int count READ rowCount NOTIFY countChanged) - int getCount() const; - Q_INVOKABLE void unselectAll(); Q_INVOKABLE void setFilterFlags(const int& filterFlags); Q_INVOKABLE void setFilterText(const QString& text); diff --git a/linphone-app/src/utils/Utils.cpp b/linphone-app/src/utils/Utils.cpp index c89bc7667..0294d1b06 100644 --- a/linphone-app/src/utils/Utils.cpp +++ b/linphone-app/src/utils/Utils.cpp @@ -484,7 +484,7 @@ QString Utils::getDisplayName(const std::shared_ptr& ad std::shared_ptr cleanAddress = address->clone(); cleanAddress->clean(); QString qtAddress = Utils::coreStringToAppString(cleanAddress->asStringUriOnly()); - ContactModel * model = CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(qtAddress); + auto model = CoreManager::getInstance()->getContactsListModel()->findContactModelFromSipAddress(qtAddress); if(model && model->getVcardModel()) displayName = model->getVcardModel()->getUsername(); else{ diff --git a/linphone-app/src/utils/plugins/PluginsManager.cpp b/linphone-app/src/utils/plugins/PluginsManager.cpp index 43b513da0..49975c4f2 100644 --- a/linphone-app/src/utils/plugins/PluginsManager.cpp +++ b/linphone-app/src/utils/plugins/PluginsManager.cpp @@ -115,20 +115,22 @@ QJsonDocument PluginsManager::getJson(const QString &pluginIdentity){ } return doc; } -QList PluginsManager::getImporterModels(const QStringList &capabilities){ - QList models; + +QList> PluginsManager::getImporterModels(const QStringList &capabilities){ + QList> models; for(int i = 0 ; i < capabilities.size() ; ++i){ if( capabilities[i] == "CONTACTS") - models += CoreManager::getInstance()->getContactsImporterListModel()->getList(); + models << CoreManager::getInstance()->getContactsImporterListModel()->getSharedList(); } return models; } + void PluginsManager::openNewPlugin(const QString &pTitle){ QString fileName = QFileDialog::getOpenFileName(nullptr, pTitle); QString pluginIdentity; QStringList capabilities; - QList modelsToReset; + QList> modelsToReset; int doCopy = QMessageBox::Yes; bool cannotRemovePlugin = false; //QVersionNumber pluginVersion, apiVersion = LinphonePlugin::gPluginVersion; @@ -155,7 +157,7 @@ void PluginsManager::openNewPlugin(const QString &pTitle){ doCopy = QMessageBox::question(nullptr, pTitle, "The plugin already exists. Do you want to overwrite it?\n"+oldPlugins.join('\n'), QMessageBox::Yes, QMessageBox::No); if( doCopy == QMessageBox::Yes){ if(gPluginsMap.contains(pluginIdentity)){ - auto importers = CoreManager::getInstance()->getContactsImporterListModel()->getList(); + auto importers = CoreManager::getInstance()->getContactsImporterListModel()->getSharedList(); for(auto importer : importers){ QJsonObject pluginMetaData(importer->getDataAPI()->getPluginLoader()->metaData()); if( pluginMetaData.contains("ID") && pluginMetaData["ID"].toString() == pluginIdentity){ diff --git a/linphone-app/src/utils/plugins/PluginsManager.hpp b/linphone-app/src/utils/plugins/PluginsManager.hpp index 098d060e3..74f310606 100644 --- a/linphone-app/src/utils/plugins/PluginsManager.hpp +++ b/linphone-app/src/utils/plugins/PluginsManager.hpp @@ -6,6 +6,7 @@ #include #include +#include // ============================================================================= @@ -14,6 +15,7 @@ class PluginDataAPI; class QPluginLoader; class PluginsModel : public QObject{ +Q_OBJECT public: PluginsModel(QObject *parent = nullptr) : QObject(parent){} virtual ~PluginsModel(){} @@ -38,7 +40,7 @@ public: - QList getImporterModels(const QStringList &capabilities); + QList> getImporterModels(const QStringList &capabilities); static QMap gPluginsMap; // Map between Identity and plugin path static QString gPluginsConfigSection; // The root name of the plugin's section in configuration file }; diff --git a/linphone-app/ui/modules/Linphone/Calls/Calls.qml b/linphone-app/ui/modules/Linphone/Calls/Calls.qml index 44bce7676..37313226c 100644 --- a/linphone-app/ui/modules/Linphone/Calls/Calls.qml +++ b/linphone-app/ui/modules/Linphone/Calls/Calls.qml @@ -130,7 +130,7 @@ ListView { // ------------------------------------------------------------------------- function useColorStatus () { - return calls.currentIndex === index && $call && $call.status !== CallModel.CallStatusEnded + return calls.currentIndex === index && modelData && modelData.status !== CallModel.CallStatusEnded } // ------------------------------------------------------------------------- @@ -150,13 +150,13 @@ ListView { return params ? 'call_sign_' + params.string : '' } - entry: $call + entry: modelData width: calls.width onClicked: { - if ($call.status !== CallModel.CallStatusEnded) { - Logic.updateSelectedCall($call, index) + if (modelData.status !== CallModel.CallStatusEnded) { + Logic.updateSelectedCall(modelData, index) } } @@ -167,9 +167,9 @@ ListView { readonly property int callId: index - readonly property var call: $call + readonly property var call: modelData readonly property var callControls: _callControls - readonly property var params: Logic.getParams($call) + readonly property var params: Logic.getParams(modelData) anchors.centerIn: parent sourceComponent: params ? params.component : null @@ -177,7 +177,7 @@ ListView { SequentialAnimation on color { loops: CallsStyle.entry.endCallAnimation.loops - running: !$call || $call.status === CallModel.CallStatusEnded + running: !modelData || modelData.status === CallModel.CallStatusEnded ColorAnimation { duration: CallsStyle.entry.endCallAnimation.duration diff --git a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml index 59348f782..ab1346c99 100644 --- a/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml +++ b/linphone-app/ui/modules/Linphone/Chat/ChatCalendarMessage.qml @@ -26,6 +26,7 @@ Loader{ property int maxWidth : parent.width property int fitHeight: active && item ? item.fitHeight + ChatCalendarMessageStyle.heightMargin*2 : 0 property int fitWidth: active && item ? Math.max(item.fitWidth, maxWidth/2) + ChatCalendarMessageStyle.widthMargin*2 : 0 + property bool containsMouse: false width: parent.width height: fitHeight @@ -45,9 +46,9 @@ Loader{ clip: false - cursorShape: Qt.ArrowCursor hoverEnabled: true onClicked: CallsListModel.launchVideoCall(mainItem.conferenceInfoModel.uri, '', 0) + onHoveredChanged: mainItem.containsMouse = loadedItem.containsMouse ColumnLayout{ id: layout @@ -59,6 +60,7 @@ Loader{ Layout.fillWidth: true Layout.preferredWidth: parent.width // Need this because fillWidth is not enough... Layout.preferredHeight: ChatCalendarMessageStyle.schedule.iconSize + Layout.topMargin: 5 spacing: 10 RowLayout { id: scheduleRow @@ -93,7 +95,7 @@ Loader{ Layout.fillHeight: true Layout.minimumWidth: implicitWidth Layout.preferredWidth: implicitWidth - Layout.rightMargin: 10 + Layout.rightMargin: 15 verticalAlignment: Qt.AlignVCenter color: ChatCalendarMessageStyle.schedule.color elide: Text.ElideRight @@ -105,7 +107,6 @@ Loader{ id: title Layout.fillWidth: true Layout.minimumWidth: implicitWidth - Layout.topMargin: 10 Layout.leftMargin: 10 Layout.alignment: Qt.AlignRight color: ChatCalendarMessageStyle.subject.color @@ -118,6 +119,7 @@ Loader{ Layout.fillWidth: true Layout.fillHeight: true Layout.leftMargin: 5 + Layout.rightMargin: 15 spacing: ChatCalendarMessageStyle.participants.spacing @@ -135,6 +137,13 @@ Loader{ elide: Text.ElideRight font.pointSize: ChatCalendarMessageStyle.participants.pointSize text: mainItem.conferenceInfoModel.displayNamesToString + } + ActionButton{ + Layout.preferredHeight: iconSize + Layout.preferredWidth: height + isCustom: true + colorSet: ChatCalendarMessageStyle.gotoButton + backgroundRadius: width/2 } } } diff --git a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatCalendarMessageStyle.qml b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatCalendarMessageStyle.qml index 19ae72fad..c9bafd014 100644 --- a/linphone-app/ui/modules/Linphone/Styles/Chat/ChatCalendarMessageStyle.qml +++ b/linphone-app/ui/modules/Linphone/Styles/Chat/ChatCalendarMessageStyle.qml @@ -8,7 +8,7 @@ import ColorsList 1.0 QtObject { property string sectionName : 'ChatCalendarMessage' - property int heightMargin: 5 + property int heightMargin: 0 property int widthMargin: 5 property int minWidth: 300 @@ -39,7 +39,7 @@ QtObject { property QtObject schedule: QtObject { property int spacing: 0 - property int pointSize: Units.dp * 10 + property int pointSize: Units.dp * 9 property string icon : 'schedule_custom' property int iconSize: 30 property color color: ColorsList.add(sectionName+'_schedule', 'j').color @@ -51,15 +51,27 @@ QtObject { } property QtObject participants: QtObject { property int spacing: 5 - property int pointSize: Units.dp * 10 + property int pointSize: Units.dp * 9 property string icon : 'calendar_participants_custom' property int iconSize: 30 property color color: ColorsList.add(sectionName+'_participants', 'j').color } + property QtObject gotoButton: QtObject{ + property int iconSize: 20 + property string name : 'goto' + property string icon : 'transfer_custom' + property color backgroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_n', icon, 's_n_b_bg').color + property color backgroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_h', icon, 's_h_b_bg').color + property color backgroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_b_p', icon, 's_p_b_bg').color + property color foregroundNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_n', icon, 's_n_b_fg').color + property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_h', icon, 's_h_b_fg').color + property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_f_p', icon, 's_p_b_fg').color + } + property QtObject organizer: QtObject { property color color: ColorsList.add(sectionName+'_conference_organizer', 'j').color - property int pointSize: Units.dp * 10 + property int pointSize: Units.dp * 9 property int width: 220 } diff --git a/linphone-app/ui/views/App/Calls/CallsWindow.qml b/linphone-app/ui/views/App/Calls/CallsWindow.qml index 35d8b3080..1f9bbf0af 100644 --- a/linphone-app/ui/views/App/Calls/CallsWindow.qml +++ b/linphone-app/ui/views/App/Calls/CallsWindow.qml @@ -249,7 +249,7 @@ Window { id: middlePane anchors.fill: parent sourceComponent: Logic.getContent() - onSourceComponentChanged: {console.log(sourceComponent); rightPaned.childAItem.update()}// Force update when loading a new Content. It's just to be sure + onSourceComponentChanged: {rightPaned.childAItem.update()}// Force update when loading a new Content. It's just to be sure } childB: Loader { diff --git a/linphone-app/ui/views/App/Calls/Conference.qml b/linphone-app/ui/views/App/Calls/Conference.qml index 051b505f4..2e33c8ced 100644 --- a/linphone-app/ui/views/App/Calls/Conference.qml +++ b/linphone-app/ui/views/App/Calls/Conference.qml @@ -120,8 +120,8 @@ Rectangle { width: grid.cellWidth Column { - readonly property string sipAddress: $call.peerAddress - property var _sipAddressObserver : SipAddressesModel.getSipAddressObserver($call.peerAddress, $call.localAddress) + readonly property string sipAddress: modelData.peerAddress + property var _sipAddressObserver : SipAddressesModel.getSipAddressObserver(modelData.peerAddress, modelData.localAddress) anchors { fill: parent @@ -148,7 +148,7 @@ Rectangle { ) anchors.horizontalCenter: parent.horizontalCenter - call: $call + call: modelData onCallChanged: if(!call) conference.conferenceModel.invalidate() height: size @@ -164,7 +164,7 @@ Rectangle { height: CallStyle.header.busyIndicator.height width: CallStyle.header.busyIndicator.width - visible: $call && $call.status === CallModel.CallStatusOutgoing + visible: modelData && modelData.status === CallModel.CallStatusOutgoing } } } @@ -176,18 +176,18 @@ Rectangle { leftMargin: ConferenceStyle.grid.spacing bottomMargin: ConferenceStyle.grid.spacing } - enabled:!$call.speakerMuted + enabled:!modelData.speakerMuted Timer { interval: 50 repeat: true running: true - onTriggered: parent.value = $call.speakerVu + onTriggered: parent.value = modelData.speakerVu } } MouseArea{ anchors.fill:parent - onClicked:$call.toggleSpeakerMute() + onClicked:modelData.toggleSpeakerMute() } } } diff --git a/linphone-app/ui/views/App/Calls/VideoConference.qml b/linphone-app/ui/views/App/Calls/VideoConference.qml index a460bac2a..09c547f3b 100644 --- a/linphone-app/ui/views/App/Calls/VideoConference.qml +++ b/linphone-app/ui/views/App/Calls/VideoConference.qml @@ -152,6 +152,7 @@ Rectangle { property ParticipantDeviceProxyModel participantDevices : ParticipantDeviceProxyModel { id: participantDevices callModel: conference.callModel + showMe: true } /* property ListModel defaultList : ListModel{} @@ -201,7 +202,7 @@ Rectangle { Loader { anchors.centerIn: parent - active: avatarCell.currentDevice && (!avatarCell.currentDevice.videoEnabled || conference._fullscreen) + active: avatarCell.currentDevice && !avatarCell.currentDevice.isMe && (!avatarCell.currentDevice.videoEnabled || conference._fullscreen) sourceComponent: avatar } Loader { @@ -217,19 +218,19 @@ Rectangle { onT_fullscreenChanged: console.log("_fullscreen changed: " +t_fullscreen+ " ["+index+"]") onTCallModelChanged: console.log("CallModel changed: " +tCallModel+ " ["+index+"]") - active: !resetActive && avatarCell.currentDevice && (avatarCell.currentDevice.videoEnabled && !conference._fullscreen) + active: !resetActive //avatarCell.currentDevice && (avatarCell.currentDevice.videoEnabled && !conference._fullscreen) onActiveChanged: {console.log("Active Changed: "+active+ " ["+index+"]") if(!active && resetActive){ resetActive = false active = true } } - - sourceComponent: avatarCell.currentDevice ? - avatarCell.currentDevice.isMe ? ( true ? cameraPreview : null ) - : camera - : null - onSourceComponentChanged: console.log("SourceComponent Changed: "+sourceComponent+ " ["+index+"]") + property int cameraMode: avatarCell.currentDevice ? + avatarCell.currentDevice.isMe ? 1 + : 2 + : 0 + sourceComponent: cameraMode == 1 ? cameraPreview : cameraMode == 2 ? camera : null + onSourceComponentChanged: console.log("SourceComponent Changed: "+cameraMode+ " ["+index+"]") Component { @@ -252,7 +253,7 @@ Rectangle { Camera { anchors.fill: parent - //call: incall.call + //participantDeviceModel: avatarCell.currentDevice isPreview: true onRequestNewRenderer: {cameraLoader.resetActive = true} @@ -261,6 +262,10 @@ Rectangle { } } } + Rectangle{ + anchors.fill: parent + color: avatarCell.currentDevice.isMe ? '#09FF0000' : '#0900FF00' + } } MouseArea{ anchors.fill: parent diff --git a/linphone-app/ui/views/App/Main/Conferences.qml b/linphone-app/ui/views/App/Main/Conferences.qml index 5f12bcebc..6b2178c10 100644 --- a/linphone-app/ui/views/App/Main/Conferences.qml +++ b/linphone-app/ui/views/App/Main/Conferences.qml @@ -13,7 +13,7 @@ import App.Styles 1.0 ColumnLayout { id: container - + property int filterMode: ConferenceInfoProxyModel.ConferenceType.Scheduled spacing: 0 // --------------------------------------------------------------------------- @@ -28,7 +28,7 @@ ColumnLayout { Text{ anchors.verticalCenter: parent.center anchors.fill: parent - + verticalAlignment: Qt.AlignCenter anchors.leftMargin: 40 text: 'Mes conférences' @@ -54,6 +54,10 @@ ColumnLayout { 'PROGRAMMEES', 'INVITATIONS' ] + + onClicked: { + mainItem.filterMode = (button === 0 ? ConferenceInfoProxyModel.ConferenceType.Ended : button === 1 ?ConferenceInfoProxyModel.ConferenceType.Scheduled : ConferenceInfoProxyModel.ConferenceType.Invitations); + } } } } @@ -79,7 +83,10 @@ ColumnLayout { property: 'date' } - model: ConferenceInfoProxyModel{} + model: ConferenceInfoProxyModel{ + id: conferencesProxyModel + + } // ----------------------------------------------------------------------- // Heading. @@ -141,7 +148,7 @@ ColumnLayout { id: calendarGrid //anchors.fill: parent cellWidth: (container.width-20)/2 - cellHeight: 112 + cellHeight: 100 model: modelData height: cellHeight * ( (count+1) /2) width: container.width - 20 @@ -151,7 +158,8 @@ ColumnLayout { height: calendarGrid.cellHeight -10 radius: 6 color: ConferencesStyle.conference.backgroundColor.normal - + border.color: calendarMessage.containsMouse ? ConferencesStyle.conference.selectedBorder.color : 'transparent' + border.width: ConferencesStyle.conference.selectedBorder.width ChatCalendarMessage{ id: calendarMessage conferenceInfoModel: modelData diff --git a/linphone-app/ui/views/App/Main/ContactEdit.js b/linphone-app/ui/views/App/Main/ContactEdit.js index be4471a79..9da0f7c3f 100644 --- a/linphone-app/ui/views/App/Main/ContactEdit.js +++ b/linphone-app/ui/views/App/Main/ContactEdit.js @@ -80,7 +80,7 @@ function removeContact () { if (status) { window.unlockView() window.setView('Contacts') - Linphone.ContactsListModel.removeContact(_contact) + Linphone.ContactsListModel.remove(_contact) } }) } diff --git a/linphone-app/ui/views/App/Main/Contacts.qml b/linphone-app/ui/views/App/Main/Contacts.qml index e46c9ced9..b23f19c52 100644 --- a/linphone-app/ui/views/App/Main/Contacts.qml +++ b/linphone-app/ui/views/App/Main/Contacts.qml @@ -17,7 +17,7 @@ ColumnLayout { descriptionText: qsTr('removeContactDescription'), }, function (status) { if (status) { - ContactsListModel.removeContact(contact) + ContactsListModel.remove(contact) } }) } @@ -109,7 +109,7 @@ ColumnLayout { PresenceLevel { Layout.preferredHeight: ContactsStyle.contact.presenceLevelSize Layout.preferredWidth: ContactsStyle.contact.presenceLevelSize - level: $contact.presenceLevel + level: modelData.presenceLevel } Text { @@ -117,7 +117,7 @@ ColumnLayout { color: ContactsStyle.contact.presence.color elide: Text.ElideRight font.pointSize: ContactsStyle.contact.presence.pointSize - text: Presence.getPresenceStatusAsString($contact.presenceStatus) + text: Presence.getPresenceStatusAsString(modelData.presenceStatus) } } } @@ -189,7 +189,7 @@ ColumnLayout { verticalCenter: parent.verticalCenter } - onClicked: _removeContact($contact) + onClicked: _removeContact(modelData) } } } @@ -223,7 +223,7 @@ ColumnLayout { relativeTo: loader relativeY: loader.height - sipAddresses: $contact.vcard.sipAddresses + sipAddresses: modelData.vcard.sipAddresses onSipAddressClicked: actions.handlers[index](sipAddress) } @@ -250,7 +250,7 @@ ColumnLayout { anchors.fill: parent onClicked: window.setView('ContactEdit', { - sipAddress: $contact.vcard.sipAddresses[0] + sipAddress: modelData.vcard.sipAddresses[0] }) } @@ -269,8 +269,8 @@ ColumnLayout { Avatar { anchors.centerIn: parent - image: $contact.vcard.avatar - username: $contact.vcard.username + image: modelData.vcard.avatar + username: modelData.vcard.username height: ContactsStyle.contact.avatarSize width: ContactsStyle.contact.avatarSize @@ -289,7 +289,7 @@ ColumnLayout { pointSize: ContactsStyle.contact.username.pointSize } - text: $contact.vcard.username + text: modelData.vcard.username verticalAlignment: Text.AlignVCenter } diff --git a/linphone-app/ui/views/App/Main/MainWindow.qml b/linphone-app/ui/views/App/Main/MainWindow.qml index 580d4f4dd..ab9156cd8 100644 --- a/linphone-app/ui/views/App/Main/MainWindow.qml +++ b/linphone-app/ui/views/App/Main/MainWindow.qml @@ -308,7 +308,7 @@ ApplicationWindow { iconSize: MainWindowStyle.menu.conferences.iconSize overwriteColor: isSelected ? MainWindowStyle.menu.conferences.selectedColor : MainWindowStyle.menu.conferences.color name: 'MES CONFERENCES' - visible: SettingsModel.conferencesEnabled + visible: SettingsModel.conferenceEnabled onSelected: { timeline.model.unselectAll() diff --git a/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.js b/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.js index 3b6087e93..44e67d2a7 100644 --- a/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.js +++ b/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.js @@ -51,6 +51,7 @@ function initForm (account) { route.text = config.route conferenceUri.text = config.conferenceUri + videoConferenceUri.text = config.videoConferenceUri contactParams.text = config.contactParams avpfInterval.text = config.avpfInterval registerEnabled.checked = config.registerEnabled @@ -71,7 +72,7 @@ function initForm (account) { } function formIsValid () { - return dialog._sipAddressOk && dialog._serverAddressOk && dialog._routeOk && dialog._conferenceUriOk + return dialog._sipAddressOk && dialog._serverAddressOk && dialog._routeOk && dialog._conferenceUriOk && dialog._videoConferenceUriOk } // ----------------------------------------------------------------------------- @@ -84,6 +85,7 @@ function validAccount (account) { transport: transport.currentText, route: route.text, conferenceUri: conferenceUri.text, + videoConferenceUri: videoConferenceUri.text, contactParams: contactParams.text, avpfInterval: avpfInterval.text, registerEnabled: registerEnabled.checked, @@ -113,6 +115,10 @@ function handleConferenceUriChanged (uri) { dialog._conferenceUriOk = uri=='' || Linphone.SipAddressesModel.addressIsValid(uri) } +function handleVideoConferenceUriChanged (uri) { + dialog._videoConferenceUriOk = uri=='' || Linphone.SipAddressesModel.addressIsValid(uri) +} + function handleServerAddressChanged (address) { if (address.length === 0) { dialog._serverAddressOk = false diff --git a/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.qml b/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.qml index 6a77c56be..b1a8e51a2 100644 --- a/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.qml +++ b/linphone-app/ui/views/App/Settings/Dialogs/SettingsSipAccountsEdit.qml @@ -17,6 +17,7 @@ DialogPlus { property bool _serverAddressOk: false property bool _routeOk: true property bool _conferenceUriOk: true + property bool _videoConferenceUriOk: true buttons: [ TextButtonA { @@ -145,6 +146,22 @@ DialogPlus { } } } + FormLine { + FormGroup { + + label: 'Video Conference URI' + + TextField { + id: videoConferenceUri + //: "invalid conference URI" : Error text about conference URI + error: dialog._videoConferenceUriOk ? '' : qsTr("invalidConferenceURI") + + onTextChanged: Logic.handleVideoConferenceUriChanged(text) + Keys.onEnterPressed: nextItemInFocusChain().forceActiveFocus() + Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus() + } + } + } FormLine { FormGroup { diff --git a/linphone-app/ui/views/App/Styles/Calls/ConferenceStyle.qml b/linphone-app/ui/views/App/Styles/Calls/ConferenceStyle.qml index 698809613..4b7ab4ee1 100644 --- a/linphone-app/ui/views/App/Styles/Calls/ConferenceStyle.qml +++ b/linphone-app/ui/views/App/Styles/Calls/ConferenceStyle.qml @@ -28,4 +28,5 @@ QtObject { } } } + } diff --git a/linphone-app/ui/views/App/Styles/Calls/VideoConferenceStyle.qml b/linphone-app/ui/views/App/Styles/Calls/VideoConferenceStyle.qml index 2b353a8c5..1158542bd 100644 --- a/linphone-app/ui/views/App/Styles/Calls/VideoConferenceStyle.qml +++ b/linphone-app/ui/views/App/Styles/Calls/VideoConferenceStyle.qml @@ -373,6 +373,15 @@ QtObject { property color foregroundDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_d', icon, 'me_d_b_fg').color property color foregroundHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_h', icon, 'me_h_b_fg').color property color foregroundPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_fg_p', icon, 'me_p_b_fg').color + + property color backgroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_n', icon, 'me_n_b_inv_bg').color + property color backgroundHiddenPartDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_d', icon, 'me_d_b_inv_bg').color + property color backgroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_h', icon, 'me_h_b_inv_bg').color + property color backgroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_bg_p', icon, 'me_p_b_inv_bg').color + property color foregroundHiddenPartNormalColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_n', icon, 'me_n_b_inv_fg').color + property color foregroundHiddenPartDisabledColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_d', icon, 'me_d_b_inv_fg').color + property color foregroundHiddenPartHoveredColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_h', icon, 'me_h_b_inv_fg').color + property color foregroundHiddenPartPressedColor : ColorsList.addImageColor(sectionName+'_'+name+'_hidden_fg_p', icon, 'me_p_b_inv_fg').color } property QtObject options: QtObject { property int iconSize: 40 diff --git a/linphone-app/ui/views/App/Styles/Main/ConferencesStyle.qml b/linphone-app/ui/views/App/Styles/Main/ConferencesStyle.qml index 9adfc73ca..691ec6161 100644 --- a/linphone-app/ui/views/App/Styles/Main/ConferencesStyle.qml +++ b/linphone-app/ui/views/App/Styles/Main/ConferencesStyle.qml @@ -43,6 +43,10 @@ QtObject { property color color: ColorsList.add(sectionName+'_conference_border', 'f').color property int width: 1 } + property QtObject selectedBorder: QtObject{ + property color color: ColorsList.add(sectionName+'_conference_selected_border', 'm').color + property int width: 2 + } property QtObject indicator: QtObject { property color color: ColorsList.add(sectionName+'_conference_indicator', 'i').color