일단 커밋. 오랫동안 커밋을 안해서 꼬였다.

리팩토리 중.
This commit is contained in:
2025-11-15 15:59:49 +09:00
parent 5a47b792d6
commit d79c10b975
12909 changed files with 2070539 additions and 285 deletions

View File

@@ -0,0 +1,20 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################

View File

@@ -0,0 +1,123 @@
#############################################################################
##
## Copyright (C) 2019 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
import sys
from ..properties import Properties
from ..uiparser import UIParser
from . import qtproxies
from .indenter import createCodeIndenter, getIndenter, write_code
from .qobjectcreator import CompilerCreatorPolicy
class UICompiler(UIParser):
def __init__(self):
UIParser.__init__(self, qtproxies.QtCore, qtproxies.QtGui,
qtproxies.QtWidgets, CompilerCreatorPolicy())
def reset(self):
qtproxies.i18n_strings = []
UIParser.reset(self)
def setContext(self, context):
qtproxies.i18n_context = context
def createToplevelWidget(self, classname, widgetname):
indenter = getIndenter()
indenter.level = 0
indenter.write("from PyQt5 import QtCore, QtGui, QtWidgets")
indenter.write("")
indenter.write("")
indenter.write("class Ui_%s(object):" % self.uiname)
indenter.indent()
indenter.write("def setupUi(self, %s):" % widgetname)
indenter.indent()
w = self.factory.createQObject(classname, widgetname, (),
is_attribute = False,
no_instantiation = True)
w.baseclass = classname
w.uiclass = "Ui_%s" % self.uiname
return w
def setDelayedProps(self):
write_code("")
write_code("self.retranslateUi(%s)" % self.toplevelWidget)
UIParser.setDelayedProps(self)
def finalize(self):
indenter = getIndenter()
indenter.level = 1
indenter.write("")
indenter.write("def retranslateUi(self, %s):" % self.toplevelWidget)
indenter.indent()
if qtproxies.i18n_strings:
indenter.write("_translate = QtCore.QCoreApplication.translate")
for s in qtproxies.i18n_strings:
indenter.write(s)
else:
indenter.write("pass")
indenter.dedent()
indenter.dedent()
# Keep a reference to the resource modules to import because the parser
# will reset() before returning.
self._resources = self.resources
self._resources.sort()
def compileUi(self, input_stream, output_stream, from_imports, resource_suffix, import_from):
createCodeIndenter(output_stream)
w = self.parse(input_stream, resource_suffix)
self.factory._cpolicy._writeOutImports()
for res in self._resources:
if from_imports:
write_code("from %s import %s" % (import_from, res))
else:
write_code("import %s" % res)
return {"widgetname": str(w),
"uiclass" : w.uiclass,
"baseclass" : w.baseclass}

View File

@@ -0,0 +1,77 @@
#############################################################################
##
## Copyright (C) 2014 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
indentwidth = 4
_indenter = None
class _IndentedCodeWriter(object):
def __init__(self, output):
self.level = 0
self.output = output
def indent(self):
self.level += 1
def dedent(self):
self.level -= 1
def write(self, line):
if line.strip():
if indentwidth > 0:
indent = " " * indentwidth
line = line.replace("\t", indent)
else:
indent = "\t"
self.output.write("%s%s\n" % (indent * self.level, line))
else:
self.output.write("\n")
def createCodeIndenter(output):
global _indenter
_indenter = _IndentedCodeWriter(output)
def getIndenter():
return _indenter
def write_code(string):
_indenter.write(string)

View File

@@ -0,0 +1,59 @@
#############################################################################
##
## Copyright (C) 2016 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
def moduleMember(module, name):
if module:
return "%s.%s" % (module, name)
return name
class Literal(object):
"""Literal(string) -> new literal
string will not be quoted when put into an argument list"""
def __init__(self, string):
self.string = string
def __str__(self):
return self.string
def __or__(self, r_op):
return Literal("%s|%s" % (self, r_op))

View File

@@ -0,0 +1,100 @@
#############################################################################
##
## Copyright (C) 2014 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
from .misc import Literal, moduleMember
class ProxyMetaclass(type):
""" ProxyMetaclass is the meta-class for proxies. """
def __init__(*args):
""" Initialise the meta-class. """
# Initialise as normal.
type.__init__(*args)
# The proxy type object we have created.
proxy = args[0]
# Go through the proxy's attributes looking for other proxies.
for sub_proxy in proxy.__dict__.values():
if type(sub_proxy) is ProxyMetaclass:
# Set the module name of the contained proxy to the name of the
# container proxy.
sub_proxy.module = proxy.__name__
# Attribute hierachies are created depth first so any proxies
# contained in the sub-proxy whose module we have just set will
# already exist and have an incomplete module name. We need to
# revisit them and prepend the new name to their module names.
# Note that this should be recursive but with current usage we
# know there will be only one level to revisit.
for sub_sub_proxy in sub_proxy.__dict__.values():
if type(sub_sub_proxy) is ProxyMetaclass:
sub_sub_proxy.module = '%s.%s' % (proxy.__name__, sub_sub_proxy.module)
# Makes sure there is a 'module' attribute.
if not hasattr(proxy, 'module'):
proxy.module = ''
def __getattribute__(cls, name):
try:
return type.__getattribute__(cls, name)
except AttributeError:
# Make sure __init__()'s use of hasattr() works.
if name == 'module':
raise
# Avoid a circular import.
from .qtproxies import LiteralProxyClass
return type(name, (LiteralProxyClass, ),
{"module": moduleMember(type.__getattribute__(cls, "module"),
type.__getattribute__(cls, "__name__"))})
def __str__(cls):
return moduleMember(type.__getattribute__(cls, "module"),
type.__getattribute__(cls, "__name__"))
def __or__(self, r_op):
return Literal("%s|%s" % (self, r_op))
def __eq__(self, other):
return str(self) == str(other)

View File

@@ -0,0 +1,180 @@
#############################################################################
##
## Copyright (C) 2018 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
import logging
import sys
from .indenter import write_code
from .qtproxies import QtGui, QtWidgets, Literal, strict_getattr
if sys.hexversion >= 0x03000000:
from ..port_v3.as_string import as_string
else:
from ..port_v2.as_string import as_string
logger = logging.getLogger(__name__)
DEBUG = logger.debug
class _QtWrapper(object):
@classmethod
def search(cls, name):
try:
return strict_getattr(cls.module, name)
except AttributeError:
return None
class _QtGuiWrapper(_QtWrapper):
module = QtGui
class _QtWidgetsWrapper(_QtWrapper):
module = QtWidgets
class _ModuleWrapper(object):
def __init__(self, name, classes):
if "." in name:
idx = name.rfind(".")
self._package = name[:idx]
self._module = name[idx + 1:]
else:
self._package = None
self._module = name
self._classes = classes
self._used = False
def search(self, cls):
if cls in self._classes:
self._used = True
# Remove any C++ scope.
cls = cls.split('.')[-1]
return type(cls, (QtWidgets.QWidget,), {"module": self._module})
else:
return None
def _writeImportCode(self):
if self._used:
if self._package is None:
write_code("import %s" % self._module)
else:
write_code("from %s import %s" % (self._package, self._module))
class _CustomWidgetLoader(object):
def __init__(self):
self._widgets = {}
self._usedWidgets = set()
def addCustomWidget(self, widgetClass, baseClass, module):
assert widgetClass not in self._widgets
self._widgets[widgetClass] = (baseClass, module)
def _resolveBaseclass(self, baseClass):
try:
for x in range(0, 10):
try: return strict_getattr(QtWidgets, baseClass)
except AttributeError: pass
baseClass = self._widgets[baseClass][0]
else:
raise ValueError("baseclass resolve took too long, check custom widgets")
except KeyError:
raise ValueError("unknown baseclass %s" % baseClass)
def search(self, cls):
try:
baseClass = self._resolveBaseclass(self._widgets[cls][0])
DEBUG("resolved baseclass of %s: %s" % (cls, baseClass))
except KeyError:
return None
self._usedWidgets.add(cls)
return type(cls, (baseClass, ), {"module" : ""})
def _writeImportCode(self):
imports = {}
for widget in self._usedWidgets:
_, module = self._widgets[widget]
imports.setdefault(module, []).append(widget)
for module, classes in sorted(imports.items()):
write_code("from %s import %s" % (module, ", ".join(sorted(classes))))
class CompilerCreatorPolicy(object):
def __init__(self):
self._modules = []
def createQtGuiWidgetsWrappers(self):
return [_QtGuiWrapper, _QtWidgetsWrapper]
def createModuleWrapper(self, name, classes):
mw = _ModuleWrapper(name, classes)
self._modules.append(mw)
return mw
def createCustomWidgetLoader(self):
cw = _CustomWidgetLoader()
self._modules.append(cw)
return cw
def instantiate(self, clsObject, objectname, ctor_args, is_attribute=True, no_instantiation=False):
return clsObject(objectname, is_attribute, ctor_args, no_instantiation)
def invoke(self, rname, method, args):
return method(rname, *args)
def getSlot(self, object, slotname):
return Literal("%s.%s" % (object, slotname))
def asString(self, s):
return as_string(s)
def _writeOutImports(self):
for module in self._modules:
module._writeImportCode()

