Exemple #1
0
 def paintEvent(self, ev):
     """Called when paint is needed, finds out which page to magnify."""
     layout = self.parent().surface().pageLayout()
     pos = self.geometry().center() - self.parent().surface().pos()
     page = layout.pageAt(pos)
     if not page:
         return
     pagePos = pos - page.pos()
     
     newPage = Page(page, self._scale)
     if not newPage.same_page(self._page):
         if self._page:
             self._page.magnifier = None
         self._page = newPage
         self._page.magnifier = self
     
     relx = pagePos.x() / float(page.width())
     rely = pagePos.y() / float(page.height())
     
     image = cache.image(self._page)
     img_rect = QRect(self.rect())
     if not image:
         cache.generate(self._page)
         image = cache.image(self._page, False)
         if image:
             img_rect.setWidth(self.width() * image.width() / self._page.width())
             img_rect.setHeight(self.height() * image.height() / self._page.height())
     if image:
         img_rect.moveCenter(QPoint(relx * image.width(), rely * image.height()))
         p = QPainter(self)
         p.drawImage(self.rect(), image, img_rect)
         p.setRenderHint(QPainter.Antialiasing, True)
         p.setPen(QPen(QColor(192, 192, 192, 128), 6))
         p.drawEllipse(self.rect().adjusted(2, 2, -2, -2))
 def paintEvent(self, ev):
     """Called when paint is needed, finds out which page to magnify."""
     layout = self.parent().pageLayout()
     pos = self.geometry().center()
     page = layout.pageAt(pos)
     if not page:
         return
     pagePos = pos - page.pos()
     
     newPage = Page(page, self._scale)
     if newPage != self._page:
         if self._page:
             self._page.magnifier = None
         self._page = newPage
         self._page.magnifier = self
     
     relx = pagePos.x() / float(page.width())
     rely = pagePos.y() / float(page.height())
     
     image = cache.image(self._page)
     img_rect = QRect(self.rect())
     if not image:
         cache.generate(self._page)
         image = cache.image(self._page, False)
         if image:
             img_rect.setWidth(self.width() * image.width() / self._page.width())
             img_rect.setHeight(self.height() * image.height() / self._page.height())
     if image:
         img_rect.moveCenter(QPoint(relx * image.width(), rely * image.height()))
         QPainter(self).drawImage(self.rect(), image, img_rect)
Exemple #3
0
    def paintEvent(self, ev):
        """Called when paint is needed, finds out which page to magnify."""
        layout = self.parent().pageLayout()
        pos = self.geometry().center()
        page = layout.pageAt(pos)
        if not page:
            return
        pagePos = pos - page.pos()

        newPage = Page(page, self._scale)
        if newPage != self._page:
            if self._page:
                self._page.magnifier = None
            self._page = newPage
            self._page.magnifier = self

        relx = pagePos.x() / float(page.width())
        rely = pagePos.y() / float(page.height())

        image = cache.image(self._page)
        img_rect = QRect(self.rect())
        if not image:
            cache.generate(self._page)
            image = cache.image(self._page, False)
            if image:
                img_rect.setWidth(self.width() * image.width() /
                                  self._page.width())
                img_rect.setHeight(self.height() * image.height() /
                                   self._page.height())
        if image:
            img_rect.moveCenter(
                QPoint(relx * image.width(), rely * image.height()))
            QPainter(self).drawImage(self.rect(), image, img_rect)
Exemple #4
0
 def calculateLogicalRect(self, physicalRect):
     gridX = self.parent().width() / 40
     gridY = self.parent().height() / 30
     logicalRect = QRect()
     logicalRect.setTop(round(physicalRect.top() / gridY))
     logicalRect.setLeft(round(physicalRect.left() / gridX))
     logicalRect.setWidth(round(physicalRect.width() / gridX))
     logicalRect.setHeight(round(physicalRect.height() / gridY))
     return logicalRect
Exemple #5
0
 def paint(self, painter, option, index):
     painter.setFont(option.font)
     painter.setBrush(QBrush(Qt.black))
     if option.state & QStyle.State_Selected:
         painter.setPen(QPen(Qt.white))
     rect = QRect(option.rect)
     rect.setLeft(rect.left() + 4)
     rect.setTop(rect.top() + 4)
     rect.setWidth(rect.width() - 8)
     rect.setHeight(rect.height() - 8)
     painter.drawText(rect, Qt.Horizontal | Qt.TextWordWrap,
                      forceString(index.data()))
Exemple #6
0
 def paintEvent(self, event):
     QWidget.paintEvent(self, event)
     p = QPainter(self)
     p.setFont(self.font)
     if self.pixmap:
         p.drawPixmap(QPoint(0,0), self.pixmap)
     r = QRect(self.rect().topLeft() + QPoint(0, 180), QSize(self.rect().size().width(), p.fontMetrics().height()))
     p.fillRect(r, self.palette().midlight())
     if self.progress:
         pr = QRect(r)
         pr.setWidth( (r.width() * self.progress) / 100 )
         p.fillRect(pr, self.palette().dark())
     p.setBrush(Qt.NoBrush)
     p.setPen(QPen(self.palette().text(), 1))
     p.drawText(QRectF(r), self.title, QTextOption(Qt.AlignHCenter))
     p.setPen(QPen(self.palette().shadow(), 1))
     p.drawRect(self.rect().adjusted(0,0,-1,-1))
Exemple #7
0
    def paintEvent(self, event):
        def _drawitem(pixmap, text, itempostion):
            painter.drawPixmap(itempostion, pixmap)
            textrect = QRectF(pixmap.width() + 40,
                              itempostion.y(),
                              framerect.width() - pixmap.width() - 40,
                              pixmap.height())
            painter.drawText(textrect, text, QTextOption(Qt.AlignVCenter))

        if not self.pixmap:
            return

        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing)
        painter.drawPixmap(event.rect(), self.pixmap)

        rect = event.rect()
        framerect = QRect(rect)
        newwidth = (rect.width() / 100) * 40
        framerect.setWidth(newwidth)
        painter.setBrush(self.legendareabrush)
        painter.setPen(self.legendareapen)
        painter.drawRect(framerect)
        self.framerect = framerect

        painter.setPen(Qt.black)

        currenty = 40
        position = rect.topLeft() + QPoint(30, currenty)
        for layer, items in self.items.iteritems():
            if len(items) == 1:
                itempostion = QPoint(position)
                itempostion.setY(currenty)
                _drawitem(items[0][1], layer, itempostion)
                currenty += 40
            else:
                for text, icon in items:
                    if not text:
                        continue
                    itempostion = QPoint(position)
                    itempostion.setY(currenty)
                    _drawitem(icon, text, itempostion)
                    currenty += 40

            position.setY(currenty + 40)
Exemple #8
0
 def renderSplit(self, painter, rowStats, splitsRect):
     painter.setFont(self.ds.splitFont())
     splitValues = [self.ds.splitValues(rowStats.index, i) for i in range(rowStats.splitCount)]
     colWidths = [0, 0, 0]
     for sv in splitValues:
         colWidths[0] = max(colWidths[0], self.stats.splitFM.width(sv.account))
         colWidths[1] = max(colWidths[1], self.stats.splitFM.width(sv.memo))
         colWidths[2] = max(colWidths[2], self.stats.splitFM.width(sv.amount))
     top = splitsRect.top()
     for sv in splitValues:
         rect = QRect(splitsRect.left(), top, colWidths[0], self.stats.splitHeight)
         painter.drawText(rect, Qt.AlignLeft, sv.account)
         rect.setLeft(rect.right() + SPLIT_XPADDING)
         rect.setWidth(colWidths[1])
         painter.drawText(rect, Qt.AlignLeft, sv.memo)
         rect.setLeft(rect.right() + SPLIT_XPADDING)
         rect.setWidth(colWidths[2])
         painter.drawText(rect, Qt.AlignRight, sv.amount)
         top += self.stats.splitHeight
 def paintEvent(self,event):
     painter = QPainter(self)
     btnRect = self.geometry()
     
     color = QColor(Qt.black)
     if self.hovered:
         color = self.color
     if self.pressed:
         color = self.color.darker(120)
         
     painter.setBrush(QBrush(color)) 
     painter_path = QPainterPath()
     painter_path.addRoundedRect(1, 1, btnRect.width() - 2, btnRect.height() - 2, 0, 0)
     
     if self.hovered:
         painter.setPen(QPen(color,2))
         outline = QPainterPath()
         outline.addRoundedRect(0, 0, btnRect.width(), btnRect.height(), 0, 0)
         painter.setOpacity(1)
         painter.drawPath(outline)
         painter.setClipPath(painter_path)
         painter.drawRoundedRect(1, 1, btnRect.width() - 2, btnRect.height() - 2, 0, 0)
     
     iconWidth = self.iconSize().width()*3/5
     iconHeight = self.iconSize().height()*3/5
     iconX = (btnRect.width()-iconWidth)/2
     iconY = (btnRect.height()-iconHeight)/2
     
     if self.pressed:
         iconX += 2
         iconY += 2
     
     iconPos = QRect()
     iconPos.setX(iconX)
     iconPos.setY(iconY)
     iconPos.setWidth(iconWidth)
     iconPos.setHeight(iconHeight)
     
     painter.drawPixmap(iconPos, QPixmap(self.icon().pixmap(self.iconSize())))
