示例#1
0
def text_size(text, font: QFont) -> 'SizeF':
    font_metrics = QFontMetrics(font)

    lines = text.split('\n')
    width = max(map(font_metrics.width, lines))
    height = font_metrics.height() * len(lines)
    return SizeF(width, height)
示例#2
0
def strRect(s, fontMetrics: QtGui.QFontMetrics):
    #baseWidth = fontMetrics.boundingRect(s).width()
    baseWidth = fontMetrics.horizontalAdvance(s)
    sWidth = baseWidth  # - fontMetrics.leftBearing(s[0])
    #sWidth -= fontMetrics.rightBearing(s[-1])
    r = QtCore.QRect(0, 0, sWidth, fontMetrics.height())
    return r
示例#3
0
 def setModelData(self, editor: '_IntervalWidget',
                  model: QAbstractItemModel, index: QModelIndex) -> None:
     datetimes: List[QDateTime]
     datetimes, byDate, byTime = editor.getOptions()
     # Do some validation
     errors = list()
     if len(datetimes) < 2:
         errors.append(('e1', 'Error: at least one range must be defined'))
     if any([a >= b for a, b in zip(datetimes, datetimes[1:])]):
         errors.append(
             ('e2', 'Error: datetime points must be strictly increasing'))
     if errors:
         editor.handleErrors(errors)
         # Avoid setting options and leave editor open
         return
     options = ([
         pd.Timestamp(date.toPython(), tz='UTC') for date in datetimes
     ], byDate, byTime)
     model.setData(index, options, Qt.EditRole)
     # Resize rows. This assumes that the TableView is the delegate parent
     f = QFontMetrics(QFont())
     rowHeight = f.height() * len(options[0])
     table: QTableView = self.parent()
     table.setRowHeight(index.row(), rowHeight)
     # Close editor. Works because it's the delegate that tells the view to close it with this signal
     self.closeEditor.emit(self.w, QStyledItemDelegate.NoHint)
示例#4
0
class ApolloGroupHeading(QWidget):
    def __init__(self, parent, text, *args, **kwargs):
        super().__init__(parent, *args, **kwargs)
        self.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed)

        self.text = text
        self.font_metrics = QFontMetrics(self.font())
        self.text_width = self.font_metrics.width(self.text)
        self.text_height = self.font_metrics.height()

    def sizeHint(self):
        return QSize(self.text_width, self.text_height)

    def paintEvent(self, event):
        p = QPainter(self)

        left_edge = self.width() // 2 - self.text_width // 2
        right_edge = self.width() // 2 + self.text_width // 2

        p.drawText(left_edge, self.text_height, self.text)

        x0 = 0
        x1 = left_edge - 4
        x2 = right_edge + 4
        x3 = self.width() - 1
        y0 = self.height() // 2 + 2
        y1 = self.height()

        p.drawLine(x0, y0, x1, y0)
        p.drawLine(x2, y0, x3, y0)
        p.drawLine(x0, y0, x0, y1)
        p.drawLine(x3, y0, x3, y1)

        p.end()
示例#5
0
    def setFont(self, qFont):
        qFont.setStyleHint(QFont.Monospace)
        qFont.setFixedPitch(True)
        fontMetrics = QFontMetrics(qFont)
        self.setTabStopWidth(self.__tabStop * fontMetrics.width(' '))
        self.__lineHeight = fontMetrics.height() * self.__lineHeightMultiplier

        super().setFont(qFont)
        self.__setLineHeight()
    def drawHeader(self):
        """Draw logo/copyright in the header"""
        pHeight = 90
        pMargin = 15
        icon_path = cm.DIR_ICONS + "app.png"

        self.header_lbl.setMinimumHeight(pHeight)
        self.header_lbl.setFrameShape(QFrame.StyledPanel)
        self.header_lbl.setContentsMargins(0, 0, 0, 0)

        pixmap = QPixmap(450, pHeight)
        pixmap.fill(Qt.transparent)

        iconY = (pHeight - 64) / 2
        logoRect = QRect(pMargin, iconY, 64, 64)

        painter = QPainter(pixmap)
        painter.setBrush(QBrush(Qt.red))
        painter.drawPixmap(
            logoRect,
            QPixmap(icon_path).scaled(
                logoRect.width(),
                logoRect.height(),
                Qt.KeepAspectRatio,
                Qt.SmoothTransformation,
            ),
        )

        titleRect = QRect(logoRect.right() + 10, iconY, 200, pHeight)

        font = QFont()
        font.setBold(True)
        font.setPixelSize(16)
        painter.setFont(font)
        painter.setPen(QPen(QApplication.instance().palette().text().color()))
        painter.drawText(titleRect, Qt.AlignTop, "Cutevariant")

        font_metrics = QFontMetrics(font)
        font.setBold(False)
        font.setPixelSize(12)
        painter.setFont(font)
        painter.setPen(QPen(Qt.darkGray))
        titleRect.setY(titleRect.y() + font_metrics.height())

        painter.drawText(
            titleRect,
            Qt.AlignTop,
            f"Version %s\nGPL3 Copyright (C) 2018-2020\nLabsquare.org" % __version__,
        )

        self.header_lbl.setPixmap(pixmap)

        # Painting is finished !
        # Avoid Segfault:
        # QPaintDevice: Cannot destroy paint device that is being painted
        painter.end()
示例#7
0
 def __init__(self, text, position, attachment_point, *args, **kwargs):
     super(TextItem, self).__init__(*args, **kwargs)
     self.text = text
     self.angle = kwargs.pop('angle')
     self.position = position
     self.font = QFont('Arial', 5)
     metrics = QFontMetrics(self.font)
     self.w = metrics.width(self.text)
     self.h = metrics.height()
     self.attachment_point = attachment_point
示例#8
0
    def text_changed(self):
        t = self.toPlainText()
        fm = QFontMetrics(self.font())
        text_width = fm.width(self.get_longest_line(t))
        text_width = text_width+25
        text_height = fm.height()*(t.count('\n')+1)+12
        self.setFixedWidth(text_width if text_width > self.base_width else self.base_width)
        self.setFixedHeight(text_height if text_height > self.base_height else self.base_height)

        self.parent_node_instance.update_shape()
    def add_item(self, item_str: str):
        """
        向导航栏中添加项目(代表一个选项卡),添加之前会查重
        :param item_str:项目名称(显示出来的文字)
        :return:None
        """
        if not item_str:
            return

        for key, value in self._m_item_maps.items():
            if value[0] == item_str:
                return  # 如果存在同名item,则返回

        f = QFont()
        f.setPointSize(self._m_item_font_size)
        fm = QFontMetrics(f)

        text_width = fm.width(item_str)
        text_height = fm.height()
        item_count = len(self._m_item_maps)
        if item_count > 0:
            if self._m_orientation == Qt.Horizontal:
                top_left = QPointF(self._m_total_text_width, 0)
                self._m_total_text_width += text_width + self._m_space
                bottom_right = QPointF(self._m_total_text_width, self._m_total_text_height)
            else:
                top_left = QPointF(0, self._m_total_text_height)
                self._m_total_text_height += text_height + self._m_space
                bottom_right = QPointF(self._m_total_text_width, self._m_total_text_height)

            self._m_item_maps[item_count] = [item_str, QRectF(top_left, bottom_right)]
        else:
            if self._m_orientation == Qt.Horizontal:
                # 水平方向,水平各占1个space, 竖直占1个space
                self._m_total_text_width = text_width + self._m_space
                self._m_total_text_height = text_height + self._m_space
            else:
                # 竖直方向, 水平各占2个space, 竖直占一个space
                self._m_total_text_width = text_width + 2 * self._m_space
                self._m_total_text_height = text_height + self._m_space

            top_left = QPointF(0.0, 0.0)
            bottom_right = QPointF(self._m_total_text_width, self._m_total_text_height)
            self._m_item_maps[item_count] = [item_str, QRectF(top_left, bottom_right)]
        self.setMinimumSize(self._m_total_text_width, self._m_total_text_height)

        if self._m_fixed:
            if self._m_orientation == Qt.Horizontal:
                self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)  # 固定高度
            else:
                self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)  # 固定宽度
        if len(self._m_item_maps):
            self._m_start_rect = QRectF(self._m_item_maps[0][1])
        self.update()
示例#10
0
文件: ui.py 项目: ramesharun/caribou
    def __init__(self, parameter):
        super().__init__()
        metrics = QFontMetrics(TEXT_FONT)
        self.min_height = metrics.height()
        self.setFont(TEXT_FONT)

        self.default_text = parameter.default
        self.textChanged.connect(self.on_update)

        self.highlighter = JSONHighlighter(self.document())
        self.setText(parameter.default)
示例#11
0
    def resize_to_content(self, lines):
        if len(lines) == 0:
            lines.append('')

        # resize properly
        fm = QFontMetrics(self.font())
        text_width = fm.width(lines[0]+'__')
        text_width = text_width+20  # some buffer
        text_height = fm.height()*(len(lines))+12  # also some vertical buffer
        self.setFixedWidth(text_width if text_width > self.base_width else self.base_width)
        self.setFixedHeight(text_height if text_height > self.base_height else self.base_height)
        self.parent_node_instance.update_shape()
示例#12
0
 def createDropTextPixmap(self):
     pixmap = QPixmap(481, 300)
     pixmap.fill(QColor("#333333"))
     painter = QPainter(pixmap)
     font = QFont("Arial")
     font.setPixelSize(28)
     font.setBold(True)
     fm = QFontMetrics(font)
     painter.setFont(font)
     painter.setPen(QPen(QColor("#888888"), 1))
     text = "Drop the tileset image here"
     x = (pixmap.width()-fm.width(text))/2
     y = (pixmap.height()+fm.height())/2
     painter.drawText(x, y, text)
     del painter
     return pixmap
示例#13
0
文件: gui.py 项目: menshiva/ascii-art
    def compute_art_layout_size(self) -> Tuple[int, int]:
        """
        Computes the size of art_layout which prints ASCII art.

        Returns:
            Pair of art_layout's width and height.
        """

        art_width = int(self.__get_property(self.__art_layout, "width").read())
        art_height = int(
            self.__get_property(self.__art_layout, "height").read())
        fm = QFontMetrics(
            self.__get_property(self.__art_layout, "font").read())
        char_width = art_width // fm.averageCharWidth()
        char_height = art_height // fm.height()
        return char_width, char_height
示例#14
0
    def paintEvent(self, event):
        sineTable = [
            0, 38, 71, 92, 100, 92, 71, 38, 0, -38, -71, -92, -100, -92, -71,
            -38
        ]

        metrics = QFontMetrics(self.font())
        x = (self.width() - metrics.horizontalAdvance(self.text)) / 2
        y = (self.height() + metrics.ascent() - metrics.descent()) / 2
        color = QColor()

        painter = QPainter(self)
        for i in range(len(self.text)):
            index = (self.step + i) % 16
            color.setHsv((15 - index) * 16, 255, 191)
            painter.setPen(color)
            painter.drawText(x,
                             y - ((sineTable[index] * metrics.height()) / 400),
                             str(self.text[i]))
            x += metrics.horizontalAdvance(self.text[i])
    def _adjust_item_size(self) -> None:
        """
        调整Item大小
        :return:
        """

        if self._m_fixed:
            return

        item_count = len(self._m_item_maps)

        if self._m_orientation == Qt.Horizontal:
            add_width = 1.0 * (self.width() - self._m_total_text_width) / item_count
            add_height = 1.0 * (self.height() - self._m_total_text_height)
        else:
            add_width = 1.0 * (self.width() - self._m_total_text_width)
            add_height = 1.0 * (self.height() - self._m_total_text_height) / item_count

        dx = dy = 0.0
        for key, value in self._m_item_maps.items():
            # f = QFont()
            fm = QFontMetrics(self._m_item_font)
            text_width = fm.width(value[0])
            text_height = fm.height()
            if self._m_orientation == Qt.Horizontal:
                topLeft = QPointF(dx, 0)
                dx += text_width + self._m_space + add_width
                dy = self._m_total_text_height + add_height
            else:
                topLeft = QPointF(0, dy)
                dx = self._m_total_text_width + add_width
                dy += text_height + self._m_space + add_height

            bottomRight = QPointF(dx, dy)
            text_rect = QRectF(topLeft, bottomRight)
            self._m_item_maps[key] = [value[0], QRectF(text_rect)]
            if key == self._m_current_index:
                self._m_start_rect = text_rect
                self._m_stop_rect = text_rect

        self.update()
