From df5b97785386a50b4d7e22bc14591f347ed7f3d5 Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Mon, 22 May 2017 22:26:28 -0400 Subject: [PATCH] Created QrEncode barcode backend. --- CMakeLists.txt | 18 +++++- cmake/Modules/FindLibQrencode.cmake | 40 ++++++++++++ glabels/BarcodeBackends.cpp | 53 +++++++++++---- glabels/BarcodeBackends.h | 16 ++--- glabels/BarcodeBackends/CMakeLists.txt | 30 +++++++++ glabels/BarcodeBackends/QrEncode.cpp | 89 ++++++++++++++++++++++++++ glabels/BarcodeBackends/QrEncode.h | 55 ++++++++++++++++ glabels/BarcodeMenu.cpp | 28 ++++++-- glabels/BarcodeStyle.cpp | 16 +++++ glabels/BarcodeStyle.h | 2 + glabels/CMakeLists.txt | 11 ++++ glabels/LabelModelBarcodeObject.cpp | 8 +-- glabels/Merge/CMakeLists.txt | 8 --- translations/glabels_C.ts | 40 ++++++------ 14 files changed, 355 insertions(+), 59 deletions(-) create mode 100644 cmake/Modules/FindLibQrencode.cmake create mode 100644 glabels/BarcodeBackends/CMakeLists.txt create mode 100644 glabels/BarcodeBackends/QrEncode.cpp create mode 100644 glabels/BarcodeBackends/QrEncode.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 3afa1e1..1cefe15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,11 @@ cmake_minimum_required (VERSION 2.8.12) ############################################################################### project (glabels) +# +# Path for locally defined cmake modules +# +set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") + #======================================= # Version Information @@ -44,6 +49,11 @@ endif () find_package(ZLIB 1.2 REQUIRED) +# +# Optional dependencies +# +find_package (LibQrencode QUIET) + #======================================= # Subdirectories @@ -67,10 +77,16 @@ message (STATUS "C++ Compiler ............ " ${CMAKE_CXX_COMPILER_ID} " " ${CMAK message (STATUS "Qt version .............. " ${Qt5Core_VERSION}) message (STATUS "zlib version ............ " ${ZLIB_VERSION_STRING}) +if (LIBQRENCODE_FOUND) + message (STATUS "qrencode (optional)...... " ${LIBQRENCODE_VERSION_STRING}) +else (LIBQRENCODE_FOUND) + message (STATUS "qrencode (optional)...... No.") +endif (LIBQRENCODE_FOUND) + if (MINGW) message (STATUS "MinGW location .......... " ${MINGW_BASE_DIR}) message (STATUS "MinGW Qt location ....... " ${QT_BASE_DIR}) -endif () +endif (MINGW) message (STATUS "") diff --git a/cmake/Modules/FindLibQrencode.cmake b/cmake/Modules/FindLibQrencode.cmake new file mode 100644 index 0000000..ec2724a --- /dev/null +++ b/cmake/Modules/FindLibQrencode.cmake @@ -0,0 +1,40 @@ +# - Try to find the LibQrencode QRCode generator library +# Once done this will define +# +# LIBQRENCODE_FOUND - System has LibQrencode +# LIBQRENCODE_INCLUDE_DIR - The LibQrencode include directory +# LIBQRENCODE_LIBRARIES - The libraries needed to use LibQrencode +# LIBQRENCODE_DEFINITIONS - Compiler switches required for using LibQrencode +# LIBQRENCODE_XMLLINT_EXECUTABLE - The XML checking tool xmllint coming with LibQrencode +# LIBQRENCODE_VERSION_STRING - the version of LibQrencode found + +# use pkg-config to get the directories and then use these values with find_path() and find_library() +find_package(PkgConfig QUIET) +PKG_CHECK_MODULES(PC_LIBQRENCODE QUIET libqrencode) +set(LIBQRENCODE_DEFINITIONS ${PC_LIBQRENCODE_CFLAGS_OTHER}) + +find_path(LIBQRENCODE_INCLUDE_DIR NAMES qrencode.h + HINTS + ${PC_LIBQRENCODE_INCLUDEDIR} + ${PC_LIBQRENCODE_INCLUDE_DIRS} + PATH_SUFFIXES libqrencode + ) + +find_library(LIBQRENCODE_LIBRARIES NAMES qrencode libqrencode + HINTS + ${PC_LIBQRENCODE_LIBDIR} + ${PC_LIBQRENCODE_LIBRARY_DIRS} + ) + +if(PC_LIBQRENCODE_VERSION) + set(LIBQRENCODE_VERSION_STRING ${PC_LIBQRENCODE_VERSION}) +endif() + +# handle the QUIETLY and REQUIRED arguments and set LIBQRENCODE_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibQrencode + REQUIRED_VARS LIBQRENCODE_LIBRARIES LIBQRENCODE_INCLUDE_DIR + VERSION_VAR LIBQRENCODE_VERSION_STRING) + +mark_as_advanced(LIBQRENCODE_INCLUDE_DIR LIBQRENCODE_LIBRARIES) diff --git a/glabels/BarcodeBackends.cpp b/glabels/BarcodeBackends.cpp index 215ee5b..48956dc 100644 --- a/glabels/BarcodeBackends.cpp +++ b/glabels/BarcodeBackends.cpp @@ -20,6 +20,12 @@ #include "BarcodeBackends.h" +#include "glbarcode/Factory.h" + +#if HAVE_QRENCODE +#include "BarcodeBackends/QrEncode.h" +#endif // HAVE_QRENCODE + namespace glabels { @@ -27,9 +33,8 @@ namespace glabels // // Static data // - BarcodeBackends::BackendMap BarcodeBackends::mBackendIdMap; - BarcodeBackends::BackendMap BarcodeBackends::mBackendNameMap; - QList BarcodeBackends::mBackendNameList; + QStringList BarcodeBackends::mBackendIdList; + QMap BarcodeBackends::mBackendNameMap; QList BarcodeBackends::mStyleList; @@ -66,11 +71,20 @@ namespace glabels registerStyle( "onecode", "", tr("USPS Intelligent Mail"), false, false, true, false, "12345678901234567890", false, 20 ); - registerStyle( "datamatrix", "", tr("DataMatrix"), + registerStyle( "datamatrix", "", tr("IEC16022 (DataMatrix)"), false, false, true, false, "1234567890AB", false, 12 ); - registerStyle( "qrcode", "", tr("QRCode"), +#if HAVE_QRENCODE + // + // Libqrencode backend + // + registerBackend( "qrencode", "QREncode" ); + + glbarcode::Factory::registerType( "qrencode::qrcode", barcode::QrEncode::createQrCode ); + + registerStyle( "qrcode", "qrencode", tr("IEC18004 (QRCode)"), false, false, true, false, "1234567890AB", false, 12 ); +#endif // HAVE_QRENCODE } @@ -86,6 +100,18 @@ namespace glabels } + const QStringList& BarcodeBackends::backendList() + { + return mBackendIdList; + } + + + QString BarcodeBackends::backendName( const QString& backendId ) + { + return mBackendNameMap[ backendId ]; + } + + const QList& BarcodeBackends::styleList() { return mStyleList; @@ -112,29 +138,28 @@ namespace glabels } - void BarcodeBackends::registerBackend( QString& id, QString& name) + void BarcodeBackends::registerBackend( const QString& backendId, const QString& backendName ) { - mBackendNameList.append( name ); - mBackendIdMap.insert( id, name ); - mBackendNameMap.insert( name, id ); + mBackendIdList.append( backendId ); + mBackendNameMap[ backendId ] = backendName; } - void BarcodeBackends::registerStyle( const char* id, - const char* backendId, + void BarcodeBackends::registerStyle( const QString& id, + const QString& backendId, const QString& name, bool canText, bool textOptional, bool canChecksum, bool checksumOptional, - const char* defaultDigits, + const QString& defaultDigits, bool canFreeForm, int preferedN ) { - BarcodeStyle style( QString(id), QString(backendId), name, + BarcodeStyle style( id, backendId, name, canText, textOptional, canChecksum, checksumOptional, - QString(defaultDigits), + defaultDigits, canFreeForm, preferedN ); mStyleList.append( style ); diff --git a/glabels/BarcodeBackends.h b/glabels/BarcodeBackends.h index 2cf3714..0704191 100644 --- a/glabels/BarcodeBackends.h +++ b/glabels/BarcodeBackends.h @@ -54,6 +54,8 @@ namespace glabels // Public Methods ///////////////////////////////// public: + static const QStringList& backendList(); + static QString backendName( const QString& backendId ); static const QList& styleList(); static const BarcodeStyle& defaultStyle(); static const BarcodeStyle& style( const QString& backendId, const QString& StyleId ); @@ -63,16 +65,16 @@ namespace glabels // Private Methods ///////////////////////////////// private: - static void registerBackend( QString &id, QString &name); + static void registerBackend( const QString &backendId, const QString &backendName ); - static void registerStyle( const char* id, - const char* backendId, + static void registerStyle( const QString& id, + const QString& backendId, const QString& name, bool canText, bool textOptional, bool canChecksum, bool checksumOptional, - const char* defaultDigits, + const QString& defaultDigits, bool canFreeForm, int preferedN ); @@ -80,10 +82,8 @@ namespace glabels ///////////////////////////////// // Private Members ///////////////////////////////// - typedef QMap BackendMap; - static BackendMap mBackendIdMap; - static BackendMap mBackendNameMap; - static QList mBackendNameList; + static QStringList mBackendIdList; + static QMap mBackendNameMap; static QList mStyleList; diff --git a/glabels/BarcodeBackends/CMakeLists.txt b/glabels/BarcodeBackends/CMakeLists.txt new file mode 100644 index 0000000..933123a --- /dev/null +++ b/glabels/BarcodeBackends/CMakeLists.txt @@ -0,0 +1,30 @@ +#======================================= +# Sources +#======================================= +set (barcode_sources + QrEncode.cpp +) + +add_library (Barcode STATIC + ${barcode_sources} +) + + +#======================================= +# Where to find stuff +#======================================= +include_directories ( +) + +link_directories ( +) + + +#======================================= +# Subdirectories +#======================================= + + +#======================================= +# Install +#======================================= diff --git a/glabels/BarcodeBackends/QrEncode.cpp b/glabels/BarcodeBackends/QrEncode.cpp new file mode 100644 index 0000000..bd5b27a --- /dev/null +++ b/glabels/BarcodeBackends/QrEncode.cpp @@ -0,0 +1,89 @@ +/* QrEncode.cpp + * + * Copyright (C) 2017 Jim Evins + * + * This file is part of gLabels-qt. + * + * gLabels-qt is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * gLabels-qt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gLabels-qt. If not, see . + */ + +#if HAVE_QRENCODE + +#include "QrEncode.h" + +#include "qrencode.h" + + +namespace glabels +{ + namespace barcode + { + + /* + * Static QrCode barcode creation method + */ + glbarcode::Barcode* QrEncode::createQrCode() + { + return new QrEncode(); + } + + + /* + * QrEncode data validation, implements glbarcode::Barcode2dBase::validate() + */ + bool QrEncode::validate( const std::string& rawData ) + { + if ( rawData.size() == 0 ) + { + return false; + } + return true; + } + + + /* + * QrEncode data encoding, implements glbarcode::Barcode2dBase::encode() + */ + bool QrEncode::encode( const std::string& cookedData, glbarcode::Matrix& encodedData ) + { + QRcode *qrcode = QRcode_encodeString( cookedData.c_str(), 0, QR_ECLEVEL_M, QR_MODE_8, 1 ); + if ( qrcode == NULL ) + { + return false; + } + + + int w = qrcode->width; + encodedData.resize( w, w ); + + + for ( int iy = 0; iy < w; iy++ ) + { + for ( int ix = 0; ix < w; ix++ ) + { + encodedData[iy][ix] = qrcode->data[ iy*w + ix ] & 0x01; + } + } + + + QRcode_free( qrcode ); + QRcode_clearCache(); + + return true; + } + + } +} + +#endif // HAVE_QRENCODE diff --git a/glabels/BarcodeBackends/QrEncode.h b/glabels/BarcodeBackends/QrEncode.h new file mode 100644 index 0000000..a266d1e --- /dev/null +++ b/glabels/BarcodeBackends/QrEncode.h @@ -0,0 +1,55 @@ +/* QrEncode.h + * + * Copyright (C) 2017 Jim Evins + * + * This file is part of gLabels-qt. + * + * gLabels-qt is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * gLabels-qt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with gLabels-qt. If not, see . + */ + +#ifndef barcode_QrEncode_h +#define barcode_QrEncode_h + + +#include "glbarcode/Barcode2dBase.h" + + +namespace glabels +{ + namespace barcode + { + + /** + * LibQREncode barcode backend + * + * Implements glbarcode::Barcode2dBase. + */ + class QrEncode : public glbarcode::Barcode2dBase + { + public: + static Barcode* createQrCode(); + + + private: + bool validate( const std::string& rawData ) override; + + bool encode( const std::string& cookedData, + glbarcode::Matrix& encodedData ) override; + + }; + + } +} + +#endif // barcode_QrEncode_h diff --git a/glabels/BarcodeMenu.cpp b/glabels/BarcodeMenu.cpp index 5a023d6..7297af6 100644 --- a/glabels/BarcodeMenu.cpp +++ b/glabels/BarcodeMenu.cpp @@ -36,11 +36,31 @@ namespace glabels { foreach ( const BarcodeStyle& bcStyle, BarcodeBackends::styleList() ) { - BarcodeMenuItem* bcMenuItem = new BarcodeMenuItem( bcStyle ); - connect( bcMenuItem, SIGNAL(activated(const BarcodeStyle&)), - this, SLOT(onMenuItemActivated(const BarcodeStyle&)) ); + if ( bcStyle.backendId() == "" ) + { + BarcodeMenuItem* bcMenuItem = new BarcodeMenuItem( bcStyle ); + connect( bcMenuItem, SIGNAL(activated(const BarcodeStyle&)), + this, SLOT(onMenuItemActivated(const BarcodeStyle&)) ); - addAction( bcMenuItem ); + addAction( bcMenuItem ); + } + } + + foreach ( const QString& backendId, BarcodeBackends::backendList() ) + { + QMenu* subMenu = addMenu( BarcodeBackends::backendName( backendId ) ); + + foreach ( const BarcodeStyle& bcStyle, BarcodeBackends::styleList() ) + { + if ( bcStyle.backendId() == backendId ) + { + BarcodeMenuItem* bcMenuItem = new BarcodeMenuItem( bcStyle ); + connect( bcMenuItem, SIGNAL(activated(const BarcodeStyle&)), + this, SLOT(onMenuItemActivated(const BarcodeStyle&)) ); + + subMenu->addAction( bcMenuItem ); + } + } } } diff --git a/glabels/BarcodeStyle.cpp b/glabels/BarcodeStyle.cpp index f41f4ea..9c510eb 100644 --- a/glabels/BarcodeStyle.cpp +++ b/glabels/BarcodeStyle.cpp @@ -80,6 +80,22 @@ namespace glabels } + /// + /// Full ID Property Getter + /// + QString BarcodeStyle::fullId() const + { + if ( mBackendId == "" ) + { + return mId; + } + else + { + return mBackendId + "::" + mId; + } + } + + /// /// Backend ID Property Getter /// diff --git a/glabels/BarcodeStyle.h b/glabels/BarcodeStyle.h index d09819a..8512853 100644 --- a/glabels/BarcodeStyle.h +++ b/glabels/BarcodeStyle.h @@ -57,6 +57,8 @@ namespace glabels ///////////////////////////////// const QString& id() const; + QString fullId() const; + const QString& backendId() const; const QString& name() const; diff --git a/glabels/CMakeLists.txt b/glabels/CMakeLists.txt index fd6d289..9ebd762 100644 --- a/glabels/CMakeLists.txt +++ b/glabels/CMakeLists.txt @@ -11,6 +11,13 @@ endif () # Uncomment to build with pedantic flags #add_compile_options (-Werror -Wall -Wpedantic) +if (${LIBQRENCODE_FOUND}) + add_definitions (-DHAVE_QRENCODE=1) +else (${LIBQRENCODE_FOUND}) + set (LIBQRENCODE_INCLUDE_DIR "") + set (LIBQRENCODE_LIBRARIES "") +endif (${LIBQRENCODE_FOUND}) + #======================================= # Auto-generate Version.h @@ -177,6 +184,7 @@ add_executable (glabels-qt WIN32 ) target_link_libraries (glabels-qt + Barcode Merge glbarcode ${Qt5Widgets_LIBRARIES} @@ -184,6 +192,7 @@ target_link_libraries (glabels-qt ${Qt5Xml_LIBRARIES} ${Qt5Svg_LIBRARIES} ${ZLIB_LIBRARIES} + ${LIBQRENCODE_LIBRARIES} ) @@ -197,6 +206,7 @@ include_directories ( ${Qt5PrintSupport_INCLUDE_DIRS} ${Qt5Xml_INCLUDE_DIRS} ${Qt5Svg_INCLUDE_DIRS} + ${LIBQRENCODE_INCLUDE_DIR} ) link_directories ( @@ -206,6 +216,7 @@ link_directories ( #======================================= # Subdirectories #======================================= +add_subdirectory (BarcodeBackends) add_subdirectory (Merge) diff --git a/glabels/LabelModelBarcodeObject.cpp b/glabels/LabelModelBarcodeObject.cpp index 94b11b9..c48fa82 100644 --- a/glabels/LabelModelBarcodeObject.cpp +++ b/glabels/LabelModelBarcodeObject.cpp @@ -363,10 +363,10 @@ namespace glabels { delete mEditorBarcode; } - mEditorBarcode = glbarcode::Factory::createBarcode( mBcStyle.id().toStdString() ); + mEditorBarcode = glbarcode::Factory::createBarcode( mBcStyle.fullId().toStdString() ); if ( !mEditorBarcode ) { - qWarning() << "Invalid barcode style" << mBcStyle.id() << "using \"code39\"."; + qWarning() << "Invalid barcode style" << mBcStyle.fullId() << "using \"code39\"."; mBcStyle = BarcodeBackends::defaultStyle(); mEditorBarcode = glbarcode::Factory::createBarcode( mBcStyle.id().toStdString() ); } @@ -382,10 +382,10 @@ namespace glabels { delete mEditorDefaultBarcode; } - mEditorDefaultBarcode = glbarcode::Factory::createBarcode( mBcStyle.id().toStdString() ); + mEditorDefaultBarcode = glbarcode::Factory::createBarcode( mBcStyle.fullId().toStdString() ); if ( !mEditorDefaultBarcode ) { - qWarning() << "Invalid barcode style" << mBcStyle.id() << "using \"code39\"."; + qWarning() << "Invalid barcode style" << mBcStyle.fullId() << "using \"code39\"."; mBcStyle = BarcodeBackends::defaultStyle(); mEditorDefaultBarcode = glbarcode::Factory::createBarcode( mBcStyle.id().toStdString() ); } diff --git a/glabels/Merge/CMakeLists.txt b/glabels/Merge/CMakeLists.txt index b800602..c06693a 100644 --- a/glabels/Merge/CMakeLists.txt +++ b/glabels/Merge/CMakeLists.txt @@ -1,11 +1,3 @@ -cmake_minimum_required (VERSION 2.8.12) - -############################################################################### -# gLabels Merge subsystem -############################################################################### -project (Merge CXX) - - #======================================= # Sources #======================================= diff --git a/translations/glabels_C.ts b/translations/glabels_C.ts index 410af72..41e774b 100644 --- a/translations/glabels_C.ts +++ b/translations/glabels_C.ts @@ -744,65 +744,65 @@ glabels::BarcodeBackends - + POSTNET (any) - + POSTNET-5 (ZIP only) - + POSTNET-9 (ZIP+4) - + POSTNET-11 (DPBC) - + CEPNET - + USPS Intelligent Mail - + + IEC16022 (DataMatrix) + + + + + IEC18004 (QRCode) + + + + Code 39 - + Code 39 Extended - + UPC-A - + EAN-13 - - - DataMatrix - - - - - QRCode - - glabels::ColorPaletteDialog