mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 16:18:42 +00:00
.. move the fluff that has collected into the src directory to somewhere more appropriate.
225 lines
7.6 KiB
C++
225 lines
7.6 KiB
C++
/*
|
|
* Copyright (c) 2009 Ned Harding (ned@hardinggroup.com)
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc., 51
|
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include "SplitRideDialog.h"
|
|
#include "GcRideFile.h"
|
|
#include "MainWindow.h"
|
|
#include "RideFile.h"
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <QtGui>
|
|
|
|
namespace
|
|
{
|
|
QString MakeTimeString(double secs)
|
|
{
|
|
QString strTime;
|
|
double mins = ((int) secs) / 60;
|
|
secs = secs - mins * 60.0;
|
|
double hrs = ((int) mins) / 60;
|
|
mins = mins - hrs * 60.0;
|
|
strTime.sprintf("%02.0f:%02.0f:%02.0f", hrs, mins, secs);
|
|
return strTime;
|
|
}
|
|
|
|
class ListItem_Split : public QListWidgetItem
|
|
{
|
|
public:
|
|
int m_nRecNum;
|
|
explicit ListItem_Split(int nRecNum, const QString &text, QListWidget *view)
|
|
: QListWidgetItem(text, view)
|
|
, m_nRecNum(nRecNum)
|
|
{
|
|
}
|
|
};
|
|
}
|
|
|
|
SplitRideDialog::SplitRideDialog(MainWindow *mainWindow)
|
|
: mainWindow(mainWindow)
|
|
{
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
setWindowTitle("Split Ride");
|
|
|
|
listWidget = new QListWidget(this);
|
|
listWidget->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
QLabel *splitLabel = new QLabel(tr("Split at the following positions:"), this);
|
|
QLabel *labelSpacer = new QLabel(this);
|
|
labelSpacer->setIndent(10);
|
|
|
|
okButton = new QPushButton(tr("&OK"), this);
|
|
cancelButton = new QPushButton(tr("&Cancel"), this);
|
|
|
|
connect(okButton, SIGNAL(clicked()), this, SLOT(okClicked()));
|
|
connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancelClicked()));
|
|
connect(listWidget,
|
|
SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()));
|
|
|
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
|
buttonLayout->addWidget(okButton);
|
|
buttonLayout->addWidget(cancelButton);
|
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout(this);
|
|
mainLayout->addWidget(splitLabel);
|
|
mainLayout->addWidget(listWidget);
|
|
mainLayout->addWidget(labelSpacer);
|
|
mainLayout->addLayout(buttonLayout);
|
|
|
|
const RideFile *ride = mainWindow->currentRide();
|
|
QMap<int,QString> splitPoints;
|
|
|
|
QList<RideFileInterval> intervals = ride->intervals();
|
|
if (!intervals.empty()) {
|
|
intervals.removeFirst();
|
|
foreach (RideFileInterval interval, intervals) {
|
|
int nDataPoint = ride->intervalBegin(interval);
|
|
QString strDesc = QString("Interval %1").arg(interval.name);
|
|
splitPoints.insert(nDataPoint, strDesc);
|
|
}
|
|
}
|
|
|
|
for (int nDataPoint = 1; nDataPoint < ride->dataPoints().size(); ++nDataPoint) {
|
|
const RideFilePoint *point = ride->dataPoints()[nDataPoint];
|
|
double dLastSeconds = ride->dataPoints()[nDataPoint - 1]->secs;
|
|
if ((point->secs-dLastSeconds)>=30 && !splitPoints.contains(nDataPoint)) {
|
|
QString strDesc = "Time Gap: " + MakeTimeString(point->secs-dLastSeconds);
|
|
splitPoints.insert(nDataPoint, strDesc);
|
|
}
|
|
}
|
|
|
|
QMapIterator<int,QString> i(splitPoints);
|
|
while (i.hasNext()) {
|
|
i.next();
|
|
int nDataPoint = i.key();
|
|
const RideFilePoint *point = ride->dataPoints()[nDataPoint];
|
|
QString strDesc = MakeTimeString(point->secs) + " - " + i.value();
|
|
ListItem_Split *pItem = new ListItem_Split(nDataPoint, strDesc, listWidget);
|
|
|
|
if (nDataPoint > 0) {
|
|
double dLastSeconds = ride->dataPoints()[nDataPoint - 1]->secs;
|
|
if ((point->secs-dLastSeconds)>20*60)
|
|
pItem->setCheckState(Qt::Checked);
|
|
else
|
|
pItem->setCheckState(Qt::Unchecked);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
SplitRideDialog::cancelClicked()
|
|
{
|
|
reject();
|
|
}
|
|
|
|
void
|
|
SplitRideDialog::CreateNewRideFile(const RideFile *ride, int nRecStart, int nRecEnd)
|
|
{
|
|
// set the start time, taking care to include the offset for the interval
|
|
QDateTime newStart = ride->startTime();
|
|
RideFilePoint *pointStart = ride->dataPoints().at(nRecStart);
|
|
newStart = newStart.addMSecs(static_cast<qint64>(pointStart->secs*1000 + 0.5));
|
|
|
|
QString fileName;
|
|
QString filePath;
|
|
|
|
// adjust start time of file to avoid conflicts with existing files
|
|
int offset = 0;
|
|
QDateTime noConflicts;
|
|
do {
|
|
noConflicts = newStart.addSecs(offset);
|
|
|
|
fileName.sprintf("%04d_%02d_%02d_%02d_%02d_%02d.gc",
|
|
noConflicts.date().year(), noConflicts.date().month(),
|
|
noConflicts.date().day(), noConflicts.time().hour(), noConflicts.time().minute(),
|
|
noConflicts.time().second());
|
|
filePath = mainWindow->home.absolutePath() + "/" + fileName;
|
|
|
|
offset++;
|
|
|
|
} while (QFile(filePath).exists());
|
|
newStart = newStart.addSecs(offset);
|
|
|
|
// create the ridefile in memory
|
|
QScopedPointer<RideFile> newRideFile(new RideFile(newStart, ride->recIntSecs()));
|
|
for (int nItem = nRecStart; nItem<nRecEnd; ++nItem)
|
|
{
|
|
RideFilePoint *pPoint = ride->dataPoints().at(nItem);
|
|
newRideFile->appendPoint(pPoint->secs-pointStart->secs, pPoint->cad, pPoint->hr, pPoint->km - pointStart->km,
|
|
pPoint->kph, pPoint->nm, pPoint->watts, pPoint->alt, pPoint->lon, pPoint->lat, pPoint->headwind, pPoint->slope,
|
|
pPoint->temp, pPoint->lrbalance, pPoint->interval-pointStart->interval);
|
|
}
|
|
newRideFile->setDeviceType(ride->deviceType());
|
|
newRideFile->setFileFormat(ride->fileFormat());
|
|
|
|
double endSecs = ride->dataPoints().at(nRecEnd - 1)->secs + ride->recIntSecs();
|
|
foreach (RideFileInterval interval, ride->intervals()) {
|
|
if ((interval.start >= pointStart->secs) && (interval.stop <= endSecs)) {
|
|
newRideFile->addInterval(interval.start - pointStart->secs,
|
|
interval.stop - pointStart->secs,
|
|
interval.name);
|
|
}
|
|
}
|
|
|
|
// should never, ever complain.. could wipe out, but lets check anyway
|
|
// it costs nothing and might save a file one day
|
|
QFile file(filePath);
|
|
if (file.exists())
|
|
{
|
|
QMessageBox::critical(this, tr("Split Ride"), tr("The file %1 already exists and will not be overwritten").arg(filePath));
|
|
return;
|
|
}
|
|
|
|
// write to disk
|
|
GcFileReader f;
|
|
f.writeRideFile(mainWindow, newRideFile.data(), file);
|
|
|
|
// add to the ride list
|
|
mainWindow->addRide(fileName, false);
|
|
}
|
|
void
|
|
SplitRideDialog::okClicked()
|
|
{
|
|
const RideFile *ride = mainWindow->currentRide();
|
|
|
|
int nStartPoint = 0;
|
|
for (int nRow=0; nRow<listWidget->count(); ++nRow)
|
|
{
|
|
const ListItem_Split *pItem = static_cast<const ListItem_Split *>(listWidget->item(nRow));
|
|
if (pItem->checkState()==Qt::Checked)
|
|
{
|
|
CreateNewRideFile(ride, nStartPoint, pItem->m_nRecNum);
|
|
nStartPoint = pItem->m_nRecNum;
|
|
}
|
|
}
|
|
|
|
if (nStartPoint!=0)
|
|
{
|
|
CreateNewRideFile(ride, nStartPoint, mainWindow->currentRide()->dataPoints().count());
|
|
mainWindow->removeCurrentRide();
|
|
}
|
|
|
|
done(0);
|
|
}
|
|
|
|
void
|
|
SplitRideDialog::selectionChanged()
|
|
{
|
|
}
|