def show_message_associate_geometry_creation(self, message): msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setText(message) msg.setWindowTitle( QCoreApplication.translate("WizardTranslations", "Continue editing?")) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.button(QMessageBox.No).setText( QCoreApplication.translate("WizardTranslations", "No, close the wizard")) reply = msg.exec_() if reply == QMessageBox.No: # stop edition in close_wizard crash qgis if self._layers[self.EDITING_LAYER_NAME].isEditable(): self._layers[self.EDITING_LAYER_NAME].rollBack() message = QCoreApplication.translate( "WizardTranslations", "'{}' tool has been closed.").format(self.WIZARD_TOOL_NAME) self.close_wizard(message) else: # Continue creating geometry pass
def map_tool_changed(self, new_tool, old_tool): self.canvas.mapToolSet.disconnect(self.map_tool_changed) msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setText( QCoreApplication.translate( "WizardTranslations", "Do you really want to change the map tool?")) msg.setWindowTitle( QCoreApplication.translate("WizardTranslations", "CHANGING MAP TOOL?")) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.button(QMessageBox.Yes).setText( QCoreApplication.translate("WizardTranslations", "Yes, and close the wizard")) msg.button(QMessageBox.No).setText( QCoreApplication.translate("WizardTranslations", "No, continue editing")) reply = msg.exec_() if reply == QMessageBox.No: self.canvas.setMapTool(old_tool) self.canvas.mapToolSet.connect(self.map_tool_changed) else: message = QCoreApplication.translate( "WizardTranslations", "'{}' tool has been closed because the map tool change." ).format(self.WIZARD_TOOL_NAME) self.close_wizard(message)
def closeEvent(self, event): if self.isRecalculating or self.configurationHasChanged: return if self.unsavedChanges: msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(self.tr('Nicht gespeicherte Aenderungen')) msgBox.setText(self.tr('Moechten Sie die Ergebnisse speichern?')) msgBox.setStandardButtons(QMessageBox.Cancel | QMessageBox.No | QMessageBox.Yes) cancelBtn = msgBox.button(QMessageBox.Cancel) cancelBtn.setText(self.tr("Abbrechen")) noBtn = msgBox.button(QMessageBox.No) noBtn.setText(self.tr("Nein")) yesBtn = msgBox.button(QMessageBox.Yes) yesBtn.setText(self.tr("Ja")) msgBox.show() msgBox.exec() if msgBox.clickedButton() == yesBtn: self.onSave() self.drawTool.reset() elif msgBox.clickedButton() == cancelBtn: event.ignore() return elif msgBox.clickedButton() == noBtn: self.drawTool.reset() else: self.drawTool.reset() self.timer.stop()
def call_allocate_parcels_to_receiver_panel(self): # Make sure that all selected items are not yet allocated, otherwise, allow users to deallocate selected already_allocated = list() # [parcel_fid1, ...] for parcel_fid, parcel_number in self.__selected_items.items(): if parcel_fid in self._parcel_data(): if self._parcel_data()[parcel_fid][1]: # surveyor_name already_allocated.append(parcel_fid) if already_allocated: msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setText(QCoreApplication.translate("AllocateParcelsFieldDataCapturePanelWidget", "Some selected parcels are already allocated!\n\nWhat would you like to do with selected parcels that are already allocated?")) msg.setWindowTitle(QCoreApplication.translate("AllocateParcelsFieldDataCapturePanelWidget", "Warning")) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) msg.button(QMessageBox.Yes).setText( QCoreApplication.translate("AllocateParcelsFieldDataCapturePanelWidget", "Deselect them and continue")) msg.button(QMessageBox.No).setText( QCoreApplication.translate("AllocateParcelsFieldDataCapturePanelWidget", "Reallocate and continue")) reply = msg.exec_() if reply == QMessageBox.Yes: # Ignore # Remove selection of allocated parcels, reload table widget data and continue for allocated_parcel_id in already_allocated: if allocated_parcel_id in self._parcel_data(): items = self.tbl_parcels.findItems(self._parcel_data()[allocated_parcel_id][0], Qt.MatchExactly) if items: # Item is currently shown, so deselect it in GUI items[0].setSelected(False) # Deselect item in column 0 self.tbl_parcels.item(items[0].row(), self.STATUS_COL).setSelected(False) # Deselect item in column 1 else: # Item is not currently shown, deselected in internal selection dict if allocated_parcel_id in self.__selected_items: del self.__selected_items[allocated_parcel_id] self.fill_data() if not self.__selected_items: self.logger.warning_msg(__name__, QCoreApplication.translate("AllocateParcelsFieldDataCapturePanelWidget", "Ignoring selected parcels, there are none to be allocated! First select some!"), 10) return elif reply == QMessageBox.No: # Reallocate # Preserve the selected_items dict, but remove allocation before continuing if not self.discard_parcel_allocation(already_allocated): return else: # QMessageBox.Cancel return if self.__selected_items: self.allocate_parcels_to_receiver_panel_requested.emit(self.__selected_items) else: self.logger.warning_msg(__name__, QCoreApplication.translate("AllocateParcelsFieldDataCapturePanelWidget", "First select some parcels to be allocated."), 5)
def show_message_associate_geometry_creation(message) -> bool: # TODO parent in message box msg = QMessageBox() msg.setIcon(QMessageBox.Question) msg.setText(message) msg.setWindowTitle( QCoreApplication.translate("WizardTranslations", "Continue editing?")) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.button(QMessageBox.No).setText( QCoreApplication.translate("WizardTranslations", "No, close the wizard")) reply = msg.exec_() return reply != QMessageBox.No
def show_message_clean_layers_panel(self, message): msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setText(message) msg.setWindowTitle(QCoreApplication.translate("ChangeDetectionSettingsDialog", "Remove layers?")) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) msg.button(QMessageBox.Yes).setText(QCoreApplication.translate("ChangeDetectionSettingsDialog", "Yes, remove layers")) msg.button(QMessageBox.No).setText(QCoreApplication.translate("ChangeDetectionSettingsDialog", "No, don't remove")) reply = msg.exec_() if reply == QMessageBox.Yes: QgsProject.instance().layerTreeRoot().removeAllChildren() self.close_dialog(QDialog.Accepted) elif reply == QMessageBox.No: self.close_dialog(QDialog.Accepted) elif reply == QMessageBox.Cancel: pass # Continue config db connections
def onRemoveParameterSet(self): currParamset = self.fieldParamSet.currentText() # No action if there is no parameter set specified if currParamset == '': return # Standard set cannot be deleted if currParamset == self.paramHandler.defaultSet: QMessageBox.critical(self, self.tr('Parameterset loeschen'), self.tr('Standardparameterset kann nicht geloescht werden.'), QMessageBox.Ok) return # Ask before removing msgBox = QMessageBox() msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(self.tr('Parameterset loeschen')) msgBox.setText(self.tr('Moechten Sie das Parameterset wirklich loeschen?')) msgBox.setStandardButtons(QMessageBox.No | QMessageBox.Yes) noBtn = msgBox.button(QMessageBox.No) noBtn.setText(self.tr("Nein")) yesBtn = msgBox.button(QMessageBox.Yes) yesBtn.setText(self.tr("Ja")) msgBox.show() msgBox.exec() if msgBox.clickedButton() == yesBtn: success = self.paramHandler.removeParameterSet(currParamset) if not success: QMessageBox.critical(self, self.tr('Parameterset loeschen'), self.tr('Ein Fehler ist aufgetreten. Parameterset kann nicht geloescht werden.'), QMessageBox.Ok) else: # Set default set self.paramHandler.setParameterSet(self.paramHandler.defaultSet) # Update drop down list to remove set self.fillParametersetList() # Fill in values of default set self.fillInValues() # Deactivate / Activate status of field HMKran depending on # point type of start point self.updateHMKran(self.projectHandler.A_type)
def _map_tool_changed(self, args: MapToolChangedArgs): # TODO parent was removed msg = QMessageBox() msg.setIcon(QMessageBox.Question) msg.setText( QCoreApplication.translate( "WizardTranslations", "Do you really want to change the map tool?")) msg.setWindowTitle( QCoreApplication.translate("WizardTranslations", "CHANGING MAP TOOL?")) msg.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msg.button(QMessageBox.Yes).setText( QCoreApplication.translate("WizardTranslations", "Yes, and close the wizard")) msg.button(QMessageBox.No).setText( QCoreApplication.translate("WizardTranslations", "No, continue editing")) reply = msg.exec_() if reply == QMessageBox.Yes: args.change_map_tool = True self._wizard_messages.show_map_tool_changed_msg() self.close_wizard()
def accepted(self): """ We start checking the document repository configuration and only allow to continue if we have a valid repo or if the repo won't be used. Then, check if connection to DB/schema is valid, if not, block the dialog. If valid, check it complies with LADM. If not, block the dialog. If it complies, we have two options: To emit db_connection changed or not. Finally, we store options in QSettings. """ res_doc_repo, msg_doc_repo = self.check_document_repository_before_saving_settings( ) if not res_doc_repo: self.show_message(msg_doc_repo, Qgis.Warning, 0) return # Do not close the dialog ladm_col_schema = False db = self._get_db_connector_from_gui() test_level = EnumTestLevel.DB_SCHEMA if self._action_type == EnumDbActionType.SCHEMA_IMPORT: # Limit the validation (used in GeoPackage) test_level |= EnumTestLevel.SCHEMA_IMPORT res, code, msg = db.test_connection( test_level ) # No need to pass required_models, we don't test that much if res: if self._action_type != EnumDbActionType.SCHEMA_IMPORT: # Only check LADM-schema if we are not in an SCHEMA IMPORT. # We know in an SCHEMA IMPORT, at this point the schema is still not LADM. ladm_col_schema, code, msg = db.test_connection( EnumTestLevel.LADM, required_models=self._required_models) if not ladm_col_schema and self._action_type != EnumDbActionType.SCHEMA_IMPORT: if self._blocking_mode: self.show_message(msg, Qgis.Warning) return # Do not close the dialog else: if self._blocking_mode: self.show_message(msg, Qgis.Warning) return # Do not close the dialog # Connection is valid and complies with LADM current_db_engine = self.cbo_db_engine.currentData() if self._lst_panel[current_db_engine].state_changed( ) or self.init_db_engine != current_db_engine: # Emit db_connection_changed if self._db is not None: self._db.close_connection() self._db = db # Update db connect with new db conn self.conn_manager.set_db_connector_for_source( self._db, self.db_source) # Emmit signal when db source changes self.db_connection_changed.emit(self._db, ladm_col_schema, self.db_source) self.logger.debug( __name__, "Settings dialog emitted a db_connection_changed.") if not ladm_col_schema and self._action_type == EnumDbActionType.CONFIG: msg_box = QMessageBox(self) msg_box.setIcon(QMessageBox.Question) msg_box.setText( QCoreApplication.translate( "SettingsDialog", "No LADM-COL DB has been configured! You'll continue with limited functionality until you configure a LADM-COL DB.\n\nDo you want to go to 'Create LADM-COL structure' dialog?" )) msg_box.setWindowTitle( QCoreApplication.translate("SettingsDialog", "Important")) msg_box.setStandardButtons(QMessageBox.Yes | QMessageBox.Ignore) msg_box.setDefaultButton(QMessageBox.Ignore) msg_box.button(QMessageBox.Yes).setText( QCoreApplication.translate("SettingsDialog", "Yes, go to create structure")) msg_box.button(QMessageBox.Ignore).setText( QCoreApplication.translate("SettingsDialog", "No, I'll do it later")) reply = msg_box.exec_() if reply == QMessageBox.Yes: self._open_dlg_import_schema = True # We will open it when we've closed this Settings dialog # If active role is changed (a check and confirmation may be needed), refresh the GUI # Note: Better to leave this check as the last one in the accepted() method. selected_role = self.get_selected_role() if self.roles.get_active_role() != selected_role: b_change_role = True if STSession().is_user_logged(): reply = QMessageBox.question( self.parent, QCoreApplication.translate("SettingsDialog", "Warning"), QCoreApplication.translate( "SettingsDialog", "You have a ST connection opened and you want to change your role.\nIf you confirm that you want to change your role, you'll be logged out from the ST.\n\nDo you really want to change your role?" ), QMessageBox.Yes | QMessageBox.Cancel, QMessageBox.Cancel) if reply == QMessageBox.Yes: STSession().logout() elif reply == QMessageBox.Cancel: # No need to switch back selected role, the Settings Dialog gets it from role registry b_change_role = False if b_change_role: self.logger.info( __name__, "The active role has changed from '{}' to '{}'.".format( self.roles.get_active_role(), selected_role)) self.roles.set_active_role( selected_role ) # Emits signal that refreshed the plugin for this role self.save_settings(db) QDialog.accept(self) self.close() if self._open_dlg_import_schema: # After Settings dialog has been closed, we could call Import Schema depending on user's answer above self.open_dlg_import_schema.emit(Context()) self.logger.debug( __name__, "Settings dialog emitted a show Import Schema dialog.")
def search(self): try: # Current service service = self.tab.tabText(self.tab.currentIndex()) # Params params = {'geometry': self.polygonInput.text()} # Set auth and add params according to service if service == 'BaseMap': # ! Auth self.bmSetAuth() # Set request attributes url = 'https://view.geoapi-airbusds.com/api/v1/images' auth = self.bmAuth headers = None # Update params params.update({ 'size': self.maxResultsInput.value(), 'insertdtstart': '1970-01-01T00:00:00', 'insertdtend': self.now() }) # Dates if self.bmFromCheck.isChecked(): params['insertdtstart'] = self.bmFromInput.dateTime( ).toString(Qt.ISODate) if self.bmToCheck.isChecked(): params['insertdtend'] = self.bmToInput.dateTime().toString( Qt.ISODate) else: # ! Auth self.dtSetAuth() url = 'https://search.oneatlas.geoapi-airbusds.com/api/v1/opensearch' auth = None headers = self.dtHeaders # Constellations (at least one) constellations = [] if self.dtSpotCheck.isChecked(): constellations.append('SPOT') if self.dtPleiadesCheck.isChecked(): constellations.append('PHR') # Dates # MAYBE remove hours from dates dateFrom, dateTo = '1970-01-01T00:00:00', self.now() if self.dtFromCheck.isChecked(): dateFrom = self.dtFromInput.dateTime().toString(Qt.ISODate) if self.dtToCheck.isChecked(): dateTo = self.dtToInput.dateTime().toString(Qt.ISODate) # Angles angleMin, angleMax = 0, 30 if self.dtAngleMinCheck.isChecked(): angleMin = self.dtAngleMinInput.value() if self.dtAngleMaxCheck.isChecked(): angleMax = self.dtAngleMaxInput.value() # Covers (directlly update params) if self.dtCloudCheck.isChecked(): params['cloudCover'] = f'[0,{self.dtCloudInput.value()}]' if self.dtSnowCheck.isChecked(): params['snowCover'] = f'[0,{self.dtSnowInput.value()}]' # Workspaces (at leat one) workspaces = [] if self.dtPublicCheck.isChecked(): workspaces.append('0e33eb50-3404-48ad-b835-b0b4b72a5625') if self.dtPrivateCheck.isChecked(): workspaces.append(self.dtWorkspaceId) # Update all params with right format params.update({ 'itemsPerPage': self.maxResultsInput.value(), 'constellation': ','.join(constellations), 'acquisitionDate': f'[{dateFrom},{dateTo}]', 'incidenceAngle': f'[{angleMin},{angleMax}]', 'workspace': ','.join(workspaces) }) # Finally do the api call t = datetime.datetime.now() print(f'START {service} search') r = self.session.get(url, auth=auth, headers=headers, params=params) rSearch = r.json() # Exception request error if r.status_code != 200: self.error( f'{service} search error {r.status_code}\n{rSearch["message"]}' ) return # Create the search result layer with fields according to current service layer = QgsVectorLayer( f'Polygon?crs=epsg:4326&index=yes&{FIELDS[service]}', providerLib='memory', baseName=f'{service} search results') # Extract features features = [] self.errorFeatures = [] for rFeature in rSearch['features']: # Add a feature of the bbox on the new layer feature = QgsFeature(layer.fields()) # Try to get each attributes feature['service'] = service feature['constellation'] = self.getPropertie( rFeature, 'constellation') feature['incidenceAngle'] = self.getPropertie( rFeature, 'incidenceAngle') feature['cloudCover'] = self.getPropertie( rFeature, 'cloudCover') if service == 'BaseMap': feature['id'] = rFeature['id'] feature['insertionDate'] = self.getPropertie( rFeature, 'insertionDate') feature['wmts'] = self.getPropertie(rFeature, 'wmts') # Bbox fBbox = rFeature['properties']['bbox'] rectangle = QgsRectangle(fBbox[0], fBbox[1], fBbox[2], fBbox[3]) else: feature['id'] = self.getPropertie(rFeature, 'id') feature['acquisitionDate'] = self.getPropertie( rFeature, 'acquisitionDate') feature['snowCover'] = self.getPropertie( rFeature, 'snowCover') try: for json in rFeature['_links']['imagesWmts']: feature[f'wmts_{json["name"]}'] = json['href'] for json in rFeature['_links']['imagesWcs']: if 'buffer' in rFeature['rights']: feature[f'wcs_{json["name"]}'] = json['href'] else: feature[f'wcs_{json["name"]}'] = None except Exception as e: print( f'ERROR * eF = qgis.utils.plugins["OneAtlas"].mySearch.errorFeatures[{len(self.errorFeatures)}]' ) print(str(e)) self.errorFeatures.append(rFeature) continue # Bbox coordinates = rFeature['geometry']['coordinates'][0] rectangle = QgsRectangle(coordinates[0][0], coordinates[0][1], coordinates[2][0], coordinates[2][1]) # Add geometry from rectangle feature.setGeometry( QgsGeometry.fromWkt(rectangle.asWktPolygon())) # Add feature to list features.append(feature) # Total if service == 'BaseMap': # Note : rSearch['totalResults'] is maybe the number of total element in bbox ? # and numberOfElements is the true total result total = rSearch['numberOfElements'] color = QColor.fromRgb(0, 250, 0) else: total = rSearch['totalResults'] color = QColor.fromRgb(0, 250, 250) if len(self.errorFeatures) > 0: total -= len(self.errorFeatures) print(f'* {len(self.errorFeatures)} error feature') # Notification for number of total results msgBox = QMessageBox() msgBox.setWindowTitle(WINDOW_TITLE) msgBox.setText(f'There are {total} results') if total > len(features): msgBox.setIcon(QMessageBox.Warning) msgBox.setInformativeText( f'The maximum is configured to {self.maxResultsInput.value()}\nPlease refine your criteria or your AOI' ) msgBox.setStandardButtons(QMessageBox.Retry | QMessageBox.Ignore) msgBox.setDefaultButton(QMessageBox.Retry) else: msgBox.setIcon(QMessageBox.Information) msgBox.setStandardButtons(QMessageBox.Retry | QMessageBox.Ok) msgBox.setDefaultButton(QMessageBox.Ok) msgBox.button(QMessageBox.Retry).setText('Refine') msgBox.button(QMessageBox.Retry).setIcon( QIcon(os.path.dirname(__file__) + f'/search.png')) reply = msgBox.exec_() if reply == QMessageBox.Retry or len(features) == 0: return # Add result feature to the new layer (res, outFeats) = layer.dataProvider().addFeatures(features) # Change layer syle programmatically # Note : if we styling before save and add layer, we avoid to update legend style # => self.iface.layerTreeView().refreshLayerSymbology(vlayer.id()) symbol = layer.renderer().symbol() symbol.setOpacity(0.2) symbol.setColor(color) QgsProject.instance().addMapLayer(layer) # And refresh view layer.triggerRepaint() self.close() except: return