Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 120 additions & 22 deletions src/Home.qml
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ HomeForm {
model: appModel
leftMargin: { if(OS_VERSION === "Android") (Screen.width % cellWidth) / 2; else (parent.width % cellWidth) / 2; }
anchors.topMargin: (!window.lockTiles ? rootItem.topBarHeight + 30 : 0)
interactive: !window.lockTiles
id: gridView
objectName: "gridview"
onMovementEnded: { headerToolbar.visible = (contentY == 0) || window.lockTiles; }
Expand Down Expand Up @@ -320,15 +321,6 @@ HomeForm {
Accessible.description: largeButton ? largeButtonLabel : (secondLine !== "" ? secondLine : (writable ? qsTr("Adjustable. Current value: ") + value : qsTr("Current value: ") + value))
Accessible.focusable: true

Behavior on x {
enabled: id1.state != "active"
NumberAnimation { duration: 400; easing.type: Easing.OutBack }
}

Behavior on y {
enabled: id1.state != "active"
NumberAnimation { duration: 400; easing.type: Easing.OutBack }
}

SequentialAnimation on rotation {
NumberAnimation { to: 2; duration: 60 }
Expand All @@ -340,10 +332,10 @@ HomeForm {

states: State {
name: "active"; when: loc.currentId === gridId && window.lockTiles
PropertyChanges { target: id1; x: loc.mouseX - gridView.x - width/2; y: loc.mouseY - gridView.y - height/2; scale: 0.5; z: 10 }
PropertyChanges { target: id1; opacity: 0.3 }
}

transitions: Transition { NumberAnimation { property: "scale"; duration: 200} }
transitions: Transition { NumberAnimation { property: "opacity"; duration: 200} }

Rectangle {
width: 168 * settings.ui_zoom / 100
Expand Down Expand Up @@ -630,27 +622,133 @@ HomeForm {
}
}

Item {
id: ghostTile
visible: loc.currentId !== -1 && window.lockTiles
x: loc.mouseX - width / 2
y: loc.mouseY - height / 2
width: 85 * settings.ui_zoom / 100
height: 63 * settings.ui_zoom / 100
z: 200

Rectangle {
anchors.fill: parent
radius: 3
color: settings.theme_tile_background_color
opacity: 0.9
border.width: 2
border.color: settings.theme_tile_shadow_color

Text {
anchors.centerIn: parent
color: "white"
text: loc.tileName
font.pointSize: 10 * settings.ui_zoom / 100
font.bold: true
horizontalAlignment: Text.AlignHCenter
width: parent.width - 8
wrapMode: Text.WordWrap
}
}
}

Timer {
id: autoScrollTimer
interval: 50
repeat: true
running: false
property real scrollSpeed: 15
onTriggered: {
if (loc.currentId === -1) { running = false; return; }
var edgeZone = 80
if (loc.mouseY > gridView.height - edgeZone) {
var factor = (loc.mouseY - (gridView.height - edgeZone)) / edgeZone
gridView.contentY = Math.min(
gridView.contentHeight - gridView.height,
gridView.contentY + scrollSpeed * (1 + factor * 2)
)
} else if (loc.mouseY < edgeZone) {
var factor2 = (edgeZone - loc.mouseY) / edgeZone
gridView.contentY = Math.max(0, gridView.contentY - scrollSpeed * (1 + factor2 * 2))
} else {
running = false
}
}
}

MouseArea {
property int currentId: -1 // Original position in model
property int newIndex // Current Position in model
property int index: (Math.floor(gridView.width / gridView.cellWidth) * Math.floor(mouseY / gridView.cellHeight)) + Math.floor(mouseX / gridView.cellWidth) // gridView.indexAt(mouseX - gridView.x, mouseY - gridView.y) // Item underneath cursor
property int currentId: -1
property int newIndex
property int startIndex: -1
property string tileName: ""
property real lastScrollY: 0
property bool isSwiping: false

function indexAtMouse(mx, my) {
var cols = Math.max(1, Math.floor(gridView.width / gridView.cellWidth))
var adjustedY = my + gridView.contentY
var col = Math.floor(mx / gridView.cellWidth)
var row = Math.floor(adjustedY / gridView.cellHeight)
var idx = row * cols + col
if (idx < 0 || idx >= appModel.count) return -1
return idx
}

id: loc
enabled: window.lockTiles
anchors.fill: parent
onPressAndHold: { console.log("onPressAndHold " + index); if(index !== -1) currentId = appModel[newIndex = index].gridId; else currentId = -1; }

onPressed: {
lastScrollY = mouseY
isSwiping = false
}

onPressAndHold: {
if (isSwiping) return
var idx = indexAtMouse(mouseX, mouseY)
if (idx !== -1) {
startIndex = idx
newIndex = idx
currentId = appModel[idx].gridId
tileName = appModel[idx].name
} else {
currentId = -1
tileName = ""
}
}

onReleased: {
console.log("onReleased " + currentId + " " + index );
if (currentId !== -1 && index !== -1 && index !== newIndex) {
rootItem.moveTile(appModel[currentId].name, index, newIndex);
} currentId = -1
autoScrollTimer.running = false
if (currentId !== -1) {
var idx = indexAtMouse(mouseX, mouseY)
if (idx !== -1 && idx !== startIndex)
rootItem.moveTile(tileName, idx, startIndex)
}
currentId = -1
startIndex = -1
tileName = ""
isSwiping = false
}

onPositionChanged: {
console.log("onPositionChanged " + currentId + " " + index + " " + newIndex + " " + mouseX + " " + mouseY)
if (currentId !== -1 && index !== -1 && index !== newIndex) {
//appModel.move(newIndex, newIndex = index)
if (currentId === -1) {
// No drag in progress: scroll the grid like a normal flick
var dy = mouseY - lastScrollY
if (Math.abs(dy) > 5) isSwiping = true
gridView.contentY = Math.max(0,
Math.min(gridView.contentHeight - gridView.height,
gridView.contentY - dy))
lastScrollY = mouseY
return
}
var edgeZone = 80
if (mouseY > gridView.height - edgeZone || mouseY < edgeZone)
autoScrollTimer.running = true
else
autoScrollTimer.running = false

var idx = indexAtMouse(mouseX, mouseY)
if (idx !== -1 && idx !== newIndex) newIndex = idx
}
}
}
40 changes: 21 additions & 19 deletions src/homeform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) {
true, QStringLiteral("peloton_remaining"), valueElapsedFontSize, labelFontSize);
strokesCount = new DataObject(tr("Strokes Count"), QStringLiteral("icons/icons/cadence.png"),
QStringLiteral("0"), false, QStringLiteral("strokes_count"), 48, labelFontSize);
strokesLength = new DataObject(tr("Stroke Length"), QStringLiteral("icons/icons/cadence.png"),
strokesLength = new DataObject(tr("Strokes Length"), QStringLiteral("icons/icons/cadence.png"),
QStringLiteral("0"), false, QStringLiteral("strokes_length"), 48, labelFontSize);
gears = new DataObject(tr("Gears"), QStringLiteral("icons/icons/elevationgain.png"),
QStringLiteral("0"), true, QStringLiteral("gears"), 48, labelFontSize);
Expand Down Expand Up @@ -4537,35 +4537,37 @@ void homeform::moveTile(QString name, int newIndex, int oldIndex) {
if (current) {
qDebug() << "moveTile" << name << newIndex << oldIndex;

foreach (QString s, settings.allKeys()) {
if (s.contains(QStringLiteral("tile_")) && s.contains(QStringLiteral("_order"))) {

qDebug() << s << settings.value(s);
}
}
// Some DataObject m_ids don't match their QZSettings _order key (camelCase vs snake_case).
// This lambda returns the correct settings key for a given DataObject.
auto orderKey = [](const DataObject *d) -> QString {
static const QHash<QString, QString> overrides = {
{QStringLiteral("avgWattLap"), QStringLiteral("tile_avg_watt_lap_order")},
{QStringLiteral("joul"), QStringLiteral("tile_jouls_order")},
{QStringLiteral("steeringangle"), QStringLiteral("tile_steering_angle_order")},
{QStringLiteral("stride_length"), QStringLiteral("tile_instantaneous_stride_length_order")},
{QStringLiteral("external_inclination"),QStringLiteral("tile_ext_incline_order")},
{QStringLiteral("target_inclination"), QStringLiteral("tile_target_incline_order")},
};
auto it = overrides.constFind(d->m_id);
if (it != overrides.constEnd()) return it.value();
return QStringLiteral("tile_") + d->m_id.toLower() + QStringLiteral("_order");
};

int i = 0;
foreach (QObject *d, dataList) {
if (i == newIndex) {
settings.setValue("tile_" + current->m_id.toLower() + "_order", i);
settings.setValue(orderKey(current), i);
i++;
}
QString n = ((DataObject *)d)->m_id;
if (((DataObject *)d)->name().compare(name)) {
settings.setValue("tile_" + n.toLower() + "_order", i);
settings.setValue(orderKey((DataObject *)d), i);
i++;
}
}

foreach (QString s, settings.allKeys()) {
if (s.contains(QStringLiteral("tile_")) && s.contains(QStringLiteral("_order"))) {

qDebug() << s << settings.value(s);
}
if (i <= newIndex) {
settings.setValue(orderKey(current), newIndex);
}

// sortTiles();
// dataList.move(oldIndex, newIndex);
// very dirty, but i needed a way to synchronize QML with C++
QTimer::singleShot(100, this, &homeform::sortTilesTimeout);
}
Expand Down Expand Up @@ -10760,7 +10762,7 @@ void homeform::sendMail() {
((rower *)bluetoothManager->device())->maxPace().toString(QStringLiteral("m:ss")) +
QStringLiteral("\n");
textMessage +=
QStringLiteral("Average Stroke Length: ") +
QStringLiteral("Average Strokes Length: ") +
QString::number(((rower *)bluetoothManager->device())->currentStrokesLength().average(), 'f', 1) + "\n";
} else if (bluetoothManager->device()->deviceType() == TREADMILL || bluetoothManager->device()->deviceType() == ELLIPTICAL) {
textMessage += QStringLiteral("Average Pace: ") +
Expand Down