class gimpPaletteExporter:

    def __init__(self, name):
        # We want people to select a palette and a location to save to...
        self.fileName = QFileDialog.getExistingDirectory()
        allPalettes = Application.resources("palette")
        self.paletteName = name
        self.currentPalette = Palette(allPalettes[self.paletteName])
        self.export()
        done = QMessageBox()
        done.setWindowTitle(i18n("Export Successful"))
        done.setText(
            str(i18n("{input} has been exported to {output}.")).format(
                input=self.paletteName, output=self.fileName))
        done.exec_()
        pass

    def export(self):
        # open the appropriate file...
        gplFile = open(self.fileName + "/" + self.paletteName + ".gpl", "w")
        gplFile.write("GIMP Palette\n")
        gplFile.write("Name: %s\n" % self.paletteName)
        gplFile.write("Columns: %s/n", self.currentPalette.columnCount())
        gplFile.write("#%s\n" % self.currentPalette.comment())
        colorCount = self.currentPalette.colorsCountGroup("")

        for i in range(colorCount):
            entry = self.currentPalette.colorSetEntryFromGroup(i, "")
            color = self.currentPalette.colorForEntry(entry)
            # convert to sRGB
            color.setColorSpace("RGBA", "U8", "sRGB built-in")

            red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0)
            green = max(min(int(color.componentsOrdered()[1] * 255), 255), 0)
            blue = max(min(int(color.componentsOrdered()[2] * 255), 255), 0)
            gplFile.write(
                "{red} {green} {blue}    {id}-{name}\n".format(
                    red=red, green=green, blue=blue, id=entry.id(),
                    name=entry.name))
            groupNames = self.currentPalette.groupNames()
            for groupName in groupNames:
                colorCount = self.currentPalette.colorsCountGroup(groupName)
                for i in range(colorCount):
                    entry = self.currentPalette.colorSetEntryFromGroup(
                        i, groupName)
                    color = self.currentPalette.colorForEntry(entry)
                    # convert to sRGB
                    color.setColorSpace("RGBA", "U8", "sRGB built-in")
                    red = max(
                        min(int(color.componentsOrdered()[0] * 255), 255), 0)
                    green = max(
                        min(int(color.componentsOrdered()[1] * 255), 255), 0)
                    blue = max(
                        min(int(color.componentsOrdered()[2] * 255), 255), 0)
                    gplFile.write(
                        "{red} {green} {blue}    {id}-{name}\n".format(
                            red=red, green=green, blue=blue, id=entry.id(),
                            name=entry.name))
        gplFile.close()
