diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *~ +*.qmlc +*.kdev4 diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set(REQUIRED_QT_VERSION 5.7.0) find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG REQUIRED Core Gui) +find_package(Qt5 ${REQUIRED_QT_VERSION} CONFIG OPTIONAL_COMPONENTS Quick) find_package(QRencode) set_package_properties(QRencode PROPERTIES TYPE REQUIRED) find_package(Dmtx) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,5 @@ add_subdirectory(lib) add_subdirectory(tools) +if(TARGET Qt5::Quick) + add_subdirectory(quick) +endif() diff --git a/src/quick/CMakeLists.txt b/src/quick/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/quick/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(prisonquickplugin SHARED + barcodequickitem.cpp + prisonquickplugin.cpp +) +target_link_libraries(prisonquickplugin PRIVATE Qt5::Quick KF5::Prison) +install(TARGETS prisonquickplugin DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/prison) +install(FILES qmldir DESTINATION ${KDE_INSTALL_QMLDIR}/org/kde/prison) diff --git a/src/quick/barcodequickitem.h b/src/quick/barcodequickitem.h new file mode 100644 --- /dev/null +++ b/src/quick/barcodequickitem.h @@ -0,0 +1,94 @@ +/* + Copyright (c) 2018 Volker Krause + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#ifndef PRISON_BARCODEQUICKITEM_H +#define PRISON_BARCODEQUICKITEM_H + +#include + +#include +#include + +#include + +namespace Prison { + +class AbstractBarcode; + +class BarcodeQuickItem : public QQuickPaintedItem +{ + Q_OBJECT + Q_PROPERTY(QString content READ content WRITE setContent NOTIFY contentChanged) + Q_PROPERTY(BarcodeType barcodeType READ barcodeType WRITE setBarcodeType NOTIFY barcodeTypeChanged) + Q_PROPERTY(QColor foregroundColor READ foregroundColor WRITE setForegroundColor NOTIFY foregroundColorChanged) + Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged) + +public: + enum BarcodeType { + Null = Prison::Null, + QRCode = Prison::QRCode, + DataMatrix = Prison::DataMatrix, + Aztec = Prison::Aztec, + Code39 = Prison::Code39, + Code93 = Prison::Code93 + }; + Q_ENUM(BarcodeType) + explicit BarcodeQuickItem(QQuickItem *parent = nullptr); + ~BarcodeQuickItem(); + + QString content() const; + void setContent(const QString &data); + + Prison::BarcodeQuickItem::BarcodeType barcodeType() const; + void setBarcodeType(Prison::BarcodeQuickItem::BarcodeType type); + + QColor foregroundColor() const; + void setForegroundColor(const QColor &color); + QColor backgroundColor() const; + void setBackgroundColor(const QColor &color); + + void paint(QPainter *painter) override; + void componentComplete() override; + +Q_SIGNALS: + void contentChanged(); + void barcodeTypeChanged(); + void foregroundColorChanged(); + void backgroundColorChanged(); + +private: + void updateBarcode(); + + QString m_content; + std::unique_ptr m_barcode; + QColor m_fgColor = Qt::black; + QColor m_bgColor = Qt::white; + Prison::BarcodeType m_type = Prison::Null; +}; + +} + +#endif // PRISON_BARCODEQUICKITEM_H diff --git a/src/quick/barcodequickitem.cpp b/src/quick/barcodequickitem.cpp new file mode 100644 --- /dev/null +++ b/src/quick/barcodequickitem.cpp @@ -0,0 +1,147 @@ +/* + Copyright (c) 2018 Volker Krause + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include "barcodequickitem.h" + +#include + +#include +#include + +using namespace Prison; + +BarcodeQuickItem::BarcodeQuickItem(QQuickItem *parent) + : QQuickPaintedItem(parent) +{ +} + +BarcodeQuickItem::~BarcodeQuickItem() = default; + +QString BarcodeQuickItem::content() const +{ + return m_content; +} + +void BarcodeQuickItem::setContent(const QString& content) +{ + if (m_content == content) + return; + m_content = content; + emit contentChanged(); + updateBarcode(); +} + +BarcodeQuickItem::BarcodeType BarcodeQuickItem::barcodeType() const +{ + return static_cast(m_type); +} + +void BarcodeQuickItem::setBarcodeType(BarcodeQuickItem::BarcodeType type) +{ + if (m_type == static_cast(type)) + return; + m_type = static_cast(type); + emit barcodeTypeChanged(); + m_barcode.reset(); + updateBarcode(); +} + +QColor BarcodeQuickItem::foregroundColor() const +{ + return m_fgColor; +} + +void BarcodeQuickItem::setForegroundColor(const QColor &color) +{ + if (m_fgColor == color) + return; + m_fgColor = color; + emit foregroundColorChanged(); + updateBarcode(); +} + +QColor BarcodeQuickItem::backgroundColor() const +{ + return m_bgColor; +} + +void BarcodeQuickItem::setBackgroundColor(const QColor &color) +{ + if (m_bgColor == color) + return; + m_bgColor = color; + emit backgroundColorChanged(); + updateBarcode(); +} + +void BarcodeQuickItem::paint(QPainter* painter) +{ + if (!m_barcode) + return; + + const auto w_max = std::max(implicitWidth(), width()); + const auto h_max = std::max(implicitHeight(), height()); + const auto scale = std::min(w_max / implicitWidth(), h_max / implicitHeight()); + const auto w = scale * implicitWidth(); + const auto h = scale * implicitHeight(); + const auto x = (width() - w) / 2; + const auto y = (height() - h) / 2; + + const auto img = m_barcode->toImage(m_barcode->minimumSize()); + painter->setRenderHint(QPainter::SmoothPixmapTransform, false); + painter->drawImage(QRectF(x, y, w, h), img, img.rect()); +} + +void BarcodeQuickItem::componentComplete() +{ + QQuickPaintedItem::componentComplete(); + updateBarcode(); +} + +void BarcodeQuickItem::updateBarcode() +{ + if (!isComponentComplete()) + return; + + if (m_type == Prison::Null || m_content.isEmpty()) { + m_barcode.reset(); + update(); + return; + } + + if (!m_barcode) + m_barcode.reset(Prison::createBarcode(m_type)); + if (m_barcode) { + m_barcode->setData(m_content); + m_barcode->setForegroundColor(m_fgColor); + m_barcode->setBackgroundColor(m_bgColor); + // minimumSize() is only providing valid results after the first call to toImage()... + m_barcode->toImage(m_barcode->minimumSize()); + setImplicitSize(m_barcode->minimumSize().width(), m_barcode->minimumSize().height()); + } + + update(); +} diff --git a/src/quick/prisonquickplugin.cpp b/src/quick/prisonquickplugin.cpp new file mode 100644 --- /dev/null +++ b/src/quick/prisonquickplugin.cpp @@ -0,0 +1,52 @@ +/* + Copyright (c) 2018 Volker Krause + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +*/ + +#include "barcodequickitem.h" + +#include + +#include + +class PrisonQuickPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.kde.prison") + +public: + PrisonQuickPlugin(QObject *parent = nullptr) + : QQmlExtensionPlugin(parent) + {} + + void registerTypes(const char *uri) override; +}; + + +void PrisonQuickPlugin::registerTypes(const char *uri) +{ + qmlRegisterType(uri, 1, 0, "Barcode"); +} + +#include "prisonquickplugin.moc" diff --git a/src/quick/qmldir b/src/quick/qmldir new file mode 100644 --- /dev/null +++ b/src/quick/qmldir @@ -0,0 +1,2 @@ +module org.kde.prison +plugin prisonquickplugin diff --git a/tests/barcode.qml b/tests/barcode.qml new file mode 100644 --- /dev/null +++ b/tests/barcode.qml @@ -0,0 +1,61 @@ +/* + Copyright (c) 2018 Volker Krause + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +*/ + +import QtQuick 2.0 +import QtQuick.Controls 2.0 +import QtQuick.Layouts 1.0 +import org.kde.prison 1.0 as Prison +Rectangle { + width: 640 + height: 320 + color: "lightsteelblue" + ColumnLayout { + anchors.fill: parent + + RowLayout { + Layout.fillWidth: true + TextField { + id: contentEdit + Layout.fillWidth: true + text: "KF5::Prison - The KDE barcode generation framework." + } + ComboBox { + id: typeCombobox + model: [ "Null", "QRCode", "DataMatrix", "Aztec", "Code39", "Code93" ] + currentIndex: 3 + } + } + + Prison.Barcode { + Layout.fillWidth: true + Layout.fillHeight: true + content: contentEdit.text + barcodeType: typeCombobox.currentIndex +// foregroundColor: "red" +// backgroundColor: "green" + } + } +}