Support for control characters as quote and separator in CSV import

New options and spin boxes are added for entering any non-printable
character in the Import CSV dialog.

This adds support for Concordance DAT files and similar cases. See issue
#2012
This commit is contained in:
mgrojo
2020-01-06 00:50:33 +01:00
parent d0e0ee3f64
commit 9b670b4b94
5 changed files with 98 additions and 11 deletions

View File

@@ -32,6 +32,7 @@ static const QString FILE_FILTER_CSV(QObject::tr("Comma-Separated Values Files (
static const QString FILE_EXT_CSV_DEFAULT(".csv");
static const QString FILE_FILTER_TSV(QObject::tr("Tab-Separated Values Files (*.tsv)"));
static const QString FILE_FILTER_DSV(QObject::tr("Delimiter-Separated Values Files (*.dsv)"));
static const QString FILE_FILTER_DAT(QObject::tr("Concordance DAT files (*.dat)"));
// JSON File Extensions Filter
static const QString FILE_FILTER_JSON(QObject::tr("JSON Files (*.json *.js)"));

View File

@@ -217,8 +217,11 @@ void ImportCsvDialog::accept()
void ImportCsvDialog::updatePreview()
{
// Show/hide custom quote/separator input fields
ui->editCustomQuote->setVisible(ui->comboQuote->currentIndex() == ui->comboQuote->count()-1);
ui->editCustomSeparator->setVisible(ui->comboSeparator->currentIndex() == ui->comboSeparator->count()-1);
ui->editCustomQuote->setVisible(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherPrintable);
ui->editCustomSeparator->setVisible(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherPrintable);
ui->spinBoxQuote->setVisible(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherCode);
ui->spinBoxSeparator->setVisible(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherCode);
ui->editCustomEncoding->setVisible(ui->comboEncoding->currentIndex() == ui->comboEncoding->count()-1);
// Reset preview widget
@@ -702,10 +705,18 @@ void ImportCsvDialog::setQuoteChar(QChar c)
{
QComboBox* combo = ui->comboQuote;
int index = combo->findText(QString(c));
ui->spinBoxQuote->setValue(c.unicode());
if(index == -1)
{
combo->setCurrentIndex(combo->count() - 1);
ui->editCustomQuote->setText(QString(c));
if(c.isPrint())
{
combo->setCurrentIndex(combo->count() - OtherPrintable);
ui->editCustomQuote->setText(QString(c));
}
else
{
combo->setCurrentIndex(combo->count() - OtherCode);
}
}
else
{
@@ -718,8 +729,10 @@ QChar ImportCsvDialog::currentQuoteChar() const
QString value;
// The last item in the combobox is the 'Other' item; if it is selected return the text of the line edit field instead
if(ui->comboQuote->currentIndex() == ui->comboQuote->count()-1)
if(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherPrintable)
value = ui->editCustomQuote->text().length() ? ui->editCustomQuote->text() : "";
else if(ui->comboQuote->currentIndex() == ui->comboQuote->count() - OtherCode)
value = QString(QChar(ui->spinBoxQuote->value()));
else if(ui->comboQuote->currentText().length())
value = ui->comboQuote->currentText();
@@ -731,10 +744,18 @@ void ImportCsvDialog::setSeparatorChar(QChar c)
QComboBox* combo = ui->comboSeparator;
QString sText = c == '\t' ? QString("Tab") : QString(c);
int index = combo->findText(sText);
ui->spinBoxSeparator->setValue(c.unicode());
if(index == -1)
{
combo->setCurrentIndex(combo->count() - 1);
ui->editCustomSeparator->setText(QString(c));
if(c.isPrint())
{
combo->setCurrentIndex(combo->count() - OtherPrintable);
ui->editCustomSeparator->setText(QString(c));
}
else
{
combo->setCurrentIndex(combo->count() - OtherCode);
}
}
else
{
@@ -746,9 +767,12 @@ QChar ImportCsvDialog::currentSeparatorChar() const
{
QString value;
// The last item in the combobox is the 'Other' item; if it is selected return the text of the line edit field instead
if(ui->comboSeparator->currentIndex() == ui->comboSeparator->count()-1 || ui->comboSeparator->currentText().isEmpty())
// The last options in the combobox are the 'Other (*)' items;
// if one of them is selected return the text or code of the corresponding field instead
if(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherPrintable)
value = ui->editCustomSeparator->text().length() ? ui->editCustomSeparator->text() : "";
else if(ui->comboSeparator->currentIndex() == ui->comboSeparator->count() - OtherCode)
value = QString(QChar(ui->spinBoxSeparator->value()));
else
value = ui->comboSeparator->currentText() == tr("Tab") ? "\t" : ui->comboSeparator->currentText();

View File

@@ -33,6 +33,11 @@ private slots:
void toggleAdvancedSection(bool show);
private:
// Positions for combos starting at the bottom
enum {OtherCode = 1,
OtherPrintable = 2};
Ui::ImportCsvDialog* ui;
std::vector<QString> csvFilenames;
QString selectedFile;

View File

@@ -85,7 +85,12 @@
</item>
<item>
<property name="text">
<string>Other</string>
<string>Other (printable)</string>
</property>
</item>
<item>
<property name="text">
<string>Other (code)</string>
</property>
</item>
</widget>
@@ -97,6 +102,13 @@
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxSeparator">
<property name="maximum">
<number>1114112</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
@@ -143,7 +155,12 @@
</item>
<item>
<property name="text">
<string>Other</string>
<string>Other (printable)</string>
</property>
</item>
<item>
<property name="text">
<string>Other (code)</string>
</property>
</item>
</widget>
@@ -155,6 +172,13 @@
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="spinBoxQuote">
<property name="maximum">
<number>1114112</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
@@ -719,6 +743,38 @@
</hint>
</hints>
</connection>
<connection>
<sender>spinBoxQuote</sender>
<signal>valueChanged(int)</signal>
<receiver>ImportCsvDialog</receiver>
<slot>updatePreview()</slot>
<hints>
<hint type="sourcelabel">
<x>529</x>
<y>111</y>
</hint>
<hint type="destinationlabel">
<x>393</x>
<y>358</y>
</hint>
</hints>
</connection>
<connection>
<sender>spinBoxSeparator</sender>
<signal>valueChanged(int)</signal>
<receiver>ImportCsvDialog</receiver>
<slot>updatePreview()</slot>
<hints>
<hint type="sourcelabel">
<x>529</x>
<y>77</y>
</hint>
<hint type="destinationlabel">
<x>393</x>
<y>358</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>updatePreview()</slot>

View File

@@ -1241,6 +1241,7 @@ void MainWindow::importTableFromCSV()
<< FILE_FILTER_TSV
<< FILE_FILTER_DSV
<< FILE_FILTER_TXT
<< FILE_FILTER_DAT
<< FILE_FILTER_ALL;
QStringList wFiles = FileDialog::getOpenFileNames(