示例#16
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)
        # options
        self.options = None
        # exposure slider
        self.sliderExp = QbLUeSlider(Qt.Horizontal)
        self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderExp.setRange(-20, 20)
        self.sliderExp.setSingleStep(1)

        expLabel = QbLUeLabel()
        expLabel.setMaximumSize(150, 30)
        expLabel.setText("Exposure Correction")
        expLabel.doubleClicked.connect(
            lambda: self.sliderExp.setValue(self.defaultExpCorrection))

        self.expValue = QbLUeLabel()
        font = self.expValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.expValue.setMinimumSize(w, h)
        self.expValue.setMaximumSize(w, h)

        # exp change/released slot
        def f():
            self.expValue.setText(
                str("{:+.1f}".format(self.sliderExp.value() *
                                     self.defaultStep)))
            if self.sliderExp.isSliderDown() or (self.expCorrection
                                                 == self.sliderExp.value() *
                                                 self.defaultStep):
                return
            try:
                self.sliderExp.valueChanged.disconnect()
                self.sliderExp.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.expCorrection = self.sliderExp.value() * self.defaultStep
            self.dataChanged.emit()
            self.sliderExp.valueChanged.connect(f)
            self.sliderExp.sliderReleased.connect(f)

        self.sliderExp.valueChanged.connect(f)
        self.sliderExp.sliderReleased.connect(f)

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        l.addWidget(expLabel)
        hl = QHBoxLayout()
        hl.addWidget(self.expValue)
        hl.addWidget(self.sliderExp)
        l.addLayout(hl)
        l.setContentsMargins(20, 0, 20, 25)  # left, top, right, bottom
        self.setLayout(l)
        self.adjustSize()
        self.setWhatsThis("""<b>Exposure Correction</b>
                        Multiplicative correction in the linear sRGB color space.<br>
                        Unit is the diaphragm stop.<br>
                        """)  # end setWhatsThis

        self.setDefaults()
示例#17
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)
        # connect layer selectionChanged signal
        self.layer.selectionChanged.sig.connect(self.updateLayer)
        self.kernelCategory = filterIndex.UNSHARP
        # options
        self.optionList = [
            'Unsharp Mask', 'Sharpen', 'Gaussian Blur', 'Surface Blur'
        ]
        filters = [
            filterIndex.UNSHARP, filterIndex.SHARPEN, filterIndex.BLUR1,
            filterIndex.SURFACEBLUR
        ]
        self.filterDict = dict(
            zip(self.optionList,
                filters))  # filters is not a dict: don't use UDict here

        self.listWidget1 = optionsWidget(options=self.optionList,
                                         exclusive=True,
                                         changed=self.dataChanged)
        # set initial selection to unsharp mask
        self.listWidget1.checkOption(self.optionList[0])

        # sliders
        self.sliderRadius = QbLUeSlider(Qt.Horizontal)
        self.sliderRadius.setRange(1, 50)
        self.sliderRadius.setSingleStep(1)
        self.radiusLabel = QLabel()
        self.radiusLabel.setMaximumSize(150, 30)
        self.radiusLabel.setText("Radius")

        self.radiusValue = QLabel()
        font = self.radiusValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.radiusValue.setMinimumSize(w, h)
        self.radiusValue.setMaximumSize(w, h)

        self.sliderAmount = QbLUeSlider(Qt.Horizontal)
        self.sliderAmount.setRange(0, 100)
        self.sliderAmount.setSingleStep(1)
        self.amountLabel = QLabel()
        self.amountLabel.setMaximumSize(150, 30)
        self.amountLabel.setText("Amount")
        self.amountValue = QLabel()
        font = self.radiusValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.amountValue.setMinimumSize(w, h)
        self.amountValue.setMaximumSize(w, h)

        self.toneValue = QLabel()
        self.toneLabel = QLabel()
        self.toneLabel.setMaximumSize(150, 30)
        self.toneLabel.setText("Sigma")
        self.sliderTone = QbLUeSlider(Qt.Horizontal)
        self.sliderTone.setRange(0, 100)
        self.sliderTone.setSingleStep(1)
        font = self.radiusValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.toneValue.setMinimumSize(w, h)
        self.toneValue.setMaximumSize(w, h)

        # value change/done slot
        def formUpdate():
            self.radiusValue.setText(str('%d ' % self.sliderRadius.value()))
            self.amountValue.setText(str('%d ' % self.sliderAmount.value()))
            self.toneValue.setText(str('%d ' % self.sliderTone.value()))
            if self.sliderRadius.isSliderDown(
            ) or self.sliderAmount.isSliderDown(
            ) or self.sliderTone.isSliderDown():
                return
            try:
                for slider in [
                        self.sliderRadius, self.sliderAmount, self.sliderTone
                ]:
                    slider.valueChanged.disconnect()
                    slider.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.tone = self.sliderTone.value()
            self.radius = self.sliderRadius.value()
            self.amount = self.sliderAmount.value()
            self.dataChanged.emit()
            for slider in [
                    self.sliderRadius, self.sliderAmount, self.sliderTone
            ]:
                slider.valueChanged.connect(formUpdate)
                slider.sliderReleased.connect(formUpdate)

        for slider in [self.sliderRadius, self.sliderAmount, self.sliderTone]:
            slider.valueChanged.connect(formUpdate)
            slider.sliderReleased.connect(formUpdate)

        # layout
        l = QVBoxLayout()
        l.addWidget(self.listWidget1)
        hl = QHBoxLayout()
        hl.addWidget(self.radiusLabel)
        hl.addWidget(self.radiusValue)
        hl.addWidget(self.sliderRadius)
        l.addLayout(hl)
        hl = QHBoxLayout()
        hl.addWidget(self.amountLabel)
        hl.addWidget(self.amountValue)
        hl.addWidget(self.sliderAmount)
        l.addLayout(hl)
        hl = QHBoxLayout()
        hl.addWidget(self.toneLabel)
        hl.addWidget(self.toneValue)
        hl.addWidget(self.sliderTone)
        l.addLayout(hl)
        l.setContentsMargins(20, 0, 20, 25)  # left, top, right, bottom
        self.setLayout(l)

        self.setDefaults()
        self.setWhatsThis("""
                       <b>Unsharp Mask</b> and <b>Sharpen Mask</b> are used to sharpen an image.
                       Unsharp Mask usually gives best results.<br>
                       <b>Gaussian Blur</b> and <b>Surface Blur</b> are used to blur an image.<br>
                       In contrast to Gaussian Blur, Surface Blur preserves edges and reduces noise,
                       but it may be slow.<br>
                       It is possible to <b>limit the effect of a filter to a rectangular region of the image</b> by
                       drawing a selection rectangle on the layer with the marquee (rectangle) tool.<br>
                       Ctrl Click <b>clears the selection</b><br>
                       
                    """)  # end setWhatsThis
