def test_icon_with_settings(self): r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200)) # need a layer in order to make legend nodes layer = QgsVectorLayer('dummy', 'test', 'memory') layer_tree_layer = QgsLayerTreeLayer(layer) settings = QgsColorRampLegendNodeSettings() format = QgsBasicNumericFormat() format.setShowTrailingZeros(True) format.setNumberDecimalPlaces(3) settings.setNumericFormat(format) settings.setDirection(QgsColorRampLegendNodeSettings.MaximumToMinimum) node = TestColorRampLegend(layer_tree_layer, r, settings, 5, 10) pixmap = node.data(Qt.DecorationRole) im = QImage(pixmap.size(), QImage.Format_ARGB32) im.fill(QColor(255, 255, 255)) p = QPainter(im) p.drawPixmap(0, 0, pixmap) p.end() self.assertTrue(self.imageCheck('color_ramp_legend_node_settings_icon', 'color_ramp_legend_node_settings_icon', im, 10))
def test_icon_horizontal_flipped(self): r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200)) # need a layer in order to make legend nodes layer = QgsVectorLayer('dummy', 'test', 'memory') layer_tree_layer = QgsLayerTreeLayer(layer) settings = QgsColorRampLegendNodeSettings() settings.setDirection(QgsColorRampLegendNodeSettings.MaximumToMinimum) settings.setOrientation(Qt.Horizontal) node = TestColorRampLegend(layer_tree_layer, r, settings, 5, 10) pixmap = node.data(Qt.DecorationRole) im = QImage(pixmap.size(), QImage.Format_ARGB32) im.fill(QColor(255, 255, 255)) p = QPainter(im) p.drawPixmap(0, 0, pixmap) p.end() self.assertTrue( self.imageCheck('color_ramp_legend_node_flipped_horizontal_icon', 'color_ramp_legend_node_flipped_horizontal_icon', im, 10))
def test_icon_prefix_suffix(self): r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200)) # need a layer in order to make legend nodes layer = QgsVectorLayer('dummy', 'test', 'memory') layer_tree_layer = QgsLayerTreeLayer(layer) settings = QgsColorRampLegendNodeSettings() settings.setPrefix('pref ') settings.setSuffix(' suff') node = TestColorRampLegend(layer_tree_layer, r, settings, 5, 10) pixmap = node.data(Qt.DecorationRole) im = QImage(pixmap.size(), QImage.Format_ARGB32) im.fill(QColor(255, 255, 255)) p = QPainter(im) p.drawPixmap(0, 0, pixmap) p.end() self.assertTrue( self.imageCheck('color_ramp_legend_node_prefix_suffix_icon', 'color_ramp_legend_node_prefix_suffix_icon', im, 10))
def print_photo(self): print_dialog = QPrintDialog(self._printer, self) if print_dialog.exec_() == QDialog.Accepted: painter = QPainter(self._printer) rect = painter.viewport() size = self._lbl_photo.pixmap().size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.setWindow(self._lbl_photo.pixmap().rect()) painter.drawPixmap(0, 0, self._lbl_photo.pixmap())
def createCompoundThumbnail(_bboxes, thumbnails): bboxes = [] transform = QgsCoordinateTransform( QgsCoordinateReferenceSystem("EPSG:4326"), QgsCoordinateReferenceSystem("EPSG:3857"), QgsProject.instance(), ) for box in _bboxes: rect4326 = qgsgeometry_from_geojson(box).boundingBox() rect = transform.transformBoundingBox(rect4326) bboxes.append([ rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum() ]) globalbox = ( min([v[0] for v in bboxes]), min([v[1] for v in bboxes]), max([v[2] for v in bboxes]), max([v[3] for v in bboxes]), ) SIZE = 256 globalwidth = globalbox[2] - globalbox[0] globalheight = globalbox[3] - globalbox[1] pixmap = QPixmap(SIZE, SIZE) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) try: for i, thumbnail in enumerate(thumbnails): box = bboxes[i] width = box[2] - box[0] height = box[3] - box[1] if width > height: offsety = (width - height) / 2 offsetx = 0 else: offsetx = (height - width) / 2 offsety = 0 x = int((box[0] - offsetx - globalbox[0]) / globalwidth * SIZE) y = int((globalbox[3] - box[3] - offsety) / globalheight * SIZE) outputwidth = int((width + 2 * offsetx) / globalwidth * SIZE) outputheight = int((height + 2 * offsety) / globalheight * SIZE) painter.drawPixmap(x, y, outputwidth, outputheight, thumbnail) except Exception: """ Unexpected values for bboxes might cause uneexpected errors. We just ignore them and return an empty image in that case """ finally: painter.end() return pixmap
def get_colored_pixmap(filename, color, size): """Returns a colored pixmap of given size.""" pixmap = QPixmap(filename).scaled(size, Qt.KeepAspectRatio, Qt.SmoothTransformation) image = QImage(pixmap.width(), pixmap.height(), QImage.Format_ARGB32_Premultiplied) image.fill(color) painter = QPainter(image) painter.setCompositionMode(QPainter.CompositionMode_DestinationIn) painter.drawPixmap(0, 0, pixmap) painter.end() return QPixmap.fromImage(image)
def test_icon(self): r = QgsGradientColorRamp(QColor(200, 0, 0, 100), QColor(0, 200, 0, 200)) # need a layer in order to make legend nodes layer = QgsVectorLayer('dummy', 'test', 'memory') layer_tree_layer = QgsLayerTreeLayer(layer) node = TestColorRampLegend(layer_tree_layer, r, 'min_label', 'max_label') pixmap = node.data(Qt.DecorationRole) im = QImage(pixmap.size(), QImage.Format_ARGB32) im.fill(QColor(255, 255, 255)) p = QPainter(im) p.drawPixmap(0, 0, pixmap) p.end() self.assertTrue(self.imageCheck('color_ramp_legend_node_icon', 'color_ramp_legend_node_icon', im, 10))
def createCompoundThumbnail(_bboxes, thumbnails): bboxes = [] transform = QgsCoordinateTransform( QgsCoordinateReferenceSystem('EPSG:4326'), QgsCoordinateReferenceSystem('EPSG:3857'), QgsProject.instance()) for box in _bboxes: rect4326 = qgsgeometry_from_geojson(box).boundingBox() rect = transform.transformBoundingBox(rect4326) bboxes.append([ rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum() ]) globalbox = (min([v[0] for v in bboxes]), min([v[1] for v in bboxes]), max([v[2] for v in bboxes]), max([v[3] for v in bboxes])) SIZE = 256 globalwidth = globalbox[2] - globalbox[0] globalheight = globalbox[3] - globalbox[1] pixmap = QPixmap(SIZE, SIZE) pixmap.fill(Qt.transparent) painter = QPainter(pixmap) for i, thumbnail in enumerate(thumbnails): box = bboxes[i] width = box[2] - box[0] height = box[3] - box[1] if width > height: offsety = (width - height) / 2 offsetx = 0 else: offsetx = (height - width) / 2 offsety = 0 x = int((box[0] - offsetx - globalbox[0]) / globalwidth * SIZE) y = int((globalbox[3] - box[3] - offsety) / globalheight * SIZE) outputwidth = int((width + 2 * offsetx) / globalwidth * SIZE) outputheight = int((height + 2 * offsety) / globalheight * SIZE) painter.drawPixmap(x, y, outputwidth, outputheight, thumbnail) painter.end() return pixmap
def update_summary_sheet(self,lyr=None, force=None): ''' Creates a summary sheet with thumbnail, layer metadata and online view link ''' #create a layer snapshot and upload it to google drive if not lyr: lyr = self.lyr mapbox_style = self.service_sheet.sheet_cell('settings!A5') if not mapbox_style: logger("migrating mapbox style") self.service_sheet.set_style_mapbox(self.layer_style_to_json(self.lyr)) if not force and not self.dirty and not self.restyled: return if self.restyled: self.service_sheet.set_style_qgis(self.layer_style_to_xml(self.lyr)) self.service_sheet.set_style_sld(self.SLD_to_xml(self.lyr)) self.service_sheet.set_style_mapbox(self.layer_style_to_json(self.lyr)) self.saveMetadataState() canvas = QgsMapCanvas() canvas.resize(QSize(600,600)) canvas.setCanvasColor(Qt.white) canvas.setExtent(lyr.extent()) canvas.setLayers([lyr]) canvas.refresh() canvas.update() settings = canvas.mapSettings() settings.setLayers([lyr]) job = QgsMapRendererParallelJob(settings) job.start() job.waitForFinished() image = job.renderedImage() transparent_image = QImage(image.width(), image.height(), QImage.Format_ARGB32) transparent_image.fill(Qt.transparent) p = QPainter(transparent_image) mask = image.createMaskFromColor(QColor(255, 255, 255).rgb(), Qt.MaskInColor) p.setClipRegion(QRegion(QBitmap(QPixmap.fromImage(mask)))) p.drawPixmap(0, 0, QPixmap.fromImage(image)) p.end() tmp_path = os.path.join(self.parent.plugin_dir,self.service_sheet.name+".png") transparent_image.save(tmp_path,"PNG") image_istances = self.service_drive.list_files(mimeTypeFilter='image/png',filename=self.service_sheet.name+".png") for imagename, image_props in image_istances.items(): self.service_drive.delete_file(image_props['id']) result = self.service_drive.upload_image(tmp_path) self.service_drive.add_permission(result['id'],'anyone','reader') webLink = result['webContentLink'] #'https://drive.google.com/uc?export=view&id='+result['id'] logger("webLink:" + webLink) canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) worldfile = QgsMapSettingsUtils.worldFileContent(settings) lonlat_min = self.transformToWGS84(QgsPointXY(canvas.extent().xMinimum(), canvas.extent().yMinimum())) lonlat_max = self.transformToWGS84(QgsPointXY(canvas.extent().xMaximum(), canvas.extent().yMaximum())) keymap_extent = [lonlat_min.x(),lonlat_min.y(),lonlat_max.x(),lonlat_max.y()] os.remove(tmp_path) #update layer metadata summary_id = self.service_sheet.add_sheet('summary', no_grid=True) appPropsUpdate = [ ["keymap",webLink], ["worldfile",pack(worldfile)], ["keymap_extent", json.dumps(keymap_extent)] ] res = self.service_sheet.update_appProperties(self.spreadsheet_id,appPropsUpdate) self.saveMetadataState(metadata=self.get_layer_metadata()) self.parent.public_db.setKey(self.spreadsheet_id, dict(self.get_layer_metadata()+appPropsUpdate),only_update=True) #merge cells to visualize snapshot and aaply image snapshot request_body = { 'requests': [{ 'mergeCells': { "range": { "sheetId": summary_id, "startRowIndex": 9, "endRowIndex": 32, "startColumnIndex": 0, "endColumnIndex": 9, }, "mergeType": 'MERGE_ALL' } }] } self.service_sheet.service.spreadsheets().batchUpdate(spreadsheetId=self.spreadsheet_id, body=request_body).execute() self.service_sheet.set_sheet_cell('summary!A10','=IMAGE("%s",3)' % webLink) permissions = self.service_drive.file_property(self.spreadsheet_id,'permissions') for permission in permissions: if permission['type'] == 'anyone': public = True break else: public = False if public: update_range = 'summary!A9:B9' update_body = { "range": update_range, "values": [['public link', "https://enricofer.github.io/gdrive_provider/weblink/converter.html?spreadsheet_id="+self.spreadsheet_id]] } self.service_sheet.service.spreadsheets().values().update(spreadsheetId=self.spreadsheet_id,range=update_range, body=update_body, valueInputOption='USER_ENTERED').execute() #hide worksheets except summary sheets = self.service_sheet.get_sheets() #self.service_sheet.toggle_sheet('summary', sheets['summary'], hidden=None) for sheet_name,sheet_id in sheets.items(): if not sheet_name == 'summary': self.service_sheet.toggle_sheet(sheet_name, sheet_id, hidden=True)