Exemple #1
0
    def acceptdlg(self):
        """
        On user clicking the login button
        """
        isValid = self.validateInput()
        if isValid:
            # Capture DB connection properties
            host = self.txtHost.text()
            port = self.txtPort.text()
            database = self.txtDatabase.text()
            dbconfig = DatabaseConfig()
            try:
                self.dbconn = DatabaseConnection(host, port, database)
                # Write DB conn object to the registry
                dbconfig.write(self.dbconn)
            except Exception as ex:
                QMessageBox.critical(self, QApplication.translate("DbConnectionDialog", "Error saving settings"),
                                     QApplication.translate("DbConnectionDialog", unicode(ex.message)))

            self.accept()
Exemple #2
0
    def acceptdlg(self):
        '''
        On user clicking the login button
        '''
        isValid = self.validateInput()
        if isValid:
            #Capture DB connection properties
            host = self.txtHost.text()
            port = self.txtPort.text()
            database = self.txtDatabase.text()
            dbconfig = DatabaseConfig()
            try:
                self.dbconn = DatabaseConnection(host,port,database)
                #Write DB conn object to the registry
                dbconfig.write(self.dbconn)
            except Exception as ex:
                QMessageBox.critical(self, QApplication.translate("DbConnectionDialog","Error saving settings"),
                                 QApplication.translate("DbConnectionDialog",unicode(ex.message)))

            self.accept()
