diff --git a/pygadmin/connectionstore.py b/pygadmin/connectionstore.py index 3c79eca..9453c83 100644 --- a/pygadmin/connectionstore.py +++ b/pygadmin/connectionstore.py @@ -118,6 +118,28 @@ class ConnectionStore: if connection_parameter_dictionary["Username"] == connection_parameter_dictionary_for_check["Username"] \ and connection_parameter_dictionary["Host"] == connection_parameter_dictionary_for_check["Host"] \ and connection_parameter_dictionary["Port"] == connection_parameter_dictionary_for_check["Port"]: + + # If the two dictionaries contain a parameter for loading all databases, check them for their equality. + # If they are not equal, the given connection has changed. + if "Load All" in connection_parameter_dictionary \ + and "Load All" in connection_parameter_dictionary_for_check: + if connection_parameter_dictionary["Load All"] \ + != connection_parameter_dictionary_for_check["Load All"]: + return False + + # If only one dictionary has a key for "Load All", there is a change in the connection parameters. + elif "Load All" in connection_parameter_dictionary \ + or "Load All" in connection_parameter_dictionary_for_check: + return False + + # If load all in the check dictionary is False and if the databases are not the same, the connection has + # changed, because only one database is used. One database is not a universal enter point in this case. + if "Load All" in connection_parameter_dictionary_for_check \ + and connection_parameter_dictionary_for_check["Load All"] is False \ + and connection_parameter_dictionary["Database"] \ + != connection_parameter_dictionary_for_check["Database"]: + return False + return True # If a duplicate is not found, this else branch is active. @@ -217,5 +239,22 @@ class ConnectionStore: except IndexError: return None + def get_connection_load_all_information(self, host, database, port, username): + """ + Get the load all information of one connection defined by its host, database, port and username. + """ + + # Find in all current parameters the one with the correct host, database, port and username. + for parameters in self.connection_parameters_yaml: + if host == parameters["Host"] and database == parameters["Database"] and port == parameters["Port"] \ + and username == parameters["Username"]: + + # Try to get the parameter for loading all databases. This parameter could not exist in the dictionary. + try: + return parameters["Load All"] + + except KeyError: + return False + global_connection_store = ConnectionStore() diff --git a/pygadmin/models/treemodel.py b/pygadmin/models/treemodel.py index 99c0d73..fc76e7b 100644 --- a/pygadmin/models/treemodel.py +++ b/pygadmin/models/treemodel.py @@ -199,7 +199,7 @@ class ServerNode(AbstractBaseNode): Create a class for server nodes based on the class AbstractBaseNode. """ - def __init__(self, name, host, user, port, database="postgres", timeout=1000): + def __init__(self, name, host, user, port, database="postgres", timeout=1000, load_all_databases=True): # Use the database postgres, because this database should definitely exist on a database server and is used as # entry point here. super().__init__(name, host, user, database, port, timeout) @@ -212,8 +212,16 @@ class ServerNode(AbstractBaseNode): node_icon_path = os.path.join(os.path.dirname(pygadmin.__file__), "icons", "{}_valid.svg".format(self._node_type.lower())) + # If all databases should be loaded, this parameter is True. This is a default parameter. + if load_all_databases is True: + child = None + + # If the parameter is not True, only one database should be loaded. + else: + child = database + # Get the children with a query. - self.get_children_with_query() + self.get_children_with_query(child) else: # Use the server icon for a invalid connection. @@ -232,13 +240,21 @@ class ServerNode(AbstractBaseNode): return child - def get_children_with_query(self): + def get_children_with_query(self, child=None): """ - Get all children of the node with a database query. + Get all children of the node with a database query. As default, get all the children of the node, but use an + option for only getting one given child. """ - # Use a query to get all children, in this case, all the database nodes. - self.fetch_children(DatabaseNode, "SELECT datname FROM pg_database ORDER BY datname ASC;") + # If one explicit child is not given, get all the children of the server node. + if child is None: + # Use a query to get all children, in this case, all the database nodes. + self.fetch_children(DatabaseNode, "SELECT datname FROM pg_database ORDER BY datname ASC;") + + # If an explicit child is given, load the one explicit child. + else: + self.fetch_children(DatabaseNode, "SELECT datname FROM pg_database WHERE datname=%s ORDER BY datname ASC;", + [child]) class DatabaseNode(AbstractBaseNode): diff --git a/pygadmin/widgets/connection_dialog.py b/pygadmin/widgets/connection_dialog.py index 3758f7a..157738a 100644 --- a/pygadmin/widgets/connection_dialog.py +++ b/pygadmin/widgets/connection_dialog.py @@ -73,6 +73,10 @@ class ConnectionDialogWidget(QDialog): self.show() def init_line_edit_ui(self): + """ + Initialize the line edits. + """ + # Make a list for storing the QLabels for every connection parameter. This is necessary for using the QLabel in # the layout setting. self.connection_parameter_label_list = [] @@ -213,6 +217,11 @@ class ConnectionDialogWidget(QDialog): # Connect the state change to a function for handling a change in the checked status of the checkbox. self.use_postgres_database_checkbox.stateChanged.connect(self.set_database_edit_field_to_checkbox) + # Create a checkbox for loading all databases as a configurable parameter. + self.load_all_databases_checkbox = QCheckBox("Load all databases") + # Set the default as checked. + self.load_all_databases_checkbox.setChecked(True) + # Create a checkbox for usage in specific cases. self.open_at_start_checkbox = QCheckBox("Open always a connection dialog at start") @@ -242,8 +251,8 @@ class ConnectionDialogWidget(QDialog): # This case happens for the label of the port. else: - # The label is placed further down, so the checkbox for the default database is placed accurate. - grid_layout.addWidget(self.connection_parameter_label_list[parameter_number], parameter_number + 2, 2) + # The label is placed further down, so the checkboxes for the database are placed accurate. + grid_layout.addWidget(self.connection_parameter_label_list[parameter_number], parameter_number + 3, 2) # Use an incrementer for the next for loop. connection_parameter_edit_incrementer = 1 @@ -259,7 +268,8 @@ class ConnectionDialogWidget(QDialog): if connection_parameter == "Database": # Place the checkbox under the QLineEdit for the database. grid_layout.addWidget(self.use_postgres_database_checkbox, connection_parameter_edit_incrementer, 3) - connection_parameter_edit_incrementer += 1 + grid_layout.addWidget(self.load_all_databases_checkbox, connection_parameter_edit_incrementer + 1, 3) + connection_parameter_edit_incrementer += 2 # The port as the parameter which belongs to this checkbox is the last one in the list for the user, so this # checkbox is placed below the QLineEdit for the port. @@ -468,12 +478,14 @@ class ConnectionDialogWidget(QDialog): return - # Define the parameter in a dictionary which is required by the connection store. + # Define the parameters in a dictionary which is required by the connection store. connection_parameters = {"Host": self.connection_parameter_edit_dictionary["Host"].text(), "Username": self.connection_parameter_edit_dictionary["Username"].text(), "Database": self.connection_parameter_edit_dictionary["Database"].text(), # The port is used as integer number, not as string. - "Port": int(self.connection_parameter_edit_dictionary["Port"].text()) + "Port": int(self.connection_parameter_edit_dictionary["Port"].text()), + # Get the status for loading all databases out of the checkbox. + "Load All": self.load_all_databases_checkbox.isChecked() } return connection_parameters, connection_identifier, changed_password @@ -861,6 +873,19 @@ class ConnectionDialogWidget(QDialog): # Use the port as string, because all elements of the QLineEdit have to be strings. str(self.selected_connection_parameters_dictionary["Port"])) + # Get the status for loading all databases for the selected connection. + load_all_databases = global_connection_store.get_connection_load_all_information( + self.selected_connection_parameters_dictionary["Host"], + self.selected_connection_parameters_dictionary["Database"], + self.selected_connection_parameters_dictionary["Port"], + self.selected_connection_parameters_dictionary["Username"] + ) + + # Set the status as status of the checkbox. + self.load_all_databases_checkbox.setChecked(load_all_databases) + # Save the status in the dictionary for the selected connection. + self.selected_connection_parameters_dictionary["Load All"] = load_all_databases + # Define a password identifier for recognition in the password manager and keyring. password_identifier = self.selected_connection_identifier.split("/")[0] # Set the password as text in the QLineEdit. This is not a security flaw, because it is protected by the diff --git a/pygadmin/widgets/tree.py b/pygadmin/widgets/tree.py index 3b6f211..993d3bd 100644 --- a/pygadmin/widgets/tree.py +++ b/pygadmin/widgets/tree.py @@ -178,12 +178,20 @@ class TreeWidget(QWidget): # Create a server node for every connection dictionary. for connection_parameter in connection_parameters: + # Get the parameter for loading all databases. + try: + load_all_databases = connection_parameter["Load All"] + + except KeyError: + load_all_databases = True + new_node = ServerNode(name=connection_parameter["Host"], host=connection_parameter["Host"], user=connection_parameter["Username"], database=connection_parameter["Database"], port=connection_parameter["Port"], - timeout=connection_parameter["Timeout"]) + timeout=connection_parameter["Timeout"], + load_all_databases=load_all_databases) # Append the node to the server list. server_node_list.append(new_node) @@ -415,6 +423,13 @@ class TreeWidget(QWidget): the server node. """ + # Get the parameter for loading all databases. + try: + load_all_databases = connection_parameters_for_server_node["Load All"] + + except KeyError: + load_all_databases = True + # Try to create a server node. try: # Check for a duplicate, because only one server node is necessary for one host, user and port. @@ -424,7 +439,8 @@ class TreeWidget(QWidget): user=connection_parameters_for_server_node["Username"], database=connection_parameters_for_server_node["Database"], port=connection_parameters_for_server_node["Port"], - timeout=connection_parameters_for_server_node["Timeout"]) + timeout=connection_parameters_for_server_node["Timeout"], + load_all_databases=load_all_databases) else: # If there is a duplicate, set the server node as return value to None, because a server node was not