Skip to content

Commit 709fa3e

Browse files
cagnuleingithub-actions[bot]claude
authored
Detailed Bug Report: Running Workout Incline Parsing Issue & CORE Sensor Garmin Sync Failure (#4663)
* Detailed Bug Report: Running Workout Incline Parsing Issue & CORE Sensor Garmin Sync Failure * zwo xml decision and inclinaion handled even with 1% instead of 0.01 * 28/5/2026 mail * prevent overwriting of intervals and garmin files * paste from clipboard * workout subfolders, delete and garmin multiple sync * swipe for delete * clipboard from the homescreen * workout preview after clipboard * Update TrainingProgramsListJS.qml * Update TrainingProgramsListJS.qml * Add startup workout fetch settings * chore: update translation strings [automated] Automatic update of translatable strings extracted from source code. Updated 30 language files in src/translations/ - Updated by GitHub Actions (Testing Mode) - Triggered by: pull_request - Date: 2026-06-08 09:42:55 UTC * Update qzsettings.cpp * Handle SmartBike manual resistance power table (#4697) * Handle SmartBike manual resistance power table * Route SmartBike workout targets through custom table * Apply cadence scaling to custom resistance watts * Keep SmartBike workout targets manual-only * Narrow SmartBike target resistance handling * cleaning code * fix: pre-generate .qm translation files before Windows builds On Windows with MSVC/MinGW, qmake places compiled .qm files in translations/debug/ (for debug builds), but translations.qrc references them at translations/xxx.qm. This causes NMAKE to fail with U1073: "don't know how to make translations\qdomyos-zwift_vi.qm". Add explicit `lrelease src/qdomyos-zwift.pri` before qmake in all Windows CI build steps, mirroring the same approach already used for Linux and Android builds. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * HR program stuck in one gear (Issue #3897) #3897 * untraslatable terms * Update qdomyos-zwift_ja.ts * normalize zwo with 0.4 instead of 0.6 and prompt for deleting clipboard workouts * ignoring languages * chore: update translation strings [automated] Automatic update of translatable strings extracted from source code. Updated 30 language files in src/translations/ - Updated by GitHub Actions (Testing Mode) - Triggered by: pull_request - Date: 2026-06-09 11:51:08 UTC --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9741df9 commit 709fa3e

54 files changed

Lines changed: 43791 additions & 44882 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/TrainingProgramsList.qml

Lines changed: 96 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,54 @@ import QtQuick.Dialogs 1.0
77
import QtCharts 2.2
88
import Qt.labs.settings 1.0
99

10-
ColumnLayout {
11-
signal trainprogram_open_clicked(url name)
12-
signal trainprogram_open_other_folder(url name)
13-
signal trainprogram_preview(url name)
14-
Loader {
15-
id: fileDialogLoader
16-
active: false
10+
ColumnLayout {
11+
signal trainprogram_open_clicked(url name)
12+
signal trainprogram_open_other_folder(url name)
13+
signal trainprogram_preview(url name)
14+
signal trainprogram_autostart_requested()
15+
property url selectedWorkoutUrl: ""
16+
property url initialWorkoutUrl: ""
17+
18+
function openWorkoutPreview(fileUrl) {
19+
if (!fileUrl || fileUrl.toString() === "") {
20+
return
21+
}
22+
selectedWorkoutUrl = fileUrl
23+
trainprogram_preview(fileUrl)
24+
powerSeries.clear();
25+
for(var i=0;i<rootItem.preview_workout_points;i+=10)
26+
{
27+
powerSeries.append(i * 1000, rootItem.preview_workout_watt[i]);
28+
}
29+
rootItem.update_chart_power(powerChart);
30+
}
31+
32+
Component.onCompleted: {
33+
Qt.callLater(function() {
34+
openWorkoutPreview(initialWorkoutUrl)
35+
})
36+
}
37+
38+
MessageDialog {
39+
id: deleteDialog
40+
text: "Delete workout?"
41+
informativeText: "This cannot be undone."
42+
buttons: (MessageDialog.Yes | MessageDialog.No)
43+
onYesClicked: {
44+
if (rootItem.deleteTrainingProgramFile(selectedWorkoutUrl)) {
45+
selectedWorkoutUrl = ""
46+
var currentFolder = folderModel.folder
47+
folderModel.folder = ""
48+
folderModel.folder = currentFolder
49+
}
50+
visible = false
51+
}
52+
onNoClicked: visible = false
53+
}
54+
55+
Loader {
56+
id: fileDialogLoader
57+
active: false
1758
sourceComponent: Component {
1859
FileDialog {
1960
title: "Please choose a file"
@@ -174,22 +215,25 @@ ColumnLayout {
174215
}*/
175216
}
176217
focus: true
177-
onCurrentItemChanged: {
178-
let fileUrl = folderModel.get(list.currentIndex, 'fileUrl') || folderModel.get(list.currentIndex, 'fileURL');
179-
if (fileUrl) {
180-
list.currentItem.textColor = Material.color(Material.Yellow)
181-
console.log(fileUrl + ' selected');
182-
trainprogram_preview(fileUrl)
218+
onCurrentItemChanged: {
219+
let fileUrl = folderModel.get(list.currentIndex, 'fileUrl') || folderModel.get(list.currentIndex, 'fileURL');
220+
if (fileUrl && !folderModel.isFolder(list.currentIndex)) {
221+
selectedWorkoutUrl = fileUrl
222+
list.currentItem.textColor = Material.color(Material.Yellow)
223+
console.log(fileUrl + ' selected');
224+
trainprogram_preview(fileUrl)
183225
powerSeries.clear();
184226
for(var i=0;i<rootItem.preview_workout_points;i+=10)
185227
{
186228
powerSeries.append(i * 1000, rootItem.preview_workout_watt[i]);
187229
}
188230
rootItem.update_chart_power(powerChart);
189-
//trainprogram_open_clicked(fileUrl);
190-
//popup.open()
191-
}
192-
}
231+
//trainprogram_open_clicked(fileUrl);
232+
//popup.open()
233+
} else {
234+
selectedWorkoutUrl = ""
235+
}
236+
}
193237
Component.onCompleted: {
194238

195239
}
@@ -298,19 +342,41 @@ ColumnLayout {
298342
}
299343
}
300344

301-
Button {
302-
id: searchButton
303-
height: 50
304-
width: parent.width
305-
text: "Other folders"
306-
Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter
307-
onClicked: {
308-
console.log("folder is " + rootItem.getWritableAppDir() + 'training')
309-
// Create a fresh FileDialog instance
310-
fileDialogLoader.active = true
311-
}
312-
anchors {
313-
bottom: parent.bottom
345+
RowLayout {
346+
height: 50
347+
width: parent.width
348+
Layout.alignment: Qt.AlignCenter | Qt.AlignVCenter
349+
350+
Button {
351+
Layout.fillWidth: true
352+
text: "Start Workout"
353+
visible: selectedWorkoutUrl != ""
354+
onClicked: {
355+
trainprogram_open_clicked(selectedWorkoutUrl)
356+
trainprogram_autostart_requested()
357+
}
358+
}
359+
360+
Button {
361+
id: deleteButton
362+
Layout.fillWidth: true
363+
text: "Delete"
364+
visible: selectedWorkoutUrl != ""
365+
onClicked: deleteDialog.visible = true
366+
}
367+
368+
Button {
369+
id: searchButton
370+
Layout.fillWidth: true
371+
text: "Other folders"
372+
onClicked: {
373+
console.log("folder is " + rootItem.getWritableAppDir() + 'training')
374+
// Create a fresh FileDialog instance
375+
fileDialogLoader.active = true
376+
}
377+
}
378+
anchors {
379+
bottom: parent.bottom
314380
}
315381
}
316382
}

src/TrainingProgramsListJS.qml

Lines changed: 67 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ ColumnLayout {
1515
signal trainprogram_autostart_requested()
1616

1717
property url pendingWorkoutUrl: ""
18+
property url initialWorkoutUrl: ""
1819

1920
Settings {
2021
id: settings
@@ -24,6 +25,21 @@ ColumnLayout {
2425
property var selectedFileUrl: ""
2526
property bool isSearching: false
2627

28+
function openWorkoutPreview(fileUrl) {
29+
if (!fileUrl || fileUrl.toString() === "") {
30+
return
31+
}
32+
pendingWorkoutUrl = fileUrl
33+
trainprogram_preview(fileUrl)
34+
stackView.push(detailView)
35+
}
36+
37+
Component.onCompleted: {
38+
Qt.callLater(function() {
39+
openWorkoutPreview(initialWorkoutUrl)
40+
})
41+
}
42+
2743
// Model for search results
2844
ListModel {
2945
id: searchResultsModel
@@ -79,6 +95,24 @@ ColumnLayout {
7995
}
8096
}
8197

98+
MessageDialog {
99+
id: deleteDialog
100+
property url fileUrl: ""
101+
text: "Delete workout?"
102+
informativeText: "This cannot be undone."
103+
buttons: (MessageDialog.Yes | MessageDialog.No)
104+
onYesClicked: {
105+
if (rootItem.deleteTrainingProgramFile(fileUrl)) {
106+
pendingWorkoutUrl = ""
107+
isSearching = false
108+
stackView.clear()
109+
stackView.push(masterView)
110+
}
111+
visible = false
112+
}
113+
onNoClicked: visible = false
114+
}
115+
82116
StackView {
83117
id: stackView
84118
Layout.fillWidth: true
@@ -157,22 +191,29 @@ ColumnLayout {
157191

158192
model: isSearching ? searchResultsModel : folderModel
159193

160-
delegate: Rectangle {
194+
delegate: ItemDelegate {
195+
id: workoutDelegate
161196
width: ListView.view.width
162197
height: 50
163-
color: ListView.isCurrentItem ? Material.color(Material.Green, Material.Shade800) : Material.backgroundColor
164198

165199
// Determine item properties based on which model is active
166200
property bool isItemFolder: isSearching ? model.isFolder : folderModel.isFolder(index)
167201
property string itemFileName: isSearching ? model.fileName : folderModel.get(index, "fileName")
168202
property string itemFileUrl: isSearching ? model.filePath : (folderModel.get(index, 'fileUrl') || folderModel.get(index, 'fileURL'))
169203
property string itemRelativePath: isSearching ? model.relativePath : ""
170204

171-
RowLayout {
172-
anchors.fill: parent
173-
anchors.margins: 10
205+
background: Rectangle {
206+
color: ListView.isCurrentItem ? Material.color(Material.Green, Material.Shade800) : Material.backgroundColor
207+
}
208+
209+
contentItem: RowLayout {
174210
spacing: 10
175211

212+
Item {
213+
width: 10
214+
height: 1
215+
}
216+
176217
Text {
177218
id: fileIcon
178219
text: isItemFolder ? "📁" : "📄"
@@ -212,24 +253,17 @@ ColumnLayout {
212253
}
213254
}
214255

215-
MouseArea {
216-
anchors.fill: parent
217-
onClicked: {
218-
list.currentIndex = index
219-
220-
if (isItemFolder) {
221-
// Navigate to folder (only in browse mode)
222-
if (!isSearching) {
223-
folderModel.folder = itemFileUrl
224-
}
225-
} else if (itemFileUrl) {
226-
// Load preview and show detail view
227-
trainprogram_preview(itemFileUrl)
228-
pendingWorkoutUrl = itemFileUrl
229-
230-
// Wait for preview to load then push detail view
231-
detailViewTimer.restart()
256+
onClicked: {
257+
list.currentIndex = index
258+
259+
if (isItemFolder) {
260+
// Navigate to folder (only in browse mode)
261+
if (!isSearching) {
262+
folderModel.folder = itemFileUrl
232263
}
264+
} else if (itemFileUrl) {
265+
// Load preview and show detail view
266+
openWorkoutPreview(itemFileUrl)
233267
}
234268
}
235269
}
@@ -245,16 +279,6 @@ ColumnLayout {
245279
fileDialogLoader.active = true
246280
}
247281
}
248-
249-
// Timer to push detail view after preview loads
250-
Timer {
251-
id: detailViewTimer
252-
interval: 300
253-
repeat: false
254-
onTriggered: {
255-
stackView.push(detailView)
256-
}
257-
}
258282
}
259283
}
260284

@@ -278,6 +302,16 @@ ColumnLayout {
278302

279303
Item { Layout.fillWidth: true }
280304

305+
Button {
306+
text: "Delete"
307+
visible: pendingWorkoutUrl.toString() !== ""
308+
Material.background: Material.Red
309+
onClicked: {
310+
deleteDialog.fileUrl = pendingWorkoutUrl
311+
deleteDialog.visible = true
312+
}
313+
}
314+
281315
Button {
282316
text: "Start Workout"
283317
highlighted: true
@@ -288,6 +322,7 @@ ColumnLayout {
288322
stackView.pop()
289323
}
290324
}
325+
291326
}
292327

293328
// Descrizione workout

0 commit comments

Comments
 (0)