Embed image data in glabels file.

This commit is contained in:
Jim Evins
2017-03-12 22:39:15 -04:00
parent fe1aa77799
commit fd79d7c6bd
11 changed files with 287 additions and 32 deletions
+1
View File
@@ -36,6 +36,7 @@ set (glabels_sources
ColorPaletteButtonItem.cpp ColorPaletteButtonItem.cpp
ColorSwatch.cpp ColorSwatch.cpp
Cursors.cpp Cursors.cpp
DataCache.cpp
Db.cpp Db.cpp
Distance.cpp Distance.cpp
EnumUtil.cpp EnumUtil.cpp
+82
View File
@@ -0,0 +1,82 @@
/* DataCache.cpp
*
* Copyright (C) 2017 Jim Evins <evins@snaught.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "DataCache.h"
#include "LabelModelImageObject.h"
namespace glabels
{
DataCache::DataCache()
{
// empty
}
DataCache::DataCache( const LabelModel* model )
{
foreach( LabelModelObject* object, model->objectList() )
{
if ( LabelModelImageObject* imageObject = dynamic_cast<LabelModelImageObject*>(object) )
{
TextNode filenameNode = imageObject->filenameNode();
if ( !filenameNode.isField() )
{
if ( const QImage* image = imageObject->image() )
{
addImage( filenameNode.data(), *imageObject->image() );
}
else
{
// TODO handle SVG files
}
}
}
}
}
bool DataCache::hasImage( const QString& name ) const
{
return mImageMap.contains( name );
}
QImage DataCache::getImage( const QString& name ) const
{
return mImageMap[ name ];
}
void DataCache::addImage( const QString& name, const QImage& image )
{
mImageMap[ name ] = image;
}
QList<QString> DataCache::imageNames() const
{
return mImageMap.keys();
}
}
+51
View File
@@ -0,0 +1,51 @@
/* DataCache.h
*
* Copyright (C) 2017 Jim Evins <evins@snaught.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef glabels_DataCache_h
#define glabels_DataCache_h
#include "LabelModel.h"
namespace glabels
{
class DataCache
{
public:
DataCache();
DataCache( const LabelModel* model );
bool hasImage( const QString& name ) const;
QImage getImage( const QString& name ) const;
void addImage( const QString& name, const QImage& image );
QList<QString> imageNames() const;
private:
QMap<QString,QImage> mImageMap;
};
}
#endif // glabels_DataCache_h
+37 -7
View File
@@ -120,7 +120,16 @@ namespace glabels
/// ///
/// Image Property Default Setter /// Image image Property Getter
///
const QImage* LabelModelImageObject::image() const
{
return mImage;
}
///
/// Image Property Setter
/// ///
void LabelModelImageObject::setImage( const QImage& value ) void LabelModelImageObject::setImage( const QImage& value )
{ {
@@ -144,6 +153,30 @@ namespace glabels
} }
///
/// Image Property Setter
///
void LabelModelImageObject::setImage( const QString& name, const QImage& value )
{
if ( !value.isNull() )
{
if ( mImage )
{
delete mImage;
}
if ( mSvg )
{
delete mSvg;
}
mImage = new QImage(value);
mFilenameNode = TextNode( false, name );
emit changed();
}
}
/// ///
/// naturalSize Property Getter (assumes 72 DPI, i.e. 1pixel == 1pt) /// naturalSize Property Getter (assumes 72 DPI, i.e. 1pixel == 1pt)
/// ///
@@ -246,18 +279,15 @@ namespace glabels
if ( mImage ) if ( mImage )
{ {
delete mImage; delete mImage;
mImage = 0;
} }
if ( mSvg ) if ( mSvg )
{ {
delete mSvg; delete mSvg;
}
if ( mFilenameNode.isField() )
{
mImage = 0;
mSvg = 0; mSvg = 0;
} }
else
if ( !mFilenameNode.isField() )
{ {
QString filename = mFilenameNode.data(); QString filename = mFilenameNode.data();
QFileInfo fileInfo( filename ); QFileInfo fileInfo( filename );
+2
View File
@@ -65,7 +65,9 @@ namespace glabels
// //
// Image Property: image // Image Property: image
// //
virtual const QImage* image() const;
virtual void setImage( const QImage& value ); virtual void setImage( const QImage& value );
virtual void setImage( const QString& name, const QImage& value );
// //
// Property: naturalSize // Property: naturalSize
+20
View File
@@ -600,6 +600,16 @@ namespace glabels
} }
///
/// Virtual Image Property Default Getter
/// (Overridden by concrete class)
///
const QImage* LabelModelObject::image() const
{
return 0;
}
/// ///
/// Virtual Image Property Default Setter /// Virtual Image Property Default Setter
/// (Overridden by concrete class) /// (Overridden by concrete class)
@@ -610,6 +620,16 @@ namespace glabels
} }
///
/// Virtual Image Property Default Setter
/// (Overridden by concrete class)
///
void LabelModelObject::setImage( const QString& name, const QImage& value )
{
// empty
}
/// ///
/// Virtual Line Width Property Default Getter /// Virtual Line Width Property Default Getter
/// (Overridden by concrete class) /// (Overridden by concrete class)
+2
View File
@@ -257,7 +257,9 @@ namespace glabels
// //
// Virtual Image Property: image // Virtual Image Property: image
// //
virtual const QImage* image() const;
virtual void setImage( const QImage& value ); virtual void setImage( const QImage& value );
virtual void setImage( const QString& name, const QImage& value );
/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////
+28 -3
View File
@@ -25,6 +25,7 @@
#include <QFile> #include <QFile>
#include <QTextBlock> #include <QTextBlock>
#include <QTextDocument> #include <QTextDocument>
#include <QBuffer>
#include <QtDebug> #include <QtDebug>
#include "EnumUtil.h" #include "EnumUtil.h"
@@ -36,6 +37,7 @@
#include "LabelModelLineObject.h" #include "LabelModelLineObject.h"
#include "LabelModelImageObject.h" #include "LabelModelImageObject.h"
#include "LabelModelTextObject.h" #include "LabelModelTextObject.h"
#include "DataCache.h"
#include "XmlTemplateCreator.h" #include "XmlTemplateCreator.h"
#include "XmlUtil.h" #include "XmlUtil.h"
@@ -444,14 +446,37 @@ namespace glabels
void void
XmlLabelCreator::createDataNode( QDomElement &parent, const LabelModel* label ) XmlLabelCreator::createDataNode( QDomElement &parent, const LabelModel* label )
{ {
// TODO QDomDocument doc = parent.ownerDocument();
QDomElement node = doc.createElement( "Data" );
parent.appendChild( node );
DataCache data( label );
foreach ( QString name, data.imageNames() )
{
createPngFileNode( node, name, data.getImage( name ) );
}
} }
void void
XmlLabelCreator::createPixdataNode( QDomElement &parent, const LabelModel* label, const QString& name ) XmlLabelCreator::createPngFileNode( QDomElement &parent, const QString& name, const QImage& image )
{ {
// TODO QDomDocument doc = parent.ownerDocument();
QDomElement node = doc.createElement( "File" );
parent.appendChild( node );
XmlUtil::setStringAttr( node, "name", name );
XmlUtil::setStringAttr( node, "mimetype", "image/png" );
XmlUtil::setStringAttr( node, "encoding", "base64" );
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG");
QByteArray ba64 = ba.toBase64();
node.appendChild( doc.createTextNode( QString( ba64 ) ) );
} }
+1 -1
View File
@@ -68,7 +68,7 @@ namespace glabels
static void createShadowAttrs( QDomElement &node, const LabelModelObject* object ); static void createShadowAttrs( QDomElement &node, const LabelModelObject* object );
static void createMergeNode( QDomElement &parent, const LabelModel* label ); static void createMergeNode( QDomElement &parent, const LabelModel* label );
static void createDataNode( QDomElement &parent, const LabelModel* label ); static void createDataNode( QDomElement &parent, const LabelModel* label );
static void createPixdataNode( QDomElement &parent, const LabelModel* label, const QString& name ); static void createPngFileNode( QDomElement &parent, const QString& name, const QImage& image );
static void createSvgFileNode( QDomElement &parent, const LabelModel* label, const QString& name ); static void createSvgFileNode( QDomElement &parent, const LabelModel* label, const QString& name );
}; };
+56 -15
View File
@@ -40,6 +40,7 @@
#include "LabelModelTextObject.h" #include "LabelModelTextObject.h"
#include "XmlTemplateParser.h" #include "XmlTemplateParser.h"
#include "XmlUtil.h" #include "XmlUtil.h"
#include "DataCache.h"
#include "Merge/Factory.h" #include "Merge/Factory.h"
@@ -151,7 +152,7 @@ namespace glabels
return list; return list;
} }
return parseObjects( root ); return parseObjects( root, DataCache() );
} }
@@ -217,11 +218,12 @@ namespace glabels
LabelModel* label = new LabelModel(); LabelModel* label = new LabelModel();
/* Pass 1, extract data nodes to pre-load cache. */ /* Pass 1, extract data nodes to pre-load cache. */
DataCache data;
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() ) for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
{ {
if ( child.toElement().tagName() == "Data" ) if ( child.toElement().tagName() == "Data" )
{ {
parseDataNode( child.toElement(), label ); parseDataNode( child.toElement(), data );
} }
} }
@@ -242,7 +244,7 @@ namespace glabels
} }
else if ( tagName == "Objects" ) else if ( tagName == "Objects" )
{ {
parseObjectsNode( child.toElement(), label ); parseObjectsNode( child.toElement(), data, label );
} }
else if ( tagName == "Merge" ) else if ( tagName == "Merge" )
{ {
@@ -264,7 +266,7 @@ namespace glabels
QList<LabelModelObject*> QList<LabelModelObject*>
XmlLabelParser::parseObjects( const QDomElement &node ) XmlLabelParser::parseObjects( const QDomElement &node, const DataCache& data )
{ {
QList<LabelModelObject*> list; QList<LabelModelObject*> list;
@@ -290,7 +292,7 @@ namespace glabels
} }
else if ( tagName == "Object-image" ) else if ( tagName == "Object-image" )
{ {
list.append( parseObjectImageNode( child.toElement() ) ); list.append( parseObjectImageNode( child.toElement(), data ) );
} }
#if 0 #if 0
else if ( tagName == "Object-barcode" ) else if ( tagName == "Object-barcode" )
@@ -309,9 +311,9 @@ namespace glabels
void void
XmlLabelParser::parseObjectsNode( const QDomElement &node, LabelModel* label ) XmlLabelParser::parseObjectsNode( const QDomElement &node, const DataCache& data, LabelModel* label )
{ {
QList<LabelModelObject*> list = parseObjects( node ); QList<LabelModelObject*> list = parseObjects( node, data );
foreach ( LabelModelObject* object, list ) foreach ( LabelModelObject* object, list )
{ {
@@ -441,7 +443,7 @@ namespace glabels
LabelModelImageObject* LabelModelImageObject*
XmlLabelParser::parseObjectImageNode( const QDomElement &node ) XmlLabelParser::parseObjectImageNode( const QDomElement &node, const DataCache& data )
{ {
LabelModelImageObject* object = new LabelModelImageObject(); LabelModelImageObject* object = new LabelModelImageObject();
@@ -460,7 +462,21 @@ namespace glabels
bool field_flag = !key.isEmpty(); bool field_flag = !key.isEmpty();
QString filename = XmlUtil::getStringAttr( node, "src", "" ); QString filename = XmlUtil::getStringAttr( node, "src", "" );
object->setFilenameNode( TextNode( field_flag, field_flag ? key : filename ) ); if ( field_flag )
{
object->setFilenameNode( TextNode( true, key ) );
}
else
{
if ( data.hasImage( filename ) )
{
object->setImage( filename, data.getImage( filename ) );
}
else
{
object->setFilenameNode( TextNode( false, filename ) );
}
}
} }
/* affine attrs */ /* affine attrs */
@@ -607,23 +623,48 @@ namespace glabels
void void
XmlLabelParser::parseDataNode( const QDomElement &node, LabelModel* label ) XmlLabelParser::parseDataNode( const QDomElement &node, DataCache& data )
{ {
// TODO for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
{
QString tagName = child.toElement().tagName();
if ( tagName == "File" )
{
parseFileNode( child.toElement(), data );
}
else if ( !child.isComment() )
{
qWarning() << "Unexpected" << node.tagName() << "child:" << tagName;
}
}
} }
void void
XmlLabelParser::parsePixdataNode( const QDomElement &node, LabelModel* label ) XmlLabelParser::parsePixdataNode( const QDomElement& node, DataCache& data )
{ {
// TODO // TODO, compatability with glabels-3
} }
void void
XmlLabelParser::parseFileNode( const QDomElement &node, LabelModel* label ) XmlLabelParser::parseFileNode( const QDomElement& node, DataCache& data )
{ {
// TODO QString name = XmlUtil::getStringAttr( node, "name", "" );
QString mimetype = XmlUtil::getStringAttr( node, "mimetype", "image/png" );
QString encoding = XmlUtil::getStringAttr( node, "encoding", "base64" );
if ( mimetype == "image/png" )
{
QByteArray ba64 = node.text().toUtf8();
QByteArray ba = QByteArray::fromBase64( ba64 );
QImage image;
image.loadFromData( ba, "PNG" );
data.addImage( name, image );
}
} }
} }
+7 -6
View File
@@ -38,6 +38,7 @@ namespace glabels
class LabelModelImageObject; class LabelModelImageObject;
class LabelModelBarcodeObject; class LabelModelBarcodeObject;
class LabelModelTextObject; class LabelModelTextObject;
class DataCache;
/// ///
@@ -55,21 +56,21 @@ namespace glabels
private: private:
static void gunzip( const QByteArray& gzippedData, QByteArray& data ); static void gunzip( const QByteArray& gzippedData, QByteArray& data );
static LabelModel* parseRootNode( const QDomElement &node ); static LabelModel* parseRootNode( const QDomElement &node );
static QList<LabelModelObject*> parseObjects( const QDomElement &node ); static QList<LabelModelObject*> parseObjects( const QDomElement &node, const DataCache& data );
static void parseObjectsNode( const QDomElement &node, LabelModel* label ); static void parseObjectsNode( const QDomElement &node, const DataCache& data, LabelModel* label );
static LabelModelBoxObject* parseObjectBoxNode( const QDomElement &node ); static LabelModelBoxObject* parseObjectBoxNode( const QDomElement &node );
static LabelModelEllipseObject* parseObjectEllipseNode( const QDomElement &node ); static LabelModelEllipseObject* parseObjectEllipseNode( const QDomElement &node );
static LabelModelLineObject* parseObjectLineNode( const QDomElement &node ); static LabelModelLineObject* parseObjectLineNode( const QDomElement &node );
static LabelModelImageObject* parseObjectImageNode( const QDomElement &node ); static LabelModelImageObject* parseObjectImageNode( const QDomElement &node, const DataCache& data );
static LabelModelBarcodeObject* parseObjectBarcodeNode( const QDomElement &node ); static LabelModelBarcodeObject* parseObjectBarcodeNode( const QDomElement &node );
static LabelModelTextObject* parseObjectTextNode( const QDomElement &node ); static LabelModelTextObject* parseObjectTextNode( const QDomElement &node );
static QString parsePNode( const QDomElement &node ); static QString parsePNode( const QDomElement &node );
static void parseAffineAttrs( const QDomElement &node, LabelModelObject* object ); static void parseAffineAttrs( const QDomElement &node, LabelModelObject* object );
static void parseShadowAttrs( const QDomElement &node, LabelModelObject* object ); static void parseShadowAttrs( const QDomElement &node, LabelModelObject* object );
static void parseMergeNode( const QDomElement &node, LabelModel* label ); static void parseMergeNode( const QDomElement &node, LabelModel* label );
static void parseDataNode( const QDomElement &node, LabelModel* label ); static void parseDataNode( const QDomElement &node, DataCache& data );
static void parsePixdataNode( const QDomElement &node, LabelModel* label ); static void parsePixdataNode( const QDomElement &node, DataCache& data );
static void parseFileNode( const QDomElement &node, LabelModel* label ); static void parseFileNode( const QDomElement &node, DataCache& data );
}; };