Commit 5d268f44 authored by Claudio Cambra's avatar Claudio Cambra
Browse files

More granularly update multidayincidencemodel when new rows inserted into incidenceoccurrencemodel



Signed-off-by: Claudio Cambra's avatarClaudio Cambra <claudio.cambra@gmail.com>
parent fd0e36c9
......@@ -87,7 +87,7 @@ void IncidenceOccurrenceModel::updateQuery()
mEnd = mStart.addDays(mLength);
QObject::connect(m_coreCalendar->model(), &QAbstractItemModel::dataChanged, this, &IncidenceOccurrenceModel::slotSourceDataChanged);
QObject::connect(m_coreCalendar->model(), &QAbstractItemModel::rowsInserted, this, &IncidenceOccurrenceModel::refreshView);
QObject::connect(m_coreCalendar->model(), &QAbstractItemModel::rowsInserted, this, &IncidenceOccurrenceModel::slotSourceRowsInserted);
QObject::connect(m_coreCalendar->model(), &QAbstractItemModel::rowsRemoved, this, &IncidenceOccurrenceModel::refreshView);
QObject::connect(m_coreCalendar->model(), &QAbstractItemModel::modelReset, this, &IncidenceOccurrenceModel::refreshView);
QObject::connect(m_coreCalendar.get(), &Akonadi::ETMCalendar::collectionsRemoved, this, &IncidenceOccurrenceModel::refreshView);
......@@ -174,7 +174,7 @@ void IncidenceOccurrenceModel::slotSourceDataChanged(const QModelIndex &upperLef
const auto endRow = bottomRight.row();
for (int i = startRow; i <= endRow; ++i) {
const auto sourceModelIndex = m_coreCalendar->model()->index(i, 0);
const auto sourceModelIndex = m_coreCalendar->model()->index(i, 0, upperLeft.parent());
const auto incidenceItem = sourceModelIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
if(!incidenceItem.isValid() || !incidenceItem.hasPayload<KCalendarCore::Incidence::Ptr>()) {
......@@ -214,6 +214,63 @@ void IncidenceOccurrenceModel::slotSourceDataChanged(const QModelIndex &upperLef
}
}
void IncidenceOccurrenceModel::slotSourceRowsInserted(const QModelIndex &parent, const int first, const int last)
{
if (!m_coreCalendar) {
return;
}
for (int i = first; i <= last; ++i) {
const auto sourceModelIndex = m_coreCalendar->model()->index(i, 0, parent);
const auto incidenceItem = sourceModelIndex.data(Akonadi::EntityTreeModel::ItemRole).value<Akonadi::Item>();
if(!incidenceItem.isValid() || !incidenceItem.hasPayload<KCalendarCore::Incidence::Ptr>()) {
continue;
}
const auto incidence = incidenceItem.payload<KCalendarCore::Incidence::Ptr>();
if(!incidencePassesFilter(incidence)) {
continue;
}
KCalendarCore::OccurrenceIterator occurrenceIterator{*m_coreCalendar, incidence, QDateTime{mStart, {0, 0, 0}}, QDateTime{mEnd, {12, 59, 59}}};
while (occurrenceIterator.hasNext()) {
occurrenceIterator.next();
const auto occurrenceStartEnd = incidenceOccurrenceStartEnd(occurrenceIterator.occurrenceStartDate(), incidence);
const auto start = occurrenceStartEnd.first;
const auto end = occurrenceStartEnd.second;
const auto occurrenceHashKey = incidenceOccurrenceHash(start, end, incidence->uid());
if(m_occurrenceIndexHash.contains(occurrenceHashKey)) {
continue;
}
const Occurrence occurrence{
start,
end,
incidence,
getColor(incidence),
getCollectionId(incidence),
incidence->allDay(),
};
const auto indexRow = m_incidences.count();
beginInsertRows({}, indexRow, indexRow);
m_incidences.append(occurrence);
endInsertRows();
const auto occurrenceIndex = index(indexRow);
const QPersistentModelIndex persistentIndex(occurrenceIndex);
m_occurrenceIndexHash.insert(occurrenceHashKey, persistentIndex);
}
}
}
int IncidenceOccurrenceModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid()) {
......
......@@ -108,6 +108,7 @@ Q_SIGNALS:
private Q_SLOTS:
void slotSourceDataChanged(const QModelIndex &upperLeft, const QModelIndex &bottomRight);
void slotSourceRowsInserted(const QModelIndex &parent, const int first, const int last);
void refreshView();
void updateFromSource();
......
......@@ -16,11 +16,12 @@ MultiDayIncidenceModel::MultiDayIncidenceModel(QObject *parent)
mRefreshTimer.setInterval(100);
mRefreshTimer.callOnTimeout(this, &MultiDayIncidenceModel::resetLayoutLines);
m_updateLinesTimer.setSingleShot(true);
m_updateLinesTimer.setInterval(100);
m_updateLinesTimer.callOnTimeout(this, &MultiDayIncidenceModel::updateScheduledLayoutLines);
m_config = KalendarConfig::self();
QObject::connect(m_config, &KalendarConfig::showSubtodosInCalendarViewsChanged, this, [&]() {
beginResetModel();
endResetModel();
});
connect(m_config, &KalendarConfig::showSubtodosInCalendarViewsChanged, this, &MultiDayIncidenceModel::resetLayoutLines);
}
int MultiDayIncidenceModel::rowCount(const QModelIndex &parent) const
......@@ -221,6 +222,13 @@ QVariantList MultiDayIncidenceModel::layoutLines(const QDate &rowStart) const
void MultiDayIncidenceModel::resetLayoutLines()
{
if(mSourceModel->calendar()->isLoading()) {
if(!mRefreshTimer.isActive()) {
mRefreshTimer.start(100);
}
return;
}
beginResetModel();
m_laidOutLines.clear();
......@@ -228,15 +236,12 @@ void MultiDayIncidenceModel::resetLayoutLines()
const auto numPeriods = rowCount({});
m_laidOutLines.reserve(numPeriods);
qDebug() << numPeriods;
for(int i = 0; i < numPeriods; ++i) {
const auto periodStart = mSourceModel->start().addDays(i * mPeriodLength);
const auto periodIncidenceLayout = layoutLines(periodStart);
m_laidOutLines.append(periodIncidenceLayout);
}
Q_EMIT incidenceCountChanged();
endResetModel();
}
......@@ -283,9 +288,9 @@ void MultiDayIncidenceModel::setModel(IncidenceOccurrenceModel *model)
QObject::connect(model, &QAbstractItemModel::dataChanged, this, &MultiDayIncidenceModel::slotSourceDataChanged);
QObject::connect(model, &QAbstractItemModel::layoutChanged, this, resetModel);
QObject::connect(model, &QAbstractItemModel::modelReset, this, resetModel);
QObject::connect(model, &QAbstractItemModel::rowsInserted, this, resetModel);
QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &MultiDayIncidenceModel::scheduleLayoutLinesUpdates);
QObject::connect(model, &QAbstractItemModel::rowsMoved, this, resetModel);
QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, resetModel);
QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &MultiDayIncidenceModel::scheduleLayoutLinesUpdates);
mRefreshTimer.start(100);
}
......@@ -299,8 +304,33 @@ void MultiDayIncidenceModel::slotSourceDataChanged(const QModelIndex &upperLeft,
const auto startRow = upperLeft.row();
const auto endRow = bottomRight.row();
for (int i = startRow; i <= endRow; ++i) {
const auto sourceModelIndex = mSourceModel->index(i);
scheduleLayoutLinesUpdates(upperLeft.parent(), startRow, endRow);
}
void MultiDayIncidenceModel::scheduleLayoutLinesUpdates(const QModelIndex &sourceIndexParent, const int sourceFirstRow, const int sourceLastRow)
{
if (!mSourceModel) {
return;
}
// If we have no existing laid out lines it means we have not done an
// initial setup. Go do that, which will provide incidences anyway
if (m_laidOutLines.empty()) {
resetLayoutLines();
return;
}
// Don't bother if we are going for a full reset soon
if (mRefreshTimer.isActive()) {
return;
}
for (int i = sourceFirstRow; i <= sourceLastRow; ++i) {
if(m_linesToUpdate.count() == m_laidOutLines.count()) {
break;
}
const auto sourceModelIndex = mSourceModel->index(i, 0, sourceIndexParent);
const auto occurrence = sourceModelIndex.data(IncidenceOccurrenceModel::IncidenceOccurrence).value<IncidenceOccurrenceModel::Occurrence>();
const auto sourceModelStartDate = mSourceModel->start();
......@@ -310,20 +340,37 @@ void MultiDayIncidenceModel::slotSourceDataChanged(const QModelIndex &upperLeft,
const auto firstPeriodOccurrenceAppears = startDaysFromSourceStart / mPeriodLength;
const auto lastPeriodOccurrenceAppears = endDaysFromSourceStart / mPeriodLength;
qDebug() << occurrence.incidence->summary() << firstPeriodOccurrenceAppears << lastPeriodOccurrenceAppears;
if(firstPeriodOccurrenceAppears > m_laidOutLines.count() || lastPeriodOccurrenceAppears < 0) {
continue;
}
for (int i = firstPeriodOccurrenceAppears; i <= lastPeriodOccurrenceAppears; ++i) {
const auto periodStart = mSourceModel->start().addDays(i * mPeriodLength);
const auto idx = index(i, 0);
const auto lastRow = m_laidOutLines.count() - 1;
const auto minRow = qMin(qMax(static_cast<int>(firstPeriodOccurrenceAppears), 0), lastRow);
const auto maxRow = qMin(static_cast<int>(lastPeriodOccurrenceAppears), lastRow);
m_laidOutLines.replace(i, layoutLines(periodStart));
Q_EMIT dataChanged(idx, idx);
}
// We set the layout lines scheduled to redo
m_linesToUpdate.insert(minRow);
m_linesToUpdate.insert(maxRow);
}
// Throttle how often we are changing the lines or the views will be slow
if (!m_updateLinesTimer.isActive()) {
m_updateLinesTimer.start(100);
}
}
void MultiDayIncidenceModel::updateScheduledLayoutLines()
{
for (const auto lineIndex : m_linesToUpdate) {
const auto periodStart = mSourceModel->start().addDays(lineIndex * mPeriodLength);
const auto idx = index(lineIndex, 0);
const auto laidOutLine = layoutLines(periodStart);
m_laidOutLines.replace(lineIndex, laidOutLine);
Q_EMIT dataChanged(idx, idx);
}
m_linesToUpdate.clear();
}
int MultiDayIncidenceModel::periodLength() const
......
......@@ -75,12 +75,16 @@ protected:
private Q_SLOTS:
void resetLayoutLines();
void slotSourceDataChanged(const QModelIndex &upperLeft, const QModelIndex &bottomRight);
void scheduleLayoutLinesUpdates(const QModelIndex &sourceIndexParent, const int sourceFirstRow, const int sourceLastRow);
void updateScheduledLayoutLines();
private:
QList<QModelIndex> sortedIncidencesFromSourceModel(const QDate &rowStart) const;
QVariantList layoutLines(const QDate &rowStart) const;
QSet<int> m_linesToUpdate;
QTimer mRefreshTimer;
QTimer m_updateLinesTimer;
IncidenceOccurrenceModel *mSourceModel{nullptr};
QVector<QVariantList> m_laidOutLines;
int mPeriodLength = 7;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment