def _runImpl(self):

        processed = set()
        self._dataPending.wait()
        if self._numLayers == 0:
            return
        bbox = QRect()
        toUpdate = numpy.zeros((len(self._tiling),), dtype=numpy.uint8)
        while len(self._queue) > 0:
            self._dataPending.clear()

            layerNr, patchNr, image, tiling, numLayers = self._queue.popleft()
            if tiling != self._tiling or numLayers != self._numLayers:
                continue            
            if (layerNr, patchNr) in processed:
                continue
            processed.add((layerNr, patchNr))

            rect = self._tiling._imageRect[patchNr]
            bbox = bbox.united(rect)

            self._imageLayersNext[layerNr,patchNr] = image
            toUpdate[patchNr] = 1


        firstOpaqueLayer = 1000000000000000000
        for i, (visible, layerOpacity, layerImageSource) in enumerate(self._stackedIms):
            if visible and layerOpacity == 1.0 and layerImageSource.isOpaque():
                firstOpaqueLayer = i
                break

        for patchNr in toUpdate.nonzero()[0]: 
            self._compositeNext[patchNr] = QImage(self._tiling._imageRect[patchNr].size(), QImage.Format_ARGB32_Premultiplied)
            self._compositeNext[patchNr].fill(Qt.white)
            p = QPainter(self._compositeNext[patchNr])

            for i, v in enumerate(reversed(self._stackedIms)):
                visible, layerOpacity, layerImageSource = v
                if not visible:
                    continue

                layerNr = len(self._stackedIms) - i - 1
                if layerNr > firstOpaqueLayer:
                    continue

                patch = self._imageLayersNext[layerNr, patchNr]
                p.setOpacity(layerOpacity)
                if patch is not None:
                    p.drawImage(0,0, patch)
            p.end()

        w = numpy.equal(self._compositeNext, None)
        self._compositeCurrent = numpy.where(numpy.equal(self._compositeNext, None), self._compositeCurrent, self._compositeNext)
        self._compositeNext[:] = None

        self.patchAvailable.emit(bbox)
Esempio n. 2
0
 def destinationsRect(self, destinations):
     """Return the rectangle containing all destinations."""
     layout = self.view.surface().pageLayout()
     rect = QRect()
     for dest in destinations:
         for pageNum, r in dest:
             rect = rect.united(layout[pageNum].linkRect(r.normalized()))
     # not larger than viewport
     rect.setSize(rect.size().boundedTo(self.view.viewport().size()))
     return rect
Esempio n. 3
0
 def destinationsRect(self, destinations):
     """Return the rectangle containing all destinations."""
     layout = self.view.surface().pageLayout()
     rect = QRect()
     for dest in destinations:
         for pageNum, r in dest:
             rect = rect.united(layout[pageNum].linkRect(r.normalized()))
     # not larger than viewport
     rect.setSize(rect.size().boundedTo(self.view.viewport().size()))
     return rect
Esempio n. 4
0
class VispaWidgetOwner(object):
    """ Interface for classes containing VispaWidgets
    
    Only makes sense if implementing class also inherits QWidget or class inheriting QWidget.
    """
    def enableMultiSelect(self, multiSelect=True):
        self._multiSelectEnabledFlag = multiSelect

    def multiSelectEnabled(self):
        return hasattr(
            self, "_multiSelectEnabledFlag") and self._multiSelectEnabledFlag

    def selectedWidgets(self):
        """ Returns a list of all selected widgets.
        """
        if hasattr(self, "_selectedWidgets"):
            return self._selectedWidgets
        return [
            child for child in self.children()
            if hasattr(child, "isSelected") and child.isSelected()
        ]

    def widgetSelected(self, widget, multiSelect=False):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        logging.debug(self.__class__.__name__ + ": widgetSelected()")

        if isinstance(self, QObject):
            if not hasattr(self, "_selectedWidgets"):
                self._selectedWidgets = []

            if not multiSelect or not self.multiSelectEnabled():
                self.deselectAllWidgets(widget)
                self._selectedWidgets = []

            if widget.parent() == self and not widget in self._selectedWidgets:
                self._selectedWidgets.append(widget)

            for widget in [
                    child for child in self._selectedWidgets
                    if hasattr(child, "isSelected") and not child.isSelected()
            ]:
                self._selectedWidgets.remove(widget)

            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetSelected(widget)

    def widgetDoubleClicked(self, widget):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        #logging.debug(self.__class__.__name__ +": widgetDoubleClicked()")
        if isinstance(self, QObject):
            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetDoubleClicked(widget)

    def initWidgetMovement(self, widget):
        self._lastMovedWidgets = []
        if self.multiSelectEnabled():
            pos = widget.pos()
            for child in self.children():
                if child != widget and hasattr(
                        child, "isSelected") and child.isSelected():
                    child.setDragReferencePoint(pos - child.pos())

    def widgetDragged(self, widget):
        """ Tell parent widget has moved.
        
        Only informs parent if it is a VispaWidgetOwner, too.
        """
        if isinstance(self.parent(), VispaWidgetOwner):
            self.parent().widgetDragged(widget)

        if hasattr(self, "_lastMovedWidgets"):
            self._lastMovedWidgets.append(widget)

        if self.multiSelectEnabled():
            for child in self.children():
                if hasattr(
                        child,
                        "dragReferencePoint") and child != widget and hasattr(
                            child, "isSelected") and child.isSelected():
                    if hasattr(child, "setPreviousDragPosition"):
                        child.setPreviousDragPosition(child.pos())
                    child.move(widget.pos() - child.dragReferencePoint())
                    self._lastMovedWidgets.append(child)

