Exemplo n.º 1
0
    def setData(self, index, value, role=Qt.EditRole):

        if role == Qt.EditRole  and index.column() == self.ColumnID.Color:
            row = index.row()
            color = QColor(value["color"][0])
            colorglobal=value["color"][1]

            fontsize,fontsizeglobal = value["fontsize"]
            linewidth,linewidthglobal = value["linewidth"]

            fontcolor = QColor(value["fontcolor"][0])
            fontcolorglobal = value["fontcolor"][1]



            if color.isValid():
                if not colorglobal:
                    self._elements[row].color=color
                    self.dataChanged.emit(index, index)
                else:
                    for row,el in enumerate(self._elements):
                        el.color=color
                        ind=self.createIndex(row, self.ColumnID.Color, object=0)
                        self.dataChanged.emit(ind, ind)


            if fontcolor.isValid():
                if not fontcolorglobal:
                    self._elements[row].fontcolor=fontcolor
                else:
                    for row,el in enumerate(self._elements):
                        el.fontcolor=fontcolor

            if not linewidthglobal:
                self._elements[row].linewidth=linewidth
            else:
                for row,el in enumerate(self._elements):
                    el.linewidth=linewidth



            if not fontsizeglobal:
                self._elements[row].fontsize=fontsize
            else:
                for row,el in enumerate(self._elements):
                    el.fontsize=fontsize

            return True


        if index.column()==self.ColumnID.Fix:
            try:
                value=float(value)
                self._elements[index.row()].isFixed=True
                row=index.row()
                self._elements[row].fixvalue="%.1f"%value
                self.dataChanged.emit(index,index)
                return True
            except:
                return False
Exemplo n.º 2
0
def _transform_hint_color(val):
    """Transformer for hint colors."""
    log.config.debug("Transforming hint value {}".format(val))

    def to_rgba(qcolor):
        """Convert a QColor to a rgba() value."""
        return 'rgba({}, {}, {}, 0.8)'.format(qcolor.red(), qcolor.green(),
                                              qcolor.blue())

    if val.startswith('-webkit-gradient'):
        pattern = re.compile(r'-webkit-gradient\(linear, left top, '
                             r'left bottom, '
                             r'color-stop\(0%, *([^)]*)\), '
                             r'color-stop\(100%, *([^)]*)\)\)')

        match = pattern.fullmatch(val)
        if match:
            log.config.debug('Color groups: {}'.format(match.groups()))
            start_color = QColor(match.group(1))
            stop_color = QColor(match.group(2))
            if not start_color.isValid() or not stop_color.isValid():
                return None

            return ('qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 {}, '
                    'stop:1 {})'.format(to_rgba(start_color),
                                        to_rgba(stop_color)))
        else:
            return None
    elif val.startswith('-'):  # Custom CSS stuff?
        return None
    else:  # Already transformed or a named color.
        return val
Exemplo n.º 3
0
def _transform_hint_color(val):
    """Transformer for hint colors."""
    log.config.debug("Transforming hint value {}".format(val))

    def to_rgba(qcolor):
        """Convert a QColor to a rgba() value."""
        return 'rgba({}, {}, {}, 0.8)'.format(qcolor.red(), qcolor.green(),
                                              qcolor.blue())

    if val.startswith('-webkit-gradient'):
        pattern = re.compile(r'-webkit-gradient\(linear, left top, '
                             r'left bottom, '
                             r'color-stop\(0%, *([^)]*)\), '
                             r'color-stop\(100%, *([^)]*)\)\)')

        match = pattern.fullmatch(val)
        if match:
            log.config.debug('Color groups: {}'.format(match.groups()))
            start_color = QColor(match.group(1))
            stop_color = QColor(match.group(2))
            if not start_color.isValid() or not stop_color.isValid():
                return None

            return ('qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 {}, '
                    'stop:1 {})'.format(to_rgba(start_color),
                                        to_rgba(stop_color)))
        else:
            return None
    elif val.startswith('-'):  # Custom CSS stuff?
        return None
    else:  # Already transformed or a named color.
        return val
Exemplo n.º 4
0
class ColorButton(QPushButton):
    """A PushButton displaying a color.

    When clicked, opens a color dialog to change the color.

    """
    colorChanged = pyqtSignal(QColor)

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

        self.setFixedSize(self.sizeHint())
        self._color = QColor()
        self.clicked.connect(self.openDialog)

    def color(self):
        """Returns the currently set color."""
        return self._color

    def setColor(self, color):
        """Sets the current color. Maybe QColor() to indicate 'unset'."""
        if self._color != color:
            self._color = color
            self.update()
            self.colorChanged.emit(color)

    def clear(self):
        """Unsets the current color (setting it to QColor())."""
        self.setColor(QColor())

    def openDialog(self):
        """Called when clicked, opens a dialog to change the color."""
        color = self._color if self._color.isValid() else QColor(Qt.white)
        color = QColorDialog.getColor(color, self)
        if color.isValid():
            self.setColor(color)

    def paintEvent(self, ev):
        """Reimplemented to display a colored rectangle."""
        QPushButton.paintEvent(self, ev)
        if not self._color.isValid():
            return
        style = self.style()
        opt = QStyleOptionButton()
        self.initStyleOption(opt)
        r = style.subElementRect(QStyle.SE_PushButtonContents, opt, self)
        shift = style.pixelMetric(QStyle.PM_ButtonMargin, opt, self) // 2
        r.adjust(shift, shift, -shift, -shift)
        if self.isChecked() or self.isDown():
            dx = style.pixelMetric(QStyle.PM_ButtonShiftHorizontal, opt, self)
            dy = style.pixelMetric(QStyle.PM_ButtonShiftVertical, opt, self)
            r.translate(dx, dy)
        p = QPainter(self)
        if not self.isEnabled():
            p.setOpacity(0.5)
        qDrawShadeRect(p, r, self.palette(), True, 1, 0, self._color)
    def paint(self, painter, option, index):
        hasValue = True
        if (self.m_editorPrivate):
            property = self.m_editorPrivate.indexToProperty(index)
            if (property):
                hasValue = property.hasValue()

        opt = QStyleOptionViewItem(option)
        if ((self.m_editorPrivate and index.column() == 0) or not hasValue):
            property = self.m_editorPrivate.indexToProperty(index)
            if (property and property.isModified()):
                opt.font.setBold(True)
                opt.fontMetrics = QFontMetrics(opt.font)

        c = QColor()
        if (not hasValue
                and self.m_editorPrivate.markPropertiesWithoutValue()):
            c = opt.palette.color(QPalette.Dark)
            opt.palette.setColor(QPalette.Text,
                                 opt.palette.color(QPalette.BrightText))
        else:
            c = self.m_editorPrivate.calculatedBackgroundColor(
                self.m_editorPrivate.indexToBrowserItem(index))
            if (c.isValid()
                    and (opt.features & QStyleOptionViewItem.Alternate)):
                c = c.lighter(112)

        if (c.isValid()):
            painter.fillRect(option.rect, c)
        opt.state &= ~QStyle.State_HasFocus

        if (index.column() == 1):
            item = self.m_editorPrivate.indexToItem(index)
            if (self.m_editedItem and (self.m_editedItem == item)):
                self.m_disablePainting = True

        super(QtPropertyEditorDelegate, self).paint(painter, opt, index)
        if (option.type):
            self.m_disablePainting = False

        opt.palette.setCurrentColorGroup(QPalette.Active)
        color = QApplication.style().styleHint(QStyle.SH_Table_GridLineColor,
                                               opt)
        painter.save()
        painter.setPen(QPen(color))
        if (not self.m_editorPrivate
                or (not self.m_editorPrivate.lastColumn(index.column())
                    and hasValue)):
            if option.direction == Qt.LeftToRight:
                right = option.rect.right()
            else:
                right = option.rect.left()
            painter.drawLine(right, option.rect.y(), right,
                             option.rect.bottom())

        painter.restore()
