Exemplo n.º 1
0
    def paintEvent(self, event):
        """QToolBar.paintEvent reimplementation
        Draws buttons, dock icon and text
        """
        rect = self._spacer.rect()

        painter = QPainter(self)

        transform = QTransform()
        transform.translate(self._spacer.pos().x(), self._spacer.pos().y())
        painter.setTransform(transform)
        """ Not supported currently
        if  self._dock.features() & QDockWidget.DockWidgetVerticalTitleBar :
            transform = QTransform()

            rect.setSize(QSize(rect.height(), rect.width()))
            transform.rotate(-90)
            transform.translate(-rect.width(), 0)

            painter.setTransform(transform)
        """

        # icon / title
        optionB = QStyleOptionButton()
        optionB.initFrom(self._dock)
        optionB.rect = rect
        optionB.text = self._dock.windowTitle()
        optionB.iconSize = self.iconSize()
        optionB.icon = self._dock.windowIcon()

        self.style().drawControl(QStyle.CE_PushButtonLabel, optionB, painter,
                                 self._dock)
Exemplo n.º 2
0
def scene_bbox(item, view=None):
    """
    Returns the bounding box of an item in scene space.

    If view is given and the object has the
    QGraphicsItem::ItemIgnoresTransformations flag set, additional steps are
    taken to compute the exact bounding box of the item.
    """
    bbox = item.boundingRect()
    if not (item.flags() & QGraphicsItem.ItemIgnoresTransformations):
        # Normal item, simply map its bounding box to scene space
        bbox = item.mapRectToScene(bbox)
    else:
        # Item with the ItemIgnoresTransformations flag, need to compute its
        # bounding box with deviceTransform()
        if view is not None:
            vp_trans = view.viewportTransform()
        else:
            vp_trans = QTransform()
        item_to_vp_trans = item.deviceTransform(vp_trans)
        # Map bbox to viewport space
        bbox = item_to_vp_trans.mapRect(bbox)
        # Map bbox back to scene space
        bbox = vp_trans.inverted()[0].mapRect(bbox)
    return bbox                    
Exemplo n.º 3
0
class Curve1(Curve):
    def __init__(self):
        Curve.__init__(self)
        self.setPen( QColor( 150, 150, 200 ), 2 )
        self.setStyle( Qwt.QwtPlotCurve.Lines )

        curveFitter = Qwt.QwtSplineCurveFitter()
        curveFitter.setSplineSize( 150 )
        self.setCurveFitter( curveFitter )
        self.setCurveAttribute( Qwt.QwtPlotCurve.Fitted, True )

        symbol = Qwt.QwtSymbol( Qwt.QwtSymbol.XCross )
        symbol.setPen( Qt.yellow )
        symbol.setSize( 7 )

        self.setSymbol( symbol )
        # somewhere to the left
        self.transform = QTransform()
        self.transform.scale( 1.5, 1.0 );
        self.transform.translate( 1.5, 3.0 );

        self.setTransformation( self.transform )

    def points(self, phase ):
        pnts = QPolygonF()
        numSamples = 15;
        for i in range(numSamples):
            v = 6.28 * i / ( numSamples - 1 )
            pnts += QPointF( math.sin( v - phase ), v )
        return pnts

    def updateSamples( self, phase ):
        self.setSamples( self.d_transform.map( self.points( phase )))
def get_nametag(char_id, x, y, color, vertical = False):
  
  w = IMG_W
  h = IMG_H
  
  nametag = get_char_name(char_id, common.editor_config.data01_dir)
  if nametag == None:
    nametag = "NAMETAG MISSING"
  
  if vertical:
    nametag_img = QImage(h, w, QImage.Format_ARGB32_Premultiplied)
    
    new_x   = h - y
    new_y   = x
    x       = new_x
    y       = new_y
  else:
    nametag_img = QImage(w, h, QImage.Format_ARGB32_Premultiplied)
  
  format = TextFormat(x = x, y = y, w = 25, h = 25, align = TEXT_ALIGN.left, orient = TEXT_ORIENT.hor, clt = 0)
  nametag_img = print_text(nametag_img, nametag, None, format = format, mangle = False)
  
  if vertical:
    matrix = QTransform()
    matrix.rotate(-90)
    nametag_img = nametag_img.transformed(matrix)
  
  nametag_img = replace_all_colors(nametag_img, color)
  
  return nametag_img
Exemplo n.º 5
0
    def paintEvent(self, event ):
        """QToolBar.paintEvent reimplementation
        Draws buttons, dock icon and text
        """
        rect = self._spacer.rect()

        painter = QPainter( self )

        transform = QTransform()
        transform.translate(self._spacer.pos().x(), self._spacer.pos().y())
        painter.setTransform( transform )

        """ Not supported currently
        if  self._dock.features() & QDockWidget.DockWidgetVerticalTitleBar :
            transform = QTransform()

            rect.setSize( QSize( rect.height(), rect.width() ) )
            transform.rotate( -90 )
            transform.translate( -rect.width(), 0 )

            painter.setTransform( transform )
        """

        # icon / title
        optionB = QStyleOptionButton()
        optionB.initFrom( self._dock )
        optionB.rect = rect
        optionB.text = self._dock.windowTitle()
        optionB.iconSize = self.iconSize()
        optionB.icon = self._dock.windowIcon()

        self.style().drawControl( QStyle.CE_PushButtonLabel, optionB, painter, self._dock )
Exemplo n.º 6
0
 def updateZoom(self, zx, zy):
     trans = QTransform()
     trans.scale(1.0 / zx, 1.0 / zy)
     # self.setTransform( trans )
     self.VP.setTransform(trans)
     self.preBP.setTransform(trans)
     self.postBP.setTransform(trans)
     self.updateTPPos()
Exemplo n.º 7
0
	def updateTransfrom( self ):
		if self.updating : return
		self.updating = True
		trans = QTransform()
		trans.translate( self.valueToX( -self.scrollX ) + self.offsetX, self.valueToY( -self.scrollY ) )
		self.setTransform( trans )
		self.update()
		self.updating = False
Exemplo n.º 8
0
	def setZoom( self, x, y ):
		self.zx = x
		self.zy = y
		trans = QTransform()
		trans.scale( self.zx, self.zy )
		self.setTransform( trans )
		for vert in self.vertItems:
			vert.updateZoom( self.zx, self.zy )
Exemplo n.º 9
0
	def updateZoom( self, zx, zy ):
		trans = QTransform()
		trans.scale( 1.0/zx, 1.0/zy )
		# self.setTransform( trans )
		self.VP.setTransform( trans )
		self.preBP.setTransform( trans )
		self.postBP.setTransform( trans )
		self.updateTPPos()
Exemplo n.º 10
0
 def setZoom(self, x, y):
     self.zx = x
     self.zy = y
     trans = QTransform()
     trans.scale(self.zx, self.zy)
     self.setTransform(trans)
     for vert in self.vertItems:
         vert.updateZoom(self.zx, self.zy)
