* Updating power values of workout based planned activities when they
fall into a timerange with different CP
* Triggers:
* CP configuration changes (future activities only)
* planned activities are moved (calendar)
* schedules are repeated (calendar)
* rest days are inserted or removed (calendar)
* Additional: Typo in Calendar (show in train _n_ode -> mode)
* Bidirectional linking of planned and completed activities via field "Linked Filename"
* Convenience functions in RideCache, taking care of updating all relations
* link activities
* unlink activities
* move activities
* copy planned activities
* batch copy planned activities
* shift planned activities
* Calendar
* Visual hints to show whether an activity is linked (bar on right side)
* Options to link, unlink, jump to linked activity
* Option to save an activity
* Visual hint indicating unsaved changes in an activity (italic font)
* Deleting activities clears the link
* Agenda: Hiding completed / linked activities
* Repeat Schedule: Clearing the link in copied entries
* RideImportWizard: Autolinking new activities if a planned counterpart exists
* Stricter consistency handling of linked activities
Additional:
* highlighting linked activities when clicking in calendar
* linked() datafilter access function (similar to filename())
* New dialog to link planned and completed activities
* Centralized the calendar context menus (only one location to maintain them for all views)
* Restructured the entries of all calendar context menus
i) Ensure that SpecialFields (and SepcialTabs for consistency) are singletons, and GlobalContext & RideCache can reload its configuration.
ii) GlobalContext not longer holds a SpecialFields parameter, SpecialFields is a single globally available object.
ii) The unused model and accessor have been removed.
iii) The unused and unimplemented fieldType() and associated enum have been removed.
iv) All SpecialFields accessor functions now use const QString& parameter types.
Batch Processing - Delete, Data Processors & Export
Extension of Batch Export dialog to include other operation on multiple activities:
- run data processor (Builtin or Python)
- delete (after confirmation)
Co-authored-by: Alejandro Martinez <amtriathlon@gmail.com>
This boundary error provokes the cache entry for the oldest
activity don't be refreshed on full cache refresh, only
when the activity is imported or opened (s.t. selecting it
in Activities View).
For most users this may be uneventfull, but if the oldest
activity becomes dirty, a full cache will happend on each
following start, until the oldest activity is opened and
it may explain the behavior reported ocasionally at the forum
and recently in #4297
.. precious commit has a significant improvement in performance
since it reduces total CPU activity not related to metric
calculation dramatically.
.. this commit is a minor tweak to ensure updates are shown
relative to the number of activities- so instead of giving
visual feedback after every 100 activities we give feedback
after every 10% of the activies are processed.
.. since Qt5.15 QtConcurrent::map() will use all available
worker threads in the global thread pool. And this causes
a deadlock in the GUI since QGraphicsView uses threads to
manage updates.
.. we now manage the metric refresh via RideCacheRefreshThread
and use at most 50% of the overall threads available in the
global thread pool.
.. Have tested obvious triggers such as metric schema updates
and user metrics being changed, but more testing is needed.
Fixes#3611
All sports defined as values for Sport metadata field can have
specifics HR Zones and default to Bike zones otherwise.
Similar to current HR zones for Run.
Part 2 of #3280
.. mostly straight replacement as qt5 containers are templated
and qSort semantics are the same as std::sort
.. prepping for Qt6.2 which is due late 2021.
Signed-off-by: Mark Liversedge <liversedge@gmail.com>
.. Global settings (themes, metadata etc) are now maintained
in the config dialog as in the past, whilst athlete settings
(such as zones, measures etc) are now maintained in a new
config dialog accessible from the athlete view (gear icon).
.. Config changes are communicated via two signals;
* Context::configChanged(qint32)
* GlobalContext::configChanged(qint32)
Crucially, all global context signals are cascaded through
the athlete contexts-- so athlete specific widgets only
need to connect to the athlete context signal (and will get
athlete and global config change notifications).
Whilst global widgets such as the sidebar and mainwindow
need only connect to the globalcontext signal since they
are not interested in athlete specific details.
[publish binaries]
.. Ride metadata was associated to the athlete rather than a
global setting. This was a serious design flaw since user
metrics can reference metadata.
.. A global metadata.xml file is generated on startup by
consolidating all athlete level settings into a single
configuration.
.. Other dependencies were also moved; SpecialFields,
ColorEngine and UseMetricUnits.
.. We should now be able to remove athlete configuration
from the config dialog and put it into the athlete view
instead.
This will also fixe a long standing issue with
configuring athlete settings when multiple athletes are
open.
[publish binaries]
.. move thread based load of ridecache into ridecache, this fixes a
serious regression.
.. previously because the ridecache was created in a thread it could
not attach to the events from the main gui event loop.
.. we now load the RideDB.json file in a worker thread, but the
ridecache, and its items are created in the main thread.
.. GlobalContext::context() provides a global context that is not
tied to an athlete or MainWindow.
.. At present it just offers signals for config changes but will
likely see more context move across as the application preferences
and athlete configuration are separated as we enhance support
for multiple athletes.
.. string manipulation using raw C since its simple character
replacement, halved time over previous approach.
.. lookup rideitem in ridecache via binary search (lower_bound)
rather than serial. Minor speed up.
.. Overall, loading should be noticeably quicker for most users.
Exiting isRun/isSwim are preserved and new isRide/isXtrain added.
Use them in DataFilter to provide isRide, isRun, isSwim and isXtrain
and in RideSummary for better filtering of activities in rides, runs
swims and xtrains.
Part 1 of #3280
.. Refresh model estimates when rides added, deleted, saved.
.. Lazy refresh will cancel any pending or running threads and
trigger a new one in 15 secs time.
.. This strategy allows us to call a lazy refresh even when importing
large number of rides, since the start will be delayed and cancelled
by the next ride added etc.
.. The thread stop() function is also called by the destructor to stop
when the user exits and avoiding delay/SEGV on exit.
.. new Estimator class to refresh model estimates in a thread.
.. localised all data access to the new class to resolve issues
with thread safety.
.. RideSummary and LTMPlot do not trigger refresh of the estimates
.. added a QMutex around access in Athlete::getPDEstimates and the
code in Estimator::run that updates them.
NOTE:
will still need a follow-up commit to resolve estimate refresh
e.g. after ride saved, or rides imported or rides downloaded from
a cloud service. This is a challenging problem since refreshes
need to be 'very lazy' to avoid wasted cycles.
Fixes#2820
.. at startup we ask the user for permission to share
.. once permission is granted the upload is performed and
re-done every year, so long as > 100 workouts have been
collected since the last time.
.. Will prepare and post data to an OpenData server running
in a background thread:
* will find servers from www.goldencheetah.org
* uses first server it finds that is running
* prepares and sends data
.. need to write the code to get explicit permission from
the user to do it, then send data when worthwhile.
.. thinking this is annually, but only if > 100 new workouts.
.. phew! this was a subtle bug.
.. the SpecialFields class tells the data filter what
type of thing each symbol equates to.
.. it was saying TSS was metadata not a metric.
.. this is becuase SpecialFields is setup before the
user metrics are loaded, so it only saw it as a
metadata field.
.. we now refresh context.specialFields after the
user metrics are loaded. So this will not just
fix TSS but ALL user metrics that have an override
defined in metadata.
.. as usermetrics that alias the old metric name to
the renamed metric.
.. need to follow up with restrictions on the use of
the compatibility metrics.
.. Gui notifications of background activity
.. a small notification area at the bottom of the analysis
sidebar shows checking and download status.
.. also fixed up the ride list to not select them, since that
is irritating if your in the middle of doing something.
.. initial plumbing to get the auto downloader integrated
into context, athlete and ridecache refresh.
.. part 2 will need to perform the download functions
.. part 3 to add the GUI / notification of progress
.. full wizard now done, will write appsettings.
.. need to now look at how OAuth can be call mid-config as
a refactor if OAuthDialog in part 2
.. need to also look at how folder selection can be called using
"in-progress" config in part 3
.. need to tidy up special topics in Part 4, such as google drive
id and todays plan handling coach/athlete selection.
... in addition to DateTime in the .json File name (which is in local Time), also check for duplicates using UTC from RideCache to avoid duplicate imports if user changes his PC TimeZone (e.g. when travelling)
... the problem e.g. occurs in Autoimport where the same files would be imported again, if the PC TimeZone changes
.. a data processor can now be configured to run on save
.. in addition, the data processor is now passed the operation
that is triggering it: "Manual", "ADD", "UPDATE", "DELETE",
"IMPORT".
.. a new data processor has been added to write a JSON file to
the snippet directory (added to the athlete structure).
.. this is so we can output a snippet every time an activity is
added, updated or deleted (i.e. runs "on save").
.. these JSON snippets can be used to update external datastores
where coaches use other analytic software but don't want to
manually sync GC changes with there external stores.
Adds isMetricRelevantForRides(specification, metric) to RideCache
to check if a metric isRelevant for some of the activities passing
the specification
Also reduces from 3 to 1 the calls to getRideTypeCounts