From 467ca9fc624e07442d45b0214f2cccb4919004a4 Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Sat, 11 Aug 2018 14:05:26 -0400 Subject: [PATCH] Implement continuous tape labels and path-based label shapes. - Added "roll" as a special paper id - Added roll_width attribute to draw tape in previews - Updated Brother QL-500/* label templates - Preserve print dialog settings between print jobs. - Added path based labels for arbitrary shaped labels. - Fleshed out implementation of continuous labels. --- glabels/CMakeLists.txt | 3 + glabels/File.cpp | 5 +- glabels/LabelEditor.cpp | 2 +- glabels/MiniPreviewPixmap.cpp | 27 +- glabels/Preview.cpp | 57 +- glabels/Preview.h | 3 +- glabels/PrintView.cpp | 19 +- glabels/PrintView.h | 5 +- glabels/PropertiesView.cpp | 33 + glabels/PropertiesView.h | 3 + glabels/RollTemplatePath.cpp | 71 + glabels/RollTemplatePath.h | 49 + glabels/SimplePreview.cpp | 47 +- glabels/SimplePreview.h | 3 +- glabels/TemplateDesigner.cpp | 304 +++- glabels/TemplateDesigner.h | 34 +- glabels/ui/PropertiesView.ui | 85 +- glabels/ui/TemplateDesignerContinuousPage.ui | 59 + glabels/ui/TemplateDesignerPageSizePage.ui | 145 +- glabels/ui/TemplateDesignerPathPage.ui | 59 + glabels/ui/TemplateDesignerRectPage.ui | 101 +- model/CMakeLists.txt | 2 + model/Db.cpp | 26 +- model/Db.h | 3 - model/Distance.cpp | 10 + model/Distance.h | 12 + model/Frame.cpp | 77 +- model/Frame.h | 16 +- model/FrameCd.cpp | 34 +- model/FrameCd.h | 9 +- model/FrameContinuous.cpp | 166 ++ model/FrameContinuous.h | 85 + model/FrameEllipse.cpp | 30 +- model/FrameEllipse.h | 9 +- model/FramePath.cpp | 157 ++ model/FramePath.h | 86 + model/FrameRect.cpp | 39 +- model/FrameRect.h | 9 +- model/FrameRound.cpp | 29 +- model/FrameRound.h | 9 +- model/Layout.cpp | 38 +- model/Layout.h | 10 +- model/Markup.cpp | 35 +- model/Markup.h | 17 +- model/Model.cpp | 65 +- model/Model.h | 9 +- model/PageRenderer.cpp | 22 +- model/StrUtil.cpp | 2 +- model/Template.cpp | 105 +- model/Template.h | 16 +- model/XmlTemplateCreator.cpp | 72 +- model/XmlTemplateCreator.h | 6 +- model/XmlTemplateParser.cpp | 81 +- model/XmlTemplateParser.h | 2 + model/XmlUtil.cpp | 188 ++ model/XmlUtil.h | 19 + templates/brother-other-templates.xml | 56 +- templates/dymo-other-templates.xml | 61 +- templates/glabels-4.0.dtd | 18 +- translations/glabels_C.ts | 451 +++-- translations/glabels_ar.ts | 1431 ++++++++++----- translations/glabels_bs.ts | 1302 +++++++++++--- translations/glabels_ca.ts | 1300 +++++++++++--- translations/glabels_ca@valencia.ts | 1146 ++++++++++-- translations/glabels_cs.ts | 1300 +++++++++++--- translations/glabels_da.ts | 1300 +++++++++++--- translations/glabels_de_DE.ts | 1675 ++++++++++-------- translations/glabels_el.ts | 1302 +++++++++++--- translations/glabels_en_GB.ts | 1302 +++++++++++--- translations/glabels_eo.ts | 1345 ++++++++++---- translations/glabels_es.ts | 1300 +++++++++++--- translations/glabels_fi.ts | 1354 ++++++++++---- translations/glabels_fr.ts | 1300 +++++++++++--- translations/glabels_gl.ts | 1367 ++++++++++---- translations/glabels_hu.ts | 1300 +++++++++++--- translations/glabels_id.ts | 1321 +++++++++++--- translations/glabels_it.ts | 1370 ++++++++++---- translations/glabels_ja.ts | 1302 +++++++++++--- translations/glabels_ko.ts | 1355 ++++++++++---- translations/glabels_lv.ts | 1300 +++++++++++--- translations/glabels_nb.ts | 1415 +++++++++++---- translations/glabels_nl.ts | 1302 +++++++++++--- translations/glabels_oc.ts | 1300 +++++++++++--- translations/glabels_pt.ts | 1300 +++++++++++--- translations/glabels_pt_BR.ts | 1300 +++++++++++--- translations/glabels_ro.ts | 1306 +++++++++++--- translations/glabels_ru.ts | 1302 +++++++++++--- translations/glabels_sk.ts | 1302 +++++++++++--- translations/glabels_sl.ts | 1302 +++++++++++--- translations/glabels_sr.ts | 1300 +++++++++++--- translations/glabels_sr@latin.ts | 1300 +++++++++++--- translations/glabels_sv.ts | 1300 +++++++++++--- translations/glabels_tr.ts | 1300 +++++++++++--- translations/glabels_uk.ts | 453 +++-- translations/glabels_zh_CN.ts | 1339 ++++++++++---- translations/glabels_zh_HK.ts | 1350 ++++++++++---- translations/glabels_zh_TW.ts | 1350 ++++++++++---- translations/templates_C.ts | 184 +- translations/templates_ar.ts | 84 +- translations/templates_bs.ts | 74 +- translations/templates_ca.ts | 110 +- translations/templates_ca@valencia.ts | 38 +- translations/templates_cs.ts | 110 +- translations/templates_da.ts | 110 +- translations/templates_de_DE.ts | 676 +++---- translations/templates_el.ts | 74 +- translations/templates_en_GB.ts | 74 +- translations/templates_eo.ts | 124 +- translations/templates_es.ts | 110 +- translations/templates_fi.ts | 131 +- translations/templates_fr.ts | 110 +- translations/templates_gl.ts | 74 +- translations/templates_hu.ts | 110 +- translations/templates_id.ts | 87 +- translations/templates_it.ts | 61 +- translations/templates_ja.ts | 74 +- translations/templates_ko.ts | 56 +- translations/templates_lv.ts | 110 +- translations/templates_nb.ts | 83 +- translations/templates_nl.ts | 70 +- translations/templates_oc.ts | 111 +- translations/templates_pt.ts | 110 +- translations/templates_pt_BR.ts | 110 +- translations/templates_ro.ts | 74 +- translations/templates_ru.ts | 74 +- translations/templates_sk.ts | 129 +- translations/templates_sl.ts | 74 +- translations/templates_sr.ts | 110 +- translations/templates_sr@latin.ts | 110 +- translations/templates_sv.ts | 110 +- translations/templates_tr.ts | 74 +- translations/templates_uk.ts | 186 +- translations/templates_zh_CN.ts | 73 +- translations/templates_zh_HK.ts | 74 +- translations/templates_zh_TW.ts | 74 +- 135 files changed, 41934 insertions(+), 13681 deletions(-) create mode 100644 glabels/RollTemplatePath.cpp create mode 100644 glabels/RollTemplatePath.h create mode 100644 glabels/ui/TemplateDesignerContinuousPage.ui create mode 100644 glabels/ui/TemplateDesignerPathPage.ui create mode 100644 model/FrameContinuous.cpp create mode 100644 model/FrameContinuous.h create mode 100644 model/FramePath.cpp create mode 100644 model/FramePath.h diff --git a/glabels/CMakeLists.txt b/glabels/CMakeLists.txt index 65c54b5..9d636c1 100644 --- a/glabels/CMakeLists.txt +++ b/glabels/CMakeLists.txt @@ -31,6 +31,7 @@ set (glabels_sources PropertiesView.cpp Preview.cpp PreviewOverlayItem.cpp + RollTemplatePath.cpp SelectProductDialog.cpp SimplePreview.cpp StartupView.cpp @@ -85,6 +86,8 @@ set (glabels_forms ui/TemplateDesignerRoundPage.ui ui/TemplateDesignerEllipsePage.ui ui/TemplateDesignerCdPage.ui + ui/TemplateDesignerPathPage.ui + ui/TemplateDesignerContinuousPage.ui ui/TemplateDesignerNLayoutsPage.ui ui/TemplateDesignerOneLayoutPage.ui ui/TemplateDesignerTwoLayoutPage.ui diff --git a/glabels/File.cpp b/glabels/File.cpp index f87a4c8..1e65f59 100644 --- a/glabels/File.cpp +++ b/glabels/File.cpp @@ -56,12 +56,13 @@ namespace glabels { auto* model = new model::Model(); model->setTmplate( tmplate ); - model->clearModified(); - + // Intelligently decide to rotate label by default const model::Frame* frame = tmplate->frames().first(); model->setRotate( frame->h() > frame->w() ); + model->clearModified(); + // Either apply to current window or open a new one if ( window->isEmpty() ) { diff --git a/glabels/LabelEditor.cpp b/glabels/LabelEditor.cpp index 574fe38..ef7fe05 100644 --- a/glabels/LabelEditor.cpp +++ b/glabels/LabelEditor.cpp @@ -1143,7 +1143,7 @@ namespace glabels foreach( model::Markup* markup, mModel->frame()->markups() ) { - painter->drawPath( markup->path() ); + painter->drawPath( markup->path( mModel->frame() ) ); } painter->restore(); diff --git a/glabels/MiniPreviewPixmap.cpp b/glabels/MiniPreviewPixmap.cpp index 4486eed..15a7d8e 100644 --- a/glabels/MiniPreviewPixmap.cpp +++ b/glabels/MiniPreviewPixmap.cpp @@ -20,6 +20,8 @@ #include "MiniPreviewPixmap.h" + +#include "RollTemplatePath.h" #include "model/Template.h" @@ -63,16 +65,25 @@ namespace glabels painter.setBackgroundMode( Qt::TransparentMode ); painter.setRenderHint( QPainter::Antialiasing, true ); + // For "Roll" templates, allow extra room for tape width and continuation break lines + model::Distance drawWidth = tmplate->pageWidth(); + model::Distance drawHeight = tmplate->pageHeight(); + if ( tmplate->isRoll() ) + { + drawWidth = tmplate->rollWidth(); + drawHeight *= 1.2; + } + double w = width - 1; double h = height - 1; double scale; - if ( (w/tmplate->pageWidth().pt()) > (h/tmplate->pageHeight().pt()) ) + if ( (w/drawWidth.pt()) > (h/drawHeight.pt()) ) { - scale = h / tmplate->pageHeight().pt(); + scale = h / drawHeight.pt(); } else { - scale = w / tmplate->pageWidth().pt(); + scale = w / drawWidth.pt(); } painter.scale( scale, scale ); @@ -95,7 +106,15 @@ namespace glabels painter.setBrush( brush ); painter.setPen( pen ); - painter.drawRect( 0, 0, tmplate->pageWidth().pt(), tmplate->pageHeight().pt() ); + + if ( !tmplate->isRoll() ) + { + painter.drawRect( 0, 0, tmplate->pageWidth().pt(), tmplate->pageHeight().pt() ); + } + else + { + painter.drawPath( RollTemplatePath( tmplate ) ); + } painter.restore(); } diff --git a/glabels/Preview.cpp b/glabels/Preview.cpp index 259732a..0a7dd72 100644 --- a/glabels/Preview.cpp +++ b/glabels/Preview.cpp @@ -21,6 +21,7 @@ #include "Preview.h" #include "PreviewOverlayItem.h" +#include "RollTemplatePath.h" #include #include @@ -35,7 +36,7 @@ namespace glabels // namespace { - const QColor paperColor( 255, 255, 255 ); + const QColor paperColor( 242, 242, 242 ); const QColor paperOutlineColor( 0, 0, 0 ); const double paperOutlineWidthPixels = 1; @@ -44,7 +45,7 @@ namespace glabels const double shadowRadiusPixels = 12; const QColor labelColor( 255, 255, 255 ); - const QColor labelOutlineColor( 215, 215, 215 ); + const QColor labelOutlineColor( 192, 192, 192 ); const double labelOutlineWidthPixels = 1; } @@ -85,20 +86,31 @@ namespace glabels { mModel = mRenderer->model(); - clearScene(); + mScene->clear(); if ( mModel != nullptr ) { + auto tmplate = mModel->tmplate(); + + // For "Roll" templates, allow extra room to draw continuation break lines. + model::Distance drawHeight = mModel->tmplate()->pageHeight(); + model::Distance drawOffset = 0; + if ( tmplate->isRoll() ) + { + drawHeight = 1.2 * tmplate->pageHeight(); + drawOffset = 0.1 * tmplate->pageHeight(); + } + // Set scene up with a 5% margin around paper - model::Distance x = -0.05 * mModel->tmplate()->pageWidth(); - model::Distance y = -0.05 * mModel->tmplate()->pageHeight(); - model::Distance w = 1.10 * mModel->tmplate()->pageWidth(); - model::Distance h = 1.10 * mModel->tmplate()->pageHeight(); + model::Distance x = -0.05 * tmplate->pageWidth(); + model::Distance y = -0.05 * drawHeight - drawOffset; + model::Distance w = 1.10 * tmplate->pageWidth(); + model::Distance h = 1.10 * drawHeight; mScene->setSceneRect( x.pt(), y.pt(), w.pt(), h.pt() ); fitInView( mScene->sceneRect(), Qt::KeepAspectRatio ); - drawPaper( mModel->tmplate()->pageWidth(), mModel->tmplate()->pageHeight() ); + drawPaper(); drawLabels(); drawPreviewOverlay(); } @@ -114,23 +126,10 @@ namespace glabels } - /// - /// Clear View - /// - void Preview::clearScene() - { - foreach ( QGraphicsItem *item, mScene->items() ) - { - mScene->removeItem( item ); - delete item; - } - } - - /// /// Draw Paper /// - void Preview::drawPaper( const model::Distance& pw, const model::Distance& ph ) + void Preview::drawPaper() { auto *shadowEffect = new QGraphicsDropShadowEffect(); shadowEffect->setColor( shadowColor ); @@ -142,7 +141,16 @@ namespace glabels pen.setCosmetic( true ); pen.setWidthF( paperOutlineWidthPixels ); - auto *pageItem = new QGraphicsRectItem( 0, 0, pw.pt(), ph.pt() ); + QAbstractGraphicsShapeItem* pageItem; + auto tmplate = mModel->tmplate(); + if ( !tmplate->isRoll() ) + { + pageItem = new QGraphicsRectItem( 0, 0, tmplate->pageWidth().pt(), tmplate->pageHeight().pt() ); + } + else + { + pageItem = new QGraphicsPathItem( RollTemplatePath( tmplate ) ); + } pageItem->setBrush( brush ); pageItem->setPen( pen ); pageItem->setGraphicsEffect( shadowEffect ); @@ -170,9 +178,8 @@ namespace glabels /// void Preview::drawLabel( const model::Distance& x, const model::Distance& y, const QPainterPath& path ) { - QBrush brush( Qt::NoBrush ); + QBrush brush( labelColor ); QPen pen( labelOutlineColor ); - pen.setStyle( Qt::DotLine ); pen.setCosmetic( true ); pen.setWidthF( labelOutlineWidthPixels ); diff --git a/glabels/Preview.h b/glabels/Preview.h index 3ba7981..33af702 100644 --- a/glabels/Preview.h +++ b/glabels/Preview.h @@ -68,8 +68,7 @@ namespace glabels // Internal Methods ///////////////////////////////// private: - void clearScene(); - void drawPaper( const model::Distance& pw, const model::Distance& ph ); + void drawPaper(); void drawLabels(); void drawLabel( const model::Distance& x, const model::Distance& y, const QPainterPath& path ); diff --git a/glabels/PrintView.cpp b/glabels/PrintView.cpp index 13384e9..1508d4c 100644 --- a/glabels/PrintView.cpp +++ b/glabels/PrintView.cpp @@ -40,6 +40,14 @@ namespace glabels preview->setRenderer( &mRenderer ); mPrinter = new QPrinter( QPrinter::HighResolution ); mPrinter->setColorMode( QPrinter::Color ); + + mPrintDialog = new QPrintDialog( mPrinter, this ); + mPrintDialog->setOption( QAbstractPrintDialog::PrintToFile, true ); + mPrintDialog->setOption( QAbstractPrintDialog::PrintSelection, false ); + mPrintDialog->setOption( QAbstractPrintDialog::PrintPageRange, false ); + mPrintDialog->setOption( QAbstractPrintDialog::PrintShowPageSize, true ); + mPrintDialog->setOption( QAbstractPrintDialog::PrintCollateCopies, false ); + mPrintDialog->setOption( QAbstractPrintDialog::PrintCurrentPage, false ); } @@ -120,16 +128,7 @@ namespace glabels /// void PrintView::onPrintButtonClicked() { - QPrintDialog printDialog( mPrinter, this ); - - printDialog.setOption( QAbstractPrintDialog::PrintToFile, true ); - printDialog.setOption( QAbstractPrintDialog::PrintSelection, false ); - printDialog.setOption( QAbstractPrintDialog::PrintPageRange, false ); - printDialog.setOption( QAbstractPrintDialog::PrintShowPageSize, true ); - printDialog.setOption( QAbstractPrintDialog::PrintCollateCopies, false ); - printDialog.setOption( QAbstractPrintDialog::PrintCurrentPage, false ); - - if ( printDialog.exec() == QDialog::Accepted ) + if ( mPrintDialog->exec() == QDialog::Accepted ) { mRenderer.print( mPrinter ); } diff --git a/glabels/PrintView.h b/glabels/PrintView.h index 7240844..1902e61 100644 --- a/glabels/PrintView.h +++ b/glabels/PrintView.h @@ -28,6 +28,7 @@ #include "model/PageRenderer.h" #include +#include namespace glabels @@ -73,7 +74,9 @@ namespace glabels QPrinter* mPrinter; model::PageRenderer mRenderer; - bool mBlocked; + QPrintDialog* mPrintDialog; + + bool mBlocked; }; diff --git a/glabels/PropertiesView.cpp b/glabels/PropertiesView.cpp index 63eaff2..83897d4 100644 --- a/glabels/PropertiesView.cpp +++ b/glabels/PropertiesView.cpp @@ -24,6 +24,7 @@ #include "UndoRedoModel.h" #include "model/Db.h" +#include "model/FrameContinuous.h" #include "model/Settings.h" #include @@ -171,6 +172,38 @@ namespace glabels orientationCombo->setCurrentIndex( isRotated ? 0 : 1 ); } mOldOrientationIndex = orientationCombo->currentIndex(); + + if ( auto* continuousFrame = dynamic_cast( frame ) ) + { + if (!mInLengthSpinChanged) + { + const QSignalBlocker blocker( lengthSpin ); + + lengthSpin->setSuffix( " " + mUnits.toTrName() ); + lengthSpin->setDecimals( mUnits.resolutionDigits() ); + lengthSpin->setSingleStep( mUnits.resolution() ); + lengthSpin->setMinimum( continuousFrame->hMin().inUnits( mUnits ) ); + lengthSpin->setMaximum( continuousFrame->hMax().inUnits( mUnits ) ); + lengthSpin->setValue( continuousFrame->h().inUnits( mUnits ) ); + } + + parametersGroupBox->setVisible( true ); + } + else + { + parametersGroupBox->setVisible( false ); + } + } + + + /// + /// Length spin changed handler + /// + void PropertiesView::onLengthSpinChanged() + { + mInLengthSpinChanged = true; + mModel->setH( model::Distance( lengthSpin->value(), mUnits ) ); + mInLengthSpinChanged = false; } diff --git a/glabels/PropertiesView.h b/glabels/PropertiesView.h index e2beaf9..798d5ee 100644 --- a/glabels/PropertiesView.h +++ b/glabels/PropertiesView.h @@ -63,6 +63,7 @@ namespace glabels private slots: void onSettingsChanged(); void onLabelSizeChanged(); + void onLengthSpinChanged(); void onOrientationActivated(); void onChangeProductButtonClicked(); @@ -71,6 +72,8 @@ namespace glabels // Private Data ///////////////////////////////// private: + bool mInLengthSpinChanged{ false }; + model::Model* mModel; UndoRedoModel* mUndoRedoModel; model::Units mUnits; diff --git a/glabels/RollTemplatePath.cpp b/glabels/RollTemplatePath.cpp new file mode 100644 index 0000000..90d7bab --- /dev/null +++ b/glabels/RollTemplatePath.cpp @@ -0,0 +1,71 @@ +/* RollTemplatePath.cpp + * + * Copyright (C) 2014 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 . + */ + +#include "RollTemplatePath.h" + +#include + + +namespace glabels +{ + + /// + /// Constructor + /// + RollTemplatePath::RollTemplatePath( const model::Template* tmplate ) + { + if ( !tmplate->isRoll() ) + { + qWarning() << "Not a \"Roll\" template type."; + } + + model::Distance x0 = (tmplate->pageWidth() - tmplate->rollWidth()) / 2.0; + model::Distance w = tmplate->rollWidth(); + model::Distance h = tmplate->pageHeight(); + model::Distance c = 0.07*h; + model::Distance b = 0.03*h; + + const int nx = 18; + + // Upper break line + moveTo( x0.pt(), -c.pt() ); + for ( int ix = 1; ix <= nx; ix++ ) + { + model::Distance x = ix * (w/double(nx)) + x0; + double a = ix * (2*M_PI/double(nx)); + + lineTo( x.pt(), b.pt()*sin(a) - c.pt() ); + } + + // Lower break line + lineTo( (x0+w).pt(), (h+c).pt() ); + for ( int ix = nx-1; ix >= 0; ix-- ) + { + model::Distance x = ix * (w/double(nx)) + x0; + double a = ix * (2*M_PI/double(nx)); + + lineTo( x.pt(), b.pt()*sin(a) + h.pt() + c.pt() ); + } + + // Close path + closeSubpath(); + } + +} // namespace glabels diff --git a/glabels/RollTemplatePath.h b/glabels/RollTemplatePath.h new file mode 100644 index 0000000..194f733 --- /dev/null +++ b/glabels/RollTemplatePath.h @@ -0,0 +1,49 @@ +/* RollTemplatePath.h + * + * Copyright (C) 2018 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 RollTemplatePath_h +#define RollTemplatePath_h + + +#include "model/Template.h" +#include + + +namespace glabels +{ + + /// + /// Painter path for "Roll" templates + /// + class RollTemplatePath : public QPainterPath + { + + ///////////////////////////////// + // Life Cycle + ///////////////////////////////// + public: + RollTemplatePath( const model::Template* tmplate ); + + }; + +} + + +#endif // RollTemplatePath_h diff --git a/glabels/SimplePreview.cpp b/glabels/SimplePreview.cpp index b19bde8..00b26e7 100644 --- a/glabels/SimplePreview.cpp +++ b/glabels/SimplePreview.cpp @@ -20,6 +20,9 @@ #include "SimplePreview.h" +#include "RollTemplatePath.h" + +#include #include #include #include @@ -33,7 +36,7 @@ namespace glabels // namespace { - const QColor paperColor( 255, 255, 255 ); + const QColor paperColor( 242, 242, 242 ); const QColor paperOutlineColor( 0, 0, 0 ); const double paperOutlineWidthPixels = 1; @@ -105,43 +108,39 @@ namespace glabels /// void SimplePreview::update() { - clearScene(); + mScene->clear(); if ( mTmplate != nullptr ) { + // For "Roll" templates, allow extra room to draw continuation break lines. + model::Distance drawHeight = mTmplate->pageHeight(); + model::Distance drawOffset = 0; + if ( mTmplate->isRoll() ) + { + drawHeight = 1.2 * mTmplate->pageHeight(); + drawOffset = 0.1 * mTmplate->pageHeight(); + } + // Set scene up with a 5% margin around paper model::Distance x = -0.05 * mTmplate->pageWidth(); - model::Distance y = -0.05 * mTmplate->pageHeight(); + model::Distance y = -0.05 * drawHeight - drawOffset; model::Distance w = 1.10 * mTmplate->pageWidth(); - model::Distance h = 1.10 * mTmplate->pageHeight(); + model::Distance h = 1.10 * drawHeight; mScene->setSceneRect( x.pt(), y.pt(), w.pt(), h.pt() ); fitInView( mScene->sceneRect(), Qt::KeepAspectRatio ); - drawPaper( mTmplate->pageWidth(), mTmplate->pageHeight() ); + drawPaper(); drawLabels(); drawArrow(); } } - /// - /// Clear View - /// - void SimplePreview::clearScene() - { - foreach ( QGraphicsItem *item, mScene->items() ) - { - mScene->removeItem( item ); - delete item; - } - } - - /// /// Draw Paper /// - void SimplePreview::drawPaper( const model::Distance& pw, const model::Distance& ph ) + void SimplePreview::drawPaper() { auto *shadowEffect = new QGraphicsDropShadowEffect(); shadowEffect->setColor( shadowColor ); @@ -153,7 +152,15 @@ namespace glabels pen.setCosmetic( true ); pen.setWidthF( paperOutlineWidthPixels ); - auto *pageItem = new QGraphicsRectItem( 0, 0, pw.pt(), ph.pt() ); + QAbstractGraphicsShapeItem* pageItem; + if ( !mTmplate->isRoll() ) + { + pageItem = new QGraphicsRectItem( 0, 0, mTmplate->pageWidth().pt(), mTmplate->pageHeight().pt() ); + } + else + { + pageItem = new QGraphicsPathItem( RollTemplatePath( mTmplate ) ); + } pageItem->setBrush( brush ); pageItem->setPen( pen ); pageItem->setGraphicsEffect( shadowEffect ); diff --git a/glabels/SimplePreview.h b/glabels/SimplePreview.h index 3148cee..7fdbae1 100644 --- a/glabels/SimplePreview.h +++ b/glabels/SimplePreview.h @@ -67,8 +67,7 @@ namespace glabels ///////////////////////////////// private: void update(); - void clearScene(); - void drawPaper( const model::Distance& pw, const model::Distance& ph ); + void drawPaper(); void drawLabels(); void drawLabel( const model::Distance& x, const model::Distance& y, const QPainterPath& path ); void drawArrow(); diff --git a/glabels/TemplateDesigner.cpp b/glabels/TemplateDesigner.cpp index f6b8fe6..34eaed6 100644 --- a/glabels/TemplateDesigner.cpp +++ b/glabels/TemplateDesigner.cpp @@ -24,7 +24,9 @@ #include "model/Db.h" #include "model/Distance.h" #include "model/FrameCd.h" +#include "model/FrameContinuous.h" #include "model/FrameEllipse.h" +#include "model/FramePath.h" #include "model/FrameRect.h" #include "model/FrameRound.h" #include "model/Markup.h" @@ -60,6 +62,8 @@ namespace glabels RoundPageId, EllipsePageId, CdPageId, + PathPageId, + ContinuousPageId, NLayoutsPageId, OneLayoutPageId, TwoLayoutPageId, @@ -114,18 +118,20 @@ namespace glabels setOption( QWizard::IndependentPages, false ); setOption( QWizard::NoBackButtonOnStartPage, true ); - setPage( IntroPageId, new TemplateDesignerIntroPage() ); - setPage( NamePageId, new TemplateDesignerNamePage() ); - setPage( PageSizePageId, new TemplateDesignerPageSizePage() ); - setPage( ShapePageId, new TemplateDesignerShapePage() ); - setPage( RectPageId, new TemplateDesignerRectPage() ); - setPage( RoundPageId, new TemplateDesignerRoundPage() ); - setPage( EllipsePageId, new TemplateDesignerEllipsePage() ); - setPage( CdPageId, new TemplateDesignerCdPage() ); - setPage( NLayoutsPageId, new TemplateDesignerNLayoutsPage() ); - setPage( OneLayoutPageId, new TemplateDesignerOneLayoutPage() ); - setPage( TwoLayoutPageId, new TemplateDesignerTwoLayoutPage() ); - setPage( ApplyPageId, new TemplateDesignerApplyPage() ); + setPage( IntroPageId, new TemplateDesignerIntroPage() ); + setPage( NamePageId, new TemplateDesignerNamePage() ); + setPage( PageSizePageId, new TemplateDesignerPageSizePage() ); + setPage( ShapePageId, new TemplateDesignerShapePage() ); + setPage( RectPageId, new TemplateDesignerRectPage() ); + setPage( RoundPageId, new TemplateDesignerRoundPage() ); + setPage( EllipsePageId, new TemplateDesignerEllipsePage() ); + setPage( CdPageId, new TemplateDesignerCdPage() ); + setPage( PathPageId, new TemplateDesignerPathPage() ); + setPage( ContinuousPageId, new TemplateDesignerContinuousPage() ); + setPage( NLayoutsPageId, new TemplateDesignerNLayoutsPage() ); + setPage( OneLayoutPageId, new TemplateDesignerOneLayoutPage() ); + setPage( TwoLayoutPageId, new TemplateDesignerTwoLayoutPage() ); + setPage( ApplyPageId, new TemplateDesignerApplyPage() ); } @@ -136,16 +142,27 @@ namespace glabels { switch (currentId()) { - + case IntroPageId: - return NamePageId; - + if ( mIsTemplatePathBased ) + { + return PathPageId; + } + else if ( mIsTemplateContinuousBased ) + { + return ContinuousPageId; + } + else + { + return NamePageId; + } + case NamePageId: return PageSizePageId; - + case PageSizePageId: return ShapePageId; - + case ShapePageId: if ( field( "shape.rect" ).toBool() ) { @@ -163,19 +180,53 @@ namespace glabels { return CdPageId; } - + case RectPageId: - return NLayoutsPageId; - + if ( field( "pageSize.pageSize" ) != tr("Roll") ) + { + return NLayoutsPageId; + } + else + { + return OneLayoutPageId; + } + case RoundPageId: - return NLayoutsPageId; - + if ( field( "pageSize.pageSize" ) != tr("Roll") ) + { + return NLayoutsPageId; + } + else + { + return OneLayoutPageId; + } + case EllipsePageId: - return NLayoutsPageId; - + if ( field( "pageSize.pageSize" ) != tr("Roll") ) + { + return NLayoutsPageId; + } + else + { + return OneLayoutPageId; + } + case CdPageId: - return NLayoutsPageId; - + if ( field( "pageSize.pageSize" ) != tr("Roll") ) + { + return NLayoutsPageId; + } + else + { + return OneLayoutPageId; + } + + case PathPageId: + return IntroPageId; + + case ContinuousPageId: + return IntroPageId; + case NLayoutsPageId: if ( field( "nLayouts.one" ).toBool() ) { @@ -188,10 +239,10 @@ namespace glabels case OneLayoutPageId: return ApplyPageId; - + case TwoLayoutPageId: return ApplyPageId; - + case ApplyPageId: default: return -1; @@ -326,8 +377,9 @@ namespace glabels QString paperId = model::Db::lookupPaperIdFromName( field( "pageSize.pageSize" ).toString() ); model::Distance pageW( field( "pageSize.w" ).toDouble(), units ); model::Distance pageH( field( "pageSize.h" ).toDouble(), units ); + model::Distance pageRollW( field( "pageSize.rollW" ).toDouble(), units ); - auto t = new model::Template( brand, part, description, paperId, pageW, pageH, true ); + auto t = new model::Template( brand, part, description, paperId, pageW, pageH, pageRollW, true ); model::Frame* frame; if ( field( "shape.rect" ).toBool() ) @@ -337,10 +389,11 @@ namespace glabels model::Distance r( field( "rect.r" ).toDouble(), units ); model::Distance xWaste( field( "rect.xWaste" ).toDouble(), units ); model::Distance yWaste( field( "rect.yWaste" ).toDouble(), units ); - model::Distance margin( field( "rect.margin" ).toDouble(), units ); + model::Distance xMargin( field( "rect.xMargin" ).toDouble(), units ); + model::Distance yMargin( field( "rect.yMargin" ).toDouble(), units ); frame = new model::FrameRect( w, h, r, xWaste, yWaste ); - frame->addMarkup( new model::MarkupMargin( frame, margin ) ); + frame->addMarkup( new model::MarkupMargin( xMargin, yMargin ) ); } else if ( field( "shape.round" ).toBool() ) { @@ -349,7 +402,7 @@ namespace glabels model::Distance margin( field( "round.margin" ).toDouble(), units ); frame = new model::FrameRound( r, waste ); - frame->addMarkup( new model::MarkupMargin( frame, margin ) ); + frame->addMarkup( new model::MarkupMargin( margin ) ); } else if ( field( "shape.ellipse" ).toBool() ) { @@ -359,7 +412,7 @@ namespace glabels model::Distance margin( field( "ellipse.margin" ).toDouble(), units ); frame = new model::FrameEllipse( w, h, waste ); - frame->addMarkup( new model::MarkupMargin( frame, margin ) ); + frame->addMarkup( new model::MarkupMargin( margin ) ); } else { @@ -371,7 +424,7 @@ namespace glabels model::Distance margin( field( "cd.margin" ).toDouble(), units ); frame = new model::FrameCd( r1, r2, xClip, yClip, waste ); - frame->addMarkup( new model::MarkupMargin( frame, margin ) ); + frame->addMarkup( new model::MarkupMargin( margin ) ); } t->addFrame( frame ); @@ -384,7 +437,7 @@ namespace glabels model::Distance dx( field( "oneLayout.dx" ).toDouble(), units ); model::Distance dy( field( "oneLayout.dy" ).toDouble(), units ); - frame->addLayout( new model::Layout( nx, ny, x0, y0, dx, dy ) ); + frame->addLayout( model::Layout( nx, ny, x0, y0, dx, dy ) ); } else { @@ -402,8 +455,8 @@ namespace glabels model::Distance dx2( field( "twoLayout.dx2" ).toDouble(), units ); model::Distance dy2( field( "twoLayout.dy2" ).toDouble(), units ); - frame->addLayout( new model::Layout( nx1, ny1, x01, y01, dx1, dy1 ) ); - frame->addLayout( new model::Layout( nx2, ny2, x02, y02, dx2, dy2 ) ); + frame->addLayout( model::Layout( nx1, ny1, x01, y01, dx1, dy1 ) ); + frame->addLayout( model::Layout( nx2, ny2, x02, y02, dx2, dy2 ) ); } return t; @@ -458,6 +511,7 @@ namespace glabels setField( "pageSize.pageSize", model::Db::lookupPaperNameFromId( tmplate->paperId() ) ); setField( "pageSize.w", tmplate->pageWidth().inUnits( units ) ); setField( "pageSize.h", tmplate->pageHeight().inUnits( units ) ); + setField( "pageSize.rollW", tmplate->rollWidth().inUnits( units ) ); const model::Frame* frame = tmplate->frames().first(); if ( auto frameRect = dynamic_cast( frame ) ) @@ -500,38 +554,39 @@ namespace glabels { if ( auto markupMargin = dynamic_cast( markup ) ) { - setField( "rect.margin", markupMargin->size().inUnits( units ) ); - setField( "round.margin", markupMargin->size().inUnits( units ) ); - setField( "ellipse.margin", markupMargin->size().inUnits( units ) ); - setField( "cd.margin", markupMargin->size().inUnits( units ) ); + setField( "rect.xMargin", markupMargin->xSize().inUnits( units ) ); + setField( "rect.yMargin", markupMargin->ySize().inUnits( units ) ); + setField( "round.margin", markupMargin->xSize().inUnits( units ) ); + setField( "ellipse.margin", markupMargin->xSize().inUnits( units ) ); + setField( "cd.margin", markupMargin->xSize().inUnits( units ) ); } } - QList layouts = frame->layouts(); + auto layouts = frame->layouts(); if ( layouts.size() == 1 ) { - setField( "oneLayout.nx", layouts[0]->nx() ); - setField( "oneLayout.ny", layouts[0]->ny() ); - setField( "oneLayout.x0", layouts[0]->x0().inUnits( units ) ); - setField( "oneLayout.y0", layouts[0]->y0().inUnits( units ) ); - setField( "oneLayout.dx", layouts[0]->dx().inUnits( units ) ); - setField( "oneLayout.dy", layouts[0]->dy().inUnits( units ) ); + setField( "oneLayout.nx", layouts[0].nx() ); + setField( "oneLayout.ny", layouts[0].ny() ); + setField( "oneLayout.x0", layouts[0].x0().inUnits( units ) ); + setField( "oneLayout.y0", layouts[0].y0().inUnits( units ) ); + setField( "oneLayout.dx", layouts[0].dx().inUnits( units ) ); + setField( "oneLayout.dy", layouts[0].dy().inUnits( units ) ); } else if ( layouts.size() > 1 ) { - setField( "twoLayout.nx1", layouts[0]->nx() ); - setField( "twoLayout.ny1", layouts[0]->ny() ); - setField( "twoLayout.x01", layouts[0]->x0().inUnits( units ) ); - setField( "twoLayout.y01", layouts[0]->y0().inUnits( units ) ); - setField( "twoLayout.dx1", layouts[0]->dx().inUnits( units ) ); - setField( "twoLayout.dy1", layouts[0]->dy().inUnits( units ) ); + setField( "twoLayout.nx1", layouts[0].nx() ); + setField( "twoLayout.ny1", layouts[0].ny() ); + setField( "twoLayout.x01", layouts[0].x0().inUnits( units ) ); + setField( "twoLayout.y01", layouts[0].y0().inUnits( units ) ); + setField( "twoLayout.dx1", layouts[0].dx().inUnits( units ) ); + setField( "twoLayout.dy1", layouts[0].dy().inUnits( units ) ); - setField( "twoLayout.nx2", layouts[1]->nx() ); - setField( "twoLayout.ny2", layouts[1]->ny() ); - setField( "twoLayout.x02", layouts[1]->x0().inUnits( units ) ); - setField( "twoLayout.y02", layouts[1]->y0().inUnits( units ) ); - setField( "twoLayout.dx2", layouts[1]->dx().inUnits( units ) ); - setField( "twoLayout.dy2", layouts[1]->dy().inUnits( units ) ); + setField( "twoLayout.nx2", layouts[1].nx() ); + setField( "twoLayout.ny2", layouts[1].ny() ); + setField( "twoLayout.x02", layouts[1].x0().inUnits( units ) ); + setField( "twoLayout.y02", layouts[1].y0().inUnits( units ) ); + setField( "twoLayout.dx2", layouts[1].dx().inUnits( units ) ); + setField( "twoLayout.dy2", layouts[1].dy().inUnits( units ) ); } } @@ -583,7 +638,20 @@ namespace glabels { if ( auto td = dynamic_cast( wizard() ) ) { - td->loadFromTemplate( tmplate ); + if ( dynamic_cast(tmplate->frames().constFirst()) ) + { + td->mIsTemplatePathBased = true; + } + else if ( dynamic_cast(tmplate->frames().constFirst()) ) + { + td->mIsTemplateContinuousBased = true; + } + else + { + td->mIsTemplatePathBased = false; + td->mIsTemplateContinuousBased = false; + td->loadFromTemplate( tmplate ); + } td->next(); } } @@ -658,20 +726,30 @@ namespace glabels setupUi( widget ); pageSizeCombo->insertItem( 0, tr("Other") ); - pageSizeCombo->insertItems( 1, model::Db::paperNames() ); + pageSizeCombo->insertItem( 1, tr("Roll") ); + pageSizeCombo->insertItems( 2, model::Db::paperNames() ); pageSizeCombo->setCurrentText( defaultPageSize[ model::Settings::preferedPageSizeFamily() ] ); + bool isOther = pageSizeCombo->currentText() == tr("Other"); + bool isRoll = pageSizeCombo->currentText() == tr("Roll"); + wSpin->setSuffix( " " + model::Settings::units().toTrName() ); wSpin->setDecimals( model::Settings::units().resolutionDigits() ); wSpin->setSingleStep( model::Settings::units().resolution() ); wSpin->setMaximum( maxPageSize[ model::Settings::units().toEnum() ] ); - wSpin->setEnabled( pageSizeCombo->currentText() == tr("Other") ); + wSpin->setEnabled( isOther || isRoll ); hSpin->setSuffix( " " + model::Settings::units().toTrName() ); hSpin->setDecimals( model::Settings::units().resolutionDigits() ); hSpin->setSingleStep( model::Settings::units().resolution() ); hSpin->setMaximum( maxPageSize[ model::Settings::units().toEnum() ] ); - hSpin->setEnabled( pageSizeCombo->currentText() == tr("Other") ); + hSpin->setEnabled( isOther || isRoll ); + + rollWSpin->setSuffix( " " + model::Settings::units().toTrName() ); + rollWSpin->setDecimals( model::Settings::units().resolutionDigits() ); + rollWSpin->setSingleStep( model::Settings::units().resolution() ); + rollWSpin->setMaximum( maxPageSize[ model::Settings::units().toEnum() ] ); + rollWSpin->setEnabled( isRoll ); if ( pageSizeCombo->currentText() != tr("Other") ) { @@ -683,6 +761,7 @@ namespace glabels registerField( "pageSize.pageSize", pageSizeCombo, "currentText" ); registerField( "pageSize.w", wSpin, "value" ); registerField( "pageSize.h", hSpin, "value" ); + registerField( "pageSize.rollW", rollWSpin, "value" ); connect( pageSizeCombo, &QComboBox::currentTextChanged, this, &TemplateDesignerPageSizePage::onComboChanged ); @@ -705,15 +784,29 @@ namespace glabels void TemplateDesignerPageSizePage::onComboChanged() { - if ( pageSizeCombo->currentText() != tr("Other") ) + bool isOther = pageSizeCombo->currentText() == tr("Other"); + bool isRoll = pageSizeCombo->currentText() == tr("Roll"); + + if ( !isOther && !isRoll ) { const model::Paper* paper = model::Db::lookupPaperFromName( pageSizeCombo->currentText() ); wSpin->setValue( paper->width().inUnits( model::Settings::units() ) ); hSpin->setValue( paper->height().inUnits( model::Settings::units() ) ); } - wSpin->setEnabled( pageSizeCombo->currentText() == tr("Other") ); - hSpin->setEnabled( pageSizeCombo->currentText() == tr("Other") ); + if ( !isRoll ) + { + rollWSpin->setValue( 0 ); + } + + wLabel->setEnabled( isOther || isRoll ); + wSpin->setEnabled( isOther || isRoll ); + + hLabel->setEnabled( isOther || isRoll ); + hSpin->setEnabled( isOther || isRoll ); + + rollWLabel->setEnabled( isRoll ); + rollWSpin->setEnabled( isRoll ); } @@ -781,16 +874,21 @@ namespace glabels yWasteSpin->setDecimals( model::Settings::units().resolutionDigits() ); yWasteSpin->setSingleStep( model::Settings::units().resolution() ); - marginSpin->setSuffix( " " + model::Settings::units().toTrName() ); - marginSpin->setDecimals( model::Settings::units().resolutionDigits() ); - marginSpin->setSingleStep( model::Settings::units().resolution() ); + xMarginSpin->setSuffix( " " + model::Settings::units().toTrName() ); + xMarginSpin->setDecimals( model::Settings::units().resolutionDigits() ); + xMarginSpin->setSingleStep( model::Settings::units().resolution() ); - registerField( "rect.w", wSpin, "value" ); - registerField( "rect.h", hSpin, "value" ); - registerField( "rect.r", rSpin, "value" ); - registerField( "rect.xWaste", xWasteSpin, "value" ); - registerField( "rect.yWaste", yWasteSpin, "value" ); - registerField( "rect.margin", marginSpin, "value" ); + yMarginSpin->setSuffix( " " + model::Settings::units().toTrName() ); + yMarginSpin->setDecimals( model::Settings::units().resolutionDigits() ); + yMarginSpin->setSingleStep( model::Settings::units().resolution() ); + + registerField( "rect.w", wSpin, "value" ); + registerField( "rect.h", hSpin, "value" ); + registerField( "rect.r", rSpin, "value" ); + registerField( "rect.xWaste", xWasteSpin, "value" ); + registerField( "rect.yWaste", yWasteSpin, "value" ); + registerField( "rect.xMargin", xMarginSpin, "value" ); + registerField( "rect.yMargin", yMarginSpin, "value" ); QVBoxLayout* layout = new QVBoxLayout; layout->addWidget( widget ); @@ -811,7 +909,8 @@ namespace glabels rSpin->setMaximum( std::min(wMax,hMax)/2.0 ); xWasteSpin->setMaximum( std::min(wMax,hMax)/4.0 ); yWasteSpin->setMaximum( std::min(wMax,hMax)/4.0 ); - marginSpin->setMaximum( std::min(wMax,hMax)/4.0 ); + xMarginSpin->setMaximum( std::min(wMax,hMax)/4.0 ); + yMarginSpin->setMaximum( std::min(wMax,hMax)/4.0 ); static bool alreadyInitialized = false; if ( !td->isBasedOnCopy() && !alreadyInitialized ) @@ -824,7 +923,8 @@ namespace glabels rSpin->setValue( defaultRectR.inUnits( model::Settings::units() ) ); xWasteSpin->setValue( defaultWaste.inUnits( model::Settings::units() ) ); yWasteSpin->setValue( defaultWaste.inUnits( model::Settings::units() ) ); - marginSpin->setValue( defaultMargin.inUnits( model::Settings::units() ) ); + xMarginSpin->setValue( defaultMargin.inUnits( model::Settings::units() ) ); + yMarginSpin->setValue( defaultMargin.inUnits( model::Settings::units() ) ); } } } @@ -1059,6 +1159,54 @@ namespace glabels } + /// + /// Path Product Page + /// + TemplateDesignerPathPage::TemplateDesignerPathPage( QWidget* parent ) : QWizardPage(parent) + { + setTitle( tr("Unsupported Product Style") ); + setSubTitle( tr("Path based product templates are not currently supported by the Product Template Designer.") ); + + QWidget* widget = new QWidget; + setupUi( widget ); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget( widget ); + setLayout( layout ); + } + + + bool TemplateDesignerPathPage::isComplete() const + { + // Must "Cancel" or "Back" from this page + return false; + } + + + /// + /// Continuous Product Page + /// + TemplateDesignerContinuousPage::TemplateDesignerContinuousPage( QWidget* parent ) : QWizardPage(parent) + { + setTitle( tr("Unsupported Product Style") ); + setSubTitle( tr("Continuous tape product templates are not currently supported by the Product Template Designer.") ); + + QWidget* widget = new QWidget; + setupUi( widget ); + + QVBoxLayout* layout = new QVBoxLayout; + layout->addWidget( widget ); + setLayout( layout ); + } + + + bool TemplateDesignerContinuousPage::isComplete() const + { + // Must "Cancel" or "Back" from this page + return false; + } + + /// /// Number of Layouts Page /// diff --git a/glabels/TemplateDesigner.h b/glabels/TemplateDesigner.h index 15534f3..b00040b 100644 --- a/glabels/TemplateDesigner.h +++ b/glabels/TemplateDesigner.h @@ -30,6 +30,8 @@ #include "ui_TemplateDesignerRoundPage.h" #include "ui_TemplateDesignerEllipsePage.h" #include "ui_TemplateDesignerCdPage.h" +#include "ui_TemplateDesignerPathPage.h" +#include "ui_TemplateDesignerContinuousPage.h" #include "ui_TemplateDesignerNLayoutsPage.h" #include "ui_TemplateDesignerOneLayoutPage.h" #include "ui_TemplateDesignerTwoLayoutPage.h" @@ -59,6 +61,8 @@ namespace glabels friend class TemplateDesignerRoundPage; friend class TemplateDesignerEllipsePage; friend class TemplateDesignerCdPage; + friend class TemplateDesignerPathPage; + friend class TemplateDesignerContinuousPage; friend class TemplateDesignerNLayoutsPage; friend class TemplateDesignerOneLayoutPage; friend class TemplateDesignerTwoLayoutPage; @@ -92,7 +96,9 @@ namespace glabels // Private methods ///////////////////////////////// private: - bool mIsBasedOnCopy; + bool mIsBasedOnCopy{false}; + bool mIsTemplatePathBased{false}; + bool mIsTemplateContinuousBased{false}; }; @@ -220,6 +226,32 @@ namespace glabels }; + // + // Path Page + // + class TemplateDesignerPathPage : public QWizardPage, public Ui::TemplateDesignerPathPage + { + Q_OBJECT + public: + TemplateDesignerPathPage( QWidget* parent = nullptr ); + + bool isComplete() const override; + }; + + + // + // Continuous Page + // + class TemplateDesignerContinuousPage : public QWizardPage, public Ui::TemplateDesignerContinuousPage + { + Q_OBJECT + public: + TemplateDesignerContinuousPage( QWidget* parent = nullptr ); + + bool isComplete() const override; + }; + + // // NLayouts Page // diff --git a/glabels/ui/PropertiesView.ui b/glabels/ui/PropertiesView.ui index c005184..2cac3c9 100644 --- a/glabels/ui/PropertiesView.ui +++ b/glabels/ui/PropertiesView.ui @@ -6,7 +6,7 @@ 0 0 - 806 + 886 742 @@ -25,7 +25,7 @@ Form - + @@ -42,7 +42,16 @@ - + + 12 + + + 12 + + + 12 + + 12 @@ -256,6 +265,51 @@ + + + + Adjustable Parameters + + + + 12 + + + + + false + + + + + + in + + + + + + + Label length: + + + + + + + Qt::Horizontal + + + + 10 + 20 + + + + + + + @@ -385,8 +439,8 @@ onChangeProductButtonClicked() - 309 - 239 + 342 + 291 728 @@ -401,8 +455,8 @@ onOrientationActivated() - 308 - 334 + 342 + 467 802 @@ -410,9 +464,26 @@ + + lengthSpin + valueChanged(double) + PropertiesView + onLengthSpinChanged() + + + 188 + 349 + + + 801 + 376 + + + onChangeProductButtonClicked() onOrientationActivated() + onLengthSpinChanged() diff --git a/glabels/ui/TemplateDesignerContinuousPage.ui b/glabels/ui/TemplateDesignerContinuousPage.ui new file mode 100644 index 0000000..8960aa6 --- /dev/null +++ b/glabels/ui/TemplateDesignerContinuousPage.ui @@ -0,0 +1,59 @@ + + + TemplateDesignerContinuousPage + + + + 0 + 0 + 640 + 400 + + + + + 0 + 0 + + + + + 640 + 400 + + + + Form + + + + 18 + + + + + <html><head/><body><p>Click &quot;Cancel&quot; to quit, or click &quot;Back&quot; to begin with a different product.</p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/glabels/ui/TemplateDesignerPageSizePage.ui b/glabels/ui/TemplateDesignerPageSizePage.ui index c65edaa..38c631f 100644 --- a/glabels/ui/TemplateDesignerPageSizePage.ui +++ b/glabels/ui/TemplateDesignerPageSizePage.ui @@ -25,54 +25,19 @@ Form - - - - - - - Page size: - - - - - - - Width: - - - - - - - true - - - in - - - - - - - Height: - - - - - - - true - - - in - - - - - - - + + + + + Qt::Vertical + + + + 20 + 173 + + + @@ -87,18 +52,80 @@ - - - - Qt::Vertical + + + + 12 - - - 20 - 173 - - - + + + + + + true + + + in + + + + + + + Roll width: + + + + + + + Height: + + + + + + + + + + Width: + + + + + + + in + + + + + + + + 0 + 0 + + + + true + + + in + + + + + + + Page size: + + + + + + diff --git a/glabels/ui/TemplateDesignerPathPage.ui b/glabels/ui/TemplateDesignerPathPage.ui new file mode 100644 index 0000000..2f78452 --- /dev/null +++ b/glabels/ui/TemplateDesignerPathPage.ui @@ -0,0 +1,59 @@ + + + TemplateDesignerPathPage + + + + 0 + 0 + 640 + 400 + + + + + 0 + 0 + + + + + 640 + 400 + + + + Form + + + + 18 + + + + + <html><head/><body><p>Click &quot;Cancel&quot; to quit, or click &quot;Back&quot; to begin with a different product.</p></body></html> + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/glabels/ui/TemplateDesignerRectPage.ui b/glabels/ui/TemplateDesignerRectPage.ui index d8b2132..7265e8f 100644 --- a/glabels/ui/TemplateDesignerRectPage.ui +++ b/glabels/ui/TemplateDesignerRectPage.ui @@ -30,25 +30,15 @@ - - + + - 2. Height: - - - - - - - true - - - in + 4. Horizontal waste: - + true @@ -57,23 +47,10 @@ - - - - true - - - in - - - - - - - true - - - in + + + + 3. Corner radius @@ -94,24 +71,54 @@ - - - - 4. Horizontal waste: + + + + true + + + in - - + + - 3. Corner radius + 5. Vertical waste: + + + + + + + true + + + in + + + + + + + true + + + in + + + + + + + 2. Height: - 6. Margin: + 6. Margin (X): @@ -125,10 +132,20 @@ - - + + - 5. Vertical waste: + 7. Margin (Y): + + + + + + + true + + + in diff --git a/model/CMakeLists.txt b/model/CMakeLists.txt index d01a551..a5d50e8 100644 --- a/model/CMakeLists.txt +++ b/model/CMakeLists.txt @@ -26,7 +26,9 @@ set (Model_sources FileUtil.cpp Frame.cpp FrameCd.cpp + FrameContinuous.cpp FrameEllipse.cpp + FramePath.cpp FrameRect.cpp FrameRound.cpp Handles.cpp diff --git a/model/Db.cpp b/model/Db.cpp index 6592193..9c65009 100644 --- a/model/Db.cpp +++ b/model/Db.cpp @@ -67,13 +67,10 @@ namespace glabels QList Db::mVendors; QStringList Db::mVendorNames; QList Db::mTemplates; - QString Db::mPaperNameOther; Db::Db() { - mPaperNameOther = tr("Other"); - readPapers(); readCategories(); readVendors(); @@ -209,6 +206,15 @@ namespace glabels { if ( !name.isNull() && !name.isEmpty() ) { + if ( name == tr("Other") ) + { + return "other"; + } + else if ( name == tr("Roll") ) + { + return "roll"; + } + const Paper *paper = lookupPaperFromName( name ); if ( paper != nullptr ) { @@ -225,9 +231,13 @@ namespace glabels { if ( !id.isNull() && !id.isEmpty() ) { - if ( isPaperIdOther( id ) ) + if ( id == "roll" ) { - return mPaperNameOther; + return tr("Roll"); + } + else + { + return tr("Other"); } const Paper *paper = lookupPaperFromId( id ); @@ -256,12 +266,6 @@ namespace glabels } - bool Db::isPaperIdOther( const QString& id ) - { - return ( id == "Other" ); - } - - void Db::registerCategory( Category *category ) { if ( !isCategoryIdKnown( category->id() ) ) diff --git a/model/Db.h b/model/Db.h index 6964a81..5f85377 100644 --- a/model/Db.h +++ b/model/Db.h @@ -71,7 +71,6 @@ namespace glabels static QString lookupPaperIdFromName( const QString& name ); static QString lookupPaperNameFromId( const QString& id ); static bool isPaperIdKnown( const QString& id ); - static bool isPaperIdOther( const QString& id ); static void registerCategory( Category *category ); static const Category *lookupCategoryFromName( const QString& name ); @@ -134,8 +133,6 @@ namespace glabels static QList mTemplates; - static QString mPaperNameOther; - }; } diff --git a/model/Distance.cpp b/model/Distance.cpp index 19cd155..724e200 100644 --- a/model/Distance.cpp +++ b/model/Distance.cpp @@ -208,3 +208,13 @@ namespace glabels } } + + +QDebug operator<<( QDebug dbg, const glabels::model::Distance& distance ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << distance.pt() << "pt"; + + return dbg; +} diff --git a/model/Distance.h b/model/Distance.h index ba525ab..8222d17 100644 --- a/model/Distance.h +++ b/model/Distance.h @@ -69,6 +69,7 @@ namespace glabels Distance& operator+=( const Distance& d ); Distance& operator-=( const Distance& d ); + Distance& operator*=( double f ); Distance operator-(); friend inline Distance operator+( const Distance& d1, const Distance& d2 ); @@ -100,6 +101,10 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::Distance& distance ); + + // // Inline methods // @@ -200,6 +205,13 @@ namespace glabels } + inline Distance& Distance::operator*=( double f ) + { + mDPts *= f; + return *this; + } + + inline Distance Distance::operator-() { return Distance::pt( -mDPts ); diff --git a/model/Frame.cpp b/model/Frame.cpp index f020cd9..76c280f 100644 --- a/model/Frame.cpp +++ b/model/Frame.cpp @@ -20,6 +20,12 @@ #include "Frame.h" +#include "FrameCd.h" +#include "FrameContinuous.h" +#include "FrameEllipse.h" +#include "FramePath.h" +#include "FrameRect.h" +#include "FrameRound.h" #include "Markup.h" #include @@ -42,12 +48,12 @@ namespace glabels mId = other.mId; mNLabels = 0; - foreach ( Layout *layout, mLayouts ) + foreach ( const Layout& layout, other.mLayouts ) { - addLayout( layout->dup() ); + addLayout( layout ); } - foreach ( Markup *markup, mMarkups ) + foreach ( Markup *markup, other.mMarkups ) { addMarkup( markup->dup() ); } @@ -72,7 +78,7 @@ namespace glabels } - const QList& Frame::layouts() const + const QList& Frame::layouts() const { return mLayouts; } @@ -89,13 +95,13 @@ namespace glabels QVector origins( nLabels() ); int i = 0; - foreach ( Layout *layout, mLayouts ) + foreach ( const Layout& layout, mLayouts ) { - for ( int iy = 0; iy < layout->ny(); iy++ ) + for ( int iy = 0; iy < layout.ny(); iy++ ) { - for ( int ix = 0; ix < layout->nx(); ix++ ) + for ( int ix = 0; ix < layout.nx(); ix++ ) { - origins[i++] = Point( ix*layout->dx() + layout->x0(), iy*layout->dy() + layout->y0() ); + origins[i++] = Point( ix*layout.dx() + layout.x0(), iy*layout.dy() + layout.y0() ); } } } @@ -106,12 +112,12 @@ namespace glabels } - void Frame::addLayout( Layout *layout ) + void Frame::addLayout( const Layout& layout ) { mLayouts << layout; // Update total number of labels - mNLabels += layout->nx() * layout->ny(); + mNLabels += layout.nx() * layout.ny(); // Update layout description if ( mLayouts.size() == 1 ) @@ -122,7 +128,7 @@ namespace glabels * %3 = total number of labels on a page (sheet). */ mLayoutDescription = QString( tr("%1 x %2 (%3 per sheet)") ) - .arg(layout->nx()).arg(layout->ny()).arg(mNLabels); + .arg(layout.nx()).arg(layout.ny()).arg(mNLabels); } else { @@ -137,5 +143,54 @@ namespace glabels mMarkups << markup; } + + void Frame::setH( const Distance& h ) + { + // Default implementation does nothing + } + + } +} + + +QDebug operator<<( QDebug dbg, const glabels::model::Frame& frame ) +{ + if ( auto* frameCd = dynamic_cast(&frame) ) + { + dbg << *frameCd; + return dbg; + } + else if ( auto* frameContinuous = dynamic_cast(&frame) ) + { + dbg << *frameContinuous; + return dbg; + } + else if ( auto* frameEllipse = dynamic_cast(&frame) ) + { + dbg << *frameEllipse; + return dbg; + } + else if ( auto* framePath = dynamic_cast(&frame) ) + { + dbg << *framePath; + return dbg; + } + else if ( auto* frameRect = dynamic_cast(&frame) ) + { + dbg << *frameRect; + return dbg; + } + else if ( auto* frameRound = dynamic_cast(&frame) ) + { + dbg << *frameRound; + return dbg; + } + else + { + QDebugStateSaver saver(dbg); + + dbg.nospace() << "UNKNOWN FRAME"; + + return dbg; } } diff --git a/model/Frame.h b/model/Frame.h index b2bbc2c..da8d55a 100644 --- a/model/Frame.h +++ b/model/Frame.h @@ -27,6 +27,7 @@ #include "Point.h" #include +#include #include #include #include @@ -56,23 +57,26 @@ namespace glabels QString id() const; int nLabels() const; QString layoutDescription() const; - const QList& layouts() const; + const QList& layouts() const; const QList& markups() const; QVector getOrigins() const; - void addLayout( Layout* layout ); + void addLayout( const Layout& layout ); void addMarkup( Markup* markup ); virtual Distance w() const = 0; virtual Distance h() const = 0; + virtual void setH( const Distance& h ); + virtual QString sizeDescription( const Units& units ) const = 0; virtual bool isSimilarTo( Frame* other ) const = 0; virtual const QPainterPath& path() const = 0; virtual const QPainterPath& clipPath() const = 0; - virtual QPainterPath marginPath( const Distance& size ) const = 0; + virtual QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const = 0; private: @@ -80,7 +84,7 @@ namespace glabels int mNLabels; QString mLayoutDescription; - QList mLayouts; + QList mLayouts; QList mMarkups; }; @@ -88,4 +92,8 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::Frame& frame ); + + #endif // model_Frame_h diff --git a/model/FrameCd.cpp b/model/FrameCd.cpp index ed4aad1..465ac24 100644 --- a/model/FrameCd.cpp +++ b/model/FrameCd.cpp @@ -93,15 +93,6 @@ namespace glabels } - FrameCd::FrameCd( const FrameCd& other ) - : Frame(other), - mR1(other.mR1), mR2(other.mR2), mW(other.mW), mH(other.mH), mWaste(other.mWaste), - mPath(other.mPath) - { - // empty - } - - Frame* FrameCd::dup() const { return new FrameCd( *this ); @@ -187,8 +178,12 @@ namespace glabels } - QPainterPath FrameCd::marginPath( const Distance& size ) const + QPainterPath FrameCd::marginPath( const Distance& xSize, + const Distance& ySize ) const { + // Note: ignore ySize, assume xSize == ySize + Distance size = xSize; + Distance wReal = (mW == 0) ? 2*mR1 : mW; Distance hReal = (mH == 0) ? 2*mR1 : mH; @@ -219,3 +214,22 @@ namespace glabels } } + + +QDebug operator<<( QDebug dbg, const glabels::model::FrameCd& frame ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "FrameCd{ " + << frame.id() << "," + << frame.r1() << "," + << frame.r2() << "," + << frame.waste() << "," + << frame.w() << "," + << frame.h() << "," + << frame.layouts() << "," + << frame.markups() + << " }"; + + return dbg; +} diff --git a/model/FrameCd.h b/model/FrameCd.h index 4805549..1c80075 100644 --- a/model/FrameCd.h +++ b/model/FrameCd.h @@ -42,7 +42,7 @@ namespace glabels const Distance& waste, const QString& id = "0" ); - FrameCd( const FrameCd &other ); + FrameCd( const FrameCd &other ) = default; Frame *dup() const override; @@ -58,7 +58,8 @@ namespace glabels const QPainterPath& path() const override; const QPainterPath& clipPath() const override; - QPainterPath marginPath( const Distance& size ) const override; + QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const override; private: @@ -77,4 +78,8 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::FrameCd& frame ); + + #endif // model_FrameCd_h diff --git a/model/FrameContinuous.cpp b/model/FrameContinuous.cpp new file mode 100644 index 0000000..16f2bc7 --- /dev/null +++ b/model/FrameContinuous.cpp @@ -0,0 +1,166 @@ +/* FrameContinuous.cpp + * + * Copyright (C) 2018 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 . + */ + +#include "FrameContinuous.h" + +#include "Constants.h" +#include "StrUtil.h" + + +namespace glabels +{ + namespace model + { + + FrameContinuous::FrameContinuous( const Distance& w, + const Distance& hMin, + const Distance& hMax, + const Distance& hDefault, + const QString& id ) + : Frame(id), mW(w), mHMin(hMin), mHMax(hMax), mHDefault(hDefault), mH(hDefault) + { + mPath.addRect( 0, 0, mW.pt(), mH.pt() ); + } + + + Frame* FrameContinuous::dup() const + { + return new FrameContinuous( *this ); + } + + + Distance FrameContinuous::w() const + { + return mW; + } + + + Distance FrameContinuous::h() const + { + return mH; + } + + + Distance FrameContinuous::hMin() const + { + return mHMin; + } + + + Distance FrameContinuous::hMax() const + { + return mHMax; + } + + + Distance FrameContinuous::hDefault() const + { + return mHDefault; + } + + + void FrameContinuous::setH( const Distance& h ) + { + mH = h; + mPath = QPainterPath(); // clear path + mPath.addRect( 0, 0, mW.pt(), mH.pt() ); + } + + + QString FrameContinuous::sizeDescription( const Units& units ) const + { + if ( units.toEnum() == Units::IN ) + { + QString wStr = StrUtil::formatFraction( mW.in() ); + + return QString().sprintf( "%s %s %s", + qPrintable(wStr), + qPrintable(units.toTrName()), + qPrintable(tr("wide")) ); + } + else + { + return QString().sprintf( "%.3f %s %s", + mW.inUnits(units), + qPrintable(units.toTrName()), + qPrintable(tr("wide")) ); + } + } + + + bool FrameContinuous::isSimilarTo( Frame* other ) const + { + if ( auto *otherContinuous = dynamic_cast(other) ) + { + if ( fabs( mW - otherContinuous->mW ) <= EPSILON ) + { + return true; + } + } + return false; + } + + + const QPainterPath& FrameContinuous::path() const + { + return mPath; + } + + + const QPainterPath& FrameContinuous::clipPath() const + { + return mPath; + } + + + QPainterPath FrameContinuous::marginPath( const Distance& xSize, + const Distance& ySize ) const + { + Distance w = mW - 2*xSize; + Distance h = mH - 2*ySize; + + QPainterPath path; + path.addRect( xSize.pt(), ySize.pt(), w.pt(), h.pt() ); + + return path; + } + + + } +} + + +QDebug operator<<( QDebug dbg, const glabels::model::FrameContinuous& frame ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "FrameContinuous{ " + << frame.id() << "," + << frame.w() << "," + << frame.h() << "," + << frame.hMin() << "," + << frame.hMax() << "," + << frame.hDefault() << "," + << frame.layouts() << "," + << frame.markups() + << " }"; + + return dbg; +} diff --git a/model/FrameContinuous.h b/model/FrameContinuous.h new file mode 100644 index 0000000..72ea002 --- /dev/null +++ b/model/FrameContinuous.h @@ -0,0 +1,85 @@ +/* FrameContinuous.h + * + * Copyright (C) 2018 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 model_FrameContinuous_h +#define model_FrameContinuous_h + + +#include "Frame.h" + + +namespace glabels +{ + namespace model + { + + class FrameContinuous : public Frame + { + Q_DECLARE_TR_FUNCTIONS(FrameContinuous) + + public: + FrameContinuous( const Distance& w, + const Distance& hMin, + const Distance& hMax, + const Distance& hDefault, + const QString& id = "0" ); + + FrameContinuous( const FrameContinuous& other ) = default; + + Frame* dup() const override; + + Distance w() const override; + Distance h() const override; + + Distance hMin() const; + Distance hMax() const; + Distance hDefault() const; + + void setH( const Distance& h ) override; + + QString sizeDescription( const Units& units ) const override; + + bool isSimilarTo( Frame* other ) const override; + + const QPainterPath& path() const override; + const QPainterPath& clipPath() const override; + QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const override; + + + private: + Distance mW; + Distance mHMin; + Distance mHMax; + Distance mHDefault; + Distance mH; + + QPainterPath mPath; + }; + + } +} + + +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::FrameContinuous& frame ); + + +#endif // model_FrameContinuous_h diff --git a/model/FrameEllipse.cpp b/model/FrameEllipse.cpp index 5c27f72..18b3844 100644 --- a/model/FrameEllipse.cpp +++ b/model/FrameEllipse.cpp @@ -40,13 +40,6 @@ namespace glabels } - FrameEllipse::FrameEllipse( const FrameEllipse& other ) - : Frame(other), mW(other.mW), mH(other.mH), mWaste(other.mWaste), mPath(other.mPath) - { - // empty - } - - Frame* FrameEllipse::dup() const { return new FrameEllipse( *this ); @@ -119,8 +112,12 @@ namespace glabels } - QPainterPath FrameEllipse::marginPath( const Distance& size ) const + QPainterPath FrameEllipse::marginPath( const Distance& xSize, + const Distance& ySize ) const { + // Note: ignore ySize, assume xSize == ySize + Distance size = xSize; + Distance w = mW - 2*size; Distance h = mH - 2*size; @@ -132,3 +129,20 @@ namespace glabels } } + + +QDebug operator<<( QDebug dbg, const glabels::model::FrameEllipse& frame ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "FrameEllipse{ " + << frame.id() << "," + << frame.w() << "," + << frame.h() << "," + << frame.waste() << "," + << frame.layouts() << "," + << frame.markups() + << " }"; + + return dbg; +} diff --git a/model/FrameEllipse.h b/model/FrameEllipse.h index 43c0ed2..1799740 100644 --- a/model/FrameEllipse.h +++ b/model/FrameEllipse.h @@ -40,7 +40,7 @@ namespace glabels const Distance& waste, const QString& id = "0" ); - FrameEllipse( const FrameEllipse& other ); + FrameEllipse( const FrameEllipse& other ) = default; Frame* dup() const override; @@ -54,7 +54,8 @@ namespace glabels const QPainterPath& path() const override; const QPainterPath& clipPath() const override; - QPainterPath marginPath( const Distance& size ) const override; + QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const override; private: @@ -71,4 +72,8 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::FrameEllipse& frame ); + + #endif // model_FrameEllipse_h diff --git a/model/FramePath.cpp b/model/FramePath.cpp new file mode 100644 index 0000000..dcf9f41 --- /dev/null +++ b/model/FramePath.cpp @@ -0,0 +1,157 @@ +/* FramePath.cpp + * + * Copyright (C) 2018 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 . + */ + +#include "FramePath.h" + +#include "Constants.h" +#include "StrUtil.h" + + +namespace glabels +{ + namespace model + { + + FramePath::FramePath( const QPainterPath& path, + const Distance& xWaste, + const Distance& yWaste, + const Units& originalUnits, + const QString& id ) + : Frame(id), mXWaste(xWaste), mYWaste(yWaste), mPath(path), mOriginalUnits(originalUnits) + { + QRectF r = path.boundingRect(); + + mW = Distance::pt( r.width() ); + mH = Distance::pt( r.height() ); + + mClipPath.addRect( r.x()-mXWaste.pt(), r.y()-mYWaste.pt(), + r.width() + 2*mXWaste.pt(), r.height() + 2*mYWaste.pt() ); + } + + + Frame* FramePath::dup() const + { + return new FramePath( *this ); + } + + + Distance FramePath::w() const + { + return mW; + } + + + Distance FramePath::h() const + { + return mH; + } + + + Distance FramePath::xWaste() const + { + return mXWaste; + } + + + Distance FramePath::yWaste() const + { + return mYWaste; + } + + + Units FramePath::originalUnits() const + { + return mOriginalUnits; + } + + + QString FramePath::sizeDescription( const Units& units ) const + { + if ( units.toEnum() == Units::IN ) + { + QString wStr = StrUtil::formatFraction( mW.in() ); + QString hStr = StrUtil::formatFraction( mH.in() ); + + return QString().sprintf( "%s x %s %s", + qPrintable(wStr), + qPrintable(hStr), + qPrintable(units.toTrName()) ); + } + else + { + return QString().sprintf( "%.5g x %.5g %s", + mW.inUnits(units), + mH.inUnits(units), + qPrintable(units.toTrName()) ); + } + } + + + bool FramePath::isSimilarTo( Frame* other ) const + { + if ( auto *otherPath = dynamic_cast(other) ) + { + if ( mPath == otherPath->mPath ) + { + return true; + } + } + return false; + } + + + const QPainterPath& FramePath::path() const + { + return mPath; + } + + + const QPainterPath& FramePath::clipPath() const + { + return mClipPath; + } + + + QPainterPath FramePath::marginPath( const Distance& xSize, + const Distance& ySize ) const + { + return mPath; // No margin + } + + + } +} + + +QDebug operator<<( QDebug dbg, const glabels::model::FramePath& frame ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "FramePath{ " + << frame.id() << "," + << frame.path() << "," + << frame.xWaste() << "," + << frame.yWaste() << "," + << frame.layouts() << "," + << frame.markups() + << " }"; + + return dbg; +} diff --git a/model/FramePath.h b/model/FramePath.h new file mode 100644 index 0000000..774b2fb --- /dev/null +++ b/model/FramePath.h @@ -0,0 +1,86 @@ +/* FramePath.h + * + * Copyright (C) 2018 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 model_FramePath_h +#define model_FramePath_h + + +#include "Frame.h" + + +namespace glabels +{ + namespace model + { + + class FramePath : public Frame + { + Q_DECLARE_TR_FUNCTIONS(FramePath) + + public: + FramePath( const QPainterPath& path, + const Distance& xWaste, + const Distance& yWaste, + const Units& originalUnits, + const QString& id = "0" ); + + FramePath( const FramePath& other ) = default; + + Frame* dup() const override; + + Distance xWaste() const; + Distance yWaste() const; + + Units originalUnits() const; + + Distance w() const override; + Distance h() const override; + + QString sizeDescription( const Units& units ) const override; + + bool isSimilarTo( Frame* other ) const override; + + const QPainterPath& path() const override; + const QPainterPath& clipPath() const override; + QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const override; + + + private: + Distance mW; + Distance mH; + Distance mXWaste; + Distance mYWaste; + + QPainterPath mPath; + QPainterPath mClipPath; + + Units mOriginalUnits; + }; + + } +} + + +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::FramePath& frame ); + + +#endif // model_FramePath_h diff --git a/model/FrameRect.cpp b/model/FrameRect.cpp index 373e289..204eb74 100644 --- a/model/FrameRect.cpp +++ b/model/FrameRect.cpp @@ -44,16 +44,7 @@ namespace glabels mR.pt(), mR.pt() ); } - - FrameRect::FrameRect( const FrameRect &other ) - : Frame(other), - mW(other.mW), mH(other.mH), mR(other.mR), mXWaste(other.mXWaste), - mYWaste(other.mYWaste), mPath(other.mPath) - { - // empty - } - Frame* FrameRect::dup() const { return new FrameRect( *this ); @@ -138,14 +129,15 @@ namespace glabels } - QPainterPath FrameRect::marginPath( const Distance& size ) const + QPainterPath FrameRect::marginPath( const Distance& xSize, + const Distance& ySize ) const { - Distance w = mW - 2*size; - Distance h = mH - 2*size; - Distance r = std::max( mR - size, Distance(0.0) ); + Distance w = mW - 2*xSize; + Distance h = mH - 2*ySize; + Distance r = std::max( mR - std::min(xSize, ySize), Distance(0.0) ); QPainterPath path; - path.addRoundedRect( size.pt(), size.pt(), w.pt(), h.pt(), r.pt(), r.pt() ); + path.addRoundedRect( xSize.pt(), ySize.pt(), w.pt(), h.pt(), r.pt(), r.pt() ); return path; } @@ -153,3 +145,22 @@ namespace glabels } } + + +QDebug operator<<( QDebug dbg, const glabels::model::FrameRect& frame ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "FrameRect{ " + << frame.id() << "," + << frame.w() << "," + << frame.h() << "," + << frame.r() << "," + << frame.xWaste() << "," + << frame.yWaste() << "," + << frame.layouts() << "," + << frame.markups() + << " }"; + + return dbg; +} diff --git a/model/FrameRect.h b/model/FrameRect.h index 03438ae..315b714 100644 --- a/model/FrameRect.h +++ b/model/FrameRect.h @@ -42,7 +42,7 @@ namespace glabels const Distance& yWaste, const QString& id = "0" ); - FrameRect( const FrameRect& other ); + FrameRect( const FrameRect& other ) = default; Frame* dup() const override; @@ -59,7 +59,8 @@ namespace glabels const QPainterPath& path() const override; const QPainterPath& clipPath() const override; - QPainterPath marginPath( const Distance& size ) const override; + QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const override; private: @@ -78,4 +79,8 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::FrameRect& frame ); + + #endif // model_FrameRect_h diff --git a/model/FrameRound.cpp b/model/FrameRound.cpp index fe39ecb..b1c4f7b 100644 --- a/model/FrameRound.cpp +++ b/model/FrameRound.cpp @@ -40,13 +40,6 @@ namespace glabels } - FrameRound::FrameRound( const FrameRound& other ) - : Frame(other), mR(other.mR), mWaste(other.mWaste), mPath(other.mPath) - { - // empty - } - - Frame* FrameRound::dup() const { return new FrameRound( *this ); @@ -123,8 +116,12 @@ namespace glabels } - QPainterPath FrameRound::marginPath( const Distance& size ) const + QPainterPath FrameRound::marginPath( const Distance& xSize, + const Distance& ySize ) const { + // Note: ignore ySize, assume xSize == ySize + Distance size = xSize; + Distance r = mR - size; QPainterPath path; @@ -135,3 +132,19 @@ namespace glabels } } + + +QDebug operator<<( QDebug dbg, const glabels::model::FrameRound& frame ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "FrameRound{ " + << frame.id() << "," + << frame.r() << "," + << frame.waste() << "," + << frame.layouts() << "," + << frame.markups() + << " }"; + + return dbg; +} diff --git a/model/FrameRound.h b/model/FrameRound.h index 41c53e9..ad296c9 100644 --- a/model/FrameRound.h +++ b/model/FrameRound.h @@ -39,7 +39,7 @@ namespace glabels const Distance& waste, const QString& id = "0" ); - FrameRound( const FrameRound &other ); + FrameRound( const FrameRound &other ) = default; Frame *dup() const override; @@ -54,7 +54,8 @@ namespace glabels const QPainterPath& path() const override; const QPainterPath& clipPath() const override; - QPainterPath marginPath( const Distance& size ) const override; + QPainterPath marginPath( const Distance& xSize, + const Distance& ySize ) const override; private: @@ -70,4 +71,8 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::FrameRound& frame ); + + #endif // model_FrameRound_h diff --git a/model/Layout.cpp b/model/Layout.cpp index dc5069c..abc9f9f 100644 --- a/model/Layout.cpp +++ b/model/Layout.cpp @@ -86,22 +86,32 @@ namespace glabels } - bool Layout::isSimilarTo( const Layout *other ) + bool Layout::isSimilarTo( const Layout& other ) const { - return ( (mNx == other->mNx) && - (mNy == other->mNy) && - (fabs(mX0 - other->mX0) < EPSILON) && - (fabs(mY0 - other->mY0) < EPSILON) && - (fabs(mDx - other->mDx) < EPSILON) && - (fabs(mDy - other->mDy) < EPSILON) ); - } - - - Layout* Layout::dup() const - { - auto *other = new Layout( *this ); - return other; + return ( (mNx == other.mNx) && + (mNy == other.mNy) && + (fabs(mX0 - other.mX0) < EPSILON) && + (fabs(mY0 - other.mY0) < EPSILON) && + (fabs(mDx - other.mDx) < EPSILON) && + (fabs(mDy - other.mDy) < EPSILON) ); } } } + + +QDebug operator<<( QDebug dbg, const glabels::model::Layout& layout ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "Layout{ " + << layout.nx() << "," + << layout.ny() << "," + << layout.x0() << "," + << layout.y0() << "," + << layout.dx() << "," + << layout.dy() + << " }"; + + return dbg; +} diff --git a/model/Layout.h b/model/Layout.h index 3485780..853c10d 100644 --- a/model/Layout.h +++ b/model/Layout.h @@ -24,6 +24,8 @@ #include "Distance.h" +#include + namespace glabels { @@ -52,9 +54,7 @@ namespace glabels Distance dx() const; Distance dy() const; - bool isSimilarTo( const Layout *other ); - - Layout* dup() const; + bool isSimilarTo( const Layout& other ) const; private: @@ -71,4 +71,8 @@ namespace glabels } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::Layout& layout ); + + #endif // model_Layout_h diff --git a/model/Markup.cpp b/model/Markup.cpp index 4f16ae9..83edb0d 100644 --- a/model/Markup.cpp +++ b/model/Markup.cpp @@ -26,29 +26,48 @@ namespace glabels namespace model { - const QPainterPath& Markup::path() const + QPainterPath Markup::path( const Frame* frame ) const { + // Use cached path -- default does not depend on frame size return mPath; } - MarkupMargin::MarkupMargin( const Frame* frame, - const Distance& size ) - : mFrame(frame), mSize(size) + MarkupMargin::MarkupMargin( const Distance& size ) + : mXSize(size), mYSize(size) { - mPath = frame->marginPath( size ); } + MarkupMargin::MarkupMargin( const Distance& xSize, + const Distance& ySize ) + : mXSize(xSize), mYSize(ySize) + { + } + + + QPainterPath MarkupMargin::path( const Frame* frame ) const + { + // Re-calculate path -- frame size may have changed + return frame->marginPath( mXSize, mYSize ); + } + + Markup* MarkupMargin::dup() const { - return new MarkupMargin( mFrame, mSize ); + return new MarkupMargin( mXSize, mYSize ); } - Distance MarkupMargin::size() const + Distance MarkupMargin::xSize() const { - return mSize; + return mXSize; + } + + + Distance MarkupMargin::ySize() const + { + return mYSize; } diff --git a/model/Markup.h b/model/Markup.h index 1c57859..fa39365 100644 --- a/model/Markup.h +++ b/model/Markup.h @@ -37,7 +37,7 @@ namespace glabels public: virtual Markup* dup() const = 0; - const QPainterPath& path() const; + virtual QPainterPath path( const Frame* frame ) const; protected: QPainterPath mPath; @@ -47,16 +47,21 @@ namespace glabels class MarkupMargin : public Markup { public: - MarkupMargin( const Frame* frame, - const Distance& size ); + MarkupMargin( const Distance& size ); - Distance size() const; + MarkupMargin( const Distance& xSize, + const Distance& ySize ); + + QPainterPath path( const Frame* frame ) const override; + + Distance xSize() const; + Distance ySize() const; Markup* dup() const override; private: - const Frame* mFrame; - Distance mSize; + Distance mXSize; + Distance mYSize; }; diff --git a/model/Model.cpp b/model/Model.cpp index 774ebab..b0eb83d 100644 --- a/model/Model.cpp +++ b/model/Model.cpp @@ -55,12 +55,21 @@ namespace glabels /// Default constructor. /// Model::Model() - : mUntitledInstance(0), mModified(true), mTmplate(nullptr), mFrame(nullptr), mRotate(false) + : mUntitledInstance(0), mModified(true), mRotate(false) { mMerge = new merge::None(); } + /// + /// Destructor. + /// + Model::~Model() + { + delete mMerge; + } + + /// /// Save model state /// @@ -90,7 +99,6 @@ namespace glabels mModified = savedModel->mModified; mFileName = savedModel->mFileName; mTmplate = savedModel->mTmplate; - mFrame = savedModel->mFrame; mRotate = savedModel->mRotate; foreach ( ModelObject* savedObject, savedModel->mObjectList ) @@ -155,7 +163,7 @@ namespace glabels /// const Template* Model::tmplate() const { - return mTmplate; + return &mTmplate; } @@ -164,7 +172,7 @@ namespace glabels /// const Frame* Model::frame() const { - return mFrame; + return mTmplate.frames().constFirst(); } @@ -173,18 +181,14 @@ namespace glabels /// void Model::setTmplate( const Template* tmplate ) { - if (mTmplate != tmplate) - { - mTmplate = tmplate; - mFrame = tmplate->frames().first(); + mTmplate = *tmplate; - setModified(); + setModified(); - emit changed(); - emit sizeChanged(); + emit changed(); + emit sizeChanged(); - Settings::addToRecentTemplateList( tmplate->name() ); - } + Settings::addToRecentTemplateList( tmplate->name() ); } @@ -219,7 +223,14 @@ namespace glabels /// Distance Model::w() const { - return mRotate ? mFrame->h() : mFrame->w(); + if ( auto* frame = mTmplate.frames().constFirst() ) + { + return mRotate ? frame->h() : frame->w(); + } + else + { + return Distance::pt(0); + } } @@ -228,7 +239,31 @@ namespace glabels /// Distance Model::h() const { - return mRotate ? mFrame->w() : mFrame->h(); + if ( auto* frame = mTmplate.frames().constFirst() ) + { + return mRotate ? frame->w() : frame->h(); + } + else + { + return Distance::pt(0); + } + } + + + /// + /// Set height (if variable length) + /// + void Model::setH( const Distance& h ) + { + if ( auto* frame = mTmplate.frames().first() ) + { + frame->setH( h ); + + setModified(); + + emit changed(); + emit sizeChanged(); + } } diff --git a/model/Model.h b/model/Model.h index e1d0cfa..992606e 100644 --- a/model/Model.h +++ b/model/Model.h @@ -57,7 +57,7 @@ namespace glabels ///////////////////////////////// public: Model(); - ~Model() override = default; + ~Model(); ///////////////////////////////// @@ -103,6 +103,8 @@ namespace glabels Distance w() const; Distance h() const; + void setH( const Distance& h ); + const QList& objectList() const; merge::Merge* merge() const; @@ -222,11 +224,10 @@ namespace glabels int mUntitledInstance; bool mModified; QString mFileName; - const Template* mTmplate; - const Frame* mFrame; + Template mTmplate; bool mRotate; - QList mObjectList; + QList mObjectList; merge::Merge* mMerge; }; diff --git a/model/PageRenderer.cpp b/model/PageRenderer.cpp index 3d7d237..9c2b702 100644 --- a/model/PageRenderer.cpp +++ b/model/PageRenderer.cpp @@ -193,6 +193,10 @@ namespace glabels void PageRenderer::print( QPrinter* printer ) const { QSizeF pageSize( mModel->tmplate()->pageWidth().pt(), mModel->tmplate()->pageHeight().pt() ); + if ( mModel->tmplate()->pageWidth().pt() > mModel->tmplate()->pageHeight().pt() ) + { + printer->setOrientation( QPrinter::Landscape ); + } printer->setPageSize( QPageSize(pageSize, QPageSize::Point) ); printer->setFullPage( true ); printer->setPageMargins( 0, 0, 0, 0, QPrinter::Point ); @@ -338,16 +342,16 @@ namespace glabels Distance w = mModel->frame()->w(); Distance h = mModel->frame()->h(); - foreach ( Layout* layout, mModel->frame()->layouts() ) + foreach ( const Layout& layout, mModel->frame()->layouts() ) { - Distance xMin = layout->x0(); - Distance yMin = layout->y0(); - Distance xMax = layout->x0() + layout->dx()*(layout->nx()-1) + w; - Distance yMax = layout->y0() + layout->dy()*(layout->ny()-1) + h; + Distance xMin = layout.x0(); + Distance yMin = layout.y0(); + Distance xMax = layout.x0() + layout.dx()*(layout.nx()-1) + w; + Distance yMax = layout.y0() + layout.dy()*(layout.ny()-1) + h; - for ( int ix = 0; ix < layout->nx(); ix++ ) + for ( int ix = 0; ix < layout.nx(); ix++ ) { - Distance x1 = xMin + ix*layout->dx(); + Distance x1 = xMin + ix*layout.dx(); Distance x2 = x1 + w; Distance y1 = max( yMin-tickOffset, Distance::pt(0) ); @@ -362,9 +366,9 @@ namespace glabels painter->drawLine( x2.pt(), y3.pt(), x2.pt(), y4.pt() ); } - for ( int iy = 0; iy < layout->ny(); iy++ ) + for ( int iy = 0; iy < layout.ny(); iy++ ) { - Distance y1 = yMin + iy*layout->dy(); + Distance y1 = yMin + iy*layout.dy(); Distance y2 = y1 + h; Distance x1 = max( xMin-tickOffset, Distance::pt(0) ); diff --git a/model/StrUtil.cpp b/model/StrUtil.cpp index 4c318f7..169f7cd 100644 --- a/model/StrUtil.cpp +++ b/model/StrUtil.cpp @@ -61,7 +61,7 @@ namespace glabels if ( denom[i] == 0.0 ) { /* None of our denominators work. */ - return QString().sprintf( "%.5g", x ); + return QString().sprintf( "%.3f", x ); } if ( denom[i] == 1.0 ) { diff --git a/model/Template.cpp b/model/Template.cpp index 6acc685..690b56c 100644 --- a/model/Template.cpp +++ b/model/Template.cpp @@ -21,6 +21,7 @@ #include "Template.h" #include "Db.h" +#include "FrameContinuous.h" #include @@ -36,6 +37,7 @@ namespace glabels const QString& paperId, const Distance& pageWidth, const Distance& pageHeight, + const Distance& rollWidth, bool isUserDefined ) : mBrand(brand), mPart(part), @@ -43,6 +45,7 @@ namespace glabels mPaperId(paperId), mPageWidth(pageWidth), mPageHeight(pageHeight), + mRollWidth(rollWidth), mIsUserDefined(isUserDefined), mIsSizeIso(false), mIsSizeUs(false), @@ -56,6 +59,8 @@ namespace glabels mIsSizeIso = paper->isSizeIso(); mIsSizeUs = paper->isSizeUs(); } + + mIsRoll = (paperId == "roll"); } @@ -67,15 +72,17 @@ namespace glabels mPaperId = other.mPaperId; mPageWidth = other.mPageWidth; mPageHeight = other.mPageHeight; + mRollWidth = other.mRollWidth; mIsSizeIso = other.mIsSizeIso; mIsSizeUs = other.mIsSizeUs; + mIsRoll = other.mIsRoll; mEquivPart = other.mEquivPart; mName = other.mName; mProductUrl = other.mProductUrl; foreach ( Frame* frame, other.mFrames ) { - addFrame( frame ); + addFrame( frame->dup() ); } foreach ( QString categoryId, other.mCategoryIds ) @@ -85,9 +92,50 @@ namespace glabels } - Template* Template::dup() const + Template::~Template() { - return new Template( *this ); + while ( !mFrames.isEmpty() ) + { + delete mFrames.takeFirst(); + } + } + + + Template& Template::operator=( const Template& other ) + { + if ( this != &other ) + { + mBrand = other.mBrand; + mPart = other.mPart; + mDescription = other.mDescription; + mPaperId = other.mPaperId; + mPageWidth = other.mPageWidth; + mPageHeight = other.mPageHeight; + mRollWidth = other.mRollWidth; + mIsSizeIso = other.mIsSizeIso; + mIsSizeUs = other.mIsSizeUs; + mIsRoll = other.mIsRoll; + mEquivPart = other.mEquivPart; + mName = other.mName; + mProductUrl = other.mProductUrl; + + while ( !mFrames.isEmpty() ) + { + delete mFrames.takeFirst(); + } + foreach ( Frame* frame, other.mFrames ) + { + addFrame( frame->dup() ); + } + + mCategoryIds.clear(); + foreach ( QString categoryId, other.mCategoryIds ) + { + addCategory( categoryId ); + } + } + + return *this; } @@ -107,7 +155,7 @@ namespace glabels const Template* other = Db::lookupTemplateFromBrandPart( brand, equivPart ); if ( other != nullptr ) { - Template* tmplate = other->dup(); + Template* tmplate = new Template( *other ); tmplate->mPart = part; tmplate->mEquivPart = equivPart; @@ -159,7 +207,22 @@ namespace glabels Distance Template::pageHeight() const { - return mPageHeight; + // Adjust height if continuous tape + const model::Frame* frame = mFrames.constFirst(); + if ( const auto* frameContinuous = dynamic_cast(frame) ) + { + return frameContinuous->h(); + } + else + { + return mPageHeight; + } + } + + + Distance Template::rollWidth() const + { + return mRollWidth; } @@ -181,6 +244,12 @@ namespace glabels } + bool Template::isRoll() const + { + return mIsRoll; + } + + bool Template::isUserDefined() const { return mIsUserDefined; @@ -274,12 +343,12 @@ namespace glabels } // Are they layed out similarly? - foreach ( Layout* layout1, frame1->layouts() ) + foreach ( const Layout& layout1, frame1->layouts() ) { bool matchFound = false; - foreach ( Layout* layout2, frame2->layouts() ) + foreach ( const Layout& layout2, frame2->layouts() ) { - if ( layout1->isSimilarTo(layout2) ) + if ( layout1.isSimilarTo( layout2 ) ) { matchFound = true; break; @@ -297,3 +366,23 @@ namespace glabels } } + + +QDebug operator<<( QDebug dbg, const glabels::model::Template& tmplate ) +{ + QDebugStateSaver saver(dbg); + + dbg.nospace() << "Template{ " + << tmplate.brand() << "," << tmplate.part() << "," << tmplate.description() << "," + << tmplate.paperId() << "," + << tmplate.pageWidth() << "," + << tmplate.pageHeight() << "," + << tmplate.rollWidth() << "," + << tmplate.isSizeIso() << "," + << tmplate.isSizeUs() << "," + << tmplate.isSizeOther() << "," + << tmplate.isRoll() << "," + << *tmplate.frames().constFirst() << "," + << " }"; + return dbg; +} diff --git a/model/Template.h b/model/Template.h index 144d8a6..c83faf9 100644 --- a/model/Template.h +++ b/model/Template.h @@ -43,17 +43,22 @@ namespace glabels public: + Template() = default; + Template( const QString& brand, const QString& part, const QString& description, const QString& paperId, const Distance& pageWidth, const Distance& pageHeight, + const Distance& rollWidth = 0, bool isUserDefined = false ); Template( const Template& other ); - Template* dup() const; + ~Template(); + + Template& operator=( const Template& other ); // Generic full page template static Template* fullPage( const QString& paperId ); @@ -71,9 +76,11 @@ namespace glabels QString paperId() const; Distance pageWidth() const; Distance pageHeight() const; + Distance rollWidth() const; bool isSizeIso() const; bool isSizeUs() const; bool isSizeOther() const; + bool isRoll() const; bool isUserDefined() const; @@ -104,8 +111,10 @@ namespace glabels QString mPaperId; Distance mPageWidth; Distance mPageHeight; + Distance mRollWidth; bool mIsSizeIso; bool mIsSizeUs; + bool mIsRoll; bool mIsUserDefined; @@ -119,7 +128,12 @@ namespace glabels }; } + } +// Debugging support +QDebug operator<<( QDebug dbg, const glabels::model::Template& tmplate ); + + #endif // model_Template_h diff --git a/model/XmlTemplateCreator.cpp b/model/XmlTemplateCreator.cpp index e4ef1b7..8892a63 100644 --- a/model/XmlTemplateCreator.cpp +++ b/model/XmlTemplateCreator.cpp @@ -91,7 +91,10 @@ namespace glabels XmlUtil::setLengthAttr( node, "width", tmplate->pageWidth() ); XmlUtil::setLengthAttr( node, "height", tmplate->pageHeight() ); } - + if ( tmplate->isRoll() ) + { + XmlUtil::setLengthAttr( node, "roll_width", tmplate->rollWidth() ); + } XmlUtil::setStringAttr( node, "description", tmplate->description() ); @@ -141,6 +144,14 @@ namespace glabels { createLabelCdNode( parent, frameCd ); } + else if ( const auto* framePath = dynamic_cast(frame) ) + { + createLabelPathNode( parent, framePath ); + } + else if ( const auto* frameContinuous = dynamic_cast(frame) ) + { + createLabelContinuousNode( parent, frameContinuous ); + } else { Q_ASSERT_X( false, "XmlTemplateCreator::createLabelNode", "Invalid frame type." ); @@ -217,6 +228,39 @@ namespace glabels } + void XmlTemplateCreator::createLabelPathNode( QDomElement &parent, const FramePath* frame ) + { + QDomDocument doc = parent.ownerDocument(); + QDomElement node = doc.createElement( "Label-path" ); + parent.appendChild( node ); + + XmlUtil::setStringAttr( node, "id", frame->id() ); + XmlUtil::setLengthAttr( node, "x_waste", frame->xWaste() ); + XmlUtil::setLengthAttr( node, "y_waste", frame->yWaste() ); + XmlUtil::setUnitsAttr( node, "d_units", frame->originalUnits() ); + XmlUtil::setPathDataAttr( node, "d", frame->path(), frame->originalUnits() ); + + createLabelNodeCommon( node, frame ); + } + + + void XmlTemplateCreator::createLabelContinuousNode( QDomElement &parent, const FrameContinuous* frame ) + { + QDomDocument doc = parent.ownerDocument(); + QDomElement node = doc.createElement( "Label-continuous" ); + parent.appendChild( node ); + + XmlUtil::setStringAttr( node, "id", frame->id() ); + XmlUtil::setLengthAttr( node, "width", frame->w() ); + XmlUtil::setLengthAttr( node, "height", frame->h() ); + XmlUtil::setLengthAttr( node, "min_height", frame->hMin() ); + XmlUtil::setLengthAttr( node, "max_height", frame->hMin() ); + XmlUtil::setLengthAttr( node, "default_height", frame->hDefault() ); + + createLabelNodeCommon( node, frame ); + } + + void XmlTemplateCreator::createLabelNodeCommon( QDomElement &node, const Frame *frame ) { foreach ( Markup* markup, frame->markups() ) @@ -247,27 +291,27 @@ namespace glabels } } - foreach ( Layout* layout, frame->layouts() ) + foreach ( const Layout& layout, frame->layouts() ) { createLayoutNode( node, layout ); } } - void XmlTemplateCreator::createLayoutNode( QDomElement& parent, const Layout* layout ) + void XmlTemplateCreator::createLayoutNode( QDomElement& parent, const Layout& layout ) { QDomDocument doc = parent.ownerDocument(); QDomElement node = doc.createElement( "Layout" ); parent.appendChild( node ); - XmlUtil::setIntAttr( node, "nx", layout->nx() ); - XmlUtil::setIntAttr( node, "ny", layout->ny() ); + XmlUtil::setIntAttr( node, "nx", layout.nx() ); + XmlUtil::setIntAttr( node, "ny", layout.ny() ); - XmlUtil::setLengthAttr( node, "x0", layout->x0() ); - XmlUtil::setLengthAttr( node, "y0", layout->y0() ); + XmlUtil::setLengthAttr( node, "x0", layout.x0() ); + XmlUtil::setLengthAttr( node, "y0", layout.y0() ); - XmlUtil::setLengthAttr( node, "dx", layout->dx() ); - XmlUtil::setLengthAttr( node, "dy", layout->dy() ); + XmlUtil::setLengthAttr( node, "dx", layout.dx() ); + XmlUtil::setLengthAttr( node, "dy", layout.dy() ); } @@ -277,7 +321,15 @@ namespace glabels QDomElement node = doc.createElement( "Markup-margin" ); parent.appendChild( node ); - XmlUtil::setLengthAttr( node, "size", markup->size() ); + if ( markup->xSize() == markup->ySize() ) + { + XmlUtil::setLengthAttr( node, "size", markup->xSize() ); + } + else + { + XmlUtil::setLengthAttr( node, "x_size", markup->xSize() ); + XmlUtil::setLengthAttr( node, "y_size", markup->ySize() ); + } } diff --git a/model/XmlTemplateCreator.h b/model/XmlTemplateCreator.h index 1b88eb0..46e50ca 100644 --- a/model/XmlTemplateCreator.h +++ b/model/XmlTemplateCreator.h @@ -23,7 +23,9 @@ #include "FrameCd.h" +#include "FrameContinuous.h" #include "FrameEllipse.h" +#include "FramePath.h" #include "FrameRect.h" #include "FrameRound.h" #include "Layout.h" @@ -55,8 +57,10 @@ namespace glabels void createLabelEllipseNode( QDomElement& parent, const FrameEllipse* frame ); void createLabelRoundNode( QDomElement& parent, const FrameRound* frame ); void createLabelCdNode( QDomElement& parent, const FrameCd* frame ); + void createLabelPathNode( QDomElement& parent, const FramePath* frame ); + void createLabelContinuousNode( QDomElement& parent, const FrameContinuous* frame ); void createLabelNodeCommon( QDomElement& node, const Frame* frame ); - void createLayoutNode( QDomElement& parent, const Layout* layout ); + void createLayoutNode( QDomElement& parent, const Layout& layout ); void createMarkupMarginNode( QDomElement& parent, const MarkupMargin* markupMargin ); void createMarkupLineNode( QDomElement& parent, const MarkupLine* markupLine ); void createMarkupCircleNode( QDomElement& parent, const MarkupCircle* markupCircle ); diff --git a/model/XmlTemplateParser.cpp b/model/XmlTemplateParser.cpp index 3bf7452..561a4dd 100644 --- a/model/XmlTemplateParser.cpp +++ b/model/XmlTemplateParser.cpp @@ -25,6 +25,8 @@ #include "FrameCd.h" #include "FrameRound.h" #include "FrameEllipse.h" +#include "FramePath.h" +#include "FrameContinuous.h" #include "Layout.h" #include "Markup.h" #include "Template.h" @@ -153,7 +155,7 @@ namespace glabels QString description = XmlUtil::getI18nAttr( node, "description", "" ); QString paperId = XmlUtil::getStringAttr( node, "size", "" ); - if ( !Db::isPaperIdOther( paperId ) ) + if ( Db::isPaperIdKnown( paperId ) ) { const Paper *paper = Db::lookupPaperFromId( paperId ); if ( paper == nullptr ) @@ -169,8 +171,9 @@ namespace glabels { Distance width = XmlUtil::getLengthAttr( node, "width", Distance(0) ); Distance height = XmlUtil::getLengthAttr( node, "height", Distance(0) ); + Distance rollWidth = XmlUtil::getLengthAttr( node, "roll_width", Distance(0) ); - tmplate = new Template( brand, part, description, paperId, width, height, isUserDefined ); + tmplate = new Template( brand, part, description, paperId, width, height, rollWidth, isUserDefined ); } for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() ) @@ -195,6 +198,14 @@ namespace glabels { parseLabelCdNode( child.toElement(), tmplate ); } + else if ( child.toElement().tagName() == "Label-path" ) + { + parseLabelPathNode( child.toElement(), tmplate ); + } + else if ( child.toElement().tagName() == "Label-continuous" ) + { + parseLabelContinuousNode( child.toElement(), tmplate ); + } else if ( !child.isComment() ) { qWarning() << "Warning: bad element: " @@ -303,6 +314,57 @@ namespace glabels } + void XmlTemplateParser::parseLabelPathNode( const QDomElement &node, Template *tmplate ) + { + QString id = XmlUtil::getStringAttr( node, "id", "0" ); + + Units dUnits = XmlUtil::getUnitsAttr( node, "d_units", Units::pc() ); + QPainterPath d = XmlUtil::getPathDataAttr( node, "d", dUnits ); + + Distance xWaste, yWaste; + + Distance waste = XmlUtil::getLengthAttr( node, "waste", Distance(-1) ); + if ( waste >= Distance(0) ) + { + xWaste = waste; + yWaste = waste; + } + else + { + xWaste = XmlUtil::getLengthAttr( node, "x_waste", Distance(0) ); + yWaste = XmlUtil::getLengthAttr( node, "y_waste", Distance(0) ); + } + + Frame *frame = new FramePath( d, xWaste, yWaste, dUnits, id ); + + parseLabelNodeCommon( node, frame ); + + tmplate->addFrame( frame ); + } + + + void XmlTemplateParser::parseLabelContinuousNode( const QDomElement &node, Template *tmplate ) + { + QString id = XmlUtil::getStringAttr( node, "id", "0" ); + + Distance w = XmlUtil::getLengthAttr( node, "width", Distance(0) ); + Distance h = XmlUtil::getLengthAttr( node, "height", Distance(0) ); + Distance hMin = XmlUtil::getLengthAttr( node, "min_height", Distance(0) ); + Distance hMax = XmlUtil::getLengthAttr( node, "max_height", Distance(0) ); + Distance hDefault = XmlUtil::getLengthAttr( node, "default_height", Distance(0) ); + + Frame *frame = new FrameContinuous( w, hMin, hMax, hDefault, id ); + if ( h > Distance(0) ) + { + frame->setH( h ); + } + + parseLabelNodeCommon( node, frame ); + + tmplate->addFrame( frame ); + } + + void XmlTemplateParser::parseLabelNodeCommon( const QDomElement &node, Frame *frame ) { for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() ) @@ -352,15 +414,24 @@ namespace glabels Distance dX = XmlUtil::getLengthAttr( node, "dx", Distance(0) ); Distance dY = XmlUtil::getLengthAttr( node, "dy", Distance(0) ); - frame->addLayout( new Layout( nX, nY, x0, y0, dX, dY ) ); + frame->addLayout( Layout( nX, nY, x0, y0, dX, dY ) ); } void XmlTemplateParser::parseMarkupMarginNode( const QDomElement &node, Frame *frame ) { - Distance size = XmlUtil::getLengthAttr( node, "size", Distance(0) ); + Distance size = XmlUtil::getLengthAttr( node, "size", Distance(0) ); + Distance xSize = XmlUtil::getLengthAttr( node, "x_size", Distance(0) ); + Distance ySize = XmlUtil::getLengthAttr( node, "y_size", Distance(0) ); - frame->addMarkup( new MarkupMargin( frame, size ) ); + if ( size > Distance(0) ) + { + frame->addMarkup( new MarkupMargin( size ) ); + } + else + { + frame->addMarkup( new MarkupMargin( xSize, ySize ) ); + } } diff --git a/model/XmlTemplateParser.h b/model/XmlTemplateParser.h index e48434f..4683d0d 100644 --- a/model/XmlTemplateParser.h +++ b/model/XmlTemplateParser.h @@ -48,6 +48,8 @@ namespace glabels void parseLabelEllipseNode( const QDomElement &node, Template *tmplate ); void parseLabelRoundNode( const QDomElement &node, Template *tmplate ); void parseLabelCdNode( const QDomElement &node, Template *tmplate ); + void parseLabelPathNode( const QDomElement &node, Template *tmplate ); + void parseLabelContinuousNode( const QDomElement &node, Template *tmplate ); void parseLabelNodeCommon( const QDomElement &node, Frame *frame ); void parseLayoutNode( const QDomElement &node, Frame *frame ); void parseMarkupMarginNode( const QDomElement &node, Frame *frame ); diff --git a/model/XmlUtil.cpp b/model/XmlUtil.cpp index 0d4a5fe..45e246b 100644 --- a/model/XmlUtil.cpp +++ b/model/XmlUtil.cpp @@ -325,6 +325,149 @@ namespace glabels } + Units XmlUtil::getUnitsAttr( const QDomElement& node, + const QString& name, + const Units& default_value ) + { + init(); + + QString valueString = node.attribute( name, "" ); + if ( valueString != "" ) + { + return Units( valueString ); + } + + return default_value; + } + + + QPainterPath XmlUtil::getPathDataAttr( const QDomElement& node, + const QString& name, + const Units& units ) + { + init(); + + QPainterPath d; + + // + // Simple path data parser + // + QStringList tokens = node.attribute( name, "" ).split( " ", QString::SkipEmptyParts ); + + enum { CMD, MX, MY, MDX, MDY, LX, LY, LDX, LDY, HX, HDX, VY, VDY } state = CMD; + Distance x = 0; + Distance y = 0; + Distance dx = 0; + Distance dy = 0; + QPointF c; + + for ( unsigned int i = 0; i < tokens.size(); i++ ) + { + switch (state) + { + case CMD: + switch (tokens[i][0].unicode()) + { + case 'M': + state = MX; + break; + case 'm': + state = MDX; + break; + case 'L': + state = LX; + break; + case 'l': + state = LDX; + break; + case 'H': + state = HX; + break; + case 'h': + state = HDX; + break; + case 'V': + state = VY; + break; + case 'v': + state = VDY; + break; + case 'Z': + case 'z': + d.closeSubpath(); + state = CMD; + break; + } + break; + case MX: + x = Distance( tokens[i].toDouble(), units ); + state = MY; + break; + case MY: + y = Distance( tokens[i].toDouble(), units ); + d.moveTo( x.pt(), y.pt() ); + state = CMD; + break; + case MDX: + dx = Distance( tokens[i].toDouble(), units ); + state = MDY; + break; + case MDY: + dy = Distance( tokens[i].toDouble(), units ); + c = d.currentPosition(); + d.moveTo( c.x()+x.pt(), c.y()+y.pt() ); + state = CMD; + break; + case LX: + x = Distance( tokens[i].toDouble(), units ); + state = LY; + break; + case LY: + y = Distance( tokens[i].toDouble(), units ); + d.lineTo( x.pt(), y.pt() ); + state = CMD; + break; + case LDX: + dx = Distance( tokens[i].toDouble(), units ); + state = LDY; + break; + case LDY: + dy = Distance( tokens[i].toDouble(), units ); + c = d.currentPosition(); + d.lineTo( c.x()+dx.pt(), c.y()+dy.pt() ); + state = CMD; + break; + case HX: + x = Distance( tokens[i].toDouble(), units ); + c = d.currentPosition(); + d.lineTo( x.pt(), c.y() ); + state = CMD; + break; + case HDX: + dx = Distance( tokens[i].toDouble(), units ); + c = d.currentPosition(); + d.lineTo( c.x()+dx.pt(), c.y() ); + state = CMD; + break; + case VY: + y = Distance( tokens[i].toDouble(), units ); + c = d.currentPosition(); + d.lineTo( c.x(), y.pt() ); + state = CMD; + break; + case VDY: + dy = Distance( tokens[i].toDouble(), units ); + c = d.currentPosition(); + d.lineTo( c.x(), c.y()+dy.pt() ); + state = CMD; + break; + } + } + + return d; + } + + void XmlUtil::setStringAttr( QDomElement& node, const QString& name, const QString& value ) @@ -456,5 +599,50 @@ namespace glabels } + void XmlUtil::setUnitsAttr( QDomElement& node, + const QString& name, + const Units& value ) + { + node.setAttribute( name, value.toIdString() ); + } + + + void XmlUtil::setPathDataAttr( QDomElement& node, + const QString& name, + const QPainterPath& path, + const Units& units ) + { + QString pathString; + for ( int i = 0; i < path.elementCount(); i++ ) + { + auto element = path.elementAt( i ); + + // QPainterPath is natively in pts + Distance x = Distance::pt( element.x ); + Distance y = Distance::pt( element.y ); + + // Translate desired units for path data + double xValue = x.inUnits( units ); + double yValue = y.inUnits( units ); + + if ( element.isMoveTo() ) + { + pathString.append( QString( "M %1 %2" ).arg( xValue ).arg( yValue ) ); + } + else if ( element.isLineTo() ) + { + pathString.append( QString( "L %1 %2" ).arg( xValue ).arg( yValue ) ); + } + + if ( i < (path.elementCount() - 1) ) + { + pathString.append( " " ); + } + } + + node.setAttribute( name, pathString ); + } + + } } diff --git a/model/XmlUtil.h b/model/XmlUtil.h index 833f0b8..a576c57 100644 --- a/model/XmlUtil.h +++ b/model/XmlUtil.h @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -91,6 +92,14 @@ namespace glabels const QString& name, QTextOption::WrapMode default_value ); + static Units getUnitsAttr( const QDomElement& node, + const QString& name, + const Units& default_value ); + + static QPainterPath getPathDataAttr( const QDomElement& node, + const QString& name, + const Units& units ); + static void setStringAttr( QDomElement& node, const QString& name, @@ -128,6 +137,16 @@ namespace glabels const QString& name, QTextOption::WrapMode value ); + static void setUnitsAttr( QDomElement& node, + const QString& name, + const Units& value ); + + static void setPathDataAttr( QDomElement& node, + const QString& name, + const QPainterPath& value, + const Units& units ); + + private: Units mUnits; diff --git a/templates/brother-other-templates.xml b/templates/brother-other-templates.xml index cc554e3..437538a 100644 --- a/templates/brother-other-templates.xml +++ b/templates/brother-other-templates.xml @@ -7,49 +7,75 @@ ********************************************************************* Labels for the Brother QL-500/550/650 PC Label Printers - These templates are based on the exact media sizes and measurements - in version 1.1 of the 'Brother-QL-500-ptouch.ppd' file. - Currently only have templates for a few of the popular sizes. + REFERENCES: + + Brother Industries, Ltd. (October 3, 2011), "Brother QL Series + Command Reference (QL-500/550/560/570/580N/650TD/700/1050/1060N)", + http://download.brother.com/welcome/docp000678/cv_qlseries_eng_raster_600.pdf + ********************************************************************* ********************************************************************* --> -