以TestProvider为例:
要实现DataProvider的基本功能,需要继承4个父类:
- QgsProviderMetadata
QgsProviderRegistry内部以Map结构保存了QgsProvideMetadata的子类实例,每个实例关联了一个DataProvider插件。QgsProviderMetadata保存了DataProvider的key和description,提供了createProvider()接口创建DataProvider对象,同时还有encodeUri()、decodeUri()接口用于生成和解析uri字符串。 - QgsVectorDataProvider
QgsVectorDataProvider为DataProvider的主要实现。如获取属性字段、获取坐标参考系、读取数据等。 - QgsAbstractFeatureSource
QgsAbstractFeatureSource保存要素的基本信息。 - QgsAbstractFeatureIteratorFromSource<T>
QgsAbstractFeatureIteratorFromSource实现了对要素一些访问操作。
1. 新建QgsTestProviderMetadata类继承QgsProviderMetadata
class QgsTestProviderMetadata final: public QgsProviderMetadata
{
public:
QgsSDEProviderMetadata();
QgsDataProvider *createProvider( const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ) override;
QVariantMap decodeUri( const QString &uri ) const override;
QString encodeUri( const QVariantMap &parts ) const override;
void initProvider() override;
};
1.1 基础函数实现
1.1.1 重载函数
1) createProvider()
virtual QgsDataProvider *createProvider( const QString &uri,
const QgsDataProvider::ProviderOptions &options,
QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() ) SIP_FACTORY;
createProvider()用以创建一个dataprovider实例,实现函数时new一个自定义的dataprovider对象,然后返回即可
QgsDataProvider *QgsTestProviderMetadata::createProvider(const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags)
{
return new QgsTestProvider( uri, options, flags );
}
2) decodeUri()
virtual QVariantMap decodeUri( const QString &uri ) const;
decodeUri()解析uri字符串,并以map结构返回解析后的数据,QGis提供了QgsDataSourceUri类,某些情况下可以直接使用QgsDataSourceUri类解析和生成uri字符串,省去了自己解析字符串的操作。参考postgresprovider的uri: dbname='sdetest' host=127.0.0.1 port=5432 user='sde' password='123' table="sde"."testlayer" (shape)。如果不用QgsDataSourceUri类,也可自定义字符串格式并自行解析。
QVariantMap QgsTestProviderMetadata::decodeUri(const QString &uri) const
{
const QgsDataSourceUri dsUri{ uri };
QVariantMap uriParts;
if (!dsUri.database().isEmpty())
uriParts[QStringLiteral("dbname")] = dsUri.database();
if (!dsUri.host().isEmpty())
uriParts[QStringLiteral("host")] = dsUri.host();
return uriParts;
}
3) encodeUri()
virtual QString encodeUri( const QVariantMap &parts ) const;
同理,encodeUri的实现也可以借助QgsDataSourceUri类生成uri字符串。
QString QgsTestProviderMetadata::encodeUri(const QVariantMap &parts) const
{
QgsDataSourceUri dsUri;
if (parts.contains(QStringLiteral("dbname")))
dsUri.setDatabase(parts.value(QStringLiteral("dbname")).toString());
if (parts.contains(QStringLiteral("port")))
dsUri.setParam(QStringLiteral("port"), parts.value(QStringLiteral("port")).toString());
return dsUri.uri(false);
}
4) initProvider()
void initProvider() override;
2. 新建QgsTestProvider类继承QgsVectorDataProvider
class QgsTestProvider final: public QgsVectorDataProvider
{
friend class QgsTestFeatureSource;
Q_OBJECT
public:
explicit QgsTestProvider( QString const &uri, const QgsDataProvider::ProviderOptions &providerOptions,
QgsDataProvider::ReadFlags flags = QgsDataProvider::ReadFlags() );
~QgsTestProvider();
virtual QgsAbstractFeatureSource *featureSource() const override;
QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) const override;
QgsWkbTypes::Type wkbType() const override;
long long featureCount() const override;
QgsFields fields() const override;
QgsCoordinateReferenceSystem crs() const override;
QgsRectangle extent() const override;
bool isValid() const override;
QString name() const override;
QString description() const override;
private:
/**
* Flag indicating if the layer data source is a valid PostgreSQL layer
*/
bool mValid = false;
QgsWkbTypes::Type mWkbType;
QgsFields mAttributeFieds;
QgsRectangle mExtent;
QList<QgsFeature> mFeatures;
};
QgsTestProvider重载QgsVectorDataProvider的纯虚函数:
- featureSource()
- getFeatures()
- wkbType()
- featureCount()
- fields()
重载QgsDataProvider的纯虚函数:
- crs()
- extent()
- isValid()
- name()
- description()
2.1 基础函数实现
2.1.1 实现QgsVectorDataProvider的纯虚函数
1) featureSource()
virtual QgsAbstractFeatureSource *featureSource() const = 0 SIP_FACTORY;
featureSource()返回自定义的QgsTestFeatureSource对象即可,QgsTestFeatureSource继承自QgsAbstractFeatureSource
QgsAbstractFeatureSource *QgsTestProvider::featureSource() const
{
return new QgsTestFeatureSource( this );
}
2) getFeatures()
QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) const override = 0;
getFeatures()返回一个迭代器,通过该迭代器遍历features,同样也需要新建类QgsTestFeatureIterator继承自QgsAbstractFeatureIteratorFromSource<QgsTestFeatureSource>
QgsFeatureIterator QgsTestProvider::getFeatures( const QgsFeatureRequest &request ) const
{
QgsTestFeatureSource *featureSrc = static_cast<QgsTestFeatureSource *>( featureSource() );
return QgsFeatureIterator( new QgsTestFeatureIterator( featureSrc, true, request ) );
}
3) wkbType()
QgsWkbTypes::Type wkbType() const override = 0;
wkbType()返回feature的类型,该类型为qgswkbtypes.h中QgsWkbTypes::Type枚举。在自定义Provider中定义一个私有变量存放该类型,则返回该变量值即可。
QgsWkbTypes::Type QgsTestProvider::wkbType() const
{
return mWkbType;
}
4) featureCount()
long long featureCount() const override = 0;
返回要素数量。
5) fields()
QgsFields fields() const override = 0;
fields()返回属性字段,QGis提供了一个QgsFields类去储存属性字段,可以在provider内定义一个该类对象为成员变量,fields()直接返回该对象即可
QgsFields mAttributeFields;
QgsFields QgsTestProvider::fields() const
{
return mAttributeFields;
}
QgsFields提供append函数添加属性字段,每个字段的具体数据由QgsField对象持有。
QgsField f1;
f1.setName(QStringLiteral("name"));
f1.setType(QVariant::Int);
f1.setTypeName(QStringLiteral("typename"));
f1.setLength(5);
f1.setPrecision(1);
f1.setComment(QStringLiteral("comment"));
mAttributeFieds.append(f1);
2.1.2 还有一部分是QgsDataProvider的纯虚函数需要实现
1) crs()
virtual QgsCoordinateReferenceSystem crs() const = 0;
crs()返回坐标参考系
2) extent()
virtual QgsRectangle extent() const = 0;
extent()返回图层的范围,将读取到的数据以QgsRectangle对象返回,这里以一个成员变量mExtent储存数据。
QgsRectangle QgsTestProvider::extent() const
{
//mExtent.setXMinimum(97.3475);
//mExtent.setXMaximum(108.543);
//mExtent.setYMinimum(26.0482);
//mExtent.setYMaximum(34.3152);
return mExtent;
}
3) isValid()
virtual bool isValid() const = 0;
isValid()返回该图层是否有效。返回自定义的成员变量即可
bool QgsTestProvider::isValid() const
{
return mValid;
}
4) name()
virtual QString name() const = 0;
name()返回provider的key
QString QgsTestProvider::name() const
{
return TEXT_PROVIDER_KEY;
}
5) description()
virtual QString description() const = 0;
description()返回provider描述
QString QgsTestProvider::description() const
{
return TEXT_PROVIDER_DESCRIPTION;
}
2.1.3 重载函数
3. 新建QgsTestFeatureSource类继承QgsAbstractFeatureSource
class QgsTestFeatureSource final: public QgsAbstractFeatureSource
{};
3.1 基础函数实现
3.1.1 实现QgsAbstractFeatureSource的纯虚函数
1) getFeatures()
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest &request = QgsFeatureRequest() ) = 0 SIP_TRANSFERBACK;
getFeatures()返回QgsFeatureIterator对象, 通过QgsFeatureIterator( QgsAbstractFeatureIterator *iter SIP_TRANSFER )构造函数创建一个有效的迭代器,构造函数实参传入自定义的FeatureIterator。
QgsFeatureIterator QgsTestFeatureSource::getFeatures( const QgsFeatureRequest &request )
{
return QgsFeatureIterator( new QgsTestFeatureIterator( this, false, request ) );
}
4. 新建QgsTestFeatureIterator类继承QgsAbstractFeatureIteratorFromSource<QgsSDEFeatureSource>
4.1 基础函数实现
4.1.1 实现QgsAbstractFeatureIterator的纯虚函数
1) rewind()
virtual bool rewind() = 0;
rewind()将迭代器重置到起始位置,在QgsTestFeatureIterator中定义成员变量mIterator用以遍历feature,mIterator类型可以根据储存feature的数据结构确定,以QList为例,则定义为:QList<QgsFeature>::iterator mIterator;
mClosed变量为父类QgsAbstractFeatureIterator的成员变量,当迭代器关闭时,该变量应置为true。
bool QgsTestFeatureIterator::rewind()
{
if (mClosed)
{
return false;
}
mIterator = mSource->mFeatures.begin();
return true;
}
2) close()
virtual bool close() = 0;
close()用以关闭迭代器,函数体内直接调用父类QgsAbstractFeatureIteratorFromSource的iteratorClosed()即可
bool QgsTestFeatureIterator::close()
{
if (mClosed)
{
return false;
}
iteratorClosed();
return true;
}
查看QgsAbstractFeatureIteratorFromSource::iteratorClosed()源码可知,其也是直接调用QgsAbstractFeatureSource的iteratorClosed()函数
template<typename T>
class QgsAbstractFeatureIteratorFromSource : public QgsAbstractFeatureIterator
{
......
protected:
//! to be called by from subclass in close()
void iteratorClosed() { mSource->iteratorClosed( this ); }
......
};
3) fetchFeature()
protected:
virtual bool fetchFeature( QgsFeature &f ) = 0;
fetchFeature()获取下一个feature,内部实现也是通过mIterator迭代,将获得的feature赋值给形参feature。
bool QgsTestFeatureIterator::fetchFeature(QgsFeature &feature)
{
if (mClosed)
{
return false;
}
if (mIterator != mSource->mFeatures.end())
{
feature = *mIterator;
mIterator++;
return true;
}
else
{
close();
return false;
}
}
网友评论