Added a Menu item to create new empty shapefiles. Unfortunately, a dummy feature is inserted into each new layer (coordinates 0/0). Without the dummy features, a segfault in OGR would happen when opening the .dbf file. I will do more investigations to figure out if there is a way such that there is no need for dummy features.

git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@2129 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
mhugent 2004-10-14 22:54:24 +00:00
parent 74c42d09fe
commit da8fce8702
11 changed files with 614 additions and 106 deletions

View File

@ -86,7 +86,7 @@ QgsShapeFileProvider::QgsShapeFileProvider(QString uri):mEditable(false), mModif
delete feat;
} else {
valid = false;
}
}
ogrLayer->ResetReading();
#ifdef QGISDEBUG
@ -339,7 +339,7 @@ QgsFeature *QgsShapeFileProvider::getNextFeature(std::list<int>& attlist)
{
#ifdef QGISDEBUG
qWarning("accessing feature in the cache");
#endif QGISDEBUG
#endif //QGISDEBUG
QgsFeature* addedfeature=*mAddedFeaturesIt;
++mAddedFeaturesIt;
//copy the feature because it will be deleted in QgsVectorLayer::draw()
@ -736,7 +736,7 @@ bool QgsShapeFileProvider::commitFeature(QgsFeature* f)
feature->SetGeometry(multipol);
}
}
if(ogrLayer->CreateFeature(feature)!=OGRERR_NONE)
{
//writing failed

View File

@ -33,6 +33,7 @@ bin_PROGRAMS = qgis
## ancillary library for plug-ins
lib_LTLIBRARIES = libqgis.la
headers = \
qgisapp.h \
qgis.h \
@ -53,6 +54,7 @@ headers = \
qgsfeatureattribute.h \
qgsfeature.h \
qgsfield.h \
qgsgeomtypedialog.h \
qgsgraduatedmarenderer.h \
qgsgraduatedsymrenderer.h \
qgsgramadialog.h \
@ -111,12 +113,14 @@ headers = \
splashscreen.h
## qt designer files for all the GUI stuff
qgis_UIC = \
qgisappbase.ui \
qgsabout.ui \
qgsattributetablebase.ui \
qgscontcoldialogbase.ui \
qgsdlgvectorlayerpropertiesbase.ui \
qgsgeomtypedialogbase.ui \
qgsgramadialogbase.ui \
qgsgrasydialogbase.ui \
qgshelpviewerbase.ui \
@ -162,12 +166,14 @@ qgis_UIMOC = $(qgis_UIC:.ui=.moc.uic.cpp)
## non-uic files generated from MOC
qgis_MOC = \
qgisapp.moc.cpp \
qgisinterface.moc.cpp \
qgsattributetable.moc.cpp \
qgscontcoldialog.moc.cpp \
qgsdlgvectorlayerproperties.moc.cpp \
qgsgeomtypedialog.moc.cpp \
qgsgramadialog.moc.cpp \
qgsgramaextensionwidget.moc.cpp \
qgsgrasydialog.moc.cpp \
@ -217,6 +223,7 @@ qgis_SOURCES = \
qgsfeatureattribute.cpp \
qgsfeature.cpp \
qgsfield.cpp \
qgsgeomtypedialog.cpp \
qgsgraduatedmarenderer.cpp \
qgsgraduatedsymrenderer.cpp \
qgsgramadialog.cpp \

View File

@ -85,6 +85,7 @@
#include "qgslegend.h"
#include "qgsprojectio.h"
#include "qgsmapserverexport.h"
#include "qgsgeomtypedialog.h"
#ifdef HAVE_POSTGRESQL
@ -1213,6 +1214,103 @@ void QgisApp::fileNew(bool thePromptToSaveFlag)
}
}
void QgisApp::newVectorLayer()
{
QGis::WKBTYPE geometrytype;
QgsGeomTypeDialog geomDialog;
if(geomDialog.exec()==QDialog::Rejected)
{
#ifdef QGISDEBUG
qWarning("dialog rejected");
#endif
return;
}
geometrytype = geomDialog.selectedType();
#ifdef QGISDEBUG
qWarning("dialog accepted");
#endif
QString filename=QFileDialog::getSaveFileName();
#ifdef QGISDEBUG
qWarning("the filename is : "+filename);
#endif
if(geometrytype == QGis::WKBPoint)
{
QgsVectorFileWriter writer(filename,wkbPoint);
if(!writer.initialise())
{
QMessageBox::warning(0,"Warning","Writing of the layer failed",QMessageBox::Ok,QMessageBox::NoButton);
return;
}
writer.createField("dummy", OFTReal, 1, 1);
//creation of a dummy feature
QgsPoint point(0,0);
writer.writePoint(&point);
}
else if(geometrytype == QGis::WKBLineString)
{
QgsVectorFileWriter writer(filename,wkbLineString);
if(!writer.initialise())
{
QMessageBox::warning(0,"Warning","Writing of the layer failed",QMessageBox::Ok,QMessageBox::NoButton);
return;
}
writer.createField("dummy", OFTReal, 1, 1);
//creation of a dummy line with just one point (0,0)
int size=1+2*sizeof(int)+2*sizeof(double);
unsigned char* wkb=new unsigned char[size];
int wkbtype=QGis::WKBLineString;
memcpy(&wkb[1],&wkbtype, sizeof(int));
int length=1;
memcpy(&wkb[1+sizeof(int)],&length, sizeof(int));
double dummycoordinate=0;
memcpy(&wkb[1+2*sizeof(int)],&dummycoordinate,sizeof(double));
memcpy(&wkb[1+2*sizeof(int)+sizeof(double)],&dummycoordinate,sizeof(double));
writer.writeLine(wkb,size);
delete[] wkb;
}
else if(geometrytype == QGis::WKBPolygon)
{
QgsVectorFileWriter writer(filename,wkbPolygon);
if(!writer.initialise())
{
QMessageBox::warning(0,"Warning","Writing of the layer failed",QMessageBox::Ok,QMessageBox::NoButton);
return;
}
writer.createField("dummy", OFTReal, 1, 1);
//creation of a dummy polygon with just one point (0,0)
int size=1+3*sizeof(int)+2*sizeof(double);
unsigned char* wkb=new unsigned char[size];
int wkbtype=QGis::WKBPolygon;
memcpy(&wkb[1],&wkbtype, sizeof(int));
int numring=1;
memcpy(&wkb[1+sizeof(int)],&numring,sizeof(int));
int length=1;
memcpy(&wkb[1+2*sizeof(int)],&length, sizeof(int));
double dummycoordinate=0;
memcpy(&wkb[1+3*sizeof(int)],&dummycoordinate,sizeof(double));
memcpy(&wkb[1+3*sizeof(int)+sizeof(double)],&dummycoordinate,sizeof(double));
writer.writePolygon(wkb,size);
delete[] wkb;
}
else
{
#ifdef QGISDEBUG
qWarning("QgisApp.cpp: geometry type not recognised");
#endif
return;
}
//then add the layer to the view
QFileInfo fileinfo(filename);
addLayer(fileinfo);
return;
}
void QgisApp::fileOpen()
{

View File

@ -266,6 +266,8 @@ private slots:
void fileNew();
//! As above but allows forcing without prompt
void fileNew(bool thePromptToSaveFlag);
//! Create a new empty vector layer
void newVectorLayer();
//! Print the current map view frame
void filePrint();
//! Add all loaded layers into the overview - overides qgisappbase method

File diff suppressed because one or more lines are too long

View File

@ -257,3 +257,9 @@ void QgisAppBase::about()
{
}
void QgisAppBase::newVectorLayer()
{
}

47
src/qgsgeomtypedialog.cpp Normal file
View File

@ -0,0 +1,47 @@
/***************************************************************************
qgsgeomtypedialog.cpp - description
-------------------
begin : October 2004
copyright : (C) 2004 by Marco Hugentobler
email : marco.hugentobler@autoform.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsgeomtypedialog.h"
#include <qradiobutton.h>
QgsGeomTypeDialog::QgsGeomTypeDialog(): QgsGeomTypeDialogBase()
{
QObject::connect((QObject*)mOkButton, SIGNAL(clicked()), this, SLOT(accept()));//why is this cast necessary????
QObject::connect((QObject*)mCancelButton, SIGNAL(clicked()), this, SLOT(reject()));//why is this cast necessary????
mPointRadioButton->setChecked(true);
}
QgsGeomTypeDialog::~QgsGeomTypeDialog()
{
}
QGis::WKBTYPE QgsGeomTypeDialog::selectedType()
{
if(mPointRadioButton->isChecked())
{
return QGis::WKBPoint;
}
else if(mLineRadioButton->isChecked())
{
return QGis::WKBLineString;
}
else if(mPolygonRadioButton->isChecked())
{
return QGis::WKBPolygon;
}
}

40
src/qgsgeomtypedialog.h Normal file
View File

@ -0,0 +1,40 @@
/***************************************************************************
qgsgeomtypedialog.h - description
-------------------
begin : October 2004
copyright : (C) 2004 by Marco Hugentobler
email : marco.hugentobler@autoform.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGEOMTYPEDIALOG_H
#define QGSGEOMTYPEDIALOG_H
#ifdef WIN32
#include "qgsgeomtypedialogbase.h"
#else
#include "qgsgeomtypedialogbase.uic.h"
#endif //WIN32
#include "qgis.h"
class QgsGeomTypeDialog: public QgsGeomTypeDialogBase
{
Q_OBJECT
public:
QgsGeomTypeDialog();
~QgsGeomTypeDialog();
/**Returns the selected geometry type*/
QGis::WKBTYPE selectedType();
};
#endif //QGSGEOMTYPEDIALOG_H