View File

@@ -0,0 +1,470 @@
#############################################################################
##
## Copyright (C) 2021 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
import sys
import re
from .indenter import write_code
from .misc import Literal, moduleMember
if sys.hexversion >= 0x03000000:
from ..port_v3.proxy_base import ProxyBase
from ..port_v3.as_string import as_string
else:
from ..port_v2.proxy_base import ProxyBase
from ..port_v2.as_string import as_string
i18n_strings = []
i18n_context = ""
def i18n_print(string):
i18n_strings.append(string)
def i18n_void_func(name):
def _printer(self, *args):
i18n_print("%s.%s(%s)" % (self, name, ", ".join(map(as_string, args))))
return _printer
def i18n_func(name):
def _printer(self, rname, *args):
i18n_print("%s = %s.%s(%s)" % (rname, self, name, ", ".join(map(as_string, args))))
return Literal(rname)
return _printer
def strict_getattr(module, clsname):
cls = getattr(module, clsname)
if issubclass(cls, LiteralProxyClass):
raise AttributeError(cls)
else:
return cls
class i18n_string(object):
def __init__(self, string, disambig):
self.string = string
self.disambig = disambig
def __str__(self):
if self.disambig is None:
return '_translate("%s", %s)' % (i18n_context, as_string(self.string))
return '_translate("%s", %s, %s)' % (i18n_context, as_string(self.string), as_string(self.disambig))
# Classes with this flag will be handled as literal values. If functions are
# called on these classes, the literal value changes.
# Example:
# the code
# >>> QSize(9,10).expandedTo(...)
# will print just that code.
AS_ARGUMENT = 0x02
# Classes with this flag may have members that are signals which themselves
# will have a connect() member.
AS_SIGNAL = 0x01
# ATTENTION: currently, classes can either be literal or normal. If a class
# should need both kinds of behaviour, the code has to be changed.
class ProxyClassMember(object):
def __init__(self, proxy, function_name, flags):
self.proxy = proxy
self.function_name = function_name
self.flags = flags
def __str__(self):
return "%s.%s" % (self.proxy, self.function_name)
def __call__(self, *args):
if self.function_name == 'setProperty':
str_args = (as_string(args[0]), as_string(args[1]))
else:
str_args = map(as_string, args)
func_call = "%s.%s(%s)" % (self.proxy,
self.function_name,
", ".join(str_args))
if self.flags & AS_ARGUMENT:
self.proxy._uic_name = func_call
return self.proxy
else:
needs_translation = False
for arg in args:
if isinstance(arg, i18n_string):
needs_translation = True
if needs_translation:
i18n_print(func_call)
else:
if self.function_name == 'connect':
func_call += ' # type: ignore'
write_code(func_call)
def __getattribute__(self, attribute):
""" Reimplemented to create a proxy connect() if requested and this
might be a proxy for a signal.
"""
try:
return object.__getattribute__(self, attribute)
except AttributeError:
if attribute == 'connect' and self.flags & AS_SIGNAL:
return ProxyClassMember(self, attribute, 0)
raise
def __getitem__(self, idx):
""" Reimplemented to create a proxy member that should be a signal that
passes arguments. We handle signals without arguments before we get
here and never apply the index notation to them.
"""
return ProxySignalWithArguments(self.proxy, self.function_name, idx)
class ProxySignalWithArguments(object):
""" This is a proxy for (what should be) a signal that passes arguments.
"""
def __init__(self, sender, signal_name, signal_index):
self._sender = sender
self._signal_name = signal_name
# Convert the signal index, which will be a single argument or a tuple
# of arguments, to quoted strings.
if isinstance(signal_index, tuple):
self._signal_index = ','.join(["'%s'" % a for a in signal_index])
else:
self._signal_index = "'%s'" % signal_index
def connect(self, slot):
write_code("%s.%s[%s].connect(%s) # type: ignore" % (self._sender, self._signal_name, self._signal_index, slot))
class ProxyClass(ProxyBase):
flags = 0
def __init__(self, objectname, is_attribute, args=(), noInstantiation=False):
if objectname:
if is_attribute:
objectname = "self." + objectname
self._uic_name = objectname
else:
self._uic_name = "Unnamed"
if not noInstantiation:
funcall = "%s(%s)" % \
(moduleMember(self.module, self.__class__.__name__),
", ".join(map(str, args)))
if objectname:
funcall = "%s = %s" % (objectname, funcall)
write_code(funcall)
def __str__(self):
return self._uic_name
def __getattribute__(self, attribute):
try:
return object.__getattribute__(self, attribute)
except AttributeError:
return ProxyClassMember(self, attribute, self.flags)
class LiteralProxyClass(ProxyClass):
"""LiteralObject(*args) -> new literal class
a literal class can be used as argument in a function call
>>> class Foo(LiteralProxyClass): pass
>>> str(Foo(1,2,3)) == "Foo(1,2,3)"
"""
flags = AS_ARGUMENT
def __init__(self, *args):
self._uic_name = "%s(%s)" % \
(moduleMember(self.module, self.__class__.__name__),
", ".join(map(as_string, args)))
class ProxyNamespace(ProxyBase):
pass
# These are all the Qt classes used by pyuic5 in their namespaces. If a class
# is missing, the compiler will fail, normally with an AttributeError.
#
# For adding new classes:
# - utility classes used as literal values do not need to be listed
# because they are created on the fly as subclasses of LiteralProxyClass
# - classes which are *not* QWidgets inherit from ProxyClass and they
# have to be listed explicitly in the correct namespace. These classes
# are created via a ProxyQObjectCreator
# - new QWidget-derived classes have to inherit from qtproxies.QWidget
# If the widget does not need any special methods, it can be listed
# in _qwidgets
class QtCore(ProxyNamespace):
class Qt(ProxyNamespace):
pass
## connectSlotsByName and connect have to be handled as class methods,
## otherwise they would be created as LiteralProxyClasses and never be
## printed
class QMetaObject(ProxyClass):
@classmethod
def connectSlotsByName(cls, *args):
ProxyClassMember(cls, "connectSlotsByName", 0)(*args)
class QObject(ProxyClass):
flags = AS_SIGNAL
def metaObject(self):
class _FakeMetaObject(object):
def className(*args):
return self.__class__.__name__
return _FakeMetaObject()
def objectName(self):
return self._uic_name.split(".")[-1]
class QtGui(ProxyNamespace):
class QIcon(ProxyClass):
class fromTheme(ProxyClass): pass
class QConicalGradient(ProxyClass): pass
class QLinearGradient(ProxyClass): pass
class QRadialGradient(ProxyClass): pass
class QBrush(ProxyClass): pass
class QPainter(ProxyClass): pass
class QPalette(ProxyClass): pass
class QFont(ProxyClass): pass
class QFontDatabase(ProxyClass): pass
# These sub-class QWidget but aren't themselves sub-classed.
_qwidgets = ("QCalendarWidget", "QDialogButtonBox", "QDockWidget", "QGroupBox",
"QLineEdit", "QMainWindow", "QMenuBar", "QOpenGLWidget",
"QProgressBar", "QStatusBar", "QToolBar", "QWizardPage")
class QtWidgets(ProxyNamespace):
class QApplication(QtCore.QObject):
@staticmethod
def translate(uiname, text, disambig):
return i18n_string(text or "", disambig)
class QSpacerItem(ProxyClass): pass
class QSizePolicy(ProxyClass): pass
# QActions inherit from QObject for the meta-object stuff and the hierarchy
# has to be correct since we have a isinstance(x, QtWidgets.QLayout) call
# in the UI parser.
class QAction(QtCore.QObject): pass
class QActionGroup(QtCore.QObject): pass
class QButtonGroup(QtCore.QObject): pass
class QLayout(QtCore.QObject): pass
class QGridLayout(QLayout): pass
class QBoxLayout(QLayout): pass
class QHBoxLayout(QBoxLayout): pass
class QVBoxLayout(QBoxLayout): pass
class QFormLayout(QLayout): pass
class QWidget(QtCore.QObject):
def font(self):
return Literal("%s.font()" % self)
def minimumSizeHint(self):
return Literal("%s.minimumSizeHint()" % self)
def sizePolicy(self):
sp = LiteralProxyClass()
sp._uic_name = "%s.sizePolicy()" % self
return sp
class QDialog(QWidget): pass
class QColorDialog(QDialog): pass
class QFileDialog(QDialog): pass
class QFontDialog(QDialog): pass
class QInputDialog(QDialog): pass
class QMessageBox(QDialog): pass
class QWizard(QDialog): pass
class QAbstractSlider(QWidget): pass
class QDial(QAbstractSlider): pass
class QScrollBar(QAbstractSlider): pass
class QSlider(QAbstractSlider): pass
class QMenu(QWidget):
def menuAction(self):
return Literal("%s.menuAction()" % self)
class QTabWidget(QWidget):
def addTab(self, *args):
text = args[-1]
if isinstance(text, i18n_string):
i18n_print("%s.setTabText(%s.indexOf(%s), %s)" % \
(self._uic_name, self._uic_name, args[0], text))
args = args[:-1] + ("", )
ProxyClassMember(self, "addTab", 0)(*args)
def indexOf(self, page):
return Literal("%s.indexOf(%s)" % (self, page))
class QComboBox(QWidget): pass
class QFontComboBox(QComboBox): pass
class QAbstractSpinBox(QWidget): pass
class QDoubleSpinBox(QAbstractSpinBox): pass
class QSpinBox(QAbstractSpinBox): pass
class QDateTimeEdit(QAbstractSpinBox): pass
class QDateEdit(QDateTimeEdit): pass
class QTimeEdit(QDateTimeEdit): pass
class QFrame(QWidget): pass
class QLabel(QFrame): pass
class QLCDNumber(QFrame): pass
class QSplitter(QFrame): pass
class QStackedWidget(QFrame): pass
class QToolBox(QFrame):
def addItem(self, *args):
text = args[-1]
if isinstance(text, i18n_string):
i18n_print("%s.setItemText(%s.indexOf(%s), %s)" % \
(self._uic_name, self._uic_name, args[0], text))
args = args[:-1] + ("", )
ProxyClassMember(self, "addItem", 0)(*args)
def indexOf(self, page):
return Literal("%s.indexOf(%s)" % (self, page))
def layout(self):
return QtWidgets.QLayout("%s.layout()" % self,
False, (), noInstantiation=True)
class QAbstractScrollArea(QFrame):
def viewport(self):
return QtWidgets.QWidget("%s.viewport()" % self, False, (),
noInstantiation=True)
class QGraphicsView(QAbstractScrollArea): pass
class QMdiArea(QAbstractScrollArea): pass
class QPlainTextEdit(QAbstractScrollArea): pass
class QScrollArea(QAbstractScrollArea): pass
class QTextEdit(QAbstractScrollArea): pass
class QTextBrowser(QTextEdit): pass
class QAbstractItemView(QAbstractScrollArea): pass
class QColumnView(QAbstractItemView): pass
class QHeaderView(QAbstractItemView): pass
class QListView(QAbstractItemView): pass
class QTableView(QAbstractItemView):
def horizontalHeader(self):
return QtWidgets.QHeaderView("%s.horizontalHeader()" % self,
False, (), noInstantiation=True)
def verticalHeader(self):
return QtWidgets.QHeaderView("%s.verticalHeader()" % self,
False, (), noInstantiation=True)
class QTreeView(QAbstractItemView):
def header(self):
return QtWidgets.QHeaderView("%s.header()" % self,
False, (), noInstantiation=True)
class QUndoView(QListView): pass
class QListWidgetItem(ProxyClass): pass
class QListWidget(QListView):
setSortingEnabled = i18n_void_func("setSortingEnabled")
isSortingEnabled = i18n_func("isSortingEnabled")
item = i18n_func("item")
class QTableWidgetItem(ProxyClass): pass
class QTableWidget(QTableView):
setSortingEnabled = i18n_void_func("setSortingEnabled")
isSortingEnabled = i18n_func("isSortingEnabled")
item = i18n_func("item")
horizontalHeaderItem = i18n_func("horizontalHeaderItem")
verticalHeaderItem = i18n_func("verticalHeaderItem")
class QTreeWidgetItem(ProxyClass):
def child(self, index):
return QtWidgets.QTreeWidgetItem("%s.child(%i)" % (self, index),
False, (), noInstantiation=True)
class QTreeWidget(QTreeView):
setSortingEnabled = i18n_void_func("setSortingEnabled")
isSortingEnabled = i18n_func("isSortingEnabled")
def headerItem(self):
return QtWidgets.QWidget("%s.headerItem()" % self, False, (),
noInstantiation=True)
def topLevelItem(self, index):
return QtWidgets.QTreeWidgetItem("%s.topLevelItem(%i)" % (self, index),
False, (), noInstantiation=True)
class QAbstractButton(QWidget): pass
class QCheckBox(QAbstractButton): pass
class QRadioButton(QAbstractButton): pass
class QToolButton(QAbstractButton): pass
class QPushButton(QAbstractButton): pass
class QCommandLinkButton(QPushButton): pass
class QKeySequenceEdit(QWidget): pass
# Add all remaining classes.
for _class in _qwidgets:
if _class not in locals():
locals()[_class] = type(_class, (QWidget, ), {})