Exemplo n.º 6
0
    def setData(self, index, value, role=Qt.EditRole):

        if role == Qt.EditRole and index.column() == self.ColumnID.Color:
            row = index.row()
            color = QColor(value["color"][0])
            colorglobal = value["color"][1]

            fontsize, fontsizeglobal = value["fontsize"]
            linewidth, linewidthglobal = value["linewidth"]

            fontcolor = QColor(value["fontcolor"][0])
            fontcolorglobal = value["fontcolor"][1]

            if color.isValid():
                if not colorglobal:
                    self._elements[row].color = color
                    self.dataChanged.emit(index, index)
                else:
                    for row, el in enumerate(self._elements):
                        el.color = color
                        ind = self.createIndex(row,
                                               self.ColumnID.Color,
                                               object=0)
                        self.dataChanged.emit(ind, ind)

            if fontcolor.isValid():
                if not fontcolorglobal:
                    self._elements[row].fontcolor = fontcolor
                else:
                    for row, el in enumerate(self._elements):
                        el.fontcolor = fontcolor

            if not linewidthglobal:
                self._elements[row].linewidth = linewidth
            else:
                for row, el in enumerate(self._elements):
                    el.linewidth = linewidth

            if not fontsizeglobal:
                self._elements[row].fontsize = fontsize
            else:
                for row, el in enumerate(self._elements):
                    el.fontsize = fontsize

            return True

        if index.column() == self.ColumnID.Fix:
            try:
                value = float(value)
                self._elements[index.row()].isFixed = True
                row = index.row()
                self._elements[row].fixvalue = "%.1f" % value
                self.dataChanged.emit(index, index)
                return True
            except:
                return False
Exemplo n.º 7
0
    def set_colors(data: bin,
                   fg: QColor,
                   bg: QColor,
                   trans: QColor,
                   swap_fg_bg=False) -> bin:  # pylint: disable=too-many-locals
        """
        Burns foreground and background colors into a raster image, and returns
        the results as a PNG binary
        """
        image = QImage()
        image.loadFromData(data)
        if image.isNull():
            raise UnreadablePictureException(
                'Could not read embedded picture data')

        image = image.convertToFormat(QImage.Format_ARGB32)
        ucharptr = image.bits()
        ucharptr.setsize(image.byteCount() * image.height())

        fg_rgba = qRgba(fg.red(), fg.green(), fg.blue(),
                        fg.alpha()) if fg and fg.isValid() else None
        bg_rgba = qRgba(bg.red(), bg.green(), bg.blue(),
                        bg.alpha()) if bg and bg.isValid() else None

        COLOR_TOLERANCE = 40

        fg_comp = 0
        bg_comp = 255

        for y in range(image.height()):
            start = y * image.width() * 4
            for x in range(image.width()):
                x_start = x * 4 + start
                rgba = struct.unpack('I', ucharptr[x_start:x_start + 4])[0]
                if trans and abs(qRed(rgba) - trans.red(
                )) < COLOR_TOLERANCE and abs(qGreen(rgba) - trans.green(
                )) < COLOR_TOLERANCE and abs(qBlue(rgba) -
                                             trans.blue()) < COLOR_TOLERANCE:
                    ucharptr[x_start:x_start + 4] = struct.pack(
                        'I', qRgba(0, 0, 0, 0))
                elif fg_rgba is not None and abs(
                        qRed(rgba) - fg_comp) < COLOR_TOLERANCE and abs(
                            qGreen(rgba) - fg_comp) < COLOR_TOLERANCE and abs(
                                qBlue(rgba) - fg_comp) < COLOR_TOLERANCE:
                    ucharptr[x_start:x_start + 4] = struct.pack('I', fg_rgba)
                elif bg_rgba is not None and abs(
                        qRed(rgba) - bg_comp) < COLOR_TOLERANCE and abs(
                            qGreen(rgba) - bg_comp) < COLOR_TOLERANCE and abs(
                                qBlue(rgba) - bg_comp) < COLOR_TOLERANCE:
                    ucharptr[x_start:x_start + 4] = struct.pack('I', bg_rgba)

        # convert to PNG
        png_data = QBuffer()
        image.save(png_data, "png")
        return png_data.data()
Exemplo n.º 8
0
    def setModelData(self, editor, model, index):
        if not editor.isModified():
            return

        text = editor.text()
        validator = editor.validator()
        if validator is not None:
            state, text, _ = validator.validate(text, 0)
            if state != QValidator.Acceptable:
                return

        originalValue = index.model().data(index, Qt.UserRole)

        if isinstance(originalValue, QColor):
            self.colorExp.exactMatch(text)
            value = QColor(
                min(int(self.colorExp.cap(1)), 255),
                min(int(self.colorExp.cap(2)), 255),
                min(int(self.colorExp.cap(3)), 255),
                min(int(self.colorExp.cap(4)), 255),
            )
        elif isinstance(originalValue, QDate):
            value = QDate.fromString(text, Qt.ISODate)
            if not value.isValid():
                return
        elif isinstance(originalValue, QDateTime):
            value = QDateTime.fromString(text, Qt.ISODate)
            if not value.isValid():
                return
        elif isinstance(originalValue, QTime):
            value = QTime.fromString(text, Qt.ISODate)
            if not value.isValid():
                return
        elif isinstance(originalValue, QPoint):
            self.pointExp.exactMatch(text)
            value = QPoint(int(self.pointExp.cap(1)), int(self.pointExp.cap(2)))
        elif isinstance(originalValue, QRect):
            self.rectExp.exactMatch(text)
            value = QRect(
                int(self.rectExp.cap(1)),
                int(self.rectExp.cap(2)),
                int(self.rectExp.cap(3)),
                int(self.rectExp.cap(4)),
            )
        elif isinstance(originalValue, QSize):
            self.sizeExp.exactMatch(text)
            value = QSize(int(self.sizeExp.cap(1)), int(self.sizeExp.cap(2)))
        elif isinstance(originalValue, list):
            value = text.split(",")
        else:
            value = type(originalValue)(text)

        model.setData(index, self.displayText(value), Qt.DisplayRole)
        model.setData(index, value, Qt.UserRole)
