def __init__(self, user, parent=None): QgsPanelWidget.__init__(self, parent) self.setupUi(self) self._user = user self.parent = parent self.logger = Logger() self.session = STSession() self._current_widget = None self.home_widget = loadUi( get_ui_file_path('transitional_system/home_widget.ui'), QWidget()) self.tasks_widget = TasksWidget( user ) # No need to use parent, as the layout will call setParent automatically self.tasks_widget.task_panel_requested.connect(self.show_task_panel) self.setDockMode(True) self.setPanelTitle( QCoreApplication.translate("TransitionalSystemInitialPanelWidget", "Transitional System")) self.btn_home.clicked.connect(self.show_home_widget) self.btn_view_tasks.clicked.connect(self.show_tasks_widget) self.btn_logout.clicked.connect(self.logout_requested) # Now update controls to show an initial state to users self._update_user_info() self.show_tasks_widget()
class LoginSTDialog(QDialog, DIALOG_UI): active_role_changed = pyqtSignal() def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.session = STSession() self.logger = Logger() self.help_strings = HelpStrings() self.should_emit_role_changed = False self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.login) self.buttonBox.helpRequested.connect(self.show_help) self.txt_login_user.setFocus() self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) def login(self): if not self.txt_login_user.text().strip( ) or not self.txt_login_password.text().strip(): msg = QCoreApplication.translate( "LoginSTDialog", "First enter user and password data.") self.show_message(msg, Qgis.Warning) return msg = self.logger.status( QCoreApplication.translate("LoginSTDialog", "Connecting to login service...")) with ProcessWithStatus(msg): res, msg, change_role = self.session.login( self.txt_login_user.text(), self.txt_login_password.text()) if res: self.should_emit_role_changed = change_role self.logger.info(__name__, msg, EnumLogHandler.MESSAGE_BAR, 15) self.close() else: self.show_message(msg, Qgis.Warning, 0) def show_message(self, message, level, duration=15): self.bar.clearWidgets( ) # Remove previous messages before showing a new one self.bar.pushMessage(message, level, duration) def show_help(self): show_plugin_help('transitional_system_login') def reject(self): if self.should_emit_role_changed: self.logger.info(__name__, "Emit active_role_changed.") self.active_role_changed.emit() self.logger.info(__name__, "Dialog closed.") self.done(QDialog.Accepted) # Any code, we don't use it anyways
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.session = STSession() self.logger = Logger() self.help_strings = HelpStrings() #self.txt_help_page.setHtml(self.help_strings.DLG_WELCOME_SCREEN) #self.txt_help_page.anchorClicked.connect(self.save_template) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.login) self.buttonBox.helpRequested.connect(self.show_help) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.session = STSession() self.logger = Logger() self.help_strings = HelpStrings() self.should_emit_role_changed = False self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.login) self.buttonBox.helpRequested.connect(self.show_help) self.txt_login_user.setFocus() self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)
def __init__(self, user): QWidget.__init__(self) self.setupUi(self) self.logger = Logger() self.session = STSession() self._user = user self.lvw_tasks.itemSelectionChanged.connect(self.update_controls) self.lvw_tasks.itemDoubleClicked.connect(self.call_task_panel) self.btn_view_task.clicked.connect(self.view_task) self.btn_close_task.clicked.connect(self.close_task) self.update_controls() # Initialize controls
def __init__(self, task_id, parent): QgsPanelWidget.__init__(self, parent) self.setupUi(self) self.session = STSession() self._task = self.session.task_manager.get_task(task_id) self.parent = parent self.logger = Logger() self.setDockMode(True) self.setPanelTitle( QCoreApplication.translate("TaskPanelWidget", "Task details")) self.trw_task_steps.itemDoubleClicked.connect(self.trigger_action) self.trw_task_steps.itemChanged.connect(self.update_step_controls) self.session.task_manager.task_started.connect(self.update_task) self.session.task_manager.task_canceled.connect(self.acceptPanel) self.session.task_manager.task_closed.connect(self.acceptPanel) self.btn_start_task.clicked.connect(self.start_task) self.btn_cancel_task.clicked.connect(self.cancel_task) self.btn_close_task.clicked.connect(self.close_task) self.initialize_gui()
class LoginSTDialog(QDialog, DIALOG_UI): def __init__(self, parent=None): QDialog.__init__(self, parent) self.setupUi(self) self.session = STSession() self.logger = Logger() self.help_strings = HelpStrings() #self.txt_help_page.setHtml(self.help_strings.DLG_WELCOME_SCREEN) #self.txt_help_page.anchorClicked.connect(self.save_template) self.buttonBox.accepted.disconnect() self.buttonBox.accepted.connect(self.login) self.buttonBox.helpRequested.connect(self.show_help) self.bar = QgsMessageBar() self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop) def login(self): if not self.txt_login_user.text().strip( ) or not self.txt_login_password.text().strip(): msg = QCoreApplication.translate( "LoginSTDialog", "First enter user and password data.") self.show_message(msg, Qgis.Warning) return msg = self.logger.status( QCoreApplication.translate("LoginSTDialog", "Connecting to login service...")) with ProcessWithStatus(msg): res, msg = self.session.login(self.txt_login_user.text(), self.txt_login_password.text()) if res: self.logger.info(__name__, msg, LogHandlerEnum.MESSAGE_BAR, 15) self.close() else: self.show_message(msg, Qgis.Warning, 0) def show_message(self, message, level, duration=15): self.bar.clearWidgets( ) # Remove previous messages before showing a new one self.bar.pushMessage(message, level, duration) def show_help(self): self.qgis_utils.show_help("import_from_excel")
class TaskPanelWidget(QgsPanelWidget, WIDGET_UI): trigger_action_emitted = pyqtSignal(str) # action tag def __init__(self, task_id, parent): QgsPanelWidget.__init__(self, parent) self.setupUi(self) self.session = STSession() self._task = self.session.task_manager.get_task(task_id) self.parent = parent self.logger = Logger() self.st_config = TransitionalSystemConfig() self.setDockMode(True) self.setPanelTitle( QCoreApplication.translate("TaskPanelWidget", "Task details")) self.trw_task_steps.itemDoubleClicked.connect(self.trigger_action) self.trw_task_steps.itemChanged.connect(self.update_step_controls) self.session.task_manager.task_started.connect(self.update_task) self.session.task_manager.task_canceled.connect(self.acceptPanel) self.session.task_manager.task_closed.connect(self.acceptPanel) self.btn_start_task.clicked.connect(self.start_task) self.btn_cancel_task.clicked.connect(self.cancel_task) self.btn_close_task.clicked.connect(self.close_task) self.initialize_gui() def initialize_gui(self): self.show_task_description() self.show_task_steps() self.update_controls() def show_task_description(self): if self._task is not None: self.logger.debug(__name__, "Setting task description in Task Panel...") self.lbl_name.setText(self._task.get_name()) self.lbl_description.setText(self._task.get_description()) self.lbl_created_at.setText( QCoreApplication.translate("TaskPanelWidget", "Created at: {}").format( self._task.get_creation_date())) if self._task.get_status() == EnumSTTaskStatus.STARTED.value: self.lbl_started_at.setVisible(True) self.lbl_started_at.setText( QCoreApplication.translate( "TaskPanelWidget", "Started at: {}").format( self._task.get_started_date())) else: self.lbl_started_at.setVisible(False) self.lbl_deadline.setText( QCoreApplication.translate("TaskPanelWidget", "Deadline: {}").format( self._task.get_deadline())) self.lbl_status.setText(self._task.get_status()) # Styles self.lbl_name.setStyleSheet(self.st_config.TASK_TITLE_BIG_TEXT_CSS) if self._task.get_status() == EnumSTTaskStatus.ASSIGNED.value: self.lbl_status.setStyleSheet( self.st_config.TASK_ASSIGNED_STATUS_BIG_TEXT_CSS) elif self._task.get_status() == EnumSTTaskStatus.STARTED.value: self.lbl_status.setStyleSheet( self.st_config.TASK_STARTED_STATUS_BIG_TEXT_CSS) def show_task_steps(self): self.trw_task_steps.clear() steps = self._task.get_steps() self.logger.debug( __name__, "Showing task steps in Task Panel. {} task steps found: {}.". format(len(steps), ", ".join([s.get_name() for s in steps]))) for i, step in enumerate(steps): children = [] step_item = QTreeWidgetItem([ QCoreApplication.translate("TaskPanelWidget", "Step {}").format(i + 1) ]) step_item.setData(0, Qt.BackgroundRole, QBrush(GRAY_COLOR)) step_item.setToolTip(0, step.get_name()) step_item.setCheckState( 0, Qt.Checked if step.get_status() else Qt.Unchecked) action_item = QTreeWidgetItem([step.get_name()]) action_item.setData(0, Qt.UserRole, step.get_id()) action_item.setIcon( 0, QIcon(":/Asistente-LADM-COL/resources/images/process.svg")) action_item.setToolTip(0, step.get_description()) step_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) children.append(action_item) step_item.addChildren(children) self.trw_task_steps.addTopLevelItem(step_item) for i in range(self.trw_task_steps.topLevelItemCount()): self.trw_task_steps.topLevelItem( i).setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsSelectable) self.trw_task_steps.topLevelItem(i).setExpanded(True) def trigger_action(self, item, column): """ Triggers an action linked to the task step. Action config comes from TaskStepsConfig, and it can be either a default action slot or a customized action slot (even passing a task context). :param item: QTreeWidgetItem that is linked to an action, (i.e., a child item) :param column: 0 """ # Make sure we have a child item and only trigger if parent is not checked yet (i.e., step is not done yet) if not item.childCount() and item.parent().checkState( column) == Qt.Unchecked: step_id = item.data(column, Qt.UserRole) step = self._task.get_step(step_id) if step: slot = step.get_custom_action_slot() if slot: # Custom action call self.logger.info( __name__, "Executing step action with custom parameters...") if SLOT_CONTEXT in slot and slot[SLOT_CONTEXT]: slot[SLOT_CONTEXT].set_slot_on_result( partial(self.set_item_enabled, item.parent())) slot[SLOT_NAME]( slot[SLOT_CONTEXT], **slot[SLOT_PARAMS]) # Call passing task context else: slot[SLOT_NAME](**slot[SLOT_PARAMS]) else: # Default action call self.logger.info(__name__, "Executing default action...") self.trigger_action_emitted.emit(step.get_action_tag()) def set_item_enabled(self, item, enable): """ Slot to react upon getting the result of an action (dialog) linked to a task step :param item: Checkable QTreeWidgetItem (i.e., it's the parent, not the child that triggers the action) :param enable: Whether the task step was successfully run or not """ item.setCheckState(0, Qt.Checked if enable else Qt.Unchecked) def set_item_style(self, item, column): color = CHECKED_COLOR if item.checkState( column) == Qt.Checked else UNCHECKED_COLOR item.setData(column, Qt.BackgroundRole, QBrush(color)) for index in range(item.childCount()): color = GRAY_COLOR if item.checkState( column) == Qt.Checked else Qt.black item.child(index).setData(column, Qt.ForegroundRole, QBrush(color)) def update_step_controls(self, item, column): if item.childCount(): # Only do this for parents self.trw_task_steps.blockSignals(True) self.set_item_style(item, column) self.save_task_steps_status(column) self.trw_task_steps.blockSignals(False) self.update_close_control() def update_controls(self): # Steps panel self.trw_task_steps.setEnabled( self._task.get_status() == EnumSTTaskStatus.STARTED.value) # Start task button self.btn_start_task.setEnabled( self._task.get_status() == EnumSTTaskStatus.ASSIGNED.value) # Cancel task button self.btn_cancel_task.setEnabled( self._task.get_status() == EnumSTTaskStatus.STARTED.value) self.update_close_control() def update_close_control(self): # Can we close the task? self.btn_close_task.setEnabled( self._task.get_status() == EnumSTTaskStatus.STARTED.value and self.steps_complete()) if self._task.get_status( ) == EnumSTTaskStatus.STARTED.value and self.steps_complete(): self.btn_close_task.setToolTip("") elif self._task.get_status( ) != EnumSTTaskStatus.STARTED.value and self.steps_complete(): self.btn_close_task.setToolTip( QCoreApplication.translate( "TaskPanelWidget", "The task is not started yet, hence, it cannot be closed.") ) else: # The remaining 2 cases: steps incomplete (whether the task is started or not) self.btn_close_task.setToolTip( QCoreApplication.translate( "TaskPanelWidget", "You should complete the steps before closing the task.")) def steps_complete(self): """ :return: boolean --> Can we close the task """ return self._task.steps_complete() def save_task_steps_status(self, column): steps_status = dict() for i in range(self.trw_task_steps.topLevelItemCount()): steps_status[i + 1] = self.trw_task_steps.topLevelItem( i).checkState(column) == Qt.Checked # Don't save if not necessary status = QSettings().value( "Asistente-LADM-COL/transitional_system/tasks/{}/step_status". format(self._task.get_id()), "{}") if status != json.dumps(steps_status): self._task.save_steps_status(steps_status) def start_task(self): self.session.task_manager.start_task(self.session.get_logged_st_user(), self._task.get_id()) self.update_controls() def cancel_task(self): reply = QMessageBox.question( self, QCoreApplication.translate("TaskPanelWidget", "Confirm"), QCoreApplication.translate( "TaskPanelWidget", "Are you sure you want to cancel the task '{}'?").format( self._task.get_name()), QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: dlg = STCancelTaskDialog(self.parent) res = dlg.exec_() if res == QDialog.Accepted: if dlg.comments: self.session.task_manager.cancel_task( self.session.get_logged_st_user(), self._task.get_id(), dlg.comments) else: self.logger.warning_msg( __name__, QCoreApplication.translate("TaskPanelWidget", "The task was not canceled.")) def close_task(self): reply = QMessageBox.question( self, QCoreApplication.translate("TaskPanelWidget", "Confirm"), QCoreApplication.translate( "TaskPanelWidget", "Are you sure you want to close the task '{}'?").format( self._task.get_name()), QMessageBox.Yes, QMessageBox.No) if reply == QMessageBox.Yes: self.session.task_manager.close_task( self.session.get_logged_st_user(), self._task.get_id()) def update_task(self, task_id): """A task changed in the Task Manager, so, update the base task for the panel and update the panel itself""" self._task = self.session.task_manager.get_task(task_id) self.initialize_gui()
def __init__(self): QObject.__init__(self) self.logger = Logger() self.st_session = STSession() self.st_config = TransitionalSystemConfig()
class STUtils(QObject): def __init__(self): QObject.__init__(self) self.logger = Logger() self.st_session = STSession() self.st_config = TransitionalSystemConfig() def upload_file(self, request_id, supply_type, file_path, comments): url = self.st_config.ST_UPLOAD_FILE_SERVICE_URL.format(request_id) payload = {'typeSupplyId': supply_type, 'observations': comments} files = [('files[]', open(file_path, 'rb'))] headers = { 'Authorization': "Bearer {}".format( self.st_session.get_logged_st_user().get_token()) } msg = "" try: self.logger.debug(__name__, "Uploading file to transitional system...") response = requests.request("PUT", url, headers=headers, data=payload, files=files) except requests.ConnectionError as e: msg = self.st_config.ST_CONNECTION_ERROR_MSG.format(e) self.logger.warning(__name__, msg) return False, msg status_OK = response.status_code == 200 if status_OK: msg = QCoreApplication.translate( "STUtils", "The file was successfully uploaded to the Transitional System!" ) self.logger.success(__name__, msg) else: if response.status_code == 500: msg = self.st_config.ST_STATUS_500_MSG self.logger.warning(__name__, self.st_config.ST_STATUS_500_MSG) elif response.status_code > 500 and response.status_code < 600: msg = self.st_config.ST_STATUS_GT_500_MSG self.logger.warning(__name__, self.st_config.ST_STATUS_GT_500_MSG) elif response.status_code == 401: msg = self.st_config.ST_STATUS_401_MSG self.logger.warning(__name__, self.st_config.ST_STATUS_401_MSG) elif response.status_code == 422: response_data = json.loads(response.text) msg = QCoreApplication.translate( "STUtils", "File was not uploaded! Details: {}").format( response_data['message']) self.logger.warning(__name__, msg) else: msg = QCoreApplication.translate( "STUtils", "Status code not handled: {}").format(response.status_code) self.logger.warning(__name__, msg) return status_OK, msg
def accepted(self): """ We start checking the document repository configuration and only allow to continue if we have a valid repo or if the repo won't be used. Then, check if connection to DB/schema is valid, if not, block the dialog. If valid, check it complies with LADM. If not, block the dialog. If it complies, we have two options: To emit db_connection changed or not. Finally, we store options in QSettings. """ res_doc_repo, msg_doc_repo = self.check_document_repository_before_saving_settings( ) if not res_doc_repo: self.show_message(msg_doc_repo, Qgis.Warning, 0) return # Do not close the dialog ladm_col_schema = False db = self._get_db_connector_from_gui() test_level = EnumTestLevel.DB_SCHEMA if self._action_type == EnumDbActionType.SCHEMA_IMPORT: # Limit the validation (used in GeoPackage) test_level |= EnumTestLevel.SCHEMA_IMPORT res, code, msg = db.test_connection( test_level ) # No need to pass required_models, we don't test that much if res: if self._action_type != EnumDbActionType.SCHEMA_IMPORT: # Only check LADM-schema if we are not in an SCHEMA IMPORT. # We know in an SCHEMA IMPORT, at this point the schema is still not LADM. ladm_col_schema, code, msg = db.test_connection( EnumTestLevel.LADM, required_models=self._required_models) if not ladm_col_schema and self._action_type != EnumDbActionType.SCHEMA_IMPORT: if self._blocking_mode: self.show_message(msg, Qgis.Warning) return # Do not close the dialog else: if self._blocking_mode: self.show_message(msg, Qgis.Warning) return # Do not close the dialog # Connection is valid and complies with LADM current_db_engine = self.cbo_db_engine.currentData() if self._lst_panel[current_db_engine].state_changed( ) or self.init_db_engine != current_db_engine: # Emit db_connection_changed if self._db is not None: self._db.close_connection() self._db = db # Update db connect with new db conn self.conn_manager.set_db_connector_for_source( self._db, self.db_source) # Emmit signal when db source changes self.db_connection_changed.emit(self._db, ladm_col_schema, self.db_source) self.logger.debug( __name__, "Settings dialog emitted a db_connection_changed.") if not ladm_col_schema and self._action_type == EnumDbActionType.CONFIG: msg_box = QMessageBox(self) msg_box.setIcon(QMessageBox.Question) msg_box.setText( QCoreApplication.translate( "SettingsDialog", "No LADM-COL DB has been configured! You'll continue with limited functionality until you configure a LADM-COL DB.\n\nDo you want to go to 'Create LADM-COL structure' dialog?" )) msg_box.setWindowTitle( QCoreApplication.translate("SettingsDialog", "Important")) msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.Ignore) msg_box.setDefaultButton(QMessageBox.Ignore) msg_box.button(QMessageBox.Yes).setText( QCoreApplication.translate("SettingsDialog", "Yes, go to create structure")) msg_box.button(QMessageBox.Ignore).setText( QCoreApplication.translate("SettingsDialog", "No, I'll do it later")) reply = msg_box.exec_() if reply == QMessageBox.Yes: self._open_dlg_import_schema = True # We will open it when we've closed this Settings dialog # If active role is changed (a check and confirmation may be needed), refresh the GUI # Note: Better to leave this check as the last one in the accepted() method. selected_role = self.get_selected_role() if self.roles.get_active_role() != selected_role: b_change_role = True if STSession().is_user_logged(): reply = QMessageBox.question( self.parent, QCoreApplication.translate("SettingsDialog", "Warning"), QCoreApplication.translate( "SettingsDialog", "You have a ST connection opened and you want to change your role.\nIf you confirm that you want to change your role, you'll be logged out from the ST.\n\nDo you really want to change your role?" ), QMessageBox.Yes | QMessageBox.Cancel, QMessageBox.Cancel) if reply == QMessageBox.Yes: STSession().logout() elif reply == QMessageBox.Cancel: # No need to switch back selected role, the Settings Dialog gets it from role registry b_change_role = False if b_change_role: self.logger.info( __name__, "The active role has changed from '{}' to '{}'.".format( self.roles.get_active_role(), selected_role)) self.roles.set_active_role( selected_role ) # Emits signal that refreshed the plugin for this role self.save_settings(db) QDialog.accept(self) self.close() if self._open_dlg_import_schema: # After Settings dialog has been closed, we could call Import Schema depending on user's answer above self.open_dlg_import_schema.emit(Context()) self.logger.debug( __name__, "Settings dialog emitted a show Import Schema dialog.")