diff --git a/libglabels/CMakeLists.txt b/libglabels/CMakeLists.txt index 387f847..14caee6 100644 --- a/libglabels/CMakeLists.txt +++ b/libglabels/CMakeLists.txt @@ -25,6 +25,7 @@ set (libglabels_sources XmlVendorParser.cpp XmlTemplateParser.cpp XmlUtil.cpp + MiniPreviewPixmap.cpp ) set (libglabels_qobject_headers diff --git a/libglabels/Db.cpp b/libglabels/Db.cpp index a00927f..d15fd85 100644 --- a/libglabels/Db.cpp +++ b/libglabels/Db.cpp @@ -335,6 +335,7 @@ namespace libglabels { if ( !isTemplateKnown( tmplate->brand(), tmplate->part() ) ) { + tmplate->initPreview(); mTemplates << tmplate; } else diff --git a/libglabels/Frame.cpp b/libglabels/Frame.cpp index 174ccbd..dd16f0f 100644 --- a/libglabels/Frame.cpp +++ b/libglabels/Frame.cpp @@ -41,9 +41,9 @@ namespace libglabels } - std::vector Frame::getOrigins() const + QVector Frame::getOrigins() const { - std::vector origins( nLabels() ); + QVector origins( nLabels() ); foreach ( Layout *layout, mLayouts ) { @@ -51,12 +51,14 @@ namespace libglabels { for ( int ix = 0; ix < layout->nx(); ix++ ) { - origins.push_back( Point( ix*layout->dx() + layout->x0(), iy*layout->dy() + layout->y0() ) ); + origins << Point( ix*layout->dx() + layout->x0(), iy*layout->dy() + layout->y0() ); } } } - std::sort( origins.begin(), origins.end(), Point::compare ); + qStableSort( origins.begin(), origins.end() ); + + return origins; } diff --git a/libglabels/Frame.h b/libglabels/Frame.h index ff80e72..9ec87fd 100644 --- a/libglabels/Frame.h +++ b/libglabels/Frame.h @@ -24,8 +24,8 @@ #include #include #include - -#include +#include +#include #include "Units.h" #include "Point.h" @@ -56,7 +56,7 @@ namespace libglabels inline const QList &layouts() { return mLayouts; } inline const QList &markups() { return mMarkups; } - std::vector getOrigins() const; + QVector getOrigins() const; void addLayout( Layout *layout ); void addMarkup( Markup *markup ); @@ -67,6 +67,8 @@ namespace libglabels virtual const QString &sizeDescription( Units *units ) = 0; virtual bool isSimilarTo( Frame *other ) const = 0; + virtual const QPainterPath &path() const = 0; + private: QString mId; @@ -75,7 +77,6 @@ namespace libglabels QList mLayouts; QList mMarkups; - }; } diff --git a/libglabels/FrameCd.cpp b/libglabels/FrameCd.cpp index 14eea44..2760207 100644 --- a/libglabels/FrameCd.cpp +++ b/libglabels/FrameCd.cpp @@ -67,5 +67,25 @@ namespace libglabels return false; } + + void FrameCd::initPath() + { + double xc = w()/2; + double yc = h()/2; + + // Outer path (may be clipped in the case business card type CD) + double theta1 = acos( w() / (2*mR1) ) * 180/M_PI; + double theta2 = asin( h() / (2*mR1) ) * 180/M_PI; + + mPath.arcTo( 0, 0, 2*mR1, 2*mR1, theta1, theta2 ); + mPath.arcTo( 0, 0, 2*mR1, 2*mR1, 180-theta2, 180-theta1 ); + mPath.arcTo( 0, 0, 2*mR1, 2*mR1, 180+theta1, 180+theta2 ); + mPath.arcTo( 0, 0, 2*mR1, 2*mR1, 360-theta2, 360-theta1 ); + mPath.closeSubpath(); + + // Inner path (hole) + mPath.addEllipse( xc-mR2, yc-mR2, 2*mR2, 2*mR2 ); + } + } diff --git a/libglabels/FrameCd.h b/libglabels/FrameCd.h index 5e80006..6eb2f94 100644 --- a/libglabels/FrameCd.h +++ b/libglabels/FrameCd.h @@ -38,10 +38,12 @@ namespace libglabels QString id = "0" ) : mR1(r1), mR2(r2), mW(w), mH(h), mWaste(waste), Frame(id) { + initPath(); } FrameCd( const FrameCd &other ) - : mR1(other.mR1), mR2(other.mR2), mW(other.mW), mH(other.mH), mWaste(other.mWaste), Frame(other) + : mR1(other.mR1), mR2(other.mR2), mW(other.mW), mH(other.mH), mWaste(other.mWaste), + mPath(other.mPath), Frame(other) { } @@ -57,8 +59,12 @@ namespace libglabels const QString &sizeDescription( Units *units ); bool isSimilarTo( Frame *other ) const; + const QPainterPath &path() const { return mPath; } + private: + void initPath(); + double mR1; double mR2; double mW; @@ -67,6 +73,8 @@ namespace libglabels QString mSizeDescription; + QPainterPath mPath; + }; } diff --git a/libglabels/FrameEllipse.h b/libglabels/FrameEllipse.h index b6d4448..63cedc2 100644 --- a/libglabels/FrameEllipse.h +++ b/libglabels/FrameEllipse.h @@ -36,10 +36,11 @@ namespace libglabels QString id = "0" ) : mW(w), mH(h), mWaste(waste), Frame(id) { + mPath.addEllipse( 0, 0, mW, mH ); } FrameEllipse( const FrameEllipse &other ) - : mW(other.mW), mH(other.mH), mWaste(other.mWaste), Frame(other) + : mW(other.mW), mH(other.mH), mWaste(other.mWaste), mPath(other.mPath), Frame(other) { } @@ -53,6 +54,8 @@ namespace libglabels const QString &sizeDescription( Units *units ); bool isSimilarTo( Frame *other ) const; + const QPainterPath &path() const { return mPath; } + private: double mW; @@ -61,6 +64,8 @@ namespace libglabels QString mSizeDescription; + QPainterPath mPath; + }; } diff --git a/libglabels/FrameRect.cpp b/libglabels/FrameRect.cpp index ea41979..2624e16 100644 --- a/libglabels/FrameRect.cpp +++ b/libglabels/FrameRect.cpp @@ -66,6 +66,5 @@ namespace libglabels return false; } - } diff --git a/libglabels/FrameRect.h b/libglabels/FrameRect.h index 1f11b5d..8fbca4b 100644 --- a/libglabels/FrameRect.h +++ b/libglabels/FrameRect.h @@ -38,11 +38,12 @@ namespace libglabels QString id = "0" ) : mW(w), mH(h), mR(r), mXWaste(xWaste), mYWaste(yWaste), Frame(id) { + mPath.addRoundedRect( 0, 0, mW, mH, mR, mR ); } FrameRect( const FrameRect &other ) : mW(other.mW), mH(other.mH), mR(other.mR), mXWaste(other.mXWaste), mYWaste(other.mYWaste), - Frame(other) + mPath(other.mPath), Frame(other) { } @@ -58,6 +59,8 @@ namespace libglabels const QString &sizeDescription( Units *units ); bool isSimilarTo( Frame *other ) const; + const QPainterPath &path() const { return mPath; } + private: double mW; @@ -68,6 +71,8 @@ namespace libglabels QString mSizeDescription; + QPainterPath mPath; + }; } diff --git a/libglabels/FrameRound.h b/libglabels/FrameRound.h index 1371917..db1b90e 100644 --- a/libglabels/FrameRound.h +++ b/libglabels/FrameRound.h @@ -35,10 +35,11 @@ namespace libglabels QString id = "0" ) : mR(r), mWaste(waste), Frame(id) { + mPath.addEllipse( 0, 0, 2*mR, 2*mR ); } FrameRound( const FrameRound &other ) - : mR(other.mR), mWaste(other.mWaste), Frame(other) + : mR(other.mR), mWaste(other.mWaste), mPath(other.mPath), Frame(other) { } @@ -53,12 +54,17 @@ namespace libglabels const QString &sizeDescription( Units *units ); bool isSimilarTo( Frame *other ) const; + const QPainterPath &path() const { return mPath; } + private: double mR; double mWaste; QString mSizeDescription; + + QPainterPath mPath; + }; } diff --git a/libglabels/MiniPreviewPixmap.cpp b/libglabels/MiniPreviewPixmap.cpp new file mode 100644 index 0000000..fe0f5d3 --- /dev/null +++ b/libglabels/MiniPreviewPixmap.cpp @@ -0,0 +1,120 @@ +/* MiniPreviewPixmap.cpp + * + * Copyright (C) 2013 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 "MiniPreviewPixmap.h" + +#include "Template.h" + + +namespace +{ + const QColor paperColor( 217, 217, 217 ); + const QColor paperOutlineColor( 0, 0, 0 ); + const double paperOutlineWidthPixels = 1.0; + + const QColor labelColor( 242, 242, 242 ); + const QColor labelOutlineColor( 64, 64, 64 ); + const double labelOutlineWidthPixels = 1.0; +} + + +namespace libglabels +{ + + void MiniPreviewPixmap::draw( const Template *tmplate, int width, int height ) + { + QPainter painter( this ); + + painter.setBackgroundMode( Qt::TransparentMode ); + painter.setRenderHint( QPainter::Antialiasing ); + + double w = width - 1; + double h = height - 1; + double scale; + if ( (w/tmplate->pageWidth()) > (h/tmplate->pageHeight()) ) + { + scale = h / tmplate->pageHeight(); + } + else + { + scale = w / tmplate->pageWidth(); + } + painter.scale( scale, scale ); + + double xOffset = ( width/scale - tmplate->pageWidth() ) / 2; + double yOffset = ( height/scale - tmplate->pageHeight() ) / 2; + painter.translate( xOffset, yOffset ); + + drawPaper( painter, tmplate, scale ); + drawLabelOutlines( painter, tmplate, scale ); + } + + + void MiniPreviewPixmap::drawPaper( QPainter &painter, const Template *tmplate, double scale ) + { + QBrush brush( paperColor ); + QPen pen( paperOutlineColor ); + pen.setWidth( paperOutlineWidthPixels/scale ); + + painter.save(); + + painter.setBrush( brush ); + painter.setPen( pen ); + painter.drawRect( 0, 0, tmplate->pageWidth(), tmplate->pageHeight() ); + + painter.restore(); + } + + + void MiniPreviewPixmap::drawLabelOutlines( QPainter &painter, const Template *tmplate, double scale ) + { + QBrush brush( labelColor ); + QPen pen( labelOutlineColor ); + pen.setWidth( labelOutlineWidthPixels/scale ); + + painter.save(); + + painter.setBrush( brush ); + painter.setPen( pen ); + + Frame *frame = tmplate->frames().first(); + QVector origins = frame->getOrigins(); + + foreach ( Point point, origins ) + { + drawLabelOutline( painter, frame, point.x(), point.y() ); + } + + painter.restore(); + } + + + void MiniPreviewPixmap::drawLabelOutline( QPainter &painter, const Frame *frame, double x0, double y0 ) + { + painter.save(); + + painter.translate( x0, y0 ); + painter.drawPath( frame->path() ); + + painter.restore(); + } + +} + diff --git a/libglabels/MiniPreviewPixmap.h b/libglabels/MiniPreviewPixmap.h new file mode 100644 index 0000000..c954bfc --- /dev/null +++ b/libglabels/MiniPreviewPixmap.h @@ -0,0 +1,57 @@ +/* MiniPreviewPixmap.h + * + * Copyright (C) 2013 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 libglabels_MiniPreviewPixmap_h +#define libglabels_MiniPreviewPixmap_h + + +#include +#include + + +namespace libglabels +{ + class Template; // Forward reference + class Frame; // Forward reference + + + class MiniPreviewPixmap : public QPixmap + { + public: + MiniPreviewPixmap() + { + } + + MiniPreviewPixmap( const Template *tmplate, int width, int height ) + : QPixmap( width, height ) + { + draw( tmplate, width, height ); + } + + private: + void draw( const Template *tmplate, int width, int height ); + void drawPaper( QPainter &painter, const Template *tmplate, double scale ); + void drawLabelOutlines( QPainter &painter, const Template *tmplate, double scale ); + void drawLabelOutline( QPainter &painter, const Frame *frame, double x0, double y0 ); + }; + +} + +#endif // libglabels_MiniPreviewPixmap_h diff --git a/libglabels/Point.cpp b/libglabels/Point.cpp index 3c368f1..b8ebefe 100644 --- a/libglabels/Point.cpp +++ b/libglabels/Point.cpp @@ -24,31 +24,17 @@ namespace libglabels { - int Point::compare( const Point &a, const Point &b ) + bool Point::operator<( const Point &other ) const { - if ( a.mY < b.mY ) + if ( mY < other.mY ) { - return -1; + return true; } - else if ( a.mY > b.mY ) + else if ( mY == other.mY ) { - return 1; - } - else - { - if ( a.mX < b.mX ) - { - return -1; - } - else if ( a.mX > b.mX ) - { - return 1; - } - else - { - return 0; /* hopefully 2 label frames won't have the same origin. */ - } + return mX < other.mX; } + return false; } } diff --git a/libglabels/Point.h b/libglabels/Point.h index 6c2e08d..4a18aea 100644 --- a/libglabels/Point.h +++ b/libglabels/Point.h @@ -39,7 +39,7 @@ namespace libglabels inline double x() const { return mX; } inline double y() const { return mY; } - static int compare( const Point &a, const Point &b ); + bool operator<( const Point &other ) const; private: diff --git a/libglabels/Template.cpp b/libglabels/Template.cpp index 3edb484..bfcbcb2 100644 --- a/libglabels/Template.cpp +++ b/libglabels/Template.cpp @@ -23,6 +23,9 @@ #include #include "Db.h" +#include "privateConstants.h" + +using namespace libglabels::Constants; namespace libglabels @@ -98,6 +101,12 @@ namespace libglabels } + void Template::initPreview() + { + mPreview = MiniPreviewPixmap( this, PREVIEW_PIXMAP_SIZE, PREVIEW_PIXMAP_SIZE ); + } + + bool Template::operator==( const Template &other ) const { return (mBrand == other.mBrand) && (mPart == other.mPart); diff --git a/libglabels/Template.h b/libglabels/Template.h index cc2d18e..b000afd 100644 --- a/libglabels/Template.h +++ b/libglabels/Template.h @@ -31,6 +31,7 @@ #include "Units.h" #include "Point.h" #include "Frame.h" +#include "MiniPreviewPixmap.h" namespace libglabels @@ -91,6 +92,11 @@ namespace libglabels void addCategory( const QString &categoryId ); void addFrame( Frame *frame ); + void initPreview(); + inline const MiniPreviewPixmap &preview() const { return mPreview; } + + inline const QList &frames() const { return mFrames; } + bool operator==( const Template &other ) const; bool hasCategory( const QString &categoryId ) const; @@ -112,6 +118,8 @@ namespace libglabels QStringList mCategoryIds; QList mFrames; + + MiniPreviewPixmap mPreview; }; } diff --git a/libglabels/privateConstants.h b/libglabels/privateConstants.h index c94247f..acf3763 100644 --- a/libglabels/privateConstants.h +++ b/libglabels/privateConstants.h @@ -33,6 +33,7 @@ namespace libglabels const double EPSILON = 0.5; /* Allowed error when comparing dimensions. (0.5pts ~= .007in ~= .2mm) */ + const int PREVIEW_PIXMAP_SIZE = 72; } }