| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- # This script is licensed CC 0 1.0, so that you can learn from it.
- # ------ CC 0 1.0 ---------------
- # The person who associated a work with this deed has dedicated the
- # work to the public domain by waiving all of his or her rights to the
- # work worldwide under copyright law, including all related and
- # neighboring rights, to the extent allowed by law.
- # You can copy, modify, distribute and perform the work, even for
- # commercial purposes, all without asking permission.
- # https://creativecommons.org/publicdomain/zero/1.0/legalcode
- from . import exportlayersdialog
- from PyQt5.QtCore import (Qt, QRect)
- from PyQt5.QtWidgets import (QFormLayout, QListWidget, QHBoxLayout,
- QDialogButtonBox, QVBoxLayout, QFrame,
- QPushButton, QAbstractScrollArea, QLineEdit,
- QMessageBox, QFileDialog, QCheckBox, QSpinBox,
- QComboBox)
- import os
- import krita
- class UIExportLayers(object):
- def __init__(self):
- self.mainDialog = exportlayersdialog.ExportLayersDialog()
- self.mainLayout = QVBoxLayout(self.mainDialog)
- self.formLayout = QFormLayout()
- self.resSpinBoxLayout = QFormLayout()
- self.documentLayout = QVBoxLayout()
- self.directorySelectorLayout = QHBoxLayout()
- self.optionsLayout = QVBoxLayout()
- self.rectSizeLayout = QHBoxLayout()
- self.refreshButton = QPushButton(i18n("Refresh"))
- self.widgetDocuments = QListWidget()
- self.directoryTextField = QLineEdit()
- self.directoryDialogButton = QPushButton(i18n("..."))
- self.exportFilterLayersCheckBox = QCheckBox(
- i18n("Export filter layers"))
- self.batchmodeCheckBox = QCheckBox(i18n("Export in batchmode"))
- self.groupAsLayer = QCheckBox(i18n("Group as layer"))
- self.ignoreInvisibleLayersCheckBox = QCheckBox(
- i18n("Ignore invisible layers"))
- self.cropToImageBounds = QCheckBox(
- i18n("Adjust export size to layer content"))
- self.rectWidthSpinBox = QSpinBox()
- self.rectHeightSpinBox = QSpinBox()
- self.formatsComboBox = QComboBox()
- self.resSpinBox = QSpinBox()
- self.buttonBox = QDialogButtonBox(
- QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
- self.kritaInstance = krita.Krita.instance()
- self.documentsList = []
- self.directoryTextField.setReadOnly(True)
- self.batchmodeCheckBox.setChecked(True)
- self.directoryDialogButton.clicked.connect(self._selectDir)
- self.widgetDocuments.currentRowChanged.connect(self._setResolution)
- self.refreshButton.clicked.connect(self.refreshButtonClicked)
- self.buttonBox.accepted.connect(self.confirmButton)
- self.buttonBox.rejected.connect(self.mainDialog.close)
- self.cropToImageBounds.stateChanged.connect(self._toggleCropSize)
- self.mainDialog.setWindowModality(Qt.NonModal)
- self.widgetDocuments.setSizeAdjustPolicy(
- QAbstractScrollArea.AdjustToContents)
- def initialize(self):
- self.loadDocuments()
- self.rectWidthSpinBox.setRange(1, 10000)
- self.rectHeightSpinBox.setRange(1, 10000)
- self.resSpinBox.setRange(20, 1200)
- self.formatsComboBox.addItem(i18n("PNG"))
- self.formatsComboBox.addItem(i18n("JPEG"))
- self.documentLayout.addWidget(self.widgetDocuments)
- self.documentLayout.addWidget(self.refreshButton)
- self.directorySelectorLayout.addWidget(self.directoryTextField)
- self.directorySelectorLayout.addWidget(self.directoryDialogButton)
- self.optionsLayout.addWidget(self.exportFilterLayersCheckBox)
- self.optionsLayout.addWidget(self.batchmodeCheckBox)
- self.optionsLayout.addWidget(self.groupAsLayer)
- self.optionsLayout.addWidget(self.ignoreInvisibleLayersCheckBox)
- self.optionsLayout.addWidget(self.cropToImageBounds)
- self.resSpinBoxLayout.addRow(i18n("dpi:"), self.resSpinBox)
- self.rectSizeLayout.addWidget(self.rectWidthSpinBox)
- self.rectSizeLayout.addWidget(self.rectHeightSpinBox)
- self.rectSizeLayout.addLayout(self.resSpinBoxLayout)
- self.formLayout.addRow(i18n("Documents:"), self.documentLayout)
- self.formLayout.addRow(
- i18n("Initial directory:"), self.directorySelectorLayout)
- self.formLayout.addRow(i18n("Export options:"), self.optionsLayout)
- self.formLayout.addRow(i18n("Export size:"), self.rectSizeLayout)
- self.formLayout.addRow(
- i18n("Images extensions:"), self.formatsComboBox)
- self.line = QFrame()
- self.line.setFrameShape(QFrame.HLine)
- self.line.setFrameShadow(QFrame.Sunken)
- self.mainLayout.addLayout(self.formLayout)
- self.mainLayout.addWidget(self.line)
- self.mainLayout.addWidget(self.buttonBox)
- self.mainDialog.resize(500, 300)
- self.mainDialog.setWindowTitle(i18n("Export Layers"))
- self.mainDialog.setSizeGripEnabled(True)
- self.mainDialog.show()
- self.mainDialog.activateWindow()
- def loadDocuments(self):
- self.widgetDocuments.clear()
- self.documentsList = [
- document for document in self.kritaInstance.documents()
- if document.fileName()
- ]
- for document in self.documentsList:
- self.widgetDocuments.addItem(document.fileName())
- def refreshButtonClicked(self):
- self.loadDocuments()
- def confirmButton(self):
- selectedPaths = [
- item.text() for item in self.widgetDocuments.selectedItems()]
- selectedDocuments = [
- document for document in self.documentsList
- for path in selectedPaths if path == document.fileName()
- ]
- self.msgBox = QMessageBox(self.mainDialog)
- if not selectedDocuments:
- self.msgBox.setText(i18n("Select one document."))
- elif not self.directoryTextField.text():
- self.msgBox.setText(i18n("Select the initial directory."))
- else:
- self.export(selectedDocuments[0])
- self.msgBox.setText(i18n("All layers has been exported."))
- self.msgBox.exec_()
- def mkdir(self, directory):
- target_directory = self.directoryTextField.text() + directory
- if (os.path.exists(target_directory)
- and os.path.isdir(target_directory)):
- return
- try:
- os.makedirs(target_directory)
- except OSError as e:
- raise e
- def export(self, document):
- Application.setBatchmode(self.batchmodeCheckBox.isChecked())
- documentName = document.fileName() if document.fileName() else 'Untitled' # noqa: E501
- fileName, extension = os.path.splitext(os.path.basename(documentName))
- self.mkdir('/' + fileName)
- self._exportLayers(
- document.rootNode(),
- self.formatsComboBox.currentText(),
- '/' + fileName)
- Application.setBatchmode(True)
- def _exportLayers(self, parentNode, fileFormat, parentDir):
- """ This method get all sub-nodes from the current node and export then in
- the defined format."""
- for node in parentNode.childNodes():
- newDir = ''
- if node.type() == 'grouplayer' and not self.groupAsLayer.isChecked():
- newDir = os.path.join(parentDir, node.name())
- self.mkdir(newDir)
- elif (not self.exportFilterLayersCheckBox.isChecked()
- and 'filter' in node.type()):
- continue
- elif (self.ignoreInvisibleLayersCheckBox.isChecked()
- and not node.visible()):
- continue
- else:
- nodeName = node.name()
- _fileFormat = self.formatsComboBox.currentText()
- exportConfig = krita.InfoObject()
- if '[jpeg]' in nodeName:
- _fileFormat = 'jpeg'
- elif '[png]' in nodeName:
- _fileFormat = 'png'
- if _fileFormat.lower() == 'png':
- # Values from https://api.kde.org/appscomplete-api/krita-apidocs/libs/libkis/html/classDocument.html#abda324b9beee9384879af8b7e7807cfa
- # https://api.kde.org/appscomplete-api/krita-apidocs/libs/libkis/html/classInfoObject.html#a45fd7051d88d4d02221cb81d54189bc3
- exportConfig.setProperty('alpha', False)
- exportConfig.setProperty('compression', 9)
- # exportConfig.setProperty('transparencyFillcolor', [255, 255, 255])
- if self.cropToImageBounds.isChecked():
- bounds = QRect()
- else:
- bounds = QRect(0, 0, self.rectWidthSpinBox.value(), self.rectHeightSpinBox.value())
- layerFileName = '{0}{1}/{2}.{3}'.format(
- self.directoryTextField.text(),
- parentDir, node.name(), _fileFormat)
- node.save(layerFileName, self.resSpinBox.value() / 72.,
- self.resSpinBox.value() / 72., exportConfig, bounds)
- if node.childNodes() and not self.groupAsLayer.isChecked():
- self._exportLayers(node, fileFormat, newDir)
- def _selectDir(self):
- directory = QFileDialog.getExistingDirectory(
- self.mainDialog,
- i18n("Select a Folder"),
- os.path.expanduser("~"),
- QFileDialog.ShowDirsOnly)
- self.directoryTextField.setText(directory)
- def _setResolution(self, index):
- document = self.documentsList[index]
- self.rectWidthSpinBox.setValue(document.width())
- self.rectHeightSpinBox.setValue(document.height())
- self.resSpinBox.setValue(document.resolution())
- def _toggleCropSize(self):
- cropToLayer = self.cropToImageBounds.isChecked()
- self.rectWidthSpinBox.setDisabled(cropToLayer)
- self.rectHeightSpinBox.setDisabled(cropToLayer)
|