mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
Planned activities: Keeping track of original date (#4822)
* Planned activities: Keeping track of original date * Adding original date to planned activities * Resetting the original date when copying planned activities * Showing original planned date in calendar tooltips * Ensuring metrics get recalculated when moving, shifting, copying activities * Ensuring all tags are written when moving or shifting activities
This commit is contained in:
committed by
GitHub
parent
31d8708376
commit
a0fe8afa32
@@ -1006,12 +1006,18 @@ CalendarWindow::getActivities
|
|||||||
activity.isRelocatable = rideItem->planned;
|
activity.isRelocatable = rideItem->planned;
|
||||||
activity.hasTrainMode = rideItem->planned && sport == "Bike" && ! buildWorkoutFilter(rideItem).isEmpty();
|
activity.hasTrainMode = rideItem->planned && sport == "Bike" && ! buildWorkoutFilter(rideItem).isEmpty();
|
||||||
activity.dirty = rideItem->isDirty();
|
activity.dirty = rideItem->isDirty();
|
||||||
|
if (rideItem->planned) {
|
||||||
|
activity.originalPlanLabel = buildOriginalLabel(rideItem);
|
||||||
|
}
|
||||||
|
|
||||||
RideItem *linkedRide = context->athlete->rideCache->getLinkedActivity(rideItem);
|
RideItem *linkedRide = context->athlete->rideCache->getLinkedActivity(rideItem);
|
||||||
if (linkedRide != nullptr) {
|
if (linkedRide != nullptr) {
|
||||||
activity.linkedReference = linkedRide->fileName;
|
activity.linkedReference = linkedRide->fileName;
|
||||||
activity.linkedPrimary = getPrimary(linkedRide);
|
activity.linkedPrimary = getPrimary(linkedRide);
|
||||||
activity.linkedStartDT = linkedRide->dateTime;
|
activity.linkedStartDT = linkedRide->dateTime;
|
||||||
|
if (linkedRide->planned) {
|
||||||
|
activity.originalPlanLabel = buildOriginalLabel(linkedRide);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
activities[rideItem->dateTime.date()] << activity;
|
activities[rideItem->dateTime.date()] << activity;
|
||||||
@@ -1328,6 +1334,51 @@ CalendarWindow::findFreeSlot
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QString
|
||||||
|
CalendarWindow::buildOriginalLabel
|
||||||
|
(RideItem const * const item) const
|
||||||
|
{
|
||||||
|
QDate originalPlan = QDate::fromString(item->getText("Original Date", ""), "yyyy/MM/dd");
|
||||||
|
if (! originalPlan.isValid() || originalPlan == item->dateTime.date()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
QLocale locale;
|
||||||
|
QString unitLabel;
|
||||||
|
int days = originalPlan.daysTo(item->dateTime.date());
|
||||||
|
QChar sign = days > 0 ? '+' : '-';
|
||||||
|
ShowDaysAsUnit unit = showDaysAs(days);
|
||||||
|
int c = 0;
|
||||||
|
if (unit == ShowDaysAsUnit::Days) {
|
||||||
|
c = std::abs(days);
|
||||||
|
if (c == 1) {
|
||||||
|
unitLabel = tr("day");
|
||||||
|
} else {
|
||||||
|
unitLabel = tr("days");
|
||||||
|
}
|
||||||
|
} else if (unit == ShowDaysAsUnit::Weeks) {
|
||||||
|
c = daysToWeeks(days);
|
||||||
|
if (c == 1) {
|
||||||
|
unitLabel = tr("week");
|
||||||
|
} else {
|
||||||
|
unitLabel = tr("weeks");
|
||||||
|
}
|
||||||
|
} else if (unit == ShowDaysAsUnit::Months) {
|
||||||
|
c = daysToMonths(days);
|
||||||
|
if (c == 1) {
|
||||||
|
unitLabel = tr("month");
|
||||||
|
} else {
|
||||||
|
unitLabel = tr("months");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QString("%1 (%2%3 %4)")
|
||||||
|
.arg(locale.toString(originalPlan, QLocale::NarrowFormat))
|
||||||
|
.arg(sign)
|
||||||
|
.arg(c)
|
||||||
|
.arg(unitLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CalendarWindow::updateActivities
|
CalendarWindow::updateActivities
|
||||||
()
|
()
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ class CalendarWindow : public GcChartWindow
|
|||||||
QString getPrimary(RideItem const * const rideItem) const;
|
QString getPrimary(RideItem const * const rideItem) const;
|
||||||
QTime findFreeSlot(RideItem *sourceItem, QDate newDate, QTime time);
|
QTime findFreeSlot(RideItem *sourceItem, QDate newDate, QTime time);
|
||||||
QTime findFreeSlot(QList<std::pair<QTime, int>> busySlots, QTime targetTime, int requiredDurationSeconds) const;
|
QTime findFreeSlot(QList<std::pair<QTime, int>> busySlots, QTime targetTime, int requiredDurationSeconds) const;
|
||||||
|
QString buildOriginalLabel(RideItem const * const item) const;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void updateActivities();
|
void updateActivities();
|
||||||
|
|||||||
@@ -439,6 +439,7 @@ RideCache::removeRide(const QString& filenameToDelete) {
|
|||||||
context->notifyRideSelected(context->ride);
|
context->notifyRideSelected(context->ride);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refresh();
|
||||||
// model estimates (lazy refresh)
|
// model estimates (lazy refresh)
|
||||||
estimator->refresh();
|
estimator->refresh();
|
||||||
|
|
||||||
@@ -1187,21 +1188,38 @@ RideCache::moveActivity
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDate originalDate = QDate::fromString(ride->getTag("Original Date", ""), "yyyy/MM/dd");
|
||||||
|
if (! originalDate.isValid()) {
|
||||||
|
ride->setTag("Original Date", oldDateTime.date().toString("yyyy/MM/dd"));
|
||||||
|
}
|
||||||
item->setStartTime(newDateTime);
|
item->setStartTime(newDateTime);
|
||||||
ride->setTag("Year", newDateTime.toString("yyyy"));
|
ride->setTag("Year", newDateTime.toString("yyyy"));
|
||||||
ride->setTag("Month", newDateTime.toString("MMMM"));
|
ride->setTag("Month", newDateTime.toString("MMMM"));
|
||||||
ride->setTag("Weekday", newDateTime.toString("ddd"));
|
ride->setTag("Weekday", newDateTime.toString("ddd"));
|
||||||
|
ride->setTag("Filename", newFileName);
|
||||||
item->metadata_.insert("Calendar Text", GlobalContext::context()->rideMetadata->calendarText(item));
|
item->metadata_.insert("Calendar Text", GlobalContext::context()->rideMetadata->calendarText(item));
|
||||||
item->close();
|
|
||||||
|
|
||||||
QString renameError;
|
QString renameError;
|
||||||
if (! renameRideFiles(oldFileName, newFileName, item->planned, renameError)) {
|
if (! renameRideFiles(oldFileName, newFileName, item->planned, renameError)) {
|
||||||
item->dateTime = oldDateTime;
|
item->dateTime = oldDateTime;
|
||||||
item->fileName = oldFileName;
|
item->fileName = oldFileName;
|
||||||
result.error = tr("Failed to rename files: %1").arg(renameError);
|
result.error = tr("Failed to rename files: %1").arg(renameError);
|
||||||
|
item->close();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString newPath = (item->planned ? plannedDirectory : directory).canonicalPath() + "/" + newFileName;
|
||||||
|
QFile outFile(newPath);
|
||||||
|
if (! RideFileFactory::instance().writeRideFile(context, ride, outFile, QFileInfo(newFileName).suffix())) {
|
||||||
|
renameRideFiles(newFileName, oldFileName, item->planned, renameError);
|
||||||
|
item->dateTime = oldDateTime;
|
||||||
|
item->fileName = oldFileName;
|
||||||
|
result.error = tr("Failed to save activity file after rename");
|
||||||
|
item->close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
item->close();
|
||||||
|
|
||||||
int index = rides_.indexOf(item);
|
int index = rides_.indexOf(item);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
model_->startRemove(index);
|
model_->startRemove(index);
|
||||||
@@ -1236,6 +1254,7 @@ RideCache::moveActivity
|
|||||||
if (context->ride == item) {
|
if (context->ride == item) {
|
||||||
context->notifyRideSelected(item);
|
context->notifyRideSelected(item);
|
||||||
}
|
}
|
||||||
|
refresh();
|
||||||
estimator->refresh();
|
estimator->refresh();
|
||||||
|
|
||||||
result.success = true;
|
result.success = true;
|
||||||
@@ -1302,7 +1321,8 @@ RideCache::copyPlannedActivity
|
|||||||
std::sort(rides_.begin(), rides_.end(), rideCacheLessThan);
|
std::sort(rides_.begin(), rides_.end(), rideCacheLessThan);
|
||||||
model_->endReset();
|
model_->endReset();
|
||||||
|
|
||||||
newItem->refresh();
|
refresh();
|
||||||
|
estimator->refresh();
|
||||||
|
|
||||||
result.success = true;
|
result.success = true;
|
||||||
result.affectedCount = 1;
|
result.affectedCount = 1;
|
||||||
@@ -1541,18 +1561,33 @@ RideCache::shiftPlannedActivities
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDate originalDate = QDate::fromString(ride->getTag("Original Date", ""), "yyyy/MM/dd");
|
||||||
|
if (! originalDate.isValid()) {
|
||||||
|
ride->setTag("Original Date", item->dateTime.date().toString("yyyy/MM/dd"));
|
||||||
|
}
|
||||||
item->setStartTime(newDateTime);
|
item->setStartTime(newDateTime);
|
||||||
ride->setTag("Year", newDateTime.toString("yyyy"));
|
ride->setTag("Year", newDateTime.toString("yyyy"));
|
||||||
ride->setTag("Month", newDateTime.toString("MMMM"));
|
ride->setTag("Month", newDateTime.toString("MMMM"));
|
||||||
ride->setTag("Weekday", newDateTime.toString("ddd"));
|
ride->setTag("Weekday", newDateTime.toString("ddd"));
|
||||||
|
ride->setTag("Filename", newFileName);
|
||||||
item->metadata_.insert("Calendar Text", GlobalContext::context()->rideMetadata->calendarText(item));
|
item->metadata_.insert("Calendar Text", GlobalContext::context()->rideMetadata->calendarText(item));
|
||||||
item->close();
|
|
||||||
|
|
||||||
QString renameError;
|
QString renameError;
|
||||||
if (! renameRideFiles(oldFileName, newFileName, true, renameError)) {
|
if (! renameRideFiles(oldFileName, newFileName, true, renameError)) {
|
||||||
failedFiles << oldFileName;
|
failedFiles << oldFileName;
|
||||||
|
item->close();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString newPath = plannedDirectory.canonicalPath() + "/" + newFileName;
|
||||||
|
QFile outFile(newPath);
|
||||||
|
if (! RideFileFactory::instance().writeRideFile(context, ride, outFile, QFileInfo(newFileName).suffix())) {
|
||||||
|
renameRideFiles(newFileName, oldFileName, true, renameError);
|
||||||
|
failedFiles << oldFileName;
|
||||||
|
item->close();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
item->close();
|
||||||
item->setFileName(plannedDirectory.canonicalPath(), newFileName);
|
item->setFileName(plannedDirectory.canonicalPath(), newFileName);
|
||||||
updateFromWorkout(item, true);
|
updateFromWorkout(item, true);
|
||||||
item->isstale = true;
|
item->isstale = true;
|
||||||
@@ -1840,6 +1875,7 @@ RideCache::copyPlannedRideFile
|
|||||||
newRide->setTag("Year", newDateTime.toString("yyyy"));
|
newRide->setTag("Year", newDateTime.toString("yyyy"));
|
||||||
newRide->setTag("Month", newDateTime.toString("MMMM"));
|
newRide->setTag("Month", newDateTime.toString("MMMM"));
|
||||||
newRide->setTag("Weekday", newDateTime.toString("ddd"));
|
newRide->setTag("Weekday", newDateTime.toString("ddd"));
|
||||||
|
newRide->setTag("Original Date", newDateTime.date().toString("yyyy/MM/dd"));
|
||||||
|
|
||||||
if (! newRide->getTag("Linked Filename", "").isEmpty()) {
|
if (! newRide->getTag("Linked Filename", "").isEmpty()) {
|
||||||
newRide->removeTag("Linked Filename");
|
newRide->removeTag("Linked Filename");
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ struct CalendarEntry {
|
|||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
QDate spanStart = QDate();
|
QDate spanStart = QDate();
|
||||||
QDate spanEnd = QDate();
|
QDate spanEnd = QDate();
|
||||||
|
QString originalPlanLabel = QString();
|
||||||
|
|
||||||
QString linkedReference = QString();
|
QString linkedReference = QString();
|
||||||
QString linkedPrimary = QString();
|
QString linkedPrimary = QString();
|
||||||
|
|||||||
@@ -1773,10 +1773,18 @@ toolTipDayEntry(const QPoint &pos, QAbstractItemView *view, const CalendarDay &d
|
|||||||
}
|
}
|
||||||
tooltip += QString("<tr><td><b>%1:</b></td><td>%2</td></tr>").arg(QObject::tr("When")).arg(time);
|
tooltip += QString("<tr><td><b>%1:</b></td><td>%2</td></tr>").arg(QObject::tr("When")).arg(time);
|
||||||
}
|
}
|
||||||
|
if (calEntry.type == ENTRY_TYPE_PLANNED_ACTIVITY && ! calEntry.originalPlanLabel.isEmpty()) {
|
||||||
|
tooltip += QString("<tr><td><b>%1:</b></td><td>%2</td></tr>")
|
||||||
|
.arg(QObject::tr("Originally"))
|
||||||
|
.arg(calEntry.originalPlanLabel);
|
||||||
|
}
|
||||||
if (! calEntry.linkedReference.isEmpty()) {
|
if (! calEntry.linkedReference.isEmpty()) {
|
||||||
QString countertype;
|
QString countertype;
|
||||||
countertype = QObject::tr("Linked");
|
countertype = QObject::tr("Linked");
|
||||||
tooltip += QString("<tr><td style='padding-top: %1px'><b>%2:</b></td><td style='padding-top: %1px'>%3</td></tr>").arg(6 * dpiYFactor).arg(countertype).arg(calEntry.linkedPrimary);
|
tooltip += QString("<tr><td style='padding-top: %1px'><b>%2:</b></td><td style='padding-top: %1px'>%3</td></tr>")
|
||||||
|
.arg(6 * dpiYFactor)
|
||||||
|
.arg(countertype)
|
||||||
|
.arg(calEntry.linkedPrimary);
|
||||||
if (calEntry.linkedStartDT.isValid()) {
|
if (calEntry.linkedStartDT.isValid()) {
|
||||||
QString linkedWhen;
|
QString linkedWhen;
|
||||||
QLocale locale;
|
QLocale locale;
|
||||||
@@ -1786,6 +1794,11 @@ toolTipDayEntry(const QPoint &pos, QAbstractItemView *view, const CalendarDay &d
|
|||||||
linkedWhen = locale.toString(calEntry.linkedStartDT, QLocale::NarrowFormat);
|
linkedWhen = locale.toString(calEntry.linkedStartDT, QLocale::NarrowFormat);
|
||||||
}
|
}
|
||||||
tooltip += QString("<tr><td><b>%1:</b></td><td>%2</td></tr>").arg(QObject::tr("On")).arg(linkedWhen);
|
tooltip += QString("<tr><td><b>%1:</b></td><td>%2</td></tr>").arg(QObject::tr("On")).arg(linkedWhen);
|
||||||
|
if (calEntry.type == ENTRY_TYPE_ACTUAL_ACTIVITY && ! calEntry.originalPlanLabel.isEmpty()) {
|
||||||
|
tooltip += QString("<tr><td><b>%1:</b></td><td>%2</td></tr>")
|
||||||
|
.arg(QObject::tr("Originally"))
|
||||||
|
.arg(calEntry.originalPlanLabel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tooltip += "</table>";
|
tooltip += "</table>";
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ ManualActivityWizard::done
|
|||||||
rideFile.setRecIntSecs(0.00);
|
rideFile.setRecIntSecs(0.00);
|
||||||
rideFile.setDeviceType("Manual");
|
rideFile.setDeviceType("Manual");
|
||||||
rideFile.setFileFormat("GoldenCheetah Json");
|
rideFile.setFileFormat("GoldenCheetah Json");
|
||||||
|
if (plan) {
|
||||||
|
rideFile.setTag("Original Date", field("activityDate").toDate().toString("yyyy/MM/dd"));
|
||||||
|
}
|
||||||
|
|
||||||
field2TagString(rideFile, "sport", "Sport");
|
field2TagString(rideFile, "sport", "Sport");
|
||||||
field2TagString(rideFile, "subSport", "SubSport");
|
field2TagString(rideFile, "subSport", "SubSport");
|
||||||
|
|||||||
Reference in New Issue
Block a user