Skip to content

Commit a00e276

Browse files
authored
Dialog to build filter queries for similar activities (#4805)
* list all (non-zero) fields and metrics * filter list by field / metric name * select an operator per field (ignore, equals, contains, larger than, ...) * available in the context menus of activity- and calendar view
1 parent 7a8f329 commit a00e276

16 files changed

Lines changed: 609 additions & 19 deletions

src/Charts/CalendarWindow.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "RepeatScheduleWizard.h"
3232
#include "WorkoutFilter.h"
3333
#include "IconManager.h"
34+
#include "FilterSimilarDialog.h"
3435
#include "SeasonDialogs.h"
3536
#include "SaveDialogs.h"
3637

@@ -333,6 +334,15 @@ CalendarWindow::CalendarWindow(Context *context)
333334
}
334335
}
335336
});
337+
connect(calendar, &Calendar::filterSimilar, this, [this](CalendarEntry activity) {
338+
for (RideItem *rideItem : this->context->athlete->rideCache->rides()) {
339+
if (rideItem != nullptr && rideItem->fileName == activity.reference) {
340+
FilterSimilarDialog dlg(this->context, rideItem, this);
341+
dlg.exec();
342+
break;
343+
}
344+
}
345+
});
336346
connect(calendar, &Calendar::linkActivity, this, &CalendarWindow::linkActivities);
337347
connect(calendar, &Calendar::unlinkActivity, this, &CalendarWindow::unlinkActivities);
338348
connect(calendar, &Calendar::viewActivity, this, [this](CalendarEntry activity) {

src/Core/Utils.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,31 @@ QString xmlprotect(const QString &string)
162162
return s;
163163
}
164164

165+
QString quoteEscape(const QString &string)
166+
{
167+
QString out;
168+
out.reserve(string.size() * 2);
169+
int backslashes = 0;
170+
for (QChar c : string) {
171+
if (c == '\\') {
172+
backslashes++;
173+
out += c;
174+
} else if (c == '"') {
175+
if (backslashes % 2 == 0) {
176+
out += "\\\"";
177+
} else {
178+
out += '"';
179+
}
180+
backslashes = 0;
181+
} else {
182+
out += c;
183+
backslashes = 0;
184+
}
185+
}
186+
out.squeeze();
187+
return out;
188+
}
189+
165190
QString unescape(const QString &string)
166191
{
167192
// just unescape common \ characters

src/Core/Utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace Utils
4040
{
4141
QString xmlprotect(const QString &string);
4242
QString unprotect(const QString &buffer);
43+
QString quoteEscape(const QString &string); // escape quotes (" -> \", \" -> \", \\" -> \\\", ...)
4344
QString unescape(const QString &string); // simple string unescaping, used in datafilters
4445
QString jsonprotect(const QString &buffer);
4546
QString jsonunprotect(const QString &buffer);

src/Gui/AnalysisSidebar.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242
// Show in Train Mode
4343
#include "WorkoutFilter.h"
4444

45+
// Filter for similar activities
46+
#include "FilterSimilarDialog.h"
47+
4548
AnalysisSidebar::AnalysisSidebar(Context *context) : QWidget(context->mainWindow), context(context)
4649
{
4750
QVBoxLayout *mainLayout = new QVBoxLayout(this);
@@ -412,6 +415,16 @@ AnalysisSidebar::showActivityMenu(const QPoint &pos)
412415
connect(actFindBest, SIGNAL(triggered(void)), this, SLOT(addIntervals(void)));
413416
menu.addAction(actFindBest);
414417

418+
QAction *filterSimilar = new QAction(tr("Filter similar activities..."), rideNavigator);
419+
connect(filterSimilar, &QAction::triggered, this, [this]() {
420+
if (context->ride != nullptr) {
421+
FilterSimilarDialog dlg(context, context->ride, this);
422+
dlg.exec();
423+
}
424+
});
425+
menu.addAction(filterSimilar);
426+
427+
415428
if (rideItem->planned && rideItem->sport == "Bike") {
416429
QString filter = buildWorkoutFilter(rideItem);
417430
if (! filter.isEmpty()) {

src/Gui/Calendar.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ CalendarBaseTable::buildContextMenu
184184
contextMenu->addAction(tr("Unlink from planned activity"), this, [this, entry]() { emit unlinkActivity(entry); });
185185
}
186186
contextMenu->addSeparator();
187+
contextMenu->addAction(tr("Filter similar activities..."), this, [this, entry]() { emit filterSimilar(entry); });
188+
contextMenu->addSeparator();
187189
contextMenu->addAction(tr("Delete completed activity"), this, [this, entry]() { emit delActivity(entry); });
188190
break;
189191
case ENTRY_TYPE_PLANNED_ACTIVITY:
@@ -203,10 +205,11 @@ CalendarBaseTable::buildContextMenu
203205
} else {
204206
contextMenu->addAction(tr("Mark as incomplete"), this, [this, entry]() { emit unlinkActivity(entry); });
205207
}
208+
contextMenu->addSeparator();
206209
if (entry.hasTrainMode) {
207-
contextMenu->addSeparator();
208210
contextMenu->addAction(tr("Show in train mode..."), this, [this, entry]() { emit showInTrainMode(entry); });
209211
}
212+
contextMenu->addAction(tr("Filter similar activities..."), this, [this, entry]() { emit filterSimilar(entry); });
210213
contextMenu->addSeparator();
211214
contextMenu->addAction(tr("Delete planned activity"), this, [this, entry]() { emit delActivity(entry); });
212215
break;
@@ -1543,6 +1546,7 @@ CalendarDayView::CalendarDayView
15431546
connect(dayTable, &CalendarDayTable::viewLinkedActivity, this, &CalendarDayView::viewLinkedActivity);
15441547
connect(dayTable, &CalendarDayTable::addActivity, this, &CalendarDayView::addActivity);
15451548
connect(dayTable, &CalendarDayTable::showInTrainMode, this, &CalendarDayView::showInTrainMode);
1549+
connect(dayTable, &CalendarDayTable::filterSimilar, this, &CalendarDayView::filterSimilar);
15461550
connect(dayTable, &CalendarDayTable::delActivity, this, &CalendarDayView::delActivity);
15471551
connect(dayTable, &CalendarDayTable::saveChanges, this, &CalendarDayView::saveChanges);
15481552
connect(dayTable, &CalendarDayTable::discardChanges, this, &CalendarDayView::discardChanges);
@@ -1842,6 +1846,7 @@ CalendarWeekView::CalendarWeekView
18421846
connect(weekTable, &CalendarDayTable::viewLinkedActivity, this, &CalendarWeekView::viewLinkedActivity);
18431847
connect(weekTable, &CalendarDayTable::addActivity, this, &CalendarWeekView::addActivity);
18441848
connect(weekTable, &CalendarDayTable::showInTrainMode, this, &CalendarWeekView::showInTrainMode);
1849+
connect(weekTable, &CalendarDayTable::filterSimilar, this, &CalendarWeekView::filterSimilar);
18451850
connect(weekTable, &CalendarDayTable::delActivity, this, &CalendarWeekView::delActivity);
18461851
connect(weekTable, &CalendarDayTable::saveChanges, this, &CalendarWeekView::saveChanges);
18471852
connect(weekTable, &CalendarDayTable::discardChanges, this, &CalendarWeekView::discardChanges);
@@ -2039,6 +2044,7 @@ Calendar::Calendar
20392044
connect(dayView, &CalendarDayView::viewLinkedActivity, this, &Calendar::viewLinkedActivity);
20402045
connect(dayView, &CalendarDayView::addActivity, this, &Calendar::addActivity);
20412046
connect(dayView, &CalendarDayView::showInTrainMode, this, &Calendar::showInTrainMode);
2047+
connect(dayView, &CalendarDayView::filterSimilar, this, &Calendar::filterSimilar);
20422048
connect(dayView, &CalendarDayView::delActivity, this, &Calendar::delActivity);
20432049
connect(dayView, &CalendarDayView::saveChanges, this, &Calendar::saveChanges);
20442050
connect(dayView, &CalendarDayView::discardChanges, this, &Calendar::discardChanges);
@@ -2067,6 +2073,7 @@ Calendar::Calendar
20672073
connect(weekView, &CalendarWeekView::viewLinkedActivity, this, &Calendar::viewLinkedActivity);
20682074
connect(weekView, &CalendarWeekView::addActivity, this, &Calendar::addActivity);
20692075
connect(weekView, &CalendarWeekView::showInTrainMode, this, &Calendar::showInTrainMode);
2076+
connect(weekView, &CalendarWeekView::filterSimilar, this, &Calendar::filterSimilar);
20702077
connect(weekView, &CalendarWeekView::delActivity, this, &Calendar::delActivity);
20712078
connect(weekView, &CalendarWeekView::saveChanges, this, &Calendar::saveChanges);
20722079
connect(weekView, &CalendarWeekView::discardChanges, this, &Calendar::discardChanges);
@@ -2093,6 +2100,7 @@ Calendar::Calendar
20932100
setView(CalendarView::Day);
20942101
});
20952102
connect(monthView, &CalendarMonthTable::showInTrainMode, this, &Calendar::showInTrainMode);
2103+
connect(monthView, &CalendarMonthTable::filterSimilar, this, &Calendar::filterSimilar);
20962104
connect(monthView, &CalendarMonthTable::linkActivity, this, &Calendar::linkActivity);
20972105
connect(monthView, &CalendarMonthTable::unlinkActivity, this, &Calendar::unlinkActivity);
20982106
connect(monthView, &CalendarMonthTable::viewActivity, this, &Calendar::viewActivity);

src/Gui/Calendar.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class CalendarBaseTable : public QTableWidget {
6868

6969
signals:
7070
void showInTrainMode(CalendarEntry ctivity);
71+
void filterSimilar(CalendarEntry activity);
7172
void linkActivity(CalendarEntry activity, bool autoLink);
7273
void unlinkActivity(CalendarEntry activity);
7374
void viewActivity(CalendarEntry activity);
@@ -262,6 +263,7 @@ class CalendarDayView : public QWidget {
262263
void dayChanged(QDate date);
263264

264265
void showInTrainMode(CalendarEntry activity);
266+
void filterSimilar(CalendarEntry activity);
265267
void linkActivity(CalendarEntry activity, bool autoLink);
266268
void unlinkActivity(CalendarEntry activity);
267269
void viewActivity(CalendarEntry activity);
@@ -315,6 +317,7 @@ class CalendarWeekView : public QWidget {
315317
void dayChanged(QDate date);
316318

317319
void showInTrainMode(CalendarEntry activity);
320+
void filterSimilar(CalendarEntry activity);
318321
void linkActivity(CalendarEntry activity, bool autoLink);
319322
void unlinkActivity(CalendarEntry activity);
320323
void viewActivity(CalendarEntry activity);
@@ -381,6 +384,7 @@ public slots:
381384
void moveActivity(CalendarEntry activity, QDate srcDay, QDate destDay, QTime destTime);
382385

383386
void showInTrainMode(CalendarEntry activity);
387+
void filterSimilar(CalendarEntry activity);
384388
void linkActivity(CalendarEntry activity, bool autoLink);
385389
void unlinkActivity(CalendarEntry activity);
386390
void viewActivity(CalendarEntry activity);

0 commit comments

Comments
 (0)