Exemple #10
0
	def __init__(self, parent = None):
		QDialog.__init__(self, parent)

		# get primiry monitor resolution
		qdw = QDesktopWidget()

		mainScreenSize = qdw.availableGeometry(qdw.primaryScreen())
		# get center of the monitor
		center = mainScreenSize.center()
		# calculate width, height and x,y positions of the window
		r_width = round(mainScreenSize.width()/2)
		r_height = round(mainScreenSize.height()/2)
		r_x = round(center.x()-r_width/2)
		r_y = round(center.y()-r_height/2)
		
		# set default geometry of the window
		rect = QRect()
		rect.setX(r_x)
		rect.setY(r_y)
		rect.setWidth(r_width)
		rect.setHeight(r_height)
		self.setGeometry(rect)
 def calIconTextPos(self,btnSize,iconSize):
     if self.text().isNull():
         iconWidth = iconSize.width()*3/5
         iconHeight = iconSize.height()*3/5
     else:
         iconWidth = iconSize.width()
         iconHeight = iconSize.height() - 50
         
     iconX = (btnSize.width()-iconWidth)/2
     iconY = (btnSize.height()-iconHeight)/2
     
     iconPos = QRect()
     iconPos.setX(iconX)
     iconPos.setY(iconY)
     iconPos.setWidth(iconWidth)
     iconPos.setHeight(iconHeight)
     
     textPos = QRect()
     if not self.text().isNull():
         textPos.setX(iconX)
         textPos.setY(btnSize.height()- 50)
         textPos.setWidth(iconWidth)
         textPos.setHeight(50)
     return (iconPos,textPos)
Exemple #12
0
    def calIconTextPos(self, btnSize, iconSize):
        if self.text().isNull():
            iconWidth = iconSize.width() * 3 / 5
            iconHeight = iconSize.height() * 3 / 5
        else:
            iconWidth = iconSize.width()
            iconHeight = iconSize.height() - 50

        iconX = (btnSize.width() - iconWidth) / 2
        iconY = (btnSize.height() - iconHeight) / 2

        iconPos = QRect()
        iconPos.setX(iconX)
        iconPos.setY(iconY)
        iconPos.setWidth(iconWidth)
        iconPos.setHeight(iconHeight)

        textPos = QRect()
        if not self.text().isNull():
            textPos.setX(iconX)
            textPos.setY(btnSize.height() - 50)
            textPos.setWidth(iconWidth)
            textPos.setHeight(50)
        return (iconPos, textPos)
Exemple #13
0
    def paint(self, painter, option, index):
        self.initStyleOption(option, index)
        if hasattr(option, "checkState"):
            if option.checkState == Qt.Unchecked:
                option.checkState = Qt.PartiallyChecked
            elif option.checkState == Qt.PartiallyChecked:
                option.checkState = Qt.Unchecked
            elif option.checkState == Qt.Checked:
                option.font = QFont(option.font)
                option.font.setStrikeOut(True)
        # ref: qt4-x11-4.6.2/src/gui/styles/qcommonstyle.cpp
        painter.save()
        painter.setClipRect(option.rect)
        # QApplication.style().drawControl(
        #     QStyle.CE_ItemViewItem, option, painter,
        #     getattr(option, "widget", None))
        style = QApplication.style()
        widget = getattr(option, "widget", None)
        # log.debug("widget: %r style: %r" % (widget, style.metaObject().className()))
        style.drawPrimitive(
            QStyle.PE_PanelItemViewItem, option, painter, widget)

        if option.checkState == Qt.Checked:
            painter.setOpacity(0.3)
        text_rect = style.subElementRect(
            QStyle.SE_ItemViewItemText, option, widget)
        item_text = option.fontMetrics.elidedText(
            option.text, option.textElideMode, text_rect.width())
        painter.setFont(option.font)
        style.drawItemText(painter, text_rect, option.displayAlignment,
                           option.palette, True, item_text, QPalette.Text)

        check_rect = style.subElementRect(
            QStyle.SE_ItemViewItemCheckIndicator, option, widget)
        if option.checkState == Qt.PartiallyChecked:
            brush = option.palette.brush(QPalette.Base)
            painter.fillRect(check_rect, brush)
            bullet_rect = QRect(check_rect)
            if bullet_rect.width() > BULLET_SIZE:
                bullet_rect.setLeft(
                    bullet_rect.left() +
                    (bullet_rect.width() - BULLET_SIZE) / 2)
                bullet_rect.setWidth(BULLET_SIZE)
            if bullet_rect.height() > BULLET_SIZE:
                bullet_rect.setTop(
                    bullet_rect.top() +
                    (bullet_rect.height() - BULLET_SIZE) / 2)
                bullet_rect.setHeight(BULLET_SIZE)
            painter.setPen(QPen(option.palette.color(QPalette.Text)))
            painter.setBrush(option.palette.brush(QPalette.Text))
            painter.drawEllipse(bullet_rect)
        else:
            check_opt = QStyleOptionButton()
            check_opt.rect = check_rect
            check_opt.state = option.state & ~QStyle.State_HasFocus
            if option.checkState == Qt.Checked:
                check_opt.state |= QStyle.State_On
            else:
                check_opt.state |= QStyle.State_Off
            style.drawPrimitive(
                QStyle.PE_IndicatorItemViewItemCheck, check_opt, painter,
                widget)
        painter.restore()
Exemple #14
0
    def paintEvent(self, event):
        def itemlist(items):
            for layer, items in self.items.iteritems():
                if len(items) == 1:
                    yield layer, items[0][1]
                else:
                    for text, icon in items:
                        if not text:
                            continue
                        yield text, icon

        def _drawitem(pixmap, text, itempostion):
            painter.drawPixmap(itempostion, pixmap)
            textrect = QRectF(pixmap.width() + currentx + 10,
                              itempostion.y(),
                              event.rect().width() - pixmap.width() - OFFSET_X,
                              pixmap.height())
            painter.drawText(textrect, text, QTextOption(Qt.AlignVCenter))

        def calcitems():
            font = painter.font()
            metrices = QFontMetrics(font)
            maxwidth = 0
            maxheight = 0
            for item, _ in itemlist(self.items):
                maxwidth = max(metrices.boundingRect(item).width(), maxwidth)
                maxheight = max(metrices.boundingRect(item).height(), maxheight)
            return maxwidth, maxheight

        if not self.pixmap:
            return

        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing)
        painter.drawPixmap(event.rect(), self.pixmap)

        itemwidths, itemmaxheight = calcitems()
        OFFSET_X = 30
        OFFSET_Y = itemmaxheight + 10
        rect = event.rect()
        neededheight = (len(self.items) * OFFSET_Y)
        runs = 1
        if neededheight > rect.height():
            import math
            runs = math.ceil(neededheight / float(rect.height()))
            print runs

        framerect = QRect(rect)
        framewidth = (itemwidths + OFFSET_X + ICON_SIZE.width() + 100) * runs
        framerect.setWidth(framewidth)
        painter.setBrush(self.legendareabrush)
        painter.setPen(self.legendareapen)
        painter.drawRect(framerect)
        self.framerect = framerect

        painter.setPen(Qt.black)
        currenty = OFFSET_Y
        currentx = OFFSET_X
        position = rect.topLeft() + QPoint(OFFSET_X, currenty)
        for text, icon in itemlist(self.items):
            itempostion = QPoint(position)
            if currenty > rect.height():
                currentx = itemwidths + OFFSET_X + 100
                currenty = itemmaxheight + 10

            itempostion.setX(currentx)
            itempostion.setY(currenty)

            _drawitem(icon, text, itempostion)
            currenty += OFFSET_Y

        position.setY(currenty + OFFSET_Y)
