annotate widgets/CSVFormatDialog.cpp @ 640:c6d705bf1672

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:36:43 +0100
parents c9d6cf9c51c8
children d8bd193ad17d
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@378 7 This file copyright 2006 Chris Cannam.
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@378 20 #include <QFrame>
Chris@378 21 #include <QGridLayout>
Chris@378 22 #include <QPushButton>
Chris@378 23 #include <QHBoxLayout>
Chris@378 24 #include <QVBoxLayout>
Chris@378 25 #include <QTableWidget>
Chris@378 26 #include <QComboBox>
Chris@378 27 #include <QLabel>
Chris@512 28 #include <QDialogButtonBox>
Chris@378 29
Chris@560 30 #include <iostream>
Chris@378 31
Chris@581 32 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format,
Chris@581 33 int maxDisplayCols) :
Chris@378 34 QDialog(parent),
Chris@581 35 m_format(format),
Chris@581 36 m_maxDisplayCols(maxDisplayCols),
Chris@581 37 m_fuzzyColumn(-1)
Chris@378 38 {
Chris@378 39 setModal(true);
Chris@378 40 setWindowTitle(tr("Select Data Format"));
Chris@378 41
Chris@378 42 QGridLayout *layout = new QGridLayout;
Chris@378 43
Chris@560 44 int row = 0;
Chris@378 45
Chris@560 46 layout->addWidget(new QLabel(tr("Please select the correct data format for this file.")),
Chris@560 47 row++, 0, 1, 4);
Chris@560 48
Chris@560 49 QFrame *exampleFrame = new QFrame;
Chris@560 50 exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
Chris@560 51 exampleFrame->setLineWidth(2);
Chris@560 52 QGridLayout *exampleLayout = new QGridLayout;
Chris@561 53 exampleLayout->setSpacing(4);
Chris@560 54 exampleFrame->setLayout(exampleLayout);
Chris@560 55
Chris@560 56 QPalette palette = exampleFrame->palette();
Chris@560 57 palette.setColor(QPalette::Window, palette.color(QPalette::Base));
Chris@560 58 exampleFrame->setPalette(palette);
Chris@560 59
Chris@560 60 QFont fp;
Chris@561 61 fp.setPointSize(fp.pointSize() * 0.9);
Chris@561 62 // fp.setFixedPitch(true);
Chris@561 63 // fp.setStyleHint(QFont::TypeWriter);
Chris@561 64 // fp.setFamily("Monospaced");
Chris@560 65
Chris@560 66 int columns = format.getColumnCount();
Chris@560 67 QList<QStringList> example = m_format.getExample();
Chris@560 68
Chris@560 69 for (int i = 0; i < columns; ++i) {
Chris@581 70
Chris@560 71 QComboBox *cpc = new QComboBox;
Chris@560 72 m_columnPurposeCombos.push_back(cpc);
Chris@560 73 exampleLayout->addWidget(cpc, 0, i);
Chris@581 74 connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int)));
Chris@581 75
Chris@581 76 if (i == m_maxDisplayCols && columns > i + 2) {
Chris@581 77 m_fuzzyColumn = i;
Chris@581 78 cpc->addItem(tr("<ignore>"));
Chris@581 79 cpc->addItem(tr("Values"));
Chris@581 80 cpc->setCurrentIndex
Chris@581 81 (m_format.getColumnPurpose(i-1) == CSVFormat::ColumnUnknown ? 0 : 1);
Chris@581 82 exampleLayout->addWidget(new QLabel(tr("(%1 more)").arg(columns - i)),
Chris@581 83 1, i);
Chris@581 84 break;
Chris@581 85 }
Chris@560 86
Chris@560 87 // NB must be in the same order as the CSVFormat::ColumnPurpose enum
Chris@560 88 cpc->addItem(tr("<ignore>")); // ColumnUnknown
Chris@560 89 cpc->addItem(tr("Time")); // ColumnStartTime
Chris@560 90 cpc->addItem(tr("End time")); // ColumnEndTime
Chris@560 91 cpc->addItem(tr("Duration")); // ColumnDuration
Chris@560 92 cpc->addItem(tr("Value")); // ColumnValue
Chris@560 93 cpc->addItem(tr("Label")); // ColumnLabel
Chris@560 94 cpc->setCurrentIndex(int(m_format.getColumnPurpose(i)));
Chris@560 95
Chris@581 96 for (int j = 0; j < example.size() && j < 6; ++j) {
Chris@581 97 QLabel *label = new QLabel;
Chris@581 98 label->setTextFormat(Qt::PlainText);
Chris@581 99 label->setText(example[j][i]);
Chris@581 100 label->setFont(fp);
Chris@581 101 label->setPalette(palette);
Chris@581 102 label->setIndent(8);
Chris@581 103 exampleLayout->addWidget(label, j+1, i);
Chris@560 104 }
Chris@560 105 }
Chris@560 106
Chris@560 107 layout->addWidget(exampleFrame, row, 0, 1, 4);
Chris@560 108 layout->setColumnStretch(3, 10);
Chris@560 109 layout->setRowStretch(row++, 10);
Chris@560 110
Chris@560 111 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0);
Chris@378 112
Chris@378 113 m_timingTypeCombo = new QComboBox;
Chris@560 114 m_timingTypeCombo->addItem(tr("Explicitly, in seconds"));
Chris@560 115 m_timingTypeCombo->addItem(tr("Explicitly, in audio sample frames"));
Chris@560 116 m_timingTypeCombo->addItem(tr("Implicitly: rows are equally spaced in time"));
Chris@560 117 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2);
Chris@378 118 connect(m_timingTypeCombo, SIGNAL(activated(int)),
Chris@378 119 this, SLOT(timingTypeChanged(int)));
Chris@560 120 m_timingTypeCombo->setCurrentIndex
Chris@560 121 (m_format.getTimingType() == CSVFormat::ExplicitTiming ?
Chris@560 122 m_format.getTimeUnits() == CSVFormat::TimeSeconds ? 0 : 1 : 2);
Chris@559 123
Chris@378 124 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
Chris@560 125 layout->addWidget(m_sampleRateLabel, row, 0);
Chris@378 126
Chris@378 127 size_t sampleRates[] = {
Chris@378 128 8000, 11025, 12000, 22050, 24000, 32000,
Chris@378 129 44100, 48000, 88200, 96000, 176400, 192000
Chris@378 130 };
Chris@378 131
Chris@378 132 m_sampleRateCombo = new QComboBox;
Chris@378 133 for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) {
Chris@378 134 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i]));
Chris@560 135 if (sampleRates[i] == m_format.getSampleRate()) {
Chris@560 136 m_sampleRateCombo->setCurrentIndex(i);
Chris@560 137 }
Chris@378 138 }
Chris@378 139 m_sampleRateCombo->setEditable(true);
Chris@378 140
Chris@560 141 layout->addWidget(m_sampleRateCombo, row++, 1);
Chris@378 142 connect(m_sampleRateCombo, SIGNAL(activated(QString)),
Chris@378 143 this, SLOT(sampleRateChanged(QString)));
Chris@378 144 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
Chris@378 145 this, SLOT(sampleRateChanged(QString)));
Chris@378 146
Chris@378 147 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
Chris@560 148 layout->addWidget(m_windowSizeLabel, row, 0);
Chris@378 149
Chris@378 150 m_windowSizeCombo = new QComboBox;
Chris@378 151 for (int i = 0; i <= 16; ++i) {
Chris@378 152 int value = 1 << i;
Chris@378 153 m_windowSizeCombo->addItem(QString("%1").arg(value));
Chris@560 154 if (value == int(m_format.getWindowSize())) {
Chris@560 155 m_windowSizeCombo->setCurrentIndex(i);
Chris@560 156 }
Chris@378 157 }
Chris@378 158 m_windowSizeCombo->setEditable(true);
Chris@378 159
Chris@560 160 layout->addWidget(m_windowSizeCombo, row++, 1);
Chris@378 161 connect(m_windowSizeCombo, SIGNAL(activated(QString)),
Chris@378 162 this, SLOT(windowSizeChanged(QString)));
Chris@378 163 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
Chris@378 164 this, SLOT(windowSizeChanged(QString)));
Chris@378 165
Chris@561 166 m_modelLabel = new QLabel;
Chris@561 167 QFont f(m_modelLabel->font());
Chris@561 168 f.setItalic(true);
Chris@561 169 m_modelLabel->setFont(f);
Chris@561 170 layout->addWidget(m_modelLabel, row++, 0, 1, 4);
Chris@561 171
Chris@512 172 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
Chris@512 173 QDialogButtonBox::Cancel);
Chris@560 174 layout->addWidget(bb, row++, 0, 1, 4);
Chris@512 175 connect(bb, SIGNAL(accepted()), this, SLOT(accept()));
Chris@512 176 connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
Chris@378 177
Chris@512 178 setLayout(layout);
Chris@378 179
Chris@378 180 timingTypeChanged(m_timingTypeCombo->currentIndex());
Chris@561 181 updateModelLabel();
Chris@378 182 }
Chris@378 183
Chris@378 184 CSVFormatDialog::~CSVFormatDialog()
Chris@378 185 {
Chris@378 186 }
Chris@378 187
Chris@378 188 CSVFormat
Chris@378 189 CSVFormatDialog::getFormat() const
Chris@378 190 {
Chris@560 191 return m_format;
Chris@378 192 }
Chris@378 193
Chris@378 194 void
Chris@561 195 CSVFormatDialog::updateModelLabel()
Chris@378 196 {
Chris@561 197 LayerFactory *f = LayerFactory::getInstance();
Chris@561 198
Chris@561 199 QString s;
Chris@561 200 switch (m_format.getModelType()) {
Chris@561 201 case CSVFormat::OneDimensionalModel:
Chris@561 202 s = f->getLayerPresentationName(LayerFactory::TimeInstants);
Chris@561 203 break;
Chris@561 204 case CSVFormat::TwoDimensionalModel:
Chris@561 205 s = f->getLayerPresentationName(LayerFactory::TimeValues);
Chris@561 206 break;
Chris@561 207 case CSVFormat::TwoDimensionalModelWithDuration:
Chris@561 208 s = f->getLayerPresentationName(LayerFactory::Regions);
Chris@561 209 break;
Chris@561 210 case CSVFormat::ThreeDimensionalModel:
Chris@561 211 s = f->getLayerPresentationName(LayerFactory::Colour3DPlot);
Chris@561 212 break;
Chris@561 213 }
Chris@561 214
Chris@578 215 m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.").arg(s));
Chris@378 216 }
Chris@378 217
Chris@378 218 void
Chris@378 219 CSVFormatDialog::timingTypeChanged(int type)
Chris@378 220 {
Chris@378 221 switch (type) {
Chris@378 222
Chris@378 223 case 0:
Chris@560 224 m_format.setTimingType(CSVFormat::ExplicitTiming);
Chris@560 225 m_format.setTimeUnits(CSVFormat::TimeSeconds);
Chris@378 226 m_sampleRateCombo->setEnabled(false);
Chris@378 227 m_sampleRateLabel->setEnabled(false);
Chris@378 228 m_windowSizeCombo->setEnabled(false);
Chris@378 229 m_windowSizeLabel->setEnabled(false);
Chris@378 230 break;
Chris@378 231
Chris@378 232 case 1:
Chris@560 233 m_format.setTimingType(CSVFormat::ExplicitTiming);
Chris@560 234 m_format.setTimeUnits(CSVFormat::TimeAudioFrames);
Chris@378 235 m_sampleRateCombo->setEnabled(true);
Chris@378 236 m_sampleRateLabel->setEnabled(true);
Chris@378 237 m_windowSizeCombo->setEnabled(false);
Chris@378 238 m_windowSizeLabel->setEnabled(false);
Chris@378 239 break;
Chris@378 240
Chris@378 241 case 2:
Chris@560 242 m_format.setTimingType(CSVFormat::ImplicitTiming);
Chris@560 243 m_format.setTimeUnits(CSVFormat::TimeWindows);
Chris@378 244 m_sampleRateCombo->setEnabled(true);
Chris@378 245 m_sampleRateLabel->setEnabled(true);
Chris@378 246 m_windowSizeCombo->setEnabled(true);
Chris@378 247 m_windowSizeLabel->setEnabled(true);
Chris@378 248 break;
Chris@378 249 }
Chris@559 250 }
Chris@559 251
Chris@559 252 void
Chris@378 253 CSVFormatDialog::sampleRateChanged(QString rateString)
Chris@378 254 {
Chris@378 255 bool ok = false;
Chris@378 256 int sampleRate = rateString.toInt(&ok);
Chris@560 257 if (ok) m_format.setSampleRate(sampleRate);
Chris@378 258 }
Chris@378 259
Chris@378 260 void
Chris@378 261 CSVFormatDialog::windowSizeChanged(QString sizeString)
Chris@378 262 {
Chris@378 263 bool ok = false;
Chris@378 264 int size = sizeString.toInt(&ok);
Chris@560 265 if (ok) m_format.setWindowSize(size);
Chris@378 266 }
Chris@560 267
Chris@560 268 void
Chris@561 269 CSVFormatDialog::columnPurposeChanged(int p)
Chris@560 270 {
Chris@560 271 QObject *o = sender();
Chris@561 272
Chris@560 273 QComboBox *cb = qobject_cast<QComboBox *>(o);
Chris@560 274 if (!cb) return;
Chris@561 275
Chris@561 276 CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p;
Chris@561 277
Chris@561 278 bool haveStartTime = false;
Chris@561 279 bool haveDuration = false;
Chris@561 280 int valueCount = 0;
Chris@561 281
Chris@560 282 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
Chris@561 283
Chris@561 284 CSVFormat::ColumnPurpose cp = m_format.getColumnPurpose(i);
Chris@561 285
Chris@561 286 bool thisChanged = (cb == m_columnPurposeCombos[i]);
Chris@561 287
Chris@561 288 if (thisChanged) {
Chris@561 289
Chris@581 290 std::cerr << "i == " << i << ", fuzzy == " << m_fuzzyColumn
Chris@581 291 << ", p == " << p << std::endl;
Chris@581 292
Chris@581 293 if (i == m_fuzzyColumn) {
Chris@581 294 for (int j = i; j < m_format.getColumnCount(); ++j) {
Chris@581 295 if (p == 0) { // Ignore
Chris@581 296 m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown);
Chris@581 297 } else { // Value
Chris@581 298 m_format.setColumnPurpose(j, CSVFormat::ColumnValue);
Chris@581 299 ++valueCount;
Chris@581 300 }
Chris@581 301 }
Chris@581 302 continue;
Chris@581 303 }
Chris@581 304
Chris@561 305 cp = purpose;
Chris@561 306
Chris@561 307 } else {
Chris@561 308
Chris@581 309 if (i == m_fuzzyColumn) continue;
Chris@581 310
Chris@561 311 // We can only have one ColumnStartTime column, and only
Chris@561 312 // one of either ColumnDuration or ColumnEndTime
Chris@561 313
Chris@561 314 if (purpose == CSVFormat::ColumnStartTime) {
Chris@561 315 if (cp == purpose) {
Chris@561 316 cp = CSVFormat::ColumnValue;
Chris@561 317 }
Chris@561 318 } else if (purpose == CSVFormat::ColumnDuration ||
Chris@561 319 purpose == CSVFormat::ColumnEndTime) {
Chris@561 320 if (cp == CSVFormat::ColumnDuration ||
Chris@561 321 cp == CSVFormat::ColumnEndTime) {
Chris@561 322 cp = CSVFormat::ColumnValue;
Chris@561 323 }
Chris@561 324 }
Chris@561 325
Chris@561 326 // And we can only have one label
Chris@561 327 if (purpose == CSVFormat::ColumnLabel) {
Chris@561 328 if (cp == purpose) {
Chris@561 329 cp = CSVFormat::ColumnUnknown;
Chris@561 330 }
Chris@561 331 }
Chris@561 332 }
Chris@561 333
Chris@561 334 if (cp == CSVFormat::ColumnStartTime) {
Chris@561 335 haveStartTime = true;
Chris@561 336 }
Chris@561 337 if (cp == CSVFormat::ColumnEndTime ||
Chris@561 338 cp == CSVFormat::ColumnDuration) {
Chris@561 339 haveDuration = true;
Chris@561 340 }
Chris@561 341 if (cp == CSVFormat::ColumnValue) {
Chris@561 342 ++valueCount;
Chris@561 343 }
Chris@561 344
Chris@561 345 m_columnPurposeCombos[i]->setCurrentIndex(int(cp));
Chris@561 346 m_format.setColumnPurpose(i, cp);
Chris@561 347 }
Chris@561 348
Chris@561 349 if (!haveStartTime) {
Chris@561 350 m_timingTypeCombo->setCurrentIndex(2);
Chris@561 351 timingTypeChanged(2);
Chris@561 352 }
Chris@561 353
Chris@561 354 if (haveStartTime && haveDuration) {
Chris@561 355 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDuration);
Chris@561 356 } else {
Chris@561 357 if (valueCount > 1) {
Chris@561 358 m_format.setModelType(CSVFormat::ThreeDimensionalModel);
Chris@561 359 } else if (valueCount > 0) {
Chris@561 360 m_format.setModelType(CSVFormat::TwoDimensionalModel);
Chris@561 361 } else {
Chris@561 362 m_format.setModelType(CSVFormat::OneDimensionalModel);
Chris@560 363 }
Chris@560 364 }
Chris@561 365
Chris@561 366 updateModelLabel();
Chris@560 367 }
Chris@560 368
Chris@560 369