Add error handling when QImage::load fails.
[toast/barcode2cash.git] / qtapp / barcode2cash / mainwindow.cpp
index 94285c256edeb20f2b3d86cd77e869aed2fd333a..bd5717e73df8025061d5c7e8a486ab14f732d735 100644 (file)
@@ -1,8 +1,39 @@
+#include <cstddef>
+#include <zbar.h>
 #include "mainwindow.h"
 #include "ui_mainwindow.h"
-#include <QCameraInfo>
-#include <QCameraImageCapture>
-#include <QCameraViewfinder>
+
+
+/// converts a string like "123,45" (comma as decimal point) to 12345.
+bool cashstr_to_currencycent(QString cash, CurrencyCent& cent) {
+    bool ok;
+    cent = cash.replace(",", "").toInt(&ok);
+    return ok;
+}
+
+
+/// returns true if the decoding was successful
+bool decode_rksv(const QString& rksv_string, RksvParts& rksv_parts) {
+    // https://github.com/a-sit-plus/at-registrierkassen-mustercode/releases/download/1.2-DOK/2016-09-05-Detailfragen-RKSV-V1.2.pdf
+    auto parts = rksv_string.split("_");
+    if (parts.size() != 14) return false; // QR code found but not RKSV
+    if (!parts.takeFirst().isEmpty()) return false;
+    rksv_parts.rlat = parts.takeFirst();
+    if (!rksv_parts.rlat.startsWith("R1-")) return false; // e.g. "R1-AT1"
+    rksv_parts.device_id = parts.takeFirst(); // e.g. "603002101"
+    rksv_parts.receipt_id = parts.takeFirst(); // e.g. "1/603002101/691/10340"
+    rksv_parts.date_time = QDateTime::fromString(parts.takeFirst(), "yyyy-MM-ddThh:mm:ss");
+    if (!rksv_parts.date_time.isValid()) return false;
+    for (int i = 0; i != RksvParts::cash_count; ++i) {
+        if (!cashstr_to_currencycent(parts.takeFirst(), rksv_parts.cash[i])) return false;
+    }
+    rksv_parts.counter = parts.takeFirst(); // e.g. "9IY7hV1mTqhVd4bii4gIhw=="
+    rksv_parts.cert_serial = parts.takeFirst();  // e.g. "5660C34F"
+    rksv_parts.sig_prev = parts.takeFirst(); // e.g. "I8/Wa2TZWgw="
+    rksv_parts.sig = parts.takeFirst(); // e.g."eSmlrKimgzbtYBJXq0MzwmgI3fBDL+NfSjzfFCCdcZuoHC+LET8BGvmVGWAwmNSZnDD2tCewJ7AooQc0Bt0HcQ=="
+    return true;
+}
+
 
 bool checkCameraAvailability()
 {
@@ -20,23 +51,96 @@ MainWindow::MainWindow(QWidget *parent) :
 
     QCameraInfo info = QCameraInfo::defaultCamera();
     if (!info.isNull()) {
-        QCamera* camera = new QCamera(info);
+        camera = new QCamera(info);
         camera->setCaptureMode(QCamera::CaptureStillImage);
-        QCameraViewfinder* viewfinder = new QCameraViewfinder;
-        camera->setViewfinder(viewfinder);
-        viewfinder->show();
-        QCameraImageCapture imageCapture(camera);
+        camera->setViewfinder(ui->viewFinder);
+        imageCapture = new QCameraImageCapture(camera);
+        connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), SLOT(updateCameraInfo()));
+        connect(imageCapture, SIGNAL(imageSaved(int,QString)), SLOT(showCaptureSuccess(int,QString)));
+        connect(imageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)), SLOT(showCaptureError(int,QCameraImageCapture::Error,QString)));
+        updateCameraInfo();
+        connect(ui->pbCapture, SIGNAL(clicked()), SLOT(capture()));
+        QImageEncoderSettings imageSettings;
+        imageSettings.setCodec("image/jpeg");
+        imageCapture->setEncodingSettings(imageSettings);
         camera->start();
-        camera->searchAndLock();
-        imageCapture.capture("test.png");
-        camera->unlock();
-        //delete camera;
     }
 
+
     ui->statusBar->showMessage(tr("There are %1 cameras").arg(checkCameraAvailability()));
+
 }
 
-MainWindow::~MainWindow()
-{
+MainWindow::~MainWindow() {
+    delete imageCapture;
+    delete camera;
     delete ui;
 }
+
+
+void MainWindow::updateRksv(const RksvParts& rksv) {
+    ui->le_rlat->setText(rksv.rlat);
+    ui->le_device_id->setText(rksv.device_id);
+    ui->le_receipt_id->setText(rksv.receipt_id);
+    ui->dte_date_time->setDateTime(rksv.date_time);
+    ui->le_counter->setText(rksv.counter);
+    ui->le_cert_serial->setText(rksv.cert_serial);
+    ui->le_sig_prev->setText(rksv.sig_prev);
+    ui->le_sig->setText(rksv.sig);
+    for (int i = 0; i != RksvParts::cash_count; ++i) {
+        QString text = tr("%1").arg(double(rksv.cash[i]) / 100);
+        QTableWidgetItem* item = new QTableWidgetItem(text);
+        ui->twCash->setItem(i, 0, item);
+    }
+}
+
+
+void MainWindow::updateCameraInfo() {
+    ui->labCameraReady->setText(imageCapture->isReadyForCapture() ? "ready" : "not ready");
+}
+
+
+void MainWindow::capture() {
+    camera->searchAndLock();
+    imageCapture->capture("test.jpg");
+    camera->unlock();
+}
+
+
+void MainWindow::showCaptureSuccess(int, QString fileName) {
+    ui->statusBar->showMessage(tr("Image captured and saved as '%1'.").arg(fileName));
+}
+
+
+void MainWindow::showCaptureError(int, QCameraImageCapture::Error error, QString errorString) {
+    ui->statusBar->showMessage(tr("Error when capturing image (error id %2): %1.").arg(errorString).arg(error));
+}
+
+
+void MainWindow::analyze() {
+    QImage qimage("test.jpg");
+    if (qimage.isNull()) {
+        ui->labAnalyzeImage->setText("Can't read image");
+        return;
+    }
+    qimage = qimage.convertToFormat(QImage::Format_Grayscale8);
+    auto zbimage = zbar::Image(qimage.width(), qimage.height(), "GREY", qimage.constBits(), qimage.byteCount());
+    auto scanner = zbar::ImageScanner();
+    auto scan_results = scanner.scan(zbimage);
+    if (scan_results > 0) {
+        auto results = scanner.get_results();
+        for (auto resit = results.symbol_begin(); resit != results.symbol_end(); ++ resit) {
+            if (resit->get_type() == zbar::ZBAR_QRCODE) {
+                QString qrcode_data = QString::fromStdString(resit->get_data());
+                RksvParts rksv_parts;
+                if (decode_rksv(qrcode_data, rksv_parts)) {
+                    updateRksv(rksv_parts);
+                    break;
+                }
+            }
+        }
+    }
+
+    if (qimage.width() > 500) qimage = qimage.scaledToWidth(500);
+    ui->labAnalyzeImage->setPixmap(QPixmap::fromImage(qimage));
+}