Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Style manager code cleanups
  • Loading branch information
wonder-sk committed Jan 7, 2015
1 parent 43d6042 commit f00f4fd
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 27 deletions.
27 changes: 23 additions & 4 deletions src/app/qgsmaplayerstyleguiutils.cpp
@@ -1,9 +1,25 @@
/***************************************************************************
qgsmaplayerstyleguiutils.cpp
--------------------------------------
Date : January 2015
Copyright : (C) 2015 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmaplayerstyleguiutils.h"

#include <QAction>
#include <QInputDialog>
#include <QMenu>

#include "qgslogger.h"
#include "qgsmapcanvas.h"
#include "qgsmaplayer.h"
#include "qgsmaplayerstylemanager.h"
Expand Down Expand Up @@ -58,17 +74,18 @@ void QgsMapLayerStyleGuiUtils::addStyle()
bool ok;
QString text = QInputDialog::getText( 0, tr( "New style" ),
tr( "Style name:" ), QLineEdit::Normal,
"newstyle", &ok );
"new style", &ok );
if ( !ok || text.isEmpty() )
return;

layer->enableStyleManager(); // make sure it exists

bool res = layer->styleManager()->addStyleFromLayer( text );
qDebug( "ADD: %d", res );

if ( res ) // make it active!
layer->styleManager()->setCurrentStyle( text );
else
QgsDebugMsg( "Failed to add style: " + text );
}

void QgsMapLayerStyleGuiUtils::useStyle()
Expand All @@ -84,7 +101,8 @@ void QgsMapLayerStyleGuiUtils::useStyle()
name.clear();

bool res = layer->styleManager()->setCurrentStyle( name );
qDebug( "USE: %d", res );
if ( !res )
QgsDebugMsg( "Failed to set current style: " + name );

layer->triggerRepaint();
}
Expand Down Expand Up @@ -113,7 +131,8 @@ void QgsMapLayerStyleGuiUtils::removeStyle()
bool needsRefresh = ( layer->styleManager()->currentStyle() == name );

bool res = layer->styleManager()->removeStyle( name );
qDebug( "DEL: %d", res );
if ( !res )
QgsDebugMsg( "Failed to remove style: " + name );

if ( needsRefresh )
layer->triggerRepaint();
Expand Down
16 changes: 16 additions & 0 deletions src/app/qgsmaplayerstyleguiutils.h
@@ -1,3 +1,18 @@
/***************************************************************************
qgsmaplayerstyleguiutils.h
--------------------------------------
Date : January 2015
Copyright : (C) 2015 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMAPLAYERSTYLEGUIUTILS_H
#define QGSMAPLAYERSTYLEGUIUTILS_H

Expand All @@ -14,6 +29,7 @@ class QgsMapLayerStyleGuiUtils : public QObject, public QgsSingleton<QgsMapLayer
Q_OBJECT
public:

//! Return menu instance with actions for the give map layer
QMenu* createStyleManagerMenu( QgsMapLayer* layer );

private:
Expand Down
33 changes: 24 additions & 9 deletions src/core/qgsmaplayerstylemanager.cpp
@@ -1,5 +1,21 @@
/***************************************************************************
qgsmaplayerstylemanager.cpp
--------------------------------------
Date : January 2015
Copyright : (C) 2015 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsmaplayerstylemanager.h"

#include "qgslogger.h"
#include "qgsmaplayer.h"

#include <QDomElement>
Expand All @@ -10,7 +26,7 @@ QgsMapLayerStyleManager::QgsMapLayerStyleManager( QgsMapLayer* layer )
: mLayer( layer )
{
QgsMapLayerStyle defaultStyle;
defaultStyle.loadFromLayer( mLayer );
defaultStyle.readFromLayer( mLayer );
mStyles.insert( QString(), defaultStyle );
}

Expand Down Expand Up @@ -74,7 +90,7 @@ bool QgsMapLayerStyleManager::addStyle( const QString& name, const QgsMapLayerSt
bool QgsMapLayerStyleManager::addStyleFromLayer( const QString& name )
{
QgsMapLayerStyle style;
style.loadFromLayer( mLayer );
style.readFromLayer( mLayer );
return addStyle( name, style );
}

Expand Down Expand Up @@ -114,13 +130,13 @@ bool QgsMapLayerStyleManager::setCurrentStyle( const QString& name )

syncCurrentStyle(); // sync before unloading it
mCurrentStyle = name;
mStyles[mCurrentStyle].applyToLayer( mLayer );
mStyles[mCurrentStyle].writeToLayer( mLayer );
return true;
}

void QgsMapLayerStyleManager::syncCurrentStyle()
{
mStyles[mCurrentStyle].loadFromLayer( mLayer );
mStyles[mCurrentStyle].readFromLayer( mLayer );
}

// -----
Expand All @@ -139,22 +155,22 @@ QString QgsMapLayerStyle::dump() const
return mXmlData;
}

void QgsMapLayerStyle::loadFromLayer( QgsMapLayer* layer )
void QgsMapLayerStyle::readFromLayer( QgsMapLayer* layer )
{
QString errorMsg;
QDomDocument doc;
layer->exportNamedStyle( doc, errorMsg );
if ( !errorMsg.isEmpty() )
{
qDebug( " ERR: %s", errorMsg.toAscii().data() );
QgsDebugMsg( "Failed to export style from layer: " + errorMsg );
return;
}

QTextStream stream( &mXmlData );
doc.save( stream, 0 );
}

void QgsMapLayerStyle::applyToLayer( QgsMapLayer* layer ) const
void QgsMapLayerStyle::writeToLayer( QgsMapLayer* layer ) const
{
// QgsMapLayer does not have a importNamedStyle() method - working it around like this
QTemporaryFile f;
Expand All @@ -164,9 +180,8 @@ void QgsMapLayerStyle::applyToLayer( QgsMapLayer* layer ) const

bool res;
QString status = layer->loadNamedStyle( f.fileName(), res );
qDebug( "APPLY: %s", status.toAscii().data() );
if ( !res )
qDebug( " APPLY ERR!" );
QgsDebugMsg( "Failed to import style to layer: " + status );
}

void QgsMapLayerStyle::readXml( const QDomElement& styleElement )
Expand Down
77 changes: 67 additions & 10 deletions src/core/qgsmaplayerstylemanager.h
@@ -1,56 +1,113 @@
/***************************************************************************
qgsmaplayerstylemanager.h
--------------------------------------
Date : January 2015
Copyright : (C) 2015 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program 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 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMAPLAYERSTYLEMANAGER_H
#define QGSMAPLAYERSTYLEMANAGER_H


class QgsMapLayer;


#include <QByteArray>
#include <QMap>
#include <QStringList>

class QDomElement;

/** stores style information (renderer, transparency, labeling, diagrams etc.) applicable to a map layer */
class QgsMapLayerStyle
/**
* Stores style information (renderer, transparency, labeling, diagrams etc.) applicable to a map layer.
*
* Stored data are considered as opaque - it is not possible to access them directly or modify them - it is
* only possible to read or write layer's current style.
*
* @note added in 2.8
*/
class CORE_EXPORT QgsMapLayerStyle
{
public:
QgsMapLayerStyle(); // consutrct invalid style
//! construct invalid style
QgsMapLayerStyle();

//! Tell whether the style is valid (i.e. there is something stored in it)
bool isValid() const;

QString dump() const; // for debugging only
//! Return information about the style - for debugging purposes only
QString dump() const;

void loadFromLayer( QgsMapLayer* layer );
void applyToLayer( QgsMapLayer* layer ) const;
//! Store layer's active style information in the instance
void readFromLayer( QgsMapLayer* layer );
//! Apply stored layer's style information to the layer
void writeToLayer( QgsMapLayer* layer ) const;

//! Read style configuration (for project file reading)
void readXml( const QDomElement& styleElement );
//! Write style configuration (for project file writing)
void writeXml( QDomElement& styleElement ) const;

private:
QByteArray mXmlData;
};


