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 __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 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_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)
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
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()
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 paint(self, painter, option, index): """ Draws the widget Arguments: painter -- a QPainter option -- a QStyleOptionView index -- a QModelIndex """ # Retrieve the data model = index.model() record = model.data(index) text = record.toString() zoteroItem = zoteroCache[unicode(text)] l = zoteroItem.full_format().split("\n") if zoteroItem.fulltext == None: pixmap = self.noPdfPixmap else: pixmap = self.pdfPixmap # Choose the colors self.palette = self.qnotero.ui.listWidgetResults.palette() if option.state & QStyle.State_MouseOver: background = self.palette.Highlight foreground = self.palette.HighlightedText _note = zoteroItem.get_note() if _note != None: self.qnotero.showNoteHint() else: self.qnotero.hideNoteHint() elif option.state & QStyle.State_Selected: background = self.palette.Dark foreground = self.palette.WindowText else: background = self.palette.Base foreground = self.palette.WindowText # Draw the frame _rect = option.rect.adjusted(self._margin, self._margin, \ -2*self._margin, -self._margin) pen = painter.pen() pen.setColor(self.palette.color(background)) painter.setPen(pen) painter.setBrush(self.palette.brush(background)) painter.drawRoundedRect(_rect, self.roundness, self.roundness) font = painter.font pen = painter.pen() pen.setColor(self.palette.color(foreground)) painter.setPen(pen) # Draw icon _rect = QRect(option.rect) _rect.moveBottom(_rect.bottom() + 0.5*self.dy) _rect.moveLeft(_rect.left() + 0.5*self.dy) _rect.setHeight(self.pixmapSize) _rect.setWidth(self.pixmapSize) painter.drawPixmap(_rect, pixmap) # Draw the text _rect = option.rect.adjusted(self.pixmapSize+self.dy, 0.5*self.dy, \ -self.dy, 0) f = [self.tagFont, self.italicFont, self.regularFont, \ self.boldFont] l.reverse() while len(l) > 0: s = l.pop() if len(f) > 0: painter.setFont(f.pop()) painter.drawText(_rect, Qt.AlignLeft, s) _rect = _rect.adjusted(0, self.dy, 0, 0)
class SelectedFeatureByRectTasDraw(QgsMapTool): def __init__(self, canvas, distance): self.mCanvas = canvas QgsMapTool.__init__(self, canvas) self.mCursor = Qt.ArrowCursor self.mRubberBand = None self.mDragging = False self.mSelectRect = QRect() self.rubberBandLine = None self.distance = distance self.mSnapper = QgsMapCanvasSnapper(canvas) # QgsRubberBand* mRubberBand; # def reset(self): # self.startPoint = None # self.endPoint = None # self.isDrawing = False # SelectByRect.RubberRect.reset(QGis.Polygon) # self.layer = self.canvas.currentLayer() def canvasPressEvent(self, e): self.mSelectRect.setRect(0, 0, 0, 0) self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon) self.startPoint, self.pointID, self.layer = self.snapPoint(e.pos()) # self.reset() # self.startPoint = self.toMapCoordinates(e.pos()) # self.isDrawing = True def canvasMoveEvent(self, e): if (e.buttons() != Qt.LeftButton): return if (not self.mDragging): self.mDragging = True self.mSelectRect.setTopLeft(e.pos()) self.mSelectRect.setBottomRight(e.pos()) QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect, self.mRubberBand) # if not self.isDrawing: # return # SelectByRect.RubberRect.reset(QGis.Polygon) # self.endPoint = self.toMapCoordinates(e.pos()) # self.rect = QgsRectangle(self.startPoint, self.endPoint) # SelectByRect.RubberRect.addGeometry(QgsGeometry.fromRect(self.rect), None) # SelectByRect.RubberRect.show() def canvasReleaseEvent(self, e): self.endPoint, self.pointID, self.layer = self.snapPoint(e.pos()) if len(define._newGeometryList) > 0: geom = define._newGeometryList[0] if geom.intersects(self.mRubberBand.asGeometry()): pointArray = geom.asPolyline() # pointArray1 = QgisHelper.offsetCurve(pointArray, 1200) if self.rubberBandLine != None: self.rubberBandLine.reset(QGis.Line) del self.rubberBandLine self.rubberBandLine = None self.rubberBandLine = QgsRubberBand(self.mCanvas, QGis.Line) self.rubberBandLine.setColor(Qt.blue) bearing = 0.0 if self.startPoint.y() >= self.endPoint.y() and ( math.fabs(self.startPoint.x() - self.endPoint.x()) < math.fabs(self.startPoint.y() - self.endPoint.y())): bearing = Unit.ConvertDegToRad(180) elif self.startPoint.x() >= self.endPoint.x() and ( math.fabs(self.startPoint.x() - self.endPoint.x()) > math.fabs(self.startPoint.y() - self.endPoint.y())): bearing = Unit.ConvertDegToRad(270) elif self.startPoint.x() < self.endPoint.x() and ( math.fabs(self.startPoint.x() - self.endPoint.x()) > math.fabs(self.startPoint.y() - self.endPoint.y())): bearing = Unit.ConvertDegToRad(90) else: bearing = 0.0 for point in pointArray: pt = MathHelper.distanceBearingPoint( Point3D(point.x(), point.y()), bearing, self.distance ) # MathHelper.getBearing(self.startPoint, self.endPoint), self.distance) self.rubberBandLine.addPoint(pt) gg = self.rubberBandLine.asGeometry() g = gg.asPolyline() # self.rubberBandLine.show() if (self.mRubberBand != None): self.mRubberBand.reset(QGis.Polygon) del self.mRubberBand self.mRubberBand = None self.mDragging = False self.emit( SIGNAL("resultSelectedFeatureByRectTasDraw"), gg, self.distance, bearing ) # MathHelper.getBearing(self.startPoint, self.endPoint)) return vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer(self.mCanvas) if (vlayer == None): if (self.mRubberBand != None): self.mRubberBand.reset(QGis.Polygon) del self.mRubberBand self.mRubberBand = None self.mDragging = False return if (not self.mDragging): QgsMapToolSelectUtils.expandSelectRectangle( self.mSelectRect, vlayer, e.pos()) else: if (self.mSelectRect.width() == 1): self.mSelectRect.setLeft(self.mSelectRect.left() + 1) if (self.mSelectRect.height() == 1): self.mSelectRect.setBottom(self.mSelectRect.bottom() + 1) if (self.mRubberBand != None): QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect, self.mRubberBand) selectGeom = self.mRubberBand.asGeometry() # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, selectGeom, e ) selectedFeatures = QgsMapToolSelectUtils.setSelectFeaturesOrRubberband_Tas_1( self.mCanvas, selectGeom, e) if len(selectedFeatures) > 0: geom = selectedFeatures[0].geometry() if geom.intersects(self.mRubberBand.asGeometry()): pointArray = geom.asPolyline() # pointArray1 = QgisHelper.offsetCurve(pointArray, 1200) if self.rubberBandLine != None: self.rubberBandLine.reset(QGis.Line) del self.rubberBandLine self.rubberBandLine = None self.rubberBandLine = QgsRubberBand( self.mCanvas, QGis.Line) self.rubberBandLine.setColor(Qt.blue) bearing = 0.0 gg = None if self.startPoint.y() >= self.endPoint.y() and ( math.fabs(self.startPoint.x() - self.endPoint.x()) < math.fabs(self.startPoint.y() - self.endPoint.y())): bearing = Unit.ConvertDegToRad(180) gg = self.newCreateLine(geom, self.distance, 180) elif self.startPoint.x() >= self.endPoint.x() and ( math.fabs(self.startPoint.x() - self.endPoint.x()) > math.fabs(self.startPoint.y() - self.endPoint.y())): bearing = Unit.ConvertDegToRad(270) gg = self.newCreateLine(geom, self.distance, 270) elif self.startPoint.x() < self.endPoint.x() and ( math.fabs(self.startPoint.x() - self.endPoint.x()) > math.fabs(self.startPoint.y() - self.endPoint.y())): bearing = Unit.ConvertDegToRad(90) gg = self.newCreateLine(geom, self.distance, 90) else: bearing = 0.0 gg = self.newCreateLine(geom, self.distance, 0) for point in pointArray: pt = MathHelper.distanceBearingPoint( Point3D(point.x(), point.y()), bearing, self.distance ) #MathHelper.getBearing(self.startPoint, self.endPoint), self.distance) self.rubberBandLine.addPoint(pt) # gg= self.newCreateLine(geom, -self.distance, 0) self.emit( SIGNAL("resultSelectedFeatureByRectTasDraw"), gg, self.distance, bearing ) #MathHelper.getBearing(self.startPoint, self.endPoint)) self.rubberBandLine.reset(QGis.Line) del selectGeom self.mRubberBand.reset(QGis.Polygon) del self.mRubberBand self.mRubberBand = None self.mDragging = False # self.canvasMoveEvent(e) # if self.layer != None: # self.layer.removeSelection() # if self.layer.crs().mapUnits() != self.canvas.mapUnits(): # if self.layer.crs().mapUnits == QGis.Meters: # lstPoint = QgisHelper.Degree2MeterList([self.startPoint, self.endPoint]) # else: # lstPoint = QgisHelper.Meter2DegreeList([self.startPoint, self.endPoint]) # rect = QgsRectangle(lstPoint[0], lstPoint[1]) # self.layer.select(rect, True) # else: # self.layer.select(self.rect, False) # else: # QMessageBox.warning(None, "Information", "Please select layer!") # self.reset() def snapPoint(self, p, bNone=False): if define._snapping == False: return ( define._canvas.getCoordinateTransform().toMapCoordinates(p), None, None) snappingResults = self.mSnapper.snapToBackgroundLayers(p) if (snappingResults[0] != 0 or len(snappingResults[1]) < 1): if bNone: return (None, None, None) else: return (define._canvas.getCoordinateTransform(). toMapCoordinates(p), None, None) else: return (snappingResults[1][0].snappedVertex, snappingResults[1][0].snappedAtGeometry, snappingResults[1][0].layer) def newCreateLine(self, geom, dist, angle): if define._units != QGis.Meters: dist = define._qgsDistanceArea.convertMeasurement( dist, QGis.Meters, QGis.Degrees, False)[0] g = geom.offsetCurve(dist, 0, 2, 2) pointArrayOld = geom.asPolyline() pointArrayNew = g.asPolyline() if MathHelper.calcDistance( pointArrayNew[0], pointArrayOld[0]) > MathHelper.calcDistance( pointArrayNew[0], pointArrayOld[len(pointArrayOld) - 1]): array = [] i = len(pointArrayNew) - 1 while i >= 0: array.append(pointArrayNew[i]) i -= 1 pointArrayNew = array if angle == 0: if pointArrayNew[0].y() < pointArrayOld[0].y(): g = geom.offsetCurve(-dist, 0, 2, 2) pointArrayNew = g.asPolyline() elif angle == 90: if pointArrayNew[0].x() < pointArrayOld[0].x(): g = geom.offsetCurve(-dist, 0, 2, 2) pointArrayNew = g.asPolyline() elif angle == 180: if pointArrayNew[0].y() > pointArrayOld[0].y(): g = geom.offsetCurve(-dist, 0, 2, 2) pointArrayNew = g.asPolyline() elif angle == 270: if pointArrayNew[0].x() > pointArrayOld[0].x(): g = geom.offsetCurve(-dist, 0, 2, 2) pointArrayNew = g.asPolyline() if MathHelper.calcDistance( pointArrayNew[0], pointArrayOld[0]) > MathHelper.calcDistance( pointArrayNew[0], pointArrayOld[len(pointArrayOld) - 1]): array = [] i = len(pointArrayNew) - 1 while i >= 0: array.append(pointArrayNew[i]) i -= 1 pointArrayNew = array i = 0 while i < len(pointArrayNew) - 1: if i == 0: i += 1 continue line = None if define._units == QGis.Meters: if angle == 0: line = QgsGeometry.fromPolyline([ pointArrayOld[0], QgsPoint(pointArrayOld[0].x(), 100000000) ]) elif angle == 90: line = QgsGeometry.fromPolyline([ pointArrayOld[0], QgsPoint(100000000, pointArrayOld[0].y()) ]) elif angle == 180: line = QgsGeometry.fromPolyline( [pointArrayOld[0], QgsPoint(pointArrayOld[0].x(), 0)]) elif angle == 270: line = QgsGeometry.fromPolyline( [pointArrayOld[0], QgsPoint(0, pointArrayOld[0].y())]) else: if angle == 0: line = QgsGeometry.fromPolyline([ pointArrayOld[0], QgsPoint(pointArrayOld[0].x(), pointArrayOld[0].y() + 0.1) ]) elif angle == 90: line = QgsGeometry.fromPolyline([ pointArrayOld[0], QgsPoint(pointArrayOld[0].x() + 0.1, pointArrayOld[0].y()) ]) elif angle == 180: line = QgsGeometry.fromPolyline([ pointArrayOld[0], QgsPoint(pointArrayOld[0].x(), pointArrayOld[0].y() - 0.1) ]) elif angle == 270: line = QgsGeometry.fromPolyline([ pointArrayOld[0], QgsPoint(pointArrayOld[0].x() - 0.1, pointArrayOld[0].y()) ]) lineNew = QgsGeometry.fromPolyline([ MathHelper.distanceBearingPoint( Point3D(pointArrayNew[i].x(), pointArrayNew[i].y()), MathHelper.getBearing(pointArrayNew[i], pointArrayNew[i - 1]), 100000), pointArrayNew[i] ]) if line.intersects(lineNew): pointGeom = line.intersection(lineNew) intersectPoint = pointGeom.asPoint() pointArrayNew.pop(i - 1) pointArrayNew.insert(i - 1, intersectPoint) break else: pointArrayNew.pop(i - 1) continue i += 1 i = len(pointArrayNew) - 1 while i > 1: line = None if define._units == QGis.Meters: if angle == 0: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint(pointArrayOld[len(pointArrayOld) - 1].x(), 100000000) ]) elif angle == 90: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint(100000000, pointArrayOld[len(pointArrayOld) - 1].y()) ]) elif angle == 180: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint(pointArrayOld[len(pointArrayOld) - 1].x(), 0) ]) elif angle == 270: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint(0, pointArrayOld[len(pointArrayOld) - 1].y()) ]) else: if angle == 0: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint( pointArrayOld[len(pointArrayOld) - 1].x(), pointArrayOld[len(pointArrayOld) - 1].y() + 0.1) ]) elif angle == 90: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint( pointArrayOld[len(pointArrayOld) - 1].x() + 0.1, pointArrayOld[len(pointArrayOld) - 1].y()) ]) elif angle == 180: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint( pointArrayOld[len(pointArrayOld) - 1].x(), pointArrayOld[len(pointArrayOld) - 1].y() - 0.1) ]) elif angle == 270: line = QgsGeometry.fromPolyline([ pointArrayOld[len(pointArrayOld) - 1], QgsPoint( pointArrayOld[len(pointArrayOld) - 1].x() - 0.1, pointArrayOld[len(pointArrayOld) - 1].y()) ]) # line = QgsGeometry.fromPolyline([pointArrayOld[len(pointArrayOld) - 1], QgsPoint(pointArrayOld[len(pointArrayOld) - 1].x(), 100000000)]) lineNew = QgsGeometry.fromPolyline([ MathHelper.distanceBearingPoint( Point3D(pointArrayNew[i].x(), pointArrayNew[i].y()), MathHelper.getBearing(pointArrayNew[i - 1], pointArrayNew[i]), 100000), pointArrayNew[i - 1] ]) if line.intersects(lineNew): pointGeom = line.intersection(lineNew) intersectPoint = pointGeom.asPoint() pointArrayNew.pop(i) pointArrayNew.insert(i, intersectPoint) break else: pointArrayNew.pop(i) i -= 1 continue i -= 1 return QgsGeometry.fromPolyline(pointArrayNew)
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 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 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 ObstacleAreaJigSelectArea(QgsMapTool): def __init__(self, canvas, areaType): self.mCanvas = canvas self.areaType = areaType QgsMapTool.__init__(self, canvas) self.mCursor = Qt.ArrowCursor self.mRubberBand = None self.mDragging = False self.mSelectRect = QRect() self.mRubberBandResult = None self.mSnapper = QgsMapCanvasSnapper(canvas) self.lineCount = 0 self.resultGeomList = [] self.geomList = [] self.area = None self.isFinished = False # QgsRubberBand* mRubberBand; # def reset(self): # self.startPoint = None # self.endPoint = None # self.isDrawing = False # SelectByRect.RubberRect.reset(QGis.Polygon) # self.layer = self.canvas.currentLayer() def canvasPressEvent(self, e): QgisHelper.ClearRubberBandInCanvas(define._canvas) self.mSelectRect.setRect( 0, 0, 0, 0 ) self.mRubberBand = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.startPoint, self.pointID, self.layer= self.snapPoint(e.pos()) def canvasMoveEvent(self, e): if self.areaType == ProtectionAreaType.Secondary: if self.lineCount == 0: define._messageLabel.setText("Select a line or arc representing the INNER edge of the secondary area.") elif self.lineCount == 1: define._messageLabel.setText("Select a line representing the OUTER edge of the secondary area.") elif self.areaType == ProtectionAreaType.Primary: define._messageLabel.setText("") elif self.areaType == ProtectionAreaType.PrimaryAndSecondary: if self.lineCount == 0: define._messageLabel.setText("Select a line or arc representing the INNER edge of the FIRST secondary area.") elif self.lineCount == 1: define._messageLabel.setText("Select a line representing the OUTER edge of the FIRST secondary area.") elif self.lineCount == 2: define._messageLabel.setText("Select a line or arc representing the INNER edge of the SECOND secondary area.") elif self.lineCount == 3: define._messageLabel.setText("Select a line representing the OUTER edge of the SECOND secondary area.") else: define._messageLabel.setText("") if ( e.buttons() != Qt.LeftButton ): return if ( not self.mDragging ): self.mDragging = True self.mSelectRect.setTopLeft( e.pos() ) self.mSelectRect.setBottomRight( e.pos() ) QgsMapToolSelectUtils.setRubberBand( self.mCanvas, self.mSelectRect,self.mRubberBand ) def canvasReleaseEvent(self, e): self.endPoint, self.pointID, self.layer= self.snapPoint(e.pos()) vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer( self.mCanvas ) if ( vlayer == None ): if ( self.mRubberBand != None): self.mRubberBand.reset( QGis.Polygon ) del self.mRubberBand self.mRubberBand = None self.mDragging = False return if (not self.mDragging ): QgsMapToolSelectUtils.expandSelectRectangle(self. mSelectRect, vlayer, e.pos() ) else: if ( self.mSelectRect.width() == 1 ): self.mSelectRect.setLeft( self.mSelectRect.left() + 1 ) if ( self.mSelectRect.height() == 1 ): self.mSelectRect.setBottom( self.mSelectRect.bottom() + 1 ) if ( self.mRubberBand != None ): QgsMapToolSelectUtils.setRubberBand( self.mCanvas, self.mSelectRect, self.mRubberBand ) selectGeom = self.mRubberBand.asGeometry() selectedFeatures = QgsMapToolSelectUtils.setSelectFeaturesOrRubberband_Tas_1( self.mCanvas, selectGeom, e ) if len(selectedFeatures) > 0: self.lineCount += 1 geom = selectedFeatures[0].geometry() resultArray = QgisHelper.findArcOrLineInLineGeometry(geom, selectGeom) # if resultArray != None: # bulge = MathHelper.smethod_60(resultArray[0], resultArray[int(len(resultArray)/2)], resultArray[len(resultArray)-1]) # bulge1 = MathHelper.smethod_60(resultArray[len(resultArray)-1], resultArray[int(len(resultArray)/2)], resultArray[0]) # n = 0 pointArray0 = geom.asPolyline() self.resultGeomList.append(resultArray) self.geomList.append(pointArray0) if self.lineCount == 2 and self.areaType != ProtectionAreaType.PrimaryAndSecondary and self.areaType != ProtectionAreaType.Complex: self.area = self.makeArea(self.resultGeomList, self.areaType) pointArray = self.getPointArray(self.resultGeomList).method_14_closed() self.mRubberBandResult = None self.mRubberBandResult = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBandResult.setFillColor(QColor(255, 255, 255, 100)) self.mRubberBandResult.setBorderColor(QColor(0, 0, 0)) for point in pointArray: self.mRubberBandResult.addPoint(point) self.mRubberBandResult.show() self.emit(SIGNAL("outputResult"), self.area, self.mRubberBandResult) self.lineCount = 0 self.resultGeomList = [] self.isFinished = True # self.rubberBandLine.reset(QGis.Line) elif self.lineCount == 4 and self.areaType == ProtectionAreaType.PrimaryAndSecondary: self.area = self.makeArea(self.resultGeomList, self.areaType) pointArray = self.getPointArray([self.resultGeomList[1], self.resultGeomList[3]]).method_14_closed() self.mRubberBandResult = None self.mRubberBandResult = QgsRubberBand( self.mCanvas, QGis.Polygon ) self.mRubberBandResult.setFillColor(QColor(255, 255, 255, 100)) self.mRubberBandResult.setBorderColor(QColor(0, 0, 0)) for point in pointArray: self.mRubberBandResult.addPoint(point) self.mRubberBandResult.show() self.emit(SIGNAL("outputResult"), self.area, self.mRubberBandResult) self.lineCount = 0 self.resultGeomList = [] # else: # return del selectGeom self.mRubberBand.reset( QGis.Polygon ) del self.mRubberBand self.mRubberBand = None self.mDragging = False def getPointArray(self, geomList): pointArrayInner = geomList[0] pointArray1Outer = geomList[1] innerStartPoint = pointArrayInner[0] innerEndPoint = pointArrayInner[1] innerBulge = pointArrayInner[2] outerStartPoint = pointArray1Outer[0] outerEndPoint = pointArray1Outer[1] outerBulge = pointArray1Outer[2] line0 = QgsGeometry.fromPolyline([innerStartPoint, outerStartPoint]) line1 = QgsGeometry.fromPolyline([innerEndPoint, outerEndPoint]) # for i in range(1, len(pointArray0)): if line0.intersects(line1): tempPoint = outerStartPoint outerStartPoint = outerEndPoint outerEndPoint = tempPoint outerBulge = -outerBulge polylineArea = PolylineArea() polylineArea.Add(PolylineAreaPoint(innerStartPoint, innerBulge)) polylineArea.Add(PolylineAreaPoint(innerEndPoint)) polylineArea.Add(PolylineAreaPoint(outerEndPoint, -outerBulge)) polylineArea.Add(PolylineAreaPoint(outerStartPoint)) return polylineArea def makeArea(self, geomList, areaType): if areaType == ProtectionAreaType.Primary or areaType == ProtectionAreaType.Secondary: return self.makePrimaryAreaOrSecondaryArea(geomList, areaType) elif areaType == ProtectionAreaType.PrimaryAndSecondary: pointArray0 = geomList[0] pointArray1 = geomList[1] pointArray2 = geomList[2] pointArray3 = geomList[3] primaryArea = self.makePrimaryAreaOrSecondaryArea([pointArray0, pointArray2], ProtectionAreaType.Primary) secondaryArea1 = self.makePrimaryAreaOrSecondaryArea([pointArray0, pointArray1], ProtectionAreaType.Secondary) secondaryArea2 = self.makePrimaryAreaOrSecondaryArea([pointArray2, pointArray3], ProtectionAreaType.Secondary) return PrimarySecondaryObstacleArea(primaryArea, secondaryArea1, secondaryArea2) # if len(geomList[0]) == 2 and len(geomList[1]) == 2 and len(geomList[2]) == 2 and len(geomList[3]) == 2: # for i in range(1, len(geomList)): # pointArray0 = geomList[0] # pointArray1 = geomList[i] # line0 = QgsGeometry.fromPolyline([pointArray0[0], pointArray1[0]]) # line1 = QgsGeometry.fromPolyline([pointArray0[len(pointArray0) - 1], pointArray1[len(pointArray1) - 1]]) # if line0.intersects(line1): # pointArray1.reverse() # pointArray0 = geomList[0] # pointArray1 = geomList[1] # pointArray2 = geomList[2] # pointArray3 = geomList[3] # area = PrimarySecondaryObstacleArea() # area.set_areas(pointArray0, pointArray1, pointArray2, pointArray3) # return area # return None return None def makePrimaryAreaOrSecondaryArea(self, geomList, areaType): pointArrayInner = geomList[0] pointArray1Outer = geomList[1] innerStartPoint = pointArrayInner[0] innerEndPoint = pointArrayInner[1] innerBulge = pointArrayInner[2] outerStartPoint = pointArray1Outer[0] outerEndPoint = pointArray1Outer[1] outerBulge = pointArray1Outer[2] line0 = QgsGeometry.fromPolyline([innerStartPoint, outerStartPoint]) line1 = QgsGeometry.fromPolyline([innerEndPoint, outerEndPoint]) # for i in range(1, len(pointArray0)): if line0.intersects(line1): tempPoint = Point3D(outerStartPoint.get_X(), outerStartPoint.get_Y()) outerStartPoint = Point3D(outerEndPoint.get_X(), outerEndPoint.get_Y()) outerEndPoint = Point3D(tempPoint.get_X(), tempPoint.get_Y()) outerBulge = -outerBulge if areaType == ProtectionAreaType.Primary: polylineArea = PolylineArea() polylineArea.Add(PolylineAreaPoint(innerStartPoint, innerBulge)) polylineArea.Add(PolylineAreaPoint(innerEndPoint)) polylineArea.Add(PolylineAreaPoint(outerEndPoint, -outerBulge)) polylineArea.Add(PolylineAreaPoint(outerStartPoint)) return PrimaryObstacleArea(polylineArea) elif areaType == ProtectionAreaType.Secondary: if innerBulge == 0 and outerBulge == 0: return SecondaryObstacleArea(innerStartPoint, innerEndPoint, outerStartPoint, outerEndPoint, MathHelper.getBearing(innerStartPoint, innerEndPoint)) elif innerBulge != 0 and outerBulge != 0: if round(innerBulge, 1) != round(outerBulge, 1): return None innerCenterPoint = MathHelper.smethod_71(innerStartPoint, innerEndPoint, innerBulge) outerCenterPoint = MathHelper.smethod_71(outerStartPoint, outerEndPoint, outerBulge) innerRadius = MathHelper.calcDistance(innerCenterPoint, innerStartPoint); outerRadius = MathHelper.calcDistance(outerCenterPoint, outerStartPoint); bearing = (MathHelper.getBearing(innerCenterPoint, innerStartPoint) + MathHelper.getBearing(innerCenterPoint, innerEndPoint)) / 2 innerMiddlePoint = MathHelper.distanceBearingPoint(innerCenterPoint, bearing, innerRadius) if round(MathHelper.smethod_60(innerStartPoint, innerMiddlePoint, innerEndPoint), 4) != round(outerBulge, 4): bearing += 3.14159265358979 innerMiddlePoint = MathHelper.distanceBearingPoint(innerCenterPoint, bearing, innerRadius) bearing = (MathHelper.getBearing(outerCenterPoint, outerStartPoint) + MathHelper.getBearing(outerCenterPoint, outerEndPoint)) / 2 outerMiddlePoint = MathHelper.distanceBearingPoint(outerCenterPoint, bearing, outerRadius) if round(MathHelper.smethod_60(outerStartPoint, outerMiddlePoint, outerEndPoint), 4) != round(outerBulge, 4): bearing += 3.14159265358979 outerMiddlePoint = MathHelper.distanceBearingPoint(outerCenterPoint, bearing, outerRadius) return SecondaryObstacleArea(innerStartPoint, innerMiddlePoint, innerEndPoint, outerStartPoint, None, outerMiddlePoint, outerEndPoint, innerBulge, innerBulge) return None def snapPoint(self, p, bNone = False): if define._snapping == False: return (define._canvas.getCoordinateTransform().toMapCoordinates( p ), None, None) snappingResults = self.mSnapper.snapToBackgroundLayers( p ) if ( snappingResults[0] != 0 or len(snappingResults[1]) < 1 ): if bNone: return (None, None, None) else: return (define._canvas.getCoordinateTransform().toMapCoordinates( p ), None, None) else: return (snappingResults[1][0].snappedVertex, snappingResults[1][0].snappedAtGeometry, snappingResults[1][0].layer)
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
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()
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)
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 SelectByRect(QgsMapTool): def __init__(self, canvas): self.mCanvas = canvas QgsMapTool.__init__(self, canvas) self.mCursor = Qt.ArrowCursor self.mRubberBand = None self.mDragging = False self.mSelectRect = QRect() # QgsRubberBand* mRubberBand; # def reset(self): # self.startPoint = None # self.endPoint = None # self.isDrawing = False # SelectByRect.RubberRect.reset(QGis.Polygon) # self.layer = self.canvas.currentLayer() def canvasPressEvent(self, e): self.mSelectRect.setRect(0, 0, 0, 0) self.mRubberBand = QgsRubberBand(self.mCanvas, QGis.Polygon) # self.reset() # self.startPoint = self.toMapCoordinates(e.pos()) # self.isDrawing = True def canvasMoveEvent(self, e): if (e.buttons() != Qt.LeftButton): return if (not self.mDragging): self.mDragging = True self.mSelectRect.setTopLeft(e.pos()) self.mSelectRect.setBottomRight(e.pos()) QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect, self.mRubberBand) # if not self.isDrawing: # return # SelectByRect.RubberRect.reset(QGis.Polygon) # self.endPoint = self.toMapCoordinates(e.pos()) # self.rect = QgsRectangle(self.startPoint, self.endPoint) # SelectByRect.RubberRect.addGeometry(QgsGeometry.fromRect(self.rect), None) # SelectByRect.RubberRect.show() def canvasReleaseEvent(self, e): selectedFeatures = None vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer(self.mCanvas) if (vlayer == None): if (self.mRubberBand != None): self.mRubberBand.reset(QGis.Polygon) del self.mRubberBand self.mRubberBand = None self.mDragging = False return if (not self.mDragging): QgsMapToolSelectUtils.expandSelectRectangle( self.mSelectRect, vlayer, e.pos()) else: if (self.mSelectRect.width() == 1): self.mSelectRect.setLeft(self.mSelectRect.left() + 1) if (self.mSelectRect.height() == 1): self.mSelectRect.setBottom(self.mSelectRect.bottom() + 1) if (self.mRubberBand != None): QgsMapToolSelectUtils.setRubberBand(self.mCanvas, self.mSelectRect, self.mRubberBand) selectGeom = self.mRubberBand.asGeometry() # QgsMapToolSelectUtils.setSelectFeatures( self.mCanvas, selectGeom, e ) selectedFeatures = QgsMapToolSelectUtils.setSelectFeatures1( self.mCanvas, selectGeom, e) del selectGeom self.mRubberBand.reset(QGis.Polygon) del self.mRubberBand self.mRubberBand = None self.mDragging = False self.emit(SIGNAL("getSelectedFeatures"), selectedFeatures)
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 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 paint(self, painter, option, index): """ Draws the widget Arguments: painter -- a QPainter option -- a QStyleOptionView index -- a QModelIndex """ # Retrieve the data model = index.model() record = model.data(index) text = record.toString() zoteroItem = zoteroCache[unicode(text)] l = zoteroItem.full_format().split(u"\n") if zoteroItem.fulltext == None: pixmap = self.noPdfPixmap else: pixmap = self.pdfPixmap # Choose the colors self.palette = self.qnotero.ui.listWidgetResults.palette() if option.state & QStyle.State_MouseOver: background = self.palette.Highlight foreground = self.palette.HighlightedText _note = zoteroItem.get_note() if _note != None: self.qnotero.showNoteHint() else: self.qnotero.hideNoteHint() elif option.state & QStyle.State_Selected: background = self.palette.Dark foreground = self.palette.WindowText else: background = self.palette.Base foreground = self.palette.WindowText # Draw the frame _rect = option.rect.adjusted(self._margin, self._margin, \ -2*self._margin, -self._margin) pen = painter.pen() pen.setColor(self.palette.color(background)) painter.setPen(pen) painter.setBrush(self.palette.brush(background)) painter.drawRoundedRect(_rect, self.roundness, self.roundness) font = painter.font pen = painter.pen() pen.setColor(self.palette.color(foreground)) painter.setPen(pen) # Draw icon _rect = QRect(option.rect) _rect.moveBottom(_rect.bottom() + 0.5 * self.dy) _rect.moveLeft(_rect.left() + 0.5 * self.dy) _rect.setHeight(self.pixmapSize) _rect.setWidth(self.pixmapSize) painter.drawPixmap(_rect, pixmap) # Draw the text _rect = option.rect.adjusted(self.pixmapSize+self.dy, 0.5*self.dy, \ -self.dy, 0) f = [self.tagFont, self.italicFont, self.regularFont, \ self.boldFont] l.reverse() while len(l) > 0: s = l.pop() if len(f) > 0: painter.setFont(f.pop()) painter.drawText(_rect, Qt.AlignLeft, s) _rect = _rect.adjusted(0, self.dy, 0, 0)
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()