fix meeting list ui

This commit is contained in:
Gaelle Braud 2024-11-25 17:17:45 +01:00
parent 3863365863
commit 7608fbcfdb
7 changed files with 123 additions and 148 deletions

View file

@ -188,8 +188,9 @@ void ConferenceInfoCore::setSelf(QSharedPointer<ConferenceInfoCore> 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) {

View file

@ -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

View file

@ -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 <QSharedPointer>
#include <linphone++/linphone.hh>
@ -52,8 +53,8 @@ void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> me) {
mCoreModelConnection = QSharedPointer<SafeConnection<ConferenceInfoList, CoreModel>>(
new SafeConnection<ConferenceInfoList, CoreModel>(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<QSharedPointer<ConferenceInfoCore>> *items = new QList<QSharedPointer<ConferenceInfoCore>>();
mustBeInLinphoneThread(getClassName());
auto defaultAccount = CoreModel::getInstance()->getCore()->getDefaultAccount();
@ -69,27 +70,22 @@ void ConferenceInfoList::setSelf(QSharedPointer<ConferenceInfoList> 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<ConferenceInfoCore>(*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<ConferenceInfoList> 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<linphone::ConferenceInfo> &confInfo) {
auto list = getSharedList<ConferenceInfoCore>();
auto haveConf =
std::find_if(list.begin(), list.end(), [confInfo](const QSharedPointer<ConferenceInfoCore> &item) {
std::shared_ptr<linphone::Address> 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<linphone::ConferenceInfo> &confInfo) {
auto confInfoCore = ConferenceInfoCore::create(confInfo);
auto haveConf =
std::find_if(mList.begin(), mList.end(), [confInfoCore](const QSharedPointer<QObject> &item) {
auto isConfInfo = item.objectCast<ConferenceInfoCore>();
if (!isConfInfo) return false;
return isConfInfo->getUri() == confInfoCore->getUri();
});
if (haveConf == mList.end()) {
mLastConfInfoInserted = confInfoCore;
emit lUpdate();
}
});
&CoreModel::conferenceInfoCreated,
[addConference](const std::shared_ptr<linphone::ConferenceInfo> &confInfo) { addConference(confInfo); });
mCoreModelConnection->makeConnectToModel(
&CoreModel::conferenceInfoReceived,
[this](const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<const linphone::ConferenceInfo> &conferenceInfo) {
[this, addConference](const std::shared_ptr<linphone::Core> &core,
const std::shared_ptr<const linphone::ConferenceInfo> &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<ConferenceInfoCore>();
if (model && model->getDateTimeUtc().date() == today) {
setHaveCurrentDate(true);
return;
}
}
setHaveCurrentDate(false);
auto today = QDate::currentDate();
auto confInfoList = getSharedList<ConferenceInfoCore>();
auto haveCurrent =
std::find_if(confInfoList.begin(), confInfoList.end(), [today](const QSharedPointer<ConferenceInfoCore> &item) {
return item && item->getDateTimeUtc().date() == today;
});
setHaveCurrentDate(haveCurrent != confInfoList.end());
}
void ConferenceInfoList::updateHaveCurrentDate(QSharedPointer<ConferenceInfoCore> 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<QObject> &item) {
auto isConfInfo = item.objectCast<ConferenceInfoCore>();
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<ConferenceInfoCore>();
auto it = std::find(confInfoList.begin(), confInfoList.end(), nullptr);
return it == confInfoList.end() ? -1 : std::distance(confInfoList.begin(), it);
}
QSharedPointer<ConferenceInfoCore>
ConferenceInfoList::build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo) const {
ConferenceInfoList::build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo) {
auto me = CoreModel::getInstance()->getCore()->getDefaultAccount()->getParams()->getIdentityAddress();
std::list<std::shared_ptr<linphone::ParticipantInfo>> participants = conferenceInfo->getParticipantInfos();
bool haveMe = conferenceInfo->getOrganizer()->weakEqual(me);
@ -193,12 +178,18 @@ ConferenceInfoList::build(const std::shared_ptr<linphone::ConferenceInfo> &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<ConferenceInfoCore> confInfoCore) {
connect(confInfoCore.get(), &ConferenceInfoCore::removed, this, [this](ConferenceInfoCore *confInfo) {
remove(confInfo);
updateHaveCurrentDate();
});
}
QHash<int, QByteArray> ConferenceInfoList::roleNames() const {
QHash<int, QByteArray> roles;
roles[Qt::DisplayRole] = "$modelData";
@ -224,20 +215,4 @@ QVariant ConferenceInfoList::data(const QModelIndex &index, int role) const {
}
}
return QVariant();
}
int ConferenceInfoList::sort(QList<QSharedPointer<ConferenceInfoCore>> &listToSort) {
auto nowDate = QDateTime(QDate::currentDate(), QTime(0, 0, 0)).toUTC().date();
std::sort(listToSort.begin(), listToSort.end(),
[nowDate](const QSharedPointer<QObject> &a, const QSharedPointer<QObject> &b) {
auto l = a.objectCast<ConferenceInfoCore>();
auto r = b.objectCast<ConferenceInfoCore>();
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();
}
}

View file

@ -42,34 +42,30 @@ public:
bool haveCurrentDate() const;
void setHaveCurrentDate(bool have);
void updateHaveCurrentDate();
void updateHaveCurrentDate(QSharedPointer<ConferenceInfoCore> itemToCompare);
int getCurrentDateIndex() const;
void setCurrentDateIndex(int index);
int getCurrentDateIndex();
int findConfInfoIndexByUri(const QString &uri);
QSharedPointer<ConferenceInfoCore> build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo) const;
QSharedPointer<ConferenceInfoCore> build(const std::shared_ptr<linphone::ConferenceInfo> &conferenceInfo);
void connectItem(QSharedPointer<ConferenceInfoCore> confInfoCore);
QHash<int, QByteArray> roleNames() const override;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
static int sort(QList<QSharedPointer<ConferenceInfoCore>> &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<SafeConnection<ConferenceInfoList, CoreModel>> mCoreModelConnection;
std::shared_ptr<CoreModel> mCoreModel;
QSharedPointer<ConferenceInfoCore> mLastConfInfoInserted;
QSharedPointer<AccountCore> mCurrentAccountCore;
bool mHaveCurrentDate = false;
int mCurrentDateIndex = -1;
DECLARE_ABSTRACT_OBJECT
};
#endif // CONFERENCE_INFO_LIST_H_

View file

@ -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<SortFilterList *>(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<SortFilterList *>(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<ConferenceInfoList *>(sourceModel());
auto ciCore = list->getAt<ConferenceInfoCore>(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<SortFilterList *>(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<ConferenceInfoList, ConferenceInfoCore>(sourceLeft.row());
auto r = getItemAtSource<ConferenceInfoList, ConferenceInfoCore>(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();
}
}

View file

@ -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<ConferenceInfoList> mList;

View file

@ -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