Exemplo n.º 11
0
    def testData2Scene(self):
        t = Tiling((0, 0))
        trans = QTransform()
        t.data2scene = trans
        self.assertEquals(trans, t.data2scene)

        # try using transformation that is not invertible
        trans = QTransform(1, 1, 1, 1, 1, 1)
        with self.assertRaises(AssertionError):
            t.data2scene = trans
Exemplo n.º 12
0
 def updateTransfrom(self):
     if self.updating: return
     self.updating = True
     trans = QTransform()
     trans.translate(
         self.valueToX(-self.scrollX) + self.offsetX,
         self.valueToY(-self.scrollY))
     self.setTransform(trans)
     self.update()
     self.updating = False
Exemplo n.º 13
0
    def setLeftHanded(self, bValue):
        """Configure the neck as left or right-handed.

        bValue -- bool, if True, mirror the neck

        Return None.
        """
        if bValue:
            self.setTransform(QTransform().scale(-1, 1))
        else:
            self.setTransform(QTransform().scale(1, 1))
Exemplo n.º 14
0
    def _refreshTile( self, stack_id, tile_no, prefetch=False ):
        if not self.axesSwapped:
            transform = QTransform(0,1,0,1,0,0,1,1,1)
        else:
            transform = QTransform().rotate(90).scale(1,-1)
        transform *= self.tiling.data2scene

        try:
            if self._cache.tileDirty( stack_id, tile_no ):
                if not prefetch:
                    self._cache.setTileDirty(stack_id, tile_no, False)
                    img = self._renderTile( stack_id, tile_no )
                    self._cache.setTile(stack_id, tile_no, img,
                                        self._sims.viewVisible(),
                                        self._sims.viewOccluded())

                # refresh dirty layer tiles
                for ims in self._sims.viewImageSources():
                    if self._cache.layerDirty(stack_id, ims, tile_no) \
                       and not self._sims.isOccluded(ims) \
                       and self._sims.isVisible(ims):

                        rect = self.tiling.imageRects[tile_no]
                        dataRect = self.tiling.scene2data.mapRect(rect)
                        ims_req = ims.request(dataRect, stack_id[1])
                        if ims.direct and not prefetch:
                            # The ImageSource 'ims' is fast (it has the
                            # direct flag set to true) so we process
                            # the request synchronously here. This
                            # improves the responsiveness for layers
                            # that have the data readily available.
                            start = time.time()
                            img = ims_req.wait()

                            img = img.transformed(transform)
                            stop = time.time()

                            ims._layer.timePerTile(stop-start,
                                                   self.tiling.imageRects[tile_no])

                            self._cache.updateTileIfNecessary(
                                stack_id, ims, tile_no, time.time(), img )
                            img = self._renderTile( stack_id, tile_no )
                            self._cache.setTile(stack_id, tile_no,
                                                img, self._sims.viewVisible(),
                                                self._sims.viewOccluded() )
                        else:
                            pool = get_render_pool()
                            pool.submit(prefetch, time.time(),
                                    self, ims, transform, tile_no,
                                    stack_id, ims_req, self._cache)
        except KeyError:
            pass
Exemplo n.º 15
0
 def transform(self):
     try:
         return self.__dict__['transform'] if self.scale else QTransform()
     except KeyError:
         transform = QTransform()
         image = self.client.image
         if image is not None and not image.isNull():
             scale = min(self.width()/image.width(), self.height()/image.height())
             transform.translate((self.width() - image.width()*scale)/2, (self.height() - image.height()*scale)/2)
             transform.scale(scale, scale)
             transform = self.__dict__.setdefault('transform', transform)
         return transform
Exemplo n.º 16
0
 def __init__(self, undo_stack, delete_act, sel_actions, *args):
     """
     Constructor
     """
     params = parameters.instance
     QGraphicsScene.__init__(self, *args)
     self.delete_act = delete_act
     self.undo_stack = undo_stack
     self.data_manager = None
     self._mode = None
     self.link = None
     self.image_path = None
     self.image_name = None
     self.background_image = None
     self.template = TemplateItem()
     self.template.setPos(QPointF(0, 0))
     self.template.setVisible(params.show_template)
     self.show_template = False
     self.points = {}
     self.cells = {}
     self._real_scene_rect = QRectF()
     params.pointParameterChange.connect(self.updatePoints)
     params.cellParameterChange.connect(self.updateCells)
     params.searchParameterChange.connect(self.updateTemplate)
     self.had_selection = None
     self.selectionChanged.connect(self.updateSelectionActions)
     self.current_data = None
     self.back_matrix = QTransform()
     self.invert_back_matrix = QTransform()
     self.clear()
     popup = QMenu("Scene menu")
     validate_cell_act = popup.addAction("Validate cell", self.validateCell)
     validate_cell_act.setVisible(False)
     self._validate_cell_act = validate_cell_act
     lifespan_act = popup.addAction("Change cell lifespan", self.changeLifespan)
     lifespan_act.setVisible(False)
     self.lifespan_act = lifespan_act
     make_starshape_act = popup.addAction("Make cell star shaped", self.makeCellStarshaped)
     make_starshape_act.setVisible(False)
     self.make_starshape_act = make_starshape_act
     sel = popup.addMenu("Selection")
     for act in sel_actions:
         if act == "-":
             sel.addSeparator()
         else:
             sel.addAction(act)
     popup.addAction(delete_act)
     self._popup = popup
     self._sel_rect = None
     self._sel_first_pt = None
     self._current_cell = None
     self._first_point = None
     self.mode = TrackingScene.Pan
Exemplo n.º 17
0
    def __updateText(self):
        self.prepareGeometryChange()

        if self.__sourceName or self.__sinkName:
            if self.__sourceName != self.__sinkName:
                text = u"{0} \u2192 {1}".format(self.__sourceName,
                                                self.__sinkName)
            else:
                # If the names are the same show only one.
                # Is this right? If the sink has two input channels of the
                # same type having the name on the link help elucidate
                # the scheme.
                text = self.__sourceName
        else:
            text = ""

        self.linkTextItem.setPlainText(text)

        path = self.curveItem.path()
        if not path.isEmpty():
            center = path.pointAtPercent(0.5)
            angle = path.angleAtPercent(0.5)

            brect = self.linkTextItem.boundingRect()

            transform = QTransform()
            transform.translate(center.x(), center.y())
            transform.rotate(-angle)

            # Center and move above the curve path.
            transform.translate(-brect.width() / 2, -brect.height())

            self.linkTextItem.setTransform(transform)
Exemplo n.º 18
0
def ellipse_path(center, a, b, rotation=0):
    if not isinstance(center, QPointF):
        center = QPointF(*center)

    brect = QRectF(-a, -b, 2 * a, 2 * b)

    path = QPainterPath()
    path.addEllipse(brect)

    if rotation != 0:
        transform = QTransform().rotate(rotation)
        path = transform.map(path)

    path.translate(center)
    return path
