Calendar: New option to hide planned activities from summary (#4843)

* Options:
  * Include all planned activities
  * Include no planned activities
  * Include upcoming planned activities
  * Include upcoming or missed planned activities
* Tooltip shows if an activity is skipped in the summary
* Added new filter type to Specification
[publish binaries]
This commit is contained in:
Joachim Kohlhammer
2026-03-14 23:36:39 +01:00
committed by GitHub
parent 5a13b7d6a4
commit 961456ff19
6 changed files with 118 additions and 4 deletions

View File

@@ -297,6 +297,7 @@ CalendarWindow::CalendarWindow(Context *context)
setStartHour(8);
setEndHour(21);
setShowSecondaryLabel(true);
setSummaryIncludePlanned(0);
QVBoxLayout *mainLayout = new QVBoxLayout();
setChartLayout(mainLayout);
@@ -539,6 +540,22 @@ CalendarWindow::isSummaryVisibleDay
}
int
CalendarWindow::getSummaryIncludePlanned
() const
{
return includePlannedCombo->currentIndex();
}
void
CalendarWindow::setSummaryIncludePlanned
(int type)
{
includePlannedCombo->setCurrentIndex(type);
}
void
CalendarWindow::setSummaryVisibleDay
(bool visible)
@@ -799,6 +816,11 @@ CalendarWindow::mkControls
endHourSpin = new QSpinBox();
endHourSpin->setSuffix(":00");
endHourSpin->setMaximum(24);
includePlannedCombo = new QComboBox();
includePlannedCombo->addItem(tr("Always"), QVariant::fromValue(PlanFilterType::IncludeAll));
includePlannedCombo->addItem(tr("If upcoming or missed"), QVariant::fromValue(PlanFilterType::IncludeIfUpcomingOrMissed));
includePlannedCombo->addItem(tr("If upcoming"), QVariant::fromValue(PlanFilterType::IncludeIfUpcoming));
includePlannedCombo->addItem(tr("Never"), QVariant::fromValue(PlanFilterType::IncludeNone));
summaryDayCheck = new QCheckBox(tr("Day View"));
summaryDayCheck->setChecked(true);
summaryWeekCheck = new QCheckBox(tr("Week View"));
@@ -836,6 +858,7 @@ CalendarWindow::mkControls
generalForm->addRow(tr("Default End Time"), endHourSpin);
generalForm->addItem(new QSpacerItem(0, 20 * dpiYFactor));
generalForm->addRow(new QLabel(HLO + tr("Summary Options") + HLC));
generalForm->addRow(tr("Include Planned"), includePlannedCombo);
generalForm->addRow(tr("Show Summary In"), summaryDayCheck);
generalForm->addRow("", summaryWeekCheck);
generalForm->addRow("", summaryMonthCheck);
@@ -866,6 +889,7 @@ CalendarWindow::mkControls
connect(primaryFallbackCombo, &QComboBox::currentIndexChanged, this, &CalendarWindow::updateActivities);
connect(secondaryCombo, &QComboBox::currentIndexChanged, this, &CalendarWindow::updateActivities);
connect(tertiaryCombo, &QComboBox::currentIndexChanged, this, &CalendarWindow::updateActivities);
connect(includePlannedCombo, &QComboBox::currentIndexChanged, this, &CalendarWindow::updateActivities);
connect(summaryDayCheck, &QCheckBox::toggled, this, &CalendarWindow::setSummaryVisibleDay);
connect(summaryWeekCheck, &QCheckBox::toggled, this, &CalendarWindow::setSummaryVisibleWeek);
connect(summaryMonthCheck, &QCheckBox::toggled, this, &CalendarWindow::setSummaryVisibleMonth);
@@ -969,6 +993,11 @@ CalendarWindow::getActivities
}
}
PlanFilter planFilter(PlanFilterType::IncludeAll);
if (includePlannedCombo->currentIndex() != -1) {
planFilter.setType(includePlannedCombo->currentData().value<PlanFilterType>());
}
for (RideItem *rideItem : rides) {
if ( rideItem == nullptr
|| ! rideItem->dateTime.isValid()) {
@@ -1021,6 +1050,7 @@ CalendarWindow::getActivities
activity.dirty = rideItem->isDirty();
if (rideItem->planned) {
activity.originalPlanLabel = buildOriginalLabel(rideItem);
activity.isExcludedFromSummary = ! planFilter.pass(rideItem);
}
RideItem *linkedRide = context->athlete->rideCache->getLinkedActivity(rideItem);
@@ -1061,6 +1091,11 @@ CalendarWindow::getSummaries
FilterSet filterSet(context->isfiltered, context->filters);
Specification spec;
spec.setFilterSet(filterSet);
PlanFilterType planFilterType = PlanFilterType::IncludeAll;
if (includePlannedCombo->currentIndex() != -1) {
planFilterType = includePlannedCombo->currentData().value<PlanFilterType>();
}
spec.setPlanFilter(planFilterType);
for (int timeBucket = 0; timeBucket < numTimeBuckets; ++timeBucket) {
QDate firstDayOfTimeBucket = firstDay.addDays(timeBucket * timeBucketSize);
QDate lastDayOfTimeBucket = firstDayOfTimeBucket.addDays(timeBucketSize - 1);

View File

@@ -79,6 +79,7 @@ class CalendarWindow : public GcChartWindow
Q_PROPERTY(int firstDayOfWeek READ getFirstDayOfWeek WRITE setFirstDayOfWeek USER true)
Q_PROPERTY(int startHour READ getStartHour WRITE setStartHour USER true)
Q_PROPERTY(int endHour READ getEndHour WRITE setEndHour USER true)
Q_PROPERTY(int summaryIncludePlanned READ getSummaryIncludePlanned WRITE setSummaryIncludePlanned USER true)
Q_PROPERTY(bool summaryVisibleDay READ isSummaryVisibleDay WRITE setSummaryVisibleDay USER true)
Q_PROPERTY(bool summaryVisibleWeek READ isSummaryVisibleWeek WRITE setSummaryVisibleWeek USER true)
Q_PROPERTY(bool summaryVisibleMonth READ isSummaryVisibleMonth WRITE setSummaryVisibleMonth USER true)
@@ -96,6 +97,7 @@ class CalendarWindow : public GcChartWindow
int getFirstDayOfWeek() const;
int getStartHour() const;
int getEndHour() const;
int getSummaryIncludePlanned() const;
bool isSummaryVisibleDay() const;
bool isSummaryVisibleWeek() const;
bool isSummaryVisibleMonth() const;
@@ -115,6 +117,7 @@ class CalendarWindow : public GcChartWindow
void setFirstDayOfWeek(int fdw);
void setStartHour(int hour);
void setEndHour(int hour);
void setSummaryIncludePlanned(int type);
void setSummaryVisibleDay(bool visible);
void setSummaryVisibleWeek(bool visible);
void setSummaryVisibleMonth(bool svm);
@@ -139,6 +142,7 @@ class CalendarWindow : public GcChartWindow
QComboBox *firstDayOfWeekCombo;
QSpinBox *startHourSpin;
QSpinBox *endHourSpin;
QComboBox *includePlannedCombo;
QCheckBox *summaryDayCheck;
QCheckBox *summaryWeekCheck;
QCheckBox *summaryMonthCheck;

View File

@@ -21,7 +21,49 @@
#include "IntervalItem.h"
#include "RideFile.h"
Specification::Specification(DateRange dr, FilterSet fs) : dr(dr), fs(fs), it(NULL), recintsecs(0), ri(NULL) {}
PlanFilter::PlanFilter
(PlanFilterType type)
: type(type)
{
}
void
PlanFilter::setType
(PlanFilterType type)
{
this->type = type;
}
PlanFilterType
PlanFilter::getType
() const
{
return type;
}
bool
PlanFilter::pass
(RideItem const * const rideItem) const
{
if (!rideItem->planned || type == PlanFilterType::IncludeAll) {
return true;
} else if (type == PlanFilterType::IncludeIfUpcomingOrMissed) {
return !rideItem->hasLinkedActivity();
} else if (type == PlanFilterType::IncludeIfUpcoming) {
return rideItem->dateTime.date() >= QDate::currentDate()
&& !rideItem->hasLinkedActivity();
} else if (type == PlanFilterType::IncludeNone) {
return false;
}
return true;
}
Specification::Specification(DateRange dr, FilterSet fs, PlanFilter pf) : dr(dr), fs(fs), pf(pf), it(NULL), recintsecs(0), ri(NULL) {}
Specification::Specification(IntervalItem *it, double recintsecs) : it(it), recintsecs(recintsecs), ri(NULL) {}
Specification::Specification() : it(NULL), recintsecs(0), ri(NULL) {}
@@ -36,7 +78,7 @@ Specification::pass(QDate date) const
bool
Specification::pass(RideItem*item) const
{
return (dr.pass(item->dateTime.date()) && fs.pass(item->fileName));
return (dr.pass(item->dateTime.date()) && fs.pass(item->fileName) && pf.pass(item));
}
bool
@@ -58,6 +100,12 @@ void
Specification::setFilterSet(FilterSet fs)
{
this->fs = fs;
}
void
Specification::setPlanFilter(PlanFilter pf)
{
this->pf = pf;
}
void

View File

@@ -74,12 +74,33 @@ class FilterSet
int count() { return filters_.count(); }
};
enum class PlanFilterType {
IncludeAll,
IncludeIfUpcomingOrMissed,
IncludeIfUpcoming,
IncludeNone
};
Q_DECLARE_METATYPE(PlanFilterType)
class PlanFilter
{
public:
PlanFilter(PlanFilterType type = PlanFilterType::IncludeAll);
void setType(PlanFilterType type);
PlanFilterType getType() const;
bool pass(RideItem const * const rideItem) const;
private:
PlanFilterType type = PlanFilterType::IncludeAll;
};
class RideFileIterator;
class Specification
{
friend class ::RideFileIterator;
public:
Specification(DateRange dr, FilterSet fs);
Specification(DateRange dr, FilterSet fs, PlanFilter pf = PlanFilter());
Specification(IntervalItem *it, double recintsecs);
Specification();
@@ -101,6 +122,7 @@ class Specification
// set criteria
void setDateRange(DateRange dr);
void setFilterSet(FilterSet fs);
void setPlanFilter(PlanFilter pf);
void setIntervalItem(IntervalItem *it, double recintsecs);
void setRideItem(RideItem *ri);
@@ -123,6 +145,7 @@ class Specification
private:
DateRange dr;
FilterSet fs;
PlanFilter pf;
IntervalItem *it;
double recintsecs;
RideItem *ri;

View File

@@ -65,6 +65,7 @@ struct CalendarEntry {
QTime start;
int durationSecs = 0;
int type = 0;
bool isExcludedFromSummary = false;
bool isRelocatable = false;
bool hasTrainMode = false;
bool dirty = false;

View File

@@ -1756,7 +1756,10 @@ toolTipDayEntry(const QPoint &pos, QAbstractItemView *view, const CalendarDay &d
status = QObject::tr("planned");
}
if (calEntry.dirty) {
status += ", " + QObject::tr("modified");
status += " " + QObject::tr("modified");
}
if (calEntry.isExcludedFromSummary) {
status += "" + QObject::tr("not in summary");
}
QString tooltip = QString("<div style='padding: %1px;'>").arg(4 * dpiXFactor);