Exemplo n.º 9
0
class ColorButton(QPushButton):
    """A PushButton displaying a color.
    
    When clicked, opens a color dialog to change the color.
    
    """
    colorChanged = pyqtSignal(QColor)
    
    def __init__(self, parent=None):
        super(ColorButton, self).__init__(parent)
        
        self.setFixedSize(self.sizeHint())
        self._color = QColor()
        self.clicked.connect(self.openDialog)
    
    def color(self):
        """Returns the currently set color."""
        return self._color
    
    def setColor(self, color):
        """Sets the current color. Maybe QColor() to indicate 'unset'."""
        if self._color != color:
            self._color = color
            self.update()
            self.colorChanged.emit(color)

    def clear(self):
        """Unsets the current color (setting it to QColor())."""
        self.setColor(QColor())
        
    def openDialog(self):
        """Called when clicked, opens a dialog to change the color."""
        color = self._color if self._color.isValid() else QColor(Qt.white)
        color = QColorDialog.getColor(color, self)
        if color.isValid():
            self.setColor(color)

    def paintEvent(self, ev):
        """Reimplemented to display a colored rectangle."""
        QPushButton.paintEvent(self, ev)
        if not self._color.isValid():
            return
        style = self.style()
        opt = QStyleOptionButton()
        self.initStyleOption(opt)
        r = style.subElementRect(QStyle.SE_PushButtonContents, opt, self)
        shift = style.pixelMetric(QStyle.PM_ButtonMargin, opt, self) // 2
        r.adjust(shift, shift, -shift, -shift)
        if self.isChecked() or self.isDown():
            dx = style.pixelMetric(QStyle.PM_ButtonShiftHorizontal, opt, self)
            dy = style.pixelMetric(QStyle.PM_ButtonShiftVertical, opt, self)
            r.translate(dx, dy)
        p = QPainter(self)
        qDrawShadeRect(p, r, self.palette(), True, 1, 0, self._color)
Exemplo n.º 10
0
    def setModelData(self, editor, model, index):
        if not editor.isModified():
            return

        text = editor.text()
        validator = editor.validator()
        if validator is not None:
            state, text, _ = validator.validate(text, 0)
            if state != QValidator.Acceptable:
                return

        originalValue = index.model().data(index, Qt.UserRole)

        if isinstance(originalValue, QColor):
            self.colorExp.exactMatch(text)
            value = QColor(min(int(self.colorExp.cap(1)), 255),
                           min(int(self.colorExp.cap(2)), 255),
                           min(int(self.colorExp.cap(3)), 255),
                           min(int(self.colorExp.cap(4)), 255))
        elif isinstance(originalValue, QDate):
            value = QDate.fromString(text, Qt.ISODate)
            if not value.isValid():
                return
        elif isinstance(originalValue, QDateTime):
            value = QDateTime.fromString(text, Qt.ISODate)
            if not value.isValid():
                return
        elif isinstance(originalValue, QTime):
            value = QTime.fromString(text, Qt.ISODate)
            if not value.isValid():
                return
        elif isinstance(originalValue, QPoint):
            self.pointExp.exactMatch(text)
            value = QPoint(int(self.pointExp.cap(1)),
                           int(self.pointExp.cap(2)))
        elif isinstance(originalValue, QRect):
            self.rectExp.exactMatch(text)
            value = QRect(int(self.rectExp.cap(1)),
                          int(self.rectExp.cap(2)),
                          int(self.rectExp.cap(3)),
                          int(self.rectExp.cap(4)))
        elif isinstance(originalValue, QSize):
            self.sizeExp.exactMatch(text)
            value = QSize(int(self.sizeExp.cap(1)),
                          int(self.sizeExp.cap(2)))
        elif isinstance(originalValue, list):
            value = text.split(',')
        else:
            value = type(originalValue)(text)

        model.setData(index, self.displayText(value), Qt.DisplayRole)
        model.setData(index, value, Qt.UserRole)
    def paint(self, painter, option, index):
        hasValue = True
        if (self.m_editorPrivate):
            property = self.m_editorPrivate.indexToProperty(index)
            if (property):
                hasValue = property.hasValue()

        opt = QStyleOptionViewItem(option)
        if ((self.m_editorPrivate and index.column() == 0) or not hasValue):
            property = self.m_editorPrivate.indexToProperty(index)
            if (property and property.isModified()):
                opt.font.setBold(True)
                opt.fontMetrics = QFontMetrics(opt.font)

        c = QColor()
        if (not hasValue and self.m_editorPrivate.markPropertiesWithoutValue()):
            c = opt.palette.color(QPalette.Dark)
            opt.palette.setColor(QPalette.Text, opt.palette.color(QPalette.BrightText))
        else:
            c = self.m_editorPrivate.calculatedBackgroundColor(self.m_editorPrivate.indexToBrowserItem(index))
            if (c.isValid() and (opt.features & QStyleOptionViewItem.Alternate)):
                c = c.lighter(112)

        if (c.isValid()):
            painter.fillRect(option.rect, c)
        opt.state &= ~QStyle.State_HasFocus

        if (index.column() == 1):
            item = self.m_editorPrivate.indexToItem(index)
            if (self.m_editedItem and (self.m_editedItem == item)):
                self.m_disablePainting = True

        super(QtPropertyEditorDelegate, self).paint(painter, opt, index)
        if (option.type):
            self.m_disablePainting = False

        opt.palette.setCurrentColorGroup(QPalette.Active)
        color = QApplication.style().styleHint(QStyle.SH_Table_GridLineColor, opt)
        painter.save()
        painter.setPen(QPen(color))
        if (not self.m_editorPrivate or (not self.m_editorPrivate.lastColumn(index.column()) and hasValue)):
            if option.direction == Qt.LeftToRight:
                right = option.rect.right()
            else:
                right = option.rect.left()
            painter.drawLine(right, option.rect.y(), right, option.rect.bottom())

        painter.restore()
Exemplo n.º 12
0
 def func():
     bg = QColor(obj.getColor())
     color = QColorDialog.getColor(bg)
     if not QColor.isValid(color):
         return
     obj.setColor(color.name())
     self.setSetting('Graph/' + key, color.name())
Exemplo n.º 13
0
    def askForColorChange(self):
        if (self.selectedPolygon is not None):
            color = QColorDialog.getColor()

            if (QColor.isValid(color)):
                self.setColor(color)
                self.selectedPolygon.setColor(color)
Exemplo n.º 14
0
    def set_colors(self, colors: List[Union[str, QColor]],
                   polygons: List[Union[int, str, NodePolygon]] = [],
                   brush_styles: List[Union[str, Qt.BrushStyle]] = []):
        self.lstColors.clear()
        for color, poly, brush_style in zip_longest(colors, polygons, brush_styles):
            if isinstance(color, str):
                color = QColor(color)

            if isinstance(poly, str):
                try:
                    poly = NodePolygon[poly]
                except KeyError:
                    poly = NodePolygon.Circle
            if isinstance(poly, int):
                poly = NodePolygon(poly)

            if isinstance(brush_style, str):
                brush_style = Qt.BrushStyle(int(brush_style))

            if color.isValid():
                item = ColorListWidgetItem()
                item.setBackground(color)
                if poly is not None:
                    item.setData(BaseColorMappingDialog.PolygonRole, poly)
                if brush_style is not None:
                    item.setData(BaseColorMappingDialog.BrushStyleRole, brush_style)
                self.lstColors.addItem(item)
Exemplo n.º 15
0
def load_theme(name):
    theme_data = available_themes()[name]
    global FLAGS
    FLAGS = theme_data.get("flags")
    global DEFAULT_EDITOR_SCHEME
    DEFAULT_EDITOR_SCHEME = theme_data.get("editor-theme")
    colors = theme_data.get("colors")
    palette = theme_data.get("palette")
    # Create colors
    for role, color in colors.items():
        qcolor = QColor(color)
        if not qcolor.isValid():
            logger.warning("The color '%s' for '%s' is not valid" %
                           (color, role))
            # If color is invalid, set white
            qcolor = QColor(Qt.white)
        COLORS[role] = qcolor
    qpalette = QApplication.palette()
    if FLAGS["PaletteFromTheme"]:
        for role, color in palette.items():
            qcolor = QColor(color)
            color_group = QPalette.All
            if role.endswith("Disabled"):
                role = role.split("Disabled")[0]
                color_group = QPalette.Disabled
            color_role = getattr(qpalette, role)
            qpalette.setBrush(color_group, color_role, qcolor)
            COLORS[role] = qcolor
    QApplication.setPalette(qpalette)
