예제 #1
0
class Convertor:

    def __init__(self, path, stitches_only = False):
    
        self.jef = jef.Pattern(path)
        self.stitches_only = stitches_only
        self.rect = QRect()
    
    def bounding_rect(self):
    
        if not self.rect.isNull():
            return self.rect
        
        x, y = [], []
        for coordinates in self.jef.coordinates:
            i = map(lambda (op, i, j): i, coordinates)
            j = map(lambda (op, i, j): j, coordinates)
            x.append(min(i))
            x.append(max(i))
            y.append(min(j))
            y.append(max(j))
        
        return QRect(min(x), -max(y), max(x) - min(x), max(y) - min(y))
    
    def show(self, painter):
    
        painter.save()
        painter.translate(-self.bounding_rect().topLeft())
        
        i = 0
        for i in range(self.jef.threads):
        
            colour = QColor(*self.jef.colour_for_thread(i))
            coordinates = self.jef.coordinates[i]
            
            if not self.stitches_only:
                pen = QPen(QColor(200, 200, 200))
                painter.setPen(pen)
                
                for op, x, y in coordinates:
                    painter.drawEllipse(x - 2, -y - 2, 4, 4)
            
            pen = QPen(colour)
            painter.setPen(pen)
            
            mx, my = 0, 0
            for op, x, y in coordinates:
                if op == "move":
                    mx, my = x, y
                elif op == "stitch":
                    painter.drawLine(mx, -my, x, -y)
                    mx, my = x, y
            
            i += 1
        
        painter.restore()