Exemple #15
0
class PlottingThread(QThread):
    def __init__(self, parent):
        QThread.__init__(self)
        self.result = None
        self.parent = parent
        self._stopped = False
        self.mutex = QMutex()
        self.filePrefix = None
        self.fileFormat = None
        self.wallColoring = None
        self.cellColoring = None
        self.pointColoring = None
        self.extraDrawing = []
        self.pointSize = None
        self.pointLineColor = None
        self.pointLineThickness = None
        self.ellipsisDraw = None
        self.overSampling = None
        self.wallThickness = None
        self.bgColor = None
        self.loading = False
        self._crop = QRect(0, 0, 1, 1)
        self._pix = None
        self._end_image_plot = False
        self._loading_arguments = {}
        self.retryObject = None

    def end_step(self):
        return len(self.result) + 1

    def stop(self, value=True):
        self.mutex.lock()
        self._stopped = value
        self.mutex.unlock()

    def stopped(self):
        self.mutex.lock()
        val = self._stopped
        self.mutex.unlock()
        return val

    def nextImage(self):
        QCoreApplication.postEvent(self.parent, NextImageEvent())

    def abort(self, reason, **others):
        e = AbortPlottingEvent(reason)
        if others:
            e.others = others
        QCoreApplication.postEvent(self.parent, e)

    def finished(self):
        if self.loading:
            QCoreApplication.postEvent(self.parent, FinishLoadingEvent())
            self.loading = False
        else:
            QCoreApplication.postEvent(self.parent, FinishPlottingEvent())

    def image_ready(self):
        QCoreApplication.postEvent(self.parent, ImageReadyPlottingEvent())

    def update_nb_images(self, nb):
        QCoreApplication.postEvent(self.parent, UpdateNbImageEvent(nb))

    @property
    def crop_left(self):
        return self._crop.left()

    @crop_left.setter
    def crop_left(self, value):
        self._crop.moveLeft(int(value))

    @property
    def crop_top(self):
        return self._crop.top()

    @crop_top.setter
    def crop_top(self, value):
        self._crop.moveTop(int(value))

    @property
    def crop_width(self):
        return self._crop.width()

    @crop_width.setter
    def crop_width(self, value):
        self._crop.setWidth(int(value))

    @property
    def crop_height(self):
        return self._crop.height()

    @crop_height.setter
    def crop_height(self, value):
        self._crop.setHeight(int(value))

    def reset_crop(self):
        self._crop = QRect(QPoint(0, 0), self.img_size)

    @property
    def crop(self):
        return QRect(self._crop)

    @crop.deleter
    def crop(self):
        self.reset_crop()

    @property
    def end_image_plot(self):
        '''
        If true, plot the growth data on the end image rather than the start image of the growth calculation.
        '''
        return self._end_image_plot

    @end_image_plot.setter
    def end_image_plot(self, value):
        self._end_image_plot = bool(value)

    @property
    def pix(self):
        '''Thread-safe image storage.'''
        self.mutex.lock()
        pix = self._pix
        self.mutex.unlock()
        return pix

    @pix.setter
    def pix(self, value):
        self.mutex.lock()
        self._pix = value
        self.mutex.unlock()

    def render_valid(self):
        if self.result is None:
            log_debug("result is None")
            return False
        if self.parent is None:
            log_debug("parent is None")
            return False
        if self.ellipsisDraw is None:
            log_debug("ellipsisDraw is None")
            return False
        if self.cellColoring is None:
            log_debug("cellColoring is None")
            return False
        if self.wallColoring is None:
            log_debug("wallColoring is None")
            return False
        if self.pointColoring is None:
            log_debug("pointColoring is None")
            return False
        if self.pointSize is None:
            log_debug("pointSize is None")
            return False
        if self.pointLineThickness is None:
            log_debug("pointSize is None")
            return False
        if self.pointLineColor is None:
            log_debug("pointSize is None")
            return False
        if self.wallThickness is None:
            log_debug("wallThickness is None")
            return False
        if self.overSampling is None:
            log_debug("overSampling is None")
            return False
        if self.bgColor is None:
            log_debug("bgColor is None")
            return False
        return True

    def valid(self):
        if self.filePrefix is None:
            log_debug("filePrefix is None")
            return False
        if not self.filePrefix:
            log_debug("filePrefix is Empty")
            return False
        if self.fileFormat is None:
            log_debug("fileFormat is None")
            return False
        return self.render_valid()

    def drawImage(self, imageid):
        cache = image_cache.cache
        cellColoring = self.cellColoring
        wallColoring = self.wallColoring
        pointColoring = self.pointColoring
        ellipsisDraw = self.ellipsisDraw
        overSampling = self.overSampling
        extraDrawing = self.extraDrawing
        bgColor = self.bgColor.rgb()
        result = self.result
        if self.result_type == "Data":
            data = result
            img_name = result.images_name[imageid]
        else:
            data = result.data
            img_name = result.images[imageid]
        #scale = data.images_scale[img_name]
        min_scale = data.minScale()
        img = cache.image(data.image_path(img_name))
        img_data = data[img_name]
        size = self._crop.size()
        pix = QImage(size * overSampling, QImage.Format_ARGB32)
        pix.fill(bgColor)
        painter = QPainter()
        if not painter.begin(pix):
            self.abort("Cannot create painter on QImage")
            return None, None, None
        painter.setRenderHints(QPainter.SmoothPixmapTransform, True)
        painter.setRenderHints(QPainter.Antialiasing, True)
        if overSampling > 1:
            painter.scale(overSampling, overSampling)
        painter.translate(-self._crop.topLeft())
        painter.save()
        painter.translate(self.translate)
        log_debug("Translating: %gx%g" %
                  (self.translate.x(), self.translate.y()))
        painter.scale(1 / min_scale, 1 / min_scale)
        painter.save()
        matrix = img_data.matrix()
        painter.setWorldTransform(matrix, True)
        painter.drawImage(QPoint(0, 0), img)
        painter.restore()
        #pt_matrix = QTransform()
        #pt_matrix.scale(1/min_scale, 1/min_scale)
        #painter.setTransform(pt_matrix, True)
        cellColoring.startImage(painter, imageid)
        wallColoring.startImage(painter, imageid)
        for ed in extraDrawing:
            ed.startImage(painter, imageid)
        if self.result_type == "Growth":
            cells = result.cells[imageid]
            walls = result.walls[imageid]
        else:
            cells = img_data.cells
            walls = set()
            for cid in img_data.cells:
                pts = [pt for pt in data.cells[cid] if pt in img_data]
                if len(pts) > 1:
                    for i in range(len(pts)):
                        walls.add(data.wallId(pts[i - 1], pts[i]))
        # Now, draw the cells and the ellipsis
        for cid in cells:
            painter.setPen(Qt.NoPen)
            color = cellColoring(imageid, cid)
            painter.setBrush(color)
            pts = data.cellAtTime(cid, img_data.index)
            if pts:
                pts.append(pts[0])
                ppts = []
                for p1, p2 in zip(pts[:-1], pts[1:]):
                    ppts.append(img_data[p1])
                    ppts.extend(img_data.walls[p1, p2])
                ppts.append(ppts[0])
                poly = QPolygonF(ppts)
                painter.drawPolygon(poly)
        # And draw the walls
        wallThickness = self.wallThickness * min_scale
        for wid in walls:
            color = wallColoring(imageid, wid)
            if color.alpha() > 0:
                pen = QPen(color)
                pen.setWidthF(wallThickness)
                painter.setPen(pen)
                pts = [img_data[wid[0]]
                       ] + img_data.walls[wid[0], wid[1]] + [img_data[wid[1]]]
                #painter.drawLine(img_data[wid[0]], img_data[wid[1]])
                painter.drawPolyline(*pts)
        # Then, draw the points
        pointSize = self.pointSize * min_scale
        pointLineColor = self.pointLineColor
        pointLineThickness = self.pointLineThickness * min_scale
        log_debug("pointSize = %g" % pointSize)
        for pid in img_data:
            color = pointColoring(imageid, pid)
            if color.alpha() > 0:
                pen = QPen(pointLineColor)
                pen.setWidthF(pointLineThickness)
                brush = QBrush(color)
                painter.setPen(pen)
                painter.setBrush(brush)
                pos = img_data[pid]
                rect = QRectF(pos.x() - pointSize,
                              pos.y() - pointSize, 2 * pointSize,
                              2 * pointSize)
                painter.drawEllipse(rect)
        if ellipsisDraw.plot:
            for cid in cells:
                pts = data.cellAtTime(cid, img_data.index)
                if pts:
                    pts.append(pts[0])
                    ppts = []
                    for p1, p2 in zip(pts[:-1], pts[1:]):
                        ppts.append(img_data[p1])
                        ppts.extend(img_data.walls[p1, p2])
                    ppts.append(ppts[0])
                    #poly = QPolygonF(ppts)
                    #painter.drawPolygon(poly)
                    ellipsisDraw(painter, imageid, cid, ppts, min_scale)
        # At last, draw the extra data
        for ed in extraDrawing:
            ed(painter, imageid)
        tr = painter.worldTransform()
        painter.restore()
        pic_w = wallColoring.finalizeImage(painter, imageid, tr, self.crop)
        pic_c = cellColoring.finalizeImage(painter, imageid, tr, self.crop)
        for ed in extraDrawing:
            ed.finalizeImage(painter, imageid, tr, self.crop)
        painter.end()
        return pix, pic_w, pic_c

    def start(self):
        if self.isRunning():
            assert not self.rendering_all, "Cannot run twice the rendering of all images with the same object."
            return
        if parameters.instance.use_thread:
            log_debug("Starting rendering thread.")
            QThread.start(self)
            return False
        else:
            self.run()
            return True

    def render_all(self):
        self.rendering_all = True
        return self.start()

    def render_single(self, img_id, retry=False):
        if retry:
            while self.isRunning():
                self.wait(10000)
        elif self.isRunning():
            return
        self.rendering_all = False
        self.current_image = img_id
        return self.start()

    def load(self, filename):
        self.loading = True
        self.result = filename
        return self.start()

    def run(self):
        if self.loading:
            self.run_loader()
        elif self.rendering_all:
            self.run_full()
        else:
            self.run_single()

    def run_single(self):
        img = self.current_image
        self.cellColoring.init()
        self.wallColoring.init()
        self.pointColoring.init()
        log_debug("Rendering image %d" % img)
        self.pix, self.pic_w, self.pic_c = self.drawImage(img)
        if self.pic_w is not None:
            log_debug("Has wall image")
        if self.pic_c is not None:
            log_debug("Has cell image")
        if self.pix is not None:
            log_debug("Pix correctly rendered")
        log_debug("Rendered image %d  = %s" % (img, self.pix))
        self.image_ready()

    def reload(self):
        if self.retryObject is None:
            return
        self._loading_arguments.update(self.retryObject.method_args)
        self.load(self.retryObject.filename)

    def run_loader(self):
        filename = self.result
        try:
            self.retryObject = None
            # First, prepare the data by getting the images and computing how big they
            # should be
            f = open(filename)
            first_line = f.readline()
            f.close()
            if first_line.startswith("TRKR_VERSION"):
                result = Result(None)
                result.load(self.result, **self._loading_arguments)
                result_type = "Growth"
            else:
                result = TrackingData()
                result.load(self.result, **self._loading_arguments)
                result_type = "Data"
            self.result = result
            self.result_type = result_type
            if result_type == "Data":
                data = result
                images = data.images_name
                if data.cells:
                    self.has_cells = True
                    self.has_walls = True
                else:
                    self.has_cells = False
                    self.has_walls = False
                self.has_points = bool(data.cell_points)
            else:
                data = result.data
                images = result.images
                self.has_cells = False
                self.has_walls = False
                self.has_points = False
            self.images = images
            cache = image_cache.cache
            self.update_nb_images(len(result))
            bbox = QRectF()
            ms = data.minScale()
            for i in range(len(result)):
                img_name = images[i]
                img_data = data[img_name]
                img = cache.image(data.image_path(img_name))
                matrix = QTransform()
                matrix = img_data.matrix()
                sc = QTransform()
                sc.scale(1.0 / ms, 1.0 / ms)
                matrix *= sc
                r = QRectF(img.rect())
                rbox = matrix.map(QPolygonF(r)).boundingRect()
                bbox |= rbox
                log_debug(
                    "Image '%s':\n\tSize = %gx%g\n\tTransformed = %gx%g %+g %+g\n\tGlobal bbox = %gx%g %+g %+g\n"
                    % (img_name, r.width(), r.height(), rbox.width(),
                       rbox.height(), rbox.left(), rbox.top(), bbox.width(),
                       bbox.height(), bbox.left(), bbox.top()))
                log_debug("Matrix:\n%g\t%g\t%g\n%g\t%g\t%g\n" %
                          (matrix.m11(), matrix.m12(), matrix.dx(),
                           matrix.m21(), matrix.m22(), matrix.dy()))
                if result_type == "Growth":
                    if result.cells[i]:
                        self.has_cells = True
                    if result.walls[i]:
                        self.has_walls = True
                    self.has_points = bool(result.data.cell_points)
                self.nextImage()
            translate = bbox.topLeft()
            translate *= -1
            self.translate = translate
            size = bbox.size().toSize()
            self.img_size = size
            self._crop = QRect(QPoint(0, 0), size)
            self.finished()
            self._loading_arguments = {
            }  # All done, we don't need that anymore
        except RetryTrackingDataException as ex:
            ex.filename = filename
            self.retryObject = ex
            self.finished()
            return
        except Exception as ex:
            _, _, exceptionTraceback = sys.exc_info()
            self.abort(ex, traceback=exceptionTraceback)
            raise

    def run_full(self):
        if not self.valid():
            self.abort("Object was not correctly initialized")
            return
        self.stop(False)
        painter = None
        try:
            result = self.result
            self.update_nb_images(len(result))
            #            if self.result_type == "Data":
            #                data = result
            #                images = result.images_name
            #            else:
            #                data = result.data
            #                images = result.images
            #            cache = image_cache.cache
            cellColoring = self.cellColoring
            wallColoring = self.wallColoring
            pointColoring = self.pointColoring
            file_format = self.fileFormat
            file_pattern = "%s%%0%dd.%s" % (self.filePrefix,
                                            len(str(len(result))), file_format)
            wall_file_pattern = "%s%%0%dd_wall.%s" % (
                self.filePrefix, len(str(len(result))), file_format)
            cell_file_pattern = "%s%%0%dd_cell.%s" % (
                self.filePrefix, len(str(len(result))), file_format)
            cellColoring.init()
            wallColoring.init()
            pointColoring.init()
            self.nextImage()
            for i in range(len(result)):
                if self.stopped():
                    self.abort("User interruption")
                    return
                pix, pic_w, pic_c = self.drawImage(i)
                pix.save(file_pattern % (i + 1), file_format)
                if pic_w is not None:
                    self.saveExtra(pic_w, wall_file_pattern % (i + 1),
                                   file_format)
                if pic_c is not None:
                    self.saveExtra(pic_c, cell_file_pattern % (i + 1),
                                   file_format)
                self.nextImage()
            self.finished()
        except Exception as ex:
            if painter is not None:
                painter.end()
            _, _, exceptionTraceback = sys.exc_info()
            self.abort(ex, traceback=exceptionTraceback)
            raise

    def saveExtra(self, picture, file_name, file_format):
        rect = picture.boundingRect()
        pix = QImage(rect.size(), QImage.Format_ARGB32)
        pix.fill(QColor(0, 0, 0, 0).rgba())
        paint = QPainter()
        paint.begin(pix)
        paint.drawPicture(rect.topLeft() * -1, picture)
        paint.end()
        pix.save(file_name, file_format)
