Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select crs #31

Merged
merged 10 commits into from
Jul 4, 2017
119 changes: 112 additions & 7 deletions PyQt4Dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from qgisToolbox import FeatureSelector
from PyQt4Widgets import XQPushButton, XQDialogButtonBox
from database import *
from utilities import images_path, get_ui_class
from utilities import images_path, get_ui_class, get_path

UI_CLASS = get_ui_class("ui_pgnewconnection.ui")

Expand Down Expand Up @@ -183,25 +183,24 @@ def __init__(self):
None, Qt.WindowStaysOnTopHint)
# initialize ui
self.connection = None
self.crs = None
self.setup_ui()
self.populate_database_choices()

def get_database_connection(self):
return self.connection

def get_crs(self):
return self.crs

def populate_database_choices(self):
""" Populate database connection choices
"""
self.cmbbx_conn.clear()
settings = QSettings()
settings.beginGroup('PostgreSQL/connections')
self.cmbbx_conn.addItem(_from_utf8(""))
self.cmbbx_conn.setItemText(0, QApplication.translate(
"DatabaseConnectionDialog", "", None))
for index, database in enumerate(settings.childGroups()):
self.cmbbx_conn.addItem(_from_utf8(""))
self.cmbbx_conn.setItemText(index + 1, QApplication.translate(
"DatabaseConnectionDialog", database, None))
self.cmbbx_conn.addItem(database)

