Mercurial > hg > svcore
diff data/fileio/CSVFileReader.cpp @ 392:183ee2a55fc7
* More work to abstract out interactive components used in the data library,
so that it does not need to depend on QtGui.
author | Chris Cannam |
---|---|
date | Fri, 14 Mar 2008 17:14:21 +0000 |
parents | 21e79997e80f |
children | 6f8ee19984ad |
line wrap: on
line diff
--- a/data/fileio/CSVFileReader.cpp Thu Mar 13 14:06:03 2008 +0000 +++ b/data/fileio/CSVFileReader.cpp Fri Mar 14 17:14:21 2008 +0000 @@ -27,18 +27,12 @@ #include <QRegExp> #include <QStringList> #include <QTextStream> -#include <QFrame> -#include <QGridLayout> -#include <QPushButton> -#include <QHBoxLayout> -#include <QVBoxLayout> -#include <QTableWidget> -#include <QComboBox> -#include <QLabel> #include <iostream> -CSVFileReader::CSVFileReader(QString path, size_t mainModelSampleRate) : +CSVFileReader::CSVFileReader(QString path, CSVFormat format, + size_t mainModelSampleRate) : + m_format(format), m_file(0), m_mainModelSampleRate(mainModelSampleRate) { @@ -86,7 +80,7 @@ CSVFileReader::load() const { if (!m_file) return 0; - +/*!!! CSVFormatDialog *dialog = new CSVFormatDialog (0, m_file, m_mainModelSampleRate); @@ -94,20 +88,19 @@ delete dialog; throw DataFileReaderFactory::ImportCancelled; } +*/ - CSVFormatDialog::ModelType modelType = dialog->getModelType(); - CSVFormatDialog::TimingType timingType = dialog->getTimingType(); - CSVFormatDialog::TimeUnits timeUnits = dialog->getTimeUnits(); - QString separator = dialog->getSeparator(); - QString::SplitBehavior behaviour = dialog->getSplitBehaviour(); - size_t sampleRate = dialog->getSampleRate(); - size_t windowSize = dialog->getWindowSize(); + CSVFormat::ModelType modelType = m_format.getModelType(); + CSVFormat::TimingType timingType = m_format.getTimingType(); + CSVFormat::TimeUnits timeUnits = m_format.getTimeUnits(); + QString separator = m_format.getSeparator(); + QString::SplitBehavior behaviour = m_format.getSplitBehaviour(); + size_t sampleRate = m_format.getSampleRate(); + size_t windowSize = m_format.getWindowSize(); - delete dialog; - - if (timingType == CSVFormatDialog::ExplicitTiming) { + if (timingType == CSVFormat::ExplicitTiming) { windowSize = 1; - if (timeUnits == CSVFormatDialog::TimeSeconds) { + if (timeUnits == CSVFormat::TimeSeconds) { sampleRate = m_mainModelSampleRate; } } @@ -155,17 +148,17 @@ switch (modelType) { - case CSVFormatDialog::OneDimensionalModel: + case CSVFormat::OneDimensionalModel: model1 = new SparseOneDimensionalModel(sampleRate, windowSize); model = model1; break; - case CSVFormatDialog::TwoDimensionalModel: + case CSVFormat::TwoDimensionalModel: model2 = new SparseTimeValueModel(sampleRate, windowSize, false); model = model2; break; - case CSVFormatDialog::ThreeDimensionalModel: + case CSVFormat::ThreeDimensionalModel: model3 = new EditableDenseThreeDimensionalModel(sampleRate, windowSize, list.size()); @@ -187,13 +180,13 @@ s = s.mid(1, s.length() - 2); } - if (i == 0 && timingType == CSVFormatDialog::ExplicitTiming) { + if (i == 0 && timingType == CSVFormat::ExplicitTiming) { bool ok = false; QString numeric = s; numeric.remove(nonNumericRx); - if (timeUnits == CSVFormatDialog::TimeSeconds) { + if (timeUnits == CSVFormat::TimeSeconds) { double time = numeric.toDouble(&ok); frameNo = int(time * sampleRate + 0.00001); @@ -202,7 +195,7 @@ frameNo = numeric.toInt(&ok); - if (timeUnits == CSVFormatDialog::TimeWindows) { + if (timeUnits == CSVFormat::TimeWindows) { frameNo *= windowSize; } } @@ -224,7 +217,7 @@ } } - if (modelType == CSVFormatDialog::OneDimensionalModel) { + if (modelType == CSVFormat::OneDimensionalModel) { SparseOneDimensionalModel::Point point (frameNo, @@ -233,7 +226,7 @@ model1->addPoint(point); - } else if (modelType == CSVFormatDialog::TwoDimensionalModel) { + } else if (modelType == CSVFormat::TwoDimensionalModel) { SparseTimeValueModel::Point point (frameNo, @@ -242,7 +235,7 @@ model2->addPoint(point); - } else if (modelType == CSVFormatDialog::ThreeDimensionalModel) { + } else if (modelType == CSVFormat::ThreeDimensionalModel) { DenseThreeDimensionalModel::Column values; @@ -277,14 +270,14 @@ } ++lineno; - if (timingType == CSVFormatDialog::ImplicitTiming || + if (timingType == CSVFormat::ImplicitTiming || list.size() == 0) { frameNo += windowSize; } } } - if (modelType == CSVFormatDialog::ThreeDimensionalModel) { + if (modelType == CSVFormat::ThreeDimensionalModel) { model3->setMinimumLevel(min); model3->setMaximumLevel(max); } @@ -292,390 +285,3 @@ return model; } - -CSVFormatDialog::CSVFormatDialog(QWidget *parent, QFile *file, - size_t defaultSampleRate) : - QDialog(parent), - m_modelType(OneDimensionalModel), - m_timingType(ExplicitTiming), - m_timeUnits(TimeAudioFrames), - m_separator(""), - m_behaviour(QString::KeepEmptyParts) -{ - setModal(true); - setWindowTitle(tr("Select Data Format")); - - (void)guessFormat(file); - - QGridLayout *layout = new QGridLayout; - - layout->addWidget(new QLabel(tr("<b>Select Data Format</b><p>Please select the correct data format for this file.")), - 0, 0, 1, 4); - - layout->addWidget(new QLabel(tr("Each row specifies:")), 1, 0); - - m_modelTypeCombo = new QComboBox; - m_modelTypeCombo->addItem(tr("A point in time")); - m_modelTypeCombo->addItem(tr("A value at a time")); - m_modelTypeCombo->addItem(tr("A set of values")); - layout->addWidget(m_modelTypeCombo, 1, 1, 1, 2); - connect(m_modelTypeCombo, SIGNAL(activated(int)), - this, SLOT(modelTypeChanged(int))); - m_modelTypeCombo->setCurrentIndex(int(m_modelType)); - - layout->addWidget(new QLabel(tr("The first column contains:")), 2, 0); - - m_timingTypeCombo = new QComboBox; - m_timingTypeCombo->addItem(tr("Time, in seconds")); - m_timingTypeCombo->addItem(tr("Time, in audio sample frames")); - m_timingTypeCombo->addItem(tr("Data (rows are consecutive in time)")); - layout->addWidget(m_timingTypeCombo, 2, 1, 1, 2); - connect(m_timingTypeCombo, SIGNAL(activated(int)), - this, SLOT(timingTypeChanged(int))); - m_timingTypeCombo->setCurrentIndex(m_timingType == ExplicitTiming ? - m_timeUnits == TimeSeconds ? 0 : 1 : 2); - - m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); - layout->addWidget(m_sampleRateLabel, 3, 0); - - size_t sampleRates[] = { - 8000, 11025, 12000, 22050, 24000, 32000, - 44100, 48000, 88200, 96000, 176400, 192000 - }; - - m_sampleRateCombo = new QComboBox; - m_sampleRate = defaultSampleRate; - for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) { - m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); - if (sampleRates[i] == m_sampleRate) m_sampleRateCombo->setCurrentIndex(i); - } - m_sampleRateCombo->setEditable(true); - - layout->addWidget(m_sampleRateCombo, 3, 1); - connect(m_sampleRateCombo, SIGNAL(activated(QString)), - this, SLOT(sampleRateChanged(QString))); - connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), - this, SLOT(sampleRateChanged(QString))); - - m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); - layout->addWidget(m_windowSizeLabel, 4, 0); - - m_windowSizeCombo = new QComboBox; - m_windowSize = 1024; - for (int i = 0; i <= 16; ++i) { - int value = 1 << i; - m_windowSizeCombo->addItem(QString("%1").arg(value)); - if (value == int(m_windowSize)) m_windowSizeCombo->setCurrentIndex(i); - } - m_windowSizeCombo->setEditable(true); - - layout->addWidget(m_windowSizeCombo, 4, 1); - connect(m_windowSizeCombo, SIGNAL(activated(QString)), - this, SLOT(windowSizeChanged(QString))); - connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)), - this, SLOT(windowSizeChanged(QString))); - - layout->addWidget(new QLabel(tr("\nExample data from file:")), 5, 0, 1, 4); - - m_exampleWidget = new QTableWidget - (std::min(10, m_example.size()), m_maxExampleCols); - - layout->addWidget(m_exampleWidget, 6, 0, 1, 4); - layout->setColumnStretch(3, 10); - layout->setRowStretch(4, 10); - - QPushButton *ok = new QPushButton(tr("OK")); - connect(ok, SIGNAL(clicked()), this, SLOT(accept())); - ok->setDefault(true); - - QPushButton *cancel = new QPushButton(tr("Cancel")); - connect(cancel, SIGNAL(clicked()), this, SLOT(reject())); - - QHBoxLayout *buttonLayout = new QHBoxLayout; - buttonLayout->addStretch(1); - buttonLayout->addWidget(ok); - buttonLayout->addWidget(cancel); - - QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addLayout(layout); - mainLayout->addLayout(buttonLayout); - - setLayout(mainLayout); - - timingTypeChanged(m_timingTypeCombo->currentIndex()); -} - -CSVFormatDialog::~CSVFormatDialog() -{ -} - -void -CSVFormatDialog::populateExample() -{ - m_exampleWidget->setColumnCount - (m_timingType == ExplicitTiming ? - m_maxExampleCols - 1 : m_maxExampleCols); - - m_exampleWidget->setHorizontalHeaderLabels(QStringList()); - - for (int i = 0; i < m_example.size(); ++i) { - for (int j = 0; j < m_example[i].size(); ++j) { - - QTableWidgetItem *item = new QTableWidgetItem(m_example[i][j]); - - if (j == 0) { - if (m_timingType == ExplicitTiming) { - m_exampleWidget->setVerticalHeaderItem(i, item); - continue; - } else { - QTableWidgetItem *header = - new QTableWidgetItem(QString("%1").arg(i)); - header->setFlags(Qt::ItemIsEnabled); - m_exampleWidget->setVerticalHeaderItem(i, header); - } - } - int index = j; - if (m_timingType == ExplicitTiming) --index; - item->setFlags(Qt::ItemIsEnabled); - m_exampleWidget->setItem(i, index, item); - } - } -} - -void -CSVFormatDialog::modelTypeChanged(int type) -{ - m_modelType = (ModelType)type; - - if (m_modelType == ThreeDimensionalModel) { - // We can't load 3d models with explicit timing, because the 3d - // model is dense so we need a fixed sample increment - m_timingTypeCombo->setCurrentIndex(2); - timingTypeChanged(2); - } -} - -void -CSVFormatDialog::timingTypeChanged(int type) -{ - switch (type) { - - case 0: - m_timingType = ExplicitTiming; - m_timeUnits = TimeSeconds; - m_sampleRateCombo->setEnabled(false); - m_sampleRateLabel->setEnabled(false); - m_windowSizeCombo->setEnabled(false); - m_windowSizeLabel->setEnabled(false); - if (m_modelType == ThreeDimensionalModel) { - m_modelTypeCombo->setCurrentIndex(1); - modelTypeChanged(1); - } - break; - - case 1: - m_timingType = ExplicitTiming; - m_timeUnits = TimeAudioFrames; - m_sampleRateCombo->setEnabled(true); - m_sampleRateLabel->setEnabled(true); - m_windowSizeCombo->setEnabled(false); - m_windowSizeLabel->setEnabled(false); - if (m_modelType == ThreeDimensionalModel) { - m_modelTypeCombo->setCurrentIndex(1); - modelTypeChanged(1); - } - break; - - case 2: - m_timingType = ImplicitTiming; - m_timeUnits = TimeWindows; - m_sampleRateCombo->setEnabled(true); - m_sampleRateLabel->setEnabled(true); - m_windowSizeCombo->setEnabled(true); - m_windowSizeLabel->setEnabled(true); - break; - } - - populateExample(); -} - -void -CSVFormatDialog::sampleRateChanged(QString rateString) -{ - bool ok = false; - int sampleRate = rateString.toInt(&ok); - if (ok) m_sampleRate = sampleRate; -} - -void -CSVFormatDialog::windowSizeChanged(QString sizeString) -{ - bool ok = false; - int size = sizeString.toInt(&ok); - if (ok) m_windowSize = size; -} - -bool -CSVFormatDialog::guessFormat(QFile *file) -{ - QTextStream in(file); - in.seek(0); - - unsigned int lineno = 0; - - bool nonIncreasingPrimaries = false; - bool nonNumericPrimaries = false; - bool floatPrimaries = false; - bool variableItemCount = false; - int itemCount = 1; - int earliestNonNumericItem = -1; - - float prevPrimary = 0.0; - - m_maxExampleCols = 0; - - while (!in.atEnd()) { - - // See comment about line endings in load() above - - QString chunk = in.readLine(); - QStringList lines = chunk.split('\r', QString::SkipEmptyParts); - - for (size_t li = 0; li < lines.size(); ++li) { - - QString line = lines[li]; - - if (line.startsWith("#")) continue; - - m_behaviour = QString::KeepEmptyParts; - - if (m_separator == "") { - //!!! to do: ask the user - if (line.split(",").size() >= 2) m_separator = ","; - else if (line.split("\t").size() >= 2) m_separator = "\t"; - else if (line.split("|").size() >= 2) m_separator = "|"; - else if (line.split("/").size() >= 2) m_separator = "/"; - else if (line.split(":").size() >= 2) m_separator = ":"; - else { - m_separator = " "; - m_behaviour = QString::SkipEmptyParts; - } - } - - QStringList list = line.split(m_separator, m_behaviour); - QStringList tidyList; - - for (int i = 0; i < list.size(); ++i) { - - QString s(list[i]); - bool numeric = false; - - if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) { - s = s.mid(1, s.length() - 2); - } else if (s.length() >= 2 && s.startsWith("'") && s.endsWith("'")) { - s = s.mid(1, s.length() - 2); - } else { - (void)s.toFloat(&numeric); - } - - tidyList.push_back(s); - - if (lineno == 0 || (list.size() < itemCount)) { - itemCount = list.size(); - } else { - if (itemCount != list.size()) { - variableItemCount = true; - } - } - - if (i == 0) { // primary - - if (numeric) { - - float primary = s.toFloat(); - - if (lineno > 0 && primary <= prevPrimary) { - nonIncreasingPrimaries = true; - } - - if (s.contains(".") || s.contains(",")) { - floatPrimaries = true; - } - - prevPrimary = primary; - - } else { - nonNumericPrimaries = true; - } - } else { // secondary - - if (!numeric) { - if (earliestNonNumericItem < 0 || - i < earliestNonNumericItem) { - earliestNonNumericItem = i; - } - } - } - } - - if (lineno < 10) { - m_example.push_back(tidyList); - if (lineno == 0 || tidyList.size() > m_maxExampleCols) { - m_maxExampleCols = tidyList.size(); - } - } - - ++lineno; - - if (lineno == 50) break; - } - } - - if (nonNumericPrimaries || nonIncreasingPrimaries) { - - // Primaries are probably not a series of times - - m_timingType = ImplicitTiming; - m_timeUnits = TimeWindows; - - if (nonNumericPrimaries) { - m_modelType = OneDimensionalModel; - } else if (itemCount == 1 || variableItemCount || - (earliestNonNumericItem != -1)) { - m_modelType = TwoDimensionalModel; - } else { - m_modelType = ThreeDimensionalModel; - } - - } else { - - // Increasing numeric primaries -- likely to be time - - m_timingType = ExplicitTiming; - - if (floatPrimaries) { - m_timeUnits = TimeSeconds; - } else { - m_timeUnits = TimeAudioFrames; - } - - if (itemCount == 1) { - m_modelType = OneDimensionalModel; - } else if (variableItemCount || (earliestNonNumericItem != -1)) { - if (earliestNonNumericItem != -1 && earliestNonNumericItem < 2) { - m_modelType = OneDimensionalModel; - } else { - m_modelType = TwoDimensionalModel; - } - } else { - m_modelType = ThreeDimensionalModel; - } - } - - std::cerr << "Estimated model type: " << m_modelType << std::endl; - std::cerr << "Estimated timing type: " << m_timingType << std::endl; - std::cerr << "Estimated units: " << m_timeUnits << std::endl; - - in.seek(0); - return true; -}