View File

@@ -0,0 +1,20 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################

View File

@@ -0,0 +1,66 @@
#############################################################################
##
## Copyright (C) 2019 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
from PyQt5 import QtCore, QtGui, QtWidgets
from ..uiparser import UIParser
from .qobjectcreator import LoaderCreatorPolicy
class DynamicUILoader(UIParser):
def __init__(self, package):
UIParser.__init__(self, QtCore, QtGui, QtWidgets,
LoaderCreatorPolicy(package))
def createToplevelWidget(self, classname, widgetname):
if self.toplevelInst is None:
return self.factory.createQObject(classname, widgetname, ())
if not isinstance(self.toplevelInst, self.factory.findQObjectType(classname)):
raise TypeError(
("Wrong base class of toplevel widget",
(type(self.toplevelInst), classname)))
return self.toplevelInst
def loadUi(self, filename, toplevelInst, resource_suffix):
self.toplevelInst = toplevelInst
return self.parse(filename, resource_suffix)

View File

@@ -0,0 +1,150 @@
#############################################################################
##
## Copyright (C) 2015 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
import sys
from PyQt5 import QtGui, QtWidgets
class _QtWrapper(object):
@classmethod
def search(cls, name):
return getattr(cls.module, name, None)
class _QtGuiWrapper(_QtWrapper):
module = QtGui
class _QtWidgetsWrapper(_QtWrapper):
module = QtWidgets
class _ModuleWrapper(object):
def __init__(self, moduleName, classes):
self._moduleName = moduleName
self._module = None
self._classes = classes
def search(self, cls):
if cls in self._classes:
if self._module is None:
self._module = __import__(self._moduleName, {}, {}, self._classes)
# Remove any C++ scope.
cls = cls.split('.')[-1]
return getattr(self._module, cls)
return None
class _CustomWidgetLoader(object):
def __init__(self, package):
# should it stay this way?
if '.' not in sys.path:
sys.path.append('.')
self._widgets = {}
self._modules = {}
self._package = package
def addCustomWidget(self, widgetClass, baseClass, module):
assert widgetClass not in self._widgets
self._widgets[widgetClass] = module
def search(self, cls):
module_name = self._widgets.get(cls)
if module_name is None:
return None
module = self._modules.get(module_name)
if module is None:
if module_name.startswith('.'):
if self._package == '':
raise ImportError(
"relative import of %s without base package specified" % module_name)
if self._package.startswith('.'):
raise ImportError(
"base package %s is relative" % self._package)
mname = self._package + module_name
else:
mname = module_name
try:
module = __import__(mname, {}, {}, (cls,))
except ValueError:
# Raise a more helpful exception.
raise ImportError("unable to import module %s" % mname)
self._modules[module_name] = module
return getattr(module, cls)
class LoaderCreatorPolicy(object):
def __init__(self, package):
self._package = package
def createQtGuiWidgetsWrappers(self):
return [_QtGuiWrapper, _QtWidgetsWrapper]
def createModuleWrapper(self, moduleName, classes):
return _ModuleWrapper(moduleName, classes)
def createCustomWidgetLoader(self):
return _CustomWidgetLoader(self._package)
def instantiate(self, clsObject, objectName, ctor_args, is_attribute=True):
return clsObject(*ctor_args)
def invoke(self, rname, method, args):
return method(*args)
def getSlot(self, object, slotname):
# Rename slots that correspond to Python keyword arguments.
if slotname == 'raise':
slotname += '_'
return getattr(object, slotname)
def asString(self, s):
return s