View File

@ -0,0 +1,125 @@
<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
<class>QgsGeomTypeDialogBase</class>
<widget class="QDialog">
<property name="name">
<cstring>QgsGeomTypeDialogBase</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>330</width>
<height>244</height>
</rect>
</property>
<property name="caption">
<string>Select Geometry type</string>
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QButtonGroup" row="0" column="0">
<property name="name">
<cstring>buttonGroup1</cstring>
</property>
<property name="title">
<string>Type</string>
</property>
<property name="exclusive">
<bool>true</bool>
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<widget class="QRadioButton" row="0" column="0">
<property name="name">
<cstring>mPointRadioButton</cstring>
</property>
<property name="text">
<string>Point</string>
</property>
</widget>
<widget class="QRadioButton" row="1" column="0">
<property name="name">
<cstring>mLineRadioButton</cstring>
</property>
<property name="text">
<string>Line</string>
</property>
</widget>
<widget class="QRadioButton" row="2" column="0">
<property name="name">
<cstring>mPolygonRadioButton</cstring>
</property>
<property name="text">
<string>Polygon</string>
</property>
</widget>
</grid>
</widget>
<widget class="QLayoutWidget" row="1" column="0">
<property name="name">
<cstring>layout3</cstring>
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<spacer>
<property name="name">
<cstring>spacer9</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>93</width>
<height>20</height>
</size>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>mOkButton</cstring>
</property>
<property name="text">
<string>OK</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>mCancelButton</cstring>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
<spacer>
<property name="name">
<cstring>spacer10</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
<property name="sizeHint">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</hbox>
</widget>
</grid>
</widget>
<layoutdefaults spacing="6" margin="11"/>
</UI>

