Пример #1
0
    def login_action(self):
        self.username = self.logindiag.txtUsername.text()
        self.password = self.logindiag.txtPassword.text()
        self.host = self.logindiag.txtHost.text()
        self.port = self.logindiag.txtPort.text()
        self.db = self.logindiag.txtDb.text()

        try:
            uri = QgsDataSourceUri()
            #uri.setConnection("localhost", "5432", "stdm", "postgres", "postgres")
            uri.setConnection(self.host, self.port, self.db, self.username,
                              self.password)
            conn = pgconn.PostGisDBConnector(uri)
            dbtables = conn.getTables()
            if len(dbtables) > 0:
                msg = QMessageBox()
                msg.setWindowTitle("Message")
                msg.setText("Login Successful")
                msg.setIcon(QMessageBox.Information)
                msg.exec_()
                self.loginDialog.close()
            else:
                msg = QMessageBox()
                msg.setWindowTitle("Message")
                msg.setText("Login Error")
                msg.setIcon(QMessageBox.Critical)
                msg.exec_()

        except:
            msg = QMessageBox()
            msg.setWindowTitle("Message")
            msg.setText("Login Error")
            msg.setIcon(QMessageBox.Critical)
            msg.exec_()
 def get_db_tables(self):
     """Retrieve all tables from the selected database."""
     self.dlg.cmb_geo.clear()
     db_name = self.dlg.cmb_db.currentText()
     con_name = self.dlg.cmb_con.currentText()
     con_str = "{db}/connections/{con}/".format(db=db_name, con=con_name)
     qs = QSettings()
     db_host = qs.value(con_str + "host")
     db_port = qs.value(con_str + "port")
     db_name = qs.value(con_str + "database")
     con_usr = qs.value(con_str + "username")
     con_pwd = qs.value(con_str + "password")
     uri = QgsDataSourceURI()
     uri.setConnection(db_host, db_port, db_name, con_usr, con_pwd)
     post_c = pg_con.PostGisDBConnector(uri)
     tbl_list = []
     for table in post_c.getTables():
         if table[3] or table[1] == 'spatial_ref_sys':
             pass
         else:
             tbl_list.append(table[1])
     if len(tbl_list) == 0:
         QMessageBox.warning(
             None, 'Layer and Tables',
             """There are no tables to geo-code in this database.""")
     else:
         self.dlg.cmb_geo.addItems(tbl_list)