View File

@@ -0,0 +1,245 @@
#############################################################################
##
## Copyright (C) 2020 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
__all__ = ("compileUi", "compileUiDir", "loadUiType", "loadUi", "widgetPluginPath")
from .Compiler import indenter, compiler
_header = """# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file '%s'
#
# Created by: PyQt5 UI code generator %s
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
"""
_display_code = """
if __name__ == "__main__":
\timport sys
\tapp = QtWidgets.QApplication(sys.argv)
\t%(widgetname)s = QtWidgets.%(baseclass)s()
\tui = %(uiclass)s()
\tui.setupUi(%(widgetname)s)
\t%(widgetname)s.show()
\tsys.exit(app.exec_())"""
def compileUiDir(dir, recurse=False, map=None, **compileUi_args):
"""compileUiDir(dir, recurse=False, map=None, **compileUi_args)
Creates Python modules from Qt Designer .ui files in a directory or
directory tree.
dir is the name of the directory to scan for files whose name ends with
'.ui'. By default the generated Python module is created in the same
directory ending with '.py'.
recurse is set if any sub-directories should be scanned. The default is
False.
map is an optional callable that is passed the name of the directory
containing the '.ui' file and the name of the Python module that will be
created. The callable should return a tuple of the name of the directory
in which the Python module will be created and the (possibly modified)
name of the module. The default is None.
compileUi_args are any additional keyword arguments that are passed to
the compileUi() function that is called to create each Python module.
"""
import os
# Compile a single .ui file.
def compile_ui(ui_dir, ui_file):
# Ignore if it doesn't seem to be a .ui file.
if ui_file.endswith('.ui'):
py_dir = ui_dir
py_file = ui_file[:-3] + '.py'
# Allow the caller to change the name of the .py file or generate
# it in a different directory.
if map is not None:
py_dir, py_file = map(py_dir, py_file)
# Make sure the destination directory exists.
try:
os.makedirs(py_dir)
except:
pass
ui_path = os.path.join(ui_dir, ui_file)
py_path = os.path.join(py_dir, py_file)
try:
# Python v3.
py_file = open(py_path, 'w', encoding='utf-8')
except TypeError:
# Python v2.
py_file = open(py_path, 'w')
try:
compileUi(ui_path, py_file, **compileUi_args)
finally:
py_file.close()
if recurse:
for root, _, files in os.walk(dir):
for ui in files:
compile_ui(root, ui)
else:
for ui in os.listdir(dir):
if os.path.isfile(os.path.join(dir, ui)):
compile_ui(dir, ui)
def compileUi(uifile, pyfile, execute=False, indent=4, from_imports=False, resource_suffix='_rc', import_from='.'):
"""compileUi(uifile, pyfile, execute=False, indent=4, from_imports=False, resource_suffix='_rc', import_from='.')
Creates a Python module from a Qt Designer .ui file.
uifile is a file name or file-like object containing the .ui file.
pyfile is the file-like object to which the Python code will be written to.
execute is optionally set to generate extra Python code that allows the
code to be run as a standalone application. The default is False.
indent is the optional indentation width using spaces. If it is 0 then a
tab is used. The default is 4.
from_imports is optionally set to generate relative import statements. At
the moment this only applies to the import of resource modules.
resource_suffix is the suffix appended to the basename of any resource file
specified in the .ui file to create the name of the Python module generated
from the resource file by pyrcc4. The default is '_rc', i.e. if the .ui
file specified a resource file called foo.qrc then the corresponding Python
module is foo_rc.
import_from is optionally set to the package used for relative import
statements. The default is ``'.'``.
"""
from PyQt5.QtCore import PYQT_VERSION_STR
try:
uifname = uifile.name
except AttributeError:
uifname = uifile
indenter.indentwidth = indent
pyfile.write(_header % (uifname, PYQT_VERSION_STR))
winfo = compiler.UICompiler().compileUi(uifile, pyfile, from_imports, resource_suffix, import_from)
if execute:
indenter.write_code(_display_code % winfo)
def loadUiType(uifile, from_imports=False, resource_suffix='_rc', import_from='.'):
"""loadUiType(uifile, from_imports=False, resource_suffix='_rc', import_from='.') -> (form class, base class)
Load a Qt Designer .ui file and return the generated form class and the Qt
base class.
uifile is a file name or file-like object containing the .ui file.
from_imports is optionally set to generate relative import statements. At
the moment this only applies to the import of resource modules.
resource_suffix is the suffix appended to the basename of any resource file
specified in the .ui file to create the name of the Python module generated
from the resource file by pyrcc4. The default is '_rc', i.e. if the .ui
file specified a resource file called foo.qrc then the corresponding Python
module is foo_rc.
import_from is optionally set to the package used for relative import
statements. The default is ``'.'``.
"""
import sys
from PyQt5 import QtWidgets
if sys.hexversion >= 0x03000000:
from .port_v3.string_io import StringIO
else:
from .port_v2.string_io import StringIO
code_string = StringIO()
winfo = compiler.UICompiler().compileUi(uifile, code_string, from_imports,
resource_suffix, import_from)
ui_globals = {}
exec(code_string.getvalue(), ui_globals)
uiclass = winfo["uiclass"]
baseclass = winfo["baseclass"]
# Assume that the base class is a custom class exposed in the globals.
ui_base = ui_globals.get(baseclass)
if ui_base is None:
# Otherwise assume it is in the QtWidgets module.
ui_base = getattr(QtWidgets, baseclass)
return (ui_globals[uiclass], ui_base)
def loadUi(uifile, baseinstance=None, package='', resource_suffix='_rc'):
"""loadUi(uifile, baseinstance=None, package='') -> widget
Load a Qt Designer .ui file and return an instance of the user interface.
uifile is a file name or file-like object containing the .ui file.
baseinstance is an optional instance of the Qt base class. If specified
then the user interface is created in it. Otherwise a new instance of the
base class is automatically created.
package is the optional package which is used as the base for any relative
imports of custom widgets.
resource_suffix is the suffix appended to the basename of any resource file
specified in the .ui file to create the name of the Python module generated
from the resource file by pyrcc4. The default is '_rc', i.e. if the .ui
file specified a resource file called foo.qrc then the corresponding Python
module is foo_rc.
"""
from .Loader.loader import DynamicUILoader
return DynamicUILoader(package).loadUi(uifile, baseinstance, resource_suffix)
# The list of directories that are searched for widget plugins.
from .objcreator import widgetPluginPath