示例#18
0
    def __init__(self, parent):
        super().__init__(parent)
        self.img = None
        # graphic form to show : it
        # should correspond to the currently selected layer
        self.currentWin = None
        # mouse click event
        self.clicked.connect(self.viewClicked)

        # set behavior and styles
        self.setSelectionBehavior(QAbstractItemView.SelectRows)
        delegate = itemDelegate(parent=self)
        self.setItemDelegate(delegate)
        ic1 = QImage(":/images/resources/eye-icon.png")
        ic2 = QImage(":/images/resources/eye-icon-strike.png")
        delegate.px1 = QPixmap.fromImage(ic1)
        delegate.px2 = QPixmap.fromImage(ic2)
        ic1.invertPixels()
        ic2.invertPixels()
        delegate.inv_px1 = QPixmap.fromImage(ic1)
        delegate.inv_px2 = QPixmap.fromImage(ic2)
        self.setIconSize(QSize(20, 15))
        self.verticalHeader().setMinimumSectionSize(-1)
        self.verticalHeader().setDefaultSectionSize(
            self.verticalHeader().minimumSectionSize())
        self.horizontalHeader().setMinimumSectionSize(40)
        self.horizontalHeader().setDefaultSectionSize(40)

        # drag and drop
        self.setDragDropMode(QAbstractItemView.DragDrop)
        self.setDefaultDropAction(Qt.MoveAction)
        self.setDragDropOverwriteMode(False)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDropIndicatorShown(True)

        ################################
        # layer property GUI :
        # preview, blending mode, opacity, mask color
        ################################
        # Preview option
        # We should use a QListWidget or a custom optionsWidget
        # (cf. utils.py) :  adding it to QVBoxLayout with mode
        # Qt.AlignBottom does not work.
        self.previewOptionBox = QCheckBox('Preview')
        self.previewOptionBox.setMaximumSize(100, 30)

        # View/Preview changed slot
        def m(state):  # state : Qt.Checked Qt.UnChecked
            if self.img is None:
                return
            useThumb = (state == Qt.Checked)
            if useThumb == self.img.useThumb:
                return
            self.img.useThumb = useThumb
            window.updateStatus()
            self.img.cacheInvalidate()
            try:
                QApplication.setOverrideCursor(
                    Qt.WaitCursor
                )  # TODO 18/04/18 waitcursor already called by applytostack
                QApplication.processEvents()
                # update the whole stack
                self.img.layersStack[0].applyToStack()
                self.img.onImageChanged()
            finally:
                QApplication.restoreOverrideCursor()
                QApplication.processEvents()

        self.previewOptionBox.stateChanged.connect(m)
        self.previewOptionBox.setChecked(True)  # m is not triggered

        # title
        titleLabel = QLabel('Layer')
        titleLabel.setMaximumSize(100, 30)

        # opacity slider
        self.opacitySlider = QbLUeSlider(Qt.Horizontal)
        self.opacitySlider.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.opacitySlider.setTickPosition(QSlider.TicksBelow)
        self.opacitySlider.setRange(0, 100)
        self.opacitySlider.setSingleStep(1)
        self.opacitySlider.setSliderPosition(100)

        self.opacityValue = QLabel()
        font = self.opacityValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100 ")
        h = metrics.height()
        self.opacityValue.setMinimumSize(w, h)
        self.opacityValue.setMaximumSize(w, h)
        self.opacityValue.setText('100 ')

        # opacity value changed event handler
        def f1():
            self.opacityValue.setText(str('%d ' % self.opacitySlider.value()))

        # opacity slider released event handler
        def f2():
            try:
                layer = self.img.getActiveLayer()
                layer.setOpacity(self.opacitySlider.value())
                layer.applyToStack()
                self.img.onImageChanged()
            except AttributeError:
                return

        self.opacitySlider.valueChanged.connect(f1)
        self.opacitySlider.sliderReleased.connect(f2)

        # mask color slider
        self.maskLabel = QLabel('Mask Color')
        maskSlider = QbLUeSlider(Qt.Horizontal)
        maskSlider.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        maskSlider.setTickPosition(QSlider.TicksBelow)
        maskSlider.setRange(0, 100)
        maskSlider.setSingleStep(1)
        maskSlider.setSliderPosition(100)
        self.maskSlider = maskSlider

        self.maskValue = QLabel()
        font = self.maskValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100 ")
        h = metrics.height()
        self.maskValue.setMinimumSize(w, h)
        self.maskValue.setMaximumSize(w, h)
        self.maskValue.setText('100 ')
        # masks are disbled by default
        self.maskLabel.setEnabled(False)
        self.maskSlider.setEnabled(False)
        self.maskValue.setEnabled(False)

        # mask value changed event handler
        def g1():
            self.maskValue.setText(str('%d ' % self.maskSlider.value()))

        # mask slider released event handler
        def g2():
            try:
                layer = self.img.getActiveLayer()
                layer.setColorMaskOpacity(self.maskSlider.value() * 255.0 /
                                          100.0)
                layer.applyToStack()
                self.img.onImageChanged()
            except AttributeError:
                return

        self.maskSlider.valueChanged.connect(g1)
        self.maskSlider.sliderReleased.connect(g2)

        # blending mode combo box
        compLabel = QLabel()
        compLabel.setText("Blend")

        self.compositionModeDict = OrderedDict([
            ('Normal', QPainter.CompositionMode_SourceOver),
            ('Plus', QPainter.CompositionMode_Plus),
            ('Multiply', QPainter.CompositionMode_Multiply),
            ('Screen', QPainter.CompositionMode_Screen),
            ('Overlay', QPainter.CompositionMode_Overlay),
            ('Darken', QPainter.CompositionMode_Darken),
            ('Lighten', QPainter.CompositionMode_Lighten),
            ('Color Dodge', QPainter.CompositionMode_ColorDodge),
            ('Color Burn', QPainter.CompositionMode_ColorBurn),
            ('Hard Light', QPainter.CompositionMode_HardLight),
            ('Soft Light', QPainter.CompositionMode_SoftLight),
            ('Difference', QPainter.CompositionMode_Difference),
            ('Exclusion', QPainter.CompositionMode_Exclusion),
            # Type of previous modes is QPainter.CompositionMode (Shiboken enum-type).
            # Next additional modes are not implemented by QPainter:
            ('Luminosity', -1),
            ('color', -2)
        ])

        self.blendingModeCombo = QComboBox()
        for key in self.compositionModeDict:
            self.blendingModeCombo.addItem(key, self.compositionModeDict[key])

        # combo box item changed slot
        def g(ind):
            layer = self.img.getActiveLayer()
            s = self.blendingModeCombo.currentText()
            newMode = self.compositionModeDict[str(s)]
            if newMode == layer.compositionMode:
                return
            layer.compositionMode = newMode
            layer.applyToStack()
            self.img.onImageChanged()

        self.blendingModeCombo.currentIndexChanged.connect(g)

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        hl0 = QHBoxLayout()
        hl0.addWidget(titleLabel)
        hl0.addStretch(1)
        hl0.addWidget(self.previewOptionBox)
        l.addLayout(hl0)
        hl = QHBoxLayout()
        hl.addWidget(QLabel('Opacity'))
        hl.addWidget(self.opacityValue)
        hl.addWidget(self.opacitySlider)
        l.addLayout(hl)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.maskLabel)
        hl1.addWidget(self.maskValue)
        hl1.addWidget(self.maskSlider)
        l.addLayout(hl1)
        l.setContentsMargins(0, 0, 10, 0)  # left, top, right, bottom
        hl2 = QHBoxLayout()
        hl2.addWidget(compLabel)
        hl2.addWidget(self.blendingModeCombo)
        l.addLayout(hl2)
        for layout in [hl, hl1, hl2]:
            layout.setContentsMargins(5, 0, 0, 0)
        # this layout must be added to the propertyWidget object loaded from blue.ui :
        # we postpone it to in blue.py, after loading the main form.
        self.propertyLayout = l
        # shortcut actions
        self.actionDup = QAction('Duplicate layer', None)
        self.actionDup.setShortcut(QKeySequence(Qt.CTRL + Qt.Key_J))
        self.addAction(self.actionDup)

        def dup():
            row = self.selectedIndexes()[0].row()
            # Stack index
            index = len(self.img.layersStack) - row - 1
            layer = self.img.layersStack[index]
            if layer.isAdjustLayer():
                return
            # add new layer to stack and set it to active
            self.img.dupLayer(index=index)
            # update layer view
            self.setLayers(self.img)

        self.actionDup.triggered.connect(dup)
        self.setWhatsThis("""<b>Layer Stack</b><br>
To <b>toggle the layer visibility</b> click on the Eye icon.<br>
To <b>add a mask</b> use the context menu to enable it and paint pixels with the Mask/Unmask tools in the left pane.<br>
For <b>color mask<b/b>: <br>
    &nbsp; green pixels are masked,<br>
    &nbsp; red pixels are unmasked.<br>
    &nbsp; Other colors correspond to partially masked pixels.<br>
Note that upper visible layers slow down mask edition.<br>
""")  # end of setWhatsThis
示例#19
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)
        self.setMinimumSize(axeSize, axeSize+100)
        # contrast spline viewer
        self.contrastForm = None
        # options
        optionList1, optionNames1 = ['Multi-Mode', 'CLAHE'], ['Multi-Mode', 'CLAHE']
        self.listWidget1 = optionsWidget(options=optionList1, optionNames=optionNames1, exclusive=True,
                                         changed=lambda: self.dataChanged.emit())
        self.listWidget1.checkOption(self.listWidget1.intNames[0])
        self.listWidget1.setStyleSheet("QListWidget {border: 0px;} QListWidget::item {border: 0px; padding-left: 0px;}")
        optionList2, optionNames2 = ['High', 'manualCurve'], ['Preserve Highlights', 'Show Contrast Curve']

        def optionList2Change(item):
            if item.internalName == 'High':
                # force to recalculate the spline
                self.layer.autoSpline = True
            self.dataChanged.emit()
        self.listWidget2 = optionsWidget(options=optionList2, optionNames=optionNames2, exclusive=False,
                                         changed=optionList2Change)
        self.listWidget2.checkOption(self.listWidget2.intNames[0])
        self.listWidget2.setStyleSheet("QListWidget {border: 0px;} QListWidget::item {border: 0px; padding-left: 0px;}")
        self.options = UDict((self.listWidget1.options, self.listWidget2.options))

        # contrast slider
        self.sliderContrast = QbLUeSlider(Qt.Horizontal)
        self.sliderContrast.setStyleSheet(QbLUeSlider.bLueSliderDefaultIBWStylesheet)
        self.sliderContrast.setRange(0, 10)
        self.sliderContrast.setSingleStep(1)

        contrastLabel = QbLUeLabel()
        contrastLabel.setMaximumSize(150, 30)
        contrastLabel.setText("Contrast Level")
        contrastLabel.doubleClicked.connect(lambda: self.sliderContrast.setValue(self.contrast2Slider(self.contrastDefault)))

        self.contrastValue = QLabel()
        font = self.contrastValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.contrastValue.setMinimumSize(w, h)
        self.contrastValue.setMaximumSize(w, h)
        self.contrastValue.setText(str("{:d}".format(self.sliderContrast.value())))

        # contrast changed  event handler.
        def contrastUpdate(value):
            self.contrastValue.setText(str("{:d}".format(self.sliderContrast.value())))
            # move not yet terminated or value not modified
            if self.sliderContrast.isSliderDown() or self.slider2Contrast(value) == self.contrastCorrection:
                return
            self.sliderContrast.valueChanged.disconnect()
            self.sliderContrast.sliderReleased.disconnect()
            self.contrastCorrection = self.slider2Contrast(self.sliderContrast.value())
            # force to recalculate the spline
            self.layer.autoSpline = True
            self.dataChanged.emit()
            self.sliderContrast.valueChanged.connect(contrastUpdate)
            self.sliderContrast.sliderReleased.connect(lambda: contrastUpdate(self.sliderContrast.value()))

        self.sliderContrast.valueChanged.connect(contrastUpdate)
        self.sliderContrast.sliderReleased.connect(lambda: contrastUpdate(self.sliderContrast.value()))

        # saturation slider
        self.sliderSaturation = QbLUeSlider(Qt.Horizontal)
        self.sliderSaturation.setStyleSheet(QbLUeSlider.bLueSliderDefaultColorStylesheet)
        self.sliderSaturation.setRange(0, 100)
        self.sliderSaturation.setSingleStep(1)

        saturationLabel = QbLUeLabel()
        saturationLabel.setMaximumSize(150, 30)
        saturationLabel.setText("Saturation")
        saturationLabel.doubleClicked.connect(lambda: self.sliderSaturation.setValue(self.saturation2Slider(self.saturationDefault)))

        self.saturationValue = QLabel()
        font = self.saturationValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.saturationValue.setMinimumSize(w, h)
        self.saturationValue.setMaximumSize(w, h)
        self.saturationValue.setText(str("{:+d}".format(self.sliderContrast.value())))

        # saturation changed  event handler
        def saturationUpdate(value):
            self.saturationValue.setText(str("{:+d}".format(int(self.slidersaturation2User(self.sliderSaturation.value())))))
            # move not yet terminated or value not modified
            if self.sliderSaturation.isSliderDown() or self.slider2Saturation(value) == self.satCorrection:
                return
            self.sliderSaturation.valueChanged.disconnect()
            self.sliderSaturation.sliderReleased.disconnect()
            self.satCorrection = self.slider2Saturation(self.sliderSaturation.value())
            self.dataChanged.emit()
            self.sliderSaturation.valueChanged.connect(saturationUpdate)
            self.sliderSaturation.sliderReleased.connect(lambda: saturationUpdate(self.sliderSaturation.value()))
        self.sliderSaturation.valueChanged.connect(saturationUpdate)
        self.sliderSaturation.sliderReleased.connect(lambda: saturationUpdate(self.sliderSaturation.value()))

        # brightness slider
        self.sliderBrightness = QbLUeSlider(Qt.Horizontal)
        self.sliderBrightness.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderBrightness.setRange(0, 100)
        self.sliderBrightness.setSingleStep(1)

        brightnessLabel = QbLUeLabel()
        brightnessLabel.setMaximumSize(150, 30)
        brightnessLabel.setText("Brightness")
        brightnessLabel.doubleClicked.connect(lambda: self.sliderBrightness.setValue(self.brightness2Slider(self.brightnessDefault)))

        self.brightnessValue = QLabel()
        font = self.brightnessValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.brightnessValue.setMinimumSize(w, h)
        self.brightnessValue.setMaximumSize(w, h)
        self.brightnessValue.setText(str("{:+d}".format(self.sliderContrast.value())))

        # brightness changed  event handler
        def brightnessUpdate(value):
            self.brightnessValue.setText(str("{:+d}".format(int(self.sliderBrightness2User(self.sliderBrightness.value())))))
            # move not yet terminated or value not modified
            if self.sliderBrightness.isSliderDown() or self.slider2Brightness(value) == self.brightnessCorrection:
                return
            self.sliderBrightness.valueChanged.disconnect()
            self.sliderBrightness.sliderReleased.disconnect()
            self.brightnessCorrection = self.slider2Brightness(self.sliderBrightness.value())
            self.dataChanged.emit()
            self.sliderBrightness.valueChanged.connect(brightnessUpdate)
            self.sliderBrightness.sliderReleased.connect(lambda: brightnessUpdate(self.sliderBrightness.value()))

        self.sliderBrightness.valueChanged.connect(brightnessUpdate)
        self.sliderBrightness.sliderReleased.connect(lambda: brightnessUpdate(self.sliderBrightness.value()))

        # attributes initialized in setDefaults, declared here
        # for the sake of correctness
        self.contrastCorrection = None    # range
        self.satCorrection = None         # range -0.5..0.5
        self.brightnessCorrection = None  # range -0.5..0.5

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        gb1 = QGroupBox()
        gb1.setStyleSheet("QGroupBox {border: 1px solid gray; border-radius: 4px}")
        l1 = QVBoxLayout()
        ct = QLabel()
        ct.setText('Contrast')
        l.setAlignment(Qt.AlignTop)
        l1.addWidget(ct)
        l1.addWidget(self.listWidget1)
        gb1.setLayout(l1)
        l.addWidget(gb1)
        l.addWidget(self.listWidget2)
        l.addWidget(contrastLabel)
        hl = QHBoxLayout()
        hl.addWidget(self.contrastValue)
        hl.addWidget(self.sliderContrast)
        l.addLayout(hl)
        l.addWidget(brightnessLabel)
        hl3 = QHBoxLayout()
        hl3.addWidget(self.brightnessValue)
        hl3.addWidget(self.sliderBrightness)
        l.addLayout(hl3)
        l.addWidget(saturationLabel)
        hl2 = QHBoxLayout()
        hl2.addWidget(self.saturationValue)
        hl2.addWidget(self.sliderSaturation)
        l.addLayout(hl2)
        self.setLayout(l)
        self.adjustSize()
        self.setStyleSheet("QListWidget, QLabel {font : 7pt;}")
        self.setDefaults()
        self.setWhatsThis(
            """<b>Contrast Brightness Saturation</b><br>
            <b>Contrast</b> is enhanced using one of these two methods:<br>
              - <b>CLAHE</b> : increases the local contrast.<br>
              - <b>Multi-Mode</b> : increases the local contrast and the contrast between regions of the image.<br>
            For both methods the contrast slider controls the level of the correction.<br>
            With Multi-Mode enabled, use the option <b>Show Contrast Curve</b> to edit the correction curve and check
            <b>Preserve Highlights</b> for softer highlights.<br>
            <b>Brightness</b> and <b>Saturation</b> corrections are non linear to limit clipping.<br>
            Sliders are <b>reset</b> to their default value by double clicking the name of the slider.<br>
            """
                        )  # end setWhatsThis
