446 changes: 416 additions & 30 deletions src/core/qgsvectorfilewriter.cpp

Large diffs are not rendered by default.

48 changes: 45 additions & 3 deletions src/core/qgsvectorfilewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@

#include "qgsvectorlayer.h"
#include "qgsfield.h"
#include "qgssymbolv2.h"

#include <QPair>

typedef void *OGRDataSourceH;
typedef void *OGRLayerH;
typedef void *OGRGeometryH;
typedef void *OGRFeatureH;

class QgsSymbolLayerV2;
class QTextCodec;

/** \ingroup core
Expand Down Expand Up @@ -56,6 +59,14 @@ class CORE_EXPORT QgsVectorFileWriter
ErrInvalidLayer, // added in 2.0
};

//added in 2.0
enum SymbologyExport
{
NoSymbology = 0, //export only data
FeatureSymbology, //Keeps the number of features and export symbology per feature
SymbolLayerSymbology //Exports one feature per symbol layer (considering symbol levels)
};

/** Write contents of vector layer to an (OGR supported) vector formt
@note: this method was added in version 1.5
@param layer layer to write
Expand All @@ -81,7 +92,9 @@ class CORE_EXPORT QgsVectorFileWriter
const QStringList &datasourceOptions = QStringList(), // added in 1.6
const QStringList &layerOptions = QStringList(), // added in 1.6
bool skipAttributeCreation = false, // added in 1.6
QString *newFilename = 0 // added in 1.9
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
double symbologyScale = 1.0 // added in 2.0
);

/** create shapefile and initialize it */
Expand All @@ -93,7 +106,8 @@ class CORE_EXPORT QgsVectorFileWriter
const QString& driverName = "ESRI Shapefile",
const QStringList &datasourceOptions = QStringList(), // added in 1.6
const QStringList &layerOptions = QStringList(), // added in 1.6
QString *newFilename = 0 // added in 1.9
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology//added in 2.0
);

/**Returns map with format filter string as key and OGR format key as value*/
Expand All @@ -120,7 +134,7 @@ class CORE_EXPORT QgsVectorFileWriter
QString errorMessage();

/** add feature to the currently opened shapefile */
bool addFeature( QgsFeature& feature );
bool addFeature( QgsFeature& feature, QgsFeatureRendererV2* renderer = 0, QGis::UnitType outputUnit = QGis::Meters );

//! @note not available in python bindings
QMap<int, int> attrIdxToOgrIdx() { return mAttrIdxToOgrIdx; }
Expand All @@ -134,6 +148,12 @@ class CORE_EXPORT QgsVectorFileWriter
*/
static bool deleteShapeFile( QString theFileName );

SymbologyExport symbologyExport() const { return mSymbologyExport; }
void setSymbologyExport( SymbologyExport symExport ) { mSymbologyExport = symExport; }

double symbologyScaleDenominator() const { return mSymbologyScaleDenominator; }
void setSymbologyScaleDenominator( double d ) { mSymbologyScaleDenominator = d; }

protected:
//! @note not available in python bindings
OGRGeometryH createEmptyGeometry( QGis::WkbType wkbType );
Expand All @@ -156,8 +176,30 @@ class CORE_EXPORT QgsVectorFileWriter
/** map attribute indizes to OGR field indexes */
QMap<int, int> mAttrIdxToOgrIdx;

SymbologyExport mSymbologyExport;

QMap< QgsSymbolLayerV2*, QString > mSymbolLayerTable;

/**Scale for symbology export (e.g. for symbols units in map units)*/
double mSymbologyScaleDenominator;

private:
static bool driverMetadata( QString driverName, QString &longName, QString &trLongName, QString &glob, QString &ext );
void createSymbolLayerTable( QgsVectorLayer* vl, const QgsCoordinateTransform* ct, OGRDataSourceH ds );
OGRFeatureH createFeature( QgsFeature& feature );
bool writeFeature( OGRLayerH layer, OGRFeatureH feature );

