QGIS API Documentation 3.99.0-Master (d270888f95f)
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 <QString>
25#include <QTimer>
26
27#include "moc_qgstransactiongroup.cpp"
28
29using namespace Qt::StringLiterals;
30
32 : QObject( parent )
33{
34
35}
36
38{
40 return false;
41
42 const QString connString = QgsTransaction::connectionString( layer->source() );
43 if ( mConnString.isEmpty() )
44 {
45 mConnString = connString;
46 mProviderKey = layer->providerType();
47 }
48 else if ( mConnString != connString || mProviderKey != layer->providerType() )
49 {
50 return false;
51 }
52
53 mLayers.insert( layer );
54
55 connect( layer, &QgsVectorLayer::beforeEditingStarted, this, &QgsTransactionGroup::onEditingStarted );
56 connect( layer, &QgsVectorLayer::destroyed, this, &QgsTransactionGroup::onLayerDeleted );
57
58 return true;
59}
60
61QSet<QgsVectorLayer *> QgsTransactionGroup::layers() const
62{
63 return mLayers;
64}
65
67{
68 const auto constMLayers = mLayers;
69 for ( QgsVectorLayer *layer : constMLayers )
70 {
71 if ( layer->isModified() )
72 return true;
73 }
74 return false;
75}
76
77void QgsTransactionGroup::onEditingStarted()
78{
79 if ( mTransaction )
80 return;
81
82 mTransaction.reset( QgsTransaction::create( mConnString, mProviderKey ) );
83 if ( !mTransaction )
84 return;
85
86 QString errorMsg;
87 mTransaction->begin( errorMsg );
88
89 const auto triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
90
91 const auto constMLayers = mLayers;
92 for ( QgsVectorLayer *layer : constMLayers )
93 {
94 mTransaction->addLayer( layer, true );
95
96 // Do not start editing the triggering layer, it will be started by the caller
97 if ( layer != triggeringLayer )
98 {
99 layer->startEditing();
100 }
101
102 connect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onBeforeCommitChanges );
103 connect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
104
105 }
106}
107
108void QgsTransactionGroup::onLayerDeleted()
109{
110 mLayers.remove( static_cast<QgsVectorLayer *>( sender() ) );
111}
112
113void QgsTransactionGroup::onBeforeCommitChanges( bool stopEditing )
114{
115 if ( mEditingStopping )
116 return;
117
118 mEditingStopping = true;
119
120 const QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
121
122 QString errMsg;
123 if ( mTransaction->commit( errMsg ) )
124 {
125 const auto constMLayers = mLayers;
126 for ( QgsVectorLayer *layer : constMLayers )
127 {
128 if ( layer != triggeringLayer )
129 {
130 layer->commitChanges( stopEditing );
131 }
132 }
133
134 if ( stopEditing )
135 {
136 disableTransaction();
137 }
138 else
139 {
140 if ( ! mTransaction->begin( errMsg ) )
141 {
142 QgsDebugError( u"Could not restart a transaction for %1: %2"_s.arg( triggeringLayer->name() ).arg( errMsg ) );
143 }
144 }
145
146 }
147 else
148 {
149 emit commitError( errMsg );
150 restartTransaction( triggeringLayer );
151 }
152 mEditingStopping = false;
153}
154
155void QgsTransactionGroup::onRollback()
156{
157 if ( mEditingStopping )
158 return;
159
160 mEditingStopping = true;
161
162 QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
163
164 QString errMsg;
165 if ( mTransaction->rollback( errMsg ) )
166 {
167 const auto constMLayers = mLayers;
168 for ( QgsVectorLayer *layer : constMLayers )
169 {
170 if ( layer != triggeringLayer )
171 layer->rollBack();
172 }
173 disableTransaction();
174 }
175 else
176 {
177 restartTransaction( triggeringLayer );
178 }
179 mEditingStopping = false;
180}
181
182void QgsTransactionGroup::disableTransaction()
183{
184 mTransaction.reset();
185
186 const auto constMLayers = mLayers;
187 for ( QgsVectorLayer *layer : constMLayers )
188 {
189 disconnect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onBeforeCommitChanges );
190 disconnect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
191 }
192}
193
194void QgsTransactionGroup::restartTransaction( const QgsVectorLayer *layer )
195{
196 // Restart editing the calling layer in the next event loop cycle
197 QTimer::singleShot( 0, layer, &QgsVectorLayer::startEditing );
198}
199
201{
202 return mProviderKey;
203}
204
206{
207 return mLayers.isEmpty();
208}
209
211{
212 return mConnString;
213}
QString name
Definition qgsmaplayer.h:87
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:59