예제 #2
0
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)
예제 #3
0
class XSnapshotWidget(QWidget):
    def __init__(self, parent=None):
        super(XSnapshotWidget, self).__init__(parent)

        # define custom properties
        self._region = QRect()
        self._filepath = ''

        # define custom properties
        palette = self.palette()
        palette.setColor(palette.Window, QColor('white'))
        self.setPalette(palette)
        self.setWindowOpacity(0.5)
        self.setWindowFlags(Qt.SplashScreen)
        self.setFocus()

    def accept(self):
        """
        Prompts the user for the filepath to save and then saves the image.
        """
        filetypes = 'PNG Files (*.png);;JPG Files (*.jpg);;All Files (*.*)'
        filename = QFileDialog.getSaveFileName(None, 'Save Snapshot',
                                               self.filepath(), filetypes)

        if type(filename) == tuple:
            filename = filename[0]

        filename = str(filename)
        if not filename:
            self.reject()
        else:
            self.setFilepath(filename)
            self.save()

    def filepath(self):
        """
        Returns the filepath that is going to be asved for this snapshot widget.
        
        :return     <str>
        """
        return self._filepath

    def hideWindow(self):
        """
        Sets the window to hide/show while taking the snapshot.
        
        :param      window | <QMainWindow> || <QDialog>
        """
        return self._hideWindow

    def keyPressEvent(self, event):
        """
        Listens for the escape key to cancel out from this snapshot.
        
        :param      event | <QKeyPressEvent>
        """
        # reject on a cancel
        if event.key() == Qt.Key_Escape:
            self.reject()

        super(XSnapshotWidget, self).keyPressEvent(event)

    def mousePressEvent(self, event):
        """
        Starts the selection process for this widget and snapshot area.
        
        :param      event | <QMousePressEvent>
        """
        self._region.setX(event.pos().x())
        self._region.setY(event.pos().y())
        super(XSnapshotWidget, self).mousePressEvent(event)

    def mouseMoveEvent(self, event):
        """
        Drags the selection view for this widget.
        
        :param      event | <QMouseMoveEvent>
        """
        w = event.pos().x() - self._region.x()
        h = event.pos().y() - self._region.y()

        self._region.setWidth(w)
        self._region.setHeight(h)
        self.repaint()

        super(XSnapshotWidget, self).mouseMoveEvent(event)

    def mouseReleaseEvent(self, event):
        """
        Finishes the selection event.
        
        :param      event | <QMouseReleaseEvent>
        """
        self.accept()
        super(XSnapshotWidget, self).mouseReleaseEvent(event)

    def paintEvent(self, event):
        """
        Handles the drawing for this widget and its selection region.
        
        :param      event | <QPaintEvent>
        """
        pen = QPen(Qt.DashLine)
        pen.setColor(QColor('red'))
        painter = QPainter(self)
        painter.setPen(pen)
        clr = QColor('black')
        clr.setAlpha(100)
        painter.setBrush(clr)

        painter.drawRect(self._region)

    def reject(self):
        """
        Rejects the snapshot and closes the widget.
        """
        if self.hideWindow():
            self.hideWindow().show()

        self.close()
        self.deleteLater()

    def region(self):
        """
        Returns the selection region defined by the rectangle for snapshoting.
        
        :return     <QRect>
        """
        return self._region

    def save(self):
        """
        Saves the snapshot based on the current region.
        """
        # close down the snapshot widget
        if self.hideWindow():
            self.hideWindow().hide()

        self.hide()
        QApplication.processEvents()
        time.sleep(1)

        # create the pixmap to save
        wid = QApplication.desktop().winId()

        if not self._region.isNull():
            x = self._region.x()
            y = self._region.y()
            w = self._region.width()
            h = self._region.height()
        else:
            x = self.x()
            y = self.y()
            w = self.width()
            h = self.height()

        pixmap = QPixmap.grabWindow(wid, x, y, w, h)
        pixmap.save(self.filepath())

        self.close()
        self.deleteLater()
        if self.hideWindow():
            self.hideWindow().show()

    def show(self):
        """
        Shows this widget and hides the specified window if necessary.
        """
        super(XSnapshotWidget, self).show()

        if self.hideWindow():
            self.hideWindow().hide()
            QApplication.processEvents()

    def setFilepath(self, filepath):
        """
        Sets the filepath that will be saved for this snapshot.
        
        :param      filepath | <str>
        """
        self._filepath = filepath

    def setHideWindow(self, window):
        """
        Sets the window that will be hidden while this snapshot is being
        taken.
        
        :param      window | <QMainWindow>
        """
        self._hideWindow = window

    def setRegion(self, rect):
        """
        Sets the region rectangle to the inputed rect.
        
        :param      rect | <QRect>
        """
        if rect is not None:
            self._region = rect

    @staticmethod
    def capture(rect=None, filepath='', prompt=True, hideWindow=None):
        """
        Prompts the user to capture the screen.
        
        :param      rect     | <QRect>
                    filepath | <str>
                    prompt   | <bool>
        
        :return     (<str> filepath, <bool> accepted)
        """
        widget = XSnapshotWidget(QApplication.desktop())
        widget.setRegion(rect)
        widget.setHideWindow(hideWindow)
        widget.setFilepath(filepath)
        widget.move(1, 1)
        widget.resize(QApplication.desktop().size())

        if prompt or not filepath:
            widget.show()
        else:
            widget.save()
