QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgstransactiongroup.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstransactiongroup.cpp - QgsTransactionGroup
3  ---------------------------------------------
4 
5  begin : 15.1.2016
6  Copyright : (C) 2016 Matthias Kuhn
7  Email : matthias at opengis dot ch
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************/
16 #include "qgstransactiongroup.h"
17 
18 #include "qgstransaction.h"
19 #include "qgsvectorlayer.h"
20 #include "qgsdatasourceuri.h"
21 #include "qgsvectordataprovider.h"
22 
23 #include <QTimer>
24 
26  : QObject( parent )
27 {
28 
29 }
30 
32 {
34  return false;
35 
36  QString connString = QgsTransaction::connectionString( layer->source() );
37  if ( mConnString.isEmpty() )
38  {
39  mConnString = connString;
40  mProviderKey = layer->providerType();
41  }
42  else if ( mConnString != connString || mProviderKey != layer->providerType() )
43  {
44  return false;
45  }
46 
47  mLayers.insert( layer );
48 
49  connect( layer, &QgsVectorLayer::beforeEditingStarted, this, &QgsTransactionGroup::onEditingStarted );
50  connect( layer, &QgsVectorLayer::destroyed, this, &QgsTransactionGroup::onLayerDeleted );
51 
52  return true;
53 }
54 
55 QSet<QgsVectorLayer *> QgsTransactionGroup::layers() const
56 {
57  return mLayers;
58 }
59 
61 {
62  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
63  {
64  if ( layer->isModified() )
65  return true;
66  }
67  return false;
68 }
69 
70 void QgsTransactionGroup::onEditingStarted()
71 {
72  if ( mTransaction )
73  return;
74 
75  mTransaction.reset( QgsTransaction::create( mConnString, mProviderKey ) );
76  if ( !mTransaction )
77  return;
78 
79  QString errorMsg;
80  mTransaction->begin( errorMsg );
81 
82  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
83  {
84  mTransaction->addLayer( layer );
85  layer->startEditing();
86  connect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onCommitChanges );
87  connect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
88  }
89 }
90 
91 void QgsTransactionGroup::onLayerDeleted()
92 {
93  mLayers.remove( static_cast<QgsVectorLayer *>( sender() ) );
94 }
95 
96 void QgsTransactionGroup::onCommitChanges()
97 {
98  if ( mEditingStopping )
99  return;
100 
101  mEditingStopping = true;
102 
103  QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
104 
105  QString errMsg;
106  if ( mTransaction->commit( errMsg ) )
107  {
108  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
109  {
110  if ( layer != sender() )
111  layer->commitChanges();
112  }
113 
114  disableTransaction();
115  }
116  else
117  {
118  emit commitError( errMsg );
119  // Restart editing the calling layer in the next event loop cycle
120  QTimer::singleShot( 0, triggeringLayer, SLOT( startEditing() ) );
121  }
122  mEditingStopping = false;
123 }
124 
125 void QgsTransactionGroup::onRollback()
126 {
127  if ( mEditingStopping )
128  return;
129 
130  mEditingStopping = true;
131 
132  QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
133 
134  QString errMsg;
135  if ( mTransaction->rollback( errMsg ) )
136  {
137  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
138  {
139  if ( layer != triggeringLayer )
140  layer->rollBack();
141  }
142  disableTransaction();
143  }
144  else
145  {
146  // Restart editing the calling layer in the next event loop cycle
147  QTimer::singleShot( 0, triggeringLayer, SLOT( startEditing() ) );
148  }
149  mEditingStopping = false;
150 }
151 
152 void QgsTransactionGroup::disableTransaction()
153 {
154  mTransaction.reset();
155 
156  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
157  {
158  disconnect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onCommitChanges );
159  disconnect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
160  }
161 }
162 
164 {
165  return mProviderKey;
166 }
167 
169 {
170  return mLayers.isEmpty();
171 }
172 
174 {
175  return mConnString;
176 }
QSet< QgsVectorLayer * > layers() const
Gets the set of layers currently managed by this transaction group.
static QgsTransaction * create(const QString &connString, const QString &providerKey)
Create a transaction for the specified connection string connString and provider with providerKey...
void beforeRollBack()
Is emitted, before changes are rolled back.
bool commitChanges()
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
bool startEditing()
Makes the layer editable.
QString source() const
Returns the source for the layer.
QString connString() const
Returns the connection string used by this transaction group.
void beforeCommitChanges()
Is emitted, before changes are committed to the data provider.
bool isEmpty() const
Returns true if there are no layers in this transaction group.
bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
void beforeEditingStarted()
Is emitted, before editing on this layer is started.
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
QString providerKey() const
Returns the provider key used by this transaction group.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
QString providerType() const
Returns the provider type for this layer.
QgsTransactionGroup(QObject *parent=nullptr)
Constructor for QgsTransactionGroup.
bool modified() const
Returns true if any of the layers in this group reports a modification.
void commitError(const QString &msg)
Will be emitted whenever there is a commit error.
Represents a vector layer which manages a vector based data sets.