def read_hand_drawing(file_name, db):
    try:
        with open(file_name, encoding='utf8') as f:
            draw_sections = []
            line = f.readline()
            while line != '':
                line = line.strip()
                if line != '':
                    try:
                        colour = QColor(line)
                        if not colour.isValid():
                            raise ValueError('Not a colour: ' + line)
                        points = []
                        tokens = f.readline().split(maxsplit=1)
                        while len(tokens) != 0:
                            text = tokens[1].strip() if len(
                                tokens) == 2 else None
                            points.append((read_point_spec(tokens[0],
                                                           db), text))
                            tokens = f.readline().split(maxsplit=1)
                        if len(points) == 0:
                            raise ValueError('No points in sequence')
                    except (NavpointError,
                            ValueError) as err:  # error on line;
                        print('Drawing spec error in %s section %d: %s' %
                              (file_name, len(draw_sections) + 1, err))
                        while line != '':  # skip until next empty line or EOF
                            line = f.readline().strip()
                    else:
                        draw_sections.append((colour, points))
                line = f.readline()
        return draw_sections
    except FileNotFoundError:
        raise ValueError('Drawing file not found')
Exemplo n.º 17
0
    def update_color(self, event: QColor) -> None:
        """
        更新颜色
        两种方式同时
        :param event:
        :return:
        """
        # print(event, type(event))
        # print(self.color_dialog.selectedColor(), type(self.color_dialog.selectedColor()))

        # QPalette.Background   表示设置背景色
        # QPalette.WindowText  表示设置文本颜色
        self.palette.setColor(QPalette.Background, event)  # 给调色板设置颜色
        self.palette.setBrush(QPalette.Base, QBrush(QColor(*event.getRgb())))
        # self.palette.setColor(QPalette.Background, self.color_dialog.selectedColor())  # 给调色板设置颜色

        # 给控件设置颜色
        if event.isValid():
            # self.main_window.setStyleSheet('QWidget {background-color:%s}' % event.name())
            # self.main_window.setPalette(self.palette)
            self.color_dialog.setStyleSheet('QWidget {background-color:%s}' %
                                            event.name())
            self.color_dialog.setPalette(self.palette)
            # 发色信号
            communicate.skin_color.emit(event)
Exemplo n.º 18
0
def main(argv):
    args = parse_args(argv[1:])
    color = QColor(args.color)
    if not color.isValid():
        raise Exception("invalid color name")

    fullscreenn_flashlight(color, args)
Exemplo n.º 19
0
 def setFromOption(self):
     """Set color based on the option setting.
     """
     colorStr = globalref.miscOptions[self.roleKey + 'Color']
     color = QColor(colorStr)
     if color.isValid():
         self.currentColor = color
Exemplo n.º 20
0
 def setFromOption(self, option):
     """Set color based on the option setting.
     """
     colorStr = '#' + option.strData(self.roleKey + 'Color', True)
     color = QColor(colorStr)
     if color.isValid():
         self.currentColor = color
Exemplo n.º 21
0
 def actionSetMoveLineColorSlot(self) -> None:
     # Inspector doesn't understand Qt's static methods
     # noinspection PyCallByClass,PyTypeChecker
     color = QColorDialog.getColor(self.moveLineColor, self,
                                   'Select new move line color')
     if QColor.isValid(color):
         self.moveLineColor = color
Exemplo n.º 22
0
def get_valid_color(screen, color_type, palette, default):
    """
    Get a valid QColor object.
    :param screen: Screen specification
    :param color_type: color key in the Screen specification
    :param palette: Palette specification
    :param default: default QColor object
    :return: valid QColor object
    """
    try:
        color = eval(screen[color_type], None, None)
    except (NameError, SyntaxError):
        color = screen[color_type]
    except KeyError:
        return default

    if type(color) is tuple:
        qc = QColor(*color)
    elif type(color) is str and palette and color in palette:
        qc = QColor(palette[color])
    else:
        qc = QColor(color)

    if not qc.isValid():
        qc = default

    return qc
Exemplo n.º 23
0
class LandBattleFieldType:
    """Class LandBattleFieldType
    """
    def __init__(self, name, color, texture):
        if not isinstance(name, str) or name == '':
            raise ValueError('name must be a non empty string')
        if texture is not None and (not isinstance(texture, str)
                                    or texture == ''):
            raise ValueError('texture must be a non empty string')
        if color is not None and (not isinstance(color, str) or color == ''):
            raise ValueError('color must be a non empty string')
        self.color = QColor(color)
        self.color_str = color
        self.texture_str = texture
        self.texture = QPixmap(texture)
        if not self.color.isValid() and self.texture.isNull():
            raise ValueError('texture or color must be specified')
        self.name = name

    def __str__(self):
        return self.name

    def __repr__(self):
        return 'name=\'%s\' color=\'%s\' texture=\'%s\'' % (
            self.name, self.color_str, self.texture_str)
Exemplo n.º 24
0
    def __init__(self,
                 action: QAction = None,
                 color_group=None,
                 default_color=Qt.blue,
                 *args,
                 **kwargs):
        super().__init__(*args, **kwargs)

        self.last_color_action = action if action is not None else QAction(
            self)
        self._color_group = color_group

        dialog_action = QWidgetAction(self)
        self._dialog = QColorDialog(self)

        self.btReset = None
        button_box = self._dialog.findChild(QDialogButtonBox, "")
        if button_box is not None:
            self.btReset = button_box.addButton(QDialogButtonBox.Reset)

        self._dialog.setWindowFlags(Qt.Widget)
        self._dialog.setOptions(self._dialog.options()
                                | QColorDialog.DontUseNativeDialog)
        dialog_action.setDefaultWidget(self._dialog)

        # Hide pick screen color button
        button = self._dialog.findChild(QAbstractButton)
        if button:
            button.hide()

        # Load custom colors
        settings = QSettings()
        settings.beginGroup("Colors")
        custom_colors = settings.value("Custom", [])
        for i, color in enumerate(custom_colors):
            self._dialog.setCustomColor(i, color)
        current_color = QColor(default_color) if color_group is None\
            else settings.value(f"{color_group}/Current", QColor(default_color), type=QColor)
        if current_color.isValid():
            self._dialog.setCurrentColor(current_color)
            self.on_color_selected(current_color)
        settings.endGroup()

        menu = QMenu()
        menu.addAction(dialog_action)

        self.setMenu(menu)
        self.setPopupMode(QToolButton.MenuButtonPopup)
        self.setDefaultAction(self.last_color_action)

        # Connect events
        self.colorSelected = self._dialog.colorSelected
        if self.btReset is not None:
            self.btReset.clicked.connect(self.colorReset.emit)
        self.currentColorChanged = self._dialog.currentColorChanged
        menu.aboutToShow.connect(self._dialog.show)
        self._dialog.rejected.connect(menu.hide)
        self._dialog.colorSelected.connect(menu.hide)
        self._dialog.colorSelected.connect(self.on_color_selected)
        self.last_color_action.triggered.connect(self.on_use_last_color)