예제 #4
0
class XSnapshotWidget(QWidget):
    def __init__(self, parent=None):
        super(XSnapshotWidget, self).__init__(parent)
        
        # define custom properties
        self._region = QRect()
        self._filepath = ''
        
        # define custom properties
        palette = self.palette()
        palette.setColor(palette.Window, QColor('white'))
        self.setPalette(palette)
        self.setWindowOpacity(0.5)
        self.setWindowFlags(Qt.SplashScreen)
        self.setFocus()
    
    def accept(self):
        """
        Prompts the user for the filepath to save and then saves the image.
        """
        filetypes = 'PNG Files (*.png);;JPG Files (*.jpg);;All Files (*.*)'
        filename = QFileDialog.getSaveFileName(None,
                                               'Save Snapshot',
                                               self.filepath(),
                                               filetypes)
        
        if type(filename) == tuple:
            filename = filename[0]
        
        filename = str(filename)
        if not filename:
            self.reject()
        else:
            self.setFilepath(filename)
            self.save()
    
    def filepath(self):
        """
        Returns the filepath that is going to be asved for this snapshot widget.
        
        :return     <str>
        """
        return self._filepath
    
    def hideWindow(self):
        """
        Sets the window to hide/show while taking the snapshot.
        
        :param      window | <QMainWindow> || <QDialog>
        """
        return self._hideWindow
    
    def keyPressEvent(self, event):
        """
        Listens for the escape key to cancel out from this snapshot.
        
        :param      event | <QKeyPressEvent>
        """
        # reject on a cancel
        if event.key() == Qt.Key_Escape:
            self.reject()
        
        super(XSnapshotWidget, self).keyPressEvent(event)
    
    def mousePressEvent(self, event):
        """
        Starts the selection process for this widget and snapshot area.
        
        :param      event | <QMousePressEvent>
        """
        self._region.setX(event.pos().x())
        self._region.setY(event.pos().y())
        super(XSnapshotWidget, self).mousePressEvent(event)
    
    def mouseMoveEvent(self, event):
        """
        Drags the selection view for this widget.
        
        :param      event | <QMouseMoveEvent>
        """
        w = event.pos().x() - self._region.x()
        h = event.pos().y() - self._region.y()
        
        self._region.setWidth(w)
        self._region.setHeight(h)
        self.repaint()
        
        super(XSnapshotWidget, self).mouseMoveEvent(event)
    
    def mouseReleaseEvent(self, event):
        """
        Finishes the selection event.
        
        :param      event | <QMouseReleaseEvent>
        """
        self.accept()
        super(XSnapshotWidget, self).mouseReleaseEvent(event)
    
    def paintEvent(self, event):
        """
        Handles the drawing for this widget and its selection region.
        
        :param      event | <QPaintEvent>
        """
        pen = QPen(Qt.DashLine)
        pen.setColor(QColor('red'))
        painter = QPainter(self)
        painter.setPen(pen)
        clr = QColor('black')
        clr.setAlpha(100)
        painter.setBrush(clr)
        
        painter.drawRect(self._region)
    
    def reject(self):
        """
        Rejects the snapshot and closes the widget.
        """
        if self.hideWindow():
            self.hideWindow().show()
            
        self.close()
        self.deleteLater()
    
    def region(self):
        """
        Returns the selection region defined by the rectangle for snapshoting.
        
        :return     <QRect>
        """
        return self._region
    
    def save(self):
        """
        Saves the snapshot based on the current region.
        """
        # close down the snapshot widget
        if self.hideWindow():
            self.hideWindow().hide()
        
        self.hide()
        QApplication.processEvents()
        time.sleep(1)
        
        # create the pixmap to save
        wid = QApplication.desktop().winId()
        
        if not self._region.isNull():
            x = self._region.x()
            y = self._region.y()
            w = self._region.width()
            h = self._region.height()
        else:
            x = self.x()
            y = self.y()
            w = self.width()
            h = self.height()
        
        pixmap = QPixmap.grabWindow(wid, x, y, w, h)
        pixmap.save(self.filepath())
        
        self.close()
        self.deleteLater()
        if self.hideWindow():
            self.hideWindow().show()
    
    def show(self):
        """
        Shows this widget and hides the specified window if necessary.
        """
        super(XSnapshotWidget, self).show()
        
        if self.hideWindow():
            self.hideWindow().hide()
            QApplication.processEvents()
    
    def setFilepath(self, filepath):
        """
        Sets the filepath that will be saved for this snapshot.
        
        :param      filepath | <str>
        """
        self._filepath = filepath
    
    def setHideWindow(self, window):
        """
        Sets the window that will be hidden while this snapshot is being
        taken.
        
        :param      window | <QMainWindow>
        """
        self._hideWindow = window
    
    def setRegion(self, rect):
        """
        Sets the region rectangle to the inputed rect.
        
        :param      rect | <QRect>
        """
        if rect is not None:
            self._region = rect
    
    @staticmethod
    def capture(rect=None, filepath='', prompt=True, hideWindow=None):
        """
        Prompts the user to capture the screen.
        
        :param      rect     | <QRect>
                    filepath | <str>
                    prompt   | <bool>
        
        :return     (<str> filepath, <bool> accepted)
        """
        widget = XSnapshotWidget(QApplication.desktop())
        widget.setRegion(rect)
        widget.setHideWindow(hideWindow)
        widget.setFilepath(filepath)
        widget.move(1, 1)
        widget.resize(QApplication.desktop().size())
        
        if prompt or not filepath:
            widget.show()
        else:
            widget.save()
예제 #5
0
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)