1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Copyright © 2016-2017 B. Clausius <barcc@gmx.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
try:
from PyQt5.QtCore import (pyqtProperty, pyqtSignal, pyqtSlot, Qt, QObject, QVariant, QUrl, QStandardPaths,
QElapsedTimer, QFileSystemWatcher, QTimer, QByteArray,
QLocale, QTranslator, QLibraryInfo, QMetaObject, QPointF)
from PyQt5.QtGui import (QColor, QImage, QIcon, QKeySequence, QTextDocumentFragment, QSurfaceFormat,
QOpenGLTexture, QOpenGLFramebufferObject, QTransform, QPixmap, QCursor,
QOpenGLContext, QOpenGLDebugLogger, QIconEngine)
from PyQt5.QtQml import QQmlEngine, QQmlComponent
from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QLabel, QOpenGLWidget, QDialog, QStyledItemDelegate
from PyQt5.QtQuick import QQuickView, QQuickItem
except ImportError as e:
print('Need PyQt5 in pure python mode:', e)
raise SystemExit(1)
import OpenGL.GL as gl
NULL = None
Format_RGBA8888 = QImage.Format_RGBA8888
PortableText = QKeySequence.PortableText
MoveToNextWord = QKeySequence.MoveToNextWord
MoveToPreviousWord = QKeySequence.MoveToPreviousWord
fromString = QKeySequence.fromString
standardLocations = QStandardPaths.standardLocations
PicturesLocation = QStandardPaths.PicturesLocation
HomeLocation = QStandardPaths.HomeLocation
fromPlainText = QTextDocumentFragment.fromPlainText
setDefaultFormat = QSurfaceFormat.setDefaultFormat
defaultFormat = QSurfaceFormat.defaultFormat
Target2D = QOpenGLTexture.Target2D
RGBA32F = QOpenGLTexture.RGBA32F
Linear = QOpenGLTexture.Linear
Depth = QOpenGLFramebufferObject.Depth
fromLocalFile = QUrl.fromLocalFile
Asynchronous = QQmlComponent.Asynchronous
fromImage = QPixmap.fromImage
location = QLibraryInfo.location
TranslationsPath = QLibraryInfo.TranslationsPath
QLocale_system = QLocale.system
arguments = QApplication.arguments
setAttribute = QApplication.setAttribute
OpenGLES = QSurfaceFormat.OpenGLES
DebugContext = QSurfaceFormat.DebugContext
openGLModuleType = QOpenGLContext.openGLModuleType
LibGL = QOpenGLContext.LibGL
LibGLES = QOpenGLContext.LibGLES
currentContext = QOpenGLContext.currentContext
SynchronousLogging = QOpenGLDebugLogger.SynchronousLogging
invokeMethod = QMetaObject.invokeMethod
SizeRootObjectToView = QQuickView.SizeRootObjectToView
GL_TEXTURE_2D = gl.GL_TEXTURE_2D
class MetaSlot(type(QObject)):
def __new__(cls, name, bases, namespace):
import inspect
qtypemap = {'QString': str, 'QList<QObject*>': QVariant, 'QVariantList': QVariant}
def member(proptype, propname, notify):
def getter(self):
try:
returnv = getattr(self, propname)
except AttributeError:
returnv = proptype()
return returnv
def setter(self, v):
setattr(self, propname, v)
notify and notify.__get__(self).emit()
return getter, setter
for k, v in sorted(namespace.items()):
if k.startswith('slot_'):
spec = inspect.getfullargspec(v)
argtypes = [spec.annotations[a] for a in spec.args[1:]]
rtype = spec.annotations.get('return')
fname = k.split('_', 1)[1]
if rtype is None:
slot = pyqtSlot(*argtypes, name=fname)
else:
slot = pyqtSlot(*argtypes, name=fname, result=rtype)
assert fname not in namespace
namespace[fname] = slot(v)
del namespace[k]
elif k.startswith('action_'):
action = k.split('_', 1)[1]
fname = 'on_action_%s_triggered' % action
slot = pyqtSlot(name=fname)
assert fname not in namespace
def _mkactionfunc(action, pydata):
def on_action_X_triggered(self):
getattr(pydata.app, 'on_action_%s_triggered' % action)()
return on_action_X_triggered
namespace[fname] = slot(_mkactionfunc(action, v))
del namespace[k]
elif k.startswith('prop_'):
pname = k.split('_', 1)[1]
ptype, *flags = v.split()
try:
ptype = qtypemap.get(ptype) or eval(ptype.rstrip('*'))
except NameError:
print('{}: name={}, type={!r}, flags={!r}'.format(k, pname, ptype, flags))
raise
assert type(ptype) is not str or ptype.isalpha(), ptype
pargs = {}
getter = setter = notify = None
def pop(flag):
if flag in flags:
flags.remove(flag)
return True
return False
if pop('NOTIFY'):
fname = pname + '_changed'
assert fname not in namespace, fname
notify = pyqtSignal()
pargs['notify'] = notify
namespace[fname] = notify
if pop('MEMBER'):
fname = 'm_' + pname
assert fname not in namespace, fname
getter, setter = member(ptype, fname, notify)
pargs['fget'], pargs['fset'] = getter, setter
if pop('READ'):
fname = 'get_' + pname
assert fname in namespace, fname
getter = namespace[fname]
pargs['fget'] = getter
if pop('WRITE'):
fname = 'set_' + pname
assert fname in namespace, fname
setter = namespace[fname]
pargs['fset'] = setter
if flags:
assert False, flags
assert pname not in namespace, pname
namespace[pname] = pyqtProperty(ptype, **pargs)
del namespace[k]
return type(QObject)(name, bases, namespace)
|