mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-22 07:29:52 -05:00
Better handle of parser status messages (critical/not critical)
Use of messageWidget for displaying parser status messages setRootGroup assigns the right label to the root db folder test uses portable QTemporaryFile instead of hardcoded file
This commit is contained in:
parent
a7e358c27d
commit
41f9c3d2a1
@ -60,7 +60,7 @@ bool CsvParser::reparse() {
|
||||
bool CsvParser::parse(QFile *device) {
|
||||
clear();
|
||||
if (nullptr == device) {
|
||||
m_statusMsg += QObject::tr("NULL device\n");
|
||||
appendStatusMsg(QObject::tr("NULL device"), true);
|
||||
return false;
|
||||
}
|
||||
if (!readFile(device))
|
||||
@ -74,7 +74,7 @@ bool CsvParser::readFile(QFile *device) {
|
||||
|
||||
device->open(QIODevice::ReadOnly);
|
||||
if (!Tools::readAllFromDevice(device, m_array)) {
|
||||
m_statusMsg += QObject::tr("Error reading from device\n");
|
||||
appendStatusMsg(QObject::tr("error reading from device"), true);
|
||||
m_isFileLoaded = false;
|
||||
}
|
||||
else {
|
||||
@ -82,9 +82,8 @@ bool CsvParser::readFile(QFile *device) {
|
||||
|
||||
m_array.replace("\r\n", "\n");
|
||||
m_array.replace("\r", "\n");
|
||||
if (0 == m_array.size()) {
|
||||
m_statusMsg += QObject::tr("File empty\n");
|
||||
}
|
||||
if (0 == m_array.size())
|
||||
appendStatusMsg(QObject::tr("file empty !\n"));
|
||||
m_isFileLoaded = true;
|
||||
}
|
||||
return m_isFileLoaded;
|
||||
@ -119,7 +118,7 @@ bool CsvParser::parseFile() {
|
||||
parseRecord();
|
||||
while (!m_isEof) {
|
||||
if (!skipEndline())
|
||||
appendStatusMsg(QObject::tr("malformed string"));
|
||||
appendStatusMsg(QObject::tr("malformed string"), true);
|
||||
m_currRow++;
|
||||
m_currCol = 1;
|
||||
parseRecord();
|
||||
@ -180,7 +179,7 @@ void CsvParser::parseQuoted(QString &s) {
|
||||
parseEscaped(s);
|
||||
//getChar(m_ch);
|
||||
if (!isQualifier(m_ch))
|
||||
appendStatusMsg(QObject::tr("missing closing quote"));
|
||||
appendStatusMsg(QObject::tr("missing closing quote"), true);
|
||||
}
|
||||
|
||||
void CsvParser::parseEscaped(QString &s) {
|
||||
@ -269,7 +268,7 @@ void CsvParser::getChar(QChar& c) {
|
||||
|
||||
void CsvParser::ungetChar() {
|
||||
if (!m_ts.seek(m_lastPos))
|
||||
m_statusMsg += QObject::tr("Internal: unget lower bound exceeded");
|
||||
appendStatusMsg(QObject::tr("INTERNAL - unget lower bound exceeded"), true);
|
||||
}
|
||||
|
||||
void CsvParser::peek(QChar& c) {
|
||||
@ -360,9 +359,6 @@ const CsvTable CsvParser::getCsvTable() const {
|
||||
}
|
||||
|
||||
QString CsvParser::getStatus() const {
|
||||
if (m_statusMsg.size() > 100)
|
||||
return m_statusMsg.section('\n', 0, 4)
|
||||
.append("\n[...]\n").append(QObject::tr("More messages, skipped!"));
|
||||
return m_statusMsg;
|
||||
}
|
||||
|
||||
@ -377,11 +373,11 @@ int CsvParser::getCsvRows() const {
|
||||
}
|
||||
|
||||
|
||||
void CsvParser::appendStatusMsg(QString s) {
|
||||
void CsvParser::appendStatusMsg(QString s, bool isCritical) {
|
||||
m_statusMsg += s
|
||||
.append(" @" + QString::number(m_currRow))
|
||||
.append(": (row,col) " + QString::number(m_currRow))
|
||||
.append(",")
|
||||
.append(QString::number(m_currCol))
|
||||
.append("\n");
|
||||
m_isGood = false;
|
||||
m_isGood = not isCritical;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ private:
|
||||
void clear();
|
||||
bool skipEndline();
|
||||
void skipLine();
|
||||
void appendStatusMsg(QString s);
|
||||
void appendStatusMsg(QString s, bool isCritical = false);
|
||||
};
|
||||
|
||||
#endif //CSVPARSER_H
|
||||
|
@ -160,8 +160,9 @@
|
||||
<li>debfx (KeePassX)</li>
|
||||
<li>droidmonkey</li>
|
||||
<li>louib</li>
|
||||
<li>phoerious<li>
|
||||
<li>phoerious</li>
|
||||
<li>thezero</li>
|
||||
<li>seatedscribe</li>
|
||||
</ul></string>
|
||||
</property>
|
||||
</widget>
|
||||
|
@ -48,8 +48,6 @@ CsvImportWidget::CsvImportWidget(QWidget *parent)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
m_ui->messageWidget->setHidden(true);
|
||||
|
||||
m_ui->comboBoxCodec->addItems(QStringList() <<"UTF-8" <<"Windows-1252" <<"UTF-16" <<"UTF-16LE");
|
||||
m_ui->comboBoxFieldSeparator->addItems(QStringList() <<"," <<";" <<"-" <<":" <<".");
|
||||
m_ui->comboBoxTextQualifier->addItems(QStringList() <<"\"" <<"'" <<":" <<"." <<"|");
|
||||
@ -75,9 +73,9 @@ CsvImportWidget::CsvImportWidget(QWidget *parent)
|
||||
connect(combo, SIGNAL(currentIndexChanged(int)), m_comboMapper, SLOT(map()));
|
||||
|
||||
//layout labels and combo fields in column-first order
|
||||
int combo_rows = 1+(m_columnHeader.count()-1)/2;
|
||||
int x = i%combo_rows;
|
||||
int y = 2*(i/combo_rows);
|
||||
int combo_rows = 1 + (m_columnHeader.count() - 1) / 2;
|
||||
int x = i % combo_rows;
|
||||
int y = 2 * (i / combo_rows);
|
||||
m_ui->gridLayout_combos->addWidget(label, x, y);
|
||||
m_ui->gridLayout_combos->addWidget(combo, x, y+1);
|
||||
}
|
||||
@ -91,7 +89,6 @@ CsvImportWidget::CsvImportWidget(QWidget *parent)
|
||||
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()));
|
||||
connect(m_ui->pushButtonWarnings, SIGNAL(clicked()), this, SLOT(showReport()));
|
||||
connect(m_comboMapper, SIGNAL(mapped(int)), this, SLOT(comboChanged(int)));
|
||||
|
||||
connect(m_ui->buttonBox, SIGNAL(accepted()), this, SLOT(writeDatabase()));
|
||||
@ -125,17 +122,15 @@ void CsvImportWidget::updateTableview() {
|
||||
m_ui->tableViewFields->resizeRowsToContents();
|
||||
m_ui->tableViewFields->resizeColumnsToContents();
|
||||
|
||||
for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c) {
|
||||
m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(
|
||||
c, QHeaderView::Stretch);
|
||||
}
|
||||
for (int c = 0; c < m_ui->tableViewFields->horizontalHeader()->count(); ++c)
|
||||
m_ui->tableViewFields->horizontalHeader()->setSectionResizeMode(c, QHeaderView::Stretch);
|
||||
}
|
||||
|
||||
void CsvImportWidget::updatePreview() {
|
||||
|
||||
m_ui->labelSizeRowsCols->setText(m_parserModel->getFileInfo());
|
||||
m_ui->spinBoxSkip->setValue(0);
|
||||
m_ui->spinBoxSkip->setMaximum(m_parserModel->rowCount() - 1);
|
||||
m_ui->spinBoxSkip->setMaximum(qMax(0, m_parserModel->rowCount() - 1));
|
||||
|
||||
int i;
|
||||
QStringList list(tr("Not present in CSV file"));
|
||||
@ -157,48 +152,63 @@ void CsvImportWidget::updatePreview() {
|
||||
}
|
||||
|
||||
void CsvImportWidget::load(const QString& filename, Database* const db) {
|
||||
//QApplication::processEvents();
|
||||
m_db = db;
|
||||
m_parserModel->setFilename(filename);
|
||||
m_ui->labelFilename->setText(filename);
|
||||
Group* group = m_db->rootGroup();
|
||||
group->setUuid(Uuid::random());
|
||||
group->setNotes(tr("Imported from CSV file").append("\n").append(tr("Original data: ")) + filename);
|
||||
|
||||
parse();
|
||||
}
|
||||
|
||||
void CsvImportWidget::parse() {
|
||||
configParser();
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
//QApplication::processEvents();
|
||||
bool good = m_parserModel->parse();
|
||||
QApplication::restoreOverrideCursor();
|
||||
updatePreview();
|
||||
m_ui->pushButtonWarnings->setEnabled(!good);
|
||||
QApplication::restoreOverrideCursor();
|
||||
if (good)
|
||||
//four newline are provided to avoid resizing at every Positive/Warning switch
|
||||
m_ui->messageWidget->showMessage(QString("\n\n").append(tr("CSV syntax seems in good shape !"))
|
||||
.append("\n\n"), MessageWidget::Positive);
|
||||
else
|
||||
m_ui->messageWidget->showMessage(tr("Error(s) detected in CSV file !").append("\n")
|
||||
.append(formatStatusText()), MessageWidget::Warning);
|
||||
QWidget::adjustSize();
|
||||
}
|
||||
|
||||
void CsvImportWidget::showReport() {
|
||||
// MessageBox::warning(this, tr("Syntax error"), tr("While parsing file...\n")
|
||||
// .append(m_parserModel->getStatus()), QMessageBox::Ok, QMessageBox::Ok);
|
||||
m_ui->messageWidget->showMessage(tr("Syntax error while parsing file.").append("\n")
|
||||
.append(m_parserModel->getStatus()), MessageWidget::Warning);
|
||||
|
||||
QString CsvImportWidget::formatStatusText() const {
|
||||
QString text = m_parserModel->getStatus();
|
||||
int items = text.count('\n');
|
||||
if (items > 3)
|
||||
return text.section('\n', 0, 2)
|
||||
.append("\n[").append(QString::number(items - 3))
|
||||
.append(tr(" more messages skipped]"));
|
||||
else
|
||||
for (int i = 0; i < 3 - items; i++)
|
||||
text.append(QString("\n"));
|
||||
return text;
|
||||
}
|
||||
|
||||
void CsvImportWidget::writeDatabase() {
|
||||
|
||||
setRootGroup();
|
||||
for (int r = 0; r < m_parserModel->rowCount(); r++)
|
||||
//use the validity of second column as a GO/NOGO hint for all others fields
|
||||
if (m_parserModel->data(m_parserModel->index(r, 1)).isValid()) {
|
||||
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());
|
||||
}
|
||||
|
||||
for (int r = 0; r < m_parserModel->rowCount(); r++) {
|
||||
//use validity of second column as a GO/NOGO for all others fields
|
||||
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());
|
||||
}
|
||||
QBuffer buffer;
|
||||
buffer.open(QBuffer::ReadWrite);
|
||||
|
||||
@ -207,7 +217,7 @@ void CsvImportWidget::writeDatabase() {
|
||||
if (writer.hasError())
|
||||
MessageBox::warning(this, tr("Error"), tr("CSV import: writer has errors:\n")
|
||||
.append((writer.errorString())), QMessageBox::Ok, QMessageBox::Ok);
|
||||
Q_EMIT editFinished(true);
|
||||
emit editFinished(true);
|
||||
}
|
||||
|
||||
|
||||
@ -219,33 +229,39 @@ void CsvImportWidget::setRootGroup() {
|
||||
bool is_label = false;
|
||||
|
||||
for (int r = 0; r < m_parserModel->rowCount(); r++) {
|
||||
//use validity of second column as a GO/NOGO for all others fields
|
||||
if (not m_parserModel->data(m_parserModel->index(r, 1)).isValid())
|
||||
continue;
|
||||
groupLabel = m_parserModel->data(m_parserModel->index(r, 0)).toString();
|
||||
//check if group name is either "root", "" (empty) or some other label
|
||||
groupList = groupLabel.split("/", QString::SkipEmptyParts);
|
||||
if (not groupList.first().compare("Root", Qt::CaseSensitive))
|
||||
is_root = true;
|
||||
else if (not groupLabel.compare(""))
|
||||
if (groupList.isEmpty())
|
||||
is_empty = true;
|
||||
else
|
||||
is_label = true;
|
||||
if (not groupList.first().compare("Root", Qt::CaseSensitive))
|
||||
is_root = true;
|
||||
else if (not groupLabel.compare(""))
|
||||
is_empty = true;
|
||||
else
|
||||
is_label = true;
|
||||
|
||||
groupList.clear();
|
||||
}
|
||||
|
||||
if ((not is_label and (is_empty xor is_root)) or (is_label and not is_root))
|
||||
m_db->rootGroup()->setName("Root");
|
||||
else if ((is_empty and is_root) or (is_label and not is_empty and is_root))
|
||||
if ((is_empty and is_root) or (is_label and not is_empty and is_root))
|
||||
m_db->rootGroup()->setName("CSV IMPORTED");
|
||||
else
|
||||
//SHOULD NEVER GET HERE
|
||||
m_db->rootGroup()->setName("ROOT_FALLBACK");
|
||||
m_db->rootGroup()->setName("Root");
|
||||
}
|
||||
|
||||
Group *CsvImportWidget::splitGroups(QString label) {
|
||||
//extract group names from nested path provided in "label"
|
||||
Group *current = m_db->rootGroup();
|
||||
QStringList groupList = label.split("/", QString::SkipEmptyParts);
|
||||
if (label.isEmpty())
|
||||
return current;
|
||||
|
||||
//skip the creation of a subgroup of Root with the same name
|
||||
QStringList groupList = label.split("/", QString::SkipEmptyParts);
|
||||
//avoid the creation of a subgroup with the same name as Root
|
||||
if (m_db->rootGroup()->name() == "Root" && groupList.first() == "Root")
|
||||
groupList.removeFirst();
|
||||
|
||||
@ -274,5 +290,5 @@ Group* CsvImportWidget::hasChildren(Group* current, QString groupName) {
|
||||
}
|
||||
|
||||
void CsvImportWidget::reject() {
|
||||
Q_EMIT editFinished(false);
|
||||
emit editFinished(false);
|
||||
}
|
||||
|
@ -50,7 +50,6 @@ Q_SIGNALS:
|
||||
|
||||
private Q_SLOTS:
|
||||
void parse();
|
||||
void showReport();
|
||||
void comboChanged(int comboId);
|
||||
void skippedChanged(int rows);
|
||||
void writeDatabase();
|
||||
@ -73,6 +72,7 @@ private:
|
||||
void updateTableview();
|
||||
Group* splitGroups(QString label);
|
||||
Group* hasChildren(Group* current, QString groupName);
|
||||
QString formatStatusText() const;
|
||||
};
|
||||
|
||||
#endif // KEEPASSX_CSVIMPORTWIDGET_H
|
||||
|
@ -122,22 +122,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QPushButton" name="pushButtonWarnings">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show parser warnings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
@ -162,6 +146,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
@ -239,6 +229,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
@ -290,6 +286,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
@ -309,6 +311,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>50</weight>
|
||||
@ -342,7 +350,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Treat '\' as escape character</string>
|
||||
<string>Consider '\' as escape character</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -33,6 +33,10 @@ CsvImportWizard::CsvImportWizard(QWidget *parent)
|
||||
m_pages->addWidget(key = new ChangeMasterKeyWidget(m_pages));
|
||||
m_pages->addWidget(parse = new CsvImportWidget(m_pages));
|
||||
key->headlineLabel()->setText(tr("Import CSV file"));
|
||||
QFont headLineFont = key->headlineLabel()->font();
|
||||
headLineFont.setBold(true);
|
||||
headLineFont.setPointSize(headLineFont.pointSize() + 2);
|
||||
key->headlineLabel()->setFont(headLineFont);
|
||||
|
||||
connect(key, SIGNAL(editFinished(bool)), this, SLOT(keyFinished(bool)));
|
||||
connect(parse, SIGNAL(editFinished(bool)), this, SLOT(parseFinished(bool)));
|
||||
@ -64,7 +68,6 @@ void CsvImportWizard::keyFinished(bool accepted)
|
||||
if (!result) {
|
||||
MessageBox::critical(this, tr("Error"), tr("Unable to calculate master key"));
|
||||
emit(importFinished(false));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ void CsvParserModel::setFilename(const QString& filename) {
|
||||
QString CsvParserModel::getFileInfo(){
|
||||
QString a(QString::number(getFileSize()).append(tr(" byte, ")));
|
||||
a.append(QString::number(getCsvRows())).append(tr(" rows, "));
|
||||
a.append(QString::number((getCsvCols()-1))).append(tr(" columns"));
|
||||
a.append(QString::number(qMax(0, getCsvCols()-1))).append(tr(" columns"));
|
||||
return a;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include "TestCsvParser.h"
|
||||
|
||||
#include <QTest>
|
||||
|
||||
QTEST_GUILESS_MAIN(TestCsvParser)
|
||||
@ -32,8 +33,8 @@ void TestCsvParser::cleanupTestCase()
|
||||
|
||||
void TestCsvParser::init()
|
||||
{
|
||||
file.setFileName("/tmp/keepassXn94do1x.csv");
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Truncate))
|
||||
file = new QTemporaryFile();
|
||||
if (not file->open())
|
||||
QFAIL("Cannot open file!");
|
||||
parser->setBackslashSyntax(false);
|
||||
parser->setComment('#');
|
||||
@ -43,26 +44,26 @@ void TestCsvParser::init()
|
||||
|
||||
void TestCsvParser::cleanup()
|
||||
{
|
||||
file.close();
|
||||
file->remove();
|
||||
}
|
||||
|
||||
/****************** TEST CASES ******************/
|
||||
void TestCsvParser::testMissingQuote() {
|
||||
parser->setTextQualifier(':');
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "A,B\n:BM,1";
|
||||
QEXPECT_FAIL("", "Bad format", Continue);
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QWARN(parser->getStatus().toLatin1());
|
||||
}
|
||||
|
||||
void TestCsvParser::testMalformed() {
|
||||
parser->setTextQualifier(':');
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "A,B,C\n:BM::,1,:2:";
|
||||
QEXPECT_FAIL("", "Bad format", Continue);
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QWARN(parser->getStatus().toLatin1());
|
||||
}
|
||||
@ -70,14 +71,14 @@ void TestCsvParser::testMalformed() {
|
||||
void TestCsvParser::testBackslashSyntax() {
|
||||
parser->setBackslashSyntax(true);
|
||||
parser->setTextQualifier(QChar('X'));
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
//attended result: one"\t\"wo
|
||||
out << "Xone\\\"\\\\t\\\\\\\"w\noX\n"
|
||||
<< "X13X,X2\\X,X,\"\"3\"X\r"
|
||||
<< "3,X\"4\"X,,\n"
|
||||
<< "XX\n"
|
||||
<< "\\";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "one\"\\t\\\"w\no");
|
||||
QVERIFY(t.at(1).at(0) == "13");
|
||||
@ -92,10 +93,10 @@ void TestCsvParser::testBackslashSyntax() {
|
||||
}
|
||||
|
||||
void TestCsvParser::testQuoted() {
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "ro,w,\"end, of \"\"\"\"\"\"row\"\"\"\"\"\n"
|
||||
<< "2\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "ro");
|
||||
QVERIFY(t.at(0).at(1) == "w");
|
||||
@ -105,41 +106,41 @@ void TestCsvParser::testQuoted() {
|
||||
}
|
||||
|
||||
void TestCsvParser::testEmptySimple() {
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out <<"";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 0);
|
||||
}
|
||||
|
||||
void TestCsvParser::testEmptyQuoted() {
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out <<"\"\"";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 0);
|
||||
}
|
||||
|
||||
void TestCsvParser::testEmptyNewline() {
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out <<"\"\n\"";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 0);
|
||||
}
|
||||
|
||||
void TestCsvParser::testEmptyFile()
|
||||
{
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 0);
|
||||
}
|
||||
|
||||
void TestCsvParser::testNewline()
|
||||
{
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "1,2\n\n\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 1);
|
||||
QVERIFY(t.at(0).at(0) == "1");
|
||||
@ -148,9 +149,9 @@ void TestCsvParser::testNewline()
|
||||
|
||||
void TestCsvParser::testCR()
|
||||
{
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "1,2\r3,4";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
QVERIFY(t.at(0).at(0) == "1");
|
||||
@ -161,9 +162,9 @@ void TestCsvParser::testCR()
|
||||
|
||||
void TestCsvParser::testLF()
|
||||
{
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "1,2\n3,4";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
QVERIFY(t.at(0).at(0) == "1");
|
||||
@ -174,9 +175,9 @@ void TestCsvParser::testLF()
|
||||
|
||||
void TestCsvParser::testCRLF()
|
||||
{
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "1,2\r\n3,4";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
QVERIFY(t.at(0).at(0) == "1");
|
||||
@ -187,13 +188,13 @@ void TestCsvParser::testCRLF()
|
||||
|
||||
void TestCsvParser::testComments()
|
||||
{
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << " #one\n"
|
||||
<< " \t # two, three \r\n"
|
||||
<< " #, sing\t with\r"
|
||||
<< " #\t me!\n"
|
||||
<< "useful,text #1!";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 1);
|
||||
QVERIFY(t.at(0).at(0) == "useful");
|
||||
@ -201,21 +202,21 @@ void TestCsvParser::testComments()
|
||||
}
|
||||
|
||||
void TestCsvParser::testColumns() {
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "1,2\n"
|
||||
<< ",,,,,,,,,a\n"
|
||||
<< "a,b,c,d\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(parser->getCsvCols() == 10);
|
||||
}
|
||||
|
||||
void TestCsvParser::testSimple() {
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << ",,2\r,2,3\n"
|
||||
<< "A,,B\"\n"
|
||||
<< " ,,\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 4);
|
||||
QVERIFY(t.at(0).at(0) == "");
|
||||
@ -234,11 +235,11 @@ void TestCsvParser::testSimple() {
|
||||
|
||||
void TestCsvParser::testSeparator() {
|
||||
parser->setFieldSeparator('\t');
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "\t\t2\r\t2\t3\n"
|
||||
<< "A\t\tB\"\n"
|
||||
<< " \t\t\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 4);
|
||||
QVERIFY(t.at(0).at(0) == "");
|
||||
@ -258,10 +259,10 @@ void TestCsvParser::testSeparator() {
|
||||
void TestCsvParser::testMultiline()
|
||||
{
|
||||
parser->setTextQualifier(QChar(':'));
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << ":1\r\n2a::b:,:3\r4:\n"
|
||||
<< "2\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.at(0).at(0) == "1\n2a:b");
|
||||
QVERIFY(t.at(0).at(1) == "3\n4");
|
||||
@ -279,10 +280,10 @@ void TestCsvParser::testEmptyReparsing()
|
||||
|
||||
void TestCsvParser::testReparsing()
|
||||
{
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << ":te\r\nxt1:,:te\rxt2:,:end of \"this\n string\":\n"
|
||||
<< "2\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
|
||||
QEXPECT_FAIL("", "Wrong qualifier", Continue);
|
||||
@ -301,10 +302,10 @@ void TestCsvParser::testReparsing()
|
||||
|
||||
void TestCsvParser::testQualifier() {
|
||||
parser->setTextQualifier(QChar('X'));
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << "X1X,X2XX,X,\"\"3\"\"\"X\r"
|
||||
<< "3,X\"4\"X,,\n";
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 2);
|
||||
QVERIFY(t.at(0).at(0) == "1");
|
||||
@ -322,10 +323,10 @@ void TestCsvParser::testUnicode() {
|
||||
//CORRECT QChar g(0x20AC);
|
||||
//ERROR QChar g("\u20AC");
|
||||
parser->setFieldSeparator(QChar('A'));
|
||||
QTextStream out(&file);
|
||||
QTextStream out(file);
|
||||
out << QString("€1A2śA\"3śAż\"Ażac");
|
||||
|
||||
QVERIFY(parser->parse(&file));
|
||||
QVERIFY(parser->parse(file));
|
||||
t = parser->getCsvTable();
|
||||
QVERIFY(t.size() == 1);
|
||||
QVERIFY(t.at(0).at(0) == "€1");
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
#include "core/CsvParser.h"
|
||||
|
||||
@ -60,7 +61,7 @@ private Q_SLOTS:
|
||||
void testColumns();
|
||||
|
||||
private:
|
||||
QFile file;
|
||||
QTemporaryFile* file;
|
||||
CsvParser* parser;
|
||||
CsvTable t;
|
||||
void dumpRow(CsvTable table, int row);
|
||||
|
Loading…
x
Reference in New Issue
Block a user