Commit c9a7215f14cb2b1fe5c9de3c5c19e36c02027823

Authored by Ben Klein
Committed by GitHub
2 parents e9e452c0 5d82d11b

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 33 class csvGallery : public FileGallery
34 34 {
35 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 37 FileList files;
40 38 QStringList headers;
... ... @@ -42,42 +40,30 @@ class csvGallery : public FileGallery
42 40 ~csvGallery()
43 41 {
44 42 f.close();
45   -
46 43 if (files.isEmpty()) return;
47 44  
48   - QMap<QString,QVariant> samples;
  45 + QSet<QString> samples;
49 46 foreach (const File &file, files)
50 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 50 QStringList lines;
59 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 58 // Make table
75 59 foreach (const File &file, files) {
76 60 QStringList words;
77 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 68 lines.append(words.join(","));
83 69 }
... ... @@ -94,32 +80,28 @@ class csvGallery : public FileGallery
94 80 *done = true;
95 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 86 QByteArray lineBytes = f.readLine();
103 87 QString line = QString::fromLocal8Bit(lineBytes).trimmed();
  88 + QRegExp regexp("\\s*,\\s*");
104 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 104 *done = f.atEnd();
122   -
123 105 return templates;
124 106 }
125 107  
... ... @@ -128,51 +110,27 @@ class csvGallery : public FileGallery
128 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  
... ...