Commit 2f3a2fa283abfcb587ef7d269e1790dc8246930e

Authored by Scott Klum
1 parent 78eb9f12

Change qtutils to unix encoding from dos

openbr/core/qtutils.cpp
1   -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2   - * Copyright 2012 The MITRE Corporation *
3   - * *
4   - * Licensed under the Apache License, Version 2.0 (the "License"); *
5   - * you may not use this file except in compliance with the License. *
6   - * You may obtain a copy of the License at *
7   - * *
8   - * http://www.apache.org/licenses/LICENSE-2.0 *
9   - * *
10   - * Unless required by applicable law or agreed to in writing, software *
11   - * distributed under the License is distributed on an "AS IS" BASIS, *
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13   - * See the License for the specific language governing permissions and *
14   - * limitations under the License. *
15   - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16   -
17   -#include <QCryptographicHash>
18   -#include <QDebug>
19   -#ifndef BR_EMBEDDED
20   -#include <QDesktopServices>
21   -#endif // BR_EMBEDDED
22   -#include <QFile>
23   -#include <QFileInfo>
24   -#include <QProcess>
25   -#include <QProcessEnvironment>
26   -#include <QRegExp>
27   -#include <QRegularExpression>
28   -#include <QStack>
29   -#include <QUrl>
30   -#include <openbr/openbr_plugin.h>
31   -
32   -#include "alphanum.hpp"
33   -#include "qtutils.h"
34   -#include "opencvutils.h"
35   -
36   -using namespace br;
37   -
38   -namespace QtUtils
39   -{
40   -
41   -QStringList readLines(const QString &file)
42   -{
43   - QStringList lines;
44   - readFile(file, lines);
45   - return lines;
46   -}
47   -
48   -void readFile(const QString &file, QStringList &lines)
49   -{
50   - QByteArray data;
51   - readFile(file, data);
52   - lines = QString(data).split(QRegularExpression("[\n|\r\n|\r]"), QString::SkipEmptyParts);
53   - for (int i=0; i<lines.size(); i++)
54   - lines[i] = lines[i].simplified();
55   -}
56   -
57   -void readFile(const QString &file, QByteArray &data, bool uncompress)
58   -{
59   - QFile f(file);
60   - if (!f.open(QFile::ReadOnly)) {
61   - if (f.exists()) qFatal("Unable to open %s for reading. Check file permissions.", qPrintable(file));
62   - else qFatal("Unable to open %s for reading. File does not exist.", qPrintable(file));
63   - }
64   - data = f.readAll();
65   - if (uncompress) data = qUncompress(data);
66   - f.close();
67   -}
68   -
69   -void writeFile(const QString &file, const QStringList &lines)
70   -{
71   - if (file.isEmpty()) return;
72   - const QString baseName = QFileInfo(file).baseName();
73   -
74   - if (baseName == "terminal") {
75   - printf("%s\n", qPrintable(lines.join("\n")));
76   - } else if (baseName == "buffer") {
77   - Globals->buffer = lines.join("\n").toStdString().c_str();
78   - } else {
79   - QFile f(file);
80   - touchDir(f);
81   -
82   - if (!f.open(QFile::WriteOnly))
83   - qFatal("Failed to open %s for writing.", qPrintable(file));
84   -
85   - foreach (const QString &line, lines)
86   - f.write((line+"\n").toLocal8Bit());
87   -
88   - f.close();
89   - }
90   -}
91   -
92   -void writeFile(const QString &file, const QString &data)
93   -{
94   - writeFile(file, data.toLocal8Bit());
95   -}
96   -
97   -void writeFile(const QString &file, const QByteArray &data, int compression)
98   -{
99   - if (file.isEmpty()) return;
100   - const QString baseName = QFileInfo(file).baseName();
101   - const QByteArray contents = (compression == 0) ? data : qCompress(data, compression);
102   - if (baseName == "terminal") {
103   - printf("%s\n", qPrintable(contents));
104   - } else if (baseName == "buffer") {
105   - Globals->buffer = data;
106   - } else {
107   - QFile f(file);
108   - touchDir(f);
109   - if (!f.open(QFile::WriteOnly))
110   - qFatal("Failed to open %s for writing.", qPrintable(file));
111   - f.write(contents);
112   - f.close();
113   - }
114   -}
115   -
116   -void copyFile(const QString &src, const QString &dst)
117   -{
118   - touchDir(QFileInfo(dst));
119   - if (!QFile::copy(src, dst)) {
120   - if (QFileInfo(src).exists()) qFatal("Unable to copy %s to %s. Check file permissions.", qPrintable(src), qPrintable(dst));
121   - else qFatal("Unable to copy %s to %s. File does not exist.", qPrintable(src), qPrintable(dst));
122   - }
123   -}
124   -
125   -void touchDir(const QDir &dir)
126   -{
127   - if (dir.exists(".")) return;
128   - if (!dir.mkpath("."))
129   - qFatal("Unable to create path to dir %s", qPrintable(dir.absolutePath()));
130   -}
131   -
132   -void touchDir(const QFile &file)
133   -{
134   - touchDir(QFileInfo(file));
135   -}
136   -
137   -void touchDir(const QFileInfo &fileInfo)
138   -{
139   - touchDir(fileInfo.dir());
140   -}
141   -
142   -void emptyDir(QDir &dir)
143   -{
144   - foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks)) {
145   - QDir subdir(dir);
146   - bool success = subdir.cd(folder); if (!success) qFatal("cd failure.");
147   - emptyDir(subdir);
148   - }
149   -
150   - foreach (const QString &file, dir.entryList(QDir::Files))
151   - dir.remove(file);
152   -
153   - foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks))
154   - dir.rmdir(folder);
155   -
156   - foreach (const QString &symlink, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
157   - dir.remove(symlink);
158   -}
159   -
160   -void deleteDir(QDir &dir)
161   -{
162   - emptyDir(dir);
163   - dir.rmdir(".");
164   -}
165   -
166   -QString find(const QString &file, const QString &alt)
167   -{
168   - if (QFileInfo(file).exists()) return file;
169   - if (QFileInfo(alt).exists()) return alt;
170   - qFatal("Can't find file %s or alt %s\n", qPrintable(file), qPrintable(alt));
171   - return "";
172   -}
173   -
174   -bool toBool(const QString &string)
175   -{
176   - bool ok;
177   - bool result = (string.toFloat(&ok) != 0.f);
178   - if (ok) return result;
179   - else return (string != "FALSE") && (string != "false") && (string != "F") && (string != "f");
180   -}
181   -
182   -int toInt(const QString &string)
183   -{
184   - bool ok;
185   - int result = string.toInt(&ok); if (!ok) qFatal("Expected integer value, got %s.", qPrintable(string));
186   - return result;
187   -}
188   -
189   -float toFloat(const QString &string)
190   -{
191   - bool ok;
192   - float result = string.toFloat(&ok); if (!ok) qFatal("Expected floating point value, got %s.", qPrintable(string));
193   - return result;
194   -}
195   -
196   -QList<float> toFloats(const QStringList &strings)
197   -{
198   - QList<float> floats;
199   - bool ok;
200   - foreach (const QString &string, strings) {
201   - floats.append(string.toFloat(&ok));
202   - if (!ok) qFatal("Failed to convert %s to floating point format.", qPrintable(string));
203   - }
204   - return floats;
205   -}
206   -
207   -QStringList toStringList(const QList<float> &values)
208   -{
209   - QStringList result; result.reserve(values.size());
210   - foreach (float value, values)
211   - result.append(QString::number(value));
212   - return result;
213   -}
214   -
215   -QStringList toStringList(const std::vector<std::string> &string_list)
216   -{
217   - QStringList result;
218   - foreach (const std::string &string, string_list)
219   - result.append(QString::fromStdString(string));
220   - return result;
221   -}
222   -
223   -QStringList toStringList(int num_strings, const char *strings[])
224   -{
225   - QStringList result;
226   - for (int i=0; i<num_strings; i++)
227   - result.append(strings[i]);
228   - return result;
229   -}
230   -
231   -QString shortTextHash(QString string)
232   -{
233   - string.remove(QRegExp("[{}<>&]"));
234   - return QString(QCryptographicHash::hash(qPrintable(string), QCryptographicHash::Md5).toBase64()).remove(QRegExp("[^a-zA-Z1-9]")).left(6);
235   -}
236   -
237   -QStringList parse(QString args, char split, bool *ok)
238   -{
239   - if (args.isEmpty()) return QStringList();
240   -
241   - QStringList words;
242   - int start = 0;
243   - bool inQuote = false;
244   - QStack<QChar> subexpressions;
245   - for (int i=0; i<args.size(); i++) {
246   - if (inQuote) {
247   - if (args[i] == '\'')
248   - inQuote = false;
249   - } else {
250   - if (args[i] == '\'') {
251   - inQuote = true;
252   - } else if ((args[i] == '(') || (args[i] == '[') || (args[i] == '<') || (args[i] == '{')) {
253   - subexpressions.push(args[i]);
254   - } else if (args[i] == ')') {
255   - if (subexpressions.isEmpty() || (subexpressions.pop() != '(')) {
256   - if (ok) *ok = false;
257   - else qFatal("Unexpected ')'.");
258   - return words;
259   - }
260   - } else if (args[i] == ']') {
261   - if (subexpressions.isEmpty() || (subexpressions.pop() != '[')) {
262   - if (ok) *ok = false;
263   - else qFatal("Unexpected ']'.");
264   - return words;
265   - }
266   - } else if (args[i] == '>') {
267   - if (subexpressions.isEmpty() || (subexpressions.pop() != '<')) {
268   - if (ok) *ok = false;
269   - else qFatal("Unexpected '>'.");
270   - return words;
271   - }
272   - } else if (args[i] == '}') {
273   - if (subexpressions.isEmpty() || (subexpressions.pop() != '{')) {
274   - if (ok) *ok = false;
275   - else qFatal("Unexpected '}'.");
276   - return words;
277   - }
278   - } else if (subexpressions.isEmpty() && (args[i] == split)) {
279   - words.append(args.mid(start, i-start).trimmed());
280   - start = i+1;
281   - }
282   - }
283   - }
284   -
285   - if (ok) *ok = true;
286   - words.append(args.mid(start).trimmed());
287   - return words;
288   -}
289   -
290   -void checkArgsSize(const QString &name, const QStringList &args, int min, int max)
291   -{
292   - if (max == -1) max = std::numeric_limits<int>::max();
293   - if (max == 0) max = min;
294   - if (args.size() < min) qFatal("%s expects at least %d arguments, got %d", qPrintable(name), min, args.size());
295   - if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size());
296   -}
297   -
298   -QPointF toPoint(const QString &string, bool *ok)
299   -{
300   - if (string.startsWith('(') && string.endsWith(')')) {
301   - bool okParse;
302   - const QStringList words = parse(string.mid(1, string.size()-2), ',', &okParse);
303   - if (okParse && (words.size() == 2)) {
304   - float x, y;
305   - bool okX, okY;
306   - x = words[0].toFloat(&okX);
307   - y = words[1].toFloat(&okY);
308   - if (okX && okY) {
309   - if (ok) *ok = true;
310   - return QPointF(x, y);
311   - }
312   - }
313   - }
314   -
315   - if (ok) *ok = false;
316   - return QPointF();
317   -}
318   -
319   -QRectF toRect(const QString &string, bool *ok)
320   -{
321   - if (string.startsWith('(') && string.endsWith(')')) {
322   - bool okParse;
323   - const QStringList words = parse(string.mid(1, string.size()-2), ',', &okParse);
324   - if (okParse && (words.size() == 4)) {
325   - float x, y, width, height;
326   - bool okX, okY, okWidth, okHeight;
327   - x = words[0].toFloat(&okX);
328   - y = words[1].toFloat(&okY);
329   - width = words[2].toFloat(&okWidth);
330   - height = words[3].toFloat(&okHeight);
331   - if (okX && okY && okWidth && okHeight) {
332   - if (ok) *ok = true;
333   - return QRectF(x, y, width, height);
334   - }
335   - }
336   - }
337   -
338   - if (ok) *ok = false;
339   - return QRectF();
340   -}
341   -
342   -QStringList naturalSort(const QStringList &strings)
343   -{
344   - QList<std::string> stdStrings; stdStrings.reserve(strings.size());
345   - foreach (const QString &string, strings)
346   - stdStrings.append(string.toStdString());
347   -
348   - std::sort(stdStrings.begin(), stdStrings.end(), doj::alphanum_less<std::string>());
349   -
350   - QStringList result; result.reserve(strings.size());
351   - foreach (const std::string &stdString, stdStrings)
352   - result.append(QString::fromStdString(stdString));
353   -
354   - return result;
355   -}
356   -
357   -bool runRScript(const QString &file)
358   -{
359   -// iOS doesn't support QProcess
360   -#ifdef QT_NO_PROCESS
361   - (void) file;
362   - return false;
363   -#else // !QT_NO_PROCESS
364   - QProcess RScript;
365   - RScript.start("Rscript", QStringList() << file);
366   - RScript.waitForFinished(-1);
367   - bool result = ((RScript.exitCode() == 0) && (RScript.error() == QProcess::UnknownError));
368   - if (!result) qDebug("Failed to run 'Rscript', did you forget to install R? "
369   - "See online documentation of 'br_plot' for required R packages. "
370   - "Otherwise, try running Rscript on %s to get the exact error.", qPrintable(file));
371   - return result;
372   -#endif // QT_NO_PROCESS
373   -}
374   -
375   -bool runDot(const QString &file)
376   -{
377   -// iOS doesn't support QProcess
378   -#ifdef QT_NO_PROCESS
379   - (void) file;
380   - return false;
381   -#else // !QT_NO_PROCESS
382   - QProcess dot;
383   - dot.start("dot -Tpdf -O " + file);
384   - dot.waitForFinished(-1);
385   - return ((dot.exitCode() == 0) && (dot.error() == QProcess::UnknownError));
386   -#endif // QT_NO_PROCESS
387   -}
388   -
389   -void showFile(const QString &file)
390   -{
391   -#ifndef BR_EMBEDDED
392   - (void) file;
393   - // A bug in Qt5 currently prevents us from doing this:
394   - // QDesktopServices::openUrl(QUrl::fromLocalFile(file));
395   -#else // BR_EMBEDDED
396   - (void) file;
397   -#endif // BR_EMBEDDED
398   -}
399   -
400   -QString toString(const QVariant &variant)
401   -{
402   - if (variant.canConvert(QVariant::List)) return toString(qvariant_cast<QVariantList>(variant));
403   - else if (variant.canConvert(QVariant::String)) return variant.toString();
404   - else if (variant.canConvert(QVariant::PointF)) {
405   - QPointF point = qvariant_cast<QPointF>(variant);
406   - return QString("(%1,%2)").arg(QString::number(point.x()),QString::number(point.y()));
407   - } else if (variant.canConvert(QVariant::RectF)) {
408   - QRectF rect = qvariant_cast<QRectF>(variant);
409   - return QString("(%1,%2,%3,%4)").arg(QString::number(rect.x()),
410   - QString::number(rect.y()),
411   - QString::number(rect.width()),
412   - QString::number(rect.height()));
413   - } else if (variant.canConvert<cv::Mat>()) {
414   - return OpenCVUtils::matrixToString(variant.value<cv::Mat>());
415   - } else if (variant.canConvert<cv::RotatedRect>()) {
416   - return OpenCVUtils::rotatedRectToString(variant.value<cv::RotatedRect>());
417   - }
418   -
419   - return QString();
420   -}
421   -
422   -QString toString(const QVariantList &variantList)
423   -{
424   - QStringList variants;
425   -
426   - foreach (const QVariant &variant, variantList)
427   - variants.append(toString(variant));
428   -
429   - if (!variants.isEmpty()) return "[" + variants.join(", ") + "]";
430   -
431   - return QString();
432   -}
433   -
434   -QString toString(const QMap<QString,QVariant> &variantMap)
435   -{
436   - QStringList variants = toStringList(variantMap);
437   -
438   - if (!variants.isEmpty()) return "[" + variants.join(", ") + "]";
439   -
440   - return QString();
441   -}
442   -
443   -QStringList toStringList(const QMap<QString,QVariant> &variantMap)
444   -{
445   - QStringList variants;
446   -
447   - QMapIterator<QString, QVariant> i(variantMap);
448   - while (i.hasNext()) {
449   - i.next();
450   - variants.append(i.key() + "=" + toString(i.value()));
451   - }
452   -
453   - return variants;
454   -}
455   -
456   -QString toTime(int s)
457   -{
458   - int h = s / (60*60);
459   - int m = (s - h*60*60) / 60;
460   - s = (s - h*60*60 - m*60);
461   -
462   - const QChar fillChar = QLatin1Char('0');
463   -
464   - return QString("%1:%2:%3").arg(h,2,10,fillChar).arg(m,2,10,fillChar).arg(s,2,10,fillChar);
465   -}
466   -
467   -float euclideanLength(const QPointF &point)
468   -{
469   - return sqrt(pow(point.x(), 2) + pow(point.y(), 2));
470   -}
471   -
472   -float orientation(const QPointF &pointA, const QPointF &pointB)
473   -{
474   - return atan2(pointB.y() - pointA.y(), pointB.x() - pointA.x());
475   -}
476   -
477   -float overlap(const QRectF &r, const QRectF &s) {
478   - QRectF intersection = r & s;
479   -
480   - return (intersection.width()*intersection.height())/(r.width()*r.height());
481   -}
482   -
483   -
484   -QString getAbsolutePath(const QString &filename)
485   -{
486   - // Try adding the global path, if present
487   - QString withPath = (Globals->path.isEmpty() ? "" : Globals->path + "/") + filename;
488   -
489   - // we weren't necessarily using it to begin with, so see if that file
490   - // exists
491   - QFileInfo wpInfo(withPath);
492   - if (wpInfo.exists() )
493   - return wpInfo.absoluteFilePath();
494   -
495   - // If no, just use the nominal filename
496   - return QFileInfo(filename).absoluteFilePath();
497   -}
498   -
499   -const int base_block = 100000000;
500   -
501   -BlockCompression::BlockCompression(QIODevice *_basis)
502   -{
503   - blockSize = base_block;
504   - setBasis(_basis);
505   -}
506   -
507   -BlockCompression::BlockCompression() { blockSize = base_block;};
508   -
509   -bool BlockCompression::open(QIODevice::OpenMode mode)
510   -{
511   - this->setOpenMode(mode);
512   - bool res = basis->open(mode);
513   -
514   - if (!res)
515   - return false;
516   -
517   - blockReader.setDevice(basis);
518   - blockWriter.setDevice(basis);
519   -
520   - if (mode & QIODevice::WriteOnly) {
521   - precompressedBlockWriter.open(QIODevice::WriteOnly);
522   - }
523   - else if (mode & QIODevice::ReadOnly) {
524   -
525   - // Read an initial compressed block from the underlying QIODevice,
526   - // decompress, and set up a reader on it
527   - QByteArray compressedBlock;
528   - quint32 block_size;
529   - blockReader >> block_size;
530   - compressedBlock.resize(block_size);
531   - int read_count = blockReader.readRawData(compressedBlock.data(), block_size);
532   - if (read_count != int(block_size))
533   - qFatal("Failed to read initial block");
534   -
535   - decompressedBlock = qUncompress(compressedBlock);
536   -
537   - decompressedBlockReader.setBuffer(&decompressedBlock);
538   - decompressedBlockReader.open(QIODevice::ReadOnly);
539   - }
540   -
541   - return true;
542   -}
543   -
544   -void BlockCompression::close()
545   -{
546   - // flush output buffer, since we may have a partial block which hasn't been
547   - // written to disk yet.
548   - if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter.isOpen()) {
549   - QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer());
550   - precompressedBlockWriter.close();
551   -
552   - quint32 bsize= compressedBlock.size();
553   - blockWriter << bsize;
554   - blockWriter.writeRawData(compressedBlock.constData(), compressedBlock.size());
555   - }
556   - // close the underlying device.
557   - basis->close();
558   -}
559   -
560   -void BlockCompression::setBasis(QIODevice *_basis)
561   -{
562   - basis = _basis;
563   - blockReader.setDevice(basis);
564   - blockWriter.setDevice(basis);
565   -}
566   -
567   -// read from current decompressed block, if out of space, read and decompress another
568   -// block from basis
569   -qint64 BlockCompression::readData(char *data, qint64 remaining)
570   -{
571   - qint64 read = 0;
572   - while (remaining > 0) {
573   - // attempt to read the target amount of data
574   - qint64 single_read = decompressedBlockReader.read(data, remaining);
575   - if (single_read == -1)
576   - qFatal("miss read");
577   -
578   - remaining -= single_read;
579   - read += single_read;
580   - data += single_read;
581   -
582   - // need a new block if we didn't get enough bytes from the previous read
583   - if (remaining > 0) {
584   - QByteArray compressedBlock;
585   -
586   - // read the size of the next block
587   - quint32 block_size;
588   - blockReader >> block_size;
589   - if (block_size == 0)
590   - break;
591   -
592   - compressedBlock.resize(block_size);
593   - int actualRead = blockReader.readRawData(compressedBlock.data(), block_size);
594   - if (actualRead != int(block_size))
595   - qFatal("Bad read on nominal block size: %d, only got %d", block_size, int(remaining));
596   -
597   - decompressedBlock = qUncompress(compressedBlock);
598   -
599   - decompressedBlockReader.close();
600   - decompressedBlockReader.setBuffer(&decompressedBlock);
601   - decompressedBlockReader.open(QIODevice::ReadOnly);
602   - }
603   - }
604   -
605   - bool condition = blockReader.atEnd() && !basis->isReadable() ;
606   - if (condition)
607   - qWarning("Returning -1 from read");
608   -
609   - return condition ? -1 : read;
610   -}
611   -
612   -bool BlockCompression::isSequential() const
613   -{
614   - return true;
615   -}
616   -
617   -qint64 BlockCompression::writeData(const char *data, qint64 remaining)
618   -{
619   - const char * endPoint = data + remaining;
620   - qint64 initial = remaining;
621   -
622   - qint64 written = 0;
623   -
624   - while (remaining > 0) {
625   - // how much more can be put in this buffer?
626   - qint64 capacity = blockSize - precompressedBlockWriter.pos();
627   - if (capacity < 0)
628   - qFatal("Negative capacity!!!");
629   -
630   - // don't try to write beyond capacity
631   - qint64 write_size = qMin(capacity, remaining);
632   -
633   - qint64 singleWrite = precompressedBlockWriter.write(data, write_size);
634   -
635   - if (singleWrite == -1)
636   - qFatal("matrix write failure?");
637   -
638   - remaining -= singleWrite;
639   - data += singleWrite;
640   - written += singleWrite;
641   - if (data > endPoint)
642   - qFatal("Wrote past the end");
643   -
644   - if (remaining > 0) {
645   - QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer(), -1);
646   -
647   - if (precompressedBlockWriter.buffer().size() != 0) {
648   - quint32 block_size = compressedBlock.size();
649   - blockWriter << block_size;
650   -
651   - int write_count = blockWriter.writeRawData(compressedBlock.constData(), block_size);
652   - if (write_count != int(block_size))
653   - qFatal("Didn't write enough data");
654   - }
655   - else
656   - qFatal("serialized empty compressed block (?)");
657   -
658   - precompressedBlockWriter.close();
659   - precompressedBlockWriter.open(QIODevice::WriteOnly);
660   - }
661   - }
662   -
663   - if (written != initial)
664   - qFatal("didn't write enough bytes");
665   -
666   - bool condition = basis->isWritable();
667   - if (!condition)
668   - qWarning("Returning -1 from write");
669   -
670   - return basis->isWritable() ? written : -1;
671   -}
672   -
673   -
674   -
675   -} // namespace QtUtils
676   -
  1 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2 + * Copyright 2012 The MITRE Corporation *
  3 + * *
  4 + * Licensed under the Apache License, Version 2.0 (the "License"); *
  5 + * you may not use this file except in compliance with the License. *
  6 + * You may obtain a copy of the License at *
  7 + * *
  8 + * http://www.apache.org/licenses/LICENSE-2.0 *
  9 + * *
  10 + * Unless required by applicable law or agreed to in writing, software *
  11 + * distributed under the License is distributed on an "AS IS" BASIS, *
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
  13 + * See the License for the specific language governing permissions and *
  14 + * limitations under the License. *
  15 + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  16 +
  17 +#include <QCryptographicHash>
  18 +#include <QDebug>
  19 +#ifndef BR_EMBEDDED
  20 +#include <QDesktopServices>
  21 +#endif // BR_EMBEDDED
  22 +#include <QFile>
  23 +#include <QFileInfo>
  24 +#include <QProcess>
  25 +#include <QProcessEnvironment>
  26 +#include <QRegExp>
  27 +#include <QRegularExpression>
  28 +#include <QStack>
  29 +#include <QUrl>
  30 +#include <openbr/openbr_plugin.h>
  31 +
  32 +#include "alphanum.hpp"
  33 +#include "qtutils.h"
  34 +#include "opencvutils.h"
  35 +
  36 +using namespace br;
  37 +
  38 +namespace QtUtils
  39 +{
  40 +
  41 +QStringList readLines(const QString &file)
  42 +{
  43 + QStringList lines;
  44 + readFile(file, lines);
  45 + return lines;
  46 +}
  47 +
  48 +void readFile(const QString &file, QStringList &lines)
  49 +{
  50 + QByteArray data;
  51 + readFile(file, data);
  52 + lines = QString(data).split(QRegularExpression("[\n|\r\n|\r]"), QString::SkipEmptyParts);
  53 + for (int i=0; i<lines.size(); i++)
  54 + lines[i] = lines[i].simplified();
  55 +}
  56 +
  57 +void readFile(const QString &file, QByteArray &data, bool uncompress)
  58 +{
  59 + QFile f(file);
  60 + if (!f.open(QFile::ReadOnly)) {
  61 + if (f.exists()) qFatal("Unable to open %s for reading. Check file permissions.", qPrintable(file));
  62 + else qFatal("Unable to open %s for reading. File does not exist.", qPrintable(file));
  63 + }
  64 + data = f.readAll();
  65 + if (uncompress) data = qUncompress(data);
  66 + f.close();
  67 +}
  68 +
  69 +void writeFile(const QString &file, const QStringList &lines)
  70 +{
  71 + if (file.isEmpty()) return;
  72 + const QString baseName = QFileInfo(file).baseName();
  73 +
  74 + if (baseName == "terminal") {
  75 + printf("%s\n", qPrintable(lines.join("\n")));
  76 + } else if (baseName == "buffer") {
  77 + Globals->buffer = lines.join("\n").toStdString().c_str();
  78 + } else {
  79 + QFile f(file);
  80 + touchDir(f);
  81 +
  82 + if (!f.open(QFile::WriteOnly))
  83 + qFatal("Failed to open %s for writing.", qPrintable(file));
  84 +
  85 + foreach (const QString &line, lines)
  86 + f.write((line+"\n").toLocal8Bit());
  87 +
  88 + f.close();
  89 + }
  90 +}
  91 +
  92 +void writeFile(const QString &file, const QString &data)
  93 +{
  94 + writeFile(file, data.toLocal8Bit());
  95 +}
  96 +
  97 +void writeFile(const QString &file, const QByteArray &data, int compression)
  98 +{
  99 + if (file.isEmpty()) return;
  100 + const QString baseName = QFileInfo(file).baseName();
  101 + const QByteArray contents = (compression == 0) ? data : qCompress(data, compression);
  102 + if (baseName == "terminal") {
  103 + printf("%s\n", qPrintable(contents));
  104 + } else if (baseName == "buffer") {
  105 + Globals->buffer = data;
  106 + } else {
  107 + QFile f(file);
  108 + touchDir(f);
  109 + if (!f.open(QFile::WriteOnly))
  110 + qFatal("Failed to open %s for writing.", qPrintable(file));
  111 + f.write(contents);
  112 + f.close();
  113 + }
  114 +}
  115 +
  116 +void copyFile(const QString &src, const QString &dst)
  117 +{
  118 + touchDir(QFileInfo(dst));
  119 + if (!QFile::copy(src, dst)) {
  120 + if (QFileInfo(src).exists()) qFatal("Unable to copy %s to %s. Check file permissions.", qPrintable(src), qPrintable(dst));
  121 + else qFatal("Unable to copy %s to %s. File does not exist.", qPrintable(src), qPrintable(dst));
  122 + }
  123 +}
  124 +
  125 +void touchDir(const QDir &dir)
  126 +{
  127 + if (dir.exists(".")) return;
  128 + if (!dir.mkpath("."))
  129 + qFatal("Unable to create path to dir %s", qPrintable(dir.absolutePath()));
  130 +}
  131 +
  132 +void touchDir(const QFile &file)
  133 +{
  134 + touchDir(QFileInfo(file));
  135 +}
  136 +
  137 +void touchDir(const QFileInfo &fileInfo)
  138 +{
  139 + touchDir(fileInfo.dir());
  140 +}
  141 +
  142 +void emptyDir(QDir &dir)
  143 +{
  144 + foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks)) {
  145 + QDir subdir(dir);
  146 + bool success = subdir.cd(folder); if (!success) qFatal("cd failure.");
  147 + emptyDir(subdir);
  148 + }
  149 +
  150 + foreach (const QString &file, dir.entryList(QDir::Files))
  151 + dir.remove(file);
  152 +
  153 + foreach (const QString &folder, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks))
  154 + dir.rmdir(folder);
  155 +
  156 + foreach (const QString &symlink, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
  157 + dir.remove(symlink);
  158 +}
  159 +
  160 +void deleteDir(QDir &dir)
  161 +{
  162 + emptyDir(dir);
  163 + dir.rmdir(".");
  164 +}
  165 +
  166 +QString find(const QString &file, const QString &alt)
  167 +{
  168 + if (QFileInfo(file).exists()) return file;
  169 + if (QFileInfo(alt).exists()) return alt;
  170 + qFatal("Can't find file %s or alt %s\n", qPrintable(file), qPrintable(alt));
  171 + return "";
  172 +}
  173 +
  174 +bool toBool(const QString &string)
  175 +{
  176 + bool ok;
  177 + bool result = (string.toFloat(&ok) != 0.f);
  178 + if (ok) return result;
  179 + else return (string != "FALSE") && (string != "false") && (string != "F") && (string != "f");
  180 +}
  181 +
  182 +int toInt(const QString &string)
  183 +{
  184 + bool ok;
  185 + int result = string.toInt(&ok); if (!ok) qFatal("Expected integer value, got %s.", qPrintable(string));
  186 + return result;
  187 +}
  188 +
  189 +float toFloat(const QString &string)
  190 +{
  191 + bool ok;
  192 + float result = string.toFloat(&ok); if (!ok) qFatal("Expected floating point value, got %s.", qPrintable(string));
  193 + return result;
  194 +}
  195 +
  196 +QList<float> toFloats(const QStringList &strings)
  197 +{
  198 + QList<float> floats;
  199 + bool ok;
  200 + foreach (const QString &string, strings) {
  201 + floats.append(string.toFloat(&ok));
  202 + if (!ok) qFatal("Failed to convert %s to floating point format.", qPrintable(string));
  203 + }
  204 + return floats;
  205 +}
  206 +
  207 +QStringList toStringList(const QList<float> &values)
  208 +{
  209 + QStringList result; result.reserve(values.size());
  210 + foreach (float value, values)
  211 + result.append(QString::number(value));
  212 + return result;
  213 +}
  214 +
  215 +QStringList toStringList(const std::vector<std::string> &string_list)
  216 +{
  217 + QStringList result;
  218 + foreach (const std::string &string, string_list)
  219 + result.append(QString::fromStdString(string));
  220 + return result;
  221 +}
  222 +
  223 +QStringList toStringList(int num_strings, const char *strings[])
  224 +{
  225 + QStringList result;
  226 + for (int i=0; i<num_strings; i++)
  227 + result.append(strings[i]);
  228 + return result;
  229 +}
  230 +
  231 +QString shortTextHash(QString string)
  232 +{
  233 + string.remove(QRegExp("[{}<>&]"));
  234 + return QString(QCryptographicHash::hash(qPrintable(string), QCryptographicHash::Md5).toBase64()).remove(QRegExp("[^a-zA-Z1-9]")).left(6);
  235 +}
  236 +
  237 +QStringList parse(QString args, char split, bool *ok)
  238 +{
  239 + if (args.isEmpty()) return QStringList();
  240 +
  241 + QStringList words;
  242 + int start = 0;
  243 + bool inQuote = false;
  244 + QStack<QChar> subexpressions;
  245 + for (int i=0; i<args.size(); i++) {
  246 + if (inQuote) {
  247 + if (args[i] == '\'')
  248 + inQuote = false;
  249 + } else {
  250 + if (args[i] == '\'') {
  251 + inQuote = true;
  252 + } else if ((args[i] == '(') || (args[i] == '[') || (args[i] == '<') || (args[i] == '{')) {
  253 + subexpressions.push(args[i]);
  254 + } else if (args[i] == ')') {
  255 + if (subexpressions.isEmpty() || (subexpressions.pop() != '(')) {
  256 + if (ok) *ok = false;
  257 + else qFatal("Unexpected ')'.");
  258 + return words;
  259 + }
  260 + } else if (args[i] == ']') {
  261 + if (subexpressions.isEmpty() || (subexpressions.pop() != '[')) {
  262 + if (ok) *ok = false;
  263 + else qFatal("Unexpected ']'.");
  264 + return words;
  265 + }
  266 + } else if (args[i] == '>') {
  267 + if (subexpressions.isEmpty() || (subexpressions.pop() != '<')) {
  268 + if (ok) *ok = false;
  269 + else qFatal("Unexpected '>'.");
  270 + return words;
  271 + }
  272 + } else if (args[i] == '}') {
  273 + if (subexpressions.isEmpty() || (subexpressions.pop() != '{')) {
  274 + if (ok) *ok = false;
  275 + else qFatal("Unexpected '}'.");
  276 + return words;
  277 + }
  278 + } else if (subexpressions.isEmpty() && (args[i] == split)) {
  279 + words.append(args.mid(start, i-start).trimmed());
  280 + start = i+1;
  281 + }
  282 + }
  283 + }
  284 +
  285 + if (ok) *ok = true;
  286 + words.append(args.mid(start).trimmed());
  287 + return words;
  288 +}
  289 +
  290 +void checkArgsSize(const QString &name, const QStringList &args, int min, int max)
  291 +{
  292 + if (max == -1) max = std::numeric_limits<int>::max();
  293 + if (max == 0) max = min;
  294 + if (args.size() < min) qFatal("%s expects at least %d arguments, got %d", qPrintable(name), min, args.size());
  295 + if (args.size() > max) qFatal("%s expects no more than %d arguments, got %d", qPrintable(name), max, args.size());
  296 +}
  297 +
  298 +QPointF toPoint(const QString &string, bool *ok)
  299 +{
  300 + if (string.startsWith('(') && string.endsWith(')')) {
  301 + bool okParse;
  302 + const QStringList words = parse(string.mid(1, string.size()-2), ',', &okParse);
  303 + if (okParse && (words.size() == 2)) {
  304 + float x, y;
  305 + bool okX, okY;
  306 + x = words[0].toFloat(&okX);
  307 + y = words[1].toFloat(&okY);
  308 + if (okX && okY) {
  309 + if (ok) *ok = true;
  310 + return QPointF(x, y);
  311 + }
  312 + }
  313 + }
  314 +
  315 + if (ok) *ok = false;
  316 + return QPointF();
  317 +}
  318 +
  319 +QRectF toRect(const QString &string, bool *ok)
  320 +{
  321 + if (string.startsWith('(') && string.endsWith(')')) {
  322 + bool okParse;
  323 + const QStringList words = parse(string.mid(1, string.size()-2), ',', &okParse);
  324 + if (okParse && (words.size() == 4)) {
  325 + float x, y, width, height;
  326 + bool okX, okY, okWidth, okHeight;
  327 + x = words[0].toFloat(&okX);
  328 + y = words[1].toFloat(&okY);
  329 + width = words[2].toFloat(&okWidth);
  330 + height = words[3].toFloat(&okHeight);
  331 + if (okX && okY && okWidth && okHeight) {
  332 + if (ok) *ok = true;
  333 + return QRectF(x, y, width, height);
  334 + }
  335 + }
  336 + }
  337 +
  338 + if (ok) *ok = false;
  339 + return QRectF();
  340 +}
  341 +
  342 +QStringList naturalSort(const QStringList &strings)
  343 +{
  344 + QList<std::string> stdStrings; stdStrings.reserve(strings.size());
  345 + foreach (const QString &string, strings)
  346 + stdStrings.append(string.toStdString());
  347 +
  348 + std::sort(stdStrings.begin(), stdStrings.end(), doj::alphanum_less<std::string>());
  349 +
  350 + QStringList result; result.reserve(strings.size());
  351 + foreach (const std::string &stdString, stdStrings)
  352 + result.append(QString::fromStdString(stdString));
  353 +
  354 + return result;
  355 +}
  356 +
  357 +bool runRScript(const QString &file)
  358 +{
  359 +// iOS doesn't support QProcess
  360 +#ifdef QT_NO_PROCESS
  361 + (void) file;
  362 + return false;
  363 +#else // !QT_NO_PROCESS
  364 + QProcess RScript;
  365 + RScript.start("Rscript", QStringList() << file);
  366 + RScript.waitForFinished(-1);
  367 + bool result = ((RScript.exitCode() == 0) && (RScript.error() == QProcess::UnknownError));
  368 + if (!result) qDebug("Failed to run 'Rscript', did you forget to install R? "
  369 + "See online documentation of 'br_plot' for required R packages. "
  370 + "Otherwise, try running Rscript on %s to get the exact error.", qPrintable(file));
  371 + return result;
  372 +#endif // QT_NO_PROCESS
  373 +}
  374 +
  375 +bool runDot(const QString &file)
  376 +{
  377 +// iOS doesn't support QProcess
  378 +#ifdef QT_NO_PROCESS
  379 + (void) file;
  380 + return false;
  381 +#else // !QT_NO_PROCESS
  382 + QProcess dot;
  383 + dot.start("dot -Tpdf -O " + file);
  384 + dot.waitForFinished(-1);
  385 + return ((dot.exitCode() == 0) && (dot.error() == QProcess::UnknownError));
  386 +#endif // QT_NO_PROCESS
  387 +}
  388 +
  389 +void showFile(const QString &file)
  390 +{
  391 +#ifndef BR_EMBEDDED
  392 + (void) file;
  393 + // A bug in Qt5 currently prevents us from doing this:
  394 + // QDesktopServices::openUrl(QUrl::fromLocalFile(file));
  395 +#else // BR_EMBEDDED
  396 + (void) file;
  397 +#endif // BR_EMBEDDED
  398 +}
  399 +
  400 +QString toString(const QVariant &variant)
  401 +{
  402 + if (variant.canConvert(QVariant::List)) return toString(qvariant_cast<QVariantList>(variant));
  403 + else if (variant.canConvert(QVariant::String)) return variant.toString();
  404 + else if (variant.canConvert(QVariant::PointF)) {
  405 + QPointF point = qvariant_cast<QPointF>(variant);
  406 + return QString("(%1,%2)").arg(QString::number(point.x()),QString::number(point.y()));
  407 + } else if (variant.canConvert(QVariant::RectF)) {
  408 + QRectF rect = qvariant_cast<QRectF>(variant);
  409 + return QString("(%1,%2,%3,%4)").arg(QString::number(rect.x()),
  410 + QString::number(rect.y()),
  411 + QString::number(rect.width()),
  412 + QString::number(rect.height()));
  413 + } else if (variant.canConvert<cv::Mat>()) {
  414 + return OpenCVUtils::matrixToString(variant.value<cv::Mat>());
  415 + } else if (variant.canConvert<cv::RotatedRect>()) {
  416 + return OpenCVUtils::rotatedRectToString(variant.value<cv::RotatedRect>());
  417 + }
  418 +
  419 + return QString();
  420 +}
  421 +
  422 +QString toString(const QVariantList &variantList)
  423 +{
  424 + QStringList variants;
  425 +
  426 + foreach (const QVariant &variant, variantList)
  427 + variants.append(toString(variant));
  428 +
  429 + if (!variants.isEmpty()) return "[" + variants.join(", ") + "]";
  430 +
  431 + return QString();
  432 +}
  433 +
  434 +QString toString(const QMap<QString,QVariant> &variantMap)
  435 +{
  436 + QStringList variants = toStringList(variantMap);
  437 +
  438 + if (!variants.isEmpty()) return "[" + variants.join(", ") + "]";
  439 +
  440 + return QString();
  441 +}
  442 +
  443 +QStringList toStringList(const QMap<QString,QVariant> &variantMap)
  444 +{
  445 + QStringList variants;
  446 +
  447 + QMapIterator<QString, QVariant> i(variantMap);
  448 + while (i.hasNext()) {
  449 + i.next();
  450 + variants.append(i.key() + "=" + toString(i.value()));
  451 + }
  452 +
  453 + return variants;
  454 +}
  455 +
  456 +QString toTime(int s)
  457 +{
  458 + int h = s / (60*60);
  459 + int m = (s - h*60*60) / 60;
  460 + s = (s - h*60*60 - m*60);
  461 +
  462 + const QChar fillChar = QLatin1Char('0');
  463 +
  464 + return QString("%1:%2:%3").arg(h,2,10,fillChar).arg(m,2,10,fillChar).arg(s,2,10,fillChar);
  465 +}
  466 +
  467 +float euclideanLength(const QPointF &point)
  468 +{
  469 + return sqrt(pow(point.x(), 2) + pow(point.y(), 2));
  470 +}
  471 +
  472 +float orientation(const QPointF &pointA, const QPointF &pointB)
  473 +{
  474 + return atan2(pointB.y() - pointA.y(), pointB.x() - pointA.x());
  475 +}
  476 +
  477 +float overlap(const QRectF &r, const QRectF &s) {
  478 + QRectF intersection = r & s;
  479 +
  480 + return (intersection.width()*intersection.height())/(r.width()*r.height());
  481 +}
  482 +
  483 +
  484 +QString getAbsolutePath(const QString &filename)
  485 +{
  486 + // Try adding the global path, if present
  487 + QString withPath = (Globals->path.isEmpty() ? "" : Globals->path + "/") + filename;
  488 +
  489 + // we weren't necessarily using it to begin with, so see if that file
  490 + // exists
  491 + QFileInfo wpInfo(withPath);
  492 + if (wpInfo.exists() )
  493 + return wpInfo.absoluteFilePath();
  494 +
  495 + // If no, just use the nominal filename
  496 + return QFileInfo(filename).absoluteFilePath();
  497 +}
  498 +
  499 +const int base_block = 100000000;
  500 +
  501 +BlockCompression::BlockCompression(QIODevice *_basis)
  502 +{
  503 + blockSize = base_block;
  504 + setBasis(_basis);
  505 +}
  506 +
  507 +BlockCompression::BlockCompression() { blockSize = base_block;};
  508 +
  509 +bool BlockCompression::open(QIODevice::OpenMode mode)
  510 +{
  511 + this->setOpenMode(mode);
  512 + bool res = basis->open(mode);
  513 +
  514 + if (!res)
  515 + return false;
  516 +
  517 + blockReader.setDevice(basis);
  518 + blockWriter.setDevice(basis);
  519 +
  520 + if (mode & QIODevice::WriteOnly) {
  521 + precompressedBlockWriter.open(QIODevice::WriteOnly);
  522 + }
  523 + else if (mode & QIODevice::ReadOnly) {
  524 +
  525 + // Read an initial compressed block from the underlying QIODevice,
  526 + // decompress, and set up a reader on it
  527 + QByteArray compressedBlock;
  528 + quint32 block_size;
  529 + blockReader >> block_size;
  530 + compressedBlock.resize(block_size);
  531 + int read_count = blockReader.readRawData(compressedBlock.data(), block_size);
  532 + if (read_count != int(block_size))
  533 + qFatal("Failed to read initial block");
  534 +
  535 + decompressedBlock = qUncompress(compressedBlock);
  536 +
  537 + decompressedBlockReader.setBuffer(&decompressedBlock);
  538 + decompressedBlockReader.open(QIODevice::ReadOnly);
  539 + }
  540 +
  541 + return true;
  542 +}
  543 +
  544 +void BlockCompression::close()
  545 +{
  546 + // flush output buffer, since we may have a partial block which hasn't been
  547 + // written to disk yet.
  548 + if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter.isOpen()) {
  549 + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer());
  550 + precompressedBlockWriter.close();
  551 +
  552 + quint32 bsize= compressedBlock.size();
  553 + blockWriter << bsize;
  554 + blockWriter.writeRawData(compressedBlock.constData(), compressedBlock.size());
  555 + }
  556 + // close the underlying device.
  557 + basis->close();
  558 +}
  559 +
  560 +void BlockCompression::setBasis(QIODevice *_basis)
  561 +{
  562 + basis = _basis;
  563 + blockReader.setDevice(basis);
  564 + blockWriter.setDevice(basis);
  565 +}
  566 +
  567 +// read from current decompressed block, if out of space, read and decompress another
  568 +// block from basis
  569 +qint64 BlockCompression::readData(char *data, qint64 remaining)
  570 +{
  571 + qint64 read = 0;
  572 + while (remaining > 0) {
  573 + // attempt to read the target amount of data
  574 + qint64 single_read = decompressedBlockReader.read(data, remaining);
  575 + if (single_read == -1)
  576 + qFatal("miss read");
  577 +
  578 + remaining -= single_read;
  579 + read += single_read;
  580 + data += single_read;
  581 +
  582 + // need a new block if we didn't get enough bytes from the previous read
  583 + if (remaining > 0) {
  584 + QByteArray compressedBlock;
  585 +
  586 + // read the size of the next block
  587 + quint32 block_size;
  588 + blockReader >> block_size;
  589 + if (block_size == 0)
  590 + break;
  591 +
  592 + compressedBlock.resize(block_size);
  593 + int actualRead = blockReader.readRawData(compressedBlock.data(), block_size);
  594 + if (actualRead != int(block_size))
  595 + qFatal("Bad read on nominal block size: %d, only got %d", block_size, int(remaining));
  596 +
  597 + decompressedBlock = qUncompress(compressedBlock);
  598 +
  599 + decompressedBlockReader.close();
  600 + decompressedBlockReader.setBuffer(&decompressedBlock);
  601 + decompressedBlockReader.open(QIODevice::ReadOnly);
  602 + }
  603 + }
  604 +
  605 + bool condition = blockReader.atEnd() && !basis->isReadable() ;
  606 + if (condition)
  607 + qWarning("Returning -1 from read");
  608 +
  609 + return condition ? -1 : read;
  610 +}
  611 +
  612 +bool BlockCompression::isSequential() const
  613 +{
  614 + return true;
  615 +}
  616 +
  617 +qint64 BlockCompression::writeData(const char *data, qint64 remaining)
  618 +{
  619 + const char * endPoint = data + remaining;
  620 + qint64 initial = remaining;
  621 +
  622 + qint64 written = 0;
  623 +
  624 + while (remaining > 0) {
  625 + // how much more can be put in this buffer?
  626 + qint64 capacity = blockSize - precompressedBlockWriter.pos();
  627 + if (capacity < 0)
  628 + qFatal("Negative capacity!!!");
  629 +
  630 + // don't try to write beyond capacity
  631 + qint64 write_size = qMin(capacity, remaining);
  632 +
  633 + qint64 singleWrite = precompressedBlockWriter.write(data, write_size);
  634 +
  635 + if (singleWrite == -1)
  636 + qFatal("matrix write failure?");
  637 +
  638 + remaining -= singleWrite;
  639 + data += singleWrite;
  640 + written += singleWrite;
  641 + if (data > endPoint)
  642 + qFatal("Wrote past the end");
  643 +
  644 + if (remaining > 0) {
  645 + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer(), -1);
  646 +
  647 + if (precompressedBlockWriter.buffer().size() != 0) {
  648 + quint32 block_size = compressedBlock.size();
  649 + blockWriter << block_size;
  650 +
  651 + int write_count = blockWriter.writeRawData(compressedBlock.constData(), block_size);
  652 + if (write_count != int(block_size))
  653 + qFatal("Didn't write enough data");
  654 + }
  655 + else
  656 + qFatal("serialized empty compressed block (?)");
  657 +
  658 + precompressedBlockWriter.close();
  659 + precompressedBlockWriter.open(QIODevice::WriteOnly);
  660 + }
  661 + }
  662 +
  663 + if (written != initial)
  664 + qFatal("didn't write enough bytes");
  665 +
  666 + bool condition = basis->isWritable();
  667 + if (!condition)
  668 + qWarning("Returning -1 from write");
  669 +
  670 + return basis->isWritable() ? written : -1;
  671 +}
  672 +
  673 +
  674 +
  675 +} // namespace QtUtils
  676 +
