def set_source_document_location(doc_path): """ Set the latest source directory of uploaded source documents. :param doc_path: Directory path or file path. The system will attempt to extract the directory path from the file name. """ doc_dir_path = "" # Check if it is a file or directory doc_dir = QDir(doc_path) if not doc_dir.exists(): doc_file_info = QFileInfo(doc_path) if doc_file_info.exists(): doc_dir_path = doc_file_info.dir().path() else: doc_dir_path = doc_path if len(doc_dir_path) > 0: reg_config = RegistryConfig() reg_config.write({LOCAL_SOURCE_DOC: doc_dir_path})
def get_rat(raster_layer, band, colors=('R', 'G', 'B', 'A')): """Extracts RAT from raster layer and given band :param raster_layer: the raster layer to classify :type raster_layer: QgsRasterLayer :param band: band number (1-based) :type band: int :param colors: default name of the RGB(A) columns for sidecar DBF files, defaults to ('R', 'G', 'B', 'A'), these are searched first :type red_column_name: tuple, optional :return: RAT :rtype: RAT """ headers = [] values = {} fields = {} # For sidecar files path = None COLOR_ROLES = (gdal.GFU_Red, gdal.GFU_Green, gdal.GFU_Blue, gdal.GFU_Alpha) is_dbf = False ds = gdal.OpenEx(raster_layer.source()) if ds: band = ds.GetRasterBand(band) if band: rat = band.GetDefaultRAT() if rat is not None: for i in range(0, rat.GetColumnCount()): column = rat.GetNameOfCol(i) headers.append(column) values[column] = [] fields[column] = RATField( column, rat.GetUsageOfCol(i), rat.GetTypeOfCol(i)) for r in range(0, rat.GetRowCount()): for c in range(0, rat.GetColumnCount()): column = headers[c] if fields[column].type == gdal.GFT_Integer: values[headers[c]].append(rat.GetValueAsInt(r, c)) elif fields[column].type == gdal.GFT_Real: values[headers[c]].append( rat.GetValueAsDouble(r, c)) else: values[headers[c]].append( html.unescape(rat.GetValueAsString(r, c))) # Try to identify fields in case of RAT with wrong usages usages = [f.usage for f in fields.values()] if gdal.GFU_MinMax not in usages and not {gdal.GFU_Min, gdal.GFU_Max}.issubset(usages): try: field_name = [f.name for f in fields.values() if f.name.upper() == 'VALUE'][0] fields[field_name].usage = gdal.GFU_MinMax except IndexError: pass try: field_name = [f.name for f in fields.values() if f.name.upper() in ('VALUE MIN', 'MIN', 'MIN VALUE', 'VALUE_MIN', 'MIN_VALUE')][0] fields[field_name].usage = gdal.GFU_Min except IndexError: pass try: field_name = [f.name for f in fields.values() if f.name.upper() in ('VALUE MAX', 'MAX', 'MAX VALUE', 'VALUE_MAX', 'MAX_VALUE')][0] fields[field_name].usage = gdal.GFU_Max except IndexError: pass if gdal.GFU_PixelCount not in usages: try: field_name = [f.name for f in fields.values() if f.name.upper() == 'COUNT'][0] fields[field_name].usage = gdal.GFU_PixelCount except IndexError: pass path = raster_layer.source() + '.aux.xml' # Search for sidecar DBF files, `band` is ignored! if not values: info = QFileInfo(raster_layer.publicSource()) directory = info.dir().path() basename = info.baseName() filename = info.fileName() candidates = (basename + '.dbf', basename + '.vat.dbf', filename + '.dbf', filename + '.vat.dbf') for candidate in candidates: if os.path.exists(os.path.join(directory, candidate)): rat_layer = QgsVectorLayer(os.path.join( directory, candidate), 'rat', 'ogr') if rat_layer.isValid(): path = os.path.join(directory, candidate) # Get fields # Check if color fields are there, fall-back to RED GREEN BLUE ALPHA if not field_upper_names = [f.name().upper() for f in rat_layer.fields()] upper_colors = [c.upper() for c in colors] def _search_color(): color_found = True for color_field_name in upper_colors[:3]: if color_field_name not in field_upper_names: color_found = False return color_found if not _search_color() and colors == ('R', 'G', 'B', 'A'): upper_colors = ('RED', 'GREEN', 'BLUE', 'ALPHA') # Create fields for f in rat_layer.fields(): headers.append(f.name()) field_name_upper = f.name().upper() if field_name_upper in upper_colors: fields[f.name()] = RATField( f.name(), COLOR_ROLES[upper_colors.index(field_name_upper)], gdal.GFT_Integer if f.type() in (QVariant.Int, QVariant.LongLong) else gdal.GFT_Real) elif field_name_upper == 'COUNT': fields[f.name()] = RATField( f.name(), gdal.GFU_PixelCount, gdal.GFT_Integer) elif field_name_upper == 'VALUE': fields[f.name()] = RATField( f.name(), gdal.GFU_MinMax, gdal.GFT_Integer if f.type() in (QVariant.Int, QVariant.LongLong) else gdal.GFT_Real) elif field_name_upper in ('VALUE MIN', 'VALUE_MIN', 'MIN VALUE', 'MIN_VALUE'): fields[f.name()] = RATField( f.name(), gdal.GFU_Min, gdal.GFT_Integer if f.type() in (QVariant.Int, QVariant.LongLong) else gdal.GFT_Real) elif field_name_upper in ('VALUE MAX', 'VALUE_MAX', 'MAX VALUE', 'MAX_VALUE'): fields[f.name()] = RATField( f.name(), gdal.GFU_Max, gdal.GFT_Integer if f.type() in (QVariant.Int, QVariant.LongLong) else gdal.GFT_Real) else: if f.type() in (QVariant.Int, QVariant.LongLong): type = gdal.GFT_Integer elif f.type() == QVariant.Double: type = gdal.GFT_Real else: type = gdal.GFT_String fields[f.name()] = RATField( f.name(), gdal.GFU_Generic, type) for header in headers: values[header] = [] for f in rat_layer.getFeatures(): for header in headers: values[header].append(f.attribute(header)) is_dbf = True break # Colors if headers: red = None green = None blue = None alpha = None is_integer = False for name, f in fields.items(): if f.usage == gdal.GFU_Red: red = name is_integer = f.type == gdal.GFT_Integer continue if f.usage == gdal.GFU_Green: green = name continue if f.usage == gdal.GFU_Blue: blue = name continue if f.usage == gdal.GFU_Alpha: alpha = name continue if red and green and blue: headers.append(RAT_COLOR_HEADER_NAME) values[RAT_COLOR_HEADER_NAME] = [] for i in range(len(values[red])): func = 'fromRgb' if is_integer else 'fromRgbF' if alpha: values[RAT_COLOR_HEADER_NAME].append(getattr(QColor, func)( values[red][i], values[green][i], values[blue][i], values[alpha][i])) else: values[RAT_COLOR_HEADER_NAME].append(getattr(QColor, func)( values[red][i], values[green][i], values[blue][i])) return RAT(values, is_dbf, fields, path)
def get_rat(raster_layer, band, colors=('R', 'G', 'B', 'A')): """Extracts RAT from raster layer and given band :param raster_layer: the raster layer to classify :type raster_layer: QgsRasterLayer :param band: band number (1-based) :type band: int :param colors: name of the RGB(A) columns for sidecar DBF files, defaults to ('R', 'G', 'B', 'A') :type red_column_name: tuple, optional :return: RAT :rtype: RAT """ headers = [] values = {} fields = {} # For sidecar files path = None COLOR_ROLES = (gdal.GFU_Red, gdal.GFU_Green, gdal.GFU_Blue, gdal.GFU_Alpha) is_sidecar = False ds = gdal.OpenEx(raster_layer.source()) if ds: band = ds.GetRasterBand(band) if band: rat = band.GetDefaultRAT() if rat is not None: for i in range(0, rat.GetColumnCount()): column = rat.GetNameOfCol(i) headers.append(column) values[column] = [] fields[column] = RATField(column, rat.GetUsageOfCol(i), rat.GetTypeOfCol(i)) for r in range(0, rat.GetRowCount()): for c in range(0, rat.GetColumnCount()): column = headers[c] if fields[column].type == gdal.GFT_Integer: values[headers[c]].append(rat.GetValueAsInt(r, c)) elif fields[column].type == gdal.GFT_Real: values[headers[c]].append( rat.GetValueAsDouble(r, c)) else: values[headers[c]].append( html.unescape(rat.GetValueAsString(r, c))) path = raster_layer.source() + '.aux.xml' # Search for sidecar DBF files, `band` is ignored! if not values: info = QFileInfo(raster_layer.publicSource()) directory = info.dir().path() basename = info.baseName() filename = info.fileName() candidates = (basename + '.dbf', basename + '.vat.dbf', filename + '.dbf', filename + '.vat.dbf') for candidate in candidates: if os.path.exists(os.path.join(directory, candidate)): rat_layer = QgsVectorLayer(os.path.join(directory, candidate), 'rat', 'ogr') if rat_layer.isValid(): path = os.path.join(directory, candidate) for f in rat_layer.fields(): headers.append(f.name()) if f.name().upper() in colors: fields[f.name()] = RATField( f.name(), COLOR_ROLES[colors.index(f.name().upper())], gdal.GFT_Integer if f.type() in (QVariant.Int, QVariant.LongLong) else gdal.GFT_Real) elif f.name().upper() == 'COUNT': fields[f.name()] = RATField( f.name(), gdal.GFU_PixelCount, gdal.GFT_Integer) elif f.name().upper() == 'VALUE': fields[f.name()] = RATField( f.name(), gdal.GFU_MinMax, gdal.GFT_Integer if f.type() in (QVariant.Int, QVariant.LongLong) else gdal.GFT_Real) else: if f.type() in (QVariant.Int, QVariant.LongLong): type = gdal.GFT_Integer elif f.type() == QVariant.Double: type = gdal.GFT_Real else: type = gdal.GFT_String fields[f.name()] = RATField( f.name(), gdal.GFU_Generic, type) for header in headers: values[header] = [] for f in rat_layer.getFeatures(): for header in headers: values[header].append(f.attribute(header)) is_sidecar = True break # Colors if headers: red = None green = None blue = None alpha = None is_integer = False for name, f in fields.items(): if f.usage == gdal.GFU_Red: red = name is_integer = f.type == gdal.GFT_Integer continue if f.usage == gdal.GFU_Green: green = name continue if f.usage == gdal.GFU_Blue: blue = name continue if f.usage == gdal.GFU_Alpha: alpha = name continue if red and green and blue: headers.append(RAT_COLOR_HEADER_NAME) values[RAT_COLOR_HEADER_NAME] = [] for i in range(len(values[red])): func = 'fromRgb' if is_integer else 'fromRgbF' if alpha: values[RAT_COLOR_HEADER_NAME].append( getattr(QColor, func)(values[red][i], values[green][i], values[blue][i], values[alpha][i])) else: values[RAT_COLOR_HEADER_NAME].append( getattr(QColor, func)(values[red][i], values[green][i], values[blue][i])) return RAT(values, is_sidecar, fields, path)
def onGenerate(self): """ Slot raised to initiate the certificate generation process. """ self._notif_bar.clear() success_status = True config = self.current_config() self.last_data_source = config.data_source() if config is None: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "The entity configuration could not be extracted.")) return # Get selected records and validate records = self.tabWidget.currentWidget().entities() if self.chk_template_datasource.isChecked(): records = self._dummy_template_records() if len(records) == 0: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "Please load at least one entity record")) return if not self._docTemplatePath: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "Please select a document template to use")) return documentNamingAttrs = self.lstDocNaming.selectedMappings() if self.chkUseOutputFolder.checkState() == Qt.Checked and len( documentNamingAttrs) == 0: self._notif_bar.insertErrorNotification(QApplication.translate("DocumentGeneratorDialog", \ "Please select at least one field for naming the output document")) return # Set output file properties if self.rbExpImage.isChecked(): outputMode = DocumentGenerator.Image fileExtension = self.cboImageType.currentText() saveAsText = "Image File" else: outputMode = DocumentGenerator.PDF fileExtension = "pdf" saveAsText = "PDF File" # Show save file dialog if not using output folder if self.chkUseOutputFolder.checkState() == Qt.Unchecked: docDir = source_document_location() if self._outputFilePath: fileInfo = QFileInfo(self._outputFilePath) docDir = fileInfo.dir().path() self._outputFilePath, _ = QFileDialog.getSaveFileName( self, QApplication.translate("DocumentGeneratorDialog", "Save Document"), docDir, "{0} (*.{1})".format( QApplication.translate("DocumentGeneratorDialog", saveAsText), fileExtension)) if not self._outputFilePath: self._notif_bar.insertErrorNotification( QApplication.translate( "DocumentGeneratorDialog", "Process aborted. No output file was specified.")) return # Include extension in file name self._outputFilePath = self._outputFilePath # + "." + fileExtension # else: # Multiple files to be generated. # pass self._doc_generator.set_link_field(config.link_field()) self._doc_generator.clear_attr_value_formatters() if not self.chk_template_datasource.isChecked(): # Apply cell formatters for naming output files self._doc_generator.set_attr_value_formatters(config.formatters()) entity_field_name = "id" # Iterate through the selected records progressDlg = QProgressDialog(self) progressDlg.setMaximum(len(records)) try: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) for i, record in enumerate(records): progressDlg.setValue(i) if progressDlg.wasCanceled(): success_status = False break # User-defined location if self.chkUseOutputFolder.checkState() == Qt.Unchecked: status, msg = self._doc_generator.run( self._docTemplatePath, entity_field_name, record.id, outputMode, data_source=self.ds_entity.name, filePath=self._outputFilePath) self._doc_generator.clear_temporary_layers() # Output folder location using custom naming else: status, msg = self._doc_generator.run( self._docTemplatePath, entity_field_name, record.id, outputMode, dataFields=documentNamingAttrs, fileExtension=fileExtension, data_source=self.ds_entity.name) self._doc_generator.clear_temporary_layers() if not status: result = QMessageBox.warning( self, QApplication.translate("DocumentGeneratorDialog", "Document Generate Error"), msg, QMessageBox.Ignore | QMessageBox.Abort) if result == QMessageBox.Abort: progressDlg.close() success_status = False # Restore cursor QApplication.restoreOverrideCursor() return # If its the last record and user has selected to ignore if i + 1 == len(records): progressDlg.close() success_status = False # Restore cursor QApplication.restoreOverrideCursor() return else: progressDlg.setValue(len(records)) QApplication.restoreOverrideCursor() QMessageBox.information( self, QApplication.translate("DocumentGeneratorDialog", "Document Generation Complete"), QApplication.translate( "DocumentGeneratorDialog", "Document generation has successfully completed.")) except DummyException as ex: LOGGER.debug(str(ex)) err_msg = sys.exc_info()[1] QApplication.restoreOverrideCursor() QMessageBox.critical( self, "STDM", QApplication.translate( "DocumentGeneratorDialog", "Error Generating documents - %s" % (err_msg))) success_status = False # Reset UI self.reset(success_status)