class PlottingThread(QThread):
    def __init__(self, parent):
        QThread.__init__(self)
        self.result = None
        self.parent = parent
        self._stopped = False
        self.mutex = QMutex()
        self.filePrefix = None
        self.fileFormat = None
        self.wallColoring = None
        self.cellColoring = None
        self.pointColoring = None
        self.extraDrawing = []
        self.pointSize = None
        self.pointLineColor = None
        self.pointLineThickness = None
        self.ellipsisDraw = None
        self.overSampling = None
        self.wallThickness = None
        self.bgColor = None
        self.loading = False
        self._crop = QRect(0,0,1,1)
        self._pix = None
        self._end_image_plot = False
        self._loading_arguments = {}
        self.retryObject = None

    def end_step(self):
        return len(self.result)+1

    def stop(self, value = True):
        self.mutex.lock()
        self._stopped = value
        self.mutex.unlock()

    def stopped(self):
        self.mutex.lock()
        val = self._stopped
        self.mutex.unlock()
        return val

    def nextImage(self):
        QCoreApplication.postEvent(self.parent, NextImageEvent())

    def abort(self, reason, **others):
        e = AbortPlottingEvent(reason)
        if others:
            e.others = others
        QCoreApplication.postEvent(self.parent, e)

    def finished(self):
        if self.loading:
            QCoreApplication.postEvent(self.parent, FinishLoadingEvent())
            self.loading = False
        else:
            QCoreApplication.postEvent(self.parent, FinishPlottingEvent())

    def image_ready(self):
        QCoreApplication.postEvent(self.parent, ImageReadyPlottingEvent())

    def update_nb_images(self, nb):
        QCoreApplication.postEvent(self.parent, UpdateNbImageEvent(nb))

    @property
    def crop_left(self):
        return self._crop.left()

    @crop_left.setter
    def crop_left(self, value):
        self._crop.moveLeft(int(value))

    @property
    def crop_top(self):
        return self._crop.top()

    @crop_top.setter
    def crop_top(self, value):
        self._crop.moveTop(int(value))

    @property
    def crop_width(self):
        return self._crop.width()

    @crop_width.setter
    def crop_width(self, value):
        self._crop.setWidth(int(value))

    @property
    def crop_height(self):
        return self._crop.height()

    @crop_height.setter
    def crop_height(self, value):
        self._crop.setHeight(int(value))

    def reset_crop(self):
        self._crop = QRect(QPoint(0,0), self.img_size)

    @property
    def crop(self):
        return QRect(self._crop)

    @crop.deleter
    def crop(self):
        self.reset_crop()

    @property
    def end_image_plot(self):
        '''
        If true, plot the growth data on the end image rather than the start image of the growth calculation.
        '''
        return self._end_image_plot

    @end_image_plot.setter
    def end_image_plot(self, value):
        self._end_image_plot = bool(value)

    @property
    def pix(self):
        '''Thread-safe image storage.'''
        self.mutex.lock()
        pix = self._pix
        self.mutex.unlock()
        return pix

    @pix.setter
    def pix(self, value):
        self.mutex.lock()
        self._pix = value
        self.mutex.unlock()

    def render_valid(self):
        if self.result is None:
            log_debug("result is None")
            return False
        if self.parent is None:
            log_debug("parent is None")
            return False
        if self.ellipsisDraw is None:
            log_debug("ellipsisDraw is None")
            return False
        if self.cellColoring is None:
            log_debug("cellColoring is None")
            return False
        if self.wallColoring is None:
            log_debug("wallColoring is None")
            return False
        if self.pointColoring is None:
            log_debug("pointColoring is None")
            return False
        if self.pointSize is None:
            log_debug("pointSize is None")
            return False
        if self.pointLineThickness is None:
            log_debug("pointSize is None")
            return False
        if self.pointLineColor is None:
            log_debug("pointSize is None")
            return False
        if self.wallThickness is None:
            log_debug("wallThickness is None")
            return False
        if self.overSampling is None:
            log_debug("overSampling is None")
            return False
        if self.bgColor is None:
            log_debug("bgColor is None")
            return False
        return True

    def valid(self):
        if self.filePrefix is None:
            log_debug("filePrefix is None")
            return False
        if not self.filePrefix:
            log_debug("filePrefix is Empty")
            return False
        if self.fileFormat is None:
            log_debug("fileFormat is None")
            return False
        return self.render_valid()

    def drawImage(self, imageid):
        cache = image_cache.cache
        cellColoring = self.cellColoring
        wallColoring = self.wallColoring
        pointColoring = self.pointColoring
        ellipsisDraw = self.ellipsisDraw
        overSampling = self.overSampling
        extraDrawing = self.extraDrawing
        bgColor = self.bgColor.rgb()
        result = self.result
        if self.result_type == "Data":
            data = result
            img_name = result.images_name[imageid]
        else:
            data = result.data
            img_name = result.images[imageid]
        #scale = data.images_scale[img_name]
        min_scale = data.minScale()
        img = cache.image(data.image_path(img_name))
        img_data = data[img_name]
        size = self._crop.size()
        pix = QImage(size*overSampling, QImage.Format_ARGB32)
        pix.fill(bgColor)
        painter = QPainter()
        if not painter.begin(pix):
            self.abort("Cannot create painter on QImage")
            return None, None, None
        painter.setRenderHints(QPainter.SmoothPixmapTransform, True)
        painter.setRenderHints(QPainter.Antialiasing, True)
        if overSampling > 1:
            painter.scale(overSampling, overSampling)
        painter.translate(-self._crop.topLeft())
        painter.save()
        painter.translate(self.translate)
        log_debug("Translating: %gx%g" % (self.translate.x(), self.translate.y()) )
        painter.scale(1/min_scale, 1/min_scale)
        painter.save()
        matrix = img_data.matrix()
        painter.setWorldTransform(matrix, True)
        painter.drawImage(QPoint(0,0), img)
        painter.restore()
        #pt_matrix = QTransform()
        #pt_matrix.scale(1/min_scale, 1/min_scale)
        #painter.setTransform(pt_matrix, True)
        cellColoring.startImage(painter, imageid)
        wallColoring.startImage(painter, imageid)
        for ed in extraDrawing:
            ed.startImage(painter, imageid)
        if self.result_type == "Growth":
            cells = result.cells[imageid]
            walls = result.walls[imageid]
        else:
            cells = img_data.cells
            walls = set()
            for cid in img_data.cells:
                pts = [ pt for pt in data.cells[cid] if pt in img_data ]
                if len(pts) > 1:
                    for i in range(len(pts)):
                        walls.add(data.wallId(pts[i-1], pts[i]))
        # Now, draw the cells and the ellipsis
        for cid in cells:
            painter.setPen(Qt.NoPen)
            color = cellColoring(imageid, cid)
            painter.setBrush(color)
            pts = data.cellAtTime(cid, img_data.index)
            if pts:
                pts.append(pts[0])
                ppts = []
                for p1,p2 in zip(pts[:-1], pts[1:]):
                    ppts.append(img_data[p1])
                    ppts.extend(img_data.walls[p1,p2])
                ppts.append(ppts[0])
                poly = QPolygonF(ppts)
                painter.drawPolygon(poly)
        # And draw the walls
        wallThickness = self.wallThickness*min_scale
        for wid in walls:
            color = wallColoring(imageid, wid)
            if color.alpha() > 0:
                pen = QPen(color)
                pen.setWidthF(wallThickness)
                painter.setPen(pen)
                pts = [img_data[wid[0]]] + img_data.walls[wid[0], wid[1]] + [img_data[wid[1]]]
                #painter.drawLine(img_data[wid[0]], img_data[wid[1]])
                painter.drawPolyline(*pts)
        # Then, draw the points
        pointSize = self.pointSize*min_scale
        pointLineColor = self.pointLineColor
        pointLineThickness = self.pointLineThickness*min_scale
        log_debug("pointSize = %g" % pointSize)
        for pid in img_data:
            color = pointColoring(imageid, pid)
            if color.alpha() > 0:
                pen = QPen(pointLineColor)
                pen.setWidthF(pointLineThickness)
                brush = QBrush(color)
                painter.setPen(pen)
                painter.setBrush(brush)
                pos = img_data[pid]
                rect = QRectF(pos.x()-pointSize, pos.y()-pointSize, 2*pointSize, 2*pointSize)
                painter.drawEllipse(rect)
        if ellipsisDraw.plot:
            for cid in cells:
                pts = data.cellAtTime(cid, img_data.index)
                if pts:
                    pts.append(pts[0])
                    ppts = []
                    for p1,p2 in zip(pts[:-1], pts[1:]):
                        ppts.append(img_data[p1])
                        ppts.extend(img_data.walls[p1,p2])
                    ppts.append(ppts[0])
                    #poly = QPolygonF(ppts)
                    #painter.drawPolygon(poly)
                    ellipsisDraw(painter, imageid, cid, ppts, min_scale)
        # At last, draw the extra data
        for ed in extraDrawing:
            ed(painter, imageid)
        tr = painter.worldTransform()
        painter.restore()
        pic_w = wallColoring.finalizeImage(painter, imageid, tr, self.crop)
        pic_c = cellColoring.finalizeImage(painter, imageid, tr, self.crop)
        for ed in extraDrawing:
            ed.finalizeImage(painter, imageid, tr, self.crop)
        painter.end()
        return pix, pic_w, pic_c

    def start(self):
        if self.isRunning():
            assert not self.rendering_all, "Cannot run twice the rendering of all images with the same object."
            return
        if parameters.instance.use_thread:
            log_debug("Starting rendering thread.")
            QThread.start(self)
            return False
        else:
            self.run()
            return True

    def render_all(self):
        self.rendering_all = True
        return self.start()

    def render_single(self, img_id, retry=False):
        if retry:
            while self.isRunning():
                self.wait(10000)
        elif self.isRunning():
            return
        self.rendering_all = False
        self.current_image = img_id
        return self.start()

    def load(self, filename):
        self.loading = True
        self.result = filename
        return self.start()

    def run(self):
        if self.loading:
            self.run_loader()
        elif self.rendering_all:
            self.run_full()
        else:
            self.run_single()

    def run_single(self):
        img = self.current_image
        self.cellColoring.init()
        self.wallColoring.init()
        self.pointColoring.init()
        log_debug("Rendering image %d" % img)
        self.pix, self.pic_w, self.pic_c = self.drawImage(img)
        if self.pic_w is not None:
            log_debug("Has wall image")
        if self.pic_c is not None:
            log_debug("Has cell image")
        if self.pix is not None:
            log_debug("Pix correctly rendered")
        log_debug("Rendered image %d  = %s" % (img, self.pix))
        self.image_ready()

    def reload(self):
        if self.retryObject is None:
            return
        self._loading_arguments.update(self.retryObject.method_args)
        self.load(self.retryObject.filename)

    def run_loader(self):
        filename = self.result
        try:
            self.retryObject = None