View File

@@ -0,0 +1,149 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
import sys
import logging
from . import compileUi, loadUi
class Driver(object):
""" This encapsulates access to the pyuic functionality so that it can be
called by code that is Python v2/v3 specific.
"""
LOGGER_NAME = 'PyQt5.uic'
def __init__(self, opts, ui_file):
""" Initialise the object. opts is the parsed options. ui_file is the
name of the .ui file.
"""
if opts.debug:
logger = logging.getLogger(self.LOGGER_NAME)
handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("%(name)s: %(message)s"))
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
self._opts = opts
self._ui_file = ui_file
def invoke(self):
""" Invoke the action as specified by the parsed options. Returns 0 if
there was no error.
"""
if self._opts.preview:
return self._preview()
self._generate()
return 0
def _preview(self):
""" Preview the .ui file. Return the exit status to be passed back to
the parent process.
"""
from PyQt5 import QtWidgets
app = QtWidgets.QApplication([self._ui_file])
widget = loadUi(self._ui_file)
widget.show()
return app.exec_()
def _generate(self):
""" Generate the Python code. """
needs_close = False
if sys.hexversion >= 0x03000000:
if self._opts.output == '-':
from io import TextIOWrapper
pyfile = TextIOWrapper(sys.stdout.buffer, encoding='utf8')
else:
pyfile = open(self._opts.output, 'wt', encoding='utf8')
needs_close = True
else:
if self._opts.output == '-':
pyfile = sys.stdout
else:
pyfile = open(self._opts.output, 'wt')
needs_close = True
import_from = self._opts.import_from
if import_from:
from_imports = True
elif self._opts.from_imports:
from_imports = True
import_from = '.'
else:
from_imports = False
compileUi(self._ui_file, pyfile, self._opts.execute, self._opts.indent,
from_imports, self._opts.resource_suffix, import_from)
if needs_close:
pyfile.close()
def on_IOError(self, e):
""" Handle an IOError exception. """
sys.stderr.write("Error: %s: \"%s\"\n" % (e.strerror, e.filename))
def on_SyntaxError(self, e):
""" Handle a SyntaxError exception. """
sys.stderr.write("Error in input file: %s\n" % e)
def on_NoSuchClassError(self, e):
""" Handle a NoSuchClassError exception. """
sys.stderr.write(str(e) + "\n")
def on_NoSuchWidgetError(self, e):
""" Handle a NoSuchWidgetError exception. """
sys.stderr.write(str(e) + "\n")
def on_Exception(self, e):
""" Handle a generic exception. """
if logging.getLogger(self.LOGGER_NAME).level == logging.DEBUG:
import traceback
traceback.print_exception(*sys.exc_info())
else:
from PyQt5 import QtCore
sys.stderr.write("""An unexpected error occurred.
Check that you are using the latest version of PyQt5 and send an error report to
support@riverbankcomputing.com, including the following information:
* your version of PyQt (%s)
* the UI file that caused this error
* the debug output of pyuic5 (use the -d flag when calling pyuic5)
""" % QtCore.PYQT_VERSION_STR)

View File

@@ -0,0 +1,53 @@
#############################################################################
##
## Copyright (C) 2017 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
class NoSuchClassError(Exception):
def __str__(self):
return "Unknown C++ class: %s" % self.args[0]
class NoSuchWidgetError(Exception):
def __str__(self):
return "Unknown Qt widget: %s" % self.args[0]
class UnsupportedPropertyError(Exception):
pass
class WidgetPluginError(Exception):
pass

View File

@@ -0,0 +1,159 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
import os.path
class IconCache(object):
"""Maintain a cache of icons. If an icon is used more than once by a GUI
then ensure that only one copy is created.
"""
def __init__(self, object_factory, qtgui_module):
"""Initialise the cache."""
self._object_factory = object_factory
self._qtgui_module = qtgui_module
self._base_dir = ''
self._cache = []
def set_base_dir(self, base_dir):
""" Set the base directory to be used for all relative filenames. """
self._base_dir = base_dir
def get_icon(self, iconset):
"""Return an icon described by the given iconset tag."""
# Handle a themed icon.
theme = iconset.attrib.get('theme')
if theme is not None:
return self._object_factory.createQObject("QIcon.fromTheme",
'icon', (self._object_factory.asString(theme), ),
is_attribute=False)
# Handle an empty iconset property.
if iconset.text is None:
return None
iset = _IconSet(iconset, self._base_dir)
try:
idx = self._cache.index(iset)
except ValueError:
idx = -1
if idx >= 0:
# Return the icon from the cache.
iset = self._cache[idx]
else:
# Follow uic's naming convention.
name = 'icon'
idx = len(self._cache)
if idx > 0:
name += str(idx)
icon = self._object_factory.createQObject("QIcon", name, (),
is_attribute=False)
iset.set_icon(icon, self._qtgui_module)
self._cache.append(iset)
return iset.icon
class _IconSet(object):
"""An icon set, ie. the mode and state and the pixmap used for each."""
def __init__(self, iconset, base_dir):
"""Initialise the icon set from an XML tag."""
# Set the pre-Qt v4.4 fallback (ie. with no roles).
self._fallback = self._file_name(iconset.text, base_dir)
self._use_fallback = True
# Parse the icon set.
self._roles = {}
for i in iconset:
file_name = i.text
if file_name is not None:
file_name = self._file_name(file_name, base_dir)
self._roles[i.tag] = file_name
self._use_fallback = False
# There is no real icon yet.
self.icon = None
@staticmethod
def _file_name(fname, base_dir):
""" Convert a relative filename if we have a base directory. """
fname = fname.replace("\\", "\\\\")
if base_dir != '' and fname[0] != ':' and not os.path.isabs(fname):
fname = os.path.join(base_dir, fname)
return fname
def set_icon(self, icon, qtgui_module):
"""Save the icon and set its attributes."""
if self._use_fallback:
icon.addFile(self._fallback)
else:
for role, pixmap in self._roles.items():
if role.endswith("off"):
mode = role[:-3]
state = qtgui_module.QIcon.Off
elif role.endswith("on"):
mode = role[:-2]
state = qtgui_module.QIcon.On
else:
continue
mode = getattr(qtgui_module.QIcon, mode.title())
if pixmap:
icon.addPixmap(qtgui_module.QPixmap(pixmap), mode, state)
else:
icon.addPixmap(qtgui_module.QPixmap(), mode, state)
self.icon = icon
def __eq__(self, other):
"""Compare two icon sets for equality."""
if not isinstance(other, type(self)):
return NotImplemented
if self._use_fallback:
if other._use_fallback:
return self._fallback == other._fallback
return False
if other._use_fallback:
return False
return self._roles == other._roles

View File