# apparently unused feature (2010-07-02), remove if really unnecessary
# also see self._lastMovedWidget definition above

    def lastMovedWidgets(self):
        if hasattr(self, "_lastMovedWidgets"):
            return self._lastMovedWidgets
        return None

    def widgetAboutToDelete(self, widget):
        """ This function is called from the delete() function of VispaWidget.
        """
        pass

    def keyPressEvent(self, event):
        """ Calls delete() method of selected child widgets if multi-select is activated.
        """
        if self.multiSelectEnabled() and (event.key() == Qt.Key_Backspace
                                          or event.key() == Qt.Key_Delete):
            selection = self.selectedWidgets()[:]
            for widget in selection:
                widget.delete()

    def deselectAllWidgets(self, exception=None):
        """ Deselects all widgets except the widget given as exception.
        """
        #logging.debug(self.__class__.__name__ +": deselectAllWidgets()")
        self._selectedWidgets = []
        for child in self.children():
            if child != exception:
                if hasattr(child, 'select'):
                    child.select(False)
            else:
                self._selectedWidgets.append(child)

            if isinstance(child, VispaWidgetOwner):
                child.deselectAllWidgets(exception)
        self.update()

    def mousePressEvent(self, event):
        """ Calls deselectAllWidgets.
        """
        multiSelectEnabled = self.multiSelectEnabled()
        if event.modifiers() != Qt.ControlModifier:
            self.deselectAllWidgets()
        if multiSelectEnabled:
            self._selectionRectStartPos = QPoint(event.pos())
            self._selectionRect = None

    def mouseMoveEvent(self, event):
        if self.multiSelectEnabled() and self._selectionRectStartPos and (
                event.pos() - self._selectionRectStartPos
        ).manhattanLength() >= QApplication.startDragDistance():
            eventX = event.pos().x()
            eventY = event.pos().y()
            startX = self._selectionRectStartPos.x()
            startY = self._selectionRectStartPos.y()
            oldRect = self._selectionRect
            self._selectionRect = QRect(min(startX, eventX),
                                        min(startY, eventY),
                                        abs(eventX - startX),
                                        abs(eventY - startY))
            if oldRect:
                self.update(
                    self._selectionRect.united(oldRect).adjusted(-5, -5, 5, 5))
            else:
                self.update(self._selectionRect)

            # dynamically update selection statur
            # currently bad performance (2010-07-07)
            # TODO: improve selection mechanism
#            for child in self.children():
#                if hasattr(child, "select") and hasattr(child, "isSelected"):
#                    child.select(self._selectionRect.contains(child.geometry()), True)    # select, mulitSelect

    def mouseReleaseEvent(self, event):
        if hasattr(self, "_selectionRect"
                   ) and self._selectionRect and self.multiSelectEnabled():
            for child in self.children():
                if hasattr(child, "select") and hasattr(
                        child, "isSelected") and self._selectionRect.contains(
                            child.geometry()) and not child.isSelected():
                    child.select(True, True)  # select, mulitSelect
            self.update(self._selectionRect.adjusted(-5, -5, 5, 5))
        self._selectionRect = None
        self._selectionRectStartPos = None
Esempio n. 5
0
 def __selectionForArea(self, area):
     r1, c1 = self._cellAt(area.topLeft())
     r2, c2 = self._cellAt(area.bottomRight())
     topleft = QRect(c1, r1, 1, 1)
     bottomright = QRect(c2, r2, 1, 1)
     return topleft.united(bottomright).normalized()