# First, prepare the data by getting the images and computing how big they
# should be
            f = open(filename)
            first_line = f.readline()
            f.close()
            if first_line.startswith("TRKR_VERSION"):
                result = Result(None)
                result.load(self.result, **self._loading_arguments)
                result_type = "Growth"
            else:
                result = TrackingData()
                result.load(self.result, **self._loading_arguments)
                result_type = "Data"
            self.result = result
            self.result_type = result_type
            if result_type == "Data":
                data = result
                images = data.images_name
                if data.cells:
                    self.has_cells = True
                    self.has_walls = True
                else:
                    self.has_cells = False
                    self.has_walls = False
                self.has_points = bool(data.cell_points)
            else:
                data = result.data
                images = result.images
                self.has_cells = False
                self.has_walls = False
                self.has_points = False
            self.images = images
            cache = image_cache.cache
            self.update_nb_images(len(result))
            bbox = QRectF()
            ms = data.minScale()
            for i in range(len(result)):
                img_name = images[i]
                img_data = data[img_name]
                img = cache.image(data.image_path(img_name))
                matrix = QTransform()
                matrix = img_data.matrix()
                sc = QTransform()
                sc.scale(1.0/ms, 1.0/ms)
                matrix *= sc
                r = QRectF(img.rect())
                rbox = matrix.map(QPolygonF(r)).boundingRect()
                bbox |= rbox
                log_debug("Image '%s':\n\tSize = %gx%g\n\tTransformed = %gx%g %+g %+g\n\tGlobal bbox = %gx%g %+g %+g\n" %
                             (img_name, r.width(), r.height(), rbox.width(), rbox.height(), rbox.left(), rbox.top(),
                              bbox.width(), bbox.height(), bbox.left(), bbox.top()))
                log_debug("Matrix:\n%g\t%g\t%g\n%g\t%g\t%g\n" %
                            (matrix.m11(), matrix.m12(), matrix.dx(), matrix.m21(), matrix.m22(), matrix.dy()))
                if result_type == "Growth":
                    if result.cells[i]:
                        self.has_cells = True
                    if result.walls[i]:
                        self.has_walls = True
                    self.has_points = bool(result.data.cell_points)
                self.nextImage()
            translate = bbox.topLeft()
            translate *= -1
            self.translate = translate
            size = bbox.size().toSize()
            self.img_size = size
            self._crop = QRect(QPoint(0,0), size)
            self.finished()
            self._loading_arguments = {} # All done, we don't need that anymore
        except RetryTrackingDataException as ex:
            ex.filename = filename
            self.retryObject = ex
            self.finished()
            return
        except Exception as ex:
            _, _, exceptionTraceback = sys.exc_info()
            self.abort(ex, traceback=exceptionTraceback)
            raise

    def run_full(self):
        if not self.valid():
            self.abort("Object was not correctly initialized")
            return
        self.stop(False)
        painter = None
        try:
            result = self.result
            self.update_nb_images(len(result))