Exemplo n.º 25
0
    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole and index.column() == self.ColumnID.Color:
            row = index.row()
            brushColor = QColor(value[0])
            pmapColor = QColor(value[1])
            if brushColor.isValid() and pmapColor.isValid():
                logger.debug("setData: brushColor = {}, pmapColor = {}" "".format(brushColor.name(), pmapColor.name()))
                logger.debug("  self._elements[row] has type {}" "".format(type(self._elements[row])))
                self._elements[row].setBrushColor(brushColor)
                self._elements[row].setPmapColor(pmapColor)
                logger.debug("  self._elements[row].brushColor = {}" "".format(self._elements[row].brushColor().name()))
                logger.debug("  self._elements[row].pmapColor  = {}" "".format(self._elements[row].pmapColor().name()))
                self.dataChanged.emit(index, index)
                return True

        else:
            return ListModel.setData(self, index, value, role)
Exemplo n.º 26
0
    def setSweepColor(self, color : QtGui.QColor):
        if color.isValid():
            self.color = color
            p = self.btnColorPicker.palette()
            p.setColor(QtGui.QPalette.ButtonText, color)
            self.btnColorPicker.setPalette(p)

            for c in self.charts:
                c.setSweepColor(color)
Exemplo n.º 27
0
 def setCorkColor(self):
     color = QColor(settings.corkBackground["color"])
     self.colorDialog = QColorDialog(color, self)
     color = self.colorDialog.getColor(color)
     if color.isValid():
         settings.corkBackground["color"] = color.name()
         self.updateCorkColor()
         # Update Cork view 
         self.mw.mainEditor.updateCorkBackground()
Exemplo n.º 28
0
 def setCorkColor(self):
     color = QColor(settings.corkBackground["color"])
     self.colorDialog = QColorDialog(color, self)
     color = self.colorDialog.getColor(color)
     if color.isValid():
         settings.corkBackground["color"] = color.name()
         self.updateCorkColor()
         # Update Cork view
         self.mw.mainEditor.updateCorkBackground()
Exemplo n.º 29
0
class ColorMatch(QWidget, Ui_ColorMatch):
    """Main Window."""

    def __init__(self):
        QWidget.__init__(self)
        self.setupUi(self)
        self.selectedColor = None
        self.colorButton.clicked.connect(self.colorButtonClicked)

        self.rRangeSpinBox.valueChanged.connect(self.updateColors)
        self.gRangeSpinBox.valueChanged.connect(self.updateColors)
        self.bRangeSpinBox.valueChanged.connect(self.updateColors)

    def colorButtonClicked(self):
        try:
            if self.selectedColor is not None:
                    self.selectedColor = QColorDialog().getColor(self.selectedColor)
            else:
                    self.selectedColor = QColorDialog().getColor()
            if self.selectedColor.isValid():
                self.updateColors();
        except Exception as e:
            logging.exception(e)

    def updateColors(self):
        if self.selectedColor is not None:
            rgb = [self.selectedColor.red(),self.selectedColor.green(),self.selectedColor.blue()]
            self.lowerColor, self.upperColor = ColorUtils.getColorRange(rgb, self.rRangeSpinBox.value(), self.gRangeSpinBox.value(), self.bRangeSpinBox.value())
            #Convert the RGB tuples to hex for CSS
            hex_lower = '#%02x%02x%02x' % self.lowerColor
            hex_upper = '#%02x%02x%02x' % self.upperColor
            self.min_color.setStyleSheet("background-color: "+hex_lower)
            self.mid_color.setStyleSheet("background-color: "+self.selectedColor.name())
            self.max_color.setStyleSheet("background-color: "+hex_upper)

    def getOptions(self):
        options = dict()
        options['color_range'] = [self.lowerColor, self.upperColor]
        options['selected_color'] = (self.selectedColor.red(),self.selectedColor.green(),self.selectedColor.blue())
        options['range_values']=(self.rRangeSpinBox.value(), self.gRangeSpinBox.value(), self.bRangeSpinBox.value())
        return options

    def validate(self):
        if self.selectedColor is None:
            return "Please select a search color."
        return None;

    def loadOptions(self, options):
        if 'range_values' in options and 'selected_color' in options:
            ranges = literal_eval(options['range_values'])
            self.rRangeSpinBox.setValue(ranges[0])
            self.gRangeSpinBox.setValue(ranges[1])
            self.bRangeSpinBox.setValue(ranges[2])
            selected_color = literal_eval(options['selected_color'])
            self.selectedColor = QColor(selected_color[0],selected_color[1],selected_color[2])
            self.updateColors()
Exemplo n.º 30
0
    def import_color_item(self, row: List[str]) -> Tuple:
        color = QColor(row[1][0])
        try:
            polygon_id = NodePolygon[row[1][1]] if len(row[1]) > 1 else NodePolygon.Circle
        except KeyError:
            polygon_id = NodePolygon.Circle
        brushstyle = Qt.BrushStyle(row[1][2]) if len(row[1]) > 2 else Qt.NoBrush

        if color.isValid():
            return color, polygon_id, brushstyle
Exemplo n.º 31
0
 def set_main_color(self, color_str=''):
     if color_str == '':
         color = QColorDialog.getColor()
     else:
         print(color_str)
         color = QColor(color_str)
     if color.isValid():
         self.myMainColor = QColor(color)
         self.main_color_pixmap.fill(self.myMainColor)
         self.mColorAction.setIcon(QIcon(self.main_color_pixmap))
Exemplo n.º 32
0
    def __get_cut_line_color(self):
        color = QColorDialog.getColor()

        if not QColor.isValid(color):
            return

        self.pen_res.setColor(color)
        hexcolor = color.name()
        self.cut_line_color.setStyleSheet('QPushButton{background-color:' +
                                          hexcolor + '}')
Exemplo n.º 33
0
    def to_py(self, value):
        self._basic_py_validation(value, str)
        if not value:
            return None

        color = QColor(value)
        if color.isValid():
            return color
        else:
            raise configexc.ValidationError(value, "must be a valid color")
Exemplo n.º 34
0
 def setWidgetCategory(self, desc):
     """
     Set the widget category.
     """
     self.category_description = desc
     if desc and desc.background:
         background = NAMED_COLORS.get(desc.background, desc.background)
         color = QColor(background)
         if color.isValid():
             self.setColor(color)
Exemplo n.º 35
0
    def to_py(self, value):
        self._basic_py_validation(value, str)
        if not value:
            return None

        color = QColor(value)
        if color.isValid():
            return color
        else:
            raise configexc.ValidationError(value, "must be a valid color")
Exemplo n.º 36
0
 def setSecondarySweepColor(self, color: QtGui.QColor):
     if color.isValid():
         self.secondarySweepColor = color
         p = self.btnSecondaryColorPicker.palette()
         p.setColor(QtGui.QPalette.ButtonText, color)
         self.btnSecondaryColorPicker.setPalette(p)
         self.app.settings.setValue("SecondarySweepColor", color)
         self.app.settings.sync()
         for c in self.app.subscribing_charts:
             c.setSecondarySweepColor(color)
Exemplo n.º 37
0
    def changeColor(self, index):
        row = index.row()
        color = self._model_data[row]['color']
        color_256 = [color[0] * 255, color[1] * 255, color[2] * 255]
        qcolor = _QColor(color_256[0], color_256[1], color_256[2])

        result = _QColorDialog.getColor(qcolor)
        if _QColor.isValid(result):
            self.setData(index, result.getRgb())
        else:
            return None
