From 965c7a382e61086539d52523517f0fa6a4c52051 Mon Sep 17 00:00:00 2001 From: Stefan Brand Date: Sun, 16 Feb 2014 21:41:36 +0100 Subject: [PATCH] Finished up QR-Code Reader Integration --- qml/components/NotifyBanner.qml | 2 +- qml/pages/About.qml | 4 +- qml/pages/AddOTP.qml | 2 +- qml/pages/ExportPage.qml | 15 +++++- qml/pages/MainView.qml | 13 +---- qml/pages/ScanOTP.qml | 91 ++++++++++++++++++++++++++------- src/fileio.cpp | 40 +++++++++++++++ src/fileio.h | 30 +++++++++++ src/harbour-sailotp.cpp | 3 +- 9 files changed, 165 insertions(+), 35 deletions(-) diff --git a/qml/components/NotifyBanner.qml b/qml/components/NotifyBanner.qml index 3274ec3..4f15db2 100644 --- a/qml/components/NotifyBanner.qml +++ b/qml/components/NotifyBanner.qml @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/qml/pages/About.qml b/qml/pages/About.qml index a0c139e..48a748c 100644 --- a/qml/pages/About.qml +++ b/qml/pages/About.qml @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -85,7 +85,7 @@ Page { font.pixelSize: Theme.fontSizeSmall horizontalAlignment: TextEdit.Center readOnly: true - text: qsTr("SailOTP uses the following third party libs:")+"\n\nhttp://caligatio.github.io/jsSHA/\nhttps://github.com/mdp/gibberish-aes" + text: qsTr("SailOTP uses the following third party libs:")+"\n\nhttp://caligatio.github.io/jsSHA/\nhttps://github.com/mdp/gibberish-aes/\nhttp://sourceforge.net/projects/qzxing/" color: "white" } } diff --git a/qml/pages/AddOTP.qml b/qml/pages/AddOTP.qml index c28df00..300190d 100644 --- a/qml/pages/AddOTP.qml +++ b/qml/pages/AddOTP.qml @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, diff --git a/qml/pages/ExportPage.qml b/qml/pages/ExportPage.qml index 2513dca..ea60aaa 100644 --- a/qml/pages/ExportPage.qml +++ b/qml/pages/ExportPage.qml @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -84,6 +84,19 @@ Dialog { id: exportFlickable anchors.fill: parent + PullDownMenu { + MenuItem { + text: mode == "export" ? qsTr("Import") : qsTr("Export") + onClicked: { + if (mode == "export") { + mode = "import" + } else { + mode = "export" + } + } + } + } + VerticalScrollDecorator {} Column { diff --git a/qml/pages/MainView.qml b/qml/pages/MainView.qml index d73454d..9984930 100644 --- a/qml/pages/MainView.qml +++ b/qml/pages/MainView.qml @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -103,20 +103,11 @@ Page { onClicked: pageStack.push(Qt.resolvedUrl("About.qml")) } MenuItem { - text: qsTr("Export Token-DB") + text: qsTr("Export / Import") onClicked: pageStack.push(Qt.resolvedUrl("ExportPage.qml"), {parentPage: mainPage, mode: "export"}) } - MenuItem { - text: qsTr("Import Token-DB") - onClicked: pageStack.push(Qt.resolvedUrl("ExportPage.qml"), {parentPage: mainPage, mode: "import"}) - } MenuItem { text: qsTr("Add Token") - onClicked: pageStack.push(Qt.resolvedUrl("AddOTP.qml"), {parentPage: mainPage}) - } - - MenuItem { - text: qsTr("Scan Token") onClicked: pageStack.push(Qt.resolvedUrl("ScanOTP.qml"), {parentPage: mainPage}) } } diff --git a/qml/pages/ScanOTP.qml b/qml/pages/ScanOTP.qml index 42c6a73..a6f6c73 100644 --- a/qml/pages/ScanOTP.qml +++ b/qml/pages/ScanOTP.qml @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -32,6 +32,7 @@ import QtMultimedia 5.0 import Sailfish.Silica 1.0 import Sailfish.Media 1.0 // Not allowed in harbour, but normal VideoOutput doesn't work yet! import harbour.sailotp.QZXing 2.2 +import harbour.sailotp.FileIO 1.0 import "../lib/urldecoder.js" as URL Page { @@ -39,9 +40,44 @@ Page { property QtObject parentPage: null + Timer { + id: scanTimer + interval: 100 + running: false + repeat: false + onTriggered: { + if (fileIO.mkpath(XDG_CACHE_DIR)) { + busy.running = true + cam.imageCapture.captureToLocation(XDG_CACHE_DIR + "/qrscan.jpg"); + } else { + notify.show(qsTr("Can't access temporary directory"), 3000); + } + } + } + SilicaFlickable { anchors.fill: parent + PullDownMenu { + MenuItem { + text: qsTr("Add manually") + onClicked: pageStack.replace(Qt.resolvedUrl("AddOTP.qml"), {parentPage: parentPage, paramNew: true}) + } + } + + PageHeader { + id: header + title: "Scan Code" + } + + BusyIndicator { + id: busy + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + anchors.topMargin: 16 + running: false + } + Camera { id: cam @@ -51,24 +87,12 @@ Page { imageCapture { onImageSaved: { - decoder.decodeImageFromFile("/tmp/qrscan.jpg"); + decoder.decodeImageFromFile(XDG_CACHE_DIR + "/qrscan.jpg"); } } } - GStreamerVideoOutput { - id: videoPreview - anchors.centerIn: parent - source: cam - MouseArea { - anchors.fill: parent - onClicked: { - cam.imageCapture.captureToLocation("/tmp/qrscan.jpg"); - } - } - } - - QZXing{ + QZXing { id: decoder enabledDecoders: QZXing.DecoderFormat_QR_CODE @@ -77,14 +101,45 @@ Page { onTagFound: { console.log("Barcode data: " + tag) var ret = URL.decode(tag); - if (ret.type != "" && ret.title != "" && ret.secret != "" && (ret.counter != "" || ret.type == "TOTP ")) { + busy.running = false + if (ret && ret.type != "" && ret.title != "" && ret.secret != "" && (ret.counter != "" || ret.type == "TOTP")) { pageStack.replace(Qt.resolvedUrl("AddOTP.qml"), {parentPage: parentPage, paramLabel: ret.title, paramKey: ret.secret, paramType: ret.type, paramCounter: ret.counter, paramNew: true}) } else { - notify.show(qsTr("Error decoding QR-Code"), 3000); + notify.show(qsTr("No valid Token data found."), 3000); } } - onDecodingFinished: console.log("Decoding finished " + (succeeded==true ? "successfully" : "unsuccessfully") ) + onDecodingFinished: if (succeeded==false) scanTimer.start(); + } + + FileIO { + id: fileIO + } + + GStreamerVideoOutput { + id: prev + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: header.bottom + source: cam + MouseArea { + anchors.fill: parent + onClicked: scanTimer.start(); + } + } + + Text { + id: text + + anchors.top: prev.bottom + anchors.topMargin: 32 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width - 2*Theme.paddingLarge + + wrapMode: Text.Wrap + maximumLineCount: 4 + font.pixelSize: Theme.fontSizeSmall + color: Theme.primaryColor + text: qsTr("Tap the picture to start scanning. Pull down to add Token manually.") } } } diff --git a/src/fileio.cpp b/src/fileio.cpp index 9793d60..146bc74 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -1,5 +1,35 @@ +/* + * Copyright (c) 2014, Stefan Brand + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. The names of the contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include "fileio.h" #include +#include #include FileIO::FileIO(QObject *parent) : @@ -71,3 +101,13 @@ bool FileIO::exists(const QString& filename) QFile file(filename); return file.exists(); } + +bool FileIO::mkpath(const QString& dirpath) { + if (dirpath.isEmpty()) { + emit error("Source is empty!"); + return false; + } + + QDir dir(dirpath); + return dir.mkpath(dirpath); +} diff --git a/src/fileio.h b/src/fileio.h index e8c67c2..b78f46c 100644 --- a/src/fileio.h +++ b/src/fileio.h @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2014, Stefan Brand + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * 3. The names of the contributors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef FILEIO_H #define FILEIO_H @@ -18,6 +47,7 @@ public: Q_INVOKABLE bool write(const QString& data); Q_INVOKABLE bool exists(); Q_INVOKABLE bool exists(const QString& filename); + Q_INVOKABLE bool mkpath(const QString& dirpath); QString source() { return mSource; }; diff --git a/src/harbour-sailotp.cpp b/src/harbour-sailotp.cpp index e90620d..2652ca6 100644 --- a/src/harbour-sailotp.cpp +++ b/src/harbour-sailotp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Stefan Brand + * Copyright (c) 2014, Stefan Brand * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -61,6 +61,7 @@ int main(int argc, char *argv[]) // Prepare the QML and set Homedir view->setSource(SailfishApp::pathTo("qml/harbour-sailotp.qml")); view->rootContext()->setContextProperty("XDG_HOME_DIR", QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + view->rootContext()->setContextProperty("XDG_CACHE_DIR", QStandardPaths::writableLocation(QStandardPaths::CacheLocation)); view->show(); // Run the app