Mercurial > hg > svgui
comparison widgets/CSVFormatDialog.cpp @ 959:2633a1d73e39
Address #1214, layer import produces wrong layer type. We needed a more principled approach to making sure the format gets updated properly and the dialog elements are consistent (basically separating making the dialog elements consistent from subsequently updating the format). This change should provide that, though there may be gotchas still.
author | Chris Cannam |
---|---|
date | Tue, 12 May 2015 12:31:37 +0100 |
parents | 50be12cf2802 |
children | fd934705973f |
comparison
equal
deleted
inserted
replaced
947:e53a87a5efb2 | 959:2633a1d73e39 |
---|---|
119 layout->setRowStretch(row++, 10); | 119 layout->setRowStretch(row++, 10); |
120 | 120 |
121 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0); | 121 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0); |
122 | 122 |
123 m_timingTypeCombo = new QComboBox; | 123 m_timingTypeCombo = new QComboBox; |
124 m_timingTypeCombo->addItem(tr("Explicitly, in seconds")); | 124 |
125 m_timingTypeCombo->addItem(tr("Explicitly, in milliseconds")); | 125 m_timingLabels = { |
126 m_timingTypeCombo->addItem(tr("Explicitly, in audio sample frames")); | 126 { TimingExplicitSeconds, tr("Explicitly, in seconds") }, |
127 m_timingTypeCombo->addItem(tr("Implicitly: rows are equally spaced in time")); | 127 { TimingExplicitMsec, tr("Explicitly, in milliseconds") }, |
128 { TimingExplicitSamples, tr("Explicitly, in audio sample frames") }, | |
129 { TimingImplicit, tr("Implicitly: rows are equally spaced in time") } | |
130 }; | |
131 | |
132 for (auto &l: m_timingLabels) { | |
133 m_timingTypeCombo->addItem(l.second); | |
134 } | |
135 | |
128 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2); | 136 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2); |
137 | |
129 connect(m_timingTypeCombo, SIGNAL(activated(int)), | 138 connect(m_timingTypeCombo, SIGNAL(activated(int)), |
130 this, SLOT(timingTypeChanged(int))); | 139 this, SLOT(timingTypeChanged(int))); |
131 m_timingTypeCombo->setCurrentIndex | 140 |
132 (m_format.getTimingType() == CSVFormat::ExplicitTiming ? | 141 m_initialTimingOption = TimingImplicit; |
133 m_format.getTimeUnits() == CSVFormat::TimeSeconds ? 0 : 2 : 3); | 142 if (m_format.getTimingType() == CSVFormat::ExplicitTiming) { |
143 switch (m_format.getTimeUnits()) { | |
144 case CSVFormat::TimeSeconds: | |
145 m_initialTimingOption = TimingExplicitSeconds; break; | |
146 case CSVFormat::TimeMilliseconds: | |
147 m_initialTimingOption = TimingExplicitMsec; break; | |
148 case CSVFormat::TimeAudioFrames: | |
149 m_initialTimingOption = TimingExplicitSamples; break; | |
150 case CSVFormat::TimeWindows: | |
151 m_initialTimingOption = TimingImplicit; break; | |
152 } | |
153 } | |
154 m_timingTypeCombo->setCurrentIndex(int(m_initialTimingOption)); | |
134 | 155 |
135 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); | 156 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); |
136 layout->addWidget(m_sampleRateLabel, row, 0); | 157 layout->addWidget(m_sampleRateLabel, row, 0); |
137 | 158 |
138 int sampleRates[] = { | 159 int sampleRates[] = { |
187 connect(bb, SIGNAL(rejected()), this, SLOT(reject())); | 208 connect(bb, SIGNAL(rejected()), this, SLOT(reject())); |
188 | 209 |
189 setLayout(layout); | 210 setLayout(layout); |
190 | 211 |
191 timingTypeChanged(m_timingTypeCombo->currentIndex()); | 212 timingTypeChanged(m_timingTypeCombo->currentIndex()); |
192 updateModelLabel(); | |
193 } | 213 } |
194 | 214 |
195 CSVFormatDialog::~CSVFormatDialog() | 215 CSVFormatDialog::~CSVFormatDialog() |
196 { | 216 { |
197 } | 217 } |
228 | 248 |
229 m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.").arg(s)); | 249 m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.").arg(s)); |
230 } | 250 } |
231 | 251 |
232 void | 252 void |
253 CSVFormatDialog::applyStartTimePurpose() | |
254 { | |
255 // First check if we already have any | |
256 for (int i = 0; i < m_format.getColumnCount(); ++i) { | |
257 QComboBox *cb = m_columnPurposeCombos[i]; | |
258 if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) { | |
259 return; | |
260 } | |
261 } | |
262 // and if not, select one | |
263 for (int i = 0; i < m_format.getColumnCount(); ++i) { | |
264 QComboBox *cb = m_columnPurposeCombos[i]; | |
265 if (cb->currentIndex() == int(CSVFormat::ColumnValue)) { | |
266 cb->setCurrentIndex(int(CSVFormat::ColumnStartTime)); | |
267 return; | |
268 } | |
269 } | |
270 } | |
271 | |
272 void | |
273 CSVFormatDialog::removeStartTimePurpose() | |
274 { | |
275 for (int i = 0; i < m_format.getColumnCount(); ++i) { | |
276 QComboBox *cb = m_columnPurposeCombos[i]; | |
277 if (cb->currentIndex() == int(CSVFormat::ColumnStartTime)) { | |
278 cb->setCurrentIndex(int(CSVFormat::ColumnValue)); | |
279 } | |
280 } | |
281 } | |
282 | |
283 void | |
284 CSVFormatDialog::updateComboVisibility() | |
285 { | |
286 bool wantRate = (m_format.getTimingType() == CSVFormat::ImplicitTiming || | |
287 m_format.getTimeUnits() == CSVFormat::TimeAudioFrames); | |
288 bool wantWindow = (m_format.getTimingType() == CSVFormat::ImplicitTiming); | |
289 | |
290 m_sampleRateCombo->setEnabled(wantRate); | |
291 m_sampleRateLabel->setEnabled(wantRate); | |
292 | |
293 m_windowSizeCombo->setEnabled(wantWindow); | |
294 m_windowSizeLabel->setEnabled(wantWindow); | |
295 } | |
296 | |
297 void | |
233 CSVFormatDialog::timingTypeChanged(int type) | 298 CSVFormatDialog::timingTypeChanged(int type) |
234 { | 299 { |
235 switch (type) { | 300 // Update any column purpose combos |
236 | 301 if (TimingOption(type) == TimingImplicit) { |
237 case 0: | 302 removeStartTimePurpose(); |
238 m_format.setTimingType(CSVFormat::ExplicitTiming); | 303 } else { |
239 m_format.setTimeUnits(CSVFormat::TimeSeconds); | 304 applyStartTimePurpose(); |
240 m_sampleRateCombo->setEnabled(false); | 305 } |
241 m_sampleRateLabel->setEnabled(false); | 306 updateFormatFromDialog(); |
242 m_windowSizeCombo->setEnabled(false); | 307 updateComboVisibility(); |
243 m_windowSizeLabel->setEnabled(false); | |
244 break; | |
245 | |
246 case 1: | |
247 m_format.setTimingType(CSVFormat::ExplicitTiming); | |
248 m_format.setTimeUnits(CSVFormat::TimeMilliseconds); | |
249 m_sampleRateCombo->setEnabled(true); | |
250 m_sampleRateLabel->setEnabled(true); | |
251 m_windowSizeCombo->setEnabled(false); | |
252 m_windowSizeLabel->setEnabled(false); | |
253 break; | |
254 | |
255 case 2: | |
256 m_format.setTimingType(CSVFormat::ExplicitTiming); | |
257 m_format.setTimeUnits(CSVFormat::TimeAudioFrames); | |
258 m_sampleRateCombo->setEnabled(true); | |
259 m_sampleRateLabel->setEnabled(true); | |
260 m_windowSizeCombo->setEnabled(false); | |
261 m_windowSizeLabel->setEnabled(false); | |
262 break; | |
263 | |
264 case 3: | |
265 m_format.setTimingType(CSVFormat::ImplicitTiming); | |
266 m_format.setTimeUnits(CSVFormat::TimeWindows); | |
267 m_sampleRateCombo->setEnabled(true); | |
268 m_sampleRateLabel->setEnabled(true); | |
269 m_windowSizeCombo->setEnabled(true); | |
270 m_windowSizeLabel->setEnabled(true); | |
271 break; | |
272 } | |
273 } | 308 } |
274 | 309 |
275 void | 310 void |
276 CSVFormatDialog::sampleRateChanged(QString rateString) | 311 CSVFormatDialog::sampleRateChanged(QString rateString) |
277 { | 312 { |
290 | 325 |
291 void | 326 void |
292 CSVFormatDialog::columnPurposeChanged(int p) | 327 CSVFormatDialog::columnPurposeChanged(int p) |
293 { | 328 { |
294 QObject *o = sender(); | 329 QObject *o = sender(); |
295 | |
296 QComboBox *cb = qobject_cast<QComboBox *>(o); | 330 QComboBox *cb = qobject_cast<QComboBox *>(o); |
297 if (!cb) return; | 331 if (!cb) return; |
298 | 332 |
299 CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p; | 333 CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p; |
300 | 334 |
301 bool haveStartTime = false; | 335 bool haveStartTime = false; // so as to update timing type combo appropriately |
302 bool haveDuration = false; | 336 |
303 bool havePitch = false; | 337 // Ensure the column purpose combos are consistent with one |
304 int valueCount = 0; | 338 // another, without reference to m_format (which we'll update |
305 | 339 // separately) |
340 | |
306 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { | 341 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { |
307 | 342 |
308 CSVFormat::ColumnPurpose cp = m_format.getColumnPurpose(i); | 343 QComboBox *thisCombo = m_columnPurposeCombos[i]; |
309 | |
310 bool thisChanged = (cb == m_columnPurposeCombos[i]); | |
311 | 344 |
312 if (thisChanged) { | 345 CSVFormat::ColumnPurpose cp = (CSVFormat::ColumnPurpose) |
313 | 346 (thisCombo->currentIndex()); |
314 cerr << "i == " << i << ", fuzzy == " << m_fuzzyColumn | 347 bool thisChanged = (cb == thisCombo); |
315 << ", p == " << p << endl; | 348 |
316 | 349 if (!thisChanged) { |
317 if (i == m_fuzzyColumn) { | |
318 for (int j = i; j < m_format.getColumnCount(); ++j) { | |
319 if (p == 0) { // Ignore | |
320 m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown); | |
321 } else { // Value | |
322 m_format.setColumnPurpose(j, CSVFormat::ColumnValue); | |
323 ++valueCount; | |
324 } | |
325 } | |
326 continue; | |
327 } | |
328 | |
329 cp = purpose; | |
330 | |
331 } else { | |
332 | 350 |
333 if (i == m_fuzzyColumn) continue; | 351 if (i == m_fuzzyColumn) continue; |
334 | 352 |
335 // We can only have one ColumnStartTime column, and only | 353 // We can only have one ColumnStartTime column, and only |
336 // one of either ColumnDuration or ColumnEndTime | 354 // one of either ColumnDuration or ColumnEndTime |
351 if (purpose == CSVFormat::ColumnLabel) { | 369 if (purpose == CSVFormat::ColumnLabel) { |
352 if (cp == purpose) { | 370 if (cp == purpose) { |
353 cp = CSVFormat::ColumnUnknown; | 371 cp = CSVFormat::ColumnUnknown; |
354 } | 372 } |
355 } | 373 } |
356 } | 374 |
357 | 375 if (cp == CSVFormat::ColumnStartTime) { |
358 if (cp == CSVFormat::ColumnStartTime) { | 376 haveStartTime = true; |
377 } | |
378 | |
379 thisCombo->setCurrentIndex(int(cp)); | |
380 | |
381 } else { | |
382 if (purpose == CSVFormat::ColumnStartTime) { | |
383 haveStartTime = true; | |
384 } | |
385 } | |
386 } | |
387 | |
388 if (!haveStartTime) { | |
389 m_timingTypeCombo->setCurrentIndex(int(TimingImplicit)); | |
390 } else if (m_timingTypeCombo->currentIndex() == int(TimingImplicit)) { | |
391 if (m_initialTimingOption == TimingImplicit) { | |
392 m_timingTypeCombo->setCurrentIndex(TimingExplicitSeconds); | |
393 } else { | |
394 m_timingTypeCombo->setCurrentIndex(m_initialTimingOption); | |
395 } | |
396 } | |
397 | |
398 updateFormatFromDialog(); | |
399 updateComboVisibility(); | |
400 } | |
401 | |
402 void | |
403 CSVFormatDialog::updateFormatFromDialog() | |
404 { | |
405 switch (TimingOption(m_timingTypeCombo->currentIndex())) { | |
406 | |
407 case TimingExplicitSeconds: | |
408 m_format.setTimingType(CSVFormat::ExplicitTiming); | |
409 m_format.setTimeUnits(CSVFormat::TimeSeconds); | |
410 break; | |
411 | |
412 case TimingExplicitMsec: | |
413 m_format.setTimingType(CSVFormat::ExplicitTiming); | |
414 m_format.setTimeUnits(CSVFormat::TimeMilliseconds); | |
415 break; | |
416 | |
417 case TimingExplicitSamples: | |
418 m_format.setTimingType(CSVFormat::ExplicitTiming); | |
419 m_format.setTimeUnits(CSVFormat::TimeAudioFrames); | |
420 break; | |
421 | |
422 case TimingImplicit: | |
423 m_format.setTimingType(CSVFormat::ImplicitTiming); | |
424 m_format.setTimeUnits(CSVFormat::TimeWindows); | |
425 break; | |
426 } | |
427 | |
428 bool haveStartTime = false; | |
429 bool haveDuration = false; | |
430 bool havePitch = false; | |
431 int valueCount = 0; | |
432 | |
433 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { | |
434 | |
435 QComboBox *thisCombo = m_columnPurposeCombos[i]; | |
436 | |
437 CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose) | |
438 (thisCombo->currentIndex()); | |
439 | |
440 if (purpose == CSVFormat::ColumnStartTime) { | |
359 haveStartTime = true; | 441 haveStartTime = true; |
360 } | 442 } |
361 if (cp == CSVFormat::ColumnEndTime || | 443 if (purpose == CSVFormat::ColumnEndTime || |
362 cp == CSVFormat::ColumnDuration) { | 444 purpose == CSVFormat::ColumnDuration) { |
363 haveDuration = true; | 445 haveDuration = true; |
364 } | 446 } |
365 if (cp == CSVFormat::ColumnPitch) { | 447 if (purpose == CSVFormat::ColumnPitch) { |
366 havePitch = true; | 448 havePitch = true; |
367 } | 449 } |
368 if (cp == CSVFormat::ColumnValue) { | 450 if (purpose == CSVFormat::ColumnValue) { |
369 ++valueCount; | 451 ++valueCount; |
370 } | 452 } |
371 | 453 |
372 m_columnPurposeCombos[i]->setCurrentIndex(int(cp)); | 454 m_format.setColumnPurpose(i, purpose); |
373 m_format.setColumnPurpose(i, cp); | 455 |
374 } | 456 if (i == m_fuzzyColumn) { |
375 | 457 for (int j = i + 1; j < m_format.getColumnCount(); ++j) { |
376 if (!haveStartTime) { | 458 if (purpose == CSVFormat::ColumnUnknown) { |
377 m_timingTypeCombo->setCurrentIndex(2); | 459 m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown); |
378 timingTypeChanged(2); | 460 } else { // Value |
461 m_format.setColumnPurpose(j, CSVFormat::ColumnValue); | |
462 ++valueCount; | |
463 } | |
464 } | |
465 } | |
379 } | 466 } |
380 | 467 |
381 if (haveStartTime && haveDuration) { | 468 if (haveStartTime && haveDuration) { |
382 if (havePitch) { | 469 if (havePitch) { |
383 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDurationAndPitch); | 470 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDurationAndPitch); |
396 | 483 |
397 updateModelLabel(); | 484 updateModelLabel(); |
398 } | 485 } |
399 | 486 |
400 | 487 |
488 |