View File

@ -11,6 +11,9 @@
//#include "gdal_alg.h"
//#include "cpl_conv.h"
#include "ogr_srs_api.h"
#ifndef WIN32
#include <netinet/in.h>
#endif
QgsVectorFileWriter::QgsVectorFileWriter(QString theOutputFileName, QgsVectorLayer * theVectorLayer)
{
@ -103,11 +106,23 @@ bool QgsVectorFileWriter::initialise()
mySpatialReferenceSystemHandle = OSRNewSpatialReference( myWKT );
}
//change 'contour' to something more useful!
mLayerHandle = OGR_DS_CreateLayer( mDataSourceHandle,
"contour",
mySpatialReferenceSystemHandle,
mGeometryType,
NULL );
#ifdef QGISDEBUG
qWarning("mOutputFileName: "+mOutputFileName);
#endif //QGISDEBUG
#ifdef WIN32
QString outname=mOutputFileName.mid(mOutputFileName.findRev("\\")+1,mOutputFileName.length());
#else
QString outname=mOutputFileName.mid(mOutputFileName.findRev("/")+1,mOutputFileName.length());
#endif
#ifdef QGISDEBUG
qWarning("outname: "+outname);
#endif //QGISDEBUG
mLayerHandle = OGR_DS_CreateLayer( mDataSourceHandle, outname,
mySpatialReferenceSystemHandle, mGeometryType, NULL );
if( mLayerHandle == NULL )
{
@ -118,6 +133,7 @@ bool QgsVectorFileWriter::initialise()
{
std::cout << "File handle created!" << std::endl;
}
//let other methods know we have an initialised file
mInitialisedFlag=true;
return true;
@ -185,72 +201,186 @@ bool QgsVectorFileWriter::createField(QString theName, OGRFieldType theType, int
bool QgsVectorFileWriter::writePoint(QgsPoint * thePoint)
{
//check the output file has been initialised
if (!mInitialisedFlag)
{
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
return false;
}
//check the geomtry of the output file is compatible
if (mGeometryType != wkbPoint)
{
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
return false;
}
//
//
// Do Stuff
//
return true;
bool returnvalue=true;
//check the output file has been initialised
if (!mInitialisedFlag)
{
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
return false;
}
//check the geomtry of the output file is compatible
if (mGeometryType != wkbPoint)
{
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
return false;
}
OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
OGRFeatureH fhand= OGR_F_Create( fdef );
OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbPoint);
OGR_G_AddPoint( geometryh, thePoint->x(), thePoint->y(), 0 );
if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Set geometry failed");
#endif
returnvalue=false;
}
if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Creation of the point failed");
#endif
returnvalue=false;
}
if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Sync to disk failed");
#endif
returnvalue=false;
}
OGR_F_Destroy( fhand );
return returnvalue;
}
//
// I think this stuff illustrates how to write features to a vector file.
//
bool QgsVectorFileWriter::writeLine(unsigned char* wkb, int size)
{
bool returnvalue=true;
//add endianness
int endianval = endian();
memcpy(&wkb[0],&endianval,1);
//check the output file has been initialised
if (!mInitialisedFlag)
{
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
return false;
}
//check the geomtry of the output file is compatible
if (mGeometryType != wkbLineString)
{
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
return false;
}
/*
CPLErr eErr;
CPLErr OGRContourWriter( double dfLevel,
int nPoints, double *padfX, double *padfY,
void *pInfo )
OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
OGRFeatureH fhand= OGR_F_Create( fdef );
OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbLineString);
if(OGR_G_ImportFromWkb(geometryh, wkb, size)!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("wkb import failed");
#endif
returnvalue=false;
}
{
OGRContourWriterInfo *poInfo = (OGRContourWriterInfo *) pInfo;
OGRFeatureH hFeat;
OGRGeometryH hGeom;
int iPoint;
if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Set geometry failed");
#endif
returnvalue=false;
}
hFeat = OGR_F_Create( OGR_L_GetLayerDefn( poInfo->myLayerHandle ) );
if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Creation of the point failed");
#endif
returnvalue=false;
}
if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Sync to disk failed");
#endif
returnvalue=false;
}
OGR_F_Destroy( fhand );
return returnvalue;
}
if( poInfo->nIDField != -1 )
OGR_F_SetFieldInteger( hFeat, poInfo->nIDField, poInfo->nNextID++ );
bool QgsVectorFileWriter::writePolygon(unsigned char* wkb, int size)
{
bool returnvalue = true;
//add endianness
int endianval = endian();
memcpy(&wkb[0],&endianval,1);
//check the output file has been initialised
if (!mInitialisedFlag)
{
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
return false;
}
//check the geomtry of the output file is compatible
if (mGeometryType != wkbPolygon)
{
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
return false;
}
if( poInfo->nElevField != -1 )
OGR_F_SetFieldDouble( hFeat, poInfo->nElevField, dfLevel );
OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
OGRFeatureH fhand= OGR_F_Create( fdef );
OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbPolygon);
if(OGR_G_ImportFromWkb(geometryh, wkb, size)!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("wkb import failed");
#endif
returnvalue = false;
}
hGeom = OGR_G_CreateGeometry( wkbLineString );
if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Set geometry failed");
#endif
returnvalue = false;
}
for( iPoint = nPoints-1; iPoint >= 0; iPoint-- )
{
OGR_G_SetPoint( hGeom, iPoint,
poInfo->adfGeoTransform[0]
+ poInfo->adfGeoTransform[1] * padfX[iPoint]
+ poInfo->adfGeoTransform[2] * padfY[iPoint],
poInfo->adfGeoTransform[3]
+ poInfo->adfGeoTransform[4] * padfX[iPoint]
+ poInfo->adfGeoTransform[5] * padfY[iPoint],
dfLevel );
}
if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Creation of the point failed");
#endif
returnvalue = false;
}
if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
{
#ifdef QGISDEBUG
qWarning("Sync to disk failed");
#endif
returnvalue = false;
}
OGR_F_Destroy( fhand );
return true;
}
OGR_F_SetGeometryDirectly( hFeat, hGeom );
int QgsVectorFileWriter::endian()
{
#ifdef WIN32
return NDR;
#else
// XXX why re-calculate this all the time? Why not just calculate this
// XXX once and return the value? For that matter, some machines have
// XXX endian.h, which stores the constant variable for local endian-ness.
if ( 23 == htons( 23 ) )
{
// if host byte order is same as network (big-endian) byte order, then
// this is a big-endian environment
return XDR;
}
// otherwise this must be little-endian
OGR_L_CreateFeature( poInfo->myLayerHandle, hFeat );
OGR_F_Destroy( hFeat );
return CE_None;
}
*/
return NDR;
#endif
}

