Rename visibility presets to map themes part 2 (#3641)

This commit is contained in:
Matthias Kuhn 2016-10-20 12:55:48 +02:00 committed by GitHub
parent bb225f562b
commit f3482d2ce2
13 changed files with 332 additions and 219 deletions

View File

@ -1467,6 +1467,8 @@ in code which previously passed a null pointer to QgsVectorLayerImport.</li>
<ul>
<li>Has been renamed to QgsMapThemeCollection</li>
<li>The nested class PresetRecord has been renamed to MapThemeRecord</li>
<li>Various member functions have been renamed from *preset* to *mapTheme*</li>
</ul>
\subsection qgis_api_break_3_0_QgsVectorFileWriter QgsVectorFileWriter

View File

@ -1,9 +1,9 @@
/**
\class QgsMapThemeCollection
\ingroup core
\brief Container class that allows storage of visibility presets consisting of visible
\brief Container class that allows storage of map themes consisting of visible
map layers and layer styles.
\note added in QGIS 2.12
\note Added in QGIS 2.12, renamed for QGIS 3.0
*/
class QgsMapThemeCollection : QObject
@ -13,119 +13,134 @@ class QgsMapThemeCollection : QObject
%End
public:
/** Individual preset record of visible layers and styles.
/** \ingroup core
* Individual map theme record of visible layers and styles.
*/
class PresetRecord
class MapThemeRecord
{
public:
bool operator==( const QgsMapThemeCollection::PresetRecord& other ) const;
bool operator!=( const QgsMapThemeCollection::PresetRecord& other ) const;
bool operator==( const QgsMapThemeCollection::MapThemeRecord& other ) const;
bool operator!=( const QgsMapThemeCollection::MapThemeRecord& other ) const;
//! Ordered list of layers that are visible
QStringList mVisibleLayerIDs;
/** For layers that have checkable legend symbols and not all symbols are checked - list which ones are
/**
* Ordered list of visible layers
*/
QStringList visibleLayerIds() const;
/**
* Ordered list of visible layers
*/
void setVisibleLayerIds( const QStringList& visibleLayerIds );
/**
* Lists which legend symbols are checked for layers which support this and where
* not all symbols are checked.
* @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;
// QMap<QString, QSet<QString> > perLayerCheckedLegendSymbols() const;
/**
* Lists which legend symbols are checked for layers which support this and where
* not all symbols are checked.
* @note not available in Python bindings
*/
// void setPerLayerCheckedLegendSymbols(const QMap<QString, QSet<QString> >& perLayerCheckedLegendSymbols);
/**
* The currently used style name for layers with multiple styles.
* The map has layer ids as keys and style names as values.
*/
QMap<QString, QString> perLayerCurrentStyle() const;
/**
* The currently used style name for layers with multiple styles.
* The map has layer ids as keys and style names as values.
*/
void setPerLayerCurrentStyle(const QMap<QString, QString>& perLayerCurrentStyle);
};
QgsMapThemeCollection();
/** Returns whether a preset with a matching name exists.
* @param name name of preset to check
* @returns true if preset exists
/**
* Returns whether a map theme with a matching name exists.
*/
bool hasPreset( const QString& name ) const;
bool hasMapTheme( const QString& name ) const;
/** Inserts a new preset to the collection.
* @param name name of preset
* @param state preset record
/**
* Inserts a new map theme to the collection.
* @see update()
*/
void insert( const QString& name, const PresetRecord& state );
void insert( const QString& name, const MapThemeRecord& state );
/** Updates a preset within the collection.
* @param name name of preset to update
* @param state preset record to replace existing preset
/**
* Updates a map theme within the collection.
* @param name name of map theme to update
* @param state map theme record to replace existing map theme
* @see insert()
*/
void update( const QString& name, const PresetRecord& state );
void update( const QString& name, const MapThemeRecord& state );
/** Remove existing preset from collection.
* @param name preset name
/**
* Remove an existing map theme from collection.
*/
void removePreset( const QString& name );
void removeMapTheme( const QString& name );
//! Remove all presets from the collection.
//! Remove all map themes from the collection.
void clear();
//! Returns a list of existing preset names.
QStringList presets() const;
//! Returns a list of existing map theme names.
QStringList mapThemes() const;
/** Returns the recorded state of a preset.
* @param name name of preset
/**
* Returns the recorded state of a map theme.
*/
PresetRecord presetState( const QString& name ) const;
MapThemeRecord mapThemeState( const QString& name ) const;
/** Returns the list of layer IDs that should be visible for the specified preset.
/**
* Returns the list of layer IDs that are visible for the specified map theme.
*
* @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;
QStringList mapThemeVisibleLayers( const QString& name ) const;
/** Apply check states of legend nodes of a given layer as defined in the preset.
* @param name preset name
* @param layerID layer ID
/**
* Apply check states of legend nodes of a given layer as defined in the map theme.
*/
void applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
void applyMapThemeCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
/** Get layer style overrides (for QgsMapSettings) of the visible layers for given preset.
* @param name preset name
/**
* Get layer style overrides (for QgsMapSettings) of the visible layers for given map theme.
*/
QMap<QString, QString> presetStyleOverrides( const QString& name );
QMap<QString, QString> mapThemeStyleOverride( const QString& name );
/** Reads the preset collection state from XML
/**
* Reads the map theme collection state from XML
* @param doc DOM document
* @see writeXML
* @see writeXml
*/
void readXml( const QDomDocument& doc );
/** Writes the preset collection state to XML.
/** Writes the map theme collection state to XML.
* @param doc DOM document
* @see readXML
* @see readXml
*/
void writeXml( QDomDocument& doc );
/** Static method for adding visible layers from a layer tree group to a preset
/**
* Static method for adding visible layers from a layer tree group to a map theme
* record.
* @param parent layer tree group parent
* @param rec preset record to amend
* @param rec map theme record to amend
*/
static void addVisibleLayersToPreset( QgsLayerTreeGroup* parent, PresetRecord& rec );
static void addVisibleLayersToMapTheme( QgsLayerTreeGroup* parent, MapThemeRecord& rec );
signals:
/** Emitted when presets within the collection are changed.
/** Emitted when map themes within the collection are changed.
*/
void presetsChanged();
protected slots:
/** Handles updates of the preset collection when layers are removed from the registry
*/
void registryLayersRemoved( const 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();
void mapThemesChanged();
};

View File

@ -158,7 +158,7 @@ void QgsComposerMapWidget::aboutToShowKeepLayersVisibilityPresetsMenu()
return;
menu->clear();
Q_FOREACH ( const QString& presetName, QgsProject::instance()->mapThemeCollection()->presets() )
Q_FOREACH ( const QString& presetName, QgsProject::instance()->mapThemeCollection()->mapThemes() )
{
menu->addAction( presetName, this, SLOT( keepLayersVisibilityPresetSelected() ) );
}
@ -206,7 +206,7 @@ void QgsComposerMapWidget::keepLayersVisibilityPresetSelected()
mKeepLayerStylesCheckBox->setChecked( true );
mComposerMap->setLayerStyleOverrides( QgsProject::instance()->mapThemeCollection()->presetStyleOverrides( presetName ) );
mComposerMap->setLayerStyleOverrides( QgsProject::instance()->mapThemeCollection()->mapThemeStyleOverride( presetName ) );
mComposerMap->cache();
mComposerMap->update();
@ -219,7 +219,7 @@ void QgsComposerMapWidget::onPresetsChanged()
{
QStringList lst;
lst.append( tr( "(none)" ) );
lst += QgsProject::instance()->mapThemeCollection()->presets();
lst += QgsProject::instance()->mapThemeCollection()->mapThemes();
model->setStringList( lst );
// select the previously selected item again

View File

@ -1200,7 +1200,7 @@ int main( int argc, char *argv[] )
QList< QPair<QgsVectorLayer *, int > > layers;
if ( !dxfPreset.isEmpty() )
{
Q_FOREACH ( const QString& layer, QgsProject::instance()->mapThemeCollection()->presetVisibleLayers( dxfPreset ) )
Q_FOREACH ( const QString& layer, QgsProject::instance()->mapThemeCollection()->mapThemeVisibleLayers( dxfPreset ) )
{
QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( QgsMapLayerRegistry::instance()->mapLayer( layer ) );
if ( !vl )

View File

@ -346,7 +346,7 @@ void QgsVectorLayerAndAttributeModel::applyVisibilityPreset( const QString &name
}
else
{
visibleLayers = QgsProject::instance()->mapThemeCollection()->presetVisibleLayers( name ).toSet();
visibleLayers = QgsProject::instance()->mapThemeCollection()->mapThemeVisibleLayers( name ).toSet();
}
if ( visibleLayers.isEmpty() )
@ -452,7 +452,7 @@ QgsDxfExportDialog::QgsDxfExportDialog( QWidget *parent, Qt::WindowFlags f )
mLayerTitleAsName->setChecked( QgsProject::instance()->readEntry( "dxf", "/lastDxfLayerTitleAsName", s.value( "qgis/lastDxfLayerTitleAsName", "false" ).toString() ) != "false" );
mMapExtentCheckBox->setChecked( QgsProject::instance()->readEntry( "dxf", "/lastDxfMapRectangle", s.value( "qgis/lastDxfMapRectangle", "false" ).toString() ) != "false" );
QStringList ids = QgsProject::instance()->mapThemeCollection()->presets();
QStringList ids = QgsProject::instance()->mapThemeCollection()->mapThemes();
ids.prepend( "" );
mVisibilityPresets->addItems( ids );
mVisibilityPresets->setCurrentIndex( mVisibilityPresets->findText( QgsProject::instance()->readEntry( "dxf", "/lastVisibliltyPreset", "" ) ) );

View File

@ -55,11 +55,11 @@ QgsMapThemes::QgsMapThemes()
connect( mMenu, SIGNAL( aboutToShow() ), this, SLOT( menuAboutToShow() ) );
}
void QgsMapThemes::addPerLayerCheckedLegendSymbols( QgsMapThemeCollection::PresetRecord& rec )
void QgsMapThemes::addPerLayerCheckedLegendSymbols( QgsMapThemeCollection::MapThemeRecord& rec )
{
QgsLayerTreeModel* model = QgisApp::instance()->layerTreeView()->layerTreeModel();
Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIDs )
Q_FOREACH ( const QString& layerID, rec.visibleLayerIds() )
{
QgsLayerTreeLayer* nodeLayer = model->rootGroup()->findLayer( layerID );
if ( !nodeLayer )
@ -81,30 +81,37 @@ void QgsMapThemes::addPerLayerCheckedLegendSymbols( QgsMapThemeCollection::Prese
}
}
QMap<QString, QSet<QString> > checkedSymbols = rec.perLayerCheckedLegendSymbols();
if ( hasCheckableItems && someItemsUnchecked )
rec.mPerLayerCheckedLegendSymbols.insert( nodeLayer->layerId(), checkedItems );
checkedSymbols.insert( nodeLayer->layerId(), checkedItems );
rec.setPerLayerCheckedLegendSymbols( checkedSymbols );
}
}
void QgsMapThemes::addPerLayerCurrentStyle( QgsMapThemeCollection::PresetRecord& rec )
void QgsMapThemes::addPerLayerCurrentStyle( QgsMapThemeCollection::MapThemeRecord& rec )
{
QgsLayerTreeModel* model = QgisApp::instance()->layerTreeView()->layerTreeModel();
Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIDs )
QMap<QString, QString> styles = rec.perLayerCurrentStyle();
Q_FOREACH ( const QString& layerID, rec.visibleLayerIds() )
{
QgsLayerTreeLayer* nodeLayer = model->rootGroup()->findLayer( layerID );
if ( !nodeLayer )
continue;
rec.mPerLayerCurrentStyle[layerID] = nodeLayer->layer()->styleManager()->currentStyle();
styles[layerID] = nodeLayer->layer()->styleManager()->currentStyle();
}
rec.setPerLayerCurrentStyle( styles );
}
QgsMapThemeCollection::PresetRecord QgsMapThemes::currentState()
QgsMapThemeCollection::MapThemeRecord QgsMapThemes::currentState()
{
QgsMapThemeCollection::PresetRecord rec;
QgsMapThemeCollection::MapThemeRecord rec;
QgsLayerTreeGroup* root = QgsProject::instance()->layerTreeRoot();
QgsMapThemeCollection::addVisibleLayersToPreset( root, rec );
QgsMapThemeCollection::addVisibleLayersToMapTheme( root, rec );
addPerLayerCheckedLegendSymbols( rec );
addPerLayerCurrentStyle( rec );
return rec;
@ -130,7 +137,7 @@ void QgsMapThemes::updatePreset( const QString& name )
QStringList QgsMapThemes::orderedPresetVisibleLayers( const QString& name ) const
{
QStringList visibleIds = QgsProject::instance()->mapThemeCollection()->presetVisibleLayers( name );
QStringList visibleIds = QgsProject::instance()->mapThemeCollection()->mapThemeVisibleLayers( name );
// also make sure to order the layers according to map canvas order
QgsLayerTreeMapCanvasBridge* bridge = QgisApp::instance()->layerTreeCanvasBridge();
@ -153,7 +160,7 @@ QMenu* QgsMapThemes::menu()
void QgsMapThemes::addPreset()
{
QStringList existingNames = QgsProject::instance()->mapThemeCollection()->presets();
QStringList existingNames = QgsProject::instance()->mapThemeCollection()->mapThemes();
QgsNewNameDialog dlg( tr( "theme" ) , tr( "Theme" ), QStringList(), existingNames, QRegExp(), Qt::CaseInsensitive, mMenu );
dlg.setWindowTitle( tr( "Map Themes" ) );
dlg.setHintString( tr( "Name of the new theme" ) );
@ -185,7 +192,7 @@ void QgsMapThemes::replaceTriggered()
addPreset( actionPreset->text() );
}
void QgsMapThemes::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const QgsMapThemeCollection::PresetRecord& rec )
void QgsMapThemes::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const QgsMapThemeCollection::MapThemeRecord& rec )
{
Q_FOREACH ( QgsLayerTreeNode* node, parent->children() )
{
@ -194,21 +201,21 @@ void QgsMapThemes::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const
else if ( QgsLayerTree::isLayer( node ) )
{
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
bool isVisible = rec.mVisibleLayerIDs.contains( nodeLayer->layerId() );
bool isVisible = rec.visibleLayerIds().contains( nodeLayer->layerId() );
nodeLayer->setVisible( isVisible ? Qt::Checked : Qt::Unchecked );
if ( isVisible )
{
if ( rec.mPerLayerCurrentStyle.contains( nodeLayer->layerId() ) )
if ( rec.perLayerCurrentStyle().contains( nodeLayer->layerId() ) )
{
// apply desired style first
nodeLayer->layer()->styleManager()->setCurrentStyle( rec.mPerLayerCurrentStyle[nodeLayer->layerId()] );
nodeLayer->layer()->styleManager()->setCurrentStyle( rec.perLayerCurrentStyle().value( nodeLayer->layerId() ) );
}
QgsLayerTreeModel* model = QgisApp::instance()->layerTreeView()->layerTreeModel();
if ( rec.mPerLayerCheckedLegendSymbols.contains( nodeLayer->layerId() ) )
if ( rec.perLayerCheckedLegendSymbols().contains( nodeLayer->layerId() ) )
{
const QSet<QString>& checkedNodes = rec.mPerLayerCheckedLegendSymbols[nodeLayer->layerId()];
const QSet<QString>& checkedNodes = rec.perLayerCheckedLegendSymbols().value( nodeLayer->layerId() );
// some nodes are not checked
Q_FOREACH ( QgsLayerTreeModelLegendNode* legendNode, model->layerLegendNodes( nodeLayer ) )
{
@ -236,10 +243,10 @@ void QgsMapThemes::applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const
void QgsMapThemes::applyState( const QString& presetName )
{
if ( !QgsProject::instance()->mapThemeCollection()->hasPreset( presetName ) )
if ( !QgsProject::instance()->mapThemeCollection()->hasMapTheme( presetName ) )
return;
applyStateToLayerTreeGroup( QgsProject::instance()->layerTreeRoot(), QgsProject::instance()->mapThemeCollection()->presetState( presetName ) );
applyStateToLayerTreeGroup( QgsProject::instance()->layerTreeRoot(), QgsProject::instance()->mapThemeCollection()->mapThemeState( presetName ) );
// also make sure that the preset is up-to-date (not containing any non-existent legend items)
QgsProject::instance()->mapThemeCollection()->update( presetName, currentState() );
@ -251,7 +258,7 @@ void QgsMapThemes::removeCurrentPreset()
{
if ( a->isChecked() )
{
QgsProject::instance()->mapThemeCollection()->removePreset( a->text() );
QgsProject::instance()->mapThemeCollection()->removeMapTheme( a->text() );
break;
}
}
@ -265,14 +272,14 @@ void QgsMapThemes::menuAboutToShow()
qDeleteAll( mMenuReplaceActions );
mMenuReplaceActions.clear();
QgsMapThemeCollection::PresetRecord rec = currentState();
QgsMapThemeCollection::MapThemeRecord rec = currentState();
bool hasCurrent = false;
Q_FOREACH ( const QString& grpName, QgsProject::instance()->mapThemeCollection()->presets() )
Q_FOREACH ( const QString& grpName, QgsProject::instance()->mapThemeCollection()->mapThemes() )
{
QAction* a = new QAction( grpName, mMenu );
a->setCheckable( true );
if ( !hasCurrent && rec == QgsProject::instance()->mapThemeCollection()->presetState( grpName ) )
if ( !hasCurrent && rec == QgsProject::instance()->mapThemeCollection()->mapThemeState( grpName ) )
{
a->setChecked( true );
hasCurrent = true;

View File

@ -74,14 +74,14 @@ class APP_EXPORT QgsMapThemes : public QObject
QgsMapThemes(); // singleton
//! Applies current layer state to a preset record
void applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const QgsMapThemeCollection::PresetRecord& rec );
void applyStateToLayerTreeGroup( QgsLayerTreeGroup* parent, const QgsMapThemeCollection::MapThemeRecord& rec );
//! Applies layer checked legend symbols to a preset record
void addPerLayerCheckedLegendSymbols( QgsMapThemeCollection::PresetRecord& rec );
void addPerLayerCheckedLegendSymbols( QgsMapThemeCollection::MapThemeRecord& rec );
//! Applies current layer styles to a preset record
void addPerLayerCurrentStyle( QgsMapThemeCollection::PresetRecord& rec );
void addPerLayerCurrentStyle( QgsMapThemeCollection::MapThemeRecord& rec );
//! Returns the current state of the map canvas as a preset record
QgsMapThemeCollection::PresetRecord currentState();
QgsMapThemeCollection::MapThemeRecord currentState();
//! Applies a preset for the project's collection to the canvas
void applyState( const QString& presetName );

View File

@ -537,8 +537,8 @@ QStringList QgsComposerMap::layersToRender( const QgsExpressionContext* context
presetName = exprVal.toString();
}
if ( QgsProject::instance()->mapThemeCollection()->hasPreset( presetName ) )
renderLayerSet = QgsProject::instance()->mapThemeCollection()->presetVisibleLayers( presetName );
if ( QgsProject::instance()->mapThemeCollection()->hasMapTheme( presetName ) )
renderLayerSet = QgsProject::instance()->mapThemeCollection()->mapThemeVisibleLayers( presetName );
else // fallback to using map canvas layers
renderLayerSet = mComposition->mapSettings().layers();
}
@ -598,8 +598,8 @@ QMap<QString, QString> QgsComposerMap::layerStyleOverridesToRender( const QgsExp
presetName = exprVal.toString();
}
if ( QgsProject::instance()->mapThemeCollection()->hasPreset( presetName ) )
return QgsProject::instance()->mapThemeCollection()->presetStyleOverrides( presetName );
if ( QgsProject::instance()->mapThemeCollection()->hasMapTheme( presetName ) )
return QgsProject::instance()->mapThemeCollection()->mapThemeStyleOverride( presetName );
else
return QMap<QString, QString>();
}

View File

@ -32,85 +32,85 @@ QgsMapThemeCollection::QgsMapThemeCollection()
this, SLOT( registryLayersRemoved( QStringList ) ) );
}
void QgsMapThemeCollection::addVisibleLayersToPreset( QgsLayerTreeGroup* parent, QgsMapThemeCollection::PresetRecord& rec )
void QgsMapThemeCollection::addVisibleLayersToMapTheme( QgsLayerTreeGroup* parent, QgsMapThemeCollection::MapThemeRecord& rec )
{
Q_FOREACH ( QgsLayerTreeNode* node, parent->children() )
{
if ( QgsLayerTree::isGroup( node ) )
addVisibleLayersToPreset( QgsLayerTree::toGroup( node ), rec );
addVisibleLayersToMapTheme( QgsLayerTree::toGroup( node ), rec );
else if ( QgsLayerTree::isLayer( node ) )
{
QgsLayerTreeLayer* nodeLayer = QgsLayerTree::toLayer( node );
if ( nodeLayer->isVisible() )
rec.mVisibleLayerIDs << nodeLayer->layerId();
rec.mVisibleLayerIds << nodeLayer->layerId();
}
}
}
bool QgsMapThemeCollection::hasPreset( const QString& name ) const
bool QgsMapThemeCollection::hasMapTheme( const QString& name ) const
{
return mPresets.contains( name );
return mMapThemes.contains( name );
}
void QgsMapThemeCollection::insert( const QString& name, const QgsMapThemeCollection::PresetRecord& state )
void QgsMapThemeCollection::insert( const QString& name, const QgsMapThemeCollection::MapThemeRecord& state )
{
mPresets.insert( name, state );
mMapThemes.insert( name, state );
reconnectToLayersStyleManager();
emit presetsChanged();
emit mapThemesChanged();
}
void QgsMapThemeCollection::update( const QString& name, const PresetRecord& state )
void QgsMapThemeCollection::update( const QString& name, const MapThemeRecord& state )
{
if ( !mPresets.contains( name ) )
if ( !mMapThemes.contains( name ) )
return;
mPresets[name] = state;
mMapThemes[name] = state;
reconnectToLayersStyleManager();
emit presetsChanged();
emit mapThemesChanged();
}
void QgsMapThemeCollection::removePreset( const QString& name )
void QgsMapThemeCollection::removeMapTheme( const QString& name )
{
if ( !mPresets.contains( name ) )
if ( !mMapThemes.contains( name ) )
return;
mPresets.remove( name );
mMapThemes.remove( name );
reconnectToLayersStyleManager();
emit presetsChanged();
emit mapThemesChanged();
}
void QgsMapThemeCollection::clear()
{
mPresets.clear();
mMapThemes.clear();
reconnectToLayersStyleManager();
emit presetsChanged();
emit mapThemesChanged();
}
QStringList QgsMapThemeCollection::presets() const
QStringList QgsMapThemeCollection::mapThemes() const
{
return mPresets.keys();
return mMapThemes.keys();
}
QStringList QgsMapThemeCollection::presetVisibleLayers( const QString& name ) const
QStringList QgsMapThemeCollection::mapThemeVisibleLayers( const QString& name ) const
{
return mPresets.value( name ).mVisibleLayerIDs;
return mMapThemes.value( name ).mVisibleLayerIds;
}
void QgsMapThemeCollection::applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID )
void QgsMapThemeCollection::applyMapThemeCheckedLegendNodesToLayer( const QString& name, const QString& layerID )
{
if ( !mPresets.contains( name ) )
if ( !mMapThemes.contains( name ) )
return;
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
if ( !layer )
return;
const PresetRecord& rec = mPresets[name];
const MapThemeRecord& rec = mMapThemes[name];
QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer*>( layer );
if ( !vlayer || !vlayer->renderer() )
@ -131,14 +131,14 @@ void QgsMapThemeCollection::applyPresetCheckedLegendNodesToLayer( const QString&
}
QMap<QString, QString> QgsMapThemeCollection::presetStyleOverrides( const QString& presetName )
QMap<QString, QString> QgsMapThemeCollection::mapThemeStyleOverride( const QString& presetName )
{
QMap<QString, QString> styleOverrides;
if ( !mPresets.contains( presetName ) )
if ( !mMapThemes.contains( presetName ) )
return styleOverrides;
QStringList lst = presetVisibleLayers( presetName );
const QgsMapThemeCollection::PresetRecord& rec = mPresets[presetName];
QStringList lst = mapThemeVisibleLayers( presetName );
const QgsMapThemeCollection::MapThemeRecord& rec = mMapThemes[presetName];
Q_FOREACH ( const QString& layerID, lst )
{
QgsMapLayer* layer = QgsMapLayerRegistry::instance()->mapLayer( layerID );
@ -152,7 +152,7 @@ QMap<QString, QString> QgsMapThemeCollection::presetStyleOverrides( const QStrin
layer->styleManager()->setOverrideStyle( overrideStyleName );
// set the checked legend nodes
applyPresetCheckedLegendNodesToLayer( presetName, layerID );
applyMapThemeCheckedLegendNodesToLayer( presetName, layerID );
// save to overrides
QgsMapLayerStyle layerStyle;
@ -169,10 +169,10 @@ void QgsMapThemeCollection::reconnectToLayersStyleManager()
// disconnect( 0, 0, this, SLOT( layerStyleRenamed( QString, QString ) ) );
QSet<QString> layerIDs;
PresetRecordMap::const_iterator it = mPresets.constBegin();
for ( ; it != mPresets.constEnd(); ++it )
MapThemeRecordMap::const_iterator it = mMapThemes.constBegin();
for ( ; it != mMapThemes.constEnd(); ++it )
{
const PresetRecord& rec = it.value();
const MapThemeRecord& rec = it.value();
QMap<QString, QString>::const_iterator layerIt = rec.mPerLayerCurrentStyle.constBegin();
for ( ; layerIt != rec.mPerLayerCurrentStyle.constEnd(); ++layerIt )
layerIDs << layerIt.key();
@ -197,14 +197,14 @@ void QgsMapThemeCollection::readXml( const QDomDocument& doc )
while ( !visPresetElem.isNull() )
{
QString presetName = visPresetElem.attribute( "name" );
PresetRecord rec;
MapThemeRecord 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
rec.mVisibleLayerIds << layerID; // only use valid layer IDs
if ( visPresetLayerElem.hasAttribute( "style" ) )
rec.mPerLayerCurrentStyle[layerID] = visPresetLayerElem.attribute( "style" );
}
@ -229,26 +229,26 @@ void QgsMapThemeCollection::readXml( const QDomDocument& doc )
checkedLegendNodesElem = checkedLegendNodesElem.nextSiblingElement( "checked-legend-nodes" );
}
mPresets.insert( presetName, rec );
mMapThemes.insert( presetName, rec );
visPresetElem = visPresetElem.nextSiblingElement( "visibility-preset" );
}
reconnectToLayersStyleManager();
emit presetsChanged();
emit mapThemesChanged();
}
void QgsMapThemeCollection::writeXml( QDomDocument& doc )
{
QDomElement visPresetsElem = doc.createElement( "visibility-presets" );
PresetRecordMap::const_iterator it = mPresets.constBegin();
for ( ; it != mPresets.constEnd(); ++ it )
MapThemeRecordMap::const_iterator it = mMapThemes.constBegin();
for ( ; it != mMapThemes.constEnd(); ++ it )
{
QString grpName = it.key();
const PresetRecord& rec = it.value();
const MapThemeRecord& rec = it.value();
QDomElement visPresetElem = doc.createElement( "visibility-preset" );
visPresetElem.setAttribute( "name", grpName );
Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIDs )
Q_FOREACH ( const QString& layerID, rec.mVisibleLayerIds )
{
QDomElement layerElem = doc.createElement( "layer" );
layerElem.setAttribute( "id", layerID );
@ -282,16 +282,16 @@ void QgsMapThemeCollection::registryLayersRemoved( const QStringList& layerIDs )
{
Q_FOREACH ( const QString& layerID, layerIDs )
{
PresetRecordMap::iterator it = mPresets.begin();
for ( ; it != mPresets.end(); ++it )
MapThemeRecordMap::iterator it = mMapThemes.begin();
for ( ; it != mMapThemes.end(); ++it )
{
PresetRecord& rec = it.value();
rec.mVisibleLayerIDs.removeAll( layerID );
MapThemeRecord& rec = it.value();
rec.mVisibleLayerIds.removeAll( layerID );
rec.mPerLayerCheckedLegendSymbols.remove( layerID );
rec.mPerLayerCurrentStyle.remove( layerID );
}
}
emit presetsChanged();
emit mapThemesChanged();
}
void QgsMapThemeCollection::layerStyleRenamed( const QString& oldName, const QString& newName )
@ -302,10 +302,10 @@ void QgsMapThemeCollection::layerStyleRenamed( const QString& oldName, const QSt
QString layerID = styleMgr->layer()->id();
PresetRecordMap::iterator it = mPresets.begin();
for ( ; it != mPresets.end(); ++it )
MapThemeRecordMap::iterator it = mMapThemes.begin();
for ( ; it != mMapThemes.end(); ++it )
{
PresetRecord& rec = it.value();
MapThemeRecord& rec = it.value();
if ( rec.mPerLayerCurrentStyle.contains( layerID ) )
{
@ -314,5 +314,35 @@ void QgsMapThemeCollection::layerStyleRenamed( const QString& oldName, const QSt
rec.mPerLayerCurrentStyle[layerID] = newName;
}
}
emit presetsChanged();
emit mapThemesChanged();
}
QStringList QgsMapThemeCollection::MapThemeRecord::visibleLayerIds() const
{
return mVisibleLayerIds;
}
void QgsMapThemeCollection::MapThemeRecord::setVisibleLayerIds( const QStringList& visibleLayerIds )
{
mVisibleLayerIds = visibleLayerIds;
}
QMap<QString, QSet<QString> > QgsMapThemeCollection::MapThemeRecord::perLayerCheckedLegendSymbols() const
{
return mPerLayerCheckedLegendSymbols;
}
void QgsMapThemeCollection::MapThemeRecord::setPerLayerCheckedLegendSymbols( const QMap<QString, QSet<QString> >& perLayerCheckedLegendSymbols )
{
mPerLayerCheckedLegendSymbols = perLayerCheckedLegendSymbols;
}
QMap<QString, QString> QgsMapThemeCollection::MapThemeRecord::perLayerCurrentStyle() const
{
return mPerLayerCurrentStyle;
}
void QgsMapThemeCollection::MapThemeRecord::setPerLayerCurrentStyle( const QMap<QString, QString>& perLayerCurrentStyle )
{
mPerLayerCurrentStyle = perLayerCurrentStyle;
}

View File

@ -37,134 +37,193 @@ class CORE_EXPORT QgsMapThemeCollection : public QObject
{
Q_OBJECT
Q_PROPERTY( QStringList mapThemes READ mapThemes NOTIFY mapThemesChanged )
public:
/** \ingroup core
* Individual preset record of visible layers and styles.
/**
* \ingroup core
* Individual map theme record of visible layers and styles.
*
* @note Added in QGIS 3.0, Previously called PresetRecord
*/
class PresetRecord
class MapThemeRecord
{
public:
bool operator==( const PresetRecord& other ) const
bool operator==( const MapThemeRecord& other ) const
{
return mVisibleLayerIDs.toSet() == other.mVisibleLayerIDs.toSet()
return mVisibleLayerIds.toSet() == other.mVisibleLayerIds.toSet()
&& mPerLayerCheckedLegendSymbols == other.mPerLayerCheckedLegendSymbols
&& mPerLayerCurrentStyle == other.mPerLayerCurrentStyle;
}
bool operator!=( const PresetRecord& other ) const
bool operator!=( const MapThemeRecord& other ) const
{
return !( *this == other );
}
//! Ordered list of layers that are visible
QStringList mVisibleLayerIDs;
/** For layers that have checkable legend symbols and not all symbols are checked - list which ones are
* @note not available in Python bindings
/**
* Ordered list of visible layers
* @note Added in QGIS 3.0
*/
QStringList visibleLayerIds() const;
/**
* Ordered list of visible layers
* @note Added in QGIS 3.0
*/
void setVisibleLayerIds( const QStringList& visibleLayerIds );
/**
* Lists which legend symbols are checked for layers which support this and where
* not all symbols are checked.
* @note not available in Python bindings
* @note Added in QGIS 3.0
*/
QMap<QString, QSet<QString> > perLayerCheckedLegendSymbols() const;
/**
* Lists which legend symbols are checked for layers which support this and where
* not all symbols are checked.
* @note not available in Python bindings
* @note Added in QGIS 3.0
*/
void setPerLayerCheckedLegendSymbols( const QMap<QString, QSet<QString> >& perLayerCheckedLegendSymbols );
/**
* The currently used style name for layers with multiple styles.
* The map has layer ids as keys and style names as values.
* @note Added in QGIS 3.0
*/
QMap<QString, QString> perLayerCurrentStyle() const;
/**
* The currently used style name for layers with multiple styles.
* The map has layer ids as keys and style names as values.
* @note Added in QGIS 3.0
*/
void setPerLayerCurrentStyle( const QMap<QString, QString>& perLayerCurrentStyle );
private:
QStringList mVisibleLayerIds;
QMap<QString, QSet<QString> > mPerLayerCheckedLegendSymbols;
//! For layers that use multiple styles - which one is currently selected
QMap<QString, QString> mPerLayerCurrentStyle;
friend class QgsMapThemeCollection;
};
QgsMapThemeCollection();
/** Returns whether a preset with a matching name exists.
* @param name name of preset to check
* @returns true if preset exists
/**
* Returns whether a map theme with a matching name exists.
* @note Added in QGIS 3.0
*/
bool hasPreset( const QString& name ) const;
bool hasMapTheme( const QString& name ) const;
/** Inserts a new preset to the collection.
* @param name name of preset
* @param state preset record
/**
* Inserts a new map theme to the collection.
* @see update()
*/
void insert( const QString& name, const PresetRecord& state );
void insert( const QString& name, const MapThemeRecord& state );
/** Updates a preset within the collection.
* @param name name of preset to update
* @param state preset record to replace existing preset
/**
* Updates a map theme within the collection.
* @param name name of map theme to update
* @param state map theme record to replace existing map theme
* @see insert()
*/
void update( const QString& name, const PresetRecord& state );
void update( const QString& name, const MapThemeRecord& state );
/** Remove existing preset from collection.
* @param name preset name
/**
* Remove an existing map theme from collection.
* @note Added in QGIS 3.0
*/
void removePreset( const QString& name );
void removeMapTheme( const QString& name );
//! Remove all presets from the collection.
//! Remove all map themes 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
/**
* Returns a list of existing map theme names.
* @note Added in QGIS 3.0
*/
PresetRecord presetState( const QString& name ) const { return mPresets[name]; }
QStringList mapThemes() const;
/** Returns the list of layer IDs that should be visible for the specified preset.
/**
* Returns the recorded state of a map theme.
* @note Added in QGIS 3.0
*/
MapThemeRecord mapThemeState( const QString& name ) const { return mMapThemes[name]; }
/**
* Returns the list of layer IDs that are visible for the specified map theme.
*
* @note The order of the returned list is not guaranteed to reflect the order of layers
* in the canvas.
* @param name preset name
* @note Added in QGIS 3.0
*/
QStringList presetVisibleLayers( const QString& name ) const;
QStringList mapThemeVisibleLayers( const QString& name ) const;
/** Apply check states of legend nodes of a given layer as defined in the preset.
* @param name preset name
* @param layerID layer ID
/**
* Apply check states of legend nodes of a given layer as defined in the map theme.
* @note Added in QGIS 3.0
*/
void applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
void applyMapThemeCheckedLegendNodesToLayer( const QString& name, const QString& layerID );
/** Get layer style overrides (for QgsMapSettings) of the visible layers for given preset.
* @param name preset name
/**
* Get layer style overrides (for QgsMapSettings) of the visible layers for given map theme.
* @note Added in QGIS 3.0
*/
QMap<QString, QString> presetStyleOverrides( const QString& name );
QMap<QString, QString> mapThemeStyleOverride( const QString& name );
/** Reads the preset collection state from XML
/**
* Reads the map theme collection state from XML
* @param doc DOM document
* @see writeXml
*/
void readXml( const QDomDocument& doc );
/** Writes the preset collection state to XML.
/** Writes the map theme 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
/**
* Static method for adding visible layers from a layer tree group to a map theme
* record.
* @param parent layer tree group parent
* @param rec preset record to amend
* @param rec map theme record to amend
*/
static void addVisibleLayersToPreset( QgsLayerTreeGroup* parent, PresetRecord& rec );
static void addVisibleLayersToMapTheme( QgsLayerTreeGroup* parent, MapThemeRecord& rec );
signals:
/** Emitted when presets within the collection are changed.
/**
* Emitted when map themes within the collection are changed.
* @note Added in QGIS 3.0
*/
void presetsChanged();
void mapThemesChanged();
protected slots:
private slots:
/** Handles updates of the preset collection when layers are removed from the registry
/**
* Handles updates of the map theme collection when layers are removed from the registry
*/
void registryLayersRemoved( const QStringList& layerIDs );
//! Update style name if a stored style gets renamed
void layerStyleRenamed( const QString& oldName, const QString& newName );
protected:
private:
/** Reconnects all preset layers to handle style renames
/**
* Reconnects all map theme layers to handle style renames
*/
void reconnectToLayersStyleManager();
typedef QMap<QString, PresetRecord> PresetRecordMap;
PresetRecordMap mPresets;
typedef QMap<QString, MapThemeRecord> MapThemeRecordMap;
MapThemeRecordMap mMapThemes;
};

View File

@ -480,7 +480,7 @@ void QgsProject::clear()
mEmbeddedLayers.clear();
mRelationManager->clear();
mVisibilityPresetCollection.reset( new QgsMapThemeCollection() );
mMapThemeCollection.reset( new QgsMapThemeCollection() );
mRootGroup->removeAllChildren();
@ -916,8 +916,8 @@ bool QgsProject::read()
mRootGroup->removeCustomProperty( "loading" );
mVisibilityPresetCollection.reset( new QgsMapThemeCollection() );
mVisibilityPresetCollection->readXml( *doc );
mMapThemeCollection.reset( new QgsMapThemeCollection() );
mMapThemeCollection->readXml( *doc );
// reassign change dependencies now that all layers are loaded
QMap<QString, QgsMapLayer*> existingMaps = QgsMapLayerRegistry::instance()->mapLayers();
@ -1203,7 +1203,7 @@ bool QgsProject::write()
imp_->properties_.writeXml( "properties", qgisNode, *doc );
}
mVisibilityPresetCollection->writeXml( *doc );
mMapThemeCollection->writeXml( *doc );
// now wrap it up and ship it to the project file
doc->normalize(); // XXX I'm not entirely sure what this does
@ -2195,7 +2195,7 @@ QgsLayerTreeGroup *QgsProject::layerTreeRoot() const
QgsMapThemeCollection* QgsProject::mapThemeCollection()
{
return mVisibilityPresetCollection.data();
return mMapThemeCollection.data();
}
void QgsProject::setNonIdentifiableLayers( QList<QgsMapLayer*> layers )

View File

@ -76,6 +76,7 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
Q_PROPERTY( QString fileName READ fileName WRITE setFileName NOTIFY fileNameChanged )
Q_PROPERTY( QString homePath READ homePath NOTIFY homePathChanged )
Q_PROPERTY( QgsCoordinateReferenceSystem crs READ crs WRITE setCrs )
Q_PROPERTY( QgsMapThemeCollection* mapThemeCollection READ mapThemeCollection )
public:
@ -615,7 +616,7 @@ class CORE_EXPORT QgsProject : public QObject, public QgsExpressionContextGenera
//! map of transaction group: QPair( providerKey, connString ) -> transactionGroup
QMap< QPair< QString, QString>, QgsTransactionGroup*> mTransactionGroups;
QScopedPointer<QgsMapThemeCollection> mVisibilityPresetCollection;
QScopedPointer<QgsMapThemeCollection> mMapThemeCollection;
};

View File

@ -349,9 +349,8 @@ void TestQgsComposerMap::dataDefinedStyles()
mComposerMap->setFrameEnabled( true );
mComposition->addComposerMap( mComposerMap );
QgsMapThemeCollection::PresetRecord rec;
rec.mVisibleLayerIDs << mPointsLayer->id();
rec.mVisibleLayerIDs << mLinesLayer->id();
QgsMapThemeCollection::MapThemeRecord rec;
rec.setVisibleLayerIds( QStringList() << mPointsLayer->id() << mLinesLayer->id() );
QgsProject::instance()->mapThemeCollection()->insert( "test preset", rec );