Esempio n. 1
0
    def draw_bg_rect(self, painter: QPainter, rect: QRect, color: int):
        painter.setPen(Qt.NoPen)
        brush = QBrush(QColor(color))
        painter.setBrush(brush)
        painter.drawRect(rect)

        # draw line at bottom of the rect
        painter.setPen(QColor(self.invert_color(color, bw=True)))
        painter.drawLine(rect.x(), rect.bottom(), rect.right(), rect.bottom())
Esempio n. 2
0
    def paint_wide_item(self, painter, option, index):
        painter.save()
        font = self.font
        fm = self.fm

        email_field, subject, snippet, date, unread = self.item_data(index)

        # If email is unread paint certain parts bold, if not then just set font_bold and fm_bold
        # to font and fm to avoid unnecessary checks later.
        if unread is False:
            font_bold = font
            fm_bold = fm
        else:
            font_bold = self.font_bold
            fm_bold = self.fm_bold
        option_rect = option.rect
        option_rect.setX(10)
        option_rect.setY(option_rect.y() + 10)
        row_height = (option_rect.height()) // 3
        option_rect.setWidth(option_rect.width() - 10)
        viewport_width = option_rect.width()

        email_field_rect = QRect(*option_rect.getRect())
        email_field_rect.setHeight(row_height)
        email_field_width = viewport_width // 2
        email_field_rect.setWidth(email_field_width)
        #email_field = fm_bold.elidedText(email_field, Qt.ElideRigth, email_field_width)
        painter.setFont(font_bold)
        painter.drawText(email_field_rect, 0, email_field)

        date_rect = QRect(*option_rect.getRect())
        date_rect.setHeight(row_height)
        date_rect.setLeft(email_field_rect.right())
        date_width = viewport_width // 2
        date_rect.setWidth(date_width)
        #date = fm_bold.elidedText(date, Qt.ElideLeft, date_width)
        painter.drawText(date_rect, Qt.AlignRight, date)

        subject_rect = QRect(*option_rect.getRect())
        subject_rect.setTop(email_field_rect.bottom())
        subject_rect.setHeight(row_height)
        subject_width = min(fm_bold.horizontalAdvance(subject), viewport_width)
        subject = fm_bold.elidedText(subject, Qt.ElideRight, subject_width)
        painter.drawText(subject_rect, 0, subject)

        snippet_rect = QRect(*option_rect.getRect())
        snippet_rect.setTop(subject_rect.bottom())
        snippet_rect.setHeight(row_height)
        snippet_rect.setWidth(viewport_width)
        snippet_width = min(fm.horizontalAdvance(snippet), viewport_width)
        snippet = fm.elidedText(snippet, Qt.ElideRight, snippet_width)
        painter.setFont(font)
        painter.drawText(snippet_rect, 0, snippet)

        painter.restore()
Esempio n. 3
0
    def to_image_rect(self, rect: QRect) -> QRect:
        rect = QRect(rect)
        if rect.top() > rect.bottom():
            _top, _bottom = rect.top(), rect.bottom()
            rect.setBottom(_top), rect.setTop(_bottom)

        if rect.left() > rect.right():
            _left, _right = rect.left(), rect.right()
            rect.setLeft(_right)
            rect.setRight(_left)

        return QRect(
            self.to_image_coord(rect.topLeft()),
            self.to_image_coord(rect.bottomRight())
        )
Esempio n. 4
0
def applyMargin(rect, margin):
    result = QRect(rect)
    result.setLeft(result.left()+margin)
    result.setRight(result.right()-margin)
    result.setTop(result.top()+margin)
    result.setBottom(result.bottom()-margin)
    return result
Esempio n. 5
0
    def __autoScrollAdvance(self):
        """Advance the auto scroll
        """
        pos = QCursor.pos()
        pos = self.mapFromGlobal(pos)
        margin = self.__autoScrollMargin

        vvalue = self.verticalScrollBar().value()
        hvalue = self.horizontalScrollBar().value()

        vrect = QRect(0, 0, self.width(), self.height())

        # What should be the speed
        advance = 10

        # We only do auto scroll if the mouse is inside the view.
        if vrect.contains(pos):
            if pos.x() < vrect.left() + margin:
                self.horizontalScrollBar().setValue(hvalue - advance)
            if pos.y() < vrect.top() + margin:
                self.verticalScrollBar().setValue(vvalue - advance)
            if pos.x() > vrect.right() - margin:
                self.horizontalScrollBar().setValue(hvalue + advance)
            if pos.y() > vrect.bottom() - margin:
                self.verticalScrollBar().setValue(vvalue + advance)

            if self.verticalScrollBar().value() == vvalue and \
                    self.horizontalScrollBar().value() == hvalue:
                self.__stopAutoScroll()
        else:
            self.__stopAutoScroll()

        log.debug("Auto scroll advance")
Esempio n. 6
0
    def paint_real_time_tips(self, qp: QPainter):
        if not self.__enable_real_time_tips or self.__l_pressing:
            return

        qp.drawLine(0, self.__mouse_on_coordinate.y(), self.__width,
                    self.__mouse_on_coordinate.y())
        qp.drawLine(self.__mouse_on_coordinate.x(), 0,
                    self.__mouse_on_coordinate.x(), self.__height)

        tip_text = self.format_real_time_tip()

        fm = QFontMetrics(self.__tip_font)
        text_width = fm.width(tip_text)
        text_height = fm.height()
        tip_area = QRect(self.__mouse_on_coordinate,
                         QSize(text_width, text_height))

        tip_area.setTop(tip_area.top() - fm.height())
        tip_area.setBottom(tip_area.bottom() - fm.height())
        if tip_area.right() > self.__axis_width:
            tip_area.setLeft(tip_area.left() - text_width)
            tip_area.setRight(tip_area.right() - text_width)

        qp.setFont(self.__tip_font)
        qp.setBrush(QColor(36, 169, 225))

        qp.drawRect(tip_area)
        qp.drawText(tip_area, Qt.AlignLeft, tip_text)
Esempio n. 7
0
    def saveScreenshot(self,
                       clipboard=False,
                       fileName='screenshot.png',
                       picType='png'):
        fullWindow = QRect(0, 0, self.width() - 1, self.height() - 1)
        selected = QRect(self.selectedArea)
        if selected.left() < 0:
            selected.setLeft(0)
        if selected.right() >= self.width():
            selected.setRight(self.width() - 1)
        if selected.top() < 0:
            selected.setTop(0)
        if selected.bottom() >= self.height():
            selected.setBottom(self.height() - 1)

        source = (fullWindow & selected)
        source.setTopLeft(
            QPoint(source.topLeft().x() * self.scale,
                   source.topLeft().y() * self.scale))
        source.setBottomRight(
            QPoint(source.bottomRight().x() * self.scale,
                   source.bottomRight().y() * self.scale))
        image = self.screenPixel.copy(source)
        image.setDevicePixelRatio(1)

        if clipboard:
            QGuiApplication.clipboard().setImage(QImage(image),
                                                 QClipboard.Clipboard)
        else:
            image.save(fileName, picType, 10)
        self.target_img = image
        self.screen_shot_grabed.emit(QImage(image))
Esempio n. 8
0
    def draw_hex_and_ascii(self, painter: QPainter):
        scroll_value = self.verticalScrollBar().value()
        first_index = scroll_value * self.bytes_per_row
        last_index = min(
            self.max_data_index + 1,
            (scroll_value + self.visible_rows()) * self.bytes_per_row,
        )

        for i, byte_index in enumerate(range(first_index, last_index)):
            if byte_index in self.data:

                bg_color = self.data[byte_index]["color"]
                text_color = self.invert_color(bg_color, bw=True)

                byte_hex = self.int_to_hex(
                    self.data[byte_index]["value"]).upper()
                byte_ascii = chr(self.data[byte_index]["value"])

                if byte_ascii not in string.printable:
                    byte_ascii = "."

                start_block = False
                if "start_block" in self.data[byte_index]:
                    start_block = True

                y = self.first_row_y + int(
                    i / self.bytes_per_row) * self.row_height

                # draw hex
                x = self.hex_table_x + (i %
                                        self.bytes_per_row) * self.byte_width
                rect = QRect(x, y, self.byte_width, self.row_height)
                self.draw_bg_rect(painter, rect, bg_color)
                self.draw_text(painter, byte_hex, x + 6, y + 15, text_color)
                if start_block:
                    painter.drawLine(rect.x(),
                                     rect.top() + 1, rect.x(), rect.bottom())

                # draw ascii
                x = self.ascii_table_x + (
                    i % self.bytes_per_row) * self.ascii_width
                rect = QRect(x, y, self.ascii_width, self.row_height)
                self.draw_bg_rect(painter, rect, bg_color)
                self.draw_text(painter, byte_ascii, x + 3, y + 15, text_color)
                if start_block:
                    painter.drawLine(rect.x(),
                                     rect.top() + 1, rect.x(), rect.bottom())
Esempio n. 9
0
    def popup(self, pos=None, searchText=""):
        """
        Popup the menu at `pos` (in screen coordinates). 'Search' text field
        is initialized with `searchText` if provided.

        """
        if pos is None:
            pos = QPoint()

        self.__clearCurrentItems()

        self.__search.setText(searchText)
        self.__suggestPage.setFilterFixedString(searchText)

        self.ensurePolished()

        if self.testAttribute(Qt.WA_Resized) and self.sizeGripEnabled():
            size = self.size()
        else:
            size = self.sizeHint()

        desktop = QApplication.desktop()
        screen_geom = desktop.availableGeometry(pos)

        # Adjust the size to fit inside the screen.
        if size.height() > screen_geom.height():
            size.setHeight(screen_geom.height())
        if size.width() > screen_geom.width():
            size.setWidth(screen_geom.width())

        geom = QRect(pos, size)

        if geom.top() < screen_geom.top():
            geom.setTop(screen_geom.top())

        if geom.left() < screen_geom.left():
            geom.setLeft(screen_geom.left())

        bottom_margin = screen_geom.bottom() - geom.bottom()
        right_margin = screen_geom.right() - geom.right()
        if bottom_margin < 0:
            # Falls over the bottom of the screen, move it up.
            geom.translate(0, bottom_margin)

        # TODO: right to left locale
        if right_margin < 0:
            # Falls over the right screen edge, move the menu to the
            # other side of pos.
            geom.translate(-size.width(), 0)

        self.setGeometry(geom)

        self.show()

        if searchText:
            self.setFocusProxy(self.__search)
        else:
            self.setFocusProxy(None)
Esempio n. 10
0
 def merge(self, pos, layer):
     # Determine the overlapping area
     area = QRect(pos, QSize(layer.width(), layer.height()))
     area &= QRect(0, 0, self.width(), self.height())
     for y in range(area.top(), area.bottom() + 1):
         for x in range(area.left(), area.right() + 1):
             cell = layer.cellAt(x - pos.x(), y - pos.y())
             if (not cell.isEmpty()):
                 self.setCell(x, y, cell)
Esempio n. 11
0
 def merge(self, pos, layer):
     # Determine the overlapping area
     area = QRect(pos, QSize(layer.width(), layer.height()))
     area &= QRect(0, 0, self.width(), self.height())
     for y in range(area.top(), area.bottom()+1):
         for x in range(area.left(), area.right()+1):
             cell = layer.cellAt(x - pos.x(), y - pos.y())
             if (not cell.isEmpty()):
                 self.setCell(x, y, cell)
Esempio n. 12
0
 def _create_qrect_with_border(source: QRect, border: int) -> QRect:
     """
     Takes a QRect item, copies it and adds a border, by shrinking the input by border pixels on each
     side. In other words: It performs a centered scaling, by reducing the input QRect size by 2*border pixels.
     """
     target = QRect(source)
     target.setRight(target.right() - border)
     target.setLeft(target.left() + border)
     target.setTop(target.top() + border)
     target.setBottom(target.bottom() - border)
     return target
 def adjust_area(self, area: QRect) -> QRect:
     if self.__layout == LAYOUT_VERTICAL:
         if area.top() < self.__longitudinal_since:
             area.setTop(self.__longitudinal_since)
         if area.bottom() > self.__longitudinal_until:
             area.setBottom(self.__longitudinal_until)
     elif self.__layout == LAYOUT_HORIZON:
         if area.left() < self.__longitudinal_since:
             area.setLeft(self.__longitudinal_since)
         if area.right() > self.__longitudinal_until:
             area.setRight(self.__longitudinal_until)
     return area
Esempio n. 14
0
def popup_position_from_source(popup, source, orientation=Qt.Vertical):
    popup.ensurePolished()
    source.ensurePolished()

    if popup.testAttribute(Qt.WA_Resized):
        size = popup.size()
    else:
        size = popup.sizeHint()

    desktop = QApplication.desktop()
    screen_geom = desktop.availableGeometry(source)
    source_rect = QRect(source.mapToGlobal(QPoint(0, 0)), source.size())

    if orientation == Qt.Vertical:
        if source_rect.right() + size.width() < screen_geom.right():
            x = source_rect.right()
        else:
            x = source_rect.left() - size.width()

        # bottom overflow
        dy = source_rect.top() + size.height() - screen_geom.bottom()
        if dy < 0:
            y = source_rect.top()
        else:
            y = source_rect.top() - dy
    else:
        # right overflow
        dx = source_rect.left() + size.width() - screen_geom.right()
        if dx < 0:
            x = source_rect.left()
        else:
            x = source_rect.left() - dx

        if source_rect.bottom() + size.height() < screen_geom.bottom():
            y = source_rect.bottom()
        else:
            y = source_rect.top() - size.height()

    return QPoint(x, y)
Esempio n. 15
0
class TilePainter(IPainter):
    def __init__(self, osm: "osm.Receiver", screen: "QRect"):
        super().__init__()
        self.tile_size = TILE_SIZE
        self.osm = osm
        self.osm.connect_handle_data(self.handle_network_data)
        self.zoom = 14
        self.latitude = 56.86738408969649
        self.longitude = 60.532554388046265
        self.set_map_rect(screen)
        self.download()

    def draw_tile(self, painter: "QPainter", tile: "QTile"):
        if tile.zoom == self.zoom:
            self.drawn.append(tile)
            target = QRect(tile.map_x, tile.map_y, TILE_SIZE, TILE_SIZE)
            painter.drawPixmap(target, self.osm.get_tile((tile.x, tile.y)))

    def draw(self, painter: "QPainter"):
        for x in range(self.map_rect.left(), self.map_rect.right()):
            for y in range(self.map_rect.top(), self.map_rect.bottom()):
                tile = QTile(Tile(x, y, self.zoom),
                             (x - self.map_rect.left()) * TILE_SIZE,
                             (y - self.map_rect.top()) * TILE_SIZE)
                self.draw_tile(painter, tile)

    def set_map_rect(self, rect: "QRect"):
        x, y = Translator.deg2num(self.latitude, self.longitude, self.zoom)
        width = rect.width() // TILE_SIZE + 2
        height = rect.height() // TILE_SIZE + 2
        self.map_rect = QRect(x, y, width, height)

    def handle_network_data(self, reply):
        self.osm.handle_network_data(reply)
        self.osm.purge_cache(self.map_rect)
        self.drawn = [
            tile for tile in self.drawn
            if self.osm.exist_tile((tile.x, tile.y))
        ]
        self.download()

    def download(self):
        self.drawn.clear()
        for x in range(self.map_rect.left(), self.map_rect.right()):
            for y in range(self.map_rect.top(), self.map_rect.bottom()):
                tile = Tile(x, y, self.zoom)
                if not self.osm.exist_tile((tile.x, tile.y)):
                    self.osm.download_tile(tile)
                    return
