mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-16 01:19:57 +00:00
Ride editor and tools
A new tab 'Editor' for manually editing ride file data points and associated menu options under 'Tools' for fixing spikes, gaps, GPS errors and adjusting torque values. A revert to saved ride option is also included to 'undo' all changes. The ride editor supports undo/redo as well as cut and paste and "paste special" (to append points or swap columns/overwrite selected data series). The editor also supports search and will automatically highlight anomalous data. When a file is saved, the changes are recorded in a new metadata special field called "Change History" which can be added as a Textbox in the metadata config. The data processors can be run manually or automatically when a ride is opened - these are configured on the ride data tab in the config pane. Significant changes have been introduced in the codebase, the most significant of which are; a RideFileCommand class for modifying ride data has been introduced (as a member of RideFile) and the RideItem class is now a QObject as well as QTreeWidgetItem to enable signalling. The Ride Editor uses a RideFileTableModel that can be re-used in other parts of the code. LTMoutliers class has been introduced in support of anomaly detection in the editor (which highlights anomalies with a wiggly red line). Fixes #103.
This commit is contained in:
@@ -843,10 +843,12 @@ MetadataPage::MetadataPage(MainWindow *main) : main(main)
|
||||
// setup maintenance pages using current config
|
||||
fieldsPage = new FieldsPage(this, fieldDefinitions);
|
||||
keywordsPage = new KeywordsPage(this, keywordDefinitions);
|
||||
processorPage = new ProcessorPage(main);
|
||||
|
||||
tabs = new QTabWidget(this);
|
||||
tabs->addTab(fieldsPage, tr("Fields"));
|
||||
tabs->addTab(keywordsPage, tr("Notes Keywords"));
|
||||
tabs->addTab(processorPage, tr("Processing"));
|
||||
|
||||
layout->addWidget(tabs);
|
||||
}
|
||||
@@ -860,6 +862,9 @@ MetadataPage::saveClicked()
|
||||
|
||||
// write to metadata.xml
|
||||
RideMetadata::serialize(main->home.absolutePath() + "/metadata.xml", keywordDefinitions, fieldDefinitions);
|
||||
|
||||
// save processors config
|
||||
processorPage->saveClicked();
|
||||
}
|
||||
|
||||
// little helper since we create/recreate combos
|
||||
@@ -1219,6 +1224,81 @@ FieldsPage::getDefinitions(QList<FieldDefinition> &fieldList)
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Data processors config page
|
||||
//
|
||||
ProcessorPage::ProcessorPage(MainWindow *main) : main(main)
|
||||
{
|
||||
// get the available processors
|
||||
const DataProcessorFactory &factory = DataProcessorFactory::instance();
|
||||
processors = factory.getProcessors();
|
||||
|
||||
QGridLayout *mainLayout = new QGridLayout(this);
|
||||
|
||||
processorTree = new QTreeWidget;
|
||||
processorTree->headerItem()->setText(0, tr("Processor"));
|
||||
processorTree->headerItem()->setText(1, tr("Apply"));
|
||||
processorTree->headerItem()->setText(2, tr("Settings"));
|
||||
processorTree->setColumnCount(3);
|
||||
processorTree->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
processorTree->setEditTriggers(QAbstractItemView::SelectedClicked); // allow edit
|
||||
processorTree->setUniformRowHeights(true);
|
||||
processorTree->setIndentation(0);
|
||||
processorTree->header()->resizeSection(0,150);
|
||||
|
||||
// iterate over all the processors and add an entry to the
|
||||
QMapIterator<QString, DataProcessor*> i(processors);
|
||||
i.toFront();
|
||||
while (i.hasNext()) {
|
||||
i.next();
|
||||
|
||||
QTreeWidgetItem *add;
|
||||
|
||||
add = new QTreeWidgetItem(processorTree->invisibleRootItem());
|
||||
add->setFlags(add->flags() & ~Qt::ItemIsEditable);
|
||||
|
||||
// Processor Name
|
||||
add->setText(0, i.key());
|
||||
|
||||
// Auto or Manual run?
|
||||
QComboBox *comboButton = new QComboBox(this);
|
||||
comboButton->addItem(tr("Manual"));
|
||||
comboButton->addItem(tr("Auto"));
|
||||
processorTree->setItemWidget(add, 1, comboButton);
|
||||
|
||||
QString configsetting = QString("dp/%1/apply").arg(i.key());
|
||||
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
|
||||
if (settings->value(configsetting, "Manual").toString() == "Manual")
|
||||
comboButton->setCurrentIndex(0);
|
||||
else
|
||||
comboButton->setCurrentIndex(1);
|
||||
|
||||
// Get and Set the Config Widget
|
||||
DataProcessorConfig *config = i.value()->processorConfig(this);
|
||||
config->readConfig();
|
||||
|
||||
processorTree->setItemWidget(add, 2, config);
|
||||
}
|
||||
|
||||
mainLayout->addWidget(processorTree, 0,0);
|
||||
}
|
||||
|
||||
void
|
||||
ProcessorPage::saveClicked()
|
||||
{
|
||||
// call each processor config widget's saveConfig() to
|
||||
// write away separately
|
||||
boost::shared_ptr<QSettings> settings = GetApplicationSettings();
|
||||
for (int i=0; i<processorTree->invisibleRootItem()->childCount(); i++) {
|
||||
// auto or manual?
|
||||
QString configsetting = QString("dp/%1/apply").arg(processorTree->invisibleRootItem()->child(i)->text(0));
|
||||
QString apply = ((QComboBox*)(processorTree->itemWidget(processorTree->invisibleRootItem()->child(i), 1)))->currentIndex() ?
|
||||
"Auto" : "Manual";
|
||||
settings->setValue(configsetting, apply);
|
||||
((DataProcessorConfig*)(processorTree->itemWidget(processorTree->invisibleRootItem()->child(i), 2)))->saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Zone Config page
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user