diff --git a/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt b/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt index 969c20b3ec..18d1a86257 100644 --- a/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt +++ b/plugins/extensions/pykrita/plugin/plugins/CMakeLists.txt @@ -1,101 +1,102 @@ # Copyright (C) 2012, 2013 Shaheed Haque # Copyright (C) 2013 Alex Turbov # Copyright (C) 2014-2016 Boudewijn Rempt # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. include(CMakeParseArguments) # # Simple helper function to install plugin and related files # having only a name of the plugin... # (just to reduce syntactic noise when a lot of plugins get installed) # function(install_pykrita_plugin name) set(_options) set(_one_value_args) set(_multi_value_args PATTERNS FILE) cmake_parse_arguments(install_pykrita_plugin "${_options}" "${_one_value_args}" "${_multi_value_args}" ${ARGN}) if(NOT name) message(FATAL_ERROR "Plugin filename is not given") endif() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.py) install(FILES kritapykrita_${name}.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita) foreach(_f ${name}.py ${name}.ui ${install_pykrita_plugin_FILE}) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_f}) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${_f} DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita) endif() endforeach() elseif(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${name}) install(FILES ${name}/kritapykrita_${name}.desktop DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita) install( DIRECTORY ${name} DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita FILES_MATCHING PATTERN "*.py" PATTERN "*.ui" PATTERN "__pycache__*" EXCLUDE ) # TODO Is there any way to form a long PATTERN options string # and use it in a single install() call? # NOTE Install specified patterns one-by-one... foreach(_pattern ${install_pykrita_plugin_PATTERNS}) install( DIRECTORY ${name} DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita FILES_MATCHING PATTERN "${_pattern}" PATTERN "__pycache__*" EXCLUDE ) endforeach() else() message(FATAL_ERROR "Do not know what to do with ${name}") endif() endfunction() install_pykrita_plugin(hello) install_pykrita_plugin(assignprofiledialog) install_pykrita_plugin(scripter) install_pykrita_plugin(colorspace) install_pykrita_plugin(canvassize) install_pykrita_plugin(filtermanager) +install_pykrita_plugin(exportlayers) #install_pykrita_plugin(highpass) install_pykrita_plugin(tenbrushes) install( FILES tenbrushes/tenbrushes.action DESTINATION ${DATA_INSTALL_DIR}/krita/actions) install_pykrita_plugin(palette_docker) # if(PYTHON_VERSION_MAJOR VERSION_EQUAL 3) # install_pykrita_plugin(cmake_utils) # install_pykrita_plugin(js_utils PATTERNS "*.json") # install_pykrita_plugin(expand PATTERNS "*.expand" "templates/*.tpl") # endif() install( DIRECTORY libkritapykrita DESTINATION ${DATA_INSTALL_DIR}/krita/pykrita FILES_MATCHING PATTERN "*.py" PATTERN "__pycache__*" EXCLUDE ) diff --git a/plugins/extensions/pykrita/plugin/plugins/exportlayers/__init__.py b/plugins/extensions/pykrita/plugin/plugins/exportlayers/__init__.py new file mode 100644 index 0000000000..b0a4cf13f3 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/exportlayers/__init__.py @@ -0,0 +1,2 @@ +# let's make a module +from .exportlayers import * diff --git a/plugins/extensions/pykrita/plugin/plugins/exportlayers/exportlayers.py b/plugins/extensions/pykrita/plugin/plugins/exportlayers/exportlayers.py new file mode 100644 index 0000000000..1fdc00e7fd --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/exportlayers/exportlayers.py @@ -0,0 +1,20 @@ +import krita +from exportlayers import uiexportlayers + + +class ExportLayersExtension(krita.Extension): + + def __init__(self, parent): + super(ExportLayersExtension, self).__init__(parent) + + def setup(self): + action = krita.Krita.instance().createAction("export_layers", "Export Layers") + action.setToolTip("Plugin to export layers from a document") + action.triggered.connect(self.initialize) + + def initialize(self): + self.uiexportlayers = uiexportlayers.UIExportLayers() + self.uiexportlayers.initialize() + + +Scripter.addExtension(ExportLayersExtension(krita.Krita.instance())) diff --git a/plugins/extensions/pykrita/plugin/plugins/exportlayers/exportlayersdialog.py b/plugins/extensions/pykrita/plugin/plugins/exportlayers/exportlayersdialog.py new file mode 100644 index 0000000000..780c9af762 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/exportlayers/exportlayersdialog.py @@ -0,0 +1,10 @@ +from PyQt5.QtWidgets import QDialog + + +class ExportLayersDialog(QDialog): + + def __init__(self, parent=None): + super(ExportLayersDialog, self).__init__(parent) + + def closeEvent(self, event): + event.accept() diff --git a/plugins/extensions/pykrita/plugin/plugins/exportlayers/kritapykrita_exportlayers.desktop b/plugins/extensions/pykrita/plugin/plugins/exportlayers/kritapykrita_exportlayers.desktop new file mode 100644 index 0000000000..027c439ec9 --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/exportlayers/kritapykrita_exportlayers.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Type=Service +ServiceTypes=Krita/PythonPlugin +X-KDE-Library=exportlayers +X-Python-2-Compatible=false +Name=Export Layers +Name[en_GB]=Export Layers +Name[pt]=Exportar camadas +Comment=Plugin to export layers from a document +Comment[en_GB]=Plugin to export layers from a document +Comment[pt]='Plugin' para exportar camadas de um documento diff --git a/plugins/extensions/pykrita/plugin/plugins/exportlayers/uiexportlayers.py b/plugins/extensions/pykrita/plugin/plugins/exportlayers/uiexportlayers.py new file mode 100644 index 0000000000..b479aa15ca --- /dev/null +++ b/plugins/extensions/pykrita/plugin/plugins/exportlayers/uiexportlayers.py @@ -0,0 +1,93 @@ +from exportlayers import exportlayersdialog +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import (QFormLayout, QListWidget, QAbstractItemView, + QDialogButtonBox, QVBoxLayout, QFrame, + QPushButton, QAbstractScrollArea, QSpinBox, + QHBoxLayout, QMessageBox, QFileDialog, QLineEdit) +from os.path import expanduser +import krita + + +class UIExportLayers(object): + + def __init__(self): + self.mainDialog = exportlayersdialog.ExportLayersDialog() + self.mainLayout = QVBoxLayout(self.mainDialog) + self.formLayout = QFormLayout() + self.documentLayout = QVBoxLayout() + self.directorySelectorLayout = QHBoxLayout() + + self.refreshButton = QPushButton("Refresh") + self.widgetDocuments = QListWidget() + self.directoryTextField = QLineEdit() + self.direcoryDialogButton = QPushButton("...") + self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) + + self.kritaInstance = krita.Krita.instance() + self.documentsList = [] + + self.directoryTextField.setReadOnly(True) + self.direcoryDialogButton.clicked.connect(self._selectDir) + self.refreshButton.clicked.connect(self.refreshButtonClicked) + self.buttonBox.accepted.connect(self.confirmButton) + self.buttonBox.rejected.connect(self.mainDialog.close) + + self.mainDialog.setWindowModality(Qt.NonModal) + self.widgetDocuments.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents) + + def initialize(self): + self.loadDocuments() + + self.documentLayout.addWidget(self.widgetDocuments) + self.documentLayout.addWidget(self.refreshButton) + + self.directorySelectorLayout.addWidget(self.directoryTextField) + self.directorySelectorLayout.addWidget(self.direcoryDialogButton) + + self.formLayout.addRow('Documents', self.documentLayout) + self.formLayout.addRow('Initial directory', self.directorySelectorLayout) + + 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("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("Select one document.") + elif not self.directoryTextField.text(): + self.msgBox.setText("Select the initial directory.") + else: + self.msgBox.setText("All layers has been exported.") + self.msgBox.exec_() + + def _exportLayers(rootNode, fileFormat, parentDir): + pass + + def _selectDir(self): + directory = QFileDialog.getExistingDirectory(self.mainDialog, "Open a folder", expanduser("~"), QFileDialog.ShowDirsOnly) + self.directoryTextField.setText(directory)