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