diff --git a/src/Core/RideCache.cpp b/src/Core/RideCache.cpp index 410ef2e46..9daf31457 100644 --- a/src/Core/RideCache.cpp +++ b/src/Core/RideCache.cpp @@ -287,6 +287,9 @@ RideCache::addRide(QString name, bool dosignal, bool select, bool useTempActivit // notify everyone to select the one we were already on context->notifyRideSelected(prior); } + + // model estimates (lazy refresh) + estimator->refresh(); } void @@ -376,6 +379,9 @@ RideCache::removeCurrentRide() // now select another ride context->notifyRideSelected(select); + + // model estimates (lazy refresh) + estimator->refresh(); } // NOTE: diff --git a/src/Core/RideCache.h b/src/Core/RideCache.h index 92ab90633..f129088fd 100644 --- a/src/Core/RideCache.h +++ b/src/Core/RideCache.h @@ -132,6 +132,7 @@ class RideCache : public QObject protected: friend class ::Athlete; + friend class ::MainWindow; // save dialog friend class ::RideCacheBackgroundRefresh; Context *context; diff --git a/src/Gui/SaveDialogs.cpp b/src/Gui/SaveDialogs.cpp index 0042d79ae..3a31e4424 100644 --- a/src/Gui/SaveDialogs.cpp +++ b/src/Gui/SaveDialogs.cpp @@ -19,6 +19,7 @@ #include "Tab.h" #include "Athlete.h" #include "RideCache.h" +#include "Estimator.h" #include "GcRideFile.h" #include "JsonRideFile.h" #include "RideItem.h" @@ -197,6 +198,9 @@ MainWindow::saveSilent(Context *context, RideItem *rideItem) // mark clean as we have now saved the data rideItem->ride()->emitSaved(); + + // model estimates (lazy refresh) + context->athlete->rideCache->estimator->refresh(); } diff --git a/src/Metrics/Estimator.cpp b/src/Metrics/Estimator.cpp index 7ee7cf5fd..9ae2453ec 100644 --- a/src/Metrics/Estimator.cpp +++ b/src/Metrics/Estimator.cpp @@ -99,10 +99,51 @@ class RollingBests { Estimator::Estimator(Context *context) : context(context) { + // used to flag when we need to stop + abort = false; + + // lazy start signal + connect(&singleshot, SIGNAL(timeout()), this, SLOT(calculate())); + // when thread finishes we can let everyone know estimates are updated connect(this, SIGNAL(finished()), context, SLOT(notifyEstimatesRefreshed())); } +void +Estimator::stop() +{ + if (isRunning()) { + + // we could use requestInterruption but would mean we need QT > 5.2 + // and there isn't much value in that. + abort = true; + + // now wait for the thread to stop + while(isRunning() && abort == true) msleep(50); + } +} + +// terminate thread before closing +Estimator::~Estimator() +{ + stop(); +} + +// refresh +void +Estimator::refresh() +{ + printd("Lazy start triggered.\n"); + + stop(); // stop any running threads + singleshot.stop(); // stop any pending threads + + // 15 secs delay before calculate() is triggered + singleshot.setSingleShot(true); + singleshot.setInterval(15000); + singleshot.start(); +} + // setup and run, if not already running void Estimator::calculate() @@ -184,6 +225,13 @@ Estimator::run() QDate date = from; while (date < to) { + // check if we've been asked to stop + if (abort == true) { + printd("Model estimator aborted.\n"); + abort = false; + return; + } + QDate begin = date; QDate end = date.addDays(6); diff --git a/src/Metrics/Estimator.h b/src/Metrics/Estimator.h index 594fe2887..416c1fd2d 100644 --- a/src/Metrics/Estimator.h +++ b/src/Metrics/Estimator.h @@ -38,13 +38,22 @@ class Estimator : public QThread { public: Estimator(Context *); - - // sets up and kicks off thread - void calculate(); + ~Estimator(); // perform calculation in thread void run(); + // halt the thread + void stop(); + + // cancel any pending/running and kick off with 15 sec delay + void refresh(); + + public slots: + + // setup and run estimators + void calculate(); + protected: friend class ::Athlete; @@ -53,7 +62,9 @@ class Estimator : public QThread { QMutex lock; QList estimates; QVector rides; // worklist + QTimer singleshot; + bool abort; }; #endif