def progress_bar(self): try: return self._progress_bar except AttributeError: message_bar_item = QgsMessageBarItem("") label = QLabel(self.tr("Computing cartogram")) label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) message_bar_item.layout().addWidget(label) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progress_bar.setMaximum(100) message_bar_item.layout().addWidget(progress_bar) cancel_button = QPushButton(self.tr("Cancel")) cancel_button.clicked.connect(self.cancel_task) message_bar_item.layout().addWidget(cancel_button) self.iface.messageBar().pushWidget(message_bar_item) self._progress_bar_message_bar_item = message_bar_item self._progress_bar = progress_bar self._cancel_button = cancel_button return self._progress_bar
class MessageBarProgress(QgsProcessingFeedback): def __init__(self, algname=None): QgsProcessingFeedback.__init__(self) self.msg = [] self.progressMessageBar = \ iface.messageBar().createMessage(self.tr('Executing algorithm <i>{0}</i>'.format(algname if algname else ''))) self.progress = QProgressBar() self.progressChanged.connect(self.progress.setValue) self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) def reportError(self, msg, fatalError=False): self.msg.append(msg) def close(self): if self.msg: dlg = MessageDialog() dlg.setTitle( QCoreApplication.translate('MessageBarProgress', 'Problem executing algorithm')) dlg.setMessage("<br>".join(self.msg)) dlg.exec_() iface.messageBar().clearWidgets() def tr(self, string, context=''): if context == '': context = 'MessageBarProgress' return QCoreApplication.translate(context, string)
def process_meta_file(self): meta_file = self.select_meta_file() if meta_file: # process peaks processed_peaks = get_peaks(meta_file) self.peaks.append(processed_peaks) self.populate_lists() self.iface.messageBar().pushSuccess( "Success", "Meta file processed successfully!") # process hydrographs progressMessageBar = self.iface.messageBar().createMessage( "Processing hydrographs...") progress = QProgressBar() progress.setMaximum( len(self.peaks[0]["storm"].sort_values().unique())) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) processed_hydrographs = get_hydrographs(meta_file, progress=progress) self.hydrographs.append(processed_hydrographs) self.iface.messageBar().clearWidgets() self.iface.messageBar().pushSuccess( "Success", "Hydrographs processed successfully!") model = DataFrameModel(self.peaks[0]) self.dockwidget.dataTableView.setModel(model)
class MessageBarProgress(QgsProcessingFeedback): def __init__(self, algname=None): QgsProcessingFeedback.__init__(self) self.msg = [] self.progressMessageBar = \ iface.messageBar().createMessage(self.tr('Executing algorithm <i>{0}</i>'.format(algname if algname else ''))) self.progress = QProgressBar() self.progressChanged.connect(self.progress.setValue) self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) self.message_bar_item = iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) def reportError(self, msg, fatalError=False): self.msg.append(msg) def close(self): if self.msg: dlg = MessageDialog() dlg.setTitle(QCoreApplication.translate('MessageBarProgress', 'Problem executing algorithm')) dlg.setMessage("<br>".join(self.msg)) dlg.exec_() iface.messageBar().popWidget(self.message_bar_item) def tr(self, string, context=''): if context == '': context = 'MessageBarProgress' return QCoreApplication.translate(context, string)
def publish(self): progressMessageBar = self.bar.createMessage( self.tr("Publishing layers")) progress = QProgressBar() progress.setMaximum(100) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.bar.pushWidget(progressMessageBar, Qgis.Info) QCoreApplication.processEvents() task = self.getPublishTask(self.parent) task.progressChanged.connect(progress.setValue) ret = execute(task.run) self.bar.clearWidgets() task.finished(ret) if task.exception is not None: self.bar.clearWidgets() self.bar.pushMessage(self.tr("Error while publishing"), self.tr("See QGIS log for details"), level=Qgis.Warning, duration=5) QgsMessageLog.logMessage(task.exception, 'GeoCat Bridge', level=Qgis.Critical) self.updateLayersPublicationStatus(task.geodataServer is not None, task.metadataServer is not None)
def create_progress_bar(self, message, size): progress_message_bar = self.iface.messageBar().createMessage(message) progress_b = QProgressBar() progress_b.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progress_message_bar.layout().addWidget(progress_b) self.iface.messageBar().pushWidget(progress_message_bar) progress_b.setMaximum(size) return progress_b
def create_progress_bar(message): progress_widget = QProgressBar() progress_widget.setMaximum(100) progress_widget.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) message_bar = iface.messageBar().createMessage(message) message_bar.setWidget(progress_widget) iface.messageBar().pushMessage('') iface.messageBar().pushWidget(message_bar) return progress_widget
def startProgressBar(self, iniMsg): #iniMsg ="Disabling Snapping to Layer: " #iface=self.iface progressMessageBar = iface.messageBar().createMessage( self.SETTINGS, iniMsg) progress = QProgressBar() progress.setMaximum(100) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) #pass the progress bar to the message Bar progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar) return progress, progressMessageBar
def OnGenerate(self): """Reads the directory and other input values. Loops the TIF files and runs the conversion.""" input_dir = self.textInput.toPlainText() output_dir = self.textOutput.toPlainText() if input_dir == output_dir: iface.messageBar().pushMessage( self.tr("Error"), self.tr("The input and output directories must differ"), level=Qgis.Critical) return directory = os.fsencode(input_dir) # Sets the color values r_color = self.mColorButton.color().red() g_color = self.mColorButton.color().green() b_color = self.mColorButton.color().blue() # Sets the progress bar item to show progress in the loop progressMessageBar = iface.messageBar().createMessage("Converting...") progress = QProgressBar() progress.setMaximum(len(os.listdir(directory))) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) i = 0 # Loop the directory for file in os.listdir(directory): progress.setValue(i + 1) filename = os.fsdecode(file) if filename.endswith(".tif"): src_filename = os.path.join(input_dir, filename) dst_filename = os.path.join(output_dir, filename) try: self.addAlpha(src_filename, dst_filename, r_color, g_color, b_color) except: iface.messageBar().pushMessage( self.tr("Error"), self. tr("The conversion did not work. Please check input and out directories." ), level=Qgis.Critical) return # If succeeded the message appears iface.messageBar().clearWidgets() iface.messageBar().pushMessage( self.tr("Success"), self.tr("Output layers saved to {}").format(output_dir), level=Qgis.Success)
def createProgressbar(self, loopnumber): """ Create a progress bar when iterating over features """ progressMessageBar = self.messageBar.createMessage( str(u"Chargement des données...")) progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(loopnumber) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.messageBar.pushWidget(progressMessageBar) return progress
def initField(self): # get current layer layer = self.iface.mapCanvas().currentLayer( ) # nF = layer.selectedFeatureCount() #print nF #self.ui.txX.setText("Yes, you can!") layer.setLabelsEnabled(True) vpr = layer.dataProvider() # Get the field of current comobox cbField_origin = str( self.ui.cbField.currentText()) #print cbField_origin print(cbField_origin) # start to edit attributes of fields layer.startEditing() allFeatures = layer.getFeatures() count = layer.featureCount() infoString = str( "<font color='red'> Creating and initializing the label fields......Wait this completed please......</font>" ) progressMessageBar = self.iface.messageBar().createMessage(infoString) progress = QProgressBar() progress.setMaximum(count) progress.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) # loop for initialization n = -1 for feature in allFeatures: feature[share.field_list[0][0]] = feature[cbField_origin] feature[share.field_list[1][0]] = 999999999999999999.0 feature[share.field_list[2][0]] = 999999999999999999.0 feature[share.field_list[3][0]] = 0.0 feature[share.field_list[4][0]] = 1 feature[share.field_list[5][0]] = "Center" feature[share.field_list[6][0]] = "Half" n = n + 1 layer.updateFeature(feature) progress.setValue(n + 1) self.iface.messageBar().clearWidgets() # updateExtents and refresh mapCanvas #layer.updateExtents() layer.commitChanges() # make sure that fields are initialize correctly self.iface.mapCanvas().refresh()
def __init__(self, parent, msg = ''): ''' progressBar class instatiation method. It creates a QgsMessageBar with provided msg and a working QProgressBar :param parent: :param msg: string ''' self.iface = parent.iface widget = self.iface.messageBar().createMessage("GooGIS plugin:",msg) progressBar = QProgressBar() progressBar.setRange(0,0) #(1,steps) progressBar.setValue(0) progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) widget.layout().addWidget(progressBar) QApplication.processEvents() self.iface.messageBar().pushWidget(widget, Qgis.Info, 50) QApplication.processEvents()
class MessageBarProgress(object): def __init__(self, algname=None): self.msg = [] self.progressMessageBar = \ iface.messageBar().createMessage(self.tr('Executing algorithm <i>{0}</i>'.format(algname if algname else ''))) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, iface.messageBar().INFO) def error(self, msg): self.msg.append(msg) def setText(self, text): pass def setPercentage(self, i): self.progress.setValue(i) def setInfo(self, _): pass def setCommand(self, _): pass def setDebugInfo(self, _): pass def setConsoleInfo(self, _): pass def close(self): if self.msg: dlg = MessageDialog() dlg.setTitle( QCoreApplication.translate('MessageBarProgress', 'Problem executing algorithm')) dlg.setMessage("<br>".join(self.msg)) dlg.exec_() iface.messageBar().clearWidgets() def tr(self, string, context=''): if context == '': context = 'MessageBarProgress' return QCoreApplication.translate(context, string)
class MessageBarProgress(object): def __init__(self, algname=None): self.msg = [] self.progressMessageBar = \ iface.messageBar().createMessage(self.tr('Executing algorithm <i>{0}</i>'.format(algname if algname else ''))) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, iface.messageBar().INFO) def error(self, msg): self.msg.append(msg) def setText(self, text): pass def setPercentage(self, i): self.progress.setValue(i) def setInfo(self, _): pass def setCommand(self, _): pass def setDebugInfo(self, _): pass def setConsoleInfo(self, _): pass def close(self): if self.msg: dlg = MessageDialog() dlg.setTitle(QCoreApplication.translate('MessageBarProgress', 'Problem executing algorithm')) dlg.setMessage("<br>".join(self.msg)) dlg.exec_() iface.messageBar().clearWidgets() def tr(self, string, context=''): if context == '': context = 'MessageBarProgress' return QCoreApplication.translate(context, string)
class ProgessBarDialog(QDialog): def __init__(self, GTFS_folder, parent=None): QDialog.__init__(self, parent) self.resize(310, 140) self.setWindowTitle("Info") self.process_info = QLineEdit(self) self.process_info.resize(230, 20) self.process_info.move(40, 35) self.process_info.setAlignment(Qt.AlignVCenter) self.progBar = QProgressBar(self) self.progBar.resize(230,20) self.progBar.move(40, 70) self.progBar.setAlignment(Qt.AlignVCenter) self.newTask(GTFS_folder) def newTask(self,GTFS_folder): self.task = HeavyTask(GTFS_folder) self.task.progressChanged.connect(lambda: self.progBar.setValue(self.task.progress())) self.task.progressChanged.connect(lambda: self.info(self.task.progress())) QgsApplication.taskManager().addTask(self.task) def info(self,value): if value == 10: self.process_info.setText("Unzipping file") elif value == 60: self.process_info.setText("Saving layers into GeoPackage") elif value == 70: self.process_info.setText("Loading layers from GeoPackage") elif value == 80: self.process_info.setText("Deleting unzipped folder") elif value == 85: self.process_info.setText("Connecting shapes") elif value == 95: self.process_info.setText("Coloring of line layers") elif value == 100: time.sleep(2) self.close()
def progressBar(self): progressMessageBar = self.iface.messageBar().createMessage( "Project setup...") progress = QProgressBar() progress.setMaximum(5) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) for i in range(5): time.sleep(1) progress.setValue(i + 1) self.iface.messageBar().clearWidgets() energy_plant_radiation_class.popupMessage(self, "Project setup:", "Completed with success", "success") print("Project Loaded")
class MessageBarProgressItem(QObject): """ Message bar item which shows a progress report bar """ def __init__(self, text, iface: QgisInterface, parent: QObject = None): """ Constructor for MessageBarProgressItem :param text: text to show :param parent: parent object """ super().__init__(parent) self.iface = iface self.progressMessageBar = \ self.iface.messageBar().createMessage(text) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.destroyed.connect(self.clear_progress) self.progressMessageBar.layout().addWidget(self.progress) self.iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) def close(self): # pylint disable=may-be-static """ Closes the message bar item """ if self.progressMessageBar is not None: self.iface.messageBar().popWidget(self.progressMessageBar) def clear_progress(self): """ Called on deletion of the progress bar, e.g. by user closing the bar """ self.progress = None self.progressMessageBar = None def set_progress(self, progress: int): """ Sets the progress to show in the item :param progress: integer for percent progress, 0 - 100 """ if self.progress is not None: self.progress.setValue(progress)
class Source: def __init__(self): placeholder = 100 def set_iface(self, iface): self.iface = iface def has_options_dialog(self): return False def download_data(self, url, path, msg): if not os.path.exists(path): try: progressMessageBar = self.iface.messageBar().createMessage( "Downloading " + msg) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(self.progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) http = urllib3.PoolManager() response = http.request('GET', url, preload_content=False) content_length = response.headers['Content-Length'] total_size = int(content_length) downloaded = 0 CHUNK = 256 * 10240 self.progress.setMinimum(0) self.progress.setMaximum(total_size) with open(path, 'wb') as fp: while True: time.sleep(1) chunk = response.read(CHUNK) downloaded += len(chunk) self.progress.setValue(downloaded) if not chunk: break fp.write(chunk) response.release_conn() self.iface.messageBar().clearWidgets() except urllib3.exceptions.MaxRetryError: QMessageBox.information(self.iface.mainWindow(), "HTTP Error", "Unable to download file")
def start_worker(worker, message_bar, message): """ Configure the QgsMessageBar with a :guilabel:`Cancel` button and start the worker in a new thread :param worker: the worker to be started :param message_bar: the message bar to be used to display progress :param message: a message describing the task to be performed """ # configure the QgsMessageBar message_bar_item = message_bar.createMessage(message) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) cancel_button = QPushButton() cancel_button.setText('Cancel') cancel_button.clicked.connect(worker.kill) message_bar_item.layout().addWidget(progress_bar) message_bar_item.layout().addWidget(cancel_button) message_bar.pushWidget(message_bar_item, Qgis.Info) # start the worker in a new thread thread = QThread(message_bar.parent()) worker.moveToThread(thread) worker.set_message.connect( lambda message: set_worker_message(message, message_bar_item)) worker.toggle_show_progress.connect( lambda show: toggle_worker_progress(show, progress_bar)) worker.toggle_show_cancel.connect( lambda show: toggle_worker_cancel(show, cancel_button)) worker.finished.connect(lambda result: worker_finished( result, thread, worker, message_bar, message_bar_item)) worker.error.connect( lambda e, exception_str: worker_error(e, exception_str, message_bar)) worker.progress.connect(progress_bar.setValue) thread.started.connect(worker.run) thread.start() return thread, message_bar_item
def __import_data(self): assert(self.project) dir_ = QFileDialog.getExistingDirectory( None, u"Data directory", QgsProject.instance().readEntry("albion", "last_dir", "")[0], QFileDialog.ShowDirsOnly | QFileDialog.DontUseNativeDialog ) if not dir_: return QgsProject.instance().writeEntry("albion", "last_dir", dir_), progressMessageBar = self.__iface.messageBar().createMessage( "Loading {}...".format(dir_) ) progress = QProgressBar() progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.__iface.messageBar().pushWidget(progressMessageBar) self.project.import_data(dir_, ProgressBar(progress)) #self.project.triangulate() self.project.create_section_view_0_90(4) self.__iface.messageBar().clearWidgets() collar = QgsProject.instance().mapLayersByName("collar") if len(collar): collar[0].reload() collar[0].updateExtents() self.__iface.setActiveLayer(collar[0]) QApplication.instance().processEvents() while self.__iface.mapCanvas().isDrawing(): QApplication.instance().processEvents() self.__iface.zoomToActiveLayer() self.__iface.actionSaveProject().trigger() self.__viewer3d.widget().resetScene(self.project) self.__current_section.clear() self.__current_section.addItems(self.project.sections())
class progressBar: def __init__(self, parent, title=''): ''' progressBar class instatiation method. It creates a QgsMessageBar with provided msg and a working QProgressBar :param parent: :param msg: string ''' self.iface = parent.iface self.title = title def start(self, max=0, msg=''): self.widget = self.iface.messageBar().createMessage(self.title, msg) self.progressBar = QProgressBar() self.progressBar.setRange(0, max) self.progressBar.setValue(0) self.progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.widget.layout().addWidget(self.progressBar) QApplication.processEvents() self.iface.messageBar().pushWidget(self.widget, Qgis.Info, 50) QApplication.processEvents() def setProgress(self, value): try: self.progressBar.setValue(value) QApplication.processEvents() except: pass def setMsg(self, msg): self.widget.setText(msg) QApplication.processEvents() def stop(self, msg=''): ''' the progressbar is stopped with a succes message :param msg: string :return: ''' self.iface.messageBar().clearWidgets() message = self.iface.messageBar().createMessage(self.title, msg) self.iface.messageBar().pushWidget(message, Qgis.Info, 2)
def onSubmit(self): self.choosing.close() progressMessageBar = iface.messageBar().createMessage("") self.process_info = QLabel() progressMessageBar.layout().addWidget(self.process_info) progress = QProgressBar() progress.setMaximum(100) progress.setAlignment(Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) task = LoadTask(self.dockwidget.input_dir.filePath(), self.do_zones) task.progressChanged.connect( lambda: progress.setValue(task.progress())) task.progressChanged.connect(lambda: self.info(task.progress())) QgsApplication.taskManager().addTask(task)
def import_mesh(self): qfd = QFileDialog() path = "" import_function = load_IO() fil = '' for model in import_function: fil += import_function[model]['extension']() + ';' fname = QFileDialog.getOpenFileName(qfd, 'Import Mesh file', path, fil) fname = fname[0] if fname == '': return filename, file_extension = os.path.splitext(fname) if file_extension == '': return progressMessageBar = self.iface.messageBar().createMessage("Load Mesh") progress = QProgressBar() progress.setMaximum(10) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) self.mesh = Mesh([], [], [], []) for model in import_function: ext = import_function[model]['extension']() if file_extension in ext: progress.setValue(0) self.mesh = import_function[model]['import'](self.mesh, fname) progress.setValue(3) self.mesh._calculate_face_nodes() progress.setValue(6) # self.mesh._remove_hanging_nodes() self.mesh.calc_parameters() progress.setValue(9) Mesh2Shapefile(self.mesh) self.iface.messageBar().clearWidgets()
def prepareProcess(self, process, message): """ Prepares the process to be executed. Creates a message bar. Connects the destroyed progress bar signal to the process cancel method """ # Setting the progress bar progressMessageBar = self.iface.messageBar().createMessage(message) progressBar = QProgressBar() progressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progressBar) self.iface.messageBar().pushWidget(progressMessageBar, self.iface.messageBar().INFO) #connecting the destroyed signal progressMessageBar.destroyed.connect( process.messenger.progressCanceled) #storing the process and its related progressBar self.processDict[process] = progressBar #initiating processing QThreadPool.globalInstance().start(process)
def start_worker(worker, iface, message, with_progress=True): # configure the QgsMessageBar message_bar_item = iface.messageBar().createMessage(message) progress_bar = QProgressBar() progress_bar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) if not with_progress: progress_bar.setMinimum(0) progress_bar.setMaximum(0) cancel_button = QPushButton() cancel_button.setText('Cancel') cancel_button.clicked.connect(worker.kill) message_bar_item.layout().addWidget(progress_bar) message_bar_item.layout().addWidget(cancel_button) iface.messageBar().pushWidget(message_bar_item, Qgis.Info) # start the worker in a new thread # let Qt take ownership of the QThread thread = QThread(iface.mainWindow()) worker.moveToThread(thread) worker.set_message.connect(lambda message: set_worker_message( message, message_bar_item)) worker.toggle_show_progress.connect(lambda show: toggle_worker_progress( show, progress_bar)) worker.toggle_show_cancel.connect(lambda show: toggle_worker_cancel( show, cancel_button)) worker.finished.connect(lambda result: worker_finished( result, thread, worker, iface, message_bar_item)) worker.error.connect(lambda e: worker_error(e)) worker.was_killed.connect(lambda result: worker_killed( result, thread, worker, iface, message_bar_item)) worker.progress.connect(progress_bar.setValue) thread.started.connect(worker.run) thread.start() return thread, message_bar_item
def run_custom_evalscript(self): """ Run operations given user inputted custom evalscript code and return a raster layer based on specifications """ progressMessageBar = self.iface.messageBar().createMessage( 'Getting mosaic preview') progress = QProgressBar() progress.setMaximum(3) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) # get bounding box bbox = self.get_bounding_box(default=False) # validate and set time interval start_date, end_date = self.dockwidget.start_date.text( ), self.dockwidget.end_date.text() accepted_date_format = "%Y-%m-%d" try: dt.datetime.strptime(start_date, accepted_date_format) dt.datetime.strptime(end_date, accepted_date_format) except ValueError: raise ValueError( "Please enter start and end dates with the format of YYYY-MM-DD (ex. 2000-01-01)." ) time_interval = [start_date, end_date] # set and validate max_cc max_cc = float(self.dockwidget.custom_max_cc.text()) assert max_cc >= 0 and max_cc <= 1, 'Please enter a max cloud cover proportion between 0 and 1.' # grab user inputted custom evalscript and substitute generic custom_evalscript_code = self.dockwidget.custom_evalscript_code.toPlainText( ) preview_eval = custom_evalscript_code QgsMessageLog.logMessage('requesting preview image', level=Qgis.Info) preview_request = SentinelHubRequest( evalscript=preview_eval, data_folder='/tmp/mosaic_tests', input_data=[ SentinelHubRequest.input_data( data_collection=DataCollection.SENTINEL2_L2A, time_interval=time_interval, maxcc=max_cc) ], responses=[ SentinelHubRequest.output_response('default', MimeType.TIFF) ], bbox=bbox, size=(512, get_image_dimension(bbox=bbox, width=512)), config=config) preview_request.get_data(save_data=True) progress.setValue(3) output_file = '/tmp/mosaic_tests' + '/' + preview_request.get_filename_list( )[0] # add file to QGIS custom_layer_name_input = self.dockwidget.custom_layer_name_input.text( ) if len(custom_layer_name_input) != 0: layer_name = custom_layer_name_input else: layer_name = 'custom_evalscript_layer' self.iface.addRasterLayer(output_file, layer_name) self.iface.messageBar().clearWidgets() return None
windows = platform.system() == 'Windows' LavFilters = "https://github.com/Nevcairiel/LAVFilters/releases/download/0.73.1/LAVFilters-0.73.1-Installer.exe" # 64 Bits if platform.machine().endswith('64'): FFMPEG = "https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20190225-2e67f75-win64-static.zip" # 32 Bits else: FFMPEG = "https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20190225-2e67f75-win32-static.zip" DemGlobal = "http://www.gisandbeers.com/RRSS/Cartografia/DEM-Mundial.rar" progress = QProgressBar() progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) opener = build_opener() opener.addheaders = [( 'User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1941.0 Safari/537.36' )] install_opener(opener) def reporthook(blocknum, blocksize, totalsize): readsofar = blocknum * blocksize if totalsize > 0: percent = readsofar * 1e2 / totalsize progress.setValue(int(percent))
def generate_report(self, db, report_type): # Check if mapfish and Jasper are installed, otherwise show where to # download them from and return if not self.report_dependency.check_if_dependency_is_valid(): self.report_dependency.download_dependency(URL_REPORTS_LIBRARIES) return java_home_set = self.java_dependency.set_java_home() if not java_home_set: self.java_dependency.get_java_on_demand() self.logger.info_msg( __name__, QCoreApplication.translate( "ReportGenerator", "Java is a prerequisite. Since it was not found, it is being configured..." )) return plot_layer = self.app.core.get_layer(db, db.names.LC_PLOT_T, load=True) if not plot_layer: return selected_plots = plot_layer.selectedFeatures() if not selected_plots: self.logger.warning_msg( __name__, QCoreApplication.translate( "ReportGenerator", "To generate reports, first select at least a plot!")) return # Where to store the reports? previous_folder = QSettings().value( "Asistente-LADM-COL/reports/save_into_dir", ".") save_into_folder = QFileDialog.getExistingDirectory( None, QCoreApplication.translate( "ReportGenerator", "Select a folder to save the reports to be generated"), previous_folder) if not save_into_folder: self.logger.warning_msg( __name__, QCoreApplication.translate( "ReportGenerator", "You need to select a folder where to save the reports before continuing." )) return QSettings().setValue("Asistente-LADM-COL/reports/save_into_dir", save_into_folder) config_path = os.path.join(DEPENDENCY_REPORTS_DIR_NAME, report_type) json_spec_file = os.path.join(config_path, 'spec_json_file.json') script_name = '' if os.name == 'posix': script_name = 'print' elif os.name == 'nt': script_name = 'print.bat' script_path = os.path.join(DEPENDENCY_REPORTS_DIR_NAME, 'bin', script_name) if not os.path.isfile(script_path): self.logger.warning( __name__, "Script file for reports wasn't found! {}".format(script_path)) return self.enable_action_requested.emit(report_type, False) # Update config file yaml_config_path = self.update_yaml_config(db, config_path) self.logger.debug( __name__, "Config file for reports: {}".format(yaml_config_path)) total = len(selected_plots) step = 0 count = 0 tmp_dir = self.get_tmp_dir() # Progress bar setup progress = QProgressBar() if total == 1: progress.setRange(0, 0) else: progress.setRange(0, 100) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.app.gui.create_progress_message_bar( QCoreApplication.translate("ReportGenerator", "Generating {} report{}...").format( total, '' if total == 1 else 's'), progress) polygons_with_holes = [] multi_polygons = [] for selected_plot in selected_plots: plot_id = selected_plot[db.names.T_ID_F] geometry = selected_plot.geometry() abstract_geometry = geometry.get() if abstract_geometry.ringCount() > 1: polygons_with_holes.append(str(plot_id)) self.logger.warning( __name__, QCoreApplication.translate( "ReportGenerator", "Skipping Annex 17 for plot with {}={} because it has holes. The reporter module does not support such polygons." ).format(db.names.T_ID_F, plot_id)) continue if abstract_geometry.numGeometries() > 1: multi_polygons.append(str(plot_id)) self.logger.warning( __name__, QCoreApplication.translate( "ReportGenerator", "Skipping Annex 17 for plot with {}={} because it is a multi-polygon. The reporter module does not support such polygons." ).format(db.names.T_ID_F, plot_id)) continue # Generate data file json_file = self.update_json_data(db, json_spec_file, plot_id, tmp_dir, report_type) self.logger.debug(__name__, "JSON file for reports: {}".format(json_file)) # Run sh/bat passing config and data files proc = QProcess() proc.readyReadStandardError.connect( functools.partial(self.stderr_ready, proc=proc)) proc.readyReadStandardOutput.connect( functools.partial(self.stdout_ready, proc=proc)) parcel_number = self.ladm_data.get_parcels_related_to_plots( db, [plot_id], db.names.LC_PARCEL_T_PARCEL_NUMBER_F) or [''] file_name = '{}_{}_{}.pdf'.format(report_type, plot_id, parcel_number[0]) current_report_path = os.path.join(save_into_folder, file_name) proc.start(script_path, [ '-config', yaml_config_path, '-spec', json_file, '-output', current_report_path ]) if not proc.waitForStarted(): # Grant execution permissions os.chmod( script_path, stat.S_IXOTH | stat.S_IXGRP | stat.S_IXUSR | stat.S_IRUSR | stat.S_IRGRP) proc.start(script_path, [ '-config', yaml_config_path, '-spec', json_file, '-output', current_report_path ]) if not proc.waitForStarted(): proc = None self.logger.warning( __name__, "Couldn't execute script to generate report...") else: loop = QEventLoop() proc.finished.connect(loop.exit) loop.exec() self.logger.debug(__name__, "{}:{}".format(plot_id, proc.exitCode())) if proc.exitCode() == 0: count += 1 step += 1 progress.setValue(step * 100 / total) os.remove(yaml_config_path) self.enable_action_requested.emit(report_type, True) self.logger.clear_message_bar() if total == count: if total == 1: msg = QCoreApplication.translate( "ReportGenerator", "The report <a href='file:///{}'>{}</a> was successfully generated!" ).format(normalize_local_url(save_into_folder), file_name) else: msg = QCoreApplication.translate( "ReportGenerator", "All reports were successfully generated in folder <a href='file:///{path}'>{path}</a>!" ).format(path=normalize_local_url(save_into_folder)) self.logger.success_msg(__name__, msg) else: details_msg = '' if polygons_with_holes: details_msg += QCoreApplication.translate( "ReportGenerator", " The following polygons were skipped because they have holes and are not supported: {}." ).format(", ".join(polygons_with_holes)) if multi_polygons: details_msg += QCoreApplication.translate( "ReportGenerator", " The following polygons were skipped because they are multi-polygons and are not supported: {}." ).format(", ".join(multi_polygons)) if total == 1: msg = QCoreApplication.translate( "ReportGenerator", "The report for plot {} couldn't be generated!{} See QGIS log (tab '{}') for details." ).format(plot_id, details_msg, self.LOG_TAB) else: if count == 0: msg = QCoreApplication.translate( "ReportGenerator", "No report could be generated!{} See QGIS log (tab '{}') for details." ).format(details_msg, self.LOG_TAB) else: msg = QCoreApplication.translate( "ReportGenerator", "At least one report couldn't be generated!{details_msg} See QGIS log (tab '{log_tab}') for details. Go to <a href='file:///{path}'>{path}</a> to see the reports that were generated." ).format(details_msg=details_msg, path=normalize_local_url(save_into_folder), log_tab=self.LOG_TAB) self.logger.warning_msg(__name__, msg)
class OSMDownloaderDialog(QDialog, FORM_CLASS): def __init__(self, iface, startX, startY, endX, endY, parent=None): """Constructor.""" super(OSMDownloaderDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.iface = iface self.setCoordinates(startX, startY, endX, endY) self.threadpool = QThreadPool() self.size = 0 def setCoordinates(self, startX, startY, endX, endY): if startX < endX: minLong = startX maxLong = endX else: minLong = endX maxLong = startX if startY < endY: minLat = startY maxLat = endY else: minLat = endY maxLat = startY self.wEdit.setText(str(minLong)) self.sEdit.setText(str(minLat)) self.eEdit.setText(str(maxLong)) self.nEdit.setText(str(maxLat)) @pyqtSlot() def on_saveButton_clicked(self): ret = QFileDialog.getSaveFileName(parent=None, caption='Define file name and location', filter='OSM Files(*.osm)') fileName = ret[0] split = fileName.split('.') if len(split)>0 and split[-1] == 'osm': pass else: fileName += '.osm' self.filenameEdit.setText(fileName) @pyqtSlot() def on_button_box_accepted(self): if self.filenameEdit.text() == '': QMessageBox.warning(self, self.tr("Warning!"), self.tr("Please, select a location to save the file.")) return # Initiating processing osmRequest = OSMRequest(self.filenameEdit.text()) osmRequest.setParameters(self.wEdit.text(), self.sEdit.text(), self.eEdit.text(), self.nEdit.text()) # Connecting end signal osmRequest.signals.processFinished.connect(self.processFinished) osmRequest.signals.sizeReported.connect(self.reportSize) osmRequest.signals.proxyOpened.connect(self.proxy) osmRequest.signals.errorOccurred.connect(self.errorOccurred) osmRequest.signals.userCanceled.connect(self.userCanceled) # Setting the progress bar self.progressMessageBar = self.iface.messageBar().createMessage('Downloading data...') self.progressBar = QProgressBar() self.progressBar.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progressBar) self.iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) self.progressBar.setRange(0, 0) self.progressMessageBar.destroyed.connect(osmRequest.signals.cancel) # Starting process self.threadpool.start(osmRequest) @pyqtSlot(str) def proxy(self, proxy): self.progressMessageBar.setText('Proxy set to: '+proxy) @pyqtSlot(str) def errorOccurred(self, message): QMessageBox.warning(self, 'Fatal!', message) self.close() @pyqtSlot() def userCanceled(self): QMessageBox.warning(self, 'Info!', 'Process canceled by user!') self.close() @pyqtSlot(float) def reportSize(self, size): self.size = size self.progressMessageBar.setText('Downloading: '+"{0:.2f}".format(size)+' megabytes from OSM servers...') @pyqtSlot(str) def processFinished(self, message): self.progressBar.setRange(0, 100) self.progressBar.setValue(100) self.progressMessageBar.setText('Downloaded '+"{0:.2f}".format(self.size)+' megabytes in total from OSM servers') QMessageBox.warning(self, 'Info!', message) if self.checkBox.isChecked(): self.iface.addVectorLayer(self.filenameEdit.text(), 'osm_data', 'ogr') self.close()
class Window(QDialog): def __init__(self): super().__init__() self.title = "PyQt5 ProgressBar" self.top = 200 self.left = 500 self.width = 300 self.height = 100 self.setWindowIcon(QtGui.QIcon("icon.png")) self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) vbox = QVBoxLayout() self.progressbar = QProgressBar() #self.progressbar.setOrientation(Qt.Vertical) self.progressbar.setMaximum(100) vbox.addWidget(self.progressbar) self.startProgressBar() self.setLayout(vbox) #self.show() def startProgressBar(self): self.thread = MyThread() self.thread.change_value.connect(self.setProgressBarAndMessages) self.thread.start() def setProgressBarAndMessages(self, val): self.progressbar.setValue(val) # --- Progress bar in the QGIS user messages (top) if val <= 10: message = "Starting..." self.progressMessageBar = iface.messageBar().createMessage(message) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) self.progress.setValue(val) elif val < 50: message = "First half" self.progressMessageBar = iface.messageBar().createMessage(message) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) self.progress.setValue(val) elif val < 100: message = "Second Half" self.progressMessageBar = iface.messageBar().createMessage(message) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) self.progress.setValue(val) elif val == 100: message = "Complete" self.progressMessageBar = iface.messageBar().createMessage(message) self.progress = QProgressBar() self.progress.setMaximum(100) self.progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) self.progressMessageBar.layout().addWidget(self.progress) iface.messageBar().pushWidget(self.progressMessageBar, Qgis.Info) self.progress.setValue(val) iface.messageBar().clearWidgets()
def run(self): """Run method that performs all the real work""" def blankPaint(geometry): blank = ee.Image(0).mask(0) geometryDraw = blank.paint(geometry, '0000AA', 1) return geometryDraw # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False self.dlg = simex_pluginDialog() # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: uf = self.dlg.selectUF.currentText() path = self.dlg.path.toPlainText() row = self.dlg.row.toPlainText() cloud_cover = int(self.dlg.cloudcover.cleanText()) startdate = self.dlg.startdate.date().toString('yyyy-MM-dd') enddate = self.dlg.enddate.date().toString('yyyy-MM-dd') self.iface.messageBar().pushMessage('loading ...') geometry = path_row_am.filterMetadata('PATH', 'equals', int(path)).filterMetadata('ROW', 'equals', int(row)).geometry() countourGeometry = blankPaint(geometry) Map.centerObject(geometry, 100) progressMessageBar = iface.messageBar().createMessage("loading...") progress = QProgressBar() progress.setMaximum(10) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) for i in range(10): time.sleep(1) progress.setValue(i + 1) parametrosColecaoL8 = { 'collectionid': 'LANDSAT/LC08/C01/T1_SR', 'geometry': geometry.centroid(), 'dateStart': ee.Date(startdate), 'dateEnd': ee.Date(enddate), 'cloud_cover': cloud_cover, } colecaoL8 = getCollection(parametrosColecaoL8).select(bandNames("l8")['bandNames'],bandNames("l8")['newNames'])\ .map(getSMA).map(getNDFI) #nImages = colecaoL8.size().getInfo() #colList = colecaoL8.toList(nImages) #idG = 1 listYears = list(range(int(startdate[:4]),int(enddate[:4])+1)) for item in listYears: #imgYear = ee.Image(colecaoL8.filterDate(str(item) + '-01-01',str(item+1) + '-01-01').sort('cloud_cover').first()) colYear = colecaoL8.filterDate(str(item) + '-01-01',str(item+1) + '-01-01').sort('cloud_cover').limit(3) colList = colYear.toList(5) idG = 1 while idG < 3: img = ee.Image(colList.get(idG)) try: dictionaryInfos = ee.Dictionary({'satellite_name':img.get('satellite_name'), 'date':img.get('date'), 'cloud_cover':img.get('cloud_cover')}).getInfo() if listYears.index(item) == len(listYears)-2: status = True else: status = False Map.addLayer(img, {'bands': ['swir2'],'gain' : [0.2],'gamma':0.6},\ 'B7_' + str(dictionaryInfos['date']).replace('-','_')+'_'+dictionaryInfos['satellite_name'],status) Map.addLayer(img,{"bands": ['ndfi'], "palette": ['ffffff', 'fffcff', 'fff9ff', 'fff7ff', 'fff4ff', 'fff2ff', 'ffefff', 'ffecff', 'ffeaff', 'ffe7ff', 'ffe5ff', 'ffe2ff', 'ffe0ff', 'ffddff', 'ffdaff', 'ffd8ff', 'ffd5ff', 'ffd3ff', 'ffd0ff', 'ffceff', 'ffcbff', 'ffc8ff', 'ffc6ff', 'ffc3ff', 'ffc1ff', 'ffbeff', 'ffbcff', 'ffb9ff', 'ffb6ff', 'ffb4ff', 'ffb1ff', 'ffafff', 'ffacff', 'ffaaff', 'ffa7ff', 'ffa4ff', 'ffa2ff', 'ff9fff', 'ff9dff', 'ff9aff', 'ff97ff', 'ff95ff', 'ff92ff', 'ff90ff', 'ff8dff', 'ff8bff', 'ff88ff', 'ff85ff', 'ff83ff', 'ff80ff', 'ff7eff', 'ff7bff', 'ff79ff', 'ff76ff', 'ff73ff', 'ff71ff', 'ff6eff', 'ff6cff', 'ff69ff', 'ff67ff', 'ff64ff', 'ff61ff', 'ff5fff', 'ff5cff', 'ff5aff', 'ff57ff', 'ff55ff', 'ff52ff', 'ff4fff', 'ff4dff', 'ff4aff', 'ff48ff', 'ff45ff', 'ff42ff', 'ff40ff', 'ff3dff', 'ff3bff', 'ff38ff', 'ff36ff', 'ff33ff', 'ff30ff', 'ff2eff', 'ff2bff', 'ff29ff', 'ff26ff', 'ff24ff', 'ff21ff', 'ff1eff', 'ff1cff', 'ff19ff', 'ff17ff', 'ff14ff', 'ff12ff', 'ff0fff', 'ff0cff', 'ff0aff', 'ff07ff', 'ff05ff', 'ff02ff', 'ff00ff', 'ff00ff', 'ff0af4', 'ff15e9', 'ff1fdf', 'ff2ad4', 'ff35c9', 'ff3fbf', 'ff4ab4', 'ff55aa', 'ff5f9f', 'ff6a94', 'ff748a', 'ff7f7f', 'ff8a74', 'ff946a', 'ff9f5f', 'ffaa55', 'ffb44a', 'ffbf3f', 'ffc935', 'ffd42a', 'ffdf1f', 'ffe915', 'fff40a', 'ffff00', 'ffff00', 'fffb00', 'fff700', 'fff300', 'fff000', 'ffec00', 'ffe800', 'ffe400', 'ffe100', 'ffdd00', 'ffd900', 'ffd500', 'ffd200', 'ffce00', 'ffca00', 'ffc600', 'ffc300', 'ffbf00', 'ffbb00', 'ffb700', 'ffb400', 'ffb000', 'ffac00', 'ffa800', 'ffa500', 'ffa500', 'f7a400', 'f0a300', 'e8a200', 'e1a200', 'd9a100', 'd2a000', 'ca9f00', 'c39f00', 'bb9e00', 'b49d00', 'ac9c00', 'a59c00', '9d9b00', '969a00', '8e9900', '879900', '7f9800', '789700', '709700', '699600', '619500', '5a9400', '529400', '4b9300', '439200', '349100', '2d9000', '258f00', '1e8e00', '168e00', '0f8d00', '078c00', '008c00', '008c00', '008700', '008300', '007f00', '007a00', '007600', '007200', '006e00', '006900', '006500', '006100', '005c00', '005800', '005400', '005000', '004c00'],\ "min":0,"max":200},'NDFI_' + str(dictionaryInfos['date']).replace('-','_')+'_'+dictionaryInfos['satellite_name'],status) except Exception as e: # print('Exception\n',str(e)) pass idG = idG + 1 for i in range(10): time.sleep(1) progress.setValue(i + 1) iface.messageBar().clearWidgets() Map.addLayer(countourGeometry,{ 'palette': '#000000', 'opacity': 0.8 },str(path) + '_' + str(row)) for item in auxLayers[dicAuxState[uf]][0]: outline = blankPaint(auxLayers[dicAuxState[uf]][item][1][1]) Map.addLayer(outline,auxLayers[dicAuxState[uf]][item][1][3],\ auxLayers[dicAuxState[uf]][item][1][2], False)
def CreateMISB(self): ''' Create MISB Video ''' ''' Only tested using DJI Data ''' # Create ProgressBar self.iface.messageBar().clearWidgets() progressMessageBar = self.iface.messageBar().createMessage("Creating video packets...") progress = QProgressBar() progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, QGis.Info) QApplication.setOverrideCursor(Qt.WaitCursor) QApplication.processEvents() HFOV = self.sp_hfov.value() #VFOV = self.sp_vfov.value() index = self.cmb_telemetry.currentIndex() out_record = self.cmb_telemetry.itemData(index) rowCount = self.GetRows(out_record) progress.setMaximum(rowCount) d = {} with open(out_record) as csvfile: reader = csv.DictReader(csvfile) for row in reader: date_start = datetime.strptime(row["CUSTOM.updateTime"], '%Y/%m/%d %H:%M:%S.%f') break with open(out_record) as csvfile: reader = csv.DictReader(csvfile) for row in reader: for k in row: stripK = k.strip() stripV = row[k].strip() d[stripK] = stripV # We create the klv file for every moment sizeTotal = 0 bufferData = b'' cnt = 0 for k, v in d.items(): try: if k == "CUSTOM.updateTime": # We prevent it from failing in the exact times that don't have milliseconds try: date_end = datetime.strptime(v, '%Y/%m/%d %H:%M:%S.%f') except: date_end = datetime.strptime(v, '%Y/%m/%d %H:%M:%S') _bytes = datetime_to_bytes(date_end) _len = int_to_bytes(len(_bytes)) _bytes = _key2 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Platform Heading Angle if k == "OSD.yaw": OSD_yaw = float(v) _bytes = float_to_bytes(round(OSD_yaw, 4), _domain5, _range5) _len = int_to_bytes(len(_bytes)) _bytes = _key5 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Platform Pitch Angle if k == "OSD.pitch": OSD_pitch = 0.0 _bytes = float_to_bytes(round(OSD_pitch, 4), _domain6, _range6) _len = int_to_bytes(len(_bytes)) _bytes = _key6 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Platform Roll Angle if k == "OSD.roll": OSD_roll = 0.0 _bytes = float_to_bytes(round(OSD_roll, 4), _domain7, _range7) _len = int_to_bytes(len(_bytes)) _bytes = _key7 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Latitude if k == "OSD.latitude": OSD_latitude = float(v) _bytes = float_to_bytes(round(OSD_latitude, 4), _domain13, _range13) _len = int_to_bytes(len(_bytes)) _bytes = _key13 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Longitude if k == "OSD.longitude": OSD_longitude = float(v) _bytes = float_to_bytes(OSD_longitude, _domain14, _range14) _len = int_to_bytes(len(_bytes)) _bytes = _key14 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor True Altitude if k == "OSD.altitude [m]": OSD_altitude = float(v) _bytes = float_to_bytes(round(OSD_altitude, 4), _domain15, _range15) _len = int_to_bytes(len(_bytes)) _bytes = _key15 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Ellipsoid Height if k == "OSD.height [m]": OSD_height = float(v) _bytes = float_to_bytes(round(OSD_height, 4), _domain75, _range75) _len = int_to_bytes(len(_bytes)) _bytes = _key75 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Relative Azimuth Angle if k == "GIMBAL.yaw": #GIMBAL_yaw = float(v) GIMBAL_yaw = 0.0 _bytes = float_to_bytes(round(GIMBAL_yaw, 4), _domain18, _range18) _len = int_to_bytes(len(_bytes)) _bytes = _key18 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Relative Elevation Angle if k == "GIMBAL.pitch": GIMBAL_pitch = float(v) _bytes = float_to_bytes(round(GIMBAL_pitch, 4), _domain19, _range19) _len = int_to_bytes(len(_bytes)) _bytes = _key19 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Relative Roll Angle if k == "GIMBAL.roll": GIMBAL_roll = 0.0 _bytes = float_to_bytes(round(GIMBAL_roll, 4), _domain20, _range20) _len = int_to_bytes(len(_bytes)) _bytes = _key20 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes except Exception: print("Multiplexer error") continue try: # Diference time td = date_end - date_start end_path = self.klv_folder + "/%.1f.klv" % (round(td.total_seconds(), 1)) # CheckSum v = abs(hash(end_path)) % (10 ** 4) _bytes = int_to_bytes(v, 4) _len = int_to_bytes(len(_bytes)) _bytes = _key1 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Horizontal Field of View v = self.sp_hfov.value() _bytes = float_to_bytes(float(v), _domain16, _range16) _len = int_to_bytes(len(_bytes)) _bytes = _key16 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Sensor Vertical Field of View v = self.sp_vfov.value() _bytes = float_to_bytes(float(v), _domain17, _range17) _len = int_to_bytes(len(_bytes)) _bytes = _key17 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # TODO : Check these calculations # Slant Range anlge = 180 + (OSD_pitch + GIMBAL_pitch) slantRange = abs(OSD_altitude / (cos(radians(anlge)))) _bytes = float_to_bytes(round(slantRange, 4), _domain21, _range21) _len = int_to_bytes(len(_bytes)) _bytes = _key21 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Target Width # targetWidth = 0.0 targetWidth = 2.0 * slantRange * tan(radians(HFOV / 2.0)) _bytes = float_to_bytes(round(targetWidth, 4), _domain22, _range22) _len = int_to_bytes(len(_bytes)) _bytes = _key22 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Frame Center Latitude angle = 90 + (OSD_pitch + GIMBAL_pitch) tgHzDist = OSD_altitude * tan(radians(angle)) r_earth = 6371008.8 dy = tgHzDist * cos(radians(OSD_yaw)) framecenterlatitude = OSD_latitude + (dy / r_earth) * (180 / pi) _bytes = float_to_bytes(round(framecenterlatitude, 4), _domain23, _range23) _len = int_to_bytes(len(_bytes)) _bytes = _key23 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Frame Center Longitude dx = tgHzDist * sin(radians(OSD_yaw)) framecenterlongitude = OSD_longitude + (dx / r_earth) * (180 / pi) / cos(OSD_latitude * pi/180) _bytes = float_to_bytes(round(framecenterlongitude, 4), _domain24, _range24) _len = int_to_bytes(len(_bytes)) _bytes = _key24 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Frame Center Elevation frameCenterElevation = 0.0 _bytes = float_to_bytes(frameCenterElevation, _domain25, _range25) _len = int_to_bytes(len(_bytes)) _bytes = _key25 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # TODO : If we save the corners in the klv have a overflow # # CALCULATE CORNERS COORDINATES # sensor = (OSD_longitude, OSD_latitude, OSD_altitude) # frameCenter = (destPoint[0], destPoint[1], frameCenterElevation) # FOV = (VFOV, HFOV) # others = (OSD_yaw, GIMBAL_yaw, targetWidth, slantRange) # cornerPointUL, cornerPointUR, cornerPointLR, cornerPointLL = CornerEstimationWithoutOffsets(sensor=sensor, frameCenter=frameCenter, FOV=FOV, others=others) # # # Corner Latitude Point 1 (Full) # _bytes = float_to_bytes(round(cornerPointUL[0],4), _domain82, _range82) # _len = int_to_bytes(len(_bytes)) # _bytes = _key82 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Longitude Point 1 (Full) # _bytes = float_to_bytes(round(cornerPointUL[1],4), _domain83, _range83) # _len = int_to_bytes(len(_bytes)) # _bytes = _key83 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Latitude Point 2 (Full) # _bytes = float_to_bytes(round(cornerPointUR[0],4), _domain84, _range84) # _len = int_to_bytes(len(_bytes)) # _bytes = _key84 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Longitude Point 2 (Full) # _bytes = float_to_bytes(round(cornerPointUR[1],4), _domain85, _range85) # _len = int_to_bytes(len(_bytes)) # _bytes = _key85 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Latitude Point 3 (Full) # _bytes = float_to_bytes(round(cornerPointLR[0],4), _domain86, _range86) # _len = int_to_bytes(len(_bytes)) # _bytes = _key86 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Longitude Point 3 (Full) # _bytes = float_to_bytes(round(cornerPointLR[1],4), _domain87, _range87) # _len = int_to_bytes(len(_bytes)) # _bytes = _key87 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Latitude Point 4 (Full) # _bytes = float_to_bytes(round(cornerPointLL[0],4), _domain88, _range88) # _len = int_to_bytes(len(_bytes)) # _bytes = _key88 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # # # Corner Longitude Point 4 (Full) # _bytes = float_to_bytes(round(cornerPointLL[1],4), _domain89, _range89) # _len = int_to_bytes(len(_bytes)) # _bytes = _key89 + _len + _bytes # sizeTotal += len(_bytes) # bufferData += _bytes # Platform Pitch Angle (Full) _bytes = float_to_bytes(round(OSD_pitch, 4), _domain90, _range90) _len = int_to_bytes(len(_bytes)) _bytes = _key90 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # Platform Roll Angle (Full) _bytes = float_to_bytes(round(OSD_roll, 4), _domain91, _range91) _len = int_to_bytes(len(_bytes)) _bytes = _key91 + _len + _bytes sizeTotal += len(_bytes) bufferData += _bytes # set packet header writeData = cle writeData += int_to_bytes(sizeTotal) writeData += bufferData # Write packet f_write = open(end_path, "wb+") f_write.write(writeData) f_write.close() cnt += 1 progress.setValue(cnt) except Exception as e: print("Multiplexer error : " + str(e)) QApplication.restoreOverrideCursor() QApplication.processEvents() progress.setValue(rowCount) self.iface.messageBar().clearWidgets() # We add it to the manager _, name = os.path.split(self.video_file) self.parent.AddFileRowToManager(name, self.video_file, islocal=True, klv_folder=self.klv_folder) # Close dialog self.close() return
def run(self): """Run method that performs all the real work""" layers = self.iface.mapCanvas().layers() layer_list = [] self.dlg.layerComboBox.clear() for layer in layers: layer_list.append(layer.name()) self.dlg.layerComboBox.addItems(layer_list) # TODO: Make the active layer the selected item in combo box aLayer = qgis.utils.iface.activeLayer() # TODO: Add signal to update toleranceSpinBox.suffix (Degrees) from layerComboBox.crs.mapUnits when layer is selected: #my_UnitType = { 0: 'Meters', 1: 'Feet', 2: 'Degrees', 7: 'NauticalMiles', 8: 'Kilometers', 9: 'Yards', 10: 'Miles', 3: 'UnknownUnit'} #suffix = my_UnitType[aLayer.crs().mapUnits()] # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: if self.checkNetworkXModule() < 0: return -4 import networkx as nx layerName = self.dlg.layerComboBox.currentText() try: aLayer = QgsProject.instance().mapLayersByName(layerName)[0] except: self.iface.messageBar().pushMessage("Error", "Failed to load layer!", level=Qgis.Critical) return -1 try: previousEditingMode = True if not aLayer.isEditable(): aLayer.startEditing() #self.iface.messageBar().pushMessage("Info", "Layer " + aLayer.name() + " needs to be in edit mode", level=Qgis.Info) #self.iface.messageBar().pushMessage("Error", "Layer " + aLayer.name() + " needs to be in edit mode", level=Qgis.Critical) #return -2 previousEditingMode = False attrIdx = self.getAttributeIndex(aLayer) if attrIdx < 0: return -3 progressMessageBar = self.iface.messageBar().createMessage("Creating network graph...") progress = QProgressBar() progress.setMaximum(aLayer.featureCount()) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) G = nx.Graph() aLayer.beginEditCommand("Clear group attribute, create graph") # construct undirected graph tolerance = self.dlg.toleranceSpinBox.value() if tolerance == 0: tolerance = 0.000001 count = 0 for feat in aLayer.getFeatures(): count += 1 progress.setValue(count) done = aLayer.changeAttributeValue(feat.id(), attrIdx, -1) geom = feat.geometry() QgsGeometry.convertToSingleType(geom) # QGIS 3.x seems to load single LineString as MultiLineString?? line = geom.asPolyline() for i in range(len(line)-1): G.add_edges_from([((int(line[i][0]/tolerance), int(line[i][1]/tolerance)), (int(line[i+1][0]/tolerance), int(line[i+1][1]/tolerance)), {'fid': feat.id()})]) # first scale by tolerance, then convert to int. Before doing this, there were problems (in NetworkX v1) with floats not equating, thus creating disconnects that weren't there. if count % 100 == 0: QApplication.processEvents() # keep the UI responsive, every 100 features #TODO: check to see if Esc pressed aLayer.endEditCommand() self.iface.messageBar().pushMessage("Finding connected subgraphs, please wait...", level=Qgis.Warning) # WARNING - to highlight the next stage, where we cannot show progress QApplication.processEvents() connected_components = list(nx.connected_component_subgraphs(G)) # this takes a long time. TODO: how to show progress? self.iface.messageBar().pushMessage("Updating group attribute...", level=Qgis.Info) QApplication.processEvents() # gather edges and components to which they belong fid_comp = {} for i, graph in enumerate(connected_components): for edge in graph.edges(data=True): fid_comp[edge[2].get('fid', None)] = i # write output to csv file #with open('C:/Tmp/Components.csv', 'wb') as f: # w = csv.DictWriter(f, fieldnames=['fid', 'group']) # w.writeheader() # for (fid, group) in fid_comp.items(): # w.writerow({'fid': fid, 'group': group}) aLayer.beginEditCommand("Update group attribute") for (fid, group) in fid_comp.items(): done = aLayer.changeAttributeValue(fid, attrIdx, group) aLayer.endEditCommand() groups = list(set(fid_comp.values())) if self.dlg.stylingCheckBox.isChecked(): aLayer.beginEditCommand("Update layer styling") categories = [] firstCat = True for cat in groups: symbol = QgsSymbol.defaultSymbol(aLayer.geometryType()) symbol.setColor(QColor(randint(0,255), randint(0,255), randint(0,255))) if firstCat: firstCat = False else: symbol.setWidth(symbol.width()*5) category = QgsRendererCategory(cat, symbol, "%d" % cat) categories.append(category) field = self.dlg.attributeNameEditBox.text() renderer = QgsCategorizedSymbolRenderer(field, categories) aLayer.setRenderer(renderer) # if self.iface.mapCanvas().isCachingEnabled(): # aLayer.setCacheImage(None) # else: # self.iface.mapCanvas().refresh() aLayer.triggerRepaint() aLayer.endEditCommand() self.iface.messageBar().clearWidgets() self.iface.messageBar().pushMessage("Found main network and %d disconnected islands in layer %s" % (len(groups)-1, aLayer.name()), level=Qgis.Success) aLayer.commitChanges() # if not previousEditingMode: except Exception as e: self.iface.messageBar().pushMessage("Error", "Exception caught: %s. Please report an issue to the author of the plugin." % repr(e), level=Qgis.Critical)
class ThinGreyscaleDialog(QDialog, FORM_CLASS): def __init__(self, iface, parent=None): """Constructor.""" self.iface = iface self.plugin_dir = dirname(__file__) self.THINGREYSCALE = self.tr('ThinGreyscale') self.BROWSE = self.tr('Browse') self.CANCEL = self.tr('Cancel') self.CLOSE = self.tr('Close') self.HELP = self.tr('Help') self.OK = self.tr('OK') self.DEFAULTPROVIDER = 'GTiff' self.DEFAULTEXTENSION = '.tif' self.EXTRAEXTENSION = ' *.tiff' super(ThinGreyscaleDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.showInfo("Connecting UI components") okButton = self.button_box.button(QDialogButtonBox.Ok) okButton.setText(self.OK) cancelButton = self.button_box.button(QDialogButtonBox.Cancel) cancelButton.setText(self.CANCEL) cancelButton.setEnabled(False) closeButton = self.button_box.button(QDialogButtonBox.Close) closeButton.setText(self.CLOSE) browseButton = self.browseButton browseButton.setText(self.BROWSE) self.calcHistPushButton.setEnabled(False) self.listModel = QStandardItemModel(self.levelsListView) self.levelsListView.setModel(self.listModel) self.levelsListView.sizeHintForColumn(20) #self.levelValuesCheckBox.setEnabled(False) # Help button helpButton = self.helpButton helpButton.setText(self.HELP) # Connect signals self.showInfo("Connecting signals") okButton.clicked.connect(self.startWorker) cancelButton.clicked.connect(self.killWorker) closeButton.clicked.connect(self.reject) helpButton.clicked.connect(self.help) browseButton.clicked.connect(self.browse) inpIndexCh = self.inputRaster.currentIndexChanged['QString'] inpIndexCh.connect(self.layerchanged) bandCh = self.bandComboBox.currentIndexChanged['QString'] bandCh.connect(self.bandChanged) #self.iface.legendInterface().itemAdded.connect( # self.layerlistchanged) #self.iface.legendInterface().itemRemoved.connect( # self.layerlistchanged) #QObject.disconnect(self.button_box, SIGNAL("rejected()"), self.reject) self.button_box.rejected.disconnect(self.reject) calchistPr = self.calcHistPushButton.clicked calchistPr.connect(self.calculateHistogram) sugglevPr = self.suggestlevelsPushButton.clicked sugglevPr.connect(self.suggestLevels) addlevPr = self.addlevelPushButton.clicked addlevPr.connect(self.addLevel) dellevPr = self.deletelevelsPushButton.clicked dellevPr.connect(self.removeLevel) maxvalCh = self.maxValueSpinBox.valueChanged maxvalCh.connect(self.minmaxvalueChanged) maxvalFi = self.maxValueSpinBox.editingFinished maxvalFi.connect(self.minmaxvalueEdFinished) minvalCh = self.minValueSpinBox.valueChanged minvalCh.connect(self.minmaxvalueChanged) minvalFi = self.minValueSpinBox.editingFinished minvalFi.connect(self.minmaxvalueEdFinished) # Set instance variables #self.mem_layer = None self.worker = None self.inputlayerid = None self.inputlayer = None self.layerlistchanging = False self.minvalue = 1 self.inputrasterprovider = None self.histobins = 50 self.setupScene = QGraphicsScene(self) self.histoGraphicsView.setScene(self.setupScene) # Is the layer band of an integer type self.intband = False self.histogramAvailable = False self.histo = None self.histopadding = 1 def startWorker(self): """Initialises and starts the worker thread.""" try: layerindex = self.inputRaster.currentIndex() layerId = self.inputRaster.itemData(layerindex) inputlayer = QgsProject.instance().mapLayer(layerId) #inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId) if inputlayer is None: self.showError(self.tr('No input layer defined')) return # create a reference to the layer that is being processed # (for use when creating the resulting raster layer) self.thinninglayer = inputlayer self.levels = [] #self.levelsListView.selectAll() #selected = self.levelsListView.selectedIndexes() if self.levelsListView.model().rowCount() == 0: self.showInfo("Levels must be specified!") return for i in range(self.levelsListView.model().rowCount()): levelstring = self.levelsListView.model().item(i).text() #for i in selected: # levelstring = self.levelsListView.model().itemData(i)[0] if self.intband: self.levels.append(int(levelstring)) else: self.levels.append(float(levelstring)) #self.levelsListView.clearSelection() # create a new worker instance worker = Worker(inputlayer, self.levels, self.intband) # configure the QgsMessageBar msgBar = self.iface.messageBar().createMessage( self.tr('Skeletonising'), '') self.aprogressBar = QProgressBar() self.aprogressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) acancelButton = QPushButton() acancelButton.setText(self.CANCEL) acancelButton.clicked.connect(self.killWorker) msgBar.layout().addWidget(self.aprogressBar) msgBar.layout().addWidget(acancelButton) # Has to be popped after the thread has finished (in # workerFinished). self.iface.messageBar().pushWidget(msgBar, Qgis.Info) self.messageBar = msgBar # start the worker in a new thread thread = QThread(self) worker.moveToThread(thread) worker.finished.connect(self.workerFinished) worker.error.connect(self.workerError) worker.status.connect(self.workerInfo) worker.progress.connect(self.progressBar.setValue) worker.progress.connect(self.aprogressBar.setValue) worker.iterprogress.connect(self.iterProgressBar.setValue) thread.started.connect(worker.run) thread.start() self.thread = thread self.worker = worker self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.button_box.button(QDialogButtonBox.Close).setEnabled(False) self.button_box.button(QDialogButtonBox.Cancel).setEnabled(True) except: import traceback self.showError(traceback.format_exc()) else: pass def workerFinished(self, ok, ret): """Handles the output from the worker and cleans up after the worker has finished.""" # clean up the worker and thread self.showInfo("Handling the result") self.worker.deleteLater() self.thread.quit() self.thread.wait() self.thread.deleteLater() # remove widget from message bar (pop) self.iface.messageBar().popWidget(self.messageBar) if ok and ret is not None: #self.showInfo("Ret: "+str(ret[10,])) # Transformation: self.minx = self.thinninglayer.extent().xMinimum() self.maxx = self.thinninglayer.extent().xMaximum() self.miny = self.thinninglayer.extent().yMinimum() self.maxy = self.thinninglayer.extent().yMaximum() self.rows = self.thinninglayer.height() self.cols = self.thinninglayer.width() self.xres = (self.maxx - self.minx) / float(self.cols) self.yres = (self.maxy - self.miny) / float(self.rows) geotransform = (self.minx, self.xres, 0, self.maxy, 0, -self.yres) try: format = self.DEFAULTPROVIDER driver = gdal.GetDriverByName(format) NOVALUE = 0 metadata = driver.GetMetadata() fileName = self.outputRaster.text() if self.outputRaster.text() == "": self.showInfo("No output file specified, " + "creating a temporary file") # Get a temporary file fileName = mktemp(prefix='greyskel', suffix=self.DEFAULTEXTENSION) fileInfo = QFileInfo(fileName) filepath = fileInfo.absolutePath() baseName = fileInfo.baseName() suffix = fileInfo.suffix() thisfilename = filepath + baseName + '.' + suffix thisfilename = fileName self.showInfo("File name: " + thisfilename) gdaldatatype = gdal.GDT_Byte skelmatrix = None if self.levelValuesCheckBox.isChecked(): # Transform the pixel values back to the original # level values my_dict = {} # Add zero to handle the "empty" pixels my_dict[0] = 0 for i in range(len(self.levels)): my_dict[i + 1] = self.levels[i] skelmatrix = np.vectorize(my_dict.__getitem__, otypes=[np.float])(ret) gdaldatatype = gdal.GDT_Int32 if not self.intband: gdaldatatype = gdal.GDT_Float32 else: skelmatrix = ret outDataset = driver.Create(thisfilename, self.cols, self.rows, 1, gdaldatatype) if self.thinninglayer.dataProvider().crs() is not None: srs = self.thinninglayer.dataProvider().crs() outDataset.SetProjection(srs.toWkt().encode('ascii', 'ignore')) skeletonband = outDataset.GetRasterBand(1) skeletonband.WriteArray(skelmatrix) skeletonband.SetNoDataValue(NOVALUE) #stats = skeletonband.GetStatistics(False, True) #skeletonband.SetStatistics(stats[0], stats[1], # stats[2], stats[3]) outDataset.SetGeoTransform(geotransform) outDataset = None # To close the file # report the result rlayer = QgsRasterLayer(thisfilename, baseName) self.layerlistchanging = True #QgsMapLayerRegistry.instance().addMapLayer(rlayer) QgsProject.instance().addMapLayer(rlayer) self.layerlistchanging = False except: import traceback self.showError("Can't write the skeleton file: %s" % self.outputRaster.text() + ' - ' + traceback.format_exc()) okb = self.button_box.button(QDialogButtonBox.Ok) okb.setEnabled(True) closb = self.button_box.button(QDialogButtonBox.Close) closb.setEnabled(True) cancb = self.button_box.button(QDialogButtonBox.Cancel) cancb.setEnabled(False) return QgsMessageLog.logMessage(self.tr('ThinGreyscale finished'), self.THINGREYSCALE, Qgis.Info) else: # notify the user that something went wrong if not ok: self.showError(self.tr('Aborted') + '!') else: self.showError(self.tr('No skeleton created') + '!') self.progressBar.setValue(0.0) #self.aprogressBar.setValue(0.0) self.iterProgressBar.setValue(0.0) self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) self.button_box.button(QDialogButtonBox.Close).setEnabled(True) self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False) def workerError(self, exception_string): """Report an error from the worker.""" #QgsMessageLog.logMessage(self.tr('Worker failed - exception') + # ': ' + str(exception_string), # self.THINGREYSCALE, # QgsMessageLog.CRITICAL) self.showError(exception_string) def workerInfo(self, message_string): """Report an info message from the worker.""" QgsMessageLog.logMessage(self.tr('Worker') + ': ' + message_string, self.THINGREYSCALE, Qgis.Info) def layerchanged(self, number=0): """Do the necessary updates after a layer selection has been changed.""" self.showInfo("Layer changed") # If the layer list is being updated, don't do anything if self.layerlistchanging: return layerindex = self.inputRaster.currentIndex() layerId = self.inputRaster.itemData(layerindex) self.inputlayerid = layerId #self.inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId) self.inputlayer = QgsProject.instance().mapLayer(layerId) if self.inputlayer is not None: self.inputrasterprovider = self.inputlayer.dataProvider() self.bandComboBox.clear() bandcount = self.inputlayer.bandCount() #self.showInfo("Layer bandcount: "+str(bandcount)) for i in range(bandcount): self.bandComboBox.addItem(self.inputlayer.bandName(i + 1), i) #self.showInfo("Band " + str(i) + ": " + # self.inputlayer.bandName(i+1)) # Check if the driver supports Create() or CreateCopy() #gdalmetadata = self.inputlayer.metadata() #self.showInfo("Layer metadata: " + # str(gdalmetadata.encode('utf-8'))) #provstring = '<p>GDAL provider</p>\n' #providerpos = gdalmetadata.find(provstring) #brpos = gdalmetadata.find('<br>', providerpos + len(provstring)) #self.gdalprovider = gdalmetadata[int(providerpos + # len(provstring)):int(brpos)] #self.showInfo('GDAL provider: '+self.gdalprovider) #drivername = self.gdalprovider.encode('ascii', 'ignore') #theDriver = gdal.GetDriverByName(drivername) #if theDriver is None: # self.showInfo("Unable to get the raster driver") #else: #data theMetadata = theDriver.GetMetadata() #self.showInfo("Driver metadata: "+str(theMetadata)) #if ((gdal.DCAP_CREATE in theMetadata) and # theMetadata[gdal.DCAP_CREATE] == 'YES'): # self.canCreate = True #if (theMetadata.has_key(gdal.DCAP_CREATECOPY) and #if ((gdal.DCAP_CREATECOPY in theMetadata) and # theMetadata[gdal.DCAP_CREATECOPY] == 'YES'): # self.canCreateCopy = True #self.showInfo('raster provider type: ' + # str(self.inputlayer.providerType())) # Determine the file suffix #self.gdalext = "" #if gdal.DMD_EXTENSION in theMetadata: # self.gdalext = "." + theMetadata[gdal.DMD_EXTENSION] #else: # self.showInfo("No extension available in GDAL metadata") # by parsing the layer metadata looking for # "Dataset Description" #descstring = 'Dataset Description</p>\n<p>' #descpos = gdalmetadata.find(descstring) #ppos = gdalmetadata.find('</p>',descpos+len(descstring)) #filename = gdalmetadata[descpos+len(descstring):ppos] #self.gdalext = splitext(filename)[1] #self.showInfo('GDAL extension: '+self.gdalext) # Determine the datatype #datatypestring = 'Data Type</p>\n<p>' #datatypepos = gdalmetadata.find(datatypestring) #ppos = gdalmetadata.find('</p>', # datatypepos + len(datatypestring)) #datatypedesc = gdalmetadata[datatypepos + # len(datatypestring):ppos] #shortdesc = datatypedesc.split()[0] #self.showInfo('GDAL data type: GDT_'+shortdesc) # Call the findGdalDatatype function #self.findGdalDatatype(shortdesc) # self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) self.calcHistPushButton.setEnabled(True) self.suggestlevelsPushButton.setEnabled(True) def bandChanged(self): band = self.bandComboBox.currentIndex() + 1 self.showInfo("Band changed: " + str(band)) statistics = self.inputrasterprovider.bandStatistics(band) #self.showInfo("Band statistics: " + str(statistics.minimumValue) + # " - " + str(statistics.maximumValue) + # " - " + str(statistics.mean)) self.bandmin = statistics.minimumValue self.bandmax = statistics.maximumValue dt = self.inputrasterprovider.dataType(band) # Integer data type if (dt == Qgis.Byte or dt == Qgis.UInt16 or dt == Qgis.Int16 or dt == Qgis.UInt32 or dt == Qgis.Int32): self.intband = True self.minValueSpinBox.setDecimals(0) self.maxValueSpinBox.setDecimals(0) self.levelSpinBox.setDecimals(0) self.bandMinLabel.setText(str(int(statistics.minimumValue))) self.bandMaxLabel.setText(str(int(statistics.maximumValue))) else: self.intband = False self.minValueSpinBox.setDecimals(5) self.maxValueSpinBox.setDecimals(5) self.levelSpinBox.setDecimals(5) minlabtext = "{0:.5f}".format(statistics.minimumValue) self.bandMinLabel.setText(minlabtext) maxlabtext = "{0:.5f}".format(statistics.maximumValue) self.bandMaxLabel.setText(maxlabtext) #self.minValueSpinBox.setMinimum(statistics.minimumValue) self.maxValueSpinBox.setMinimum(statistics.minimumValue) #self.minValueSpinBox.setMaximum(statistics.maximumValue) self.maxValueSpinBox.setMaximum(statistics.maximumValue) #self.minValueSpinBox.setValue(statistics.minimumValue) if not (statistics.statsGathered & statistics.Mean): bandmean = (statistics.minimumValue + statistics.maximumValue) / 2 else: #self.showInfo("statsgathered: " + str(statistics.statsGathered)) bandmean = statistics.mean if self.intband: self.minValueSpinBox.setValue(int(ceil(bandmean))) else: self.minValueSpinBox.setValue(bandmean) self.maxValueSpinBox.setValue(statistics.maximumValue) self.histMinValue.setText(str(statistics.minimumValue)) self.histMaxValue.setText(str(statistics.maximumValue)) self.levelSpinBox.setMinimum(statistics.minimumValue) self.levelSpinBox.setMaximum(statistics.maximumValue) self.histogramAvailable = False #if self.inputrasterprovider.hasStatistics(band): #if statistics.statsGathered: #histogram = statistics.histogramVector #self.showInfo("Histogram: " + str(histogram)) #range = min to max #np.histogram(band, 50, range) def minmaxvalueChanged(self): #if self.minValueSpinBox is None: # return minvalue = self.minValueSpinBox.value() #if minvalue is None: # return #if self.maxValueSpinBox is None: # return maxvalue = self.maxValueSpinBox.value() #if maxvalue is None: # return if isnan(maxvalue) or isnan(minvalue): return self.showInfo("minvalue: " + str(minvalue) + " Maxvalue: " + str(maxvalue)) #if self.intband: # minvalue = int(minvalue) # maxvalue = int(maxvalue) if abs(maxvalue - minvalue) < 0.00001: #if maxvalue == maxvalue: self.calcHistPushButton.setEnabled(False) else: self.calcHistPushButton.setEnabled(True) # Update the min and max value spinboxes self.minValueSpinBox.setMaximum(maxvalue) self.maxValueSpinBox.setMinimum(minvalue) self.minValueSpinBox.setMinimum(self.bandmin) def minmaxvalueEdFinished(self): minvalue = self.minValueSpinBox.value() maxvalue = self.maxValueSpinBox.value() if self.intband: minvalue = int(minvalue) maxvalue = int(maxvalue) self.showInfo("minvalue: " + str(minvalue) + " Maxvalue: " + str(maxvalue)) # Update the spin box for adding levels self.levelSpinBox.setMinimum(minvalue) self.levelSpinBox.setMaximum(maxvalue) if self.levelSpinBox.value() < minvalue: self.levelSpinBox.setValue(minvalue) if self.levelSpinBox.value() > maxvalue: self.levelSpinBox.setValue(maxvalue) # Update the min and max value spinboxes self.minValueSpinBox.setMaximum(maxvalue) self.maxValueSpinBox.setMinimum(minvalue) # Adjust the levels: i = 0 while self.levelsListView.model().item(i): #for i in range(self.levelsListView.model().rowCount()): #self.showInfo("Element: " + # str(self.levelsListView.model().item(i).text())) #continue value = float(self.levelsListView.model().item(i).text()) if value < minvalue: if i == 0: self.levelsListView.model().item(i).setText(str(minvalue)) i = i + 1 else: self.levelsListView.model().removeRow(i) elif value > maxvalue: if i == self.levelsListView.model().rowCount() - 1: self.levelsListView.model().item(i).setText(str(maxvalue)) i = i + 1 else: self.levelsListView.model().removeRow(i) else: i = i + 1 self.drawHistogram() def calculateHistogram(self): self.showInfo("Calculating histogram...") if self.inputlayer is None: return self.showInfo("Calculating histogram...") # Check if there is only one value myrange = (self.minValueSpinBox.value(), self.maxValueSpinBox.value()) self.inputextent = self.inputlayer.extent() self.inputrdp = self.inputlayer.dataProvider() width = self.inputlayer.width() height = self.inputlayer.height() if width == 0 or height == 0: self.showInfo("Image has zero width or height") return extwidth = self.inputextent.width() extheight = self.inputextent.height() # Read the raster block and get the maximum value rasterblock = self.inputrdp.block(1, self.inputextent, width, height) # Create a numpy array version of the image imageMat = np.zeros((height, width), dtype=np.float16) # This one takes a lot of time! for row in range(height): for column in range(width): imageMat[row, column] = rasterblock.value(row, column) self.showInfo("Image: " + str(height) + ", " + str(width) + " - " + str(imageMat[row, column])) self.histo = np.histogram(imageMat, self.histobins, myrange) #relevantpixels = imageMat[np.where(imageMat >= bandval)] minlevel = float(self.bandMinLabel.text()) relevantpixels = imageMat[np.where(imageMat >= minlevel)] #self.showInfo("Histogram: " + str(self.histo)) nanpercentage = 100.0 - 100.0 * len(relevantpixels) / (width * height) self.bandNANLabel.setText("{0:.1f}".format(nanpercentage)) #self.showInfo("Percentage NAN: " + str(100.0 - 100.0 * # len(relevantpixels) / (width * height))) #self.showInfo("First element: " + str(self.histo[0])) #self.showInfo("First element, first: " + str(self.histo[0][0])) #self.showInfo("First element, second: " + str(self.histo[0][1])) self.histMinValue.setText(str(self.minValueSpinBox.value())) self.histMaxValue.setText(str(self.maxValueSpinBox.value())) if self.intband: self.histMinValue.setText(str(int(self.minValueSpinBox.value()))) self.histMaxValue.setText(str(int(self.maxValueSpinBox.value()))) self.histogramAvailable = True self.drawHistogram() def drawHistogram(self): #if self.inputlayer is None: # return self.showInfo("Drawing histogram...") viewprect = QRectF(self.histoGraphicsView.viewport().rect()) self.histoGraphicsView.setSceneRect(viewprect) self.setupScene.clear() self.setupScene.update() histbottom = self.histoGraphicsView.sceneRect().bottom() histtop = self.histoGraphicsView.sceneRect().top() left = self.histoGraphicsView.sceneRect().left() + self.histopadding right = self.histoGraphicsView.sceneRect().right() - self.histopadding histheight = histbottom - histtop histwidth = right - left step = 1.0 * histwidth / self.histobins maxlength = histheight padding = 1 ll = QPoint(self.histopadding - 1, histheight - padding) start = QPointF(self.histoGraphicsView.mapToScene(ll)) # Check if there is only one value #myrange = (self.minValueSpinBox.value(),self.maxValueSpinBox.value()) if self.histogramAvailable: maxvalue = 0.0 for i in range(len(self.histo[0])): if self.histo[0][i] > maxvalue: maxvalue = self.histo[0][i] if maxvalue == 0: return self.maxBinNumber.setText(str(maxvalue)) # Create the histogram: #self.showInfo("maxvalue: " + str(maxvalue)) #self.showInfo("maxlength: " + str(maxlength)) #self.showInfo("step: " + str(step)) for i in range(self.histobins): binnumber = self.histo[0][i] if binnumber == 0: continue height = (1.0 * self.histo[0][i] / maxvalue * (maxlength - padding)) rectangle = QGraphicsRectItem(start.x() + step * i, start.y(), step, -height) rectangle.setPen(QPen(QColor(102, 102, 102))) rectangle.setBrush(QBrush(QColor(240, 240, 240))) self.setupScene.addItem(rectangle) #self.showInfo(str(i) + ": " + str(height)) #if self.levelsListView.model().rowCount() > 0: # Add lines for the levels minvalue = float(self.histMinValue.text()) maxvalue = float(self.histMaxValue.text()) datarange = maxvalue - minvalue if datarange == 0: return i = 0 while self.levelsListView.model().item(i): #self.showInfo("Element: " + # str(self.levelsListView.model().item(i).text())) #continue value = float(self.levelsListView.model().item(i).text()) xvalue = start.x() + histwidth * (value - minvalue) / datarange line = QGraphicsLineItem(xvalue, 0, xvalue, histheight) if i == 0 or i == (self.levelsListView.model().rowCount() - 1): line.setPen(QPen(QColor(204, 0, 0))) else: line.setPen(QPen(QColor(0, 204, 0))) self.setupScene.addItem(line) i = i + 1 def suggestLevels(self): self.listModel.clear() self.showInfo("Suggesting levels") levels = self.levelsSpinBox.value() startvalue = self.minValueSpinBox.value() endvalue = self.maxValueSpinBox.value() increment = (endvalue - startvalue) / levels for i in range(levels + 1): value = startvalue + increment * i if self.intband: value = int(value) item = QStandardItem(str(value)) self.listModel.appendRow(item) self.drawHistogram() def addLevel(self): newvalue = self.levelSpinBox.value() if self.intband: newvalue = int(newvalue) for i in range(self.listModel.rowCount()): # Check if the value is already in the list if self.listModel.item(i).text() == str(newvalue): return else: # Maintain a sorted list of distances if (float(self.listModel.item(i).text()) > float(str(newvalue))): item = QStandardItem(str(newvalue)) self.listModel.insertRow(i, item) self.drawHistogram() return item = QStandardItem(str(newvalue)) self.listModel.appendRow(item) #if self.histogramAvailable: # addLevelsToHistogram() self.drawHistogram() def removeLevel(self): self.levelsListView.setUpdatesEnabled(False) indexes = self.levelsListView.selectedIndexes() indexes.sort() for i in range(len(indexes) - 1, -1, -1): self.listModel.removeRow(indexes[i].row()) self.levelsListView.setUpdatesEnabled(True) #if self.histogramAvailable: # removeLevelFromHistogram() self.drawHistogram() def layerlistchanged(self): self.layerlistchanging = True self.showInfo("Layer list changed") # Repopulate the input layer combo box # Save the currently selected input layer inputlayerid = self.inputlayerid self.inputRaster.clear() for alayer in self.iface.legendInterface().layers(): if alayer.type() == QgsMapLayer.RasterLayer: gdalmetadata = alayer.metadata() # Skip WMS layers WMSstring = 'Web Map Service' wmspos = gdalmetadata.find(WMSstring) if wmspos != -1: continue self.inputRaster.addItem(alayer.name(), alayer.id()) # Set the previous selection for i in range(self.inputRaster.count()): if self.inputRaster.itemData(i) == inputlayerid: self.inputRaster.setCurrentIndex(i) self.layerlistchanging = False #self.updateui() def updateui(self): """Do the necessary updates after a layer selection has been changed.""" #if self.layerlistchanged: # return #self.outputRaster.setText(self.inputRaster.currentText() + # '_' + 'thinned') layerindex = self.inputRaster.currentIndex() layerId = self.inputRaster.itemData(layerindex) #inputlayer = QgsMapLayerRegistry.instance().mapLayer(layerId) inputlayer = QgsProject.instance().mapLayer(layerId) if inputlayer is not None: pass else: pass def findGdalDatatype(self, shortdesc): gdaldatatype = None # // Unknown or unspecified type # GDT_Unknown = GDALDataType(C.GDT_Unknown) if shortdesc == 'Unknown': gdaldatatype = gdal.GDT_Unknown # // Eight bit unsigned integer # GDT_Byte = GDALDataType(C.GDT_Byte) elif shortdesc == 'Byte': gdaldatatype = gdal.GDT_Byte # // Sixteen bit unsigned integer # GDT_UInt16 = GDALDataType(C.GDT_UInt16) elif shortdesc == 'UInt16': gdaldatatype = gdal.GDT_UInt16 # // Sixteen bit signed integer # GDT_Int16 = GDALDataType(C.GDT_Int16) elif shortdesc == 'Int16': gdaldatatype = gdal.GDT_Int16 # // Thirty two bit unsigned integer # GDT_UInt32 = GDALDataType(C.GDT_UInt32) elif shortdesc == 'UInt32': gdaldatatype = gdal.GDT_UInt32 # // Thirty two bit signed integer # GDT_Int32 = GDALDataType(C.GDT_Int32) elif shortdesc == 'Int32': gdaldatatype = gdal.GDT_Int32 # // Thirty two bit floating point # GDT_Float32 = GDALDataType(C.GDT_Float32) elif shortdesc == 'Float32': gdaldatatype = gdal.GDT_Float32 # // Sixty four bit floating point # GDT_Float64 = GDALDataType(C.GDT_Float64) elif shortdesc == 'Float64': gdaldatatype = gdal.GDT_Float64 # // Complex Int16 # GDT_CInt16 = GDALDataType(C.GDT_CInt16) elif shortdesc == 'CInt16': gdaldatatype = gdal.CInt16 # // Complex Int32 # GDT_CInt32 = GDALDataType(C.GDT_CInt32) elif shortdesc == 'CInt32': gdaldatatype = gdal.CInt32 # // Complex Float32 # GDT_CFloat32 = GDALDataType(C.GDT_CFloat32) elif shortdesc == 'CFloat32': gdaldatatype = gdal.CFloat32 # // Complex Float64 # GDT_CFloat64 = GDALDataType(C.GDT_CFloat64) elif shortdesc == 'CFloat64': gdaldatatype = gdal.CFloat64 # // maximum type # + 1 # GDT_TypeCount = GDALDataType(C.GDT_TypeCount) elif shortdesc == 'TypeCount': gdaldatatype = gdal.TypeCount self.gdaldatatype = gdaldatatype def killWorker(self): """Kill the worker thread.""" if self.worker is not None: QgsMessageLog.logMessage(self.tr('Killing worker'), self.THINGREYSCALE, Qgis.Info) self.worker.kill() def showError(self, text): """Show an error.""" self.iface.messageBar().pushMessage(self.tr('Error'), text, level=QgsMessageBar.CRITICAL, duration=3) QgsMessageLog.logMessage('Error: ' + text, self.THINGREYSCALE, QgsMessageLog.CRITICAL) def showWarning(self, text): """Show a warning.""" self.iface.messageBar().pushMessage(self.tr('Warning'), text, level=QgsMessageBar.WARNING, duration=2) QgsMessageLog.logMessage('Warning: ' + text, self.THINGREYSCALE, QgsMessageLog.WARNING) def showInfo(self, text): """Show info.""" self.iface.messageBar().pushMessage(self.tr('Info'), text, level=Qgis.Info, duration=2) QgsMessageLog.logMessage('Info: ' + text, self.THINGREYSCALE, Qgis.Info) # def help(self): # #QDesktopServices.openUrl(QUrl.fromLocalFile(self.plugin_dir + # "/help/build/html/index.html")) # QDesktopServices.openUrl(QUrl.fromLocalFile(self.plugin_dir + # "/help/index.html")) # #showPluginHelp() def tr(self, message): """Get the translation for a string using Qt translation API. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ return QCoreApplication.translate('ThinGreyScaleDialog', message) def browse(self): settings = QSettings() key = '/UI/lastShapefileDir' outDir = settings.value(key) home = outDir #outDir = expanduser("~") #filter = (self.DEFAULTPROVIDER + " (*" + # self.DEFAULTEXTENSION + ");;All files (*)") filter = (self.DEFAULTPROVIDER + " (*" + self.DEFAULTEXTENSION + self.EXTRAEXTENSION + ")") #if (self.gdalprovider != self.DEFAULTPROVIDER and # (self.canCreateCopy or # self.canCreate)): # filter = (self.gdalprovider + " (*" + self.gdalext + # ");;" + filter) outFilePath = QFileDialog.getSaveFileName(self, 'Specify file name for skeleton', outDir, filter) outFilePath = unicode(outFilePath) if outFilePath: root, ext = splitext(outFilePath) if ext.lower() != '.tif' and ext.lower() != '.tiff': outFilePath = '%s.tif' % outFilePath outDir = dirname(outFilePath) settings.setValue(key, outDir) # (self.canCreateCopy or self.canCreate): # fileName = splitext(str(fileName))[0]+self.gdalext self.outputRaster.setText(outFilePath) # Overriding def resizeEvent(self, event): #self.showInfo("resizeEvent") self.calculateHistogram() def help(self): #QDesktopServices.openUrl(QUrl.fromLocalFile( # self.plugin_dir + "/help/html/index.html")) showPluginHelp(None, "help/html/index") # Implement the accept method to avoid exiting the dialog when # starting the work def accept(self): """Accept override.""" pass # Implement the reject method to have the possibility to avoid # exiting the dialog when cancelling def reject(self): """Reject override.""" # exit the dialog QDialog.reject(self)
def processRequest(self): #iface.messageBar().pushMessage("BC TRO API", "Processing Request", level=0) progressMessageBar = iface.messageBar().createMessage("Processing Request...") progress = QProgressBar() progress.setMaximum(100) progress.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) #API Code here apilayer = 'bctroapi' maplayerName = "BC TRO" layers_names = [] lopen = False for layer in QgsProject.instance().mapLayers().values(): if layer.name() == maplayerName: lopen = True layers_names.append(layer.name()) progress.setValue(10) #Params from dialog troformat = str(self.dlg.Formatcombobox.currentText()) area = self.dlg.AreaTextBox.text() radius = "{}".format(self.dlg.RadiusSlider.value()) x = self.dlg.Xtextbox.text() y = self.dlg.Ytextbox.text() epsg = str(self.dlg.Projectioncombobox.currentText()) #self.iface.mapCanvas().mapSettings().destinationCrs().authid() api_token = self.dlg.APIKeyTextBox.text() progress.setValue(20) time.sleep(0.5) #Set EPSG value as expected by TRO API if "27700" in epsg: epsg = "27700" elif "4326" in epsg: epsg = "4326" elif "3857" in epsg: epsg = "3857" else: return; progress.setValue(25) #Construct request parameters payload = {'api_token':api_token,'epsg': epsg, 'x': x, 'y': y, 'radius': radius} print ("API Payload: {}".format(payload)) #Set Endpoint from troformat if troformat == "TRO-D": url = 'https://dev.trafficorders.uk/tro/v1/trod' else: url = 'https://dev.trafficorders.uk/tro/v1/{}'.format(troformat.lower()) progress.setValue(30) # Send Request print ("Sending Request...") try: response = requests.get(url,params=payload) print ("Normal Request Success") except: print ("Normal Request Failed") """try: response = requests.get(url,params=payload, verify ='IONOS_trafficorders.uk.pem') print ("PEM File Request Success") except: print ("PEM File Request Failed")""" try: response = requests.get(url,params=payload, verify = False) print ("Verify Request Success") except: print ("Verify Request Failed") QMessageBox.critical(self.iface.mainWindow(), "BC TRO API error", "The request processed unsuccesfully!\n\n" "Error Code:\n" "Unable to send GET request") iface.messageBar().clearWidgets() return progress.setValue(50) print(response.url) print("Status: {}".format(response.status_code)) #Check request status for error if response.status_code != 200: QMessageBox.critical(self.iface.mainWindow(), "BC TRO API error", "The request processed unsuccesfully!\n\n" "Error Code:\n" "{}".format(response.status_code)) iface.messageBar().clearWidgets() return progress.setValue(60) #Convert JSON to Geojson r_json = self.geojsontojson(response.json(),troformat) progress.setValue(70) #Save Converted Geojson to file path_to_tro_layer = os.path.join(self.temp_dir,"bcnativedata.geojson") print ("Write Geojson...") with open(path_to_tro_layer, "w") as outfile: outfile.write(r_json) progress.setValue(80) ExitMessage = '' #Map geojson file #print("{}".format(self.currentformat)) #print(troformat) if not lopen: #Open file print ("Open Geojson...") if not self.addTROlayers(path_to_tro_layer,epsg,maplayerName,troformat): ExitMessage = 'Layer Failed' else: self.currentformat = troformat ExitMessage = 'Layer added to map' elif self.currentformat != troformat: print ("Rebuild table format...") #Remove Layer vlayers = QgsProject.instance().mapLayersByName(maplayerName) for vlayer in vlayers: QgsProject.instance().removeMapLayer(vlayer.id()) #Add - Rebuilding Table structure if not self.addTROlayers(path_to_tro_layer,epsg,maplayerName,troformat): ExitMessage = 'Layer Failed' else: self.currentformat = troformat ExitMessage = 'Layer added to map - Format change' else: print ("Reload Geojson...") #Refresh Layer vlayers = QgsProject.instance().mapLayersByName(maplayerName) for vlayer in vlayers: vlayer.dataProvider().reloadData() vlayer.triggerRepaint() ExitMessage = 'Layer refreshed' progress.setValue(100) #Show Exit message iface.messageBar().clearWidgets() iface.messageBar().pushMessage("BC TRO API", ExitMessage, level=3)
class NNJoinDialog(QDialog, FORM_CLASS): def __init__(self, iface, parent=None): """Constructor.""" self.iface = iface self.plugin_dir = dirname(__file__) # Some translated text (to enable reuse) self.NNJOIN = self.tr('NNJoin') self.CANCEL = self.tr('Cancel') self.CLOSE = self.tr('Close') self.HELP = self.tr('Help') self.OK = self.tr('OK') super(NNJoinDialog, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html#\ # widgets-and-dialogs-with-auto-connect self.setupUi(self) # Modify ui components okButton = self.button_box.button(QDialogButtonBox.Ok) okButton.setText(self.OK) self.cancelButton = self.button_box.button(QDialogButtonBox.Cancel) self.cancelButton.setText(self.CANCEL) closeButton = self.button_box.button(QDialogButtonBox.Close) closeButton.setText(self.CLOSE) self.approximate_input_geom_cb.setCheckState(Qt.Unchecked) self.approximate_input_geom_cb.setVisible(False) stytxt = "QCheckBox:checked {color: red; background-color: white}" self.approximate_input_geom_cb.setStyleSheet(stytxt) self.use_indexapprox_cb.setCheckState(Qt.Unchecked) self.use_indexapprox_cb.setVisible(False) self.use_indexapprox_cb.setStyleSheet(stytxt) self.use_index_nonpoint_cb.setCheckState(Qt.Unchecked) self.use_index_nonpoint_cb.setVisible(False) self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False) # Help button helpButton = self.helpButton helpButton.setText(self.HELP) # Connect signals okButton.clicked.connect(self.startWorker) # self.cancelButton.clicked.connect(self.killWorker) closeButton.clicked.connect(self.reject) helpButton.clicked.connect(self.help) self.approximate_input_geom_cb.stateChanged['int'].connect( self.useindexchanged) self.use_indexapprox_cb.stateChanged['int'].connect( self.useindexchanged) self.use_index_nonpoint_cb.stateChanged['int'].connect( self.useindexchanged) inpIndexCh = self.inputVectorLayer.currentIndexChanged['QString'] inpIndexCh.connect(self.layerchanged) joinIndexCh = self.joinVectorLayer.currentIndexChanged['QString'] # joinIndexCh.connect(self.layerchanged) joinIndexCh.connect(self.joinlayerchanged) # self.distancefieldname.editingFinished.connect(self.fieldchanged) self.distancefieldname.textChanged.connect(self.distfieldchanged) self.joinPrefix.editingFinished.connect(self.fieldchanged) theRegistry = QgsProject.instance() theRegistry.layersAdded.connect(self.layerlistchanged) theRegistry.layersRemoved.connect(self.layerlistchanged) # Disconnect the cancel button to avoid exiting. self.button_box.rejected.disconnect(self.reject) # Set instance variables self.mem_layer = None self.worker = None self.inputlayerid = None self.joinlayerid = None self.layerlistchanging = False def startWorker(self): """Initialises and starts the worker thread.""" try: layerindex = self.inputVectorLayer.currentIndex() layerId = self.inputVectorLayer.itemData(layerindex) inputlayer = QgsProject.instance().mapLayer(layerId) if inputlayer is None: self.showError(self.tr('No input layer defined')) return joinindex = self.joinVectorLayer.currentIndex() joinlayerId = self.joinVectorLayer.itemData(joinindex) joinlayer = QgsProject.instance().mapLayer(joinlayerId) if joinlayer is None: self.showError(self.tr('No join layer defined')) return if joinlayer is not None and joinlayer.crs().isGeographic(): self.showWarning('Geographic CRS used for the join layer -' ' distances will be in decimal degrees!') outputlayername = self.outputDataset.text() approximateinputgeom = self.approximate_input_geom_cb.isChecked() joinprefix = self.joinPrefix.text() # useindex = True useindex = self.use_index_nonpoint_cb.isChecked() useindexapproximation = self.use_indexapprox_cb.isChecked() distancefieldname = self.distancefieldname.text() selectedinputonly = self.inputSelected.isChecked() selectedjoinonly = self.joinSelected.isChecked() excludecontaining = self.exclude_containing_poly_cb.isChecked() # create a new worker instance self.worker = Worker(inputlayer, joinlayer, outputlayername, joinprefix, distancefieldname, approximateinputgeom, useindexapproximation, useindex, selectedinputonly, selectedjoinonly, excludecontaining) # configure the QgsMessageBar msgBar = self.iface.messageBar().createMessage( self.tr('Joining'), '') self.aprogressBar = QProgressBar() self.aprogressBar.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) acancelButton = QPushButton() acancelButton.setText(self.CANCEL) # acancelButton.clicked.connect(self.killWorker) msgBar.layout().addWidget(self.aprogressBar) msgBar.layout().addWidget(acancelButton) # Has to be popped after the thread has finished (in # workerFinished). self.iface.messageBar().pushWidget(msgBar, Qgis.Info) # self.iface.messageBar().INFO) self.messageBar = msgBar # start the worker in a new thread self.mythread = QThread(self) # QT requires the "self" self.worker.status.connect(self.workerInfo) self.worker.progress.connect(self.progressBar.setValue) self.worker.progress.connect(self.aprogressBar.setValue) self.worker.finished.connect(self.workerFinished) self.worker.error.connect(self.workerError) # Must come before movetothread: self.cancelButton.clicked.connect(self.worker.kill) acancelButton.clicked.connect(self.worker.kill) self.worker.finished.connect(self.worker.deleteLater) self.worker.finished.connect(self.mythread.quit) # self.worker.error.connect(self.worker.deleteLater) # self.worker.error.connect(self.mythread.quit) # Must come before thread.started.connect!: self.worker.moveToThread(self.mythread) self.mythread.started.connect(self.worker.run) self.mythread.finished.connect(self.mythread.deleteLater) self.mythread.start() # self.thread = thread # self.worker = worker self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.button_box.button(QDialogButtonBox.Close).setEnabled(False) self.button_box.button(QDialogButtonBox.Cancel).setEnabled(True) if layerId == joinlayerId: self.showInfo("The join layer is the same as the" " input layer - doing a self join!") except: import traceback self.showError("Error starting worker: " + traceback.format_exc()) else: pass # End of startworker def workerFinished(self, ok, ret): """Handles the output from the worker and cleans up after the worker has finished.""" # remove widget from message bar (pop) self.iface.messageBar().popWidget(self.messageBar) if ok and ret is not None: # report the result mem_layer = ret QgsMessageLog.logMessage(self.tr('NNJoin finished'), self.NNJOIN, Qgis.Info) mem_layer.dataProvider().updateExtents() mem_layer.commitChanges() self.layerlistchanging = True QgsProject.instance().addMapLayer(mem_layer) self.layerlistchanging = False else: # notify the user that something went wrong if not ok: self.showError(self.tr('Aborted') + '!') else: self.showError(self.tr('No layer created') + '!') self.progressBar.setValue(0.0) self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) self.button_box.button(QDialogButtonBox.Close).setEnabled(True) self.button_box.button(QDialogButtonBox.Cancel).setEnabled(False) # End of workerFinished def workerError(self, exception_string): """Report an error from the worker.""" self.showError(exception_string) def workerInfo(self, message_string): """Report an info message from the worker.""" QgsMessageLog.logMessage(self.tr('Worker') + ': ' + message_string, self.NNJOIN, Qgis.Info) def fieldchanged(self, number=0): # If the layer list is being updated, don't do anything if self.layerlistchanging: return self.updateui() # End of fieldchanged def distfieldchanged(self, number=0): # If the layer list is being updated, don't do anything # if self.layerlistchanging: # return # Retrieve the input layer layerindex = self.inputVectorLayer.currentIndex() layerId = self.inputVectorLayer.itemData(layerindex) inputlayer = QgsProject.instance().mapLayer(layerId) # Retrieve the join layer joinindex = self.joinVectorLayer.currentIndex() joinlayerId = self.joinVectorLayer.itemData(joinindex) joinlayer = QgsProject.instance().mapLayer(joinlayerId) # Enable the OK button (if layers are OK) if inputlayer is not None and joinlayer is not None: self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) if inputlayer is not None: # Set the default background (white) for the distance field name self.distancefieldname.setStyleSheet("background:#fff;") # Check if the distance field name already is used inputfields = inputlayer.fields().toList() for infield in inputfields: if infield.name() == self.distancefieldname.text(): self.distancefieldname.setStyleSheet("background:#f00;") self.showInfo( "Distance field name conflict in input layer") if self.button_box.button( QDialogButtonBox.Ok).isEnabled(): self.button_box.button( QDialogButtonBox.Ok).setEnabled(False) if joinlayer is not None: joinfields = joinlayer.fields().toList() for joinfield in joinfields: if (self.joinPrefix.text() + joinfield.name() == self.distancefieldname.text()): self.distancefieldname.setStyleSheet( "background:#f00;") self.showInfo( "Distance field name conflict in join layer") if self.button_box.button( QDialogButtonBox.Ok).isEnabled(): self.button_box.button( QDialogButtonBox.Ok).setEnabled(False) # self.updateui() # End of distfieldchanged def joinlayerchanged(self, number=0): # If the layer list is being updated, don't do anything if self.layerlistchanging: return # Retrieve the join layer joinindex = self.joinVectorLayer.currentIndex() joinlayerId = self.joinVectorLayer.itemData(joinindex) self.joinlayerid = joinlayerId joinlayer = QgsProject.instance().mapLayer(joinlayerId) # Geographic? - give a warning! if joinlayer is not None and joinlayer.crs().isGeographic(): self.showWarning('Geographic CRS used for the join layer -' ' distances will be in decimal degrees!') self.layerchanged() # End of joinlayerchanged def layerchanged(self, number=0): """Do the necessary updates after a layer selection has been changed.""" # If the layer list is being updated, don't do anything if self.layerlistchanging: return # Retrieve the input layer layerindex = self.inputVectorLayer.currentIndex() layerId = self.inputVectorLayer.itemData(layerindex) self.inputlayerid = layerId inputlayer = QgsProject.instance().mapLayer(layerId) # Retrieve the join layer joinindex = self.joinVectorLayer.currentIndex() joinlayerId = self.joinVectorLayer.itemData(joinindex) self.joinlayerid = joinlayerId joinlayer = QgsProject.instance().mapLayer(joinlayerId) # Update the input layer UI label with input geometry # type information if inputlayer is not None: inputwkbtype = inputlayer.wkbType() inputlayerwkbtext = self.getwkbtext(inputwkbtype) self.inputgeometrytypelabel.setText(inputlayerwkbtext) # Update the join layer UI label with join geometry type # information if joinlayer is not None: joinwkbtype = joinlayer.wkbType() joinlayerwkbtext = self.getwkbtext(joinwkbtype) self.joingeometrytypelabel.setText(joinlayerwkbtext) # Check the coordinate systems # Different CRSs? - give a warning! if (inputlayer is not None and joinlayer is not None and inputlayer.crs() != joinlayer.crs()): self.showWarning( 'Layers have different CRS! - Input CRS authid: ' + str(inputlayer.crs().authid()) + ' - Join CRS authid: ' + str(joinlayer.crs().authid()) + ". The input layer will be transformed.") self.updateui() # end of layerchanged def useindexchanged(self, number=0): self.updateui() def layerlistchanged(self): # When a layer has been added to or removed by the user, # the comboboxes should be updated to include the new # possibilities. self.layerlistchanging = True # Repopulate the input and join layer combo boxes # Save the currently selected input layer inputlayerid = self.inputlayerid layers = QgsProject.instance().mapLayers() layerslist = [] for id in layers.keys(): if layers[id].type() == QgsMapLayer.VectorLayer: if not layers[id].isValid(): QMessageBox.information(None, self.tr('Information'), 'Layer ' + layers[id].name() + ' is not valid') if layers[id].wkbType() != QgsWkbTypes.NoGeometry: layerslist.append((layers[id].name(), id)) # Add the layers to the input layers combobox self.inputVectorLayer.clear() for layerdescription in layerslist: self.inputVectorLayer.addItem(layerdescription[0], layerdescription[1]) # Set the previous selection for the input layer for i in range(self.inputVectorLayer.count()): if self.inputVectorLayer.itemData(i) == inputlayerid: self.inputVectorLayer.setCurrentIndex(i) # Save the currently selected join layer joinlayerid = self.joinlayerid # Add the layers to the join layers combobox self.joinVectorLayer.clear() for layerdescription in layerslist: self.joinVectorLayer.addItem(layerdescription[0], layerdescription[1]) # Set the previous selection for the join layer for i in range(self.joinVectorLayer.count()): if self.joinVectorLayer.itemData(i) == joinlayerid: self.joinVectorLayer.setCurrentIndex(i) self.layerlistchanging = False self.updateui() # End of layerlistchanged def updateui(self): """Do the necessary updates after a layer selection has been changed.""" # if self.layerlistchanged: # return # Update the output dataset name self.outputDataset.setText(self.inputVectorLayer.currentText() + '_' + self.joinVectorLayer.currentText()) # Retrieve the input layer layerindex = self.inputVectorLayer.currentIndex() layerId = self.inputVectorLayer.itemData(layerindex) inputlayer = QgsProject.instance().mapLayer(layerId) # Retrieve the join layer joinindex = self.joinVectorLayer.currentIndex() joinlayerId = self.joinVectorLayer.itemData(joinindex) joinlayer = QgsProject.instance().mapLayer(joinlayerId) # Enable the OK button (if layers are OK) if inputlayer is not None and joinlayer is not None: self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) # Check the geometry type of the input layer and set # user interface options accordingly if inputlayer is not None: wkbType = inputlayer.wkbType() geomType = inputlayer.geometryType() # not used yet joinwkbType = QgsWkbTypes.Unknown joingeomType = QgsWkbTypes.UnknownGeometry # not used yet if joinlayer is not None: joinwkbType = joinlayer.wkbType() joingeomType = joinlayer.geometryType() # If the input layer is not a point layer, allow choosing # approximate geometry (centroid) if wkbType == QgsWkbTypes.Point or wkbType == QgsWkbTypes.Point25D: # Input layer is a simple point layer and can not # be approximated self.approximate_input_geom_cb.blockSignals(True) self.approximate_input_geom_cb.setCheckState(Qt.Unchecked) self.approximate_input_geom_cb.setVisible(False) self.approximate_input_geom_cb.blockSignals(False) else: # Input layer is not a point layer, so approximation # is possible self.approximate_input_geom_cb.blockSignals(True) self.approximate_input_geom_cb.setVisible(True) self.approximate_input_geom_cb.blockSignals(False) # Update the use index checkbox if ((wkbType == QgsWkbTypes.LineString or wkbType == QgsWkbTypes.LineString25D or wkbType == QgsWkbTypes.Polygon or wkbType == QgsWkbTypes.Polygon25D) and not self.approximate_input_geom_cb.isChecked()): # The input layer is a line or polygong layer that # is not approximated, so the user is allowed to # choose not to use the spatial index (not very useful!) if not self.use_index_nonpoint_cb.isVisible(): self.use_index_nonpoint_cb.blockSignals(True) self.use_index_nonpoint_cb.setCheckState(Qt.Checked) self.use_index_nonpoint_cb.setVisible(True) self.use_index_nonpoint_cb.blockSignals(False) else: # The input layer is either a point approximation # or it is a point layer (or some kind of # multigeometry!), anyway we won't allow the user to # choose not to use a spatial index self.use_index_nonpoint_cb.blockSignals(True) self.use_index_nonpoint_cb.setCheckState(Qt.Unchecked) self.use_index_nonpoint_cb.setVisible(False) self.use_index_nonpoint_cb.blockSignals(False) # This does not work!!???? # Update the use index approximation checkbox: if (((wkbType == QgsWkbTypes.Point) or (wkbType == QgsWkbTypes.Point25D) or self.approximate_input_geom_cb.isChecked()) and not (joinwkbType == QgsWkbTypes.Point or joinwkbType == QgsWkbTypes.Point25D)): # For non-point join layers and point input layers, # the user is allowed to choose an approximation (the # index geometry) to be used for the join geometry in # the join. self.use_indexapprox_cb.setVisible(True) else: # For point join layers, and non-point, # non-point-approximated input layers, the user is # not allowed to choose an approximation (the index # geometry) to be used for the join geometry in the # join. self.use_indexapprox_cb.blockSignals(True) self.use_indexapprox_cb.setCheckState(Qt.Unchecked) self.use_indexapprox_cb.setVisible(False) self.use_indexapprox_cb.blockSignals(False) # Update the exclude containing polygon checkbox: if ((wkbType == QgsWkbTypes.Point or wkbType == QgsWkbTypes.Point25D or self.approximate_input_geom_cb.isChecked()) and (joinwkbType == QgsWkbTypes.Polygon or joinwkbType == QgsWkbTypes.Polygon25D) and (not self.use_indexapprox_cb.isChecked())): # For polygon join layers and point input layers, # the user is allowed to choose to exclude the # containing polygon in the join. self.exclude_containing_poly_cb.blockSignals(True) self.exclude_containing_poly_cb.setVisible(True) self.exclude_containing_poly_cb.blockSignals(False) else: self.exclude_containing_poly_cb.blockSignals(True) self.exclude_containing_poly_cb.setCheckState(Qt.Unchecked) self.exclude_containing_poly_cb.setVisible(False) self.exclude_containing_poly_cb.blockSignals(False) # Set the default background (white) for the distance field name self.distancefieldname.setStyleSheet("background:#fff;") # Check if the distance field name already is used inputfields = inputlayer.fields().toList() for infield in inputfields: if infield.name() == self.distancefieldname.text(): self.distancefieldname.setStyleSheet("background:#f00;") self.showInfo( "Distance field name conflict in input layer") if self.button_box.button( QDialogButtonBox.Ok).isEnabled(): self.button_box.button( QDialogButtonBox.Ok).setEnabled(False) break if joinlayer is not None: joinfields = joinlayer.fields().toList() for joinfield in joinfields: if (self.joinPrefix.text() + joinfield.name() == self.distancefieldname.text()): self.distancefieldname.setStyleSheet( "background:#f00;") self.showInfo( "Distance field name conflict in join layer") if self.button_box.button( QDialogButtonBox.Ok).isEnabled(): self.button_box.button( QDialogButtonBox.Ok).setEnabled(False) break else: # No input layer defined, so options are disabled self.approximate_input_geom_cb.setVisible(False) self.use_indexapprox_cb.setVisible(False) self.use_index_nonpoint_cb.setVisible(False) # End of updateui def getwkbtext(self, number): if number == QgsWkbTypes.Unknown: return "Unknown" elif number == QgsWkbTypes.Point: return "Point" elif number == QgsWkbTypes.LineString: return "LineString" elif number == QgsWkbTypes.Polygon: return "Polygon" elif number == QgsWkbTypes.MultiPoint: return "MultiPoint" elif number == QgsWkbTypes.MultiLineString: return "MultiLineString" elif number == QgsWkbTypes.MultiPolygon: return "MultiPolygon" elif number == QgsWkbTypes.NoGeometry: return "NoGeometry" elif number == QgsWkbTypes.Point25D: return "Point25D" elif number == QgsWkbTypes.LineString25D: return "LineString25D" elif number == QgsWkbTypes.Polygon25D: return "Polygon25D" elif number == QgsWkbTypes.MultiPoint25D: return "MultiPoint25D" elif number == QgsWkbTypes.MultiLineString25D: return "MultiLineString25D" elif number == QgsWkbTypes.MultiPolygon25D: return "MultiPolygon25D" else: showError('Unknown or invalid geometry type: ' + str(number)) return "Don't know" # End of getwkbtext def killWorker(self): """Kill the worker thread.""" # if self.worker is not None: # self.showInfo(self.tr('Killing worker')) # self.worker.kill() def showError(self, text): """Show an error.""" self.iface.messageBar().pushMessage(self.tr('Error'), text, level=Qgis.Critical, duration=3) QgsMessageLog.logMessage('Error: ' + text, self.NNJOIN, Qgis.Critical) def showWarning(self, text): """Show a warning.""" self.iface.messageBar().pushMessage(self.tr('Warning'), text, level=Qgis.Warning, duration=2) QgsMessageLog.logMessage('Warning: ' + text, self.NNJOIN, Qgis.Warning) def showInfo(self, text): """Show info.""" self.iface.messageBar().pushMessage(self.tr('Info'), text, level=Qgis.Info, duration=2) QgsMessageLog.logMessage('Info: ' + text, self.NNJOIN, Qgis.Info) def help(self): QDesktopServices.openUrl(QUrl.fromLocalFile( self.plugin_dir + "/help/html/index.html")) # showPluginHelp(None, "help/html/index") def tr(self, message): """Get the translation for a string using Qt translation API. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ return QCoreApplication.translate('NNJoinDialog', message) # Implement the accept method to avoid exiting the dialog when # starting the work def accept(self): """Accept override.""" pass # Implement the reject method to have the possibility to avoid # exiting the dialog when cancelling def reject(self): """Reject override.""" # exit the dialog QDialog.reject(self)