Mercurial > hg > svgui
comparison widgets/CSVFormatDialog.cpp @ 1413:0930a27ebea2
Support changing the separator (if more than one plausible one is found) and repopulating the dialog
author | Chris Cannam |
---|---|
date | Wed, 09 Jan 2019 14:41:52 +0000 |
parents | fbda05431ce0 |
children | d3ef60b6ae93 |
comparison
equal
deleted
inserted
replaced
1412:79032214f79d | 1413:0930a27ebea2 |
---|---|
32 #include <iostream> | 32 #include <iostream> |
33 #include <cmath> | 33 #include <cmath> |
34 | 34 |
35 #include "base/Debug.h" | 35 #include "base/Debug.h" |
36 | 36 |
37 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format, | 37 CSVFormatDialog::CSVFormatDialog(QWidget *parent, |
38 CSVFormat format, | |
38 int maxDisplayCols) : | 39 int maxDisplayCols) : |
39 QDialog(parent), | 40 QDialog(parent), |
41 m_csvFilePath(""), | |
42 m_referenceSampleRate(0), | |
40 m_format(format), | 43 m_format(format), |
41 m_maxDisplayCols(maxDisplayCols), | 44 m_maxDisplayCols(maxDisplayCols), |
42 m_fuzzyColumn(-1) | 45 m_fuzzyColumn(-1) |
43 { | 46 { |
47 init(); | |
48 } | |
49 | |
50 CSVFormatDialog::CSVFormatDialog(QWidget *parent, | |
51 QString csvFilePath, | |
52 sv_samplerate_t referenceSampleRate, | |
53 int maxDisplayCols) : | |
54 QDialog(parent), | |
55 m_csvFilePath(csvFilePath), | |
56 m_referenceSampleRate(referenceSampleRate), | |
57 m_maxDisplayCols(maxDisplayCols), | |
58 m_fuzzyColumn(-1) | |
59 { | |
60 m_format = CSVFormat(csvFilePath); | |
61 m_format.setSampleRate(referenceSampleRate); | |
62 init(); | |
63 } | |
64 | |
65 CSVFormatDialog::~CSVFormatDialog() | |
66 { | |
67 } | |
68 | |
69 static int sampleRates[] = { | |
70 8000, 11025, 12000, 22050, 24000, 32000, | |
71 44100, 48000, 88200, 96000, 176400, 192000 | |
72 }; | |
73 | |
74 void | |
75 CSVFormatDialog::init() | |
76 { | |
44 setModal(true); | 77 setModal(true); |
45 setWindowTitle(tr("Select Data Format")); | 78 setWindowTitle(tr("Select Data Format")); |
46 | 79 |
47 QGridLayout *layout = new QGridLayout; | 80 QGridLayout *layout = new QGridLayout; |
48 | 81 |
49 int row = 0; | 82 int row = 0; |
50 | 83 |
51 layout->addWidget | 84 layout->addWidget |
52 (new QLabel(tr("Please select the correct data format for this file.")), | 85 (new QLabel(tr("Please select the correct data format for this file.")), |
53 row++, 0, 1, 4); | 86 row++, 0, 1, 4); |
87 | |
88 m_exampleFrame = nullptr; | |
89 m_exampleFrameRow = row++; | |
90 | |
91 std::set<QChar> plausible = m_format.getPlausibleSeparators(); | |
92 SVDEBUG << "Have " << plausible.size() << " plausible separator(s)" << endl; | |
93 | |
94 if (m_csvFilePath != "" && plausible.size() > 1) { | |
95 // can only update when separator changed if we still have a | |
96 // file to refer to | |
97 layout->addWidget(new QLabel(tr("Column separator:")), row, 0); | |
98 m_separatorCombo = new QComboBox; | |
99 for (QChar c: plausible) { | |
100 m_separatorCombo->addItem(QString(c)); | |
101 if (c == m_format.getSeparator()) { | |
102 m_separatorCombo->setCurrentIndex(m_separatorCombo->count()-1); | |
103 } | |
104 } | |
105 m_separatorCombo->setEditable(false); | |
106 | |
107 layout->addWidget(m_separatorCombo, row++, 1); | |
108 connect(m_separatorCombo, SIGNAL(activated(QString)), | |
109 this, SLOT(separatorChanged(QString))); | |
110 } | |
111 | |
112 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0); | |
113 | |
114 m_timingTypeCombo = new QComboBox; | |
115 | |
116 m_timingLabels = { | |
117 { TimingExplicitSeconds, tr("Explicitly, in seconds") }, | |
118 { TimingExplicitMsec, tr("Explicitly, in milliseconds") }, | |
119 { TimingExplicitSamples, tr("Explicitly, in audio sample frames") }, | |
120 { TimingImplicit, tr("Implicitly: rows are equally spaced in time") } | |
121 }; | |
122 | |
123 for (auto &l: m_timingLabels) { | |
124 m_timingTypeCombo->addItem(l.second); | |
125 } | |
126 | |
127 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2); | |
128 | |
129 connect(m_timingTypeCombo, SIGNAL(activated(int)), | |
130 this, SLOT(timingTypeChanged(int))); | |
131 | |
132 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); | |
133 layout->addWidget(m_sampleRateLabel, row, 0); | |
134 | |
135 m_sampleRateCombo = new QComboBox; | |
136 for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) { | |
137 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); | |
138 } | |
139 m_sampleRateCombo->setEditable(true); | |
140 | |
141 layout->addWidget(m_sampleRateCombo, row++, 1); | |
142 connect(m_sampleRateCombo, SIGNAL(activated(QString)), | |
143 this, SLOT(sampleRateChanged(QString))); | |
144 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), | |
145 this, SLOT(sampleRateChanged(QString))); | |
146 | |
147 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); | |
148 layout->addWidget(m_windowSizeLabel, row, 0); | |
149 | |
150 m_windowSizeCombo = new QComboBox; | |
151 for (int i = 0; i <= 16; ++i) { | |
152 int value = 1 << i; | |
153 m_windowSizeCombo->addItem(QString("%1").arg(value)); | |
154 } | |
155 m_windowSizeCombo->setEditable(true); | |
156 | |
157 layout->addWidget(m_windowSizeCombo, row++, 1); | |
158 connect(m_windowSizeCombo, SIGNAL(activated(QString)), | |
159 this, SLOT(windowSizeChanged(QString))); | |
160 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)), | |
161 this, SLOT(windowSizeChanged(QString))); | |
162 | |
163 m_modelLabel = new QLabel; | |
164 QFont f(m_modelLabel->font()); | |
165 f.setItalic(true); | |
166 m_modelLabel->setFont(f); | |
167 layout->addWidget(m_modelLabel, row++, 0, 1, 4); | |
168 | |
169 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | | |
170 QDialogButtonBox::Cancel); | |
171 layout->addWidget(bb, row++, 0, 1, 4); | |
172 connect(bb, SIGNAL(accepted()), this, SLOT(accept())); | |
173 connect(bb, SIGNAL(rejected()), this, SLOT(reject())); | |
174 | |
175 setLayout(layout); | |
176 | |
177 repopulate(); | |
178 } | |
179 | |
180 void | |
181 CSVFormatDialog::repopulate() | |
182 { | |
183 SVCERR << "CSVFormatDialog::repopulate()" << endl; | |
184 | |
185 QGridLayout *layout = qobject_cast<QGridLayout *>(this->layout()); | |
54 | 186 |
55 QFrame *exampleFrame = new QFrame; | 187 QFrame *exampleFrame = new QFrame; |
56 exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); | 188 exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); |
57 exampleFrame->setLineWidth(2); | 189 exampleFrame->setLineWidth(2); |
58 QGridLayout *exampleLayout = new QGridLayout; | 190 QGridLayout *exampleLayout = new QGridLayout; |
64 exampleFrame->setPalette(palette); | 196 exampleFrame->setPalette(palette); |
65 | 197 |
66 QFont fp; | 198 QFont fp; |
67 fp.setPointSize(int(floor(fp.pointSize() * 0.9))); | 199 fp.setPointSize(int(floor(fp.pointSize() * 0.9))); |
68 | 200 |
69 int columns = format.getColumnCount(); | 201 int columns = m_format.getColumnCount(); |
70 QList<QStringList> example = m_format.getExample(); | 202 QList<QStringList> example = m_format.getExample(); |
71 | 203 |
204 m_columnPurposeCombos.clear(); | |
205 | |
72 for (int i = 0; i < columns; ++i) { | 206 for (int i = 0; i < columns; ++i) { |
73 | 207 |
74 QComboBox *cpc = new QComboBox; | 208 QComboBox *cpc = new QComboBox; |
75 m_columnPurposeCombos.push_back(cpc); | 209 m_columnPurposeCombos.push_back(cpc); |
76 exampleLayout->addWidget(cpc, 0, i); | 210 exampleLayout->addWidget(cpc, 0, i); |
113 label->setIndent(8); | 247 label->setIndent(8); |
114 exampleLayout->addWidget(label, j+1, i); | 248 exampleLayout->addWidget(label, j+1, i); |
115 } | 249 } |
116 } | 250 } |
117 | 251 |
118 layout->addWidget(exampleFrame, row, 0, 1, 4); | 252 if (m_exampleFrame) { |
253 delete m_exampleFrame; | |
254 } | |
255 m_exampleFrame = exampleFrame; | |
256 | |
257 layout->addWidget(exampleFrame, m_exampleFrameRow, 0, 1, 4); | |
119 layout->setColumnStretch(3, 10); | 258 layout->setColumnStretch(3, 10); |
120 layout->setRowStretch(row++, 10); | 259 layout->setRowStretch(m_exampleFrameRow, 10); |
121 | |
122 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0); | |
123 | |
124 m_timingTypeCombo = new QComboBox; | |
125 | |
126 m_timingLabels = { | |
127 { TimingExplicitSeconds, tr("Explicitly, in seconds") }, | |
128 { TimingExplicitMsec, tr("Explicitly, in milliseconds") }, | |
129 { TimingExplicitSamples, tr("Explicitly, in audio sample frames") }, | |
130 { TimingImplicit, tr("Implicitly: rows are equally spaced in time") } | |
131 }; | |
132 | |
133 for (auto &l: m_timingLabels) { | |
134 m_timingTypeCombo->addItem(l.second); | |
135 } | |
136 | |
137 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2); | |
138 | |
139 connect(m_timingTypeCombo, SIGNAL(activated(int)), | |
140 this, SLOT(timingTypeChanged(int))); | |
141 | 260 |
142 m_initialTimingOption = TimingImplicit; | 261 m_initialTimingOption = TimingImplicit; |
143 if (m_format.getTimingType() == CSVFormat::ExplicitTiming) { | 262 if (m_format.getTimingType() == CSVFormat::ExplicitTiming) { |
144 switch (m_format.getTimeUnits()) { | 263 switch (m_format.getTimeUnits()) { |
145 case CSVFormat::TimeSeconds: | 264 case CSVFormat::TimeSeconds: |
151 case CSVFormat::TimeWindows: | 270 case CSVFormat::TimeWindows: |
152 m_initialTimingOption = TimingImplicit; break; | 271 m_initialTimingOption = TimingImplicit; break; |
153 } | 272 } |
154 } | 273 } |
155 m_timingTypeCombo->setCurrentIndex(int(m_initialTimingOption)); | 274 m_timingTypeCombo->setCurrentIndex(int(m_initialTimingOption)); |
156 | 275 |
157 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); | |
158 layout->addWidget(m_sampleRateLabel, row, 0); | |
159 | |
160 int sampleRates[] = { | |
161 8000, 11025, 12000, 22050, 24000, 32000, | |
162 44100, 48000, 88200, 96000, 176400, 192000 | |
163 }; | |
164 | |
165 m_sampleRateCombo = new QComboBox; | |
166 for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) { | 276 for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) { |
167 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); | |
168 if (sampleRates[i] == m_format.getSampleRate()) { | 277 if (sampleRates[i] == m_format.getSampleRate()) { |
169 m_sampleRateCombo->setCurrentIndex(i); | 278 m_sampleRateCombo->setCurrentIndex(i); |
170 } | 279 } |
171 } | 280 } |
172 m_sampleRateCombo->setEditable(true); | 281 |
173 | |
174 layout->addWidget(m_sampleRateCombo, row++, 1); | |
175 connect(m_sampleRateCombo, SIGNAL(activated(QString)), | |
176 this, SLOT(sampleRateChanged(QString))); | |
177 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), | |
178 this, SLOT(sampleRateChanged(QString))); | |
179 | |
180 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); | |
181 layout->addWidget(m_windowSizeLabel, row, 0); | |
182 | |
183 m_windowSizeCombo = new QComboBox; | |
184 for (int i = 0; i <= 16; ++i) { | 282 for (int i = 0; i <= 16; ++i) { |
185 int value = 1 << i; | 283 int value = 1 << i; |
186 m_windowSizeCombo->addItem(QString("%1").arg(value)); | |
187 if (value == int(m_format.getWindowSize())) { | 284 if (value == int(m_format.getWindowSize())) { |
188 m_windowSizeCombo->setCurrentIndex(i); | 285 m_windowSizeCombo->setCurrentIndex(i); |
189 } | 286 } |
190 } | 287 } |
191 m_windowSizeCombo->setEditable(true); | |
192 | |
193 layout->addWidget(m_windowSizeCombo, row++, 1); | |
194 connect(m_windowSizeCombo, SIGNAL(activated(QString)), | |
195 this, SLOT(windowSizeChanged(QString))); | |
196 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)), | |
197 this, SLOT(windowSizeChanged(QString))); | |
198 | |
199 m_modelLabel = new QLabel; | |
200 QFont f(m_modelLabel->font()); | |
201 f.setItalic(true); | |
202 m_modelLabel->setFont(f); | |
203 layout->addWidget(m_modelLabel, row++, 0, 1, 4); | |
204 | |
205 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | | |
206 QDialogButtonBox::Cancel); | |
207 layout->addWidget(bb, row++, 0, 1, 4); | |
208 connect(bb, SIGNAL(accepted()), this, SLOT(accept())); | |
209 connect(bb, SIGNAL(rejected()), this, SLOT(reject())); | |
210 | |
211 setLayout(layout); | |
212 | 288 |
213 timingTypeChanged(m_timingTypeCombo->currentIndex()); | 289 timingTypeChanged(m_timingTypeCombo->currentIndex()); |
214 } | |
215 | |
216 CSVFormatDialog::~CSVFormatDialog() | |
217 { | |
218 } | 290 } |
219 | 291 |
220 CSVFormat | 292 CSVFormat |
221 CSVFormatDialog::getFormat() const | 293 CSVFormatDialog::getFormat() const |
222 { | 294 { |
313 m_windowSizeCombo->setEnabled(wantWindow); | 385 m_windowSizeCombo->setEnabled(wantWindow); |
314 m_windowSizeLabel->setEnabled(wantWindow); | 386 m_windowSizeLabel->setEnabled(wantWindow); |
315 } | 387 } |
316 | 388 |
317 void | 389 void |
390 CSVFormatDialog::separatorChanged(QString sep) | |
391 { | |
392 if (sep == "" || m_csvFilePath == "") { | |
393 return; | |
394 } | |
395 | |
396 m_format.setSeparator(sep[0]); | |
397 m_format.guessFormatFor(m_csvFilePath); | |
398 | |
399 repopulate(); | |
400 } | |
401 | |
402 void | |
318 CSVFormatDialog::timingTypeChanged(int type) | 403 CSVFormatDialog::timingTypeChanged(int type) |
319 { | 404 { |
320 // Update any column purpose combos | 405 // Update any column purpose combos |
321 if (TimingOption(type) == TimingImplicit) { | 406 if (TimingOption(type) == TimingImplicit) { |
322 removeStartTimePurpose(); | 407 removeStartTimePurpose(); |