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)
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)
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)
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)
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)
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()
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
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