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