Bugfix (Calendar): Parallel activities ending after midnight (#4729)

When having two parallel activities ending after midnight, they were not
layouted correctly in day- and week view of the calendar.
This change fixes that, showing them side by side and not overlapping
any more.
This commit is contained in:
Joachim Kohlhammer
2025-11-10 19:00:24 +01:00
committed by GitHub
parent 84d7272f6d
commit db2cc86b6d
2 changed files with 51 additions and 26 deletions

View File

@@ -40,32 +40,52 @@ CalendarEntryLayouter::layout
QList<QList<int>>
CalendarEntryLayouter::groupOverlapping
(const QList<CalendarEntry> &entries)
(const QList<CalendarEntry> &entries) const
{
struct TimedEntry {
int index;
qint64 startSecs;
qint64 endSecs;
};
QList<TimedEntry> normalized;
for (int i = 0; i < entries.size(); ++i) {
const CalendarEntry &entry = entries[i];
qint64 startSecs = entry.start.hour() * 3600 + entry.start.minute() * 60 + entry.start.second();
QTime endTime = entry.start.addSecs(entry.durationSecs);
qint64 endSecs = endTime.hour() * 3600 + endTime.minute() * 60 + endTime.second();
if (endTime < entry.start) {
endSecs += 24 * 3600;
}
normalized.append({ i, startSecs, endSecs });
}
std::sort(normalized.begin(), normalized.end(), [](const TimedEntry &a, const TimedEntry &b) {
return a.startSecs < b.startSecs;
});
QList<QList<int>> clusters;
QList<int> currentCluster;
QTime clusterEnd;
for (int entryIdx = 0; entryIdx < entries.count(); ++entryIdx) {
const CalendarEntry &entry = entries[entryIdx];
QTime end = entry.start.addSecs(entry.durationSecs);
qint64 clusterEnd = -1;
for (const TimedEntry &t : normalized) {
if (currentCluster.isEmpty()) {
currentCluster.append(entryIdx);
clusterEnd = end;
currentCluster.append(t.index);
clusterEnd = t.endSecs;
} else {
if (entry.start < clusterEnd) {
currentCluster.append(entryIdx);
if (end > clusterEnd) {
clusterEnd = end;
if (t.startSecs < clusterEnd) {
currentCluster.append(t.index);
if (t.endSecs > clusterEnd) {
clusterEnd = t.endSecs;
}
} else {
clusters.append(currentCluster);
currentCluster = { entryIdx };
clusterEnd = end;
currentCluster = { t.index };
clusterEnd = t.endSecs;
}
}
}
if (! currentCluster.isEmpty()) {
clusters.append(currentCluster);
}
@@ -76,27 +96,31 @@ CalendarEntryLayouter::groupOverlapping
QList<CalendarEntryLayout>
CalendarEntryLayouter::assignColumns
(const QList<int> &cluster, const QList<CalendarEntry> &entries)
(const QList<int> &cluster, const QList<CalendarEntry> &entries) const
{
QList<QTime> columns;
QList<qint64> columnEndTimes;
QMap<int, int> entryColumns;
for (int entryIdx : cluster) {
const CalendarEntry &entry = entries[entryIdx];
QTime start = entry.start;
QTime end = start.addSecs(entry.durationSecs);
qint64 startSecs = entry.start.hour() * 3600 + entry.start.minute() * 60 + entry.start.second();
QTime endTime = entry.start.addSecs(entry.durationSecs);
qint64 endSecs = endTime.hour() * 3600 + endTime.minute() * 60 + endTime.second();
if (endTime < entry.start) {
endSecs += 24 * 3600;
}
bool found = false;
for (int colIdx = 0; colIdx < columns.count(); ++colIdx) {
if (columns[colIdx] <= start) {
columns[colIdx] = end;
for (int colIdx = 0; colIdx < columnEndTimes.size(); ++colIdx) {
if (columnEndTimes[colIdx] <= startSecs) {
columnEndTimes[colIdx] = endSecs;
entryColumns[entryIdx] = colIdx;
found = true;
break;
}
}
if (! found) {
columns << end;
entryColumns[entryIdx] = columns.count() - 1;
columnEndTimes << endSecs;
entryColumns[entryIdx] = columnEndTimes.size() - 1;
}
}
@@ -105,8 +129,9 @@ CalendarEntryLayouter::assignColumns
result << CalendarEntryLayout({
entryIdx,
entryColumns[entryIdx],
static_cast<int>(columns.count())
static_cast<int>(columnEndTimes.size())
});
}
return result;
}

View File

@@ -88,8 +88,8 @@ public:
QList<CalendarEntryLayout> layout(const QList<CalendarEntry> &entries);
private:
QList<QList<int>> groupOverlapping(const QList<CalendarEntry> &entries);
QList<CalendarEntryLayout> assignColumns(const QList<int> &cluster, const QList<CalendarEntry> &entries);
QList<QList<int>> groupOverlapping(const QList<CalendarEntry> &entries) const;
QList<CalendarEntryLayout> assignColumns(const QList<int> &cluster, const QList<CalendarEntry> &entries) const;
};
#endif