示例#20
0
    def __init__(self, axeSize=500, layer=None, parent=None):
        super(noiseForm, self).__init__(parent=parent)
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setMinimumSize(axeSize, axeSize)
        self.setAttribute(Qt.WA_DeleteOnClose)
        # link back to image layer
        # using weak ref for back links
        if type(layer) in weakref.ProxyTypes:
            self.layer = layer
        else:
            self.layer = weakref.proxy(layer)
        # attribute initialized in setDefaults
        # defined here for the sake of correctness
        self.noiseCorrection = 0

        # options
        optionList = ['Wavelets', 'Bilateral', 'NLMeans']
        self.listWidget1 = optionsWidget(
            options=optionList,
            exclusive=True,
            changed=lambda: self.dataChanged.emit(True))
        self.listWidget1.checkOption(self.listWidget1.intNames[0])
        self.options = self.listWidget1.options

        # threshold slider
        self.sliderThr = QbLUeSlider(Qt.Horizontal)
        self.sliderThr.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderThr.setTickPosition(QSlider.TicksBelow)
        self.sliderThr.setRange(0, 10)
        self.sliderThr.setSingleStep(1)

        self.sliderThr.valueChanged.connect(self.thrUpdate)
        self.sliderThr.sliderReleased.connect(lambda: self.thrUpdate(
            self.sliderThr.value()))  # signal has no parameter)

        self.thrLabel = QLabel()
        self.thrLabel.setMaximumSize(150, 30)
        self.thrLabel.setText("level")

        self.thrValue = QLabel()
        font = self.thrValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.thrValue.setMinimumSize(w, h)
        self.thrValue.setMaximumSize(w, h)
        self.thrValue.setText(
            str("{:.0f}".format(self.slider2Thr(self.sliderThr.value()))))
        # self.dataChanged.connect(self.updateLayer)
        # self.setStyleSheet("QListWidget, QLabel {font : 7pt;}")
        # layout
        l = QVBoxLayout()
        #l.setAlignment(Qt.AlignBottom)
        l.addWidget(self.listWidget1)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.thrLabel)
        hl1.addWidget(self.thrValue)
        hl1.addWidget(self.sliderThr)
        l.addLayout(hl1)
        l.setContentsMargins(20, 0, 20, 25)  # left, top, right, bottom
        #l.setContentsMargins(10, 10, 10, 10)  # left, top, right, bottom
        self.setLayout(l)
        self.adjustSize()
        self.setDefaults()
        self.setWhatsThis("""<b>Noise Reduction</b><br>
   <b>Bilateral Filtering</b> is the fastest method.<br>
   <b>NLMeans</b> (Non Local Means) and <b>Wavelets</b> are slower,
   but they usually give better results.<br>
   It is possible to <b>limit the application of all methods to a rectangular region of the image</b>
   by drawing a selection rectangle on the layer with the marquee tool.<br>
   Ctrl-Click to <b>clear the selection</b><br>
   
""")  # end of setWhatsThis
示例#21
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(targetImage=targetImage,
                         axeSize=axeSize,
                         layer=layer,
                         parent=parent)
        graphicsScene = self.scene()
        # connect layer selectionChanged signal
        self.layer.selectionChanged.sig.connect(self.updateLayer)
        # Init curves
        dSplineItem = activeBSpline(axeSize,
                                    period=axeSize,
                                    yZero=-3 * axeSize // 4)
        graphicsScene.addItem(dSplineItem)
        dSplineItem.setVisible(True)
        dSplineItem.initFixedPoints()
        self.dSplineItemB = dSplineItem
        graphicsScene.dSplineItemB = dSplineItem
        text = graphicsScene.addText('Hue (0-360)')
        text.setDefaultTextColor(Qt.white)
        text.setPos(-40, 10)
        text = graphicsScene.addText('delta H')
        text.setDefaultTextColor(Qt.white)
        text.setPos(-40, -self.axeSize // 4)
        text = graphicsScene.addText('delta B')
        text.setDefaultTextColor(Qt.white)
        text.setPos(-40, -(self.axeSize * 3) // 4)

        dSplineItem = activeBSpline(axeSize,
                                    period=axeSize,
                                    yZero=-axeSize // 4)
        graphicsScene.addItem(dSplineItem)
        dSplineItem.setVisible(True)
        dSplineItem.initFixedPoints()
        self.dSplineItemH = dSplineItem
        graphicsScene.dSplineItemH = dSplineItem

        # init 3D LUT
        self.LUT = DeltaLUT3D((34, 32, 32))

        self.marker = activeMarker.fromTriangle(parent=self.dSplineItemB)
        self.marker.setPos(0, 0)  # -(axeSize * 3) // 4)
        self.marker.setMoveRange(QRect(0, 0, axeSize, 0))
        self.scene().addItem(self.marker)

        def showPos(e, x, y):
            self.markerLabel.setText("%d" % (x * 360 // axeSize))

        self.marker.onMouseMove = showPos

        self.markerLabel = QLabel()
        font = self.markerLabel.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.markerLabel.setMinimumSize(w, h)
        self.markerLabel.setMaximumSize(w, h)

        self.sliderSat = QbLUeSlider(Qt.Horizontal)
        self.sliderSat.setMinimumWidth(200)

        def satUpdate(value):
            self.satValue.setText(str("{:d}".format(value)))
            # move not yet terminated or values not modified
            if self.sliderSat.isSliderDown() or value == self.satThr:
                return
            try:
                self.sliderSat.valueChanged.disconnect()
                self.sliderSat.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.satThr = value
            self.dataChanged.emit()
            self.sliderSat.valueChanged.connect(satUpdate)
            self.sliderSat.sliderReleased.connect(
                lambda: satUpdate(self.sliderSat.value()))

        self.sliderSat.valueChanged.connect(satUpdate)
        self.sliderSat.sliderReleased.connect(
            lambda: satUpdate(self.sliderSat.value()))

        self.satValue = QLabel()
        font = self.markerLabel.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.satValue.setMinimumSize(w, h)
        self.satValue.setMaximumSize(w, h)

        # layout
        gl = QGridLayout()
        gl.addWidget(QLabel('Hue '), 0, 0)
        gl.addWidget(self.markerLabel, 0, 1)
        gl.addWidget(QLabel('Sat Thr '), 1, 0)
        gl.addWidget(self.satValue, 1, 1)
        gl.addWidget(self.sliderSat, 1, 2, 4, 1)
        self.addCommandLayout(gl)

        self.setDefaults()

        self.setWhatsThis("""<b>3D LUT Shift HSV</b><br>
            All pixel colors are changed by the specific hue and brightness shifts corresponding to their hue.<br>
            x-axis represents hue values from 0 to 360. 
            The upper curve shows brightness multiplicative shifts (initially 1) and
            the lower curve hue additive shifts (initially 0). <br>
            Each curve is controlled by bump triangles.<br>
            To <b>add a bump triangle</b> to the curve click anywhere on the curve.
            To <b>remove the triangle</b> click on any vertex.<br>
            Drag the triangle vertices to move the bump along the x-axis and to change 
            its height and orientation. Use the <b> Sat Thr</b> slider 
            to preserve low saturated colors.<br>
            To <b>set the Hue Value Marker</b> Ctrl+click on the image.<br>
            To limit the shift corrections to a region of the image select the desired area
            with the rectangular marquee tool.<br>
            <b>Zoom</b> the curves with the mouse wheel.<br>
            """)
示例#22
0
    def paint(self, painter: QPainter, option: QStyleOptionViewItem,
              index: QModelIndex):
        """Apply graphical formatting to each item in each displayed column in the view"""
        brush = QBrush()
        pen = QPen()
        font = QFont()

        if option.state & QStyle.State_Selected:
            text_color = option.palette.color(QPalette.Normal,
                                              QPalette.BrightText)
        else:
            text_color = option.palette.color(QPalette.Normal, QPalette.Text)

        is_selected = option.state & QStyle.State_Selected

        # Default theme color
        pen.setColor(text_color)

        field_name = self.field_name(index).lower()
        value = self.value(index)

        # Colour bases (default color is the one of the current theme)
        if (field_name == "ref"
                or field_name == "alt") and (value in ("A", "C", "G", "T")
                                             and not is_selected):
            pen.setColor(
                self.BASE_COLOR.get(value,
                                    option.palette.color(QPalette.WindowText)))

        if field_name == "impact" and not is_selected:
            font.setBold(True)
            pen.setColor(
                self.IMPACT_COLOR.get(value, self.IMPACT_COLOR["MODIFIER"]))

        if field_name == "gene" and not is_selected:
            pen.setColor("#6a9fca")

        if field_name == "classification":
            icon = self.ACMG_ICON.get(str(value), self.ACMG_ICON["0"])
            self.draw_icon(painter, option.rect, icon)
            return

        if field_name == "favorite":
            icon = self.FAV_ICON.get(int(value), self.FAV_ICON[0])
            self.draw_icon(painter, option.rect, icon)
            return

        if field_name == "hgvs_c":
            font.setBold(True)
            m = re.search(r"([cnm]\..+)", str(value))
            if m:
                value = m.group(1)

        if field_name == "hgvs_p":
            font.setBold(True)
            m = re.search(r"(p\..+)", str(value))
            if m:
                value = m.group(1)

        if re.match(r"sample\[.+\]\.gt", field_name):
            icon = self.GENOTYPE_ICONS.get(int(value), self.GENOTYPE_ICONS[-1])
            self.draw_icon(painter, option.rect, icon)
            return

        if field_name == "consequence":
            values = str(self.value(index)).split("&")
            metrics = QFontMetrics(font)
            x = option.rect.x() + 5
            # y = option.rect.center().y()
            for value in values:
                width = metrics.width(value)
                height = metrics.height()
                rect = QRect(x, 0, width + 15, height + 10)
                rect.moveCenter(option.rect.center())
                rect.moveLeft(x)
                painter.setFont(font)
                painter.setClipRect(option.rect, Qt.IntersectClip)
                painter.setBrush(
                    QBrush(QColor(self.SO_COLOR.get(value, "#90d4f7"))))
                painter.setPen(Qt.NoPen)
                painter.drawRoundedRect(rect, 3, 3)
                painter.setPen(QPen(QColor("white")))
                painter.drawText(rect, Qt.AlignCenter | Qt.AlignVCenter, value)
                x += width + 20
                painter.setClipping(False)

            return

        if field_name == "rsid":
            self.draw_url(painter, option.rect, value,
                          QUrl("http://www.google.fr"), index)
            return

        painter.setBrush(brush)
        painter.setPen(pen)
        painter.setFont(font)
        painter.drawText(option.rect, option.displayAlignment, value)
示例#23
0
    def __init__(self,
                 targetImage=None,
                 axeSize=500,
                 layer=None,
                 parent=None,
                 mainForm=None):
        super().__init__(parent=parent)
        defaultRadius = 10
        defaultTone = 100.0
        defaultAmount = 50.0
        self.radius = defaultRadius
        self.tone = defaultTone
        self.amount = defaultAmount
        self.targetImage = targetImage
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setMinimumSize(axeSize, axeSize)
        self.setAttribute(Qt.WA_DeleteOnClose)
        self.img = targetImage
        # link back to image layer
        self.layer = weakProxy(layer)
        """
        # using weak ref for back links
        if type(layer) in weakref.ProxyTypes:
            self.layer = layer
        else:
            self.layer = weakref.proxy(layer)
        """
        self.mainForm = mainForm
        self.kernelCategory = filterIndex.UNSHARP

        # options
        self.optionList = [
            'Unsharp Mask', 'Sharpen', 'Gaussian Blur', 'Surface Blur'
        ]
        filters = [
            filterIndex.UNSHARP, filterIndex.SHARPEN, filterIndex.BLUR1,
            filterIndex.SURFACEBLUR
        ]
        self.filterDict = dict(zip(self.optionList, filters))

        self.listWidget1 = optionsWidget(options=self.optionList,
                                         exclusive=True,
                                         changed=self.dataChanged)
        # set initial selection to unsharp mask
        item = self.listWidget1.checkOption(self.optionList[0])

        # sliders
        self.sliderRadius = QbLUeSlider(Qt.Horizontal)
        #self.sliderRadius.setTickPosition(QSlider.TicksBelow)
        self.sliderRadius.setRange(1, 50)
        self.sliderRadius.setSingleStep(1)
        self.radiusLabel = QLabel()
        self.radiusLabel.setMaximumSize(150, 30)
        self.radiusLabel.setText("Radius")

        self.radiusValue = QLabel()
        font = self.radiusValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.radiusValue.setMinimumSize(w, h)
        self.radiusValue.setMaximumSize(w, h)

        self.sliderAmount = QbLUeSlider(Qt.Horizontal)
        #self.sliderAmount.setTickPosition(QSlider.TicksBelow)
        self.sliderAmount.setRange(0, 100)
        self.sliderAmount.setSingleStep(1)
        self.amountLabel = QLabel()
        self.amountLabel.setMaximumSize(150, 30)
        self.amountLabel.setText("Amount")
        self.amountValue = QLabel()
        font = self.radiusValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.amountValue.setMinimumSize(w, h)
        self.amountValue.setMaximumSize(w, h)

        self.toneValue = QLabel()
        self.toneLabel = QLabel()
        self.toneLabel.setMaximumSize(150, 30)
        self.toneLabel.setText("Sigma")
        self.sliderTone = QbLUeSlider(Qt.Horizontal)
        #self.sliderTone.setTickPosition(QSlider.TicksBelow)
        self.sliderTone.setRange(0, 100)
        self.sliderTone.setSingleStep(1)
        font = self.radiusValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.toneValue.setMinimumSize(w, h)
        self.toneValue.setMaximumSize(w, h)

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignBottom)
        l.addWidget(self.listWidget1)
        hl = QHBoxLayout()
        hl.addWidget(self.radiusLabel)
        hl.addWidget(self.radiusValue)
        hl.addWidget(self.sliderRadius)
        l.addLayout(hl)
        hl = QHBoxLayout()
        hl.addWidget(self.amountLabel)
        hl.addWidget(self.amountValue)
        hl.addWidget(self.sliderAmount)
        l.addLayout(hl)
        hl = QHBoxLayout()
        hl.addWidget(self.toneLabel)
        hl.addWidget(self.toneValue)
        hl.addWidget(self.sliderTone)
        l.addLayout(hl)
        l.setContentsMargins(20, 0, 20, 25)  # left, top, right, bottom
        self.setLayout(l)

        # value changed event handler
        def sliderUpdate():
            self.radiusValue.setText(str('%d ' % self.sliderRadius.value()))
            self.amountValue.setText(str('%d ' % self.sliderAmount.value()))
            self.toneValue.setText(str('%d ' % self.sliderTone.value()))

        # value done event handler
        def formUpdate():
            sR, sA, sT = self.sliderRadius.isEnabled(
            ), self.sliderAmount.isEnabled(), self.sliderTone.isEnabled()
            self.sliderRadius.setEnabled(False)
            self.sliderAmount.setEnabled(False)
            self.sliderTone.setEnabled(False)
            self.tone = self.sliderTone.value()
            self.radius = self.sliderRadius.value()
            self.amount = self.sliderAmount.value()
            sliderUpdate()
            self.dataChanged.emit()
            self.sliderRadius.setEnabled(sR)
            self.sliderAmount.setEnabled(sA)
            self.sliderTone.setEnabled(sT)

        self.sliderRadius.valueChanged.connect(sliderUpdate)
        self.sliderRadius.sliderReleased.connect(formUpdate)
        self.sliderAmount.valueChanged.connect(sliderUpdate)
        self.sliderAmount.sliderReleased.connect(formUpdate)
        self.sliderTone.valueChanged.connect(sliderUpdate)
        self.sliderTone.sliderReleased.connect(formUpdate)

        self.dataChanged.connect(self.updateLayer)
        # init
        self.sliderRadius.setValue(defaultRadius)
        self.sliderAmount.setValue(defaultAmount)
        self.sliderTone.setValue(defaultTone)
        self.enableSliders()
        sliderUpdate()
        self.setWhatsThis("""
   <b>Unsharp Mask</b> and <b>Sharpen Mask</b> are used to sharpen an image.<br>
   <b>Gaussian Blur</b> and <b>Surface Blur</b> are used to blur an image.<br>
   In contrast to Gaussian Blur, Surface Blur preserves edges and reduces noise.<br>
   It is possible to <b>limit the effect of a filter to a rectangular region of the image</b> by
   drawing a selection rectangle on the layer with the marquee tool.<br>
   Ctrl-Click to <b>clear the selection</b><br>
   
""")  # end setWhatsThis
示例#24
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)
        self.tempCorrection = 6500
        self.tintCorrection = 1.0
        self.defaultTemp = sRGBWP  # ref temperature D65
        self.defaultTint = 0

        # options
        optionList, optionNames = ['Photo Filter', 'Chromatic Adaptation'
                                   ], ['Photo Filter', 'Chromatic Adaptation']
        self.listWidget1 = optionsWidget(
            options=optionList,
            optionNames=optionNames,
            exclusive=True,
            changed=lambda: self.dataChanged.emit())
        self.listWidget1.checkOption(self.listWidget1.intNames[1])
        self.options = self.listWidget1.options

        # temp slider
        self.sliderTemp = QbLUeSlider(Qt.Horizontal)
        self.sliderTemp.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultIColorStylesheet)
        self.sliderTemp.setRange(
            17, 100
        )  # 250)  # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP
        self.sliderTemp.setSingleStep(1)

        tempLabel = QbLUeLabel()
        tempLabel.setMaximumSize(150, 30)
        tempLabel.setText("Filter Temperature")
        tempLabel.doubleClicked.connect(lambda: self.sliderTemp.setValue(
            self.temp2Slider(self.defaultTemp)))

        self.tempValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("00000")
        h = metrics.height()
        self.tempValue.setMinimumSize(w, h)
        self.tempValue.setMaximumSize(w, h)
        self.tempValue.setText(
            str("{:d}".format(self.sliderTemp2User(self.sliderTemp.value()))))

        # tint slider
        self.sliderTint = QbLUeSlider(Qt.Horizontal)
        self.sliderTint.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultMGColorStylesheet)
        self.sliderTint.setRange(
            0, 100
        )  # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP
        self.sliderTint.setSingleStep(1)

        self.tintLabel = QbLUeLabel()
        self.tintLabel.setMaximumSize(150, 30)
        self.tintLabel.setText("Tint")
        self.tintLabel.doubleClicked.connect(lambda: self.sliderTint.setValue(
            self.tint2Slider(self.defaultTint)))

        self.tintValue = QLabel()
        font = self.tintValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.tintValue.setMinimumSize(w, h)
        self.tintValue.setMaximumSize(w, h)
        self.tintValue.setText(
            str("{:d}".format(self.sliderTint2User(self.sliderTint.value()))))

        # temp change slot
        def tempUpdate(value):
            self.tempValue.setText(
                str("{:d}".format(self.sliderTemp2User(value))))
            # move not yet terminated or values not modified
            if self.sliderTemp.isSliderDown() or self.slider2Temp(
                    value) == self.tempCorrection:
                return
            try:
                self.sliderTemp.valueChanged.disconnect()
                self.sliderTemp.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.tempCorrection = self.slider2Temp(value)
            self.dataChanged.emit()
            self.sliderTemp.valueChanged.connect(tempUpdate)
            self.sliderTemp.sliderReleased.connect(
                lambda: tempUpdate(self.sliderTemp.value()))

        # tint change slot
        def tintUpdate(value):
            self.tintValue.setText(
                str("{:d}".format(self.sliderTint2User(value))))
            # move not yet terminated or values not modified
            if self.sliderTint.isSliderDown() or self.slider2Tint(
                    value) == self.tintCorrection:
                return
            try:
                self.sliderTint.valueChanged.disconnect()
                self.sliderTint.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.tintCorrection = self.slider2Tint(value)
            self.dataChanged.emit()
            self.sliderTint.valueChanged.connect(tintUpdate)
            self.sliderTint.sliderReleased.connect(
                lambda: tintUpdate(self.sliderTint.value()))

        self.sliderTemp.valueChanged.connect(tempUpdate)
        self.sliderTemp.sliderReleased.connect(
            lambda: tempUpdate(self.sliderTemp.value()))
        self.sliderTint.valueChanged.connect(tintUpdate)
        self.sliderTint.sliderReleased.connect(
            lambda: tintUpdate(self.sliderTint.value()))

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        l.addWidget(self.listWidget1)
        l.addWidget(tempLabel)
        hl = QHBoxLayout()
        hl.addWidget(self.tempValue)
        hl.addWidget(self.sliderTemp)
        l.addLayout(hl)
        l.addWidget(self.tintLabel)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.tintValue)
        hl1.addWidget(self.sliderTint)
        l.addLayout(hl1)
        self.setLayout(l)
        self.adjustSize()
        self.setDefaults()
        self.setWhatsThis("""<b>Color Temperature</b><br>
                        <b>Photo Filter</b> uses the multiply blending mode to mimic a warming or cooling filter
                        put in front of the camera lens. The luminosity of the resulting image is corrected.<br>
                        <b>Chromatic Adaptation</b> uses multipliers in the linear sRGB
                        color space to adjust <b>temperature</b> and <b>tint</b>.
                        """)  # end of setWhatsThis
示例#25
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)
        self.tempCorrection = 6500
        self.tintCorrection = 1.0
        self.filterColor = QColor(255, 255, 255)
        self.defaultTemp = sRGBWP  # ref temperature D65
        self.defaultTint = 0

        # options
        optionList, optionNames = [
            'Color Filter', 'Photo Filter', 'Chromatic Adaptation'
        ], ['Color Filter', 'Photo Filter', 'Chromatic Adaptation']
        self.listWidget1 = optionsWidget(
            options=optionList,
            optionNames=optionNames,
            exclusive=True,
            changed=lambda: self.dataChanged.emit())
        self.listWidget1.checkOption(self.listWidget1.intNames[0])
        self.options = self.listWidget1.options
        # link to app color dialog
        self.colorChooser = self.parent().colorChooser
        # color viewer
        self.colorLabel = QLabel()
        self.colorLabel.setMaximumSize(50, 50)
        # color chooser button
        self.colorChooserBtn = QbLUePushButton('Select Filter Color')
        self.colorChooserBtn.clicked.connect(self.showColorChooser)

        # temp slider
        self.sliderTemp = QbLUeSlider(Qt.Horizontal)
        self.sliderTemp.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultIColorStylesheet)
        self.sliderTemp.setRange(
            17, 100
        )  # 250)  # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP
        self.sliderTemp.setSingleStep(1)

        self.tempLabel = QbLUeLabel()
        self.tempLabel.setMaximumSize(150, 30)
        self.tempLabel.setText("Filter Temperature")
        self.tempLabel.doubleClicked.connect(lambda: self.sliderTemp.setValue(
            self.temp2Slider(self.defaultTemp)))

        self.tempValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("00000")
        h = metrics.height()
        self.tempValue.setMinimumSize(w, h)
        self.tempValue.setMaximumSize(w, h)
        self.tempValue.setText(
            str("{:d}".format(self.sliderTemp2User(self.sliderTemp.value()))))

        # tint slider
        self.sliderTint = QbLUeSlider(Qt.Horizontal)
        self.sliderTint.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultMGColorStylesheet)
        self.sliderTint.setRange(
            0, 100
        )  # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP
        self.sliderTint.setSingleStep(1)

        self.tintLabel = QbLUeLabel()
        self.tintLabel.setMaximumSize(150, 30)
        self.tintLabel.setText("Tint")
        self.tintLabel.doubleClicked.connect(lambda: self.sliderTint.setValue(
            self.tint2Slider(self.defaultTint)))

        self.tintValue = QLabel()
        font = self.tintValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.tintValue.setMinimumSize(w, h)
        self.tintValue.setMaximumSize(w, h)
        self.tintValue.setText(
            str("{:d}".format(self.sliderTint2User(self.sliderTint.value()))))

        self.sliderTemp.valueChanged.connect(self.tempUpdate)
        self.sliderTemp.sliderReleased.connect(
            lambda: self.tempUpdate(self.sliderTemp.value()))
        self.sliderTint.valueChanged.connect(self.tintUpdate)
        self.sliderTint.sliderReleased.connect(
            lambda: self.tintUpdate(self.sliderTint.value()))

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        l.addWidget(self.listWidget1)
        hl2 = QHBoxLayout()
        hl2.addWidget(self.colorLabel)
        hl2.addWidget(self.colorChooserBtn)
        l.addLayout(hl2)
        l.addWidget(self.tempLabel)
        hl = QHBoxLayout()
        hl.addWidget(self.tempValue)
        hl.addWidget(self.sliderTemp)
        l.addLayout(hl)
        l.addWidget(self.tintLabel)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.tintValue)
        hl1.addWidget(self.sliderTint)
        l.addLayout(hl1)
        self.setLayout(l)
        self.adjustSize()
        self.setDefaults()
        self.setWhatsThis(
            """<b> Color Filter</b> and <b>Photo Filter</b> use the multiply blending mode
                        to mimic a warming or cooling filter put in front of the camera lens. 
                        The luminosity of the resulting image is corrected.<br>
                        <b>Chromatic Adaptation</b> uses multipliers in the linear sRGB
                        color space to adjust <b>temperature</b> and <b>tint</b>.
                        """)  # end of setWhatsThis
