Restructuring directory layout. Move towards "Modern CMake" usage.
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
project (Model LANGUAGES CXX)
|
||||
|
||||
#=======================================
|
||||
# Sources
|
||||
#=======================================
|
||||
# Auto-generated files
|
||||
configure_file (Version.h.in ${CMAKE_CURRENT_BINARY_DIR}/Version.h @ONLY)
|
||||
configure_file (Config.h.in ${CMAKE_CURRENT_BINARY_DIR}/Config.h @ONLY)
|
||||
|
||||
set (Model_sources
|
||||
Category.cpp
|
||||
ColorNode.cpp
|
||||
DataCache.cpp
|
||||
Db.cpp
|
||||
Distance.cpp
|
||||
FileUtil.cpp
|
||||
Frame.cpp
|
||||
FrameCd.cpp
|
||||
FrameEllipse.cpp
|
||||
FrameRect.cpp
|
||||
FrameRound.cpp
|
||||
Handles.cpp
|
||||
Layout.cpp
|
||||
Markup.cpp
|
||||
Model.cpp
|
||||
ModelObject.cpp
|
||||
ModelBarcodeObject.cpp
|
||||
ModelBoxObject.cpp
|
||||
ModelEllipseObject.cpp
|
||||
ModelImageObject.cpp
|
||||
ModelLineObject.cpp
|
||||
ModelShapeObject.cpp
|
||||
ModelTextObject.cpp
|
||||
Outline.cpp
|
||||
PageRenderer.cpp
|
||||
Paper.cpp
|
||||
Point.cpp
|
||||
RawText.cpp
|
||||
Region.cpp
|
||||
Settings.cpp
|
||||
Size.cpp
|
||||
StrUtil.cpp
|
||||
SubstitutionField.cpp
|
||||
Template.cpp
|
||||
TextNode.cpp
|
||||
Units.cpp
|
||||
Vendor.cpp
|
||||
XmlCategoryParser.cpp
|
||||
XmlLabelCreator.cpp
|
||||
XmlLabelParser.cpp
|
||||
XmlPaperParser.cpp
|
||||
XmlTemplateCreator.cpp
|
||||
XmlTemplateParser.cpp
|
||||
XmlUtil.cpp
|
||||
XmlVendorParser.cpp
|
||||
)
|
||||
|
||||
set (Model_qobject_headers
|
||||
Model.h
|
||||
ModelObject.h
|
||||
ModelBarcodeObject.h
|
||||
ModelBoxObject.h
|
||||
ModelEllipseObject.h
|
||||
ModelImageObject.h
|
||||
ModelLineObject.h
|
||||
ModelShapeObject.h
|
||||
ModelTextObject.h
|
||||
PageRenderer.h
|
||||
Settings.h
|
||||
)
|
||||
|
||||
qt5_wrap_cpp (Model_moc_sources ${Model_qobject_headers})
|
||||
|
||||
#=====================================
|
||||
# Target
|
||||
#=====================================
|
||||
add_library (Model STATIC
|
||||
${Model_sources}
|
||||
${Model_moc_sources}
|
||||
)
|
||||
|
||||
target_compile_features (Model
|
||||
PUBLIC cxx_std_11
|
||||
)
|
||||
|
||||
target_include_directories (Model
|
||||
PUBLIC .. ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
PRIVATE ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries (Model
|
||||
Barcode
|
||||
Merge
|
||||
Qt5::Widgets
|
||||
Qt5::PrintSupport
|
||||
Qt5::Xml
|
||||
Qt5::Svg
|
||||
ZLIB::ZLIB
|
||||
)
|
||||
|
||||
#=======================================
|
||||
# Subdirectories
|
||||
#=======================================
|
||||
add_subdirectory (unit_tests)
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/* Category.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Category.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Category::Category( const QString &id, const QString &name )
|
||||
: mId(id), mName(name)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
QString Category::id() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
|
||||
QString Category::name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Category.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Category_h
|
||||
#define model_Category_h
|
||||
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Category
|
||||
{
|
||||
|
||||
public:
|
||||
Category( const QString& id, const QString& name );
|
||||
|
||||
QString id() const;
|
||||
QString name() const;
|
||||
|
||||
|
||||
private:
|
||||
QString mId;
|
||||
QString mName;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Category_h
|
||||
@@ -0,0 +1,202 @@
|
||||
/* ColorNode.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 "ColorNode.h"
|
||||
|
||||
#include "merge/Record.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Default Constructor
|
||||
///
|
||||
ColorNode::ColorNode()
|
||||
: mIsField(false), mColor(QColor::fromRgba(0x00000000)), mKey("")
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor From Data
|
||||
///
|
||||
ColorNode::ColorNode( bool isField, const QColor& color, const QString& key )
|
||||
: mIsField(isField), mColor(color), mKey(key)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor From Data
|
||||
///
|
||||
ColorNode::ColorNode( bool isField, uint32_t rgba, const QString& key )
|
||||
: mIsField(isField), mKey(key)
|
||||
{
|
||||
mColor = QColor( (rgba >> 24) & 0xFF,
|
||||
(rgba >> 16) & 0xFF,
|
||||
(rgba >> 8) & 0xFF,
|
||||
(rgba ) & 0xFF );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor From Color
|
||||
///
|
||||
ColorNode::ColorNode( const QColor& color )
|
||||
: mIsField(false), mColor(color), mKey("")
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor From Key
|
||||
///
|
||||
ColorNode::ColorNode( const QString& key )
|
||||
: mIsField(true), mColor(QColor::fromRgba(0x00000000)), mKey(key)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// == Operator
|
||||
///
|
||||
bool ColorNode::operator==( const ColorNode& cn )
|
||||
{
|
||||
return (mIsField == cn.mIsField) &&
|
||||
(mColor == cn.mColor) &&
|
||||
(mKey == cn.mKey);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// != Operator
|
||||
///
|
||||
bool ColorNode::operator!=( const ColorNode& cn )
|
||||
{
|
||||
return (mIsField != cn.mIsField) ||
|
||||
(mColor != cn.mColor) ||
|
||||
(mKey != cn.mKey);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Field Flag Property Getter
|
||||
///
|
||||
bool ColorNode::isField() const
|
||||
{
|
||||
return mIsField;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Field Flag Property Setter
|
||||
///
|
||||
void ColorNode::setField( bool isField )
|
||||
{
|
||||
mIsField = isField;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Color Property Getter
|
||||
///
|
||||
const QColor& ColorNode::color() const
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Color Property Setter
|
||||
///
|
||||
void ColorNode::setColor( const QColor& color )
|
||||
{
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Key Property Getter
|
||||
///
|
||||
const QString& ColorNode::key() const
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Key Property Setter
|
||||
///
|
||||
void ColorNode::setKey( const QString& key )
|
||||
{
|
||||
mKey = key;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get color encoded as an RGBA 32-bit number
|
||||
///
|
||||
uint32_t ColorNode::rgba() const
|
||||
{
|
||||
uint32_t c =
|
||||
mColor.red() << 24 |
|
||||
mColor.green() << 16 |
|
||||
mColor.blue() << 8 |
|
||||
mColor.alpha();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get color, expand if necessary
|
||||
///
|
||||
QColor ColorNode::color( merge::Record* record ) const
|
||||
{
|
||||
if ( mIsField )
|
||||
{
|
||||
if ( record == nullptr )
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( record->contains( mKey ) )
|
||||
{
|
||||
return QColor( (*record)[ mKey ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,112 @@
|
||||
/* ColorNode.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 model_ColorNode_h
|
||||
#define model_ColorNode_h
|
||||
|
||||
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Color Node Type
|
||||
///
|
||||
struct ColorNode
|
||||
{
|
||||
|
||||
/////////////////////////////////
|
||||
// Life Cycle
|
||||
/////////////////////////////////
|
||||
public:
|
||||
ColorNode();
|
||||
|
||||
ColorNode( bool isField, const QColor& color, const QString& key );
|
||||
|
||||
ColorNode( bool isField, uint32_t rgba, const QString& key );
|
||||
|
||||
ColorNode( const QColor& color );
|
||||
|
||||
ColorNode( const QString& key );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Operators
|
||||
/////////////////////////////////
|
||||
public:
|
||||
bool operator==( const ColorNode& cn );
|
||||
|
||||
bool operator!=( const ColorNode& cn );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Properties
|
||||
/////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Field Flag Property
|
||||
//
|
||||
bool isField() const;
|
||||
void setField( bool isField );
|
||||
|
||||
|
||||
//
|
||||
// Color Property
|
||||
//
|
||||
const QColor& color() const;
|
||||
void setColor( const QColor& color );
|
||||
|
||||
|
||||
//
|
||||
// Key Property
|
||||
//
|
||||
const QString& key() const;
|
||||
void setKey( const QString& key );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Misc. Methods
|
||||
/////////////////////////////////
|
||||
public:
|
||||
uint32_t rgba() const;
|
||||
QColor color( merge::Record* record ) const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
bool mIsField;
|
||||
QColor mColor;
|
||||
QString mKey;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ColorNode_h
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Config.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Config_h
|
||||
#define model_Config_h
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
namespace Config
|
||||
{
|
||||
const QString PROJECT_SOURCE_DIR = "@glabels-qt_SOURCE_DIR@";
|
||||
const QString PROJECT_BUILD_DIR = "@glabels-qt_BINARY_DIR@";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Config_h
|
||||
@@ -0,0 +1,37 @@
|
||||
/* Constants.h
|
||||
*
|
||||
* Copyright (C) 2016 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 model_Constants_h
|
||||
#define model_Constants_h
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
const double PTS_PER_PT = 1.0;
|
||||
const double PTS_PER_INCH = 72.0;
|
||||
const double PTS_PER_MM = 2.83464566929;
|
||||
const double PTS_PER_CM = (10.0*PTS_PER_MM);
|
||||
const double PTS_PER_PICA = 12.0;
|
||||
|
||||
const Distance EPSILON( 0.5, Units::PT );
|
||||
}
|
||||
|
||||
#endif // model_Constants_h
|
||||
@@ -0,0 +1,110 @@
|
||||
/* 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 "ModelImageObject.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
DataCache::DataCache()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
DataCache::DataCache( const QList<ModelObject*>& objects )
|
||||
{
|
||||
foreach( ModelObject* object, objects )
|
||||
{
|
||||
if ( ModelImageObject* imageObject = dynamic_cast<ModelImageObject*>(object) )
|
||||
{
|
||||
TextNode filenameNode = imageObject->filenameNode();
|
||||
if ( !filenameNode.isField() )
|
||||
{
|
||||
if ( const QImage* image = imageObject->image() )
|
||||
{
|
||||
addImage( filenameNode.data(), *image );
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray svg = imageObject->svg();
|
||||
if ( !svg.isEmpty() )
|
||||
{
|
||||
addSvg( filenameNode.data(), svg );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
bool DataCache::hasSvg( const QString& name ) const
|
||||
{
|
||||
return mSvgMap.contains( name );
|
||||
}
|
||||
|
||||
|
||||
QByteArray DataCache::getSvg( const QString& name ) const
|
||||
{
|
||||
return mSvgMap[ name ];
|
||||
}
|
||||
|
||||
|
||||
void DataCache::addSvg( const QString& name, const QByteArray& svg )
|
||||
{
|
||||
mSvgMap[ name ] = svg;
|
||||
}
|
||||
|
||||
|
||||
QList<QString> DataCache::svgNames() const
|
||||
{
|
||||
return mSvgMap.keys();
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,58 @@
|
||||
/* 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 model_DataCache_h
|
||||
#define model_DataCache_h
|
||||
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class DataCache
|
||||
{
|
||||
public:
|
||||
DataCache();
|
||||
|
||||
DataCache( const QList<ModelObject*>& objects );
|
||||
|
||||
bool hasImage( const QString& name ) const;
|
||||
QImage getImage( const QString& name ) const;
|
||||
void addImage( const QString& name, const QImage& image );
|
||||
QList<QString> imageNames() const;
|
||||
|
||||
bool hasSvg( const QString& name ) const;
|
||||
QByteArray getSvg( const QString& name ) const;
|
||||
void addSvg( const QString& name, const QByteArray& svg );
|
||||
QList<QString> svgNames() const;
|
||||
|
||||
|
||||
private:
|
||||
QMap<QString,QImage> mImageMap;
|
||||
QMap<QString,QByteArray> mSvgMap;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_DataCache_h
|
||||
+689
@@ -0,0 +1,689 @@
|
||||
/* Db.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Db.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "StrUtil.h"
|
||||
#include "FileUtil.h"
|
||||
#include "XmlCategoryParser.h"
|
||||
#include "XmlPaperParser.h"
|
||||
#include "XmlTemplateParser.h"
|
||||
#include "XmlVendorParser.h"
|
||||
|
||||
#include <QtDebug>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const QString empty = "";
|
||||
|
||||
bool partNameLessThan( const Template *a, const Template *b )
|
||||
{
|
||||
return StrUtil::comparePartNames( a->name(), b->name() ) < 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Static data
|
||||
//
|
||||
QList<Paper*> Db::mPapers;
|
||||
QStringList Db::mPaperIds;
|
||||
QStringList Db::mPaperNames;
|
||||
QList<Category*> Db::mCategories;
|
||||
QStringList Db::mCategoryIds;
|
||||
QStringList Db::mCategoryNames;
|
||||
QList<Vendor*> Db::mVendors;
|
||||
QStringList Db::mVendorNames;
|
||||
QList<Template*> Db::mTemplates;
|
||||
QString Db::mPaperNameOther;
|
||||
|
||||
|
||||
Db::Db()
|
||||
{
|
||||
mPaperNameOther = tr("Other");
|
||||
|
||||
readPapers();
|
||||
readCategories();
|
||||
readVendors();
|
||||
readTemplates();
|
||||
}
|
||||
|
||||
|
||||
void Db::init()
|
||||
{
|
||||
instance();
|
||||
}
|
||||
|
||||
|
||||
Db* Db::instance()
|
||||
{
|
||||
static Db* db = new Db();
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
const QList<Paper*>& Db::papers()
|
||||
{
|
||||
return mPapers;
|
||||
}
|
||||
|
||||
|
||||
const QStringList& Db::paperIds()
|
||||
{
|
||||
return mPaperIds;
|
||||
}
|
||||
|
||||
|
||||
const QStringList& Db::paperNames()
|
||||
{
|
||||
return mPaperNames;
|
||||
}
|
||||
|
||||
|
||||
const QList<Category*>& Db::categories()
|
||||
{
|
||||
return mCategories;
|
||||
}
|
||||
|
||||
|
||||
const QStringList& Db::categoryIds()
|
||||
{
|
||||
return mCategoryIds;
|
||||
}
|
||||
|
||||
|
||||
const QStringList& Db::categoryNames()
|
||||
{
|
||||
return mCategoryNames;
|
||||
}
|
||||
|
||||
|
||||
const QList<Vendor*>& Db::vendors()
|
||||
{
|
||||
return mVendors;
|
||||
}
|
||||
|
||||
|
||||
const QStringList& Db::vendorNames()
|
||||
{
|
||||
return mVendorNames;
|
||||
}
|
||||
|
||||
|
||||
const QList<Template*>& Db::templates()
|
||||
{
|
||||
return mTemplates;
|
||||
}
|
||||
|
||||
|
||||
void Db::registerPaper( Paper *paper )
|
||||
{
|
||||
if ( !isPaperIdKnown( paper->id() ) )
|
||||
{
|
||||
mPapers << paper;
|
||||
mPaperIds << paper->id();
|
||||
mPaperNames << paper->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Duplicate paper ID: " << paper->id();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Paper *Db::lookupPaperFromName( const QString& name )
|
||||
{
|
||||
if ( name.isNull() || name.isEmpty() )
|
||||
{
|
||||
qWarning() << "NULL paper name.";
|
||||
return mPapers.first();
|
||||
}
|
||||
|
||||
foreach ( Paper *paper, mPapers )
|
||||
{
|
||||
if ( paper->name() == name )
|
||||
{
|
||||
return paper;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown paper name: " << name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const Paper *Db::lookupPaperFromId( const QString& id )
|
||||
{
|
||||
if ( id.isNull() || id.isEmpty() )
|
||||
{
|
||||
qWarning() << "NULL paper ID.";
|
||||
return mPapers.first();
|
||||
}
|
||||
|
||||
foreach ( Paper *paper, mPapers )
|
||||
{
|
||||
if ( paper->id() == id )
|
||||
{
|
||||
return paper;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown paper ID: " << id;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
QString Db::lookupPaperIdFromName( const QString& name )
|
||||
{
|
||||
if ( !name.isNull() && !name.isEmpty() )
|
||||
{
|
||||
const Paper *paper = lookupPaperFromName( name );
|
||||
if ( paper != nullptr )
|
||||
{
|
||||
return paper->id();
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown paper name: " << name;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
QString Db::lookupPaperNameFromId( const QString& id )
|
||||
{
|
||||
if ( !id.isNull() && !id.isEmpty() )
|
||||
{
|
||||
if ( isPaperIdOther( id ) )
|
||||
{
|
||||
return mPaperNameOther;
|
||||
}
|
||||
|
||||
const Paper *paper = lookupPaperFromId( id );
|
||||
if ( paper != nullptr )
|
||||
{
|
||||
return paper->name();
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown paper id: " << id;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
bool Db::isPaperIdKnown( const QString& id )
|
||||
{
|
||||
foreach ( Paper *paper, mPapers )
|
||||
{
|
||||
if ( paper->id() == id )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Db::isPaperIdOther( const QString& id )
|
||||
{
|
||||
return ( id == "Other" );
|
||||
}
|
||||
|
||||
|
||||
void Db::registerCategory( Category *category )
|
||||
{
|
||||
if ( !isCategoryIdKnown( category->id() ) )
|
||||
{
|
||||
mCategories << category;
|
||||
mCategoryIds << category->id();
|
||||
mCategoryNames << category->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Duplicate category ID: " << category->id();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Category *Db::lookupCategoryFromName( const QString& name )
|
||||
{
|
||||
if ( name.isNull() || name.isEmpty() )
|
||||
{
|
||||
qWarning() << "NULL category name.";
|
||||
return mCategories.first();
|
||||
}
|
||||
|
||||
foreach ( Category *category, mCategories )
|
||||
{
|
||||
if ( category->name() == name )
|
||||
{
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown category name: \"%s\"." << name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const Category *Db::lookupCategoryFromId( const QString& id )
|
||||
{
|
||||
if ( id.isNull() || id.isEmpty() )
|
||||
{
|
||||
qDebug() << "NULL category ID.";
|
||||
return mCategories.first();
|
||||
}
|
||||
|
||||
foreach ( Category *category, mCategories )
|
||||
{
|
||||
if ( category->id() == id )
|
||||
{
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown category ID: " << id;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
QString Db::lookupCategoryIdFromName( const QString& name )
|
||||
{
|
||||
if ( !name.isNull() && !name.isEmpty() )
|
||||
{
|
||||
const Category *category = lookupCategoryFromName( name );
|
||||
if ( category != nullptr )
|
||||
{
|
||||
return category->id();
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown category name: " << name;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
QString Db::lookupCategoryNameFromId( const QString& id )
|
||||
{
|
||||
if ( !id.isNull() && !id.isEmpty() )
|
||||
{
|
||||
const Category *category = lookupCategoryFromId( id );
|
||||
if ( category != nullptr )
|
||||
{
|
||||
return category->name();
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown category id: " << id;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
bool Db::isCategoryIdKnown( const QString& id )
|
||||
{
|
||||
foreach ( Category *category, mCategories )
|
||||
{
|
||||
if ( category->id() == id )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Db::registerVendor( Vendor *vendor )
|
||||
{
|
||||
if ( !isVendorNameKnown( vendor->name() ) )
|
||||
{
|
||||
mVendors << vendor;
|
||||
mVendorNames << vendor->name();
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Duplicate vendor name: " << vendor->name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Vendor *Db::lookupVendorFromName( const QString& name )
|
||||
{
|
||||
if ( name.isNull() || name.isEmpty() )
|
||||
{
|
||||
qWarning() << "NULL vendor name.";
|
||||
return mVendors.first();
|
||||
}
|
||||
|
||||
foreach ( Vendor *vendor, mVendors )
|
||||
{
|
||||
if ( vendor->name() == name )
|
||||
{
|
||||
return vendor;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown vendor name: " << name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
QString Db::lookupVendorUrlFromName( const QString& name )
|
||||
{
|
||||
if ( !name.isNull() && !name.isEmpty() )
|
||||
{
|
||||
const Vendor *vendor = lookupVendorFromName( name );
|
||||
if ( vendor != nullptr )
|
||||
{
|
||||
return vendor->url();
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown vendor name: " << name;
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
bool Db::isVendorNameKnown( const QString& name )
|
||||
{
|
||||
foreach ( Vendor *vendor, mVendors )
|
||||
{
|
||||
if ( vendor->name() == name )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Db::registerTemplate( Template *tmplate )
|
||||
{
|
||||
if ( !isTemplateKnown( tmplate->brand(), tmplate->part() ) )
|
||||
{
|
||||
mTemplates << tmplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Duplicate template name: " << tmplate->name();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const Template *Db::lookupTemplateFromName( const QString& name )
|
||||
{
|
||||
if ( name.isNull() || name.isEmpty() )
|
||||
{
|
||||
qWarning() << "NULL template name.";
|
||||
return mTemplates.first();
|
||||
}
|
||||
|
||||
foreach ( Template *tmplate, mTemplates )
|
||||
{
|
||||
if ( tmplate->name() == name )
|
||||
{
|
||||
return tmplate;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown template name: " << name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
const Template *Db::lookupTemplateFromBrandPart( const QString& brand, const QString& part )
|
||||
{
|
||||
if ( brand.isNull() || brand.isEmpty() || part.isNull() || part.isEmpty() )
|
||||
{
|
||||
qWarning() << "NULL template brand and/or part.";
|
||||
return mTemplates.first();
|
||||
}
|
||||
|
||||
foreach ( Template *tmplate, mTemplates )
|
||||
{
|
||||
if ( (tmplate->brand() == brand) && (tmplate->part() == part) )
|
||||
{
|
||||
return tmplate;
|
||||
}
|
||||
}
|
||||
|
||||
qWarning() << "Unknown template brand, part: " << brand << ", " << part;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool Db::isTemplateKnown( const QString& brand, const QString& part )
|
||||
{
|
||||
foreach ( Template *tmplate, mTemplates )
|
||||
{
|
||||
if ( (tmplate->brand() == brand) && (tmplate->part() == part) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QStringList Db::getNameListOfSimilarTemplates( const QString& name )
|
||||
{
|
||||
QStringList list;
|
||||
|
||||
const Template *tmplate1 = lookupTemplateFromName( name );
|
||||
if ( tmplate1 == nullptr )
|
||||
{
|
||||
qWarning() << "Unknown template name: " << name;
|
||||
return list;
|
||||
}
|
||||
|
||||
foreach (const Template *tmplate2, mTemplates )
|
||||
{
|
||||
if ( tmplate1->name() != tmplate2->name() )
|
||||
{
|
||||
if ( tmplate1->isSimilarTo( tmplate2 ) )
|
||||
{
|
||||
list << tmplate2->name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void Db::registerUserTemplate( Template *templat )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
void Db::deleteUserTemplateByName( const QString& name )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
void Db::deleteUserTemplateByBrandPart( const QString& brand, const QString& part )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
void Db::printKnownPapers()
|
||||
{
|
||||
qDebug() << "KNOWN PAPERS:";
|
||||
|
||||
foreach ( Paper *paper, mPapers )
|
||||
{
|
||||
qDebug() << "paper "
|
||||
<< "id=" << paper->id() << ", "
|
||||
<< "name=" << paper->name() << ", "
|
||||
<< "width=" << paper->width().pt() << "pts, "
|
||||
<< "height=" << paper->height().pt() << "pts, "
|
||||
<< "pwg_size=" << paper->pwgSize();
|
||||
}
|
||||
|
||||
qDebug();
|
||||
}
|
||||
|
||||
|
||||
void Db::printKnownCategories()
|
||||
{
|
||||
qDebug() << "KNOWN CATEGORIES:";
|
||||
|
||||
foreach ( Category *category, mCategories )
|
||||
{
|
||||
qDebug() << "category "
|
||||
<< "id=" << category->id() << ", "
|
||||
<< "name=" << category->name();
|
||||
}
|
||||
|
||||
qDebug();
|
||||
}
|
||||
|
||||
|
||||
void Db::printKnownVendors()
|
||||
{
|
||||
qDebug() << "KNOWN VENDORS:";
|
||||
|
||||
foreach ( Vendor *vendor, mVendors )
|
||||
{
|
||||
qDebug() << "vendor "
|
||||
<< "name='" << vendor->name() << ", "
|
||||
<< "url='" << vendor->url();
|
||||
}
|
||||
|
||||
qDebug();
|
||||
}
|
||||
|
||||
|
||||
void Db::printKnownTemplates()
|
||||
{
|
||||
qDebug() << "KNOWN TEMPLATES:";
|
||||
|
||||
foreach ( Template *tmplate, mTemplates )
|
||||
{
|
||||
qDebug() << "template "
|
||||
<< "brand=" << tmplate->brand() << ", "
|
||||
<< "part=" << tmplate->part() << ", "
|
||||
<< "description=" << tmplate->description();
|
||||
}
|
||||
|
||||
qDebug();
|
||||
}
|
||||
|
||||
|
||||
void Db::readPapers()
|
||||
{
|
||||
readPapersFromDir( FileUtil::systemTemplatesDir() );
|
||||
}
|
||||
|
||||
|
||||
void Db::readPapersFromDir( const QDir& dir )
|
||||
{
|
||||
XmlPaperParser parser;
|
||||
|
||||
foreach ( QString fileName, dir.entryList( QDir::Files ) )
|
||||
{
|
||||
if ( fileName == "paper-sizes.xml" )
|
||||
{
|
||||
parser.readFile( dir.absoluteFilePath( fileName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Db::readCategories()
|
||||
{
|
||||
readCategoriesFromDir( FileUtil::systemTemplatesDir() );
|
||||
}
|
||||
|
||||
|
||||
void Db::readCategoriesFromDir( const QDir& dir )
|
||||
{
|
||||
XmlCategoryParser parser;
|
||||
|
||||
foreach ( QString fileName, dir.entryList( QDir::Files ) )
|
||||
{
|
||||
if ( fileName == "categories.xml" )
|
||||
{
|
||||
parser.readFile( dir.absoluteFilePath( fileName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Db::readVendors()
|
||||
{
|
||||
readVendorsFromDir( FileUtil::systemTemplatesDir() );
|
||||
}
|
||||
|
||||
|
||||
void Db::readVendorsFromDir( const QDir& dir )
|
||||
{
|
||||
XmlVendorParser parser;
|
||||
|
||||
foreach ( QString fileName, dir.entryList( QDir::Files ) )
|
||||
{
|
||||
if ( fileName == "vendors.xml" )
|
||||
{
|
||||
parser.readFile( dir.absoluteFilePath( fileName ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Db::readTemplates()
|
||||
{
|
||||
readTemplatesFromDir( FileUtil::systemTemplatesDir() );
|
||||
|
||||
// TODO: Read user directories
|
||||
|
||||
std::stable_sort( mTemplates.begin(), mTemplates.end(), partNameLessThan );
|
||||
}
|
||||
|
||||
|
||||
void Db::readTemplatesFromDir( const QDir& dir )
|
||||
{
|
||||
QStringList filters;
|
||||
filters << "*-templates.xml" << "*.template";
|
||||
|
||||
XmlTemplateParser parser;
|
||||
|
||||
foreach ( QString fileName, dir.entryList( filters, QDir::Files ) )
|
||||
{
|
||||
parser.readFile( dir.absoluteFilePath( fileName ) );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/* Db.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Db_h
|
||||
#define model_Db_h
|
||||
|
||||
|
||||
#include "Category.h"
|
||||
#include "Paper.h"
|
||||
#include "Template.h"
|
||||
#include "Vendor.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Db
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Db)
|
||||
|
||||
private:
|
||||
Db();
|
||||
|
||||
|
||||
public:
|
||||
static void init();
|
||||
static Db* instance();
|
||||
|
||||
|
||||
static const QList<Paper*>& papers();
|
||||
static const QStringList& paperIds();
|
||||
static const QStringList& paperNames();
|
||||
|
||||
static const QList<Category*>& categories();
|
||||
static const QStringList& categoryIds();
|
||||
static const QStringList& categoryNames();
|
||||
|
||||
static const QList<Vendor*>& vendors();
|
||||
static const QStringList& vendorNames();
|
||||
|
||||
static const QList<Template*>& templates();
|
||||
|
||||
|
||||
static void registerPaper( Paper *paper );
|
||||
static const Paper *lookupPaperFromName( const QString& name );
|
||||
static const Paper *lookupPaperFromId( const QString& id );
|
||||
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 );
|
||||
static const Category *lookupCategoryFromId( const QString& id );
|
||||
static QString lookupCategoryIdFromName( const QString& name );
|
||||
static QString lookupCategoryNameFromId( const QString& id );
|
||||
static bool isCategoryIdKnown( const QString& id );
|
||||
|
||||
static void registerVendor( Vendor *vendor );
|
||||
static const Vendor *lookupVendorFromName( const QString& name );
|
||||
static QString lookupVendorUrlFromName( const QString& name );
|
||||
static bool isVendorNameKnown( const QString& id );
|
||||
|
||||
static void registerTemplate( Template *tmplate );
|
||||
static const Template *lookupTemplateFromName( const QString& name );
|
||||
static const Template *lookupTemplateFromBrandPart( const QString& brand,
|
||||
const QString& part );
|
||||
static bool isTemplateKnown( const QString& brand, const QString& part );
|
||||
static QStringList getNameListOfSimilarTemplates( const QString& name );
|
||||
|
||||
static void registerUserTemplate( Template *tmplate );
|
||||
static void deleteUserTemplateByName( const QString& name );
|
||||
static void deleteUserTemplateByBrandPart( const QString& brand,
|
||||
const QString& part );
|
||||
|
||||
static void printKnownPapers();
|
||||
static void printKnownCategories();
|
||||
static void printKnownVendors();
|
||||
static void printKnownTemplates();
|
||||
|
||||
|
||||
private:
|
||||
static QDir systemTemplatesDir();
|
||||
|
||||
static void readPapers();
|
||||
static void readPapersFromDir( const QDir& dir );
|
||||
|
||||
static void readCategories();
|
||||
static void readCategoriesFromDir( const QDir& dir );
|
||||
|
||||
static void readVendors();
|
||||
static void readVendorsFromDir( const QDir& dir );
|
||||
|
||||
static void readTemplates();
|
||||
static void readTemplatesFromDir( const QDir& dir );
|
||||
|
||||
|
||||
private:
|
||||
static QList<Paper*> mPapers;
|
||||
static QStringList mPaperIds;
|
||||
static QStringList mPaperNames;
|
||||
|
||||
static QList<Category*> mCategories;
|
||||
static QStringList mCategoryIds;
|
||||
static QStringList mCategoryNames;
|
||||
|
||||
static QList<Vendor*> mVendors;
|
||||
static QStringList mVendorNames;
|
||||
|
||||
static QList<Template*> mTemplates;
|
||||
|
||||
static QString mPaperNameOther;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Db_h
|
||||
@@ -0,0 +1,207 @@
|
||||
/* Distance.cpp
|
||||
*
|
||||
* Copyright (C) 2016 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 "Distance.h"
|
||||
|
||||
#include <QTextStream>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Distance::Distance( double d, Units::Enum unitsEnum )
|
||||
{
|
||||
switch (unitsEnum)
|
||||
{
|
||||
case Units::PT:
|
||||
mDPts = d;
|
||||
break;
|
||||
case Units::IN:
|
||||
mDPts = d * PTS_PER_INCH;
|
||||
break;
|
||||
case Units::MM:
|
||||
mDPts = d * PTS_PER_MM;
|
||||
break;
|
||||
case Units::CM:
|
||||
mDPts = d * PTS_PER_CM;
|
||||
break;
|
||||
case Units::PC:
|
||||
mDPts = d * PTS_PER_PICA;
|
||||
break;
|
||||
default:
|
||||
mDPts = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Distance::Distance( double d, const Units& units )
|
||||
{
|
||||
switch (units.toEnum())
|
||||
{
|
||||
case Units::PT:
|
||||
mDPts = d;
|
||||
break;
|
||||
case Units::IN:
|
||||
mDPts = d * PTS_PER_INCH;
|
||||
break;
|
||||
case Units::MM:
|
||||
mDPts = d * PTS_PER_MM;
|
||||
break;
|
||||
case Units::CM:
|
||||
mDPts = d * PTS_PER_CM;
|
||||
break;
|
||||
case Units::PC:
|
||||
mDPts = d * PTS_PER_PICA;
|
||||
break;
|
||||
default:
|
||||
mDPts = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Distance::Distance( double d, const QString& unitsId )
|
||||
{
|
||||
Units units = Units( unitsId );
|
||||
|
||||
switch (units.toEnum())
|
||||
{
|
||||
case Units::PT:
|
||||
mDPts = d;
|
||||
break;
|
||||
case Units::IN:
|
||||
mDPts = d * PTS_PER_INCH;
|
||||
break;
|
||||
case Units::MM:
|
||||
mDPts = d * PTS_PER_MM;
|
||||
break;
|
||||
case Units::CM:
|
||||
mDPts = d * PTS_PER_CM;
|
||||
break;
|
||||
case Units::PC:
|
||||
mDPts = d * PTS_PER_PICA;
|
||||
break;
|
||||
default:
|
||||
mDPts = d;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Distance Distance::fromString( const QString& string )
|
||||
{
|
||||
QString stringCopy = string;
|
||||
QTextStream valueStream( &stringCopy, QIODevice::ReadOnly );
|
||||
|
||||
double value;
|
||||
QString unitsString;
|
||||
valueStream >> value >> unitsString;
|
||||
|
||||
if ( !unitsString.isEmpty() && !Units::isIdValid( unitsString ) )
|
||||
{
|
||||
qWarning() << "Invalid Units in string: \"" << string << "\"";
|
||||
}
|
||||
|
||||
return Distance( value, unitsString );
|
||||
}
|
||||
|
||||
|
||||
double Distance::inUnits( const Units& units ) const
|
||||
{
|
||||
double d;
|
||||
|
||||
switch (units.toEnum())
|
||||
{
|
||||
case Units::PT:
|
||||
d = pt();
|
||||
break;
|
||||
case Units::IN:
|
||||
d = in();
|
||||
break;
|
||||
case Units::MM:
|
||||
d = mm();
|
||||
break;
|
||||
case Units::CM:
|
||||
d = cm();
|
||||
break;
|
||||
case Units::PC:
|
||||
d = pc();
|
||||
break;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
double Distance::inUnits( Units::Enum unitsEnum ) const
|
||||
{
|
||||
double d;
|
||||
|
||||
switch (unitsEnum)
|
||||
{
|
||||
case Units::PT:
|
||||
d = pt();
|
||||
break;
|
||||
case Units::IN:
|
||||
d = in();
|
||||
break;
|
||||
case Units::MM:
|
||||
d = mm();
|
||||
break;
|
||||
case Units::CM:
|
||||
d = cm();
|
||||
break;
|
||||
case Units::PC:
|
||||
d = pc();
|
||||
break;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
double Distance::inUnits( const QString& unitsId ) const
|
||||
{
|
||||
return inUnits( Units( unitsId ) );
|
||||
}
|
||||
|
||||
|
||||
QString Distance::toString( const Units& units ) const
|
||||
{
|
||||
return QString::number( inUnits(units) ) + units.toIdString();
|
||||
}
|
||||
|
||||
|
||||
QString Distance::toString( Units::Enum unitsEnum ) const
|
||||
{
|
||||
Units units(unitsEnum);
|
||||
return QString::number( inUnits(units) ) + units.toIdString();
|
||||
}
|
||||
|
||||
|
||||
QString Distance::toString( const QString& unitsId ) const
|
||||
{
|
||||
Units units(unitsId);
|
||||
return QString::number( inUnits(units) ) + units.toIdString();
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,302 @@
|
||||
/* Distance.h
|
||||
*
|
||||
* Copyright (C) 2016 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 model_Distance_h
|
||||
#define model_Distance_h
|
||||
|
||||
|
||||
#include "Units.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QtMath>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Distance
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Distance)
|
||||
|
||||
public:
|
||||
Distance();
|
||||
Distance( double d, Units::Enum unitsEnum = Units::PT );
|
||||
Distance( double d, const Units& units );
|
||||
Distance( double d, const QString& unitsId );
|
||||
|
||||
static Distance pt( double dPts );
|
||||
static Distance in( double dInches );
|
||||
static Distance mm( double dMm );
|
||||
static Distance cm( double dCm );
|
||||
static Distance pc( double dPicas );
|
||||
static Distance fromString( const QString& string );
|
||||
|
||||
|
||||
double pt() const;
|
||||
double in() const;
|
||||
double mm() const;
|
||||
double cm() const;
|
||||
double pc() const;
|
||||
double inUnits( const Units& units ) const;
|
||||
double inUnits( Units::Enum unitsEnum ) const;
|
||||
double inUnits( const QString& unitsId ) const;
|
||||
|
||||
|
||||
QString toString( const Units& units ) const;
|
||||
QString toString( Units::Enum unitsEnum ) const;
|
||||
QString toString( const QString& unitsId ) const;
|
||||
|
||||
|
||||
Distance& operator+=( const Distance& d );
|
||||
Distance& operator-=( const Distance& d );
|
||||
Distance operator-();
|
||||
|
||||
friend inline Distance operator+( const Distance& d1, const Distance& d2 );
|
||||
friend inline Distance operator-( const Distance& d1, const Distance& d2 );
|
||||
friend inline Distance operator*( double x, const Distance& d );
|
||||
friend inline Distance operator*( const Distance& d, double x );
|
||||
friend inline double operator/( const Distance& d1, const Distance& d2 );
|
||||
friend inline Distance operator/( const Distance& d, double x );
|
||||
|
||||
friend inline bool operator<( const Distance& d1, const Distance& d2 );
|
||||
friend inline bool operator<=( const Distance& d1, const Distance& d2 );
|
||||
friend inline bool operator>( const Distance& d1, const Distance& d2 );
|
||||
friend inline bool operator>=( const Distance& d1, const Distance& d2 );
|
||||
friend inline bool operator==( const Distance& d1, const Distance& d2 );
|
||||
friend inline bool operator!=( const Distance& d1, const Distance& d2 );
|
||||
|
||||
friend inline Distance fabs( const Distance& d );
|
||||
friend inline Distance min( const Distance& d1, const Distance& d2 );
|
||||
friend inline Distance max( const Distance& d1, const Distance& d2 );
|
||||
friend inline Distance fmod( const Distance& d1, const Distance& d2 );
|
||||
|
||||
|
||||
private:
|
||||
double mDPts;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Inline methods
|
||||
//
|
||||
|
||||
#include "Constants.h"
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
inline Distance::Distance() : mDPts(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
inline Distance Distance::pt( double dPts )
|
||||
{
|
||||
Distance d;
|
||||
d.mDPts = dPts;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline Distance Distance::in( double dInches )
|
||||
{
|
||||
Distance d;
|
||||
d.mDPts = dInches * PTS_PER_INCH;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline Distance Distance::mm( double dMm )
|
||||
{
|
||||
Distance d;
|
||||
d.mDPts = dMm * PTS_PER_MM;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline Distance Distance::cm( double dCm )
|
||||
{
|
||||
Distance d;
|
||||
d.mDPts = dCm * PTS_PER_CM;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline Distance Distance::pc( double dPicas )
|
||||
{
|
||||
Distance d;
|
||||
d.mDPts = dPicas * PTS_PER_PICA;
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
inline double Distance::pt() const
|
||||
{
|
||||
return mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline double Distance::in() const
|
||||
{
|
||||
return mDPts / PTS_PER_INCH;
|
||||
}
|
||||
|
||||
|
||||
inline double Distance::mm() const
|
||||
{
|
||||
return mDPts / PTS_PER_MM;
|
||||
}
|
||||
|
||||
|
||||
inline double Distance::cm() const
|
||||
{
|
||||
return mDPts / PTS_PER_CM;
|
||||
}
|
||||
|
||||
|
||||
inline double Distance::pc() const
|
||||
{
|
||||
return mDPts / PTS_PER_PICA;
|
||||
}
|
||||
|
||||
|
||||
inline Distance& Distance::operator+=( const Distance& d )
|
||||
{
|
||||
mDPts += d.mDPts;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline Distance& Distance::operator-=( const Distance& d )
|
||||
{
|
||||
mDPts -= d.mDPts;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline Distance Distance::operator-()
|
||||
{
|
||||
return Distance::pt( -mDPts );
|
||||
}
|
||||
|
||||
|
||||
inline Distance operator+( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return Distance::pt( d1.mDPts + d2.mDPts );
|
||||
}
|
||||
|
||||
|
||||
inline Distance operator-( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return Distance::pt( d1.mDPts - d2.mDPts );
|
||||
}
|
||||
|
||||
|
||||
inline Distance operator*( double x, const Distance& d )
|
||||
{
|
||||
return Distance::pt( x * d.mDPts );
|
||||
}
|
||||
|
||||
|
||||
inline Distance operator*( const Distance& d, double x )
|
||||
{
|
||||
return Distance::pt( d.mDPts * x );
|
||||
}
|
||||
|
||||
|
||||
inline double operator/( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts / d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline Distance operator/( const Distance& d, double x )
|
||||
{
|
||||
return Distance::pt( d.mDPts / x );
|
||||
}
|
||||
|
||||
|
||||
inline bool operator<( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts < d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator<=( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts <= d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator>( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts > d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator>=( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts >= d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator==( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts == d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline bool operator!=( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return d1.mDPts != d2.mDPts;
|
||||
}
|
||||
|
||||
|
||||
inline Distance fabs( const Distance& d )
|
||||
{
|
||||
return Distance::pt( qFabs( d.mDPts ) );
|
||||
}
|
||||
|
||||
|
||||
inline Distance min( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return (d1.mDPts < d2.mDPts) ? d1 : d2;
|
||||
}
|
||||
|
||||
|
||||
inline Distance max( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return (d1.mDPts > d2.mDPts) ? d1 : d2;
|
||||
}
|
||||
|
||||
|
||||
inline Distance fmod( const Distance& d1, const Distance& d2 )
|
||||
{
|
||||
return Distance::pt( std::fmod( d1.mDPts, d2.mDPts ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Distance_h
|
||||
@@ -0,0 +1,87 @@
|
||||
/* FileUtil.cpp
|
||||
*
|
||||
* Copyright (C) 2015 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 "FileUtil.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
QString FileUtil::addExtension( const QString& rawFilename, const QString& extension )
|
||||
{
|
||||
if ( rawFilename.endsWith( extension ) )
|
||||
{
|
||||
return rawFilename;
|
||||
}
|
||||
|
||||
return rawFilename + extension;
|
||||
}
|
||||
|
||||
|
||||
QDir FileUtil::systemTemplatesDir()
|
||||
{
|
||||
QDir dir;
|
||||
|
||||
// First, try finding templates directory relative to application path
|
||||
dir.cd( QApplication::applicationDirPath() );
|
||||
if ( (dir.dirName() == "bin") &&
|
||||
dir.cdUp() && dir.cd( "share" ) && dir.cd( "glabels-qt" ) && dir.cd( "templates" ) )
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
|
||||
// Next, try running out of the source directory.
|
||||
if ( dir.cd( Config::PROJECT_SOURCE_DIR ) && dir.cd( "templates" ) )
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
|
||||
qFatal( "Cannot locate system template directory!" );
|
||||
return QDir("/");
|
||||
}
|
||||
|
||||
|
||||
QDir FileUtil::translationsDir()
|
||||
{
|
||||
QDir dir;
|
||||
|
||||
// First, try finding translations directory relative to application path
|
||||
dir.cd( QApplication::applicationDirPath() );
|
||||
if ( (dir.dirName() == "bin") &&
|
||||
dir.cdUp() && dir.cd( "share" ) && dir.cd( "glabels-qt" ) && dir.cd( "translations" ) )
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
|
||||
// Next, try running out of the source directory.
|
||||
if ( dir.cd( Config::PROJECT_BUILD_DIR ) && dir.cd( "translations" ) )
|
||||
{
|
||||
return dir;
|
||||
}
|
||||
|
||||
qFatal( "Cannot locate system template directory!" );
|
||||
return QDir("/");
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,46 @@
|
||||
/* FileUtil.h
|
||||
*
|
||||
* Copyright (C) 2015 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 model_FileUtil_h
|
||||
#define model_FileUtil_h
|
||||
|
||||
|
||||
#include <QString>
|
||||
#include <QDir>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
namespace FileUtil
|
||||
{
|
||||
|
||||
QString addExtension( const QString& rawFilename, const QString& extension );
|
||||
|
||||
QDir systemTemplatesDir();
|
||||
QDir userTemplatesDir();
|
||||
|
||||
QDir translationsDir();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_FileUtil_h
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
/* Frame.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Frame.h"
|
||||
|
||||
#include "Markup.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Frame::Frame( const QString& id )
|
||||
: mId(id), mNLabels(0), mLayoutDescription("")
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Frame::Frame( const Frame& other )
|
||||
{
|
||||
mId = other.mId;
|
||||
mNLabels = 0;
|
||||
|
||||
foreach ( Layout *layout, mLayouts )
|
||||
{
|
||||
addLayout( layout->dup() );
|
||||
}
|
||||
|
||||
foreach ( Markup *markup, mMarkups )
|
||||
{
|
||||
addMarkup( markup->dup() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString Frame::id() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
|
||||
int Frame::nLabels() const
|
||||
{
|
||||
return mNLabels;
|
||||
}
|
||||
|
||||
|
||||
QString Frame::layoutDescription() const
|
||||
{
|
||||
return mLayoutDescription;
|
||||
}
|
||||
|
||||
|
||||
const QList<Layout*>& Frame::layouts() const
|
||||
{
|
||||
return mLayouts;
|
||||
}
|
||||
|
||||
|
||||
const QList<Markup*>& Frame::markups() const
|
||||
{
|
||||
return mMarkups;
|
||||
}
|
||||
|
||||
|
||||
QVector<Point> Frame::getOrigins() const
|
||||
{
|
||||
QVector<Point> origins( nLabels() );
|
||||
|
||||
int i = 0;
|
||||
foreach ( Layout *layout, mLayouts )
|
||||
{
|
||||
for ( int iy = 0; iy < layout->ny(); iy++ )
|
||||
{
|
||||
for ( int ix = 0; ix < layout->nx(); ix++ )
|
||||
{
|
||||
origins[i++] = Point( ix*layout->dx() + layout->x0(), iy*layout->dy() + layout->y0() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_sort( origins.begin(), origins.end() );
|
||||
|
||||
return origins;
|
||||
}
|
||||
|
||||
|
||||
void Frame::addLayout( Layout *layout )
|
||||
{
|
||||
mLayouts << layout;
|
||||
|
||||
// Update total number of labels
|
||||
mNLabels += layout->nx() * layout->ny();
|
||||
|
||||
// Update layout description
|
||||
if ( mLayouts.size() == 1 )
|
||||
{
|
||||
/*
|
||||
* Translators: %1 = number of labels across a page,
|
||||
* %2 = number of labels down a page,
|
||||
* %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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Translators: %1 is the total number of labels on a page (sheet). */
|
||||
mLayoutDescription = QString( tr("%1 per sheet") ).arg(mNLabels);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Frame::addMarkup( Markup *markup )
|
||||
{
|
||||
mMarkups << markup;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,88 @@
|
||||
/* Frame.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Frame_h
|
||||
#define model_Frame_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
#include "Layout.h"
|
||||
#include "Point.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QPainterPath>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward references
|
||||
class Markup;
|
||||
|
||||
|
||||
class Frame
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Frame)
|
||||
|
||||
protected:
|
||||
Frame( const QString& id = "0" );
|
||||
Frame( const Frame& other );
|
||||
|
||||
public:
|
||||
virtual Frame* dup() const = 0;
|
||||
|
||||
QString id() const;
|
||||
int nLabels() const;
|
||||
QString layoutDescription() const;
|
||||
const QList<Layout*>& layouts() const;
|
||||
const QList<Markup*>& markups() const;
|
||||
|
||||
QVector<Point> getOrigins() const;
|
||||
|
||||
void addLayout( Layout* layout );
|
||||
void addMarkup( Markup* markup );
|
||||
|
||||
virtual Distance w() const = 0;
|
||||
virtual Distance h() const = 0;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
private:
|
||||
QString mId;
|
||||
int mNLabels;
|
||||
QString mLayoutDescription;
|
||||
|
||||
QList<Layout*> mLayouts;
|
||||
QList<Markup*> mMarkups;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Frame_h
|
||||
@@ -0,0 +1,218 @@
|
||||
/* FrameCd.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "FrameCd.h"
|
||||
|
||||
#include "Constants.h"
|
||||
#include "StrUtil.h"
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
FrameCd::FrameCd( const Distance& r1,
|
||||
const Distance& r2,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& waste,
|
||||
const QString& id )
|
||||
: Frame(id), mR1(r1), mR2(r2), mW(w), mH(h), mWaste(waste)
|
||||
{
|
||||
Distance wReal = (mW == 0) ? 2*mR1 : mW;
|
||||
Distance hReal = (mH == 0) ? 2*mR1 : mH;
|
||||
|
||||
//
|
||||
// Create path
|
||||
//
|
||||
{
|
||||
/*
|
||||
* Construct outer subpath (may be clipped if it's a business card CD)
|
||||
*/
|
||||
QPainterPath outerPath;
|
||||
outerPath.addEllipse( (wReal/2 - r1).pt(), (hReal/2 - r1).pt(), 2*r1.pt(), 2*r1.pt() );
|
||||
|
||||
QPainterPath clipPath;
|
||||
clipPath.addRect( 0, 0, wReal.pt(), hReal.pt() );
|
||||
|
||||
mPath.addPath( outerPath & clipPath );
|
||||
mPath.closeSubpath();
|
||||
|
||||
/*
|
||||
* Add inner subpath
|
||||
*/
|
||||
mPath.addEllipse( (wReal/2 - r2).pt(), (hReal/2 - r2).pt(), 2*r2.pt(), 2*r2.pt() );
|
||||
}
|
||||
|
||||
//
|
||||
// Create clip path
|
||||
//
|
||||
{
|
||||
Distance r1Clip = mR1 + mWaste;
|
||||
Distance r2Clip = mR2 - mWaste;
|
||||
Distance wClip = (mW == 0) ? 2*r1Clip : mW + 2*mWaste;
|
||||
Distance hClip = (mH == 0) ? 2*r1Clip : mH + 2*mWaste;
|
||||
|
||||
/*
|
||||
* Construct outer subpath (may be clipped if it's a business card CD)
|
||||
*/
|
||||
QPainterPath outerPath;
|
||||
outerPath.addEllipse( (wReal/2 - r1Clip).pt(), (hReal/2 - r1Clip).pt(), 2*r1Clip.pt(), 2*r1Clip.pt() );
|
||||
|
||||
QPainterPath clipPath;
|
||||
clipPath.addRect( -mWaste.pt(), -mWaste.pt(), wClip.pt(), hClip.pt() );
|
||||
|
||||
mClipPath.addPath( outerPath & clipPath );
|
||||
mClipPath.closeSubpath();
|
||||
|
||||
/*
|
||||
* Add inner subpath
|
||||
*/
|
||||
mClipPath.addEllipse( (wReal/2 - r2Clip).pt(), (hReal/2 - r2Clip).pt(), 2*r2Clip.pt(), 2*r2Clip.pt() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
Distance FrameCd::w() const
|
||||
{
|
||||
return (mW == 0) ? 2*mR1 : mW;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameCd::h() const
|
||||
{
|
||||
return (mH == 0) ? 2*mR1 : mH;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameCd::r1() const
|
||||
{
|
||||
return mR1;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameCd::r2() const
|
||||
{
|
||||
return mR2;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameCd::waste() const
|
||||
{
|
||||
return mWaste;
|
||||
}
|
||||
|
||||
|
||||
QString FrameCd::sizeDescription( const Units& units ) const
|
||||
{
|
||||
if ( units.toEnum() == Units::IN )
|
||||
{
|
||||
QString dStr = StrUtil::formatFraction( 2 * mR1.in() );
|
||||
|
||||
return QString().sprintf( "%s %s %s",
|
||||
qPrintable(dStr),
|
||||
qPrintable(units.toTrName()),
|
||||
qPrintable(tr("diameter")) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString().sprintf( "%.5g %s %s",
|
||||
2 * mR1.inUnits(units),
|
||||
qPrintable(units.toTrName()),
|
||||
qPrintable(tr("diameter")) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FrameCd::isSimilarTo( Frame* other ) const
|
||||
{
|
||||
if ( FrameCd *otherCd = dynamic_cast<FrameCd*>(other) )
|
||||
{
|
||||
if ( (fabs( mW - otherCd->mW ) <= EPSILON) &&
|
||||
(fabs( mH - otherCd->mH ) <= EPSILON) &&
|
||||
(fabs( mR1 - otherCd->mR1 ) <= EPSILON) &&
|
||||
(fabs( mR2 - otherCd->mR2 ) <= EPSILON) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameCd::path() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameCd::clipPath() const
|
||||
{
|
||||
return mClipPath;
|
||||
}
|
||||
|
||||
|
||||
QPainterPath FrameCd::marginPath( const Distance& size ) const
|
||||
{
|
||||
Distance wReal = (mW == 0) ? 2*mR1 : mW;
|
||||
Distance hReal = (mH == 0) ? 2*mR1 : mH;
|
||||
|
||||
Distance r1 = mR1 - size;
|
||||
Distance r2 = mR2 + size;
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
/*
|
||||
* Construct outer subpath (may be clipped if it's a business card CD)
|
||||
*/
|
||||
QPainterPath outerPath;
|
||||
outerPath.addEllipse( (wReal/2 - r1).pt(), (hReal/2 - r1).pt(), 2*r1.pt(), 2*r1.pt() );
|
||||
|
||||
QPainterPath clipPath;
|
||||
clipPath.addRect( size.pt(), size.pt(), (wReal-2*size).pt(), (hReal-2*size).pt() );
|
||||
|
||||
path.addPath( outerPath & clipPath );
|
||||
path.closeSubpath();
|
||||
|
||||
/*
|
||||
* Add inner subpath
|
||||
*/
|
||||
path.addEllipse( (wReal/2 - r2).pt(), (hReal/2 - r2).pt(), 2*r2.pt(), 2*r2.pt() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,77 @@
|
||||
/* FrameCd.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_FrameCd_h
|
||||
#define model_FrameCd_h
|
||||
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class FrameCd : public Frame
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(FrameCd)
|
||||
|
||||
public:
|
||||
FrameCd( const Distance& r1,
|
||||
const Distance& r2,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& waste,
|
||||
const QString& id = "0" );
|
||||
|
||||
FrameCd( const FrameCd &other );
|
||||
|
||||
Frame *dup() const override;
|
||||
|
||||
Distance r1() const;
|
||||
Distance r2() const;
|
||||
Distance waste() 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& size ) const override;
|
||||
|
||||
|
||||
private:
|
||||
Distance mR1;
|
||||
Distance mR2;
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
Distance mWaste;
|
||||
|
||||
QPainterPath mPath;
|
||||
QPainterPath mClipPath;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_FrameCd_h
|
||||
@@ -0,0 +1,130 @@
|
||||
/* FrameEllipse.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "FrameEllipse.h"
|
||||
|
||||
#include "Constants.h"
|
||||
#include "StrUtil.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
FrameEllipse::FrameEllipse( const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& waste,
|
||||
const QString& id )
|
||||
: Frame(id), mW(w), mH(h), mWaste(waste)
|
||||
{
|
||||
mPath.addEllipse( 0, 0, mW.pt(), mH.pt() );
|
||||
mClipPath.addEllipse( -mWaste.pt(), -mWaste.pt(), (mW+2*mWaste).pt(), (mH+2*mWaste).pt() );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
Distance FrameEllipse::w() const
|
||||
{
|
||||
return mW;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameEllipse::h() const
|
||||
{
|
||||
return mH;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameEllipse::waste() const
|
||||
{
|
||||
return mWaste;
|
||||
}
|
||||
|
||||
|
||||
QString FrameEllipse::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 FrameEllipse::isSimilarTo( Frame* other ) const
|
||||
{
|
||||
if ( FrameEllipse* otherEllipse = dynamic_cast<FrameEllipse*>(other) )
|
||||
{
|
||||
if ( (fabs( mW - otherEllipse->mW ) <= EPSILON) &&
|
||||
(fabs( mH - otherEllipse->mH ) <= EPSILON) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameEllipse::path() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameEllipse::clipPath() const
|
||||
{
|
||||
return mClipPath;
|
||||
}
|
||||
|
||||
|
||||
QPainterPath FrameEllipse::marginPath( const Distance& size ) const
|
||||
{
|
||||
Distance w = mW - 2*size;
|
||||
Distance h = mH - 2*size;
|
||||
|
||||
QPainterPath path;
|
||||
path.addEllipse( size.pt(), size.pt(), w.pt(), h.pt() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,71 @@
|
||||
/* FrameEllipse.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_FrameEllipse_h
|
||||
#define model_FrameEllipse_h
|
||||
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class FrameEllipse : public Frame
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(FrameEllipse)
|
||||
|
||||
public:
|
||||
FrameEllipse( const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& waste,
|
||||
const QString& id = "0" );
|
||||
|
||||
FrameEllipse( const FrameEllipse& other );
|
||||
|
||||
Frame* dup() const override;
|
||||
|
||||
Distance waste() 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& size ) const override;
|
||||
|
||||
|
||||
private:
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
Distance mWaste;
|
||||
|
||||
QPainterPath mPath;
|
||||
QPainterPath mClipPath;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_FrameEllipse_h
|
||||
@@ -0,0 +1,152 @@
|
||||
/* FrameRect.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "FrameRect.h"
|
||||
|
||||
#include "Constants.h"
|
||||
#include "StrUtil.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
FrameRect::FrameRect( const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& r,
|
||||
const Distance& xWaste,
|
||||
const Distance& yWaste,
|
||||
const QString& id )
|
||||
: Frame(id), mW(w), mH(h), mR(r), mXWaste(xWaste), mYWaste(yWaste)
|
||||
{
|
||||
mPath.addRoundedRect( 0, 0, mW.pt(), mH.pt(), mR.pt(), mR.pt() );
|
||||
|
||||
mClipPath.addRoundedRect( -mXWaste.pt(), -mYWaste.pt(),
|
||||
mW.pt() + 2*mXWaste.pt(), mH.pt() + 2*mYWaste.pt(),
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRect::w() const
|
||||
{
|
||||
return mW;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRect::h() const
|
||||
{
|
||||
return mH;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRect::r() const
|
||||
{
|
||||
return mR;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRect::xWaste() const
|
||||
{
|
||||
return mXWaste;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRect::yWaste() const
|
||||
{
|
||||
return mYWaste;
|
||||
}
|
||||
|
||||
|
||||
QString FrameRect::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 FrameRect::isSimilarTo( Frame* other ) const
|
||||
{
|
||||
if ( FrameRect *otherRect = dynamic_cast<FrameRect*>(other) )
|
||||
{
|
||||
if ( (fabs( mW - otherRect->mW ) <= EPSILON) &&
|
||||
(fabs( mH - otherRect->mH ) <= EPSILON) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameRect::path() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameRect::clipPath() const
|
||||
{
|
||||
return mClipPath;
|
||||
}
|
||||
|
||||
|
||||
QPainterPath FrameRect::marginPath( const Distance& size ) const
|
||||
{
|
||||
Distance w = mW - 2*size;
|
||||
Distance h = mH - 2*size;
|
||||
Distance r = std::max( mR - size, Distance(0.0) );
|
||||
|
||||
QPainterPath path;
|
||||
path.addRoundedRect( size.pt(), size.pt(), w.pt(), h.pt(), r.pt(), r.pt() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,78 @@
|
||||
/* FrameRect.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_FrameRect_h
|
||||
#define model_FrameRect_h
|
||||
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class FrameRect : public Frame
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(FrameRect)
|
||||
|
||||
public:
|
||||
FrameRect( const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& r,
|
||||
const Distance& xWaste,
|
||||
const Distance& yWaste,
|
||||
const QString& id = "0" );
|
||||
|
||||
FrameRect( const FrameRect& other );
|
||||
|
||||
Frame* dup() const override;
|
||||
|
||||
Distance r() const;
|
||||
Distance xWaste() const;
|
||||
Distance yWaste() 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& size ) const override;
|
||||
|
||||
|
||||
private:
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
Distance mR;
|
||||
Distance mXWaste;
|
||||
Distance mYWaste;
|
||||
|
||||
QPainterPath mPath;
|
||||
QPainterPath mClipPath;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_FrameRect_h
|
||||
@@ -0,0 +1,134 @@
|
||||
/* FrameRound.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "FrameRound.h"
|
||||
|
||||
#include "Constants.h"
|
||||
#include "StrUtil.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
FrameRound::FrameRound( const Distance& r,
|
||||
const Distance& waste,
|
||||
const QString& id )
|
||||
: Frame(id), mR(r), mWaste(waste)
|
||||
{
|
||||
mPath.addEllipse( 0, 0, 2*mR.pt(), 2*mR.pt() );
|
||||
mClipPath.addEllipse( -mWaste.pt(), -mWaste.pt(),
|
||||
2*(mR+mWaste).pt(), 2*(mR+mWaste).pt() );
|
||||
}
|
||||
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRound::w() const
|
||||
{
|
||||
return 2*mR;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRound::h() const
|
||||
{
|
||||
return 2*mR;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRound::r() const
|
||||
{
|
||||
return mR;
|
||||
}
|
||||
|
||||
|
||||
Distance FrameRound::waste() const
|
||||
{
|
||||
return mWaste;
|
||||
}
|
||||
|
||||
|
||||
QString FrameRound::sizeDescription( const Units& units ) const
|
||||
{
|
||||
if ( units.toEnum() == Units::IN )
|
||||
{
|
||||
QString dStr = StrUtil::formatFraction( 2 * mR.in() );
|
||||
|
||||
return QString().sprintf( "%s %s %s",
|
||||
qPrintable(dStr),
|
||||
qPrintable(units.toTrName()),
|
||||
qPrintable(tr("diameter")) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString().sprintf( "%.5g %s %s",
|
||||
2 * mR.inUnits(units),
|
||||
qPrintable(units.toTrName()),
|
||||
qPrintable(tr("diameter")) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool FrameRound::isSimilarTo( Frame* other ) const
|
||||
{
|
||||
if ( FrameRound *otherRound = dynamic_cast<FrameRound*>(other) )
|
||||
{
|
||||
if ( fabs( mR - otherRound->mR ) <= EPSILON )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameRound::path() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
|
||||
const QPainterPath& FrameRound::clipPath() const
|
||||
{
|
||||
return mClipPath;
|
||||
}
|
||||
|
||||
|
||||
QPainterPath FrameRound::marginPath( const Distance& size ) const
|
||||
{
|
||||
Distance r = mR - size;
|
||||
|
||||
QPainterPath path;
|
||||
path.addEllipse( size.pt(), size.pt(), 2*r.pt(), 2*r.pt() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,70 @@
|
||||
/* FrameRound.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_FrameRound_h
|
||||
#define model_FrameRound_h
|
||||
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class FrameRound : public Frame
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(FrameRound)
|
||||
|
||||
public:
|
||||
FrameRound( const Distance& r,
|
||||
const Distance& waste,
|
||||
const QString& id = "0" );
|
||||
|
||||
FrameRound( const FrameRound &other );
|
||||
|
||||
Frame *dup() const override;
|
||||
|
||||
Distance r() const;
|
||||
Distance waste() 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& size ) const override;
|
||||
|
||||
|
||||
private:
|
||||
Distance mR;
|
||||
Distance mWaste;
|
||||
|
||||
QPainterPath mPath;
|
||||
QPainterPath mClipPath;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_FrameRound_h
|
||||
@@ -0,0 +1,588 @@
|
||||
/* Handles.cpp
|
||||
*
|
||||
* Copyright (C) 2013 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 "Handles.h"
|
||||
|
||||
#include "ModelObject.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const double handlePixels = 7;
|
||||
const double handleOutlineWidthPixels = 1;
|
||||
|
||||
const QColor handleFillColor( 0, 192, 0, 96 );
|
||||
const QColor originHandleFillColor( 192, 0, 0, 96 );
|
||||
const QColor handleOutlineColor( 0, 0, 0, 192 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Handle Constructor
|
||||
///
|
||||
Handle::Handle( ModelObject* owner, Location location )
|
||||
: mOwner(owner), mLocation(location)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Handle Destructor
|
||||
///
|
||||
Handle::~Handle()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Handle owner
|
||||
///
|
||||
ModelObject* Handle::owner() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Handle location
|
||||
///
|
||||
Handle::Location Handle::location() const
|
||||
{
|
||||
return mLocation;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw Handle at x,y
|
||||
///
|
||||
void Handle::drawAt( QPainter* painter,
|
||||
double scale,
|
||||
const Distance& x,
|
||||
const Distance& y,
|
||||
QColor color ) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->translate( x.pt(), y.pt() );
|
||||
|
||||
double s = 1.0 / scale;
|
||||
|
||||
QPen pen( handleOutlineColor );
|
||||
pen.setCosmetic( true );
|
||||
pen.setWidth( handleOutlineWidthPixels );
|
||||
|
||||
painter->setPen( pen );
|
||||
painter->setBrush( color );
|
||||
|
||||
painter->drawRect( QRectF( -s*handlePixels/2.0, -s*handlePixels/2.0,
|
||||
s*handlePixels, s*handlePixels ) );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Create Handle path at x,y
|
||||
///
|
||||
QPainterPath Handle::pathAt( double scale,
|
||||
const Distance& x,
|
||||
const Distance& y ) const
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
double s = 1/scale;
|
||||
|
||||
path.addRect( -s*handlePixels/2, -s*handlePixels/2, s*handlePixels, s*handlePixels );
|
||||
path.translate( x.pt(), y.pt() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorth Constructor
|
||||
///
|
||||
HandleNorth::HandleNorth( ModelObject* owner )
|
||||
: Handle( owner, N )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorth Destructor
|
||||
///
|
||||
HandleNorth::~HandleNorth()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorth Clone
|
||||
///
|
||||
HandleNorth* HandleNorth::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleNorth( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleNorth
|
||||
///
|
||||
void HandleNorth::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, mOwner->w()/2, 0, handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorth Path
|
||||
///
|
||||
QPainterPath HandleNorth::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, mOwner->w()/2, 0 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthEast Constructor
|
||||
///
|
||||
HandleNorthEast::HandleNorthEast( ModelObject* owner )
|
||||
: Handle( owner, NE )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthEast Destructor
|
||||
///
|
||||
HandleNorthEast::~HandleNorthEast()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthEast Clone
|
||||
///
|
||||
HandleNorthEast* HandleNorthEast::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleNorthEast( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleNorthEast
|
||||
///
|
||||
void HandleNorthEast::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, mOwner->w(), 0, handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthEast Path
|
||||
///
|
||||
QPainterPath HandleNorthEast::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, mOwner->w(), 0 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleEast Constructor
|
||||
///
|
||||
HandleEast::HandleEast( ModelObject* owner )
|
||||
: Handle( owner, E )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleEast Destructor
|
||||
///
|
||||
HandleEast::~HandleEast()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleEast Clone
|
||||
///
|
||||
HandleEast* HandleEast::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleEast( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleEast
|
||||
///
|
||||
void HandleEast::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, mOwner->w(), mOwner->h()/2, handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleEast Path
|
||||
///
|
||||
QPainterPath HandleEast::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, mOwner->w(), mOwner->h()/2 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthEast Constructor
|
||||
///
|
||||
HandleSouthEast::HandleSouthEast( ModelObject* owner )
|
||||
: Handle( owner, SE )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthEast Destructor
|
||||
///
|
||||
HandleSouthEast::~HandleSouthEast()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthEast Clone
|
||||
///
|
||||
HandleSouthEast* HandleSouthEast::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleSouthEast( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleSouthEast
|
||||
///
|
||||
void HandleSouthEast::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, mOwner->w(), mOwner->h(), handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthEast Path
|
||||
///
|
||||
QPainterPath HandleSouthEast::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, mOwner->w(), mOwner->h() );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouth Constructor
|
||||
///
|
||||
HandleSouth::HandleSouth( ModelObject* owner )
|
||||
: Handle( owner, S )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouth Destructor
|
||||
///
|
||||
HandleSouth::~HandleSouth()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouth Clone
|
||||
///
|
||||
HandleSouth* HandleSouth::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleSouth( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleSouth
|
||||
///
|
||||
void HandleSouth::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, mOwner->w()/2, mOwner->h(), handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouth Path
|
||||
///
|
||||
QPainterPath HandleSouth::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, mOwner->w()/2, mOwner->h() );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthWest Constructor
|
||||
///
|
||||
HandleSouthWest::HandleSouthWest( ModelObject* owner )
|
||||
: Handle( owner, SW )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthWest Destructor
|
||||
///
|
||||
HandleSouthWest::~HandleSouthWest()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthWest Clone
|
||||
///
|
||||
HandleSouthWest* HandleSouthWest::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleSouthWest( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleSouthWest
|
||||
///
|
||||
void HandleSouthWest::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, 0, mOwner->h(), handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthWest Path
|
||||
///
|
||||
QPainterPath HandleSouthWest::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, 0, mOwner->h() );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleWest Constructor
|
||||
///
|
||||
HandleWest::HandleWest( ModelObject* owner )
|
||||
: Handle( owner, W )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleWest Destructor
|
||||
///
|
||||
HandleWest::~HandleWest()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleWest Clone
|
||||
///
|
||||
HandleWest* HandleWest::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleWest( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleWest
|
||||
///
|
||||
void HandleWest::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, 0, mOwner->h()/2, handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleWest Path
|
||||
///
|
||||
QPainterPath HandleWest::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, 0, mOwner->h()/2 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthWest Constructor
|
||||
///
|
||||
HandleNorthWest::HandleNorthWest( ModelObject* owner )
|
||||
: Handle( owner, NW )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthWest Destructor
|
||||
///
|
||||
HandleNorthWest::~HandleNorthWest()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
///
|
||||
/// HandleNorthWest Clone
|
||||
///
|
||||
HandleNorthWest* HandleNorthWest::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleNorthWest( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleNorthWest
|
||||
///
|
||||
void HandleNorthWest::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, 0, 0, originHandleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthWest Path
|
||||
///
|
||||
QPainterPath HandleNorthWest::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP1 Constructor
|
||||
///
|
||||
HandleP1::HandleP1( ModelObject* owner )
|
||||
: Handle( owner, P1 )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP1 Destructor
|
||||
///
|
||||
HandleP1::~HandleP1()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP1 Clone
|
||||
///
|
||||
HandleP1* HandleP1::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleP1( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleP1
|
||||
///
|
||||
void HandleP1::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, 0, 0, originHandleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP1 Path
|
||||
///
|
||||
QPainterPath HandleP1::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP2 Constructor
|
||||
///
|
||||
HandleP2::HandleP2( ModelObject* owner )
|
||||
: Handle( owner, P2 )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP2 Destructor
|
||||
///
|
||||
HandleP2::~HandleP2()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP2 Clone
|
||||
///
|
||||
HandleP2* HandleP2::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new HandleP2( newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw HandleP2
|
||||
///
|
||||
void HandleP2::draw( QPainter* painter, double scale ) const
|
||||
{
|
||||
drawAt( painter, scale, mOwner->w(), mOwner->h(), handleFillColor );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// HandleP2 Path
|
||||
///
|
||||
QPainterPath HandleP2::path( double scale ) const
|
||||
{
|
||||
return pathAt( scale, mOwner->w(), mOwner->h() );
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
+336
@@ -0,0 +1,336 @@
|
||||
/* Handles.h
|
||||
*
|
||||
* Copyright (C) 2013 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 model_Handles_h
|
||||
#define model_Handles_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward References
|
||||
class ModelObject;
|
||||
|
||||
|
||||
///
|
||||
/// Handle Base Class
|
||||
///
|
||||
class Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Location enumeration
|
||||
////////////////////////////
|
||||
public:
|
||||
enum Location { NW, N, NE, E, SE, S, SW, W, P1, P2 };
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
protected:
|
||||
Handle( ModelObject* owner, Location location );
|
||||
public:
|
||||
virtual ~Handle();
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Duplication
|
||||
////////////////////////////
|
||||
virtual Handle* clone( ModelObject* newOwner ) const = 0;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Attribue Methods
|
||||
////////////////////////////
|
||||
ModelObject* owner() const;
|
||||
Location location() const;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
virtual void draw( QPainter* painter, double scale ) const = 0;
|
||||
virtual QPainterPath path( double scale ) const = 0;
|
||||
protected:
|
||||
void drawAt( QPainter* painter,
|
||||
double scale,
|
||||
const Distance& x,
|
||||
const Distance& y,
|
||||
QColor color ) const;
|
||||
|
||||
QPainterPath pathAt( double scale,
|
||||
const Distance& x,
|
||||
const Distance& y ) const;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Protected Data
|
||||
////////////////////////////
|
||||
protected:
|
||||
ModelObject* mOwner;
|
||||
Location mLocation;
|
||||
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorth Class
|
||||
///
|
||||
class HandleNorth : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleNorth( ModelObject* owner );
|
||||
~HandleNorth() override;
|
||||
HandleNorth* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthEast Class
|
||||
///
|
||||
class HandleNorthEast : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleNorthEast( ModelObject* owner );
|
||||
~HandleNorthEast() override;
|
||||
HandleNorthEast* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleEast Class
|
||||
///
|
||||
class HandleEast : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleEast( ModelObject* owner );
|
||||
~HandleEast() override;
|
||||
HandleEast* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthEast Class
|
||||
///
|
||||
class HandleSouthEast : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleSouthEast( ModelObject* owner );
|
||||
~HandleSouthEast() override;
|
||||
HandleSouthEast* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouth Class
|
||||
///
|
||||
class HandleSouth : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleSouth( ModelObject* owner );
|
||||
~HandleSouth() override;
|
||||
HandleSouth* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleSouthWest Class
|
||||
///
|
||||
class HandleSouthWest : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleSouthWest( ModelObject* owner );
|
||||
~HandleSouthWest() override;
|
||||
HandleSouthWest* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleWest Class
|
||||
///
|
||||
class HandleWest : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleWest( ModelObject* owner );
|
||||
~HandleWest() override;
|
||||
HandleWest* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleNorthWest Class
|
||||
///
|
||||
class HandleNorthWest : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleNorthWest( ModelObject* owner );
|
||||
~HandleNorthWest() override;
|
||||
HandleNorthWest* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleP1 Class
|
||||
///
|
||||
class HandleP1 : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleP1( ModelObject* owner );
|
||||
~HandleP1() override;
|
||||
HandleP1* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
|
||||
///
|
||||
/// HandleP2 Class
|
||||
///
|
||||
class HandleP2 : public Handle
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
HandleP2( ModelObject* owner );
|
||||
~HandleP2() override;
|
||||
|
||||
////////////////////////////
|
||||
// Duplication
|
||||
////////////////////////////
|
||||
HandleP2* clone( ModelObject* newOwner ) const override;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, double scale ) const override;
|
||||
QPainterPath path( double scale ) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Handles_h
|
||||
@@ -0,0 +1,104 @@
|
||||
/* Layout.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Layout.h"
|
||||
|
||||
#include "Constants.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Layout::Layout( int nx,
|
||||
int ny,
|
||||
const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& dx,
|
||||
const Distance& dy )
|
||||
: mNx(nx), mNy(ny), mX0(x0), mY0(y0), mDx(dx), mDy(dy)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Layout::Layout( const Layout& other )
|
||||
: mNx(other.mNx), mNy(other.mNy), mX0(other.mX0), mY0(other.mY0),
|
||||
mDx(other.mDx), mDy(other.mDy)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
int Layout::nx() const
|
||||
{
|
||||
return mNx;
|
||||
}
|
||||
|
||||
|
||||
int Layout::ny() const
|
||||
{
|
||||
return mNy;
|
||||
}
|
||||
|
||||
|
||||
Distance Layout::x0() const
|
||||
{
|
||||
return mX0;
|
||||
}
|
||||
|
||||
|
||||
Distance Layout::y0() const
|
||||
{
|
||||
return mY0;
|
||||
}
|
||||
|
||||
|
||||
Distance Layout::dx() const
|
||||
{
|
||||
return mDx;
|
||||
}
|
||||
|
||||
|
||||
Distance Layout::dy() const
|
||||
{
|
||||
return mDy;
|
||||
}
|
||||
|
||||
|
||||
bool Layout::isSimilarTo( const Layout *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) );
|
||||
}
|
||||
|
||||
|
||||
Layout* Layout::dup() const
|
||||
{
|
||||
Layout *other = new Layout( *this );
|
||||
return other;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Layout.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Layout_h
|
||||
#define model_Layout_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Layout
|
||||
{
|
||||
|
||||
public:
|
||||
Layout( int nx,
|
||||
int ny,
|
||||
const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& dx,
|
||||
const Distance& dy );
|
||||
|
||||
Layout( const Layout &other );
|
||||
|
||||
int nx() const;
|
||||
int ny() const;
|
||||
|
||||
Distance x0() const;
|
||||
Distance y0() const;
|
||||
|
||||
Distance dx() const;
|
||||
Distance dy() const;
|
||||
|
||||
bool isSimilarTo( const Layout *other );
|
||||
|
||||
Layout* dup() const;
|
||||
|
||||
|
||||
private:
|
||||
int mNx;
|
||||
int mNy;
|
||||
Distance mX0;
|
||||
Distance mY0;
|
||||
Distance mDx;
|
||||
Distance mDy;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Layout_h
|
||||
@@ -0,0 +1,212 @@
|
||||
/* Markup.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Markup.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
const QPainterPath& Markup::path() const
|
||||
{
|
||||
return mPath;
|
||||
}
|
||||
|
||||
|
||||
MarkupMargin::MarkupMargin( const Frame* frame,
|
||||
const Distance& size )
|
||||
: mFrame(frame), mSize(size)
|
||||
{
|
||||
mPath = frame->marginPath( size );
|
||||
}
|
||||
|
||||
|
||||
Markup* MarkupMargin::dup() const
|
||||
{
|
||||
return new MarkupMargin( mFrame, mSize );
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupMargin::size() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
|
||||
MarkupLine::MarkupLine( const Distance& x1,
|
||||
const Distance& y1,
|
||||
const Distance& x2,
|
||||
const Distance& y2 )
|
||||
: mX1(x1), mY1(y1), mX2(x2), mY2(y2)
|
||||
{
|
||||
mPath.moveTo( x1.pt(), y1.pt() );
|
||||
mPath.lineTo( x2.pt(), y2.pt() );
|
||||
}
|
||||
|
||||
|
||||
Markup* MarkupLine::dup() const
|
||||
{
|
||||
return new MarkupLine( mX1, mY1, mX2, mY2 );
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupLine::x1() const
|
||||
{
|
||||
return mX1;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupLine::y1() const
|
||||
{
|
||||
return mY1;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupLine::x2() const
|
||||
{
|
||||
return mX2;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupLine::y2() const
|
||||
{
|
||||
return mY2;
|
||||
}
|
||||
|
||||
|
||||
MarkupRect::MarkupRect( const Distance& x1,
|
||||
const Distance& y1,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& r )
|
||||
: mX1(x1), mY1(y1), mW(w), mH(h), mR(r)
|
||||
{
|
||||
mPath.addRoundedRect( x1.pt(), y1.pt(), w.pt(), h.pt(), r.pt(), r.pt() );
|
||||
}
|
||||
|
||||
|
||||
Markup* MarkupRect::dup() const
|
||||
{
|
||||
return new MarkupRect( mX1, mY1, mW, mH, mR );
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupRect::x1() const
|
||||
{
|
||||
return mX1;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupRect::y1() const
|
||||
{
|
||||
return mY1;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupRect::w() const
|
||||
{
|
||||
return mW;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupRect::h() const
|
||||
{
|
||||
return mH;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupRect::r() const
|
||||
{
|
||||
return mR;
|
||||
}
|
||||
|
||||
|
||||
MarkupEllipse::MarkupEllipse( const Distance& x1,
|
||||
const Distance& y1,
|
||||
const Distance& w,
|
||||
const Distance& h )
|
||||
: mX1(x1), mY1(y1), mW(w), mH(h)
|
||||
{
|
||||
mPath.addEllipse( x1.pt(), y1.pt(), w.pt(), h.pt() );
|
||||
}
|
||||
|
||||
|
||||
Markup* MarkupEllipse::dup() const
|
||||
{
|
||||
return new MarkupEllipse( mX1, mY1, mW, mH );
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupEllipse::x1() const
|
||||
{
|
||||
return mX1;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupEllipse::y1() const
|
||||
{
|
||||
return mY1;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupEllipse::w() const
|
||||
{
|
||||
return mW;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupEllipse::h() const
|
||||
{
|
||||
return mH;
|
||||
}
|
||||
|
||||
|
||||
MarkupCircle::MarkupCircle( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& r )
|
||||
: mX0(x0), mY0(y0), mR(r)
|
||||
{
|
||||
mPath.addEllipse( (x0-r).pt(), (y0-r).pt(), 2*r.pt(), 2*r.pt() );
|
||||
}
|
||||
|
||||
Markup* MarkupCircle::dup() const
|
||||
{
|
||||
return new MarkupCircle( mX0, mY0, mR );
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupCircle::x0() const
|
||||
{
|
||||
return mX0;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupCircle::y0() const
|
||||
{
|
||||
return mY0;
|
||||
}
|
||||
|
||||
|
||||
Distance MarkupCircle::r() const
|
||||
{
|
||||
return mR;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/* Markup.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Markup_h
|
||||
#define model_Markup_h
|
||||
|
||||
|
||||
#include "Frame.h"
|
||||
|
||||
#include <QPainterPath>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Markup
|
||||
{
|
||||
public:
|
||||
virtual Markup* dup() const = 0;
|
||||
|
||||
const QPainterPath& path() const;
|
||||
|
||||
protected:
|
||||
QPainterPath mPath;
|
||||
};
|
||||
|
||||
|
||||
class MarkupMargin : public Markup
|
||||
{
|
||||
public:
|
||||
MarkupMargin( const Frame* frame,
|
||||
const Distance& size );
|
||||
|
||||
Distance size() const;
|
||||
|
||||
Markup* dup() const override;
|
||||
|
||||
private:
|
||||
const Frame* mFrame;
|
||||
Distance mSize;
|
||||
};
|
||||
|
||||
|
||||
class MarkupLine : public Markup
|
||||
{
|
||||
public:
|
||||
MarkupLine( const Distance& x1,
|
||||
const Distance& y1,
|
||||
const Distance& x2,
|
||||
const Distance& y2 );
|
||||
|
||||
Distance x1() const;
|
||||
Distance y1() const;
|
||||
Distance x2() const;
|
||||
Distance y2() const;
|
||||
|
||||
Markup* dup() const override;
|
||||
|
||||
private:
|
||||
Distance mX1;
|
||||
Distance mY1;
|
||||
Distance mX2;
|
||||
Distance mY2;
|
||||
};
|
||||
|
||||
|
||||
class MarkupRect : public Markup
|
||||
{
|
||||
public:
|
||||
MarkupRect( const Distance& x1,
|
||||
const Distance& y1,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& r );
|
||||
|
||||
Distance x1() const;
|
||||
Distance y1() const;
|
||||
Distance w() const;
|
||||
Distance h() const;
|
||||
Distance r() const;
|
||||
|
||||
Markup* dup() const override;
|
||||
|
||||
private:
|
||||
Distance mX1;
|
||||
Distance mY1;
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
Distance mR;
|
||||
};
|
||||
|
||||
|
||||
class MarkupEllipse : public Markup
|
||||
{
|
||||
public:
|
||||
MarkupEllipse( const Distance& x1,
|
||||
const Distance& y1,
|
||||
const Distance& w,
|
||||
const Distance& h );
|
||||
|
||||
Distance x1() const;
|
||||
Distance y1() const;
|
||||
Distance w() const;
|
||||
Distance h() const;
|
||||
|
||||
Markup* dup() const override;
|
||||
|
||||
private:
|
||||
Distance mX1;
|
||||
Distance mY1;
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
};
|
||||
|
||||
|
||||
class MarkupCircle : public Markup
|
||||
{
|
||||
public:
|
||||
MarkupCircle( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& r );
|
||||
|
||||
Distance x0() const;
|
||||
Distance y0() const;
|
||||
Distance r() const;
|
||||
|
||||
Markup* dup() const override;
|
||||
|
||||
private:
|
||||
Distance mX0;
|
||||
Distance mY0;
|
||||
Distance mR;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Markup_h
|
||||
+1444
File diff suppressed because it is too large
Load Diff
+239
@@ -0,0 +1,239 @@
|
||||
/* Model.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Model_h
|
||||
#define model_Model_h
|
||||
|
||||
|
||||
#include "Settings.h"
|
||||
#include "Template.h"
|
||||
|
||||
#include "merge/Merge.h"
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QList>
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward References
|
||||
class ColorNode;
|
||||
class Handle;
|
||||
class ModelObject;
|
||||
class Region;
|
||||
|
||||
///
|
||||
/// Model
|
||||
///
|
||||
class Model : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Lifecycle
|
||||
/////////////////////////////////
|
||||
public:
|
||||
Model();
|
||||
~Model() override {}
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Save/restore model state
|
||||
/////////////////////////////////
|
||||
Model* save() const;
|
||||
void restore( const Model *savedModel );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Signals
|
||||
/////////////////////////////////
|
||||
signals:
|
||||
void changed();
|
||||
void nameChanged();
|
||||
void sizeChanged();
|
||||
void selectionChanged();
|
||||
void modifiedChanged();
|
||||
void mergeChanged();
|
||||
void mergeSourceChanged();
|
||||
void mergeSelectionChanged();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Properties
|
||||
/////////////////////////////////
|
||||
public:
|
||||
bool isModified() const;
|
||||
void setModified();
|
||||
void clearModified();
|
||||
|
||||
QString shortName();
|
||||
const QString& fileName() const;
|
||||
void setFileName( const QString &fileName );
|
||||
|
||||
int compressionLevel() const;
|
||||
void setCompressionLevel( int compressionLevel );
|
||||
|
||||
const Template* tmplate() const;
|
||||
const Frame* frame() const;
|
||||
void setTmplate( const Template* tmplate );
|
||||
|
||||
bool rotate() const;
|
||||
void setRotate( bool rotate );
|
||||
|
||||
Distance w() const;
|
||||
Distance h() const;
|
||||
|
||||
const QList<ModelObject*>& objectList() const;
|
||||
|
||||
merge::Merge* merge() const;
|
||||
void setMerge( merge::Merge* merge );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Manage objects
|
||||
/////////////////////////////////
|
||||
public:
|
||||
void addObject( ModelObject* object );
|
||||
void deleteObject( ModelObject* object );
|
||||
|
||||
ModelObject* objectAt( double scale,
|
||||
const Distance& x,
|
||||
const Distance& y ) const;
|
||||
|
||||
Handle* handleAt( double scale,
|
||||
const Distance& x,
|
||||
const Distance& y ) const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Manipulate selection
|
||||
/////////////////////////////////
|
||||
public:
|
||||
void selectObject( ModelObject* object );
|
||||
void unselectObject( ModelObject* object );
|
||||
void selectAll();
|
||||
void unselectAll();
|
||||
void selectRegion( const Region& region );
|
||||
bool isSelectionEmpty();
|
||||
bool isSelectionAtomic();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Get selected objects
|
||||
/////////////////////////////////
|
||||
public:
|
||||
QList<ModelObject*> getSelection();
|
||||
ModelObject* getFirstSelectedObject();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Query selection capabilities
|
||||
/////////////////////////////////
|
||||
public:
|
||||
bool canSelectionText();
|
||||
bool canSelectionFill();
|
||||
bool canSelectionLineColor();
|
||||
bool canSelectionLineWidth();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Operations on selections
|
||||
/////////////////////////////////
|
||||
public:
|
||||
void deleteSelection();
|
||||
void raiseSelectionToTop();
|
||||
void lowerSelectionToBottom();
|
||||
void rotateSelection( double thetaDegs );
|
||||
void rotateSelectionLeft();
|
||||
void rotateSelectionRight();
|
||||
void flipSelectionHoriz();
|
||||
void flipSelectionVert();
|
||||
void alignSelectionLeft();
|
||||
void alignSelectionRight();
|
||||
void alignSelectionHCenter();
|
||||
void alignSelectionTop();
|
||||
void alignSelectionBottom();
|
||||
void alignSelectionVCenter();
|
||||
void centerSelectionHoriz();
|
||||
void centerSelectionVert();
|
||||
void moveSelection( const Distance& dx, const Distance& dy );
|
||||
void setSelectionFontFamily( const QString& fontFamily );
|
||||
void setSelectionFontSize( double fontSize );
|
||||
void setSelectionFontWeight( QFont::Weight fontWeight );
|
||||
void setSelectionFontItalicFlag( bool fontItalicFlag );
|
||||
void setSelectionTextHAlign( Qt::Alignment textHAlign );
|
||||
void setSelectionTextVAlign( Qt::Alignment textVAlign );
|
||||
void setSelectionTextLineSpacing( double textLineSpacing );
|
||||
void setSelectionTextColorNode( ColorNode textColorNode );
|
||||
void setSelectionLineWidth( const Distance& lineWidth );
|
||||
void setSelectionLineColorNode( ColorNode lineColorNode );
|
||||
void setSelectionFillColorNode( ColorNode fillColorNode );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Clipboard operations
|
||||
/////////////////////////////////
|
||||
void copySelection();
|
||||
void cutSelection();
|
||||
bool canPaste();
|
||||
void paste();
|
||||
|
||||
/////////////////////////////////
|
||||
// Drawing operations
|
||||
/////////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, bool inEditor = true, merge::Record* record = nullptr ) const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Slots
|
||||
/////////////////////////////////
|
||||
private slots:
|
||||
void onObjectChanged();
|
||||
void onObjectMoved();
|
||||
void onMergeSourceChanged();
|
||||
void onMergeSelectionChanged();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
int mUntitledInstance;
|
||||
bool mModified;
|
||||
QString mFileName;
|
||||
int mCompressionLevel;
|
||||
const Template* mTmplate;
|
||||
const Frame* mFrame;
|
||||
bool mRotate;
|
||||
|
||||
QList<ModelObject*> mObjectList;
|
||||
|
||||
merge::Merge* mMerge;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Model_h
|
||||
@@ -0,0 +1,531 @@
|
||||
/* ModelBarcodeObject.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 "ModelBarcodeObject.h"
|
||||
|
||||
#include "Size.h"
|
||||
|
||||
#include "barcode/Backends.h"
|
||||
|
||||
#include "glbarcode/Factory.h"
|
||||
#include "glbarcode/QtRenderer.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
#include <QTextDocument>
|
||||
#include <QTextBlock>
|
||||
#include <QRegularExpression>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const QColor fillColor = QColor( 224, 224, 224, 255 );
|
||||
const Distance pad = Distance::pt(4);
|
||||
const Distance minW = Distance::pt(18);
|
||||
const Distance minH = Distance::pt(18);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelBarcodeObject::ModelBarcodeObject()
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mBcStyle = barcode::Backends::defaultStyle();
|
||||
mBcTextFlag = mBcStyle.canText();
|
||||
mBcChecksumFlag = mBcStyle.canChecksum();
|
||||
mBcFormatDigits = mBcStyle.preferedN();
|
||||
mBcData = "";
|
||||
mBcColorNode = ColorNode( Qt::black );
|
||||
|
||||
mEditorBarcode = nullptr;
|
||||
mEditorDefaultBarcode = nullptr;
|
||||
|
||||
update(); // Initialize cached editor layouts
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelBarcodeObject::ModelBarcodeObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const barcode::Style& bcStyle,
|
||||
bool bcTextFlag,
|
||||
bool bcChecksumFlag,
|
||||
QString bcData,
|
||||
const ColorNode& bcColorNode,
|
||||
const QMatrix& matrix )
|
||||
: ModelObject( x0, y0, w, h, matrix )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mBcStyle = bcStyle;
|
||||
mBcTextFlag = bcTextFlag;
|
||||
mBcChecksumFlag = bcChecksumFlag;
|
||||
mBcData = bcData;
|
||||
mBcColorNode = bcColorNode;
|
||||
|
||||
mEditorBarcode = nullptr;
|
||||
mEditorDefaultBarcode = nullptr;
|
||||
|
||||
update(); // Initialize cached editor layouts
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelBarcodeObject::ModelBarcodeObject( const ModelBarcodeObject* object )
|
||||
: ModelObject(object)
|
||||
{
|
||||
mBcStyle = object->mBcStyle;
|
||||
mBcTextFlag = object->mBcTextFlag;
|
||||
mBcChecksumFlag = object->mBcChecksumFlag;
|
||||
mBcFormatDigits = object->mBcFormatDigits;
|
||||
mBcData = object->mBcData;
|
||||
mBcColorNode = object->mBcColorNode;
|
||||
|
||||
mEditorBarcode = nullptr;
|
||||
mEditorDefaultBarcode = nullptr;
|
||||
|
||||
update(); // Initialize cached editor layouts
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelBarcodeObject::~ModelBarcodeObject()
|
||||
{
|
||||
delete mOutline;
|
||||
|
||||
foreach( Handle* handle, mHandles )
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
mHandles.clear();
|
||||
|
||||
delete mEditorBarcode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone
|
||||
///
|
||||
ModelBarcodeObject* ModelBarcodeObject::clone() const
|
||||
{
|
||||
return new ModelBarcodeObject( this );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// bcData Property Getter
|
||||
///
|
||||
QString ModelBarcodeObject::bcData() const
|
||||
{
|
||||
return mBcData.toString();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// bcData Property Setter
|
||||
///
|
||||
void ModelBarcodeObject::setBcData( const QString& value )
|
||||
{
|
||||
if ( mBcData.toString() != value )
|
||||
{
|
||||
mBcData = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// bcTextFlag Property Getter
|
||||
///
|
||||
bool ModelBarcodeObject::bcTextFlag() const
|
||||
{
|
||||
return mBcTextFlag;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// bcTextFlag Property Setter
|
||||
///
|
||||
void ModelBarcodeObject::setBcTextFlag( bool value )
|
||||
{
|
||||
if ( mBcTextFlag != value )
|
||||
{
|
||||
mBcTextFlag = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// bcChecksumFlag Property Getter
|
||||
///
|
||||
bool ModelBarcodeObject::bcChecksumFlag() const
|
||||
{
|
||||
return mBcChecksumFlag;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// bcChecksumFlag Property Setter
|
||||
///
|
||||
void ModelBarcodeObject::setBcChecksumFlag( bool value )
|
||||
{
|
||||
if ( mBcChecksumFlag != value )
|
||||
{
|
||||
mBcChecksumFlag = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Barcode Color Node Property Getter
|
||||
///
|
||||
ColorNode ModelBarcodeObject::bcColorNode() const
|
||||
{
|
||||
return mBcColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Barcode Color Node Property Setter
|
||||
///
|
||||
void ModelBarcodeObject::setBcColorNode( const ColorNode& value )
|
||||
{
|
||||
if ( mBcColorNode != value )
|
||||
{
|
||||
mBcColorNode = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Barcode Style Property Getter
|
||||
///
|
||||
barcode::Style ModelBarcodeObject::bcStyle() const
|
||||
{
|
||||
return mBcStyle;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Barcode Style Property Setter
|
||||
///
|
||||
void ModelBarcodeObject::setBcStyle( const barcode::Style& value )
|
||||
{
|
||||
if ( mBcStyle != value )
|
||||
{
|
||||
mBcStyle = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Barcode Format Digits Property Getter
|
||||
///
|
||||
int ModelBarcodeObject::bcFormatDigits() const
|
||||
{
|
||||
return mBcFormatDigits;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Barcode Format Digits Property Setter
|
||||
///
|
||||
void ModelBarcodeObject::setBcFormatDigits( int value )
|
||||
{
|
||||
if ( mBcFormatDigits != value )
|
||||
{
|
||||
mBcFormatDigits = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw shadow of object
|
||||
///
|
||||
void ModelBarcodeObject::drawShadow( QPainter* painter,
|
||||
bool inEditor,
|
||||
merge::Record* record ) const
|
||||
{
|
||||
// Barcodes don't support shadows.
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw object itself
|
||||
///
|
||||
void ModelBarcodeObject::drawObject( QPainter* painter,
|
||||
bool inEditor,
|
||||
merge::Record* record ) const
|
||||
{
|
||||
QColor bcColor = mBcColorNode.color( record );
|
||||
|
||||
if ( inEditor )
|
||||
{
|
||||
drawBcInEditor( painter, bcColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
drawBc( painter, bcColor, record );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Path to test for hover condition
|
||||
///
|
||||
QPainterPath ModelBarcodeObject::hoverPath( double scale ) const
|
||||
{
|
||||
return mHoverPath;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Size updated
|
||||
///
|
||||
void ModelBarcodeObject::sizeUpdated()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Update cached information for editor view
|
||||
///
|
||||
void ModelBarcodeObject::update()
|
||||
{
|
||||
//
|
||||
// Build barcode from data
|
||||
//
|
||||
if ( mEditorBarcode )
|
||||
{
|
||||
delete mEditorBarcode;
|
||||
}
|
||||
mEditorBarcode = glbarcode::Factory::createBarcode( mBcStyle.fullId().toStdString() );
|
||||
if ( !mEditorBarcode )
|
||||
{
|
||||
qWarning() << "Invalid barcode style" << mBcStyle.fullId() << "using \"code39\".";
|
||||
mBcStyle = barcode::Backends::defaultStyle();
|
||||
mEditorBarcode = glbarcode::Factory::createBarcode( mBcStyle.id().toStdString() );
|
||||
}
|
||||
mEditorBarcode->setChecksum(mBcChecksumFlag);
|
||||
mEditorBarcode->setShowText(mBcTextFlag);
|
||||
|
||||
mEditorBarcode->build( mBcData.toStdString(), mW.pt(), mH.pt() );
|
||||
|
||||
//
|
||||
// Build a place holder barcode to display in editor, if cannot display actual barcode
|
||||
//
|
||||
if ( mEditorDefaultBarcode )
|
||||
{
|
||||
delete mEditorDefaultBarcode;
|
||||
}
|
||||
mEditorDefaultBarcode = glbarcode::Factory::createBarcode( mBcStyle.fullId().toStdString() );
|
||||
if ( !mEditorDefaultBarcode )
|
||||
{
|
||||
qWarning() << "Invalid barcode style" << mBcStyle.fullId() << "using \"code39\".";
|
||||
mBcStyle = barcode::Backends::defaultStyle();
|
||||
mEditorDefaultBarcode = glbarcode::Factory::createBarcode( mBcStyle.id().toStdString() );
|
||||
}
|
||||
mEditorDefaultBarcode->setChecksum(mBcChecksumFlag);
|
||||
mEditorDefaultBarcode->setShowText(mBcTextFlag);
|
||||
|
||||
mEditorDefaultBarcode->build( mBcStyle.defaultDigits().toStdString(), mW.pt(), mH.pt() );
|
||||
|
||||
//
|
||||
// Adjust size
|
||||
//
|
||||
if ( mEditorBarcode->isDataValid() )
|
||||
{
|
||||
mW = Distance::pt( mEditorBarcode->width() );
|
||||
mH = Distance::pt( mEditorBarcode->height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
mW = Distance::pt( mEditorDefaultBarcode->width() );
|
||||
mH = Distance::pt( mEditorDefaultBarcode->height() );
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
path.addRect( 0, 0, mW.pt(), mH.pt() );
|
||||
mHoverPath = path;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw barcode in editor from cached information
|
||||
///
|
||||
void ModelBarcodeObject::drawBcInEditor( QPainter* painter, const QColor& color ) const
|
||||
{
|
||||
if ( mBcData.isEmpty() )
|
||||
{
|
||||
drawPlaceHolder( painter, color, tr("No barcode data") );
|
||||
}
|
||||
else if ( mBcData.hasPlaceHolders() )
|
||||
{
|
||||
drawPlaceHolder( painter, color, mBcData.toString() );
|
||||
}
|
||||
else if ( mEditorBarcode->isDataValid() )
|
||||
{
|
||||
painter->setPen( QPen( color ) );
|
||||
glbarcode::QtRenderer renderer(painter);
|
||||
mEditorBarcode->render( renderer );
|
||||
}
|
||||
else
|
||||
{
|
||||
drawPlaceHolder( painter, color, tr("Invalid barcode data") );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw barcode in final printout or preview
|
||||
///
|
||||
void
|
||||
ModelBarcodeObject::drawBc( QPainter* painter,
|
||||
const QColor& color,
|
||||
merge::Record* record ) const
|
||||
{
|
||||
painter->setPen( QPen( color ) );
|
||||
|
||||
glbarcode::Barcode* bc = glbarcode::Factory::createBarcode( mBcStyle.fullId().toStdString() );
|
||||
bc->setChecksum(mBcChecksumFlag);
|
||||
bc->setShowText(mBcTextFlag);
|
||||
|
||||
bc->build( mBcData.toStdString(), mW.pt(), mH.pt() );
|
||||
|
||||
glbarcode::QtRenderer renderer(painter);
|
||||
bc->render( renderer );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw barcode place holder in editor
|
||||
///
|
||||
void
|
||||
ModelBarcodeObject::drawPlaceHolder( QPainter* painter,
|
||||
const QColor& color,
|
||||
const QString& text ) const
|
||||
{
|
||||
QString shortText = text.left( 32 ); // Don't let the text get out of hand
|
||||
|
||||
//
|
||||
// Render box
|
||||
//
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( QBrush( fillColor ) );
|
||||
painter->drawRect( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
|
||||
//
|
||||
// Render default barcode
|
||||
//
|
||||
painter->setPen( QPen( color ) );
|
||||
glbarcode::QtRenderer renderer(painter);
|
||||
mEditorDefaultBarcode->render( renderer );
|
||||
|
||||
//
|
||||
// Determine font size for text
|
||||
//
|
||||
QFont font( "Sans" );
|
||||
font.setPointSizeF( 6 );
|
||||
|
||||
QFontMetricsF fm( font );
|
||||
QRectF textRect = fm.boundingRect( shortText );
|
||||
|
||||
double wPts = (mW - 2*pad).pt();
|
||||
double hPts = (mH - 2*pad).pt();
|
||||
if ( (wPts < textRect.width()) || (hPts < textRect.height()) )
|
||||
{
|
||||
double scaleX = wPts / textRect.width();
|
||||
double scaleY = hPts / textRect.height();
|
||||
font.setPointSizeF( 6 * std::min( scaleX, scaleY ) );
|
||||
}
|
||||
|
||||
//
|
||||
// Render hole for text (font size may have changed above)
|
||||
//
|
||||
fm = QFontMetricsF( font );
|
||||
textRect = fm.boundingRect( shortText );
|
||||
|
||||
QRectF holeRect( (mW.pt() - textRect.width())/2 - pad.pt(),
|
||||
(mH.pt() - textRect.height())/2 - pad.pt(),
|
||||
textRect.width() + 2*pad.pt(),
|
||||
textRect.height() + 2*pad.pt() );
|
||||
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( QBrush( fillColor ) );
|
||||
painter->drawRect( holeRect );
|
||||
|
||||
//
|
||||
// Render text
|
||||
//
|
||||
painter->setFont( font );
|
||||
painter->setPen( QPen( color ) );
|
||||
painter->drawText( QRectF( 0, 0, mW.pt(), mH.pt() ), Qt::AlignCenter, shortText );
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,166 @@
|
||||
/* ModelBarcodeObject.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 model_ModelBarcodeObject_h
|
||||
#define model_ModelBarcodeObject_h
|
||||
|
||||
|
||||
#include "ModelObject.h"
|
||||
|
||||
#include "RawText.h"
|
||||
|
||||
#include "glbarcode/Barcode.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Line Object
|
||||
///
|
||||
class ModelBarcodeObject : public ModelObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
ModelBarcodeObject();
|
||||
|
||||
ModelBarcodeObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const barcode::Style& bcStyle,
|
||||
bool bcTextFlag,
|
||||
bool bcChecksumFlag,
|
||||
QString bcData,
|
||||
const ColorNode& bcColorNode,
|
||||
const QMatrix& matrix = QMatrix() );
|
||||
|
||||
ModelBarcodeObject( const ModelBarcodeObject* object );
|
||||
|
||||
~ModelBarcodeObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
ModelBarcodeObject* clone() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Property Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Barcode Property: bcData
|
||||
//
|
||||
QString bcData() const override;
|
||||
void setBcData( const QString &value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Barcode Property: bcTextFlag
|
||||
//
|
||||
bool bcTextFlag() const override;
|
||||
void setBcTextFlag( bool value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Barcode Property: bcChecksumFlag
|
||||
//
|
||||
bool bcChecksumFlag() const override;
|
||||
void setBcChecksumFlag( bool value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Barcode Property: bcColorNode
|
||||
//
|
||||
ColorNode bcColorNode() const override;
|
||||
void setBcColorNode( const ColorNode &value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Barcode Property: bcStyle
|
||||
//
|
||||
barcode::Style bcStyle() const override;
|
||||
void setBcStyle( const barcode::Style &value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Barcode Property: bcFormatDigits
|
||||
//
|
||||
int bcFormatDigits() const override;
|
||||
void setBcFormatDigits( int value ) override;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Capability Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
QPainterPath hoverPath( double scale ) const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
private:
|
||||
void sizeUpdated() override;
|
||||
void update();
|
||||
|
||||
void drawBcInEditor( QPainter* painter, const QColor& color ) const;
|
||||
void drawBc( QPainter* painter, const QColor& color, merge::Record* record ) const;
|
||||
void drawPlaceHolder( QPainter* painter, const QColor& color, const QString& text ) const;
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
private:
|
||||
barcode::Style mBcStyle;
|
||||
bool mBcTextFlag;
|
||||
bool mBcChecksumFlag;
|
||||
int mBcFormatDigits;
|
||||
RawText mBcData;
|
||||
ColorNode mBcColorNode;
|
||||
|
||||
glbarcode::Barcode* mEditorBarcode;
|
||||
glbarcode::Barcode* mEditorDefaultBarcode;
|
||||
|
||||
QPainterPath mHoverPath;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelBarcodeObject_h
|
||||
@@ -0,0 +1,194 @@
|
||||
/* ModelBoxObject.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "ModelBoxObject.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const double slopPixels = 2;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelBoxObject::ModelBoxObject()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelBoxObject::ModelBoxObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const ColorNode& fillColorNode,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelShapeObject( x0, y0, w, h,
|
||||
lineWidth, lineColorNode, fillColorNode,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelBoxObject::ModelBoxObject( const ModelBoxObject* object )
|
||||
: ModelShapeObject( object )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelBoxObject::~ModelBoxObject()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone
|
||||
///
|
||||
ModelBoxObject* ModelBoxObject::clone() const
|
||||
{
|
||||
return new ModelBoxObject( this );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw shadow of object
|
||||
///
|
||||
void ModelBoxObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QColor lineColor = mLineColorNode.color( record );
|
||||
QColor fillColor = mFillColorNode.color( record );
|
||||
QColor shadowColor = mShadowColorNode.color( record );
|
||||
|
||||
shadowColor.setAlphaF( mShadowOpacity );
|
||||
|
||||
if ( fillColor.alpha() )
|
||||
{
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( shadowColor );
|
||||
|
||||
if ( lineColor.alpha() )
|
||||
{
|
||||
/* Has FILL and OUTLINE: adjust size to account for line width. */
|
||||
painter->drawRect( QRectF( -mLineWidth.pt()/2,
|
||||
-mLineWidth.pt()/2,
|
||||
(mW + mLineWidth).pt(),
|
||||
(mH + mLineWidth).pt() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Has FILL, but no OUTLINE. */
|
||||
painter->drawRect( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( lineColor.alpha() )
|
||||
{
|
||||
/* Has only OUTLINE. */
|
||||
painter->setPen( QPen( shadowColor, mLineWidth.pt() ) );
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
|
||||
painter->drawRect( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw object itself
|
||||
///
|
||||
void ModelBoxObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QColor lineColor = mLineColorNode.color( record );
|
||||
QColor fillColor = mFillColorNode.color( record );
|
||||
|
||||
painter->setPen( QPen( lineColor, mLineWidth.pt() ) );
|
||||
painter->setBrush( fillColor );
|
||||
|
||||
painter->drawRect( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Path to test for hover condition
|
||||
///
|
||||
QPainterPath ModelBoxObject::hoverPath( double scale ) const
|
||||
{
|
||||
double s = 1 / scale;
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
if ( mFillColorNode.color().alpha() && mLineColorNode.color().alpha() )
|
||||
{
|
||||
path.addRect( -mLineWidth.pt()/2, -mLineWidth.pt()/2, (mW+mLineWidth).pt(), (mH+mLineWidth).pt() );
|
||||
}
|
||||
else if ( mFillColorNode.color().alpha() && !(mLineColorNode.color().alpha()) )
|
||||
{
|
||||
path.addRect( 0, 0, mW.pt(), mH.pt() );
|
||||
}
|
||||
else if ( mLineColorNode.color().alpha() )
|
||||
{
|
||||
path.addRect( (-mLineWidth.pt()/2) - s*slopPixels,
|
||||
(-mLineWidth.pt()/2) - s*slopPixels,
|
||||
(mW + mLineWidth).pt() + s*2*slopPixels,
|
||||
(mH + mLineWidth).pt() + s*2*slopPixels );
|
||||
path.closeSubpath();
|
||||
path.addRect( mLineWidth.pt()/2 + s*slopPixels,
|
||||
mLineWidth.pt()/2 + s*slopPixels,
|
||||
(mW - mLineWidth).pt() - s*2*slopPixels,
|
||||
(mH - mLineWidth).pt() - s*2*slopPixels );
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,82 @@
|
||||
/* ModelBoxObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelBoxObject_h
|
||||
#define model_ModelBoxObject_h
|
||||
|
||||
|
||||
#include "ModelShapeObject.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Box Object
|
||||
///
|
||||
class ModelBoxObject : public ModelShapeObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
ModelBoxObject();
|
||||
|
||||
ModelBoxObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const ColorNode& fillColorNode,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelBoxObject( const ModelBoxObject* object );
|
||||
|
||||
~ModelBoxObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
ModelBoxObject* clone() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
QPainterPath hoverPath( double scale ) const override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelBoxObject_h
|
||||
@@ -0,0 +1,194 @@
|
||||
/* ModelEllipseObject.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "ModelEllipseObject.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const double slopPixels = 2;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelEllipseObject::ModelEllipseObject()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelEllipseObject::ModelEllipseObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const ColorNode& fillColorNode,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelShapeObject( x0, y0, w, h,
|
||||
lineWidth, lineColorNode, fillColorNode,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelEllipseObject::ModelEllipseObject( const ModelEllipseObject* object )
|
||||
: ModelShapeObject( object )
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelEllipseObject::~ModelEllipseObject()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone
|
||||
///
|
||||
ModelEllipseObject* ModelEllipseObject::clone() const
|
||||
{
|
||||
return new ModelEllipseObject( this );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw shadow of object
|
||||
///
|
||||
void ModelEllipseObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QColor lineColor = mLineColorNode.color( record );
|
||||
QColor fillColor = mFillColorNode.color( record );
|
||||
QColor shadowColor = mShadowColorNode.color( record );
|
||||
|
||||
shadowColor.setAlphaF( mShadowOpacity );
|
||||
|
||||
if ( fillColor.alpha() )
|
||||
{
|
||||
painter->setPen( Qt::NoPen );
|
||||
painter->setBrush( shadowColor );
|
||||
|
||||
if ( lineColor.alpha() )
|
||||
{
|
||||
/* Has FILL and OUTLINE: adjust size to account for line width. */
|
||||
painter->drawEllipse( QRectF( -mLineWidth.pt()/2,
|
||||
-mLineWidth.pt()/2,
|
||||
(mW + mLineWidth).pt(),
|
||||
(mH + mLineWidth).pt() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Has FILL, but no OUTLINE. */
|
||||
painter->drawEllipse( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( lineColor.alpha() )
|
||||
{
|
||||
/* Has only OUTLINE. */
|
||||
painter->setPen( QPen( shadowColor, mLineWidth.pt() ) );
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
|
||||
painter->drawEllipse( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw object itself
|
||||
///
|
||||
void ModelEllipseObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QColor lineColor = mLineColorNode.color( record );
|
||||
QColor fillColor = mFillColorNode.color( record );
|
||||
|
||||
painter->setPen( QPen( lineColor, mLineWidth.pt() ) );
|
||||
painter->setBrush( fillColor );
|
||||
|
||||
painter->drawEllipse( QRectF( 0, 0, mW.pt(), mH.pt() ) );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Path to test for hover condition
|
||||
///
|
||||
QPainterPath ModelEllipseObject::hoverPath( double scale ) const
|
||||
{
|
||||
double s = 1 / scale;
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
if ( mFillColorNode.color().alpha() && mLineColorNode.color().alpha() )
|
||||
{
|
||||
path.addEllipse( -mLineWidth.pt()/2, -mLineWidth.pt()/2, (mW+mLineWidth).pt(), (mH+mLineWidth).pt() );
|
||||
}
|
||||
else if ( mFillColorNode.color().alpha() && !(mLineColorNode.color().alpha()) )
|
||||
{
|
||||
path.addEllipse( 0, 0, mW.pt(), mH.pt() );
|
||||
}
|
||||
else if ( mLineColorNode.color().alpha() )
|
||||
{
|
||||
path.addEllipse( (-mLineWidth.pt()/2) - s*slopPixels,
|
||||
(-mLineWidth.pt()/2) - s*slopPixels,
|
||||
(mW + mLineWidth).pt() + s*2*slopPixels,
|
||||
(mH + mLineWidth).pt() + s*2*slopPixels );
|
||||
path.closeSubpath();
|
||||
path.addEllipse( mLineWidth.pt()/2 + s*slopPixels,
|
||||
mLineWidth.pt()/2 + s*slopPixels,
|
||||
(mW - mLineWidth).pt() - s*2*slopPixels,
|
||||
(mH - mLineWidth).pt() - s*2*slopPixels );
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,82 @@
|
||||
/* ModelEllipseObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelEllipseObject_h
|
||||
#define model_ModelEllipseObject_h
|
||||
|
||||
|
||||
#include "ModelShapeObject.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Ellipse Object
|
||||
///
|
||||
class ModelEllipseObject : public ModelShapeObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
ModelEllipseObject();
|
||||
|
||||
ModelEllipseObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const ColorNode& fillColorNode,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelEllipseObject( const ModelEllipseObject* object );
|
||||
|
||||
~ModelEllipseObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
ModelEllipseObject* clone() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
QPainterPath hoverPath( double scale ) const override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelEllipseObject_h
|
||||
@@ -0,0 +1,566 @@
|
||||
/* ModelImageObject.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "ModelImageObject.h"
|
||||
|
||||
#include "Size.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QFileInfo>
|
||||
#include <QImage>
|
||||
#include <QPen>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Static data
|
||||
///
|
||||
QImage* ModelImageObject::smDefaultImage = nullptr;
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelImageObject::ModelImageObject() : mImage(nullptr), mSvgRenderer(nullptr)
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
if ( smDefaultImage == nullptr )
|
||||
{
|
||||
smDefaultImage = new QImage( ":images/checkerboard.png" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelImageObject::ModelImageObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const TextNode& filenameNode,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelObject( x0, y0, w, h,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
if ( smDefaultImage == nullptr )
|
||||
{
|
||||
smDefaultImage = new QImage( ":images/checkerboard.png" );
|
||||
}
|
||||
|
||||
mFilenameNode = filenameNode;
|
||||
|
||||
mImage = nullptr;
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelImageObject::ModelImageObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QString& filename,
|
||||
const QImage& image,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelObject( x0, y0, w, h,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
if ( smDefaultImage == nullptr )
|
||||
{
|
||||
smDefaultImage = new QImage( ":images/checkerboard.png" );
|
||||
}
|
||||
|
||||
mImage = new QImage(image);
|
||||
mFilenameNode = TextNode( false, filename );
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelImageObject::ModelImageObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QString& filename,
|
||||
const QByteArray& svg,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelObject( x0, y0, w, h,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
if ( smDefaultImage == nullptr )
|
||||
{
|
||||
smDefaultImage = new QImage( ":images/checkerboard.png" );
|
||||
}
|
||||
|
||||
mSvg = svg;
|
||||
mSvgRenderer = new QSvgRenderer( mSvg );
|
||||
mFilenameNode = TextNode( false, filename );
|
||||
mImage = nullptr;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelImageObject::ModelImageObject( const ModelImageObject* object ) : ModelObject(object)
|
||||
{
|
||||
mFilenameNode = object->mFilenameNode;
|
||||
if ( object->mImage )
|
||||
{
|
||||
mImage = new QImage( *object->mImage );
|
||||
}
|
||||
else
|
||||
{
|
||||
mImage = nullptr;
|
||||
}
|
||||
if ( object->mSvgRenderer )
|
||||
{
|
||||
mSvgRenderer = new QSvgRenderer( object->mSvg );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
mSvg = object->mSvg;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelImageObject::~ModelImageObject()
|
||||
{
|
||||
delete mOutline;
|
||||
|
||||
foreach( Handle* handle, mHandles )
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
mHandles.clear();
|
||||
|
||||
if ( mImage )
|
||||
{
|
||||
delete mImage;
|
||||
}
|
||||
if ( mSvgRenderer )
|
||||
{
|
||||
delete mSvgRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone
|
||||
///
|
||||
ModelImageObject* ModelImageObject::clone() const
|
||||
{
|
||||
return new ModelImageObject( this );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image filenameNode Property Getter
|
||||
///
|
||||
TextNode ModelImageObject::filenameNode() const
|
||||
{
|
||||
return mFilenameNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image filenameNode Property Setter
|
||||
///
|
||||
void ModelImageObject::setFilenameNode( const TextNode& value )
|
||||
{
|
||||
if ( mFilenameNode != value )
|
||||
{
|
||||
mFilenameNode = value;
|
||||
loadImage();
|
||||
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image image Property Getter
|
||||
///
|
||||
const QImage* ModelImageObject::image() const
|
||||
{
|
||||
return mImage;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image Property Setter
|
||||
///
|
||||
void ModelImageObject::setImage( const QImage& value )
|
||||
{
|
||||
if ( !value.isNull() )
|
||||
{
|
||||
if ( mImage )
|
||||
{
|
||||
delete mImage;
|
||||
mImage = nullptr;
|
||||
}
|
||||
if ( mSvgRenderer )
|
||||
{
|
||||
delete mSvgRenderer;
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
|
||||
mImage = new QImage(value);
|
||||
quint16 cs = qChecksum( (const char*)mImage->constBits(), mImage->byteCount() );
|
||||
mFilenameNode = TextNode( false, QString("%image_%1%").arg( cs ) );
|
||||
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image Property Setter
|
||||
///
|
||||
void ModelImageObject::setImage( const QString& name, const QImage& value )
|
||||
{
|
||||
if ( !value.isNull() )
|
||||
{
|
||||
if ( mImage )
|
||||
{
|
||||
delete mImage;
|
||||
mImage = nullptr;
|
||||
}
|
||||
if ( mSvgRenderer )
|
||||
{
|
||||
delete mSvgRenderer;
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
|
||||
mImage = new QImage(value);
|
||||
mFilenameNode = TextNode( false, name );
|
||||
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image svg Property Getter
|
||||
///
|
||||
QByteArray ModelImageObject::svg() const
|
||||
{
|
||||
return mSvg;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Image svgSource Property Setter
|
||||
///
|
||||
void ModelImageObject::setSvg( const QString& name, const QByteArray& value )
|
||||
{
|
||||
if ( !value.isEmpty() )
|
||||
{
|
||||
if ( mImage )
|
||||
{
|
||||
delete mImage;
|
||||
mImage = nullptr;
|
||||
}
|
||||
if ( mSvgRenderer )
|
||||
{
|
||||
delete mSvgRenderer;
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
|
||||
mSvg = value;
|
||||
mSvgRenderer = new QSvgRenderer( mSvg );
|
||||
mFilenameNode = TextNode( false, name );
|
||||
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// naturalSize Property Getter (assumes 72 DPI, i.e. 1pixel == 1pt)
|
||||
///
|
||||
Size ModelImageObject::naturalSize() const
|
||||
{
|
||||
Size size( Distance::pt(72), Distance::pt(72) );
|
||||
|
||||
if ( mImage )
|
||||
{
|
||||
QSize qsize = mImage->size();
|
||||
size.setW( Distance::pt( qsize.width() ) );
|
||||
size.setH( Distance::pt( qsize.height() ) );
|
||||
}
|
||||
else if ( mSvgRenderer )
|
||||
{
|
||||
QSize qsize = mSvgRenderer->defaultSize();
|
||||
size.setW( Distance::pt( qsize.width() ) );
|
||||
size.setH( Distance::pt( qsize.height() ) );
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw shadow of object
|
||||
///
|
||||
void ModelImageObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QRectF destRect( 0, 0, mW.pt(), mH.pt() );
|
||||
|
||||
QColor shadowColor = mShadowColorNode.color( record );
|
||||
shadowColor.setAlphaF( mShadowOpacity );
|
||||
|
||||
if ( mImage && mImage->hasAlphaChannel() && (mImage->depth() == 32) )
|
||||
{
|
||||
QImage* shadowImage = createShadowImage( shadowColor );
|
||||
painter->drawImage( destRect, *shadowImage );
|
||||
delete shadowImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( mImage || inEditor )
|
||||
{
|
||||
painter->setBrush( shadowColor );
|
||||
painter->setPen( QPen( Qt::NoPen ) );
|
||||
|
||||
painter->drawRect( destRect );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw object itself
|
||||
///
|
||||
void ModelImageObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QRectF destRect( 0, 0, mW.pt(), mH.pt() );
|
||||
|
||||
if ( inEditor && (mFilenameNode.isField() || (!mImage && !mSvgRenderer) ) )
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint( QPainter::SmoothPixmapTransform, false );
|
||||
painter->drawImage( destRect, *smDefaultImage );
|
||||
painter->restore();
|
||||
}
|
||||
else if ( mImage )
|
||||
{
|
||||
painter->drawImage( destRect, *mImage );
|
||||
}
|
||||
else if ( mSvgRenderer )
|
||||
{
|
||||
mSvgRenderer->render( painter, destRect );
|
||||
}
|
||||
else if ( mFilenameNode.isField() )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Path to test for hover condition
|
||||
///
|
||||
QPainterPath ModelImageObject::hoverPath( double scale ) const
|
||||
{
|
||||
QPainterPath path;
|
||||
path.addRect( 0, 0, mW.pt(), mH.pt() );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Load image
|
||||
///
|
||||
void ModelImageObject::loadImage()
|
||||
{
|
||||
if ( mImage )
|
||||
{
|
||||
delete mImage;
|
||||
mImage = nullptr;
|
||||
}
|
||||
if ( mSvgRenderer )
|
||||
{
|
||||
delete mSvgRenderer;
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
|
||||
if ( !mFilenameNode.isField() )
|
||||
{
|
||||
QString filename = mFilenameNode.data();
|
||||
QFileInfo fileInfo( filename );
|
||||
|
||||
if ( fileInfo.isReadable() )
|
||||
{
|
||||
if ( (fileInfo.suffix() == "svg") || (fileInfo.suffix() == "SVG") )
|
||||
{
|
||||
QFile file( filename );
|
||||
if ( file.open( QFile::ReadOnly ) )
|
||||
{
|
||||
mSvg = file.readAll();
|
||||
file.close();
|
||||
mSvgRenderer = new QSvgRenderer( mSvg );
|
||||
if ( !mSvgRenderer->isValid() )
|
||||
{
|
||||
mSvgRenderer = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust size based on aspect ratio of SVG image
|
||||
QRectF rect = mSvgRenderer->viewBoxF();
|
||||
double aspectRatio = rect.height() / rect.width();
|
||||
if ( mH > mW*aspectRatio )
|
||||
{
|
||||
mH = mW*aspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
mW = mH/aspectRatio;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mImage = new QImage( filename );
|
||||
if ( mImage->isNull() )
|
||||
{
|
||||
mImage = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust size based on aspect ratio of image
|
||||
double imageW = mImage->width();
|
||||
double imageH = mImage->height();
|
||||
double aspectRatio = imageH / imageW;
|
||||
if ( mH > mW*aspectRatio )
|
||||
{
|
||||
mH = mW*aspectRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
mW = mH/aspectRatio;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Create shadow image
|
||||
///
|
||||
QImage* ModelImageObject::createShadowImage( const QColor& color ) const
|
||||
{
|
||||
int r = color.red();
|
||||
int g = color.green();
|
||||
int b = color.blue();
|
||||
int a = color.alpha();
|
||||
|
||||
QImage* shadow = new QImage( *mImage );
|
||||
for ( int iy = 0; iy < shadow->height(); iy++ )
|
||||
{
|
||||
QRgb* scanLine = (QRgb*)shadow->scanLine( iy );
|
||||
|
||||
for ( int ix = 0; ix < shadow->width(); ix++ )
|
||||
{
|
||||
scanLine[ix] = qRgba( r, g, b, (a*qAlpha(scanLine[ix]))/255 );
|
||||
}
|
||||
}
|
||||
|
||||
return shadow;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,161 @@
|
||||
/* ModelImageObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelImageObject_h
|
||||
#define model_ModelImageObject_h
|
||||
|
||||
|
||||
#include "ModelObject.h"
|
||||
|
||||
#include <QSvgRenderer>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Image Object
|
||||
///
|
||||
class ModelImageObject : public ModelObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
ModelImageObject();
|
||||
|
||||
ModelImageObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const TextNode& filenameNode,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelImageObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QString& filename,
|
||||
const QImage& image,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelImageObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QString& filename,
|
||||
const QByteArray& svg,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelImageObject( const ModelImageObject* object );
|
||||
|
||||
~ModelImageObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
ModelImageObject* clone() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Property Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Image Property: filenameNode
|
||||
//
|
||||
TextNode filenameNode() const override;
|
||||
void setFilenameNode( const TextNode& value ) override;
|
||||
|
||||
//
|
||||
// Image Property: image
|
||||
//
|
||||
const QImage* image() const override;
|
||||
void setImage( const QImage& value ) override;
|
||||
void setImage( const QString& name, const QImage& value ) override;
|
||||
|
||||
//
|
||||
// Image Property: svg
|
||||
//
|
||||
QByteArray svg() const override;
|
||||
void setSvg( const QString& name, const QByteArray& value ) override;
|
||||
|
||||
//
|
||||
// Property: naturalSize
|
||||
//
|
||||
Size naturalSize() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Capability Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
QPainterPath hoverPath( double scale ) const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////
|
||||
void loadImage();
|
||||
QImage* createShadowImage( const QColor& color ) const;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
TextNode mFilenameNode;
|
||||
QImage* mImage;
|
||||
QSvgRenderer* mSvgRenderer;
|
||||
QByteArray mSvg;
|
||||
|
||||
static QImage* smDefaultImage;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelImageObject_h
|
||||
@@ -0,0 +1,243 @@
|
||||
/* ModelLineObject.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "ModelLineObject.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const double slopPixels = 2;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelLineObject::ModelLineObject()
|
||||
{
|
||||
mOutline = nullptr;
|
||||
|
||||
mHandles << new HandleP1( this );
|
||||
mHandles << new HandleP2( this );
|
||||
|
||||
mLineWidth = 1.0;
|
||||
mLineColorNode = ColorNode( QColor( 0, 0, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelLineObject::ModelLineObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& dx,
|
||||
const Distance& dy,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelObject( x0, y0, dx, dy,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mLineWidth = lineWidth;
|
||||
mLineColorNode = lineColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelLineObject::ModelLineObject( const ModelLineObject* object )
|
||||
: ModelObject(object)
|
||||
{
|
||||
mLineWidth = object->mLineWidth;
|
||||
mLineColorNode = object->mLineColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelLineObject::~ModelLineObject()
|
||||
{
|
||||
foreach( Handle* handle, mHandles )
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
mHandles.clear();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone
|
||||
///
|
||||
ModelLineObject* ModelLineObject::clone() const
|
||||
{
|
||||
return new ModelLineObject( this );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Width Property Getter
|
||||
///
|
||||
Distance ModelLineObject::lineWidth() const
|
||||
{
|
||||
return mLineWidth;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Width Property Setter
|
||||
///
|
||||
void ModelLineObject::setLineWidth( const Distance& value )
|
||||
{
|
||||
if ( mLineWidth != value )
|
||||
{
|
||||
mLineWidth = value;
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Color Node Property Getter
|
||||
///
|
||||
ColorNode ModelLineObject::lineColorNode() const
|
||||
{
|
||||
return mLineColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Color Node Property Setter
|
||||
///
|
||||
void ModelLineObject::setLineColorNode( const ColorNode& value )
|
||||
{
|
||||
if ( mLineColorNode != value )
|
||||
{
|
||||
mLineColorNode = value;
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Can Line Color Capability Implementation
|
||||
///
|
||||
bool ModelLineObject::canLineColor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Can Line Width Capability Implementation
|
||||
///
|
||||
bool ModelLineObject::canLineWidth()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw shadow of object
|
||||
///
|
||||
void ModelLineObject::drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QColor lineColor = mLineColorNode.color( record );
|
||||
QColor shadowColor = mShadowColorNode.color( record );
|
||||
|
||||
shadowColor.setAlphaF( mShadowOpacity );
|
||||
|
||||
if ( lineColor.alpha() )
|
||||
{
|
||||
painter->setPen( QPen( shadowColor, mLineWidth.pt() ) );
|
||||
painter->drawLine( 0, 0, mW.pt(), mH.pt() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw object itself
|
||||
///
|
||||
void ModelLineObject::drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const
|
||||
{
|
||||
QColor lineColor = mLineColorNode.color( record );
|
||||
|
||||
painter->setPen( QPen( lineColor, mLineWidth.pt() ) );
|
||||
painter->drawLine( 0, 0, mW.pt(), mH.pt() );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Path to test for hover condition
|
||||
///
|
||||
QPainterPath ModelLineObject::hoverPath( double scale ) const
|
||||
{
|
||||
QPainterPath path;
|
||||
|
||||
if ( mLineColorNode.color().alpha() )
|
||||
{
|
||||
//
|
||||
// Build a thin rectangle representing line
|
||||
//
|
||||
double rPts = mLineWidth.pt()/2 + slopPixels / scale;
|
||||
|
||||
double lengthPts = sqrt( mW.pt()*mW.pt() + mH.pt()*mH.pt() );
|
||||
double dx = mH.pt() / lengthPts; // horizontal pitch of perpendicular line
|
||||
double dy = mW.pt() / lengthPts; // vertical pitch of perpendicular line
|
||||
|
||||
path.moveTo( rPts*dx, - rPts*dy );
|
||||
path.lineTo( mW.pt() + rPts*dx, mH.pt() - rPts*dy );
|
||||
path.lineTo( mW.pt() - rPts*dx, mH.pt() + rPts*dy );
|
||||
path.lineTo( - rPts*dx, rPts*dy );
|
||||
|
||||
path.closeSubpath();
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,115 @@
|
||||
/* ModelLineObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelLineObject_h
|
||||
#define model_ModelLineObject_h
|
||||
|
||||
|
||||
#include "ModelObject.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Line Object
|
||||
///
|
||||
class ModelLineObject : public ModelObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
ModelLineObject();
|
||||
|
||||
ModelLineObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelLineObject( const ModelLineObject* object );
|
||||
|
||||
~ModelLineObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
ModelLineObject* clone() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Property Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Line Property: lineWidth
|
||||
//
|
||||
Distance lineWidth() const override;
|
||||
void setLineWidth( const Distance& value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Line Property: lineColorNode
|
||||
//
|
||||
ColorNode lineColorNode() const override;
|
||||
void setLineColorNode( const ColorNode& value ) override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Capability Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual bool canLineColor();
|
||||
virtual bool canLineWidth();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
QPainterPath hoverPath( double scale ) const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
Distance mLineWidth;
|
||||
ColorNode mLineColorNode;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelLineObject_h
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,436 @@
|
||||
/* ModelObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelObject_h
|
||||
#define model_ModelObject_h
|
||||
|
||||
|
||||
#include "ColorNode.h"
|
||||
#include "Distance.h"
|
||||
#include "Handles.h"
|
||||
#include "Outline.h"
|
||||
#include "TextNode.h"
|
||||
|
||||
#include "barcode/Style.h"
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QFont>
|
||||
#include <QMatrix>
|
||||
#include <QPainter>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward References
|
||||
class Region;
|
||||
class Size;
|
||||
|
||||
|
||||
///
|
||||
/// Label Model Object Base Class
|
||||
///
|
||||
class ModelObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
ModelObject();
|
||||
|
||||
ModelObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelObject( const ModelObject* object );
|
||||
|
||||
public:
|
||||
~ModelObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
virtual ModelObject* clone() const = 0;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Signals
|
||||
///////////////////////////////////////////////////////////////
|
||||
signals:
|
||||
void moved();
|
||||
void changed();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Common Properties
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// ID Property.
|
||||
//
|
||||
int id() const;
|
||||
|
||||
//
|
||||
// Selected Property.
|
||||
//
|
||||
bool isSelected() const;
|
||||
void select( bool value = true );
|
||||
void unselect();
|
||||
|
||||
|
||||
//
|
||||
// x0 Property ( x coordinate of origin )
|
||||
//
|
||||
Distance x0() const;
|
||||
void setX0( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// y0 Property ( y coordinate of origin )
|
||||
//
|
||||
Distance y0() const;
|
||||
void setY0( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// w Property ( width of bounding box )
|
||||
//
|
||||
Distance w() const;
|
||||
void setW( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// h Property ( height of bounding box )
|
||||
//
|
||||
Distance h() const;
|
||||
void setH( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// Transformation Matrix Property
|
||||
//
|
||||
QMatrix matrix() const;
|
||||
void setMatrix( const QMatrix& value );
|
||||
|
||||
|
||||
//
|
||||
// Shadow State Property
|
||||
//
|
||||
bool shadow() const;
|
||||
void setShadow( bool value );
|
||||
|
||||
|
||||
//
|
||||
// Shadow x Offset Property
|
||||
//
|
||||
Distance shadowX() const;
|
||||
void setShadowX( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// Shadow y Offset Property
|
||||
//
|
||||
Distance shadowY() const;
|
||||
void setShadowY( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// Shadow opacity Property
|
||||
//
|
||||
double shadowOpacity() const;
|
||||
void setShadowOpacity( double value );
|
||||
|
||||
|
||||
//
|
||||
// Shadow Color Property
|
||||
//
|
||||
ColorNode shadowColorNode() const;
|
||||
void setShadowColorNode( const ColorNode& value );
|
||||
|
||||
|
||||
//
|
||||
// Natural Size Property (read-only)
|
||||
//
|
||||
virtual Size naturalSize() const;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Text Properties Virtual Interface
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Virtual Text Property: text
|
||||
//
|
||||
virtual QString text() const;
|
||||
virtual void setText( const QString &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: fontFamily
|
||||
//
|
||||
virtual QString fontFamily() const;
|
||||
virtual void setFontFamily( const QString &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: fontSize
|
||||
//
|
||||
virtual double fontSize() const;
|
||||
virtual void setFontSize( double value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: fontWeight
|
||||
//
|
||||
virtual QFont::Weight fontWeight() const;
|
||||
virtual void setFontWeight( QFont::Weight value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: fontItalicFlag
|
||||
//
|
||||
virtual bool fontItalicFlag() const;
|
||||
virtual void setFontItalicFlag( bool value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: fontUnderlineFlag
|
||||
//
|
||||
virtual bool fontUnderlineFlag() const;
|
||||
virtual void setFontUnderlineFlag( bool value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: textColorNode
|
||||
//
|
||||
virtual ColorNode textColorNode() const;
|
||||
virtual void setTextColorNode( const ColorNode &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: textHAlign
|
||||
//
|
||||
virtual Qt::Alignment textHAlign() const;
|
||||
virtual void setTextHAlign( Qt::Alignment value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: textVAlign
|
||||
//
|
||||
virtual Qt::Alignment textVAlign() const;
|
||||
virtual void setTextVAlign( Qt::Alignment value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Text Property: textLineSpacing
|
||||
//
|
||||
virtual double textLineSpacing() const;
|
||||
virtual void setTextLineSpacing( double value );
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Image Properties Virtual Interface
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Virtual Image Property: filenameNode
|
||||
//
|
||||
virtual TextNode filenameNode() const;
|
||||
virtual void setFilenameNode( const TextNode &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Image Property: image
|
||||
//
|
||||
virtual const QImage* image() const;
|
||||
virtual void setImage( const QImage& value );
|
||||
virtual void setImage( const QString& name, const QImage& value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Image Property: svg
|
||||
//
|
||||
virtual QByteArray svg() const;
|
||||
virtual void setSvg( const QString& name, const QByteArray& value );
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Shape Properties Virtual Interface
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Virtual Shape Property: lineWidth
|
||||
//
|
||||
virtual Distance lineWidth() const;
|
||||
virtual void setLineWidth( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Shape Property: lineColorNode
|
||||
//
|
||||
virtual ColorNode lineColorNode() const;
|
||||
virtual void setLineColorNode( const ColorNode &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Shape Property: fillColorNode
|
||||
//
|
||||
virtual ColorNode fillColorNode() const;
|
||||
virtual void setFillColorNode( const ColorNode &value );
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Barcode Properties Virtual Interface
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Virtual Barcode Property: bcData
|
||||
//
|
||||
virtual QString bcData() const;
|
||||
virtual void setBcData( const QString& value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Barcode Property: bcTextFlag
|
||||
//
|
||||
virtual bool bcTextFlag() const;
|
||||
virtual void setBcTextFlag( bool value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Barcode Property: bcChecksumFlag
|
||||
//
|
||||
virtual bool bcChecksumFlag() const;
|
||||
virtual void setBcChecksumFlag( bool value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Barcode Property: bcColorNode
|
||||
//
|
||||
virtual ColorNode bcColorNode() const;
|
||||
virtual void setBcColorNode( const ColorNode &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Barcode Property: bcStyle
|
||||
//
|
||||
virtual barcode::Style bcStyle() const;
|
||||
virtual void setBcStyle( const barcode::Style &value );
|
||||
|
||||
|
||||
//
|
||||
// Virtual Barcode Property: bcFormatDigits
|
||||
//
|
||||
virtual int bcFormatDigits() const;
|
||||
virtual void setBcFormatDigits( int value );
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Capabilities (Overridden by concrete classes.)
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual bool canText() const;
|
||||
virtual bool canFill() const;
|
||||
virtual bool canLineColor() const;
|
||||
virtual bool canLineWidth() const;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Position and Size methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
void setPosition( const Distance& x0, const Distance& y0 );
|
||||
void setPositionRelative( const Distance& dx, const Distance& dy );
|
||||
Size size() const;
|
||||
void setSize( const Distance& w, const Distance& h );
|
||||
void setSize( const Size& size );
|
||||
void setSizeHonorAspect( const Distance& w, const Distance& h );
|
||||
void setWHonorAspect( const Distance& w );
|
||||
void setHHonorAspect( const Distance& h );
|
||||
Region getExtent();
|
||||
void rotate( double thetaDegs );
|
||||
void flipHoriz();
|
||||
void flipVert();
|
||||
bool isLocatedAt( double scale, const Distance& x, const Distance& y ) const;
|
||||
Handle* handleAt( double scale, const Distance& x, const Distance& y ) const;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter, bool inEditor, merge::Record* record ) const;
|
||||
void drawSelectionHighlight( QPainter* painter, double scale ) const;
|
||||
|
||||
protected:
|
||||
virtual void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const = 0;
|
||||
virtual void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const = 0;
|
||||
virtual QPainterPath hoverPath( double scale ) const = 0;
|
||||
|
||||
virtual void sizeUpdated();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Protected Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
bool mSelectedFlag;
|
||||
|
||||
Distance mX0;
|
||||
Distance mY0;
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
|
||||
bool mShadowState;
|
||||
Distance mShadowX;
|
||||
Distance mShadowY;
|
||||
double mShadowOpacity;
|
||||
ColorNode mShadowColorNode;
|
||||
|
||||
QList<Handle*> mHandles;
|
||||
Outline* mOutline;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
private:
|
||||
static int msNextId;
|
||||
int mId;
|
||||
|
||||
QMatrix mMatrix;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelObject_h
|
||||
@@ -0,0 +1,207 @@
|
||||
/* ModelShapeObject.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "ModelShapeObject.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelShapeObject::ModelShapeObject()
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mLineWidth = 1.0;
|
||||
mLineColorNode = ColorNode( QColor( 0, 0, 0 ) );
|
||||
mFillColorNode = ColorNode( QColor( 0, 255, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelShapeObject::ModelShapeObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const ColorNode& fillColorNode,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelObject( x0, y0, w, h,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mLineWidth = lineWidth;
|
||||
mLineColorNode = lineColorNode;
|
||||
mFillColorNode = fillColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelShapeObject::ModelShapeObject( const ModelShapeObject* object ) : ModelObject(object)
|
||||
{
|
||||
mLineWidth = object->mLineWidth;
|
||||
mLineColorNode = object->mLineColorNode;
|
||||
mFillColorNode = object->mFillColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelShapeObject::~ModelShapeObject()
|
||||
{
|
||||
delete mOutline;
|
||||
|
||||
foreach( Handle* handle, mHandles )
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
mHandles.clear();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Width Property Getter
|
||||
///
|
||||
Distance ModelShapeObject::lineWidth() const
|
||||
{
|
||||
return mLineWidth;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Width Property Setter
|
||||
///
|
||||
void ModelShapeObject::setLineWidth( const Distance& value )
|
||||
{
|
||||
if ( mLineWidth != value )
|
||||
{
|
||||
mLineWidth = value;
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Color Node Property Getter
|
||||
///
|
||||
ColorNode ModelShapeObject::lineColorNode() const
|
||||
{
|
||||
return mLineColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Line Color Node Property Setter
|
||||
///
|
||||
void ModelShapeObject::setLineColorNode( const ColorNode& value )
|
||||
{
|
||||
if ( mLineColorNode != value )
|
||||
{
|
||||
mLineColorNode = value;
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Fill Color Node Property Getter
|
||||
///
|
||||
ColorNode ModelShapeObject::fillColorNode() const
|
||||
{
|
||||
return mFillColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Fill Color Node Property Setter
|
||||
///
|
||||
void ModelShapeObject::setFillColorNode( const ColorNode& value )
|
||||
{
|
||||
if ( mFillColorNode != value )
|
||||
{
|
||||
mFillColorNode = value;
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Can Fill Capability Implementation
|
||||
///
|
||||
bool ModelShapeObject::canFill()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Can Line Color Capability Implementation
|
||||
///
|
||||
bool ModelShapeObject::canLineColor()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Can Line Width Capability Implementation
|
||||
///
|
||||
bool ModelShapeObject::canLineWidth()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,110 @@
|
||||
/* ModelShapeObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelShapeObject_h
|
||||
#define model_ModelShapeObject_h
|
||||
|
||||
|
||||
#include "ModelObject.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Shape Object (Box or Ellipse)
|
||||
///
|
||||
class ModelShapeObject : public ModelObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
ModelShapeObject();
|
||||
|
||||
ModelShapeObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const Distance& lineWidth,
|
||||
const ColorNode& lineColorNode,
|
||||
const ColorNode& fillColorNode,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode );
|
||||
|
||||
ModelShapeObject( const ModelShapeObject* object );
|
||||
public:
|
||||
~ModelShapeObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Property Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Shape Property: lineWidth
|
||||
//
|
||||
Distance lineWidth() const override;
|
||||
void setLineWidth( const Distance& value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Shape Property: lineColorNode
|
||||
//
|
||||
ColorNode lineColorNode() const override;
|
||||
void setLineColorNode( const ColorNode& value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Shape Property: fillColorNode
|
||||
//
|
||||
ColorNode fillColorNode() const override;
|
||||
void setFillColorNode( const ColorNode& value ) override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Capability Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual bool canFill();
|
||||
virtual bool canLineColor();
|
||||
virtual bool canLineWidth();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
Distance mLineWidth;
|
||||
ColorNode mLineColorNode;
|
||||
ColorNode mFillColorNode;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelShapeObject_h
|
||||
@@ -0,0 +1,720 @@
|
||||
/* ModelTextObject.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "ModelTextObject.h"
|
||||
|
||||
#include "Size.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
#include <QTextDocument>
|
||||
#include <QTextBlock>
|
||||
#include <QRegularExpression>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const double marginPts = 3;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelTextObject::ModelTextObject()
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mText = "";
|
||||
mFontFamily = "Sans";
|
||||
mFontSize = 10;
|
||||
mFontWeight = QFont::Normal;
|
||||
mFontItalicFlag = false;
|
||||
mFontUnderlineFlag = false;
|
||||
mTextColorNode = ColorNode( QColor( 0, 0, 0 ) );
|
||||
mTextHAlign = Qt::AlignLeft;
|
||||
mTextVAlign = Qt::AlignTop;
|
||||
mTextLineSpacing = 1;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
ModelTextObject::ModelTextObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QString& text,
|
||||
const QString& fontFamily,
|
||||
double fontSize,
|
||||
QFont::Weight fontWeight,
|
||||
bool fontItalicFlag,
|
||||
bool fontUnderlineFlag,
|
||||
ColorNode textColorNode,
|
||||
Qt::Alignment textHAlign,
|
||||
Qt::Alignment textVAlign,
|
||||
double textLineSpacing,
|
||||
const QMatrix& matrix,
|
||||
bool shadowState,
|
||||
const Distance& shadowX,
|
||||
const Distance& shadowY,
|
||||
double shadowOpacity,
|
||||
const ColorNode& shadowColorNode )
|
||||
: ModelObject( x0, y0, w, h,
|
||||
matrix,
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode )
|
||||
{
|
||||
mOutline = new Outline( this );
|
||||
|
||||
mHandles << new HandleNorthWest( this );
|
||||
mHandles << new HandleNorth( this );
|
||||
mHandles << new HandleNorthEast( this );
|
||||
mHandles << new HandleEast( this );
|
||||
mHandles << new HandleSouthEast( this );
|
||||
mHandles << new HandleSouth( this );
|
||||
mHandles << new HandleSouthWest( this );
|
||||
mHandles << new HandleWest( this );
|
||||
|
||||
mText = text;
|
||||
mFontFamily = fontFamily;
|
||||
mFontSize = fontSize;
|
||||
mFontWeight = fontWeight;
|
||||
mFontItalicFlag = fontItalicFlag;
|
||||
mFontUnderlineFlag = fontUnderlineFlag;
|
||||
mTextColorNode = textColorNode;
|
||||
mTextHAlign = textHAlign;
|
||||
mTextVAlign = textVAlign;
|
||||
mTextLineSpacing = textLineSpacing;
|
||||
|
||||
update(); // Initialize cached editor layouts
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Copy constructor
|
||||
///
|
||||
ModelTextObject::ModelTextObject( const ModelTextObject* object )
|
||||
: ModelObject(object)
|
||||
{
|
||||
mText = object->mText;
|
||||
mFontFamily = object->mFontFamily;
|
||||
mFontSize = object->mFontSize;
|
||||
mFontWeight = object->mFontWeight;
|
||||
mFontItalicFlag = object->mFontItalicFlag;
|
||||
mFontUnderlineFlag = object->mFontUnderlineFlag;
|
||||
mTextColorNode = object->mTextColorNode;
|
||||
mTextHAlign = object->mTextHAlign;
|
||||
mTextVAlign = object->mTextVAlign;
|
||||
mTextLineSpacing = object->mTextLineSpacing;
|
||||
|
||||
update(); // Initialize cached editor layouts
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Destructor
|
||||
///
|
||||
ModelTextObject::~ModelTextObject()
|
||||
{
|
||||
delete mOutline;
|
||||
|
||||
foreach( Handle* handle, mHandles )
|
||||
{
|
||||
delete handle;
|
||||
}
|
||||
mHandles.clear();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone
|
||||
///
|
||||
ModelTextObject* ModelTextObject::clone() const
|
||||
{
|
||||
return new ModelTextObject( this );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Text Property Getter
|
||||
///
|
||||
QString ModelTextObject::text() const
|
||||
{
|
||||
return mText.toString();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Text Property Setter
|
||||
///
|
||||
void ModelTextObject::setText( const QString& value )
|
||||
{
|
||||
if ( mText.toString() != value )
|
||||
{
|
||||
mText = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontFamily Property Getter
|
||||
///
|
||||
QString ModelTextObject::fontFamily() const
|
||||
{
|
||||
return mFontFamily;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontFamily Property Setter
|
||||
///
|
||||
void ModelTextObject::setFontFamily( const QString& value )
|
||||
{
|
||||
if ( mFontFamily != value )
|
||||
{
|
||||
mFontFamily = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontSize Property Getter
|
||||
///
|
||||
double ModelTextObject::fontSize() const
|
||||
{
|
||||
return mFontSize;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontSize Property Setter
|
||||
///
|
||||
void ModelTextObject::setFontSize( double value )
|
||||
{
|
||||
if ( mFontSize != value )
|
||||
{
|
||||
mFontSize = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontWeight Property Getter
|
||||
///
|
||||
QFont::Weight ModelTextObject::fontWeight() const
|
||||
{
|
||||
return mFontWeight;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontWeight Property Setter
|
||||
///
|
||||
void ModelTextObject::setFontWeight( QFont::Weight value )
|
||||
{
|
||||
if ( mFontWeight != value )
|
||||
{
|
||||
mFontWeight = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontItalicFlag Property Getter
|
||||
///
|
||||
bool ModelTextObject::fontItalicFlag() const
|
||||
{
|
||||
return mFontItalicFlag;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontItalicFlag Property Setter
|
||||
///
|
||||
void ModelTextObject::setFontItalicFlag( bool value )
|
||||
{
|
||||
if ( mFontItalicFlag != value )
|
||||
{
|
||||
mFontItalicFlag = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontUnderlineFlag Property Getter
|
||||
///
|
||||
bool ModelTextObject::fontUnderlineFlag() const
|
||||
{
|
||||
return mFontUnderlineFlag;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// FontUnderlineFlag Property Setter
|
||||
///
|
||||
void ModelTextObject::setFontUnderlineFlag( bool value )
|
||||
{
|
||||
if ( mFontUnderlineFlag != value )
|
||||
{
|
||||
mFontUnderlineFlag = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Text Color Node Property Getter
|
||||
///
|
||||
ColorNode ModelTextObject::textColorNode() const
|
||||
{
|
||||
return mTextColorNode;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Text Color Node Property Setter
|
||||
///
|
||||
void ModelTextObject::setTextColorNode( const ColorNode& value )
|
||||
{
|
||||
if ( mTextColorNode != value )
|
||||
{
|
||||
mTextColorNode = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// TextHAlign Property Getter
|
||||
///
|
||||
Qt::Alignment ModelTextObject::textHAlign() const
|
||||
{
|
||||
return mTextHAlign;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// TextHAlign Property Setter
|
||||
///
|
||||
void ModelTextObject::setTextHAlign( Qt::Alignment value )
|
||||
{
|
||||
if ( mTextHAlign != value )
|
||||
{
|
||||
mTextHAlign = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// TextVAlign Property Getter
|
||||
///
|
||||
Qt::Alignment ModelTextObject::textVAlign() const
|
||||
{
|
||||
return mTextVAlign;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// TextVAlign Property Setter
|
||||
///
|
||||
void ModelTextObject::setTextVAlign( Qt::Alignment value )
|
||||
{
|
||||
if ( mTextVAlign != value )
|
||||
{
|
||||
mTextVAlign = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// TextLineSpacing Property Getter
|
||||
///
|
||||
double ModelTextObject::textLineSpacing() const
|
||||
{
|
||||
return mTextLineSpacing;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// TextLineSpacing Property Setter
|
||||
///
|
||||
void ModelTextObject::setTextLineSpacing( double value )
|
||||
{
|
||||
if ( mTextLineSpacing != value )
|
||||
{
|
||||
mTextLineSpacing = value;
|
||||
update();
|
||||
emit changed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// NaturalSize Property Getter
|
||||
///
|
||||
Size ModelTextObject::naturalSize() const
|
||||
{
|
||||
QFont font;
|
||||
font.setFamily( mFontFamily );
|
||||
font.setPointSizeF( mFontSize );
|
||||
font.setWeight( mFontWeight );
|
||||
font.setItalic( mFontItalicFlag );
|
||||
font.setUnderline( mFontUnderlineFlag );
|
||||
|
||||
QTextOption textOption;
|
||||
textOption.setAlignment( mTextHAlign );
|
||||
textOption.setWrapMode( QTextOption::WordWrap );
|
||||
|
||||
QFontMetricsF fontMetrics( font );
|
||||
double dy = fontMetrics.lineSpacing() * mTextLineSpacing;
|
||||
|
||||
QString displayText = mText.isEmpty() ? tr("Text") : mText.toString();
|
||||
QTextDocument document( displayText );
|
||||
|
||||
// Do layouts
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
QRectF boundingRect;
|
||||
for ( int i = 0; i < document.blockCount(); i++ )
|
||||
{
|
||||
QTextLayout* layout = new QTextLayout( document.findBlockByNumber(i).text() );
|
||||
|
||||
layout->setFont( font );
|
||||
layout->setTextOption( textOption );
|
||||
layout->setCacheEnabled(true);
|
||||
|
||||
layout->beginLayout();
|
||||
for ( QTextLine l = layout->createLine(); l.isValid(); l = layout->createLine() )
|
||||
{
|
||||
l.setPosition( QPointF( x, y ) );
|
||||
y += dy;
|
||||
}
|
||||
layout->endLayout();
|
||||
|
||||
boundingRect = layout->boundingRect().united( boundingRect );
|
||||
}
|
||||
|
||||
return Size( boundingRect.width() + 2*marginPts, boundingRect.height() + 2*marginPts );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Can Text Capability Implementation
|
||||
///
|
||||
bool ModelTextObject::canText()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw shadow of object
|
||||
///
|
||||
void ModelTextObject::drawShadow( QPainter* painter,
|
||||
bool inEditor,
|
||||
merge::Record* record ) const
|
||||
{
|
||||
QColor textColor = mTextColorNode.color( record );
|
||||
|
||||
if ( textColor.alpha() )
|
||||
{
|
||||
QColor shadowColor = mShadowColorNode.color( record );
|
||||
shadowColor.setAlphaF( mShadowOpacity );
|
||||
|
||||
if ( inEditor )
|
||||
{
|
||||
drawTextInEditor( painter, shadowColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
drawText( painter, shadowColor, record );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw object itself
|
||||
///
|
||||
void ModelTextObject::drawObject( QPainter* painter,
|
||||
bool inEditor,
|
||||
merge::Record* record ) const
|
||||
{
|
||||
QColor textColor = mTextColorNode.color( record );
|
||||
|
||||
if ( inEditor )
|
||||
{
|
||||
drawTextInEditor( painter, textColor );
|
||||
}
|
||||
else
|
||||
{
|
||||
drawText( painter, textColor, record );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Path to test for hover condition
|
||||
///
|
||||
QPainterPath ModelTextObject::hoverPath( double scale ) const
|
||||
{
|
||||
return mHoverPath;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Size updated
|
||||
///
|
||||
void ModelTextObject::sizeUpdated()
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Update cached information for editor view
|
||||
///
|
||||
void ModelTextObject::update()
|
||||
{
|
||||
QFont font;
|
||||
font.setFamily( mFontFamily );
|
||||
font.setPointSizeF( mFontSize );
|
||||
font.setWeight( mFontWeight );
|
||||
font.setItalic( mFontItalicFlag );
|
||||
font.setUnderline( mFontUnderlineFlag );
|
||||
|
||||
QTextOption textOption;
|
||||
textOption.setAlignment( mTextHAlign );
|
||||
textOption.setWrapMode( QTextOption::WordWrap );
|
||||
|
||||
QFontMetricsF fontMetrics( font );
|
||||
double dy = fontMetrics.lineSpacing() * mTextLineSpacing;
|
||||
|
||||
QString displayText = mText.isEmpty() ? tr("Text") : mText.toString();
|
||||
QTextDocument document( displayText );
|
||||
|
||||
qDeleteAll( mEditorLayouts );
|
||||
mEditorLayouts.clear();
|
||||
|
||||
// Pass #1 -- do initial layouts
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
QRectF boundingRect;
|
||||
for ( int i = 0; i < document.blockCount(); i++ )
|
||||
{
|
||||
QTextLayout* layout = new QTextLayout( document.findBlockByNumber(i).text() );
|
||||
|
||||
layout->setFont( font );
|
||||
layout->setTextOption( textOption );
|
||||
layout->setCacheEnabled(true);
|
||||
|
||||
layout->beginLayout();
|
||||
for ( QTextLine l = layout->createLine(); l.isValid(); l = layout->createLine() )
|
||||
{
|
||||
l.setLineWidth( mW.pt() - 2*marginPts );
|
||||
l.setPosition( QPointF( x, y ) );
|
||||
y += dy;
|
||||
}
|
||||
layout->endLayout();
|
||||
|
||||
mEditorLayouts.append( layout );
|
||||
|
||||
boundingRect = layout->boundingRect().united( boundingRect );
|
||||
}
|
||||
double h = boundingRect.height();
|
||||
|
||||
|
||||
// Pass #2 -- adjust layout positions for vertical alignment and create hover path
|
||||
x = marginPts;
|
||||
switch ( mTextVAlign )
|
||||
{
|
||||
case Qt::AlignVCenter:
|
||||
y = mH.pt()/2 - h/2;
|
||||
break;
|
||||
case Qt::AlignBottom:
|
||||
y = mH.pt() - h - marginPts;
|
||||
break;
|
||||
default:
|
||||
y = marginPts;
|
||||
break;
|
||||
}
|
||||
QPainterPath hoverPath; // new empty hover path
|
||||
foreach ( QTextLayout* layout, mEditorLayouts )
|
||||
{
|
||||
for ( int j = 0; j < layout->lineCount(); j++ )
|
||||
{
|
||||
QTextLine l = layout->lineAt(j);
|
||||
l.setPosition( QPointF( x, y ) );
|
||||
y += dy;
|
||||
|
||||
hoverPath.addRect( l.naturalTextRect() ); // add to new hover path
|
||||
}
|
||||
}
|
||||
|
||||
mHoverPath = hoverPath; // save new hover path
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw text in editor from cached information
|
||||
///
|
||||
void ModelTextObject::drawTextInEditor( QPainter* painter, const QColor& color ) const
|
||||
{
|
||||
if ( mText.isEmpty() )
|
||||
{
|
||||
QColor mutedColor = color;
|
||||
mutedColor.setAlphaF( 0.5 * color.alphaF() );
|
||||
painter->setPen( QPen( mutedColor ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen( QPen( color ) );
|
||||
}
|
||||
|
||||
foreach ( QTextLayout* layout, mEditorLayouts )
|
||||
{
|
||||
layout->draw( painter, QPointF( 0, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw text in final printout or preview
|
||||
///
|
||||
void
|
||||
ModelTextObject::drawText( QPainter* painter,
|
||||
const QColor& color,
|
||||
merge::Record* record ) const
|
||||
{
|
||||
QFont font;
|
||||
font.setFamily( mFontFamily );
|
||||
font.setPointSizeF( mFontSize );
|
||||
font.setWeight( mFontWeight );
|
||||
font.setItalic( mFontItalicFlag );
|
||||
font.setUnderline( mFontUnderlineFlag );
|
||||
|
||||
QTextOption textOption;
|
||||
textOption.setAlignment( mTextHAlign );
|
||||
textOption.setWrapMode( QTextOption::WordWrap );
|
||||
|
||||
QFontMetricsF fontMetrics( font );
|
||||
double dy = fontMetrics.lineSpacing() * mTextLineSpacing;
|
||||
|
||||
QTextDocument document( mText.expand( record ) );
|
||||
|
||||
QList<QTextLayout*> layouts;
|
||||
|
||||
// Pass #1 -- do initial layouts
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
QRectF boundingRect;
|
||||
for ( int i = 0; i < document.blockCount(); i++ )
|
||||
{
|
||||
QTextLayout* layout = new QTextLayout( document.findBlockByNumber(i).text() );
|
||||
|
||||
layout->setFont( font );
|
||||
layout->setTextOption( textOption );
|
||||
layout->setCacheEnabled(true);
|
||||
|
||||
layout->beginLayout();
|
||||
for ( QTextLine l = layout->createLine(); l.isValid(); l = layout->createLine() )
|
||||
{
|
||||
l.setLineWidth( mW.pt() - 2*marginPts );
|
||||
l.setPosition( QPointF( x, y ) );
|
||||
y += dy;
|
||||
}
|
||||
layout->endLayout();
|
||||
|
||||
layouts.append( layout );
|
||||
|
||||
boundingRect = layout->boundingRect().united( boundingRect );
|
||||
}
|
||||
double h = boundingRect.height();
|
||||
|
||||
|
||||
// Pass #2 -- adjust layout positions for vertical alignment and create hover path
|
||||
x = marginPts;
|
||||
switch ( mTextVAlign )
|
||||
{
|
||||
case Qt::AlignVCenter:
|
||||
y = mH.pt()/2 - h/2;
|
||||
break;
|
||||
case Qt::AlignBottom:
|
||||
y = mH.pt() - h - marginPts;
|
||||
break;
|
||||
default:
|
||||
y = marginPts;
|
||||
break;
|
||||
}
|
||||
foreach ( QTextLayout* layout, layouts )
|
||||
{
|
||||
for ( int j = 0; j < layout->lineCount(); j++ )
|
||||
{
|
||||
QTextLine l = layout->lineAt(j);
|
||||
l.setPosition( QPointF( x, y ) );
|
||||
y += dy;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw layouts
|
||||
painter->setPen( QPen( color ) );
|
||||
foreach ( QTextLayout* layout, layouts )
|
||||
{
|
||||
layout->draw( painter, QPointF( 0, 0 ) );
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
qDeleteAll( layouts );
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,209 @@
|
||||
/* ModelTextObject.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_ModelTextObject_h
|
||||
#define model_ModelTextObject_h
|
||||
|
||||
|
||||
#include "ModelObject.h"
|
||||
#include "RawText.h"
|
||||
|
||||
#include <QTextLayout>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Model Line Object
|
||||
///
|
||||
class ModelTextObject : public ModelObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Lifecycle Methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
ModelTextObject();
|
||||
|
||||
ModelTextObject( const Distance& x0,
|
||||
const Distance& y0,
|
||||
const Distance& w,
|
||||
const Distance& h,
|
||||
const QString& text,
|
||||
const QString& fontFamily,
|
||||
double fontSize,
|
||||
QFont::Weight fontWeight,
|
||||
bool fontItalicFlag,
|
||||
bool fontUnderlineFlag,
|
||||
ColorNode textColorNode,
|
||||
Qt::Alignment textHAlign,
|
||||
Qt::Alignment textVAlign,
|
||||
double textLineSpacing,
|
||||
const QMatrix& matrix = QMatrix(),
|
||||
bool shadowState = false,
|
||||
const Distance& shadowX = 0,
|
||||
const Distance& shadowY = 0,
|
||||
double shadowOpacity = 1.0,
|
||||
const ColorNode& shadowColorNode = ColorNode() );
|
||||
|
||||
ModelTextObject( const ModelTextObject* object );
|
||||
|
||||
~ModelTextObject() override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Object duplication
|
||||
///////////////////////////////////////////////////////////////
|
||||
ModelTextObject* clone() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Property Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// Text Property: text
|
||||
//
|
||||
QString text() const override;
|
||||
void setText( const QString &value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: fontFamily
|
||||
//
|
||||
QString fontFamily() const override;
|
||||
void setFontFamily( const QString &value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: fontSize
|
||||
//
|
||||
double fontSize() const override;
|
||||
void setFontSize( double value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: fontWeight
|
||||
//
|
||||
QFont::Weight fontWeight() const override;
|
||||
void setFontWeight( QFont::Weight value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: fontItalicFlag
|
||||
//
|
||||
bool fontItalicFlag() const override;
|
||||
void setFontItalicFlag( bool value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: fontUnderlineFlag
|
||||
//
|
||||
bool fontUnderlineFlag() const override;
|
||||
void setFontUnderlineFlag( bool value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: textColorNode
|
||||
//
|
||||
ColorNode textColorNode() const override;
|
||||
void setTextColorNode( const ColorNode &value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: textHAlign
|
||||
//
|
||||
Qt::Alignment textHAlign() const override;
|
||||
void setTextHAlign( Qt::Alignment value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: textVAlign
|
||||
//
|
||||
Qt::Alignment textVAlign() const override;
|
||||
void setTextVAlign( Qt::Alignment value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Text Property: textLineSpacing
|
||||
//
|
||||
double textLineSpacing() const override;
|
||||
void setTextLineSpacing( double value ) override;
|
||||
|
||||
|
||||
//
|
||||
// Property: naturalSize
|
||||
//
|
||||
Size naturalSize() const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Capability Implementations
|
||||
///////////////////////////////////////////////////////////////
|
||||
public:
|
||||
virtual bool canText();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Drawing operations
|
||||
///////////////////////////////////////////////////////////////
|
||||
protected:
|
||||
void drawShadow( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
void drawObject( QPainter* painter, bool inEditor, merge::Record* record ) const override;
|
||||
QPainterPath hoverPath( double scale ) const override;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////
|
||||
private:
|
||||
void sizeUpdated() override;
|
||||
void update();
|
||||
void drawTextInEditor( QPainter* painter, const QColor& color ) const;
|
||||
void drawText( QPainter* painter, const QColor&color, merge::Record* record ) const;
|
||||
QString expandText( QString text, merge::Record* record ) const;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Private Members
|
||||
///////////////////////////////////////////////////////////////
|
||||
private:
|
||||
RawText mText;
|
||||
QString mFontFamily;
|
||||
double mFontSize;
|
||||
QFont::Weight mFontWeight;
|
||||
bool mFontItalicFlag;
|
||||
bool mFontUnderlineFlag;
|
||||
ColorNode mTextColorNode;
|
||||
Qt::Alignment mTextHAlign;
|
||||
Qt::Alignment mTextVAlign;
|
||||
double mTextLineSpacing;
|
||||
|
||||
QList<QTextLayout*> mEditorLayouts;
|
||||
QPainterPath mHoverPath;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_ModelTextObject_h
|
||||
@@ -0,0 +1,135 @@
|
||||
/* Outline.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Outline.h"
|
||||
|
||||
#include "ModelObject.h"
|
||||
|
||||
#include <QColor>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const qreal dashSize = 2;
|
||||
|
||||
const double slopPixels = 2;
|
||||
const double outlineWidthPixels = 1;
|
||||
const QColor outlineColor1( 0, 0, 0 );
|
||||
const QColor outlineColor2( 255, 255, 255 );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Outline Constructor
|
||||
///
|
||||
Outline::Outline( ModelObject* owner )
|
||||
: mOwner(owner)
|
||||
{
|
||||
mDashes << dashSize << dashSize;
|
||||
|
||||
mPen1.setColor( outlineColor1 );
|
||||
mPen1.setWidth( outlineWidthPixels );
|
||||
mPen1.setCosmetic( true );
|
||||
mPen1.setCapStyle( Qt::FlatCap );
|
||||
mPen1.setDashPattern( mDashes );
|
||||
|
||||
mPen2.setColor( outlineColor2 );
|
||||
mPen2.setWidth( outlineWidthPixels );
|
||||
mPen2.setCosmetic( true );
|
||||
mPen2.setCapStyle( Qt::FlatCap );
|
||||
mPen2.setDashPattern( mDashes );
|
||||
mPen2.setDashOffset( dashSize );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Outline Copy constructor
|
||||
///
|
||||
Outline::Outline( const Outline* outline, ModelObject* newOwner )
|
||||
: mOwner(newOwner)
|
||||
{
|
||||
mDashes = outline->mDashes;
|
||||
mPen1 = outline->mPen1;
|
||||
mPen2 = outline->mPen2;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Outline Destructor
|
||||
///
|
||||
Outline::~Outline()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Clone Outline
|
||||
///
|
||||
Outline* Outline::clone( ModelObject* newOwner ) const
|
||||
{
|
||||
return new Outline( this, newOwner );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Draw Outline
|
||||
///
|
||||
void Outline::draw( QPainter* painter ) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setBrush( Qt::NoBrush );
|
||||
|
||||
painter->setPen( mPen1 );
|
||||
painter->drawRect( QRectF( 0, 0, mOwner->w().pt(), mOwner->h().pt() ) );
|
||||
|
||||
painter->setPen( mPen2 );
|
||||
painter->drawRect( QRectF( 0, 0, mOwner->w().pt(), mOwner->h().pt() ) );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Create path for testing for hover condition
|
||||
///
|
||||
QPainterPath Outline::hoverPath( double scale ) const
|
||||
{
|
||||
double s = 1 / scale;
|
||||
|
||||
QPainterPath path;
|
||||
|
||||
path.addRect( -s*slopPixels, -s*slopPixels,
|
||||
mOwner->w().pt()+s*2*slopPixels, mOwner->h().pt()+s*2*slopPixels );
|
||||
path.closeSubpath();
|
||||
path.addRect( s*slopPixels, s*slopPixels,
|
||||
mOwner->w().pt()-s*2*slopPixels, mOwner->h().pt()-s*2*slopPixels );
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,79 @@
|
||||
/* Outline.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Outline_h
|
||||
#define model_Outline_h
|
||||
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward references
|
||||
class ModelObject;
|
||||
|
||||
|
||||
///
|
||||
/// Outline Base Class
|
||||
///
|
||||
class Outline
|
||||
{
|
||||
////////////////////////////
|
||||
// Lifecycle Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
Outline( ModelObject* owner );
|
||||
Outline( const Outline* outline, ModelObject* newOwner );
|
||||
virtual ~Outline();
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Duplication
|
||||
////////////////////////////
|
||||
Outline* clone( ModelObject* newOwner ) const;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Drawing Methods
|
||||
////////////////////////////
|
||||
public:
|
||||
void draw( QPainter* painter ) const;
|
||||
QPainterPath hoverPath( double scale ) const;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Private Data
|
||||
////////////////////////////
|
||||
private:
|
||||
ModelObject* mOwner;
|
||||
|
||||
QVector<qreal> mDashes;
|
||||
QPen mPen1;
|
||||
QPen mPen2;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Outline_h
|
||||
@@ -0,0 +1,429 @@
|
||||
/* PageRenderer.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "PageRenderer.h"
|
||||
|
||||
#include "Model.h"
|
||||
|
||||
#include "merge/Merge.h"
|
||||
#include "merge/None.h"
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const QColor labelOutlineColor( 0, 0, 0 );
|
||||
const double labelOutlineWidth = 0.25;
|
||||
const double tickOffset = 2.25;
|
||||
const double tickLength = 18;
|
||||
}
|
||||
|
||||
|
||||
PageRenderer::PageRenderer( const Model* model )
|
||||
: mModel(nullptr), mNCopies(0), mStartLabel(0),
|
||||
mPrintOutlines(false), mPrintCropMarks(false), mPrintReverse(false),
|
||||
mIPage(0), mIsMerge(false), mNPages(0)
|
||||
{
|
||||
if ( model )
|
||||
{
|
||||
setModel( model );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setModel( const Model* model )
|
||||
{
|
||||
mModel = model;
|
||||
|
||||
connect( mModel, SIGNAL(changed()), this, SLOT(onModelChanged()) );
|
||||
|
||||
onModelChanged();
|
||||
}
|
||||
|
||||
|
||||
const Model* PageRenderer::model() const
|
||||
{
|
||||
return mModel;
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::onModelChanged()
|
||||
{
|
||||
mMerge = mModel->merge();
|
||||
mOrigins = mModel->frame()->getOrigins();
|
||||
mNLabelsPerPage = mModel->frame()->nLabels();
|
||||
mIsMerge = ( dynamic_cast<const merge::None*>(mMerge) == nullptr );
|
||||
updateNPages();
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setNCopies( int nCopies )
|
||||
{
|
||||
mNCopies = nCopies;
|
||||
updateNPages();
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setStartLabel( int startLabel )
|
||||
{
|
||||
mStartLabel = startLabel;
|
||||
updateNPages();
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setPrintOutlines( bool printOutlinesFlag )
|
||||
{
|
||||
mPrintOutlines = printOutlinesFlag;
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setPrintCropMarks( bool printCropMarksFlag )
|
||||
{
|
||||
mPrintCropMarks = printCropMarksFlag;
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setPrintReverse( bool printReverseFlag )
|
||||
{
|
||||
mPrintReverse = printReverseFlag;
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::setIPage( int iPage )
|
||||
{
|
||||
mIPage = iPage;
|
||||
|
||||
emit changed();
|
||||
}
|
||||
|
||||
|
||||
int PageRenderer::nItems() const
|
||||
{
|
||||
return mLastLabel - mStartLabel;
|
||||
}
|
||||
|
||||
|
||||
int PageRenderer::nPages() const
|
||||
{
|
||||
return mNPages;
|
||||
}
|
||||
|
||||
|
||||
QRectF PageRenderer::pageRect() const
|
||||
{
|
||||
if ( mModel )
|
||||
{
|
||||
return QRectF( 0, 0, mModel->tmplate()->pageWidth().pt(), mModel->tmplate()->pageHeight().pt() );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QRectF( 0, 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::updateNPages()
|
||||
{
|
||||
if ( mModel )
|
||||
{
|
||||
if ( mIsMerge )
|
||||
{
|
||||
mLastLabel = mStartLabel + mNCopies*mMerge->nSelectedRecords();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLastLabel = mStartLabel + mNCopies;
|
||||
}
|
||||
|
||||
mNPages = mLastLabel / mNLabelsPerPage;
|
||||
if ( mLastLabel % mNLabelsPerPage )
|
||||
{
|
||||
mNPages++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mNPages = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Print
|
||||
///
|
||||
void PageRenderer::print( QPrinter* printer ) const
|
||||
{
|
||||
QSizeF pageSize( mModel->tmplate()->pageWidth().pt(), mModel->tmplate()->pageHeight().pt() );
|
||||
printer->setPageSize( QPageSize(pageSize, QPageSize::Point) );
|
||||
printer->setFullPage( true );
|
||||
printer->setPageMargins( 0, 0, 0, 0, QPrinter::Point );
|
||||
|
||||
QPainter painter( printer );
|
||||
|
||||
QRectF rectPx = printer->paperRect( QPrinter::DevicePixel );
|
||||
QRectF rectPts = printer->paperRect( QPrinter::Point );
|
||||
painter.scale( rectPx.width()/rectPts.width(), rectPx.height()/rectPts.height() );
|
||||
|
||||
for ( int iPage = 0; iPage < mNPages; iPage++ )
|
||||
{
|
||||
if ( iPage )
|
||||
{
|
||||
printer->newPage();
|
||||
}
|
||||
|
||||
printPage( &painter, iPage );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Print page using persistent page number
|
||||
///
|
||||
void PageRenderer::printPage( QPainter* painter ) const
|
||||
{
|
||||
printPage( painter, mIPage );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Print page
|
||||
///
|
||||
void PageRenderer::printPage( QPainter* painter, int iPage ) const
|
||||
{
|
||||
if ( mModel )
|
||||
{
|
||||
if ( mIsMerge )
|
||||
{
|
||||
printMergePage( painter, iPage );
|
||||
}
|
||||
else
|
||||
{
|
||||
printSimplePage( painter, iPage );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::printSimplePage( QPainter* painter, int iPage ) const
|
||||
{
|
||||
int iStart = 0;
|
||||
int iEnd = mNLabelsPerPage;
|
||||
|
||||
if ( iPage == 0 )
|
||||
{
|
||||
iStart = mStartLabel;
|
||||
}
|
||||
|
||||
if ( (mLastLabel / mNLabelsPerPage) == iPage )
|
||||
{
|
||||
iEnd = mLastLabel % mNLabelsPerPage;
|
||||
}
|
||||
|
||||
printCropMarks( painter );
|
||||
|
||||
for ( int i = iStart; i < iEnd; i++ )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->translate( mOrigins[i].x().pt(), mOrigins[i].y().pt() );
|
||||
|
||||
painter->save();
|
||||
|
||||
clipLabel( painter );
|
||||
printLabel( painter, nullptr );
|
||||
|
||||
painter->restore(); // From before clip
|
||||
|
||||
printOutline( painter );
|
||||
|
||||
painter->restore(); // From before translation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::printMergePage( QPainter* painter, int iPage ) const
|
||||
{
|
||||
int iRecord = 0;
|
||||
int iStart = 0;
|
||||
int iEnd = mNLabelsPerPage;
|
||||
|
||||
if ( iPage == 0 )
|
||||
{
|
||||
iStart = mStartLabel;
|
||||
}
|
||||
|
||||
if ( (mLastLabel / mNLabelsPerPage) == iPage )
|
||||
{
|
||||
iEnd = mLastLabel % mNLabelsPerPage;
|
||||
}
|
||||
|
||||
const QList<merge::Record*> records = mMerge->selectedRecords();
|
||||
if ( records.size() )
|
||||
{
|
||||
iRecord = (iPage*mNLabelsPerPage + iStart - mStartLabel) % records.size();
|
||||
}
|
||||
|
||||
printCropMarks( painter );
|
||||
|
||||
for ( int i = iStart; i < iEnd; i++ )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->translate( mOrigins[i].x().pt(), mOrigins[i].y().pt() );
|
||||
|
||||
painter->save();
|
||||
|
||||
clipLabel( painter );
|
||||
printLabel( painter, records[iRecord] );
|
||||
|
||||
painter->restore(); // From before clip
|
||||
|
||||
printOutline( painter );
|
||||
|
||||
painter->restore(); // From before translation
|
||||
|
||||
iRecord = (iRecord + 1) % records.size();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::printCropMarks( QPainter* painter ) const
|
||||
{
|
||||
if ( mPrintCropMarks )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setBrush( QBrush( Qt::NoBrush ) );
|
||||
painter->setPen( QPen( labelOutlineColor, labelOutlineWidth ) );
|
||||
|
||||
Distance w = mModel->frame()->w();
|
||||
Distance h = mModel->frame()->h();
|
||||
|
||||
foreach ( 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;
|
||||
|
||||
for ( int ix = 0; ix < layout->nx(); ix++ )
|
||||
{
|
||||
Distance x1 = xMin + ix*layout->dx();
|
||||
Distance x2 = x1 + w;
|
||||
|
||||
Distance y1 = max( yMin-tickOffset, Distance::pt(0) );
|
||||
Distance y2 = max( y1-tickLength, Distance::pt(0) );
|
||||
|
||||
Distance y3 = min( yMax+tickOffset, mModel->tmplate()->pageHeight() );
|
||||
Distance y4 = min( y3+tickLength, mModel->tmplate()->pageHeight() );
|
||||
|
||||
painter->drawLine( x1.pt(), y1.pt(), x1.pt(), y2.pt() );
|
||||
painter->drawLine( x2.pt(), y1.pt(), x2.pt(), y2.pt() );
|
||||
painter->drawLine( x1.pt(), y3.pt(), x1.pt(), y4.pt() );
|
||||
painter->drawLine( x2.pt(), y3.pt(), x2.pt(), y4.pt() );
|
||||
}
|
||||
|
||||
for ( int iy = 0; iy < layout->ny(); iy++ )
|
||||
{
|
||||
Distance y1 = yMin + iy*layout->dy();
|
||||
Distance y2 = y1 + h;
|
||||
|
||||
Distance x1 = max( xMin-tickOffset, Distance::pt(0) );
|
||||
Distance x2 = max( x1-tickLength, Distance::pt(0) );
|
||||
|
||||
Distance x3 = min( xMax+tickOffset, mModel->tmplate()->pageWidth() );
|
||||
Distance x4 = min( x3+tickLength, mModel->tmplate()->pageWidth() );
|
||||
|
||||
painter->drawLine( x1.pt(), y1.pt(), x2.pt(), y1.pt() );
|
||||
painter->drawLine( x1.pt(), y2.pt(), x2.pt(), y2.pt() );
|
||||
painter->drawLine( x3.pt(), y1.pt(), x4.pt(), y1.pt() );
|
||||
painter->drawLine( x3.pt(), y2.pt(), x4.pt(), y2.pt() );
|
||||
}
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::printOutline( QPainter* painter ) const
|
||||
{
|
||||
if ( mPrintOutlines )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
painter->setBrush( QBrush( Qt::NoBrush ) );
|
||||
painter->setPen( QPen( labelOutlineColor, labelOutlineWidth ) );
|
||||
|
||||
painter->drawPath( mModel->frame()->path() );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::clipLabel( QPainter* painter ) const
|
||||
{
|
||||
painter->setClipPath( mModel->frame()->clipPath() );
|
||||
}
|
||||
|
||||
|
||||
void PageRenderer::printLabel( QPainter* painter, merge::Record* record ) const
|
||||
{
|
||||
painter->save();
|
||||
|
||||
if ( mModel->rotate() )
|
||||
{
|
||||
painter->rotate( -90.0 );
|
||||
painter->translate( -mModel->w().pt(), 0 );
|
||||
}
|
||||
|
||||
if ( mPrintReverse )
|
||||
{
|
||||
painter->translate( mModel->w().pt(), 0 );
|
||||
painter->scale( -1, 1 );
|
||||
}
|
||||
|
||||
mModel->draw( painter, false, record );
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,129 @@
|
||||
/* PageRenderer.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_PageRenderer_h
|
||||
#define model_PageRenderer_h
|
||||
|
||||
|
||||
#include "Point.h"
|
||||
|
||||
#include "merge/Merge.h"
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPrinter>
|
||||
#include <QRect>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward references
|
||||
class Model;
|
||||
|
||||
|
||||
///
|
||||
/// PageRenderer Widget
|
||||
///
|
||||
class PageRenderer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
/////////////////////////////////
|
||||
// Life Cycle
|
||||
/////////////////////////////////
|
||||
public:
|
||||
PageRenderer( const Model* model = nullptr );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Public Methods
|
||||
/////////////////////////////////
|
||||
public:
|
||||
void setModel( const Model* model );
|
||||
const Model* model() const;
|
||||
void setNCopies( int nCopies );
|
||||
void setStartLabel( int startLabel );
|
||||
void setPrintOutlines( bool printOutlinesFlag );
|
||||
void setPrintCropMarks( bool printCropMarksFlag );
|
||||
void setPrintReverse( bool printReverseFlag );
|
||||
void setIPage( int iPage );
|
||||
int nItems() const;
|
||||
int nPages() const;
|
||||
QRectF pageRect() const;
|
||||
void print( QPrinter* printer ) const;
|
||||
void printPage( QPainter* painter ) const;
|
||||
void printPage( QPainter* painter, int iPage ) const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Signals
|
||||
/////////////////////////////////
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private slots
|
||||
/////////////////////////////////
|
||||
private slots:
|
||||
void onModelChanged();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Internal Methods
|
||||
/////////////////////////////////
|
||||
private:
|
||||
void updateNPages();
|
||||
void printSimplePage( QPainter* painter, int iPage ) const;
|
||||
void printMergePage( QPainter* painter, int iPage ) const;
|
||||
void printCropMarks( QPainter* painter ) const;
|
||||
void printOutline( QPainter* painter ) const;
|
||||
void clipLabel( QPainter* painter ) const;
|
||||
void printLabel( QPainter* painter, merge::Record* record ) const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
const Model* mModel;
|
||||
const merge::Merge* mMerge;
|
||||
|
||||
int mNCopies;
|
||||
int mStartLabel;
|
||||
int mLastLabel;
|
||||
bool mPrintOutlines;
|
||||
bool mPrintCropMarks;
|
||||
bool mPrintReverse;
|
||||
int mIPage;
|
||||
|
||||
bool mIsMerge;
|
||||
int mNPages;
|
||||
int mNLabelsPerPage;
|
||||
|
||||
QVector<Point> mOrigins;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_PageRenderer_h
|
||||
@@ -0,0 +1,79 @@
|
||||
/* Paper.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Paper.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Paper::Paper( const QString& id,
|
||||
const QString& name,
|
||||
const Distance& width,
|
||||
const Distance& height,
|
||||
const QString& pwgSize )
|
||||
: mId(id), mName(name), mWidth(width), mHeight(height), mPwgSize(pwgSize)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
QString Paper::id() const
|
||||
{
|
||||
return mId;
|
||||
}
|
||||
|
||||
|
||||
QString Paper::name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
|
||||
Distance Paper::width() const
|
||||
{
|
||||
return mWidth;
|
||||
}
|
||||
|
||||
|
||||
Distance Paper::height() const
|
||||
{
|
||||
return mHeight;
|
||||
}
|
||||
|
||||
|
||||
QString Paper::pwgSize() const
|
||||
{
|
||||
return mPwgSize;
|
||||
}
|
||||
|
||||
|
||||
bool Paper::isSizeIso() const
|
||||
{
|
||||
return mPwgSize.startsWith( "iso_" );
|
||||
}
|
||||
|
||||
|
||||
bool Paper::isSizeUs() const
|
||||
{
|
||||
return mPwgSize.startsWith( "na_" );
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,68 @@
|
||||
/* Paper.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Paper_h
|
||||
#define model_Paper_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Paper
|
||||
{
|
||||
public:
|
||||
Paper( const QString& id,
|
||||
const QString& name,
|
||||
const Distance& width,
|
||||
const Distance& height,
|
||||
const QString& pwgSize );
|
||||
|
||||
QString id() const;
|
||||
QString name() const;
|
||||
|
||||
/* Width */
|
||||
Distance width() const;
|
||||
|
||||
/* Height */
|
||||
Distance height() const;
|
||||
|
||||
/* PWG 5101.1-2002 size name */
|
||||
QString pwgSize() const;
|
||||
|
||||
bool isSizeIso() const;
|
||||
bool isSizeUs() const;
|
||||
|
||||
private:
|
||||
QString mId;
|
||||
QString mName;
|
||||
Distance mWidth;
|
||||
Distance mHeight;
|
||||
QString mPwgSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Paper_h
|
||||
@@ -0,0 +1,64 @@
|
||||
/* Point.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Point.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Point::Point() : mX(Distance(0)), mY(Distance(0))
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Point::Point( Distance x, Distance y ) : mX(x), mY(y)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Distance Point::x() const
|
||||
{
|
||||
return mX;
|
||||
}
|
||||
|
||||
|
||||
Distance Point::y() const
|
||||
{
|
||||
return mY;
|
||||
}
|
||||
|
||||
|
||||
bool Point::operator<( const Point &other ) const
|
||||
{
|
||||
if ( mY < other.mY )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if ( mY == other.mY )
|
||||
{
|
||||
return mX < other.mX;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Point.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Point_h
|
||||
#define model_Point_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Point
|
||||
{
|
||||
public:
|
||||
Point();
|
||||
|
||||
Point( Distance x, Distance y );
|
||||
|
||||
Distance x() const;
|
||||
Distance y() const;
|
||||
|
||||
bool operator<( const Point &other ) const;
|
||||
|
||||
|
||||
private:
|
||||
Distance mX;
|
||||
Distance mY;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Point_h
|
||||
@@ -0,0 +1,149 @@
|
||||
/* RawText.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 "RawText.h"
|
||||
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Constructor from QString
|
||||
///
|
||||
RawText::RawText( const QString& string ) : mString(string)
|
||||
{
|
||||
tokenize();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor from C string operator
|
||||
///
|
||||
RawText::RawText( const char* cString ) : mString(QString(cString))
|
||||
{
|
||||
tokenize();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Access as QString
|
||||
///
|
||||
QString RawText::toString() const
|
||||
{
|
||||
return mString;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Access as std::string
|
||||
///
|
||||
std::string RawText::toStdString() const
|
||||
{
|
||||
return mString.toStdString();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Expand all place holders
|
||||
///
|
||||
QString RawText::expand( merge::Record* record ) const
|
||||
{
|
||||
QString text;
|
||||
|
||||
foreach ( const Token& token, mTokens )
|
||||
{
|
||||
if ( token.isField )
|
||||
{
|
||||
text += token.field.evaluate( record );
|
||||
}
|
||||
else
|
||||
{
|
||||
text += token.text;
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Does raw text contain place holders?
|
||||
///
|
||||
bool RawText::hasPlaceHolders() const
|
||||
{
|
||||
QRegularExpression re("\\${\\w+}");
|
||||
return mString.contains( re );
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Is raw text empty?
|
||||
///
|
||||
bool RawText::isEmpty() const
|
||||
{
|
||||
return mString.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Tokenize string
|
||||
///
|
||||
void RawText::tokenize()
|
||||
{
|
||||
Token token;
|
||||
|
||||
QStringRef s = &mString;
|
||||
while ( s.size() )
|
||||
{
|
||||
SubstitutionField field;
|
||||
if ( SubstitutionField::parse( s, field ) )
|
||||
{
|
||||
// Finalize current text token, if apropos
|
||||
if ( !token.text.isEmpty() )
|
||||
{
|
||||
token.isField = false;
|
||||
mTokens.append( token );
|
||||
}
|
||||
|
||||
// Create and finalize field token
|
||||
token.isField = true;
|
||||
token.text = "";
|
||||
token.field = field;
|
||||
mTokens.append( token );
|
||||
}
|
||||
else
|
||||
{
|
||||
token.text += s[0];
|
||||
s = s.mid(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Finalize last text token, if apropos
|
||||
if ( !token.text.isEmpty() )
|
||||
{
|
||||
token.isField = false;
|
||||
mTokens.append( token );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,84 @@
|
||||
/* RawText.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 model_RawText_h
|
||||
#define model_RawText_h
|
||||
|
||||
|
||||
#include "SubstitutionField.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Raw Text Type
|
||||
///
|
||||
struct RawText
|
||||
{
|
||||
|
||||
/////////////////////////////////
|
||||
// Life Cycle
|
||||
/////////////////////////////////
|
||||
public:
|
||||
RawText() = default;
|
||||
RawText( const QString& string );
|
||||
RawText( const char* cString );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Misc. Methods
|
||||
/////////////////////////////////
|
||||
QString toString() const;
|
||||
std::string toStdString() const;
|
||||
QString expand( merge::Record* record ) const;
|
||||
bool hasPlaceHolders() const;
|
||||
bool isEmpty() const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Methods
|
||||
/////////////////////////////////
|
||||
private:
|
||||
void tokenize();
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
QString mString;
|
||||
|
||||
struct Token
|
||||
{
|
||||
bool isField;
|
||||
QString text;
|
||||
SubstitutionField field;
|
||||
};
|
||||
|
||||
QList<Token> mTokens;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_RawText_h
|
||||
@@ -0,0 +1,134 @@
|
||||
/* Region.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Region.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
Region::Region() : mX1(0), mY1(0), mX2(0), mY2(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
Region::Region( const Distance& x1, const Distance& y1,
|
||||
const Distance& x2, const Distance& y2 )
|
||||
: mX1(x1), mY1(y1), mX2(x2), mY2(y2)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get x1
|
||||
///
|
||||
Distance Region::x1() const
|
||||
{
|
||||
return mX1;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Set x1
|
||||
///
|
||||
void Region::setX1( const Distance& value )
|
||||
{
|
||||
mX1 = value;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get y1
|
||||
///
|
||||
Distance Region::y1() const
|
||||
{
|
||||
return mY1;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Set y1
|
||||
///
|
||||
void Region::setY1( const Distance& value )
|
||||
{
|
||||
mY1 = value;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get x2
|
||||
///
|
||||
Distance Region::x2() const
|
||||
{
|
||||
return mX2;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Set x2
|
||||
///
|
||||
void Region::setX2( const Distance& value )
|
||||
{
|
||||
mX2 = value;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get y2
|
||||
///
|
||||
Distance Region::y2() const
|
||||
{
|
||||
return mY2;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Set y2
|
||||
///
|
||||
void Region::setY2( const Distance& value )
|
||||
{
|
||||
mY2 = value;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert to a QRectF
|
||||
///
|
||||
QRectF Region::rect() const
|
||||
{
|
||||
QRectF r;
|
||||
|
||||
r.setX( min( mX1, mX2 ).pt() );
|
||||
r.setY( min( mY1, mY2 ).pt() );
|
||||
r.setWidth( fabs( mX2 - mX1 ).pt() );
|
||||
r.setHeight( fabs( mY2 - mY1 ).pt() );
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* Region.h
|
||||
*
|
||||
* Copyright (C) 2013 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 model_Region_h
|
||||
#define model_Region_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
#include <QRectF>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Label Region Type
|
||||
///
|
||||
struct Region
|
||||
{
|
||||
|
||||
/////////////////////////////////
|
||||
// Constructors
|
||||
/////////////////////////////////
|
||||
public:
|
||||
Region();
|
||||
Region( const Distance& x1, const Distance& y1,
|
||||
const Distance& x2, const Distance& y2 );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Properties
|
||||
/////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// X1 Property
|
||||
//
|
||||
Distance x1() const;
|
||||
void setX1( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// Y1 Property
|
||||
//
|
||||
Distance y1() const;
|
||||
void setY1( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// X2 Property
|
||||
//
|
||||
Distance x2() const;
|
||||
void setX2( const Distance& value );
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Y2 Property
|
||||
//
|
||||
Distance y2() const;
|
||||
void setY2( const Distance& value );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Methods
|
||||
/////////////////////////////////
|
||||
public:
|
||||
QRectF rect() const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
Distance mX1;
|
||||
Distance mY1;
|
||||
Distance mX2;
|
||||
Distance mY2;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Region_h
|
||||
@@ -0,0 +1,261 @@
|
||||
/* Settings.cpp
|
||||
*
|
||||
* Copyright (C) 2016 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 "Settings.h"
|
||||
|
||||
#include <QLocale>
|
||||
#include <QString>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Static data
|
||||
//
|
||||
Settings* Settings::mInstance = nullptr;
|
||||
|
||||
|
||||
Settings::Settings()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
void Settings::init()
|
||||
{
|
||||
if ( mInstance == nullptr )
|
||||
{
|
||||
mInstance = new Settings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Settings* Settings::instance()
|
||||
{
|
||||
init();
|
||||
|
||||
return mInstance;
|
||||
}
|
||||
|
||||
|
||||
Units Settings::units()
|
||||
{
|
||||
// Guess at a suitable default
|
||||
QString defaultIdString;
|
||||
if ( QLocale::system().measurementSystem() == QLocale::ImperialSystem )
|
||||
{
|
||||
defaultIdString = Units(Units::IN).toIdString();
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultIdString = Units(Units::MM).toIdString();
|
||||
}
|
||||
|
||||
mInstance->beginGroup( "Locale" );
|
||||
QString idString = mInstance->value( "units", defaultIdString ).toString();
|
||||
mInstance->endGroup();
|
||||
|
||||
return Units( idString );
|
||||
}
|
||||
|
||||
|
||||
void Settings::setUnits( const Units& units )
|
||||
{
|
||||
QString idString = units.toIdString();
|
||||
|
||||
mInstance->beginGroup( "Locale" );
|
||||
mInstance->setValue( "units", idString );
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
|
||||
bool Settings::searchIsoPaperSizes()
|
||||
{
|
||||
// Guess at a suitable default
|
||||
bool defaultValue;
|
||||
switch (QLocale::system().country())
|
||||
{
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::Canada:
|
||||
defaultValue = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
defaultValue = true;
|
||||
break;
|
||||
}
|
||||
|
||||
mInstance->beginGroup( "Search" );
|
||||
bool returnValue = mInstance->value( "isoPaperSizes", defaultValue ).toBool();
|
||||
mInstance->endGroup();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void Settings::setSearchIsoPaperSizes( bool searchIsoPaperSizes )
|
||||
{
|
||||
mInstance->beginGroup( "Search" );
|
||||
mInstance->setValue( "isoPaperSizes", searchIsoPaperSizes );
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
|
||||
bool Settings::searchUsPaperSizes()
|
||||
{
|
||||
// Guess at a suitable default
|
||||
bool defaultValue;
|
||||
switch (QLocale::system().country())
|
||||
{
|
||||
case QLocale::UnitedStates:
|
||||
case QLocale::Canada:
|
||||
defaultValue = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
defaultValue = false;
|
||||
break;
|
||||
}
|
||||
|
||||
mInstance->beginGroup( "Search" );
|
||||
bool returnValue = mInstance->value( "usPaperSizes", defaultValue ).toBool();
|
||||
mInstance->endGroup();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void Settings::setSearchUsPaperSizes( bool searchUsPaperSizes )
|
||||
{
|
||||
mInstance->beginGroup( "Search" );
|
||||
mInstance->setValue( "usPaperSizes", searchUsPaperSizes );
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
|
||||
bool Settings::searchOtherPaperSizes()
|
||||
{
|
||||
// Guess at a suitable default
|
||||
bool defaultValue = true;
|
||||
|
||||
mInstance->beginGroup( "Search" );
|
||||
bool returnValue = mInstance->value( "otherPaperSizes", defaultValue ).toBool();
|
||||
mInstance->endGroup();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void Settings::setSearchOtherPaperSizes( bool searchOtherPaperSizes )
|
||||
{
|
||||
mInstance->beginGroup( "Search" );
|
||||
mInstance->setValue( "otherPaperSizes", searchOtherPaperSizes );
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
|
||||
bool Settings::searchAllCategories()
|
||||
{
|
||||
// Guess at a suitable default
|
||||
bool defaultValue = true;
|
||||
|
||||
mInstance->beginGroup( "Search" );
|
||||
bool returnValue = mInstance->value( "allCategories", defaultValue ).toBool();
|
||||
mInstance->endGroup();
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void Settings::setSearchAllCategories( bool searchAllCategories )
|
||||
{
|
||||
mInstance->beginGroup( "Search" );
|
||||
mInstance->setValue( "allCategories", searchAllCategories );
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
|
||||
QStringList Settings::searchCategoryList()
|
||||
{
|
||||
QStringList defaultList;
|
||||
|
||||
mInstance->beginGroup( "Search" );
|
||||
QStringList returnList = mInstance->value( "categoryList", defaultList ).toStringList();
|
||||
mInstance->endGroup();
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
|
||||
void Settings::setSearchCategoryList( const QStringList& searchCategoryList )
|
||||
{
|
||||
mInstance->beginGroup( "Search" );
|
||||
mInstance->setValue( "categoryList", searchCategoryList );
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
|
||||
QStringList Settings::recentTemplateList()
|
||||
{
|
||||
QStringList defaultList;
|
||||
|
||||
mInstance->beginGroup( "Recent" );
|
||||
QStringList returnList = mInstance->value( "templates", defaultList ).toStringList();
|
||||
mInstance->endGroup();
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
|
||||
void Settings::addToRecentTemplateList( const QString& name )
|
||||
{
|
||||
mInstance->beginGroup( "Recent" );
|
||||
|
||||
QStringList list = mInstance->value( "templates" ).toStringList();
|
||||
|
||||
list.removeAll( name );
|
||||
list.prepend( name );
|
||||
while ( list.count() > 10 )
|
||||
{
|
||||
list.removeLast();
|
||||
}
|
||||
|
||||
mInstance->setValue( "templates", list );
|
||||
|
||||
mInstance->endGroup();
|
||||
|
||||
emit mInstance->changed();
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,97 @@
|
||||
/* Settings.h
|
||||
*
|
||||
* Copyright (C) 2016 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 model_Settings_h
|
||||
#define model_Settings_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Settings Singleton Class
|
||||
///
|
||||
class Settings : public QSettings
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class PageSizeFamilty { ISO, US, };
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Life Cycle
|
||||
/////////////////////////////////
|
||||
private:
|
||||
Settings();
|
||||
|
||||
public:
|
||||
static void init();
|
||||
static Settings* instance();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Signals
|
||||
/////////////////////////////////
|
||||
signals:
|
||||
void changed();
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Accessors
|
||||
/////////////////////////////////
|
||||
public:
|
||||
static Units units();
|
||||
static void setUnits( const Units& units );
|
||||
|
||||
static bool searchIsoPaperSizes();
|
||||
static void setSearchIsoPaperSizes( bool searchIsoPaperSizes );
|
||||
|
||||
static bool searchUsPaperSizes();
|
||||
static void setSearchUsPaperSizes( bool searchUsPaperSizes );
|
||||
|
||||
static bool searchOtherPaperSizes();
|
||||
static void setSearchOtherPaperSizes( bool searchOtherPaperSizes );
|
||||
|
||||
static bool searchAllCategories();
|
||||
static void setSearchAllCategories( bool searchAllCategories );
|
||||
|
||||
static QStringList searchCategoryList();
|
||||
static void setSearchCategoryList( const QStringList& searchCategoryList );
|
||||
|
||||
static QStringList recentTemplateList();
|
||||
static void addToRecentTemplateList( const QString& name );
|
||||
|
||||
|
||||
private:
|
||||
static Settings* mInstance;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Settings_h
|
||||
@@ -0,0 +1,94 @@
|
||||
/* Size.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Size.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
Size::Size() : mW(0), mH(0)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
Size::Size( const Distance& w, const Distance& h ) : mW(w), mH(h)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get w
|
||||
///
|
||||
Distance Size::w() const
|
||||
{
|
||||
return mW;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Set w
|
||||
///
|
||||
void Size::setW( const Distance& value )
|
||||
{
|
||||
mW = value;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get h
|
||||
///
|
||||
Distance Size::h() const
|
||||
{
|
||||
return mH;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Set h
|
||||
///
|
||||
void Size::setH( const Distance& value )
|
||||
{
|
||||
mH = value;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Convert to a QSizeF
|
||||
///
|
||||
QSizeF Size::qSizeF() const
|
||||
{
|
||||
QSizeF s;
|
||||
|
||||
s.setWidth( mW.pt() );
|
||||
s.setHeight( mH.pt() );
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Size.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 model_Size_h
|
||||
#define model_Size_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
#include <QSizeF>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Size Type
|
||||
///
|
||||
class Size
|
||||
{
|
||||
|
||||
/////////////////////////////////
|
||||
// Constructors
|
||||
/////////////////////////////////
|
||||
public:
|
||||
Size();
|
||||
Size( const Distance& w, const Distance& h );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Properties
|
||||
/////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// w Property
|
||||
//
|
||||
Distance w() const;
|
||||
void setW( const Distance& value );
|
||||
|
||||
|
||||
//
|
||||
// H Property
|
||||
//
|
||||
Distance h() const;
|
||||
void setH( const Distance& value );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Methods
|
||||
/////////////////////////////////
|
||||
public:
|
||||
QSizeF qSizeF() const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
Distance mW;
|
||||
Distance mH;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Size_h
|
||||
@@ -0,0 +1,211 @@
|
||||
/* StrUtil.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "StrUtil.h"
|
||||
|
||||
#include <QtMath>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
namespace
|
||||
{
|
||||
const double FRAC_EPSILON = 0.00005;
|
||||
const double denom[] = { 1.0, 2.0, 3.0, 4.0, 8.0, 16.0, 32.0, 0.0 };
|
||||
const char* denom_string[] = { "1", "₂", "₃", "₄", "₈", "₁₆", "₃₂", nullptr };
|
||||
const char* num_string[] = { "⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹",
|
||||
"¹⁰", "¹¹", "¹²", "¹³", "¹⁴", "¹⁵", "¹⁶", "¹⁷", "¹⁸", "¹⁹",
|
||||
"²⁰", "²¹", "²²", "²³", "²⁴", "²⁵", "²⁶", "²⁷", "²⁸", "²⁹",
|
||||
"³⁰", "³¹" };
|
||||
}
|
||||
|
||||
|
||||
namespace StrUtil
|
||||
{
|
||||
|
||||
QString formatFraction( double x )
|
||||
{
|
||||
int i;
|
||||
double product, remainder;
|
||||
|
||||
for ( i=0; denom[i] != 0.0; i++ )
|
||||
{
|
||||
product = x * denom[i];
|
||||
remainder = qFabs(product - ((int)(product+0.5)));
|
||||
if ( remainder < FRAC_EPSILON ) break;
|
||||
}
|
||||
|
||||
if ( denom[i] == 0.0 )
|
||||
{
|
||||
/* None of our denominators work. */
|
||||
return QString().sprintf( "%.5g", x );
|
||||
}
|
||||
if ( denom[i] == 1.0 )
|
||||
{
|
||||
/* Simple integer. */
|
||||
return QString().sprintf( "%.0f", x );
|
||||
}
|
||||
int n = (int)( x * denom[i] + 0.5 );
|
||||
int d = (int)denom[i];
|
||||
if ( n > d )
|
||||
{
|
||||
return QString::number(n/d) +
|
||||
QString::fromUtf8(num_string[n%d]) + "/" + QString::fromUtf8(denom_string[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString::fromUtf8(num_string[n%d]) + "/" + QString::fromUtf8(denom_string[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString spanDigits( const QString &s, int *i )
|
||||
{
|
||||
QString chunk;
|
||||
|
||||
for ( int j = *i; (j < s.size()) && s.at(j).isNumber(); j++ )
|
||||
{
|
||||
chunk.append( s.at(j) );
|
||||
*i = j+1; /* only advance i, if character is used. */
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
|
||||
QString spanNonDigits( const QString &s, int *i )
|
||||
{
|
||||
QString chunk;
|
||||
|
||||
for ( int j = *i; (j < s.size()) && !s.at(j).isNumber(); j++ )
|
||||
{
|
||||
chunk.append( s.at(j) );
|
||||
*i = j+1; /* only advance i, if character is used. */
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compare part names
|
||||
* @s1: string to compare with s2.
|
||||
* @s2: string to compare with s1.
|
||||
*
|
||||
* Compare two strings representing part names or numbers. This function
|
||||
* uses a natural sort order:
|
||||
*
|
||||
* - Ignores case.
|
||||
*
|
||||
* - Strings are divided into chunks (numeric and non-numeric)
|
||||
*
|
||||
* - Non-numeric chunks are compared character by character
|
||||
*
|
||||
* - Numerical chunks are compared numerically, so that "20" precedes "100".
|
||||
*
|
||||
* - Comparison of chunks is performed left to right until the first difference
|
||||
* is encountered or all chunks evaluate as equal.
|
||||
*
|
||||
* Numeric chunks are converted to 64 bit unsigned integers for comparison,
|
||||
* so the behaviour may be unpredictable for numeric chunks that exceed
|
||||
* 18446744073709551615.
|
||||
*
|
||||
* Returns: 0 if the strings match, a negative value if s1 < s2,
|
||||
* or a positive value if s1 > s2.
|
||||
*
|
||||
*/
|
||||
int comparePartNames( const QString &s1, const QString &s2 )
|
||||
{
|
||||
if ( s1 == s2 ) return 0;
|
||||
if ( s1 == "" ) return -1;
|
||||
if ( s2 == "" ) return 1;
|
||||
|
||||
QString folded_s1 = s1.toUpper();
|
||||
QString folded_s2 = s2.toUpper();
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 0;
|
||||
int result = 0;
|
||||
bool done = false;
|
||||
|
||||
while ( (result == 0) && !done )
|
||||
{
|
||||
QString chunk1, chunk2;
|
||||
bool isnum1, isnum2;
|
||||
|
||||
if ( (i1 < folded_s1.size()) && folded_s1.at( i1 ).isNumber() )
|
||||
{
|
||||
chunk1 = spanDigits( folded_s1, &i1 );
|
||||
isnum1 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk1 = spanNonDigits( folded_s1, &i1 );
|
||||
isnum1 = false;
|
||||
}
|
||||
|
||||
if ( (i2 < folded_s2.size()) && folded_s2.at( i2 ).isNumber() )
|
||||
{
|
||||
chunk2 = spanDigits( folded_s2, &i2 );
|
||||
isnum2 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
chunk2 = spanNonDigits( folded_s2, &i2 );
|
||||
isnum2 = false;
|
||||
}
|
||||
|
||||
|
||||
if ( ( chunk1 == "" ) && ( chunk2 == "" ) )
|
||||
{
|
||||
/* Case 1: Both are empty. */
|
||||
done = true;
|
||||
}
|
||||
else if ( isnum1 && isnum2 )
|
||||
{
|
||||
/* Case 2: They both contain numbers */
|
||||
qlonglong n1 = chunk1.toLongLong();
|
||||
qlonglong n2 = chunk2.toLongLong();
|
||||
|
||||
if ( n1 < n2 ) result = -1;
|
||||
else if ( n1 > n2 ) result = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Case 3: One or both do not contain numbers */
|
||||
if ( chunk1 < chunk2 ) result = -1;
|
||||
else if( chunk1 > chunk2 ) result = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,43 @@
|
||||
/* StrUtil.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_StrUtil_h
|
||||
#define model_StrUtil_h
|
||||
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
namespace StrUtil
|
||||
{
|
||||
|
||||
QString formatFraction( double x );
|
||||
|
||||
int comparePartNames( const QString &s1, const QString &s2 );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_StrUtil_h
|
||||
@@ -0,0 +1,331 @@
|
||||
/* SubstitutionField.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 "SubstitutionField.h"
|
||||
|
||||
#include <QTextStream>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
SubstitutionField::SubstitutionField()
|
||||
: mNewLine(false), mFormatType(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
SubstitutionField::SubstitutionField( const QString& string )
|
||||
: mNewLine(false), mFormatType(0)
|
||||
{
|
||||
QStringRef s(&string);
|
||||
parse( s, *this );
|
||||
}
|
||||
|
||||
|
||||
QString SubstitutionField::evaluate( const merge::Record* record ) const
|
||||
{
|
||||
QString value = mDefaultValue;
|
||||
|
||||
if ( record && record->contains(mFieldName) && !record->value(mFieldName).isEmpty() )
|
||||
{
|
||||
value = record->value(mFieldName);
|
||||
}
|
||||
|
||||
if ( !mFormatType.isNull() )
|
||||
{
|
||||
value = formatValue( value );
|
||||
}
|
||||
|
||||
if ( record && record->contains(mFieldName) && !record->value(mFieldName).isEmpty() && mNewLine )
|
||||
{
|
||||
value = "\n" + value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
QString SubstitutionField::fieldName() const
|
||||
{
|
||||
return mFieldName;
|
||||
}
|
||||
|
||||
|
||||
QString SubstitutionField::defaultValue() const
|
||||
{
|
||||
return mDefaultValue;
|
||||
}
|
||||
|
||||
|
||||
QString SubstitutionField::format() const
|
||||
{
|
||||
return mFormat;
|
||||
}
|
||||
|
||||
|
||||
QChar SubstitutionField::formatType() const
|
||||
{
|
||||
return mFormatType;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::newLine() const
|
||||
{
|
||||
return mNewLine;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parse( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
QStringRef sTmp = s;
|
||||
|
||||
if ( sTmp.startsWith( "${" ) )
|
||||
{
|
||||
sTmp = sTmp.mid(2);
|
||||
|
||||
if ( parseFieldName( sTmp, field ) )
|
||||
{
|
||||
while ( sTmp.size() && sTmp[0] == ':' )
|
||||
{
|
||||
sTmp = sTmp.mid(1);
|
||||
if ( !parseModifier( sTmp, field ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( sTmp.size() && sTmp[0] == '}' )
|
||||
{
|
||||
sTmp = sTmp.mid(1);
|
||||
|
||||
// Success. Update s.
|
||||
s = sTmp;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseFieldName( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
while ( s.size() && (s[0].isDigit() || s[0].isLetter() || s[0] == '_' || s[0] == '-') )
|
||||
{
|
||||
field.mFieldName.append( s[0] );
|
||||
s = s.mid(1);
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseModifier( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if ( s.size() && s[0] == '%' )
|
||||
{
|
||||
s = s.mid(1);
|
||||
success = parseFormatModifier( s, field );
|
||||
}
|
||||
else if ( s.size() && s[0] == '=' )
|
||||
{
|
||||
s = s.mid(1);
|
||||
success = parseDefaultValueModifier( s, field );
|
||||
}
|
||||
else if ( s.size() && s[0] == 'n' )
|
||||
{
|
||||
s = s.mid(1);
|
||||
success = parseNewLineModifier( s, field );
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseDefaultValueModifier( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
field.mDefaultValue.clear();
|
||||
|
||||
while ( s.size() && !QString( ":}" ).contains( s[0] ) )
|
||||
{
|
||||
if ( s[0] == '\\' )
|
||||
{
|
||||
s = s.mid(1); // Skip escape
|
||||
if ( s.size() )
|
||||
{
|
||||
field.mDefaultValue.append( s[0] );
|
||||
s = s.mid(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
field.mDefaultValue.append( s[0] );
|
||||
s = s.mid(1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseFormatModifier( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
field.mFormat = "%";
|
||||
|
||||
parseFormatFlags( s, field );
|
||||
parseFormatWidth( s, field );
|
||||
|
||||
if ( s.size() && s[0] == '.' )
|
||||
{
|
||||
field.mFormat += ".";
|
||||
s = s.mid(1);
|
||||
parseFormatPrecision( s, field );
|
||||
}
|
||||
|
||||
parseFormatType( s, field );
|
||||
|
||||
return true; // Don't let invalid formats kill entire SubstitutionField
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseFormatFlags( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
while ( s.size() && QString( "-+ 0" ).contains( s[0] ) )
|
||||
{
|
||||
field.mFormat += s[0];
|
||||
s = s.mid(1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseFormatWidth( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
return parseNaturalInteger( s, field );
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseFormatPrecision( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
return parseNaturalInteger( s, field );
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseFormatType( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if ( s.size() && QString( "diufFeEgGxXos" ).contains( s[0] ) )
|
||||
{
|
||||
field.mFormatType = s[0];
|
||||
field.mFormat += s[0];
|
||||
s = s.mid(1);
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseNaturalInteger( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if ( s.size() && s[0] >= '1' && s[0] <= '9' )
|
||||
{
|
||||
field.mFormat += s[0];
|
||||
s = s.mid(1);
|
||||
|
||||
while ( s.size() && s[0].isDigit() )
|
||||
{
|
||||
field.mFormat += s[0];
|
||||
s = s.mid(1);
|
||||
}
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool SubstitutionField::parseNewLineModifier( QStringRef& s, SubstitutionField& field )
|
||||
{
|
||||
field.mNewLine = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QString SubstitutionField::formatValue( const QString& value ) const
|
||||
{
|
||||
switch (mFormatType.unicode())
|
||||
{
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
return QString::asprintf( mFormat.toStdString().c_str(),
|
||||
value.toLongLong(nullptr,0) );
|
||||
break;
|
||||
|
||||
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X':
|
||||
case 'o':
|
||||
return QString::asprintf( mFormat.toStdString().c_str(),
|
||||
value.toULongLong(nullptr,0) );
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
return QString::asprintf( mFormat.toStdString().c_str(),
|
||||
value.toDouble() );
|
||||
break;
|
||||
|
||||
case 's':
|
||||
return QString::asprintf( mFormat.toStdString().c_str(),
|
||||
value.toStdString().c_str() );
|
||||
break;
|
||||
|
||||
default:
|
||||
// Invalid format
|
||||
return "";
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,77 @@
|
||||
/* SubstitutionField.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 model_SubstitutionField_h
|
||||
#define model_SubstitutionField_h
|
||||
|
||||
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringRef>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class SubstitutionField
|
||||
{
|
||||
public:
|
||||
SubstitutionField();
|
||||
SubstitutionField( const QString& string );
|
||||
|
||||
QString evaluate( const merge::Record* record ) const;
|
||||
|
||||
QString fieldName() const;
|
||||
QString defaultValue() const;
|
||||
QString format() const;
|
||||
QChar formatType() const;
|
||||
bool newLine() const;
|
||||
|
||||
static bool parse( QStringRef& s, SubstitutionField& field );
|
||||
|
||||
private:
|
||||
static bool parseFieldName( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseModifier( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseDefaultValueModifier( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseFormatModifier( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseFormatFlags( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseFormatWidth( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseFormatPrecision( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseFormatType( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseNaturalInteger( QStringRef& s, SubstitutionField& field );
|
||||
static bool parseNewLineModifier( QStringRef& s, SubstitutionField& field );
|
||||
|
||||
QString formatValue( const QString& value ) const;
|
||||
|
||||
QString mFieldName;
|
||||
|
||||
QString mDefaultValue;
|
||||
|
||||
QString mFormat;
|
||||
QChar mFormatType;
|
||||
|
||||
bool mNewLine;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_SubstitutionField_h
|
||||
@@ -0,0 +1,288 @@
|
||||
/* Template.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Template.h"
|
||||
|
||||
#include "Db.h"
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Template::Template( const QString& brand,
|
||||
const QString& part,
|
||||
const QString& description,
|
||||
const QString& paperId,
|
||||
const Distance& pageWidth,
|
||||
const Distance& pageHeight )
|
||||
: mBrand(brand),
|
||||
mPart(part),
|
||||
mDescription(description),
|
||||
mPaperId(paperId),
|
||||
mPageWidth(pageWidth),
|
||||
mPageHeight(pageHeight),
|
||||
mIsSizeIso(false),
|
||||
mIsSizeUs(false),
|
||||
mName("")
|
||||
{
|
||||
mName.append( brand ).append( " " ).append( part );
|
||||
|
||||
if ( Db::isPaperIdKnown( paperId ) )
|
||||
{
|
||||
const Paper* paper = Db::lookupPaperFromId( paperId );
|
||||
mIsSizeIso = paper->isSizeIso();
|
||||
mIsSizeUs = paper->isSizeUs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Template::Template( const Template& other )
|
||||
{
|
||||
mBrand = other.mBrand;
|
||||
mPart = other.mPart;
|
||||
mDescription = other.mDescription;
|
||||
mPaperId = other.mPaperId;
|
||||
mPageWidth = other.mPageWidth;
|
||||
mPageHeight = other.mPageHeight;
|
||||
mIsSizeIso = other.mIsSizeIso;
|
||||
mIsSizeUs = other.mIsSizeUs;
|
||||
mEquivPart = other.mEquivPart;
|
||||
mName = other.mName;
|
||||
mProductUrl = other.mProductUrl;
|
||||
|
||||
foreach ( Frame* frame, other.mFrames )
|
||||
{
|
||||
addFrame( frame );
|
||||
}
|
||||
|
||||
foreach ( QString categoryId, other.mCategoryIds )
|
||||
{
|
||||
addCategory( categoryId );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Template* Template::dup() const
|
||||
{
|
||||
return new Template( *this );
|
||||
}
|
||||
|
||||
|
||||
// Generic full page template
|
||||
Template* Template::fullPage( const QString& paperId )
|
||||
{
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// From equivalent part number
|
||||
Template* Template::fromEquiv( const QString& brand,
|
||||
const QString& part,
|
||||
const QString& equivPart )
|
||||
{
|
||||
const Template* other = Db::lookupTemplateFromBrandPart( brand, equivPart );
|
||||
if ( other != nullptr )
|
||||
{
|
||||
Template* tmplate = other->dup();
|
||||
|
||||
tmplate->mPart = part;
|
||||
tmplate->mEquivPart = equivPart;
|
||||
|
||||
tmplate->mName = "";
|
||||
tmplate->mName.append( brand ).append( " " ).append( part );
|
||||
|
||||
return tmplate;
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Error: cannot create equivalent template for "
|
||||
<< brand << ", " << equivPart
|
||||
<< ". Forward references not supported.";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString Template::brand() const
|
||||
{
|
||||
return mBrand;
|
||||
}
|
||||
|
||||
|
||||
QString Template::part() const
|
||||
{
|
||||
return mPart;
|
||||
}
|
||||
|
||||
|
||||
QString Template::description() const
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
|
||||
QString Template::paperId() const
|
||||
{
|
||||
return mPaperId;
|
||||
}
|
||||
|
||||
|
||||
Distance Template::pageWidth() const
|
||||
{
|
||||
return mPageWidth;
|
||||
}
|
||||
|
||||
|
||||
Distance Template::pageHeight() const
|
||||
{
|
||||
return mPageHeight;
|
||||
}
|
||||
|
||||
|
||||
bool Template::isSizeIso() const
|
||||
{
|
||||
return mIsSizeIso;
|
||||
}
|
||||
|
||||
|
||||
bool Template::isSizeUs() const
|
||||
{
|
||||
return mIsSizeUs;
|
||||
}
|
||||
|
||||
|
||||
bool Template::isSizeOther() const
|
||||
{
|
||||
return !mIsSizeIso && !mIsSizeUs;
|
||||
}
|
||||
|
||||
|
||||
QString Template::equivPart() const
|
||||
{
|
||||
return mEquivPart;
|
||||
}
|
||||
|
||||
|
||||
void Template::setEquivPart( const QString& value )
|
||||
{
|
||||
mEquivPart = value;
|
||||
}
|
||||
|
||||
|
||||
QString Template::productUrl() const
|
||||
{
|
||||
return mProductUrl;
|
||||
}
|
||||
|
||||
|
||||
void Template::setProductUrl( const QString& value )
|
||||
{
|
||||
mProductUrl = value;
|
||||
}
|
||||
|
||||
|
||||
QString Template::name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
|
||||
const QList<Frame*>& Template::frames() const
|
||||
{
|
||||
return mFrames;
|
||||
}
|
||||
|
||||
|
||||
void Template::addCategory( const QString& categoryId )
|
||||
{
|
||||
mCategoryIds << categoryId;
|
||||
}
|
||||
|
||||
|
||||
void Template::addFrame( Frame* frame )
|
||||
{
|
||||
mFrames << frame;
|
||||
}
|
||||
|
||||
|
||||
bool Template::operator==( const Template& other ) const
|
||||
{
|
||||
return (mBrand == other.mBrand) && (mPart == other.mPart);
|
||||
}
|
||||
|
||||
|
||||
bool Template::hasCategory( const QString& categoryId ) const
|
||||
{
|
||||
foreach ( QString testCategoryId, mCategoryIds )
|
||||
{
|
||||
if ( categoryId == testCategoryId )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Template::isSimilarTo( const Template* other ) const
|
||||
{
|
||||
// Does page size match?
|
||||
if ( (mPaperId != other->mPaperId) ||
|
||||
(mPageWidth != other->mPageWidth ) ||
|
||||
(mPageHeight != other->mPageHeight ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Are frames similar
|
||||
Frame* frame1 = mFrames.first();
|
||||
Frame* frame2 = other->mFrames.first();
|
||||
if ( !frame1->isSimilarTo( frame2 ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Are they layed out similarly?
|
||||
foreach ( Layout* layout1, frame1->layouts() )
|
||||
{
|
||||
bool matchFound = false;
|
||||
foreach ( Layout* layout2, frame2->layouts() )
|
||||
{
|
||||
if ( layout1->isSimilarTo(layout2) )
|
||||
{
|
||||
matchFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !matchFound )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,117 @@
|
||||
/* Template.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Template_h
|
||||
#define model_Template_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
#include "Frame.h"
|
||||
#include "Point.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QList>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Template
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Template)
|
||||
|
||||
public:
|
||||
|
||||
Template( const QString& brand,
|
||||
const QString& part,
|
||||
const QString& description,
|
||||
const QString& paperId,
|
||||
const Distance& pageWidth,
|
||||
const Distance& pageHeight );
|
||||
|
||||
Template( const Template& other );
|
||||
|
||||
Template* dup() const;
|
||||
|
||||
// Generic full page template
|
||||
static Template* fullPage( const QString& paperId );
|
||||
|
||||
// From equivalent part number
|
||||
static Template* fromEquiv( const QString& brand,
|
||||
const QString& part,
|
||||
const QString& equivPart );
|
||||
|
||||
|
||||
QString brand() const;
|
||||
QString part() const;
|
||||
QString description() const;
|
||||
|
||||
QString paperId() const;
|
||||
Distance pageWidth() const;
|
||||
Distance pageHeight() const;
|
||||
bool isSizeIso() const;
|
||||
bool isSizeUs() const;
|
||||
bool isSizeOther() const;
|
||||
|
||||
QString equivPart() const;
|
||||
void setEquivPart( const QString& value );
|
||||
|
||||
QString productUrl() const;
|
||||
void setProductUrl( const QString& value );
|
||||
|
||||
QString name() const;
|
||||
|
||||
void addCategory( const QString& categoryId );
|
||||
void addFrame( Frame* frame );
|
||||
|
||||
const QList<Frame*>& frames() const;
|
||||
|
||||
bool operator==( const Template& other ) const;
|
||||
|
||||
bool hasCategory( const QString& categoryId ) const;
|
||||
bool isSimilarTo( const Template* other ) const;
|
||||
|
||||
|
||||
private:
|
||||
QString mBrand;
|
||||
QString mPart;
|
||||
QString mDescription;
|
||||
|
||||
QString mPaperId;
|
||||
Distance mPageWidth;
|
||||
Distance mPageHeight;
|
||||
bool mIsSizeIso;
|
||||
bool mIsSizeUs;
|
||||
|
||||
QString mEquivPart;
|
||||
QString mName;
|
||||
|
||||
QString mProductUrl;
|
||||
QStringList mCategoryIds;
|
||||
|
||||
QList<Frame*> mFrames;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Template_h
|
||||
@@ -0,0 +1,149 @@
|
||||
/* TextNode.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 "TextNode.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Default Constructor
|
||||
///
|
||||
TextNode::TextNode()
|
||||
: mIsField(false), mData("")
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Constructor from Data
|
||||
///
|
||||
TextNode::TextNode( bool isField, const QString &data )
|
||||
: mIsField(isField), mData(data)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// == Operator
|
||||
///
|
||||
bool TextNode::operator==( const TextNode& other )
|
||||
{
|
||||
return (mIsField == other.mIsField) &&
|
||||
(mData == other.mData);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// != Operator
|
||||
///
|
||||
bool TextNode::operator!=( const TextNode& other )
|
||||
{
|
||||
return (mIsField != other.mIsField) ||
|
||||
(mData != other.mData);
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// isField? Property Getter
|
||||
///
|
||||
bool TextNode::isField() const
|
||||
{
|
||||
return mIsField;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// isField Flag Property Setter
|
||||
///
|
||||
void TextNode::setField( bool isField )
|
||||
{
|
||||
mIsField = isField;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Data Property Getter
|
||||
///
|
||||
const QString& TextNode::data() const
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Data Property Setter
|
||||
///
|
||||
void TextNode::setData( const QString& data )
|
||||
{
|
||||
mData = data;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Get text, expand if necessary
|
||||
///
|
||||
QString TextNode::text( merge::Record* record ) const
|
||||
{
|
||||
if ( mIsField )
|
||||
{
|
||||
if ( !record )
|
||||
{
|
||||
return QString("${%1}").arg( mData );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( record->contains( mData ) )
|
||||
{
|
||||
return (*record)[ mData ];
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return mData;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Is it an empty field
|
||||
///
|
||||
bool TextNode::isEmptyField( merge::Record* record ) const
|
||||
{
|
||||
if ( record && mIsField )
|
||||
{
|
||||
if ( record->contains( mData ) )
|
||||
{
|
||||
return (*record)[mData].isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,94 @@
|
||||
/* TextNode.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 model_TextNode_h
|
||||
#define model_TextNode_h
|
||||
|
||||
|
||||
#include "merge/Record.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
///
|
||||
/// Text Node Type
|
||||
///
|
||||
struct TextNode
|
||||
{
|
||||
|
||||
/////////////////////////////////
|
||||
// Life Cycle
|
||||
/////////////////////////////////
|
||||
public:
|
||||
TextNode();
|
||||
|
||||
TextNode( bool isField, const QString &data );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Operators
|
||||
/////////////////////////////////
|
||||
public:
|
||||
bool operator==( const TextNode& other );
|
||||
|
||||
bool operator!=( const TextNode& other );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Properties
|
||||
/////////////////////////////////
|
||||
public:
|
||||
//
|
||||
// is field? Property
|
||||
//
|
||||
bool isField() const;
|
||||
void setField( bool isField );
|
||||
|
||||
//
|
||||
// Data Property
|
||||
//
|
||||
const QString& data() const;
|
||||
void setData( const QString& data );
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Misc. Methods
|
||||
/////////////////////////////////
|
||||
QString text( merge::Record* record ) const;
|
||||
bool isEmptyField( merge::Record* record ) const;
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// Private Data
|
||||
/////////////////////////////////
|
||||
private:
|
||||
|
||||
bool mIsField;
|
||||
QString mData;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_TextNode_h
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
/* Units.cpp
|
||||
*
|
||||
* Copyright (C) 2016 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 "Units.h"
|
||||
|
||||
#include <QTextStream>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
|
||||
Units::Units() : mEnumValue(PT)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
Units::Units( Units::Enum enumValue ) : mEnumValue(enumValue)
|
||||
{
|
||||
switch (enumValue)
|
||||
{
|
||||
case PT:
|
||||
case IN:
|
||||
case MM:
|
||||
case CM:
|
||||
case PC:
|
||||
/* Catch all valid enum values. */
|
||||
break;
|
||||
default:
|
||||
/* Catch invalid enum values, reset to PT. */
|
||||
qWarning() << "Bad Units::Enum value = " << enumValue << ".";
|
||||
mEnumValue = PT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Units::Units( const QString& idString )
|
||||
{
|
||||
if ( idString == "pt" )
|
||||
{
|
||||
mEnumValue = PT;
|
||||
}
|
||||
else if ( idString == "in" )
|
||||
{
|
||||
mEnumValue = IN;
|
||||
}
|
||||
else if ( idString == "mm" )
|
||||
{
|
||||
mEnumValue = MM;
|
||||
}
|
||||
else if ( idString == "cm" )
|
||||
{
|
||||
mEnumValue = CM;
|
||||
}
|
||||
else if ( idString == "pc" )
|
||||
{
|
||||
mEnumValue = PC;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEnumValue = PT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Units Units::pt()
|
||||
{
|
||||
return Units(PT);
|
||||
}
|
||||
|
||||
|
||||
Units Units::in()
|
||||
{
|
||||
return Units(IN);
|
||||
}
|
||||
|
||||
|
||||
Units Units::mm()
|
||||
{
|
||||
return Units(MM);
|
||||
}
|
||||
|
||||
|
||||
Units Units::cm()
|
||||
{
|
||||
return Units(CM);
|
||||
}
|
||||
|
||||
|
||||
Units Units::pc()
|
||||
{
|
||||
return Units(PC);
|
||||
}
|
||||
|
||||
|
||||
Units::Enum Units::toEnum() const
|
||||
{
|
||||
return mEnumValue;
|
||||
}
|
||||
|
||||
|
||||
QString Units::toIdString() const
|
||||
{
|
||||
QString idString;
|
||||
|
||||
switch (mEnumValue)
|
||||
{
|
||||
case Units::PT:
|
||||
idString = "pt";
|
||||
break;
|
||||
case Units::IN:
|
||||
idString = "in";
|
||||
break;
|
||||
case Units::MM:
|
||||
idString = "mm";
|
||||
break;
|
||||
case Units::CM:
|
||||
idString = "cm";
|
||||
break;
|
||||
case Units::PC:
|
||||
idString = "pc";
|
||||
break;
|
||||
}
|
||||
|
||||
return idString;
|
||||
}
|
||||
|
||||
|
||||
QString Units::toTrName() const
|
||||
{
|
||||
QString nameString;
|
||||
|
||||
switch (mEnumValue)
|
||||
{
|
||||
case Units::PT:
|
||||
nameString = tr("points");
|
||||
break;
|
||||
case Units::IN:
|
||||
nameString = tr("inches");
|
||||
break;
|
||||
case Units::MM:
|
||||
nameString = tr("mm");
|
||||
break;
|
||||
case Units::CM:
|
||||
nameString = tr("cm");
|
||||
break;
|
||||
case Units::PC:
|
||||
nameString = tr("picas");
|
||||
break;
|
||||
}
|
||||
|
||||
return nameString;
|
||||
}
|
||||
|
||||
|
||||
double Units::resolution() const
|
||||
{
|
||||
double value;
|
||||
|
||||
switch (mEnumValue)
|
||||
{
|
||||
case Units::PT:
|
||||
value = 0.01;
|
||||
break;
|
||||
case Units::IN:
|
||||
value = 0.001;
|
||||
break;
|
||||
case Units::MM:
|
||||
value = 0.01;
|
||||
break;
|
||||
case Units::CM:
|
||||
value = 0.001;
|
||||
break;
|
||||
case Units::PC:
|
||||
value = 0.01;
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
int Units::resolutionDigits() const
|
||||
{
|
||||
int digits;
|
||||
|
||||
switch (mEnumValue)
|
||||
{
|
||||
case Units::PT:
|
||||
digits = 2;
|
||||
break;
|
||||
case Units::IN:
|
||||
digits = 3;
|
||||
break;
|
||||
case Units::MM:
|
||||
digits = 2;
|
||||
break;
|
||||
case Units::CM:
|
||||
digits = 3;
|
||||
break;
|
||||
case Units::PC:
|
||||
digits = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return digits;
|
||||
}
|
||||
|
||||
|
||||
bool Units::isIdValid( const QString& idString )
|
||||
{
|
||||
bool retValue = false;
|
||||
|
||||
if ( idString == "pt" )
|
||||
{
|
||||
retValue = true;
|
||||
}
|
||||
else if ( idString == "in" )
|
||||
{
|
||||
retValue = true;
|
||||
}
|
||||
else if ( idString == "mm" )
|
||||
{
|
||||
retValue = true;
|
||||
}
|
||||
else if ( idString == "cm" )
|
||||
{
|
||||
retValue = true;
|
||||
}
|
||||
else if ( idString == "pc" )
|
||||
{
|
||||
retValue = true;
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,69 @@
|
||||
/* Units.h
|
||||
*
|
||||
* Copyright (C) 2016 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 model_Units_h
|
||||
#define model_Units_h
|
||||
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
|
||||
class Units
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Units)
|
||||
|
||||
public:
|
||||
enum Enum { PT, IN, MM, CM, PC };
|
||||
|
||||
Units();
|
||||
Units( Enum enumValue );
|
||||
Units( const QString& idString );
|
||||
|
||||
static Units pt();
|
||||
static Units in();
|
||||
static Units mm();
|
||||
static Units cm();
|
||||
static Units pc();
|
||||
|
||||
Enum toEnum() const;
|
||||
|
||||
QString toIdString() const;
|
||||
QString toTrName() const;
|
||||
|
||||
double resolution() const;
|
||||
int resolutionDigits() const;
|
||||
|
||||
static bool isIdValid( const QString& unitsId );
|
||||
|
||||
|
||||
private:
|
||||
Enum mEnumValue;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Units_h
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Vendor.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "Vendor.h"
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Vendor::Vendor( const QString &name, const QString &url ) : mName(name), mUrl(url)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
QString Vendor::name() const
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
|
||||
QString Vendor::url() const
|
||||
{
|
||||
return mUrl;
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,47 @@
|
||||
/* Vendor.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_Vendor_h
|
||||
#define model_Vendor_h
|
||||
|
||||
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class Vendor
|
||||
{
|
||||
public:
|
||||
Vendor( const QString &name, const QString &url );
|
||||
|
||||
QString name() const;
|
||||
QString url() const;
|
||||
|
||||
private:
|
||||
QString mName;
|
||||
QString mUrl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Vendor_h
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Version.h
|
||||
*
|
||||
* Copyright (C) 2016 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 model_Version_h
|
||||
#define model_Version_h
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
namespace Version
|
||||
{
|
||||
const QString WEBSITE = "@Website@";
|
||||
|
||||
const int MAJOR = @Major_Version@;
|
||||
const int MINOR = @Minor_Version@;
|
||||
const int MICRO = @Micro_Version@;
|
||||
|
||||
const QString STRING = "@Full_Version@";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // model_Version_h
|
||||
@@ -0,0 +1,103 @@
|
||||
/* XmlCategoryParser.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "XmlCategoryParser.h"
|
||||
|
||||
#include "Category.h"
|
||||
#include "Db.h"
|
||||
#include "XmlUtil.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomNode>
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
bool XmlCategoryParser::readFile( const QString &fileName )
|
||||
{
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::ReadOnly | QFile::Text) )
|
||||
{
|
||||
qWarning() << "Error: Cannot read file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QDomDocument doc;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( &file, false, &errorString, &errorLine, &errorColumn ) )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-categories" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-categories file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
parseRootNode( root );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void XmlCategoryParser::parseRootNode( const QDomElement &node )
|
||||
{
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Category" )
|
||||
{
|
||||
parseCategoryNode( child.toElement() );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlCategoryParser::parseCategoryNode( const QDomElement &node )
|
||||
{
|
||||
QString id = XmlUtil::getStringAttr( node, "id", "" );
|
||||
QString name = XmlUtil::getI18nAttr( node, "name", "" );
|
||||
|
||||
Category *category = new Category( id, name );
|
||||
if ( category != nullptr )
|
||||
{
|
||||
Db::registerCategory( category );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,47 @@
|
||||
/* XmlCategoryParser.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_XmlCategoryParser_h
|
||||
#define model_XmlCategoryParser_h
|
||||
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class XmlCategoryParser
|
||||
{
|
||||
public:
|
||||
XmlCategoryParser() {}
|
||||
|
||||
bool readFile( const QString &fileName );
|
||||
|
||||
private:
|
||||
void parseRootNode( const QDomElement &node );
|
||||
void parseCategoryNode( const QDomElement &node );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlCategoryParser_h
|
||||
@@ -0,0 +1,521 @@
|
||||
/* XmlLabelCreator.cpp
|
||||
*
|
||||
* Copyright (C) 2014 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 "XmlLabelCreator.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelObject.h"
|
||||
#include "ModelBarcodeObject.h"
|
||||
#include "ModelBoxObject.h"
|
||||
#include "ModelEllipseObject.h"
|
||||
#include "ModelLineObject.h"
|
||||
#include "ModelImageObject.h"
|
||||
#include "ModelTextObject.h"
|
||||
#include "DataCache.h"
|
||||
#include "XmlTemplateCreator.h"
|
||||
#include "XmlUtil.h"
|
||||
|
||||
#include "merge/None.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QTextBlock>
|
||||
#include <QTextDocument>
|
||||
#include <QBuffer>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
void
|
||||
XmlLabelCreator::writeFile( const Model* label, const QString& fileName )
|
||||
{
|
||||
QDomDocument doc;
|
||||
|
||||
createDoc( doc, label );
|
||||
QByteArray buffer = doc.toByteArray( 2 );
|
||||
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::WriteOnly | QFile::Text) )
|
||||
{
|
||||
qWarning() << "Error: Cannot write file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
}
|
||||
|
||||
file.write( buffer.data(), buffer.size() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::writeBuffer( const Model* label, QByteArray& buffer )
|
||||
{
|
||||
QDomDocument doc;
|
||||
|
||||
createDoc( doc, label );
|
||||
buffer = doc.toByteArray( 2 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::serializeObjects( const QList<ModelObject*>& objects,
|
||||
QByteArray& buffer )
|
||||
{
|
||||
QDomDocument doc;
|
||||
|
||||
QDomNode xmlNode( doc.createProcessingInstruction( "xml", "version=\"1.0\"" ) );
|
||||
doc.appendChild( xmlNode );
|
||||
|
||||
QDomElement root = doc.createElement( "Glabels-objects" );
|
||||
doc.appendChild( root );
|
||||
XmlUtil::setStringAttr( root, "version", "4.0" );
|
||||
|
||||
createDataNode( root, objects );
|
||||
createObjectsNode( root, objects, false );
|
||||
|
||||
buffer = doc.toByteArray( 2 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createDoc( QDomDocument& doc, const Model* label )
|
||||
{
|
||||
QDomNode xmlNode( doc.createProcessingInstruction( "xml", "version=\"1.0\"" ) );
|
||||
doc.appendChild( xmlNode );
|
||||
|
||||
QDomElement root = doc.createElement( "Glabels-document" );
|
||||
doc.appendChild( root );
|
||||
XmlUtil::setStringAttr( root, "version", "4.0" );
|
||||
|
||||
XmlTemplateCreator().createTemplateNode( root, label->tmplate() );
|
||||
|
||||
createObjectsNode( root, label->objectList(), label->rotate() );
|
||||
|
||||
if ( label->merge() && !dynamic_cast<merge::None*>(label->merge()) )
|
||||
{
|
||||
createMergeNode( root, label );
|
||||
}
|
||||
|
||||
createDataNode( root, label->objectList() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectsNode( QDomElement &parent, const QList<ModelObject*>& objects, bool rotate )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Objects" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "id", "0" );
|
||||
XmlUtil::setBoolAttr( node, "rotate", rotate );
|
||||
|
||||
foreach ( ModelObject* object, objects )
|
||||
{
|
||||
if ( ModelBoxObject* boxObject = dynamic_cast<ModelBoxObject*>(object) )
|
||||
{
|
||||
createObjectBoxNode( node, boxObject );
|
||||
}
|
||||
else if ( ModelEllipseObject* ellipseObject = dynamic_cast<ModelEllipseObject*>(object) )
|
||||
{
|
||||
createObjectEllipseNode( node, ellipseObject );
|
||||
}
|
||||
else if ( ModelLineObject* lineObject = dynamic_cast<ModelLineObject*>(object) )
|
||||
{
|
||||
createObjectLineNode( node, lineObject );
|
||||
}
|
||||
else if ( ModelImageObject* imageObject = dynamic_cast<ModelImageObject*>(object) )
|
||||
{
|
||||
createObjectImageNode( node, imageObject );
|
||||
}
|
||||
else if ( ModelBarcodeObject* barcodeObject = dynamic_cast<ModelBarcodeObject*>(object) )
|
||||
{
|
||||
createObjectBarcodeNode( node, barcodeObject );
|
||||
}
|
||||
else if ( ModelTextObject* textObject = dynamic_cast<ModelTextObject*>(object) )
|
||||
{
|
||||
createObjectTextNode( node, textObject );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT_X( false, "XmlLabelCreator::createObjectsNode", "Invalid object type." );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectBoxNode( QDomElement &parent, const ModelBoxObject* object )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Object-box" );
|
||||
parent.appendChild( node );
|
||||
|
||||
/* position attrs */
|
||||
createPositionAttrs( node, object );
|
||||
|
||||
/* size attrs */
|
||||
createSizeAttrs( node, object );
|
||||
|
||||
/* line attrs */
|
||||
createLineAttrs( node, object );
|
||||
|
||||
/* fill attrs */
|
||||
createFillAttrs( node, object );
|
||||
|
||||
/* affine attrs */
|
||||
createAffineAttrs( node, object );
|
||||
|
||||
/* shadow attrs */
|
||||
createShadowAttrs( node, object );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectEllipseNode( QDomElement &parent, const ModelEllipseObject* object )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Object-ellipse" );
|
||||
parent.appendChild( node );
|
||||
|
||||
/* position attrs */
|
||||
createPositionAttrs( node, object );
|
||||
|
||||
/* size attrs */
|
||||
createSizeAttrs( node, object );
|
||||
|
||||
/* line attrs */
|
||||
createLineAttrs( node, object );
|
||||
|
||||
/* fill attrs */
|
||||
createFillAttrs( node, object );
|
||||
|
||||
/* affine attrs */
|
||||
createAffineAttrs( node, object );
|
||||
|
||||
/* shadow attrs */
|
||||
createShadowAttrs( node, object );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectLineNode( QDomElement &parent, const ModelLineObject* object )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Object-line" );
|
||||
parent.appendChild( node );
|
||||
|
||||
/* position attrs */
|
||||
createPositionAttrs( node, object );
|
||||
|
||||
/* size attrs of line */
|
||||
XmlUtil::setLengthAttr( node, "dx", object->w() );
|
||||
XmlUtil::setLengthAttr( node, "dy", object->h() );
|
||||
|
||||
/* line attrs */
|
||||
createLineAttrs( node, object );
|
||||
|
||||
/* affine attrs */
|
||||
createAffineAttrs( node, object );
|
||||
|
||||
/* shadow attrs */
|
||||
createShadowAttrs( node, object );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectImageNode( QDomElement &parent, const ModelImageObject* object )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Object-image" );
|
||||
parent.appendChild( node );
|
||||
|
||||
/* position attrs */
|
||||
createPositionAttrs( node, object );
|
||||
|
||||
/* size attrs */
|
||||
createSizeAttrs( node, object );
|
||||
|
||||
/* file attrs */
|
||||
if ( object->filenameNode().isField() )
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "src_field", object->filenameNode().data() );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "src", object->filenameNode().data() );
|
||||
}
|
||||
|
||||
/* affine attrs */
|
||||
createAffineAttrs( node, object );
|
||||
|
||||
/* shadow attrs */
|
||||
createShadowAttrs( node, object );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectBarcodeNode( QDomElement &parent, const ModelBarcodeObject* object )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Object-barcode" );
|
||||
parent.appendChild( node );
|
||||
|
||||
/* position attrs */
|
||||
createPositionAttrs( node, object );
|
||||
|
||||
/* size attrs */
|
||||
createSizeAttrs( node, object );
|
||||
|
||||
/* barcode attrs */
|
||||
XmlUtil::setStringAttr( node, "backend", object->bcStyle().backendId() );
|
||||
XmlUtil::setStringAttr( node, "style", object->bcStyle().id() );
|
||||
XmlUtil::setBoolAttr( node, "text", object->bcTextFlag() );
|
||||
XmlUtil::setBoolAttr( node, "checksum", object->bcChecksumFlag() );
|
||||
if ( object->bcColorNode().isField() )
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "color_field", object->bcColorNode().key() );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlUtil::setUIntAttr( node, "color", object->bcColorNode().rgba() );
|
||||
}
|
||||
XmlUtil::setStringAttr( node, "data", object->bcData() );
|
||||
|
||||
/* affine attrs */
|
||||
createAffineAttrs( node, object );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createObjectTextNode( QDomElement &parent, const ModelTextObject* object )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Object-text" );
|
||||
parent.appendChild( node );
|
||||
|
||||
/* position attrs */
|
||||
createPositionAttrs( node, object );
|
||||
|
||||
/* size attrs */
|
||||
createSizeAttrs( node, object );
|
||||
|
||||
/* color attr */
|
||||
if ( object->textColorNode().isField() )
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "color_field", object->textColorNode().key() );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlUtil::setUIntAttr( node, "color", object->textColorNode().rgba() );
|
||||
}
|
||||
|
||||
/* font attrs */
|
||||
XmlUtil::setStringAttr( node, "font_family", object->fontFamily() );
|
||||
XmlUtil::setDoubleAttr( node, "font_size", object->fontSize() );
|
||||
XmlUtil::setWeightAttr( node, "font_weight", object->fontWeight() );
|
||||
XmlUtil::setBoolAttr( node, "font_italic", object->fontItalicFlag() );
|
||||
XmlUtil::setBoolAttr( node, "font_underline", object->fontUnderlineFlag() );
|
||||
|
||||
/* text attrs */
|
||||
XmlUtil::setDoubleAttr( node, "line_spacing", object->textLineSpacing() );
|
||||
XmlUtil::setAlignmentAttr( node, "align", object->textHAlign() );
|
||||
XmlUtil::setAlignmentAttr( node, "valign", object->textVAlign() );
|
||||
|
||||
/* affine attrs */
|
||||
createAffineAttrs( node, object );
|
||||
|
||||
/* shadow attrs */
|
||||
createShadowAttrs( node, object );
|
||||
|
||||
/* serialize text contents */
|
||||
QTextDocument document( object->text() );
|
||||
int nBlocks = document.blockCount();
|
||||
for ( int iBlock = 0; iBlock < nBlocks; iBlock++ )
|
||||
{
|
||||
createPNode( node, document.findBlockByNumber(iBlock).text() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createPNode( QDomElement &parent, const QString& blockText )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "p" );
|
||||
parent.appendChild( node );
|
||||
|
||||
node.appendChild( doc.createTextNode( blockText ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createPositionAttrs( QDomElement &node, const ModelObject* object )
|
||||
{
|
||||
XmlUtil::setLengthAttr( node, "x", object->x0() );
|
||||
XmlUtil::setLengthAttr( node, "y", object->y0() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createSizeAttrs( QDomElement &node, const ModelObject* object )
|
||||
{
|
||||
XmlUtil::setLengthAttr( node, "w", object->w() );
|
||||
XmlUtil::setLengthAttr( node, "h", object->h() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createLineAttrs( QDomElement &node, const ModelObject* object )
|
||||
{
|
||||
XmlUtil::setLengthAttr( node, "line_width", object->lineWidth() );
|
||||
if ( object->lineColorNode().isField() )
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "line_color_field", object->lineColorNode().key() );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlUtil::setUIntAttr( node, "line_color", object->lineColorNode().rgba() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createFillAttrs( QDomElement &node, const ModelObject* object )
|
||||
{
|
||||
if ( object->fillColorNode().isField() )
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "fill_color_field", object->fillColorNode().key() );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlUtil::setUIntAttr( node, "fill_color", object->fillColorNode().rgba() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createAffineAttrs( QDomElement &node, const ModelObject* object )
|
||||
{
|
||||
QMatrix a = object->matrix();
|
||||
|
||||
XmlUtil::setDoubleAttr( node, "a0", a.m11() );
|
||||
XmlUtil::setDoubleAttr( node, "a1", a.m12() );
|
||||
XmlUtil::setDoubleAttr( node, "a2", a.m21() );
|
||||
XmlUtil::setDoubleAttr( node, "a3", a.m22() );
|
||||
XmlUtil::setDoubleAttr( node, "a4", a.dx() );
|
||||
XmlUtil::setDoubleAttr( node, "a5", a.dy() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createShadowAttrs( QDomElement &node, const ModelObject* object )
|
||||
{
|
||||
if ( object->shadow() )
|
||||
{
|
||||
XmlUtil::setBoolAttr( node, "shadow", object->shadow() );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "shadow_x", object->shadowX() );
|
||||
XmlUtil::setLengthAttr( node, "shadow_y", object->shadowY() );
|
||||
|
||||
if ( object->fillColorNode().isField() )
|
||||
{
|
||||
XmlUtil::setStringAttr( node, "shadow_color_field", object->shadowColorNode().key() );
|
||||
}
|
||||
else
|
||||
{
|
||||
XmlUtil::setUIntAttr( node, "shadow_color", object->shadowColorNode().rgba() );
|
||||
}
|
||||
|
||||
XmlUtil::setDoubleAttr( node, "shadow_opacity", object->shadowOpacity() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createMergeNode( QDomElement &parent, const Model* label )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Merge" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "type", label->merge()->id() );
|
||||
XmlUtil::setStringAttr( node, "src", label->merge()->source() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createDataNode( QDomElement &parent, const QList<ModelObject*>& objects )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Data" );
|
||||
parent.appendChild( node );
|
||||
|
||||
DataCache data( objects );
|
||||
|
||||
foreach ( QString name, data.imageNames() )
|
||||
{
|
||||
createPngFileNode( node, name, data.getImage( name ) );
|
||||
}
|
||||
|
||||
foreach ( QString name, data.svgNames() )
|
||||
{
|
||||
createSvgFileNode( node, name, data.getSvg( name ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createPngFileNode( QDomElement &parent, const QString& name, const QImage& image )
|
||||
{
|
||||
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 ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelCreator::createSvgFileNode( QDomElement &parent, const QString& name, const QByteArray& svg )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "File" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "name", name );
|
||||
XmlUtil::setStringAttr( node, "mimetype", "image/svg+xml" );
|
||||
XmlUtil::setStringAttr( node, "encoding", "cdata" );
|
||||
|
||||
node.appendChild( doc.createCDATASection( QString( svg ) ) );
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,82 @@
|
||||
/* XmlLabelCreator.h
|
||||
*
|
||||
* Copyright (C) 2014 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 model_XmlLabelCreator_h
|
||||
#define model_XmlLabelCreator_h
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QDomElement>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward references
|
||||
class Model;
|
||||
class ModelObject;
|
||||
class ModelBoxObject;
|
||||
class ModelEllipseObject;
|
||||
class ModelLineObject;
|
||||
class ModelImageObject;
|
||||
class ModelBarcodeObject;
|
||||
class ModelTextObject;
|
||||
|
||||
|
||||
///
|
||||
/// XmlLabelCreator
|
||||
///
|
||||
class XmlLabelCreator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static void writeFile( const Model* label, const QString& fileName );
|
||||
static void writeBuffer( const Model* label, QByteArray& buffer );
|
||||
static void serializeObjects( const QList<ModelObject*>& objects, QByteArray& buffer );
|
||||
|
||||
private:
|
||||
static void createDoc( QDomDocument& doc, const Model* label );
|
||||
static void createRootNode( const Model* label );
|
||||
static void createObjectsNode( QDomElement &parent, const QList<ModelObject*>& objects, bool rotate );
|
||||
static void createObjectBoxNode( QDomElement &parent, const ModelBoxObject* object );
|
||||
static void createObjectEllipseNode( QDomElement &parent, const ModelEllipseObject* object );
|
||||
static void createObjectLineNode( QDomElement &parent, const ModelLineObject* object );
|
||||
static void createObjectImageNode( QDomElement &parent, const ModelImageObject* object );
|
||||
static void createObjectBarcodeNode( QDomElement &parent, const ModelBarcodeObject* object );
|
||||
static void createObjectTextNode( QDomElement &parent, const ModelTextObject* object );
|
||||
static void createPNode( QDomElement &parent, const QString& blockText );
|
||||
static void createPositionAttrs( QDomElement &node, const ModelObject* object );
|
||||
static void createSizeAttrs( QDomElement &node, const ModelObject* object );
|
||||
static void createLineAttrs( QDomElement &node, const ModelObject* object );
|
||||
static void createFillAttrs( QDomElement &node, const ModelObject* object );
|
||||
static void createAffineAttrs( QDomElement &node, const ModelObject* object );
|
||||
static void createShadowAttrs( QDomElement &node, const ModelObject* object );
|
||||
static void createMergeNode( QDomElement &parent, const Model* label );
|
||||
static void createDataNode( QDomElement &parent, const QList<ModelObject*>& objects );
|
||||
static void createPngFileNode( QDomElement &parent, const QString& name, const QImage& image );
|
||||
static void createSvgFileNode( QDomElement &parent, const QString& name, const QByteArray& svg );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlLabelCreator_h
|
||||
@@ -0,0 +1,754 @@
|
||||
/* XmlLabelParser.cpp
|
||||
*
|
||||
* Copyright (C) 2014-2016 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 "XmlLabelParser.h"
|
||||
|
||||
#include "Model.h"
|
||||
#include "ModelObject.h"
|
||||
#include "ModelBarcodeObject.h"
|
||||
#include "ModelBoxObject.h"
|
||||
#include "ModelEllipseObject.h"
|
||||
#include "ModelImageObject.h"
|
||||
#include "ModelLineObject.h"
|
||||
#include "ModelTextObject.h"
|
||||
#include "XmlTemplateParser.h"
|
||||
#include "XmlUtil.h"
|
||||
#include "DataCache.h"
|
||||
|
||||
#include "barcode/Backends.h"
|
||||
#include "merge/Factory.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFile>
|
||||
#include <QTextCursor>
|
||||
#include <QTextDocument>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
Model*
|
||||
XmlLabelParser::readFile( const QString& fileName )
|
||||
{
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::ReadOnly ) )
|
||||
{
|
||||
qWarning() << "Error: Cannot read file" << fileName
|
||||
<< ":" << file.errorString();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QDomDocument doc;
|
||||
bool success;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
QByteArray rawData = file.readAll();
|
||||
if ( ((rawData[0]&0xFF) == 0x1F) && ((rawData[1]&0xFF) == 0x8b) ) // gzip magic number 0x1F, 0x8B
|
||||
{
|
||||
// gzip compressed format
|
||||
QByteArray unzippedData;
|
||||
gunzip( rawData, unzippedData );
|
||||
success = doc.setContent( unzippedData, false, &errorString, &errorLine, &errorColumn );
|
||||
}
|
||||
else
|
||||
{
|
||||
// plain text
|
||||
success = doc.setContent( rawData, false, &errorString, &errorLine, &errorColumn );
|
||||
}
|
||||
|
||||
if ( !success )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-document" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-document file";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return parseRootNode( root );
|
||||
}
|
||||
|
||||
|
||||
Model*
|
||||
XmlLabelParser::readBuffer( const QByteArray& buffer )
|
||||
{
|
||||
QDomDocument doc;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( buffer, false, &errorString, &errorLine, &errorColumn ) )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-document" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-document file";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return parseRootNode( root );
|
||||
}
|
||||
|
||||
|
||||
QList<ModelObject*>
|
||||
XmlLabelParser::deserializeObjects( const QByteArray& buffer )
|
||||
{
|
||||
QList<ModelObject*> list;
|
||||
|
||||
QDomDocument doc;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( buffer, false, &errorString, &errorLine, &errorColumn ) )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return list;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-objects" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-objects stream";
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Pass 1, extract data nodes to pre-load cache. */
|
||||
DataCache data;
|
||||
for ( QDomNode child = root.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Data" )
|
||||
{
|
||||
parseDataNode( child.toElement(), data );
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2, now extract objects. */
|
||||
for ( QDomNode child = root.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Objects" )
|
||||
{
|
||||
list = parseObjectsNode( child.toElement(), data );
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelParser::gunzip( const QByteArray& data, QByteArray& result )
|
||||
{
|
||||
result.clear();
|
||||
|
||||
if (data.size() <= 4) {
|
||||
qWarning("XmlLabelParser::gunzip: Input data is truncated");
|
||||
return;
|
||||
}
|
||||
|
||||
// setup stream for inflate()
|
||||
z_stream strm;
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = data.size();
|
||||
strm.next_in = (Bytef*)(data.data());
|
||||
|
||||
int ret = inflateInit2(&strm, MAX_WBITS + 16); // gzip decoding
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static const int CHUNK_SIZE = 1024;
|
||||
char out[CHUNK_SIZE];
|
||||
|
||||
// run inflate(), one chunk at a time
|
||||
do {
|
||||
strm.avail_out = CHUNK_SIZE;
|
||||
strm.next_out = (Bytef*)(out);
|
||||
|
||||
ret = inflate(&strm, Z_NO_FLUSH);
|
||||
Q_ASSERT(ret != Z_STREAM_ERROR); // state not clobbered
|
||||
|
||||
if ( (ret == Z_NEED_DICT) || (ret == Z_DATA_ERROR) || (ret == Z_MEM_ERROR) )
|
||||
{
|
||||
// clean up
|
||||
inflateEnd(&strm);
|
||||
return;
|
||||
}
|
||||
|
||||
result.append(out, CHUNK_SIZE - strm.avail_out);
|
||||
} while (strm.avail_out == 0);
|
||||
|
||||
// clean up
|
||||
inflateEnd(&strm);
|
||||
}
|
||||
|
||||
|
||||
Model*
|
||||
XmlLabelParser::parseRootNode( const QDomElement &node )
|
||||
{
|
||||
QString version = XmlUtil::getStringAttr( node, "version", "" );
|
||||
if ( version != "4.0" )
|
||||
{
|
||||
qWarning() << "TODO: compatability mode.";
|
||||
}
|
||||
|
||||
Model* label = new Model();
|
||||
|
||||
/* Pass 1, extract data nodes to pre-load cache. */
|
||||
DataCache data;
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Data" )
|
||||
{
|
||||
parseDataNode( child.toElement(), data );
|
||||
}
|
||||
}
|
||||
|
||||
/* Pass 2, now extract everything else. */
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
QString tagName = child.toElement().tagName();
|
||||
|
||||
if ( tagName == "Template" )
|
||||
{
|
||||
Template* tmplate = XmlTemplateParser().parseTemplateNode( child.toElement() );
|
||||
if ( tmplate == nullptr )
|
||||
{
|
||||
qWarning() << "Unable to parse template";
|
||||
delete label;
|
||||
return nullptr;
|
||||
}
|
||||
label->setTmplate( tmplate );
|
||||
}
|
||||
else if ( tagName == "Objects" )
|
||||
{
|
||||
label->setRotate( parseRotateAttr( child.toElement() ) );
|
||||
QList<ModelObject*> list = parseObjectsNode( child.toElement(), data );
|
||||
foreach ( ModelObject* object, list )
|
||||
{
|
||||
label->addObject( object );
|
||||
}
|
||||
}
|
||||
else if ( tagName == "Merge" )
|
||||
{
|
||||
parseMergeNode( child.toElement(), label );
|
||||
}
|
||||
else if ( tagName == "Data" )
|
||||
{
|
||||
/* Handled in pass 1. */
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Unexpected" << node.tagName() << "child:" << tagName;
|
||||
}
|
||||
}
|
||||
|
||||
label->clearModified();
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
QList<ModelObject*>
|
||||
XmlLabelParser::parseObjectsNode( const QDomElement &node, const DataCache& data )
|
||||
{
|
||||
QList<ModelObject*> list;
|
||||
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
QString tagName = child.toElement().tagName();
|
||||
|
||||
if ( tagName == "Object-box" )
|
||||
{
|
||||
list.append( parseObjectBoxNode( child.toElement() ) );
|
||||
}
|
||||
else if ( tagName == "Object-ellipse" )
|
||||
{
|
||||
list.append( parseObjectEllipseNode( child.toElement() ) );
|
||||
}
|
||||
else if ( tagName == "Object-line" )
|
||||
{
|
||||
list.append( parseObjectLineNode( child.toElement() ) );
|
||||
}
|
||||
else if ( tagName == "Object-text" )
|
||||
{
|
||||
list.append( parseObjectTextNode( child.toElement() ) );
|
||||
}
|
||||
else if ( tagName == "Object-image" )
|
||||
{
|
||||
list.append( parseObjectImageNode( child.toElement(), data ) );
|
||||
}
|
||||
else if ( tagName == "Object-barcode" )
|
||||
{
|
||||
list.append( parseObjectBarcodeNode( child.toElement() ) );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Unexpected" << node.tagName() << "child:" << tagName;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
ModelBoxObject*
|
||||
XmlLabelParser::parseObjectBoxNode( const QDomElement &node )
|
||||
{
|
||||
/* position attrs */
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x", 0.0 );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y", 0.0 );
|
||||
|
||||
/* size attrs */
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", 0 );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", 0 );
|
||||
|
||||
/* line attrs */
|
||||
Distance lineWidth = XmlUtil::getLengthAttr( node, "line_width", 1.0 );
|
||||
|
||||
QString key = XmlUtil::getStringAttr( node, "line_color_field", "" );
|
||||
bool field_flag = !key.isEmpty();
|
||||
uint32_t color = XmlUtil::getUIntAttr( node, "line_color", 0 );
|
||||
ColorNode lineColorNode( field_flag, color, key );
|
||||
|
||||
/* fill attrs */
|
||||
key = XmlUtil::getStringAttr( node, "fill_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
color = XmlUtil::getUIntAttr( node, "fill_color", 0 );
|
||||
ColorNode fillColorNode( field_flag, color, key );
|
||||
|
||||
/* affine attrs */
|
||||
double a[6];
|
||||
a[0] = XmlUtil::getDoubleAttr( node, "a0", 1.0 );
|
||||
a[1] = XmlUtil::getDoubleAttr( node, "a1", 0.0 );
|
||||
a[2] = XmlUtil::getDoubleAttr( node, "a2", 0.0 );
|
||||
a[3] = XmlUtil::getDoubleAttr( node, "a3", 1.0 );
|
||||
a[4] = XmlUtil::getDoubleAttr( node, "a4", 0.0 );
|
||||
a[5] = XmlUtil::getDoubleAttr( node, "a5", 0.0 );
|
||||
|
||||
/* shadow attrs */
|
||||
bool shadowState = XmlUtil::getBoolAttr( node, "shadow", false );
|
||||
Distance shadowX = XmlUtil::getLengthAttr( node, "shadow_x", 0.0 );
|
||||
Distance shadowY = XmlUtil::getLengthAttr( node, "shadow_y", 0.0 );
|
||||
double shadowOpacity = XmlUtil::getDoubleAttr( node, "shadow_opacity", 1.0 );
|
||||
|
||||
key = XmlUtil::getStringAttr( node, "shadow_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
color = XmlUtil::getUIntAttr( node, "shadow_color", 0 );
|
||||
ColorNode shadowColorNode( field_flag, color, key );
|
||||
|
||||
return new ModelBoxObject( x0, y0, w, h,
|
||||
lineWidth, lineColorNode,
|
||||
fillColorNode,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
|
||||
|
||||
ModelEllipseObject*
|
||||
XmlLabelParser::parseObjectEllipseNode( const QDomElement &node )
|
||||
{
|
||||
/* position attrs */
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x", 0.0 );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y", 0.0 );
|
||||
|
||||
/* size attrs */
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", 0 );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", 0 );
|
||||
|
||||
/* line attrs */
|
||||
Distance lineWidth = XmlUtil::getLengthAttr( node, "line_width", 1.0 );
|
||||
|
||||
QString key = XmlUtil::getStringAttr( node, "line_color_field", "" );
|
||||
bool field_flag = !key.isEmpty();
|
||||
uint32_t color = XmlUtil::getUIntAttr( node, "line_color", 0 );
|
||||
ColorNode lineColorNode( field_flag, color, key );
|
||||
|
||||
/* fill attrs */
|
||||
key = XmlUtil::getStringAttr( node, "fill_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
color = XmlUtil::getUIntAttr( node, "fill_color", 0 );
|
||||
ColorNode fillColorNode( field_flag, color, key );
|
||||
|
||||
/* affine attrs */
|
||||
double a[6];
|
||||
a[0] = XmlUtil::getDoubleAttr( node, "a0", 1.0 );
|
||||
a[1] = XmlUtil::getDoubleAttr( node, "a1", 0.0 );
|
||||
a[2] = XmlUtil::getDoubleAttr( node, "a2", 0.0 );
|
||||
a[3] = XmlUtil::getDoubleAttr( node, "a3", 1.0 );
|
||||
a[4] = XmlUtil::getDoubleAttr( node, "a4", 0.0 );
|
||||
a[5] = XmlUtil::getDoubleAttr( node, "a5", 0.0 );
|
||||
|
||||
/* shadow attrs */
|
||||
bool shadowState = XmlUtil::getBoolAttr( node, "shadow", false );
|
||||
Distance shadowX = XmlUtil::getLengthAttr( node, "shadow_x", 0.0 );
|
||||
Distance shadowY = XmlUtil::getLengthAttr( node, "shadow_y", 0.0 );
|
||||
double shadowOpacity = XmlUtil::getDoubleAttr( node, "shadow_opacity", 1.0 );
|
||||
|
||||
key = XmlUtil::getStringAttr( node, "shadow_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
color = XmlUtil::getUIntAttr( node, "shadow_color", 0 );
|
||||
ColorNode shadowColorNode( field_flag, color, key );
|
||||
|
||||
return new ModelEllipseObject( x0, y0, w, h,
|
||||
lineWidth, lineColorNode,
|
||||
fillColorNode,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
|
||||
|
||||
ModelLineObject*
|
||||
XmlLabelParser::parseObjectLineNode( const QDomElement &node )
|
||||
{
|
||||
/* position attrs */
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x", 0.0 );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y", 0.0 );
|
||||
|
||||
/* size attrs of line */
|
||||
Distance dx = XmlUtil::getLengthAttr( node, "dx", 0 );
|
||||
Distance dy = XmlUtil::getLengthAttr( node, "dy", 0 );
|
||||
|
||||
/* line attrs */
|
||||
Distance lineWidth = XmlUtil::getLengthAttr( node, "line_width", 1.0 );
|
||||
|
||||
QString key = XmlUtil::getStringAttr( node, "line_color_field", "" );
|
||||
bool field_flag = !key.isEmpty();
|
||||
uint32_t color = XmlUtil::getUIntAttr( node, "line_color", 0 );
|
||||
ColorNode lineColorNode( field_flag, color, key );
|
||||
|
||||
/* affine attrs */
|
||||
double a[6];
|
||||
a[0] = XmlUtil::getDoubleAttr( node, "a0", 1.0 );
|
||||
a[1] = XmlUtil::getDoubleAttr( node, "a1", 0.0 );
|
||||
a[2] = XmlUtil::getDoubleAttr( node, "a2", 0.0 );
|
||||
a[3] = XmlUtil::getDoubleAttr( node, "a3", 1.0 );
|
||||
a[4] = XmlUtil::getDoubleAttr( node, "a4", 0.0 );
|
||||
a[5] = XmlUtil::getDoubleAttr( node, "a5", 0.0 );
|
||||
|
||||
/* shadow attrs */
|
||||
bool shadowState = XmlUtil::getBoolAttr( node, "shadow", false );
|
||||
Distance shadowX = XmlUtil::getLengthAttr( node, "shadow_x", 0.0 );
|
||||
Distance shadowY = XmlUtil::getLengthAttr( node, "shadow_y", 0.0 );
|
||||
double shadowOpacity = XmlUtil::getDoubleAttr( node, "shadow_opacity", 1.0 );
|
||||
|
||||
key = XmlUtil::getStringAttr( node, "shadow_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
color = XmlUtil::getUIntAttr( node, "shadow_color", 0 );
|
||||
ColorNode shadowColorNode( field_flag, color, key );
|
||||
|
||||
return new ModelLineObject( x0, y0, dx, dy,
|
||||
lineWidth, lineColorNode,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
|
||||
|
||||
ModelImageObject*
|
||||
XmlLabelParser::parseObjectImageNode( const QDomElement &node, const DataCache& data )
|
||||
{
|
||||
/* position attrs */
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x", 0.0 );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y", 0.0 );
|
||||
|
||||
/* size attrs */
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", 0 );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", 0 );
|
||||
|
||||
/* file attrs */
|
||||
QString key = XmlUtil::getStringAttr( node, "src_field", "" );
|
||||
bool field_flag = !key.isEmpty();
|
||||
QString filename = XmlUtil::getStringAttr( node, "src", "" );
|
||||
TextNode filenameNode( field_flag, field_flag ? key : filename );
|
||||
|
||||
/* affine attrs */
|
||||
double a[6];
|
||||
a[0] = XmlUtil::getDoubleAttr( node, "a0", 1.0 );
|
||||
a[1] = XmlUtil::getDoubleAttr( node, "a1", 0.0 );
|
||||
a[2] = XmlUtil::getDoubleAttr( node, "a2", 0.0 );
|
||||
a[3] = XmlUtil::getDoubleAttr( node, "a3", 1.0 );
|
||||
a[4] = XmlUtil::getDoubleAttr( node, "a4", 0.0 );
|
||||
a[5] = XmlUtil::getDoubleAttr( node, "a5", 0.0 );
|
||||
|
||||
/* shadow attrs */
|
||||
bool shadowState = XmlUtil::getBoolAttr( node, "shadow", false );
|
||||
Distance shadowX = XmlUtil::getLengthAttr( node, "shadow_x", 0.0 );
|
||||
Distance shadowY = XmlUtil::getLengthAttr( node, "shadow_y", 0.0 );
|
||||
double shadowOpacity = XmlUtil::getDoubleAttr( node, "shadow_opacity", 1.0 );
|
||||
|
||||
key = XmlUtil::getStringAttr( node, "shadow_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
uint32_t color = XmlUtil::getUIntAttr( node, "shadow_color", 0 );
|
||||
ColorNode shadowColorNode( field_flag, color, key );
|
||||
|
||||
if ( filenameNode.isField() )
|
||||
{
|
||||
return new ModelImageObject( x0, y0, w, h,
|
||||
filenameNode,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( data.hasImage( filename ) )
|
||||
{
|
||||
return new ModelImageObject( x0, y0, w, h,
|
||||
filename, data.getImage( filename ),
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
else if ( data.hasSvg( filename ) )
|
||||
{
|
||||
return new ModelImageObject( x0, y0, w, h,
|
||||
filename, data.getSvg( filename ),
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Embedded file" << filename << "missing. Trying actual file.";
|
||||
return new ModelImageObject( x0, y0, w, h,
|
||||
filenameNode,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ModelBarcodeObject*
|
||||
XmlLabelParser::parseObjectBarcodeNode( const QDomElement &node )
|
||||
{
|
||||
/* position attrs */
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x", 0.0 );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y", 0.0 );
|
||||
|
||||
/* size attrs */
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", 0 );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", 0 );
|
||||
|
||||
/* barcode attrs */
|
||||
barcode::Style bcStyle = barcode::Backends::style( XmlUtil::getStringAttr( node, "backend", "" ),
|
||||
XmlUtil::getStringAttr( node, "style", "") );
|
||||
bool bcTextFlag = XmlUtil::getBoolAttr( node, "text", true );
|
||||
bool bcChecksumFlag = XmlUtil::getBoolAttr( node, "checksum", true );
|
||||
|
||||
QString key = XmlUtil::getStringAttr( node, "color_field", "" );
|
||||
bool field_flag = !key.isEmpty();
|
||||
uint32_t color = XmlUtil::getUIntAttr( node, "color", 0 );
|
||||
ColorNode bcColorNode( field_flag, color, key );
|
||||
|
||||
QString bcData = XmlUtil::getStringAttr( node, "data", "" );
|
||||
|
||||
/* affine attrs */
|
||||
double a[6];
|
||||
a[0] = XmlUtil::getDoubleAttr( node, "a0", 1.0 );
|
||||
a[1] = XmlUtil::getDoubleAttr( node, "a1", 0.0 );
|
||||
a[2] = XmlUtil::getDoubleAttr( node, "a2", 0.0 );
|
||||
a[3] = XmlUtil::getDoubleAttr( node, "a3", 1.0 );
|
||||
a[4] = XmlUtil::getDoubleAttr( node, "a4", 0.0 );
|
||||
a[5] = XmlUtil::getDoubleAttr( node, "a5", 0.0 );
|
||||
|
||||
return new ModelBarcodeObject( x0, y0, w, h,
|
||||
bcStyle, bcTextFlag, bcChecksumFlag, bcData, bcColorNode,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ) );
|
||||
}
|
||||
|
||||
|
||||
ModelTextObject*
|
||||
XmlLabelParser::parseObjectTextNode( const QDomElement &node )
|
||||
{
|
||||
/* position attrs */
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x", 0.0 );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y", 0.0 );
|
||||
|
||||
/* size attrs */
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", 0 );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", 0 );
|
||||
|
||||
/* color attr */
|
||||
QString key = XmlUtil::getStringAttr( node, "color_field", "" );
|
||||
bool field_flag = !key.isEmpty();
|
||||
uint32_t color = XmlUtil::getUIntAttr( node, "color", 0 );
|
||||
ColorNode textColorNode( field_flag, color, key );
|
||||
|
||||
/* font attrs */
|
||||
QString fontFamily = XmlUtil::getStringAttr( node, "font_family", "Sans" );
|
||||
double fontSize = XmlUtil::getDoubleAttr( node, "font_size", 10 );
|
||||
QFont::Weight fontWeight = XmlUtil::getWeightAttr( node, "font_weight", QFont::Normal );
|
||||
bool fontItalicFlag = XmlUtil::getBoolAttr( node, "font_italic", false );
|
||||
bool fontUnderlineFlag = XmlUtil::getBoolAttr( node, "font_underline", false );
|
||||
|
||||
/* text attrs */
|
||||
double textLineSpacing = XmlUtil::getDoubleAttr( node, "line_spacing", 1 );
|
||||
Qt::Alignment textHAlign = XmlUtil::getAlignmentAttr( node, "align", Qt::AlignLeft );
|
||||
Qt::Alignment textVAlign = XmlUtil::getAlignmentAttr( node, "valign", Qt::AlignTop );
|
||||
|
||||
/* affine attrs */
|
||||
double a[6];
|
||||
a[0] = XmlUtil::getDoubleAttr( node, "a0", 1.0 );
|
||||
a[1] = XmlUtil::getDoubleAttr( node, "a1", 0.0 );
|
||||
a[2] = XmlUtil::getDoubleAttr( node, "a2", 0.0 );
|
||||
a[3] = XmlUtil::getDoubleAttr( node, "a3", 1.0 );
|
||||
a[4] = XmlUtil::getDoubleAttr( node, "a4", 0.0 );
|
||||
a[5] = XmlUtil::getDoubleAttr( node, "a5", 0.0 );
|
||||
|
||||
/* shadow attrs */
|
||||
bool shadowState = XmlUtil::getBoolAttr( node, "shadow", false );
|
||||
Distance shadowX = XmlUtil::getLengthAttr( node, "shadow_x", 0.0 );
|
||||
Distance shadowY = XmlUtil::getLengthAttr( node, "shadow_y", 0.0 );
|
||||
double shadowOpacity = XmlUtil::getDoubleAttr( node, "shadow_opacity", 1.0 );
|
||||
|
||||
key = XmlUtil::getStringAttr( node, "shadow_color_field", "" );
|
||||
field_flag = !key.isEmpty();
|
||||
color = XmlUtil::getUIntAttr( node, "shadow_color", 0 );
|
||||
ColorNode shadowColorNode( field_flag, color, key );
|
||||
|
||||
/* deserialize contents. */
|
||||
QTextDocument document;
|
||||
QTextCursor cursor( &document );
|
||||
bool firstBlock = true;
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
QString tagName = child.toElement().tagName();
|
||||
|
||||
if ( tagName == "p" )
|
||||
{
|
||||
if ( !firstBlock )
|
||||
{
|
||||
cursor.insertBlock();
|
||||
}
|
||||
firstBlock = false;
|
||||
cursor.insertText( parsePNode( child.toElement() ) );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Unexpected" << node.tagName() << "child:" << tagName;
|
||||
}
|
||||
}
|
||||
QString text = document.toPlainText();
|
||||
|
||||
return new ModelTextObject( x0, y0, w, h,
|
||||
text,
|
||||
fontFamily, fontSize, fontWeight, fontItalicFlag, fontUnderlineFlag,
|
||||
textColorNode, textHAlign, textVAlign, textLineSpacing,
|
||||
QMatrix( a[0], a[1], a[2], a[3], a[4], a[5] ),
|
||||
shadowState, shadowX, shadowY, shadowOpacity, shadowColorNode );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
XmlLabelParser::parsePNode( const QDomElement &node )
|
||||
{
|
||||
return node.text();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
XmlLabelParser::parseRotateAttr( const QDomElement &node )
|
||||
{
|
||||
return XmlUtil::getBoolAttr( node, "rotate", false );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelParser::parseMergeNode( const QDomElement &node, Model* label )
|
||||
{
|
||||
QString type = XmlUtil::getStringAttr( node, "type", "None" );
|
||||
QString src = XmlUtil::getStringAttr( node, "src", "" );
|
||||
|
||||
merge::Merge* merge = merge::Factory::createMerge( type );
|
||||
merge->setSource( src );
|
||||
|
||||
label->setMerge( merge );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelParser::parseDataNode( const QDomElement &node, DataCache& data )
|
||||
{
|
||||
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
|
||||
XmlLabelParser::parsePixdataNode( const QDomElement& node, DataCache& data )
|
||||
{
|
||||
// TODO, compatability with glabels-3
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmlLabelParser::parseFileNode( const QDomElement& node, DataCache& data )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
else if ( mimetype == "image/svg+xml" )
|
||||
{
|
||||
data.addSvg( name, node.text().toUtf8() );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,78 @@
|
||||
/* XmlLabelParser.h
|
||||
*
|
||||
* Copyright (C) 2014-2016 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 model_XmlLabelParser_h
|
||||
#define model_XmlLabelParser_h
|
||||
|
||||
|
||||
#include <QObject>
|
||||
#include <QDomElement>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
// Forward references
|
||||
class Model;
|
||||
class ModelObject;
|
||||
class ModelBoxObject;
|
||||
class ModelEllipseObject;
|
||||
class ModelLineObject;
|
||||
class ModelImageObject;
|
||||
class ModelBarcodeObject;
|
||||
class ModelTextObject;
|
||||
class DataCache;
|
||||
|
||||
|
||||
///
|
||||
/// XmlLabelParser
|
||||
///
|
||||
class XmlLabelParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static Model* readFile( const QString& fileName );
|
||||
static Model* readBuffer( const QByteArray& buffer );
|
||||
static QList<ModelObject*> deserializeObjects( const QByteArray& buffer );
|
||||
|
||||
private:
|
||||
static void gunzip( const QByteArray& gzippedData, QByteArray& data );
|
||||
static Model* parseRootNode( const QDomElement &node );
|
||||
static QList<ModelObject*> parseObjectsNode( const QDomElement &node, const DataCache& data );
|
||||
static ModelBoxObject* parseObjectBoxNode( const QDomElement &node );
|
||||
static ModelEllipseObject* parseObjectEllipseNode( const QDomElement &node );
|
||||
static ModelLineObject* parseObjectLineNode( const QDomElement &node );
|
||||
static ModelImageObject* parseObjectImageNode( const QDomElement &node, const DataCache& data );
|
||||
static ModelBarcodeObject* parseObjectBarcodeNode( const QDomElement &node );
|
||||
static ModelTextObject* parseObjectTextNode( const QDomElement &node );
|
||||
static QString parsePNode( const QDomElement &node );
|
||||
static bool parseRotateAttr( const QDomElement &node );
|
||||
static void parseMergeNode( const QDomElement &node, Model* label );
|
||||
static void parseDataNode( const QDomElement &node, DataCache& data );
|
||||
static void parsePixdataNode( const QDomElement &node, DataCache& data );
|
||||
static void parseFileNode( const QDomElement &node, DataCache& data );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlLabelParser_h
|
||||
@@ -0,0 +1,108 @@
|
||||
/* XmlPaperParser.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "XmlPaperParser.h"
|
||||
|
||||
#include "Db.h"
|
||||
#include "Paper.h"
|
||||
#include "XmlUtil.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomNode>
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
bool XmlPaperParser::readFile( const QString &fileName )
|
||||
{
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::ReadOnly | QFile::Text ) )
|
||||
{
|
||||
qWarning() << "Error: Cannot read file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QDomDocument doc;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( &file, false, &errorString, &errorLine, &errorColumn ) )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-paper-sizes" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-paper-sizes file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
parseRootNode( root );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void XmlPaperParser::parseRootNode( const QDomElement &node )
|
||||
{
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Paper-size" )
|
||||
{
|
||||
parsePaperSizeNode( child.toElement() );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlPaperParser::parsePaperSizeNode( const QDomElement &node )
|
||||
{
|
||||
QString id = XmlUtil::getStringAttr( node, "id", "" );
|
||||
QString name = XmlUtil::getI18nAttr( node, "name", "" );
|
||||
|
||||
Distance width = XmlUtil::getLengthAttr( node, "width", Distance(0) );
|
||||
Distance height = XmlUtil::getLengthAttr( node, "height", Distance(0) );
|
||||
|
||||
QString pwgSize = XmlUtil::getStringAttr( node, "pwg_size", "" );
|
||||
|
||||
Paper *paper = new Paper( id, name, width, height, pwgSize );
|
||||
if ( paper != nullptr )
|
||||
{
|
||||
Db::registerPaper( paper );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,47 @@
|
||||
/* XmlPaperParser.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_XmlPaperParser_h
|
||||
#define model_XmlPaperParser_h
|
||||
|
||||
|
||||
#include <QString>
|
||||
#include <QDomElement>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class XmlPaperParser
|
||||
{
|
||||
public:
|
||||
XmlPaperParser() {}
|
||||
|
||||
bool readFile( const QString &fileName );
|
||||
|
||||
private:
|
||||
void parseRootNode( const QDomElement &node );
|
||||
void parsePaperSizeNode( const QDomElement &node );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlPaperParser_h
|
||||
@@ -0,0 +1,333 @@
|
||||
/* XmlTemplateCreator.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "XmlTemplateCreator.h"
|
||||
|
||||
#include "Db.h"
|
||||
#include "Template.h"
|
||||
#include "XmlUtil.h"
|
||||
|
||||
#include <QDomNode>
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
bool XmlTemplateCreator::writeTemplates( const QList<const Template*> tmplates, const QString &fileName )
|
||||
{
|
||||
QDomDocument doc( "Glabels-templates" );
|
||||
QDomElement root = doc.createElement( "Glabels-templates" );
|
||||
doc.appendChild( root );
|
||||
|
||||
foreach ( const Template* tmplate, tmplates )
|
||||
{
|
||||
createTemplateNode( root, tmplate );
|
||||
}
|
||||
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::WriteOnly | QFile::Text) )
|
||||
{
|
||||
qWarning() << "Error: Cannot open file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ( file.write( doc.toByteArray() ) < 0 )
|
||||
{
|
||||
qWarning() << "Error: Cannot write file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool XmlTemplateCreator::writeTemplate( const Template* tmplate, const QString& fileName )
|
||||
{
|
||||
QList<const Template*> tmplates;
|
||||
|
||||
tmplates.append(tmplate);
|
||||
|
||||
return writeTemplates( tmplates, fileName );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createTemplateNode( QDomElement &parent, const Template* tmplate )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Template" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "brand", tmplate->brand() );
|
||||
XmlUtil::setStringAttr( node, "part", tmplate->part() );
|
||||
|
||||
XmlUtil::setStringAttr( node, "size", tmplate->paperId() );
|
||||
if ( tmplate->isSizeOther() )
|
||||
{
|
||||
XmlUtil::setLengthAttr( node, "width", tmplate->pageWidth() );
|
||||
XmlUtil::setLengthAttr( node, "height", tmplate->pageHeight() );
|
||||
}
|
||||
|
||||
|
||||
XmlUtil::setStringAttr( node, "description", tmplate->description() );
|
||||
|
||||
if ( !tmplate->productUrl().isEmpty() )
|
||||
{
|
||||
createMetaNode( node, "product_url", tmplate->productUrl() );
|
||||
}
|
||||
#if TODO
|
||||
foreach ( QString categoryId, tmplate->categoryIds() )
|
||||
{
|
||||
createMetaNode( node, "category", categoryId );
|
||||
}
|
||||
#endif
|
||||
|
||||
foreach ( Frame* frame, tmplate->frames() )
|
||||
{
|
||||
createLabelNode( node, frame );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createMetaNode( QDomElement &parent, const QString& attr, const QString& value )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Meta" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, attr, value );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createLabelNode( QDomElement &parent, const Frame* frame )
|
||||
{
|
||||
if ( const FrameRect* frameRect = dynamic_cast<const FrameRect*>(frame) )
|
||||
{
|
||||
createLabelRectangleNode( parent, frameRect );
|
||||
}
|
||||
else if ( const FrameEllipse* frameEllipse = dynamic_cast<const FrameEllipse*>(frame) )
|
||||
{
|
||||
createLabelEllipseNode( parent, frameEllipse );
|
||||
}
|
||||
else if ( const FrameRound* frameRound = dynamic_cast<const FrameRound*>(frame) )
|
||||
{
|
||||
createLabelRoundNode( parent, frameRound );
|
||||
}
|
||||
else if ( const FrameCd* frameCd = dynamic_cast<const FrameCd*>(frame) )
|
||||
{
|
||||
createLabelCdNode( parent, frameCd );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT_X( false, "XmlTemplateCreator::createLabelNode", "Invalid frame type." );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createLabelRectangleNode( QDomElement &parent, const FrameRect* frame )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Label-rectangle" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "id", frame->id() );
|
||||
XmlUtil::setLengthAttr( node, "width", frame->w() );
|
||||
XmlUtil::setLengthAttr( node, "height", frame->h() );
|
||||
XmlUtil::setLengthAttr( node, "round", frame->r() );
|
||||
XmlUtil::setLengthAttr( node, "x_waste", frame->xWaste() );
|
||||
XmlUtil::setLengthAttr( node, "y_waste", frame->yWaste() );
|
||||
|
||||
createLabelNodeCommon( node, frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createLabelEllipseNode( QDomElement &parent, const FrameEllipse* frame )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Label-ellipse" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "id", frame->id() );
|
||||
XmlUtil::setLengthAttr( node, "width", frame->w() );
|
||||
XmlUtil::setLengthAttr( node, "height", frame->h() );
|
||||
XmlUtil::setLengthAttr( node, "waste", frame->waste() );
|
||||
|
||||
createLabelNodeCommon( node, frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createLabelRoundNode( QDomElement &parent, const FrameRound* frame )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Label-round" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "id", frame->id() );
|
||||
XmlUtil::setLengthAttr( node, "radius", frame->r() );
|
||||
XmlUtil::setLengthAttr( node, "waste", frame->waste() );
|
||||
|
||||
createLabelNodeCommon( node, frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createLabelCdNode( QDomElement &parent, const FrameCd* frame )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Label-cd" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setStringAttr( node, "id", frame->id() );
|
||||
XmlUtil::setLengthAttr( node, "radius", frame->r1() );
|
||||
XmlUtil::setLengthAttr( node, "hole", frame->r2() );
|
||||
XmlUtil::setLengthAttr( node, "waste", frame->waste() );
|
||||
if ( frame->w() != Distance(0) )
|
||||
{
|
||||
XmlUtil::setLengthAttr( node, "width", frame->w() );
|
||||
}
|
||||
if ( frame->h() != Distance(0) )
|
||||
{
|
||||
XmlUtil::setLengthAttr( node, "height", frame->h() );
|
||||
}
|
||||
|
||||
createLabelNodeCommon( node, frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createLabelNodeCommon( QDomElement &node, const Frame *frame )
|
||||
{
|
||||
foreach ( Markup* markup, frame->markups() )
|
||||
{
|
||||
if ( MarkupMargin* markupMargin = dynamic_cast<MarkupMargin*>(markup) )
|
||||
{
|
||||
createMarkupMarginNode( node, markupMargin );
|
||||
}
|
||||
else if ( MarkupLine* markupLine = dynamic_cast<MarkupLine*>(markup) )
|
||||
{
|
||||
createMarkupLineNode( node, markupLine );
|
||||
}
|
||||
else if ( MarkupCircle* markupCircle = dynamic_cast<MarkupCircle*>(markup) )
|
||||
{
|
||||
createMarkupCircleNode( node, markupCircle );
|
||||
}
|
||||
else if ( MarkupRect* markupRect = dynamic_cast<MarkupRect*>(markup) )
|
||||
{
|
||||
createMarkupRectNode( node, markupRect );
|
||||
}
|
||||
else if ( MarkupEllipse* markupEllipse = dynamic_cast<MarkupEllipse*>(markup) )
|
||||
{
|
||||
createMarkupEllipseNode( node, markupEllipse );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT_X( false, "XmlTemplateCreator::createLabelNodeCommon", "Invalid markup type." );
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( Layout* layout, frame->layouts() )
|
||||
{
|
||||
createLayoutNode( node, 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::setLengthAttr( node, "x0", layout->x0() );
|
||||
XmlUtil::setLengthAttr( node, "y0", layout->y0() );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "dx", layout->dx() );
|
||||
XmlUtil::setLengthAttr( node, "dy", layout->dy() );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createMarkupMarginNode( QDomElement& parent, const MarkupMargin* markup )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Markup-margin" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "size", markup->size() );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createMarkupLineNode( QDomElement& parent, const MarkupLine* markup )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Markup-line" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "x1", markup->x1() );
|
||||
XmlUtil::setLengthAttr( node, "y1", markup->y1() );
|
||||
XmlUtil::setLengthAttr( node, "x2", markup->x2() );
|
||||
XmlUtil::setLengthAttr( node, "y2", markup->y2() );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createMarkupCircleNode( QDomElement& parent, const MarkupCircle* markup )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Markup-circle" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "x0", markup->x0() );
|
||||
XmlUtil::setLengthAttr( node, "y0", markup->y0() );
|
||||
XmlUtil::setLengthAttr( node, "radius", markup->r() );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createMarkupRectNode( QDomElement& parent, const MarkupRect* markup )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Markup-rect" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "x1", markup->x1() );
|
||||
XmlUtil::setLengthAttr( node, "y1", markup->y1() );
|
||||
XmlUtil::setLengthAttr( node, "w", markup->w() );
|
||||
XmlUtil::setLengthAttr( node, "h", markup->h() );
|
||||
XmlUtil::setLengthAttr( node, "r", markup->r() );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateCreator::createMarkupEllipseNode( QDomElement& parent, const MarkupEllipse* markup )
|
||||
{
|
||||
QDomDocument doc = parent.ownerDocument();
|
||||
QDomElement node = doc.createElement( "Markup-ellipse" );
|
||||
parent.appendChild( node );
|
||||
|
||||
XmlUtil::setLengthAttr( node, "x1", markup->x1() );
|
||||
XmlUtil::setLengthAttr( node, "y1", markup->y1() );
|
||||
XmlUtil::setLengthAttr( node, "w", markup->w() );
|
||||
XmlUtil::setLengthAttr( node, "h", markup->h() );
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,69 @@
|
||||
/* XmlTemplateCreator.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_XmlTemplateCreator_h
|
||||
#define model_XmlTemplateCreator_h
|
||||
|
||||
|
||||
#include "FrameCd.h"
|
||||
#include "FrameEllipse.h"
|
||||
#include "FrameRect.h"
|
||||
#include "FrameRound.h"
|
||||
#include "Layout.h"
|
||||
#include "Markup.h"
|
||||
#include "Template.h"
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class XmlTemplateCreator
|
||||
{
|
||||
public:
|
||||
XmlTemplateCreator() {}
|
||||
|
||||
bool writeTemplates( const QList<const Template*> tmplates, const QString& fileName );
|
||||
bool writeTemplate( const Template* tmplate, const QString& fileName );
|
||||
void createTemplateNode( QDomElement& parent, const Template* tmplate );
|
||||
|
||||
private:
|
||||
void createMetaNode( QDomElement& parent, const QString& attr, const QString& value );
|
||||
void createLabelNode( QDomElement& parent, const Frame* frame );
|
||||
void createLabelRectangleNode( QDomElement& parent, const FrameRect* frame );
|
||||
void createLabelEllipseNode( QDomElement& parent, const FrameEllipse* frame );
|
||||
void createLabelRoundNode( QDomElement& parent, const FrameRound* frame );
|
||||
void createLabelCdNode( QDomElement& parent, const FrameCd* frame );
|
||||
void createLabelNodeCommon( QDomElement& node, const Frame* frame );
|
||||
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 );
|
||||
void createMarkupRectNode( QDomElement& parent, const MarkupRect* markupRect );
|
||||
void createMarkupEllipseNode( QDomElement& parent, const MarkupEllipse* markupEllipse );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlTemplateCreator_h
|
||||
@@ -0,0 +1,408 @@
|
||||
/* XmlTemplateParser.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "XmlTemplateParser.h"
|
||||
|
||||
#include "Db.h"
|
||||
#include "FrameRect.h"
|
||||
#include "FrameCd.h"
|
||||
#include "FrameRound.h"
|
||||
#include "FrameEllipse.h"
|
||||
#include "Layout.h"
|
||||
#include "Markup.h"
|
||||
#include "Template.h"
|
||||
#include "XmlUtil.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDomDocument>
|
||||
#include <QDomNode>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
bool XmlTemplateParser::readFile( const QString &fileName )
|
||||
{
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::ReadOnly | QFile::Text) )
|
||||
{
|
||||
qWarning() << "Error: Cannot read file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QDomDocument doc;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( &file, false, &errorString, &errorLine, &errorColumn ) )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-templates" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-templates file";
|
||||
return false;
|
||||
}
|
||||
|
||||
parseRootNode( root );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseRootNode( const QDomElement &node )
|
||||
{
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Template" )
|
||||
{
|
||||
Template *tmplate = parseTemplateNode( child.toElement() );
|
||||
if ( tmplate != nullptr )
|
||||
{
|
||||
Db::registerTemplate( tmplate );
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Warning: could not create template, Ignored.";
|
||||
}
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Template *XmlTemplateParser::parseTemplateNode( const QDomElement &node )
|
||||
{
|
||||
QString brand = XmlUtil::getStringAttr( node, "brand", "" );
|
||||
QString part = XmlUtil::getStringAttr( node, "part", "" );
|
||||
|
||||
if ( (brand == "") || (part == "") )
|
||||
{
|
||||
// Try the deprecated "name" attribute.
|
||||
QString name = XmlUtil::getStringAttr( node, "name", "" );
|
||||
if ( name != "" )
|
||||
{
|
||||
QStringList fields = name.split( " ", QString::SkipEmptyParts );
|
||||
brand = fields[0];
|
||||
part = fields[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning() << "Error: missing name or brand/part attributes.";
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Template *tmplate = nullptr;
|
||||
|
||||
QString equivPart = XmlUtil::getStringAttr( node, "equiv", "" );
|
||||
if ( equivPart != nullptr )
|
||||
{
|
||||
tmplate = Template::fromEquiv( brand, part, equivPart );
|
||||
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Meta" )
|
||||
{
|
||||
parseMetaNode( child.toElement(), tmplate );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString description = XmlUtil::getI18nAttr( node, "description", "" );
|
||||
QString paperId = XmlUtil::getStringAttr( node, "size", "" );
|
||||
|
||||
if ( !Db::isPaperIdOther( paperId ) )
|
||||
{
|
||||
const Paper *paper = Db::lookupPaperFromId( paperId );
|
||||
if ( paper == nullptr )
|
||||
{
|
||||
qWarning() << "Error: unknown paper ID: " << paperId;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tmplate = new Template( brand, part, description,
|
||||
paper->id(), paper->width(), paper->height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Distance width = XmlUtil::getLengthAttr( node, "width", Distance(0) );
|
||||
Distance height = XmlUtil::getLengthAttr( node, "height", Distance(0) );
|
||||
|
||||
tmplate = new Template( brand, part, description, paperId, width, height );
|
||||
}
|
||||
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Meta" )
|
||||
{
|
||||
parseMetaNode( child.toElement(), tmplate );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Label-rectangle" )
|
||||
{
|
||||
parseLabelRectangleNode( child.toElement(), tmplate );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Label-ellipse" )
|
||||
{
|
||||
parseLabelEllipseNode( child.toElement(), tmplate );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Label-round" )
|
||||
{
|
||||
parseLabelRoundNode( child.toElement(), tmplate );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Label-cd" )
|
||||
{
|
||||
parseLabelCdNode( child.toElement(), tmplate );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tmplate;
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseMetaNode( const QDomElement &node, Template *tmplate )
|
||||
{
|
||||
QString productUrl = XmlUtil::getStringAttr( node, "product_url", "" );
|
||||
if ( productUrl != "" )
|
||||
{
|
||||
tmplate->setProductUrl( productUrl );
|
||||
}
|
||||
|
||||
QString categoryId = XmlUtil::getStringAttr( node, "category", "" );
|
||||
if ( categoryId != "" )
|
||||
{
|
||||
tmplate->addCategory( categoryId );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseLabelRectangleNode( 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 r = XmlUtil::getLengthAttr( node, "round", Distance(0) );
|
||||
|
||||
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 FrameRect( w, h, r, xWaste, yWaste, id );
|
||||
|
||||
parseLabelNodeCommon( node, frame );
|
||||
|
||||
tmplate->addFrame( frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseLabelEllipseNode( 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 waste = XmlUtil::getLengthAttr( node, "waste", Distance(0) );
|
||||
|
||||
Frame *frame = new FrameEllipse( w, h, waste, id );
|
||||
|
||||
parseLabelNodeCommon( node, frame );
|
||||
|
||||
tmplate->addFrame( frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseLabelRoundNode( const QDomElement &node, Template *tmplate )
|
||||
{
|
||||
QString id = XmlUtil::getStringAttr( node, "id", "0" );
|
||||
|
||||
Distance r = XmlUtil::getLengthAttr( node, "radius", Distance(0) );
|
||||
Distance waste = XmlUtil::getLengthAttr( node, "waste", Distance(0) );
|
||||
|
||||
Frame *frame = new FrameRound( r, waste, id );
|
||||
|
||||
parseLabelNodeCommon( node, frame );
|
||||
|
||||
tmplate->addFrame( frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseLabelCdNode( const QDomElement &node, Template *tmplate )
|
||||
{
|
||||
QString id = XmlUtil::getStringAttr( node, "id", "0" );
|
||||
|
||||
Distance r1 = XmlUtil::getLengthAttr( node, "radius", Distance(0) );
|
||||
Distance r2 = XmlUtil::getLengthAttr( node, "hole", Distance(0) );
|
||||
Distance w = XmlUtil::getLengthAttr( node, "width", Distance(0) );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "height", Distance(0) );
|
||||
Distance waste = XmlUtil::getLengthAttr( node, "waste", Distance(0) );
|
||||
|
||||
Frame *frame = new FrameCd( r1, r2, w, h, waste, id );
|
||||
|
||||
parseLabelNodeCommon( node, frame );
|
||||
|
||||
tmplate->addFrame( frame );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseLabelNodeCommon( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Layout" )
|
||||
{
|
||||
parseLayoutNode( child.toElement(), frame );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Markup-margin" )
|
||||
{
|
||||
parseMarkupMarginNode( child.toElement(), frame );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Markup-line" )
|
||||
{
|
||||
parseMarkupLineNode( child.toElement(), frame );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Markup-circle" )
|
||||
{
|
||||
parseMarkupCircleNode( child.toElement(), frame );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Markup-rect" )
|
||||
{
|
||||
parseMarkupRectNode( child.toElement(), frame );
|
||||
}
|
||||
else if ( child.toElement().tagName() == "Markup-ellipse" )
|
||||
{
|
||||
parseMarkupEllipseNode( child.toElement(), frame );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseLayoutNode( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
int nX = XmlUtil::getIntAttr( node, "nx", 1 );
|
||||
int nY = XmlUtil::getIntAttr( node, "ny", 1 );
|
||||
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x0", Distance(0) );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y0", Distance(0) );
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseMarkupMarginNode( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
Distance size = XmlUtil::getLengthAttr( node, "size", Distance(0) );
|
||||
|
||||
frame->addMarkup( new MarkupMargin( frame, size ) );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseMarkupLineNode( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
Distance x1 = XmlUtil::getLengthAttr( node, "x1", Distance(0) );
|
||||
Distance y1 = XmlUtil::getLengthAttr( node, "y1", Distance(0) );
|
||||
Distance x2 = XmlUtil::getLengthAttr( node, "x2", Distance(0) );
|
||||
Distance y2 = XmlUtil::getLengthAttr( node, "y2", Distance(0) );
|
||||
|
||||
frame->addMarkup( new MarkupLine( x1, y1, x2, y2 ) );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseMarkupCircleNode( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
Distance x0 = XmlUtil::getLengthAttr( node, "x0", Distance(0) );
|
||||
Distance y0 = XmlUtil::getLengthAttr( node, "y0", Distance(0) );
|
||||
Distance r = XmlUtil::getLengthAttr( node, "radius", Distance(0) );
|
||||
|
||||
frame->addMarkup( new MarkupCircle( x0, y0, r ) );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseMarkupRectNode( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
Distance x1 = XmlUtil::getLengthAttr( node, "x1", Distance(0) );
|
||||
Distance y1 = XmlUtil::getLengthAttr( node, "y1", Distance(0) );
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", Distance(0) );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", Distance(0) );
|
||||
Distance r = XmlUtil::getLengthAttr( node, "r", Distance(0) );
|
||||
|
||||
frame->addMarkup( new MarkupRect( x1, y1, w, h, r ) );
|
||||
}
|
||||
|
||||
|
||||
void XmlTemplateParser::parseMarkupEllipseNode( const QDomElement &node, Frame *frame )
|
||||
{
|
||||
Distance x1 = XmlUtil::getLengthAttr( node, "x1", Distance(0) );
|
||||
Distance y1 = XmlUtil::getLengthAttr( node, "y1", Distance(0) );
|
||||
Distance w = XmlUtil::getLengthAttr( node, "w", Distance(0) );
|
||||
Distance h = XmlUtil::getLengthAttr( node, "h", Distance(0) );
|
||||
|
||||
frame->addMarkup( new MarkupEllipse( x1, y1, w, h ) );
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,62 @@
|
||||
/* XmlTemplateParser.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_XmlTemplateParser_h
|
||||
#define model_XmlTemplateParser_h
|
||||
|
||||
|
||||
#include "Template.h"
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class XmlTemplateParser
|
||||
{
|
||||
public:
|
||||
XmlTemplateParser() {}
|
||||
|
||||
bool readFile( const QString &fileName );
|
||||
Template *parseTemplateNode( const QDomElement &node );
|
||||
|
||||
private:
|
||||
void parseRootNode( const QDomElement &node );
|
||||
void parseMetaNode( const QDomElement &node, Template *tmplate );
|
||||
void parseLabelRectangleNode( const QDomElement &node, Template *tmplate );
|
||||
void parseLabelEllipseNode( const QDomElement &node, Template *tmplate );
|
||||
void parseLabelRoundNode( const QDomElement &node, Template *tmplate );
|
||||
void parseLabelCdNode( 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 );
|
||||
void parseMarkupLineNode( const QDomElement &node, Frame *frame );
|
||||
void parseMarkupCircleNode( const QDomElement &node, Frame *frame );
|
||||
void parseMarkupRectNode( const QDomElement &node, Frame *frame );
|
||||
void parseMarkupEllipseNode( const QDomElement &node, Frame *frame );
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlTemplateParser_h
|
||||
@@ -0,0 +1,407 @@
|
||||
/* XmlUtil.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "XmlUtil.h"
|
||||
|
||||
#include <QTextStream>
|
||||
#include <QCoreApplication>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
//
|
||||
// Static data
|
||||
//
|
||||
XmlUtil* XmlUtil::mInstance = nullptr;
|
||||
|
||||
|
||||
XmlUtil::XmlUtil()
|
||||
{
|
||||
mUnits = Units(Units::PT);
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::init()
|
||||
{
|
||||
if ( mInstance == nullptr )
|
||||
{
|
||||
mInstance = new XmlUtil();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Units XmlUtil::units()
|
||||
{
|
||||
init();
|
||||
|
||||
return mInstance->mUnits;
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setUnits( const Units& units )
|
||||
{
|
||||
init();
|
||||
|
||||
mInstance->mUnits = units;
|
||||
}
|
||||
|
||||
|
||||
QString XmlUtil::getStringAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
const QString& default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
return node.attribute( name, default_value );
|
||||
}
|
||||
|
||||
|
||||
double XmlUtil::getDoubleAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
double default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
bool ok;
|
||||
double value = valueString.toDouble(& ok );
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
qWarning() << "Error: bad double value in attribute "
|
||||
<< node.tagName() << ":" << name << "=" << valueString;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
bool XmlUtil::getBoolAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
bool default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
int intValue = valueString.toInt();
|
||||
|
||||
if ( (valueString == "True") ||
|
||||
(valueString == "TRUE") ||
|
||||
(valueString == "true") ||
|
||||
(intValue == 1) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( (valueString == "False") ||
|
||||
(valueString == "FALSE") ||
|
||||
(valueString == "false") ||
|
||||
(intValue == 0) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
qWarning() << "Error: bad boolean value in attribute "
|
||||
<< node.tagName() << ":" << name << "=" << valueString;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
int XmlUtil::getIntAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
int default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
bool ok;
|
||||
int value = valueString.toInt(& ok );
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
qWarning() << "Error: bad integer value in attribute "
|
||||
<< node.tagName() << ":" << name << "=" << valueString;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
uint32_t XmlUtil::getUIntAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
uint32_t default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
bool ok;
|
||||
uint32_t value = valueString.toUInt(& ok, 0 );
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
qWarning() << "Error: bad unsigned integer value in attribute "
|
||||
<< node.tagName() << ":" << name << "=" << valueString;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
QString XmlUtil::getI18nAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
const QString& default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString i18nString = node.attribute( QString("_").append(name), "" );
|
||||
|
||||
if ( i18nString == "" )
|
||||
{
|
||||
return node.attribute( name, default_value );
|
||||
}
|
||||
|
||||
return QCoreApplication::translate( "XmlStrings", i18nString.toUtf8().constData() );
|
||||
}
|
||||
|
||||
|
||||
Distance XmlUtil::getLengthAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
const Distance& default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
double value;
|
||||
QString unitsString;
|
||||
QTextStream valueStream( &valueString, QIODevice::ReadOnly );
|
||||
|
||||
valueStream >> value >> unitsString;
|
||||
|
||||
if ( !unitsString.isEmpty() && !Units::isIdValid( unitsString ) )
|
||||
{
|
||||
qWarning() << "Error: bad length value in attribute "
|
||||
<< node.tagName() << ":" << name << "=" << valueString;
|
||||
}
|
||||
|
||||
return Distance( value, unitsString );
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
QFont::Weight XmlUtil::getWeightAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
QFont::Weight default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
if ( valueString == "bold" )
|
||||
{
|
||||
return QFont::Bold;
|
||||
}
|
||||
else if ( valueString == "normal" )
|
||||
{
|
||||
return QFont::Normal;
|
||||
}
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
Qt::Alignment XmlUtil::getAlignmentAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
Qt::Alignment default_value )
|
||||
{
|
||||
init();
|
||||
|
||||
QString valueString = node.attribute( name, "" );
|
||||
if ( valueString != "" )
|
||||
{
|
||||
if ( valueString == "right" )
|
||||
{
|
||||
return Qt::AlignRight;
|
||||
}
|
||||
else if ( valueString == "hcenter" )
|
||||
{
|
||||
return Qt::AlignHCenter;
|
||||
}
|
||||
else if ( valueString == "left" )
|
||||
{
|
||||
return Qt::AlignLeft;
|
||||
}
|
||||
else if ( valueString == "bottom" )
|
||||
{
|
||||
return Qt::AlignBottom;
|
||||
}
|
||||
else if ( valueString == "vcenter" )
|
||||
{
|
||||
return Qt::AlignVCenter;
|
||||
}
|
||||
else if ( valueString == "top" )
|
||||
{
|
||||
return Qt::AlignTop;
|
||||
}
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setStringAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
const QString& value )
|
||||
{
|
||||
init();
|
||||
|
||||
node.setAttribute( name, value );
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setDoubleAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
double value )
|
||||
{
|
||||
init();
|
||||
|
||||
node.setAttribute( name, QString::number(value) );
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setBoolAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
bool value )
|
||||
{
|
||||
init();
|
||||
|
||||
node.setAttribute( name, value ? "true" : "false" );
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setIntAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
int value )
|
||||
{
|
||||
init();
|
||||
|
||||
node.setAttribute( name, QString::number(value) );
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setUIntAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
uint32_t value )
|
||||
{
|
||||
init();
|
||||
|
||||
node.setAttribute( name, "0x" + QString::number(value, 16) );
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setLengthAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
const Distance& value )
|
||||
{
|
||||
init();
|
||||
|
||||
Units units = mInstance->mUnits;
|
||||
node.setAttribute( name, QString::number(value.inUnits(units)) + units.toIdString() );
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setWeightAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
QFont::Weight value )
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case QFont::Bold:
|
||||
node.setAttribute( name, "bold" );
|
||||
break;
|
||||
default:
|
||||
node.setAttribute( name, "normal" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlUtil::setAlignmentAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
Qt::Alignment value )
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case Qt::AlignRight:
|
||||
node.setAttribute( name, "right" );
|
||||
break;
|
||||
case Qt::AlignHCenter:
|
||||
node.setAttribute( name, "hcenter" );
|
||||
break;
|
||||
case Qt::AlignLeft:
|
||||
node.setAttribute( name, "left" );
|
||||
break;
|
||||
case Qt::AlignBottom:
|
||||
node.setAttribute( name, "bottom" );
|
||||
break;
|
||||
case Qt::AlignVCenter:
|
||||
node.setAttribute( name, "vcenter" );
|
||||
break;
|
||||
case Qt::AlignTop:
|
||||
node.setAttribute( name, "top" );
|
||||
break;
|
||||
default:
|
||||
node.setAttribute( name, "left" );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace glabels::model
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
/* XmlUtil.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_XmlUtil_h
|
||||
#define model_XmlUtil_h
|
||||
|
||||
|
||||
#include "Distance.h"
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QFont>
|
||||
#include <QString>
|
||||
#include <Qt>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class XmlUtil
|
||||
{
|
||||
private:
|
||||
XmlUtil();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
static void init();
|
||||
|
||||
static Units units();
|
||||
static void setUnits( const Units& units );
|
||||
|
||||
static QString getStringAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
const QString& default_value );
|
||||
|
||||
static double getDoubleAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
double default_value );
|
||||
|
||||
static bool getBoolAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
bool default_value );
|
||||
|
||||
static int getIntAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
int default_value );
|
||||
|
||||
static uint32_t getUIntAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
uint32_t default_value );
|
||||
|
||||
static QString getI18nAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
const QString& default_value );
|
||||
|
||||
static Distance getLengthAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
const Distance& default_value );
|
||||
|
||||
static QFont::Weight getWeightAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
QFont::Weight default_value );
|
||||
|
||||
static Qt::Alignment getAlignmentAttr( const QDomElement& node,
|
||||
const QString& name,
|
||||
Qt::Alignment default_value );
|
||||
|
||||
|
||||
static void setStringAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
const QString& value );
|
||||
|
||||
static void setDoubleAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
double value );
|
||||
|
||||
static void setBoolAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
bool value );
|
||||
|
||||
static void setIntAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
int value );
|
||||
|
||||
static void setUIntAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
uint32_t value );
|
||||
|
||||
static void setLengthAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
const Distance& value );
|
||||
|
||||
static void setWeightAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
QFont::Weight value );
|
||||
|
||||
static void setAlignmentAttr( QDomElement& node,
|
||||
const QString& name,
|
||||
Qt::Alignment value );
|
||||
|
||||
|
||||
private:
|
||||
Units mUnits;
|
||||
|
||||
static XmlUtil* mInstance;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlUtil_h
|
||||
@@ -0,0 +1,103 @@
|
||||
/* XmlVendorParser.cpp
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 "XmlVendorParser.h"
|
||||
|
||||
#include "Db.h"
|
||||
#include "Vendor.h"
|
||||
#include "XmlUtil.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QDomNode>
|
||||
#include <QFile>
|
||||
#include <QtDebug>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
bool XmlVendorParser::readFile( const QString &fileName )
|
||||
{
|
||||
QFile file( fileName );
|
||||
|
||||
if ( !file.open( QFile::ReadOnly | QFile::Text) )
|
||||
{
|
||||
qWarning() << "Error: Cannot read file " << fileName
|
||||
<< ": " << file.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QDomDocument doc;
|
||||
QString errorString;
|
||||
int errorLine;
|
||||
int errorColumn;
|
||||
|
||||
if ( !doc.setContent( &file, false, &errorString, &errorLine, &errorColumn ) )
|
||||
{
|
||||
qWarning() << "Error: Parse error at line " << errorLine
|
||||
<< "column " << errorColumn
|
||||
<< ": " << errorString;
|
||||
return false;
|
||||
}
|
||||
|
||||
QDomElement root = doc.documentElement();
|
||||
if ( root.tagName() != "Glabels-vendors" )
|
||||
{
|
||||
qWarning() << "Error: Not a Glabels-vendors file.";
|
||||
return false;
|
||||
}
|
||||
|
||||
parseRootNode( root );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void XmlVendorParser::parseRootNode( const QDomElement &node )
|
||||
{
|
||||
for ( QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling() )
|
||||
{
|
||||
if ( child.toElement().tagName() == "Vendor" )
|
||||
{
|
||||
parseVendorNode( child.toElement() );
|
||||
}
|
||||
else if ( !child.isComment() )
|
||||
{
|
||||
qWarning() << "Warning: bad element: "
|
||||
<< child.toElement().tagName()
|
||||
<< ", Ignored.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void XmlVendorParser::parseVendorNode( const QDomElement &node )
|
||||
{
|
||||
QString name = XmlUtil::getStringAttr( node, "name", "" );
|
||||
QString url = XmlUtil::getStringAttr( node, "url", "" );
|
||||
|
||||
Vendor *vendor = new Vendor( name, url );
|
||||
if ( vendor != nullptr )
|
||||
{
|
||||
Db::registerVendor( vendor );
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace glabels::model
|
||||
@@ -0,0 +1,47 @@
|
||||
/* XmlVendorParser.h
|
||||
*
|
||||
* Copyright (C) 2013-2016 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 model_XmlVendorParser_h
|
||||
#define model_XmlVendorParser_h
|
||||
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace glabels::model
|
||||
{
|
||||
|
||||
class XmlVendorParser
|
||||
{
|
||||
public:
|
||||
XmlVendorParser() {}
|
||||
|
||||
bool readFile( const QString &fileName );
|
||||
|
||||
private:
|
||||
void parseRootNode( const QDomElement &node );
|
||||
void parseVendorNode( const QDomElement &node );
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // model_XmlVendorParser_h
|
||||
@@ -0,0 +1,11 @@
|
||||
if (Qt5Test_FOUND)
|
||||
|
||||
#=======================================
|
||||
# Test SubstitutionField class
|
||||
#=======================================
|
||||
qt5_wrap_cpp (TestSubstitutionField_moc_sources TestSubstitutionField.h)
|
||||
add_executable (TestSubstitutionField TestSubstitutionField.cpp ../SubstitutionField.cpp ${TestSubstitutionField_moc_sources})
|
||||
target_link_libraries (TestSubstitutionField Model Qt5::Test)
|
||||
add_test (NAME SubstitutionField COMMAND TestSubstitutionField)
|
||||
|
||||
endif (Qt5Test_FOUND)
|
||||
@@ -0,0 +1,342 @@
|
||||
/* TestSubstitutionField.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 "TestSubstitutionField.h"
|
||||
|
||||
#include "model/SubstitutionField.h"
|
||||
|
||||
|
||||
QTEST_MAIN(TestSubstitutionField)
|
||||
|
||||
|
||||
void TestSubstitutionField::parseValid()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
//
|
||||
// Valid substitution fields (concatenated in single input string)
|
||||
//
|
||||
QString input = "${1234}${abc:=ABC}${x:%08.2f}${y:%08.2f:=12.34}${ADDR2:n}";
|
||||
QStringRef s = &input;
|
||||
|
||||
model::SubstitutionField f1;
|
||||
QCOMPARE( model::SubstitutionField::parse( s, f1 ), true );
|
||||
QCOMPARE( f1.fieldName(), QString( "1234" ) );
|
||||
QCOMPARE( f1.newLine(), false );
|
||||
|
||||
model::SubstitutionField f2;
|
||||
QCOMPARE( model::SubstitutionField::parse( s, f2 ), true );
|
||||
QCOMPARE( f2.fieldName(), QString( "abc" ) );
|
||||
QCOMPARE( f2.defaultValue(), QString( "ABC" ) );
|
||||
QCOMPARE( f2.newLine(), false );
|
||||
|
||||
model::SubstitutionField f3;
|
||||
QCOMPARE( model::SubstitutionField::parse( s, f3 ), true );
|
||||
QCOMPARE( f3.fieldName(), QString( "x" ) );
|
||||
QCOMPARE( f3.format(), QString( "%08.2f" ) );
|
||||
QCOMPARE( f3.formatType(), QChar('f') );
|
||||
QCOMPARE( f3.newLine(), false );
|
||||
|
||||
model::SubstitutionField f4;
|
||||
QCOMPARE( model::SubstitutionField::parse( s, f4 ), true );
|
||||
QCOMPARE( f4.fieldName(), QString( "y" ) );
|
||||
QCOMPARE( f4.defaultValue(), QString( "12.34" ) );
|
||||
QCOMPARE( f4.format(), QString( "%08.2f" ) );
|
||||
QCOMPARE( f4.formatType(), QChar('f') );
|
||||
QCOMPARE( f4.newLine(), false );
|
||||
|
||||
model::SubstitutionField f5;
|
||||
QCOMPARE( model::SubstitutionField::parse( s, f5 ), true );
|
||||
QCOMPARE( f5.fieldName(), QString( "ADDR2" ) );
|
||||
QCOMPARE( f5.newLine(), true );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::parseInvalid()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
//
|
||||
// Ordinary text
|
||||
//
|
||||
QString input5 = "Abcdefg";
|
||||
QStringRef s5 = &input5;
|
||||
model::SubstitutionField f5;
|
||||
QCOMPARE( model::SubstitutionField::parse( s5, f5 ), false );
|
||||
QCOMPARE( s5, QStringRef( &input5 ) ); // Should not advance string reference
|
||||
|
||||
//
|
||||
// Invalid substitution fields (which are treated as ordinary text)
|
||||
//
|
||||
QString input6 = "$abc";
|
||||
QStringRef s6 = &input6;
|
||||
model::SubstitutionField f6;
|
||||
QCOMPARE( model::SubstitutionField::parse( s6, f6 ), false );
|
||||
QCOMPARE( s6, QStringRef( &input6 ) ); // Should not advance string reference
|
||||
|
||||
QString input7 = "${abc";
|
||||
QStringRef s7 = &input7;
|
||||
model::SubstitutionField f7;
|
||||
QCOMPARE( model::SubstitutionField::parse( s7, f7 ), false );
|
||||
QCOMPARE( s7, QStringRef( &input7 ) ); // Should not advance string reference
|
||||
|
||||
QString input8 = "${abc:}";
|
||||
QStringRef s8 = &input8;
|
||||
model::SubstitutionField f8;
|
||||
QCOMPARE( model::SubstitutionField::parse( s8, f8 ), false );
|
||||
QCOMPARE( s8, QStringRef( &input8 ) ); // Should not advance string reference
|
||||
|
||||
// Even though format is invalid, let it slide. Overall structure still good. Format will be ignored.
|
||||
QString input9 = "${abc:%3.2}";
|
||||
QStringRef s9 = &input9;
|
||||
model::SubstitutionField f9;
|
||||
QCOMPARE( model::SubstitutionField::parse( s9, f9 ), true );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::construction()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField f1( "${1234}" );
|
||||
QCOMPARE( f1.fieldName(), QString( "1234" ) );
|
||||
|
||||
model::SubstitutionField f2( "${abc:=ABC}" );
|
||||
QCOMPARE( f2.fieldName(), QString( "abc" ) );
|
||||
QCOMPARE( f2.defaultValue(), QString( "ABC" ) );
|
||||
|
||||
model::SubstitutionField f3( "${x:%08.2f}" );
|
||||
QCOMPARE( f3.fieldName(), QString( "x" ) );
|
||||
QCOMPARE( f3.format(), QString( "%08.2f" ) );
|
||||
QCOMPARE( f3.formatType(), QChar('f') );
|
||||
|
||||
model::SubstitutionField f4( "${y:%08.2f:=12.34}" );
|
||||
QCOMPARE( f4.fieldName(), QString( "y" ) );
|
||||
QCOMPARE( f4.defaultValue(), QString( "12.34" ) );
|
||||
QCOMPARE( f4.format(), QString( "%08.2f" ) );
|
||||
QCOMPARE( f4.formatType(), QChar('f') );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::simpleEvaluation()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField f1( "${1}" );
|
||||
model::SubstitutionField f2( "${2}" );
|
||||
model::SubstitutionField f3( "${3}" );
|
||||
model::SubstitutionField f4( "${4}" );
|
||||
|
||||
merge::Record record1;
|
||||
record1[ "1" ] = "Abcdefg";
|
||||
record1[ "2" ] = "Hijklmn";
|
||||
record1[ "3" ] = "Opqrstu";
|
||||
record1[ "4" ] = "Vwxyz!@";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record1 ), QString( "Abcdefg" ) );
|
||||
QCOMPARE( f2.evaluate( &record1 ), QString( "Hijklmn" ) );
|
||||
QCOMPARE( f3.evaluate( &record1 ), QString( "Opqrstu" ) );
|
||||
QCOMPARE( f4.evaluate( &record1 ), QString( "Vwxyz!@" ) );
|
||||
|
||||
merge::Record record2;
|
||||
record2[ "1" ] = "1234567";
|
||||
record2[ "2" ] = "FooBar";
|
||||
record2[ "3" ] = "8901234";
|
||||
record2[ "4" ] = "#$%^&*";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record2 ), QString( "1234567" ) );
|
||||
QCOMPARE( f2.evaluate( &record2 ), QString( "FooBar" ) );
|
||||
QCOMPARE( f3.evaluate( &record2 ), QString( "8901234" ) );
|
||||
QCOMPARE( f4.evaluate( &record2 ), QString( "#$%^&*" ) );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::defaultValueEvaluation()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField f1( "${1:=foo1}" );
|
||||
model::SubstitutionField f2( "${2:=foo2}" );
|
||||
model::SubstitutionField f3( "${3:=foo3}" );
|
||||
model::SubstitutionField f4( "${4:=foo4}" );
|
||||
|
||||
merge::Record record1;
|
||||
record1[ "1" ] = "Abcdefg";
|
||||
record1[ "2" ] = "Hijklmn";
|
||||
record1[ "3" ] = "Opqrstu";
|
||||
record1[ "4" ] = "Vwxyz!@";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record1 ), QString( "Abcdefg" ) );
|
||||
QCOMPARE( f2.evaluate( &record1 ), QString( "Hijklmn" ) );
|
||||
QCOMPARE( f3.evaluate( &record1 ), QString( "Opqrstu" ) );
|
||||
QCOMPARE( f4.evaluate( &record1 ), QString( "Vwxyz!@" ) );
|
||||
|
||||
merge::Record record2; // All fields empty
|
||||
|
||||
QCOMPARE( f1.evaluate( &record2 ), QString( "foo1" ) );
|
||||
QCOMPARE( f2.evaluate( &record2 ), QString( "foo2" ) );
|
||||
QCOMPARE( f3.evaluate( &record2 ), QString( "foo3" ) );
|
||||
QCOMPARE( f4.evaluate( &record2 ), QString( "foo4" ) );
|
||||
|
||||
merge::Record record3;
|
||||
record3[ "1" ] = "xyzzy";
|
||||
// Field "2" empty
|
||||
// Field "3" empty
|
||||
record3[ "4" ] = "plugh";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record3 ), QString( "xyzzy" ) );
|
||||
QCOMPARE( f2.evaluate( &record3 ), QString( "foo2" ) );
|
||||
QCOMPARE( f3.evaluate( &record3 ), QString( "foo3" ) );
|
||||
QCOMPARE( f4.evaluate( &record3 ), QString( "plugh" ) );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::formattedStringEvaluation()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField f1( "${1:%10s}" );
|
||||
model::SubstitutionField f2( "${2:%10s}" );
|
||||
model::SubstitutionField f3( "${3:%10s}" );
|
||||
model::SubstitutionField f4( "${4:%10s}" );
|
||||
|
||||
model::SubstitutionField f5( "${5:%-10s}" );
|
||||
model::SubstitutionField f6( "${6:%-10s}" );
|
||||
model::SubstitutionField f7( "${7:%-10s}" );
|
||||
model::SubstitutionField f8( "${8:%-10s}" );
|
||||
|
||||
merge::Record record1;
|
||||
record1[ "1" ] = "0";
|
||||
record1[ "2" ] = "1";
|
||||
record1[ "3" ] = "-1";
|
||||
record1[ "4" ] = "3.14";
|
||||
|
||||
record1[ "5" ] = "0";
|
||||
record1[ "6" ] = "100";
|
||||
record1[ "7" ] = "-100";
|
||||
record1[ "8" ] = "3.14";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record1 ), QString( " 0" ) );
|
||||
QCOMPARE( f2.evaluate( &record1 ), QString( " 1" ) );
|
||||
QCOMPARE( f3.evaluate( &record1 ), QString( " -1" ) );
|
||||
QCOMPARE( f4.evaluate( &record1 ), QString( " 3.14" ) );
|
||||
|
||||
QCOMPARE( f5.evaluate( &record1 ), QString( "0 " ) );
|
||||
QCOMPARE( f6.evaluate( &record1 ), QString( "100 " ) );
|
||||
QCOMPARE( f7.evaluate( &record1 ), QString( "-100 " ) );
|
||||
QCOMPARE( f8.evaluate( &record1 ), QString( "3.14 " ) );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::formattedFloatEvaluation()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField f1( "${1:%+5.2f}" );
|
||||
model::SubstitutionField f2( "${2:%+5.2f}" );
|
||||
model::SubstitutionField f3( "${3:%+5.2f}" );
|
||||
model::SubstitutionField f4( "${4:%+5.2f}" );
|
||||
|
||||
model::SubstitutionField f5( "${5:%+5.2e}" );
|
||||
model::SubstitutionField f6( "${6:%+5.2e}" );
|
||||
model::SubstitutionField f7( "${7:%+5.2e}" );
|
||||
model::SubstitutionField f8( "${8:%+5.2e}" );
|
||||
|
||||
merge::Record record1;
|
||||
record1[ "1" ] = "0";
|
||||
record1[ "2" ] = "1";
|
||||
record1[ "3" ] = "-1";
|
||||
record1[ "4" ] = "3.14";
|
||||
|
||||
record1[ "5" ] = "0";
|
||||
record1[ "6" ] = "100";
|
||||
record1[ "7" ] = "-100";
|
||||
record1[ "8" ] = "3.14";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record1 ), QString( "+0.00" ) );
|
||||
QCOMPARE( f2.evaluate( &record1 ), QString( "+1.00" ) );
|
||||
QCOMPARE( f3.evaluate( &record1 ), QString( "-1.00" ) );
|
||||
QCOMPARE( f4.evaluate( &record1 ), QString( "+3.14" ) );
|
||||
|
||||
QCOMPARE( f5.evaluate( &record1 ), QString( "+0.00e+00" ) );
|
||||
QCOMPARE( f6.evaluate( &record1 ), QString( "+1.00e+02" ) );
|
||||
QCOMPARE( f7.evaluate( &record1 ), QString( "-1.00e+02" ) );
|
||||
QCOMPARE( f8.evaluate( &record1 ), QString( "+3.14e+00" ) );
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::formattedIntEvaluation()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField f1( "${1:%08d}" );
|
||||
model::SubstitutionField f2( "${2:%08d}" );
|
||||
model::SubstitutionField f3( "${3:%08d}" );
|
||||
model::SubstitutionField f4( "${4:%08d}" );
|
||||
|
||||
model::SubstitutionField f5( "${5:%08x}" );
|
||||
model::SubstitutionField f6( "${6:%08x}" );
|
||||
model::SubstitutionField f7( "${7:%08x}" );
|
||||
model::SubstitutionField f8( "${8:%08x}" );
|
||||
|
||||
merge::Record record1;
|
||||
record1[ "1" ] = "0";
|
||||
record1[ "2" ] = "1";
|
||||
record1[ "3" ] = "-1";
|
||||
record1[ "4" ] = "3.14";
|
||||
|
||||
record1[ "5" ] = "100";
|
||||
record1[ "6" ] = "0x100";
|
||||
record1[ "7" ] = "-1";
|
||||
record1[ "8" ] = "314";
|
||||
|
||||
QCOMPARE( f1.evaluate( &record1 ), QString( "00000000" ) );
|
||||
QCOMPARE( f2.evaluate( &record1 ), QString( "00000001" ) );
|
||||
QCOMPARE( f3.evaluate( &record1 ), QString( "-0000001" ) );
|
||||
QCOMPARE( f4.evaluate( &record1 ), QString( "00000000" ) ); // Invalid integer value
|
||||
|
||||
QCOMPARE( f5.evaluate( &record1 ), QString( "00000064" ) ); // 100(decimal) == 64(hex)
|
||||
QCOMPARE( f6.evaluate( &record1 ), QString( "00000100" ) );
|
||||
QCOMPARE( f7.evaluate( &record1 ), QString( "00000000" ) ); // Invalid unsigned integer
|
||||
QCOMPARE( f8.evaluate( &record1 ), QString( "0000013a" ) ); // 314(decimal) == 13a(hex)
|
||||
}
|
||||
|
||||
|
||||
void TestSubstitutionField::newLineEvaluation()
|
||||
{
|
||||
using namespace glabels;
|
||||
|
||||
model::SubstitutionField addr2( "${ADDR2:n}" );
|
||||
QCOMPARE( addr2.fieldName(), QString( "ADDR2" ) );
|
||||
QCOMPARE( addr2.newLine(), true );
|
||||
|
||||
merge::Record record1;
|
||||
record1[ "ADDR2" ] = "Apt. 5B";
|
||||
|
||||
merge::Record record2;
|
||||
record2[ "ADDR2" ] = ""; // ADDR2 Empty
|
||||
|
||||
merge::Record record3;
|
||||
// ADDR2 not defined
|
||||
|
||||
QCOMPARE( addr2.evaluate( &record1 ), QString( "\nApt. 5B" ) ); // Prepends a newline
|
||||
QCOMPARE( addr2.evaluate( &record2 ), QString( "" ) ); // Evaluates empty
|
||||
QCOMPARE( addr2.evaluate( &record3 ), QString( "" ) ); // Evaluates empty
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* TestSubstitutionField.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/>.
|
||||
*/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
|
||||
class TestSubstitutionField : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void parseValid();
|
||||
void parseInvalid();
|
||||
void construction();
|
||||
void simpleEvaluation();
|
||||
void defaultValueEvaluation();
|
||||
void formattedStringEvaluation();
|
||||
void formattedFloatEvaluation();
|
||||
void formattedIntEvaluation();
|
||||
void newLineEvaluation();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user