/** Management of styles for use with one map layer */
class QgsMapLayerStyleManager
/**
* Management of styles for use with one map layer. Stored styles are identified by their names. The manager
* always keep track of which style of the stored ones is currently active. When the current style is changed,
* the new style is applied to the associated layer.
*
* The class takes care of updating itself when the layer's current style configuration changes.
* When some of layer style's properties change (e.g. transparency / colors), the style manager will
* record them in the currently active style without any extra effort required.
*
* When an instance is created, it creates "default" style (with empty name) recorded from the associated map layer
* and it is set as the current style.
*
* The instance must always contain at least one style. If no extra styles are wanted, the style manager should get
* disabled in QgsMapLayer instance.
*
* @note added in 2.8
*/
class CORE_EXPORT QgsMapLayerStyleManager
{
public:
//! Construct a style manager associated with a map layer (must not be null)
QgsMapLayerStyleManager( QgsMapLayer* layer );

//! Read configuration (for project loading)
void readXml( const QDomElement& mgrElement );
//! Write configuration (for project saving)
void writeXml( QDomElement& mgrElement ) const;

//! Return list of all defined style names
QStringList styles() const;
//! Return data of a stored style - accessed by its unique name
QgsMapLayerStyle style( const QString& name ) const;

//! Add a style with given name and data
//! @return true on success (name is unique and style is valid)
bool addStyle( const QString& name, const QgsMapLayerStyle& style );
//! Add style by cloning the current one
//! @return true on success
bool addStyleFromLayer( const QString& name );
//! Remove a stored style
//! @return true on success (style exists and it is not the last one)
bool removeStyle( const QString& name );

//! Return name of the current style
QString currentStyle() const;
bool setCurrentStyle( const QString& name ); // applies to the mLayer! (+ sync previous style)
//! Set a different style as the current style - will apply it to the layer
//! @return true on success
bool setCurrentStyle( const QString& name );

private:
void syncCurrentStyle();
Expand Down
8 changes: 4 additions & 4 deletions tests/src/core/testqgsmaplayerstylemanager.cpp
Expand Up @@ -86,25 +86,25 @@ void TestQgsMapLayerStyleManager::testStyle()
mVL->setRendererV2( new QgsSingleSymbolRendererV2( sym1 ) );

QgsMapLayerStyle st1;
st1.loadFromLayer( mVL );
st1.readFromLayer( mVL );
QCOMPARE( st1.isValid(), true );

qDebug( "CNT-1: %s", st1.dump().toAscii().data() );

mVL->setRendererV2( new QgsSingleSymbolRendererV2( sym2 ) );

QgsMapLayerStyle st2;
st2.loadFromLayer( mVL );
st2.readFromLayer( mVL );

qDebug( "CNT-2: %s", st2.dump().toAscii().data() );

st1.applyToLayer( mVL );
st1.writeToLayer( mVL );

QgsSingleSymbolRendererV2* r1 = dynamic_cast<QgsSingleSymbolRendererV2*>( mVL->rendererV2() );
QVERIFY( r1 );
QCOMPARE( r1->symbol()->color(), QColor( Qt::magenta ) );

st2.applyToLayer( mVL );
st2.writeToLayer( mVL );

QgsSingleSymbolRendererV2* r2 = dynamic_cast<QgsSingleSymbolRendererV2*>( mVL->rendererV2() );
QVERIFY( r2 );
Expand Down

0 comments on commit f00f4fd

Please sign in to comment.