svgui  1.9
CSVFormatDialog.cpp
Go to the documentation of this file.
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4  Sonic Visualiser
5  An audio file viewer and annotation editor.
6  Centre for Digital Music, Queen Mary, University of London.
7  This file copyright 2006 Chris Cannam.
8 
9  This program is free software; you can redistribute it and/or
10  modify it under the terms of the GNU General Public License as
11  published by the Free Software Foundation; either version 2 of the
12  License, or (at your option) any later version. See the file
13  COPYING included with this distribution for more information.
14 */
15 
16 #include "CSVFormatDialog.h"
17 
18 #include "layer/LayerFactory.h"
19 
20 #include "TextAbbrev.h"
21 
22 #include <QFrame>
23 #include <QGridLayout>
24 #include <QPushButton>
25 #include <QHBoxLayout>
26 #include <QVBoxLayout>
27 #include <QTableWidget>
28 #include <QComboBox>
29 #include <QLabel>
30 #include <QDialogButtonBox>
31 
32 #include <iostream>
33 
34 #include "base/Debug.h"
35 
36 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format,
37  int maxDisplayCols) :
38  QDialog(parent),
39  m_format(format),
40  m_maxDisplayCols(maxDisplayCols),
41  m_fuzzyColumn(-1)
42 {
43  setModal(true);
44  setWindowTitle(tr("Select Data Format"));
45 
46  QGridLayout *layout = new QGridLayout;
47 
48  int row = 0;
49 
50  layout->addWidget(new QLabel(tr("Please select the correct data format for this file.")),
51  row++, 0, 1, 4);
52 
53  QFrame *exampleFrame = new QFrame;
54  exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
55  exampleFrame->setLineWidth(2);
56  QGridLayout *exampleLayout = new QGridLayout;
57  exampleLayout->setSpacing(4);
58  exampleFrame->setLayout(exampleLayout);
59 
60  QPalette palette = exampleFrame->palette();
61  palette.setColor(QPalette::Window, palette.color(QPalette::Base));
62  exampleFrame->setPalette(palette);
63 
64  QFont fp;
65  fp.setPointSize(fp.pointSize() * 0.9);
66 // fp.setFixedPitch(true);
67 // fp.setStyleHint(QFont::TypeWriter);
68 // fp.setFamily("Monospaced");
69 
70  int columns = format.getColumnCount();
71  QList<QStringList> example = m_format.getExample();
72 
73  for (int i = 0; i < columns; ++i) {
74 
75  QComboBox *cpc = new QComboBox;
76  m_columnPurposeCombos.push_back(cpc);
77  exampleLayout->addWidget(cpc, 0, i);
78  connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int)));
79 
80  if (i == m_maxDisplayCols && columns > i + 2) {
81  m_fuzzyColumn = i;
82  cpc->addItem(tr("<ignore>"));
83  cpc->addItem(tr("Values"));
84  cpc->setCurrentIndex
85  (m_format.getColumnPurpose(i-1) == CSVFormat::ColumnUnknown ? 0 : 1);
86  exampleLayout->addWidget(new QLabel(tr("(%1 more)").arg(columns - i)),
87  1, i);
88  break;
89  }
90 
91  // NB must be in the same order as the CSVFormat::ColumnPurpose enum
92  cpc->addItem(tr("<ignore>")); // ColumnUnknown
93  cpc->addItem(tr("Time")); // ColumnStartTime
94  cpc->addItem(tr("End time")); // ColumnEndTime
95  cpc->addItem(tr("Duration")); // ColumnDuration
96  cpc->addItem(tr("Value")); // ColumnValue
97  cpc->addItem(tr("Pitch")); // ColumnPitch
98  cpc->addItem(tr("Label")); // ColumnLabel
99  cpc->setCurrentIndex(int(m_format.getColumnPurpose(i)));
100 
101  for (int j = 0; j < example.size() && j < 6; ++j) {
102  QLabel *label = new QLabel;
103  label->setTextFormat(Qt::PlainText);
104  QString text = TextAbbrev::abbreviate(example[j][i], 35);
105  label->setText(text);
106  label->setFont(fp);
107  label->setPalette(palette);
108  label->setIndent(8);
109  exampleLayout->addWidget(label, j+1, i);
110  }
111  }
112 
113  layout->addWidget(exampleFrame, row, 0, 1, 4);
114  layout->setColumnStretch(3, 10);
115  layout->setRowStretch(row++, 10);
116 
117  layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0);
118 
119  m_timingTypeCombo = new QComboBox;
120  m_timingTypeCombo->addItem(tr("Explicitly, in seconds"));
121  m_timingTypeCombo->addItem(tr("Explicitly, in audio sample frames"));
122  m_timingTypeCombo->addItem(tr("Implicitly: rows are equally spaced in time"));
123  layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2);
124  connect(m_timingTypeCombo, SIGNAL(activated(int)),
125  this, SLOT(timingTypeChanged(int)));
126  m_timingTypeCombo->setCurrentIndex
127  (m_format.getTimingType() == CSVFormat::ExplicitTiming ?
128  m_format.getTimeUnits() == CSVFormat::TimeSeconds ? 0 : 1 : 2);
129 
130  m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):"));
131  layout->addWidget(m_sampleRateLabel, row, 0);
132 
133  int sampleRates[] = {
134  8000, 11025, 12000, 22050, 24000, 32000,
135  44100, 48000, 88200, 96000, 176400, 192000
136  };
137 
138  m_sampleRateCombo = new QComboBox;
139  for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) {
140  m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i]));
141  if (sampleRates[i] == m_format.getSampleRate()) {
142  m_sampleRateCombo->setCurrentIndex(i);
143  }
144  }
145  m_sampleRateCombo->setEditable(true);
146 
147  layout->addWidget(m_sampleRateCombo, row++, 1);
148  connect(m_sampleRateCombo, SIGNAL(activated(QString)),
149  this, SLOT(sampleRateChanged(QString)));
150  connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)),
151  this, SLOT(sampleRateChanged(QString)));
152 
153  m_windowSizeLabel = new QLabel(tr("Frame increment between rows:"));
154  layout->addWidget(m_windowSizeLabel, row, 0);
155 
156  m_windowSizeCombo = new QComboBox;
157  for (int i = 0; i <= 16; ++i) {
158  int value = 1 << i;
159  m_windowSizeCombo->addItem(QString("%1").arg(value));
160  if (value == int(m_format.getWindowSize())) {
161  m_windowSizeCombo->setCurrentIndex(i);
162  }
163  }
164  m_windowSizeCombo->setEditable(true);
165 
166  layout->addWidget(m_windowSizeCombo, row++, 1);
167  connect(m_windowSizeCombo, SIGNAL(activated(QString)),
168  this, SLOT(windowSizeChanged(QString)));
169  connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)),
170  this, SLOT(windowSizeChanged(QString)));
171 
172  m_modelLabel = new QLabel;
173  QFont f(m_modelLabel->font());
174  f.setItalic(true);
175  m_modelLabel->setFont(f);
176  layout->addWidget(m_modelLabel, row++, 0, 1, 4);
177 
178  QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok |
179  QDialogButtonBox::Cancel);
180  layout->addWidget(bb, row++, 0, 1, 4);
181  connect(bb, SIGNAL(accepted()), this, SLOT(accept()));
182  connect(bb, SIGNAL(rejected()), this, SLOT(reject()));
183 
184  setLayout(layout);
185 
186  timingTypeChanged(m_timingTypeCombo->currentIndex());
188 }
189 
191 {
192 }
193 
194 CSVFormat
196 {
197  return m_format;
198 }
199 
200 void
202 {
204 
205  QString s;
206  switch (m_format.getModelType()) {
207  case CSVFormat::OneDimensionalModel:
209  break;
210  case CSVFormat::TwoDimensionalModel:
212  break;
213  case CSVFormat::TwoDimensionalModelWithDuration:
215  break;
216  case CSVFormat::TwoDimensionalModelWithDurationAndPitch:
218  break;
219  case CSVFormat::ThreeDimensionalModel:
221  break;
222  }
223 
224  m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.").arg(s));
225 }
226 
227 void
229 {
230  switch (type) {
231 
232  case 0:
233  m_format.setTimingType(CSVFormat::ExplicitTiming);
234  m_format.setTimeUnits(CSVFormat::TimeSeconds);
235  m_sampleRateCombo->setEnabled(false);
236  m_sampleRateLabel->setEnabled(false);
237  m_windowSizeCombo->setEnabled(false);
238  m_windowSizeLabel->setEnabled(false);
239  break;
240 
241  case 1:
242  m_format.setTimingType(CSVFormat::ExplicitTiming);
243  m_format.setTimeUnits(CSVFormat::TimeAudioFrames);
244  m_sampleRateCombo->setEnabled(true);
245  m_sampleRateLabel->setEnabled(true);
246  m_windowSizeCombo->setEnabled(false);
247  m_windowSizeLabel->setEnabled(false);
248  break;
249 
250  case 2:
251  m_format.setTimingType(CSVFormat::ImplicitTiming);
252  m_format.setTimeUnits(CSVFormat::TimeWindows);
253  m_sampleRateCombo->setEnabled(true);
254  m_sampleRateLabel->setEnabled(true);
255  m_windowSizeCombo->setEnabled(true);
256  m_windowSizeLabel->setEnabled(true);
257  break;
258  }
259 }
260 
261 void
263 {
264  bool ok = false;
265  int sampleRate = rateString.toInt(&ok);
266  if (ok) m_format.setSampleRate(sampleRate);
267 }
268 
269 void
271 {
272  bool ok = false;
273  int size = sizeString.toInt(&ok);
274  if (ok) m_format.setWindowSize(size);
275 }
276 
277 void
279 {
280  QObject *o = sender();
281 
282  QComboBox *cb = qobject_cast<QComboBox *>(o);
283  if (!cb) return;
284 
285  CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p;
286 
287  bool haveStartTime = false;
288  bool haveDuration = false;
289  bool havePitch = false;
290  int valueCount = 0;
291 
292  for (int i = 0; i < m_columnPurposeCombos.size(); ++i) {
293 
294  CSVFormat::ColumnPurpose cp = m_format.getColumnPurpose(i);
295 
296  bool thisChanged = (cb == m_columnPurposeCombos[i]);
297 
298  if (thisChanged) {
299 
300  cerr << "i == " << i << ", fuzzy == " << m_fuzzyColumn
301  << ", p == " << p << endl;
302 
303  if (i == m_fuzzyColumn) {
304  for (int j = i; j < m_format.getColumnCount(); ++j) {
305  if (p == 0) { // Ignore
306  m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown);
307  } else { // Value
308  m_format.setColumnPurpose(j, CSVFormat::ColumnValue);
309  ++valueCount;
310  }
311  }
312  continue;
313  }
314 
315  cp = purpose;
316 
317  } else {
318 
319  if (i == m_fuzzyColumn) continue;
320 
321  // We can only have one ColumnStartTime column, and only
322  // one of either ColumnDuration or ColumnEndTime
323 
324  if (purpose == CSVFormat::ColumnStartTime) {
325  if (cp == purpose) {
326  cp = CSVFormat::ColumnValue;
327  }
328  } else if (purpose == CSVFormat::ColumnDuration ||
329  purpose == CSVFormat::ColumnEndTime) {
330  if (cp == CSVFormat::ColumnDuration ||
331  cp == CSVFormat::ColumnEndTime) {
332  cp = CSVFormat::ColumnValue;
333  }
334  }
335 
336  // And we can only have one label
337  if (purpose == CSVFormat::ColumnLabel) {
338  if (cp == purpose) {
339  cp = CSVFormat::ColumnUnknown;
340  }
341  }
342  }
343 
344  if (cp == CSVFormat::ColumnStartTime) {
345  haveStartTime = true;
346  }
347  if (cp == CSVFormat::ColumnEndTime ||
348  cp == CSVFormat::ColumnDuration) {
349  haveDuration = true;
350  }
351  if (cp == CSVFormat::ColumnPitch) {
352  havePitch = true;
353  }
354  if (cp == CSVFormat::ColumnValue) {
355  ++valueCount;
356  }
357 
358  m_columnPurposeCombos[i]->setCurrentIndex(int(cp));
359  m_format.setColumnPurpose(i, cp);
360  }
361 
362  if (!haveStartTime) {
363  m_timingTypeCombo->setCurrentIndex(2);
365  }
366 
367  if (haveStartTime && haveDuration) {
368  if (havePitch) {
369  m_format.setModelType(CSVFormat::TwoDimensionalModelWithDurationAndPitch);
370  } else {
371  m_format.setModelType(CSVFormat::TwoDimensionalModelWithDuration);
372  }
373  } else {
374  if (valueCount > 1) {
375  m_format.setModelType(CSVFormat::ThreeDimensionalModel);
376  } else if (valueCount > 0) {
377  m_format.setModelType(CSVFormat::TwoDimensionalModel);
378  } else {
379  m_format.setModelType(CSVFormat::OneDimensionalModel);
380  }
381  }
382 
384 }
385 
386 
void windowSizeChanged(QString)
static LayerFactory * getInstance()
void timingTypeChanged(int type)
static QString abbreviate(QString text, int maxLength, Policy policy=ElideEnd, bool fuzzy=true, QString ellipsis="")
Abbreviate the given text to the given maximum length (including ellipsis), using the given abbreviat...
Definition: TextAbbrev.cpp:74
CSVFormat getFormat() const
QLabel * m_modelLabel
QComboBox * m_timingTypeCombo
CSVFormat m_format
CSVFormatDialog(QWidget *parent, CSVFormat initialFormat, int maxDisplayCols=5)
QString getLayerPresentationName(LayerType type)
void columnPurposeChanged(int purpose)
QLabel * m_sampleRateLabel
QComboBox * m_sampleRateCombo
QComboBox * m_windowSizeCombo
void sampleRateChanged(QString)
QList< QComboBox * > m_columnPurposeCombos
QLabel * m_windowSizeLabel