Add tab delimiter in CSV import. (#1842)

* Add tab delimiter in CSV import. Closes #1798
* Corrected several code style issues
This commit is contained in:
Tarquin Winot 2018-07-09 02:31:12 +02:00 committed by Jonathan White
parent d06819eb6c
commit 0142e070cc
2 changed files with 36 additions and 19 deletions

View File

@ -27,8 +27,8 @@
#include "gui/MessageBox.h" #include "gui/MessageBox.h"
#include "gui/MessageWidget.h" #include "gui/MessageWidget.h"
// I wanted to make the CSV import GUI future-proof, so if one day you need entries // I wanted to make the CSV import GUI future-proof, so if one day you need a new field,
// to have a new field, all you have to do is uncomment a row or two here, and the GUI will follow: // all you have to do is uncomment a row or two here, and the GUI will follow:
// dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun! // dynamic generation of comboBoxes, labels, placement and so on. Try it for immense fun!
const QStringList CsvImportWidget::m_columnHeader = const QStringList CsvImportWidget::m_columnHeader =
QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password") QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password")
@ -56,7 +56,14 @@ CsvImportWidget::CsvImportWidget(QWidget* parent)
<< ";" << ";"
<< "-" << "-"
<< ":" << ":"
<< "."); << "."
<< "TAB (\\t)");
m_fieldSeparatorList = QStringList() << ","
<< ";"
<< "-"
<< ":"
<< "."
<< "\t";
m_ui->comboBoxTextQualifier->addItems(QStringList() << "\"" m_ui->comboBoxTextQualifier->addItems(QStringList() << "\""
<< "'" << "'"
<< ":" << ":"
@ -115,9 +122,10 @@ CsvImportWidget::CsvImportWidget(QWidget* parent)
void CsvImportWidget::comboChanged(int comboId) void CsvImportWidget::comboChanged(int comboId)
{ {
QComboBox* currentSender = qobject_cast<QComboBox*>(m_comboMapper->mapping(comboId)); QComboBox* currentSender = qobject_cast<QComboBox*>(m_comboMapper->mapping(comboId));
if (currentSender->currentIndex() != -1) if (currentSender->currentIndex() != -1) {
// this line is the one that actually updates GUI table // this line is the one that actually updates GUI table
m_parserModel->mapColumns(currentSender->currentIndex(), comboId); m_parserModel->mapColumns(currentSender->currentIndex(), comboId);
}
updateTableview(); updateTableview();
} }
@ -137,7 +145,7 @@ void CsvImportWidget::configParser()
m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0)); m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0));
m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0)); m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0));
m_parserModel->setCodec(m_ui->comboBoxCodec->currentText()); m_parserModel->setCodec(m_ui->comboBoxCodec->currentText());
m_parserModel->setFieldSeparator(m_ui->comboBoxFieldSeparator->currentText().at(0)); m_parserModel->setFieldSeparator(m_fieldSeparatorList.at(m_ui->comboBoxFieldSeparator->currentIndex()).at(0));
} }
void CsvImportWidget::updateTableview() void CsvImportWidget::updateTableview()
@ -145,16 +153,17 @@ void CsvImportWidget::updateTableview()
m_ui->tableViewFields->resizeRowsToContents(); m_ui->tableViewFields->resizeRowsToContents();
m_ui->tableViewFields->resizeColumnsToContents(); m_ui->tableViewFields->resizeColumnsToContents();
for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) {
m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch); m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch);
}
} }
void CsvImportWidget::updatePreview() void CsvImportWidget::updatePreview()
{ {
int minSkip = 0; int minSkip = 0;
if (m_ui->checkBoxFieldNames->isChecked()) if (m_ui->checkBoxFieldNames->isChecked()) {
minSkip = 1; minSkip = 1;
}
m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo()); m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo());
m_ui->spinBoxSkip->setRange(minSkip, qMax(minSkip, m_parserModel->rowCount() - 1)); m_ui->spinBoxSkip->setRange(minSkip, qMax(minSkip, m_parserModel->rowCount() - 1));
m_ui->spinBoxSkip->setValue(minSkip); m_ui->spinBoxSkip->setValue(minSkip);
@ -166,8 +175,9 @@ void CsvImportWidget::updatePreview()
for (int i = 1; i < m_parserModel->getCsvCols(); ++i) { for (int i = 1; i < m_parserModel->getCsvCols(); ++i) {
if (m_ui->checkBoxFieldNames->isChecked()) { if (m_ui->checkBoxFieldNames->isChecked()) {
columnName = m_parserModel->getCsvTable().at(0).at(i); columnName = m_parserModel->getCsvTable().at(0).at(i);
if (columnName.isEmpty()) if (columnName.isEmpty()) {
columnName = "<" + tr("Empty fieldname %1").arg(++emptyId) + ">"; columnName = "<" + tr("Empty fieldname %1").arg(++emptyId) + ">";
}
list << columnName; list << columnName;
} else { } else {
list << QString(tr("column %1").arg(i)); list << QString(tr("column %1").arg(i));
@ -177,10 +187,11 @@ void CsvImportWidget::updatePreview()
int j = 1; int j = 1;
for (QComboBox* b : m_combos) { for (QComboBox* b : m_combos) {
if (j < m_parserModel->getCsvCols()) if (j < m_parserModel->getCsvCols()) {
b->setCurrentIndex(j); b->setCurrentIndex(j);
else } else {
b->setCurrentIndex(0); b->setCurrentIndex(0);
}
++j; ++j;
} }
} }
@ -205,11 +216,12 @@ void CsvImportWidget::parse()
bool good = m_parserModel->parse(); bool good = m_parserModel->parse();
updatePreview(); updatePreview();
QApplication::restoreOverrideCursor(); QApplication::restoreOverrideCursor();
if (!good) if (!good) {
m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n").append(formatStatusText()), m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n").append(formatStatusText()),
MessageWidget::Warning); MessageWidget::Warning);
else } else {
m_ui->messageWidget->setHidden(true); m_ui->messageWidget->setHidden(true);
}
QWidget::adjustSize(); QWidget::adjustSize();
} }
@ -228,12 +240,12 @@ QString CsvImportWidget::formatStatusText() const
void CsvImportWidget::writeDatabase() void CsvImportWidget::writeDatabase()
{ {
setRootGroup(); setRootGroup();
for (int r = 0; r < m_parserModel->rowCount(); ++r) { for (int r = 0; r < m_parserModel->rowCount(); ++r) {
// use validity of second column as a GO/NOGO for all others fields // use validity of second column as a GO/NOGO for all others fields
if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid()) {
continue; continue;
}
Entry* entry = new Entry(); Entry* entry = new Entry();
entry->setUuid(Uuid::random()); entry->setUuid(Uuid::random());
entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString())); entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString()));
@ -264,12 +276,13 @@ void CsvImportWidget::writeDatabase()
KeePass2Writer writer; KeePass2Writer writer;
writer.writeDatabase(&buffer, m_db); writer.writeDatabase(&buffer, m_db);
if (writer.hasError()) if (writer.hasError()) {
MessageBox::warning(this, MessageBox::warning(this,
tr("Error"), tr("Error"),
tr("CSV import: writer has errors:\n%1").arg(writer.errorString()), tr("CSV import: writer has errors:\n%1").arg(writer.errorString()),
QMessageBox::Ok, QMessageBox::Ok,
QMessageBox::Ok); QMessageBox::Ok);
}
emit editFinished(true); emit editFinished(true);
} }
@ -310,13 +323,15 @@ Group* CsvImportWidget::splitGroups(QString label)
{ {
// extract group names from nested path provided in "label" // extract group names from nested path provided in "label"
Group* current = m_db->rootGroup(); Group* current = m_db->rootGroup();
if (label.isEmpty()) if (label.isEmpty()) {
return current; return current;
}
QStringList groupList = label.split("/", QString::SkipEmptyParts); QStringList groupList = label.split("/", QString::SkipEmptyParts);
// avoid the creation of a subgroup with the same name as Root // avoid the creation of a subgroup with the same name as Root
if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root") {
groupList.removeFirst(); groupList.removeFirst();
}
for (const QString& groupName : groupList) { for (const QString& groupName : groupList) {
Group* children = hasChildren(current, groupName); Group* children = hasChildren(current, groupName);
@ -338,8 +353,9 @@ Group* CsvImportWidget::hasChildren(Group* current, QString groupName)
{ {
// returns the group whose name is "groupName" and is child of "current" group // returns the group whose name is "groupName" and is child of "current" group
for (Group* group : current->children()) { for (Group* group : current->children()) {
if (group->name() == groupName) if (group->name() == groupName) {
return group; return group;
}
} }
return nullptr; return nullptr;
} }

View File

@ -67,6 +67,7 @@ private:
Database* m_db; Database* m_db;
static const QStringList m_columnHeader; static const QStringList m_columnHeader;
QStringList m_fieldSeparatorList;
void configParser(); void configParser();
void updateTableview(); void updateTableview();
Group* splitGroups(QString label); Group* splitGroups(QString label);