... ...
openbr/core/qtutils.h
1   -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2   - * Copyright 2012 The MITRE Corporation *
3   - * *
4   - * Licensed under the Apache License, Version 2.0 (the "License"); *
5   - * you may not use this file except in compliance with the License. *
6   - * You may obtain a copy of the License at *
7   - * *
8   - * http://www.apache.org/licenses/LICENSE-2.0 *
9   - * *
10   - * Unless required by applicable law or agreed to in writing, software *
11   - * distributed under the License is distributed on an "AS IS" BASIS, *
12   - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
13   - * See the License for the specific language governing permissions and *
14   - * limitations under the License. *
15   - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
16   -
17   -#ifndef QTUTILS_QTUTILS_H
18   -#define QTUTILS_QTUTILS_H
19   -
20   -#include <QBuffer>
21   -#include <QByteArray>
22   -#include <QDataStream>
23   -#include <QDir>
24   -#include <QFile>
25   -#include <QFileInfo>
26   -#include <QFuture>
27   -#include <QFutureSynchronizer>
28   -#include <QMap>
29   -#include <QString>
30   -#include <QStringList>
31   -#include <QThreadPool>
32   -#include <string>
33   -#include <vector>
34   -
35   -#include <openbr/openbr_export.h>
36   -
37   -namespace QtUtils
38   -{
39   - /**** File Utilities ****/
40   - QStringList readLines(const QString &file);
41   - void readFile(const QString &file, QStringList &lines);
42   - void readFile(const QString &file, QByteArray &data, bool uncompress = false);
43   - void writeFile(const QString &file, const QStringList &lines);
44   - void writeFile(const QString &file, const QString &data);
45   - void writeFile(const QString &file, const QByteArray &data, int compression = 0);
46   - void copyFile(const QString &src, const QString &dst);
47   -
48   - /**** Directory Utilities ****/
49   - void touchDir(const QDir &dir);
50   - void touchDir(const QFile &file);
51   - void touchDir(const QFileInfo &fileInfo);
52   - void emptyDir(QDir &dir);
53   - void deleteDir(QDir &dir);
54   - QString find(const QString &file, const QString &alt);
55   - QString getAbsolutePath(const QString &filename);
56   -
57   - /**** String Utilities ****/
58   - bool toBool(const QString &string);
59   - int toInt(const QString &string);
60   - float toFloat(const QString &string);
61   - QList<float> toFloats(const QStringList &strings);
62   - QStringList toStringList(const QList<float> &values);
63   - QStringList toStringList(const std::vector<std::string> &string_list);
64   - QStringList toStringList(int num_strings, const char* strings[]);
65   - QString shortTextHash(QString string);
66   - QStringList parse(QString args, char split = ',', bool *ok = NULL);
67   - void checkArgsSize(const QString &name, const QStringList &args, int min, int max);
68   - BR_EXPORT QPointF toPoint(const QString &string, bool *ok = NULL);
69   - BR_EXPORT QRectF toRect(const QString &string, bool *ok = NULL);
70   - QStringList naturalSort(const QStringList &strings);
71   - QString toTime(int s);
72   -
73   - /**** Process Utilities ****/
74   - bool runRScript(const QString &file);
75   - bool runDot(const QString &file);
76   - void showFile(const QString &file);
77   -
78   - /**** Variant Utilities ****/
79   - BR_EXPORT QString toString(const QVariant &variant);
80   - QString toString(const QVariantList &variantList);
81   - BR_EXPORT QString toString(const QVariantMap &QVariantMap);
82   - BR_EXPORT QStringList toStringList(const QVariantMap &QVariantMap);
83   -
84   - template <typename T>
85   - QVariantList toVariantList(const QList<T> &list)
86   - {
87   - QVariantList variantList;
88   - foreach (const T &item, list)
89   - variantList << item;
90   -
91   - return variantList;
92   - }
93   -
94   - /**** Point Utilities ****/
95   - float euclideanLength(const QPointF &point);
96   - float orientation(const QPointF &pointA, const QPointF &pointB);
97   -
98   - /**** Rect Utilities ****/
99   - float overlap(const QRectF &r, const QRectF &s);
100   -
101   -
102   - class BlockCompression : public QIODevice
103   - {
104   - public:
105   - BlockCompression(QIODevice *_basis);
106   - BlockCompression();
107   - int blockSize;
108   - QIODevice *basis;
109   -
110   - bool open(QIODevice::OpenMode mode);
111   -
112   - void close();
113   -
114   - void setBasis(QIODevice *_basis);
115   -
116   - QDataStream blockReader;
117   - QByteArray decompressedBlock;
118   - QBuffer decompressedBlockReader;
119   -
120   - // read from current decompressed block, if out of space, read and decompress another
121   - // block from basis
122   - qint64 readData(char *data, qint64 remaining);
123   -
124   - bool isSequential() const;
125   -
126   - // write to a QByteArray, when max block sized is reached, compress and write
127   - // it to basis
128   - QBuffer precompressedBlockWriter;
129   - QDataStream blockWriter;
130   - qint64 writeData(const char *data, qint64 remaining);
131   - };
132   -}
133   -
134   -#endif // QTUTILS_QTUTILS_H
  1 +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  2 + * Copyright 2012 The MITRE Corporation *
  3 + * *
  4 + * Licensed under the Apache License, Version 2.0 (the "License"); *
  5 + * you may not use this file except in compliance with the License. *
  6 + * You may obtain a copy of the License at *
  7 + * *
  8 + * http://www.apache.org/licenses/LICENSE-2.0 *
  9 + * *
  10 + * Unless required by applicable law or agreed to in writing, software *
  11 + * distributed under the License is distributed on an "AS IS" BASIS, *
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
  13 + * See the License for the specific language governing permissions and *
  14 + * limitations under the License. *
  15 + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  16 +
  17 +#ifndef QTUTILS_QTUTILS_H
  18 +#define QTUTILS_QTUTILS_H
  19 +
  20 +#include <QBuffer>
  21 +#include <QByteArray>
  22 +#include <QDataStream>
  23 +#include <QDir>
  24 +#include <QFile>
  25 +#include <QFileInfo>
  26 +#include <QFuture>
  27 +#include <QFutureSynchronizer>
  28 +#include <QMap>
  29 +#include <QString>
  30 +#include <QStringList>
  31 +#include <QThreadPool>
  32 +#include <string>
  33 +#include <vector>
  34 +
  35 +#include <openbr/openbr_export.h>
  36 +
  37 +namespace QtUtils
  38 +{
  39 + /**** File Utilities ****/
  40 + QStringList readLines(const QString &file);
  41 + void readFile(const QString &file, QStringList &lines);
  42 + void readFile(const QString &file, QByteArray &data, bool uncompress = false);
  43 + void writeFile(const QString &file, const QStringList &lines);
  44 + void writeFile(const QString &file, const QString &data);
  45 + void writeFile(const QString &file, const QByteArray &data, int compression = 0);
  46 + void copyFile(const QString &src, const QString &dst);
  47 +
  48 + /**** Directory Utilities ****/
  49 + void touchDir(const QDir &dir);
  50 + void touchDir(const QFile &file);
  51 + void touchDir(const QFileInfo &fileInfo);
  52 + void emptyDir(QDir &dir);
  53 + void deleteDir(QDir &dir);
  54 + QString find(const QString &file, const QString &alt);
  55 + QString getAbsolutePath(const QString &filename);
  56 +
  57 + /**** String Utilities ****/
  58 + bool toBool(const QString &string);
  59 + int toInt(const QString &string);
  60 + float toFloat(const QString &string);
  61 + QList<float> toFloats(const QStringList &strings);
  62 + QStringList toStringList(const QList<float> &values);
  63 + QStringList toStringList(const std::vector<std::string> &string_list);
  64 + QStringList toStringList(int num_strings, const char* strings[]);
  65 + QString shortTextHash(QString string);
  66 + QStringList parse(QString args, char split = ',', bool *ok = NULL);
  67 + void checkArgsSize(const QString &name, const QStringList &args, int min, int max);
  68 + BR_EXPORT QPointF toPoint(const QString &string, bool *ok = NULL);
  69 + BR_EXPORT QRectF toRect(const QString &string, bool *ok = NULL);
  70 + QStringList naturalSort(const QStringList &strings);
  71 + QString toTime(int s);
  72 +
  73 + /**** Process Utilities ****/
  74 + bool runRScript(const QString &file);
  75 + bool runDot(const QString &file);
  76 + void showFile(const QString &file);
  77 +
  78 + /**** Variant Utilities ****/
  79 + BR_EXPORT QString toString(const QVariant &variant);
  80 + QString toString(const QVariantList &variantList);
  81 + BR_EXPORT QString toString(const QVariantMap &QVariantMap);
  82 + BR_EXPORT QStringList toStringList(const QVariantMap &QVariantMap);
  83 +
  84 + template <typename T>
  85 + QVariantList toVariantList(const QList<T> &list)
  86 + {
  87 + QVariantList variantList;
  88 + foreach (const T &item, list)
  89 + variantList << item;
  90 +
  91 + return variantList;
  92 + }
  93 +
  94 + /**** Point Utilities ****/
  95 + float euclideanLength(const QPointF &point);
  96 + float orientation(const QPointF &pointA, const QPointF &pointB);
  97 +
  98 + /**** Rect Utilities ****/
  99 + float overlap(const QRectF &r, const QRectF &s);
  100 +
  101 +
  102 + class BlockCompression : public QIODevice
  103 + {
  104 + public:
  105 + BlockCompression(QIODevice *_basis);
  106 + BlockCompression();
  107 + int blockSize;
  108 + QIODevice *basis;
  109 +
  110 + bool open(QIODevice::OpenMode mode);
  111 +
  112 + void close();
  113 +
  114 + void setBasis(QIODevice *_basis);
  115 +
  116 + QDataStream blockReader;
  117 + QByteArray decompressedBlock;
  118 + QBuffer decompressedBlockReader;
  119 +
  120 + // read from current decompressed block, if out of space, read and decompress another
  121 + // block from basis
  122 + qint64 readData(char *data, qint64 remaining);
  123 +
  124 + bool isSequential() const;
  125 +
  126 + // write to a QByteArray, when max block sized is reached, compress and write
  127 + // it to basis
  128 + QBuffer precompressedBlockWriter;
  129 + QDataStream blockWriter;
  130 + qint64 writeData(const char *data, qint64 remaining);
  131 + };
  132 +}
  133 +
  134 +#endif // QTUTILS_QTUTILS_H
... ...