[DBManager] Integrate QSpatialite's query builder

This commit is contained in:
Hugo Mercier 2015-03-30 15:31:19 +02:00
parent d684c8c749
commit 4876e7a2be
16 changed files with 1232 additions and 138 deletions

View File

@ -1894,6 +1894,69 @@ Colonnes</translation>
<translation>Éviter la sélection par l&apos;id de lentité</translation>
</message>
</context>
<context>
<name>DbManagerQueryBuilderDlg</name>
<message>
<source>SQL query builder</source>
<translation>Constructeur de requête SQL</translation>
</message>
<message>
<source>Data</source>
<translation>Données</translation>
</message>
<message>
<source>Columns' values</source>
<translation>Valeurs</translation>
</message>
<message>
<source>Spatial index</source>
<translation>Index spatial</translation>
</message>
<message>
<source>Columns</source>
<translation>Colonnes</translation>
</message>
<message>
<source>Aggregates</source>
<translation>Agrégats</translation>
</message>
<message>
<source>Functions</source>
<translation>Fonctions</translation>
</message>
<message>
<source>String functions</source>
<translation>Fonctions sur les chaînes</translation>
</message>
<message>
<source>Operators</source>
<translation>Opérateurs</translation>
</message>
<message>
<source>Only 10 first values</source>
<translation>Seulement les 10 premières</translation>
</message>
<message>
<source>&amp;Reset</source>
<translation>Effacer</translation>
</message>
<message>
<source>Table (with spatial index)</source>
<translation>Table (avec index spatial)</translation>
</message>
<message>
<source>Table (Target)</source>
<translation>Table (cible)</translation>
</message>
<message>
<source>Use spatial index</source>
<translation>Utiliser index spatial</translation>
</message>
<message>
<source>Show system tables</source>
<translation>Montrer les tables système</translation>
</message>
</context>
<context>
<name>DbManagerDlgTableProperties</name>
<message>

View File

@ -223,3 +223,7 @@ class DBConnector:
return getSqlDictionary()
except ImportError:
return []
def getQueryBuilderDictionary(self):
return {}

View File

@ -208,6 +208,12 @@ class Database(DbItemObject):
return SqlResultModel(self, sql, parent)
def columnUniqueValuesModel( self, col, table, limit = 10 ):
l = ""
if limit is not None:
l = "LIMIT %d" % limit
return self.sqlResultModel( "SELECT DISTINCT %s FROM %s %s" % (col, table, l), self)
def uniqueIdFunction(self):
"""Return a SQL function used to generate a unique id for rows of a query"""
# may be overloaded by derived classes
@ -456,8 +462,8 @@ class Database(DbItemObject):
def rasterTablesFactory(self, row, db, schema=None):
return None
def tables(self, schema=None):
tables = self.connector.getTables(schema.name if schema else None)
def tables(self, schema=None, sys_tables=False):
tables = self.connector.getTables(schema.name if schema else None, sys_tables)
if tables is not None:
tables = map(lambda x: self.tablesFactory(x, self, schema), tables)
return tables
@ -494,6 +500,12 @@ class Database(DbItemObject):
self.refresh()
return True
def explicitSpatialIndex( self ):
return False
def spatialIndexClause( self, src_table, src_column, dest_table, dest_table_column ):
return None
class Schema(DbItemObject):
def __init__(self, db):
@ -554,6 +566,9 @@ class Table(DbItemObject):
def __del__(self):
pass # print "Table.__del__", self
def canBeAddedToCanvas( self ):
return True
def database(self):
return self.parent()

View File