Пример #3
0
    def __init__(self, db_settings=None):
        """
        Manuals for db connectors:
        https://github.com/qgis/QGIS/blob/master/python/plugins/db_manager/db_plugins/connector.py
        https://github.com/qgis/QGIS/blob/master/python/plugins/db_manager/db_plugins/postgis/connector.py
        https://github.com/qgis/QGIS/blob/master/python/plugins/db_manager/db_plugins/spatialite/connector.py
        """
        self.conn = None
        self.cursor = None
        self.connector = None

        if db_settings is None:
            db_settings = QgsProject.instance().readEntry(
                "Midvatten", "database")[0]

        if isinstance(db_settings, str):
            #Test if the db_setting is an old database
            if os.path.isfile(db_settings):
                db_settings = {'spatialite': {'dbpath': db_settings}}
            else:
                if not db_settings:
                    raise utils.UsageError(
                        ru(
                            QCoreApplication.translate(
                                'DbConnectionManager',
                                'Database setting was empty. Check DB tab in Midvatten settings.'
                            )))
                else:
                    try:
                        db_settings = ast.literal_eval(db_settings)
                    except:
                        raise utils.UsageError(
                            ru(
                                QCoreApplication.translate(
                                    'DbConnectionManager',
                                    'Database could not be set. Check DB tab in Midvatten settings.'
                                )))

        elif isinstance(db_settings, dict):
            # Assume it the dict is a valid db_settings dict.
            pass
        else:
            raise Exception(
                ru(
                    QCoreApplication.translate(
                        'DbConnectionManager',
                        "DbConnectionManager programming error: db_settings must be either a dict like {'spatialite': {'dbpath': 'x'} or a string representation of it. Was: %s"
                    )) % ru(db_settings))

        db_settings = ru(db_settings, keep_containers=True)

        self.db_settings = db_settings

        self.dbtype = list(self.db_settings.keys())[0]
        self.connection_settings = list(self.db_settings.values())[0]

        self.uri = QgsDataSourceUri()

        if self.dbtype == 'spatialite':
            self.dbpath = ru(self.connection_settings['dbpath'])

            if not os.path.isfile(self.dbpath):
                raise utils.UsageError(
                    ru(
                        QCoreApplication.translate(
                            'DbConnectionManager',
                            'Database error! File "%s" not found! Check db tab in Midvatten settings!'
                        )) % self.dbpath)

            self.check_db_is_locked()

            #Create the database if it's not existing
            self.uri.setDatabase(self.dbpath)

            try:
                self.connector = spatialite_connector.SpatiaLiteDBConnector(
                    self.uri)
            except Exception as e:

                utils.MessagebarAndLog.critical(bar_msg=ru(
                    QCoreApplication.translate(
                        'DbConnectionManager',
                        'Connecting to spatialite db %s failed! Check that the file or path exists.'
                    )) % self.dbpath,
                                                log_msg=ru(
                                                    QCoreApplication.translate(
                                                        'DbConnectionManager',
                                                        'msg %s')) % str(e))
                raise

        elif self.dbtype == 'postgis':
            connection_name = self.connection_settings['connection'].split(
                '/')[0]
            self.postgis_settings = get_postgis_connections()[connection_name]
            self.uri.setConnection(self.postgis_settings['host'],
                                   self.postgis_settings['port'],
                                   self.postgis_settings['database'],
                                   self.postgis_settings['username'],
                                   self.postgis_settings['password'])
            try:
                self.connector = postgis_connector.PostGisDBConnector(self.uri)
            except Exception as e:
                print(str(e))
                if 'no password supplied' in str(e):
                    utils.MessagebarAndLog.warning(bar_msg=ru(
                        QCoreApplication.translate(
                            'DbConnectionManager',
                            'No password supplied for postgis connection')))
                    raise utils.UserInterruptError()
                else:
                    raise

        if self.connector is not None:
            self.conn = self.connector.connection
            self.cursor = self.conn.cursor()
Пример #4
0
    def populateLayersView(self):

        # Get connection details of the currently selected connection
        settings = QtCore.QSettings()
        key = utils.baseKey + self.cmbConnections.currentText()
        host = settings.value(key + '/host')
        database = settings.value(key + '/database')
        port = settings.value(key + '/port')
        schema = settings.value(key + '/workspace')
        username, password = utils.getMcUsernameAndPassword(
            self.cmbConnections.currentText())
        if not (username and password):
            return False

        originalText = self.btnConnect.text()
        self.btnConnect.setText(utils.tr("Connecting..."))
        self.btnConnect.setEnabled(False)
        self.btnConnect.repaint()

        # Reset the layers table
        self.setLayersView()

        # Get the postgis username and password from the MIKEC utility
        pgUsername, pgPassword = utils.getPgLogin(host, port, database, schema,
                                                  username, password)

        # Retrieve the geotables from postgis database
        try:
            self.uri = QgsDataSourceURI()
            self.uri.setConnection(host, port, database, pgUsername,
                                   pgPassword)
            self.connection = connector.PostGisDBConnector(self.uri)
            vectorTablesList = self.connection.getVectorTables(schema)
            rasterTablesList = self.connection.getRasterTables(schema)
            geotablesList = vectorTablesList + rasterTablesList
        except ConnectionError:
            QtGui.QMessageBox.information(
                self, utils.tr("Connection failed"),
                utils.tr(
                    "Connection failed - Check settings and try again.\n\n"))
            self.connection = None

        if self.connection:
            # Get additional table information from mc2qgis utility
            layersInfoList = utils.getMikecLayersInfo(host, port, database,
                                                      schema, username,
                                                      password)

        # Populate the layers view with tables for which information is present in both connections
        if self.connection and layersInfoList:
            for geotable in geotablesList:
                layerProperty = {}
                layerProperty[
                    'mc_connection_name'] = self.cmbConnections.currentText()
                layerProperty['table_name'] = geotable[1]
                layerInfo = next(
                    (item for item in layersInfoList
                     if item["Table"] == layerProperty['table_name']), None)
                if layerInfo:
                    layerProperty['layer_name'] = layerInfo["Name"]
                    layerProperty['table_path'] = layerInfo["Path"]
                    layerProperty['table_keywords'] = layerInfo["Keywords"]
                else:
                    continue

                if geotable in vectorTablesList:
                    layerProperty['table_type'] = geotable[9]
                    layerProperty['table_srid'] = str(geotable[11])
                else:
                    layerProperty['table_type'] = "RASTER"
                    layerProperty['table_srid'] = str(geotable[13])
                layerProperty['geometry_column'] = geotable[8]
                layerProperty['table_schema'] = geotable[2]

                self.layersModel.addTableEntry(layerProperty)
                self.btnOpen.setDisabled(False)
                self.btnImportRaster.setDisabled(False)

        self.mcConnectionName = self.cmbConnections.currentText()
        self.connection = None
        self.btnConnect.setText(originalText)
        self.btnConnect.setEnabled(True)
