QGIS API Documentation 3.99.0-Master (26c88405ac0)
Loading...
Searching...
No Matches
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 "qgsdatasourceuri.h"
19#include "qgslogger.h"
20#include "qgstransaction.h"
22#include "qgsvectorlayer.h"
23
24#include <QTimer>
25
26#include "moc_qgstransactiongroup.cpp"
27
29 : QObject( parent )
30{
31
32}
33
35{
37 return false;
38
39 const QString connString = QgsTransaction::connectionString( layer->source() );
40 if ( mConnString.isEmpty() )
41 {
42 mConnString = connString;
43 mProviderKey = layer->providerType();
44 }
45 else if ( mConnString != connString || mProviderKey != layer->providerType() )
46 {
47 return false;
48 }
49
50 mLayers.insert( layer );
51
52 connect( layer, &QgsVectorLayer::beforeEditingStarted, this, &QgsTransactionGroup::onEditingStarted );
53 connect( layer, &QgsVectorLayer::destroyed, this, &QgsTransactionGroup::onLayerDeleted );
54
55 return true;
56}
57
58QSet<QgsVectorLayer *> QgsTransactionGroup::layers() const
59{
60 return mLayers;
61}
62
64{
65 const auto constMLayers = mLayers;
66 for ( QgsVectorLayer *layer : constMLayers )
67 {
68 if ( layer->isModified() )
69 return true;
70 }
71 return false;
72}
73
74void QgsTransactionGroup::onEditingStarted()
75{
76 if ( mTransaction )
77 return;
78
79 mTransaction.reset( QgsTransaction::create( mConnString, mProviderKey ) );
80 if ( !mTransaction )
81 return;
82
83 QString errorMsg;
84 mTransaction->begin( errorMsg );
85
86 const auto triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
87
88 const auto constMLayers = mLayers;
89 for ( QgsVectorLayer *layer : constMLayers )
90 {
91 mTransaction->addLayer( layer, true );
92
93 // Do not start editing the triggering layer, it will be started by the caller
94 if ( layer != triggeringLayer )
95 {
96 layer->startEditing();
97 }
98
99 connect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onBeforeCommitChanges );
100 connect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
101
102 }
103}
104
105void QgsTransactionGroup::onLayerDeleted()
106{
107 mLayers.remove( static_cast<QgsVectorLayer *>( sender() ) );
108}
109
110void QgsTransactionGroup::onBeforeCommitChanges( bool stopEditing )
111{
112 if ( mEditingStopping )
113 return;
114
115 mEditingStopping = true;
116
117 const QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
118
119 QString errMsg;
120 if ( mTransaction->commit( errMsg ) )
121 {
122 const auto constMLayers = mLayers;
123 for ( QgsVectorLayer *layer : constMLayers )
124 {
125 if ( layer != triggeringLayer )
126 {
127 layer->commitChanges( stopEditing );
128 }
129 }
130
131 if ( stopEditing )
132 {
133 disableTransaction();
134 }
135 else
136 {
137 if ( ! mTransaction->begin( errMsg ) )
138 {
139 QgsDebugError( QStringLiteral( "Could not restart a transaction for %1: %2" ).arg( triggeringLayer->name() ).arg( errMsg ) );
140 }
141 }
142
143 }
144 else
145 {
146 emit commitError( errMsg );
147 restartTransaction( triggeringLayer );
148 }
149 mEditingStopping = false;
150}
151
152void QgsTransactionGroup::onRollback()
153{
154 if ( mEditingStopping )
155 return;
156
157 mEditingStopping = true;
158
159 QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
160
161 QString errMsg;
162 if ( mTransaction->rollback( errMsg ) )
163 {
164 const auto constMLayers = mLayers;
165 for ( QgsVectorLayer *layer : constMLayers )
166 {
167 if ( layer != triggeringLayer )
168 layer->rollBack();
169 }
170 disableTransaction();
171 }
172 else
173 {
174 restartTransaction( triggeringLayer );
175 }
176 mEditingStopping = false;
177}
178
179void QgsTransactionGroup::disableTransaction()
180{
181 mTransaction.reset();
182
183 const auto constMLayers = mLayers;
184 for ( QgsVectorLayer *layer : constMLayers )
185 {
186 disconnect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onBeforeCommitChanges );
187 disconnect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
188 }
189}
190
191void QgsTransactionGroup::restartTransaction( const QgsVectorLayer *layer )
192{
193 // Restart editing the calling layer in the next event loop cycle
194 QTimer::singleShot( 0, layer, &QgsVectorLayer::startEditing );
195}
196
198{
199 return mProviderKey;
200}
201
203{
204 return mLayers.isEmpty();
205}
206
208{
209 return mConnString;
210}
QString name
Definition qgsmaplayer.h:84
QString source() const
Returns the source for the layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QString connString() const
Returns the connection string used by this transaction group.
bool modified() const
Returns true if any of the layers in this group reports a modification.
QgsTransactionGroup(QObject *parent=nullptr)
Constructor for QgsTransactionGroup.
bool isEmpty() const
Returns true if there are no layers in this transaction group.
void commitError(const QString &msg)
Will be emitted whenever there is a commit error.
QString providerKey() const
Returns the provider key used by this transaction group.
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
QSet< QgsVectorLayer * > layers() const
Gets the set of layers currently managed by this transaction group.
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
QString connectionString() const
Returns the connection string of the transaction.
static QgsTransaction * create(const QString &connString, const QString &providerKey)
Create a transaction for the specified connection string connString and provider with providerKey.
Represents a vector layer which manages a vector based dataset.
void beforeCommitChanges(bool stopEditing)
Emitted before changes are committed to the data provider.
Q_INVOKABLE bool startEditing()
Makes the layer editable.
void beforeEditingStarted()
Emitted before editing on this layer is started.
void beforeRollBack()
Emitted before changes are rolled back.
#define QgsDebugError(str)
Definition qgslogger.h:57