annotate widgets/CSVFormatDialog.cpp @ 738:d26545a2a02d tonioni

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