mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	Use the new UsersCannotToggleEditing property to refine situations
when various actions and editing dependant states should be reflected in qgis app We don't want annotation layers (which are always editable) to make things like the "cancel edits for all layers" action to become enabled.
This commit is contained in:
		
							parent
							
								
									3b2e640cee
								
							
						
					
					
						commit
						1925277b4e
					
				@ -45,10 +45,14 @@ Convert Qt.CheckState to QString
 | 
				
			|||||||
Convert QString to Qt.CheckState
 | 
					Convert QString to Qt.CheckState
 | 
				
			||||||
%End
 | 
					%End
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static bool layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes );
 | 
					    static bool layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes, bool ignoreLayersWhichCannotBeToggled = false );
 | 
				
			||||||
%Docstring
 | 
					%Docstring
 | 
				
			||||||
Returns ``True`` if any of the layers is editable
 | 
					Returns ``True`` if any of the specified layers is editable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The ``ignoreLayersWhichCannotBeToggled`` argument can be used to control whether layers which cannot have their
 | 
				
			||||||
 | 
					edit states toggled by users should be ignored or not (since QGIS 3.22).
 | 
				
			||||||
%End
 | 
					%End
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static bool layersModified( const QList<QgsLayerTreeLayer *> &layerNodes );
 | 
					    static bool layersModified( const QList<QgsLayerTreeLayer *> &layerNodes );
 | 
				
			||||||
%Docstring
 | 
					%Docstring
 | 
				
			||||||
Returns ``True`` if any of the layers is modified
 | 
					Returns ``True`` if any of the layers is modified
 | 
				
			||||||
 | 
				
			|||||||
@ -11468,7 +11468,7 @@ void QgisApp::saveAllEdits( bool verifyAction )
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const auto layers = editableLayers( true );
 | 
					  const auto layers = editableLayers( true, true );
 | 
				
			||||||
  for ( QgsMapLayer *layer : layers )
 | 
					  for ( QgsMapLayer *layer : layers )
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    saveEdits( layer, true, false );
 | 
					    saveEdits( layer, true, false );
 | 
				
			||||||
@ -11496,7 +11496,7 @@ void QgisApp::rollbackAllEdits( bool verifyAction )
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const auto layers = editableLayers( true );
 | 
					  const auto layers = editableLayers( true, true );
 | 
				
			||||||
  for ( QgsMapLayer *layer : layers )
 | 
					  for ( QgsMapLayer *layer : layers )
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    cancelEdits( layer, true, false );
 | 
					    cancelEdits( layer, true, false );
 | 
				
			||||||
@ -11524,7 +11524,7 @@ void QgisApp::cancelAllEdits( bool verifyAction )
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const auto layers = editableLayers();
 | 
					  const auto layers = editableLayers( false, true );
 | 
				
			||||||
  for ( QgsMapLayer *layer : layers )
 | 
					  for ( QgsMapLayer *layer : layers )
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    cancelEdits( layer, false, false );
 | 
					    cancelEdits( layer, false, false );
 | 
				
			||||||
