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