def popup(self, pos=None, searchText=""): """ Popup the menu at `pos` (in screen coordinates). 'Search' text field is initialized with `searchText` if provided. """ if pos is None: pos = QPoint() self.__clearCurrentItems() self.__search.setText(searchText) patt = QRegExp("(^|\W)"+searchText) patt.setCaseSensitivity(False) self.__suggestPage.setFilterRegExp(patt) self.ensurePolished() if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled(): size = self.size() else: size = self.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) self.setGeometry(geom) self.show() if searchText: self.setFocusProxy(self.__search) else: self.setFocusProxy(None)
def popup(self, pos=None, searchText=""): """ Popup the menu at `pos` (in screen coordinates). 'Search' text field is initialized with `searchText` if provided. """ if pos is None: pos = QPoint() self.__clearCurrentItems() self.__search.setText(searchText) patt = QRegExp("(^|\W)" + searchText) patt.setCaseSensitivity(False) self.__suggestPage.setFilterRegExp(patt) self.ensurePolished() if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled(): size = self.size() else: size = self.sizeHint() desktop = QApplication.desktop() screen_geom = desktop.availableGeometry(pos) # Adjust the size to fit inside the screen. if size.height() > screen_geom.height(): size.setHeight(screen_geom.height()) if size.width() > screen_geom.width(): size.setWidth(screen_geom.width()) geom = QRect(pos, size) if geom.top() < screen_geom.top(): geom.setTop(screen_geom.top()) if geom.left() < screen_geom.left(): geom.setLeft(screen_geom.left()) bottom_margin = screen_geom.bottom() - geom.bottom() right_margin = screen_geom.right() - geom.right() if bottom_margin < 0: # Falls over the bottom of the screen, move it up. geom.translate(0, bottom_margin) # TODO: right to left locale if right_margin < 0: # Falls over the right screen edge, move the menu to the # other side of pos. geom.translate(-size.width(), 0) self.setGeometry(geom) self.show() if searchText: self.setFocusProxy(self.__search) else: self.setFocusProxy(None)
def _paint_icon(self, iconic, painter, rect, mode, state, options): """Paint a single icon.""" painter.save() color = options['color'] char = options['char'] color_options = { QIcon.On: { QIcon.Normal: (options['color_on'], options['on']), QIcon.Disabled: (options['color_on_disabled'], options['on_disabled']), QIcon.Active: (options['color_on_active'], options['on_active']), QIcon.Selected: (options['color_on_selected'], options['on_selected']) }, QIcon.Off: { QIcon.Normal: (options['color_off'], options['off']), QIcon.Disabled: (options['color_off_disabled'], options['off_disabled']), QIcon.Active: (options['color_off_active'], options['off_active']), QIcon.Selected: (options['color_off_selected'], options['off_selected']) } } color, char = color_options[state][mode] painter.setPen(QColor(color)) # A 16 pixel-high icon yields a font size of 14, which is pixel perfect # for font-awesome. 16 * 0.875 = 14 # The reason why the glyph size is smaller than the icon size is to # account for font bearing. draw_size = 0.875 * qRound(rect.height() * options['scale_factor']) prefix = options['prefix'] # Animation setup hook animation = options.get('animation') if animation is not None: animation.setup(self, painter, rect) painter.setFont(iconic.font(prefix, draw_size)) if 'offset' in options: rect = QRect(rect) rect.translate(options['offset'][0] * rect.width(), options['offset'][1] * rect.height()) painter.setOpacity(options.get('opacity', 1.0)) painter.drawText(rect, Qt.AlignCenter | Qt.AlignVCenter, char) painter.restore()
def linkRect(self, linkarea): """Returns a QRect encompassing the linkArea (of a link) in coordinates of our rect().""" left, top, right, bottom = linkarea.normalized().getCoords() # rotate if self._rotation: if self._rotation == popplerqt4.Poppler.Page.Rotate90: left, top, right, bottom = 1-bottom, left, 1-top, right elif self._rotation == popplerqt4.Poppler.Page.Rotate180: left, top, right, bottom = 1-right, 1-bottom, 1-left, 1-top else: # 270 left, top, right, bottom = top, 1-right, bottom, 1-left rect = QRect() rect.setCoords(left * self.width(), top * self.height(), right * self.width(), bottom * self.height()) rect.translate(self.pos()) return rect
def linkRect(self, linkarea): """Returns a QRect encompassing the linkArea (of a link) in coordinates of our rect().""" left, top, right, bottom = linkarea.normalized().getCoords() # rotate if self._rotation: if self._rotation == popplerqt4.Poppler.Page.Rotate90: left, top, right, bottom = 1 - bottom, left, 1 - top, right elif self._rotation == popplerqt4.Poppler.Page.Rotate180: left, top, right, bottom = 1 - right, 1 - bottom, 1 - left, 1 - top else: # 270 left, top, right, bottom = top, 1 - right, bottom, 1 - left rect = QRect() rect.setCoords(left * self.width(), top * self.height(), right * self.width(), bottom * self.height()) rect.translate(self.pos()) return rect
def notify(self, html): note = Notification(html) self.connect(note, SIGNAL("done"), self.noteDestroyed) desktop = QApplication.desktop().availableGeometry(note) me = QRect(QPoint(0, 0), self.size) me.moveBottomRight(desktop.bottomRight() - self.margin) while self.notePosTaken(me): me.translate(0, 0 - (self.size.height() + (self.margin.y() * 2))) if not desktop.contains(me): me.moveBottom(desktop.bottom() - self.margin.y()) me.translate(0 - (self.size.width() + self.margin.x() * 2), 0) note.setGeometry(me) self.notifications.add(note) note.display()
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
class ImageAreaSelector (QtGui.QWidget): '''This widget provides means to visually crop a portion of an image by selecting it''' # pylint: disable=W0612 NAME = 'ImageAreaSelector' DESCRIPTION = 'A widget used to select part of an image' AUTHOR = 'Gabriele "Whisky" Visconti' WEBSITE = '' # pylint: enable=W0612 selection_changed = QtCore.pyqtSignal() def __init__(self, pixmap, parent=None): '''Constructor''' QtGui.QWidget.__init__(self, parent) self._pixmap = pixmap self._selection_rect = QRect() self._image_origin = QPoint() self._resize_start = None self._drag_start = None self._handle_size = QSize(-10, -10) self._painter = QtGui.QPainter() self._hl_color1 = QtGui.QPalette().color(QtGui.QPalette.Highlight) self._hl_color2 = QtGui.QPalette().color(QtGui.QPalette.Highlight) self._hl_color2.setAlpha(150) self._zoom = 1.0 self.adjust_minum_size() self.setBackgroundRole(QtGui.QPalette.Dark) self.setMouseTracking(True) self.setCursor(Qt.CrossCursor) # -------------------- [BEGIN] QT_OVERRIDE def mousePressEvent (self, event): '''Overrides QWidget's mousePressEvent. Handles starting a new selection, starting a drag operation''' # pylint: disable=C0103 mouse_pos = event.pos() / self._zoom sel_rect = self._selection_rect if not event.button() == Qt.LeftButton: return if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self._resize_start = mouse_pos else: self._drag_start = mouse_pos else: self._resize_start = mouse_pos sel_rect.setTopLeft (mouse_pos) self._selection_rect.setSize(QSize(0, 0)) def mouseMoveEvent (self, event): '''Overrides QWidget's mouseMoveEvent. Handles resizing and dragging operations on selection''' # pylint: disable=C0103 sel_rect = self._selection_rect if self._resize_start: resize_end = event.pos() / self._zoom sel_rect.setBottomRight(sel_rect.bottomRight() + (resize_end - self._resize_start)) self._resize_start = resize_end self.make_selection_square() self.update() elif self._drag_start is not None: drag_end = event.pos() / self._zoom sel_rect.translate(drag_end - self._drag_start) self._drag_start = drag_end self.update() # cursor shape: mouse_pos = event.pos() / self._zoom if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self.setCursor(Qt.SizeFDiagCursor) else: self.setCursor(Qt.OpenHandCursor) else: self.setCursor(Qt.CrossCursor) def mouseReleaseEvent (self, event): '''Overrides QWidget's mouseReleaseEvent. Handles ending a resizing or draggin operation on the selection''' # pylint: disable=C0103 self._selection_rect = self._selection_rect.normalized() self._resize_start = None self._drag_start = None self.update() if not self._selection_rect.isNull(): self.selection_changed.emit() def paintEvent(self, event): '''Overrides QWidtget's paintEvent.''' # pylint: disable=C0103 QtGui.QWidget.paintEvent(self, event) self._painter.begin(self) pixmap_dest_rect = QRect(self._image_origin * self._zoom, self._pixmap.size()*self._zoom) self._painter.drawPixmap(pixmap_dest_rect, self._pixmap) if not self._selection_rect.isNull(): # preparing the darkened frame: sel_rect = self._selection_rect.normalized() frame = QtGui.QPixmap(event.rect().size()) frame.fill(QtGui.QColor(0, 0, 0, 127)) frame_painter = QtGui.QPainter(frame) # erase the selected area from the frame: frame_painter.setCompositionMode( QtGui.QPainter.CompositionMode_DestinationIn) sel_rect_scaled = QRect(sel_rect.topLeft() * self._zoom, sel_rect.size() * self._zoom) frame_painter.fillRect(sel_rect_scaled, QtGui.QColor(0, 0, 0, 0)) # draw selection border : frame_painter.setCompositionMode( QtGui.QPainter.CompositionMode_SourceOver) frame_painter.setPen(self._hl_color1) frame_painter.drawRect(sel_rect_scaled) # draw the resize grip (if possible) if sel_rect_scaled.width() > 20 and sel_rect_scaled.height() > 20: handle_rect = QRect(sel_rect_scaled.bottomRight(), self._handle_size) frame_painter.fillRect(handle_rect, self._hl_color2) frame_painter.drawRect(handle_rect) frame_painter.end() # painting the darkened frame: self._painter.drawPixmap(0, 0, frame) self._painter.end() def resizeEvent(self, event): '''Overrides QWidget's resizeEvent. Handles image centering.''' # pylint: disable=C0103 self.adjust_image_origin() # -------------------- [END] QT_OVERRIDE def adjust_image_origin(self): '''Recalculates the top left corner's image position, so the image is painted centered''' # pylint: disable=C0103 new_size = self.size() / self._zoom pix_size = self._pixmap.size() dx = (new_size.width() - pix_size.width() ) /2 dy = (new_size.height() - pix_size.height()) /2 new_image_origin = QPoint(dx, dy) self._selection_rect.translate(new_image_origin - self._image_origin) self._image_origin = new_image_origin log.info('image origin: %s' % new_image_origin) def select_unscaled(self): '''Selects, if possible, a 96 x 96 square centered around the original image. In this way the image won't be scaled but won't take up all the 96 x 96 area.''' # pylint: disable=C0103 pix_size = self._pixmap.size() if pix_size.width() <= 96 and pix_size.height() <= 96: viewport_size = self.size() x = (viewport_size.width () - 96) / 2 y = (viewport_size.height() - 96) / 2 self._selection_rect.setTopLeft(QPoint(x, y)) self._selection_rect.setSize(QSize(96, 96)) self.update() self.selection_changed.emit() def select_all(self): '''Selects the whole image. Currently broken for images taller than wide.''' # TODO: make me work! self._selection_rect.setTopLeft(self._image_origin) self._selection_rect.setSize(self._pixmap.size()) self.update() self.selection_changed.emit() def rotate_left(self): '''Rotates the image counterclockwise.''' self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(-90)) self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def rotate_right(self): '''Rotates the image clockwise''' self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(90)) self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def adjust_minum_size(self): '''Sets the new minimum size, calculated upon the image size and the _zoom factor.''' pixmap = self._pixmap if pixmap.width() < 96 or pixmap.height() < 96: min_size = QSize(96, 96) else: min_size = pixmap.size() self.setMinimumSize(min_size*self._zoom) def make_selection_square(self): '''Modify the selected area making it square''' wid = self._selection_rect.width () self._selection_rect.setSize(QSize(wid, wid)) def set_zoom(self, zoomlevel): '''Sets the specified zoomlevel''' self._zoom = zoomlevel self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def fit_zoom(self): '''Chooses a zoomlevel that makes visible the entire image. Currently broken.''' widget_wid = self.size().width () widget_hei = self.size().height() pixmap_wid = self._pixmap.width () pixmap_hei = self._pixmap.height() self._zoom = (min(widget_wid, widget_hei) / min(pixmap_wid, pixmap_hei)) self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def get_selected_pixmap(self): '''Returns the pixmap contained in the selection rect. Currently doesn't handle transparency correctly''' sel_rect_scaled = QRect(self._selection_rect.topLeft() * self._zoom, self._selection_rect.size() * self._zoom) return QtGui.QPixmap.grabWidget(self, sel_rect_scaled)
class AbstractScrollTela(TelaConsole): def __init__(self, altura, parent=None): super().__init__(parent=parent) self._rectTela = QRect(0,0,0,altura) self._mostrarHorizontal = False self._mostrarVertical = False self._scrollHorizontal = ScrollBarConsole(3,0,orientacao=ScrollBarConsole.HORIZONTAL,parent=self) self._scrollVertical = ScrollBarConsole(self._rectTela.height(),0,orientacao=ScrollBarConsole.VERTICAL,parent=self) self._scrollHorizontal.valorScrollModificado.connect(self._moverHorizontal) self._scrollVertical.valorScrollModificado.connect(self._moverVertical) self._scrollBarFocus = ScrollBarConsole(3,0,parent=self) self._scrollBarFocus.installEventFilter(self) def eventFilter(self, obj, event): if obj == self._scrollBarFocus and event.type() != EventoTecladoConsole.TabType: self._scrollVertical.customEvent(event) self._scrollHorizontal.customEvent(event) return True else: return False def acceptFocus(self): return True def focusNextChild(self): if self._scrollBarFocus.hasFocus(): return False if self.hasFocus(): if not (self._mostrarVertical or self._mostrarHorizontal): return False self._scrollBarFocus.setFocus() else: if not self.acceptFocus(): return False self.setFocus() return True def focusPrevChild(self): if self.hasFocus(): return False if self._scrollBarFocus.hasFocus(): if self.acceptFocus(): self.setFocus() else: return False else: self._scrollBarFocus.setFocus() return True def indexChildActive(self): if self._scrollBarFocus.hasFocus(): return 0 return -1 def getRectTela(self): return self._rectTela def _moverVertical(self, valor): self._scrollVertical.setValorAtual(valor) self._rectTela.moveTop(valor) def _moverHorizontal(self, valor): self._scrollHorizontal.setValorAtual(valor) self._rectTela.moveLeft(valor) def deixarVisivelVertical(self, valor): top = self.getRectTela().top() height = self.getRectTela().height() - self._numLinhasFixas() - 1 bottom = top + height if valor < top: self._moverVertical(valor) elif valor > bottom: self._moverVertical(valor - height) def deixarVisivelHorizontal(self, valor): left = self.getRectTela().left() width = self.getRectTela().width()-1 right = left + width if valor < left: self._moverHorizontal(valor) elif valor > right: self._moverHorizontal(valor - width) def scrollContentsBy(self, dx, dy): self._rectTela.translate(dx,dy) def getDesenhoTela(self): raise NotImplemented("Metodo abstrato") def _adicionarScrollBar(self, tela): if self._mostrarVertical: tela = self._adicionarScrollVertical(tela) if self._mostrarHorizontal: tela = self._adicionarScrollHorizontal(tela) return tela def _adicionarScrollVertical(self, texto): scroll = '' for i in self._scrollVertical.desenhoTelaConsole(self._rectTela.width()).split('\n'): scroll += "{0}|\n".format(i) scroll = "-|\n{0}-|".format(scroll).split('\n') s = '' texto = texto.split('\n') for i in range(len(texto)): s += "{0:{1}}{2}\n".format(texto[i], self._rectTela.width()+2, scroll[i]) if s.endswith('\n'): s = s[:len(s)-1] return s def _adicionarScrollHorizontal(self, texto): texto += '\n|{0}|{1}\n'.format(self._scrollHorizontal.desenhoTelaConsole(self._rectTela.width()), 'X|' if self._mostrarVertical else '') texto += '|{0:-<{1}}|{2}'.format('', self._rectTela.width(), '-|' if self._mostrarVertical else '') return texto def _ajustarScroll(self, tela): linhas = tela.split('\n') numColunas = max(map(len, linhas)) numLinhasFixas = self._numLinhasFixas() numLinhas = len(linhas) + numLinhasFixas self._mostrarVertical = numLinhas > self._rectTela.height() self._mostrarHorizontal = numColunas > self._rectTela.width() self._scrollHorizontal.setAteValor(max(0, numColunas-self._rectTela.width())) self._scrollVertical.setAteValor(max(0, numLinhas-self._rectTela.height())) def _adicionarLinhasFixas(self, tela): """Esse método deve ser sobrescrito pela classe filha para adicionar as linhas fixas na tela""" return tela def _numLinhasFixas(self): return self._adicionarLinhasFixas('').count('\n') def _linhasVisiveis(self, tela): linhas = tela.split('\n') numLinhasFixas = self._numLinhasFixas() numLinhas = len(linhas) + numLinhasFixas if numLinhas < self._rectTela.height(): tela = self._adicionarLinhasFixas(tela) tela += '\n'*(self._rectTela.height()-numLinhas) else: top = self.getRectTela().top() bottom = self.getRectTela().bottom()+1 return self._adicionarLinhasFixas('\n'.join(linhas[top:bottom - numLinhasFixas])) return tela def _colunasVisiveis(self, tela): linhas = tela.split('\n') numColunas = max(map(len, linhas))+1 if numColunas > self._rectTela.width(): tela = '\n'.join([linha[self._rectTela.left():self._rectTela.right()+1] for linha in linhas]) return tela def _ajustarTela(self, tela): tela = self._linhasVisiveis(tela) tela = self._colunasVisiveis(tela) return tela def desenhoTela(self, tam): tela = self.getDesenhoTela() self._ajustarScroll(tela) if self._mostrarVertical: tam -= 2 if tam-2 != self._rectTela.width(): self._rectTela.setWidth(tam-2) self._scrollHorizontal.setTamanho(tam-2) self._ajustarScroll(tela) tela = self._ajustarTela(tela) tela = self._colocarBorda(tela, tam) return self._adicionarScrollBar(tela)
class ImageAreaSelector(QtGui.QWidget): '''This widget provides means to visually crop a portion of an image by selecting it''' # pylint: disable=W0612 NAME = 'ImageAreaSelector' DESCRIPTION = 'A widget used to select part of an image' AUTHOR = 'Gabriele "Whisky" Visconti' WEBSITE = '' # pylint: enable=W0612 selection_changed = QtCore.pyqtSignal() def __init__(self, pixmap, parent=None): '''Constructor''' QtGui.QWidget.__init__(self, parent) self._pixmap = pixmap self._selection_rect = QRect() self._image_origin = QPoint() self._resize_start = None self._drag_start = None self._handle_size = QSize(-10, -10) self._painter = QtGui.QPainter() self._hl_color1 = QtGui.QPalette().color(QtGui.QPalette.Highlight) self._hl_color2 = QtGui.QPalette().color(QtGui.QPalette.Highlight) self._hl_color2.setAlpha(150) self._zoom = 1.0 self.adjust_minum_size() self.setBackgroundRole(QtGui.QPalette.Dark) self.setMouseTracking(True) self.setCursor(Qt.CrossCursor) # -------------------- [BEGIN] QT_OVERRIDE def mousePressEvent(self, event): '''Overrides QWidget's mousePressEvent. Handles starting a new selection, starting a drag operation''' # pylint: disable=C0103 mouse_pos = event.pos() / self._zoom sel_rect = self._selection_rect if not event.button() == Qt.LeftButton: return if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self._resize_start = mouse_pos else: self._drag_start = mouse_pos else: self._resize_start = mouse_pos sel_rect.setTopLeft(mouse_pos) self._selection_rect.setSize(QSize(0, 0)) def mouseMoveEvent(self, event): '''Overrides QWidget's mouseMoveEvent. Handles resizing and dragging operations on selection''' # pylint: disable=C0103 sel_rect = self._selection_rect if self._resize_start: resize_end = event.pos() / self._zoom sel_rect.setBottomRight(sel_rect.bottomRight() + (resize_end - self._resize_start)) self._resize_start = resize_end self.make_selection_square() self.update() elif self._drag_start is not None: drag_end = event.pos() / self._zoom sel_rect.translate(drag_end - self._drag_start) self._drag_start = drag_end self.update() # cursor shape: mouse_pos = event.pos() / self._zoom if (not sel_rect.isNull()) and sel_rect.contains(mouse_pos, True): handle_rect = QRect(sel_rect.bottomRight(), self._handle_size) if handle_rect.contains(mouse_pos): self.setCursor(Qt.SizeFDiagCursor) else: self.setCursor(Qt.OpenHandCursor) else: self.setCursor(Qt.CrossCursor) def mouseReleaseEvent(self, event): '''Overrides QWidget's mouseReleaseEvent. Handles ending a resizing or draggin operation on the selection''' # pylint: disable=C0103 self._selection_rect = self._selection_rect.normalized() self._resize_start = None self._drag_start = None self.update() if not self._selection_rect.isNull(): self.selection_changed.emit() def paintEvent(self, event): '''Overrides QWidtget's paintEvent.''' # pylint: disable=C0103 QtGui.QWidget.paintEvent(self, event) self._painter.begin(self) pixmap_dest_rect = QRect(self._image_origin * self._zoom, self._pixmap.size() * self._zoom) self._painter.drawPixmap(pixmap_dest_rect, self._pixmap) if not self._selection_rect.isNull(): # preparing the darkened frame: sel_rect = self._selection_rect.normalized() frame = QtGui.QPixmap(event.rect().size()) frame.fill(QtGui.QColor(0, 0, 0, 127)) frame_painter = QtGui.QPainter(frame) # erase the selected area from the frame: frame_painter.setCompositionMode( QtGui.QPainter.CompositionMode_DestinationIn) sel_rect_scaled = QRect(sel_rect.topLeft() * self._zoom, sel_rect.size() * self._zoom) frame_painter.fillRect(sel_rect_scaled, QtGui.QColor(0, 0, 0, 0)) # draw selection border : frame_painter.setCompositionMode( QtGui.QPainter.CompositionMode_SourceOver) frame_painter.setPen(self._hl_color1) frame_painter.drawRect(sel_rect_scaled) # draw the resize grip (if possible) if sel_rect_scaled.width() > 20 and sel_rect_scaled.height() > 20: handle_rect = QRect(sel_rect_scaled.bottomRight(), self._handle_size) frame_painter.fillRect(handle_rect, self._hl_color2) frame_painter.drawRect(handle_rect) frame_painter.end() # painting the darkened frame: self._painter.drawPixmap(0, 0, frame) self._painter.end() def resizeEvent(self, event): '''Overrides QWidget's resizeEvent. Handles image centering.''' # pylint: disable=C0103 self.adjust_image_origin() # -------------------- [END] QT_OVERRIDE def adjust_image_origin(self): '''Recalculates the top left corner's image position, so the image is painted centered''' # pylint: disable=C0103 new_size = self.size() / self._zoom pix_size = self._pixmap.size() dx = (new_size.width() - pix_size.width()) / 2 dy = (new_size.height() - pix_size.height()) / 2 new_image_origin = QPoint(dx, dy) self._selection_rect.translate(new_image_origin - self._image_origin) self._image_origin = new_image_origin log.info('image origin: %s' % new_image_origin) def select_unscaled(self): '''Selects, if possible, a 96 x 96 square centered around the original image. In this way the image won't be scaled but won't take up all the 96 x 96 area.''' # pylint: disable=C0103 pix_size = self._pixmap.size() if pix_size.width() <= 96 and pix_size.height() <= 96: viewport_size = self.size() x = (viewport_size.width() - 96) / 2 y = (viewport_size.height() - 96) / 2 self._selection_rect.setTopLeft(QPoint(x, y)) self._selection_rect.setSize(QSize(96, 96)) self.update() self.selection_changed.emit() def select_all(self): '''Selects the whole image. Currently broken for images taller than wide.''' # TODO: make me work! self._selection_rect.setTopLeft(self._image_origin) self._selection_rect.setSize(self._pixmap.size()) self.update() self.selection_changed.emit() def rotate_left(self): '''Rotates the image counterclockwise.''' self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(-90)) self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def rotate_right(self): '''Rotates the image clockwise''' self._pixmap = self._pixmap.transformed(QtGui.QTransform().rotate(90)) self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def adjust_minum_size(self): '''Sets the new minimum size, calculated upon the image size and the _zoom factor.''' pixmap = self._pixmap if pixmap.width() < 96 or pixmap.height() < 96: min_size = QSize(96, 96) else: min_size = pixmap.size() self.setMinimumSize(min_size * self._zoom) def make_selection_square(self): '''Modify the selected area making it square''' wid = self._selection_rect.width() self._selection_rect.setSize(QSize(wid, wid)) def set_zoom(self, zoomlevel): '''Sets the specified zoomlevel''' self._zoom = zoomlevel self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def fit_zoom(self): '''Chooses a zoomlevel that makes visible the entire image. Currently broken.''' widget_wid = self.size().width() widget_hei = self.size().height() pixmap_wid = self._pixmap.width() pixmap_hei = self._pixmap.height() self._zoom = (min(widget_wid, widget_hei) / min(pixmap_wid, pixmap_hei)) self.adjust_minum_size() self.adjust_image_origin() self.update() self.selection_changed.emit() def get_selected_pixmap(self): '''Returns the pixmap contained in the selection rect. Currently doesn't handle transparency correctly''' sel_rect_scaled = QRect(self._selection_rect.topLeft() * self._zoom, self._selection_rect.size() * self._zoom) return QtGui.QPixmap.grabWidget(self, sel_rect_scaled)