2017-01-09 00:33:21 +00:00
|
|
|
|
/*
|
|
|
|
|
|
* Copyright (C) 2016 Enrico Mariotti <enricomariotti@yahoo.it>
|
2017-06-09 21:40:36 +00:00
|
|
|
|
* Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
|
2017-01-09 00:33:21 +00:00
|
|
|
|
*
|
|
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
|
* the Free Software Foundation, either version 2 or (at your option)
|
|
|
|
|
|
* version 3 of the License.
|
|
|
|
|
|
*
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
*
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "CsvImportWidget.h"
|
|
|
|
|
|
#include "ui_CsvImportWidget.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <QFile>
|
|
|
|
|
|
#include <QFileInfo>
|
2017-03-05 23:47:49 +00:00
|
|
|
|
#include <QSpacerItem>
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2017-06-15 14:26:37 +00:00
|
|
|
|
#include "format/KeePass2Writer.h"
|
2017-02-18 00:51:31 +00:00
|
|
|
|
#include "gui/MessageBox.h"
|
|
|
|
|
|
#include "gui/MessageWidget.h"
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// I wanted to make the CSV import GUI future-proof, so if one day you need entries
|
|
|
|
|
|
// to have a new field, 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!
|
|
|
|
|
|
const QStringList CsvImportWidget::m_columnHeader =
|
|
|
|
|
|
QStringList() << QObject::tr("Group") << QObject::tr("Title") << QObject::tr("Username") << QObject::tr("Password")
|
|
|
|
|
|
<< QObject::tr("URL") << QObject::tr("Notes") << QObject::tr("Last Modified")
|
|
|
|
|
|
<< QObject::tr("Created")
|
|
|
|
|
|
// << QObject::tr("Future field1")
|
|
|
|
|
|
// << QObject::tr("Future field2")
|
|
|
|
|
|
// << QObject::tr("Future field3")
|
2017-01-09 00:33:21 +00:00
|
|
|
|
;
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
CsvImportWidget::CsvImportWidget(QWidget* parent)
|
2017-01-09 00:33:21 +00:00
|
|
|
|
: QWidget(parent)
|
|
|
|
|
|
, m_ui(new Ui::CsvImportWidget())
|
|
|
|
|
|
, m_parserModel(new CsvParserModel(this))
|
|
|
|
|
|
, m_comboModel(new QStringListModel(this))
|
|
|
|
|
|
, m_comboMapper(new QSignalMapper(this))
|
|
|
|
|
|
{
|
|
|
|
|
|
m_ui->setupUi(this);
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
m_ui->comboBoxCodec->addItems(QStringList() << "UTF-8"
|
|
|
|
|
|
<< "Windows-1252"
|
|
|
|
|
|
<< "UTF-16"
|
|
|
|
|
|
<< "UTF-16LE");
|
|
|
|
|
|
m_ui->comboBoxFieldSeparator->addItems(QStringList() << ","
|
|
|
|
|
|
<< ";"
|
|
|
|
|
|
<< "-"
|
|
|
|
|
|
<< ":"
|
|
|
|
|
|
<< ".");
|
|
|
|
|
|
m_ui->comboBoxTextQualifier->addItems(QStringList() << "\""
|
|
|
|
|
|
<< "'"
|
|
|
|
|
|
<< ":"
|
|
|
|
|
|
<< "."
|
|
|
|
|
|
<< "|");
|
|
|
|
|
|
m_ui->comboBoxComment->addItems(QStringList() << "#"
|
|
|
|
|
|
<< ";"
|
|
|
|
|
|
<< ":"
|
|
|
|
|
|
<< "@");
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_ui->tableViewFields->setSelectionMode(QAbstractItemView::NoSelection);
|
|
|
|
|
|
m_ui->tableViewFields->setFocusPolicy(Qt::NoFocus);
|
2017-03-05 23:47:49 +00:00
|
|
|
|
m_ui->messageWidget->setHidden(true);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2017-02-18 00:51:31 +00:00
|
|
|
|
for (int i = 0; i < m_columnHeader.count(); ++i) {
|
|
|
|
|
|
QLabel* label = new QLabel(m_columnHeader.at(i), this);
|
2017-03-05 23:47:49 +00:00
|
|
|
|
label->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
2017-02-18 00:51:31 +00:00
|
|
|
|
QFont font = label->font();
|
2017-01-09 00:33:21 +00:00
|
|
|
|
font.setBold(false);
|
|
|
|
|
|
label->setFont(font);
|
|
|
|
|
|
|
|
|
|
|
|
QComboBox* combo = new QComboBox(this);
|
|
|
|
|
|
font = combo->font();
|
|
|
|
|
|
font.setBold(false);
|
|
|
|
|
|
combo->setFont(font);
|
|
|
|
|
|
m_combos.append(combo);
|
|
|
|
|
|
combo->setModel(m_comboModel);
|
|
|
|
|
|
m_comboMapper->setMapping(combo, i);
|
|
|
|
|
|
connect(combo, SIGNAL(currentIndexChanged(int)), m_comboMapper, SLOT(map()));
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// layout labels and combo fields in column-first order
|
2017-02-22 00:03:22 +00:00
|
|
|
|
int combo_rows = 1 + (m_columnHeader.count() - 1) / 2;
|
|
|
|
|
|
int x = i % combo_rows;
|
|
|
|
|
|
int y = 2 * (i / combo_rows);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_ui->gridLayout_combos->addWidget(label, x, y);
|
2018-03-31 20:01:30 +00:00
|
|
|
|
m_ui->gridLayout_combos->addWidget(combo, x, y + 1);
|
|
|
|
|
|
QSpacerItem* item = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
|
|
|
|
m_ui->gridLayout_combos->addItem(item, x, y + 2);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-18 00:51:31 +00:00
|
|
|
|
m_parserModel->setHeaderLabels(m_columnHeader);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_ui->tableViewFields->setModel(m_parserModel);
|
|
|
|
|
|
|
|
|
|
|
|
connect(m_ui->spinBoxSkip, SIGNAL(valueChanged(int)), SLOT(skippedChanged(int)));
|
|
|
|
|
|
connect(m_ui->comboBoxCodec, SIGNAL(currentIndexChanged(int)), SLOT(parse()));
|
|
|
|
|
|
connect(m_ui->comboBoxTextQualifier, SIGNAL(currentIndexChanged(int)), SLOT(parse()));
|
|
|
|
|
|
connect(m_ui->comboBoxComment, SIGNAL(currentIndexChanged(int)), SLOT(parse()));
|
|
|
|
|
|
connect(m_ui->comboBoxFieldSeparator, SIGNAL(currentIndexChanged(int)), SLOT(parse()));
|
|
|
|
|
|
connect(m_ui->checkBoxBackslash, SIGNAL(toggled(bool)), SLOT(parse()));
|
2017-04-10 15:39:54 +00:00
|
|
|
|
connect(m_ui->checkBoxFieldNames, SIGNAL(toggled(bool)), SLOT(updatePreview()));
|
2017-01-09 00:33:21 +00:00
|
|
|
|
connect(m_comboMapper, SIGNAL(mapped(int)), this, SLOT(comboChanged(int)));
|
|
|
|
|
|
|
|
|
|
|
|
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(writeDatabase()));
|
|
|
|
|
|
connect(m_ui->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::comboChanged(int comboId)
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
QComboBox* currentSender = qobject_cast<QComboBox*>(m_comboMapper->mapping(comboId));
|
2017-02-18 00:51:31 +00:00
|
|
|
|
if (currentSender->currentIndex() != -1)
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// this line is the one that actually updates GUI table
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_parserModel->mapColumns(currentSender->currentIndex(), comboId);
|
|
|
|
|
|
updateTableview();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::skippedChanged(int rows)
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_parserModel->setSkippedRows(rows);
|
|
|
|
|
|
updateTableview();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
CsvImportWidget::~CsvImportWidget()
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::configParser()
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_parserModel->setBackslashSyntax(m_ui->checkBoxBackslash->isChecked());
|
|
|
|
|
|
m_parserModel->setComment(m_ui->comboBoxComment->currentText().at(0));
|
|
|
|
|
|
m_parserModel->setTextQualifier(m_ui->comboBoxTextQualifier->currentText().at(0));
|
|
|
|
|
|
m_parserModel->setCodec(m_ui->comboBoxCodec->currentText());
|
|
|
|
|
|
m_parserModel->setFieldSeparator(m_ui->comboBoxFieldSeparator->currentText().at(0));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::updateTableview()
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_ui->tableViewFields->resizeRowsToContents();
|
|
|
|
|
|
m_ui->tableViewFields->resizeColumnsToContents();
|
|
|
|
|
|
|
2017-02-22 00:03:22 +00:00
|
|
|
|
for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c)
|
|
|
|
|
|
m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::updatePreview()
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2017-04-10 15:39:54 +00:00
|
|
|
|
int minSkip = 0;
|
|
|
|
|
|
if (m_ui->checkBoxFieldNames->isChecked())
|
|
|
|
|
|
minSkip = 1;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo());
|
2017-04-10 15:39:54 +00:00
|
|
|
|
m_ui->spinBoxSkip->setRange(minSkip, qMax(minSkip, m_parserModel->rowCount() - 1));
|
|
|
|
|
|
m_ui->spinBoxSkip->setValue(minSkip);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2017-04-27 20:11:26 +00:00
|
|
|
|
int emptyId = 0;
|
2017-04-10 15:39:54 +00:00
|
|
|
|
QString columnName;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
QStringList list(tr("Not present in CSV file"));
|
|
|
|
|
|
|
2017-04-27 20:11:26 +00:00
|
|
|
|
for (int i = 1; i < m_parserModel->getCsvCols(); ++i) {
|
2017-04-10 15:39:54 +00:00
|
|
|
|
if (m_ui->checkBoxFieldNames->isChecked()) {
|
|
|
|
|
|
columnName = m_parserModel->getCsvTable().at(0).at(i);
|
|
|
|
|
|
if (columnName.isEmpty())
|
2018-03-13 19:59:08 +00:00
|
|
|
|
columnName = "<" + tr("Empty fieldname %1").arg(++emptyId) + ">";
|
2017-04-10 15:39:54 +00:00
|
|
|
|
list << columnName;
|
|
|
|
|
|
} else {
|
2018-03-13 19:59:08 +00:00
|
|
|
|
list << QString(tr("column %1").arg(i));
|
2017-04-10 15:39:54 +00:00
|
|
|
|
}
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
m_comboModel->setStringList(list);
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
int j = 1;
|
2017-03-08 21:58:46 +00:00
|
|
|
|
for (QComboBox* b : m_combos) {
|
2017-04-27 20:11:26 +00:00
|
|
|
|
if (j < m_parserModel->getCsvCols())
|
|
|
|
|
|
b->setCurrentIndex(j);
|
2017-02-18 00:51:31 +00:00
|
|
|
|
else
|
2017-01-09 00:33:21 +00:00
|
|
|
|
b->setCurrentIndex(0);
|
2017-04-27 20:11:26 +00:00
|
|
|
|
++j;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::load(const QString& filename, Database* const db)
|
|
|
|
|
|
{
|
|
|
|
|
|
// QApplication::processEvents();
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_db = db;
|
|
|
|
|
|
m_parserModel->setFilename(filename);
|
|
|
|
|
|
m_ui->labelFilename->setText(filename);
|
|
|
|
|
|
Group* group = m_db->rootGroup();
|
|
|
|
|
|
group->setUuid(Uuid::random());
|
2018-03-13 19:59:08 +00:00
|
|
|
|
group->setNotes(tr("Imported from CSV file\nOriginal data: %1").arg(filename));
|
2017-01-09 00:33:21 +00:00
|
|
|
|
parse();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::parse()
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
configParser();
|
|
|
|
|
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// QApplication::processEvents();
|
2017-01-09 00:33:21 +00:00
|
|
|
|
bool good = m_parserModel->parse();
|
|
|
|
|
|
updatePreview();
|
2017-02-22 00:03:22 +00:00
|
|
|
|
QApplication::restoreOverrideCursor();
|
2017-03-05 23:47:49 +00:00
|
|
|
|
if (!good)
|
2018-03-31 20:01:30 +00:00
|
|
|
|
m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file!").append("\n").append(formatStatusText()),
|
|
|
|
|
|
MessageWidget::Warning);
|
2017-03-05 23:47:49 +00:00
|
|
|
|
else
|
|
|
|
|
|
m_ui->messageWidget->setHidden(true);
|
2017-02-22 00:03:22 +00:00
|
|
|
|
QWidget::adjustSize();
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
QString CsvImportWidget::formatStatusText() const
|
|
|
|
|
|
{
|
2017-02-22 00:03:22 +00:00
|
|
|
|
QString text = m_parserModel->getStatus();
|
|
|
|
|
|
int items = text.count('\n');
|
2017-03-08 21:58:46 +00:00
|
|
|
|
if (items > 2) {
|
2018-03-31 20:01:30 +00:00
|
|
|
|
return text.section('\n', 0, 1).append("\n").append(tr("[%n more message(s) skipped]", "", items - 2));
|
2017-03-08 21:58:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
if (items == 1) {
|
|
|
|
|
|
text.append(QString("\n"));
|
|
|
|
|
|
}
|
|
|
|
|
|
return text;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::writeDatabase()
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2017-02-18 00:51:31 +00:00
|
|
|
|
setRootGroup();
|
2017-03-08 21:58:46 +00:00
|
|
|
|
for (int r = 0; r < m_parserModel->rowCount(); ++r) {
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// use validity of second column as a GO/NOGO for all others fields
|
2017-02-22 00:03:22 +00:00
|
|
|
|
if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid())
|
|
|
|
|
|
continue;
|
|
|
|
|
|
Entry* entry = new Entry();
|
|
|
|
|
|
entry->setUuid(Uuid::random());
|
|
|
|
|
|
entry->setGroup(splitGroups(m_parserModel->data(m_parserModel->index(r, 0)).toString()));
|
|
|
|
|
|
entry->setTitle(m_parserModel->data(m_parserModel->index(r, 1)).toString());
|
|
|
|
|
|
entry->setUsername(m_parserModel->data(m_parserModel->index(r, 2)).toString());
|
|
|
|
|
|
entry->setPassword(m_parserModel->data(m_parserModel->index(r, 3)).toString());
|
|
|
|
|
|
entry->setUrl(m_parserModel->data(m_parserModel->index(r, 4)).toString());
|
|
|
|
|
|
entry->setNotes(m_parserModel->data(m_parserModel->index(r, 5)).toString());
|
2018-01-07 00:28:04 +00:00
|
|
|
|
|
|
|
|
|
|
TimeInfo timeInfo;
|
|
|
|
|
|
if (m_parserModel->data(m_parserModel->index(r, 6)).isValid()) {
|
|
|
|
|
|
qint64 lastModified = m_parserModel->data(m_parserModel->index(r, 6)).toString().toLongLong();
|
|
|
|
|
|
if (lastModified) {
|
2018-03-31 20:01:30 +00:00
|
|
|
|
timeInfo.setLastModificationTime(
|
|
|
|
|
|
QDateTime::fromMSecsSinceEpoch(lastModified * 1000).toTimeSpec(Qt::UTC));
|
2018-01-07 00:28:04 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (m_parserModel->data(m_parserModel->index(r, 7)).isValid()) {
|
|
|
|
|
|
qint64 created = m_parserModel->data(m_parserModel->index(r, 7)).toString().toLongLong();
|
|
|
|
|
|
if (created) {
|
|
|
|
|
|
timeInfo.setCreationTime(QDateTime::fromMSecsSinceEpoch(created * 1000).toTimeSpec(Qt::UTC));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
entry->setTimeInfo(timeInfo);
|
2017-02-22 00:03:22 +00:00
|
|
|
|
}
|
2017-01-09 00:33:21 +00:00
|
|
|
|
QBuffer buffer;
|
|
|
|
|
|
buffer.open(QBuffer::ReadWrite);
|
|
|
|
|
|
|
|
|
|
|
|
KeePass2Writer writer;
|
|
|
|
|
|
writer.writeDatabase(&buffer, m_db);
|
2017-02-18 00:51:31 +00:00
|
|
|
|
if (writer.hasError())
|
2018-03-31 20:01:30 +00:00
|
|
|
|
MessageBox::warning(this,
|
|
|
|
|
|
tr("Error"),
|
|
|
|
|
|
tr("CSV import: writer has errors:\n%1").arg(writer.errorString()),
|
|
|
|
|
|
QMessageBox::Ok,
|
|
|
|
|
|
QMessageBox::Ok);
|
2017-02-22 00:03:22 +00:00
|
|
|
|
emit editFinished(true);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::setRootGroup()
|
|
|
|
|
|
{
|
2017-01-09 00:33:21 +00:00
|
|
|
|
QString groupLabel;
|
|
|
|
|
|
QStringList groupList;
|
2018-03-31 20:01:30 +00:00
|
|
|
|
bool is_root = false;
|
2017-02-18 00:51:31 +00:00
|
|
|
|
bool is_empty = false;
|
|
|
|
|
|
bool is_label = false;
|
|
|
|
|
|
|
2017-03-08 21:58:46 +00:00
|
|
|
|
for (int r = 0; r < m_parserModel->rowCount(); ++r) {
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// use validity of second column as a GO/NOGO for all others fields
|
2017-02-22 00:03:22 +00:00
|
|
|
|
if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid())
|
|
|
|
|
|
continue;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
groupLabel = m_parserModel->data(m_parserModel->index(r, 0)).toString();
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// check if group name is either "root", "" (empty) or some other label
|
2017-01-09 00:33:21 +00:00
|
|
|
|
groupList = groupLabel.split("/", QString::SkipEmptyParts);
|
2017-02-22 00:03:22 +00:00
|
|
|
|
if (groupList.isEmpty())
|
2017-01-09 00:33:21 +00:00
|
|
|
|
is_empty = true;
|
2018-03-31 20:01:30 +00:00
|
|
|
|
else if (not groupList.first().compare("Root", Qt::CaseSensitive))
|
|
|
|
|
|
is_root = true;
|
|
|
|
|
|
else if (not groupLabel.compare(""))
|
|
|
|
|
|
is_empty = true;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
else
|
2018-03-31 20:01:30 +00:00
|
|
|
|
is_label = true;
|
2017-02-22 00:03:22 +00:00
|
|
|
|
|
2017-01-09 00:33:21 +00:00
|
|
|
|
groupList.clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2017-02-22 00:03:22 +00:00
|
|
|
|
if ((is_empty and is_root) or (is_label and not is_empty and is_root))
|
2017-01-09 00:33:21 +00:00
|
|
|
|
m_db->rootGroup()->setName("CSV IMPORTED");
|
2017-02-18 00:51:31 +00:00
|
|
|
|
else
|
2017-02-22 00:03:22 +00:00
|
|
|
|
m_db->rootGroup()->setName("Root");
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
Group* CsvImportWidget::splitGroups(QString label)
|
|
|
|
|
|
{
|
|
|
|
|
|
// extract group names from nested path provided in "label"
|
|
|
|
|
|
Group* current = m_db->rootGroup();
|
2017-02-22 00:03:22 +00:00
|
|
|
|
if (label.isEmpty())
|
|
|
|
|
|
return current;
|
2017-01-09 00:33:21 +00:00
|
|
|
|
|
2017-02-22 00:03:22 +00:00
|
|
|
|
QStringList groupList = label.split("/", QString::SkipEmptyParts);
|
2018-03-31 20:01:30 +00:00
|
|
|
|
// avoid the creation of a subgroup with the same name as Root
|
2017-02-18 00:51:31 +00:00
|
|
|
|
if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root")
|
2017-01-09 00:33:21 +00:00
|
|
|
|
groupList.removeFirst();
|
|
|
|
|
|
|
|
|
|
|
|
for (const QString& groupName : groupList) {
|
2018-03-31 20:01:30 +00:00
|
|
|
|
Group* children = hasChildren(current, groupName);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
if (children == nullptr) {
|
2018-03-31 20:01:30 +00:00
|
|
|
|
Group* brandNew = new Group();
|
2017-01-09 00:33:21 +00:00
|
|
|
|
brandNew->setParent(current);
|
|
|
|
|
|
brandNew->setName(groupName);
|
2017-03-06 22:05:06 +00:00
|
|
|
|
brandNew->setUuid(Uuid::random());
|
2017-01-09 00:33:21 +00:00
|
|
|
|
current = brandNew;
|
2017-02-18 00:51:31 +00:00
|
|
|
|
} else {
|
2017-01-09 00:33:21 +00:00
|
|
|
|
Q_ASSERT(children != nullptr);
|
|
|
|
|
|
current = children;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return current;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
Group* CsvImportWidget::hasChildren(Group* current, QString groupName)
|
|
|
|
|
|
{
|
|
|
|
|
|
// returns the group whose name is "groupName" and is child of "current" group
|
|
|
|
|
|
for (Group* group : current->children()) {
|
2017-02-18 00:51:31 +00:00
|
|
|
|
if (group->name() == groupName)
|
2017-01-09 00:33:21 +00:00
|
|
|
|
return group;
|
|
|
|
|
|
}
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2018-03-31 20:01:30 +00:00
|
|
|
|
void CsvImportWidget::reject()
|
|
|
|
|
|
{
|
2017-02-22 00:03:22 +00:00
|
|
|
|
emit editFinished(false);
|
2017-01-09 00:33:21 +00:00
|
|
|
|
}
|