diff --git a/.gitignore b/.gitignore index 84d259d..37f2190 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ *.pro.user -/ build +/build *.o *.dylib *.app @@ -10,3 +10,9 @@ Makefile # IDEs .idea + +# Python +.eggs +*.pyc +*.pyd +__pycache__ \ No newline at end of file diff --git a/PyQtAds/QtAds/__init__.py b/PyQtAds/QtAds/__init__.py new file mode 100644 index 0000000..59b7929 --- /dev/null +++ b/PyQtAds/QtAds/__init__.py @@ -0,0 +1,10 @@ +from .ads import ads +from ._version import * + +import inspect + +for name, member in inspect.getmembers(ads): + if not name.startswith('_'): + globals()[name] = member + +del ads \ No newline at end of file diff --git a/PyQtAds/__init__.py b/PyQtAds/__init__.py new file mode 100644 index 0000000..7a2d551 --- /dev/null +++ b/PyQtAds/__init__.py @@ -0,0 +1 @@ +from .rc import * \ No newline at end of file diff --git a/PyQtAds/_version.py b/PyQtAds/_version.py new file mode 100644 index 0000000..07cc7ab --- /dev/null +++ b/PyQtAds/_version.py @@ -0,0 +1,9 @@ +# THIS FILE IS GENERATED FROM PyQtAds SETUP.PY + +short_version = '2.5.1' +version = '2.5.1' +full_version = '2.5.1' +git_revision = 'c10ff7c688fb50fe9157bad3982164e0f955f9e4' +release = True +if not release: + version = full_version diff --git a/PyQtAds/rc.py b/PyQtAds/rc.py new file mode 100644 index 0000000..7b7f9a1 --- /dev/null +++ b/PyQtAds/rc.py @@ -0,0 +1,670 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created by: The Resource Compiler for PyQt5 (Qt v5.9.7) +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore + +qt_resource_data = b"\ +\x00\x00\x0b\x04\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ +\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ +\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x30\x2e\x30\x2c\ +\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ +\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ +\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ +\x20\x20\x2d\x2d\x3e\x0d\x0a\x0d\x0a\x3c\x73\x76\x67\x0d\x0a\x20\ +\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\ +\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x0d\x0a\x20\ +\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\ +\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\x22\x0d\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ +\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ +\x61\x78\x2d\x6e\x73\x23\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x6e\ +\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ +\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\ +\x67\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\ +\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0d\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\ +\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\ +\x6d\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x22\x0d\x0a\x20\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\ +\x31\x2e\x31\x22\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x43\x61\x70\ +\x61\x5f\x31\x22\x0d\x0a\x20\x20\x20\x78\x3d\x22\x30\x70\x78\x22\ +\x0d\x0a\x20\x20\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x20\x20\ +\x20\x77\x69\x64\x74\x68\x3d\x22\x35\x31\x32\x22\x0d\x0a\x20\x20\ +\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x35\x31\x32\x22\x0d\x0a\x20\ +\x20\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x35\ +\x31\x32\x20\x35\x31\x32\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x3a\ +\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\ +\x0d\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\ +\x63\x6e\x61\x6d\x65\x3d\x22\x63\x6c\x6f\x73\x65\x2d\x62\x75\x74\ +\x74\x6f\x6e\x2e\x73\x76\x67\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\ +\x2e\x39\x32\x2e\x33\x20\x28\x32\x34\x30\x35\x35\x34\x36\x2c\x20\ +\x32\x30\x31\x38\x2d\x30\x33\x2d\x31\x31\x29\x22\x3e\x3c\x6d\x65\ +\x74\x61\x64\x61\x74\x61\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x6d\ +\x65\x74\x61\x64\x61\x74\x61\x38\x39\x37\x22\x3e\x3c\x72\x64\x66\ +\x3a\x52\x44\x46\x3e\x3c\x63\x63\x3a\x57\x6f\x72\x6b\x0d\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\ +\x22\x22\x3e\x3c\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\ +\x61\x67\x65\x2f\x73\x76\x67\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\ +\x66\x6f\x72\x6d\x61\x74\x3e\x3c\x64\x63\x3a\x74\x79\x70\x65\x0d\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x72\x64\x66\x3a\x72\x65\ +\x73\x6f\x75\x72\x63\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\ +\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\ +\x79\x70\x65\x2f\x53\x74\x69\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\ +\x2f\x3e\x3c\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\ +\x3a\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\ +\x3e\x3c\x2f\x72\x64\x66\x3a\x52\x44\x46\x3e\x3c\x2f\x6d\x65\x74\ +\x61\x64\x61\x74\x61\x3e\x3c\x64\x65\x66\x73\x0d\x0a\x20\x20\x20\ +\x69\x64\x3d\x22\x64\x65\x66\x73\x38\x39\x35\x22\x20\x2f\x3e\x3c\ +\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\ +\x65\x77\x0d\x0a\x20\x20\x20\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\ +\x3d\x22\x23\x66\x66\x66\x66\x66\x66\x22\x0d\x0a\x20\x20\x20\x62\ +\x6f\x72\x64\x65\x72\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\ +\x36\x36\x36\x22\x0d\x0a\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\ +\x70\x61\x63\x69\x74\x79\x3d\x22\x31\x22\x0d\x0a\x20\x20\x20\x6f\ +\x62\x6a\x65\x63\x74\x74\x6f\x6c\x65\x72\x61\x6e\x63\x65\x3d\x22\ +\x31\x30\x22\x0d\x0a\x20\x20\x20\x67\x72\x69\x64\x74\x6f\x6c\x65\ +\x72\x61\x6e\x63\x65\x3d\x22\x31\x30\x22\x0d\x0a\x20\x20\x20\x67\ +\x75\x69\x64\x65\x74\x6f\x6c\x65\x72\x61\x6e\x63\x65\x3d\x22\x31\ +\x30\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x70\x61\x67\x65\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x22\x0d\ +\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\ +\x65\x73\x68\x61\x64\x6f\x77\x3d\x22\x32\x22\x0d\x0a\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\ +\x77\x69\x64\x74\x68\x3d\x22\x31\x39\x32\x30\x22\x0d\x0a\x20\x20\ +\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\ +\x2d\x68\x65\x69\x67\x68\x74\x3d\x22\x31\x30\x31\x37\x22\x0d\x0a\ +\x20\x20\x20\x69\x64\x3d\x22\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\ +\x38\x39\x33\x22\x0d\x0a\x20\x20\x20\x73\x68\x6f\x77\x67\x72\x69\ +\x64\x3d\x22\x66\x61\x6c\x73\x65\x22\x0d\x0a\x20\x20\x20\x66\x69\ +\x74\x2d\x6d\x61\x72\x67\x69\x6e\x2d\x74\x6f\x70\x3d\x22\x30\x22\ +\x0d\x0a\x20\x20\x20\x66\x69\x74\x2d\x6d\x61\x72\x67\x69\x6e\x2d\ +\x6c\x65\x66\x74\x3d\x22\x30\x22\x0d\x0a\x20\x20\x20\x66\x69\x74\ +\x2d\x6d\x61\x72\x67\x69\x6e\x2d\x72\x69\x67\x68\x74\x3d\x22\x30\ +\x22\x0d\x0a\x20\x20\x20\x66\x69\x74\x2d\x6d\x61\x72\x67\x69\x6e\ +\x2d\x62\x6f\x74\x74\x6f\x6d\x3d\x22\x30\x22\x0d\x0a\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x30\ +\x2e\x38\x35\x38\x36\x32\x39\x36\x36\x22\x0d\x0a\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x78\x3d\x22\x33\x34\x35\x2e\ +\x32\x39\x31\x34\x32\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x63\x79\x3d\x22\x33\x32\x2e\x37\x33\x31\x32\x35\ +\x38\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\ +\x77\x69\x6e\x64\x6f\x77\x2d\x78\x3d\x22\x2d\x38\x22\x0d\x0a\x20\ +\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\ +\x77\x2d\x79\x3d\x22\x2d\x38\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\ +\x69\x6d\x69\x7a\x65\x64\x3d\x22\x31\x22\x0d\x0a\x20\x20\x20\x69\ +\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\ +\x6c\x61\x79\x65\x72\x3d\x22\x43\x61\x70\x61\x5f\x31\x22\x20\x2f\ +\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\ +\x36\x30\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\ +\x6d\x3d\x22\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x37\x31\x37\x30\ +\x38\x36\x38\x33\x2c\x30\x2c\x30\x2c\x30\x2e\x37\x31\x37\x30\x38\ +\x36\x38\x33\x2c\x31\x32\x38\x2c\x31\x32\x38\x29\x22\x3e\x0d\x0a\ +\x09\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x63\x6c\x6f\x73\ +\x65\x22\x3e\x0d\x0a\x09\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x0d\ +\x0a\x20\x20\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x33\x35\x37\x2c\ +\x33\x32\x31\x2e\x33\x20\x32\x31\x34\x2e\x32\x2c\x31\x37\x38\x2e\ +\x35\x20\x33\x35\x37\x2c\x33\x35\x2e\x37\x20\x33\x32\x31\x2e\x33\ +\x2c\x30\x20\x31\x37\x38\x2e\x35\x2c\x31\x34\x32\x2e\x38\x20\x33\ +\x35\x2e\x37\x2c\x30\x20\x30\x2c\x33\x35\x2e\x37\x20\x31\x34\x32\ +\x2e\x38\x2c\x31\x37\x38\x2e\x35\x20\x30\x2c\x33\x32\x31\x2e\x33\ +\x20\x33\x35\x2e\x37\x2c\x33\x35\x37\x20\x31\x37\x38\x2e\x35\x2c\ +\x32\x31\x34\x2e\x32\x20\x33\x32\x31\x2e\x33\x2c\x33\x35\x37\x20\ +\x22\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x70\x6f\x6c\x79\x67\x6f\ +\x6e\x38\x35\x37\x22\x20\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\ +\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\ +\x3d\x22\x67\x38\x36\x32\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\ +\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\ +\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\ +\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x36\x34\ +\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\ +\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\ +\x20\x20\x69\x64\x3d\x22\x67\x38\x36\x36\x22\x0d\x0a\x20\x20\x20\ +\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\ +\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\ +\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\ +\x67\x38\x36\x38\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\ +\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\ +\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\ +\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x37\x30\x22\x0d\ +\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\ +\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\ +\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\ +\x69\x64\x3d\x22\x67\x38\x37\x32\x22\x0d\x0a\x20\x20\x20\x74\x72\ +\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\ +\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\ +\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\ +\x37\x34\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\ +\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\ +\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\ +\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x37\x36\x22\x0d\x0a\x20\ +\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\ +\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\ +\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\ +\x3d\x22\x67\x38\x37\x38\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\ +\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\ +\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\ +\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x38\x30\ +\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ +\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\ +\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\ +\x20\x20\x69\x64\x3d\x22\x67\x38\x38\x32\x22\x0d\x0a\x20\x20\x20\ +\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\ +\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\ +\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\ +\x67\x38\x38\x34\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\ +\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\ +\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\ +\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x38\x36\x22\x0d\ +\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\ +\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\ +\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\ +\x69\x64\x3d\x22\x67\x38\x38\x38\x22\x0d\x0a\x20\x20\x20\x74\x72\ +\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\ +\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\ +\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\ +\x39\x30\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\ +\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\ +\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\ +\x76\x67\x3e\ +\x00\x00\x0b\xf7\ +\x3c\ +\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ +\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x55\x54\x46\ +\x2d\x38\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\ +\x6e\x6f\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ +\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ +\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x30\x2e\x30\x2c\ +\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ +\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ +\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ +\x20\x20\x2d\x2d\x3e\x0d\x0a\x0d\x0a\x3c\x73\x76\x67\x0d\x0a\x20\ +\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\ +\x6c\x65\x6d\x65\x6e\x74\x73\x2f\x31\x2e\x31\x2f\x22\x0d\x0a\x20\ +\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\x22\x68\x74\x74\x70\ +\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\ +\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\x22\x0d\x0a\x20\x20\x20\ +\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\x68\x74\x74\x70\x3a\ +\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ +\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\x2d\x73\x79\x6e\x74\ +\x61\x78\x2d\x6e\x73\x23\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x6e\ +\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ +\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\ +\x67\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\ +\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x0d\x0a\x20\x20\x20\x78\x6d\ +\x6c\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\ +\x74\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\ +\x75\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\ +\x44\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\ +\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\x6b\x73\ +\x63\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\ +\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\x6e\x61\ +\x6d\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x22\x0d\x0a\x20\x20\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\ +\x31\x2e\x31\x22\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x43\x61\x70\ +\x61\x5f\x31\x22\x0d\x0a\x20\x20\x20\x78\x3d\x22\x30\x70\x78\x22\ +\x0d\x0a\x20\x20\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x20\x20\ +\x20\x77\x69\x64\x74\x68\x3d\x22\x35\x31\x32\x22\x0d\x0a\x20\x20\ +\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x35\x31\x32\x22\x0d\x0a\x20\ +\x20\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x35\ +\x31\x32\x20\x35\x31\x32\x22\x0d\x0a\x20\x20\x20\x78\x6d\x6c\x3a\ +\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\ +\x0d\x0a\x20\x20\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\x64\x6f\ +\x63\x6e\x61\x6d\x65\x3d\x22\x63\x6c\x6f\x73\x65\x2d\x62\x75\x74\ +\x74\x6f\x6e\x2d\x64\x69\x73\x61\x62\x6c\x65\x64\x2e\x73\x76\x67\ +\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x76\ +\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x39\x32\x2e\x33\x20\x28\ +\x32\x34\x30\x35\x35\x34\x36\x2c\x20\x32\x30\x31\x38\x2d\x30\x33\ +\x2d\x31\x31\x29\x22\x3e\x3c\x6d\x65\x74\x61\x64\x61\x74\x61\x0d\ +\x0a\x20\x20\x20\x69\x64\x3d\x22\x6d\x65\x74\x61\x64\x61\x74\x61\ +\x38\x39\x37\x22\x3e\x3c\x72\x64\x66\x3a\x52\x44\x46\x3e\x3c\x63\ +\x63\x3a\x57\x6f\x72\x6b\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x72\ +\x64\x66\x3a\x61\x62\x6f\x75\x74\x3d\x22\x22\x3e\x3c\x64\x63\x3a\ +\x66\x6f\x72\x6d\x61\x74\x3e\x69\x6d\x61\x67\x65\x2f\x73\x76\x67\ +\x2b\x78\x6d\x6c\x3c\x2f\x64\x63\x3a\x66\x6f\x72\x6d\x61\x74\x3e\ +\x3c\x64\x63\x3a\x74\x79\x70\x65\x0d\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x20\x72\x64\x66\x3a\x72\x65\x73\x6f\x75\x72\x63\x65\x3d\ +\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\x6c\x2e\x6f\x72\x67\ +\x2f\x64\x63\x2f\x64\x63\x6d\x69\x74\x79\x70\x65\x2f\x53\x74\x69\ +\x6c\x6c\x49\x6d\x61\x67\x65\x22\x20\x2f\x3e\x3c\x64\x63\x3a\x74\ +\x69\x74\x6c\x65\x3e\x3c\x2f\x64\x63\x3a\x74\x69\x74\x6c\x65\x3e\ +\x3c\x2f\x63\x63\x3a\x57\x6f\x72\x6b\x3e\x3c\x2f\x72\x64\x66\x3a\ +\x52\x44\x46\x3e\x3c\x2f\x6d\x65\x74\x61\x64\x61\x74\x61\x3e\x3c\ +\x64\x65\x66\x73\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x64\x65\x66\ +\x73\x38\x39\x35\x22\x20\x2f\x3e\x3c\x73\x6f\x64\x69\x70\x6f\x64\ +\x69\x3a\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x0d\x0a\x20\x20\x20\ +\x70\x61\x67\x65\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x66\x66\x66\x66\ +\x66\x66\x22\x0d\x0a\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x63\x6f\ +\x6c\x6f\x72\x3d\x22\x23\x36\x36\x36\x36\x36\x36\x22\x0d\x0a\x20\ +\x20\x20\x62\x6f\x72\x64\x65\x72\x6f\x70\x61\x63\x69\x74\x79\x3d\ +\x22\x31\x22\x0d\x0a\x20\x20\x20\x6f\x62\x6a\x65\x63\x74\x74\x6f\ +\x6c\x65\x72\x61\x6e\x63\x65\x3d\x22\x31\x30\x22\x0d\x0a\x20\x20\ +\x20\x67\x72\x69\x64\x74\x6f\x6c\x65\x72\x61\x6e\x63\x65\x3d\x22\ +\x31\x30\x22\x0d\x0a\x20\x20\x20\x67\x75\x69\x64\x65\x74\x6f\x6c\ +\x65\x72\x61\x6e\x63\x65\x3d\x22\x31\x30\x22\x0d\x0a\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x6f\x70\x61\ +\x63\x69\x74\x79\x3d\x22\x30\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\ +\x73\x63\x61\x70\x65\x3a\x70\x61\x67\x65\x73\x68\x61\x64\x6f\x77\ +\x3d\x22\x32\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x77\x69\x64\x74\x68\x3d\x22\ +\x31\x39\x32\x30\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\ +\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x68\x65\x69\x67\x68\x74\ +\x3d\x22\x31\x30\x31\x37\x22\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\ +\x6e\x61\x6d\x65\x64\x76\x69\x65\x77\x38\x39\x33\x22\x0d\x0a\x20\ +\x20\x20\x73\x68\x6f\x77\x67\x72\x69\x64\x3d\x22\x66\x61\x6c\x73\ +\x65\x22\x0d\x0a\x20\x20\x20\x66\x69\x74\x2d\x6d\x61\x72\x67\x69\ +\x6e\x2d\x74\x6f\x70\x3d\x22\x30\x22\x0d\x0a\x20\x20\x20\x66\x69\ +\x74\x2d\x6d\x61\x72\x67\x69\x6e\x2d\x6c\x65\x66\x74\x3d\x22\x30\ +\x22\x0d\x0a\x20\x20\x20\x66\x69\x74\x2d\x6d\x61\x72\x67\x69\x6e\ +\x2d\x72\x69\x67\x68\x74\x3d\x22\x30\x22\x0d\x0a\x20\x20\x20\x66\ +\x69\x74\x2d\x6d\x61\x72\x67\x69\x6e\x2d\x62\x6f\x74\x74\x6f\x6d\ +\x3d\x22\x30\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\ +\x65\x3a\x7a\x6f\x6f\x6d\x3d\x22\x30\x2e\x38\x35\x38\x36\x32\x39\ +\x36\x36\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x63\x78\x3d\x22\x33\x34\x35\x2e\x32\x39\x31\x34\x32\x22\x0d\ +\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x63\x79\x3d\ +\x22\x33\x32\x2e\x37\x33\x31\x32\x35\x38\x22\x0d\x0a\x20\x20\x20\ +\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\ +\x78\x3d\x22\x2d\x38\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\ +\x61\x70\x65\x3a\x77\x69\x6e\x64\x6f\x77\x2d\x79\x3d\x22\x2d\x38\ +\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\x3a\x77\ +\x69\x6e\x64\x6f\x77\x2d\x6d\x61\x78\x69\x6d\x69\x7a\x65\x64\x3d\ +\x22\x31\x22\x0d\x0a\x20\x20\x20\x69\x6e\x6b\x73\x63\x61\x70\x65\ +\x3a\x63\x75\x72\x72\x65\x6e\x74\x2d\x6c\x61\x79\x65\x72\x3d\x22\ +\x43\x61\x70\x61\x5f\x31\x22\x20\x2f\x3e\x0d\x0a\x3c\x67\x0d\x0a\ +\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x36\x30\x22\x0d\x0a\x20\x20\ +\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\ +\x69\x78\x28\x30\x2e\x37\x31\x37\x30\x38\x36\x38\x33\x2c\x30\x2c\ +\x30\x2c\x30\x2e\x37\x31\x37\x30\x38\x36\x38\x33\x2c\x31\x32\x38\ +\x2c\x31\x32\x38\x29\x22\x0d\x0a\x20\x20\x20\x73\x74\x79\x6c\x65\ +\x3d\x22\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\x3b\x73\x74\ +\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x31\x3b\x66\ +\x69\x6c\x6c\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\x69\x6c\x6c\ +\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x35\x30\x31\x39\x36\ +\x30\x38\x31\x22\x3e\x0d\x0a\x09\x3c\x67\x0d\x0a\x20\x20\x20\x69\ +\x64\x3d\x22\x63\x6c\x6f\x73\x65\x22\x0d\x0a\x20\x20\x20\x73\x74\ +\x79\x6c\x65\x3d\x22\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\x65\ +\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\ +\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\x66\ +\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x35\x30\ +\x31\x39\x36\x30\x38\x31\x22\x3e\x0d\x0a\x09\x09\x3c\x70\x6f\x6c\ +\x79\x67\x6f\x6e\x0d\x0a\x20\x20\x20\x70\x6f\x69\x6e\x74\x73\x3d\ +\x22\x33\x35\x37\x2c\x33\x32\x31\x2e\x33\x20\x32\x31\x34\x2e\x32\ +\x2c\x31\x37\x38\x2e\x35\x20\x33\x35\x37\x2c\x33\x35\x2e\x37\x20\ +\x33\x32\x31\x2e\x33\x2c\x30\x20\x31\x37\x38\x2e\x35\x2c\x31\x34\ +\x32\x2e\x38\x20\x33\x35\x2e\x37\x2c\x30\x20\x30\x2c\x33\x35\x2e\ +\x37\x20\x31\x34\x32\x2e\x38\x2c\x31\x37\x38\x2e\x35\x20\x30\x2c\ +\x33\x32\x31\x2e\x33\x20\x33\x35\x2e\x37\x2c\x33\x35\x37\x20\x31\ +\x37\x38\x2e\x35\x2c\x32\x31\x34\x2e\x32\x20\x33\x32\x31\x2e\x33\ +\x2c\x33\x35\x37\x20\x22\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x70\ +\x6f\x6c\x79\x67\x6f\x6e\x38\x35\x37\x22\x0d\x0a\x20\x20\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x73\x74\x72\x6f\x6b\x65\x3a\x6e\x6f\x6e\ +\x65\x3b\x73\x74\x72\x6f\x6b\x65\x2d\x6f\x70\x61\x63\x69\x74\x79\ +\x3a\x31\x3b\x66\x69\x6c\x6c\x3a\x23\x30\x30\x30\x30\x30\x30\x3b\ +\x66\x69\x6c\x6c\x2d\x6f\x70\x61\x63\x69\x74\x79\x3a\x30\x2e\x35\ +\x30\x31\x39\x36\x30\x38\x31\x22\x20\x2f\x3e\x0d\x0a\x09\x3c\x2f\ +\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\ +\x20\x69\x64\x3d\x22\x67\x38\x36\x32\x22\x0d\x0a\x20\x20\x20\x74\ +\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\ +\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\ +\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\ +\x38\x36\x34\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\ +\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\ +\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\ +\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x36\x36\x22\x0d\x0a\ +\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\ +\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\ +\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\ +\x64\x3d\x22\x67\x38\x36\x38\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\ +\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\ +\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\ +\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x37\ +\x30\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\ +\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\ +\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\ +\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x37\x32\x22\x0d\x0a\x20\x20\ +\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\ +\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\ +\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\ +\x22\x67\x38\x37\x34\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\ +\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\ +\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x37\x36\x22\ +\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\ +\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\ +\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\ +\x20\x69\x64\x3d\x22\x67\x38\x37\x38\x22\x0d\x0a\x20\x20\x20\x74\ +\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\ +\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\ +\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\ +\x38\x38\x30\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\ +\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\ +\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\ +\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x38\x32\x22\x0d\x0a\ +\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\ +\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\ +\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\ +\x64\x3d\x22\x67\x38\x38\x34\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\ +\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\ +\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\ +\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x38\ +\x36\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\ +\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\ +\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\ +\x20\x20\x20\x69\x64\x3d\x22\x67\x38\x38\x38\x22\x0d\x0a\x20\x20\ +\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\ +\x73\x6c\x61\x74\x65\x28\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\ +\x3c\x2f\x67\x3e\x0d\x0a\x3c\x67\x0d\x0a\x20\x20\x20\x69\x64\x3d\ +\x22\x67\x38\x39\x30\x22\x0d\x0a\x20\x20\x20\x74\x72\x61\x6e\x73\ +\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\ +\x30\x2c\x31\x35\x35\x29\x22\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\ +\x3c\x2f\x73\x76\x67\x3e\ +\x00\x00\x06\x61\ +\x0d\ +\x0a\x2f\x2a\x0d\x0a\x20\x2a\x20\x44\x65\x66\x61\x75\x6c\x74\x20\ +\x73\x74\x79\x6c\x65\x20\x73\x68\x65\x65\x74\x20\x6f\x6e\x20\x57\ +\x69\x6e\x64\x6f\x77\x73\x20\x50\x6c\x61\x74\x66\x6f\x72\x6d\x73\ +\x0d\x0a\x20\x2a\x20\x4e\x6f\x74\x65\x3a\x20\x41\x6c\x77\x61\x79\ +\x73\x20\x75\x73\x65\x20\x43\x53\x53\x2d\x63\x6c\x61\x73\x73\x65\ +\x73\x20\x77\x69\x74\x68\x20\x61\x6e\x64\x20\x77\x69\x74\x68\x6f\ +\x75\x74\x20\x22\x61\x64\x73\x2d\x2d\x22\x20\x6e\x61\x6d\x65\x73\ +\x70\x61\x63\x65\x20\x74\x6f\x20\x73\x75\x70\x70\x6f\x72\x74\x20\ +\x51\x74\x34\x20\x26\x20\x51\x74\x35\x0d\x0a\x20\x2a\x2f\x0d\x0a\ +\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\x63\x6b\x43\x6f\x6e\x74\ +\x61\x69\x6e\x65\x72\x57\x69\x64\x67\x65\x74\x0d\x0a\x7b\x0d\x0a\ +\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\ +\x70\x61\x6c\x65\x74\x74\x65\x28\x64\x61\x72\x6b\x29\x3b\x0d\x0a\ +\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\x63\x6b\x43\ +\x6f\x6e\x74\x61\x69\x6e\x65\x72\x57\x69\x64\x67\x65\x74\x20\x51\ +\x53\x70\x6c\x69\x74\x74\x65\x72\x3a\x3a\x68\x61\x6e\x64\x6c\x65\ +\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ +\x75\x6e\x64\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x64\x61\x72\ +\x6b\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\ +\x44\x6f\x63\x6b\x41\x72\x65\x61\x57\x69\x64\x67\x65\x74\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x77\x69\x6e\x64\x6f\ +\x77\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\ +\x20\x31\x70\x78\x20\x73\x6f\x6c\x69\x64\x20\x77\x68\x69\x74\x65\ +\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\ +\x63\x6b\x41\x72\x65\x61\x57\x69\x64\x67\x65\x74\x20\x23\x74\x61\ +\x62\x73\x4d\x65\x6e\x75\x42\x75\x74\x74\x6f\x6e\x3a\x3a\x6d\x65\ +\x6e\x75\x2d\x69\x6e\x64\x69\x63\x61\x74\x6f\x72\x0d\x0a\x7b\x0d\ +\x0a\x20\x20\x20\x20\x69\x6d\x61\x67\x65\x3a\x20\x6e\x6f\x6e\x65\ +\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\ +\x44\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x0d\x0a\x7b\ +\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ +\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x77\x69\x6e\x64\x6f\x77\ +\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x6c\x69\ +\x67\x68\x74\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ +\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0d\ +\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\ +\x68\x3a\x20\x30\x20\x31\x70\x78\x20\x30\x20\x30\x3b\x0d\x0a\x20\ +\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x30\x20\x30\x70\ +\x78\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\ +\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x5b\x61\x63\x74\ +\x69\x76\x65\x54\x61\x62\x3d\x22\x74\x72\x75\x65\x22\x5d\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\ +\x6e\x74\x28\x73\x70\x72\x65\x61\x64\x3a\x70\x61\x64\x2c\x20\x78\ +\x31\x3a\x30\x2c\x20\x79\x31\x3a\x30\x2c\x20\x78\x32\x3a\x30\x2c\ +\x20\x79\x32\x3a\x30\x2e\x35\x2c\x20\x73\x74\x6f\x70\x3a\x30\x20\ +\x70\x61\x6c\x65\x74\x74\x65\x28\x77\x69\x6e\x64\x6f\x77\x29\x2c\ +\x20\x73\x74\x6f\x70\x3a\x31\x20\x70\x61\x6c\x65\x74\x74\x65\x28\ +\x6c\x69\x67\x68\x74\x29\x29\x3b\x0d\x0a\x20\x20\x20\x20\x2f\x2a\ +\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x70\x61\x6c\x65\ +\x74\x74\x65\x28\x68\x69\x67\x68\x6c\x69\x67\x68\x74\x29\x3b\x2a\ +\x2f\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\ +\x63\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x20\x51\x4c\x61\x62\ +\x65\x6c\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\ +\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x64\x61\x72\x6b\x29\x3b\ +\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\x63\ +\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x5b\x61\x63\x74\x69\x76\ +\x65\x54\x61\x62\x3d\x22\x74\x72\x75\x65\x22\x5d\x20\x51\x4c\x61\ +\x62\x65\x6c\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\ +\x72\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x66\x6f\x72\x65\x67\ +\x72\x6f\x75\x6e\x64\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\ +\x73\x2d\x2d\x43\x44\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x6c\x69\x67\x68\x74\ +\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x6c\x69\ +\x67\x68\x74\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ +\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0d\ +\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\ +\x68\x3a\x20\x31\x70\x78\x20\x30\x20\x30\x20\x30\x3b\x0d\x0a\x7d\ +\x0d\x0a\x0d\x0a\x23\x74\x61\x62\x73\x4d\x65\x6e\x75\x42\x75\x74\ +\x74\x6f\x6e\x2c\x0d\x0a\x23\x63\x6c\x6f\x73\x65\x42\x75\x74\x74\ +\x6f\x6e\x2c\x0d\x0a\x23\x75\x6e\x64\x6f\x63\x6b\x42\x75\x74\x74\ +\x6f\x6e\x0d\x0a\x7b\x0d\x0a\x09\x70\x61\x64\x64\x69\x6e\x67\x3a\ +\x20\x30\x70\x78\x20\x2d\x32\x70\x78\x3b\x0d\x0a\x7d\x0d\x0a\x0d\ +\x0a\x0d\x0a\x51\x53\x63\x72\x6f\x6c\x6c\x41\x72\x65\x61\x23\x64\ +\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x53\x63\x72\x6f\x6c\x6c\x41\ +\x72\x65\x61\x0d\x0a\x7b\x0d\x0a\x09\x70\x61\x64\x64\x69\x6e\x67\ +\x3a\x20\x30\x70\x78\x3b\x0d\x0a\x09\x62\x6f\x72\x64\x65\x72\x3a\ +\x20\x6e\x6f\x6e\x65\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x0d\x0a\x23\ +\x74\x61\x62\x43\x6c\x6f\x73\x65\x42\x75\x74\x74\x6f\x6e\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x6d\x61\x72\x67\x69\ +\x6e\x2d\x74\x6f\x70\x3a\x20\x32\x70\x78\x3b\x0d\x0a\x20\x20\x20\ +\x20\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\ +\x20\x6e\x6f\x6e\x65\x3b\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x62\x6f\x72\x64\x65\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0d\x0a\x20\ +\x20\x20\x20\x20\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\ +\x30\x70\x78\x20\x2d\x32\x70\x78\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\ +\x23\x74\x61\x62\x43\x6c\x6f\x73\x65\x42\x75\x74\x74\x6f\x6e\x3a\ +\x68\x6f\x76\x65\x72\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x20\x20\ +\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\x20\x31\x70\x78\x20\x73\x6f\ +\x6c\x69\x64\x20\x72\x67\x62\x61\x28\x30\x2c\x20\x30\x2c\x20\x30\ +\x2c\x20\x33\x32\x29\x3b\x0d\x0a\x20\x20\x20\x20\x20\x20\x20\x20\ +\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x72\x67\x62\x61\ +\x28\x30\x2c\x20\x30\x2c\x20\x30\x2c\x20\x31\x36\x29\x3b\x0d\x0a\ +\x7d\x0d\x0a\x0d\x0a\x23\x74\x61\x62\x43\x6c\x6f\x73\x65\x42\x75\ +\x74\x74\x6f\x6e\x3a\x70\x72\x65\x73\x73\x65\x64\x0d\x0a\x7b\x0d\ +\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ +\x75\x6e\x64\x3a\x20\x72\x67\x62\x61\x28\x30\x2c\x20\x30\x2c\x20\ +\x30\x2c\x20\x33\x32\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x0d\x0a\ +\ +\x00\x00\x06\x30\ +\x0d\ +\x0a\x2f\x2a\x0d\x0a\x20\x2a\x20\x44\x65\x66\x61\x75\x6c\x74\x20\ +\x73\x74\x79\x6c\x65\x20\x73\x68\x65\x65\x74\x20\x6f\x6e\x20\x57\ +\x69\x6e\x64\x6f\x77\x73\x20\x50\x6c\x61\x74\x66\x6f\x72\x6d\x73\ +\x0d\x0a\x20\x2a\x20\x4e\x6f\x74\x65\x3a\x20\x41\x6c\x77\x61\x79\ +\x73\x20\x75\x73\x65\x20\x43\x53\x53\x2d\x63\x6c\x61\x73\x73\x65\ +\x73\x20\x77\x69\x74\x68\x20\x61\x6e\x64\x20\x77\x69\x74\x68\x6f\ +\x75\x74\x20\x22\x61\x64\x73\x2d\x2d\x22\x20\x6e\x61\x6d\x65\x73\ +\x70\x61\x63\x65\x20\x74\x6f\x20\x73\x75\x70\x70\x6f\x72\x74\x20\ +\x51\x74\x34\x20\x26\x20\x51\x74\x35\x0d\x0a\x20\x2a\x2f\x0d\x0a\ +\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\x63\x6b\x43\x6f\x6e\x74\ +\x61\x69\x6e\x65\x72\x57\x69\x64\x67\x65\x74\x0d\x0a\x7b\x0d\x0a\ +\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\ +\x70\x61\x6c\x65\x74\x74\x65\x28\x64\x61\x72\x6b\x29\x3b\x0d\x0a\ +\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\x63\x6b\x43\ +\x6f\x6e\x74\x61\x69\x6e\x65\x72\x57\x69\x64\x67\x65\x74\x20\x51\ +\x53\x70\x6c\x69\x74\x74\x65\x72\x3a\x3a\x68\x61\x6e\x64\x6c\x65\ +\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\ +\x75\x6e\x64\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x64\x61\x72\ +\x6b\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\ +\x44\x6f\x63\x6b\x41\x72\x65\x61\x57\x69\x64\x67\x65\x74\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x77\x69\x6e\x64\x6f\ +\x77\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x3a\ +\x20\x31\x70\x78\x20\x73\x6f\x6c\x69\x64\x20\x77\x68\x69\x74\x65\ +\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\ +\x63\x6b\x41\x72\x65\x61\x57\x69\x64\x67\x65\x74\x20\x23\x74\x61\ +\x62\x73\x4d\x65\x6e\x75\x42\x75\x74\x74\x6f\x6e\x3a\x3a\x6d\x65\ +\x6e\x75\x2d\x69\x6e\x64\x69\x63\x61\x74\x6f\x72\x0d\x0a\x7b\x0d\ +\x0a\x20\x20\x20\x20\x69\x6d\x61\x67\x65\x3a\x20\x6e\x6f\x6e\x65\ +\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\ +\x44\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x0d\x0a\x7b\ +\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ +\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x77\x69\x6e\x64\x6f\x77\ +\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x6c\x69\ +\x67\x68\x74\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ +\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0d\ +\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\ +\x68\x3a\x20\x30\x20\x31\x70\x78\x20\x30\x20\x30\x3b\x0d\x0a\x20\ +\x20\x20\x20\x70\x61\x64\x64\x69\x6e\x67\x3a\x20\x30\x20\x30\x70\ +\x78\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\ +\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x5b\x61\x63\x74\ +\x69\x76\x65\x54\x61\x62\x3d\x22\x74\x72\x75\x65\x22\x5d\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x71\x6c\x69\x6e\x65\x61\x72\x67\x72\x61\x64\x69\x65\ +\x6e\x74\x28\x73\x70\x72\x65\x61\x64\x3a\x70\x61\x64\x2c\x20\x78\ +\x31\x3a\x30\x2c\x20\x79\x31\x3a\x30\x2c\x20\x78\x32\x3a\x30\x2c\ +\x20\x79\x32\x3a\x30\x2e\x35\x2c\x20\x73\x74\x6f\x70\x3a\x30\x20\ +\x70\x61\x6c\x65\x74\x74\x65\x28\x77\x69\x6e\x64\x6f\x77\x29\x2c\ +\x20\x73\x74\x6f\x70\x3a\x31\x20\x70\x61\x6c\x65\x74\x74\x65\x28\ +\x6c\x69\x67\x68\x74\x29\x29\x3b\x0d\x0a\x20\x20\x20\x20\x2f\x2a\ +\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x20\x70\x61\x6c\x65\ +\x74\x74\x65\x28\x68\x69\x67\x68\x6c\x69\x67\x68\x74\x29\x3b\x2a\ +\x2f\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\ +\x63\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x20\x51\x4c\x61\x62\ +\x65\x6c\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\x72\ +\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x64\x61\x72\x6b\x29\x3b\ +\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\x73\x2d\x2d\x43\x44\x6f\x63\ +\x6b\x57\x69\x64\x67\x65\x74\x54\x61\x62\x5b\x61\x63\x74\x69\x76\ +\x65\x54\x61\x62\x3d\x22\x74\x72\x75\x65\x22\x5d\x20\x51\x4c\x61\ +\x62\x65\x6c\x0d\x0a\x7b\x0d\x0a\x20\x20\x20\x20\x63\x6f\x6c\x6f\ +\x72\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x66\x6f\x72\x65\x67\ +\x72\x6f\x75\x6e\x64\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x61\x64\ +\x73\x2d\x2d\x43\x44\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x0d\x0a\ +\x7b\x0d\x0a\x20\x20\x20\x20\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x6c\x69\x67\x68\x74\ +\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x63\ +\x6f\x6c\x6f\x72\x3a\x20\x70\x61\x6c\x65\x74\x74\x65\x28\x6c\x69\ +\x67\x68\x74\x29\x3b\x0d\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\ +\x72\x2d\x73\x74\x79\x6c\x65\x3a\x20\x73\x6f\x6c\x69\x64\x3b\x0d\ +\x0a\x20\x20\x20\x20\x62\x6f\x72\x64\x65\x72\x2d\x77\x69\x64\x74\ +\x68\x3a\x20\x31\x70\x78\x20\x30\x20\x30\x20\x30\x3b\x0d\x0a\x7d\ +\x0d\x0a\x0d\x0a\x23\x74\x61\x62\x73\x4d\x65\x6e\x75\x42\x75\x74\ +\x74\x6f\x6e\x2c\x0d\x0a\x23\x63\x6c\x6f\x73\x65\x42\x75\x74\x74\ +\x6f\x6e\x2c\x0d\x0a\x23\x75\x6e\x64\x6f\x63\x6b\x42\x75\x74\x74\ +\x6f\x6e\x0d\x0a\x7b\x0d\x0a\x09\x70\x61\x64\x64\x69\x6e\x67\x3a\ +\x20\x30\x70\x78\x20\x2d\x32\x70\x78\x3b\x0d\x0a\x7d\x0d\x0a\x0d\ +\x0a\x0d\x0a\x51\x53\x63\x72\x6f\x6c\x6c\x41\x72\x65\x61\x23\x64\ +\x6f\x63\x6b\x57\x69\x64\x67\x65\x74\x53\x63\x72\x6f\x6c\x6c\x41\ +\x72\x65\x61\x0d\x0a\x7b\x0d\x0a\x09\x70\x61\x64\x64\x69\x6e\x67\ +\x3a\x20\x30\x70\x78\x3b\x0d\x0a\x09\x62\x6f\x72\x64\x65\x72\x3a\ +\x20\x6e\x6f\x6e\x65\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x0d\x0a\x23\ +\x74\x61\x62\x43\x6c\x6f\x73\x65\x42\x75\x74\x74\x6f\x6e\x0d\x0a\ +\x7b\x0d\x0a\x09\x6d\x61\x72\x67\x69\x6e\x2d\x74\x6f\x70\x3a\x20\ +\x32\x70\x78\x3b\x0d\x0a\x09\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ +\x64\x3a\x20\x6e\x6f\x6e\x65\x3b\x0d\x0a\x09\x62\x6f\x72\x64\x65\ +\x72\x3a\x20\x6e\x6f\x6e\x65\x3b\x0d\x0a\x09\x70\x61\x64\x64\x69\ +\x6e\x67\x3a\x20\x30\x70\x78\x20\x2d\x32\x70\x78\x3b\x0d\x0a\x7d\ +\x0d\x0a\x0d\x0a\x23\x74\x61\x62\x43\x6c\x6f\x73\x65\x42\x75\x74\ +\x74\x6f\x6e\x3a\x68\x6f\x76\x65\x72\x0d\x0a\x7b\x0d\x0a\x09\x62\ +\x6f\x72\x64\x65\x72\x3a\x20\x31\x70\x78\x20\x73\x6f\x6c\x69\x64\ +\x20\x72\x67\x62\x61\x28\x30\x2c\x20\x30\x2c\x20\x30\x2c\x20\x33\ +\x32\x29\x3b\x0d\x0a\x09\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ +\x3a\x20\x72\x67\x62\x61\x28\x30\x2c\x20\x30\x2c\x20\x30\x2c\x20\ +\x31\x36\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x23\x74\x61\x62\x43\ +\x6c\x6f\x73\x65\x42\x75\x74\x74\x6f\x6e\x3a\x70\x72\x65\x73\x73\ +\x65\x64\x0d\x0a\x7b\x0d\x0a\x09\x62\x61\x63\x6b\x67\x72\x6f\x75\ +\x6e\x64\x3a\x20\x72\x67\x62\x61\x28\x30\x2c\x20\x30\x2c\x20\x30\ +\x2c\x20\x33\x32\x29\x3b\x0d\x0a\x7d\x0d\x0a\x0d\x0a\x0d\x0a\ +" + +qt_resource_name = b"\ +\x00\x03\ +\x00\x00\x67\xb3\ +\x00\x61\ +\x00\x64\x00\x73\ +\x00\x0b\ +\x0c\x6b\x3c\xf3\ +\x00\x73\ +\x00\x74\x00\x79\x00\x6c\x00\x65\x00\x73\x00\x68\x00\x65\x00\x65\x00\x74\x00\x73\ +\x00\x06\ +\x07\x03\x7d\xc3\ +\x00\x69\ +\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\ +\x00\x10\ +\x08\x7c\xee\x07\ +\x00\x63\ +\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2d\x00\x62\x00\x75\x00\x74\x00\x74\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x19\ +\x03\x4c\x6a\xc7\ +\x00\x63\ +\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2d\x00\x62\x00\x75\x00\x74\x00\x74\x00\x6f\x00\x6e\x00\x2d\x00\x64\x00\x69\x00\x73\x00\x61\ +\x00\x62\x00\x6c\x00\x65\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\ +\x00\x11\ +\x0c\x15\xf2\x83\ +\x00\x64\ +\x00\x65\x00\x66\x00\x61\x00\x75\x00\x6c\x00\x74\x00\x5f\x00\x6c\x00\x69\x00\x6e\x00\x75\x00\x78\x00\x2e\x00\x63\x00\x73\x00\x73\ +\ +\x00\x0b\ +\x0c\xe2\x33\xa3\ +\x00\x64\ +\x00\x65\x00\x66\x00\x61\x00\x75\x00\x6c\x00\x74\x00\x2e\x00\x63\x00\x73\x00\x73\ +" + +qt_resource_struct_v1 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\ +\x00\x00\x00\x28\x00\x02\x00\x00\x00\x02\x00\x00\x00\x06\ +\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x02\x00\x00\x00\x04\ +\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x17\x03\ +\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x68\ +\x00\x00\x00\x60\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x08\ +\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +" + +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x28\x00\x02\x00\x00\x00\x02\x00\x00\x00\x06\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x0c\x00\x02\x00\x00\x00\x02\x00\x00\x00\x04\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\x17\x03\ +\x00\x00\x01\x6d\xaf\xb0\x91\x61\ +\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x1d\x68\ +\x00\x00\x01\x6d\xaf\xb0\x91\x60\ +\x00\x00\x00\x60\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x08\ +\x00\x00\x01\x6d\xaf\xb0\x91\x5e\ +\x00\x00\x00\x3a\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x6d\xaf\xb0\x91\x5e\ +" + +qt_version = QtCore.qVersion().split('.') +if qt_version < ['5', '8', '0']: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + +def qInitResources(): + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/demo.py b/demo.py new file mode 100644 index 0000000..11c3f09 --- /dev/null +++ b/demo.py @@ -0,0 +1,316 @@ +import datetime +import logging + +from PyQt5.QtCore import (QCoreApplication, QDir, Qt, QSettings, QSignalBlocker, + QRect) +from PyQt5.QtGui import QGuiApplication +from PyQt5.QtWidgets import (QCalendarWidget, QFileSystemModel, QFrame, QLabel, + QMenu, QTreeView, QAction, QWidgetAction, + QComboBox, QStyle, QSizePolicy, QInputDialog) + +from PyQt5 import QtWidgets + +from PyQtAds import QtAds + + +class _State: + label_count = 0 + calendar_count = 0 + file_system_count = 0 + + +def create_long_text_label_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget: + ''' + Create long text label dock widget + + Parameters + ---------- + view_menu : QMenu + + Returns + ------- + value : QtAds.CDockWidget + ''' + label = QLabel() + label.setWordWrap(True) + label.setAlignment(Qt.AlignTop | Qt.AlignLeft) + label.setText('''\ +Label {} {} - Lorem ipsum dolor sit amet, consectetuer +adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum +sociis natoque penatibus et magnis dis parturient montes, nascetur +ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium +quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla +vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, +imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis +pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. +Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, +consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra +quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. + '''.format(_State.label_count, str(datetime.datetime.now()))) + _State.label_count += 1 + + dock_widget = QtAds.CDockWidget("Label {}".format(_State.label_count)) + dock_widget.setWidget(label) + + view_menu.addAction(dock_widget.toggleViewAction()) + return dock_widget + + +def create_calendar_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget: + ''' + Create calendar dock widget + + Parameters + ---------- + view_menu : QMenu + + Returns + ------- + value : QtAds.CDockWidget + ''' + widget = QCalendarWidget() + + dock_widget = QtAds.CDockWidget("Calendar {}".format(_State.calendar_count)) + _State.calendar_count += 1 + dock_widget.setWidget(widget) + dock_widget.setToggleViewActionMode(QtAds.CDockWidget.ActionModeShow) + view_menu.addAction(dock_widget.toggleViewAction()) + return dock_widget + + +def create_file_system_tree_dock_widget(view_menu: QMenu) -> QtAds.CDockWidget: + ''' + Create file system tree dock widget + + Parameters + ---------- + view_menu : QMenu + + Returns + ------- + value : QtAds.CDockWidget + ''' + widget = QTreeView() + widget.setFrameShape(QFrame.NoFrame) + + m = QFileSystemModel(widget) + m.setRootPath(QDir.currentPath()) + widget.setModel(m) + + dock_widget = QtAds.CDockWidget("Filesystem {}".format(_State.file_system_count)) + _State.file_system_count += 1 + dock_widget.setWidget(widget) + view_menu.addAction(dock_widget.toggleViewAction()) + return dock_widget + + +class MainWindow(QtWidgets.QMainWindow): + save_perspective_action: QAction + perspective_list_action: QWidgetAction + perspective_combo_box: QComboBox + dock_manager: QtAds.CDockManager + + def __init__(self, parent=None): + super().__init__(parent) + self.save_perspective_action = None + self.perspective_list_action = None + self.perspective_combo_box = None + self.dock_manager = None + + self.setup_ui() + + self.dock_manager = QtAds.CDockManager(self) + self.perspective_combo_box.activated[str].connect(self.dock_manager.openPerspective) + self.create_content() + self.resize(800, 600) + self.restore_state() + self.restore_perspectives() + + def setup_ui(self): + self.setObjectName("MainWindow") + self.resize(400, 300) + self.setDockOptions(QtWidgets.QMainWindow.AllowTabbedDocks) + self.centralWidget = QtWidgets.QWidget(self) + self.centralWidget.setObjectName("centralWidget") + self.setCentralWidget(self.centralWidget) + self.status_bar = QtWidgets.QStatusBar(self) + self.status_bar.setObjectName("statusBar") + self.setStatusBar(self.status_bar) + self.menu_bar = QtWidgets.QMenuBar(self) + self.menu_bar.setGeometry(QRect(0, 0, 400, 21)) + self.menu_bar.setObjectName("menuBar") + self.menu_file = QtWidgets.QMenu(self.menu_bar) + self.menu_file.setObjectName("menuFile") + self.menu_view = QtWidgets.QMenu(self.menu_bar) + self.menu_view.setObjectName("menuView") + self.menu_about = QtWidgets.QMenu(self.menu_bar) + self.menu_about.setObjectName("menuAbout") + self.setMenuBar(self.menu_bar) + self.tool_bar = QtWidgets.QToolBar(self) + self.tool_bar.setObjectName("toolBar") + self.addToolBar(Qt.TopToolBarArea, self.tool_bar) + self.action_exit = QtWidgets.QAction(self) + self.action_exit.setObjectName("actionExit") + self.action_save_state = QtWidgets.QAction(self) + self.action_save_state.setObjectName("actionSaveState") + self.action_save_state.triggered.connect(self.saveState) + + self.action_restore_state = QtWidgets.QAction(self) + self.action_restore_state.setObjectName("actionRestoreState") + self.action_restore_state.triggered.connect(self.restore_state) + + self.menu_file.addAction(self.action_exit) + self.menu_file.addAction(self.action_save_state) + self.menu_file.addAction(self.action_restore_state) + self.menu_bar.addAction(self.menu_file.menuAction()) + self.menu_bar.addAction(self.menu_view.menuAction()) + self.menu_bar.addAction(self.menu_about.menuAction()) + + self.setWindowTitle("MainWindow") + self.menu_file.setTitle("File") + self.menu_view.setTitle("View") + self.menu_about.setTitle("About") + self.tool_bar.setWindowTitle("toolBar") + self.action_exit.setText("Exit") + self.action_save_state.setText("Save State") + self.action_restore_state.setText("Restore State") + self.create_actions() + + def create_actions(self): + ''' + Creates the toolbar actions + ''' + self.tool_bar.addAction(self.action_save_state) + self.action_save_state.setIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton)) + self.tool_bar.addAction(self.action_restore_state) + self.action_restore_state.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton)) + self.save_perspective_action = QAction("Save Perspective", self) + self.save_perspective_action.triggered.connect(self.save_perspective) + + self.perspective_list_action = QWidgetAction(self) + self.perspective_combo_box = QComboBox(self) + self.perspective_combo_box.setSizeAdjustPolicy(QComboBox.AdjustToContents) + self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) + self.perspective_list_action.setDefaultWidget(self.perspective_combo_box) + self.tool_bar.addSeparator() + self.tool_bar.addAction(self.perspective_list_action) + self.tool_bar.addAction(self.save_perspective_action) + + def create_content(self): + ''' + Fill the dock manager with dock widgets + ''' + # Test container docking + view_menu = self.menu_view + dock_widget = create_calendar_dock_widget(view_menu) + dock_widget.setIcon(self.style().standardIcon(QStyle.SP_DialogOpenButton)) + dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False) + self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget) + self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, create_long_text_label_dock_widget(view_menu)) + file_system_widget = create_file_system_tree_dock_widget(view_menu) + tool_bar = file_system_widget.createDefaultToolBar() + tool_bar.addAction(self.action_save_state) + tool_bar.addAction(self.action_restore_state) + self.dock_manager.addDockWidget(QtAds.BottomDockWidgetArea, file_system_widget) + file_system_widget = create_file_system_tree_dock_widget(view_menu) + tool_bar = file_system_widget.createDefaultToolBar() + tool_bar.addAction(self.action_save_state) + tool_bar.addAction(self.action_restore_state) + file_system_widget.setFeature(QtAds.CDockWidget.DockWidgetMovable, False) + top_dock_area = self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, file_system_widget) + dock_widget = create_calendar_dock_widget(view_menu) + dock_widget.setFeature(QtAds.CDockWidget.DockWidgetClosable, False) + dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna") + self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea, dock_widget, top_dock_area) + + # Test dock area docking + right_dock_area = self.dock_manager.addDockWidget( + QtAds.RightDockWidgetArea, + create_long_text_label_dock_widget(view_menu), top_dock_area) + self.dock_manager.addDockWidget( + QtAds.TopDockWidgetArea, + create_long_text_label_dock_widget(view_menu), right_dock_area) + + bottom_dock_area = self.dock_manager.addDockWidget( + QtAds.BottomDockWidgetArea, + create_long_text_label_dock_widget(view_menu), right_dock_area) + + self.dock_manager.addDockWidget( + QtAds.RightDockWidgetArea, + create_long_text_label_dock_widget(view_menu), right_dock_area) + self.dock_manager.addDockWidget( + QtAds.CenterDockWidgetArea, + create_long_text_label_dock_widget(view_menu), bottom_dock_area) + + def save_state(self): + ''' + Saves the dock manager state and the main window geometry + ''' + settings = QSettings("Settings.ini", QSettings.IniFormat) + settings.setValue("mainWindow/Geometry", self.saveGeometry()) + settings.setValue("mainWindow/State", self.saveState()) + settings.setValue("mainWindow/DockingState", self.dock_manager.saveState()) + + def save_perspectives(self): + ''' + Save the list of perspectives + ''' + settings = QSettings("Settings.ini", QSettings.IniFormat) + self.dock_manager.savePerspectives(settings) + + def restore_state(self): + ''' + Restores the dock manager state + ''' + settings = QSettings("Settings.ini", QSettings.IniFormat) + geom = settings.value("mainWindow/Geometry") + if geom is not None: + self.restoreGeometry(geom) + + state = settings.value("mainWindow/State") + if state is not None: + self.restoreState(state) + + state = settings.value("mainWindow/DockingState") + if state is not None: + self.dock_manager.restore_state(state) + + def restore_perspectives(self): + ''' + Restore the perspective listo of the dock manager + ''' + settings = QSettings("Settings.ini", QSettings.IniFormat) + self.dock_manager.loadPerspectives(settings) + self.perspective_combo_box.clear() + self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames()) + + def save_perspective(self): + perspective_name, ok = QInputDialog.getText(self, 'Save perspective', 'Enter unique name:') + if ok and perspective_name: + self.dock_manager.addPerspective(perspective_name) + _ = QSignalBlocker(self.perspective_combo_box) + self.perspective_combo_box.clear() + self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames()) + self.perspective_combo_box.setCurrentText(perspective_name) + self.save_perspectives() + + +def main(app_): + main_window = MainWindow() + main_window.show() + state = main_window.dock_manager.saveState() + # print('This is what the saved state looks like in XML:') + # print(str(state, 'utf-8')) + # print() + # main_window.dock_manager.restore_state(state) + return main_window + + +if __name__ == '__main__': + # logging.basicConfig(level='DEBUG') + QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) + QGuiApplication.setAttribute(Qt.AA_EnableHighDpiScaling) + app = QtWidgets.QApplication([]) + window = main(app) + window.show() + app.exec_() diff --git a/recipes/meta.yaml b/recipes/meta.yaml new file mode 100644 index 0000000..d7ee54b --- /dev/null +++ b/recipes/meta.yaml @@ -0,0 +1,41 @@ +{% set data = load_setup_py_data() %} + +package: + name: pyqtads + version: {{ data.get('version') }} + +source: + path: ../ + +build: + number: 0 + script: python setup.py install --single-version-externally-managed --record=record.txt --conda-recipe + +requirements: + build: + - python + - setuptools + - pyqt>=5.9 + - sip>=4.19 + run: + - python + - pyqt>=5.9 + - sip>=4.19 + - pywin32 [win] + +test: + imports: + - PyQtAds + +about: + home: {{ data.get('url') }} + license: {{ data.get('license') }} + license_family: LGPL + license_file: 'LICENSE.md' + summary: {{ data.get('description') }} + description: {{ data.get('description') }} + doc_url: '' + dev_url: {{ data.get('url') }} + +extra: + recipe-maintainers: 'nicolas.elie@cnrs.fr' diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1918272 --- /dev/null +++ b/setup.py @@ -0,0 +1,342 @@ +import os +import sys +import shlex +import subprocess +import glob + +from setuptools import setup, find_packages +from setuptools.extension import Extension +from distutils import sysconfig, dir_util, spawn, log +from distutils.dep_util import newer +import sipdistutils +import sipconfig +from PyQt5.QtCore import PYQT_CONFIGURATION +from PyQt5.pyrcc_main import processResourceFile + +MAJOR = 2 +MINOR = 5 +MICRO = 1 +ISRELEASED = True +VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) +MODULE_NAME = "ads" +SRC_PATH = "PyQtAds" + +REQUIRE_PYQT = True +if "--conda-recipe" in sys.argv: + REQUIRE_PYQT = False + sys.argv.remove("--conda-recipe") + + +class HostPythonConfiguration(object): + def __init__(self): + self.platform = sys.platform + self.version = sys.hexversion>>8 + + self.inc_dir = sysconfig.get_python_inc() + self.venv_inc_dir = sysconfig.get_python_inc(prefix=sys.prefix) + self.module_dir = sysconfig.get_python_lib(plat_specific=1) + + if sys.platform == 'win32': + self.data_dir = sys.prefix + self.lib_dir = sys.prefix +'\\libs' + else: + self.data_dir = sys.prefix + '/share' + self.lib_dir = sys.prefix + '/lib' + + +class TargetQtConfiguration(object): + def __init__(self, qmake): + pipe = os.popen(' '.join([qmake, '-query'])) + + for l in pipe: + l = l.strip() + + tokens = l.split(':', 1) + if isinstance(tokens, list): + if len(tokens) != 2: + error("Unexpected output from qmake: '%s'\n" % l) + + name, value = tokens + else: + name = tokens + value = None + + name = name.replace('/', '_') + setattr(self, name, value) + + pipe.close() + + +class build_ext(sipdistutils.build_ext): + + description = "Builds the " + MODULE_NAME + " module." + + user_options = sipdistutils.build_ext.user_options + [ + ('qmake-bin=', None, "Path to qmake binary"), + ('sip-bin=', None, "Path to sip binary"), + ('qt-include-dir=', None, "Path to Qt headers"), + ('pyqt-sip-dir=', None, "Path to PyQt's SIP files"), + ('pyqt-sip-flags=', None, "SIP flags used to generate PyQt bindings"), + ('sip-dir=', None, "Path to module's SIP files"), + ('inc-dir=', None, "Path to module's include files") + ] + + def initialize_options (self): + super().initialize_options() + self.qmake_bin = 'qmake' + self.sip_bin = None + self.qt_include_dir = None + self.qt_libinfix = '' + self.pyqt_sip_dir = None + self.pyqt_sip_flags = None + self.sip_files_dir = None + self.sip_inc_dir = None + self.inc_dir = None + self.pyconfig = HostPythonConfiguration() + self.qtconfig = TargetQtConfiguration(self.qmake_bin) + self.config = sipconfig.Configuration() + self.config.default_mod_dir = ("/usr/local/lib/python%i.%i/dist-packages" % + (sys.version_info.major, sys.version_info.minor)) + + def finalize_options (self): + super().finalize_options() + + if not self.qt_include_dir: + self.qt_include_dir = self.qtconfig.QT_INSTALL_HEADERS + + if not self.qt_libinfix: + try: + with open(os.path.join(self.qtconfig.QT_INSTALL_PREFIX, 'mkspecs', 'qconfig.pri'), 'r') as f: + for line in f.readlines(): + if line.startswith('QT_LIBINFIX'): + self.qt_libinfix = line.split('=')[1].strip('\n').strip() + except (FileNotFoundError, IndexError): + pass + + if not self.pyqt_sip_dir: + self.pyqt_sip_dir = os.path.join(self.pyconfig.data_dir, 'sip', 'PyQt5') + + if not self.pyqt_sip_flags: + self.pyqt_sip_flags = PYQT_CONFIGURATION.get('sip_flags', '') + + if not self.sip_files_dir: + self.sip_files_dir = os.path.abspath(os.path.join(".", "sip")) + + if not self.sip_inc_dir: + self.sip_inc_dir = self.pyconfig.venv_inc_dir + + if not self.inc_dir: + self.inc_dir = os.path.abspath(os.path.join(".", "src")) + + if not self.qt_include_dir: + raise SystemExit('Could not find Qt5 headers. ' + 'Please specify via --qt-include-dir=') + + if not self.pyqt_sip_dir: + raise SystemExit('Could not find PyQt SIP files. ' + 'Please specify containing directory via ' + '--pyqt-sip-dir=') + + if not self.pyqt_sip_flags: + raise SystemExit('Could not find PyQt SIP flags. ' + 'Please specify via --pyqt-sip-flags=') + + def _find_sip(self): + """override _find_sip to allow for manually speficied sip path.""" + return self.sip_bin or super()._find_sip() + + def _sip_compile(self, sip_bin, source, sbf): + cmd = [sip_bin] + if hasattr(self, 'sip_opts'): + cmd += self.sip_opts + if hasattr(self, '_sip_sipfiles_dir'): + cmd += ['-I', self._sip_sipfiles_dir()] + cmd += [ + "-I", self.sip_files_dir, + "-I", self.pyqt_sip_dir, + "-I", self.sip_inc_dir, + "-I", self.inc_dir, + "-c", self._sip_output_dir(), + "-b", sbf, + "-w", "-o"] + + cmd += shlex.split(self.pyqt_sip_flags) # use same SIP flags as for PyQt5 + cmd.append(source) + self.spawn(cmd) + + def swig_sources (self, sources, extension=None): + if not self.extensions: + return + + # Add the local include directory to the include path + if extension is not None: + extension.extra_compile_args += ['-D', 'QT_CORE_LIB', + '-D', 'QT_GUI_LIB', + '-D', 'QT_WIDGETS_LIB', + '-D', 'ADS_SHARED_EXPORT'] + extension.include_dirs += [self.qt_include_dir, self.inc_dir, + os.path.join(self.qt_include_dir, 'QtCore'), + os.path.join(self.qt_include_dir, 'QtGui'), + os.path.join(self.qt_include_dir, 'QtWidgets')] + extension.libraries += ['Qt5Core' + self.qt_libinfix, + 'Qt5Gui' + self.qt_libinfix, + 'Qt5Widgets' + self.qt_libinfix] + + if sys.platform == 'win32': + extension.library_dirs += [self.qtconfig.QT_INSTALL_LIBS, + self.inc_dir, self._sip_output_dir()] + elif sys.platform == 'darwin': + extension.extra_compile_args += ['-F' + self.qtconfig.QT_INSTALL_LIBS, + '-std=c++11', '-stdlib=libc++', '-mmacosx-version-min=10.9'] + extension.extra_link_args += ['-F' + self.qtconfig.QT_INSTALL_LIBS, + '-mmacosx-version-min=10.9'] + elif sys.platform == 'linux': + extension.extra_compile_args += ['-std=c++11'] + + return super().swig_sources(sources, extension) + + def build_extension(self, ext): + cppsources = [source for source in ext.sources if source.endswith(".cpp")] + + dir_util.mkpath(self.build_temp, dry_run=self.dry_run) + + # Run moc on all header files. + for source in cppsources: + header = source.replace(".cpp", ".h") + if os.path.exists(header): + moc_file = "moc_" + os.path.basename(header).replace(".h", ".cpp") + out_file = os.path.join(self.build_temp, moc_file) + + if newer(header, out_file) or self.force: + call_arg = ["moc", "-o", out_file, header] + spawn.spawn(call_arg, dry_run=self.dry_run) + + if os.path.getsize(out_file) > 0: + ext.sources.append(out_file) + + # Add the temp build directory to include path, for compiler to find + # the created .moc files + ext.include_dirs += [self._sip_output_dir()] + + sipdistutils.build_ext.build_extension(self, ext) + + +def git_version(): + '''Return the git revision as a string''' + + def _minimal_ext_cmd(cmd): + # construct minimal environment + env = {} + for k in ['SYSTEMROOT', 'PATH', 'HOME']: + v = os.environ.get(k) + if v is not None: + env[k] = v + # LANGUAGE is used on win32 + env['LANGUAGE'] = 'C' + env['LANG'] = 'C' + env['LC_ALL'] = 'C' + out = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env).communicate()[0] + return out + + try: + out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD']) + GIT_REVISION = out.strip().decode('ascii') + except OSError: + GIT_REVISION = "Unknown" + + return GIT_REVISION + + +def get_version_info(): + # Adding the git rev number needs to be done inside write_version_py(), + # otherwise the import of numpy.version messes up the build under Python 3. + FULLVERSION = VERSION + if os.path.exists('.git'): + GIT_REVISION = git_version() + elif os.path.exists(os.path.join(SRC_PATH, 'version.py')): + # must be a source distribution, use existing version file + try: + from PyQtAds.version import git_revision as GIT_REVISION + except ImportError: + raise ImportError("Unable to import git_revision. Try removing " \ + "%(module)/version.py and the build directory " \ + "before building." % {'module': SRC_PATH}) + else: + GIT_REVISION = "Unknown" + + if not ISRELEASED: + FULLVERSION += '.dev0+' + GIT_REVISION[:7] + + return FULLVERSION, GIT_REVISION + + +def write_version_py(filename=os.path.join(SRC_PATH, '_version.py')): + cnt = ("# THIS FILE IS GENERATED FROM %(module)s SETUP.PY\n\n" + "short_version = '%(version)s'\n" + "version = '%(version)s'\n" + "full_version = '%(full_version)s'\n" + "git_revision = '%(git_revision)s'\n" + "release = %(isrelease)s\n" + "if not release:\n" + " version = full_version\n") + FULLVERSION, GIT_REVISION = get_version_info() + + with open(filename, 'w') as f: + f.write(cnt % {'module': SRC_PATH, + 'version': VERSION, + 'full_version': FULLVERSION, + 'git_revision': GIT_REVISION, + 'isrelease': str(ISRELEASED)}) + +setup_requires = ["PyQt5"] if REQUIRE_PYQT else [] +cpp_sources = glob.glob(os.path.join('src', '*.cpp')) +sip_sources = [os.path.join('sip', MODULE_NAME + '.sip')] +if sys.platform == 'linux': + cpp_sources += glob.glob(os.path.join('src', 'linux', '*.cpp')) +ext_modules = [Extension('PyQtAds.QtAds.ads', cpp_sources + sip_sources)] + +install_requires = ["PyQt5"] +if sys.platform == 'win32': + install_requires.append("pywin32") + + +write_version_py(os.path.join(SRC_PATH, '_version.py')) +processResourceFile([os.path.join('src', 'ads.qrc')], + os.path.join(SRC_PATH, 'rc.py'), False) +with open('README.md', 'r') as f: + LONG_DESCRIPTION = f.read() + +setup( + name = SRC_PATH, + author = "Nicolas Elie", + author_email = "nicolas.elie@cnrs.fr", + url = "https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System", + version = get_version_info()[0], + description = "Advanced Docking System for Qt", + long_description = LONG_DESCRIPTION, + keywords = ["qt"], + license = "LGPLv2+", + classifiers = ["Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)", + "Operating System :: OS Independent", + "Topic :: Software Development :: Libraries :: Python Modules", + "Environment :: Win32 (MS Windows)", + "Environment :: MacOS X", + "Environment :: X11 Applications :: Qt", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.2", + "Programming Language :: Python :: 3.3", + "Programming Language :: Python :: 3.4", + "Programming Language :: Python :: 3.5", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7"], + ext_modules = ext_modules, + cmdclass = { + 'build_ext': build_ext, + }, + packages = find_packages(), + setup_requires = setup_requires, + install_requires = install_requires, + zip_safe=False +) diff --git a/simple.py b/simple.py new file mode 100644 index 0000000..9fff924 --- /dev/null +++ b/simple.py @@ -0,0 +1,82 @@ +import logging + +from PyQt5 import QtWidgets, QtCore +from PyQt5.QtCore import Qt +from PyQtAds import QtAds + + +class MainWindow(QtWidgets.QMainWindow): + def __init__(self, parent=None): + super().__init__(parent) + self.setup_ui() + self.dock_manager = QtAds.CDockManager(self) + + self.dock_widgets = [] + + for label_text, area in ( + ('1 Top', QtAds.TopDockWidgetArea), + ('2 Bottom', QtAds.BottomDockWidgetArea), + ('3 Left', QtAds.LeftDockWidgetArea), + ('4 Right', QtAds.RightDockWidgetArea), + ): + # Create example content label - this can be any application specific + # widget + label = QtWidgets.QLabel() + label.setWordWrap(True) + label.setAlignment(Qt.AlignTop | Qt.AlignLeft) + label.setText(f"{label_text}: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ") + + # Create a dock widget with the title Label 1 and set the created label + # as the dock widget content + dock_widget = QtAds.CDockWidget(label_text) + dock_widget.setWidget(label) + self.dock_widgets.append(dock_widget) + + # Add the toggleViewAction of the dock widget to the menu to give + # the user the possibility to show the dock widget if it has been closed + self.menu_view.addAction(dock_widget.toggleViewAction()) + + # Add the dock widget to the top dock widget area + self.dock_manager.addDockWidget(area, dock_widget) + + def setup_ui(self): + self.setWindowTitle("MainWindow") + self.setObjectName("MainWindow") + self.resize(400, 300) + self.central_widget = QtWidgets.QWidget(self) + self.central_widget.setObjectName("central_widget") + self.setCentralWidget(self.central_widget) + + self.menu_bar = QtWidgets.QMenuBar(self) + self.menu_bar.setGeometry(QtCore.QRect(0, 0, 400, 21)) + self.menu_bar.setObjectName("menuBar") + + self.menu_view = QtWidgets.QMenu(self.menu_bar) + self.menu_view.setObjectName("menu_view") + self.menu_view.setTitle("View") + self.setMenuBar(self.menu_bar) + + self.status_bar = QtWidgets.QStatusBar(self) + self.status_bar.setObjectName("statusBar") + self.setStatusBar(self.status_bar) + self.menu_bar.addAction(self.menu_view.menuAction()) + + +def main(app): + main = MainWindow() + main.show() + state = main.dock_manager.saveState() + print('This is what the saved state looks like in XML:') + print(state) + print() + main.dock_manager.restoreState(state) + return main + + +if __name__ == '__main__': + logging.basicConfig(level='DEBUG') + app = QtWidgets.QApplication([]) + window = main(app) + window.show() + print('shown') + app.exec_() diff --git a/sip/DockAreaTabBar.sip b/sip/DockAreaTabBar.sip new file mode 100644 index 0000000..09de7e1 --- /dev/null +++ b/sip/DockAreaTabBar.sip @@ -0,0 +1,56 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockAreaTabBar : QScrollArea +{ + %TypeHeaderCode + #include + %End + +protected: + virtual void wheelEvent(QWheelEvent* Event); + virtual void mousePressEvent(QMouseEvent* ev); + virtual void mouseReleaseEvent(QMouseEvent* ev); + virtual void mouseMoveEvent(QMouseEvent* ev); + virtual void mouseDoubleClickEvent(QMouseEvent *event); + void startFloating(const QPoint& Offset); + ads::CFloatingDockContainer* makeAreaFloating(const QPoint& Offset, + ads::eDragState DragState); + +public: + CDockAreaTabBar(ads::CDockAreaWidget* parent /TransferThis/); + virtual ~CDockAreaTabBar(); + void insertTab(int Index, ads::CDockWidgetTab* Tab /Transfer/); + void removeTab(ads::CDockWidgetTab* Tab) /TransferBack/; + int count() const; + int currentIndex() const; + ads::CDockWidgetTab* currentTab() const; + ads::CDockWidgetTab* tab(int Index) const; + virtual bool eventFilter(QObject *watched, QEvent *event); + bool isTabOpen(int Index) const; + virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + +public slots: + void setCurrentIndex(int Index); + void closeTab(int Index); + +signals: + void currentChanging(int Index); + void currentChanged(int Index); + void tabBarClicked(int index); + void tabCloseRequested(int index); + void tabClosed(int index); + void tabOpened(int index); + void tabMoved(int from, int to); + void removingTab(int index); + void tabInserted(int index); +}; + +}; + +%End \ No newline at end of file diff --git a/sip/DockAreaTitleBar.sip b/sip/DockAreaTitleBar.sip new file mode 100644 index 0000000..98638ab --- /dev/null +++ b/sip/DockAreaTitleBar.sip @@ -0,0 +1,32 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockAreaTitleBar : QFrame +{ + %TypeHeaderCode + #include + %End + +public slots: + void markTabsMenuOutdated(); + + +public: + CDockAreaTitleBar(ads::CDockAreaWidget* parent /TransferThis/); + virtual ~CDockAreaTitleBar(); + ads::CDockAreaTabBar* tabBar() const; + QAbstractButton* button(ads::TitleBarButton which) const; + virtual void setVisible(bool Visible); + + +signals: + void tabBarClicked(int index); +}; + +}; + +%End diff --git a/sip/DockAreaWidget.sip b/sip/DockAreaWidget.sip new file mode 100644 index 0000000..3ac93ec --- /dev/null +++ b/sip/DockAreaWidget.sip @@ -0,0 +1,65 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockAreaWidget : QFrame +{ + + %TypeHeaderCode + #include + %End + +protected: + void insertDockWidget(int index, ads::CDockWidget* DockWidget /Transfer/, bool Activate = true); + void addDockWidget(ads::CDockWidget* DockWidget /Transfer/); + void removeDockWidget(ads::CDockWidget* DockWidget) /TransferBack/; + void toggleDockWidgetView(ads::CDockWidget* DockWidget, bool Open); + CDockWidget* nextOpenDockWidget(ads::CDockWidget* DockWidget) const; + int index(ads::CDockWidget* DockWidget); + void hideAreaWithNoVisibleContent(); + void updateTitleBarVisibility(); + void internalSetCurrentDockWidget(ads::CDockWidget* DockWidget /Transfer/); + void markTitleBarMenuOutdated(); + +protected slots: + void toggleView(bool Open); + +public: + CDockAreaWidget(ads::CDockManager* DockManager /TransferThis/, ads::CDockContainerWidget* parent /TransferThis/); + virtual ~CDockAreaWidget(); + ads::CDockManager* dockManager() const; + ads::CDockContainerWidget* dockContainer() const; + QRect titleBarGeometry() const; + QRect contentAreaGeometry() const; + int dockWidgetsCount() const; + QList dockWidgets() const; + int openDockWidgetsCount() const; + QList openedDockWidgets() const; + ads::CDockWidget* dockWidget(int Index) const; + int currentIndex() const; + int indexOfFirstOpenDockWidget() const; + ads::CDockWidget* currentDockWidget() const; + void setCurrentDockWidget(ads::CDockWidget* DockWidget /Transfer/); + void saveState(QXmlStreamWriter& Stream) const; + ads::CDockWidget::DockWidgetFeatures features() const; + QAbstractButton* titleBarButton(ads::TitleBarButton which) const; + virtual void setVisible(bool Visible); + +public slots: + void setCurrentIndex(int index); + void closeArea(); + void closeOtherAreas(); + +signals: + void tabBarClicked(int index); + void currentChanging(int index); + void currentChanged(int index); + void viewToggled(bool Open); +}; + +}; + +%End diff --git a/sip/DockContainerWidget.sip b/sip/DockContainerWidget.sip new file mode 100644 index 0000000..e6ec964 --- /dev/null +++ b/sip/DockContainerWidget.sip @@ -0,0 +1,154 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +/** + * Container that manages a number of dock areas with single dock widgets + * or tabyfied dock widgets in each area. + * Each window that support docking has a DockContainerWidget. That means + * the main application window and all floating windows are ore contain + * an DockContainerWidget. + */ +class CDockContainerWidget : QFrame +{ + %TypeHeaderCode + #include + %End + +protected: + virtual bool event(QEvent *e); + QSplitter* rootSplitter() const; + void createRootSplitter(); + void dropFloatingWidget(ads::CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos); + void addDockArea(ads::CDockAreaWidget* DockAreaWidget /Transfer/, ads::DockWidgetArea area = ads::CenterDockWidgetArea); + void removeDockArea(ads::CDockAreaWidget* area /Transfer/); + void saveState(QXmlStreamWriter& Stream) const; + bool restoreState(QXmlStreamReader& Stream, bool Testing); + ads::CDockAreaWidget* lastAddedDockAreaWidget(ads::DockWidgetArea area) const; + bool hasTopLevelDockWidget() const; + ads::CDockWidget* topLevelDockWidget() const; + ads::CDockAreaWidget* topLevelDockArea() const; + QList dockWidgets() const; + +public: + /** + * Default Constructor + */ + CDockContainerWidget(ads::CDockManager* DockManager /TransferThis/, QWidget* parent /TransferThis/ = 0); + + /** + * Virtual Destructor + */ + virtual ~CDockContainerWidget(); + + /** + * Adds dockwidget into the given area. + * If DockAreaWidget is not null, then the area parameter indicates the area + * into the DockAreaWidget. If DockAreaWidget is null, the Dockwidget will + * be dropped into the container. + * \return Returns the dock area widget that contains the new DockWidget + */ + ads::CDockAreaWidget* addDockWidget(ads::DockWidgetArea area, ads::CDockWidget* Dockwidget /Transfer/, + ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0); + + /** + * Removes dockwidget + */ + void removeDockWidget(ads::CDockWidget* Dockwidget) /TransferBack/; + + /** + * Returns the current zOrderIndex + */ + virtual unsigned int zOrderIndex() const; + + /** + * This function returns true if this container widgets z order index is + * higher than the index of the container widget given in Other parameter + */ + bool isInFrontOf(ads::CDockContainerWidget* Other) const; + + /** + * Returns the dock area at teh given global position or 0 if there is no + * dock area at this position + */ + ads::CDockAreaWidget* dockAreaAt(const QPoint& GlobalPos) const; + + /** + * Returns the dock area at the given Index or 0 if the index is out of + * range + */ + ads::CDockAreaWidget* dockArea(int Index) const; + + /** + * Returns the list of dock areas that are not closed + * If all dock widgets in a dock area are closed, the dock area will be closed + */ + QList openedDockAreas() const; + + /** + * Returns the number of dock areas in this container + */ + int dockAreaCount() const; + + /** + * Returns the number of visible dock areas + */ + int visibleDockAreaCount() const; + + /** + * This function returns true, if this container is in a floating widget + */ + bool isFloating() const; + + /** + * Dumps the layout for debugging purposes + */ + void dumpLayout(); + + /** + * This functions returns the dock widget features of all dock widget in + * this container. + * A bitwise and is used to combine the flags of all dock widgets. That + * means, if only dock widget does not support a certain flag, the whole + * dock are does not support the flag. + */ + ads::CDockWidget::DockWidgetFeatures features() const; + + /** + * If this dock container is in a floating widget, this function returns + * the floating widget. + * Else, it returns a nullptr. + */ + ads::CFloatingDockContainer* floatingWidget() const; + + /** + * Call this function to close all dock areas except the KeepOpenArea + */ + void closeOtherAreas(ads::CDockAreaWidget* KeepOpenArea); + +signals: + /** + * This signal is emitted if one or multiple dock areas has been added to + * the internal list of dock areas. + * If multiple dock areas are inserted, this signal is emitted only once + */ + void dockAreasAdded(); + + /** + * This signal is emitted if one or multiple dock areas has been removed + */ + void dockAreasRemoved(); + + /** + * This signal is emitted if a dock area is opened or closed via + * toggleView() function + */ + void dockAreaViewToggled(ads::CDockAreaWidget* DockArea, bool Open); +}; // class DockContainerWidget +}; + // namespace ads + +%End diff --git a/sip/DockManager.sip b/sip/DockManager.sip new file mode 100644 index 0000000..2ce20ca --- /dev/null +++ b/sip/DockManager.sip @@ -0,0 +1,205 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +%MappedType QMap + /TypeHint="Dict[QString, CDockWidget*]", TypeHintValue="{}"/ +{ +%TypeHeaderCode +#include +%End + +%ConvertFromTypeCode + PyObject *d = PyDict_New(); + + if (!d) + return 0; + + QMap::const_iterator it = sipCpp->constBegin(); + QMap::const_iterator end = sipCpp->constEnd(); + + while (it != end) + { + QString *k = new QString(it.key()); + PyObject *kobj = sipConvertFromType(k, sipType_QString, + sipTransferObj); + + if (!kobj) + { + delete k; + Py_DECREF(d); + + return 0; + } + + PyObject *vobj = sipConvertFromType(it.value(), sipType_ads_CDockWidget, + sipTransferObj); + + if (!vobj) + { + Py_DECREF(kobj); + Py_DECREF(d); + + return 0; + } + + int rc = PyDict_SetItem(d, kobj, vobj); + + Py_DECREF(vobj); + Py_DECREF(kobj); + + if (rc < 0) + { + Py_DECREF(d); + + return 0; + } + + ++it; + } + + return d; +%End + +%ConvertToTypeCode + if (!sipIsErr) + return PyDict_Check(sipPy); + + QMap *qm = new QMap; + + Py_ssize_t pos = 0; + PyObject *kobj, *vobj; + while (PyDict_Next(sipPy, &pos, &kobj, &vobj)) + { + int kstate; + QString *k = reinterpret_cast( + sipForceConvertToType(kobj, sipType_QString, sipTransferObj, + SIP_NOT_NONE, &kstate, sipIsErr)); + + if (*sipIsErr) + { + PyErr_Format(PyExc_TypeError, + "a dict key has type '%s' but '_TYPE1_' is expected", + sipPyTypeName(Py_TYPE(kobj))); + + delete qm; + + return 0; + } + + int vstate; + ads::CDockWidget *v = reinterpret_cast( + sipForceConvertToType(vobj, sipType_ads_CDockWidget, sipTransferObj, + SIP_NOT_NONE, &vstate, sipIsErr)); + + if (*sipIsErr) + { + PyErr_Format(PyExc_TypeError, + "a dict value has type '%s' but '_TYPE2_' is expected", + sipPyTypeName(Py_TYPE(vobj))); + + sipReleaseType(k, sipType_QString, kstate); + delete qm; + + return 0; + } + + qm->insert(*k, v); + + sipReleaseType(v, sipType_ads_CDockWidget, vstate); + sipReleaseType(k, sipType_QString, kstate); + } + + *sipCppPtr = qm; + + return sipGetState(sipTransferObj); +%End +}; + +namespace ads +{ + +class CDockManager : ads::CDockContainerWidget +{ + + %TypeHeaderCode + #include + %End + +protected: + void registerFloatingWidget(ads::CFloatingDockContainer* FloatingWidget /Transfer/); + void removeFloatingWidget(ads::CFloatingDockContainer* FloatingWidget) /TransferBack/; + void registerDockContainer(ads::CDockContainerWidget* DockContainer /Transfer/); + void removeDockContainer(ads::CDockContainerWidget* DockContainer /TransferBack/); + ads::CDockOverlay* containerOverlay() const; + ads::CDockOverlay* dockAreaOverlay() const; + +public: + enum eViewMenuInsertionOrder + { + MenuSortedByInsertion, + MenuAlphabeticallySorted + }; + + enum eConfigFlag + { + ActiveTabHasCloseButton, + DockAreaHasCloseButton, + DockAreaCloseButtonClosesTab, + OpaqueSplitterResize, + XmlAutoFormattingEnabled, + XmlCompressionEnabled, + TabCloseButtonIsToolButton, + AllTabsHaveCloseButton, + RetainTabSizeWhenCloseButtonHidden, + DefaultConfig, + }; + typedef QFlags ConfigFlags; + + CDockManager(QWidget* parent /TransferThis/ = 0); + virtual ~CDockManager(); + static ads::CDockManager::ConfigFlags configFlags(); + static void setConfigFlags(const ads::CDockManager::ConfigFlags Flags); + static void setConfigFlag(ads::CDockManager::eConfigFlag Flag, bool On = true); + ads::CDockAreaWidget* addDockWidget(ads::DockWidgetArea area, ads::CDockWidget* Dockwidget /Transfer/, + ads::CDockAreaWidget* DockAreaWidget /Transfer/ = 0); + ads::CDockAreaWidget* addDockWidgetTab(ads::DockWidgetArea area, + ads::CDockWidget* Dockwidget /Transfer/); + ads::CDockAreaWidget* addDockWidgetTabToArea(ads::CDockWidget* Dockwidget /Transfer/, + ads::CDockAreaWidget* DockAreaWidget /Transfer/); + ads::CDockWidget* findDockWidget(const QString& ObjectName) const; + void removeDockWidget(ads::CDockWidget* Dockwidget) /TransferBack/; + QMap dockWidgetsMap() const; + const QList dockContainers() const; + const QList floatingWidgets() const; + virtual unsigned int zOrderIndex() const; + QByteArray saveState(int version = 0) const; + bool restoreState(const QByteArray &state, int version = 0); + void addPerspective(const QString& UniquePrespectiveName); + void removePerspective(const QString& Name); + void removePerspectives(const QStringList& Names); + QStringList perspectiveNames() const; + void savePerspectives(QSettings& Settings) const; + void loadPerspectives(QSettings& Settings); + QAction* addToggleViewActionToMenu(QAction* ToggleViewAction /Transfer/, + const QString& Group = QString(), const QIcon& GroupIcon = QIcon()); + QMenu* viewMenu() const; + void setViewMenuInsertionOrder(ads::CDockManager::eViewMenuInsertionOrder Order); + bool isRestoringState() const; + static int startDragDistance(); + +public slots: + void openPerspective(const QString& PerspectiveName); + +signals: + void perspectiveListChanged(); + void perspectivesRemoved(); + void restoringState(); + void stateRestored(); + void openingPerspective(const QString& PerspectiveName); + void perspectiveOpened(const QString& PerspectiveName); +}; + +}; + +%End \ No newline at end of file diff --git a/sip/DockOverlay.sip b/sip/DockOverlay.sip new file mode 100644 index 0000000..a712a10 --- /dev/null +++ b/sip/DockOverlay.sip @@ -0,0 +1,77 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockOverlay : public QFrame +{ + %TypeHeaderCode + #include + %End + +public: + + enum eMode + { + ModeDockAreaOverlay, + ModeContainerOverlay + }; + + CDockOverlay(QWidget* parent /TransferThis/, eMode Mode = ads::CDockOverlay::ModeDockAreaOverlay); + virtual ~CDockOverlay(); + void setAllowedAreas(ads::DockWidgetAreas areas); + ads::DockWidgetAreas allowedAreas() const; + ads::DockWidgetArea dropAreaUnderCursor() const; + ads::DockWidgetArea showOverlay(QWidget* target); + void hideOverlay(); + void enableDropPreview(bool Enable); + QRect dropOverlayRect() const; + virtual bool event(QEvent *e); + +protected: + virtual void paintEvent(QPaintEvent *e); + virtual void showEvent(QShowEvent* e); + virtual void hideEvent(QHideEvent* e); +}; + + +class CDockOverlayCross : public QWidget +{ + +public: + enum eIconColor + { + FrameColor, + WindowBackgroundColor, + OverlayColor, + ArrowColor, + ShadowColor + }; + +protected: + QString iconColors() const; + QColor iconColor() const; + void setIconFrameColor(const QColor& Color); + void setIconBackgroundColor(const QColor& Color); + void setIconOverlayColor(const QColor& Color); + void setIconArrowColor(const QColor& Color); + void setIconShadowColor(const QColor& Color); + +public: + CDockOverlayCross(ads::CDockOverlay* overlay /TransferThis/); + virtual ~CDockOverlayCross(); + void setIconColor(ads::CDockOverlayCross::eIconColor ColorIndex, const QColor& Color); + QColor iconColor(ads::CDockOverlayCross::eIconColor ColorIndex) const; + ads::DockWidgetArea cursorLocation() const; + void setupOverlayCross(ads::CDockOverlay::eMode Mode); + void updateOverlayIcons(); + void reset(); + void updatePosition(); + void setIconColors(const QString& Colors); +}; + +}; + +%End diff --git a/sip/DockSplitter.sip b/sip/DockSplitter.sip new file mode 100644 index 0000000..82775ef --- /dev/null +++ b/sip/DockSplitter.sip @@ -0,0 +1,23 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockSplitter : QSplitter +{ + %TypeHeaderCode + #include + %End + +public: + CDockSplitter(QWidget *parent /TransferThis/ = 0); + CDockSplitter(Qt::Orientation orientation, QWidget *parent /TransferThis/ = 0); + virtual ~CDockSplitter(); + bool hasVisibleContent() const; +}; + +}; + +%End diff --git a/sip/DockWidget.sip b/sip/DockWidget.sip new file mode 100644 index 0000000..9dfb78e --- /dev/null +++ b/sip/DockWidget.sip @@ -0,0 +1,101 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockWidget : QFrame +{ + %TypeHeaderCode + #include + %End + +protected: + void setDockManager(ads::CDockManager* DockManager /Transfer/); + void setDockArea(ads::CDockAreaWidget* DockArea /Transfer/); + void setToggleViewActionChecked(bool Checked); + void saveState(QXmlStreamWriter& Stream) const; + void flagAsUnassigned(); + static void emitTopLevelEventForWidget(ads::CDockWidget* TopLevelDockWidget, bool Floating); + void emitTopLevelChanged(bool Floating); + void setClosedState(bool Closed); + void toggleViewInternal(bool Open); + +public: + enum DockWidgetFeature + { + DockWidgetClosable, + DockWidgetMovable, + DockWidgetFloatable, + AllDockWidgetFeatures, + NoDockWidgetFeatures + }; + typedef QFlags DockWidgetFeatures; + + enum eState + { + StateHidden, + StateDocked, + StateFloating + }; + + enum eInsertMode + { + AutoScrollArea, + ForceScrollArea, + ForceNoScrollArea + }; + + enum eToggleViewActionMode + { + ActionModeToggle, + ActionModeShow + }; + + + CDockWidget(const QString &title, QWidget* parent /TransferThis/ = 0); + virtual ~CDockWidget(); + virtual QSize minimumSizeHint() const; + void setWidget(QWidget* widget /Transfer/, ads::CDockWidget::eInsertMode InsertMode = AutoScrollArea); + QWidget* takeWidget() /TransferBack/; + QWidget* widget() const; + ads::CDockWidgetTab* tabWidget() const; + void setFeatures(ads::CDockWidget::DockWidgetFeatures features); + void setFeature(ads::CDockWidget::DockWidgetFeature flag, bool on); + ads::CDockWidget::DockWidgetFeatures features() const; + ads::CDockManager* dockManager() const; + ads::CDockContainerWidget* dockContainer() const; + ads::CDockAreaWidget* dockAreaWidget() const; + bool isFloating() const; + bool isInFloatingContainer() const; + bool isClosed() const; + QAction* toggleViewAction() const; + void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode); + void setIcon(const QIcon& Icon); + QIcon icon() const; + QToolBar* toolBar() const; + QToolBar* createDefaultToolBar(); + void setToolBar(QToolBar* ToolBar); + void setToolBarStyle(Qt::ToolButtonStyle Style, ads::CDockWidget::eState State); + Qt::ToolButtonStyle toolBarStyle(ads::CDockWidget::eState State) const; + void setToolBarIconSize(const QSize& IconSize, ads::CDockWidget::eState State); + QSize toolBarIconSize(eState State) const; + void setTabToolTip(const QString &text); + +public: + virtual bool event(QEvent *e); + +public slots: + void toggleView(bool Open = true); + +signals: + void viewToggled(bool Open); + void closed(); + void titleChanged(const QString& Title); + void topLevelChanged(bool topLevel); +}; + +}; + +%End diff --git a/sip/DockWidgetTab.sip b/sip/DockWidgetTab.sip new file mode 100644 index 0000000..204fb38 --- /dev/null +++ b/sip/DockWidgetTab.sip @@ -0,0 +1,50 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CDockWidgetTab : QFrame +{ + %TypeHeaderCode + #include + %End + +protected: + virtual void mousePressEvent(QMouseEvent* ev); + virtual void mouseReleaseEvent(QMouseEvent* ev); + virtual void mouseMoveEvent(QMouseEvent* ev); + virtual void contextMenuEvent(QContextMenuEvent* ev); + virtual void mouseDoubleClickEvent(QMouseEvent *event); + +public: + CDockWidgetTab(ads::CDockWidget* DockWidget /TransferThis/, QWidget* parent /TransferThis/ = 0); + virtual ~CDockWidgetTab(); + bool isActiveTab() const; + void setActiveTab(bool active); + ads::CDockWidget* dockWidget() const; + void setDockAreaWidget(ads::CDockAreaWidget* DockArea /Transfer/); + ads::CDockAreaWidget* dockAreaWidget() const; + void setIcon(const QIcon& Icon); + const QIcon& icon() const; + QString text() const; + void setText(const QString& title); + bool isClosable() const; + virtual bool event(QEvent *e); + + +public slots: + virtual void setVisible(bool visible); + +signals: + void activeTabChanged(); + void clicked(); + void closeRequested(); + void closeOtherTabsRequested(); + void moved(const QPoint& GlobalPos); +}; // class DockWidgetTab +}; + // namespace ads + +%End diff --git a/sip/ElidingLabel.sip b/sip/ElidingLabel.sip new file mode 100644 index 0000000..aa89a7b --- /dev/null +++ b/sip/ElidingLabel.sip @@ -0,0 +1,40 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CElidingLabel : QLabel +{ + %TypeHeaderCode + #include + %End + +protected: + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void resizeEvent( QResizeEvent *event ); + virtual void mouseDoubleClickEvent( QMouseEvent *ev ); + +public: + CElidingLabel(QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0); + CElidingLabel(const QString& text, QWidget* parent /TransferThis/ = 0, Qt::WindowFlags f = 0); + virtual ~CElidingLabel(); + Qt::TextElideMode elideMode() const; + void setElideMode(Qt::TextElideMode mode); + + +public: + virtual QSize minimumSizeHint() const; + virtual QSize sizeHint() const; + void setText(const QString &text); + QString text() const; + +signals: + void clicked(); + void doubleClicked(); +}; + +}; + +%End diff --git a/sip/FloatingDockContainer.sip b/sip/FloatingDockContainer.sip new file mode 100644 index 0000000..ba30e6f --- /dev/null +++ b/sip/FloatingDockContainer.sip @@ -0,0 +1,50 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + +class CFloatingDockContainer : QWidget +{ + + %TypeHeaderCode + #include + %End + +protected: + void startFloating(const QPoint& DragStartMousePos, const QSize& Size, + ads::eDragState DragState, QWidget* MouseEventHandler); + void startDragging(const QPoint& DragStartMousePos, const QSize& Size, + QWidget* MouseEventHandler); + void finishDragging(); + void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size); + void moveFloating(); + bool restoreState(QXmlStreamReader& Stream, bool Testing); + void updateWindowTitle(); + + +protected: + virtual void changeEvent(QEvent *event); + virtual void moveEvent(QMoveEvent *event); + virtual bool event(QEvent *e); + virtual void closeEvent(QCloseEvent *event); + virtual void hideEvent(QHideEvent *event); + virtual void showEvent(QShowEvent *event); + virtual bool eventFilter(QObject *watched, QEvent *event); + +public: + CFloatingDockContainer(ads::CDockManager* DockManager /TransferThis/); + CFloatingDockContainer(ads::CDockAreaWidget* DockArea /TransferThis/); + CFloatingDockContainer(ads::CDockWidget* DockWidget /TransferThis/); + virtual ~CFloatingDockContainer(); + ads::CDockContainerWidget* dockContainer() const; + bool isClosable() const; + bool hasTopLevelDockWidget() const; + ads::CDockWidget* topLevelDockWidget() const; + QList dockWidgets() const; +}; + +}; + +%End diff --git a/sip/ads.sip b/sip/ads.sip new file mode 100644 index 0000000..8f71957 --- /dev/null +++ b/sip/ads.sip @@ -0,0 +1,20 @@ +%Module(name=PyQtAds.QtAds.ads, call_super_init=True, keyword_arguments="Optional", use_limited_api=True) +%Import QtCore/QtCoremod.sip +%DefaultSupertype sip.simplewrapper +%Platforms {Linux macOS Windows} + +%Include ads_globals.sip +%Include DockWidget.sip +%Include DockAreaTabBar.sip +%Include DockAreaTitleBar.sip +%Include DockAreaWidget.sip +%Include DockContainerWidget.sip +%Include DockManager.sip +%Include DockOverlay.sip +%Include DockSplitter.sip +%Include DockWidgetTab.sip +%Include ElidingLabel.sip +%Include FloatingDockContainer.sip +%If (Linux) + %Include linux/FloatingWidgetTitleBar.sip +%End \ No newline at end of file diff --git a/sip/ads_globals.sip b/sip/ads_globals.sip new file mode 100644 index 0000000..b9451d5 --- /dev/null +++ b/sip/ads_globals.sip @@ -0,0 +1,44 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + %TypeHeaderCode + #include + %End + + enum DockWidgetArea + { + NoDockWidgetArea, + LeftDockWidgetArea, + RightDockWidgetArea, + TopDockWidgetArea, + BottomDockWidgetArea, + CenterDockWidgetArea, + + InvalidDockWidgetArea, + OuterDockAreas, + AllDockAreas + }; + typedef QFlags DockWidgetAreas; + + + enum TitleBarButton + { + TitleBarButtonTabsMenu, + TitleBarButtonUndock, + TitleBarButtonClose + }; + + enum eDragState + { + DraggingInactive, + DraggingMousePressed, + DraggingTab, + DraggingFloatingWidget + }; + +}; + +%End \ No newline at end of file diff --git a/sip/linux/FloatingWidgetTitleBar.sip b/sip/linux/FloatingWidgetTitleBar.sip new file mode 100644 index 0000000..ceeef80 --- /dev/null +++ b/sip/linux/FloatingWidgetTitleBar.sip @@ -0,0 +1,31 @@ +%Import QtWidgets/QtWidgetsmod.sip + +%If (Qt_5_0_0 -) + +namespace ads +{ + %TypeHeaderCode + #include + %End + +class CFloatingWidgetTitleBar : QWidget +{ + +protected: + virtual void mousePressEvent(QMouseEvent *ev); + virtual void mouseReleaseEvent(QMouseEvent *ev); + virtual void mouseMoveEvent(QMouseEvent *ev); + +public: + explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent /TransferThis/ = 0); + virtual ~CFloatingWidgetTitleBar(); + void enableCloseButton(bool Enable); + void setTitle(const QString &Text); + +signals: + void closeRequested(); +}; + +}; + +%End