def fitRect(rect, targetrect): size = rect.size().boundedTo(targetgeom.size()) newrect = QRect(rect.topLeft(), size) dx, dy = 0, 0 if newrect.left() < targetrect.left(): dx = targetrect.left() - newrect.left() if newrect.top() < targetrect.top(): dy = targetrect.top() - newrect.top() if newrect.right() > targetrect.right(): dx = targetrect.right() - newrect.right() if newrect.bottom() > targetrect.bottom(): dy = targetrect.bottom() - newrect.bottom() return newrect.translated(dx, dy)
def popup(self, pos=None, searchText=""): """ Popup the menu at `pos` (in screen coordinates). 'Search' text field is initialized with `searchText` if provided. """ if pos is None: pos = QPoint() self.__clearCurrentItems() self.__search.setText(searchText) patt = QRegExp("(^|\W)"+searchText) patt.setCaseSensitivity(False) self.__suggestPage.setFilterRegExp(patt) self.ensurePolished() if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled(): size = self.size() else: size = self.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) self.setGeometry(geom) self.show() if searchText: self.setFocusProxy(self.__search) else: self.setFocusProxy(None)
def popup(self, pos=None, searchText=""): """ Popup the menu at `pos` (in screen coordinates). 'Search' text field is initialized with `searchText` if provided. """ if pos is None: pos = QPoint() self.__clearCurrentItems() self.__search.setText(searchText) patt = QRegExp("(^|\W)" + searchText) patt.setCaseSensitivity(False) self.__suggestPage.setFilterRegExp(patt) self.ensurePolished() if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled(): size = self.size() else: size = self.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) self.setGeometry(geom) self.show() if searchText: self.setFocusProxy(self.__search) else: self.setFocusProxy(None)
def __autoScrollAdvance(self): """Advance the auto scroll """ pos = QCursor.pos() pos = self.mapFromGlobal(pos) margin = self.__autoScrollMargin vvalue = self.verticalScrollBar().value() hvalue = self.horizontalScrollBar().value() vrect = QRect(0, 0, self.width(), self.height()) # What should be the speed advance = 10 # We only do auto scroll if the mouse is inside the view. if vrect.contains(pos): if pos.x() < vrect.left() + margin: self.horizontalScrollBar().setValue(hvalue - advance) if pos.y() < vrect.top() + margin: self.verticalScrollBar().setValue(vvalue - advance) if pos.x() > vrect.right() - margin: self.horizontalScrollBar().setValue(hvalue + advance) if pos.y() > vrect.bottom() - margin: self.verticalScrollBar().setValue(vvalue + advance) if self.verticalScrollBar().value() == vvalue and \ self.horizontalScrollBar().value() == hvalue: self.__stopAutoScroll() else: self.__stopAutoScroll() log.debug("Auto scroll advance")
def applyMargin(rect, margin): result = QRect(rect) result.setLeft(result.left()+margin) result.setRight(result.right()-margin) result.setTop(result.top()+margin) result.setBottom(result.bottom()-margin) return result
def renderSplit(self, painter, rowStats, splitsRect): painter.setFont(self.ds.splitFont()) splitValues = [self.ds.splitValues(rowStats.index, i) for i in range(rowStats.splitCount)] colWidths = [0, 0, 0] for sv in splitValues: colWidths[0] = max(colWidths[0], self.stats.splitFM.width(sv.account)) colWidths[1] = max(colWidths[1], self.stats.splitFM.width(sv.memo)) colWidths[2] = max(colWidths[2], self.stats.splitFM.width(sv.amount)) top = splitsRect.top() for sv in splitValues: rect = QRect(splitsRect.left(), top, colWidths[0], self.stats.splitHeight) painter.drawText(rect, Qt.AlignLeft, sv.account) rect.setLeft(rect.right() + SPLIT_XPADDING) rect.setWidth(colWidths[1]) painter.drawText(rect, Qt.AlignLeft, sv.memo) rect.setLeft(rect.right() + SPLIT_XPADDING) rect.setWidth(colWidths[2]) painter.drawText(rect, Qt.AlignRight, sv.amount) top += self.stats.splitHeight
def popup_position_from_source(popup, source, orientation=Qt.Vertical): popup.ensurePolished() source.ensurePolished() if popup.testAttribute(Qt.WA_Resized): size = popup.size() else: size = popup.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(source) source_rect = QRect(source.mapToGlobal(QPoint(0, 0)), source.size()) if orientation == Qt.Vertical: if source_rect.right() + size.width() < screen_geom.right(): x = source_rect.right() else: x = source_rect.left() - size.width() # bottom overflow dy = source_rect.top() + size.height() - screen_geom.bottom() if dy < 0: y = source_rect.top() else: y = source_rect.top() - dy else: # right overflow dx = source_rect.left() + size.width() - screen_geom.right() if dx < 0: x = source_rect.left() else: x = source_rect.left() - dx if source_rect.bottom() + size.height() < screen_geom.bottom(): y = source_rect.bottom() else: y = source_rect.top() - size.height() return QPoint(x, y)
def widget_popup_geometry(pos, widget): widget.ensurePolished() if widget.testAttribute(Qt.WA_Resized): size = widget.size() else: size = widget.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) return geom
def __init__(self, url): QWidget.__init__(self, None, Qt.ToolTip) self.url = url self.font = QFont(QApplication.font(self)) self.font.setPointSize(8) desktop = QApplication.desktop().availableGeometry(self) cursor = QCursor.pos() rect = QRect(cursor + QPoint(-10, 10), QSize(240,180 + QFontMetrics(self.font).height())) if rect.left() < desktop.left(): rect.moveLeft(desktop.left()) if rect.right() > desktop.right(): rect.moveRight(cursor.x() - 10) if rect.bottom() > desktop.bottom(): rect.moveBottom(cursor.y() - 10) self.setGeometry(rect) self.pixmap = None self.progress = 0 self.title = unicode(self.url) self.webView = QWebView() self.webView.page().mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.webView.page().mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self.webView.resize(1024,768) self.webView.load(QUrl(url)) self.timer = QTimer(self) self.connect(self.timer, SIGNAL("timeout()"), self.refresh) self.timer.start(3000) self.connect(self.webView, SIGNAL("loadFinished(bool)"), self.refresh) self.connect(self.webView, SIGNAL("loadProgress(int)"), self.updateProgress) self.connect(self.webView, SIGNAL("urlChanged(const QUrl&)"), self.newUrl) self.connect(self.webView, SIGNAL("titleChanged(const QString&)"), self.newTitle)
def paint(self, painter, option, index): painter.save() cell_width = self.size.width() #if option.state & QStyle.State_Selected: # painter.fillRect(option.rect, option.palette.highlight()) #painter.drawRect(option.rect) # Draw marks before translating painter # ===================================== # Draw avatar if not self.avatar: avatar_filepath = index.data(self.AvatarRole).toPyObject() self.avatar = QPixmap(avatar_filepath) x = option.rect.left() + (self.BOX_MARGIN * 2) y = option.rect.top() + (self.BOX_MARGIN * 2) rect = QRect(x, y, self.AVATAR_SIZE, self.AVATAR_SIZE) painter.drawPixmap(rect, self.avatar) # Draw verified account icon if index.data(self.VerifiedRole).toPyObject(): rect2 = QRect(rect.right() - 11, rect.bottom() - 10, 16, 16) painter.drawPixmap(rect2, self.verified_icon) marks_margin = 0 # Favorite mark if index.data(self.FavoritedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.favorite_icon) marks_margin = 16 # Draw reposted icon if index.data(self.RepeatedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN - marks_margin y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.repeated_icon) # Draw protected account icon protected_icon_margin = 0 if index.data(self.ProtectedRole).toPyObject(): x = option.rect.left() + self.BOX_MARGIN + self.AVATAR_SIZE + self.LEFT_MESSAGE_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.protected_icon) protected_icon_margin = 16 # ==== End of pixmap drawing ==== accumulated_height = 0 # Draw fullname fullname = self.__render_fullname(cell_width, index) x = option.rect.left() + self.BOX_MARGIN + self.AVATAR_SIZE x += self.LEFT_MESSAGE_MARGIN + protected_icon_margin y = option.rect.top() painter.translate(x, y) fullname.drawContents(painter) # Draw username username = self.__render_username(cell_width, index) painter.translate(fullname.idealWidth(), 0) username.drawContents(painter) # Draw status message x = -fullname.idealWidth() - protected_icon_margin y = fullname.size().height() + self.TOP_MESSAGE_MARGIN painter.translate(x, y) message = self.__render_status_message(cell_width, index) message.drawContents(painter) accumulated_height += y + message.size().height() # Draw reposted by x = self.BOX_MARGIN + 16 - (self.LEFT_MESSAGE_MARGIN + self.AVATAR_SIZE) y = message.size().height() + self.BOTTOM_MESSAGE_MARGIN if accumulated_height < self.AVATAR_SIZE: y += (self.AVATAR_SIZE - accumulated_height) + self.COMPLEMENT_HEIGHT painter.translate(x, y) reposted_by = index.data(self.RepostedRole).toPyObject() if reposted_by: reposted = QTextDocument() reposted.setHtml("<span style='color: #999;'>%s</span>" % reposted_by) reposted.setDefaultFont(FOOTER_FONT) reposted.setTextWidth(self.__calculate_text_width(cell_width)) reposted.drawContents(painter) # Draw reposted icon rect2 = QRect(-16, 3, 16, 16) painter.drawPixmap(rect2, self.reposted_icon) # Draw datetime datetime = index.data(self.DateRole).toPyObject() timestamp = QTextDocument() timestamp.setHtml("<span style='color: #999;'>%s</span>" % datetime) timestamp.setDefaultFont(FOOTER_FONT) timestamp.setTextWidth(self.__calculate_text_width(cell_width)) x = self.size.width() - timestamp.idealWidth() - 20 - self.BOX_MARGIN painter.translate(x, 0) timestamp.drawContents(painter) painter.resetTransform() painter.translate(0, option.rect.bottom()) line = QLine(0, 0, option.rect.width(), 0) painter.setPen(QColor(230, 230, 230)) painter.drawLine(line) painter.restore()
def paintInterface(self,painter,option,contentRect): # define some parameters padding = contentRect.height()/50 fontSize = contentRect.height()/35 txtFieldWidth = contentRect.width()/2 - 2*padding txtFieldHeight = contentRect.height()/20 current_img_width = contentRect.height()/3 current_img_height = contentRect.height()/3 whiteBrush10p = QBrush(QColor.fromCmyk(0,0,0,0,5)) whiteBrush20p = QBrush(QColor.fromCmyk(0,0,0,0,40)) fcRectWidth = (contentRect.width() - 4 * padding)/3 fcRectHeight = current_img_height + 2 * padding + 2 * txtFieldHeight textColor = Plasma.Theme.defaultTheme().color(Plasma.Theme.TextColor) bgColor = Plasma.Theme.defaultTheme().color(Plasma.Theme.BackgroundColor) textFont = Plasma.Theme.defaultTheme().font(Plasma.Theme.DefaultFont) # create text rects rect_text_location = QRect(contentRect.left() + padding ,contentRect.top() + 2*padding, 2*txtFieldWidth, txtFieldHeight) rect_text_temperature = QRect(contentRect.left() + padding ,contentRect.top() + 3* padding + 1 * txtFieldHeight , txtFieldWidth, txtFieldHeight) rect_text_condition = QRect(contentRect.left() + padding ,contentRect.top() + 4* padding + 2 * txtFieldHeight , txtFieldWidth, txtFieldHeight) rect_text_humidity = QRect(contentRect.left() + padding ,contentRect.top() + 5* padding + 3 * txtFieldHeight , txtFieldWidth, txtFieldHeight) rect_text_wind = QRect(contentRect.left() + padding , contentRect.top() + 6* padding + 4 * txtFieldHeight , txtFieldWidth, txtFieldHeight) painter.save() painter.setPen(textColor) textFont.setPointSize(fontSize) painter.setFont(textFont) painter.drawText(rect_text_location,Qt.Alignment(Qt.AlignLeft),"Location: " + self._weather.location) painter.drawText(rect_text_temperature,Qt.Alignment(Qt.AlignLeft),"Temperature: " + self._weather.current_temperature) painter.drawText(rect_text_condition,Qt.Alignment(Qt.AlignLeft),"Condition: " + self._weather.current_condition) painter.drawText(rect_text_humidity,Qt.Alignment(Qt.AlignLeft),self._weather.current_humidity) painter.drawText(rect_text_wind,Qt.Alignment(Qt.AlignLeft),self._weather.current_wind) svg_current = Plasma.Svg(self) curImgName = self._mapper.getMappedImageName(self._weather.current_condition) svg_current.setImagePath(self._image_prefix + curImgName) svg_current.resize(current_img_width,current_img_height) xOffset = contentRect.width()/2 + contentRect.width()/2 - current_img_width yOffset = contentRect.top() + txtFieldHeight + 2 * padding svg_current.paint(painter,contentRect.left() + xOffset, yOffset) # create forecast blocks fc_rect1 = QRect(contentRect.left() + padding, contentRect.bottom() - fcRectHeight, fcRectWidth, fcRectHeight) fc_rect2 = QRect(fc_rect1.right() + padding, contentRect.bottom() - fcRectHeight, fcRectWidth, fcRectHeight) fc_rect3 = QRect(fc_rect2.right() + padding, contentRect.bottom() - fcRectHeight, fcRectWidth, fcRectHeight) painter.setPen(bgColor) painter.setBrush(whiteBrush20p) painter.drawRect(fc_rect1) painter.drawRect(fc_rect3) painter.setBrush(whiteBrush10p) painter.drawRect(fc_rect2) # text rects for day list rect_text_dl1 = QRect(fc_rect1.left(),fc_rect1.top() + padding,fcRectWidth,txtFieldHeight) rect_text_dl2 = QRect(fc_rect2.left(),fc_rect2.top() + padding,fcRectWidth,txtFieldHeight) rect_text_dl3 = QRect(fc_rect3.left(),fc_rect3.top() + padding,fcRectWidth,txtFieldHeight) painter.setPen(textColor) painter.drawText(rect_text_dl1,Qt.Alignment(Qt.AlignCenter),self._weather.fc_dl[0]) painter.drawText(rect_text_dl2,Qt.Alignment(Qt.AlignCenter),self._weather.fc_dl[1]) painter.drawText(rect_text_dl3,Qt.Alignment(Qt.AlignCenter),self._weather.fc_dl[2]) fc_svg1 = Plasma.Svg() fc_svg2 = Plasma.Svg() fc_svg3 = Plasma.Svg() fc_svg1.setImagePath(self._image_prefix + self._mapper.getMappedImageName(self._weather.fc_conditions[0])) fc_svg2.setImagePath(self._image_prefix + self._mapper.getMappedImageName(self._weather.fc_conditions[1])) fc_svg3.setImagePath(self._image_prefix + self._mapper.getMappedImageName(self._weather.fc_conditions[2])) fc_svg1.resize(current_img_width,current_img_height) fc_svg2.resize(current_img_width,current_img_height) fc_svg3.resize(current_img_width,current_img_height) xOffSet = fc_rect1.left() + (fc_rect1.width() - current_img_width)/2 fc_svg1.paint(painter,xOffSet, fc_rect1.top() + txtFieldHeight + 2* padding) xOffSet = fc_rect2.left() + (fc_rect2.width() - current_img_width)/2 fc_svg2.paint(painter,xOffSet, fc_rect2.top() + txtFieldHeight + 2* padding) xOffSet = fc_rect3.left() + (fc_rect3.width() - current_img_width)/2 fc_svg3.paint(painter,xOffSet, fc_rect3.top() + txtFieldHeight + 2* padding) # text rects for high/low temperatures rect_text_temp1 = QRect(fc_rect1.left(),fc_rect1.bottom() - 3 * padding,fcRectWidth,txtFieldHeight) rect_text_temp2 = QRect(fc_rect2.left(),fc_rect2.bottom() - 3 * padding,fcRectWidth,txtFieldHeight) rect_text_temp3 = QRect(fc_rect3.left(),fc_rect3.bottom() - 3 * padding,fcRectWidth,txtFieldHeight) painter.setPen(textColor) painter.drawText(rect_text_temp1,Qt.Alignment(Qt.AlignCenter),self._weather.fc_low_high[0]) painter.drawText(rect_text_temp2,Qt.Alignment(Qt.AlignCenter),self._weather.fc_low_high[1]) painter.drawText(rect_text_temp3,Qt.Alignment(Qt.AlignCenter),self._weather.fc_low_high[2]) painter.restore()
class MapToolInteractive(QgsMapTool): """Tool to interact with map, including panning, zooming, and snapping""" def __init__(self, canvas, snappingEnabled=False): super(MapToolInteractive, self).__init__(canvas) self._active = False self._dragging = False self._panningEnabled = False self._zoomingEnabled = False self._zoomRubberBand = None # QgsRubberBand() self._zoomRect = None # QRect() self._snappingEnabled = snappingEnabled self._snapper = None # QgsMapCanvasSnapper() self._snappingMarker = None # QgsVertexMarker() def __del__(self): if self._active: self.deactivate() def isActive(self): return self._active def activate(self): super(MapToolInteractive, self).activate() self._active = True self._startSnapping() def deactivate(self): self._active = False if self._snappingEnabled: self._stopSnapping() if (self._zoomRubberBand is not None): self.canvas().scene().removeItem(self._zoomRubberBand) self._zoomRubberBand = None super(MapToolInteractive, self).deactivate() def setAction(self, action): super(MapToolInteractive, self).setAction(action) self.action().triggered.connect(self._activate) def _activate(self): self.canvas().setMapTool(self) def panningEnabled(self): return self._panningEnabled def setPanningEnabled(self, enabled): self._panningEnabled = enabled def zoomingEnabled(self): return self._zoomingEnabled def setZoomingEnabled(self, enabled): self._zoomingEnabled = enabled def snappingEnabled(self): return self._snappingEnabled def setSnappingEnabled(self, enabled): if (self._snappingEnabled == enabled): return self._snappingEnabled = enabled if not self._active: return if enabled: self._startSnapping() else: self._stopSnapping() def _startSnapping(self): self._snapper = QgsMapCanvasSnapper() self._snapper.setMapCanvas(self.canvas()) def _stopSnapping(self): self._deleteSnappingMarker() self._snapper = None def canvasMoveEvent(self, e): super(MapToolInteractive, self).canvasMoveEvent(e) if not self._active: return e.ignore() if (self._panningEnabled and e.buttons() & Qt.LeftButton): # Pan map mode if not self._dragging: self._dragging = True self.setCursor(QCursor(Qt.ClosedHandCursor)) self.canvas().panAction(e) e.accept() elif (self._zoomingEnabled and e.buttons() & Qt.RightButton): # Zoom map mode if not self._dragging: self._dragging = True self.setCursor(QCursor(Qt.ClosedHandCursor)) self._zoomRubberBand = QgsRubberBand(self.canvas(), QGis.Polygon) color = QColor(Qt.blue) color.setAlpha(63) self._zoomRubberBand.setColor(color) self._zoomRect = QRect(0, 0, 0, 0) self._zoomRect.setTopLeft(e.pos()) self._zoomRect.setBottomRight(e.pos()) if self._zoomRubberBand is not None: self._zoomRubberBand.setToCanvasRectangle(self._zoomRect) self._zoomRubberBand.show() e.accept() elif self._snappingEnabled: mapPoint, mapPointV2, snapped = self._snapCursorPoint(e.pos()) if (snapped): self._createSnappingMarker(mapPoint) else: self._deleteSnappingMarker() def canvasReleaseEvent(self, e): super(MapToolInteractive, self).canvasReleaseEvent(e) e.ignore() if (e.button() == Qt.LeftButton): if self._dragging: # Pan map mode self.canvas().panActionEnd(e.pos()) self.setCursor(CapturePointCursor) self._dragging = False e.accept() elif (e.button() == Qt.RightButton): if self._dragging: # Zoom mode self._zoomRect.setBottomRight(e.pos()) if (self._zoomRect.topLeft() != self._zoomRect.bottomRight()): coordinateTransform = self.canvas().getCoordinateTransform( ) ll = coordinateTransform.toMapCoordinates( self._zoomRect.left(), self._zoomRect.bottom()) ur = coordinateTransform.toMapCoordinates( self._zoomRect.right(), self._zoomRect.top()) r = QgsRectangle() r.setXMinimum(ll.x()) r.setYMinimum(ll.y()) r.setXMaximum(ur.x()) r.setYMaximum(ur.y()) r.normalize() if (r.width() != 0 and r.height() != 0): self.canvas().setExtent(r) self.canvas().refresh() self._dragging = False if (self._zoomRubberBand is not None): self.canvas().scene().removeItem(self._zoomRubberBand) self._zoomRubberBand = None e.accept() def keyPressEvent(self, e): super(MapToolInteractive, self).keyPressEvent(e) if (e.key() == Qt.Key_Escape): self.canvas().unsetMapTool(self) e.accept() def _snapCursorPoint(self, cursorPoint): res, snapResults = self._snapper.snapToBackgroundLayers(cursorPoint) if (res != 0 or len(snapResults) < 1): clicked = self.toMapCoordinates(cursorPoint) clickedV2 = QgsPointV2(clicked) return clicked, clickedV2, False else: # Take a copy as QGIS will delete the result! snapped = QgsPoint(snapResults[0].snappedVertex) snappedV2 = QgsPointV2(snapped) return snapped, snappedV2, True def _createSnappingMarker(self, snapPoint): if (self._snappingMarker is None): self._snappingMarker = QgsVertexMarker(self.canvas()) self._snappingMarker.setIconType(QgsVertexMarker.ICON_CROSS) self._snappingMarker.setColor(Qt.magenta) self._snappingMarker.setPenWidth(3) self._snappingMarker.setCenter(snapPoint) def _deleteSnappingMarker(self): if (self._snappingMarker is not None): self.canvas().scene().removeItem(self._snappingMarker) self._snappingMarker = None
def paint(self, painter, option, index): painter.save() cell_width = self.size.width() #if option.state & QStyle.State_Selected: # painter.fillRect(option.rect, option.palette.highlight()) #painter.drawRect(option.rect) # Draw marks before translating painter # ===================================== # Draw avatar if not self.avatar: avatar_filepath = index.data(self.AvatarRole).toPyObject() self.avatar = QPixmap(avatar_filepath) x = option.rect.left() + (self.BOX_MARGIN * 2) y = option.rect.top() + (self.BOX_MARGIN * 2) rect = QRect(x, y, self.AVATAR_SIZE, self.AVATAR_SIZE) painter.drawPixmap(rect, self.avatar) # Draw verified account icon if index.data(self.VerifiedRole).toPyObject(): rect2 = QRect(rect.right() - 11, rect.bottom() - 10, 16, 16) painter.drawPixmap(rect2, self.verified_icon) marks_margin = 0 # Favorite mark if index.data(self.FavoritedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.favorite_icon) marks_margin = 16 # Draw reposted icon if index.data(self.RepeatedRole).toPyObject(): x = cell_width - 16 - self.BOX_MARGIN - marks_margin y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.repeated_icon) # Draw protected account icon protected_icon_margin = 0 if index.data(self.ProtectedRole).toPyObject(): x = option.rect.left( ) + self.BOX_MARGIN + self.AVATAR_SIZE + self.LEFT_MESSAGE_MARGIN y = option.rect.top() + self.BOX_MARGIN rect = QRect(x, y, 16, 16) painter.drawPixmap(rect, self.protected_icon) protected_icon_margin = 16 # ==== End of pixmap drawing ==== accumulated_height = 0 # Draw fullname fullname = self.__render_fullname(cell_width, index) x = option.rect.left() + self.BOX_MARGIN + self.AVATAR_SIZE x += self.LEFT_MESSAGE_MARGIN + protected_icon_margin y = option.rect.top() painter.translate(x, y) fullname.drawContents(painter) # Draw username username = self.__render_username(cell_width, index) painter.translate(fullname.idealWidth(), 0) username.drawContents(painter) # Draw status message x = -fullname.idealWidth() - protected_icon_margin y = fullname.size().height() + self.TOP_MESSAGE_MARGIN painter.translate(x, y) message = self.__render_status_message(cell_width, index) message.drawContents(painter) accumulated_height += y + message.size().height() # Draw reposted by x = self.BOX_MARGIN + 16 - (self.LEFT_MESSAGE_MARGIN + self.AVATAR_SIZE) y = message.size().height() + self.BOTTOM_MESSAGE_MARGIN if accumulated_height < self.AVATAR_SIZE: y += (self.AVATAR_SIZE - accumulated_height) + self.COMPLEMENT_HEIGHT painter.translate(x, y) reposted_by = index.data(self.RepostedRole).toPyObject() if reposted_by: reposted = QTextDocument() reposted.setHtml("<span style='color: #999;'>%s</span>" % reposted_by) reposted.setDefaultFont(FOOTER_FONT) reposted.setTextWidth(self.__calculate_text_width(cell_width)) reposted.drawContents(painter) # Draw reposted icon rect2 = QRect(-16, 3, 16, 16) painter.drawPixmap(rect2, self.reposted_icon) # Draw datetime datetime = index.data(self.DateRole).toPyObject() timestamp = QTextDocument() timestamp.setHtml("<span style='color: #999;'>%s</span>" % datetime) timestamp.setDefaultFont(FOOTER_FONT) timestamp.setTextWidth(self.__calculate_text_width(cell_width)) x = self.size.width() - timestamp.idealWidth() - 20 - self.BOX_MARGIN painter.translate(x, 0) timestamp.drawContents(painter) painter.resetTransform() painter.translate(0, option.rect.bottom()) line = QLine(0, 0, option.rect.width(), 0) painter.setPen(QColor(230, 230, 230)) painter.drawLine(line) painter.restore()
class ArkMapToolInteractive(QgsMapTool): _active = False _dragging = False _panningEnabled = False _zoomingEnabled = False _zoomRubberBand = None #QgsRubberBand() _zoomRect = None # QRect() _snappingEnabled = False _snapper = None #QgsMapCanvasSnapper() _snappingMarker = None # QgsVertexMarker() _showSnappableVertices = False _snappableVertices = [] # [QgsPoint()] _snappableMarkers = [] # [QgsVertexMarker()] def __init__(self, canvas, snappingEnabled=False, showSnappableVertices=False): super(ArkMapToolInteractive, self).__init__(canvas) self._snappingEnabled = snappingEnabled self._showSnappableVertices = showSnappableVertices def __del__(self): if self._active: self.deactivate() def isActive(self): return self._active def activate(self): super(ArkMapToolInteractive, self).activate() self._active = True self._startSnapping() def deactivate(self): self._active = False if self._snappingEnabled: self._stopSnapping() if (self._zoomRubberBand is not None): self.canvas().scene().removeItem(self._zoomRubberBand) self._zoomRubberBand = None super(ArkMapToolInteractive, self).deactivate() def setAction(self, action): super(ArkMapToolInteractive, self).setAction(action) self.action().triggered.connect(self._activate) def _activate(self): self.canvas().setMapTool(self) def panningEnabled(self): return self._panningEnabled def setPanningEnabled(self, enabled): self._panningEnabled = enabled def zoomingEnabled(self): return self._zoomingEnabled def setZoomingEnabled(self, enabled): self._zoomingEnabled = enabled def snappingEnabled(self): return self._snappingEnabled def setSnappingEnabled(self, enabled): if (self._snappingEnabled == enabled): return self._snappingEnabled = enabled if not self._active: return if enabled: self._startSnapping() else: self._stopSnapping() def _startSnapping(self): self._snapper = QgsMapCanvasSnapper() self._snapper.setMapCanvas(self.canvas()) if self._showSnappableVertices: self._startSnappableVertices() def _stopSnapping(self): self._deleteSnappingMarker() self._snapper = None if self._showSnappableVertices: self._stopSnappableVertices() def showSnappableVertices(self): return self._showSnappableVertices def setShowSnappableVertices(self, show): if (self._showSnappableVertices == show): return self._showSnappableVertices = show if not self._active: return if show: self._startSnappableVertices() else: self._stopSnappableVertices() def _startSnappableVertices(self): self.canvas().layersChanged.connect(self._layersChanged) self.canvas().extentsChanged.connect(self._redrawSnappableMarkers) QgsProject.instance().snapSettingsChanged.connect(self._layersChanged) self._layersChanged() def _stopSnappableVertices(self): self._deleteSnappableMarkers() self._snappableLayers = [] self.canvas().layersChanged.disconnect(self._layersChanged) self.canvas().extentsChanged.disconnect(self._redrawSnappableMarkers) QgsProject.instance().snapSettingsChanged.disconnect(self._layersChanged) def canvasMoveEvent(self, e): super(ArkMapToolInteractive, self).canvasMoveEvent(e) if not self._active: return e.ignore() if (self._panningEnabled and e.buttons() & Qt.LeftButton): # Pan map mode if not self._dragging: self._dragging = True self.setCursor(QCursor(Qt.ClosedHandCursor)) self.canvas().panAction(e) e.accept() elif (self._zoomingEnabled and e.buttons() & Qt.RightButton): # Zoom map mode if not self._dragging: self._dragging = True self.setCursor(QCursor(Qt.ClosedHandCursor)) self._zoomRubberBand = QgsRubberBand(self.canvas(), QGis.Polygon) color = QColor(Qt.blue) color.setAlpha(63) self._zoomRubberBand.setColor(color) self._zoomRect = QRect(0, 0, 0, 0) self._zoomRect.setTopLeft(e.pos()) self._zoomRect.setBottomRight(e.pos()) if self._zoomRubberBand is not None: self._zoomRubberBand.setToCanvasRectangle(self._zoomRect) self._zoomRubberBand.show() e.accept() elif self._snappingEnabled: mapPoint, snapped = self._snapCursorPoint(e.pos()) if (snapped): self._createSnappingMarker(mapPoint) else: self._deleteSnappingMarker() def canvasReleaseEvent(self, e): super(ArkMapToolInteractive, self).canvasReleaseEvent(e) e.ignore() if (e.button() == Qt.LeftButton): if self._dragging: # Pan map mode self.canvas().panActionEnd(e.pos()) self.setCursor(capture_point_cursor) self._dragging = False e.accept() elif (e.button() == Qt.RightButton): if self._dragging: # Zoom mode self._zoomRect.setBottomRight(e.pos()) if (self._zoomRect.topLeft() != self._zoomRect.bottomRight()): coordinateTransform = self.canvas().getCoordinateTransform() ll = coordinateTransform.toMapCoordinates(self._zoomRect.left(), self._zoomRect.bottom()) ur = coordinateTransform.toMapCoordinates(self._zoomRect.right(), self._zoomRect.top()) r = QgsRectangle() r.setXMinimum(ll.x()) r.setYMinimum(ll.y()) r.setXMaximum(ur.x()) r.setYMaximum(ur.y()) r.normalize() if (r.width() != 0 and r.height() != 0): self.canvas().setExtent(r) self.canvas().refresh() self._dragging = False if (self._zoomRubberBand is not None): self.canvas().scene().removeItem(self._zoomRubberBand) self._zoomRubberBand = None e.accept() def keyPressEvent(self, e): super(ArkMapToolInteractive, self).keyPressEvent(e) if (e.key() == Qt.Key_Escape): self.canvas().unsetMapTool(self) e.accept() def _snapCursorPoint(self, cursorPoint): res, snapResults = self._snapper.snapToBackgroundLayers(cursorPoint) if (res != 0 or len(snapResults) < 1): return self.toMapCoordinates(cursorPoint), False else: # Take a copy as QGIS will delete the result! snappedVertex = QgsPoint(snapResults[0].snappedVertex) return snappedVertex, True def _createSnappingMarker(self, snapPoint): if (self._snappingMarker is None): self._snappingMarker = QgsVertexMarker(self.canvas()) self._snappingMarker.setIconType(QgsVertexMarker.ICON_CROSS) self._snappingMarker.setColor(Qt.magenta) self._snappingMarker.setPenWidth(3) self._snappingMarker.setCenter(snapPoint) def _deleteSnappingMarker(self): if (self._snappingMarker is not None): self.canvas().scene().removeItem(self._snappingMarker) self._snappingMarker = None def _createSnappableMarkers(self): if (not self._showSnappableVertices or not self._snappingEnabled): return extent = self.canvas().extent() for vertex in self._snappableVertices.asMultiPoint(): if (extent.contains(vertex)): marker = QgsVertexMarker(self.canvas()) marker.setIconType(QgsVertexMarker.ICON_X) marker.setColor(Qt.gray) marker.setPenWidth(1) marker.setCenter(vertex) self._snappableMarkers.append(marker) def _deleteSnappableMarkers(self): for marker in self._snappableMarkers: self.canvas().scene().removeItem(marker) del self._snappableMarkers[:] def _layersChanged(self): if (not self._showSnappableVertices or not self._snappingEnabled): return self._buildSnappableLayers() self._deleteSnappableMarkers() self._createSnappableMarkers() def _redrawSnappableMarkers(self): if (not self._showSnappableVertices or not self._snappingEnabled): return self._deleteSnappableMarkers() self._createSnappableMarkers() def _buildSnappableLayers(self): if (not self._showSnappableVertices or not self._snappingEnabled): return vertices = [] for layer in self.canvas().layers(): ok, enabled, type, units, tolerance, avoid = QgsProject.instance().snapSettingsForLayer(layer.id()) if (ok and enabled and not layer.isEditable()): for feature in layer.getFeatures(): geometry = feature.geometry() if geometry is None: pass elif geometry.type() == QGis.Point: vertices.extend([geometry.asPoint()]) elif geometry.type() == QGis.Line: vertices.extend(geometry.asPolyline()) elif geometry.type() == QGis.Polygon: lines = geometry.asPolygon() for line in lines: vertices.extend(line) self._snappableVertices = QgsGeometry.fromMultiPoint(vertices) self._snappableVertices.simplify(0)
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self): QObject.__init__(self) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not(self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): print "Setting Drawnnumer", num self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x()+0.0001, pos.y()+0.0001) line = self.moveTo(pos) return line def endDrawing(self, pos): self.moveTo(pos) tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height()))) painter.end() ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0] labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0)) labels = labels.swapaxes(0,1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() #print "BrushingModel.moveTo(pos=%r)" % (pos) line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(x,y), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize/2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize/2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) ) #update/move position self.pos = pos
class MincutConnec(QgsMapTool): canvasClicked = pyqtSignal() def __init__(self, iface, controller): """ Class constructor """ self.iface = iface self.canvas = self.iface.mapCanvas() self.controller = controller # Call superclass constructor and set current action QgsMapTool.__init__(self, self.canvas) self.dragging = False # Vertex marker color = QColor(255, 100, 255) self.vertex_marker = QgsVertexMarker(self.canvas) self.vertex_marker.setIconType(QgsVertexMarker.ICON_CIRCLE) self.vertex_marker.setColor(color) self.vertex_marker.setIconSize(15) self.vertex_marker.setPenWidth(3) # Rubber band self.rubber_band = QgsRubberBand(self.canvas, QGis.Line) self.rubber_band.setColor(color) self.rubber_band.setWidth(1) # Select rectangle self.select_rect = QRect() # TODO: Parametrize self.connec_group = ["Wjoin", "Tap", "Fountain", "Greentap"] #self.snapperManager = SnappingConfigManager(self.iface) self.snapper = QgsMapCanvasSnapper(self.canvas) def activate(self): pass def canvasPressEvent(self, event): #@UnusedVariable self.select_rect.setRect(0, 0, 0, 0) self.rubber_band.reset() def canvasMoveEvent(self, event): """ With left click the digitizing is finished """ if event.buttons() == Qt.LeftButton: if not self.dragging: self.dragging = True self.select_rect.setTopLeft(event.pos()) self.select_rect.setBottomRight(event.pos()) self.set_rubber_band() else: # Hide highlight self.vertex_marker.hide() # Get the click x = event.pos().x() y = event.pos().y() event_point = QPoint(x, y) # Snapping (retval, result) = self.snapper.snapToBackgroundLayers( event_point) # @UnusedVariable # That's the snapped point if result: # Check feature for snap_point in result: element_type = snap_point.layer.name() if element_type in self.connec_group: # Get the point point = QgsPoint(snap_point.snappedVertex) # Add marker self.vertex_marker.setCenter(point) self.vertex_marker.show() break def canvasReleaseEvent(self, event): """ With left click the digitizing is finished """ if event.button() == Qt.LeftButton: # Get the click x = event.pos().x() y = event.pos().y() event_point = QPoint(x, y) # Not dragging, just simple selection if not self.dragging: # Snap to node (retval, result) = self.snapper.snapToBackgroundLayers( event_point) # @UnusedVariable # That's the snapped point if result: # Check feature for snapped_point in result: element_type = snapped_point.layer.name() if element_type in self.connec_group: feat_type = 'connec' else: continue point = QgsPoint( snapped_point.snappedVertex) # @UnusedVariable # layer.removeSelection() # layer.select([result[0].snappedAtGeometry]) #snapped_point.layer.removeSelection() snapped_point.layer.select( [snapped_point.snappedAtGeometry]) else: # Set valid values for rectangle's width and height if self.select_rect.width() == 1: self.select_rect.setLeft(self.select_rect.left() + 1) if self.select_rect.height() == 1: self.select_rect.setBottom(self.select_rect.bottom() + 1) self.set_rubber_band() self.select_multiple_features(self.selected_rectangle) self.dragging = False # Refresh map canvas self.rubber_band.reset() self.refresh_map_canvas() def set_rubber_band(self): # Coordinates transform transform = self.canvas.getCoordinateTransform() # Coordinates ll = transform.toMapCoordinates(self.select_rect.left(), self.select_rect.bottom()) lr = transform.toMapCoordinates(self.select_rect.right(), self.select_rect.bottom()) ul = transform.toMapCoordinates(self.select_rect.left(), self.select_rect.top()) ur = transform.toMapCoordinates(self.select_rect.right(), self.select_rect.top()) # Rubber band self.rubber_band.reset() self.rubber_band.addPoint(ll, False) self.rubber_band.addPoint(lr, False) self.rubber_band.addPoint(ur, False) self.rubber_band.addPoint(ul, False) self.rubber_band.addPoint(ll, True) self.selected_rectangle = QgsRectangle(ll, ur) def select_multiple_features(self, rectangle): if self.connec_group is None: return if QGis.QGIS_VERSION_INT >= 21600: # Selection for all connec group layers for layer_name in self.connec_group: # Get layer by his name layer = self.controller.get_layer_by_layername(layer_name, log_info=True) if layer: self.group_pointers_connec.append(layer) layer.selectByRect(rectangle) else: for layer_name in self.connec_group: self.iface.setActiveLayer(layer) layer.removeSelection() layer.select(rectangle, True)
class ConnecMapTool(ParentMapTool): """ Button 20: User select connections from layer 'connec' Execute SQL function: 'gw_fct_connect_to_network' """ def __init__(self, iface, settings, action, index_action): """ Class constructor """ # Call ParentMapTool constructor super(ConnecMapTool, self).__init__(iface, settings, action, index_action) self.dragging = False # Select rectangle self.select_rect = QRect() """ QgsMapTools inherited event functions """ def canvasMoveEvent(self, event): """ With left click the digitizing is finished """ if event.buttons() == Qt.LeftButton: if not self.dragging: self.dragging = True self.select_rect.setTopLeft(event.pos()) self.select_rect.setBottomRight(event.pos()) self.set_rubber_band() else: # Hide marker self.vertex_marker.hide() # Get the click x = event.pos().x() y = event.pos().y() event_point = QPoint(x, y) # Snapping (retval, result) = self.snapper.snapToBackgroundLayers( event_point) # @UnusedVariable # That's the snapped features if result: for snapped_feat in result: # Check if it belongs to 'connec' or 'gully' group exist_connec = self.snapper_manager.check_connec_group( snapped_feat.layer) exist_gully = self.snapper_manager.check_gully_group( snapped_feat.layer) if exist_connec or exist_gully: # Get the point and add marker point = QgsPoint(result[0].snappedVertex) self.vertex_marker.setCenter(point) self.vertex_marker.show() break def canvasPressEvent(self, event): #@UnusedVariable self.select_rect.setRect(0, 0, 0, 0) self.rubber_band.reset(QGis.Polygon) def canvasReleaseEvent(self, event): """ With left click the digitizing is finished """ if event.button() == Qt.LeftButton: # Get the click x = event.pos().x() y = event.pos().y() event_point = QPoint(x, y) # Simple selection if not self.dragging: # Snap to connec or gully (retval, result) = self.snapper.snapToBackgroundLayers( event_point) # @UnusedVariable # That's the snapped features if result: # Check if it belongs to 'connec' or 'gully' group exist_connec = self.snapper_manager.check_connec_group( result[0].layer) exist_gully = self.snapper_manager.check_gully_group( result[0].layer) if exist_connec or exist_gully: key = QApplication.keyboardModifiers() # If Ctrl+Shift is clicked: deselect snapped feature if key == (Qt.ControlModifier | Qt.ShiftModifier): result[0].layer.deselect( [result[0].snappedAtGeometry]) else: # If Ctrl is not clicked: remove previous selection if key != Qt.ControlModifier: result[0].layer.removeSelection() result[0].layer.select( [result[0].snappedAtGeometry]) # Hide marker self.vertex_marker.hide() # Multiple selection else: # Set valid values for rectangle's width and height if self.select_rect.width() == 1: self.select_rect.setLeft(self.select_rect.left() + 1) if self.select_rect.height() == 1: self.select_rect.setBottom(self.select_rect.bottom() + 1) self.set_rubber_band() selected_geom = self.rubber_band.asGeometry() #@UnusedVariable self.select_multiple_features(self.selected_rectangle) self.dragging = False # Refresh map canvas self.rubber_band.reset() elif event.button() == Qt.RightButton: # Check selected records number_features = 0 for layer in self.layer_connec_man: number_features += layer.selectedFeatureCount() if number_features > 0: message = ("Number of features selected in the 'connec' group") title = "Interpolate value - Do you want to update values" answer = self.controller.ask_question( message, title, parameter=str(number_features)) if answer: # Create link self.link_selected_features('connec', self.layer_connec_man) if self.layer_gully_man: # Check selected records number_features = 0 for layer in self.layer_gully_man: number_features += layer.selectedFeatureCount() if number_features > 0: message = ( "Number of features selected in the 'gully' group") title = "Interpolate value - Do you want to update values" answer = self.controller.ask_question( message, title, parameter=str(number_features)) if answer: # Create link self.link_selected_features('gully', self.layer_gully_man) def activate(self): # Check button self.action().setChecked(True) # Rubber band self.rubber_band.reset() # Store user snapping configuration self.snapper_manager.store_snapping_options() # Clear snapping self.snapper_manager.clear_snapping() # Set snapping to 'connec' and 'gully' self.snapper_manager.snap_to_connec_gully() # Change cursor cursor = self.get_cursor_multiple_selection() self.canvas.setCursor(cursor) # Show help message when action is activated if self.show_help: message = "Right click to use current selection, select connec points by clicking or dragging (selection box)" self.controller.show_info(message) def deactivate(self): # Call parent method ParentMapTool.deactivate(self) def link_selected_features(self, geom_type, layers): """ Link selected @geom_type to the pipe """ # Check features selected number_features = 0 for layer in layers: number_features += layer.selectedFeatureCount() if number_features == 0: message = "You have to select at least one feature!" self.controller.show_warning(message) return # Get selected features from layers of selected @geom_type aux = "{" field_id = geom_type + "_id" # Iterate over all layers for layer in layers: if layer.selectedFeatureCount() > 0: # Get selected features of the layer features = layer.selectedFeatures() for feature in features: feature_id = feature.attribute(field_id) aux += str(feature_id) + ", " list_feature_id = aux[:-2] + "}" # Execute function function_name = "gw_fct_connect_to_network" sql = ("SELECT " + self.schema_name + "." + function_name + "" "('" + list_feature_id + "', '" + geom_type.upper() + "');") self.controller.execute_sql(sql, log_sql=True) layer.removeSelection() # Refresh map canvas self.rubber_band.reset() self.refresh_map_canvas() self.iface.actionPan().trigger() def set_rubber_band(self): # Coordinates transform transform = self.canvas.getCoordinateTransform() # Coordinates ll = transform.toMapCoordinates(self.select_rect.left(), self.select_rect.bottom()) lr = transform.toMapCoordinates(self.select_rect.right(), self.select_rect.bottom()) ul = transform.toMapCoordinates(self.select_rect.left(), self.select_rect.top()) ur = transform.toMapCoordinates(self.select_rect.right(), self.select_rect.top()) # Rubber band self.rubber_band.reset(QGis.Polygon) self.rubber_band.addPoint(ll, False) self.rubber_band.addPoint(lr, False) self.rubber_band.addPoint(ur, False) self.rubber_band.addPoint(ul, False) self.rubber_band.addPoint(ll, True) self.selected_rectangle = QgsRectangle(ll, ur) def select_multiple_features(self, selectGeometry): if self.layer_connec_man is None and self.layer_gully_man is None: return key = QApplication.keyboardModifiers() # If Ctrl+Shift clicked: remove features from selection if key == (Qt.ControlModifier | Qt.ShiftModifier): behaviour = QgsVectorLayer.RemoveFromSelection # If Ctrl clicked: add features to selection elif key == Qt.ControlModifier: behaviour = QgsVectorLayer.AddToSelection # If Ctrl not clicked: add features to selection else: behaviour = QgsVectorLayer.AddToSelection # Selection for all connec and gully layers for layer in self.layer_connec_man: layer.selectByRect(selectGeometry, behaviour) if self.layer_gully_man: for layer in self.layer_gully_man: layer.selectByRect(selectGeometry, behaviour)
class AbstractScrollTela(TelaConsole): def __init__(self, altura, parent=None): super().__init__(parent=parent) self._rectTela = QRect(0,0,0,altura) self._mostrarHorizontal = False self._mostrarVertical = False self._scrollHorizontal = ScrollBarConsole(3,0,orientacao=ScrollBarConsole.HORIZONTAL,parent=self) self._scrollVertical = ScrollBarConsole(self._rectTela.height(),0,orientacao=ScrollBarConsole.VERTICAL,parent=self) self._scrollHorizontal.valorScrollModificado.connect(self._moverHorizontal) self._scrollVertical.valorScrollModificado.connect(self._moverVertical) self._scrollBarFocus = ScrollBarConsole(3,0,parent=self) self._scrollBarFocus.installEventFilter(self) def eventFilter(self, obj, event): if obj == self._scrollBarFocus and event.type() != EventoTecladoConsole.TabType: self._scrollVertical.customEvent(event) self._scrollHorizontal.customEvent(event) return True else: return False def acceptFocus(self): return True def focusNextChild(self): if self._scrollBarFocus.hasFocus(): return False if self.hasFocus(): if not (self._mostrarVertical or self._mostrarHorizontal): return False self._scrollBarFocus.setFocus() else: if not self.acceptFocus(): return False self.setFocus() return True def focusPrevChild(self): if self.hasFocus(): return False if self._scrollBarFocus.hasFocus(): if self.acceptFocus(): self.setFocus() else: return False else: self._scrollBarFocus.setFocus() return True def indexChildActive(self): if self._scrollBarFocus.hasFocus(): return 0 return -1 def getRectTela(self): return self._rectTela def _moverVertical(self, valor): self._scrollVertical.setValorAtual(valor) self._rectTela.moveTop(valor) def _moverHorizontal(self, valor): self._scrollHorizontal.setValorAtual(valor) self._rectTela.moveLeft(valor) def deixarVisivelVertical(self, valor): top = self.getRectTela().top() height = self.getRectTela().height() - self._numLinhasFixas() - 1 bottom = top + height if valor < top: self._moverVertical(valor) elif valor > bottom: self._moverVertical(valor - height) def deixarVisivelHorizontal(self, valor): left = self.getRectTela().left() width = self.getRectTela().width()-1 right = left + width if valor < left: self._moverHorizontal(valor) elif valor > right: self._moverHorizontal(valor - width) def scrollContentsBy(self, dx, dy): self._rectTela.translate(dx,dy) def getDesenhoTela(self): raise NotImplemented("Metodo abstrato") def _adicionarScrollBar(self, tela): if self._mostrarVertical: tela = self._adicionarScrollVertical(tela) if self._mostrarHorizontal: tela = self._adicionarScrollHorizontal(tela) return tela def _adicionarScrollVertical(self, texto): scroll = '' for i in self._scrollVertical.desenhoTelaConsole(self._rectTela.width()).split('\n'): scroll += "{0}|\n".format(i) scroll = "-|\n{0}-|".format(scroll).split('\n') s = '' texto = texto.split('\n') for i in range(len(texto)): s += "{0:{1}}{2}\n".format(texto[i], self._rectTela.width()+2, scroll[i]) if s.endswith('\n'): s = s[:len(s)-1] return s def _adicionarScrollHorizontal(self, texto): texto += '\n|{0}|{1}\n'.format(self._scrollHorizontal.desenhoTelaConsole(self._rectTela.width()), 'X|' if self._mostrarVertical else '') texto += '|{0:-<{1}}|{2}'.format('', self._rectTela.width(), '-|' if self._mostrarVertical else '') return texto def _ajustarScroll(self, tela): linhas = tela.split('\n') numColunas = max(map(len, linhas)) numLinhasFixas = self._numLinhasFixas() numLinhas = len(linhas) + numLinhasFixas self._mostrarVertical = numLinhas > self._rectTela.height() self._mostrarHorizontal = numColunas > self._rectTela.width() self._scrollHorizontal.setAteValor(max(0, numColunas-self._rectTela.width())) self._scrollVertical.setAteValor(max(0, numLinhas-self._rectTela.height())) def _adicionarLinhasFixas(self, tela): """Esse método deve ser sobrescrito pela classe filha para adicionar as linhas fixas na tela""" return tela def _numLinhasFixas(self): return self._adicionarLinhasFixas('').count('\n') def _linhasVisiveis(self, tela): linhas = tela.split('\n') numLinhasFixas = self._numLinhasFixas() numLinhas = len(linhas) + numLinhasFixas if numLinhas < self._rectTela.height(): tela = self._adicionarLinhasFixas(tela) tela += '\n'*(self._rectTela.height()-numLinhas) else: top = self.getRectTela().top() bottom = self.getRectTela().bottom()+1 return self._adicionarLinhasFixas('\n'.join(linhas[top:bottom - numLinhasFixas])) return tela def _colunasVisiveis(self, tela): linhas = tela.split('\n') numColunas = max(map(len, linhas))+1 if numColunas > self._rectTela.width(): tela = '\n'.join([linha[self._rectTela.left():self._rectTela.right()+1] for linha in linhas]) return tela def _ajustarTela(self, tela): tela = self._linhasVisiveis(tela) tela = self._colunasVisiveis(tela) return tela def desenhoTela(self, tam): tela = self.getDesenhoTela() self._ajustarScroll(tela) if self._mostrarVertical: tam -= 2 if tam-2 != self._rectTela.width(): self._rectTela.setWidth(tam-2) self._scrollHorizontal.setTamanho(tam-2) self._ajustarScroll(tela) tela = self._ajustarTela(tela) tela = self._colocarBorda(tela, tam) return self._adicionarScrollBar(tela)
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not(self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert(self.pos == pos) self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, target=QRectF(), source=QRectF(QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height()))) painter.end() ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0] labels = numpy.where(ndarr>0,numpy.uint8(self.drawnNumber),numpy.uint8(0)) labels = labels.swapaxes(0,1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0: labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX,oldY), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize/2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize/2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize/2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize/2+1) ) ) #update/move position self.pos = pos
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not (self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b - 1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b + 1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert (self.pos == pos) self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001)) # move a little tempi = QImage(QSize(self.bb.width(), self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) self.scene.render(painter, target=QRectF(), source=QRectF( QPointF(self.bb.x(), self.bb.y()), QSizeF(self.bb.width(), self.bb.height()))) painter.end() ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0] labels = numpy.where(ndarr > 0, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0, 1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero( labels) == 0: labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen( QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) #grow bounding box self.bb.setLeft(min(self.bb.left(), max(0, x - self.brushSize / 2 - 1))) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize / 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize / 2 - 1))) self.bb.setBottom( max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize / 2 + 1))) #update/move position self.pos = pos
class ImageView(QtGui.QScrollArea): def __init__(self,parent): '''constructor of ImageView''' QtGui.QWidget.__init__(self) self.parent = parent self.selection = None self.image = None self.zoom = 100 #if (!ic) ic=new IconCache(); self.setFocusPolicy(QtCore.Qt.WheelFocus) self.setSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding) self.d =ImageViewPrivate(self) self.setWidget(self.d) self.setWidgetResizable(True) self.setBackgroundRole(QtGui.QPalette.Dark) self.setMouseTracking(True) self.mouse_x = -1 self.mouse_y = -1 self.mouse_ex = 0 self.mouse_ey = 0 self.data_rect = QtCore.QRect(0,0,1,1) #self.setMode(view) def saveImage(self,name): '''Save image in viewer under given name''' if self.image: save_success = self.image.saveImage(name) if save_success: return True else : return False else: print("[ImageView][Save Image Failed]:No image to save") return False def selectionFromImageCoords(self,selectionRect): '''Return selection rectangle converted from image coordinate system to window coordinate syste''' x= (selectionRect.left())*self.data_rect.width()/self.image.x()+self.data_rect.left() y= (selectionRect.top())*self.data_rect.height()/self.image.y()+self.data_rect.top() xr=(selectionRect.right()+1)*self.data_rect.width()/self.image.x()+self.data_rect.left()-1 yr=(selectionRect.bottom()+1)*self.data_rect.height()/self.image.y()+self.data_rect.top()-1 return QRect(x,y,xr,yr) def selectPointToImageCoords(self,point): '''Return selected point converted to image coordinate system''' dw=self.data_rect.width() dh=self.data_rect.height() x=int(floor((point.x()-self.data_rect.left())* self.image.x()/dw))-1 y=int(floor((point.y()-self.data_rect.top())* self.image.y()/dh))-1 return QPoint(x,y) def selectionToImageCoords(self,selectionRect): '''Return selection rectangle converted to image coordinate system@param selectionRect rectangle to convert''' dw=self.data_rect.width() dh=self.data_rect.height() x=int(floor((selectionRect.left()-self.data_rect.left())* self.image.x()/dw)) y=int(floor((selectionRect.top()-self.data_rect.top())* self.image.y()/dh)) xr=int(floor((selectionRect.right()-self.data_rect.left()) * self.image.x()/dw)) yr=int(floor((selectionRect.bottom()-self.data_rect.top())*self.image.y()/dh)) #print(QRect(x,y,xr,yr)) return QRect(x,y,xr,yr) def setDataRect(self): '''Update data_rect''' #Get image dimensions dx=self.image.x() dy=self.image.y() if dx == 0 or dy == 0: print("Null Image") return #printInfo ="setDataRect %f_%f" %(dx,dy) #print(printInfo) #Get image screen dimensions (may differ if zoom is set) screen_dx=dx*self.zoom/100.0 screen_dy=dy*self.zoom/100.0 x=self.d.width() y=self.d.height() wx=x wy=dy*wx/dx if wy > y: wy=y wx=dx*wy/dy if self.isSet("center"):#居中画图而不拉伸 self.data_rect=QRect(max((x-screen_dx)/2,0),max((y-screen_dy)/2,0),screen_dx,screen_dy) else: self.data_rect=QRect(max((x-wx)/2,0),max((y-wy)/2,0),wx,wy) def getSelection(self): '''return the selection rectangle from (x0,y0,x1,y1) to (x,y,width,height)''' if not self.selection: return None width = self.selection.width() - self.selection.left() height = self.selection.height() - self.selection.top() return QRect(self.selection.left(),self.selection.top(),width,height) def repaint(self,x,y,p,src): '''Repaint the image using given painter and size of output window @param x width of output window @param y height of output window @param p QPainter to use @param src Which part of image to repaint (when not in fullscreen)''' '''TypeError: QPainter.setRenderHint(QPainter.RenderHint, bool on=True): first argument of unbound method must have type 'QPainter''' #p.setRenderHint(QtGui.QPainter.SmoothPixmapTransform,True) p.setRenderHint(QtGui.QPainter.Antialiasing,True) p.setPen = Qt.blue black = QtGui.QColor(0,0,0) if not self.image: #No image is loaded p.drawRect(0,0,x-1,y-1) p.fillRect(1,1,x-2,y-2,black) p.drawText(0,0,x,y,Qt.AlignVCenter | Qt.AlignCenter,QString(NOIMAGELOAD)) return if self.image.x<=0 and self.image.y()<=0: #Invalid image is loaded p.drawRect(0,0,x-1,y-1) p.fillRect(1,1,x-2,y-2,black) p.drawText(0,0,x,y,Qt.AlignVCenter | Qt.AlignCenter,QString("Invalid image")) return #Rectangle specifying entire window rect = QRect(0,0,x,y) #Determine target rectangle at screen #Update data rectangle for mouse navigation self.setDataRect() #Repaint stripes around image if needed if self.data_rect.left() > src.left(): #repaint stripe on left tmp = QRect(0,0,self.data_rect.left(),y) p.fillRect(tmp & src,black) if self.data_rect.right()<src.right(): #repaint on right tmp = QRect(self.data_rect.right(),0,x-self.data_rect.right(),y) p.fillRect(tmp & src,black) if self.data_rect.top()>src.top(): #repaint on top tmp = QRect(self.data_rect.left(),0,self.data_rect.width(),self.data_rect.top()) p.fillRect(tmp & src,black) if self.data_rect.bottom()<src.bottom(): #repaint on bottom tmp = QRect(self.data_rect.left(),self.data_rect.bottom(),self.data_rect.width(),y-self.data_rect.bottom()) p.fillRect(tmp & src,black) #Show scaled to window #Set target to data rectangle target=self.data_rect #Draw entire image scaled source = QRect(0,0,self.image.x(),self.image.y()) self.image.draw(p,source,target)#Stop Here def getImage(self): ''' Return image shown in the widget (or NULL if nothing is shown) If the image is modified, update() should be called to redraw the new image''' return self.image def moveRubberBand(self,newGeom): '''Move the rubberband after updating the zoom level''' if not rb: return self.rb.setGeometry(newGeom) def rectCheck(self): ''' Called when selection is finished (on releasing the mouse button) and on start''' pass #if self.selection.isValid(): ##"Snap rect to grid" #self.setDataRect() #self.d.moveRubberBand(self.selectionFromImageCoords(self.selection)) def cancelRect(self): self.d.cancelRect() self.rectCheck() def flushImage(self): '''Use after new image is loaded to flush/redraw various data''' self.update() self.cancelRect() #emit zoomChanged(zoom); #emit info(""); def loadImage(self,name): '''Open image with given name in viewer''' if self.image: del self.image self.image = Image(name) if not self.image: return False self.flushImage() return True def sizeHint(self): '''sizeHint() 方法给出一个推荐的大小。这里我们重写这个方法''' '''Return size hint for the widget''' if self.image: #Size of image return QtCore.QSize(self.image.x(),self.image.y()) else: #Some default,very Important return QtCore.QSize(840,630) #Load state of specified optional feature from settings (default value is false) def isSet(self,name): globalSettings = QtCore.QSettings("JiZhe","CTAnalysis") return globalSettings.value("view/"+name).toBool() #Return minimum size neede to display the widget def minSize(self): if self.image : #if self.image and self.isSet("scale"): #Size of image x = self.image.x() y = self.image.y() x = x * self.zoom / 100.0 y = y * self.zoom / 100.0 return QtCore.QSize(x,y) else: #No minimum return QtCore.QSize(0,0) #Change internal widget's minimum size.Schedule this and internal widget to repaint. def update(self): self.d.setMinimumSize(self.minSize()) self.d.update() #QtGui.QScrollArea.update()? def mouseCoordEvent(self,e): pass def selPoint(self,point): '''Select a point and then do region grow''' region_grow_seed_point = self.selectPointToImageCoords(point) self.parent.region_grow(region_grow_seed_point) def selRect(self,r): '''Update selection rectangle position''' if r.width()<=0 or r.height()<=0: self.selection=QRect() else: self.selection = self.selectionToImageCoords(r) #print(self.selection) x1=self.selection.left() x2=self.selection.right() y1=self.selection.top() y2=self.selection.bottom() w=self.selection.width() h=self.selection.height()
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not(self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b-1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b+1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert(self.pos == pos) self.moveTo(QPointF(pos.x()+0.0001, pos.y()+0.0001)) # move a little # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage. # We seem to get better results if we do the following: # 1) Slightly offset the source window because apparently there is a small shift in the data # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x) # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image, # applying some threshold to determine if the final pixel is on or off. tempi = QImage(QSize(4*self.bb.width(), 4*self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) # Offset the source window. At first I thought the right offset was 0.5, because # that would seem to make sure points are rounded to pixel CENTERS, but # experimentation indicates that 0.25 is slightly better for some reason... source_rect = QRectF( QPointF(self.bb.x()+0.25, self.bb.y()+0.25), QSizeF(self.bb.width(), self.bb.height()) ) target_rect = QRectF( QPointF(0,0), QSizeF(4*self.bb.width(), 4*self.bb.height()) ) self.scene.render(painter, target=target_rect, source=source_rect) painter.end() # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing ndarr = qimage2ndarray.rgb_view(tempi)[:,:,0].astype(int) ndarr = ndarr.reshape( (ndarr.shape[0],) + (ndarr.shape[1]//4,) + (4,) ) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr = ndarr.reshape( (ndarr.shape[0],) + (ndarr.shape[1]//4,) + (4,) ) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr //= 4*4 downsample_threshold = (7./16)*255 labels = numpy.where(ndarr>=downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0,1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0: labels[labels.shape[0]//2, labels.shape[1]//2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x,y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen(QPen( QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX,oldY), QSize(1,1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x-self.brushSize//2-1) ) ) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0]-1, x+self.brushSize//2+1) ) ) self.bb.setTop( min(self.bb.top(), max(0, y-self.brushSize//2-1) ) ) self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1]-1, y+self.brushSize//2+1) ) ) #update/move position self.pos = pos
def __layout(self): # position itself over `widget` widget = self.__widget if widget is None: return alignment = self.__alignment policy = self.sizePolicy() if widget.isWindow(): bounds = widget.geometry() else: bounds = QRect(widget.mapToGlobal(QPoint(0, 0)), widget.size()) if self.isWindow(): bounds = bounds else: bounds = QRect(self.parent().mapFromGlobal(bounds.topLeft()), bounds.size()) sh = self.sizeHint() minsh = self.minimumSizeHint() minsize = self.minimumSize() if minsize.isNull(): minsize = minsh maxsize = bounds.size().boundedTo(self.maximumSize()) minsize = minsize.boundedTo(maxsize) effectivesh = sh.expandedTo(minsize).boundedTo(maxsize) hpolicy = policy.horizontalPolicy() vpolicy = policy.verticalPolicy() def getsize(hint, minimum, maximum, policy): if policy == QSizePolicy.Ignored: return maximum elif policy & QSizePolicy.ExpandFlag: return maximum else: return max(hint, minimum) width = getsize(effectivesh.width(), minsize.width(), maxsize.width(), hpolicy) heightforw = self.heightForWidth(width) if heightforw > 0: height = getsize(heightforw, minsize.height(), maxsize.height(), vpolicy) else: height = getsize(effectivesh.height(), minsize.height(), maxsize.height(), vpolicy) size = QSize(width, height) if alignment & Qt.AlignLeft: x = bounds.x() elif alignment & Qt.AlignRight: x = bounds.right() - size.width() else: x = bounds.x() + max(0, bounds.width() - size.width()) // 2 if alignment & Qt.AlignTop: y = bounds.y() elif alignment & Qt.AlignBottom: y = bounds.bottom() - size.height() else: y = bounds.y() + max(0, bounds.height() - size.height()) // 2 geom = QRect(QPoint(x, y), size) self.setGeometry(geom)
def __paintEventNoStyle(self): p = QPainter(self) opt = QStyleOptionToolButton() self.initStyleOption(opt) fm = QFontMetrics(opt.font) palette = opt.palette # highlight brush is used as the background for the icon and background # when the tab is expanded and as mouse hover color (lighter). brush_highlight = palette.highlight() if opt.state & QStyle.State_Sunken: # State 'down' pressed during a mouse press (slightly darker). background_brush = brush_darker(brush_highlight, 110) elif opt.state & QStyle.State_MouseOver: background_brush = brush_darker(brush_highlight, 95) elif opt.state & QStyle.State_On: background_brush = brush_highlight else: # The default button brush. background_brush = palette.button() rect = opt.rect icon = opt.icon icon_size = opt.iconSize # TODO: add shift for pressed as set by the style (PM_ButtonShift...) pm = None if not icon.isNull(): if opt.state & QStyle.State_Enabled: mode = QIcon.Normal else: mode = QIcon.Disabled pm = opt.icon.pixmap( rect.size().boundedTo(icon_size), mode, QIcon.On if opt.state & QStyle.State_On else QIcon.Off) icon_area_rect = QRect(rect) icon_area_rect.setRight(int(icon_area_rect.height() * 1.26)) text_rect = QRect(rect) text_rect.setLeft(icon_area_rect.right() + 10) # Background (TODO: Should the tab button have native # toolbutton shape, drawn using PE_PanelButtonTool or even # QToolBox tab shape) # Default outline pen pen = QPen(palette.color(QPalette.Mid)) p.save() p.setPen(Qt.NoPen) p.setBrush(QBrush(background_brush)) p.drawRect(rect) # Draw the background behind the icon if the background_brush # is different. if not opt.state & QStyle.State_On: p.setBrush(brush_highlight) p.drawRect(icon_area_rect) # Line between the icon and text p.setPen(pen) p.drawLine(icon_area_rect.topRight(), icon_area_rect.bottomRight()) if opt.state & QStyle.State_HasFocus: # Set the focus frame pen and draw the border pen = QPen(QColor(FOCUS_OUTLINE_COLOR)) p.setPen(pen) p.setBrush(Qt.NoBrush) # Adjust for pen rect = rect.adjusted(0, 0, -1, -1) p.drawRect(rect) else: p.setPen(pen) # Draw the top/bottom border if self.position == QStyleOptionToolBoxV2.OnlyOneTab or \ self.position == QStyleOptionToolBoxV2.Beginning or \ self.selected & \ QStyleOptionToolBoxV2.PreviousIsSelected: p.drawLine(rect.topLeft(), rect.topRight()) p.drawLine(rect.bottomLeft(), rect.bottomRight()) p.restore() p.save() text = fm.elidedText(opt.text, Qt.ElideRight, text_rect.width()) p.setPen(QPen(palette.color(QPalette.ButtonText))) p.setFont(opt.font) p.drawText(text_rect, int(Qt.AlignVCenter | Qt.AlignLeft) | \ int(Qt.TextSingleLine), text) if pm: pm_rect = QRect(QPoint(0, 0), pm.size()) centered_rect = QRect(pm_rect) centered_rect.moveCenter(icon_area_rect.center()) p.drawPixmap(centered_rect, pm, pm_rect) p.restore()
class BrushingModel(QObject): brushSizeChanged = pyqtSignal(int) brushColorChanged = pyqtSignal(QColor) brushStrokeAvailable = pyqtSignal(QPointF, object) drawnNumberChanged = pyqtSignal(int) minBrushSize = 1 maxBrushSize = 61 defaultBrushSize = 3 defaultDrawnNumber = 1 defaultColor = Qt.white erasingColor = Qt.black erasingNumber = 100 def __init__(self, parent=None): QObject.__init__(self, parent=parent) self.sliceRect = None self.bb = QRect() #bounding box enclosing the drawing self.brushSize = self.defaultBrushSize self.drawColor = self.defaultColor self._temp_color = None self._temp_number = None self.drawnNumber = self.defaultDrawnNumber self.pos = None self.erasing = False self._hasMoved = False self.drawOnto = None #an empty scene, where we add all drawn line segments #a QGraphicsLineItem, and which we can use to then #render to an image self.scene = QGraphicsScene() def toggleErase(self): self.erasing = not (self.erasing) if self.erasing: self.setErasing() else: self.disableErasing() def setErasing(self): self.erasing = True self._temp_color = self.drawColor self._temp_number = self.drawnNumber self.setBrushColor(self.erasingColor) self.brushColorChanged.emit(self.erasingColor) self.setDrawnNumber(self.erasingNumber) def disableErasing(self): self.erasing = False self.setBrushColor(self._temp_color) self.brushColorChanged.emit(self.drawColor) self.setDrawnNumber(self._temp_number) def setBrushSize(self, size): self.brushSize = size self.brushSizeChanged.emit(self.brushSize) def setDrawnNumber(self, num): self.drawnNumber = num self.drawnNumberChanged.emit(num) def getBrushSize(self): return self.brushSize def brushSmaller(self): b = self.brushSize if b > self.minBrushSize: self.setBrushSize(b - 1) def brushBigger(self): b = self.brushSize if self.brushSize < self.maxBrushSize: self.setBrushSize(b + 1) def setBrushColor(self, color): self.drawColor = color self.brushColorChanged.emit(self.drawColor) def beginDrawing(self, pos, sliceRect): ''' pos -- QPointF-like ''' self.sliceRect = sliceRect self.scene.clear() self.bb = QRect() self.pos = QPointF(pos.x(), pos.y()) self._hasMoved = False def endDrawing(self, pos): has_moved = self._hasMoved # _hasMoved will change after calling moveTo if has_moved: self.moveTo(pos) else: assert (self.pos == pos) self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001)) # move a little # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage. # We seem to get better results if we do the following: # 1) Slightly offset the source window because apparently there is a small shift in the data # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x) # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image, # applying some threshold to determine if the final pixel is on or off. tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()), QImage.Format_ARGB32_Premultiplied) #TODO: format tempi.fill(0) painter = QPainter(tempi) # Offset the source window. At first I thought the right offset was 0.5, because # that would seem to make sure points are rounded to pixel CENTERS, but # experimentation indicates that 0.25 is slightly better for some reason... source_rect = QRectF(QPointF(self.bb.x() + 0.25, self.bb.y() + 0.25), QSizeF(self.bb.width(), self.bb.height())) target_rect = QRectF(QPointF(0, 0), QSizeF(4 * self.bb.width(), 4 * self.bb.height())) self.scene.render(painter, target=target_rect, source=source_rect) painter.end() # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int) ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) + (4, )) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) + (4, )) ndarr = ndarr.sum(axis=-1) ndarr = ndarr.transpose() ndarr //= 4 * 4 downsample_threshold = (7. / 16) * 255 labels = numpy.where(ndarr >= downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0)) labels = labels.swapaxes(0, 1) assert labels.shape[0] == self.bb.width() assert labels.shape[1] == self.bb.height() ## ## ensure that at least one pixel is label when the brush size is 1 ## ## this happens when the user just clicked without moving ## in that case the lineitem will be so tiny, that it won't be rendered ## into a single pixel by the code above if not has_moved and self.brushSize <= 1 and numpy.count_nonzero( labels) == 0: labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels) def dumpDraw(self, pos): res = self.endDrawing(pos) self.beginDrawing(pos, self.sliceRect) return res def moveTo(self, pos): #data coordinates oldX, oldY = self.pos.x(), self.pos.y() x, y = pos.x(), pos.y() line = QGraphicsLineItem(oldX, oldY, x, y) line.setPen( QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.scene.addItem(line) self._hasMoved = True #update bounding Box if not self.bb.isValid(): self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1)) #grow bounding box self.bb.setLeft( min(self.bb.left(), max(0, x - self.brushSize // 2 - 1))) self.bb.setRight( max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1))) self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1))) self.bb.setBottom( max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1))) #update/move position self.pos = pos
class ExtractRasterValue(ParentMapTool): """ Button 18. User select nodes and assign raster elevation or value """ def __init__(self, iface, settings, action, index_action): """ Class constructor """ # Call ParentMapTool constructor super(ExtractRasterValue, self).__init__(iface, settings, action, index_action) self.dragging = False # Vertex marker self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker.setColor(QColor(255, 25, 25)) self.vertexMarker.setIconSize(11) self.vertexMarker.setIconType(QgsVertexMarker.ICON_BOX) # or ICON_CROSS, ICON_X self.vertexMarker.setPenWidth(5) # Rubber band self.rubberBand = QgsRubberBand(self.canvas, True) mFillColor = QColor(100, 0, 0) self.rubberBand.setColor(mFillColor) self.rubberBand.setWidth(3) mBorderColor = QColor(254, 58, 29) self.rubberBand.setBorderColor(mBorderColor) # Select rectangle self.selectRect = QRect() # Init self.vectorLayer = None self.rasterLayer = None def reset(self): """ Clear selected features """ layer = self.vectorLayer if layer is not None: layer.removeSelection() # Graphic elements self.rubberBand.reset() def set_config_action(self, action_99): """ Get the config form action""" self.configAction = action_99 """ QgsMapTools inherited event functions """ def canvasMoveEvent(self, event): """ With left click the digitizing is finished """ if self.vectorLayer is None: return if event.buttons() == Qt.LeftButton: if not self.dragging: self.dragging = True self.selectRect.setTopLeft(event.pos()) self.selectRect.setBottomRight(event.pos()) self.set_rubber_band() else: # Hide highlight self.vertexMarker.hide() # Get the click x = event.pos().x() y = event.pos().y() eventPoint = QPoint(x, y) # Snapping (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) # @UnusedVariable # That's the snapped point if result <> []: # Check Arc or Node for snapPoint in result: if snapPoint.layer == self.vectorLayer: # Get the point point = QgsPoint(result[0].snappedVertex) # Add marker self.vertexMarker.setCenter(point) self.vertexMarker.show() break def canvasPressEvent(self, event): self.selectRect.setRect(0, 0, 0, 0) self.rubberBand.reset() def canvasReleaseEvent(self, event): """ With left click the digitizing is finished """ if event.button() == Qt.LeftButton: # Get the click x = event.pos().x() y = event.pos().y() eventPoint = QPoint(x, y) # Node layer layer = self.vectorLayer # Not dragging, just simple selection if not self.dragging: # Snap to node (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) # @UnusedVariable # That's the snapped point if result <> [] and (result[0].layer.name() == self.vectorLayer.name()): point = QgsPoint(result[0].snappedVertex) # @UnusedVariable layer.removeSelection() layer.select([result[0].snappedAtGeometry]) # Interpolate values self.raster_interpolate() # Hide highlight self.vertexMarker.hide() else: # Set valid values for rectangle's width and height if self.selectRect.width() == 1: self.selectRect.setLeft(self.selectRect.left() + 1) if self.selectRect.height() == 1: self.selectRect.setBottom(self.selectRect.bottom() + 1) self.set_rubber_band() selectGeom = self.rubberBand.asGeometry() # @UnusedVariable self.select_multiple_features(self.selectRectMapCoord) self.dragging = False # Interpolate values self.raster_interpolate() elif event.button() == Qt.RightButton: # Interpolate values self.raster_interpolate() def activate(self): # Check button self.action().setChecked(True) # Rubber band self.rubberBand.reset() # Store user snapping configuration self.snapperManager.storeSnappingOptions() # Clear snapping self.snapperManager.clearSnapping() # Get layers res = self.find_raster_layers() # if res == 0: # self.controller.show_warning("Raster configuration tool not properly configured.") # return # Change cursor self.canvas.setCursor(self.cursor) # Show help message when action is activated if self.show_help: message = ( "Right click to use current selection, select connec points by clicking or dragging (selection box)" ) self.controller.show_info(message, context_name="ui_message") # Control current layer (due to QGIS bug in snapping system) try: if self.canvas.currentLayer().type() == QgsMapLayer.VectorLayer: self.canvas.setCurrentLayer(self.layer_arc) except: self.canvas.setCurrentLayer(self.layer_arc) def deactivate(self): # Check button self.action().setChecked(False) # Rubber band self.rubberBand.reset() # Restore previous snapping self.snapperManager.recoverSnappingOptions() # Recover cursor self.canvas.setCursor(self.stdCursor) def nearestNeighbor(self, thePoint): ident = self.dataProv.identify(thePoint, QgsRaster.IdentifyFormatValue) value = None if ident is not None: # and ident.has_key(choosenBand+1): try: value = float(ident.results()[int(self.band)]) except TypeError: value = None if value == self.noDataValue: return None return value def writeInterpolation(self, f, fieldIdx): thePoint = f.geometry().asPoint() value = self.nearestNeighbor(thePoint) self.vectorLayer.changeAttributeValue(f.id(), fieldIdx, value) def raster_interpolate(self): """ Interpolate features value from raster """ # Interpolate values if self.vectorLayer is None and self.rasterLayer is None: return # Get data provider layer = self.vectorLayer self.dataProv = self.rasterLayer.dataProvider() if self.dataProv.srcNoDataValue(int(self.band)): self.noDataValue = self.dataProv.srcNoDataValue(int(self.band)) else: self.noDataValue = None self.continueProcess = True self.fieldIdx = "" self.fieldIdx = layer.fieldNameIndex(self.fieldName) if self.band == 0: self.controller.show_warning("You must choose a band for the raster layer.") return if self.fieldName == "": self.controller.show_warning("You must choose a field to write values.") return if self.fieldIdx < 0: self.controller.show_warning("Selected field does not exist in feature layer.") return k = 0 c = 0 f = QgsFeature() # Check features selected if layer.selectedFeatureCount() == 0: message = "You have to select at least one feature!" self.controller.show_warning(message, context_name="ui_message") return # Check editable if not layer.isEditable(): layer.startEditing() # Get selected id's ids = self.vectorLayer.selectedFeaturesIds() for fid in ids: k += 1 layer.getFeatures(QgsFeatureRequest(fid)).nextFeature(f) c += 1 self.writeInterpolation(f, self.fieldIdx) QCoreApplication.processEvents() self.controller.show_info( "%u values have been updated in layer %s.%s over %u points using %s raster" % (c, self.vectorLayer.name(), self.fieldName, k, self.table_raster) ) # Check editable if layer.isEditable(): layer.commitChanges() # Refresh map canvas self.rubberBand.reset() self.iface.mapCanvas().refresh() def set_rubber_band(self): # Coordinates transform transform = self.canvas.getCoordinateTransform() # Coordinates ll = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.bottom()) lr = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.bottom()) ul = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.top()) ur = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.top()) # Rubber band self.rubberBand.reset() self.rubberBand.addPoint(ll, False) self.rubberBand.addPoint(lr, False) self.rubberBand.addPoint(ur, False) self.rubberBand.addPoint(ul, False) self.rubberBand.addPoint(ll, True) self.selectRectMapCoord = QgsRectangle(ll, ur) def select_multiple_features(self, selectGeometry): # Default choice behaviour = QgsVectorLayer.SetSelection # Modifiers modifiers = QApplication.keyboardModifiers() if modifiers == Qt.ControlModifier: behaviour = QgsVectorLayer.AddToSelection elif modifiers == Qt.ShiftModifier: behaviour = QgsVectorLayer.RemoveFromSelection if self.vectorLayer is None: return # Change cursor QApplication.setOverrideCursor(Qt.WaitCursor) # Selection self.vectorLayer.selectByRect(selectGeometry, behaviour) # Old cursor QApplication.restoreOverrideCursor() def find_raster_layers(self): # Query database (form data) sql = "SELECT *" sql += " FROM " + self.schema_name + ".config_extract_raster_value" rows = self.controller.get_rows(sql) if not rows: self.controller.show_warning("Any data found in table config_extract_raster_value") self.configAction.activate(QAction.Trigger) return 0 # Layers row = rows[0] self.table_raster = row[1] self.band = row[2] self.table_vector = row[3] self.fieldName = row[4] # Check if we have any layer loaded layers = self.iface.legendInterface().layers() if len(layers) == 0: return # Init layers self.rasterLayer = None self.vectorLayer = None # Iterate over all layers to get the ones specified in 'db' config section for cur_layer in layers: if cur_layer.name() == self.table_raster: self.rasterLayer = cur_layer (uri_schema, uri_table) = self.controller.get_layer_source(cur_layer) # @UnusedVariable if uri_table is not None: if self.table_vector in uri_table: self.vectorLayer = cur_layer # Check config if self.vectorLayer is None or self.rasterLayer is None: self.configAction.activate(QAction.Trigger) # Set snapping if self.vectorLayer <> None: self.snapperManager.snapToLayer(self.vectorLayer) else: self.controller.show_warning("Check vector_layer in config form, layer does not exist or is not defined.") return 0 if self.rasterLayer == None: self.controller.show_warning("Check raster_layer in config form, layer does not exist or is not defined.") return 0 return 1
class ConnecMapTool(ParentMapTool): """ Button 20. User select connections from layer 'connec' Execute SQL function: 'gw_fct_connect_to_network' """ def __init__(self, iface, settings, action, index_action): """ Class constructor """ # Call ParentMapTool constructor super(ConnecMapTool, self).__init__(iface, settings, action, index_action) self.dragging = False # Vertex marker self.vertexMarker = QgsVertexMarker(self.canvas) self.vertexMarker.setColor(QColor(255, 25, 25)) self.vertexMarker.setIconSize(11) self.vertexMarker.setIconType(QgsVertexMarker.ICON_BOX) # or ICON_CROSS, ICON_X self.vertexMarker.setPenWidth(5) # Rubber band self.rubberBand = QgsRubberBand(self.canvas, True) mFillColor = QColor(100, 0, 0) self.rubberBand.setColor(mFillColor) self.rubberBand.setWidth(3) mBorderColor = QColor(254, 58, 29) self.rubberBand.setBorderColor(mBorderColor) # Select rectangle self.selectRect = QRect() def reset(self): """ Clear selected features """ layer = self.layer_connec if layer is not None: layer.removeSelection() # Graphic elements self.rubberBand.reset() """ QgsMapTools inherited event functions """ def canvasMoveEvent(self, event): """ With left click the digitizing is finished """ if event.buttons() == Qt.LeftButton: if not self.dragging: self.dragging = True self.selectRect.setTopLeft(event.pos()) self.selectRect.setBottomRight(event.pos()) self.set_rubber_band() else: # Hide highlight self.vertexMarker.hide() # Get the click x = event.pos().x() y = event.pos().y() eventPoint = QPoint(x, y) # Snapping (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) # @UnusedVariable # That's the snapped point if result <> []: # Check Arc or Node for snapPoint in result: if snapPoint.layer == self.layer_connec: # Get the point point = QgsPoint(result[0].snappedVertex) # Add marker self.vertexMarker.setCenter(point) self.vertexMarker.show() break def canvasPressEvent(self, event): self.selectRect.setRect(0, 0, 0, 0) self.rubberBand.reset() def canvasReleaseEvent(self, event): """ With left click the digitizing is finished """ if event.button() == Qt.LeftButton: # Get the click x = event.pos().x() y = event.pos().y() eventPoint = QPoint(x, y) # Node layer layer = self.layer_connec # Not dragging, just simple selection if not self.dragging: # Snap to node (retval, result) = self.snapper.snapToBackgroundLayers(eventPoint) # @UnusedVariable # That's the snapped point if result <> [] and (result[0].layer.name() == self.layer_connec.name()): point = QgsPoint(result[0].snappedVertex) # @UnusedVariable layer.removeSelection() layer.select([result[0].snappedAtGeometry]) # Create link self.link_connec() # Hide highlight self.vertexMarker.hide() else: # Set valid values for rectangle's width and height if self.selectRect.width() == 1: self.selectRect.setLeft(self.selectRect.left() + 1) if self.selectRect.height() == 1: self.selectRect.setBottom(self.selectRect.bottom() + 1) self.set_rubber_band() selectGeom = self.rubberBand.asGeometry() # @UnusedVariable self.select_multiple_features(self.selectRectMapCoord) self.dragging = False # Create link self.link_connec() elif event.button() == Qt.RightButton: # Create link self.link_connec() def activate(self): # Check button self.action().setChecked(True) # Rubber band self.rubberBand.reset() # Store user snapping configuration self.snapperManager.storeSnappingOptions() # Clear snapping self.snapperManager.clearSnapping() # Set snapping to arc and node self.snapperManager.snapToConnec() # Change cursor self.canvas.setCursor(self.cursor) # Show help message when action is activated if self.show_help: message = ( "Right click to use current selection, select connec points by clicking or dragging (selection box)" ) self.controller.show_info(message, context_name="ui_message") # Control current layer (due to QGIS bug in snapping system) try: if self.canvas.currentLayer().type() == QgsMapLayer.VectorLayer: self.canvas.setCurrentLayer(self.layer_connec) except: self.canvas.setCurrentLayer(self.layer_connec) def deactivate(self): # Check button self.action().setChecked(False) # Rubber band self.rubberBand.reset() # Restore previous snapping self.snapperManager.recoverSnappingOptions() # Recover cursor self.canvas.setCursor(self.stdCursor) def link_connec(self): """ Link selected connec to the pipe """ # Get selected features (from layer 'connec') aux = "{" layer = self.layer_connec if layer.selectedFeatureCount() == 0: message = "You have to select at least one feature!" self.controller.show_warning(message, context_name="ui_message") return features = layer.selectedFeatures() for feature in features: connec_id = feature.attribute("connec_id") aux += str(connec_id) + ", " connec_array = aux[:-2] + "}" # Execute function function_name = "gw_fct_connect_to_network" sql = "SELECT " + self.schema_name + "." + function_name + "('" + connec_array + "');" self.controller.execute_sql(sql) # Refresh map canvas self.rubberBand.reset() self.iface.mapCanvas().refresh() def set_rubber_band(self): # Coordinates transform transform = self.canvas.getCoordinateTransform() # Coordinates ll = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.bottom()) lr = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.bottom()) ul = transform.toMapCoordinates(self.selectRect.left(), self.selectRect.top()) ur = transform.toMapCoordinates(self.selectRect.right(), self.selectRect.top()) # Rubber band self.rubberBand.reset() self.rubberBand.addPoint(ll, False) self.rubberBand.addPoint(lr, False) self.rubberBand.addPoint(ur, False) self.rubberBand.addPoint(ul, False) self.rubberBand.addPoint(ll, True) self.selectRectMapCoord = QgsRectangle(ll, ur) def select_multiple_features(self, selectGeometry): # Default choice behaviour = QgsVectorLayer.SetSelection # Modifiers modifiers = QApplication.keyboardModifiers() if modifiers == Qt.ControlModifier: behaviour = QgsVectorLayer.AddToSelection elif modifiers == Qt.ShiftModifier: behaviour = QgsVectorLayer.RemoveFromSelection if self.layer_connec is None: return # Change cursor QApplication.setOverrideCursor(Qt.WaitCursor) # Selection self.layer_connec.selectByRect(selectGeometry, behaviour) # Old cursor QApplication.restoreOverrideCursor()