Ejemplo n.º 1
0
    def populateTable(self, table):
        cols = len(self.param.headers())
        rows = len(table) // cols
        model = QStandardItemModel(rows, cols)

        # Set headers
        model.setHorizontalHeaderLabels(self.param.headers())

        # Populate table
        for row in range(rows):
            for col in range(cols):
                item = QStandardItem(str(table[row * cols + col]))
                model.setItem(row, col, item)
        self.tblView.setModel(model)
Ejemplo n.º 2
0
    def populateTable(self, table):
        cols = len(self.param.cols)
        rows = len(table)
        model = QStandardItemModel(rows, cols)

        # Set headers
        model.setHorizontalHeaderLabels(self.param.cols)

        # Populate table
        for i in range(rows):
            for j in range(cols):
                item = QStandardItem(table[i][j])
                model.setItem(i, j, item)
        self.tblView.setModel(model)
Ejemplo n.º 3
0
class ConfigDialog(BASE, WIDGET):

    def __init__(self, showSearch=True):
        super(ConfigDialog, self).__init__(None)
        self.setupUi(self)

        self.groupIcon = QIcon()
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirClosedIcon), QIcon.Normal, QIcon.Off)
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirOpenIcon), QIcon.Normal, QIcon.On)

        self.model = QStandardItemModel()
        self.tree.setModel(self.model)

        self.delegate = SettingDelegate()
        self.tree.setItemDelegateForColumn(1, self.delegate)

        if showSearch:
            if hasattr(self.searchBox, 'setPlaceholderText'):
                self.searchBox.setPlaceholderText(QApplication.translate('ConfigDialog', 'Search…'))
            self.searchBox.textChanged.connect(self.textChanged)
        else:
            self.searchBox.hide()

        self.fillTree()

        self.saveMenus = False
        self.tree.expanded.connect(self.itemExpanded)
        self.auto_adjust_columns = True

    def textChanged(self, text=None):
        if text is not None:
            text = str(text.lower())
        else:
            text = str(self.searchBox.text().lower())
        found = self._filterItem(self.model.invisibleRootItem(), text)

        self.auto_adjust_columns = False
        if text:
            self.tree.expandAll()
        else:
            self.tree.collapseAll()

        self.adjustColumns()
        self.auto_adjust_columns = True

        if text:
            return found
        else:
            self.tree.collapseAll()
            return False

    def _filterItem(self, item, text, forceShow=False):
        if item.hasChildren():
            show = forceShow or isinstance(item, QStandardItem) and bool(text) and (text in item.text().lower())
            for i in range(item.rowCount()):
                child = item.child(i)
                show = self._filterItem(child, text, forceShow) or show
            self.tree.setRowHidden(item.row(), item.index().parent(), not show)
            return show

        elif isinstance(item, QStandardItem):
            show = forceShow or bool(text) and (text in item.text().lower())
            self.tree.setRowHidden(item.row(), item.index().parent(), not show)
            return show

    def fillTree(self):
        self.fillTreeUsingProviders()

    def fillTreeUsingProviders(self):
        self.items = {}
        self.model.clear()
        self.model.setHorizontalHeaderLabels([self.tr('Setting'),
                                              self.tr('Value')])

        settings = ProcessingConfig.getSettings()

        rootItem = self.model.invisibleRootItem()

        """
        Filter 'General', 'Models' and 'Scripts' items
        """
        priorityKeys = [self.tr('General'), self.tr('Models'), self.tr('Scripts')]
        for group in priorityKeys:
            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            emptyItem = QStandardItem()
            emptyItem.setEditable(False)

            rootItem.insertRow(0, [groupItem, emptyItem])
            if not group in settings:
                continue

            # add menu item only if it has any search matches
            for setting in settings[group]:
                if setting.hidden or setting.name.startswith("MENU_"):
                    continue

                labelItem = QStandardItem(setting.description)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])

        """
        Filter 'Providers' items
        """
        providersItem = QStandardItem(self.tr('Providers'))
        icon = QgsApplication.getThemeIcon("/processingAlgorithm.svg")
        providersItem.setIcon(icon)
        providersItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)

        rootItem.insertRow(0, [providersItem, emptyItem])
        for group in list(settings.keys()):
            if group in priorityKeys or group == menusSettingsGroup:
                continue

            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)

            for setting in settings[group]:
                if setting.hidden:
                    continue

                labelItem = QStandardItem(setting.description)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            providersItem.appendRow([groupItem, emptyItem])

        """
        Filter 'Menus' items
        """
        self.menusItem = QStandardItem(self.tr('Menus'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'menu.png'))
        self.menusItem.setIcon(icon)
        self.menusItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)

        rootItem.insertRow(0, [self.menusItem, emptyItem])

        button = QPushButton(self.tr('Reset to defaults'))
        button.clicked.connect(self.resetMenusToDefaults)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(button)
        layout.addStretch()
        widget = QWidget()
        widget.setLayout(layout)
        self.tree.setIndexWidget(emptyItem.index(), widget)

        for provider in QgsApplication.processingRegistry().providers():
            providerDescription = provider.name()
            groupItem = QStandardItem(providerDescription)
            icon = provider.icon()
            groupItem.setIcon(icon)
            groupItem.setEditable(False)

            for alg in provider.algorithms():
                algItem = QStandardItem(alg.displayName())
                algItem.setIcon(icon)
                algItem.setEditable(False)
                try:
                    settingMenu = ProcessingConfig.settings["MENU_" + alg.id()]
                    settingButton = ProcessingConfig.settings["BUTTON_" + alg.id()]
                    settingIcon = ProcessingConfig.settings["ICON_" + alg.id()]
                except:
                    continue
                self.items[settingMenu] = SettingItem(settingMenu)
                self.items[settingButton] = SettingItem(settingButton)
                self.items[settingIcon] = SettingItem(settingIcon)
                menuLabelItem = QStandardItem("Menu path")
                menuLabelItem.setEditable(False)
                buttonLabelItem = QStandardItem("Add button in toolbar")
                buttonLabelItem.setEditable(False)
                iconLabelItem = QStandardItem("Icon")
                iconLabelItem.setEditable(False)
                emptyItem = QStandardItem()
                emptyItem.setEditable(False)
                algItem.insertRow(0, [menuLabelItem, self.items[settingMenu]])
                algItem.insertRow(0, [buttonLabelItem, self.items[settingButton]])
                algItem.insertRow(0, [iconLabelItem, self.items[settingIcon]])
                groupItem.insertRow(0, [algItem, emptyItem])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)

            self.menusItem.appendRow([groupItem, emptyItem])

        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.adjustColumns()

    def resetMenusToDefaults(self):
        for provider in QgsApplication.processingRegistry().providers():
            for alg in provider.algorithms():
                d = defaultMenuEntries.get(alg.id(), "")
                setting = ProcessingConfig.settings["MENU_" + alg.id()]
                item = self.items[setting]
                item.setData(d, Qt.EditRole)
        self.saveMenus = True

    def accept(self):
        qsettings = QgsSettings()
        for setting in list(self.items.keys()):
            if setting.group != menusSettingsGroup or self.saveMenus:
                if isinstance(setting.value, bool):
                    setting.setValue(self.items[setting].checkState() == Qt.Checked)
                else:
                    try:
                        setting.setValue(str(self.items[setting].text()))
                    except ValueError as e:
                        QMessageBox.warning(self, self.tr('Wrong value'),
                                            self.tr('Wrong value for parameter "{0}":\n\n{1}').format(setting.description, str(e)))
                        return
                setting.save(qsettings)

        with OverrideCursor(Qt.WaitCursor):
            for p in QgsApplication.processingRegistry().providers():
                p.refreshAlgorithms()

        settingsWatcher.settingsChanged.emit()

    def itemExpanded(self, idx):
        if idx == self.menusItem.index():
            self.saveMenus = True
        if self.auto_adjust_columns:
            self.adjustColumns()

    def adjustColumns(self):
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(1)
Ejemplo n.º 4
0
class ConfigDialog(BASE, WIDGET):

    def __init__(self, toolbox):
        super(ConfigDialog, self).__init__(None)
        self.setupUi(self)

        self.toolbox = toolbox
        self.groupIcon = QIcon()
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirClosedIcon), QIcon.Normal, QIcon.Off)
        self.groupIcon.addPixmap(self.style().standardPixmap(
            QStyle.SP_DirOpenIcon), QIcon.Normal, QIcon.On)

        if hasattr(self.searchBox, 'setPlaceholderText'):
            self.searchBox.setPlaceholderText(self.tr('Search...'))

        self.model = QStandardItemModel()
        self.tree.setModel(self.model)

        self.delegate = SettingDelegate()
        self.tree.setItemDelegateForColumn(1, self.delegate)

        self.searchBox.textChanged.connect(self.textChanged)

        self.fillTree()

        self.tree.expanded.connect(self.adjustColumns)

    def textChanged(self):
        text = str(self.searchBox.text().lower())
        self._filterItem(self.model.invisibleRootItem(), text)
        if text:
            self.tree.expandAll()
        else:
            self.tree.collapseAll()

    def _filterItem(self, item, text):
        if item.hasChildren():
            show = False
            for i in range(item.rowCount()):
                child = item.child(i)
                showChild = self._filterItem(child, text)
                show = (showChild or show)
            self.tree.setRowHidden(item.row(), item.index().parent(), not show)
            return show

        elif isinstance(item, QStandardItem):
            hide = bool(text) and (text not in item.text().lower())
            self.tree.setRowHidden(item.row(), item.index().parent(), hide)
            return not hide

    def fillTree(self):
        self.fillTreeUsingProviders()

    def fillTreeUsingProviders(self):
        self.items = {}
        self.model.clear()
        self.model.setHorizontalHeaderLabels([self.tr('Setting'),
                                              self.tr('Value')])

        settings = ProcessingConfig.getSettings()

        rootItem = self.model.invisibleRootItem()

        """
        Filter 'General', 'Models' and 'Scripts' items
        """
        priorityKeys = [self.tr('General'), self.tr('Models'), self.tr('Scripts')]
        for group in priorityKeys:
            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            emptyItem = QStandardItem()
            emptyItem.setEditable(False)

            rootItem.insertRow(0, [groupItem, emptyItem])
            # add menu item only if it has any search matches
            for setting in settings[group]:
                if setting.hidden or setting.name.startswith("MENU_"):
                    continue

                labelItem = QStandardItem(setting.description)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])

        """
        Filter 'Providers' items
        """
        providersItem = QStandardItem(self.tr('Providers'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'alg.png'))
        providersItem.setIcon(icon)
        providersItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)

        rootItem.insertRow(0, [providersItem, emptyItem])
        for group in list(settings.keys()):
            if group in priorityKeys or group == menusSettingsGroup:
                continue

            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)

            for setting in settings[group]:
                if setting.hidden:
                    continue

                labelItem = QStandardItem(setting.description)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            providersItem.appendRow([groupItem, emptyItem])

        """
        Filter 'Menus' items
        """
        menusItem = QStandardItem(self.tr('Menus'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'menu.png'))
        menusItem.setIcon(icon)
        menusItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)

        rootItem.insertRow(0, [menusItem, emptyItem])

        button = QPushButton(self.tr('Reset to defaults'))
        button.clicked.connect(self.resetMenusToDefaults)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(button)
        layout.addStretch()
        widget = QWidget()
        widget.setLayout(layout)
        self.tree.setIndexWidget(emptyItem.index(), widget)

        providers = Processing.providers
        for provider in providers:
            providerDescription = provider.getDescription()
            groupItem = QStandardItem(providerDescription)
            icon = provider.getIcon()
            groupItem.setIcon(icon)
            groupItem.setEditable(False)

            for alg in provider.algs:
                algItem = QStandardItem(alg.i18n_name or alg.name)
                algItem.setIcon(icon)
                algItem.setEditable(False)
                try:
                    settingMenu = ProcessingConfig.settings["MENU_" + alg.commandLineName()]
                    settingButton = ProcessingConfig.settings["BUTTON_" + alg.commandLineName()]
                    settingIcon = ProcessingConfig.settings["ICON_" + alg.commandLineName()]
                except:
                    continue
                self.items[settingMenu] = SettingItem(settingMenu)
                self.items[settingButton] = SettingItem(settingButton)
                self.items[settingIcon] = SettingItem(settingIcon)
                menuLabelItem = QStandardItem("Menu path")
                menuLabelItem.setEditable(False)
                buttonLabelItem = QStandardItem("Add button in toolbar")
                buttonLabelItem.setEditable(False)
                iconLabelItem = QStandardItem("Icon")
                iconLabelItem.setEditable(False)
                emptyItem = QStandardItem()
                emptyItem.setEditable(False)
                algItem.insertRow(0, [menuLabelItem, self.items[settingMenu]])
                algItem.insertRow(0, [buttonLabelItem, self.items[settingButton]])
                algItem.insertRow(0, [iconLabelItem, self.items[settingIcon]])
                groupItem.insertRow(0, [algItem, emptyItem])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)

            menusItem.appendRow([groupItem, emptyItem])

        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.adjustColumns()

    def resetMenusToDefaults(self):
        providers = Processing.providers
        for provider in providers:
            for alg in provider.algs:
                d = defaultMenuEntries.get(alg.commandLineName(), "")
                setting = ProcessingConfig.settings["MENU_" + alg.commandLineName()]
                item = self.items[setting]
                item.setData(d, Qt.EditRole)

    def accept(self):
        for setting in list(self.items.keys()):
            if isinstance(setting.value, bool):
                setting.setValue(self.items[setting].checkState() == Qt.Checked)
            else:
                try:
                    setting.setValue(str(self.items[setting].text()))
                except ValueError as e:
                    QMessageBox.warning(self, self.tr('Wrong value'),
                                        self.tr('Wrong value for parameter "%s":\n\n%s' % (setting.description, str(e))))
                    return
            setting.save()
        Processing.updateAlgsList()
        settingsWatcher.settingsChanged.emit()

        QDialog.accept(self)

    def adjustColumns(self):
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(1)
Ejemplo n.º 5
0
class ConfigDialog(BASE, WIDGET):
    def __init__(self):
        super(ConfigDialog, self).__init__(None)
        self.setupUi(self)

        self.groupIcon = QIcon()
        self.groupIcon.addPixmap(
            self.style().standardPixmap(QStyle.SP_DirClosedIcon), QIcon.Normal,
            QIcon.Off)
        self.groupIcon.addPixmap(
            self.style().standardPixmap(QStyle.SP_DirOpenIcon), QIcon.Normal,
            QIcon.On)

        if hasattr(self.searchBox, 'setPlaceholderText'):
            self.searchBox.setPlaceholderText(self.tr('Search...'))

        self.model = QStandardItemModel()
        self.tree.setModel(self.model)

        self.delegate = SettingDelegate()
        self.tree.setItemDelegateForColumn(1, self.delegate)

        self.searchBox.textChanged.connect(self.textChanged)

        self.fillTree()

        self.saveMenus = False
        self.tree.expanded.connect(self.itemExpanded)

    def textChanged(self):
        text = str(self.searchBox.text().lower())
        self._filterItem(self.model.invisibleRootItem(), text)
        if text:
            self.tree.expandAll()
        else:
            self.tree.collapseAll()

    def _filterItem(self, item, text):
        if item.hasChildren():
            show = False
            for i in range(item.rowCount()):
                child = item.child(i)
                showChild = self._filterItem(child, text)
                show = (showChild or show)
            self.tree.setRowHidden(item.row(), item.index().parent(), not show)
            return show

        elif isinstance(item, QStandardItem):
            hide = bool(text) and (text not in item.text().lower())
            self.tree.setRowHidden(item.row(), item.index().parent(), hide)
            return not hide

    def fillTree(self):
        self.fillTreeUsingProviders()

    def fillTreeUsingProviders(self):
        self.items = {}
        self.model.clear()
        self.model.setHorizontalHeaderLabels(
            [self.tr('Setting'), self.tr('Value')])

        settings = ProcessingConfig.getSettings()

        rootItem = self.model.invisibleRootItem()
        """
        Filter 'General', 'Models' and 'Scripts' items
        """
        priorityKeys = [
            self.tr('General'),
            self.tr('Models'),
            self.tr('Scripts')
        ]
        for group in priorityKeys:
            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)
            emptyItem = QStandardItem()
            emptyItem.setEditable(False)

            rootItem.insertRow(0, [groupItem, emptyItem])
            if not group in settings:
                continue

            # add menu item only if it has any search matches
            for setting in settings[group]:
                if setting.hidden or setting.name.startswith("MENU_"):
                    continue

                labelItem = QStandardItem(setting.description)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])
        """
        Filter 'Providers' items
        """
        providersItem = QStandardItem(self.tr('Providers'))
        icon = QgsApplication.getThemeIcon("/processingAlgorithm.svg")
        providersItem.setIcon(icon)
        providersItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)

        rootItem.insertRow(0, [providersItem, emptyItem])
        for group in list(settings.keys()):
            if group in priorityKeys or group == menusSettingsGroup:
                continue

            groupItem = QStandardItem(group)
            icon = ProcessingConfig.getGroupIcon(group)
            groupItem.setIcon(icon)
            groupItem.setEditable(False)

            for setting in settings[group]:
                if setting.hidden:
                    continue

                labelItem = QStandardItem(setting.description)
                labelItem.setIcon(icon)
                labelItem.setEditable(False)
                self.items[setting] = SettingItem(setting)
                groupItem.insertRow(0, [labelItem, self.items[setting]])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)
            providersItem.appendRow([groupItem, emptyItem])
        """
        Filter 'Menus' items
        """
        self.menusItem = QStandardItem(self.tr('Menus'))
        icon = QIcon(os.path.join(pluginPath, 'images', 'menu.png'))
        self.menusItem.setIcon(icon)
        self.menusItem.setEditable(False)
        emptyItem = QStandardItem()
        emptyItem.setEditable(False)

        rootItem.insertRow(0, [self.menusItem, emptyItem])

        button = QPushButton(self.tr('Reset to defaults'))
        button.clicked.connect(self.resetMenusToDefaults)
        layout = QHBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(button)
        layout.addStretch()
        widget = QWidget()
        widget.setLayout(layout)
        self.tree.setIndexWidget(emptyItem.index(), widget)

        for provider in QgsApplication.processingRegistry().providers():
            providerDescription = provider.name()
            groupItem = QStandardItem(providerDescription)
            icon = provider.icon()
            groupItem.setIcon(icon)
            groupItem.setEditable(False)

            for alg in provider.algorithms():
                algItem = QStandardItem(alg.displayName())
                algItem.setIcon(icon)
                algItem.setEditable(False)
                try:
                    settingMenu = ProcessingConfig.settings["MENU_" + alg.id()]
                    settingButton = ProcessingConfig.settings["BUTTON_" +
                                                              alg.id()]
                    settingIcon = ProcessingConfig.settings["ICON_" + alg.id()]
                except:
                    continue
                self.items[settingMenu] = SettingItem(settingMenu)
                self.items[settingButton] = SettingItem(settingButton)
                self.items[settingIcon] = SettingItem(settingIcon)
                menuLabelItem = QStandardItem("Menu path")
                menuLabelItem.setEditable(False)
                buttonLabelItem = QStandardItem("Add button in toolbar")
                buttonLabelItem.setEditable(False)
                iconLabelItem = QStandardItem("Icon")
                iconLabelItem.setEditable(False)
                emptyItem = QStandardItem()
                emptyItem.setEditable(False)
                algItem.insertRow(0, [menuLabelItem, self.items[settingMenu]])
                algItem.insertRow(0,
                                  [buttonLabelItem, self.items[settingButton]])
                algItem.insertRow(0, [iconLabelItem, self.items[settingIcon]])
                groupItem.insertRow(0, [algItem, emptyItem])

            emptyItem = QStandardItem()
            emptyItem.setEditable(False)

            self.menusItem.appendRow([groupItem, emptyItem])

        self.tree.sortByColumn(0, Qt.AscendingOrder)
        self.adjustColumns()

    def resetMenusToDefaults(self):
        for provider in QgsApplication.processingRegistry().providers():
            for alg in provider.algorithms():
                d = defaultMenuEntries.get(alg.id(), "")
                setting = ProcessingConfig.settings["MENU_" + alg.id()]
                item = self.items[setting]
                item.setData(d, Qt.EditRole)
        self.saveMenus = True

    def accept(self):
        qsettings = QgsSettings()
        for setting in list(self.items.keys()):
            if setting.group != menusSettingsGroup or self.saveMenus:
                if isinstance(setting.value, bool):
                    setting.setValue(
                        self.items[setting].checkState() == Qt.Checked)
                else:
                    try:
                        setting.setValue(str(self.items[setting].text()))
                    except ValueError as e:
                        QMessageBox.warning(
                            self, self.tr('Wrong value'),
                            self.tr('Wrong value for parameter "{0}":\n\n{1}').
                            format(setting.description, str(e)))
                        return
                setting.save(qsettings)

        with OverrideCursor(Qt.WaitCursor):
            for p in QgsApplication.processingRegistry().providers():
                p.refreshAlgorithms()

        settingsWatcher.settingsChanged.emit()

    def itemExpanded(self, idx):
        if idx == self.menusItem.index():
            self.saveMenus = True
        self.adjustColumns()

    def adjustColumns(self):
        self.tree.resizeColumnToContents(0)
        self.tree.resizeColumnToContents(1)
