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)
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
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
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()
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
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()