Exemplo n.º 19
0
def ellipse_path(center, a, b, rotation=0):
    if not isinstance(center, QPointF):
        center = QPointF(*center)

    brect = QRectF(-a, -b, 2 * a, 2 * b)

    path = QPainterPath()
    path.addEllipse(brect)

    if rotation != 0:
        transform = QTransform().rotate(rotation)
        path = transform.map(path)

    path.translate(center)
    return path
Exemplo n.º 20
0
    def trigger(self, ui):
        """
        Trigger this animation
        """
        glyph = [
            glyph for glyph in ui.scene.items()
            if hasattr(glyph, 'entity') and glyph.entity == self.mover
        ][0]

        if self.direction in (2, 3, 4):
            self.flipped = True
            self.offset = 32

        if self.direction in (6, 7, 8):
            self.flipped = False
            self.offset = 0

        if self.flipped:
            glyph.flipped = True
            glyph.setTransform(QTransform.fromScale(-1, 1))
        else:
            glyph.flipped = False
            glyph.setTransform(QTransform.fromScale(1, 1))

        if glyph.entity.artificial_intelligence:
            adapter = MapGlyphAdapter(ui, glyph)
        else:
            adapter = MapGlyphAdapter(ui, glyph, True)

        animation = QParallelAnimationGroup()

        move_y = QPropertyAnimation(adapter, 'y_location')
        move_y.setDuration(100)
        move_y.setStartValue(self.start[1] * 32)
        move_y.setEndValue(self.destination[1] * 32)

        move_x = QPropertyAnimation(adapter, 'x_location')
        move_x.setDuration(100)
        move_x.setStartValue(self.start[0] * 32 + self.offset)
        move_x.setEndValue(self.destination[0] * 32 + self.offset)

        animation.addAnimation(move_y)
        animation.addAnimation(move_x)

        ui.animations.append(animation)
        animation.finished.connect(ui.remove_finished_animation)

        animation.start()
Exemplo n.º 21
0
    def __init__(self, *args, **kwargs):
        QDockWidget.__init__(self, *args, **kwargs)

        self.__expandedWidget = None
        self.__collapsedWidget = None
        self.__expanded = True

        self.__trueMinimumWidth = -1

        self.setFeatures(QDockWidget.DockWidgetClosable | \
                         QDockWidget.DockWidgetMovable)
        self.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)

        self.featuresChanged.connect(self.__onFeaturesChanged)
        self.dockLocationChanged.connect(self.__onDockLocationChanged)

        # Use the toolbar horizontal extension button icon as the default
        # for the expand/collapse button
        pm = self.style().standardPixmap(
            QStyle.SP_ToolBarHorizontalExtensionButton
        )

        # Rotate the icon
        transform = QTransform()
        transform.rotate(180)

        pm_rev = pm.transformed(transform)

        self.__iconRight = QIcon(pm)
        self.__iconLeft = QIcon(pm_rev)

        close = self.findChild(QAbstractButton,
                               name="qt_dockwidget_closebutton")

        close.installEventFilter(self)
        self.__closeButton = close

        self.__stack = AnimatedStackedWidget()

        self.__stack.setSizePolicy(QSizePolicy.Fixed,
                                   QSizePolicy.Expanding)

        self.__stack.transitionStarted.connect(self.__onTransitionStarted)
        self.__stack.transitionFinished.connect(self.__onTransitionFinished)

        QDockWidget.setWidget(self, self.__stack)

        self.__closeButton.setIcon(self.__iconLeft)
Exemplo n.º 22
0
 def setImageMove(self, scale, pos, angle):
     log_debug("New scale = %s" % (scale,))
     self.scale = scale
     self.min_scale = self.data_manager.minScale()
     self.img_scale = (scale[0]/self.min_scale, scale[1]/self.min_scale)
     back_matrix = QTransform()
     back_matrix.scale(*self.img_scale)
     back_matrix.translate(pos.x(), pos.y())
     back_matrix.rotate(angle)
     self.back_matrix = back_matrix
     rect = back_matrix.mapRect(QRectF(self.background_image.rect()))
     inv, ok = back_matrix.inverted()
     if not ok:
         raise ValueError("The movement is not invertible !?!")
     self.invert_back_matrix = inv
     self.real_scene_rect = rect
Exemplo n.º 23
0
 def add_line(self, cord_1, cord_2, color):
     key = tuple(sorted([tuple(cord_1), tuple(cord_2)]))
     x = min(cord_1[0], cord_2[0])
     y = min(cord_1[1], cord_2[1])
     if key in self.lines:
         print("ERROR: Line between {} and {} already added.".format(
             cord_1, cord_2))
     else:
         line = QLabel(self)
         if color == "white":
             pixmap = QPixmap(get_asset_path("hor_line_white"))
         else:
             pixmap = QPixmap(get_asset_path("hor_line_black"))
         c1 = (30 + cord_1[0] * 30, 30 + cord_1[1] * 30)
         c2 = (30 + cord_2[0] * 30, 30 + cord_2[1] * 30)
         length = ((c1[0] - c2[0])**2 + (c1[1] - c2[1])**2)**(1 / 2)
         angle = math.degrees(
             math.atan2(key[1][1] - key[0][1], key[1][0] - key[0][0]))
         pixmap = pixmap.scaled(length, 5)
         pixmap = pixmap.transformed(QTransform().rotate(angle))
         line.setPixmap(pixmap)
         line.move(30 + x * 30, 30 + y * 30)
         line.show()
         line.lower()
         self.lines[key] = line
Exemplo n.º 24
0
 def paint(self, painter, option, widget):
     params = parameters.instance
     tr = painter.worldMatrix()
     saved = False
     scale = self.scale
     ms = min(scale)
     if tr.m11() < 1 / scale[0] or tr.m12() < 1 / scale[1]:
         painter.save()
         saved = True
         dx = tr.dx()
         dy = tr.dy()
         painter.setWorldTransform(
             QTransform(1 / scale[0], 0, 0, 1 / scale[1], dx, dy))
     if self.hover:
         pen_color = params.old_point_matching_color
     else:
         pen_color = params.old_point_color
     half_size = params.old_point_size / 2.
     pen = QPen(pen_color)
     pen.setWidth(params.old_point_thickness * ms)
     painter.setPen(pen)
     painter.drawLine(0, -half_size * scale[1], 0, half_size * scale[1])
     painter.drawLine(-half_size * scale[0], 0, half_size * scale[0], 0)
     if saved:
         painter.restore()
