mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
moved the responsability for not-commited features to qgsvectorlayer. Because of this, it is now possible to treat not-commited features like commited ones. Vectordataproviders now only need to implement 'addFeatures','deleteFeatures', 'supportsFeatureAddition' and 'supportsFeatureDeletion' if they support feature addition or deletion
git-svn-id: http://svn.osgeo.org/qgis/trunk@2258 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
a5450673ee
commit
20d4d60ce0
@ -448,7 +448,7 @@ QgsFeature *QgsDelimitedTextProvider::getNextFeature(bool fetchAttributes)
|
||||
return f;
|
||||
}
|
||||
|
||||
QgsFeature * QgsDelimitedTextProvider::getNextFeature(std::list<int>& attlist, bool getnotcommited)
|
||||
QgsFeature * QgsDelimitedTextProvider::getNextFeature(std::list<int>& attlist)
|
||||
{
|
||||
// We must manually check each point to see if it is within the
|
||||
// selection rectangle
|
||||
@ -755,35 +755,6 @@ bool QgsDelimitedTextProvider::isValid(){
|
||||
return mValid;
|
||||
}
|
||||
|
||||
bool QgsDelimitedTextProvider::startEditing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsDelimitedTextProvider::stopEditing()
|
||||
{
|
||||
}
|
||||
|
||||
bool QgsDelimitedTextProvider::commitChanges()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsDelimitedTextProvider::rollBack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsDelimitedTextProvider::addFeature(QgsFeature* f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsDelimitedTextProvider::deleteFeature(int id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the point is within the selection rectangle
|
||||
*/
|
||||
|
@ -48,7 +48,8 @@ public:
|
||||
*/
|
||||
QgsFeature * getNextFeature(bool fetchAttributes=false);
|
||||
bool getNextFeature(QgsFeature &feature, bool fetchAttributes=false);
|
||||
QgsFeature * getNextFeature(std::list<int>& attlist, bool getnotcommited=false);
|
||||
|
||||
QgsFeature * getNextFeature(std::list<int>& attlist);
|
||||
|
||||
/** Get the feature type. This corresponds to
|
||||
WKBPoint,
|
||||
@ -129,44 +130,6 @@ public:
|
||||
*/
|
||||
bool isValid();
|
||||
|
||||
/**
|
||||
Enables editing capabilities of the provider (if supported)
|
||||
@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing();
|
||||
|
||||
/**
|
||||
Disables the editing capabilities of the provider
|
||||
*/
|
||||
virtual void stopEditing();
|
||||
|
||||
/**
|
||||
Commits changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool commitChanges();
|
||||
|
||||
/**
|
||||
Discards changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool rollBack();
|
||||
|
||||
/**Returns true if the provider is in editing mode*/
|
||||
virtual bool isEditable() const {return false;}
|
||||
|
||||
/**Returns true if the provider has been modified since the last commit*/
|
||||
virtual bool isModified() const {return false;}
|
||||
|
||||
/**Adds a feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool addFeature(QgsFeature* f);
|
||||
|
||||
/**Deletes a feature
|
||||
@param id the number of the feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool deleteFeature(int id);
|
||||
|
||||
/**
|
||||
* Check to see if the point is withn the selection
|
||||
* rectangle
|
||||
|
@ -143,10 +143,10 @@ QgsFeature *QgsGPXProvider::getNextFeature(bool fetchAttributes) {
|
||||
QgsFeature* feature = new QgsFeature(-1);
|
||||
bool success;
|
||||
if (fetchAttributes)
|
||||
success = getNextFeature(feature, mAllAttributes, false);
|
||||
success = getNextFeature(feature, mAllAttributes);
|
||||
else {
|
||||
std::list<int> emptyList;
|
||||
success = getNextFeature(feature, emptyList, false);
|
||||
success = getNextFeature(feature, emptyList);
|
||||
}
|
||||
if (success)
|
||||
return feature;
|
||||
@ -155,10 +155,9 @@ QgsFeature *QgsGPXProvider::getNextFeature(bool fetchAttributes) {
|
||||
}
|
||||
|
||||
|
||||
QgsFeature * QgsGPXProvider::getNextFeature(std::list<int>& attlist,
|
||||
bool getnotcommited) {
|
||||
QgsFeature * QgsGPXProvider::getNextFeature(std::list<int>& attlist) {
|
||||
QgsFeature* feature = new QgsFeature(-1);
|
||||
bool success = getNextFeature(feature, attlist, getnotcommited);
|
||||
bool success = getNextFeature(feature, attlist);
|
||||
if (success)
|
||||
return feature;
|
||||
delete feature;
|
||||
@ -167,11 +166,10 @@ QgsFeature * QgsGPXProvider::getNextFeature(std::list<int>& attlist,
|
||||
|
||||
|
||||
bool QgsGPXProvider::getNextFeature(QgsFeature* feature,
|
||||
std::list<int>& attlist,
|
||||
bool getnotcommitted) {
|
||||
bool result = false;
|
||||
std::list<int>& attlist) {
|
||||
bool result = false;
|
||||
|
||||
std::list<int>::const_iterator iter;
|
||||
/*std::list<int>::const_iterator iter;
|
||||
|
||||
if (mFeatureType == WaypointType) {
|
||||
// go through the list of waypoints and return the first one that is in
|
||||
@ -371,7 +369,7 @@ bool QgsGPXProvider::getNextFeature(QgsFeature* feature,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -551,214 +549,7 @@ bool QgsGPXProvider::isValid(){
|
||||
return mValid;
|
||||
}
|
||||
|
||||
bool QgsGPXProvider::startEditing() {
|
||||
mEditable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void QgsGPXProvider::stopEditing() {
|
||||
mEditable = false;
|
||||
}
|
||||
|
||||
|
||||
bool QgsGPXProvider::commitChanges() {
|
||||
for (int i = 0; i < mAddedFeatures.size(); ++i) {
|
||||
if (mFeatureType == WaypointType)
|
||||
data->addWaypoint(*dynamic_cast<Waypoint*>(mAddedFeatures[i]));
|
||||
else if (mFeatureType == RouteType)
|
||||
data->addRoute(*dynamic_cast<Route*>(mAddedFeatures[i]));
|
||||
else if (mFeatureType == TrackType)
|
||||
data->addTrack(*dynamic_cast<Track*>(mAddedFeatures[i]));
|
||||
|
||||
delete mAddedFeatures[i];
|
||||
}
|
||||
mAddedFeatures.clear();
|
||||
|
||||
// write back to file
|
||||
QDomDocument qdd;
|
||||
data->fillDom(qdd);
|
||||
QFile file(mFileName);
|
||||
if (file.open(IO_WriteOnly)) {
|
||||
QTextStream stream(&file);
|
||||
stream<<qdd.toString();
|
||||
}
|
||||
else {
|
||||
std::cerr<<"Could not write \""<<mFileName<<"\""<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool QgsGPXProvider::rollBack() {
|
||||
for (int i = 0; i < mAddedFeatures.size(); ++i)
|
||||
delete mAddedFeatures[i];
|
||||
mAddedFeatures.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool QgsGPXProvider::addFeature(QgsFeature* f) {
|
||||
if (!mEditable)
|
||||
return false;
|
||||
|
||||
GPSObject* obj = NULL;
|
||||
|
||||
unsigned char* geo = f->getGeometry();
|
||||
int id;
|
||||
QGis::WKBTYPE ftype;
|
||||
memcpy(&ftype, (geo + 1), sizeof(int));
|
||||
|
||||
/* Do different things for different geometry types:
|
||||
WKBPoint -> add waypoint if this is a waypoint layer
|
||||
WKBLineString -> add track if this is a track layer, route if this is a
|
||||
route layer
|
||||
WKBPolygon and the WKBMulti types are not supported because they don't
|
||||
make sense for GPX files. */
|
||||
switch(ftype) {
|
||||
|
||||
// the user is trying to add a point feature
|
||||
case QGis::WKBPoint: {
|
||||
if (mFeatureType != WaypointType) {
|
||||
std::cerr<<"Tried to write point feature to non-point layer!"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
mAddedFeatures.push_back(new Waypoint);
|
||||
Waypoint* wpt(dynamic_cast<Waypoint*>(mAddedFeatures[mAddedFeatures.size() - 1]));
|
||||
wpt->lat = *((double*)(geo + 5 + sizeof(double)));
|
||||
wpt->lon = *((double*)(geo + 5));
|
||||
|
||||
// parse waypoint-specific attributes
|
||||
std::vector<QgsFeatureAttribute>::const_iterator iter;
|
||||
for (iter = f->attributeMap().begin();
|
||||
iter != f->attributeMap().end(); ++iter) {
|
||||
if (iter->fieldName() == "ele") {
|
||||
bool b;
|
||||
double d = iter->fieldValue().toDouble(&b);
|
||||
if (b)
|
||||
wpt->ele = d;
|
||||
else
|
||||
wpt->ele = -std::numeric_limits<double>::max();
|
||||
}
|
||||
else if (iter->fieldName() == "sym")
|
||||
wpt->sym = iter->fieldValue();
|
||||
}
|
||||
|
||||
obj = wpt;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// the user is trying to add a line feature
|
||||
case QGis::WKBLineString: {
|
||||
if (mFeatureType == WaypointType) {
|
||||
std::cerr<<"Tried to write line feature to point layer!"<<std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// get the number of points
|
||||
int length;
|
||||
memcpy(&length,f->getGeometry()+1+sizeof(int),sizeof(int));
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("length: "+QString::number(length));
|
||||
#endif
|
||||
|
||||
GPSExtended* ext = NULL;
|
||||
|
||||
// add route
|
||||
if (mFeatureType == RouteType) {
|
||||
mAddedFeatures.push_back(new Route);
|
||||
Route* rte(dynamic_cast<Route*>(mAddedFeatures[mAddedFeatures.size() - 1]));
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Routepoint rpt;
|
||||
std::memcpy(&rpt.lon, geo + 9 + 16 * i, sizeof(double));
|
||||
std::memcpy(&rpt.lat, geo + 9 + 16 * i + 8, sizeof(double));
|
||||
|
||||
// update the route bounds
|
||||
rte->xMin = (rte->xMin < rpt.lon ? rte->xMin : rpt.lon);
|
||||
rte->xMax = (rte->xMax > rpt.lon ? rte->xMax : rpt.lon);
|
||||
rte->yMin = (rte->yMin < rpt.lat ? rte->yMin : rpt.lat);
|
||||
rte->yMax = (rte->yMax > rpt.lat ? rte->yMax : rpt.lat);
|
||||
|
||||
rte->points.push_back(rpt);
|
||||
}
|
||||
|
||||
ext = rte;
|
||||
}
|
||||
|
||||
// add track
|
||||
else if (mFeatureType == TrackType) {
|
||||
mAddedFeatures.push_back(new Track);
|
||||
Track* trk(dynamic_cast<Track*>(mAddedFeatures[mAddedFeatures.size() - 1]));
|
||||
TrackSegment trkSeg;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
Trackpoint tpt;
|
||||
std::memcpy(&tpt.lon, geo + 9 + 16 * i, sizeof(double));
|
||||
std::memcpy(&tpt.lat, geo + 9 + 16 * i + 8, sizeof(double));
|
||||
|
||||
// update the track bounds
|
||||
trk->xMin = (trk->xMin < tpt.lon ? trk->xMin : tpt.lon);
|
||||
trk->xMax = (trk->xMax > tpt.lon ? trk->xMax : tpt.lon);
|
||||
trk->yMin = (trk->yMin < tpt.lat ? trk->yMin : tpt.lat);
|
||||
trk->yMax = (trk->yMax > tpt.lat ? trk->yMax : tpt.lat);
|
||||
|
||||
trkSeg.points.push_back(tpt);
|
||||
}
|
||||
trk->segments.push_back(trkSeg);
|
||||
|
||||
ext = trk;
|
||||
}
|
||||
|
||||
// parse GPSExtended-specific attributes
|
||||
std::vector<QgsFeatureAttribute>::const_iterator iter;
|
||||
for (iter = f->attributeMap().begin();
|
||||
iter != f->attributeMap().end(); ++iter) {
|
||||
if (iter->fieldName() == "number") {
|
||||
bool b;
|
||||
int n = iter->fieldValue().toInt(&b);
|
||||
if (b)
|
||||
ext->number = n;
|
||||
else
|
||||
ext->number = std::numeric_limits<int>::max();
|
||||
}
|
||||
}
|
||||
|
||||
obj = ext;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// unsupported geometry - something's wrong
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// parse common attributes
|
||||
std::vector<QgsFeatureAttribute>::const_iterator iter;
|
||||
for (iter = f->attributeMap().begin();
|
||||
iter != f->attributeMap().end(); ++iter) {
|
||||
if (iter->fieldName() == "name")
|
||||
obj->name = iter->fieldValue();
|
||||
else if (iter->fieldName() == "cmt")
|
||||
obj->cmt = iter->fieldValue();
|
||||
else if (iter->fieldName() == "desc")
|
||||
obj->desc = iter->fieldValue();
|
||||
else if (iter->fieldName() == "src")
|
||||
obj->src = iter->fieldValue();
|
||||
else if (iter->fieldName() == "url")
|
||||
obj->url = iter->fieldValue();
|
||||
else if (iter->fieldName() == "urlname")
|
||||
obj->urlname = iter->fieldValue();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool QgsGPXProvider::deleteFeature(int id) {
|
||||
bool QgsGPXProvider::addFeatures(std::list<QgsFeature*> flist) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
*/
|
||||
QgsFeature * getNextFeature(bool fetchAttributes=false);
|
||||
bool getNextFeature(QgsFeature &feature, bool fetchAttributes=false);
|
||||
QgsFeature * getNextFeature(std::list<int>& attlist, bool getnotcommited=false);
|
||||
QgsFeature * getNextFeature(std::list<int>& attlist);
|
||||
|
||||
/** Get the feature type. This corresponds to
|
||||
WKBPoint,
|
||||
@ -129,29 +129,6 @@ public:
|
||||
*/
|
||||
bool isValid();
|
||||
|
||||
/**
|
||||
Enables editing capabilities of the provider (if supported)
|
||||
@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing();
|
||||
|
||||
/**
|
||||
Disables the editing capabilities of the provider
|
||||
*/
|
||||
virtual void stopEditing();
|
||||
|
||||
/**
|
||||
Commits changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool commitChanges();
|
||||
|
||||
/**
|
||||
Discards changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool rollBack();
|
||||
|
||||
/**Returns true if the provider is in editing mode*/
|
||||
virtual bool isEditable() const { return mEditable; }
|
||||
|
||||
@ -160,12 +137,7 @@ public:
|
||||
|
||||
/**Adds a feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool addFeature(QgsFeature* f);
|
||||
|
||||
/**Deletes a feature
|
||||
@param id the number of the feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool deleteFeature(int id);
|
||||
bool addFeatures(std::list<QgsFeature*> flist);
|
||||
|
||||
/**Returns the default value for attribute @c attr for feature @c f. */
|
||||
QString getDefaultValue(const QString& attr, QgsFeature* f);
|
||||
@ -178,12 +150,13 @@ public:
|
||||
* @return True if point is within the rectangle
|
||||
*/
|
||||
bool boundsCheck(double x, double y);
|
||||
|
||||
bool supportsFeatureAddition(){return true;}
|
||||
|
||||
private:
|
||||
|
||||
/** Internal function used by the other getNextFeature() functions. */
|
||||
bool getNextFeature(QgsFeature* feature, std::list<int>& attlist,
|
||||
bool getnotcommitted);
|
||||
bool getNextFeature(QgsFeature* feature, std::list<int>& attlist);
|
||||
|
||||
bool mEditable;
|
||||
std::vector<GPSObject*> mAddedFeatures;
|
||||
|
@ -326,7 +326,7 @@ QgsFeature *QgsGrassProvider::getNextFeature(bool fetchAttributes)
|
||||
return ( getNextFeature(attlist) );
|
||||
}
|
||||
|
||||
QgsFeature* QgsGrassProvider::getNextFeature(std::list<int>& attlist, bool getnotcommited)
|
||||
QgsFeature* QgsGrassProvider::getNextFeature(std::list<int>& attlist)
|
||||
{
|
||||
int cat, type, id, idx;
|
||||
unsigned char *wkb;
|
||||
@ -649,41 +649,6 @@ bool QgsGrassProvider::isValid(){
|
||||
return mValid;
|
||||
}
|
||||
|
||||
bool QgsGrassProvider::startEditing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsGrassProvider::stopEditing()
|
||||
{
|
||||
}
|
||||
|
||||
bool QgsGrassProvider::commitChanges()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsGrassProvider::rollBack()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsGrassProvider::addFeature(QgsFeature* f)
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "QgsGrassProvider::addFeature()" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsGrassProvider::deleteFeature(int id)
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "QgsGrassProvider::deleteFeature()" << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// Compare categories in GATT
|
||||
static int cmpAtt ( const void *a, const void *b ) {
|
||||
|
@ -108,7 +108,7 @@ public:
|
||||
*/
|
||||
QgsFeature * getNextFeature(bool fetchAttributes=false);
|
||||
bool getNextFeature(QgsFeature &feature, bool fetchAttributes=false);
|
||||
QgsFeature* getNextFeature(std::list<int>& attlist, bool getnotcommited=false);
|
||||
QgsFeature* getNextFeature(std::list<int>& attlist);
|
||||
|
||||
/**
|
||||
* Get the feature type as defined in WKBTYPE (qgis.h).
|
||||
@ -408,44 +408,6 @@ public:
|
||||
/** Get maximum category for field index */
|
||||
int cidxGetMaxCat ( int idx );
|
||||
|
||||
/**
|
||||
Enables editing capabilities of the provider (if supported)
|
||||
@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing();
|
||||
|
||||
/**
|
||||
Disables the editing capabilities of the provider
|
||||
*/
|
||||
virtual void stopEditing();
|
||||
|
||||
/**
|
||||
Commits changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool commitChanges();
|
||||
|
||||
/**
|
||||
Discards changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool rollBack();
|
||||
|
||||
/**Returns true if the provider is in editing mode*/
|
||||
virtual bool isEditable() const {return true;}
|
||||
|
||||
/**Returns true if the provider has been modified since the last commit*/
|
||||
virtual bool isModified() const {return false;}
|
||||
|
||||
/**Adds a feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool addFeature(QgsFeature* f);
|
||||
|
||||
/**Deletes a feature
|
||||
@param id the number of the feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool deleteFeature(int id);
|
||||
|
||||
private:
|
||||
enum ENDIAN {
|
||||
NDR = 1,
|
||||
|
@ -120,13 +120,6 @@ QgsShapeFileProvider::~QgsShapeFileProvider()
|
||||
}
|
||||
delete[] minmaxcache;
|
||||
|
||||
//delete not commited features
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
mAddedFeatures.clear();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -360,7 +353,7 @@ QgsFeature *QgsShapeFileProvider::getNextFeature(bool fetchAttributes)
|
||||
return f;
|
||||
}
|
||||
|
||||
QgsFeature *QgsShapeFileProvider::getNextFeature(std::list<int>& attlist, bool getnotcommited)
|
||||
QgsFeature *QgsShapeFileProvider::getNextFeature(std::list<int>& attlist)
|
||||
{
|
||||
QgsFeature *f = 0;
|
||||
if(valid)
|
||||
@ -408,26 +401,11 @@ QgsFeature *QgsShapeFileProvider::getNextFeature(std::list<int>& attlist, bool g
|
||||
}
|
||||
else
|
||||
{
|
||||
if(getnotcommited&&mAddedFeatures.size()>0&&mAddedFeaturesIt!=mAddedFeatures.end())
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("accessing feature in the cache");
|
||||
#endif //QGISDEBUG
|
||||
QgsFeature* addedfeature=*mAddedFeaturesIt;
|
||||
++mAddedFeaturesIt;
|
||||
//copy the feature because it will be deleted in QgsVectorLayer::draw()
|
||||
QgsFeature* returnf=new QgsFeature(*addedfeature);
|
||||
return returnf;
|
||||
}
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "Feature is null\n";
|
||||
#endif
|
||||
// probably should reset reading here
|
||||
ogrLayer->ResetReading();
|
||||
if(!mAddedFeatures.empty())
|
||||
{
|
||||
mAddedFeaturesIt=mAddedFeatures.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -616,10 +594,6 @@ void QgsShapeFileProvider::reset()
|
||||
{
|
||||
ogrLayer->SetSpatialFilter(0);
|
||||
ogrLayer->ResetReading();
|
||||
if(!mAddedFeatures.empty())
|
||||
{
|
||||
mAddedFeaturesIt=mAddedFeatures.begin();
|
||||
}
|
||||
}
|
||||
|
||||
QString QgsShapeFileProvider::minValue(int position)
|
||||
@ -687,17 +661,11 @@ bool QgsShapeFileProvider::isValid()
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool QgsShapeFileProvider::startEditing()
|
||||
{
|
||||
mEditable=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsShapeFileProvider::commitFeature(QgsFeature* f)
|
||||
bool QgsShapeFileProvider::addFeature(QgsFeature* f)
|
||||
{
|
||||
qWarning("try to commit a feature");
|
||||
if(mEditable)
|
||||
{
|
||||
|
||||
|
||||
bool returnValue = true;
|
||||
OGRFeatureDefn* fdef=ogrLayer->GetLayerDefn();
|
||||
OGRFeature* feature=new OGRFeature(fdef);
|
||||
@ -839,39 +807,20 @@ bool QgsShapeFileProvider::commitFeature(QgsFeature* f)
|
||||
++numberFeatures;
|
||||
delete feature;
|
||||
return returnValue;
|
||||
}
|
||||
else//layer not editable
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*bool QgsShapeFileProvider::deleteFeature(int id)
|
||||
bool QgsShapeFileProvider::addFeatures(std::list<QgsFeature*> flist)
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
int test=ogrLayer->TestCapability("OLCDeleteFeature");
|
||||
if(!test)
|
||||
bool returnvalue=true;
|
||||
for(std::list<QgsFeature*>::iterator it=flist.begin();it!=flist.end();++it)
|
||||
{
|
||||
qWarning("no support for deletion of features");
|
||||
if(!addFeature(*it))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
OGRErr message=ogrLayer->DeleteFeature(id);
|
||||
switch(message)
|
||||
{
|
||||
case OGRERR_UNSUPPORTED_OPERATION:
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("driver does not support deletion");
|
||||
#endif
|
||||
return false;
|
||||
case OGRERR_NONE:
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("deletion successfull");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}*/
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class factory to return a pointer to a newly created
|
||||
|
@ -49,7 +49,7 @@ class QgsShapeFileProvider:public QgsVectorDataProvider
|
||||
*@param attlist a list containing the indexes of the attribute fields to copy
|
||||
*@param getnotcommited flag indicating if not commited features should be returned
|
||||
*/
|
||||
QgsFeature *getNextFeature(std::list<int>& attlist, bool getnotcommited=false);
|
||||
QgsFeature *getNextFeature(std::list<int>& attlist);
|
||||
/**
|
||||
* Get the next feature resutling from a select operation
|
||||
* @return True if the feature was read. This does not indicate
|
||||
@ -139,14 +139,10 @@ class QgsShapeFileProvider:public QgsVectorDataProvider
|
||||
*/
|
||||
bool isValid();
|
||||
|
||||
/**
|
||||
*Enables editing capabilities of the provider (if supported)
|
||||
*@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing();
|
||||
/**Writes a list of features to the file*/
|
||||
bool addFeatures(std::list<QgsFeature*> flist);
|
||||
|
||||
protected:
|
||||
bool commitFeature(QgsFeature* f);
|
||||
bool supportsFeatureAddition(){return true;}
|
||||
|
||||
private:
|
||||
unsigned char *getGeometryPointer(OGRFeature * fet);
|
||||
@ -173,6 +169,6 @@ class QgsShapeFileProvider:public QgsVectorDataProvider
|
||||
void fillMinMaxCash();
|
||||
//! Selection rectangle
|
||||
OGRPolygon * mSelectionRectangle;
|
||||
|
||||
|
||||
/**Adds one feature*/
|
||||
bool addFeature(QgsFeature* f);
|
||||
};
|
||||
|
@ -456,7 +456,7 @@ QgsFeature *QgsPostgresProvider::getNextFeature(bool fetchAttributes)
|
||||
return f;
|
||||
}
|
||||
|
||||
QgsFeature* QgsPostgresProvider::getNextFeature(std::list<int>& attlist, bool getnotcommited)
|
||||
QgsFeature* QgsPostgresProvider::getNextFeature(std::list<int>& attlist)
|
||||
{
|
||||
QgsFeature *f = 0;
|
||||
if (valid)
|
||||
@ -465,36 +465,16 @@ QgsFeature* QgsPostgresProvider::getNextFeature(std::list<int>& attlist, bool ge
|
||||
queryResult = PQexec(connection, (const char *)fetch);
|
||||
if(PQntuples(queryResult) == 0)
|
||||
{
|
||||
|
||||
if(getnotcommited&&mAddedFeatures.size()>0&&mAddedFeaturesIt!=mAddedFeatures.end())
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("accessing feature in the cache");
|
||||
#endif //QGISDEBUG
|
||||
QgsFeature* addedfeature=*mAddedFeaturesIt;
|
||||
++mAddedFeaturesIt;
|
||||
//copy the feature because it will be deleted in QgsVectorLayer::draw()
|
||||
QgsFeature* returnf=new QgsFeature(*addedfeature);
|
||||
return returnf;
|
||||
}
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "Feature is null\n";
|
||||
#endif
|
||||
if(!mAddedFeatures.empty())
|
||||
{
|
||||
mAddedFeaturesIt=mAddedFeatures.begin();
|
||||
}
|
||||
|
||||
PQexec(connection, "end work");
|
||||
ready = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int *noid;
|
||||
bool cont=false;//flag for repeating the loop in case of deleted features
|
||||
while(cont==false)
|
||||
{
|
||||
int oid = *(int *)PQgetvalue(queryResult,0,PQfnumber(queryResult,primaryKey));
|
||||
int oid = *(int *)PQgetvalue(queryResult,0,PQfnumber(queryResult,primaryKey));
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "Primary key type is " << primaryKeyType << std::endl;
|
||||
#endif
|
||||
@ -525,23 +505,8 @@ QgsFeature* QgsPostgresProvider::getNextFeature(std::list<int>& attlist, bool ge
|
||||
noid = &oid;
|
||||
}
|
||||
}
|
||||
//block feature if oid is contained in mDeletedFeatures
|
||||
std::set<int>::iterator iter=mDeletedFeatures.find(*noid);
|
||||
if(iter==mDeletedFeatures.end())
|
||||
{
|
||||
cont=true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we hit deleted feature, fetch the next
|
||||
fetch = "fetch forward 1 from qgisf";
|
||||
queryResult = PQexec(connection, (const char *)fetch);
|
||||
if(PQntuples(queryResult) == 0)
|
||||
{
|
||||
cont=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int returnedLength = PQgetlength(queryResult,0, PQfnumber(queryResult,"qgs_feature_geometry"));
|
||||
if(returnedLength > 0)
|
||||
@ -934,13 +899,7 @@ bool QgsPostgresProvider::isValid(){
|
||||
return valid;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::startEditing()
|
||||
{
|
||||
mEditable=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::commitFeature(QgsFeature* f)
|
||||
bool QgsPostgresProvider::addFeature(QgsFeature* f)
|
||||
{
|
||||
if(f)
|
||||
{
|
||||
@ -1044,13 +1003,6 @@ QString QgsPostgresProvider::getDefaultValue(const QString& attr, QgsFeature* f)
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::deleteFeature(int id)
|
||||
{
|
||||
mDeletedFeatures.insert(id);
|
||||
mModified=true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::eraseFeature(int id)
|
||||
{
|
||||
QString sql("DELETE FROM "+tableName+" WHERE "+primaryKey+" = "+QString::number(id));
|
||||
#ifdef QGISDEBUG
|
||||
@ -1111,6 +1063,32 @@ QString QgsPostgresProvider::postgisVersion(PGconn *connection){
|
||||
return postgisVersionInfo;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::addFeatures(std::list<QgsFeature*> flist)
|
||||
{
|
||||
bool returnvalue=true;
|
||||
for(std::list<QgsFeature*>::iterator it=flist.begin();it!=flist.end();++it)
|
||||
{
|
||||
if(!addFeature(*it))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
bool QgsPostgresProvider::deleteFeatures(std::list<int> id)
|
||||
{
|
||||
bool returnvalue=true;
|
||||
for(std::list<int>::iterator it=id.begin();it!=id.end();++it)
|
||||
{
|
||||
if(!deleteFeature(*it))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class factory to return a pointer to a newly created
|
||||
* QgsPostgresProvider object
|
||||
|
@ -61,7 +61,7 @@ class QgsPostgresProvider:public QgsVectorDataProvider
|
||||
*@param attlist a list containing the indexes of the attribute fields to copy
|
||||
*@param getnotcommited flag indicating if not commited features should be returned
|
||||
*/
|
||||
QgsFeature* getNextFeature(std::list<int>& attlist, bool getnotcommited=false);
|
||||
QgsFeature* getNextFeature(std::list<int>& attlist);
|
||||
/** Get the feature type. This corresponds to
|
||||
* WKBPoint,
|
||||
* WKBLineString,
|
||||
@ -162,28 +162,22 @@ class QgsPostgresProvider:public QgsVectorDataProvider
|
||||
//! get status of PROJ4 capability
|
||||
bool hasPROJ(PGconn *);
|
||||
|
||||
/**
|
||||
*Enables editing capabilities of the provider (if supported)
|
||||
*@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing();
|
||||
|
||||
/**Returns the default value for attribute @c attr for feature @c f. */
|
||||
QString getDefaultValue(const QString& attr, QgsFeature* f);
|
||||
|
||||
/**Deletes a feature
|
||||
@param id the number of the feature
|
||||
/**Adds a list of features
|
||||
@return true in case of success and false in case of failure*/
|
||||
virtual bool deleteFeature(int id);
|
||||
bool addFeatures(std::list<QgsFeature*> flist);
|
||||
|
||||
protected:
|
||||
/**Commits a feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool commitFeature(QgsFeature* f);
|
||||
/**Commits the deletion of a feature
|
||||
@return true in case of success and false in case of faiure*/
|
||||
bool eraseFeature(int id);
|
||||
/**Deletes a list of features
|
||||
@param id list of feature ids
|
||||
@return true in case of success and false in case of failure*/
|
||||
bool deleteFeatures(std::list<int> id);
|
||||
|
||||
bool supportsFeatureAddition(){return true;}
|
||||
|
||||
bool supportsFeatureDeletion(){return true;}
|
||||
|
||||
private:
|
||||
std::vector < QgsFeature > features;
|
||||
std::vector < bool > *selected;
|
||||
@ -282,4 +276,8 @@ private:
|
||||
bool gistAvailable;
|
||||
//! PROJ4 capability
|
||||
bool projAvailable;
|
||||
/**Writes a single feature*/
|
||||
bool addFeature(QgsFeature* f);
|
||||
/**Deletes a feature*/
|
||||
bool deleteFeature(int id);
|
||||
};
|
||||
|
@ -1870,11 +1870,6 @@ void QgisApp::deleteSelected()
|
||||
if (li)
|
||||
{
|
||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(((QgsLegendItem *) li)->layer());
|
||||
if(!vlayer->getDataProvider()||!vlayer->getDataProvider()->isEditable())
|
||||
{
|
||||
QMessageBox::information(0,"Layer not editable","Cannot edit the vector layer. Use 'Start editing' in the legend item menu",QMessageBox::Ok);
|
||||
return;
|
||||
}
|
||||
if(vlayer)
|
||||
{
|
||||
if(!vlayer->deleteSelectedFeatures())
|
||||
|
@ -85,35 +85,6 @@ public:
|
||||
*/
|
||||
virtual bool isValid()=0;
|
||||
|
||||
/**
|
||||
Enables editing capabilities of the provider (if supported)
|
||||
@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing()=0;
|
||||
|
||||
/**
|
||||
Disables the editing capabilities of the provider
|
||||
*/
|
||||
virtual void stopEditing()=0;
|
||||
|
||||
/**
|
||||
Commits changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool commitChanges()=0;
|
||||
|
||||
/**
|
||||
Discards changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool rollBack()=0;
|
||||
|
||||
/**Returns true if the provider is in editing mode*/
|
||||
virtual bool isEditable() const=0;
|
||||
|
||||
/**Returns true if the provider has been modified since the last commit*/
|
||||
virtual bool isModified() const=0;
|
||||
|
||||
/* Reset the layer - for an OGRLayer, this means clearing the
|
||||
* spatial filter and calling ResetReading
|
||||
*/
|
||||
|
@ -1202,10 +1202,10 @@ void QgsMapCanvas::mouseReleaseEvent(QMouseEvent * e)
|
||||
|
||||
if(vlayer)
|
||||
{
|
||||
if(!vlayer->getDataProvider()||!vlayer->getDataProvider()->isEditable())
|
||||
if(!vlayer->isEditable())
|
||||
{
|
||||
QMessageBox::information(0,"Layer not editable","Cannot edit the vector layer. Use 'Start editing' in the legend item menu",QMessageBox::Ok);
|
||||
break;
|
||||
QMessageBox::information(0,"Layer not editable","Cannot edit the vector layer. Use 'Start editing' in the legend item menu",QMessageBox::Ok);
|
||||
break;
|
||||
}
|
||||
|
||||
QgsFeature* f = new QgsFeature(0,"WKBPoint");
|
||||
@ -1250,7 +1250,7 @@ void QgsMapCanvas::mouseReleaseEvent(QMouseEvent * e)
|
||||
QgsVectorLayer* vlayer=dynamic_cast<QgsVectorLayer*>(mCanvasProperties->mapLegend->currentLayer());
|
||||
if(vlayer)
|
||||
{
|
||||
if(!vlayer->getDataProvider()||!vlayer->getDataProvider()->isEditable())
|
||||
if(!vlayer->isEditable())
|
||||
{
|
||||
QMessageBox::information(0,"Layer not editable","Cannot edit the vector layer. Use 'Start editing' in the legend item menu",QMessageBox::Ok);
|
||||
break;
|
||||
|
@ -222,7 +222,7 @@ public:
|
||||
void setLegendItem(QgsLegendItem * li);
|
||||
|
||||
/**True if the layer can be edited*/
|
||||
virtual bool isEditable()=0;
|
||||
virtual bool isEditable() const =0;
|
||||
|
||||
/** sets state from DOM document
|
||||
|
||||
|
@ -3142,7 +3142,7 @@ RasterPyramidList QgsRasterLayer::buildRasterPyramidList()
|
||||
}
|
||||
|
||||
|
||||
bool QgsRasterLayer::isEditable()
|
||||
bool QgsRasterLayer::isEditable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -769,7 +769,7 @@ public:
|
||||
// RasterPyramid getRasterPyramid(int thePyramidNo);
|
||||
|
||||
/**Currently returns always false*/
|
||||
bool isEditable();
|
||||
bool isEditable() const;
|
||||
|
||||
|
||||
public slots:
|
||||
|
@ -18,91 +18,19 @@
|
||||
#include "qgsfeature.h"
|
||||
|
||||
|
||||
QgsVectorDataProvider::QgsVectorDataProvider(): mEditable(false), mModified(false)
|
||||
QgsVectorDataProvider::QgsVectorDataProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool QgsVectorDataProvider::startEditing()
|
||||
|
||||
bool QgsVectorDataProvider::addFeatures(std::list<QgsFeature*> flist)
|
||||
{
|
||||
//providers supporting editing need to overwrite this method
|
||||
return false;
|
||||
}
|
||||
|
||||
void QgsVectorDataProvider::stopEditing()
|
||||
bool QgsVectorDataProvider::deleteFeatures(std::list<int> id)
|
||||
{
|
||||
mEditable=false;
|
||||
}
|
||||
|
||||
bool QgsVectorDataProvider::commitChanges()
|
||||
{
|
||||
if(mEditable)
|
||||
{
|
||||
bool returnvalue=true;
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
if(!commitFeature(*it))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
delete *it;
|
||||
}
|
||||
|
||||
for(std::set<int>::iterator it=mDeletedFeatures.begin();it!=mDeletedFeatures.end();++it)
|
||||
{
|
||||
if(!eraseFeature(*it))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
}
|
||||
|
||||
mAddedFeatures.clear();
|
||||
mDeletedFeatures.clear();
|
||||
mModified=false;
|
||||
return returnvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVectorDataProvider::rollBack()
|
||||
{
|
||||
if(mEditable)
|
||||
{
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
mAddedFeatures.clear();
|
||||
mModified=false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVectorDataProvider::addFeature(QgsFeature* f)
|
||||
{
|
||||
if(mEditable)
|
||||
{
|
||||
mAddedFeatures.push_back(f);
|
||||
mAddedFeaturesIt=mAddedFeatures.begin();
|
||||
mModified=true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVectorDataProvider::deleteFeature(int id)
|
||||
{
|
||||
//needs to be done by subclasses, because not all providers support it
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -112,15 +40,14 @@ QString QgsVectorDataProvider::getDefaultValue(const QString& attr,
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
bool QgsVectorDataProvider::commitFeature(QgsFeature* f)
|
||||
bool QgsVectorDataProvider::supportsFeatureAddition()
|
||||
{
|
||||
//needs to be done by subclasses
|
||||
//needs to be overwritten by providers if they provide feature editing
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsVectorDataProvider::eraseFeature(int id)
|
||||
bool QgsVectorDataProvider::supportsFeatureDeletion()
|
||||
{
|
||||
//needs to be done by subclasses
|
||||
//needs to be overwritten by providers which support this
|
||||
return false;
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ class QgsVectorDataProvider: public QgsDataProvider
|
||||
*@param attlist a list containing the indexes of the attribute fields to copy
|
||||
*@param getnotcommited flag indicating if not commited features should be returned
|
||||
*/
|
||||
virtual QgsFeature * getNextFeature(std::list<int>& attlist, bool getnotcommited=false)=0;
|
||||
virtual QgsFeature * getNextFeature(std::list<int>& attlist)=0;
|
||||
|
||||
/**
|
||||
* Get the next feature using new method
|
||||
@ -93,14 +93,14 @@ class QgsVectorDataProvider: public QgsDataProvider
|
||||
@param position the number of the attribute*/
|
||||
virtual QString maxValue(int position)=0;
|
||||
|
||||
/**Adds a feature (but does not commit it)
|
||||
/**Adds a list of features
|
||||
@return true in case of success and false in case of failure*/
|
||||
virtual bool addFeature(QgsFeature* f);
|
||||
virtual bool addFeatures(std::list<QgsFeature*> flist);
|
||||
|
||||
/**Deletes a feature (but not not write it to disk yes)
|
||||
@param id the number of the feature
|
||||
@param id list containing feature ids to delete
|
||||
@return true in case of success and false in case of failure*/
|
||||
virtual bool deleteFeature(int id);
|
||||
virtual bool deleteFeatures(std::list<int> id);
|
||||
|
||||
/**Returns the default value for attribute @c attr for feature @c f. */
|
||||
virtual QString getDefaultValue(const QString& attr, QgsFeature* f);
|
||||
@ -112,56 +112,11 @@ class QgsVectorDataProvider: public QgsDataProvider
|
||||
*/
|
||||
virtual std::vector<QgsFeature>& identify(QgsRect *rect)=0;
|
||||
|
||||
/**
|
||||
*Enables editing capabilities of the provider (if supported)
|
||||
*@return false in case of error or if the provider does not support editing
|
||||
*/
|
||||
virtual bool startEditing();
|
||||
/**Returns true if a provider supports feature editing*/
|
||||
virtual bool supportsFeatureAddition();
|
||||
|
||||
/**
|
||||
*Disables the editing capabilities of the provider
|
||||
*/
|
||||
virtual void stopEditing();
|
||||
|
||||
/**
|
||||
Commits changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool commitChanges();
|
||||
|
||||
/**
|
||||
Discards changes
|
||||
@return false in case of problems
|
||||
*/
|
||||
virtual bool rollBack();
|
||||
|
||||
/**Returns true if the provider is in editing mode*/
|
||||
virtual bool isEditable() const {return mEditable;}
|
||||
|
||||
/**Returns true if the provider has been modified since the last commit*/
|
||||
virtual bool isModified() const {return mModified;}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/**Flag indicating wheter the provider is in editing mode or not*/
|
||||
bool mEditable;
|
||||
/**Flag indicating wheter the provider has been modified since the last commit*/
|
||||
bool mModified;
|
||||
/**Features which are added but not yet commited*/
|
||||
std::list<QgsFeature*> mAddedFeatures;
|
||||
/**Ids of features to delete*/
|
||||
std::set<int> mDeletedFeatures;
|
||||
/**Commits the addition of a feature
|
||||
@return true in case of success and false in case of failure*/
|
||||
virtual bool commitFeature(QgsFeature* f);
|
||||
/**Commits the deletion of a feature
|
||||
@return true in case of success and false in case of faiure*/
|
||||
virtual bool eraseFeature(int id);
|
||||
|
||||
/**If getNextFeature needs to returns pointers to not commited features,
|
||||
this member points to the latest feature*/
|
||||
std::list<QgsFeature*>::iterator mAddedFeaturesIt;
|
||||
/**Returns true if a provider supports deleting features*/
|
||||
virtual bool supportsFeatureDeletion();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -89,7 +89,9 @@ QgsVectorLayer::QgsVectorLayer(QString vectorLayerPath,
|
||||
m_renderer(0),
|
||||
m_propertiesDialog(0),
|
||||
m_rendererDialog(0),
|
||||
ir(0) // initialize the identify results pointer
|
||||
ir(0), // initialize the identify results pointer
|
||||
mEditable(false),
|
||||
mModified(false)
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "VECTORLAYERPATH: " << vectorLayerPath.ascii() << std::endl;
|
||||
@ -275,13 +277,25 @@ void QgsVectorLayer::drawLabels(QPainter * p, QgsRect * viewExtent, QgsCoordinat
|
||||
{
|
||||
// Render label
|
||||
if ( mLabelOn && (fet != 0)) {
|
||||
bool sel=selected.find(fet->featureId()) != selected.end();
|
||||
mLabel->renderLabel ( p, viewExtent, cXf, dst, fet, sel);
|
||||
if(mDeleted.find(fet->featureId())==mDeleted.end())//don't render labels of deleted features
|
||||
{
|
||||
bool sel=mSelected.find(fet->featureId()) != mSelected.end();
|
||||
mLabel->renderLabel ( p, viewExtent, cXf, dst, fet, sel);
|
||||
}
|
||||
}
|
||||
delete fet;
|
||||
featureCount++;
|
||||
}
|
||||
|
||||
//render labels of not-commited features
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
bool sel=mSelected.find((*it)->featureId()) != mSelected.end();
|
||||
mLabel->renderLabel ( p, viewExtent, cXf, dst, *it, sel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "Total features processed is " << featureCount << std::endl;
|
||||
#endif
|
||||
@ -340,7 +354,7 @@ void QgsVectorLayer::draw(QPainter * p, QgsRect * viewExtent, QgsCoordinateTrans
|
||||
|
||||
std::list<int> attributes=m_renderer->classificationAttributes();
|
||||
|
||||
while((fet = dataProvider->getNextFeature(attributes,true)))
|
||||
while((fet = dataProvider->getNextFeature(attributes)))
|
||||
{
|
||||
// If update threshold is greater than 0, check to see if
|
||||
// the threshold has been exceeded
|
||||
@ -360,235 +374,25 @@ void QgsVectorLayer::draw(QPainter * p, QgsRect * viewExtent, QgsCoordinateTrans
|
||||
#endif
|
||||
} else
|
||||
{
|
||||
bool sel=selected.find(fet->featureId()) != selected.end();
|
||||
m_renderer->renderFeature(p, fet, &marker, &markerScaleFactor, sel);
|
||||
if(mDeleted.find(fet->featureId())==mDeleted.end())
|
||||
{
|
||||
bool sel=mSelected.find(fet->featureId()) != mSelected.end();
|
||||
m_renderer->renderFeature(p, fet, &marker, &markerScaleFactor, sel);
|
||||
|
||||
drawFeature(p,fet,cXf,&marker, markerScaleFactor);
|
||||
++featureCount;
|
||||
delete fet;
|
||||
}
|
||||
}
|
||||
}
|
||||
//also draw the not yet commited features
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
bool sel=mSelected.find((*it)->featureId()) != mSelected.end();
|
||||
m_renderer->renderFeature(p, fet, &marker, &markerScaleFactor, sel);
|
||||
drawFeature(p,*it,cXf,&marker,markerScaleFactor);
|
||||
}
|
||||
|
||||
// std::cout << "Feature type: " << wkbType << std::endl;
|
||||
// read each feature based on its type
|
||||
|
||||
// get the wkb representation
|
||||
feature = fet->getGeometry();
|
||||
// if (feature != 0) {
|
||||
// std::cout << featureCount << "'the feature is null\n";
|
||||
//TODO - add this to the debug options -- if we decide to keep it
|
||||
//wkbHeader header;
|
||||
//memcpy((void *)&header,feature,sizeof(header));
|
||||
//std::cout << "Endian:" << header.endian << " WkbType:" << header.wkbType << std::endl;
|
||||
|
||||
// FIX for the endian problem on osx (possibly sparc?)
|
||||
// TODO Restructure this whole wkb reading code to use
|
||||
// wkb structures as defined at (among other places):
|
||||
// http://publib.boulder.ibm.com/infocenter/db2help/index.jsp?topic=/com.ibm.db2.udb.doc/opt/rsbp4121.htm
|
||||
memcpy(&wkbType, (feature+1), sizeof(wkbType));
|
||||
|
||||
switch (wkbType)
|
||||
{
|
||||
case WKBPoint:
|
||||
|
||||
// fldDef = fet->GetFieldDefnRef(1);
|
||||
// fld = fldDef->GetNameRef();
|
||||
//NEEDTHIS? val = fet->GetFieldAsString(1);
|
||||
//std::cout << val << "\n";
|
||||
|
||||
x = (double *) (feature + 5);
|
||||
y = (double *) (feature + 5 + sizeof(double));
|
||||
// std::cout << "transforming point\n";
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
//std::cout << "drawing marker for feature " << featureCount << "\n";
|
||||
p->drawRect(static_cast<int>(pt.x()), static_cast<int>(pt.y()), 5, 5);
|
||||
p->scale(markerScaleFactor,markerScaleFactor);
|
||||
p->drawPicture((int)(static_cast<int>(pt.x()) / markerScaleFactor - marker.boundingRect().width() / 2),
|
||||
(int)(static_cast<int>(pt.y()) / markerScaleFactor - marker.boundingRect().height() / 2),
|
||||
marker);
|
||||
p->resetXForm();
|
||||
|
||||
break;
|
||||
|
||||
case WKBLineString:
|
||||
|
||||
// get number of points in the line
|
||||
ptr = feature + 5;
|
||||
nPoints = (int *) ptr;
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
// transform the point
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
if (idx == 0)
|
||||
p->moveTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
else
|
||||
p->lineTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
break;
|
||||
|
||||
case WKBMultiLineString:
|
||||
|
||||
numLineStrings = (int) (feature[5]);
|
||||
ptr = feature + 9;
|
||||
for (jdx = 0; jdx < numLineStrings; jdx++)
|
||||
{
|
||||
// each of these is a wbklinestring so must handle as such
|
||||
lsb = *ptr;
|
||||
ptr += 5; // skip type since we know its 2
|
||||
nPoints = (int *) ptr;
|
||||
ptr += sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
// transform the point
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
if (idx == 0)
|
||||
p->moveTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
else
|
||||
p->lineTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WKBPolygon:
|
||||
|
||||
{
|
||||
// get number of rings in the polygon
|
||||
numRings = (int *) (feature + 1 + sizeof(int));
|
||||
|
||||
if ( ! *numRings ) // sanity check for zero rings in polygon
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int *ringStart; // index of first point for each ring
|
||||
int *ringNumPoints; // number of points in each ring
|
||||
ringStart = new int[*numRings];
|
||||
ringNumPoints = new int[*numRings];
|
||||
|
||||
int x0, y0, pdx;
|
||||
pdx = 0;
|
||||
ptr = feature + 1 + 2 * sizeof(int); // set pointer to the first ring
|
||||
for (idx = 0; idx < *numRings; idx++) {
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ringStart[idx] = pdx;
|
||||
ringNumPoints[idx] = *nPoints;
|
||||
ptr += 4;
|
||||
if ( idx == 0 ) {
|
||||
pa = new QPointArray(*nPoints);
|
||||
} else {
|
||||
pa->resize ( pa->size() + *nPoints + 1 ); // better to calc size for all rings before?
|
||||
}
|
||||
for (jdx = 0; jdx < *nPoints; jdx++) {
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
#ifdef QGISX11DEBUG
|
||||
std::cout << "Transforming " << *x << "," << *y << " to ";
|
||||
#endif
|
||||
ptr += sizeof(double);
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
pa->setPoint(pdx++, static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
if ( idx == 0 ) { // remember last outer ring point
|
||||
x0 = static_cast<int>(pt.x());
|
||||
y0 = static_cast<int>(pt.y());
|
||||
} else { // return to x0,y0 (inner rings - islands)
|
||||
pa->setPoint(pdx++, x0, y0);
|
||||
}
|
||||
}
|
||||
// draw the polygon fill
|
||||
pen = p->pen(); // store current pen
|
||||
p->setPen ( Qt::NoPen ); // no boundary
|
||||
p->drawPolygon(*pa);
|
||||
|
||||
// draw outline
|
||||
p->setPen ( pen );
|
||||
p->setBrush ( Qt::NoBrush );
|
||||
for (idx = 0; idx < *numRings; idx++) {
|
||||
p->drawPolygon( *pa, FALSE, ringStart[idx], ringNumPoints[idx]);
|
||||
}
|
||||
|
||||
delete pa;
|
||||
delete [] ringStart;
|
||||
delete [] ringNumPoints;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case WKBMultiPolygon:
|
||||
|
||||
// get the number of polygons
|
||||
ptr = feature + 5;
|
||||
numPolygons = (int *) ptr;
|
||||
ptr = feature + 9;
|
||||
for (kdx = 0; kdx < *numPolygons; kdx++)
|
||||
{
|
||||
//skip the endian and feature type info and
|
||||
// get number of rings in the polygon
|
||||
ptr+=5;
|
||||
numRings = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ptr += 4;
|
||||
pa = new QPointArray(*nPoints);
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
#ifdef QGISX11DEBUG
|
||||
std::cout << "Transforming " << *x << "," << *y << " to ";
|
||||
#endif
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
pa->setPoint(jdx, static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
// draw the ring
|
||||
p->drawPolygon(*pa);
|
||||
delete pa;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef QGISDEBUG
|
||||
std::cout << "UNKNOWN WKBTYPE ENCOUNTERED\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// XXX should be lower down? delete fet;
|
||||
delete fet;
|
||||
//std::cout << "deleting feature[]\n";
|
||||
// std::cout << geom->getGeometryName() << std::endl;
|
||||
featureCount++;
|
||||
|
||||
}
|
||||
|
||||
//qApp->processEvents();
|
||||
|
||||
//delete fet;
|
||||
}
|
||||
#ifdef QGISDEBUG
|
||||
std::cerr << "Total features processed is " << featureCount << std::endl;
|
||||
#endif
|
||||
@ -598,6 +402,7 @@ void QgsVectorLayer::draw(QPainter * p, QgsRect * viewExtent, QgsCoordinateTrans
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("Warning, QgsRenderer is null in QgsVectorLayer::draw()");
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,7 +497,7 @@ void QgsVectorLayer::table()
|
||||
int numFields = dataProvider->fieldCount();
|
||||
tabledisplay = new QgsAttributeTableDisplay();
|
||||
connect(tabledisplay, SIGNAL(deleted()), this, SLOT(invalidateTableDisplay()));
|
||||
tabledisplay->table()->setNumRows(dataProvider->featureCount());
|
||||
tabledisplay->table()->setNumRows(dataProvider->featureCount()+mAddedFeatures.size()-mDeleted.size());
|
||||
tabledisplay->table()->setNumCols(numFields + 1); //+1 for the id-column
|
||||
|
||||
int row = 0;
|
||||
@ -708,7 +513,11 @@ void QgsVectorLayer::table()
|
||||
QgsFeature *fet;
|
||||
while ((fet = dataProvider->getNextFeature(true)))
|
||||
{
|
||||
|
||||
if(mDeleted.find(fet->featureId())!=mDeleted.end())
|
||||
{
|
||||
//feature has been deleted
|
||||
continue;
|
||||
}
|
||||
//id-field
|
||||
tabledisplay->table()->setText(row, 0, QString::number(fet->featureId()));
|
||||
tabledisplay->table()->insertFeatureId(fet->featureId(), row); //insert the id into the search tree of qgsattributetable
|
||||
@ -722,6 +531,21 @@ void QgsVectorLayer::table()
|
||||
delete fet;
|
||||
}
|
||||
|
||||
//also consider the not commited features
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
//id-field
|
||||
tabledisplay->table()->setText(row, 0, QString::number((*it)->featureId()));
|
||||
tabledisplay->table()->insertFeatureId((*it)->featureId(), row); //insert the id into the search tree of qgsattributetable
|
||||
std::vector < QgsFeatureAttribute > attr = (*it)->attributeMap();
|
||||
for (int i = 0; i < attr.size(); i++)
|
||||
{
|
||||
// get the field values
|
||||
tabledisplay->table()->setText(row, i + 1, attr[i].fieldValue());
|
||||
}
|
||||
row++;
|
||||
}
|
||||
|
||||
// reset the pointer to start of fetabledisplayures so
|
||||
// subsequent reads will not fail
|
||||
dataProvider->reset();
|
||||
@ -738,11 +562,11 @@ void QgsVectorLayer::table()
|
||||
|
||||
QObject::disconnect(tabledisplay->table(), SIGNAL(selectionChanged()), tabledisplay->table(), SLOT(handleChangedSelections()));
|
||||
|
||||
for (std::map < int, bool >::iterator it = selected.begin(); it != selected.end(); ++it)
|
||||
for (std::set<int>::iterator it = mSelected.begin(); it != mSelected.end(); ++it)
|
||||
{
|
||||
tabledisplay->table()->selectRowWithId(it->first);
|
||||
tabledisplay->table()->selectRowWithId(*it);
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("selecting row with id " + QString::number(it->first));
|
||||
qWarning("selecting row with id " + QString::number(*it));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -761,7 +585,7 @@ void QgsVectorLayer::table()
|
||||
|
||||
void QgsVectorLayer::select(int number)
|
||||
{
|
||||
selected[number] = true;
|
||||
mSelected.insert(number);
|
||||
}
|
||||
|
||||
void QgsVectorLayer::select(QgsRect * rect, bool lock)
|
||||
@ -790,10 +614,26 @@ void QgsVectorLayer::select(int number)
|
||||
|
||||
while (fet = dataProvider->getNextFeature(true))
|
||||
{
|
||||
select(fet->featureId());
|
||||
if (tabledisplay)
|
||||
if(mDeleted.find(fet->featureId())==mDeleted.end())//don't select deleted features
|
||||
{
|
||||
tabledisplay->table()->selectRowWithId(fet->featureId());
|
||||
select(fet->featureId());
|
||||
if (tabledisplay)
|
||||
{
|
||||
tabledisplay->table()->selectRowWithId(fet->featureId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//also test the not commited features
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
if((*it)->intersects(rect))
|
||||
{
|
||||
select((*it)->featureId());
|
||||
if (tabledisplay)
|
||||
{
|
||||
tabledisplay->table()->selectRowWithId((*it)->featureId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,7 +648,7 @@ void QgsVectorLayer::select(int number)
|
||||
|
||||
void QgsVectorLayer::removeSelection()
|
||||
{
|
||||
selected.clear();
|
||||
mSelected.clear();
|
||||
}
|
||||
|
||||
void QgsVectorLayer::triggerRepaint()
|
||||
@ -976,7 +816,7 @@ void QgsVectorLayer::select(int number)
|
||||
|
||||
while ((fet = dataProvider->getNextFeature(false)))
|
||||
{
|
||||
if (selected.find(fet->featureId()) != selected.end())
|
||||
if (mSelected.find(fet->featureId()) != mSelected.end())
|
||||
{
|
||||
feature = fet->getGeometry();
|
||||
wkbType = (int) feature[1];
|
||||
@ -1265,16 +1105,38 @@ void QgsVectorLayer::select(int number)
|
||||
{
|
||||
if(dataProvider)
|
||||
{
|
||||
int end=endian();
|
||||
memcpy(f->getGeometry(),&end,1);
|
||||
//set the endian properly
|
||||
int end=endian();
|
||||
memcpy(f->getGeometry(),&end,1);
|
||||
|
||||
//using a feature id which (hopefully) does not conflict with already commited features
|
||||
f->setFeatureId(-1);
|
||||
//assign a temporary id to the feature
|
||||
int tempid;
|
||||
if(mAddedFeatures.size()==0)
|
||||
{
|
||||
tempid=findFreeId();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::list<QgsFeature*>::iterator it=mAddedFeatures.end();
|
||||
--it;
|
||||
tempid=(*it)->featureId()+1;
|
||||
}
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("assigned feature id "+QString::number(tempid));
|
||||
#endif
|
||||
f->setFeatureId(tempid);
|
||||
mAddedFeatures.push_back(f);
|
||||
mModified=true;
|
||||
|
||||
if(dataProvider->addFeature(f))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
//hide and delete the table because it is not up to date any more
|
||||
if (tabledisplay)
|
||||
{
|
||||
tabledisplay->close();
|
||||
delete tabledisplay;
|
||||
tabledisplay=0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -1287,25 +1149,55 @@ void QgsVectorLayer::select(int number)
|
||||
|
||||
bool QgsVectorLayer::deleteSelectedFeatures()
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("entering QgsVectorLayer::deleteSelectedFeatures");
|
||||
#endif
|
||||
bool resvalue=true;
|
||||
for(std::map<int,bool>::iterator it=selected.begin();it!=selected.end();++it)
|
||||
{
|
||||
if(it->second==true)
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("selected feature detected");
|
||||
#endif
|
||||
if(!dataProvider->deleteFeature(it->first))
|
||||
{
|
||||
resvalue=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
triggerRepaint();
|
||||
return resvalue;
|
||||
if(!dataProvider->supportsFeatureDeletion())
|
||||
{
|
||||
QMessageBox::information(0, tr("Provider does not support deletion"), tr("Data provider does not support deleting features"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!isEditable())
|
||||
{
|
||||
QMessageBox::information(0, tr("Layer not editable"), tr("The current layer is not editable. Choose 'start editing' in the legend item right click menu"));
|
||||
return false;
|
||||
}
|
||||
|
||||
for(std::set<int>::iterator it=mSelected.begin();it!=mSelected.end();++it)
|
||||
{
|
||||
bool notcommitedfeature=false;
|
||||
//first test, if the feature with this id is a not-commited feature
|
||||
for(std::list<QgsFeature*>::iterator iter=mAddedFeatures.begin();iter!=mAddedFeatures.end();++iter)
|
||||
{
|
||||
if((*it)==(*iter)->featureId())
|
||||
{
|
||||
mAddedFeatures.erase(iter);
|
||||
notcommitedfeature=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(notcommitedfeature)
|
||||
{
|
||||
break;
|
||||
}
|
||||
mDeleted.insert(*it);
|
||||
}
|
||||
|
||||
if(mSelected.size()>0)
|
||||
{
|
||||
mModified=true;
|
||||
mSelected.clear();
|
||||
triggerRepaint();
|
||||
|
||||
//hide and delete the table because it is not up to date any more
|
||||
if (tabledisplay)
|
||||
{
|
||||
tabledisplay->close();
|
||||
delete tabledisplay;
|
||||
tabledisplay=0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QgsLabel * QgsVectorLayer::label()
|
||||
@ -1327,14 +1219,15 @@ void QgsVectorLayer::select(int number)
|
||||
{
|
||||
if(dataProvider)
|
||||
{
|
||||
if(!dataProvider->startEditing())
|
||||
{
|
||||
if(!dataProvider->supportsFeatureAddition())
|
||||
{
|
||||
QMessageBox::information(0,"Start editing failed","Provider cannot be opened for editing",QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
updateItemPixmap();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mEditable=true;
|
||||
updateItemPixmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1342,18 +1235,19 @@ void QgsVectorLayer::select(int number)
|
||||
{
|
||||
if(dataProvider)
|
||||
{
|
||||
if(dataProvider->isModified())
|
||||
if(mModified)
|
||||
{
|
||||
//commit or roll back?
|
||||
int commit=QMessageBox::information(0,"Stop editing","Do you want to save the changes?",QMessageBox::Yes,QMessageBox::No);
|
||||
if(commit==QMessageBox::Yes)
|
||||
{
|
||||
if(!dataProvider->commitChanges())
|
||||
if(!commitChanges())
|
||||
{
|
||||
QMessageBox::information(0,"Error","Could not commit changes",QMessageBox::Ok);
|
||||
}
|
||||
else
|
||||
{
|
||||
//hide and delete the table because it is not up to date any more
|
||||
if (tabledisplay)
|
||||
{
|
||||
tabledisplay->close();
|
||||
@ -1364,29 +1258,25 @@ void QgsVectorLayer::select(int number)
|
||||
}
|
||||
else if(commit==QMessageBox::No)
|
||||
{
|
||||
if(!dataProvider->rollBack())
|
||||
if(!rollBack())
|
||||
{
|
||||
QMessageBox::information(0,"Error","Problems during roll back",QMessageBox::Ok);
|
||||
}
|
||||
//hide and delete the table because it is not up to date any more
|
||||
if (tabledisplay)
|
||||
{
|
||||
tabledisplay->close();
|
||||
delete tabledisplay;
|
||||
tabledisplay=0;
|
||||
}
|
||||
}
|
||||
triggerRepaint();
|
||||
}
|
||||
dataProvider->stopEditing();
|
||||
mEditable=false;
|
||||
mModified=false;
|
||||
updateItemPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVectorLayer::isEditable()
|
||||
{
|
||||
if(dataProvider)
|
||||
{
|
||||
return dataProvider->isEditable();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// return state of scale dependent rendering. True if features should
|
||||
// only be rendered if between mMinimumScale and mMaximumScale
|
||||
@ -1860,3 +1750,316 @@ void QgsVectorLayer::inOverview( bool b )
|
||||
{
|
||||
QgsMapLayer::inOverview( b );
|
||||
}
|
||||
|
||||
int QgsVectorLayer::findFreeId()
|
||||
{
|
||||
int freeid=-INT_MAX;
|
||||
int fid;
|
||||
if(dataProvider)
|
||||
{
|
||||
dataProvider->reset();
|
||||
QgsFeature *fet;
|
||||
while ((fet = dataProvider->getNextFeature(true)))
|
||||
{
|
||||
fid=fet->featureId();
|
||||
if(fid>freeid)
|
||||
{
|
||||
freeid=fid;
|
||||
}
|
||||
delete fet;
|
||||
}
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("freeid is: "+QString::number(freeid+1));
|
||||
#endif
|
||||
return freeid+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef QGISDEBUG
|
||||
qWarning("Error, dataProvider is 0 in QgsVectorLayer::findFreeId");
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVectorLayer::commitChanges()
|
||||
{
|
||||
if(dataProvider)
|
||||
{
|
||||
bool returnvalue=true;
|
||||
std::list<QgsFeature*> addedlist;
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
addedlist.push_back(*it);
|
||||
}
|
||||
if(!dataProvider->addFeatures(addedlist))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
delete *it;
|
||||
}
|
||||
mAddedFeatures.clear();
|
||||
|
||||
if(mDeleted.size()>0)
|
||||
{
|
||||
std::list<int> deletelist;
|
||||
for(std::set<int>::iterator it=mDeleted.begin();it!=mDeleted.end();++it)
|
||||
{
|
||||
deletelist.push_back(*it);
|
||||
mSelected.erase(*it);//just in case the feature is still selected
|
||||
}
|
||||
if(!dataProvider->deleteFeatures(deletelist))
|
||||
{
|
||||
returnvalue=false;
|
||||
}
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsVectorLayer::rollBack()
|
||||
{
|
||||
for(std::list<QgsFeature*>::iterator it=mAddedFeatures.begin();it!=mAddedFeatures.end();++it)
|
||||
{
|
||||
delete *it;
|
||||
mSelected.erase((*it)->featureId());
|
||||
}
|
||||
mAddedFeatures.clear();
|
||||
for(std::set<int>::iterator it=mDeleted.begin();it!=mDeleted.end();++it)
|
||||
{
|
||||
mSelected.erase(*it);
|
||||
}
|
||||
mDeleted.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsVectorLayer::drawFeature(QPainter* p, QgsFeature* fet, QgsCoordinateTransform * cXf, QPicture* marker, double markerScaleFactor)
|
||||
{
|
||||
unsigned char *feature;
|
||||
bool attributesneeded = m_renderer->needsAttributes();
|
||||
|
||||
double *x;
|
||||
double *y;
|
||||
int wkbType;
|
||||
QgsPoint pt;
|
||||
|
||||
QPen pen;
|
||||
feature = fet->getGeometry();
|
||||
|
||||
memcpy(&wkbType, (feature+1), sizeof(wkbType));
|
||||
|
||||
switch (wkbType)
|
||||
{
|
||||
case WKBPoint:
|
||||
{
|
||||
x = (double *) (feature + 5);
|
||||
y = (double *) (feature + 5 + sizeof(double));
|
||||
// std::cout << "transforming point\n";
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
//std::cout << "drawing marker for feature " << featureCount << "\n";
|
||||
p->drawRect(static_cast<int>(pt.x()), static_cast<int>(pt.y()), 5, 5);
|
||||
p->scale(markerScaleFactor,markerScaleFactor);
|
||||
p->drawPicture((int)(static_cast<int>(pt.x()) / markerScaleFactor - marker->boundingRect().width() / 2),
|
||||
(int)(static_cast<int>(pt.y()) / markerScaleFactor - marker->boundingRect().height() / 2),
|
||||
*marker);
|
||||
p->resetXForm();
|
||||
|
||||
break;
|
||||
}
|
||||
case WKBLineString:
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int *nPoints;
|
||||
int idx;
|
||||
|
||||
// get number of points in the line
|
||||
ptr = feature + 5;
|
||||
nPoints = (int *) ptr;
|
||||
ptr = feature + 1 + 2 * sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
// transform the point
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
if (idx == 0)
|
||||
p->moveTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
else
|
||||
p->lineTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WKBMultiLineString:
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int idx, jdx, numLineStrings;
|
||||
int *nPoints;
|
||||
char lsb;
|
||||
|
||||
numLineStrings = (int) (feature[5]);
|
||||
ptr = feature + 9;
|
||||
for (jdx = 0; jdx < numLineStrings; jdx++)
|
||||
{
|
||||
// each of these is a wbklinestring so must handle as such
|
||||
lsb = *ptr;
|
||||
ptr += 5; // skip type since we know its 2
|
||||
nPoints = (int *) ptr;
|
||||
ptr += sizeof(int);
|
||||
for (idx = 0; idx < *nPoints; idx++)
|
||||
{
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
// transform the point
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
if (idx == 0)
|
||||
p->moveTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
else
|
||||
p->lineTo(static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WKBPolygon:
|
||||
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int idx, jdx;
|
||||
int *numRings, *nPoints;
|
||||
QPointArray *pa;
|
||||
|
||||
// get number of rings in the polygon
|
||||
numRings = (int *) (feature + 1 + sizeof(int));
|
||||
|
||||
if ( ! *numRings ) // sanity check for zero rings in polygon
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int *ringStart; // index of first point for each ring
|
||||
int *ringNumPoints; // number of points in each ring
|
||||
ringStart = new int[*numRings];
|
||||
ringNumPoints = new int[*numRings];
|
||||
|
||||
int x0, y0, pdx;
|
||||
pdx = 0;
|
||||
ptr = feature + 1 + 2 * sizeof(int); // set pointer to the first ring
|
||||
for (idx = 0; idx < *numRings; idx++) {
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ringStart[idx] = pdx;
|
||||
ringNumPoints[idx] = *nPoints;
|
||||
ptr += 4;
|
||||
if ( idx == 0 ) {
|
||||
pa = new QPointArray(*nPoints);
|
||||
} else {
|
||||
pa->resize ( pa->size() + *nPoints + 1 ); // better to calc size for all rings before?
|
||||
}
|
||||
for (jdx = 0; jdx < *nPoints; jdx++) {
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
#ifdef QGISX11DEBUG
|
||||
std::cout << "Transforming " << *x << "," << *y << " to ";
|
||||
#endif
|
||||
ptr += sizeof(double);
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
pa->setPoint(pdx++, static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
if ( idx == 0 ) { // remember last outer ring point
|
||||
x0 = static_cast<int>(pt.x());
|
||||
y0 = static_cast<int>(pt.y());
|
||||
} else { // return to x0,y0 (inner rings - islands)
|
||||
pa->setPoint(pdx++, x0, y0);
|
||||
}
|
||||
}
|
||||
// draw the polygon fill
|
||||
pen = p->pen(); // store current pen
|
||||
p->setPen ( Qt::NoPen ); // no boundary
|
||||
p->drawPolygon(*pa);
|
||||
|
||||
// draw outline
|
||||
p->setPen ( pen );
|
||||
p->setBrush ( Qt::NoBrush );
|
||||
for (idx = 0; idx < *numRings; idx++) {
|
||||
p->drawPolygon( *pa, FALSE, ringStart[idx], ringNumPoints[idx]);
|
||||
}
|
||||
|
||||
delete pa;
|
||||
delete [] ringStart;
|
||||
delete [] ringNumPoints;
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
case WKBMultiPolygon:
|
||||
{
|
||||
unsigned char *ptr;
|
||||
int idx, jdx, kdx;
|
||||
int *numPolygons, *numRings, *nPoints;
|
||||
QPointArray *pa;
|
||||
|
||||
// get the number of polygons
|
||||
ptr = feature + 5;
|
||||
numPolygons = (int *) ptr;
|
||||
ptr = feature + 9;
|
||||
for (kdx = 0; kdx < *numPolygons; kdx++)
|
||||
{
|
||||
//skip the endian and feature type info and
|
||||
// get number of rings in the polygon
|
||||
ptr+=5;
|
||||
numRings = (int *) ptr;
|
||||
ptr += 4;
|
||||
for (idx = 0; idx < *numRings; idx++)
|
||||
{
|
||||
// get number of points in the ring
|
||||
nPoints = (int *) ptr;
|
||||
ptr += 4;
|
||||
pa = new QPointArray(*nPoints);
|
||||
for (jdx = 0; jdx < *nPoints; jdx++)
|
||||
{
|
||||
// add points to a point array for drawing the polygon
|
||||
x = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
y = (double *) ptr;
|
||||
ptr += sizeof(double);
|
||||
#ifdef QGISX11DEBUG
|
||||
std::cout << "Transforming " << *x << "," << *y << " to ";
|
||||
#endif
|
||||
pt.setX(*x);
|
||||
pt.setY(*y);
|
||||
cXf->transform(&pt);
|
||||
pa->setPoint(jdx, static_cast<int>(pt.x()), static_cast<int>(pt.y()));
|
||||
}
|
||||
// draw the ring
|
||||
p->drawPolygon(*pa);
|
||||
delete pa;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
#ifdef QGISDEBUG
|
||||
std::cout << "UNKNOWN WKBTYPE ENCOUNTERED\n";
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -210,9 +210,6 @@ class QgsVectorLayer : public QgsMapLayer
|
||||
/**Label is on */
|
||||
bool labelOn( void );
|
||||
|
||||
/**True if the layer can be edited*/
|
||||
bool isEditable();
|
||||
|
||||
/**
|
||||
* Minimum scale at which the layer is rendered
|
||||
* @return Scale as integer
|
||||
@ -228,11 +225,20 @@ class QgsVectorLayer : public QgsMapLayer
|
||||
* @return true if so
|
||||
*/
|
||||
bool scaleDependentRender();
|
||||
|
||||
/**Returns true if the provider is in editing mode*/
|
||||
virtual bool isEditable() const {return (mEditable&&dataProvider);}
|
||||
|
||||
/**Returns true if the provider has been modified since the last commit*/
|
||||
virtual bool isModified() const {return mModified;}
|
||||
|
||||
protected:
|
||||
/**Pointer to the table display object if there is one, else a pointer to 0*/
|
||||
QgsAttributeTableDisplay * tabledisplay;
|
||||
/**Vector holding the information which features are activated*/
|
||||
std::map < int, bool > selected;
|
||||
std::set<int> mSelected;
|
||||
std::set<int> mDeleted;
|
||||
std::list<QgsFeature*> mAddedFeatures;
|
||||
/**Color to and fill the selected features*/
|
||||
QColor selectionColor;
|
||||
/**Renderer object which holds the information about how to display the features*/
|
||||
@ -245,11 +251,19 @@ protected:
|
||||
QgsDlgVectorLayerProperties *m_propertiesDialog;
|
||||
/**Widget to set the symbology properties*/
|
||||
QDialog *m_rendererDialog;
|
||||
/**Goes through all features and finds a free id (e.g. to give it temporarily to a not-commited feature)*/
|
||||
int findFreeId();
|
||||
/**Writes the changes to disk*/
|
||||
bool commitChanges();
|
||||
/**Discards the edits*/
|
||||
bool rollBack();
|
||||
|
||||
protected slots:
|
||||
void startEditing();
|
||||
void stopEditing();
|
||||
|
||||
void drawFeature(QPainter* p, QgsFeature* fet, QgsCoordinateTransform * cXf, QPicture* marker, double markerScaleFactor);
|
||||
|
||||
private: // Private attributes
|
||||
|
||||
//! Draws the layer labels using coordinate transformation
|
||||
@ -313,6 +327,11 @@ private: // Private methods
|
||||
// Identify Results dialog box
|
||||
QgsAttributeAction mActions;
|
||||
|
||||
/**Flag indicating wheter the layer is in editing mode or not*/
|
||||
bool mEditable;
|
||||
/**Flag indicating wheter the layer has been modified since the last commit*/
|
||||
bool mModified;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user