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:
seatedscribe 2017-02-22 01:03:22 +01:00
parent a7e358c27d
commit 41f9c3d2a1
10 changed files with 150 additions and 124 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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>
&lt;/ul&gt;</string>
</property>
</widget>

View File

@ -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);
}

View File

@ -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

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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");

View File

@ -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);