Пример #5
0
    def __init__(self, db_settings=None):
        """
        Manuals for db connectors:
        https://github.com/qgis/QGIS/blob/master/python/plugins/db_manager/db_plugins/connector.py
        https://github.com/qgis/QGIS/blob/master/python/plugins/db_manager/db_plugins/postgis/connector.py
        https://github.com/qgis/QGIS/blob/master/python/plugins/db_manager/db_plugins/spatialite/connector.py
        """
        self.conn = None
        self.cursor = None

        if db_settings is None:
            db_settings = QgsProject.instance().readEntry(
                "Midvatten", "database")[0]

        if isinstance(db_settings, basestring):
            #Test if the db_setting is an old database
            if os.path.isfile(db_settings):
                db_settings = {u'spatialite': {u'dbpath': db_settings}}
            else:
                if not db_settings:
                    # TODO: Something feels off here. It should not return None, as that will just cause other hard to solve errors.
                    # TODO An exception feels better but is uglier for the user.
                    utils.MessagebarAndLog.critical(bar_msg=utils.returnunicode(
                        QCoreApplication.translate(
                            u'DbConnectionManager',
                            u'Database not chosen correctly. Check DB tab in Midvatten settings.'
                        )))
                    return None
                else:
                    try:
                        db_settings = ast.literal_eval(db_settings)
                    except:
                        #TODO: Something feels off here. It should not return None, as that will just cause other hard to solve errors.
                        #TODO An exception feels better but is uglier for the user.
                        utils.MessagebarAndLog.critical(
                            bar_msg=utils.returnunicode(
                                QCoreApplication.translate(
                                    u'DbConnectionManager',
                                    u'Database connection failed. Try reset settings.'
                                )))
                        return None
        elif isinstance(db_settings, dict):
            pass
        else:
            raise Exception(
                utils.returnunicode(
                    QCoreApplication.translate(
                        u'DbConnectionManager',
                        u"DbConnectionManager error: db_settings must be either a dict like {u'spatialite': {u'dbpath': u'x'} or a string representation of it. Was: %s"
                    )) % utils.returnunicode(db_settings))

        db_settings = utils.returnunicode(db_settings, keep_containers=True)

        self.db_settings = db_settings

        self.dbtype = self.db_settings.keys()[0]
        self.connection_settings = self.db_settings.values()[0]

        self.uri = QgsDataSourceURI()

        if self.dbtype == u'spatialite':
            self.dbpath = utils.returnunicode(
                self.connection_settings[u'dbpath'])
            self.check_db_is_locked()

            #Create the database if it's not existing
            self.uri.setDatabase(self.dbpath)
            try:
                self.conn = sqlite.connect(self.dbpath,
                                           detect_types=sqlite.PARSE_DECLTYPES
                                           | sqlite.PARSE_COLNAMES)
            except:
                utils.MessagebarAndLog.critical(bar_msg=utils.returnunicode(
                    QCoreApplication.translate(
                        u'DbConnectionManager',
                        u'Connecting to spatialite db %s failed! Check that the file or path exists.'
                    )) % self.dbpath)
                self.conn = None
            else:
                try:
                    self.connector = spatialite_connector.SpatiaLiteDBConnector(
                        self.uri)
                except:
                    pass
                self.cursor = self.conn.cursor()
        elif self.dbtype == u'postgis':
            connection_name = self.connection_settings[u'connection'].split(
                u'/')[0]
            self.postgis_settings = get_postgis_connections()[connection_name]
            self.uri.setConnection(self.postgis_settings[u'host'],
                                   self.postgis_settings[u'port'],
                                   self.postgis_settings[u'database'],
                                   self.postgis_settings[u'username'],
                                   self.postgis_settings[u'password'])
            try:
                self.connector = postgis_connector.PostGisDBConnector(self.uri)
            except Exception as e:
                if u'no password supplied' in str(e):
                    utils.MessagebarAndLog.warning(bar_msg=utils.returnunicode(
                        QCoreApplication.translate(
                            u'DbConnectionManager',
                            u'No password supplied for postgis connection')))
                    raise utils.UserInterruptError()
                else:
                    raise

            self.conn = self.connector.connection
            self.cursor = self.connector._get_cursor()
