コード例 #1
0
class BaseSplitDataForReceiversPanelWidget(QgsPanelWidget, WIDGET_UI):
    refresh_parcel_data_clear_selection_requested = pyqtSignal()

    def __init__(self, parent, controller):
        QgsPanelWidget.__init__(self, parent)
        self.setupUi(self)
        self.parent = parent
        self._controller = controller

        self.logger = Logger()
        self.app = AppInterface()

        self.setDockMode(True)
        self.setPanelTitle(QCoreApplication.translate("BaseSplitDataForReceiversPanelWidget", "Convert to offline"))
        self.parent.setWindowTitle(QCoreApplication.translate("BaseSplitDataForReceiversPanelWidget", "Allocate parcels"))

        self.mQgsFileWidget.lineEdit().setPlaceholderText(QCoreApplication.translate("BaseSplitDataForReceiversPanelWidget", "Choose the output folder..."))
        self.mQgsFileWidget.setDefaultRoot(self.app.settings.export_dir_field_data)

        self.panelAccepted.connect(self.panel_accepted)
        self._controller.export_field_data_progress.connect(self.update_progress)
        self.btn_split_data.clicked.connect(self.export_field_data)

        self.fill_data()

    def panel_accepted(self):
        self.refresh_parcel_data_clear_selection_requested.emit()

    def fill_data(self):
        summary_data = self._controller.get_summary_data()
        row = 1
        for row_data in summary_data:
            receiver_name, parcel_count = row_data
            self.fill_row(receiver_name, parcel_count, row)
            row += 2  # v_spacer + label

        # After the real data, we add a new spacer that expands itself to shrink content upwards
        v_spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
        self.grb_summary.layout().addItem(v_spacer, row, 0)

        # Show/hide warning depending on if there are not allocated parcels
        not_allocated_parcels = self._controller.get_count_of_not_allocated_parcels()
        self.lbl_warning.setVisible(not_allocated_parcels)
        self.lbl_not_allocated_parcels.setVisible(not_allocated_parcels)
        self.lbl_not_allocated_parcels.setText(QCoreApplication.translate("BaseSplitDataForReceiversPanelWidget",
                                               "{} parcels have not been yet allocated!").format(not_allocated_parcels))

    def fill_row(self, receiver_name, parcel_count, row):
        # First add a spacer between previoud data row (could be the title) and the next row data
        v_spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Preferred)
        self.grb_summary.layout().addItem(v_spacer, row, 0)

        # Now, let's add a row of data
        w = QLabel(receiver_name)
        self.grb_summary.layout().addWidget(w, row+1, 0)
        w = QLabel(str(parcel_count))
        w.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
        self.grb_summary.layout().addWidget(w, row+1, 2)

    def export_field_data(self):
        self.logger.clear_message_bar()
        export_dir = self.mQgsFileWidget.filePath()

        if export_dir and os.path.isdir(export_dir):
            self.app.settings.export_dir_field_data = export_dir
            self.prb_export_field_data.setRange(0, 100)
            self.prb_export_field_data.setValue(0)

            res, msg = self._controller.export_field_data(export_dir)

            self.logger.success_warning(__name__, res, msg, EnumLogHandler.MESSAGE_BAR)
        else:
            self.logger.warning_msg(__name__, QCoreApplication.translate("BaseSplitDataForReceiversPanelWidget", "The output folder is invalid. Choose a valid folder."))

    def update_progress(self, progress):
        self.prb_export_field_data.setValue(progress)