Exemplo n.º 25
0
 def data(self, index, role):
     if not index.isValid():
         return QVariant()
     if index.row() >= len(self.list):
         return QVariant()
     if role == Qt.DecorationRole:
         card = self.list[index.row()]
         pixmap = card.pixmap()
         pixmap = pixmap.scaledToHeight(self.preferredCardHeight)
         if card.tapped:
             transform = QTransform()
             transform.rotate(90)
             pixmap = pixmap.transformed(transform)
         return pixmap
         
     return QVariant()
Exemplo n.º 26
0
    def __init__(self,
                 sliceShape,
                 data2scene=QTransform(),
                 blockSize=256,
                 overlap=0,
                 overlap_draw=1e-3,
                 name="Unnamed Tiling"):
        self.blockSize = blockSize
        self.overlap = overlap
        self._patchAccessor = PatchAccessor(sliceShape[0],
                                            sliceShape[1],
                                            blockSize=self.blockSize)
        self._overlap_draw = overlap_draw
        self._overlap = overlap

        numPatches = self._patchAccessor.patchCount

        self.imageRectFs = [None] * numPatches
        self.dataRectFs = [None] * numPatches
        self.tileRectFs = [None] * numPatches
        self.imageRects = [None] * numPatches
        self.dataRects = [None] * numPatches
        self.tileRects = [None] * numPatches
        self.sliceShape = sliceShape
        self.name = name
        self.data2scene = data2scene
Exemplo n.º 27
0
def rotateCenter(item, angle):
    """rotates a QGraphicsItem around its center"""
    center = item.boundingRect().center()
    centerX, centerY = center.x() * item.scale(), center.y() * item.scale()
    item.setTransform(QTransform().translate(
        centerX, centerY).rotate(angle).translate(-centerX, -centerY))
    return item
Exemplo n.º 28
0
 def __init__(self,parent, font_name, font_size, font_height, w,h, colorscheme):
     super().__init__(parent)
     self.setFocusPolicy(Qt.WheelFocus)
     self.setAutoFillBackground(False)
     self.setAttribute(Qt.WA_OpaquePaintEvent, True)
     self.setCursor(Qt.IBeamCursor)
     font = QFont(font_name)
     font.setPixelSize(font_size)
     self.setFont(font)
     self._screen = []
     self._text = []
     self._transform= QTransform()
     self._cursor_col = 0
     self._cursor_row = 0
     self._dirty = False
     self._kbdfunc= None
     self._w=w
     self._h=h
     self._alt_sequence= False
     self._alt_seq_length=0
     self._alt_seq_value=0
     self._cursortype= CURSOR_OFF
     self._color_scheme=self.color_schemes[self.color_scheme_names[colorscheme]]
     self._cursor_color=self._color_scheme[2]
     self._cursor_char= 0x20
     self._cursor_attr=-1
     self._cursor_update=True
     self._blink= True
     self._blink_counter=0
     self._cursor_rect = QRect(0, 0, self._char_width, self._char_height)
     self._cursor_polygon=QPolygon([QPoint(0,0+(self._char_height/2)), QPoint(0+(self._char_width*0.8),0+self._char_height), QPoint(0+(self._char_width*0.8),0+(self._char_height*0.67)), QPoint(0+self._char_width,0+(self._char_height*0.67)), QPoint(0+self._char_width,0+(self._char_height*0.33)), QPoint(0+(self._char_width*0.8),0+(self._char_height*0.33)), QPoint(0+(self._char_width*0.8),0), QPoint(0,0+(self._char_height/2))])
Exemplo n.º 29
0
    def __init__(self, sliceShape, data2scene=QTransform(),
                 blockSize=512, overlap=0, overlap_draw=1e-3,
                 name="Unnamed Tiling"):
        """
        Args:
            sliceShape -- (width, height)
            data2scene -- QTransform from data to image coordinates (default:
                          identity transform)
            blockSize  -- base tile size: blockSize x blockSize (default 256)
            overlap    -- overlap between tiles positive number prevents rendering
                          artifacts between tiles for certain zoom levels (default 1)
        """
        self.blockSize = blockSize
        self.overlap = overlap
        self._patchAccessor = PatchAccessor(sliceShape[0],
                                            sliceShape[1],
                                            blockSize=self.blockSize)
        self._overlap_draw = overlap_draw
        self._overlap = overlap

        numPatches = self._patchAccessor.patchCount

        self.imageRectFs = [None]*numPatches
        self.dataRectFs  = [None]*numPatches
        self.tileRectFs  = [None]*numPatches
        self.imageRects  = [None]*numPatches
        self.dataRects   = [None]*numPatches
        self.tileRects   = [None]*numPatches
        self.sliceShape  = sliceShape
        self.name = name
        self.data2scene = data2scene
Exemplo n.º 30
0
    def updateStandardIcons(self):
        size = QSize(16, 16)
        rect = QRect(QPoint(), self.iconSize())

        transform = QTransform()
        transform.rotate(90)

        pixmap = self.style().standardIcon(QStyle.SP_TitleBarNormalButton, None, self.widgetForAction(self.aFloat)).pixmap(size)
        rect.moveCenter(pixmap.rect().center())
        pixmap = pixmap.copy(rect)
        self.aFloat.setIcon(QIcon(pixmap))

        pixmap = self.style().standardIcon(QStyle.SP_TitleBarCloseButton, None, self.widgetForAction(self.aClose)).pixmap(size)
        rect.moveCenter(pixmap.rect().center())
        pixmap = pixmap.copy(rect)
        self.aClose.setIcon(QIcon(pixmap))
Exemplo n.º 31
0
 def _resetIcon(self):
     if self._swapped:
         pixmap = self._pixmap_swapped
     else:
         pixmap = self._orig_pixmap
     transform = QTransform().rotate(self._rotation * 90)
     self.setPixmap(pixmap.transformed(transform))
Exemplo n.º 32
0
    def trigger(self, ui):
        """
        Trigger this animation
        """
        glyph = [glyph for glyph in ui.scene.items()
                 if hasattr(glyph, 'entity') and glyph.entity == self.mover][0]

        if self.direction in (2, 3, 4):
            self.flipped = True
            self.offset = 32

        if self.direction in (6, 7, 8):
            self.flipped = False
            self.offset = 0

        if self.flipped:
            glyph.flipped = True
            glyph.setTransform(QTransform.fromScale(-1, 1))
        else:
            glyph.flipped = False
            glyph.setTransform(QTransform.fromScale(1, 1))

        if glyph.entity.artificial_intelligence:
            adapter = MapGlyphAdapter(ui, glyph)
        else:
            adapter = MapGlyphAdapter(ui, glyph, True)

        animation = QParallelAnimationGroup()

        move_y = QPropertyAnimation(adapter, 'y_location')
        move_y.setDuration(100)
        move_y.setStartValue(self.start[1] * 32)
        move_y.setEndValue(self.destination[1] * 32)

        move_x = QPropertyAnimation(adapter, 'x_location')
        move_x.setDuration(100)
        move_x.setStartValue(self.start[0] * 32 + self.offset)
        move_x.setEndValue(self.destination[0] * 32 + self.offset)

        animation.addAnimation(move_y)
        animation.addAnimation(move_x)

        ui.animations.append(animation)
        animation.finished.connect(ui.remove_finished_animation)

        animation.start()
