annotate widgets/CSVFormatDialog.cpp @ 400:32acd578fcba

* Basic implementation of add and remove point in data editor * Improve resilience of frame - real-time - frame round-trip conversions
author Chris Cannam
date Mon, 16 Jun 2008 14:48:42 +0000
parents 22b72f0f6a4e
children ed65126e503d
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@378 18 #include <QFrame>
Chris@378 19 #include <QGridLayout>
Chris@378 20 #include <QPushButton>
Chris@378 21 #include <QHBoxLayout>
Chris@378 22 #include <QVBoxLayout>
Chris@378 23 #include <QTableWidget>
Chris@378 24 #include <QComboBox>
Chris@378 25 #include <QLabel>
Chris@378 26
Chris@378 27
Chris@378 28 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format,
Chris@378 29 size_t defaultSampleRate) :
Chris@378 30 QDialog(parent),
Chris@378 31 m_modelType(CSVFormat::OneDimensionalModel),
Chris@378 32 m_timingType(CSVFormat::ExplicitTiming),
Chris@378 33 m_timeUnits(CSVFormat::TimeAudioFrames),
Chris@378 34 m_separator(""),
Chris@378 35 m_behaviour(QString::KeepEmptyParts)
Chris@378 36 {
Chris@378 37 setModal(true);
Chris@378 38 setWindowTitle(tr("Select Data Format"));
Chris@378 39
Chris@378 40 m_modelType = format.getModelType();
Chris@378 41 m_timingType = format.getTimingType();
Chris@378 42 m_timeUnits = format.getTimeUnits();
Chris@378 43 m_separator = format.getSeparator();
Chris@378 44 m_sampleRate = format.getSampleRate();
Chris@378 45 m_windowSize = format.getWindowSize();
Chris@378 46 m_behaviour = format.getSplitBehaviour();
Chris@378 47 m_example = format.getExample();
Chris@378 48 m_maxExampleCols = format.getMaxExampleCols();
Chris@378 49
Chris@378 50 QGridLayout *layout = new QGridLayout;
Chris@378 51
Chris@378 52 layout->addWidget(new QLabel(tr("<b>Select Data Format</b><p>Please select the correct data format for this file.")),
Chris@378 53 0, 0, 1, 4);
Chris@378 54
Chris@378 55 layout->addWidget(new QLabel(tr("Each row specifies:")), 1, 0);
Chris@378 56
Chris@378 57 m_modelTypeCombo = new QComboBox;
Chris@378 58 m_modelTypeCombo->addItem(tr("A point in time"));
Chris@378 59 m_modelTypeCombo->addItem(tr("A value at a time"));
Chris@378 60 m_modelTypeCombo->addItem(tr("A set of values"));
Chris@378 61 layout->addWidget(m_modelTypeCombo, 1, 1, 1, 2);
Chris@378 62 connect(m_modelTypeCombo, SIGNAL(activated(int)),
Chris@378 63 this, SLOT(modelTypeChanged(int)));
Chris@378 64 m_modelTypeCombo->setCurrentIndex(int(m_modelType));
Chris@378 65
Chris@378 66 layout->addWidget(new QLabel(tr("The first column contains:")), 2, 0);
Chris@378 67
Chris@378 68 m_timingTypeCombo = new QComboBox;
Chris@378 69 m_timingTypeCombo->addItem(tr("Time, in seconds"));
Chris@378 70 m_timingTypeCombo->addItem(tr("Time, in audio sample frames"));
Chris@378 71 m_timingTypeCombo->addItem(tr("Data (rows are consecutive in time)"));
Chris@378 72 layout->addWidget(m_timingTypeCombo, 2, 1, 1, 2);
Chris@378 73 connect(m_timingTypeCombo, SIGNAL(activated(int)),
Chris@378 74 this, SLOT(timingTypeChanged(int)));
Chris@378 75 m_timingTypeCombo->setCurrentIndex(m_timingType == CSVFormat::ExplicitTiming ?
Chris@378 76 m_timeUnits == CSVFormat::TimeSeconds ? 0 : 1 : 2);
Chris@378 77
Chris@378 78 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
Chris@378 79 layout->addWidget(m_sampleRateLabel, 3, 0);
Chris@378 80
Chris@378 81 size_t sampleRates[] = {
Chris@378 82 8000, 11025, 12000, 22050, 24000, 32000,
Chris@378 83 44100, 48000, 88200, 96000, 176400, 192000
Chris@378 84 };
Chris@378 85
Chris@378 86 m_sampleRateCombo = new QComboBox;
Chris@378 87 m_sampleRate = defaultSampleRate;
Chris@378 88 for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) {
Chris@378 89 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i]));
Chris@378 90 if (sampleRates[i] == m_sampleRate) m_sampleRateCombo->setCurrentIndex(i);
Chris@378 91 }
Chris@378 92 m_sampleRateCombo->setEditable(true);
Chris@378 93
Chris@378 94 layout->addWidget(m_sampleRateCombo, 3, 1);
Chris@378 95 connect(m_sampleRateCombo, SIGNAL(activated(QString)),
Chris@378 96 this, SLOT(sampleRateChanged(QString)));
Chris@378 97 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
Chris@378 98 this, SLOT(sampleRateChanged(QString)));
Chris@378 99
Chris@378 100 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
Chris@378 101 layout->addWidget(m_windowSizeLabel, 4, 0);
Chris@378 102
Chris@378 103 m_windowSizeCombo = new QComboBox;
Chris@378 104 m_windowSize = 1024;
Chris@378 105 for (int i = 0; i <= 16; ++i) {
Chris@378 106 int value = 1 << i;
Chris@378 107 m_windowSizeCombo->addItem(QString("%1").arg(value));
Chris@378 108 if (value == int(m_windowSize)) m_windowSizeCombo->setCurrentIndex(i);
Chris@378 109 }
Chris@378 110 m_windowSizeCombo->setEditable(true);
Chris@378 111
Chris@378 112 layout->addWidget(m_windowSizeCombo, 4, 1);
Chris@378 113 connect(m_windowSizeCombo, SIGNAL(activated(QString)),
Chris@378 114 this, SLOT(windowSizeChanged(QString)));
Chris@378 115 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
Chris@378 116 this, SLOT(windowSizeChanged(QString)));
Chris@378 117
Chris@378 118 layout->addWidget(new QLabel(tr("\nExample data from file:")), 5, 0, 1, 4);
Chris@378 119
Chris@378 120 m_exampleWidget = new QTableWidget
Chris@378 121 (std::min(10, m_example.size()), m_maxExampleCols);
Chris@378 122
Chris@378 123 layout->addWidget(m_exampleWidget, 6, 0, 1, 4);
Chris@378 124 layout->setColumnStretch(3, 10);
Chris@378 125 layout->setRowStretch(4, 10);
Chris@378 126
Chris@378 127 QPushButton *ok = new QPushButton(tr("OK"));
Chris@378 128 connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
Chris@378 129 ok->setDefault(true);
Chris@378 130
Chris@378 131 QPushButton *cancel = new QPushButton(tr("Cancel"));
Chris@378 132 connect(cancel, SIGNAL(clicked()), this, SLOT(reject()));
Chris@378 133
Chris@378 134 QHBoxLayout *buttonLayout = new QHBoxLayout;
Chris@378 135 buttonLayout->addStretch(1);
Chris@378 136 buttonLayout->addWidget(ok);
Chris@378 137 buttonLayout->addWidget(cancel);
Chris@378 138
Chris@378 139 QVBoxLayout *mainLayout = new QVBoxLayout;
Chris@378 140 mainLayout->addLayout(layout);
Chris@378 141 mainLayout->addLayout(buttonLayout);
Chris@378 142
Chris@378 143 setLayout(mainLayout);
Chris@378 144
Chris@378 145 timingTypeChanged(m_timingTypeCombo->currentIndex());
Chris@378 146 }
Chris@378 147
Chris@378 148 CSVFormatDialog::~CSVFormatDialog()
Chris@378 149 {
Chris@378 150 }
Chris@378 151
Chris@378 152 CSVFormat
Chris@378 153 CSVFormatDialog::getFormat() const
Chris@378 154 {
Chris@378 155 CSVFormat format;
Chris@378 156 format.setModelType(m_modelType);
Chris@378 157 format.setTimingType(m_timingType);
Chris@378 158 format.setTimeUnits(m_timeUnits);
Chris@378 159 format.setSeparator(m_separator);
Chris@378 160 format.setSampleRate(m_sampleRate);
Chris@378 161 format.setWindowSize(m_windowSize);
Chris@378 162 format.setSplitBehaviour(m_behaviour);
Chris@378 163 return format;
Chris@378 164 }
Chris@378 165
Chris@378 166 void
Chris@378 167 CSVFormatDialog::populateExample()
Chris@378 168 {
Chris@378 169 m_exampleWidget->setColumnCount
Chris@378 170 (m_timingType == CSVFormat::ExplicitTiming ?
Chris@378 171 m_maxExampleCols - 1 : m_maxExampleCols);
Chris@378 172
Chris@378 173 m_exampleWidget->setHorizontalHeaderLabels(QStringList());
Chris@378 174
Chris@378 175 for (int i = 0; i < m_example.size(); ++i) {
Chris@378 176 for (int j = 0; j < m_example[i].size(); ++j) {
Chris@378 177
Chris@378 178 QTableWidgetItem *item = new QTableWidgetItem(m_example[i][j]);
Chris@378 179
Chris@378 180 if (j == 0) {
Chris@378 181 if (m_timingType == CSVFormat::ExplicitTiming) {
Chris@378 182 m_exampleWidget->setVerticalHeaderItem(i, item);
Chris@378 183 continue;
Chris@378 184 } else {
Chris@378 185 QTableWidgetItem *header =
Chris@378 186 new QTableWidgetItem(QString("%1").arg(i));
Chris@378 187 header->setFlags(Qt::ItemIsEnabled);
Chris@378 188 m_exampleWidget->setVerticalHeaderItem(i, header);
Chris@378 189 }
Chris@378 190 }
Chris@378 191 int index = j;
Chris@378 192 if (m_timingType == CSVFormat::ExplicitTiming) --index;
Chris@378 193 item->setFlags(Qt::ItemIsEnabled);
Chris@378 194 m_exampleWidget->setItem(i, index, item);
Chris@378 195 }
Chris@378 196 }
Chris@378 197 }
Chris@378 198
Chris@378 199 void
Chris@378 200 CSVFormatDialog::modelTypeChanged(int type)
Chris@378 201 {
Chris@378 202 m_modelType = (CSVFormat::ModelType)type;
Chris@378 203
Chris@378 204 if (m_modelType == CSVFormat::ThreeDimensionalModel) {
Chris@378 205 // We can't load 3d models with explicit timing, because the 3d
Chris@378 206 // model is dense so we need a fixed sample increment
Chris@378 207 m_timingTypeCombo->setCurrentIndex(2);
Chris@378 208 timingTypeChanged(2);
Chris@378 209 }
Chris@378 210 }
Chris@378 211
Chris@378 212 void
Chris@378 213 CSVFormatDialog::timingTypeChanged(int type)
Chris@378 214 {
Chris@378 215 switch (type) {
Chris@378 216
Chris@378 217 case 0:
Chris@378 218 m_timingType = CSVFormat::ExplicitTiming;
Chris@378 219 m_timeUnits = CSVFormat::TimeSeconds;
Chris@378 220 m_sampleRateCombo->setEnabled(false);
Chris@378 221 m_sampleRateLabel->setEnabled(false);
Chris@378 222 m_windowSizeCombo->setEnabled(false);
Chris@378 223 m_windowSizeLabel->setEnabled(false);
Chris@378 224 if (m_modelType == CSVFormat::ThreeDimensionalModel) {
Chris@378 225 m_modelTypeCombo->setCurrentIndex(1);
Chris@378 226 modelTypeChanged(1);
Chris@378 227 }
Chris@378 228 break;
Chris@378 229
Chris@378 230 case 1:
Chris@378 231 m_timingType = CSVFormat::ExplicitTiming;
Chris@378 232 m_timeUnits = CSVFormat::TimeAudioFrames;
Chris@378 233 m_sampleRateCombo->setEnabled(true);
Chris@378 234 m_sampleRateLabel->setEnabled(true);
Chris@378 235 m_windowSizeCombo->setEnabled(false);
Chris@378 236 m_windowSizeLabel->setEnabled(false);
Chris@378 237 if (m_modelType == CSVFormat::ThreeDimensionalModel) {
Chris@378 238 m_modelTypeCombo->setCurrentIndex(1);
Chris@378 239 modelTypeChanged(1);
Chris@378 240 }
Chris@378 241 break;
Chris@378 242
Chris@378 243 case 2:
Chris@378 244 m_timingType = CSVFormat::ImplicitTiming;
Chris@378 245 m_timeUnits = CSVFormat::TimeWindows;
Chris@378 246 m_sampleRateCombo->setEnabled(true);
Chris@378 247 m_sampleRateLabel->setEnabled(true);
Chris@378 248 m_windowSizeCombo->setEnabled(true);
Chris@378 249 m_windowSizeLabel->setEnabled(true);
Chris@378 250 break;
Chris@378 251 }
Chris@378 252
Chris@378 253 populateExample();
Chris@378 254 }
Chris@378 255
Chris@378 256 void
Chris@378 257 CSVFormatDialog::sampleRateChanged(QString rateString)
Chris@378 258 {
Chris@378 259 bool ok = false;
Chris@378 260 int sampleRate = rateString.toInt(&ok);
Chris@378 261 if (ok) m_sampleRate = sampleRate;
Chris@378 262 }
Chris@378 263
Chris@378 264 void
Chris@378 265 CSVFormatDialog::windowSizeChanged(QString sizeString)
Chris@378 266 {
Chris@378 267 bool ok = false;
Chris@378 268 int size = sizeString.toInt(&ok);
Chris@378 269 if (ok) m_windowSize = size;
Chris@378 270 }