Equipment feature based upon Overview tiles
This PR has been updated (1st Sept) to support multiple eqlink values in activities and tiles, also supports equipment tile cloning and tile movement between equipment pages, and metadata tile has quick set popup, as per PR https://github.com/GoldenCheetah/GoldenCheetah/pull/4519.
- So if you have already created an EquipmentLink meta data item, this needs to change from a SHORTTEXT field to a TEXT field. Also note the equipment-perspective.xml file format has changed, but on start-up the old version will be converted to the new format.
- To define multiple EquipmentLink values in an activity they need to be comma separated, so BIKE1, POWER-METER, please ensure the tags do not include any internal spaces, so "BIKE 1" will be replaced by "BIKE1" by the input parsing.
This is an update to my earlier Equipment Feature proposal https://github.com/GoldenCheetah/GoldenCheetah/pull/4466 and this builds upon the Tile interface approach and provides a more consistent user interface. It also requires fewer lines of code to implement as it reuses many existing GC capabilities and additionally the redesign now supports multiple athletes sharing equipment for different activities. Any feedback or guidance on future development would be useful.
Design Aims:
- To be as generic as possible, support multiple equipment & components
- Support multiple athletes
- Supports multiple equipment link values in activities and tiles
- Use existing GC capabilities: - Using the perspective mechanism to loading/save equipment information. - Use the GCChartWindow to support importing/export of chart templates.
- Minimise the number of Metadata items added to GC activities
Description This PR will create a new unpopulated “EquipmentLink” metadata item in all activities to provide a mechanism to link an activity to an equipment link item defined in the new page. The diagram below tries to illustrate the relationships between the equipment items:
An Equipment Overview chart is created as shown below:
Each Equipment Overview chart can contain one or more of the following tiles:
- Equipment Item
- Equipment Overview Summary
- Equipment Notes
Each Equipment Tile can be configured using the Tile Settings dialog:
The Tile Settings dialog supports the following fields:
Name: Short descriptive name of equipment item Manual dst: Any distance the equipment item has covered not captured by GC activities Manual elev: Any elevation climbed the equipment item has covered not captured by GC activities EqLink History:A list of equipment link values and the dates when they are active:
- EqLink Name: The EqLink Name used within the activities Equipment Link metadata field
- Start Date: The first use of the equipment item
- End Date: Last use of the equipment item
Replacement dst: Replacement distance for the equipment item (highlights yellow on the tile when distance exceeded), setting a zero value disables this feature. Replacement elev: Replacement elevation climbed for the equipment item (highlights yellow on the tile when height is exceeded), setting a zero value disables this feature. Notes: Information specific to the equipment item
The Equipment Item Tiles will display totals for all the activities with matching Equipment Link text and restricted to any Start Date/End Date range defined.
The Tiles main distance value will be displayed as follows:
- Blue if today's date falls within the equipment's date range.
- Greyed out if today's date falls outside the range defined by the End Date.
- Yellow if the distance or elevation is over the user entered replacement value
- Yellow if the date range is invalid.
The Equipment Summary Tile provides totals for all activities with matching Equipment Link text or if the Equipment Link field in the Tile is left empty then it provides a summary of all GoldenCheetah's activities for the open athletes.
The Equipment Notes Tile provides location to hold information about the equipment represented by the Equipment Link.
Tiles can be cloned or moved between equipment pages by right clicking and selecting the option from the popup menu, the example shows some test page names (Synapse-2014, Tarmac-2016, etc :
Also any equipment link metadata tile on an overview page now includes a right click popup to quickly select the equipment used for the activity (only supports a single equipment entry):
The Equipment Overview pages can be exported as gcharts, so templates for bikes or other equipment can be created and then duplicated by importing them and modifying their page title to the required equipment link text.
The Equipment Overview information is automatically saved to the equipment-perspectives.xml file in the GC root directory (the one with the Athlete folders).
The values and totals displayed in the Tiles are computed dynamically from those athletes who are open within GC, as athletes activities are only loaded by GC when an athlete is opened.
The Equipment Overview supports metric and imperial units, modifying them in Tools->Options dialog will update the user entered values and recompute all other values and totals.
Brief Design Information:
- A new equipment view class EquipView has been created derived from AbstractView.
- In the MainWindow the Equipment View is a new view stack (value =2) .
- The Equipment view has a single perspective that cannot be altered by the user. --The perspective selector in the MainWindows tool bar is hidden when the Equipment View is selected --The MainWindow's perspective management of athlete specific views is ignored when Equipment View is selected
- An OverviewEquipmentWindow is derived from the existing OverviewWindow
- The OverviewEquipmentWindowtiles (equipment, notes & summary) are derived from the ChartSpaceItem class.
- The values within the tiles are recomputed upon page display or for individual tile updates by a new EquipCalculator class, this uses a thread implementation similar to that found in the RideCache class.
- The equipment-perspective.xml file is shared between all athletes, and only holds information that cannot be derived/re-calculated, this simplifies keeping the displayed values correct. The file is loaded by the EquipView class and saved upon destruction, as per the other derived AbstractView classes.
While working out how to implement this equipment PR, I found the following which I have corrected, if required these can be put in separate PRs:
src/Gui/AthleteTab.cpp The saveState() call casues any loaded perspectives to be saved twice when GC exits, once here and once the when the AbstractView's destructor is called.
void
AthleteTab::close()
{
// I have deleted the saveState calls below
analysisView->saveState();
homeView->saveState();
trainView->saveState();
diaryView->saveState();
analysisView->close();
homeView->close();
trainView->close();
diaryView->close();
src/Gui/MainWindow.cpp
The following are not called or used:
void
MainWindow::setChartMenu()
{
unsigned int mask=0;
// called when chart menu about to be shown
// setup to only show charts that are relevant
// to this view
switch(currentAthleteTab->currentView()) {
case 0 : mask = VIEW_TRENDS; break;
default:
case 1 : mask = VIEW_ANALYSIS; break;
case 2 : mask = VIEW_DIARY; break;
case 3 : mask = VIEW_TRAIN; break;
}
chartMenu->clear();
if (!mask) return;
for(int i=0; GcWindows[i].relevance; i++) {
if (GcWindows[i].relevance & mask)
chartMenu->addAction(GcWindows[i].name);
}
}
void
MainWindow::actionClicked(int index)
{
switch(index) {
default:
case 0: currentAthleteTab->addIntervals();
break;
case 1 : splitRide();
break;
case 2 : deleteRide();
break;
}
}
src/Gui/AbstractView.h
I have added a view string attribute to the AbstractView class
const QString view; // type of view: "train", "analysis", "diary", "home", "equipment"
and in each View's constructor in Views.cpp they each pass in their view name and description
AnalysisView::AnalysisView(Context *context, QStackedWidget *controls) :
AbstractView(context, VIEW_ANALYSIS, "analysis", "Compare Activities and Intervals")
this removes the need for the case statements in AbstractView:
QString view = "none";
switch(type) {
case VIEW_ANALYSIS: view = "analysis"; break;
case VIEW_TRAIN: view = "train"; break;
case VIEW_DIARY: view = "diary"; break;
case VIEW_TRENDS: view = "home"; break;
As the view string attribute can be used directly as it is already defined for the view
src/Gui/Views.h
Each view has a hw perspective attribute defined that is never used and has been deleted:
Perspective *hw;
Thanks for this development, @paulj49457; the new interface (compared with #4466) is excellent. I am configuring it, 'translating' my tests with that other PR. I haven't found a way to use the sharing equipment between equipment links functionality. For example, I do not see the way to share a power meter with two bicycles. Or, in my case, I have a treadmill, and sometimes I run with running shoes A and sometimes with running shoes B. In #4466 I defined two equipmentLinks: IndoorA and IndoorB, with shared equipments: IndoorA had Treadmill and running shoes A, and IndoorB had Treadmill and running shoes B,so each shered equipment accounted kilometers accordingly. And sometimes I run outdoor, so I had the equivalent equipment links, to account for the running shoes accordingly.
As a solution, in case sharing equipments is not worth being implemented in this new design, it could be solved if the metadata field was a multiselect field; in fact, it could be better, specifying the equipment list per activity. Cleaner, IMHO, that defining equipment links for each combination of equiqments.
Thanks for this great job!
Hi @peret2000, Thank you for the feedback and I'm currently working on:
- Adding the reference item functionality to the tab version, so that a tile can have a list of equipment links each with a date window, and the equipment page will now become just a convenient way to group items, its title will no longer need to be the equipment link name.
- Additionally, I'll now look supporting multiple equipment link values in an activity, so the metadata field is a multiselect field.
I think given these changes your shared a power meter with two bicycles case can be solved by bullet 1, so:
Activities [Eq Link] Equipment Tile [Eq Link]
Activity1: [Bike 1] ------------> Power Meter Tile: [Bike 1 - All dates, _Bike 2 - All dates]
Activity2: [Bike 2] ------------> Power Meter Tile: [Bike 1 - All dates, _Bike 2 - All dates]
Activity3: [Bike 1] ------------> Power Meter Tile: [Bike 1 - All dates, _Bike 2 - All dates]
etc
and your shoes A/B on the treadmill by bullet 2
Activities [Eq Link] Equipment Tile [Eq Link]
Activity1: [Treadmill, ShoesA] ------------> Shoes A Tile: [Shoes A - All dates]
------------> Treadmill Tile: [Treadmill - All dates]
Activity2: [Treadmill, ShoesB] ------------> Shoes B Tile: [Shoes B - All dates]
------------> Treadmill Tile: [Treadmill - All dates]
Hello @paulj49457 and thanks for working in this solution. I see this solution as better than the previous one (albeit I have not tried it). After the comments of @peret2000 I like the new proposal of having a tile that goups the equipment rather than creating new equipmnent links as, as time passes and equipment is replaced, this can be a non optimal approach of managing multiple equipment links with multiple names.
Just one thing I'd like to have is "equipment type" to have a perspective of all the shoes I'have or had, for example. But This could be done with tile being a equipment links.
Could we assign automatically equipment based on sport/subsport?
@ocellz & @peret2000 please see updates in description & latest commit
Great! I am testing it, and it is really powerful, with the new update for sharing equipment, and multi equipment activities. I have found two small issues, in case you want to make some changes:
-
The filter bar is not taken into accout. To be consistent with the rest of the screens (activities and trends), it would be nice to consider just the filtered activities, if there is some active filter
-
In a chart with more than one Eq Link Summary tiles, each one referencing a different EqLink, all the cummulative fields account for the same amount: the total number of activities, distance, etc. With the exception of the number of activities per athlete, that matches correctly in every each Summary tile for its EqLink. Just if you go to the settings of a tile (the screw) and press close 'Close', the figures of that summary become correct, until you switch to other chart, for example.
The rest of the functionality is terrific. Thanks for the tool!
Great! I am testing it, and it is really powerful, with the new update for sharing equipment, and multi equipment activities. I have found two small issues, in case you want to make some changes:
- The filter bar is not taken into accout. To be consistent with the rest of the screens (activities and trends), it would be nice to consider just the filtered activities, if there is some active filter
- In a chart with more than one Eq Link Summary tiles, each one referencing a different EqLink, all the cummulative fields account for the same amount: the total number of activities, distance, etc. With the exception of the number of activities per athlete, that matches correctly in every each Summary tile for its EqLink. Just if you go to the settings of a tile (the screw) and press close 'Close', the figures of that summary become correct, until you switch to other chart, for example.
The rest of the functionality is terrific. Thanks for the tool!
Thanks for the feedback, I'll take a look at the Eq Link Summary tiles issue and have a think about the filter bar. Also soon I'll have an update that allows tiles to be moved between equipment pages and to be cloned, I'm just testing it at the moment.
@ocellz & @peret2000 Tile cloning and Tile moves between pages added, Metadata quick entry is included, plus protection from special characters in the notes fields for json. I have updated the description and I think this now almost complete.....
@peret2000 I'm still undecided on the filtering, I'll wait for more feedback, and maybe you can provide some examples when it would be required.
Works nice the clone and move functionality. I'll be handy, I'm sure.
Regarding the flltering, I do not know if it is useful in the context of equipment cumulative distances, etc. The other screens (activities and trends) are always considering the active filters, so anyone relies on the figures, that are consistent among screens and affected by the activities covered by the filter. It is just that; in my opinion, it is not relevant, but I also think that it could be confusing if somebody is applying a filter and the equipment screen does not reflect it
@peret2000 Please see the latest commit, as there is a bug if you start-up GC then quickly switch to equipment, as sometimes a perspective window appeared which should just be cancelled. As the equipment page uses a single hidden perspective to manage the charts. Its odd as it doesn't appear on my development machine, but it does on my main Windows PC, I've fixed this now.
Maybe the solution for the search/filtering on the equipment page is to automatically hide the toolbar containing the search/filter, and restore it (if required) when Train, Activities, etc are selected.
Working ok. I did not notice that bug, anyway. The filtering solution is ok, I am not a user of filtering, only to detect errors in activities. What I see convinient, if you agree, is the total computations on the equipment link tiles, that are summing up all the figures of all the equipment links that are present in the chart. When modifying one, it shows correct figures, until you switch and back from other chart. I can show you examples it is weird to explain
Working ok. I did not notice that bug, anyway. The filtering solution is ok, I am not a user of filtering, only to detect errors in activities. What I see convinient, if you agree, is the total computations on the equipment link tiles, that are summing up all the figures of all the equipment links that are present in the chart. When modifying one, it shows correct figures, until you switch and back from other chart. I can show you examples it is weird to explain
Hi @peret2000 Thank you for the testing, I have found the issue from your description and fixed the summary tile issue.
@paulj49457 , it iw working perfectly. Now, all the figures are correct, no matter the equipment link tiles there are in a chart. That is a very good commit, as it makes the tool really useful. I will continue to test, and if I find something or have some suggestion, I will let you know. Thanks a lot for this job
Is there a need to upload Equipment Charts to the cloud? As I need to implement or disable this in the following functions for Equipment views:
#ifdef GC_HAS_CLOUD_DB
void
MainWindow::exportChartToCloudDB()
{}
void
MainWindow::addChartFromCloudDB()
{}
A very nice solution, especially the tiles. Here are my thoughts:
- By accident I deleted a tile and therefore lost all of its data. Could the equipment be stored outside the chart and just be referenced by the tiles? I expect this to give less surprises to the user
- It seems like the Equipment Links can't be nested. My usecase is: Take a bike with two different wheelsets, each one with its own tires, cassette and disc. As of today swapping the wheelset requires also reconfiguring tires, cassette and discs on the bike. An aggregate wheelset (referencing these items) would be easier to handle
Additionally I have some feature requests :), probably for the future:
- A checkbox "retire" would be helpful to signal the definitive end of live, in contrast to a currently not mounted equipment (i.e. mountain wheelset)
- An additional field "maintenance / notes", similar to equipment link, including a date. This could be used for stuff like
- "Cracking noise" since ... (maybe with an end-date) as support to identify all measures that might have lead to or resolved the issue
- Greased pedal threads on ...
- Waxed chain on ...
- A reverse-link-view: Which equipment is currently linked to my Bike?
Sorry for my late comment, I hope I am not too late to the party
Hi @thejockl
Thank you for the feedback, I have aimed to keep it simple and generic as possible initially, if enough people want it and becomes a feature of GC, then some more specific tiles and features can be added.
Regarding your lost data, storing the data outside of the tiles creates another relationship between the data and view, which would create a nice MVC pattern, but does create more code and complexity, and given that each tile doesn't hold much data storing it with the tile & charts seems ok. Exporting your chart(s) is another way to backup your data. If the majority of feedback is in that direction then it can be done. Maybe a simple answer is a "Are your really sure? " popup, but they soon become annoying.
To solve your aggregate wheelset problem, just create an Equipment Link for the set say "Wheelset1", and use that in the tiles for the wheels, tyres, cassette, etc, then add it your activities equipment link say: Bike1, Wheelset1. You can have more than one equipment link name for an activity, they just need to be comma separated, unfortunately the auto completion doesn't work so well with multiple names.
A work around for the retirement issue, would be to create a page(s) for your retired kit and using the popup menu to move the tile across to the page. Although for me, once a piece of equipment is worn out the item goes in the recycling and I no longer need to track it. I use the notes tile as a service history page so I can get an idea of how long a chain or tyres last.
The notes tile was aimed at capturing the service history, and you can increase the width of the notes tile (shift + click drag on the righthand edge). Its free format so can structure it as you wish, again if a more featured tile is required to track service history, then this can be added.
Given the Equipment pages create a new athlete and activity independent view, I wanted to keep it simple initially so that any interaction with existing functionality could be understood, questions I still have are:
i) Should you be able to export equipment charts to the cloud, are they likely to be shared? ii) Should the toolbar filter apply to the equipment view? Or should it be automatically hidden. iii) Should all the menu options like sidebar toggle etc be hidden in Equipment mode?
Hi @thejockl
I have now added a history tile with dates & text as you suggested, for the recording of "maintenance / notes". Can you please test and let me know if its missing any functionality.
I have just noticed the History tile cloning doesn't work, other than that its fine, I'll fix it later.
@paulj49457, thanks a lot for this addition, works like expected and I am sure it will help me a lot (my current cracking noise disappeared after greasing the thru axles threads, using this feature will help documenting this fix for future maintenance)
As always I have comments :o
- In Qt6 qSort was removed (see https://doc.qt.io/qt-5/qtalgorithms-obsolete.html#qSort-1), replacing it in Charts/OverviewEquipmentItems.cpp by std::sort (same signature) made it compile again, both for Qt5 and Qt6
- Can you make the tile scrollable in the case the history grows, similar to the "Table"-tile in Trends view?
- As most maintenance will probably be documented promptly, defaulting the date selector to today would improve UX
@paulj49457, thanks a lot for this addition, works like expected and I am sure it will help me a lot (my current cracking noise disappeared after greasing the thru axles threads, using this feature will help documenting this fix for future maintenance)
As always I have comments :o
- In Qt6 qSort was removed (see https://doc.qt.io/qt-5/qtalgorithms-obsolete.html#qSort-1), replacing it in Charts/OverviewEquipmentItems.cpp by std::sort (same signature) made it compile again, both for Qt5 and Qt6
- Can you make the tile scrollable in the case the history grows, similar to the "Table"-tile in Trends view?
- As most maintenance will probably be documented promptly, defaulting the date selector to today would improve UX
@thejockl Thanks for the suggestion on the history tile, I'll update it with scrolling, I have already fixed the qsort as I'm building against qt5.15 & today's date on new entries.
Fixes and updates in the latest commit:
- History tile entries default to today's date
- qsort removed and replaced with std::sort
- Fixed for the athlete tabbar being set for display on GC restart, when GC closed from the equipment view
- History & Notes tiles scrolling, adapts for thin/wide tile sizes
- Notes tile expansion
- Simplified equipment view's implementation of temporary modifications to view menu to maintain consistency with the displayed equipment window
I think this now complete and ready consideration/review, unless there is any more feedback?
I am using this tool for some time and it fits all the requirements I can came up with. There may be other approaches or design or integration, but this is the one implemented and happy to have it. Thanks a lot for your work. If I could ask for a cosmetic issue, if not late yet, I'd ask for the possibility of formatting the numbers with the thousands sepatator. At a first glance, some figures are difficult to distinguish, if they are tens or hundreds of thousands. Thanks for this tool!
@peret2000 Thank you for the feedback, and I agree that a thousands separator is required, I'll update the PR
On my Linux system I have 2 issues with the latest version A compilation error in OverviewEquipmentItems.cpp line 1318: The colon must be put in single quotes (char) A crash when adding a new "Equipment Overview" on a fully fresh user (deleted .goldencheetah before start), see the trace below. I will try debugging further into this
(gdb) backtrace
#0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x00007fffea49debf in __pthread_kill_internal (threadid=<optimized out>, signo=6) at ./nptl/pthread_kill.c:78
#2 0x00007fffea449c82 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x00007fffea4324f0 in __GI_abort () at ./stdlib/abort.c:79
#4 0x00007fffeaad56c2 in qAbort() () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#5 0x00007fffeab22940 in ??? () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#6 0x00007fffeaad61cb in QMessageLogger::fatal(char const*, ...) const () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#7 0x00007fffeaad6227 in qt_assert(char const*, char const*, int) () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#8 0x00005555558d5e9a in QString::at (this=0x7fffffff9650, i=48) at /usr/include/x86_64-linux-gnu/qt6/QtCore/qstring.h:1080
#9 0x00005555558cc728 in CommonEquipmentItem::setupScrollableText (this=0x55555ac950c0, fm=..., tileText=..., rowTextMap=..., rowOffset=0) at Charts/OverviewEquipmentItems.cpp:699
#10 0x00005555558d1dba in EquipmentHistory::itemGeometryChanged (this=0x55555ac950c0) at Charts/OverviewEquipmentItems.cpp:1267
#11 0x0000555555852d05 in ChartSpaceItem::geometryChanged (this=0x55555ac950c0) at Gui/ChartSpace.cpp:277
#12 0x00005555562d6c0c in ChartSpaceItem::qt_static_metacall (_o=0x55555ac950c0, _c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x7fffffff9898) at .moc/moc_ChartSpace.cpp:117
#13 0x00007fffeabd1ce8 in ??? () at /lib/x86_64-linux-gnu/libQt6Core.so.6
#14 0x00007ffff6b78c70 in QGraphicsWidget::setGeometry(QRectF const&) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#15 0x0000555555855474 in ChartSpace::updateGeometry (this=0x555560485e50) at Gui/ChartSpace.cpp:625
#16 0x00005555558b7f3c in OverviewWindow::setConfiguration (this=0x555561737860, config=...) at Charts/Overview.cpp:581
#17 0x0000555556043996 in GcWindowDialog::GcWindowDialog (this=0x7fffd400a330, type=GcWindowTypes::OverviewEquipment, context=0x555557650230, here=0x7fffffffb130, sidebar=false, use=0x0)
at Gui/Perspective.cpp:1371
#18 0x000055555604062d in Perspective::appendChart (this=0x55555857d580, id=GcWindowTypes::OverviewEquipment) at Gui/Perspective.cpp:649
Seems to be a simple one in OverviewEquipmentItems.cpp:697:
The comparison <= in the while-loop goes one index too far, exceeding the tileText. Changing it to < fixes the crash for me:
int i = 0;
while (i < tileText.length())
{
chr = tileText.at(i);
@thejockl Thank you for the testing & bug fixes, they are in the latest commit.
I'm sorry, I have rebased this PR upon the latest GC commit, instead I should have merged, doh! All the history of the commits has been retained, and additionally this now uses the editable metadata tile icon approach from PR https://github.com/GoldenCheetah/GoldenCheetah/pull/4519
- Fixed crash caused by adding numerous equipment links and editing them out of sequence, which caused the datachange() sorting to create a mismatch between the QtTableWidget and the EquipmentItem's internal list, the list is now sorted when the dialog is closed using setData().
- Improved sort of equipment links to use date as a secondary level sort
- Add new equipment links entries & new history items to the top of the tables, removes the need to scroll when the window is full.
- Correct misleading set/unset button names, so they reflect the action that will be completed when pressed, reset/set
I have noticed that color of the tiles are not saved with the chart. Every time GC is opened, tiles have all the same color (dark, white,...) no matter if there have been made changes in th e tiles; I guess the default color depends on the general theme. If they are cloned, also the color is not cloned.
Tile colour saving & tracking of theme changes should now be fixed.
I am closing this since there seems to be no interest from end users, and to store data at the view components level is not a good match for GoldenCheetah.