View File

@ -18,7 +18,18 @@ class QgsVectorFileWriter
QgsVectorFileWriter(QString theOutputFileName, QgsVectorLayer * theVectorLayer);
QgsVectorFileWriter(QString theOutputFileName, OGRwkbGeometryType theGeometryType);
~QgsVectorFileWriter() ;
bool writePoint(QgsPoint * thePoint);
/**Writes a point to the file*/
bool writePoint(QgsPoint * thePoint);
/**Writes a line to the file
@param wkb well known binary char array
@param size size of the binary array
@return true in case of success and false else*/
bool writeLine(unsigned char* wkb, int size);
/**Writes a polygon to the file
@param wkb well known binary char array
@param size size of the binary array
@return true in case of success and false else*/
bool writePolygon(unsigned char* wkb, int size);
//! Add a new field to the output attribute table
bool createField(QString theName, OGRFieldType theType, int theWidthInt=0, int thePrecisionInt=0);
//! creates the output file etc...
@ -38,5 +49,12 @@ class QgsVectorFileWriter
OGRwkbGeometryType mGeometryType;
//! Whether the output gile has been initialised. Some operations require this to be true before they will run
bool mInitialisedFlag;
enum ENDIAN
{
NDR = 1,
XDR = 0
};
/** Return endian-ness for this layer*/
int endian();
};
#endif