annotate data/fileio/CSVFileReader.cpp @ 0:fc9323a41f5a

start base : Sonic Visualiser sv1-1.0rc1
author lbajardsilogic
date Fri, 11 May 2007 09:08:14 +0000
parents
children 6a31322cd9ed
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "CSVFileReader.h"
lbajardsilogic@0 17
lbajardsilogic@0 18 #include "model/Model.h"
lbajardsilogic@0 19 #include "base/RealTime.h"
lbajardsilogic@0 20 #include "model/SparseOneDimensionalModel.h"
lbajardsilogic@0 21 #include "model/SparseTimeValueModel.h"
lbajardsilogic@0 22 #include "model/EditableDenseThreeDimensionalModel.h"
lbajardsilogic@0 23
lbajardsilogic@0 24 #include <QFile>
lbajardsilogic@0 25 #include <QString>
lbajardsilogic@0 26 #include <QRegExp>
lbajardsilogic@0 27 #include <QStringList>
lbajardsilogic@0 28 #include <QTextStream>
lbajardsilogic@0 29 #include <QFrame>
lbajardsilogic@0 30 #include <QGridLayout>
lbajardsilogic@0 31 #include <QPushButton>
lbajardsilogic@0 32 #include <QHBoxLayout>
lbajardsilogic@0 33 #include <QVBoxLayout>
lbajardsilogic@0 34 #include <QTableWidget>
lbajardsilogic@0 35 #include <QComboBox>
lbajardsilogic@0 36 #include <QLabel>
lbajardsilogic@0 37
lbajardsilogic@0 38 #include <iostream>
lbajardsilogic@0 39
lbajardsilogic@0 40 CSVFileReader::CSVFileReader(QString path, size_t mainModelSampleRate) :
lbajardsilogic@0 41 m_file(0),
lbajardsilogic@0 42 m_mainModelSampleRate(mainModelSampleRate)
lbajardsilogic@0 43 {
lbajardsilogic@0 44 m_file = new QFile(path);
lbajardsilogic@0 45 bool good = false;
lbajardsilogic@0 46
lbajardsilogic@0 47 if (!m_file->exists()) {
lbajardsilogic@0 48 m_error = QFile::tr("File \"%1\" does not exist").arg(path);
lbajardsilogic@0 49 } else if (!m_file->open(QIODevice::ReadOnly | QIODevice::Text)) {
lbajardsilogic@0 50 m_error = QFile::tr("Failed to open file \"%1\"").arg(path);
lbajardsilogic@0 51 } else {
lbajardsilogic@0 52 good = true;
lbajardsilogic@0 53 }
lbajardsilogic@0 54
lbajardsilogic@0 55 if (!good) {
lbajardsilogic@0 56 delete m_file;
lbajardsilogic@0 57 m_file = 0;
lbajardsilogic@0 58 }
lbajardsilogic@0 59 }
lbajardsilogic@0 60
lbajardsilogic@0 61 CSVFileReader::~CSVFileReader()
lbajardsilogic@0 62 {
lbajardsilogic@0 63 std::cerr << "CSVFileReader::~CSVFileReader: file is " << m_file << std::endl;
lbajardsilogic@0 64
lbajardsilogic@0 65 if (m_file) {
lbajardsilogic@0 66 std::cerr << "CSVFileReader::CSVFileReader: Closing file" << std::endl;
lbajardsilogic@0 67 m_file->close();
lbajardsilogic@0 68 }
lbajardsilogic@0 69 delete m_file;
lbajardsilogic@0 70 }
lbajardsilogic@0 71
lbajardsilogic@0 72 bool
lbajardsilogic@0 73 CSVFileReader::isOK() const
lbajardsilogic@0 74 {
lbajardsilogic@0 75 return (m_file != 0);
lbajardsilogic@0 76 }
lbajardsilogic@0 77
lbajardsilogic@0 78 QString
lbajardsilogic@0 79 CSVFileReader::getError() const
lbajardsilogic@0 80 {
lbajardsilogic@0 81 return m_error;
lbajardsilogic@0 82 }
lbajardsilogic@0 83
lbajardsilogic@0 84 Model *
lbajardsilogic@0 85 CSVFileReader::load() const
lbajardsilogic@0 86 {
lbajardsilogic@0 87 if (!m_file) return 0;
lbajardsilogic@0 88
lbajardsilogic@0 89 CSVFormatDialog *dialog = new CSVFormatDialog
lbajardsilogic@0 90 (0, m_file, m_mainModelSampleRate);
lbajardsilogic@0 91
lbajardsilogic@0 92 if (dialog->exec() == QDialog::Rejected) {
lbajardsilogic@0 93 delete dialog;
lbajardsilogic@0 94 return 0;
lbajardsilogic@0 95 }
lbajardsilogic@0 96
lbajardsilogic@0 97 CSVFormatDialog::ModelType modelType = dialog->getModelType();
lbajardsilogic@0 98 CSVFormatDialog::TimingType timingType = dialog->getTimingType();
lbajardsilogic@0 99 CSVFormatDialog::TimeUnits timeUnits = dialog->getTimeUnits();
lbajardsilogic@0 100 QString separator = dialog->getSeparator();
lbajardsilogic@0 101 size_t sampleRate = dialog->getSampleRate();
lbajardsilogic@0 102 size_t windowSize = dialog->getWindowSize();
lbajardsilogic@0 103
lbajardsilogic@0 104 delete dialog;
lbajardsilogic@0 105
lbajardsilogic@0 106 if (timingType == CSVFormatDialog::ExplicitTiming) {
lbajardsilogic@0 107 windowSize = 1;
lbajardsilogic@0 108 if (timeUnits == CSVFormatDialog::TimeSeconds) {
lbajardsilogic@0 109 sampleRate = m_mainModelSampleRate;
lbajardsilogic@0 110 }
lbajardsilogic@0 111 }
lbajardsilogic@0 112
lbajardsilogic@0 113 SparseOneDimensionalModel *model1 = 0;
lbajardsilogic@0 114 SparseTimeValueModel *model2 = 0;
lbajardsilogic@0 115 EditableDenseThreeDimensionalModel *model3 = 0;
lbajardsilogic@0 116 Model *model = 0;
lbajardsilogic@0 117
lbajardsilogic@0 118 QTextStream in(m_file);
lbajardsilogic@0 119 in.seek(0);
lbajardsilogic@0 120
lbajardsilogic@0 121 unsigned int warnings = 0, warnLimit = 10;
lbajardsilogic@0 122 unsigned int lineno = 0;
lbajardsilogic@0 123
lbajardsilogic@0 124 float min = 0.0, max = 0.0;
lbajardsilogic@0 125
lbajardsilogic@0 126 size_t frameNo = 0;
lbajardsilogic@0 127
lbajardsilogic@0 128 while (!in.atEnd()) {
lbajardsilogic@0 129
lbajardsilogic@0 130 QString line = in.readLine().trimmed();
lbajardsilogic@0 131 if (line.startsWith("#") || line.trimmed() == "") continue;
lbajardsilogic@0 132
lbajardsilogic@0 133 QStringList list = line.split(separator);
lbajardsilogic@0 134
lbajardsilogic@0 135 if (!model) {
lbajardsilogic@0 136
lbajardsilogic@0 137 switch (modelType) {
lbajardsilogic@0 138
lbajardsilogic@0 139 case CSVFormatDialog::OneDimensionalModel:
lbajardsilogic@0 140 model1 = new SparseOneDimensionalModel(sampleRate, windowSize);
lbajardsilogic@0 141 model = model1;
lbajardsilogic@0 142 break;
lbajardsilogic@0 143
lbajardsilogic@0 144 case CSVFormatDialog::TwoDimensionalModel:
lbajardsilogic@0 145 model2 = new SparseTimeValueModel(sampleRate, windowSize, false);
lbajardsilogic@0 146 model = model2;
lbajardsilogic@0 147 break;
lbajardsilogic@0 148
lbajardsilogic@0 149 case CSVFormatDialog::ThreeDimensionalModel:
lbajardsilogic@0 150 model3 = new EditableDenseThreeDimensionalModel(sampleRate,
lbajardsilogic@0 151 windowSize,
lbajardsilogic@0 152 list.size());
lbajardsilogic@0 153 model = model3;
lbajardsilogic@0 154 break;
lbajardsilogic@0 155 }
lbajardsilogic@0 156 }
lbajardsilogic@0 157
lbajardsilogic@0 158 QStringList tidyList;
lbajardsilogic@0 159 QRegExp nonNumericRx("[^0-9.,+-]");
lbajardsilogic@0 160
lbajardsilogic@0 161 for (int i = 0; i < list.size(); ++i) {
lbajardsilogic@0 162
lbajardsilogic@0 163 QString s(list[i].trimmed());
lbajardsilogic@0 164
lbajardsilogic@0 165 if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) {
lbajardsilogic@0 166 s = s.mid(1, s.length() - 2);
lbajardsilogic@0 167 } else if (s.length() >= 2 && s.startsWith("'") && s.endsWith("'")) {
lbajardsilogic@0 168 s = s.mid(1, s.length() - 2);
lbajardsilogic@0 169 }
lbajardsilogic@0 170
lbajardsilogic@0 171 if (i == 0 && timingType == CSVFormatDialog::ExplicitTiming) {
lbajardsilogic@0 172
lbajardsilogic@0 173 bool ok = false;
lbajardsilogic@0 174 QString numeric = s;
lbajardsilogic@0 175 numeric.remove(nonNumericRx);
lbajardsilogic@0 176
lbajardsilogic@0 177 if (timeUnits == CSVFormatDialog::TimeSeconds) {
lbajardsilogic@0 178
lbajardsilogic@0 179 double time = numeric.toDouble(&ok);
lbajardsilogic@0 180 frameNo = int(time * sampleRate + 0.00001);
lbajardsilogic@0 181
lbajardsilogic@0 182 } else {
lbajardsilogic@0 183
lbajardsilogic@0 184 frameNo = numeric.toInt(&ok);
lbajardsilogic@0 185
lbajardsilogic@0 186 if (timeUnits == CSVFormatDialog::TimeWindows) {
lbajardsilogic@0 187 frameNo *= windowSize;
lbajardsilogic@0 188 }
lbajardsilogic@0 189 }
lbajardsilogic@0 190
lbajardsilogic@0 191 if (!ok) {
lbajardsilogic@0 192 if (warnings < warnLimit) {
lbajardsilogic@0 193 std::cerr << "WARNING: CSVFileReader::load: "
lbajardsilogic@0 194 << "Bad time format (\"" << s.toStdString()
lbajardsilogic@0 195 << "\") in data line "
lbajardsilogic@0 196 << lineno << ":" << std::endl;
lbajardsilogic@0 197 std::cerr << line.toStdString() << std::endl;
lbajardsilogic@0 198 } else if (warnings == warnLimit) {
lbajardsilogic@0 199 std::cerr << "WARNING: Too many warnings" << std::endl;
lbajardsilogic@0 200 }
lbajardsilogic@0 201 ++warnings;
lbajardsilogic@0 202 }
lbajardsilogic@0 203 } else {
lbajardsilogic@0 204 tidyList.push_back(s);
lbajardsilogic@0 205 }
lbajardsilogic@0 206 }
lbajardsilogic@0 207
lbajardsilogic@0 208 if (modelType == CSVFormatDialog::OneDimensionalModel) {
lbajardsilogic@0 209
lbajardsilogic@0 210 SparseOneDimensionalModel::Point point
lbajardsilogic@0 211 (frameNo,
lbajardsilogic@0 212 tidyList.size() > 0 ? tidyList[tidyList.size()-1] :
lbajardsilogic@0 213 QString("%1").arg(lineno));
lbajardsilogic@0 214
lbajardsilogic@0 215 model1->addPoint(point);
lbajardsilogic@0 216
lbajardsilogic@0 217 } else if (modelType == CSVFormatDialog::TwoDimensionalModel) {
lbajardsilogic@0 218
lbajardsilogic@0 219 SparseTimeValueModel::Point point
lbajardsilogic@0 220 (frameNo,
lbajardsilogic@0 221 tidyList.size() > 0 ? tidyList[0].toFloat() : 0.0,
lbajardsilogic@0 222 tidyList.size() > 1 ? tidyList[1] : QString("%1").arg(lineno));
lbajardsilogic@0 223
lbajardsilogic@0 224 model2->addPoint(point);
lbajardsilogic@0 225
lbajardsilogic@0 226 } else if (modelType == CSVFormatDialog::ThreeDimensionalModel) {
lbajardsilogic@0 227
lbajardsilogic@0 228 DenseThreeDimensionalModel::Column values;
lbajardsilogic@0 229
lbajardsilogic@0 230 for (int i = 0; i < tidyList.size(); ++i) {
lbajardsilogic@0 231
lbajardsilogic@0 232 bool ok = false;
lbajardsilogic@0 233 float value = list[i].toFloat(&ok);
lbajardsilogic@0 234 values.push_back(value);
lbajardsilogic@0 235
lbajardsilogic@0 236 if ((lineno == 0 && i == 0) || value < min) min = value;
lbajardsilogic@0 237 if ((lineno == 0 && i == 0) || value > max) max = value;
lbajardsilogic@0 238
lbajardsilogic@0 239 if (!ok) {
lbajardsilogic@0 240 if (warnings < warnLimit) {
lbajardsilogic@0 241 std::cerr << "WARNING: CSVFileReader::load: "
lbajardsilogic@0 242 << "Non-numeric value in data line " << lineno
lbajardsilogic@0 243 << ":" << std::endl;
lbajardsilogic@0 244 std::cerr << line.toStdString() << std::endl;
lbajardsilogic@0 245 ++warnings;
lbajardsilogic@0 246 } else if (warnings == warnLimit) {
lbajardsilogic@0 247 std::cerr << "WARNING: Too many warnings" << std::endl;
lbajardsilogic@0 248 }
lbajardsilogic@0 249 }
lbajardsilogic@0 250 }
lbajardsilogic@0 251
lbajardsilogic@0 252 std::cerr << "Setting bin values for count " << lineno << ", frame "
lbajardsilogic@0 253 << frameNo << ", time " << RealTime::frame2RealTime(frameNo, sampleRate) << std::endl;
lbajardsilogic@0 254
lbajardsilogic@0 255 model3->setColumn(frameNo / model3->getResolution(), values);
lbajardsilogic@0 256 }
lbajardsilogic@0 257
lbajardsilogic@0 258 ++lineno;
lbajardsilogic@0 259 if (timingType == CSVFormatDialog::ImplicitTiming ||
lbajardsilogic@0 260 list.size() == 0) {
lbajardsilogic@0 261 frameNo += windowSize;
lbajardsilogic@0 262 }
lbajardsilogic@0 263 }
lbajardsilogic@0 264
lbajardsilogic@0 265 if (modelType == CSVFormatDialog::ThreeDimensionalModel) {
lbajardsilogic@0 266 model3->setMinimumLevel(min);
lbajardsilogic@0 267 model3->setMaximumLevel(max);
lbajardsilogic@0 268 }
lbajardsilogic@0 269
lbajardsilogic@0 270 return model;
lbajardsilogic@0 271 }
lbajardsilogic@0 272
lbajardsilogic@0 273
lbajardsilogic@0 274 CSVFormatDialog::CSVFormatDialog(QWidget *parent, QFile *file,
lbajardsilogic@0 275 size_t defaultSampleRate) :
lbajardsilogic@0 276 QDialog(parent),
lbajardsilogic@0 277 m_modelType(OneDimensionalModel),
lbajardsilogic@0 278 m_timingType(ExplicitTiming),
lbajardsilogic@0 279 m_timeUnits(TimeAudioFrames),
lbajardsilogic@0 280 m_separator("")
lbajardsilogic@0 281 {
lbajardsilogic@0 282 setModal(true);
lbajardsilogic@0 283 setWindowTitle(tr("Select Data Format"));
lbajardsilogic@0 284
lbajardsilogic@0 285 (void)guessFormat(file);
lbajardsilogic@0 286
lbajardsilogic@0 287 QGridLayout *layout = new QGridLayout;
lbajardsilogic@0 288
lbajardsilogic@0 289 layout->addWidget(new QLabel(tr("\nPlease select the correct data format for this file.\n")),
lbajardsilogic@0 290 0, 0, 1, 4);
lbajardsilogic@0 291
lbajardsilogic@0 292 layout->addWidget(new QLabel(tr("Each row specifies:")), 1, 0);
lbajardsilogic@0 293
lbajardsilogic@0 294 m_modelTypeCombo = new QComboBox;
lbajardsilogic@0 295 m_modelTypeCombo->addItem(tr("A point in time"));
lbajardsilogic@0 296 m_modelTypeCombo->addItem(tr("A value at a time"));
lbajardsilogic@0 297 m_modelTypeCombo->addItem(tr("A set of values"));
lbajardsilogic@0 298 layout->addWidget(m_modelTypeCombo, 1, 1, 1, 2);
lbajardsilogic@0 299 connect(m_modelTypeCombo, SIGNAL(activated(int)),
lbajardsilogic@0 300 this, SLOT(modelTypeChanged(int)));
lbajardsilogic@0 301 m_modelTypeCombo->setCurrentIndex(int(m_modelType));
lbajardsilogic@0 302
lbajardsilogic@0 303 layout->addWidget(new QLabel(tr("The first column contains:")), 2, 0);
lbajardsilogic@0 304
lbajardsilogic@0 305 m_timingTypeCombo = new QComboBox;
lbajardsilogic@0 306 m_timingTypeCombo->addItem(tr("Time, in seconds"));
lbajardsilogic@0 307 m_timingTypeCombo->addItem(tr("Time, in audio sample frames"));
lbajardsilogic@0 308 m_timingTypeCombo->addItem(tr("Data (rows are consecutive in time)"));
lbajardsilogic@0 309 layout->addWidget(m_timingTypeCombo, 2, 1, 1, 2);
lbajardsilogic@0 310 connect(m_timingTypeCombo, SIGNAL(activated(int)),
lbajardsilogic@0 311 this, SLOT(timingTypeChanged(int)));
lbajardsilogic@0 312 m_timingTypeCombo->setCurrentIndex(m_timingType == ExplicitTiming ?
lbajardsilogic@0 313 m_timeUnits == TimeSeconds ? 0 : 1 : 2);
lbajardsilogic@0 314
lbajardsilogic@0 315 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
lbajardsilogic@0 316 layout->addWidget(m_sampleRateLabel, 3, 0);
lbajardsilogic@0 317
lbajardsilogic@0 318 size_t sampleRates[] = {
lbajardsilogic@0 319 8000, 11025, 12000, 22050, 24000, 32000,
lbajardsilogic@0 320 44100, 48000, 88200, 96000, 176400, 192000
lbajardsilogic@0 321 };
lbajardsilogic@0 322
lbajardsilogic@0 323 m_sampleRateCombo = new QComboBox;
lbajardsilogic@0 324 m_sampleRate = defaultSampleRate;
lbajardsilogic@0 325 for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) {
lbajardsilogic@0 326 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i]));
lbajardsilogic@0 327 if (sampleRates[i] == m_sampleRate) m_sampleRateCombo->setCurrentIndex(i);
lbajardsilogic@0 328 }
lbajardsilogic@0 329 m_sampleRateCombo->setEditable(true);
lbajardsilogic@0 330
lbajardsilogic@0 331 layout->addWidget(m_sampleRateCombo, 3, 1);
lbajardsilogic@0 332 connect(m_sampleRateCombo, SIGNAL(activated(QString)),
lbajardsilogic@0 333 this, SLOT(sampleRateChanged(QString)));
lbajardsilogic@0 334 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
lbajardsilogic@0 335 this, SLOT(sampleRateChanged(QString)));
lbajardsilogic@0 336
lbajardsilogic@0 337 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
lbajardsilogic@0 338 layout->addWidget(m_windowSizeLabel, 4, 0);
lbajardsilogic@0 339
lbajardsilogic@0 340 m_windowSizeCombo = new QComboBox;
lbajardsilogic@0 341 m_windowSize = 1024;
lbajardsilogic@0 342 for (int i = 0; i <= 16; ++i) {
lbajardsilogic@0 343 int value = 1 << i;
lbajardsilogic@0 344 m_windowSizeCombo->addItem(QString("%1").arg(value));
lbajardsilogic@0 345 if (value == int(m_windowSize)) m_windowSizeCombo->setCurrentIndex(i);
lbajardsilogic@0 346 }
lbajardsilogic@0 347 m_windowSizeCombo->setEditable(true);
lbajardsilogic@0 348
lbajardsilogic@0 349 layout->addWidget(m_windowSizeCombo, 4, 1);
lbajardsilogic@0 350 connect(m_windowSizeCombo, SIGNAL(activated(QString)),
lbajardsilogic@0 351 this, SLOT(windowSizeChanged(QString)));
lbajardsilogic@0 352 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
lbajardsilogic@0 353 this, SLOT(windowSizeChanged(QString)));
lbajardsilogic@0 354
lbajardsilogic@0 355 layout->addWidget(new QLabel(tr("\nExample data from file:")), 5, 0, 1, 4);
lbajardsilogic@0 356
lbajardsilogic@0 357 m_exampleWidget = new QTableWidget
lbajardsilogic@0 358 (min(10, m_example.size()), m_maxExampleCols);
lbajardsilogic@0 359
lbajardsilogic@0 360 layout->addWidget(m_exampleWidget, 6, 0, 1, 4);
lbajardsilogic@0 361 layout->setColumnStretch(3, 10);
lbajardsilogic@0 362 layout->setRowStretch(4, 10);
lbajardsilogic@0 363
lbajardsilogic@0 364 QPushButton *ok = new QPushButton(tr("OK"));
lbajardsilogic@0 365 connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
lbajardsilogic@0 366 ok->setDefault(true);
lbajardsilogic@0 367
lbajardsilogic@0 368 QPushButton *cancel = new QPushButton(tr("Cancel"));
lbajardsilogic@0 369 connect(cancel, SIGNAL(clicked()), this, SLOT(reject()));
lbajardsilogic@0 370
lbajardsilogic@0 371 QHBoxLayout *buttonLayout = new QHBoxLayout;
lbajardsilogic@0 372 buttonLayout->addStretch(1);
lbajardsilogic@0 373 buttonLayout->addWidget(ok);
lbajardsilogic@0 374 buttonLayout->addWidget(cancel);
lbajardsilogic@0 375
lbajardsilogic@0 376 QVBoxLayout *mainLayout = new QVBoxLayout;
lbajardsilogic@0 377 mainLayout->addLayout(layout);
lbajardsilogic@0 378 mainLayout->addLayout(buttonLayout);
lbajardsilogic@0 379
lbajardsilogic@0 380 setLayout(mainLayout);
lbajardsilogic@0 381
lbajardsilogic@0 382 timingTypeChanged(m_timingTypeCombo->currentIndex());
lbajardsilogic@0 383 }
lbajardsilogic@0 384
lbajardsilogic@0 385 CSVFormatDialog::~CSVFormatDialog()
lbajardsilogic@0 386 {
lbajardsilogic@0 387 }
lbajardsilogic@0 388
lbajardsilogic@0 389 void
lbajardsilogic@0 390 CSVFormatDialog::populateExample()
lbajardsilogic@0 391 {
lbajardsilogic@0 392 m_exampleWidget->setColumnCount
lbajardsilogic@0 393 (m_timingType == ExplicitTiming ?
lbajardsilogic@0 394 m_maxExampleCols - 1 : m_maxExampleCols);
lbajardsilogic@0 395
lbajardsilogic@0 396 m_exampleWidget->setHorizontalHeaderLabels(QStringList());
lbajardsilogic@0 397
lbajardsilogic@0 398 for (int i = 0; i < m_example.size(); ++i) {
lbajardsilogic@0 399 for (int j = 0; j < m_example[i].size(); ++j) {
lbajardsilogic@0 400
lbajardsilogic@0 401 QTableWidgetItem *item = new QTableWidgetItem(m_example[i][j]);
lbajardsilogic@0 402
lbajardsilogic@0 403 if (j == 0) {
lbajardsilogic@0 404 if (m_timingType == ExplicitTiming) {
lbajardsilogic@0 405 m_exampleWidget->setVerticalHeaderItem(i, item);
lbajardsilogic@0 406 continue;
lbajardsilogic@0 407 } else {
lbajardsilogic@0 408 QTableWidgetItem *header =
lbajardsilogic@0 409 new QTableWidgetItem(QString("%1").arg(i));
lbajardsilogic@0 410 header->setFlags(Qt::ItemIsEnabled);
lbajardsilogic@0 411 m_exampleWidget->setVerticalHeaderItem(i, header);
lbajardsilogic@0 412 }
lbajardsilogic@0 413 }
lbajardsilogic@0 414 int index = j;
lbajardsilogic@0 415 if (m_timingType == ExplicitTiming) --index;
lbajardsilogic@0 416 item->setFlags(Qt::ItemIsEnabled);
lbajardsilogic@0 417 m_exampleWidget->setItem(i, index, item);
lbajardsilogic@0 418 }
lbajardsilogic@0 419 }
lbajardsilogic@0 420 }
lbajardsilogic@0 421
lbajardsilogic@0 422 void
lbajardsilogic@0 423 CSVFormatDialog::modelTypeChanged(int type)
lbajardsilogic@0 424 {
lbajardsilogic@0 425 m_modelType = (ModelType)type;
lbajardsilogic@0 426
lbajardsilogic@0 427 if (m_modelType == ThreeDimensionalModel) {
lbajardsilogic@0 428 // We can't load 3d models with explicit timing, because the 3d
lbajardsilogic@0 429 // model is dense so we need a fixed sample increment
lbajardsilogic@0 430 m_timingTypeCombo->setCurrentIndex(2);
lbajardsilogic@0 431 timingTypeChanged(2);
lbajardsilogic@0 432 }
lbajardsilogic@0 433 }
lbajardsilogic@0 434
lbajardsilogic@0 435 void
lbajardsilogic@0 436 CSVFormatDialog::timingTypeChanged(int type)
lbajardsilogic@0 437 {
lbajardsilogic@0 438 switch (type) {
lbajardsilogic@0 439
lbajardsilogic@0 440 case 0:
lbajardsilogic@0 441 m_timingType = ExplicitTiming;
lbajardsilogic@0 442 m_timeUnits = TimeSeconds;
lbajardsilogic@0 443 m_sampleRateCombo->setEnabled(false);
lbajardsilogic@0 444 m_sampleRateLabel->setEnabled(false);
lbajardsilogic@0 445 m_windowSizeCombo->setEnabled(false);
lbajardsilogic@0 446 m_windowSizeLabel->setEnabled(false);
lbajardsilogic@0 447 if (m_modelType == ThreeDimensionalModel) {
lbajardsilogic@0 448 m_modelTypeCombo->setCurrentIndex(1);
lbajardsilogic@0 449 modelTypeChanged(1);
lbajardsilogic@0 450 }
lbajardsilogic@0 451 break;
lbajardsilogic@0 452
lbajardsilogic@0 453 case 1:
lbajardsilogic@0 454 m_timingType = ExplicitTiming;
lbajardsilogic@0 455 m_timeUnits = TimeAudioFrames;
lbajardsilogic@0 456 m_sampleRateCombo->setEnabled(true);
lbajardsilogic@0 457 m_sampleRateLabel->setEnabled(true);
lbajardsilogic@0 458 m_windowSizeCombo->setEnabled(false);
lbajardsilogic@0 459 m_windowSizeLabel->setEnabled(false);
lbajardsilogic@0 460 if (m_modelType == ThreeDimensionalModel) {
lbajardsilogic@0 461 m_modelTypeCombo->setCurrentIndex(1);
lbajardsilogic@0 462 modelTypeChanged(1);
lbajardsilogic@0 463 }
lbajardsilogic@0 464 break;
lbajardsilogic@0 465
lbajardsilogic@0 466 case 2:
lbajardsilogic@0 467 m_timingType = ImplicitTiming;
lbajardsilogic@0 468 m_timeUnits = TimeWindows;
lbajardsilogic@0 469 m_sampleRateCombo->setEnabled(true);
lbajardsilogic@0 470 m_sampleRateLabel->setEnabled(true);
lbajardsilogic@0 471 m_windowSizeCombo->setEnabled(true);
lbajardsilogic@0 472 m_windowSizeLabel->setEnabled(true);
lbajardsilogic@0 473 break;
lbajardsilogic@0 474 }
lbajardsilogic@0 475
lbajardsilogic@0 476 populateExample();
lbajardsilogic@0 477 }
lbajardsilogic@0 478
lbajardsilogic@0 479 void
lbajardsilogic@0 480 CSVFormatDialog::sampleRateChanged(QString rateString)
lbajardsilogic@0 481 {
lbajardsilogic@0 482 bool ok = false;
lbajardsilogic@0 483 int sampleRate = rateString.toInt(&ok);
lbajardsilogic@0 484 if (ok) m_sampleRate = sampleRate;
lbajardsilogic@0 485 }
lbajardsilogic@0 486
lbajardsilogic@0 487 void
lbajardsilogic@0 488 CSVFormatDialog::windowSizeChanged(QString sizeString)
lbajardsilogic@0 489 {
lbajardsilogic@0 490 bool ok = false;
lbajardsilogic@0 491 int size = sizeString.toInt(&ok);
lbajardsilogic@0 492 if (ok) m_windowSize = size;
lbajardsilogic@0 493 }
lbajardsilogic@0 494
lbajardsilogic@0 495 bool
lbajardsilogic@0 496 CSVFormatDialog::guessFormat(QFile *file)
lbajardsilogic@0 497 {
lbajardsilogic@0 498 QTextStream in(file);
lbajardsilogic@0 499 in.seek(0);
lbajardsilogic@0 500
lbajardsilogic@0 501 unsigned int lineno = 0;
lbajardsilogic@0 502
lbajardsilogic@0 503 bool nonIncreasingPrimaries = false;
lbajardsilogic@0 504 bool nonNumericPrimaries = false;
lbajardsilogic@0 505 bool floatPrimaries = false;
lbajardsilogic@0 506 bool variableItemCount = false;
lbajardsilogic@0 507 int itemCount = 1;
lbajardsilogic@0 508 int earliestNonNumericItem = -1;
lbajardsilogic@0 509
lbajardsilogic@0 510 float prevPrimary = 0.0;
lbajardsilogic@0 511
lbajardsilogic@0 512 m_maxExampleCols = 0;
lbajardsilogic@0 513
lbajardsilogic@0 514 while (!in.atEnd()) {
lbajardsilogic@0 515
lbajardsilogic@0 516 QString line = in.readLine().trimmed();
lbajardsilogic@0 517 if (line.startsWith("#")) continue;
lbajardsilogic@0 518
lbajardsilogic@0 519 if (m_separator == "") {
lbajardsilogic@0 520 //!!! to do: ask the user
lbajardsilogic@0 521 if (line.split(",").size() >= 2) m_separator = ",";
lbajardsilogic@0 522 else if (line.split("\t").size() >= 2) m_separator = "\t";
lbajardsilogic@0 523 else if (line.split("|").size() >= 2) m_separator = "|";
lbajardsilogic@0 524 else if (line.split("/").size() >= 2) m_separator = "/";
lbajardsilogic@0 525 else if (line.split(":").size() >= 2) m_separator = ":";
lbajardsilogic@0 526 else m_separator = " ";
lbajardsilogic@0 527 }
lbajardsilogic@0 528
lbajardsilogic@0 529 QStringList list = line.split(m_separator);
lbajardsilogic@0 530 QStringList tidyList;
lbajardsilogic@0 531
lbajardsilogic@0 532 for (int i = 0; i < list.size(); ++i) {
lbajardsilogic@0 533
lbajardsilogic@0 534 QString s(list[i]);
lbajardsilogic@0 535 bool numeric = false;
lbajardsilogic@0 536
lbajardsilogic@0 537 if (s.length() >= 2 && s.startsWith("\"") && s.endsWith("\"")) {
lbajardsilogic@0 538 s = s.mid(1, s.length() - 2);
lbajardsilogic@0 539 } else if (s.length() >= 2 && s.startsWith("'") && s.endsWith("'")) {
lbajardsilogic@0 540 s = s.mid(1, s.length() - 2);
lbajardsilogic@0 541 } else {
lbajardsilogic@0 542 (void)s.toFloat(&numeric);
lbajardsilogic@0 543 }
lbajardsilogic@0 544
lbajardsilogic@0 545 tidyList.push_back(s);
lbajardsilogic@0 546
lbajardsilogic@0 547 if (lineno == 0 || (list.size() < itemCount)) {
lbajardsilogic@0 548 itemCount = list.size();
lbajardsilogic@0 549 } else {
lbajardsilogic@0 550 if (itemCount != list.size()) {
lbajardsilogic@0 551 variableItemCount = true;
lbajardsilogic@0 552 }
lbajardsilogic@0 553 }
lbajardsilogic@0 554
lbajardsilogic@0 555 if (i == 0) { // primary
lbajardsilogic@0 556
lbajardsilogic@0 557 if (numeric) {
lbajardsilogic@0 558
lbajardsilogic@0 559 float primary = s.toFloat();
lbajardsilogic@0 560
lbajardsilogic@0 561 if (lineno > 0 && primary <= prevPrimary) {
lbajardsilogic@0 562 nonIncreasingPrimaries = true;
lbajardsilogic@0 563 }
lbajardsilogic@0 564
lbajardsilogic@0 565 if (s.contains(".") || s.contains(",")) {
lbajardsilogic@0 566 floatPrimaries = true;
lbajardsilogic@0 567 }
lbajardsilogic@0 568
lbajardsilogic@0 569 prevPrimary = primary;
lbajardsilogic@0 570
lbajardsilogic@0 571 } else {
lbajardsilogic@0 572 nonNumericPrimaries = true;
lbajardsilogic@0 573 }
lbajardsilogic@0 574 } else { // secondary
lbajardsilogic@0 575
lbajardsilogic@0 576 if (!numeric) {
lbajardsilogic@0 577 if (earliestNonNumericItem < 0 ||
lbajardsilogic@0 578 i < earliestNonNumericItem) {
lbajardsilogic@0 579 earliestNonNumericItem = i;
lbajardsilogic@0 580 }
lbajardsilogic@0 581 }
lbajardsilogic@0 582 }
lbajardsilogic@0 583 }
lbajardsilogic@0 584
lbajardsilogic@0 585 if (lineno < 10) {
lbajardsilogic@0 586 m_example.push_back(tidyList);
lbajardsilogic@0 587 if (lineno == 0 || tidyList.size() > m_maxExampleCols) {
lbajardsilogic@0 588 m_maxExampleCols = tidyList.size();
lbajardsilogic@0 589 }
lbajardsilogic@0 590 }
lbajardsilogic@0 591
lbajardsilogic@0 592 ++lineno;
lbajardsilogic@0 593
lbajardsilogic@0 594 if (lineno == 50) break;
lbajardsilogic@0 595 }
lbajardsilogic@0 596
lbajardsilogic@0 597 if (nonNumericPrimaries || nonIncreasingPrimaries) {
lbajardsilogic@0 598
lbajardsilogic@0 599 // Primaries are probably not a series of times
lbajardsilogic@0 600
lbajardsilogic@0 601 m_timingType = ImplicitTiming;
lbajardsilogic@0 602 m_timeUnits = TimeWindows;
lbajardsilogic@0 603
lbajardsilogic@0 604 if (nonNumericPrimaries) {
lbajardsilogic@0 605 m_modelType = OneDimensionalModel;
lbajardsilogic@0 606 } else if (itemCount == 1 || variableItemCount ||
lbajardsilogic@0 607 (earliestNonNumericItem != -1)) {
lbajardsilogic@0 608 m_modelType = TwoDimensionalModel;
lbajardsilogic@0 609 } else {
lbajardsilogic@0 610 m_modelType = ThreeDimensionalModel;
lbajardsilogic@0 611 }
lbajardsilogic@0 612
lbajardsilogic@0 613 } else {
lbajardsilogic@0 614
lbajardsilogic@0 615 // Increasing numeric primaries -- likely to be time
lbajardsilogic@0 616
lbajardsilogic@0 617 m_timingType = ExplicitTiming;
lbajardsilogic@0 618
lbajardsilogic@0 619 if (floatPrimaries) {
lbajardsilogic@0 620 m_timeUnits = TimeSeconds;
lbajardsilogic@0 621 } else {
lbajardsilogic@0 622 m_timeUnits = TimeAudioFrames;
lbajardsilogic@0 623 }
lbajardsilogic@0 624
lbajardsilogic@0 625 if (itemCount == 1) {
lbajardsilogic@0 626 m_modelType = OneDimensionalModel;
lbajardsilogic@0 627 } else if (variableItemCount || (earliestNonNumericItem != -1)) {
lbajardsilogic@0 628 if (earliestNonNumericItem != -1 && earliestNonNumericItem < 2) {
lbajardsilogic@0 629 m_modelType = OneDimensionalModel;
lbajardsilogic@0 630 } else {
lbajardsilogic@0 631 m_modelType = TwoDimensionalModel;
lbajardsilogic@0 632 }
lbajardsilogic@0 633 } else {
lbajardsilogic@0 634 m_modelType = ThreeDimensionalModel;
lbajardsilogic@0 635 }
lbajardsilogic@0 636 }
lbajardsilogic@0 637
lbajardsilogic@0 638 std::cerr << "Estimated model type: " << m_modelType << std::endl;
lbajardsilogic@0 639 std::cerr << "Estimated timing type: " << m_timingType << std::endl;
lbajardsilogic@0 640 std::cerr << "Estimated units: " << m_timeUnits << std::endl;
lbajardsilogic@0 641
lbajardsilogic@0 642 in.seek(0);
lbajardsilogic@0 643 return true;
lbajardsilogic@0 644 }