/**Writes features considering symbol level order*/
WriterError exportFeaturesSymbolLevels( QgsVectorLayer* layer, QgsFeatureIterator& fit, const QgsCoordinateTransform* ct, QString* errorMessage = 0 );
double mmScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits );
double mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits );
QgsRenderContext renderContext() const;
void startRender( QgsVectorLayer* vl ) const;
void stopRender( QgsVectorLayer* vl ) const;
QgsFeatureRendererV2* symbologyRenderer( QgsVectorLayer* vl ) const;
/**Adds attributes needed for classification*/
void addRendererAttributes( QgsVectorLayer* vl, QgsAttributeList& attList );

};

#endif
26 changes: 26 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,17 @@ void QgsSimpleFillSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
QgsSymbolLayerV2Utils::createDisplacementElement( doc, symbolizerElem, mOffset );
}

QString QgsSimpleFillSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
{
//brush
QString symbolStyle;
symbolStyle.append( QgsSymbolLayerV2Utils::ogrFeatureStyleBrush( mColor ) );
symbolStyle.append( ";" );
//pen
symbolStyle.append( QgsSymbolLayerV2Utils::ogrFeatureStylePen( mBorderWidth, mmScaleFactor, mapUnitScaleFactor, mBorderColor ) );
return symbolStyle;
}

QgsSymbolLayerV2* QgsSimpleFillSymbolLayerV2::createFromSld( QDomElement &element )
{
QgsDebugMsg( "Entered." );
Expand Down Expand Up @@ -907,6 +918,21 @@ void QgsLinePatternFillSymbolLayer::toSld( QDomDocument &doc, QDomElement &eleme
}
}

QString QgsLinePatternFillSymbolLayer::ogrFeatureStyle( double widthScaleFactor ) const
{
QString featureStyle;
featureStyle.append( "Brush(" );
featureStyle.append( QString( "fc:%1" ).arg( mColor.name() ) );
featureStyle.append( QString( ",bc:%1" ).arg( "#00000000" ) ); //transparent background
featureStyle.append( ",id:\"ogr-brush-2\"" );
featureStyle.append( QString( ",a:%1" ).arg( mLineAngle ) );
featureStyle.append( QString( ",s:%1" ).arg( mLineWidth * widthScaleFactor ) );
featureStyle.append( ",dx:0mm" );
featureStyle.append( QString( ",dy:%1mm" ).arg( mDistance * widthScaleFactor ) );
featureStyle.append( ")" );
return featureStyle;
}

QgsSymbolLayerV2* QgsLinePatternFillSymbolLayer::createFromSld( QDomElement &element )
{
QgsDebugMsg( "Entered." );
Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class CORE_EXPORT QgsSimpleFillSymbolLayerV2 : public QgsFillSymbolLayerV2

void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;

QString ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const;

Qt::BrushStyle brushStyle() const { return mBrushStyle; }
void setBrushStyle( Qt::BrushStyle style ) { mBrushStyle = style; }

Expand Down Expand Up @@ -189,6 +191,8 @@ class CORE_EXPORT QgsLinePatternFillSymbolLayer: public QgsImageFillSymbolLayer

void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;

QString ogrFeatureStyle( double widthScaleFactor ) const;

//getters and setters
void setLineAngle( double a ) { mLineAngle = a; }
double lineAngle() const { return mLineAngle; }
Expand Down
15 changes: 15 additions & 0 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,21 @@ void QgsSimpleLineSymbolLayerV2::toSld( QDomDocument &doc, QDomElement &element,
}
}

QString QgsSimpleLineSymbolLayerV2::ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const
{
if ( mUseCustomDashPattern )
{
return QgsSymbolLayerV2Utils::ogrFeatureStylePen( mWidth, mmScaleFactor, mapUnitScaleFactor,
mPen.color(), mPenJoinStyle,
mPenCapStyle, mOffset, &mCustomDashVector );
}
else
{
return QgsSymbolLayerV2Utils::ogrFeatureStylePen( mWidth, mmScaleFactor, mapUnitScaleFactor, mPen.color(), mPenJoinStyle,
mPenCapStyle, mOffset );
}
}