Esempio n. 16
0
    def adjustPosition(self, p):
        rect = self.rect()
        screen = QApplication.desktop().screenGeometry(self.getToolTipScreen())

        if p.x() + rect.width() > screen.x() + screen.width():
            # p.rx() -= 4 + rect.width()
            p.setX(p.x() - 4 + rect.width())
        if p.y() + rect.height() > screen.y() + screen.height():
            # p.ry() -= 24 + rect.height ()
            p.setY(p.x() - 24 + rect.height())
        if p.y() < screen.y():
            p.setY(screen.y())
        if p.x() + rect.width() > screen.x() + screen.width():
            p.setX(screen.x() + screen.width() - rect.width())
        if p.x() < screen.x():
            p.setX(screen.x())
        if p.y() + rect.height() > screen.y() + screen.height():
            p.setY(screen.y() + screen.height() - rect.height())

        futureRect = QRect(p.x(), p.y(), rect.width(), rect.height())
        cursor = QCursor.pos()
        if futureRect.contains(cursor):
            offset = QPoint()

            diff = cursor.x() - futureRect.left()
            minDiff = diff
            offset = QPoint(diff + abs(self.cursorOffset.x()) + 1, 0)

            diff = futureRect.right() - cursor.x()
            if diff < minDiff:
                minDiff = diff
                offset = QPoint(-diff - abs(self.cursorOffset.x()) - 1, 0)

            diff = cursor.y() - futureRect.top()
            if diff < minDiff:
                minDiff = diff
                offset = QPoint(0, diff + abs(self.cursorOffset.y()) + 1)

            diff = futureRect.bottom() - cursor.y()
            if diff < minDiff:
                minDiff = diff
                offset = QPoint(0, -diff - abs(self.cursorOffset.y()) - 1)

            p += offset

            assert not QRect(p.x(), p.y(), rect.width(),
                             rect.height()).contains(cursor)

        return p
Esempio n. 17
0
    def drawBackground(self, painter, rect):
        roomRect = QRect(rect.x() + (rect.width() - self.roomWidth) * .5,
                         rect.y() + (rect.height() - self.roomHeight) * .5,
                         self.roomWidth, self.roomHeight)
        gridWidth = roomRect.width() - (roomRect.width() % self.gridSize)
        gridHeight = roomRect.height() - (roomRect.height() % self.gridSize)
        left = int((self.roomWidth - gridWidth + 2 * roomRect.left()) * .5)
        top = int((self.roomHeight - gridHeight + 2 * roomRect.top()) * .5)
        painter.setPen(QPen(QColor("black"), 2, Qt.SolidLine))
        if self.grid:
            for x in range(left, int(roomRect.right()), self.gridSize):
                for y in range(top, int(roomRect.bottom()), self.gridSize):
                    painter.drawPoint(x, y)

        painter.drawRect(roomRect)
    def paint(self, painter: QPainter, option: 'QStyleOptionViewItem', index: QModelIndex) -> None:
        """
        Paint the playlist on the screen

        :param painter: Controls actual painting
        :param option: Options for painting
        :param index: Index of item
        """

        playlist = index.model().at(index.row())

        if not index.isValid():
            return

        painter.save()  # Save current state, before altering for custom painting

        painter.setRenderHints(QPainter.Antialiasing, True)
        painter.setRenderHints(QPainter.HighQualityAntialiasing, True)
        painter.setRenderHints(QPainter.SmoothPixmapTransform, True)

        playlist_pix: QPixmap = index.data(Qt.DecorationRole)  # Tiled pixmap

        title_font = QApplication.font()
        title_font.setPixelSize(15)
        title_fm = QFontMetrics(title_font)

        icon_rect = QRect(option.rect.left() + PlaylistDelegate.pad_horizontal,
                          option.rect.top(),
                          PlaylistDelegate.icon_diameter,
                          PlaylistDelegate.icon_diameter)

        title_rect = title_fm.boundingRect(option.rect.left() + PlaylistDelegate.pad_horizontal,
                                           icon_rect.bottom() + PlaylistDelegate.pad_vertical,
                                           icon_rect.width(),
                                           0,
                                           Qt.AlignHCenter | Qt.AlignTop | Qt.TextWordWrap,
                                           playlist.name)

        # Draw icon
        painter.drawPixmap(icon_rect, playlist_pix)

        # Draw title
        painter.setFont(title_font)
        painter.setPen(Qt.white)
        painter.drawText(title_rect, Qt.AlignHCenter | Qt.AlignTop | Qt.TextWordWrap, playlist.name)

        painter.restore()
Esempio n. 19
0
    def paintEvent(self, event):
        painter = QPainter(self)
        margin = 25
        pad = 10
        ind = 50
        cr = self.contentsRect()
        size = cr.size()
        boxWidth = (size.width() - 2 * margin - ind - 6 * pad) / 7
        boxHeight = boxWidth / 1.618

        date = datetime.date.today()
        prevMonth = date.month - 1
        top = cr.top() + margin

        while True:
            if not date.weekday():
                top += boxHeight + pad
            if prevMonth != date.month:
                top += boxHeight + pad

            rect = QRect(cr.left() + margin + ind + \
                    date.weekday() * (boxWidth + pad),
                    top, boxWidth, boxHeight)

            if rect.bottom() > cr.bottom() - margin:
                break

            if prevMonth != date.month:
                monRect = QRect(cr.left() + margin, top, ind, boxHeight)
                painter.drawText(monRect, Qt.AlignCenter, date.strftime('%b'))
            elif not date.weekday():
                monRect = QRect(cr.left() + margin, top, ind, boxHeight)
                painter.drawText(monRect, Qt.AlignCenter, date.strftime('%V'))

            if date in self.busyDays:
                color = QColor(200, 100, 100)
            elif date.weekday() > 4:
                color = QColor(0, 0, 120)
            else:
                color = QColor(60, 60, 180)

            painter.fillRect(rect, color)
            painter.drawText(rect, Qt.AlignCenter, str(date.day))

            prevMonth = date.month
            date += datetime.timedelta(days=1)