#            if self.result_type == "Data":
#                data = result
#                images = result.images_name
#            else:
#                data = result.data
#                images = result.images
#            cache = image_cache.cache
            cellColoring = self.cellColoring
            wallColoring = self.wallColoring
            pointColoring = self.pointColoring
            file_format = self.fileFormat
            file_pattern = "%s%%0%dd.%s" % (self.filePrefix, len(str(len(result))), file_format)
            wall_file_pattern = "%s%%0%dd_wall.%s" % (self.filePrefix, len(str(len(result))), file_format)
            cell_file_pattern = "%s%%0%dd_cell.%s" % (self.filePrefix, len(str(len(result))), file_format)
            cellColoring.init()
            wallColoring.init()
            pointColoring.init()
            self.nextImage()
            for i in range(len(result)):
                if self.stopped():
                    self.abort("User interruption")
                    return
                pix, pic_w, pic_c = self.drawImage(i)
                pix.save(file_pattern % (i+1), file_format)
                if pic_w is not None:
                    self.saveExtra(pic_w, wall_file_pattern % (i+1), file_format)
                if pic_c is not None:
                    self.saveExtra(pic_c, cell_file_pattern % (i+1), file_format)
                self.nextImage()
            self.finished()
        except Exception as ex:
            if painter is not None:
                painter.end()
            _, _, exceptionTraceback = sys.exc_info()
            self.abort(ex, traceback=exceptionTraceback)
            raise

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

        def _drawitem(pixmap, text, itempostion):
            painter.drawPixmap(itempostion, pixmap)
            textrect = QRectF(pixmap.width() + currentx + 10, itempostion.y(),
                              event.rect().width() - pixmap.width() - OFFSET_X,
                              pixmap.height())
            painter.drawText(textrect, text, QTextOption(Qt.AlignVCenter))

        def calcitems():
            font = painter.font()
            metrices = QFontMetrics(font)
            maxwidth = 0
            maxheight = 0
            for item, _ in itemlist():
                maxwidth = max(metrices.boundingRect(item).width(), maxwidth)
                maxheight = max(
                    metrices.boundingRect(item).height(), maxheight)
            return maxwidth, maxheight

        if not self.canvasimage:
            return

        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing)
        painter.drawImage(event.rect(), self.canvasimage)

        itemwidths, itemmaxheight = calcitems()
        OFFSET_X = 30
        OFFSET_Y = itemmaxheight + 10
        rect = event.rect()
        neededheight = (len(self.items) * OFFSET_Y)
        columns = 1
        if neededheight > rect.height():
            columns = math.ceil(neededheight / float(rect.height()))

        framerect = QRect(rect)
        framewidth = (itemwidths + OFFSET_X + ICON_SIZE.width() +
                      100) * columns
        framerect.setWidth(framewidth)
        painter.setBrush(self.legendareabrush)
        painter.setPen(self.legendareapen)
        painter.drawRect(framerect)
        self.framerect = framerect

        painter.setPen(Qt.black)
        currenty = OFFSET_Y
        currentx = OFFSET_X
        position = rect.topLeft() + QPoint(OFFSET_X, currenty)
        for text, icon in itemlist():
            itempostion = QPoint(position)
            if currenty > rect.height():
                currentx = itemwidths + OFFSET_X + 100
                currenty = itemmaxheight + 10

            itempostion.setX(currentx)
            itempostion.setY(currenty)

            _drawitem(icon, text, itempostion)
            currenty += OFFSET_Y

        position.setY(currenty + OFFSET_Y)
	def paint(self, painter, option, index):
	
		"""
		Draws the widget
		
		Arguments:
		painter -- a QPainter
		option -- a QStyleOptionView
		index -- a QModelIndex		
		"""
		
		# Retrieve the data
		model = index.model()
		record = model.data(index)
		text = record.toString()				
		zoteroItem = zoteroCache[unicode(text)]		
		l = zoteroItem.full_format().split("\n")
		if zoteroItem.fulltext == None:
			pixmap = self.noPdfPixmap
		else:
			pixmap = self.pdfPixmap
			
		# Choose the colors
		self.palette = self.qnotero.ui.listWidgetResults.palette()				
		if option.state & QStyle.State_MouseOver:
			background = self.palette.Highlight
			foreground = self.palette.HighlightedText
			_note = zoteroItem.get_note()			
			if _note != None:
				self.qnotero.showNoteHint()
			else:
				self.qnotero.hideNoteHint()
			
		elif option.state & QStyle.State_Selected:
			background = self.palette.Dark
			foreground = self.palette.WindowText
		else:
			background = self.palette.Base
			foreground = self.palette.WindowText
							
		# Draw the frame		
		_rect = option.rect.adjusted(self._margin, self._margin, \
			-2*self._margin, -self._margin)		
		pen = painter.pen()	
		pen.setColor(self.palette.color(background))
		painter.setPen(pen)
		painter.setBrush(self.palette.brush(background))
		painter.drawRoundedRect(_rect, self.roundness, self.roundness)
		font = painter.font
		pen = painter.pen()
		pen.setColor(self.palette.color(foreground))
		painter.setPen(pen)		
		
		# Draw icon		
		_rect = QRect(option.rect)
		_rect.moveBottom(_rect.bottom() + 0.5*self.dy)
		_rect.moveLeft(_rect.left() + 0.5*self.dy)
		_rect.setHeight(self.pixmapSize)
		_rect.setWidth(self.pixmapSize)
		painter.drawPixmap(_rect, pixmap)
					
		# Draw the text
		_rect = option.rect.adjusted(self.pixmapSize+self.dy, 0.5*self.dy, \
			-self.dy, 0)
		
		f = [self.tagFont, self.italicFont, self.regularFont, \
			self.boldFont]
		l.reverse()		
		while len(l) > 0:
			s = l.pop()
			if len(f) > 0:
				painter.setFont(f.pop())
			painter.drawText(_rect, Qt.AlignLeft, s)
			_rect = _rect.adjusted(0, self.dy, 0, 0)				