def test_database_connection(self):
""" Test database connection has necessary tables
Expand All @@ -214,8 +213,104 @@ def test_database_connection(self):
"Please select a database connection")
else:
self.connection = connection

if self.connection:
ok = self.test_database_schema()
if not ok:
return
self.accept()

def test_database_schema(self):
"""Test whether co-go schema is applied in the database."""
query = "SELECT EXISTS (SELECT 1 AS result FROM pg_tables " \
"WHERE schemaname = 'public' AND tablename = 'beacons')"

settings_postgis = QSettings()
settings_postgis.beginGroup('PostgreSQL/connections')
max_attempts = 3
is_credential_exist = True

db_service = settings_postgis.value(self.connection + '/service')
db_host = settings_postgis.value(self.connection + '/host')
db_port = settings_postgis.value(self.connection + '/port')
db_name = settings_postgis.value(self.connection + '/database')
db_username = settings_postgis.value(self.connection + '/username')
db_password = settings_postgis.value(self.connection + '/password')

uri = QgsDataSourceURI()
uri.setConnection(
db_host,
db_port,
db_name,
db_username,
db_password)

if not db_username and not db_password:
msg = "Please enter the username and password."
for i in range(max_attempts):
ok, db_username, db_password = (
QgsCredentials.instance().get(
uri.connectionInfo(),
db_username,
db_password,
msg
))

connection = None
if is_credential_exist:
if db_service:
connection = psycopg2.connect(
"service='{SERVICE}' user='{USER}' "
"password='{PASSWORD}'".format(
SERVICE=db_service,
USER=db_username,
PASSWORD=db_password
))
else:
connection = psycopg2.connect(
"host='{HOST}' dbname='{NAME}' user='{USER}' "
"password='{PASSWORD}' port='{PORT}'".format(
HOST=db_host,
NAME=db_name,
USER=db_username,
PASSWORD=db_password,
PORT=db_port
))

if connection:
cursor = connection.cursor()
cursor.execute(query)
is_schema_valid = cursor.fetchall()[0][0]
del cursor

if not is_schema_valid:

message = ("WARNING: The selected database does not contain "
"tables and functions required for use of "
"the plugin. Please select a CRS and click "
"OK to procees setting up a database using "
"the chosen CRS.")
crs_options = {
'WGS 84 / UTM zone 31N': 32631,
'Minna / UTM zone 31N': 26331,
'WGS 84 / UTM zone 32N': 32632,
'Minna / UTM zone 32N': 26332
}
items = crs_options.keys()

item, ok = QInputDialog.getItem(
self, "Setup Database Schema", message, items, 0, False)

if item and ok:
query = open(
get_path("scripts","database_setup.sql"), "r").read()
query = query.replace(":CRS", "{CRS}")
cursor = connection.cursor()
cursor.execute(query.format(CRS=crs_options[item]))
connection.commit()

return ok

def setup_ui(self):
""" Initialize ui
"""
Expand Down Expand Up @@ -285,6 +380,16 @@ def setup_ui(self):
"define a new connection.",
None
))
self.btn_new_conn.setToolTip(QApplication.translate(
"DatabaseConnectionDialog",
"Add new PostgreSQL connection",
None
))
self.btn_refresh_conn.setToolTip(QApplication.translate(
"DatabaseConnectionDialog",
"Refresh available PostgreSQL connection",
None
))
# connect ui widgets
self.btnbx_options.accepted.connect(self.test_database_connection)
self.btnbx_options.rejected.connect(self.reject)
Expand Down
3 changes: 2 additions & 1 deletion database.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ def connect(self, parameters):
if not hasattr(self, 'conn') or self.connection is None:
if parameters.get("SERVICE"):
self.connection = psycopg2.connect(
"service='{SERVICE}'".format(
"service='{SERVICE}' user='{USER}' "
"password='{PASSWORD}'".format(
SERVICE=parameters["SERVICE"],
USER=parameters["USER"],
PASSWORD=parameters["PASSWORD"]
Expand Down
27 changes: 23 additions & 4 deletions plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def __init__(self, iface):
self.plugin_dir = os.path.dirname(os.path.realpath(__file__))
self.uri = None
self.connection = None
self.crs = None
self.database = None
self.datetime = datetime.now()
self.required_layers = []
Expand Down Expand Up @@ -162,7 +163,7 @@ def remove_plugin_toolbar(self):
self.iface.mainWindow().removeToolBar(self.plugin_toolbar)
self.plugin_toolbar.hide()

def set_database_connection(self, connection=None):
def set_database_connection(self, connection=None, crs=None):
""" Create a database connection
"""
# fetch settings
Expand All @@ -178,13 +179,16 @@ def set_database_connection(self, connection=None):
if bool(self.connection):
if self.connection not in settings_postgis.childGroups():
settings_plugin.setValue("DatabaseConnection", "")
connection = None
self.connection = None
# fetch from user if necessary
if not bool(self.connection):
dialog = DatabaseConnectionDialog()
dialog.show()
if bool(dialog.exec_()):
self.connection = dialog.get_database_connection()
if dialog.get_crs():
self.crs = QgsCoordinateReferenceSystem(
dialog.get_crs().get('auth_id'))
settings_plugin.setValue("DatabaseConnection", self.connection)
# validate database connection
if bool(self.connection):
Expand Down Expand Up @@ -222,6 +226,8 @@ def set_database_connection(self, connection=None):
error_message))
if not ok:
break
else:
break

else:
msg = "Please enter the username and password."
Expand Down Expand Up @@ -299,6 +305,8 @@ def refresh_layers(self):
required_layer.layer = layer
self.iface.legendInterface().setLayerVisible(
layer, True)
if self.crs:
layer.setCrs(self.crs)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok. But just to be sure how does the selected CRS affect the database operations

@NyakudyaA here, we will set the crs to the selected crs as soon as the layers are added by the plugin to the canvas.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. That's fine. We assume that the user selects a CRS that corresponds to his database in the backend. Later we might need to add rules to check what database CRS has already been assigned to a table and compare this with the selected CRS so that a user can not select a CRS that is not the same as his database

self.iface.zoomToActiveLayer()

def manage_beacons(self):
Expand Down Expand Up @@ -345,9 +353,10 @@ def manage_database_connection(self):
""" Action to select the db connection to work with.
"""
database_manager = DatabaseManager()
connection = database_manager.current_connection
connection = database_manager.get_current_connection()
crs = database_manager.get_current_crs()
if connection:
self.set_database_connection(connection=connection)
self.set_database_connection(connection=connection, crs=crs)


class DatabaseManager():
Expand All @@ -356,13 +365,23 @@ def __init__(self):
self.dialog = DatabaseConnectionDialog()
self.dialog.show()
self.current_connection = None
self.current_crs = None
if bool(self.dialog.exec_()):
self.current_connection = self.dialog.get_database_connection()
self.current_crs = self.dialog.get_crs()
settings_plugin = QSettings()
settings_plugin.beginGroup(metadata.name().replace(" ", "_"))
settings_plugin.setValue(
"DatabaseConnection", self.current_connection)

def get_current_connection(self):

return self.current_connection

def get_current_crs(self):

return self.current_crs


class BeaconManager():

Expand Down
Loading