@@ -0,0 +1,163 @@
#############################################################################
##
## Copyright (C) 2015 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
import os.path
from .exceptions import NoSuchWidgetError, WidgetPluginError
# The list of directories that are searched for widget plugins. This is
# exposed as part of the API.
widgetPluginPath = [os.path.join(os.path.dirname(__file__), 'widget-plugins')]
MATCH = True
NO_MATCH = False
MODULE = 0
CW_FILTER = 1
class QObjectCreator(object):
def __init__(self, creatorPolicy):
self._cpolicy = creatorPolicy
self._cwFilters = []
self._modules = self._cpolicy.createQtGuiWidgetsWrappers()
# Get the optional plugins.
for plugindir in widgetPluginPath:
try:
plugins = os.listdir(plugindir)
except:
plugins = []
for filename in plugins:
if not filename.endswith('.py'):
continue
filename = os.path.join(plugindir, filename)
plugin_globals = {
"MODULE": MODULE,
"CW_FILTER": CW_FILTER,
"MATCH": MATCH,
"NO_MATCH": NO_MATCH}
plugin_locals = {}
if self.load_plugin(filename, plugin_globals, plugin_locals):
pluginType = plugin_locals["pluginType"]
if pluginType == MODULE:
modinfo = plugin_locals["moduleInformation"]()
self._modules.append(self._cpolicy.createModuleWrapper(*modinfo))
elif pluginType == CW_FILTER:
self._cwFilters.append(plugin_locals["getFilter"]())
else:
raise WidgetPluginError("Unknown plugin type of %s" % filename)
self._customWidgets = self._cpolicy.createCustomWidgetLoader()
self._modules.append(self._customWidgets)
def createQObject(self, classname, *args, **kwargs):
# Handle regular and custom widgets.
factory = self.findQObjectType(classname)
if factory is None:
# Handle scoped names, typically static factory methods.
parts = classname.split('.')
if len(parts) > 1:
factory = self.findQObjectType(parts[0])
if factory is not None:
for part in parts[1:]:
factory = getattr(factory, part, None)
if factory is None:
break
if factory is None:
raise NoSuchWidgetError(classname)
return self._cpolicy.instantiate(factory, *args, **kwargs)
def invoke(self, rname, method, args=()):
return self._cpolicy.invoke(rname, method, args)
def findQObjectType(self, classname):
for module in self._modules:
w = module.search(classname)
if w is not None:
return w
return None
def getSlot(self, obj, slotname):
return self._cpolicy.getSlot(obj, slotname)
def asString(self, s):
return self._cpolicy.asString(s)
def addCustomWidget(self, widgetClass, baseClass, module):
for cwFilter in self._cwFilters:
match, result = cwFilter(widgetClass, baseClass, module)
if match:
widgetClass, baseClass, module = result
break
self._customWidgets.addCustomWidget(widgetClass, baseClass, module)
@staticmethod
def load_plugin(filename, plugin_globals, plugin_locals):
""" Load the plugin from the given file. Return True if the plugin was
loaded, or False if it wanted to be ignored. Raise an exception if
there was an error.
"""
plugin = open(filename)
try:
exec(plugin.read(), plugin_globals, plugin_locals)
except ImportError:
return False
except Exception as e:
raise WidgetPluginError("%s: %s" % (e.__class__, str(e)))
finally:
plugin.close()
return True

View File

@@ -0,0 +1,20 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################

View File

@@ -0,0 +1,40 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
import re
def as_string(obj):
if isinstance(obj, basestring):
return '"' + _escape(obj.encode('UTF-8')) + '"'
return str(obj)
_esc_regex = re.compile(r"(\"|\'|\\)")
def _escape(text):
# This escapes any escaped single or double quote or backslash.
x = _esc_regex.sub(r"\\\1", text)
# This replaces any '\n' with an escaped version and a real line break.
return re.sub(r'\n', r'\\n"\n"', x)

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
import string
# A translation table for converting ASCII lower case to upper case.
_ascii_trans_table = string.maketrans(string.ascii_lowercase,
string.ascii_uppercase)
# Convert a string to ASCII upper case irrespective of the current locale.
def ascii_upper(s):
return s.translate(_ascii_trans_table)

View File

@@ -0,0 +1,31 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
from ..Compiler.proxy_metaclass import ProxyMetaclass
class ProxyBase(object):
""" A base class for proxies using Python v2 syntax for setting the
meta-class.
"""
__metaclass__ = ProxyMetaclass

View File

@@ -0,0 +1,27 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# Import the StringIO object.
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO

View File

@@ -0,0 +1,20 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################

View File

@@ -0,0 +1,40 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
import re
def as_string(obj):
if isinstance(obj, str):
return '"' + _escape(obj) + '"'
return str(obj)
_esc_regex = re.compile(r"(\"|\'|\\)")
def _escape(text):
# This escapes any escaped single or double quote or backslash.
x = _esc_regex.sub(r"\\\1", text)
# This replaces any '\n' with an escaped version and a real line break.
return re.sub(r'\n', r'\\n"\n"', x)

View File

