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,13 @@ 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) + find_package(PythonInterp 2.7 EXACT) + find_package(PythonLibs 2.7 EXACT) + 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,32 @@ endfunction() if(MINGW) - find_package(PythonInterp 3.6 EXACT) - find_package(PythonLibs 3.6 EXACT) + if(ENABLE_PYTHON_2) + find_package(PythonInterp 2.7 EXACT) + find_package(PythonLibs 2.7 EXACT) + 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.0) + find_package(PythonLibrary 2.0) + else(ENABLE_PYTHON_2) + find_package(PythonInterp 3.0) + find_package(PythonLibrary 3.0) + endif(ENABLE_PYTHON_2) endif(MINGW) ######################## @@ -458,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 @@ -620,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.6 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,8 +3,8 @@ 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 @@ -12,8 +12,8 @@ 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,6 +105,7 @@ pluginManagerInstance.reset(new PythonPluginManager()); +#if defined(IS_PY3K) // Initialize our built-in module. auto pykritaModule = PyInit_pykrita(); @@ -109,6 +114,9 @@ return initStatus; //return i18nc("@info:tooltip ", "No pykrita built-in module"); } +#else + initpykrita(); +#endif initStatus = INIT_OK; return initStatus; @@ -407,12 +415,16 @@ #ifdef Q_OS_WIN 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 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,8 +9,8 @@ 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, @@ -18,7 +18,7 @@ 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,7 +101,9 @@ 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()) @@ -106,15 +112,15 @@ @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()