QGIS API Documentation  3.0.2-Girona (307d082)
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 = QgsDataSourceUri( layer->source() ).connectionInfo();
37 
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 
56 QSet<QgsVectorLayer *> QgsTransactionGroup::layers() const
57 {
58  return mLayers;
59 }
60 
62 {
63  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
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 
78  QString errorMsg;
79  mTransaction->begin( errorMsg );
80 
81  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
82  {
83  mTransaction->addLayer( layer );
84  layer->startEditing();
85  connect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onCommitChanges );
86  connect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
87  }
88 }
89 
90 void QgsTransactionGroup::onLayerDeleted()
91 {
92  mLayers.remove( static_cast<QgsVectorLayer *>( sender() ) );
93 }
94 
95 void QgsTransactionGroup::onCommitChanges()
96 {
97  if ( mEditingStopping )
98  return;
99 
100  mEditingStopping = true;
101 
102  QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
103 
104  QString errMsg;
105  if ( mTransaction->commit( errMsg ) )
106  {
107  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
108  {
109  if ( layer != sender() )
110  layer->commitChanges();
111  }
112 
113  disableTransaction();
114  }
115  else
116  {
117  emit commitError( errMsg );
118  // Restart editing the calling layer in the next event loop cycle
119  QTimer::singleShot( 0, triggeringLayer, SLOT( startEditing() ) );
120  }
121  mEditingStopping = false;
122 }
123 
124 void QgsTransactionGroup::onRollback()
125 {
126  if ( mEditingStopping )
127  return;
128 
129  mEditingStopping = true;
130 
131  QgsVectorLayer *triggeringLayer = qobject_cast<QgsVectorLayer *>( sender() );
132 
133  QString errMsg;
134  if ( mTransaction->rollback( errMsg ) )
135  {
136  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
137  {
138  if ( layer != triggeringLayer )
139  layer->rollBack();
140  }
141  disableTransaction();
142  }
143  else
144  {
145  // Restart editing the calling layer in the next event loop cycle
146  QTimer::singleShot( 0, triggeringLayer, SLOT( startEditing() ) );
147  }
148  mEditingStopping = false;
149 }
150 
151 void QgsTransactionGroup::disableTransaction()
152 {
153  mTransaction.reset();
154 
155  Q_FOREACH ( QgsVectorLayer *layer, mLayers )
156  {
157  disconnect( layer, &QgsVectorLayer::beforeCommitChanges, this, &QgsTransactionGroup::onCommitChanges );
158  disconnect( layer, &QgsVectorLayer::beforeRollBack, this, &QgsTransactionGroup::onRollback );
159  }
160 }
161 
163 {
164  return mProviderKey;
165 }
166 
168 {
169  return mLayers.isEmpty();
170 }
171 
173 {
174  return mConnString;
175 }
static QgsTransaction * create(const QString &connString, const QString &providerKey)
Create a transaction for the specified connection string connString and provider with providerKey...
void beforeRollBack()
Is emitted, before changes are rolled back.
bool commitChanges()
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
bool startEditing()
Makes the layer editable.
QSet< QgsVectorLayer * > layers() const
Get the set of layers currently managed by this transaction group.
void beforeCommitChanges()
Is emitted, before changes are committed to the data provider.
QString providerKey() const
Return the provider key used by this transaction group.
bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits.
void beforeEditingStarted()
Is emitted, before editing on this layer is started.
bool addLayer(QgsVectorLayer *layer)
Add a layer to this transaction group.
static bool supportsTransaction(const QgsVectorLayer *layer)
Checks if the provider of a given layer supports transactions.
QgsTransactionGroup(QObject *parent=nullptr)
Constructor for QgsTransactionGroup.
QString source() const
Returns the source for the layer.
virtual bool isModified() const
Returns true if the provider has been modified since the last commit.
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 providerType() const
Return the provider type for this layer.
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
Represents a vector layer which manages a vector based data sets.
QString connString() const
Return the connection string used by this transaction group.
bool modified() const
Returns true if any of the layers in this group reports a modification.