Exemplo n.º 33
0
 def updatePixmap(self):
     path = _PATH + os.sep + "assets" + os.sep + self._base_image
     self.__pixmap = QPixmap(path)
     self.__pixmap = self.__pixmap.scaled(self.__pixmap.width() * _SCALE,
                                          self.__pixmap.height() * _SCALE)
     self.__pixmap = self.__pixmap.transformed(QTransform().rotate(
         self.angle))
     self._base_label.setPixmap(self.__pixmap)
Exemplo n.º 34
0
    def resizeEvent(self, event):
        w = self.view.width() - 10
        h = self.view.height() - 10

        transform = QTransform.fromScale(w, h)

        self.view.setTransform(transform)
        QWidget.resizeEvent(self, event)
Exemplo n.º 35
0
 def updatePixmap(self):
     path = get_asset_path(self._base_image)
     self.__pixmap = QPixmap(path)
     self.__pixmap = self.__pixmap.scaled(self._size[0], self._size[1])
     self.__pixmap = self.__pixmap.transformed(QTransform().rotate(
         self.angle))
     self._base_label.setPixmap(self.__pixmap)
     self._base_label.show()
Exemplo n.º 36
0
def _define_symbols():
    """
    Add symbol ? to ScatterPlotItemSymbols,
    reflect the triangle to point upwards
    """
    symbols = pyqtgraph.graphicsItems.ScatterPlotItem.Symbols
    path = QPainterPath()
    path.addEllipse(QRectF(-0.35, -0.35, 0.7, 0.7))
    path.moveTo(-0.5, 0.5)
    path.lineTo(0.5, -0.5)
    path.moveTo(-0.5, -0.5)
    path.lineTo(0.5, 0.5)
    symbols["?"] = path

    tr = QTransform()
    tr.rotate(180)
    symbols['t'] = tr.map(symbols['t'])
Exemplo n.º 37
0
 def flip_vt(self):
     for obj in self.childItems():
         rect = obj.boundingRect()
         x = rect.width() / 2
         y = rect.height() / 2
         obj.setTransform(QTransform().translate(x, y).scale(1,
                                                             -1).translate(
                                                                 -x, -y))
Exemplo n.º 38
0
def _define_symbols():
    """
    Add symbol ? to ScatterPlotItemSymbols,
    reflect the triangle to point upwards
    """
    symbols = pyqtgraph.graphicsItems.ScatterPlotItem.Symbols
    path = QPainterPath()
    path.addEllipse(QRectF(-0.35, -0.35, 0.7, 0.7))
    path.moveTo(-0.5, 0.5)
    path.lineTo(0.5, -0.5)
    path.moveTo(-0.5, -0.5)
    path.lineTo(0.5, 0.5)
    symbols["?"] = path

    tr = QTransform()
    tr.rotate(180)
    symbols['t'] = tr.map(symbols['t'])
Exemplo n.º 39
0
    def _fetch_tile_layer(self, timestamp, ims, transform, tile_nr, stack_id, ims_req, cache):
        """
        Fetch a single tile from a layer (ImageSource).
        
        Parameters
        ----------
        timestamp
            The timestamp at which ims_req was created
        ims
            The layer (image source) we're fetching from
        transform
            The transform to apply to the fetched data, before storing it in the cache
        tile_nr
            The ID of the fetched tile
        stack_id
            The stack ID of the tile we're fetching (e.g. which T-slice and Z-slice this tile belongs to) 
        ims_req
            A request object (e.g. GrayscaleImageRequest) with a wait() method that produces an item of 
            the appropriate type for the layer (i.e. either a QImage or a QGraphicsItem)
        cache
            The value of self._cache at the time the ims_req was created.
            (The cache can be replaced occasionally. See TileProvider._onSizeChanged().)
        """
        try:
            try:
                with cache:
                    layerTimestamp = cache.layerTimestamp(stack_id, ims, tile_nr)
            except KeyError:
                # May not be a timestamp yet (especially when prefetching)
                layerTimestamp = 0

            tile_rect = QRectF( self.tiling.imageRects[tile_nr] )

            if timestamp > layerTimestamp:
                img = ims_req.wait()
                if isinstance(img, QImage):
                    img = img.transformed(transform)
                elif isinstance(img, QGraphicsItem):
                    # FIXME: It *seems* like applying the same transform to QImages and QGraphicsItems
                    #        makes sense here, but for some strange reason it isn't right.
                    #        For QGraphicsItems, it seems obvious that this is the correct transform.
                    #        I do not understand the formula that produces 'transform', which is used for QImage tiles.
                    img.setTransform(QTransform.fromTranslate(tile_rect.left(), tile_rect.top()), combine=True)
                    img.setTransform(self.tiling.data2scene, combine=True)
                else:
                    assert False, "Unexpected image type: {}".format( type(img) )

                with cache:
                    try:
                        cache.updateTileIfNecessary(stack_id, ims, tile_nr, timestamp, img)
                    except KeyError:
                        pass

                if stack_id == self._current_stack_id \
                        and cache is self._cache:
                    self.sceneRectChanged.emit( tile_rect )
        except BaseException:
            sys.excepthook( *sys.exc_info() )
Exemplo n.º 40
0
    def _fetch_tile_layer(self, timestamp, ims, transform, tile_nr, stack_id, ims_req, cache):
        """
        Fetch a single tile from a layer (ImageSource).
        
        Parameters
        ----------
        timestamp
            The timestamp at which ims_req was created
        ims
            The layer (image source) we're fetching from
        transform
            The transform to apply to the fetched data, before storing it in the cache
        tile_nr
            The ID of the fetched tile
        stack_id
            The stack ID of the tile we're fetching (e.g. which T-slice and Z-slice this tile belongs to) 
        ims_req
            A request object (e.g. GrayscaleImageRequest) with a wait() method that produces an item of 
            the appropriate type for the layer (i.e. either a QImage or a QGraphicsItem)
        cache
            The value of self._cache at the time the ims_req was created.
            (The cache can be replaced occasionally. See TileProvider._onSizeChanged().)
        """
        try:
            try:
                with cache:
                    layerTimestamp = cache.layerTimestamp(stack_id, ims, tile_nr)
            except KeyError:
                # May not be a timestamp yet (especially when prefetching)
                layerTimestamp = 0

            tile_rect = QRectF( self.tiling.imageRects[tile_nr] )

            if timestamp > layerTimestamp:
                img = ims_req.wait()
                if isinstance(img, QImage):
                    img = img.transformed(transform)
                elif isinstance(img, QGraphicsItem):
                    # FIXME: It *seems* like applying the same transform to QImages and QGraphicsItems
                    #        makes sense here, but for some strange reason it isn't right.
                    #        For QGraphicsItems, it seems obvious that this is the correct transform.
                    #        I do not understand the formula that produces 'transform', which is used for QImage tiles.
                    img.setTransform(QTransform.fromTranslate(tile_rect.left(), tile_rect.top()), combine=True)
                    img.setTransform(self.tiling.data2scene, combine=True)
                else:
                    assert False, "Unexpected image type: {}".format( type(img) )

                with cache:
                    try:
                        cache.updateTileIfNecessary(stack_id, ims, tile_nr, timestamp, img)
                    except KeyError:
                        pass

                if stack_id == self._current_stack_id \
                        and cache is self._cache:
                    self.sceneRectChanged.emit( tile_rect )
        except BaseException:
            sys.excepthook( *sys.exc_info() )
