annotate widgets/CSVFormatDialog.cpp @ 1431:af824022bffd single-point

Begin fixing the various snap operations. Also remove SnapNearest, which is never used and seems to consume more lines of code than the rest!
author Chris Cannam
date Wed, 20 Mar 2019 14:59:34 +0000
parents 0930a27ebea2
children d3ef60b6ae93
rev   line source
Chris@378 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@378 2
Chris@378 3 /*
Chris@378 4 Sonic Visualiser
Chris@378 5 An audio file viewer and annotation editor.
Chris@378 6 Centre for Digital Music, Queen Mary, University of London.
Chris@1319 7 This file copyright 2006-2018 Chris Cannam and QMUL.
Chris@378 8
Chris@378 9 This program is free software; you can redistribute it and/or
Chris@378 10 modify it under the terms of the GNU General Public License as
Chris@378 11 published by the Free Software Foundation; either version 2 of the
Chris@378 12 License, or (at your option) any later version. See the file
Chris@378 13 COPYING included with this distribution for more information.
Chris@378 14 */
Chris@378 15
Chris@378 16 #include "CSVFormatDialog.h"
Chris@378 17
Chris@561 18 #include "layer/LayerFactory.h"
Chris@561 19
Chris@674 20 #include "TextAbbrev.h"
Chris@674 21
Chris@378 22 #include <QFrame>
Chris@378 23 #include <QGridLayout>
Chris@378 24 #include <QPushButton>
Chris@378 25 #include <QHBoxLayout>
Chris@378 26 #include <QVBoxLayout>
Chris@378 27 #include <QTableWidget>
Chris@378 28 #include <QComboBox>
Chris@378 29 #include <QLabel>
Chris@512 30 #include <QDialogButtonBox>
Chris@378 31
Chris@560 32 #include <iostream>
Chris@913 33 #include <cmath>
Chris@378 34
Chris@682 35 #include "base/Debug.h"
Chris@682 36
Chris@1413 37 CSVFormatDialog::CSVFormatDialog(QWidget *parent,
Chris@1413 38 CSVFormat format,
Chris@581 39 int maxDisplayCols) :
Chris@378 40 QDialog(parent),
Chris@1413 41 m_csvFilePath(""),
Chris@1413 42 m_referenceSampleRate(0),
Chris@581 43 m_format(format),
Chris@581 44 m_maxDisplayCols(maxDisplayCols),
Chris@581 45 m_fuzzyColumn(-1)
Chris@378 46 {
Chris@1413 47 init();
Chris@1413 48 }
Chris@1413 49
Chris@1413 50 CSVFormatDialog::CSVFormatDialog(QWidget *parent,
Chris@1413 51 QString csvFilePath,
Chris@1413 52 sv_samplerate_t referenceSampleRate,
Chris@1413 53 int maxDisplayCols) :
Chris@1413 54 QDialog(parent),
Chris@1413 55 m_csvFilePath(csvFilePath),
Chris@1413 56 m_referenceSampleRate(referenceSampleRate),
Chris@1413 57 m_maxDisplayCols(maxDisplayCols),
Chris@1413 58 m_fuzzyColumn(-1)
Chris@1413 59 {
Chris@1413 60 m_format = CSVFormat(csvFilePath);
Chris@1413 61 m_format.setSampleRate(referenceSampleRate);
Chris@1413 62 init();
Chris@1413 63 }
Chris@1413 64
Chris@1413 65 CSVFormatDialog::~CSVFormatDialog()
Chris@1413 66 {
Chris@1413 67 }
Chris@1413 68
Chris@1413 69 static int sampleRates[] = {
Chris@1413 70 8000, 11025, 12000, 22050, 24000, 32000,
Chris@1413 71 44100, 48000, 88200, 96000, 176400, 192000
Chris@1413 72 };
Chris@1413 73
Chris@1413 74 void
Chris@1413 75 CSVFormatDialog::init()
Chris@1413 76 {
Chris@378 77 setModal(true);
Chris@378 78 setWindowTitle(tr("Select Data Format"));
Chris@1413 79
Chris@378 80 QGridLayout *layout = new QGridLayout;
Chris@378 81
Chris@560 82 int row = 0;
Chris@378 83
Chris@1318 84 layout->addWidget
Chris@1318 85 (new QLabel(tr("Please select the correct data format for this file.")),
Chris@1318 86 row++, 0, 1, 4);
Chris@560 87
Chris@1413 88 m_exampleFrame = nullptr;
Chris@1413 89 m_exampleFrameRow = row++;
Chris@1413 90
Chris@1413 91 std::set<QChar> plausible = m_format.getPlausibleSeparators();
Chris@1413 92 SVDEBUG << "Have " << plausible.size() << " plausible separator(s)" << endl;
Chris@1413 93
Chris@1413 94 if (m_csvFilePath != "" && plausible.size() > 1) {
Chris@1413 95 // can only update when separator changed if we still have a
Chris@1413 96 // file to refer to
Chris@1413 97 layout->addWidget(new QLabel(tr("Column separator:")), row, 0);
Chris@1413 98 m_separatorCombo = new QComboBox;
Chris@1413 99 for (QChar c: plausible) {
Chris@1413 100 m_separatorCombo->addItem(QString(c));
Chris@1413 101 if (c == m_format.getSeparator()) {
Chris@1413 102 m_separatorCombo->setCurrentIndex(m_separatorCombo->count()-1);
Chris@1413 103 }
Chris@1413 104 }
Chris@1413 105 m_separatorCombo->setEditable(false);
Chris@1413 106
Chris@1413 107 layout->addWidget(m_separatorCombo, row++, 1);
Chris@1413 108 connect(m_separatorCombo, SIGNAL(activated(QString)),
Chris@1413 109 this, SLOT(separatorChanged(QString)));
Chris@1413 110 }
Chris@1413 111
Chris@1413 112 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0);
Chris@1413 113
Chris@1413 114 m_timingTypeCombo = new QComboBox;
Chris@1413 115
Chris@1413 116 m_timingLabels = {
Chris@1413 117 { TimingExplicitSeconds, tr("Explicitly, in seconds") },
Chris@1413 118 { TimingExplicitMsec, tr("Explicitly, in milliseconds") },
Chris@1413 119 { TimingExplicitSamples, tr("Explicitly, in audio sample frames") },
Chris@1413 120 { TimingImplicit, tr("Implicitly: rows are equally spaced in time") }
Chris@1413 121 };
Chris@1413 122
Chris@1413 123 for (auto &l: m_timingLabels) {
Chris@1413 124 m_timingTypeCombo->addItem(l.second);
Chris@1413 125 }
Chris@1413 126
Chris@1413 127 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2);
Chris@1413 128
Chris@1413 129 connect(m_timingTypeCombo, SIGNAL(activated(int)),
Chris@1413 130 this, SLOT(timingTypeChanged(int)));
Chris@1413 131
Chris@1413 132 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
Chris@1413 133 layout->addWidget(m_sampleRateLabel, row, 0);
Chris@1413 134
Chris@1413 135 m_sampleRateCombo = new QComboBox;
Chris@1413 136 for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) {
Chris@1413 137 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i]));
Chris@1413 138 }
Chris@1413 139 m_sampleRateCombo->setEditable(true);
Chris@1413 140
Chris@1413 141 layout->addWidget(m_sampleRateCombo, row++, 1);
Chris@1413 142 connect(m_sampleRateCombo, SIGNAL(activated(QString)),
Chris@1413 143 this, SLOT(sampleRateChanged(QString)));
Chris@1413 144 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
Chris@1413 145 this, SLOT(sampleRateChanged(QString)));
Chris@1413 146
Chris@1413 147 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
Chris@1413 148 layout->addWidget(m_windowSizeLabel, row, 0);
Chris@1413 149
Chris@1413 150 m_windowSizeCombo = new QComboBox;
Chris@1413 151 for (int i = 0; i <= 16; ++i) {
Chris@1413 152 int value = 1 << i;
Chris@1413 153 m_windowSizeCombo->addItem(QString("%1").arg(value));
Chris@1413 154 }
Chris@1413 155 m_windowSizeCombo->setEditable(true);
Chris@1413 156
Chris@1413 157 layout->addWidget(m_windowSizeCombo, row++, 1);
Chris@1413 158 connect(m_windowSizeCombo, SIGNAL(activated(QString)),
Chris@1413 159 this, SLOT(windowSizeChanged(QString)));
Chris@1413 160 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
Chris@1413 161 this, SLOT(windowSizeChanged(QString)));
Chris@1413 162
Chris@1413 163 m_modelLabel = new QLabel;
Chris@1413 164 QFont f(m_modelLabel->font());
Chris@1413 165 f.setItalic(true);
Chris@1413 166 m_modelLabel->setFont(f);
Chris@1413 167 layout->addWidget(m_modelLabel, row++, 0, 1, 4);
Chris@1413 168
Chris@1413 169 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
Chris@1413 170 QDialogButtonBox::Cancel);
Chris@1413 171 layout->addWidget(bb, row++, 0, 1, 4);
Chris@1413 172 connect(bb, SIGNAL(accepted()), this, SLOT(accept()));
Chris@1413 173 connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
Chris@1413 174
Chris@1413 175 setLayout(layout);
Chris@1413 176
Chris@1413 177 repopulate();
Chris@1413 178 }
Chris@1413 179
Chris@1413 180 void
Chris@1413 181 CSVFormatDialog::repopulate()
Chris@1413 182 {
Chris@1413 183 SVCERR << "CSVFormatDialog::repopulate()" << endl;
Chris@1413 184
Chris@1413 185 QGridLayout *layout = qobject_cast<QGridLayout *>(this->layout());
Chris@1413 186
Chris@560 187 QFrame *exampleFrame = new QFrame;
Chris@560 188 exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
Chris@560 189 exampleFrame->setLineWidth(2);
Chris@560 190 QGridLayout *exampleLayout = new QGridLayout;
Chris@561 191 exampleLayout->setSpacing(4);
Chris@560 192 exampleFrame->setLayout(exampleLayout);
Chris@560 193
Chris@560 194 QPalette palette = exampleFrame->palette();
Chris@560 195 palette.setColor(QPalette::Window, palette.color(QPalette::Base));
Chris@560 196 exampleFrame->setPalette(palette);
Chris@560 197
Chris@560 198 QFont fp;
Chris@908 199 fp.setPointSize(int(floor(fp.pointSize() * 0.9)));
Chris@560 200
Chris@1413 201 int columns = m_format.getColumnCount();
Chris@560 202 QList<QStringList> example = m_format.getExample();
Chris@560 203
Chris@1413 204 m_columnPurposeCombos.clear();
Chris@1413 205
Chris@560 206 for (int i = 0; i < columns; ++i) {
Chris@581 207
Chris@560 208 QComboBox *cpc = new QComboBox;
Chris@560 209 m_columnPurposeCombos.push_back(cpc);
Chris@560 210 exampleLayout->addWidget(cpc, 0, i);
Chris@581 211 connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int)));
Chris@1318 212
Chris@581 213 if (i == m_maxDisplayCols && columns > i + 2) {
Chris@581 214 m_fuzzyColumn = i;
Chris@1318 215
Chris@1319 216 cpc->addItem(tr("<ignore>"));
Chris@1319 217 cpc->addItem(tr("Values"));
Chris@1319 218 cpc->setCurrentIndex
Chris@1319 219 (m_format.getColumnPurpose(i-1) ==
Chris@1319 220 CSVFormat::ColumnUnknown ? 0 : 1);
Chris@1319 221
Chris@1318 222 exampleLayout->addWidget
Chris@1318 223 (new QLabel(tr("(%1 more)").arg(columns - i)), 1, i);
Chris@581 224 break;
Chris@581 225 }
Chris@560 226
Chris@1319 227 // NB must be in the same order as the CSVFormat::ColumnPurpose enum
Chris@1319 228 cpc->addItem(tr("<ignore>")); // ColumnUnknown
Chris@1319 229 cpc->addItem(tr("Time")); // ColumnStartTime
Chris@1319 230 cpc->addItem(tr("End time")); // ColumnEndTime
Chris@1319 231 cpc->addItem(tr("Duration")); // ColumnDuration
Chris@1319 232 cpc->addItem(tr("Value")); // ColumnValue
Chris@1319 233 cpc->addItem(tr("Pitch")); // ColumnPitch
Chris@1319 234 cpc->addItem(tr("Label")); // ColumnLabel
Chris@1319 235 cpc->setCurrentIndex(int(m_format.getColumnPurpose(i)));
Chris@1318 236
Chris@581 237 for (int j = 0; j < example.size() && j < 6; ++j) {
Chris@866 238 if (i >= example[j].size()) {
Chris@866 239 continue;
Chris@866 240 }
Chris@581 241 QLabel *label = new QLabel;
Chris@581 242 label->setTextFormat(Qt::PlainText);
Chris@674 243 QString text = TextAbbrev::abbreviate(example[j][i], 35);
Chris@674 244 label->setText(text);
Chris@581 245 label->setFont(fp);
Chris@581 246 label->setPalette(palette);
Chris@581 247 label->setIndent(8);
Chris@581 248 exampleLayout->addWidget(label, j+1, i);
Chris@560 249 }
Chris@560 250 }
Chris@560 251
Chris@1413 252 if (m_exampleFrame) {
Chris@1413 253 delete m_exampleFrame;
Chris@1413 254 }
Chris@1413 255 m_exampleFrame = exampleFrame;
Chris@1413 256
Chris@1413 257 layout->addWidget(exampleFrame, m_exampleFrameRow, 0, 1, 4);
Chris@560 258 layout->setColumnStretch(3, 10);
Chris@1413 259 layout->setRowStretch(m_exampleFrameRow, 10);
Chris@1319 260
Chris@1319 261 m_initialTimingOption = TimingImplicit;
Chris@1319 262 if (m_format.getTimingType() == CSVFormat::ExplicitTiming) {
Chris@1319 263 switch (m_format.getTimeUnits()) {
Chris@1319 264 case CSVFormat::TimeSeconds:
Chris@1319 265 m_initialTimingOption = TimingExplicitSeconds; break;
Chris@1319 266 case CSVFormat::TimeMilliseconds:
Chris@1319 267 m_initialTimingOption = TimingExplicitMsec; break;
Chris@1319 268 case CSVFormat::TimeAudioFrames:
Chris@1319 269 m_initialTimingOption = TimingExplicitSamples; break;
Chris@1319 270 case CSVFormat::TimeWindows:
Chris@1319 271 m_initialTimingOption = TimingImplicit; break;
Chris@1318 272 }
Chris@959 273 }
Chris@1319 274 m_timingTypeCombo->setCurrentIndex(int(m_initialTimingOption));
Chris@378 275
Chris@807 276 for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) {
Chris@1266 277 if (sampleRates[i] == m_format.getSampleRate()) {
Chris@560 278 m_sampleRateCombo->setCurrentIndex(i);
Chris@560 279 }
Chris@378 280 }
Chris@1318 281
Chris@1319 282 for (int i = 0; i <= 16; ++i) {
Chris@1319 283 int value = 1 << i;
Chris@1319 284 if (value == int(m_format.getWindowSize())) {
Chris@1319 285 m_windowSizeCombo->setCurrentIndex(i);
Chris@1319 286 }
Chris@1319 287 }
Chris@378 288
Chris@1319 289 timingTypeChanged(m_timingTypeCombo->currentIndex());
Chris@378 290 }
Chris@378 291
Chris@378 292 CSVFormat
Chris@378 293 CSVFormatDialog::getFormat() const
Chris@378 294 {
Chris@560 295 return m_format;
Chris@378 296 }
Chris@378 297
Chris@378 298 void
Chris@561 299 CSVFormatDialog::updateModelLabel()
Chris@378 300 {
Chris@1318 301 if (!m_modelLabel) {
Chris@1318 302 return;
Chris@1318 303 }
Chris@1318 304
Chris@561 305 LayerFactory *f = LayerFactory::getInstance();
Chris@561 306
Chris@561 307 QString s;
Chris@561 308 switch (m_format.getModelType()) {
Chris@561 309 case CSVFormat::OneDimensionalModel:
Chris@561 310 s = f->getLayerPresentationName(LayerFactory::TimeInstants);
Chris@561 311 break;
Chris@561 312 case CSVFormat::TwoDimensionalModel:
Chris@561 313 s = f->getLayerPresentationName(LayerFactory::TimeValues);
Chris@561 314 break;
Chris@561 315 case CSVFormat::TwoDimensionalModelWithDuration:
Chris@561 316 s = f->getLayerPresentationName(LayerFactory::Regions);
Chris@561 317 break;
Chris@763 318 case CSVFormat::TwoDimensionalModelWithDurationAndPitch:
Chris@763 319 s = f->getLayerPresentationName(LayerFactory::Notes);
Chris@763 320 break;
Chris@561 321 case CSVFormat::ThreeDimensionalModel:
Chris@561 322 s = f->getLayerPresentationName(LayerFactory::Colour3DPlot);
Chris@561 323 break;
Chris@1312 324 case CSVFormat::WaveFileModel:
Chris@1312 325 s = f->getLayerPresentationName(LayerFactory::Waveform);
Chris@1312 326 break;
Chris@561 327 }
Chris@561 328
Chris@1318 329 m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.")
Chris@1318 330 .arg(s));
Chris@378 331 }
Chris@378 332
Chris@378 333 void
Chris@959 334 CSVFormatDialog::applyStartTimePurpose()
Chris@959 335 {
Chris@971 336 // First check if we already have any. NB there may be fewer than
Chris@971 337 // m_format.getColumnCount() elements in m_columnPurposeCombos
Chris@992 338 // (because of the fuzzy column behaviour). Note also that the
Chris@992 339 // fuzzy column (which is the one just showing how many more
Chris@992 340 // columns there are) has a different combo with only two items
Chris@992 341 // (ignore or Values)
Chris@971 342 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
Chris@992 343 if (i == m_fuzzyColumn) continue;
Chris@959 344 QComboBox *cb = m_columnPurposeCombos[i];
Chris@959 345 if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) {
Chris@959 346 return;
Chris@959 347 }
Chris@959 348 }
Chris@959 349 // and if not, select one
Chris@971 350 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
Chris@992 351 if (i == m_fuzzyColumn) continue;
Chris@959 352 QComboBox *cb = m_columnPurposeCombos[i];
Chris@959 353 if (cb->currentIndex() == int(CSVFormat::ColumnValue)) {
Chris@959 354 cb->setCurrentIndex(int(CSVFormat::ColumnStartTime));
Chris@959 355 return;
Chris@959 356 }
Chris@959 357 }
Chris@959 358 }
Chris@959 359
Chris@959 360 void
Chris@959 361 CSVFormatDialog::removeStartTimePurpose()
Chris@959 362 {
Chris@971 363 // NB there may be fewer than m_format.getColumnCount() elements
Chris@971 364 // in m_columnPurposeCombos (because of the fuzzy column
Chris@971 365 // behaviour)
Chris@971 366 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
Chris@992 367 if (i == m_fuzzyColumn) continue;
Chris@959 368 QComboBox *cb = m_columnPurposeCombos[i];
Chris@959 369 if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) {
Chris@959 370 cb->setCurrentIndex(int(CSVFormat::ColumnValue));
Chris@959 371 }
Chris@959 372 }
Chris@959 373 }
Chris@959 374
Chris@959 375 void
Chris@959 376 CSVFormatDialog::updateComboVisibility()
Chris@959 377 {
Chris@1319 378 bool wantRate = (m_format.getTimingType() == CSVFormat::ImplicitTiming ||
Chris@959 379 m_format.getTimeUnits() == CSVFormat::TimeAudioFrames);
Chris@959 380 bool wantWindow = (m_format.getTimingType() == CSVFormat::ImplicitTiming);
Chris@959 381
Chris@959 382 m_sampleRateCombo->setEnabled(wantRate);
Chris@959 383 m_sampleRateLabel->setEnabled(wantRate);
Chris@959 384
Chris@1319 385 m_windowSizeCombo->setEnabled(wantWindow);
Chris@1319 386 m_windowSizeLabel->setEnabled(wantWindow);
Chris@959 387 }
Chris@959 388
Chris@959 389 void
Chris@1413 390 CSVFormatDialog::separatorChanged(QString sep)
Chris@1413 391 {
Chris@1413 392 if (sep == "" || m_csvFilePath == "") {
Chris@1413 393 return;
Chris@1413 394 }
Chris@1413 395
Chris@1413 396 m_format.setSeparator(sep[0]);
Chris@1413 397 m_format.guessFormatFor(m_csvFilePath);
Chris@1413 398
Chris@1413 399 repopulate();
Chris@1413 400 }
Chris@1413 401
Chris@1413 402 void
Chris@378 403 CSVFormatDialog::timingTypeChanged(int type)
Chris@378 404 {
Chris@959 405 // Update any column purpose combos
Chris@959 406 if (TimingOption(type) == TimingImplicit) {
Chris@959 407 removeStartTimePurpose();
Chris@959 408 } else {
Chris@959 409 applyStartTimePurpose();
Chris@378 410 }
Chris@959 411 updateFormatFromDialog();
Chris@959 412 updateComboVisibility();
Chris@559 413 }
Chris@559 414
Chris@559 415 void
Chris@378 416 CSVFormatDialog::sampleRateChanged(QString rateString)
Chris@378 417 {
Chris@378 418 bool ok = false;
Chris@378 419 int sampleRate = rateString.toInt(&ok);
Chris@560 420 if (ok) m_format.setSampleRate(sampleRate);
Chris@378 421 }
Chris@378 422
Chris@378 423 void
Chris@378 424 CSVFormatDialog::windowSizeChanged(QString sizeString)
Chris@378 425 {
Chris@378 426 bool ok = false;
Chris@378 427 int size = sizeString.toInt(&ok);
Chris@560 428 if (ok) m_format.setWindowSize(size);
Chris@378 429 }
Chris@560 430
Chris@560 431 void
Chris@561 432 CSVFormatDialog::columnPurposeChanged(int p)
Chris@560 433 {
Chris@560 434 QObject *o = sender();
Chris@560 435 QComboBox *cb = qobject_cast<QComboBox *>(o);
Chris@560 436 if (!cb) return;
Chris@561 437
Chris@1319 438 // Ensure a consistent set of column purposes, in case of a
Chris@1319 439 // situation where some combinations are contradictory. Only
Chris@1319 440 // updates the UI, does not update the stored format record from
Chris@1319 441 // the UI - that's the job of updateFormatFromDialog
Chris@1318 442
Chris@561 443 CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p;
Chris@561 444
Chris@959 445 bool haveStartTime = false; // so as to update timing type combo appropriately
Chris@959 446
Chris@959 447 // Ensure the column purpose combos are consistent with one
Chris@959 448 // another, without reference to m_format (which we'll update
Chris@959 449 // separately)
Chris@959 450
Chris@560 451 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
Chris@561 452
Chris@992 453 // The fuzzy column combo only has the entries <ignore> or
Chris@992 454 // Values, so it can't affect the timing type and none of this
Chris@992 455 // logic affects it
Chris@992 456 if (i == m_fuzzyColumn) continue;
Chris@992 457
Chris@959 458 QComboBox *thisCombo = m_columnPurposeCombos[i];
Chris@561 459
Chris@959 460 CSVFormat::ColumnPurpose cp = (CSVFormat::ColumnPurpose)
Chris@959 461 (thisCombo->currentIndex());
Chris@959 462 bool thisChanged = (cb == thisCombo);
Chris@959 463
Chris@959 464 if (!thisChanged) {
Chris@561 465
Chris@561 466 // We can only have one ColumnStartTime column, and only
Chris@561 467 // one of either ColumnDuration or ColumnEndTime
Chris@561 468
Chris@561 469 if (purpose == CSVFormat::ColumnStartTime) {
Chris@561 470 if (cp == purpose) {
Chris@561 471 cp = CSVFormat::ColumnValue;
Chris@561 472 }
Chris@561 473 } else if (purpose == CSVFormat::ColumnDuration ||
Chris@561 474 purpose == CSVFormat::ColumnEndTime) {
Chris@561 475 if (cp == CSVFormat::ColumnDuration ||
Chris@561 476 cp == CSVFormat::ColumnEndTime) {
Chris@561 477 cp = CSVFormat::ColumnValue;
Chris@561 478 }
Chris@561 479 }
Chris@561 480
Chris@561 481 // And we can only have one label
Chris@561 482 if (purpose == CSVFormat::ColumnLabel) {
Chris@561 483 if (cp == purpose) {
Chris@561 484 cp = CSVFormat::ColumnUnknown;
Chris@561 485 }
Chris@561 486 }
Chris@959 487
Chris@959 488 if (cp == CSVFormat::ColumnStartTime) {
Chris@959 489 haveStartTime = true;
Chris@959 490 }
Chris@959 491
Chris@959 492 thisCombo->setCurrentIndex(int(cp));
Chris@959 493
Chris@959 494 } else {
Chris@959 495 if (purpose == CSVFormat::ColumnStartTime) {
Chris@959 496 haveStartTime = true;
Chris@959 497 }
Chris@561 498 }
Chris@959 499 }
Chris@561 500
Chris@1319 501 if (!haveStartTime) {
Chris@1319 502 m_timingTypeCombo->setCurrentIndex(int(TimingImplicit));
Chris@1319 503 } else if (m_timingTypeCombo->currentIndex() == int(TimingImplicit)) {
Chris@1319 504 if (m_initialTimingOption == TimingImplicit) {
Chris@1319 505 m_timingTypeCombo->setCurrentIndex(TimingExplicitSeconds);
Chris@1319 506 } else {
Chris@1319 507 m_timingTypeCombo->setCurrentIndex(m_initialTimingOption);
Chris@959 508 }
Chris@959 509 }
Chris@1319 510
Chris@1319 511 updateFormatFromDialog();
Chris@1319 512 updateComboVisibility();
Chris@959 513 }
Chris@1318 514
Chris@959 515 void
Chris@959 516 CSVFormatDialog::updateFormatFromDialog()
Chris@959 517 {
Chris@1319 518 switch (TimingOption(m_timingTypeCombo->currentIndex())) {
Chris@959 519
Chris@1319 520 case TimingExplicitSeconds:
Chris@1319 521 m_format.setTimingType(CSVFormat::ExplicitTiming);
Chris@1319 522 m_format.setTimeUnits(CSVFormat::TimeSeconds);
Chris@1319 523 break;
Chris@1319 524
Chris@1319 525 case TimingExplicitMsec:
Chris@1319 526 m_format.setTimingType(CSVFormat::ExplicitTiming);
Chris@1319 527 m_format.setTimeUnits(CSVFormat::TimeMilliseconds);
Chris@1319 528 break;
Chris@1319 529
Chris@1319 530 case TimingExplicitSamples:
Chris@1319 531 m_format.setTimingType(CSVFormat::ExplicitTiming);
Chris@1319 532 m_format.setTimeUnits(CSVFormat::TimeAudioFrames);
Chris@1319 533 break;
Chris@1319 534
Chris@1319 535 case TimingImplicit:
Chris@1318 536 m_format.setTimingType(CSVFormat::ImplicitTiming);
Chris@1319 537 m_format.setTimeUnits(CSVFormat::TimeWindows);
Chris@1319 538 break;
Chris@959 539 }
Chris@1318 540
Chris@959 541 bool haveStartTime = false;
Chris@959 542 bool haveDuration = false;
Chris@959 543 bool havePitch = false;
Chris@959 544 int valueCount = 0;
Chris@959 545
Chris@959 546 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
Chris@959 547
Chris@959 548 QComboBox *thisCombo = m_columnPurposeCombos[i];
Chris@959 549
Chris@1319 550 CSVFormat::ColumnPurpose purpose =
Chris@1319 551 (CSVFormat::ColumnPurpose) (thisCombo->currentIndex());
Chris@1319 552
Chris@959 553 if (i == m_fuzzyColumn) {
Chris@992 554 for (int j = i; j < m_format.getColumnCount(); ++j) {
Chris@959 555 if (purpose == CSVFormat::ColumnUnknown) {
Chris@959 556 m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown);
Chris@959 557 } else { // Value
Chris@959 558 m_format.setColumnPurpose(j, CSVFormat::ColumnValue);
Chris@959 559 ++valueCount;
Chris@959 560 }
Chris@959 561 }
Chris@992 562 } else {
Chris@992 563
Chris@992 564 if (purpose == CSVFormat::ColumnStartTime) {
Chris@992 565 haveStartTime = true;
Chris@992 566 }
Chris@992 567 if (purpose == CSVFormat::ColumnEndTime ||
Chris@992 568 purpose == CSVFormat::ColumnDuration) {
Chris@992 569 haveDuration = true;
Chris@992 570 }
Chris@992 571 if (purpose == CSVFormat::ColumnPitch) {
Chris@992 572 havePitch = true;
Chris@992 573 }
Chris@992 574 if (purpose == CSVFormat::ColumnValue) {
Chris@992 575 ++valueCount;
Chris@992 576 }
Chris@992 577
Chris@992 578 m_format.setColumnPurpose(i, purpose);
Chris@959 579 }
Chris@561 580 }
Chris@561 581
Chris@1319 582 if (haveStartTime && haveDuration) {
Chris@763 583 if (havePitch) {
Chris@763 584 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDurationAndPitch);
Chris@763 585 } else {
Chris@763 586 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDuration);
Chris@763 587 }
Chris@561 588 } else {
Chris@561 589 if (valueCount > 1) {
Chris@561 590 m_format.setModelType(CSVFormat::ThreeDimensionalModel);
Chris@561 591 } else if (valueCount > 0) {
Chris@561 592 m_format.setModelType(CSVFormat::TwoDimensionalModel);
Chris@561 593 } else {
Chris@561 594 m_format.setModelType(CSVFormat::OneDimensionalModel);
Chris@560 595 }
Chris@560 596 }
Chris@561 597
Chris@561 598 updateModelLabel();
Chris@560 599 }
Chris@560 600
Chris@560 601
Chris@959 602