diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -5,7 +5,7 @@ # Parameters: EXTERNALS_DOWNLOAD_DIR place to download all packages # INSTALL_ROOT place to install everything to # MXE_TOOLCHAIN: the toolchain file to cross-compile using MXE -# +# # Example usage: cmake ..\kritadeposx -DEXTERNALS_DOWNLOAD_DIR=/dev2/d -DINSTALL_ROOT=/dev2/i -DWIN64_BUILD=TRUE -DBOOST_LIBRARYDIR=/dev2/i/lib -G "Visual Studio 11 Win64" @@ -37,11 +37,11 @@ set(CMAKE_PREFIX_PATH "${EXTPREFIX}") if (${CMAKE_GENERATOR} STREQUAL "Visual Studio 14 2015 Win64") - SET(GLOBAL_PROFILE - -DCMAKE_MODULE_LINKER_FLAGS=/machine:x64 - -DCMAKE_EXE_LINKER_FLAGS=/machine:x64 - -DCMAKE_SHARED_LINKER_FLAGS=/machine:x64 - -DCMAKE_STATIC_LINKER_FLAGS=/machine:x64 + SET(GLOBAL_PROFILE + -DCMAKE_MODULE_LINKER_FLAGS=/machine:x64 + -DCMAKE_EXE_LINKER_FLAGS=/machine:x64 + -DCMAKE_SHARED_LINKER_FLAGS=/machine:x64 + -DCMAKE_STATIC_LINKER_FLAGS=/machine:x64 ) endif () @@ -105,16 +105,16 @@ if (MSYS) set(PATCH_COMMAND patch) - set(GLOBAL_PROFILE ${GLOBAL_PROFILE} + set(GLOBAL_PROFILE ${GLOBAL_PROFILE} -DCMAKE_TOOLCHAIN_FILE=${MXE_TOOLCHAIN} -DCMAKE_FIND_PREFIX_PATH=${CMAKE_PREFIX_PATH} -DCMAKE_SYSTEM_INCLUDE_PATH=${CMAKE_PREFIX_PATH}/include - -DCMAKE_INCLUDE_PATH=${CMAKE_PREFIX_PATH}/include + -DCMAKE_INCLUDE_PATH=${CMAKE_PREFIX_PATH}/include -DCMAKE_LIBRARY_PATH=${CMAKE_PREFIX_PATH}/lib -DZLIB_ROOT=${CMAKE_PREFIX_PATH} ) set(GLOBAL_AUTOMAKE_PROFILE --host=i686-pc-mingw32 ) -endif() +endif() if (APPLE) set(GLOBAL_PROFILE ${GLOBAL_PROFILE} -DCMAKE_MACOSX_RPATH=ON -DKDE_SKIP_RPATH_SETTINGS=ON -DBUILD_WITH_INSTALL_RPATH=ON -DAPPLE_SUPPRESS_X11_WARNING=ON) @@ -144,8 +144,12 @@ if (MINGW) option(ENABLE_PYTHON_DEPS "Enable Python deps (sip, pyqt)" ON) if (ENABLE_PYTHON_DEPS) - find_package(PythonInterp 3.6 EXACT) - find_package(PythonLibs 3.6 EXACT) + if (ENABLE_PYTHON_2) + message(FATAL_ERROR "Python 2.7 is not supported on Windows at the moment.") + else(ENABLE_PYTHON_2) + find_package(PythonInterp 3.6 EXACT) + find_package(PythonLibs 3.6 EXACT) + endif(ENABLE_PYTHON_2) if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) message(STATUS "Python requirements met.") TestCompileLinkPythonLibs(CAN_USE_PYTHON_LIBS) diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -194,6 +194,7 @@ option(KRITA_ENABLE_BROKEN_TESTS "Enable tests that are marked as broken" OFF) add_feature_info("Enable Broken Tests" KRITA_ENABLE_BROKEN_TESTS "Runs broken test when \"make test\" is invoked (use -DKRITA_ENABLE_BROKEN_TESTS=ON to enable).") +option(ENABLE_PYTHON_2 "Enables the compiler to look for Python 2.7 instead of Python 3. Some packaged scripts are not compatible with Python 2 and this should only be used if you really have to use 2.7." OFF) include(MacroJPEG) @@ -218,18 +219,31 @@ endfunction() if(MINGW) - find_package(PythonInterp 3.6 EXACT) - find_package(PythonLibs 3.6 EXACT) + if(ENABLE_PYTHON_2) + message(FATAL_ERROR "Python 2.7 is not supported on Windows at the moment.") + else(ENABLE_PYTHON_2) + find_package(PythonInterp 3.6 EXACT) + find_package(PythonLibs 3.6 EXACT) + endif(ENABLE_PYTHON_2) if (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) - find_package(PythonLibrary 3.6) + if(ENABLE_PYTHON_2) + find_package(PythonLibrary 2.7) + else(ENABLE_PYTHON_2) + find_package(PythonLibrary 3.6) + endif(ENABLE_PYTHON_2) TestCompileLinkPythonLibs(CAN_USE_PYTHON_LIBS) if (NOT CAN_USE_PYTHON_LIBS) message(FATAL_ERROR "Compiling with Python library failed, please check whether the architecture is correct. Python will be disabled.") endif (NOT CAN_USE_PYTHON_LIBS) endif (PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) else(MINGW) - find_package(PythonInterp 3.0) - find_package(PythonLibrary 3.0) + if(ENABLE_PYTHON_2) + find_package(PythonInterp 2.7) + find_package(PythonLibrary 2.7) + else(ENABLE_PYTHON_2) + find_package(PythonInterp 3.0) + find_package(PythonLibrary 3.0) + endif(ENABLE_PYTHON_2) endif(MINGW) ######################## @@ -459,7 +473,7 @@ endif() add_definitions(-DBOOST_ALL_NO_LIB) -find_package(Boost 1.55 REQUIRED COMPONENTS system) +find_package(Boost 1.55 REQUIRED COMPONENTS system) include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) ## ## Test for GNU Scientific Library @@ -621,7 +635,7 @@ set(OLD_CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ) set(HAVE_VC FALSE) -if (NOT ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") +if (NOT ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") if(NOT MSVC) find_package(Vc 1.1.0) set_package_properties(Vc PROPERTIES diff --git a/cmake/modules/FindPythonLibrary.cmake b/cmake/modules/FindPythonLibrary.cmake --- a/cmake/modules/FindPythonLibrary.cmake +++ b/cmake/modules/FindPythonLibrary.cmake @@ -25,7 +25,11 @@ include(FindPackageHandleStandardArgs) -find_package(PythonInterp) +if (ENABLE_PYTHON_2) + find_package(PythonInterp 2.7 REQUIRED) +else(ENABLE_PYTHON_2) + find_package(PythonInterp 3.0 REQUIRED) +endif(ENABLE_PYTHON_2) if (PYTHONINTERP_FOUND) diff --git a/plugins/extensions/pykrita/plugin/CMakeLists.txt b/plugins/extensions/pykrita/plugin/CMakeLists.txt --- a/plugins/extensions/pykrita/plugin/CMakeLists.txt +++ b/plugins/extensions/pykrita/plugin/CMakeLists.txt @@ -3,17 +3,17 @@ add_definitions(-DQT_NO_KEYWORDS) configure_file(config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) -set(SOURCES - plugin.cpp +set(SOURCES + plugin.cpp pyqtpluginsettings.cpp utilities.cpp PykritaModule.cpp PythonPluginManager.cpp PythonPluginsModel.cpp ) -ki18n_wrap_ui(SOURCES - info.ui +ki18n_wrap_ui(SOURCES + info.ui manager.ui ) diff --git a/plugins/extensions/pykrita/plugin/PykritaModule.h b/plugins/extensions/pykrita/plugin/PykritaModule.h --- a/plugins/extensions/pykrita/plugin/PykritaModule.h +++ b/plugins/extensions/pykrita/plugin/PykritaModule.h @@ -25,9 +25,19 @@ #include +#if PY_MAJOR_VERSION >= 3 +#ifndef IS_PY3K +#define IS_PY3K +#endif +#endif + /** * Initializer for the built-in Python module. */ +#if defined(IS_PY3K) PyMODINIT_FUNC PyInit_pykrita(); +#else +void initpykrita(); +#endif #endif diff --git a/plugins/extensions/pykrita/plugin/PykritaModule.cpp b/plugins/extensions/pykrita/plugin/PykritaModule.cpp --- a/plugins/extensions/pykrita/plugin/PykritaModule.cpp +++ b/plugins/extensions/pykrita/plugin/PykritaModule.cpp @@ -27,6 +27,17 @@ #define PYKRITA_INIT PyInit_pykrita +struct module_state { + PyObject *error; +}; + +#if defined(IS_PY3K) +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) +#else +#define GETSTATE(m) (&_state) +static struct module_state _state; +#endif + /// \note Namespace name written in uppercase intentionally! /// It will appear in debug output from Python plugins... namespace PYKRITA @@ -56,23 +67,48 @@ } // anonymous namespace //BEGIN Python module registration +#if defined(IS_PY3K) +// Python 3 initializes modules differently from Python 2 +// +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT + , "pykrita" + , "The pykrita module" + , -1 + , pykritaMethods + , 0 + , 0 + , 0 + , 0 +}; + +#define INITERROR return NULL + PyMODINIT_FUNC PyInit_pykrita() + +#else +#define INITERROR return + +void +initpykrita(void) +#endif { - static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT - , "pykrita" - , "The pykrita module" - , -1 - , pykritaMethods - , 0 - , 0 - , 0 - , 0 - }; +#if defined(IS_PY3K) PyObject *pykritaModule = PyModule_Create(&moduledef); +#else + PyObject *pykritaModule = Py_InitModule("pykrita", pykritaMethods); +#endif + + if (pykritaModule == NULL) + INITERROR; + PyModule_AddStringConstant(pykritaModule, "__file__", __FILE__); + +#if defined(IS_PY3K) return pykritaModule; +#endif } + //END Python module registration // krita: space-indent on; indent-width 4; diff --git a/plugins/extensions/pykrita/plugin/PythonPluginManager.cpp b/plugins/extensions/pykrita/plugin/PythonPluginManager.cpp --- a/plugins/extensions/pykrita/plugin/PythonPluginManager.cpp +++ b/plugins/extensions/pykrita/plugin/PythonPluginManager.cpp @@ -59,6 +59,13 @@ dbgScript << "Ignore desktop file w/o a module to import"; return false; } +#if PY_MAJOR_VERSION == 2 + // Check if the plug-in is compatible with Python 2 or not. + if (m_properties["X-Python-2-Compatible"].toBool() != true) { + dbgScript << "Ignoring plug-in. It is marked incompatible with Python 2."; + return false; + } +#endif return true; } diff --git a/plugins/extensions/pykrita/plugin/krita/__init__.py b/plugins/extensions/pykrita/plugin/krita/__init__.py --- a/plugins/extensions/pykrita/plugin/krita/__init__.py +++ b/plugins/extensions/pykrita/plugin/krita/__init__.py @@ -1,15 +1,17 @@ +from __future__ import print_function + import pykrita import os import sys -import signal -signal.signal(signal.SIGINT, signal.SIG_DFL) - from .api import * from .decorators import * from .dockwidgetfactory import * from PyKrita import krita +import signal +signal.signal(signal.SIGINT, signal.SIG_DFL) + krita_path = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, krita_path) print("%s added to PYTHONPATH" % krita_path, file=sys.stderr) @@ -26,7 +28,10 @@ import excepthook excepthook.install() -import builtins +if sys.version_info[0] > 2: + import builtins +else: + import __builtin__ as builtins builtins.i18n = lambda s: QCoreApplication.translate("PyKrita", s) builtins.Scripter = Krita.instance() builtins.Application = Krita.instance() diff --git a/plugins/extensions/pykrita/plugin/krita/dockwidgetfactory.py b/plugins/extensions/pykrita/plugin/krita/dockwidgetfactory.py --- a/plugins/extensions/pykrita/plugin/krita/dockwidgetfactory.py +++ b/plugins/extensions/pykrita/plugin/krita/dockwidgetfactory.py @@ -7,7 +7,7 @@ class DockWidgetFactory(DockWidgetFactoryBase): def __init__(self, _id, _dockPosition, _klass): - super().__init__(_id, _dockPosition) + super(DockWidgetFactory, self).__init__(_id, _dockPosition) self.klass = _klass def createDockWidget(self): diff --git a/plugins/extensions/pykrita/plugin/utilities.cpp b/plugins/extensions/pykrita/plugin/utilities.cpp --- a/plugins/extensions/pykrita/plugin/utilities.cpp +++ b/plugins/extensions/pykrita/plugin/utilities.cpp @@ -76,7 +76,11 @@ return initStatus; } +#if defined(IS_PY3K) if (0 != PyImport_AppendInittab(Python::PYKRITA_ENGINE, PyInit_pykrita)) { +#else + if (0 != PyImport_AppendInittab(Python::PYKRITA_ENGINE, initpykrita)) { +#endif initStatus = INIT_CANNOT_LOAD_PYKRITA_MODULE; return initStatus; } @@ -101,14 +105,18 @@ pluginManagerInstance.reset(new PythonPluginManager()); +#if defined(IS_PY3K) // Initialize our built-in module. auto pykritaModule = PyInit_pykrita(); if (!pykritaModule) { initStatus = INIT_CANNOT_LOAD_PYKRITA_MODULE; return initStatus; //return i18nc("@info:tooltip ", "No pykrita built-in module"); } +#else + initpykrita(); +#endif initStatus = INIT_OK; return initStatus; @@ -412,7 +420,9 @@ if (KoResourcePaths::getApplicationRoot().contains(".mount_Krita")) { QVector joinedPathsWChars(joinedPaths.size() + 1, 0); joinedPaths.toWCharArray(joinedPathsWChars.data()); - Py_SetPath(joinedPathsWChars.data()); + PyRun_SimpleString("import sys; import os"); + QString pathCommand = QString("sys.path += '") + joinedPaths + QString("'.split(os.pathsep)"); + PyRun_SimpleString(pathCommand.toUtf8().constData()); } else { qputenv("PYTHONPATH", joinedPaths.toLocal8Bit()); diff --git a/plugins/extensions/pykrita/sip/CMakeLists.txt b/plugins/extensions/pykrita/sip/CMakeLists.txt --- a/plugins/extensions/pykrita/sip/CMakeLists.txt +++ b/plugins/extensions/pykrita/sip/CMakeLists.txt @@ -6,7 +6,7 @@ message( ${SIP_INCLUDE_DIR} " - Directory holding the SIP C++ header file.") message( ${SIP_DEFAULT_SIP_DIR} " - default SIP dir" ) -set(SIP_INCLUDES +set(SIP_INCLUDES ${SIP_DEFAULT_SIP_DIR} ${PYQT5_SIP_DIR} ${PYQT_SIP_DIR_OVERRIDE} @@ -21,7 +21,10 @@ set(SIP_EXTRA_FILES_DEPEND ${PYKRITA_KRITA_sip_files}) add_sip_python_module(PyKrita.krita ./krita/kritamod.sip kritalibkis kritaui kritaimage kritalibbrush) -#install(FILES -# ./__init__.py -# DESTINATION ${PYTHON_SITE_PACKAGES_INSTALL_DIR}) - +if (ENABLE_PYTHON_2) + # Add an init file to turn it into a valid py2 module. + # Otherwise PyKrita cannot be loaded. + install(FILES + ./__init__.py + DESTINATION ${PYTHON_SITE_PACKAGES_INSTALL_DIR}/PyKrita) +endif (ENABLE_PYTHON_2) diff --git a/plugins/extensions/pykrita/sip/__init__.py b/plugins/extensions/pykrita/sip/__init__.py new file mode 100644 diff --git a/plugins/python/assignprofiledialog/assignprofiledialog.py b/plugins/python/assignprofiledialog/assignprofiledialog.py --- a/plugins/python/assignprofiledialog/assignprofiledialog.py +++ b/plugins/python/assignprofiledialog/assignprofiledialog.py @@ -9,20 +9,20 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' -import sys -from PyQt5.QtGui import * -from PyQt5.QtWidgets import * -from krita import * +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import (QDialogButtonBox, QDialog, + QMessageBox, QComboBox, QVBoxLayout) +from krita import Extension class AssignProfileDialog(Extension): def __init__(self, parent): - super().__init__(parent) + super(AssignProfileDialog, self).__init__(parent) def assignProfile(self): doc = Application.activeDocument() - if doc == None: + if doc is None: QMessageBox.information(Application.activeWindow().qwindow(), "Assign Profile", "There is no active document.") return @@ -35,7 +35,7 @@ vbox = QVBoxLayout(self.dialog) vbox.addWidget(self.cmbProfile) self.buttonBox = QDialogButtonBox(self.dialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.accepted.connect(self.dialog.accept) self.buttonBox.accepted.connect(self.accept) @@ -51,9 +51,10 @@ def setup(self): pass - + def createActions(self, window): action = window.createAction("assing_profile_to_image", "Assign Profile to Image") action.triggered.connect(self.assignProfile) + Scripter.addExtension(AssignProfileDialog(Application)) diff --git a/plugins/python/assignprofiledialog/kritapykrita_assignprofiledialog.desktop b/plugins/python/assignprofiledialog/kritapykrita_assignprofiledialog.desktop --- a/plugins/python/assignprofiledialog/kritapykrita_assignprofiledialog.desktop +++ b/plugins/python/assignprofiledialog/kritapykrita_assignprofiledialog.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=assignprofiledialog -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Assign Profile to Image Name[ar]=إسناد اللاحات إلى الصّور diff --git a/plugins/python/colorspace/colorspace.py b/plugins/python/colorspace/colorspace.py --- a/plugins/python/colorspace/colorspace.py +++ b/plugins/python/colorspace/colorspace.py @@ -10,7 +10,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' import krita -from colorspace import uicolorspace +from . import uicolorspace class ColorSpaceExtension(krita.Extension): @@ -20,7 +20,7 @@ def setup(self): pass - + def createActions(self, window): action = window.createAction("color_space", "Color Space") action.setToolTip("Plugin to change color space to selected documents") diff --git a/plugins/python/colorspace/kritapykrita_colorspace.desktop b/plugins/python/colorspace/kritapykrita_colorspace.desktop --- a/plugins/python/colorspace/kritapykrita_colorspace.desktop +++ b/plugins/python/colorspace/kritapykrita_colorspace.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=colorspace -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Color Space Name[ar]=الفضاء اللونيّ diff --git a/plugins/python/colorspace/uicolorspace.py b/plugins/python/colorspace/uicolorspace.py --- a/plugins/python/colorspace/uicolorspace.py +++ b/plugins/python/colorspace/uicolorspace.py @@ -9,16 +9,16 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' -from colorspace import colorspacedialog -from colorspace.components import colormodelcombobox, colordepthcombobox, colorprofilecombobox +from . import colorspacedialog +from .components import colormodelcombobox, colordepthcombobox, colorprofilecombobox from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QFormLayout, QListWidget, QListWidgetItem, QAbstractItemView, QComboBox, QDialogButtonBox, QVBoxLayout, QFrame, QMessageBox, QPushButton, QHBoxLayout, QAbstractScrollArea) from PyQt5.QtGui import QIcon import krita -from colorspace import resources_rc +from . import resources_rc class UIColorSpace(object): diff --git a/plugins/python/documenttools/documenttools.py b/plugins/python/documenttools/documenttools.py --- a/plugins/python/documenttools/documenttools.py +++ b/plugins/python/documenttools/documenttools.py @@ -10,7 +10,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' import krita -from documenttools import uidocumenttools +from . import uidocumenttools class DocumentToolsExtension(krita.Extension): @@ -20,7 +20,7 @@ def setup(self): pass - + def createActions(self, window): action = window.createAction("document_tools", "Document Tools") action.setToolTip("Plugin to manipulate properties of selected documents") diff --git a/plugins/python/documenttools/kritapykrita_documenttools.desktop b/plugins/python/documenttools/kritapykrita_documenttools.desktop --- a/plugins/python/documenttools/kritapykrita_documenttools.desktop +++ b/plugins/python/documenttools/kritapykrita_documenttools.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=documenttools -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Document Tools Name[ar]=أدوات المستندات diff --git a/plugins/python/documenttools/uidocumenttools.py b/plugins/python/documenttools/uidocumenttools.py --- a/plugins/python/documenttools/uidocumenttools.py +++ b/plugins/python/documenttools/uidocumenttools.py @@ -9,7 +9,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' -from documenttools import documenttoolsdialog +from . import documenttoolsdialog from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QFormLayout, QListWidget, QAbstractItemView, QDialogButtonBox, QVBoxLayout, QFrame, QTabWidget, @@ -71,7 +71,8 @@ modules = [] for classPath in toolsModule.ToolClasses: - _module, _klass = classPath.rsplit('.', maxsplit=1) + _module = classPath[:classPath.rfind(".")] + _klass = classPath[classPath.rfind(".") + 1:] modules.append(dict(module='{0}.{1}'.format(modulePath, _module), klass=_klass)) diff --git a/plugins/python/exportlayers/exportlayers.py b/plugins/python/exportlayers/exportlayers.py --- a/plugins/python/exportlayers/exportlayers.py +++ b/plugins/python/exportlayers/exportlayers.py @@ -10,7 +10,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' import krita -from exportlayers import uiexportlayers +from . import uiexportlayers class ExportLayersExtension(krita.Extension): @@ -20,7 +20,7 @@ def setup(self): pass - + def createActions(self, window): action = window.createAction("export_layers", "Export Layers") action.setToolTip("Plugin to export layers from a document") diff --git a/plugins/python/exportlayers/kritapykrita_exportlayers.desktop b/plugins/python/exportlayers/kritapykrita_exportlayers.desktop --- a/plugins/python/exportlayers/kritapykrita_exportlayers.desktop +++ b/plugins/python/exportlayers/kritapykrita_exportlayers.desktop @@ -3,7 +3,7 @@ ServiceTypes=Krita/PythonPlugin X-KDE-Library=exportlayers X-Krita-Manual=Manual.html -X-Python-2-Compatible=false +X-Python-2-Compatible=true Name=Export Layers Name[ar]=تصدير الطّبقات Name[ca]=Exportació de capes diff --git a/plugins/python/exportlayers/uiexportlayers.py b/plugins/python/exportlayers/uiexportlayers.py --- a/plugins/python/exportlayers/uiexportlayers.py +++ b/plugins/python/exportlayers/uiexportlayers.py @@ -9,7 +9,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' -from exportlayers import exportlayersdialog +from . import exportlayersdialog from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QFormLayout, QListWidget, QHBoxLayout, QDialogButtonBox, QVBoxLayout, QFrame, @@ -127,17 +127,20 @@ 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(self.directoryTextField.text() + directory) + os.makedirs(target_directory) except OSError as e: - if e.errno != errno.EEXIST: - raise + raise e def export(self, document): Application.setBatchmode(self.batchmodeCheckBox.isChecked()) documentName = document.fileName() if document.fileName() else 'Untitled' - fileName, extension = str(documentName).rsplit('/', maxsplit=1)[-1].split('.', maxsplit=1) + fileName, extension = os.path.splitext(os.path.basename(documentName)) self.mkdir('/' + fileName) self._exportLayers(document.rootNode(), self.formatsComboBox.currentText(), '/' + fileName) @@ -150,7 +153,7 @@ for node in parentNode.childNodes(): newDir = '' if node.type() == 'grouplayer': - newDir = parentDir + '/' + node.name() + newDir = os.path.join(parentDir, node.name()) self.mkdir(newDir) elif not self.exportFilterLayersCheckBox.isChecked() and 'filter' in node.type(): continue @@ -164,8 +167,9 @@ elif '[png]' in nodeName: _fileFormat = 'png' - layerFileName = '{0}{1}/{2}.{3}'.format(self.directoryTextField.text(), parentDir, node.name(), _fileFormat) - teste = node.save(layerFileName, self.xResSpinBox.value(), self.yResSpinBox.value()) + layerFileName = '{0}{1}/{2}.{3}'.format(self.directoryTextField.text(), + parentDir, node.name(), _fileFormat) + node.save(layerFileName, self.xResSpinBox.value(), self.yResSpinBox.value()) if node.childNodes(): self._exportLayers(node, fileFormat, newDir) diff --git a/plugins/python/filtermanager/components/filtermanagertreemodel.py b/plugins/python/filtermanager/components/filtermanagertreemodel.py --- a/plugins/python/filtermanager/components/filtermanagertreemodel.py +++ b/plugins/python/filtermanager/components/filtermanagertreemodel.py @@ -11,7 +11,7 @@ ''' from PyQt5.QtCore import QAbstractItemModel, QFile, QIODevice, QModelIndex, Qt from PyQt5.QtWidgets import QApplication, QTreeView -from filtermanager.components import filtermanagertreeitem +from . import filtermanagertreeitem from PyQt5.QtGui import QPixmap diff --git a/plugins/python/filtermanager/filtermanager.py b/plugins/python/filtermanager/filtermanager.py --- a/plugins/python/filtermanager/filtermanager.py +++ b/plugins/python/filtermanager/filtermanager.py @@ -10,7 +10,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' import krita -from filtermanager import uifiltermanager +from . import uifiltermanager class FilterManagerExtension(krita.Extension): @@ -20,7 +20,7 @@ def setup(self): pass - + def createActions(self, window): action = window.createAction("filter_manager", "Filter Manager") action.setToolTip("Plugin to filters management") diff --git a/plugins/python/filtermanager/kritapykrita_filtermanager.desktop b/plugins/python/filtermanager/kritapykrita_filtermanager.desktop --- a/plugins/python/filtermanager/kritapykrita_filtermanager.desktop +++ b/plugins/python/filtermanager/kritapykrita_filtermanager.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=filtermanager -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Filter Manager Name[ar]=مدير المرشّحات diff --git a/plugins/python/filtermanager/uifiltermanager.py b/plugins/python/filtermanager/uifiltermanager.py --- a/plugins/python/filtermanager/uifiltermanager.py +++ b/plugins/python/filtermanager/uifiltermanager.py @@ -9,8 +9,8 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' -from filtermanager import filtermanagerdialog -from filtermanager.components import (filtercombobox, filtermanagertreemodel) +from . import filtermanagerdialog +from .components import (filtercombobox, filtermanagertreemodel) from PyQt5.QtCore import Qt from PyQt5.QtWidgets import (QFormLayout, QAbstractItemView, QDialogButtonBox, QVBoxLayout, QFrame, QAbstractScrollArea, QWidget, diff --git a/plugins/python/hello/hello.py b/plugins/python/hello/hello.py --- a/plugins/python/hello/hello.py +++ b/plugins/python/hello/hello.py @@ -9,14 +9,14 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' -""" -This is a simple example of a Python script for Krita. -It demonstrates how to set up a custom extension and a custom docker! -""" +# +# This is a simple example of a Python script for Krita. +# It demonstrates how to set up a custom extension and a custom docker! +# -from PyQt5.QtCore import qDebug from PyQt5.QtWidgets import QWidget, QLabel, QMessageBox -from krita import Krita, Extension, DockWidget, DockWidgetFactory, DockWidgetFactoryBase +from krita import (Krita, Extension, DockWidget, + DockWidgetFactory, DockWidgetFactoryBase) def hello(): @@ -39,7 +39,7 @@ :param parent: Parent widget :type parent: :class:`QWidget` or None """ - super().__init__(parent) + super(HelloExtension, self).__init__(parent) def setup(self): pass @@ -65,7 +65,7 @@ """ Constructs an instance of HelloDocker and the widget it contains """ - super().__init__() + super(HelloDocker, self).__init__() # The window title is also used in the Docker menu, # so it should be set to something sensible! diff --git a/plugins/python/hello/kritapykrita_hello.desktop b/plugins/python/hello/kritapykrita_hello.desktop --- a/plugins/python/hello/kritapykrita_hello.desktop +++ b/plugins/python/hello/kritapykrita_hello.desktop @@ -3,7 +3,7 @@ ServiceTypes=Krita/PythonPlugin X-KDE-Library=hello X-Krita-Manual=Manual.html -X-Python-2-Compatible=false +X-Python-2-Compatible=true Name=Hello World Name[ar]=مرحبًا يا عالم Name[ca]=Hola món diff --git a/plugins/python/lastdocumentsdocker/lastdocumentsdocker.py b/plugins/python/lastdocumentsdocker/lastdocumentsdocker.py --- a/plugins/python/lastdocumentsdocker/lastdocumentsdocker.py +++ b/plugins/python/lastdocumentsdocker/lastdocumentsdocker.py @@ -11,7 +11,7 @@ ''' from PyQt5.QtWidgets import QWidget, QVBoxLayout, QListView, QPushButton import krita -from lastdocumentsdocker import lastdocumentslistmodel +from . import lastdocumentslistmodel class LastDocumentsDocker(krita.DockWidget): diff --git a/plugins/python/palette_docker/kritapykrita_palette_docker.desktop b/plugins/python/palette_docker/kritapykrita_palette_docker.desktop --- a/plugins/python/palette_docker/kritapykrita_palette_docker.desktop +++ b/plugins/python/palette_docker/kritapykrita_palette_docker.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=palette_docker -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Palette docker Name[ar]=رصيف اللوحات diff --git a/plugins/python/palette_docker/palette_docker.py b/plugins/python/palette_docker/palette_docker.py --- a/plugins/python/palette_docker/palette_docker.py +++ b/plugins/python/palette_docker/palette_docker.py @@ -32,7 +32,7 @@ # Init the docker def __init__(self): - super().__init__() + super(Palette_Docker, self).__init__() # make base-widget and layout widget = QWidget() layout = QVBoxLayout() @@ -142,7 +142,7 @@ pass palette = self.currentPalette self.colorComboBox.clear() - self.colorList.clear() + self.colorList = list() for i in range(palette.colorsCountTotal()): entry = palette.colorSetEntryByIndex(i) color = palette.colorForEntry(entry).colorForCanvas(self.canvas()) diff --git a/plugins/python/palette_docker/palette_sortColors.py b/plugins/python/palette_docker/palette_sortColors.py --- a/plugins/python/palette_docker/palette_sortColors.py +++ b/plugins/python/palette_docker/palette_sortColors.py @@ -18,12 +18,10 @@ # Importing the relevant dependencies: -import sys -import math from krita import * -class sortColors: +class sortColors(object): def __init__(self, name): # We want people to select a palette... diff --git a/plugins/python/quick_settings_docker/kritapykrita_quick_settings_docker.desktop b/plugins/python/quick_settings_docker/kritapykrita_quick_settings_docker.desktop --- a/plugins/python/quick_settings_docker/kritapykrita_quick_settings_docker.desktop +++ b/plugins/python/quick_settings_docker/kritapykrita_quick_settings_docker.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=quick_settings_docker -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Quick Settings Docker Name[ar]=رصيف بإعدادات سريعة diff --git a/plugins/python/quick_settings_docker/quick_settings_docker.py b/plugins/python/quick_settings_docker/quick_settings_docker.py --- a/plugins/python/quick_settings_docker/quick_settings_docker.py +++ b/plugins/python/quick_settings_docker/quick_settings_docker.py @@ -28,7 +28,7 @@ # Init the docker def __init__(self): - super().__init__() + super(QuickSettingsDocker, self).__init__() # make base-widget and layout widget = QWidget() layout = QVBoxLayout() @@ -133,7 +133,7 @@ brush.setColor(self.brushSizeTableView.palette().color(QPalette.Text)) circlePainter.setBrush(brush) circlePainter.setPen(QPen(QBrush(Qt.transparent), 0)) - circlePainter.setOpacity(self.opacityList[s] / 100) + circlePainter.setOpacity(float(self.opacityList[s]) / 100.0) circlePainter.drawEllipse(QPointF(32, 32), 32, 32) circlePainter.end() brushImage = QPixmap.fromImage(img) @@ -159,14 +159,14 @@ @pyqtSlot('QModelIndex') def setBrushOpacity(self, index): i = index.row() - brushOpacity = self.opacityList[i] / 100 + brushOpacity = float(self.opacityList[i]) / 100.0 if Application.activeWindow() and len(Application.activeWindow().views()) > 0: Application.activeWindow().views()[0].setPaintingOpacity(brushOpacity) @pyqtSlot('QModelIndex') def setBrushFlow(self, index): i = index.row() - brushOpacity = self.opacityList[i] / 100 + brushOpacity = float(self.opacityList[i]) / 100.0 if Application.activeWindow() and len(Application.activeWindow().views()) > 0: Application.activeWindow().views()[0].setPaintingFlow(brushOpacity) diff --git a/plugins/python/scripter/debugcontroller.py b/plugins/python/scripter/debugcontroller.py --- a/plugins/python/scripter/debugcontroller.py +++ b/plugins/python/scripter/debugcontroller.py @@ -15,8 +15,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -from scripter.debugger_scripter import debugger -import asyncio +from .debugger_scripter import debugger +import sys +if sys.version_info[0] > 2: + import asyncio +else: + # trollius is a port of asyncio for python2. + import trollius as asyncio class DebugController (object): diff --git a/plugins/python/scripter/debugger_scripter/debugger.py b/plugins/python/scripter/debugger_scripter/debugger.py --- a/plugins/python/scripter/debugger_scripter/debugger.py +++ b/plugins/python/scripter/debugger_scripter/debugger.py @@ -17,7 +17,11 @@ """ import bdb import multiprocessing -import asyncio +import sys +if sys.version_info[0] > 2: + import asyncio +else: + import trollius as asyncio from . import debuggerformatter @@ -97,24 +101,26 @@ while True: if self.applicationq.empty(): - yield from asyncio.sleep(0.3) + # 'yield from' is not available in Python 2. + for i in asyncio.sleep(0.3): + yield i else: while not self.applicationq.empty(): self.application_data.update(self.applicationq.get()) self.scripter.uicontroller.repaintDebugArea() return @asyncio.coroutine def start(self): - yield from self.display() + yield self.display() @asyncio.coroutine def step(self): self.debugq.put("step") - yield from self.display() + yield self.display() @asyncio.coroutine def stop(self): self.debugq.put("stop") self.applicationq.put({"quit": True}) - yield from self.display() + yield self.display() diff --git a/plugins/python/scripter/documentcontroller.py b/plugins/python/scripter/documentcontroller.py --- a/plugins/python/scripter/documentcontroller.py +++ b/plugins/python/scripter/documentcontroller.py @@ -15,7 +15,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -from scripter.document_scripter import document +from .document_scripter import document class DocumentController(object): diff --git a/plugins/python/scripter/kritapykrita_scripter.desktop b/plugins/python/scripter/kritapykrita_scripter.desktop --- a/plugins/python/scripter/kritapykrita_scripter.desktop +++ b/plugins/python/scripter/kritapykrita_scripter.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=scripter -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Scripter Name[ca]=Scripter diff --git a/plugins/python/scripter/scripter.py b/plugins/python/scripter/scripter.py --- a/plugins/python/scripter/scripter.py +++ b/plugins/python/scripter/scripter.py @@ -15,20 +15,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -from PyQt5.QtWidgets import QDialog from PyQt5.QtCore import QSettings, QStandardPaths -from krita import * -from scripter import uicontroller, documentcontroller, debugcontroller +from krita import Krita, Extension +from . import uicontroller, documentcontroller, debugcontroller class ScripterExtension(Extension): def __init__(self, parent): - super().__init__(parent) + super(ScripterExtension, self).__init__(parent) def setup(self): pass - + def createActions(self, window): action = window.createAction("python_scripter", "Scripter") action.triggered.connect(self.initialize) diff --git a/plugins/python/scripter/ui_scripter/actions/closeaction/closeaction.py b/plugins/python/scripter/ui_scripter/actions/closeaction/closeaction.py --- a/plugins/python/scripter/ui_scripter/actions/closeaction/closeaction.py +++ b/plugins/python/scripter/ui_scripter/actions/closeaction/closeaction.py @@ -43,7 +43,7 @@ msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Save) - ret = msgBox.exec() + ret = msgBox.exec_() if ret == QMessageBox.Cancel: return diff --git a/plugins/python/scripter/ui_scripter/actions/newaction/newaction.py b/plugins/python/scripter/ui_scripter/actions/newaction/newaction.py --- a/plugins/python/scripter/ui_scripter/actions/newaction/newaction.py +++ b/plugins/python/scripter/ui_scripter/actions/newaction/newaction.py @@ -44,7 +44,7 @@ msgBox.setStandardButtons(QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Save) - ret = msgBox.exec() + ret = msgBox.exec_() if ret == QMessageBox.Cancel: return diff --git a/plugins/python/scripter/ui_scripter/actions/openaction/openaction.py b/plugins/python/scripter/ui_scripter/actions/openaction/openaction.py --- a/plugins/python/scripter/ui_scripter/actions/openaction/openaction.py +++ b/plugins/python/scripter/ui_scripter/actions/openaction/openaction.py @@ -19,6 +19,8 @@ from PyQt5.QtGui import QKeySequence from PyQt5.QtCore import Qt +import os + class OpenAction(QAction): @@ -40,16 +42,15 @@ dialog = QFileDialog(self.scripter.uicontroller.mainWidget) dialog.setNameFilter('Python files (*.py)') - if dialog.exec(): + if dialog.exec_(): try: selectedFile = dialog.selectedFiles()[0] - fileExtension = selectedFile.rsplit('.', maxsplit=1)[1] + _, fileExtension = os.path.splitext(selectedFile) - if fileExtension == 'py': + if fileExtension == '.py': document = self.scripter.documentcontroller.openDocument(selectedFile) self.scripter.uicontroller.setDocumentEditor(document) self.scripter.uicontroller.setStatusBar(document.filePath) - print("open is run") except Exception: QMessageBox.information(self.scripter.uicontroller.mainWidget, 'Invalid File', diff --git a/plugins/python/scripter/ui_scripter/actions/reloadaction/reloadaction.py b/plugins/python/scripter/ui_scripter/actions/reloadaction/reloadaction.py --- a/plugins/python/scripter/ui_scripter/actions/reloadaction/reloadaction.py +++ b/plugins/python/scripter/ui_scripter/actions/reloadaction/reloadaction.py @@ -1,4 +1,21 @@ -from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox +""" +Copyright (c) 2017 Eliakin Costa + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" +from PyQt5.QtWidgets import QAction, QMessageBox from PyQt5.QtGui import QKeySequence from PyQt5.QtCore import Qt @@ -41,6 +58,5 @@ document = self.scripter.documentcontroller.openDocument(curr_doc_fpath) self.scripter.uicontroller.setDocumentEditor(document) self.scripter.uicontroller.setStatusBar(document.filePath) - print("reload is run") return document diff --git a/plugins/python/scripter/ui_scripter/actions/runaction/docwrapper.py b/plugins/python/scripter/ui_scripter/actions/runaction/docwrapper.py --- a/plugins/python/scripter/ui_scripter/actions/runaction/docwrapper.py +++ b/plugins/python/scripter/ui_scripter/actions/runaction/docwrapper.py @@ -18,7 +18,7 @@ from PyQt5.QtGui import QTextCursor -class DocWrapper: +class DocWrapper(object): def __init__(self, textdocument): self.textdocument = textdocument diff --git a/plugins/python/scripter/ui_scripter/actions/runaction/runaction.py b/plugins/python/scripter/ui_scripter/actions/runaction/runaction.py --- a/plugins/python/scripter/ui_scripter/actions/runaction/runaction.py +++ b/plugins/python/scripter/ui_scripter/actions/runaction/runaction.py @@ -19,12 +19,17 @@ from PyQt5.QtGui import QIcon, QKeySequence from PyQt5.QtCore import Qt import sys -from . import docwrapper -import importlib -from importlib.machinery import SourceFileLoader import traceback +import inspect +from . import docwrapper +if sys.version_info[0] > 2: + import importlib + from importlib.machinery import SourceFileLoader +else: + import imp +PYTHON27 = sys.version_info.major == 2 and sys.version_info.minor == 7 PYTHON33 = sys.version_info.major == 3 and sys.version_info.minor == 3 PYTHON34 = sys.version_info.major == 3 and sys.version_info.minor == 4 EXEC_NAMESPACE = "__main__" # namespace that user scripts will run in @@ -75,37 +80,26 @@ try: if document and self.editor._documentModified is False: - spec = importlib.util.spec_from_file_location(EXEC_NAMESPACE, document.filePath) - try: - users_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(users_module) - - except AttributeError as e: # no module from spec - if PYTHON34 or PYTHON33: - loader = SourceFileLoader(EXEC_NAMESPACE, document.filePath) - users_module = loader.load_module() - else: - raise e - - try: - # maybe script is to be execed, maybe main needs to be invoked - # if there is a main() then execute it, otherwise don't worry... + if PYTHON27: + users_module = self.run_py2_document(document) + else: + users_module = self.run_py3_document(document) + + # maybe script is to be execed, maybe main needs to be invoked + # if there is a main() then execute it, otherwise don't worry... + if hasattr(users_module, "main") and inspect.isfunction(users_module.main): users_module.main() - except AttributeError: - pass - else: code = compile(script, '', 'exec') globals_dict = {"__name__": EXEC_NAMESPACE} exec(code, globals_dict) - except Exception as e: - """Provide context (line number and text) for an error that is caught. - Ordinarily, syntax and Indent errors are caught during initial - compilation in exec(), and the traceback traces back to this file. - So these need to be treated separately. - Other errors trace back to the file/script being run. - """ + except Exception: + # Provide context (line number and text) for an error that is caught. + # Ordinarily, syntax and Indent errors are caught during initial + # compilation in exec(), and the traceback traces back to this file. + # So these need to be treated separately. + # Other errors trace back to the file/script being run. type_, value_, traceback_ = sys.exc_info() if type_ == SyntaxError: errorMessage = "%s\n%s" % (value_.text.rstrip(), " " * (value_.offset - 1) + "^") @@ -130,3 +124,32 @@ # scroll to bottom of output bottom = self.output.verticalScrollBar().maximum() self.output.verticalScrollBar().setValue(bottom) + + def run_py2_document(self, document): + """ Loads and executes an external script using Python 2 specific operations + and returns the loaded module for further execution if needed. + """ + try: + user_module = imp.load_source(EXEC_NAMESPACE, document.filePath) + except Exception as e: + raise e + + return user_module + + def run_py3_document(self, document): + """ Loads and executes an external script using Python 3 specific operations + and returns the loaded module for further execution if needed. + """ + spec = importlib.util.spec_from_file_location(EXEC_NAMESPACE, document.filePath) + try: + users_module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(users_module) + + except AttributeError as e: # no module from spec + if PYTHON34 or PYTHON33: + loader = SourceFileLoader(EXEC_NAMESPACE, document.filePath) + users_module = loader.load_module() + else: + raise e + + return users_module diff --git a/plugins/python/scripter/ui_scripter/actions/settingsaction/settingsaction.py b/plugins/python/scripter/ui_scripter/actions/settingsaction/settingsaction.py --- a/plugins/python/scripter/ui_scripter/actions/settingsaction/settingsaction.py +++ b/plugins/python/scripter/ui_scripter/actions/settingsaction/settingsaction.py @@ -40,7 +40,7 @@ def openSettings(self): self.settingsDialog.show() - self.settingsDialog.exec() + self.settingsDialog.exec_() def readSettings(self): self.settingsDialog.readSettings(self.scripter.settings) diff --git a/plugins/python/scripter/uicontroller.py b/plugins/python/scripter/uicontroller.py --- a/plugins/python/scripter/uicontroller.py +++ b/plugins/python/scripter/uicontroller.py @@ -15,14 +15,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -from PyQt5.QtGui import QTextCursor, QPalette, QFontInfo +from PyQt5.QtCore import Qt, QObject, QFileInfo, QRect +from PyQt5.QtGui import QTextCursor, QPalette from PyQt5.QtWidgets import (QToolBar, QMenuBar, QTabWidget, QLabel, QVBoxLayout, QMessageBox, QSplitter, QSizePolicy) -from PyQt5.QtCore import Qt, QObject, QFileInfo, pyqtSlot, QRect -from scripter.ui_scripter.syntax import syntax, syntaxstyles -from scripter.ui_scripter.editor import pythoneditor -from scripter import scripterdialog +from .ui_scripter.syntax import syntax, syntaxstyles +from .ui_scripter.editor import pythoneditor +from . import scripterdialog import importlib KEY_GEOMETRY = "geometry" @@ -122,7 +122,8 @@ modules = [] for class_path in actions_module.action_classes: - _module, _klass = class_path.rsplit('.', maxsplit=1) + _module = class_path[:class_path.rfind(".")] + _klass = class_path[class_path.rfind(".") + 1:] modules.append(dict(module='{0}.{1}'.format(module_path, _module), klass=_klass)) @@ -141,8 +142,9 @@ widgetsModule = importlib.import_module(modulePath) modules = [] - for classPath in widgetsModule.widgetClasses: - _module, _klass = classPath.rsplit('.', maxsplit=1) + for class_path in widgetsModule.widgetClasses: + _module = class_path[:class_path.rfind(".")] + _klass = class_path[class_path.rfind(".") + 1:] modules.append(dict(module='{0}.{1}'.format(modulePath, _module), klass=_klass)) diff --git a/plugins/python/tenbrushes/kritapykrita_tenbrushes.desktop b/plugins/python/tenbrushes/kritapykrita_tenbrushes.desktop --- a/plugins/python/tenbrushes/kritapykrita_tenbrushes.desktop +++ b/plugins/python/tenbrushes/kritapykrita_tenbrushes.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=tenbrushes -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Ten Brushes Name[ar]=عشرُ فُرش diff --git a/plugins/python/tenbrushes/tenbrushes.py b/plugins/python/tenbrushes/tenbrushes.py --- a/plugins/python/tenbrushes/tenbrushes.py +++ b/plugins/python/tenbrushes/tenbrushes.py @@ -10,7 +10,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' import krita -from tenbrushes import uitenbrushes +from . import uitenbrushes class TenBrushesExtension(krita.Extension): @@ -24,7 +24,7 @@ def setup(self): self.readSettings() - + def createActions(self, window): action = window.createAction("ten_brushes", "Ten Brushes") action.setToolTip("Assign ten brush presets to ten shortcuts.") diff --git a/plugins/python/tenbrushes/uitenbrushes.py b/plugins/python/tenbrushes/uitenbrushes.py --- a/plugins/python/tenbrushes/uitenbrushes.py +++ b/plugins/python/tenbrushes/uitenbrushes.py @@ -12,7 +12,7 @@ from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QPixmap, QIcon from PyQt5.QtWidgets import (QDialogButtonBox, QLabel, QVBoxLayout, QHBoxLayout) -from tenbrushes import tenbrushesdialog, dropbutton +from . import tenbrushesdialog, dropbutton import krita @@ -44,7 +44,6 @@ self.vbox.addWidget(self.presetChooser) self.vbox.addWidget(self.buttonBox) - self.mainDialog.show() self.mainDialog.activateWindow() self.mainDialog.exec_() diff --git a/plugins/python/tenscripts/kritapykrita_tenscripts.desktop b/plugins/python/tenscripts/kritapykrita_tenscripts.desktop --- a/plugins/python/tenscripts/kritapykrita_tenscripts.desktop +++ b/plugins/python/tenscripts/kritapykrita_tenscripts.desktop @@ -2,7 +2,7 @@ Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=tenscripts -X-Python-2-Compatible=false +X-Python-2-Compatible=true X-Krita-Manual=Manual.html Name=Ten Scripts Name[ar]=عشرُ سكربتات diff --git a/plugins/python/tenscripts/tenscripts.py b/plugins/python/tenscripts/tenscripts.py --- a/plugins/python/tenscripts/tenscripts.py +++ b/plugins/python/tenscripts/tenscripts.py @@ -9,23 +9,29 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode ''' +import sys + from PyQt5.QtWidgets import QMessageBox import krita -from tenscripts import uitenscripts -import importlib +from . import uitenscripts + +if sys.version_info[0] > 2: + import importlib +else: + import imp class TenScriptsExtension(krita.Extension): def __init__(self, parent): - super(TenScriptsExtension, self).__init__(parent) + super(TenScriptsExtension, self).__init__(parent) - self.actions = [] - self.scripts = [] + self.actions = [] + self.scripts = [] def setup(self): self.readSettings() - + def createActions(self, window): action = window.createAction("ten_scripts", "Ten Scripts") action.setToolTip("Assign ten scripts to ten shortcuts.") @@ -62,10 +68,13 @@ script = self.sender().script if script: try: - spec = importlib.util.spec_from_file_location("users_script", script) - users_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(users_module) - + if sys.version_info[0] > 2: + spec = importlib.util.spec_from_file_location("users_script", script) + users_module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(users_module) + else: + users_module = imp.load_source("users_script", script) + if hasattr(users_module, 'main') and callable(users_module.main): users_module.main() diff --git a/plugins/python/tenscripts/uitenscripts.py b/plugins/python/tenscripts/uitenscripts.py --- a/plugins/python/tenscripts/uitenscripts.py +++ b/plugins/python/tenscripts/uitenscripts.py @@ -13,7 +13,7 @@ from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLineEdit, QScrollArea, QGridLayout, QFileDialog, QLabel, QDialogButtonBox) -from tenscripts import tenscriptsdialog +from . import tenscriptsdialog import krita @@ -27,7 +27,7 @@ self.layout = QVBoxLayout(self.mainDialog) self.baseWidget = QWidget() self.baseArea = QWidget() - self.scrollArea = QScrollArea() + self.scrollArea = QScrollArea() self.scriptsLayout = QGridLayout() self.buttonBox.accepted.connect(self.mainDialog.accept) @@ -86,7 +86,7 @@ dialog = QFileDialog(self.mainDialog) dialog.setNameFilter('Python files (*.py)') - if dialog.exec(): + if dialog.exec_(): selectedFile = dialog.selectedFiles()[0] obj = self.mainDialog.sender() textField = self.scriptsLayout.itemAt(self.scriptsLayout.indexOf(obj)-1).widget()