Esempio n. 6
0
class VispaWidgetOwner(object):
    """ Interface for classes containing VispaWidgets
    
    Only makes sense if implementing class also inherits QWidget or class inheriting QWidget.
    """
    
    def enableMultiSelect(self, multiSelect=True):
        self._multiSelectEnabledFlag = multiSelect
        
    def multiSelectEnabled(self):
        return hasattr(self, "_multiSelectEnabledFlag") and self._multiSelectEnabledFlag
    
    def selectedWidgets(self):
        """ Returns a list of all selected widgets.
        """
        if hasattr(self, "_selectedWidgets"):
            return self._selectedWidgets
        return [child for child in self.children() if hasattr(child, "isSelected") and child.isSelected()]
    
    def widgetSelected(self, widget, multiSelect=False):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        logging.debug(self.__class__.__name__ +": widgetSelected()")

        if isinstance(self, QObject):
            if not hasattr(self, "_selectedWidgets"):
                self._selectedWidgets = []
                
            if  not multiSelect or not self.multiSelectEnabled():
                self.deselectAllWidgets(widget)
                self._selectedWidgets = []
                
            if widget.parent() == self and not widget in self._selectedWidgets:
                self._selectedWidgets.append(widget)
                
            for widget in [child for child in self._selectedWidgets if hasattr(child, "isSelected") and not child.isSelected()]:
                self._selectedWidgets.remove(widget)
                
            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetSelected(widget)
            
    def widgetDoubleClicked(self, widget):
        """ Forward selection information to super class if it is a VispaWidgetOwner.
        """
        #logging.debug(self.__class__.__name__ +": widgetDoubleClicked()")
        if isinstance(self, QObject):
            if isinstance(self.parent(), VispaWidgetOwner):
                self.parent().widgetDoubleClicked(widget)
                
    def initWidgetMovement(self, widget):
        self._lastMovedWidgets = []
        if self.multiSelectEnabled():
            pos = widget.pos()
            for child in self.children():
                if child != widget and hasattr(child, "isSelected") and child.isSelected():
                    child.setDragReferencePoint(pos - child.pos())
            
    def widgetDragged(self, widget):
        """ Tell parent widget has moved.
        
        Only informs parent if it is a VispaWidgetOwner, too.
        """
        if isinstance(self.parent(), VispaWidgetOwner):
            self.parent().widgetDragged(widget)

        if hasattr(self, "_lastMovedWidgets"):
            self._lastMovedWidgets.append(widget)
            
        if self.multiSelectEnabled():
            for child in self.children():
                if hasattr(child, "dragReferencePoint") and child != widget and hasattr(child, "isSelected") and child.isSelected():
                    if hasattr(child, "setPreviousDragPosition"):
                        child.setPreviousDragPosition(child.pos())
                    child.move(widget.pos() - child.dragReferencePoint())
                    self._lastMovedWidgets.append(child)

# apparently unused feature (2010-07-02), remove if really unnecessary
# also see self._lastMovedWidget definition above
    def lastMovedWidgets(self):
        if hasattr(self, "_lastMovedWidgets"):
            return self._lastMovedWidgets
        return None

    def widgetAboutToDelete(self, widget):
        """ This function is called from the delete() function of VispaWidget.
        """
        pass
        
    def keyPressEvent(self, event):
        """ Calls delete() method of selected child widgets if multi-select is activated.
        """
        if self.multiSelectEnabled() and ( event.key() == Qt.Key_Backspace or event.key() == Qt.Key_Delete ):
            selection = self.selectedWidgets()[:]
            for widget in selection:
                widget.delete()
    
    def deselectAllWidgets(self, exception=None):
        """ Deselects all widgets except the widget given as exception.
        """
        #logging.debug(self.__class__.__name__ +": deselectAllWidgets()")
        self._selectedWidgets = []
        for child in self.children():
            if child != exception:
                if hasattr(child, 'select'):
                    child.select(False)
            else:
                self._selectedWidgets.append(child)
                
            if isinstance(child, VispaWidgetOwner):
                child.deselectAllWidgets(exception)
        self.update()
        
    def mousePressEvent(self, event):
        """ Calls deselectAllWidgets.
        """
        multiSelectEnabled = self.multiSelectEnabled()
        if event.modifiers() != Qt.ControlModifier:
            self.deselectAllWidgets()
        if multiSelectEnabled:
            self._selectionRectStartPos = QPoint(event.pos())
            self._selectionRect = None

    def mouseMoveEvent(self, event):
        if self.multiSelectEnabled() and self._selectionRectStartPos and (event.pos() - self._selectionRectStartPos).manhattanLength() >= QApplication.startDragDistance():
            eventX = event.pos().x()
            eventY = event.pos().y()
            startX = self._selectionRectStartPos.x()
            startY = self._selectionRectStartPos.y()
            oldRect = self._selectionRect
            self._selectionRect = QRect(min(startX, eventX), min(startY, eventY), abs(eventX - startX), abs(eventY - startY))
            if oldRect:
                self.update(self._selectionRect.united(oldRect).adjusted(-5, -5, 5, 5))
            else:
                self.update(self._selectionRect)
                
            # dynamically update selection statur
            # currently bad performance (2010-07-07)
            # TODO: improve selection mechanism