Exemple #20
0
class AbstractScrollTela(TelaConsole):
    def __init__(self, altura, parent=None):
        super().__init__(parent=parent)

        self._rectTela = QRect(0,0,0,altura)
        self._mostrarHorizontal = False
        self._mostrarVertical = False

        self._scrollHorizontal = ScrollBarConsole(3,0,orientacao=ScrollBarConsole.HORIZONTAL,parent=self)
        self._scrollVertical = ScrollBarConsole(self._rectTela.height(),0,orientacao=ScrollBarConsole.VERTICAL,parent=self)

        self._scrollHorizontal.valorScrollModificado.connect(self._moverHorizontal)
        self._scrollVertical.valorScrollModificado.connect(self._moverVertical)

        self._scrollBarFocus = ScrollBarConsole(3,0,parent=self)
        self._scrollBarFocus.installEventFilter(self)

    def eventFilter(self, obj, event):
        if obj == self._scrollBarFocus and event.type() != EventoTecladoConsole.TabType:
            self._scrollVertical.customEvent(event)
            self._scrollHorizontal.customEvent(event)
            return True
        else:
            return False

    def acceptFocus(self):
        return True

    def focusNextChild(self):
        if self._scrollBarFocus.hasFocus():
            return False

        if self.hasFocus():
            if not (self._mostrarVertical or self._mostrarHorizontal):
                return False
            self._scrollBarFocus.setFocus()
        else:
            if not self.acceptFocus():
                return False
            self.setFocus()

        return True

    def focusPrevChild(self):
        if self.hasFocus():
            return False

        if self._scrollBarFocus.hasFocus():
            if self.acceptFocus():
                self.setFocus()
            else:
                return False
        else:
            self._scrollBarFocus.setFocus()
        return True
    
    def indexChildActive(self):
        if self._scrollBarFocus.hasFocus():
            return 0
        
        return -1

    def getRectTela(self):
        return self._rectTela

    def _moverVertical(self, valor):
        self._scrollVertical.setValorAtual(valor)
        self._rectTela.moveTop(valor)

    def _moverHorizontal(self, valor):
        self._scrollHorizontal.setValorAtual(valor)
        self._rectTela.moveLeft(valor)

    def deixarVisivelVertical(self, valor):
        top = self.getRectTela().top()
        height = self.getRectTela().height() - self._numLinhasFixas() - 1
        bottom = top + height

        if valor < top:
            self._moverVertical(valor)
        elif valor > bottom:
            self._moverVertical(valor - height)

    def deixarVisivelHorizontal(self, valor):
        left = self.getRectTela().left()
        width = self.getRectTela().width()-1
        right = left + width

        if valor < left:
            self._moverHorizontal(valor)
        elif valor > right:
            self._moverHorizontal(valor - width)

    def scrollContentsBy(self, dx, dy):
        self._rectTela.translate(dx,dy)

    def getDesenhoTela(self):
        raise NotImplemented("Metodo abstrato")

    def _adicionarScrollBar(self, tela):
        if self._mostrarVertical:
            tela = self._adicionarScrollVertical(tela)

        if self._mostrarHorizontal:
            tela = self._adicionarScrollHorizontal(tela)

        return tela

    def _adicionarScrollVertical(self, texto):
        scroll = ''
        for i in self._scrollVertical.desenhoTelaConsole(self._rectTela.width()).split('\n'):
            scroll += "{0}|\n".format(i)
        scroll = "-|\n{0}-|".format(scroll).split('\n')

        s = ''
        texto = texto.split('\n')
        for i in range(len(texto)):
            s += "{0:{1}}{2}\n".format(texto[i], self._rectTela.width()+2, scroll[i])

        if s.endswith('\n'):
            s = s[:len(s)-1]

        return s

    def _adicionarScrollHorizontal(self, texto):
        texto += '\n|{0}|{1}\n'.format(self._scrollHorizontal.desenhoTelaConsole(self._rectTela.width()), 'X|' if self._mostrarVertical else '')
        texto += '|{0:-<{1}}|{2}'.format('', self._rectTela.width(), '-|' if self._mostrarVertical else '')
        return texto

    def _ajustarScroll(self, tela):
        linhas = tela.split('\n')
        numColunas = max(map(len, linhas))
        numLinhasFixas = self._numLinhasFixas()
        numLinhas = len(linhas) + numLinhasFixas

        self._mostrarVertical = numLinhas > self._rectTela.height()
        self._mostrarHorizontal = numColunas > self._rectTela.width()

        self._scrollHorizontal.setAteValor(max(0, numColunas-self._rectTela.width()))
        self._scrollVertical.setAteValor(max(0, numLinhas-self._rectTela.height()))

    def _adicionarLinhasFixas(self, tela):
        """Esse método deve ser sobrescrito pela classe filha para adicionar as linhas fixas na tela"""
        return tela

    def _numLinhasFixas(self):
        return self._adicionarLinhasFixas('').count('\n')

    def _linhasVisiveis(self, tela):
        linhas = tela.split('\n')
        numLinhasFixas = self._numLinhasFixas()
        numLinhas = len(linhas) + numLinhasFixas

        if numLinhas < self._rectTela.height():
            tela = self._adicionarLinhasFixas(tela)
            tela += '\n'*(self._rectTela.height()-numLinhas)
        else:
            top = self.getRectTela().top()
            bottom = self.getRectTela().bottom()+1
            return self._adicionarLinhasFixas('\n'.join(linhas[top:bottom - numLinhasFixas]))

        return tela

    def _colunasVisiveis(self, tela):
        linhas = tela.split('\n')
        numColunas = max(map(len, linhas))+1

        if numColunas > self._rectTela.width():
            tela = '\n'.join([linha[self._rectTela.left():self._rectTela.right()+1] for linha in linhas])

        return tela

    def _ajustarTela(self, tela):
        tela = self._linhasVisiveis(tela)
        tela = self._colunasVisiveis(tela)
        return tela

    def desenhoTela(self, tam):
        tela = self.getDesenhoTela()
        self._ajustarScroll(tela)

        if self._mostrarVertical:
            tam -= 2

        if tam-2 != self._rectTela.width():
            self._rectTela.setWidth(tam-2)
            self._scrollHorizontal.setTamanho(tam-2)
            self._ajustarScroll(tela)

        tela = self._ajustarTela(tela)
        tela = self._colocarBorda(tela, tam)
        return self._adicionarScrollBar(tela)