Exemplo n.º 41
0
    def __updateText(self):
        self.prepareGeometryChange()

        if self.__sourceName or self.__sinkName:
            if self.__sourceName != self.__sinkName:
                text = u"{0} \u2192 {1}".format(self.__sourceName,
                                                self.__sinkName)
            else:
                # If the names are the same show only one.
                # Is this right? If the sink has two input channels of the
                # same type having the name on the link help elucidate
                # the scheme.
                text = self.__sourceName
        else:
            text = ""

        self.linkTextItem.setPlainText(text)

        path = self.curveItem.path()
        if not path.isEmpty():
            center = path.pointAtPercent(0.5)
            angle = path.angleAtPercent(0.5)

            brect = self.linkTextItem.boundingRect()

            transform = QTransform()
            transform.translate(center.x(), center.y())
            transform.rotate(-angle)

            # Center and move above the curve path.
            transform.translate(-brect.width() / 2, -brect.height())

            self.linkTextItem.setTransform(transform)
Exemplo n.º 42
0
    def _newAxes(self):
        """Given self._rotation and self._swapped, calculates and sets
        the appropriate data2scene transformation.

        """
        # TODO: this function works, but it is not elegant. There must
        # be a simpler way to calculate the appropriate tranformation.

        w, h = self.dataShape
        assert self._rotation in range(0, 4)

        # unlike self._rotation, the local variable 'rotation'
        # indicates how many times to rotate clockwise after swapping
        # axes.

        # t1 : do axis swap
        t1 = QTransform()
        if self._swapped:
            t1 = QTransform(0, 1, 0, 1, 0, 0, 0, 0, 1)
            h, w = w, h

        # t2 : do rotation
        t2 = QTransform()
        t2.rotate(self._rotation * 90)

        # t3: shift to re-center
        rot2trans = {0: (0, 0), 1: (h, 0), 2: (w, h), 3: (0, w)}

        trans = rot2trans[self._rotation]
        t3 = QTransform.fromTranslate(*trans)

        self.data2scene = t1 * t2 * t3
        if self._tileProvider:
            self._tileProvider.axesSwapped = self._swapped
        self.axesChanged.emit(self._rotation, self._swapped)
Exemplo n.º 43
0
 def mappedPolygon( self, polygon, path = None, percent = 0.5 ):
     """
     Maps the inputed polygon to the inputed path \
     used when drawing items along the path.  If no \
     specific path is supplied, then this object's own \
     path will be used.  It will rotate and move the \
     polygon according to the inputed percentage.
     
     :param      polygon     <QPolygonF>
     :param      path        <QPainterPath>
     :param      percent     <float>
     
     :return     <QPolygonF> mapped_poly
     """
     translatePerc   = percent
     anglePerc       = percent
     
     # we don't want to allow the angle percentage greater than 0.85
     # or less than 0.05 or we won't get a good rotation angle
     if ( 0.95 <= anglePerc ):
         anglePerc = 0.98
     elif ( anglePerc <= 0.05 ):
         anglePerc = 0.05
     
     if ( not path ):
         path = self.path()
     if ( not (path and path.length()) ):
         return QPolygonF()
     
     # transform the polygon to the path
     point   = path.pointAtPercent(translatePerc)
     angle   = path.angleAtPercent(anglePerc)
     
     # rotate about the 0 axis
     transform   = QTransform().rotate(-angle)
     polygon     = transform.map(polygon)
     
     # move to the translation point
     transform   = QTransform().translate(point.x(), point.y())
     
     # create the rotated polygon
     mapped_poly = transform.map(polygon)
     self._polygons.append(mapped_poly)
     
     return mapped_poly
Exemplo n.º 44
0
 def saveSlice(self, filename):
     """Legacy code."""
     #print "Saving in ", filename, "slice #", self.sliceNumber, "axis", self._axis
     result_image = QImage(self.scene().image.size(), self.scene().image.format())
     p = QPainter(result_image)
     for patchNr in range(self.patchAccessor.patchCount):
         bounds = self.patchAccessor.getPatchBounds(patchNr)
         if self.openglWidget is None:
             p.drawImage(0, 0, self.scene().image)
         else:
             p.drawImage(bounds[0], bounds[2], self.imagePatches[patchNr])
     p.end()
     #horrible way to transpose an image. but it works.
     transform = QTransform()
     transform.rotate(90)
     result_image = result_image.mirrored()
     result_image = result_image.transformed(transform)
     result_image.save(QString(filename))
Exemplo n.º 45
0
 def rotate(self, rotation):
     "rotates item over its own center"
     for obj in self.childItems():
         if hasattr(obj, "rotable") and obj.rotable:
             rect = obj.boundingRect()
             x = rect.width() / 2
             y = rect.height() / 2
             obj.setTransform(QTransform().translate(
                 x, y).rotate(rotation).translate(-x, -y))
Exemplo n.º 46
0
    def _updateLayout(self):
        rect = self.geometry()
        n = len(self._items)
        if not n:
            return

        regions = venn_diagram(n, shape=self.shapeType)

        # The y axis in Qt points downward
        transform = QTransform().scale(1, -1)
        regions = list(map(transform.map, regions))

        union_brect = reduce(QRectF.united,
                             (path.boundingRect() for path in regions))

        scalex = rect.width() / union_brect.width()
        scaley = rect.height() / union_brect.height()
        scale = min(scalex, scaley)

        transform = QTransform().scale(scale, scale)

        regions = [transform.map(path) for path in regions]

        center = rect.width() / 2, rect.height() / 2
        for item, path in zip(self.items(), regions):
            item.setPath(path)
            item.setPos(*center)

        intersections = venn_intersections(regions)
        assert len(intersections) == 2 ** n
        assert len(self.vennareas()) == 2 ** n

        anchors = [(0, 0)] + subset_anchors(self._items)

        anchor_transform = QTransform().scale(rect.width(), -rect.height())
        for i, area in enumerate(self.vennareas()):
            area.setPath(intersections[setkey(i, n)])
            area.setPos(*center)
            x, y = anchors[i]
            anchor = anchor_transform.map(QPointF(x, y))
            area.setTextAnchor(anchor)
            area.setZValue(30)

        self._updateTextAnchors()