@ -231,7 +231,7 @@ class PostGisDBConnector(DBConnector):
self._close_cursor(c)
return res
def getTables(self, schema=None):
def getTables(self, schema=None, add_sys_tables=False):
""" get list of tables """
tablenames = []
items = []
@ -242,7 +242,7 @@ class PostGisDBConnector(DBConnector):
try:
vectors = self.getVectorTables(schema)
for tbl in vectors:
if tbl[1] in sys_tables and tbl[2] in ['', 'public']:
if not add_sys_tables and tbl[1] in sys_tables and tbl[2] in ['', 'public']:
continue
tablenames.append((tbl[2], tbl[1]))
items.append(tbl)
@ -252,7 +252,7 @@ class PostGisDBConnector(DBConnector):
try:
rasters = self.getRasterTables(schema)
for tbl in rasters:
if tbl[1] in sys_tables and tbl[2] in ['', 'public']:
if not add_sys_tables and tbl[1] in sys_tables and tbl[2] in ['', 'public']:
continue
tablenames.append((tbl[2], tbl[1]))
items.append(tbl)
@ -988,3 +988,9 @@ UNION SELECT attname FROM pg_attribute WHERE attnum > 0"""
sql_dict["identifier"] = items
return sql_dict
def getQueryBuilderDictionary(self):
from .sql_dictionary import getQueryBuilderDictionary
return getQueryBuilderDictionary()

View File

@ -93,75 +93,88 @@ postgis_keywords = []
# functions
functions = [
# TODO get them from a reference page
"abs", "changes", "coalesce", "glob", "ifnull", "hex", "last_insert_rowid",
"length", "like", "lower", "ltrim", "max", "min", "nullif", "quote", "random",
"randomblob", "replace", "round", "rtrim", "soundex", "total_change", "trim",
"typeof", "upper", "zeroblob", "date", "datetime", "julianday", "strftime",
"avg", "count", "group_concat", "sum", "total"
"coalesce",
"nullif", "quote", "random",
"replace", "soundex"
]
operators=[
' AND ',' OR ','||',' < ',' <= ',' > ',' >= ',' = ',' <> ',' IS ',' IS NOT ',' IN ',' LIKE ',' GLOB ',' MATCH ',' REGEXP '
]
math_functions = [
# SQL math functions
"Abs", "ACos", "ASin", "ATan", "Cos", "Cot", "Degrees", "Exp", "Floor", "Log", "Log2",
"Log10", "Pi", "Radians", "Round", "Sign", "Sin", "Sqrt", "StdDev_Pop", "StdDev_Samp", "Tan",
"Var_Pop", "Var_Samp" ]
string_functions=["Length", "Lower", "Upper", "Like", "Trim", "LTrim", "RTrim", "Replace", "Substr"]
aggregate_functions=[
"Max","Min","Avg","Count","Sum","Group_Concat","Total","Var_Pop","Var_Samp","StdDev_Pop","StdDev_Samp"
]
postgis_functions = [ # from http://www.postgis.org/docs/reference.html
# 7.1. PostgreSQL PostGIS Types
"box2d", "box3d", "box3d_extent", "geometry", "geometry_dump", "geography",
"*box2d", "*box3d", "*box3d_extent", "*geometry", "*geometry_dump", "*geography",
# 7.2. Management Functions
"addgeometrycolumn", "dropgeometrycolumn", "dropgeometrytable", "postgis_full_version",
"postgis_geos_version", "postgis_libxml_version", "postgis_lib_build_date",
"postgis_lib_version", "postgis_proj_version", "postgis_scripts_build_date",
"postgis_scripts_installed", "postgis_scripts_released", "postgis_uses_stats", "postgis_version",
"populate_geometry_columns", "probe_geometry_columns", "updategeometrysrid",
"*addgeometrycolumn", "*dropgeometrycolumn", "*dropgeometrytable", "*postgis_full_version",
"*postgis_geos_version", "*postgis_libxml_version", "*postgis_lib_build_date",
"*postgis_lib_version", "*postgis_proj_version", "*postgis_scripts_build_date",
"*postgis_scripts_installed", "*postgis_scripts_released", "*postgis_uses_stats", "*postgis_version",
"*populate_geometry_columns", "*probe_geometry_columns", "*updategeometrysrid",
# 7.3. Geometry Constructors
"st_bdpolyfromtext", "st_bdmpolyfromtext", "st_geogfromtext", "st_geographyfromtext",
"st_geogfromwkb", "st_geomcollfromtext", "st_geomfromewkb", "st_geomfromewkt",
"st_geometryfromtext", "st_geomfromgml", "st_geomfromkml", "st_gmltosql", "st_geomfromtext",
"st_geomfromwkb", "st_linefrommultipoint", "st_linefromtext", "st_linefromwkb",
"st_linestringfromwkb", "st_makebox2d", "st_makebox3d", "st_makeline", "st_makeenvelope",
"st_makepolygon", "st_makepoint", "st_makepointm", "st_mlinefromtext", "st_mpointfromtext",
"st_mpolyfromtext", "st_point", "st_pointfromtext", "st_pointfromwkb", "st_polygon",
"st_polygonfromtext", "st_wkbtosql", "st_wkttosql",
"*ST_bdpolyfromtext", "*ST_bdmpolyfromtext", "*ST_geogfromtext", "*ST_geographyfromtext",
"*ST_geogfromwkb", "*ST_geomcollfromtext", "*ST_geomfromewkb", "*ST_geomfromewkt",
"*ST_geometryfromtext", "*ST_geomfromgml", "*ST_geomfromkml", "*ST_gmltosql", "*ST_geomfromtext",
"*ST_geomfromwkb", "*ST_linefrommultipoint", "*ST_linefromtext", "*ST_linefromwkb",
"*ST_linestringfromwkb", "*ST_makebox2d", "*ST_makebox3d", "ST_MakeLine", "*ST_makeenvelope",
"ST_MakePolygon", "ST_MakePoint", "ST_MakePointM", "*ST_MLinefromtext", "*ST_mpointfromtext",
"*ST_mpolyfromtext", "ST_Point", "*ST_pointfromtext", "*ST_pointfromwkb", "ST_Polygon",
"*ST_polygonfromtext", "*ST_wkbtosql", "*ST_wkttosql",
# 7.4. Geometry Accessors
"geometrytype", "st_boundary", "st_coorddim", "st_dimension", "st_endpoint", "st_envelope",
"st_exteriorring", "st_geometryn", "st_geometrytype", "st_interiorringn", "st_isclosed",
"st_isempty", "st_isring", "st_issimple", "st_isvalid", "st_isvalidreason", "st_m", "st_ndims",
"st_npoints", "st_nrings", "st_numgeometries", "st_numinteriorrings", "st_numinteriorring",
"st_numpoints", "st_pointn", "st_srid", "st_startpoint", "st_summary", "st_x", "st_y", "st_z",
"st_zmflag",
"GeometryType", "ST_Boundary", "*ST_coorddim", "ST_Dimension", "ST_EndPoint", "ST_Envelope",
"ST_ExteriorRing", "ST_GeometryN", "ST_GeometryType", "ST_InteriorRingN", "ST_isClosed",
"ST_isEmpty", "ST_isRing", "ST_isSimple", "ST_isValid", "ST_isValidReason", "ST_M", "ST_NDims",
"ST_NPoints", "ST_NRings", "ST_NumGeometries", "ST_NumInteriorrings", "ST_NumInteriorring",
"ST_NumPoints", "ST_PointN", "ST_Srid", "ST_StartPoint", "ST_Summary", "ST_X", "ST_Y", "ST_Z",
"*ST_zmflag",
# 7.5. Geometry Editors
"st_addpoint", "st_affine", "st_force_2d", "st_force_3d", "st_force_3dz", "st_force_3dm",
"st_force_4d", "st_force_collection", "st_forcerhr", "st_linemerge", "st_collectionextract",
"st_multi", "st_removepoint", "st_reverse", "st_rotate", "st_rotatex", "st_rotatey",
"st_rotatez", "st_scale", "st_segmentize", "st_setpoint", "st_setsrid", "st_snaptogrid",
"st_transform", "st_translate", "st_transscale",
"ST_AddPoint", "ST_Affine", "ST_Force2D", "*ST_Force3D", "*ST_Force3dZ", "*ST_Force3DM",
"*ST_Force_4d", "*ST_force_collection", "*ST_forcerhr", "*ST_linemerge", "*ST_collectionextract",
"ST_Multi", "*ST_removepoint", "*ST_reverse", "*ST_rotate", "*ST_rotatex", "*ST_rotatey",
"*ST_rotatez", "*ST_scale", "*ST_segmentize", "*ST_setpoint", "ST_SetSrid", "ST_SnapToGrid",
"ST_Transform", "ST_Translate", "*ST_transscale",
# 7.6. Geometry Outputs
"st_asbinary", "st_asewkb", "st_asewkt", "st_asgeojson", "st_asgml", "st_ashexewkb", "st_askml",
"st_assvg", "st_geohash", "st_astext",
"*ST_asbinary", "*ST_asewkb", "*ST_asewkt", "*ST_asgeojson", "*ST_asgml", "*ST_ashexewkb", "*ST_askml",
"*ST_assvg", "*ST_geohash", "ST_Astext",
# 7.7. Operators
# 7.8. Spatial Relationships and Measurements
"st_area", "st_azimuth", "st_centroid", "st_closestpoint", "st_contains", "st_containsproperly",
"st_covers", "st_coveredby", "st_crosses", "st_linecrossingdirection", "st_disjoint",
"st_distance", "st_hausdorffdistance", "st_maxdistance", "st_distance_sphere",
"st_distance_spheroid", "st_dfullywithin", "st_dwithin", "st_equals", "st_hasarc",
"st_intersects", "st_length", "st_length2d", "st_length3d", "st_length_spheroid",
"st_length2d_spheroid", "st_length3d_spheroid", "st_longestline", "st_orderingequals",
"st_overlaps", "st_perimeter", "st_perimeter2d", "st_perimeter3d", "st_pointonsurface",
"st_relate", "st_shortestline", "st_touches", "st_within",
"ST_Area", "ST_Azimuth", "ST_Centroid", "ST_ClosestPoint", "ST_Contains", "ST_ContainsProperly",
"ST_Covers", "ST_CoveredBy", "ST_Crosses", "*ST_linecrossingdirection", "ST_Cisjoint",
"ST_Distance", "*ST_hausdorffdistance", "*ST_maxdistance", "ST_Distance_Sphere",
"ST_Distance_Spheroid", "*ST_DFullyWithin", "ST_DWithin", "ST_Equals", "*ST_hasarc",
"ST_Intersects", "ST_Length", "*ST_Length2d", "*ST_length3d", "ST_Length_Spheroid",
"*ST_length2d_spheroid", "*ST_length3d_spheroid", "*ST_longestline", "*ST_orderingequals",
"ST_Overlaps", "*ST_perimeter", "*ST_perimeter2d", "*ST_perimeter3d", "ST_PointOnSurface",
"ST_Relate", "ST_ShortestLine", "ST_Touches", "ST_Within",
# 7.9. Geometry Processing Functions
"st_buffer", "st_buildarea", "st_collect", "st_convexhull", "st_curvetoline", "st_difference",
"st_dump", "st_dumppoints", "st_dumprings", "st_intersection", "st_linetocurve", "st_memunion",
"st_minimumboundingcircle", "st_polygonize", "st_shift_longitude", "st_simplify",
"st_simplifypreservetopology", "st_symdifference", "st_union",
"ST_Buffer", "ST_BuildArea", "ST_Collect", "ST_ConvexHull", "*ST_curvetoline", "ST_Difference",
"ST_Dump", "*ST_dumppoints", "*ST_dumprings", "ST_Intersection", "*ST_linetocurve", "*ST_memunion",
"*ST_minimumboundingcircle", "*ST_polygonize", "*ST_shift_longitude", "ST_Simplify",
"ST_SimplifyPreserveTopology", "ST_SymDifference", "ST_Union",
# 7.10. Linear Referencing
"st_line_interpolate_point", "st_line_locate_point", "st_line_substring",
"st_locate_along_measure", "st_locate_between_measures", "st_locatebetweenelevations",
"st_addmeasure",
"ST_Line_Interpolate_Point", "ST_Line_Locate_Point", "ST_Line_Substring",
"*ST_locate_along_measure", "*ST_locate_between_measures", "*ST_locatebetweenelevations",
"*ST_addmeasure",
# 7.11. Long Transactions Support
"addauth", "checkauth", "disablelongtransactions", "enablelongtransactions", "lockrow",
"unlockrows",
"*addauth", "*checkauth", "*disablelongtransactions", "*enablelongtransactions", "*lockrow",
"*unlockrows",
# 7.12. Miscellaneous Functions
"st_accum", "box2d", "box3d", "st_estimated_extent", "st_expand", "st_extent", "st_extent3d",
"find_srid", "st_mem_size", "st_point_inside_circle", "st_xmax", "st_xmin", "st_ymax", "st_ymin",
"st_zmax", "st_zmin",
"*ST_accum", "*box2d", "*box3d", "*ST_estimated_extent", "*ST_expand", "ST_Extent", "*ST_extent3d",
"*find_srid", "*ST_mem_size", "*ST_point_inside_circle", "ST_XMax", "ST_XMin", "ST_YMax", "ST_YMin",
"ST_ZMax", "ST_ZMin",
# 7.13. Exceptional Functions
"postgis_addbbox", "postgis_dropbbox", "postgis_hasbbox"
"*postgis_addbbox", "*postgis_dropbbox", "*postgis_hasbbox"
]
# constants
@ -170,6 +183,12 @@ postgis_constants = []
def getSqlDictionary(spatial=True):
def strip_star(s):
if s[0] == '*':
return s.lower()[1:]
else:
return s.lower()
k, c, f = list(keywords), list(constants), list(functions)
if spatial:
@ -177,4 +196,17 @@ def getSqlDictionary(spatial=True):
f += postgis_functions
c += postgis_constants
return {'keyword': k, 'constant': c, 'function': f}
return {'keyword': map(strip_star,k), 'constant': map(strip_star,c), 'function': map(strip_star,f)}
def getQueryBuilderDictionary():
# concat functions
def ff( l ):
return filter( lambda s:s[0] != '*', l )
def add_paren( l ):
return map( lambda s:s+"(", l )
foo = sorted(add_paren(ff( list(set.union(set(functions), set(postgis_functions))) )))
m = sorted(add_paren(ff( math_functions )))
agg = sorted(add_paren(ff(aggregate_functions)))
op = ff(operators)
s = sorted(add_paren(ff(string_functions)))
return {'function': foo, 'math' : m, 'aggregate': agg, 'operator': op, 'string': s }

View File

@ -135,22 +135,28 @@ class SpatiaLiteDBConnector(DBConnector):
def getSchemas(self):
return None
def getTables(self, schema=None):
def getTables(self, schema=None, add_sys_tables=False):
""" get list of tables """
tablenames = []
items = []
sys_tables = ["geom_cols_ref_sys", "geometry_columns", "geometry_columns_auth",
sys_tables = ["SpatialIndex", "geom_cols_ref_sys", "geometry_columns", "geometry_columns_auth",
"views_geometry_columns", "virts_geometry_columns", "spatial_ref_sys",
"sqlite_sequence", # "tableprefix_metadata", "tableprefix_rasters",
"layer_params", "layer_statistics", "layer_sub_classes", "layer_table_layout",
"pattern_bitmaps", "symbol_bitmaps", "project_defs", "raster_pyramids",
"sqlite_stat1", "sqlite_stat2", "spatialite_history"]
"sqlite_stat1", "sqlite_stat2", "spatialite_history",
"geometry_columns_field_infos",
"geometry_columns_statistics", "geometry_columns_time",
"sql_statements_log","vector_layers", "vector_layers_auth", "vector_layers_field_infos", "vector_layers_statistics",
"views_geometry_columns_auth", "views_geometry_columns_field_infos", "views_geometry_columns_statistics",
"virts_geometry_columns_auth", "virts_geometry_columns_field_infos", "virts_geometry_columns_statistics"
]
try:
vectors = self.getVectorTables(schema)
for tbl in vectors:
if tbl[1] in sys_tables:
if not add_sys_tables and tbl[1] in sys_tables:
continue
tablenames.append(tbl[1])
items.append(tbl)
@ -160,7 +166,7 @@ class SpatiaLiteDBConnector(DBConnector):
try:
rasters = self.getRasterTables(schema)
for tbl in rasters:
if tbl[1] in sys_tables:
if not add_sys_tables and tbl[1] in sys_tables:
continue
tablenames.append(tbl[1])
items.append(tbl)
@ -183,7 +189,9 @@ class SpatiaLiteDBConnector(DBConnector):
self._execute(c, sql)
for tbl in c.fetchall():
if tablenames.count(tbl[0]) <= 0 and not (tbl[0].startswith('idx_') and tbl[0] in sys_tables):
if tablenames.count(tbl[0]) <= 0 and not tbl[0].startswith('idx_'):
if not add_sys_tables and tbl[0] in sys_tables:
continue
item = list(tbl)
item.insert(0, Table.TableType)
items.append(item)
@ -638,3 +646,8 @@ class SpatiaLiteDBConnector(DBConnector):
sql_dict["identifier"] = items
return sql_dict
def getQueryBuilderDictionary(self):
from .sql_dictionary import getQueryBuilderDictionary
return getQueryBuilderDictionary()

View File

@ -109,7 +109,6 @@ class SLDatabase(Database):
return SLSqlResultModel(self, sql, parent)
def registerDatabaseActions(self, mainWindow):
action = QAction(self.tr("Run &Vacuum"), self)
mainWindow.registerAction(action, self.tr("&Database"), self.runVacuumActionSlot)
@ -147,6 +146,12 @@ class SLDatabase(Database):
def uniqueIdFunction(self):
return None
def explicitSpatialIndex( self ):
return True
def spatialIndexClause( self, src_table, src_column, dest_table, dest_column ):
return """"%s".ROWID IN (\nSELECT ROWID FROM SpatialIndex WHERE f_table_name='%s' AND search_frame="%s"."%s") """ % (src_table,src_table,dest_table, dest_column)
class SLTable(Table):
def __init__(self, row, db, schema=None):
Table.__init__(self, db, None)

View File

@ -50,73 +50,89 @@ spatialite_keywords = []
# functions
functions = [
# TODO get them from a reference page
"abs", "changes", "coalesce", "glob", "ifnull", "hex", "last_insert_rowid",
"length", "like", "lower", "ltrim", "max", "min", "nullif", "quote", "random",
"randomblob", "replace", "round", "rtrim", "soundex", "total_change", "trim",
"typeof", "upper", "zeroblob", "date", "datetime", "julianday", "strftime",
"avg", "count", "group_concat", "sum", "total"
"changes", "coalesce", "glob", "ifnull", "hex", "last_insert_rowid",
"nullif", "quote", "random",
"randomblob", "replace", "round", "soundex", "total_change",
"typeof", "zeroblob", "date", "datetime", "julianday", "strftime"
]
operators=[
' AND ',' OR ','||',' < ',' <= ',' > ',' >= ',' = ',' <> ',' IS ',' IS NOT ',' IN ',' LIKE ',' GLOB ',' MATCH ',' REGEXP '
]
math_functions = [
# SQL math functions
"Abs", "ACos", "ASin", "ATan", "Cos", "Cot", "Degrees", "Exp", "Floor", "Log", "Log2",
"Log10", "Pi", "Radians", "Round", "Sign", "Sin", "Sqrt", "StdDev_Pop", "StdDev_Samp", "Tan",
"Var_Pop", "Var_Samp" ]
string_functions=["Length", "Lower", "Upper", "Like", "Trim", "LTrim", "RTrim", "Replace", "Substr"]
aggregate_functions=[
"Max","Min","Avg","Count","Sum","Group_Concat","Total","Var_Pop","Var_Samp","StdDev_Pop","StdDev_Samp"
]
spatialite_functions = [ # from www.gaia-gis.it/spatialite-2.3.0/spatialite-sql-2.3.0.html
# SQL math functions
"abs", "acos", "asin", "atan", "cos", "cot", "degrees", "exp", "floor", "log", "log2",
"log10", "pi", "radians", "round", "sign", "sin", "sqrt", "stddev_pop", "stddev_samp", "tan",
"var_pop", "var_samp",
# SQL utility functions for BLOB objects
"iszipblob", "ispdfblob", "isgifblob", "ispngblob", "isjpegblob", "isexifblob",
"isexifgpsblob", "geomfromexifgpsblob", "makepoint", "buildmbr", "buildcirclembr", "mbrminx",
"mbrminy", "mbrmaxx", "mbrmaxy",
"*iszipblob", "*ispdfblob", "*isgifblob", "*ispngblob", "*isjpegblob", "*isexifblob",
"*isexifgpsblob", "*geomfromexifgpsblob", "MakePoint", "BuildMbr", "*buildcirclembr", "ST_MinX",
"ST_MinY", "ST_MaxX", "ST_MaxY",
# SQL functions for constructing a geometric object given its Well-known Text Representation
"geomfromtext", "pointfromtext",
"ST_GeomFromText", "*pointfromtext",
# SQL functions for constructing a geometric object given its Well-known Binary Representation
"geomfromwkb", "pointfromwkb",
"*geomfromwkb", "*pointfromwkb",
# SQL functions for obtaining the Well-known Text / Well-known Binary Representation of a geometric object
"astext", "asbinary",
"ST_AsText", "ST_AsBinary",
# SQL functions supporting exotic geometric formats
"assvg", "asfgf", "geomfromfgf",
"*assvg", "*asfgf", "*geomfromfgf",
# SQL functions on type Geometry
"dimension", "geometrytype", "srid", "setsrid", "isempty", "issimple", "isvalid", "boundary",
"envelope",
"ST_Dimension", "ST_GeometryType", "ST_Srid", "ST_SetSrid", "ST_isEmpty", "ST_isSimple", "ST_isValid", "ST_Boundary",
"ST_Envelope",
# SQL functions on type Point
"x", "y",
"ST_X", "ST_Y",
# SQL functions on type Curve [Linestring or Ring]
"startpoint", "endpoint", "glength", "isclosed", "isring", "simplify",
"simplifypreservetopology",
"ST_StartPoint", "ST_EndPoint", "ST_Length", "ST_isClosed", "ST_isRing", "ST_Simplify",
"*simplifypreservetopology",
# SQL functions on type LineString
"numpoints", "pointn",
"ST_NumPoints", "ST_PointN",
# SQL functions on type Surface [Polygon or Ring]
"centroid", "pointonsurface", "area",
"ST_Centroid", "ST_PointOnSurface", "ST_Area",
# SQL functions on type Polygon
"exteriorring", "interiorringn",
"ST_ExteriorRing", "ST_InteriorRingN",
# SQL functions on type GeomCollection
"numgeometries", "geometryn",
"ST_NumGeometries", "ST_GeometryN",
# SQL functions that test approximative spatial relationships via MBRs
"mbrequal", "mbrdisjoint", "mbrtouches", "mbrwithin", "mbroverlaps", "mbrintersects",
"mbrcontains",
"MbrEqual", "MbrDisjoint", "MbrTouches", "MbrWithin", "MbrOverlaps", "MbrIntersects",
"MbrContains",
# SQL functions that test spatial relationships
"equals", "disjoint", "touches", "within", "overlaps", "crosses", "intersects", "contains",
"relate",
"ST_Equals", "ST_Disjoint", "ST_Touches", "ST_Within", "ST_Overlaps", "ST_Crosses", "ST_Intersects", "ST_Contains",
"ST_Relate",
# SQL functions for distance relationships
"distance",
"ST_Distance",
# SQL functions that implement spatial operators
"intersection", "difference", "gunion", "gunion", "symdifference", "buffer", "convexhull",
"ST_Intersection", "ST_Difference", "ST_Union", "ST_SymDifference", "ST_Buffer", "ST_ConvexHull",
# SQL functions for coordinate transformations
"transform",
"ST_Transform",
# SQL functions for Spatial-MetaData and Spatial-Index handling
"initspatialmetadata", "addgeometrycolumn", "recovergeometrycolumn", "discardgeometrycolumn",
"createspatialindex", "creatembrcache", "disablespatialindex",
"*initspatialmetadata", "*addgeometrycolumn", "*recovergeometrycolumn", "*discardgeometrycolumn",
"*createspatialindex", "*creatembrcache", "*disablespatialindex",
# SQL functions implementing FDO/OGR compatibily
"checkspatialmetadata", "autofdostart", "autofdostop", "initfdospatialmetadata",
"addfdogeometrycolumn", "recoverfdogeometrycolumn", "discardfdogeometrycolumn",
"*checkspatialmetadata", "*autofdostart", "*autofdostop", "*initfdospatialmetadata",
"*addfdogeometrycolumn", "*recoverfdogeometrycolumn", "*discardfdogeometrycolumn",
# SQL functions for MbrCache-based queries
"filtermbrwithin", "filtermbrcontains", "filtermbrintersects", "buildmbrfilter"
"*filtermbrwithin", "*filtermbrcontains", "*filtermbrintersects", "*buildmbrfilter"
]
# constants
constants = ["null", "false", "true"]
spatialite_constants = []
def getSqlDictionary(spatial=True):
def strip_star(s):
if s[0] == '*':
return s.lower()[1:]
else:
return s.lower()
k, c, f = list(keywords), list(constants), list(functions)
if spatial:
@ -124,4 +140,17 @@ def getSqlDictionary(spatial=True):
f += spatialite_functions
c += spatialite_constants
return {'keyword': k, 'constant': c, 'function': f}
return {'keyword': map(strip_star,k), 'constant': map(strip_star,c), 'function': map(strip_star,f)}
def getQueryBuilderDictionary():
# concat functions
def ff( l ):
return filter( lambda s:s[0] != '*', l )
def add_paren( l ):
return map( lambda s:s+"(", l )
foo = sorted(add_paren(ff( list(set.union(set(functions), set(spatialite_functions))) )))
m = sorted(add_paren(ff( math_functions )))
agg = sorted(add_paren(ff(aggregate_functions)))
op = ff(operators)
s = sorted(add_paren(ff(string_functions)))
return {'function': foo, 'math' : m, 'aggregate': agg, 'operator': op, 'string': s }

View File

@ -117,7 +117,7 @@ class DBTree(QTreeView):
menu.addAction(self.tr("Rename"), self.rename)
menu.addAction(self.tr("Delete"), self.delete)
if isinstance(item, Table):
if isinstance(item, Table) and item.canBeAddedToCanvas():
menu.addSeparator()
menu.addAction(self.tr("Add to canvas"), self.addLayer)

View File

@ -0,0 +1,381 @@
# -*- coding: utf-8 -*-
"""
/***************************************************************************
Name : DB Manager
Description : Database manager plugin for QGIS
Date : March 2015
copyright : (C) 2015 Hugo Mercier / Oslandia
email : hugo dot mercier at oslandia dot com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
Query builder dialog, based on the QSpatialite plugin (GPLv2+) by Romain Riviere
"""
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from .ui.ui_DlgQueryBuilder import Ui_DbManagerQueryBuilderDlg as Ui_Dialog
from .db_plugins.plugin import VectorTable
class FocusEventFilter(QObject):
def __init__( self, parent ):
QObject.__init__( self, parent)
self.focus = ''
def eventFilter( self, obj, event ):
if event.type() == QEvent.FocusIn:
self.focus = obj.objectName()
return QObject.eventFilter( self, obj, event )
def insertWithSelection( widget, text ):
if widget.textCursor().hasSelection(): #user has selectedsomething...
selection=widget.textCursor().selectedText()
widget.insertPlainText(text+selection+")")
else:
widget.insertPlainText(text)
def insertWithSelectionOn( parent, objectname, text ):
"""Insert the text in a QTextEdit given by its objectname"""
w = parent.findChild( QTextEdit, objectname )
insertWithSelection( w, text )
class QueryBuilderDlg(QDialog):
# object used to store parameters between invocations
saveParameter = None
def __init__(self, iface, db, parent=None, reset = False):
QDialog.__init__(self, parent)
self.iface = iface
self.db = db
self.query = ''
self.ui = Ui_Dialog()
self.ui.setupUi(self)
self.ui.group.setMaximumHeight(self.ui.tab.sizeHint().height())
self.ui.order.setMaximumHeight(self.ui.tab.sizeHint().height())
self.evt = FocusEventFilter( self )
self.ui.col.installEventFilter( self.evt )
self.ui.where.installEventFilter( self.evt )
self.ui.group.installEventFilter( self.evt )
self.ui.order.installEventFilter( self.evt )
d = self.db.connector.getQueryBuilderDictionary()
#Application default parameters
self.table=None
self.col_col=[]
self.col_where=[]
self.coltables=[]
self.ui.extract.setChecked(True)
#ComboBox default values
self.ui.functions.insertItems(1,d['function'])
self.ui.math.insertItems(1,d['math'])
self.ui.aggregates.insertItems(1,d['aggregate'])
self.ui.operators.insertItems(1,d['operator'])
self.ui.stringfct.insertItems(1,d['string'])
#self.ui.Rtree.insertItems(1,rtreecommand)
# restore last query if needed
if reset:
QueryBuilderDlg.saveParameter = None
if QueryBuilderDlg.saveParameter is not None:
self.restoreLastQuery()
#Show Tables
self.show_tables()
#Signal/slot
QObject.connect(self.ui.aggregates,SIGNAL("currentIndexChanged(const QString&)"),self.add_aggregate)
QObject.connect(self.ui.stringfct,SIGNAL("currentIndexChanged(const QString&)"),self.add_stringfct)
QObject.connect(self.ui.operators,SIGNAL("currentIndexChanged(const QString&)"),self.add_operators)
QObject.connect(self.ui.functions,SIGNAL("currentIndexChanged(const QString&)"),self.add_functions)
QObject.connect(self.ui.math,SIGNAL("currentIndexChanged(const QString&)"),self.add_math)
QObject.connect(self.ui.tables,SIGNAL("currentIndexChanged(const QString&)"),self.add_tables)
QObject.connect(self.ui.tables,SIGNAL("currentIndexChanged(const QString&)"),self.list_cols)
QObject.connect(self.ui.columns,SIGNAL("currentIndexChanged(const QString&)"),self.add_columns)
QObject.connect(self.ui.columns_2,SIGNAL("currentIndexChanged(const QString&)"),self.list_values)
QObject.connect(self.ui.reset,SIGNAL("clicked(bool)"),self.reset)
QObject.connect(self.ui.extract,SIGNAL("stateChanged(int)"),self.list_values)
QObject.connect(self.ui.values,SIGNAL("doubleClicked(const QModelIndex &)"),self.query_item)
QObject.connect(self.ui.buttonBox,SIGNAL("accepted()"),self.validate)
QObject.connect(self.ui.checkBox,SIGNAL("stateChanged(int)"),self.show_tables)
if self.db.explicitSpatialIndex():
self.tablesGeo=[table for table in self.tables if isinstance(table,VectorTable)]
tablesGeo=[ '"%s"."%s"'%(table.name,table.geomColumn) for table in self.tablesGeo]
self.ui.table_target.insertItems(1,tablesGeo)
self.idxTables=[table for table in self.tablesGeo if table.hasSpatialIndex()]
idxTables=['"%s"."%s"'%(table.name,table.geomColumn) for table in self.idxTables]
self.ui.table_idx.insertItems(1,idxTables)
QObject.connect(self.ui.usertree,SIGNAL("clicked(bool)"),self.use_rtree)
else:
self.ui.toolBox.setItemEnabled(2, False )
def update_table_list( self ):
self.tables = []
add_sys_tables = self.ui.checkBox.isChecked()
schemas = self.db.schemas()
if schemas is None:
self.tables = self.db.tables( None, add_sys_tables )
else:
for schema in schemas:
self.tables += self.db.tables(schema, add_sys_tables)
def show_tables(self):
self.update_table_list()
self.ui.tables.clear()
self.ui.tables.insertItems(0,["Tables"])
self.ui.tables.insertItems(1,[t.name for t in self.tables])
def add_aggregate(self):
if self.ui.aggregates.currentIndex() <= 0:
return
ag=self.ui.aggregates.currentText()
insertWithSelection( self.ui.col, ag )
self.ui.aggregates.setCurrentIndex(0)
def add_functions(self):
if self.ui.functions.currentIndex() <= 0:
return
ag=self.ui.functions.currentText()
insertWithSelectionOn( self, self.evt.focus, ag )
self.ui.functions.setCurrentIndex(0)
def add_stringfct(self):
if self.ui.stringFct.currentIndex() <= 0:
return
ag=self.ui.stringfct.currentText()
insertWithSelectionOn( self, self.evt.focus, ag )
self.ui.stringfct.setCurrentIndex(0)
def add_math(self):
if self.ui.math.currentIndex() <= 0:
return
ag=self.ui.math.currentText()
insertWithSelectionOn( self, self.evt.focus, ag )
self.ui.math.setCurrentIndex(0)
def add_operators(self):
if self.ui.operators.currentIndex() <= 0:
return
ag=self.ui.operators.currentText()
if self.evt.focus == "where": # in where section
self.ui.where.insertPlainText(ag)
else:
self.ui.col.insertPlainText(ag)
self.ui.operators.setCurrentIndex(0)
def add_tables(self):
if self.ui.tables.currentIndex() <= 0:
return
ag=self.ui.tables.currentText()
#Retrieve Table Object from txt
tableObj=[table for table in self.tables if table.name.upper()==ag.upper()]
if len(tableObj)!=1:
return #No object with this name
self.table=tableObj[0]
if (ag in self.coltables): #table already use
reponse=QMessageBox.question(self, "Table already used","Do you want to add table %s again ?"%ag, QMessageBox.Yes | QMessageBox.No)
if reponse==QMessageBox.No:
return
ag = self.table.quotedName()
txt=self.ui.tab.text()
if (txt is None) or (txt in (""," ")):
self.ui.tab.setText('%s'%ag)
else:
self.ui.tab.setText('%s, %s'%(txt,ag))
self.ui.tables.setCurrentIndex(0)
def add_columns(self):
if self.ui.columns.currentIndex() <= 0:
return
ag=self.ui.columns.currentText()
if self.evt.focus == "where": # in where section
if ag in self.col_where: # column already called in where section
reponse=QMessageBox.question(self, "Column already used in WHERE clause","Do you want to add column %s again ?"%ag, QMessageBox.Yes | QMessageBox.No)
if reponse==QMessageBox.No:
self.ui.columns.setCurrentIndex(0)
return
self.ui.where.insertPlainText(ag)
self.col_where.append(ag)
elif self.evt.focus == "col" :
if ag in self.col_col: # column already called in col section
reponse=QMessageBox.question(self, "Column already used in COLUMNS section","Do you want to add column %s again ?"%ag, QMessageBox.Yes | QMessageBox.No)
if reponse==QMessageBox.No:
self.ui.columns.setCurrentIndex(0)
return
if len(self.ui.col.toPlainText().strip()) > 0:
self.ui.col.insertPlainText(",\n" + ag)
else:
self.ui.col.insertPlainText(ag)
self.col_col.append(ag)
elif self.evt.focus == "group":
if len(self.ui.group.toPlainText().strip()) > 0:
self.ui.group.insertPlainText( ", " + ag )
else:
self.ui.group.insertPlainText( ag )
elif self.evt.focus == "order":
if len(self.ui.order.toPlainText().strip()) > 0:
self.ui.order.insertPlainText( ", " + ag )
else:
self.ui.order.insertPlainText( ag )
self.ui.columns.setCurrentIndex(0)
def list_cols(self):
table=self.table
if (table is None):
return
if (table.name in self.coltables):
return
columns=['"%s"."%s"'%(table.name,col.name) for col in table.fields()]
#add special '*' column:
columns=['"%s".*'%table.name]+columns
self.coltables.append(table.name) #table columns have been listed
# first and second col combobox
end=self.ui.columns.count()
self.ui.columns.insertItems(end,columns)
self.ui.columns_2.insertItems(end,columns)
end=self.ui.columns.count()
self.ui.columns.insertSeparator(end)
self.ui.columns_2.insertSeparator(end)
def list_values(self):
if self.ui.columns_2.currentIndex() <= 0:
return
item=self.ui.columns_2.currentText()
#recover column and table:
column=item.split(".") # "table".'column'
table=column[0]
if column[1]=='*':
return
table = table[1:-1]
qtable = [t for t in self.tables if t.name.lower() == table.lower()][0].quotedName()
if self.ui.extract.isChecked():
limit = 10
else:
limit = None
model = self.db.columnUniqueValuesModel( item, qtable, limit )
self.ui.values.setModel(model)
def query_item(self, index):
queryWord = index.data()
queryWord=' "%s"' %queryWord
if queryWord != '':
self.ui.where.insertPlainText(queryWord)
self.ui.where.setFocus()
def use_rtree(self):
idx=self.ui.table_idx.currentText()
if idx in (None,""," ","Table (with Spatial Index)"):
return
try:
tab_idx=idx.split(".")[0][1:-1] #remove "
col_idx=idx.split(".")[1][1:-1] #remove '
except:
pop_up_error("All fields are necessary",self)
tgt=self.ui.table_target.currentText()
if tgt in (None,""," ","Table (Target)"):
return
tgt_tab = tgt.split('.')[0][1:-1]
tgt_col = tgt.split('.')[1][1:-1]
sql=""
if self.ui.where.toPlainText() not in (None,""," "):
sql+="\nAND"
sql+=self.db.spatialIndexClause( tab_idx, col_idx, tgt_tab, tgt_col )
self.ui.where.insertPlainText(sql)
def reset(self):
#reset lists:
self.ui.values.setModel(None)
self.ui.columns_2.clear()
self.ui.columns.insertItems(0,["Columns"])
self.ui.columns_2.insertItems(0,["Columns"])
self.coltables=[]
self.col_col=[]
self.col_where=[]
def validate(self):
query_col=unicode(self.ui.col.toPlainText())
query_table=unicode(self.ui.tab.text())
query_where=unicode(self.ui.where.toPlainText())
query_group=unicode(self.ui.group.toPlainText())
query_order=unicode(self.ui.order.toPlainText())
query=""
if query_col.strip()!='':
query+="SELECT %s \nFROM %s"%(query_col,query_table)
if query_where.strip()!='':
query+="\nWHERE %s"%query_where
if query_group.strip()!='':
query+="\nGROUP BY %s"%query_group
if query_order.strip()!='':
query+="\nORDER BY %s"%query_order
if query == '':
return
self.query = query
saveParameter = {}
saveParameter["coltables"]=self.coltables
saveParameter["col_col"]=self.col_col
saveParameter["col_where"]=self.col_where
saveParameter["col"]=query_col
saveParameter["tab"]=query_table
saveParameter["where"]=query_where
saveParameter["group"]=query_group
saveParameter["order"]=query_order
QueryBuilderDlg.saveParameter = saveParameter
def restoreLastQuery(self):
self.update_table_list()
saveParameter = QueryBuilderDlg.saveParameter
self.coltables=saveParameter["coltables"]
self.col_col=saveParameter["col_col"]
self.col_where=saveParameter["col_where"]
self.ui.col.insertPlainText(saveParameter["col"])
self.ui.tab.setText(saveParameter["tab"])
self.ui.where.insertPlainText(saveParameter["where"])
self.ui.order.setPlainText(saveParameter["order"])
self.ui.group.setPlainText(saveParameter["group"])
#list previous colist:
for tablename in self.coltables:
#Retrieve table object from table name:
table=[table for table in self.tables if table.name.upper()==tablename.upper()]
if len(table)!=1:
break
table=table[0]
columns=['"%s"."%s"'%(table.name,col.name) for col in table.fields()]
# first and second col combobox
end=self.ui.columns.count()
self.ui.columns.insertItems(end,columns)
self.ui.columns_2.insertItems(end,columns)
end=self.ui.columns.count()
self.ui.columns.insertSeparator(end)
self.ui.columns_2.insertSeparator(end)

View File

@ -30,6 +30,7 @@ from qgis.core import QgsProject
from .db_plugins.plugin import BaseError
from .dlg_db_error import DlgDbError
from .dlg_query_builder import QueryBuilderDlg
try:
from qgis.gui import QgsCodeEditorSQL
@ -88,6 +89,9 @@ class DlgSqlWindow(QDialog, Ui_Dialog):
self.connect(self.loadAsLayerGroup, SIGNAL("toggled(bool)"), self.loadAsLayerToggled)
self.loadAsLayerToggled(False)
self.queryBuilderFirst = True
self.connect( self.queryBuilderBtn, SIGNAL("clicked()"), self.displayQueryBuilder )
def updatePresetsCombobox(self):
self.presetCombo.clear()
@ -326,3 +330,11 @@ class DlgSqlWindow(QDialog, Ui_Dialog):
api.prepare()
self.editSql.lexer().setAPIs(api)
def displayQueryBuilder( self ):
dlg = QueryBuilderDlg( self.iface, self.db, self, reset = self.queryBuilderFirst )
self.queryBuilderFirst = False
r = dlg.exec_()
if r == QDialog.Accepted:
self.editSql.setText( dlg.query )

View File

@ -1,3 +1,3 @@
FILE(GLOB ICON_FILES *.png *.xpm toolbar/*.png)
FILE(GLOB ICON_FILES *.gif *.png *.xpm toolbar/*.png)
PLUGIN_INSTALL(db_manager icons ${ICON_FILES})

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

View File

@ -1,30 +1,31 @@
<RCC>
<qresource prefix="/db_manager">
<file>icons/layer_line.png</file>
<file>icons/layer_point.png</file>
<file>icons/layer_polygon.png</file>
<file>icons/layer_raster.png</file>
<file>icons/layer_unknown.png</file>
<file>icons/namespace.png</file>
<file>icons/namespaces.xpm</file>
<file>icons/table.png</file>
<file>icons/tables.xpm</file>
<file>icons/user.xpm</file>
<file>icons/users.xpm</file>
<file>icons/view.png</file>
<file alias="warning">icons/warning-20px.png</file>
<file>icons/plugged.png</file>
<file>icons/unplugged.png</file>
<file alias="icon">icons/dbmanager.png</file>
<file>icons/about.png</file>
</qresource>
<qresource prefix="/db_manager/actions">
<file alias="del_table">icons/toolbar/action_del_table.png</file>
<file alias="edit_table">icons/toolbar/action_edit_table.png</file>
<file alias="export">icons/toolbar/action_export.png</file>
<file alias="import">icons/toolbar/action_import.png</file>
<file alias="create_table">icons/toolbar/action_new_table.png</file>
<file alias="refresh">icons/toolbar/action_refresh.png</file>
<file alias="sql_window">icons/toolbar/action_sql_window.png</file>
</qresource>
<qresource prefix="/db_manager">
<file>icons/layer_line.png</file>
<file>icons/sql.gif</file>
<file>icons/layer_point.png</file>
<file>icons/layer_polygon.png</file>
<file>icons/layer_raster.png</file>
<file>icons/layer_unknown.png</file>
<file>icons/namespace.png</file>
<file>icons/namespaces.xpm</file>
<file>icons/table.png</file>
<file>icons/tables.xpm</file>
<file>icons/user.xpm</file>
<file>icons/users.xpm</file>
<file>icons/view.png</file>
<file alias="warning">icons/warning-20px.png</file>
<file>icons/plugged.png</file>
<file>icons/unplugged.png</file>
<file alias="icon">icons/dbmanager.png</file>
<file>icons/about.png</file>
</qresource>
<qresource prefix="/db_manager/actions">
<file alias="del_table">icons/toolbar/action_del_table.png</file>
<file alias="edit_table">icons/toolbar/action_edit_table.png</file>
<file alias="export">icons/toolbar/action_export.png</file>
<file alias="import">icons/toolbar/action_import.png</file>
<file alias="create_table">icons/toolbar/action_new_table.png</file>
<file alias="refresh">icons/toolbar/action_refresh.png</file>
<file alias="sql_window">icons/toolbar/action_sql_window.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,520 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DbManagerQueryBuilderDlg</class>
<widget class="QDialog" name="DbManagerQueryBuilderDlg">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>797</width>
<height>463</height>
</rect>
</property>
<property name="windowTitle">
<string>SQL query builder</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="0,0">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Columns</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QTextEdit" name="col">
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Tables </string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="tab">
<property name="frame">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QTextEdit" name="where"/>
</item>
<item row="3" column="1">
<widget class="QTextEdit" name="group">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>25</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QTextEdit" name="order">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>25</height>
</size>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Where </string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Group by</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Order by</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QToolBox" name="toolBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>250</width>
<height>16777215</height>
</size>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>250</width>
<height>313</height>
</rect>
</property>
<attribute name="label">
<string>Data</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QCheckBox" name="checkBox">
<property name="font">
<font>
<pointsize>8</pointsize>
<kerning>true</kerning>
</font>
</property>
<property name="text">
<string>Show system tables</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="tables">
<item>
<property name="text">
<string>Tables</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="columns">
<item>
<property name="text">
<string>Columns</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="aggregates">
<item>
<property name="text">
<string>Aggregates</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="functions">
<item>
<property name="text">
<string>Functions</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="math">
<item>
<property name="text">
<string>Math</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="stringfct">
<item>
<property name="text">
<string>Strings functions</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="operators">
<item>
<property name="text">
<string>Operators</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>250</width>
<height>313</height>
</rect>
</property>
<attribute name="label">
<string>Columns' values</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QComboBox" name="columns_2">
<item>
<property name="text">
<string>Columns</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QCheckBox" name="extract">
<property name="text">
<string>Only 10 first values</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="values">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="showDropIndicator" stdset="0">
<bool>false</bool>
</property>
<property name="dragEnabled">
<bool>false</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::NoDragDrop</enum>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>250</width>
<height>313</height>
</rect>
</property>
<attribute name="label">
<string>Spatial index</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QComboBox" name="table_idx">
<item>
<property name="text">
<string>Table (with spatial index)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QComboBox" name="table_target">
<item>
<property name="text">
<string>Table (Target)</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QPushButton" name="usertree">
<property name="text">
<string>Use spatial index</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QPushButton" name="reset">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>&amp;Reset</string>
</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>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DbManagerQueryBuilderDlg</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>633</x>
<y>440</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DbManagerQueryBuilderDlg</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>516</x>
<y>433</y>
</hint>
<hint type="destinationlabel">
<x>306</x>
<y>423</y>
</hint>
</hints>
</connection>
<connection>
<sender>reset</sender>
<signal>clicked()</signal>
<receiver>where</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>21</x>
<y>426</y>
</hint>
<hint type="destinationlabel">
<x>118</x>
<y>249</y>
</hint>
</hints>
</connection>
<connection>
<sender>reset</sender>
<signal>clicked()</signal>
<receiver>tab</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>24</x>
<y>434</y>
</hint>
<hint type="destinationlabel">
<x>147</x>
<y>165</y>
</hint>
</hints>
</connection>
<connection>
<sender>reset</sender>
<signal>clicked()</signal>
<receiver>col</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>24</x>
<y>428</y>
</hint>
<hint type="destinationlabel">
<x>208</x>
<y>98</y>
</hint>
</hints>
</connection>
<connection>
<sender>reset</sender>
<signal>clicked()</signal>
<receiver>columns</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>57</x>
<y>437</y>
</hint>
<hint type="destinationlabel">
<x>513</x>
<y>67</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<width>801</width>
<height>525</height>
</rect>
</property>
@ -43,6 +43,17 @@
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="queryBuilderBtn">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/db_manager/icons/sql.gif</normaloff>:/db_manager/icons/sql.gif</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="presetName">
<property name="text">
@ -372,7 +383,9 @@ columns</string>
<tabstop>btnClear</tabstop>
<tabstop>viewResult</tabstop>
</tabstops>
<resources/>
<resources>
<include location="../resources.qrc"/>
</resources>
<connections>
<connection>
<sender>loadAsLayerGroup</sender>