Exemple #3
0
class OptionsDialog(QDialog, Ui_DlgOptions):
    """
    Dialog for editing STDM settings.
    """
    def __init__(self, iface):
        QDialog.__init__(self, iface.mainWindow())
        self.setupUi(self)
        self.iface = iface

        self.notif_bar = NotificationBar(self.vlNotification, 6000)
        self._apply_btn = self.buttonBox.button(QDialogButtonBox.Apply)
        self._reg_config = RegistryConfig()
        self._db_config = DatabaseConfig()

        #Connect signals
        self._apply_btn.clicked.connect(self.apply_settings)
        self.buttonBox.accepted.connect(self.on_accept)
        self.chk_pg_connections.toggled.connect(self._on_use_pg_connections)
        self.cbo_pg_connections.currentIndexChanged.connect(
            self._on_pg_profile_changed)
        self.btn_db_conn_clear.clicked.connect(self.clear_properties)
        self.btn_test_db_connection.clicked.connect(self._on_test_connection)
        self.btn_supporting_docs.clicked.connect(
            self._on_choose_supporting_docs_path)
        self.btn_template_folder.clicked.connect(
            self._on_choose_doc_designer_template_path)
        self.btn_composer_out_folder.clicked.connect(
            self._on_choose_doc_generator_output_path)
        self.upgradeButton.toggled.connect(self.manage_upgrade)

        self._config = StdmConfiguration.instance()
        self._default_style_sheet = self.txtRepoLocation.styleSheet()

        self.manage_upgrade()

        self.init_gui()

    def init_gui(self):
        #Set integer validator for the port number
        int_validator = QIntValidator(1024, 49151)
        self.txtPort.setValidator(int_validator)

        #Load profiles
        self.load_profiles()

        #Set current profile in the combobox
        curr_profile = current_profile()
        if not curr_profile is None:
            setComboCurrentIndexWithText(self.cbo_profiles, curr_profile.name)

        #Load current database connection properties
        self._load_db_conn_properties()

        #Load existing PostgreSQL connections
        self._load_qgis_pg_connections()

        #Load directory paths
        self._load_directory_paths()

        # Debug logging
        lvl = debug_logging()
        if lvl:
            self.chk_logging.setCheckState(Qt.Checked)
        else:
            self.chk_logging.setCheckState(Qt.Unchecked)

    def load_profiles(self):
        """
        Load existing profiles into the combobox.
        """
        profile_names = self._config.profiles.keys()

        self.cbo_profiles.clear()
        self.cbo_profiles.addItem('')
        self.cbo_profiles.addItems(profile_names)

    def _load_db_conn_properties(self):
        #Load database connection properties from the registry.
        db_conn = self._db_config.read()

        if not db_conn is None:
            self.txtHost.setText(db_conn.Host)
            self.txtPort.setText(db_conn.Port)
            self.txtDatabase.setText(db_conn.Database)

    def _load_qgis_pg_connections(self):
        """
        Load QGIS postgres connections.
        """
        self.cbo_pg_connections.addItem('')

        profiles = pg_profile_names()
        for profile in profiles:
            self.cbo_pg_connections.addItem(profile[0], profile[1])

    def _load_directory_paths(self):
        #Load paths to various directory settings.
        comp_out_path = composer_output_path()
        comp_temp_path = composer_template_path()
        source_doc_path = source_documents_path()

        if not source_doc_path is None:
            self.txtRepoLocation.setText(source_doc_path)

        if not comp_out_path is None:
            self.txt_output_dir.setText(comp_out_path)

        if not comp_temp_path is None:
            self.txt_template_dir.setText(comp_temp_path)

    def _on_use_pg_connections(self, state):
        #Slot raised when to (not) use existing pg connections
        if not state:
            self.cbo_pg_connections.setCurrentIndex(0)
            self.cbo_pg_connections.setEnabled(False)

            #Restore current connection in registry
            self._load_db_conn_properties()

        else:
            self.cbo_pg_connections.setEnabled(True)

    def _on_pg_profile_changed(self, index):
        """
        Slot raised when the index of the pg profile changes. If the
        selection is valid then the system will attempt to extract
        the database connection properties of the selected profile
        stored in the registry.
        """
        if index == 0:
            return

        profile_path = self.cbo_pg_connections.itemData(index)

        q_config = QGISRegistryConfig(profile_path)
        db_items = q_config.read(['Database', 'Host', 'Port'])

        if len(db_items) > 0:
            self.txtDatabase.setText(db_items['Database'])
            self.txtHost.setText(db_items['Host'])
            self.txtPort.setText(db_items['Port'])

    def clear_properties(self):
        """
        Clears the host, database name and port number values from the
        respective controls.
        """
        self.txtDatabase.clear()
        self.txtHost.clear()
        self.txtPort.clear()

    def _on_choose_supporting_docs_path(self):
        #Slot raised to select directory for supporting documents.
        self._set_selected_directory(self.txtRepoLocation,
                                     self.tr('Supporting Documents Directory'))

    def _on_choose_doc_designer_template_path(self):
        #Slot raised to select directory for document designer templates.
        self._set_selected_directory(
            self.txt_template_dir,
            self.tr('Document Designer Templates Directory'))

    def _on_choose_doc_generator_output_path(self):
        #Slot raised to select directory for doc generator outputs.
        self._set_selected_directory(
            self.txt_output_dir,
            self.tr('Document Generator Output Directory'))

    def _set_selected_directory(self, txt_box, title):
        def_path = txt_box.text()
        sel_doc_path = QFileDialog.getExistingDirectory(self, title, def_path)

        if sel_doc_path:
            normalized_path = QDir.fromNativeSeparators(sel_doc_path)
            txt_box.clear()
            txt_box.setText(normalized_path)

    def _validate_db_props(self):
        #Test if all properties have been specified
        status = True

        self.notif_bar.clear()

        if not self.txtHost.text():
            msg = self.tr('Please specify the database host address.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        if not self.txtPort.text():
            msg = self.tr('Please specify the port number.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        if not self.txtDatabase.text():
            msg = self.tr('Please specify the database name.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        return status

    def _database_connection(self):
        #Creates a databaase connection object from the specified args
        host = self.txtHost.text()
        port = self.txtPort.text()
        database = self.txtDatabase.text()

        #Create database connection object
        db_conn = DatabaseConnection(host, port, database)

        return db_conn

    def _on_test_connection(self):
        """
        Slot raised to test database connection.
        """
        status = self._validate_db_props()

        if not status:
            return

        login_dlg = loginDlg(self, True)
        db_conn = self._database_connection()
        login_dlg.set_database_connection(db_conn)

        res = login_dlg.exec_()
        if res == QDialog.Accepted:
            msg = self.tr(u"Connection to '{0}' database was "
                          "successful.".format(db_conn.Database))
            QMessageBox.information(self, self.tr('Database Connection'), msg)

    def set_current_profile(self):
        """
        Saves the given profile name as the current profile.
        """
        profile_name = self.cbo_profiles.currentText()

        if not profile_name:
            self.notif_bar.clear()

            msg = self.tr('Profile name is empty, current profile will not '
                          'be set.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        save_current_profile(profile_name)

        return True

    def save_database_properties(self):
        """
        Saves the specified database connection properties to the registry.
        :return: True if the connection properties were successfully saved.
        :rtype: bool
        """
        if not self._validate_db_props():
            return False

        #Create a database object and write it to the registry
        db_conn = self._database_connection()
        self._db_config.write(db_conn)

        return True

    def set_supporting_documents_path(self):
        """
        Set the directory of supporting documents.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txtRepoLocation.text()

        if not path:
            msg = self.tr('Please set the supporting documents directory.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        #Validate path
        if not self._check_path_exists(path, self.txtRepoLocation):
            return False

        #Commit to registry
        self._reg_config.write({NETWORK_DOC_RESOURCE: path})

        return True

    def set_document_templates_path(self):
        """
        Set the directory of document designer templates.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txt_template_dir.text()

        if not path:
            msg = self.tr('Please set the document designer templates '
                          'directory.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        #Validate path
        if not self._check_path_exists(path, self.txt_template_dir):
            return False

        #Commit to registry
        self._reg_config.write({COMPOSER_TEMPLATE: path})

        return True

    def set_document_output_path(self):
        """
        Set the directory of document generator outputs.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txt_output_dir.text()

        if not path:
            msg = self.tr('Please set the document generator output directory'
                          '.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        #Validate path
        if not self._check_path_exists(path, self.txt_output_dir):
            return False

        #Commit to registry
        self._reg_config.write({COMPOSER_OUTPUT: path})

        return True

    def _check_path_exists(self, path, text_box):
        #Validates if the specified folder exists
        dir = QDir()

        if not dir.exists(path):
            msg = self.tr(u"'{0}' directory does not exist.".format(path))
            self.notif_bar.insertErrorNotification(msg)

            #Highlight textbox control
            text_box.setStyleSheet(INVALIDATESTYLESHEET)

            timer = QTimer(self)
            #Sync interval with that of the notification bar
            timer.setInterval(self.notif_bar.interval)
            timer.setSingleShot(True)

            #Remove previous connected slots (if any)
            receivers = timer.receivers(SIGNAL('timeout()'))
            if receivers > 0:
                self._timer.timeout.disconnect()

            timer.start()
            timer.timeout.connect(lambda: self._restore_stylesheet(text_box))

            return False

        return True

    def _restore_stylesheet(self, textbox):
        # Slot raised to restore the original stylesheet of the textbox control
        textbox.setStyleSheet(self._default_style_sheet)

        # Get reference to timer and delete
        sender = self.sender()
        if not sender is None:
            sender.deleteLater()

    def apply_debug_logging(self):
        # Save debug logging
        logger = logging.getLogger('stdm')

        if self.chk_logging.checkState() == Qt.Checked:
            logger.setLevel(logging.DEBUG)
            set_debug_logging(True)
        else:
            logger.setLevel(logging.ERROR)
            set_debug_logging(False)

    def apply_settings(self):
        """
        Save settings.
        :return: True if the settings were successfully applied, otherwise
        False.
        :rtype: bool
        """
        #Set current profile
        if not self.set_current_profile():
            return False

        #Set db connection properties
        if not self.save_database_properties():
            return False

        #Set supporting documents directory
        if not self.set_supporting_documents_path():
            return False

        #Set document designer templates path
        if not self.set_document_templates_path():
            return False

        #Set document generator output path
        if not self.set_document_output_path():
            return False

        self.apply_debug_logging()

        msg = self.tr('Settings successfully saved.')
        self.notif_bar.insertSuccessNotification(msg)

        return True

    def on_accept(self):
        """
        Slot raised to save the settings of the current widget and close the
        widget.
        """
        if not self.apply_settings():
            return

        self.accept()

    def manage_upgrade(self):
        """
        A slot raised when the upgrade button is clicked.
        It disables or enables the upgrade
        button based on the ConfigUpdated registry value.
        """

        self.config_updated_dic = self._reg_config.read([CONFIG_UPDATED])

        # if config file exists, check if registry key exists
        if len(self.config_updated_dic) > 0:
            config_updated_val = self.config_updated_dic[CONFIG_UPDATED]
            # If failed to upgrade, enable the upgrade button
            if config_updated_val == '0' or config_updated_val == '-1':
                self.upgradeButton.setEnabled(True)

            # disable the button if any other value.
            else:
                self.upgradeButton.setEnabled(False)
        else:
            self.upgradeButton.setEnabled(False)
Exemple #4
0
class OptionsDialog(QDialog, Ui_DlgOptions):
    """
    Dialog for editing STDM settings.
    """
    def __init__(self, iface):
        QDialog.__init__(self, iface.mainWindow())
        self.setupUi(self)
        self.iface = iface

        self.notif_bar = NotificationBar(self.vlNotification, 6000)
        self._apply_btn = self.buttonBox.button(QDialogButtonBox.Apply)
        self._reg_config = RegistryConfig()
        self._db_config = DatabaseConfig()

        # Connect signals
        self._apply_btn.clicked.connect(self.apply_settings)
        self.buttonBox.accepted.connect(self.on_accept)
        self.chk_pg_connections.toggled.connect(self._on_use_pg_connections)
        self.cbo_pg_connections.currentIndexChanged.connect(
            self._on_pg_profile_changed)
        self.btn_db_conn_clear.clicked.connect(self.clear_properties)
        self.btn_test_db_connection.clicked.connect(
            self._on_test_db_connection)
        self.btn_template_folder.clicked.connect(
            self._on_choose_doc_designer_template_path)
        self.btn_composer_out_folder.clicked.connect(
            self._on_choose_doc_generator_output_path)
        self.btn_test_docs_repo_conn.clicked.connect(
            self._on_test_cmis_connection)
        self.txt_atom_pub_url.textChanged.connect(self._on_cmis_url_changed)
        self.btn_holders_conf_file.clicked.connect(
            self._on_choose_holders_config_file)

        self._config = StdmConfiguration.instance()
        self.init_gui()

    def init_gui(self):
        # Set integer validator for the port number
        int_validator = QIntValidator(1024, 49151)
        self.txtPort.setValidator(int_validator)

        # Load profiles
        self.load_profiles()

        # Set current profile in the combobox
        curr_profile = current_profile()
        if not curr_profile is None:
            setComboCurrentIndexWithText(self.cbo_profiles, curr_profile.name)

        # Load current database connection properties
        self._load_db_conn_properties()

        # Load existing PostgreSQL connections
        self._load_qgis_pg_connections()

        # Load directory paths
        self._load_directory_paths()

        # Load document repository-related settings
        self._load_cmis_config()

        # Load holders configuration file path
        self._load_holders_configuration_file()

        # Debug logging
        lvl = debug_logging()
        if lvl:
            self.chk_logging.setCheckState(Qt.Checked)
        else:
            self.chk_logging.setCheckState(Qt.Unchecked)

        # Shortcut dialog
        self._check_shortcuts_settings()

        self.chk_shortcut_dlg.toggled.connect(self._on_check_shortcut_checkbox)

    def _load_cmis_config(self):
        """
        Load configuration names and IDs in the combobox then select
        the user specified ID.
        """
        # Load CMIS atom pub URL
        self.txt_atom_pub_url.setText(cmis_atom_pub_url())

        self.cbo_auth_config_name.clear()
        self.cbo_auth_config_name.addItem('')

        config_ids = config_entries()
        for ci in config_ids:
            id = ci[0]
            name = ci[1]
            display = u'{0} ({1})'.format(name, id)
            self.cbo_auth_config_name.addItem(display, id)

        # Then select the user specific config ID if specified
        conf_id = cmis_auth_config_id()
        if conf_id:
            id_idx = self.cbo_auth_config_name.findData(conf_id)
            if id_idx != -1:
                self.cbo_auth_config_name.setCurrentIndex(id_idx)

    def _load_holders_configuration_file(self):
        # Load the path of the holders configuration file.
        holders_config = holders_config_path()
        if not holders_config:
            # Use the default path
            holders_config = DEF_HOLDERS_CONFIG_PATH

        self.txt_holders_config.setText(holders_config)

    def _on_choose_holders_config_file(self):
        # Slot raised to browse the holders config file
        holders_config = self.txt_holders_config.text()
        if not holders_config:
            holders_config = QDir.home().path()

        conf_file = QFileDialog.getOpenFileName(
            self, self.tr('Browse Holders Configuration File'), holders_config,
            'Holders INI file (*.ini)')
        if conf_file:
            self.txt_holders_config.setText(conf_file)

    def _on_cmis_url_changed(self, new_text):
        # Slot raised when text for CMIS URL changes. Basically updates
        # the tooltip so as to display long URLs
        self.txt_atom_pub_url.setToolTip(new_text)

    def _check_shortcuts_settings(self):
        """
        Checks the state of the show dialog checkbox
        :return: Bool
        """
        # Check registry values for shortcut dialog
        show_dlg = 1
        dlg_key = self._reg_config.read([SHOW_SHORTCUT_DIALOG])

        if len(dlg_key) > 0:
            show_dlg = dlg_key[SHOW_SHORTCUT_DIALOG]

        if show_dlg == 1 or show_dlg == unicode(1):
            self.chk_shortcut_dlg.setChecked(True)
        elif show_dlg == 0 or show_dlg == unicode(0):
            self.chk_shortcut_dlg.setChecked(False)

    def _on_check_shortcut_checkbox(self, toggled):
        """
        Slot raised when the checkbox for showing shortcut window
        is checked/unchecked.
        :param toggled: Toggle status
        :type toggled: bool
        """
        if toggled:
            self._reg_config.write({SHOW_SHORTCUT_DIALOG: 1})
            self.notif_bar.clear()
            msg = self.tr(u"Shortcuts window will show after login")
            self.notif_bar.insertWarningNotification(msg)
        else:
            self._reg_config.write({SHOW_SHORTCUT_DIALOG: 0})
            self.notif_bar.clear()
            msg = self.tr(u"Shortcuts window will not show after login")
            self.notif_bar.insertWarningNotification(msg)

    def load_profiles(self):
        """
        Load existing profiles into the combobox.
        """
        profile_names = self._config.profiles.keys()

        self.cbo_profiles.clear()
        self.cbo_profiles.addItem('')
        self.cbo_profiles.addItems(profile_names)

    def _load_db_conn_properties(self):
        # Load database connection properties from the registry.
        db_conn = self._db_config.read()

        if not db_conn is None:
            self.txtHost.setText(db_conn.Host)
            self.txtPort.setText(db_conn.Port)
            self.txtDatabase.setText(db_conn.Database)

    def _load_qgis_pg_connections(self):
        """
        Load QGIS postgres connections.
        """
        self.cbo_pg_connections.addItem('')

        profiles = pg_profile_names()
        for profile in profiles:
            self.cbo_pg_connections.addItem(profile[0], profile[1])

    def _load_directory_paths(self):
        # Load paths to various directory settings.
        comp_out_path = composer_output_path()
        comp_temp_path = composer_template_path()

        if not comp_out_path is None:
            self.txt_output_dir.setText(comp_out_path)

        if not comp_temp_path is None:
            self.txt_template_dir.setText(comp_temp_path)

    def _on_use_pg_connections(self, state):
        # Slot raised when to (not) use existing pg connections
        if not state:
            self.cbo_pg_connections.setCurrentIndex(0)
            self.cbo_pg_connections.setEnabled(False)

            # Restore current connection in registry
            self._load_db_conn_properties()

        else:
            self.cbo_pg_connections.setEnabled(True)

    def _on_pg_profile_changed(self, index):
        """
        Slot raised when the index of the pg profile changes. If the
        selection is valid then the system will attempt to extract
        the database connection properties of the selected profile
        stored in the registry.
        """
        if index == 0:
            return

        profile_path = self.cbo_pg_connections.itemData(index)

        q_config = QGISRegistryConfig(profile_path)
        db_items = q_config.read(['Database', 'Host', 'Port'])

        if len(db_items) > 0:
            self.txtDatabase.setText(db_items['Database'])
            self.txtHost.setText(db_items['Host'])
            self.txtPort.setText(db_items['Port'])

    def clear_properties(self):
        """
        Clears the host, database name and port number values from the
        respective controls.
        """
        self.txtDatabase.clear()
        self.txtHost.clear()
        self.txtPort.clear()

    def _on_choose_doc_designer_template_path(self):
        # Slot raised to select directory for document designer templates.
        self._set_selected_directory(
            self.txt_template_dir,
            self.tr('Document Designer Templates Directory'))

    def _on_choose_doc_generator_output_path(self):
        # Slot raised to select directory for doc generator outputs.
        self._set_selected_directory(
            self.txt_output_dir,
            self.tr('Document Generator Output Directory'))

    def _set_selected_directory(self, txt_box, title):
        def_path = txt_box.text()
        sel_doc_path = QFileDialog.getExistingDirectory(self, title, def_path)

        if sel_doc_path:
            normalized_path = QDir.fromNativeSeparators(sel_doc_path)
            txt_box.clear()
            txt_box.setText(normalized_path)

    def _validate_db_props(self):
        # Test if all properties have been specified
        status = True

        self.notif_bar.clear()

        if not self.txtHost.text():
            msg = self.tr('Please specify the database host address.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        if not self.txtPort.text():
            msg = self.tr('Please specify the port number.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        if not self.txtDatabase.text():
            msg = self.tr('Please specify the database name.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        return status

    def _database_connection(self):
        # Creates a databaase connection object from the specified args
        host = self.txtHost.text()
        port = self.txtPort.text()
        database = self.txtDatabase.text()

        # Create database connection object
        db_conn = DatabaseConnection(host, port, database)

        return db_conn

    def _on_test_db_connection(self):
        """
        Slot raised to test database connection.
        """
        status = self._validate_db_props()

        if not status:
            return

        login_dlg = loginDlg(self, True)
        db_conn = self._database_connection()
        login_dlg.set_database_connection(db_conn)

        res = login_dlg.exec_()
        if res == QDialog.Accepted:
            msg = self.tr(u"Connection to '{0}' database was "
                          "successful.".format(db_conn.Database))
            self.notif_bar.insertSuccessNotification(msg)

    def _on_test_cmis_connection(self):
        # Slot raised to test connection to CMIS service
        status = self._validate_cmis_properties()
        if not status:
            return

        self.notif_bar.clear()

        atom_pub_url = self.txt_atom_pub_url.text()
        auth_conf_id = self.cbo_auth_config_name.itemData(
            self.cbo_auth_config_name.currentIndex())

        cmis_mgr = CmisManager(url=atom_pub_url, auth_config_id=auth_conf_id)

        QgsApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        status = cmis_mgr.connect()
        QgsApplication.restoreOverrideCursor()

        if status:
            msg = self.tr('Connection to the CMIS server succeeded.')
            self.notif_bar.insertSuccessNotification(msg)
        else:
            msg = self.tr(
                'Failed to connect to the CMIS server. Check URL and/or '
                'credentials.')
            self.notif_bar.insertErrorNotification(msg)

    def set_current_profile(self):
        """
        Saves the given profile name as the current profile.
        """
        profile_name = self.cbo_profiles.currentText()

        if not profile_name:
            self.notif_bar.clear()

            msg = self.tr('Profile name is empty, current profile will not '
                          'be set.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        save_current_profile(profile_name)

        return True

    def set_cmis_properties(self):
        """
        Saves the CMIS atom pub URL and authentication configuration ID.
        """
        if not self._validate_cmis_properties():
            return False

        atom_pub_url = self.txt_atom_pub_url.text()
        set_cmis_atom_pub_url(atom_pub_url)

        curr_idx = self.cbo_auth_config_name.currentIndex()
        config_id = self.cbo_auth_config_name.itemData(curr_idx)
        set_cmis_auth_config_id(config_id)

        return True

    def _validate_cmis_properties(self):
        # Assert if user has specified URL and authentication config ID.
        atom_pub_url = self.txt_atom_pub_url.text()
        config_name_id = self.cbo_auth_config_name.currentText()

        status = True

        if not atom_pub_url:
            msg = self.tr(
                'Please specify the URL of the CMIS atom pub service.')
            self.notif_bar.insertErrorNotification(msg)
            status = False

        if not config_name_id:
            msg = self.tr(
                'Please select the configuration ID containing the CMIS authentication.'
            )
            self.notif_bar.insertErrorNotification(msg)
            status = False

        return status

    def set_holders_config_file(self):
        # Save the path to the holders configuration file
        holders_config_file = self.txt_holders_config.text()
        if not holders_config_file:
            msg = self.tr(
                'Please set the path to the holders configuration file.')
            self.notif_bar.insertErrorNotification(msg)
            return False

        set_holders_config_path(holders_config_file)

        return True

    def save_database_properties(self):
        """
        Saves the specified database connection properties to the registry.
        :return: True if the connection properties were successfully saved.
        :rtype: bool
        """
        if not self._validate_db_props():
            return False

        # Create a database object and write it to the registry
        db_conn = self._database_connection()
        self._db_config.write(db_conn)

        return True

    def set_document_templates_path(self):
        """
        Set the directory of document designer templates.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txt_template_dir.text()

        if not path:
            msg = self.tr('Please set the document designer templates '
                          'directory.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        # Validate path
        if not self._check_path_exists(path, self.txt_template_dir):
            return False

        # Commit to registry
        self._reg_config.write({COMPOSER_TEMPLATE: path})

        return True

    def set_document_output_path(self):
        """
        Set the directory of document generator outputs.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txt_output_dir.text()

        if not path:
            msg = self.tr('Please set the document generator output directory'
                          '.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        # Validate path
        if not self._check_path_exists(path, self.txt_output_dir):
            return False

        # Commit to registry
        self._reg_config.write({COMPOSER_OUTPUT: path})

        return True

    def _check_path_exists(self, path, text_box):
        # Validates if the specified folder exists
        dir = QDir()

        if not dir.exists(path):
            msg = self.tr(u"'{0}' directory does not exist.".format(path))
            self.notif_bar.insertErrorNotification(msg)

            # Highlight textbox control
            text_box.setStyleSheet(INVALIDATESTYLESHEET)

            timer = QTimer(self)
            # Sync interval with that of the notification bar
            timer.setInterval(self.notif_bar.interval)
            timer.setSingleShot(True)

            # Remove previous connected slots (if any)
            receivers = timer.receivers(SIGNAL('timeout()'))
            if receivers > 0:
                self._timer.timeout.disconnect()

            timer.start()
            timer.timeout.connect(lambda: self._restore_stylesheet(text_box))

            return False

        return True

    def _restore_stylesheet(self, textbox):
        # Slot raised to restore the original stylesheet of the textbox control
        textbox.setStyleSheet(self._default_style_sheet)

        # Get reference to timer and delete
        sender = self.sender()
        if not sender is None:
            sender.deleteLater()

    def apply_debug_logging(self):
        # Save debug logging
        logger = logging.getLogger('stdm')

        if self.chk_logging.checkState() == Qt.Checked:
            logger.setLevel(logging.DEBUG)
            set_debug_logging(True)
        else:
            logger.setLevel(logging.ERROR)
            set_debug_logging(False)

    def apply_settings(self):
        """
        Save settings.
        :return: True if the settings were successfully applied, otherwise
        False.
        :rtype: bool
        """
        # Set current profile
        if not self.set_current_profile():
            return False

        # Set db connection properties
        if not self.save_database_properties():
            return False

        # Set CMIS properties
        if not self.set_cmis_properties():
            return False

        # Set holders configuration file path
        if not self.set_holders_config_file():
            return False

        # Set document designer templates path
        if not self.set_document_templates_path():
            return False

        # Set document generator output path
        if not self.set_document_output_path():
            return False

        self.apply_debug_logging()

        msg = self.tr('Settings successfully saved.')
        self.notif_bar.insertSuccessNotification(msg)

        return True

    def on_accept(self):
        """
        Slot raised to save the settings of the current widget and close the
        widget.
        """
        if not self.apply_settings():
            return

        self.accept()
Exemple #5
0
class OptionsDialog(QDialog, Ui_DlgOptions):
    """
    Dialog for editing STDM settings.
    """
    def __init__(self, iface):
        QDialog.__init__(self, iface.mainWindow())
        self.setupUi(self)
        self.iface = iface

        self.notif_bar = NotificationBar(self.vlNotification, 6000)
        self._apply_btn = self.buttonBox.button(QDialogButtonBox.Apply)
        self._reg_config = RegistryConfig()
        self._db_config = DatabaseConfig()

        version = version_from_metadata()
        upgrade_label_text = self.label_9.text().replace('1.4', version)
        self.label_9.setText(upgrade_label_text)

        #Connect signals
        self._apply_btn.clicked.connect(self.apply_settings)
        self.buttonBox.accepted.connect(self.on_accept)
        self.chk_pg_connections.toggled.connect(self._on_use_pg_connections)
        self.cbo_pg_connections.currentIndexChanged.connect(
            self._on_pg_profile_changed)
        self.btn_db_conn_clear.clicked.connect(self.clear_properties)
        self.btn_test_db_connection.clicked.connect(self._on_test_connection)
        self.btn_supporting_docs.clicked.connect(
            self._on_choose_supporting_docs_path
        )
        self.btn_template_folder.clicked.connect(
            self._on_choose_doc_designer_template_path
        )
        self.btn_composer_out_folder.clicked.connect(
            self._on_choose_doc_generator_output_path
        )
        self.upgradeButton.toggled.connect(
            self.manage_upgrade
        )

        self._config = StdmConfiguration.instance()
        self._default_style_sheet = self.txtRepoLocation.styleSheet()

        self.manage_upgrade()

        self.init_gui()

    def init_gui(self):
        #Set integer validator for the port number
        int_validator = QIntValidator(1024, 49151)
        self.txtPort.setValidator(int_validator)

        #Load profiles
        self.load_profiles()

        #Set current profile in the combobox
        curr_profile = current_profile()
        if not curr_profile is None:
            setComboCurrentIndexWithText(self.cbo_profiles, curr_profile.name)

        #Load current database connection properties
        self._load_db_conn_properties()

        #Load existing PostgreSQL connections
        self._load_qgis_pg_connections()

        #Load directory paths
        self._load_directory_paths()

        self.edtEntityRecords.setMaximum(MAX_LIMIT)
        self.edtEntityRecords.setValue(get_entity_browser_record_limit())

        # Debug logging
        lvl = debug_logging()
        if lvl:
            self.chk_logging.setCheckState(Qt.Checked)
        else:
            self.chk_logging.setCheckState(Qt.Unchecked)

    def load_profiles(self):
        """
        Load existing profiles into the combobox.
        """
        profile_names = self._config.profiles.keys()

        self.cbo_profiles.clear()
        self.cbo_profiles.addItem('')
        self.cbo_profiles.addItems(profile_names)

    def _load_db_conn_properties(self):
        #Load database connection properties from the registry.
        db_conn = self._db_config.read()

        if not db_conn is None:
            self.txtHost.setText(db_conn.Host)
            self.txtPort.setText(db_conn.Port)
            self.txtDatabase.setText(db_conn.Database)

    def _load_qgis_pg_connections(self):
        """
        Load QGIS postgres connections.
        """
        self.cbo_pg_connections.addItem('')

        profiles = pg_profile_names()
        for profile in profiles:
            self.cbo_pg_connections.addItem(profile[0], profile[1])

    def _load_directory_paths(self):
        #Load paths to various directory settings.
        comp_out_path = composer_output_path()
        comp_temp_path = composer_template_path()
        source_doc_path = source_documents_path()

        if not source_doc_path is None:
            self.txtRepoLocation.setText(source_doc_path)

        if not comp_out_path is None:
            self.txt_output_dir.setText(comp_out_path)

        if not comp_temp_path is None:
            self.txt_template_dir.setText(comp_temp_path)

    def _on_use_pg_connections(self, state):
        #Slot raised when to (not) use existing pg connections
        if not state:
            self.cbo_pg_connections.setCurrentIndex(0)
            self.cbo_pg_connections.setEnabled(False)

            #Restore current connection in registry
            self._load_db_conn_properties()

        else:
            self.cbo_pg_connections.setEnabled(True)

    def _on_pg_profile_changed(self, index):
        """
        Slot raised when the index of the pg profile changes. If the
        selection is valid then the system will attempt to extract
        the database connection properties of the selected profile
        stored in the registry.
        """
        if index == 0:
            return

        profile_path = self.cbo_pg_connections.itemData(index)

        q_config = QGISRegistryConfig(profile_path)
        db_items = q_config.read(['Database', 'Host', 'Port'])

        if len(db_items) > 0:
            self.txtDatabase.setText(db_items['Database'])
            self.txtHost.setText(db_items['Host'])
            self.txtPort.setText(db_items['Port'])

    def clear_properties(self):
        """
        Clears the host, database name and port number values from the
        respective controls.
        """
        self.txtDatabase.clear()
        self.txtHost.clear()
        self.txtPort.clear()

    def _on_choose_supporting_docs_path(self):
        #Slot raised to select directory for supporting documents.
        self._set_selected_directory(self.txtRepoLocation, self.tr(
            'Supporting Documents Directory')
        )

    def _on_choose_doc_designer_template_path(self):
        #Slot raised to select directory for document designer templates.
        self._set_selected_directory(self.txt_template_dir, self.tr(
            'Document Designer Templates Directory')
        )

    def _on_choose_doc_generator_output_path(self):
        #Slot raised to select directory for doc generator outputs.
        self._set_selected_directory(self.txt_output_dir, self.tr(
            'Document Generator Output Directory')
        )

    def _set_selected_directory(self, txt_box, title):
        def_path= txt_box.text()
        sel_doc_path = QFileDialog.getExistingDirectory(self, title, def_path)

        if sel_doc_path:
            normalized_path = QDir.fromNativeSeparators(sel_doc_path)
            txt_box.clear()
            txt_box.setText(normalized_path)

    def _validate_db_props(self):
        #Test if all properties have been specified
        status = True

        self.notif_bar.clear()

        if not self.txtHost.text():
            msg = self.tr('Please specify the database host address.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        if not self.txtPort.text():
            msg = self.tr('Please specify the port number.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        if not self.txtDatabase.text():
            msg = self.tr('Please specify the database name.')
            self.notif_bar.insertErrorNotification(msg)

            status = False

        return status

    def _database_connection(self):
        #Creates a databaase connection object from the specified args
        host = self.txtHost.text()
        port = self.txtPort.text()
        database = self.txtDatabase.text()

        #Create database connection object
        db_conn = DatabaseConnection(host, port, database)

        return db_conn

    def _on_test_connection(self):
        """
        Slot raised to test database connection.
        """
        status = self._validate_db_props()

        if not status:
            return

        login_dlg = loginDlg(self, True)
        db_conn = self._database_connection()
        login_dlg.set_database_connection(db_conn)

        res = login_dlg.exec_()
        if res == QDialog.Accepted:
            msg = self.tr(u"Connection to '{0}' database was "
                          "successful.".format(db_conn.Database))
            QMessageBox.information(self, self.tr('Database Connection'), msg)

    def set_current_profile(self):
        """
        Saves the given profile name as the current profile.
        """
        profile_name = self.cbo_profiles.currentText()

        if not profile_name:
            self.notif_bar.clear()

            msg = self.tr('Profile name is empty, current profile will not '
                          'be set.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        save_current_profile(profile_name)

        return True

    def save_database_properties(self):
        """
        Saves the specified database connection properties to the registry.
        :return: True if the connection properties were successfully saved.
        :rtype: bool
        """
        if not self._validate_db_props():
            return False

        #Create a database object and write it to the registry
        db_conn = self._database_connection()
        self._db_config.write(db_conn)

        return True

    def set_supporting_documents_path(self):
        """
        Set the directory of supporting documents.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txtRepoLocation.text()

        if not path:
            msg = self.tr('Please set the supporting documents directory.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        #Validate path
        if not self._check_path_exists(path, self.txtRepoLocation):
            return False

        #Commit to registry
        self._reg_config.write({NETWORK_DOC_RESOURCE: path})

        return True

    def set_document_templates_path(self):
        """
        Set the directory of document designer templates.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txt_template_dir.text()

        if not path:
            msg = self.tr('Please set the document designer templates '
                          'directory.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        #Validate path
        if not self._check_path_exists(path, self.txt_template_dir):
            return False

        #Commit to registry
        self._reg_config.write({COMPOSER_TEMPLATE: path})

        return True

    def set_document_output_path(self):
        """
        Set the directory of document generator outputs.
        :return: True if the directory was set in the registry, otherwise
        False.
        :rtype: bool
        """
        path = self.txt_output_dir.text()

        if not path:
            msg = self.tr('Please set the document generator output directory'
                          '.')
            self.notif_bar.insertErrorNotification(msg)

            return False

        #Validate path
        if not self._check_path_exists(path, self.txt_output_dir):
            return False

        #Commit to registry
        self._reg_config.write({COMPOSER_OUTPUT: path})

        return True

    def _check_path_exists(self, path, text_box):
        #Validates if the specified folder exists
        dir = QDir()

        if not dir.exists(path):
            msg = self.tr(u"'{0}' directory does not exist.".format(path))
            self.notif_bar.insertErrorNotification(msg)

            #Highlight textbox control
            text_box.setStyleSheet(INVALIDATESTYLESHEET)

            timer = QTimer(self)
            #Sync interval with that of the notification bar
            timer.setInterval(self.notif_bar.interval)
            timer.setSingleShot(True)

            #Remove previous connected slots (if any)
            receivers = timer.receivers(SIGNAL('timeout()'))
            if receivers > 0:
                self._timer.timeout.disconnect()

            timer.start()
            timer.timeout.connect(lambda:self._restore_stylesheet(
                text_box)
            )

            return False

        return True

    def _restore_stylesheet(self, textbox):
        # Slot raised to restore the original stylesheet of the textbox control
        textbox.setStyleSheet(self._default_style_sheet)

        # Get reference to timer and delete
        sender = self.sender()
        if not sender is None:
            sender.deleteLater()

    def apply_debug_logging(self):
        # Save debug logging
        logger = logging.getLogger('stdm')

        if self.chk_logging.checkState() == Qt.Checked:
            logger.setLevel(logging.DEBUG)
            set_debug_logging(True)
        else:
            logger.setLevel(logging.ERROR)
            set_debug_logging(False)

    def apply_settings(self):
        """
        Save settings.
        :return: True if the settings were successfully applied, otherwise
        False.
        :rtype: bool
        """
        #Set current profile
        if not self.set_current_profile():
            return False

        #Set db connection properties
        if not self.save_database_properties():
            return False

        #Set supporting documents directory
        if not self.set_supporting_documents_path():
            return False

        #Set document designer templates path
        if not self.set_document_templates_path():
            return False

        #Set document generator output path
        if not self.set_document_output_path():
            return False

        self.apply_debug_logging()

        # Set Entity browser record limit
        save_entity_browser_record_limit(self.edtEntityRecords.value())

        msg = self.tr('Settings successfully saved.')
        self.notif_bar.insertSuccessNotification(msg)

        return True

    def on_accept(self):
        """
        Slot raised to save the settings of the current widget and close the
        widget.
        """
        if not self.apply_settings():
            return

        self.accept()

    def manage_upgrade(self):
        """
        A slot raised when the upgrade button is clicked.
        It disables or enables the upgrade
        button based on the ConfigUpdated registry value.
        """

        self.config_updated_dic = self._reg_config.read(
            [CONFIG_UPDATED]
        )

        # if config file exists, check if registry key exists
        if len(self.config_updated_dic) > 0:
            config_updated_val = self.config_updated_dic[
                CONFIG_UPDATED
            ]
            # If failed to upgrade, enable the upgrade button
            if config_updated_val == '0' or config_updated_val == '-1':
                self.upgradeButton.setEnabled(True)

            # disable the button if any other value.
            else:
                self.upgradeButton.setEnabled(False)
        else:
            self.upgradeButton.setEnabled(False)