class inkscapeSVGExporter:
    def __init__(self, name):
        # We want people to select a palette and a location to save to...
        self.fileName = QFileDialog.getExistingDirectory()
        allPalettes = Application.resources("palette")
        self.paletteName = name
        self.currentPalette = Palette(allPalettes[self.paletteName])
        self.export()
        done = QMessageBox()
        done.setWindowTitle(i18n("Export Successful"))
        done.setText(
            str(i18n("{input} has been exported to {output}.")).format(
                input=self.paletteName, output=self.fileName))
        done.exec_()
        pass

    def export(self):
        # open the appropriate file...
        svgFile = open(self.fileName + "/" + self.paletteName + ".svg", "w")
        svgDoc = QDomDocument()
        svgBaseElement = svgDoc.createElement("svg")
        svgBaseElement.setAttribute(
            "xmlns:osb", "http://www.openswatchbook.org/uri/2009/osb")
        svgBaseElement.setAttribute("xmlns:svg", "http://www.w3.org/2000/svg")
        svgBaseElement.setAttribute("xmlns:dc",
                                    "http://purl.org/dc/elements/1.1/")
        svgBaseElement.setAttribute("xmlns:cc",
                                    "http://creativecommons.org/ns#")
        svgBaseElement.setAttribute(
            "xmlns:rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
        svgDefs = svgDoc.createElement("defs")
        svgSwatches = svgDoc.createElement("g")
        svgSwatches.setAttribute("id", "Swatches")

        svgMeta = svgDoc.createElement("metadata")
        svgBaseElement.appendChild(svgMeta)
        rdf = svgDoc.createElement("rdf:RDF")
        ccwork = svgDoc.createElement("cc:Work")
        dctitle = svgDoc.createElement("dc:title")
        dcdescription = svgDoc.createElement("dc:description")
        dctitle.appendChild(svgDoc.createTextNode(self.paletteName))
        dcdescription.appendChild(
            svgDoc.createTextNode(self.currentPalette.comment()))
        ccwork.appendChild(dctitle)
        ccwork.appendChild(dcdescription)
        rdf.appendChild(ccwork)
        svgMeta.appendChild(rdf)
        Row = 0
        Column = 0
        iccProfileList = []

        colorCount = self.currentPalette.colorsCountGroup("")

        for i in range(colorCount):
            entry = self.currentPalette.colorSetEntryFromGroup(i, "")
            color = self.currentPalette.colorForEntry(entry)

            iccColor = "icc-color(" + color.colorProfile()
            for c in range(len(color.componentsOrdered()) - 1):
                iccColor = "{col},{c}".format(col=iccColor,
                                              c=color.componentsOrdered()[c])
            iccColor = iccColor + ")"
            if color.colorProfile() not in iccProfileList:
                iccProfileList.append(color.colorProfile())

            # convert to sRGB
            color.setColorSpace("RGBA", "U8", "sRGB built-in")
            red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0)
            green = max(min(int(color.componentsOrdered()[1] * 255), 255), 0)
            blue = max(min(int(color.componentsOrdered()[2] * 255), 255), 0)
            hexcode = "#{red:02x}{green:02x}{blue:02x}".format(red=red,
                                                               green=green,
                                                               blue=blue)
            swatchName = "{i}-{name}".format(i=i, name=entry.name())
            swatchName = swatchName.replace(" ", "-")
            swatchName = swatchName.replace("(", "-")
            swatchName = swatchName.replace(")", "-")
            swatchMain = svgDoc.createElement("linearGradient")
            swatchMain.setAttribute("osb:paint", "solid")
            swatchMain.setAttribute("id", swatchName)
            swatchSub = svgDoc.createElement("stop")
            swatchSub.setAttribute(
                "style", "stop-color: {hex} {color};stop-opacity:1;".format(
                    hex=hexcode, color=iccColor))
            swatchMain.appendChild(swatchSub)
            svgDefs.appendChild(swatchMain)
            svgSingleSwatch = svgDoc.createElement("rect")
            svgSingleSwatch.setAttribute("x", str(int(Column * 20)))
            svgSingleSwatch.setAttribute("y", str(int(Row * 20)))
            svgSingleSwatch.setAttribute("width", str(int(20)))
            svgSingleSwatch.setAttribute("height", str(int(20)))
            svgSingleSwatch.setAttribute("fill", "url(#%s)" % swatchName)
            svgSingleSwatch.setAttribute("id", "swatch %s" % swatchName)
            if entry.spotColor() is True:
                svgSingleSwatch.setAttribute("rx", str(10))
                svgSingleSwatch.setAttribute("ry", str(10))
            svgSwatches.appendChild(svgSingleSwatch)
            Column += 1
            if (Column >= self.currentPalette.columnCount()):
                Column = 0
                Row += 1

        groupNames = self.currentPalette.groupNames()
        for groupName in groupNames:
            Column = 0
            Row += 1
            groupTitle = svgDoc.createElement("text")
            groupTitle.setAttribute("x", str(int(Column * 20)))
            groupTitle.setAttribute("y", str(int(Row * 20) + 15))
            groupTitle.appendChild(svgDoc.createTextNode(groupName))
            svgSwatches.appendChild(groupTitle)
            Row += 1
            colorCount = self.currentPalette.colorsCountGroup(groupName)
            for i in range(colorCount):
                entry = self.currentPalette.colorSetEntryFromGroup(
                    i, groupName)
                color = self.currentPalette.colorForEntry(entry)
                iccColor = "icc-color(" + color.colorProfile()
                for c in range(len(color.componentsOrdered()) - 1):
                    iccColor = "{col},{c}".format(
                        col=iccColor, c=color.componentsOrdered()[c])
                iccColor = iccColor + ")"
                if color.colorProfile() not in iccProfileList:
                    iccProfileList.append(color.colorProfile())
                # convert to sRGB
                color.setColorSpace("RGBA", "U8", "sRGB built-in")
                red = max(min(int(color.componentsOrdered()[0] * 255), 255), 0)
                green = max(min(int(color.componentsOrdered()[1] * 255), 255),
                            0)
                blue = max(min(int(color.componentsOrdered()[2] * 255), 255),
                           0)
                hexcode = "#{red:02x}{green:02x}{blue:02x}".format(red=red,
                                                                   green=green,
                                                                   blue=blue)
                swatchName = groupName + str(i) + "-" + entry.name()
                swatchName = swatchName.replace(" ", "-")
                swatchName = swatchName.replace("(", "-")
                swatchName = swatchName.replace(")", "-")
                swatchMain = svgDoc.createElement("linearGradient")
                swatchMain.setAttribute("osb:paint", "solid")
                swatchMain.setAttribute("id", swatchName)
                swatchSub = svgDoc.createElement("stop")
                swatchSub.setAttribute(
                    "style",
                    "stop-color: {hex} {color};stop-opacity:1;".format(
                        hex=hexcode, color=iccColor))

                swatchMain.appendChild(swatchSub)
                svgDefs.appendChild(swatchMain)
                svgSingleSwatch = svgDoc.createElement("rect")
                svgSingleSwatch.setAttribute("x", str(int(Column * 20)))
                svgSingleSwatch.setAttribute("y", str(int(Row * 20)))
                svgSingleSwatch.setAttribute("width", str(int(20)))
                svgSingleSwatch.setAttribute("height", str(int(20)))
                svgSingleSwatch.setAttribute("fill", "url(#%s)" % swatchName)
                svgSingleSwatch.setAttribute("id", "swatch %s" % swatchName)
                if entry.spotColor() is True:
                    svgSingleSwatch.setAttribute("rx", str(10))
                    svgSingleSwatch.setAttribute("ry", str(10))
                svgSwatches.appendChild(svgSingleSwatch)
                Column += 1
                if (Column >= self.currentPalette.columnCount()):
                    Column = 0
                    Row += 1

        for profile in iccProfileList:
            svgProfileDesc = svgDoc.createElement("color-profile")
            svgProfileDesc.setAttribute("name", profile)
            # This is incomplete because python api doesn't have any
            # way to ask for this data yet.
            # svgProfileDesc.setAttribute("local", "sRGB")
            # svgProfileDesc.setAttribute("xlink:href", colorprofileurl)
            svgProfileDesc.setAttribute("rendering-intent", "perceptual")
            svgDefs.appendChild(svgProfileDesc)
        svgBaseElement.appendChild(svgDefs)
        svgBaseElement.appendChild(svgSwatches)
        svgBaseElement.setAttribute(
            "viewBox", "0 0 {cols} {row}".format(
                cols=self.currentPalette.columnCount() * 20,
                row=int((Row + 1) * 20)))
        svgDoc.appendChild(svgBaseElement)
        svgFile.write(svgDoc.toString())
        svgFile.close()