Ejemplo n.º 6
0
class SchematisationLoad(uicls, basecls):
    """Dialog for local schematisation loading."""
    def __init__(self, plugin_dock, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.plugin_dock = plugin_dock
        self.working_dir = self.plugin_dock.plugin_settings.working_dir
        self.communication = self.plugin_dock.communication
        self.local_schematisations = list_local_schematisations(
            self.working_dir)
        self.tv_schematisations_model = QStandardItemModel()
        self.schematisations_tv.setModel(self.tv_schematisations_model)
        self.tv_revisions_model = QStandardItemModel()
        self.revisions_tv.setModel(self.tv_revisions_model)
        self.selected_local_schematisation = None
        self.pb_load.clicked.connect(self.load_local_schematisation)
        self.pb_cancel.clicked.connect(self.cancel_load_local_schematisation)
        self.schematisations_tv.selectionModel().selectionChanged.connect(
            self.populate_local_schematisation_revisions)
        self.revisions_tv.selectionModel().selectionChanged.connect(
            self.toggle_load_local_schematisation)
        self.populate_local_schematisations()

    def populate_local_schematisations(self):
        """Populate local schematisations."""
        self.tv_revisions_model.clear()
        self.tv_schematisations_model.clear()
        header = ["Schematisation name", "Schematisation ID", "Absolute path"]
        self.tv_schematisations_model.setHorizontalHeaderLabels(header)
        for schematisation_id, local_schematisation in self.local_schematisations.items(
        ):
            name_item = QStandardItem(local_schematisation.name)
            name_item.setData(local_schematisation, role=Qt.UserRole)
            id_item = QStandardItem(str(schematisation_id))
            dir_item = QStandardItem(local_schematisation.main_dir)
            self.tv_schematisations_model.appendRow(
                [name_item, id_item, dir_item])
        for i in range(len(header)):
            self.schematisations_tv.resizeColumnToContents(i)

    def populate_local_schematisation_revisions(self):
        """Populate local schematisation revisions."""
        self.tv_revisions_model.clear()
        header = ["Revision number", "Subdirectory"]
        self.tv_revisions_model.setHorizontalHeaderLabels(header)
        local_schematisation = self.get_selected_local_schematisation()
        wip_revision = local_schematisation.wip_revision
        if wip_revision is not None:
            number_item = QStandardItem(str(wip_revision.number))
            number_item.setData(wip_revision, role=Qt.UserRole)
            subdir_item = QStandardItem(wip_revision.sub_dir)
            self.tv_revisions_model.appendRow([number_item, subdir_item])
        for revision_number, local_revision in reversed(
                local_schematisation.revisions.items()):
            number_item = QStandardItem(str(revision_number))
            number_item.setData(local_revision, role=Qt.UserRole)
            subdir_item = QStandardItem(local_revision.sub_dir)
            self.tv_revisions_model.appendRow([number_item, subdir_item])
        for i in range(len(header)):
            self.schematisations_tv.resizeColumnToContents(i)
        if self.tv_revisions_model.rowCount() > 0:
            row_idx = self.tv_revisions_model.index(0, 0)
            self.revisions_tv.selectionModel().setCurrentIndex(
                row_idx, QItemSelectionModel.ClearAndSelect)
        self.toggle_load_local_schematisation()

    def toggle_load_local_schematisation(self):
        """Toggle load button if any schematisation revision is selected."""
        selection_model = self.revisions_tv.selectionModel()
        if selection_model.hasSelection():
            self.pb_load.setEnabled(True)
        else:
            self.pb_load.setDisabled(True)

    def get_selected_local_schematisation(self):
        """Get currently selected local schematisation."""
        index = self.schematisations_tv.currentIndex()
        if index.isValid():
            current_row = index.row()
            name_item = self.tv_schematisations_model.item(current_row, 0)
            local_schematisation = name_item.data(Qt.UserRole)
        else:
            local_schematisation = None
        return local_schematisation

    def get_selected_local_revision(self):
        """Get currently selected local revision."""
        index = self.revisions_tv.currentIndex()
        if index.isValid():
            current_row = index.row()
            name_item = self.tv_revisions_model.item(current_row, 0)
            local_revision = name_item.data(Qt.UserRole)
        else:
            local_revision = None
        return local_revision

    def load_local_schematisation(self):
        """Loading selected local schematisation."""
        local_schematisation = self.get_selected_local_schematisation()
        local_revision = self.get_selected_local_revision()
        if not isinstance(local_revision, WIPRevision):
            title = "Pick action"
            question = f"Replace WIP with data from the revision {local_revision.number}?"
            picked_action_name = self.communication.custom_ask(
                self, title, question, "Replace", "Cancel")
            if picked_action_name == "Replace":
                wip_revision = local_schematisation.set_wip_revision(
                    local_revision.number)
                replace_revision_data(local_revision, wip_revision)
            else:
                local_schematisation = None
        self.selected_local_schematisation = local_schematisation
        self.close()

    def cancel_load_local_schematisation(self):
        """Cancel local schematisation loading."""
        self.close()
Ejemplo n.º 7
0
class AdjustmentDialogThresholds(QObject):

    COLOR_ERROR = QColor(224, 103, 103)
    COLOR_ATTENTION = QColor(237, 148, 76)
    COLOR_NEUTRAL = QColor(255, 255, 255)
    COLOR = {1: COLOR_NEUTRAL, 2: COLOR_ATTENTION, 3: COLOR_ERROR}

    sig_clickedRow = pyqtSignal(int)

    def __init__(self, parent, datasetSize):
        """
        :type parent: gui.adjustmentDialog.AdjustmentDialog
        """
        super().__init__()
        self.parent = parent
        self.tbl = self.parent.tableThresholds
        self.model = QStandardItemModel(datasetSize[0], datasetSize[1],
                                        self.tbl)
        self.initState = True
        self.thresholdExeeded = False
        self.tbl.setModel(self.model)
        self.tbl.resizeColumnsToContents()
        self.tbl.resizeRowsToContents()
        # Icons
        self.iconOk = QIcon()
        self.iconOk.addPixmap(
            QPixmap(":/plugins/SeilaplanPlugin/gui/icons/icon_green.png"),
            QIcon.Normal, QIcon.Off)
        self.iconErr = QIcon()
        self.iconErr.addPixmap(
            QPixmap(
                ":/plugins/SeilaplanPlugin/gui/icons/icon_exclamation.png"),
            QIcon.Normal, QIcon.Off)

        self.tbl.clicked.connect(self.onClick)

    def populate(self, header, dataset, valueColumn):
        self.model.setHorizontalHeaderLabels(header)
        self.tbl.hideColumn(5)

        # Insert data into cells
        for i, rowData in enumerate(dataset):
            for j, cellData in enumerate(rowData):
                if j == 0:
                    # Create clickable info button in first column
                    btnWidget = self.createInfoBtn(cellData)
                    self.tbl.setIndexWidget(self.model.index(i, j), btnWidget)
                    continue
                if j == 5 and isinstance(cellData, dict):
                    loclen = len(cellData['loc'])
                    if loclen > 0:
                        # Set background color for cells where threshold is
                        #  exceeded
                        color = self.COLOR[max(cellData['color'] or [1])]
                        self.colorBackground(i, valueColumn, color)
                    cellData = loclen
                item = QStandardItem(cellData)
                self.model.setItem(i, j, item)
                self.model.setData(self.model.index(i, j), cellData)

        # Adjust column widths
        self.tbl.resizeColumnsToContents()
        for idx in range(2, self.model.columnCount()):
            currSize = self.tbl.sizeHintForColumn(idx)
            self.tbl.setColumnWidth(idx, max(currSize, 100))
        self.tbl.setFocusPolicy(Qt.NoFocus)
        self.updateTabIcon()

    def updateData(self, row, col, newVal):
        # Update background color of new values
        if col == 5 and isinstance(newVal, dict):
            locLen = len(newVal['loc'])
            color = self.COLOR[max(newVal['color'] or [1])]
            self.colorBackground(row, 4, color)
            newVal = locLen
        # Update value itself
        self.model.setData(self.model.index(row, col), newVal)
        self.updateTabIcon()

        # Remove the background color from initially calculated
        # cable line data
        if self.initState:
            self.initState = False
            for row in range(self.model.rowCount()):
                self.colorBackground(row, 3, self.COLOR_NEUTRAL)

    def colorBackground(self, row, col, color):
        self.model.setData(self.model.index(row, col), QBrush(color),
                           Qt.BackgroundRole)

    def updateTabIcon(self):
        """ Updates icon of QTabWidget with an exclamation mark or check
        mark depending on presents of exceeded thresholds."""
        thresholdExceeded = False
        for i in range(0, self.model.rowCount()):
            if i == 2:
                # Dont check thresholds for 'Sattelkraft'
                continue
            data = self.model.data(self.model.index(i, 5))
            if data and data > 0:
                thresholdExceeded = True
                break
        if thresholdExceeded:
            self.parent.tabWidget.setTabIcon(2, self.iconErr)
        else:
            self.parent.tabWidget.setTabIcon(2, self.iconOk)

    def onClick(self, item):
        # Row is already selected
        if self.parent.selectedThdRow == item.row():
            # Deselect
            self.tbl.clearSelection()
        # Emit select signal
        self.sig_clickedRow.emit(item.row())

    def createInfoBtn(self, cellData):
        button = QPushButton('?')
        button.setMaximumSize(QSize(22, 22))
        # Fill info text into message box
        button.clicked.connect(
            lambda: QMessageBox.information(self.parent, cellData[
                'title'], cellData['message'], QMessageBox.Ok))
        cellWidget = QWidget()
        # Add layout to center button in cell
        layout = QHBoxLayout(cellWidget)
        layout.addWidget(button, 0, Qt.AlignCenter)
        layout.setAlignment(Qt.AlignCenter)
        cellWidget.setLayout(layout)
        return cellWidget
Ejemplo n.º 8
0
class PosiviewProperties(QgsOptionsDialogBase, Ui_PosiviewPropertiesBase):
    '''
    GUI class classdocs for the Configuration dialog
    '''
    applyChanges = pyqtSignal(dict)

    PROVIDER_FLAGS = {}

    def __init__(self, project, parent=None):
        '''
        Setup dialog widgets with the project properties
        '''
        super(PosiviewProperties, self).__init__("PosiViewProperties", parent)
        self.setupUi(self)
        if not self.PROVIDER_FLAGS:
            self.PROVIDER_FLAGS[FILTER_FLAGS[0]] = self.tr('ignore heading')
            self.PROVIDER_FLAGS[FILTER_FLAGS[1]] = self.tr('ignore position')
            self.PROVIDER_FLAGS[FILTER_FLAGS[2]] = self.tr('course as heading')
        self.comboBoxProviderFlags.addItems(list(self.PROVIDER_FLAGS.values()))
        self.groupBox_6.hide()
        self.initOptionsBase(False)
        self.restoreOptionsBaseUi()
        self.comboBoxParser.addItems(PARSERS)
        self.comboBoxProviderType.addItems(DEVICE_TYPES)
        self.project = project
        self.projectProperties = project.properties()
        self.mToolButtonLoad.setDefaultAction(self.actionLoadConfiguration)
        self.mToolButtonSave.setDefaultAction(self.actionSaveConfiguration)

        self.mobileListModel = QStringListModel()
        self.mMobileListView.setModel(self.mobileListModel)
        self.mobileProviderModel = QStandardItemModel()
        self.mobileProviderModel.setHorizontalHeaderLabels(
            (self.tr('Provider'), self.tr('Filter'),
             self.tr('Advanced Filter')))
        self.mMobileProviderTableView.setModel(self.mobileProviderModel)

        self.providerListModel = QStringListModel()
        self.mDataProviderListView.setModel(self.providerListModel)
        self.comboBoxProviders.setModel(self.providerListModel)
        self.setupModelData(self.projectProperties)
        self.setupGeneralData(self.projectProperties)

    def setupModelData(self, properties):
        self.mobileListModel.setStringList(sorted(
            properties['Mobiles'].keys()))
        self.providerListModel.setStringList(
            sorted(properties['Provider'].keys()))

    def setupGeneralData(self, properties):
        self.lineEditCruise.setText(properties['Mission']['cruise'])
        self.lineEditDive.setText(properties['Mission']['dive'])
        self.lineEditStation.setText(properties['Mission']['station'])
        self.lineEditRecorderPath.setText(properties['RecorderPath'])
        self.checkBoxAutoRecording.setChecked(properties['AutoRecord'])
        self.spinBoxNotifyDuration.setValue(properties['NotifyDuration'])
        self.checkBoxUtcClock.setChecked(properties['ShowUtcClock'])
        self.checkBoxWithSuffix.setChecked(properties['DefaultFormat'] & 4)
        self.comboBoxDefaultPositionFormat.setCurrentIndex(
            (properties['DefaultFormat']) & 3)

    def updateGeneralData(self):
        self.projectProperties['Mission']['cruise'] = self.lineEditCruise.text(
        )
        self.projectProperties['Mission']['dive'] = self.lineEditDive.text()
        self.projectProperties['Mission'][
            'station'] = self.lineEditStation.text()
        self.projectProperties[
            'RecorderPath'] = self.lineEditRecorderPath.text()
        self.projectProperties[
            'AutoRecord'] = self.checkBoxAutoRecording.isChecked()
        self.projectProperties[
            'NotifyDuration'] = self.spinBoxNotifyDuration.value()
        self.projectProperties[
            'ShowUtcClock'] = self.checkBoxUtcClock.isChecked()
        self.projectProperties[
            'DefaultFormat'] = self.comboBoxDefaultPositionFormat.currentIndex(
            )
        if self.checkBoxWithSuffix.isChecked():
            self.projectProperties['DefaultFormat'] |= 4

    def getColor(self, value):
        try:
            return QColor.fromRgba(int(value))
        except ValueError:
            return QColor(value)

    @pyqtSlot(QAbstractButton, name='on_buttonBox_clicked')
    def onButtonBoxClicked(self, button):
        role = self.buttonBox.buttonRole(button)
        if role == QDialogButtonBox.ApplyRole or role == QDialogButtonBox.AcceptRole:
            self.updateGeneralData()
            self.applyChanges.emit(self.projectProperties)

    @pyqtSlot(name='on_actionSaveConfiguration_triggered')
    def onActionSaveConfigurationTriggered(self):
        ''' Save the current configuration
        '''
        fn, __ = QFileDialog.getSaveFileName(None,
                                             'Save PosiView configuration', '',
                                             'Configuration (*.ini *.conf)')
        if fn:
            if not os.path.splitext(fn)[1]:
                fn += u'.conf'
            self.project.store(fn)

    @pyqtSlot(name='on_actionLoadConfiguration_triggered')
    def onActionLoadConfigurationTriggered(self):
        ''' Load configuration from file
        '''
        fn, __ = QFileDialog.getOpenFileName(None,
                                             'Save PosiView configuration', '',
                                             'Configuration (*.ini *.conf)')
        self.projectProperties = self.project.read(fn)
        self.setupModelData(self.projectProperties)
        self.setupGeneralData(self.projectProperties)

    @pyqtSlot(QModelIndex, name='on_mMobileListView_clicked')
    def editMobile(self, index):
        ''' Populate the widgets with the selected mobiles properties
        '''
        if index.isValid():
            self.populateMobileWidgets(index)

    @pyqtSlot(str, name='on_comboBoxMobileType_currentIndexChanged')
    def mobileTypeChanged(self, mType):
        if mType == 'SHAPE':
            self.lineEditMobileShape.setEnabled(True)
        else:
            self.lineEditMobileShape.setEnabled(False)

    @pyqtSlot(QModelIndex, name='on_mMobileListView_activated')
    def activated(self, index):
        pass

    @pyqtSlot(name='on_toolButtonAddMobile_clicked')
    def addMobile(self):
        self.mobileListModel.insertRow(self.mobileListModel.rowCount())
        index = self.mobileListModel.index(self.mobileListModel.rowCount() - 1)
        self.lineEditMobileName.setText('NewMobile')
        self.mobileListModel.setData(index, 'NewMobile', Qt.DisplayRole)
        self.mMobileListView.setCurrentIndex(index)
        self.applyMobile()

    @pyqtSlot(name='on_pushButtonApplyMobile_clicked')
    def applyMobile(self):
        index = self.mMobileListView.currentIndex()
        if index.isValid() and not self.lineEditMobileName.text() == '':
            mobile = dict()
            mobile['Name'] = self.lineEditMobileName.text()
            mobile['type'] = self.comboBoxMobileType.currentText()
            try:
                t = eval(self.lineEditMobileShape.text())
                if t.__class__ is tuple or t.__class__ is dict:
                    mobile['shape'] = t
            except SyntaxError:
                mobile['shape'] = ((0.0, -0.5), (0.3, 0.5), (0.0, 0.2), (-0.5,
                                                                         0.5))
            mobile['length'] = self.doubleSpinBoxMobileLength.value()
            mobile['width'] = self.doubleSpinBoxMobileWidth.value()
            mobile['defaultIcon'] = self.checkBoxDefaultIcon.isChecked()
            mobile['defaultIconFilled'] = self.checkBoxDefIconFilled.isChecked(
            )
            mobile['offsetX'] = self.doubleSpinBoxXOffset.value()
            mobile['offsetY'] = self.doubleSpinBoxYOffset.value()
            mobile['zValue'] = self.spinBoxZValue.value()
            mobile['color'] = self.mColorButtonMobileColor.color().rgba()
            mobile['fillColor'] = self.mColorButtonMobileFillColor.color(
            ).rgba()
            mobile['timeout'] = self.spinBoxMobileTimeout.value() * 1000
            mobile['nofixNotify'] = self.spinBoxMobileNotification.value()
            mobile['fadeOut'] = self.checkBoxFadeOut.isChecked()
            mobile['trackLength'] = self.spinBoxTrackLength.value()
            mobile['trackColor'] = self.mColorButtonMobileTrackColor.color(
            ).rgba()
            mobile['showLabel'] = self.checkBoxShowLabel.isChecked()
            provs = dict()
            for r in range(self.mobileProviderModel.rowCount()):
                try:
                    fil = self.mobileProviderModel.item(r,
                                                        1).data(Qt.DisplayRole)
                    try:
                        fil = int(fil)
                    except (TypeError, ValueError):
                        if not fil:
                            fil = None
                except AttributeError:
                    fil = None

                try:
                    flags = list()
                    flgs = self.mobileProviderModel.item(r, 2).data(
                        Qt.DisplayRole).split(', ')
                    for k, v in self.PROVIDER_FLAGS.items():
                        if v in flgs:
                            flags.append(k)
                except AttributeError:
                    pass

                provs[self.mobileProviderModel.item(r, 0).data(
                    Qt.DisplayRole)] = {
                        'id': fil,
                        'flags': flags
                    }

            mobile['provider'] = provs
            currName = self.mobileListModel.data(index, Qt.DisplayRole)
            if not currName == mobile['Name']:
                del self.projectProperties['Mobiles'][currName]
                self.mobileListModel.setData(index, mobile['Name'],
                                             Qt.DisplayRole)
            self.projectProperties['Mobiles'][mobile['Name']] = mobile

    def populateMobileWidgets(self, index):
        mobile = self.projectProperties['Mobiles'][self.mobileListModel.data(
            index, Qt.DisplayRole)]
        self.lineEditMobileName.setText(mobile.get('Name'))
        self.comboBoxMobileType.setCurrentIndex(
            self.comboBoxMobileType.findText(
                mobile.setdefault('type', 'BOX').upper()))
        if mobile['type'] == 'SHAPE':
            self.lineEditMobileShape.setText(str(mobile['shape']))
            self.lineEditMobileShape.setEnabled(True)
            self.doubleSpinBoxXOffset.setEnabled(True)
            self.doubleSpinBoxYOffset.setEnabled(True)
        else:
            self.lineEditMobileShape.setEnabled(False)
            self.doubleSpinBoxXOffset.setEnabled(False)
            self.doubleSpinBoxYOffset.setEnabled(False)
            self.lineEditMobileShape.clear()
        self.doubleSpinBoxMobileLength.setValue(mobile.get('length', 20.0))
        self.doubleSpinBoxMobileWidth.setValue(mobile.get('width', 5.0))
        self.checkBoxDefaultIcon.setChecked(mobile.get('defaultIcon', True))
        self.checkBoxDefIconFilled.setChecked(
            mobile.get('defaultIconFilled', False))
        self.doubleSpinBoxXOffset.setValue(mobile.get('offsetX', 0.0))
        self.doubleSpinBoxYOffset.setValue(mobile.get('offsetY', 0.0))
        self.spinBoxZValue.setValue(int(mobile.get('zValue', 100)))
        self.mColorButtonMobileColor.setColor(
            self.getColor(mobile.get('color', 'black')))
        self.mColorButtonMobileFillColor.setColor(
            self.getColor(mobile.get('fillColor', 'green')))
        self.spinBoxMobileTimeout.setValue(mobile.get('timeout', 3000) // 1000)
        self.spinBoxMobileNotification.setValue(mobile.get('nofixNotify', 0))
        self.checkBoxFadeOut.setChecked(mobile.get('fadeOut', False))
        self.spinBoxTrackLength.setValue(mobile.get('trackLength', 100))
        self.mColorButtonMobileTrackColor.setColor(
            self.getColor(mobile.get('trackColor', 'green')))
        self.checkBoxShowLabel.setChecked(mobile.get('showLabel', False))
        r = 0
        self.mobileProviderModel.removeRows(
            0, self.mobileProviderModel.rowCount())
        if 'provider' in mobile:
            for k, v in mobile['provider'].items():
                try:
                    prov = QStandardItem(k)
                    self.mobileProviderModel.setItem(r, 0, prov)
                    try:
                        val = QStandardItem(str(v['id']))
                    except TypeError:
                        val = QStandardItem(
                            str(v))  # for compatibility reasons
                    self.mobileProviderModel.setItem(r, 1, val)
                    s = ', '.join([self.PROVIDER_FLAGS[i] for i in v['flags']])
                    flags = QStandardItem(s)
                    flags.setToolTip(s)
                    self.mobileProviderModel.setItem(r, 2, flags)
                except (KeyError, TypeError, ValueError):
                    pass
                r += 1
        self.mMobileProviderTableView.resizeColumnToContents(2)

    @pyqtSlot(name='on_toolButtonRemoveMobile_clicked')
    def removeMobile(self):
        idx = self.mMobileListView.currentIndex()
        if idx.isValid():
            self.projectProperties['Mobiles'].pop(
                self.mobileListModel.data(idx, Qt.DisplayRole))
            self.mobileListModel.removeRows(idx.row(), 1)
            idx = self.mMobileListView.currentIndex()
            if idx.isValid():
                self.populateMobileWidgets(idx)

    @pyqtSlot(QModelIndex, name='on_mMobileProviderTableView_clicked')
    def pupulateMobileProviderWidgets(self, idx):
        if idx.isValid():
            try:
                self.comboBoxProviders.setCurrentText(
                    self.mobileProviderModel.item(idx.row(),
                                                  0).data(Qt.DisplayRole))
                self.lineEditProviderFilter.setText(
                    self.mobileProviderModel.item(idx.row(),
                                                  1).data(Qt.DisplayRole))
                flgs = self.mobileProviderModel.item(idx.row(),
                                                     2).data(Qt.DisplayRole)
                self.comboBoxProviderFlags.deselectAllOptions()
                if flgs:
                    self.comboBoxProviderFlags.setCheckedItems(
                        flgs.split(', '))
            except (AttributeError, TypeError):
                pass

    @pyqtSlot(name='on_toolButtonRefreshMobileProvider_clicked')
    def refreshMobileProvider(self):
        prov = self.comboBoxProviders.currentText()
        if prov == '':
            return
        fil = None
        if self.lineEditProviderFilter.text() != '':
            fil = self.lineEditProviderFilter.text()
        flags = ', '.join(self.comboBoxProviderFlags.checkedItems())
        items = self.mobileProviderModel.findItems(prov, Qt.MatchExactly, 0)
        if items:
            for item in items:
                self.mobileProviderModel.setItem(item.row(), 1,
                                                 QStandardItem(fil))
                self.mobileProviderModel.setItem(item.row(), 2,
                                                 QStandardItem(flags))
        else:
            self.mobileProviderModel.appendRow([
                QStandardItem(prov),
                QStandardItem(fil),
                QStandardItem(flags)
            ])

    @pyqtSlot(name='on_toolButtonRemoveMobileProvider_clicked')
    def removeMobileProvider(self):
        idx = self.mMobileProviderTableView.currentIndex()
        if idx.isValid():
            self.mobileProviderModel.removeRow(idx.row())

    @pyqtSlot(name='on_pushButtonApplyDataProvider_clicked')
    def applyDataProvider(self):
        index = self.mDataProviderListView.currentIndex()
        if index.isValid() and not self.lineEditProviderName.text() == '':
            provider = dict()
            provider['Name'] = self.lineEditProviderName.text()
            provider['DataDeviceType'] = self.comboBoxProviderType.currentText(
            )
            if provider['DataDeviceType'] in NETWORK_TYPES:
                provider['Host'] = self.lineEditProviderHostName.text()
                provider['Port'] = self.spinBoxProviderPort.value()
                provider['ReuseAddr'] = self.checkBoxReuseAddr.isChecked()
            elif provider['DataDeviceType'] == 'SERIAL':
                provider['SerialPort'] = self.comboBoxSerialPort.currentText()
                provider['Baudrate'] = int(self.comboBoxBaudRate.currentText())
                provider['Databits'] = self.comboBoxDatabits.currentIndex() + 5
                provider['Parity'] = self.comboBoxParity.currentIndex()
                provider['Stopbits'] = self.comboBoxStopbits.currentIndex() + 1
                provider['FlowControl'] = self.comboBoxFlow.currentIndex()
            provider['Parser'] = self.comboBoxParser.currentText()
            currName = self.providerListModel.data(index, Qt.DisplayRole)
            if not currName == provider['Name']:
                del self.projectProperties['Provider'][currName]
                self.providerListModel.setData(index, provider['Name'],
                                               Qt.DisplayRole)
            self.projectProperties['Provider'][provider['Name']] = provider

    @pyqtSlot(QModelIndex, name='on_mDataProviderListView_clicked')
    def editDataProvider(self, index):
        '''
        '''
        if index.isValid():
            self.populateDataProviderWidgets(index)

    def populateDataProviderWidgets(self, index):
        provider = self.projectProperties['Provider'][
            self.providerListModel.data(index, Qt.DisplayRole)]
        self.lineEditProviderName.setText(provider.get('Name'))
        self.comboBoxProviderType.setCurrentIndex(
            self.comboBoxProviderType.findText(
                provider.setdefault('DataDeviceType', 'UDP').upper()))
        if provider['DataDeviceType'] in NETWORK_TYPES:
            self.stackedWidgetDataDevice.setCurrentIndex(0)
            self.lineEditProviderHostName.setText(
                provider.setdefault('Host', '0.0.0.0'))
            self.spinBoxProviderPort.setValue(
                int(provider.setdefault('Port', 2000)))
            self.checkBoxReuseAddr.setChecked(
                provider.setdefault('ReuseAddr', False))
        elif provider[
                'DataDeviceType'] == 'SERIAL' and 'PyQt5.QtSerialPort' in sys.modules:
            self.stackedWidgetDataDevice.setCurrentIndex(1)
            self.comboBoxSerialPort.setCurrentText(
                provider.setdefault('SerialPort', ''))
            self.comboBoxBaudRate.setCurrentText(
                str(provider.setdefault('Baudrate', '9600')))
            self.comboBoxDatabits.setCurrentIndex(
                provider.setdefault('Databits', 8) - 5)
            self.comboBoxParity.setCurrentIndex(
                provider.setdefault('Parity', 0))
            self.comboBoxStopbits.setCurrentIndex(
                provider.setdefault('Stopbits', 1) - 1)
            self.comboBoxFlow.setCurrentIndex(
                provider.setdefault('FlowControl', 0))
        self.comboBoxParser.setCurrentIndex(
            self.comboBoxParser.findText(
                provider.setdefault('Parser', 'NONE').upper()))

    @pyqtSlot(name='on_toolButtonAddDataProvider_clicked')
    def addDataProvider(self):
        self.providerListModel.insertRow(self.providerListModel.rowCount())
        index = self.providerListModel.index(
            self.providerListModel.rowCount() - 1)
        self.lineEditProviderName.setText('NewDataProvider')
        self.providerListModel.setData(index, 'NewDataProvider',
                                       Qt.DisplayRole)
        self.mDataProviderListView.setCurrentIndex(index)
        self.applyDataProvider()

    @pyqtSlot(name='on_toolButtonRemoveDataProvider_clicked')
    def removeDataProvider(self):
        idx = self.mDataProviderListView.currentIndex()
        if idx.isValid():
            self.projectProperties['Provider'].pop(
                self.providerListModel.data(idx, Qt.DisplayRole))
            self.providerListModel.removeRows(idx.row(), 1)
            idx = self.mDataProviderListView.currentIndex()
            if idx.isValid():
                self.populateDataProviderWidgets(idx)

    @pyqtSlot(str, name='on_comboBoxProviderType_currentIndexChanged')
    def setProviderType(self, pType):
        if pType == 'UDP':
            self.checkBoxReuseAddr.show()
        else:
            self.checkBoxReuseAddr.hide()
        if pType == 'SERIAL':
            try:
                from PyQt5.QtSerialPort import QSerialPortInfo
                ports = QSerialPortInfo.availablePorts()
                cport = self.comboBoxSerialPort.currentText()
                self.comboBoxSerialPort.clear()
                for port in ports:
                    self.comboBoxSerialPort.addItem(port.portName())
                self.comboBoxSerialPort.setCurrentText(cport)
                self.stackedWidgetDataDevice.setCurrentIndex(1)
            except (ModuleNotFoundError, ImportError):
                self.comboBoxSerialPort.clear()
                self.stackedWidgetDataDevice.setCurrentIndex(0)
        else:
            self.stackedWidgetDataDevice.setCurrentIndex(0)

    @pyqtSlot(name='on_toolButtonSelectLogPath_clicked')
    def selectRecorderPath(self):
        path = QFileDialog.getExistingDirectory(
            self, self.tr('Select Recorder Path'),
            self.lineEditRecorderPath.text(),
            QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks)
        if path != '':
            self.lineEditRecorderPath.setText(path)

    @pyqtSlot(QPoint, name='on_lineEditMobileShape_customContextMenuRequested')
    def mobileShapeContextMenu(self, pos):
        menu = QMenu(self.lineEditMobileShape)
        vesselAction = menu.addAction(self.tr('Vessel'))
        rovAction = menu.addAction(self.tr('ROV'))
        auvAction = menu.addAction(self.tr('AUV'))
        arrowAction = menu.addAction(self.tr('Arrow'))
        selectedAction = menu.exec_(self.lineEditMobileShape.mapToGlobal(pos))
        if selectedAction == vesselAction:
            self.lineEditMobileShape.setText(
                u'((0, -0.5), (0.5, -0.3), (0.5, 0.5), (-0.5, 0.5), (-0.5, -0.3))'
            )
        elif selectedAction == rovAction:
            self.lineEditMobileShape.setText(
                u'((0.3, -0.5), (0.5, -0.3), (0.5, 0.5), (-0.5, 0.5), (-0.5, -0.3), (-0.3, -0.5))'
            )
        elif selectedAction == auvAction:
            self.lineEditMobileShape.setText(
                u'((0, -0.5), (0.4, -0.3), (0.5, -0.3), (0.5, -0.2), (0.4, -0.2), (0.4, 0.3), (0.5, 0.3), (0.5, 0.4), (0.4, 0.4), (0.0, 0.5), \
             (-0.4, 0.4), (-0.5, 0.4), (-0.5, 0.3), (-0.4, 0.3), (-0.4, -0.2), (-0.5, -0.2), (-0.5, -0.3), (-0.4, -0.3))'
            )
        elif selectedAction == arrowAction:
            self.lineEditMobileShape.setText(
                u'((0, -0.5), (0.5, 0.5), (0, 0), (-0.5, 0.5))')

    @pyqtSlot(name='on_buttonBox_helpRequested')
    def showHelp(self):
        """Display application help to the user."""
        help_file = os.path.join(
            os.path.split(os.path.dirname(__file__))[0], 'help', 'index.html')
        QDesktopServices.openUrl(QUrl.fromLocalFile(help_file))
class ModelSelectionDialog(uicls, basecls):
    """Dialog for model selection."""

    TABLE_LIMIT = 10
    NAME_COLUMN_IDX = 1

    def __init__(self, plugin_dock, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self.plugin_dock = plugin_dock
        self.communication = self.plugin_dock.communication
        self.current_user = self.plugin_dock.current_user
        self.threedi_api = self.plugin_dock.threedi_api
        self.organisations = self.plugin_dock.organisations
        self.threedi_models = None
        self.simulation_templates = None
        self.current_model = None
        self.current_model_cells = None
        self.current_model_breaches = None
        self.current_simulation_template = None
        self.cells_layer = None
        self.breaches_layer = None
        self.organisation = None
        self.model_is_loaded = False
        self.models_model = QStandardItemModel()
        self.models_tv.setModel(self.models_model)
        self.templates_model = QStandardItemModel()
        self.templates_tv.setModel(self.templates_model)
        self.pb_prev_page.clicked.connect(self.move_models_backward)
        self.pb_next_page.clicked.connect(self.move_models_forward)
        self.page_sbox.valueChanged.connect(self.fetch_3di_models)
        self.pb_load.clicked.connect(self.load_model)
        self.pb_cancel_load.clicked.connect(self.cancel_load_model)
        self.search_le.returnPressed.connect(self.search_model)
        self.models_tv.selectionModel().selectionChanged.connect(
            self.refresh_templates_list)
        self.templates_tv.selectionModel().selectionChanged.connect(
            self.toggle_load_model)
        self.populate_organisations()
        self.fetch_3di_models()

    def refresh_templates_list(self):
        """Refresh simulation templates list if any model is selected."""
        selection_model = self.models_tv.selectionModel()
        self.templates_model.clear()
        self.templates_page_sbox.setMaximum(1)
        self.templates_page_sbox.setSuffix(" / 1")
        if selection_model.hasSelection():
            self.fetch_simulation_templates()
            if self.templates_model.rowCount() > 0:
                row_idx = self.templates_model.index(0, 0)
                self.templates_tv.selectionModel().setCurrentIndex(
                    row_idx, QItemSelectionModel.ClearAndSelect)
        self.toggle_load_model()

    def toggle_load_model(self):
        """Toggle load button if any model is selected."""
        selection_model = self.templates_tv.selectionModel()
        if selection_model.hasSelection():
            self.pb_load.setEnabled(True)
        else:
            self.pb_load.setDisabled(True)

    def move_models_backward(self):
        """Moving to the models previous results page."""
        self.page_sbox.setValue(self.page_sbox.value() - 1)

    def move_models_forward(self):
        """Moving to the models next results page."""
        self.page_sbox.setValue(self.page_sbox.value() + 1)

    def move_templates_backward(self):
        """Moving to the templates previous results page."""
        self.templates_page_sbox.setValue(self.page_sbox.value() - 1)

    def move_templates_forward(self):
        """Moving to the templates next results page."""
        self.templates_page_sbox.setValue(self.page_sbox.value() + 1)

    def populate_organisations(self):
        """Populating organisations list inside combo box."""
        for org in self.organisations.values():
            self.organisations_box.addItem(org.name, org)

    def fetch_3di_models(self):
        """Fetching 3Di models list."""
        try:
            tc = ThreediCalls(self.threedi_api)
            offset = (self.page_sbox.value() - 1) * self.TABLE_LIMIT
            text = self.search_le.text()
            threedi_models, models_count = tc.fetch_3di_models_with_count(
                limit=self.TABLE_LIMIT, offset=offset, name_contains=text)
            pages_nr = ceil(models_count / self.TABLE_LIMIT) or 1
            self.page_sbox.setMaximum(pages_nr)
            self.page_sbox.setSuffix(f" / {pages_nr}")
            self.models_model.clear()
            header = [
                "ID", "Model", "Schematisation", "Revision", "Last updated",
                "Updated by"
            ]
            self.models_model.setHorizontalHeaderLabels(header)
            for sim_model in sorted(threedi_models,
                                    key=attrgetter("revision_commit_date"),
                                    reverse=True):
                id_item = QStandardItem(str(sim_model.id))
                name_item = QStandardItem(sim_model.name)
                name_item.setData(sim_model, role=Qt.UserRole)
                schema_item = QStandardItem(sim_model.schematisation_name)
                rev_item = QStandardItem(sim_model.revision_number)
                last_updated_day = sim_model.revision_commit_date.split("T")[0]
                lu_datetime = QDateTime.fromString(last_updated_day,
                                                   "yyyy-MM-dd")
                lu_item = QStandardItem(lu_datetime.toString("dd-MMMM-yyyy"))
                ub_item = QStandardItem(sim_model.user)
                self.models_model.appendRow([
                    id_item, name_item, schema_item, rev_item, lu_item, ub_item
                ])
            self.threedi_models = threedi_models
        except ApiException as e:
            self.close()
            error_msg = extract_error_message(e)
            self.communication.show_error(error_msg)
        except Exception as e:
            self.close()
            error_msg = f"Error: {e}"
            self.communication.show_error(error_msg)

    def fetch_simulation_templates(self):
        """Fetching simulation templates list."""
        try:
            tc = ThreediCalls(self.threedi_api)
            offset = (self.templates_page_sbox.value() - 1) * self.TABLE_LIMIT
            selected_model = self.get_selected_model()
            model_pk = selected_model.id
            templates, templates_count = tc.fetch_simulation_templates_with_count(
                model_pk, limit=self.TABLE_LIMIT, offset=offset)
            pages_nr = ceil(templates_count / self.TABLE_LIMIT) or 1
            self.templates_page_sbox.setMaximum(pages_nr)
            self.templates_page_sbox.setSuffix(f" / {pages_nr}")
            self.templates_model.clear()
            header = ["Template ID", "Template name", "Creation date"]
            self.templates_model.setHorizontalHeaderLabels(header)
            for template in sorted(templates,
                                   key=attrgetter("id"),
                                   reverse=True):
                id_item = QStandardItem(str(template.id))
                name_item = QStandardItem(template.name)
                name_item.setData(template, role=Qt.UserRole)
                creation_date = template.created.strftime(
                    "%d-%m-%Y") if template.created else ""
                creation_date_item = QStandardItem(creation_date)
                self.templates_model.appendRow(
                    [id_item, name_item, creation_date_item])
            for i in range(len(header)):
                self.templates_tv.resizeColumnToContents(i)
            self.simulation_templates = templates
        except ApiException as e:
            error_msg = extract_error_message(e)
            self.communication.show_error(error_msg)
        except Exception as e:
            error_msg = f"Error: {e}"
            self.communication.show_error(error_msg)

    def search_model(self):
        """Method used for searching models with text typed withing search bar."""
        self.page_sbox.valueChanged.disconnect(self.fetch_3di_models)
        self.page_sbox.setValue(1)
        self.page_sbox.valueChanged.connect(self.fetch_3di_models)
        self.fetch_3di_models()

    def load_cached_layers(self):
        """Loading cached layers into the map canvas."""
        if self.current_model_cells is not None:
            self.cells_layer = QgsVectorLayer(self.current_model_cells,
                                              "cells", "ogr")
            set_named_style(self.cells_layer, "cells.qml")
            QgsProject.instance().addMapLayer(self.cells_layer, False)
            QgsProject.instance().layerTreeRoot().insertLayer(
                0, self.cells_layer)
            self.cells_layer.setFlags(QgsMapLayer.Searchable
                                      | QgsMapLayer.Identifiable)
        if self.current_model_breaches is not None:
            self.breaches_layer = QgsVectorLayer(self.current_model_breaches,
                                                 "breaches", "ogr")
            set_named_style(self.breaches_layer, "breaches.qml")
            QgsProject.instance().addMapLayer(self.breaches_layer, False)
            QgsProject.instance().layerTreeRoot().insertLayer(
                0, self.breaches_layer)
            self.breaches_layer.setFlags(QgsMapLayer.Searchable
                                         | QgsMapLayer.Identifiable)
        if self.current_model_cells is not None:
            self.plugin_dock.iface.setActiveLayer(self.cells_layer)
            self.plugin_dock.iface.zoomToActiveLayer()

    def unload_cached_layers(self):
        """Removing model related vector layers from map canvas."""
        try:
            if self.breaches_layer is not None:
                QgsProject.instance().removeMapLayer(self.breaches_layer)
                self.breaches_layer = None
            if self.cells_layer is not None:
                QgsProject.instance().removeMapLayer(self.cells_layer)
                self.cells_layer = None
            self.plugin_dock.iface.mapCanvas().refresh()
        except AttributeError:
            pass

    def load_model(self):
        """Loading selected model."""
        index = self.models_tv.currentIndex()
        if index.isValid():
            self.organisation = self.organisations_box.currentData()
            self.unload_cached_layers()
            current_row = index.row()
            name_item = self.models_model.item(current_row,
                                               self.NAME_COLUMN_IDX)
            self.current_model = name_item.data(Qt.UserRole)
            self.current_model_cells = self.get_cached_data("cells")
            self.current_model_breaches = self.get_cached_data("breaches")
            self.current_simulation_template = self.get_selected_template()
            self.load_cached_layers()
            self.model_is_loaded = True
        self.close()

    def cancel_load_model(self):
        """Cancel loading model."""
        self.current_simulation_template = None
        self.model_is_loaded = False
        self.close()

    def get_selected_model(self):
        """Get currently selected model."""
        index = self.models_tv.currentIndex()
        if index.isValid():
            current_row = index.row()
            name_item = self.models_model.item(current_row,
                                               self.NAME_COLUMN_IDX)
            selected_model = name_item.data(Qt.UserRole)
        else:
            selected_model = None
        return selected_model

    def get_selected_template(self):
        """Get currently selected simulation template."""
        index = self.templates_tv.currentIndex()
        if index.isValid():
            current_row = index.row()
            name_item = self.templates_model.item(current_row,
                                                  self.NAME_COLUMN_IDX)
            selected_template = name_item.data(Qt.UserRole)
        else:
            selected_template = None
        return selected_template

    def get_cached_data(self, geojson_name):
        """Get model data that should be cached."""
        cached_file_path = None
        try:
            tc = ThreediCalls(self.threedi_api)
            model_id = self.current_model.id
            if geojson_name == "breaches":
                download = tc.fetch_3di_model_geojson_breaches_download(
                    model_id)
            elif geojson_name == "cells":
                download = tc.fetch_3di_model_geojson_cells_download(model_id)
            else:
                return cached_file_path
            filename = f"{geojson_name}_{model_id}_{download.etag}.json"
            file_path = os.path.join(CACHE_PATH, filename)
            if not file_cached(file_path):
                get_download_file(download, file_path)
            cached_file_path = file_path
            self.communication.bar_info(f"Model {geojson_name} cached.")
        except ApiException as e:
            error_msg = extract_error_message(e)
            if "geojson file not found" in error_msg:
                pass
            else:
                self.communication.bar_error(error_msg)
        except Exception as e:
            logger.exception("Error when getting to-be-cached data")
            error_msg = f"Error: {e}"
            self.communication.bar_error(error_msg)
        return cached_file_path