QgsSymbolLayerV2* QgsSimpleLineSymbolLayerV2::createFromSld( QDomElement &element )
{
QgsDebugMsg( "Entered." );
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgslinesymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class CORE_EXPORT QgsSimpleLineSymbolLayerV2 : public QgsLineSymbolLayerV2

void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;

QString ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const;

// new stuff

Qt::PenStyle penStyle() const { return mPenStyle; }
Expand Down
60 changes: 60 additions & 0 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,66 @@ void QgsSimpleMarkerSymbolLayerV2::writeSldMarker( QDomDocument &doc, QDomElemen
QgsSymbolLayerV2Utils::createDisplacementElement( doc, graphicElem, mOffset );
}

QString QgsSimpleMarkerSymbolLayerV2::ogrFeatureStyle( double widthScaleFactor ) const
{
#if 0
QString ogrType = "3"; //default is circle
if ( mName == "square" )
{
ogrType = "5";
}
else if ( mName == "triangle" )
{
ogrType = "7";
}
else if ( mName == "star" )
{
ogrType = "9";
}
else if ( mName == "circle" )
{
ogrType = "3";
}
else if ( mName == "cross" )
{
ogrType = "0";
}
else if ( mName == "x" || mName == "cross2" )
{
ogrType = "1";
}
else if ( mName == "line" )
{
ogrType = "10";
}

QString ogrString;
ogrString.append( "SYMBOL(" );
ogrString.append( "id:" );
ogrString.append( "\"" );
ogrString.append( "ogr-sym-" );
ogrString.append( ogrType );
ogrString.append( "\"" );
ogrString.append( ",c:" );
ogrString.append( mColor.name() );
ogrString.append( ",o:" );
ogrString.append( mBorderColor.name() );
ogrString.append( QString( ",s:%1mm" ).arg( mSize ) );
ogrString.append( ")" );
return ogrString;
#endif //0

QString ogrString;
ogrString.append( "PEN(" );
ogrString.append( "c:" );
ogrString.append( mColor.name() );
ogrString.append( ",w:" );
ogrString.append( QString::number( mSize ) );
ogrString.append( "mm" );
ogrString.append( ")" );
return ogrString;
}

QgsSymbolLayerV2* QgsSimpleMarkerSymbolLayerV2::createFromSld( QDomElement &element )
{
QgsDebugMsg( "Entered." );
Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgsmarkersymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class CORE_EXPORT QgsSimpleMarkerSymbolLayerV2 : public QgsMarkerSymbolLayerV2

void writeSldMarker( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const;

QString ogrFeatureStyle( double widthScaleFactor ) const;

QString name() const { return mName; }
void setName( QString name ) { mName = name; }

Expand Down
2 changes: 2 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ class CORE_EXPORT QgsSymbolLayerV2
virtual void toSld( QDomDocument &doc, QDomElement &element, QgsStringMap props ) const
{ Q_UNUSED( props ); element.appendChild( doc.createComment( QString( "SymbolLayerV2 %1 not implemented yet" ).arg( layerType() ) ) ); }

virtual QString ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const { Q_UNUSED( mmScaleFactor ); Q_UNUSED( mapUnitScaleFactor ); return QString(); }

virtual QgsStringMap properties() const = 0;

virtual void drawPreviewIcon( QgsSymbolV2RenderContext& context, QSize size ) = 0;
Expand Down
88 changes: 86 additions & 2 deletions src/core/symbology-ng/qgssymbollayerv2utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2095,6 +2095,90 @@ void QgsSymbolLayerV2Utils::labelTextToSld( QDomDocument &doc, QDomElement &elem
}
}

QString QgsSymbolLayerV2Utils::ogrFeatureStylePen( double width, double mmScaleFactor, double mapUnitScaleFactor, const QColor& c,
Qt::PenJoinStyle joinStyle,
Qt::PenCapStyle capStyle,
double offset,
const QVector<qreal>* dashPattern )
{
QString penStyle;
penStyle.append( "PEN(" );
penStyle.append( "c:" );
penStyle.append( c.name() );
penStyle.append( ",w:" );
//dxf driver writes ground units as mm? Should probably be changed in ogr
penStyle.append( QString::number( width * mmScaleFactor ) );
penStyle.append( "mm" );

//dash dot vector
if ( dashPattern && dashPattern->size() > 0 )
{
penStyle.append( ",p:\"" );
QVector<qreal>::const_iterator pIt = dashPattern->constBegin();
for ( ; pIt != dashPattern->constEnd(); ++pIt )
{
if ( pIt != dashPattern->constBegin() )
{
penStyle.append( " " );
}
penStyle.append( QString::number( *pIt * mapUnitScaleFactor ) );
penStyle.append( "g" );
}
penStyle.append( "\"" );
}

//cap
penStyle.append( ",cap:" );
switch ( capStyle )
{
case Qt::SquareCap:
penStyle.append( "p" );
break;
case Qt::RoundCap:
penStyle.append( "r" );
break;
case Qt::FlatCap:
default:
penStyle.append( "b" );
}

//join
penStyle.append( ",j:" );
switch ( joinStyle )
{
case Qt::BevelJoin:
penStyle.append( "b" );
break;
case Qt::RoundJoin:
penStyle.append( "r" );
break;
case Qt::MiterJoin:
default:
penStyle.append( "m" );
}

//offset
if ( !doubleNear( offset, 0.0 ) )
{
penStyle.append( ",dp:" );
penStyle.append( QString::number( offset * mapUnitScaleFactor ) );
penStyle.append( "g" );
}

penStyle.append( ")" );
return penStyle;
}

QString QgsSymbolLayerV2Utils::ogrFeatureStyleBrush( const QColor& fillColor )
{
QString brushStyle;
brushStyle.append( "BRUSH(" );
brushStyle.append( "fc:" );
brushStyle.append( fillColor.name() );
brushStyle.append( ")" );
return brushStyle;
}

void QgsSymbolLayerV2Utils::createGeometryElement( QDomDocument &doc, QDomElement &element, QString geomFunc )
{
if ( geomFunc.isEmpty() )
Expand Down Expand Up @@ -2454,7 +2538,7 @@ QColor QgsSymbolLayerV2Utils::parseColor( QString colorStr )
return QColor( p[0].toInt(), p[1].toInt(), p[2].toInt() );
}

double QgsSymbolLayerV2Utils::lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
double QgsSymbolLayerV2Utils::lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
{

if ( u == QgsSymbolV2::MM )
Expand All @@ -2475,7 +2559,7 @@ double QgsSymbolLayerV2Utils::lineWidthScaleFactor( QgsRenderContext& c, QgsSymb
}
}

double QgsSymbolLayerV2Utils::pixelSizeScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
double QgsSymbolLayerV2Utils::pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u )
{
if ( u == QgsSymbolV2::MM )
{
Expand Down
16 changes: 14 additions & 2 deletions src/core/symbology-ng/qgssymbollayerv2utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,18 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
static void labelTextToSld( QDomDocument &doc, QDomElement &element, QString label,
QFont font, QColor color = QColor(), double size = -1 );

/**Create ogr feature style string for pen
@param width linewidth in mm
@param c line color*/
static QString ogrFeatureStylePen( double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor& c,
Qt::PenJoinStyle joinStyle = Qt::MiterJoin,
Qt::PenCapStyle capStyle = Qt::FlatCap,
double offset = 0.0,
const QVector<qreal>* dashPattern = 0 );
/**Create ogr feature syle string for brush
@param fillColr fill color*/
static QString ogrFeatureStyleBrush( const QColor& fillColr );

static void createRotationElement( QDomDocument &doc, QDomElement &element, QString rotationFunc );
static bool rotationFromSldElement( QDomElement &element, QString &rotationFunc );

Expand Down Expand Up @@ -203,9 +215,9 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
static QColor parseColor( QString colorStr );

/**Returns the line width scale factor depending on the unit and the paint device*/
static double lineWidthScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
static double lineWidthScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Returns scale factor painter units -> pixel dimensions*/
static double pixelSizeScaleFactor( QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
static double pixelSizeScaleFactor( const QgsRenderContext& c, QgsSymbolV2::OutputUnit u );
/**Creates a render context for a pixel based device*/
static QgsRenderContext createRenderContext( QPainter* p );

Expand Down
1 change: 1 addition & 0 deletions src/providers/ogr/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ QT4_WRAP_CPP(OGR_MOC_SRCS ${OGR_MOC_HDRS})
INCLUDE_DIRECTORIES(
.
../../core
${CMAKE_CURRENT_SOURCE_DIR}/../../core/symbology-ng
${GDAL_INCLUDE_DIR}
${GEOS_INCLUDE_DIR}
)
Expand Down
104 changes: 67 additions & 37 deletions src/ui/qgsvectorlayersaveasdialogbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,40 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLineEdit" name="leCRS">
<property name="enabled">
<bool>false</bool>
<item row="6" column="2">
<widget class="QPushButton" name="browseCRS">
<property name="text">
<string>Browse</string>
</property>
<property name="readOnly">
<bool>true</bool>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Encoding</string>
</property>
<property name="buddy">
<cstring>mEncodingComboBox</cstring>
</property>
</widget>
</item>
<item row="8" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<item row="5" column="0" rowspan="2">
<widget class="QLabel" name="label_3">
<property name="text">
<string>CRS</string>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
<property name="buddy">
<cstring>leCRS</cstring>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mEncodingComboBox"/>
</item>
<item row="7" column="0">
<widget class="QLabel" name="mSymbologyExportLabel">
<property name="text">
<string>Symbology export</string>
</property>
</widget>
</item>
Expand All @@ -51,6 +68,9 @@
</property>
</widget>
</item>
<item row="7" column="1" colspan="2">
<widget class="QComboBox" name="mSymbologyExportComboBox"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="browseFilename">
<property name="enabled">
Expand All @@ -61,26 +81,19 @@
</property>
</widget>
</item>
<item row="6" column="2">
<widget class="QPushButton" name="browseCRS">
<property name="text">
<string>Browse</string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="2">
<widget class="QComboBox" name="mEncodingComboBox"/>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Encoding</string>
<item row="6" column="1">
<widget class="QLineEdit" name="leCRS">
<property name="enabled">
<bool>false</bool>
</property>
<property name="buddy">
<cstring>mEncodingComboBox</cstring>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="mCRSSelection"/>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
Expand All @@ -91,10 +104,20 @@
</property>
</widget>
</item>
<item row="10" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mFormatComboBox"/>
</item>
<item row="7" column="0" colspan="3">
<item row="9" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>OGR creation options</string>
Expand Down Expand Up @@ -146,16 +169,23 @@
</layout>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QComboBox" name="mCRSSelection"/>
<item row="8" column="1" colspan="2">
<widget class="QSpinBox" name="mScaleSpinBox">
<property name="prefix">
<string>1:</string>
</property>
<property name="maximum">
<number>999999999</number>
</property>
<property name="value">
<number>50000</number>
</property>
</widget>
</item>
<item row="5" column="0" rowspan="2">
<widget class="QLabel" name="label_3">
<item row="8" column="0">
<widget class="QLabel" name="mScaleLabel">
<property name="text">
<string>CRS</string>
</property>
<property name="buddy">
<cstring>leCRS</cstring>
<string>Scale</string>
</property>
</widget>
</item>
Expand Down