示例#26
0
class scrollTextLabel(QLabel):
    deletesig = Signal()

    def __init__(self, text, Rect, scale, speed, line, color, bold, parent=None):
        super(scrollTextLabel, self).__init__(parent)

        if color == 'red':
            self.color = QColor(231, 0, 18, 255)  # red
        elif color == 'white':
            self.color = QColor(255, 255, 246, 255)  # white
        elif color == 'Grass':
            self.color = QColor(144, 195, 32, 255)  # Grass
        elif color == 'Blue':
            self.color = QColor(0, 160, 234, 255)  # Blue
        if bold:
            self.font = QFont("Helvetica", scale, QFont.Bold)  # 20 25 30 粗體
        else:
            self.font = QFont("Helvetica", scale)
        self.txt = text
        self.speed = speed  # between 50 ~ 120

        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(
            Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.WindowCloseButtonHint)  # 隱藏 FramelessWindow

        self.metrics = QFontMetrics(self.font)
        self.setFixedWidth(self.metrics.width(self.txt) + 10)
        self.setFixedHeight(self.metrics.height() + 5)

        # self.move(Rect.x() + Rect.width() * 0.97, Rect.y() + 50 * line)
        self.setFocusPolicy(Qt.NoFocus)
        self.hide()
        self.anim = QPropertyAnimation(self, 'pos')
        self.anim.setDuration(self.speed * 100)
        self.anim.setStartValue(QPoint(Rect.x() + Rect.width() * 0.95, Rect.y() + 50 * line))
        self.anim.setEndValue(QPoint(-self.width() + Rect.x(), Rect.y() + 50 * line))
        self.anim.setEasingCurve(QEasingCurve.Linear)

        self.show()
        self.repaint()
        self.anim.start()
        self.anim.finished.connect(self.sendslot)

    def sendslot(self):
        self.hide()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.save()
        path = QPainterPath()

        painter.setFont(self.font)
        painter.setRenderHint(QPainter.Antialiasing)

        pen = QPen(QColor(0, 0, 0, 230))
        pen_width = 3
        pen.setWidth(pen_width)

        len = self.metrics.width(self.txt)
        w = self.width()
        px = (len - w) / 2
        if px < 0:
            px = -px
        py = (self.height() - self.metrics.height()) / 2 + self.metrics.ascent()
        if py < 0:
            py = -py

        path.addText(px + 2, py + 2, self.font, self.txt)
        painter.strokePath(path, pen)
        painter.drawPath(path)
        painter.fillPath(path, QBrush(self.color))
        painter.restore()