@ -11595,16 +11595,16 @@ void QgisApp::updateLayerModifiedActions()
 | 
				
			|||||||
  mActionRollbackEdits->setEnabled( QgsLayerTreeUtils::layersModified( selectedLayerNodes ) );
 | 
					  mActionRollbackEdits->setEnabled( QgsLayerTreeUtils::layersModified( selectedLayerNodes ) );
 | 
				
			||||||
  mActionCancelEdits->setEnabled( QgsLayerTreeUtils::layersEditable( selectedLayerNodes ) );
 | 
					  mActionCancelEdits->setEnabled( QgsLayerTreeUtils::layersEditable( selectedLayerNodes ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool hasEditLayers = !editableLayers().isEmpty();
 | 
					  bool hasEditLayers = !editableLayers( false, true ).isEmpty();
 | 
				
			||||||
  mActionAllEdits->setEnabled( hasEditLayers );
 | 
					  mActionAllEdits->setEnabled( hasEditLayers );
 | 
				
			||||||
  mActionCancelAllEdits->setEnabled( hasEditLayers );
 | 
					  mActionCancelAllEdits->setEnabled( hasEditLayers );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool hasModifiedLayers = !editableLayers( true ).isEmpty();
 | 
					  bool hasModifiedLayers = !editableLayers( true, true ).isEmpty();
 | 
				
			||||||
  mActionSaveAllEdits->setEnabled( hasModifiedLayers );
 | 
					  mActionSaveAllEdits->setEnabled( hasModifiedLayers );
 | 
				
			||||||
  mActionRollbackAllEdits->setEnabled( hasModifiedLayers );
 | 
					  mActionRollbackAllEdits->setEnabled( hasModifiedLayers );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QList<QgsMapLayer *> QgisApp::editableLayers( bool modified ) const
 | 
					QList<QgsMapLayer *> QgisApp::editableLayers( bool modified, bool ignoreLayersWhichCannotBeToggled ) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  QList<QgsMapLayer *> editLayers;
 | 
					  QList<QgsMapLayer *> editLayers;
 | 
				
			||||||
  // use legend layers (instead of registry) so QList mirrors its order
 | 
					  // use legend layers (instead of registry) so QList mirrors its order
 | 
				
			||||||
@ -11615,7 +11615,7 @@ QList<QgsMapLayer *> QgisApp::editableLayers( bool modified ) const
 | 
				
			|||||||
    if ( !layer )
 | 
					    if ( !layer )
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( layer->isEditable() && ( !modified || layer->isModified() ) )
 | 
					    if ( layer->isEditable() && ( !modified || layer->isModified() ) && ( !ignoreLayersWhichCannotBeToggled || !( layer->properties() & Qgis::MapLayerProperty::UsersCannotToggleEditing ) ) )
 | 
				
			||||||
      editLayers << layer;
 | 
					      editLayers << layer;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return editLayers;
 | 
					  return editLayers;
 | 
				
			||||||
@ -15723,7 +15723,6 @@ void QgisApp::activateDeactivateLayerRelatedActions( QgsMapLayer *layer )
 | 
				
			|||||||
      updateUndoActions();
 | 
					      updateUndoActions();
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  refreshFeatureActions();
 | 
					  refreshFeatureActions();
 | 
				
			||||||
 | 
				
			|||||||
@ -706,7 +706,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
 | 
				
			|||||||
     * \param modified whether to return only layers that have been modified
 | 
					     * \param modified whether to return only layers that have been modified
 | 
				
			||||||
     * \returns list of layers in legend order, or empty list
 | 
					     * \returns list of layers in legend order, or empty list
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
    QList<QgsMapLayer *> editableLayers( bool modified = false ) const;
 | 
					    QList<QgsMapLayer *> editableLayers( bool modified = false, bool ignoreLayersWhichCannotBeToggled = false ) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //! emit initializationCompleted signal
 | 
					    //! emit initializationCompleted signal
 | 
				
			||||||
    void completeInitialization();
 | 
					    void completeInitialization();
 | 
				
			||||||
 | 
				
			|||||||
@ -261,7 +261,7 @@ static void _readOldLegendLayer( const QDomElement &layerElem, QgsLayerTreeGroup
 | 
				
			|||||||
  parent->addChildNode( layerNode );
 | 
					  parent->addChildNode( layerNode );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes )
 | 
					bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes, bool ignoreLayersWhichCannotBeToggled )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  const auto constLayerNodes = layerNodes;
 | 
					  const auto constLayerNodes = layerNodes;
 | 
				
			||||||
  for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
 | 
					  for ( QgsLayerTreeLayer *layerNode : constLayerNodes )
 | 
				
			||||||
@ -270,7 +270,7 @@ bool QgsLayerTreeUtils::layersEditable( const QList<QgsLayerTreeLayer *> &layerN
 | 
				
			|||||||
    if ( !layer )
 | 
					    if ( !layer )
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ( layer->isEditable() )
 | 
					    if ( layer->isEditable() && ( !ignoreLayersWhichCannotBeToggled || !( layer->properties() & Qgis::MapLayerProperty::UsersCannotToggleEditing ) ) )
 | 
				
			||||||
      return true;
 | 
					      return true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
 | 
				
			|||||||
@ -53,8 +53,14 @@ class CORE_EXPORT QgsLayerTreeUtils
 | 
				
			|||||||
    //! Convert QString to Qt::CheckState
 | 
					    //! Convert QString to Qt::CheckState
 | 
				
			||||||
    static Qt::CheckState checkStateFromXml( const QString &txt );
 | 
					    static Qt::CheckState checkStateFromXml( const QString &txt );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //! Returns TRUE if any of the layers is editable
 | 
					    /**
 | 
				
			||||||
    static bool layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes );
 | 
					     * Returns TRUE if any of the specified layers is editable.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * The \a ignoreLayersWhichCannotBeToggled argument can be used to control whether layers which cannot have their
 | 
				
			||||||
 | 
					     * edit states toggled by users should be ignored or not (since QGIS 3.22).
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static bool layersEditable( const QList<QgsLayerTreeLayer *> &layerNodes, bool ignoreLayersWhichCannotBeToggled = false );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //! Returns TRUE if any of the layers is modified
 | 
					    //! Returns TRUE if any of the layers is modified
 | 
				
			||||||
    static bool layersModified( const QList<QgsLayerTreeLayer *> &layerNodes );
 | 
					    static bool layersModified( const QList<QgsLayerTreeLayer *> &layerNodes );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@
 | 
				
			|||||||
#include <qgssettings.h>
 | 
					#include <qgssettings.h>
 | 
				
			||||||
#include "qgslegendsettings.h"
 | 
					#include "qgslegendsettings.h"
 | 
				
			||||||
#include "qgsmarkersymbol.h"
 | 
					#include "qgsmarkersymbol.h"
 | 
				
			||||||
 | 
					#include "qgsannotationlayer.h"
 | 
				
			||||||
#include <QSignalSpy>
 | 
					#include <QSignalSpy>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestQgsLayerTree : public QObject
 | 
					class TestQgsLayerTree : public QObject
 | 
				
			||||||
@ -62,6 +63,7 @@ class TestQgsLayerTree : public QObject
 | 
				
			|||||||
    void testSymbolText();
 | 
					    void testSymbolText();
 | 
				
			||||||
    void testNodeDepth();
 | 
					    void testNodeDepth();
 | 
				
			||||||
    void testRasterSymbolNode();
 | 
					    void testRasterSymbolNode();
 | 
				
			||||||
 | 
					    void testLayersEditable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private:
 | 
					  private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -900,5 +902,39 @@ void TestQgsLayerTree::testRasterSymbolNode()
 | 
				
			|||||||
  QCOMPARE( static_cast< int >( rasterNode2.flags() ), static_cast< int >( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) );
 | 
					  QCOMPARE( static_cast< int >( rasterNode2.flags() ), static_cast< int >( Qt::ItemIsEnabled | Qt::ItemIsUserCheckable ) );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void TestQgsLayerTree::testLayersEditable()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  QgsProject project;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QgsVectorLayer *vl1 = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer" ), QStringLiteral( "vl1" ), QStringLiteral( "memory" ) );
 | 
				
			||||||
 | 
					  QgsVectorLayer *vl2 = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer" ), QStringLiteral( "vl1" ), QStringLiteral( "memory" ) );
 | 
				
			||||||
 | 
					  QgsAnnotationLayer *al = new QgsAnnotationLayer( QStringLiteral( "al" ), QgsAnnotationLayer::LayerOptions( project.transformContext() ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  project.addMapLayer( vl1 );
 | 
				
			||||||
 | 
					  project.addMapLayer( vl2 );
 | 
				
			||||||
 | 
					  project.addMapLayer( al );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QgsLayerTree root;
 | 
				
			||||||
 | 
					  QgsLayerTreeLayer *nodeVl1 = root.addLayer( vl1 );
 | 
				
			||||||
 | 
					  QgsLayerTreeGroup *nodeGrp = root.addGroup( QStringLiteral( "grp" ) );
 | 
				
			||||||
 | 
					  QgsLayerTreeLayer *nodeVl2 = nodeGrp->addLayer( vl2 );
 | 
				
			||||||
 | 
					  QgsLayerTreeLayer *nodeAl = nodeGrp->addLayer( al );
 | 
				
			||||||
 | 
					  QVERIFY( !QgsLayerTreeUtils::layersEditable( {} ) );
 | 
				
			||||||
 | 
					  QVERIFY( !QgsLayerTreeUtils::layersEditable( {nodeVl1, nodeVl2} ) );
 | 
				
			||||||
 | 
					  vl1->startEditing();
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeVl1} ) );
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeVl1, nodeVl2} ) );
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeVl2, nodeVl1 } ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeAl} ) );
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeAl, nodeVl1} ) );
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeAl, nodeVl2} ) );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // ignore layers which can't be toggled (the annotation layer)
 | 
				
			||||||
 | 
					  QVERIFY( !QgsLayerTreeUtils::layersEditable( {nodeAl}, true ) );
 | 
				
			||||||
 | 
					  QVERIFY( QgsLayerTreeUtils::layersEditable( {nodeAl, nodeVl1}, true ) );
 | 
				
			||||||
 | 
					  QVERIFY( !QgsLayerTreeUtils::layersEditable( {nodeAl, nodeVl2}, true ) );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QGSTEST_MAIN( TestQgsLayerTree )
 | 
					QGSTEST_MAIN( TestQgsLayerTree )
 | 
				
			||||||
#include "testqgslayertree.moc"
 | 
					#include "testqgslayertree.moc"
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user