Exemplo n.º 47
0
    def inicializarUI(self):
        self.setWindowTitle("BlueKing::Reversa")
        self.setGeometry(0,0,320,240)
        self.setAutoFillBackground(True)

        #QGraphicsView/Scene
        self.view = QGraphicsView()
        self.view.setStyleSheet("border: 0px;margin: 0px;background-color: #000000;")

        self.scene = QGraphicsScene(0,0,320,240)
        self.view.setScene(self.scene)

        self.baseLayout = QVBoxLayout()
        self.baseLayout.setContentsMargins(0,0,0,0)
        self.baseLayout.addWidget(self.view)

        #Decoracion
        car_logo = QPixmap("imagenes/car_logo.png")
        car_logo_item = QGraphicsPixmapItem(car_logo)
        car_logo_item.setPos(5,5)
        self.scene.addItem(car_logo_item)

        self.distlabel = QLabel("-")
        self.distlabel.setGeometry(20, 20, 280, 200)
        self.distlabel.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignVCenter)
        self.distlabel.setStyleSheet("color: #00FFFF;font-size: 150px;background-color: transparent;")
        self.scene.addWidget(self.distlabel)

        self.measureLabel=QLabel("metros")
        self.measureLabel.setGeometry(10,190,300,30)
        self.measureLabel.setAlignment(QtCore.Qt.AlignRight |QtCore.Qt.AlignVCenter)
        self.measureLabel.setStyleSheet("color: #FFFF00;font-size: 30px; font-weight: bold; font-style: italic;background-color: transparent;")
        self.scene.addWidget(self.measureLabel)

        self.setLayout(self.baseLayout)

        transformacion = QTransform()
        transformacion.scale(1.0,-1.0)

        #self.view.setTransform(transformacion)

        self.show()
Exemplo n.º 48
0
    def updateStandardIcons(self):
        size = QSize(16, 16)
        rect = QRect(QPoint(), self.iconSize())

        transform = QTransform()
        transform.rotate(90)

        pixmap = self.style().standardIcon(
            QStyle.SP_TitleBarNormalButton, None,
            self.widgetForAction(self.aFloat)).pixmap(size)
        rect.moveCenter(pixmap.rect().center())
        pixmap = pixmap.copy(rect)
        self.aFloat.setIcon(QIcon(pixmap))

        pixmap = self.style().standardIcon(QStyle.SP_TitleBarCloseButton, None,
                                           self.widgetForAction(
                                               self.aClose)).pixmap(size)
        rect.moveCenter(pixmap.rect().center())
        pixmap = pixmap.copy(rect)
        self.aClose.setIcon(QIcon(pixmap))
Exemplo n.º 49
0
        def paint(self, painter, option, widget=None):
            t = painter.transform()

            rect = t.mapRect(self.rect())

            painter.save()
            painter.setTransform(QTransform())
            pwidth = self.pen().widthF()
            painter.setPen(self.pen())
            painter.drawRect(rect.adjusted(pwidth, -pwidth, -pwidth, pwidth))
            painter.restore()
Exemplo n.º 50
0
 def wheelEvent( self, event ):
     """ Mouse wheel event """
     if QApplication.keyboardModifiers() == Qt.ControlModifier:
         factor = 1.41 ** ( -event.delta() / 240.0 )
         self.__currentFactor *= factor
         self.setTransform( QTransform.fromScale( self.__currentFactor,
                                                  self.__currentFactor ) )
         Settings().flowScale = self.__currentFactor
     else:
         QGraphicsView.wheelEvent( self, event )
     return
Exemplo n.º 51
0
    def run(self):
        """Main method of a thread to receive the MJEPG-stream.
        For every frame received, the SIGNAL newFrame() is thrown.
        Never call this directly. Always use start().
        
        """
        self.updateControls = self.hasUpdateControls()
        self.inputAvt = self.isInputAvt()
        self.running = True
        while (self.running):
            frame = self.httpGet("?action=snapshot")
            if (frame):
                self.raw = frame
                frame = QImage.fromData(frame)
                oldWidth = frame.size().width()
                oldHeight = frame.size().height()
                if self.rotation is not None:
                    #print "rot"
                    #print "before", frame.size().width(),frame.size().height()
                    transf = QTransform()
                    transf.rotate(self.rotation)
                    frame = frame.transformed(transf)
                    #print "after", frame.size().width(),frame.size().height()
                    newWidth = frame.size().width()
                    newHeight = frame.size().height()

                    addedHeight = oldWidth * math.sin(
                        math.radians(self.rotation))
                    addedWidth = oldHeight * math.sin(
                        math.radians(self.rotation))

                    h = oldHeight / math.sin(math.radians(self.rotation))
                    #l1 =
                    #print "addedwidth,Height",addedWidth,addedHeight
                if (self.transformMode is not None
                        and not (self.width == frame.width()
                                 and self.height == frame.height())):
                    frame = frame.scaled(self.width, self.height,
                                         self.aspectRatio, self.transformMode)
                self.frame = frame
                self.emit(SIGNAL("newFrame()"))
Exemplo n.º 52
0
    def _newAxes(self):
        """Given self._rotation and self._swapped, calculates and sets
        the appropriate data2scene transformation.

        """
        # TODO: this function works, but it is not elegant. There must
        # be a simpler way to calculate the appropriate transformation.

        w, h = self.dataShape
        assert self._rotation in range(0, 4)

        # unlike self._rotation, the local variable 'rotation'
        # indicates how many times to rotate clockwise after swapping
        # axes.

        # t1 : do axis swap
        t1 = QTransform()
        if self._swapped:
            t1 = QTransform(0, 1, 0,
                            1, 0, 0,
                            0, 0, 1)
            h, w = w, h

        # t2 : do rotation
        t2 = QTransform()
        t2.rotate(self._rotation * 90)

        # t3: shift to re-center
        rot2trans = {0 : (0, 0),
                     1 : (h, 0),
                     2 : (w, h),
                     3 : (0, w)}

        trans = rot2trans[self._rotation]
        t3 = QTransform.fromTranslate(*trans)

        self.data2scene = t1 * t2 * t3
        if self._tileProvider:
            self._tileProvider.axesSwapped = self._swapped
        self.axesChanged.emit(self._rotation, self._swapped)
Exemplo n.º 53
0
    def overlay_for(pt1, pt2, frequency):
        # Construct the line-geometry, we'll use this to construct the ellipsoid
        line = QLineF(pt1, pt2)

        # Determine the radius for the ellipsoid
        radius = fresnel_radius(line.length(), frequency)

        # Draw the ellipsoid
        zone = QPainterPath()
        zone.addEllipse(QPointF(0., 0.), line.length() / 2, radius)

        # Rotate the ellipsoid - same angle as the line
        transform = QTransform()
        transform.rotate(-line.angle())
        zone = transform.map(zone)

        # Center the zone over the line
        lc = QRectF(pt1, pt2).center()
        zc = zone.boundingRect().center()
        zone.translate(lc.x() - zc.x(), lc.y() - zc.y())

        return line, zone
