Commit 6509644e authored by Jeroen Hoolmans's avatar Jeroen Hoolmans

Added support to compile with Python2.7 on Linux

Windows support will come later as discussed in
https://phabricator.kde.org/D12838. To compile use the
-DENABLE_PYTHON_2 flag. Python 3 is still the default.

For the plugins to work correctly we need the tollius and pathlib
modules through pip.

Differential Revision: https://phabricator.kde.org/D12838
parent 65e24ca5
......@@ -5,7 +5,7 @@ project (krita-and-all-its-deps)
# 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(EXTPREFIX "${TOP_INST_DIR}")
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 @@ endif()
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 @@ endfunction()
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)
......
......@@ -194,6 +194,7 @@ add_feature_info("Foundation Build" FOUNDATION_BUILD "A Foundation build is a bi
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 @@ int main(int argc, char *argv[]) {
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 @@ if (APPLE)
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 @@ endif()
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
......
......@@ -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)
......
......@@ -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 @@ set(SOURCES
PythonPluginsModel.cpp
)
ki18n_wrap_ui(SOURCES
info.ui
ki18n_wrap_ui(SOURCES
info.ui
manager.ui
)
......
......@@ -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 @@ namespace
} // 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;
......
......@@ -25,9 +25,19 @@
#include <Python.h>
#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
......@@ -59,6 +59,13 @@ bool PythonPlugin::isValid() const
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;
}
......
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 @@ except ImportError:
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()
......
......@@ -7,7 +7,7 @@ from PyKrita.krita import *
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):
......
......@@ -76,7 +76,11 @@ namespace PyKrita
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 @@ namespace PyKrita
pluginManagerInstance.reset(new PythonPluginManager());
#if defined(IS_PY3K)
// Initialize our built-in module.
auto pykritaModule = PyInit_pykrita();
......@@ -109,6 +114,9 @@ namespace PyKrita
return initStatus;
//return i18nc("@info:tooltip ", "No <icode>pykrita</icode> built-in module");
}
#else
initpykrita();
#endif
initStatus = INIT_OK;
return initStatus;
......@@ -412,7 +420,9 @@ bool Python::setPath(const QStringList& scriptPaths)
if (KoResourcePaths::getApplicationRoot().contains(".mount_Krita")) {
QVector<wchar_t> 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());
......
......@@ -6,7 +6,7 @@ message( ${SIP_EXECUTABLE} " - Path and filename of the SIP command line executa
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 @@ file(GLOB PYKRITA_KRITA_sip_files ./krita/*.sip)
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)
......@@ -9,20 +9,20 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class AssignProfileDialog(Extension):
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 @@ class AssignProfileDialog(Extension):
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))
......@@ -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]=إسناد اللاحات إلى الصّور
......
......@@ -10,7 +10,7 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class ColorSpaceExtension(krita.Extension):
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")
......
......@@ -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]=الفضاء اللونيّ
......
......@@ -9,8 +9,8 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ from PyQt5.QtWidgets import (QFormLayout, QListWidget, QListWidgetItem,
QHBoxLayout, QAbstractScrollArea)
from PyQt5.QtGui import QIcon
import krita
from colorspace import resources_rc
from . import resources_rc
class UIColorSpace(object):
......
......@@ -10,7 +10,7 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class DocumentToolsExtension(krita.Extension):
def setup(self):
pass
def createActions(self, window):
action = window.createAction("document_tools", "Document Tools")
action.setToolTip("Plugin to manipulate properties of selected documents")
......
......@@ -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]=أدوات المستندات
......
......@@ -9,7 +9,7 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class UIDocumentTools(object):
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))
......
......@@ -10,7 +10,7 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class ExportLayersExtension(krita.Extension):
def setup(self):
pass
def createActions(self, window):
action = window.createAction("export_layers", "Export Layers")
action.setToolTip("Plugin to export layers from a document")
......
......@@ -3,7 +3,7 @@ Type=Service
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
......
......@@ -9,7 +9,7 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class UIExportLayers(object):
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 @@ class UIExportLayers(object):
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 @@ class UIExportLayers(object):
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)
......
......@@ -11,7 +11,7 @@ https://creativecommons.org/publicdomain/zero/1.0/legalcode
'''
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
......
......@@ -10,7 +10,7 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class FilterManagerExtension(krita.Extension):
def setup(self):
pass
def createActions(self, window):
action = window.createAction("filter_manager", "Filter Manager")
action.setToolTip("Plugin to filters management")
......
......@@ -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]=مدير المرشّحات
......
......@@ -9,8 +9,8 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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,
......
......@@ -9,14 +9,14 @@ You can copy, modify, distribute and perform the work, even for commercial purpo
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 @@ class HelloExtension(Extension):
: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 @@ class HelloDocker(DockWidget):
"""
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!
......
......@@ -3,7 +3,7 @@ Type=Service
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]=مرحبًا يا عالم