From 7608fbcfdbb4e97b9124b82bfbfb1fb263db9ca4 Mon Sep 17 00:00:00 2001 From: Gaelle Braud Date: Mon, 25 Nov 2024 17:17:45 +0100 Subject: [PATCH] fix meeting list ui --- .../core/conference/ConferenceInfoCore.cpp | 5 +- .../core/conference/ConferenceInfoCore.hpp | 2 +- .../core/conference/ConferenceInfoList.cpp | 149 ++++++++---------- .../core/conference/ConferenceInfoList.hpp | 18 +-- .../core/conference/ConferenceInfoProxy.cpp | 57 ++++--- .../core/conference/ConferenceInfoProxy.hpp | 8 +- .../Display/Meeting/MeetingListView.qml | 32 ++-- 7 files changed, 123 insertions(+), 148 deletions(-) diff --git a/Linphone/core/conference/ConferenceInfoCore.cpp b/Linphone/core/conference/ConferenceInfoCore.cpp index 21d856889..e3f815a03 100644 --- a/Linphone/core/conference/ConferenceInfoCore.cpp +++ b/Linphone/core/conference/ConferenceInfoCore.cpp @@ -188,8 +188,9 @@ void ConferenceInfoCore::setSelf(QSharedPointer me) { mConfInfoModelConnection->makeConnectToCore(&ConferenceInfoCore::lDeleteConferenceInfo, [this]() { mConfInfoModelConnection->invokeToModel([this] { mConferenceInfoModel->deleteConferenceInfo(); }); }); - mConfInfoModelConnection->makeConnectToModel(&ConferenceInfoModel::conferenceInfoDeleted, - &ConferenceInfoCore::removed); + mConfInfoModelConnection->makeConnectToModel(&ConferenceInfoModel::conferenceInfoDeleted, [this] { + mConfInfoModelConnection->invokeToCore([this] { removed(this); }); + }); mConfInfoModelConnection->makeConnectToModel( &ConferenceInfoModel::schedulerStateChanged, [this](linphone::ConferenceScheduler::State state) { diff --git a/Linphone/core/conference/ConferenceInfoCore.hpp b/Linphone/core/conference/ConferenceInfoCore.hpp index 587511a14..358010cb3 100644 --- a/Linphone/core/conference/ConferenceInfoCore.hpp +++ b/Linphone/core/conference/ConferenceInfoCore.hpp @@ -153,7 +153,7 @@ signals: void saveFailed(); void invitationsSent(); - void removed(); + void removed(ConferenceInfoCore* confInfo); void lCancelConferenceInfo(); void lDeleteConferenceInfo(); // Remove completly this conference info from DB diff --git a/Linphone/core/conference/ConferenceInfoList.cpp b/Linphone/core/conference/ConferenceInfoList.cpp index fd32b17f6..a2adcd7f0 100644 --- a/Linphone/core/conference/ConferenceInfoList.cpp +++ b/Linphone/core/conference/ConferenceInfoList.cpp @@ -23,6 +23,7 @@ #include "ConferenceInfoGui.hpp" #include "core/App.hpp" #include "model/object/VariantObject.hpp" +#include "model/tool/ToolModel.hpp" #include "tool/Utils.hpp" #include #include @@ -52,8 +53,8 @@ void ConferenceInfoList::setSelf(QSharedPointer me) { mCoreModelConnection = QSharedPointer>( new SafeConnection(me, CoreModel::getInstance()), &QObject::deleteLater); - mCoreModelConnection->makeConnectToCore(&ConferenceInfoList::lUpdate, [this]() { - mCoreModelConnection->invokeToModel([this]() { + mCoreModelConnection->makeConnectToCore(&ConferenceInfoList::lUpdate, [this](bool isInitialization) { + mCoreModelConnection->invokeToModel([this, isInitialization]() { QList> *items = new QList>(); mustBeInLinphoneThread(getClassName()); auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount(); @@ -69,27 +70,22 @@ void ConferenceInfoList::setSelf(QSharedPointer me) { auto confInfoCore = build(conferenceInfo); // Cancelled conference organized ourself me must be hidden if (confInfoCore) { - qDebug() << log().arg("Add conf") << confInfoCore->getSubject() << "with state" - << confInfoCore->getConferenceInfoState(); + // qDebug() << log().arg("Add conf") << confInfoCore->getSubject() << "with state" + // << confInfoCore->getConferenceInfoState(); items->push_back(confInfoCore); } } - mCoreModelConnection->invokeToCore([this, items]() { + mCoreModelConnection->invokeToCore([this, items, isInitialization]() { mustBeInMainThread(getClassName()); - int currentDateIndex = sort(*items); - auto itemAfterDummy = currentDateIndex < items->size() - 1 ? items->at(currentDateIndex + 1) : nullptr; - updateHaveCurrentDate(itemAfterDummy); + for (auto &item : *items) { + connectItem(item); + } resetData(*items); - if (mLastConfInfoInserted) { - int index = -1; - // TODO : uncomment when linphone conference scheduler updated - // and model returns the scheduler conferenceInfo uri - index = findConfInfoIndexByUri(mLastConfInfoInserted->getUri()); - if (index != -1) setCurrentDateIndex(index); - else setCurrentDateIndex(mHaveCurrentDate ? currentDateIndex : currentDateIndex + 1); - mLastConfInfoInserted = nullptr; - } else setCurrentDateIndex(mHaveCurrentDate ? currentDateIndex : currentDateIndex + 1); + updateHaveCurrentDate(); delete items; + if (isInitialization) { + emit initialized(); + } }); }); }); @@ -104,35 +100,43 @@ void ConferenceInfoList::setSelf(QSharedPointer me) { if (defaultAccount) { mCurrentAccountCore = AccountCore::create(defaultAccount); connect(mCurrentAccountCore.get(), &AccountCore::registrationStateChanged, this, - &ConferenceInfoList::lUpdate); + [this] { emit lUpdate(); }); } }); }; mCoreModelConnection->makeConnectToModel(&CoreModel::defaultAccountChanged, connectModel); connectModel(); + auto addConference = [this](const std::shared_ptr &confInfo) { + auto list = getSharedList(); + auto haveConf = + std::find_if(list.begin(), list.end(), [confInfo](const QSharedPointer &item) { + std::shared_ptr confAddr = nullptr; + if (item) ToolModel::interpretUrl(item->getUri()); + return confInfo->getUri()->weakEqual(confAddr); + }); + if (haveConf == list.end()) { + auto confInfoCore = build(confInfo); + mCoreModelConnection->invokeToCore([this, confInfoCore] { + add(confInfoCore); + connectItem(confInfoCore); + updateHaveCurrentDate(); + emit confInfoInserted(getCount() - 1, new ConferenceInfoGui(confInfoCore)); + }); + } + }; + mCoreModelConnection->makeConnectToModel( - &CoreModel::conferenceInfoCreated, [this](const std::shared_ptr &confInfo) { - auto confInfoCore = ConferenceInfoCore::create(confInfo); - auto haveConf = - std::find_if(mList.begin(), mList.end(), [confInfoCore](const QSharedPointer &item) { - auto isConfInfo = item.objectCast(); - if (!isConfInfo) return false; - return isConfInfo->getUri() == confInfoCore->getUri(); - }); - if (haveConf == mList.end()) { - mLastConfInfoInserted = confInfoCore; - emit lUpdate(); - } - }); + &CoreModel::conferenceInfoCreated, + [addConference](const std::shared_ptr &confInfo) { addConference(confInfo); }); mCoreModelConnection->makeConnectToModel( &CoreModel::conferenceInfoReceived, - [this](const std::shared_ptr &core, - const std::shared_ptr &conferenceInfo) { + [this, addConference](const std::shared_ptr &core, + const std::shared_ptr &conferenceInfo) { lDebug() << log().arg("conference info received") << conferenceInfo->getSubject(); - emit lUpdate(); + addConference(conferenceInfo->clone()); }); - emit lUpdate(); + emit lUpdate(true); } bool ConferenceInfoList::haveCurrentDate() const { @@ -147,43 +151,24 @@ void ConferenceInfoList::setHaveCurrentDate(bool have) { } void ConferenceInfoList::updateHaveCurrentDate() { - auto today = QDateTime::currentDateTimeUtc().date(); - for (auto item : mList) { - auto model = item.objectCast(); - if (model && model->getDateTimeUtc().date() == today) { - setHaveCurrentDate(true); - return; - } - } - setHaveCurrentDate(false); + auto today = QDate::currentDate(); + auto confInfoList = getSharedList(); + auto haveCurrent = + std::find_if(confInfoList.begin(), confInfoList.end(), [today](const QSharedPointer &item) { + return item && item->getDateTimeUtc().date() == today; + }); + setHaveCurrentDate(haveCurrent != confInfoList.end()); } -void ConferenceInfoList::updateHaveCurrentDate(QSharedPointer itemToCompare) { - setHaveCurrentDate(itemToCompare && - itemToCompare->getDateTimeUtc().date() == QDateTime::currentDateTimeUtc().date()); -} - -int ConferenceInfoList::getCurrentDateIndex() const { - return mCurrentDateIndex; -} - -void ConferenceInfoList::setCurrentDateIndex(int index) { - mCurrentDateIndex = index; - emit currentDateIndexChanged(index); -} - -int ConferenceInfoList::findConfInfoIndexByUri(const QString &uri) { - auto confInList = std::find_if(mList.begin(), mList.end(), [uri](const QSharedPointer &item) { - auto isConfInfo = item.objectCast(); - if (!isConfInfo) return false; - return isConfInfo->getUri() == uri; - }); - - return (confInList == mList.end() ? -1 : std::distance(mList.begin(), confInList)); +int ConferenceInfoList::getCurrentDateIndex() { + // Dummy item (nullptr) is QDate::currentDate() + auto confInfoList = getSharedList(); + auto it = std::find(confInfoList.begin(), confInfoList.end(), nullptr); + return it == confInfoList.end() ? -1 : std::distance(confInfoList.begin(), it); } QSharedPointer -ConferenceInfoList::build(const std::shared_ptr &conferenceInfo) const { +ConferenceInfoList::build(const std::shared_ptr &conferenceInfo) { auto me = CoreModel::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress(); std::list> participants = conferenceInfo->getParticipantInfos(); bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me); @@ -193,12 +178,18 @@ ConferenceInfoList::build(const std::shared_ptr &confe return me->weakEqual(p->getAddress()); }) != participants.end()); if (haveMe) { - auto conferenceModel = ConferenceInfoCore::create(conferenceInfo); - connect(conferenceModel.get(), &ConferenceInfoCore::removed, this, &ConferenceInfoList::lUpdate); - return conferenceModel; + auto confInfoCore = ConferenceInfoCore::create(conferenceInfo); + return confInfoCore; } else return nullptr; } +void ConferenceInfoList::connectItem(QSharedPointer confInfoCore) { + connect(confInfoCore.get(), &ConferenceInfoCore::removed, this, [this](ConferenceInfoCore *confInfo) { + remove(confInfo); + updateHaveCurrentDate(); + }); +} + QHash ConferenceInfoList::roleNames() const { QHash roles; roles[Qt::DisplayRole] = "$modelData"; @@ -224,20 +215,4 @@ QVariant ConferenceInfoList::data(const QModelIndex &index, int role) const { } } return QVariant(); -} - -int ConferenceInfoList::sort(QList> &listToSort) { - auto nowDate = QDateTime(QDate::currentDate(), QTime(0, 0, 0)).toUTC().date(); - std::sort(listToSort.begin(), listToSort.end(), - [nowDate](const QSharedPointer &a, const QSharedPointer &b) { - auto l = a.objectCast(); - auto r = b.objectCast(); - if (!l || !r) { // sort on date - return !l ? nowDate <= r->getDateTimeUtc().date() : l->getDateTimeUtc().date() < nowDate; - } else { - return l->getDateTimeUtc() < r->getDateTimeUtc(); - } - }); - auto it = std::find(listToSort.begin(), listToSort.end(), nullptr); - return it == listToSort.end() ? -1 : it - listToSort.begin(); -} +} \ No newline at end of file diff --git a/Linphone/core/conference/ConferenceInfoList.hpp b/Linphone/core/conference/ConferenceInfoList.hpp index 252f60ecf..723fc4474 100644 --- a/Linphone/core/conference/ConferenceInfoList.hpp +++ b/Linphone/core/conference/ConferenceInfoList.hpp @@ -42,34 +42,30 @@ public: bool haveCurrentDate() const; void setHaveCurrentDate(bool have); + void updateHaveCurrentDate(); - void updateHaveCurrentDate(QSharedPointer itemToCompare); - int getCurrentDateIndex() const; - void setCurrentDateIndex(int index); + int getCurrentDateIndex(); - int findConfInfoIndexByUri(const QString &uri); - - QSharedPointer build(const std::shared_ptr &conferenceInfo) const; + QSharedPointer build(const std::shared_ptr &conferenceInfo); + void connectItem(QSharedPointer confInfoCore); QHash roleNames() const override; virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - static int sort(QList> &listToSort); // return the index of null item. signals: - void lUpdate(); + void lUpdate(bool isInitialization = false); + void initialized(); void addCurrentDateChanged(); void haveCurrentDateChanged(); void currentDateIndexChanged(int index); + void confInfoInserted(int index, ConferenceInfoGui *data); private: QSharedPointer> mCoreModelConnection; - std::shared_ptr mCoreModel; - QSharedPointer mLastConfInfoInserted; QSharedPointer mCurrentAccountCore; bool mHaveCurrentDate = false; - int mCurrentDateIndex = -1; DECLARE_ABSTRACT_OBJECT }; #endif // CONFERENCE_INFO_LIST_H_ diff --git a/Linphone/core/conference/ConferenceInfoProxy.cpp b/Linphone/core/conference/ConferenceInfoProxy.cpp index c5f080096..4aaa64e50 100644 --- a/Linphone/core/conference/ConferenceInfoProxy.cpp +++ b/Linphone/core/conference/ConferenceInfoProxy.cpp @@ -27,21 +27,26 @@ DEFINE_ABSTRACT_OBJECT(ConferenceInfoProxy) ConferenceInfoProxy::ConferenceInfoProxy(QObject *parent) : LimitProxy(parent) { mList = ConferenceInfoList::create(); - setSourceModels(new SortFilterList(mList.get())); - connect( - this, &ConferenceInfoProxy::filterTextChanged, this, [this] { updateCurrentDateIndex(); }, - Qt::QueuedConnection); + setSourceModels(new SortFilterList(mList.get(), Qt::AscendingOrder)); connect( mList.get(), &ConferenceInfoList::haveCurrentDateChanged, this, [this] { - invalidate(); - updateCurrentDateIndex(); + auto sortModel = dynamic_cast(sourceModel()); + sortModel->invalidate(); }, Qt::QueuedConnection); - connect(mList.get(), &ConferenceInfoList::haveCurrentDateChanged, this, - &ConferenceInfoProxy::haveCurrentDateChanged, Qt::QueuedConnection); - connect(mList.get(), &ConferenceInfoList::currentDateIndexChanged, this, - &ConferenceInfoProxy::updateCurrentDateIndex, Qt::QueuedConnection); + connect( + mList.get(), &ConferenceInfoList::confInfoInserted, this, + [this](int index, ConferenceInfoGui *data) { + auto sortModel = dynamic_cast(sourceModel()); + if (sortModel) { + auto proxyIndex = sortModel->mapFromSource(mList->index(index, 0)).row(); + if (proxyIndex >= getMaxDisplayItems()) setMaxDisplayItems(proxyIndex + 1); + emit conferenceInfoCreated(proxyIndex); + } + }, + Qt::QueuedConnection); + connect(mList.get(), &ConferenceInfoList::initialized, this, &ConferenceInfoProxy::initialized); } ConferenceInfoProxy::~ConferenceInfoProxy() { @@ -51,16 +56,6 @@ bool ConferenceInfoProxy::haveCurrentDate() const { return mList->haveCurrentDate(); } -int ConferenceInfoProxy::getCurrentDateIndex() const { - return mCurrentDateIndex; -} - -void ConferenceInfoProxy::updateCurrentDateIndex() { - int newIndex = mapFromSource(sourceModel()->index(mList->getCurrentDateIndex(), 0)).row(); - mCurrentDateIndex = newIndex; - emit currentDateIndexChanged(newIndex); -} - bool ConferenceInfoProxy::SortFilterList::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const { auto list = qobject_cast(sourceModel()); auto ciCore = list->getAt(sourceRow); @@ -84,12 +79,30 @@ bool ConferenceInfoProxy::SortFilterList::filterAcceptsRow(int sourceRow, const return res; } else return mFilterType == -1; } else { - return !list->haveCurrentDate() && list->getCount() > 1 && mFilterText.isEmpty(); // if mlist count == 1 there is only the dummy row which we don't display alone + return !list->haveCurrentDate() && list->getCount() > 1 && mFilterText.isEmpty(); } } +int ConferenceInfoProxy::getCurrentDateIndex() const { + auto sortModel = dynamic_cast(sourceModel()); + auto modelIndex = mList->getCurrentDateIndex(); + auto proxyIndex = sortModel->mapFromSource(mList->index(modelIndex, 0)).row(); + return proxyIndex; +} + bool ConferenceInfoProxy::SortFilterList::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const { - return true; // Not used + auto l = getItemAtSource(sourceLeft.row()); + auto r = getItemAtSource(sourceRight.row()); + if (!l && !r) { + return true; + } + auto nowDate = QDate::currentDate(); + if (!l || !r) { // sort on date + auto rdate = r ? r->getDateTimeUtc().date() : QDate::currentDate(); + return !l ? nowDate <= r->getDateTimeUtc().date() : l->getDateTimeUtc().date() < nowDate; + } else { + return l->getDateTimeUtc() < r->getDateTimeUtc(); + } } diff --git a/Linphone/core/conference/ConferenceInfoProxy.hpp b/Linphone/core/conference/ConferenceInfoProxy.hpp index 95117db9a..fd2fee965 100644 --- a/Linphone/core/conference/ConferenceInfoProxy.hpp +++ b/Linphone/core/conference/ConferenceInfoProxy.hpp @@ -30,7 +30,7 @@ class ConferenceInfoProxy : public LimitProxy, public AbstractObject { Q_OBJECT Q_PROPERTY(bool haveCurrentDate READ haveCurrentDate NOTIFY haveCurrentDateChanged) - Q_PROPERTY(int currentDateIndex READ getCurrentDateIndex NOTIFY currentDateIndexChanged) + // Q_PROPERTY(int currentDateIndex READ getCurrentDateIndex NOTIFY currentDateIndexChanged) public: enum ConferenceInfoFiltering { None = 0, Future = 1 }; @@ -43,12 +43,12 @@ public: bool haveCurrentDate() const; - int getCurrentDateIndex() const; - void updateCurrentDateIndex(); + Q_INVOKABLE int getCurrentDateIndex() const; signals: void haveCurrentDateChanged(); - void currentDateIndexChanged(int index); + void conferenceInfoCreated(int index); + void initialized(); private: QSharedPointer mList; diff --git a/Linphone/view/Control/Display/Meeting/MeetingListView.qml b/Linphone/view/Control/Display/Meeting/MeetingListView.qml index bda2680cb..bdac36929 100644 --- a/Linphone/view/Control/Display/Meeting/MeetingListView.qml +++ b/Linphone/view/Control/Display/Meeting/MeetingListView.qml @@ -17,34 +17,16 @@ ListView { property ConferenceInfoGui selectedConference: model && currentIndex != -1 ? model.getAt(currentIndex) : null spacing: 8 * DefaultStyle.dp - currentIndex: confInfoProxy.currentDateIndex - // using highlight doesn't center, take time before moving and don't work for not visible item (like not loaded) - highlightFollowsCurrentItem: false + highlightFollowsCurrentItem: true + highlightMoveVelocity: 1500 onCountChanged: { selectedConference = model && currentIndex != -1 && currentIndex < model.count ? model.getAt(currentIndex) : null } - Connections { - target: confInfoProxy - function onCurrentDateIndexChanged(index) { - mainItem.currentIndex = index - } - } onCurrentIndexChanged: { selectedConference = model.getAt(currentIndex) || null - if (currentIndex != -1) positionViewAtIndex(currentIndex, ListView.Contain) - } - onVisibleChanged: if( visible) { - mainItem.positionViewAtIndex(currentIndex, ListView.Center)// First approximative move - delayMove.restart() // Move to exact position after load. } onAtYEndChanged: if(atYEnd) confInfoProxy.displayMore() - - Timer{ - id: delayMove - interval: 60 - onTriggered: mainItem.positionViewAtIndex(currentIndex, ListView.Center) - } model: ConferenceInfoProxy { id: confInfoProxy @@ -52,6 +34,14 @@ ListView { filterType: ConferenceInfoProxy.None initialDisplayItems: mainItem.height / (63 * DefaultStyle.dp) + 5 displayItemsStep: initialDisplayItems/2 + onConferenceInfoCreated: (index) => { + mainItem.currentIndex = index + } + onInitialized: { + var initIndex = confInfoProxy.getCurrentDateIndex() + if (initIndex >= maxDisplayItems) maxDisplayItems = initIndex + 1 + mainItem.currentIndex = initIndex + } } section { @@ -85,7 +75,7 @@ ListView { property int topOffset: (dateDay.visible && !isFirst? 8 * DefaultStyle.dp : 0) property var endDateTime: $modelData ? $modelData.core.endDateTime : UtilsCpp.getCurrentDateTime() property var haveModel: !!$modelData && $modelData != undefined && $modelData.core.haveModel || false - property bool isCanceled: $modelData.core.state === LinphoneEnums.ConferenceInfoState.Cancelled + property bool isCanceled: $modelData?.core.state === LinphoneEnums.ConferenceInfoState.Cancelled || false Component.onCompleted: if (!isFirst && dateDay.visible) { height = (63+topOffset)*DefaultStyle.dp delegateIn.anchors.topMargin = topOffset