mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-15 00:02:52 -04:00
Refactor visibility presets, so that all non-app specific
methods are now in core A new QgsVisibilityPresetCollection object has been created which stores a set of visibility presets. QgsProject now contains a preset collection object. This allows plugins and other core objects to retrieve and modify visibility presets.
This commit is contained in:
parent
612df6ae14
commit
73522dce7e
@ -127,6 +127,7 @@
|
||||
%Include qgsprojectfiletransform.sip
|
||||
%Include qgsvectorlayereditutils.sip
|
||||
%Include qgsvectorlayerfeatureiterator.sip
|
||||
%Include qgsvisibilitypresetcollection.sip
|
||||
%Include qgslayerdefinition.sip
|
||||
|
||||
%Include composer/qgsaddremoveitemcommand.sip
|
||||
|
@ -258,6 +258,11 @@ class QgsProject : QObject
|
||||
*/
|
||||
QgsLayerTreeRegistryBridge* layerTreeRegistryBridge() const;
|
||||
|
||||
/** Returns pointer to the project's visibility preset collection.
|
||||
* @note added in QGIS 2.12
|
||||
*/
|
||||
QgsVisibilityPresetCollection* visibilityPresetCollection();
|
||||
|
||||
protected:
|
||||
|
||||
/** Set error message from read/write operation */
|
||||
|
131
python/core/qgsvisibilitypresetcollection.sip
Normal file
131
python/core/qgsvisibilitypresetcollection.sip
Normal file
@ -0,0 +1,131 @@
|
||||
/**
|
||||
\class QgsVisibilityPresetCollection
|
||||
\ingroup core
|
||||
\brief Container class that allows storage of visibility presets consisting of visible
|
||||
map layers and layer styles.
|
||||
\note added in QGIS 2.12
|
||||
*/
|
||||
|
||||
class QgsVisibilityPresetCollection : QObject
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsvisibilitypresetcollection.h>
|
||||
%End
|
||||
public:
|
||||
|
||||
/** Individual preset record of visible layers and styles.
|
||||
*/
|
||||
class PresetRecord
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator==( const QgsVisibilityPresetCollection::PresetRecord& other ) const;
|
||||
bool operator!=( const QgsVisibilityPresetCollection::PresetRecord& other ) const;
|
||||
|
||||
//! List of layers that are visible
|
||||
QSet<QString> mVisibleLayerIDs;
|
||||
/** For layers that have checkable legend symbols and not all symbols are checked - list which ones are
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
//QMap<QString, QSet<QString> > mPerLayerCheckedLegendSymbols;
|
||||
//! For layers that use multiple styles - which one is currently selected
|
||||
QMap<QString, QString> mPerLayerCurrentStyle;
|
||||
};
|
||||
|
||||
QgsVisibilityPresetCollection();
|
||||
|
||||
/** Returns whether a preset with a matching name exists.
|
||||
* @param name name of preset to check
|
||||
* @returns true if preset exists
|
||||
*/
|
||||
bool hasPreset( const QString& name ) const;
|
||||
|
||||
/** Inserts a new preset to the collection.
|
||||
* @param name name of preset
|
||||
* @param state preset record
|
||||
* @see update()
|
||||
*/
|
||||
void insert( const QString& name, const PresetRecord& state );
|
||||
|
||||
/** Updates a preset within the collection.
|
||||
* @param name name of preset to update
|
||||
* @param state preset record to replace existing preset
|
||||
* @see insert()
|
||||
*/
|
||||
void update( const QString& name, const PresetRecord& state );
|
||||
|
||||
/** Remove existing preset from collection.
|
||||
* @param name preset name
|
||||
*/
|
||||
void removePreset( const QString& name );
|
||||
|
||||
//! Remove all presets from the collection.
|
||||
void clear();
|
||||
|
||||
//! Returns a list of existing preset names.
|
||||
QStringList presets() const;
|
||||
|
||||
/** Returns the recorded state of a preset.
|
||||
* @param name name of preset
|
||||
*/
|
||||
PresetRecord presetState( const QString& name ) const;
|
||||
|
||||
/** Returns the list of layer IDs that should be visible for the specified preset.
|
||||
* @note The order of the returned list is not guaranteed to reflect the order of layers
|
||||
* in the canvas.
|
||||
* @param name preset name
|
||||
*/
|
||||
QStringList presetVisibleLayers( const QString& name ) const;
|
||||
|
||||
/** Apply check states of legend nodes of a given layer as defined in the preset.
|
||||
* @param preset name
|
||||
* @param layerID layer ID
|
||||
*/
|
||||
void applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
|
||||
|
||||
/** Get layer style overrides (for QgsMapSettings) of the visible layers for given preset.
|
||||
* @param name preset name
|
||||
*/
|
||||
QMap<QString, QString> presetStyleOverrides( const QString& name );
|
||||
|
||||
/** Reads the preset collection state from XML
|
||||
* @param doc DOM document
|
||||
* @see writeXML
|
||||
*/
|
||||
void readXML( const QDomDocument& doc );
|
||||
|
||||
/** Writes the preset collection state to XML.
|
||||
* @param doc DOM document
|
||||
* @see readXML
|
||||
*/
|
||||
void writeXML( QDomDocument& doc );
|
||||
|
||||
/** Static method for adding visible layers from a layer tree group to a preset
|
||||
* record.
|
||||
* @param parent layer tree group parent
|
||||
* @param rec preset record to amend
|
||||
*/
|
||||
static void addVisibleLayersToPreset( QgsLayerTreeGroup* parent, PresetRecord& rec );
|
||||
|
||||
signals:
|
||||
|
||||
/** Emitted when presets within the collection are changed.
|
||||
*/
|
||||
void presetsChanged();
|
||||
|
||||
protected slots:
|
||||
|
||||
/** Handles updates of the preset collection when layers are removed from the registry
|
||||
*/
|
||||
void registryLayersRemoved( QStringList layerIDs );
|
||||
|
||||
//! Update style name if a stored style gets renamed
|
||||
void layerStyleRenamed( const QString& oldName, const QString& newName );
|
||||
|
||||
protected:
|
||||
|
||||
/** Reconnects all preset layers to handle style renames
|
||||
*/
|
||||
void reconnectToLayersStyleManager();
|
||||
};
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "qgsexpressionbuilderdialog.h"
|
||||
#include "qgsgenericprojectionselector.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvisibilitypresets.h"
|
||||
#include "qgsvisibilitypresetcollection.h"
|
||||
#include "qgisgui.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
@ -285,12 +285,12 @@ void QgsComposerMapWidget::aboutToShowVisibilityPresetsMenu()
|
||||
return;
|
||||
|
||||
menu->clear();
|
||||
foreach ( QString presetName, QgsVisibilityPresets::instance()->presets() )
|
||||
foreach ( QString presetName, QgsProject::instance()->visibilityPresetCollection()->presets() )
|
||||
{
|
||||
QAction* a = menu->addAction( presetName, this, SLOT( visibilityPresetSelected() ) );
|
||||
a->setCheckable( true );
|
||||
QStringList layers = QgsVisibilityPresets::instance()->presetVisibleLayers( presetName );
|
||||
QMap<QString, QString> styles = QgsVisibilityPresets::instance()->presetStyleOverrides( presetName );
|
||||
QStringList layers = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( presetName );
|
||||
QMap<QString, QString> styles = QgsProject::instance()->visibilityPresetCollection()->presetStyleOverrides( presetName );
|
||||
if ( layers == mComposerMap->layerSet() && styles == mComposerMap->layerStyleOverrides() )
|
||||
a->setChecked( true );
|
||||
}
|
||||
@ -306,7 +306,7 @@ void QgsComposerMapWidget::visibilityPresetSelected()
|
||||
return;
|
||||
|
||||
QString presetName = action->text();
|
||||
QStringList lst = QgsVisibilityPresets::instance()->presetVisibleLayers( presetName );
|
||||
QStringList lst = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( presetName );
|
||||
if ( mComposerMap )
|
||||
{
|
||||
mKeepLayerListCheckBox->setChecked( true );
|
||||
@ -314,7 +314,7 @@ void QgsComposerMapWidget::visibilityPresetSelected()
|
||||
|
||||
mKeepLayerStylesCheckBox->setChecked( true );
|
||||
|
||||
mComposerMap->setLayerStyleOverrides( QgsVisibilityPresets::instance()->presetStyleOverrides( presetName ) );
|
||||
mComposerMap->setLayerStyleOverrides( QgsProject::instance()->visibilityPresetCollection()->presetStyleOverrides( presetName ) );
|
||||
|
||||
mComposerMap->cache();
|
||||
mComposerMap->update();
|
||||
|
@ -3756,8 +3756,6 @@ void QgisApp::fileNew( bool thePromptToSaveFlag, bool forceBlank )
|
||||
fileNewFromDefaultTemplate();
|
||||
}
|
||||
|
||||
QgsVisibilityPresets::instance()->clear();
|
||||
|
||||
// set the initial map tool
|
||||
#ifndef HAVE_TOUCH
|
||||
mMapCanvas->setMapTool( mMapTools.mPan );
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "qgsfieldcombobox.h"
|
||||
#include "qgisapp.h"
|
||||
#include "qgslayertreemapcanvasbridge.h"
|
||||
#include "qgsvisibilitypresets.h"
|
||||
#include "qgsvisibilitypresetcollection.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QPushButton>
|
||||
@ -329,7 +329,7 @@ QList< QPair<QgsVectorLayer *, int> > QgsVectorLayerAndAttributeModel::layers()
|
||||
|
||||
void QgsVectorLayerAndAttributeModel::applyVisibilityPreset( const QString &name )
|
||||
{
|
||||
QSet<QString> visibleLayers = QgsVisibilityPresets::instance()->presetVisibleLayers( name ).toSet();
|
||||
QSet<QString> visibleLayers = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( name ).toSet();
|
||||
if ( visibleLayers.isEmpty() )
|
||||
return;
|
||||
|
||||
@ -429,7 +429,7 @@ QgsDxfExportDialog::QgsDxfExportDialog( QWidget *parent, Qt::WindowFlags f )
|
||||
mScaleWidget->setScale( s.value( "qgis/lastSymbologyExportScale", "1/50000" ).toDouble() );
|
||||
mMapExtentCheckBox->setChecked( s.value( "qgis/lastDxfMapRectangle", "false" ).toBool() );
|
||||
|
||||
QStringList ids = QgsVisibilityPresets::instance()->presets();
|
||||
QStringList ids = QgsProject::instance()->visibilityPresetCollection()->presets();
|
||||
ids.prepend( "" );
|
||||
mVisibilityPresets->addItems( ids );
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsvisibilitypresets.h"
|
||||
#include "qgsvisibilitypresetcollection.h"
|
||||
|
||||
#include "qgslayertree.h"
|
||||
#include "qgslayertreemapcanvasbridge.h"
|
||||
@ -49,32 +50,9 @@ QgsVisibilityPresets::QgsVisibilityPresets()
|
||||
mActionRemoveCurrentPreset = mMenu->addAction( tr( "Remove Current Preset" ), this, SLOT( removeCurrentPreset() ) );
|
||||
|
||||
connect( mMenu, SIGNAL( aboutToShow() ), this, SLOT( menuAboutToShow() ) );
|
||||
|
||||
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersRemoved( QStringList ) ),
|
||||
this, SLOT( registryLayersRemoved( QStringList ) ) );
|
||||
|
||||
connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ),
|
||||
this, SLOT( readProject( const QDomDocument & ) ) );
|
||||
connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ),
|
||||
this, SLOT( writeProject( QDomDocument & ) ) );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::addVisibleLayersToPreset( QgsLayerTreeGroup* parent, QgsVisibilityPresets::PresetRecord& rec )
|
||||
{
|
||||
foreach ( QgsLayerTreeNode* node, parent->children() )
|
||||
{
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
addVisibleLayersToPreset( QgsLayerTree::toGroup( node ), rec );
|
||||
else if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
|
||||
if ( nodeLayer->isVisible() )
|
||||
rec.mVisibleLayerIDs << nodeLayer->layerId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::addPerLayerCheckedLegendSymbols( QgsVisibilityPresets::PresetRecord& rec )
|
||||
void QgsVisibilityPresets::addPerLayerCheckedLegendSymbols( QgsVisibilityPresetCollection::PresetRecord& rec )
|
||||
{
|
||||
QgsLayerTreeModel* model = QgisApp::instance()->layerTreeView()->layerTreeModel();
|
||||
|
||||
@ -105,7 +83,7 @@ void QgsVisibilityPresets::addPerLayerCheckedLegendSymbols( QgsVisibilityPresets
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::addPerLayerCurrentStyle( QgsVisibilityPresets::PresetRecord& rec )
|
||||
void QgsVisibilityPresets::addPerLayerCurrentStyle( QgsVisibilityPresetCollection::PresetRecord& rec )
|
||||
{
|
||||
QgsLayerTreeModel* model = QgisApp::instance()->layerTreeView()->layerTreeModel();
|
||||
|
||||
@ -119,11 +97,11 @@ void QgsVisibilityPresets::addPerLayerCurrentStyle( QgsVisibilityPresets::Preset
|
||||
}
|
||||
}
|
||||
|
||||
QgsVisibilityPresets::PresetRecord QgsVisibilityPresets::currentState()
|
||||
QgsVisibilityPresetCollection::PresetRecord QgsVisibilityPresets::currentState()
|
||||
{
|
||||
PresetRecord rec;
|
||||
QgsVisibilityPresetCollection::PresetRecord rec;
|
||||
QgsLayerTreeGroup* root = QgsProject::instance()->layerTreeRoot();
|
||||
addVisibleLayersToPreset( root, rec );
|
||||
QgsVisibilityPresetCollection::addVisibleLayersToPreset( root, rec );
|
||||
addPerLayerCheckedLegendSymbols( rec );
|
||||
addPerLayerCurrentStyle( rec );
|
||||
return rec;
|
||||
@ -139,43 +117,17 @@ QgsVisibilityPresets* QgsVisibilityPresets::instance()
|
||||
|
||||
void QgsVisibilityPresets::addPreset( const QString& name )
|
||||
{
|
||||
mPresets.insert( name, currentState() );
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
QgsProject::instance()->visibilityPresetCollection()->insert( name, currentState() );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::updatePreset( const QString& name )
|
||||
{
|
||||
if ( !mPresets.contains( name ) )
|
||||
return;
|
||||
|
||||
mPresets[name] = currentState();
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
QgsProject::instance()->visibilityPresetCollection()->update( name, currentState() );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::removePreset( const QString& name )
|
||||
QStringList QgsVisibilityPresets::orderedPresetVisibleLayers( const QString& name ) const
|
||||
{
|
||||
mPresets.remove( name );
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::clear()
|
||||
{
|
||||
mPresets.clear();
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
QStringList QgsVisibilityPresets::presets() const
|
||||
{
|
||||
return mPresets.keys();
|
||||
}
|
||||
|
||||
QStringList QgsVisibilityPresets::presetVisibleLayers( const QString& name ) const
|
||||
{
|
||||
QSet<QString> visibleIds = mPresets.value( name ).mVisibleLayerIDs;
|
||||
QStringList visibleIds = QgsProject::instance()->visibilityPresetCollection()->presetVisibleLayers( name );
|
||||
|
||||
// also make sure to order the layers according to map canvas order
|
||||
QgsLayerTreeMapCanvasBridge* bridge = QgisApp::instance()->layerTreeCanvasBridge();
|
||||
@ -190,71 +142,6 @@ QStringList QgsVisibilityPresets::presetVisibleLayers( const QString& name ) con
|
||||
return order2;
|
||||
}
|
||||
|
||||
|
||||
void QgsVisibilityPresets::applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID )
|
||||
{
|
||||
if ( !mPresets.contains( name ) )
|
||||
return;
|
||||
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
|
||||
if ( !layer )
|
||||
return;
|
||||
|
||||
const PresetRecord& rec = mPresets[name];
|
||||
|
||||
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
|
||||
if ( !vlayer || !vlayer->rendererV2() )
|
||||
return;
|
||||
|
||||
if ( !vlayer->rendererV2()->legendSymbolItemsCheckable() )
|
||||
return; // no need to do anything
|
||||
|
||||
bool someNodesUnchecked = rec.mPerLayerCheckedLegendSymbols.contains( layerID );
|
||||
|
||||
foreach ( const QgsLegendSymbolItemV2& item, vlayer->rendererV2()->legendSymbolItemsV2() )
|
||||
{
|
||||
bool checked = vlayer->rendererV2()->legendSymbolItemChecked( item.ruleKey() );
|
||||
bool shouldBeChecked = someNodesUnchecked ? rec.mPerLayerCheckedLegendSymbols[layerID].contains( item.ruleKey() ) : true;
|
||||
if ( checked != shouldBeChecked )
|
||||
vlayer->rendererV2()->checkLegendSymbolItem( item.ruleKey(), shouldBeChecked );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QMap<QString, QString> QgsVisibilityPresets::presetStyleOverrides( const QString& presetName )
|
||||
{
|
||||
QMap<QString, QString> styleOverrides;
|
||||
if ( !mPresets.contains( presetName ) )
|
||||
return styleOverrides;
|
||||
|
||||
QStringList lst = QgsVisibilityPresets::instance()->presetVisibleLayers( presetName );
|
||||
const QgsVisibilityPresets::PresetRecord& rec = mPresets[presetName];
|
||||
foreach ( const QString& layerID, lst )
|
||||
{
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
|
||||
if ( !layer )
|
||||
continue;
|
||||
|
||||
// use either the stored style name or the current one if none has been stored
|
||||
QString overrideStyleName = rec.mPerLayerCurrentStyle.value( layerID, layer->styleManager()->currentStyle() );
|
||||
|
||||
// store original style and temporarily apply a style
|
||||
layer->styleManager()->setOverrideStyle( overrideStyleName );
|
||||
|
||||
// set the checked legend nodes
|
||||
applyPresetCheckedLegendNodesToLayer( presetName, layerID );
|
||||
|
||||
// save to overrides
|
||||
QgsMapLayerStyle layerStyle;
|
||||
layerStyle.readFromLayer( layer );
|
||||
styleOverrides[layerID] = layerStyle.xmlData();
|
||||
|
||||
layer->styleManager()->restoreOverrideStyle();
|
||||
}
|
||||
return styleOverrides;
|
||||
}
|
||||
|
||||
|
||||
QMenu* QgsVisibilityPresets::menu()
|
||||
{
|
||||
return mMenu;
|
||||
@ -282,7 +169,7 @@ void QgsVisibilityPresets::presetTriggerred()
|
||||
}
|
||||
|
||||
|
||||
void QgsVisibilityPresets::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const PresetRecord& rec )
|
||||
void QgsVisibilityPresets::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const QgsVisibilityPresetCollection::PresetRecord& rec )
|
||||
{
|
||||
foreach ( QgsLayerTreeNode* node, parent->children() )
|
||||
{
|
||||
@ -333,61 +220,40 @@ void QgsVisibilityPresets::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent
|
||||
|
||||
void QgsVisibilityPresets::applyState( const QString& presetName )
|
||||
{
|
||||
if ( !mPresets.contains( presetName ) )
|
||||
if ( !QgsProject::instance()->visibilityPresetCollection()->hasPreset( presetName ) )
|
||||
return;
|
||||
|
||||
applyStateToLayerTreeGroup( QgsProject::instance()->layerTreeRoot(), mPresets[presetName] );
|
||||
applyStateToLayerTreeGroup( QgsProject::instance()->layerTreeRoot(), QgsProject::instance()->visibilityPresetCollection()->presetState( presetName ) );
|
||||
|
||||
// also make sure that the preset is up-to-date (not containing any non-existent legend items)
|
||||
mPresets[presetName] = currentState();
|
||||
QgsProject::instance()->visibilityPresetCollection()->update( presetName, currentState() );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::reconnectToLayersStyleManager()
|
||||
{
|
||||
// disconnect( 0, 0, this, SLOT( layerStyleRenamed( QString, QString ) ) );
|
||||
|
||||
QSet<QString> layerIDs;
|
||||
foreach ( const QString& grpName, mPresets.keys() )
|
||||
{
|
||||
const PresetRecord& rec = mPresets[grpName];
|
||||
foreach ( const QString& layerID, rec.mPerLayerCurrentStyle.keys() )
|
||||
layerIDs << layerID;
|
||||
}
|
||||
|
||||
foreach ( const QString& layerID, layerIDs )
|
||||
{
|
||||
if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
|
||||
connect( ml->styleManager(), SIGNAL( styleRenamed( QString, QString ) ), this, SLOT( layerStyleRenamed( QString, QString ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QgsVisibilityPresets::removeCurrentPreset()
|
||||
{
|
||||
foreach ( QAction* a, mMenuPresetActions )
|
||||
{
|
||||
if ( a->isChecked() )
|
||||
{
|
||||
removePreset( a->text() );
|
||||
QgsProject::instance()->visibilityPresetCollection()->removePreset( a->text() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QgsVisibilityPresets::menuAboutToShow()
|
||||
{
|
||||
qDeleteAll( mMenuPresetActions );
|
||||
mMenuPresetActions.clear();
|
||||
|
||||
PresetRecord rec = currentState();
|
||||
QgsVisibilityPresetCollection::PresetRecord rec = currentState();
|
||||
bool hasCurrent = false;
|
||||
|
||||
foreach ( const QString& grpName, mPresets.keys() )
|
||||
foreach ( const QString& grpName, QgsProject::instance()->visibilityPresetCollection()->presets() )
|
||||
{
|
||||
QAction* a = new QAction( grpName, mMenu );
|
||||
a->setCheckable( true );
|
||||
if ( rec == mPresets[grpName] )
|
||||
if ( !hasCurrent && rec == QgsProject::instance()->visibilityPresetCollection()->presetState( grpName ) )
|
||||
{
|
||||
a->setChecked( true );
|
||||
hasCurrent = true;
|
||||
@ -399,127 +265,3 @@ void QgsVisibilityPresets::menuAboutToShow()
|
||||
|
||||
mActionRemoveCurrentPreset->setEnabled( hasCurrent );
|
||||
}
|
||||
|
||||
|
||||
void QgsVisibilityPresets::readProject( const QDomDocument& doc )
|
||||
{
|
||||
clear();
|
||||
|
||||
QDomElement visPresetsElem = doc.firstChildElement( "qgis" ).firstChildElement( "visibility-presets" );
|
||||
if ( visPresetsElem.isNull() )
|
||||
return;
|
||||
|
||||
QDomElement visPresetElem = visPresetsElem.firstChildElement( "visibility-preset" );
|
||||
while ( !visPresetElem.isNull() )
|
||||
{
|
||||
QString presetName = visPresetElem.attribute( "name" );
|
||||
PresetRecord rec;
|
||||
QDomElement visPresetLayerElem = visPresetElem.firstChildElement( "layer" );
|
||||
while ( !visPresetLayerElem.isNull() )
|
||||
{
|
||||
QString layerID = visPresetLayerElem.attribute( "id" );
|
||||
if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
|
||||
{
|
||||
rec.mVisibleLayerIDs << layerID; // only use valid layer IDs
|
||||
if ( visPresetLayerElem.hasAttribute( "style" ) )
|
||||
rec.mPerLayerCurrentStyle[layerID] = visPresetLayerElem.attribute( "style" );
|
||||
}
|
||||
visPresetLayerElem = visPresetLayerElem.nextSiblingElement( "layer" );
|
||||
}
|
||||
|
||||
QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( "checked-legend-nodes" );
|
||||
while ( !checkedLegendNodesElem.isNull() )
|
||||
{
|
||||
QSet<QString> checkedLegendNodes;
|
||||
|
||||
QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( "checked-legend-node" );
|
||||
while ( !checkedLegendNodeElem.isNull() )
|
||||
{
|
||||
checkedLegendNodes << checkedLegendNodeElem.attribute( "id" );
|
||||
checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( "checked-legend-node" );
|
||||
}
|
||||
|
||||
QString layerID = checkedLegendNodesElem.attribute( "id" );
|
||||
if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ) // only use valid IDs
|
||||
rec.mPerLayerCheckedLegendSymbols.insert( layerID, checkedLegendNodes );
|
||||
checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( "checked-legend-nodes" );
|
||||
}
|
||||
|
||||
mPresets.insert( presetName, rec );
|
||||
|
||||
visPresetElem = visPresetElem.nextSiblingElement( "visibility-preset" );
|
||||
}
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::writeProject( QDomDocument& doc )
|
||||
{
|
||||
QDomElement visPresetsElem = doc.createElement( "visibility-presets" );
|
||||
foreach ( const QString& grpName, mPresets.keys() )
|
||||
{
|
||||
const PresetRecord& rec = mPresets[grpName];
|
||||
QDomElement visPresetElem = doc.createElement( "visibility-preset" );
|
||||
visPresetElem.setAttribute( "name", grpName );
|
||||
foreach ( QString layerID, rec.mVisibleLayerIDs )
|
||||
{
|
||||
QDomElement layerElem = doc.createElement( "layer" );
|
||||
layerElem.setAttribute( "id", layerID );
|
||||
if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
|
||||
layerElem.setAttribute( "style", rec.mPerLayerCurrentStyle[layerID] );
|
||||
visPresetElem.appendChild( layerElem );
|
||||
}
|
||||
|
||||
foreach ( QString layerID, rec.mPerLayerCheckedLegendSymbols.keys() )
|
||||
{
|
||||
QDomElement checkedLegendNodesElem = doc.createElement( "checked-legend-nodes" );
|
||||
checkedLegendNodesElem.setAttribute( "id", layerID );
|
||||
foreach ( QString checkedLegendNode, rec.mPerLayerCheckedLegendSymbols[layerID] )
|
||||
{
|
||||
QDomElement checkedLegendNodeElem = doc.createElement( "checked-legend-node" );
|
||||
checkedLegendNodeElem.setAttribute( "id", checkedLegendNode );
|
||||
checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
|
||||
}
|
||||
visPresetElem.appendChild( checkedLegendNodesElem );
|
||||
}
|
||||
|
||||
visPresetsElem.appendChild( visPresetElem );
|
||||
}
|
||||
|
||||
doc.firstChildElement( "qgis" ).appendChild( visPresetsElem );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::registryLayersRemoved( QStringList layerIDs )
|
||||
{
|
||||
foreach ( QString layerID, layerIDs )
|
||||
{
|
||||
foreach ( QString presetName, mPresets.keys() )
|
||||
{
|
||||
PresetRecord& rec = mPresets[presetName];
|
||||
rec.mVisibleLayerIDs.remove( layerID );
|
||||
rec.mPerLayerCheckedLegendSymbols.remove( layerID );
|
||||
rec.mPerLayerCurrentStyle.remove( layerID );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVisibilityPresets::layerStyleRenamed( const QString& oldName, const QString& newName )
|
||||
{
|
||||
QgsMapLayerStyleManager* styleMgr = qobject_cast<QgsMapLayerStyleManager*>( sender() );
|
||||
if ( !styleMgr )
|
||||
return;
|
||||
|
||||
QString layerID = styleMgr->layer()->id();
|
||||
|
||||
foreach ( QString presetName, mPresets.keys() )
|
||||
{
|
||||
PresetRecord& rec = mPresets[presetName];
|
||||
|
||||
if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
|
||||
{
|
||||
QString styleName = rec.mPerLayerCurrentStyle[layerID];
|
||||
if ( styleName == oldName )
|
||||
rec.mPerLayerCurrentStyle[layerID] = newName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef QGSVISIBILITYPRESETS_H
|
||||
#define QGSVISIBILITYPRESETS_H
|
||||
|
||||
#include "qgsvisibilitypresetcollection.h"
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
@ -29,102 +30,61 @@ class QgsLayerTreeNode;
|
||||
class QgsLayerTreeGroup;
|
||||
|
||||
/**
|
||||
* Controller class that allows creation of visibility presets consisting of currently visible
|
||||
* map layers in map canvas.
|
||||
* Contains methods for app-specific visibility preset functions.
|
||||
*/
|
||||
class QgsVisibilityPresets : public QObject
|
||||
class APP_EXPORT QgsVisibilityPresets : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
typedef struct PresetRecord
|
||||
{
|
||||
bool operator==( const PresetRecord& other ) const
|
||||
{
|
||||
return mVisibleLayerIDs == other.mVisibleLayerIDs
|
||||
&& mPerLayerCheckedLegendSymbols == other.mPerLayerCheckedLegendSymbols
|
||||
&& mPerLayerCurrentStyle == other.mPerLayerCurrentStyle;
|
||||
}
|
||||
bool operator!=( const PresetRecord& other ) const
|
||||
{
|
||||
return !( *this == other );
|
||||
}
|
||||
|
||||
//! List of layers that are visible
|
||||
QSet<QString> mVisibleLayerIDs;
|
||||
//! For layers that have checkable legend symbols and not all symbols are checked - list which ones are
|
||||
QMap<QString, QSet<QString> > mPerLayerCheckedLegendSymbols;
|
||||
//! For layers that use multiple styles - which one is currently selected
|
||||
QMap<QString, QString> mPerLayerCurrentStyle;
|
||||
} PresetRecord;
|
||||
|
||||
|
||||
/** Returns the instance QgsVisibilityPresets.
|
||||
*/
|
||||
static QgsVisibilityPresets* instance();
|
||||
|
||||
//! Add a new preset using the current state of project's layer tree
|
||||
void addPreset( const QString& name );
|
||||
//! Update existing preset using the current state of project's layer tree
|
||||
void updatePreset( const QString& name );
|
||||
//! Remove existing preset
|
||||
void removePreset( const QString& name );
|
||||
|
||||
//! Remove all presets
|
||||
void clear();
|
||||
|
||||
//! Return list of existing preset names
|
||||
QStringList presets() const;
|
||||
|
||||
//! Return recorded state of a preset
|
||||
PresetRecord presetState( const QString& presetName ) const { return mPresets[presetName]; }
|
||||
|
||||
//! Return list of layer IDs that should be visible for particular preset
|
||||
QStringList presetVisibleLayers( const QString& name ) const;
|
||||
|
||||
//! Apply check states of legend nodes of a given layer as defined in the preset
|
||||
void applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
|
||||
//! Return list of layer IDs that should be visible for particular preset.
|
||||
//! The order will match the layer order from the map canvas
|
||||
QStringList orderedPresetVisibleLayers( const QString& name ) const;
|
||||
|
||||
//! Convenience menu that lists available presets and actions for management
|
||||
QMenu* menu();
|
||||
|
||||
//! Get layer style overrides (for QgsMapSettings) of the visible layers for given preset
|
||||
QMap<QString, QString> presetStyleOverrides( const QString& presetName );
|
||||
|
||||
signals:
|
||||
void presetsChanged();
|
||||
|
||||
protected slots:
|
||||
|
||||
//! Handles adding a preset to the project's collection
|
||||
void addPreset();
|
||||
|
||||
//! Handles apply a preset to the map canvas
|
||||
void presetTriggerred();
|
||||
|
||||
//! Handles removal of current preset from the project's collection
|
||||
void removeCurrentPreset();
|
||||
|
||||
//! Handles creation of preset menu
|
||||
void menuAboutToShow();
|
||||
|
||||
void readProject( const QDomDocument& doc );
|
||||
void writeProject( QDomDocument& doc );
|
||||
|
||||
void registryLayersRemoved( QStringList layerIDs );
|
||||
|
||||
//! Update style name if a stored style gets renamed
|
||||
void layerStyleRenamed( const QString& oldName, const QString& newName );
|
||||
|
||||
protected:
|
||||
QgsVisibilityPresets(); // singleton
|
||||
|
||||
typedef QMap<QString, PresetRecord> PresetRecordMap;
|
||||
//! Applies current layer state to a preset record
|
||||
void applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const QgsVisibilityPresetCollection::PresetRecord& rec );
|
||||
//! Applies layer checked legend symbols to a preset record
|
||||
void addPerLayerCheckedLegendSymbols( QgsVisibilityPresetCollection::PresetRecord& rec );
|
||||
//! Applies current layer styles to a preset record
|
||||
void addPerLayerCurrentStyle( QgsVisibilityPresetCollection::PresetRecord& rec );
|
||||
|
||||
void addVisibleLayersToPreset( QgsLayerTreeGroup* parent, PresetRecord& rec );
|
||||
void applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const PresetRecord& rec );
|
||||
void addPerLayerCheckedLegendSymbols( PresetRecord& rec );
|
||||
void addPerLayerCurrentStyle( PresetRecord& rec );
|
||||
//! Returns the current state of the map canvas as a preset record
|
||||
QgsVisibilityPresetCollection::PresetRecord currentState();
|
||||
|
||||
PresetRecord currentState();
|
||||
//! Applies a preset for the project's collection to the canvas
|
||||
void applyState( const QString& presetName );
|
||||
|
||||
void reconnectToLayersStyleManager();
|
||||
|
||||
static QgsVisibilityPresets* sInstance;
|
||||
|
||||
PresetRecordMap mPresets;
|
||||
|
||||
QMenu* mMenu;
|
||||
QAction* mMenuSeparator;
|
||||
QAction* mActionRemoveCurrentPreset;
|
||||
|
@ -185,6 +185,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgsvectorlayerrenderer.cpp
|
||||
qgsvectorlayerundocommand.cpp
|
||||
qgsvectorsimplifymethod.cpp
|
||||
qgsvisibilitypresetcollection.cpp
|
||||
qgsxmlutils.cpp
|
||||
qgsslconnect.cpp
|
||||
qgslocalec.cpp
|
||||
@ -408,6 +409,7 @@ SET(QGIS_CORE_MOC_HDRS
|
||||
qgsvectordataprovider.h
|
||||
qgsvectorlayercache.h
|
||||
qgsvectorlayerjoinbuffer.h
|
||||
qgsvisibilitypresetcollection.h
|
||||
qgsgeometryvalidator.h
|
||||
qgswebview.h
|
||||
|
||||
@ -602,6 +604,7 @@ SET(QGIS_CORE_HDRS
|
||||
qgsvectorlayerrenderer.h
|
||||
qgsvectorlayerundocommand.h
|
||||
qgsvectorsimplifymethod.h
|
||||
qgsvisibilitypresetcollection.h
|
||||
qgsxmlutils.h
|
||||
qgswebpage.h
|
||||
qgswebframe.h
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include "qgsrectangle.h"
|
||||
#include "qgsrelationmanager.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "qgsvisibilitypresetcollection.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFileInfo>
|
||||
@ -414,6 +415,8 @@ void QgsProject::clear()
|
||||
mEmbeddedLayers.clear();
|
||||
mRelationManager->clear();
|
||||
|
||||
mVisibilityPresetCollection.reset( new QgsVisibilityPresetCollection() );
|
||||
|
||||
mRootGroup->removeAllChildren();
|
||||
|
||||
// reset some default project properties
|
||||
@ -894,6 +897,9 @@ bool QgsProject::read()
|
||||
|
||||
mRootGroup->removeCustomProperty( "loading" );
|
||||
|
||||
mVisibilityPresetCollection.reset( new QgsVisibilityPresetCollection() );
|
||||
mVisibilityPresetCollection->readXML( *doc );
|
||||
|
||||
// read the project: used by map canvas and legend
|
||||
emit readProject( *doc );
|
||||
|
||||
@ -1093,6 +1099,8 @@ bool QgsProject::write()
|
||||
imp_->properties_.writeXML( "properties", qgisNode, *doc );
|
||||
}
|
||||
|
||||
mVisibilityPresetCollection->writeXML( *doc );
|
||||
|
||||
// now wrap it up and ship it to the project file
|
||||
doc->normalize(); // XXX I'm not entirely sure what this does
|
||||
|
||||
@ -1966,3 +1974,8 @@ QgsLayerTreeGroup *QgsProject::layerTreeRoot() const
|
||||
{
|
||||
return mRootGroup;
|
||||
}
|
||||
|
||||
QgsVisibilityPresetCollection* QgsProject::visibilityPresetCollection()
|
||||
{
|
||||
return mVisibilityPresetCollection.data();
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ class QgsMapLayer;
|
||||
class QgsProjectBadLayerHandler;
|
||||
class QgsRelationManager;
|
||||
class QgsVectorLayer;
|
||||
class QgsVisibilityPresetCollection;
|
||||
|
||||
/** \ingroup core
|
||||
* Reads and writes project states.
|
||||
@ -301,6 +302,11 @@ class CORE_EXPORT QgsProject : public QObject
|
||||
*/
|
||||
QgsLayerTreeRegistryBridge* layerTreeRegistryBridge() const { return mLayerTreeRegistryBridge; }
|
||||
|
||||
/** Returns pointer to the project's visibility preset collection.
|
||||
* @note added in QGIS 2.12
|
||||
*/
|
||||
QgsVisibilityPresetCollection* visibilityPresetCollection();
|
||||
|
||||
protected:
|
||||
|
||||
/** Set error message from read/write operation */
|
||||
@ -394,6 +400,8 @@ class CORE_EXPORT QgsProject : public QObject
|
||||
|
||||
QgsLayerTreeRegistryBridge* mLayerTreeRegistryBridge;
|
||||
|
||||
QScopedPointer<QgsVisibilityPresetCollection> mVisibilityPresetCollection;
|
||||
|
||||
}; // QgsProject
|
||||
|
||||
|
||||
|
304
src/core/qgsvisibilitypresetcollection.cpp
Normal file
304
src/core/qgsvisibilitypresetcollection.cpp
Normal file
@ -0,0 +1,304 @@
|
||||
/***************************************************************************
|
||||
qgsvisibilitypresetcollection.cpp
|
||||
--------------------------------------
|
||||
Date : September 2014
|
||||
Copyright : (C) 2014 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 "qgsvisibilitypresetcollection.h"
|
||||
|
||||
#include "qgslayertree.h"
|
||||
#include "qgslayertreemodel.h"
|
||||
#include "qgslayertreemodellegendnode.h"
|
||||
#include "qgsmaplayerregistry.h"
|
||||
#include "qgsmaplayerstylemanager.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsrendererv2.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
|
||||
QgsVisibilityPresetCollection::QgsVisibilityPresetCollection()
|
||||
{
|
||||
connect( QgsMapLayerRegistry::instance(), SIGNAL( layersRemoved( QStringList ) ),
|
||||
this, SLOT( registryLayersRemoved( QStringList ) ) );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::addVisibleLayersToPreset( QgsLayerTreeGroup* parent, QgsVisibilityPresetCollection::PresetRecord& rec )
|
||||
{
|
||||
foreach ( QgsLayerTreeNode* node, parent->children() )
|
||||
{
|
||||
if ( QgsLayerTree::isGroup( node ) )
|
||||
addVisibleLayersToPreset( QgsLayerTree::toGroup( node ), rec );
|
||||
else if ( QgsLayerTree::isLayer( node ) )
|
||||
{
|
||||
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
|
||||
if ( nodeLayer->isVisible() )
|
||||
rec.mVisibleLayerIDs << nodeLayer->layerId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVisibilityPresetCollection::hasPreset( const QString& name ) const
|
||||
{
|
||||
return mPresets.contains( name );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::insert( const QString& name, const QgsVisibilityPresetCollection::PresetRecord& state )
|
||||
{
|
||||
mPresets.insert( name, state );
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::update( const QString& name, const PresetRecord& state )
|
||||
{
|
||||
if ( !mPresets.contains( name ) )
|
||||
return;
|
||||
|
||||
mPresets[name] = state;
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::removePreset( const QString& name )
|
||||
{
|
||||
if ( !mPresets.contains( name ) )
|
||||
return;
|
||||
|
||||
mPresets.remove( name );
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::clear()
|
||||
{
|
||||
mPresets.clear();
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
QStringList QgsVisibilityPresetCollection::presets() const
|
||||
{
|
||||
return mPresets.keys();
|
||||
}
|
||||
|
||||
QStringList QgsVisibilityPresetCollection::presetVisibleLayers( const QString& name ) const
|
||||
{
|
||||
QSet<QString> visibleIds = mPresets.value( name ).mVisibleLayerIDs;
|
||||
return visibleIds.toList();
|
||||
}
|
||||
|
||||
|
||||
void QgsVisibilityPresetCollection::applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID )
|
||||
{
|
||||
if ( !mPresets.contains( name ) )
|
||||
return;
|
||||
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
|
||||
if ( !layer )
|
||||
return;
|
||||
|
||||
const PresetRecord& rec = mPresets[name];
|
||||
|
||||
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
|
||||
if ( !vlayer || !vlayer->rendererV2() )
|
||||
return;
|
||||
|
||||
if ( !vlayer->rendererV2()->legendSymbolItemsCheckable() )
|
||||
return; // no need to do anything
|
||||
|
||||
bool someNodesUnchecked = rec.mPerLayerCheckedLegendSymbols.contains( layerID );
|
||||
|
||||
foreach ( const QgsLegendSymbolItemV2& item, vlayer->rendererV2()->legendSymbolItemsV2() )
|
||||
{
|
||||
bool checked = vlayer->rendererV2()->legendSymbolItemChecked( item.ruleKey() );
|
||||
bool shouldBeChecked = someNodesUnchecked ? rec.mPerLayerCheckedLegendSymbols[layerID].contains( item.ruleKey() ) : true;
|
||||
if ( checked != shouldBeChecked )
|
||||
vlayer->rendererV2()->checkLegendSymbolItem( item.ruleKey(), shouldBeChecked );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QMap<QString, QString> QgsVisibilityPresetCollection::presetStyleOverrides( const QString& presetName )
|
||||
{
|
||||
QMap<QString, QString> styleOverrides;
|
||||
if ( !mPresets.contains( presetName ) )
|
||||
return styleOverrides;
|
||||
|
||||
QStringList lst = presetVisibleLayers( presetName );
|
||||
const QgsVisibilityPresetCollection::PresetRecord& rec = mPresets[presetName];
|
||||
foreach ( const QString& layerID, lst )
|
||||
{
|
||||
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
|
||||
if ( !layer )
|
||||
continue;
|
||||
|
||||
// use either the stored style name or the current one if none has been stored
|
||||
QString overrideStyleName = rec.mPerLayerCurrentStyle.value( layerID, layer->styleManager()->currentStyle() );
|
||||
|
||||
// store original style and temporarily apply a style
|
||||
layer->styleManager()->setOverrideStyle( overrideStyleName );
|
||||
|
||||
// set the checked legend nodes
|
||||
applyPresetCheckedLegendNodesToLayer( presetName, layerID );
|
||||
|
||||
// save to overrides
|
||||
QgsMapLayerStyle layerStyle;
|
||||
layerStyle.readFromLayer( layer );
|
||||
styleOverrides[layerID] = layerStyle.xmlData();
|
||||
|
||||
layer->styleManager()->restoreOverrideStyle();
|
||||
}
|
||||
return styleOverrides;
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::reconnectToLayersStyleManager()
|
||||
{
|
||||
// disconnect( 0, 0, this, SLOT( layerStyleRenamed( QString, QString ) ) );
|
||||
|
||||
QSet<QString> layerIDs;
|
||||
foreach ( const QString& grpName, mPresets.keys() )
|
||||
{
|
||||
const PresetRecord& rec = mPresets[grpName];
|
||||
foreach ( const QString& layerID, rec.mPerLayerCurrentStyle.keys() )
|
||||
layerIDs << layerID;
|
||||
}
|
||||
|
||||
foreach ( const QString& layerID, layerIDs )
|
||||
{
|
||||
if ( QgsMapLayer* ml = QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
|
||||
connect( ml->styleManager(), SIGNAL( styleRenamed( QString, QString ) ), this, SLOT( layerStyleRenamed( QString, QString ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::readXML( const QDomDocument& doc )
|
||||
{
|
||||
clear();
|
||||
|
||||
QDomElement visPresetsElem = doc.firstChildElement( "qgis" ).firstChildElement( "visibility-presets" );
|
||||
if ( visPresetsElem.isNull() )
|
||||
return;
|
||||
|
||||
QDomElement visPresetElem = visPresetsElem.firstChildElement( "visibility-preset" );
|
||||
while ( !visPresetElem.isNull() )
|
||||
{
|
||||
QString presetName = visPresetElem.attribute( "name" );
|
||||
PresetRecord rec;
|
||||
QDomElement visPresetLayerElem = visPresetElem.firstChildElement( "layer" );
|
||||
while ( !visPresetLayerElem.isNull() )
|
||||
{
|
||||
QString layerID = visPresetLayerElem.attribute( "id" );
|
||||
if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) )
|
||||
{
|
||||
rec.mVisibleLayerIDs << layerID; // only use valid layer IDs
|
||||
if ( visPresetLayerElem.hasAttribute( "style" ) )
|
||||
rec.mPerLayerCurrentStyle[layerID] = visPresetLayerElem.attribute( "style" );
|
||||
}
|
||||
visPresetLayerElem = visPresetLayerElem.nextSiblingElement( "layer" );
|
||||
}
|
||||
|
||||
QDomElement checkedLegendNodesElem = visPresetElem.firstChildElement( "checked-legend-nodes" );
|
||||
while ( !checkedLegendNodesElem.isNull() )
|
||||
{
|
||||
QSet<QString> checkedLegendNodes;
|
||||
|
||||
QDomElement checkedLegendNodeElem = checkedLegendNodesElem.firstChildElement( "checked-legend-node" );
|
||||
while ( !checkedLegendNodeElem.isNull() )
|
||||
{
|
||||
checkedLegendNodes << checkedLegendNodeElem.attribute( "id" );
|
||||
checkedLegendNodeElem = checkedLegendNodeElem.nextSiblingElement( "checked-legend-node" );
|
||||
}
|
||||
|
||||
QString layerID = checkedLegendNodesElem.attribute( "id" );
|
||||
if ( QgsMapLayerRegistry::instance()->mapLayer( layerID ) ) // only use valid IDs
|
||||
rec.mPerLayerCheckedLegendSymbols.insert( layerID, checkedLegendNodes );
|
||||
checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( "checked-legend-nodes" );
|
||||
}
|
||||
|
||||
mPresets.insert( presetName, rec );
|
||||
|
||||
visPresetElem = visPresetElem.nextSiblingElement( "visibility-preset" );
|
||||
}
|
||||
|
||||
reconnectToLayersStyleManager();
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::writeXML( QDomDocument& doc )
|
||||
{
|
||||
QDomElement visPresetsElem = doc.createElement( "visibility-presets" );
|
||||
foreach ( const QString& grpName, mPresets.keys() )
|
||||
{
|
||||
const PresetRecord& rec = mPresets[grpName];
|
||||
QDomElement visPresetElem = doc.createElement( "visibility-preset" );
|
||||
visPresetElem.setAttribute( "name", grpName );
|
||||
foreach ( QString layerID, rec.mVisibleLayerIDs )
|
||||
{
|
||||
QDomElement layerElem = doc.createElement( "layer" );
|
||||
layerElem.setAttribute( "id", layerID );
|
||||
if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
|
||||
layerElem.setAttribute( "style", rec.mPerLayerCurrentStyle[layerID] );
|
||||
visPresetElem.appendChild( layerElem );
|
||||
}
|
||||
|
||||
foreach ( QString layerID, rec.mPerLayerCheckedLegendSymbols.keys() )
|
||||
{
|
||||
QDomElement checkedLegendNodesElem = doc.createElement( "checked-legend-nodes" );
|
||||
checkedLegendNodesElem.setAttribute( "id", layerID );
|
||||
foreach ( QString checkedLegendNode, rec.mPerLayerCheckedLegendSymbols[layerID] )
|
||||
{
|
||||
QDomElement checkedLegendNodeElem = doc.createElement( "checked-legend-node" );
|
||||
checkedLegendNodeElem.setAttribute( "id", checkedLegendNode );
|
||||
checkedLegendNodesElem.appendChild( checkedLegendNodeElem );
|
||||
}
|
||||
visPresetElem.appendChild( checkedLegendNodesElem );
|
||||
}
|
||||
|
||||
visPresetsElem.appendChild( visPresetElem );
|
||||
}
|
||||
|
||||
doc.firstChildElement( "qgis" ).appendChild( visPresetsElem );
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::registryLayersRemoved( QStringList layerIDs )
|
||||
{
|
||||
foreach ( QString layerID, layerIDs )
|
||||
{
|
||||
foreach ( QString presetName, mPresets.keys() )
|
||||
{
|
||||
PresetRecord& rec = mPresets[presetName];
|
||||
rec.mVisibleLayerIDs.remove( layerID );
|
||||
rec.mPerLayerCheckedLegendSymbols.remove( layerID );
|
||||
rec.mPerLayerCurrentStyle.remove( layerID );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QgsVisibilityPresetCollection::layerStyleRenamed( const QString& oldName, const QString& newName )
|
||||
{
|
||||
QgsMapLayerStyleManager* styleMgr = qobject_cast<QgsMapLayerStyleManager*>( sender() );
|
||||
if ( !styleMgr )
|
||||
return;
|
||||
|
||||
QString layerID = styleMgr->layer()->id();
|
||||
|
||||
foreach ( QString presetName, mPresets.keys() )
|
||||
{
|
||||
PresetRecord& rec = mPresets[presetName];
|
||||
|
||||
if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
|
||||
{
|
||||
QString styleName = rec.mPerLayerCurrentStyle[layerID];
|
||||
if ( styleName == oldName )
|
||||
rec.mPerLayerCurrentStyle[layerID] = newName;
|
||||
}
|
||||
}
|
||||
}
|
170
src/core/qgsvisibilitypresetcollection.h
Normal file
170
src/core/qgsvisibilitypresetcollection.h
Normal file
@ -0,0 +1,170 @@
|
||||
/***************************************************************************
|
||||
qgsvisibilitypresetcollection.h
|
||||
--------------------------------------
|
||||
Date : September 2014
|
||||
Copyright : (C) 2014 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 QGSVISIBILITYPRESETCOLLECTION_H
|
||||
#define QGSVISIBILITYPRESETCOLLECTION_H
|
||||
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QStringList>
|
||||
|
||||
class QDomDocument;
|
||||
class QgsLayerTreeNode;
|
||||
class QgsLayerTreeGroup;
|
||||
|
||||
/**
|
||||
\class QgsVisibilityPresetCollection
|
||||
\ingroup core
|
||||
\brief Container class that allows storage of visibility presets consisting of visible
|
||||
map layers and layer styles.
|
||||
\note added in QGIS 2.12
|
||||
*/
|
||||
|
||||
class CORE_EXPORT QgsVisibilityPresetCollection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
/** Individual preset record of visible layers and styles.
|
||||
*/
|
||||
class PresetRecord
|
||||
{
|
||||
public:
|
||||
|
||||
bool operator==( const PresetRecord& other ) const
|
||||
{
|
||||
return mVisibleLayerIDs == other.mVisibleLayerIDs
|
||||
&& mPerLayerCheckedLegendSymbols == other.mPerLayerCheckedLegendSymbols
|
||||
&& mPerLayerCurrentStyle == other.mPerLayerCurrentStyle;
|
||||
}
|
||||
bool operator!=( const PresetRecord& other ) const
|
||||
{
|
||||
return !( *this == other );
|
||||
}
|
||||
|
||||
//! List of layers that are visible
|
||||
QSet<QString> mVisibleLayerIDs;
|
||||
/** For layers that have checkable legend symbols and not all symbols are checked - list which ones are
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
QMap<QString, QSet<QString> > mPerLayerCheckedLegendSymbols;
|
||||
//! For layers that use multiple styles - which one is currently selected
|
||||
QMap<QString, QString> mPerLayerCurrentStyle;
|
||||
};
|
||||
|
||||
QgsVisibilityPresetCollection();
|
||||
|
||||
/** Returns whether a preset with a matching name exists.
|
||||
* @param name name of preset to check
|
||||
* @returns true if preset exists
|
||||
*/
|
||||
bool hasPreset( const QString& name ) const;
|
||||
|
||||
/** Inserts a new preset to the collection.
|
||||
* @param name name of preset
|
||||
* @param state preset record
|
||||
* @see update()
|
||||
*/
|
||||
void insert( const QString& name, const PresetRecord& state );
|
||||
|
||||
/** Updates a preset within the collection.
|
||||
* @param name name of preset to update
|
||||
* @param state preset record to replace existing preset
|
||||
* @see insert()
|
||||
*/
|
||||
void update( const QString& name, const PresetRecord& state );
|
||||
|
||||
/** Remove existing preset from collection.
|
||||
* @param name preset name
|
||||
*/
|
||||
void removePreset( const QString& name );
|
||||
|
||||
//! Remove all presets from the collection.
|
||||
void clear();
|
||||
|
||||
//! Returns a list of existing preset names.
|
||||
QStringList presets() const;
|
||||
|
||||
/** Returns the recorded state of a preset.
|
||||
* @param name name of preset
|
||||
*/
|
||||
PresetRecord presetState( const QString& name ) const { return mPresets[name]; }
|
||||
|
||||
/** Returns the list of layer IDs that should be visible for the specified preset.
|
||||
* @note The order of the returned list is not guaranteed to reflect the order of layers
|
||||
* in the canvas.
|
||||
* @param name preset name
|
||||
*/
|
||||
QStringList presetVisibleLayers( const QString& name ) const;
|
||||
|
||||
/** Apply check states of legend nodes of a given layer as defined in the preset.
|
||||
* @param preset name
|
||||
* @param layerID layer ID
|
||||
*/
|
||||
void applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
|
||||
|
||||
/** Get layer style overrides (for QgsMapSettings) of the visible layers for given preset.
|
||||
* @param name preset name
|
||||
*/
|
||||
QMap<QString, QString> presetStyleOverrides( const QString& name );
|
||||
|
||||
/** Reads the preset collection state from XML
|
||||
* @param doc DOM document
|
||||
* @see writeXML
|
||||
*/
|
||||
void readXML( const QDomDocument& doc );
|
||||
|
||||
/** Writes the preset collection state to XML.
|
||||
* @param doc DOM document
|
||||
* @see readXML
|
||||
*/
|
||||
void writeXML( QDomDocument& doc );
|
||||
|
||||
/** Static method for adding visible layers from a layer tree group to a preset
|
||||
* record.
|
||||
* @param parent layer tree group parent
|
||||
* @param rec preset record to amend
|
||||
*/
|
||||
static void addVisibleLayersToPreset( QgsLayerTreeGroup* parent, PresetRecord& rec );
|
||||
|
||||
signals:
|
||||
|
||||
/** Emitted when presets within the collection are changed.
|
||||
*/
|
||||
void presetsChanged();
|
||||
|
||||
protected slots:
|
||||
|
||||
/** Handles updates of the preset collection when layers are removed from the registry
|
||||
*/
|
||||
void registryLayersRemoved( QStringList layerIDs );
|
||||
|
||||
//! Update style name if a stored style gets renamed
|
||||
void layerStyleRenamed( const QString& oldName, const QString& newName );
|
||||
|
||||
protected:
|
||||
|
||||
/** Reconnects all preset layers to handle style renames
|
||||
*/
|
||||
void reconnectToLayersStyleManager();
|
||||
|
||||
typedef QMap<QString, PresetRecord> PresetRecordMap;
|
||||
PresetRecordMap mPresets;
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSVISIBILITYPRESETCOLLECTION_H
|
Loading…
x
Reference in New Issue
Block a user