示例#27
0
    def __init__(self,
                 targetImage=None,
                 axeSize=500,
                 layer=None,
                 parent=None,
                 mainForm=None):
        super().__init__(parent=parent)
        #self.targetImage = targetImage
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setMinimumSize(axeSize, axeSize)
        self.setAttribute(Qt.WA_DeleteOnClose)
        # link back to image layer
        # using weak ref for back links
        if type(layer) in weakref.ProxyTypes:
            self.layer = layer
        else:
            self.layer = weakref.proxy(layer)

        # options
        self.options = None

        # exposure slider
        self.sliderExp = QbLUeSlider(Qt.Horizontal)
        self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderExp.setTickPosition(QSlider.TicksBelow)
        self.sliderExp.setRange(-20, 20)
        self.sliderExp.setSingleStep(1)

        expLabel = QbLUeLabel()
        expLabel.setMaximumSize(150, 30)
        expLabel.setText("Exposure Correction")
        expLabel.doubleClicked.connect(
            lambda: self.sliderExp.setValue(self.defaultExpCorrection))

        self.expValue = QbLUeLabel()
        font = self.expValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("1000 ")
        h = metrics.height()
        self.expValue.setMinimumSize(w, h)
        self.expValue.setMaximumSize(w, h)

        # exp done event handler
        def f():
            self.sliderExp.setEnabled(False)
            self.expValue.setText(
                str("{:+.1f}".format(self.sliderExp.value() *
                                     self.DefaultStep)))
            self.onUpdateExposure(self.layer,
                                  self.sliderExp.value() * self.DefaultStep)
            self.sliderExp.setEnabled(True)

        # exp value changed slot
        def g():
            self.expValue.setText(
                str("{:+.1f}".format(self.sliderExp.value() *
                                     self.DefaultStep)))

        self.sliderExp.valueChanged.connect(g)
        self.sliderExp.sliderReleased.connect(f)

        self.sliderExp.setValue(self.defaultExpCorrection / self.DefaultStep)
        self.expValue.setText(str("{:+.1f}".format(self.defaultExpCorrection)))

        #layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        l.addWidget(expLabel)
        hl = QHBoxLayout()
        hl.addWidget(self.expValue)
        hl.addWidget(self.sliderExp)
        l.addLayout(hl)
        l.setContentsMargins(20, 0, 20, 25)  # left, top, right, bottom
        #l.addStretch(1)
        self.setLayout(l)
        self.adjustSize()
        self.setWhatsThis("""<b>Exposure Correction</b>
Multiplicative correction in the linear sRGB color space.<br>
""")  # end setWhatsThis
示例#28
0
    def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None):
        super().__init__(layer=layer, targetImage=targetImage, parent=parent)

        #######################################
        # Libraw correspondences:
        # rgb_xyz_matrix is libraw cam_xyz
        # camera_whitebalance is libraw cam_mul
        # daylight_whitebalance is libraw pre_mul
        # dng correspondences:
        # ASSHOTNEUTRAL tag value is (X,Y,Z) =  1 / rawpyObj.camera_whitebalance
        ##########################################
        rawpyObj = layer.parentImage.rawImage

        # constants and as shot values
        self.XYZ2CameraMatrix = rawpyObj.rgb_xyz_matrix[:3, :]
        self.XYZ2CameraInverseMatrix = np.linalg.inv(self.XYZ2CameraMatrix)
        # initial post processing multipliers (as shot)
        m1, m2, m3, m4 = rawpyObj.camera_whitebalance
        self.asShotMultipliers = (
            m1 / m2, 1.0, m3 / m2, m4 / m2
        )  # normalization is mandatory : for nef files white balance is around 256
        self.asShotTemp, self.asShotTint = multipliers2TemperatureAndTint(
            *1 / np.array(self.asShotMultipliers[:3]), self.XYZ2CameraMatrix)
        self.rawMultipliers = self.asShotMultipliers  # rawpyObj.camera_whitebalance # = 1/(dng ASSHOTNEUTRAL tag value)
        self.sampleMultipliers = False
        self.samples = []
        ########################################
        # XYZ-->Camera conversion matrix:
        # Last row is zero for RGB cameras (cf. rawpy and libraw docs).
        # type ndarray, shape (4,3)
        #########################################

        # attributes initialized in setDefaults, declared here for the sake of correctness
        self.tempCorrection, self.tintCorrection, self.expCorrection, self.highCorrection,\
                                                   self.contCorrection, self.satCorrection, self.brCorrection = [None] * 7
        # contrast spline vie (initialized by setContrastSpline)
        self.contrastForm = None
        # tone spline view (initialized by setToneSpline)
        self.toneForm = None
        # dock containers for contrast and tome forms
        self.dockC, self.dockT = None, None
        # options
        optionList0, optionNames0 = ['Auto Brightness', 'Preserve Highlights'
                                     ], ['Auto Expose', 'Preserve Highlights']
        optionList1, optionNames1 = ['Auto WB', 'Camera WB', 'User WB'
                                     ], ['Auto', 'Camera (As Shot)', 'User']
        optionList2, optionNames2 = [
            'cpLookTable', 'cpToneCurve', 'manualCurve'
        ], [
            'Use Camera Profile Look Table', 'Show Tone Curves',
            'Show Contrast Curve'
        ]
        self.listWidget1 = optionsWidget(
            options=optionList0,
            optionNames=optionNames0,
            exclusive=False,
            changed=lambda: self.dataChanged.emit(1))
        self.listWidget2 = optionsWidget(
            options=optionList1,
            optionNames=optionNames1,
            exclusive=True,
            changed=lambda: self.dataChanged.emit(1))
        self.listWidget3 = optionsWidget(
            options=optionList2,
            optionNames=optionNames2,
            exclusive=False,
            changed=lambda: self.dataChanged.emit(2))
        self.options = UDict(
            (self.listWidget1.options, self.listWidget2.options,
             self.listWidget3.options))
        # display the 'as shot' temperature
        item = self.listWidget2.item(1)
        item.setText(item.text() + ' : %d' % self.asShotTemp)

        # temperature slider
        self.sliderTemp = QbLUeSlider(Qt.Horizontal)
        self.sliderTemp.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultColorStylesheet)
        self.sliderTemp.setRange(0, 100)
        self.sliderTemp.setSingleStep(1)

        self.tempLabel = QLabel()
        self.tempLabel.setText("Temp")

        self.tempValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("10000")
        h = metrics.height()
        self.tempValue.setMinimumSize(w, h)
        self.tempValue.setMaximumSize(w, h)
        self.tempValue.setText(
            str("{:.0f}".format(self.slider2Temp(self.sliderTemp.value()))))

        self.sliderTemp.valueChanged.connect(
            self.tempUpdate)  # signal send new value as parameter
        self.sliderTemp.sliderReleased.connect(lambda: self.tempUpdate(
            self.sliderTemp.value()))  # signal pass no parameter

        # tint slider
        self.sliderTint = QbLUeSlider(Qt.Horizontal)
        self.sliderTint.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultIMGColorStylesheet)
        self.sliderTint.setRange(0, 150)

        self.sliderTint.setSingleStep(1)

        self.tintLabel = QLabel()
        self.tintLabel.setText("Tint")

        self.tintValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.tintValue.setMinimumSize(w, h)
        self.tintValue.setMaximumSize(w, h)
        self.tintValue.setText(
            str("{:.0f}".format(self.sliderTint2User(
                self.sliderTint.value()))))

        self.sliderTint.valueChanged.connect(self.tintUpdate)
        self.sliderTint.sliderReleased.connect(lambda: self.tintUpdate(
            self.sliderTint.value()))  # signal pass no parameter)

        ######################
        # From libraw and dcraw sources:
        # Exposure and brightness are curve transformations.
        # Exposure curve is y = alpha*x, with cubic root ending; it is applied before demosaicing.
        # Brightness is (similar to) y = x**alpha and part of gamma transformation from linear sRGB to RGB.
        # Exposure and brightness both dilate the histogram towards highlights.
        # Exposure dilatation is uniform (homothety), brightness dilataion is
        # maximum for the midtones and the highlghts are preserved.
        # As a consequence, normal workflow begins with the adjustment of exposure,
        # to fill the entire range of the histogram and to adjust the highlights. Next,
        # one adjusts the brightness to put the midtones at the level we want them to be.
        # Cf. https://www.cambridgeincolour.com/forums/thread653.htm
        #####################

        # profile combo
        self.dngDict = self.setCameraProfilesCombo()

        # cameraProfilesCombo index changed event handler

        def cameraProfileUpdate(value):
            self.dngDict = self.cameraProfilesCombo.itemData(value)
            if self.options['cpToneCurve']:
                toneCurve = dngProfileToneCurve(
                    self.dngDict.get('ProfileToneCurve', []))
                self.toneForm.baseCurve = [
                    QPointF(x * axeSize, -y * axeSize)
                    for x, y in zip(toneCurve.dataX, toneCurve.dataY)
                ]
                self.toneForm.update()
            # recompute as shot temp and tint using new profile
            self.asShotTemp, self.asShotTint = multipliers2TemperatureAndTint(
                *1 / np.array(self.asShotMultipliers[:3]),
                self.XYZ2CameraMatrix,
                dngDict=self.dngDict
            )  # TODO 6/12/19 added keyword dngDict validate
            # display updated as shot temp
            item = self.listWidget2.item(1)
            item.setText(item.text().split(":")[0] + ': %d' % self.asShotTemp)
            # invalidate cache
            self.layer.bufCache_HSV_CV32 = None
            self.dataChanged.emit(2)  # 2 = no postprocessing

        self.cameraProfilesCombo.currentIndexChanged.connect(
            cameraProfileUpdate)

        # denoising combo
        self.denoiseCombo = QComboBox()
        items = OrderedDict([('Off', 0), ('Medium', 1), ('Full', 2)])
        for key in items:
            self.denoiseCombo.addItem(key, items[key])

        # denoiseCombo index changed event handler
        def denoiseUpdate(value):
            self.denoiseValue = self.denoiseCombo.itemData(value)
            self.dataChanged.emit(1)

        self.denoiseCombo.currentIndexChanged.connect(denoiseUpdate)

        # overexposed area restoration
        self.overexpCombo = QComboBox()
        items = OrderedDict([('Clip', 0), ('Ignore', 1), ('Blend', 2),
                             ('Reconstruct', 3)])
        for key in items:
            self.overexpCombo.addItem(key, items[key])

        # overexpCombo index changed event handler
        def overexpUpdate(value):
            self.overexpValue = self.overexpCombo.itemData(value)
            self.dataChanged.emit(1)

        self.overexpCombo.currentIndexChanged.connect(overexpUpdate)

        # exp slider
        self.sliderExp = QbLUeSlider(Qt.Horizontal)
        self.sliderExp.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderExp.setRange(0, 100)

        self.sliderExp.setSingleStep(1)

        self.expLabel = QLabel()
        self.expLabel.setText("Exp.")

        self.expValue = QLabel()
        font = self.expValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("+1.0")
        h = metrics.height()
        self.expValue.setMinimumSize(w, h)
        self.expValue.setMaximumSize(w, h)
        self.expValue.setText(
            str("{:.1f}".format(self.slider2Exp(self.sliderExp.value()))))

        # exp done event handler
        def expUpdate(value):
            self.expValue.setText(
                str("{:+.1f}".format(
                    self.sliderExp2User(self.sliderExp.value()))))
            # move not yet terminated or value not modified
            if self.sliderExp.isSliderDown() or self.slider2Exp(
                    value) == self.expCorrection:
                return
            try:
                self.sliderExp.valueChanged.disconnect()
                self.sliderExp.sliderReleased.disconnect()
            except RuntimeError:
                pass
            # rawpy: expCorrection range is -2.0...3.0, boiling down to exp_shift range 2**(-2)=0.25...2**3=8.0
            self.expCorrection = self.slider2Exp(self.sliderExp.value())
            self.dataChanged.emit(1)
            self.sliderExp.valueChanged.connect(
                expUpdate)  # send new value as parameter
            self.sliderExp.sliderReleased.connect(lambda: expUpdate(
                self.sliderExp.value()))  # signal pass no parameter

        self.sliderExp.valueChanged.connect(
            expUpdate)  # send new value as parameter
        self.sliderExp.sliderReleased.connect(lambda: expUpdate(
            self.sliderExp.value()))  # signal pass no parameter

        # brightness slider
        brSlider = QbLUeSlider(Qt.Horizontal)
        brSlider.setRange(1, 101)

        self.sliderExp.setSingleStep(1)

        brSlider.setStyleSheet(QbLUeSlider.bLueSliderDefaultBWStylesheet)

        self.sliderBrightness = brSlider
        brLabel = QLabel()
        brLabel.setText("Bright.")

        self.brValue = QLabel()
        font = self.expValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("+99")
        h = metrics.height()
        self.brValue.setMinimumSize(w, h)
        self.brValue.setMaximumSize(w, h)
        self.brValue.setText(
            str("{:+d}".format(
                int(self.brSlider2User(self.sliderBrightness.value())))))

        # brightness done event handler
        def brUpdate(value):
            self.brValue.setText(
                str("{:+d}".format(
                    int(self.brSlider2User(self.sliderBrightness.value())))))
            # move not yet terminated or value not modified
            if self.sliderBrightness.isSliderDown() or self.slider2Br(
                    value) == self.brCorrection:
                return
            try:
                self.sliderBrightness.valueChanged.disconnect()
                self.sliderBrightness.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.brCorrection = self.slider2Br(self.sliderBrightness.value())
            self.dataChanged.emit(1)
            self.sliderBrightness.sliderReleased.connect(
                lambda: brUpdate(self.sliderBrightness.value()))
            self.sliderBrightness.valueChanged.connect(
                brUpdate)  # send new value as parameter

        self.sliderBrightness.valueChanged.connect(
            brUpdate)  # send new value as parameter
        self.sliderBrightness.sliderReleased.connect(
            lambda: brUpdate(self.sliderBrightness.value()))

        # contrast slider
        self.sliderCont = QbLUeSlider(Qt.Horizontal)
        self.sliderCont.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultBWStylesheet)
        self.sliderCont.setRange(0, 20)

        self.sliderCont.setSingleStep(1)

        self.contLabel = QLabel()
        self.contLabel.setText("Cont.")

        self.contValue = QLabel()
        font = self.contValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("100")
        h = metrics.height()
        self.contValue.setMinimumSize(w, h)
        self.contValue.setMaximumSize(w, h)
        self.contValue.setText(
            str("{:.0f}".format(self.slider2Cont(self.sliderCont.value()))))

        # cont done event handler
        def contUpdate(value):
            self.contValue.setText(
                str("{:.0f}".format(self.slider2Cont(
                    self.sliderCont.value()))))
            # move not yet terminated or value not modified
            if self.sliderCont.isSliderDown() or self.slider2Cont(
                    value) == self.tempCorrection:
                return
            try:
                self.sliderCont.valueChanged.disconnect()
                self.sliderCont.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.contCorrection = self.slider2Cont(self.sliderCont.value())
            self.contValue.setText(str("{:+d}".format(self.contCorrection)))
            # force to recalculate the spline
            self.layer.autoSpline = True
            self.dataChanged.emit(
                3)  # no postprocessing and no camera profile stuff
            self.sliderCont.valueChanged.connect(
                contUpdate)  # send new value as parameter
            self.sliderCont.sliderReleased.connect(lambda: contUpdate(
                self.sliderCont.value()))  # signal has no parameter

        self.sliderCont.valueChanged.connect(
            contUpdate)  # send new value as parameter
        self.sliderCont.sliderReleased.connect(lambda: contUpdate(
            self.sliderCont.value()))  # signal has no parameter

        # saturation slider
        self.sliderSat = QbLUeSlider(Qt.Horizontal)
        self.sliderSat.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultColorStylesheet)
        self.sliderSat.setRange(0, 100)

        self.sliderSat.setSingleStep(1)

        satLabel = QLabel()
        satLabel.setText("Sat.")

        self.satValue = QLabel()
        font = self.satValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("+10")
        h = metrics.height()
        self.satValue.setMinimumSize(w, h)
        self.satValue.setMaximumSize(w, h)
        self.satValue.setText(
            str("{:+d}".format(self.slider2Sat(self.sliderSat.value()))))
        """sat done event handler"""

        def satUpdate(value):
            self.satValue.setText(
                str("{:+d}".format(self.slider2Sat(self.sliderSat.value()))))
            # move not yet terminated or value not modified
            if self.sliderSat.isSliderDown() or self.slider2Sat(
                    value) == self.satCorrection:
                return
            try:
                self.sliderSat.valueChanged.disconnect()
                self.sliderSat.sliderReleased.disconnect()
            except RuntimeError:
                pass
            self.satCorrection = self.slider2Sat(self.sliderSat.value())
            self.dataChanged.emit(
                3)  # no post processing and no camera profile stuff
            self.sliderSat.valueChanged.connect(
                satUpdate)  # send new value as parameter
            self.sliderSat.sliderReleased.connect(lambda: satUpdate(
                self.sliderSat.value()))  # signal has no parameter

        self.sliderSat.valueChanged.connect(
            satUpdate)  # send new value as parameter
        self.sliderSat.sliderReleased.connect(lambda: satUpdate(
            self.sliderSat.value()))  # signal has no parameter

        # layout
        l = QVBoxLayout()
        l.addWidget(self.listWidget3)
        hl01 = QHBoxLayout()
        hl01.addWidget(QLabel('Camera Profile'))
        hl01.addWidget(self.cameraProfilesCombo)
        l.addLayout(hl01)
        hl0 = QHBoxLayout()
        hl0.addWidget(QLabel('Denoising'))
        hl0.addWidget(self.denoiseCombo)
        l.addLayout(hl0)
        hl00 = QHBoxLayout()
        hl00.addWidget(QLabel('Overexp. Restoration'))
        hl00.addWidget(self.overexpCombo)
        l.addLayout(hl00)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.expLabel)
        hl1.addWidget(self.expValue)
        hl1.addWidget(self.sliderExp)
        l.addLayout(hl1)
        hl8 = QHBoxLayout()
        hl8.addWidget(brLabel)
        hl8.addWidget(self.brValue)
        hl8.addWidget(self.sliderBrightness)
        l.addLayout(hl8)
        l.addWidget(self.listWidget1)
        vl1 = QVBoxLayout()
        vl1.addWidget(self.listWidget2)
        gb1 = QGroupBox()
        gb1.setTitle('White Balance')
        hl2 = QHBoxLayout()
        hl2.addWidget(self.tempLabel)
        hl2.addWidget(self.tempValue)
        hl2.addWidget(self.sliderTemp)
        hl3 = QHBoxLayout()
        hl3.addWidget(self.tintLabel)
        hl3.addWidget(self.tintValue)
        hl3.addWidget(self.sliderTint)
        vl1.addLayout(hl2)
        vl1.addLayout(hl3)
        gb1.setLayout(vl1)
        l.addWidget(gb1)
        hl4 = QHBoxLayout()
        hl4.addWidget(self.contLabel)
        hl4.addWidget(self.contValue)
        hl4.addWidget(self.sliderCont)
        hl7 = QHBoxLayout()
        hl7.addWidget(satLabel)
        hl7.addWidget(self.satValue)
        hl7.addWidget(self.sliderSat)

        # separator
        sep = QFrame()
        sep.setFrameShape(QFrame.HLine)
        sep.setFrameShadow(QFrame.Sunken)
        l.addWidget(sep)
        l.addLayout(hl4)
        l.addLayout(hl7)
        l.addStretch(1)
        self.setLayout(l)
        self.adjustSize()
        self.setDefaults()
        self.setWhatsThis("""<b>Development of raw files</b><br>
                    <b>Default settings</b> are a good starting point.<br>
                    A <b>Tone Curve</b> is applied to the raw image prior to postprocessing.<br> 
                    The cuvre can be edited by checking the option
                    <b>Show Tone Curve</b>; this option works best with manual exposure.<br>
                    <b>Contrast</b> correction is based on an automatic algorithm 
                    well suited to multi-mode histograms.<br>
                    <b>Brightness, Contrast</b> and <b>Saturation</b> levels</b> are 
                    adjustable with the correponding sliders.<br>
                    The <b>Contrast Curve</b> can be edited manually by checking 
                    the option <b>Show Contrast Curve</b>.<br>
                    Uncheck <b>Auto Expose</b> to adjust the exposure manually.<br>
                    The <b>OverExp. Rest.</b> slider controls the mode of restoration of overexposed areas. 
                    Valid values are 0 to 3 (0=clip;1=unclip;2=blend;3=rebuild); (with Auto Exposed 
                    checked the mode is clip).<br>
                    """)  # end of setWhatsThis
