mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
handling vector data geometry and attribute updates refactored
QgsVectorLayer: - move attribute part of editing to vector layer class and unify with geometry handling: * remove commitAttributeChanges(), addedFeatures(), deletedFeatureIds(), changedAttributes() and replace with changeAttributeValue(), deleteFeature(), addAttribute() and deleteAttribute() * add pendingFields(), pendingAttributeList(), pendingFeatureCount() * emit signals on start editing and commit, change of attribute values, adding/deleting of attributes and layer or feature removal (currently used in the attribute table) - new commitErrors() method to query errors from commitChanges() - replaced featuresInRectangle with select/getNextFeature combo - edit types added to support more input widgets and input constraints QgsFeature: - remove update aware ctor - unify geometry handling in ctors QgsVectorDataProvider: - add QVariant::Type to supportNativeTypes() QgisApp: - add instance() method to query QgisApp object - replace code at various place to use it instead of passing the pointer arround or searching it in the widget tree. - move toggleEditing() code from the legend here QgsAttributeTable/QgsAttributeTableDisplay: - move attribute table creation legend here - make attribute table dockable (from Tim) - most editing logic moved to QgsVectorLayer - adding/deleting attributes moved to QgsVectorLayerProperties QgsIdentifyResults: - add support for attribute editing when it edit mode QgsVectorLayerProperties: add a new tab to show attribute list: * start/stop editing * add/delete attributes * assign edit type to attributes (unique values, value map, ranges) QgsAttributeDialog: add support for attribute edit types: * selection from unique value render classes (combobox) * selection from unique values of existing features (combobox or line edits with completion) * spinboxes for ranges QgsPostgresProvider: - use read-only connection for cursors and read-write connection for updates - updated native types QgsOgrProvider: - remove unused references to GEOS geometry factory - updated native types git-svn-id: http://svn.osgeo.org/qgis/trunk@9092 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
03ef707a0d
commit
43278d720b
@ -13,18 +13,6 @@ class QgsFeature
|
|||||||
//! Constructor
|
//! Constructor
|
||||||
QgsFeature(int id = 0, QString typeName = "" );
|
QgsFeature(int id = 0, QString typeName = "" );
|
||||||
|
|
||||||
/** create a copy of this feature in its uncommitted state.
|
|
||||||
To do this, you also pass in a reference to the feature's
|
|
||||||
layer's uncommitted attribute and geometry changes.
|
|
||||||
The resulting feature will have those changes applied.
|
|
||||||
|
|
||||||
This is useful in the cut/copy routine, where you'd
|
|
||||||
want a copy of the "current" feature, not the on-disk feature.
|
|
||||||
*/
|
|
||||||
QgsFeature( const QgsFeature & rhs,
|
|
||||||
const QMap<int, QMap<int, QVariant> >& changedAttributes,
|
|
||||||
const QMap<int, QgsGeometry> & changedGeometries );
|
|
||||||
|
|
||||||
/** copy ctor needed due to internal pointer */
|
/** copy ctor needed due to internal pointer */
|
||||||
QgsFeature(const QgsFeature & rhs );
|
QgsFeature(const QgsFeature & rhs );
|
||||||
|
|
||||||
|
@ -88,7 +88,6 @@ class QgsVectorDataProvider : QgsDataProvider
|
|||||||
*/
|
*/
|
||||||
virtual QGis::WKBTYPE geometryType() const = 0;
|
virtual QGis::WKBTYPE geometryType() const = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of features in the layer
|
* Number of features in the layer
|
||||||
* @return long containing number of features
|
* @return long containing number of features
|
||||||
@ -230,7 +229,7 @@ class QgsVectorDataProvider : QgsDataProvider
|
|||||||
QList<int> allAttributesList();
|
QList<int> allAttributesList();
|
||||||
|
|
||||||
/**Returns the names of the numerical types*/
|
/**Returns the names of the numerical types*/
|
||||||
const QSet<QString>& supportedNativeTypes() const;
|
const QMap<QString,QVariant::Type> &supportedNativeTypes() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether provider should return also features that don't have
|
* Set whether provider should return also features that don't have
|
||||||
|
@ -1,12 +1,27 @@
|
|||||||
|
|
||||||
|
|
||||||
class QgsVectorLayer : QgsMapLayer
|
class QgsVectorLayer : QgsMapLayer
|
||||||
{
|
{
|
||||||
%TypeHeaderCode
|
%TypeHeaderCode
|
||||||
#include <qgsvectorlayer.h>
|
#include "qgsvectorlayer.h"
|
||||||
%End
|
%End
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum EditType {
|
||||||
|
LineEdit,
|
||||||
|
UniqueValues,
|
||||||
|
UniqueValuesEditable,
|
||||||
|
ValueMap,
|
||||||
|
Classification,
|
||||||
|
Range,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RangeData {
|
||||||
|
RangeData();
|
||||||
|
RangeData(QVariant theMin, QVariant theMax, QVariant theStep);
|
||||||
|
|
||||||
|
QVariant mMin;
|
||||||
|
QVariant mMax;
|
||||||
|
QVariant mStep;
|
||||||
|
};
|
||||||
|
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
QgsVectorLayer(QString baseName = 0, QString path = 0, QString providerLib = 0);
|
QgsVectorLayer(QString baseName = 0, QString path = 0, QString providerLib = 0);
|
||||||
@ -66,10 +81,6 @@ public:
|
|||||||
/** Returns the bounding box of the selected features. If there is no selection, QgsRect(0,0,0,0) is returned */
|
/** Returns the bounding box of the selected features. If there is no selection, QgsRect(0,0,0,0) is returned */
|
||||||
QgsRect boundingBoxOfSelected();
|
QgsRect boundingBoxOfSelected();
|
||||||
|
|
||||||
|
|
||||||
/** Insert a copy of the given features into the layer */
|
|
||||||
bool addFeatures(QList<QgsFeature> features, bool makeSelected = TRUE);
|
|
||||||
|
|
||||||
/** Copies the symbology settings from another layer. Returns true in case of success */
|
/** Copies the symbology settings from another layer. Returns true in case of success */
|
||||||
bool copySymbologySettings(const QgsMapLayer& other);
|
bool copySymbologySettings(const QgsMapLayer& other);
|
||||||
|
|
||||||
@ -92,12 +103,12 @@ public:
|
|||||||
QString providerType() const;
|
QString providerType() const;
|
||||||
|
|
||||||
/** reads vector layer specific state from project file DOM node.
|
/** reads vector layer specific state from project file DOM node.
|
||||||
* @note Called by QgsMapLayer::readXML().
|
* @note Called by QgsMapLayer::readXml().
|
||||||
*/
|
*/
|
||||||
virtual bool readXml( QDomNode & layer_node );
|
virtual bool readXml( QDomNode & layer_node );
|
||||||
|
|
||||||
/** write vector layer specific state to project file DOM node.
|
/** write vector layer specific state to project file DOM node.
|
||||||
* @note Called by QgsMapLayer::writeXML().
|
* @note Called by QgsMapLayer::writeXml().
|
||||||
*/
|
*/
|
||||||
virtual bool writeXml( QDomNode & layer_node, QDomDocument & doc );
|
virtual bool writeXml( QDomNode & layer_node, QDomDocument & doc );
|
||||||
|
|
||||||
@ -130,17 +141,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual QString subsetString();
|
virtual QString subsetString();
|
||||||
|
|
||||||
/**Returns the features contained in the rectangle. Considers the changed, added, deleted and permanent features
|
void select(QList<int> fetchAttributes = QList<int>(),
|
||||||
@return 0 in case of success*/
|
QgsRect rect = QgsRect(),
|
||||||
int featuresInRectangle(const QgsRect& searchRect, QList<QgsFeature>& features /Out/, bool fetchGeometries = true, bool fetchAttributes = true);
|
bool fetchGeometry = true);
|
||||||
|
|
||||||
/**Gets the feature at the given feature id. Considers the changed, added, deleted and permanent features
|
bool getNextFeature(QgsFeature& feature);
|
||||||
|
|
||||||
|
|
||||||
|
/**Gets the feature at the given feature id. Considers the changed, added, deleted and permanent features
|
||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
int getFeatureAtId(int featureId, QgsFeature& f, bool fetchGeometries = true, bool fetchAttributes = true);
|
int getFeatureAtId(int featureId, QgsFeature& f, bool fetchGeometries = true, bool fetchAttributes = true);
|
||||||
|
|
||||||
/** Adds a feature
|
/** Adds a feature
|
||||||
@param lastFeatureInBatch If True, will also go to the effort of e.g. updating the extents.
|
@param alsoUpdateExtent If True, will also go to the effort of e.g. updating the extents.
|
||||||
@return Irue in case of success and False in case of error
|
@return True in case of success and False in case of error
|
||||||
*/
|
*/
|
||||||
bool addFeature(QgsFeature& f, bool alsoUpdateExtent = TRUE);
|
bool addFeature(QgsFeature& f, bool alsoUpdateExtent = TRUE);
|
||||||
|
|
||||||
@ -168,49 +182,60 @@ public:
|
|||||||
bool deleteSelectedFeatures();
|
bool deleteSelectedFeatures();
|
||||||
|
|
||||||
/**Adds a ring to polygon/multipolygon features
|
/**Adds a ring to polygon/multipolygon features
|
||||||
@return 0 in case of success, 1 problem with feature type, 2 ring not closed, 3 ring not valid, 4 ring crosses \
|
@return
|
||||||
existing rings, 5 no feature found where ring can be inserted*/
|
0 in case of success,
|
||||||
|
1 problem with feature type,
|
||||||
|
2 ring not closed,
|
||||||
|
3 ring not valid,
|
||||||
|
4 ring crosses existing rings,
|
||||||
|
5 no feature found where ring can be inserted*/
|
||||||
int addRing(const QList<QgsPoint>& ring);
|
int addRing(const QList<QgsPoint>& ring);
|
||||||
|
|
||||||
/**Adds a new island polygon to a multipolygon feature
|
/**Adds a new island polygon to a multipolygon feature
|
||||||
@return 0 in case of success, 1 if selected feature is not multipolygon, 2 if ring is not a valid geometry, \
|
@return
|
||||||
3 if new polygon ring not disjoint with existing rings, 4 if no feature was selected, 5 if several features are selected, \
|
0 in case of success,
|
||||||
6 if selected geometry not found*/
|
1 if selected feature is not multipolygon,
|
||||||
|
2 if ring is not a valid geometry,
|
||||||
|
3 if new polygon ring not disjoint with existing rings,
|
||||||
|
4 if no feature was selected,
|
||||||
|
5 if several features are selected,
|
||||||
|
6 if selected geometry not found*/
|
||||||
int addIsland(const QList<QgsPoint>& ring);
|
int addIsland(const QList<QgsPoint>& ring);
|
||||||
|
|
||||||
/**Translates feature by dx, dy
|
/**Translates feature by dx, dy
|
||||||
@param featureId id of the feature to translate
|
@param featureId id of the feature to translate
|
||||||
@param dx translation of x-coordinate
|
@param dx translation of x-coordinate
|
||||||
@param dy translation of y-coordinate
|
@param dy translation of y-coordinate
|
||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
int translateFeature(int featureId, double dx, double dy);
|
int translateFeature(int featureId, double dx, double dy);
|
||||||
|
|
||||||
/**Splits features cut by the given line
|
/**Splits features cut by the given line
|
||||||
@param splitLine line that splits the layer features
|
@param splitLine line that splits the layer features
|
||||||
@param topologicalEditing true if topological editing is enabled
|
@param topologicalEditing true if topological editing is enabled
|
||||||
@return 0 in case of success, 1 if several intersections but only 1 split done, \
|
@return
|
||||||
2 if intersection too complex to be handled, else other error*/
|
0 in case of success,
|
||||||
|
1 if several intersections but only 1 split done,
|
||||||
|
2 if intersection too complex to be handled, else other error*/
|
||||||
int splitFeatures(const QList<QgsPoint>& splitLine, bool topologicalEditing = false);
|
int splitFeatures(const QList<QgsPoint>& splitLine, bool topologicalEditing = false);
|
||||||
|
|
||||||
/**Changes the specified geometry such that it has no intersections with other \
|
/**Changes the specified geometry such that it has no intersections with other \
|
||||||
polygon (or multipolygon) geometries in this vector layer
|
polygon (or multipolygon) geometries in this vector layer
|
||||||
@param geom geometry to modify
|
@param geom geometry to modify
|
||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
int removePolygonIntersections(QgsGeometry* geom);
|
int removePolygonIntersections(QgsGeometry* geom);
|
||||||
|
|
||||||
/**Adds topological points for every vertex of the
|
/**Adds topological points for every vertex of the geometry
|
||||||
geometry
|
@param geom the geometry where each vertex is added to segments of other features
|
||||||
@param geom the geometry where each vertex is added to segments of other features
|
Note: geom is not going to be modified by the function
|
||||||
Note: geom is not going to be modified by the function
|
@return 0 in case of success*/
|
||||||
@return 0 in case of success*/
|
|
||||||
int addTopologicalPoints(QgsGeometry* geom);
|
int addTopologicalPoints(QgsGeometry* geom);
|
||||||
|
|
||||||
/**Adds a vertex to segments which intersect point p but don't
|
/**Adds a vertex to segments which intersect point p but don't
|
||||||
already have a vertex there. If a feature already has a vertex at position p,
|
already have a vertex there. If a feature already has a vertex at position p,
|
||||||
no additional vertex is inserted. This method is usefull for topological
|
no additional vertex is inserted. This method is usefull for topological
|
||||||
editing.
|
editing.
|
||||||
@param p position of the vertex
|
@param p position of the vertex
|
||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
int addTopologicalPoints(const QgsPoint& p);
|
int addTopologicalPoints(const QgsPoint& p);
|
||||||
|
|
||||||
/**Inserts vertices to the snapped segments.
|
/**Inserts vertices to the snapped segments.
|
||||||
@ -246,29 +271,7 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
@return 0 in case of success
|
@return 0 in case of success
|
||||||
*/
|
*/
|
||||||
int snapWithContext(const QgsPoint& startPoint, double snappingTolerance, QMultiMap<double, QgsSnappingResult>& snappingResults /Out/,
|
int snapWithContext(const QgsPoint& startPoint, double snappingTolerance, QMultiMap<double, QgsSnappingResult>& snappingResults /Out/,
|
||||||
QgsSnapper::SNAP_TO snap_to);
|
QgsSnapper::SNAP_TO snap_to);
|
||||||
|
|
||||||
/**
|
|
||||||
Commits edited attributes. Depending on the feature id,
|
|
||||||
the changes are written to not commited features or redirected to
|
|
||||||
the data provider
|
|
||||||
|
|
||||||
The commits (in this version) occur in three distinct stages,
|
|
||||||
(delete attributes, add attributes, change attribute values)
|
|
||||||
so if a stage fails, it's difficult to roll back cleanly.
|
|
||||||
|
|
||||||
\todo Need to indicate at which stage the failed commit occurred,
|
|
||||||
for better cleanup and recovery from the error.
|
|
||||||
|
|
||||||
\param deleted Set of attribute indices (i.e. columns) to delete
|
|
||||||
\param added Map (name, type) of attribute names (i.e. columns) to add
|
|
||||||
\param changed Map (feature ID, Map (attribute name, new value) )
|
|
||||||
of attribute values to change
|
|
||||||
|
|
||||||
*/
|
|
||||||
bool commitAttributeChanges(const QSet<int>& deleted,
|
|
||||||
const QMap<QString, QString>& added,
|
|
||||||
const QMap<int, QMap<int, QVariant> >& changed);
|
|
||||||
|
|
||||||
/** Draws the layer using coordinate transformation
|
/** Draws the layer using coordinate transformation
|
||||||
* @return FALSE if an error occurred during drawing
|
* @return FALSE if an error occurred during drawing
|
||||||
@ -283,20 +286,36 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
*/
|
*/
|
||||||
void drawLabels(QPainter * p, const QgsRect& viewExtent, const QgsMapToPixel* cXf, const QgsCoordinateTransform* ct, double scale);
|
void drawLabels(QPainter * p, const QgsRect& viewExtent, const QgsMapToPixel* cXf, const QgsCoordinateTransform* ct, double scale);
|
||||||
|
|
||||||
/** returns array of added features */
|
/** returns list of attributes */
|
||||||
QList<QgsFeature>& addedFeatures();
|
QList<int> pendingAllAttributesList();
|
||||||
|
|
||||||
/** returns array of deleted feature IDs */
|
/** returns fields list which are not commited */
|
||||||
QSet<int>& deletedFeatureIds();
|
const QMap<int, QgsField> &pendingFields();
|
||||||
|
|
||||||
/** returns array of features with changed attributes */
|
|
||||||
QMap<int, QMap<int, QVariant> >& changedAttributes();
|
|
||||||
|
|
||||||
|
/** returns feature count after commit */
|
||||||
|
int pendingFeatureCount();
|
||||||
|
|
||||||
/** Sets whether some features are modified or not */
|
/** Sets whether some features are modified or not */
|
||||||
void setModified(bool modified = TRUE, bool onlyGeometryWasModified = FALSE);
|
void setModified(bool modified = TRUE, bool onlyGeometryWasModified = FALSE);
|
||||||
|
|
||||||
/** Make layer editable */
|
/** Make layer editable */
|
||||||
bool startEditing();
|
bool startEditing();
|
||||||
|
|
||||||
|
/** changed an attribute value (but does not commit it */
|
||||||
|
bool changeAttributeValue(int fid, int field, QVariant value, bool emitSignal = true);
|
||||||
|
|
||||||
|
/** add an attribute field (but does not commit it)
|
||||||
|
returns the field index or -1 in case of failure */
|
||||||
|
bool addAttribute(QString name, QString type);
|
||||||
|
|
||||||
|
/** delete an attribute field (but does not commit it) */
|
||||||
|
bool deleteAttribute(int attr);
|
||||||
|
|
||||||
|
/** Insert a copy of the given features into the layer (but does not commit it) */
|
||||||
|
bool addFeatures(QList<QgsFeature> features, bool makeSelected = TRUE);
|
||||||
|
|
||||||
|
/** delete a feature from the layer (but does not commit it) */
|
||||||
|
bool deleteFeature(int fid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Attempts to commit any changes to disk. Returns the result of the attempt.
|
Attempts to commit any changes to disk. Returns the result of the attempt.
|
||||||
@ -314,10 +333,23 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
bool commitChanges();
|
bool commitChanges();
|
||||||
|
const QStringList &commitErrors();
|
||||||
|
|
||||||
/** Stop editing and discard the edits */
|
/** Stop editing and discard the edits */
|
||||||
bool rollBack();
|
bool rollBack();
|
||||||
|
|
||||||
|
/**get edit type*/
|
||||||
|
EditType editType(int idx);
|
||||||
|
|
||||||
|
/**set edit type*/
|
||||||
|
void setEditType(int idx, EditType edit);
|
||||||
|
|
||||||
|
/**access value map*/
|
||||||
|
QMap<QString, QVariant> &valueMap(int idx);
|
||||||
|
|
||||||
|
/**access range */
|
||||||
|
RangeData &range(int idx);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
/** Select feature by its ID, optionally emit signal selectionChanged() */
|
/** Select feature by its ID, optionally emit signal selectionChanged() */
|
||||||
@ -341,6 +373,15 @@ signals:
|
|||||||
/** This signal is emitted when modifications has been done on layer */
|
/** This signal is emitted when modifications has been done on layer */
|
||||||
void wasModified(bool onlyGeometry);
|
void wasModified(bool onlyGeometry);
|
||||||
|
|
||||||
|
void editingStarted();
|
||||||
|
void editingStopped();
|
||||||
|
void attributeAdded(int idx);
|
||||||
|
void attributeDeleted(int idx);
|
||||||
|
void featureDeleted(int fid);
|
||||||
|
void layerDeleted();
|
||||||
|
|
||||||
|
void attributeValueChanged(int fid, int idx, const QVariant &);
|
||||||
|
|
||||||
private: // Private methods
|
private: // Private methods
|
||||||
|
|
||||||
/** vector layers are not copyable */
|
/** vector layers are not copyable */
|
||||||
|
@ -36,9 +36,8 @@
|
|||||||
#include "qgsproject.h"
|
#include "qgsproject.h"
|
||||||
#include "qgsrasterlayer.h"
|
#include "qgsrasterlayer.h"
|
||||||
#include "qgsrasterlayerproperties.h"
|
#include "qgsrasterlayerproperties.h"
|
||||||
#include "qgsvectorlayer.h"
|
|
||||||
#include "qgsvectorlayerproperties.h"
|
#include "qgsvectorlayerproperties.h"
|
||||||
#include "qgsvectordataprovider.h"
|
#include "qgsattributetabledisplay.h"
|
||||||
|
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -1811,29 +1810,39 @@ void QgsLegend::legendLayerZoomNative()
|
|||||||
void QgsLegend::legendLayerAttributeTable()
|
void QgsLegend::legendLayerAttributeTable()
|
||||||
{
|
{
|
||||||
if(!mMapCanvas || mMapCanvas->isDrawing())
|
if(!mMapCanvas || mMapCanvas->isDrawing())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsVectorLayer *vlayer = 0;
|
||||||
|
|
||||||
// try whether it's a legend layer
|
// try whether it's a legend layer
|
||||||
QgsLegendLayer* ll = dynamic_cast<QgsLegendLayer*>(currentItem());
|
QgsLegendLayer* ll = dynamic_cast<QgsLegendLayer*>(currentItem());
|
||||||
if (ll)
|
if (ll)
|
||||||
{
|
{
|
||||||
ll->table();
|
vlayer = dynamic_cast<QgsVectorLayer*>(ll->firstMapLayer());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// try whether it's a legend layer file
|
if(!vlayer) {
|
||||||
QgsLegendLayerFile* llf = dynamic_cast<QgsLegendLayerFile*>(currentItem());
|
// try whether it's a legend layer file
|
||||||
if (llf)
|
QgsLegendLayerFile* llf = dynamic_cast<QgsLegendLayerFile*>(currentItem());
|
||||||
{
|
if (llf)
|
||||||
llf->table();
|
{
|
||||||
return;
|
vlayer = dynamic_cast<QgsVectorLayer*>(llf->layer());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing selected
|
if(vlayer)
|
||||||
QMessageBox::information(this, tr("No Layer Selected"),
|
{
|
||||||
tr("To open an attribute table, you must select a vector layer in the legend"));
|
QgsAttributeTableDisplay::attributeTable( vlayer );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// nothing selected
|
||||||
|
QMessageBox::information(this,
|
||||||
|
tr("No Layer Selected"),
|
||||||
|
tr("To open an attribute table, you must select a vector layer in the legend"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLegend::readProject(const QDomDocument & doc)
|
void QgsLegend::readProject(const QDomDocument & doc)
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
|
|
||||||
QgsLegendLayerFile::QgsLegendLayerFile(QTreeWidgetItem * theLegendItem, QString theString, QgsMapLayer* theLayer)
|
QgsLegendLayerFile::QgsLegendLayerFile(QTreeWidgetItem * theLegendItem, QString theString, QgsMapLayer* theLayer)
|
||||||
: QgsLegendItem(theLegendItem, theString), mLyr(theLayer), mTableDisplay(NULL)
|
: QgsLegendItem(theLegendItem, theString), mLyr(theLayer)
|
||||||
{
|
{
|
||||||
// Set the initial visibility flag for layers
|
// Set the initial visibility flag for layers
|
||||||
// This user option allows the user to turn off inital drawing of
|
// This user option allows the user to turn off inital drawing of
|
||||||
@ -69,23 +69,12 @@ QgsLegendLayerFile::QgsLegendLayerFile(QTreeWidgetItem * theLegendItem, QString
|
|||||||
QgsVectorLayer *isVectLyr = dynamic_cast < QgsVectorLayer * >(currentLayer);
|
QgsVectorLayer *isVectLyr = dynamic_cast < QgsVectorLayer * >(currentLayer);
|
||||||
if (isVectLyr)
|
if (isVectLyr)
|
||||||
{
|
{
|
||||||
// get notifications of changed selection - used to update attribute table
|
connect(mLyr.layer(), SIGNAL(editingStarted()), this, SLOT(updateLegendItem()));
|
||||||
connect(mLyr.layer(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
|
connect(mLyr.layer(), SIGNAL(editingStopped()), this, SLOT(updateLegendItem()));
|
||||||
// get notifications of modified layer - used to close table as it's out of sync
|
|
||||||
connect(mLyr.layer(), SIGNAL(wasModified(bool)), this, SLOT(closeTable(bool)));
|
|
||||||
}
|
}
|
||||||
connect(mLyr.layer(), SIGNAL(layerNameChanged()), this, SLOT(layerNameChanged()));
|
connect(mLyr.layer(), SIGNAL(layerNameChanged()), this, SLOT(layerNameChanged()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsLegendLayerFile::~QgsLegendLayerFile()
|
|
||||||
{
|
|
||||||
if (mTableDisplay)
|
|
||||||
{
|
|
||||||
mTableDisplay->close();
|
|
||||||
delete mTableDisplay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsLegendItem::DRAG_ACTION QgsLegendLayerFile::accept(LEGEND_ITEM_TYPE type)
|
QgsLegendItem::DRAG_ACTION QgsLegendLayerFile::accept(LEGEND_ITEM_TYPE type)
|
||||||
{
|
{
|
||||||
return NO_ACTION;
|
return NO_ACTION;
|
||||||
@ -219,112 +208,16 @@ void QgsLegendLayerFile::showInOverview()
|
|||||||
legend()->updateOverview();
|
legend()->updateOverview();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsLegendLayerFile::table()
|
|
||||||
{
|
|
||||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(mLyr.layer());
|
|
||||||
if (!vlayer)
|
|
||||||
{
|
|
||||||
QMessageBox::information(0, tr("Not a vector layer"),
|
|
||||||
tr("To open an attribute table, you must select a vector layer in the legend"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsAttributeAction& actions = *vlayer->actions();
|
|
||||||
|
|
||||||
if (mTableDisplay)
|
|
||||||
{
|
|
||||||
|
|
||||||
mTableDisplay->raise();
|
|
||||||
|
|
||||||
// Give the table the most recent copy of the actions for this layer.
|
|
||||||
mTableDisplay->table()->setAttributeActions(actions);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// display the attribute table
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
|
|
||||||
// TODO: pointer to QgisApp should be passed instead of NULL
|
|
||||||
// but we don't have pointer to it. [MD]
|
|
||||||
// but be can get it using this ugly hack. [jef]
|
|
||||||
// TODO: do this cleanly
|
|
||||||
QgisApp *app = NULL;
|
|
||||||
|
|
||||||
QList<QWidget *> list = QApplication::topLevelWidgets();
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i=0; i<list.size(); i++)
|
|
||||||
if( list[i]->windowTitle().startsWith("Quantum GIS") )
|
|
||||||
{
|
|
||||||
app=reinterpret_cast<QgisApp*>(list[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mTableDisplay = new QgsAttributeTableDisplay(vlayer, app);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
mTableDisplay->table()->fillTable(vlayer);
|
|
||||||
}
|
|
||||||
catch(std::bad_alloc& ba)
|
|
||||||
{
|
|
||||||
Q_UNUSED(ba);
|
|
||||||
QMessageBox::critical(0, tr("bad_alloc exception"), tr("Filling the attribute table has been stopped because there was no more virtual memory left"));
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(mTableDisplay, SIGNAL(deleted()), this, SLOT(invalidateTableDisplay()));
|
|
||||||
|
|
||||||
mTableDisplay->setTitle(tr("Attribute table - ") + vlayer->name());
|
|
||||||
mTableDisplay->show();
|
|
||||||
|
|
||||||
// Give the table the most recent copy of the actions for this layer.
|
|
||||||
mTableDisplay->table()->setAttributeActions(actions);
|
|
||||||
|
|
||||||
// select rows which should be selected
|
|
||||||
selectionChanged();
|
|
||||||
|
|
||||||
// etablish the necessary connections between the table and the vector layer
|
|
||||||
connect(mTableDisplay->table(), SIGNAL(selected(int, bool)), mLyr.layer(), SLOT(select(int, bool)));
|
|
||||||
connect(mTableDisplay->table(), SIGNAL(selectionRemoved(bool)), mLyr.layer(), SLOT(removeSelection(bool)));
|
|
||||||
connect(mTableDisplay->table(), SIGNAL(repaintRequested()), mLyr.layer(), SLOT(triggerRepaint()));
|
|
||||||
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsLegendLayerFile::invalidateTableDisplay()
|
|
||||||
{
|
|
||||||
// from signal deleted() - table doesn't exist anymore, just erase our pointer
|
|
||||||
mTableDisplay = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsLegendLayerFile::selectionChanged()
|
|
||||||
{
|
|
||||||
if (!mTableDisplay)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(mLyr.layer());
|
|
||||||
const QgsFeatureIds& ids = vlayer->selectedFeaturesIds();
|
|
||||||
mTableDisplay->table()->selectRowsWithId(ids);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsLegendLayerFile::closeTable(bool onlyGeometryWasChanged)
|
|
||||||
{
|
|
||||||
if (mTableDisplay)
|
|
||||||
{
|
|
||||||
mTableDisplay->close();
|
|
||||||
delete mTableDisplay;
|
|
||||||
mTableDisplay = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsLegendLayerFile::saveAsShapefile()
|
void QgsLegendLayerFile::saveAsShapefile()
|
||||||
{
|
{
|
||||||
saveAsShapefileGeneral(FALSE);
|
saveAsShapefileGeneral(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsLegendLayerFile::table()
|
||||||
|
{
|
||||||
|
QgsAttributeTableDisplay::attributeTable( dynamic_cast<QgsVectorLayer*>(mLyr.layer()) );
|
||||||
|
}
|
||||||
|
|
||||||
void QgsLegendLayerFile::saveSelectionAsShapefile()
|
void QgsLegendLayerFile::saveSelectionAsShapefile()
|
||||||
{
|
{
|
||||||
saveAsShapefileGeneral(TRUE);
|
saveAsShapefileGeneral(TRUE);
|
||||||
@ -413,69 +306,6 @@ void QgsLegendLayerFile::saveAsShapefileGeneral(bool saveOnlySelection)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsLegendLayerFile::toggleEditing()
|
|
||||||
{
|
|
||||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(mLyr.layer());
|
|
||||||
if (!vlayer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!vlayer->isEditable())
|
|
||||||
{
|
|
||||||
vlayer->startEditing();
|
|
||||||
if(!(vlayer->getDataProvider()->capabilities() & QgsVectorDataProvider::AddFeatures))
|
|
||||||
{
|
|
||||||
QMessageBox::information(0,tr("Start editing failed"),
|
|
||||||
tr("Provider cannot be opened for editing"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vlayer->triggerRepaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(vlayer->isModified())
|
|
||||||
{
|
|
||||||
|
|
||||||
// commit or roll back?
|
|
||||||
QMessageBox::StandardButton commit = QMessageBox::information(0,tr("Stop editing"), tr("Do you want to save the changes?"), QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
|
||||||
|
|
||||||
if(commit==QMessageBox::Save)
|
|
||||||
{
|
|
||||||
if(!vlayer->commitChanges())
|
|
||||||
{
|
|
||||||
QMessageBox::information(0,tr("Error"),tr("Could not commit changes"));
|
|
||||||
|
|
||||||
// Leave the in-memory editing state alone,
|
|
||||||
// to give the user a chance to enter different values
|
|
||||||
// and try the commit again later
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(commit==QMessageBox::Discard)
|
|
||||||
{
|
|
||||||
if(!vlayer->rollBack())
|
|
||||||
{
|
|
||||||
QMessageBox::information(0,tr("Error"),
|
|
||||||
tr("Problems during roll back"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //cancel
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //layer not modified
|
|
||||||
{
|
|
||||||
vlayer->rollBack();
|
|
||||||
}
|
|
||||||
vlayer->triggerRepaint();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLegendItem();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QgsLegendLayerFile::isEditing()
|
bool QgsLegendLayerFile::isEditing()
|
||||||
{
|
{
|
||||||
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(mLyr.layer());
|
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(mLyr.layer());
|
||||||
@ -491,7 +321,6 @@ void QgsLegendLayerFile::layerNameChanged()
|
|||||||
legend()->setName(this, name);
|
legend()->setName(this, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsLegendLayerFile::addToPopupMenu(QMenu& theMenu, QAction* toggleEditingAction)
|
void QgsLegendLayerFile::addToPopupMenu(QMenu& theMenu, QAction* toggleEditingAction)
|
||||||
{
|
{
|
||||||
QgsMapLayer* lyr = layer();
|
QgsMapLayer* lyr = layer();
|
||||||
@ -526,9 +355,9 @@ void QgsLegendLayerFile::addToPopupMenu(QMenu& theMenu, QAction* toggleEditingAc
|
|||||||
||(cap & QgsVectorDataProvider::DeleteFeatures))
|
||(cap & QgsVectorDataProvider::DeleteFeatures))
|
||||||
{
|
{
|
||||||
if(toggleEditingAction)
|
if(toggleEditingAction)
|
||||||
{
|
{
|
||||||
theMenu.addAction(toggleEditingAction);
|
theMenu.addAction(toggleEditingAction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// save as shapefile
|
// save as shapefile
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2005 by Tim Sutton *
|
* Copyright (C) 2005 by Tim Sutton *
|
||||||
* aps02ts@macbuntu *
|
* aps02ts@macbuntu *
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* 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 *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
@ -26,7 +26,6 @@
|
|||||||
#include "qgsmapcanvas.h"
|
#include "qgsmapcanvas.h"
|
||||||
|
|
||||||
class QgsMapLayer;
|
class QgsMapLayer;
|
||||||
class QgsAttributeTableDisplay;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@author Tim Sutton
|
@author Tim Sutton
|
||||||
@ -37,7 +36,7 @@ class QgsLegendLayerFile : public QgsLegendItem
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
QgsLegendLayerFile(QTreeWidgetItem * theLegendItem, QString theString, QgsMapLayer* theLayer);
|
QgsLegendLayerFile(QTreeWidgetItem * theLegendItem, QString theString, QgsMapLayer* theLayer);
|
||||||
~QgsLegendLayerFile();
|
|
||||||
bool isLeafNode() {return true;}
|
bool isLeafNode() {return true;}
|
||||||
DRAG_ACTION accept(LEGEND_ITEM_TYPE type);
|
DRAG_ACTION accept(LEGEND_ITEM_TYPE type);
|
||||||
QgsLegendItem::DRAG_ACTION accept(const QgsLegendItem* li) const;
|
QgsLegendItem::DRAG_ACTION accept(const QgsLegendItem* li) const;
|
||||||
@ -47,16 +46,12 @@ public:
|
|||||||
|
|
||||||
QPixmap getOriginalPixmap() const;
|
QPixmap getOriginalPixmap() const;
|
||||||
|
|
||||||
/** updates item to the current state of the layer */
|
|
||||||
void updateLegendItem();
|
|
||||||
|
|
||||||
void setIconAppearance(bool inOverview, bool editable);
|
void setIconAppearance(bool inOverview, bool editable);
|
||||||
|
|
||||||
/**Returns a label for a layer. Is static such that
|
/**Returns a label for a layer. Is static such that
|
||||||
the name can be passed to the constructor of QgsLegendLayerFile*/
|
the name can be passed to the constructor of QgsLegendLayerFile*/
|
||||||
static QString nameFromLayer(QgsMapLayer* layer);
|
static QString nameFromLayer(QgsMapLayer* layer);
|
||||||
|
|
||||||
|
|
||||||
void setVisible(bool visible = TRUE);
|
void setVisible(bool visible = TRUE);
|
||||||
bool isVisible();
|
bool isVisible();
|
||||||
|
|
||||||
@ -67,28 +62,18 @@ public:
|
|||||||
void addToPopupMenu(QMenu& theMenu, QAction* toggleEditingAction);
|
void addToPopupMenu(QMenu& theMenu, QAction* toggleEditingAction);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/** updates item to the current state of the layer */
|
||||||
|
void updateLegendItem();
|
||||||
|
|
||||||
/**Open attribute table*/
|
/**Open attribute table*/
|
||||||
void table();
|
void table();
|
||||||
|
|
||||||
/**Connected to deleted() signal of attribute table*/
|
|
||||||
void invalidateTableDisplay();
|
|
||||||
|
|
||||||
/**Connected to layer's selectionChanged() */
|
|
||||||
void selectionChanged();
|
|
||||||
|
|
||||||
/**Connected to layer's wasModified() */
|
|
||||||
void closeTable(bool onlyGeometryWasChanged);
|
|
||||||
|
|
||||||
/**Save as shapefile*/
|
/**Save as shapefile*/
|
||||||
void saveAsShapefile();
|
void saveAsShapefile();
|
||||||
|
|
||||||
/**Save selection as shapefile*/
|
/**Save selection as shapefile*/
|
||||||
void saveSelectionAsShapefile();
|
void saveSelectionAsShapefile();
|
||||||
|
|
||||||
/**Toggle editing for layer*/
|
|
||||||
void toggleEditing();
|
|
||||||
|
|
||||||
/**Return editing status for layer*/
|
/**Return editing status for layer*/
|
||||||
bool isEditing();
|
bool isEditing();
|
||||||
|
|
||||||
@ -97,7 +82,7 @@ public:
|
|||||||
|
|
||||||
/**Layer name has changed - set it also in legend*/
|
/**Layer name has changed - set it also in legend*/
|
||||||
void layerNameChanged();
|
void layerNameChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**Save as shapefile (called from saveAsShapefile and saveSelectionAsShapefile)*/
|
/**Save as shapefile (called from saveAsShapefile and saveSelectionAsShapefile)*/
|
||||||
@ -105,10 +90,6 @@ public:
|
|||||||
|
|
||||||
/** layer identified by its layer id */
|
/** layer identified by its layer id */
|
||||||
QgsMapCanvasLayer mLyr;
|
QgsMapCanvasLayer mLyr;
|
||||||
|
|
||||||
/** Pointer to the table display object if there is one, otherwise NULL */
|
|
||||||
QgsAttributeTableDisplay* mTableDisplay;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -156,25 +156,20 @@ OSErr openDocumentsAEHandler(const AppleEvent *event, AppleEvent *reply, SRefCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open files now if application has been initialized
|
QgisApp *qgis = QgisApp::instance();
|
||||||
QWidgetList wl = QApplication::topLevelWidgets();
|
if(qgis)
|
||||||
for (QWidgetList::iterator it = wl.begin(); it != wl.end(); ++it)
|
|
||||||
{
|
{
|
||||||
QgisApp *qgis = dynamic_cast<QgisApp *>(*it);
|
if (!myProjectFileName.isEmpty())
|
||||||
if (qgis && qgis->objectName() == "QgisApp")
|
|
||||||
{
|
{
|
||||||
if (!myProjectFileName.isEmpty())
|
qgis->openProject(myProjectFileName);
|
||||||
{
|
|
||||||
qgis->openProject(myProjectFileName);
|
|
||||||
}
|
|
||||||
for (QStringList::Iterator myIterator = myFileList.begin();
|
|
||||||
myIterator != myFileList.end(); ++myIterator )
|
|
||||||
{
|
|
||||||
QString fileName = *myIterator;
|
|
||||||
qgis->openLayer(fileName);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
for (QStringList::Iterator myIterator = myFileList.begin();
|
||||||
|
myIterator != myFileList.end(); ++myIterator )
|
||||||
|
{
|
||||||
|
QString fileName = *myIterator;
|
||||||
|
qgis->openLayer(fileName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return noErr;
|
return noErr;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -163,6 +163,9 @@ class QgisApp : public QMainWindow
|
|||||||
* (as documented in Qt documentation.
|
* (as documented in Qt documentation.
|
||||||
*/
|
*/
|
||||||
void setupProxy();
|
void setupProxy();
|
||||||
|
|
||||||
|
static QgisApp *instance() { return smInstance; }
|
||||||
|
|
||||||
//! Helper to get a theme icon. It will fall back to the
|
//! Helper to get a theme icon. It will fall back to the
|
||||||
//default theme if the active theme does not have the required
|
//default theme if the active theme does not have the required
|
||||||
//icon.
|
//icon.
|
||||||
@ -320,6 +323,7 @@ public slots:
|
|||||||
void refreshMapCanvas();
|
void refreshMapCanvas();
|
||||||
//! returns pointer to map legend
|
//! returns pointer to map legend
|
||||||
QgsLegend *legend() { return mMapLegend; }
|
QgsLegend *legend() { return mMapLegend; }
|
||||||
|
|
||||||
//! starts/stops editing mode of the current layer
|
//! starts/stops editing mode of the current layer
|
||||||
void toggleEditing();
|
void toggleEditing();
|
||||||
|
|
||||||
@ -330,7 +334,6 @@ public slots:
|
|||||||
Is called from the legend when the current legend item has changed*/
|
Is called from the legend when the current legend item has changed*/
|
||||||
void activateDeactivateLayerRelatedActions(QgsMapLayer* layer);
|
void activateDeactivateLayerRelatedActions(QgsMapLayer* layer);
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/** Add a dock widget to the main window. Overloaded from QMainWindow.
|
/** Add a dock widget to the main window. Overloaded from QMainWindow.
|
||||||
* After adding the dock widget to the ui (by delegating to the QMainWindow
|
* After adding the dock widget to the ui (by delegating to the QMainWindow
|
||||||
@ -368,9 +371,13 @@ public slots:
|
|||||||
void measure();
|
void measure();
|
||||||
//! Measure area
|
//! Measure area
|
||||||
void measureArea();
|
void measureArea();
|
||||||
|
|
||||||
//! show the attribute table for the currently selected layer
|
//! show the attribute table for the currently selected layer
|
||||||
void attributeTable();
|
void attributeTable();
|
||||||
|
|
||||||
|
//! starts/stops editing mode of a layer
|
||||||
|
void toggleEditing(QgsMapLayer *layer);
|
||||||
|
|
||||||
//! show python console
|
//! show python console
|
||||||
void showPythonDialog();
|
void showPythonDialog();
|
||||||
|
|
||||||
@ -644,8 +651,6 @@ class Tools
|
|||||||
QString mStartupPath;
|
QString mStartupPath;
|
||||||
//! full path name of the current map file (if it has been saved or loaded)
|
//! full path name of the current map file (if it has been saved or loaded)
|
||||||
QString mFullPathName;
|
QString mFullPathName;
|
||||||
//! A dock to show the attribute table (user optional)
|
|
||||||
QPointer<QDockWidget> mpTableDockWidget;
|
|
||||||
|
|
||||||
//! interface to QgisApp for plugins
|
//! interface to QgisApp for plugins
|
||||||
QgisAppInterface *mQgisInterface;
|
QgisAppInterface *mQgisInterface;
|
||||||
@ -697,6 +702,8 @@ class Tools
|
|||||||
bool mFullScreenMode;
|
bool mFullScreenMode;
|
||||||
QgsPythonDialog* mPythonConsole;
|
QgsPythonDialog* mPythonConsole;
|
||||||
QgsPythonUtils* mPythonUtils;
|
QgsPythonUtils* mPythonUtils;
|
||||||
|
|
||||||
|
static QgisApp *smInstance;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,34 +21,34 @@
|
|||||||
QgsAddAttrDialog::QgsAddAttrDialog(QgsVectorDataProvider* provider, QWidget *parent, Qt::WFlags fl)
|
QgsAddAttrDialog::QgsAddAttrDialog(QgsVectorDataProvider* provider, QWidget *parent, Qt::WFlags fl)
|
||||||
: QDialog(parent, fl), mDataProvider(provider)
|
: QDialog(parent, fl), mDataProvider(provider)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
//fill data types into the combo box
|
//fill data types into the combo box
|
||||||
const QSet<QString>& typelist=mDataProvider->supportedNativeTypes();
|
const QgsNativeTypeMap &typelist=mDataProvider->supportedNativeTypes();
|
||||||
|
|
||||||
for(QSet<QString>::const_iterator it = typelist.constBegin(); it != typelist.constEnd(); ++it)
|
for(QgsNativeTypeMap::const_iterator it = typelist.constBegin(); it != typelist.constEnd(); ++it)
|
||||||
{
|
{
|
||||||
mTypeBox->addItem(*it);
|
mTypeBox->addItem(it.key());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsAddAttrDialog::QgsAddAttrDialog(const std::list<QString>& typelist, QWidget *parent, Qt::WFlags fl)
|
QgsAddAttrDialog::QgsAddAttrDialog(const std::list<QString>& typelist, QWidget *parent, Qt::WFlags fl)
|
||||||
: QDialog(parent, fl), mDataProvider(0)
|
: QDialog(parent, fl), mDataProvider(0)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
for(std::list<QString>::const_iterator iter=typelist.begin();iter!=typelist.end();++iter)
|
for(std::list<QString>::const_iterator iter=typelist.begin();iter!=typelist.end();++iter)
|
||||||
{
|
{
|
||||||
mTypeBox->addItem(*iter);
|
mTypeBox->addItem(*iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsAddAttrDialog::name() const
|
QString QgsAddAttrDialog::name() const
|
||||||
{
|
{
|
||||||
return mNameEdit->text();
|
return mNameEdit->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsAddAttrDialog::type() const
|
QString QgsAddAttrDialog::type() const
|
||||||
{
|
{
|
||||||
return mTypeBox->currentText();
|
return mTypeBox->currentText();
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,6 @@ back to QgsVectorLayer.
|
|||||||
|
|
||||||
class QgsAttributeAction;
|
class QgsAttributeAction;
|
||||||
|
|
||||||
typedef QMap<int, QgsField> QgsFieldMap;
|
|
||||||
|
|
||||||
class QgsAttributeActionDialog: public QWidget, private Ui::QgsAttributeActionDialogBase
|
class QgsAttributeActionDialog: public QWidget, private Ui::QgsAttributeActionDialogBase
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
|
@ -31,8 +31,11 @@
|
|||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QScrollArea>
|
#include <QScrollArea>
|
||||||
|
#include <QCompleter>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
|
||||||
QgsAttributeDialog::QgsAttributeDialog(QgsVectorLayer *vl, QgsFeature * thepFeature)
|
QgsAttributeDialog::QgsAttributeDialog(QgsVectorLayer *vl, QgsFeature *thepFeature)
|
||||||
: QDialog(),
|
: QDialog(),
|
||||||
mSettingsPath("/Windows/AttributeDialog/"),
|
mSettingsPath("/Windows/AttributeDialog/"),
|
||||||
mpFeature(thepFeature),
|
mpFeature(thepFeature),
|
||||||
@ -67,7 +70,7 @@ QgsAttributeDialog::QgsAttributeDialog(QgsVectorLayer *vl, QgsFeature * thepFeat
|
|||||||
|
|
||||||
|
|
||||||
int classificationField = -1;
|
int classificationField = -1;
|
||||||
QStringList values;
|
QMap<QString,QString> classes;
|
||||||
|
|
||||||
const QgsUniqueValueRenderer *uvr = dynamic_cast<const QgsUniqueValueRenderer *>( mLayer->renderer() );
|
const QgsUniqueValueRenderer *uvr = dynamic_cast<const QgsUniqueValueRenderer *>( mLayer->renderer() );
|
||||||
if( uvr )
|
if( uvr )
|
||||||
@ -78,7 +81,13 @@ QgsAttributeDialog::QgsAttributeDialog(QgsVectorLayer *vl, QgsFeature * thepFeat
|
|||||||
|
|
||||||
for(int i=0; i<symbols.size(); i++)
|
for(int i=0; i<symbols.size(); i++)
|
||||||
{
|
{
|
||||||
values.append( symbols[i]->lowerValue() );
|
QString label = symbols[i]->label();
|
||||||
|
QString name = symbols[i]->lowerValue();
|
||||||
|
|
||||||
|
if(label=="")
|
||||||
|
label=name;
|
||||||
|
|
||||||
|
classes.insert(name, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,49 +96,135 @@ QgsAttributeDialog::QgsAttributeDialog(QgsVectorLayer *vl, QgsFeature * thepFeat
|
|||||||
it != myAttributes.end();
|
it != myAttributes.end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
QString myFieldName = theFieldMap[it.key()].name();
|
const QgsField &field = theFieldMap[it.key()];
|
||||||
int myFieldType = theFieldMap[it.key()].type();
|
QString myFieldName = field.name();
|
||||||
|
int myFieldType = field.type();
|
||||||
QLabel * mypLabel = new QLabel();
|
QLabel * mypLabel = new QLabel();
|
||||||
mypInnerLayout->addWidget(mypLabel,index,0);
|
mypInnerLayout->addWidget(mypLabel,index,0);
|
||||||
QVariant myFieldValue = it.value();
|
QVariant myFieldValue = it.value();
|
||||||
|
|
||||||
QWidget *myWidget;
|
QWidget *myWidget;
|
||||||
if(classificationField!=it.key())
|
|
||||||
|
QgsVectorLayer::EditType editType = vl->editType( it.key() );
|
||||||
|
|
||||||
|
switch( editType )
|
||||||
{
|
{
|
||||||
QLineEdit *le = new QLineEdit();
|
case QgsVectorLayer::Range:
|
||||||
|
|
||||||
//the provider may have provided a default value so use it
|
|
||||||
le->setText(myFieldValue.toString());
|
|
||||||
|
|
||||||
if( myFieldType==QVariant::Int )
|
|
||||||
{
|
{
|
||||||
le->setValidator( new QIntValidator(le) );
|
if( myFieldType==QVariant::Int )
|
||||||
|
{
|
||||||
|
int min = vl->range( it.key() ).mMin.toInt();
|
||||||
|
int max = vl->range( it.key() ).mMax.toInt();
|
||||||
|
int step = vl->range( it.key() ).mStep.toInt();
|
||||||
|
|
||||||
|
QSpinBox *sb = new QSpinBox();
|
||||||
|
sb->setMinimum(min);
|
||||||
|
sb->setMaximum(max);
|
||||||
|
sb->setSingleStep(step);
|
||||||
|
sb->setValue( it.value().toInt() );
|
||||||
|
|
||||||
|
myWidget = sb;
|
||||||
|
break;
|
||||||
|
} else if( myFieldType==QVariant::Double ) {
|
||||||
|
double min = vl->range( it.key() ).mMin.toDouble();
|
||||||
|
double max = vl->range( it.key() ).mMax.toDouble();
|
||||||
|
double step = vl->range( it.key() ).mStep.toDouble();
|
||||||
|
QDoubleSpinBox *dsb = new QDoubleSpinBox();
|
||||||
|
|
||||||
|
dsb->setMinimum(min);
|
||||||
|
dsb->setMaximum(max);
|
||||||
|
dsb->setSingleStep(step);
|
||||||
|
dsb->setValue( it.value().toDouble() );
|
||||||
|
|
||||||
|
myWidget = dsb;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if( myFieldType==QVariant::Double )
|
|
||||||
|
// fall-through
|
||||||
|
|
||||||
|
|
||||||
|
case QgsVectorLayer::LineEdit:
|
||||||
|
case QgsVectorLayer::UniqueValuesEditable:
|
||||||
{
|
{
|
||||||
le->setValidator( new QIntValidator(le) );
|
QLineEdit *le = new QLineEdit( myFieldValue.toString() );
|
||||||
|
|
||||||
|
if( editType == QgsVectorLayer::UniqueValuesEditable )
|
||||||
|
{
|
||||||
|
QStringList values;
|
||||||
|
mLayer->getDataProvider()->getUniqueValues(it.key(), values);
|
||||||
|
|
||||||
|
QCompleter *c = new QCompleter(values);
|
||||||
|
c->setCompletionMode(QCompleter::PopupCompletion);
|
||||||
|
le->setCompleter(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( myFieldType==QVariant::Int )
|
||||||
|
{
|
||||||
|
le->setValidator( new QIntValidator(le) );
|
||||||
|
}
|
||||||
|
else if( myFieldType==QVariant::Double )
|
||||||
|
{
|
||||||
|
le->setValidator( new QIntValidator(le) );
|
||||||
|
}
|
||||||
|
|
||||||
|
myWidget = le;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
myWidget = le;
|
case QgsVectorLayer::UniqueValues:
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QComboBox *cb = new QComboBox();
|
|
||||||
cb->addItems(values);
|
|
||||||
cb->setEditable(true);
|
|
||||||
|
|
||||||
//the provider may have provided a default value so use it
|
|
||||||
cb->setEditText(myFieldValue.toString());
|
|
||||||
|
|
||||||
if( myFieldType==QVariant::Int ) {
|
|
||||||
cb->setValidator( new QIntValidator(cb) );
|
|
||||||
}
|
|
||||||
else if( myFieldType==QVariant::Double )
|
|
||||||
{
|
{
|
||||||
cb->setValidator( new QIntValidator(cb) );
|
QStringList values;
|
||||||
}
|
mLayer->getDataProvider()->getUniqueValues(it.key(), values);
|
||||||
|
|
||||||
myWidget = cb;
|
QComboBox *cb = new QComboBox();
|
||||||
|
cb->setEditable(true);
|
||||||
|
cb->addItems(values);
|
||||||
|
|
||||||
|
int idx = cb->findText( myFieldValue.toString() );
|
||||||
|
if( idx>= 0 )
|
||||||
|
cb->setCurrentIndex( idx );
|
||||||
|
|
||||||
|
myWidget = cb;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QgsVectorLayer::ValueMap:
|
||||||
|
{
|
||||||
|
const QMap<QString,QVariant> &map = vl->valueMap( it.key() );
|
||||||
|
|
||||||
|
QComboBox *cb = new QComboBox();
|
||||||
|
|
||||||
|
for(QMap<QString,QVariant>::const_iterator it=map.begin(); it!=map.end(); it++)
|
||||||
|
{
|
||||||
|
cb->addItem( it.key(), it.value() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = cb->findData( myFieldValue );
|
||||||
|
if( idx>= 0 )
|
||||||
|
cb->setCurrentIndex( idx );
|
||||||
|
|
||||||
|
myWidget = cb;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QgsVectorLayer::Classification:
|
||||||
|
{
|
||||||
|
QComboBox *cb = new QComboBox();
|
||||||
|
for(QMap<QString,QString>::const_iterator it=classes.begin(); it!=classes.end(); it++)
|
||||||
|
{
|
||||||
|
cb->addItem( it.value(), it.key() );
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = cb->findData( myFieldValue );
|
||||||
|
if( idx>=0 )
|
||||||
|
cb->setCurrentIndex( idx );
|
||||||
|
|
||||||
|
myWidget = cb;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( myFieldType==QVariant::Int )
|
if( myFieldType==QVariant::Int )
|
||||||
@ -168,10 +263,9 @@ void QgsAttributeDialog::accept()
|
|||||||
it != myAttributes.end();
|
it != myAttributes.end();
|
||||||
++it)
|
++it)
|
||||||
{
|
{
|
||||||
const QgsFieldMap &theFieldMap = mLayer->getDataProvider()->fields();
|
const QgsField &theField = mLayer->pendingFields()[it.key()];
|
||||||
|
QgsVectorLayer::EditType editType = mLayer->editType( it.key() );
|
||||||
//Q_ASSERT(myIndex <= mpWidgets.size());
|
QString myFieldName = theField.name();
|
||||||
QString myFieldName = theFieldMap[it.key()].name();
|
|
||||||
bool myFlag=false;
|
bool myFlag=false;
|
||||||
QString myFieldValue;
|
QString myFieldValue;
|
||||||
|
|
||||||
@ -184,40 +278,62 @@ void QgsAttributeDialog::accept()
|
|||||||
QComboBox *cb = dynamic_cast<QComboBox *>(mpWidgets.value(myIndex));
|
QComboBox *cb = dynamic_cast<QComboBox *>(mpWidgets.value(myIndex));
|
||||||
if(cb)
|
if(cb)
|
||||||
{
|
{
|
||||||
myFieldValue = cb->currentText();
|
if( editType==QgsVectorLayer::UniqueValues ||
|
||||||
|
editType==QgsVectorLayer::ValueMap ||
|
||||||
|
editType==QgsVectorLayer::Classification)
|
||||||
|
{
|
||||||
|
myFieldValue = cb->itemData( cb->currentIndex() ).toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
myFieldValue = cb->currentText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( theFieldMap[it.key()].type() )
|
|
||||||
|
QSpinBox *sb = dynamic_cast<QSpinBox *>(mpWidgets.value(myIndex));
|
||||||
|
if(sb)
|
||||||
{
|
{
|
||||||
case QVariant::Int:
|
myFieldValue = QString::number(sb->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
QDoubleSpinBox *dsb = dynamic_cast<QDoubleSpinBox *>(mpWidgets.value(myIndex));
|
||||||
|
if(dsb)
|
||||||
|
{
|
||||||
|
myFieldValue = QString::number(dsb->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( theField.type() )
|
||||||
|
{
|
||||||
|
case QVariant::Int:
|
||||||
|
{
|
||||||
|
int myIntValue = myFieldValue.toInt(&myFlag);
|
||||||
|
if (myFlag && ! myFieldValue.isEmpty())
|
||||||
{
|
{
|
||||||
int myIntValue = myFieldValue.toInt(&myFlag);
|
mpFeature->changeAttribute( it.key(), QVariant(myIntValue) );
|
||||||
if (myFlag && ! myFieldValue.isEmpty())
|
|
||||||
{
|
|
||||||
mpFeature->changeAttribute( it.key(), QVariant(myIntValue) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mpFeature->changeAttribute( it.key(), QVariant(QString::null) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
case QVariant::Double:
|
|
||||||
{
|
{
|
||||||
double myDblValue = myFieldValue.toDouble(&myFlag);
|
mpFeature->changeAttribute( it.key(), QVariant(QString::null) );
|
||||||
if (myFlag && ! myFieldValue.isEmpty())
|
|
||||||
{
|
|
||||||
mpFeature->changeAttribute( it.key(), QVariant(myDblValue) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mpFeature->changeAttribute( it.key(), QVariant(QString::null) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
default: //string
|
break;
|
||||||
mpFeature->changeAttribute(it.key(),QVariant( myFieldValue ) );
|
case QVariant::Double:
|
||||||
break;
|
{
|
||||||
|
double myDblValue = myFieldValue.toDouble(&myFlag);
|
||||||
|
if (myFlag && ! myFieldValue.isEmpty())
|
||||||
|
{
|
||||||
|
mpFeature->changeAttribute( it.key(), QVariant(myDblValue) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mpFeature->changeAttribute( it.key(), QVariant(QString::null) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: //string
|
||||||
|
mpFeature->changeAttribute(it.key(),QVariant( myFieldValue ) );
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
++myIndex;
|
++myIndex;
|
||||||
}
|
}
|
||||||
@ -235,4 +351,3 @@ void QgsAttributeDialog::restoreGeometry()
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
QDialog::restoreGeometry(settings.value(mSettingsPath+"geometry").toByteArray());
|
QDialog::restoreGeometry(settings.value(mSettingsPath+"geometry").toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
#include <QValidator>
|
#include <QValidator>
|
||||||
|
|
||||||
#include "qgsattributetable.h"
|
#include "qgsattributetable.h"
|
||||||
#include "qgsfeature.h"
|
|
||||||
#include "qgsfield.h"
|
#include "qgsfield.h"
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
#include "qgsvectordataprovider.h"
|
#include "qgsvectordataprovider.h"
|
||||||
@ -33,31 +32,44 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
|
|
||||||
QgsAttributeTableItemDelegate::QgsAttributeTableItemDelegate(const QgsFieldMap & fields, QObject *parent)
|
QgsAttributeTableItemDelegate::QgsAttributeTableItemDelegate(QgsAttributeTable *table, QObject *parent)
|
||||||
: QItemDelegate(parent), mFields(fields)
|
: mTable(table), QItemDelegate(parent)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
QWidget * QgsAttributeTableItemDelegate::createEditor( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const
|
QWidget *QgsAttributeTableItemDelegate::createEditor(
|
||||||
|
QWidget *parent,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index ) const
|
||||||
{
|
{
|
||||||
QWidget *editor = QItemDelegate::createEditor(parent, option, index);
|
QWidget *editor = QItemDelegate::createEditor(parent, option, index);
|
||||||
QLineEdit *le = dynamic_cast<QLineEdit*>(editor);
|
QLineEdit *le = dynamic_cast<QLineEdit*>(editor);
|
||||||
if (le)
|
if (!le)
|
||||||
|
return editor;
|
||||||
|
|
||||||
|
int col = index.column();
|
||||||
|
QTableWidgetItem *twi = mTable->horizontalHeaderItem(col);
|
||||||
|
if(!twi)
|
||||||
{
|
{
|
||||||
int col = index.column();
|
QgsDebugMsg( QString("horizontalHeaderItem %1 not found").arg(col) );
|
||||||
if( mFields[col-1].type()==QVariant::Int )
|
return editor;
|
||||||
{
|
|
||||||
le->setValidator( new QIntValidator(le) );
|
|
||||||
}
|
|
||||||
else if( mFields[col-1].type()==QVariant::Double )
|
|
||||||
{
|
|
||||||
le->setValidator( new QDoubleValidator(le) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int type = twi->data(QgsAttributeTable::AttributeType).toInt();
|
||||||
|
if( type==QVariant::Int )
|
||||||
|
{
|
||||||
|
le->setValidator( new QIntValidator(le) );
|
||||||
|
}
|
||||||
|
else if( type==QVariant::Double )
|
||||||
|
{
|
||||||
|
le->setValidator( new QDoubleValidator(le) );
|
||||||
|
}
|
||||||
|
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QgsAttributeTable::QgsAttributeTable(QWidget * parent):
|
QgsAttributeTable::QgsAttributeTable(QWidget * parent) :
|
||||||
QTableWidget(parent),
|
QTableWidget(parent),
|
||||||
lockKeyPressed(false),
|
lockKeyPressed(false),
|
||||||
mEditable(false),
|
mEditable(false),
|
||||||
@ -69,14 +81,12 @@ QgsAttributeTable::QgsAttributeTable(QWidget * parent):
|
|||||||
f.setFamily("Helvetica");
|
f.setFamily("Helvetica");
|
||||||
f.setPointSize(9);
|
f.setPointSize(9);
|
||||||
setFont(f);
|
setFont(f);
|
||||||
mDelegate = new QgsAttributeTableItemDelegate(mFields, this);
|
mDelegate = new QgsAttributeTableItemDelegate(this);
|
||||||
setItemDelegate(mDelegate);
|
setItemDelegate(mDelegate);
|
||||||
setSelectionBehavior(QAbstractItemView::SelectRows);
|
setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(handleChangedSelections()));
|
connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(handleChangedSelections()));
|
||||||
connect(this, SIGNAL(cellChanged(int, int)), this, SLOT(storeChangedValue(int,int)));
|
|
||||||
connect(horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(columnClicked(int)));
|
connect(horizontalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(columnClicked(int)));
|
||||||
connect(verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(rowClicked(int)));
|
connect(verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(rowClicked(int)));
|
||||||
setReadOnly(true);
|
|
||||||
setFocus();
|
setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,14 +100,17 @@ void QgsAttributeTable::setReadOnly(bool b)
|
|||||||
{
|
{
|
||||||
setEditTriggers(b ? QAbstractItemView::NoEditTriggers :
|
setEditTriggers(b ? QAbstractItemView::NoEditTriggers :
|
||||||
QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
|
QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed);
|
||||||
|
if(!b) {
|
||||||
|
setColumnReadOnly(0, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTable::setColumnReadOnly(int col, bool ro)
|
void QgsAttributeTable::setColumnReadOnly(int col, bool ro)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < rowCount(); ++i)
|
for (int i = 0; i < rowCount(); ++i)
|
||||||
{
|
{
|
||||||
QTableWidgetItem *item = this->item(i, col);
|
QTableWidgetItem *twi = item(i, col);
|
||||||
item->setFlags(ro ? item->flags() & ~Qt::ItemIsEditable : item->flags() | Qt::ItemIsEditable);
|
twi->setFlags(ro ? twi->flags() & ~Qt::ItemIsEditable : twi->flags() | Qt::ItemIsEditable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,16 +186,16 @@ void QgsAttributeTable::keyReleaseEvent(QKeyEvent * ev)
|
|||||||
|
|
||||||
void QgsAttributeTable::handleChangedSelections()
|
void QgsAttributeTable::handleChangedSelections()
|
||||||
{
|
{
|
||||||
emit selectionRemoved(false);
|
emit selectionRemoved(false);
|
||||||
|
|
||||||
QList<QTableWidgetSelectionRange> selectedItemRanges = selectedRanges();
|
QList<QTableWidgetSelectionRange> selectedItemRanges = selectedRanges();
|
||||||
QList<QTableWidgetSelectionRange>::const_iterator range_it = selectedItemRanges.constBegin();
|
QList<QTableWidgetSelectionRange>::const_iterator range_it = selectedItemRanges.constBegin();
|
||||||
for (; range_it != selectedItemRanges.constEnd(); ++range_it)
|
for (; range_it != selectedItemRanges.constEnd(); ++range_it)
|
||||||
{
|
{
|
||||||
for (int index = range_it->topRow(); index <= range_it->bottomRow(); index++)
|
for (int index = range_it->topRow(); index <= range_it->bottomRow(); index++)
|
||||||
{
|
{
|
||||||
emit selected(item(index, 0)->text().toInt(), false);
|
emit selected(item(index, 0)->text().toInt(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//don't send the signal repaintRequested() from here
|
//don't send the signal repaintRequested() from here
|
||||||
@ -203,19 +216,8 @@ void QgsAttributeTable::selectRowWithId(int id)
|
|||||||
|
|
||||||
void QgsAttributeTable::sortColumn(int col, bool ascending)
|
void QgsAttributeTable::sortColumn(int col, bool ascending)
|
||||||
{
|
{
|
||||||
//if the first entry contains a letter, sort alphanumerically, otherwise numerically
|
int type = horizontalHeaderItem(col)->data(QgsAttributeTable::AttributeType).toInt();
|
||||||
QString firstentry = item(0, col)->text();
|
qsort(0, rowCount() - 1, col, ascending, type!=QVariant::Int && type==QVariant::Double);
|
||||||
bool containsletter = false;
|
|
||||||
for (int i = 0; i < firstentry.length(); i++)
|
|
||||||
{
|
|
||||||
if (firstentry[i].isLetter())
|
|
||||||
{
|
|
||||||
containsletter = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(0, rowCount() - 1, col, ascending, containsletter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -302,7 +304,8 @@ void QgsAttributeTable::qsort(int lower, int upper, int col, bool ascending, boo
|
|||||||
j = upper;
|
j = upper;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
while (compareItems(item(++i, col)->text(), v, ascending, alphanumeric) == -1);
|
while (compareItems(item(++i, col)->text(), v, ascending, alphanumeric) == -1)
|
||||||
|
;
|
||||||
while (compareItems(item(--j, col)->text(), v, ascending, alphanumeric) == 1 && j > 0); //make sure that j does not get negative
|
while (compareItems(item(--j, col)->text(), v, ascending, alphanumeric) == 1 && j > 0); //make sure that j does not get negative
|
||||||
if (i >= j)
|
if (i >= j)
|
||||||
{
|
{
|
||||||
@ -381,45 +384,6 @@ void QgsAttributeTable::popupItemSelected(QAction* menuAction)
|
|||||||
mActions.doAction(id, mActionValues, mClickedOnValue);
|
mActions.doAction(id, mActionValues, mClickedOnValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsAttributeTable::addAttribute(const QString& name, const QString& type)
|
|
||||||
{
|
|
||||||
//first test if an attribute with the same name is already in the table
|
|
||||||
for(int i=0;i<columnCount();++i)
|
|
||||||
{
|
|
||||||
if(horizontalHeaderItem(i)->text()==name)
|
|
||||||
{
|
|
||||||
//name conflict
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mAddedAttributes.insert(name,type);
|
|
||||||
|
|
||||||
QgsDebugMsg("inserting attribute " + name + " of type " + type + ", numCols: " + QString::number(columnCount()) );
|
|
||||||
//add a new column at the end of the table
|
|
||||||
insertColumn(columnCount());
|
|
||||||
setHorizontalHeaderItem(columnCount()-1, new QTableWidgetItem(name));
|
|
||||||
mEdited=true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTable::deleteAttribute(const QString& name)
|
|
||||||
{
|
|
||||||
//check, if there is already an attribute with this name in mAddedAttributes
|
|
||||||
QgsNewAttributesMap::iterator iter = mAddedAttributes.find(name);
|
|
||||||
if(iter!=mAddedAttributes.end())
|
|
||||||
{
|
|
||||||
mAddedAttributes.erase(iter);
|
|
||||||
removeAttrColumn(name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mDeletedAttributes.insert(name);
|
|
||||||
removeAttrColumn(name);
|
|
||||||
}
|
|
||||||
mEdited=true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Deprecated: See QgisApp::editCopy() instead */
|
/* Deprecated: See QgisApp::editCopy() instead */
|
||||||
void QgsAttributeTable::copySelectedRows()
|
void QgsAttributeTable::copySelectedRows()
|
||||||
{
|
{
|
||||||
@ -463,157 +427,60 @@ void QgsAttributeTable::copySelectedRows()
|
|||||||
clipboard->setText(toClipboard, QClipboard::Clipboard);
|
clipboard->setText(toClipboard, QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsAttributeTable::commitChanges(QgsVectorLayer* layer)
|
void QgsAttributeTable::fillTable(QgsVectorLayer *layer)
|
||||||
{
|
{
|
||||||
bool isSuccessful = false;
|
int row = 0;
|
||||||
|
|
||||||
if(layer)
|
const QgsFieldMap &fields = layer->pendingFields();
|
||||||
|
|
||||||
|
// set up the column headers
|
||||||
|
setColumnCount(fields.size()+1);
|
||||||
|
|
||||||
|
setHorizontalHeaderItem(0, new QTableWidgetItem("id")); //label for the id-column
|
||||||
|
|
||||||
|
int h = 1;
|
||||||
|
for (QgsFieldMap::const_iterator fldIt = fields.begin(); fldIt!=fields.end(); fldIt++, h++)
|
||||||
{
|
{
|
||||||
//convert strings of deleted attributes to ids
|
QgsDebugMsg( QString("%1: field %2: %3 | %4")
|
||||||
|
.arg(h).arg(fldIt.key()).arg(fldIt->name()).arg( QVariant::typeToName(fldIt->type()) ) );
|
||||||
|
|
||||||
QgsVectorDataProvider* provider = layer->getDataProvider();
|
QTableWidgetItem *twi = new QTableWidgetItem(fldIt->name());
|
||||||
|
twi->setData( AttributeIndex, fldIt.key() );
|
||||||
|
twi->setData( AttributeName, fldIt->name() );
|
||||||
|
twi->setData( AttributeType, fldIt->type() );
|
||||||
|
setHorizontalHeaderItem(h, twi);
|
||||||
|
|
||||||
if(provider)
|
mAttrIdxMap.insert(fldIt.key(), h);
|
||||||
{
|
|
||||||
|
|
||||||
QgsAttributeIds deletedIds;
|
|
||||||
QSet<QString>::const_iterator it = mDeletedAttributes.constBegin();
|
|
||||||
|
|
||||||
for(; it != mDeletedAttributes.constEnd(); ++it)
|
|
||||||
{
|
|
||||||
deletedIds.insert(provider->indexFromFieldName(*it));
|
|
||||||
}
|
|
||||||
|
|
||||||
isSuccessful = true;
|
|
||||||
if( !mAddedAttributes.empty() )
|
|
||||||
{
|
|
||||||
// add new attributes beforehand, so attribute changes can be applied
|
|
||||||
isSuccessful = layer->commitAttributeChanges(QgsAttributeIds(), mAddedAttributes, QgsChangedAttributesMap());
|
|
||||||
|
|
||||||
if(isSuccessful)
|
|
||||||
// forget added attributes on successful addition
|
|
||||||
mAddedAttributes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isSuccessful)
|
|
||||||
{
|
|
||||||
QgsChangedAttributesMap attributeChanges; //convert mChangedValues to QgsChangedAttributesMap
|
|
||||||
int fieldIndex;
|
|
||||||
|
|
||||||
QMap<int, QMap<QString, QString> >::const_iterator att_it = mChangedValues.constBegin();
|
|
||||||
for(; att_it != mChangedValues.constEnd(); ++att_it)
|
|
||||||
{
|
|
||||||
QgsAttributeMap newAttMap;
|
|
||||||
QMap<QString, QString>::const_iterator record_it = att_it->constBegin();
|
|
||||||
for(; record_it != att_it->constEnd(); ++record_it)
|
|
||||||
{
|
|
||||||
fieldIndex = provider->indexFromFieldName(record_it.key());
|
|
||||||
if(fieldIndex != -1)
|
|
||||||
{
|
|
||||||
if( record_it.value()=="NULL" ||
|
|
||||||
( record_it.value().isEmpty() &&
|
|
||||||
(provider->fields()[fieldIndex].type()==QVariant::Int ||
|
|
||||||
provider->fields()[fieldIndex].type()==QVariant::Double) ) )
|
|
||||||
newAttMap.insert(fieldIndex, QVariant(QString::null) );
|
|
||||||
else
|
|
||||||
newAttMap.insert(fieldIndex, record_it.value());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QgsDebugMsg("Changed attribute " + record_it.key() + " not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
attributeChanges.insert(att_it.key(), newAttMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
isSuccessful = layer->commitAttributeChanges(deletedIds,
|
|
||||||
QgsNewAttributesMap(),
|
|
||||||
attributeChanges);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSuccessful)
|
QgsFeatureList features;
|
||||||
|
if( layer->selectedFeatureCount()==0 )
|
||||||
{
|
{
|
||||||
mEdited=false;
|
layer->select(layer->pendingAllAttributesList(), QgsRect(), false);
|
||||||
clearEditingStructures();
|
|
||||||
|
QgsFeature f;
|
||||||
|
while( layer->getNextFeature(f) )
|
||||||
|
features << f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
features = layer->selectedFeatures();
|
||||||
}
|
}
|
||||||
|
|
||||||
return isSuccessful;
|
setRowCount( features.size() );
|
||||||
}
|
|
||||||
|
|
||||||
bool QgsAttributeTable::rollBack(QgsVectorLayer* layer)
|
|
||||||
{
|
|
||||||
if(layer)
|
|
||||||
{
|
|
||||||
fillTable(layer);
|
|
||||||
}
|
|
||||||
mEdited=false;
|
|
||||||
clearEditingStructures();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QgsAttributeTable::fillTable(QgsVectorLayer* layer)
|
|
||||||
{
|
|
||||||
QgsVectorDataProvider* provider=layer->getDataProvider();
|
|
||||||
if(provider)
|
|
||||||
{
|
|
||||||
QgsFeature fet;
|
|
||||||
int row = 0;
|
|
||||||
|
|
||||||
QgsFeatureList& addedFeatures = layer->addedFeatures();
|
|
||||||
QgsFeatureIds& deletedFeatures = layer->deletedFeatureIds();
|
|
||||||
|
|
||||||
// set up the column headers
|
|
||||||
mFields = provider->fields();
|
|
||||||
int fieldcount=provider->fieldCount();
|
|
||||||
|
|
||||||
setRowCount(provider->featureCount() + addedFeatures.size() - deletedFeatures.size());
|
for(int i=0; i<features.size(); i++)
|
||||||
setColumnCount(fieldcount+1);
|
putFeatureInTable(i, features[i]);
|
||||||
setHorizontalHeaderItem(0, new QTableWidgetItem("id")); //label for the id-column
|
|
||||||
|
|
||||||
int h = 1;
|
// Default row height is too tall
|
||||||
QgsFieldMap::const_iterator fldIt;
|
resizeRowsToContents();
|
||||||
for (fldIt = mFields.begin(); fldIt != mFields.end(); ++fldIt)
|
|
||||||
{
|
|
||||||
QgsDebugMsg("field " + QString::number(fldIt.key()) + ": " + fldIt->name() +
|
|
||||||
" | " + QString(QVariant::typeToName(fldIt->type())) );
|
|
||||||
|
|
||||||
setHorizontalHeaderItem(h++, new QTableWidgetItem(fldIt->name()));
|
// Make each column wide enough to show all the contents
|
||||||
}
|
for (int i=0; i<columnCount(); i++)
|
||||||
|
resizeColumnToContents(i);
|
||||||
//go through the features and fill the values into the table
|
|
||||||
QgsAttributeList all = provider->allAttributesList();
|
|
||||||
provider->select(all, QgsRect(), false);
|
|
||||||
|
|
||||||
while (provider->getNextFeature(fet))
|
|
||||||
{
|
|
||||||
if (!deletedFeatures.contains(fet.featureId()))
|
|
||||||
{
|
|
||||||
putFeatureInTable(row, fet);
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//also consider the not commited features
|
|
||||||
for(QgsFeatureList::iterator it = addedFeatures.begin(); it != addedFeatures.end(); it++)
|
|
||||||
{
|
|
||||||
putFeatureInTable(row, *it);
|
|
||||||
row++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default row height is too tall
|
|
||||||
resizeRowsToContents();
|
|
||||||
// Make each column wide enough to show all the contents
|
|
||||||
for (int i = 0; i < columnCount(); ++i)
|
|
||||||
{
|
|
||||||
resizeColumnToContents(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTable::putFeatureInTable(int row, QgsFeature& fet)
|
void QgsAttributeTable::putFeatureInTable(int row, const QgsFeature& fet)
|
||||||
{
|
{
|
||||||
// Prevent a crash if a provider doesn't update the feature count properly
|
// Prevent a crash if a provider doesn't update the feature count properly
|
||||||
if(row >= rowCount())
|
if(row >= rowCount())
|
||||||
@ -623,21 +490,35 @@ void QgsAttributeTable::putFeatureInTable(int row, QgsFeature& fet)
|
|||||||
|
|
||||||
//id-field
|
//id-field
|
||||||
int id = fet.featureId();
|
int id = fet.featureId();
|
||||||
QTableWidgetItem *item = new QTableWidgetItem(QString::number(id));
|
QTableWidgetItem *twi = new QTableWidgetItem(QString::number(id));
|
||||||
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
twi->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
setItem(row, 0, item);
|
setItem(row, 0, twi);
|
||||||
insertFeatureId(id, row); //insert the id into the search tree of qgsattributetable
|
insertFeatureId(id, row); //insert the id into the search tree of qgsattributetable
|
||||||
const QgsAttributeMap& attr = fet.attributeMap();
|
|
||||||
QgsAttributeMap::const_iterator it;
|
|
||||||
int h = 1;
|
|
||||||
for (it = attr.begin(); it != attr.end(); ++it)
|
|
||||||
{
|
|
||||||
QString value;
|
|
||||||
|
|
||||||
|
const QgsAttributeMap& attr = fet.attributeMap();
|
||||||
|
|
||||||
|
for (QgsAttributeMap::const_iterator it = attr.begin(); it != attr.end(); ++it)
|
||||||
|
{
|
||||||
|
if( !mAttrIdxMap.contains( it.key() ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int h = mAttrIdxMap[ it.key() ];
|
||||||
|
|
||||||
|
twi = horizontalHeaderItem(h);
|
||||||
|
if(!twi)
|
||||||
|
{
|
||||||
|
QgsDebugMsg("header item not found.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int type = twi->data(AttributeType).toInt();
|
||||||
|
bool isNum = (type == QVariant::Double || type == QVariant::Int);
|
||||||
|
|
||||||
|
QString value;
|
||||||
// get the field values
|
// get the field values
|
||||||
if( it->isNull() )
|
if( it->isNull() )
|
||||||
{
|
{
|
||||||
if( mFields[h-1].type()==QVariant::Int || mFields[h-1].type()==QVariant::Double )
|
if( isNum )
|
||||||
value="";
|
value="";
|
||||||
else
|
else
|
||||||
value="NULL";
|
value="NULL";
|
||||||
@ -645,58 +526,10 @@ void QgsAttributeTable::putFeatureInTable(int row, QgsFeature& fet)
|
|||||||
value = it->toString();
|
value = it->toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNum;
|
twi = new QTableWidgetItem(value);
|
||||||
value.toFloat(&isNum);
|
if (isNum)
|
||||||
item = new QTableWidgetItem(value);
|
twi->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||||
if (isNum) item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
setItem(row, h, twi);
|
||||||
setItem(row, h++, item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTable::storeChangedValue(int row, int column)
|
|
||||||
{
|
|
||||||
//id column is not editable
|
|
||||||
if(column>0)
|
|
||||||
{
|
|
||||||
//find feature id
|
|
||||||
int id=item(row,0)->text().toInt();
|
|
||||||
QString field = horizontalHeaderItem(column)->text();
|
|
||||||
|
|
||||||
if(id>=0)
|
|
||||||
{
|
|
||||||
// add empty map for feature if doesn't exist
|
|
||||||
if (!mChangedValues.contains(id))
|
|
||||||
{
|
|
||||||
mChangedValues.insert(id, QMap<QString, QString>());
|
|
||||||
}
|
|
||||||
|
|
||||||
mChangedValues[id].insert(field, item(row,column)->text());
|
|
||||||
mEdited=true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// added feature attribute changed
|
|
||||||
emit featureAttributeChanged(row,column);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTable::clearEditingStructures()
|
|
||||||
{
|
|
||||||
mDeletedAttributes.clear();
|
|
||||||
mAddedAttributes.clear();
|
|
||||||
mChangedValues.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTable::removeAttrColumn(const QString& name)
|
|
||||||
{
|
|
||||||
for(int i=0;i<columnCount();++i)
|
|
||||||
{
|
|
||||||
if(horizontalHeaderItem(i)->text()==name)
|
|
||||||
{
|
|
||||||
removeColumn(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -852,3 +685,54 @@ bool QgsAttributeTable::checkSelectionChanges()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTable::attributeValueChanged(int fid, int idx, const QVariant &value)
|
||||||
|
{
|
||||||
|
if( !rowIdMap.contains(fid) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( !mAttrIdxMap.contains(idx) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
item( rowIdMap[fid], mAttrIdxMap[idx] )->setText( value.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTable::featureDeleted(int fid)
|
||||||
|
{
|
||||||
|
if( !rowIdMap.contains(fid) )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int row = rowIdMap[fid];
|
||||||
|
|
||||||
|
removeRow(row);
|
||||||
|
|
||||||
|
for(QMap<int,int>::iterator it=rowIdMap.begin(); it!=rowIdMap.end(); it++)
|
||||||
|
if( it.value() > row )
|
||||||
|
rowIdMap[ it.key() ]--;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTable::addAttribute(int attr, const QgsField &fld)
|
||||||
|
{
|
||||||
|
QTableWidgetItem *twi = new QTableWidgetItem( fld.name() );
|
||||||
|
twi->setData( AttributeIndex, attr );
|
||||||
|
twi->setData( AttributeName, fld.name() );
|
||||||
|
twi->setData( AttributeType, fld.type() );
|
||||||
|
|
||||||
|
insertColumn( columnCount() );
|
||||||
|
setHorizontalHeaderItem(columnCount()-1, twi);
|
||||||
|
|
||||||
|
mAttrIdxMap.insert(attr, columnCount()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTable::deleteAttribute(int attr)
|
||||||
|
{
|
||||||
|
int column = mAttrIdxMap[attr];
|
||||||
|
|
||||||
|
removeColumn( column );
|
||||||
|
mAttrIdxMap.remove(attr);
|
||||||
|
for(QMap<int, int>::iterator it=mAttrIdxMap.begin(); it!=mAttrIdxMap.end(); it++)
|
||||||
|
{
|
||||||
|
if( it.value()>column )
|
||||||
|
mAttrIdxMap[ it.key() ]--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "qgsattributeaction.h"
|
#include "qgsattributeaction.h"
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
|
|
||||||
#include <QItemDelegate>
|
#include <QItemDelegate>
|
||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
@ -31,18 +32,21 @@
|
|||||||
*@author Gary E.Sherman
|
*@author Gary E.Sherman
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class QgsAttributeTable;
|
||||||
|
|
||||||
class QgsAttributeTableItemDelegate: public QItemDelegate
|
class QgsAttributeTableItemDelegate: public QItemDelegate
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QgsAttributeTableItemDelegate(const QgsFieldMap & fields, QObject * parent = 0);
|
QgsAttributeTableItemDelegate(QgsAttributeTable *table, QObject * parent = 0);
|
||||||
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
|
QWidget * createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QgsFieldMap & mFields;
|
QgsAttributeTable *mTable;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QgsAttributeTable:public QTableWidget
|
class QgsAttributeTable : public QTableWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -50,9 +54,17 @@ class QgsAttributeTable:public QTableWidget
|
|||||||
QgsAttributeTable(QWidget * parent = 0);
|
QgsAttributeTable(QWidget * parent = 0);
|
||||||
~QgsAttributeTable();
|
~QgsAttributeTable();
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AttributeIndex = Qt::UserRole,
|
||||||
|
AttributeName = Qt::UserRole+1,
|
||||||
|
AttributeType = Qt::UserRole+2,
|
||||||
|
};
|
||||||
|
|
||||||
void setReadOnly(bool b);
|
void setReadOnly(bool b);
|
||||||
void setColumnReadOnly(int col, bool ro);
|
void setColumnReadOnly(int col, bool ro);
|
||||||
/**Inserts the feature with the specified id into rowIdMap. This function has to be called (e.g. from QgsShapeFileLayer) when a row is inserted into the table*/
|
|
||||||
|
/* Inserts the feature with the specified id into rowIdMap. This function has to be called
|
||||||
|
(e.g. from QgsShapeFileLayer) when a row is inserted into the table */
|
||||||
void insertFeatureId(int id, int row);
|
void insertFeatureId(int id, int row);
|
||||||
/**Selects the row which belongs to the feature with the specified id*/
|
/**Selects the row which belongs to the feature with the specified id*/
|
||||||
void selectRowWithId(int id);
|
void selectRowWithId(int id);
|
||||||
@ -66,38 +78,11 @@ class QgsAttributeTable:public QTableWidget
|
|||||||
bool edited() const {return mEdited;}
|
bool edited() const {return mEdited;}
|
||||||
/**Switches editing mode on and off*/
|
/**Switches editing mode on and off*/
|
||||||
void setEditable(bool enabled){mEditable=enabled;}
|
void setEditable(bool enabled){mEditable=enabled;}
|
||||||
/**Adds an attribute to the table (but does not commit it yet)
|
|
||||||
@param name attribute name
|
|
||||||
@param type attribute type
|
|
||||||
@return false in case of a name conflict, true in case of success*/
|
|
||||||
bool addAttribute(const QString& name, const QString& type);
|
|
||||||
/**Deletes an attribute (but does not commit it)
|
|
||||||
@param name attribute name*/
|
|
||||||
void deleteAttribute(const QString& name);
|
|
||||||
|
|
||||||
/** Copies the selected rows to the clipboard
|
/** Copies the selected rows to the clipboard
|
||||||
Deprecated: See QgisApp::editCopy() instead */
|
Deprecated: See QgisApp::editCopy() instead */
|
||||||
void copySelectedRows();
|
void copySelectedRows();
|
||||||
|
|
||||||
/**
|
|
||||||
Attempts to commit any changes to disk. Returns the result of the attempt.
|
|
||||||
If a commit fails, the in-memory changes are left alone.
|
|
||||||
|
|
||||||
This allows editing to continue if the commit failed on e.g. a
|
|
||||||
disallowed value in a Postgres database - the user can re-edit and try
|
|
||||||
again.
|
|
||||||
|
|
||||||
Delegates to QgsVectorLayer to decide, which changes
|
|
||||||
belong to not commited features or to commited ones.
|
|
||||||
|
|
||||||
*/
|
|
||||||
bool commitChanges(QgsVectorLayer* layer);
|
|
||||||
|
|
||||||
/**Discard all changes and restore
|
|
||||||
the state before editing was started*/
|
|
||||||
bool rollBack(QgsVectorLayer* layer);
|
|
||||||
/**Fills the contents of a provider into this table*/
|
|
||||||
void fillTable(QgsVectorLayer* layer);
|
|
||||||
/**Swaps the selected rows such that the selected ones are on the top of the table*/
|
/**Swaps the selected rows such that the selected ones are on the top of the table*/
|
||||||
void bringSelectedToTop();
|
void bringSelectedToTop();
|
||||||
/** Selects rows with chosen feature IDs */
|
/** Selects rows with chosen feature IDs */
|
||||||
@ -107,38 +92,42 @@ class QgsAttributeTable:public QTableWidget
|
|||||||
/** Shows all rows */
|
/** Shows all rows */
|
||||||
void showAllRows();
|
void showAllRows();
|
||||||
|
|
||||||
|
/**Fills the contents of a provider into this table*/
|
||||||
|
void fillTable(QgsVectorLayer *layer);
|
||||||
|
void addAttribute(int idx, const QgsField &fld);
|
||||||
|
void deleteAttribute(int idx);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void columnClicked(int col);
|
void columnClicked(int col);
|
||||||
void rowClicked(int row);
|
void rowClicked(int row);
|
||||||
|
|
||||||
// Called when the user chooses an item on the popup menu
|
// Called when the user chooses an item on the popup menu
|
||||||
void popupItemSelected(QAction * menuAction);
|
void popupItemSelected(QAction * menuAction);
|
||||||
|
|
||||||
|
void attributeValueChanged(int fid, int idx, const QVariant &value);
|
||||||
|
void featureDeleted(int fid);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void handleChangedSelections();
|
void handleChangedSelections();
|
||||||
/**Writes changed values to 'mChangedValues'*/
|
|
||||||
void storeChangedValue(int row, int column);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**Flag telling if the ctrl-button or the shift-button is pressed*/
|
/**Flag telling if the ctrl-button or the shift-button is pressed*/
|
||||||
bool lockKeyPressed;
|
bool lockKeyPressed;
|
||||||
/**Search tree to find a row corresponding to a feature id*/
|
/**Search tree to find a row corresponding to a feature id*/
|
||||||
QMap<int,int> rowIdMap;
|
QMap<int,int> rowIdMap;
|
||||||
|
/**Map attribute index to columns*/
|
||||||
|
QMap<int,int> mAttrIdxMap;
|
||||||
bool mEditable;
|
bool mEditable;
|
||||||
/**True if table has been edited and contains uncommited changes*/
|
/**True if table has been edited and contains uncommited changes*/
|
||||||
bool mEdited;
|
bool mEdited;
|
||||||
/**Map containing the added attributes. The key is the attribute name
|
|
||||||
and the value the attribute type*/
|
|
||||||
QgsNewAttributesMap mAddedAttributes;
|
|
||||||
/**Set containing the attribute names of deleted attributes*/
|
|
||||||
QSet<QString> mDeletedAttributes;
|
|
||||||
/**Nested map containing the changed attribute values. The int is the feature id,
|
|
||||||
the first QString the attribute name and the second QString the new value*/
|
|
||||||
QMap<int, QMap<QString, QString> > mChangedValues;
|
|
||||||
|
|
||||||
/**Stors the numbers of the last selected rows. This is used to check for selection changes before emit repaintRequested()*/
|
/**Stors the numbers of the last selected rows. This is used to check for selection changes before emit repaintRequested()*/
|
||||||
std::set<int> mLastSelectedRows;
|
std::set<int> mLastSelectedRows;
|
||||||
|
|
||||||
/**Compares the content of two cells either alphanumeric or numeric. If 'ascending' is true, -1 means s1 is less, 0 equal, 1 greater. If 'ascending' is false, -1 means s1 is more, 0 equal, 1 greater. This method is used mainly to sort a column*/
|
/* Compares the content of two cells either alphanumeric or numeric.
|
||||||
|
If 'ascending' is true, -1 means s1 is less, 0 equal, 1 greater.
|
||||||
|
If 'ascending' is false, -1 means s1 is more, 0 equal, 1 greater.
|
||||||
|
This method is used mainly to sort a column*/
|
||||||
int compareItems(QString s1, QString s2, bool ascending, bool alphanumeric);
|
int compareItems(QString s1, QString s2, bool ascending, bool alphanumeric);
|
||||||
void keyPressEvent(QKeyEvent* ev);
|
void keyPressEvent(QKeyEvent* ev);
|
||||||
void keyReleaseEvent(QKeyEvent* ev);
|
void keyReleaseEvent(QKeyEvent* ev);
|
||||||
@ -146,16 +135,15 @@ class QgsAttributeTable:public QTableWidget
|
|||||||
void qsort(int lower, int upper, int col, bool ascending, bool alphanumeric);
|
void qsort(int lower, int upper, int col, bool ascending, bool alphanumeric);
|
||||||
/**Called when the user requests a popup menu*/
|
/**Called when the user requests a popup menu*/
|
||||||
void contextMenuEvent(QContextMenuEvent* event);
|
void contextMenuEvent(QContextMenuEvent* event);
|
||||||
/**Clears mAddedAttributes, mDeletedAttributes and mChangedValues*/
|
|
||||||
void clearEditingStructures();
|
|
||||||
/**Removes the column belonging to an attribute from the table
|
/**Removes the column belonging to an attribute from the table
|
||||||
@name attribut name*/
|
@name attribut name*/
|
||||||
void removeAttrColumn(const QString& name);
|
void removeAttrColumn(const QString& name);
|
||||||
/** puts attributes of feature to the chosen table row */
|
/** puts attributes of feature to the chosen table row */
|
||||||
void putFeatureInTable(int row, QgsFeature& fet);
|
void putFeatureInTable(int row, const QgsFeature& fet);
|
||||||
void mouseReleaseEvent(QMouseEvent* e);
|
void mouseReleaseEvent(QMouseEvent* e);
|
||||||
/**This function compares the current selection and the selection of the last repaint. Returns true if there are differences in the selection.
|
/**This function compares the current selection and the selection of the last repaint.
|
||||||
Also, mLastSelectedRows is updated*/
|
Returns true if there are differences in the selection.
|
||||||
|
Also, mLastSelectedRows is updated*/
|
||||||
bool checkSelectionChanges();
|
bool checkSelectionChanges();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
@ -165,8 +153,6 @@ class QgsAttributeTable:public QTableWidget
|
|||||||
void selectionRemoved(bool);
|
void selectionRemoved(bool);
|
||||||
/**Is emitted when a set of related selection and deselection signals have been emitted*/
|
/**Is emitted when a set of related selection and deselection signals have been emitted*/
|
||||||
void repaintRequested();
|
void repaintRequested();
|
||||||
/**Is emitted when a attribute of a added feature is changed*/
|
|
||||||
void featureAttributeChanged(int row, int column);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void swapRows(int row1, int row2);
|
void swapRows(int row1, int row2);
|
||||||
@ -179,10 +165,10 @@ class QgsAttributeTable:public QTableWidget
|
|||||||
|
|
||||||
QgsAttributeTableItemDelegate *mDelegate;
|
QgsAttributeTableItemDelegate *mDelegate;
|
||||||
|
|
||||||
QgsFieldMap mFields;
|
|
||||||
|
|
||||||
// Track previous columm for QTableView sortIndicator wrong direction workaround
|
// Track previous columm for QTableView sortIndicator wrong direction workaround
|
||||||
int mPreviousSortIndicatorColumn;
|
int mPreviousSortIndicatorColumn;
|
||||||
|
|
||||||
|
QgsVectorLayer *mLayer;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,8 +21,6 @@
|
|||||||
|
|
||||||
#include "qgisapp.h"
|
#include "qgisapp.h"
|
||||||
#include "qgsapplication.h"
|
#include "qgsapplication.h"
|
||||||
#include "qgsaddattrdialog.h"
|
|
||||||
#include "qgsdelattrdialog.h"
|
|
||||||
#include "qgsfeature.h"
|
#include "qgsfeature.h"
|
||||||
#include "qgsfield.h"
|
#include "qgsfield.h"
|
||||||
#include "qgslogger.h"
|
#include "qgslogger.h"
|
||||||
@ -39,249 +37,174 @@
|
|||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
#include <QDockWidget>
|
||||||
|
|
||||||
QgsAttributeTableDisplay::QgsAttributeTableDisplay(QgsVectorLayer* layer, QgisApp * qgisApp)
|
QgsAttributeTableDisplay::QgsAttributeTableDisplay(QgsVectorLayer* layer)
|
||||||
: QDialog(0, Qt::Window),
|
: QDialog(0, Qt::Window),
|
||||||
mLayer(layer),
|
mLayer(layer),
|
||||||
mQgisApp(qgisApp)
|
mDock(NULL)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
restorePosition();
|
restorePosition();
|
||||||
setTheme();
|
setTheme();
|
||||||
|
|
||||||
|
mToggleEditingButton->setEnabled( layer->getDataProvider()->capabilities() & QgsVectorDataProvider::ChangeAttributeValues );
|
||||||
|
mToggleEditingButton->setChecked( layer->isEditable() );
|
||||||
|
|
||||||
connect(mRemoveSelectionButton, SIGNAL(clicked()), this, SLOT(removeSelection()));
|
connect(mRemoveSelectionButton, SIGNAL(clicked()), this, SLOT(removeSelection()));
|
||||||
connect(mSelectedToTopButton, SIGNAL(clicked()), this, SLOT(selectedToTop()));
|
connect(mSelectedToTopButton, SIGNAL(clicked()), this, SLOT(selectedToTop()));
|
||||||
connect(mInvertSelectionButton, SIGNAL(clicked()), this, SLOT(invertSelection()));
|
connect(mInvertSelectionButton, SIGNAL(clicked()), this, SLOT(invertSelection()));
|
||||||
connect(mCopySelectedRowsButton, SIGNAL(clicked()), this, SLOT(copySelectedRowsToClipboard()));
|
connect(mCopySelectedRowsButton, SIGNAL(clicked()), this, SLOT(copySelectedRowsToClipboard()));
|
||||||
connect(mZoomMapToSelectedRowsButton, SIGNAL(clicked()), this, SLOT(zoomMapToSelectedRows()));
|
connect(mZoomMapToSelectedRowsButton, SIGNAL(clicked()), this, SLOT(zoomMapToSelectedRows()));
|
||||||
connect(mAddAttributeButton, SIGNAL(clicked()), this, SLOT(addAttribute()));
|
|
||||||
connect(mDeleteAttributeButton, SIGNAL(clicked()), this, SLOT(deleteAttributes()));
|
|
||||||
connect(mSearchButton, SIGNAL(clicked()), this, SLOT(search()));
|
connect(mSearchButton, SIGNAL(clicked()), this, SLOT(search()));
|
||||||
connect(mSearchShowResults, SIGNAL(activated(int)), this, SLOT(searchShowResultsChanged(int)));
|
connect(mSearchShowResults, SIGNAL(activated(int)), this, SLOT(searchShowResultsChanged(int)));
|
||||||
connect(btnAdvancedSearch, SIGNAL(clicked()), this, SLOT(advancedSearch()));
|
connect(btnAdvancedSearch, SIGNAL(clicked()), this, SLOT(advancedSearch()));
|
||||||
connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(showHelp()));
|
connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(showHelp()));
|
||||||
connect(buttonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()),
|
connect(buttonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(close()));
|
||||||
this, SLOT(close()));
|
|
||||||
connect(tblAttributes, SIGNAL(featureAttributeChanged(int,int)), this, SLOT(changeFeatureAttribute(int,int)));
|
|
||||||
|
|
||||||
//disable those buttons until start editing has been pressed and provider supports it
|
|
||||||
mAddAttributeButton->setEnabled(false);
|
|
||||||
mDeleteAttributeButton->setEnabled(false);
|
|
||||||
|
|
||||||
int cap=layer->getDataProvider()->capabilities();
|
connect(mToggleEditingButton, SIGNAL(clicked()), this, SLOT(toggleEditing()));
|
||||||
if((cap&QgsVectorDataProvider::ChangeAttributeValues)
|
connect(this, SIGNAL(editingToggled(QgsMapLayer *)), QgisApp::instance(), SLOT(toggleEditing(QgsMapLayer *)));
|
||||||
||(cap&QgsVectorDataProvider::AddAttributes)
|
|
||||||
||(cap&QgsVectorDataProvider::DeleteAttributes))
|
// etablish connection to table
|
||||||
{
|
connect(tblAttributes, SIGNAL(cellChanged(int, int)), this, SLOT(changeFeatureAttribute(int,int)));
|
||||||
btnEdit->setEnabled(true);
|
|
||||||
}
|
// etablish connections to layer
|
||||||
else
|
connect(mLayer, SIGNAL(layerDeleted()), this, SLOT(close()));
|
||||||
{
|
|
||||||
btnEdit->setEnabled(false);
|
connect(mLayer, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
|
||||||
}
|
|
||||||
|
connect(mLayer, SIGNAL(editingStarted()), this, SLOT(editingToggled()));
|
||||||
|
connect(mLayer, SIGNAL(editingStopped()), this, SLOT(editingToggled()));
|
||||||
|
|
||||||
|
connect(mLayer, SIGNAL(attributeAdded(int)), this, SLOT(attributeAdded(int)));
|
||||||
|
connect(mLayer, SIGNAL(attributeDeleted(int)), this, SLOT(attributeDeleted(int)));
|
||||||
|
|
||||||
|
connect(mLayer, SIGNAL(attributeValueChanged(int,int,const QVariant &)),
|
||||||
|
tblAttributes, SLOT(attributeValueChanged(int,int,const QVariant &)) );
|
||||||
|
|
||||||
|
connect(mLayer, SIGNAL(featureDeleted(int)),
|
||||||
|
tblAttributes, SLOT(featureDeleted(int)));
|
||||||
|
|
||||||
|
// etablish connections between table and vector layer
|
||||||
|
connect(tblAttributes, SIGNAL(selected(int, bool)), mLayer, SLOT(select(int, bool)));
|
||||||
|
connect(tblAttributes, SIGNAL(selectionRemoved(bool)), mLayer, SLOT(removeSelection(bool)));
|
||||||
|
connect(tblAttributes, SIGNAL(repaintRequested()), mLayer, SLOT(triggerRepaint()));
|
||||||
|
|
||||||
// fill in mSearchColumns with available columns
|
// fill in mSearchColumns with available columns
|
||||||
QgsVectorDataProvider* provider = mLayer->getDataProvider();
|
const QgsFieldMap& xfields = mLayer->pendingFields();
|
||||||
if (provider)
|
QgsFieldMap::const_iterator fldIt;
|
||||||
|
for (fldIt = xfields.constBegin(); fldIt != xfields.constEnd(); ++fldIt)
|
||||||
{
|
{
|
||||||
const QgsFieldMap& xfields = provider->fields();
|
mSearchColumns->addItem(fldIt->name());
|
||||||
QgsFieldMap::const_iterator fldIt;
|
|
||||||
for (fldIt = xfields.constBegin(); fldIt != xfields.constEnd(); ++fldIt)
|
|
||||||
{
|
|
||||||
mSearchColumns->addItem(fldIt->name());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: create better labels
|
// TODO: create better labels
|
||||||
mSearchShowResults->addItem(tr("select"));
|
mSearchShowResults->addItem(tr("select"));
|
||||||
mSearchShowResults->addItem(tr("select and bring to top"));
|
mSearchShowResults->addItem(tr("select and bring to top"));
|
||||||
mSearchShowResults->addItem(tr("show only matching"));
|
mSearchShowResults->addItem(tr("show only matching"));
|
||||||
|
|
||||||
|
QSettings mySettings;
|
||||||
|
bool myDockFlag = mySettings.value("/qgis/dockAttributeTable",false).toBool();
|
||||||
|
if (myDockFlag )
|
||||||
|
{
|
||||||
|
mDock = new QDockWidget(tr("Attribute table - ") + layer->name(), QgisApp::instance());
|
||||||
|
mDock->setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
|
||||||
|
mDock->setWidget(this);
|
||||||
|
QgisApp::instance()->addDockWidget(Qt::BottomDockWidgetArea, mDock);
|
||||||
|
buttonBox->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
setWindowTitle(tr("Attribute table - ") + layer->name());
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsAttributeTableDisplay::~QgsAttributeTableDisplay()
|
QgsAttributeTableDisplay::~QgsAttributeTableDisplay()
|
||||||
{
|
{
|
||||||
|
smTables.remove(mLayer);
|
||||||
}
|
}
|
||||||
QgsAttributeTable *QgsAttributeTableDisplay::table()
|
|
||||||
|
void QgsAttributeTableDisplay::closeEvent(QCloseEvent *ev)
|
||||||
{
|
{
|
||||||
return tblAttributes;
|
saveWindowLocation();
|
||||||
|
ev->ignore();
|
||||||
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::fillTable()
|
||||||
|
{
|
||||||
|
tblAttributes->fillTable( mLayer );
|
||||||
|
tblAttributes->setReadOnly( !mLayer->isEditable() );
|
||||||
|
|
||||||
|
selectionChanged();
|
||||||
|
|
||||||
|
// Give the table the most recent copy of the actions for this layer.
|
||||||
|
setAttributeActions(*mLayer->actions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::toggleEditing()
|
||||||
|
{
|
||||||
|
emit editingToggled(mLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::setAttributeActions(const QgsAttributeAction &action)
|
||||||
|
{
|
||||||
|
tblAttributes->setAttributeActions(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::selectRowsWithId(const QgsFeatureIds &ids)
|
||||||
|
{
|
||||||
|
tblAttributes->selectRowsWithId(ids);
|
||||||
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::setTheme()
|
void QgsAttributeTableDisplay::setTheme()
|
||||||
{
|
{
|
||||||
mAddAttributeButton->setIcon(QgisApp::getThemeIcon("/mActionNewAttribute.png"));
|
|
||||||
mRemoveSelectionButton->setIcon(QgisApp::getThemeIcon("/mActionUnselectAttributes.png"));
|
mRemoveSelectionButton->setIcon(QgisApp::getThemeIcon("/mActionUnselectAttributes.png"));
|
||||||
mSelectedToTopButton->setIcon(QgisApp::getThemeIcon("/mActionSelectedToTop.png"));
|
mSelectedToTopButton->setIcon(QgisApp::getThemeIcon("/mActionSelectedToTop.png"));
|
||||||
mInvertSelectionButton->setIcon(QgisApp::getThemeIcon("/mActionInvertSelection.png"));
|
mInvertSelectionButton->setIcon(QgisApp::getThemeIcon("/mActionInvertSelection.png"));
|
||||||
mCopySelectedRowsButton->setIcon(QgisApp::getThemeIcon("/mActionCopySelected.png"));
|
mCopySelectedRowsButton->setIcon(QgisApp::getThemeIcon("/mActionCopySelected.png"));
|
||||||
mZoomMapToSelectedRowsButton->setIcon(QgisApp::getThemeIcon("/mActionZoomToSelected.png"));
|
mZoomMapToSelectedRowsButton->setIcon(QgisApp::getThemeIcon("/mActionZoomToSelected.png"));
|
||||||
mAddAttributeButton->setIcon(QgisApp::getThemeIcon("/mActionNewAttribute.png"));
|
mToggleEditingButton->setIcon(QgisApp::getThemeIcon("/mActionToggleEditing.png"));
|
||||||
mDeleteAttributeButton->setIcon(QgisApp::getThemeIcon("/mActionDeleteAttribute.png"));
|
|
||||||
btnEdit->setIcon(QgisApp::getThemeIcon("/mActionToggleEditing.png"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::setTitle(QString title)
|
void QgsAttributeTableDisplay::editingToggled()
|
||||||
{
|
{
|
||||||
setWindowTitle(title);
|
mToggleEditingButton->setChecked( mLayer->isEditable() );
|
||||||
}
|
tblAttributes->setReadOnly( !mLayer->isEditable() );
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::deleteAttributes()
|
|
||||||
{
|
|
||||||
QgsDelAttrDialog dialog(table()->horizontalHeader());
|
|
||||||
if(dialog.exec()==QDialog::Accepted)
|
|
||||||
{
|
|
||||||
const std::list<QString>* attlist=dialog.selectedAttributes();
|
|
||||||
for(std::list<QString>::const_iterator iter=attlist->begin();iter!=attlist->end();++iter)
|
|
||||||
{
|
|
||||||
table()->deleteAttribute(*iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::addAttribute()
|
|
||||||
{
|
|
||||||
QgsAddAttrDialog dialog(mLayer->getDataProvider(), this);
|
|
||||||
if(dialog.exec()==QDialog::Accepted)
|
|
||||||
{
|
|
||||||
if(!table()->addAttribute(dialog.name(),dialog.type()))
|
|
||||||
{
|
|
||||||
QMessageBox::information(this,tr("Name conflict"),tr("The attribute could not be inserted. The name already exists in the table."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::startEditing()
|
|
||||||
{
|
|
||||||
QgsVectorDataProvider* provider=mLayer->getDataProvider();
|
|
||||||
bool editing=false;
|
|
||||||
|
|
||||||
if(provider)
|
|
||||||
{
|
|
||||||
if(provider->capabilities()&QgsVectorDataProvider::AddAttributes)
|
|
||||||
{
|
|
||||||
mAddAttributeButton->setEnabled(true);
|
|
||||||
editing=true;
|
|
||||||
}
|
|
||||||
if(provider->capabilities()&QgsVectorDataProvider::DeleteAttributes)
|
|
||||||
{
|
|
||||||
|
|
||||||
mDeleteAttributeButton->setEnabled(true);
|
|
||||||
editing=true;
|
|
||||||
}
|
|
||||||
if(provider->capabilities()&QgsVectorDataProvider::ChangeAttributeValues)
|
|
||||||
{
|
|
||||||
table()->setReadOnly(false);
|
|
||||||
table()->setColumnReadOnly(0,true);//id column is not editable
|
|
||||||
editing=true;
|
|
||||||
}
|
|
||||||
if(editing)
|
|
||||||
{
|
|
||||||
btnEdit->setText(tr("Stop editing"));
|
|
||||||
buttonBox->button(QDialogButtonBox::Close)->setEnabled(false);
|
|
||||||
//make the dialog modal when in editable
|
|
||||||
//otherwise map editing and table editing
|
|
||||||
//may disturb each other
|
|
||||||
//hide();
|
|
||||||
//setModal(true);
|
|
||||||
//show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//revert button
|
|
||||||
QMessageBox::information(this,tr("Editing not permitted"),tr("The data provider is read only, editing is not allowed."));
|
|
||||||
btnEdit->setChecked(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::on_btnEdit_toggled(bool theFlag)
|
|
||||||
{
|
|
||||||
if (theFlag)
|
|
||||||
{
|
|
||||||
startEditing();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stopEditing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::stopEditing()
|
|
||||||
{
|
|
||||||
if(table()->edited())
|
|
||||||
{
|
|
||||||
//commit or roll back?
|
|
||||||
QMessageBox::StandardButton commit=QMessageBox::information(this,tr("Stop editing"),
|
|
||||||
tr("Do you want to save the changes?"),
|
|
||||||
QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
|
||||||
if(commit==QMessageBox::Save)
|
|
||||||
{
|
|
||||||
if(!table()->commitChanges(mLayer))
|
|
||||||
{
|
|
||||||
QMessageBox::information(this,tr("Error"),tr("Could not commit changes - changes are still pending"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(commit == QMessageBox::Discard)
|
|
||||||
{
|
|
||||||
table()->rollBack(mLayer);
|
|
||||||
}
|
|
||||||
else //cancel
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
btnEdit->setText(tr("Start editing"));
|
|
||||||
buttonBox->button(QDialogButtonBox::Close)->setEnabled(true);
|
|
||||||
mAddAttributeButton->setEnabled(false);
|
|
||||||
mDeleteAttributeButton->setEnabled(false);
|
|
||||||
table()->setReadOnly(true);
|
|
||||||
//make this dialog modeless again
|
|
||||||
hide();
|
|
||||||
setModal(false);
|
|
||||||
show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::selectedToTop()
|
void QgsAttributeTableDisplay::selectedToTop()
|
||||||
{
|
{
|
||||||
table()->bringSelectedToTop();
|
tblAttributes->bringSelectedToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::invertSelection()
|
void QgsAttributeTableDisplay::invertSelection()
|
||||||
{
|
{
|
||||||
if(mLayer)
|
if(!mLayer)
|
||||||
{
|
return;
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
mLayer->invertSelection();
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
QApplication::restoreOverrideCursor();
|
mLayer->invertSelection();
|
||||||
}
|
QApplication::restoreOverrideCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::removeSelection()
|
void QgsAttributeTableDisplay::removeSelection()
|
||||||
{
|
{
|
||||||
table()->clearSelection();
|
tblAttributes->clearSelection();
|
||||||
mLayer->triggerRepaint();
|
mLayer->triggerRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::copySelectedRowsToClipboard()
|
void QgsAttributeTableDisplay::copySelectedRowsToClipboard()
|
||||||
{
|
{
|
||||||
// Deprecated
|
QgisApp::instance()->editCopy(mLayer);
|
||||||
// table()->copySelectedRows();
|
|
||||||
|
|
||||||
// Use the Application's copy method instead
|
|
||||||
mQgisApp->editCopy(mLayer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::zoomMapToSelectedRows()
|
void QgsAttributeTableDisplay::zoomMapToSelectedRows()
|
||||||
{
|
{
|
||||||
mQgisApp->zoomToSelected();
|
QgisApp::instance()->zoomToSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::search()
|
void QgsAttributeTableDisplay::search()
|
||||||
{
|
{
|
||||||
// if selected field is numeric, numeric comparison will be used
|
int type = tblAttributes->item(0, mSearchColumns->currentIndex())->data(QgsAttributeTable::AttributeType).toInt();
|
||||||
// else attributes containing entered text will be matched
|
|
||||||
|
|
||||||
QgsVectorDataProvider* provider = mLayer->getDataProvider();
|
|
||||||
int item = mSearchColumns->currentIndex();
|
|
||||||
QVariant::Type type = provider->fields()[item].type();
|
|
||||||
bool numeric = (type == QVariant::Int || type == QVariant::Double);
|
bool numeric = (type == QVariant::Int || type == QVariant::Double);
|
||||||
|
|
||||||
QString str;
|
QString str;
|
||||||
@ -314,25 +237,25 @@ void QgsAttributeTableDisplay::searchShowResultsChanged(int item)
|
|||||||
|
|
||||||
if (item == 2) // show only matching
|
if (item == 2) // show only matching
|
||||||
{
|
{
|
||||||
table()->showRowsWithId(mSearchIds);
|
tblAttributes->showRowsWithId(mSearchIds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// make sure that all rows are shown
|
// make sure that all rows are shown
|
||||||
table()->showAllRows();
|
tblAttributes->showAllRows();
|
||||||
|
|
||||||
// select matching
|
// select matching
|
||||||
mLayer->setSelectedFeatures(mSearchIds);
|
mLayer->setSelectedFeatures(mSearchIds);
|
||||||
|
|
||||||
if (item == 1) // select matching and bring to top
|
if (item == 1) // select matching and bring to top
|
||||||
table()->bringSelectedToTop();
|
tblAttributes->bringSelectedToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::doSearch(const QString& searchString)
|
void QgsAttributeTableDisplay::doSearch(QString searchString)
|
||||||
{
|
{
|
||||||
mSearchString = searchString;
|
mSearchString = searchString;
|
||||||
|
|
||||||
@ -343,6 +266,7 @@ void QgsAttributeTableDisplay::doSearch(const QString& searchString)
|
|||||||
QMessageBox::critical(this, tr("Search string parsing error"), search.parserErrorMsg());
|
QMessageBox::critical(this, tr("Search string parsing error"), search.parserErrorMsg());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSearchTreeNode* searchTree = search.tree();
|
QgsSearchTreeNode* searchTree = search.tree();
|
||||||
if (searchTree == NULL)
|
if (searchTree == NULL)
|
||||||
{
|
{
|
||||||
@ -354,24 +278,19 @@ void QgsAttributeTableDisplay::doSearch(const QString& searchString)
|
|||||||
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
// TODO: need optimized getNextFeature which won't extract geometry
|
|
||||||
// or search by traversing table ... which one is quicker?
|
|
||||||
QgsFeature fet;
|
|
||||||
QgsVectorDataProvider* provider = mLayer->getDataProvider();
|
|
||||||
mSearchIds.clear();
|
mSearchIds.clear();
|
||||||
const QgsFieldMap& fields = provider->fields();
|
|
||||||
QgsAttributeList all = provider->allAttributesList();
|
|
||||||
|
|
||||||
provider->select(all, QgsRect(), false);
|
|
||||||
|
|
||||||
while (provider->getNextFeature(fet))
|
mLayer->select(mLayer->pendingAllAttributesList(), true, false);
|
||||||
|
|
||||||
|
QgsFeature f;
|
||||||
|
while( mLayer->getNextFeature(f) )
|
||||||
{
|
{
|
||||||
if (searchTree->checkAgainst(fields, fet.attributeMap()))
|
if (searchTree->checkAgainst(mLayer->pendingFields(), f.attributeMap()))
|
||||||
{
|
{
|
||||||
mSearchIds.insert(fet.featureId());
|
mSearchIds << f.featureId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if there were errors during evaulating
|
// check if there were errors during evaluating
|
||||||
if (searchTree->hasError())
|
if (searchTree->hasError())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -386,22 +305,13 @@ void QgsAttributeTableDisplay::doSearch(const QString& searchString)
|
|||||||
|
|
||||||
// update table
|
// update table
|
||||||
searchShowResultsChanged(mSearchShowResults->currentIndex());
|
searchShowResultsChanged(mSearchShowResults->currentIndex());
|
||||||
|
|
||||||
QString str;
|
QString str;
|
||||||
if (mSearchIds.size())
|
if (mSearchIds.size())
|
||||||
str.sprintf(tr("Found %d matching features.","", mSearchIds.size()).toUtf8(), mSearchIds.size());
|
str.sprintf(tr("Found %d matching features.","", mSearchIds.size()).toUtf8(), mSearchIds.size());
|
||||||
else
|
else
|
||||||
str = tr("No matching features found.");
|
str = tr("No matching features found.");
|
||||||
QMessageBox::information(this, tr("Search results"), str);
|
QMessageBox::information(this, tr("Search results"), str);
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::closeEvent(QCloseEvent* ev)
|
|
||||||
{
|
|
||||||
saveWindowLocation();
|
|
||||||
ev->ignore();
|
|
||||||
emit deleted();
|
|
||||||
delete this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsAttributeTableDisplay::restorePosition()
|
void QgsAttributeTableDisplay::restorePosition()
|
||||||
@ -423,16 +333,77 @@ void QgsAttributeTableDisplay::showHelp()
|
|||||||
|
|
||||||
void QgsAttributeTableDisplay::changeFeatureAttribute(int row, int column)
|
void QgsAttributeTableDisplay::changeFeatureAttribute(int row, int column)
|
||||||
{
|
{
|
||||||
QgsFeatureList &flist = mLayer->addedFeatures();
|
if(column==0)
|
||||||
|
|
||||||
int id = table()->item(row,0)->text().toInt();
|
|
||||||
|
|
||||||
int i;
|
|
||||||
for(i=0; i<flist.size() && flist[i].featureId()!=id; i++)
|
|
||||||
;
|
|
||||||
|
|
||||||
if(i==flist.size())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
flist[i].changeAttribute(column-1, table()->item(row,column)->text());
|
if( !mLayer->isEditable() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mLayer->changeAttributeValue(
|
||||||
|
tblAttributes->item(row,0)->text().toInt(),
|
||||||
|
tblAttributes->horizontalHeaderItem(column)->data(QgsAttributeTable::AttributeIndex).toInt(),
|
||||||
|
tblAttributes->item(row, column)->text(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QgsVectorLayer *, QgsAttributeTableDisplay *> QgsAttributeTableDisplay::smTables;
|
||||||
|
|
||||||
|
QgsAttributeTableDisplay *QgsAttributeTableDisplay::attributeTable(QgsVectorLayer *layer)
|
||||||
|
{
|
||||||
|
if(!layer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if( smTables.contains(layer) ) {
|
||||||
|
QgsAttributeTableDisplay *td = smTables[layer];
|
||||||
|
td->setAttributeActions(*layer->actions());
|
||||||
|
td->raise();
|
||||||
|
|
||||||
|
return td;
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsAttributeTableDisplay *td = new QgsAttributeTableDisplay(layer);
|
||||||
|
if(!td)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// display the attribute table
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
td->fillTable();
|
||||||
|
}
|
||||||
|
catch(std::bad_alloc& ba)
|
||||||
|
{
|
||||||
|
Q_UNUSED(ba);
|
||||||
|
QMessageBox::critical(0, tr("bad_alloc exception"), tr("Filling the attribute table has been stopped because there was no more virtual memory left"));
|
||||||
|
delete td;
|
||||||
|
td=NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
||||||
|
if(!td)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
smTables[layer] = td;
|
||||||
|
td->show();
|
||||||
|
|
||||||
|
return td;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::selectionChanged()
|
||||||
|
{
|
||||||
|
// select rows which should be selected
|
||||||
|
selectRowsWithId( mLayer->selectedFeaturesIds() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::attributeAdded(int attr)
|
||||||
|
{
|
||||||
|
tblAttributes->addAttribute(attr, mLayer->pendingFields()[attr]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributeTableDisplay::attributeDeleted(int attr)
|
||||||
|
{
|
||||||
|
tblAttributes->deleteAttribute(attr);
|
||||||
}
|
}
|
||||||
|
@ -22,47 +22,41 @@
|
|||||||
|
|
||||||
#include "ui_qgsattributetablebase.h"
|
#include "ui_qgsattributetablebase.h"
|
||||||
|
|
||||||
|
class QDockWidget;
|
||||||
class QgsAttributeTable;
|
class QgsAttributeTable;
|
||||||
class QgsVectorLayer;
|
class QgsVectorLayer;
|
||||||
class QgisApp;
|
class QgisApp;
|
||||||
|
class QgsAttributeActions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*@author Gary E.Sherman
|
*@author Gary E.Sherman
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QgsAttributeTableDisplay:public QDialog, private Ui::QgsAttributeTableBase
|
class QgsAttributeTableDisplay : public QDialog, private Ui::QgsAttributeTableBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
/**
|
static QgsAttributeTableDisplay *attributeTable(QgsVectorLayer *layer);
|
||||||
\param qgisApp This should be the QgisApp that spawned this table.
|
|
||||||
Otherwise the Copy button on this QgsAttributeTableDisplay
|
|
||||||
will not work.
|
|
||||||
*/
|
|
||||||
QgsAttributeTableDisplay(QgsVectorLayer* layer, QgisApp * qgisApp);
|
|
||||||
~QgsAttributeTableDisplay();
|
~QgsAttributeTableDisplay();
|
||||||
|
|
||||||
QgsAttributeTable *table();
|
void fillTable();
|
||||||
void setTitle(QString title);
|
|
||||||
protected:
|
protected:
|
||||||
|
QgsAttributeTableDisplay(QgsVectorLayer* layer);
|
||||||
|
|
||||||
QgsVectorLayer* mLayer;
|
QgsVectorLayer* mLayer;
|
||||||
|
|
||||||
QgisApp * mQgisApp;
|
void doSearch(QString searchString);
|
||||||
|
void setAttributeActions(const QgsAttributeAction &actions);
|
||||||
|
void selectRowsWithId(const QgsFeatureIds &ids);
|
||||||
|
|
||||||
void doSearch(const QString& searchString);
|
virtual void closeEvent(QCloseEvent *ev);
|
||||||
|
|
||||||
virtual void closeEvent(QCloseEvent* ev);
|
|
||||||
|
|
||||||
/** array of feature IDs that match last searched condition */
|
/** array of feature IDs that match last searched condition */
|
||||||
QgsFeatureIds mSearchIds;
|
QgsFeatureIds mSearchIds;
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void deleteAttributes();
|
|
||||||
void addAttribute();
|
|
||||||
void on_btnEdit_toggled(bool theFlag);
|
|
||||||
void startEditing();
|
|
||||||
void stopEditing();
|
|
||||||
void selectedToTop();
|
void selectedToTop();
|
||||||
void invertSelection();
|
void invertSelection();
|
||||||
void removeSelection();
|
void removeSelection();
|
||||||
@ -72,12 +66,18 @@ class QgsAttributeTableDisplay:public QDialog, private Ui::QgsAttributeTableBase
|
|||||||
void advancedSearch();
|
void advancedSearch();
|
||||||
void searchShowResultsChanged(int item);
|
void searchShowResultsChanged(int item);
|
||||||
void showHelp();
|
void showHelp();
|
||||||
|
void toggleEditing();
|
||||||
|
|
||||||
|
void attributeAdded(int idx);
|
||||||
|
void attributeDeleted(int idx);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void changeFeatureAttribute(int row, int column);
|
void changeFeatureAttribute(int row, int column);
|
||||||
|
void editingToggled();
|
||||||
|
void selectionChanged();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deleted();
|
void editingToggled(QgsMapLayer *);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Set the icon theme for this dialog */
|
/** Set the icon theme for this dialog */
|
||||||
@ -88,7 +88,11 @@ class QgsAttributeTableDisplay:public QDialog, private Ui::QgsAttributeTableBase
|
|||||||
|
|
||||||
QString mSearchString;
|
QString mSearchString;
|
||||||
|
|
||||||
|
QDockWidget *mDock;
|
||||||
|
|
||||||
static const int context_id = 831088384;
|
static const int context_id = 831088384;
|
||||||
|
|
||||||
|
static QMap<QgsVectorLayer *, QgsAttributeTableDisplay *> smTables;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -227,14 +227,12 @@ void QgsBookmarks::zoomToBookmark()
|
|||||||
QString xmax = QString::fromUtf8((const char *)sqlite3_column_text(ppStmt, 2));
|
QString xmax = QString::fromUtf8((const char *)sqlite3_column_text(ppStmt, 2));
|
||||||
QString ymax = QString::fromUtf8((const char *)sqlite3_column_text(ppStmt, 3));
|
QString ymax = QString::fromUtf8((const char *)sqlite3_column_text(ppStmt, 3));
|
||||||
// set the extent to the bookmark
|
// set the extent to the bookmark
|
||||||
dynamic_cast<QgisApp*>(mParent)->setExtent(QgsRect(xmin.toDouble(),
|
QgisApp::instance()->setExtent(QgsRect(xmin.toDouble(),
|
||||||
ymin.toDouble(),
|
ymin.toDouble(),
|
||||||
xmax.toDouble(),
|
xmax.toDouble(),
|
||||||
ymax.toDouble()));
|
ymax.toDouble()));
|
||||||
// redraw the map
|
// redraw the map
|
||||||
dynamic_cast<QgisApp*>(mParent)->getMapCanvas()->refresh();
|
QgisApp::instance()->getMapCanvas()->refresh();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,11 +23,9 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
class QgsFeature;
|
#include "qgsfield.h"
|
||||||
class QgsField;
|
#include "qgsfeature.h"
|
||||||
|
|
||||||
typedef QList<QgsFeature> QgsFeatureList;
|
|
||||||
typedef QMap<int, QgsField> QgsFieldMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
||||||
@ -74,18 +72,18 @@ public:
|
|||||||
* when it's done with it.
|
* when it's done with it.
|
||||||
*/
|
*/
|
||||||
QgsFeatureList copyOf();
|
QgsFeatureList copyOf();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clears the internal clipboard.
|
* Clears the internal clipboard.
|
||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Inserts a copy of the feature on the internal clipboard.
|
* Inserts a copy of the feature on the internal clipboard.
|
||||||
*/
|
*/
|
||||||
void insert( QgsFeature& feature );
|
void insert( QgsFeature& feature );
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** QGIS-internal vector feature clipboard.
|
/** QGIS-internal vector feature clipboard.
|
||||||
|
@ -38,8 +38,8 @@ email : sherman at mrcc.com
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
QgsDbSourceSelect::QgsDbSourceSelect(QgisApp *app, Qt::WFlags fl)
|
QgsDbSourceSelect::QgsDbSourceSelect(QWidget *parent, Qt::WFlags fl)
|
||||||
: QDialog(app, fl), mColumnTypeThread(NULL), qgisApp(app), pd(0)
|
: QDialog(parent, fl), mColumnTypeThread(NULL), pd(0)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
btnAdd->setEnabled(false);
|
btnAdd->setEnabled(false);
|
||||||
|
@ -54,7 +54,7 @@ class QgsDbSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
QgsDbSourceSelect(QgisApp *app, Qt::WFlags fl = QgisGui::ModalDialogFlags);
|
QgsDbSourceSelect(QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags);
|
||||||
//! Destructor
|
//! Destructor
|
||||||
~QgsDbSourceSelect();
|
~QgsDbSourceSelect();
|
||||||
//! Opens the create connection dialog to build a new connection
|
//! Opens the create connection dialog to build a new connection
|
||||||
@ -136,8 +136,6 @@ class QgsDbSourceSelect : public QDialog, private Ui::QgsDbSourceSelectBase
|
|||||||
QStringList m_selectedTables;
|
QStringList m_selectedTables;
|
||||||
// Storage for the range of layer type icons
|
// Storage for the range of layer type icons
|
||||||
QMap<QString, QPair<QString, QIcon> > mLayerIcons;
|
QMap<QString, QPair<QString, QIcon> > mLayerIcons;
|
||||||
//! Pointer to the qgis application mainwindow
|
|
||||||
QgisApp *qgisApp;
|
|
||||||
PGconn *pd;
|
PGconn *pd;
|
||||||
static const int context_id = 939347163;
|
static const int context_id = 939347163;
|
||||||
//! Model that acts as datasource for mTableTreeWidget
|
//! Model that acts as datasource for mTableTreeWidget
|
||||||
|
@ -186,6 +186,15 @@ void QgsIdentifyResults::addDerivedAttribute(QTreeWidgetItem * fnode, QString fi
|
|||||||
new QTreeWidgetItem(daRootNode, labels);
|
new QTreeWidgetItem(daRootNode, labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsIdentifyResults::addEdit(QTreeWidgetItem * fnode, int id)
|
||||||
|
{
|
||||||
|
QStringList labels;
|
||||||
|
labels << "edit" << QString::number(id);
|
||||||
|
QTreeWidgetItem *item = new QTreeWidgetItem(fnode, labels );
|
||||||
|
|
||||||
|
item->setIcon ( 0, QgisApp::getThemeIcon("/mIconEditable.png") );
|
||||||
|
}
|
||||||
|
|
||||||
void QgsIdentifyResults::addAction(QTreeWidgetItem * fnode, int id, QString field, QString value)
|
void QgsIdentifyResults::addAction(QTreeWidgetItem * fnode, int id, QString field, QString value)
|
||||||
{
|
{
|
||||||
QStringList labels;
|
QStringList labels;
|
||||||
@ -198,7 +207,7 @@ void QgsIdentifyResults::addAction(QTreeWidgetItem * fnode, int id, QString fiel
|
|||||||
/** Add a feature node to the list */
|
/** Add a feature node to the list */
|
||||||
QTreeWidgetItem *QgsIdentifyResults::addNode(QString label)
|
QTreeWidgetItem *QgsIdentifyResults::addNode(QString label)
|
||||||
{
|
{
|
||||||
return (new QTreeWidgetItem(lstResults, QStringList(label)));
|
return new QTreeWidgetItem(lstResults, QStringList(label));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsIdentifyResults::setTitle(QString title)
|
void QgsIdentifyResults::setTitle(QString title)
|
||||||
@ -251,15 +260,21 @@ void QgsIdentifyResults::setActions( const QgsAttributeAction& actions )
|
|||||||
|
|
||||||
void QgsIdentifyResults::clicked ( QTreeWidgetItem *item )
|
void QgsIdentifyResults::clicked ( QTreeWidgetItem *item )
|
||||||
{
|
{
|
||||||
if ( !item ) return;
|
if ( !item )
|
||||||
|
return;
|
||||||
|
|
||||||
if ( item->text(2) != "action" ) return;
|
if ( item->text(2) == "action" )
|
||||||
|
{
|
||||||
|
int id = item->text(3).toInt();
|
||||||
|
|
||||||
int id = item->text(3).toInt();
|
extractAllItemData(item);
|
||||||
|
|
||||||
extractAllItemData(item);
|
mActions.doAction(id, mValues, mClickedOnValue);
|
||||||
|
}
|
||||||
mActions.doAction(id, mValues, mClickedOnValue);
|
else if( item->text(0) == "edit" )
|
||||||
|
{
|
||||||
|
emit editFeature( item->text(1).toInt() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void QgsIdentifyResults::on_buttonHelp_clicked()
|
void QgsIdentifyResults::on_buttonHelp_clicked()
|
||||||
{
|
{
|
||||||
@ -325,7 +340,7 @@ void QgsIdentifyResults::extractAllItemData(QTreeWidgetItem* item)
|
|||||||
parent = child;
|
parent = child;
|
||||||
|
|
||||||
mValues.clear();
|
mValues.clear();
|
||||||
|
|
||||||
// For the code below we
|
// For the code below we
|
||||||
// need to do the comparison on the text strings rather than the
|
// need to do the comparison on the text strings rather than the
|
||||||
// pointers because if the user clicked on the parent, we need
|
// pointers because if the user clicked on the parent, we need
|
||||||
@ -341,27 +356,27 @@ void QgsIdentifyResults::extractAllItemData(QTreeWidgetItem* item)
|
|||||||
if (parent->child(j)->text(0) == mDerivedLabel ) {
|
if (parent->child(j)->text(0) == mDerivedLabel ) {
|
||||||
for (int k = 0; k < parent->child(j)->childCount(); ++k)
|
for (int k = 0; k < parent->child(j)->childCount(); ++k)
|
||||||
{
|
{
|
||||||
mValues.push_back(
|
mValues.push_back(
|
||||||
std::make_pair(mDerivedLabel + "."
|
std::make_pair(mDerivedLabel + "."
|
||||||
+ parent->child(j)->child(k)->text(0),
|
+ parent->child(j)->child(k)->text(0),
|
||||||
parent->child(j)->child(k)->text(1)));
|
parent->child(j)->child(k)->text(1)));
|
||||||
|
|
||||||
if (item == parent->child(j)->child(k))
|
if (item == parent->child(j)->child(k))
|
||||||
{
|
{
|
||||||
mClickedOnValue = valuesIndex;
|
mClickedOnValue = valuesIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
valuesIndex++;
|
valuesIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // do the actual feature attributes
|
else // do the actual feature attributes
|
||||||
{
|
{
|
||||||
mValues.push_back(std::make_pair(parent->child(j)->text(0),
|
mValues.push_back(std::make_pair(parent->child(j)->text(0),
|
||||||
parent->child(j)->text(1)));
|
parent->child(j)->text(1)));
|
||||||
|
|
||||||
if (item == parent->child(j))
|
if (item == parent->child(j))
|
||||||
{
|
{
|
||||||
mClickedOnValue = valuesIndex;
|
mClickedOnValue = valuesIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
valuesIndex++;
|
valuesIndex++;
|
||||||
|
@ -57,6 +57,9 @@ class QgsIdentifyResults: public QDialog, private Ui::QgsIdentifyResultsBase
|
|||||||
/** Add an action to the feature display node */
|
/** Add an action to the feature display node */
|
||||||
void addAction(QTreeWidgetItem *parent, int id, QString field, QString value);
|
void addAction(QTreeWidgetItem *parent, int id, QString field, QString value);
|
||||||
|
|
||||||
|
/** Add an edit action to the feature display node */
|
||||||
|
void addEdit(QTreeWidgetItem *parent, int id);
|
||||||
|
|
||||||
/** Add a feature node to the feature display */
|
/** Add a feature node to the feature display */
|
||||||
QTreeWidgetItem * addNode(QString label);
|
QTreeWidgetItem * addNode(QString label);
|
||||||
/** Set the title for the identify results dialog */
|
/** Set the title for the identify results dialog */
|
||||||
@ -85,6 +88,7 @@ class QgsIdentifyResults: public QDialog, private Ui::QgsIdentifyResultsBase
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void selectedFeatureChanged(int featureId);
|
void selectedFeatureChanged(int featureId);
|
||||||
|
void editFeature(int featureId);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
@ -110,26 +114,27 @@ class QgsIdentifyResults: public QDialog, private Ui::QgsIdentifyResultsBase
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QgsAttributeAction mActions;
|
bool mEditable;
|
||||||
int mClickedOnValue;
|
QgsAttributeAction mActions;
|
||||||
QMenu* mActionPopup;
|
int mClickedOnValue;
|
||||||
std::vector<std::pair<QString, QString> > mValues;
|
QMenu* mActionPopup;
|
||||||
static const int context_id = 689216579;
|
std::vector<std::pair<QString, QString> > mValues;
|
||||||
int mCurrentFeatureId;
|
static const int context_id = 689216579;
|
||||||
QString mDerivedLabel;
|
int mCurrentFeatureId;
|
||||||
|
QString mDerivedLabel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Keeps track of what derived-attribute (e.g. Length, Area)
|
Keeps track of what derived-attribute (e.g. Length, Area)
|
||||||
root nodes have been generated for each feature in this widget.
|
root nodes have been generated for each feature in this widget.
|
||||||
|
|
||||||
First item: Feature root node
|
First item: Feature root node
|
||||||
Second item: Derived-attribute root node for that feature
|
Second item: Derived-attribute root node for that feature
|
||||||
*/
|
*/
|
||||||
std::map<QTreeWidgetItem *, QTreeWidgetItem *> mDerivedAttributeRootNodes;
|
std::map<QTreeWidgetItem *, QTreeWidgetItem *> mDerivedAttributeRootNodes;
|
||||||
|
|
||||||
// Convenience function to populate mValues with all of the item names and
|
// Convenience function to populate mValues with all of the item names and
|
||||||
// values for a item, including the derived ones.
|
// values for a item, including the derived ones.
|
||||||
void extractAllItemData(QTreeWidgetItem* item);
|
void extractAllItemData(QTreeWidgetItem* item);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,419 +42,420 @@ QgsMapToolAddFeature::~QgsMapToolAddFeature()
|
|||||||
void QgsMapToolAddFeature::canvasReleaseEvent(QMouseEvent * e)
|
void QgsMapToolAddFeature::canvasReleaseEvent(QMouseEvent * e)
|
||||||
{
|
{
|
||||||
QgsVectorLayer *vlayer = dynamic_cast <QgsVectorLayer*>(mCanvas->currentLayer());
|
QgsVectorLayer *vlayer = dynamic_cast <QgsVectorLayer*>(mCanvas->currentLayer());
|
||||||
|
|
||||||
if (!vlayer)
|
if (!vlayer)
|
||||||
{
|
{
|
||||||
QMessageBox::information(0, QObject::tr("Not a vector layer"),
|
QMessageBox::information(0, QObject::tr("Not a vector layer"),
|
||||||
QObject::tr("The current layer is not a vector layer"));
|
QObject::tr("The current layer is not a vector layer"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QGis::WKBTYPE layerWKBType = vlayer->geometryType();
|
QGis::WKBTYPE layerWKBType = vlayer->geometryType();
|
||||||
|
|
||||||
//no support for adding features to 2.5D types yet
|
//no support for adding features to 2.5D types yet
|
||||||
if(layerWKBType == QGis::WKBLineString25D || layerWKBType == QGis::WKBPolygon25D || \
|
if(layerWKBType == QGis::WKBLineString25D || layerWKBType == QGis::WKBPolygon25D || \
|
||||||
layerWKBType == QGis::WKBMultiLineString25D || layerWKBType == QGis::WKBPoint25D || layerWKBType == QGis::WKBMultiPoint25D)
|
layerWKBType == QGis::WKBMultiLineString25D || layerWKBType == QGis::WKBPoint25D || layerWKBType == QGis::WKBMultiPoint25D)
|
||||||
{
|
{
|
||||||
QMessageBox::critical(0, QObject::tr("2.5D shape type not supported"), QObject::tr("Adding features to 2.5D shapetypes is not supported yet"));
|
QMessageBox::critical(0, QObject::tr("2.5D shape type not supported"), QObject::tr("Adding features to 2.5D shapetypes is not supported yet"));
|
||||||
delete mRubberBand;
|
delete mRubberBand;
|
||||||
mRubberBand = NULL;
|
mRubberBand = NULL;
|
||||||
mCapturing = FALSE;
|
mCapturing = FALSE;
|
||||||
mCaptureList.clear();
|
mCaptureList.clear();
|
||||||
mCanvas->refresh();
|
mCanvas->refresh();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsVectorDataProvider* provider = vlayer->getDataProvider();
|
QgsVectorDataProvider* provider = vlayer->getDataProvider();
|
||||||
|
|
||||||
if(!(provider->capabilities() & QgsVectorDataProvider::AddFeatures))
|
if(!(provider->capabilities() & QgsVectorDataProvider::AddFeatures))
|
||||||
{
|
{
|
||||||
QMessageBox::information(0, QObject::tr("Layer cannot be added to"),
|
QMessageBox::information(0, QObject::tr("Layer cannot be added to"),
|
||||||
QObject::tr("The data provider for this layer does not support the addition of features."));
|
QObject::tr("The data provider for this layer does not support the addition of features."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vlayer->isEditable())
|
if (!vlayer->isEditable())
|
||||||
{
|
{
|
||||||
QMessageBox::information(0, QObject::tr("Layer not editable"),
|
QMessageBox::information(0, QObject::tr("Layer not editable"),
|
||||||
QObject::tr("Cannot edit the vector layer. To make it editable, go to the file item "
|
QObject::tr("Cannot edit the vector layer. To make it editable, go to the file item "
|
||||||
"of the layer, right click and check 'Allow Editing'."));
|
"of the layer, right click and check 'Allow Editing'."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// POINT CAPTURING
|
// POINT CAPTURING
|
||||||
if (mTool == CapturePoint)
|
if (mTool == CapturePoint)
|
||||||
|
{
|
||||||
|
//check we only use this tool for point/multipoint layers
|
||||||
|
if(vlayer->vectorType() != QGis::Point)
|
||||||
{
|
{
|
||||||
//check we only use this tool for point/multipoint layers
|
QMessageBox::information(0, QObject::tr("Wrong editing tool"),
|
||||||
if(vlayer->vectorType() != QGis::Point)
|
QObject::tr("Cannot apply the 'capture point' tool on this vector layer"));
|
||||||
{
|
return;
|
||||||
QMessageBox::information(0, QObject::tr("Wrong editing tool"),
|
}
|
||||||
QObject::tr("Cannot apply the 'capture point' tool on this vector layer"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QgsPoint idPoint; //point in map coordinates
|
QgsPoint idPoint; //point in map coordinates
|
||||||
QList<QgsSnappingResult> snapResults;
|
QList<QgsSnappingResult> snapResults;
|
||||||
QgsPoint savePoint; //point in layer coordinates
|
QgsPoint savePoint; //point in layer coordinates
|
||||||
|
|
||||||
if(mSnapper.snapToBackgroundLayers(e->pos(), snapResults) == 0)
|
if(mSnapper.snapToBackgroundLayers(e->pos(), snapResults) == 0)
|
||||||
|
{
|
||||||
|
idPoint = snapPointFromResults(snapResults, e->pos());
|
||||||
|
try
|
||||||
{
|
{
|
||||||
idPoint = snapPointFromResults(snapResults, e->pos());
|
savePoint = toLayerCoords(vlayer, idPoint);
|
||||||
try
|
QgsDebugMsg("savePoint = " + savePoint.stringRep());
|
||||||
{
|
}
|
||||||
savePoint = toLayerCoords(vlayer, idPoint);
|
catch(QgsCsException &cse)
|
||||||
QgsDebugMsg("savePoint = " + savePoint.stringRep());
|
{
|
||||||
}
|
Q_UNUSED(cse);
|
||||||
catch(QgsCsException &cse)
|
QMessageBox::information(0, QObject::tr("Coordinate transform error"), \
|
||||||
{
|
QObject::tr("Cannot transform the point to the layers coordinate system"));
|
||||||
Q_UNUSED(cse);
|
return;
|
||||||
QMessageBox::information(0, QObject::tr("Coordinate transform error"), \
|
|
||||||
QObject::tr("Cannot transform the point to the layers coordinate system"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// emit signal - QgisApp can catch it and save point position to clipboard
|
|
||||||
// FIXME: is this still actual or something old that's not used anymore?
|
|
||||||
//emit xyClickCoordinates(idPoint);
|
|
||||||
|
|
||||||
//only do the rest for provider with feature addition support
|
|
||||||
//note that for the grass provider, this will return false since
|
|
||||||
//grass provider has its own mechanism of feature addition
|
|
||||||
if(provider->capabilities() & QgsVectorDataProvider::AddFeatures)
|
|
||||||
{
|
|
||||||
QgsFeature* f = new QgsFeature(0,"WKBPoint");
|
|
||||||
|
|
||||||
int size = 0;
|
|
||||||
char end=QgsApplication::endian();
|
|
||||||
unsigned char *wkb = NULL;
|
|
||||||
int wkbtype = 0;
|
|
||||||
double x = savePoint.x();
|
|
||||||
double y = savePoint.y();
|
|
||||||
|
|
||||||
if(layerWKBType == QGis::WKBPoint)
|
|
||||||
{
|
|
||||||
size=1+sizeof(int)+2*sizeof(double);
|
|
||||||
wkb = new unsigned char[size];
|
|
||||||
wkbtype=QGis::WKBPoint;
|
|
||||||
memcpy(&wkb[0],&end,1);
|
|
||||||
memcpy(&wkb[1],&wkbtype, sizeof(int));
|
|
||||||
memcpy(&wkb[5], &x, sizeof(double));
|
|
||||||
memcpy(&wkb[5]+sizeof(double), &y, sizeof(double));
|
|
||||||
}
|
|
||||||
else if(layerWKBType == QGis::WKBMultiPoint)
|
|
||||||
{
|
|
||||||
size = 2+3*sizeof(int)+2*sizeof(double);
|
|
||||||
wkb = new unsigned char[size];
|
|
||||||
wkbtype=QGis::WKBMultiPoint;
|
|
||||||
int position = 0;
|
|
||||||
memcpy(&wkb[position], &end, 1);
|
|
||||||
position += 1;
|
|
||||||
memcpy(&wkb[position], &wkbtype, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
int npoint = 1;
|
|
||||||
memcpy(&wkb[position], &npoint, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &end, 1);
|
|
||||||
position += 1;
|
|
||||||
int pointtype = QGis::WKBPoint;
|
|
||||||
memcpy(&wkb[position],&pointtype, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &x, sizeof(double));
|
|
||||||
position += sizeof(double);
|
|
||||||
memcpy(&wkb[position], &y, sizeof(double));
|
|
||||||
}
|
|
||||||
|
|
||||||
f->setGeometryAndOwnership(&wkb[0],size);
|
|
||||||
// add the fields to the QgsFeature
|
|
||||||
const QgsFieldMap fields=provider->fields();
|
|
||||||
for(QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it)
|
|
||||||
{
|
|
||||||
f->addAttribute(it.key(), provider->getDefaultValue(it.key()) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// show the dialog to enter attribute values
|
// emit signal - QgisApp can catch it and save point position to clipboard
|
||||||
QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
|
// FIXME: is this still actual or something old that's not used anymore?
|
||||||
if (mypDialog->exec())
|
//emit xyClickCoordinates(idPoint);
|
||||||
|
|
||||||
|
//only do the rest for provider with feature addition support
|
||||||
|
//note that for the grass provider, this will return false since
|
||||||
|
//grass provider has its own mechanism of feature addition
|
||||||
|
if(provider->capabilities() & QgsVectorDataProvider::AddFeatures)
|
||||||
{
|
{
|
||||||
qDebug("Adding feature to layer");
|
QgsFeature* f = new QgsFeature(0,"WKBPoint");
|
||||||
vlayer->addFeature(*f);
|
|
||||||
|
int size = 0;
|
||||||
|
char end=QgsApplication::endian();
|
||||||
|
unsigned char *wkb = NULL;
|
||||||
|
int wkbtype = 0;
|
||||||
|
double x = savePoint.x();
|
||||||
|
double y = savePoint.y();
|
||||||
|
|
||||||
|
if(layerWKBType == QGis::WKBPoint)
|
||||||
|
{
|
||||||
|
size=1+sizeof(int)+2*sizeof(double);
|
||||||
|
wkb = new unsigned char[size];
|
||||||
|
wkbtype=QGis::WKBPoint;
|
||||||
|
memcpy(&wkb[0],&end,1);
|
||||||
|
memcpy(&wkb[1],&wkbtype, sizeof(int));
|
||||||
|
memcpy(&wkb[5], &x, sizeof(double));
|
||||||
|
memcpy(&wkb[5]+sizeof(double), &y, sizeof(double));
|
||||||
|
}
|
||||||
|
else if(layerWKBType == QGis::WKBMultiPoint)
|
||||||
|
{
|
||||||
|
size = 2+3*sizeof(int)+2*sizeof(double);
|
||||||
|
wkb = new unsigned char[size];
|
||||||
|
wkbtype=QGis::WKBMultiPoint;
|
||||||
|
int position = 0;
|
||||||
|
memcpy(&wkb[position], &end, 1);
|
||||||
|
position += 1;
|
||||||
|
memcpy(&wkb[position], &wkbtype, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
int npoint = 1;
|
||||||
|
memcpy(&wkb[position], &npoint, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &end, 1);
|
||||||
|
position += 1;
|
||||||
|
int pointtype = QGis::WKBPoint;
|
||||||
|
memcpy(&wkb[position],&pointtype, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &x, sizeof(double));
|
||||||
|
position += sizeof(double);
|
||||||
|
memcpy(&wkb[position], &y, sizeof(double));
|
||||||
|
}
|
||||||
|
|
||||||
|
f->setGeometryAndOwnership(&wkb[0],size);
|
||||||
|
// add the fields to the QgsFeature
|
||||||
|
const QgsFieldMap fields=vlayer->pendingFields();
|
||||||
|
for(QgsFieldMap::const_iterator it = fields.constBegin(); it != fields.constEnd(); ++it)
|
||||||
|
{
|
||||||
|
f->addAttribute(it.key(), provider->getDefaultValue(it.key()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the dialog to enter attribute values
|
||||||
|
QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
|
||||||
|
if (mypDialog->exec())
|
||||||
|
{
|
||||||
|
qDebug("Adding feature to layer");
|
||||||
|
vlayer->addFeature(*f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug("Adding feature to layer failed");
|
||||||
|
delete f;
|
||||||
|
}
|
||||||
|
delete mypDialog;
|
||||||
|
mCanvas->refresh();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
}
|
||||||
qDebug("Adding feature to layer failed");
|
|
||||||
delete f;
|
|
||||||
}
|
|
||||||
delete mypDialog;
|
|
||||||
mCanvas->refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (mTool == CaptureLine || mTool == CapturePolygon)
|
else if (mTool == CaptureLine || mTool == CapturePolygon)
|
||||||
|
{
|
||||||
|
//check we only use the line tool for line/multiline layers
|
||||||
|
if(mTool == CaptureLine && vlayer->vectorType() != QGis::Line)
|
||||||
{
|
{
|
||||||
//check we only use the line tool for line/multiline layers
|
QMessageBox::information(0, QObject::tr("Wrong editing tool"),
|
||||||
if(mTool == CaptureLine && vlayer->vectorType() != QGis::Line)
|
QObject::tr("Cannot apply the 'capture line' tool on this vector layer"));
|
||||||
{
|
return;
|
||||||
QMessageBox::information(0, QObject::tr("Wrong editing tool"),
|
}
|
||||||
QObject::tr("Cannot apply the 'capture line' tool on this vector layer"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check we only use the polygon tool for polygon/multipolygon layers
|
|
||||||
if(mTool == CapturePolygon && vlayer->vectorType() != QGis::Polygon)
|
|
||||||
{
|
|
||||||
QMessageBox::information(0, QObject::tr("Wrong editing tool"),
|
|
||||||
QObject::tr("Cannot apply the 'capture polygon' tool on this vector layer"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//add point to list and to rubber band
|
//check we only use the polygon tool for polygon/multipolygon layers
|
||||||
int error = addVertex(e->pos());
|
if(mTool == CapturePolygon && vlayer->vectorType() != QGis::Polygon)
|
||||||
if(error == 1)
|
|
||||||
{
|
|
||||||
//current layer is not a vector layer
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (error == 2)
|
|
||||||
{
|
|
||||||
//problem with coordinate transformation
|
|
||||||
QMessageBox::information(0, QObject::tr("Coordinate transform error"), \
|
|
||||||
QObject::tr("Cannot transform the point to the layers coordinate system"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e->button() == Qt::LeftButton)
|
|
||||||
{
|
|
||||||
mCapturing = TRUE;
|
|
||||||
}
|
|
||||||
else if (e->button() == Qt::RightButton)
|
|
||||||
{
|
|
||||||
// End of string
|
|
||||||
|
|
||||||
mCapturing = FALSE;
|
|
||||||
|
|
||||||
delete mRubberBand;
|
|
||||||
mRubberBand = NULL;
|
|
||||||
|
|
||||||
//lines: bail out if there are not at least two vertices
|
|
||||||
if(mTool == CaptureLine && mCaptureList.size() < 2)
|
|
||||||
{
|
|
||||||
mCaptureList.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//polygons: bail out if there are not at least two vertices
|
|
||||||
if(mTool == CapturePolygon && mCaptureList.size() < 3)
|
|
||||||
{
|
|
||||||
mCaptureList.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//create QgsFeature with wkb representation
|
|
||||||
QgsFeature* f = new QgsFeature(0,"WKBLineString");
|
|
||||||
unsigned char* wkb;
|
|
||||||
int size;
|
|
||||||
char end=QgsApplication::endian();
|
|
||||||
|
|
||||||
if(mTool == CaptureLine)
|
|
||||||
{
|
|
||||||
if(layerWKBType == QGis::WKBLineString)
|
|
||||||
{
|
|
||||||
size=1+2*sizeof(int)+2*mCaptureList.size()*sizeof(double);
|
|
||||||
wkb= new unsigned char[size];
|
|
||||||
int wkbtype=QGis::WKBLineString;
|
|
||||||
int length=mCaptureList.size();
|
|
||||||
memcpy(&wkb[0],&end,1);
|
|
||||||
memcpy(&wkb[1],&wkbtype, sizeof(int));
|
|
||||||
memcpy(&wkb[1+sizeof(int)],&length, sizeof(int));
|
|
||||||
int position=1+2*sizeof(int);
|
|
||||||
double x,y;
|
|
||||||
for(QList<QgsPoint>::iterator it=mCaptureList.begin();it!=mCaptureList.end();++it)
|
|
||||||
{
|
|
||||||
QgsPoint savePoint = *it;
|
|
||||||
x = savePoint.x();
|
|
||||||
y = savePoint.y();
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&x,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&y,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(layerWKBType == QGis::WKBMultiLineString)
|
|
||||||
{
|
|
||||||
size = 1+2*sizeof(int)+1+2*sizeof(int)+2*mCaptureList.size()*sizeof(double);
|
|
||||||
wkb= new unsigned char[size];
|
|
||||||
int position = 0;
|
|
||||||
int wkbtype=QGis::WKBMultiLineString;
|
|
||||||
memcpy(&wkb[position], &end, 1);
|
|
||||||
position += 1;
|
|
||||||
memcpy(&wkb[position], &wkbtype, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
int nlines = 1;
|
|
||||||
memcpy(&wkb[position], &nlines, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &end, 1);
|
|
||||||
position += 1;
|
|
||||||
int linewkbtype = QGis::WKBLineString;
|
|
||||||
memcpy(&wkb[position], &linewkbtype, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
int length=mCaptureList.size();
|
|
||||||
memcpy(&wkb[position], &length, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
double x,y;
|
|
||||||
for(QList<QgsPoint>::iterator it=mCaptureList.begin();it!=mCaptureList.end();++it)
|
|
||||||
{
|
|
||||||
QgsPoint savePoint = *it;
|
|
||||||
x = savePoint.x();
|
|
||||||
y = savePoint.y();
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&x,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&y,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Cannot add feature. Unknown WKB type"));
|
|
||||||
return; //unknown wkbtype
|
|
||||||
}
|
|
||||||
f->setGeometryAndOwnership(&wkb[0],size);
|
|
||||||
}
|
|
||||||
else // polygon
|
|
||||||
{
|
|
||||||
if(layerWKBType == QGis::WKBPolygon)
|
|
||||||
{
|
|
||||||
size=1+3*sizeof(int)+2*(mCaptureList.size()+1)*sizeof(double);
|
|
||||||
wkb= new unsigned char[size];
|
|
||||||
int wkbtype=QGis::WKBPolygon;
|
|
||||||
int length=mCaptureList.size()+1;//+1 because the first point is needed twice
|
|
||||||
int numrings=1;
|
|
||||||
memcpy(&wkb[0],&end,1);
|
|
||||||
memcpy(&wkb[1],&wkbtype, sizeof(int));
|
|
||||||
memcpy(&wkb[1+sizeof(int)],&numrings,sizeof(int));
|
|
||||||
memcpy(&wkb[1+2*sizeof(int)],&length, sizeof(int));
|
|
||||||
int position=1+3*sizeof(int);
|
|
||||||
double x,y;
|
|
||||||
QList<QgsPoint>::iterator it;
|
|
||||||
for(it=mCaptureList.begin();it!=mCaptureList.end();++it)
|
|
||||||
{
|
|
||||||
QgsPoint savePoint = *it;
|
|
||||||
x = savePoint.x();
|
|
||||||
y = savePoint.y();
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&x,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&y,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
}
|
|
||||||
// close the polygon
|
|
||||||
it=mCaptureList.begin();
|
|
||||||
QgsPoint savePoint = *it;
|
|
||||||
x = savePoint.x();
|
|
||||||
y = savePoint.y();
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&x,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&y,sizeof(double));
|
|
||||||
}
|
|
||||||
else if(layerWKBType == QGis::WKBMultiPolygon)
|
|
||||||
{
|
|
||||||
size = 2+5*sizeof(int)+2*(mCaptureList.size()+1)*sizeof(double);
|
|
||||||
wkb = new unsigned char[size];
|
|
||||||
int wkbtype = QGis::WKBMultiPolygon;
|
|
||||||
int polygontype = QGis::WKBPolygon;
|
|
||||||
int length = mCaptureList.size()+1;//+1 because the first point is needed twice
|
|
||||||
int numrings = 1;
|
|
||||||
int numpolygons = 1;
|
|
||||||
int position = 0; //pointer position relative to &wkb[0]
|
|
||||||
memcpy(&wkb[position],&end,1);
|
|
||||||
position += 1;
|
|
||||||
memcpy(&wkb[position],&wkbtype, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &numpolygons, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &end, 1);
|
|
||||||
position += 1;
|
|
||||||
memcpy(&wkb[position], &polygontype, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &numrings, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
memcpy(&wkb[position], &length, sizeof(int));
|
|
||||||
position += sizeof(int);
|
|
||||||
double x,y;
|
|
||||||
QList<QgsPoint>::iterator it;
|
|
||||||
for(it=mCaptureList.begin();it!=mCaptureList.end();++it)//add the captured points to the polygon
|
|
||||||
{
|
|
||||||
QgsPoint savePoint = *it;
|
|
||||||
x = savePoint.x();
|
|
||||||
y = savePoint.y();
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&x,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
|
|
||||||
memcpy(&wkb[position],&y,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
}
|
|
||||||
// close the polygon
|
|
||||||
it=mCaptureList.begin();
|
|
||||||
QgsPoint savePoint = *it;
|
|
||||||
x = savePoint.x();
|
|
||||||
y = savePoint.y();
|
|
||||||
memcpy(&wkb[position],&x,sizeof(double));
|
|
||||||
position+=sizeof(double);
|
|
||||||
memcpy(&wkb[position],&y,sizeof(double));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Cannot add feature. Unknown WKB type"));
|
|
||||||
return; //unknown wkbtype
|
|
||||||
}
|
|
||||||
f->setGeometryAndOwnership(&wkb[0],size);
|
|
||||||
//is automatic polygon intersection removal activated?
|
|
||||||
int avoidPolygonIntersections = QgsProject::instance()->readNumEntry("Digitizing", "/AvoidPolygonIntersections", 0);
|
|
||||||
|
|
||||||
if(avoidPolygonIntersections != 0)
|
|
||||||
{
|
|
||||||
if(vlayer->removePolygonIntersections(f->geometry()) != 0)
|
|
||||||
{
|
|
||||||
QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Could not remove polygon intersection"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the fields to the QgsFeature
|
|
||||||
const QgsFieldMap fields = provider->fields();
|
|
||||||
for(QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it)
|
|
||||||
{
|
|
||||||
f->addAttribute(it.key(), provider->getDefaultValue(it.key()));
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
|
|
||||||
if (mypDialog->exec())
|
|
||||||
{
|
{
|
||||||
if(vlayer->addFeature(*f))
|
QMessageBox::information(0, QObject::tr("Wrong editing tool"),
|
||||||
|
QObject::tr("Cannot apply the 'capture polygon' tool on this vector layer"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add point to list and to rubber band
|
||||||
|
int error = addVertex(e->pos());
|
||||||
|
if(error == 1)
|
||||||
|
{
|
||||||
|
//current layer is not a vector layer
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (error == 2)
|
||||||
|
{
|
||||||
|
//problem with coordinate transformation
|
||||||
|
QMessageBox::information(0, QObject::tr("Coordinate transform error"), \
|
||||||
|
QObject::tr("Cannot transform the point to the layers coordinate system"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
mCapturing = TRUE;
|
||||||
|
}
|
||||||
|
else if (e->button() == Qt::RightButton)
|
||||||
|
{
|
||||||
|
// End of string
|
||||||
|
|
||||||
|
mCapturing = FALSE;
|
||||||
|
|
||||||
|
delete mRubberBand;
|
||||||
|
mRubberBand = NULL;
|
||||||
|
|
||||||
|
//lines: bail out if there are not at least two vertices
|
||||||
|
if(mTool == CaptureLine && mCaptureList.size() < 2)
|
||||||
{
|
{
|
||||||
//add points to other features to keep topology up-to-date
|
mCaptureList.clear();
|
||||||
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
|
return;
|
||||||
if(topologicalEditing)
|
}
|
||||||
|
|
||||||
|
//polygons: bail out if there are not at least two vertices
|
||||||
|
if(mTool == CapturePolygon && mCaptureList.size() < 3)
|
||||||
|
{
|
||||||
|
mCaptureList.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//create QgsFeature with wkb representation
|
||||||
|
QgsFeature* f = new QgsFeature(0,"WKBLineString");
|
||||||
|
unsigned char* wkb;
|
||||||
|
int size;
|
||||||
|
char end=QgsApplication::endian();
|
||||||
|
|
||||||
|
if(mTool == CaptureLine)
|
||||||
|
{
|
||||||
|
if(layerWKBType == QGis::WKBLineString)
|
||||||
{
|
{
|
||||||
vlayer->addTopologicalPoints(f->geometry());
|
size=1+2*sizeof(int)+2*mCaptureList.size()*sizeof(double);
|
||||||
|
wkb= new unsigned char[size];
|
||||||
|
int wkbtype=QGis::WKBLineString;
|
||||||
|
int length=mCaptureList.size();
|
||||||
|
memcpy(&wkb[0],&end,1);
|
||||||
|
memcpy(&wkb[1],&wkbtype, sizeof(int));
|
||||||
|
memcpy(&wkb[1+sizeof(int)],&length, sizeof(int));
|
||||||
|
int position=1+2*sizeof(int);
|
||||||
|
double x,y;
|
||||||
|
for(QList<QgsPoint>::iterator it=mCaptureList.begin();it!=mCaptureList.end();++it)
|
||||||
|
{
|
||||||
|
QgsPoint savePoint = *it;
|
||||||
|
x = savePoint.x();
|
||||||
|
y = savePoint.y();
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&x,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&y,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(layerWKBType == QGis::WKBMultiLineString)
|
||||||
|
{
|
||||||
|
size = 1+2*sizeof(int)+1+2*sizeof(int)+2*mCaptureList.size()*sizeof(double);
|
||||||
|
wkb= new unsigned char[size];
|
||||||
|
int position = 0;
|
||||||
|
int wkbtype=QGis::WKBMultiLineString;
|
||||||
|
memcpy(&wkb[position], &end, 1);
|
||||||
|
position += 1;
|
||||||
|
memcpy(&wkb[position], &wkbtype, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
int nlines = 1;
|
||||||
|
memcpy(&wkb[position], &nlines, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &end, 1);
|
||||||
|
position += 1;
|
||||||
|
int linewkbtype = QGis::WKBLineString;
|
||||||
|
memcpy(&wkb[position], &linewkbtype, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
int length=mCaptureList.size();
|
||||||
|
memcpy(&wkb[position], &length, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
double x,y;
|
||||||
|
for(QList<QgsPoint>::iterator it=mCaptureList.begin();it!=mCaptureList.end();++it)
|
||||||
|
{
|
||||||
|
QgsPoint savePoint = *it;
|
||||||
|
x = savePoint.x();
|
||||||
|
y = savePoint.y();
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&x,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&y,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Cannot add feature. Unknown WKB type"));
|
||||||
|
return; //unknown wkbtype
|
||||||
|
}
|
||||||
|
f->setGeometryAndOwnership(&wkb[0],size);
|
||||||
|
}
|
||||||
|
else // polygon
|
||||||
|
{
|
||||||
|
if(layerWKBType == QGis::WKBPolygon)
|
||||||
|
{
|
||||||
|
size=1+3*sizeof(int)+2*(mCaptureList.size()+1)*sizeof(double);
|
||||||
|
wkb= new unsigned char[size];
|
||||||
|
int wkbtype=QGis::WKBPolygon;
|
||||||
|
int length=mCaptureList.size()+1;//+1 because the first point is needed twice
|
||||||
|
int numrings=1;
|
||||||
|
memcpy(&wkb[0],&end,1);
|
||||||
|
memcpy(&wkb[1],&wkbtype, sizeof(int));
|
||||||
|
memcpy(&wkb[1+sizeof(int)],&numrings,sizeof(int));
|
||||||
|
memcpy(&wkb[1+2*sizeof(int)],&length, sizeof(int));
|
||||||
|
int position=1+3*sizeof(int);
|
||||||
|
double x,y;
|
||||||
|
QList<QgsPoint>::iterator it;
|
||||||
|
for(it=mCaptureList.begin();it!=mCaptureList.end();++it)
|
||||||
|
{
|
||||||
|
QgsPoint savePoint = *it;
|
||||||
|
x = savePoint.x();
|
||||||
|
y = savePoint.y();
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&x,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&y,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
}
|
||||||
|
// close the polygon
|
||||||
|
it=mCaptureList.begin();
|
||||||
|
QgsPoint savePoint = *it;
|
||||||
|
x = savePoint.x();
|
||||||
|
y = savePoint.y();
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&x,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&y,sizeof(double));
|
||||||
|
}
|
||||||
|
else if(layerWKBType == QGis::WKBMultiPolygon)
|
||||||
|
{
|
||||||
|
size = 2+5*sizeof(int)+2*(mCaptureList.size()+1)*sizeof(double);
|
||||||
|
wkb = new unsigned char[size];
|
||||||
|
int wkbtype = QGis::WKBMultiPolygon;
|
||||||
|
int polygontype = QGis::WKBPolygon;
|
||||||
|
int length = mCaptureList.size()+1;//+1 because the first point is needed twice
|
||||||
|
int numrings = 1;
|
||||||
|
int numpolygons = 1;
|
||||||
|
int position = 0; //pointer position relative to &wkb[0]
|
||||||
|
memcpy(&wkb[position],&end,1);
|
||||||
|
position += 1;
|
||||||
|
memcpy(&wkb[position],&wkbtype, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &numpolygons, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &end, 1);
|
||||||
|
position += 1;
|
||||||
|
memcpy(&wkb[position], &polygontype, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &numrings, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
memcpy(&wkb[position], &length, sizeof(int));
|
||||||
|
position += sizeof(int);
|
||||||
|
double x,y;
|
||||||
|
QList<QgsPoint>::iterator it;
|
||||||
|
for(it=mCaptureList.begin();it!=mCaptureList.end();++it)//add the captured points to the polygon
|
||||||
|
{
|
||||||
|
QgsPoint savePoint = *it;
|
||||||
|
x = savePoint.x();
|
||||||
|
y = savePoint.y();
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&x,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
|
||||||
|
memcpy(&wkb[position],&y,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
}
|
||||||
|
// close the polygon
|
||||||
|
it=mCaptureList.begin();
|
||||||
|
QgsPoint savePoint = *it;
|
||||||
|
x = savePoint.x();
|
||||||
|
y = savePoint.y();
|
||||||
|
memcpy(&wkb[position],&x,sizeof(double));
|
||||||
|
position+=sizeof(double);
|
||||||
|
memcpy(&wkb[position],&y,sizeof(double));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Cannot add feature. Unknown WKB type"));
|
||||||
|
return; //unknown wkbtype
|
||||||
|
}
|
||||||
|
f->setGeometryAndOwnership(&wkb[0],size);
|
||||||
|
|
||||||
|
//is automatic polygon intersection removal activated?
|
||||||
|
int avoidPolygonIntersections = QgsProject::instance()->readNumEntry("Digitizing", "/AvoidPolygonIntersections", 0);
|
||||||
|
|
||||||
|
if(avoidPolygonIntersections != 0)
|
||||||
|
{
|
||||||
|
if(vlayer->removePolygonIntersections(f->geometry()) != 0)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(0, QObject::tr("Error"), QObject::tr("Could not remove polygon intersection"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
delete f;
|
// add the fields to the QgsFeature
|
||||||
delete mypDialog;
|
const QgsFieldMap fields = vlayer->pendingFields();
|
||||||
|
for(QgsFieldMap::const_iterator it = fields.begin(); it != fields.end(); ++it)
|
||||||
// delete the elements of mCaptureList
|
{
|
||||||
mCaptureList.clear();
|
f->addAttribute(it.key(), provider->getDefaultValue(it.key()));
|
||||||
mCanvas->refresh();
|
}
|
||||||
}
|
|
||||||
}
|
QgsAttributeDialog * mypDialog = new QgsAttributeDialog( vlayer, f );
|
||||||
|
if (mypDialog->exec())
|
||||||
|
{
|
||||||
|
if(vlayer->addFeature(*f))
|
||||||
|
{
|
||||||
|
//add points to other features to keep topology up-to-date
|
||||||
|
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
|
||||||
|
if(topologicalEditing)
|
||||||
|
{
|
||||||
|
vlayer->addTopologicalPoints(f->geometry());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete f;
|
||||||
|
delete mypDialog;
|
||||||
|
|
||||||
|
// delete the elements of mCaptureList
|
||||||
|
mCaptureList.clear();
|
||||||
|
mCanvas->refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "qgsspatialrefsys.h"
|
#include "qgsspatialrefsys.h"
|
||||||
#include "qgsvectordataprovider.h"
|
#include "qgsvectordataprovider.h"
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsattributedialog.h"
|
||||||
|
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
@ -73,7 +74,7 @@ void QgsMapToolIdentify::canvasReleaseEvent(QMouseEvent * e)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsMapLayer* layer = mCanvas->currentLayer();
|
mLayer = mCanvas->currentLayer();
|
||||||
|
|
||||||
// delete rubber band if there was any
|
// delete rubber band if there was any
|
||||||
delete mRubberBand;
|
delete mRubberBand;
|
||||||
@ -81,31 +82,31 @@ void QgsMapToolIdentify::canvasReleaseEvent(QMouseEvent * e)
|
|||||||
|
|
||||||
// call identify method for selected layer
|
// call identify method for selected layer
|
||||||
|
|
||||||
if (layer)
|
if (mLayer)
|
||||||
{
|
{
|
||||||
// In the special case of the WMS provider,
|
// In the special case of the WMS provider,
|
||||||
// coordinates are sent back to the server as pixel coordinates
|
// coordinates are sent back to the server as pixel coordinates
|
||||||
// not the layer's native CRS. So identify on screen coordinates!
|
// not the layer's native CRS. So identify on screen coordinates!
|
||||||
if (
|
if (
|
||||||
(layer->type() == QgsMapLayer::RASTER)
|
(mLayer->type() == QgsMapLayer::RASTER)
|
||||||
&&
|
&&
|
||||||
(dynamic_cast<QgsRasterLayer*>(layer)->providerKey() == "wms")
|
(dynamic_cast<QgsRasterLayer*>(mLayer)->providerKey() == "wms")
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
identifyRasterWmsLayer(dynamic_cast<QgsRasterLayer*>(layer), QgsPoint(e->x(), e->y()) );
|
identifyRasterWmsLayer( QgsPoint(e->x(), e->y()) );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// convert screen coordinates to map coordinates
|
// convert screen coordinates to map coordinates
|
||||||
QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y());
|
QgsPoint idPoint = mCanvas->getCoordinateTransform()->toMapCoordinates(e->x(), e->y());
|
||||||
|
|
||||||
if (layer->type() == QgsMapLayer::VECTOR)
|
if (mLayer->type() == QgsMapLayer::VECTOR)
|
||||||
{
|
{
|
||||||
identifyVectorLayer(dynamic_cast<QgsVectorLayer*>(layer), idPoint);
|
identifyVectorLayer(idPoint);
|
||||||
}
|
}
|
||||||
else if (layer->type() == QgsMapLayer::RASTER)
|
else if (mLayer->type() == QgsMapLayer::RASTER)
|
||||||
{
|
{
|
||||||
identifyRasterLayer(dynamic_cast<QgsRasterLayer*>(layer), idPoint);
|
identifyRasterLayer(idPoint);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -127,8 +128,9 @@ void QgsMapToolIdentify::canvasReleaseEvent(QMouseEvent * e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsMapToolIdentify::identifyRasterLayer(QgsRasterLayer* layer, const QgsPoint& point)
|
void QgsMapToolIdentify::identifyRasterLayer(const QgsPoint& point)
|
||||||
{
|
{
|
||||||
|
QgsRasterLayer *layer = dynamic_cast<QgsRasterLayer*>(mLayer);
|
||||||
if (!layer)
|
if (!layer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -140,7 +142,7 @@ void QgsMapToolIdentify::identifyRasterLayer(QgsRasterLayer* layer, const QgsPoi
|
|||||||
QgsAttributeAction aa;
|
QgsAttributeAction aa;
|
||||||
mResults = new QgsIdentifyResults(aa, mCanvas->window());
|
mResults = new QgsIdentifyResults(aa, mCanvas->window());
|
||||||
mResults->setAttribute(Qt::WA_DeleteOnClose);
|
mResults->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
// Be informed when the dialog box is closed so that we can stop using it.
|
// Be informed when the dialog box is closed so that we can stop using it.
|
||||||
connect(mResults, SIGNAL(accepted()), this, SLOT(resultsDialogGone()));
|
connect(mResults, SIGNAL(accepted()), this, SLOT(resultsDialogGone()));
|
||||||
connect(mResults, SIGNAL(rejected()), this, SLOT(resultsDialogGone()));
|
connect(mResults, SIGNAL(rejected()), this, SLOT(resultsDialogGone()));
|
||||||
mResults->restorePosition();
|
mResults->restorePosition();
|
||||||
@ -166,8 +168,9 @@ void QgsMapToolIdentify::identifyRasterLayer(QgsRasterLayer* layer, const QgsPoi
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void QgsMapToolIdentify::identifyRasterWmsLayer(QgsRasterLayer* layer, const QgsPoint& point)
|
void QgsMapToolIdentify::identifyRasterWmsLayer(const QgsPoint& point)
|
||||||
{
|
{
|
||||||
|
QgsRasterLayer *layer = dynamic_cast<QgsRasterLayer*>(mLayer);
|
||||||
if (!layer)
|
if (!layer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -193,7 +196,7 @@ void QgsMapToolIdentify::identifyRasterWmsLayer(QgsRasterLayer* layer, const Qgs
|
|||||||
|
|
||||||
if(xMinView < xMinLayer)
|
if(xMinView < xMinLayer)
|
||||||
{
|
{
|
||||||
i = (int)(point.x() - (xMinLayer - xMinView) / mupp);
|
i = (int)(point.x() - (xMinLayer - xMinView) / mupp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -214,7 +217,7 @@ void QgsMapToolIdentify::identifyRasterWmsLayer(QgsRasterLayer* layer, const Qgs
|
|||||||
|
|
||||||
if (text.isEmpty())
|
if (text.isEmpty())
|
||||||
{
|
{
|
||||||
showError(layer);
|
showError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,8 +228,9 @@ void QgsMapToolIdentify::identifyRasterWmsLayer(QgsRasterLayer* layer, const Qgs
|
|||||||
viewer->showMessage(); // deletes itself on close
|
viewer->showMessage(); // deletes itself on close
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoint& point)
|
void QgsMapToolIdentify::identifyVectorLayer(const QgsPoint& point)
|
||||||
{
|
{
|
||||||
|
QgsVectorLayer *layer = dynamic_cast<QgsVectorLayer*>(mLayer);
|
||||||
if (!layer)
|
if (!layer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -250,8 +254,7 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
//QgsFeature feat;
|
//QgsFeature feat;
|
||||||
QgsAttributeAction& actions = *layer->actions();
|
QgsAttributeAction& actions = *layer->actions();
|
||||||
QString fieldIndex = layer->displayField();
|
QString fieldIndex = layer->displayField();
|
||||||
QgsVectorDataProvider* dataProvider = layer->getDataProvider();
|
const QgsFieldMap& fields = layer->pendingFields();
|
||||||
const QgsFieldMap& fields = dataProvider->fields();
|
|
||||||
|
|
||||||
// init distance/area calculator
|
// init distance/area calculator
|
||||||
QgsDistanceArea calc;
|
QgsDistanceArea calc;
|
||||||
@ -259,6 +262,22 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
calc.setEllipsoid(ellipsoid);
|
calc.setEllipsoid(ellipsoid);
|
||||||
calc.setSourceSRS(layer->srs().srsid());
|
calc.setSourceSRS(layer->srs().srsid());
|
||||||
|
|
||||||
|
mFeatureList.clear();
|
||||||
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
|
layer->select(layer->pendingAllAttributesList(), r, true);
|
||||||
|
QgsFeature f;
|
||||||
|
while( layer->getNextFeature(f) )
|
||||||
|
mFeatureList << f;
|
||||||
|
|
||||||
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
||||||
|
if( layer->isEditable() && mFeatureList.size()==1 )
|
||||||
|
{
|
||||||
|
editFeature(mFeatureList[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// display features falling within the search radius
|
// display features falling within the search radius
|
||||||
if(!mResults)
|
if(!mResults)
|
||||||
{
|
{
|
||||||
@ -268,6 +287,8 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
connect(mResults, SIGNAL(accepted()), this, SLOT(resultsDialogGone()));
|
connect(mResults, SIGNAL(accepted()), this, SLOT(resultsDialogGone()));
|
||||||
connect(mResults, SIGNAL(rejected()), this, SLOT(resultsDialogGone()));
|
connect(mResults, SIGNAL(rejected()), this, SLOT(resultsDialogGone()));
|
||||||
connect(mResults, SIGNAL(selectedFeatureChanged(int)), this, SLOT(highlightFeature(int)));
|
connect(mResults, SIGNAL(selectedFeatureChanged(int)), this, SLOT(highlightFeature(int)));
|
||||||
|
connect(mResults, SIGNAL(editFeature(int)), this, SLOT(editFeature(int)));
|
||||||
|
|
||||||
// restore the identify window position and show it
|
// restore the identify window position and show it
|
||||||
mResults->restorePosition();
|
mResults->restorePosition();
|
||||||
}
|
}
|
||||||
@ -281,12 +302,9 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||||
|
|
||||||
int lastFeatureId = 0;
|
int lastFeatureId = 0;
|
||||||
|
QgsFeatureList::iterator f_it = mFeatureList.begin();
|
||||||
|
|
||||||
QList<QgsFeature> featureList;
|
for(; f_it != mFeatureList.end(); ++f_it)
|
||||||
layer->featuresInRectangle(r, featureList, true, true);
|
|
||||||
QList<QgsFeature>::iterator f_it = featureList.begin();
|
|
||||||
|
|
||||||
for(; f_it != featureList.end(); ++f_it)
|
|
||||||
{
|
{
|
||||||
featureCount++;
|
featureCount++;
|
||||||
|
|
||||||
@ -294,6 +312,10 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
featureNode->setData(0, Qt::UserRole, QVariant(f_it->featureId())); // save feature id
|
featureNode->setData(0, Qt::UserRole, QVariant(f_it->featureId())); // save feature id
|
||||||
lastFeatureId = f_it->featureId();
|
lastFeatureId = f_it->featureId();
|
||||||
featureNode->setText(0, fieldIndex);
|
featureNode->setText(0, fieldIndex);
|
||||||
|
|
||||||
|
if( layer->isEditable() )
|
||||||
|
mResults->addEdit( featureNode, f_it->featureId() );
|
||||||
|
|
||||||
const QgsAttributeMap& attr = f_it->attributeMap();
|
const QgsAttributeMap& attr = f_it->attributeMap();
|
||||||
|
|
||||||
for (QgsAttributeMap::const_iterator it = attr.begin(); it != attr.end(); ++it)
|
for (QgsAttributeMap::const_iterator it = attr.begin(); it != attr.end(); ++it)
|
||||||
@ -340,13 +362,12 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
mResults->addDerivedAttribute(featureNode, "Y", str);
|
mResults->addDerivedAttribute(featureNode, "Y", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add actions
|
// Add actions
|
||||||
QgsAttributeAction::aIter iter = actions.begin();
|
QgsAttributeAction::aIter iter = actions.begin();
|
||||||
for (register int i = 0; iter != actions.end(); ++iter, ++i)
|
for (register int i = 0; iter != actions.end(); ++iter, ++i)
|
||||||
{
|
{
|
||||||
mResults->addAction( featureNode, i, QObject::tr("action"), iter->name() );
|
mResults->addAction( featureNode, i, QObject::tr("action"), iter->name() );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsDebugMsg("Feature count on identify: " + QString::number(featureCount));
|
QgsDebugMsg("Feature count on identify: " + QString::number(featureCount));
|
||||||
@ -354,7 +375,7 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
//also test the not commited features //todo: eliminate copy past code
|
//also test the not commited features //todo: eliminate copy past code
|
||||||
|
|
||||||
mResults->setTitle(layer->name() + " - " + QString::number(featureCount) + QObject::tr(" features found"));
|
mResults->setTitle(layer->name() + " - " + QString::number(featureCount) + QObject::tr(" features found"));
|
||||||
if (featureCount == 1)
|
if (featureCount == 1)
|
||||||
{
|
{
|
||||||
mResults->showAllAttributes();
|
mResults->showAllAttributes();
|
||||||
mResults->setTitle(layer->name() + " - " + QObject::tr(" 1 feature found") );
|
mResults->setTitle(layer->name() + " - " + QObject::tr(" 1 feature found") );
|
||||||
@ -369,228 +390,14 @@ void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoi
|
|||||||
{
|
{
|
||||||
QString title = layer->name();
|
QString title = layer->name();
|
||||||
title += QString( tr("- %1 features found","Identify results window title",featureCount) ).arg(featureCount);
|
title += QString( tr("- %1 features found","Identify results window title",featureCount) ).arg(featureCount);
|
||||||
mResults->setTitle(title);
|
mResults->setTitle(title);
|
||||||
}
|
}
|
||||||
QApplication::restoreOverrideCursor();
|
QApplication::restoreOverrideCursor();
|
||||||
|
|
||||||
mResults->show();
|
mResults->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 //MH: old state of the function
|
void QgsMapToolIdentify::showError()
|
||||||
void QgsMapToolIdentify::identifyVectorLayer(QgsVectorLayer* layer, const QgsPoint& point)
|
|
||||||
{
|
|
||||||
if (!layer)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// load identify radius from settings
|
|
||||||
QSettings settings;
|
|
||||||
double identifyValue = settings.value("/Map/identifyRadius", QGis::DEFAULT_IDENTIFY_RADIUS).toDouble();
|
|
||||||
QString ellipsoid = settings.readEntry("/qgis/measure/ellipsoid", "WGS84");
|
|
||||||
|
|
||||||
// create the search rectangle
|
|
||||||
double searchRadius = mCanvas->extent().width() * (identifyValue/100.0);
|
|
||||||
|
|
||||||
QgsRect r;
|
|
||||||
r.setXmin(point.x() - searchRadius);
|
|
||||||
r.setXmax(point.x() + searchRadius);
|
|
||||||
r.setYmin(point.y() - searchRadius);
|
|
||||||
r.setYmax(point.y() + searchRadius);
|
|
||||||
|
|
||||||
r = toLayerCoords(layer, r);
|
|
||||||
|
|
||||||
int featureCount = 0;
|
|
||||||
QgsFeature feat;
|
|
||||||
QgsAttributeAction& actions = *layer->actions();
|
|
||||||
QString fieldIndex = layer->displayField();
|
|
||||||
QgsVectorDataProvider* dataProvider = layer->getDataProvider();
|
|
||||||
QgsAttributeList allAttributes = dataProvider->allAttributesList();
|
|
||||||
const QgsFieldMap& fields = dataProvider->fields();
|
|
||||||
|
|
||||||
dataProvider->select(allAttributes, r, true, true);
|
|
||||||
|
|
||||||
// init distance/area calculator
|
|
||||||
QgsDistanceArea calc;
|
|
||||||
calc.setProjectionsEnabled(mCanvas->projectionsEnabled()); // project?
|
|
||||||
calc.setEllipsoid(ellipsoid);
|
|
||||||
calc.setSourceSRS(layer->srs().srsid());
|
|
||||||
|
|
||||||
if ( !layer->isEditable() )
|
|
||||||
{
|
|
||||||
// display features falling within the search radius
|
|
||||||
if(!mResults)
|
|
||||||
{
|
|
||||||
mResults = new QgsIdentifyResults(actions, mCanvas->window());
|
|
||||||
mResults->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
// Be informed when the dialog box is closed so that we can stop using it.
|
|
||||||
connect(mResults, SIGNAL(accepted()), this, SLOT(resultsDialogGone()));
|
|
||||||
connect(mResults, SIGNAL(rejected()), this, SLOT(resultsDialogGone()));
|
|
||||||
connect(mResults, SIGNAL(selectedFeatureChanged(int)), this, SLOT(highlightFeature(int)));
|
|
||||||
// restore the identify window position and show it
|
|
||||||
mResults->restorePosition();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mResults->raise();
|
|
||||||
mResults->clear();
|
|
||||||
mResults->setActions(actions);
|
|
||||||
}
|
|
||||||
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
|
|
||||||
int lastFeatureId = 0;
|
|
||||||
|
|
||||||
QTreeWidgetItem *click = mResults->addNode(tr("(clicked coordinate)"));
|
|
||||||
click->setText(1, point.stringRep());
|
|
||||||
|
|
||||||
while (dataProvider->getNextFeature(feat))
|
|
||||||
{
|
|
||||||
featureCount++;
|
|
||||||
|
|
||||||
QTreeWidgetItem* featureNode = mResults->addNode("foo");
|
|
||||||
featureNode->setData(0, Qt::UserRole, QVariant(feat.featureId())); // save feature id
|
|
||||||
lastFeatureId = feat.featureId();
|
|
||||||
featureNode->setText(0, fieldIndex);
|
|
||||||
const QgsAttributeMap& attr = feat.attributeMap();
|
|
||||||
|
|
||||||
for (QgsAttributeMap::const_iterator it = attr.begin(); it != attr.end(); ++it)
|
|
||||||
{
|
|
||||||
//QgsDebugMsg(it->fieldName() + " == " + fieldIndex);
|
|
||||||
|
|
||||||
if (fields[it.key()].name() == fieldIndex)
|
|
||||||
{
|
|
||||||
featureNode->setText(1, it->toString());
|
|
||||||
}
|
|
||||||
mResults->addAttribute(featureNode, fields[it.key()].name(), it->toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate derived attributes and insert:
|
|
||||||
// measure distance or area depending on geometry type
|
|
||||||
if (layer->vectorType() == QGis::Line)
|
|
||||||
{
|
|
||||||
double dist = calc.measure(feat.geometry());
|
|
||||||
QString str = calc.textUnit(dist, 3, mCanvas->mapUnits(), false);
|
|
||||||
mResults->addDerivedAttribute(featureNode, QObject::tr("Length"), str);
|
|
||||||
}
|
|
||||||
else if (layer->vectorType() == QGis::Polygon)
|
|
||||||
{
|
|
||||||
double area = calc.measure(feat.geometry());
|
|
||||||
QString str = calc.textUnit(area, 3, mCanvas->mapUnits(), true);
|
|
||||||
mResults->addDerivedAttribute(featureNode, QObject::tr("Area"), str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add actions
|
|
||||||
QgsAttributeAction::aIter iter = actions.begin();
|
|
||||||
for (register int i = 0; iter != actions.end(); ++iter, ++i)
|
|
||||||
{
|
|
||||||
mResults->addAction( featureNode, i, QObject::tr("action"), iter->name() );
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QgsDebugMsg("Feature count on identify: " + QString::number(featureCount));
|
|
||||||
|
|
||||||
//also test the not commited features //todo: eliminate copy past code
|
|
||||||
|
|
||||||
mResults->setTitle(layer->name() + " - " + QString::number(featureCount) + QObject::tr(" features found"));
|
|
||||||
if (featureCount == 1)
|
|
||||||
{
|
|
||||||
mResults->showAllAttributes();
|
|
||||||
mResults->setTitle(layer->name() + " - " + QObject::tr(" 1 feature found") );
|
|
||||||
highlightFeature(lastFeatureId);
|
|
||||||
}
|
|
||||||
else if (featureCount == 0)
|
|
||||||
{
|
|
||||||
mResults->setTitle(layer->name() + " - " + QObject::tr("No features found") );
|
|
||||||
mResults->setMessage ( QObject::tr("No features found"), QObject::tr("No features were found in the active layer at the point you clicked") );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QString title = layer->name();
|
|
||||||
title += QString( tr("- %1 features found","Identify results window title",featureCount) ).arg(featureCount);
|
|
||||||
mResults->setTitle(title);
|
|
||||||
}
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
|
|
||||||
mResults->show();
|
|
||||||
}
|
|
||||||
else // ( layer->isEditable() )
|
|
||||||
{
|
|
||||||
// Edit attributes
|
|
||||||
// TODO: what to do if more features were selected? - nearest?
|
|
||||||
QgsChangedAttributesMap& changedAttributes = layer->changedAttributes();
|
|
||||||
|
|
||||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
|
||||||
|
|
||||||
if (dataProvider->getNextFeature(feat))
|
|
||||||
{
|
|
||||||
// these are the values to populate the dialog with
|
|
||||||
// start off with list of committed attribute values
|
|
||||||
QgsAttributeMap old = feat.attributeMap();
|
|
||||||
|
|
||||||
// Test if this feature already changed since the last commit
|
|
||||||
|
|
||||||
QgsChangedAttributesMap::iterator it = changedAttributes.find(feat.featureId());
|
|
||||||
if ( it != changedAttributes.end() )
|
|
||||||
{
|
|
||||||
// Yes, this feature already has in-memory attribute changes
|
|
||||||
|
|
||||||
// go through and apply the modified-but-not-committed values
|
|
||||||
QgsAttributeMap oldattr = *it;
|
|
||||||
int index=0;
|
|
||||||
for (QgsAttributeMap::const_iterator oldit = old.begin(); oldit != old.end(); ++oldit)
|
|
||||||
{
|
|
||||||
QgsAttributeMap::iterator ait = oldattr.find( oldit.key() );
|
|
||||||
if ( ait != oldattr.end() )
|
|
||||||
{
|
|
||||||
// replace the committed value with the
|
|
||||||
// modified-but-not-committed value
|
|
||||||
old[index] = *ait;
|
|
||||||
}
|
|
||||||
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
|
|
||||||
// Show the attribute value editing dialog
|
|
||||||
QgsAttributeDialog ad( dataProvider->fields(), old );
|
|
||||||
|
|
||||||
if (ad.exec() == QDialog::Accepted)
|
|
||||||
{
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (QgsAttributeMap::const_iterator oldit = old.begin(); oldit != old.end(); ++oldit, ++i)
|
|
||||||
{
|
|
||||||
// only apply changed values if they were edited by the user
|
|
||||||
if (ad.isDirty(i))
|
|
||||||
{
|
|
||||||
QgsDebugMsg("found a changed attribute: " + QString::number(i) + " = " + ad.value(i));
|
|
||||||
|
|
||||||
QgsAttributeMap& chattr = changedAttributes[ feat.featureId() ];
|
|
||||||
chattr[i] = ad.value(i);
|
|
||||||
|
|
||||||
// propagate "dirtyness" to the layer
|
|
||||||
layer->setModified();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QApplication::restoreOverrideCursor();
|
|
||||||
QMessageBox::information(0, tr("No features found"),
|
|
||||||
tr("<p>No features were found within the search radius. "
|
|
||||||
"Note that it is currently not possible to use the "
|
|
||||||
"identify tool on unsaved features.</p>"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void QgsMapToolIdentify::showError(QgsMapLayer * mapLayer)
|
|
||||||
{
|
{
|
||||||
// QMessageBox::warning(
|
// QMessageBox::warning(
|
||||||
// this,
|
// this,
|
||||||
@ -600,10 +407,10 @@ void QgsMapToolIdentify::showError(QgsMapLayer * mapLayer)
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
QgsMessageViewer * mv = new QgsMessageViewer();
|
QgsMessageViewer * mv = new QgsMessageViewer();
|
||||||
mv->setWindowTitle( mapLayer->errorCaptionString() );
|
mv->setWindowTitle( mLayer->errorCaptionString() );
|
||||||
mv->setMessageAsPlainText(
|
mv->setMessageAsPlainText(
|
||||||
QObject::tr("Could not identify objects on") + " " + mapLayer->name() + " " + QObject::tr("because") + ":\n" +
|
QObject::tr("Could not identify objects on") + " " + mLayer->name() + " " + QObject::tr("because") + ":\n" +
|
||||||
mapLayer->errorString()
|
mLayer->errorString()
|
||||||
);
|
);
|
||||||
mv->exec(); // deletes itself on close
|
mv->exec(); // deletes itself on close
|
||||||
}
|
}
|
||||||
@ -625,7 +432,7 @@ void QgsMapToolIdentify::deactivate()
|
|||||||
|
|
||||||
void QgsMapToolIdentify::highlightFeature(int featureId)
|
void QgsMapToolIdentify::highlightFeature(int featureId)
|
||||||
{
|
{
|
||||||
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>(mCanvas->currentLayer());
|
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>(mLayer);
|
||||||
if (!layer)
|
if (!layer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -653,3 +460,41 @@ void QgsMapToolIdentify::highlightFeature(int featureId)
|
|||||||
mRubberBand->show();
|
mRubberBand->show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsMapToolIdentify::editFeature(int featureId)
|
||||||
|
{
|
||||||
|
for(QgsFeatureList::iterator it=mFeatureList.begin(); it!=mFeatureList.end(); it++)
|
||||||
|
{
|
||||||
|
if( it->featureId() == featureId )
|
||||||
|
{
|
||||||
|
editFeature( *it );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsMapToolIdentify::editFeature(QgsFeature &f)
|
||||||
|
{
|
||||||
|
QgsVectorLayer* layer = dynamic_cast<QgsVectorLayer*>(mLayer);
|
||||||
|
if (!layer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!layer->isEditable() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QgsAttributeMap src = f.attributeMap();
|
||||||
|
|
||||||
|
QgsAttributeDialog *ad = new QgsAttributeDialog(layer, &f);
|
||||||
|
if (ad->exec())
|
||||||
|
{
|
||||||
|
const QgsAttributeMap &dst = f.attributeMap();
|
||||||
|
|
||||||
|
for(QgsAttributeMap::const_iterator it=dst.begin(); it!=dst.end(); it++)
|
||||||
|
{
|
||||||
|
if( !src.contains( it.key() ) || it.value()!=src[it.key()] )
|
||||||
|
layer->changeAttributeValue( f.featureId(), it.key(), it.value().toString() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete ad;
|
||||||
|
mCanvas->refresh();
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include "qgsmaptool.h"
|
#include "qgsmaptool.h"
|
||||||
#include "qgspoint.h"
|
#include "qgspoint.h"
|
||||||
|
#include "qgsfeature.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
@ -60,6 +61,9 @@ class QgsMapToolIdentify : public QgsMapTool
|
|||||||
public slots:
|
public slots:
|
||||||
//! creates rubberband on top of the feature to highlight it
|
//! creates rubberband on top of the feature to highlight it
|
||||||
void highlightFeature(int featureId);
|
void highlightFeature(int featureId);
|
||||||
|
|
||||||
|
//! edit a feature
|
||||||
|
void editFeature(int featureId);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -68,7 +72,7 @@ class QgsMapToolIdentify : public QgsMapTool
|
|||||||
*
|
*
|
||||||
* \param point[in] The coordinate (as the CRS of the raster layer)
|
* \param point[in] The coordinate (as the CRS of the raster layer)
|
||||||
*/
|
*/
|
||||||
void identifyRasterLayer(QgsRasterLayer* layer, const QgsPoint& point);
|
void identifyRasterLayer(const QgsPoint& point);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief function for identifying a pixel in a OGC WMS raster layer
|
* \brief function for identifying a pixel in a OGC WMS raster layer
|
||||||
@ -78,18 +82,20 @@ class QgsMapToolIdentify : public QgsMapTool
|
|||||||
* \note WMS Servers prefer to receive coordinates in image space not CRS space, therefore
|
* \note WMS Servers prefer to receive coordinates in image space not CRS space, therefore
|
||||||
* this special variant of identifyRasterLayer.
|
* this special variant of identifyRasterLayer.
|
||||||
*/
|
*/
|
||||||
void identifyRasterWmsLayer(QgsRasterLayer* layer, const QgsPoint& point);
|
void identifyRasterWmsLayer(const QgsPoint& point);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief function for identifying features at a coordinate in a vector layer
|
* \brief function for identifying features at a coordinate in a vector layer
|
||||||
*
|
*
|
||||||
* \param point[in] The coordinate (as the CRS of the vector layer)
|
* \param point[in] The coordinate (as the CRS of the vector layer)
|
||||||
*/
|
*/
|
||||||
void identifyVectorLayer(QgsVectorLayer* layer, const QgsPoint& point);
|
void identifyVectorLayer(const QgsPoint& point);
|
||||||
|
|
||||||
//! show whatever error is exposed by the QgsMapLayer.
|
//! show whatever error is exposed by the QgsMapLayer.
|
||||||
void showError(QgsMapLayer * mapLayer);
|
void showError();
|
||||||
|
|
||||||
|
//! edit a feature
|
||||||
|
void editFeature(QgsFeature &f);
|
||||||
|
|
||||||
//! Pointer to the identify results dialog for name/value pairs
|
//! Pointer to the identify results dialog for name/value pairs
|
||||||
QgsIdentifyResults *mResults;
|
QgsIdentifyResults *mResults;
|
||||||
@ -97,6 +103,11 @@ class QgsMapToolIdentify : public QgsMapTool
|
|||||||
//! Rubber band for highlighting identified feature
|
//! Rubber band for highlighting identified feature
|
||||||
QgsRubberBand* mRubberBand;
|
QgsRubberBand* mRubberBand;
|
||||||
|
|
||||||
|
QgsMapLayer *mLayer;
|
||||||
|
|
||||||
|
//! list of identified features
|
||||||
|
QgsFeatureList mFeatureList;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
// Let us know when the QgsIdentifyResults dialog box has been closed
|
// Let us know when the QgsIdentifyResults dialog box has been closed
|
||||||
void resultsDialogGone();
|
void resultsDialogGone();
|
||||||
|
@ -56,65 +56,65 @@ void QgsMapToolMoveFeature::canvasPressEvent(QMouseEvent * e)
|
|||||||
|
|
||||||
QgsVectorLayer* vlayer = currentVectorLayer();
|
QgsVectorLayer* vlayer = currentVectorLayer();
|
||||||
if(!vlayer)
|
if(!vlayer)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!vlayer->isEditable())
|
if(!vlayer->isEditable())
|
||||||
{
|
{
|
||||||
QMessageBox::information(0, QObject::tr("Layer not editable"), \
|
QMessageBox::information(0, QObject::tr("Layer not editable"),
|
||||||
QObject::tr("Cannot edit the vector layer. To make it editable, go to the file item " \
|
QObject::tr("Cannot edit the vector layer. To make it editable, go to the file item "
|
||||||
"of the layer, right click and check 'Allow Editing'."));
|
"of the layer, right click and check 'Allow Editing'."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//find first geometry under mouse cursor and store iterator to it
|
//find first geometry under mouse cursor and store iterator to it
|
||||||
QgsPoint layerCoords = toLayerCoords((QgsMapLayer*)vlayer, e->pos());
|
QgsPoint layerCoords = toLayerCoords((QgsMapLayer*)vlayer, e->pos());
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
double searchRadius = settings.value("/qgis/digitizing/search_radius_vertex_edit", 10).toDouble();
|
double searchRadius = settings.value("/qgis/digitizing/search_radius_vertex_edit", 10).toDouble();
|
||||||
QgsRect selectRect(layerCoords.x()-searchRadius, layerCoords.y()-searchRadius, \
|
QgsRect selectRect(layerCoords.x()-searchRadius, layerCoords.y()-searchRadius,
|
||||||
layerCoords.x()+searchRadius, layerCoords.y()+searchRadius);
|
layerCoords.x()+searchRadius, layerCoords.y()+searchRadius);
|
||||||
|
|
||||||
QList<QgsFeature> featureList;
|
vlayer->select(QgsAttributeList(), selectRect, true);
|
||||||
vlayer->featuresInRectangle(selectRect, featureList, true, false);
|
|
||||||
|
//find the closest feature
|
||||||
if(featureList.size() > 0)
|
QgsGeometry* pointGeometry = QgsGeometry::fromPoint(layerCoords);
|
||||||
|
if(!pointGeometry)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double minDistance = std::numeric_limits<double>::max();
|
||||||
|
|
||||||
|
QgsFeature cf;
|
||||||
|
QgsFeature f;
|
||||||
|
while( vlayer->getNextFeature(f) )
|
||||||
|
{
|
||||||
|
if(f.geometry())
|
||||||
{
|
{
|
||||||
//find the closest feature
|
double currentDistance = pointGeometry->distance(*f.geometry());
|
||||||
QgsGeometry* pointGeometry = QgsGeometry::fromPoint(layerCoords);
|
if(currentDistance < minDistance)
|
||||||
if(!pointGeometry)
|
{
|
||||||
{
|
minDistance = currentDistance;
|
||||||
return;
|
cf = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QgsFeature>::iterator closestFeatureIt;
|
|
||||||
double minDistance = std::numeric_limits<double>::max();
|
|
||||||
double currentDistance;
|
|
||||||
|
|
||||||
QList<QgsFeature>::iterator it = featureList.begin();
|
|
||||||
for(; it != featureList.end(); ++it)
|
|
||||||
{
|
|
||||||
if(it->geometry())
|
|
||||||
{
|
|
||||||
currentDistance = pointGeometry->distance(*(it->geometry()));
|
|
||||||
if(currentDistance < minDistance)
|
|
||||||
{
|
|
||||||
minDistance = currentDistance;
|
|
||||||
closestFeatureIt = it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mStartPointMapCoords = toMapCoords(e->pos());
|
|
||||||
mMovedFeature = closestFeatureIt->featureId(); //todo: take the closest feature, not the first one...
|
|
||||||
mRubberBand = createRubberBand();
|
|
||||||
mRubberBand->setToGeometry(closestFeatureIt->geometry(), *vlayer);
|
|
||||||
mRubberBand->setColor(Qt::red);
|
|
||||||
mRubberBand->setWidth(2);
|
|
||||||
mRubberBand->show();
|
|
||||||
|
|
||||||
delete pointGeometry;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( minDistance==std::numeric_limits<double>::max() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mStartPointMapCoords = toMapCoords(e->pos());
|
||||||
|
mMovedFeature = cf.featureId(); //todo: take the closest feature, not the first one...
|
||||||
|
mRubberBand = createRubberBand();
|
||||||
|
mRubberBand->setToGeometry( cf.geometry(), *vlayer);
|
||||||
|
mRubberBand->setColor(Qt::red);
|
||||||
|
mRubberBand->setWidth(2);
|
||||||
|
mRubberBand->show();
|
||||||
|
|
||||||
|
delete pointGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsMapToolMoveFeature::canvasReleaseEvent(QMouseEvent * e)
|
void QgsMapToolMoveFeature::canvasReleaseEvent(QMouseEvent * e)
|
||||||
|
@ -49,7 +49,6 @@ QgsOptions::QgsOptions(QWidget *parent, Qt::WFlags fl) :
|
|||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
connect(this, SIGNAL(accepted()), this, SLOT(saveOptions()));
|
connect(this, SIGNAL(accepted()), this, SLOT(saveOptions()));
|
||||||
|
|
||||||
qparent = parent;
|
|
||||||
// read the current browser and set it
|
// read the current browser and set it
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
#ifdef QGISDEBUG
|
#ifdef QGISDEBUG
|
||||||
@ -116,6 +115,7 @@ QgsOptions::QgsOptions(QWidget *parent, Qt::WFlags fl) :
|
|||||||
chkAddedVisibility->setChecked(settings.value("/qgis/new_layers_visible",true).toBool());
|
chkAddedVisibility->setChecked(settings.value("/qgis/new_layers_visible",true).toBool());
|
||||||
cbxLegendClassifiers->setChecked(settings.value("/qgis/showLegendClassifiers",false).toBool());
|
cbxLegendClassifiers->setChecked(settings.value("/qgis/showLegendClassifiers",false).toBool());
|
||||||
cbxHideSplash->setChecked(settings.value("/qgis/hideSplash",false).toBool());
|
cbxHideSplash->setChecked(settings.value("/qgis/hideSplash",false).toBool());
|
||||||
|
cbxAttributeTableDocked->setChecked(settings.value("/qgis/dockAttributeTable",false).toBool());
|
||||||
|
|
||||||
//set the colour for selections
|
//set the colour for selections
|
||||||
int myRed = settings.value("/qgis/default_selection_color_red",255).toInt();
|
int myRed = settings.value("/qgis/default_selection_color_red",255).toInt();
|
||||||
@ -239,7 +239,7 @@ void QgsOptions::themeChanged(const QString &newThemeName)
|
|||||||
{
|
{
|
||||||
// Slot to change the theme as user scrolls through the choices
|
// Slot to change the theme as user scrolls through the choices
|
||||||
QString newt = newThemeName;
|
QString newt = newThemeName;
|
||||||
((QgisApp*)qparent)->setTheme(newt);
|
QgisApp::instance()->setTheme(newt);
|
||||||
}
|
}
|
||||||
QString QgsOptions::theme()
|
QString QgsOptions::theme()
|
||||||
{
|
{
|
||||||
@ -260,6 +260,7 @@ void QgsOptions::saveOptions()
|
|||||||
settings.setValue("/Map/identifyRadius", spinBoxIdentifyValue->value());
|
settings.setValue("/Map/identifyRadius", spinBoxIdentifyValue->value());
|
||||||
settings.setValue("/qgis/showLegendClassifiers",cbxLegendClassifiers->isChecked());
|
settings.setValue("/qgis/showLegendClassifiers",cbxLegendClassifiers->isChecked());
|
||||||
settings.setValue("/qgis/hideSplash",cbxHideSplash->isChecked());
|
settings.setValue("/qgis/hideSplash",cbxHideSplash->isChecked());
|
||||||
|
settings.setValue("/qgis/dockAttributeTable",cbxAttributeTableDocked->isChecked());
|
||||||
settings.setValue("/qgis/new_layers_visible",chkAddedVisibility->isChecked());
|
settings.setValue("/qgis/new_layers_visible",chkAddedVisibility->isChecked());
|
||||||
settings.setValue("/qgis/enable_anti_aliasing",chkAntiAliasing->isChecked());
|
settings.setValue("/qgis/enable_anti_aliasing",chkAntiAliasing->isChecked());
|
||||||
settings.setValue("/qgis/use_qimage_to_render", !(chkUseQPixmap->isChecked()));
|
settings.setValue("/qgis/use_qimage_to_render", !(chkUseQPixmap->isChecked()));
|
||||||
|
@ -93,9 +93,6 @@ class QgsOptions :public QDialog, private Ui::QgsOptionsBase
|
|||||||
//
|
//
|
||||||
QStringList i18nList();
|
QStringList i18nList();
|
||||||
|
|
||||||
//! Pointer to our parent
|
|
||||||
QWidget *qparent;
|
|
||||||
|
|
||||||
//!Global default projection used for new layers added that have no projection
|
//!Global default projection used for new layers added that have no projection
|
||||||
long mGlobalSRSID;
|
long mGlobalSRSID;
|
||||||
|
|
||||||
|
@ -43,10 +43,9 @@
|
|||||||
static long DEFAULT_WMS_EPSG = 4326; // WGS 84
|
static long DEFAULT_WMS_EPSG = 4326; // WGS 84
|
||||||
|
|
||||||
|
|
||||||
QgsServerSourceSelect::QgsServerSourceSelect(QgisApp * app, QWidget * parent, Qt::WFlags fl)
|
QgsServerSourceSelect::QgsServerSourceSelect(QWidget * parent, Qt::WFlags fl)
|
||||||
: QDialog(parent, fl),
|
: QDialog(parent, fl),
|
||||||
m_Epsg(DEFAULT_WMS_EPSG),
|
m_Epsg(DEFAULT_WMS_EPSG),
|
||||||
qgisApp(app),
|
|
||||||
mWmsProvider(0)
|
mWmsProvider(0)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
@ -44,7 +44,7 @@ class QgsServerSourceSelect : public QDialog, private Ui::QgsServerSourceSelectB
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
QgsServerSourceSelect(QgisApp *app, QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags);
|
QgsServerSourceSelect(QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags);
|
||||||
//! Destructor
|
//! Destructor
|
||||||
~QgsServerSourceSelect();
|
~QgsServerSourceSelect();
|
||||||
//! Populate the connection list combo box
|
//! Populate the connection list combo box
|
||||||
@ -173,9 +173,6 @@ private:
|
|||||||
//! The mime type, the text to use in the button and a unique number
|
//! The mime type, the text to use in the button and a unique number
|
||||||
QMap<QString, QPair<QString, int> > m_PotentialFormats;
|
QMap<QString, QPair<QString, int> > m_PotentialFormats;
|
||||||
|
|
||||||
//! Pointer to the qgis application mainwindow
|
|
||||||
QgisApp *qgisApp;
|
|
||||||
|
|
||||||
//! The widget that controls the image format radio buttons
|
//! The widget that controls the image format radio buttons
|
||||||
QButtonGroup* m_imageFormatGroup;
|
QButtonGroup* m_imageFormatGroup;
|
||||||
QHBoxLayout* m_imageFormatLayout;
|
QHBoxLayout* m_imageFormatLayout;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "qgisapp.h"
|
||||||
#include "qgsapplication.h"
|
#include "qgsapplication.h"
|
||||||
#include "qgsattributeactiondialog.h"
|
#include "qgsattributeactiondialog.h"
|
||||||
#include "qgscontexthelp.h"
|
#include "qgscontexthelp.h"
|
||||||
@ -32,7 +33,6 @@
|
|||||||
#include "qgsproject.h"
|
#include "qgsproject.h"
|
||||||
#include "qgssinglesymboldialog.h"
|
#include "qgssinglesymboldialog.h"
|
||||||
#include "qgsuniquevaluedialog.h"
|
#include "qgsuniquevaluedialog.h"
|
||||||
#include "qgsvectordataprovider.h"
|
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
#include "qgsvectorlayerproperties.h"
|
#include "qgsvectorlayerproperties.h"
|
||||||
#include "qgsconfig.h"
|
#include "qgsconfig.h"
|
||||||
@ -48,15 +48,18 @@
|
|||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
#if QT_VERSION < 0x040300
|
#if QT_VERSION < 0x040300
|
||||||
#define toPlainText() text()
|
#define toPlainText() text()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
QgsVectorLayerProperties::QgsVectorLayerProperties(QgsVectorLayer * lyr,
|
QgsVectorLayerProperties::QgsVectorLayerProperties(
|
||||||
QWidget * parent,
|
QgsVectorLayer *lyr,
|
||||||
Qt::WFlags fl)
|
QWidget * parent,
|
||||||
|
Qt::WFlags fl)
|
||||||
: QDialog(parent, fl),
|
: QDialog(parent, fl),
|
||||||
layer(lyr),
|
layer(lyr),
|
||||||
mRendererDialog(0)
|
mRendererDialog(0)
|
||||||
@ -66,6 +69,21 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(QgsVectorLayer * lyr,
|
|||||||
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||||
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
|
connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(apply()));
|
||||||
connect(this, SIGNAL(accepted()), this, SLOT(apply()));
|
connect(this, SIGNAL(accepted()), this, SLOT(apply()));
|
||||||
|
connect(mAddAttributeButton, SIGNAL(clicked()), this, SLOT(addAttribute()));
|
||||||
|
connect(mDeleteAttributeButton, SIGNAL(clicked()), this, SLOT(deleteAttribute()));
|
||||||
|
|
||||||
|
connect(mToggleEditingButton, SIGNAL(clicked()), this, SLOT(toggleEditing()));
|
||||||
|
connect(this, SIGNAL(toggleEditing(QgsMapLayer*)),
|
||||||
|
QgisApp::instance(), SLOT(toggleEditing(QgsMapLayer*)));
|
||||||
|
|
||||||
|
connect(layer, SIGNAL(editingStarted()), this, SLOT(editingToggled()));
|
||||||
|
connect(layer, SIGNAL(editingStopped()), this, SLOT(editingToggled()));
|
||||||
|
connect(layer, SIGNAL(attributeAdded(int)), this, SLOT(attributeAdded(int)));
|
||||||
|
connect(layer, SIGNAL(attributeDeleted(int)), this, SLOT(attributeDeleted(int)));
|
||||||
|
|
||||||
|
mAddAttributeButton->setIcon(QgisApp::getThemeIcon("/mActionNewAttribute.png"));
|
||||||
|
mDeleteAttributeButton->setIcon(QgisApp::getThemeIcon("/mActionDeleteAttribute.png"));
|
||||||
|
mToggleEditingButton->setIcon(QgisApp::getThemeIcon("/mActionToggleEditing.png"));
|
||||||
|
|
||||||
// Create the Label dialog tab
|
// Create the Label dialog tab
|
||||||
QVBoxLayout *layout = new QVBoxLayout( labelOptionsFrame );
|
QVBoxLayout *layout = new QVBoxLayout( labelOptionsFrame );
|
||||||
@ -73,18 +91,31 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(QgsVectorLayer * lyr,
|
|||||||
labelDialog = new QgsLabelDialog ( layer->label(), labelOptionsFrame);
|
labelDialog = new QgsLabelDialog ( layer->label(), labelOptionsFrame);
|
||||||
layout->addWidget( labelDialog );
|
layout->addWidget( labelDialog );
|
||||||
labelOptionsFrame->setLayout(layout);
|
labelOptionsFrame->setLayout(layout);
|
||||||
connect(labelDialog, SIGNAL(labelSourceSet()),
|
connect(labelDialog, SIGNAL(labelSourceSet()), this, SLOT(setLabelCheckBox()));
|
||||||
this, SLOT(setLabelCheckBox()));
|
|
||||||
|
|
||||||
// Create the Actions dialog tab
|
// Create the Actions dialog tab
|
||||||
QgsVectorDataProvider *dp = dynamic_cast<QgsVectorDataProvider *>(layer->getDataProvider());
|
|
||||||
QVBoxLayout *actionLayout = new QVBoxLayout( actionOptionsFrame );
|
QVBoxLayout *actionLayout = new QVBoxLayout( actionOptionsFrame );
|
||||||
actionLayout->setMargin(0);
|
actionLayout->setMargin(0);
|
||||||
QgsFieldMap fields = dp->fields();
|
const QgsFieldMap &fields = layer->pendingFields();
|
||||||
actionDialog = new QgsAttributeActionDialog ( layer->actions(), fields,
|
actionDialog = new QgsAttributeActionDialog ( layer->actions(), fields, actionOptionsFrame );
|
||||||
actionOptionsFrame );
|
|
||||||
actionLayout->addWidget( actionDialog );
|
actionLayout->addWidget( actionDialog );
|
||||||
|
|
||||||
|
tblAttributes->setColumnCount(8);
|
||||||
|
tblAttributes->setRowCount( fields.size() );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 0, new QTableWidgetItem( tr("id") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 1, new QTableWidgetItem( tr("name") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 2, new QTableWidgetItem( tr("type") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 3, new QTableWidgetItem( tr("length") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 4, new QTableWidgetItem( tr("precision") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 5, new QTableWidgetItem( tr("comment") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 6, new QTableWidgetItem( tr("edit widget") ) );
|
||||||
|
tblAttributes->setHorizontalHeaderItem( 7, new QTableWidgetItem( tr("values") ) );
|
||||||
|
|
||||||
|
tblAttributes->setSelectionBehavior( QAbstractItemView::SelectRows );
|
||||||
|
tblAttributes->setSelectionMode( QAbstractItemView::MultiSelection );
|
||||||
|
|
||||||
|
loadRows();
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
if(layer->getDataProvider())//enable spatial index button group if supported by provider
|
if(layer->getDataProvider())//enable spatial index button group if supported by provider
|
||||||
{
|
{
|
||||||
@ -95,18 +126,169 @@ QgsVectorLayerProperties::QgsVectorLayerProperties(QgsVectorLayer * lyr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateButtons();
|
||||||
|
|
||||||
leSpatialRefSys->setText(layer->srs().proj4String());
|
leSpatialRefSys->setText(layer->srs().proj4String());
|
||||||
leSpatialRefSys->setCursorPosition(0);
|
leSpatialRefSys->setCursorPosition(0);
|
||||||
|
|
||||||
connect(sliderTransparency, SIGNAL(valueChanged(int)), this, SLOT(sliderTransparency_valueChanged(int)));
|
connect(sliderTransparency, SIGNAL(valueChanged(int)), this, SLOT(sliderTransparency_valueChanged(int)));
|
||||||
|
|
||||||
|
tabWidget->setCurrentIndex(0);
|
||||||
} // QgsVectorLayerProperties ctor
|
} // QgsVectorLayerProperties ctor
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::loadRows()
|
||||||
|
{
|
||||||
|
const QgsFieldMap &fields = layer->pendingFields();
|
||||||
|
|
||||||
|
int row=0;
|
||||||
|
for(QgsFieldMap::const_iterator it=fields.begin(); it!=fields.end(); it++, row++)
|
||||||
|
setRow( row, it.key(), it.value() );
|
||||||
|
|
||||||
|
tblAttributes->resizeColumnsToContents();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::setRow(int row, int idx, const QgsField &field)
|
||||||
|
{
|
||||||
|
tblAttributes->setItem(row, 0, new QTableWidgetItem( QString::number(idx) ) );
|
||||||
|
tblAttributes->setItem(row, 1, new QTableWidgetItem( field.name() ) );
|
||||||
|
tblAttributes->setItem(row, 2, new QTableWidgetItem( field.typeName() ) );
|
||||||
|
tblAttributes->setItem(row, 3, new QTableWidgetItem( QString::number( field.length() ) ) );
|
||||||
|
tblAttributes->setItem(row, 4, new QTableWidgetItem( QString::number( field.precision() ) ) );
|
||||||
|
tblAttributes->setItem(row, 5, new QTableWidgetItem( field.comment() ) );
|
||||||
|
|
||||||
|
for(int i=0; i<6; i++)
|
||||||
|
tblAttributes->item(row, i)->setFlags( tblAttributes->item(row, i)->flags() & ~Qt::ItemIsEditable );
|
||||||
|
|
||||||
|
QComboBox *cb = new QComboBox();
|
||||||
|
cb->addItem( tr("line edit"), QgsVectorLayer::LineEdit);
|
||||||
|
cb->addItem( tr("unique values"), QgsVectorLayer::UniqueValues);
|
||||||
|
cb->addItem( tr("unique values (editable)"), QgsVectorLayer::UniqueValuesEditable);
|
||||||
|
cb->addItem( tr("value map"), QgsVectorLayer::ValueMap);
|
||||||
|
cb->addItem( tr("classification"), QgsVectorLayer::Classification);
|
||||||
|
cb->addItem( tr("range"), QgsVectorLayer::Range);
|
||||||
|
cb->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
|
||||||
|
cb->setCurrentIndex( layer->editType( idx ) );
|
||||||
|
|
||||||
|
tblAttributes->setCellWidget(row, 6, cb );
|
||||||
|
|
||||||
|
if( layer->editType(idx)==QgsVectorLayer::ValueMap )
|
||||||
|
{
|
||||||
|
// TODO: create a gui for value maps
|
||||||
|
QStringList mapList;
|
||||||
|
QMap<QString, QVariant> &map = layer->valueMap( idx );
|
||||||
|
for(QMap<QString, QVariant>::iterator mit=map.begin(); mit!=map.end(); mit++)
|
||||||
|
{
|
||||||
|
QgsDebugMsg( QString("idx:%1 key:%2 value:%3").arg( idx ).arg( mit.key() ).arg( mit.value().toString() ) );
|
||||||
|
if( mit.value().isNull() )
|
||||||
|
mapList << mit.key();
|
||||||
|
else
|
||||||
|
mapList << QString( "%1=%2" ).arg( mit.key() ).arg( mit.value().toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
tblAttributes->setItem(row, 7, new QTableWidgetItem( mapList.join(";") ) );
|
||||||
|
} else if( layer->editType(idx)==QgsVectorLayer::Range ) {
|
||||||
|
tblAttributes->setItem(
|
||||||
|
row, 7,
|
||||||
|
new QTableWidgetItem( QString("%1;%2;%3")
|
||||||
|
.arg( layer->range(idx).mMin.toString() )
|
||||||
|
.arg( layer->range(idx).mMax.toString() )
|
||||||
|
.arg( layer->range(idx).mStep.toString() )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QgsVectorLayerProperties::~QgsVectorLayerProperties()
|
QgsVectorLayerProperties::~QgsVectorLayerProperties()
|
||||||
{
|
{
|
||||||
disconnect(labelDialog, SIGNAL(labelSourceSet()),
|
disconnect(labelDialog, SIGNAL(labelSourceSet()), this, SLOT(setLabelCheckBox()));
|
||||||
this, SLOT(setLabelCheckBox()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::toggleEditing()
|
||||||
|
{
|
||||||
|
emit toggleEditing(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::attributeAdded(int idx)
|
||||||
|
{
|
||||||
|
const QgsFieldMap &fields = layer->pendingFields();
|
||||||
|
int row = tblAttributes->rowCount();
|
||||||
|
tblAttributes->insertRow(row);
|
||||||
|
setRow(row, idx, fields[idx]);
|
||||||
|
tblAttributes->setCurrentCell(row, idx, QItemSelectionModel::NoUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::attributeDeleted(int idx)
|
||||||
|
{
|
||||||
|
for(int i=0; i<tblAttributes->rowCount(); i++)
|
||||||
|
{
|
||||||
|
if( tblAttributes->item(i, 0)->text().toInt()==idx )
|
||||||
|
{
|
||||||
|
tblAttributes->removeRow(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::addAttribute()
|
||||||
|
{
|
||||||
|
QgsAddAttrDialog dialog(layer->getDataProvider(), this);
|
||||||
|
if(dialog.exec()==QDialog::Accepted)
|
||||||
|
{
|
||||||
|
if(!addAttribute(dialog.name(),dialog.type()))
|
||||||
|
{
|
||||||
|
QMessageBox::information(this,tr("Name conflict"),tr("The attribute could not be inserted. The name already exists in the table."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsVectorLayerProperties::addAttribute(QString name, QString type)
|
||||||
|
{
|
||||||
|
QgsDebugMsg("inserting attribute " + name + " of type " + type );
|
||||||
|
return layer->addAttribute( name, type );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::deleteAttribute()
|
||||||
|
{
|
||||||
|
QList<QTableWidgetItem*> items = tblAttributes->selectedItems();
|
||||||
|
QList<int> idxs;
|
||||||
|
|
||||||
|
for(QList<QTableWidgetItem*>::const_iterator it=items.begin(); it!=items.end(); it++)
|
||||||
|
{
|
||||||
|
if( (*it)->column()==0 )
|
||||||
|
idxs << (*it)->text().toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(QList<int>::const_iterator it=idxs.begin(); it!=idxs.end(); it++)
|
||||||
|
layer->deleteAttribute(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::editingToggled()
|
||||||
|
{
|
||||||
|
if( layer->isEditable() )
|
||||||
|
loadRows();
|
||||||
|
|
||||||
|
updateButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsVectorLayerProperties::updateButtons()
|
||||||
|
{
|
||||||
|
if ( layer->isEditable() )
|
||||||
|
{
|
||||||
|
int cap = layer->getDataProvider()->capabilities();
|
||||||
|
mAddAttributeButton->setEnabled( cap & QgsVectorDataProvider::AddAttributes );
|
||||||
|
mDeleteAttributeButton->setEnabled( cap & QgsVectorDataProvider::DeleteAttributes );
|
||||||
|
mToggleEditingButton->setChecked( true );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mAddAttributeButton->setEnabled( false );
|
||||||
|
mDeleteAttributeButton->setEnabled( false );
|
||||||
|
mToggleEditingButton->setChecked( false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QgsVectorLayerProperties::sliderTransparency_valueChanged(int theValue)
|
void QgsVectorLayerProperties::sliderTransparency_valueChanged(int theValue)
|
||||||
{
|
{
|
||||||
//set the transparency percentage label to a suitable value
|
//set the transparency percentage label to a suitable value
|
||||||
@ -167,8 +349,6 @@ void QgsVectorLayerProperties::reset( void )
|
|||||||
"layer is shown here. This is currently only supported for PostgreSQL "
|
"layer is shown here. This is currently only supported for PostgreSQL "
|
||||||
"layers. To enter or modify the query, click on the Query Builder button"));
|
"layers. To enter or modify the query, click on the Query Builder button"));
|
||||||
|
|
||||||
//we are dealing with a pg layer here so that we can enable the sql box
|
|
||||||
QgsVectorDataProvider *dp = dynamic_cast<QgsVectorDataProvider *>(layer->getDataProvider());
|
|
||||||
//see if we are dealing with a pg layer here
|
//see if we are dealing with a pg layer here
|
||||||
if(layer->providerType() == "postgres")
|
if(layer->providerType() == "postgres")
|
||||||
{
|
{
|
||||||
@ -188,7 +368,7 @@ void QgsVectorLayerProperties::reset( void )
|
|||||||
}
|
}
|
||||||
|
|
||||||
//get field list for display field combo
|
//get field list for display field combo
|
||||||
const QgsFieldMap& myFields = dp->fields();
|
const QgsFieldMap& myFields = layer->pendingFields();
|
||||||
for (QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it)
|
for (QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it)
|
||||||
{
|
{
|
||||||
displayFieldComboBox->addItem( it->name() );
|
displayFieldComboBox->addItem( it->name() );
|
||||||
@ -249,7 +429,7 @@ void QgsVectorLayerProperties::reset( void )
|
|||||||
SLOT(alterLayerDialog(const QString &)));
|
SLOT(alterLayerDialog(const QString &)));
|
||||||
|
|
||||||
// reset fields in label dialog
|
// reset fields in label dialog
|
||||||
layer->label()->setFields ( layer->getDataProvider()->fields() );
|
layer->label()->setFields ( layer->pendingFields() );
|
||||||
|
|
||||||
//set the metadata contents
|
//set the metadata contents
|
||||||
QString myStyle = QgsApplication::reportStyleSheet();
|
QString myStyle = QgsApplication::reportStyleSheet();
|
||||||
@ -311,6 +491,69 @@ void QgsVectorLayerProperties::apply()
|
|||||||
layer->setLabelOn(labelCheckBox->isChecked());
|
layer->setLabelOn(labelCheckBox->isChecked());
|
||||||
layer->setLayerName(displayName());
|
layer->setLayerName(displayName());
|
||||||
|
|
||||||
|
for(int i=0; i<tblAttributes->rowCount(); i++)
|
||||||
|
{
|
||||||
|
int idx = tblAttributes->item(i, 0)->text().toInt();
|
||||||
|
const QgsField &field = layer->pendingFields()[idx];
|
||||||
|
QgsVectorLayer::EditType editType = layer->editType(idx);
|
||||||
|
|
||||||
|
QComboBox *cb = dynamic_cast<QComboBox*>( tblAttributes->cellWidget(i, 6) );
|
||||||
|
if(!cb)
|
||||||
|
continue;
|
||||||
|
layer->setEditType( idx, (QgsVectorLayer::EditType) cb->itemData( cb->currentIndex() ).toInt() );
|
||||||
|
|
||||||
|
if( editType==QgsVectorLayer::ValueMap )
|
||||||
|
{
|
||||||
|
QMap<QString, QVariant> &map = layer->valueMap(idx);
|
||||||
|
map.clear();
|
||||||
|
|
||||||
|
QString value = tblAttributes->item(i, 7)->text();
|
||||||
|
if( !value.isEmpty() )
|
||||||
|
{
|
||||||
|
QStringList values = tblAttributes->item(i, 7)->text().split(";");
|
||||||
|
for(int j=0; j<values.size(); j++)
|
||||||
|
{
|
||||||
|
QStringList args = values[j].split("=");
|
||||||
|
QVariant value;
|
||||||
|
|
||||||
|
if(args.size()==1 || (args.size()==2 && args[0]==args[1]))
|
||||||
|
{
|
||||||
|
QgsDebugMsg( QString("idx:%1 key:%2 value:%2").arg(idx).arg(args[0]) );
|
||||||
|
value = args[0];
|
||||||
|
}
|
||||||
|
else if(args.size()==2)
|
||||||
|
{
|
||||||
|
QgsDebugMsg( QString("idx:%1 key:%2 value:%3").arg( idx ).arg( args[0] ).arg( args[1] ) );
|
||||||
|
value = args[1];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( value.canConvert( field.type() ) )
|
||||||
|
{
|
||||||
|
map.insert( args[0], value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if( editType==QgsVectorLayer::Range ) {
|
||||||
|
QStringList values = tblAttributes->item(i, 7)->text().split(";");
|
||||||
|
|
||||||
|
if( values.size()==3 ) {
|
||||||
|
QVariant min = values[0];
|
||||||
|
QVariant max = values[1];
|
||||||
|
QVariant step = values[2];
|
||||||
|
|
||||||
|
if( min.canConvert(field.type()) &&
|
||||||
|
max.canConvert(field.type()) &&
|
||||||
|
step.canConvert(field.type()) )
|
||||||
|
{
|
||||||
|
min.convert( field.type() );
|
||||||
|
max.convert( field.type() );
|
||||||
|
step.convert( field.type() );
|
||||||
|
layer->range(idx) = QgsVectorLayer::RangeData(min,max,step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QgsSingleSymbolDialog *sdialog =
|
QgsSingleSymbolDialog *sdialog =
|
||||||
dynamic_cast < QgsSingleSymbolDialog * >(widgetStackRenderers->currentWidget());
|
dynamic_cast < QgsSingleSymbolDialog * >(widgetStackRenderers->currentWidget());
|
||||||
@ -354,11 +597,8 @@ void QgsVectorLayerProperties::on_pbnQueryBuilder_clicked()
|
|||||||
// launch the query builder using the PostgreSQL connection
|
// launch the query builder using the PostgreSQL connection
|
||||||
// from the provider
|
// from the provider
|
||||||
|
|
||||||
// get the data provider
|
// cast to postgres provider type
|
||||||
QgsVectorDataProvider *dp =
|
QgsPostgresProvider * myPGProvider = (QgsPostgresProvider *) layer->getDataProvider() ; // FIXME use dynamic cast
|
||||||
dynamic_cast<QgsVectorDataProvider *>(layer->getDataProvider());
|
|
||||||
// cast to postgres provider type
|
|
||||||
QgsPostgresProvider * myPGProvider = (QgsPostgresProvider *) dp;
|
|
||||||
// create the query builder object using the table name
|
// create the query builder object using the table name
|
||||||
// and postgres connection from the provider
|
// and postgres connection from the provider
|
||||||
QgsDataSourceURI uri(myPGProvider->dataSourceUri());
|
QgsDataSourceURI uri(myPGProvider->dataSourceUri());
|
||||||
@ -541,7 +781,7 @@ QString QgsVectorLayerProperties::getMetadata()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
//
|
//
|
||||||
// Add the info about each field in the attribute table
|
// Add the info about each field in the attribute table
|
||||||
//
|
//
|
||||||
@ -569,8 +809,7 @@ QString QgsVectorLayerProperties::getMetadata()
|
|||||||
myMetadata += "</th>";
|
myMetadata += "</th>";
|
||||||
|
|
||||||
//get info for each field by looping through them
|
//get info for each field by looping through them
|
||||||
QgsVectorDataProvider *myDataProvider = dynamic_cast<QgsVectorDataProvider *>(layer->getDataProvider());
|
const QgsFieldMap& myFields = layer->pendingFields();
|
||||||
const QgsFieldMap& myFields = myDataProvider->fields();
|
|
||||||
for (QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it)
|
for (QgsFieldMap::const_iterator it = myFields.begin(); it != myFields.end(); ++it)
|
||||||
{
|
{
|
||||||
const QgsField& myField = *it;
|
const QgsField& myField = *it;
|
||||||
@ -594,15 +833,17 @@ QString QgsVectorLayerProperties::getMetadata()
|
|||||||
|
|
||||||
//close field list
|
//close field list
|
||||||
myMetadata += "</table>"; //end of nested table
|
myMetadata += "</table>"; //end of nested table
|
||||||
|
#endif
|
||||||
|
|
||||||
myMetadata += "</td></tr>"; //end of stats container table row
|
myMetadata += "</td></tr>"; //end of stats container table row
|
||||||
//
|
//
|
||||||
// Close the table
|
// Close the table
|
||||||
//
|
//
|
||||||
|
|
||||||
myMetadata += "</table>";
|
myMetadata += "</table>";
|
||||||
|
|
||||||
myMetadata += "</body></html>";
|
myMetadata += "</body></html>";
|
||||||
return myMetadata;
|
return myMetadata;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,15 +23,20 @@
|
|||||||
#include "ui_qgsvectorlayerpropertiesbase.h"
|
#include "ui_qgsvectorlayerpropertiesbase.h"
|
||||||
#include "qgisgui.h"
|
#include "qgisgui.h"
|
||||||
#include "qgsrenderer.h"
|
#include "qgsrenderer.h"
|
||||||
|
#include "qgsaddattrdialog.h"
|
||||||
|
#include "qgsdelattrdialog.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
|
|
||||||
|
class QgsMapLayer;
|
||||||
|
|
||||||
class QgsAttributeActionDialog;
|
class QgsAttributeActionDialog;
|
||||||
class QgsLabelDialog;
|
class QgsLabelDialog;
|
||||||
class QgsVectorLayer;
|
class QgsVectorLayer;
|
||||||
|
|
||||||
|
class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPropertiesBase
|
||||||
class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPropertiesBase{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT;
|
||||||
public:
|
public:
|
||||||
QgsVectorLayerProperties(QgsVectorLayer *lyr = 0,QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags);
|
QgsVectorLayerProperties(QgsVectorLayer *lyr = 0,QWidget *parent = 0, Qt::WFlags fl = QgisGui::ModalDialogFlags);
|
||||||
~QgsVectorLayerProperties();
|
~QgsVectorLayerProperties();
|
||||||
/**Sets the legend type to "single symbol", "graduated symbol" or "continuous color"*/
|
/**Sets the legend type to "single symbol", "graduated symbol" or "continuous color"*/
|
||||||
@ -42,19 +47,42 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
|
|||||||
/**Sets the attribute that is used in the Identify Results dialog box*/
|
/**Sets the attribute that is used in the Identify Results dialog box*/
|
||||||
void setDisplayField(QString name);
|
void setDisplayField(QString name);
|
||||||
|
|
||||||
public slots:
|
/**Adds an attribute to the table (but does not commit it yet)
|
||||||
|
@param name attribute name
|
||||||
|
@param type attribute type
|
||||||
|
@return false in case of a name conflict, true in case of success*/
|
||||||
|
bool addAttribute(QString name, QString type);
|
||||||
|
|
||||||
|
/**Deletes an attribute (but does not commit it)
|
||||||
|
@param name attribute name
|
||||||
|
@return false in case of a non-existing attribute.*/
|
||||||
|
bool deleteAttribute(int attr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
void alterLayerDialog(const QString& string);
|
void alterLayerDialog(const QString& string);
|
||||||
|
|
||||||
/** Reset to original (vector layer) values */
|
/** Reset to original (vector layer) values */
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
/** Get metadata about the layer in nice formatted html */
|
/** Get metadata about the layer in nice formatted html */
|
||||||
QString getMetadata();
|
QString getMetadata();
|
||||||
|
|
||||||
/** Set transparency based on slider position */
|
/** Set transparency based on slider position */
|
||||||
void sliderTransparency_valueChanged(int theValue);
|
void sliderTransparency_valueChanged(int theValue);
|
||||||
|
|
||||||
/** Toggles on the label check box */
|
/** Toggles on the label check box */
|
||||||
void setLabelCheckBox();
|
void setLabelCheckBox();
|
||||||
|
|
||||||
/** Called when apply button is pressed or dialog is accepted */
|
/** Called when apply button is pressed or dialog is accepted */
|
||||||
void apply();
|
void apply();
|
||||||
|
|
||||||
|
/** toggle editing of layer */
|
||||||
|
void toggleEditing();
|
||||||
|
|
||||||
|
/** editing of layer was toggled */
|
||||||
|
void editingToggled();
|
||||||
|
|
||||||
//
|
//
|
||||||
//methods reimplemented from qt designer base class
|
//methods reimplemented from qt designer base class
|
||||||
//
|
//
|
||||||
@ -67,13 +95,21 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
|
|||||||
void on_pbnSaveDefaultStyle_clicked();
|
void on_pbnSaveDefaultStyle_clicked();
|
||||||
void on_pbnLoadStyle_clicked();
|
void on_pbnLoadStyle_clicked();
|
||||||
void on_pbnSaveStyleAs_clicked();
|
void on_pbnSaveStyleAs_clicked();
|
||||||
|
|
||||||
signals:
|
|
||||||
|
|
||||||
/** emitted when changes to layer were saved to update legend */
|
|
||||||
void refreshLegend(QString layerID, bool expandItem);
|
|
||||||
|
|
||||||
protected:
|
void addAttribute();
|
||||||
|
void deleteAttribute();
|
||||||
|
|
||||||
|
void attributeAdded(int idx);
|
||||||
|
void attributeDeleted(int idx);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
/** emitted when changes to layer were saved to update legend */
|
||||||
|
void refreshLegend(QString layerID, bool expandItem);
|
||||||
|
|
||||||
|
void toggleEditing(QgsMapLayer *);
|
||||||
|
|
||||||
|
protected:
|
||||||
QgsVectorLayer *layer;
|
QgsVectorLayer *layer;
|
||||||
/**Renderer dialog which is shown*/
|
/**Renderer dialog which is shown*/
|
||||||
QDialog* mRendererDialog;
|
QDialog* mRendererDialog;
|
||||||
@ -83,14 +119,19 @@ class QgsVectorLayerProperties : public QDialog, private Ui::QgsVectorLayerPrope
|
|||||||
QgsLabelDialog* labelDialog;
|
QgsLabelDialog* labelDialog;
|
||||||
/**Actions dialog. If apply is pressed, the actions are stored for later use */
|
/**Actions dialog. If apply is pressed, the actions are stored for later use */
|
||||||
QgsAttributeActionDialog* actionDialog;
|
QgsAttributeActionDialog* actionDialog;
|
||||||
|
|
||||||
|
void updateButtons();
|
||||||
|
void loadRows();
|
||||||
|
void setRow(int row, int idx, const QgsField &field);
|
||||||
|
|
||||||
/**Buffer pixmap which takes the picture of renderers before they are assigned to the vector layer*/
|
/**Buffer pixmap which takes the picture of renderers before they are assigned to the vector layer*/
|
||||||
//QPixmap bufferPixmap;
|
//QPixmap bufferPixmap;
|
||||||
static const int context_id = 94000531;
|
static const int context_id = 94000531;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QString QgsVectorLayerProperties::displayName()
|
inline QString QgsVectorLayerProperties::displayName()
|
||||||
{
|
{
|
||||||
return txtDisplayName->text();
|
return txtDisplayName->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,9 +34,7 @@ General purpose distance and area calculator
|
|||||||
*/
|
*/
|
||||||
class CORE_EXPORT QgsDistanceArea
|
class CORE_EXPORT QgsDistanceArea
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
QgsDistanceArea();
|
QgsDistanceArea();
|
||||||
|
|
||||||
|
@ -18,20 +18,12 @@ email : sherman at mrcc.com
|
|||||||
#include "qgsgeometry.h"
|
#include "qgsgeometry.h"
|
||||||
#include "qgsrect.h"
|
#include "qgsrect.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cfloat>
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <limits>
|
|
||||||
#endif
|
|
||||||
#include <cstring>
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
/** \class QgsFeature
|
/** \class QgsFeature
|
||||||
* \brief Encapsulates a spatial feature with attributes
|
* \brief Encapsulates a spatial feature with attributes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QgsFeature::QgsFeature(int id, QString typeName)
|
QgsFeature::QgsFeature(int id, QString typeName)
|
||||||
: mFid(id),
|
: mFid(id),
|
||||||
mGeometry(0),
|
mGeometry(0),
|
||||||
mOwnsGeometry(0),
|
mOwnsGeometry(0),
|
||||||
mValid(false),
|
mValid(false),
|
||||||
@ -41,101 +33,40 @@ QgsFeature::QgsFeature(int id, QString typeName)
|
|||||||
// NOOP
|
// NOOP
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsFeature::QgsFeature( QgsFeature const & rhs,
|
|
||||||
const QgsChangedAttributesMap & changedAttributes,
|
|
||||||
const QgsGeometryMap & changedGeometries )
|
|
||||||
: mFid( rhs.mFid ),
|
|
||||||
mValid( rhs.mValid ),
|
|
||||||
mDirty( rhs.mDirty ),
|
|
||||||
mTypeName( rhs.mTypeName )
|
|
||||||
|
|
||||||
{
|
|
||||||
// copy attributes from rhs feature
|
|
||||||
mAttributes = rhs.mAttributes;
|
|
||||||
|
|
||||||
if (changedAttributes.contains(mFid))
|
|
||||||
{
|
|
||||||
// get map of changed attributes
|
|
||||||
const QgsAttributeMap& changed = changedAttributes[mFid];
|
|
||||||
|
|
||||||
// changet the attributes which were provided in the attribute map
|
|
||||||
for (QgsAttributeMap::const_iterator it = changed.begin(); it != changed.end(); ++it)
|
|
||||||
{
|
|
||||||
changeAttribute(it.key(), it.value());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedGeometries.contains(mFid))
|
|
||||||
{
|
|
||||||
// deep-copy geometry purely from changedGeometries
|
|
||||||
mGeometry = new QgsGeometry(changedGeometries[mFid]);
|
|
||||||
mOwnsGeometry = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// copy geometry purely from rhs feature
|
|
||||||
if ( rhs.mGeometry )
|
|
||||||
{
|
|
||||||
mGeometry = new QgsGeometry( *(rhs.mGeometry) );
|
|
||||||
mOwnsGeometry = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mGeometry = 0;
|
|
||||||
mOwnsGeometry = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QgsFeature::QgsFeature( QgsFeature const & rhs )
|
QgsFeature::QgsFeature( QgsFeature const & rhs )
|
||||||
: mFid( rhs.mFid ),
|
: mFid( rhs.mFid ),
|
||||||
mAttributes( rhs.mAttributes ),
|
mAttributes( rhs.mAttributes ),
|
||||||
mValid( rhs.mValid ),
|
mValid( rhs.mValid ),
|
||||||
mDirty( rhs.mDirty ),
|
mDirty( rhs.mDirty ),
|
||||||
mTypeName( rhs.mTypeName )
|
mTypeName( rhs.mTypeName ),
|
||||||
|
mGeometry( 0 ),
|
||||||
|
mOwnsGeometry( false )
|
||||||
{
|
{
|
||||||
|
|
||||||
// copy embedded geometry
|
// copy embedded geometry
|
||||||
if ( rhs.mGeometry )
|
if ( rhs.mGeometry )
|
||||||
{
|
{
|
||||||
mGeometry = new QgsGeometry( *(rhs.mGeometry) );
|
setGeometry( *rhs.mGeometry );
|
||||||
mOwnsGeometry = TRUE;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
mGeometry = 0;
|
|
||||||
mOwnsGeometry = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QgsFeature & QgsFeature::operator=( QgsFeature const & rhs )
|
QgsFeature & QgsFeature::operator=( QgsFeature const & rhs )
|
||||||
{
|
{
|
||||||
if ( &rhs == this )
|
if ( &rhs == this )
|
||||||
{ return *this; }
|
return *this;
|
||||||
|
|
||||||
mFid = rhs.mFid ;
|
mFid = rhs.mFid;
|
||||||
mDirty = rhs.mDirty ;
|
mDirty = rhs.mDirty;
|
||||||
mAttributes = rhs.mAttributes ;
|
mAttributes = rhs.mAttributes;
|
||||||
mValid = rhs.mValid ;
|
mValid = rhs.mValid;
|
||||||
mTypeName = rhs.mTypeName;
|
mTypeName = rhs.mTypeName;
|
||||||
|
mGeometry = 0;
|
||||||
|
mOwnsGeometry = false;
|
||||||
|
|
||||||
// copy embedded geometry
|
|
||||||
delete mGeometry;
|
|
||||||
if ( rhs.mGeometry )
|
if ( rhs.mGeometry )
|
||||||
{
|
setGeometry( *rhs.mGeometry );
|
||||||
mGeometry = new QgsGeometry( *(rhs.mGeometry) );
|
|
||||||
mOwnsGeometry = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mGeometry = 0;
|
|
||||||
mOwnsGeometry = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
} // QgsFeature::operator=( QgsFeature const & rhs )
|
} // QgsFeature::operator=( QgsFeature const & rhs )
|
||||||
|
|
||||||
@ -144,13 +75,9 @@ QgsFeature & QgsFeature::operator=( QgsFeature const & rhs )
|
|||||||
//! Destructor
|
//! Destructor
|
||||||
QgsFeature::~QgsFeature()
|
QgsFeature::~QgsFeature()
|
||||||
{
|
{
|
||||||
|
|
||||||
// Destruct the attached geometry only if we still own it.
|
// Destruct the attached geometry only if we still own it.
|
||||||
if ( (mOwnsGeometry) && (mGeometry) )
|
if ( mOwnsGeometry && mGeometry )
|
||||||
{
|
|
||||||
delete mGeometry;
|
delete mGeometry;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,17 +124,15 @@ void QgsFeature::changeAttribute(int field, QVariant attr)
|
|||||||
mAttributes[field] = attr;
|
mAttributes[field] = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsGeometry *QgsFeature::geometry()
|
||||||
QgsGeometry * QgsFeature::geometry()
|
|
||||||
{
|
{
|
||||||
return mGeometry;
|
return mGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QgsGeometry *QgsFeature::geometryAndOwnership()
|
||||||
QgsGeometry * QgsFeature::geometryAndOwnership()
|
|
||||||
{
|
{
|
||||||
mOwnsGeometry = FALSE;
|
mOwnsGeometry = false;
|
||||||
|
|
||||||
return mGeometry;
|
return mGeometry;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,7 +143,6 @@ QgsGeometry * QgsFeature::geometryAndOwnership()
|
|||||||
void QgsFeature::setFeatureId(int id)
|
void QgsFeature::setFeatureId(int id)
|
||||||
{
|
{
|
||||||
mFid = id;
|
mFid = id;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -239,45 +163,29 @@ void QgsFeature::setTypeName(QString typeName)
|
|||||||
|
|
||||||
void QgsFeature::setGeometry(const QgsGeometry& geom)
|
void QgsFeature::setGeometry(const QgsGeometry& geom)
|
||||||
{
|
{
|
||||||
// Destruct the attached geometry only if we still own it, before assigning new one.
|
setGeometry( new QgsGeometry(geom) );
|
||||||
if ( (mOwnsGeometry) && (mGeometry) )
|
|
||||||
{
|
|
||||||
delete mGeometry;
|
|
||||||
mGeometry = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGeometry = new QgsGeometry(geom);
|
|
||||||
mOwnsGeometry = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QgsFeature::setGeometry(QgsGeometry* geom)
|
void QgsFeature::setGeometry(QgsGeometry* geom)
|
||||||
{
|
{
|
||||||
// Destruct the attached geometry only if we still own it, before assigning new one.
|
// Destruct the attached geometry only if we still own it, before assigning new one.
|
||||||
if ( (mOwnsGeometry) && (mGeometry) )
|
if ( mOwnsGeometry && mGeometry )
|
||||||
{
|
{
|
||||||
delete mGeometry;
|
delete mGeometry;
|
||||||
mGeometry = 0;
|
mGeometry = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mGeometry = geom;
|
mGeometry = geom;
|
||||||
mOwnsGeometry = TRUE;
|
mOwnsGeometry = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the pointer to the feature geometry
|
/** Set the pointer to the feature geometry
|
||||||
*/
|
*/
|
||||||
void QgsFeature::setGeometryAndOwnership(unsigned char *geom, size_t length)
|
void QgsFeature::setGeometryAndOwnership(unsigned char *geom, size_t length)
|
||||||
{
|
{
|
||||||
// Destruct the attached geometry only if we still own it, before assigning new one.
|
QgsGeometry *g = new QgsGeometry();
|
||||||
if ( (mOwnsGeometry) && (mGeometry) )
|
g->setWkbAndOwnership(geom, length);
|
||||||
{
|
setGeometry(g);
|
||||||
delete mGeometry;
|
|
||||||
mGeometry = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mGeometry = new QgsGeometry();
|
|
||||||
mGeometry->setWkbAndOwnership(geom, length);
|
|
||||||
mOwnsGeometry = TRUE;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -298,5 +206,5 @@ bool QgsFeature::isDirty() const
|
|||||||
|
|
||||||
void QgsFeature::resetDirty()
|
void QgsFeature::resetDirty()
|
||||||
{
|
{
|
||||||
mDirty = FALSE;
|
mDirty = false;
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,11 @@ email : sherman at mrcc.com
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
class QgsGeometry;
|
class QgsGeometry;
|
||||||
class QgsRect;
|
class QgsRect;
|
||||||
|
class QgsFeature;
|
||||||
|
|
||||||
// key = field index, value = field value
|
// key = field index, value = field value
|
||||||
typedef QMap<int, QVariant> QgsAttributeMap;
|
typedef QMap<int, QVariant> QgsAttributeMap;
|
||||||
@ -37,6 +38,7 @@ typedef QMap<int, QgsGeometry> QgsGeometryMap;
|
|||||||
// key = field index, value = field name
|
// key = field index, value = field name
|
||||||
typedef QMap<int, QString> QgsFieldNameMap;
|
typedef QMap<int, QString> QgsFieldNameMap;
|
||||||
|
|
||||||
|
typedef QList<QgsFeature> QgsFeatureList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class QgsFeature - Feature attribute class.
|
* @class QgsFeature - Feature attribute class.
|
||||||
@ -44,25 +46,12 @@ typedef QMap<int, QString> QgsFieldNameMap;
|
|||||||
*
|
*
|
||||||
* @author Gary E.Sherman
|
* @author Gary E.Sherman
|
||||||
*/
|
*/
|
||||||
class CORE_EXPORT QgsFeature {
|
class CORE_EXPORT QgsFeature
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Constructor
|
//! Constructor
|
||||||
QgsFeature(int id = 0, QString typeName = "" );
|
QgsFeature(int id = 0, QString typeName = "" );
|
||||||
|
|
||||||
/** create a copy of this feature in its uncommitted state.
|
|
||||||
To do this, you also pass in a reference to the feature's
|
|
||||||
layer's uncommitted attribute and geometry changes.
|
|
||||||
The resulting feature will have those changes applied.
|
|
||||||
|
|
||||||
This is useful in the cut/copy routine, where you'd
|
|
||||||
want a copy of the "current" feature, not the on-disk feature.
|
|
||||||
*/
|
|
||||||
QgsFeature( const QgsFeature & rhs,
|
|
||||||
const QgsChangedAttributesMap & changedAttributes,
|
|
||||||
const QgsGeometryMap & changedGeometries );
|
|
||||||
|
|
||||||
/** copy ctor needed due to internal pointer */
|
/** copy ctor needed due to internal pointer */
|
||||||
QgsFeature( QgsFeature const & rhs );
|
QgsFeature( QgsFeature const & rhs );
|
||||||
|
|
||||||
@ -140,17 +129,17 @@ class CORE_EXPORT QgsFeature {
|
|||||||
* You would normally do this after it's saved to permanent storage (e.g. disk, an ACID-compliant database)
|
* You would normally do this after it's saved to permanent storage (e.g. disk, an ACID-compliant database)
|
||||||
*/
|
*/
|
||||||
void resetDirty();
|
void resetDirty();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the geometry object associated with this feature
|
* Get the geometry object associated with this feature
|
||||||
*/
|
*/
|
||||||
QgsGeometry * geometry();
|
QgsGeometry *geometry();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the geometry object associated with this feature
|
* Get the geometry object associated with this feature
|
||||||
* The caller assumes responsibility for the QgsGeometry*'s destruction.
|
* The caller assumes responsibility for the QgsGeometry*'s destruction.
|
||||||
*/
|
*/
|
||||||
QgsGeometry * geometryAndOwnership();
|
QgsGeometry *geometryAndOwnership();
|
||||||
|
|
||||||
/** Set this feature's geometry from another QgsGeometry object (deep copy)
|
/** Set this feature's geometry from another QgsGeometry object (deep copy)
|
||||||
*/
|
*/
|
||||||
@ -174,17 +163,17 @@ class CORE_EXPORT QgsFeature {
|
|||||||
|
|
||||||
/** map of attributes accessed by field index */
|
/** map of attributes accessed by field index */
|
||||||
QgsAttributeMap mAttributes;
|
QgsAttributeMap mAttributes;
|
||||||
|
|
||||||
/** pointer to geometry in binary WKB format
|
/** pointer to geometry in binary WKB format
|
||||||
|
|
||||||
This is usually set by a call to OGRGeometry::exportToWkb()
|
This is usually set by a call to OGRGeometry::exportToWkb()
|
||||||
*/
|
*/
|
||||||
QgsGeometry* mGeometry;
|
QgsGeometry* mGeometry;
|
||||||
|
|
||||||
/** Indicator if the mGeometry is owned by this QgsFeature.
|
/** Indicator if the mGeometry is owned by this QgsFeature.
|
||||||
If so, this QgsFeature takes responsibility for the mGeometry's destruction.
|
If so, this QgsFeature takes responsibility for the mGeometry's destruction.
|
||||||
*/
|
*/
|
||||||
bool mOwnsGeometry;
|
bool mOwnsGeometry;
|
||||||
|
|
||||||
//! Flag to indicate if this feature is valid
|
//! Flag to indicate if this feature is valid
|
||||||
// TODO: still applies? [MD]
|
// TODO: still applies? [MD]
|
||||||
@ -200,4 +189,5 @@ class CORE_EXPORT QgsFeature {
|
|||||||
|
|
||||||
}; // class QgsFeature
|
}; // class QgsFeature
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -145,4 +145,7 @@ private:
|
|||||||
|
|
||||||
}; // class QgsField
|
}; // class QgsField
|
||||||
|
|
||||||
|
// key = field index, value=field data
|
||||||
|
typedef QMap<int, QgsField> QgsFieldMap;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -482,7 +482,7 @@ QgsLabelAttributes *QgsLabel::layerAttributes ( void )
|
|||||||
|
|
||||||
void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature )
|
void QgsLabel::labelPoint ( std::vector<QgsPoint>& points, QgsFeature & feature )
|
||||||
{
|
{
|
||||||
QgsGeometry* geometry = feature.geometry();
|
QgsGeometry *geometry = feature.geometry();
|
||||||
unsigned char *geom = geometry->wkbBuffer();
|
unsigned char *geom = geometry->wkbBuffer();
|
||||||
size_t geomlen = geometry->wkbSize();
|
size_t geomlen = geometry->wkbSize();
|
||||||
QGis::WKBTYPE wkbType = geometry->wkbType();
|
QGis::WKBTYPE wkbType = geometry->wkbType();
|
||||||
|
@ -83,7 +83,7 @@ public:
|
|||||||
void renderLabel ( QPainter* painter, const QgsRect& viewExtent,
|
void renderLabel ( QPainter* painter, const QgsRect& viewExtent,
|
||||||
const QgsCoordinateTransform* coordTransform,
|
const QgsCoordinateTransform* coordTransform,
|
||||||
const QgsMapToPixel *transform,
|
const QgsMapToPixel *transform,
|
||||||
QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0, double sizeScale = 1.);
|
QgsFeature &feature, bool selected, QgsLabelAttributes *classAttributes=0, double sizeScale = 1.);
|
||||||
|
|
||||||
/** Reads the renderer configuration from an XML file
|
/** Reads the renderer configuration from an XML file
|
||||||
@param rnode the DOM node to read
|
@param rnode the DOM node to read
|
||||||
@ -132,7 +132,7 @@ private:
|
|||||||
int width, int height, int alignment);
|
int width, int height, int alignment);
|
||||||
|
|
||||||
/** Get label point for simple feature in map units */
|
/** Get label point for simple feature in map units */
|
||||||
void labelPoint ( std::vector<QgsPoint>&, QgsFeature & feature );
|
void labelPoint ( std::vector<QgsPoint>&, QgsFeature &feature );
|
||||||
|
|
||||||
/** Get label point for the given feature in wkb format. */
|
/** Get label point for the given feature in wkb format. */
|
||||||
unsigned char* labelPoint( QgsPoint& point, unsigned char* wkb, size_t wkblen);
|
unsigned char* labelPoint( QgsPoint& point, unsigned char* wkb, size_t wkblen);
|
||||||
|
@ -57,32 +57,32 @@ class CORE_EXPORT QgsLogger
|
|||||||
static void debug(const QString& var, double val, int debuglevel = 1, const char* file = NULL, const char* function = NULL, int line = -1);
|
static void debug(const QString& var, double val, int debuglevel = 1, const char* file = NULL, const char* function = NULL, int line = -1);
|
||||||
|
|
||||||
/**Prints out a variable/value pair for types with overloaded operator<<*/
|
/**Prints out a variable/value pair for types with overloaded operator<<*/
|
||||||
template <typename T> static void debug(const QString& var, T val, const char* file = 0, const char* function = 0, \
|
template <typename T> static void debug(const QString& var, T val, const char* file = 0, const char* function = 0,
|
||||||
int line = -1, int debuglevel = 1)
|
int line = -1, int debuglevel = 1)
|
||||||
|
{
|
||||||
|
const char* dfile = debugFile();
|
||||||
|
if(dfile) //exit if QGIS_DEBUG_FILE is set and the message comes from the wrong file
|
||||||
{
|
{
|
||||||
const char* dfile = debugFile();
|
if(!file || strcmp(dfile, file) != 0)
|
||||||
if(dfile) //exit if QGIS_DEBUG_FILE is set and the message comes from the wrong file
|
{
|
||||||
{
|
return;
|
||||||
if(!file || strcmp(dfile, file) != 0)
|
}
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::ostringstream os;
|
|
||||||
os << var.toLocal8Bit().data() << " = " << val;
|
|
||||||
if(line == -1)
|
|
||||||
{
|
|
||||||
qDebug("%s: (%s) %s", file, function, os.str().c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
qDebug("%s(%d): (%s) %s", file, line, function, os.str().c_str());
|
|
||||||
#else
|
|
||||||
qDebug("%s: %d: (%s) %s", file, line, function, os.str().c_str());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
std::ostringstream os;
|
||||||
|
os << var.toLocal8Bit().data() << " = " << val;
|
||||||
|
if(line == -1)
|
||||||
|
{
|
||||||
|
qDebug("%s: (%s) %s", file, function, os.str().c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
qDebug("%s(%d): (%s) %s", file, line, function, os.str().c_str());
|
||||||
|
#else
|
||||||
|
qDebug("%s: %d: (%s) %s", file, line, function, os.str().c_str());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**Goes to qWarning*/
|
/**Goes to qWarning*/
|
||||||
static void warning(const QString& msg);
|
static void warning(const QString& msg);
|
||||||
|
@ -24,11 +24,10 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
class QgsSearchTreeValue;
|
#include <qgsfield.h>
|
||||||
class QgsField;
|
#include <qgsfeature.h>
|
||||||
|
|
||||||
typedef QMap<int, QgsField> QgsFieldMap;
|
class QgsSearchTreeValue;
|
||||||
typedef QMap<int, QVariant> QgsAttributeMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* QgsSearchTreeNode
|
* QgsSearchTreeNode
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
|
|
||||||
QgsSnapper::QgsSnapper(QgsMapRenderer* mapRender): mMapRenderer(mapRender)
|
QgsSnapper::QgsSnapper(QgsMapRenderer* mapRenderer): mMapRenderer(mapRenderer)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ QString QgsVectorDataProvider::dataComment() const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QgsVectorDataProvider::addFeatures(QgsFeatureList & flist)
|
bool QgsVectorDataProvider::addFeatures(QgsFeatureList &flist)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ QString QgsVectorDataProvider::capabilitiesString() const
|
|||||||
|
|
||||||
int QgsVectorDataProvider::indexFromFieldName(const QString& fieldName) const
|
int QgsVectorDataProvider::indexFromFieldName(const QString& fieldName) const
|
||||||
{
|
{
|
||||||
const QgsFieldMap& theFields = fields();
|
const QgsFieldMap &theFields = fields();
|
||||||
|
|
||||||
for (QgsFieldMap::const_iterator it = theFields.begin(); it != theFields.end(); ++it)
|
for (QgsFieldMap::const_iterator it = theFields.begin(); it != theFields.end(); ++it)
|
||||||
{
|
{
|
||||||
@ -248,7 +248,7 @@ void QgsVectorDataProvider::setFetchFeaturesWithoutGeom(bool fetch)
|
|||||||
mFetchFeaturesWithoutGeom = fetch;
|
mFetchFeaturesWithoutGeom = fetch;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QSet<QString>& QgsVectorDataProvider::supportedNativeTypes() const
|
const QgsNativeTypeMap &QgsVectorDataProvider::supportedNativeTypes() const
|
||||||
{
|
{
|
||||||
return mSupportedNativeTypes;
|
return mSupportedNativeTypes;
|
||||||
}
|
}
|
||||||
@ -261,15 +261,15 @@ QVariant QgsVectorDataProvider::minValue(int index)
|
|||||||
QgsDebugMsg("Warning: access requested to invalid field index: " + QString::number(index));
|
QgsDebugMsg("Warning: access requested to invalid field index: " + QString::number(index));
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCacheMinMaxDirty)
|
if (mCacheMinMaxDirty)
|
||||||
{
|
{
|
||||||
fillMinMaxCache();
|
fillMinMaxCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mCacheMinValues.contains(index))
|
if (!mCacheMinValues.contains(index))
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
return mCacheMinValues[index];
|
return mCacheMinValues[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ QVariant QgsVectorDataProvider::maxValue(int index)
|
|||||||
QgsDebugMsg("Warning: access requested to invalid field index: " + QString::number(index));
|
QgsDebugMsg("Warning: access requested to invalid field index: " + QString::number(index));
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCacheMinMaxDirty)
|
if (mCacheMinMaxDirty)
|
||||||
{
|
{
|
||||||
fillMinMaxCache();
|
fillMinMaxCache();
|
||||||
|
@ -26,9 +26,11 @@ class QTextCodec;
|
|||||||
//QGIS Includes
|
//QGIS Includes
|
||||||
#include "qgis.h"
|
#include "qgis.h"
|
||||||
#include "qgsdataprovider.h"
|
#include "qgsdataprovider.h"
|
||||||
|
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
|
|
||||||
|
typedef QMap<QString, QString> QgsNewAttributesMap;
|
||||||
|
typedef QMap<QString, QVariant::Type> QgsNativeTypeMap;
|
||||||
|
|
||||||
/** Base class for vector data providers
|
/** Base class for vector data providers
|
||||||
*/
|
*/
|
||||||
@ -137,7 +139,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
|||||||
* Return a map of indexes with field names for this layer
|
* Return a map of indexes with field names for this layer
|
||||||
* @return map of fields
|
* @return map of fields
|
||||||
*/
|
*/
|
||||||
virtual const QgsFieldMap & fields() const = 0;
|
virtual const QgsFieldMap &fields() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a short comment for the data that this provider is
|
* Return a short comment for the data that this provider is
|
||||||
@ -181,14 +183,14 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
|||||||
* Adds a list of features
|
* Adds a list of features
|
||||||
* @return true in case of success and false in case of failure
|
* @return true in case of success and false in case of failure
|
||||||
*/
|
*/
|
||||||
virtual bool addFeatures(QgsFeatureList & flist);
|
virtual bool addFeatures(QgsFeatureList &flist);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes a feature
|
* Deletes a feature
|
||||||
* @param id list containing feature ids to delete
|
* @param id list containing feature ids to delete
|
||||||
* @return true in case of success and false in case of failure
|
* @return true in case of success and false in case of failure
|
||||||
*/
|
*/
|
||||||
virtual bool deleteFeatures(const QgsFeatureIds & id);
|
virtual bool deleteFeatures(const QgsFeatureIds &id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds new attributes
|
* Adds new attributes
|
||||||
@ -246,24 +248,24 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
|||||||
* Set encoding used for accessing data from layer
|
* Set encoding used for accessing data from layer
|
||||||
*/
|
*/
|
||||||
virtual void setEncoding(const QString& e);
|
virtual void setEncoding(const QString& e);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get encoding which is used for accessing data
|
* Get encoding which is used for accessing data
|
||||||
*/
|
*/
|
||||||
QString encoding() const;
|
QString encoding() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of a field name or -1 if the field does not exist
|
* Returns the index of a field name or -1 if the field does not exist
|
||||||
*/
|
*/
|
||||||
int indexFromFieldName(const QString& fieldName) const;
|
int indexFromFieldName(const QString& fieldName) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return list of indexes to fetch all attributes in getNextFeature()
|
* Return list of indexes to fetch all attributes in getNextFeature()
|
||||||
*/
|
*/
|
||||||
virtual QgsAttributeList allAttributesList();
|
virtual QgsAttributeList allAttributesList();
|
||||||
|
|
||||||
/**Returns the names of the numerical types*/
|
/**Returns the names of the numerical types*/
|
||||||
const QSet<QString>& supportedNativeTypes() const;
|
const QgsNativeTypeMap &supportedNativeTypes() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether provider should return also features that don't have
|
* Set whether provider should return also features that don't have
|
||||||
@ -272,13 +274,12 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
|||||||
void setFetchFeaturesWithoutGeom(bool fetch);
|
void setFetchFeaturesWithoutGeom(bool fetch);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void fillMinMaxCache();
|
void fillMinMaxCache();
|
||||||
|
|
||||||
bool mCacheMinMaxDirty;
|
bool mCacheMinMaxDirty;
|
||||||
QMap<int, QVariant> mCacheMinValues, mCacheMaxValues;
|
QMap<int, QVariant> mCacheMinValues, mCacheMaxValues;
|
||||||
|
|
||||||
|
|
||||||
/** Encoding */
|
/** Encoding */
|
||||||
QTextCodec* mEncoding;
|
QTextCodec* mEncoding;
|
||||||
|
|
||||||
@ -292,7 +293,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
|
|||||||
QgsAttributeList mAttributesToFetch;
|
QgsAttributeList mAttributesToFetch;
|
||||||
|
|
||||||
/**The names of the providers native types*/
|
/**The names of the providers native types*/
|
||||||
QSet<QString> mSupportedNativeTypes;
|
QgsNativeTypeMap mSupportedNativeTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -219,7 +219,7 @@ bool QgsVectorFileWriter::addFeature(QgsFeature& feature)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build geometry from WKB
|
// build geometry from WKB
|
||||||
QgsGeometry* geom = feature.geometry();
|
QgsGeometry *geom = feature.geometry();
|
||||||
|
|
||||||
if (geom->wkbType() != mWkbType)
|
if (geom->wkbType() != mWkbType)
|
||||||
{
|
{
|
||||||
@ -234,7 +234,7 @@ bool QgsVectorFileWriter::addFeature(QgsFeature& feature)
|
|||||||
|
|
||||||
OGRGeometryH mGeom2 = createEmptyGeometry(geom->wkbType());
|
OGRGeometryH mGeom2 = createEmptyGeometry(geom->wkbType());
|
||||||
|
|
||||||
OGRErr err = OGR_G_ImportFromWkb(mGeom2,geom->wkbBuffer(), geom->wkbSize());
|
OGRErr err = OGR_G_ImportFromWkb(mGeom2, geom->wkbBuffer(), geom->wkbSize());
|
||||||
if (err != OGRERR_NONE)
|
if (err != OGRERR_NONE)
|
||||||
{
|
{
|
||||||
QgsDebugMsg("Failed to import geometry from WKB: " + QString::number(err));
|
QgsDebugMsg("Failed to import geometry from WKB: " + QString::number(err));
|
||||||
@ -247,7 +247,7 @@ bool QgsVectorFileWriter::addFeature(QgsFeature& feature)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OGRErr err = OGR_G_ImportFromWkb(mGeom,geom->wkbBuffer(), geom->wkbSize());
|
OGRErr err = OGR_G_ImportFromWkb(mGeom, geom->wkbBuffer(), geom->wkbSize());
|
||||||
if (err != OGRERR_NONE)
|
if (err != OGRERR_NONE)
|
||||||
{
|
{
|
||||||
QgsDebugMsg("Failed to import geometry from WKB: " + QString::number(err));
|
QgsDebugMsg("Failed to import geometry from WKB: " + QString::number(err));
|
||||||
|
@ -21,8 +21,7 @@
|
|||||||
#define _QGSVECTORFILEWRITER_H_
|
#define _QGSVECTORFILEWRITER_H_
|
||||||
|
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
typedef void *OGRDataSourceH;
|
typedef void *OGRDataSourceH;
|
||||||
typedef void *OGRLayerH;
|
typedef void *OGRLayerH;
|
||||||
@ -41,7 +40,7 @@ class QTextCodec;
|
|||||||
class CORE_EXPORT QgsVectorFileWriter
|
class CORE_EXPORT QgsVectorFileWriter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum WriterError
|
enum WriterError
|
||||||
{
|
{
|
||||||
NoError = 0,
|
NoError = 0,
|
||||||
@ -64,36 +63,36 @@ class CORE_EXPORT QgsVectorFileWriter
|
|||||||
const QgsFieldMap& fields,
|
const QgsFieldMap& fields,
|
||||||
QGis::WKBTYPE geometryType,
|
QGis::WKBTYPE geometryType,
|
||||||
const QgsSpatialRefSys* srs);
|
const QgsSpatialRefSys* srs);
|
||||||
|
|
||||||
/** checks whether there were any errors in constructor */
|
/** checks whether there were any errors in constructor */
|
||||||
WriterError hasError();
|
WriterError hasError();
|
||||||
|
|
||||||
/** add feature to the currently opened shapefile */
|
/** add feature to the currently opened shapefile */
|
||||||
bool addFeature(QgsFeature& feature);
|
bool addFeature(QgsFeature& feature);
|
||||||
|
|
||||||
/** close opened shapefile for writing */
|
/** close opened shapefile for writing */
|
||||||
~QgsVectorFileWriter();
|
~QgsVectorFileWriter();
|
||||||
|
|
||||||
/** Delete a shapefile (and its accompanying shx / dbf / prf)
|
/** Delete a shapefile (and its accompanying shx / dbf / prf)
|
||||||
* @param QString theFileName - /path/to/file.shp
|
* @param QString theFileName - /path/to/file.shp
|
||||||
* @return bool true if the file was deleted successfully
|
* @return bool true if the file was deleted successfully
|
||||||
*/
|
*/
|
||||||
static bool deleteShapeFile(QString theFileName);
|
static bool deleteShapeFile(QString theFileName);
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
OGRGeometryH createEmptyGeometry(QGis::WKBTYPE wkbType);
|
OGRGeometryH createEmptyGeometry(QGis::WKBTYPE wkbType);
|
||||||
|
|
||||||
OGRDataSourceH mDS;
|
OGRDataSourceH mDS;
|
||||||
OGRLayerH mLayer;
|
OGRLayerH mLayer;
|
||||||
OGRGeometryH mGeom;
|
OGRGeometryH mGeom;
|
||||||
|
|
||||||
QgsFieldMap mFields;
|
QgsFieldMap mFields;
|
||||||
|
|
||||||
/** contains error value if construction was not successfull */
|
/** contains error value if construction was not successfull */
|
||||||
WriterError mError;
|
WriterError mError;
|
||||||
|
|
||||||
QTextCodec* mCodec;
|
QTextCodec* mCodec;
|
||||||
|
|
||||||
/** geometry type which is being used */
|
/** geometry type which is being used */
|
||||||
QGis::WKBTYPE mWkbType;
|
QGis::WKBTYPE mWkbType;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,20 +22,20 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QPair>
|
#include <QStringList>
|
||||||
|
|
||||||
#include "qgis.h"
|
#include "qgis.h"
|
||||||
#include "qgsmaplayer.h"
|
#include "qgsmaplayer.h"
|
||||||
#include "qgsfeature.h"
|
#include "qgsfeature.h"
|
||||||
#include "qgssnapper.h"
|
#include "qgssnapper.h"
|
||||||
|
#include "qgsfeature.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
|
|
||||||
class QPainter;
|
class QPainter;
|
||||||
class QImage;
|
class QImage;
|
||||||
|
|
||||||
class QgsAttributeAction;
|
class QgsAttributeAction;
|
||||||
class QgsCoordinateTransform;
|
class QgsCoordinateTransform;
|
||||||
class QgsField;
|
|
||||||
class QgsFeature;
|
|
||||||
class QgsGeometry;
|
class QgsGeometry;
|
||||||
class QgsGeometryVertexIndex;
|
class QgsGeometryVertexIndex;
|
||||||
class QgsMapToPixel;
|
class QgsMapToPixel;
|
||||||
@ -44,34 +44,39 @@ class QgsRect;
|
|||||||
class QgsRenderer;
|
class QgsRenderer;
|
||||||
class QgsVectorDataProvider;
|
class QgsVectorDataProvider;
|
||||||
|
|
||||||
|
|
||||||
class QgsGeometry;
|
class QgsGeometry;
|
||||||
class QgsRect;
|
class QgsRect;
|
||||||
class QgsFeature;
|
|
||||||
|
|
||||||
//typedef QList<QgsField> QgsFieldList;
|
|
||||||
typedef QList<QgsFeature> QgsFeatureList;
|
|
||||||
typedef QList<int> QgsAttributeList;
|
|
||||||
|
|
||||||
|
typedef QList<int> QgsAttributeList;
|
||||||
typedef QSet<int> QgsFeatureIds;
|
typedef QSet<int> QgsFeatureIds;
|
||||||
typedef QSet<int> QgsAttributeIds;
|
typedef QSet<int> QgsAttributeIds;
|
||||||
|
|
||||||
// key = attribute name, value = attribute type
|
|
||||||
typedef QMap<QString, QString> QgsNewAttributesMap;
|
|
||||||
|
|
||||||
typedef QMap<int, QgsField> QgsFieldMap;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*! \class QgsVectorLayer
|
/*! \class QgsVectorLayer
|
||||||
* \brief Vector layer backed by a data source provider
|
* \brief Vector layer backed by a data source provider
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum EditType {
|
||||||
|
LineEdit,
|
||||||
|
UniqueValues,
|
||||||
|
UniqueValuesEditable,
|
||||||
|
ValueMap,
|
||||||
|
Classification,
|
||||||
|
Range,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RangeData {
|
||||||
|
RangeData() {}
|
||||||
|
RangeData(QVariant theMin, QVariant theMax, QVariant theStep)
|
||||||
|
: mMin(theMin), mMax(theMax), mStep(theStep) {}
|
||||||
|
|
||||||
|
QVariant mMin;
|
||||||
|
QVariant mMax;
|
||||||
|
QVariant mStep;
|
||||||
|
};
|
||||||
|
|
||||||
/** Constructor */
|
/** Constructor */
|
||||||
QgsVectorLayer(QString path = 0, QString baseName = 0,
|
QgsVectorLayer(QString path = 0, QString baseName = 0,
|
||||||
@ -113,35 +118,31 @@ public:
|
|||||||
|
|
||||||
/** The number of features that are selected in this layer */
|
/** The number of features that are selected in this layer */
|
||||||
int selectedFeatureCount();
|
int selectedFeatureCount();
|
||||||
|
|
||||||
/** Select features found within the search rectangle (in layer's coordinates) */
|
/** Select features found within the search rectangle (in layer's coordinates) */
|
||||||
void select(QgsRect & rect, bool lock);
|
void select(QgsRect & rect, bool lock);
|
||||||
|
|
||||||
/** Select not selected features and deselect selected ones */
|
/** Select not selected features and deselect selected ones */
|
||||||
void invertSelection();
|
void invertSelection();
|
||||||
|
|
||||||
/** Get a copy of the user-selected features */
|
/** Get a copy of the user-selected features */
|
||||||
QgsFeatureList selectedFeatures();
|
QgsFeatureList selectedFeatures();
|
||||||
|
|
||||||
/** Return reference to identifiers of selected features */
|
/** Return reference to identifiers of selected features */
|
||||||
const QgsFeatureIds& selectedFeaturesIds() const;
|
const QgsFeatureIds& selectedFeaturesIds() const;
|
||||||
|
|
||||||
/** Change selection to the new set of features */
|
/** Change selection to the new set of features */
|
||||||
void setSelectedFeatures(const QgsFeatureIds& ids);
|
void setSelectedFeatures(const QgsFeatureIds& ids);
|
||||||
|
|
||||||
/** Returns the bounding box of the selected features. If there is no selection, QgsRect(0,0,0,0) is returned */
|
/** Returns the bounding box of the selected features. If there is no selection, QgsRect(0,0,0,0) is returned */
|
||||||
QgsRect boundingBoxOfSelected();
|
QgsRect boundingBoxOfSelected();
|
||||||
|
|
||||||
|
|
||||||
/** Insert a copy of the given features into the layer */
|
|
||||||
bool addFeatures(QgsFeatureList features, bool makeSelected = TRUE);
|
|
||||||
|
|
||||||
/** Copies the symbology settings from another layer. Returns true in case of success */
|
/** Copies the symbology settings from another layer. Returns true in case of success */
|
||||||
bool copySymbologySettings(const QgsMapLayer& other);
|
bool copySymbologySettings(const QgsMapLayer& other);
|
||||||
|
|
||||||
/** Returns true if this layer can be in the same symbology group with another layer */
|
/** Returns true if this layer can be in the same symbology group with another layer */
|
||||||
bool isSymbologyCompatible(const QgsMapLayer& other) const;
|
bool isSymbologyCompatible(const QgsMapLayer& other) const;
|
||||||
|
|
||||||
/** Returns a pointer to the renderer */
|
/** Returns a pointer to the renderer */
|
||||||
const QgsRenderer* renderer() const;
|
const QgsRenderer* renderer() const;
|
||||||
|
|
||||||
@ -196,13 +197,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual QString subsetString();
|
virtual QString subsetString();
|
||||||
|
|
||||||
/**Returns the features contained in the rectangle. Considers the changed, added, deleted and permanent features
|
void select(QgsAttributeList fetchAttributes,
|
||||||
@return 0 in case of success*/
|
QgsRect rect = QgsRect(),
|
||||||
int featuresInRectangle(const QgsRect& searchRect, QList<QgsFeature>& features, bool fetchGeometries = true, bool fetchAttributes = true);
|
bool fetchGeometry = true);
|
||||||
|
|
||||||
|
bool getNextFeature(QgsFeature& feature);
|
||||||
|
|
||||||
/**Gets the feature at the given feature id. Considers the changed, added, deleted and permanent features
|
/**Gets the feature at the given feature id. Considers the changed, added, deleted and permanent features
|
||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
int getFeatureAtId(int featureId, QgsFeature& f, bool fetchGeometries = true, bool fetchAttributes = true);
|
int getFeatureAtId(int featureId, QgsFeature &f, bool fetchGeometries = true, bool fetchAttributes = true);
|
||||||
|
|
||||||
/** Adds a feature
|
/** Adds a feature
|
||||||
@param lastFeatureInBatch If True, will also go to the effort of e.g. updating the extents.
|
@param lastFeatureInBatch If True, will also go to the effort of e.g. updating the extents.
|
||||||
@ -233,14 +236,24 @@ public:
|
|||||||
bool deleteSelectedFeatures();
|
bool deleteSelectedFeatures();
|
||||||
|
|
||||||
/**Adds a ring to polygon/multipolygon features
|
/**Adds a ring to polygon/multipolygon features
|
||||||
@return 0 in case of success, 1 problem with feature type, 2 ring not closed, 3 ring not valid, 4 ring crosses \
|
@return
|
||||||
existing rings, 5 no feature found where ring can be inserted*/
|
0 in case of success,
|
||||||
|
1 problem with feature type,
|
||||||
|
2 ring not closed,
|
||||||
|
3 ring not valid,
|
||||||
|
4 ring crosses existing rings,
|
||||||
|
5 no feature found where ring can be inserted*/
|
||||||
int addRing(const QList<QgsPoint>& ring);
|
int addRing(const QList<QgsPoint>& ring);
|
||||||
|
|
||||||
/**Adds a new island polygon to a multipolygon feature
|
/**Adds a new island polygon to a multipolygon feature
|
||||||
@return 0 in case of success, 1 if selected feature is not multipolygon, 2 if ring is not a valid geometry, \
|
@return
|
||||||
3if new polygon ring not disjoint with existing rings, 4 if no feature was selected, 5 if several features are selected, \
|
0 in case of success,
|
||||||
6 if selected geometry not found*/
|
1 if selected feature is not multipolygon,
|
||||||
|
2 if ring is not a valid geometry,
|
||||||
|
3 if new polygon ring not disjoint with existing rings,
|
||||||
|
4 if no feature was selected,
|
||||||
|
5 if several features are selected,
|
||||||
|
6 if selected geometry not found*/
|
||||||
int addIsland(const QList<QgsPoint>& ring);
|
int addIsland(const QList<QgsPoint>& ring);
|
||||||
|
|
||||||
/**Translates feature by dx, dy
|
/**Translates feature by dx, dy
|
||||||
@ -256,7 +269,7 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
int splitFeatures(const QList<QgsPoint>& splitLine, bool topologicalEditing = false);
|
int splitFeatures(const QList<QgsPoint>& splitLine, bool topologicalEditing = false);
|
||||||
|
|
||||||
/**Changes the specified geometry such that it has no intersections with other \
|
/**Changes the specified geometry such that it has no intersections with other
|
||||||
polygon (or multipolygon) geometries in this vector layer
|
polygon (or multipolygon) geometries in this vector layer
|
||||||
@param geom geometry to modify
|
@param geom geometry to modify
|
||||||
@return 0 in case of success*/
|
@return 0 in case of success*/
|
||||||
@ -309,30 +322,8 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
@param snap_to to segment / to vertex
|
@param snap_to to segment / to vertex
|
||||||
@return 0 in case of success
|
@return 0 in case of success
|
||||||
*/
|
*/
|
||||||
int snapWithContext(const QgsPoint& startPoint, double snappingTolerance, QMultiMap<double, QgsSnappingResult>& snappingResults, \
|
int snapWithContext(const QgsPoint& startPoint, double snappingTolerance, QMultiMap<double, QgsSnappingResult>& snappingResults,
|
||||||
QgsSnapper::SNAP_TO snap_to);
|
QgsSnapper::SNAP_TO snap_to);
|
||||||
|
|
||||||
/**
|
|
||||||
Commits edited attributes. Depending on the feature id,
|
|
||||||
the changes are written to not commited features or redirected to
|
|
||||||
the data provider
|
|
||||||
|
|
||||||
The commits (in this version) occur in three distinct stages,
|
|
||||||
(delete attributes, add attributes, change attribute values)
|
|
||||||
so if a stage fails, it's difficult to roll back cleanly.
|
|
||||||
|
|
||||||
\todo Need to indicate at which stage the failed commit occurred,
|
|
||||||
for better cleanup and recovery from the error.
|
|
||||||
|
|
||||||
\param deleted Set of attribute indices (i.e. columns) to delete
|
|
||||||
\param added Map (name, type) of attribute names (i.e. columns) to add
|
|
||||||
\param changed Map (feature ID, Map (attribute name, new value) )
|
|
||||||
of attribute values to change
|
|
||||||
|
|
||||||
*/
|
|
||||||
bool commitAttributeChanges(const QgsAttributeIds& deleted,
|
|
||||||
const QgsNewAttributesMap& added,
|
|
||||||
const QgsChangedAttributesMap& changed);
|
|
||||||
|
|
||||||
/** Draws the layer
|
/** Draws the layer
|
||||||
* @return FALSE if an error occurred during drawing
|
* @return FALSE if an error occurred during drawing
|
||||||
@ -347,21 +338,37 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
*/
|
*/
|
||||||
void drawLabels(QPainter * p, const QgsRect& viewExtent, const QgsMapToPixel* cXf, const QgsCoordinateTransform* ct, double scale);
|
void drawLabels(QPainter * p, const QgsRect& viewExtent, const QgsMapToPixel* cXf, const QgsCoordinateTransform* ct, double scale);
|
||||||
|
|
||||||
/** returns array of added features */
|
/** returns fields list which are not commited */
|
||||||
QgsFeatureList& addedFeatures();
|
const QgsFieldMap &pendingFields();
|
||||||
|
|
||||||
/** returns array of deleted feature IDs */
|
/** returns list of attributes */
|
||||||
QgsFeatureIds& deletedFeatureIds();
|
QgsAttributeList pendingAllAttributesList();
|
||||||
|
|
||||||
/** returns array of features with changed attributes */
|
/** returns feature count after commit */
|
||||||
QgsChangedAttributesMap& changedAttributes();
|
int pendingFeatureCount();
|
||||||
|
|
||||||
/** Sets whether some features are modified or not */
|
/** Sets whether some features are modified or not */
|
||||||
void setModified(bool modified = TRUE, bool onlyGeometryWasModified = FALSE);
|
void setModified(bool modified = TRUE, bool onlyGeometryWasModified = FALSE);
|
||||||
|
|
||||||
/** Make layer editable */
|
/** Make layer editable */
|
||||||
bool startEditing();
|
bool startEditing();
|
||||||
|
|
||||||
|
/** changed an attribute value (but does not commit it */
|
||||||
|
bool changeAttributeValue(int fid, int field, QVariant value, bool emitSignal = true);
|
||||||
|
|
||||||
|
/** add an attribute field (but does not commit it)
|
||||||
|
returns the field index or -1 in case of failure */
|
||||||
|
bool addAttribute(QString name, QString type);
|
||||||
|
|
||||||
|
/** delete an attribute field (but does not commit it) */
|
||||||
|
bool deleteAttribute(int attr);
|
||||||
|
|
||||||
|
/** Insert a copy of the given features into the layer (but does not commit it) */
|
||||||
|
bool addFeatures(QgsFeatureList features, bool makeSelected = TRUE);
|
||||||
|
|
||||||
|
/** delete a feature from the layer (but does not commit it) */
|
||||||
|
bool deleteFeature(int fid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Attempts to commit any changes to disk. Returns the result of the attempt.
|
Attempts to commit any changes to disk. Returns the result of the attempt.
|
||||||
If a commit fails, the in-memory changes are left alone.
|
If a commit fails, the in-memory changes are left alone.
|
||||||
@ -370,20 +377,31 @@ existing rings, 5 no feature found where ring can be inserted*/
|
|||||||
disallowed value in a Postgres database - the user can re-edit and try
|
disallowed value in a Postgres database - the user can re-edit and try
|
||||||
again.
|
again.
|
||||||
|
|
||||||
The commits (in this version) occur in four distinct stages,
|
The commits occur in distinct stages,
|
||||||
(add features, change attributes, change geometries, delete features)
|
(add attributes, add features, change attribute values, change geometries, delete features, delete attributes)
|
||||||
so if a stage fails, it's difficult to roll back cleanly.
|
so if a stage fails, it's difficult to roll back cleanly.
|
||||||
Therefore any error message also includes which stage failed so
|
Therefore any error message also includes which stage failed so
|
||||||
that the user has some chance of repairing the damage cleanly.
|
that the user has some chance of repairing the damage cleanly.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
bool commitChanges();
|
bool commitChanges();
|
||||||
|
const QStringList &commitErrors();
|
||||||
|
|
||||||
/** Stop editing and discard the edits */
|
/** Stop editing and discard the edits */
|
||||||
bool rollBack();
|
bool rollBack();
|
||||||
|
|
||||||
public slots:
|
/**get edit type*/
|
||||||
|
EditType editType(int idx);
|
||||||
|
|
||||||
|
/**set edit type*/
|
||||||
|
void setEditType(int idx, EditType edit);
|
||||||
|
|
||||||
|
/**access value map*/
|
||||||
|
QMap<QString, QVariant> &valueMap(int idx);
|
||||||
|
|
||||||
|
/**access range */
|
||||||
|
RangeData &range(int idx);
|
||||||
|
|
||||||
|
public slots:
|
||||||
/** Select feature by its ID, optionally emit signal selectionChanged() */
|
/** Select feature by its ID, optionally emit signal selectionChanged() */
|
||||||
void select(int featureId, bool emitSignal = TRUE);
|
void select(int featureId, bool emitSignal = TRUE);
|
||||||
|
|
||||||
@ -405,6 +423,15 @@ signals:
|
|||||||
/** This signal is emitted when modifications has been done on layer */
|
/** This signal is emitted when modifications has been done on layer */
|
||||||
void wasModified(bool onlyGeometry);
|
void wasModified(bool onlyGeometry);
|
||||||
|
|
||||||
|
void editingStarted();
|
||||||
|
void editingStopped();
|
||||||
|
void attributeAdded(int idx);
|
||||||
|
void attributeDeleted(int idx);
|
||||||
|
void featureDeleted(int fid);
|
||||||
|
void layerDeleted();
|
||||||
|
|
||||||
|
void attributeValueChanged(int fid, int idx, const QVariant &);
|
||||||
|
|
||||||
private: // Private methods
|
private: // Private methods
|
||||||
|
|
||||||
enum VertexMarkerType
|
enum VertexMarkerType
|
||||||
@ -424,7 +451,7 @@ private: // Private methods
|
|||||||
@todo XXX should this return bool? Throw exceptions?
|
@todo XXX should this return bool? Throw exceptions?
|
||||||
*/
|
*/
|
||||||
bool setDataProvider( QString const & provider );
|
bool setDataProvider( QString const & provider );
|
||||||
|
|
||||||
/** Draws features. May cause projections exceptions to be generated
|
/** Draws features. May cause projections exceptions to be generated
|
||||||
* (i.e., code that calls this function needs to catch them
|
* (i.e., code that calls this function needs to catch them
|
||||||
*/
|
*/
|
||||||
@ -433,7 +460,7 @@ private: // Private methods
|
|||||||
const QgsMapToPixel* cXf,
|
const QgsMapToPixel* cXf,
|
||||||
const QgsCoordinateTransform* ct,
|
const QgsCoordinateTransform* ct,
|
||||||
QImage* marker,
|
QImage* marker,
|
||||||
double widthScale,
|
double widthScale,
|
||||||
double markerScaleFactor,
|
double markerScaleFactor,
|
||||||
bool drawingToEditingCanvas);
|
bool drawingToEditingCanvas);
|
||||||
|
|
||||||
@ -447,19 +474,19 @@ private: // Private methods
|
|||||||
/** Draw the linestring as given in the WKB format. Returns a pointer
|
/** Draw the linestring as given in the WKB format. Returns a pointer
|
||||||
* to the byte after the end of the line string binary data stream (WKB).
|
* to the byte after the end of the line string binary data stream (WKB).
|
||||||
*/
|
*/
|
||||||
unsigned char* drawLineString(unsigned char* WKBlinestring,
|
unsigned char *drawLineString(unsigned char *WKBlinestring,
|
||||||
QPainter* p,
|
QPainter *p,
|
||||||
const QgsMapToPixel* mtp,
|
const QgsMapToPixel *mtp,
|
||||||
const QgsCoordinateTransform* ct,
|
const QgsCoordinateTransform *ct,
|
||||||
bool drawingToEditingCanvas);
|
bool drawingToEditingCanvas);
|
||||||
|
|
||||||
/** Draw the polygon as given in the WKB format. Returns a pointer to
|
/** Draw the polygon as given in the WKB format. Returns a pointer to
|
||||||
* the byte after the end of the polygon binary data stream (WKB).
|
* the byte after the end of the polygon binary data stream (WKB).
|
||||||
*/
|
*/
|
||||||
unsigned char* drawPolygon(unsigned char* WKBpolygon,
|
unsigned char *drawPolygon(unsigned char *WKBpolygon,
|
||||||
QPainter* p,
|
QPainter *p,
|
||||||
const QgsMapToPixel* mtp,
|
const QgsMapToPixel *mtp,
|
||||||
const QgsCoordinateTransform* ct,
|
const QgsCoordinateTransform *ct,
|
||||||
bool drawingToEditingCanvas);
|
bool drawingToEditingCanvas);
|
||||||
|
|
||||||
/** Goes through all features and finds a free id (e.g. to give it temporarily to a not-commited feature) */
|
/** Goes through all features and finds a free id (e.g. to give it temporarily to a not-commited feature) */
|
||||||
@ -478,7 +505,7 @@ private: // Private methods
|
|||||||
@param snappingResult list to which the result is appended
|
@param snappingResult list to which the result is appended
|
||||||
@param snap_to snap to vertex or to segment
|
@param snap_to snap to vertex or to segment
|
||||||
*/
|
*/
|
||||||
void snapToGeometry(const QgsPoint& startPoint, int featureId, QgsGeometry* geom, double sqrSnappingTolerance, \
|
void snapToGeometry(const QgsPoint& startPoint, int featureId, QgsGeometry* geom, double sqrSnappingTolerance,
|
||||||
QMultiMap<double, QgsSnappingResult>& snappingResults, QgsSnapper::SNAP_TO snap_to) const;
|
QMultiMap<double, QgsSnappingResult>& snappingResults, QgsSnapper::SNAP_TO snap_to) const;
|
||||||
|
|
||||||
/**Little helper function that gives bounding box from a list of points.
|
/**Little helper function that gives bounding box from a list of points.
|
||||||
@ -488,6 +515,11 @@ private: // Private methods
|
|||||||
/**Reads vertex marker type from settings*/
|
/**Reads vertex marker type from settings*/
|
||||||
QgsVectorLayer::VertexMarkerType currentVertexMarkerType();
|
QgsVectorLayer::VertexMarkerType currentVertexMarkerType();
|
||||||
|
|
||||||
|
/**Update feature with uncommited attribute updates*/
|
||||||
|
void updateFeatureAttributes(QgsFeature &f);
|
||||||
|
|
||||||
|
/**Update feature with uncommited geometry updates*/
|
||||||
|
void updateFeatureGeometry(QgsFeature &f);
|
||||||
|
|
||||||
private: // Private attributes
|
private: // Private attributes
|
||||||
|
|
||||||
@ -513,36 +545,48 @@ private: // Private attributes
|
|||||||
|
|
||||||
/** Flag indicating whether the layer has been modified since the last commit */
|
/** Flag indicating whether the layer has been modified since the last commit */
|
||||||
bool mModified;
|
bool mModified;
|
||||||
|
|
||||||
/** cache of the committed geometries retrieved *for the current display* */
|
/** cache of the committed geometries retrieved *for the current display* */
|
||||||
QgsGeometryMap mCachedGeometries;
|
QgsGeometryMap mCachedGeometries;
|
||||||
|
|
||||||
/** Set holding the feature IDs that are activated. Note that if a feature
|
/** Set holding the feature IDs that are activated. Note that if a feature
|
||||||
subsequently gets deleted (i.e. by its addition to mDeletedFeatureIds),
|
subsequently gets deleted (i.e. by its addition to mDeletedFeatureIds),
|
||||||
it always needs to be removed from mSelectedFeatureIds as well.
|
it always needs to be removed from mSelectedFeatureIds as well.
|
||||||
*/
|
*/
|
||||||
QgsFeatureIds mSelectedFeatureIds;
|
QgsFeatureIds mSelectedFeatureIds;
|
||||||
|
|
||||||
/** Deleted feature IDs which are not commited. Note a feature can be added and then deleted
|
/** Deleted feature IDs which are not commited. Note a feature can be added and then deleted
|
||||||
again before the change is committed - in that case the added feature would be removed
|
again before the change is committed - in that case the added feature would be removed
|
||||||
from mAddedFeatures only and *not* entered here.
|
from mAddedFeatures only and *not* entered here.
|
||||||
*/
|
*/
|
||||||
QgsFeatureIds mDeletedFeatureIds;
|
QgsFeatureIds mDeletedFeatureIds;
|
||||||
|
|
||||||
/** New features which are not commited. Note a feature can be added and then changed,
|
/** New features which are not commited. Note a feature can be added and then changed,
|
||||||
therefore the details here can be overridden by mChangedAttributes and mChangedGeometries.
|
therefore the details here can be overridden by mChangedAttributeValues and mChangedGeometries.
|
||||||
*/
|
*/
|
||||||
QgsFeatureList mAddedFeatures;
|
QgsFeatureList mAddedFeatures;
|
||||||
|
|
||||||
/** Changed attributes which are not commited */
|
/** Changed attributes values which are not commited */
|
||||||
QgsChangedAttributesMap mChangedAttributes;
|
QgsChangedAttributesMap mChangedAttributeValues;
|
||||||
|
|
||||||
|
/** deleted attributes fields which are not commited */
|
||||||
|
QgsAttributeIds mDeletedAttributeIds;
|
||||||
|
|
||||||
|
/** added attributes fields which are not commited */
|
||||||
|
QgsAttributeIds mAddedAttributeIds;
|
||||||
|
|
||||||
/** Changed geometries which are not commited. */
|
/** Changed geometries which are not commited. */
|
||||||
QgsGeometryMap mChangedGeometries;
|
QgsGeometryMap mChangedGeometries;
|
||||||
|
|
||||||
|
/** field map to commit */
|
||||||
|
QgsFieldMap mUpdatedFields;
|
||||||
|
|
||||||
|
/** max field index */
|
||||||
|
int mMaxUpdatedIndex;
|
||||||
|
|
||||||
/** Geometry type as defined in enum WKBTYPE (qgis.h) */
|
/** Geometry type as defined in enum WKBTYPE (qgis.h) */
|
||||||
int mGeometryType;
|
int mGeometryType;
|
||||||
|
|
||||||
/** Renderer object which holds the information about how to display the features */
|
/** Renderer object which holds the information about how to display the features */
|
||||||
QgsRenderer *mRenderer;
|
QgsRenderer *mRenderer;
|
||||||
|
|
||||||
@ -552,6 +596,20 @@ private: // Private attributes
|
|||||||
/** Display labels */
|
/** Display labels */
|
||||||
bool mLabelOn;
|
bool mLabelOn;
|
||||||
|
|
||||||
|
QStringList mCommitErrors;
|
||||||
|
|
||||||
|
QMap< QString, EditType > mEditTypes;
|
||||||
|
QMap< QString, QMap<QString, QVariant> > mValueMaps;
|
||||||
|
QMap< QString, RangeData > mRanges;
|
||||||
|
|
||||||
|
bool mFetching;
|
||||||
|
QgsRect mFetchRect;
|
||||||
|
QgsAttributeList mFetchAttributes;
|
||||||
|
bool mFetchGeometry;
|
||||||
|
|
||||||
|
QSet<int> mFetchConsidered;
|
||||||
|
QgsGeometryMap::iterator mFetchChangedGeomIt;
|
||||||
|
QgsFeatureList::iterator mFetchAddedFeaturesIt;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -156,7 +156,7 @@ void QgsGraduatedSymbolRenderer::renderFeature(QPainter * p, QgsFeature & f, QIm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbol* QgsGraduatedSymbolRenderer::symbolForFeature(const QgsFeature* f)
|
QgsSymbol *QgsGraduatedSymbolRenderer::symbolForFeature(const QgsFeature* f)
|
||||||
{
|
{
|
||||||
//first find out the value for the classification attribute
|
//first find out the value for the classification attribute
|
||||||
const QgsAttributeMap& attrs = f->attributeMap();
|
const QgsAttributeMap& attrs = f->attributeMap();
|
||||||
|
@ -40,7 +40,7 @@ class CORE_EXPORT QgsGraduatedSymbolRenderer: public QgsRenderer
|
|||||||
void removeSymbols();
|
void removeSymbols();
|
||||||
/** Determines if a feature will be rendered or not
|
/** Determines if a feature will be rendered or not
|
||||||
@param f a pointer to the feature to determine if rendering will happen*/
|
@param f a pointer to the feature to determine if rendering will happen*/
|
||||||
bool willRenderFeature(QgsFeature *f);
|
virtual bool willRenderFeature(QgsFeature *f);
|
||||||
/**Renders an OGRFeature
|
/**Renders an OGRFeature
|
||||||
\param p a painter (usually the one from the current map canvas)
|
\param p a painter (usually the one from the current map canvas)
|
||||||
\param f a pointer to a feature to render
|
\param f a pointer to a feature to render
|
||||||
@ -72,7 +72,7 @@ class CORE_EXPORT QgsGraduatedSymbolRenderer: public QgsRenderer
|
|||||||
int mClassificationField;
|
int mClassificationField;
|
||||||
/**List holding the symbols for the individual classes*/
|
/**List holding the symbols for the individual classes*/
|
||||||
QList<QgsSymbol*> mSymbols;
|
QList<QgsSymbol*> mSymbols;
|
||||||
QgsSymbol* symbolForFeature(const QgsFeature* f);
|
QgsSymbol *symbolForFeature(const QgsFeature* f);
|
||||||
/**Cached copy of all underlying symbols required attribute fields*/
|
/**Cached copy of all underlying symbols required attribute fields*/
|
||||||
QgsAttributeList mSymbolAttributes;
|
QgsAttributeList mSymbolAttributes;
|
||||||
|
|
||||||
|
@ -103,13 +103,13 @@ void QgsSingleSymbolRenderer::renderFeature(QPainter * p, QgsFeature & f, QImage
|
|||||||
//first find out the value for the scale classification attribute
|
//first find out the value for the scale classification attribute
|
||||||
const QgsAttributeMap& attrs = f.attributeMap();
|
const QgsAttributeMap& attrs = f.attributeMap();
|
||||||
fieldScale = sqrt(fabs(attrs[mSymbol->scaleClassificationField()].toDouble()));
|
fieldScale = sqrt(fabs(attrs[mSymbol->scaleClassificationField()].toDouble()));
|
||||||
QgsDebugMsg(QString("Feature has field scale factor %1").arg(fieldScale));
|
QgsDebugMsgLevel(QString("Feature has field scale factor %1").arg(fieldScale), 3);
|
||||||
}
|
}
|
||||||
if ( mSymbol->rotationClassificationField() >= 0 )
|
if ( mSymbol->rotationClassificationField() >= 0 )
|
||||||
{
|
{
|
||||||
const QgsAttributeMap& attrs = f.attributeMap();
|
const QgsAttributeMap& attrs = f.attributeMap();
|
||||||
rotation = attrs[mSymbol->rotationClassificationField()].toDouble();
|
rotation = attrs[mSymbol->rotationClassificationField()].toDouble();
|
||||||
QgsDebugMsg(QString("Feature has rotation factor %1").arg(rotation));
|
QgsDebugMsgLevel(QString("Feature has rotation factor %1").arg(rotation), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
*img = mSymbol->getPointSymbolAsImage( widthScale, selected, mSelectionColor, fieldScale, rotation, rasterScaleFactor);
|
*img = mSymbol->getPointSymbolAsImage( widthScale, selected, mSelectionColor, fieldScale, rotation, rasterScaleFactor);
|
||||||
|
@ -34,7 +34,7 @@ class CORE_EXPORT QgsSingleSymbolRenderer: public QgsRenderer
|
|||||||
void addSymbol(QgsSymbol* sy);
|
void addSymbol(QgsSymbol* sy);
|
||||||
/*Returns a pointer to mSymbol*/
|
/*Returns a pointer to mSymbol*/
|
||||||
const QgsSymbol* symbol() const;
|
const QgsSymbol* symbol() const;
|
||||||
/**Renders an OGRFeature*/
|
/**Renders a feature*/
|
||||||
void renderFeature(QPainter* p, QgsFeature& f, QImage* img, bool selected, double widthScale = 1.0, double rasterScaleFactor = 1.0);
|
void renderFeature(QPainter* p, QgsFeature& f, QImage* img, bool selected, double widthScale = 1.0, double rasterScaleFactor = 1.0);
|
||||||
/**Reads the renderer configuration from an XML file
|
/**Reads the renderer configuration from an XML file
|
||||||
@param rnode the DOM node to read
|
@param rnode the DOM node to read
|
||||||
|
@ -165,7 +165,7 @@ void QgsUniqueValueRenderer::renderFeature(QPainter* p, QgsFeature& f,QImage* im
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsSymbol* QgsUniqueValueRenderer::symbolForFeature(const QgsFeature* f)
|
QgsSymbol *QgsUniqueValueRenderer::symbolForFeature(const QgsFeature *f)
|
||||||
{
|
{
|
||||||
//first find out the value
|
//first find out the value
|
||||||
const QgsAttributeMap& attrs = f->attributeMap();
|
const QgsAttributeMap& attrs = f->attributeMap();
|
||||||
|
@ -30,7 +30,7 @@ class CORE_EXPORT QgsUniqueValueRenderer: public QgsRenderer
|
|||||||
virtual ~QgsUniqueValueRenderer();
|
virtual ~QgsUniqueValueRenderer();
|
||||||
/** Determines if a feature will be rendered or not
|
/** Determines if a feature will be rendered or not
|
||||||
@param f a pointer to the feature to determine if rendering will happen*/
|
@param f a pointer to the feature to determine if rendering will happen*/
|
||||||
bool willRenderFeature(QgsFeature *f);
|
virtual bool willRenderFeature(QgsFeature *f);
|
||||||
void renderFeature(QPainter* p, QgsFeature& f,QImage* img, bool selected, double widthScale = 1.0, double rasterScaleFactor = 1.0);
|
void renderFeature(QPainter* p, QgsFeature& f,QImage* img, bool selected, double widthScale = 1.0, double rasterScaleFactor = 1.0);
|
||||||
/**Reads the renderer configuration from an XML file
|
/**Reads the renderer configuration from an XML file
|
||||||
@param rnode the DOM node to read
|
@param rnode the DOM node to read
|
||||||
@ -64,7 +64,7 @@ class CORE_EXPORT QgsUniqueValueRenderer: public QgsRenderer
|
|||||||
/**Symbols for the unique values*/
|
/**Symbols for the unique values*/
|
||||||
QMap<QString, QgsSymbol*> mSymbols;
|
QMap<QString, QgsSymbol*> mSymbols;
|
||||||
/**Returns the symbol for a feature or 0 if there isn't any*/
|
/**Returns the symbol for a feature or 0 if there isn't any*/
|
||||||
QgsSymbol* symbolForFeature(const QgsFeature* f);
|
QgsSymbol *symbolForFeature(const QgsFeature* f);
|
||||||
/**Cached copy of all underlying symbols required attribute fields*/
|
/**Cached copy of all underlying symbols required attribute fields*/
|
||||||
QgsAttributeList mSymbolAttributes;
|
QgsAttributeList mSymbolAttributes;
|
||||||
bool mSymbolAttributesDirty; // insertValue was called
|
bool mSymbolAttributesDirty; // insertValue was called
|
||||||
|
@ -324,7 +324,7 @@ QImage QgsSymbol::getCachedPointSymbolAsImage( double widthScale,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage QgsSymbol::getPointSymbolAsImage( double widthScale, bool selected, QColor selectionColor, double scale, \
|
QImage QgsSymbol::getPointSymbolAsImage( double widthScale, bool selected, QColor selectionColor, double scale,
|
||||||
double rotation, double rasterScaleFactor)
|
double rotation, double rasterScaleFactor)
|
||||||
{
|
{
|
||||||
//QgsDebugMsg(QString("Symbol scale = %1, and rotation = %2").arg(scale).arg(rotation));
|
//QgsDebugMsg(QString("Symbol scale = %1, and rotation = %2").arg(scale).arg(rotation));
|
||||||
|
@ -44,6 +44,8 @@ class QValidator;
|
|||||||
|
|
||||||
// Must be here, so that it is included to moc file
|
// Must be here, so that it is included to moc file
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
|
#include "qgsfield.h"
|
||||||
|
|
||||||
class QgisInterface;
|
class QgisInterface;
|
||||||
class QgsMapCanvas;
|
class QgsMapCanvas;
|
||||||
|
|
||||||
@ -490,9 +492,9 @@ public:
|
|||||||
* \param qdesc option element in QGIS module description XML file
|
* \param qdesc option element in QGIS module description XML file
|
||||||
* \param gdesc GRASS module XML description file
|
* \param gdesc GRASS module XML description file
|
||||||
*/
|
*/
|
||||||
QgsGrassModuleInput ( QgsGrassModule *module,
|
QgsGrassModuleInput ( QgsGrassModule *module,
|
||||||
QgsGrassModuleStandardOptions *options, QString key,
|
QgsGrassModuleStandardOptions *options, QString key,
|
||||||
QDomElement &qdesc, QDomElement &gdesc, QDomNode &gnode,
|
QDomElement &qdesc, QDomElement &gdesc, QDomNode &gnode,
|
||||||
QWidget * parent = 0 );
|
QWidget * parent = 0 );
|
||||||
|
|
||||||
//! Destructor
|
//! Destructor
|
||||||
|
@ -37,7 +37,7 @@ class GPSData;
|
|||||||
*/
|
*/
|
||||||
class QgsGPXProvider : public QgsVectorDataProvider
|
class QgsGPXProvider : public QgsVectorDataProvider
|
||||||
{
|
{
|
||||||
Q_OBJECT;
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -36,16 +36,6 @@ email : sherman at mrcc.com
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTextCodec>
|
#include <QTextCodec>
|
||||||
|
|
||||||
//TODO Following ifndef can be removed once WIN32 GEOS support
|
|
||||||
// is fixed
|
|
||||||
#ifndef NOWIN32GEOSXXX
|
|
||||||
//XXX GEOS support on windows is broken until we can get VC++ to
|
|
||||||
// tolerate geos.h without throwing a bunch of type errors. It
|
|
||||||
// appears that the windows version of GEOS may be compiled with
|
|
||||||
// MINGW rather than VC++.
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include "qgsapplication.h"
|
#include "qgsapplication.h"
|
||||||
#include "qgsdataprovider.h"
|
#include "qgsdataprovider.h"
|
||||||
#include "qgsfeature.h"
|
#include "qgsfeature.h"
|
||||||
@ -134,13 +124,9 @@ QgsOgrProvider::QgsOgrProvider(QString const & uri)
|
|||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the geos objects
|
mSupportedNativeTypes.insert("Integer", QVariant::Int);
|
||||||
geometryFactory = new GEOS_GEOM::GeometryFactory();
|
mSupportedNativeTypes.insert("Real", QVariant::Double);
|
||||||
assert(geometryFactory!=0);
|
mSupportedNativeTypes.insert("String", QVariant::String);
|
||||||
|
|
||||||
mSupportedNativeTypes.insert("Integer");
|
|
||||||
mSupportedNativeTypes.insert("Real");
|
|
||||||
mSupportedNativeTypes.insert("String");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QgsOgrProvider::~QgsOgrProvider()
|
QgsOgrProvider::~QgsOgrProvider()
|
||||||
@ -149,7 +135,6 @@ QgsOgrProvider::~QgsOgrProvider()
|
|||||||
ogrDataSource = 0;
|
ogrDataSource = 0;
|
||||||
free(extent_);
|
free(extent_);
|
||||||
extent_ = 0;
|
extent_ = 0;
|
||||||
delete geometryFactory;
|
|
||||||
if( mSelectionRectangle )
|
if( mSelectionRectangle )
|
||||||
{
|
{
|
||||||
OGR_G_DestroyGeometry( mSelectionRectangle );
|
OGR_G_DestroyGeometry( mSelectionRectangle );
|
||||||
|
@ -19,23 +19,10 @@ email : sherman at mrcc.com
|
|||||||
#include "qgsrect.h"
|
#include "qgsrect.h"
|
||||||
#include "qgsvectordataprovider.h"
|
#include "qgsvectordataprovider.h"
|
||||||
|
|
||||||
#include <geos/version.h>
|
|
||||||
#if GEOS_VERSION_MAJOR < 3
|
|
||||||
#include <geos/geom.h>
|
|
||||||
#define GEOS_GEOM geos
|
|
||||||
#else
|
|
||||||
#include <geos/geom/GeometryFactory.h>
|
|
||||||
#define GEOS_GEOM geos::geom
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class QgsFeature;
|
class QgsFeature;
|
||||||
class QgsField;
|
class QgsField;
|
||||||
|
|
||||||
typedef void *OGRDataSourceH;
|
#include <ogr_api.h>
|
||||||
typedef void *OGRSFDriverH;
|
|
||||||
typedef void *OGRLayerH;
|
|
||||||
typedef void *OGRFeatureH;
|
|
||||||
typedef void *OGRGeometryH;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\class QgsOgrProvider
|
\class QgsOgrProvider
|
||||||
@ -264,6 +251,4 @@ class QgsOgrProvider : public QgsVectorDataProvider
|
|||||||
bool addFeature(QgsFeature& f);
|
bool addFeature(QgsFeature& f);
|
||||||
/**Deletes one feature*/
|
/**Deletes one feature*/
|
||||||
bool deleteFeature(int id);
|
bool deleteFeature(int id);
|
||||||
//! The geometry factory
|
|
||||||
GEOS_GEOM::GeometryFactory *geometryFactory;
|
|
||||||
};
|
};
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
const QString POSTGRES_KEY = "postgres";
|
const QString POSTGRES_KEY = "postgres";
|
||||||
const QString POSTGRES_DESCRIPTION = "PostgreSQL/PostGIS data provider";
|
const QString POSTGRES_DESCRIPTION = "PostgreSQL/PostGIS data provider";
|
||||||
|
|
||||||
QMap<QString, QgsPostgresProvider::Conn *> QgsPostgresProvider::connections;
|
QMap<QString, QgsPostgresProvider::Conn *> QgsPostgresProvider::connectionsRO;
|
||||||
|
QMap<QString, QgsPostgresProvider::Conn *> QgsPostgresProvider::connectionsRW;
|
||||||
int QgsPostgresProvider::providerIds=0;
|
int QgsPostgresProvider::providerIds=0;
|
||||||
|
|
||||||
QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
||||||
@ -86,12 +87,9 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
QgsDebugMsg("Schema is: " + mSchemaName);
|
QgsDebugMsg("Schema is: " + mSchemaName);
|
||||||
QgsDebugMsg("Table name is: " + mTableName);
|
QgsDebugMsg("Table name is: " + mTableName);
|
||||||
|
|
||||||
//QString logFile = "./pg_provider_" + mTableName + ".log";
|
connectionRW = NULL;
|
||||||
//pLog.open((const char *)logFile);
|
connectionRO = connectDb( mUri.connInfo() );
|
||||||
//QgsDebugMsg("Opened log file for " + mTableName);
|
if( connectionRO==NULL ) {
|
||||||
|
|
||||||
connection = connectDb( mUri.connInfo() );
|
|
||||||
if( connection==NULL ) {
|
|
||||||
valid = false;
|
valid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -100,7 +98,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
the problems they will see :) */
|
the problems they will see :) */
|
||||||
QgsDebugMsg("Checking for GEOS support");
|
QgsDebugMsg("Checking for GEOS support");
|
||||||
|
|
||||||
if(!hasGEOS(connection))
|
if(!hasGEOS(connectionRO))
|
||||||
{
|
{
|
||||||
showMessageBox(tr("No GEOS Support!"),
|
showMessageBox(tr("No GEOS Support!"),
|
||||||
tr("Your PostGIS installation has no GEOS support.\n"
|
tr("Your PostGIS installation has no GEOS support.\n"
|
||||||
@ -114,7 +112,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
// Check that we can read from the table (i.e., we have
|
// Check that we can read from the table (i.e., we have
|
||||||
// select permission).
|
// select permission).
|
||||||
QString sql = QString("select * from %1 limit 1").arg(mSchemaTableName);
|
QString sql = QString("select * from %1 limit 1").arg(mSchemaTableName);
|
||||||
PGresult* testAccess = PQexec(connection, sql.toUtf8());
|
PGresult* testAccess = PQexec(connectionRO, sql.toUtf8());
|
||||||
if (PQresultStatus(testAccess) != PGRES_TUPLES_OK)
|
if (PQresultStatus(testAccess) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
showMessageBox(tr("Unable to access relation"),
|
showMessageBox(tr("Unable to access relation"),
|
||||||
@ -136,7 +134,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
"current_schema()")
|
"current_schema()")
|
||||||
.arg( quotedValue(mSchemaTableName) );
|
.arg( quotedValue(mSchemaTableName) );
|
||||||
|
|
||||||
testAccess = PQexec( connection, sql.toUtf8() );
|
testAccess = PQexec( connectionRO, sql.toUtf8() );
|
||||||
if( PQresultStatus(testAccess) != PGRES_TUPLES_OK ) {
|
if( PQresultStatus(testAccess) != PGRES_TUPLES_OK ) {
|
||||||
showMessageBox(tr("Unable to access relation"),
|
showMessageBox(tr("Unable to access relation"),
|
||||||
tr("Unable to determine table access privileges for the ") + mSchemaTableName +
|
tr("Unable to determine table access privileges for the ") + mSchemaTableName +
|
||||||
@ -181,7 +179,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
"relname=%1 AND nspname=%2")
|
"relname=%1 AND nspname=%2")
|
||||||
.arg( quotedValue(mTableName) )
|
.arg( quotedValue(mTableName) )
|
||||||
.arg( quotedValue(mSchemaName) );
|
.arg( quotedValue(mSchemaName) );
|
||||||
testAccess = PQexec(connection, sql.toUtf8());
|
testAccess = PQexec(connectionRO, sql.toUtf8());
|
||||||
if (PQresultStatus(testAccess) == PGRES_TUPLES_OK && PQntuples(testAccess)==1)
|
if (PQresultStatus(testAccess) == PGRES_TUPLES_OK && PQntuples(testAccess)==1)
|
||||||
{
|
{
|
||||||
enabledCapabilities |= QgsVectorDataProvider::AddAttributes | QgsVectorDataProvider::DeleteAttributes;
|
enabledCapabilities |= QgsVectorDataProvider::AddAttributes | QgsVectorDataProvider::DeleteAttributes;
|
||||||
@ -212,7 +210,7 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
// Set the postgresql message level so that we don't get the
|
// Set the postgresql message level so that we don't get the
|
||||||
// 'there is no transaction in progress' warning.
|
// 'there is no transaction in progress' warning.
|
||||||
#ifndef QGISDEBUG
|
#ifndef QGISDEBUG
|
||||||
PQexecNR(connection, QString("set client_min_messages to error").toUtf8());
|
PQexecNR(connectionRO, QString("set client_min_messages to error").toUtf8());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Kick off the long running threads
|
// Kick off the long running threads
|
||||||
@ -240,11 +238,11 @@ QgsPostgresProvider::QgsPostgresProvider(QString const & uri)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//fill type names into sets
|
//fill type names into sets
|
||||||
mSupportedNativeTypes.insert("double precision");
|
mSupportedNativeTypes.insert("double precision", QVariant::Double);
|
||||||
mSupportedNativeTypes.insert("int4");
|
mSupportedNativeTypes.insert("int4", QVariant::Int);
|
||||||
mSupportedNativeTypes.insert("int8");
|
mSupportedNativeTypes.insert("int8", QVariant::LongLong);
|
||||||
mSupportedNativeTypes.insert("text");
|
mSupportedNativeTypes.insert("text", QVariant::String);
|
||||||
mSupportedNativeTypes.insert("varchar(30)");
|
mSupportedNativeTypes.insert("varchar(30)", QVariant::String);
|
||||||
|
|
||||||
if (primaryKey.isEmpty())
|
if (primaryKey.isEmpty())
|
||||||
{
|
{
|
||||||
@ -284,8 +282,10 @@ QgsPostgresProvider::~QgsPostgresProvider()
|
|||||||
//pLog.flush();
|
//pLog.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
PGconn *QgsPostgresProvider::connectDb(const QString & conninfo)
|
PGconn *QgsPostgresProvider::connectDb(const QString & conninfo, bool readonly)
|
||||||
{
|
{
|
||||||
|
QMap<QString, QgsPostgresProvider::Conn *> &connections = readonly ? connectionsRO : connectionsRW;
|
||||||
|
|
||||||
if( connections.contains(conninfo) )
|
if( connections.contains(conninfo) )
|
||||||
{
|
{
|
||||||
QgsDebugMsg( QString("Using cached connection for %1").arg(conninfo) );
|
QgsDebugMsg( QString("Using cached connection for %1").arg(conninfo) );
|
||||||
@ -333,24 +333,42 @@ void QgsPostgresProvider::disconnectDb()
|
|||||||
{
|
{
|
||||||
if(mFetching)
|
if(mFetching)
|
||||||
{
|
{
|
||||||
PQexecNR(connection, QString("CLOSE qgisf%1").arg(providerId).toUtf8() );
|
PQexecNR(connectionRO, QString("CLOSE qgisf%1").arg(providerId).toUtf8() );
|
||||||
mFetching=false;
|
mFetching=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMap<QString, Conn *>::iterator i;
|
if(!connectionRO) {
|
||||||
for(i=connections.begin(); i!=connections.end() && i.value()->conn!=connection; i++)
|
QMap<QString, Conn *>::iterator i;
|
||||||
;
|
for(i=connectionsRO.begin(); i!=connectionsRO.end() && i.value()->conn!=connectionRO; i++)
|
||||||
|
;
|
||||||
|
|
||||||
assert( i.value()->conn==connection );
|
assert( i.value()->conn==connectionRO );
|
||||||
assert( i.value()->ref>0 );
|
assert( i.value()->ref>0 );
|
||||||
|
|
||||||
if( --i.value()->ref==0 ) {
|
if( --i.value()->ref==0 ) {
|
||||||
PQfinish( connection );
|
PQfinish( connectionRO );
|
||||||
delete i.value();
|
delete i.value();
|
||||||
connections.remove( i.key() );
|
connectionsRO.remove( i.key() );
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionRO = 0;
|
||||||
|
|
||||||
|
if(connectionRW) {
|
||||||
|
for(i=connectionsRW.begin(); i!=connectionsRW.end() && i.value()->conn!=connectionRW; i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
assert( i.value()->conn==connectionRW );
|
||||||
|
assert( i.value()->ref>0 );
|
||||||
|
|
||||||
|
if( --i.value()->ref==0 ) {
|
||||||
|
PQfinish( connectionRW );
|
||||||
|
delete i.value();
|
||||||
|
connectionsRW.remove( i.key() );
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionRW = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connection = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsPostgresProvider::storageType() const
|
QString QgsPostgresProvider::storageType() const
|
||||||
@ -409,7 +427,7 @@ bool QgsPostgresProvider::declareCursor(const QString &cursorName,
|
|||||||
|
|
||||||
QgsDebugMsg("Binary cursor: " + declare);
|
QgsDebugMsg("Binary cursor: " + declare);
|
||||||
|
|
||||||
return PQexecNR(connection, declare.toUtf8());
|
return PQexecNR(connectionRO, declare.toUtf8());
|
||||||
}
|
}
|
||||||
catch(PGFieldNotFound)
|
catch(PGFieldNotFound)
|
||||||
{
|
{
|
||||||
@ -515,7 +533,7 @@ void QgsPostgresProvider::select(QgsAttributeList fetchAttributes, QgsRect rect,
|
|||||||
|
|
||||||
if(mFetching)
|
if(mFetching)
|
||||||
{
|
{
|
||||||
PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8() );
|
PQexecNR(connectionRO, QString("CLOSE %1").arg(cursorName).toUtf8() );
|
||||||
mFetching=false;
|
mFetching=false;
|
||||||
|
|
||||||
while(!mFeatureQueue.empty())
|
while(!mFeatureQueue.empty())
|
||||||
@ -575,13 +593,13 @@ bool QgsPostgresProvider::getNextFeature(QgsFeature& feature)
|
|||||||
if( mFeatureQueue.empty() )
|
if( mFeatureQueue.empty() )
|
||||||
{
|
{
|
||||||
QString fetch = QString("fetch forward %1 from %2").arg(mFeatureQueueSize).arg(cursorName);
|
QString fetch = QString("fetch forward %1 from %2").arg(mFeatureQueueSize).arg(cursorName);
|
||||||
if(PQsendQuery(connection, fetch.toUtf8()) == 0) //fetch features in asynchronously
|
if(PQsendQuery(connectionRO, fetch.toUtf8()) == 0) //fetch features in asynchronously
|
||||||
{
|
{
|
||||||
qWarning("PQsendQuery failed (1)");
|
qWarning("PQsendQuery failed (1)");
|
||||||
}
|
}
|
||||||
|
|
||||||
PGresult *queryResult;
|
PGresult *queryResult;
|
||||||
while( (queryResult = PQgetResult(connection)) )
|
while( (queryResult = PQgetResult(connectionRO)) )
|
||||||
{
|
{
|
||||||
int rows = PQntuples(queryResult);
|
int rows = PQntuples(queryResult);
|
||||||
if (rows == 0)
|
if (rows == 0)
|
||||||
@ -627,7 +645,7 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId, QgsFeature& feature, boo
|
|||||||
if( !declareCursor( cursorName, fetchAttributes, fetchGeometry, QString("%2=%3").arg(quotedIdentifier(primaryKey)).arg(featureId) ) )
|
if( !declareCursor( cursorName, fetchAttributes, fetchGeometry, QString("%2=%3").arg(quotedIdentifier(primaryKey)).arg(featureId) ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PGresult *queryResult = PQexec(connection, QString("fetch forward 1 from %1").arg(cursorName).toUtf8());
|
PGresult *queryResult = PQexec(connectionRO, QString("fetch forward 1 from %1").arg(cursorName).toUtf8());
|
||||||
if(queryResult==0)
|
if(queryResult==0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -636,7 +654,7 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId, QgsFeature& feature, boo
|
|||||||
{
|
{
|
||||||
QgsDebugMsg("feature " + QString::number(featureId) + " not found");
|
QgsDebugMsg("feature " + QString::number(featureId) + " not found");
|
||||||
PQclear(queryResult);
|
PQclear(queryResult);
|
||||||
PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8());
|
PQexecNR(connectionRO, QString("CLOSE %1").arg(cursorName).toUtf8());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if(rows != 1)
|
else if(rows != 1)
|
||||||
@ -648,7 +666,7 @@ bool QgsPostgresProvider::getFeatureAtId(int featureId, QgsFeature& feature, boo
|
|||||||
|
|
||||||
PQclear(queryResult);
|
PQclear(queryResult);
|
||||||
|
|
||||||
PQexecNR(connection, QString("CLOSE %1").arg(cursorName).toUtf8());
|
PQexecNR(connectionRO, QString("CLOSE %1").arg(cursorName).toUtf8());
|
||||||
|
|
||||||
return gotit;
|
return gotit;
|
||||||
}
|
}
|
||||||
@ -724,7 +742,7 @@ void QgsPostgresProvider::reset()
|
|||||||
if(mFetching)
|
if(mFetching)
|
||||||
{
|
{
|
||||||
//move cursor to first record
|
//move cursor to first record
|
||||||
PQexecNR(connection, QString("move 0 in qgisf%1").arg(providerId).toUtf8());
|
PQexecNR(connectionRO, QString("move 0 in qgisf%1").arg(providerId).toUtf8());
|
||||||
}
|
}
|
||||||
mFeatureQueue.empty();
|
mFeatureQueue.empty();
|
||||||
loadFields();
|
loadFields();
|
||||||
@ -752,13 +770,13 @@ void QgsPostgresProvider::loadFields()
|
|||||||
|
|
||||||
// Get the relation oid for use in later queries
|
// Get the relation oid for use in later queries
|
||||||
QString sql = QString("SELECT regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
QString sql = QString("SELECT regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
||||||
PGresult *tresult= PQexec(connection, sql.toUtf8());
|
PGresult *tresult= PQexec(connectionRO, sql.toUtf8());
|
||||||
QString tableoid = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
QString tableoid = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
||||||
PQclear(tresult);
|
PQclear(tresult);
|
||||||
|
|
||||||
// Get the table description
|
// Get the table description
|
||||||
sql = QString("SELECT description FROM pg_description WHERE objoid=%1 AND objsubid=0").arg( tableoid );
|
sql = QString("SELECT description FROM pg_description WHERE objoid=%1 AND objsubid=0").arg( tableoid );
|
||||||
tresult = PQexec(connection, sql.toUtf8());
|
tresult = PQexec(connectionRO, sql.toUtf8());
|
||||||
if (PQntuples(tresult) > 0)
|
if (PQntuples(tresult) > 0)
|
||||||
mDataComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
mDataComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
||||||
PQclear(tresult);
|
PQclear(tresult);
|
||||||
@ -767,7 +785,7 @@ void QgsPostgresProvider::loadFields()
|
|||||||
// field name, type, length, and precision (if numeric)
|
// field name, type, length, and precision (if numeric)
|
||||||
sql = QString("select * from %1 limit 0").arg ( mSchemaTableName );
|
sql = QString("select * from %1 limit 0").arg ( mSchemaTableName );
|
||||||
|
|
||||||
PGresult *result = PQexec(connection, sql.toUtf8());
|
PGresult *result = PQexec(connectionRO, sql.toUtf8());
|
||||||
//--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
|
//--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
|
||||||
|
|
||||||
// The queries inside this loop could possibly be combined into one
|
// The queries inside this loop could possibly be combined into one
|
||||||
@ -787,7 +805,7 @@ void QgsPostgresProvider::loadFields()
|
|||||||
// "oid = (SELECT Distinct typelem FROM pg_type WHERE " //needs DISTINCT to guard against 2 or more rows on int2
|
// "oid = (SELECT Distinct typelem FROM pg_type WHERE " //needs DISTINCT to guard against 2 or more rows on int2
|
||||||
// "typelem = " + typOid + " AND typlen = -1)";
|
// "typelem = " + typOid + " AND typlen = -1)";
|
||||||
|
|
||||||
PGresult* oidResult = PQexec(connection, sql.toUtf8());
|
PGresult* oidResult = PQexec(connectionRO, sql.toUtf8());
|
||||||
QString fieldTypeName = QString::fromUtf8(PQgetvalue(oidResult, 0, 0));
|
QString fieldTypeName = QString::fromUtf8(PQgetvalue(oidResult, 0, 0));
|
||||||
QString fieldSize = QString::fromUtf8(PQgetvalue(oidResult, 0, 1));
|
QString fieldSize = QString::fromUtf8(PQgetvalue(oidResult, 0, 1));
|
||||||
PQclear(oidResult);
|
PQclear(oidResult);
|
||||||
@ -795,14 +813,14 @@ void QgsPostgresProvider::loadFields()
|
|||||||
sql = QString("SELECT attnum FROM pg_attribute WHERE attrelid=%1 AND attname=%2")
|
sql = QString("SELECT attnum FROM pg_attribute WHERE attrelid=%1 AND attname=%2")
|
||||||
.arg( tableoid ).arg( quotedValue(fieldName) );
|
.arg( tableoid ).arg( quotedValue(fieldName) );
|
||||||
|
|
||||||
PGresult *tresult = PQexec(connection, sql.toUtf8());
|
PGresult *tresult = PQexec(connectionRO, sql.toUtf8());
|
||||||
QString attnum = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
QString attnum = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
||||||
PQclear(tresult);
|
PQclear(tresult);
|
||||||
|
|
||||||
sql = QString("SELECT description FROM pg_description WHERE objoid=%1 AND objsubid=%2")
|
sql = QString("SELECT description FROM pg_description WHERE objoid=%1 AND objsubid=%2")
|
||||||
.arg( tableoid ).arg( attnum );
|
.arg( tableoid ).arg( attnum );
|
||||||
|
|
||||||
tresult = PQexec(connection, sql.toUtf8());
|
tresult = PQexec(connectionRO, sql.toUtf8());
|
||||||
if (PQntuples(tresult) > 0)
|
if (PQntuples(tresult) > 0)
|
||||||
fieldComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
fieldComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
|
||||||
PQclear(tresult);
|
PQclear(tresult);
|
||||||
@ -859,7 +877,7 @@ QString QgsPostgresProvider::getPrimaryKey()
|
|||||||
|
|
||||||
QgsDebugMsg("Getting unique index using '" + sql + "'");
|
QgsDebugMsg("Getting unique index using '" + sql + "'");
|
||||||
|
|
||||||
PGresult *pk = executeDbCommand(connection, sql);
|
PGresult *pk = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
QgsDebugMsg("Got " + QString::number(PQntuples(pk)) + " rows.");
|
QgsDebugMsg("Got " + QString::number(PQntuples(pk)) + " rows.");
|
||||||
|
|
||||||
@ -877,7 +895,7 @@ QString QgsPostgresProvider::getPrimaryKey()
|
|||||||
|
|
||||||
sql = QString("SELECT relkind FROM pg_class WHERE oid=regclass(%1)::oid")
|
sql = QString("SELECT relkind FROM pg_class WHERE oid=regclass(%1)::oid")
|
||||||
.arg( quotedValue(mSchemaTableName) );
|
.arg( quotedValue(mSchemaTableName) );
|
||||||
PGresult* tableType = executeDbCommand(connection, sql);
|
PGresult* tableType = executeDbCommand(connectionRO, sql);
|
||||||
QString type = QString::fromUtf8(PQgetvalue(tableType, 0, 0));
|
QString type = QString::fromUtf8(PQgetvalue(tableType, 0, 0));
|
||||||
PQclear(tableType);
|
PQclear(tableType);
|
||||||
|
|
||||||
@ -892,7 +910,7 @@ QString QgsPostgresProvider::getPrimaryKey()
|
|||||||
sql = QString("SELECT attname FROM pg_attribute WHERE attname='oid' AND attrelid=regclass(%1)")
|
sql = QString("SELECT attname FROM pg_attribute WHERE attname='oid' AND attrelid=regclass(%1)")
|
||||||
.arg( quotedValue(mSchemaTableName) );
|
.arg( quotedValue(mSchemaTableName) );
|
||||||
|
|
||||||
PGresult* oidCheck = executeDbCommand(connection, sql);
|
PGresult* oidCheck = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
if (PQntuples(oidCheck) != 0)
|
if (PQntuples(oidCheck) != 0)
|
||||||
{
|
{
|
||||||
@ -940,7 +958,7 @@ QString QgsPostgresProvider::getPrimaryKey()
|
|||||||
// Get the column name and data type
|
// Get the column name and data type
|
||||||
sql = QString("select attname,pg_type.typname from pg_attribute,pg_type where atttypid=pg_type.oid and attnum=%1 and attrelid=regclass(%2)")
|
sql = QString("select attname,pg_type.typname from pg_attribute,pg_type where atttypid=pg_type.oid and attnum=%1 and attrelid=regclass(%2)")
|
||||||
.arg( col ).arg( quotedValue(mSchemaTableName) );
|
.arg( col ).arg( quotedValue(mSchemaTableName) );
|
||||||
PGresult* types = executeDbCommand(connection, sql);
|
PGresult* types = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
if( PQntuples(types) > 0 )
|
if( PQntuples(types) > 0 )
|
||||||
{
|
{
|
||||||
@ -968,7 +986,7 @@ QString QgsPostgresProvider::getPrimaryKey()
|
|||||||
.arg( col.replace(" ", ",") )
|
.arg( col.replace(" ", ",") )
|
||||||
.arg( quotedValue(mSchemaTableName) );
|
.arg( quotedValue(mSchemaTableName) );
|
||||||
|
|
||||||
PGresult* types = executeDbCommand(connection, sql);
|
PGresult* types = executeDbCommand(connectionRO, sql);
|
||||||
QString colNames;
|
QString colNames;
|
||||||
int numCols = PQntuples(types);
|
int numCols = PQntuples(types);
|
||||||
for (int j = 0; j < numCols; ++j)
|
for (int j = 0; j < numCols; ++j)
|
||||||
@ -1002,7 +1020,7 @@ QString QgsPostgresProvider::getPrimaryKey()
|
|||||||
// If there is an oid on the table, use that instead,
|
// If there is an oid on the table, use that instead,
|
||||||
// otherwise give up
|
// otherwise give up
|
||||||
sql = QString("select attname from pg_attribute where attname='oid' and attrelid=regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
sql = QString("select attname from pg_attribute where attname='oid' and attrelid=regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
||||||
PGresult* oidCheck = executeDbCommand(connection, sql);
|
PGresult* oidCheck = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
if (PQntuples(oidCheck) != 0)
|
if (PQntuples(oidCheck) != 0)
|
||||||
{
|
{
|
||||||
@ -1069,7 +1087,7 @@ QString QgsPostgresProvider::chooseViewColumn(const tableCols& cols)
|
|||||||
// Get the oid from pg_class for the given schema.relation for use
|
// Get the oid from pg_class for the given schema.relation for use
|
||||||
// in subsequent queries.
|
// in subsequent queries.
|
||||||
sql = QString("select regclass(%1)::oid").arg( quotedValue( quotedIdentifier(schemaName) + "." + quotedIdentifier(tableName) ) );
|
sql = QString("select regclass(%1)::oid").arg( quotedValue( quotedIdentifier(schemaName) + "." + quotedIdentifier(tableName) ) );
|
||||||
PGresult* result = PQexec(connection, sql.toUtf8());
|
PGresult* result = PQexec(connectionRO, sql.toUtf8());
|
||||||
QString rel_oid;
|
QString rel_oid;
|
||||||
if (PQntuples(result) == 1)
|
if (PQntuples(result) == 1)
|
||||||
{
|
{
|
||||||
@ -1100,7 +1118,7 @@ QString QgsPostgresProvider::chooseViewColumn(const tableCols& cols)
|
|||||||
"and conrelid=%2 and (contype='p' or contype='u') "
|
"and conrelid=%2 and (contype='p' or contype='u') "
|
||||||
"and array_dims(conkey)='[1:1]'").arg( quotedValue(tableCol) ).arg( rel_oid );
|
"and array_dims(conkey)='[1:1]'").arg( quotedValue(tableCol) ).arg( rel_oid );
|
||||||
|
|
||||||
result = PQexec(connection, sql.toUtf8());
|
result = PQexec(connectionRO, sql.toUtf8());
|
||||||
if (PQntuples(result) == 1 && colType == "int4")
|
if (PQntuples(result) == 1 && colType == "int4")
|
||||||
suitable[viewCol] = iter->second;
|
suitable[viewCol] = iter->second;
|
||||||
|
|
||||||
@ -1159,7 +1177,7 @@ QString QgsPostgresProvider::chooseViewColumn(const tableCols& cols)
|
|||||||
sql = QString( "select * from pg_index where indrelid=%1 and indkey[0]=(select attnum from pg_attribute where attrelid=%1 and attname=%2)")
|
sql = QString( "select * from pg_index where indrelid=%1 and indkey[0]=(select attnum from pg_attribute where attrelid=%1 and attname=%2)")
|
||||||
.arg( rel_oid )
|
.arg( rel_oid )
|
||||||
.arg( quotedValue( i->second.column ) );
|
.arg( quotedValue( i->second.column ) );
|
||||||
PGresult* result = PQexec(connection, sql.toUtf8());
|
PGresult* result = PQexec(connectionRO, sql.toUtf8());
|
||||||
|
|
||||||
if (PQntuples(result) > 0 && uniqueData(mSchemaName, mTableName, i->first))
|
if (PQntuples(result) > 0 && uniqueData(mSchemaName, mTableName, i->first))
|
||||||
{ // Got one. Use it.
|
{ // Got one. Use it.
|
||||||
@ -1245,7 +1263,7 @@ bool QgsPostgresProvider::uniqueData(QString schemaName,
|
|||||||
.arg( quotedIdentifier(schemaName) )
|
.arg( quotedIdentifier(schemaName) )
|
||||||
.arg( quotedIdentifier(tableName) );
|
.arg( quotedIdentifier(tableName) );
|
||||||
|
|
||||||
PGresult* unique = PQexec(connection, sql.toUtf8());
|
PGresult* unique = PQexec(connectionRO, sql.toUtf8());
|
||||||
|
|
||||||
if (PQntuples(unique)==1 && QString::fromUtf8(PQgetvalue(unique, 0, 0)).startsWith("t"))
|
if (PQntuples(unique)==1 && QString::fromUtf8(PQgetvalue(unique, 0, 0)).startsWith("t"))
|
||||||
isUnique = true;
|
isUnique = true;
|
||||||
@ -1259,7 +1277,7 @@ int QgsPostgresProvider::SRCFromViewColumn(const QString& ns, const QString& rel
|
|||||||
{
|
{
|
||||||
QString newViewDefSql = QString("SELECT definition FROM pg_views WHERE schemaname=%1 AND viewname=%2")
|
QString newViewDefSql = QString("SELECT definition FROM pg_views WHERE schemaname=%1 AND viewname=%2")
|
||||||
.arg( quotedValue(ns) ).arg( quotedValue(relname) );
|
.arg( quotedValue(ns) ).arg( quotedValue(relname) );
|
||||||
PGresult* newViewDefResult = PQexec(connection, newViewDefSql.toUtf8());
|
PGresult* newViewDefResult = PQexec(connectionRO, newViewDefSql.toUtf8());
|
||||||
int numEntries = PQntuples(newViewDefResult);
|
int numEntries = PQntuples(newViewDefResult);
|
||||||
|
|
||||||
if(numEntries > 0) //relation is a view
|
if(numEntries > 0) //relation is a view
|
||||||
@ -1335,7 +1353,7 @@ int QgsPostgresProvider::SRCFromViewColumn(const QString& ns, const QString& rel
|
|||||||
.arg( quotedValue(relname) )
|
.arg( quotedValue(relname) )
|
||||||
.arg( quotedValue(newAttNameTable) );
|
.arg( quotedValue(newAttNameTable) );
|
||||||
|
|
||||||
PGresult* viewColumnResult = PQexec(connection, viewColumnSql.toUtf8());
|
PGresult* viewColumnResult = PQexec(connectionRO, viewColumnSql.toUtf8());
|
||||||
if(PQntuples(viewColumnResult) > 0)
|
if(PQntuples(viewColumnResult) > 0)
|
||||||
{
|
{
|
||||||
QString newTableSchema = QString::fromUtf8(PQgetvalue(viewColumnResult, 0, 0));
|
QString newTableSchema = QString::fromUtf8(PQgetvalue(viewColumnResult, 0, 0));
|
||||||
@ -1373,7 +1391,7 @@ int QgsPostgresProvider::SRCFromViewColumn(const QString& ns, const QString& rel
|
|||||||
.arg( quotedValue(ns) )
|
.arg( quotedValue(ns) )
|
||||||
.arg( quotedValue(attname_table) );
|
.arg( quotedValue(attname_table) );
|
||||||
|
|
||||||
PGresult* typeSqlResult = PQexec(connection, typeSql.toUtf8());
|
PGresult* typeSqlResult = PQexec(connectionRO, typeSql.toUtf8());
|
||||||
if(PQntuples(typeSqlResult) < 1)
|
if(PQntuples(typeSqlResult) < 1)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
@ -1446,13 +1464,13 @@ void QgsPostgresProvider::findColumns(tableCols& cols)
|
|||||||
"view_schema=%1 AND view_name=%2")
|
"view_schema=%1 AND view_name=%2")
|
||||||
.arg( quotedValue(mSchemaName) )
|
.arg( quotedValue(mSchemaName) )
|
||||||
.arg( quotedValue(mTableName) );
|
.arg( quotedValue(mTableName) );
|
||||||
PGresult* viewColumnResult = PQexec(connection, viewColumnSql.toUtf8());
|
PGresult* viewColumnResult = PQexec(connectionRO, viewColumnSql.toUtf8());
|
||||||
|
|
||||||
//find out view definition
|
//find out view definition
|
||||||
QString viewDefSql = QString("SELECT definition FROM pg_views WHERE schemaname=%1 AND viewname=%2")
|
QString viewDefSql = QString("SELECT definition FROM pg_views WHERE schemaname=%1 AND viewname=%2")
|
||||||
.arg( quotedValue( mSchemaName ) )
|
.arg( quotedValue( mSchemaName ) )
|
||||||
.arg( quotedValue( mTableName ) );
|
.arg( quotedValue( mTableName ) );
|
||||||
PGresult* viewDefResult = PQexec(connection, viewDefSql.toUtf8());
|
PGresult* viewDefResult = PQexec(connectionRO, viewDefSql.toUtf8());
|
||||||
if(PQntuples(viewDefResult) < 1)
|
if(PQntuples(viewDefResult) < 1)
|
||||||
{
|
{
|
||||||
PQclear(viewDefResult);
|
PQclear(viewDefResult);
|
||||||
@ -1523,7 +1541,7 @@ QVariant QgsPostgresProvider::minValue(int index)
|
|||||||
.arg(mSchemaTableName)
|
.arg(mSchemaTableName)
|
||||||
.arg(sqlWhereClause);
|
.arg(sqlWhereClause);
|
||||||
}
|
}
|
||||||
PGresult *rmin = PQexec(connection, sql.toUtf8());
|
PGresult *rmin = PQexec(connectionRO, sql.toUtf8());
|
||||||
QString minValue = QString::fromUtf8(PQgetvalue(rmin,0,0));
|
QString minValue = QString::fromUtf8(PQgetvalue(rmin,0,0));
|
||||||
PQclear(rmin);
|
PQclear(rmin);
|
||||||
return minValue.toDouble();
|
return minValue.toDouble();
|
||||||
@ -1558,7 +1576,7 @@ void QgsPostgresProvider::getUniqueValues(int index, QStringList &uniqueValues)
|
|||||||
.arg(sqlWhereClause);
|
.arg(sqlWhereClause);
|
||||||
}
|
}
|
||||||
|
|
||||||
PGresult *res= PQexec(connection, sql.toUtf8());
|
PGresult *res= PQexec(connectionRO, sql.toUtf8());
|
||||||
if (PQresultStatus(res) == PGRES_TUPLES_OK)
|
if (PQresultStatus(res) == PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
for(int i=0; i<PQntuples(res); i++)
|
for(int i=0; i<PQntuples(res); i++)
|
||||||
@ -1593,7 +1611,7 @@ QVariant QgsPostgresProvider::maxValue(int index)
|
|||||||
.arg(mSchemaTableName)
|
.arg(mSchemaTableName)
|
||||||
.arg(sqlWhereClause);
|
.arg(sqlWhereClause);
|
||||||
}
|
}
|
||||||
PGresult *rmax = PQexec(connection, sql.toUtf8());
|
PGresult *rmax = PQexec(connectionRO, sql.toUtf8());
|
||||||
QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
|
QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
|
||||||
PQclear(rmax);
|
PQclear(rmax);
|
||||||
return maxValue.toDouble();
|
return maxValue.toDouble();
|
||||||
@ -1613,7 +1631,7 @@ int QgsPostgresProvider::maxPrimaryKeyValue()
|
|||||||
.arg(quotedIdentifier(primaryKey))
|
.arg(quotedIdentifier(primaryKey))
|
||||||
.arg(mSchemaTableName);
|
.arg(mSchemaTableName);
|
||||||
|
|
||||||
PGresult *rmax = PQexec(connection, sql.toUtf8());
|
PGresult *rmax = PQexec(connectionRO, sql.toUtf8());
|
||||||
QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
|
QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
|
||||||
PQclear(rmax);
|
PQclear(rmax);
|
||||||
|
|
||||||
@ -1645,7 +1663,7 @@ QVariant QgsPostgresProvider::getDefaultValue(int fieldId)
|
|||||||
|
|
||||||
QVariant defaultValue(QString::null);
|
QVariant defaultValue(QString::null);
|
||||||
|
|
||||||
PGresult* result = PQexec(connection, sql.toUtf8());
|
PGresult* result = PQexec(connectionRO, sql.toUtf8());
|
||||||
|
|
||||||
if (PQntuples(result)==1 && !PQgetisnull(result, 0, 0) )
|
if (PQntuples(result)==1 && !PQgetisnull(result, 0, 0) )
|
||||||
defaultValue = QString::fromUtf8(PQgetvalue(result, 0, 0));
|
defaultValue = QString::fromUtf8(PQgetvalue(result, 0, 0));
|
||||||
@ -1723,7 +1741,7 @@ QByteArray QgsPostgresProvider::paramValue(QString fieldValue, const QString &de
|
|||||||
|
|
||||||
if( fieldValue==defaultValue && !defaultValue.isNull() )
|
if( fieldValue==defaultValue && !defaultValue.isNull() )
|
||||||
{
|
{
|
||||||
PGresult *result = PQexec( connection, QString("select %1").arg(defaultValue).toUtf8() );
|
PGresult *result = PQexec( connectionRO, QString("select %1").arg(defaultValue).toUtf8() );
|
||||||
if( PQgetisnull(result, 0, 0) ) {
|
if( PQgetisnull(result, 0, 0) ) {
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
return QByteArray(0); // QByteArray(0).isNull() is true
|
return QByteArray(0); // QByteArray(0).isNull() is true
|
||||||
@ -1742,10 +1760,13 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
|
|||||||
if( flist.size() == 0 )
|
if( flist.size() == 0 )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if( !connectRW() )
|
||||||
|
return false;
|
||||||
|
|
||||||
bool returnvalue=true;
|
bool returnvalue=true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PQexecNR(connection,QString("BEGIN").toUtf8());
|
PQexecNR(connectionRW,QString("BEGIN").toUtf8());
|
||||||
|
|
||||||
// Prepare the INSERT statement
|
// Prepare the INSERT statement
|
||||||
QString insert = QString("INSERT INTO %1(%2,%3")
|
QString insert = QString("INSERT INTO %1(%2,%3")
|
||||||
@ -1820,7 +1841,7 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
|
|||||||
insert += values + ")";
|
insert += values + ")";
|
||||||
|
|
||||||
QgsDebugMsg( QString("prepare addfeatures: %1").arg(insert) );
|
QgsDebugMsg( QString("prepare addfeatures: %1").arg(insert) );
|
||||||
PGresult *stmt = PQprepare(connection, "addfeatures", insert.toUtf8(), fieldId.size()+2, NULL);
|
PGresult *stmt = PQprepare(connectionRW, "addfeatures", insert.toUtf8(), fieldId.size()+2, NULL);
|
||||||
if(stmt==0 || PQresultStatus(stmt)==PGRES_FATAL_ERROR)
|
if(stmt==0 || PQresultStatus(stmt)==PGRES_FATAL_ERROR)
|
||||||
throw PGException(stmt);
|
throw PGException(stmt);
|
||||||
|
|
||||||
@ -1852,7 +1873,7 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
|
|||||||
param[i+2] = qparam[i+2];
|
param[i+2] = qparam[i+2];
|
||||||
}
|
}
|
||||||
|
|
||||||
PGresult *result = PQexecPrepared(connection, "addfeatures", fieldId.size()+2, param, NULL, NULL, 0);
|
PGresult *result = PQexecPrepared(connectionRW, "addfeatures", fieldId.size()+2, param, NULL, NULL, 0);
|
||||||
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
||||||
{
|
{
|
||||||
delete param;
|
delete param;
|
||||||
@ -1862,14 +1883,13 @@ bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
|
|||||||
PQclear(result);
|
PQclear(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQexecNR(connection,QString("COMMIT").toUtf8());
|
PQexecNR(connectionRW,QString("DEALLOCATE addfeatures").toUtf8());
|
||||||
PQexecNR(connection,QString("DEALLOCATE addfeatures").toUtf8());
|
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
|
||||||
delete param;
|
delete param;
|
||||||
} catch(PGException &e) {
|
} catch(PGException &e) {
|
||||||
e.showErrorMessage( tr("Error while adding features") );
|
e.showErrorMessage( tr("Error while adding features") );
|
||||||
PQexecNR(connection,QString("ROLLBACK").toUtf8());
|
PQexecNR(connectionRW,QString("DEALLOCATE addfeatures").toUtf8());
|
||||||
|
PQexecNR(connectionRW,QString("ROLLBACK").toUtf8());
|
||||||
PQexecNR(connection,QString("DEALLOCATE addfeatures").toUtf8());
|
|
||||||
returnvalue = false;
|
returnvalue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1881,8 +1901,11 @@ bool QgsPostgresProvider::deleteFeatures(const QgsFeatureIds & id)
|
|||||||
{
|
{
|
||||||
bool returnvalue=true;
|
bool returnvalue=true;
|
||||||
|
|
||||||
|
if( !connectRW() )
|
||||||
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PQexecNR(connection,QString("BEGIN").toUtf8());
|
PQexecNR(connectionRW,QString("BEGIN").toUtf8());
|
||||||
|
|
||||||
for(QgsFeatureIds::const_iterator it=id.begin();it!=id.end();++it) {
|
for(QgsFeatureIds::const_iterator it=id.begin();it!=id.end();++it) {
|
||||||
QString sql = QString("DELETE FROM %1 WHERE %2=%3")
|
QString sql = QString("DELETE FROM %1 WHERE %2=%3")
|
||||||
@ -1892,16 +1915,16 @@ bool QgsPostgresProvider::deleteFeatures(const QgsFeatureIds & id)
|
|||||||
QgsDebugMsg("delete sql: "+sql);
|
QgsDebugMsg("delete sql: "+sql);
|
||||||
|
|
||||||
//send DELETE statement and do error handling
|
//send DELETE statement and do error handling
|
||||||
PGresult* result=PQexec(connection, sql.toUtf8());
|
PGresult* result=PQexec(connectionRW, sql.toUtf8());
|
||||||
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
||||||
throw PGException(result);
|
throw PGException(result);
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQexecNR(connection,QString("COMMIT").toUtf8());
|
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
|
||||||
} catch(PGException &e) {
|
} catch(PGException &e) {
|
||||||
e.showErrorMessage( tr("Error while deleting features") );
|
e.showErrorMessage( tr("Error while deleting features") );
|
||||||
PQexecNR(connection,QString("ROLLBACK").toUtf8());
|
PQexecNR(connectionRW,QString("ROLLBACK").toUtf8());
|
||||||
returnvalue = false;
|
returnvalue = false;
|
||||||
}
|
}
|
||||||
reset();
|
reset();
|
||||||
@ -1912,8 +1935,11 @@ bool QgsPostgresProvider::addAttributes(const QgsNewAttributesMap & name)
|
|||||||
{
|
{
|
||||||
bool returnvalue=true;
|
bool returnvalue=true;
|
||||||
|
|
||||||
|
if( !connectRW() )
|
||||||
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PQexecNR(connection,QString("BEGIN").toUtf8());
|
PQexecNR(connectionRW,QString("BEGIN").toUtf8());
|
||||||
|
|
||||||
for(QgsNewAttributesMap::const_iterator iter=name.begin();iter!=name.end();++iter)
|
for(QgsNewAttributesMap::const_iterator iter=name.begin();iter!=name.end();++iter)
|
||||||
{
|
{
|
||||||
@ -1924,16 +1950,16 @@ bool QgsPostgresProvider::addAttributes(const QgsNewAttributesMap & name)
|
|||||||
QgsDebugMsg(sql);
|
QgsDebugMsg(sql);
|
||||||
|
|
||||||
//send sql statement and do error handling
|
//send sql statement and do error handling
|
||||||
PGresult* result=PQexec(connection, sql.toUtf8());
|
PGresult* result=PQexec(connectionRW, sql.toUtf8());
|
||||||
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
||||||
throw PGException(result);
|
throw PGException(result);
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQexecNR(connection,QString("COMMIT").toUtf8());
|
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
|
||||||
} catch(PGException &e) {
|
} catch(PGException &e) {
|
||||||
e.showErrorMessage( tr("Error while adding attributes") );
|
e.showErrorMessage( tr("Error while adding attributes") );
|
||||||
PQexecNR(connection,QString("ROLLBACK").toUtf8());
|
PQexecNR(connectionRW,QString("ROLLBACK").toUtf8());
|
||||||
returnvalue = false;
|
returnvalue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1945,8 +1971,11 @@ bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
|
|||||||
{
|
{
|
||||||
bool returnvalue=true;
|
bool returnvalue=true;
|
||||||
|
|
||||||
|
if( !connectRW() )
|
||||||
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PQexecNR(connection,QString("BEGIN").toUtf8());
|
PQexecNR(connectionRW,QString("BEGIN").toUtf8());
|
||||||
|
|
||||||
for(QgsAttributeIds::const_iterator iter=ids.begin();iter != ids.end();++iter)
|
for(QgsAttributeIds::const_iterator iter=ids.begin();iter != ids.end();++iter)
|
||||||
{
|
{
|
||||||
@ -1960,7 +1989,7 @@ bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
|
|||||||
.arg(quotedIdentifier(column));
|
.arg(quotedIdentifier(column));
|
||||||
|
|
||||||
//send sql statement and do error handling
|
//send sql statement and do error handling
|
||||||
PGresult* result=PQexec(connection, sql.toUtf8());
|
PGresult* result=PQexec(connectionRW, sql.toUtf8());
|
||||||
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
||||||
throw PGException(result);
|
throw PGException(result);
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
@ -1969,10 +1998,10 @@ bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
|
|||||||
attributeFields.remove(*iter);
|
attributeFields.remove(*iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQexecNR(connection,QString("COMMIT").toUtf8());
|
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
|
||||||
} catch(PGException &e) {
|
} catch(PGException &e) {
|
||||||
e.showErrorMessage( tr("Error while deleting attributes") );
|
e.showErrorMessage( tr("Error while deleting attributes") );
|
||||||
PQexecNR(connection,QString("ROLLBACK").toUtf8());
|
PQexecNR(connectionRW,QString("ROLLBACK").toUtf8());
|
||||||
returnvalue = false;
|
returnvalue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1984,8 +2013,11 @@ bool QgsPostgresProvider::changeAttributeValues(const QgsChangedAttributesMap &
|
|||||||
{
|
{
|
||||||
bool returnvalue=true;
|
bool returnvalue=true;
|
||||||
|
|
||||||
|
if( !connectRW() )
|
||||||
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
PQexecNR(connection,QString("BEGIN").toUtf8());
|
PQexecNR(connectionRW,QString("BEGIN").toUtf8());
|
||||||
|
|
||||||
// cycle through the features
|
// cycle through the features
|
||||||
for(QgsChangedAttributesMap::const_iterator iter=attr_map.begin();iter!=attr_map.end();++iter)
|
for(QgsChangedAttributesMap::const_iterator iter=attr_map.begin();iter!=attr_map.end();++iter)
|
||||||
@ -2026,17 +2058,17 @@ bool QgsPostgresProvider::changeAttributeValues(const QgsChangedAttributesMap &
|
|||||||
.arg( quotedIdentifier(primaryKey) )
|
.arg( quotedIdentifier(primaryKey) )
|
||||||
.arg( fid );
|
.arg( fid );
|
||||||
|
|
||||||
PGresult* result=PQexec(connection, sql.toUtf8());
|
PGresult* result=PQexec(connectionRW, sql.toUtf8());
|
||||||
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
||||||
throw PGException(result);
|
throw PGException(result);
|
||||||
|
|
||||||
PQclear(result);
|
PQclear(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
PQexecNR(connection,QString("COMMIT").toUtf8());
|
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
|
||||||
} catch(PGException &e) {
|
} catch(PGException &e) {
|
||||||
e.showErrorMessage( tr("Error while changing attributes") );
|
e.showErrorMessage( tr("Error while changing attributes") );
|
||||||
PQexecNR(connection,QString("ROLLBACK").toUtf8());
|
PQexecNR(connectionRW,QString("ROLLBACK").toUtf8());
|
||||||
returnvalue = false;
|
returnvalue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2061,11 +2093,14 @@ bool QgsPostgresProvider::changeGeometryValues(QgsGeometryMap & geometry_map)
|
|||||||
{
|
{
|
||||||
QgsDebugMsg("entering.");
|
QgsDebugMsg("entering.");
|
||||||
|
|
||||||
|
if( !connectRW() )
|
||||||
|
return false;
|
||||||
|
|
||||||
bool returnvalue = true;
|
bool returnvalue = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Start the PostGIS transaction
|
// Start the PostGIS transaction
|
||||||
PQexecNR(connection,QString("BEGIN").toUtf8());
|
PQexecNR(connectionRW,QString("BEGIN").toUtf8());
|
||||||
|
|
||||||
QString update = QString("UPDATE %1 SET %2=GeomFromWKB($1%3,%4) WHERE %5=$2")
|
QString update = QString("UPDATE %1 SET %2=GeomFromWKB($1%3,%4) WHERE %5=$2")
|
||||||
.arg( mSchemaTableName )
|
.arg( mSchemaTableName )
|
||||||
@ -2074,7 +2109,7 @@ bool QgsPostgresProvider::changeGeometryValues(QgsGeometryMap & geometry_map)
|
|||||||
.arg( srid )
|
.arg( srid )
|
||||||
.arg( quotedIdentifier(primaryKey) );
|
.arg( quotedIdentifier(primaryKey) );
|
||||||
|
|
||||||
PGresult *stmt = PQprepare(connection, "updatefeatures", update.toUtf8(), 2, NULL);
|
PGresult *stmt = PQprepare(connectionRW, "updatefeatures", update.toUtf8(), 2, NULL);
|
||||||
if(stmt==0 || PQresultStatus(stmt)==PGRES_FATAL_ERROR)
|
if(stmt==0 || PQresultStatus(stmt)==PGRES_FATAL_ERROR)
|
||||||
throw PGException(stmt);
|
throw PGException(stmt);
|
||||||
|
|
||||||
@ -2102,7 +2137,7 @@ bool QgsPostgresProvider::changeGeometryValues(QgsGeometryMap & geometry_map)
|
|||||||
param[0] = qparam[0];
|
param[0] = qparam[0];
|
||||||
param[1] = qparam[1];
|
param[1] = qparam[1];
|
||||||
|
|
||||||
PGresult *result = PQexecPrepared(connection, "updatefeatures", 2, param, NULL, NULL, 0);
|
PGresult *result = PQexecPrepared(connectionRW, "updatefeatures", 2, param, NULL, NULL, 0);
|
||||||
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
if( result==0 || PQresultStatus(result)==PGRES_FATAL_ERROR )
|
||||||
throw PGException(result);
|
throw PGException(result);
|
||||||
|
|
||||||
@ -2111,12 +2146,12 @@ bool QgsPostgresProvider::changeGeometryValues(QgsGeometryMap & geometry_map)
|
|||||||
|
|
||||||
} // for each feature
|
} // for each feature
|
||||||
|
|
||||||
PQexecNR(connection,QString("COMMIT").toUtf8());
|
PQexecNR(connectionRW,QString("DEALLOCATE updatefeatures").toUtf8());
|
||||||
PQexecNR(connection,QString("DEALLOCATE updatefeatures").toUtf8());
|
PQexecNR(connectionRW,QString("COMMIT").toUtf8());
|
||||||
} catch(PGException &e) {
|
} catch(PGException &e) {
|
||||||
e.showErrorMessage( tr("Error while changing geometry values") );
|
e.showErrorMessage( tr("Error while changing geometry values") );
|
||||||
PQexecNR(connection,QString("ROLLBACK").toUtf8());
|
PQexecNR(connectionRW,QString("DEALLOCATE updatefeatures").toUtf8());
|
||||||
PQexecNR(connection,QString("DEALLOCATE updatefeatures").toUtf8());
|
PQexecNR(connectionRW,QString("ROLLBACK").toUtf8());
|
||||||
returnvalue = false;
|
returnvalue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2176,7 +2211,7 @@ long QgsPostgresProvider::getFeatureCount()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PGresult *result = PQexec(connection, sql.toUtf8());
|
PGresult *result = PQexec(connectionRO, sql.toUtf8());
|
||||||
|
|
||||||
QgsDebugMsg("Approximate Number of features as text: " +
|
QgsDebugMsg("Approximate Number of features as text: " +
|
||||||
QString::fromUtf8(PQgetvalue(result, 0, 0)));
|
QString::fromUtf8(PQgetvalue(result, 0, 0)));
|
||||||
@ -2219,7 +2254,7 @@ void QgsPostgresProvider::calculateExtents()
|
|||||||
|
|
||||||
QgsDebugMsg("Getting approximate extent using: '" + sql + "'");
|
QgsDebugMsg("Getting approximate extent using: '" + sql + "'");
|
||||||
|
|
||||||
PGresult *result = PQexec(connection, sql.toUtf8());
|
PGresult *result = PQexec(connectionRO, sql.toUtf8());
|
||||||
|
|
||||||
// TODO: Guard against the result having no rows
|
// TODO: Guard against the result having no rows
|
||||||
|
|
||||||
@ -2271,7 +2306,7 @@ void QgsPostgresProvider::calculateExtents()
|
|||||||
|
|
||||||
QgsDebugMsg("Getting extents using schema.table: " + sql);
|
QgsDebugMsg("Getting extents using schema.table: " + sql);
|
||||||
|
|
||||||
PGresult *result = PQexec(connection, sql.toUtf8());
|
PGresult *result = PQexec(connectionRO, sql.toUtf8());
|
||||||
if(PQntuples(result)>0)
|
if(PQntuples(result)>0)
|
||||||
{
|
{
|
||||||
std::string box3d = PQgetvalue(result, 0, 0);
|
std::string box3d = PQgetvalue(result, 0, 0);
|
||||||
@ -2390,7 +2425,7 @@ bool QgsPostgresProvider::deduceEndian()
|
|||||||
// return data in the endian of the server
|
// return data in the endian of the server
|
||||||
|
|
||||||
QString firstOid = QString("select regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
QString firstOid = QString("select regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
||||||
PGresult * oidResult = PQexec(connection, firstOid.toUtf8());
|
PGresult * oidResult = PQexec(connectionRO, firstOid.toUtf8());
|
||||||
// get the int value from a "normal" select
|
// get the int value from a "normal" select
|
||||||
QString oidValue = QString::fromUtf8(PQgetvalue(oidResult,0,0));
|
QString oidValue = QString::fromUtf8(PQgetvalue(oidResult,0,0));
|
||||||
PQclear(oidResult);
|
PQclear(oidResult);
|
||||||
@ -2401,12 +2436,12 @@ bool QgsPostgresProvider::deduceEndian()
|
|||||||
|
|
||||||
QString oidDeclare = QString("declare oidcursor binary cursor with hold for select regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
QString oidDeclare = QString("declare oidcursor binary cursor with hold for select regclass(%1)::oid").arg( quotedValue(mSchemaTableName) );
|
||||||
// set up the cursor
|
// set up the cursor
|
||||||
PQexecNR(connection, oidDeclare.toUtf8());
|
PQexecNR(connectionRO, oidDeclare.toUtf8());
|
||||||
QString fetch = "fetch forward 1 from oidcursor";
|
QString fetch = "fetch forward 1 from oidcursor";
|
||||||
|
|
||||||
QgsDebugMsg("Fetching a record and attempting to get check endian-ness");
|
QgsDebugMsg("Fetching a record and attempting to get check endian-ness");
|
||||||
|
|
||||||
PGresult *fResult = PQexec(connection, fetch.toUtf8());
|
PGresult *fResult = PQexec(connectionRO, fetch.toUtf8());
|
||||||
swapEndian = true;
|
swapEndian = true;
|
||||||
if(PQntuples(fResult) > 0){
|
if(PQntuples(fResult) > 0){
|
||||||
// get the oid value from the binary cursor
|
// get the oid value from the binary cursor
|
||||||
@ -2420,7 +2455,7 @@ bool QgsPostgresProvider::deduceEndian()
|
|||||||
|
|
||||||
PQclear(fResult);
|
PQclear(fResult);
|
||||||
}
|
}
|
||||||
PQexecNR(connection, QString("close oidcursor").toUtf8());
|
PQexecNR(connectionRO, QString("close oidcursor").toUtf8());
|
||||||
return swapEndian;
|
return swapEndian;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2439,7 +2474,7 @@ bool QgsPostgresProvider::getGeometryDetails()
|
|||||||
|
|
||||||
QgsDebugMsg("Getting geometry column: " + sql);
|
QgsDebugMsg("Getting geometry column: " + sql);
|
||||||
|
|
||||||
PGresult *result = executeDbCommand(connection, sql);
|
PGresult *result = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
QgsDebugMsg("geometry column query returned " + QString::number(PQntuples(result)));
|
QgsDebugMsg("geometry column query returned " + QString::number(PQntuples(result)));
|
||||||
|
|
||||||
@ -2467,7 +2502,7 @@ bool QgsPostgresProvider::getGeometryDetails()
|
|||||||
|
|
||||||
sql += " limit 1";
|
sql += " limit 1";
|
||||||
|
|
||||||
result = executeDbCommand(connection, sql);
|
result = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
if (PQntuples(result) > 0)
|
if (PQntuples(result) > 0)
|
||||||
{
|
{
|
||||||
@ -2493,7 +2528,7 @@ bool QgsPostgresProvider::getGeometryDetails()
|
|||||||
if(mUri.sql()!="")
|
if(mUri.sql()!="")
|
||||||
sql += " where " + mUri.sql();
|
sql += " where " + mUri.sql();
|
||||||
|
|
||||||
result = executeDbCommand(connection, sql);
|
result = executeDbCommand(connectionRO, sql);
|
||||||
|
|
||||||
if (PQntuples(result)==1)
|
if (PQntuples(result)==1)
|
||||||
{
|
{
|
||||||
@ -2665,7 +2700,7 @@ QString QgsPostgresProvider::subsetString()
|
|||||||
|
|
||||||
PGconn * QgsPostgresProvider::pgConnection()
|
PGconn * QgsPostgresProvider::pgConnection()
|
||||||
{
|
{
|
||||||
return connection;
|
return connectionRW;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QgsPostgresProvider::getTableName()
|
QString QgsPostgresProvider::getTableName()
|
||||||
|
@ -47,10 +47,9 @@ class QgsGeometry;
|
|||||||
interface defined in the QgsDataProvider class to provide access to spatial
|
interface defined in the QgsDataProvider class to provide access to spatial
|
||||||
data residing in a PostgreSQL/PostGIS enabled database.
|
data residing in a PostgreSQL/PostGIS enabled database.
|
||||||
*/
|
*/
|
||||||
class QgsPostgresProvider:public QgsVectorDataProvider
|
class QgsPostgresProvider : public QgsVectorDataProvider
|
||||||
{
|
{
|
||||||
|
Q_OBJECT;
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@ -405,7 +404,18 @@ class QgsPostgresProvider:public QgsVectorDataProvider
|
|||||||
/**
|
/**
|
||||||
* Connection pointer
|
* Connection pointer
|
||||||
*/
|
*/
|
||||||
PGconn *connection;
|
PGconn *connectionRO;
|
||||||
|
PGconn *connectionRW;
|
||||||
|
|
||||||
|
bool connectRW() {
|
||||||
|
if(connectionRW)
|
||||||
|
return connectionRW;
|
||||||
|
|
||||||
|
connectionRW = connectDb(mUri.connInfo(), false);
|
||||||
|
|
||||||
|
return connectionRW;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spatial reference id of the layer
|
* Spatial reference id of the layer
|
||||||
*/
|
*/
|
||||||
@ -584,7 +594,7 @@ class QgsPostgresProvider:public QgsVectorDataProvider
|
|||||||
*/
|
*/
|
||||||
void customEvent ( QEvent *e );
|
void customEvent ( QEvent *e );
|
||||||
|
|
||||||
PGconn *connectDb(const QString &conninfo);
|
PGconn *connectDb(const QString &conninfo, bool readonly=true);
|
||||||
void disconnectDb();
|
void disconnectDb();
|
||||||
|
|
||||||
bool useWkbHex;
|
bool useWkbHex;
|
||||||
@ -605,7 +615,8 @@ class QgsPostgresProvider:public QgsVectorDataProvider
|
|||||||
int ref;
|
int ref;
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
};
|
};
|
||||||
static QMap<QString, Conn *> connections;
|
static QMap<QString, Conn *> connectionsRW;
|
||||||
|
static QMap<QString, Conn *> connectionsRO;
|
||||||
static int providerIds;
|
static int providerIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,27 +13,20 @@
|
|||||||
<string>Attribute Table</string>
|
<string>Attribute Table</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon" >
|
<property name="windowIcon" >
|
||||||
<iconset/>
|
<iconset>
|
||||||
|
<normaloff/>
|
||||||
|
</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" >
|
<layout class="QGridLayout" >
|
||||||
<property name="leftMargin" >
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin" >
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin" >
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin" >
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="horizontalSpacing" >
|
<property name="horizontalSpacing" >
|
||||||
<number>6</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="verticalSpacing" >
|
<property name="verticalSpacing" >
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="margin" >
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0" >
|
||||||
<widget class="QToolButton" name="mRemoveSelectionButton" >
|
<widget class="QToolButton" name="mRemoveSelectionButton" >
|
||||||
<property name="toolTip" >
|
<property name="toolTip" >
|
||||||
@ -43,7 +36,8 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon" >
|
<property name="icon" >
|
||||||
<iconset>../xpm/remove_selection.xpm</iconset>
|
<iconset>
|
||||||
|
<normaloff>../xpm/remove_selection.xpm</normaloff>../xpm/remove_selection.xpm</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut" >
|
<property name="shortcut" >
|
||||||
<string/>
|
<string/>
|
||||||
@ -59,7 +53,8 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon" >
|
<property name="icon" >
|
||||||
<iconset>../xpm/selected_to_top.png</iconset>
|
<iconset>
|
||||||
|
<normaloff>../xpm/selected_to_top.png</normaloff>../xpm/selected_to_top.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut" >
|
<property name="shortcut" >
|
||||||
<string>Ctrl+T</string>
|
<string>Ctrl+T</string>
|
||||||
@ -75,7 +70,8 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon" >
|
<property name="icon" >
|
||||||
<iconset>../xpm/switch_selection.png</iconset>
|
<iconset>
|
||||||
|
<normaloff>../xpm/switch_selection.png</normaloff>../xpm/switch_selection.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut" >
|
<property name="shortcut" >
|
||||||
<string>Ctrl+S</string>
|
<string>Ctrl+S</string>
|
||||||
@ -94,7 +90,8 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon" >
|
<property name="icon" >
|
||||||
<iconset>../xpm/copy_selection.png</iconset>
|
<iconset>
|
||||||
|
<normaloff>../xpm/copy_selection.png</normaloff>../xpm/copy_selection.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut" >
|
<property name="shortcut" >
|
||||||
<string>Ctrl+C</string>
|
<string>Ctrl+C</string>
|
||||||
@ -117,66 +114,12 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="5" >
|
|
||||||
<widget class="QToolButton" name="mAddAttributeButton" >
|
|
||||||
<property name="sizePolicy" >
|
|
||||||
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip" >
|
|
||||||
<string>New column</string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon" >
|
|
||||||
<iconset>../xpm/new_attribute.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut" >
|
|
||||||
<string>Ctrl+N</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="6" >
|
<item row="0" column="6" >
|
||||||
<widget class="QToolButton" name="mDeleteAttributeButton" >
|
|
||||||
<property name="toolTip" >
|
|
||||||
<string>Delete column</string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="icon" >
|
|
||||||
<iconset>../xpm/delete_attribute.png</iconset>
|
|
||||||
</property>
|
|
||||||
<property name="shortcut" >
|
|
||||||
<string>Ctrl+X</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="7" >
|
|
||||||
<widget class="QToolButton" name="btnEdit" >
|
|
||||||
<property name="toolTip" >
|
|
||||||
<string>Toggle editing mode</string>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis" >
|
|
||||||
<string>Click to toggle table editing</string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="checkable" >
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="8" >
|
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation" >
|
<property name="orientation" >
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" >
|
<property name="sizeHint" stdset="0" >
|
||||||
<size>
|
<size>
|
||||||
<width>421</width>
|
<width>421</width>
|
||||||
<height>20</height>
|
<height>20</height>
|
||||||
@ -184,17 +127,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" colspan="9" >
|
<item row="2" column="0" colspan="7" >
|
||||||
<widget class="QgsAttributeTable" native="1" name="tblAttributes" >
|
|
||||||
<property name="sizePolicy" >
|
|
||||||
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="9" >
|
|
||||||
<layout class="QHBoxLayout" >
|
<layout class="QHBoxLayout" >
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="textLabel1" >
|
<widget class="QLabel" name="textLabel1" >
|
||||||
@ -251,10 +184,36 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="9" >
|
<item row="3" column="0" colspan="7" >
|
||||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||||
<property name="standardButtons" >
|
<property name="standardButtons" >
|
||||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::NoButton</set>
|
<set>QDialogButtonBox::Close|QDialogButtonBox::Help</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="7" >
|
||||||
|
<widget class="QgsAttributeTable" native="1" name="tblAttributes" >
|
||||||
|
<property name="sizePolicy" >
|
||||||
|
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="5" >
|
||||||
|
<widget class="QToolButton" name="mToggleEditingButton" >
|
||||||
|
<property name="toolTip" >
|
||||||
|
<string>Toggle editing mode</string>
|
||||||
|
</property>
|
||||||
|
<property name="whatsThis" >
|
||||||
|
<string>Click to toggle table editing</string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="checkable" >
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -274,9 +233,6 @@
|
|||||||
<tabstop>mInvertSelectionButton</tabstop>
|
<tabstop>mInvertSelectionButton</tabstop>
|
||||||
<tabstop>mCopySelectedRowsButton</tabstop>
|
<tabstop>mCopySelectedRowsButton</tabstop>
|
||||||
<tabstop>mZoomMapToSelectedRowsButton</tabstop>
|
<tabstop>mZoomMapToSelectedRowsButton</tabstop>
|
||||||
<tabstop>mAddAttributeButton</tabstop>
|
|
||||||
<tabstop>mDeleteAttributeButton</tabstop>
|
|
||||||
<tabstop>btnEdit</tabstop>
|
|
||||||
<tabstop>mSearchText</tabstop>
|
<tabstop>mSearchText</tabstop>
|
||||||
<tabstop>mSearchColumns</tabstop>
|
<tabstop>mSearchColumns</tabstop>
|
||||||
<tabstop>mSearchButton</tabstop>
|
<tabstop>mSearchButton</tabstop>
|
||||||
|
@ -213,6 +213,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="0" colspan="2" >
|
||||||
|
<widget class="QCheckBox" name="cbxAttributeTableDocked" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Open attribute table in a dock window</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -223,8 +230,8 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" >
|
<property name="sizeHint" >
|
||||||
<size>
|
<size>
|
||||||
<width>547</width>
|
<width>577</width>
|
||||||
<height>51</height>
|
<height>21</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>552</width>
|
<width>839</width>
|
||||||
<height>600</height>
|
<height>675</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize" >
|
<property name="minimumSize" >
|
||||||
@ -19,21 +19,287 @@
|
|||||||
<string>Layer Properties</string>
|
<string>Layer Properties</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon" >
|
<property name="windowIcon" >
|
||||||
<iconset/>
|
<iconset>
|
||||||
|
<normaloff/>
|
||||||
|
</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="modal" >
|
<property name="modal" >
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" >
|
<layout class="QGridLayout" >
|
||||||
|
<item row="1" column="0" >
|
||||||
|
<layout class="QHBoxLayout" >
|
||||||
|
<property name="spacing" >
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="margin" >
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbnLoadDefaultStyle" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Restore Default Style</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbnSaveDefaultStyle" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Save As Default</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbnLoadStyle" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Load Style ...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbnSaveStyleAs" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Save Style ...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" >
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons" >
|
||||||
|
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0" >
|
||||||
<widget class="QTabWidget" name="tabWidget" >
|
<widget class="QTabWidget" name="tabWidget" >
|
||||||
|
<property name="enabled" >
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy" >
|
||||||
|
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="autoFillBackground" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<property name="tabShape" >
|
<property name="tabShape" >
|
||||||
<enum>QTabWidget::Rounded</enum>
|
<enum>QTabWidget::Rounded</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="currentIndex" >
|
<property name="currentIndex" >
|
||||||
<number>0</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab1" >
|
<widget class="QWidget" name="tab1" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>817</width>
|
||||||
|
<height>557</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<attribute name="title" >
|
||||||
|
<string>General</string>
|
||||||
|
</attribute>
|
||||||
|
<layout class="QGridLayout" >
|
||||||
|
<item row="0" column="0" >
|
||||||
|
<widget class="QGroupBox" name="indexGroupBox" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>Options</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" >
|
||||||
|
<item row="0" column="0" >
|
||||||
|
<widget class="QLabel" name="textLabel3" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Display name</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy" >
|
||||||
|
<cstring>txtDisplayName</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="2" >
|
||||||
|
<widget class="QLineEdit" name="txtDisplayName" />
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" >
|
||||||
|
<widget class="QLabel" name="textLabel2" >
|
||||||
|
<property name="toolTip" >
|
||||||
|
<string>Display field for the Identify Results dialog box</string>
|
||||||
|
</property>
|
||||||
|
<property name="whatsThis" >
|
||||||
|
<string>This sets the display field for the Identify Results dialog box</string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string>Display field</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy" >
|
||||||
|
<cstring>displayFieldComboBox</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" colspan="2" >
|
||||||
|
<widget class="QComboBox" name="displayFieldComboBox" >
|
||||||
|
<property name="whatsThis" >
|
||||||
|
<string>Use this control to set which field is placed at the top level of the Identify Results dialog box.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="3" >
|
||||||
|
<widget class="QLineEdit" name="leSpatialRefSys" >
|
||||||
|
<property name="readOnly" >
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1" >
|
||||||
|
<widget class="QPushButton" name="pbnIndex" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Create Spatial Index</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="2" >
|
||||||
|
<widget class="QPushButton" name="pbnChangeSpatialRefSys" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Change CRS</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" >
|
||||||
|
<widget class="QGroupBox" name="chkUseScaleDependentRendering" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>Use scale dependent rendering</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable" >
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" >
|
||||||
|
<property name="margin" >
|
||||||
|
<number>11</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="2" >
|
||||||
|
<widget class="QLabel" name="textLabel1_2_2" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Maximum</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy" >
|
||||||
|
<cstring>spinMaximumScale</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" >
|
||||||
|
<widget class="QLabel" name="textLabel1" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Minimum</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy" >
|
||||||
|
<cstring>spinMinimumScale</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" >
|
||||||
|
<widget class="QSpinBox" name="spinMinimumScale" >
|
||||||
|
<property name="toolTip" >
|
||||||
|
<string>Minimum scale at which this layer will be displayed. </string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum" >
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum" >
|
||||||
|
<number>100000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3" >
|
||||||
|
<widget class="QSpinBox" name="spinMaximumScale" >
|
||||||
|
<property name="toolTip" >
|
||||||
|
<string>Maximum scale at which this layer will be displayed. </string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum" >
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum" >
|
||||||
|
<number>100000000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" >
|
||||||
|
<widget class="QGroupBox" name="grpSubset" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>Subset</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" >
|
||||||
|
<property name="margin" >
|
||||||
|
<number>11</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0" colspan="2" >
|
||||||
|
<widget class="QTextEdit" name="txtSubsetSQL" >
|
||||||
|
<property name="enabled" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="acceptDrops" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="acceptRichText" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" >
|
||||||
|
<spacer>
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType" >
|
||||||
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0" >
|
||||||
|
<size>
|
||||||
|
<width>480</width>
|
||||||
|
<height>21</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1" >
|
||||||
|
<widget class="QPushButton" name="pbnQueryBuilder" >
|
||||||
|
<property name="text" >
|
||||||
|
<string>Query Builder</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab2" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>817</width>
|
||||||
|
<height>552</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy" >
|
||||||
|
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
<string>Symbology</string>
|
<string>Symbology</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@ -134,227 +400,44 @@
|
|||||||
<property name="currentIndex" >
|
<property name="currentIndex" >
|
||||||
<number>1</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="page" />
|
<widget class="QWidget" name="page" >
|
||||||
<widget class="QWidget" name="page_2" />
|
<property name="geometry" >
|
||||||
</widget>
|
<rect>
|
||||||
</item>
|
<x>0</x>
|
||||||
</layout>
|
<y>0</y>
|
||||||
</widget>
|
<width>100</width>
|
||||||
<widget class="QWidget" name="tab2" >
|
<height>30</height>
|
||||||
<attribute name="title" >
|
</rect>
|
||||||
<string>General</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QGridLayout" >
|
|
||||||
<item row="0" column="0" >
|
|
||||||
<widget class="QGroupBox" name="indexGroupBox" >
|
|
||||||
<property name="title" >
|
|
||||||
<string>Options</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" >
|
|
||||||
<item row="0" column="0" >
|
|
||||||
<widget class="QLabel" name="textLabel3" >
|
|
||||||
<property name="text" >
|
|
||||||
<string>Display name</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy" >
|
|
||||||
<cstring>txtDisplayName</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" colspan="2" >
|
|
||||||
<widget class="QLineEdit" name="txtDisplayName" />
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" >
|
|
||||||
<widget class="QLabel" name="textLabel2" >
|
|
||||||
<property name="toolTip" >
|
|
||||||
<string>Display field for the Identify Results dialog box</string>
|
|
||||||
</property>
|
|
||||||
<property name="whatsThis" >
|
|
||||||
<string>This sets the display field for the Identify Results dialog box</string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string>Display field</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy" >
|
|
||||||
<cstring>displayFieldComboBox</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" colspan="2" >
|
|
||||||
<widget class="QComboBox" name="displayFieldComboBox" >
|
|
||||||
<property name="whatsThis" >
|
|
||||||
<string>Use this control to set which field is placed at the top level of the Identify Results dialog box.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="3" >
|
|
||||||
<widget class="QLineEdit" name="leSpatialRefSys" >
|
|
||||||
<property name="readOnly" >
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1" >
|
|
||||||
<widget class="QPushButton" name="pbnIndex" >
|
|
||||||
<property name="text" >
|
|
||||||
<string>Create Spatial Index</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="2" >
|
|
||||||
<widget class="QPushButton" name="pbnChangeSpatialRefSys" >
|
|
||||||
<property name="text" >
|
|
||||||
<string>Change CRS</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" >
|
|
||||||
<widget class="QGroupBox" name="chkUseScaleDependentRendering" >
|
|
||||||
<property name="title" >
|
|
||||||
<string>Use scale dependent rendering</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable" >
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" >
|
|
||||||
<property name="leftMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin" >
|
</widget>
|
||||||
<number>11</number>
|
<widget class="QWidget" name="page_2" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>799</width>
|
||||||
|
<height>502</height>
|
||||||
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin" >
|
</widget>
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="2" >
|
|
||||||
<widget class="QLabel" name="textLabel1_2_2" >
|
|
||||||
<property name="text" >
|
|
||||||
<string>Maximum</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy" >
|
|
||||||
<cstring>spinMaximumScale</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0" >
|
|
||||||
<widget class="QLabel" name="textLabel1" >
|
|
||||||
<property name="text" >
|
|
||||||
<string>Minimum</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy" >
|
|
||||||
<cstring>spinMinimumScale</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1" >
|
|
||||||
<widget class="QSpinBox" name="spinMinimumScale" >
|
|
||||||
<property name="toolTip" >
|
|
||||||
<string>Minimum scale at which this layer will be displayed. </string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum" >
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum" >
|
|
||||||
<number>100000000</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3" >
|
|
||||||
<widget class="QSpinBox" name="spinMaximumScale" >
|
|
||||||
<property name="toolTip" >
|
|
||||||
<string>Maximum scale at which this layer will be displayed. </string>
|
|
||||||
</property>
|
|
||||||
<property name="minimum" >
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="maximum" >
|
|
||||||
<number>100000000</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" >
|
|
||||||
<widget class="QGroupBox" name="grpSubset" >
|
|
||||||
<property name="title" >
|
|
||||||
<string>Subset</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" >
|
|
||||||
<property name="leftMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<item row="0" column="0" colspan="2" >
|
|
||||||
<widget class="QTextEdit" name="txtSubsetSQL" >
|
|
||||||
<property name="enabled" >
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="acceptDrops" >
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="acceptRichText" >
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0" >
|
|
||||||
<spacer>
|
|
||||||
<property name="orientation" >
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType" >
|
|
||||||
<enum>QSizePolicy::Expanding</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" >
|
|
||||||
<size>
|
|
||||||
<width>480</width>
|
|
||||||
<height>21</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1" >
|
|
||||||
<widget class="QPushButton" name="pbnQueryBuilder" >
|
|
||||||
<property name="text" >
|
|
||||||
<string>Query Builder</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab3" >
|
<widget class="QWidget" name="tab3" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>817</width>
|
||||||
|
<height>552</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
<string>Metadata</string>
|
<string>Metadata</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" >
|
<layout class="QGridLayout" >
|
||||||
<property name="leftMargin" >
|
<property name="margin" >
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin" >
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin" >
|
|
||||||
<number>11</number>
|
<number>11</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0" >
|
||||||
@ -370,6 +453,14 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab4" >
|
<widget class="QWidget" name="tab4" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>817</width>
|
||||||
|
<height>552</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
<string>Labels</string>
|
<string>Labels</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@ -406,6 +497,14 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tab5" >
|
<widget class="QWidget" name="tab5" >
|
||||||
|
<property name="geometry" >
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>817</width>
|
||||||
|
<height>552</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
<attribute name="title" >
|
<attribute name="title" >
|
||||||
<string>Actions</string>
|
<string>Actions</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@ -428,63 +527,118 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
<widget class="QWidget" name="tab6" >
|
||||||
</item>
|
<property name="geometry" >
|
||||||
<item row="1" column="0" >
|
<rect>
|
||||||
<layout class="QHBoxLayout" >
|
<x>0</x>
|
||||||
<property name="spacing" >
|
<y>0</y>
|
||||||
<number>3</number>
|
<width>817</width>
|
||||||
</property>
|
<height>557</height>
|
||||||
<property name="leftMargin" >
|
</rect>
|
||||||
<number>1</number>
|
</property>
|
||||||
</property>
|
<attribute name="title" >
|
||||||
<property name="topMargin" >
|
<string>Attributes</string>
|
||||||
<number>1</number>
|
</attribute>
|
||||||
</property>
|
<layout class="QVBoxLayout" name="verticalLayout" >
|
||||||
<property name="rightMargin" >
|
<item>
|
||||||
<number>1</number>
|
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||||
</property>
|
<property name="sizeConstraint" >
|
||||||
<property name="bottomMargin" >
|
<enum>QLayout::SetNoConstraint</enum>
|
||||||
<number>1</number>
|
</property>
|
||||||
</property>
|
<item>
|
||||||
<item>
|
<widget class="QToolButton" name="mAddAttributeButton" >
|
||||||
<widget class="QPushButton" name="pbnLoadDefaultStyle" >
|
<property name="sizePolicy" >
|
||||||
<property name="text" >
|
<sizepolicy vsizetype="Fixed" hsizetype="Fixed" >
|
||||||
<string>Restore Default Style</string>
|
<horstretch>0</horstretch>
|
||||||
</property>
|
<verstretch>0</verstretch>
|
||||||
</widget>
|
</sizepolicy>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
<property name="toolTip" >
|
||||||
<widget class="QPushButton" name="pbnSaveDefaultStyle" >
|
<string>New column</string>
|
||||||
<property name="text" >
|
</property>
|
||||||
<string>Save As Default</string>
|
<property name="text" >
|
||||||
</property>
|
<string/>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
<property name="icon" >
|
||||||
<item>
|
<iconset>
|
||||||
<widget class="QPushButton" name="pbnLoadStyle" >
|
<normaloff>../xpm/new_attribute.png</normaloff>../xpm/new_attribute.png</iconset>
|
||||||
<property name="text" >
|
</property>
|
||||||
<string>Load Style ...</string>
|
<property name="shortcut" >
|
||||||
</property>
|
<string>Ctrl+N</string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
</widget>
|
||||||
<item>
|
</item>
|
||||||
<widget class="QPushButton" name="pbnSaveStyleAs" >
|
<item>
|
||||||
<property name="text" >
|
<widget class="QToolButton" name="mDeleteAttributeButton" >
|
||||||
<string>Save Style ...</string>
|
<property name="toolTip" >
|
||||||
</property>
|
<string>Delete column</string>
|
||||||
</widget>
|
</property>
|
||||||
</item>
|
<property name="text" >
|
||||||
</layout>
|
<string/>
|
||||||
</item>
|
</property>
|
||||||
<item row="3" column="0" >
|
<property name="icon" >
|
||||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
<iconset>
|
||||||
<property name="orientation" >
|
<normaloff>../xpm/delete_attribute.png</normaloff>../xpm/delete_attribute.png</iconset>
|
||||||
<enum>Qt::Horizontal</enum>
|
</property>
|
||||||
</property>
|
<property name="shortcut" >
|
||||||
<property name="standardButtons" >
|
<string>Ctrl+X</string>
|
||||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="mToggleEditingButton" >
|
||||||
|
<property name="toolTip" >
|
||||||
|
<string>Toggle editing mode</string>
|
||||||
|
</property>
|
||||||
|
<property name="whatsThis" >
|
||||||
|
<string>Click to toggle table editing</string>
|
||||||
|
</property>
|
||||||
|
<property name="text" >
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="checkable" >
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer" >
|
||||||
|
<property name="orientation" >
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0" >
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableWidget" name="tblAttributes" >
|
||||||
|
<property name="sizePolicy" >
|
||||||
|
<sizepolicy vsizetype="Expanding" hsizetype="Expanding" >
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize" >
|
||||||
|
<size>
|
||||||
|
<width>256</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled" >
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<zorder>tblAttributes</zorder>
|
||||||
|
<zorder></zorder>
|
||||||
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user