QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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  const auto constMLayers = mLayers;
63  for ( QgsVectorLayer *layer : constMLayers )
64  {
65  if ( layer->isModified() )
66  return true;
67  }
68  return false;
69 }
70 
71 void QgsTransactionGroup::onEditingStarted()
72 {
73  if ( mTransaction )
74  return;
75 
76  mTransaction.reset( QgsTransaction::create( mConnString, mProviderKey ) );
77  if ( !mTransaction )
78  return;
79 
80  QString errorMsg;
81  mTransaction->begin( errorMsg );
82 
83  const auto constMLayers = mLayers;
84  for ( QgsVectorLayer *layer : constMLayers )
85  {
86  mTransaction->addLayer( layer );
87  layer->startEditing();
88  connect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onCommitChanges );
89  connect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
90  }
91 }
92 
93 void QgsTransactionGroup::onLayerDeleted()
94 {
95  mLayers.remove( static_cast<QgsVectorLayer *>( sender() ) );
96 }
97 
98 void QgsTransactionGroup::onCommitChanges()
99 {
100  if ( mEditingStopping )
101  return;
102 
103  mEditingStopping = true;
104 
105  QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
106 
107  QString errMsg;
108  if ( mTransaction->commit( errMsg ) )
109  {
110  const auto constMLayers = mLayers;
111  for ( QgsVectorLayer *layer : constMLayers )
112  {
113  if ( layer != sender() )
114  layer->commitChanges();
115  }
116 
117  disableTransaction();
118  }
119  else
120  {
121  emit commitError( errMsg );
122  // Restart editing the calling layer in the next event loop cycle
123  QTimer::singleShot( 0, triggeringLayer, &QgsVectorLayer::startEditing );
124  }
125  mEditingStopping = false;
126 }
127 
128 void QgsTransactionGroup::onRollback()
129 {
130  if ( mEditingStopping )
131  return;
132 
133  mEditingStopping = true;
134 
135  QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
136 
137  QString errMsg;
138  if ( mTransaction->rollback( errMsg ) )
139  {
140  const auto constMLayers = mLayers;
141  for ( QgsVectorLayer *layer : constMLayers )
142  {
143  if ( layer != triggeringLayer )
144  layer->rollBack();
145  }
146  disableTransaction();
147  }
148  else
149  {
150  // Restart editing the calling layer in the next event loop cycle
151  QTimer::singleShot( 0, triggeringLayer, &QgsVectorLayer::startEditing );
152  }
153  mEditingStopping = false;
154 }
155 
156 void QgsTransactionGroup::disableTransaction()
157 {
158  mTransaction.reset();
159 
160  const auto constMLayers = mLayers;
161  for ( QgsVectorLayer *layer : constMLayers )
162  {
163  disconnect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onCommitChanges );
164  disconnect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
165  }
166 }
167 
169 {
170  return mProviderKey;
171 }
172 
174 {
175  return mLayers.isEmpty();
176 }
177 
179 {
180  return mConnString;
181 }
QgsVectorLayer::beforeRollBack
void beforeRollBack()
Emitted before changes are rolled back.
QgsVectorLayer::beforeEditingStarted
void beforeEditingStarted()
Emitted before editing on this layer is started.
QgsVectorLayer::beforeCommitChanges
void beforeCommitChanges()
Emitted before changes are committed to the data provider.
QgsTransactionGroup::isEmpty
bool isEmpty() const
Returns true if there are no layers in this transaction group.
Definition: qgstransactiongroup.cpp:173
QgsVectorLayer::startEditing
Q_INVOKABLE bool startEditing()
Makes the layer editable.
Definition: qgsvectorlayer.cpp:1411
QgsTransactionGroup::providerKey
QString providerKey() const
Returns the provider key used by this transaction group.
Definition: qgstransactiongroup.cpp:168
QgsMapLayer::providerType
QString providerType() const
Returns the provider type (provider key) for this layer.
Definition: qgsmaplayer.cpp:1614
QgsTransactionGroup::QgsTransactionGroup
QgsTransactionGroup(QObject *parent=nullptr)
Constructor for QgsTransactionGroup.
Definition: qgstransactiongroup.cpp:25
qgsdatasourceuri.h
QgsTransaction::supportsTransaction
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
Definition: qgstransaction.cpp:189
qgstransactiongroup.h
qgsvectordataprovider.h
QgsTransactionGroup::connString
QString connString() const
Returns the connection string used by this transaction group.
Definition: qgstransactiongroup.cpp:178
qgsvectorlayer.h
QgsTransactionGroup::modified
bool modified() const
Returns true if any of the layers in this group reports a modification.
Definition: qgstransactiongroup.cpp:60
qgstransaction.h
QgsMapLayer::source
QString source() const
Returns the source for the layer.
Definition: qgsmaplayer.cpp:192
QgsVectorLayer
Definition: qgsvectorlayer.h:385
QgsTransaction::create
static QgsTransaction * create(const QString &connString, const QString &providerKey)
Create a transaction for the specified connection string connString and provider with providerKey.
Definition: qgstransaction.cpp:27
QgsTransactionGroup::commitError
void commitError(const QString &msg)
Will be emitted whenever there is a commit error.
QgsTransactionGroup::layers
QSet< QgsVectorLayer * > layers() const
Gets the set of layers currently managed by this transaction group.
Definition: qgstransactiongroup.cpp:55
QgsTransactionGroup::addLayer
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
Definition: qgstransactiongroup.cpp:31