svgui
1.9
|
00001 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 00002 00003 /* 00004 Sonic Visualiser 00005 An audio file viewer and annotation editor. 00006 Centre for Digital Music, Queen Mary, University of London. 00007 This file copyright 2006 Chris Cannam. 00008 00009 This program is free software; you can redistribute it and/or 00010 modify it under the terms of the GNU General Public License as 00011 published by the Free Software Foundation; either version 2 of the 00012 License, or (at your option) any later version. See the file 00013 COPYING included with this distribution for more information. 00014 */ 00015 00016 #include "CSVFormatDialog.h" 00017 00018 #include "layer/LayerFactory.h" 00019 00020 #include "TextAbbrev.h" 00021 00022 #include <QFrame> 00023 #include <QGridLayout> 00024 #include <QPushButton> 00025 #include <QHBoxLayout> 00026 #include <QVBoxLayout> 00027 #include <QTableWidget> 00028 #include <QComboBox> 00029 #include <QLabel> 00030 #include <QDialogButtonBox> 00031 00032 #include <iostream> 00033 00034 #include "base/Debug.h" 00035 00036 CSVFormatDialog::CSVFormatDialog(QWidget *parent, CSVFormat format, 00037 int maxDisplayCols) : 00038 QDialog(parent), 00039 m_format(format), 00040 m_maxDisplayCols(maxDisplayCols), 00041 m_fuzzyColumn(-1) 00042 { 00043 setModal(true); 00044 setWindowTitle(tr("Select Data Format")); 00045 00046 QGridLayout *layout = new QGridLayout; 00047 00048 int row = 0; 00049 00050 layout->addWidget(new QLabel(tr("Please select the correct data format for this file.")), 00051 row++, 0, 1, 4); 00052 00053 QFrame *exampleFrame = new QFrame; 00054 exampleFrame->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); 00055 exampleFrame->setLineWidth(2); 00056 QGridLayout *exampleLayout = new QGridLayout; 00057 exampleLayout->setSpacing(4); 00058 exampleFrame->setLayout(exampleLayout); 00059 00060 QPalette palette = exampleFrame->palette(); 00061 palette.setColor(QPalette::Window, palette.color(QPalette::Base)); 00062 exampleFrame->setPalette(palette); 00063 00064 QFont fp; 00065 fp.setPointSize(fp.pointSize() * 0.9); 00066 // fp.setFixedPitch(true); 00067 // fp.setStyleHint(QFont::TypeWriter); 00068 // fp.setFamily("Monospaced"); 00069 00070 int columns = format.getColumnCount(); 00071 QList<QStringList> example = m_format.getExample(); 00072 00073 for (int i = 0; i < columns; ++i) { 00074 00075 QComboBox *cpc = new QComboBox; 00076 m_columnPurposeCombos.push_back(cpc); 00077 exampleLayout->addWidget(cpc, 0, i); 00078 connect(cpc, SIGNAL(activated(int)), this, SLOT(columnPurposeChanged(int))); 00079 00080 if (i == m_maxDisplayCols && columns > i + 2) { 00081 m_fuzzyColumn = i; 00082 cpc->addItem(tr("<ignore>")); 00083 cpc->addItem(tr("Values")); 00084 cpc->setCurrentIndex 00085 (m_format.getColumnPurpose(i-1) == CSVFormat::ColumnUnknown ? 0 : 1); 00086 exampleLayout->addWidget(new QLabel(tr("(%1 more)").arg(columns - i)), 00087 1, i); 00088 break; 00089 } 00090 00091 // NB must be in the same order as the CSVFormat::ColumnPurpose enum 00092 cpc->addItem(tr("<ignore>")); // ColumnUnknown 00093 cpc->addItem(tr("Time")); // ColumnStartTime 00094 cpc->addItem(tr("End time")); // ColumnEndTime 00095 cpc->addItem(tr("Duration")); // ColumnDuration 00096 cpc->addItem(tr("Value")); // ColumnValue 00097 cpc->addItem(tr("Pitch")); // ColumnPitch 00098 cpc->addItem(tr("Label")); // ColumnLabel 00099 cpc->setCurrentIndex(int(m_format.getColumnPurpose(i))); 00100 00101 for (int j = 0; j < example.size() && j < 6; ++j) { 00102 QLabel *label = new QLabel; 00103 label->setTextFormat(Qt::PlainText); 00104 QString text = TextAbbrev::abbreviate(example[j][i], 35); 00105 label->setText(text); 00106 label->setFont(fp); 00107 label->setPalette(palette); 00108 label->setIndent(8); 00109 exampleLayout->addWidget(label, j+1, i); 00110 } 00111 } 00112 00113 layout->addWidget(exampleFrame, row, 0, 1, 4); 00114 layout->setColumnStretch(3, 10); 00115 layout->setRowStretch(row++, 10); 00116 00117 layout->addWidget(new QLabel(tr("Timing is specified:")), row, 0); 00118 00119 m_timingTypeCombo = new QComboBox; 00120 m_timingTypeCombo->addItem(tr("Explicitly, in seconds")); 00121 m_timingTypeCombo->addItem(tr("Explicitly, in audio sample frames")); 00122 m_timingTypeCombo->addItem(tr("Implicitly: rows are equally spaced in time")); 00123 layout->addWidget(m_timingTypeCombo, row++, 1, 1, 2); 00124 connect(m_timingTypeCombo, SIGNAL(activated(int)), 00125 this, SLOT(timingTypeChanged(int))); 00126 m_timingTypeCombo->setCurrentIndex 00127 (m_format.getTimingType() == CSVFormat::ExplicitTiming ? 00128 m_format.getTimeUnits() == CSVFormat::TimeSeconds ? 0 : 1 : 2); 00129 00130 m_sampleRateLabel = new QLabel(tr("Audio sample rate (Hz):")); 00131 layout->addWidget(m_sampleRateLabel, row, 0); 00132 00133 int sampleRates[] = { 00134 8000, 11025, 12000, 22050, 24000, 32000, 00135 44100, 48000, 88200, 96000, 176400, 192000 00136 }; 00137 00138 m_sampleRateCombo = new QComboBox; 00139 for (int i = 0; i < int(sizeof(sampleRates) / sizeof(sampleRates[0])); ++i) { 00140 m_sampleRateCombo->addItem(QString("%1").arg(sampleRates[i])); 00141 if (sampleRates[i] == m_format.getSampleRate()) { 00142 m_sampleRateCombo->setCurrentIndex(i); 00143 } 00144 } 00145 m_sampleRateCombo->setEditable(true); 00146 00147 layout->addWidget(m_sampleRateCombo, row++, 1); 00148 connect(m_sampleRateCombo, SIGNAL(activated(QString)), 00149 this, SLOT(sampleRateChanged(QString))); 00150 connect(m_sampleRateCombo, SIGNAL(editTextChanged(QString)), 00151 this, SLOT(sampleRateChanged(QString))); 00152 00153 m_windowSizeLabel = new QLabel(tr("Frame increment between rows:")); 00154 layout->addWidget(m_windowSizeLabel, row, 0); 00155 00156 m_windowSizeCombo = new QComboBox; 00157 for (int i = 0; i <= 16; ++i) { 00158 int value = 1 << i; 00159 m_windowSizeCombo->addItem(QString("%1").arg(value)); 00160 if (value == int(m_format.getWindowSize())) { 00161 m_windowSizeCombo->setCurrentIndex(i); 00162 } 00163 } 00164 m_windowSizeCombo->setEditable(true); 00165 00166 layout->addWidget(m_windowSizeCombo, row++, 1); 00167 connect(m_windowSizeCombo, SIGNAL(activated(QString)), 00168 this, SLOT(windowSizeChanged(QString))); 00169 connect(m_windowSizeCombo, SIGNAL(editTextChanged(QString)), 00170 this, SLOT(windowSizeChanged(QString))); 00171 00172 m_modelLabel = new QLabel; 00173 QFont f(m_modelLabel->font()); 00174 f.setItalic(true); 00175 m_modelLabel->setFont(f); 00176 layout->addWidget(m_modelLabel, row++, 0, 1, 4); 00177 00178 QDialogButtonBox *bb = new QDialogButtonBox(QDialogButtonBox::Ok | 00179 QDialogButtonBox::Cancel); 00180 layout->addWidget(bb, row++, 0, 1, 4); 00181 connect(bb, SIGNAL(accepted()), this, SLOT(accept())); 00182 connect(bb, SIGNAL(rejected()), this, SLOT(reject())); 00183 00184 setLayout(layout); 00185 00186 timingTypeChanged(m_timingTypeCombo->currentIndex()); 00187 updateModelLabel(); 00188 } 00189 00190 CSVFormatDialog::~CSVFormatDialog() 00191 { 00192 } 00193 00194 CSVFormat 00195 CSVFormatDialog::getFormat() const 00196 { 00197 return m_format; 00198 } 00199 00200 void 00201 CSVFormatDialog::updateModelLabel() 00202 { 00203 LayerFactory *f = LayerFactory::getInstance(); 00204 00205 QString s; 00206 switch (m_format.getModelType()) { 00207 case CSVFormat::OneDimensionalModel: 00208 s = f->getLayerPresentationName(LayerFactory::TimeInstants); 00209 break; 00210 case CSVFormat::TwoDimensionalModel: 00211 s = f->getLayerPresentationName(LayerFactory::TimeValues); 00212 break; 00213 case CSVFormat::TwoDimensionalModelWithDuration: 00214 s = f->getLayerPresentationName(LayerFactory::Regions); 00215 break; 00216 case CSVFormat::TwoDimensionalModelWithDurationAndPitch: 00217 s = f->getLayerPresentationName(LayerFactory::Notes); 00218 break; 00219 case CSVFormat::ThreeDimensionalModel: 00220 s = f->getLayerPresentationName(LayerFactory::Colour3DPlot); 00221 break; 00222 } 00223 00224 m_modelLabel->setText("\n" + tr("Data will be displayed in a %1 layer.").arg(s)); 00225 } 00226 00227 void 00228 CSVFormatDialog::timingTypeChanged(int type) 00229 { 00230 switch (type) { 00231 00232 case 0: 00233 m_format.setTimingType(CSVFormat::ExplicitTiming); 00234 m_format.setTimeUnits(CSVFormat::TimeSeconds); 00235 m_sampleRateCombo->setEnabled(false); 00236 m_sampleRateLabel->setEnabled(false); 00237 m_windowSizeCombo->setEnabled(false); 00238 m_windowSizeLabel->setEnabled(false); 00239 break; 00240 00241 case 1: 00242 m_format.setTimingType(CSVFormat::ExplicitTiming); 00243 m_format.setTimeUnits(CSVFormat::TimeAudioFrames); 00244 m_sampleRateCombo->setEnabled(true); 00245 m_sampleRateLabel->setEnabled(true); 00246 m_windowSizeCombo->setEnabled(false); 00247 m_windowSizeLabel->setEnabled(false); 00248 break; 00249 00250 case 2: 00251 m_format.setTimingType(CSVFormat::ImplicitTiming); 00252 m_format.setTimeUnits(CSVFormat::TimeWindows); 00253 m_sampleRateCombo->setEnabled(true); 00254 m_sampleRateLabel->setEnabled(true); 00255 m_windowSizeCombo->setEnabled(true); 00256 m_windowSizeLabel->setEnabled(true); 00257 break; 00258 } 00259 } 00260 00261 void 00262 CSVFormatDialog::sampleRateChanged(QString rateString) 00263 { 00264 bool ok = false; 00265 int sampleRate = rateString.toInt(&ok); 00266 if (ok) m_format.setSampleRate(sampleRate); 00267 } 00268 00269 void 00270 CSVFormatDialog::windowSizeChanged(QString sizeString) 00271 { 00272 bool ok = false; 00273 int size = sizeString.toInt(&ok); 00274 if (ok) m_format.setWindowSize(size); 00275 } 00276 00277 void 00278 CSVFormatDialog::columnPurposeChanged(int p) 00279 { 00280 QObject *o = sender(); 00281 00282 QComboBox *cb = qobject_cast<QComboBox *>(o); 00283 if (!cb) return; 00284 00285 CSVFormat::ColumnPurpose purpose = (CSVFormat::ColumnPurpose)p; 00286 00287 bool haveStartTime = false; 00288 bool haveDuration = false; 00289 bool havePitch = false; 00290 int valueCount = 0; 00291 00292 for (int i = 0; i < m_columnPurposeCombos.size(); ++i) { 00293 00294 CSVFormat::ColumnPurpose cp = m_format.getColumnPurpose(i); 00295 00296 bool thisChanged = (cb == m_columnPurposeCombos[i]); 00297 00298 if (thisChanged) { 00299 00300 cerr << "i == " << i << ", fuzzy == " << m_fuzzyColumn 00301 << ", p == " << p << endl; 00302 00303 if (i == m_fuzzyColumn) { 00304 for (int j = i; j < m_format.getColumnCount(); ++j) { 00305 if (p == 0) { // Ignore 00306 m_format.setColumnPurpose(j, CSVFormat::ColumnUnknown); 00307 } else { // Value 00308 m_format.setColumnPurpose(j, CSVFormat::ColumnValue); 00309 ++valueCount; 00310 } 00311 } 00312 continue; 00313 } 00314 00315 cp = purpose; 00316 00317 } else { 00318 00319 if (i == m_fuzzyColumn) continue; 00320 00321 // We can only have one ColumnStartTime column, and only 00322 // one of either ColumnDuration or ColumnEndTime 00323 00324 if (purpose == CSVFormat::ColumnStartTime) { 00325 if (cp == purpose) { 00326 cp = CSVFormat::ColumnValue; 00327 } 00328 } else if (purpose == CSVFormat::ColumnDuration || 00329 purpose == CSVFormat::ColumnEndTime) { 00330 if (cp == CSVFormat::ColumnDuration || 00331 cp == CSVFormat::ColumnEndTime) { 00332 cp = CSVFormat::ColumnValue; 00333 } 00334 } 00335 00336 // And we can only have one label 00337 if (purpose == CSVFormat::ColumnLabel) { 00338 if (cp == purpose) { 00339 cp = CSVFormat::ColumnUnknown; 00340 } 00341 } 00342 } 00343 00344 if (cp == CSVFormat::ColumnStartTime) { 00345 haveStartTime = true; 00346 } 00347 if (cp == CSVFormat::ColumnEndTime || 00348 cp == CSVFormat::ColumnDuration) { 00349 haveDuration = true; 00350 } 00351 if (cp == CSVFormat::ColumnPitch) { 00352 havePitch = true; 00353 } 00354 if (cp == CSVFormat::ColumnValue) { 00355 ++valueCount; 00356 } 00357 00358 m_columnPurposeCombos[i]->setCurrentIndex(int(cp)); 00359 m_format.setColumnPurpose(i, cp); 00360 } 00361 00362 if (!haveStartTime) { 00363 m_timingTypeCombo->setCurrentIndex(2); 00364 timingTypeChanged(2); 00365 } 00366 00367 if (haveStartTime && haveDuration) { 00368 if (havePitch) { 00369 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDurationAndPitch); 00370 } else { 00371 m_format.setModelType(CSVFormat::TwoDimensionalModelWithDuration); 00372 } 00373 } else { 00374 if (valueCount > 1) { 00375 m_format.setModelType(CSVFormat::ThreeDimensionalModel); 00376 } else if (valueCount > 0) { 00377 m_format.setModelType(CSVFormat::TwoDimensionalModel); 00378 } else { 00379 m_format.setModelType(CSVFormat::OneDimensionalModel); 00380 } 00381 } 00382 00383 updateModelLabel(); 00384 } 00385 00386