Commit c9a7215f14cb2b1fe5c9de3c5c19e36c02027823
Committed by
GitHub
Merge pull request #550 from biometrics/csv
refactor csvGallery
Showing
1 changed file
with
42 additions
and
84 deletions
openbr/plugins/gallery/csv.cpp
| @@ -33,8 +33,6 @@ namespace br | @@ -33,8 +33,6 @@ namespace br | ||
| 33 | class csvGallery : public FileGallery | 33 | class csvGallery : public FileGallery |
| 34 | { | 34 | { |
| 35 | Q_OBJECT | 35 | Q_OBJECT |
| 36 | - Q_PROPERTY(int fileIndex READ get_fileIndex WRITE set_fileIndex RESET reset_fileIndex) | ||
| 37 | - BR_PROPERTY(int, fileIndex, 0) | ||
| 38 | 36 | ||
| 39 | FileList files; | 37 | FileList files; |
| 40 | QStringList headers; | 38 | QStringList headers; |
| @@ -42,42 +40,30 @@ class csvGallery : public FileGallery | @@ -42,42 +40,30 @@ class csvGallery : public FileGallery | ||
| 42 | ~csvGallery() | 40 | ~csvGallery() |
| 43 | { | 41 | { |
| 44 | f.close(); | 42 | f.close(); |
| 45 | - | ||
| 46 | if (files.isEmpty()) return; | 43 | if (files.isEmpty()) return; |
| 47 | 44 | ||
| 48 | - QMap<QString,QVariant> samples; | 45 | + QSet<QString> samples; |
| 49 | foreach (const File &file, files) | 46 | foreach (const File &file, files) |
| 50 | foreach (const QString &key, file.localKeys()) | 47 | foreach (const QString &key, file.localKeys()) |
| 51 | - if (!samples.contains(key)) | ||
| 52 | - samples.insert(key, file.value(key)); | ||
| 53 | - | ||
| 54 | - // Don't create columns in the CSV for these special fields | ||
| 55 | - samples.remove("Points"); | ||
| 56 | - samples.remove("Rects"); | 48 | + samples.insert(key); |
| 57 | 49 | ||
| 58 | QStringList lines; | 50 | QStringList lines; |
| 59 | lines.reserve(files.size()+1); | 51 | lines.reserve(files.size()+1); |
| 60 | 52 | ||
| 61 | - QMap<QString, int> columnCounts; | ||
| 62 | - | ||
| 63 | - { // Make header | ||
| 64 | - QStringList words; | ||
| 65 | - words.append("File"); | ||
| 66 | - foreach (const QString &key, samples.keys()) { | ||
| 67 | - int count = 0; | ||
| 68 | - words.append(getCSVElement(key, samples[key], true, count)); | ||
| 69 | - columnCounts.insert(key, count); | ||
| 70 | - } | ||
| 71 | - lines.append(words.join(",")); | ||
| 72 | - } | 53 | + // Make header |
| 54 | + QStringList keys = samples.values(); | ||
| 55 | + keys.sort(); | ||
| 56 | + lines.append(QStringList(QStringList("File") + keys).join(",")); | ||
| 73 | 57 | ||
| 74 | // Make table | 58 | // Make table |
| 75 | foreach (const File &file, files) { | 59 | foreach (const File &file, files) { |
| 76 | QStringList words; | 60 | QStringList words; |
| 77 | words.append(file.name); | 61 | words.append(file.name); |
| 78 | - foreach (const QString &key, samples.keys()) { | ||
| 79 | - int count = columnCounts[key]; | ||
| 80 | - words.append(getCSVElement(key, file.value(key), false, count)); | 62 | + foreach (const QString &key, keys) { |
| 63 | + QString value = QtUtils::toString(file.value(key)); | ||
| 64 | + if (value.contains(",")) | ||
| 65 | + value = '"' + value + '"'; | ||
| 66 | + words.append(value); | ||
| 81 | } | 67 | } |
| 82 | lines.append(words.join(",")); | 68 | lines.append(words.join(",")); |
| 83 | } | 69 | } |
| @@ -94,32 +80,28 @@ class csvGallery : public FileGallery | @@ -94,32 +80,28 @@ class csvGallery : public FileGallery | ||
| 94 | *done = true; | 80 | *done = true; |
| 95 | return templates; | 81 | return templates; |
| 96 | } | 82 | } |
| 97 | - QRegExp regexp("\\s*,\\s*"); | ||
| 98 | 83 | ||
| 99 | - if (f.pos() == 0) | ||
| 100 | - { | ||
| 101 | - // read a line | 84 | + if (f.pos() == 0) { |
| 85 | + // read header | ||
| 102 | QByteArray lineBytes = f.readLine(); | 86 | QByteArray lineBytes = f.readLine(); |
| 103 | QString line = QString::fromLocal8Bit(lineBytes).trimmed(); | 87 | QString line = QString::fromLocal8Bit(lineBytes).trimmed(); |
| 88 | + QRegExp regexp("\\s*,\\s*"); | ||
| 104 | headers = line.split(regexp); | 89 | headers = line.split(regexp); |
| 105 | } | 90 | } |
| 106 | 91 | ||
| 107 | - for (qint64 i = 0; i < this->readBlockSize && !f.atEnd(); i++){ | ||
| 108 | - QByteArray lineBytes = f.readLine(); | ||
| 109 | - QString line = QString::fromLocal8Bit(lineBytes).trimmed(); | 92 | + for (qint64 i = 0; i < this->readBlockSize && !f.atEnd(); i++) { |
| 93 | + const QVariantList values = parseLine(f.readLine()); | ||
| 94 | + if (values.size() != headers.size()) continue; | ||
| 110 | 95 | ||
| 111 | - QStringList words = line.split(regexp); | ||
| 112 | - if (words.size() != headers.size()) continue; | ||
| 113 | - File fi; | ||
| 114 | - for (int j=0; j<words.size(); j++) { | ||
| 115 | - if (j == 0) fi.name = words[j]; | ||
| 116 | - else fi.set(headers[j], words[j]); | 96 | + File in; |
| 97 | + for (int j=0; j<values.size(); j++) { | ||
| 98 | + if (j == 0) in.name = values[j].toString(); | ||
| 99 | + else in.set(headers[j], values[j].toString()); | ||
| 117 | } | 100 | } |
| 118 | - templates.append(fi); | ||
| 119 | - templates.last().file.set("progress", f.pos()); | 101 | + in.set("progress", f.pos()); |
| 102 | + templates.append(in); | ||
| 120 | } | 103 | } |
| 121 | *done = f.atEnd(); | 104 | *done = f.atEnd(); |
| 122 | - | ||
| 123 | return templates; | 105 | return templates; |
| 124 | } | 106 | } |
| 125 | 107 | ||
| @@ -128,51 +110,27 @@ class csvGallery : public FileGallery | @@ -128,51 +110,27 @@ class csvGallery : public FileGallery | ||
| 128 | files.append(t.file); | 110 | files.append(t.file); |
| 129 | } | 111 | } |
| 130 | 112 | ||
| 131 | - static QString getCSVElement(const QString &key, const QVariant &value, bool header, int & columnCount) | 113 | + static QVariantList parseLine(const QByteArray bytes) |
| 132 | { | 114 | { |
| 133 | - if (header) | ||
| 134 | - columnCount = 1; | ||
| 135 | - | ||
| 136 | - if (value.canConvert<QString>()) { | ||
| 137 | - if (header) return key; | ||
| 138 | - else { | ||
| 139 | - if (columnCount != 1) | ||
| 140 | - qFatal("Inconsistent datatype for key %s, csv file cannot be generated", qPrintable(key)); | ||
| 141 | - return value.value<QString>(); | ||
| 142 | - } | ||
| 143 | - } else if (value.canConvert<QPointF>()) { | ||
| 144 | - const QPointF point = value.value<QPointF>(); | ||
| 145 | - if (header) { | ||
| 146 | - columnCount = 2; | ||
| 147 | - return key+"_X,"+key+"_Y"; | ||
| 148 | - } | ||
| 149 | - else { | ||
| 150 | - if (columnCount != 2) | ||
| 151 | - qFatal("Inconsistent datatype for key %s, csv file cannot be generated", qPrintable(key)); | ||
| 152 | - | ||
| 153 | - return QString::number(point.x())+","+QString::number(point.y()); | ||
| 154 | - } | ||
| 155 | - } else if (value.canConvert<QRectF>()) { | ||
| 156 | - const QRectF rect = value.value<QRectF>(); | ||
| 157 | - if (header) { | ||
| 158 | - columnCount = 4; | ||
| 159 | - return key+"_X,"+key+"_Y,"+key+"_Width,"+key+"_Height"; | ||
| 160 | - } | ||
| 161 | - else { | ||
| 162 | - if (columnCount != 4) | ||
| 163 | - qFatal("Inconsistent datatype for key %s, csv file cannot be generated", qPrintable(key)); | ||
| 164 | - | ||
| 165 | - return QString::number(rect.x())+","+QString::number(rect.y())+","+QString::number(rect.width())+","+QString::number(rect.height()); | ||
| 166 | - } | ||
| 167 | - } else { | ||
| 168 | - if (header) return key; | ||
| 169 | - else { | ||
| 170 | - QString output = QString::number(std::numeric_limits<float>::quiet_NaN()); | ||
| 171 | - for (int i = 1; i < columnCount; i++) | ||
| 172 | - output += "," + QString::number(std::numeric_limits<float>::quiet_NaN()); | ||
| 173 | - return output; | ||
| 174 | - } | 115 | + bool inQuote(false); |
| 116 | + QVariantList values; | ||
| 117 | + QString value = QString(); | ||
| 118 | + const QString line = QString::fromLocal8Bit(bytes).trimmed(); | ||
| 119 | + for (int i=0; i<line.size(); i++) { | ||
| 120 | + const QChar c = line[i]; | ||
| 121 | + if (c == '"') { | ||
| 122 | + inQuote = !inQuote; | ||
| 123 | + continue; | ||
| 124 | + } else if (c == ',' && !inQuote) { | ||
| 125 | + values.append(QVariant(value)); | ||
| 126 | + value = QString(); | ||
| 127 | + } else | ||
| 128 | + value.append(c); | ||
| 175 | } | 129 | } |
| 130 | + if (!value.isEmpty()) | ||
| 131 | + values.append(QVariant(value)); | ||
| 132 | + | ||
| 133 | + return values; | ||
| 176 | } | 134 | } |
| 177 | }; | 135 | }; |
| 178 | 136 |