Example #3
0
class PaletteDocker(DockWidget):
    # Init the docker

    def __init__(self):
        super(PaletteDocker, self).__init__()
        # make base-widget and layout
        widget = QWidget()
        layout = QVBoxLayout()
        buttonLayout = QHBoxLayout()
        widget.setLayout(layout)
        self.setWindowTitle(i18n("Python Palette Docker"))

        # Make a combobox and add palettes
        self.cmb_palettes = QComboBox()
        allPalettes = Application.resources("palette")
        for palette_name in allPalettes:
            self.cmb_palettes.addItem(palette_name)
            self.cmb_palettes.model().sort(0)

        if len(allPalettes.keys()) > 0:
            self.currentPalette = Palette(list(allPalettes.values())[0])
        else:
            self.currentPalette = None

        self.cmb_palettes.currentTextChanged.connect(self.slot_paletteChanged)
        layout.addWidget(self.cmb_palettes)  # add combobox to the layout
        self.paletteView = PaletteView()
        self.paletteView.setPalette(self.currentPalette)
        layout.addWidget(self.paletteView)
        self.paletteView.entrySelectedForeGround.connect(
            self.slot_swatchSelected)

        self.colorComboBox = QComboBox()
        self.colorList = list()
        buttonLayout.addWidget(self.colorComboBox)
        self.bnSetColor = QToolButton()
        self.bnSetColor.setText(i18n("Set"))
        self.bnSetColor.clicked.connect(self.slot_get_color_from_combobox)
        buttonLayout.addWidget(self.bnSetColor)

        self.addEntry = QAction(self)
        self.addEntry.setIconText(i18n("+"))
        self.addEntry.triggered.connect(self.slot_add_entry)
        self.addGroup = QAction(self)
        self.addGroup.triggered.connect(self.slot_add_group)
        self.addGroup.setText(i18n("Add Group"))
        self.addGroup.setIconText(str("\U0001F4C2"))
        self.removeEntry = QAction(self)
        self.removeEntry.setText(i18n("Remove Entry"))
        self.removeEntry.setIconText("-")
        self.removeEntry.triggered.connect(self.slot_remove_entry)
        addEntryButton = QToolButton()
        addEntryButton.setDefaultAction(self.addEntry)
        buttonLayout.addWidget(addEntryButton)
        addGroupButton = QToolButton()
        addGroupButton.setDefaultAction(self.addGroup)
        buttonLayout.addWidget(addGroupButton)
        removeEntryButton = QToolButton()
        removeEntryButton.setDefaultAction(self.removeEntry)
        buttonLayout.addWidget(removeEntryButton)

        # QActions
        self.extra = QToolButton()
        self.editPaletteData = QAction(self)
        self.editPaletteData.setText(i18n("Edit Palette Settings"))
        self.editPaletteData.triggered.connect(self.slot_edit_palette_data)
        self.extra.setDefaultAction(self.editPaletteData)
        buttonLayout.addWidget(self.extra)
        self.actionMenu = QMenu()
        self.exportToGimp = QAction(self)
        self.exportToGimp.setText(i18n("Export as GIMP Palette File"))
        self.exportToGimp.triggered.connect(self.slot_export_to_gimp_palette)
        self.exportToInkscape = QAction(self)
        self.exportToInkscape.setText(
            i18n("Export as Inkscape SVG with Swatches"))
        self.exportToInkscape.triggered.connect(
            self.slot_export_to_inkscape_svg)
        self.sortColors = QAction(self)
        self.sortColors.setText(i18n("Sort Colors"))
        self.sortColors.triggered.connect(self.slot_sort_colors)
        self.actionMenu.addAction(self.editPaletteData)
        self.actionMenu.addAction(self.exportToGimp)
        self.actionMenu.addAction(self.exportToInkscape)
        # self.actionMenu.addAction(self.sortColors)

        self.extra.setMenu(self.actionMenu)

        layout.addLayout(buttonLayout)
        self.slot_fill_combobox()
        self.setWidget(widget)  # add widget to the docker

    def slot_paletteChanged(self, name):
        allPalettes = Application.resources("palette")
        if len(allPalettes) > 0 and name in allPalettes:
            self.currentPalette = Palette(
                Application.resources("palette")[name])
            self.paletteView.setPalette(self.currentPalette)
            self.slot_fill_combobox()

    @pyqtSlot('KisSwatch')
    def slot_swatchSelected(self, entry):
        if (self.canvas()) is not None:
            if (self.canvas().view()) is not None:
                name = entry.name()
                if len(entry.id) > 0:
                    name = entry.id() + " - " + entry.name()
                if len(name) > 0:
                    if name in self.colorList:
                        self.colorComboBox.setCurrentIndex(
                            self.colorList.index(name))
                color = self.currentPalette.colorForEntry(entry)
                self.canvas().view().setForeGroundColor(color)

    def slot_fill_combobox(self):
        '''A function for making a combobox with the available colors. We use
        QCompleter on the colorComboBox so that people can type in the
        name of a color to select it. This is useful for people with
        carefully made palettes where the colors are named properly,
        which makes it easier for them to find colors.
        '''

        if self.currentPalette is None:
            pass
        self.colorComboBox.clear()
        self.colorList = list()
        #        palette = self.currentPalette
        #        for info in palette.infoList():
        #            entry = info.swatch
        #            color = palette.colorForEntry(entry).colorForCanvas(self.canvas())
        #            colorSquare = QPixmap(12, 12)
        #            if entry.spotColor() is True:
        #                img = colorSquare.toImage()
        #                circlePainter = QPainter()
        #                img.fill(self.colorComboBox.palette().color(QPalette.Base))
        #                circlePainter.begin(img)
        #                brush = QBrush(Qt.SolidPattern)
        #                brush.setColor(color)
        #                circlePainter.setBrush(brush)
        #                circlePainter.pen().setWidth(0)
        #                circlePainter.drawEllipse(0, 0, 11, 11)
        #                circlePainter.end()
        #                colorSquare = QPixmap.fromImage(img)
        #            else:
        #                colorSquare.fill(color)
        #            name = entry.name()
        #            if len(entry.id()) > 0:
        #                name = entry.id() + " - " + entry.name()
        #            self.colorList.append(name)
        #            self.colorComboBox.addItem(QIcon(colorSquare), name)
        self.colorComboBox.setEditable(True)
        self.colorComboBox.setInsertPolicy(QComboBox.NoInsert)
        self.colorComboBox.completer().setCompletionMode(
            QCompleter.PopupCompletion)
        self.colorComboBox.completer().setCaseSensitivity(False)
        self.colorComboBox.completer().setFilterMode(Qt.MatchContains)

    def slot_get_color_from_combobox(self):
        if self.currentPalette is not None:
            entry = self.currentPalette.colorSetEntryByIndex(
                self.colorComboBox.currentIndex())
            self.slot_swatchSelected(entry)

    def slot_add_entry(self):
        if (self.canvas()) is not None:
            if (self.canvas().view()) is not None:
                color = self.canvas().view().foregroundColor()
                success = self.paletteView.addEntryWithDialog(color)
                if success is True:
                    self.slot_fill_combobox()

    def slot_add_group(self):
        success = self.paletteView.addGroupWithDialog()
        if success is True:
            self.slot_fill_combobox()

    def slot_remove_entry(self):
        success = self.paletteView.removeSelectedEntryWithDialog()
        if success is True:
            self.slot_fill_combobox()

    def slot_edit_palette_data(self):
        '''A function for giving a gui to edit palette metadata... I also
        want this to be the way to edit the settings of the palette
        docker.
        '''

        dialog = QDialog(self)
        tabWidget = QTabWidget()
        dialog.setWindowTitle(i18n("Edit Palette Data"))
        dialog.setLayout(QVBoxLayout())
        dialog.layout().addWidget(tabWidget)
        paletteWidget = QWidget()
        paletteWidget.setLayout(QVBoxLayout())
        tabWidget.addTab(paletteWidget, i18n("Palette Data"))
        paletteName = QLineEdit()
        paletteName.setText(self.cmb_palettes.currentText())
        paletteWidget.layout().addWidget(paletteName)
        paletteColumns = QSpinBox()
        paletteColumns.setValue(self.currentPalette.columnCount())
        paletteWidget.layout().addWidget(paletteColumns)
        paletteComment = QPlainTextEdit()
        paletteComment.appendPlainText(self.currentPalette.comment())
        paletteWidget.layout().addWidget(paletteComment)
        buttons = QDialogButtonBox(QDialogButtonBox.Ok)
        dialog.layout().addWidget(buttons)
        buttons.accepted.connect(dialog.accept)
        # buttons.rejected.connect(dialog.reject())

        if dialog.exec_() == QDialog.Accepted:
            Resource = Application.resources("palette")[
                self.cmb_palettes.currentText()]
            Resource.setName(paletteName.text())
            self.currentPalette = Palette(Resource)
            self.currentPalette.setColumnCount(paletteColumns.value())
            self.paletteView.setPalette(self.currentPalette)
            self.slot_fill_combobox()
            self.currentPalette.setComment(paletteComment.toPlainText())
            self.currentPalette.save()

    def slot_export_to_gimp_palette(self):
        palette_exporter_gimppalette.gimpPaletteExporter(
            self.cmb_palettes.currentText())

    def slot_export_to_inkscape_svg(self):
        palette_exporter_inkscapeSVG.inkscapeSVGExporter(
            self.cmb_palettes.currentText())

    def slot_sort_colors(self):
        colorSorter = palette_sortColors.sortColors(
            self.cmb_palettes.currentText())
        self.paletteView.setPalette(colorSorter.palette())

    def canvasChanged(self, canvas):
        self.cmb_palettes.clear()
        allPalettes = Application.resources("palette")
        for palette_name in allPalettes:
            self.cmb_palettes.addItem(palette_name)
            self.cmb_palettes.model().sort(0)

        if self.currentPalette is None and len(allPalettes.keys()) > 0:
            self.currentPalette = Palette(list(allPalettes.values())[0])