Exemplo n.º 38
0
    def changeColor(self, index):
        row = index.row()
        color = self._model_data[row]['color']
        color_256 = [color[0]*255, color[1]*255, color[2]*255]
        qcolor = _QColor(color_256[0], color_256[1], color_256[2])

        result = _QColorDialog.getColor(qcolor)
        if _QColor.isValid(result):
            self.setData(index, result.getRgb())
        else:
            return None
Exemplo n.º 39
0
    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole  and index.column() == self.ColumnID.Color:
            row = index.row()
            brushColor = QColor(value[0])
            pmapColor = QColor(value[1])
            if brushColor.isValid() and pmapColor.isValid():
                logger.debug("setData: brushColor = {}, pmapColor = {}"
                             "".format(brushColor.name(), pmapColor.name()))
                logger.debug("  self._elements[row] has type {}"
                             "".format(type(self._elements[row])))
                self._elements[row].setBrushColor(brushColor)
                self._elements[row].setPmapColor(pmapColor)
                logger.debug("  self._elements[row].brushColor = {}"
                             "".format(self._elements[row].brushColor().name()))
                logger.debug("  self._elements[row].pmapColor  = {}"
                             "".format(self._elements[row].pmapColor().name()))
                self.dataChanged.emit(index, index)
                return True

        else:
            return ListModel.setData(self, index, value, role)
Exemplo n.º 40
0
    def changeColor(self, index):
        row = index.row()
        col = index.column()

        if col == TableModelBars._COL_FACECOLOR:
            color = self._model_data[row]['facecolor']
        elif col == TableModelBars._COL_EDGECOLOR:
            color = self._model_data[row]['edgecolor']
        color_256 = [color[0]*255, color[1]*255, color[2]*255]
        qcolor = _QColor(color_256[0], color_256[1], color_256[2])

        result = _QColorDialog.getColor(qcolor)
        if _QColor.isValid(result):
            self.setData(index, result.getRgb())
        else:
            return None
Exemplo n.º 41
0
 def updateColor(self, item):
     pixmap = QPixmap(16, 16)
     color = QColor()
     if item:
         color = item.backgroundColor()
     if not color.isValid():
         color = self.palette().base().color()
     painter = QPainter(pixmap)
     painter.fillRect(0, 0, 16, 16, color)
     lighter = color.lighter()
     painter.setPen(lighter)
     # light frame
     painter.drawPolyline(QPoint(0, 15), QPoint(0, 0), QPoint(15, 0))
     painter.setPen(color.darker())
     # dark frame
     painter.drawPolyline(QPoint(1, 15), QPoint(15, 15), QPoint(15, 1))
     painter.end()
     self.colorAction.setIcon(QIcon(pixmap))
Exemplo n.º 42
0
 def setColor(self, color):
     if type(color)!=QColor:
         color = QColor(color)
     if (self.mColor == color or not color.isValid()):
         return
     self.mColor = color
     size = QSize(self.iconSize())
     size.setWidth(size.width()-2)
     size.setHeight(size.height()-2)
     pixmap = QPixmap(size)
     pixmap.fill(self.mColor)
     painter = QPainter(pixmap)
     border = QColor(Qt.black)
     border.setAlpha(128)
     painter.setPen(border)
     painter.drawRect(0, 0, pixmap.width() - 1, pixmap.height() - 1)
     painter.end()
     self.setIcon(QIcon(pixmap))
     self.colorChanged.emit(color)
Exemplo n.º 43
0
class ImageLayer(Layer):
    ##
    # Constructor.
    ##
    def __init__(self, name, x, y, width, height):
        super().__init__(Layer.ImageLayerType, name, x, y, width, height)

        self.mImage = QPixmap()
        self.mTransparentColor = QColor()
        self.mImageSource = QString()

    ##
    # Destructor.
    ##
    def __del__(self):
        pass

    def usedTilesets(self):
        return QSet()

    def referencesTileset(self, arg1):
        return False

    def replaceReferencesToTileset(self, arg1, arg2):
        pass

    def canMergeWith(self, arg1):
        return False

    def mergedWith(self, arg1):
        return None

    ##
    # Returns the transparent color, or an invalid color if no transparent
    # color is used.
    ##
    def transparentColor(self):
        return QColor(self.mTransparentColor)

    ##
    # Sets the transparent color. Pixels with this color will be masked out
    # when loadFromImage() is called.
    ##
    def setTransparentColor(self, c):
        self.mTransparentColor = c

    ##
    #  Sets image source file name
    ##
    def setSource(self, source):
        self.mImageSource = source

    ##
    # Returns the file name of the layer image.
    ##
    def imageSource(self):
        return self.mImageSource

    ##
    # Returns the image of this layer.
    ##
    def image(self):
        return QPixmap(self.mImage)

    ##
    # Sets the image of this layer.
    ##
    def setImage(self, image):
        self.mImage = image

    ##
    # Resets layer image.
    ##
    def resetImage(self):
        self.mImage = QPixmap()
        self.mImageSource = ''

    ##
    # Load this layer from the given \a image. This will replace the existing
    # image. The \a fileName becomes the new imageSource, regardless of
    # whether the image could be loaded.
    #
    # @param image    the image to load the layer from
    # @param fileName the file name of the image, which will be remembered
    #                 as the image source of this layer.
    # @return <code>true</code> if loading was successful, otherwise
    #         returns <code>false</code>
    ##
    def loadFromImage(self, image, fileName):
        self.mImageSource = fileName
        if (image.isNull()):
            self.mImage = QPixmap()
            return False

        self.mImage = QPixmap.fromImage(image)
        if (self.mTransparentColor.isValid()):
            mask = image.createMaskFromColor(self.mTransparentColor.rgb())
            self.mImage.setMask(QBitmap.fromImage(mask))

        return True

    ##
    # Returns True if no image source has been set.
    ##
    def isEmpty(self):
        return self.mImage.isNull()

    def clone(self):
        return self.initializeClone(ImageLayer(self.mName, self.mX, self.mY, self.mWidth, self.mHeight))

    def initializeClone(self, clone):
        super().initializeClone(clone)
        clone.mImageSource = self.mImageSource
        clone.mTransparentColor = self.mTransparentColor
        clone.mImage = self.mImage
        return clone