Пример #6
0
    def adding(self, layer_info):
        """Add a layer to QGIS map canvas.

        Take layer index, search the required information to add it in
        the temporary dictionnary constructed in the show_results function.
        It then adds it.
        """
        # one of many add-on option
        if layer_info[0] == "index":
            combobox = self.tbl_result.cellWidget(layer_info[1], 3)
            layer_label = self.tbl_result.cellWidget(layer_info[1], 0).text()
            layer_info = combobox.itemData(combobox.currentIndex())
        # the only add_on option available
        elif layer_info[0] == "info":
            layer_label = self.tbl_result.cellWidget(layer_info[2], 0).text()
            layer_info = layer_info[1]
        else:
            pass
        self.md_sync.tr = self.tr
        logger.info(
            "Adding a layer from those parameters :{}".format(layer_info))

        if type(layer_info) == list:
            # If the layer to be added is a vector file
            if layer_info[0] == "vector":
                path = layer_info[1]
                name = os.path.basename(path).split(".")[0]
                layer = QgsVectorLayer(path, layer_label, "ogr")
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    try:
                        QgsMessageLog.logMessage(
                            message="Data layer added: {}".format(name),
                            tag="Isogeo",
                            level=0,
                        )
                        logger.debug("Vector layer added: {}".format(path))
                    except UnicodeEncodeError:
                        QgsMessageLog.logMessage(
                            message="Vector layer added:: {}".format(
                                name.decode("latin1")),
                            tag="Isogeo",
                            level=0,
                        )
                        logger.debug("Vector layer added: {}".format(
                            name.decode("latin1")))
                else:
                    error_msg = layer.error().message()
                    logger.warning(
                        "Invalid vector layer: {}. QGIS says: {}".format(
                            path, error_msg))
                    QMessageBox.information(
                        iface.mainWindow(),
                        self.tr("Error", context=__class__.__name__),
                        self.tr(
                            "Vector not valid {}. QGIS says: {}",
                            context=__class__.__name__,
                        ).format(path, error_msg),
                    )
            # If raster file
            elif layer_info[0] == "raster":
                path = layer_info[1]
                name = os.path.basename(path).split(".")[0]
                layer = QgsRasterLayer(path, layer_label)
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    try:
                        QgsMessageLog.logMessage(
                            message="Data layer added: {}".format(name),
                            tag="Isogeo",
                            level=0,
                        )
                        logger.debug("Raster layer added: {}".format(path))
                    except UnicodeEncodeError:
                        QgsMessageLog.logMessage(
                            message="Raster layer added:: {}".format(
                                name.decode("latin1")),
                            tag="Isogeo",
                            level=0,
                        )
                        logger.debug("Raster layer added: {}".format(
                            name.decode("latin1")))
                else:
                    error_msg = layer.error().message()
                    logger.warning(
                        "Invalid raster layer: {}. QGIS says: {}".format(
                            path, error_msg))
                    QMessageBox.information(
                        iface.mainWindow(),
                        self.tr("Error", context=__class__.__name__),
                        self.tr(
                            "Raster not valid {}. QGIS says: {}",
                            context=__class__.__name__,
                        ).format(path, error_msg),
                    )
            # If EFS link
            elif layer_info[0] == "EFS":
                name = layer_info[1]
                uri = layer_info[2]
                layer = QgsVectorLayer(uri, layer_label, "arcgisfeatureserver")
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    logger.debug("EFS layer added: {}".format(uri))
                else:
                    error_msg = layer.error().message()
                    logger.warning("Invalid service: {}. QGIS says: {}".format(
                        uri, error_msg))
                    QMessageBox.information(
                        iface.mainWindow(),
                        self.tr("Error", context=__class__.__name__),
                        self.tr("EFS not valid. QGIS says: {}",
                                context=__class__.__name__).format(error_msg),
                    )
            # If EMS link
            elif layer_info[0] == "EMS":
                name = layer_info[1]
                uri = layer_info[2]
                layer = QgsRasterLayer(uri, layer_label, "arcgismapserver")
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    logger.debug("EMS layer added: {}".format(uri))
                else:
                    error_msg = layer.error().message()
                    logger.warning("Invalid service: {}. QGIS says: {}".format(
                        uri, error_msg))
                    QMessageBox.information(
                        iface.mainWindow(),
                        self.tr("Error", context=__class__.__name__),
                        self.tr("EMS not valid. QGIS says: {}",
                                context=__class__.__name__).format(error_msg),
                    )
            # If WFS link
            elif layer_info[0] == "WFS":
                url = layer_info[2]
                name = layer_info[1]
                layer = QgsVectorLayer(url, layer_label, "WFS")
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    logger.debug("WFS layer added: {}".format(url))
                else:
                    error_msg = layer.error().message()
                    name_url = self.build_wfs_url(layer_info[3],
                                                  layer_info[4],
                                                  mode="complete")
                    if name_url[0] != 0:
                        layer = QgsVectorLayer(name_url[2], layer_label, "WFS")
                        if layer.isValid():
                            lyr = QgsProject.instance().addMapLayer(layer)
                            logger.debug("WFS layer added: {}".format(url))
                        else:
                            error_msg = layer.error().message()
                            logger.warning(
                                "Invalid service: {}. QGIS says: {}".format(
                                    url, error_msg))
                    else:
                        QMessageBox.information(
                            iface.mainWindow(),
                            self.tr("Error", context=__class__.__name__),
                            self.tr(
                                "WFS is not valid. QGIS says: {}",
                                context=__class__.__name__,
                            ).format(error_msg),
                        )
                        pass
            # If WMS link
            elif layer_info[0] == "WMS":
                url = layer_info[2]
                name = layer_info[1]
                layer = QgsRasterLayer(url, layer_label, "wms")
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    logger.debug("WMS layer added: {}".format(url))
                else:
                    error_msg = layer.error().message()
                    name_url = self.build_wms_url(layer_info[3],
                                                  layer_info[4],
                                                  mode="complete")
                    if name_url[0] != 0:
                        layer = QgsRasterLayer(name_url[2], layer_label, "wms")
                        if layer.isValid():
                            lyr = QgsProject.instance().addMapLayer(layer)
                            logger.debug("WMS layer added: {}".format(url))
                        else:
                            error_msg = layer.error().message()
                            logger.warning(
                                "Invalid service: {}. QGIS says: {}".format(
                                    url, error_msg))
                    else:
                        QMessageBox.information(
                            iface.mainWindow(),
                            self.tr("Error", context=__class__.__name__),
                            self.tr(
                                "WMS is not valid. QGIS says: {}",
                                context=__class__.__name__,
                            ).format(error_msg),
                        )
            # If WMTS link
            elif layer_info[0] == "WMTS":
                url = layer_info[2]
                name = layer_info[1]
                layer = QgsRasterLayer(url, layer_label, "wms")
                if layer.isValid():
                    lyr = QgsProject.instance().addMapLayer(layer)
                    logger.debug("WMTS service layer added: {}".format(url))
                else:
                    error_msg = layer.error().message()
                    logger.warning("Invalid service: {}. QGIS says: {}".format(
                        url, error_msg))
                    QMessageBox.information(
                        iface.mainWindow(),
                        self.tr("Error", context=__class__.__name__),
                        self.tr(
                            "WMTS is not valid. QGIS says: {}",
                            context=__class__.__name__,
                        ).format(error_msg),
                    )
            else:
                pass

        # If the data is a PostGIS table
        elif isinstance(layer_info, dict):
            logger.debug("Data type: PostGIS")
            # Give aliases to the data passed as arguement
            base_name = layer_info.get("base_name", "")
            schema = layer_info.get("schema", "")
            table = layer_info.get("table", "")
            # Retrieve the database information stored in the PostGISdict
            uri = QgsDataSourceUri()
            host = self.PostGISdict[base_name]["host"]
            port = self.PostGISdict[base_name]["port"]
            user = self.PostGISdict[base_name]["username"]
            password = self.PostGISdict[base_name]["password"]
            # set host name, port, database name, username and password
            uri.setConnection(host, port, base_name, user, password)
            # Get the geometry column name from the database connexion & table
            # name.
            c = pgis_con.PostGisDBConnector(uri)
            dico = c.getTables()
            for i in dico:
                if i[0 == 1] and i[1] == table:
                    geometry_column = i[8]
            # set database schema, table name, geometry column
            uri.setDataSource(schema, table, geometry_column)
            # Adding the layer to the map canvas
            layer = QgsVectorLayer(uri.uri(), table, "postgres")
            if layer.isValid():
                lyr = QgsProject.instance().addMapLayer(layer)
                logger.debug("Data added: {}".format(table))
            elif (not layer.isValid() and plg_tools.last_error[0] == "postgis"
                  and "prim" in plg_tools.last_error[1]):
                logger.debug("PostGIS layer may be a view, "
                             "so key column is missing. "
                             "Trying to automatically set one...")
                # get layer fields to set as key column
                fields = layer.dataProvider().fields()
                fields_names = [i.name() for i in fields]
                # sort them by name containing id to better perf
                fields_names.sort(key=lambda x: ("id" not in x, x))
                for field in fields_names:
                    uri.setKeyColumn(field)
                    layer = QgsVectorLayer(uri.uri(True), table, "postgres")
                    if layer.isValid():
                        lyr = QgsProject.instance().addMapLayer(layer)
                        logger.debug(
                            "PostGIS view layer added with [{}] as key column".
                            format(field))
                        # filling 'QGIS Server' tab of layer Properties
                        self.md_sync.basic_sync(layer=lyr, info=layer_info)
                        return 1
                    else:
                        continue
            else:
                logger.debug("Layer not valid. table = {}".format(table))
                QMessageBox.information(
                    iface.mainWindow(),
                    self.tr("Error", context=__class__.__name__),
                    self.tr(
                        "The PostGIS layer is not valid."
                        " Reason: {}",
                        context=__class__.__name__,
                    ).format(plg_tools.last_error),
                )
                return 0
        # filling 'QGIS Server' tab of layer Properties
        if layer.isValid():
            try:
                self.md_sync.basic_sync(layer=lyr, info=layer_info)
            except IndexError as e:
                logger.debug(
                    "Not supported 'layer_info' format causes this error : {}".
                    format(e))
        else:
            pass
        return 1