65 changes: 56 additions & 9 deletions src/app/qgsvectorlayerproperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(
actionDialog = new QgsAttributeActionDialog( layer->actions(), fields, actionOptionsFrame );
actionLayout->addWidget( actionDialog );

// Create the menu for the save style button to choose the output format
mSaveAsMenu = new QMenu( pbnSaveStyleAs );
mSaveAsMenu->addAction( tr( "QGIS Layer Style File" ) );
mSaveAsMenu->addAction( tr( "SLD File" ) );
QObject::connect( mSaveAsMenu, SIGNAL( triggered( QAction * ) ), this, SLOT( saveStyleAsMenuTriggered( QAction * ) ) );

reset();

if ( layer->dataProvider() )//enable spatial index button group if supported by provider
Expand Down Expand Up @@ -950,6 +956,7 @@ void QgsVectorLayerProperties::on_pbnLoadStyle_clicked()
{
QSettings myQSettings; // where we keep last used filter in persistent state
QString myLastUsedDir = myQSettings.value( "style/lastStyleDir", "." ).toString();

QString myFileName = QFileDialog::getOpenFileName( this, tr( "Load layer properties from style file" ), myLastUsedDir,
tr( "QGIS Layer Style File" ) + " (*.qml);;" + tr( "SLD File" ) + " (*.sld)" );
if ( myFileName.isNull() )
Expand Down Expand Up @@ -987,34 +994,65 @@ void QgsVectorLayerProperties::on_pbnLoadStyle_clicked()


void QgsVectorLayerProperties::on_pbnSaveStyleAs_clicked()
{
saveStyleAs( QML );
}

void QgsVectorLayerProperties::saveStyleAsMenuTriggered( QAction *action )
{
QMenu *menu = qobject_cast<QMenu *>( sender() );
if ( !menu )
return;

int index = mSaveAsMenu->actions().indexOf( action );
if ( index < 0 )
return;

saveStyleAs( (StyleType) index );
}

void QgsVectorLayerProperties::saveStyleAs( StyleType styleType )
{
QSettings myQSettings; // where we keep last used filter in persistent state
QString myLastUsedDir = myQSettings.value( "style/lastStyleDir", "." ).toString();
QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save layer properties as style file" ), myLastUsedDir,
tr( "QGIS Layer Style File" ) + " (*.qml);;" + tr( "SLD File" ) + " (*.sld)" );

QString format, extension;
if ( styleType == SLD )
{
format = tr( "SLD File" ) + " (*.sld)";
extension = ".sld";
}
else
{
format = tr( "QGIS Layer Style File" ) + " (*.qml)";
extension = ".qml";
}

QString myOutputFileName = QFileDialog::getSaveFileName( this, tr( "Save layer properties as style file" ),
myLastUsedDir, format );
if ( myOutputFileName.isNull() ) //dialog canceled
{
return;
}

apply(); // make sure the qml to save is uptodate
apply(); // make sure the style to save is uptodate

QString myMessage;
bool defaultLoadedFlag = false;

//ensure the user never omitted the extension from the file name
if ( myOutputFileName.endsWith( ".sld", Qt::CaseInsensitive ) )
if ( myOutputFileName.endsWith( extension, Qt::CaseInsensitive ) )
{
myOutputFileName += extension;
}

if ( styleType == SLD )
{
// convert to SLD
myMessage = layer->saveSldStyle( myOutputFileName, defaultLoadedFlag );
}
else
{
if ( !myOutputFileName.endsWith( ".qml", Qt::CaseInsensitive ) )
{
myOutputFileName += ".qml";
}

myMessage = layer->saveNamedStyle( myOutputFileName, defaultLoadedFlag );
}

Expand Down Expand Up @@ -1234,6 +1272,11 @@ void QgsVectorLayerProperties::updateSymbologyPage()
mRendererDialog = new QgsRendererV2PropertiesDialog( layer, QgsStyleV2::defaultStyle(), true );

connect( mRendererDialog, SIGNAL( useNewSymbology( bool ) ), this, SLOT( setUsingNewSymbology( bool ) ) );

// display the menu to choose the output format (fix #5136)
pbnSaveStyleAs->setText( tr( "Save Style" ) );
pbnSaveStyleAs->setMenu( mSaveAsMenu );
QObject::disconnect( pbnSaveStyleAs, SIGNAL( clicked() ), this, SLOT( on_pbnSaveStyleAs_clicked() ) );
}
else if ( layer->renderer() )
{
Expand Down Expand Up @@ -1261,6 +1304,10 @@ void QgsVectorLayerProperties::updateSymbologyPage()

QObject::connect( legendtypecombobox, SIGNAL( activated( const QString & ) ), this,
SLOT( alterLayerDialog( const QString & ) ) );

pbnSaveStyleAs->setText( tr( "Save Style..." ) );
pbnSaveStyleAs->setMenu( NULL );
QObject::connect( pbnSaveStyleAs, SIGNAL( clicked() ), this, SLOT( on_pbnSaveStyleAs_clicked() ) );
}
else
{
Expand Down
15 changes: 15 additions & 0 deletions src/app/qgsvectorlayerproperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
Q_OBJECT

public:
enum StyleType
{
QML = 0,
SLD,
};

QgsVectorLayerProperties( QgsVectorLayer *lyr = 0, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags );
~QgsVectorLayerProperties();
/**Sets the legend type to "single symbol", "graduated symbol" or "continuous color"*/
Expand Down Expand Up @@ -138,8 +144,15 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope

void toggleEditing( QgsMapLayer * );

private slots:

/** save the style based on selected format from the menu */
void saveStyleAsMenuTriggered( QAction * );

protected:

void saveStyleAs( StyleType styleType );

void updateSymbologyPage();

enum attrColumns
Expand All @@ -159,6 +172,8 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope

bool mMetadataFilled;

QMenu *mSaveAsMenu;

/**Renderer dialog which is shown*/
QDialog* mRendererDialog;
/**Buffer renderer, which is assigned to the vector layer when apply is pressed*/
Expand Down
41 changes: 24 additions & 17 deletions src/core/qgsexpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,31 +689,38 @@ QgsExpression::Node* QgsExpression::Node::createFromOgcFilter( QDomElement &elem
else if ( element.localName() == "PropertyIsBetween" )
{
// <ogc:PropertyIsBetween> encode a Range check
QgsExpression::Node *operand = 0, *lowerBound = 0, *upperBound = 0;
QgsExpression::Node *operand = 0, *lowerBound = 0;
QgsExpression::Node *operand2 = 0, *upperBound = 0;

QDomElement operandElem = element.firstChildElement( "LowerBoundary" );
if ( !operandElem.isNull() )
lowerBound = createFromOgcFilter( operandElem, errorMessage );

operandElem = element.firstChildElement( "UpperBoundary" );
if ( !operandElem.isNull() )
upperBound = createFromOgcFilter( operandElem, errorMessage );

// <ogc:expression>
operandElem = element.firstChildElement();
while ( !operandElem.isNull() )
QDomElement operandElem = element.firstChildElement();
while( !operandElem.isNull() )
{
if ( operandElem.localName() != "LowerBoundary" &&
operandElem.localName() != "UpperBoundary" )
if ( operandElem.localName() == "LowerBoundary" )
{
QDomElement lowerBoundElem = operandElem.firstChildElement();
lowerBound = createFromOgcFilter( lowerBoundElem, errorMessage );
}
else if ( operandElem.localName() == "UpperBoundary" )
{
QDomElement upperBoundElem = operandElem.firstChildElement();
upperBound = createFromOgcFilter( upperBoundElem, errorMessage );
}
else
{
// <ogc:expression>
// both operand and operand2 contain the same expression,
// they are respectively compared to lower bound and upper bound
operand = createFromOgcFilter( operandElem, errorMessage );
break;
operand2 = createFromOgcFilter( operandElem, errorMessage );
}

if ( operand && lowerBound && operand2 && upperBound )
break;

operandElem = operandElem.nextSiblingElement();
}

if ( !operand || !lowerBound || !upperBound )
if ( !operand || !lowerBound || !operand2 || !upperBound )
{
if ( operand )
delete operand;
Expand All @@ -729,7 +736,7 @@ QgsExpression::Node* QgsExpression::Node::createFromOgcFilter( QDomElement &elem
}

QgsExpression::Node *geOperator = new QgsExpression::NodeBinaryOperator( boGE, operand, lowerBound );
QgsExpression::Node *leOperator = new QgsExpression::NodeBinaryOperator( boLE, operand, upperBound );
QgsExpression::Node *leOperator = new QgsExpression::NodeBinaryOperator( boLE, operand2, upperBound );
return new QgsExpression::NodeBinaryOperator( boAnd, geOperator, leOperator );
}

Expand Down
4 changes: 3 additions & 1 deletion src/core/symbology-ng/qgscategorizedsymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ void QgsRendererCategoryV2::toSld( QDomDocument &doc, QDomElement &element, QgsS
ruleElem.appendChild( nameElem );

QDomElement descrElem = doc.createElement( "se:Description" );
QDomElement abstractElem = doc.createElement( "se:Abstract" );
QString descrStr = QString( "%1 is '%2'" ).arg( attrName ).arg( mValue.toString() );
descrElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
abstractElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
descrElem.appendChild( abstractElem );
ruleElem.appendChild( descrElem );

// create the ogc:Filter for the range
Expand Down
5 changes: 4 additions & 1 deletion src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ void QgsRendererRangeV2::toSld( QDomDocument &doc, QDomElement &element, QgsStri
ruleElem.appendChild( nameElem );

QDomElement descrElem = doc.createElement( "se:Description" );
QDomElement abstractElem = doc.createElement( "se:Abstract" );
QString descrStr = QString( "range: %1 - %2" ).arg( mLowerValue ).arg( mUpperValue );
descrElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
abstractElem.appendChild( doc.createTextNode( !mLabel.isEmpty() ? mLabel : descrStr ) );
descrElem.appendChild( abstractElem );
ruleElem.appendChild( descrElem );

// create the ogc:Filter for the range
Expand All @@ -124,6 +126,7 @@ void QgsRendererRangeV2::toSld( QDomDocument &doc, QDomElement &element, QgsStri
.arg( attrName.replace( "\"", "\"\"" ) )
.arg( mLowerValue ).arg( mUpperValue );
QgsSymbolLayerV2Utils::createFunctionElement( doc, filterElem, filterFunc );
ruleElem.appendChild( filterElem );

mSymbol->toSld( doc, ruleElem, props );
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/symbology-ng/qgssymbollayerv2utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2057,12 +2057,12 @@ bool QgsSymbolLayerV2Utils::functionFromSldElement( QDomElement &element, QStrin
void QgsSymbolLayerV2Utils::createOnlineResourceElement( QDomDocument &doc, QDomElement &element,
QString path, QString format )
{
QDomElement onlineResourceElem = doc.createElement( "OnlineResource" );
QDomElement onlineResourceElem = doc.createElement( "se:OnlineResource" );
onlineResourceElem.setAttribute( "xlink:type", "simple" );
onlineResourceElem.setAttribute( "xlink:href", path );
element.appendChild( onlineResourceElem );

QDomElement formatElem = doc.createElement( "Format" );
QDomElement formatElem = doc.createElement( "se:Format" );
formatElem.appendChild( doc.createTextNode( format ) );
element.appendChild( formatElem );
}
Expand Down