Esempio n. 20
0
    def computeDiffRegion(self, other):
        ret = QRegion()
        dx = other.x() - self.mX
        dy = other.y() - self.mY
        r = QRect(0, 0, self.width(), self.height())
        r &= QRect(dx, dy, other.width(), other.height())
        for y in range(r.top(), r.bottom()+1):
            for x in range(r.left(), r.right()+1):
                if (self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                    rangeStart = x
                    while (x <= r.right() and self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                        x += 1

                    rangeEnd = x
                    ret += QRect(rangeStart, y, rangeEnd - rangeStart, 1)

        return ret
Esempio n. 21
0
    def paintEvent(self, event):
        par = self.parent()
        size = min(self.spinner_size, par.width(), par.height())
        dot_count = 5
        dot_size = int(size / dot_count) * 1.5

        r = par.rect()
        spinner_rect = QRect(r.width() / 2 - size / 2,
                             r.height() / 2 - size / 2, size, size)

        painter = QPainter()
        painter.begin(self)
        painter.setPen(QPen(Qt.NoPen))

        for i in range(dot_count):
            if self.counter % dot_count == i:
                painter.setBrush(QBrush(QColor(0, 0, 0)))
                d_size = dot_size * 1.1
            else:
                painter.setBrush(QBrush(QColor(200, 200, 200)))
                d_size = dot_size

            r = size / 2 - dot_size / 2
            x = r * math.cos(2 * math.pi * i / dot_count)
            y = r * math.sin(2 * math.pi * i / dot_count)
            x_center = spinner_rect.left(
            ) + spinner_rect.width() / 2 - dot_size / 2
            y_center = spinner_rect.top(
            ) + spinner_rect.height() / 2 - dot_size / 2
            painter.drawEllipse(x_center + x, y_center + y, d_size, d_size)

        if self.message:
            painter.setPen(QPen(Qt.black))
            if self.font_size:
                f = painter.font()
                f.setPointSize(self.font_size)
                painter.setFont(f)
            spinner_rect.setTop(spinner_rect.bottom() + 3)
            spinner_rect.setHeight(painter.fontMetrics().height() * 1.5)
            r = painter.boundingRect(spinner_rect,
                                     Qt.AlignHCenter | Qt.AlignTop,
                                     self.message)
            painter.drawText(r.bottomLeft(), self.message)

        painter.end()
Esempio n. 22
0
    def computeDiffRegion(self, other):
        ret = QRegion()
        dx = other.x() - self.mX
        dy = other.y() - self.mY
        r = QRect(0, 0, self.width(), self.height())
        r &= QRect(dx, dy, other.width(), other.height())
        for y in range(r.top(), r.bottom() + 1):
            for x in range(r.left(), r.right() + 1):
                if (self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                    rangeStart = x
                    while (x <= r.right() and
                           self.cellAt(x, y) != other.cellAt(x - dx, y - dy)):
                        x += 1

                    rangeEnd = x
                    ret += QRect(rangeStart, y, rangeEnd - rangeStart, 1)

        return ret
Esempio n. 23
0
 def __updateHandles(self):
     """
     Private method to update the handles.
     """
     r = QRect(self.__selection)
     s2 = self.__handleSize // 2
     
     self.__TLHandle.moveTopLeft(r.topLeft())
     self.__TRHandle.moveTopRight(r.topRight())
     self.__BLHandle.moveBottomLeft(r.bottomLeft())
     self.__BRHandle.moveBottomRight(r.bottomRight())
     
     self.__LHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() // 2 - s2))
     self.__THandle.moveTopLeft(QPoint(r.x() + r.width() // 2 - s2, r.y()))
     self.__RHandle.moveTopRight(
         QPoint(r.right(), r.y() + r.height() // 2 - s2))
     self.__BHandle.moveBottomLeft(
         QPoint(r.x() + r.width() // 2 - s2, r.bottom()))
    def displayGraph(self, selection: QRect):
        reader = self.mediaPlayer.reader()
        if not reader:
            logging.error("Video not available")
        self.values = []
        for frame_number in range(reader.num_frames):
            frame = reader.frame(frame_number)
            temperatures = frame.data
            if not selection.isEmpty():
                temperatures = temperatures[
                    selection.top() : selection.bottom(),
                    selection.left() : selection.right(),
                ]
            self.values.append(numpy.average(temperatures))

        self.plot.setData(self.values)
        self.displayCurrentTemperature(self.mediaPlayer.position())
        self.plotItem.getViewBox().autoRange(padding=0.11)
        self.plotItem.getViewBox().setRange(xRange=(-10, reader.num_frames * 1.12))
Esempio n. 25
0
    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        roundedRect = QRect()
        radius = 6
        roundedRect.setX(self.rect().x() + radius / 2)
        roundedRect.setY(self.rect().y() + radius / 2)
        roundedRect.setWidth(self.rect().width() - radius)
        roundedRect.setHeight(self.rect().height() - radius)

        palette = QPalette()
        rectColor = palette.color(QPalette.Window)
        painter.setBrush(QBrush(rectColor))
        roundedRectPen = QPen(Qt.black)
        painter.setPen(roundedRectPen)

        painter.drawRoundedRect(roundedRect, radius, radius)

        closeButtonGeometry = self.closeButton.geometry()
        lineColor = palette.color(QPalette.Text)
        pen = QPen(lineColor)
        pen.setWidth(1)
        painter.setPen(pen)
        # horizontal line
        if hasattr(self, 'detailsButton'):
            detailsButtonGeometry = self.detailsButton.geometry()
            y = (closeButtonGeometry.bottom() +
                 detailsButtonGeometry.top()) / 2
            left = QPoint(
                min(closeButtonGeometry.left(), detailsButtonGeometry.left()),
                y)
            right = QPoint(
                max(closeButtonGeometry.right(), detailsButtonGeometry.right())
                - 8, y)
            painter.drawLine(left, right)

        # vertical line
        # close button and details button have Preferred size policy
        x = closeButtonGeometry.left() - pen.width()
        top = QPoint(x, roundedRect.top() + roundedRectPen.width())
        bottom = QPoint(x, roundedRect.bottom() - roundedRectPen.width())
        painter.drawLine(top, bottom)
Esempio n. 26
0
    def __updateHandles(self):
        """
        Private method to update the handles.
        """
        r = QRect(self.__selection)
        s2 = self.__handleSize // 2

        self.__TLHandle.moveTopLeft(r.topLeft())
        self.__TRHandle.moveTopRight(r.topRight())
        self.__BLHandle.moveBottomLeft(r.bottomLeft())
        self.__BRHandle.moveBottomRight(r.bottomRight())

        self.__LHandle.moveTopLeft(QPoint(r.x(), r.y() + r.height() // 2 - s2))
        self.__THandle.moveTopLeft(QPoint(r.x() + r.width() // 2 - s2, r.y()))
        self.__RHandle.moveTopRight(
            QPoint(r.right(),
                   r.y() + r.height() // 2 - s2))
        self.__BHandle.moveBottomLeft(
            QPoint(r.x() + r.width() // 2 - s2, r.bottom()))
Esempio n. 27
0
    def paintEvent(self, event):
        p = QPainter(self)

        # Need this configuration to enable stylesheets for subclasses of QWidgets
        opt = QStyleOption()
        opt.initFrom(self)
        self.style().drawPrimitive(QStyle.PE_Widget, opt, p, self)

        # Set font
        font = QFont(p.font())
        font.setFamily("Helvetica Neue")
        p.setFont(font)

        actionY = 0

        for action in self.actionList:
            actionRect = QRect(0, actionY, self.actionWidth, self.actionHeight)

            if action.isChecked():
                p.fillRect(actionRect, QColor(35, 35, 35))

            #if action == mOverAction:
            #    p.fillRect(actionRect, QColor(150, 150, 150))

            # Draw text for button
            p.setPen(QColor(255, 255, 255))
            size = p.fontMetrics().size(Qt.TextSingleLine, action.text())
            actionTextRect = QRect(
                QPoint(actionRect.width() / 2 - size.width() / 2,
                       actionRect.bottom() - size.height() - 5), size)
            p.drawText(actionTextRect, Qt.AlignCenter, action.text())

            # Draw button
            actionIconRect = QRect(
                0, actionY, actionRect.width(),
                actionRect.height() - 2 * actionTextRect.height() - 10)
            actionIcon = QIcon(action.icon())
            actionIcon.paint(p, actionIconRect)

            # Move to next button location
            actionY += actionRect.height()
Esempio n. 28
0
def widget_popup_geometry(pos, widget):
    widget.ensurePolished()

    if widget.testAttribute(Qt.WA_Resized):
        size = widget.size()
    else:
        size = widget.sizeHint()

    desktop = QApplication.desktop()
    screen_geom = desktop.availableGeometry(pos)

    # Adjust the size to fit inside the screen.
    if size.height() > screen_geom.height():
        size.setHeight(screen_geom.height())
    if size.width() > screen_geom.width():
        size.setWidth(screen_geom.width())

    geom = QRect(pos, size)

    if geom.top() < screen_geom.top():
        geom.setTop(screen_geom.top())

    if geom.left() < screen_geom.left():
        geom.setLeft(screen_geom.left())

    bottom_margin = screen_geom.bottom() - geom.bottom()
    right_margin = screen_geom.right() - geom.right()
    if bottom_margin < 0:
        # Falls over the bottom of the screen, move it up.
        geom.translate(0, bottom_margin)

    # TODO: right to left locale
    if right_margin < 0:
        # Falls over the right screen edge, move the menu to the
        # other side of pos.
        geom.translate(-size.width(), 0)

    return geom
Esempio n. 29
0
class ResizeHelper(QWidget):
    offsetChanged = pyqtSignal(QPoint)
    offsetXChanged = pyqtSignal(int)
    offsetYChanged = pyqtSignal(int)
    offsetBoundsChanged = pyqtSignal(QRect)

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

        self.mMouseAnchorPoint = QPoint()
        self.mOffset = QPoint()
        self.mOldSize = QSize()
        self.mDragging = False
        self.mOffsetBounds = QRect()
        self.mScale = 0.0
        self.mNewSize = QSize()
        self.mOrigOffset = QPoint()

        self.setMinimumSize(20, 20)
        self.setOldSize(QSize(1, 1))

    def oldSize(self):
        return self.mOldSize

    def newSize(self):
        return self.mNewSize

    def offset(self):
        return self.mOffset

    def offsetBounds(self):
        return self.mOffsetBounds

    def setOldSize(self, size):
        self.mOldSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setNewSize(self, size):
        self.mNewSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setOffset(self, offset):
        # Clamp the offset within the offset bounds
        newOffset = QPoint(
            min(self.mOffsetBounds.right(),
                max(self.mOffsetBounds.left(), offset.x())),
            min(self.mOffsetBounds.bottom(),
                max(self.mOffsetBounds.top(), offset.y())))
        if (self.mOffset != newOffset):
            xChanged = self.mOffset.x() != newOffset.x()
            yChanged = self.mOffset.y() != newOffset.y()
            self.mOffset = newOffset
            if (xChanged):
                self.offsetXChanged.emit(self.mOffset.x())
            if (yChanged):
                self.offsetYChanged.emit(self.mOffset.y())
            self.offsetChanged.emit(self.mOffset)
            self.update()

    ## Method to set only the X offset, provided for convenience. */
    def setOffsetX(self, x):
        self.setOffset(QPoint(x, self.mOffset.y()))

    ## Method to set only the Y offset, provided for convenience. */
    def setOffsetY(self, y):
        self.setOffset(QPoint(self.mOffset.x(), y))

    ## Method to set only new width, provided for convenience. */
    def setNewWidth(self, width):
        self.mNewSize.setWidth(width)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    ## Method to set only new height, provided for convenience. */
    def setNewHeight(self, height):
        self.mNewSize.setHeight(height)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def paintEvent(self, event):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        origX = (_size.width() - self.mNewSize.width() * self.mScale) / 2 + 0.5
        origY = (_size.height() -
                 self.mNewSize.height() * self.mScale) / 2 + 0.5
        oldRect = QRect(self.mOffset, self.mOldSize)
        painter = QPainter(self)
        painter.translate(origX, origY)
        painter.scale(self.mScale, self.mScale)
        pen = QPen(Qt.black)
        pen.setCosmetic(True)
        painter.setPen(pen)
        painter.drawRect(QRect(QPoint(0, 0), self.mNewSize))
        pen.setColor(Qt.white)
        painter.setPen(pen)
        painter.setBrush(Qt.white)
        painter.setOpacity(0.5)
        painter.drawRect(oldRect)
        pen.setColor(Qt.black)
        pen.setStyle(Qt.DashLine)
        painter.setOpacity(1.0)
        painter.setBrush(Qt.NoBrush)
        painter.setPen(pen)
        painter.drawRect(oldRect)
        painter.end()

    def mousePressEvent(self, event):
        self.mMouseAnchorPoint = event.pos()
        self.mOrigOffset = self.mOffset
        self.mDragging = event.button() == Qt.LeftButton

    def mouseMoveEvent(self, event):
        if (not self.mDragging):
            return
        pos = event.pos()
        if (pos != self.mMouseAnchorPoint):
            self.setOffset(self.mOrigOffset +
                           (pos - self.mMouseAnchorPoint) / self.mScale)
            self.offsetChanged.emit(self.mOffset)

    def resizeEvent(self, event):
        self.recalculateScale()

    def recalculateScale(self):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        if self.mOldSize.width() < self.mNewSize.width():
            width = self.mNewSize.width()
        else:
            width = 2 * self.mOldSize.width() - self.mNewSize.width()
        if self.mOldSize.height() < self.mNewSize.height():
            height = self.mNewSize.height()
        else:
            height = 2 * self.mOldSize.height() - self.mNewSize.height()

        # Pick the smallest scale
        scaleW = _size.width() / width
        scaleH = _size.height() / height
        if scaleW < scaleH:
            self.mScale = scaleW
        else:
            self.mScale = scaleH

        self.update()

    def recalculateMinMaxOffset(self):
        offsetBounds = self.mOffsetBounds
        if (self.mOldSize.width() <= self.mNewSize.width()):
            offsetBounds.setLeft(0)
            offsetBounds.setRight(self.mNewSize.width() -
                                  self.mOldSize.width())
        else:
            offsetBounds.setLeft(self.mNewSize.width() - self.mOldSize.width())
            offsetBounds.setRight(0)

        if (self.mOldSize.height() <= self.mNewSize.height()):
            offsetBounds.setTop(0)
            offsetBounds.setBottom(self.mNewSize.height() -
                                   self.mOldSize.height())
        else:
            offsetBounds.setTop(self.mNewSize.height() -
                                self.mOldSize.height())
            offsetBounds.setBottom(0)

        if (self.mOffsetBounds != offsetBounds):
            self.mOffsetBounds = offsetBounds
            self.offsetBoundsChanged.emit(self.mOffsetBounds)
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  #bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        #an empty scene, where we add all drawn line segments
        #a QGraphicsLineItem, and which we can use to then
        #render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = QColor(color)
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        '''

        pos -- QPointF-like
        '''
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert (self.pos == pos)
            self.moveTo(QPointF(pos.x() + 0.0001,
                                pos.y() + 0.0001))  # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off.

        tempi = QImage(QSize(4 * self.bb.width(), 4 * self.bb.height()),
                       QImage.Format_ARGB32_Premultiplied)  #TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because
        #  that would seem to make sure points are rounded to pixel CENTERS, but
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF(QPointF(self.bb.x() + 0.25,
                                     self.bb.y() + 0.25),
                             QSizeF(self.bb.width(), self.bb.height()))
        target_rect = QRectF(QPointF(0, 0),
                             QSizeF(4 * self.bb.width(), 4 * self.bb.height()))
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int)
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape((ndarr.shape[0], ) + (ndarr.shape[1] // 4, ) +
                              (4, ))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4 * 4

        downsample_threshold = (7. / 16) * 255
        labels = numpy.where(ndarr >= downsample_threshold,
                             numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(
                labels) == 0:
            labels[labels.shape[0] // 2,
                   labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()),
                                       labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        #data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(
            QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap,
                 Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        #update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        #grow bounding box
        self.bb.setLeft(
            min(self.bb.left(), max(0, x - self.brushSize // 2 - 1)))
        self.bb.setRight(
            max(self.bb.right(),
                min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1)))
        self.bb.setBottom(
            max(self.bb.bottom(),
                min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1)))

        #update/move position
        self.pos = pos
Esempio n. 31
0
class corkDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        QStyledItemDelegate.__init__(self, parent)
        self.factor = settings.corkSizeFactor / 100.
        self.lastPos = None
        self.editing = None
        self.margin = 5

        self.bgColors = {}

    def newStyle(self):
        return settings.corkStyle == "new"

    def setCorkSizeFactor(self, v):
        self.factor = v / 100.

    def sizeHint(self, option, index):
        if self.newStyle():
            defaultSize = QSize(300, 210)
        else:
            defaultSize = QSize(300, 200)
        return defaultSize * self.factor

    def editorEvent(self, event, model, option, index):
        # We catch the mouse position in the widget to know which part to edit
        if type(event) == QMouseEvent:
            self.lastPos = event.pos()  # - option.rect.topLeft()
        return QStyledItemDelegate.editorEvent(self, event, model, option, index)

    def createEditor(self, parent, option, index):
        self.updateRects(option, index)

        bgColor = self.bgColors.get(index, "white")

        if self.mainLineRect.contains(self.lastPos):
            # One line summary
            self.editing = Outline.summarySentence
            edt = QLineEdit(parent)
            edt.setFocusPolicy(Qt.StrongFocus)
            edt.setFrame(False)
            f = QFont(option.font)
            if self.newStyle():
                f.setBold(True)
            else:
                f.setItalic(True)
                edt.setAlignment(Qt.AlignCenter)
            edt.setPlaceholderText(self.tr("One line summary"))
            edt.setFont(f)
            edt.setStyleSheet("background: {}; color: black;".format(bgColor))
            return edt

        elif self.titleRect.contains(self.lastPos):
            # Title
            self.editing = Outline.title
            edt = QLineEdit(parent)
            edt.setFocusPolicy(Qt.StrongFocus)
            edt.setFrame(False)
            f = QFont(option.font)
            if self.newStyle():
                f.setPointSize(f.pointSize() + 4)
            else:
                edt.setAlignment(Qt.AlignCenter)
            f.setBold(True)
            edt.setFont(f)
            edt.setStyleSheet("background: {}; color: black;".format(bgColor))
            # edt.setGeometry(self.titleRect)
            return edt

        else:  # self.mainTextRect.contains(self.lastPos):
            # Summary
            self.editing = Outline.summaryFull
            edt = QPlainTextEdit(parent)
            edt.setFocusPolicy(Qt.StrongFocus)
            edt.setFrameShape(QFrame.NoFrame)
            try:
                # QPlainTextEdit.setPlaceholderText was introduced in Qt 5.3
                edt.setPlaceholderText(self.tr("Full summary"))
            except AttributeError:
                pass
            edt.setStyleSheet("background: {}; color: black;".format(bgColor))
            return edt

    def updateEditorGeometry(self, editor, option, index):

        if self.editing == Outline.summarySentence:
            # One line summary
            editor.setGeometry(self.mainLineRect)

        elif self.editing == Outline.title:
            # Title
            editor.setGeometry(self.titleRect)

        elif self.editing == Outline.summaryFull:
            # Summary
            editor.setGeometry(self.mainTextRect)

    def setEditorData(self, editor, index):
        item = index.internalPointer()

        if self.editing == Outline.summarySentence:
            # One line summary
            editor.setText(item.data(Outline.summarySentence))

        elif self.editing == Outline.title:
            # Title
            editor.setText(index.data())

        elif self.editing == Outline.summaryFull:
            # Summary
            editor.setPlainText(item.data(Outline.summaryFull))

    def setModelData(self, editor, model, index):

        if self.editing == Outline.summarySentence:
            # One line summary
            model.setData(index.sibling(index.row(), Outline.summarySentence), editor.text())

        elif self.editing == Outline.title:
            # Title
            model.setData(index, editor.text(), Outline.title)

        elif self.editing == Outline.summaryFull:
            # Summary
            model.setData(index.sibling(index.row(), Outline.summaryFull), editor.toPlainText())

    def updateRects(self, option, index):
        if self.newStyle():
            self.updateRects_v2(option, index)
        else:
            self.updateRects_v1(option, index)

    def updateRects_v2(self, option, index):
        margin = self.margin * 2
        iconSize = max(24 * self.factor, 18)
        item = index.internalPointer()
        fm = QFontMetrics(option.font)
        h = fm.lineSpacing()

        self.itemRect = option.rect.adjusted(margin, margin, -margin, -margin)

        top = 15 * self.factor
        self.topRect = QRect(self.itemRect)
        self.topRect.setHeight(top)

        self.cardRect = QRect(self.itemRect.topLeft() + QPoint(0, top),
                         self.itemRect.bottomRight())
        self.iconRect = QRect(self.cardRect.topLeft() + QPoint(margin, margin),
                              QSize(iconSize, iconSize))
        self.labelRect = QRect(self.cardRect.topRight() - QPoint(margin + self.factor * 18, 1),
                               self.cardRect.topRight() + QPoint(- margin - self.factor * 4, self.factor * 24))
        self.titleRect = QRect(self.iconRect.topRight() + QPoint(margin, 0),
                               self.labelRect.bottomLeft() - QPoint(margin, margin))
        self.titleRect.setBottom(self.iconRect.bottom())
        self.mainRect = QRect(self.iconRect.bottomLeft() + QPoint(0, margin),
                              self.cardRect.bottomRight() - QPoint(margin, 2*margin))
        self.mainRect.setLeft(self.titleRect.left())
        self.mainLineRect = QRect(self.mainRect.topLeft(),
                                  self.mainRect.topRight() + QPoint(0, h))
        self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin),
                                  self.mainRect.bottomRight())
        if not item.data(Outline.summarySentence):
            self.mainTextRect.setTopLeft(self.mainLineRect.topLeft())

    def updateRects_v1(self, option, index):
        margin = self.margin
        iconSize = max(16 * self.factor, 12)
        item = index.internalPointer()
        self.itemRect = option.rect.adjusted(margin, margin, -margin, -margin)
        self.iconRect = QRect(self.itemRect.topLeft() + QPoint(margin, margin), QSize(iconSize, iconSize))
        self.labelRect = QRect(self.itemRect.topRight() - QPoint(iconSize + margin, 0),
                               self.itemRect.topRight() + QPoint(0, iconSize + 2 * margin))
        self.titleRect = QRect(self.iconRect.topRight() + QPoint(margin, 0),
                               self.labelRect.bottomLeft() - QPoint(margin, margin))
        self.bottomRect = QRect(QPoint(self.itemRect.x(), self.iconRect.bottom() + margin),
                                QPoint(self.itemRect.right(), self.itemRect.bottom()))
        self.topRect = QRect(self.itemRect.topLeft(), self.bottomRect.topRight())
        self.mainRect = self.bottomRect.adjusted(margin, margin, -margin, -margin)
        self.mainLineRect = QRect(self.mainRect.topLeft(),
                                  self.mainRect.topRight() + QPoint(0, iconSize))
        self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin),
                                  self.mainRect.bottomRight())
        if not item.data(Outline.summarySentence):
            self.mainTextRect.setTopLeft(self.mainLineRect.topLeft())
        if item.data(Outline.label) in ["", "0", 0]:
            self.titleRect.setBottomRight(self.labelRect.bottomRight() - QPoint(self.margin, self.margin))

    def paint(self, p, option, index):
        if self.newStyle():
            self.paint_v2(p, option, index)
        else:
            self.paint_v1(p, option, index)

    def paint_v2(self, p, option, index):
        # QStyledItemDelegate.paint(self, p, option, index)
        if not index.isValid():
            return

        item = index.internalPointer()
        self.updateRects(option, index)
        colors = outlineItemColors(item)

        style = qApp.style()

        def _rotate(angle, rect=self.mainRect):
            p.translate(rect.center())
            p.rotate(angle)
            p.translate(-rect.center())

        def drawRect(r):
            p.save()
            p.setBrush(Qt.gray)
            p.drawRect(r)
            p.restore()

        # Draw background
        cg = QPalette.ColorGroup(QPalette.Normal if option.state & QStyle.State_Enabled else QPalette.Disabled)
        if cg == QPalette.Normal and not option.state & QStyle.State_Active:
            cg = QPalette.Inactive

            # Selection
        if option.state & QStyle.State_Selected:
            p.save()
            p.setBrush(option.palette.brush(cg, QPalette.Highlight))
            p.setPen(Qt.NoPen)
            #p.drawRoundedRect(option.rect, 12, 12)
            p.drawRect(option.rect)
            p.restore()

            # Background
        p.save()
        if settings.viewSettings["Cork"]["Background"] != "Nothing":
            c = colors[settings.viewSettings["Cork"]["Background"]]
            if c == QColor(Qt.transparent):
                c = QColor(Qt.white)
            col = mixColors(c, QColor(Qt.white), .2)
            backgroundColor = col
            p.setBrush(col)
        else:
            p.setBrush(Qt.white)
            backgroundColor = QColor(Qt.white)

            # Cache background color
        self.bgColors[index] = backgroundColor.name()

        p.setPen(Qt.NoPen)
        p.drawRect(self.cardRect)
        if item.isFolder():
            itemPoly = QPolygonF([
                self.topRect.topLeft(),
                self.topRect.topLeft() + QPoint(self.topRect.width() * .35, 0),
                self.cardRect.topLeft() + QPoint(self.topRect.width() * .45, 0),
                self.cardRect.topRight(),
                self.cardRect.bottomRight(),
                self.cardRect.bottomLeft()
            ])
            p.drawPolygon(itemPoly)
        p.restore()

        # Label color
        if settings.viewSettings["Cork"]["Corner"] != "Nothing":
            p.save()
            color = colors[settings.viewSettings["Cork"]["Corner"]]
            p.setPen(Qt.NoPen)
            p.setBrush(color)
            p.drawRect(self.labelRect)
            w = self.labelRect.width()
            poly = QPolygonF([
                self.labelRect.bottomLeft() + QPointF(0, 1),
                self.labelRect.bottomLeft() + QPointF(0, w / 2),
                self.labelRect.bottomLeft() + QPointF(w / 2, 1),
                self.labelRect.bottomRight() + QPointF(1, w / 2),
                self.labelRect.bottomRight() + QPointF(1, 1),
            ])

            p.drawPolygon(poly)
            p.restore()

        if settings.viewSettings["Cork"]["Corner"] == "Nothing" or \
           color == Qt.transparent:
            # No corner, so title can be full width
            self.titleRect.setRight(self.mainRect.right())

        # Draw the icon
        iconRect = self.iconRect
        mode = QIcon.Normal
        if not option.state & style.State_Enabled:
            mode = QIcon.Disabled
        elif option.state & style.State_Selected:
            mode = QIcon.Selected
        # index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
        icon = index.data(Qt.DecorationRole).pixmap(iconRect.size())
        if settings.viewSettings["Cork"]["Icon"] != "Nothing":
            color = colors[settings.viewSettings["Cork"]["Icon"]]
            colorifyPixmap(icon, color)
        QIcon(icon).paint(p, iconRect, option.decorationAlignment, mode)

        # Draw title
        p.save()
        text = index.data()

        if text:
            p.setPen(Qt.black)
            textColor = QColor(Qt.black)
            if settings.viewSettings["Cork"]["Text"] != "Nothing":
                col = colors[settings.viewSettings["Cork"]["Text"]]
                if col == Qt.transparent:
                    col = Qt.black

                # If title setting is compile, we have to hack the color
                # Or we won't see anything in some themes
                if settings.viewSettings["Cork"]["Text"] == "Compile":
                    if item.compile() in [0, "0"]:
                        col = mixColors(QColor(Qt.black), backgroundColor)
                    else:
                        col = Qt.black
                textColor = col
                p.setPen(col)
            f = QFont(option.font)
            f.setPointSize(f.pointSize() + 4)
            f.setBold(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(text, Qt.ElideRight, self.titleRect.width())
            p.drawText(self.titleRect, Qt.AlignLeft | Qt.AlignVCenter, elidedText)
        p.restore()

            # One line summary background
        lineSummary = item.data(Outline.summarySentence)
        fullSummary = item.data(Outline.summaryFull)

            # Border
        if settings.viewSettings["Cork"]["Border"] != "Nothing":
            p.save()
            p.setBrush(Qt.NoBrush)
            pen = p.pen()
            pen.setWidth(2)
            col = colors[settings.viewSettings["Cork"]["Border"]]
            pen.setColor(col)
            p.setPen(pen)
            if item.isFolder():
                p.drawPolygon(itemPoly)
            else:
                p.drawRect(self.cardRect)
            p.restore()

        # Draw status
        status = item.data(Outline.status)
        if status:
            it = mainWindow().mdlStatus.item(int(status), 0)
            if it != None:
                p.save()
                p.setClipRegion(QRegion(self.cardRect))
                f = p.font()
                f.setPointSize(f.pointSize() + 12)
                f.setBold(True)
                p.setFont(f)
                p.setPen(QColor(Qt.red).lighter(170))
                _rotate(-35, rect=self.cardRect)
                p.drawText(self.cardRect, Qt.AlignCenter, it.text())
                p.restore()

                # Draw Summary
                # One line
        if lineSummary:
            p.save()
            f = QFont(option.font)
            f.setBold(True)
            p.setFont(f)
            p.setPen(textColor)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width())
            p.drawText(self.mainLineRect, Qt.AlignLeft | Qt.AlignVCenter, elidedText)
            p.restore()

            # Full summary
        if fullSummary:
            p.save()
            p.setFont(option.font)
            p.setPen(textColor)
            p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)
            p.restore()

    def paint_v1(self, p, option, index):
        # QStyledItemDelegate.paint(self, p, option, index)
        if not index.isValid():
            return

        item = index.internalPointer()
        self.updateRects(option, index)
        colors = outlineItemColors(item)

        style = qApp.style()

        def _rotate(angle):
            p.translate(self.mainRect.center())
            p.rotate(angle)
            p.translate(-self.mainRect.center())

        # Draw background
        cg = QPalette.ColorGroup(QPalette.Normal if option.state & QStyle.State_Enabled else QPalette.Disabled)
        if cg == QPalette.Normal and not option.state & QStyle.State_Active:
            cg = QPalette.Inactive

            # Selection
        if option.state & QStyle.State_Selected:
            p.save()
            p.setBrush(option.palette.brush(cg, QPalette.Highlight))
            p.setPen(Qt.NoPen)
            p.drawRoundedRect(option.rect, 12, 12)
            p.restore()

            # Stack
        if item.isFolder() and item.childCount() > 0:
            p.save()
            p.setBrush(Qt.white)
            for i in reversed(range(3)):
                p.drawRoundedRect(self.itemRect.adjusted(2 * i, 2 * i, -2 * i, 2 * i), 10, 10)

            p.restore()

            # Background
        itemRect = self.itemRect
        p.save()
        if settings.viewSettings["Cork"]["Background"] != "Nothing":
            c = colors[settings.viewSettings["Cork"]["Background"]]
            col = mixColors(c, QColor(Qt.white), .2)
            p.setBrush(col)
        else:
            p.setBrush(Qt.white)
        pen = p.pen()
        pen.setWidth(2)
        p.setPen(pen)
        p.drawRoundedRect(itemRect, 10, 10)
        p.restore()

        # Title bar
        topRect = self.topRect
        p.save()
        if item.isFolder():
            color = QColor(Qt.darkGreen)
        else:
            color = QColor(Qt.blue).lighter(175)
        p.setPen(Qt.NoPen)
        p.setBrush(color)
        p.setClipRegion(QRegion(topRect))
        p.drawRoundedRect(itemRect, 10, 10)
        # p.drawRect(topRect)
        p.restore()

        # Label color
        if settings.viewSettings["Cork"]["Corner"] != "Nothing":
            p.save()
            color = colors[settings.viewSettings["Cork"]["Corner"]]
            p.setPen(Qt.NoPen)
            p.setBrush(color)
            p.setClipRegion(QRegion(self.labelRect))
            p.drawRoundedRect(itemRect, 10, 10)
            # p.drawRect(topRect)
            p.restore()
            if color != Qt.transparent:
                p.drawLine(self.labelRect.topLeft(), self.labelRect.bottomLeft())

            # One line summary background
        lineSummary = item.data(Outline.summarySentence)
        fullSummary = item.data(Outline.summaryFull)
        if lineSummary or not fullSummary:
            m = self.margin
            r = self.mainLineRect.adjusted(-m, -m, m, m / 2)
            p.save()
            p.setPen(Qt.NoPen)
            p.setBrush(QColor("#EEE"))
            p.drawRect(r)
            p.restore()

            # Border
        p.save()
        p.setBrush(Qt.NoBrush)
        pen = p.pen()
        pen.setWidth(2)
        if settings.viewSettings["Cork"]["Border"] != "Nothing":
            col = colors[settings.viewSettings["Cork"]["Border"]]
            if col == Qt.transparent:
                col = Qt.black
            pen.setColor(col)
        p.setPen(pen)
        p.drawRoundedRect(itemRect, 10, 10)
        p.restore()

        # Draw the icon
        iconRect = self.iconRect
        mode = QIcon.Normal
        if not option.state & style.State_Enabled:
            mode = QIcon.Disabled
        elif option.state & style.State_Selected:
            mode = QIcon.Selected
        # index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
        icon = index.data(Qt.DecorationRole).pixmap(iconRect.size())
        if settings.viewSettings["Cork"]["Icon"] != "Nothing":
            color = colors[settings.viewSettings["Cork"]["Icon"]]
            colorifyPixmap(icon, color)
        QIcon(icon).paint(p, iconRect, option.decorationAlignment, mode)

        # Draw title
        p.save()
        text = index.data()
        titleRect = self.titleRect
        if text:
            if settings.viewSettings["Cork"]["Text"] != "Nothing":
                col = colors[settings.viewSettings["Cork"]["Text"]]
                if col == Qt.transparent:
                    col = Qt.black
                p.setPen(col)
            f = QFont(option.font)
            # f.setPointSize(f.pointSize() + 1)
            f.setBold(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(text, Qt.ElideRight, titleRect.width())
            p.drawText(titleRect, Qt.AlignCenter, elidedText)
        p.restore()

        # Draw the line
        bottomRect = self.bottomRect
        p.save()
        # p.drawLine(itemRect.x(), iconRect.bottom() + margin,
        # itemRect.right(), iconRect.bottom() + margin)
        p.drawLine(bottomRect.topLeft(), bottomRect.topRight())
        p.restore()

        # Lines
        if True:
            p.save()
            p.setPen(QColor("#EEE"))
            fm = QFontMetrics(option.font)
            h = fm.lineSpacing()
            l = self.mainTextRect.topLeft() + QPoint(0, h)
            while self.mainTextRect.contains(l):
                p.drawLine(l, QPoint(self.mainTextRect.right(), l.y()))
                l.setY(l.y() + h)
            p.restore()

        # Draw status
        mainRect = self.mainRect
        status = item.data(Outline.status)
        if status:
            it = mainWindow().mdlStatus.item(int(status), 0)
            if it != None:
                p.save()
                p.setClipRegion(QRegion(mainRect))
                f = p.font()
                f.setPointSize(f.pointSize() + 12)
                f.setBold(True)
                p.setFont(f)
                p.setPen(QColor(Qt.red).lighter(175))
                _rotate(-35)
                p.drawText(mainRect, Qt.AlignCenter, it.text())
                p.restore()

                # Draw Summary
                # One line
        if lineSummary:
            p.save()
            f = QFont(option.font)
            f.setItalic(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width())
            p.drawText(self.mainLineRect, Qt.AlignCenter, elidedText)
            p.restore()

            # Full summary
        if fullSummary:
            p.setFont(option.font)
            p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)
Esempio n. 32
0
    def mouseMoveEvent(self, evt):
        """
        Protected method to handle mouse movements.
        
        @param evt mouse move event (QMouseEvent)
        """
        shouldShowHelp = not self.__helpTextRect.contains(evt.pos())
        if shouldShowHelp != self.__showHelp:
            self.__showHelp = shouldShowHelp
            self.update()

        if self.__mouseDown:
            if self.__newSelection:
                p = evt.pos()
                r = self.rect()
                self.__selection = self.__normalizeSelection(
                    QRect(self.__dragStartPoint, self.__limitPointToRect(p,
                                                                         r)))
            elif self.__mouseOverHandle is None:
                # moving the whole selection
                r = self.rect().normalized()
                s = self.__selectionBeforeDrag.normalized()
                p = s.topLeft() + evt.pos() - self.__dragStartPoint
                r.setBottomRight(r.bottomRight() -
                                 QPoint(s.width(), s.height()) + QPoint(1, 1))
                if not r.isNull() and r.isValid():
                    self.__selection.moveTo(self.__limitPointToRect(p, r))
            else:
                # dragging a handle
                r = QRect(self.__selectionBeforeDrag)
                offset = evt.pos() - self.__dragStartPoint

                if self.__mouseOverHandle in \
                   [self.__TLHandle, self.__THandle, self.__TRHandle]:
                    r.setTop(r.top() + offset.y())

                if self.__mouseOverHandle in \
                   [self.__TLHandle, self.__LHandle, self.__BLHandle]:
                    r.setLeft(r.left() + offset.x())

                if self.__mouseOverHandle in \
                   [self.__BLHandle, self.__BHandle, self.__BRHandle]:
                    r.setBottom(r.bottom() + offset.y())

                if self.__mouseOverHandle in \
                   [self.__TRHandle, self.__RHandle, self.__BRHandle]:
                    r.setRight(r.right() + offset.x())

                r.setTopLeft(self.__limitPointToRect(r.topLeft(), self.rect()))
                r.setBottomRight(
                    self.__limitPointToRect(r.bottomRight(), self.rect()))
                self.__selection = self.__normalizeSelection(r)

            self.update()
        else:
            if self.__selection.isNull():
                return

            found = False
            for r in self.__handles:
                if r.contains(evt.pos()):
                    self.__mouseOverHandle = r
                    found = True
                    break

            if not found:
                self.__mouseOverHandle = None
                if self.__selection.contains(evt.pos()):
                    self.setCursor(Qt.OpenHandCursor)
                else:
                    self.setCursor(Qt.CrossCursor)
            else:
                if self.__mouseOverHandle in [
                        self.__TLHandle, self.__BRHandle
                ]:
                    self.setCursor(Qt.SizeFDiagCursor)
                elif self.__mouseOverHandle in [
                        self.__TRHandle, self.__BLHandle
                ]:
                    self.setCursor(Qt.SizeBDiagCursor)
                elif self.__mouseOverHandle in [
                        self.__LHandle, self.__RHandle
                ]:
                    self.setCursor(Qt.SizeHorCursor)
                elif self.__mouseOverHandle in [
                        self.__THandle, self.__BHandle
                ]:
                    self.setCursor(Qt.SizeVerCursor)
Esempio n. 33
0
    def paintEvent(self, evt):
        """
        Protected method handling paint events.
        
        @param evt paint event (QPaintEvent)
        """
        if self.__grabbing:  # grabWindow() should just get the background
            return

        painter = QPainter(self)
        pal = QPalette(QToolTip.palette())
        font = QToolTip.font()

        handleColor = pal.color(QPalette.Active, QPalette.Highlight)
        handleColor.setAlpha(160)
        overlayColor = QColor(0, 0, 0, 160)
        textColor = pal.color(QPalette.Active, QPalette.Text)
        textBackgroundColor = pal.color(QPalette.Active, QPalette.Base)
        painter.drawPixmap(0, 0, self.__pixmap)
        painter.setFont(font)

        r = QRect(self.__selection)
        if not self.__selection.isNull():
            grey = QRegion(self.rect())
            if self.__mode == SnapshotRegionGrabber.Ellipse:
                reg = QRegion(r, QRegion.Ellipse)
            else:
                reg = QRegion(r)
            grey = grey.subtracted(reg)
            painter.setClipRegion(grey)
            painter.setPen(Qt.NoPen)
            painter.setBrush(overlayColor)
            painter.drawRect(self.rect())
            painter.setClipRect(self.rect())
            drawRect(painter, r, handleColor)

        if self.__showHelp:
            painter.setPen(textColor)
            painter.setBrush(textBackgroundColor)
            self.__helpTextRect = painter.boundingRect(
                self.rect().adjusted(2, 2, -2, -2), Qt.TextWordWrap,
                self.__helpText).translated(-self.__desktop.x(),
                                            -self.__desktop.y())
            self.__helpTextRect.adjust(-2, -2, 4, 2)
            drawRect(painter, self.__helpTextRect, textColor,
                     textBackgroundColor)
            painter.drawText(self.__helpTextRect.adjusted(3, 3, -3, -3),
                             Qt.TextWordWrap, self.__helpText)

        if self.__selection.isNull():
            return

        # The grabbed region is everything which is covered by the drawn
        # rectangles (border included). This means that there is no 0px
        # selection, since a 0px wide rectangle will always be drawn as a line.
        txt = "{0}, {1} ({2} x {3})".format(
            self.__locale.toString(self.__selection.x()),
            self.__locale.toString(self.__selection.y()),
            self.__locale.toString(self.__selection.width()),
            self.__locale.toString(self.__selection.height()))
        textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt)
        boundingRect = textRect.adjusted(-4, 0, 0, 0)

        if textRect.width() < r.width() - 2 * self.__handleSize and \
           textRect.height() < r.height() - 2 * self.__handleSize and \
           r.width() > 100 and \
           r.height() > 100:
            # center, unsuitable for small selections
            boundingRect.moveCenter(r.center())
            textRect.moveCenter(r.center())
        elif r.y() - 3 > textRect.height() and \
                r.x() + textRect.width() < self.rect().width():
            # on top, left aligned
            boundingRect.moveBottomLeft(QPoint(r.x(), r.y() - 3))
            textRect.moveBottomLeft(QPoint(r.x() + 2, r.y() - 3))
        elif r.x() - 3 > textRect.width():
            # left, top aligned
            boundingRect.moveTopRight(QPoint(r.x() - 3, r.y()))
            textRect.moveTopRight(QPoint(r.x() - 5, r.y()))
        elif r.bottom() + 3 + textRect.height() < self.rect().bottom() and \
                r.right() > textRect.width():
            # at bottom, right aligned
            boundingRect.moveTopRight(QPoint(r.right(), r.bottom() + 3))
            textRect.moveTopRight(QPoint(r.right() - 2, r.bottom() + 3))
        elif r.right() + textRect.width() + 3 < self.rect().width():
            # right, bottom aligned
            boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom()))
            textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom()))

        # If the above didn't catch it, you are running on a very
        # tiny screen...
        drawRect(painter, boundingRect, textColor, textBackgroundColor)
        painter.drawText(textRect, Qt.AlignHCenter, txt)

        if (r.height() > self.__handleSize * 2 and
            r.width() > self.__handleSize * 2) or \
           not self.__mouseDown:
            self.__updateHandles()
            painter.setPen(Qt.NoPen)
            painter.setBrush(handleColor)
            painter.setClipRegion(
                self.__handleMask(SnapshotRegionGrabber.StrokeMask))
            painter.drawRect(self.rect())
            handleColor.setAlpha(60)
            painter.setBrush(handleColor)
            painter.setClipRegion(
                self.__handleMask(SnapshotRegionGrabber.FillMask))
            painter.drawRect(self.rect())
    def paint(self, painter, option, index):

        if (index.isValid() == False):
            return
        painter.save()
        painter.setOpacity(0.6)
        if (option.state & QStyle.State_Selected):
            painter.fillRect(option.rect, option.palette.highlight())
        if (option.state & QStyle.State_MouseOver):
            painter.setOpacity(0.25)
            painter.fillRect(option.rect, option.palette.highlight())
        painter.setOpacity(1.0)
        painter.setFont(option.font)
        metrics = QFontMetrics(option.font)
        regular = QFont(option.font)
        italics = QFont(option.font)
        italics.setItalic(True)
        icon = QIcon(index.data(CPE.IMAGE))
        rect = option.rect
        margin = 4
        decoratonSize = QSize(option.decorationSize)
        imageSize = icon.actualSize(option.decorationSize)
        leftSideThumbnail = (decoratonSize.width() - imageSize.width()) / 2
        if (rect.width() < decoratonSize.width()):
            leftSideThumbnail = max(0, (rect.width() - imageSize.width()) / 2)
        topSizeThumbnail = (
            (rect.height() - imageSize.height()) / 2) + rect.top()
        painter.drawImage(
            QRect(leftSideThumbnail, topSizeThumbnail, imageSize.width(),
                  imageSize.height()),
            icon.pixmap(imageSize).toImage())

        labelWidth = rect.width() - decoratonSize.width() - (margin * 3)

        if (decoratonSize.width() + (margin * 2) < rect.width()):

            textRect = QRect(decoratonSize.width() + margin,
                             margin + rect.top(), labelWidth, metrics.height())
            textTitle = metrics.elidedText(
                str(index.row() + 1) + ". " + index.data(CPE.TITLE),
                Qt.ElideRight, labelWidth)
            painter.drawText(textRect, Qt.TextWordWrap, textTitle)

            if rect.height() / (metrics.lineSpacing() +
                                margin) > 5 or index.data(
                                    CPE.KEYWORDS) is not None:
                painter.setOpacity(0.6)
                textRect = QRect(textRect.left(),
                                 textRect.bottom() + margin, labelWidth,
                                 metrics.height())
                if textRect.bottom() < rect.bottom():
                    textKeyWords = index.data(CPE.KEYWORDS)
                    if textKeyWords == None:
                        textKeyWords = i18n("No keywords")
                        painter.setOpacity(0.3)
                        painter.setFont(italics)
                    textKeyWords = metrics.elidedText(textKeyWords,
                                                      Qt.ElideRight,
                                                      labelWidth)
                    painter.drawText(textRect, Qt.TextWordWrap, textKeyWords)

            painter.setFont(regular)

            if rect.height() / (metrics.lineSpacing() + margin) > 3:
                painter.setOpacity(0.6)
                textRect = QRect(textRect.left(),
                                 textRect.bottom() + margin, labelWidth,
                                 metrics.height())
                if textRect.bottom() + metrics.height() < rect.bottom():
                    textLastEdit = index.data(CPE.LASTEDIT)
                    if textLastEdit is None:
                        textLastEdit = i18n("No last edit timestamp")
                    if index.data(CPE.EDITOR) is not None:
                        textLastEdit += " - " + index.data(CPE.EDITOR)
                    if (index.data(CPE.LASTEDIT) is None) and (index.data(
                            CPE.EDITOR) is None):
                        painter.setOpacity(0.3)
                        painter.setFont(italics)
                    textLastEdit = metrics.elidedText(textLastEdit,
                                                      Qt.ElideRight,
                                                      labelWidth)
                    painter.drawText(textRect, Qt.TextWordWrap, textLastEdit)

            painter.setFont(regular)

            descRect = QRect(textRect.left(),
                             textRect.bottom() + margin, labelWidth,
                             (rect.bottom() - margin) -
                             (textRect.bottom() + margin))
            if textRect.bottom() + metrics.height() < rect.bottom():
                textRect.setBottom(textRect.bottom() + (margin / 2))
                textRect.setLeft(textRect.left() - (margin / 2))
                painter.setOpacity(0.4)
                painter.drawLine(textRect.bottomLeft(), textRect.bottomRight())
                painter.setOpacity(1.0)
                textDescription = index.data(CPE.DESCRIPTION)
                if textDescription is None:
                    textDescription = i18n("No description")
                    painter.setOpacity(0.3)
                    painter.setFont(italics)
                linesTotal = floor(descRect.height() / metrics.lineSpacing())
                if linesTotal == 1:
                    textDescription = metrics.elidedText(
                        textDescription, Qt.ElideRight, labelWidth)
                    painter.drawText(descRect, Qt.TextWordWrap,
                                     textDescription)
                else:
                    descRect.setHeight(linesTotal * metrics.lineSpacing())
                    totalDescHeight = metrics.boundingRect(
                        descRect, Qt.TextWordWrap, textDescription).height()
                    if totalDescHeight > descRect.height():
                        if totalDescHeight - metrics.lineSpacing(
                        ) > descRect.height():
                            painter.setOpacity(0.5)
                            painter.drawText(descRect, Qt.TextWordWrap,
                                             textDescription)
                            descRect.setHeight(
                                (linesTotal - 1) * metrics.lineSpacing())
                            painter.drawText(descRect, Qt.TextWordWrap,
                                             textDescription)
                            descRect.setHeight(
                                (linesTotal - 2) * metrics.lineSpacing())
                            painter.drawText(descRect, Qt.TextWordWrap,
                                             textDescription)
                        else:
                            painter.setOpacity(0.75)
                            painter.drawText(descRect, Qt.TextWordWrap,
                                             textDescription)
                            descRect.setHeight(
                                (linesTotal - 1) * metrics.lineSpacing())
                            painter.drawText(descRect, Qt.TextWordWrap,
                                             textDescription)
                    else:
                        painter.drawText(descRect, Qt.TextWordWrap,
                                         textDescription)

            painter.setFont(regular)

        painter.restore()
    def paint(self, painter, option, index):
        """
        Public method to paint the specified list item.
        
        @param painter painter object to paint to (QPainter)
        @param option style option used for painting (QStyleOptionViewItem)
        @param index model index of the item (QModelIndex)
        """
        opt = QStyleOptionViewItem(option)
        self.initStyleOption(opt, index)

        widget = opt.widget
        style = widget.style() if widget is not None else QApplication.style()
        height = opt.rect.height()
        center = height // 2 + opt.rect.top()

        # Prepare title font
        titleFont = QFont(opt.font)
        titleFont.setBold(True)
        titleFont.setPointSize(titleFont.pointSize() + 1)

        titleMetrics = QFontMetrics(titleFont)
        if Globals.isWindowsPlatform():
            colorRole = QPalette.Text
        else:
            colorRole = QPalette.HighlightedText if opt.state & QStyle.State_Selected else QPalette.Text

        leftPos = self.__padding
        rightPos = opt.rect.right() - self.__padding - GreaseMonkeyConfigurationListDelegate.RemoveIconSize

        # Draw background
        style.drawPrimitive(QStyle.PE_PanelItemViewItem, opt, painter, widget)

        # Draw checkbox
        checkBoxYPos = center - GreaseMonkeyConfigurationListDelegate.CheckBoxSize // 2
        opt2 = QStyleOptionViewItem(opt)
        if opt2.checkState == Qt.Checked:
            opt2.state |= QStyle.State_On
        else:
            opt2.state |= QStyle.State_Off
        styleCheckBoxRect = style.subElementRect(QStyle.SE_ViewItemCheckIndicator, opt2, widget)
        opt2.rect = QRect(leftPos, checkBoxYPos, styleCheckBoxRect.width(), styleCheckBoxRect.height())
        style.drawPrimitive(QStyle.PE_IndicatorViewItemCheck, opt2, painter, widget)
        leftPos = opt2.rect.right() + self.__padding

        # Draw icon
        iconYPos = center - GreaseMonkeyConfigurationListDelegate.IconSize // 2
        iconRect = QRect(
            leftPos,
            iconYPos,
            GreaseMonkeyConfigurationListDelegate.IconSize,
            GreaseMonkeyConfigurationListDelegate.IconSize,
        )
        pixmap = index.data(Qt.DecorationRole).pixmap(GreaseMonkeyConfigurationListDelegate.IconSize)
        painter.drawPixmap(iconRect, pixmap)
        leftPos = iconRect.right() + self.__padding

        # Draw script name
        name = index.data(Qt.DisplayRole)
        leftTitleEdge = leftPos + 2
        rightTitleEdge = rightPos - self.__padding
        leftPosForVersion = titleMetrics.width(name) + self.__padding
        nameRect = QRect(
            leftTitleEdge, opt.rect.top() + self.__padding, rightTitleEdge - leftTitleEdge, titleMetrics.height()
        )
        painter.setFont(titleFont)
        style.drawItemText(painter, nameRect, Qt.AlignLeft, opt.palette, True, name, colorRole)

        # Draw version
        version = index.data(Qt.UserRole)
        versionRect = QRect(
            nameRect.x() + leftPosForVersion, nameRect.y(), rightTitleEdge - leftTitleEdge, titleMetrics.height()
        )
        versionFont = titleFont
        painter.setFont(versionFont)
        style.drawItemText(painter, versionRect, Qt.AlignLeft, opt.palette, True, version, colorRole)

        # Draw description
        infoYPos = nameRect.bottom() + opt.fontMetrics.leading()
        infoRect = QRect(nameRect.x(), infoYPos, nameRect.width(), opt.fontMetrics.height())
        info = opt.fontMetrics.elidedText(index.data(Qt.UserRole + 1), Qt.ElideRight, infoRect.width())
        painter.setFont(opt.font)
        style.drawItemText(painter, infoRect, Qt.AlignLeft | Qt.TextSingleLine, opt.palette, True, info, colorRole)

        # Draw remove button
        removeIconYPos = center - GreaseMonkeyConfigurationListDelegate.RemoveIconSize // 2
        removeIconRect = QRect(
            rightPos,
            removeIconYPos,
            GreaseMonkeyConfigurationListDelegate.RemoveIconSize,
            GreaseMonkeyConfigurationListDelegate.RemoveIconSize,
        )
        painter.drawPixmap(removeIconRect, self.__removePixmap)
Esempio n. 36
0
 def mouseMoveEvent(self, evt):
     """
     Protected method to handle mouse movements.
     
     @param evt mouse move event (QMouseEvent)
     """
     shouldShowHelp = not self.__helpTextRect.contains(evt.pos())
     if shouldShowHelp != self.__showHelp:
         self.__showHelp = shouldShowHelp
         self.update()
     
     if self.__mouseDown:
         if self.__newSelection:
             p = evt.pos()
             r = self.rect()
             self.__selection = self.__normalizeSelection(
                 QRect(self.__dragStartPoint,
                       self.__limitPointToRect(p, r)))
         elif self.__mouseOverHandle is None:
             # moving the whole selection
             r = self.rect().normalized()
             s = self.__selectionBeforeDrag.normalized()
             p = s.topLeft() + evt.pos() - self.__dragStartPoint
             r.setBottomRight(
                 r.bottomRight() - QPoint(s.width(), s.height()) +
                 QPoint(1, 1))
             if not r.isNull() and r.isValid():
                 self.__selection.moveTo(self.__limitPointToRect(p, r))
         else:
             # dragging a handle
             r = QRect(self.__selectionBeforeDrag)
             offset = evt.pos() - self.__dragStartPoint
             
             if self.__mouseOverHandle in \
                [self.__TLHandle, self.__THandle, self.__TRHandle]:
                 r.setTop(r.top() + offset.y())
             
             if self.__mouseOverHandle in \
                [self.__TLHandle, self.__LHandle, self.__BLHandle]:
                 r.setLeft(r.left() + offset.x())
             
             if self.__mouseOverHandle in \
                [self.__BLHandle, self.__BHandle, self.__BRHandle]:
                 r.setBottom(r.bottom() + offset.y())
             
             if self.__mouseOverHandle in \
                [self.__TRHandle, self.__RHandle, self.__BRHandle]:
                 r.setRight(r.right() + offset.x())
             
             r.setTopLeft(self.__limitPointToRect(r.topLeft(), self.rect()))
             r.setBottomRight(
                 self.__limitPointToRect(r.bottomRight(), self.rect()))
             self.__selection = self.__normalizeSelection(r)
         
         self.update()
     else:
         if self.__selection.isNull():
             return
         
         found = False
         for r in self.__handles:
             if r.contains(evt.pos()):
                 self.__mouseOverHandle = r
                 found = True
                 break
         
         if not found:
             self.__mouseOverHandle = None
             if self.__selection.contains(evt.pos()):
                 self.setCursor(Qt.OpenHandCursor)
             else:
                 self.setCursor(Qt.CrossCursor)
         else:
             if self.__mouseOverHandle in [self.__TLHandle,
                                           self.__BRHandle]:
                 self.setCursor(Qt.SizeFDiagCursor)
             elif self.__mouseOverHandle in [self.__TRHandle,
                                             self.__BLHandle]:
                 self.setCursor(Qt.SizeBDiagCursor)
             elif self.__mouseOverHandle in [self.__LHandle,
                                             self.__RHandle]:
                 self.setCursor(Qt.SizeHorCursor)
             elif self.__mouseOverHandle in [self.__THandle,
                                             self.__BHandle]:
                 self.setCursor(Qt.SizeVerCursor)
Esempio n. 37
0
 def paintEvent(self, evt):
     """
     Protected method handling paint events.
     
     @param evt paint event (QPaintEvent)
     """
     if self.__grabbing:     # grabWindow() should just get the background
         return
     
     painter = QPainter(self)
     pal = QPalette(QToolTip.palette())
     font = QToolTip.font()
     
     handleColor = pal.color(QPalette.Active, QPalette.Highlight)
     handleColor.setAlpha(160)
     overlayColor = QColor(0, 0, 0, 160)
     textColor = pal.color(QPalette.Active, QPalette.Text)
     textBackgroundColor = pal.color(QPalette.Active, QPalette.Base)
     painter.drawPixmap(0, 0, self.__pixmap)
     painter.setFont(font)
     
     r = QRect(self.__selection)
     if not self.__selection.isNull():
         grey = QRegion(self.rect())
         if self.__mode == SnapshotRegionGrabber.Ellipse:
             reg = QRegion(r, QRegion.Ellipse)
         else:
             reg = QRegion(r)
         grey = grey.subtracted(reg)
         painter.setClipRegion(grey)
         painter.setPen(Qt.NoPen)
         painter.setBrush(overlayColor)
         painter.drawRect(self.rect())
         painter.setClipRect(self.rect())
         drawRect(painter, r, handleColor)
     
     if self.__showHelp:
         painter.setPen(textColor)
         painter.setBrush(textBackgroundColor)
         self.__helpTextRect = painter.boundingRect(
             self.rect().adjusted(2, 2, -2, -2),
             Qt.TextWordWrap, self.__helpText).translated(
             -self.__desktop.x(), -self.__desktop.y())
         self.__helpTextRect.adjust(-2, -2, 4, 2)
         drawRect(painter, self.__helpTextRect, textColor,
                  textBackgroundColor)
         painter.drawText(
             self.__helpTextRect.adjusted(3, 3, -3, -3),
             Qt.TextWordWrap, self.__helpText)
     
     if self.__selection.isNull():
         return
     
     # The grabbed region is everything which is covered by the drawn
     # rectangles (border included). This means that there is no 0px
     # selection, since a 0px wide rectangle will always be drawn as a line.
     txt = "{0:n}, {1:n} ({2:n} x {3:n})".format(
         self.__selection.x(), self.__selection.y(),
         self.__selection.width(), self.__selection.height())
     textRect = painter.boundingRect(self.rect(), Qt.AlignLeft, txt)
     boundingRect = textRect.adjusted(-4, 0, 0, 0)
     
     if textRect.width() < r.width() - 2 * self.__handleSize and \
        textRect.height() < r.height() - 2 * self.__handleSize and \
        r.width() > 100 and \
        r.height() > 100:
         # center, unsuitable for small selections
         boundingRect.moveCenter(r.center())
         textRect.moveCenter(r.center())
     elif r.y() - 3 > textRect.height() and \
             r.x() + textRect.width() < self.rect().width():
         # on top, left aligned
         boundingRect.moveBottomLeft(QPoint(r.x(), r.y() - 3))
         textRect.moveBottomLeft(QPoint(r.x() + 2, r.y() - 3))
     elif r.x() - 3 > textRect.width():
         # left, top aligned
         boundingRect.moveTopRight(QPoint(r.x() - 3, r.y()))
         textRect.moveTopRight(QPoint(r.x() - 5, r.y()))
     elif r.bottom() + 3 + textRect.height() < self.rect().bottom() and \
             r.right() > textRect.width():
         # at bottom, right aligned
         boundingRect.moveTopRight(QPoint(r.right(), r.bottom() + 3))
         textRect.moveTopRight(QPoint(r.right() - 2, r.bottom() + 3))
     elif r.right() + textRect.width() + 3 < self.rect().width():
         # right, bottom aligned
         boundingRect.moveBottomLeft(QPoint(r.right() + 3, r.bottom()))
         textRect.moveBottomLeft(QPoint(r.right() + 5, r.bottom()))
     
     # If the above didn't catch it, you are running on a very
     # tiny screen...
     drawRect(painter, boundingRect, textColor, textBackgroundColor)
     painter.drawText(textRect, Qt.AlignHCenter, txt)
     
     if (r.height() > self.__handleSize * 2 and
         r.width() > self.__handleSize * 2) or \
        not self.__mouseDown:
         self.__updateHandles()
         painter.setPen(Qt.NoPen)
         painter.setBrush(handleColor)
         painter.setClipRegion(
             self.__handleMask(SnapshotRegionGrabber.StrokeMask))
         painter.drawRect(self.rect())
         handleColor.setAlpha(60)
         painter.setBrush(handleColor)
         painter.setClipRegion(
             self.__handleMask(SnapshotRegionGrabber.FillMask))
         painter.drawRect(self.rect())
Esempio n. 38
0
class BrushingModel(QObject):
    brushSizeChanged = pyqtSignal(int)
    brushColorChanged = pyqtSignal(QColor)
    brushStrokeAvailable = pyqtSignal(QPointF, object)
    drawnNumberChanged = pyqtSignal(int)

    minBrushSize = 1
    maxBrushSize = 61
    defaultBrushSize = 3
    defaultDrawnNumber = 1
    defaultColor = Qt.white
    erasingColor = Qt.black
    erasingNumber = 100

    def __init__(self, parent=None):
        QObject.__init__(self, parent=parent)
        self.sliceRect = None
        self.bb = QRect()  # bounding box enclosing the drawing
        self.brushSize = self.defaultBrushSize
        self.drawColor = self.defaultColor
        self._temp_color = None
        self._temp_number = None
        self.drawnNumber = self.defaultDrawnNumber

        self.pos = None
        self.erasing = False
        self._hasMoved = False

        self.drawOnto = None

        # an empty scene, where we add all drawn line segments
        # a QGraphicsLineItem, and which we can use to then
        # render to an image
        self.scene = QGraphicsScene()

    def toggleErase(self):
        self.erasing = not (self.erasing)
        if self.erasing:
            self.setErasing()
        else:
            self.disableErasing()

    def setErasing(self):
        self.erasing = True
        self._temp_color = self.drawColor
        self._temp_number = self.drawnNumber
        self.setBrushColor(self.erasingColor)
        self.brushColorChanged.emit(self.erasingColor)
        self.setDrawnNumber(self.erasingNumber)

    def disableErasing(self):
        self.erasing = False
        self.setBrushColor(self._temp_color)
        self.brushColorChanged.emit(self.drawColor)
        self.setDrawnNumber(self._temp_number)

    def setBrushSize(self, size):
        self.brushSize = size
        self.brushSizeChanged.emit(self.brushSize)

    def setDrawnNumber(self, num):
        self.drawnNumber = num
        self.drawnNumberChanged.emit(num)

    def getBrushSize(self):
        return self.brushSize

    def brushSmaller(self):
        b = self.brushSize
        if b > self.minBrushSize:
            self.setBrushSize(b - 1)

    def brushBigger(self):
        b = self.brushSize
        if self.brushSize < self.maxBrushSize:
            self.setBrushSize(b + 1)

    def setBrushColor(self, color):
        self.drawColor = QColor(color)
        self.brushColorChanged.emit(self.drawColor)

    def beginDrawing(self, pos, sliceRect):
        """

        pos -- QPointF-like
        """
        self.sliceRect = sliceRect
        self.scene.clear()
        self.bb = QRect()
        self.pos = QPointF(pos.x(), pos.y())
        self._hasMoved = False

    def endDrawing(self, pos):
        has_moved = self._hasMoved  # _hasMoved will change after calling moveTo
        if has_moved:
            self.moveTo(pos)
        else:
            assert self.pos == pos
            self.moveTo(QPointF(pos.x() + 0.0001, pos.y() + 0.0001))  # move a little

        # Qt seems to use strange rules for determining which pixels to set when rendering a brush stroke to a QImage.
        # We seem to get better results if we do the following:
        # 1) Slightly offset the source window because apparently there is a small shift in the data
        # 2) Render the scene to an image that is MUCH larger than the scene resolution (4x by 4x)
        # 3) Downsample each 4x4 patch from the large image back to a single pixel in the final image,
        #     applying some threshold to determine if the final pixel is on or off.

        tempi = QImage(
            QSize(4 * self.bb.width(), 4 * self.bb.height()), QImage.Format_ARGB32_Premultiplied
        )  # TODO: format
        tempi.fill(0)
        painter = QPainter(tempi)
        # Offset the source window.  At first I thought the right offset was 0.5, because
        #  that would seem to make sure points are rounded to pixel CENTERS, but
        #  experimentation indicates that 0.25 is slightly better for some reason...
        source_rect = QRectF(QPointF(self.bb.x() + 0.25, self.bb.y() + 0.25), QSizeF(self.bb.width(), self.bb.height()))
        target_rect = QRectF(QPointF(0, 0), QSizeF(4 * self.bb.width(), 4 * self.bb.height()))
        self.scene.render(painter, target=target_rect, source=source_rect)
        painter.end()

        # Now downsample: convert each 4x4 patch into a single pixel by summing and dividing
        ndarr = qimage2ndarray.rgb_view(tempi)[:, :, 0].astype(int)
        ndarr = ndarr.reshape((ndarr.shape[0],) + (ndarr.shape[1] // 4,) + (4,))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr = ndarr.reshape((ndarr.shape[0],) + (ndarr.shape[1] // 4,) + (4,))
        ndarr = ndarr.sum(axis=-1)
        ndarr = ndarr.transpose()
        ndarr //= 4 * 4

        downsample_threshold = (7.0 / 16) * 255
        labels = numpy.where(ndarr >= downsample_threshold, numpy.uint8(self.drawnNumber), numpy.uint8(0))
        labels = labels.swapaxes(0, 1)
        assert labels.shape[0] == self.bb.width()
        assert labels.shape[1] == self.bb.height()

        ##
        ## ensure that at least one pixel is label when the brush size is 1
        ##
        ## this happens when the user just clicked without moving
        ## in that case the lineitem will be so tiny, that it won't be rendered
        ## into a single pixel by the code above
        if not has_moved and self.brushSize <= 1 and numpy.count_nonzero(labels) == 0:
            labels[labels.shape[0] // 2, labels.shape[1] // 2] = self.drawnNumber

        self.brushStrokeAvailable.emit(QPointF(self.bb.x(), self.bb.y()), labels)

    def dumpDraw(self, pos):
        res = self.endDrawing(pos)
        self.beginDrawing(pos, self.sliceRect)
        return res

    def moveTo(self, pos):
        # data coordinates
        oldX, oldY = self.pos.x(), self.pos.y()
        x, y = pos.x(), pos.y()

        line = QGraphicsLineItem(oldX, oldY, x, y)
        line.setPen(QPen(QBrush(Qt.white), self.brushSize, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        self.scene.addItem(line)
        self._hasMoved = True

        # update bounding Box
        if not self.bb.isValid():
            self.bb = QRect(QPoint(oldX, oldY), QSize(1, 1))
        # grow bounding box
        self.bb.setLeft(min(self.bb.left(), max(0, x - self.brushSize // 2 - 1)))
        self.bb.setRight(max(self.bb.right(), min(self.sliceRect[0] - 1, x + self.brushSize // 2 + 1)))
        self.bb.setTop(min(self.bb.top(), max(0, y - self.brushSize // 2 - 1)))
        self.bb.setBottom(max(self.bb.bottom(), min(self.sliceRect[1] - 1, y + self.brushSize // 2 + 1)))

        # update/move position
        self.pos = pos
Esempio n. 39
0
    def paint_smallicon_view(self, painter: QPainter) -> None:
        self.thumbnail_rect = QRect(0, 0, self.tile_rect.height(), self.tile_rect.height())

        font = self.style.font
        fm = self.style.fm

        painter.setFont(font)
        self.paint_thumbnail(painter)

        if self.zoom_index in [0, 1]:
            text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter)
            text_option.setWrapMode(QTextOption.NoWrap)
            text_rect = QRect(QPoint(self.tile_rect.height() + 4,
                                     0),
                              QPoint(self.tile_rect.width(),
                                     self.tile_rect.height()))
            text = self.fileinfo.basename()
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            painter.drawText(QRectF(text_rect),
                             text,
                             text_option)
        elif self.zoom_index in [2]:
            text_rect = QRect(QPoint(self.tile_rect.height() + 4,
                                     0),
                              QPoint(self.tile_rect.width() - 80,
                                     self.tile_rect.height()))
            text = self.fileinfo.basename()
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter)
            text_option.setWrapMode(QTextOption.NoWrap)
            painter.drawText(QRectF(text_rect), text, text_option)

            text_rect = QRect(QPoint(self.tile_rect.width() - 80,
                                     0),
                              QPoint(self.tile_rect.width(),
                                     self.tile_rect.height()))
            text = bytefmt.humanize(self.fileinfo.size())
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter)

            text_option.setWrapMode(QTextOption.NoWrap)
            painter.setPen(QColor(96, 96, 96))
            painter.drawText(QRectF(text_rect), text, text_option)
        else:
            top_left_text, top_right_text, bottom_left_text, bottom_right = self.make_text()

            row1_rect = QRect(QPoint(self.tile_rect.left() + self.tile_rect.height() + 8,
                                     self.tile_rect.top()),
                              QPoint(self.tile_rect.right() - 8,
                                     self.tile_rect.top() + self.tile_rect.height() / 2))
            row2_rect = QRect(QPoint(self.tile_rect.left() + self.tile_rect.height() + 8,
                                     self.tile_rect.top() + self.tile_rect.height() / 2),
                              QPoint(self.tile_rect.right() - 8,
                                     self.tile_rect.bottom()))

            # row 1
            text_rect = QRect(QPoint(row1_rect.left(),
                                     row1_rect.top()),
                              QPoint(row1_rect.right() - 80,
                                     row1_rect.bottom()))
            text = self.fileinfo.basename()
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter)
            text_option.setWrapMode(QTextOption.NoWrap)
            painter.drawText(QRectF(text_rect), text, text_option)

            text_rect = QRect(QPoint(row1_rect.left() - 80,
                                     row1_rect.top()),
                              QPoint(row1_rect.right(),
                                     row1_rect.bottom()))
            text = bytefmt.humanize(self.fileinfo.size())
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter)

            text_option.setWrapMode(QTextOption.NoWrap)
            painter.setPen(QColor(96, 96, 96))
            painter.drawText(QRectF(text_rect), text, text_option)

            # row 2
            text_rect = QRect(QPoint(row2_rect.left(),
                                     row2_rect.top()),
                              QPoint(row2_rect.right() - 80,
                                     row2_rect.bottom()))
            text = bottom_left_text
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            text_option = QTextOption(Qt.AlignLeft | Qt.AlignVCenter)
            text_option.setWrapMode(QTextOption.NoWrap)
            painter.drawText(QRectF(text_rect), text, text_option)

            text_rect = QRect(QPoint(row2_rect.left() - 80,
                                     row2_rect.top()),
                              QPoint(row2_rect.right(),
                                     row2_rect.bottom()))
            text = top_left_text
            text = fm.elidedText(text, Qt.ElideRight, text_rect.width())
            text_option = QTextOption(Qt.AlignRight | Qt.AlignVCenter)

            text_option.setWrapMode(QTextOption.NoWrap)
            painter.setPen(QColor(96, 96, 96))
            painter.drawText(QRectF(text_rect), text, text_option)
Esempio n. 40
0
class ResizeHelper(QWidget):
    offsetChanged = pyqtSignal(QPoint)
    offsetXChanged = pyqtSignal(int)
    offsetYChanged = pyqtSignal(int)
    offsetBoundsChanged = pyqtSignal(QRect)

    def __init__(self, parent = None):
        super().__init__(parent)
        
        self.mMouseAnchorPoint = QPoint()
        self.mOffset = QPoint()
        self.mOldSize = QSize()
        self.mDragging = False
        self.mOffsetBounds = QRect()
        self.mScale = 0.0
        self.mNewSize = QSize()
        self.mOrigOffset = QPoint()
        
        self.setMinimumSize(20, 20)
        self.setOldSize(QSize(1, 1))

    def oldSize(self):
        return self.mOldSize

    def newSize(self):
        return self.mNewSize

    def offset(self):
        return self.mOffset

    def offsetBounds(self):
        return self.mOffsetBounds

    def setOldSize(self, size):
        self.mOldSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setNewSize(self, size):
        self.mNewSize = size
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def setOffset(self, offset):
        # Clamp the offset within the offset bounds
        newOffset = QPoint(min(self.mOffsetBounds.right(),
                            max(self.mOffsetBounds.left(), offset.x())),
                                min(self.mOffsetBounds.bottom(),
                                    max(self.mOffsetBounds.top(), offset.y())))
        if (self.mOffset != newOffset):
            xChanged = self.mOffset.x() != newOffset.x()
            yChanged = self.mOffset.y() != newOffset.y()
            self.mOffset = newOffset
            if (xChanged):
                self.offsetXChanged.emit(self.mOffset.x())
            if (yChanged):
                self.offsetYChanged.emit(self.mOffset.y())
            self.offsetChanged.emit(self.mOffset)
            self.update()

    ## Method to set only the X offset, provided for convenience. */
    def setOffsetX(self, x):
        self.setOffset(QPoint(x, self.mOffset.y()))

    ## Method to set only the Y offset, provided for convenience. */
    def setOffsetY(self, y):
        self.setOffset(QPoint(self.mOffset.x(), y))

    ## Method to set only new width, provided for convenience. */
    def setNewWidth(self, width):
        self.mNewSize.setWidth(width)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    ## Method to set only new height, provided for convenience. */
    def setNewHeight(self, height):
        self.mNewSize.setHeight(height)
        self.recalculateMinMaxOffset()
        self.recalculateScale()

    def paintEvent(self, event):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        origX = (_size.width() - self.mNewSize.width() * self.mScale) / 2 + 0.5
        origY = (_size.height() - self.mNewSize.height() * self.mScale) / 2 + 0.5
        oldRect = QRect(self.mOffset, self.mOldSize)
        painter = QPainter(self)
        painter.translate(origX, origY)
        painter.scale(self.mScale, self.mScale)
        pen = QPen(Qt.black)
        pen.setCosmetic(True)
        painter.setPen(pen)
        painter.drawRect(QRect(QPoint(0, 0), self.mNewSize))
        pen.setColor(Qt.white)
        painter.setPen(pen)
        painter.setBrush(Qt.white)
        painter.setOpacity(0.5)
        painter.drawRect(oldRect)
        pen.setColor(Qt.black)
        pen.setStyle(Qt.DashLine)
        painter.setOpacity(1.0)
        painter.setBrush(Qt.NoBrush)
        painter.setPen(pen)
        painter.drawRect(oldRect)
        painter.end()

    def mousePressEvent(self, event):
        self.mMouseAnchorPoint = event.pos()
        self.mOrigOffset = self.mOffset
        self.mDragging = event.button() == Qt.LeftButton

    def mouseMoveEvent(self, event):
        if (not self.mDragging):
            return
        pos = event.pos()
        if (pos != self.mMouseAnchorPoint):
            self.setOffset(self.mOrigOffset + (pos - self.mMouseAnchorPoint) / self.mScale)
            self.offsetChanged.emit(self.mOffset)

    def resizeEvent(self, event):
        self.recalculateScale()

    def recalculateScale(self):
        _size = self.size() - QSize(2, 2)
        if (_size.isEmpty()):
            return
        if self.mOldSize.width() < self.mNewSize.width():
            width = self.mNewSize.width()
        else:
            width = 2 * self.mOldSize.width() - self.mNewSize.width()
        if self.mOldSize.height() < self.mNewSize.height():
            height = self.mNewSize.height()
        else:
            height = 2 * self.mOldSize.height() - self.mNewSize.height()

        # Pick the smallest scale
        scaleW = _size.width() / width
        scaleH = _size.height() / height
        if scaleW < scaleH:
            self.mScale = scaleW
        else:
            self.mScale = scaleH

        self.update()

    def recalculateMinMaxOffset(self):
        offsetBounds = self.mOffsetBounds
        if (self.mOldSize.width() <= self.mNewSize.width()):
            offsetBounds.setLeft(0)
            offsetBounds.setRight(self.mNewSize.width() - self.mOldSize.width())
        else:
            offsetBounds.setLeft(self.mNewSize.width() - self.mOldSize.width())
            offsetBounds.setRight(0)

        if (self.mOldSize.height() <= self.mNewSize.height()):
            offsetBounds.setTop(0)
            offsetBounds.setBottom(self.mNewSize.height() - self.mOldSize.height())
        else:
            offsetBounds.setTop(self.mNewSize.height() - self.mOldSize.height())
            offsetBounds.setBottom(0)

        if (self.mOffsetBounds != offsetBounds):
            self.mOffsetBounds = offsetBounds
            self.offsetBoundsChanged.emit(self.mOffsetBounds)
Esempio n. 41
0
    def updateBrush(self, cursorPos, _list = None):
        # get the current tile layer
        currentLayer = self.currentTileLayer()
        layerWidth = currentLayer.width()
        layerHeight = currentLayer.height()
        numTiles = layerWidth * layerHeight
        paintCorner = 0
        # if we are in vertex paint mode, the bottom right corner on the map will appear as an invalid tile offset...
        if (self.mBrushMode == BrushMode.PaintVertex):
            if (cursorPos.x() == layerWidth):
                cursorPos.setX(cursorPos.x() - 1)
                paintCorner |= 1

            if (cursorPos.y() == layerHeight):
                cursorPos.setY(cursorPos.y() - 1)
                paintCorner |= 2

        # if the cursor is outside of the map, bail out
        if (not currentLayer.bounds().contains(cursorPos)):
            return
        terrainTileset = None
        terrainId = -1
        if (self.mTerrain):
            terrainTileset = self.mTerrain.tileset()
            terrainId = self.mTerrain.id()

        # allocate a buffer to build the terrain tilemap (TODO: this could be retained per layer to save regular allocation)
        newTerrain = []
        for i in range(numTiles):
            newTerrain.append(0)
            
        # allocate a buffer of flags for each tile that may be considered (TODO: this could be retained per layer to save regular allocation)
        checked = array('B')
        for i in range(numTiles):
            checked.append(0)
        # create a consideration list, and push the start points
        transitionList = QList()
        initialTiles = 0
        if (_list):
            # if we were supplied a list of start points
            for p in _list:
                transitionList.append(p)
                initialTiles += 1

        else:
            transitionList.append(cursorPos)
            initialTiles = 1

        brushRect = QRect(cursorPos, cursorPos)
        # produce terrain with transitions using a simple, relative naive approach (considers each tile once, and doesn't allow re-consideration if selection was bad)
        while (not transitionList.isEmpty()):
            # get the next point in the consideration list
            p = transitionList.takeFirst()
            x = p.x()
            y = p.y()
            i = y*layerWidth + x
            # if we have already considered this point, skip to the next
            # TODO: we might want to allow re-consideration if prior tiles... but not for now, this would risk infinite loops
            if (checked[i]):
                continue
            tile = currentLayer.cellAt(p).tile
            currentTerrain = terrain(tile)
            # get the tileset for this tile
            tileset = None
            if (terrainTileset):
                # if we are painting a terrain, then we'll use the terrains tileset
                tileset = terrainTileset
            elif (tile):
                # if we're erasing terrain, use the individual tiles tileset (to search for transitions)
                tileset = tile.tileset()
            else:
                # no tile here and we're erasing terrain, not much we can do
                continue

            # calculate the ideal tile for this position
            preferredTerrain = 0xFFFFFFFF
            mask = 0
            if (initialTiles):
                # for the initial tiles, we will insert the selected terrain and add the surroundings for consideration
                if (self.mBrushMode == BrushMode.PaintTile):
                    # set the whole tile to the selected terrain
                    preferredTerrain = makeTerrain(terrainId)
                    mask = 0xFFFFFFFF
                else:
                    # Bail out if encountering a tile from a different tileset
                    if (tile and tile.tileset() != tileset):
                        continue
                    # calculate the corner mask
                    mask = 0xFF << (3 - paintCorner)*8
                    # mask in the selected terrain
                    preferredTerrain = (currentTerrain & ~mask) | (terrainId << (3 - paintCorner)*8)

                initialTiles -= 1
                # if there's nothing to paint... skip this tile
                if (preferredTerrain == currentTerrain and (not tile or tile.tileset() == tileset)):
                    continue
            else:
                # Bail out if encountering a tile from a different tileset
                if (tile and tile.tileset() != tileset):
                    continue
                # following tiles each need consideration against their surroundings
                preferredTerrain = currentTerrain
                mask = 0
                # depending which connections have been set, we update the preferred terrain of the tile accordingly
                if (y > 0 and checked[i - layerWidth]):
                    preferredTerrain = ((terrain(newTerrain[i - layerWidth]) << 16) | (preferredTerrain & 0x0000FFFF))&0xFFFFFFFF
                    mask |= 0xFFFF0000

                if (y < layerHeight - 1 and checked[i + layerWidth]):
                    preferredTerrain = ((terrain(newTerrain[i + layerWidth]) >> 16) | (preferredTerrain & 0xFFFF0000))&0xFFFFFFFF
                    mask |= 0x0000FFFF

                if (x > 0 and checked[i - 1]):
                    preferredTerrain = (((terrain(newTerrain[i - 1]) << 8) & 0xFF00FF00) | (preferredTerrain & 0x00FF00FF))&0xFFFFFFFF
                    mask |= 0xFF00FF00

                if (x < layerWidth - 1 and checked[i + 1]):
                    preferredTerrain = (((terrain(newTerrain[i + 1]) >> 8) & 0x00FF00FF) | (preferredTerrain & 0xFF00FF00))&0xFFFFFFFF
                    mask |= 0x00FF00FF

            # find the most appropriate tile in the tileset
            paste = None
            if (preferredTerrain != 0xFFFFFFFF):
                paste = findBestTile(tileset, preferredTerrain, mask)
                if (not paste):
                    continue

            # add tile to the brush
            newTerrain[i] = paste
            checked[i] = True
            # expand the brush rect to fit the edit set
            brushRect |= QRect(p, p)
            # consider surrounding tiles if terrain constraints were not satisfied
            if (y > 0 and not checked[i - layerWidth]):
                above = currentLayer.cellAt(x, y - 1).tile
                if (topEdge(paste) != bottomEdge(above)):
                    transitionList.append(QPoint(x, y - 1))

            if (y < layerHeight - 1 and not checked[i + layerWidth]):
                below = currentLayer.cellAt(x, y + 1).tile
                if (bottomEdge(paste) != topEdge(below)):
                    transitionList.append(QPoint(x, y + 1))

            if (x > 0 and not checked[i - 1]):
                left = currentLayer.cellAt(x - 1, y).tile
                if (leftEdge(paste) != rightEdge(left)):
                    transitionList.append(QPoint(x - 1, y))

            if (x < layerWidth - 1 and not checked[i + 1]):
                right = currentLayer.cellAt(x + 1, y).tile
                if (rightEdge(paste) != leftEdge(right)):
                    transitionList.append(QPoint(x + 1, y))

        # create a stamp for the terrain block
        stamp = TileLayer(QString(), brushRect.left(), brushRect.top(), brushRect.width(), brushRect.height())
        for y in range(brushRect.top(), brushRect.bottom()+1):
            for x in range(brushRect.left(), brushRect.right()+1):
                i = y*layerWidth + x
                if (not checked[i]):
                    continue
                tile = newTerrain[i]
                if (tile):
                    stamp.setCell(x - brushRect.left(), y - brushRect.top(), Cell(tile))
                else:
                    # TODO: we need to do something to erase tiles where checked[i] is True, and newTerrain[i] is NULL
                    # is there an eraser stamp? investigate how the eraser works...
                    pass

        # set the new tile layer as the brush
        self.brushItem().setTileLayer(stamp)
        del checked
        del newTerrain
        self.mPaintX = cursorPos.x()
        self.mPaintY = cursorPos.y()
        self.mOffsetX = cursorPos.x() - brushRect.left()
        self.mOffsetY = cursorPos.y() - brushRect.top()
Esempio n. 42
0
class corkDelegate(QStyledItemDelegate):
    def __init__(self, parent=None):
        QStyledItemDelegate.__init__(self, parent)
        self.factor = settings.corkSizeFactor / 100.
        self.defaultSize = QSize(300, 200)
        self.lastPos = None
        self.editing = None
        self.margin = 5

    def setCorkSizeFactor(self, v):
        self.factor = v / 100.

    def sizeHint(self, option, index):
        return self.defaultSize * self.factor

    def editorEvent(self, event, model, option, index):
        # We catch the mouse position in the widget to know which part to edit
        if type(event) == QMouseEvent:
            self.lastPos = event.pos()  # - option.rect.topLeft()
        return QStyledItemDelegate.editorEvent(self, event, model, option, index)

    def createEditor(self, parent, option, index):
        self.updateRects(option, index)

        if self.mainLineRect.contains(self.lastPos):
            # One line summary
            self.editing = Outline.summarySentance
            edt = QLineEdit(parent)
            edt.setFocusPolicy(Qt.StrongFocus)
            edt.setFrame(False)
            edt.setAlignment(Qt.AlignCenter)
            edt.setPlaceholderText(self.tr("One line summary"))
            f = QFont(option.font)
            f.setItalic(True)
            edt.setFont(f)
            return edt

        elif self.titleRect.contains(self.lastPos):
            # Title
            self.editing = Outline.title
            edt = QLineEdit(parent)
            edt.setFocusPolicy(Qt.StrongFocus)
            edt.setFrame(False)
            f = QFont(option.font)
            # f.setPointSize(f.pointSize() + 1)
            f.setBold(True)
            edt.setFont(f)
            edt.setAlignment(Qt.AlignCenter)
            # edt.setGeometry(self.titleRect)
            return edt

        else:  # self.mainTextRect.contains(self.lastPos):
            # Summary
            self.editing = Outline.summaryFull
            edt = QPlainTextEdit(parent)
            edt.setFocusPolicy(Qt.StrongFocus)
            edt.setFrameShape(QFrame.NoFrame)
            edt.setPlaceholderText(self.tr("Full summary"))
            return edt

    def updateEditorGeometry(self, editor, option, index):

        if self.editing == Outline.summarySentance:
            # One line summary
            editor.setGeometry(self.mainLineRect)

        elif self.editing == Outline.title:
            # Title
            editor.setGeometry(self.titleRect)

        elif self.editing == Outline.summaryFull:
            # Summary
            editor.setGeometry(self.mainTextRect)

    def setEditorData(self, editor, index):
        item = index.internalPointer()

        if self.editing == Outline.summarySentance:
            # One line summary
            editor.setText(item.data(Outline.summarySentance.value))

        elif self.editing == Outline.title:
            # Title
            editor.setText(index.data())

        elif self.editing == Outline.summaryFull:
            # Summary
            editor.setPlainText(item.data(Outline.summaryFull.value))

    def setModelData(self, editor, model, index):

        if self.editing == Outline.summarySentance:
            # One line summary
            model.setData(index.sibling(index.row(), Outline.summarySentance.value), editor.text())

        elif self.editing == Outline.title:
            # Title
            model.setData(index, editor.text(), Outline.title.value)

        elif self.editing == Outline.summaryFull:
            # Summary
            model.setData(index.sibling(index.row(), Outline.summaryFull.value), editor.toPlainText())

    def updateRects(self, option, index):
        margin = self.margin
        iconSize = max(16 * self.factor, 12)
        item = index.internalPointer()
        self.itemRect = option.rect.adjusted(margin, margin, -margin, -margin)
        self.iconRect = QRect(self.itemRect.topLeft() + QPoint(margin, margin), QSize(iconSize, iconSize))
        self.labelRect = QRect(self.itemRect.topRight() - QPoint(iconSize + margin, 0),
                               self.itemRect.topRight() + QPoint(0, iconSize + 2 * margin))
        self.titleRect = QRect(self.iconRect.topRight() + QPoint(margin, 0),
                               self.labelRect.bottomLeft() - QPoint(margin, margin))
        self.bottomRect = QRect(QPoint(self.itemRect.x(), self.iconRect.bottom() + margin),
                                QPoint(self.itemRect.right(), self.itemRect.bottom()))
        self.topRect = QRect(self.itemRect.topLeft(), self.bottomRect.topRight())
        self.mainRect = self.bottomRect.adjusted(margin, margin, -margin, -margin)
        self.mainLineRect = QRect(self.mainRect.topLeft(),
                                  self.mainRect.topRight() + QPoint(0, iconSize))
        self.mainTextRect = QRect(self.mainLineRect.bottomLeft() + QPoint(0, margin),
                                  self.mainRect.bottomRight())
        if not item.data(Outline.summarySentance.value):
            self.mainTextRect.setTopLeft(self.mainLineRect.topLeft())
        if item.data(Outline.label.value) in ["", "0"]:
            self.titleRect.setBottomRight(self.labelRect.bottomRight() - QPoint(self.margin, self.margin))

    def paint(self, p, option, index):
        # QStyledItemDelegate.paint(self, p, option, index)
        if not index.isValid():
            return

        item = index.internalPointer()
        self.updateRects(option, index)
        colors = outlineItemColors(item)

        style = qApp.style()

        def _rotate(angle):
            p.translate(self.mainRect.center())
            p.rotate(angle)
            p.translate(-self.mainRect.center())

        # Draw background
        cg = QPalette.ColorGroup(QPalette.Normal if option.state & QStyle.State_Enabled else QPalette.Disabled)
        if cg == QPalette.Normal and not option.state & QStyle.State_Active:
            cg = QPalette.Inactive

            # Selection
        if option.state & QStyle.State_Selected:
            p.save()
            p.setBrush(option.palette.brush(cg, QPalette.Highlight))
            p.setPen(Qt.NoPen)
            p.drawRoundedRect(option.rect, 12, 12)
            p.restore()

            # Stack
        if item.isFolder() and item.childCount() > 0:
            p.save()
            p.setBrush(Qt.white)
            for i in reversed(range(3)):
                p.drawRoundedRect(self.itemRect.adjusted(2 * i, 2 * i, -2 * i, 2 * i), 10, 10)

            p.restore()

            # Background
        itemRect = self.itemRect
        p.save()
        if settings.viewSettings["Cork"]["Background"] != "Nothing":
            c = colors[settings.viewSettings["Cork"]["Background"]]
            col = mixColors(c, QColor(Qt.white), .2)
            p.setBrush(col)
        else:
            p.setBrush(Qt.white)
        pen = p.pen()
        pen.setWidth(2)
        p.setPen(pen)
        p.drawRoundedRect(itemRect, 10, 10)
        p.restore()

        # Title bar
        topRect = self.topRect
        p.save()
        if item.isFolder():
            color = QColor(Qt.darkGreen)
        else:
            color = QColor(Qt.blue).lighter(175)
        p.setPen(Qt.NoPen)
        p.setBrush(color)
        p.setClipRegion(QRegion(topRect))
        p.drawRoundedRect(itemRect, 10, 10)
        # p.drawRect(topRect)
        p.restore()

        # Label color
        if settings.viewSettings["Cork"]["Corner"] != "Nothing":
            p.save()
            color = colors[settings.viewSettings["Cork"]["Corner"]]
            p.setPen(Qt.NoPen)
            p.setBrush(color)
            p.setClipRegion(QRegion(self.labelRect))
            p.drawRoundedRect(itemRect, 10, 10)
            # p.drawRect(topRect)
            p.restore()
            p.drawLine(self.labelRect.topLeft(), self.labelRect.bottomLeft())

            # One line summary background
        lineSummary = item.data(Outline.summarySentance.value)
        fullSummary = item.data(Outline.summaryFull.value)
        if lineSummary or not fullSummary:
            m = self.margin
            r = self.mainLineRect.adjusted(-m, -m, m, m / 2)
            p.save()
            p.setPen(Qt.NoPen)
            p.setBrush(QColor("#EEE"))
            p.drawRect(r)
            p.restore()

            # Border
        p.save()
        p.setBrush(Qt.NoBrush)
        pen = p.pen()
        pen.setWidth(2)
        if settings.viewSettings["Cork"]["Border"] != "Nothing":
            col = colors[settings.viewSettings["Cork"]["Border"]]
            if col == Qt.transparent:
                col = Qt.black
            pen.setColor(col)
        p.setPen(pen)
        p.drawRoundedRect(itemRect, 10, 10)
        p.restore()

        # Draw the icon
        iconRect = self.iconRect
        mode = QIcon.Normal
        if not option.state & style.State_Enabled:
            mode = QIcon.Disabled
        elif option.state & style.State_Selected:
            mode = QIcon.Selected
        # index.data(Qt.DecorationRole).paint(p, iconRect, option.decorationAlignment, mode)
        icon = index.data(Qt.DecorationRole).pixmap(iconRect.size())
        if settings.viewSettings["Cork"]["Icon"] != "Nothing":
            color = colors[settings.viewSettings["Cork"]["Icon"]]
            colorifyPixmap(icon, color)
        QIcon(icon).paint(p, iconRect, option.decorationAlignment, mode)

        # Draw title
        p.save()
        text = index.data()
        titleRect = self.titleRect
        if text:
            if settings.viewSettings["Cork"]["Text"] != "Nothing":
                col = colors[settings.viewSettings["Cork"]["Text"]]
                if col == Qt.transparent:
                    col = Qt.black
                p.setPen(col)
            f = QFont(option.font)
            # f.setPointSize(f.pointSize() + 1)
            f.setBold(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(text, Qt.ElideRight, titleRect.width())
            p.drawText(titleRect, Qt.AlignCenter, elidedText)
        p.restore()

        # Draw the line
        bottomRect = self.bottomRect
        p.save()
        # p.drawLine(itemRect.x(), iconRect.bottom() + margin,
        # itemRect.right(), iconRect.bottom() + margin)
        p.drawLine(bottomRect.topLeft(), bottomRect.topRight())
        p.restore()

        # Lines
        if True:
            p.save()
            p.setPen(QColor("#EEE"))
            fm = QFontMetrics(option.font)
            h = fm.lineSpacing()
            l = self.mainTextRect.topLeft() + QPoint(0, h)
            while self.mainTextRect.contains(l):
                p.drawLine(l, QPoint(self.mainTextRect.right(), l.y()))
                l.setY(l.y() + h)
            p.restore()

        # Draw status
        mainRect = self.mainRect
        status = item.data(Outline.status.value)
        if status:
            it = mainWindow().mdlStatus.item(int(status), 0)
            if it != None:
                p.save()
                p.setClipRegion(QRegion(mainRect))
                f = p.font()
                f.setPointSize(f.pointSize() + 12)
                f.setBold(True)
                p.setFont(f)
                p.setPen(QColor(Qt.red).lighter(175))
                _rotate(-35)
                p.drawText(mainRect, Qt.AlignCenter, it.text())
                p.restore()

                # Draw Summary
                # One line
        if lineSummary:
            p.save()
            f = QFont(option.font)
            f.setItalic(True)
            p.setFont(f)
            fm = QFontMetrics(f)
            elidedText = fm.elidedText(lineSummary, Qt.ElideRight, self.mainLineRect.width())
            p.drawText(self.mainLineRect, Qt.AlignCenter, elidedText)
            p.restore()

            # Full summary
        if fullSummary:
            p.setFont(option.font)
            p.drawText(self.mainTextRect, Qt.TextWordWrap, fullSummary)