def publishPgTable(self, tree, explorer): if not xmlNameIsValid(self.element.name, xmlNameRegex()): QtGui.QMessageBox.warning(explorer, "Invalid name", ("The table name (%s) is not a valid XML name.\n" + "This could cause problems when published to GeoServer.\n" + "Please rename it and retry publishing.") % self.element.name) return dlg = PublishLayerDialog(explorer.catalogs(), self.element) dlg.exec_() if dlg.catalog is None: return cat = dlg.catalog catItem = tree.findFirstItem(cat) toUpdate = [catItem] if int(self.element.srid) == 0: explorer.setWarning("PostGIS table '{0}' has no SRID; ESPG:4326 " "will be assigned.".format(self.element.name)) if explorer.run(publishTable, "Publish table '" + self.element.name + "'", toUpdate, self.element, cat, dlg.workspace, True, dlg.layername): # add existing style to layer, or later some operations may fail, # like malformed XML when getting capabilities for OWS connections pglyr = cat.get_layer(dlg.layername) pgitem = tree.findFirstItem(pglyr) if pgitem is None: return if not pgitem.addStyleToLayer(explorer): # handles refresh of item # user cancelled AddStyleToLayerDialog noDefaultStyleError(explorer, dlg.layername) else: catItem.layersItem.refreshContent(explorer)
def publishPgTable(self, tree, explorer): if not xmlNameIsValid(self.element.name, xmlNameRegex()): QtGui.QMessageBox.warning( explorer, "Invalid name", ("The table name (%s) is not a valid XML name.\n" + "This could cause problems when published to GeoServer.\n" + "Please rename it and retry publishing.") % self.element.name) return dlg = PublishLayerDialog(explorer.catalogs(), self.element) dlg.exec_() if dlg.catalog is None: return cat = dlg.catalog catItem = tree.findFirstItem(cat) toUpdate = [catItem] if int(self.element.srid) == 0: explorer.setWarning("PostGIS table '{0}' has no SRID; ESPG:4326 " "will be assigned.".format(self.element.name)) if explorer.run(publishTable, "Publish table '" + self.element.name + "'", toUpdate, self.element, cat, dlg.workspace, True, dlg.layername): # add existing style to layer, or later some operations may fail, # like malformed XML when getting capabilities for OWS connections pglyr = cat.get_layer(dlg.layername) pgitem = tree.findFirstItem(pglyr) if pgitem is None: return if not pgitem.addStyleToLayer(explorer): # handles refresh of item # user cancelled AddStyleToLayerDialog noDefaultStyleError(explorer, dlg.layername) else: catItem.layersItem.refreshContent(explorer)
def okPressed(self): self.name = unicode(self.editName.text()) self.editName.setStyleSheet("QLineEdit{background: white}") if not xmlNameIsValid(self.name, xmlNameRegex()): self.editName.setStyleSheet("QLineEdit{background: yellow}") return if self.table.rowCount() == 0: QMessageBox.information(self, self.tr("Sorry"), self.tr("add some fields!")) return self.useGeomColumn = self.chkGeomColumn.isChecked() if self.useGeomColumn: self.geomColumn = unicode(self.editGeomColumn.text()) if len(self.geomColumn) == 0: self.editGeomColumn.setStyleSheet("QLineEdit{background: yellow}") return self.geomType = self.GEOM_TYPES[ self.cboGeomType.currentIndex() ] self.geomDim = self.spinGeomDim.value() try: self.geomSrid = int(self.editGeomSrid.text()) except ValueError: self.geomSrid = -1 self.useSpatialIndex = self.chkSpatialIndex.isChecked() self.fields = [] for i in xrange(self.table.rowCount()): name = self.table.cellWidget(i, 0).text() type = self.table.cellWidget(i, 1).currentText() null = self.table.cellWidget(i, 2).currentIndex == 0 self.fields.append(TableField(name, type, null)) self.pk = self.cboPrimaryKey.currentText() self.ok = True self.close()
def publishDraggedTable(tree, explorer, table, workspace): if not xmlNameIsValid(table.name, xmlNameRegex()): QtGui.QMessageBox.warning(explorer, "Invalid name", ("The table name (%s) is not a valid XML name.\n" + "This could cause problems when published to GeoServer.\n" + "Please rename it and retry publishing.") % table.name) return False cat = workspace.catalog if int(table.srid) == 0: explorer.setWarning("PostGIS table '{0}' has no SRID; ESPG:4326 will " "be assigned.".format(table.name)) gslayers = [lyr.name for lyr in cat.get_layers()] try: lyrname = getGSLayerName(name=xmlNameFixUp(table.name + "_table"), names=gslayers, unique=False) except UserCanceledOperation: return False catItem = tree.findFirstItem(cat) toUpdate = [catItem.layersItem] res = explorer.run(publishTable, "Publish table from table '" + table.name + "'", toUpdate, table, cat, workspace, True, lyrname) if res: # add existing style to layer, or later some operations may fail, # like malformed XML when getting capabilities for OWS connections pglyr = cat.get_layer(lyrname) pgitem = tree.findFirstItem(pglyr) if pgitem is None: print "pgitem not found" return False if not pgitem.addStyleToLayer(explorer): # handles refresh of item # user cancelled AddStyleToLayerDialog noDefaultStyleError(explorer, lyrname) return False else: catItem.layersItem.refreshContent(explorer) return res
def publishDraggedTable(tree, explorer, table, workspace): if not xmlNameIsValid(table.name, xmlNameRegex()): QtGui.QMessageBox.warning( explorer, "Invalid name", ("The table name (%s) is not a valid XML name.\n" + "This could cause problems when published to GeoServer.\n" + "Please rename it and retry publishing.") % table.name) return False cat = workspace.catalog if int(table.srid) == 0: explorer.setWarning("PostGIS table '{0}' has no SRID; ESPG:4326 will " "be assigned.".format(table.name)) gslayers = [lyr.name for lyr in cat.get_layers()] try: lyrname = getGSLayerName(name=xmlNameFixUp(table.name + "_table"), names=gslayers, unique=False) except UserCanceledOperation: return False catItem = tree.findFirstItem(cat) toUpdate = [catItem.layersItem] res = explorer.run(publishTable, "Publish table from table '" + table.name + "'", toUpdate, table, cat, workspace, True, lyrname) if res: # add existing style to layer, or later some operations may fail, # like malformed XML when getting capabilities for OWS connections pglyr = cat.get_layer(lyrname) pgitem = tree.findFirstItem(pglyr) if pgitem is None: print "pgitem not found" return False if not pgitem.addStyleToLayer(explorer): # handles refresh of item # user cancelled AddStyleToLayerDialog noDefaultStyleError(explorer, lyrname) return False else: catItem.layersItem.refreshContent(explorer) return res
def okPressed(self): self.name = unicode(self.editName.text()) self.editName.setStyleSheet("QLineEdit{background: white}") if not xmlNameIsValid(self.name, xmlNameRegex()): self.editName.setStyleSheet("QLineEdit{background: yellow}") return if self.table.rowCount() == 0: QMessageBox.information(self, self.tr("Sorry"), self.tr("add some fields!")) return self.useGeomColumn = self.chkGeomColumn.isChecked() if self.useGeomColumn: self.geomColumn = unicode(self.editGeomColumn.text()) if len(self.geomColumn) == 0: self.editGeomColumn.setStyleSheet( "QLineEdit{background: yellow}") return self.geomType = self.GEOM_TYPES[self.cboGeomType.currentIndex()] self.geomDim = self.spinGeomDim.value() try: self.geomSrid = int(self.editGeomSrid.text()) except ValueError: self.geomSrid = -1 self.useSpatialIndex = self.chkSpatialIndex.isChecked() self.fields = [] for i in xrange(self.table.rowCount()): name = self.table.cellWidget(i, 0).text() type = self.table.cellWidget(i, 1).currentText() null = self.table.cellWidget(i, 2).currentIndex == 0 self.fields.append(TableField(name, type, null)) self.pk = self.cboPrimaryKey.currentText() self.ok = True self.close()
def _publishExisting(self, layer, workspace, overwrite, name, storename=None): uri = QgsDataSourceURI(layer.dataProvider().dataSourceUri()) # check for table.name conflict in existing layer names where the # table.name is not the same as the user-chosen layer name, # i.e. unintended overwrite resource = self.catalog.get_resource(uri.table()) if resource is not None and uri.table() != name: raise Exception("QGIS PostGIS layer has table name conflict with " "existing GeoServer layer name: {0}\n" "You may need to rename GeoServer layer name." .format(uri.table())) conname = self.getConnectionNameFromLayer(layer) storename = xmlNameFixUp(storename or conname) if not xmlNameIsValid(storename): raise Exception("Database connection name is invalid XML and can " "not be auto-fixed: {0} -> {1}" .format(conname, storename)) if not uri.username(): raise Exception("GeoServer requires database connection's username " "to be defined") store = createPGFeatureStore(self.catalog, storename, workspace = workspace, overwrite = overwrite, host = uri.host(), database = uri.database(), schema = uri.schema(), port = uri.port(), user = uri.username(), passwd = uri.password()) if store is not None: rscname = name if uri.table() != name else uri.table() grpswlyr = [] if overwrite: # TODO: How do we honor *unchecked* user setting of # "Delete resource when deleting layer" here? # Is it an issue, if overwrite is expected? # We will soon have two layers with slightly different names, # a temp based upon table.name, the other possibly existing # layer with the same custom name, which may belong to group(s). # If so, remove existing layer from any layer group, before # continuing on with layer delete and renaming of new feature # type layer to custom name, then add new resultant layer back # to any layer groups the existing layer belonged to. Phew! flyr = self.catalog.get_layer(rscname) if flyr is not None: grpswlyr = groupsWithLayer(self.catalog, flyr) if grpswlyr: removeLayerFromGroups(self.catalog, flyr, grpswlyr) self.catalog.delete(flyr) # TODO: What about when the layer name is the same, but the # underlying db connection/store has changed? Not an issue? # The layer is deleted, which is correct, but the original # db store and feature type will not be changed. A conflict? frsc = store.get_resources(name=rscname) if frsc is not None: self.catalog.delete(frsc) # for dbs the name has to be the table name, initially ftype = self.catalog.publish_featuretype(uri.table(), store, layer.crs().authid()) # once table-based feature type created, switch name to user-chosen if ftype.name != rscname: ftype.dirty["name"] = rscname self.catalog.save(ftype) # now re-add to any previously assigned-to layer groups if overwrite and grpswlyr: ftype = self.catalog.get_resource(rscname) if ftype: addLayerToGroups(self.catalog, ftype, grpswlyr, workspace=workspace)
def publishTable(table, catalog = None, workspace = None, overwrite=True, name=None, storename=None): if catalog is None: pass lyrname = xmlNameFixUp(name) # usually fixed up by now # check for table.name conflict in existing layer names where the table.name # is not the same as the user-chosen layer name, i.e. unintended overwrite resource = catalog.get_resource(table.name) if resource is not None and table.name != lyrname: raise Exception("PostGIS table name conflicts with " "existing GeoServer layer name: {0}\n" "You may need to rename GeoServer layer name." .format(table.name)) workspace = workspace if workspace is not None else catalog.get_default_workspace() connection = table.conn geodb = connection.geodb conname = "{0}_{1}".format(connection.name, table.schema) storename = xmlNameFixUp(storename or conname) if not xmlNameIsValid(storename): raise Exception("Database connection name is invalid XML and can " "not be auto-fixed: {0} -> {1}" .format(conname, storename)) if not geodb.user: raise Exception("GeoServer requires database connection's username " "to be defined") store = createPGFeatureStore(catalog, storename, workspace = workspace, overwrite = True, host = geodb.host, database = geodb.dbname, schema = table.schema, port = geodb.port, user = geodb.user, passwd = geodb.passwd) if store is not None: rscname = name if table.name != name else table.name grpswlyr = [] if overwrite: # See notes about possible issues in OGCatalog._publishExisting() flyr = catalog.get_layer(rscname) if flyr is not None: grpswlyr = groupsWithLayer(catalog, flyr) if grpswlyr: removeLayerFromGroups(catalog, flyr, grpswlyr) catalog.delete(flyr) frsc = store.get_resources(name=rscname) if frsc is not None: catalog.delete(frsc) epsg = table.srid if int(table.srid) != 0 else 4326 ftype = catalog.publish_featuretype(table.name, store, "EPSG:" + str(epsg)) # once table-based layer created, switch name to user-chosen if table.name != rscname: ftype.dirty["name"] = rscname ftype.dirty["title"] = rscname catalog.save(ftype) if overwrite and grpswlyr: ftype = catalog.get_resource(rscname) if ftype: addLayerToGroups(catalog, ftype, grpswlyr, workspace=workspace)
def importFileOrLayer(self, source, schema, tablename, overwrite, singleGeom = False): if isinstance(source, basestring): layerName = QtCore.QFileInfo(source).completeBaseName() else: layerName = source.name() if tablename is None: tablename = layerName if not xmlNameIsValid(tablename, xmlNameRegex()): tablename = getPostGisTableName(name=tablename, names=[], unique=False) if overwrite: pk = "id" geom = "geom" providerName = "postgres" uri = QgsDataSourceURI() uri.setConnection(self.geodb.host, str(self.geodb.port), self.geodb.dbname, self.geodb.user, self.geodb.passwd) uri.setDataSource(schema, tablename, geom, "", pk) options = {} options['overwrite'] = True if singleGeom: options['forceSinglePartGeometryType'] = True if isinstance(source, basestring): layer = QgsVectorLayer(source, layerName, "ogr") if not layer.isValid() or layer.type() != QgsMapLayer.VectorLayer: layer.deleteLater() raise WrongLayerFileError("Error reading file {} or it is not a valid vector layer file".format(source)) else: layer = source if not layer.isValid() or layer.type() != QgsMapLayer.VectorLayer: raise WrongLayerFileError("Layer '%s' is not valid or is not a vector layer".format(layer.name())) ret, errMsg = QgsVectorLayerImport.importLayer(layer, uri.uri(), providerName, layer.crs(), False, False, options) if ret != 0: raise Exception(errMsg) else: if isinstance(source, QgsMapLayer): source = source.source() args = ["shp2pgsql", "-a"] if singleGeom: args.append("-S") args.extend([source, schema + "." + tablename]) if os.name == 'nt': cmdline = subprocess.list2cmdline(args) data = None p = os.popen3(cmdline) data = p[1].read() cursor = self.geodb.con.cursor() newcommand = re.compile(";$", re.MULTILINE) # split the commands cmds = newcommand.split(data) for cmd in cmds[:-1]: # run SQL commands within current DB connection self.geodb._exec_sql(cursor, cmd) data = cmds[-1] self.geodb.con.commit() if data is None or len(data) == 0: raise Exception("".join(p[2].readlines())) else: # start shp2pgsql as subprocess p = subprocess.Popen(args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # read the output while the process is running data = '' cursor = self.geodb.con.cursor() newcommand = re.compile(";$", re.MULTILINE) while p.poll() == None: data += p.stdout.read() # split the commands cmds = newcommand.split(data) for cmd in cmds[:-1]: # run SQL commands within current DB connection self.geodb._exec_sql(cursor, cmd) data = cmds[-1] # commit! self.db.con.commit() if p.returncode != 0: raise Exception(p.stderr.readlines().join("\n"))
def _publishExisting(self, layer, workspace, overwrite, name, storename=None): uri = QgsDataSourceURI(layer.dataProvider().dataSourceUri()) # check for table.name conflict in existing layer names where the # table.name is not the same as the user-chosen layer name, # i.e. unintended overwrite resource = self.catalog.get_resource(uri.table()) if resource is not None and uri.table() != name: raise Exception( "QGIS PostGIS layer has table name conflict with " "existing GeoServer layer name: {0}\n" "You may need to rename GeoServer layer name.".format( uri.table())) conname = self.getConnectionNameFromLayer(layer) storename = xmlNameFixUp(storename or conname) if not xmlNameIsValid(storename): raise Exception("Database connection name is invalid XML and can " "not be auto-fixed: {0} -> {1}".format( conname, storename)) if not uri.username(): raise Exception( "GeoServer requires database connection's username " "to be defined") store = createPGFeatureStore(self.catalog, storename, workspace=workspace, overwrite=overwrite, host=uri.host(), database=uri.database(), schema=uri.schema(), port=uri.port(), user=uri.username(), passwd=uri.password()) if store is not None: rscname = name if uri.table() != name else uri.table() grpswlyr = [] if overwrite: # TODO: How do we honor *unchecked* user setting of # "Delete resource when deleting layer" here? # Is it an issue, if overwrite is expected? # We will soon have two layers with slightly different names, # a temp based upon table.name, the other possibly existing # layer with the same custom name, which may belong to group(s). # If so, remove existing layer from any layer group, before # continuing on with layer delete and renaming of new feature # type layer to custom name, then add new resultant layer back # to any layer groups the existing layer belonged to. Phew! flyr = self.catalog.get_layer(rscname) if flyr is not None: grpswlyr = groupsWithLayer(self.catalog, flyr) if grpswlyr: removeLayerFromGroups(self.catalog, flyr, grpswlyr) self.catalog.delete(flyr) # TODO: What about when the layer name is the same, but the # underlying db connection/store has changed? Not an issue? # The layer is deleted, which is correct, but the original # db store and feature type will not be changed. A conflict? frsc = store.get_resources(name=rscname) if frsc is not None: self.catalog.delete(frsc) # for dbs the name has to be the table name, initially ftype = self.catalog.publish_featuretype(uri.table(), store, layer.crs().authid()) # once table-based feature type created, switch name to user-chosen if ftype.name != rscname: ftype.dirty["name"] = rscname self.catalog.save(ftype) # now re-add to any previously assigned-to layer groups if overwrite and grpswlyr: ftype = self.catalog.get_resource(rscname) if ftype: addLayerToGroups(self.catalog, ftype, grpswlyr, workspace=workspace)
def publishTable(table, catalog=None, workspace=None, overwrite=True, name=None, storename=None): if catalog is None: pass lyrname = xmlNameFixUp(name) # usually fixed up by now # check for table.name conflict in existing layer names where the table.name # is not the same as the user-chosen layer name, i.e. unintended overwrite resource = catalog.get_resource(table.name) if resource is not None and table.name != lyrname: raise Exception("PostGIS table name conflicts with " "existing GeoServer layer name: {0}\n" "You may need to rename GeoServer layer name.".format( table.name)) workspace = workspace if workspace is not None else catalog.get_default_workspace( ) connection = table.conn geodb = connection.geodb conname = "{0}_{1}".format(connection.name, table.schema) storename = xmlNameFixUp(storename or conname) if not xmlNameIsValid(storename): raise Exception("Database connection name is invalid XML and can " "not be auto-fixed: {0} -> {1}".format( conname, storename)) if not geodb.user: raise Exception("GeoServer requires database connection's username " "to be defined") store = createPGFeatureStore(catalog, storename, workspace=workspace, overwrite=True, host=geodb.host, database=geodb.dbname, schema=table.schema, port=geodb.port, user=geodb.user, passwd=geodb.passwd) if store is not None: rscname = name if table.name != name else table.name grpswlyr = [] if overwrite: # See notes about possible issues in OGCatalog._publishExisting() flyr = catalog.get_layer(rscname) if flyr is not None: grpswlyr = groupsWithLayer(catalog, flyr) if grpswlyr: removeLayerFromGroups(catalog, flyr, grpswlyr) catalog.delete(flyr) frsc = store.get_resources(name=rscname) if frsc is not None: catalog.delete(frsc) epsg = table.srid if int(table.srid) != 0 else 4326 ftype = catalog.publish_featuretype(table.name, store, "EPSG:" + str(epsg)) # once table-based layer created, switch name to user-chosen if table.name != rscname: ftype.dirty["name"] = rscname ftype.dirty["title"] = rscname catalog.save(ftype) if overwrite and grpswlyr: ftype = catalog.get_resource(rscname) if ftype: addLayerToGroups(catalog, ftype, grpswlyr, workspace=workspace)