Exemplo n.º 44
0
class Tileset(Object):
    ##
    # Constructor.
    #
    # @param name        the name of the tileset
    # @param tileWidth   the width of the tiles in the tileset
    # @param tileHeight  the height of the tiles in the tileset
    # @param tileSpacing the spacing between the tiles in the tileset image
    # @param margin      the margin around the tiles in the tileset image
    ##
    def __init__(self, name, tileWidth, tileHeight, tileSpacing = 0, margin = 0):
        super().__init__(Object.TilesetType)

        self.mName = name
        self.mTileWidth = tileWidth
        self.mTileHeight = tileHeight
        self.mTileSpacing = tileSpacing
        self.mMargin = margin
        self.mImageWidth = 0
        self.mImageHeight = 0
        self.mColumnCount = 0
        self.mTerrainDistancesDirty = False

        self.mTileOffset = QPoint()
        self.mFileName = QString()
        self.mTiles = QList()
        self.mTransparentColor = QColor()
        self.mImageSource = QString()
        self.mTerrainTypes = QList()
        self.mWeakPointer = None

    ##
    # Destructor.
    ##
    def __del__(self):
        self.mTiles.clear()
        self.mTerrainTypes.clear()

    def create(name, tileWidth, tileHeight, tileSpacing = 0, margin = 0):
        tileset = Tileset(name, tileWidth, tileHeight, tileSpacing, margin)
        tileset.mWeakPointer = tileset
        return tileset
    
    def __iter__(self):
        return self.mTiles.__iter__()
        
    ##
    # Returns the name of this tileset.
    ##
    def name(self):
        return self.mName

    ##
    # Sets the name of this tileset.
    ##
    def setName(self, name):
        self.mName = name

    ##
    # Returns the file name of this tileset. When the tileset isn't an
    # external tileset, the file name is empty.
    ##
    def fileName(self):
        return self.mFileName

    ##
    # Sets the filename of this tileset.
    ##
    def setFileName(self, fileName):
        self.mFileName = fileName

    ##
    # Returns whether this tileset is external.
    ##
    def isExternal(self):
        return self.mFileName!=''

    ##
    # Returns the maximum width of the tiles in this tileset.
    ##
    def tileWidth(self):
        return self.mTileWidth

    ##
    # Returns the maximum height of the tiles in this tileset.
    ##
    def tileHeight(self):
        return self.mTileHeight

    ##
    # Returns the maximum size of the tiles in this tileset.
    ##
    def tileSize(self):
        return QSize(self.mTileWidth, self.mTileHeight)

    ##
    # Returns the spacing between the tiles in the tileset image.
    ##
    def tileSpacing(self):
        return self.mTileSpacing

    ##
    # Returns the margin around the tiles in the tileset image.
    ##
    def margin(self):
        return self.mMargin

    ##
    # Returns the offset that is applied when drawing the tiles in this
    # tileset.
    ##
    def tileOffset(self):
        return self.mTileOffset

    ##
    # @see tileOffset
    ##
    def setTileOffset(self, offset):
        self.mTileOffset = offset

    ##
    # Returns a const reference to the list of tiles in this tileset.
    ##
    def tiles(self):
        return QList(self.mTiles)

    ##
    # Returns the tile for the given tile ID.
    # The tile ID is local to this tileset, which means the IDs are in range
    # [0, tileCount() - 1].
    ##
    def tileAt(self, id):
        if id < self.mTiles.size():
            return self.mTiles.at(id)
        return None

    ##
    # Returns the number of tiles in this tileset.
    ##
    def tileCount(self):
        return self.mTiles.size()

    ##
    # Returns the number of tile columns in the tileset image.
    ##
    def columnCount(self):
        return self.mColumnCount

    ##
    # Returns the width of the tileset image.
    ##
    def imageWidth(self):
        return self.mImageWidth

    ##
    # Returns the height of the tileset image.
    ##
    def imageHeight(self):
        return self.mImageHeight

    ##
    # Returns the transparent color, or an invalid color if no transparent
    # color is used.
    ##
    def transparentColor(self):
        return QColor(self.mTransparentColor)

    ##
    # Sets the transparent color. Pixels with this color will be masked out
    # when loadFromImage() is called.
    ##
    def setTransparentColor(self, c):
        self.mTransparentColor = c

    ##
    # Load this tileset from the given tileset \a image. This will replace
    # existing tile images in this tileset with new ones. If the new image
    # contains more tiles than exist in the tileset new tiles will be
    # appended, if there are fewer tiles the excess images will be blanked.
    #
    # The tile width and height of this tileset must be higher than 0.
    #
    # @param image    the image to load the tiles from
    # @param fileName the file name of the image, which will be remembered
    #                 as the image source of this tileset.
    # @return <code>true</code> if loading was successful, otherwise
    #         returns <code>false</code>
    ##
    def loadFromImage(self, *args):
        l = len(args)
        if l==2:
            image, fileName = args

            tileSize = self.tileSize()
            margin = self.margin()
            spacing = self.tileSpacing()
    
            if (image.isNull()):
                return False
            stopWidth = image.width() - tileSize.width()
            stopHeight = image.height() - tileSize.height()
            oldTilesetSize = self.tileCount()
            tileNum = 0
            for y in range(margin, stopHeight+1, tileSize.height() + spacing):
                for x in range(margin, stopWidth+1, tileSize.width() + spacing):
                    tileImage = image.copy(x, y, tileSize.width(), tileSize.height())
                    tilePixmap = QPixmap.fromImage(tileImage)
                    if (self.mTransparentColor.isValid()):
                        mask = tileImage.createMaskFromColor(self.mTransparentColor.rgb())
                        tilePixmap.setMask(QBitmap.fromImage(mask))

                    if (tileNum < oldTilesetSize):
                        self.mTiles.at(tileNum).setImage(tilePixmap)
                    else:
                        self.mTiles.append(Tile(tilePixmap, tileNum, self))

                    tileNum += 1

            # Blank out any remaining tiles to avoid confusion
            while (tileNum < oldTilesetSize):
                tilePixmap = QPixmap(tileSize)
                tilePixmap.fill()
                self.mTiles.at(tileNum).setImage(tilePixmap)
                tileNum += 1

            self.mImageWidth = image.width()
            self.mImageHeight = image.height()
            self.mColumnCount = self.columnCountForWidth(self.mImageWidth)
            self.mImageSource = fileName
            return True
        elif l==1:
            ##
            # Convenience override that loads the image using the QImage constructor.
            ##
            fileName = args[0]
            return self.loadFromImage(QImage(fileName), fileName)

    ##
    # This checks if there is a similar tileset in the given list.
    # It is needed for replacing this tileset by its similar copy.
    ##
    def findSimilarTileset(self, tilesets):
        for candidate in tilesets:
            if (candidate.tileCount() != self.tileCount()):
                continue
            if (candidate.imageSource() != self.imageSource()):
                continue
            if (candidate.tileSize() != self.tileSize()):
                continue
            if (candidate.tileSpacing() != self.tileSpacing()):
                continue
            if (candidate.margin() != self.margin()):
                continue
            if (candidate.tileOffset() != self.tileOffset()):
                continue

            # For an image collection tileset, check the image sources
            if (self.imageSource()==''):
                if (not sameTileImages(self, candidate)):
                    continue

            return candidate
            
        return None

    ##
    # Returns the file name of the external image that contains the tiles in
    # this tileset. Is an empty string when this tileset doesn't have a
    # tileset image.
    ##
    def imageSource(self):
        return self.mImageSource

    ##
    # Returns the column count that this tileset would have if the tileset
    # image would have the given \a width. This takes into account the tile
    # size, margin and spacing.
    ##
    def columnCountForWidth(self, width):
        return int((width - self.mMargin + self.mTileSpacing) / (self.mTileWidth + self.mTileSpacing))

    ##
    # Returns a const reference to the list of terrains in this tileset.
    ##
    def terrains(self):
        return QList(self.mTerrainTypes)

    ##
    # Returns the number of terrain types in this tileset.
    ##
    def terrainCount(self):
        return self.mTerrainTypes.size()

    ##
    # Returns the terrain type at the given \a index.
    ##
    def terrain(self, index):
        if index >= 0:
            _x = self.mTerrainTypes[index]
        else:
            _x = None
        return _x

    ##
    # Adds a new terrain type.
    #
    # @param name      the name of the terrain
    # @param imageTile the id of the tile that represents the terrain visually
    # @return the created Terrain instance
    ##
    def addTerrain(self, name, imageTileId):
        terrain = Terrain(self.terrainCount(), self, name, imageTileId)
        self.insertTerrain(self.terrainCount(), terrain)
        return terrain

    ##
    # Adds the \a terrain type at the given \a index.
    #
    # The terrain should already have this tileset associated with it.
    ##
    def insertTerrain(self, index, terrain):
        self.mTerrainTypes.insert(index, terrain)
        # Reassign terrain IDs
        for terrainId in range(index, self.mTerrainTypes.size()):
            self.mTerrainTypes.at(terrainId).mId = terrainId
        # Adjust tile terrain references
        for tile in self.mTiles:
            for corner in range(4):
                terrainId = tile.cornerTerrainId(corner)
                if (terrainId >= index):
                    tile.setCornerTerrainId(corner, terrainId + 1)

        self.mTerrainDistancesDirty = True

    ##
    # Removes the terrain type at the given \a index and returns it. The
    # caller becomes responsible for the lifetime of the terrain type.
    #
    # This will cause the terrain ids of subsequent terrains to shift up to
    # fill the space and the terrain information of all tiles in this tileset
    # will be updated accordingly.
    ##
    def takeTerrainAt(self, index):
        terrain = self.mTerrainTypes.takeAt(index)
        # Reassign terrain IDs
        for terrainId in range(index, self.mTerrainTypes.size()):
            self.mTerrainTypes.at(terrainId).mId = terrainId

        # Clear and adjust tile terrain references
        for tile in self.mTiles:
            for corner in range(4):
                terrainId = tile.cornerTerrainId(corner)
                if (terrainId == index):
                    tile.setCornerTerrainId(corner, 0xFF)
                elif (terrainId > index):
                    tile.setCornerTerrainId(corner, terrainId - 1)

        self.mTerrainDistancesDirty = True
        return terrain

    ##
    # Returns the transition penalty(/distance) between 2 terrains. -1 if no
    # transition is possible.
    ##
    def terrainTransitionPenalty(self, terrainType0, terrainType1):
        if (self.mTerrainDistancesDirty):
            self.recalculateTerrainDistances()
            self.mTerrainDistancesDirty = False

        if terrainType0 == 255:
            terrainType0 = -1
        if terrainType1 == 255:
            terrainType1 = -1

        # Do some magic, since we don't have a transition array for no-terrain
        if (terrainType0 == -1 and terrainType1 == -1):
            return 0
        if (terrainType0 == -1):
            return self.mTerrainTypes.at(terrainType1).transitionDistance(terrainType0)
        return self.mTerrainTypes.at(terrainType0).transitionDistance(terrainType1)

    ##
    # Adds a new tile to the end of the tileset.
    ##
    def addTile(self, image, source=QString()):
        newTile = Tile(image, source, self.tileCount(), self)
        self.mTiles.append(newTile)
        if (self.mTileHeight < image.height()):
            self.mTileHeight = image.height()
        if (self.mTileWidth < image.width()):
            self.mTileWidth = image.width()
        return newTile

    def insertTiles(self, index, tiles):
        count = tiles.count()
        for i in range(count):
            self.mTiles.insert(index + i, tiles.at(i))
        # Adjust the tile IDs of the remaining tiles
        for i in range(index + count, self.mTiles.size()):
            self.mTiles.at(i).mId += count
        self.updateTileSize()

    def removeTiles(self, index, count):
        first = self.mTiles.begin() + index
        last = first + count
        last = self.mTiles.erase(first, last)
        # Adjust the tile IDs of the remaining tiles
        for last in self.mTiles:
            last.mId -= count
        self.updateTileSize()

    ##
    # Sets the \a image to be used for the tile with the given \a id.
    ##
    def setTileImage(self, id, image, source = QString()):
        # This operation is not supposed to be used on tilesets that are based
        # on a single image
        tile = self.tileAt(id)
        if (not tile):
            return
        previousImageSize = tile.image().size()
        newImageSize = image.size()
        tile.setImage(image)
        tile.setImageSource(source)
        if (previousImageSize != newImageSize):
            # Update our max. tile size
            if (previousImageSize.height() == self.mTileHeight or
                    previousImageSize.width() == self.mTileWidth):
                # This used to be the max image; we have to recompute
                self.updateTileSize()
            else:
                # Check if we have a new maximum
                if (self.mTileHeight < newImageSize.height()):
                    self.mTileHeight = newImageSize.height()
                if (self.mTileWidth < newImageSize.width()):
                    self.mTileWidth = newImageSize.width()

    ##
    # Used by the Tile class when its terrain information changes.
    ##
    def markTerrainDistancesDirty(self):
        self.mTerrainDistancesDirty = True

    ##
    # Sets tile size to the maximum size.
    ##
    def updateTileSize(self):
        maxWidth = 0
        maxHeight = 0
        for tile in self.mTiles:
            size = tile.size()
            if (maxWidth < size.width()):
                maxWidth = size.width()
            if (maxHeight < size.height()):
                maxHeight = size.height()

        self.mTileWidth = maxWidth
        self.mTileHeight = maxHeight

    ##
    # Calculates the transition distance matrix for all terrain types.
    ##
    def recalculateTerrainDistances(self):
        # some fancy macros which can search for a value in each byte of a word simultaneously
        def hasZeroByte(dword):
            return (dword - 0x01010101) & ~dword & 0x80808080

        def hasByteEqualTo(dword, value):
            return hasZeroByte(dword ^ int(~0/255 * value))

        # Terrain distances are the number of transitions required before one terrain may meet another
        # Terrains that have no transition path have a distance of -1
        for i in range(self.terrainCount()):
            type = self.terrain(i)
            distance = QVector()
            for _x in range(self.terrainCount() + 1):
                distance.append(-1)
            # Check all tiles for transitions to other terrain types
            for j in range(self.tileCount()):
                t = self.tileAt(j)
                if (not hasByteEqualTo(t.terrain(), i)):
                    continue
                # This tile has transitions, add the transitions as neightbours (distance 1)
                tl = t.cornerTerrainId(0)
                tr = t.cornerTerrainId(1)
                bl = t.cornerTerrainId(2)
                br = t.cornerTerrainId(3)
                # Terrain on diagonally opposite corners are not actually a neighbour
                if (tl == i or br == i):
                    distance[tr + 1] = 1
                    distance[bl + 1] = 1

                if (tr == i or bl == i):
                    distance[tl + 1] = 1
                    distance[br + 1] = 1

                # terrain has at least one tile of its own type
                distance[i + 1] = 0

            type.setTransitionDistances(distance)

        # Calculate indirect transition distances
        bNewConnections = False
        # Repeat while we are still making new connections (could take a
        # number of iterations for distant terrain types to connect)
        while bNewConnections:
            bNewConnections = False
            # For each combination of terrain types
            for i in range(self.terrainCount()):
                t0 = self.terrain(i)
                for j in range(self.terrainCount()):
                    if (i == j):
                        continue
                    t1 = self.terrain(j)
                    # Scan through each terrain type, and see if we have any in common
                    for t in range(-1, self.terrainCount()):
                        d0 = t0.transitionDistance(t)
                        d1 = t1.transitionDistance(t)
                        if (d0 == -1 or d1 == -1):
                            continue
                        # We have cound a common connection
                        d = t0.transitionDistance(j)
                        # If the new path is shorter, record the new distance
                        if (d == -1 or d0 + d1 < d):
                            d = d0 + d1
                            t0.setTransitionDistance(j, d)
                            t1.setTransitionDistance(i, d)
                            # We're making progress, flag for another iteration...
                            bNewConnections = True

    def sharedPointer(self):
        return self.mWeakPointer