示例#29
0
    def __init__(self,
                 targetImage=None,
                 axeSize=500,
                 layer=None,
                 parent=None,
                 mainForm=None):
        super().__init__(parent=parent)
        self.tempCorrection = 6500
        self.tintCorrection = 1.0
        self.setStyleSheet(
            'QRangeSlider * {border: 0px; padding: 0px; margin: 0px}')
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.setMinimumSize(axeSize, axeSize)
        self.setAttribute(Qt.WA_DeleteOnClose)
        # link back to image layer
        self.layer = weakProxy(layer)
        """
        # using weak ref for back links
        if type(layer) in weakref.ProxyTypes:
            self.layer = layer
        else:
            self.layer = weakref.proxy(layer)
        """
        self.defaultTemp = sRGBWP  # ref temperature D65
        self.defaultTint = 0

        # options
        optionList, optionNames = ['Photo Filter', 'Chromatic Adaptation'
                                   ], ['Photo Filter', 'Chromatic Adaptation']
        self.listWidget1 = optionsWidget(
            options=optionList,
            optionNames=optionNames,
            exclusive=True,
            changed=lambda: self.dataChanged.emit())
        self.listWidget1.checkOption(self.listWidget1.intNames[1])
        self.options = self.listWidget1.options

        # temp slider
        self.sliderTemp = QbLUeSlider(Qt.Horizontal)
        self.sliderTemp.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultIColorStylesheet)
        self.sliderTemp.setRange(
            17, 100
        )  # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP
        self.sliderTemp.setSingleStep(1)

        tempLabel = QbLUeLabel()
        tempLabel.setMaximumSize(150, 30)
        tempLabel.setText("Color temperature")
        tempLabel.doubleClicked.connect(lambda: self.sliderTemp.setValue(
            self.temp2Slider(self.defaultTemp)))

        self.tempValue = QLabel()
        font = self.tempValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.tempValue.setMinimumSize(w, h)
        self.tempValue.setMaximumSize(w, h)
        self.tempValue.setText(
            str("{:d}".format(self.sliderTemp2User(self.sliderTemp.value()))))

        # tint slider
        self.sliderTint = QbLUeSlider(Qt.Horizontal)
        self.sliderTint.setStyleSheet(
            QbLUeSlider.bLueSliderDefaultMGColorStylesheet)
        self.sliderTint.setRange(
            0, 100
        )  # 250) # valid range for spline approximation is 1667..25000, cf. colorConv.temperature2xyWP
        self.sliderTint.setSingleStep(1)

        tintLabel = QbLUeLabel()
        tintLabel.setMaximumSize(150, 30)
        tintLabel.setText("Tint")
        tintLabel.doubleClicked.connect(lambda: self.sliderTint.setValue(
            self.tint2Slider(self.defaultTint)))

        self.tintValue = QLabel()
        font = self.tintValue.font()
        metrics = QFontMetrics(font)
        w = metrics.width("0000")
        h = metrics.height()
        self.tintValue.setMinimumSize(w, h)
        self.tintValue.setMaximumSize(w, h)
        self.tintValue.setText(
            str("{:d}".format(self.sliderTint2User(self.sliderTint.value()))))

        # temp change event handler
        def tempUpdate(value):
            self.tempValue.setText(
                str("{:d}".format(self.sliderTemp2User(value))))
            # move not yet terminated or values not modified
            if self.sliderTemp.isSliderDown() or self.slider2Temp(
                    value) == self.tempCorrection:
                return
            self.sliderTemp.valueChanged.disconnect()
            self.sliderTemp.sliderReleased.disconnect()
            self.tempCorrection = self.slider2Temp(value)
            self.dataChanged.emit()
            self.sliderTemp.valueChanged.connect(tempUpdate)
            self.sliderTemp.sliderReleased.connect(
                lambda: tempUpdate(self.sliderTemp.value()))

        # tint change event handler
        def tintUpdate(value):
            self.tintValue.setText(
                str("{:d}".format(self.sliderTint2User(value))))
            # move not yet terminated or values not modified
            if self.sliderTint.isSliderDown() or self.slider2Tint(
                    value) == self.tintCorrection:
                return
            self.sliderTint.valueChanged.disconnect()
            self.sliderTint.sliderReleased.disconnect()
            self.tintCorrection = self.slider2Tint(value)
            self.dataChanged.emit()
            self.sliderTint.valueChanged.connect(tintUpdate)
            self.sliderTint.sliderReleased.connect(
                lambda: tintUpdate(self.sliderTint.value()))

        self.sliderTemp.valueChanged.connect(tempUpdate)
        self.sliderTemp.sliderReleased.connect(
            lambda: tempUpdate(self.sliderTemp.value()))
        self.sliderTint.valueChanged.connect(tintUpdate)
        self.sliderTint.sliderReleased.connect(
            lambda: tintUpdate(self.sliderTint.value()))

        # layout
        l = QVBoxLayout()
        l.setAlignment(Qt.AlignTop)
        l.addWidget(self.listWidget1)
        l.addWidget(tempLabel)
        hl = QHBoxLayout()
        hl.addWidget(self.tempValue)
        hl.addWidget(self.sliderTemp)
        l.addLayout(hl)
        l.addWidget(tintLabel)
        hl1 = QHBoxLayout()
        hl1.addWidget(self.tintValue)
        hl1.addWidget(self.sliderTint)
        l.addLayout(hl1)
        self.setLayout(l)
        self.adjustSize()
        self.dataChanged.connect(
            self.updateLayer)  # TODO move to setDefaults 3/12/18
        self.setStyleSheet("QListWidget, QLabel {font : 7pt;}")
        self.setDefaults()
        self.setWhatsThis("""<b>Color Temperature</b><br>
<b>Photo Filter</b> uses the multiply blending mode to mimic a color filter
in front of the camera lens.<br>
<b>Chromatic Adaptation</b> uses multipliers in the linear sRGB
color space to adjust <b>temperature</b> and <b>tint</b>.
""")  # end of setWhatsThis