@@ -0,0 +1,30 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# A translation table for converting ASCII lower case to upper case.
_ascii_trans_table = bytes.maketrans(b'abcdefghijklmnopqrstuvwxyz',
b'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
# Convert a string to ASCII upper case irrespective of the current locale.
def ascii_upper(s):
return s.translate(_ascii_trans_table)

View File

@@ -0,0 +1,29 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
from ..Compiler.proxy_metaclass import ProxyMetaclass
class ProxyBase(metaclass=ProxyMetaclass):
""" A base class for proxies using Python v3 syntax for setting the
meta-class.
"""

View File

@@ -0,0 +1,24 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# Import the StringIO object.
from io import StringIO

View File

@@ -0,0 +1,523 @@
#############################################################################
##
## Copyright (C) 2019 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
import logging
import os.path
import sys
from .exceptions import NoSuchClassError, UnsupportedPropertyError
from .icon_cache import IconCache
if sys.hexversion >= 0x03000000:
from .port_v3.ascii_upper import ascii_upper
else:
from .port_v2.ascii_upper import ascii_upper
logger = logging.getLogger(__name__)
DEBUG = logger.debug
QtCore = None
QtGui = None
QtWidgets = None
def int_list(prop):
return [int(child.text) for child in prop]
def float_list(prop):
return [float(child.text) for child in prop]
bool_ = lambda v: v == "true"
def qfont_enum(v):
return getattr(QtGui.QFont, v)
def needsWidget(func):
func.needsWidget = True
return func
class Properties(object):
def __init__(self, factory, qtcore_module, qtgui_module, qtwidgets_module):
self.factory = factory
global QtCore, QtGui, QtWidgets
QtCore = qtcore_module
QtGui = qtgui_module
QtWidgets = qtwidgets_module
self._base_dir = ''
self.reset()
def set_base_dir(self, base_dir):
""" Set the base directory to be used for all relative filenames. """
self._base_dir = base_dir
self.icon_cache.set_base_dir(base_dir)
def reset(self):
self.buddies = []
self.delayed_props = []
self.icon_cache = IconCache(self.factory, QtGui)
def _pyEnumMember(self, cpp_name):
try:
prefix, membername = cpp_name.split("::")
except ValueError:
prefix = 'Qt'
membername = cpp_name
if prefix == 'Qt':
return getattr(QtCore.Qt, membername)
scope = self.factory.findQObjectType(prefix)
if scope is None:
raise NoSuchClassError(prefix)
return getattr(scope, membername)
def _set(self, prop):
expr = [self._pyEnumMember(v) for v in prop.text.split('|')]
value = expr[0]
for v in expr[1:]:
value |= v
return value
def _enum(self, prop):
return self._pyEnumMember(prop.text)
def _number(self, prop):
return int(prop.text)
_UInt = _uInt = _longLong = _uLongLong = _number
def _double(self, prop):
return float(prop.text)
def _bool(self, prop):
return prop.text == 'true'
def _stringlist(self, prop):
return [self._string(p, notr='true') for p in prop]
def _string(self, prop, notr=None):
text = prop.text
if text is None:
return ""
if prop.get('notr', notr) == 'true':
return text
disambig = prop.get('comment')
return QtWidgets.QApplication.translate(self.uiname, text, disambig)
_char = _string
def _cstring(self, prop):
return str(prop.text)
def _color(self, prop):
args = int_list(prop)
# Handle the optional alpha component.
alpha = int(prop.get("alpha", "255"))
if alpha != 255:
args.append(alpha)
return QtGui.QColor(*args)
def _point(self, prop):
return QtCore.QPoint(*int_list(prop))
def _pointf(self, prop):
return QtCore.QPointF(*float_list(prop))
def _rect(self, prop):
return QtCore.QRect(*int_list(prop))
def _rectf(self, prop):
return QtCore.QRectF(*float_list(prop))
def _size(self, prop):
return QtCore.QSize(*int_list(prop))
def _sizef(self, prop):
return QtCore.QSizeF(*float_list(prop))
def _pixmap(self, prop):
if prop.text:
fname = prop.text.replace("\\", "\\\\")
if self._base_dir != '' and fname[0] != ':' and not os.path.isabs(fname):
fname = os.path.join(self._base_dir, fname)
return QtGui.QPixmap(fname)
# Don't bother to set the property if the pixmap is empty.
return None
def _iconset(self, prop):
return self.icon_cache.get_icon(prop)
def _url(self, prop):
return QtCore.QUrl(prop[0].text)
def _locale(self, prop):
lang = getattr(QtCore.QLocale, prop.attrib['language'])
country = getattr(QtCore.QLocale, prop.attrib['country'])
return QtCore.QLocale(lang, country)
def _date(self, prop):
return QtCore.QDate(*int_list(prop))
def _datetime(self, prop):
args = int_list(prop)
return QtCore.QDateTime(QtCore.QDate(*args[-3:]), QtCore.QTime(*args[:-3]))
def _time(self, prop):
return QtCore.QTime(*int_list(prop))
def _gradient(self, prop):
name = 'gradient'
# Create the specific gradient.
gtype = prop.get('type', '')
if gtype == 'LinearGradient':
startx = float(prop.get('startx'))
starty = float(prop.get('starty'))
endx = float(prop.get('endx'))
endy = float(prop.get('endy'))
gradient = self.factory.createQObject('QLinearGradient', name,
(startx, starty, endx, endy), is_attribute=False)
elif gtype == 'ConicalGradient':
centralx = float(prop.get('centralx'))
centraly = float(prop.get('centraly'))
angle = float(prop.get('angle'))
gradient = self.factory.createQObject('QConicalGradient', name,
(centralx, centraly, angle), is_attribute=False)
elif gtype == 'RadialGradient':
centralx = float(prop.get('centralx'))
centraly = float(prop.get('centraly'))
radius = float(prop.get('radius'))
focalx = float(prop.get('focalx'))
focaly = float(prop.get('focaly'))
gradient = self.factory.createQObject('QRadialGradient', name,
(centralx, centraly, radius, focalx, focaly),
is_attribute=False)
else:
raise UnsupportedPropertyError(prop.tag)
# Set the common values.
spread = prop.get('spread')
if spread:
gradient.setSpread(getattr(QtGui.QGradient, spread))
cmode = prop.get('coordinatemode')
if cmode:
gradient.setCoordinateMode(getattr(QtGui.QGradient, cmode))
# Get the gradient stops.
for gstop in prop:
if gstop.tag != 'gradientstop':
raise UnsupportedPropertyError(gstop.tag)
position = float(gstop.get('position'))
color = self._color(gstop[0])
gradient.setColorAt(position, color)
return gradient
def _palette(self, prop):
palette = self.factory.createQObject("QPalette", "palette", (),
is_attribute=False)
for palette_elem in prop:
sub_palette = getattr(QtGui.QPalette, palette_elem.tag.title())
for role, color in enumerate(palette_elem):
if color.tag == 'color':
# Handle simple colour descriptions where the role is
# implied by the colour's position.
palette.setColor(sub_palette,
QtGui.QPalette.ColorRole(role), self._color(color))
elif color.tag == 'colorrole':
role = getattr(QtGui.QPalette, color.get('role'))
brush = self._brush(color[0])
palette.setBrush(sub_palette, role, brush)
else:
raise UnsupportedPropertyError(color.tag)
return palette
def _brush(self, prop):
brushstyle = prop.get('brushstyle')
if brushstyle in ('LinearGradientPattern', 'ConicalGradientPattern', 'RadialGradientPattern'):
gradient = self._gradient(prop[0])
brush = self.factory.createQObject("QBrush", "brush", (gradient, ),
is_attribute=False)
else:
color = self._color(prop[0])
brush = self.factory.createQObject("QBrush", "brush", (color, ),
is_attribute=False)
brushstyle = getattr(QtCore.Qt, brushstyle)
brush.setStyle(brushstyle)
return brush
#@needsWidget
def _sizepolicy(self, prop, widget):
values = [int(child.text) for child in prop]
if len(values) == 2:
# Qt v4.3.0 and later.
horstretch, verstretch = values
hsizetype = getattr(QtWidgets.QSizePolicy, prop.get('hsizetype'))
vsizetype = getattr(QtWidgets.QSizePolicy, prop.get('vsizetype'))
else:
hsizetype, vsizetype, horstretch, verstretch = values
hsizetype = QtWidgets.QSizePolicy.Policy(hsizetype)
vsizetype = QtWidgets.QSizePolicy.Policy(vsizetype)
sizePolicy = self.factory.createQObject('QSizePolicy', 'sizePolicy',
(hsizetype, vsizetype), is_attribute=False)
sizePolicy.setHorizontalStretch(horstretch)
sizePolicy.setVerticalStretch(verstretch)
sizePolicy.setHeightForWidth(widget.sizePolicy().hasHeightForWidth())
return sizePolicy
_sizepolicy = needsWidget(_sizepolicy)
# font needs special handling/conversion of all child elements.
_font_attributes = (("Family", lambda s: s),
("PointSize", int),
("Bold", bool_),
("Italic", bool_),
("Underline", bool_),
("Weight", int),
("StrikeOut", bool_),
("Kerning", bool_),
("StyleStrategy", qfont_enum))
def _font(self, prop):
newfont = self.factory.createQObject("QFont", "font", (),
is_attribute = False)
for attr, converter in self._font_attributes:
v = prop.findtext("./%s" % (attr.lower(),))
if v is None:
continue
getattr(newfont, "set%s" % (attr,))(converter(v))
return newfont
def _cursor(self, prop):
return QtGui.QCursor(QtCore.Qt.CursorShape(int(prop.text)))
def _cursorShape(self, prop):
return QtGui.QCursor(getattr(QtCore.Qt, prop.text))
def convert(self, prop, widget=None):
try:
func = getattr(self, "_" + prop[0].tag)
except AttributeError:
raise UnsupportedPropertyError(prop[0].tag)
else:
args = {}
if getattr(func, "needsWidget", False):
assert widget is not None
args["widget"] = widget
return func(prop[0], **args)
def _getChild(self, elem_tag, elem, name, default=None):
for prop in elem.findall(elem_tag):
if prop.attrib["name"] == name:
return self.convert(prop)
else:
return default
def getProperty(self, elem, name, default=None):
return self._getChild("property", elem, name, default)
def getAttribute(self, elem, name, default=None):
return self._getChild("attribute", elem, name, default)
def setProperties(self, widget, elem):
# Lines are sunken unless the frame shadow is explicitly set.
set_sunken = (elem.attrib.get('class') == 'Line')
for prop in elem.findall('property'):
prop_name = prop.attrib['name']
DEBUG("setting property %s" % (prop_name,))
if prop_name == 'frameShadow':
set_sunken = False
try:
stdset = bool(int(prop.attrib['stdset']))
except KeyError:
stdset = True
if not stdset:
self._setViaSetProperty(widget, prop)
elif hasattr(self, prop_name):
getattr(self, prop_name)(widget, prop)
else:
prop_value = self.convert(prop, widget)
if prop_value is not None:
getattr(widget, 'set%s%s' % (ascii_upper(prop_name[0]), prop_name[1:]))(prop_value)
if set_sunken:
widget.setFrameShadow(QtWidgets.QFrame.Sunken)
# SPECIAL PROPERTIES
# If a property has a well-known value type but needs special,
# context-dependent handling, the default behaviour can be overridden here.
# Delayed properties will be set after the whole widget tree has been
# populated.
def _delayed_property(self, widget, prop):
prop_value = self.convert(prop)
if prop_value is not None:
prop_name = prop.attrib["name"]
self.delayed_props.append((widget, False,
'set%s%s' % (ascii_upper(prop_name[0]), prop_name[1:]),
prop_value))
# These properties will be set with a widget.setProperty call rather than
# calling the set<property> function.
def _setViaSetProperty(self, widget, prop):
prop_value = self.convert(prop, widget)
if prop_value is not None:
prop_name = prop.attrib['name']
# This appears to be a Designer/uic hack where stdset=0 means that
# the viewport should be used.
if prop[0].tag == 'cursorShape':
widget.viewport().setProperty(prop_name, prop_value)
else:
widget.setProperty(prop_name, prop_value)
# Ignore the property.
def _ignore(self, widget, prop):
pass
# Define properties that use the canned handlers.
currentIndex = _delayed_property
currentRow = _delayed_property
showDropIndicator = _setViaSetProperty
intValue = _setViaSetProperty
value = _setViaSetProperty
objectName = _ignore
margin = _ignore
leftMargin = _ignore
topMargin = _ignore
rightMargin = _ignore
bottomMargin = _ignore
spacing = _ignore
horizontalSpacing = _ignore
verticalSpacing = _ignore
# tabSpacing is actually the spacing property of the widget's layout.
def tabSpacing(self, widget, prop):
prop_value = self.convert(prop)
if prop_value is not None:
self.delayed_props.append((widget, True, 'setSpacing', prop_value))
# buddy setting has to be done after the whole widget tree has been
# populated. We can't use delay here because we cannot get the actual
# buddy yet.
def buddy(self, widget, prop):
buddy_name = prop[0].text
if buddy_name:
self.buddies.append((widget, buddy_name))
# geometry is handled specially if set on the toplevel widget.
def geometry(self, widget, prop):
if widget.objectName() == self.uiname:
geom = int_list(prop[0])
widget.resize(geom[2], geom[3])
else:
widget.setGeometry(self._rect(prop[0]))
def orientation(self, widget, prop):
# If the class is a QFrame, it's a line.
if widget.metaObject().className() == 'QFrame':
widget.setFrameShape(
{'Qt::Horizontal': QtWidgets.QFrame.HLine,
'Qt::Vertical' : QtWidgets.QFrame.VLine}[prop[0].text])
else:
widget.setOrientation(self._enum(prop[0]))
# The isWrapping attribute of QListView is named inconsistently, it should
# be wrapping.
def isWrapping(self, widget, prop):
widget.setWrapping(self.convert(prop))
# This is a pseudo-property injected to deal with margins.
def pyuicMargins(self, widget, prop):
widget.setContentsMargins(*int_list(prop))
# This is a pseudo-property injected to deal with spacing.
def pyuicSpacing(self, widget, prop):
horiz, vert = int_list(prop)
if horiz == vert:
widget.setSpacing(horiz)
else:
if horiz >= 0:
widget.setHorizontalSpacing(horiz)
if vert >= 0:
widget.setVerticalSpacing(vert)

View File

@@ -0,0 +1,96 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
import sys
import optparse
from PyQt5 import QtCore
from .driver import Driver
from .exceptions import NoSuchClassError, NoSuchWidgetError
Version = "Python User Interface Compiler %s for Qt version %s" % (QtCore.PYQT_VERSION_STR, QtCore.QT_VERSION_STR)
def main():
parser = optparse.OptionParser(usage="pyuic5 [options] <ui-file>",
version=Version)
parser.add_option("-p", "--preview", dest="preview", action="store_true",
default=False,
help="show a preview of the UI instead of generating code")
parser.add_option("-o", "--output", dest="output", default="-",
metavar="FILE",
help="write generated code to FILE instead of stdout")
parser.add_option("-x", "--execute", dest="execute", action="store_true",
default=False,
help="generate extra code to test and display the class")
parser.add_option("-d", "--debug", dest="debug", action="store_true",
default=False, help="show debug output")
parser.add_option("-i", "--indent", dest="indent", action="store",
type="int", default=4, metavar="N",
help="set indent width to N spaces, tab if N is 0 [default: 4]")
g = optparse.OptionGroup(parser, title="Code generation options")
g.add_option("--import-from", dest="import_from", metavar="PACKAGE",
help="generate imports of pyrcc5 generated modules in the style 'from PACKAGE import ...'")
g.add_option("--from-imports", dest="from_imports", action="store_true",
default=False, help="the equivalent of '--import-from=.'")
g.add_option("--resource-suffix", dest="resource_suffix", action="store",
type="string", default="_rc", metavar="SUFFIX",
help="append SUFFIX to the basename of resource files [default: _rc]")
parser.add_option_group(g)
opts, args = parser.parse_args()
if len(args) != 1:
sys.stderr.write("Error: one input ui-file must be specified\n")
sys.exit(1)
# Invoke the appropriate driver.
driver = Driver(opts, args[0])
exit_status = 1
try:
exit_status = driver.invoke()
except IOError as e:
driver.on_IOError(e)
except SyntaxError as e:
driver.on_SyntaxError(e)
except NoSuchClassError as e:
driver.on_NoSuchClassError(e)
except NoSuchWidgetError as e:
driver.on_NoSuchWidgetError(e)
except Exception as e:
driver.on_Exception(e)
sys.exit(exit_status)
if __name__ == '__main__':
main()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return "PyQt5.QAxContainer", ("QAxWidget", )

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return "PyQt5.Qsci", ("QsciScintilla", )

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return 'PyQt5.QtChart', ('QtCharts.QChartView', )

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return 'PyQt5.QtPrintSupport', ('QAbstractPrintDialog', 'QPageSetupDialog')

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return "PyQt5.QtQuickWidgets", ("QQuickWidget", )

View File

@@ -0,0 +1,33 @@
#############################################################################
##
## Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
##
## This file is part of PyQt5.
##
## This file may be used under the terms of the GNU General Public License
## version 3.0 as published by the Free Software Foundation and appearing in
## the file LICENSE included in the packaging of this file. Please review the
## following information to ensure the GNU General Public License version 3.0
## requirements will be met: http://www.gnu.org/copyleft/gpl.html.
##
## If you do not wish to use this file under the terms of the GPL version 3.0
## then you may purchase a commercial license. For more information contact
## info@riverbankcomputing.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return "PyQt5.QtWebEngineWidgets", ("QWebEngineView", )

View File

@@ -0,0 +1,51 @@
#############################################################################
##
## Copyright (C) 2014 Riverbank Computing Limited.
## Copyright (C) 2006 Thorsten Marek.
## All right reserved.
##
## This file is part of PyQt.
##
## You may use this file under the terms of the GPL v2 or the revised BSD
## license as follows:
##
## "Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:
## * Redistributions of source code must retain the above copyright
## notice, this list of conditions and the following disclaimer.
## * Redistributions in binary form must reproduce the above copyright
## notice, this list of conditions and the following disclaimer in
## the documentation and/or other materials provided with the
## distribution.
## * Neither the name of the Riverbank Computing Limited nor the names
## of its contributors may be used to endorse or promote products
## derived from this software without specific prior written
## permission.
##
## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
##
#############################################################################
# If pluginType is MODULE, the plugin loader will call moduleInformation. The
# variable MODULE is inserted into the local namespace by the plugin loader.
pluginType = MODULE
# moduleInformation() must return a tuple (module, widget_list). If "module"
# is "A" and any widget from this module is used, the code generator will write
# "import A". If "module" is "A[.B].C", the code generator will write
# "from A[.B] import C". Each entry in "widget_list" must be unique.
def moduleInformation():
return "PyQt5.QtWebKitWidgets", ("QWebView", )