一、QgsDataSourceUri 核心定位与作用
QgsDataSourceUri 是 QGIS C++ 核心库(qgis_core)中的核心类,专门用于标准化构建、解析、修改各类地理空间数据源的连接信息(URI) 。它解决了手动拼接 URI 字符串易出错、不同数据源格式不统一、特殊字符处理复杂等问题,为 PostGIS、GeoPackage、Shapefile、XYZ 瓦片、WMS/WFS 等几乎所有 QGIS 支持的数据源提供统一的结构化操作接口。
核心价值:
- 统一接口:无论数据源类型(数据库/文件/网络瓦片),均通过相同的类方法管理连接参数,无需记忆不同数据源的 URI 格式。
- 结构化参数管理:将 URI 拆解为「键值对」或「数据库专用参数」(主机、端口、表名等),支持精准读写/修改单个参数。
- 自动转义特殊字符 :自动处理密码、表名、字段名中的空格、
@、&、中文等特殊字符,避免连接失败。 - 双向转换:支持「对象 → URI 字符串」(生成可用的连接字符串)和「URI 字符串 → 对象」(解析现有连接信息)。
- 数据源适配:内置针对数据库(PostGIS)、文件(Shapefile)、网络瓦片(XYZ)等的专用方法,简化高频操作。
二、核心常用方法(C++)
先梳理最常用的成员函数,按使用场景分类:
| 方法分类 | 关键方法 | 作用 |
|---|---|---|
| 通用参数操作 | setParam(const QString &key, const QString &value) |
设置通用键值对参数(如 XYZ 瓦片的 type、url) |
QString param(const QString &key) const |
获取指定键的参数值 | |
removeParam(const QString &key) |
删除指定参数 | |
QString uri() const |
生成最终的 URI 字符串(核心方法,供图层加载使用) | |
void setEncodedUri(const QString &uri) |
解析现有 URI 字符串到对象中 | |
| 数据库专用 | void setConnection(const QString &host, const QString &port, const QString &db, const QString &user, const QString &password) |
快速设置 PostGIS/SpatiLite 数据库连接基础参数 |
void setSchema(const QString &schema) |
设置数据库模式(PostGIS 的 schema,如 public) |
|
void setTable(const QString &table) |
设置数据库表名 | |
void setWhereClause(const QString &where) |
设置筛选条件(SQL WHERE 子句) | |
| 文件数据源专用 | void setPath(const QString &path) |
设置文件路径(Shapefile/GeoPackage 等) |
void setFileName(const QString &fileName) |
兼容部分文件数据源的文件名设置 |
三、完整 C++ 代码示例(覆盖主流场景)
前置条件:
-
编译环境需链接 QGIS 核心库(
qgis_core),包含头文件:cpp#include <QgsDataSourceUri.h> #include <QgsRasterLayer.h> #include <QgsVectorLayer.h> #include <QgsProject.h> #include <QDebug> -
运行环境需配置 QGIS 依赖(如
QGIS_PREFIX_PATH)。
示例 1:PostGIS 矢量数据源(最常用)
cpp
// 1. 创建 QgsDataSourceUri 对象
QgsDataSourceUri uri;
// 2. 设置 PostGIS 数据库基础连接参数
uri.setConnection("127.0.0.1", // 主机地址
"5432", // 端口
"gis_db", // 数据库名
"postgres", // 用户名
"123456" // 密码
);
// 3. 设置图层专用参数
uri.setSchema("public"); // 数据库模式
uri.setTable("city"); // 表名
uri.setGeometryColumn("geom"); // 几何字段名
uri.setSrid("4326"); // 坐标系 EPSG 码
uri.setWhereClause("pop > 100000"); // 筛选条件(只加载人口>10万的城市)
// 4. 生成 URI 字符串并创建矢量图层
QString uriStr = uri.uri();
qDebug() << "PostGIS URI:" << uriStr;
// 5. 加载图层到项目
QgsVectorLayer *layer = new QgsVectorLayer(uriStr, "城市数据", "postgres");
if (layer->isValid()) {
QgsProject::instance()->addMapLayer(layer);
qDebug() << "PostGIS 图层加载成功";
} else {
qDebug() << "PostGIS 图层无效:" << layer->error().message();
}
示例 2:XYZ 瓦片栅格数据源
cpp
// 1. 创建 URI 对象
QgsDataSourceUri uri;
// 2. 设置 XYZ 瓦片核心参数(键值对形式)
uri.setParam("type", "xyz"); // 必须:声明为 XYZ 类型
uri.setParam("url", "https://tile.openstreetmap.org/{z}/{x}/{y}.png"); // 瓦片 URL 模板
uri.setParam("zmin", "0"); // 最小缩放级别
uri.setParam("zmax", "19"); // 最大缩放级别
uri.setParam("crs", "EPSG:3857"); // 坐标系(默认 Web 墨卡托)
uri.setParam("referer", "https://your-app.com"); // 可选:设置 Referer 防盗链
// 3. 生成 URI 字符串并创建栅格图层
QString uriStr = uri.encodedUri();
qDebug() << "XYZ 瓦片 URI:" << uriStr;
// 4. 加载图层(注意 providerKey 固定为 "wms")
QgsRasterLayer *layer = new QgsRasterLayer(uriStr, "OpenStreetMap 瓦片", "wms");
if (layer->isValid()) {
QgsProject::instance()->addMapLayer(layer);
qDebug() << "XYZ 瓦片图层加载成功";
} else {
qDebug() << "XYZ 瓦片图层无效:" << layer->error().message();
}
示例 3:GeoPackage 数据源(文件型主流格式)
cpp
// 1. 创建 URI 对象
QgsDataSourceUri uri;
// 2. 设置 GeoPackage 文件路径和图层名
uri.setPath("/home/user/mapdata.gpkg"); // GeoPackage 文件完整路径
uri.setParam("layername", "road"); // 要加载的图层名
// 3. 生成 URI 字符串并创建图层
QString uriStr = uri.uri();
qDebug() << "GeoPackage URI:" << uriStr;
QgsVectorLayer *layer = new QgsVectorLayer(uriStr, "道路数据", "ogr");
if (layer->isValid()) {
QgsProject::instance()->addMapLayer(layer);
qDebug() << "GeoPackage 图层加载成功";
} else {
qDebug() << "GeoPackage 图层无效:" << layer->error().message();
}
示例 4:解析现有 URI 字符串(反向操作)
cpp
// 已有 PostGIS URI 字符串(比如从 QGIS 项目文件中读取)
QString existingUri = "dbname='gis_db' host=127.0.0.1 port=5432 user='postgres' password='123456' table=\"public\".\"city\" (geom) srid=4326 where=\"pop > 100000\"";
// 1. 创建 URI 对象并解析字符串
QgsDataSourceUri uri;
uri.setEncodedUri(existingUri);
// 2. 读取解析后的参数
qDebug() << "数据库名:" << uri.database();
qDebug() << "表名:" << uri.table();
qDebug() << "筛选条件:" << uri.whereClause();
qDebug() << "几何字段:" << uri.geometryColumn();
// 3. 修改参数(比如移除筛选条件)
uri.setWhereClause("");
qDebug() << "修改后的 URI:" << uri.uri();
四、关键注意事项
- Provider Key 匹配 :创建图层时,
providerKey必须与数据源类型匹配(如 PostGIS 用"postgres"、XYZ 瓦片用"wms"、GeoPackage/Shapefile 用"ogr")。 - 特殊字符处理 :无需手动转义密码/表名中的特殊字符,
QgsDataSourceUri的setParam/setConnection会自动处理。 - 路径格式 :文件型数据源(Shapefile/GeoPackage)需使用绝对路径,且路径分隔符用
/(跨平台兼容)。 - QGIS 版本兼容 :上述方法适用于 QGIS 3.x 系列(主流版本),QGIS 2.x 部分方法命名略有差异(如
setConnection参数顺序)。
总结
QgsDataSourceUri是 QGIS 中管理数据源连接信息的「标准化工具」,核心解决 URI 拼接/解析的复杂度问题,支持所有主流地理空间数据源。- 核心用法分两类:通用参数用
setParam/param操作,数据库专用参数用setConnection/setTable等专用方法,最终通过uri()生成可用的连接字符串。 - C++ 中使用时需注意「Provider Key 匹配」和「QGIS 库链接」,不同数据源的 URI 构建逻辑虽有差异,但通过该类可实现统一接口管理。