#            for child in self.children():
#                if hasattr(child, "select") and hasattr(child, "isSelected"):
#                    child.select(self._selectionRect.contains(child.geometry()), True)    # select, mulitSelect 
                
    def mouseReleaseEvent(self, event):
        if hasattr(self, "_selectionRect") and  self._selectionRect and self.multiSelectEnabled():
            for child in self.children():
                if hasattr(child, "select") and hasattr(child, "isSelected") and self._selectionRect.contains(child.geometry()) and not child.isSelected():
                    child.select(True, True)    # select, mulitSelect 
            self.update(self._selectionRect.adjusted(-5, -5, 5, 5))
        self._selectionRect = None
        self._selectionRectStartPos = None
        
Esempio n. 7
0
 def __selectionForArea(self, area):
     r1, c1 = self._cellAt(area.topLeft())
     r2, c2 = self._cellAt(area.bottomRight())
     topleft = QRect(c1, r1, 1, 1)
     bottomright = QRect(c2, r2, 1, 1)
     return topleft.united(bottomright).normalized()
Esempio n. 8
0
class Renderer:
    def __init__(self, pattern, colourModel, stitches_only=False):

        self.pattern = pattern
        self.colourModel = colourModel
        self.stitches_only = stitches_only
        self.rect = QRect()
        self.zones = []
        self._arrange_data()

    def _arrange_data(self):

        self.rect = QRect()

        for i in range(len(self.pattern.coordinates)):

            coordinates = self.pattern.coordinates[i]
            colour_item = self.colourModel.item(i)

            lines = []
            xb, yb = [], []
            mx, my = 0, 0

            for op, x, y in coordinates:
                xb.append(x)
                yb.append(y)
                if op == "move":
                    mx, my = x, y
                elif op == "stitch":
                    line = QLine(mx, -my, x, -y)
                    lines.append(line)
                    mx, my = x, y

            xb = [min(xb), max(xb)]
            yb = [min(yb), max(yb)]
            rect = QRect(min(xb), -max(yb),
                         max(xb) - min(xb),
                         max(yb) - min(yb))
            self.rect = self.rect.united(rect)

            zone = Zone(rect, colour_item)
            zone.lines = lines
            self._partition_data(zone)
            self.zones.append(zone)

    def _partition_data(self, zone):

        subzone_width = zone.rect.width() / 2
        subzone_height = zone.rect.height() / 2

        if subzone_width < 100 or subzone_height < 100 or len(
                zone.lines) <= 10:
            return

        subzones = [
            Zone(
                QRect(zone.rect.x(), zone.rect.y(), subzone_width,
                      subzone_height), zone.colour_item),
            Zone(
                QRect(zone.rect.x() + subzone_width, zone.rect.y(),
                      subzone_width, subzone_height), zone.colour_item),
            Zone(
                QRect(zone.rect.x(),
                      zone.rect.y() + subzone_height, subzone_width,
                      subzone_height), zone.colour_item),
            Zone(
                QRect(zone.rect.x() + subzone_width,
                      zone.rect.y() + subzone_height, subzone_width,
                      subzone_height), zone.colour_item)
        ]

        lines = []

        for line in zone.lines:
            for subzone in subzones:
                # If a line is completely within a subzone, add it to the
                # subzone and ignore all other subzones.
                if subzone.rect.contains(line.p1()) and subzone.rect.contains(
                        line.p2()):
                    subzone.lines.append(line)
                    break
            else:
                # If a line is not completely within a zone, add it to the list
                # of lines to keep in the zone.
                lines.append(line)

        zone.lines = lines

        for subzone in subzones:
            if subzone.lines:
                zone.subzones.append(subzone)
                self._partition_data(subzone)

    def bounding_rect(self):

        if self.pattern.hoop_size:
            return QRect(-10 * self.pattern.hoop_size[0] / 2.0,
                         -10 * self.pattern.hoop_size[1] / 2.0,
                         10 * self.pattern.hoop_size[0],
                         10 * self.pattern.hoop_size[1])
        else:
            return self.rect

    def paint(self, painter, rect):

        # Transform the rectangle from window to pattern coordinates.
        rect = rect.translated(self.bounding_rect().topLeft())

        painter.save()
        painter.translate(-self.bounding_rect().topLeft())

        if self.pattern.hoop_size:
            painter.setPen(QPen(Qt.black))
            painter.drawRect(-10 * self.pattern.hoop_size[0] / 2.0,
                             -10 * self.pattern.hoop_size[1] / 2.0,
                             10 * self.pattern.hoop_size[0],
                             10 * self.pattern.hoop_size[1])

        for zone in self.zones:
            zone.paintWithin(painter, rect)
        painter.restore()