Selectable show/hide planned activities (#4811)

This commit is contained in:
Paul Johnson
2026-01-22 20:49:55 +00:00
committed by GitHub
parent 1a4dd1d10f
commit 07e673d5d5
7 changed files with 93 additions and 6 deletions

View File

@@ -303,6 +303,8 @@
#define GC_NAVGROUPBY "<athlete-preferences>navigator/groupby" #define GC_NAVGROUPBY "<athlete-preferences>navigator/groupby"
#define GC_SORTBY "<athlete-preferences>navigator/sortby" #define GC_SORTBY "<athlete-preferences>navigator/sortby"
#define GC_SORTBYORDER "<athlete-preferences>navigator/sortbyorder" #define GC_SORTBYORDER "<athlete-preferences>navigator/sortbyorder"
#define GC_NAVDISPLAYFILTER "<athlete-preferences>navigator/displayfilter"
// Calendar sync // Calendar sync
#define GC_WEBCAL_URL "<athlete-preferences>webcal_url" #define GC_WEBCAL_URL "<athlete-preferences>webcal_url"

View File

@@ -151,6 +151,21 @@ AnalysisSidebar::AnalysisSidebar(Context *context) : QWidget(context->mainWindow
splitter->addWidget(activityItem); splitter->addWidget(activityItem);
splitter->addWidget(intervalItem); splitter->addWidget(intervalItem);
// create the ride navs display filter
activityFilter = new QComboBox(this);
activityFilter->addItem(tr("All"), static_cast<int>(RideNavFilter::ALL));
activityFilter->addItem(tr("Actual"), static_cast<int>(RideNavFilter::COMPLETED));
activityFilter->addItem(tr("Planned"), static_cast<int>(RideNavFilter::PLANNED));
int index = appsettings->cvalue(context->athlete->cyclist, GC_NAVDISPLAYFILTER, "0").toInt();
activityFilter->setCurrentIndex(index);
setDisplayFilter(index);
// add ride navs display filter to splitter's banner
QHBoxLayout* splitterBanner = activityItem->splitterHandle->getTitleLayout();
splitterBanner->insertStretch(2);
splitterBanner->insertWidget(2, activityFilter);
splitterBanner->insertStretch(2);
splitter->prepare(context->athlete->cyclist, "analysis"); splitter->prepare(context->athlete->cyclist, "analysis");
// GC signal // GC signal
@@ -164,11 +179,19 @@ AnalysisSidebar::AnalysisSidebar(Context *context) : QWidget(context->mainWindow
connect(intervalTree,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(clickZoomInterval(QTreeWidgetItem*))); connect(intervalTree,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(clickZoomInterval(QTreeWidgetItem*)));
connect(intervalTree,SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged())); connect(intervalTree,SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));
connect(activityFilter, &QComboBox::currentIndexChanged, this, &AnalysisSidebar::setDisplayFilter);
connect (context, SIGNAL(filterChanged()), this, SLOT(filterChanged())); connect (context, SIGNAL(filterChanged()), this, SLOT(filterChanged()));
configChanged(CONFIG_APPEARANCE); configChanged(CONFIG_APPEARANCE);
} }
void
AnalysisSidebar::setDisplayFilter(int index)
{
appsettings->setCValue(context->athlete->cyclist, GC_NAVDISPLAYFILTER, index);
rideNavigator->setDisplayFilter(static_cast<RideNavFilter>(index));
}
void void
AnalysisSidebar::intervalItemSelectionChanged(IntervalItem*x) AnalysisSidebar::intervalItemSelectionChanged(IntervalItem*x)
{ {
@@ -332,6 +355,15 @@ AnalysisSidebar::configChanged(qint32)
//intervalSummaryWindow->setStyleSheet(GCColor::stylesheet()); //intervalSummaryWindow->setStyleSheet(GCColor::stylesheet());
splitter->setPalette(GCColor::palette()); splitter->setPalette(GCColor::palette());
// mimic the perspective selector colors for the activity filter
QColor selected;
if (GCColor::invertColor(GColor(CTOOLBAR)) == Qt::white) selected = QColor(Qt::lightGray);
else selected = QColor(Qt::darkGray);
activityFilter->setStyleSheet(
QString("QComboBox { background: %1; color: %2; border: 1px solid rgba(127,127,127,127); border-radius: 3; }")
.arg(GColor(CTOOLBAR).name()).arg(selected.name()));
activityHistory->setStyleSheet(QString("background: %1;").arg(GColor(CPLOTBACKGROUND).name())); activityHistory->setStyleSheet(QString("background: %1;").arg(GColor(CPLOTBACKGROUND).name()));
rideNavigator->tableView->viewport()->setPalette(GCColor::palette()); rideNavigator->tableView->viewport()->setPalette(GCColor::palette());
rideNavigator->tableView->viewport()->setStyleSheet(QString("background: %1;").arg(GColor(CPLOTBACKGROUND).name())); rideNavigator->tableView->viewport()->setStyleSheet(QString("background: %1;").arg(GColor(CPLOTBACKGROUND).name()));

View File

@@ -43,6 +43,7 @@ class AnalysisSidebar : public QWidget
AnalysisSidebar(Context *context); AnalysisSidebar(Context *context);
void close(); void close();
void setWidth(int x) { rideNavigator->setWidth(x); } void setWidth(int x) { rideNavigator->setWidth(x); }
RideNavigator *rideNavigator; RideNavigator *rideNavigator;
signals: signals:
@@ -89,6 +90,10 @@ class AnalysisSidebar : public QWidget
void perfTestIntervalSelected(); void perfTestIntervalSelected();
void createPerfTestIntervalSelected(); void createPerfTestIntervalSelected();
protected slots:
void setDisplayFilter(int index);
private: private:
Context *context; Context *context;
@@ -97,6 +102,7 @@ class AnalysisSidebar : public QWidget
QWidget *activityHistory; QWidget *activityHistory;
GcSplitterItem *activityItem; GcSplitterItem *activityItem;
QSignalMapper *groupByMapper; QSignalMapper *groupByMapper;
QComboBox* activityFilter;
GcSplitterItem *calendarItem; GcSplitterItem *calendarItem;
GcMultiCalendar *calendarWidget; GcMultiCalendar *calendarWidget;

View File

@@ -109,6 +109,8 @@ public:
void addAction(QAction *action); void addAction(QAction *action);
void addActions(QList<QAction*> actions); void addActions(QList<QAction*> actions);
QHBoxLayout* getTitleLayout() { return titleLayout; }
protected: protected:
void paintEvent(QPaintEvent *); void paintEvent(QPaintEvent *);
GcSubSplitter *gcSplitter; GcSubSplitter *gcSplitter;

View File

@@ -371,6 +371,13 @@ void RideNavigator::clearSearch()
setWidth(geometry().width()); // before we update column sizes! setWidth(geometry().width()); // before we update column sizes!
} }
void
RideNavigator::setDisplayFilter(RideNavFilter filter)
{
searchFilter->setDisplayFilter(filter);
QApplication::processEvents(); // repaint/resize list view - scrollbar..
}
void RideNavigator::setWidth(int x) void RideNavigator::setWidth(int x)
{ {
// use helper function // use helper function

View File

@@ -51,6 +51,9 @@ class EditUserSeriesDialog;
class OverviewItemConfig; class OverviewItemConfig;
class RideMetric; class RideMetric;
// Ride Navigator activity list display filter options
enum class RideNavFilter { ALL=0, COMPLETED, PLANNED };
// //
// The RideNavigator // The RideNavigator
// //
@@ -158,6 +161,8 @@ class RideNavigator : public GcChartWindow
void resetView(); // when columns/width changes void resetView(); // when columns/width changes
void setDisplayFilter(RideNavFilter filter);
void searchStrings(QStringList); void searchStrings(QStringList);
void clearSearch(); void clearSearch();

View File

@@ -629,7 +629,7 @@ class SearchFilter : public QSortFilterProxyModel
public: public:
SearchFilter(QWidget *p) : QSortFilterProxyModel(p), searchActive(false) {} SearchFilter(QWidget *p) : QSortFilterProxyModel(p), searchActive(false), rideNavFilter(RideNavFilter::ALL) {}
void setSourceModel(QAbstractItemModel *model) { void setSourceModel(QAbstractItemModel *model) {
QAbstractProxyModel::setSourceModel(model); QAbstractProxyModel::setSourceModel(model);
@@ -637,11 +637,15 @@ class SearchFilter : public QSortFilterProxyModel
// find the filename column // find the filename column
fileIndex = -1; fileIndex = -1;
plannedIndex = -1;
for(int i=0; i<model->columnCount(); i++) { for(int i=0; i<model->columnCount(); i++) {
if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() == "filename" if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() == "filename"
|| model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() == tr("File")) { || model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() == tr("File")) {
fileIndex = i; fileIndex = i;
} }
if (model->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString() == "planned") {
plannedIndex = i;
}
} }
// make sure changes are propogated upstream // make sure changes are propogated upstream
@@ -654,18 +658,45 @@ class SearchFilter : public QSortFilterProxyModel
bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const { bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const {
if (fileIndex == -1 || searchActive == false) return true; // nothing to do if (fileIndex == -1 || plannedIndex == -1) return true; // nothing to do
bool keyFound = true;
bool display = true;
// lets get the ride nav display filter first
QModelIndex planned_index = model->index(source_row, plannedIndex, source_parent);
if (planned_index.isValid()) {
if (model->data(planned_index, Qt::DisplayRole).toBool()) {
if (rideNavFilter == RideNavFilter::COMPLETED) display = false; // planned row, hide if completed only
} else {
if (rideNavFilter == RideNavFilter::PLANNED) display = false; // completed activity, hide if planned only
}
}
// lets get the filename // lets get the filename
QModelIndex source_index = model->index(source_row, fileIndex, source_parent); if (searchActive) {
if (!source_index.isValid()) return true;
QString key = model->data(source_index, Qt::DisplayRole).toString(); QModelIndex source_index = model->index(source_row, fileIndex, source_parent);
return strings.contains(key);
if (source_index.isValid()) {
QString key = model->data(source_index, Qt::DisplayRole).toString();
keyFound = strings.contains(key);
}
}
// combine the two filters
return keyFound && display;
} }
public slots: public slots:
void setDisplayFilter(RideNavFilter filter) {
beginResetModel();
rideNavFilter = filter;
endResetModel();
}
void setStrings(QStringList list) { void setStrings(QStringList list) {
beginResetModel(); beginResetModel();
strings = list; strings = list;
@@ -684,6 +715,8 @@ class SearchFilter : public QSortFilterProxyModel
QAbstractItemModel *model; QAbstractItemModel *model;
QStringList strings; QStringList strings;
int fileIndex; int fileIndex;
int plannedIndex;
bool searchActive; bool searchActive;
RideNavFilter rideNavFilter;
}; };
#endif #endif