class XSnapshotWidget(QWidget):
    def __init__(self, parent=None):
        super(XSnapshotWidget, self).__init__(parent)

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

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

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

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

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

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

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

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

        super(XSnapshotWidget, self).keyPressEvent(event)

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

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

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

        super(XSnapshotWidget, self).mouseMoveEvent(event)

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

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

        painter.drawRect(self._region)

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

        self.close()
        self.deleteLater()

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

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

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

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

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

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

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

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

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

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

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

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

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

        if prompt or not filepath:
            widget.show()
        else:
            widget.save()
    def paint(self, painter, option, index):
        """
		Draws the widget

		Arguments:
		painter -- a QPainter
		option -- a QStyleOptionView
		index -- a QModelIndex
		"""

        # Retrieve the data
        model = index.model()
        record = model.data(index)
        text = record.toString()
        zoteroItem = zoteroCache[unicode(text)]
        l = zoteroItem.full_format().split(u"\n")
        if zoteroItem.fulltext == None:
            pixmap = self.noPdfPixmap
        else:
            pixmap = self.pdfPixmap

        # Choose the colors
        self.palette = self.qnotero.ui.listWidgetResults.palette()
        if option.state & QStyle.State_MouseOver:
            background = self.palette.Highlight
            foreground = self.palette.HighlightedText
            _note = zoteroItem.get_note()
            if _note != None:
                self.qnotero.showNoteHint()
            else:
                self.qnotero.hideNoteHint()

        elif option.state & QStyle.State_Selected:
            background = self.palette.Dark
            foreground = self.palette.WindowText
        else:
            background = self.palette.Base
            foreground = self.palette.WindowText

        # Draw the frame
        _rect = option.rect.adjusted(self._margin, self._margin, \
         -2*self._margin, -self._margin)
        pen = painter.pen()
        pen.setColor(self.palette.color(background))
        painter.setPen(pen)
        painter.setBrush(self.palette.brush(background))
        painter.drawRoundedRect(_rect, self.roundness, self.roundness)
        font = painter.font
        pen = painter.pen()
        pen.setColor(self.palette.color(foreground))
        painter.setPen(pen)

        # Draw icon
        _rect = QRect(option.rect)
        _rect.moveBottom(_rect.bottom() + 0.5 * self.dy)
        _rect.moveLeft(_rect.left() + 0.5 * self.dy)
        _rect.setHeight(self.pixmapSize)
        _rect.setWidth(self.pixmapSize)
        painter.drawPixmap(_rect, pixmap)

        # Draw the text
        _rect = option.rect.adjusted(self.pixmapSize+self.dy, 0.5*self.dy, \
         -self.dy, 0)

        f = [self.tagFont, self.italicFont, self.regularFont, \
         self.boldFont]
        l.reverse()
        while len(l) > 0:
            s = l.pop()
            if len(f) > 0:
                painter.setFont(f.pop())
            painter.drawText(_rect, Qt.AlignLeft, s)
            _rect = _rect.adjusted(0, self.dy, 0, 0)
    def paintEvent(self, e):
        """ """
        PKWidget.paintEvent(self, e)

        painter = QPainter(self)
        orig_pen = QPen(painter.pen())
        orig_brush = QBrush(painter.brush())
        orig_font = QFont(painter.font())
        metrics = painter.fontMetrics()
        f_height = metrics.ascent()
        text_flags = Qt.AlignHCenter | Qt.AlignVCenter
        
        region = e.region()
        for item in self._shown:
            font_y = item.y + item.height / 2 + f_height / 2

            item_rect = QRect(0, item.y, self.width(), item.height)
            if not region.contains(item_rect):
                continue

            painter.setFont(orig_font)

            # background
            pen = item.color().dark(110)
            pen.setAlpha(100)
            painter.setBrush(QBrush(item.color()))
            painter.setPen(QPen(pen))
            w = self.width() * (item.progress * .01)
            rect = QRect(0, item.y, w, item.height)
            painter.drawRect(rect)

            # queue pos
            pen = pen.dark(140)
            pen.setAlpha(255)
            painter.setPen(QPen(pen))
            queue_rect = QRect(self.padding, item.y + self.padding,
                               item.height - self.padding * 2,
                               item.height - self.padding * 2)
            painter.drawRoundRect(queue_rect, 35, 35)

            # num
            if not item.num is None:
                painter.setPen(orig_pen)
                painter.setBrush(orig_brush)
                painter.drawText(queue_rect, text_flags, str(item.num))

            # text
            painter.setPen(orig_pen)
            painter.setBrush(orig_brush)
            font = QFont('Utopia, Italic', 14, -1, True)
            painter.setFont(font)
            rect = QRect(item_rect)
            rect.setX(item.height + self.padding * 2)
            rect.setWidth(rect.width() - rect.x())
            painter.drawText(rect, Qt.AlignVCenter | Qt.AlignLeft, item.text)

            # state
            if item.state:
                font = QFont('7th Service Expanded Italic, Italic')
                font.setPointSize(18)
                pen = QColor(orig_pen.color())
                pen.setAlpha(50)
                painter.setPen(QPen(pen))
                painter.setFont(font)
                x = item.x
                y = item.y
                w = self.width()
                h = item.height
                rect = QRect(x, y, w, h)
                flags = Qt.AlignVCenter | Qt.AlignRight
                painter.drawText(rect, flags, item.state+'  ')