Exemplo n.º 54
0
    def __init__( self, parent=None ):
        QGraphicsScene.__init__( self, parent=parent )

        # tiled rendering of patches
        self._tiling         = None
        self._brushingLayer  = None
        # indicates the dirtyness of each tile
        self._dirtyIndicator = None

        self._tileProvider = None
        self._stackedImageSources = None
        self._showTileOutlines = False
    
        self.data2scene = QTransform(0,1,1,0,0,0) 
        self.scene2data = self.data2scene.transposed()
        
        self._slicingPositionSettled = True

        self._redrawIndicator = False
Exemplo n.º 55
0
    def _setup_scene(self):
        self._clear_plot()
        self.matrix_item = DistanceMapItem(self._sorted_matrix)
        # Scale the y axis to compensate for pg.ViewBox's y axis invert
        self.matrix_item.setTransform(QTransform.fromScale(1, -1), )
        self.viewbox.addItem(self.matrix_item)
        # Set fixed view box range.
        h, w = self._sorted_matrix.shape
        self.viewbox.setRange(QRectF(0, -h, w, h), padding=0)

        self.matrix_item.selectionChanged.connect(self._invalidate_selection)

        if self.sorting == OWDistanceMap.NoOrdering:
            tree = None
        elif self.sorting == OWDistanceMap.Clustering:
            tree = self._cluster_tree()
        elif self.sorting == OWDistanceMap.OrderedClustering:
            tree = self._ordered_cluster_tree()

        self._set_displayed_dendrogram(tree)

        self._update_color()
Exemplo n.º 56
0
class ImageScene2D(QGraphicsScene):
    """
    The 2D scene description of a tiled image generated by evaluating
    an overlay stack, together with a 2D cursor.
    """

    @property
    def stackedImageSources(self):
        return self._stackedImageSources
    
    @stackedImageSources.setter
    def stackedImageSources(self, s):
        self._stackedImageSources = s
        s.sizeChanged.connect(self._onSizeChanged)

    @property
    def showTileOutlines(self):
        return self._showTileOutlines
    @showTileOutlines.setter
    def showTileOutlines(self, show):
        self._showTileOutlines = show
        self.invalidate()

    @property
    def sceneShape(self):
        """
        The shape of the scene in QGraphicsView's coordinate system.
        """
        return (self.sceneRect().width(), self.sceneRect().height())
    @sceneShape.setter
    def sceneShape(self, sceneShape):
        """
        Set the size of the scene in QGraphicsView's coordinate system.
        sceneShape -- (widthX, widthY),
        where the origin of the coordinate system is in the upper left corner
        of the screen and 'x' points right and 'y' points down
        """   
        assert len(sceneShape) == 2
        self.setSceneRect(0,0, *sceneShape)
        
        #The scene shape is in Qt's QGraphicsScene coordinate system,
        #that is the origin is in the top left of the screen, and the
        #'x' axis points to the right and the 'y' axis down.
        
        #The coordinate system of the data handles things differently.
        #The x axis points down and the y axis points to the right.

        r = self.scene2data.mapRect(QRect(0,0,sceneShape[0], sceneShape[1]))
        sliceShape = (r.width(), r.height())
        
        if self._dirtyIndicator:
            self.removeItem(self._dirtyIndicator)
        del self._dirtyIndicator
        self._dirtyIndicator = None

        self._tiling = Tiling(sliceShape, self.data2scene)

        self._dirtyIndicator = DirtyIndicator(self._tiling)
        self.addItem(self._dirtyIndicator)

        self._onSizeChanged()
        if self._tileProvider:
            self._tileProvider.notifyThreadsToStop() # prevent ref cycle

        self._tileProvider = TileProvider(self._tiling, self._stackedImageSources)
        self._tileProvider.changed.connect(self.invalidateViewports)

    def invalidateViewports( self, rectF ):
        '''Call invalidate on the intersection of all observing viewport-rects and rectF.'''
        rectF = rectF if rectF.isValid() else self.sceneRect()
        for view in self.views():
            QGraphicsScene.invalidate( self, rectF.intersected(view.viewportRect()) )        

    def __init__( self, parent=None ):
        QGraphicsScene.__init__( self, parent=parent )

        # tiled rendering of patches
        self._tiling         = None
        self._brushingLayer  = None
        # indicates the dirtyness of each tile
        self._dirtyIndicator = None

        self._tileProvider = None
        self._stackedImageSources = None
        self._showTileOutlines = False
    
        self.data2scene = QTransform(0,1,1,0,0,0) 
        self.scene2data = self.data2scene.transposed()
        
        self._slicingPositionSettled = True

        self._redrawIndicator = False
    
    def drawLine(self, fromPoint, toPoint, pen):
        tileId = self._tiling.containsF(toPoint)
        if tileId is None:
            return
       
        p = self._brushingLayer[tileId] 
        p.lock()
        painter = QPainter(p.image)
        painter.setPen(pen)
        
        tL = self._tiling.imageRectFs[tileId].topLeft()
        painter.drawLine(fromPoint-tL, toPoint-tL)
        painter.end()
        p.dataVer += 1
        p.unlock()
        self.scheduleRedraw(self._tiling.imageRectFs[tileId])

    def _onSizeChanged(self):
        self._brushingLayer  = TiledImageLayer(self._tiling)
                
    def drawForeground(self, painter, rect):
        if self._tiling is None:
            return

        tile_nos = self._tiling.intersectedF(rect)

        for tileId in tile_nos:
            p = self._brushingLayer[tileId]
            if p.dataVer == p.imgVer:
                continue

            p.paint(painter) #access to the underlying image patch is serialized

            ## draw tile outlines
            if self._showTileOutlines:
                painter.drawRect(self._tiling.imageRects[tileId])
    
    def indicateSlicingPositionSettled(self, settled):
        self._dirtyIndicator.setVisible(settled)
        self._slicingPositionSettled = settled
   
    def drawBackground(self, painter, rectF):
        if self._tileProvider is None:
            return

        tiles = self._tileProvider.getTiles(rectF)
        for tile in tiles:
            # prevent flickering
            if not tile.progress < 1.0:
                painter.drawImage(tile.rectF, tile.qimg)
            self._dirtyIndicator.setTileProgress(tile.id, tile.progress) 

    def joinRendering( self ):
        return self._tileProvider.join()
 def setZoom(self, scale):
     """Scale to selected factor
     """
     transform = QTransform()
     transform.scale(scale, scale)
     self.graphicsView.setTransform(transform)