comparison widgets/CSVFormatDialog.cpp @ 560:e15afed2bfeb

* Start revamping the CSV import dialog so as to show a "purpose" for each column. These are estimated from the file now, but changing them does not actually do anything yet.
author Chris Cannam
date Fri, 16 Jul 2010 16:51:39 +0000
parents 5bcfc5606528
children aced8ec09bc8
comparison
equal deleted inserted replaced
559:5bcfc5606528 560:e15afed2bfeb
23 #include <QTableWidget> 23 #include <QTableWidget>
24 #include <QComboBox> 24 #include <QComboBox>
25 #include <QLabel> 25 #include <QLabel>
26 #include <QDialogButtonBox> 26 #include <QDialogButtonBox>
27 27
28 28 #include <iostream>
29 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format, 29
30 size_t defaultSampleRate) : 30 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format) :
31 QDialog(parent), 31 QDialog(parent),
32 m_modelType(CSVFormat::OneDimensionalModel), 32 m_format(format)
33 m_timingType(CSVFormat::ExplicitTiming),
34 m_durationType(CSVFormat::Durations),
35 m_timeUnits(CSVFormat::TimeAudioFrames),
36 m_separator(""),
37 m_behaviour(QString::KeepEmptyParts)
38 { 33 {
39 setModal(true); 34 setModal(true);
40 setWindowTitle(tr("Select Data Format")); 35 setWindowTitle(tr("Select Data Format"));
41 36
42 m_modelType = format.getModelType();
43 m_timingType = format.getTimingType();
44 m_durationType = format.getDurationType();
45 m_timeUnits = format.getTimeUnits();
46 m_separator = format.getSeparator();
47 m_sampleRate = format.getSampleRate();
48 m_windowSize = format.getWindowSize();
49 m_behaviour = format.getSplitBehaviour();
50 m_example = format.getExample();
51 m_maxExampleCols = format.getMaxExampleCols();
52
53 QGridLayout *layout = new QGridLayout; 37 QGridLayout *layout = new QGridLayout;
54 38
55 layout->addWidget(new QLabel(tr("<b>Select Data Format</b><p>Please select the correct data format for this file.")), 39 int row = 0;
56 0, 0, 1, 4); 40
57 41 layout->addWidget(new QLabel(tr("Please select the correct data format for this file.")),
58 layout->addWidget(new QLabel(tr("Each row specifies:")), 1, 0); 42 row++, 0, 1, 4);
43
44 QFrame *exampleFrame = new QFrame;
45 exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
46 exampleFrame->setLineWidth(2);
47 QGridLayout *exampleLayout = new QGridLayout;
48 exampleFrame->setLayout(exampleLayout);
49
50 QPalette palette = exampleFrame->palette();
51 palette.setColor(QPalette::Window, palette.color(QPalette::Base));
52 exampleFrame->setPalette(palette);
53
54 QFont fp;
55 fp.setFixedPitch(true);
56 fp.setStyleHint(QFont::TypeWriter);
57 fp.setFamily("Monospaced");
58
59 int columns = format.getColumnCount();
60 QList<QStringList> example = m_format.getExample();
61
62 for (int i = 0; i < columns; ++i) {
63
64 QComboBox *cpc = new QComboBox;
65 m_columnPurposeCombos.push_back(cpc);
66 exampleLayout->addWidget(cpc, 0, i);
67
68 // NB must be in the same order as the CSVFormat::ColumnPurpose enum
69 cpc->addItem(tr("<ignore>")); // ColumnUnknown
70 cpc->addItem(tr("Time")); // ColumnStartTime
71 cpc->addItem(tr("End time")); // ColumnEndTime
72 cpc->addItem(tr("Duration")); // ColumnDuration
73 cpc->addItem(tr("Value")); // ColumnValue
74 cpc->addItem(tr("Label")); // ColumnLabel
75 cpc->setCurrentIndex(int(m_format.getColumnPurpose(i)));
76 connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int)));
77
78 if (i < m_format.getMaxExampleCols()) {
79 for (int j = 0; j < example.size() && j < 6; ++j) {
80 QLabel *label = new QLabel;
81 label->setTextFormat(Qt::PlainText);
82 label->setText(example[j][i]);
83 label->setFont(fp);
84 label->setPalette(palette);
85 exampleLayout->addWidget(label, j+1, i);
86 }
87 }
88 }
89
90 layout->addWidget(exampleFrame, row, 0, 1, 4);
91 layout->setColumnStretch(3, 10);
92 layout->setRowStretch(row++, 10);
93
94 layout->addWidget(new QLabel(tr("Each row describes:")), row, 0);
59 95
60 m_modelTypeCombo = new QComboBox; 96 m_modelTypeCombo = new QComboBox;
61 m_modelTypeCombo->addItem(tr("A point in time")); 97 m_modelTypeCombo->addItem(tr("A point in time"));
62 m_modelTypeCombo->addItem(tr("A value at a time")); 98 m_modelTypeCombo->addItem(tr("A value at a time"));
63 m_modelTypeCombo->addItem(tr("A value across a time range")); 99 m_modelTypeCombo->addItem(tr("A value across a time range"));
64 m_modelTypeCombo->addItem(tr("A set of values")); 100 m_modelTypeCombo->addItem(tr("A set of values"));
65 layout->addWidget(m_modelTypeCombo, 1, 1, 1, 2); 101 layout->addWidget(m_modelTypeCombo, row++, 1, 1, 2);
66 connect(m_modelTypeCombo, SIGNAL(activated(int)), 102 connect(m_modelTypeCombo, SIGNAL(activated(int)),
67 this, SLOT(modelTypeChanged(int))); 103 this, SLOT(modelTypeChanged(int)));
68 m_modelTypeCombo->setCurrentIndex(int(m_modelType)); 104 m_modelTypeCombo->setCurrentIndex(int(m_format.getModelType()));
69 105
70 layout->addWidget(new QLabel(tr("The first column contains:")), 2, 0); 106 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0);
71 107
72 m_timingTypeCombo = new QComboBox; 108 m_timingTypeCombo = new QComboBox;
73 m_timingTypeCombo->addItem(tr("Time, in seconds")); 109 m_timingTypeCombo->addItem(tr("Explicitly, in seconds"));
74 m_timingTypeCombo->addItem(tr("Time, in audio sample frames")); 110 m_timingTypeCombo->addItem(tr("Explicitly, in audio sample frames"));
75 m_timingTypeCombo->addItem(tr("Data (rows are consecutive in time)")); 111 m_timingTypeCombo->addItem(tr("Implicitly: rows are equally spaced in time"));
76 layout->addWidget(m_timingTypeCombo, 2, 1, 1, 2); 112 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2);
77 connect(m_timingTypeCombo, SIGNAL(activated(int)), 113 connect(m_timingTypeCombo, SIGNAL(activated(int)),
78 this, SLOT(timingTypeChanged(int))); 114 this, SLOT(timingTypeChanged(int)));
79 m_timingTypeCombo->setCurrentIndex(m_timingType == CSVFormat::ExplicitTiming ? 115 m_timingTypeCombo->setCurrentIndex
80 m_timeUnits == CSVFormat::TimeSeconds ? 0 : 1 : 2); 116 (m_format.getTimingType() == CSVFormat::ExplicitTiming ?
81 117 m_format.getTimeUnits() == CSVFormat::TimeSeconds ? 0 : 1 : 2);
82 m_durationTypeLabel = new QLabel(tr("The second column contains:"));
83 layout->addWidget(m_durationTypeLabel, 3, 0);
84
85 m_durationTypeCombo = new QComboBox;
86 m_durationTypeCombo->addItem(tr("Duration"));
87 m_durationTypeCombo->addItem(tr("End time"));
88 layout->addWidget(m_durationTypeCombo, 3, 1, 1, 2);
89 connect(m_durationTypeCombo, SIGNAL(activated(int)),
90 this, SLOT(durationTypeChanged(int)));
91 m_durationTypeCombo->setCurrentIndex(int(m_durationType));
92 118
93 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); 119 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
94 layout->addWidget(m_sampleRateLabel, 4, 0); 120 layout->addWidget(m_sampleRateLabel, row, 0);
95 121
96 size_t sampleRates[] = { 122 size_t sampleRates[] = {
97 8000, 11025, 12000, 22050, 24000, 32000, 123 8000, 11025, 12000, 22050, 24000, 32000,
98 44100, 48000, 88200, 96000, 176400, 192000 124 44100, 48000, 88200, 96000, 176400, 192000
99 }; 125 };
100 126
101 m_sampleRateCombo = new QComboBox; 127 m_sampleRateCombo = new QComboBox;
102 m_sampleRate = defaultSampleRate;
103 for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) { 128 for (size_t i = 0; i < sizeof(sampleRates) / sizeof(sampleRates[0]); ++i) {
104 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); 129 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i]));
105 if (sampleRates[i] == m_sampleRate) m_sampleRateCombo->setCurrentIndex(i); 130 if (sampleRates[i] == m_format.getSampleRate()) {
131 m_sampleRateCombo->setCurrentIndex(i);
132 }
106 } 133 }
107 m_sampleRateCombo->setEditable(true); 134 m_sampleRateCombo->setEditable(true);
108 135
109 layout->addWidget(m_sampleRateCombo, 4, 1); 136 layout->addWidget(m_sampleRateCombo, row++, 1);
110 connect(m_sampleRateCombo, SIGNAL(activated(QString)), 137 connect(m_sampleRateCombo, SIGNAL(activated(QString)),
111 this, SLOT(sampleRateChanged(QString))); 138 this, SLOT(sampleRateChanged(QString)));
112 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), 139 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
113 this, SLOT(sampleRateChanged(QString))); 140 this, SLOT(sampleRateChanged(QString)));
114 141
115 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); 142 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
116 layout->addWidget(m_windowSizeLabel, 5, 0); 143 layout->addWidget(m_windowSizeLabel, row, 0);
117 144
118 m_windowSizeCombo = new QComboBox; 145 m_windowSizeCombo = new QComboBox;
119 m_windowSize = 1024;
120 for (int i = 0; i <= 16; ++i) { 146 for (int i = 0; i <= 16; ++i) {
121 int value = 1 << i; 147 int value = 1 << i;
122 m_windowSizeCombo->addItem(QString("%1").arg(value)); 148 m_windowSizeCombo->addItem(QString("%1").arg(value));
123 if (value == int(m_windowSize)) m_windowSizeCombo->setCurrentIndex(i); 149 if (value == int(m_format.getWindowSize())) {
150 m_windowSizeCombo->setCurrentIndex(i);
151 }
124 } 152 }
125 m_windowSizeCombo->setEditable(true); 153 m_windowSizeCombo->setEditable(true);
126 154
127 layout->addWidget(m_windowSizeCombo, 5, 1); 155 layout->addWidget(m_windowSizeCombo, row++, 1);
128 connect(m_windowSizeCombo, SIGNAL(activated(QString)), 156 connect(m_windowSizeCombo, SIGNAL(activated(QString)),
129 this, SLOT(windowSizeChanged(QString))); 157 this, SLOT(windowSizeChanged(QString)));
130 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)), 158 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
131 this, SLOT(windowSizeChanged(QString))); 159 this, SLOT(windowSizeChanged(QString)));
132 160
133 layout->addWidget(new QLabel(tr("\nExample data from file:")), 6, 0, 1, 4);
134
135 m_exampleWidget = new QTableWidget
136 (std::min(10, m_example.size()), m_maxExampleCols);
137
138 layout->addWidget(m_exampleWidget, 7, 0, 1, 4);
139 layout->setColumnStretch(3, 10);
140 layout->setRowStretch(6, 10);
141
142 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | 161 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
143 QDialogButtonBox::Cancel); 162 QDialogButtonBox::Cancel);
144 layout->addWidget(bb, 8, 0, 1, 4); 163 layout->addWidget(bb, row++, 0, 1, 4);
145 connect(bb, SIGNAL(accepted()), this, SLOT(accept())); 164 connect(bb, SIGNAL(accepted()), this, SLOT(accept()));
146 connect(bb, SIGNAL(rejected()), this, SLOT(reject())); 165 connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
147 166
148 setLayout(layout); 167 setLayout(layout);
149 168
150 modelTypeChanged(m_modelTypeCombo->currentIndex()); 169 modelTypeChanged(m_modelTypeCombo->currentIndex());
151 timingTypeChanged(m_timingTypeCombo->currentIndex()); 170 timingTypeChanged(m_timingTypeCombo->currentIndex());
152 durationTypeChanged(m_durationTypeCombo->currentIndex());
153 } 171 }
154 172
155 CSVFormatDialog::~CSVFormatDialog() 173 CSVFormatDialog::~CSVFormatDialog()
156 { 174 {
157 } 175 }
158 176
159 CSVFormat 177 CSVFormat
160 CSVFormatDialog::getFormat() const 178 CSVFormatDialog::getFormat() const
161 { 179 {
162 CSVFormat format; 180 return m_format;
163 format.setModelType(m_modelType);
164 format.setTimingType(m_timingType);
165 format.setDurationType(m_durationType);
166 format.setTimeUnits(m_timeUnits);
167 format.setSeparator(m_separator);
168 format.setSampleRate(m_sampleRate);
169 format.setWindowSize(m_windowSize);
170 format.setSplitBehaviour(m_behaviour);
171 return format;
172 }
173
174 void
175 CSVFormatDialog::populateExample()
176 {
177 m_exampleWidget->setColumnCount
178 (m_timingType == CSVFormat::ExplicitTiming ?
179 m_maxExampleCols - 1 : m_maxExampleCols);
180
181 m_exampleWidget->setHorizontalHeaderLabels(QStringList());
182
183 for (int i = 0; i < m_example.size(); ++i) {
184 for (int j = 0; j < m_example[i].size(); ++j) {
185
186 QTableWidgetItem *item = new QTableWidgetItem(m_example[i][j]);
187
188 if (j == 0) {
189 if (m_timingType == CSVFormat::ExplicitTiming) {
190 m_exampleWidget->setVerticalHeaderItem(i, item);
191 continue;
192 } else {
193 QTableWidgetItem *header =
194 new QTableWidgetItem(QString("%1").arg(i));
195 header->setFlags(Qt::ItemIsEnabled);
196 m_exampleWidget->setVerticalHeaderItem(i, header);
197 }
198 }
199 int index = j;
200 if (m_timingType == CSVFormat::ExplicitTiming) --index;
201 item->setFlags(Qt::ItemIsEnabled);
202 m_exampleWidget->setItem(i, index, item);
203 }
204 }
205 } 181 }
206 182
207 void 183 void
208 CSVFormatDialog::modelTypeChanged(int type) 184 CSVFormatDialog::modelTypeChanged(int type)
209 { 185 {
210 m_modelType = (CSVFormat::ModelType)type; 186 m_format.setModelType((CSVFormat::ModelType)type);
211
212 if (m_modelType == CSVFormat::TwoDimensionalModelWithDuration) {
213 m_durationTypeCombo->setEnabled(true);
214 m_durationTypeLabel->setEnabled(true);
215 } else {
216 m_durationTypeCombo->setEnabled(false);
217 m_durationTypeLabel->setEnabled(false);
218 }
219 } 187 }
220 188
221 void 189 void
222 CSVFormatDialog::timingTypeChanged(int type) 190 CSVFormatDialog::timingTypeChanged(int type)
223 { 191 {
224 switch (type) { 192 switch (type) {
225 193
226 case 0: 194 case 0:
227 m_timingType = CSVFormat::ExplicitTiming; 195 m_format.setTimingType(CSVFormat::ExplicitTiming);
228 m_timeUnits = CSVFormat::TimeSeconds; 196 m_format.setTimeUnits(CSVFormat::TimeSeconds);
229 m_sampleRateCombo->setEnabled(false); 197 m_sampleRateCombo->setEnabled(false);
230 m_sampleRateLabel->setEnabled(false); 198 m_sampleRateLabel->setEnabled(false);
231 m_windowSizeCombo->setEnabled(false); 199 m_windowSizeCombo->setEnabled(false);
232 m_windowSizeLabel->setEnabled(false); 200 m_windowSizeLabel->setEnabled(false);
233 break; 201 break;
234 202
235 case 1: 203 case 1:
236 m_timingType = CSVFormat::ExplicitTiming; 204 m_format.setTimingType(CSVFormat::ExplicitTiming);
237 m_timeUnits = CSVFormat::TimeAudioFrames; 205 m_format.setTimeUnits(CSVFormat::TimeAudioFrames);
238 m_sampleRateCombo->setEnabled(true); 206 m_sampleRateCombo->setEnabled(true);
239 m_sampleRateLabel->setEnabled(true); 207 m_sampleRateLabel->setEnabled(true);
240 m_windowSizeCombo->setEnabled(false); 208 m_windowSizeCombo->setEnabled(false);
241 m_windowSizeLabel->setEnabled(false); 209 m_windowSizeLabel->setEnabled(false);
242 break; 210 break;
243 211
244 case 2: 212 case 2:
245 m_timingType = CSVFormat::ImplicitTiming; 213 m_format.setTimingType(CSVFormat::ImplicitTiming);
246 m_timeUnits = CSVFormat::TimeWindows; 214 m_format.setTimeUnits(CSVFormat::TimeWindows);
247 m_sampleRateCombo->setEnabled(true); 215 m_sampleRateCombo->setEnabled(true);
248 m_sampleRateLabel->setEnabled(true); 216 m_sampleRateLabel->setEnabled(true);
249 m_windowSizeCombo->setEnabled(true); 217 m_windowSizeCombo->setEnabled(true);
250 m_windowSizeLabel->setEnabled(true); 218 m_windowSizeLabel->setEnabled(true);
251 break; 219 break;
252 } 220 }
253
254 populateExample();
255 }
256
257 void
258 CSVFormatDialog::durationTypeChanged(int type)
259 {
260 m_durationType = (CSVFormat::DurationType)type;
261 } 221 }
262 222
263 void 223 void
264 CSVFormatDialog::sampleRateChanged(QString rateString) 224 CSVFormatDialog::sampleRateChanged(QString rateString)
265 { 225 {
266 bool ok = false; 226 bool ok = false;
267 int sampleRate = rateString.toInt(&ok); 227 int sampleRate = rateString.toInt(&ok);
268 if (ok) m_sampleRate = sampleRate; 228 if (ok) m_format.setSampleRate(sampleRate);
269 } 229 }
270 230
271 void 231 void
272 CSVFormatDialog::windowSizeChanged(QString sizeString) 232 CSVFormatDialog::windowSizeChanged(QString sizeString)
273 { 233 {
274 bool ok = false; 234 bool ok = false;
275 int size = sizeString.toInt(&ok); 235 int size = sizeString.toInt(&ok);
276 if (ok) m_windowSize = size; 236 if (ok) m_format.setWindowSize(size);
277 } 237 }
238
239 void
240 CSVFormatDialog::columnPurposeChanged(int purpose)
241 {
242 QObject *o = sender();
243 QComboBox *cb = qobject_cast<QComboBox *>(o);
244 if (!cb) return;
245 int changedCol = -1;
246 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
247 if (cb == m_columnPurposeCombos[i]) {
248 changedCol = i;
249 break;
250 }
251 }
252 if (changedCol < 0) {
253 std::cerr << "Hm, some problem here -- column combo changed, but cannot locate column" << std::endl;
254 return;
255 }
256
257 }
258
259