class XTFModelConverterDialog(QDialog, DIALOG_XTF_MODEL_CONVERTER_UI):
    on_result = pyqtSignal(bool)  # whether the tool was run successfully or not

    def __init__(self, controller, parent=None):
        QDialog.__init__(self, parent)
        self.setupUi(self)
        self._controller = controller
        self.parent = parent

        self.logger = Logger()
        self.app = AppInterface()
        self.validators = Validators()

        self._dialog_mode = None
        self._running_tool = False        
        self.tool_name = QCoreApplication.translate("XTFModelConverterDialog", "XTF Model Converter")
 
        # Initialize
        self.initialize_progress()

        # Set MessageBar for QDialog
        self.bar = QgsMessageBar()
        self.bar.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
        self.layout().addWidget(self.bar, 0, 0, Qt.AlignTop)

        # Set connections
        self.buttonBox.accepted.disconnect()
        self.buttonBox.accepted.connect(self.accepted)
        self.buttonBox.button(QDialogButtonBox.Ok).setText(QCoreApplication.translate("XTFModelConverterDialog", "Convert"))
        self.finished.connect(self.finished_slot)

        self.btn_browse_file_source_xtf.clicked.connect(
            make_file_selector(self.txt_source_xtf, QCoreApplication.translate("XTFModelConverterDialog",
                        "Select the INTERLIS Transfer File .xtf file you want to convert"),
                        QCoreApplication.translate("XTFModelConverterDialog", 'Transfer file (*.xtf)')))

        self.btn_browse_file_target_xtf.clicked.connect(
            make_save_file_selector(self.txt_target_xtf, QCoreApplication.translate(
                "XTFModelConverterDialog", "Set the output path of the coverted INTERLIS Transfer File"),
                                    QCoreApplication.translate("XTFModelConverterDialog", 'Transfer file (*.xtf)'),
                                    extension='.xtf'))

        self._controller.progress_changed.connect(self.progress.setValue)

        self.restore_settings()

        # Set validations
        file_validator_xtf_in = FileValidator(pattern='*.xtf', allow_non_existing=False)
        file_validator_xtf_out = FileValidator(pattern='*.xtf', allow_non_existing=True)

        self.txt_source_xtf.setValidator(file_validator_xtf_in)
        self.txt_target_xtf.setValidator(file_validator_xtf_out)

        self.txt_source_xtf.textChanged.connect(self.validators.validate_line_edits)
        self.txt_target_xtf.textChanged.connect(self.validators.validate_line_edits)

        self.txt_source_xtf.textChanged.connect(self.update_model_converters)
        self.txt_source_xtf.textChanged.connect(self.xtf_paths_changed)  # Enable/disable convert button
        self.txt_target_xtf.textChanged.connect(self.xtf_paths_changed)  # Enable/disable convert button
        self.cbo_model_converter.currentIndexChanged.connect(self.selected_converter_changed)  # Need new wizard pages?

        # Trigger validators now
        self.txt_source_xtf.textChanged.emit(self.txt_source_xtf.text())
        self.txt_target_xtf.textChanged.emit(self.txt_target_xtf.text())

    def progress_changed(self, value):
        QCoreApplication.processEvents()  # Listen to cancel from the user
        self.progress.setValue(value)

    def accepted(self):
        self.save_settings()

        self.bar.clearWidgets()  # Remove previous messages
        self.set_gui_controls_enabled(False)
        self.progress.setVisible(True)

        msg = QCoreApplication.translate("XTFModelConverterDialog", "Converting XTF data (this might take a while)...")
        with ProcessWithStatus(msg):
            params = {}
            res, msg = self._controller.convert(self.cbo_model_converter.currentData(),
                                                self.txt_source_xtf.text(),
                                                self.txt_target_xtf.text(),
                                                params)
            self.show_message(msg, Qgis.Success if res else Qgis.Warning)
            self.logger.success_warning(__name__, res, msg)

        self.set_gui_controls_enabled(True)

    def reject(self):
        if self._running_tool:
            reply = QMessageBox.question(self,
                                         QCoreApplication.translate("XTFModelConverterDialog", "Warning"),
                                         QCoreApplication.translate("XTFModelConverterDialog",
                                                                    "The '{}' tool is still running. Do you want to cancel it? If you cancel, the data might be incomplete in the target database.").format(self.tool_name),
                                         QMessageBox.Yes, QMessageBox.No)

            if reply == QMessageBox.Yes:
                self._running_tool = False
                msg = QCoreApplication.translate("XTFModelConverterDialog", "The '{}' tool was cancelled.").format(self.tool_name)
                self.logger.info(__name__, msg)
                self.show_message(msg, Qgis.Info)
        else:
            self.logger.info(__name__, "Dialog closed.")
            self.done(1)

    def finished_slot(self, result):
        self.bar.clearWidgets()

    def xtf_paths_changed(self):
        # Enable/disable 'Convert' button
        state_source_xtf = self.__source_xtf_is_valid()
        state_target_xtf = self.txt_target_xtf.validator().validate(self.txt_target_xtf.text().strip(), 0)[0] == QValidator.Acceptable

        state_converter = self.cbo_model_converter.count() and self.cbo_model_converter.currentData() != "invalid"

        self.set_convert_button_enabled(state_source_xtf and state_converter and state_target_xtf)

    def __source_xtf_is_valid(self):
        return self.txt_source_xtf.validator().validate(self.txt_source_xtf.text().strip(), 0)[0] == QValidator.Acceptable

    def selected_converter_changed(self, index):
        # Ideas for this:
        #   Some converters might need new wizard pages. So this slot should get them from the controller
        #   and pass them to a method that shows them, converting first the single-page wizard into multi-page.
        pass

    def set_convert_button_enabled(self, enable):
        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(enable)

    def update_model_converters(self):
        self.cbo_model_converter.clear()

        if self.__source_xtf_is_valid():
            self.cbo_model_converter.setEnabled(True)
            source_xtf = self.txt_source_xtf.text().strip()
            for key, text in self._controller.get_converters(source_xtf).items():
                self.cbo_model_converter.addItem(text, key)

            if not self.cbo_model_converter.count():
                self.cbo_model_converter.addItem(QCoreApplication.translate("XTFModelConverterDialog",
                                                                            "No converter found for the given source XTF"), "invalid")
        else:
            if not self.cbo_model_converter.count():
                self.cbo_model_converter.setEnabled(False)

    def initialize_progress(self):
        self.progress.setValue(0)
        self.progress.setVisible(False)

    def set_gui_controls_enabled(self, enable):
        self.set_convert_button_enabled(enable)
        self.gbx_parameters.setEnabled(enable)

    def save_settings(self):
        settings = QSettings()
        settings.setValue('Asistente-LADM-COL/xtf_model_converter/xtf_in_path', self.txt_source_xtf.text())
        settings.setValue('Asistente-LADM-COL/xtf_model_converter/xtf_out_path', self.txt_target_xtf.text())

        # In the main page (source-target configuration), save if splitter is closed
        self.app.settings.xtf_converter_splitter_collapsed = self.splitter.sizes()[1] == 0
        
    def restore_settings(self):
        settings = QSettings()
        self.txt_source_xtf.setText(settings.value('Asistente-LADM-COL/xtf_model_converter/xtf_in_path', ''))
        self.txt_target_xtf.setText(settings.value('Asistente-LADM-COL/xtf_model_converter/xtf_out_path', ''))

        # If splitter in the main page was closed before, set it as closed again
        if self.app.settings.xtf_converter_splitter_collapsed:
            sizes = self.splitter.sizes()
            self.splitter.setSizes([sizes[0], 0])
        
    def show_message(self, message, level, duration=0):
        self.bar.clearWidgets()  # Remove previous messages before showing a new one
        self.bar.pushMessage(message, level, duration)