QGIS API Documentation  2.12.0-Lyon
qgstransaction.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgstransaction.cpp
3  ------------------
4  begin : May 5, 2014
5  copyright : (C) 2014 by Marco Hugentobler
6  email : marco dot hugentobler at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <QLibrary>
19 
20 #include "qgstransaction.h"
21 #include "qgsdatasourceuri.h"
22 #include "qgsmaplayerregistry.h"
23 #include "qgsproviderregistry.h"
24 #include "qgsvectordataprovider.h"
25 #include "qgsvectorlayer.h"
26 
27 typedef QgsTransaction* createTransaction_t( const QString& connString );
28 
29 QgsTransaction* QgsTransaction::create( const QString& connString, const QString& providerKey )
30 {
31 
33  if ( !lib )
34  {
35  return 0;
36  }
37 
38  createTransaction_t* createTransaction = ( createTransaction_t* ) cast_to_fptr( lib->resolve( "createTransaction" ) );
39  if ( !createTransaction )
40  {
41  return 0;
42  }
43 
44  QgsTransaction* ts = createTransaction( connString );
45 
46  delete lib;
47 
48  return ts;
49 }
50 
52 {
53  if ( layerIds.isEmpty() )
54  {
55  return 0;
56  }
57 
58  QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerIds.first() ) );
59  if ( !layer )
60  {
61  return 0;
62  }
63 
64  QString connStr = QgsDataSourceURI( layer->source() ).connectionInfo();
65  QString providerKey = layer->dataProvider()->name();
66  QgsTransaction* ts = QgsTransaction::create( connStr, providerKey );
67  if ( !ts )
68  {
69  return 0;
70  }
71 
72  Q_FOREACH ( const QString& layerId, layerIds )
73  {
74  if ( !ts->addLayer( layerId ) )
75  {
76  delete ts;
77  return 0;
78  }
79  }
80  return ts;
81 }
82 
83 
85  : mConnString( connString ), mTransactionActive( false )
86 {
87 }
88 
90 {
91  setLayerTransactionIds( 0 );
92 }
93 
94 bool QgsTransaction::addLayer( const QString& layerId )
95 {
96  if ( mTransactionActive )
97  {
98  return false;
99  }
100 
101  QgsVectorLayer* layer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerId ) );
102  if ( !layer )
103  {
104  return false;
105  }
106 
107  if ( layer->isEditable() )
108  {
109  return false;
110  }
111 
112  //test if provider supports transactions
113  if ( !layer->dataProvider() || ( layer->dataProvider()->capabilities() & QgsVectorDataProvider::TransactionSupport ) == 0 )
114  {
115  return false;
116  }
117 
118  if ( layer->dataProvider()->transaction() != 0 )
119  {
120  return false;
121  }
122 
123  //connection string not compatible
124  if ( QgsDataSourceURI( layer->source() ).connectionInfo() != mConnString )
125  {
126  return false;
127  }
128 
129  mLayers.insert( layerId );
130  return true;
131 }
132 
133 bool QgsTransaction::begin( QString& errorMsg, int statementTimeout )
134 {
135  if ( mTransactionActive )
136  {
137  return false;
138  }
139 
140  //Set all layers to direct edit mode
141  if ( !beginTransaction( errorMsg, statementTimeout ) )
142  {
143  return false;
144  }
145 
146  setLayerTransactionIds( this );
147  mTransactionActive = true;
148  return true;
149 }
150 
152 {
153  if ( !mTransactionActive )
154  {
155  return false;
156  }
157 
158  Q_FOREACH ( const QString& layerid, mLayers )
159  {
161  if ( !l || l->isEditable() )
162  {
163  return false;
164  }
165  }
166 
167  if ( !commitTransaction( errorMsg ) )
168  {
169  return false;
170  }
171 
172  setLayerTransactionIds( 0 );
173  mTransactionActive = false;
174  return true;
175 }
176 
178 {
179  if ( !mTransactionActive )
180  {
181  return false;
182  }
183 
184  Q_FOREACH ( const QString& layerid, mLayers )
185  {
187  if ( !l || l->isEditable() )
188  {
189  return false;
190  }
191  }
192 
193  if ( !rollbackTransaction( errorMsg ) )
194  {
195  return false;
196  }
197 
198  setLayerTransactionIds( 0 );
199  mTransactionActive = false;
200  return true;
201 }
202 
203 void QgsTransaction::setLayerTransactionIds( QgsTransaction* transaction )
204 {
205  Q_FOREACH ( const QString& layerid, mLayers )
206  {
207  QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( layerid ) );
208  if ( vl && vl->dataProvider() )
209  {
210  vl->dataProvider()->setTransaction( transaction );
211  }
212  }
213 }
virtual bool isEditable() const
True if the layer can be edited.
static QgsTransaction * create(const QString &connString, const QString &providerKey)
Creates a transaction for the specified connection string and provider.
static QgsProviderRegistry * instance(const QString &pluginPath=QString::null)
Means of accessing canonical single instance.
Base class for all map layer types.
Definition: qgsmaplayer.h:49
virtual ~QgsTransaction()
QString mConnString
virtual QgsTransaction * transaction() const
Returns the transaction this data provider is included in, if any.
QgsTransaction * createTransaction_t(const QString &connString)
const_iterator insert(const T &value)
virtual bool isEditable() const override
Returns true if the provider is in editing mode.
bool commit(QString &errorMsg)
Commit transaction.
virtual QString name() const =0
Return a provider name.
QgsMapLayer * mapLayer(const QString &theLayerId)
Retrieve a pointer to a loaded layer by id.
const QString & source() const
Returns the source for the layer.
bool addLayer(const QString &layerId)
Add layer to the transaction.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
bool isEmpty() const
T & first()
Class for storing the component parts of a PostgreSQL/RDBMS datasource URI.
QLibrary * providerLibrary(const QString &providerKey) const
QgsTransaction(const QString &connString)
static QgsMapLayerRegistry * instance()
Returns the instance pointer, creating the object on the first call.
void * resolve(const char *symbol)
This class allows to include a set of layers in a database-side transaction, provided the layer data ...
bool rollback(QString &errorMsg)
Roll back transaction.
void(*)() cast_to_fptr(void *p)
Definition: qgis.h:241
QgsVectorDataProvider * dataProvider()
Returns the data provider.
Represents a vector layer which manages a vector based data sets.
bool begin(QString &errorMsg, int statementTimeout=20)
Begin transaction The statement timeout, in seconds, specifies how long an sql statement is allowed t...