aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules9
-rw-r--r--.qt-license-check.exclude3
-rw-r--r--MANIFEST.in4
-rw-r--r--README.md57
-rw-r--r--build_history/blacklist.txt6
-rw-r--r--checklibs.py39
-rw-r--r--docs/conf.py42
-rw-r--r--docs/make.bat39
-rw-r--r--examples/3d/simple3d.py164
-rw-r--r--examples/axcontainer/axviewer.py84
-rw-r--r--examples/charts/audio.py128
-rw-r--r--examples/charts/memoryusage.py128
-rwxr-xr-xexamples/corelib/threads/mandelbrot.py349
-rwxr-xr-xexamples/corelib/tools/codecs/codecs.py251
-rwxr-xr-xexamples/corelib/tools/regexp.py195
-rwxr-xr-xexamples/corelib/tools/settingseditor/settingseditor.py722
-rw-r--r--examples/datavisualization/bars3d.py115
-rw-r--r--examples/declarative/extending/chapter1-basics/app.qml64
-rw-r--r--examples/declarative/extending/chapter1-basics/basics.py100
-rw-r--r--examples/declarative/extending/chapter2-methods/app.qml70
-rw-r--r--examples/declarative/extending/chapter2-methods/methods.py105
-rw-r--r--examples/declarative/extending/chapter3-bindings/app.qml78
-rw-r--r--examples/declarative/extending/chapter3-bindings/bindings.py110
-rw-r--r--examples/declarative/extending/chapter4-customPropertyTypes/app.qml60
-rw-r--r--examples/declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py115
-rw-r--r--examples/declarative/extending/chapter5-listproperties/app.qml70
-rw-r--r--examples/declarative/extending/chapter5-listproperties/listproperties.py128
-rwxr-xr-xexamples/declarative/scrolling.py73
-rw-r--r--examples/declarative/signals/pytoqml1/main.py72
-rw-r--r--examples/declarative/signals/pytoqml1/view.qml73
-rwxr-xr-xexamples/declarative/signals/qmltopy1/main.py89
-rw-r--r--examples/declarative/signals/qmltopy1/view.qml85
-rwxr-xr-xexamples/declarative/signals/qmltopy2/main.py81
-rw-r--r--examples/declarative/signals/qmltopy2/view.qml80
-rw-r--r--examples/declarative/signals/qmltopy3/main.py72
-rw-r--r--examples/declarative/signals/qmltopy3/view.qml103
-rw-r--r--examples/declarative/signals/qmltopy4/main.py72
-rw-r--r--examples/declarative/signals/qmltopy4/view.qml68
-rw-r--r--examples/declarative/usingmodel.py102
-rw-r--r--examples/declarative/view.qml65
-rw-r--r--examples/examples.pyqtc103
-rwxr-xr-xexamples/macextras/macpasteboardmime.py127
-rwxr-xr-xexamples/multimedia/audiooutput.py301
-rw-r--r--examples/multimedia/camera.py170
-rw-r--r--examples/multimedia/player.py158
-rw-r--r--examples/network/blockingfortuneclient.py225
-rwxr-xr-xexamples/network/fortuneclient.py168
-rwxr-xr-xexamples/network/fortuneserver.py125
-rwxr-xr-xexamples/network/threadedfortuneserver.py153
-rwxr-xr-xexamples/opengl/2dpainting.py174
-rw-r--r--examples/opengl/contextinfo.py251
-rw-r--r--examples/opengl/grabber.py436
-rwxr-xr-xexamples/opengl/hellogl.py288
-rwxr-xr-xexamples/opengl/hellogl2.py473
-rwxr-xr-xexamples/opengl/overpainting.py386
-rwxr-xr-xexamples/opengl/samplebuffers.py193
-rw-r--r--examples/opengl/textures/images/side1.pngbin0 -> 1044 bytes
-rw-r--r--examples/opengl/textures/images/side2.pngbin0 -> 1768 bytes
-rw-r--r--examples/opengl/textures/images/side3.pngbin0 -> 2323 bytes
-rw-r--r--examples/opengl/textures/images/side4.pngbin0 -> 1342 bytes
-rw-r--r--examples/opengl/textures/images/side5.pngbin0 -> 1959 bytes
-rw-r--r--examples/opengl/textures/images/side6.pngbin0 -> 2446 bytes
-rwxr-xr-xexamples/opengl/textures/textures.py232
-rw-r--r--examples/opengl/textures/textures.qrc10
-rw-r--r--examples/opengl/textures/textures_rc.py797
-rwxr-xr-xexamples/script/helloscript.py61
-rw-r--r--examples/scriptableapplication/CMakeLists.txt187
-rw-r--r--examples/scriptableapplication/README.CMake.txt28
-rw-r--r--examples/scriptableapplication/README.txt33
-rw-r--r--examples/scriptableapplication/main.cpp64
-rw-r--r--examples/scriptableapplication/mainwindow.cpp141
-rw-r--r--examples/scriptableapplication/mainwindow.h76
-rw-r--r--examples/scriptableapplication/pyside2.pri19
-rw-r--r--examples/scriptableapplication/pyside2_config.py283
-rw-r--r--examples/scriptableapplication/pythonutils.cpp169
-rw-r--r--examples/scriptableapplication/pythonutils.h81
-rw-r--r--examples/scriptableapplication/scriptableapplication.pro90
-rw-r--r--examples/scriptableapplication/scriptableapplication.xml56
-rw-r--r--examples/scriptableapplication/wrappedclasses.h (renamed from sources/pyside2/header.BSD)10
-rw-r--r--examples/texttospeech/texttospeech.py108
-rw-r--r--examples/tutorial/t1.py57
-rw-r--r--examples/tutorial/t10.py192
-rw-r--r--examples/tutorial/t11.py264
-rw-r--r--examples/tutorial/t12.py313
-rw-r--r--examples/tutorial/t13.py396
-rw-r--r--examples/tutorial/t14.py451
-rw-r--r--examples/tutorial/t2.py60
-rw-r--r--examples/tutorial/t3.py62
-rw-r--r--examples/tutorial/t4.py67
-rw-r--r--examples/tutorial/t5.py78
-rw-r--r--examples/tutorial/t6.py91
-rw-r--r--examples/tutorial/t7.py114
-rw-r--r--examples/tutorial/t8.py153
-rw-r--r--examples/tutorial/t9.py160
-rw-r--r--examples/utils/utils.py49
-rw-r--r--examples/webenginewidgets/simplebrowser.py102
-rwxr-xr-xexamples/widgets/animation/animatedtiles/animatedtiles.py260
-rw-r--r--examples/widgets/animation/animatedtiles/animatedtiles.qrc11
-rw-r--r--examples/widgets/animation/animatedtiles/animatedtiles_rc.py6144
-rw-r--r--examples/widgets/animation/animatedtiles/images/Time-For-Lunch-2.jpgbin0 -> 32471 bytes
-rw-r--r--examples/widgets/animation/animatedtiles/images/centered.pngbin0 -> 892 bytes
-rw-r--r--examples/widgets/animation/animatedtiles/images/ellipse.pngbin0 -> 10767 bytes
-rw-r--r--examples/widgets/animation/animatedtiles/images/figure8.pngbin0 -> 14050 bytes
-rw-r--r--examples/widgets/animation/animatedtiles/images/kinetic.pngbin0 -> 6776 bytes
-rw-r--r--examples/widgets/animation/animatedtiles/images/random.pngbin0 -> 14969 bytes
-rw-r--r--examples/widgets/animation/animatedtiles/images/tile.pngbin0 -> 16337 bytes
-rw-r--r--examples/widgets/animation/appchooser/accessories-dictionary.pngbin0 -> 5396 bytes
-rw-r--r--examples/widgets/animation/appchooser/akregator.pngbin0 -> 4873 bytes
-rwxr-xr-xexamples/widgets/animation/appchooser/appchooser.py134
-rw-r--r--examples/widgets/animation/appchooser/appchooser.qrc8
-rw-r--r--examples/widgets/animation/appchooser/appchooser_rc.py1464
-rw-r--r--examples/widgets/animation/appchooser/digikam.pngbin0 -> 3334 bytes
-rw-r--r--examples/widgets/animation/appchooser/k3b.pngbin0 -> 8220 bytes
-rw-r--r--examples/widgets/animation/easing/easing.py260
-rw-r--r--examples/widgets/animation/easing/easing.qrc5
-rw-r--r--examples/widgets/animation/easing/easing_rc.py403
-rw-r--r--examples/widgets/animation/easing/form.ui205
-rw-r--r--examples/widgets/animation/easing/images/qt-logo.pngbin0 -> 5149 bytes
-rw-r--r--examples/widgets/animation/easing/ui_form.py115
-rwxr-xr-xexamples/widgets/animation/states/states.py265
-rw-r--r--examples/widgets/animation/states/states_rc.py2221
-rwxr-xr-xexamples/widgets/dialogs/classwizard/classwizard.py404
-rw-r--r--examples/widgets/dialogs/classwizard/classwizard.qrc11
-rw-r--r--examples/widgets/dialogs/classwizard/classwizard_rc.py3928
-rw-r--r--examples/widgets/dialogs/classwizard/images/background.pngbin0 -> 22578 bytes
-rw-r--r--examples/widgets/dialogs/classwizard/images/banner.pngbin0 -> 3947 bytes
-rw-r--r--examples/widgets/dialogs/classwizard/images/logo1.pngbin0 -> 1619 bytes
-rw-r--r--examples/widgets/dialogs/classwizard/images/logo2.pngbin0 -> 1619 bytes
-rw-r--r--examples/widgets/dialogs/classwizard/images/logo3.pngbin0 -> 1619 bytes
-rw-r--r--examples/widgets/dialogs/classwizard/images/watermark1.pngbin0 -> 14516 bytes
-rw-r--r--examples/widgets/dialogs/classwizard/images/watermark2.pngbin0 -> 14912 bytes
-rwxr-xr-xexamples/widgets/dialogs/extension.py114
-rwxr-xr-xexamples/widgets/dialogs/findfiles.py211
-rw-r--r--examples/widgets/dialogs/standarddialogs.py320
-rwxr-xr-xexamples/widgets/dialogs/trivialwizard.py113
-rwxr-xr-xexamples/widgets/draganddrop/draggabletext/draggabletext.py156
-rw-r--r--examples/widgets/draganddrop/draggabletext/draggabletext.qrc5
-rw-r--r--examples/widgets/draganddrop/draggabletext/draggabletext_rc.py97
-rw-r--r--examples/widgets/draganddrop/draggabletext/words.txt41
-rwxr-xr-xexamples/widgets/effects/lighting.py145
-rwxr-xr-xexamples/widgets/graphicsview/anchorlayout.py126
-rw-r--r--examples/widgets/graphicsview/collidingmice/collidingmice.py217
-rw-r--r--examples/widgets/graphicsview/collidingmice/mice_rc.py271
-rwxr-xr-xexamples/widgets/graphicsview/diagramscene/diagramscene.py825
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene.qrc19
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene_rc.py445
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/background1.pngbin0 -> 112 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/background2.pngbin0 -> 114 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/background3.pngbin0 -> 116 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/background4.pngbin0 -> 96 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/bold.pngbin0 -> 274 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/bringtofront.pngbin0 -> 293 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/delete.pngbin0 -> 831 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/floodfill.pngbin0 -> 282 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/italic.pngbin0 -> 247 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/linecolor.pngbin0 -> 145 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/linepointer.pngbin0 -> 141 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/pointer.pngbin0 -> 173 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/sendtoback.pngbin0 -> 318 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/textpointer.pngbin0 -> 753 bytes
-rw-r--r--examples/widgets/graphicsview/diagramscene/images/underline.pngbin0 -> 250 bytes
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/dragdroprobot.py287
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/dragdroprobot.qrc5
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/dragdroprobot_rc.py1017
-rw-r--r--examples/widgets/graphicsview/dragdroprobot/images/head.pngbin0 -> 14972 bytes
-rwxr-xr-xexamples/widgets/graphicsview/elasticnodes.py414
-rw-r--r--examples/widgets/itemviews/addressbook/adddialogwidget.py103
-rw-r--r--examples/widgets/itemviews/addressbook/addressbook.py131
-rw-r--r--examples/widgets/itemviews/addressbook/addresswidget.py249
-rw-r--r--examples/widgets/itemviews/addressbook/newaddresstab.py94
-rw-r--r--examples/widgets/itemviews/addressbook/tablemodel.py147
-rwxr-xr-xexamples/widgets/itemviews/basicsortfiltermodel.py203
-rwxr-xr-xexamples/widgets/itemviews/fetchmore.py148
-rw-r--r--examples/widgets/itemviews/stardelegate/stardelegate.py174
-rw-r--r--examples/widgets/itemviews/stardelegate/stareditor.py99
-rw-r--r--examples/widgets/itemviews/stardelegate/starrating.py102
-rwxr-xr-xexamples/widgets/layouts/basiclayouts.py135
-rw-r--r--examples/widgets/layouts/dynamiclayouts.py171
-rwxr-xr-xexamples/widgets/layouts/flowlayout.py156
-rwxr-xr-xexamples/widgets/mainwindows/application/application.py273
-rw-r--r--examples/widgets/mainwindows/application/application.qrc10
-rw-r--r--examples/widgets/mainwindows/application/application_rc.py645
-rw-r--r--examples/widgets/mainwindows/application/images/copy.pngbin0 -> 1338 bytes
-rw-r--r--examples/widgets/mainwindows/application/images/cut.pngbin0 -> 1323 bytes
-rw-r--r--examples/widgets/mainwindows/application/images/new.pngbin0 -> 852 bytes
-rw-r--r--examples/widgets/mainwindows/application/images/open.pngbin0 -> 2073 bytes
-rw-r--r--examples/widgets/mainwindows/application/images/paste.pngbin0 -> 1645 bytes
-rw-r--r--examples/widgets/mainwindows/application/images/save.pngbin0 -> 1187 bytes
-rw-r--r--examples/widgets/mainwindows/dockwidgets/dockwidgets.py304
-rw-r--r--examples/widgets/mainwindows/dockwidgets/dockwidgets.qrc8
-rw-r--r--examples/widgets/mainwindows/dockwidgets/dockwidgets_rc.py503
-rw-r--r--examples/widgets/mainwindows/dockwidgets/images/new.pngbin0 -> 977 bytes
-rw-r--r--examples/widgets/mainwindows/dockwidgets/images/print.pngbin0 -> 1732 bytes
-rw-r--r--examples/widgets/mainwindows/dockwidgets/images/save.pngbin0 -> 1894 bytes
-rw-r--r--examples/widgets/mainwindows/dockwidgets/images/undo.pngbin0 -> 1768 bytes
-rw-r--r--examples/widgets/mainwindows/mdi/images/copy.pngbin0 -> 1338 bytes
-rw-r--r--examples/widgets/mainwindows/mdi/images/cut.pngbin0 -> 1323 bytes
-rw-r--r--examples/widgets/mainwindows/mdi/images/new.pngbin0 -> 852 bytes
-rw-r--r--examples/widgets/mainwindows/mdi/images/open.pngbin0 -> 2073 bytes
-rw-r--r--examples/widgets/mainwindows/mdi/images/paste.pngbin0 -> 1645 bytes
-rw-r--r--examples/widgets/mainwindows/mdi/images/save.pngbin0 -> 1187 bytes
-rwxr-xr-xexamples/widgets/mainwindows/mdi/mdi.py448
-rw-r--r--examples/widgets/mainwindows/mdi/mdi.qrc10
-rw-r--r--examples/widgets/mainwindows/mdi/mdi_rc.py645
-rwxr-xr-xexamples/widgets/painting/basicdrawing/basicdrawing.py350
-rw-r--r--examples/widgets/painting/basicdrawing/basicdrawing.qrc6
-rw-r--r--examples/widgets/painting/basicdrawing/basicdrawing_rc.py174
-rw-r--r--examples/widgets/painting/basicdrawing/images/brick.pngbin0 -> 856 bytes
-rw-r--r--examples/widgets/painting/basicdrawing/images/qt-logo.pngbin0 -> 533 bytes
-rwxr-xr-xexamples/widgets/painting/concentriccircles.py147
-rwxr-xr-xexamples/widgets/richtext/orderform.py297
-rwxr-xr-xexamples/widgets/richtext/syntaxhighlighter.py203
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/examples/example79
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.py180
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter.qrc5
-rw-r--r--examples/widgets/richtext/syntaxhighlighter/syntaxhighlighter_rc.py183
-rw-r--r--examples/widgets/richtext/textobject/files/heart.svg55
-rwxr-xr-xexamples/widgets/richtext/textobject/textobject.py130
-rwxr-xr-xexamples/widgets/state-machine/eventtrans.py93
-rwxr-xr-xexamples/widgets/state-machine/factstates.py112
-rwxr-xr-xexamples/widgets/state-machine/pingpong.py97
-rwxr-xr-xexamples/widgets/state-machine/rogue.py203
-rwxr-xr-xexamples/widgets/state-machine/trafficlight.py140
-rwxr-xr-xexamples/widgets/state-machine/twowaybutton.py71
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part1.py75
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part2.py182
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part3.py247
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part4.py301
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part5.py361
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part6.py426
-rwxr-xr-xexamples/widgets/tutorials/addressbook/part7.py478
-rwxr-xr-xexamples/widgets/widgets/hellogl_openglwidget_legacy.py289
-rw-r--r--examples/widgets/widgets/tetrix.py499
-rwxr-xr-xexamples/xml/dombookmarks/dombookmarks.py263
-rw-r--r--examples/xml/dombookmarks/frank.xbel230
-rw-r--r--examples/xml/dombookmarks/jennifer.xbel93
-rw-r--r--examples/xmlpatterns/schema/files/contact.xsd25
-rw-r--r--examples/xmlpatterns/schema/files/invalid_contact.xml11
-rw-r--r--examples/xmlpatterns/schema/files/invalid_order.xml13
-rw-r--r--examples/xmlpatterns/schema/files/invalid_recipe.xml14
-rw-r--r--examples/xmlpatterns/schema/files/order.xsd23
-rw-r--r--examples/xmlpatterns/schema/files/recipe.xsd40
-rw-r--r--examples/xmlpatterns/schema/files/valid_contact.xml11
-rw-r--r--examples/xmlpatterns/schema/files/valid_order.xml18
-rw-r--r--examples/xmlpatterns/schema/files/valid_recipe.xml13
-rwxr-xr-xexamples/xmlpatterns/schema/schema.py278
-rw-r--r--examples/xmlpatterns/schema/schema.qrc13
-rw-r--r--examples/xmlpatterns/schema/schema.ui71
-rw-r--r--examples/xmlpatterns/schema/schema_rc.py501
-rw-r--r--examples/xmlpatterns/schema/ui_schema.py62
-rw-r--r--ez_setup.py39
-rw-r--r--header.BSD-OLD (renamed from sources/pyside2/header.BSD-OLD)1
-rw-r--r--missing_bindings.py4
-rw-r--r--popenasync.py45
-rw-r--r--prepare_coin_sources.py3
-rw-r--r--qtinfo.py39
-rw-r--r--setup.py131
m---------sources/pyside2-examples0
m---------sources/pyside2-tools0
-rw-r--r--sources/pyside2/CMakeLists.txt126
-rw-r--r--sources/pyside2/PySide2/CMakeLists.txt31
-rw-r--r--sources/pyside2/PySide2/Qt3DAnimation/CMakeLists.txt55
-rw-r--r--sources/pyside2/PySide2/Qt3DAnimation/typesystem_3danimation.xml70
-rw-r--r--sources/pyside2/PySide2/Qt3DCore/CMakeLists.txt74
-rw-r--r--sources/pyside2/PySide2/Qt3DCore/typesystem_3dcore.xml90
-rw-r--r--sources/pyside2/PySide2/Qt3DExtras/CMakeLists.txt81
-rw-r--r--sources/pyside2/PySide2/Qt3DExtras/typesystem_3dextras.xml86
-rw-r--r--sources/pyside2/PySide2/Qt3DInput/CMakeLists.txt56
-rw-r--r--sources/pyside2/PySide2/Qt3DInput/typesystem_3dinput.xml85
-rw-r--r--sources/pyside2/PySide2/Qt3DLogic/CMakeLists.txt37
-rw-r--r--sources/pyside2/PySide2/Qt3DLogic/typesystem_3dlogic.xml (renamed from header.LGPL)14
-rw-r--r--sources/pyside2/PySide2/Qt3DRender/CMakeLists.txt147
-rw-r--r--sources/pyside2/PySide2/Qt3DRender/typesystem_3drender.xml243
-rw-r--r--sources/pyside2/PySide2/QtAxContainer/CMakeLists.txt46
-rw-r--r--sources/pyside2/PySide2/QtAxContainer/QtAxContainer_global.post.h.in5
-rw-r--r--sources/pyside2/PySide2/QtAxContainer/typesystem_axcontainer.xml63
-rw-r--r--sources/pyside2/PySide2/QtCharts/CMakeLists.txt90
-rw-r--r--sources/pyside2/PySide2/QtCharts/typesystem_charts.xml129
-rw-r--r--sources/pyside2/PySide2/QtConcurrent/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtConcurrent/typesystem_concurrent.xml2
-rw-r--r--sources/pyside2/PySide2/QtCore/CMakeLists.txt14
-rw-r--r--sources/pyside2/PySide2/QtCore/typesystem_core.xml.in4
-rw-r--r--sources/pyside2/PySide2/QtCore/typesystem_core_common.xml295
-rw-r--r--sources/pyside2/PySide2/QtDataVisualization/CMakeLists.txt70
-rw-r--r--sources/pyside2/PySide2/QtDataVisualization/typesystem_datavisualization.xml179
-rw-r--r--sources/pyside2/PySide2/QtGui/CMakeLists.txt24
-rw-r--r--sources/pyside2/PySide2/QtGui/QtGui_global.post.h.in1
-rw-r--r--sources/pyside2/PySide2/QtGui/typesystem_gui.xml.in6
-rw-r--r--sources/pyside2/PySide2/QtGui/typesystem_gui_common.xml486
-rw-r--r--sources/pyside2/PySide2/QtHelp/CMakeLists.txt7
-rw-r--r--sources/pyside2/PySide2/QtHelp/typesystem_help.xml3
-rw-r--r--sources/pyside2/PySide2/QtMacExtras/CMakeLists.txt8
-rw-r--r--sources/pyside2/PySide2/QtMacExtras/typesystem_macextras.xml4
-rw-r--r--sources/pyside2/PySide2/QtMultimedia/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia.xml4
-rw-r--r--sources/pyside2/PySide2/QtMultimedia/typesystem_multimedia_common.xml8
-rw-r--r--sources/pyside2/PySide2/QtMultimediaWidgets/CMakeLists.txt7
-rw-r--r--sources/pyside2/PySide2/QtMultimediaWidgets/typesystem_multimediawidgets.xml8
-rw-r--r--sources/pyside2/PySide2/QtNetwork/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtNetwork/typesystem_network.xml6
-rw-r--r--sources/pyside2/PySide2/QtOpenGL/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtOpenGL/typesystem_opengl.xml14
-rw-r--r--sources/pyside2/PySide2/QtPrintSupport/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtPrintSupport/typesystem_printsupport.xml2
-rw-r--r--sources/pyside2/PySide2/QtQml/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtQml/typesystem_qml.xml6
-rw-r--r--sources/pyside2/PySide2/QtQuick/CMakeLists.txt9
-rw-r--r--sources/pyside2/PySide2/QtQuick/typesystem_quick.xml9
-rw-r--r--sources/pyside2/PySide2/QtQuickWidgets/CMakeLists.txt8
-rw-r--r--sources/pyside2/PySide2/QtQuickWidgets/typesystem_quickwidgets.xml12
-rw-r--r--sources/pyside2/PySide2/QtScript/CMakeLists.txt4
-rw-r--r--sources/pyside2/PySide2/QtScript/typesystem_script.xml2
-rw-r--r--sources/pyside2/PySide2/QtScriptTools/CMakeLists.txt7
-rw-r--r--sources/pyside2/PySide2/QtScriptTools/typesystem_scripttools.xml6
-rw-r--r--sources/pyside2/PySide2/QtSql/CMakeLists.txt7
-rw-r--r--sources/pyside2/PySide2/QtSql/QtSql_global.pre.h.in5
-rw-r--r--sources/pyside2/PySide2/QtSql/typesystem_sql.xml2
-rw-r--r--sources/pyside2/PySide2/QtSvg/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtSvg/typesystem_svg.xml2
-rw-r--r--sources/pyside2/PySide2/QtTest/CMakeLists.txt10
-rw-r--r--sources/pyside2/PySide2/QtTest/QtTest_global.post.h.in1
-rw-r--r--sources/pyside2/PySide2/QtTest/QtTest_global.pre.h.in5
-rw-r--r--sources/pyside2/PySide2/QtTest/typesystem_test.xml7
-rw-r--r--sources/pyside2/PySide2/QtTextToSpeech/CMakeLists.txt35
-rw-r--r--sources/pyside2/PySide2/QtTextToSpeech/typesystem_texttospeech.xml (renamed from sources/pyside2/header.LGPL-NOGPL2)30
-rw-r--r--sources/pyside2/PySide2/QtUiTools/CMakeLists.txt7
-rw-r--r--sources/pyside2/PySide2/QtUiTools/typesystem_uitools.xml4
-rw-r--r--sources/pyside2/PySide2/QtWebChannel/CMakeLists.txt4
-rw-r--r--sources/pyside2/PySide2/QtWebChannel/typesystem_webchannel.xml2
-rw-r--r--sources/pyside2/PySide2/QtWebEngineWidgets/CMakeLists.txt9
-rw-r--r--sources/pyside2/PySide2/QtWebEngineWidgets/typesystem_webenginewidgets.xml14
-rw-r--r--sources/pyside2/PySide2/QtWebKit/CMakeLists.txt6
-rw-r--r--sources/pyside2/PySide2/QtWebKit/typesystem_webkit.xml6
-rw-r--r--sources/pyside2/PySide2/QtWebKitWidgets/CMakeLists.txt9
-rw-r--r--sources/pyside2/PySide2/QtWebKitWidgets/typesystem_webkitwidgets.xml12
-rw-r--r--sources/pyside2/PySide2/QtWebSockets/CMakeLists.txt5
-rw-r--r--sources/pyside2/PySide2/QtWebSockets/typesystem_websockets.xml4
-rw-r--r--sources/pyside2/PySide2/QtWidgets/CMakeLists.txt7
-rw-r--r--sources/pyside2/PySide2/QtWidgets/typesystem_widgets.xml.in6
-rw-r--r--sources/pyside2/PySide2/QtWidgets/typesystem_widgets_common.xml51
-rw-r--r--sources/pyside2/PySide2/QtWinExtras/CMakeLists.txt8
-rw-r--r--sources/pyside2/PySide2/QtWinExtras/typesystem_winextras.xml4
-rw-r--r--sources/pyside2/PySide2/QtX11Extras/CMakeLists.txt9
-rw-r--r--sources/pyside2/PySide2/QtX11Extras/QtX11Extras_global.post.h.in1
-rw-r--r--sources/pyside2/PySide2/QtX11Extras/typesystem_x11extras.xml2
-rw-r--r--sources/pyside2/PySide2/QtXml/CMakeLists.txt5
-rw-r--r--sources/pyside2/PySide2/QtXml/typesystem_xml.xml2
-rw-r--r--sources/pyside2/PySide2/QtXmlPatterns/CMakeLists.txt5
-rw-r--r--sources/pyside2/PySide2/QtXmlPatterns/typesystem_xmlpatterns.xml2
-rw-r--r--sources/pyside2/PySide2/global.h.in375
-rw-r--r--sources/pyside2/PySide2/support/signature/mapping.py2
-rw-r--r--sources/pyside2/PySide2/typesystem_templates.xml8
-rw-r--r--sources/pyside2/cmake/Macros/PySideModules.cmake46
-rw-r--r--sources/pyside2/doc/CMakeLists.txt90
-rw-r--r--sources/pyside2/doc/_templates/index.html94
-rw-r--r--sources/pyside2/doc/_templates/layout.html4
-rw-r--r--sources/pyside2/doc/_themes/pysidedocs/static/logo_indt.jpgbin3138 -> 0 bytes
-rw-r--r--sources/pyside2/doc/_themes/pysidedocs/static/logo_openbossa.pngbin4702 -> 0 bytes
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/alphachannel.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/clipboard/clipwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_io_qsettings.cpp7
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_tools_qbytearray.cpp10
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_corelib_tools_qregexp.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_gui_kernel_qapplication.cpp16
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_gui_kernel_qclipboard.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_gui_painting_qpainter.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_gui_styles_qstyle.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_gui_util_qvalidator.cpp (renamed from sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_gui_widgets_qvalidator.cpp)0
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_network_access_qftp.cpp4
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp4
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_network_access_qnetworkdiskcache.cpp4
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_network_kernel_qhostinfo.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_xml_dom_qdom.cpp8
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/customstyle/customstyle.h4
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/customviewstyle.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/dialogs/dialogs.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/dragging/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/droparea.cpp8
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/layouts/layouts.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/mainwindowsnippet.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/matrix/matrix.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/mdiareasnippets.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/picture/picture.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/polygon/polygon.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qfontdatabase/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qprocess/qprocess-simpleexecution.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qsortfilterproxymodel-details/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qsplashscreen/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qstackedwidget/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qtreewidget-using/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qtreewidgetitemiterator-using/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/qxmlstreamwriter/main.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/shareddirmodel/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/simpleparse/handler.cpp (renamed from sources/pyside2/doc/codesnippets/doc/src/snippets/xml/simpleparse/handler.cpp)0
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/simpleparse/handler.h (renamed from sources/pyside2/doc/codesnippets/doc/src/snippets/xml/simpleparse/handler.h)0
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/simpleparse/main.cpp (renamed from sources/pyside2/doc/codesnippets/doc/src/snippets/xml/simpleparse/main.cpp)0
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/splitter/splitter.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/splitterhandle/splitter.h6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/sqldatabase/sqldatabase.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/textdocument-css/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/textdocument-tables/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/textdocument-texttable/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/transform/main.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/doc/src/snippets/whatsthis/whatsthis.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/dialogs/extension/finddialog.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/imageprovider/imageprovider-example.qml (renamed from sources/pyside2/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider-example.qml)2
-rw-r--r--sources/pyside2/doc/codesnippets/examples/imageprovider/imageprovider.cpp (renamed from sources/pyside2/doc/codesnippets/examples/declarative/cppextensions/imageprovider/imageprovider.cpp)4
-rw-r--r--sources/pyside2/doc/codesnippets/examples/itemviews/customsortfiltermodel/mysortfilterproxymodel.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/mainwindows/application/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/mainwindows/dockwidgets/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/mainwindows/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/mainwindows/mdi/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/mainwindows/menus/mainwindow.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/quick/plugins/plugins.qml (renamed from sources/pyside2/doc/codesnippets/doc/src/snippets/code/src_svg_qgraphicssvgitem.cpp)0
-rw-r--r--sources/pyside2/doc/codesnippets/examples/relationaltablemodel/relationaltablemodel.cpp (renamed from sources/pyside2/doc/codesnippets/examples/sql/relationaltablemodel/relationaltablemodel.cpp)6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/svggenerator/window.cpp (renamed from sources/pyside2/doc/codesnippets/examples/painting/svggenerator/window.cpp)0
-rw-r--r--sources/pyside2/doc/codesnippets/examples/widgets/icons/iconsizespinbox.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/examples/widgets/spinboxes/window.cpp6
-rw-r--r--sources/pyside2/doc/codesnippets/webkitsnippets/simple/main.cpp2
-rw-r--r--sources/pyside2/doc/codesnippets/webkitsnippets/webpage/main.cpp2
-rw-r--r--sources/pyside2/doc/conf.py.in6
-rw-r--r--sources/pyside2/doc/inheritance_diagram.py87
-rw-r--r--sources/pyside2/doc/modules.rst26
-rw-r--r--sources/pyside2/doc/pyside-config.qdocconf.in10
-rw-r--r--sources/pyside2/doc/pyside.qdocconf.in269
-rw-r--r--sources/pyside2/doc/pysideinclude.py4
-rw-r--r--sources/pyside2/doc/pysideversion.rst18
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qt3dextras.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtcharts.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtconcurrent.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtcore.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtdatavisualization.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtgui.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qthelp.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtmacextras.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtmultimedia.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtnetwork.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtopengl.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtprintsupport.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtquickwidgets.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtsql.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtsvg.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qttest.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qttexttospeech.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtuitools.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtwebchannel.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtwebsockets.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtwidgets.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtwinextras.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtx11extras.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtxml.qdocconf.in2
-rw-r--r--sources/pyside2/doc/qtmodules/pyside-qtxmlpatterns.qdocconf.in2
-rw-r--r--sources/pyside2/doc/src/README.md1
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/helloworld/Cell.qml2
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/helloworld/tutorial1.qml2
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/helloworld/tutorial2.qml2
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/helloworld/tutorial3.qml2
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/index.rst4
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/step1.rst26
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/step2.rst46
-rw-r--r--sources/pyside2/doc/tutorials/qmltutorial/step3.rst31
-rw-r--r--sources/pyside2/doc/typesystem_doc.xml.in64
-rw-r--r--sources/pyside2/header.COMM20
-rw-r--r--sources/pyside2/header.FDL27
-rw-r--r--sources/pyside2/header.FDL-OLD27
-rw-r--r--sources/pyside2/header.GPL29
-rw-r--r--sources/pyside2/header.GPL-EXCEPT28
-rw-r--r--sources/pyside2/header.LGPL-ONLY22
-rw-r--r--sources/pyside2/header.LGPL2133
-rw-r--r--sources/pyside2/header.LGPL336
-rw-r--r--sources/pyside2/header.LGPL3-COMM28
-rw-r--r--sources/pyside2/libpyside/CMakeLists.txt5
-rw-r--r--sources/pyside2/libpyside/pysidesignal.cpp74
-rw-r--r--sources/pyside2/pyside_version.py41
-rw-r--r--sources/pyside2/tests/Qt3DAnimation/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/Qt3DCore/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/Qt3DExtras/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/Qt3DExtras/qt3dextras_test.py154
-rw-r--r--sources/pyside2/tests/Qt3DInput/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/Qt3DLogic/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/Qt3DQuick/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/Qt3DRender/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtAxContainer/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtCharts/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtCharts/qcharts_test.py63
-rw-r--r--sources/pyside2/tests/QtCore/CMakeLists.txt5
-rw-r--r--sources/pyside2/tests/QtCore/qfileread_test.py82
-rw-r--r--sources/pyside2/tests/QtCore/qmimedatabase_test.py5
-rw-r--r--sources/pyside2/tests/QtCore/qobject_test.py13
-rw-r--r--sources/pyside2/tests/QtCore/qregularexpression_test.py56
-rw-r--r--sources/pyside2/tests/QtCore/qurl_test.py132
-rw-r--r--sources/pyside2/tests/QtCore/qurlquery_test.py59
-rw-r--r--sources/pyside2/tests/QtCore/quuid_test.py45
-rw-r--r--sources/pyside2/tests/QtCore/qversionnumber_test.py48
-rw-r--r--sources/pyside2/tests/QtDataVisualization/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtDataVisualization/datavisualization_test.py85
-rw-r--r--sources/pyside2/tests/QtGui/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtGui/qopenglwindow_test.py104
-rw-r--r--sources/pyside2/tests/QtHelp/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtHelp/helpsearchengine_test.py44
-rw-r--r--sources/pyside2/tests/QtTextToSpeech/CMakeLists.txt1
-rw-r--r--sources/pyside2/tests/QtTextToSpeech/qtexttospeech_test.py63
-rw-r--r--sources/pyside2/tests/QtWidgets/CMakeLists.txt2
-rw-r--r--sources/pyside2/tests/QtWidgets/qcolormap_test.py43
-rw-r--r--sources/pyside2/tests/QtWidgets/qlistwidget_test.py7
-rw-r--r--sources/pyside2/tests/QtWidgets/qtreeview_test.py89
-rw-r--r--sources/pyside2/tests/pysidetest/CMakeLists.txt34
-rw-r--r--sources/pyside2/tests/pysidetest/typesystem_pysidetest.xml2
-rw-r--r--sources/pyside2/tests/registry/exists_darwin_5_9_4_ci.py (renamed from sources/pyside2/tests/registry/exists_darwin_5_9_3_ci.py)791
-rw-r--r--sources/pyside2/tests/registry/exists_linux_5_9_4_ci.py (renamed from sources/pyside2/tests/registry/exists_linux_5_9_3_ci.py)211
-rw-r--r--sources/pyside2/tests/registry/exists_win32_5_9_4_ci.py (renamed from sources/pyside2/tests/registry/exists_win32_5_9_3_ci.py)763
-rw-r--r--sources/pyside2/tests/registry/init_platform.py2
-rw-r--r--sources/pyside2/tests/signals/signal_signature_test.py40
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt45
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp958
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.h11
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h17
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp1062
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h404
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h18
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.cpp126
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.h10
-rw-r--r--sources/shiboken2/ApiExtractor/asttoxml.cpp160
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp858
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h (renamed from sources/shiboken2/ApiExtractor/parser/dumptree.h)37
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp150
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h (renamed from sources/shiboken2/ApiExtractor/parser/compiler_utils.h)34
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp272
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.h93
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp227
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.h101
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp202
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.h (renamed from sources/shiboken2/ApiExtractor/parser/list.cpp)15
-rw-r--r--sources/shiboken2/ApiExtractor/doc/conf.py.in2
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst5
-rw-r--r--sources/shiboken2/ApiExtractor/docparser.cpp83
-rw-r--r--sources/shiboken2/ApiExtractor/docparser.h22
-rw-r--r--sources/shiboken2/ApiExtractor/doxygenparser.cpp40
-rw-r--r--sources/shiboken2/ApiExtractor/doxygenparser.h6
-rw-r--r--sources/shiboken2/ApiExtractor/fileout.cpp16
-rw-r--r--sources/shiboken2/ApiExtractor/generator.qrc5
-rw-r--r--sources/shiboken2/ApiExtractor/graph.cpp3
-rw-r--r--sources/shiboken2/ApiExtractor/header_paths.h (renamed from sources/shiboken2/ApiExtractor/parser/codemodel_finder.h)67
-rw-r--r--sources/shiboken2/ApiExtractor/include.h4
-rw-r--r--sources/shiboken2/ApiExtractor/parser/ast.cpp38
-rw-r--r--sources/shiboken2/ApiExtractor/parser/ast.h884
-rw-r--r--sources/shiboken2/ApiExtractor/parser/binder.cpp866
-rw-r--r--sources/shiboken2/ApiExtractor/parser/binder.h133
-rw-r--r--sources/shiboken2/ApiExtractor/parser/class_compiler.cpp71
-rw-r--r--sources/shiboken2/ApiExtractor/parser/class_compiler.h77
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp80
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h65
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp103
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h28
-rw-r--r--sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp55
-rw-r--r--sources/shiboken2/ApiExtractor/parser/control.cpp135
-rw-r--r--sources/shiboken2/ApiExtractor/parser/control.h165
-rw-r--r--sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp167
-rw-r--r--sources/shiboken2/ApiExtractor/parser/declarator_compiler.h101
-rw-r--r--sources/shiboken2/ApiExtractor/parser/default_visitor.cpp464
-rw-r--r--sources/shiboken2/ApiExtractor/parser/default_visitor.h123
-rw-r--r--sources/shiboken2/ApiExtractor/parser/dumptree.cpp131
-rw-r--r--sources/shiboken2/ApiExtractor/parser/lexer.cpp1726
-rw-r--r--sources/shiboken2/ApiExtractor/parser/lexer.h295
-rw-r--r--sources/shiboken2/ApiExtractor/parser/list.h105
-rw-r--r--sources/shiboken2/ApiExtractor/parser/name_compiler.cpp139
-rw-r--r--sources/shiboken2/ApiExtractor/parser/parser.cpp4075
-rw-r--r--sources/shiboken2/ApiExtractor/parser/parser.h204
-rw-r--r--sources/shiboken2/ApiExtractor/parser/r++.macros28
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp-allocator.h29
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp28
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h62
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration86
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h1300
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h288
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h144
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h44
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h122
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h99
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h356
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h77
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration24
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h318
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h112
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h97
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp.h96
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp164
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h70
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rxx_allocator.h146
-rw-r--r--sources/shiboken2/ApiExtractor/parser/smallobject.cpp33
-rw-r--r--sources/shiboken2/ApiExtractor/parser/smallobject.h58
-rw-r--r--sources/shiboken2/ApiExtractor/parser/symbol.h127
-rw-r--r--sources/shiboken2/ApiExtractor/parser/tokens.cpp256
-rw-r--r--sources/shiboken2/ApiExtractor/parser/tokens.h152
-rw-r--r--sources/shiboken2/ApiExtractor/parser/type_compiler.cpp134
-rw-r--r--sources/shiboken2/ApiExtractor/parser/type_compiler.h76
-rw-r--r--sources/shiboken2/ApiExtractor/parser/visitor.cpp127
-rw-r--r--sources/shiboken2/ApiExtractor/parser/visitor.h145
-rw-r--r--sources/shiboken2/ApiExtractor/qtdocparser.cpp160
-rw-r--r--sources/shiboken2/ApiExtractor/qtdocparser.h6
-rw-r--r--sources/shiboken2/ApiExtractor/reporthandler.cpp12
-rw-r--r--sources/shiboken2/ApiExtractor/reporthandler.h2
-rw-r--r--sources/shiboken2/ApiExtractor/tests/CMakeLists.txt1
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp91
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp6
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp58
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.h1
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testenum.cpp10
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp4
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp20
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h1
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp3
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp3
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.cpp1
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testutil.h16
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp248
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.h37
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase_typedefs.h (renamed from sources/shiboken2/ApiExtractor/asttoxml.h)29
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.cpp46
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.h9
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp739
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h620
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_p.h3
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_typedefs.h21
-rw-r--r--sources/shiboken2/CMakeLists.txt107
-rw-r--r--sources/shiboken2/data/Shiboken2Config.cmake.in2
-rw-r--r--sources/shiboken2/doc/conf.py.in6
-rw-r--r--sources/shiboken2/ext/sparsehash/AUTHORS2
-rw-r--r--sources/shiboken2/ext/sparsehash/COPYING28
-rw-r--r--sources/shiboken2/ext/sparsehash/google/dense_hash_map310
-rw-r--r--sources/shiboken2/ext/sparsehash/google/dense_hash_set287
-rw-r--r--sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h1062
-rw-r--r--sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h45
-rw-r--r--sources/shiboken2/ext/sparsehash/google/type_traits.h250
-rw-r--r--sources/shiboken2/generator/generator.cpp99
-rw-r--r--sources/shiboken2/generator/generator.h14
-rw-r--r--sources/shiboken2/generator/main.cpp221
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp956
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.h49
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp528
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h14
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.cpp82
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.h10
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.cpp146
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.h14
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp533
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h28
-rw-r--r--sources/shiboken2/header.COMM20
-rw-r--r--sources/shiboken2/header.LGPL-ONLY22
-rw-r--r--sources/shiboken2/header.LGPL2133
-rw-r--r--sources/shiboken2/header.LGPL336
-rw-r--r--sources/shiboken2/header.LGPL3-COMM28
-rw-r--r--sources/shiboken2/libshiboken/CMakeLists.txt44
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp43
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h22
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp9
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter.cpp289
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter.h171
-rw-r--r--sources/shiboken2/libshiboken/sbkarrayconverter_p.h62
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.cpp25
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.h3
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter_p.h9
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp13
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h2
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.cpp19
-rw-r--r--sources/shiboken2/libshiboken/sbknumpyarrayconverter.cpp308
-rw-r--r--sources/shiboken2/libshiboken/shiboken.h1
-rw-r--r--sources/shiboken2/shiboken_version.py41
-rw-r--r--sources/shiboken2/tests/dumpcodemodel/main.cpp23
-rw-r--r--sources/shiboken2/tests/libother/otherderived.cpp3
-rw-r--r--sources/shiboken2/tests/libother/otherderived.h15
-rw-r--r--sources/shiboken2/tests/libsample/abstract.h1
-rw-r--r--sources/shiboken2/tests/libsample/derived.cpp6
-rw-r--r--sources/shiboken2/tests/libsample/derived.h19
-rw-r--r--sources/shiboken2/tests/libsample/functions.cpp41
-rw-r--r--sources/shiboken2/tests/libsample/functions.h11
-rw-r--r--sources/shiboken2/tests/libsample/multiple_derived.h10
-rw-r--r--sources/shiboken2/tests/libsample/objecttype.h10
-rw-r--r--sources/shiboken2/tests/libsample/objecttypelayout.h4
-rw-r--r--sources/shiboken2/tests/libsample/photon.h2
-rw-r--r--sources/shiboken2/tests/libsample/samplenamespace.h4
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.cpp19
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.h18
-rw-r--r--sources/shiboken2/tests/samplebinding/CMakeLists.txt3
-rw-r--r--sources/shiboken2/tests/samplebinding/array_numpy_test.py64
-rw-r--r--sources/shiboken2/tests/samplebinding/array_sequence_test.py53
-rw-r--r--sources/shiboken2/tests/samplebinding/enum_test.py5
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml18
-rw-r--r--sources/shiboken2/tests/test_generator/dummygenerator.cpp3
-rw-r--r--testing/runner.py16
-rw-r--r--tests/QtQml/qquickitem_grabToImage.py79
-rw-r--r--tests/QtQml/qquickitem_grabToImage.qml (renamed from sources/shiboken2/ApiExtractor/parser/name_compiler.h)75
-rw-r--r--utils.py109
m---------wiki0
698 files changed, 58947 insertions, 23671 deletions
diff --git a/.gitmodules b/.gitmodules
index 9a97d3b04..46377b89a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,11 +1,4 @@
[submodule "sources/pyside2-tools"]
path = sources/pyside2-tools
- branch = 5.6
+ branch = 5.9
url = ../pyside-tools.git
-[submodule "sources/pyside2-examples"]
- path = sources/pyside2-examples
- branch = 5.6
- url = ../examples.git
-[submodule "wiki"]
- path = wiki
- url = https://github.com/PySide/pyside2.wiki.git
diff --git a/.qt-license-check.exclude b/.qt-license-check.exclude
deleted file mode 100644
index f42def186..000000000
--- a/.qt-license-check.exclude
+++ /dev/null
@@ -1,3 +0,0 @@
-License checker is excluded with Pyside in 5.6 branch.
-Do not merge this file to other branch.
-
diff --git a/MANIFEST.in b/MANIFEST.in
index 87d6b1cbe..dd79b2380 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -17,14 +17,10 @@ recursive-include sources/patchelf **
recursive-include sources/shiboken2 **
recursive-include sources/pyside2 **
recursive-include sources/pyside2-tools **
-recursive-include sources/pyside2-examples **
-recursive-exclude sources/pyside2-examples/examples/hyperui **
-recursive-exclude sources/pyside2examples/mobility **
# ignore .git
recursive-exclude sources/shiboken2/.git **
recursive-exclude sources/pyside2/.git **
recursive-exclude sources/pyside2-tools/.git **
-recursive-exclude sources/pyside2-examples/.git **
# PySide package
recursive-include pyside_package/PySide2 **
diff --git a/README.md b/README.md
index e654276ce..cde05940d 100644
--- a/README.md
+++ b/README.md
@@ -1,38 +1,53 @@
-#PySide2
+# PySide2
-| Windows | Linux |
-|---------|-------|
-| [![AppVeyor](https://img.shields.io/appveyor/ci/techtonik/pyside2-setup.svg)](https://ci.appveyor.com/project/techtonik/pyside2-setup) | [![Travis CI](https://img.shields.io/travis/PySide/pyside2-setup.svg)](https://travis-ci.org/PySide/pyside2-setup) |
+### Introduction
+PySide is the [Python Qt bindings project](http://wiki.qt.io/PySide2), providing
+access to the complete Qt 5.x framework as well as to generator tools for rapidly
+generating bindings for any C++ libraries.
-###Introduction
+The PySide project is developed in the open, with all facilities you'd expect
+from any modern OSS project such as all code in a git repository and an open
+design process. We welcome any contribution conforming to the
+[Qt Contribution Agreement](https://www.qt.io/contributionagreement/).
+PySide 2 supports Qt5. For building, please read about
+[getting started](https://wiki.qt.io/PySide2_GettingStarted).
+Then download the sources by running
+ git clone https://code.qt.io/pyside/pyside-setup
-PySide is the [Python Qt bindings project](http://wiki.qt.io/PySide2), providing access the complete Qt 5.x framework
-as well as to generator tools for rapidly generating bindings for any C++ libraries.
+### Building
-The PySide project is developed in the open, with all facilities you'd expect
-from any modern OSS project such as all code in a git repository and an open design process. We welcome
-any contribution conforming to the [Qt Contribution Agreement](https://www.qt.io/contributionagreement/).
+#### Dependencies
+
+PySide versions following 5.6 use a C++ parser based on
+[Clang](http://clang.org/). The Clang library (C-bindings), version 3.9 or
+higher is required for building. Prebuilt versions of it can be downloaded from
+[download.qt.io](http://download.qt.io/development_releases/prebuilt/libclang/).
+After unpacking the archive, set the environment variable *LLVM_INSTALL_DIR* to
+point to the folder containing the *include* and *lib* directories of Clang:
-PySide 2 supports Qt5. For building, please read about [getting the dependencies](https://github.com/PySide/pyside2/wiki/Dependencies). Then download the sources by running `git clone --recursive https://code.qt.io/pyside/pyside-setup`.
+ 7z x .../libclang-release_39-linux-Rhel7.2-gcc5.3-x86_64.7z
+ export LLVM_INSTALL_DIR=$PWD/libclang
-###Building
+On Windows:
-####Windows
-On Windows, once you have gotten the dependencies and the source, `cd pyside2-setup.git` to enter the directory and then:
-```
-python setup.py install --qmake=\path\to\bin\qmake --cmake=\path\to\bin\cmake --openssl=\path\to\openssl\bin
-```
+ 7z x .../libclang-release_39-windows-vs2015_64.7z
+ SET LLVM_INSTALL_DIR=%CD%\libclang
-####Linux
+#### Build Instructions
+You might consider using a virtual environment as described at
+[getting started](https://wiki.qt.io/PySide2_GettingStarted).
You should be able to build:
-```
-python setup.py install --qmake=/path/to/bin/qmake --cmake=/path/to/bin/cmake --openssl=/path/to/openssl/bin
-```
+ cd pyside-setup
+ python setup.py install
+The setup script will try to find the location of the qmake tool of the Qt
+version to be used and the cmake build tool in the path. Non-standard
+locations can be specified by the *--qmake=path_to_qmake* or
+*--cmake=path_to_cmake* command line options.
diff --git a/build_history/blacklist.txt b/build_history/blacklist.txt
index 9192294e5..5da9fc427 100644
--- a/build_history/blacklist.txt
+++ b/build_history/blacklist.txt
@@ -10,6 +10,8 @@
linux
darwin
win32
+[Qt3DExtras::qt3dextras_test]
+ linux
[QtCore::qfile_test]
win32
darwin py3
@@ -66,6 +68,10 @@
win32
linux
darwin
+# PYSIDE-474
+[QtWebEngineWidgets::pyside-474-qtwebengineview]
+ py2
+ py3
[QtCore::thread_signals_test]
win32
linux
diff --git a/checklibs.py b/checklibs.py
index ff4d51ae8..172508706 100644
--- a/checklibs.py
+++ b/checklibs.py
@@ -1,3 +1,42 @@
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of PySide2.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
#!/usr/bin/env python
#
# checklibs.py
diff --git a/docs/conf.py b/docs/conf.py
index 0af22dbcb..61e4c7132 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,4 +1,42 @@
# -*- coding: utf-8 -*-
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of PySide2.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
#
# PySide documentation build configuration file, created by
# sphinx-quickstart on Mon May 12 22:14:54 2014.
@@ -147,10 +185,6 @@ html_static_path = ['_static']
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
-# If true, SmartyPants will be used to convert quotes and dashes to
-# typographically correct entities.
-#html_use_smartypants = True
-
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
diff --git a/docs/make.bat b/docs/make.bat
index 53fb034ca..3db37e4fd 100644
--- a/docs/make.bat
+++ b/docs/make.bat
@@ -1,3 +1,42 @@
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::
+:: Copyright (C) 2017 The Qt Company Ltd.
+:: Contact: https://www.qt.io/licensing/
+::
+:: This file is part of PySide2.
+::
+:: $QT_BEGIN_LICENSE:LGPL$
+:: Commercial License Usage
+:: Licensees holding valid commercial Qt licenses may use this file in
+:: accordance with the commercial license agreement provided with the
+:: Software or, alternatively, in accordance with the terms contained in
+:: a written agreement between you and The Qt Company. For licensing terms
+:: and conditions see https://www.qt.io/terms-conditions. For further
+:: information use the contact form at https://www.qt.io/contact-us.
+::
+:: GNU Lesser General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU Lesser
+:: General Public License version 3 as published by the Free Software
+:: Foundation and appearing in the file LICENSE.LGPL3 included in the
+:: packaging of this file. Please review the following information to
+:: ensure the GNU Lesser General Public License version 3 requirements
+:: will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+::
+:: GNU General Public License Usage
+:: Alternatively, this file may be used under the terms of the GNU
+:: General Public License version 2.0 or (at your option) the GNU General
+:: Public license version 3 or any later version approved by the KDE Free
+:: Qt Foundation. The licenses are as published by the Free Software
+:: Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+:: included in the packaging of this file. Please review the following
+:: information to ensure the GNU General Public License requirements will
+:: be met: https://www.gnu.org/licenses/gpl-2.0.html and
+:: https://www.gnu.org/licenses/gpl-3.0.html.
+::
+:: $QT_END_LICENSE$
+::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
+
@ECHO OFF
REM Command file for Sphinx documentation
diff --git a/examples/3d/simple3d.py b/examples/3d/simple3d.py
new file mode 100644
index 000000000..a34d19821
--- /dev/null
+++ b/examples/3d/simple3d.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the qt3d/simple-cpp example from Qt v5.x"""
+
+import sys
+from PySide2.QtCore import(Property, QObject, QPropertyAnimation, Signal, Slot)
+from PySide2.QtGui import (QGuiApplication, QMatrix4x4, QQuaternion, QVector3D, QWindow)
+from PySide2.Qt3DCore import (Qt3DCore)
+from PySide2.Qt3DRender import (Qt3DRender)
+from PySide2.Qt3DExtras import (Qt3DExtras)
+
+class OrbitTransformController(QObject):
+ def __init__(self, parent):
+ super(OrbitTransformController, self).__init__(parent)
+ self._target = None
+ self._matrix = QMatrix4x4()
+ self._radius = 1
+ self._angle = 0
+
+ def setTarget(self, t):
+ self._target = t
+
+ def getTarget(self):
+ return self._target
+
+ def setRadius(self, radius):
+ if self._radius != radius:
+ self._radius = radius
+ self.updateMatrix()
+ self.radiusChanged.emit()
+
+ def getRadius(self):
+ return self._radius
+
+ def setAngle(self, angle):
+ if self._angle != angle:
+ self._angle = angle
+ self.updateMatrix()
+ self.angleChanged.emit()
+
+ def getAngle(self):
+ return self._angle
+
+ def updateMatrix(self):
+ self._matrix.setToIdentity();
+ self._matrix.rotate(self._angle, QVector3D(0, 1, 0))
+ self._matrix.translate(self._radius, 0, 0)
+ if self._target is not None:
+ self._target.setMatrix(self._matrix)
+
+ angleChanged = Signal()
+ radiusChanged = Signal()
+ angle = Property(float, getAngle, setAngle, notify=angleChanged)
+ radius = Property(float, getRadius, setRadius, notify=radiusChanged)
+
+class Window(Qt3DExtras.Qt3DWindow):
+ def __init__(self):
+ super(Window, self).__init__()
+
+ # Camera
+ self.camera().lens().setPerspectiveProjection(45, 16 / 9, 0.1, 1000)
+ self.camera().setPosition(QVector3D(0, 0, 40))
+ self.camera().setViewCenter(QVector3D(0, 0, 0))
+
+ # For camera controls
+ self.createScene()
+ self.camController = Qt3DExtras.QOrbitCameraController(self.rootEntity)
+ self.camController.setLinearSpeed(50)
+ self.camController.setLookSpeed(180)
+ self.camController.setCamera(self.camera())
+
+ self.setRootEntity(self.rootEntity)
+
+ def createScene(self):
+ # Root entity
+ self.rootEntity = Qt3DCore.QEntity()
+
+ # Material
+ self.material = Qt3DExtras.QPhongMaterial(self.rootEntity)
+
+ # Torus
+ self.torusEntity = Qt3DCore.QEntity(self.rootEntity)
+ self.torusMesh = Qt3DExtras.QTorusMesh()
+ self.torusMesh.setRadius(5)
+ self.torusMesh.setMinorRadius(1)
+ self.torusMesh.setRings(100)
+ self.torusMesh.setSlices(20)
+
+ self.torusTransform = Qt3DCore.QTransform()
+ self.torusTransform.setScale3D(QVector3D(1.5, 1, 0.5))
+ self.torusTransform.setRotation(QQuaternion.fromAxisAndAngle(QVector3D(1, 0, 0), 45))
+
+ self.torusEntity.addComponent(self.torusMesh)
+ self.torusEntity.addComponent(self.torusTransform)
+ self.torusEntity.addComponent(self.material)
+
+ # Sphere
+ self.sphereEntity = Qt3DCore.QEntity(self.rootEntity)
+ self.sphereMesh = Qt3DExtras.QSphereMesh()
+ self.sphereMesh.setRadius(3)
+
+ self.sphereTransform = Qt3DCore.QTransform()
+ self.controller = OrbitTransformController(self.sphereTransform)
+ self.controller.setTarget(self.sphereTransform)
+ self.controller.setRadius(20)
+
+ self.sphereRotateTransformAnimation = QPropertyAnimation(self.sphereTransform)
+ self.sphereRotateTransformAnimation.setTargetObject(self.controller)
+ self.sphereRotateTransformAnimation.setPropertyName("angle")
+ self.sphereRotateTransformAnimation.setStartValue(0)
+ self.sphereRotateTransformAnimation.setEndValue(360)
+ self.sphereRotateTransformAnimation.setDuration(10000)
+ self.sphereRotateTransformAnimation.setLoopCount(-1)
+ self.sphereRotateTransformAnimation.start()
+
+ self.sphereEntity.addComponent(self.sphereMesh)
+ self.sphereEntity.addComponent(self.sphereTransform)
+ self.sphereEntity.addComponent(self.material)
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = Window()
+ view.show()
+ sys.exit(app.exec_())
diff --git a/examples/axcontainer/axviewer.py b/examples/axcontainer/axviewer.py
new file mode 100644
index 000000000..cb3d4c0de
--- /dev/null
+++ b/examples/axcontainer/axviewer.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 Active Qt Viewer example"""
+
+import sys
+from PySide2.QtAxContainer import QAxSelect, QAxWidget
+from PySide2.QtGui import QKeySequence
+from PySide2.QtWidgets import (QAction, qApp, QApplication, QDialog, QFileDialog,
+ QMainWindow, QMenu, QMenuBar, QMessageBox, QToolBar)
+
+class MainWindow(QMainWindow):
+
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ toolBar = QToolBar()
+ self.addToolBar(toolBar)
+ fileMenu = self.menuBar().addMenu("&File")
+ loadAction = QAction("Load...", self, shortcut="Ctrl+L", triggered=self.load)
+ fileMenu.addAction(loadAction)
+ toolBar.addAction(loadAction)
+ exitAction = QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close)
+ fileMenu.addAction(exitAction)
+
+ aboutMenu = self.menuBar().addMenu("&About")
+ aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
+ aboutMenu.addAction(aboutQtAct)
+ self.axWidget = QAxWidget()
+ self.setCentralWidget(self.axWidget)
+
+ def load(self):
+ axSelect = QAxSelect(self)
+ if axSelect.exec_() == QDialog.Accepted:
+ clsid = axSelect.clsid()
+ if not self.axWidget.setControl(clsid):
+ QMessageBox.warning(self, "AxViewer", "Unable to load " + clsid + ".")
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ availableGeometry = app.desktop().availableGeometry(mainWin)
+ mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/charts/audio.py b/examples/charts/audio.py
new file mode 100644
index 000000000..94da12cfd
--- /dev/null
+++ b/examples/charts/audio.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the charts/audio example from Qt v5.x"""
+
+import os
+import sys
+from PySide2.QtCharts import QtCharts
+from PySide2.QtCore import QPointF, QRect, QSize
+from PySide2.QtMultimedia import (QAudio, QAudioDeviceInfo, QAudioFormat,
+ QAudioInput)
+from PySide2.QtWidgets import QApplication, QMainWindow, QMessageBox
+
+sampleCount = 2000
+resolution = 4
+
+class MainWindow(QMainWindow):
+ def __init__(self, device):
+ super(MainWindow, self).__init__()
+
+ self.series = QtCharts.QLineSeries()
+ self.chart = QtCharts.QChart()
+ self.chart.addSeries(self.series)
+ self.axisX = QtCharts.QValueAxis()
+ self.axisX.setRange(0, sampleCount)
+ self.axisX.setLabelFormat("%g")
+ self.axisX.setTitleText("Samples")
+ self.axisY = QtCharts.QValueAxis()
+ self.axisY.setRange(-1, 1)
+ self.axisY.setTitleText("Audio level")
+ self.chart.setAxisX(self.axisX, self.series)
+ self.chart.setAxisY(self.axisY, self.series)
+ self.chart.legend().hide()
+ self.chart.setTitle("Data from the microphone ({})".format(device.deviceName()))
+
+ formatAudio = QAudioFormat()
+ formatAudio.setSampleRate(8000)
+ formatAudio.setChannelCount(1)
+ formatAudio.setSampleSize(8)
+ formatAudio.setCodec("audio/pcm")
+ formatAudio.setByteOrder(QAudioFormat.LittleEndian)
+ formatAudio.setSampleType(QAudioFormat.UnSignedInt)
+
+ self.audioInput = QAudioInput(device, formatAudio, self)
+ self.ioDevice = self.audioInput.start()
+ self.ioDevice.readyRead.connect(self._readyRead)
+
+ self.chartView = QtCharts.QChartView(self.chart)
+ self.setCentralWidget(self.chartView)
+
+ self.buffer = [QPointF(x, 0) for x in range(sampleCount)]
+ self.series.append(self.buffer)
+
+ def closeEvent(self, event):
+ if self.audioInput is not None:
+ self.audioInput.stop()
+ event.accept()
+
+ def _readyRead(self):
+ data = self.ioDevice.readAll()
+ availableSamples = data.size() // resolution
+ start = 0
+ if (availableSamples < sampleCount):
+ start = sampleCount - availableSamples
+ for s in range(start):
+ self.buffer[s].setY(self.buffer[s + availableSamples].y())
+
+ dataIndex = 0
+ for s in range(start, sampleCount):
+ value = (ord(data[dataIndex]) - 128) / 128
+ self.buffer[s].setY(value)
+ dataIndex = dataIndex + resolution
+ self.series.replace(self.buffer)
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ inputDevice = QAudioDeviceInfo.defaultInputDevice()
+ if (inputDevice.isNull()):
+ QMessageBox.warning(None, "audio", "There is no audio input device available.")
+ sys.exit(-1)
+
+ mainWin = MainWindow(inputDevice)
+ mainWin.setWindowTitle("audio")
+ availableGeometry = app.desktop().availableGeometry(mainWin)
+ size = availableGeometry.height() * 3 / 4
+ mainWin.resize(size, size)
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/charts/memoryusage.py b/examples/charts/memoryusage.py
new file mode 100644
index 000000000..c0e0a38dd
--- /dev/null
+++ b/examples/charts/memoryusage.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 Charts example: Simple memory usage viewer"""
+
+import os
+import sys
+from PySide2.QtCore import QRect, QSize, QProcess
+from PySide2.QtWidgets import QApplication, QMainWindow
+from PySide2.QtCharts import QtCharts
+
+def runProcess(command, arguments):
+ process = QProcess()
+ process.start(command, arguments)
+ process.waitForFinished()
+ result = []
+ for line in str(process.readAllStandardOutput()).split(os.linesep):
+ result.append(line)
+ return result
+
+def getMemoryUsage():
+ result = []
+ if sys.platform == 'win32':
+ # Windows: Obtain memory usage in KB from 'tasklist'
+ for line in runProcess('tasklist', [])[3:]:
+ if len(line) >= 74:
+ command = line[0:23].strip()
+ if command.endswith('.exe'):
+ command = command[0:len(command) - 4]
+ memoryUsage = float(line[64:74].strip().replace(',', '').replace('.', ''))
+ legend = ''
+ if memoryUsage > 10240:
+ legend = '{} {}M'.format(command, round(memoryUsage / 1024))
+ else:
+ legend = '{} {}K'.format(command, round(memoryUsage))
+ result.append([legend, memoryUsage])
+ else:
+ # Unix: Obtain memory usage percentage from 'ps'
+ psOptions = ['-e', 'v']
+ memoryColumn = 8
+ commandColumn = 9
+ if sys.platform == 'darwin':
+ psOptions = ['-e', '-v']
+ memoryColumn = 11
+ commandColumn = 12
+ for line in runProcess('ps', psOptions)[1:]:
+ tokens = line.split(None)
+ if len(tokens) > commandColumn: # Percentage and command
+ command = tokens[commandColumn]
+ if not command.startswith('['):
+ command = os.path.basename(command)
+ memoryUsage = round(float(tokens[memoryColumn].replace(',', '.')))
+ legend = '{} {}%'.format(command, memoryUsage)
+ result.append([legend, memoryUsage])
+
+ result.sort(key = lambda x: x[1], reverse=True)
+ return result
+
+class MainWindow(QMainWindow):
+
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ self.setWindowTitle('Memory Usage')
+
+ memoryUsage = getMemoryUsage()
+ if len(memoryUsage) > 5:
+ memoryUsage = memoryUsage[0:4]
+
+ self.series = QtCharts.QPieSeries()
+ for item in memoryUsage:
+ self.series.append(item[0], item[1]);
+
+ slice = self.series.slices()[0]
+ slice.setExploded();
+ slice.setLabelVisible();
+ self.chart = QtCharts.QChart()
+ self.chart.addSeries(self.series);
+ self.chartView = QtCharts.QChartView(self.chart)
+ self.setCentralWidget(self.chartView)
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ availableGeometry = app.desktop().availableGeometry(mainWin)
+ size = availableGeometry.height() * 3 / 4
+ mainWin.resize(size, size)
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/corelib/threads/mandelbrot.py b/examples/corelib/threads/mandelbrot.py
new file mode 100755
index 000000000..53da3d48d
--- /dev/null
+++ b/examples/corelib/threads/mandelbrot.py
@@ -0,0 +1,349 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the corelib/threads/mandelbrot example from Qt v5.x, originating from PyQt"""
+
+from PySide2.QtCore import (Signal, QMutex, QMutexLocker, QPoint, QSize, Qt,
+ QThread, QWaitCondition)
+from PySide2.QtGui import QColor, QImage, QPainter, QPixmap, qRgb
+from PySide2.QtWidgets import QApplication, QWidget
+
+
+DefaultCenterX = -0.647011
+DefaultCenterY = -0.0395159
+DefaultScale = 0.00403897
+
+ZoomInFactor = 0.8
+ZoomOutFactor = 1 / ZoomInFactor
+ScrollStep = 20
+
+
+class RenderThread(QThread):
+ ColormapSize = 512
+
+ renderedImage = Signal(QImage, float)
+
+ def __init__(self, parent=None):
+ super(RenderThread, self).__init__(parent)
+
+ self.mutex = QMutex()
+ self.condition = QWaitCondition()
+ self.centerX = 0.0
+ self.centerY = 0.0
+ self.scaleFactor = 0.0
+ self.resultSize = QSize()
+ self.colormap = []
+
+ self.restart = False
+ self.abort = False
+
+ for i in range(RenderThread.ColormapSize):
+ self.colormap.append(self.rgbFromWaveLength(380.0 + (i * 400.0 / RenderThread.ColormapSize)))
+
+ def stop(self):
+ self.mutex.lock()
+ self.abort = True
+ self.condition.wakeOne()
+ self.mutex.unlock()
+
+ self.wait(2000)
+
+ def render(self, centerX, centerY, scaleFactor, resultSize):
+ locker = QMutexLocker(self.mutex)
+
+ self.centerX = centerX
+ self.centerY = centerY
+ self.scaleFactor = scaleFactor
+ self.resultSize = resultSize
+
+ if not self.isRunning():
+ self.start(QThread.LowPriority)
+ else:
+ self.restart = True
+ self.condition.wakeOne()
+
+ def run(self):
+ while True:
+ self.mutex.lock()
+ resultSize = self.resultSize
+ scaleFactor = self.scaleFactor
+ centerX = self.centerX
+ centerY = self.centerY
+ self.mutex.unlock()
+
+ halfWidth = resultSize.width() // 2
+ halfHeight = resultSize.height() // 2
+ image = QImage(resultSize, QImage.Format_RGB32)
+
+ NumPasses = 8
+ curpass = 0
+
+ while curpass < NumPasses:
+ MaxIterations = (1 << (2 * curpass + 6)) + 32
+ Limit = 4
+ allBlack = True
+
+ for y in range(-halfHeight, halfHeight):
+ if self.restart:
+ break
+ if self.abort:
+ return
+
+ ay = 1j * (centerY + (y * scaleFactor))
+
+ for x in range(-halfWidth, halfWidth):
+ c0 = centerX + (x * scaleFactor) + ay
+ c = c0
+ numIterations = 0
+
+ while numIterations < MaxIterations:
+ numIterations += 1
+ c = c*c + c0
+ if abs(c) >= Limit:
+ break
+ numIterations += 1
+ c = c*c + c0
+ if abs(c) >= Limit:
+ break
+ numIterations += 1
+ c = c*c + c0
+ if abs(c) >= Limit:
+ break
+ numIterations += 1
+ c = c*c + c0
+ if abs(c) >= Limit:
+ break
+
+ if numIterations < MaxIterations:
+ image.setPixel(x + halfWidth, y + halfHeight,
+ self.colormap[numIterations % RenderThread.ColormapSize])
+ allBlack = False
+ else:
+ image.setPixel(x + halfWidth, y + halfHeight, qRgb(0, 0, 0))
+
+ if allBlack and curpass == 0:
+ curpass = 4
+ else:
+ if not self.restart:
+ self.renderedImage.emit(image, scaleFactor)
+ curpass += 1
+
+ self.mutex.lock()
+ if not self.restart:
+ self.condition.wait(self.mutex)
+ self.restart = False
+ self.mutex.unlock()
+
+ def rgbFromWaveLength(self, wave):
+ r = 0.0
+ g = 0.0
+ b = 0.0
+
+ if wave >= 380.0 and wave <= 440.0:
+ r = -1.0 * (wave - 440.0) / (440.0 - 380.0)
+ b = 1.0
+ elif wave >= 440.0 and wave <= 490.0:
+ g = (wave - 440.0) / (490.0 - 440.0)
+ b = 1.0
+ elif wave >= 490.0 and wave <= 510.0:
+ g = 1.0
+ b = -1.0 * (wave - 510.0) / (510.0 - 490.0)
+ elif wave >= 510.0 and wave <= 580.0:
+ r = (wave - 510.0) / (580.0 - 510.0)
+ g = 1.0
+ elif wave >= 580.0 and wave <= 645.0:
+ r = 1.0
+ g = -1.0 * (wave - 645.0) / (645.0 - 580.0)
+ elif wave >= 645.0 and wave <= 780.0:
+ r = 1.0
+
+ s = 1.0
+ if wave > 700.0:
+ s = 0.3 + 0.7 * (780.0 - wave) / (780.0 - 700.0)
+ elif wave < 420.0:
+ s = 0.3 + 0.7 * (wave - 380.0) / (420.0 - 380.0)
+
+ r = pow(r * s, 0.8)
+ g = pow(g * s, 0.8)
+ b = pow(b * s, 0.8)
+
+ return qRgb(r*255, g*255, b*255)
+
+
+class MandelbrotWidget(QWidget):
+ def __init__(self, parent=None):
+ super(MandelbrotWidget, self).__init__(parent)
+
+ self.thread = RenderThread()
+ self.pixmap = QPixmap()
+ self.pixmapOffset = QPoint()
+ self.lastDragPos = QPoint()
+
+ self.centerX = DefaultCenterX
+ self.centerY = DefaultCenterY
+ self.pixmapScale = DefaultScale
+ self.curScale = DefaultScale
+
+ self.thread.renderedImage.connect(self.updatePixmap)
+
+ self.setWindowTitle("Mandelbrot")
+ self.setCursor(Qt.CrossCursor)
+ self.resize(550, 400)
+
+ def paintEvent(self, event):
+ painter = QPainter(self)
+ painter.fillRect(self.rect(), Qt.black)
+
+ if self.pixmap.isNull():
+ painter.setPen(Qt.white)
+ painter.drawText(self.rect(), Qt.AlignCenter,
+ "Rendering initial image, please wait...")
+ return
+
+ if self.curScale == self.pixmapScale:
+ painter.drawPixmap(self.pixmapOffset, self.pixmap)
+ else:
+ scaleFactor = self.pixmapScale / self.curScale
+ newWidth = int(self.pixmap.width() * scaleFactor)
+ newHeight = int(self.pixmap.height() * scaleFactor)
+ newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2
+ newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2
+
+ painter.save()
+ painter.translate(newX, newY)
+ painter.scale(scaleFactor, scaleFactor)
+ exposed, _ = painter.matrix().inverted()
+ exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
+ painter.drawPixmap(exposed, self.pixmap, exposed)
+ painter.restore()
+
+ text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \
+ "hold left mouse button to scroll."
+ metrics = painter.fontMetrics()
+ textWidth = metrics.width(text)
+
+ painter.setPen(Qt.NoPen)
+ painter.setBrush(QColor(0, 0, 0, 127))
+ painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10,
+ metrics.lineSpacing() + 5)
+ painter.setPen(Qt.white)
+ painter.drawText((self.width() - textWidth) / 2,
+ metrics.leading() + metrics.ascent(), text)
+
+ def resizeEvent(self, event):
+ self.thread.render(self.centerX, self.centerY, self.curScale, self.size())
+
+ def keyPressEvent(self, event):
+ if event.key() == Qt.Key_Plus:
+ self.zoom(ZoomInFactor)
+ elif event.key() == Qt.Key_Minus:
+ self.zoom(ZoomOutFactor)
+ elif event.key() == Qt.Key_Left:
+ self.scroll(-ScrollStep, 0)
+ elif event.key() == Qt.Key_Right:
+ self.scroll(+ScrollStep, 0)
+ elif event.key() == Qt.Key_Down:
+ self.scroll(0, -ScrollStep)
+ elif event.key() == Qt.Key_Up:
+ self.scroll(0, +ScrollStep)
+ else:
+ super(MandelbrotWidget, self).keyPressEvent(event)
+
+ def wheelEvent(self, event):
+ numDegrees = event.angleDelta().y() / 8
+ numSteps = numDegrees / 15.0
+ self.zoom(pow(ZoomInFactor, numSteps))
+
+ def mousePressEvent(self, event):
+ if event.buttons() == Qt.LeftButton:
+ self.lastDragPos = QPoint(event.pos())
+
+ def mouseMoveEvent(self, event):
+ if event.buttons() & Qt.LeftButton:
+ self.pixmapOffset += event.pos() - self.lastDragPos
+ self.lastDragPos = QPoint(event.pos())
+ self.update()
+
+ def mouseReleaseEvent(self, event):
+ if event.button() == Qt.LeftButton:
+ self.pixmapOffset += event.pos() - self.lastDragPos
+ self.lastDragPos = QPoint()
+
+ deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x()
+ deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y()
+ self.scroll(deltaX, deltaY)
+
+ def updatePixmap(self, image, scaleFactor):
+ if not self.lastDragPos.isNull():
+ return
+
+ self.pixmap = QPixmap.fromImage(image)
+ self.pixmapOffset = QPoint()
+ self.lastDragPosition = QPoint()
+ self.pixmapScale = scaleFactor
+ self.update()
+
+ def zoom(self, zoomFactor):
+ self.curScale *= zoomFactor
+ self.update()
+ self.thread.render(self.centerX, self.centerY, self.curScale,
+ self.size())
+
+ def scroll(self, deltaX, deltaY):
+ self.centerX += deltaX * self.curScale
+ self.centerY += deltaY * self.curScale
+ self.update()
+ self.thread.render(self.centerX, self.centerY, self.curScale,
+ self.size())
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QApplication(sys.argv)
+ widget = MandelbrotWidget()
+ widget.show()
+ r = app.exec_()
+ widget.thread.stop()
+ sys.exit(r)
diff --git a/examples/corelib/tools/codecs/codecs.py b/examples/corelib/tools/codecs/codecs.py
new file mode 100755
index 000000000..15f7d9563
--- /dev/null
+++ b/examples/corelib/tools/codecs/codecs.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the widgets/tools/codecs example from Qt v5.x"""
+
+from PySide2 import QtCore, QtGui, QtWidgets
+
+
+def codec_name(codec):
+ try:
+ # Python v3.
+ name = str(codec.name(), encoding='ascii')
+ except TypeError:
+ # Python v2.
+ name = str(codec.name())
+
+ return name
+
+
+class MainWindow(QtWidgets.QMainWindow):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ self.textEdit = QtWidgets.QTextEdit()
+ self.textEdit.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
+ self.setCentralWidget(self.textEdit)
+
+ self.codecs = []
+ self.findCodecs()
+
+ self.previewForm = PreviewForm(self)
+ self.previewForm.setCodecList(self.codecs)
+
+ self.saveAsActs = []
+ self.createActions()
+ self.createMenus()
+
+ self.setWindowTitle("Codecs")
+ self.resize(500, 400)
+
+ def open(self):
+ fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self)
+ if fileName:
+ inFile = QtCore.QFile(fileName)
+ if not inFile.open(QtCore.QFile.ReadOnly):
+ QtWidgets.QMessageBox.warning(self, "Codecs",
+ "Cannot read file %s:\n%s" % (fileName, inFile.errorString()))
+ return
+
+ data = inFile.readAll()
+
+ self.previewForm.setEncodedData(data)
+ if self.previewForm.exec_():
+ self.textEdit.setPlainText(self.previewForm.decodedString())
+
+ def save(self):
+ fileName = QtWidgets.QFileDialog.getSaveFileName(self)
+ if fileName:
+ outFile = QtCore.QFile(fileName)
+ if not outFile.open(QtCore.QFile.WriteOnly|QtCore.QFile.Text):
+ QtWidgets.QMessageBox.warning(self, "Codecs",
+ "Cannot write file %s:\n%s" % (fileName, outFile.errorString()))
+ return
+
+ action = self.sender()
+ codecName = action.data()
+
+ out = QtCore.QTextStream(outFile)
+ out.setCodec(codecName)
+ out << self.textEdit.toPlainText()
+
+ def about(self):
+ QtWidgets.QMessageBox.about(self, "About Codecs",
+ "The <b>Codecs</b> example demonstrates how to read and "
+ "write files using various encodings.")
+
+ def aboutToShowSaveAsMenu(self):
+ currentText = self.textEdit.toPlainText()
+
+ for action in self.saveAsActs:
+ codecName = str(action.data())
+ codec = QtCore.QTextCodec.codecForName(codecName)
+ action.setVisible(codec and codec.canEncode(currentText))
+
+ def findCodecs(self):
+ codecMap = []
+ iso8859RegExp = QtCore.QRegExp('ISO[- ]8859-([0-9]+).*')
+
+ for mib in QtCore.QTextCodec.availableMibs():
+ codec = QtCore.QTextCodec.codecForMib(mib)
+ sortKey = codec_name(codec).upper()
+ rank = 0
+
+ if sortKey.startswith('UTF-8'):
+ rank = 1
+ elif sortKey.startswith('UTF-16'):
+ rank = 2
+ elif iso8859RegExp.exactMatch(sortKey):
+ if len(iso8859RegExp.cap(1)) == 1:
+ rank = 3
+ else:
+ rank = 4
+ else:
+ rank = 5
+
+ codecMap.append((str(rank) + sortKey, codec))
+
+ codecMap.sort()
+ self.codecs = [item[-1] for item in codecMap]
+
+ def createActions(self):
+ self.openAct = QtWidgets.QAction("&Open...", self, shortcut="Ctrl+O",
+ triggered=self.open)
+
+ for codec in self.codecs:
+ name = codec_name(codec)
+
+ action = QtWidgets.QAction(name + '...', self, triggered=self.save)
+ action.setData(name)
+ self.saveAsActs.append(action)
+
+ self.exitAct = QtWidgets.QAction("E&xit", self, shortcut="Ctrl+Q",
+ triggered=self.close)
+
+ self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)
+
+ self.aboutQtAct = QtWidgets.QAction("About &Qt", self,
+ triggered=QtWidgets.qApp.aboutQt)
+
+ def createMenus(self):
+ self.saveAsMenu = QtWidgets.QMenu("&Save As", self)
+ for action in self.saveAsActs:
+ self.saveAsMenu.addAction(action)
+
+ self.saveAsMenu.aboutToShow.connect(self.aboutToShowSaveAsMenu)
+
+ self.fileMenu = QtWidgets.QMenu("&File", self)
+ self.fileMenu.addAction(self.openAct)
+ self.fileMenu.addMenu(self.saveAsMenu)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.helpMenu = QtWidgets.QMenu("&Help", self)
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ self.menuBar().addMenu(self.fileMenu)
+ self.menuBar().addSeparator()
+ self.menuBar().addMenu(self.helpMenu)
+
+
+class PreviewForm(QtWidgets.QDialog):
+ def __init__(self, parent):
+ super(PreviewForm, self).__init__(parent)
+
+ self.encodingComboBox = QtWidgets.QComboBox()
+ encodingLabel = QtWidgets.QLabel("&Encoding:")
+ encodingLabel.setBuddy(self.encodingComboBox)
+
+ self.textEdit = QtWidgets.QTextEdit()
+ self.textEdit.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
+ self.textEdit.setReadOnly(True)
+
+ buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
+
+ self.encodingComboBox.activated.connect(self.updateTextEdit)
+ buttonBox.accepted.connect(self.accept)
+ buttonBox.rejected.connect(self.reject)
+
+ mainLayout = QtWidgets.QGridLayout()
+ mainLayout.addWidget(encodingLabel, 0, 0)
+ mainLayout.addWidget(self.encodingComboBox, 0, 1)
+ mainLayout.addWidget(self.textEdit, 1, 0, 1, 2)
+ mainLayout.addWidget(buttonBox, 2, 0, 1, 2)
+ self.setLayout(mainLayout)
+
+ self.setWindowTitle("Choose Encoding")
+ self.resize(400, 300)
+
+ def setCodecList(self, codecs):
+ self.encodingComboBox.clear()
+ for codec in codecs:
+ self.encodingComboBox.addItem(codec_name(codec), codec.mibEnum())
+
+ def setEncodedData(self, data):
+ self.encodedData = data
+ self.updateTextEdit()
+
+ def decodedString(self):
+ return self.decodedStr
+
+ def updateTextEdit(self):
+ mib = self.encodingComboBox.itemData(self.encodingComboBox.currentIndex())
+ codec = QtCore.QTextCodec.codecForMib(mib)
+
+ data = QtCore.QTextStream(self.encodedData)
+ data.setAutoDetectUnicode(False)
+ data.setCodec(codec)
+
+ self.decodedStr = data.readAll()
+ self.textEdit.setPlainText(self.decodedStr)
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ mainWin = MainWindow()
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/corelib/tools/regexp.py b/examples/corelib/tools/regexp.py
new file mode 100755
index 000000000..7e28a5365
--- /dev/null
+++ b/examples/corelib/tools/regexp.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the widgets/tools/regexp example from Qt v5.x"""
+
+from PySide2 import QtCore, QtGui, QtWidgets
+
+
+class RegExpDialog(QtWidgets.QDialog):
+ MaxCaptures = 6
+
+ def __init__(self, parent=None):
+ super(RegExpDialog, self).__init__(parent)
+
+ self.patternComboBox = QtWidgets.QComboBox()
+ self.patternComboBox.setEditable(True)
+ self.patternComboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
+ QtWidgets.QSizePolicy.Preferred)
+
+ patternLabel = QtWidgets.QLabel("&Pattern:")
+ patternLabel.setBuddy(self.patternComboBox)
+
+ self.escapedPatternLineEdit = QtWidgets.QLineEdit()
+ self.escapedPatternLineEdit.setReadOnly(True)
+ palette = self.escapedPatternLineEdit.palette()
+ palette.setBrush(QtGui.QPalette.Base,
+ palette.brush(QtGui.QPalette.Disabled, QtGui.QPalette.Base))
+ self.escapedPatternLineEdit.setPalette(palette)
+
+ escapedPatternLabel = QtWidgets.QLabel("&Escaped Pattern:")
+ escapedPatternLabel.setBuddy(self.escapedPatternLineEdit)
+
+ self.syntaxComboBox = QtWidgets.QComboBox()
+ self.syntaxComboBox.addItem("Regular expression v1",
+ QtCore.QRegExp.RegExp)
+ self.syntaxComboBox.addItem("Regular expression v2",
+ QtCore.QRegExp.RegExp2)
+ self.syntaxComboBox.addItem("Wildcard", QtCore.QRegExp.Wildcard)
+ self.syntaxComboBox.addItem("Fixed string",
+ QtCore.QRegExp.FixedString)
+
+ syntaxLabel = QtWidgets.QLabel("&Pattern Syntax:")
+ syntaxLabel.setBuddy(self.syntaxComboBox)
+
+ self.textComboBox = QtWidgets.QComboBox()
+ self.textComboBox.setEditable(True)
+ self.textComboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
+ QtWidgets.QSizePolicy.Preferred)
+
+ textLabel = QtWidgets.QLabel("&Text:")
+ textLabel.setBuddy(self.textComboBox)
+
+ self.caseSensitiveCheckBox = QtWidgets.QCheckBox("Case &Sensitive")
+ self.caseSensitiveCheckBox.setChecked(True)
+ self.minimalCheckBox = QtWidgets.QCheckBox("&Minimal")
+
+ indexLabel = QtWidgets.QLabel("Index of Match:")
+ self.indexEdit = QtWidgets.QLineEdit()
+ self.indexEdit.setReadOnly(True)
+
+ matchedLengthLabel = QtWidgets.QLabel("Matched Length:")
+ self.matchedLengthEdit = QtWidgets.QLineEdit()
+ self.matchedLengthEdit.setReadOnly(True)
+
+ self.captureLabels = []
+ self.captureEdits = []
+ for i in range(self.MaxCaptures):
+ self.captureLabels.append(QtWidgets.QLabel("Capture %d:" % i))
+ self.captureEdits.append(QtWidgets.QLineEdit())
+ self.captureEdits[i].setReadOnly(True)
+ self.captureLabels[0].setText("Match:")
+
+ checkBoxLayout = QtWidgets.QHBoxLayout()
+ checkBoxLayout.addWidget(self.caseSensitiveCheckBox)
+ checkBoxLayout.addWidget(self.minimalCheckBox)
+ checkBoxLayout.addStretch(1)
+
+ mainLayout = QtWidgets.QGridLayout()
+ mainLayout.addWidget(patternLabel, 0, 0)
+ mainLayout.addWidget(self.patternComboBox, 0, 1)
+ mainLayout.addWidget(escapedPatternLabel, 1, 0)
+ mainLayout.addWidget(self.escapedPatternLineEdit, 1, 1)
+ mainLayout.addWidget(syntaxLabel, 2, 0)
+ mainLayout.addWidget(self.syntaxComboBox, 2, 1)
+ mainLayout.addLayout(checkBoxLayout, 3, 0, 1, 2)
+ mainLayout.addWidget(textLabel, 4, 0)
+ mainLayout.addWidget(self.textComboBox, 4, 1)
+ mainLayout.addWidget(indexLabel, 5, 0)
+ mainLayout.addWidget(self.indexEdit, 5, 1)
+ mainLayout.addWidget(matchedLengthLabel, 6, 0)
+ mainLayout.addWidget(self.matchedLengthEdit, 6, 1)
+
+ for i in range(self.MaxCaptures):
+ mainLayout.addWidget(self.captureLabels[i], 7 + i, 0)
+ mainLayout.addWidget(self.captureEdits[i], 7 + i, 1)
+ self.setLayout(mainLayout)
+
+ self.patternComboBox.editTextChanged.connect(self.refresh)
+ self.textComboBox.editTextChanged.connect(self.refresh)
+ self.caseSensitiveCheckBox.toggled.connect(self.refresh)
+ self.minimalCheckBox.toggled.connect(self.refresh)
+ self.syntaxComboBox.currentIndexChanged.connect(self.refresh)
+
+ self.patternComboBox.addItem("[A-Za-z_]+([A-Za-z_0-9]*)")
+ self.textComboBox.addItem("(10 + delta4)* 32")
+
+ self.setWindowTitle("RegExp")
+ self.setFixedHeight(self.sizeHint().height())
+ self.refresh()
+
+ def refresh(self):
+ self.setUpdatesEnabled(False)
+
+ pattern = self.patternComboBox.currentText()
+ text = self.textComboBox.currentText()
+
+ escaped = str(pattern)
+ escaped.replace('\\', '\\\\')
+ escaped.replace('"', '\\"')
+ self.escapedPatternLineEdit.setText('"' + escaped + '"')
+
+ rx = QtCore.QRegExp(pattern)
+ cs = QtCore.Qt.CaseInsensitive
+ if self.caseSensitiveCheckBox.isChecked():
+ cs = QtCore.Qt.CaseSensitive
+ rx.setCaseSensitivity(cs)
+ rx.setMinimal(self.minimalCheckBox.isChecked())
+ syntax = self.syntaxComboBox.itemData(self.syntaxComboBox.currentIndex())
+ rx.setPatternSyntax(QtCore.QRegExp.PatternSyntax(syntax))
+
+ palette = self.patternComboBox.palette()
+ if rx.isValid():
+ palette.setColor(QtGui.QPalette.Text,
+ self.textComboBox.palette().color(QtGui.QPalette.Text))
+ else:
+ palette.setColor(QtGui.QPalette.Text, QtCore.Qt.red)
+ self.patternComboBox.setPalette(palette)
+
+ self.indexEdit.setText(str(rx.indexIn(text)))
+ self.matchedLengthEdit.setText(str(rx.matchedLength()))
+
+ for i in range(self.MaxCaptures):
+ self.captureLabels[i].setEnabled(i <= rx.captureCount())
+ self.captureEdits[i].setEnabled(i <= rx.captureCount())
+ self.captureEdits[i].setText(rx.cap(i))
+
+ self.setUpdatesEnabled(True)
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ dialog = RegExpDialog()
+ sys.exit(dialog.exec_())
diff --git a/examples/corelib/tools/settingseditor/settingseditor.py b/examples/corelib/tools/settingseditor/settingseditor.py
new file mode 100755
index 000000000..905049746
--- /dev/null
+++ b/examples/corelib/tools/settingseditor/settingseditor.py
@@ -0,0 +1,722 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the widgets/tools/settingseditor example from Qt v5.x"""
+
+import sys
+
+from PySide2 import QtCore, QtGui, QtWidgets
+
+
+class MainWindow(QtWidgets.QMainWindow):
+ def __init__(self, parent=None):
+ super(MainWindow, self).__init__(parent)
+
+ self.settingsTree = SettingsTree()
+ self.setCentralWidget(self.settingsTree)
+
+ self.locationDialog = None
+
+ self.createActions()
+ self.createMenus()
+
+ self.autoRefreshAct.setChecked(True)
+ self.fallbacksAct.setChecked(True)
+
+ self.setWindowTitle("Settings Editor")
+ self.resize(500, 600)
+
+ def openSettings(self):
+ if self.locationDialog is None:
+ self.locationDialog = LocationDialog(self)
+
+ if self.locationDialog.exec_():
+ settings = QtCore.QSettings(self.locationDialog.format(),
+ self.locationDialog.scope(),
+ self.locationDialog.organization(),
+ self.locationDialog.application())
+ self.setSettingsObject(settings)
+ self.fallbacksAct.setEnabled(True)
+
+ def openIniFile(self):
+ fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Open INI File",
+ '', "INI Files (*.ini *.conf)")
+
+ if fileName:
+ settings = QtCore.QSettings(fileName, QtCore.QSettings.IniFormat)
+ self.setSettingsObject(settings)
+ self.fallbacksAct.setEnabled(False)
+
+ def openPropertyList(self):
+ fileName, _ = QtWidgets.QFileDialog.getOpenFileName(self,
+ "Open Property List", '', "Property List Files (*.plist)")
+
+ if fileName:
+ settings = QtCore.QSettings(fileName, QtCore.QSettings.NativeFormat)
+ self.setSettingsObject(settings)
+ self.fallbacksAct.setEnabled(False)
+
+ def openRegistryPath(self):
+ path, ok = QtWidgets.QInputDialog.getText(self, "Open Registry Path",
+ "Enter the path in the Windows registry:",
+ QtWidgets.QLineEdit.Normal, 'HKEY_CURRENT_USER\\')
+
+ if ok and path != '':
+ settings = QtCore.QSettings(path, QtCore.QSettings.NativeFormat)
+ self.setSettingsObject(settings)
+ self.fallbacksAct.setEnabled(False)
+
+ def about(self):
+ QtWidgets.QMessageBox.about(self, "About Settings Editor",
+ "The <b>Settings Editor</b> example shows how to access "
+ "application settings using Qt.")
+
+ def createActions(self):
+ self.openSettingsAct = QtWidgets.QAction("&Open Application Settings...",
+ self, shortcut="Ctrl+O", triggered=self.openSettings)
+
+ self.openIniFileAct = QtWidgets.QAction("Open I&NI File...", self,
+ shortcut="Ctrl+N", triggered=self.openIniFile)
+
+ self.openPropertyListAct = QtWidgets.QAction("Open macOS &Property List...",
+ self, shortcut="Ctrl+P", triggered=self.openPropertyList)
+ if sys.platform != 'darwin':
+ self.openPropertyListAct.setEnabled(False)
+
+ self.openRegistryPathAct = QtWidgets.QAction(
+ "Open Windows &Registry Path...", self, shortcut="Ctrl+G",
+ triggered=self.openRegistryPath)
+ if sys.platform != 'win32':
+ self.openRegistryPathAct.setEnabled(False)
+
+ self.refreshAct = QtWidgets.QAction("&Refresh", self, shortcut="Ctrl+R",
+ enabled=False, triggered=self.settingsTree.refresh)
+
+ self.exitAct = QtWidgets.QAction("E&xit", self, shortcut="Ctrl+Q",
+ triggered=self.close)
+
+ self.autoRefreshAct = QtWidgets.QAction("&Auto-Refresh", self,
+ shortcut="Ctrl+A", checkable=True, enabled=False)
+ self.autoRefreshAct.triggered[bool].connect(self.settingsTree.setAutoRefresh)
+ self.autoRefreshAct.triggered[bool].connect(self.refreshAct.setDisabled)
+
+ self.fallbacksAct = QtWidgets.QAction("&Fallbacks", self,
+ shortcut="Ctrl+F", checkable=True, enabled=False)
+ self.fallbacksAct.triggered[bool].connect(self.settingsTree.setFallbacksEnabled)
+
+ self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)
+
+ self.aboutQtAct = QtWidgets.QAction("About &Qt", self,
+ triggered=QtWidgets.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.openSettingsAct)
+ self.fileMenu.addAction(self.openIniFileAct)
+ self.fileMenu.addAction(self.openPropertyListAct)
+ self.fileMenu.addAction(self.openRegistryPathAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.refreshAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.optionsMenu = self.menuBar().addMenu("&Options")
+ self.optionsMenu.addAction(self.autoRefreshAct)
+ self.optionsMenu.addAction(self.fallbacksAct)
+
+ self.menuBar().addSeparator()
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def setSettingsObject(self, settings):
+ settings.setFallbacksEnabled(self.fallbacksAct.isChecked())
+ self.settingsTree.setSettingsObject(settings)
+
+ self.refreshAct.setEnabled(True)
+ self.autoRefreshAct.setEnabled(True)
+
+ niceName = settings.fileName()
+ niceName.replace('\\', '/')
+ niceName = niceName.split('/')[-1]
+
+ if not settings.isWritable():
+ niceName += " (read only)"
+
+ self.setWindowTitle("%s - Settings Editor" % niceName)
+
+
+class LocationDialog(QtWidgets.QDialog):
+ def __init__(self, parent=None):
+ super(LocationDialog, self).__init__(parent)
+
+ self.formatComboBox = QtWidgets.QComboBox()
+ self.formatComboBox.addItem("Native")
+ self.formatComboBox.addItem("INI")
+
+ self.scopeComboBox = QtWidgets.QComboBox()
+ self.scopeComboBox.addItem("User")
+ self.scopeComboBox.addItem("System")
+
+ self.organizationComboBox = QtWidgets.QComboBox()
+ self.organizationComboBox.addItem("Trolltech")
+ self.organizationComboBox.setEditable(True)
+
+ self.applicationComboBox = QtWidgets.QComboBox()
+ self.applicationComboBox.addItem("Any")
+ self.applicationComboBox.addItem("Application Example")
+ self.applicationComboBox.addItem("Assistant")
+ self.applicationComboBox.addItem("Designer")
+ self.applicationComboBox.addItem("Linguist")
+ self.applicationComboBox.setEditable(True)
+ self.applicationComboBox.setCurrentIndex(3)
+
+ formatLabel = QtWidgets.QLabel("&Format:")
+ formatLabel.setBuddy(self.formatComboBox)
+
+ scopeLabel = QtWidgets.QLabel("&Scope:")
+ scopeLabel.setBuddy(self.scopeComboBox)
+
+ organizationLabel = QtWidgets.QLabel("&Organization:")
+ organizationLabel.setBuddy(self.organizationComboBox)
+
+ applicationLabel = QtWidgets.QLabel("&Application:")
+ applicationLabel.setBuddy(self.applicationComboBox)
+
+ self.locationsGroupBox = QtWidgets.QGroupBox("Setting Locations")
+
+ self.locationsTable = QtWidgets.QTableWidget()
+ self.locationsTable.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
+ self.locationsTable.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
+ self.locationsTable.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
+ self.locationsTable.setColumnCount(2)
+ self.locationsTable.setHorizontalHeaderLabels(("Location", "Access"))
+ self.locationsTable.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
+ self.locationsTable.horizontalHeader().resizeSection(1, 180)
+
+ self.buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
+
+ self.formatComboBox.activated.connect(self.updateLocationsTable)
+ self.scopeComboBox.activated.connect(self.updateLocationsTable)
+ self.organizationComboBox.lineEdit().editingFinished.connect(self.updateLocationsTable)
+ self.applicationComboBox.lineEdit().editingFinished.connect(self.updateLocationsTable)
+ self.buttonBox.accepted.connect(self.accept)
+ self.buttonBox.rejected.connect(self.reject)
+
+ locationsLayout = QtWidgets.QVBoxLayout()
+ locationsLayout.addWidget(self.locationsTable)
+ self.locationsGroupBox.setLayout(locationsLayout)
+
+ mainLayout = QtWidgets.QGridLayout()
+ mainLayout.addWidget(formatLabel, 0, 0)
+ mainLayout.addWidget(self.formatComboBox, 0, 1)
+ mainLayout.addWidget(scopeLabel, 1, 0)
+ mainLayout.addWidget(self.scopeComboBox, 1, 1)
+ mainLayout.addWidget(organizationLabel, 2, 0)
+ mainLayout.addWidget(self.organizationComboBox, 2, 1)
+ mainLayout.addWidget(applicationLabel, 3, 0)
+ mainLayout.addWidget(self.applicationComboBox, 3, 1)
+ mainLayout.addWidget(self.locationsGroupBox, 4, 0, 1, 2)
+ mainLayout.addWidget(self.buttonBox, 5, 0, 1, 2)
+ self.setLayout(mainLayout)
+
+ self.updateLocationsTable()
+
+ self.setWindowTitle("Open Application Settings")
+ self.resize(650, 400)
+
+ def format(self):
+ if self.formatComboBox.currentIndex() == 0:
+ return QtCore.QSettings.NativeFormat
+ else:
+ return QtCore.QSettings.IniFormat
+
+ def scope(self):
+ if self.scopeComboBox.currentIndex() == 0:
+ return QtCore.QSettings.UserScope
+ else:
+ return QtCore.QSettings.SystemScope
+
+ def organization(self):
+ return self.organizationComboBox.currentText()
+
+ def application(self):
+ if self.applicationComboBox.currentText() == "Any":
+ return ''
+
+ return self.applicationComboBox.currentText()
+
+ def updateLocationsTable(self):
+ self.locationsTable.setUpdatesEnabled(False)
+ self.locationsTable.setRowCount(0)
+
+ for i in range(2):
+ if i == 0:
+ if self.scope() == QtCore.QSettings.SystemScope:
+ continue
+
+ actualScope = QtCore.QSettings.UserScope
+ else:
+ actualScope = QtCore.QSettings.SystemScope
+
+ for j in range(2):
+ if j == 0:
+ if not self.application():
+ continue
+
+ actualApplication = self.application()
+ else:
+ actualApplication = ''
+
+ settings = QtCore.QSettings(self.format(), actualScope,
+ self.organization(), actualApplication)
+
+ row = self.locationsTable.rowCount()
+ self.locationsTable.setRowCount(row + 1)
+
+ item0 = QtWidgets.QTableWidgetItem()
+ item0.setText(settings.fileName())
+
+ item1 = QtWidgets.QTableWidgetItem()
+ disable = not (settings.childKeys() or settings.childGroups())
+
+ if row == 0:
+ if settings.isWritable():
+ item1.setText("Read-write")
+ disable = False
+ else:
+ item1.setText("Read-only")
+ self.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setDisabled(disable)
+ else:
+ item1.setText("Read-only fallback")
+
+ if disable:
+ item0.setFlags(item0.flags() & ~QtCore.Qt.ItemIsEnabled)
+ item1.setFlags(item1.flags() & ~QtCore.Qt.ItemIsEnabled)
+
+ self.locationsTable.setItem(row, 0, item0)
+ self.locationsTable.setItem(row, 1, item1)
+
+ self.locationsTable.setUpdatesEnabled(True)
+
+
+class SettingsTree(QtWidgets.QTreeWidget):
+ def __init__(self, parent=None):
+ super(SettingsTree, self).__init__(parent)
+
+ self.setItemDelegate(VariantDelegate(self))
+
+ self.setHeaderLabels(("Setting", "Type", "Value"))
+ self.header().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
+ self.header().setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)
+
+ self.settings = None
+ self.refreshTimer = QtCore.QTimer()
+ self.refreshTimer.setInterval(2000)
+ self.autoRefresh = False
+
+ self.groupIcon = QtGui.QIcon()
+ self.groupIcon.addPixmap(self.style().standardPixmap(QtWidgets.QStyle.SP_DirClosedIcon),
+ QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.groupIcon.addPixmap(self.style().standardPixmap(QtWidgets.QStyle.SP_DirOpenIcon),
+ QtGui.QIcon.Normal, QtGui.QIcon.On)
+ self.keyIcon = QtGui.QIcon()
+ self.keyIcon.addPixmap(self.style().standardPixmap(QtWidgets.QStyle.SP_FileIcon))
+
+ self.refreshTimer.timeout.connect(self.maybeRefresh)
+
+ def setSettingsObject(self, settings):
+ self.settings = settings
+ self.clear()
+
+ if self.settings is not None:
+ self.settings.setParent(self)
+ self.refresh()
+ if self.autoRefresh:
+ self.refreshTimer.start()
+ else:
+ self.refreshTimer.stop()
+
+ def sizeHint(self):
+ return QtCore.QSize(800, 600)
+
+ def setAutoRefresh(self, autoRefresh):
+ self.autoRefresh = autoRefresh
+
+ if self.settings is not None:
+ if self.autoRefresh:
+ self.maybeRefresh()
+ self.refreshTimer.start()
+ else:
+ self.refreshTimer.stop()
+
+ def setFallbacksEnabled(self, enabled):
+ if self.settings is not None:
+ self.settings.setFallbacksEnabled(enabled)
+ self.refresh()
+
+ def maybeRefresh(self):
+ if self.state() != QtWidgets.QAbstractItemView.EditingState:
+ self.refresh()
+
+ def refresh(self):
+ if self.settings is None:
+ return
+
+ # The signal might not be connected.
+ try:
+ self.itemChanged.disconnect(self.updateSetting)
+ except:
+ pass
+
+ self.settings.sync()
+ self.updateChildItems(None)
+
+ self.itemChanged.connect(self.updateSetting)
+
+ def event(self, event):
+ if event.type() == QtCore.QEvent.WindowActivate:
+ if self.isActiveWindow() and self.autoRefresh:
+ self.maybeRefresh()
+
+ return super(SettingsTree, self).event(event)
+
+ def updateSetting(self, item):
+ key = item.text(0)
+ ancestor = item.parent()
+
+ while ancestor:
+ key = ancestor.text(0) + '/' + key
+ ancestor = ancestor.parent()
+
+ d = item.data(2, QtCore.Qt.UserRole)
+ self.settings.setValue(key, item.data(2, QtCore.Qt.UserRole))
+
+ if self.autoRefresh:
+ self.refresh()
+
+ def updateChildItems(self, parent):
+ dividerIndex = 0
+
+ for group in self.settings.childGroups():
+ childIndex = self.findChild(parent, group, dividerIndex)
+ if childIndex != -1:
+ child = self.childAt(parent, childIndex)
+ child.setText(1, '')
+ child.setText(2, '')
+ child.setData(2, QtCore.Qt.UserRole, None)
+ self.moveItemForward(parent, childIndex, dividerIndex)
+ else:
+ child = self.createItem(group, parent, dividerIndex)
+
+ child.setIcon(0, self.groupIcon)
+ dividerIndex += 1
+
+ self.settings.beginGroup(group)
+ self.updateChildItems(child)
+ self.settings.endGroup()
+
+ for key in self.settings.childKeys():
+ childIndex = self.findChild(parent, key, 0)
+ if childIndex == -1 or childIndex >= dividerIndex:
+ if childIndex != -1:
+ child = self.childAt(parent, childIndex)
+ for i in range(child.childCount()):
+ self.deleteItem(child, i)
+ self.moveItemForward(parent, childIndex, dividerIndex)
+ else:
+ child = self.createItem(key, parent, dividerIndex)
+ child.setIcon(0, self.keyIcon)
+ dividerIndex += 1
+ else:
+ child = self.childAt(parent, childIndex)
+
+ value = self.settings.value(key)
+ if value is None:
+ child.setText(1, 'Invalid')
+ else:
+ child.setText(1, value.__class__.__name__)
+ child.setText(2, VariantDelegate.displayText(value))
+ child.setData(2, QtCore.Qt.UserRole, value)
+
+ while dividerIndex < self.childCount(parent):
+ self.deleteItem(parent, dividerIndex)
+
+ def createItem(self, text, parent, index):
+ after = None
+
+ if index != 0:
+ after = self.childAt(parent, index - 1)
+
+ if parent is not None:
+ item = QtWidgets.QTreeWidgetItem(parent, after)
+ else:
+ item = QtWidgets.QTreeWidgetItem(self, after)
+
+ item.setText(0, text)
+ item.setFlags(item.flags() | QtCore.Qt.ItemIsEditable)
+ return item
+
+ def deleteItem(self, parent, index):
+ if parent is not None:
+ item = parent.takeChild(index)
+ else:
+ item = self.takeTopLevelItem(index)
+ del item
+
+ def childAt(self, parent, index):
+ if parent is not None:
+ return parent.child(index)
+ else:
+ return self.topLevelItem(index)
+
+ def childCount(self, parent):
+ if parent is not None:
+ return parent.childCount()
+ else:
+ return self.topLevelItemCount()
+
+ def findChild(self, parent, text, startIndex):
+ for i in range(self.childCount(parent)):
+ if self.childAt(parent, i).text(0) == text:
+ return i
+ return -1
+
+ def moveItemForward(self, parent, oldIndex, newIndex):
+ for int in range(oldIndex - newIndex):
+ self.deleteItem(parent, newIndex)
+
+
+class VariantDelegate(QtWidgets.QItemDelegate):
+ def __init__(self, parent=None):
+ super(VariantDelegate, self).__init__(parent)
+
+ self.boolExp = QtCore.QRegExp()
+ self.boolExp.setPattern('true|false')
+ self.boolExp.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
+
+ self.byteArrayExp = QtCore.QRegExp()
+ self.byteArrayExp.setPattern('[\\x00-\\xff]*')
+
+ self.charExp = QtCore.QRegExp()
+ self.charExp.setPattern('.')
+
+ self.colorExp = QtCore.QRegExp()
+ self.colorExp.setPattern('\\(([0-9]*),([0-9]*),([0-9]*),([0-9]*)\\)')
+
+ self.doubleExp = QtCore.QRegExp()
+ self.doubleExp.setPattern('')
+
+ self.pointExp = QtCore.QRegExp()
+ self.pointExp.setPattern('\\((-?[0-9]*),(-?[0-9]*)\\)')
+
+ self.rectExp = QtCore.QRegExp()
+ self.rectExp.setPattern('\\((-?[0-9]*),(-?[0-9]*),(-?[0-9]*),(-?[0-9]*)\\)')
+
+ self.signedIntegerExp = QtCore.QRegExp()
+ self.signedIntegerExp.setPattern('-?[0-9]*')
+
+ self.sizeExp = QtCore.QRegExp(self.pointExp)
+
+ self.unsignedIntegerExp = QtCore.QRegExp()
+ self.unsignedIntegerExp.setPattern('[0-9]*')
+
+ self.dateExp = QtCore.QRegExp()
+ self.dateExp.setPattern('([0-9]{,4})-([0-9]{,2})-([0-9]{,2})')
+
+ self.timeExp = QtCore.QRegExp()
+ self.timeExp.setPattern('([0-9]{,2}):([0-9]{,2}):([0-9]{,2})')
+
+ self.dateTimeExp = QtCore.QRegExp()
+ self.dateTimeExp.setPattern(self.dateExp.pattern() + 'T' + self.timeExp.pattern())
+
+ def paint(self, painter, option, index):
+ if index.column() == 2:
+ value = index.model().data(index, QtCore.Qt.UserRole)
+ if not self.isSupportedType(value):
+ myOption = QtWidgets.QStyleOptionViewItem(option)
+ myOption.state &= ~QtWidgets.QStyle.State_Enabled
+ super(VariantDelegate, self).paint(painter, myOption, index)
+ return
+
+ super(VariantDelegate, self).paint(painter, option, index)
+
+ def createEditor(self, parent, option, index):
+ if index.column() != 2:
+ return None
+
+ originalValue = index.model().data(index, QtCore.Qt.UserRole)
+ if not self.isSupportedType(originalValue):
+ return None
+
+ lineEdit = QtWidgets.QLineEdit(parent)
+ lineEdit.setFrame(False)
+
+ if isinstance(originalValue, bool):
+ regExp = self.boolExp
+ elif isinstance(originalValue, float):
+ regExp = self.doubleExp
+ elif isinstance(originalValue, int):
+ regExp = self.signedIntegerExp
+ elif isinstance(originalValue, QtCore.QByteArray):
+ regExp = self.byteArrayExp
+ elif isinstance(originalValue, QtGui.QColor):
+ regExp = self.colorExp
+ elif isinstance(originalValue, QtCore.QDate):
+ regExp = self.dateExp
+ elif isinstance(originalValue, QtCore.QDateTime):
+ regExp = self.dateTimeExp
+ elif isinstance(originalValue, QtCore.QTime):
+ regExp = self.timeExp
+ elif isinstance(originalValue, QtCore.QPoint):
+ regExp = self.pointExp
+ elif isinstance(originalValue, QtCore.QRect):
+ regExp = self.rectExp
+ elif isinstance(originalValue, QtCore.QSize):
+ regExp = self.sizeExp
+ else:
+ regExp = QtCore.QRegExp()
+
+ if not regExp.isEmpty():
+ validator = QtGui.QRegExpValidator(regExp, lineEdit)
+ lineEdit.setValidator(validator)
+
+ return lineEdit
+
+ def setEditorData(self, editor, index):
+ value = index.model().data(index, QtCore.Qt.UserRole)
+ if editor is not None:
+ editor.setText(self.displayText(value))
+
+ def setModelData(self, editor, model, index):
+ if not editor.isModified():
+ return
+
+ text = editor.text()
+ validator = editor.validator()
+ if validator is not None:
+ state, text, _ = validator.validate(text, 0)
+ if state != QtGui.QValidator.Acceptable:
+ return
+
+ originalValue = index.model().data(index, QtCore.Qt.UserRole)
+
+ if isinstance(originalValue, QtGui.QColor):
+ self.colorExp.exactMatch(text)
+ value = QtGui.QColor(min(int(self.colorExp.cap(1)), 255),
+ min(int(self.colorExp.cap(2)), 255),
+ min(int(self.colorExp.cap(3)), 255),
+ min(int(self.colorExp.cap(4)), 255))
+ elif isinstance(originalValue, QtCore.QDate):
+ value = QtCore.QDate.fromString(text, QtCore.Qt.ISODate)
+ if not value.isValid():
+ return
+ elif isinstance(originalValue, QtCore.QDateTime):
+ value = QtCore.QDateTime.fromString(text, QtCore.Qt.ISODate)
+ if not value.isValid():
+ return
+ elif isinstance(originalValue, QtCore.QTime):
+ value = QtCore.QTime.fromString(text, QtCore.Qt.ISODate)
+ if not value.isValid():
+ return
+ elif isinstance(originalValue, QtCore.QPoint):
+ self.pointExp.exactMatch(text)
+ value = QtCore.QPoint(int(self.pointExp.cap(1)),
+ int(self.pointExp.cap(2)))
+ elif isinstance(originalValue, QtCore.QRect):
+ self.rectExp.exactMatch(text)
+ value = QtCore.QRect(int(self.rectExp.cap(1)),
+ int(self.rectExp.cap(2)),
+ int(self.rectExp.cap(3)),
+ int(self.rectExp.cap(4)))
+ elif isinstance(originalValue, QtCore.QSize):
+ self.sizeExp.exactMatch(text)
+ value = QtCore.QSize(int(self.sizeExp.cap(1)),
+ int(self.sizeExp.cap(2)))
+ elif isinstance(originalValue, list):
+ value = text.split(',')
+ else:
+ value = type(originalValue)(text)
+
+ model.setData(index, self.displayText(value), QtCore.Qt.DisplayRole)
+ model.setData(index, value, QtCore.Qt.UserRole)
+
+ @staticmethod
+ def isSupportedType(value):
+ return isinstance(value, (bool, float, int, QtCore.QByteArray,
+ str, QtGui.QColor, QtCore.QDate, QtCore.QDateTime,
+ QtCore.QTime, QtCore.QPoint, QtCore.QRect, QtCore.QSize,
+ list))
+
+ @staticmethod
+ def displayText(value):
+ if isinstance(value, (bool, int, QtCore.QByteArray)):
+ return str(value)
+ if isinstance(value, str):
+ return value
+ elif isinstance(value, float):
+ return '%g' % value
+ elif isinstance(value, QtGui.QColor):
+ return '(%u,%u,%u,%u)' % (value.red(), value.green(), value.blue(), value.alpha())
+ elif isinstance(value, (QtCore.QDate, QtCore.QDateTime, QtCore.QTime)):
+ return value.toString(QtCore.Qt.ISODate)
+ elif isinstance(value, QtCore.QPoint):
+ return '(%d,%d)' % (value.x(), value.y())
+ elif isinstance(value, QtCore.QRect):
+ return '(%d,%d,%d,%d)' % (value.x(), value.y(), value.width(), value.height())
+ elif isinstance(value, QtCore.QSize):
+ return '(%d,%d)' % (value.width(), value.height())
+ elif isinstance(value, list):
+ return ','.join(value)
+ elif value is None:
+ return '<Invalid>'
+
+ return '<%s>' % value
+
+
+if __name__ == '__main__':
+ app = QtWidgets.QApplication(sys.argv)
+ mainWin = MainWindow()
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/datavisualization/bars3d.py b/examples/datavisualization/bars3d.py
new file mode 100644
index 000000000..c07314cb0
--- /dev/null
+++ b/examples/datavisualization/bars3d.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 QtDataVisualization example"""
+
+import os
+import sys
+from PySide2.QtCore import QRect, QSize, QProcess, Qt
+from PySide2.QtGui import QGuiApplication, QScreen, QWindow
+from PySide2.QtWidgets import QApplication, QSizePolicy, QMainWindow, QWidget
+from PySide2.QtDataVisualization import QtDataVisualization
+
+def dataToBarDataRow(data):
+ return list(QtDataVisualization.QBarDataItem(d) for d in data)
+
+def dataToBarDataArray(data):
+ return list(dataToBarDataRow(row) for row in data)
+
+class MainWindow(QMainWindow):
+
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ self.setWindowTitle('Qt DataVisualization 3D Bars')
+
+ self.bars = QtDataVisualization.Q3DBars()
+
+ self.columnAxis = QtDataVisualization.QCategory3DAxis()
+ self.columnAxis.setTitle('Columns')
+ self.columnAxis.setTitleVisible(True)
+ self.columnAxis.setLabels(['Column1', 'Column2'])
+ self.columnAxis.setLabelAutoRotation(30);
+
+ self.rowAxis = QtDataVisualization.QCategory3DAxis()
+ self.rowAxis.setTitle('Rows')
+ self.rowAxis.setTitleVisible(True)
+ self.rowAxis.setLabels(['Row1', 'Row2'])
+ self.rowAxis.setLabelAutoRotation(30);
+
+ self.valueAxis = QtDataVisualization.QValue3DAxis()
+ self.valueAxis.setTitle('Values')
+ self.valueAxis.setTitleVisible(True)
+ self.valueAxis.setRange(0, 5);
+
+ self.bars.setRowAxis(self.rowAxis)
+ self.bars.setColumnAxis(self.columnAxis)
+ self.bars.setValueAxis(self.valueAxis)
+
+ self.series = QtDataVisualization.QBar3DSeries()
+ self.arrayData = [[1, 2], [3, 4]]
+ self.series.dataProxy().addRows(dataToBarDataArray(self.arrayData))
+
+ self.bars.setPrimarySeries(self.series)
+
+ self.container = QWidget.createWindowContainer(self.bars)
+
+ if not self.bars.hasContext():
+ print("Couldn't initialize the OpenGL context.")
+ sys.exit(-1)
+
+ camera = self.bars.scene().activeCamera()
+ camera.setYRotation(22.5)
+
+ geometry = QGuiApplication.primaryScreen().geometry()
+ size = geometry.height() * 3 / 4
+ self.container.setMinimumSize(size, size)
+
+ self.container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding);
+ self.container.setFocusPolicy(Qt.StrongFocus);
+ self.setCentralWidget(self.container)
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/declarative/extending/chapter1-basics/app.qml b/examples/declarative/extending/chapter1-basics/app.qml
new file mode 100644
index 000000000..60ecd7bff
--- /dev/null
+++ b/examples/declarative/extending/chapter1-basics/app.qml
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import Charts 1.0
+import QtQuick 2.0
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: aPieChart
+ anchors.centerIn: parent
+ width: 100; height: 100
+ name: "A simple pie chart"
+ color: "red"
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: aPieChart.name
+ }
+}
+//![0]
diff --git a/examples/declarative/extending/chapter1-basics/basics.py b/examples/declarative/extending/chapter1-basics/basics.py
new file mode 100644
index 000000000..f965cade9
--- /dev/null
+++ b/examples/declarative/extending/chapter1-basics/basics.py
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+"""PySide2 port of the qml/tutorials/extending-qml/chapter1-basics example from Qt v5.x"""
+
+import sys, os
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
+from utils import text_type
+
+from PySide2.QtCore import Property, Signal, QUrl
+from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide2.QtQml import qmlRegisterType
+from PySide2.QtQuick import QQuickPaintedItem, QQuickView
+
+class PieChart (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+
+ def paint(self, painter):
+ pen = QPen(self.color, 2)
+ painter.setPen(pen);
+ painter.setRenderHints(QPainter.Antialiasing, True);
+ painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16);
+
+ def getColor(self):
+ return self._color
+
+ def setColor(self, value):
+ self._color = value
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ nameChanged = Signal()
+
+ color = Property(QColor, getColor, setColor)
+ name = Property(text_type, getName, setName, notify=nameChanged)
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/extending/chapter2-methods/app.qml b/examples/declarative/extending/chapter2-methods/app.qml
new file mode 100644
index 000000000..863b597d0
--- /dev/null
+++ b/examples/declarative/extending/chapter2-methods/app.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import Charts 1.0
+import QtQuick 2.0
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: aPieChart
+ anchors.centerIn: parent
+ width: 100; height: 100
+ color: "red"
+
+ onChartCleared: console.log("The chart has been cleared")
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: aPieChart.clearChart()
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: "Click anywhere to clear the chart"
+ }
+}
+//![0]
diff --git a/examples/declarative/extending/chapter2-methods/methods.py b/examples/declarative/extending/chapter2-methods/methods.py
new file mode 100644
index 000000000..d6e74f5f0
--- /dev/null
+++ b/examples/declarative/extending/chapter2-methods/methods.py
@@ -0,0 +1,105 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+"""PySide2 port of the qml/tutorials/extending-qml/chapter2-methods example from Qt v5.x"""
+
+import sys, os
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
+from utils import text_type
+
+from PySide2.QtCore import Property, Signal, Slot, QUrl, Qt
+from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide2.QtQml import qmlRegisterType
+from PySide2.QtQuick import QQuickPaintedItem, QQuickView
+
+class PieChart (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+
+ def paint(self, painter):
+ pen = QPen(self.color, 2)
+ painter.setPen(pen);
+ painter.setRenderHints(QPainter.Antialiasing, True);
+ painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16);
+
+ def getColor(self):
+ return self._color
+
+ def setColor(self, value):
+ self._color = value
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ color = Property(QColor, getColor, setColor)
+ name = Property(text_type, getName, setName)
+ chartCleared = Signal()
+
+ @Slot() # This should be something like @Invokable
+ def clearChart(self):
+ self.setColor(Qt.transparent)
+ self.update()
+ self.chartCleared.emit()
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/extending/chapter3-bindings/app.qml b/examples/declarative/extending/chapter3-bindings/app.qml
new file mode 100644
index 000000000..01b9216e8
--- /dev/null
+++ b/examples/declarative/extending/chapter3-bindings/app.qml
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import Charts 1.0
+import QtQuick 2.0
+
+Item {
+ width: 300; height: 200
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 20
+
+ PieChart {
+ id: chartA
+ width: 100; height: 100
+ color: "red"
+ }
+
+ PieChart {
+ id: chartB
+ width: 100; height: 100
+ color: chartA.color
+ }
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: { chartA.color = "blue" }
+ }
+
+ Text {
+ anchors {
+ bottom: parent.bottom;
+ horizontalCenter: parent.horizontalCenter;
+ bottomMargin: 20
+ }
+ text: "Click anywhere to change the chart color"
+ }
+}
+//![0]
diff --git a/examples/declarative/extending/chapter3-bindings/bindings.py b/examples/declarative/extending/chapter3-bindings/bindings.py
new file mode 100644
index 000000000..90af6d7e1
--- /dev/null
+++ b/examples/declarative/extending/chapter3-bindings/bindings.py
@@ -0,0 +1,110 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+"""PySide2 port of the qml/tutorials/extending-qml/chapter3-bindings example from Qt v5.x"""
+
+import sys, os
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
+from utils import text_type
+
+from PySide2.QtCore import Property, Signal, Slot, QUrl, Qt
+from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide2.QtQml import qmlRegisterType
+from PySide2.QtQuick import QQuickPaintedItem, QQuickView
+
+class PieChart (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._color = QColor()
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen);
+ painter.setRenderHints(QPainter.Antialiasing, True);
+ painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16);
+
+ def getColor(self):
+ return self._color
+
+ def setColor(self, value):
+ if value != self._color:
+ self._color = value
+ self.update()
+ self.colorChanged.emit()
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ colorChanged = Signal()
+ color = Property(QColor, getColor, setColor, notify=colorChanged)
+ name = Property(text_type, getName, setName)
+ chartCleared = Signal()
+
+ @Slot() # This should be something like @Invokable
+ def clearChart(self):
+ self.setColor(Qt.transparent)
+ self.update()
+ self.chartCleared.emit()
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/extending/chapter4-customPropertyTypes/app.qml b/examples/declarative/extending/chapter4-customPropertyTypes/app.qml
new file mode 100644
index 000000000..00e077276
--- /dev/null
+++ b/examples/declarative/extending/chapter4-customPropertyTypes/app.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import Charts 1.0
+import QtQuick 2.0
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ id: chart
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ pieSlice: PieSlice {
+ anchors.fill: parent
+ color: "red"
+ }
+ }
+
+ Component.onCompleted: console.log("The pie is colored " + chart.pieSlice.color)
+}
+//![0]
diff --git a/examples/declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py b/examples/declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py
new file mode 100644
index 000000000..473b7c15f
--- /dev/null
+++ b/examples/declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py
@@ -0,0 +1,115 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+"""PySide2 port of the qml/tutorials/extending-qml/chapter4-customPropertyTypes example from Qt v5.x"""
+
+import sys, os
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
+from utils import text_type
+
+from PySide2.QtCore import Property, QUrl
+from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide2.QtQml import qmlRegisterType
+from PySide2.QtQuick import QQuickPaintedItem, QQuickView
+
+class PieSlice (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._color = QColor()
+
+ def getColor(self):
+ return self._color
+
+ def setColor(self, value):
+ self._color = value
+
+ color = Property(QColor, getColor, setColor)
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen);
+ painter.setRenderHints(QPainter.Antialiasing, True);
+ painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), 90 * 16, 290 * 16);
+
+class PieChart (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._pieSlice = None
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ name = Property(text_type, getName, setName)
+
+ def getPieSlice(self):
+ return self._pieSlice
+
+ def setPieSlice(self, value):
+ self._pieSlice = value
+ self._pieSlice.setParentItem(self)
+
+ pieSlice = Property(PieSlice, getPieSlice, setPieSlice)
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');
+ qmlRegisterType(PieSlice, "Charts", 1, 0, "PieSlice");
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/extending/chapter5-listproperties/app.qml b/examples/declarative/extending/chapter5-listproperties/app.qml
new file mode 100644
index 000000000..230c29520
--- /dev/null
+++ b/examples/declarative/extending/chapter5-listproperties/app.qml
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+//![0]
+import Charts 1.0
+import QtQuick 2.0
+
+Item {
+ width: 300; height: 200
+
+ PieChart {
+ anchors.centerIn: parent
+ width: 100; height: 100
+
+ slices: [
+ PieSlice {
+ anchors.fill: parent
+ color: "red"
+ fromAngle: 0; angleSpan: 110
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "black"
+ fromAngle: 110; angleSpan: 50
+ },
+ PieSlice {
+ anchors.fill: parent
+ color: "blue"
+ fromAngle: 160; angleSpan: 100
+ }
+ ]
+ }
+}
+//![0]
diff --git a/examples/declarative/extending/chapter5-listproperties/listproperties.py b/examples/declarative/extending/chapter5-listproperties/listproperties.py
new file mode 100644
index 000000000..b494eac0d
--- /dev/null
+++ b/examples/declarative/extending/chapter5-listproperties/listproperties.py
@@ -0,0 +1,128 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+"""PySide2 port of the qml/tutorials/extending-qml/chapter5-listproperties example from Qt v5.x"""
+
+import sys, os
+sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..', 'utils'))
+from utils import text_type
+
+from PySide2.QtCore import Property, QUrl
+from PySide2.QtGui import QGuiApplication, QPen, QPainter, QColor
+from PySide2.QtQml import qmlRegisterType, ListProperty
+from PySide2.QtQuick import QQuickPaintedItem, QQuickView
+
+class PieSlice (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._color = QColor()
+ self._fromAngle = 0
+ self._angleSpan = 0
+
+ def getColor(self):
+ return self._color
+
+ def setColor(self, value):
+ self._color = value
+
+ def getFromAngle(self):
+ return self._angle
+
+ def setFromAngle(self, value):
+ self._fromAngle = value
+
+ def getAngleSpan(self):
+ return self._angleSpan
+
+ def setAngleSpan(self, value):
+ self._angleSpan = value
+
+ color = Property(QColor, getColor, setColor)
+ fromAngle = Property(int, getFromAngle, setFromAngle)
+ angleSpan = Property(int, getAngleSpan, setAngleSpan)
+
+ def paint(self, painter):
+ pen = QPen(self._color, 2)
+ painter.setPen(pen);
+ painter.setRenderHints(QPainter.Antialiasing, True);
+ painter.drawPie(self.boundingRect().adjusted(1,1,-1,-1), self._fromAngle * 16, self._angleSpan * 16);
+
+class PieChart (QQuickPaintedItem):
+ def __init__(self, parent = None):
+ QQuickPaintedItem.__init__(self, parent)
+ self._name = u''
+ self._slices = []
+
+ def getName(self):
+ return self._name
+
+ def setName(self, value):
+ self._name = value
+
+ name = Property(text_type, getName, setName)
+
+ def appendSlice(self, _slice):
+ _slice.setParentItem(self)
+ self._slices.append(_slice)
+
+ slices = ListProperty(PieSlice, appendSlice)
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ qmlRegisterType(PieChart, 'Charts', 1, 0, 'PieChart');
+ qmlRegisterType(PieSlice, "Charts", 1, 0, "PieSlice");
+
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+ qmlFile = os.path.join(os.path.dirname(__file__), 'app.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/scrolling.py b/examples/declarative/scrolling.py
new file mode 100755
index 000000000..7b079c8f1
--- /dev/null
+++ b/examples/declarative/scrolling.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QUrl
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+# This example uses a QML file to show a scrolling list containing
+# all the items listed in dataList.
+
+if __name__ == '__main__':
+ dataList = ["Item 1", "Item 2", "Item 3", "Item 4"]
+
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ ctxt = view.rootContext()
+ ctxt.setContextProperty("myModel", dataList)
+
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+
+ app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
diff --git a/examples/declarative/signals/pytoqml1/main.py b/examples/declarative/signals/pytoqml1/main.py
new file mode 100644
index 000000000..e90a3cfab
--- /dev/null
+++ b/examples/declarative/signals/pytoqml1/main.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QTimer, QUrl
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+
+ timer = QTimer()
+ timer.start(2000)
+
+ view = QQuickView()
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ root = view.rootObject()
+
+ timer.timeout.connect(root.updateRotater)
+
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/signals/pytoqml1/view.qml b/examples/declarative/signals/pytoqml1/view.qml
new file mode 100644
index 000000000..21ba8aa65
--- /dev/null
+++ b/examples/declarative/signals/pytoqml1/view.qml
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+
+ function updateRotater() {
+ rotater.angle = rotater.angle + 45
+ }
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Rectangle {
+ id: rotater
+ property real angle : 0
+ x: 240
+ width: 100; height: 10
+ color: "black"
+ y: 95
+
+ transform: Rotation {
+ origin.x: 10; origin.y: 5
+ angle: rotater.angle
+ Behavior on angle {
+ SpringAnimation {
+ spring: 1.4
+ damping: .05
+ }
+ }
+ }
+ }
+
+}
diff --git a/examples/declarative/signals/qmltopy1/main.py b/examples/declarative/signals/qmltopy1/main.py
new file mode 100755
index 000000000..ba5684951
--- /dev/null
+++ b/examples/declarative/signals/qmltopy1/main.py
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QObject, QUrl, Slot
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+class Console(QObject):
+ """Output stuff on the console."""
+
+ @Slot(str)
+ @Slot('double')
+ def output(self, s):
+ print(s)
+
+ @Slot(str)
+ def outputStr(self, s):
+ print(s)
+
+ @Slot('double')
+ def outputFloat(self, x):
+ print(x)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ # Instantiate the Python object.
+ con = Console()
+
+ # Expose the object to QML.
+ context = view.rootContext()
+ context.setContextProperty("con", con)
+
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/signals/qmltopy1/view.qml b/examples/declarative/signals/qmltopy1/view.qml
new file mode 100644
index 000000000..0115d432b
--- /dev/null
+++ b/examples/declarative/signals/qmltopy1/view.qml
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 30
+ font.pointSize: 24; font.bold: true
+ }
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onClicked: {
+ // once the "con" context has been declared,
+ // slots can be called like functions
+ con.outputFloat(123)
+ con.outputStr("foobar")
+ con.output(helloText.x)
+ con.output(helloText.text)
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/declarative/signals/qmltopy2/main.py b/examples/declarative/signals/qmltopy2/main.py
new file mode 100755
index 000000000..be8692c08
--- /dev/null
+++ b/examples/declarative/signals/qmltopy2/main.py
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QObject, QUrl, Slot
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+class RotateValue(QObject):
+ def __init__(self):
+ super(RotateValue,self).__init__()
+ self.r = 0
+
+ # If a slot returns a value, the return value type must be explicitly
+ # defined in the decorator.
+ @Slot(result=int)
+ def val(self):
+ self.r = self.r + 10
+ return self.r
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+
+ rotatevalue = RotateValue()
+ context = view.rootContext()
+ context.setContextProperty("rotatevalue", rotatevalue)
+
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/signals/qmltopy2/view.qml b/examples/declarative/signals/qmltopy2/view.qml
new file mode 100644
index 000000000..2a905a69f
--- /dev/null
+++ b/examples/declarative/signals/qmltopy2/view.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 30
+ font.pointSize: 24; font.bold: true
+ }
+
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onClicked: {
+ helloText.rotation = rotatevalue.val()
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/declarative/signals/qmltopy3/main.py b/examples/declarative/signals/qmltopy3/main.py
new file mode 100644
index 000000000..81c19ee81
--- /dev/null
+++ b/examples/declarative/signals/qmltopy3/main.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QObject, QUrl
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+def sayThis(s):
+ print(s)
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+
+ root = view.rootObject()
+ root.textRotationChanged.connect(sayThis)
+ root.buttonClicked.connect(lambda: sayThis("clicked button (QML top-level signal)"))
+
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/signals/qmltopy3/view.qml b/examples/declarative/signals/qmltopy3/view.qml
new file mode 100644
index 000000000..72984a137
--- /dev/null
+++ b/examples/declarative/signals/qmltopy3/view.qml
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+
+ signal buttonClicked
+ signal textRotationChanged(double rot)
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Text {
+ id: helloText
+ text: "Hello world!"
+ y: 30
+ x: page.width/2-width/2
+ font.pointSize: 24; font.bold: true
+ onRotationChanged: textRotationChanged(rotation)
+
+ states: State {
+ name: "down"; when: buttonMouseArea.pressed === true
+ PropertyChanges {
+ target: helloText;
+ rotation: 180;
+ y: 100;
+ }
+ }
+
+ transitions: Transition {
+ from: ""; to: "down"; reversible: true
+ ParallelAnimation {
+ NumberAnimation {
+ properties: "y,rotation"
+ duration: 500
+ easing.type: Easing.InOutQuad
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ y: 120
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ onClicked: {
+ buttonClicked()
+ }
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/declarative/signals/qmltopy4/main.py b/examples/declarative/signals/qmltopy4/main.py
new file mode 100644
index 000000000..5f180b349
--- /dev/null
+++ b/examples/declarative/signals/qmltopy4/main.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QObject, QUrl
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+def sayThis(s):
+ print(s)
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+
+ root = view.rootObject()
+ button = root.findChild(QObject, "buttonMouseArea")
+ button.clicked.connect(lambda: sayThis("clicked button (signal directly connected)"))
+
+ view.show()
+ res = app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
+ sys.exit(res)
diff --git a/examples/declarative/signals/qmltopy4/view.qml b/examples/declarative/signals/qmltopy4/view.qml
new file mode 100644
index 000000000..212df77e2
--- /dev/null
+++ b/examples/declarative/signals/qmltopy4/view.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+ id: page
+
+ width: 500; height: 200
+ color: "lightgray"
+
+ Rectangle {
+ id: button
+ width: 150; height: 40
+ color: "darkgray"
+ anchors.horizontalCenter: page.horizontalCenter
+ anchors.verticalCenter: page.verticalCenter
+ MouseArea {
+ id: buttonMouseArea
+ objectName: "buttonMouseArea"
+ anchors.fill: parent
+ }
+ Text {
+ id: buttonText
+ text: "Press me!"
+ anchors.horizontalCenter: button.horizontalCenter
+ anchors.verticalCenter: button.verticalCenter
+ font.pointSize: 16
+ }
+ }
+}
diff --git a/examples/declarative/usingmodel.py b/examples/declarative/usingmodel.py
new file mode 100644
index 000000000..bd2e44693
--- /dev/null
+++ b/examples/declarative/usingmodel.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import sys
+from PySide2.QtCore import QAbstractListModel, Qt, QUrl
+from PySide2.QtGui import QGuiApplication
+import PySide2.QtQml
+from PySide2.QtQuick import QQuickView
+
+class PersonModel (QAbstractListModel):
+ MyRole = Qt.UserRole + 1
+
+ def __init__(self, parent = None):
+ QAbstractListModel.__init__(self, parent)
+ self._data = []
+
+ def roleNames(self):
+ roles = {
+ PersonModel.MyRole : 'modelData',
+ Qt.DisplayRole : 'display'
+ }
+ return roles
+
+ def rowCount(self, index):
+ return len(self._data)
+
+ def data(self, index, role):
+ d = self._data[index.row()]
+
+ if role == Qt.DisplayRole:
+ return d['name']
+ elif role == Qt.DecorationRole:
+ return Qt.black
+ elif role == PersonModel.MyRole:
+ return d['myrole']
+ return None
+
+ def populate(self):
+ self._data.append({'name':'Qt', 'myrole':'role1'})
+ self._data.append({'name':'PySide', 'myrole':'role2'})
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ view = QQuickView()
+ view.setResizeMode(QQuickView.SizeRootObjectToView)
+
+ myModel = PersonModel()
+ myModel.populate()
+
+ view.rootContext().setContextProperty("myModel", myModel)
+ qmlFile = os.path.join(os.path.dirname(__file__), 'view.qml')
+ view.setSource(QUrl.fromLocalFile(os.path.abspath(qmlFile)))
+ if view.status() == QQuickView.Error:
+ sys.exit(-1)
+ view.show()
+
+ app.exec_()
+ # Deleting the view before it goes out of scope is required to make sure all child QML instances
+ # are destroyed in the correct order.
+ del view
diff --git a/examples/declarative/view.qml b/examples/declarative/view.qml
new file mode 100644
index 000000000..caf2dc1cc
--- /dev/null
+++ b/examples/declarative/view.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+ListView {
+ width: 100
+ height: 100
+ anchors.fill: parent
+ model: myModel
+ delegate: Component {
+ Rectangle {
+ height: 25
+ width: 100
+ Text {
+ function displayText() {
+ var result = ""
+ if (typeof display !== "undefined")
+ result = display + ": "
+ result += modelData
+ return result
+ }
+
+ text: displayText()
+ }
+ }
+ }
+}
diff --git a/examples/examples.pyqtc b/examples/examples.pyqtc
new file mode 100644
index 000000000..eb0e35933
--- /dev/null
+++ b/examples/examples.pyqtc
@@ -0,0 +1,103 @@
+charts/memoryusage.py
+corelib/threads/mandelbrot.py
+corelib/tools/codecs/codecs.py
+corelib/tools/regexp.py
+corelib/tools/settingseditor/settingseditor.py
+declarative/extending/chapter1-basics/basics.py
+declarative/extending/chapter2-methods/methods.py
+declarative/extending/chapter3-bindings/bindings.py
+declarative/extending/chapter4-customPropertyTypes/customPropertyTypes.py
+declarative/extending/chapter5-listproperties/listproperties.py
+declarative/scrolling.py
+declarative/signals/pytoqml1/main.py
+declarative/signals/qmltopy1/main.py
+declarative/signals/qmltopy2/main.py
+declarative/signals/qmltopy3/main.py
+declarative/signals/qmltopy4/main.py
+declarative/usingmodel.py
+macextras/macpasteboardmime.py
+multimedia/audiooutput.py
+multimedia/camera.py
+multimedia/player.py
+network/blockingfortuneclient.py
+network/fortuneclient.py
+network/fortuneserver.py
+network/threadedfortuneserver.py
+opengl/2dpainting.py
+opengl/grabber.py
+opengl/hellogl.py
+opengl/overpainting.py
+opengl/samplebuffers.py
+opengl/textures/textures.py
+script/helloscript.py
+texttospeech/texttospeech.py
+tutorial/t1.py
+tutorial/t10.py
+tutorial/t11.py
+tutorial/t12.py
+tutorial/t13.py
+tutorial/t14.py
+tutorial/t2.py
+tutorial/t3.py
+tutorial/t4.py
+tutorial/t5.py
+tutorial/t6.py
+tutorial/t7.py
+tutorial/t8.py
+tutorial/t9.py
+webenginewidgets/simplebrowser.py
+widgets/animation/animatedtiles/animatedtiles.py
+widgets/animation/appchooser/appchooser.py
+widgets/animation/easing/easing.py
+widgets/animation/states/states.py
+widgets/dialogs/classwizard/classwizard.py
+widgets/dialogs/extension.py
+widgets/dialogs/findfiles.py
+widgets/dialogs/standarddialogs.py
+widgets/dialogs/trivialwizard.py
+widgets/draganddrop/draggabletext/draggabletext.py
+widgets/effects/lighting.py
+widgets/graphicsview/anchorlayout.py
+widgets/graphicsview/collidingmice/collidingmice.py
+widgets/graphicsview/diagramscene/diagramscene.py
+widgets/graphicsview/dragdroprobot/dragdroprobot.py
+widgets/graphicsview/elasticnodes.py
+widgets/itemviews/addressbook/adddialogwidget.py
+widgets/itemviews/addressbook/addressbook.py
+widgets/itemviews/addressbook/addresswidget.py
+widgets/itemviews/addressbook/newaddresstab.py
+widgets/itemviews/addressbook/tablemodel.py
+widgets/itemviews/basicsortfiltermodel.py
+widgets/itemviews/fetchmore.py
+widgets/itemviews/stardelegate/stardelegate.py
+widgets/itemviews/stardelegate/stareditor.py
+widgets/itemviews/stardelegate/starrating.py
+widgets/layouts/basiclayouts.py
+widgets/layouts/dynamiclayouts.py
+widgets/layouts/flowlayout.py
+widgets/mainwindows/application/application.py
+widgets/mainwindows/dockwidgets/dockwidgets.py
+widgets/mainwindows/mdi/mdi.py
+widgets/painting/basicdrawing/basicdrawing.py
+widgets/painting/concentriccircles.py
+widgets/richtext/orderform.py
+widgets/richtext/syntaxhighlighter.py
+widgets/richtext/syntaxhighlighter/syntaxhighlighter.py
+widgets/richtext/textobject/textobject.py
+widgets/state-machine/eventtrans.py
+widgets/state-machine/factstates.py
+widgets/state-machine/pingpong.py
+widgets/state-machine/rogue.py
+widgets/state-machine/trafficlight.py
+widgets/state-machine/twowaybutton.py
+widgets/tutorials/addressbook/part1.py
+widgets/tutorials/addressbook/part2.py
+widgets/tutorials/addressbook/part3.py
+widgets/tutorials/addressbook/part4.py
+widgets/tutorials/addressbook/part5.py
+widgets/tutorials/addressbook/part6.py
+widgets/tutorials/addressbook/part7.py
+widgets/widgets/hellogl_openglwidget_legacy.py
+widgets/widgets/tetrix.py
+xml/dombookmarks/dombookmarks.py
+xmlpatterns/schema/schema.py
diff --git a/examples/macextras/macpasteboardmime.py b/examples/macextras/macpasteboardmime.py
new file mode 100755
index 000000000..0daa21a94
--- /dev/null
+++ b/examples/macextras/macpasteboardmime.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+import sys
+import math
+from PySide2 import QtCore, QtGui, QtWidgets
+
+try:
+ from PySide2 import QtMacExtras
+except ImportError:
+ app = QtWidgets.QApplication(sys.argv)
+ messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "QtMacExtras macpasteboardmime",
+ "This exampe only runs on macOS and QtMacExtras must be installed to run this example.",
+ QtWidgets.QMessageBox.Close)
+ messageBox.exec_()
+ sys.exit(1)
+
+class VCardMime(QtMacExtras.QMacPasteboardMime):
+ def __init__(self, t = QtMacExtras.QMacPasteboardMime.MIME_ALL):
+ super(VCardMime, self).__init__(t)
+
+ def convertorName(self):
+ return "VCardMime"
+
+ def canConvert(self, mime, flav):
+ if self.mimeFor(flav) == mime:
+ return True
+ else:
+ return False
+
+ def mimeFor(self, flav):
+ if flav == "public.vcard":
+ return "application/x-mycompany-VCard"
+ else:
+ return ""
+
+ def flavorFor(self, mime):
+ if mime == "application/x-mycompany-VCard":
+ return "public.vcard"
+ else:
+ return ""
+
+ def convertToMime(self, mime, data, flav):
+ all = QtCore.QByteArray()
+ for i in data:
+ all += i
+ return all
+
+ def convertFromMime(mime, data, flav):
+ # Todo: implement!
+ return []
+
+class TestWidget(QtWidgets.QWidget):
+ def __init__(self, parent=None):
+ super(TestWidget, self).__init__(parent)
+ self.vcardMime = VCardMime()
+ self.setAcceptDrops(True)
+
+ self.label1 = QtWidgets.QLabel()
+ self.label2 = QtWidgets.QLabel()
+
+ layout = QtWidgets.QVBoxLayout()
+ layout.addWidget(self.label1)
+ layout.addWidget(self.label2)
+ self.setLayout(layout)
+
+ self.label1.setText("Please drag a \"VCard\" from Contacts application, normally a name in the list, and drop here.")
+
+ def dragEnterEvent(self, e):
+ e.accept()
+
+ def dropEvent(self, e):
+ e.accept()
+ self.contentsDropEvent(e)
+
+ def contentsDropEvent(self, e):
+ if e.mimeData().hasFormat("application/x-mycompany-VCard"):
+ s = e.mimeData().data( "application/x-mycompany-VCard" )
+ # s now contains text of vcard
+ self.label2.setText(str(s));
+ e.acceptProposedAction()
+
+if __name__ == '__main__':
+ app = QtWidgets.QApplication(sys.argv)
+ QtMacExtras.qRegisterDraggedTypes(["public.vcard"])
+ wid1 = TestWidget()
+ wid1.show()
+ sys.exit(app.exec_())
diff --git a/examples/multimedia/audiooutput.py b/examples/multimedia/audiooutput.py
new file mode 100755
index 000000000..270683110
--- /dev/null
+++ b/examples/multimedia/audiooutput.py
@@ -0,0 +1,301 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the multimedia/audiooutput example from Qt v5.x, originating from PyQt"""
+
+from math import pi, sin
+from struct import pack
+
+from PySide2.QtCore import QByteArray, QIODevice, Qt, QTimer, qWarning
+from PySide2.QtMultimedia import (QAudio, QAudioDeviceInfo, QAudioFormat,
+ QAudioOutput)
+from PySide2.QtWidgets import (QApplication, QComboBox, QHBoxLayout, QLabel,
+ QMainWindow, QPushButton, QSlider, QVBoxLayout, QWidget)
+
+
+class Generator(QIODevice):
+
+ def __init__(self, format, durationUs, sampleRate, parent):
+ super(Generator, self).__init__(parent)
+
+ self.m_pos = 0
+ self.m_buffer = QByteArray()
+
+ self.generateData(format, durationUs, sampleRate)
+
+ def start(self):
+ self.open(QIODevice.ReadOnly)
+
+ def stop(self):
+ self.m_pos = 0
+ self.close()
+
+ def generateData(self, format, durationUs, sampleRate):
+ pack_format = ''
+
+ if format.sampleSize() == 8:
+ if format.sampleType() == QAudioFormat.UnSignedInt:
+ scaler = lambda x: ((1.0 + x) / 2 * 255)
+ pack_format = 'B'
+ elif format.sampleType() == QAudioFormat.SignedInt:
+ scaler = lambda x: x * 127
+ pack_format = 'b'
+ elif format.sampleSize() == 16:
+ if format.sampleType() == QAudioFormat.UnSignedInt:
+ scaler = lambda x: (1.0 + x) / 2 * 65535
+ pack_format = '<H' if format.byteOrder() == QAudioFormat.LittleEndian else '>H'
+ elif format.sampleType() == QAudioFormat.SignedInt:
+ scaler = lambda x: x * 32767
+ pack_format = '<h' if format.byteOrder() == QAudioFormat.LittleEndian else '>h'
+
+ assert(pack_format != '')
+
+ channelBytes = format.sampleSize() // 8
+ sampleBytes = format.channelCount() * channelBytes
+
+ length = (format.sampleRate() * format.channelCount() * (format.sampleSize() // 8)) * durationUs // 100000
+
+ self.m_buffer.clear()
+ sampleIndex = 0
+ factor = 2 * pi * sampleRate / format.sampleRate()
+
+ while length != 0:
+ x = sin((sampleIndex % format.sampleRate()) * factor)
+ packed = pack(pack_format, int(scaler(x)))
+
+ for _ in range(format.channelCount()):
+ self.m_buffer.append(packed)
+ length -= channelBytes
+
+ sampleIndex += 1
+
+ def readData(self, maxlen):
+ data = QByteArray()
+ total = 0
+
+ while maxlen > total:
+ chunk = min(self.m_buffer.size() - self.m_pos, maxlen - total)
+ data.append(self.m_buffer.mid(self.m_pos, chunk))
+ self.m_pos = (self.m_pos + chunk) % self.m_buffer.size()
+ total += chunk
+
+ return data.data()
+
+ def writeData(self, data):
+ return 0
+
+ def bytesAvailable(self):
+ return self.m_buffer.size() + super(Generator, self).bytesAvailable()
+
+
+class AudioTest(QMainWindow):
+
+ PUSH_MODE_LABEL = "Enable push mode"
+ PULL_MODE_LABEL = "Enable pull mode"
+ SUSPEND_LABEL = "Suspend playback"
+ RESUME_LABEL = "Resume playback"
+
+ DurationSeconds = 1
+ ToneSampleRateHz = 600
+ DataSampleRateHz = 44100
+
+ def __init__(self):
+ super(AudioTest, self).__init__()
+
+ self.m_device = QAudioDeviceInfo.defaultOutputDevice()
+ self.m_output = None
+
+ self.initializeWindow()
+ self.initializeAudio()
+
+ def initializeWindow(self):
+ layout = QVBoxLayout()
+
+ self.m_deviceBox = QComboBox()
+ self.m_deviceBox.activated[int].connect(self.deviceChanged)
+ for deviceInfo in QAudioDeviceInfo.availableDevices(QAudio.AudioOutput):
+ self.m_deviceBox.addItem(deviceInfo.deviceName(), deviceInfo)
+
+ layout.addWidget(self.m_deviceBox)
+
+ self.m_modeButton = QPushButton()
+ self.m_modeButton.clicked.connect(self.toggleMode)
+ self.m_modeButton.setText(self.PUSH_MODE_LABEL)
+
+ layout.addWidget(self.m_modeButton)
+
+ self.m_suspendResumeButton = QPushButton(
+ clicked=self.toggleSuspendResume)
+ self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
+
+ layout.addWidget(self.m_suspendResumeButton)
+
+ volumeBox = QHBoxLayout()
+ volumeLabel = QLabel("Volume:")
+ self.m_volumeSlider = QSlider(Qt.Horizontal, minimum=0, maximum=100,
+ singleStep=10)
+ self.m_volumeSlider.valueChanged.connect(self.volumeChanged)
+
+ volumeBox.addWidget(volumeLabel)
+ volumeBox.addWidget(self.m_volumeSlider)
+
+ layout.addLayout(volumeBox)
+
+ window = QWidget()
+ window.setLayout(layout)
+
+ self.setCentralWidget(window)
+
+ def initializeAudio(self):
+ self.m_pullTimer = QTimer(self)
+ self.m_pullTimer.timeout.connect(self.pullTimerExpired)
+ self.m_pullMode = True
+
+ self.m_format = QAudioFormat()
+ self.m_format.setSampleRate(self.DataSampleRateHz)
+ self.m_format.setChannelCount(1)
+ self.m_format.setSampleSize(16)
+ self.m_format.setCodec('audio/pcm')
+ self.m_format.setByteOrder(QAudioFormat.LittleEndian)
+ self.m_format.setSampleType(QAudioFormat.SignedInt)
+
+ info = QAudioDeviceInfo(QAudioDeviceInfo.defaultOutputDevice())
+ if not info.isFormatSupported(self.m_format):
+ qWarning("Default format not supported - trying to use nearest")
+ self.m_format = info.nearestFormat(self.m_format)
+
+ self.m_generator = Generator(self.m_format,
+ self.DurationSeconds * 1000000, self.ToneSampleRateHz, self)
+
+ self.createAudioOutput()
+
+ def createAudioOutput(self):
+ self.m_audioOutput = QAudioOutput(self.m_device, self.m_format)
+ self.m_audioOutput.notify.connect(self.notified)
+ self.m_audioOutput.stateChanged.connect(self.handleStateChanged)
+
+ self.m_generator.start()
+ self.m_audioOutput.start(self.m_generator)
+ self.m_volumeSlider.setValue(self.m_audioOutput.volume() * 100)
+
+ def deviceChanged(self, index):
+ self.m_pullTimer.stop()
+ self.m_generator.stop()
+ self.m_audioOutput.stop()
+ self.m_device = self.m_deviceBox.itemData(index)
+
+ self.createAudioOutput()
+
+ def volumeChanged(self, value):
+ if self.m_audioOutput is not None:
+ self.m_audioOutput.setVolume(value / 100.0)
+
+ def notified(self):
+ qWarning("bytesFree = %d, elapsedUSecs = %d, processedUSecs = %d" % (
+ self.m_audioOutput.bytesFree(),
+ self.m_audioOutput.elapsedUSecs(),
+ self.m_audioOutput.processedUSecs()))
+
+ def pullTimerExpired(self):
+ if self.m_audioOutput is not None and self.m_audioOutput.state() != QAudio.StoppedState:
+ chunks = self.m_audioOutput.bytesFree() // self.m_audioOutput.periodSize()
+ for _ in range(chunks):
+ data = self.m_generator.read(self.m_audioOutput.periodSize())
+ if data is None or len(data) != self.m_audioOutput.periodSize():
+ break
+
+ self.m_output.write(data)
+
+ def toggleMode(self):
+ self.m_pullTimer.stop()
+ self.m_audioOutput.stop()
+
+ if self.m_pullMode:
+ self.m_modeButton.setText(self.PULL_MODE_LABEL)
+ self.m_output = self.m_audioOutput.start()
+ self.m_pullMode = False
+ self.m_pullTimer.start(20)
+ else:
+ self.m_modeButton.setText(self.PUSH_MODE_LABEL)
+ self.m_pullMode = True
+ self.m_audioOutput.start(self.m_generator)
+
+ self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
+
+ def toggleSuspendResume(self):
+ if self.m_audioOutput.state() == QAudio.SuspendedState:
+ qWarning("status: Suspended, resume()")
+ self.m_audioOutput.resume()
+ self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
+ elif self.m_audioOutput.state() == QAudio.ActiveState:
+ qWarning("status: Active, suspend()")
+ self.m_audioOutput.suspend()
+ self.m_suspendResumeButton.setText(self.RESUME_LABEL)
+ elif self.m_audioOutput.state() == QAudio.StoppedState:
+ qWarning("status: Stopped, resume()")
+ self.m_audioOutput.resume()
+ self.m_suspendResumeButton.setText(self.SUSPEND_LABEL)
+ elif self.m_audioOutput.state() == QAudio.IdleState:
+ qWarning("status: IdleState")
+
+ stateMap = {
+ QAudio.ActiveState: "ActiveState",
+ QAudio.SuspendedState: "SuspendedState",
+ QAudio.StoppedState: "StoppedState",
+ QAudio.IdleState: "IdleState"}
+
+ def handleStateChanged(self, state):
+ qWarning("state = " + self.stateMap.get(state, "Unknown"))
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QApplication(sys.argv)
+ app.setApplicationName("Audio Output Test")
+
+ audio = AudioTest()
+ audio.show()
+
+ sys.exit(app.exec_())
diff --git a/examples/multimedia/camera.py b/examples/multimedia/camera.py
new file mode 100644
index 000000000..1b8d5ad47
--- /dev/null
+++ b/examples/multimedia/camera.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 Multimedia Camera Example"""
+
+import os, sys
+from PySide2.QtCore import QDate, QDir, QStandardPaths, Qt, QUrl
+from PySide2.QtGui import QClipboard, QGuiApplication, QDesktopServices, QIcon
+from PySide2.QtGui import QImage, QPixmap
+from PySide2.QtWidgets import (QAction, qApp, QApplication, QHBoxLayout, QLabel,
+ QMainWindow, QPushButton, QTabWidget, QToolBar, QVBoxLayout, QWidget)
+from PySide2.QtMultimedia import QCamera, QCameraImageCapture, QCameraInfo
+from PySide2.QtMultimediaWidgets import QCameraViewfinder
+
+class ImageView(QWidget):
+ def __init__(self, previewImage, fileName):
+ super(ImageView, self).__init__()
+
+ self.fileName = fileName
+
+ mainLayout = QVBoxLayout(self)
+ self.imageLabel = QLabel()
+ self.imageLabel.setPixmap(QPixmap.fromImage(previewImage))
+ mainLayout.addWidget(self.imageLabel)
+
+ topLayout = QHBoxLayout()
+ self.fileNameLabel = QLabel(QDir.toNativeSeparators(fileName))
+ self.fileNameLabel.setTextInteractionFlags(Qt.TextBrowserInteraction)
+
+ topLayout.addWidget(self.fileNameLabel)
+ topLayout.addStretch()
+ copyButton = QPushButton("Copy")
+ copyButton.setToolTip("Copy file name to clipboard")
+ topLayout.addWidget(copyButton)
+ copyButton.clicked.connect(self.copy)
+ launchButton = QPushButton("Launch")
+ launchButton.setToolTip("Launch image viewer")
+ topLayout.addWidget(launchButton)
+ launchButton.clicked.connect(self.launch)
+ mainLayout.addLayout(topLayout)
+
+ def copy(self):
+ QGuiApplication.clipboard().setText(self.fileNameLabel.text())
+
+ def launch(self):
+ QDesktopServices.openUrl(QUrl.fromLocalFile(self.fileName))
+
+class MainWindow(QMainWindow):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ self.cameraInfo = QCameraInfo.defaultCamera()
+ self.camera = QCamera(self.cameraInfo)
+ self.camera.setCaptureMode(QCamera.CaptureStillImage)
+ self.imageCapture = QCameraImageCapture(self.camera)
+ self.imageCapture.imageCaptured.connect(self.imageCaptured)
+ self.imageCapture.imageSaved.connect(self.imageSaved)
+ self.currentPreview = QImage()
+
+ toolBar = QToolBar()
+ self.addToolBar(toolBar)
+
+ fileMenu = self.menuBar().addMenu("&File")
+ shutterIcon = QIcon(os.path.join(os.path.dirname(__file__),
+ "shutter.svg"))
+ self.takePictureAction = QAction(shutterIcon, "&Take Picture", self,
+ shortcut="Ctrl+T",
+ triggered=self.takePicture)
+ self.takePictureAction.setToolTip("Take Picture")
+ fileMenu.addAction(self.takePictureAction)
+ toolBar.addAction(self.takePictureAction)
+
+ exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit",
+ self, shortcut="Ctrl+Q", triggered=self.close)
+ fileMenu.addAction(exitAction)
+
+ aboutMenu = self.menuBar().addMenu("&About")
+ aboutQtAction = QAction("About &Qt", self, triggered=qApp.aboutQt)
+ aboutMenu.addAction(aboutQtAction)
+
+ self.tabWidget = QTabWidget()
+ self.setCentralWidget(self.tabWidget)
+
+ self.cameraViewfinder = QCameraViewfinder()
+ self.camera.setViewfinder(self.cameraViewfinder)
+ self.tabWidget.addTab(self.cameraViewfinder, "Viewfinder")
+
+ if self.camera.status() != QCamera.UnavailableStatus:
+ name = self.cameraInfo.description()
+ self.setWindowTitle("PySide2 Camera Example (" + name + ")")
+ self.statusBar().showMessage("Starting: '" + name + "'", 5000)
+ self.camera.start()
+ else:
+ self.setWindowTitle("PySide2 Camera Example")
+ self.takePictureAction.setEnabled(False)
+ self.statusBar().showMessage("Camera unavailable", 5000)
+
+ def nextImageFileName(self):
+ picturesLocation = QStandardPaths.writableLocation(QStandardPaths.PicturesLocation)
+ dateString = QDate.currentDate().toString("yyyyMMdd")
+ pattern = picturesLocation + "/pyside2_camera_" + dateString + "_{:03d}.jpg"
+ n = 1
+ while True:
+ result = pattern.format(n)
+ if not os.path.exists(result):
+ return result
+ n = n + 1
+ return None
+
+ def takePicture(self):
+ self.currentPreview = QImage()
+ self.camera.searchAndLock()
+ self.imageCapture.capture(self.nextImageFileName())
+ self.camera.unlock()
+
+ def imageCaptured(self, id, previewImage):
+ self.currentPreview = previewImage
+
+ def imageSaved(self, id, fileName):
+ index = self.tabWidget.count()
+ imageView = ImageView(self.currentPreview, fileName)
+ self.tabWidget.addTab(imageView, "Capture #{}".format(index))
+ self.tabWidget.setCurrentIndex(index)
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ availableGeometry = app.desktop().availableGeometry(mainWin)
+ mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/multimedia/player.py b/examples/multimedia/player.py
new file mode 100644
index 000000000..76445cd30
--- /dev/null
+++ b/examples/multimedia/player.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 Multimedia player example"""
+
+import sys
+from PySide2.QtCore import SLOT, QStandardPaths, Qt
+from PySide2.QtGui import QIcon, QKeySequence
+from PySide2.QtWidgets import (QAction, qApp, QApplication, QDialog, QFileDialog,
+ QMainWindow, QMenu, QMenuBar, QSlider, QStyle, QToolBar)
+from PySide2.QtMultimedia import QMediaPlayer, QMediaPlaylist
+from PySide2.QtMultimediaWidgets import QVideoWidget
+
+class MainWindow(QMainWindow):
+
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ self.playlist = QMediaPlaylist()
+ self.player = QMediaPlayer()
+
+ toolBar = QToolBar()
+ self.addToolBar(toolBar)
+
+ fileMenu = self.menuBar().addMenu("&File")
+ openAction = QAction(QIcon.fromTheme("document-open"),
+ "&Open...", self, shortcut=QKeySequence.Open,
+ triggered=self.open)
+ fileMenu.addAction(openAction)
+ exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit",
+ self, shortcut="Ctrl+Q", triggered=self.close)
+ fileMenu.addAction(exitAction)
+
+ playMenu = self.menuBar().addMenu("&Play")
+ playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
+ self.playAction = toolBar.addAction(playIcon, "Play")
+ self.playAction.triggered.connect(self.player.play)
+ playMenu.addAction(self.playAction)
+
+ previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward)
+ self.previousAction = toolBar.addAction(previousIcon, "Previous")
+ self.previousAction.triggered.connect(self.previousClicked)
+ playMenu.addAction(self.previousAction)
+
+ pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
+ self.pauseAction = toolBar.addAction(pauseIcon, "Pause")
+ self.pauseAction.triggered.connect(self.player.pause)
+ playMenu.addAction(self.pauseAction)
+
+ nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward)
+ self.nextAction = toolBar.addAction(nextIcon, "Next")
+ self.nextAction.triggered.connect(self.playlist.next)
+ playMenu.addAction(self.nextAction)
+
+ stopIcon = self.style().standardIcon(QStyle.SP_MediaStop)
+ self.stopAction = toolBar.addAction(stopIcon, "Stop")
+ self.stopAction.triggered.connect(self.player.stop)
+ playMenu.addAction(self.stopAction)
+
+ self.volumeSlider = QSlider()
+ self.volumeSlider.setOrientation(Qt.Horizontal)
+ self.volumeSlider.setMinimum(0)
+ self.volumeSlider.setMaximum(100)
+ self.volumeSlider.setFixedWidth(app.desktop().availableGeometry(self).width() / 10)
+ self.volumeSlider.setValue(self.player.volume())
+ self.volumeSlider.setTickInterval(10)
+ self.volumeSlider.setTickPosition(QSlider.TicksBelow)
+ self.volumeSlider.setToolTip("Volume")
+ self.volumeSlider.valueChanged.connect(self.player.setVolume)
+ toolBar.addWidget(self.volumeSlider)
+
+ aboutMenu = self.menuBar().addMenu("&About")
+ aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
+ aboutMenu.addAction(aboutQtAct)
+
+ self.videoWidget = QVideoWidget()
+ self.setCentralWidget(self.videoWidget)
+ self.player.setPlaylist(self.playlist);
+ self.player.stateChanged.connect(self.updateButtons)
+ self.player.setVideoOutput(self.videoWidget);
+
+ self.updateButtons(self.player.state())
+
+ def open(self):
+ fileDialog = QFileDialog(self)
+ supportedMimeTypes = QMediaPlayer.supportedMimeTypes()
+ if not supportedMimeTypes:
+ supportedMimeTypes.append("video/x-msvideo") # AVI
+ fileDialog.setMimeTypeFilters(supportedMimeTypes)
+ moviesLocation = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation)
+ fileDialog.setDirectory(moviesLocation)
+ if fileDialog.exec_() == QDialog.Accepted:
+ self.playlist.addMedia(fileDialog.selectedUrls()[0])
+ self.player.play()
+
+ def previousClicked(self):
+ # Go to previous track if we are within the first 5 seconds of playback
+ # Otherwise, seek to the beginning.
+ if self.player.position() <= 5000:
+ self.playlist.previous();
+ else:
+ player.setPosition(0);
+
+ def updateButtons(self, state):
+ mediaCount = self.playlist.mediaCount()
+ self.playAction.setEnabled(mediaCount > 0
+ and state != QMediaPlayer.PlayingState)
+ self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState)
+ self.stopAction.setEnabled(state != QMediaPlayer.StoppedState)
+ self.previousAction.setEnabled(self.player.position() > 0)
+ self.nextAction.setEnabled(mediaCount > 1)
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ mainWin = MainWindow()
+ availableGeometry = app.desktop().availableGeometry(mainWin)
+ mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
+ mainWin.show()
+ sys.exit(app.exec_())
diff --git a/examples/network/blockingfortuneclient.py b/examples/network/blockingfortuneclient.py
new file mode 100644
index 000000000..8e73af0f0
--- /dev/null
+++ b/examples/network/blockingfortuneclient.py
@@ -0,0 +1,225 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the network/blockingfortunclient example from Qt v5.x, originating from PyQt"""
+
+from PySide2.QtCore import (Signal, QDataStream, QMutex, QMutexLocker,
+ QThread, QWaitCondition)
+from PySide2.QtGui import QIntValidator
+from PySide2.QtWidgets import (QApplication, QDialogButtonBox, QGridLayout,
+ QLabel, QLineEdit, QMessageBox, QPushButton, QWidget)
+from PySide2.QtNetwork import (QAbstractSocket, QHostAddress, QNetworkInterface,
+ QTcpSocket)
+
+
+class FortuneThread(QThread):
+ newFortune = Signal(str)
+
+ error = Signal(int, str)
+
+ def __init__(self, parent=None):
+ super(FortuneThread, self).__init__(parent)
+
+ self.quit = False
+ self.hostName = ''
+ self.cond = QWaitCondition()
+ self.mutex = QMutex()
+ self.port = 0
+
+ def __del__(self):
+ self.mutex.lock()
+ self.quit = True
+ self.cond.wakeOne()
+ self.mutex.unlock()
+ self.wait()
+
+ def requestNewFortune(self, hostname, port):
+ locker = QMutexLocker(self.mutex)
+ self.hostName = hostname
+ self.port = port
+ if not self.isRunning():
+ self.start()
+ else:
+ self.cond.wakeOne()
+
+ def run(self):
+ self.mutex.lock()
+ serverName = self.hostName
+ serverPort = self.port
+ self.mutex.unlock()
+
+ while not self.quit:
+ Timeout = 5 * 1000
+
+ socket = QTcpSocket()
+ socket.connectToHost(serverName, serverPort)
+
+ if not socket.waitForConnected(Timeout):
+ self.error.emit(socket.error(), socket.errorString())
+ return
+
+ while socket.bytesAvailable() < 2:
+ if not socket.waitForReadyRead(Timeout):
+ self.error.emit(socket.error(), socket.errorString())
+ return
+
+ instr = QDataStream(socket)
+ instr.setVersion(QDataStream.Qt_4_0)
+ blockSize = instr.readUInt16()
+
+ while socket.bytesAvailable() < blockSize:
+ if not socket.waitForReadyRead(Timeout):
+ self.error.emit(socket.error(), socket.errorString())
+ return
+
+ self.mutex.lock()
+ fortune = instr.readQString()
+ self.newFortune.emit(fortune)
+
+ self.cond.wait(self.mutex)
+ serverName = self.hostName
+ serverPort = self.port
+ self.mutex.unlock()
+
+
+class BlockingClient(QWidget):
+ def __init__(self, parent=None):
+ super(BlockingClient, self).__init__(parent)
+
+ self.thread = FortuneThread()
+ self.currentFortune = ''
+
+ hostLabel = QLabel("&Server name:")
+ portLabel = QLabel("S&erver port:")
+
+ for ipAddress in QNetworkInterface.allAddresses():
+ if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0:
+ break
+ else:
+ ipAddress = QHostAddress(QHostAddress.LocalHost)
+
+ ipAddress = ipAddress.toString()
+
+ self.hostLineEdit = QLineEdit(ipAddress)
+ self.portLineEdit = QLineEdit()
+ self.portLineEdit.setValidator(QIntValidator(1, 65535, self))
+
+ hostLabel.setBuddy(self.hostLineEdit)
+ portLabel.setBuddy(self.portLineEdit)
+
+ self.statusLabel = QLabel(
+ "This example requires that you run the Fortune Server example as well.")
+ self.statusLabel.setWordWrap(True)
+
+ self.getFortuneButton = QPushButton("Get Fortune")
+ self.getFortuneButton.setDefault(True)
+ self.getFortuneButton.setEnabled(False)
+
+ quitButton = QPushButton("Quit")
+
+ buttonBox = QDialogButtonBox()
+ buttonBox.addButton(self.getFortuneButton, QDialogButtonBox.ActionRole)
+ buttonBox.addButton(quitButton, QDialogButtonBox.RejectRole)
+
+ self.getFortuneButton.clicked.connect(self.requestNewFortune)
+ quitButton.clicked.connect(self.close)
+ self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton)
+ self.portLineEdit.textChanged.connect(self.enableGetFortuneButton)
+ self.thread.newFortune.connect(self.showFortune)
+ self.thread.error.connect(self.displayError)
+
+ mainLayout = QGridLayout()
+ mainLayout.addWidget(hostLabel, 0, 0)
+ mainLayout.addWidget(self.hostLineEdit, 0, 1)
+ mainLayout.addWidget(portLabel, 1, 0)
+ mainLayout.addWidget(self.portLineEdit, 1, 1)
+ mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2)
+ mainLayout.addWidget(buttonBox, 3, 0, 1, 2)
+ self.setLayout(mainLayout)
+
+ self.setWindowTitle("Blocking Fortune Client")
+ self.portLineEdit.setFocus()
+
+ def requestNewFortune(self):
+ self.getFortuneButton.setEnabled(False)
+ self.thread.requestNewFortune(self.hostLineEdit.text(),
+ int(self.portLineEdit.text()))
+
+ def showFortune(self, nextFortune):
+ if nextFortune == self.currentFortune:
+ self.requestNewFortune()
+ return
+
+ self.currentFortune = nextFortune
+ self.statusLabel.setText(self.currentFortune)
+ self.getFortuneButton.setEnabled(True)
+
+ def displayError(self, socketError, message):
+ if socketError == QAbstractSocket.HostNotFoundError:
+ QMessageBox.information(self, "Blocking Fortune Client",
+ "The host was not found. Please check the host and port "
+ "settings.")
+ elif socketError == QAbstractSocket.ConnectionRefusedError:
+ QMessageBox.information(self, "Blocking Fortune Client",
+ "The connection was refused by the peer. Make sure the "
+ "fortune server is running, and check that the host name "
+ "and port settings are correct.")
+ else:
+ QMessageBox.information(self, "Blocking Fortune Client",
+ "The following error occurred: %s." % message)
+
+ self.getFortuneButton.setEnabled(True)
+
+ def enableGetFortuneButton(self):
+ self.getFortuneButton.setEnabled(self.hostLineEdit.text() != '' and
+ self.portLineEdit.text() != '')
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QApplication(sys.argv)
+ client = BlockingClient()
+ client.show()
+ sys.exit(app.exec_())
diff --git a/examples/network/fortuneclient.py b/examples/network/fortuneclient.py
new file mode 100755
index 000000000..3ec5623b8
--- /dev/null
+++ b/examples/network/fortuneclient.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the network/fortuneclient example from Qt v5.x"""
+
+from PySide2 import QtCore, QtGui, QtWidgets, QtNetwork
+
+
+class Client(QtWidgets.QDialog):
+ def __init__(self, parent=None):
+ super(Client, self).__init__(parent)
+
+ self.blockSize = 0
+ self.currentFortune = ''
+
+ hostLabel = QtWidgets.QLabel("&Server name:")
+ portLabel = QtWidgets.QLabel("S&erver port:")
+
+ self.hostLineEdit = QtWidgets.QLineEdit('Localhost')
+ self.portLineEdit = QtWidgets.QLineEdit()
+ self.portLineEdit.setValidator(QtGui.QIntValidator(1, 65535, self))
+
+ hostLabel.setBuddy(self.hostLineEdit)
+ portLabel.setBuddy(self.portLineEdit)
+
+ self.statusLabel = QtWidgets.QLabel("This examples requires that you run "
+ "the Fortune Server example as well.")
+
+ self.getFortuneButton = QtWidgets.QPushButton("Get Fortune")
+ self.getFortuneButton.setDefault(True)
+ self.getFortuneButton.setEnabled(False)
+
+ quitButton = QtWidgets.QPushButton("Quit")
+
+ buttonBox = QtWidgets.QDialogButtonBox()
+ buttonBox.addButton(self.getFortuneButton,
+ QtWidgets.QDialogButtonBox.ActionRole)
+ buttonBox.addButton(quitButton, QtWidgets.QDialogButtonBox.RejectRole)
+
+ self.tcpSocket = QtNetwork.QTcpSocket(self)
+
+ self.hostLineEdit.textChanged.connect(self.enableGetFortuneButton)
+ self.portLineEdit.textChanged.connect(self.enableGetFortuneButton)
+ self.getFortuneButton.clicked.connect(self.requestNewFortune)
+ quitButton.clicked.connect(self.close)
+ self.tcpSocket.readyRead.connect(self.readFortune)
+ self.tcpSocket.error.connect(self.displayError)
+
+ mainLayout = QtWidgets.QGridLayout()
+ mainLayout.addWidget(hostLabel, 0, 0)
+ mainLayout.addWidget(self.hostLineEdit, 0, 1)
+ mainLayout.addWidget(portLabel, 1, 0)
+ mainLayout.addWidget(self.portLineEdit, 1, 1)
+ mainLayout.addWidget(self.statusLabel, 2, 0, 1, 2)
+ mainLayout.addWidget(buttonBox, 3, 0, 1, 2)
+ self.setLayout(mainLayout)
+
+ self.setWindowTitle("Fortune Client")
+ self.portLineEdit.setFocus()
+
+ def requestNewFortune(self):
+ self.getFortuneButton.setEnabled(False)
+ self.blockSize = 0
+ self.tcpSocket.abort()
+ self.tcpSocket.connectToHost(self.hostLineEdit.text(),
+ int(self.portLineEdit.text()))
+
+ def readFortune(self):
+ instr = QtCore.QDataStream(self.tcpSocket)
+ instr.setVersion(QtCore.QDataStream.Qt_4_0)
+
+ if self.blockSize == 0:
+ if self.tcpSocket.bytesAvailable() < 2:
+ return
+
+ self.blockSize = instr.readUInt16()
+
+ if self.tcpSocket.bytesAvailable() < self.blockSize:
+ return
+
+ nextFortune = instr.readString()
+
+ try:
+ # Python v3.
+ nextFortune = str(nextFortune, encoding='ascii')
+ except TypeError:
+ # Python v2.
+ pass
+
+ if nextFortune == self.currentFortune:
+ QtCore.QTimer.singleShot(0, self.requestNewFortune)
+ return
+
+ self.currentFortune = nextFortune
+ self.statusLabel.setText(self.currentFortune)
+ self.getFortuneButton.setEnabled(True)
+
+ def displayError(self, socketError):
+ if socketError == QtNetwork.QAbstractSocket.RemoteHostClosedError:
+ pass
+ elif socketError == QtNetwork.QAbstractSocket.HostNotFoundError:
+ QtWidgets.QMessageBox.information(self, "Fortune Client",
+ "The host was not found. Please check the host name and "
+ "port settings.")
+ elif socketError == QtNetwork.QAbstractSocket.ConnectionRefusedError:
+ QtWidgets.QMessageBox.information(self, "Fortune Client",
+ "The connection was refused by the peer. Make sure the "
+ "fortune server is running, and check that the host name "
+ "and port settings are correct.")
+ else:
+ QtWidgets.QMessageBox.information(self, "Fortune Client",
+ "The following error occurred: %s." % self.tcpSocket.errorString())
+
+ self.getFortuneButton.setEnabled(True)
+
+ def enableGetFortuneButton(self):
+ self.getFortuneButton.setEnabled(bool(self.hostLineEdit.text() and
+ self.portLineEdit.text()))
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ client = Client()
+ client.show()
+ sys.exit(client.exec_())
diff --git a/examples/network/fortuneserver.py b/examples/network/fortuneserver.py
new file mode 100755
index 000000000..1c08f6e82
--- /dev/null
+++ b/examples/network/fortuneserver.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the network/fortuneserver example from Qt v5.x"""
+
+import random
+
+from PySide2 import QtCore, QtGui, QtWidgets, QtNetwork
+
+
+class Server(QtWidgets.QDialog):
+ def __init__(self, parent=None):
+ super(Server, self).__init__(parent)
+
+ statusLabel = QtWidgets.QLabel()
+ quitButton = QtWidgets.QPushButton("Quit")
+ quitButton.setAutoDefault(False)
+
+ self.tcpServer = QtNetwork.QTcpServer(self)
+ if not self.tcpServer.listen():
+ QtWidgets.QMessageBox.critical(self, "Fortune Server",
+ "Unable to start the server: %s." % self.tcpServer.errorString())
+ self.close()
+ return
+
+ statusLabel.setText("The server is running on port %d.\nRun the "
+ "Fortune Client example now." % self.tcpServer.serverPort())
+
+ self.fortunes = (
+ "You've been leading a dog's life. Stay off the furniture.",
+ "You've got to think about tomorrow.",
+ "You will be surprised by a loud noise.",
+ "You will feel hungry again in another hour.",
+ "You might have mail.",
+ "You cannot kill time without injuring eternity.",
+ "Computers are not intelligent. They only think they are.")
+
+ quitButton.clicked.connect(self.close)
+ self.tcpServer.newConnection.connect(self.sendFortune)
+
+ buttonLayout = QtWidgets.QHBoxLayout()
+ buttonLayout.addStretch(1)
+ buttonLayout.addWidget(quitButton)
+ buttonLayout.addStretch(1)
+
+ mainLayout = QtWidgets.QVBoxLayout()
+ mainLayout.addWidget(statusLabel)
+ mainLayout.addLayout(buttonLayout)
+ self.setLayout(mainLayout)
+
+ self.setWindowTitle("Fortune Server")
+
+ def sendFortune(self):
+ block = QtCore.QByteArray()
+ out = QtCore.QDataStream(block, QtCore.QIODevice.WriteOnly)
+ out.setVersion(QtCore.QDataStream.Qt_4_0)
+ out.writeUInt16(0)
+ fortune = self.fortunes[random.randint(0, len(self.fortunes) - 1)]
+
+ try:
+ # Python v3.
+ fortune = bytes(fortune, encoding='ascii')
+ except:
+ # Python v2.
+ pass
+
+ out.writeString(fortune)
+ out.device().seek(0)
+ out.writeUInt16(block.size() - 2)
+
+ clientConnection = self.tcpServer.nextPendingConnection()
+ clientConnection.disconnected.connect(clientConnection.deleteLater)
+
+ clientConnection.write(block)
+ clientConnection.disconnectFromHost()
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtWidgets.QApplication(sys.argv)
+ server = Server()
+ random.seed(None)
+ sys.exit(server.exec_())
diff --git a/examples/network/threadedfortuneserver.py b/examples/network/threadedfortuneserver.py
new file mode 100755
index 000000000..95452e7e9
--- /dev/null
+++ b/examples/network/threadedfortuneserver.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the network/threadedfortuneserver example from Qt v5.x, originating from PyQt"""
+
+import random
+
+from PySide2.QtCore import (Signal, QByteArray, QDataStream, QIODevice,
+ QThread, Qt)
+from PySide2.QtWidgets import (QApplication, QDialog, QHBoxLayout, QLabel,
+ QMessageBox, QPushButton, QVBoxLayout)
+from PySide2.QtNetwork import (QHostAddress, QNetworkInterface, QTcpServer,
+ QTcpSocket)
+
+
+class FortuneThread(QThread):
+ error = Signal(QTcpSocket.SocketError)
+
+ def __init__(self, socketDescriptor, fortune, parent):
+ super(FortuneThread, self).__init__(parent)
+
+ self.socketDescriptor = socketDescriptor
+ self.text = fortune
+
+ def run(self):
+ tcpSocket = QTcpSocket()
+ if not tcpSocket.setSocketDescriptor(self.socketDescriptor):
+ self.error.emit(tcpSocket.error())
+ return
+
+ block = QByteArray()
+ outstr = QDataStream(block, QIODevice.WriteOnly)
+ outstr.setVersion(QDataStream.Qt_4_0)
+ outstr.writeUInt16(0)
+ outstr.writeQString(self.text)
+ outstr.device().seek(0)
+ outstr.writeUInt16(block.size() - 2)
+
+ tcpSocket.write(block)
+ tcpSocket.disconnectFromHost()
+ tcpSocket.waitForDisconnected()
+
+
+class FortuneServer(QTcpServer):
+ fortunes = (
+ "You've been leading a dog's life. Stay off the furniture.",
+ "You've got to think about tomorrow.",
+ "You will be surprised by a loud noise.",
+ "You will feel hungry again in another hour.",
+ "You might have mail.",
+ "You cannot kill time without injuring eternity.",
+ "Computers are not intelligent. They only think they are.")
+
+ def incomingConnection(self, socketDescriptor):
+ fortune = self.fortunes[random.randint(0, len(self.fortunes) - 1)]
+
+ thread = FortuneThread(socketDescriptor, fortune, self)
+ thread.finished.connect(thread.deleteLater)
+ thread.start()
+
+
+class Dialog(QDialog):
+ def __init__(self, parent=None):
+ super(Dialog, self).__init__(parent)
+
+ self.server = FortuneServer()
+
+ statusLabel = QLabel()
+ statusLabel.setTextInteractionFlags(Qt.TextBrowserInteraction)
+ statusLabel.setWordWrap(True)
+ quitButton = QPushButton("Quit")
+ quitButton.setAutoDefault(False)
+
+ if not self.server.listen():
+ QMessageBox.critical(self, "Threaded Fortune Server",
+ "Unable to start the server: %s." % self.server.errorString())
+ self.close()
+ return
+
+ for ipAddress in QNetworkInterface.allAddresses():
+ if ipAddress != QHostAddress.LocalHost and ipAddress.toIPv4Address() != 0:
+ break
+ else:
+ ipAddress = QHostAddress(QHostAddress.LocalHost)
+
+ ipAddress = ipAddress.toString()
+
+ statusLabel.setText("The server is running on\n\nIP: %s\nport: %d\n\n"
+ "Run the Fortune Client example now." % (ipAddress, self.server.serverPort()))
+
+ quitButton.clicked.connect(self.close)
+
+ buttonLayout = QHBoxLayout()
+ buttonLayout.addStretch(1)
+ buttonLayout.addWidget(quitButton)
+ buttonLayout.addStretch(1)
+
+ mainLayout = QVBoxLayout()
+ mainLayout.addWidget(statusLabel)
+ mainLayout.addLayout(buttonLayout)
+ self.setLayout(mainLayout)
+
+ self.setWindowTitle("Threaded Fortune Server")
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QApplication(sys.argv)
+ dialog = Dialog()
+ dialog.show()
+ sys.exit(dialog.exec_())
diff --git a/examples/opengl/2dpainting.py b/examples/opengl/2dpainting.py
new file mode 100755
index 000000000..6073024c5
--- /dev/null
+++ b/examples/opengl/2dpainting.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/legacy/2dpainting example from Qt v5.x"""
+
+import sys
+import math
+from PySide2.QtCore import *
+from PySide2.QtGui import *
+from PySide2.QtWidgets import *
+from PySide2.QtOpenGL import *
+
+try:
+ from OpenGL import GL
+except ImportError:
+ app = QApplication(sys.argv)
+ messageBox = QMessageBox(QMessageBox.Critical, "OpenGL 2dpainting",
+ "PyOpenGL must be installed to run this example.",
+ QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+
+class Helper:
+ def __init__(self):
+ gradient = QLinearGradient(QPointF(50, -20), QPointF(80, 20))
+ gradient.setColorAt(0.0, Qt.white)
+ gradient.setColorAt(1.0, QColor(0xa6, 0xce, 0x39))
+
+ self.background = QBrush(QColor(64, 32, 64))
+ self.circleBrush = QBrush(gradient)
+ self.circlePen = QPen(Qt.black)
+ self.circlePen.setWidth(1)
+ self.textPen = QPen(Qt.white)
+ self.textFont = QFont()
+ self.textFont.setPixelSize(50)
+
+ def paint(self, painter, event, elapsed):
+ painter.fillRect(event.rect(), self.background)
+ painter.translate(100, 100)
+
+ painter.save()
+ painter.setBrush(self.circleBrush)
+ painter.setPen(self.circlePen)
+ painter.rotate(elapsed * 0.030)
+
+ r = elapsed/1000.0
+ n = 30
+ for i in range(n):
+ painter.rotate(30)
+ radius = 0 + 120.0*((i+r)/n)
+ circleRadius = 1 + ((i+r)/n)*20
+ painter.drawEllipse(QRectF(radius, -circleRadius,
+ circleRadius*2, circleRadius*2))
+
+ painter.restore()
+
+ painter.setPen(self.textPen)
+ painter.setFont(self.textFont)
+ painter.drawText(QRect(-50, -50, 100, 100), Qt.AlignCenter, "Qt")
+
+
+class Widget(QWidget):
+ def __init__(self, helper, parent = None):
+ QWidget.__init__(self, parent)
+
+ self.helper = helper
+ self.elapsed = 0
+ self.setFixedSize(200, 200)
+
+ def animate(self):
+ self.elapsed = (self.elapsed + self.sender().interval()) % 1000
+ self.repaint()
+
+ def paintEvent(self, event):
+ painter = QPainter()
+ painter.begin(self)
+ painter.setRenderHint(QPainter.Antialiasing)
+ self.helper.paint(painter, event, self.elapsed)
+ painter.end()
+
+
+class GLWidget(QGLWidget):
+ def __init__(self, helper, parent = None):
+ QGLWidget.__init__(self, QGLFormat(QGL.SampleBuffers), parent)
+
+ self.helper = helper
+ self.elapsed = 0
+ self.setFixedSize(200, 200)
+
+ def animate(self):
+ self.elapsed = (self.elapsed + self.sender().interval()) % 1000
+ self.repaint()
+
+ def paintEvent(self, event):
+ painter = QPainter()
+ painter.begin(self)
+ self.helper.paint(painter, event, self.elapsed)
+ painter.end()
+
+
+class Window(QWidget):
+ def __init__(self, parent = None):
+ QWidget.__init__(self, parent)
+
+ helper = Helper()
+ native = Widget(helper, self)
+ openGL = GLWidget(helper, self)
+ nativeLabel = QLabel(self.tr("Native"))
+ nativeLabel.setAlignment(Qt.AlignHCenter)
+ openGLLabel = QLabel(self.tr("OpenGL"))
+ openGLLabel.setAlignment(Qt.AlignHCenter)
+
+ layout = QGridLayout()
+ layout.addWidget(native, 0, 0)
+ layout.addWidget(openGL, 0, 1)
+ layout.addWidget(nativeLabel, 1, 0)
+ layout.addWidget(openGLLabel, 1, 1)
+ self.setLayout(layout)
+
+ timer = QTimer(self)
+ self.connect(timer, SIGNAL("timeout()"), native.animate)
+ self.connect(timer, SIGNAL("timeout()"), openGL.animate)
+ timer.start(50)
+
+ self.setWindowTitle(self.tr("2D Painting on Native and OpenGL Widgets"))
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/opengl/contextinfo.py b/examples/opengl/contextinfo.py
new file mode 100644
index 000000000..b2df1ded2
--- /dev/null
+++ b/examples/opengl/contextinfo.py
@@ -0,0 +1,251 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the opengl/contextinfo example from Qt v5.x"""
+
+import numpy
+import sys
+
+from PySide2.QtCore import QLibraryInfo, QSize, QTimer, Qt
+from PySide2.QtGui import (QMatrix4x4, QOpenGLBuffer, QOpenGLContext, QOpenGLShader,
+ QOpenGLShaderProgram, QOpenGLVertexArrayObject, QSurfaceFormat, QWindow)
+from PySide2.QtWidgets import (QApplication, QHBoxLayout, QMessageBox, QPlainTextEdit,
+ QWidget)
+from PySide2.support import VoidPtr
+try:
+ from OpenGL import GL
+except ImportError:
+ app = QApplication(sys.argv)
+ messageBox = QMessageBox(QMessageBox.Critical, "ContextInfo",
+ "PyOpenGL must be installed to run this example.",
+ QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+vertexShaderSource110 = """
+#version 110
+attribute highp vec4 posAttr;
+attribute lowp vec4 colAttr;
+varying lowp vec4 col;
+uniform highp mat4 matrix;
+void main() {
+ col = colAttr;
+ gl_Position = matrix * posAttr;
+}
+"""
+
+fragmentShaderSource110 = """
+#version 110
+varying lowp vec4 col;
+void main() {
+ gl_FragColor = col;
+}
+"""
+
+vertexShaderSource = """
+#version 150
+in vec4 posAttr;
+in vec4 colAttr;
+out vec4 col;
+uniform mat4 matrix;
+void main() {
+ col = colAttr;
+ gl_Position = matrix * posAttr;
+}
+"""
+
+fragmentShaderSource = """
+#version 150
+in vec4 col;
+out vec4 fragColor;
+void main() {
+ fragColor = col;
+}
+"""
+
+vertices = numpy.array([0, 0.707, -0.5, -0.5, 0.5, -0.5], dtype = numpy.float32)
+colors = numpy.array([1, 0, 0, 0, 1, 0, 0, 0, 1], dtype = numpy.float32)
+
+class RenderWindow(QWindow):
+ def __init__(self, format):
+ super(RenderWindow, self).__init__()
+ self.setSurfaceType(QWindow.OpenGLSurface);
+ self.setFormat(format);
+ self.context = QOpenGLContext(self);
+ self.context.setFormat(self.requestedFormat());
+ if not self.context.create():
+ raise Exception("Unable to create GL context")
+ self.program = None
+ self.timer = None
+ self.angle = 0
+
+ def initGl(self):
+ self.program = QOpenGLShaderProgram(self);
+ self.vao = QOpenGLVertexArrayObject()
+ self.vbo = QOpenGLBuffer()
+
+ format = self.context.format();
+ useNewStyleShader = format.profile() == QSurfaceFormat.CoreProfile;
+ # Try to handle 3.0 & 3.1 that do not have the core/compatibility profile
+ # concept 3.2+ has. This may still fail since version 150 (3.2) is
+ # specified in the sources but it's worth a try.
+ if (format.renderableType() == QSurfaceFormat.OpenGL and format.majorVersion() == 3
+ and format.minorVersion() <= 1):
+ useNewStyleShader = not format.testOption(QSurfaceFormat.DeprecatedFunctions)
+
+ vertexShader = vertexShaderSource if useNewStyleShader else vertexShaderSource110
+ fragmentShader = fragmentShaderSource if useNewStyleShader else fragmentShaderSource110
+ if not self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, vertexShader):
+ raise Exception("Vertex shader could not be added: {} ({})".format(self.program.log(), vertexShader))
+ if not self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, fragmentShader):
+ raise Exception("Fragment shader could not be added: {} ({})".format(self.program.log(), fragmentShader))
+ if not self.program.link():
+ raise Exception("Could not link shaders: {}".format(self.program.log()))
+
+ self.posAttr = self.program.attributeLocation("posAttr");
+ self.colAttr = self.program.attributeLocation("colAttr");
+ self.matrixUniform = self.program.uniformLocation("matrix");
+
+ self.vbo.create();
+ self.vbo.bind();
+ self.verticesData = vertices.tobytes()
+ self.colorsData = colors.tobytes()
+ verticesSize = 4 * vertices.size
+ colorsSize = 4 * colors.size
+ self.vbo.allocate(VoidPtr(self.verticesData), verticesSize + colorsSize);
+ self.vbo.write(verticesSize, VoidPtr(self.colorsData), colorsSize)
+ self.vbo.release();
+
+ vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
+ if self.vao.isCreated(): # have VAO support, use it
+ self.setupVertexAttribs()
+
+ def setupVertexAttribs(self):
+ self.vbo.bind();
+ self.program.setAttributeBuffer(self.posAttr, GL.GL_FLOAT, 0, 2);
+ self.program.setAttributeBuffer(self.colAttr, GL.GL_FLOAT, 4 * vertices.size, 3);
+ self.program.enableAttributeArray(self.posAttr);
+ self.program.enableAttributeArray(self.colAttr);
+ self.vbo.release();
+
+ def exposeEvent(self, event):
+ if self.isExposed():
+ self.render()
+ if self.timer is None:
+ self.timer = QTimer(self)
+ self.timer.timeout.connect(self.slotTimer)
+ self.timer.start(10)
+
+ def render(self):
+ if not self.context.makeCurrent(self):
+ raise Exception("makeCurrent() failed")
+ functions = self.context.functions()
+ if self.program is None:
+ functions.glEnable(GL.GL_DEPTH_TEST)
+ functions.glClearColor(0, 0, 0, 1)
+ self.initGl()
+
+ functions.glViewport(0, 0, self.width(), self.height());
+ functions.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
+
+ self.program.bind();
+ matrix = QMatrix4x4()
+ matrix.perspective(60, 4 / 3, 0.1, 100)
+ matrix.translate(0, 0, -2)
+ matrix.rotate(self.angle, 0, 1, 0)
+ self.program.setUniformValue(self.matrixUniform, matrix);
+
+ if self.vao.isCreated():
+ self.vao.bind();
+ else: # no VAO support, set the vertex attribute arrays now
+ self.setupVertexAttribs()
+
+ functions.glDrawArrays(GL.GL_TRIANGLES, 0, 3);
+
+ self.vao.release()
+ self.program.release()
+
+ # swapInterval is 1 by default which means that swapBuffers() will (hopefully) block
+ # and wait for vsync.
+ self.context.swapBuffers(self)
+ self.context.doneCurrent()
+
+ def slotTimer(self):
+ self.render()
+ self.angle += 1
+
+ def glInfo(self):
+ if not self.context.makeCurrent(self):
+ raise Exception("makeCurrent() failed")
+ functions = self.context.functions()
+ text = "Vendor: {}\nRenderer: {}\nVersion: {}\nShading language: {}".format(
+ functions.glGetString(GL.GL_VENDOR), functions.glGetString(GL.GL_RENDERER),
+ functions.glGetString(GL.GL_VERSION),
+ functions.glGetString(GL.GL_SHADING_LANGUAGE_VERSION))
+ self.context.doneCurrent()
+ return text
+
+class MainWindow(QWidget):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+ hBoxLayout = QHBoxLayout(self)
+ self.plainTextEdit = QPlainTextEdit()
+ self.plainTextEdit.setMinimumWidth(400)
+ self.plainTextEdit.setReadOnly(True)
+ hBoxLayout.addWidget(self.plainTextEdit)
+ self.renderWindow = RenderWindow(QSurfaceFormat())
+ container = QWidget.createWindowContainer(self.renderWindow)
+ container.setMinimumSize(QSize(400, 400))
+ hBoxLayout.addWidget(container)
+
+ def updateDescription(self):
+ text = "{}\n\nPython {}\n\n{}".format(QLibraryInfo.build(), sys.version,
+ self.renderWindow.glInfo())
+ self.plainTextEdit.setPlainText(text)
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ mainWindow = MainWindow()
+ mainWindow.show()
+ mainWindow.updateDescription()
+ sys.exit(app.exec_())
diff --git a/examples/opengl/grabber.py b/examples/opengl/grabber.py
new file mode 100644
index 000000000..f9eb9dc05
--- /dev/null
+++ b/examples/opengl/grabber.py
@@ -0,0 +1,436 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/legacy/grabber example from Qt v5.x"""
+
+import sys
+import math
+
+from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
+
+try:
+ from OpenGL.GL import *
+except ImportError:
+ app = QtWidgets.QApplication(sys.argv)
+ messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL grabber",
+ "PyOpenGL must be installed to run this example.",
+ QtWidgets.QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+
+class GLWidget(QtOpenGL.QGLWidget):
+ xRotationChanged = QtCore.Signal(int)
+ yRotationChanged = QtCore.Signal(int)
+ zRotationChanged = QtCore.Signal(int)
+
+ def __init__(self, parent=None):
+ super(GLWidget, self).__init__(parent)
+
+ self.gear1 = 0
+ self.gear2 = 0
+ self.gear3 = 0
+ self.xRot = 0
+ self.yRot = 0
+ self.zRot = 0
+ self.gear1Rot = 0
+
+ timer = QtCore.QTimer(self)
+ timer.timeout.connect(self.advanceGears)
+ timer.start(20)
+
+ def freeResources(self):
+ self.makeCurrent()
+ glDeleteLists(self.gear1, 1)
+ glDeleteLists(self.gear2, 1)
+ glDeleteLists(self.gear3, 1)
+
+ def setXRotation(self, angle):
+ self.normalizeAngle(angle)
+
+ if angle != self.xRot:
+ self.xRot = angle
+ self.xRotationChanged.emit(angle)
+ self.updateGL()
+
+ def setYRotation(self, angle):
+ self.normalizeAngle(angle)
+
+ if angle != self.yRot:
+ self.yRot = angle
+ self.yRotationChanged.emit(angle)
+ self.updateGL()
+
+ def setZRotation(self, angle):
+ self.normalizeAngle(angle)
+
+ if angle != self.zRot:
+ self.zRot = angle
+ self.zRotationChanged.emit(angle)
+ self.updateGL()
+
+ def initializeGL(self):
+ lightPos = (5.0, 5.0, 10.0, 1.0)
+ reflectance1 = (0.8, 0.1, 0.0, 1.0)
+ reflectance2 = (0.0, 0.8, 0.2, 1.0)
+ reflectance3 = (0.2, 0.2, 1.0, 1.0)
+
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPos)
+ glEnable(GL_LIGHTING)
+ glEnable(GL_LIGHT0)
+ glEnable(GL_DEPTH_TEST)
+
+ self.gear1 = self.makeGear(reflectance1, 1.0, 4.0, 1.0, 0.7, 20)
+ self.gear2 = self.makeGear(reflectance2, 0.5, 2.0, 2.0, 0.7, 10)
+ self.gear3 = self.makeGear(reflectance3, 1.3, 2.0, 0.5, 0.7, 10)
+
+ glEnable(GL_NORMALIZE)
+ glClearColor(0.0, 0.0, 0.0, 1.0)
+
+ def paintGL(self):
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+
+ glPushMatrix()
+ glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
+ glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
+ glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
+
+ self.drawGear(self.gear1, -3.0, -2.0, 0.0, self.gear1Rot / 16.0)
+ self.drawGear(self.gear2, +3.1, -2.0, 0.0,
+ -2.0 * (self.gear1Rot / 16.0) - 9.0)
+
+ glRotated(+90.0, 1.0, 0.0, 0.0)
+ self.drawGear(self.gear3, -3.1, -1.8, -2.2,
+ +2.0 * (self.gear1Rot / 16.0) - 2.0)
+
+ glPopMatrix()
+
+ def resizeGL(self, width, height):
+ side = min(width, height)
+ if side < 0:
+ return
+
+ glViewport(int((width - side) / 2), int((height - side) / 2), side, side)
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+ glFrustum(-1.0, +1.0, -1.0, 1.0, 5.0, 60.0)
+ glMatrixMode(GL_MODELVIEW)
+ glLoadIdentity()
+ glTranslated(0.0, 0.0, -40.0)
+
+ def mousePressEvent(self, event):
+ self.lastPos = event.pos()
+
+ def mouseMoveEvent(self, event):
+ dx = event.x() - self.lastPos.x()
+ dy = event.y() - self.lastPos.y()
+
+ if event.buttons() & QtCore.Qt.LeftButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setYRotation(self.yRot + 8 * dx)
+ elif event.buttons() & QtCore.Qt.RightButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setZRotation(self.zRot + 8 * dx)
+
+ self.lastPos = event.pos()
+
+ def advanceGears(self):
+ self.gear1Rot += 2 * 16
+ self.updateGL()
+
+ def xRotation(self):
+ return self.xRot
+
+ def yRotation(self):
+ return self.yRot
+
+ def zRotation(self):
+ return self.zRot
+
+ def makeGear(self, reflectance, innerRadius, outerRadius, thickness, toothSize, toothCount):
+ list = glGenLists(1)
+ glNewList(list, GL_COMPILE)
+ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, reflectance)
+
+ r0 = innerRadius
+ r1 = outerRadius - toothSize / 2.0
+ r2 = outerRadius + toothSize / 2.0
+ delta = (2.0 * math.pi / toothCount) / 4.0
+ z = thickness / 2.0
+
+ glShadeModel(GL_FLAT)
+
+ for i in range(2):
+ if i == 0:
+ sign = +1.0
+ else:
+ sign = -1.0
+
+ glNormal3d(0.0, 0.0, sign)
+
+ glBegin(GL_QUAD_STRIP)
+
+ for j in range(toothCount+1):
+ angle = 2.0 * math.pi * j / toothCount
+ glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), sign * z)
+ glVertex3d(r1 * math.cos(angle), r1 * math.sin(angle), sign * z)
+ glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), sign * z)
+ glVertex3d(r1 * math.cos(angle + 3 * delta), r1 * math.sin(angle + 3 * delta), sign * z)
+
+ glEnd()
+
+ glBegin(GL_QUADS)
+
+ for j in range(toothCount):
+ angle = 2.0 * math.pi * j / toothCount
+ glVertex3d(r1 * math.cos(angle), r1 * math.sin(angle), sign * z)
+ glVertex3d(r2 * math.cos(angle + delta), r2 * math.sin(angle + delta), sign * z)
+ glVertex3d(r2 * math.cos(angle + 2 * delta), r2 * math.sin(angle + 2 * delta), sign * z)
+ glVertex3d(r1 * math.cos(angle + 3 * delta), r1 * math.sin(angle + 3 * delta), sign * z)
+
+ glEnd()
+
+ glBegin(GL_QUAD_STRIP)
+
+ for i in range(toothCount):
+ for j in range(2):
+ angle = 2.0 * math.pi * (i + (j / 2.0)) / toothCount
+ s1 = r1
+ s2 = r2
+
+ if j == 1:
+ s1, s2 = s2, s1
+
+ glNormal3d(math.cos(angle), math.sin(angle), 0.0)
+ glVertex3d(s1 * math.cos(angle), s1 * math.sin(angle), +z)
+ glVertex3d(s1 * math.cos(angle), s1 * math.sin(angle), -z)
+
+ glNormal3d(s2 * math.sin(angle + delta) - s1 * math.sin(angle), s1 * math.cos(angle) - s2 * math.cos(angle + delta), 0.0)
+ glVertex3d(s2 * math.cos(angle + delta), s2 * math.sin(angle + delta), +z)
+ glVertex3d(s2 * math.cos(angle + delta), s2 * math.sin(angle + delta), -z)
+
+ glVertex3d(r1, 0.0, +z)
+ glVertex3d(r1, 0.0, -z)
+ glEnd()
+
+ glShadeModel(GL_SMOOTH)
+
+ glBegin(GL_QUAD_STRIP)
+
+ for i in range(toothCount+1):
+ angle = i * 2.0 * math.pi / toothCount
+ glNormal3d(-math.cos(angle), -math.sin(angle), 0.0)
+ glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), +z)
+ glVertex3d(r0 * math.cos(angle), r0 * math.sin(angle), -z)
+
+ glEnd()
+
+ glEndList()
+
+ return list
+
+ def drawGear(self, gear, dx, dy, dz, angle):
+ glPushMatrix()
+ glTranslated(dx, dy, dz)
+ glRotated(angle, 0.0, 0.0, 1.0)
+ glCallList(gear)
+ glPopMatrix()
+
+ def normalizeAngle(self, angle):
+ while (angle < 0):
+ angle += 360 * 16
+
+ while (angle > 360 * 16):
+ angle -= 360 * 16
+
+
+class MainWindow(QtWidgets.QMainWindow):
+ def __init__(self):
+ super(MainWindow, self).__init__()
+
+ centralWidget = QtWidgets.QWidget()
+ self.setCentralWidget(centralWidget)
+
+ self.glWidget = GLWidget()
+ self.pixmapLabel = QtWidgets.QLabel()
+
+ self.glWidgetArea = QtWidgets.QScrollArea()
+ self.glWidgetArea.setWidget(self.glWidget)
+ self.glWidgetArea.setWidgetResizable(True)
+ self.glWidgetArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+ self.glWidgetArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
+ self.glWidgetArea.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
+ QtWidgets.QSizePolicy.Ignored)
+ self.glWidgetArea.setMinimumSize(50, 50)
+
+ self.pixmapLabelArea = QtWidgets.QScrollArea()
+ self.pixmapLabelArea.setWidget(self.pixmapLabel)
+ self.pixmapLabelArea.setSizePolicy(QtWidgets.QSizePolicy.Ignored,
+ QtWidgets.QSizePolicy.Ignored)
+ self.pixmapLabelArea.setMinimumSize(50, 50)
+
+ xSlider = self.createSlider(self.glWidget.xRotationChanged,
+ self.glWidget.setXRotation)
+ ySlider = self.createSlider(self.glWidget.yRotationChanged,
+ self.glWidget.setYRotation)
+ zSlider = self.createSlider(self.glWidget.zRotationChanged,
+ self.glWidget.setZRotation)
+
+ self.createActions()
+ self.createMenus()
+
+ centralLayout = QtWidgets.QGridLayout()
+ centralLayout.addWidget(self.glWidgetArea, 0, 0)
+ centralLayout.addWidget(self.pixmapLabelArea, 0, 1)
+ centralLayout.addWidget(xSlider, 1, 0, 1, 2)
+ centralLayout.addWidget(ySlider, 2, 0, 1, 2)
+ centralLayout.addWidget(zSlider, 3, 0, 1, 2)
+ centralWidget.setLayout(centralLayout)
+
+ xSlider.setValue(15 * 16)
+ ySlider.setValue(345 * 16)
+ zSlider.setValue(0 * 16)
+
+ self.setWindowTitle("Grabber")
+ self.resize(400, 300)
+
+ def renderIntoPixmap(self):
+ size = self.getSize()
+
+ if size.isValid():
+ pixmap = self.glWidget.renderPixmap(size.width(), size.height())
+ self.setPixmap(pixmap)
+
+ def grabFrameBuffer(self):
+ image = self.glWidget.grabFrameBuffer()
+ self.setPixmap(QtGui.QPixmap.fromImage(image))
+
+ def clearPixmap(self):
+ self.setPixmap(QtGui.QPixmap())
+
+ def about(self):
+ QtWidgets.QMessageBox.about(self, "About Grabber",
+ "The <b>Grabber</b> example demonstrates two approaches for "
+ "rendering OpenGL into a Qt pixmap.")
+
+ def createActions(self):
+ self.renderIntoPixmapAct = QtWidgets.QAction("&Render into Pixmap...",
+ self, shortcut="Ctrl+R", triggered=self.renderIntoPixmap)
+
+ self.grabFrameBufferAct = QtWidgets.QAction("&Grab Frame Buffer", self,
+ shortcut="Ctrl+G", triggered=self.grabFrameBuffer)
+
+ self.clearPixmapAct = QtWidgets.QAction("&Clear Pixmap", self,
+ shortcut="Ctrl+L", triggered=self.clearPixmap)
+
+ self.exitAct = QtWidgets.QAction("E&xit", self, shortcut="Ctrl+Q",
+ triggered=self.close)
+
+ self.aboutAct = QtWidgets.QAction("&About", self, triggered=self.about)
+
+ self.aboutQtAct = QtWidgets.QAction("About &Qt", self,
+ triggered=QtWidgets.qApp.aboutQt)
+
+ def createMenus(self):
+ self.fileMenu = self.menuBar().addMenu("&File")
+ self.fileMenu.addAction(self.renderIntoPixmapAct)
+ self.fileMenu.addAction(self.grabFrameBufferAct)
+ self.fileMenu.addAction(self.clearPixmapAct)
+ self.fileMenu.addSeparator()
+ self.fileMenu.addAction(self.exitAct)
+
+ self.helpMenu = self.menuBar().addMenu("&Help")
+ self.helpMenu.addAction(self.aboutAct)
+ self.helpMenu.addAction(self.aboutQtAct)
+
+ def createSlider(self, changedSignal, setterSlot):
+ slider = QtWidgets.QSlider(QtCore.Qt.Horizontal)
+ slider.setRange(0, 360 * 16)
+ slider.setSingleStep(16)
+ slider.setPageStep(15 * 16)
+ slider.setTickInterval(15 * 16)
+ slider.setTickPosition(QtWidgets.QSlider.TicksRight)
+
+ slider.valueChanged.connect(setterSlot)
+ changedSignal.connect(slider.setValue)
+
+ return slider
+
+ def setPixmap(self, pixmap):
+ self.pixmapLabel.setPixmap(pixmap)
+ size = pixmap.size()
+
+ if size - QtCore.QSize(1, 0) == self.pixmapLabelArea.maximumViewportSize():
+ size -= QtCore.QSize(1, 0)
+
+ self.pixmapLabel.resize(size)
+
+ def getSize(self):
+ text, ok = QtWidgets.QInputDialog.getText(self, "Grabber",
+ "Enter pixmap size:", QtWidgets.QLineEdit.Normal,
+ "%d x %d" % (self.glWidget.width(), self.glWidget.height()))
+
+ if not ok:
+ return QtCore.QSize()
+
+ regExp = QtCore.QRegExp("([0-9]+) *x *([0-9]+)")
+
+ if regExp.exactMatch(text):
+ width = int(regExp.cap(1))
+ height = int(regExp.cap(2))
+ if width > 0 and width < 2048 and height > 0 and height < 2048:
+ return QtCore.QSize(width, height)
+
+ return self.glWidget.size()
+
+
+if __name__ == '__main__':
+
+ app = QtWidgets.QApplication(sys.argv)
+ mainWin = MainWindow()
+ mainWin.show()
+ res = app.exec_()
+ mainWin.glWidget.freeResources()
+ sys.exit(res)
diff --git a/examples/opengl/hellogl.py b/examples/opengl/hellogl.py
new file mode 100755
index 000000000..18857faca
--- /dev/null
+++ b/examples/opengl/hellogl.py
@@ -0,0 +1,288 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/legacy/hellogl example from Qt v5.x"""
+
+import sys
+import math
+from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
+
+try:
+ from OpenGL import GL
+except ImportError:
+ app = QtWidgets.QApplication(sys.argv)
+ messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL hellogl",
+ "PyOpenGL must be installed to run this example.",
+ QtWidgets.QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+
+class Window(QtWidgets.QWidget):
+ def __init__(self, parent=None):
+ QtWidgets.QWidget.__init__(self, parent)
+
+ self.glWidget = GLWidget()
+
+ self.xSlider = self.createSlider(QtCore.SIGNAL("xRotationChanged(int)"),
+ self.glWidget.setXRotation)
+ self.ySlider = self.createSlider(QtCore.SIGNAL("yRotationChanged(int)"),
+ self.glWidget.setYRotation)
+ self.zSlider = self.createSlider(QtCore.SIGNAL("zRotationChanged(int)"),
+ self.glWidget.setZRotation)
+
+ mainLayout = QtWidgets.QHBoxLayout()
+ mainLayout.addWidget(self.glWidget)
+ mainLayout.addWidget(self.xSlider)
+ mainLayout.addWidget(self.ySlider)
+ mainLayout.addWidget(self.zSlider)
+ self.setLayout(mainLayout)
+
+ self.xSlider.setValue(170 * 16)
+ self.ySlider.setValue(160 * 16)
+ self.zSlider.setValue(90 * 16)
+
+ self.setWindowTitle(self.tr("Hello GL"))
+
+ def createSlider(self, changedSignal, setterSlot):
+ slider = QtWidgets.QSlider(QtCore.Qt.Vertical)
+
+ slider.setRange(0, 360 * 16)
+ slider.setSingleStep(16)
+ slider.setPageStep(15 * 16)
+ slider.setTickInterval(15 * 16)
+ slider.setTickPosition(QtWidgets.QSlider.TicksRight)
+
+ self.glWidget.connect(slider, QtCore.SIGNAL("valueChanged(int)"), setterSlot)
+ self.connect(self.glWidget, changedSignal, slider, QtCore.SLOT("setValue(int)"))
+
+ return slider
+
+
+class GLWidget(QtOpenGL.QGLWidget):
+ xRotationChanged = QtCore.Signal(int)
+ yRotationChanged = QtCore.Signal(int)
+ zRotationChanged = QtCore.Signal(int)
+
+ def __init__(self, parent=None):
+ QtOpenGL.QGLWidget.__init__(self, parent)
+
+ self.object = 0
+ self.xRot = 0
+ self.yRot = 0
+ self.zRot = 0
+
+ self.lastPos = QtCore.QPoint()
+
+ self.trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
+ self.trolltechPurple = QtGui.QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)
+
+ def xRotation(self):
+ return self.xRot
+
+ def yRotation(self):
+ return self.yRot
+
+ def zRotation(self):
+ return self.zRot
+
+ def minimumSizeHint(self):
+ return QtCore.QSize(50, 50)
+
+ def sizeHint(self):
+ return QtCore.QSize(400, 400)
+
+ def setXRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.xRot:
+ self.xRot = angle
+ self.emit(QtCore.SIGNAL("xRotationChanged(int)"), angle)
+ self.updateGL()
+
+ def setYRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.yRot:
+ self.yRot = angle
+ self.emit(QtCore.SIGNAL("yRotationChanged(int)"), angle)
+ self.updateGL()
+
+ def setZRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.zRot:
+ self.zRot = angle
+ self.emit(QtCore.SIGNAL("zRotationChanged(int)"), angle)
+ self.updateGL()
+
+ def initializeGL(self):
+ self.qglClearColor(self.trolltechPurple.darker())
+ self.object = self.makeObject()
+ GL.glShadeModel(GL.GL_FLAT)
+ GL.glEnable(GL.GL_DEPTH_TEST)
+ GL.glEnable(GL.GL_CULL_FACE)
+
+ def paintGL(self):
+ GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
+ GL.glLoadIdentity()
+ GL.glTranslated(0.0, 0.0, -10.0)
+ GL.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
+ GL.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
+ GL.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
+ GL.glCallList(self.object)
+
+ def resizeGL(self, width, height):
+ side = min(width, height)
+ GL.glViewport(int((width - side) / 2),int((height - side) / 2), side, side)
+
+ GL.glMatrixMode(GL.GL_PROJECTION)
+ GL.glLoadIdentity()
+ GL.glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0)
+ GL.glMatrixMode(GL.GL_MODELVIEW)
+
+ def mousePressEvent(self, event):
+ self.lastPos = QtCore.QPoint(event.pos())
+
+ def mouseMoveEvent(self, event):
+ dx = event.x() - self.lastPos.x()
+ dy = event.y() - self.lastPos.y()
+
+ if event.buttons() & QtCore.Qt.LeftButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setYRotation(self.yRot + 8 * dx)
+ elif event.buttons() & QtCore.Qt.RightButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setZRotation(self.zRot + 8 * dx)
+
+ self.lastPos = QtCore.QPoint(event.pos())
+
+ def makeObject(self):
+ genList = GL.glGenLists(1)
+ GL.glNewList(genList, GL.GL_COMPILE)
+
+ GL.glBegin(GL.GL_QUADS)
+
+ x1 = +0.06
+ y1 = -0.14
+ x2 = +0.14
+ y2 = -0.06
+ x3 = +0.08
+ y3 = +0.00
+ x4 = +0.30
+ y4 = +0.22
+
+ self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
+ self.quad(x3, y3, x4, y4, y4, x4, y3, x3)
+
+ self.extrude(x1, y1, x2, y2)
+ self.extrude(x2, y2, y2, x2)
+ self.extrude(y2, x2, y1, x1)
+ self.extrude(y1, x1, x1, y1)
+ self.extrude(x3, y3, x4, y4)
+ self.extrude(x4, y4, y4, x4)
+ self.extrude(y4, x4, y3, x3)
+
+ Pi = 3.14159265358979323846
+ NumSectors = 200
+
+ for i in range(NumSectors):
+ angle1 = (i * 2 * Pi) / NumSectors
+ x5 = 0.30 * math.sin(angle1)
+ y5 = 0.30 * math.cos(angle1)
+ x6 = 0.20 * math.sin(angle1)
+ y6 = 0.20 * math.cos(angle1)
+
+ angle2 = ((i + 1) * 2 * Pi) / NumSectors
+ x7 = 0.20 * math.sin(angle2)
+ y7 = 0.20 * math.cos(angle2)
+ x8 = 0.30 * math.sin(angle2)
+ y8 = 0.30 * math.cos(angle2)
+
+ self.quad(x5, y5, x6, y6, x7, y7, x8, y8)
+
+ self.extrude(x6, y6, x7, y7)
+ self.extrude(x8, y8, x5, y5)
+
+ GL.glEnd()
+ GL.glEndList()
+
+ return genList
+
+ def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
+ self.qglColor(self.trolltechGreen)
+
+ GL.glVertex3d(x1, y1, +0.05)
+ GL.glVertex3d(x2, y2, +0.05)
+ GL.glVertex3d(x3, y3, +0.05)
+ GL.glVertex3d(x4, y4, +0.05)
+
+ GL.glVertex3d(x4, y4, -0.05)
+ GL.glVertex3d(x3, y3, -0.05)
+ GL.glVertex3d(x2, y2, -0.05)
+ GL.glVertex3d(x1, y1, -0.05)
+
+ def extrude(self, x1, y1, x2, y2):
+ self.qglColor(self.trolltechGreen.darker(250 + int(100 * x1)))
+
+ GL.glVertex3d(x1, y1, -0.05)
+ GL.glVertex3d(x2, y2, -0.05)
+ GL.glVertex3d(x2, y2, +0.05)
+ GL.glVertex3d(x1, y1, +0.05)
+
+ def normalizeAngle(self, angle):
+ while angle < 0:
+ angle += 360 * 16
+ while angle > 360 * 16:
+ angle -= 360 * 16
+ return angle
+
+ def freeResources(self):
+ self.makeCurrent()
+ GL.glDeleteLists(self.object, 1)
+
+if __name__ == '__main__':
+ app = QtWidgets.QApplication(sys.argv)
+ window = Window()
+ window.show()
+ res = app.exec_()
+ window.glWidget.freeResources()
+ sys.exit(res)
diff --git a/examples/opengl/hellogl2.py b/examples/opengl/hellogl2.py
new file mode 100755
index 000000000..29a68269e
--- /dev/null
+++ b/examples/opengl/hellogl2.py
@@ -0,0 +1,473 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/hellogl2 example from Qt v5.x"""
+
+import sys
+import math
+import numpy
+import ctypes
+from PySide2.QtCore import QCoreApplication, Signal, SIGNAL, SLOT, Qt, QSize, QPoint
+from PySide2.QtGui import (QVector3D, QOpenGLFunctions, QOpenGLVertexArrayObject, QOpenGLBuffer,
+ QOpenGLShaderProgram, QMatrix4x4, QOpenGLShader, QOpenGLContext, QSurfaceFormat)
+from PySide2.QtWidgets import (QApplication, QWidget, QMessageBox, QHBoxLayout, QSlider,
+ QOpenGLWidget)
+from PySide2.shiboken2 import VoidPtr
+
+try:
+ from OpenGL import GL
+except ImportError:
+ app = QApplication(sys.argv)
+ messageBox = QMessageBox(QMessageBox.Critical, "OpenGL hellogl",
+ "PyOpenGL must be installed to run this example.",
+ QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+
+class Window(QWidget):
+ def __init__(self, parent=None):
+ QWidget.__init__(self, parent)
+
+ self.glWidget = GLWidget()
+
+ self.xSlider = self.createSlider(SIGNAL("xRotationChanged(int)"),
+ self.glWidget.setXRotation)
+ self.ySlider = self.createSlider(SIGNAL("yRotationChanged(int)"),
+ self.glWidget.setYRotation)
+ self.zSlider = self.createSlider(SIGNAL("zRotationChanged(int)"),
+ self.glWidget.setZRotation)
+
+ mainLayout = QHBoxLayout()
+ mainLayout.addWidget(self.glWidget)
+ mainLayout.addWidget(self.xSlider)
+ mainLayout.addWidget(self.ySlider)
+ mainLayout.addWidget(self.zSlider)
+ self.setLayout(mainLayout)
+
+ self.xSlider.setValue(15 * 16)
+ self.ySlider.setValue(345 * 16)
+ self.zSlider.setValue(0 * 16)
+
+ self.setWindowTitle(self.tr("Hello GL"))
+
+ def createSlider(self, changedSignal, setterSlot):
+ slider = QSlider(Qt.Vertical)
+
+ slider.setRange(0, 360 * 16)
+ slider.setSingleStep(16)
+ slider.setPageStep(15 * 16)
+ slider.setTickInterval(15 * 16)
+ slider.setTickPosition(QSlider.TicksRight)
+
+ self.glWidget.connect(slider, SIGNAL("valueChanged(int)"), setterSlot)
+ self.connect(self.glWidget, changedSignal, slider, SLOT("setValue(int)"))
+
+ return slider
+
+ def keyPressEvent(self, event):
+ if event.key() == Qt.Key_Escape:
+ self.close()
+ else:
+ super(Window, self).keyPressEvent(event)
+
+class Logo():
+ def __init__(self):
+ self.m_count = 0
+ self.i = 0
+ self.m_data = numpy.empty(2500 * 6, dtype = ctypes.c_float)
+
+ x1 = +0.06
+ y1 = -0.14
+ x2 = +0.14
+ y2 = -0.06
+ x3 = +0.08
+ y3 = +0.00
+ x4 = +0.30
+ y4 = +0.22
+
+ self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
+ self.quad(x3, y3, x4, y4, y4, x4, y3, x3)
+
+ self.extrude(x1, y1, x2, y2)
+ self.extrude(x2, y2, y2, x2)
+ self.extrude(y2, x2, y1, x1)
+ self.extrude(y1, x1, x1, y1)
+ self.extrude(x3, y3, x4, y4)
+ self.extrude(x4, y4, y4, x4)
+ self.extrude(y4, x4, y3, x3)
+
+ Pi = 3.14159265358979323846
+ NumSectors = 100
+
+ for i in range(NumSectors):
+ angle = (i * 2 * Pi) / NumSectors
+ x5 = 0.30 * math.sin(angle)
+ y5 = 0.30 * math.cos(angle)
+ x6 = 0.20 * math.sin(angle)
+ y6 = 0.20 * math.cos(angle)
+
+ angle = ((i + 1) * 2 * Pi) / NumSectors
+ x7 = 0.20 * math.sin(angle)
+ y7 = 0.20 * math.cos(angle)
+ x8 = 0.30 * math.sin(angle)
+ y8 = 0.30 * math.cos(angle)
+
+ self.quad(x5, y5, x6, y6, x7, y7, x8, y8)
+
+ self.extrude(x6, y6, x7, y7)
+ self.extrude(x8, y8, x5, y5)
+
+ def constData(self):
+ return self.m_data.tobytes()
+
+ def count(self):
+ return self.m_count
+
+ def vertexCount(self):
+ return self.m_count / 6
+
+ def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
+ n = QVector3D.normal(QVector3D(x4 - x1, y4 - y1, 0), QVector3D(x2 - x1, y2 - y1, 0))
+
+ self.add(QVector3D(x1, y1, -0.05), n)
+ self.add(QVector3D(x4, y4, -0.05), n)
+ self.add(QVector3D(x2, y2, -0.05), n)
+
+ self.add(QVector3D(x3, y3, -0.05), n)
+ self.add(QVector3D(x2, y2, -0.05), n)
+ self.add(QVector3D(x4, y4, -0.05), n)
+
+ n = QVector3D.normal(QVector3D(x1 - x4, y1 - y4, 0), QVector3D(x2 - x4, y2 - y4, 0))
+
+ self.add(QVector3D(x4, y4, 0.05), n)
+ self.add(QVector3D(x1, y1, 0.05), n)
+ self.add(QVector3D(x2, y2, 0.05), n)
+
+ self.add(QVector3D(x2, y2, 0.05), n)
+ self.add(QVector3D(x3, y3, 0.05), n)
+ self.add(QVector3D(x4, y4, 0.05), n)
+
+ def extrude(self, x1, y1, x2, y2):
+ n = QVector3D.normal(QVector3D(0, 0, -0.1), QVector3D(x2 - x1, y2 - y1, 0))
+
+ self.add(QVector3D(x1, y1, 0.05), n)
+ self.add(QVector3D(x1, y1, -0.05), n)
+ self.add(QVector3D(x2, y2, 0.05), n)
+
+ self.add(QVector3D(x2, y2, -0.05), n)
+ self.add(QVector3D(x2, y2, 0.05), n)
+ self.add(QVector3D(x1, y1, -0.05), n)
+
+ def add(self, v, n):
+ self.m_data[self.i] = v.x()
+ self.i += 1
+ self.m_data[self.i] = v.y()
+ self.i += 1
+ self.m_data[self.i] = v.z()
+ self.i += 1
+ self.m_data[self.i] = n.x()
+ self.i += 1
+ self.m_data[self.i] = n.y()
+ self.i += 1
+ self.m_data[self.i] = n.z()
+ self.i += 1
+ self.m_count += 6
+
+class GLWidget(QOpenGLWidget, QOpenGLFunctions):
+ xRotationChanged = Signal(int)
+ yRotationChanged = Signal(int)
+ zRotationChanged = Signal(int)
+
+ def __init__(self, parent=None):
+ QOpenGLWidget.__init__(self, parent)
+ QOpenGLFunctions.__init__(self)
+
+ self.core = "--coreprofile" in QCoreApplication.arguments()
+ self.xRot = 0
+ self.yRot = 0
+ self.zRot = 0
+ self.lastPos = 0
+ self.logo = Logo()
+ self.vao = QOpenGLVertexArrayObject()
+ self.logoVbo = QOpenGLBuffer()
+ self.program = QOpenGLShaderProgram()
+ self.projMatrixLoc = 0
+ self.mvMatrixLoc = 0
+ self.normalMatrixLoc = 0
+ self.lightPosLoc = 0
+ self.proj = QMatrix4x4()
+ self.camera = QMatrix4x4()
+ self.world = QMatrix4x4()
+ self.transparent = "--transparent" in QCoreApplication.arguments()
+ if self.transparent:
+ fmt = self.format()
+ fmt.setAlphaBufferSize(8)
+ self.setFormat(fmt)
+
+ def xRotation(self):
+ return self.xRot
+
+ def yRotation(self):
+ return self.yRot
+
+ def zRotation(self):
+ return self.zRot
+
+ def minimumSizeHint(self):
+ return QSize(50, 50)
+
+ def sizeHint(self):
+ return QSize(400, 400)
+
+ def normalizeAngle(self, angle):
+ while angle < 0:
+ angle += 360 * 16
+ while angle > 360 * 16:
+ angle -= 360 * 16
+ return angle
+
+ def setXRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.xRot:
+ self.xRot = angle
+ self.emit(SIGNAL("xRotationChanged(int)"), angle)
+ self.update()
+
+ def setYRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.yRot:
+ self.yRot = angle
+ self.emit(SIGNAL("yRotationChanged(int)"), angle)
+ self.update()
+
+ def setZRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.zRot:
+ self.zRot = angle
+ self.emit(SIGNAL("zRotationChanged(int)"), angle)
+ self.update()
+
+ def cleanup(self):
+ self.makeCurrent()
+ self.logoVbo.destroy()
+ del self.program
+ self.program = None
+ self.doneCurrent()
+
+ def vertexShaderSourceCore(self):
+ return """#version 150
+ in vec4 vertex;
+ in vec3 normal;
+ out vec3 vert;
+ out vec3 vertNormal;
+ uniform mat4 projMatrix;
+ uniform mat4 mvMatrix;
+ uniform mat3 normalMatrix;
+ void main() {
+ vert = vertex.xyz;
+ vertNormal = normalMatrix * normal;
+ gl_Position = projMatrix * mvMatrix * vertex;
+ }"""
+
+ def fragmentShaderSourceCore(self):
+ return """#version 150
+ in highp vec3 vert;
+ in highp vec3 vertNormal;
+ out highp vec4 fragColor;
+ uniform highp vec3 lightPos;
+ void main() {
+ highp vec3 L = normalize(lightPos - vert);
+ highp float NL = max(dot(normalize(vertNormal), L), 0.0);
+ highp vec3 color = vec3(0.39, 1.0, 0.0);
+ highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);
+ fragColor = vec4(col, 1.0);
+ }"""
+
+
+ def vertexShaderSource(self):
+ return """attribute vec4 vertex;
+ attribute vec3 normal;
+ varying vec3 vert;
+ varying vec3 vertNormal;
+ uniform mat4 projMatrix;
+ uniform mat4 mvMatrix;
+ uniform mat3 normalMatrix;
+ void main() {
+ vert = vertex.xyz;
+ vertNormal = normalMatrix * normal;
+ gl_Position = projMatrix * mvMatrix * vertex;
+ }"""
+
+ def fragmentShaderSource(self):
+ return """varying highp vec3 vert;
+ varying highp vec3 vertNormal;
+ uniform highp vec3 lightPos;
+ void main() {
+ highp vec3 L = normalize(lightPos - vert);
+ highp float NL = max(dot(normalize(vertNormal), L), 0.0);
+ highp vec3 color = vec3(0.39, 1.0, 0.0);
+ highp vec3 col = clamp(color * 0.2 + color * 0.8 * NL, 0.0, 1.0);
+ gl_FragColor = vec4(col, 1.0);
+ }"""
+
+ def initializeGL(self):
+ self.context().aboutToBeDestroyed.connect(self.cleanup)
+ self.initializeOpenGLFunctions()
+ self.glClearColor(0, 0, 0, 1)
+
+ self.program = QOpenGLShaderProgram()
+
+ if self.core:
+ self.vertexShader = self.vertexShaderSourceCore()
+ self.fragmentShader = self.fragmentShaderSourceCore()
+ else:
+ self.vertexShader = self.vertexShaderSource()
+ self.fragmentShader = self.fragmentShaderSource()
+
+ self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, self.vertexShader)
+ self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, self.fragmentShader)
+ self.program.bindAttributeLocation("vertex", 0)
+ self.program.bindAttributeLocation("normal", 1)
+ self.program.link()
+
+ self.program.bind()
+ self.projMatrixLoc = self.program.uniformLocation("projMatrix")
+ self.mvMatrixLoc = self.program.uniformLocation("mvMatrix")
+ self.normalMatrixLoc = self.program.uniformLocation("normalMatrix")
+ self.lightPosLoc = self.program.uniformLocation("lightPos")
+
+ self.vao.create()
+ vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
+
+ self.logoVbo.create()
+ self.logoVbo.bind()
+ float_size = ctypes.sizeof(ctypes.c_float)
+ self.logoVbo.allocate(self.logo.constData(), self.logo.count() * float_size)
+
+ self.setupVertexAttribs()
+
+ self.camera.setToIdentity()
+ self.camera.translate(0, 0, -1)
+
+ self.program.setUniformValue(self.lightPosLoc, QVector3D(0, 0, 70))
+ self.program.release()
+ vaoBinder = None
+
+ def setupVertexAttribs(self):
+ self.logoVbo.bind()
+ f = QOpenGLContext.currentContext().functions()
+ f.glEnableVertexAttribArray(0)
+ f.glEnableVertexAttribArray(1)
+ float_size = ctypes.sizeof(ctypes.c_float)
+
+ null = VoidPtr(0)
+ pointer = VoidPtr(3 * float_size)
+ f.glVertexAttribPointer(0, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, null)
+ f.glVertexAttribPointer(1, 3, int(GL.GL_FLOAT), int(GL.GL_FALSE), 6 * float_size, pointer)
+ self.logoVbo.release()
+
+ def paintGL(self):
+ self.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
+ self.glEnable(GL.GL_DEPTH_TEST)
+ self.glEnable(GL.GL_CULL_FACE)
+
+ self.world.setToIdentity()
+ self.world.rotate(180 - (self.xRot / 16), 1, 0, 0)
+ self.world.rotate(self.yRot / 16, 0, 1, 0)
+ self.world.rotate(self.zRot / 16, 0, 0, 1)
+
+ vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao)
+ self.program.bind()
+ self.program.setUniformValue(self.projMatrixLoc, self.proj)
+ self.program.setUniformValue(self.mvMatrixLoc, self.camera * self.world)
+ normalMatrix = self.world.normalMatrix()
+ self.program.setUniformValue(self.normalMatrixLoc, normalMatrix)
+
+ self.glDrawArrays(GL.GL_TRIANGLES, 0, self.logo.vertexCount())
+ self.program.release()
+ vaoBinder = None
+
+ def resizeGL(self, width, height):
+ self.proj.setToIdentity()
+ self.proj.perspective(45, width / height, 0.01, 100)
+
+ def mousePressEvent(self, event):
+ self.lastPos = QPoint(event.pos())
+
+ def mouseMoveEvent(self, event):
+ dx = event.x() - self.lastPos.x()
+ dy = event.y() - self.lastPos.y()
+
+ if event.buttons() & Qt.LeftButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setYRotation(self.yRot + 8 * dx)
+ elif event.buttons() & Qt.RightButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setZRotation(self.zRot + 8 * dx)
+
+ self.lastPos = QPoint(event.pos())
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ fmt = QSurfaceFormat()
+ fmt.setDepthBufferSize(24)
+ if "--multisample" in QCoreApplication.arguments():
+ fmt.setSamples(4)
+ if "--coreprofile" in QCoreApplication.arguments():
+ fmt.setVersion(3, 2)
+ fmt.setProfile(QSurfaceFormat.CoreProfile)
+ QSurfaceFormat.setDefaultFormat(fmt)
+
+ mainWindow = Window()
+ if "--transparent" in QCoreApplication.arguments():
+ mainWindow.setAttribute(Qt.WA_TranslucentBackground)
+ mainWindow.setAttribute(Qt.WA_NoSystemBackground, False)
+
+ mainWindow.resize(mainWindow.sizeHint())
+ mainWindow.show()
+
+ res = app.exec_()
+ sys.exit(res)
diff --git a/examples/opengl/overpainting.py b/examples/opengl/overpainting.py
new file mode 100755
index 000000000..9285eaa9b
--- /dev/null
+++ b/examples/opengl/overpainting.py
@@ -0,0 +1,386 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/legacy/overpainting example from Qt v5.x"""
+
+import sys
+import math, random
+from PySide2.QtCore import *
+from PySide2.QtGui import *
+from PySide2.QtWidgets import *
+from PySide2.QtOpenGL import *
+
+try:
+ from OpenGL.GL import *
+except ImportError:
+ app = QApplication(sys.argv)
+ messageBox = QMessageBox(QMessageBox.Critical, "OpenGL overpainting",
+ "PyOpenGL must be installed to run this example.",
+ QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+
+class Bubble:
+ def __init__(self, position, radius, velocity):
+ self.position = position
+ self.vel = velocity
+ self.radius = radius
+ self.innerColor = self.randomColor()
+ self.outerColor = self.randomColor()
+ self.updateBrush()
+
+ def updateBrush(self):
+ gradient = QRadialGradient(QPointF(self.radius, self.radius), self.radius,
+ QPointF(self.radius*0.5, self.radius*0.5))
+
+ gradient.setColorAt(0, QColor(255, 255, 255, 255))
+ gradient.setColorAt(0.25, self.innerColor)
+ gradient.setColorAt(1, self.outerColor)
+ self.brush = QBrush(gradient)
+
+ def drawBubble(self, painter):
+ painter.save()
+ painter.translate(self.position.x() - self.radius,
+ self.position.y() - self.radius)
+ painter.setBrush(self.brush)
+ painter.drawEllipse(0, 0, int(2*self.radius), int(2*self.radius))
+ painter.restore()
+
+ def randomColor(self):
+ red = random.randrange(205, 256)
+ green = random.randrange(205, 256)
+ blue = random.randrange(205, 256)
+ alpha = random.randrange(91, 192)
+
+ return QColor(red, green, blue, alpha)
+
+ def move(self, bbox):
+ self.position += self.vel
+ leftOverflow = self.position.x() - self.radius - bbox.left()
+ rightOverflow = self.position.x() + self.radius - bbox.right()
+ topOverflow = self.position.y() - self.radius - bbox.top()
+ bottomOverflow = self.position.y() + self.radius - bbox.bottom()
+
+ if leftOverflow < 0.0:
+ self.position.setX(self.position.x() - 2 * leftOverflow)
+ self.vel.setX(-self.vel.x())
+ elif rightOverflow > 0.0:
+ self.position.setX(self.position.x() - 2 * rightOverflow)
+ self.vel.setX(-self.vel.x())
+
+ if topOverflow < 0.0:
+ self.position.setY(self.position.y() - 2 * topOverflow)
+ self.vel.setY(-self.vel.y())
+ elif bottomOverflow > 0.0:
+ self.position.setY(self.position.y() - 2 * bottomOverflow)
+ self.vel.setY(-self.vel.y())
+
+ def rect(self):
+ return QRectF(self.position.x() - self.radius,
+ self.position.y() - self.radius,
+ 2 * self.radius, 2 * self.radius)
+
+
+class GLWidget(QGLWidget):
+ def __init__(self, parent = None):
+ QGLWidget.__init__(self, QGLFormat(QGL.SampleBuffers), parent)
+
+ midnight = QTime(0, 0, 0)
+ random.seed(midnight.secsTo(QTime.currentTime()))
+
+ self.object = 0
+ self.xRot = 0
+ self.yRot = 0
+ self.zRot = 0
+ self.image = QImage()
+ self.bubbles = []
+ self.lastPos = QPoint()
+
+ self.trolltechGreen = QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
+ self.trolltechPurple = QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)
+
+ self.animationTimer = QTimer()
+ self.animationTimer.setSingleShot(False)
+ self.connect(self.animationTimer, SIGNAL("timeout()"), self.animate)
+ self.animationTimer.start(25)
+
+ self.setAttribute(Qt.WA_NoSystemBackground)
+ self.setMinimumSize(200, 200)
+ self.setWindowTitle(self.tr("Overpainting a Scene"))
+
+ def freeResources(self):
+ self.makeCurrent()
+ glDeleteLists(self.object, 1)
+
+ def setXRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.xRot:
+ self.xRot = angle
+ self.emit(SIGNAL("xRotationChanged(int)"), angle)
+
+ def setYRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.yRot:
+ self.yRot = angle
+ self.emit(SIGNAL("yRotationChanged(int)"), angle)
+
+ def setZRotation(self, angle):
+ angle = self.normalizeAngle(angle)
+ if angle != self.zRot:
+ self.zRot = angle
+ self.emit(SIGNAL("zRotationChanged(int)"), angle)
+
+ def initializeGL(self):
+ self.object = self.makeObject()
+
+ def mousePressEvent(self, event):
+ self.lastPos = QPoint(event.pos())
+
+ def mouseMoveEvent(self, event):
+ dx = event.x() - self.lastPos.x()
+ dy = event.y() - self.lastPos.y()
+
+ if event.buttons() & Qt.LeftButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setYRotation(self.yRot + 8 * dx)
+ elif event.buttons() & Qt.RightButton:
+ self.setXRotation(self.xRot + 8 * dy)
+ self.setZRotation(self.zRot + 8 * dx)
+
+ self.lastPos = QPoint(event.pos())
+
+ def paintEvent(self, event):
+ painter = QPainter()
+ painter.begin(self)
+ painter.setRenderHint(QPainter.Antialiasing)
+
+ glPushAttrib(GL_ALL_ATTRIB_BITS)
+ glMatrixMode(GL_PROJECTION)
+ glPushMatrix()
+ glMatrixMode(GL_MODELVIEW)
+ glPushMatrix()
+
+ self.qglClearColor(self.trolltechPurple.darker())
+ glShadeModel(GL_SMOOTH)
+ glEnable(GL_DEPTH_TEST)
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_LIGHTING)
+ glEnable(GL_LIGHT0)
+ lightPosition = ( 0.5, 5.0, 7.0, 1.0 )
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPosition)
+
+ self.resizeGL(self.width(), self.height())
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+ glLoadIdentity()
+ glTranslated(0.0, 0.0, -10.0)
+ glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
+ glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
+ glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
+ glCallList(self.object)
+
+ glPopAttrib()
+ glMatrixMode(GL_MODELVIEW)
+ glPopMatrix()
+ glMatrixMode(GL_PROJECTION)
+ glPopMatrix()
+
+ glDisable(GL_CULL_FACE) ### not required if begin() also does it
+
+ for bubble in self.bubbles:
+ if bubble.rect().intersects(QRectF(event.rect())):
+ bubble.drawBubble(painter)
+
+ painter.drawImage((self.width() - self.image.width())/2, 0, self.image)
+ painter.end()
+
+ def resizeGL(self, width, height):
+ side = min(width, height)
+ glViewport(int((width - side) / 2), int((height - side) / 2), side, side)
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+ glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
+ glMatrixMode(GL_MODELVIEW)
+
+ self.formatInstructions(width, height)
+
+ def showEvent(self, event):
+ self.createBubbles(20 - len(self.bubbles))
+
+ def sizeHint(self):
+ return QSize(400, 400)
+
+ def makeObject(self):
+ list = glGenLists(1)
+ glNewList(list, GL_COMPILE)
+
+ glEnable(GL_NORMALIZE)
+ glBegin(GL_QUADS)
+
+ logoDiffuseColor = (self.trolltechGreen.red()/255.0,
+ self.trolltechGreen.green()/255.0,
+ self.trolltechGreen.blue()/255.0, 1.0)
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, logoDiffuseColor)
+
+ x1 = +0.06
+ y1 = -0.14
+ x2 = +0.14
+ y2 = -0.06
+ x3 = +0.08
+ y3 = +0.00
+ x4 = +0.30
+ y4 = +0.22
+
+ self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
+ self.quad(x3, y3, x4, y4, y4, x4, y3, x3)
+
+ self.extrude(x1, y1, x2, y2)
+ self.extrude(x2, y2, y2, x2)
+ self.extrude(y2, x2, y1, x1)
+ self.extrude(y1, x1, x1, y1)
+ self.extrude(x3, y3, x4, y4)
+ self.extrude(x4, y4, y4, x4)
+ self.extrude(y4, x4, y3, x3)
+
+ NumSectors = 200
+
+ for i in range(NumSectors):
+ angle1 = (i * 2 * math.pi) / NumSectors
+ x5 = 0.30 * math.sin(angle1)
+ y5 = 0.30 * math.cos(angle1)
+ x6 = 0.20 * math.sin(angle1)
+ y6 = 0.20 * math.cos(angle1)
+
+ angle2 = ((i + 1) * 2 * math.pi) / NumSectors
+ x7 = 0.20 * math.sin(angle2)
+ y7 = 0.20 * math.cos(angle2)
+ x8 = 0.30 * math.sin(angle2)
+ y8 = 0.30 * math.cos(angle2)
+
+ self.quad(x5, y5, x6, y6, x7, y7, x8, y8)
+
+ self.extrude(x6, y6, x7, y7)
+ self.extrude(x8, y8, x5, y5)
+
+ glEnd()
+
+ glEndList()
+ return list
+
+ def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
+ glNormal3d(0.0, 0.0, -1.0)
+ glVertex3d(x1, y1, -0.05)
+ glVertex3d(x2, y2, -0.05)
+ glVertex3d(x3, y3, -0.05)
+ glVertex3d(x4, y4, -0.05)
+
+ glNormal3d(0.0, 0.0, 1.0)
+ glVertex3d(x4, y4, +0.05)
+ glVertex3d(x3, y3, +0.05)
+ glVertex3d(x2, y2, +0.05)
+ glVertex3d(x1, y1, +0.05)
+
+ def extrude(self, x1, y1, x2, y2):
+ self.qglColor(self.trolltechGreen.darker(250 + int(100 * x1)))
+
+ glNormal3d((x1 + x2)/2.0, (y1 + y2)/2.0, 0.0)
+ glVertex3d(x1, y1, +0.05)
+ glVertex3d(x2, y2, +0.05)
+ glVertex3d(x2, y2, -0.05)
+ glVertex3d(x1, y1, -0.05)
+
+ def normalizeAngle(self, angle):
+ while angle < 0:
+ angle += 360 * 16
+ while angle > 360 * 16:
+ angle -= 360 * 16
+ return angle
+
+ def createBubbles(self, number):
+ for i in range(number):
+ position = QPointF(self.width()*(0.1 + 0.8*random.random()),
+ self.height()*(0.1 + 0.8*random.random()))
+ radius = min(self.width(), self.height())*(0.0125 + 0.0875*random.random())
+ velocity = QPointF(self.width()*0.0125*(-0.5 + random.random()),
+ self.height()*0.0125*(-0.5 + random.random()))
+
+ self.bubbles.append(Bubble(position, radius, velocity))
+
+ def animate(self):
+ for bubble in self.bubbles:
+ self.update(bubble.rect().toRect())
+ bubble.move(self.rect())
+ self.update(bubble.rect().toRect())
+
+ def formatInstructions(self, width, height):
+ text = self.tr("Click and drag with the left mouse button "
+ "to rotate the Qt logo.")
+ metrics = QFontMetrics(self.font())
+ border = max(4, metrics.leading())
+
+ rect = metrics.boundingRect(0, 0, width - 2*border, int(height*0.125),
+ Qt.AlignCenter | Qt.TextWordWrap, text)
+ self.image = QImage(width, rect.height() + 2*border,
+ QImage.Format_ARGB32_Premultiplied)
+ self.image.fill(qRgba(0, 0, 0, 127))
+
+ painter = QPainter()
+ painter.begin(self.image)
+ painter.setRenderHint(QPainter.TextAntialiasing)
+ painter.setPen(Qt.white)
+ painter.drawText((width - rect.width())/2, border,
+ rect.width(), rect.height(),
+ Qt.AlignCenter | Qt.TextWordWrap, text)
+ painter.end()
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ window = GLWidget()
+ window.show()
+ res = app.exec_()
+ window.freeResources()
+ sys.exit(res)
diff --git a/examples/opengl/samplebuffers.py b/examples/opengl/samplebuffers.py
new file mode 100755
index 000000000..eabcdd313
--- /dev/null
+++ b/examples/opengl/samplebuffers.py
@@ -0,0 +1,193 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/legacy/samplebuffers example from Qt v5.x"""
+
+import sys
+import math
+from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
+
+try:
+ from OpenGL import GL
+except ImportError:
+ app = QtWidgets.QApplication(sys.argv)
+ messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL samplebuffers",
+ "PyOpenGL must be installed to run this example.",
+ QtWidgets.QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+
+class GLWidget(QtOpenGL.QGLWidget):
+ GL_MULTISAMPLE = 0x809D
+ rot = 0.0
+
+ def __init__(self, parent=None):
+ QtOpenGL.QGLWidget.__init__(self, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers), parent)
+
+ self.list_ = []
+
+ self.startTimer(40)
+ self.setWindowTitle(self.tr("Sample Buffers"))
+
+ def initializeGL(self):
+ GL.glMatrixMode(GL.GL_PROJECTION)
+ GL.glLoadIdentity()
+ GL.glOrtho( -.5, .5, .5, -.5, -1000, 1000)
+ GL.glMatrixMode(GL.GL_MODELVIEW)
+ GL.glLoadIdentity()
+ GL.glClearColor(1.0, 1.0, 1.0, 1.0)
+
+ self.makeObject()
+
+ def resizeGL(self, w, h):
+ GL.glViewport(0, 0, w, h)
+
+ def paintGL(self):
+ GL.glClear(GL.GL_COLOR_BUFFER_BIT)
+
+ GL.glMatrixMode(GL.GL_MODELVIEW)
+ GL.glPushMatrix()
+ GL.glEnable(GLWidget.GL_MULTISAMPLE)
+ GL.glTranslatef( -0.25, -0.10, 0.0)
+ GL.glScalef(0.75, 1.15, 0.0)
+ GL.glRotatef(GLWidget.rot, 0.0, 0.0, 1.0)
+ GL.glCallList(self.list_)
+ GL.glPopMatrix()
+
+ GL.glPushMatrix()
+ GL.glDisable(GLWidget.GL_MULTISAMPLE)
+ GL.glTranslatef(0.25, -0.10, 0.0)
+ GL.glScalef(0.75, 1.15, 0.0)
+ GL.glRotatef(GLWidget.rot, 0.0, 0.0, 1.0)
+ GL.glCallList(self.list_)
+ GL.glPopMatrix()
+
+ GLWidget.rot += 0.2
+
+ self.qglColor(QtCore.Qt.black)
+ self.renderText(-0.35, 0.4, 0.0, "Multisampling enabled")
+ self.renderText(0.15, 0.4, 0.0, "Multisampling disabled")
+
+ def timerEvent(self, event):
+ self.update()
+
+ def makeObject(self):
+ trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
+ Pi = 3.14159265358979323846
+ NumSectors = 15
+ x1 = +0.06
+ y1 = -0.14
+ x2 = +0.14
+ y2 = -0.06
+ x3 = +0.08
+ y3 = +0.00
+ x4 = +0.30
+ y4 = +0.22
+
+ self.list_ = GL.glGenLists(1)
+ GL.glNewList(self.list_, GL.GL_COMPILE)
+
+ for i in range(NumSectors):
+ angle1 = float((i * 2 * Pi) / NumSectors)
+ x5 = 0.30 * math.sin(angle1)
+ y5 = 0.30 * math.cos(angle1)
+ x6 = 0.20 * math.sin(angle1)
+ y6 = 0.20 * math.cos(angle1)
+
+ angle2 = float(((i + 1) * 2 * Pi) / NumSectors)
+ x7 = 0.20 * math.sin(angle2)
+ y7 = 0.20 * math.cos(angle2)
+ x8 = 0.30 * math.sin(angle2)
+ y8 = 0.30 * math.cos(angle2)
+
+ self.qglColor(trolltechGreen)
+ self.quad(GL.GL_QUADS, x5, y5, x6, y6, x7, y7, x8, y8)
+ self.qglColor(QtCore.Qt.black)
+ self.quad(GL.GL_LINE_LOOP, x5, y5, x6, y6, x7, y7, x8, y8)
+
+ self.qglColor(trolltechGreen)
+ self.quad(GL.GL_QUADS, x1, y1, x2, y2, y2, x2, y1, x1)
+ self.quad(GL.GL_QUADS, x3, y3, x4, y4, y4, x4, y3, x3)
+
+ self.qglColor(QtCore.Qt.black)
+ self.quad(GL.GL_LINE_LOOP, x1, y1, x2, y2, y2, x2, y1, x1)
+ self.quad(GL.GL_LINE_LOOP, x3, y3, x4, y4, y4, x4, y3, x3)
+
+ GL.glEndList()
+
+ def quad(self, primitive, x1, y1, x2, y2, x3, y3, x4, y4):
+ GL.glBegin(primitive)
+
+ GL.glVertex2d(x1, y1)
+ GL.glVertex2d(x2, y2)
+ GL.glVertex2d(x3, y3)
+ GL.glVertex2d(x4, y4)
+
+ GL.glEnd()
+
+ def freeResources(self):
+ self.makeCurrent()
+ GL.glDeleteLists(self.list_, 1)
+
+
+if __name__ == '__main__':
+ app = QtWidgets.QApplication(sys.argv)
+
+ if not QtOpenGL.QGLFormat.hasOpenGL():
+ QMessageBox.information(0, "OpenGL pbuffers",
+ "This system does not support OpenGL.",
+ QMessageBox.Ok)
+ sys.exit(1)
+
+ f = QtOpenGL.QGLFormat.defaultFormat()
+ f.setSampleBuffers(True)
+ QtOpenGL.QGLFormat.setDefaultFormat(f)
+
+ widget = GLWidget()
+ widget.resize(640, 480)
+ widget.show()
+ res = app.exec_()
+ widget.freeResources()
+ sys.exit(res)
diff --git a/examples/opengl/textures/images/side1.png b/examples/opengl/textures/images/side1.png
new file mode 100644
index 000000000..68fd4336d
--- /dev/null
+++ b/examples/opengl/textures/images/side1.png
Binary files differ
diff --git a/examples/opengl/textures/images/side2.png b/examples/opengl/textures/images/side2.png
new file mode 100644
index 000000000..b12d30d49
--- /dev/null
+++ b/examples/opengl/textures/images/side2.png
Binary files differ
diff --git a/examples/opengl/textures/images/side3.png b/examples/opengl/textures/images/side3.png
new file mode 100644
index 000000000..f582ae558
--- /dev/null
+++ b/examples/opengl/textures/images/side3.png
Binary files differ
diff --git a/examples/opengl/textures/images/side4.png b/examples/opengl/textures/images/side4.png
new file mode 100644
index 000000000..19829d2d6
--- /dev/null
+++ b/examples/opengl/textures/images/side4.png
Binary files differ
diff --git a/examples/opengl/textures/images/side5.png b/examples/opengl/textures/images/side5.png
new file mode 100644
index 000000000..3843b1229
--- /dev/null
+++ b/examples/opengl/textures/images/side5.png
Binary files differ
diff --git a/examples/opengl/textures/images/side6.png b/examples/opengl/textures/images/side6.png
new file mode 100644
index 000000000..798a9bb66
--- /dev/null
+++ b/examples/opengl/textures/images/side6.png
Binary files differ
diff --git a/examples/opengl/textures/textures.py b/examples/opengl/textures/textures.py
new file mode 100755
index 000000000..3c91a6024
--- /dev/null
+++ b/examples/opengl/textures/textures.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+############################################################################
+
+"""PySide2 port of the opengl/textures example from Qt v5.x"""
+
+import sys
+from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL
+
+try:
+ from OpenGL.GL import *
+except ImportError:
+ app = QtWidgets.QApplication(sys.argv)
+ messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL textures",
+ "PyOpenGL must be installed to run this example.",
+ QtWidgets.QMessageBox.Close)
+ messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate")
+ messageBox.exec_()
+ sys.exit(1)
+
+import textures_rc
+
+
+class GLWidget(QtOpenGL.QGLWidget):
+ sharedObject = 0
+ refCount = 0
+
+ coords = (
+ ( ( +1, -1, -1 ), ( -1, -1, -1 ), ( -1, +1, -1 ), ( +1, +1, -1 ) ),
+ ( ( +1, +1, -1 ), ( -1, +1, -1 ), ( -1, +1, +1 ), ( +1, +1, +1 ) ),
+ ( ( +1, -1, +1 ), ( +1, -1, -1 ), ( +1, +1, -1 ), ( +1, +1, +1 ) ),
+ ( ( -1, -1, -1 ), ( -1, -1, +1 ), ( -1, +1, +1 ), ( -1, +1, -1 ) ),
+ ( ( +1, -1, +1 ), ( -1, -1, +1 ), ( -1, -1, -1 ), ( +1, -1, -1 ) ),
+ ( ( -1, -1, +1 ), ( +1, -1, +1 ), ( +1, +1, +1 ), ( -1, +1, +1 ) )
+ )
+
+ clicked = QtCore.Signal()
+
+ def __init__(self, parent, shareWidget):
+ QtOpenGL.QGLWidget.__init__(self, parent, shareWidget)
+
+ self.clearColor = QtCore.Qt.black
+ self.xRot = 0
+ self.yRot = 0
+ self.zRot = 0
+ self.clearColor = QtGui.QColor()
+ self.lastPos = QtCore.QPoint()
+
+ def freeGLResources(self):
+ GLWidget.refCount -= 1
+ if GLWidget.refCount == 0:
+ self.makeCurrent()
+ glDeleteLists(self.__class__.sharedObject, 1)
+
+ def minimumSizeHint(self):
+ return QtCore.QSize(50, 50)
+
+ def sizeHint(self):
+ return QtCore.QSize(200, 200)
+
+ def rotateBy(self, xAngle, yAngle, zAngle):
+ self.xRot = (self.xRot + xAngle) % 5760
+ self.yRot = (self.yRot + yAngle) % 5760
+ self.zRot = (self.zRot + zAngle) % 5760
+ self.updateGL()
+
+ def setClearColor(self, color):
+ self.clearColor = color
+ self.updateGL()
+
+ def initializeGL(self):
+ if not GLWidget.sharedObject:
+ self.textures = []
+ for i in range(6):
+ self.textures.append(self.bindTexture(QtGui.QPixmap(":/images/side%d.png" % (i + 1))))
+ GLWidget.sharedObject = self.makeObject()
+ GLWidget.refCount += 1
+
+ glEnable(GL_DEPTH_TEST)
+ glEnable(GL_CULL_FACE)
+ glEnable(GL_TEXTURE_2D)
+
+ def paintGL(self):
+ self.qglClearColor(self.clearColor)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
+ glLoadIdentity()
+ glTranslated(0.0, 0.0, -10.0)
+ glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0)
+ glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0)
+ glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0)
+ glCallList(GLWidget.sharedObject)
+
+ def resizeGL(self, width, height):
+ side = min(width, height)
+ glViewport(int((width - side) / 2), int((height - side) / 2), side, side)
+
+ glMatrixMode(GL_PROJECTION)
+ glLoadIdentity()
+ glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
+ glMatrixMode(GL_MODELVIEW)
+
+ def mousePressEvent(self, event):
+ self.lastPos = QtCore.QPoint(event.pos())
+
+ def mouseMoveEvent(self, event):
+ dx = event.x() - self.lastPos.x()
+ dy = event.y() - self.lastPos.y()
+
+ if event.buttons() & QtCore.Qt.LeftButton:
+ self.rotateBy(8 * dy, 8 * dx, 0)
+ elif event.buttons() & QtCore.Qt.RightButton:
+ self.rotateBy(8 * dy, 0, 8 * dx)
+
+ self.lastPos = QtCore.QPoint(event.pos())
+
+ def mouseReleaseEvent(self, event):
+ self.clicked.emit()
+
+ def makeObject(self):
+ dlist = glGenLists(1)
+ glNewList(dlist, GL_COMPILE)
+
+ for i in range(6):
+ glBindTexture(GL_TEXTURE_2D, self.textures[i])
+
+ glBegin(GL_QUADS)
+ for j in range(4):
+ tx = {False: 0, True: 1}[j == 0 or j == 3]
+ ty = {False: 0, True: 1}[j == 0 or j == 1]
+ glTexCoord2d(tx, ty)
+ glVertex3d(0.2 * GLWidget.coords[i][j][0],
+ 0.2 * GLWidget.coords[i][j][1],
+ 0.2 * GLWidget.coords[i][j][2])
+
+ glEnd()
+
+ glEndList()
+ return dlist
+
+
+class Window(QtWidgets.QWidget):
+ NumRows = 2
+ NumColumns = 3
+
+ def __init__(self, parent=None):
+ QtWidgets.QWidget.__init__(self, parent)
+
+ mainLayout = QtWidgets.QGridLayout()
+ self.glWidgets = []
+
+ for i in range(Window.NumRows):
+ self.glWidgets.append([])
+ for j in range(Window.NumColumns):
+ self.glWidgets[i].append(None)
+
+ for i in range(Window.NumRows):
+ for j in range(Window.NumColumns):
+ clearColor = QtGui.QColor()
+ clearColor.setHsv(((i * Window.NumColumns) + j) * 255
+ / (Window.NumRows * Window.NumColumns - 1),
+ 255, 63)
+
+ self.glWidgets[i][j] = GLWidget(self, self.glWidgets[0][0])
+ self.glWidgets[i][j].setClearColor(clearColor)
+ self.glWidgets[i][j].rotateBy(+42 * 16, +42 * 16, -21 * 16)
+ mainLayout.addWidget(self.glWidgets[i][j], i, j)
+
+ self.glWidgets[i][j].clicked.connect(self.setCurrentGlWidget)
+ QtWidgets.qApp.lastWindowClosed.connect(self.glWidgets[i][j].freeGLResources)
+
+ self.setLayout(mainLayout)
+
+ self.currentGlWidget = self.glWidgets[0][0]
+
+ timer = QtCore.QTimer(self)
+ timer.timeout.connect(self.rotateOneStep)
+ timer.start(20)
+
+ self.setWindowTitle(self.tr("Textures"))
+
+ def setCurrentGlWidget(self):
+ self.currentGlWidget = self.sender()
+
+ def rotateOneStep(self):
+ if self.currentGlWidget:
+ self.currentGlWidget.rotateBy(+2 * 16, +2 * 16, -1 * 16)
+
+
+if __name__ == "__main__":
+ app = QtWidgets.QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/opengl/textures/textures.qrc b/examples/opengl/textures/textures.qrc
new file mode 100644
index 000000000..efa9e9c8d
--- /dev/null
+++ b/examples/opengl/textures/textures.qrc
@@ -0,0 +1,10 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/side1.png</file>
+ <file>images/side2.png</file>
+ <file>images/side3.png</file>
+ <file>images/side4.png</file>
+ <file>images/side5.png</file>
+ <file>images/side6.png</file>
+</qresource>
+</RCC>
diff --git a/examples/opengl/textures/textures_rc.py b/examples/opengl/textures/textures_rc.py
new file mode 100644
index 000000000..2e9faeea7
--- /dev/null
+++ b/examples/opengl/textures/textures_rc.py
@@ -0,0 +1,797 @@
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# Resource object code
+#
+# Created: Wed Dec 28 19:57:29 2005
+# by: The Resource Compiler for PyQt (Qt v4.1.0)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x05\x3e\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x03\x00\x00\x00\x6b\xac\x58\x54\
+\x00\x00\x00\xa5\x50\x4c\x54\x45\x00\x7c\xf8\x00\x80\xf8\x08\x80\
+\xf8\x08\x84\xf8\x10\x84\xf8\x10\x88\xf8\x18\x88\xf8\x18\x8c\xf8\
+\x20\x90\xf8\x28\x90\xf8\x28\x94\xf8\x30\x94\xf8\x30\x98\xf8\x38\
+\x98\xf8\x38\x9c\xf8\x40\x9c\xf8\x40\xa0\xf8\x48\xa4\xf8\x50\xa4\
+\xf8\x50\xa8\xf8\x58\xa8\xf8\x58\xac\xf8\x60\xb0\xf8\x68\xb0\xf8\
+\x68\xb4\xf8\x70\xb4\xf8\x70\xb8\xf8\x78\xbc\xf8\x80\xbc\xf8\x80\
+\xc0\xf8\x88\xc4\xf8\x90\xc4\xf8\x90\xc8\xf8\x98\xcc\xf8\xa0\xcc\
+\xf8\xa0\xd0\xf8\xa8\xd4\xf8\xb0\xd8\xf8\xb8\xd8\xf8\xb8\xdc\xf8\
+\xc0\xdc\xf8\xc0\xe0\xf8\xc8\xe0\xf8\xc8\xe4\xf8\xd0\xe4\xf8\xd0\
+\xe8\xf8\xd8\xe8\xf8\xd8\xec\xf8\xe0\xec\xf8\xe0\xf0\xf8\xe8\xf4\
+\xf8\xf0\xf4\xf8\xf0\xf8\xf8\xf8\xf8\xf8\xf8\xfc\xf8\xce\x99\xaa\
+\x77\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x00\x48\x00\x00\x00\
+\x48\x00\x46\xc9\x6b\x3e\x00\x00\x04\x3f\x49\x44\x41\x54\x78\xda\
+\xed\xdd\xe1\x76\xd2\x40\x10\x05\xe0\x0d\x34\x05\x91\x62\x28\x82\
+\x14\x24\x16\x53\xc4\x88\x18\x13\xd3\x79\xff\x47\xf3\x8f\x9e\xee\
+\x20\x25\x9b\x9e\xb6\xb6\x73\xef\x3e\x40\x0f\xfb\x41\x93\xbd\x33\
+\x13\x70\x02\xbe\x1c\x01\x08\x40\x00\x02\x10\x40\x1c\xe0\x22\x00\
+\x01\x08\xa0\x01\xa0\x2e\x7d\x04\x20\x00\x01\x08\x40\x00\x02\x10\
+\x80\x00\x04\x20\x00\x01\x08\x40\x00\x02\x10\x80\x00\x04\x20\x00\
+\x01\x08\x40\x00\x02\x10\x80\x00\x04\x20\x00\x01\x08\x40\x00\x02\
+\x10\xe0\x05\xac\x9f\xd9\x7c\x38\x02\x05\xa8\xf3\x74\xd2\x73\xce\
+\xb9\x1e\x20\x40\x91\xcd\x87\xd1\xdf\x21\x96\x2e\x16\x40\x9d\xa7\
+\x93\xf3\x63\x63\x3c\x08\x00\xea\x8d\x07\x03\xa8\xf3\xf4\x32\x3e\
+\x39\xc8\x65\x18\xa0\x3c\xfe\xc6\xc3\x00\x54\xbd\xa0\x51\x3e\xbb\
+\x00\x53\x87\x0d\x70\xe3\xb0\x01\xaa\x18\x1c\x60\xe2\xb0\x01\x32\
+\x87\x0d\x50\xc6\xe0\x00\x63\x87\x0d\x90\x39\x6c\x80\xf2\x0c\x1c\
+\x60\xec\xb0\x01\x32\x87\x0d\x10\x74\x07\xb0\x0c\x70\xe9\xb0\x01\
+\x32\x87\x0d\x50\xc5\xe0\x00\x7e\x06\x88\x00\x01\x54\x08\x5e\xe0\
+\x01\xa8\x2a\x50\xbf\xc6\x03\x98\xf9\x1b\xdc\x0a\x1c\xc0\xd6\xdf\
+\xdf\x4c\xe0\x00\xea\xbe\xb7\xbd\xb8\xc2\x03\xb8\xf2\xb7\x97\x09\
+\x1c\xc0\x37\xff\xb6\x97\x08\x1e\xc0\xc0\x3f\x02\x14\x78\x00\x2b\
+\x7f\x73\x4b\x81\x03\x28\x3a\xea\x08\x80\x07\x90\xf8\x7b\xdb\x08\
+\x1c\xc0\xda\xdf\xda\x58\xe0\x00\x54\x08\xec\x14\x78\x00\xaa\x13\
+\xba\x12\x38\x00\x75\x06\xfe\x73\x05\x44\x02\x50\x67\x60\xf7\x45\
+\xe0\x00\x96\xfe\xbe\x26\x02\x07\xf0\xc3\x3f\x03\x77\x4b\x3c\x00\
+\x75\x04\x48\x05\x0e\x40\xd5\x81\x07\x02\x07\xa0\xeb\xc0\x39\x1e\
+\xc0\xfc\xa0\x0c\x84\x06\xb0\x8b\x0e\xca\x40\x68\x00\x43\x7f\x4f\
+\x6b\x81\x03\x50\x21\x68\x28\x70\x00\xea\x0a\x18\xed\xf0\x00\x3e\
+\xf8\x3b\x9a\x0b\x1c\xc0\xa9\x2b\x20\x04\xc0\xf0\xb0\x10\x0e\x06\
+\xf0\xd9\xdf\xcf\x85\xc0\x01\xd4\xe7\xf7\x9e\x01\x31\x00\x54\xfb\
+\x3b\x11\x38\x80\x42\x0d\x40\xec\xf0\x00\xc6\xf7\x94\x41\x50\x00\
+\x36\xee\x9f\x56\x18\x16\xc0\x9b\xfb\x53\x20\x04\xc0\xb5\xbf\x97\
+\x4e\x09\x07\xa0\xcb\x20\x0b\x81\x03\x50\xb7\xc0\xb3\x0a\x0e\x40\
+\xdf\x02\x53\x81\x03\x50\xcf\x44\xf5\x6a\x38\x80\xdc\x9d\xa8\x03\
+\x21\x00\xa8\x14\xd8\x17\x38\x00\x3d\x11\x7e\x03\x07\x70\xdb\x3f\
+\x55\x08\x04\x00\xf8\xe4\xf4\x44\x2c\x1a\xc0\xaf\xb8\x29\x06\x1b\
+\x07\x50\xcd\xf0\xa3\x31\xd8\x36\x40\xd9\x69\x8c\xc1\xb6\x01\x66\
+\xcd\x31\xd8\x34\x80\x3e\x04\xcf\x04\x0e\xe0\x7d\x40\x0c\xb6\x0c\
+\xf0\xdd\x05\xc4\x60\xcb\x00\xe3\x90\x18\x6c\x18\x40\xa7\xa0\x54\
+\xe0\x00\x46\x41\x31\xd8\x2e\xc0\x36\x2c\x06\xdb\x05\x18\x85\xc5\
+\x60\xb3\x00\xdb\xc0\x18\x6c\x16\x60\x18\x18\x83\xad\x02\x6c\x42\
+\x63\xb0\x55\x80\x61\x68\x0c\x36\x0a\xb0\x09\x8e\xc1\x46\x01\x2e\
+\x82\x63\xb0\x4d\x00\x7d\x0b\xd8\xe3\x01\xbc\xf3\x5f\xfc\xa5\xc0\
+\x01\xe4\xad\xaf\x00\xc6\x00\x92\xb6\xb7\x00\x63\x00\x3b\xf5\xda\
+\xbf\xe2\x01\x4c\x5a\x1e\x02\xad\x01\xec\xa3\x76\x29\xc0\x1c\xc0\
+\xac\x5d\x0c\x34\x07\x50\xaa\x0f\xc0\x35\x1e\x80\x1a\x88\xe9\xd6\
+\x70\x00\x55\xb7\x45\x29\xd8\x22\xc0\x2a\xbc\x19\x64\x12\xe0\xf6\
+\xbc\x75\x0c\xb2\x05\xa0\x1e\x0b\x38\x36\x16\x6f\x1d\xc0\xff\x7e\
+\x1c\x37\x12\x38\x80\xb6\xa5\x50\x73\x00\xe3\x07\x1d\x82\xec\x00\
+\xec\xdb\x35\x43\xec\x01\xa8\x53\x70\x4f\xe0\x00\xf4\x21\x68\x8d\
+\x07\x90\x3e\xfc\x03\x60\x03\xa0\xe9\xb7\x62\x1e\x79\x15\x2f\x0d\
+\xe0\xe6\x79\xf7\x1f\xd2\x6f\x7a\x5e\x80\x04\x1c\x60\xef\xc0\x01\
+\xe6\xe0\x00\x75\x17\x1c\xe0\xda\x81\x03\x0c\xc0\x01\x72\x07\x0e\
+\x30\x05\x07\xa8\x22\x70\x80\xbd\x43\xff\x17\x40\xff\x04\xc8\x5b\
+\x5e\x04\xc1\x01\x52\x74\x80\x2d\x3a\x40\x89\x0e\x20\x31\x3a\x40\
+\x82\x0e\x70\x85\x0e\xf0\x08\xaf\xc4\xe0\xb3\xc3\x04\x20\x00\x01\
+\x08\x40\x00\x02\x10\x80\x00\x04\x20\x00\x01\x08\x40\x00\x02\x9c\
+\x58\x0d\xbf\x3b\x5c\x9b\x07\x68\x28\x29\x56\xe6\x01\x76\x4f\x3f\
+\x10\xf6\xb2\x01\x36\xa7\x01\x72\xf3\x00\x0d\x7d\x95\xcc\x3c\x40\
+\x43\x67\x6d\x69\x1e\xa0\x61\xc8\x34\xb1\x0e\xd0\x34\x5e\xd0\xb5\
+\x0e\xf0\xb1\xa9\x07\x90\x1b\x07\x68\x1c\xb3\x9e\xd9\x06\x58\x37\
+\x76\x81\xba\x95\x65\x80\x2a\x60\xce\x7e\x69\x19\x20\x64\xba\x24\
+\x2a\xec\x02\xac\x82\x5a\xa1\x83\xda\x2a\xc0\x22\xb0\x19\x9c\xd4\
+\x26\x01\xf6\xa3\xe0\x76\xf8\x60\x67\x0e\xa0\xde\x4c\xda\xcc\x17\
+\x46\xd3\xfc\x15\x03\xac\x96\x07\x6b\x31\xbd\x68\x3f\x5d\x19\x27\
+\xf3\xbb\xbf\x50\xbc\x2a\x80\x27\x18\x25\xdd\x12\x80\x00\x04\x20\
+\x00\x01\x08\x40\x00\x02\x18\x28\x8a\xfe\xaf\x45\x00\x02\x10\x80\
+\x00\x04\x20\x00\x01\x08\x40\x00\x02\x10\x80\x00\x04\x20\x00\x01\
+\x08\x40\x00\x02\x10\x80\x00\x04\x20\x00\x01\x08\x40\x00\x02\x10\
+\x80\x00\x04\x20\x00\x2a\x00\xda\x22\x00\x01\x08\x70\x07\x80\xbb\
+\x08\x40\x00\x02\x10\x00\x7a\xfd\x06\x0e\x4c\xb1\x67\x70\xf4\x76\
+\x0b\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x07\xa7\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x03\x00\x00\x00\x6b\xac\x58\x54\
+\x00\x00\x00\x8d\x50\x4c\x54\x45\x78\xfc\x00\x80\xfc\x00\x80\xfc\
+\x08\x80\xfc\x10\x88\xfc\x10\x88\xfc\x18\x88\xfc\x20\x90\xfc\x20\
+\x90\xfc\x28\x90\xfc\x30\x98\xfc\x30\x98\xfc\x38\x98\xfc\x40\xa0\
+\xfc\x40\xa0\xfc\x48\xa0\xfc\x50\xa8\xfc\x50\xa8\xfc\x58\xa8\xfc\
+\x60\xb0\xfc\x60\xb0\xfc\x68\xb0\xfc\x70\xb8\xfc\x70\xb8\xfc\x78\
+\xc0\xfc\x80\xc0\xfc\x88\xc0\xfc\x90\xc8\xfc\x90\xc8\xfc\x98\xc8\
+\xfc\xa0\xd0\xfc\xa0\xd0\xfc\xa8\xd0\xfc\xb0\xd8\xfc\xb0\xd8\xfc\
+\xb8\xd8\xfc\xc0\xe0\xfc\xc0\xe0\xfc\xc8\xe0\xfc\xd0\xe8\xfc\xd0\
+\xe8\xfc\xd8\xe8\xfc\xe0\xf0\xfc\xe0\xf0\xfc\xe8\xf0\xfc\xf0\xf8\
+\xfc\xf0\xf8\xfc\xf8\xa0\x01\x02\x2a\x00\x00\x00\x09\x70\x48\x59\
+\x73\x00\x00\x00\x48\x00\x00\x00\x48\x00\x46\xc9\x6b\x3e\x00\x00\
+\x06\xc0\x49\x44\x41\x54\x78\xda\xed\xdd\xdb\x62\x9b\x38\x10\x06\
+\x60\x4b\x85\x42\x21\x66\xa1\x26\x1c\x8a\x03\x81\x9a\x40\x21\xf0\
+\xfe\x8f\xb7\x17\xbb\x6d\xe2\xc6\x18\x8c\xf5\x13\x81\x86\xcb\x36\
+\x17\xf8\x33\x16\xd2\x68\x66\xb4\xeb\x15\xbf\x76\x04\x40\x00\x04\
+\x40\x00\x04\xd0\xef\x14\xbc\x08\x80\x00\x08\xe0\x1c\x40\xa9\xa1\
+\x8f\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\
+\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\
+\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\
+\x80\x00\x08\xe0\xae\xab\x43\xde\x7c\xd7\x49\x0f\xf0\xcc\x76\x5c\
+\x37\xac\x07\xc7\x3b\x04\x61\x9c\x3c\x65\x79\x51\x56\x75\xd3\x4e\
+\xba\xf3\xae\x6d\xea\xaa\x3c\x15\x79\x96\x3e\x1d\x7f\xc4\x51\x18\
+\xf8\x07\xcf\x75\xf6\xb6\x65\x1a\xba\xc6\xd9\x6e\xc7\x7f\x49\x0e\
+\x50\xf2\xc1\xcc\x2c\xc6\x35\xdd\x30\x4d\xcb\xde\x3b\x8e\xeb\x79\
+\x07\xff\x31\xf8\xf0\xf9\xc6\x2f\x47\x72\x80\x00\x9d\xe0\x66\x48\
+\x0e\x10\xa1\x01\x7c\xc9\x01\x12\x34\x40\x26\x39\x40\x8a\x06\x68\
+\x25\x07\x28\xc0\x9f\xdf\x94\xfd\x35\x58\x82\x01\x3c\xd9\x01\x6a\
+\x30\xc0\x0f\xd9\x01\x5a\x30\x40\x21\xfd\x4c\x10\x0c\xf0\x4b\x7a\
+\x00\x0e\xfd\xfc\x4c\xfe\xc5\x90\x0e\x05\xd0\xe4\x07\x30\x65\x7f\
+\x0b\xa2\x01\x6c\x28\x80\x25\x3f\xc0\x1e\x0a\x60\xcb\x0f\xe0\xaa\
+\x0e\x70\x50\x1d\xe0\x51\x75\x80\x50\x75\x80\x58\xf5\xb7\x00\x36\
+\x22\xf2\x4d\x7e\x80\x54\xf5\x89\x50\x26\x79\x48\x14\x0e\x90\xab\
+\xbe\x16\xc0\xc6\xc4\x56\xb0\x1a\x04\xc7\xc4\xe4\xdf\x1a\x7b\x51\
+\xfd\x2d\x50\x41\x7f\x01\x95\xfc\x00\xf5\x87\xfd\xc0\xff\x36\x04\
+\xff\xec\x08\xfa\x41\x18\x46\x71\x9c\x1c\x8f\x69\x96\xe5\x45\x71\
+\x2a\xcb\xb2\x3c\xfd\x2c\xf2\x3c\xcb\xd2\xa7\x63\x92\xc4\x51\x14\
+\x86\x81\xef\x1f\xbe\x7b\xae\xeb\xec\xf7\xb6\x6d\x99\xa6\xf1\x55\
+\xd7\x34\x1e\xf5\xf2\x03\x34\x67\x00\x61\x2f\xdf\xb5\x28\x40\xa4\
+\x1e\xc0\x79\x5c\x3c\x56\x1d\x20\x51\x0f\xe0\xf5\x0c\xe0\xa8\x1e\
+\x40\x77\x06\xf0\xa4\x3a\x40\xaa\x3a\x40\xa6\x3a\x40\xae\x3a\x40\
+\xa1\x3a\xc0\x4f\xd5\x01\x4e\xaa\x03\x94\xaa\x03\x54\xaa\x03\xd4\
+\xaa\x03\x34\xaa\x03\xb4\x04\xa0\x38\x40\xa7\x3a\x40\xaf\x38\x00\
+\x53\x1d\x80\x13\x80\xe2\x00\x9a\xea\x00\xba\xea\x00\x86\xea\x00\
+\xa6\xea\x00\xdf\x54\x07\xb0\x54\x07\xb0\x55\x07\xd8\xab\x0e\xe0\
+\x5c\xfc\x93\xf6\x74\x0c\xbd\xbd\xa9\x6b\x9c\xed\xd8\x17\xdd\x30\
+\x6d\xf7\x31\xce\x4e\xaf\x1b\x04\x70\x3f\xfc\xf7\x4b\xe2\x1a\x83\
+\x39\x70\x6e\x94\x77\x5b\x06\xe8\x32\x4f\x1b\x4d\x82\x79\x88\x5f\
+\xd6\x0d\xf0\x3a\x50\xe6\xd8\x65\xee\xd4\x7a\x2a\x3d\xac\x57\x0c\
+\x70\x96\x1f\x70\xf8\xfd\xaf\xa7\xc3\x6d\xd5\x64\xf6\xb1\x5b\x2b\
+\x40\xf3\xb1\xd6\xbd\x4d\x66\x54\x52\x69\x71\xb7\x01\x80\xa0\xef\
+\xfb\xea\x30\xb3\x94\x10\x45\xb0\x64\x9a\x5c\xd8\x3f\xdf\x53\x45\
+\xf6\x35\x5f\x21\xc0\x59\xa6\xa8\x6d\xdc\x5b\x2c\xde\xae\x0e\xe0\
+\x24\x38\x3d\x3c\x5f\x1b\x80\xf0\x6c\xf1\x70\x65\x00\xcf\xc2\x13\
+\x84\x9d\x76\x55\x00\x80\x92\x19\xb3\x5d\x13\x00\xa2\x68\x4a\xac\
+\xc0\x1a\xcb\xe6\xcc\x66\x3d\x00\x98\xc2\x49\xb3\x5b\x0d\x80\x8f\
+\x29\x95\x70\x57\x03\xe0\x81\x8a\x45\xe2\xb5\x00\xa0\xca\xe7\x59\
+\xb1\x12\x00\x58\x03\x05\xa3\x5b\x07\x80\x05\xab\x98\x0a\xd6\x01\
+\x60\xc0\x00\xd8\xcb\x2a\x00\x34\x18\xc0\xee\x61\x15\x00\x0c\x07\
+\x20\x28\xf1\x16\x0b\xd0\x21\xeb\x26\xf7\x2b\x00\x68\xa0\x95\xb3\
+\xa5\xfc\x00\x03\x95\xb3\xcc\xf2\xa2\xb4\xa8\x9a\xd7\xbe\xef\xdb\
+\xa6\x2e\x8e\xa1\x37\x67\xb4\xf4\xe4\x07\xb8\x10\x10\xe2\x4e\x7c\
+\xf1\x9b\x6b\x73\xff\xd6\xc6\x63\xbc\x93\x1e\xe0\xef\xfe\x09\xcc\
+\xcd\xae\xdd\x74\xe9\xdf\x16\x32\x4e\xa5\x07\x38\x8f\x87\xe8\xd1\
+\xe8\x4a\xbe\x4b\xf4\x85\x87\x41\x2c\xc0\xfb\x78\x88\x3e\xad\x6c\
+\xb2\x8b\xa7\x3f\x05\xac\x95\x1d\xe0\xad\xb1\x32\x9f\xbe\x7e\x6b\
+\xa7\xaf\xa0\x72\xd9\x01\x82\x79\x11\xfd\x27\xbe\xdc\x82\x00\x3c\
+\x0f\xf0\xd9\xac\x70\x7e\x35\x71\x24\xb0\x64\x07\xe8\xfb\xca\x99\
+\x15\xc9\x6e\xa6\x2d\x23\x59\x27\x3d\x40\xdf\x9f\x66\x45\x6f\x3a\
+\x6b\xa1\xc9\x20\x1e\x60\xe6\xd5\x1a\xcb\xcc\x04\xa4\x05\xe8\xeb\
+\x29\x4b\xe9\x68\xc3\x00\x93\xfa\x90\x79\x5b\x06\x98\x12\x53\xb7\
+\x37\x0d\xd0\x8d\xbf\x0c\xcd\x4d\x03\x4c\xd8\x5a\x35\xb6\x0d\x30\
+\x1e\x54\xd6\x36\x0e\x30\x3a\x0e\xf2\x8d\x03\x8c\x86\xd5\xd9\xd6\
+\x01\x62\xd5\x9f\x80\xb1\xa8\xaa\xbe\x75\x80\xb1\xf6\xf4\xe6\xe6\
+\x01\x62\x95\x27\x42\x7d\x3f\xda\x94\xd4\xd9\x3c\xc0\xc8\x29\x25\
+\xde\xf6\x01\xf6\xe0\xbc\x49\xe9\x01\x7c\x65\xe3\x01\xff\x5f\xd7\
+\x33\x0d\xab\xed\x03\xe4\xe0\xd6\xd2\xd2\x03\x54\xd8\x69\x80\xfc\
+\x00\xbf\xc0\xfb\xc3\xd2\x03\x5c\x3d\xaf\x2d\x51\x00\xe0\x6a\x92\
+\x49\xad\x00\x40\x8f\x1d\x02\xd6\xfd\x04\x84\x2a\x00\x34\xe0\x3c\
+\x31\xe9\x01\x6a\x64\x40\x70\x0d\x00\x57\xea\xce\x7c\x99\x01\x2a\
+\x57\x50\x61\x4b\x8a\x9c\x07\xc3\x00\x5a\x9f\x89\x2a\x70\x8b\xd6\
+\x98\x28\x19\x7f\xd9\xed\x76\x5c\xcc\x23\x30\x7c\x5e\x5d\x26\x2b\
+\xc0\xb3\x21\x32\xa1\xdd\xc4\xc5\x43\x41\x00\x7f\xaa\x64\x98\x88\
+\xc6\x07\x1d\x03\x57\xcd\x88\x07\x78\x7b\x66\xff\x11\x70\x7f\x83\
+\xb5\xb7\x5a\x27\x2b\x40\x2a\xb4\x97\x78\x30\x04\x20\xea\xb0\x06\
+\xf1\x00\x8d\xd0\xc2\x9e\xaf\xc0\x65\x00\x6a\x10\x34\x04\xe6\xf1\
+\x95\xc0\x14\x49\x18\xc0\xbb\x30\x26\xbb\x77\xb6\xee\x43\xe7\x00\
+\x20\x80\xf7\x7b\xda\xfa\x7d\x93\x81\x76\x60\x57\x80\x55\x32\x03\
+\xb4\xe2\x8a\x5c\x63\x78\xe1\x28\x64\x26\x68\x8a\xba\xd7\x56\x43\
+\xff\x00\x30\x00\x67\x3f\x5c\x76\xc7\x70\x35\xf0\x0e\xd4\x64\x2f\
+\x9f\x3f\xef\x9b\xc1\x67\xff\x5e\x6b\x86\x5c\x04\x00\x01\xda\xf3\
+\x1b\xd7\xe7\x4e\x89\x2d\x60\x18\x00\xbb\x1a\xfc\xeb\xce\x67\x0a\
+\x04\xf8\x01\x00\x05\xf0\xf7\xad\xeb\x73\x7e\x05\x29\xbe\x7b\x04\
+\x0c\xe0\xc3\x7e\x9e\x76\xfb\x84\xa8\xb8\x3c\x00\xe8\xa2\x4f\xa9\
+\x80\x00\xbc\x7e\xb8\x79\x7e\xeb\x3e\xf6\xcf\xcb\x53\x20\x2e\xbc\
+\xbf\x22\x26\x24\x76\x61\xf8\xf2\x6f\x7a\x74\xb3\xcb\xdf\x3f\x17\
+\x7f\x56\x15\x06\xe0\xd2\xf8\x65\xde\x50\xdd\x11\x0d\x7c\x7e\xc0\
+\x49\x4d\x18\x80\x8b\x9b\xfa\x2c\x98\xf8\x10\x34\x03\xb9\x71\x1a\
+\xe2\xa0\x26\x50\x54\x78\x60\x04\x9b\x14\xc5\x18\xaa\x9c\xd4\x21\
+\xbd\x45\x41\xfb\x02\x43\x69\xde\x46\x32\xf6\x14\xa4\x43\xe9\xc1\
+\x06\xa6\xb7\x2a\x08\xe0\x71\x78\x3f\x2b\xb8\xf2\x20\xb7\x91\xbe\
+\x54\x17\x39\x30\xc0\xd5\x3c\x77\x23\x28\x2e\x3d\x07\x75\xf2\x30\
+\x18\x02\x66\xb0\x23\x8b\x41\x00\xed\x58\x9a\xbb\x75\x48\xf2\xea\
+\xf7\x97\xda\x96\x69\xe4\x5c\x2b\x12\xd3\x70\x47\x35\xa2\xf6\x06\
+\xa7\x75\x84\x60\x5c\xd3\xb5\xf1\x46\x2b\x36\xf0\x90\x32\x14\xc0\
+\x41\x5c\xab\x10\x0e\x3d\xb0\x1a\x05\x70\x14\xd7\x2c\x06\x7b\x48\
+\x1f\x6c\x7b\x5c\xd0\xc7\xd7\xd0\x67\x15\xc3\x12\x24\xb8\x88\x8f\
+\xcf\x7c\xf8\x01\x75\x30\x00\x01\x7d\xe4\xd8\xf7\x05\x8e\xa8\x84\
+\x01\xdc\xdf\x4c\xd3\x5d\xe4\x88\x52\x18\x40\x76\xe7\xb7\xef\xbd\
+\xf4\xfd\xaa\x01\xee\xea\xa2\x35\xa1\xe1\x8e\xf4\x00\x7d\x30\xb7\
+\x95\x1e\x73\x96\x3c\xa3\x1c\x98\x26\xd7\xa5\x33\x9a\xe9\xb3\x7d\
+\xb2\xec\xd9\xb4\xd8\x3c\xc1\x3a\xba\xe9\x34\x09\xee\xa6\x8b\x9f\
+\xcb\x0a\x4f\x94\xac\x93\xfd\xa4\xae\x8a\x9a\x13\x15\x9f\x71\x28\
+\xeb\x22\x99\xa2\xa7\xd8\x35\xae\x28\x68\xb6\x9f\x7e\xda\xa1\xd4\
+\x8b\xa5\xca\x76\x2f\x59\x1c\xb8\x7b\xcb\xd0\x38\x67\x3b\xc6\x75\
+\xc3\xb4\xf7\x6e\x90\xe4\xd5\xe7\x1e\xc6\x2b\x7f\xbd\x00\x01\x10\
+\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\
+\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\
+\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x40\x00\x54\xbb\
+\x08\x80\x00\x08\xe0\x0d\x40\xdd\x8b\x00\x08\x80\x00\x08\x40\xe9\
+\xeb\x5f\x29\x7e\x47\x9c\x8c\x3f\x1d\xdc\x00\x00\x00\x00\x49\x45\
+\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x09\x8e\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x03\x00\x00\x00\x6b\xac\x58\x54\
+\x00\x00\x00\xf0\x50\x4c\x54\x45\xf8\x00\x78\xf8\x00\x80\xf8\x04\
+\x80\xf8\x08\x80\xf8\x0c\x80\xf8\x10\x80\xf8\x10\x88\xf8\x14\x88\
+\xf8\x18\x88\xf8\x1c\x88\xf8\x20\x88\xf8\x20\x90\xf8\x24\x90\xf8\
+\x28\x90\xf8\x2c\x90\xf8\x30\x90\xf8\x30\x98\xf8\x34\x98\xf8\x38\
+\x98\xf8\x3c\x98\xf8\x40\x98\xf8\x40\xa0\xf8\x44\xa0\xf8\x48\xa0\
+\xf8\x4c\xa0\xf8\x50\xa0\xf8\x50\xa8\xf8\x54\xa8\xf8\x58\xa8\xf8\
+\x5c\xa8\xf8\x60\xa8\xf8\x60\xb0\xf8\x64\xb0\xf8\x68\xb0\xf8\x6c\
+\xb0\xf8\x70\xb0\xf8\x70\xb8\xf8\x74\xb8\xf8\x78\xb8\xf8\x7c\xb8\
+\xf8\x80\xb8\xf8\x80\xc0\xf8\x84\xc0\xf8\x88\xc0\xf8\x8c\xc0\xf8\
+\x90\xc0\xf8\x90\xc8\xf8\x94\xc8\xf8\x98\xc8\xf8\x9c\xc8\xf8\xa0\
+\xc8\xf8\xa0\xd0\xf8\xa4\xd0\xf8\xa8\xd0\xf8\xac\xd0\xf8\xb0\xd0\
+\xf8\xb0\xd8\xf8\xb4\xd8\xf8\xb8\xd8\xf8\xbc\xd8\xf8\xc0\xd8\xf8\
+\xc0\xe0\xf8\xc4\xe0\xf8\xc8\xe0\xf8\xcc\xe0\xf8\xd0\xe0\xf8\xd0\
+\xe8\xf8\xd4\xe8\xf8\xd8\xe8\xf8\xdc\xe8\xf8\xe0\xe8\xf8\xe0\xf0\
+\xf8\xe4\xf0\xf8\xe8\xf0\xf8\xec\xf0\xf8\xf0\xf0\xf8\xf0\xf8\xf8\
+\xf4\xf8\xf8\xf8\xf8\xf8\xfc\xf8\xd6\xac\x3e\xe0\x00\x00\x00\x09\
+\x70\x48\x59\x73\x00\x00\x00\x48\x00\x00\x00\x48\x00\x46\xc9\x6b\
+\x3e\x00\x00\x08\x44\x49\x44\x41\x54\x78\xda\xed\xdd\x6b\x5b\xda\
+\x48\x14\x00\xe0\x40\x52\x01\x05\x54\xac\xc8\x4a\x11\x61\x2d\x56\
+\xa4\x5c\xaa\x60\x15\xb9\x88\x60\x00\x49\xce\xff\xff\x37\xfb\xa1\
+\xbb\xed\xb6\x0f\x73\x83\x99\x30\xc9\x9c\xf9\xac\x79\x98\x37\x99\
+\xfb\x99\x19\x0b\x0c\x4f\x16\x02\x20\x00\x02\x20\x00\x02\x80\x65\
+\x60\x42\x00\x04\x40\x80\xdf\x01\x8c\xaa\xfa\x10\x00\x01\x10\x00\
+\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\
+\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\
+\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x60\xf7\x69\xe5\
+\x4e\x86\x4f\x0f\xdd\xce\xa3\x61\x00\xf3\xe7\xbb\x9b\xf2\xd9\x51\
+\x32\xfe\x33\x96\xa7\xb8\x34\x04\xc0\x1f\xb7\x2f\x73\x1f\xd6\x44\
+\x33\x25\x9f\xa2\x0f\xe0\xf5\xaf\x4f\xe2\xe4\x80\xae\xaa\x17\x69\
+\x80\x79\xbb\x60\x33\x42\xda\x32\xe3\xc8\x02\xbc\x77\xf2\x31\x8e\
+\xa0\xbe\x78\x3d\x9a\x00\xe3\xb2\xcd\x1b\xd7\x98\x9b\x45\x0f\xa0\
+\x77\x2c\x12\xd9\xe9\xb8\xd1\x02\xf0\x3b\x69\xb1\xd0\xd6\x46\xb4\
+\xbe\x80\x7b\xc1\xec\x5b\xb5\x48\xd5\x01\xfd\xac\x68\x68\x73\x25\
+\x4a\x95\xe0\xec\x9c\x23\xc7\x76\x36\x5f\xba\xaa\x37\x5a\xed\x4e\
+\xbb\x59\xff\x7c\x1d\xa1\x66\xd0\xaf\x33\x6a\xfe\x58\xa6\xf4\xb5\
+\x3f\x8f\xec\x60\x68\x44\xff\xfa\xd3\x95\xde\x52\xfd\x8f\xd8\x1d\
+\x80\x5f\xa3\x75\x7b\xb2\x37\xaf\x11\x1f\x0e\x8f\x29\xaf\xdf\xa9\
+\xbc\x44\x7e\x3e\xa0\x41\x1e\xf0\xa4\xdb\x1e\x40\xc4\x01\x16\x67\
+\xc4\xec\x1f\xf5\x0c\x98\x11\x1a\x24\x49\xd9\x3f\xe8\x9a\x30\x25\
+\xd6\x22\x7d\xfe\x4e\xc3\x37\x60\x4e\xd0\xbb\x20\xbd\xfe\x73\x17\
+\x20\xfa\x00\xee\x11\x21\xfb\x7b\x5d\x00\x03\x00\x5e\x48\xc5\xff\
+\x74\x0e\x26\x00\xf4\x1d\x42\xfe\xaf\x01\x4c\x00\xb8\x27\x54\x7f\
+\x4e\x0f\x8c\x00\x68\x10\x5e\x7f\x72\x02\x46\x00\xd4\x49\x5d\xbf\
+\x19\x18\x01\x70\x4b\xc8\xff\xe1\x02\x8c\x00\x20\xe5\x3f\xb3\xd3\
+\xfc\x07\x07\x40\x2a\xff\xe9\x39\x18\x01\xf0\x8d\x90\xff\xc4\x0c\
+\x8c\x00\x78\x22\xb4\x7f\xf6\x08\x8c\x00\x78\x21\xf5\x7f\xba\x60\
+\x04\x80\x4b\xea\xff\x56\xc1\x08\x00\xef\x90\x90\xff\x63\xdf\x0c\
+\x80\x32\x69\xf8\x3f\x03\x23\x00\xda\xa4\xf1\x7f\x1b\x8c\x00\x18\
+\x93\xe6\x7f\xf2\x60\x04\xc0\x32\x45\x5a\xf0\x9a\x99\x01\x50\x22\
+\x15\x80\x3a\x18\x01\xf0\x9d\x94\xff\x7d\xdf\x08\x80\x65\x82\x04\
+\x70\x0f\x46\x00\x14\x89\xeb\x1f\x60\x04\x00\xb1\x00\x58\x0f\x46\
+\x00\x78\x07\xc4\xc5\x5f\x30\x02\xe0\x86\xf8\x01\x74\x8c\x00\x70\
+\x89\xf1\x1f\x09\xcf\x08\x80\x62\x30\x71\x5e\xda\x02\x8c\xc8\x11\
+\x10\x53\x23\x00\xc8\x31\x00\x39\x30\x01\x60\x48\xfe\x00\x9a\x46\
+\x00\xe4\xc9\x00\xae\x09\x00\x94\x0f\xe0\x18\x4c\x00\x28\x90\x01\
+\xae\x4d\x00\x98\x52\x82\x00\x07\x26\x00\x54\x29\x51\x80\xbe\x01\
+\x00\x2b\x87\x0c\x90\x07\x03\x00\x9a\x56\x48\xaa\x00\x55\x00\x19\
+\x0a\xc0\xa3\x01\x00\x63\x5a\x14\xf8\xc2\x00\x80\x2b\x4a\xfe\x93\
+\x10\x7d\x00\x3f\x69\x85\xa5\x0e\x54\x03\xf0\x44\x2b\x01\x57\x06\
+\x00\x94\x68\x00\x2d\x03\x00\xf6\x68\x00\xfd\xe8\x03\x0c\xa9\x5b\
+\x81\x28\x2b\x62\xb3\x6e\xbd\x7c\x9a\x4d\x3a\x76\xcc\x4e\xa4\x32\
+\x27\x17\xf5\xee\x24\x94\x00\x35\xea\x46\x30\x42\x47\xf8\xad\x75\
+\xbe\xee\xc3\x71\x0a\x8d\x71\xe8\x00\xa8\x9b\xc1\xd6\xb6\x82\xab\
+\x56\x8e\xb6\x7d\xac\xee\x86\x0a\xc0\xa5\x96\x80\x35\x93\x01\x6e\
+\xd5\x61\x6c\x9d\x8c\xe5\x07\x21\x02\xe8\x50\xf3\x52\xf8\xf3\xcf\
+\x17\xd5\x38\xcf\x86\xd9\xfc\x30\x34\x00\x65\x6a\x46\x2e\xff\xf8\
+\xeb\x96\x63\x71\xa6\xe2\x22\x24\x00\x69\x81\xad\xdf\x53\x91\x73\
+\x03\xf6\xee\x42\x01\xb0\x10\xd8\xfb\xdf\xb6\x2d\xa1\x74\xbe\x0a\
+\x01\x40\x8f\x9e\x87\xff\xad\x0a\x7a\x25\xe1\x5b\xc1\xb2\x6f\xfa\
+\x03\x5c\xd1\xb3\xf0\x6b\x6f\xc8\xfc\x68\x83\x7b\xd1\x12\x43\xed\
+\x01\x3e\xd2\x73\xf0\xf3\x28\xa4\xd7\xd4\x46\x37\xc3\x39\x43\xdd\
+\x01\xf6\xe8\x19\x18\xfd\xd7\x5f\x76\xac\xcd\x92\x33\xd6\x1b\x60\
+\xce\xf8\xfd\xff\xee\x8a\x7f\xb6\xad\x4d\xd3\xde\xab\xd6\x00\x4f\
+\x8c\x9f\xff\x63\x2c\xd4\xdf\x3c\xff\x96\x95\x59\xe9\x0c\xd0\x60\
+\xfc\xfa\x39\x00\xc0\x70\x9b\xfc\x5b\x56\x51\x67\x00\x56\xd3\xb6\
+\x04\x80\xc9\x87\x2d\xef\xc8\x6c\x6a\x0c\x70\xc2\xf8\xed\x2b\xca\
+\xf6\x01\xee\x24\x31\xcc\x56\x3a\x00\xab\x71\xf3\xe0\x3d\x6b\x6d\
+\x9d\xce\xb4\x05\xf0\x59\x07\xc2\xf9\xfe\xa9\x8c\x8b\x62\x7b\xba\
+\x02\xcc\x58\xbf\xdc\xaf\x48\xb9\x29\x37\xe5\x6b\x0a\xf0\xcc\xfa\
+\xe5\x6d\x49\x77\x05\xb7\x35\x05\xb8\x63\x9e\x87\x28\x09\xe0\xc0\
+\xd7\x13\xe0\x56\xb4\x3e\x3f\xbd\xbe\x1f\xb9\x4b\xdf\x9b\x4f\xba\
+\xb5\x93\x98\xc0\x7f\x7e\xd3\x13\xa0\x26\x92\xfb\xf8\xf9\xc3\xef\
+\xef\x71\xd1\xca\x70\xff\xf3\xa1\x9e\x00\x97\xfc\xd9\x8f\x95\xd7\
+\xb5\xe6\x3d\x6e\x82\x17\x2d\x01\x8a\xfc\x3d\xfa\x11\xa1\x21\xad\
+\x71\x56\x13\x55\x2d\x01\xb8\x1b\xf9\x22\x39\x5e\x7a\x98\xe0\x9b\
+\x1b\xf1\x75\x04\x38\xb4\x24\xbc\xbe\x19\x5f\x31\x78\xd4\x11\xe0\
+\x80\x2f\xff\x25\xc6\xc4\x2a\x97\xc0\x95\x8e\x00\x7c\xf3\x5c\x39\
+\xd6\xd7\x3b\xdf\xe7\xa9\x45\x74\x04\xe0\x2a\xbe\x36\x3b\x5c\x7e\
+\xcc\x53\x13\xba\x1a\x02\xec\xc9\x3a\x17\x98\xa7\xcb\xdc\xd1\x10\
+\xc0\x96\x36\x90\x29\x04\x73\xc0\xae\x6c\x80\xb8\xb4\x17\xf7\xc6\
+\xb6\xcc\x69\x08\x20\xb1\xfd\xae\xb3\x67\xc8\xc3\xf9\x05\x7c\xe6\
+\x7c\x94\xc7\xae\x50\xa7\xfa\x01\x70\x2c\x77\x70\xc7\xfd\xb0\x47\
+\x96\x0f\xfa\x01\xb0\xdf\xda\x3e\xf7\xb3\x56\x4c\xcd\x56\x18\x3b\
+\x42\x02\x55\x37\x73\xf6\xac\xa6\x1f\x00\xfb\xa8\x7c\x81\xe9\xcc\
+\xf1\x96\x3d\xea\x5d\x00\x64\xa5\x76\xdf\x58\x4f\x3b\xd5\x0f\x80\
+\x19\xf2\x22\x14\x2c\xfe\x45\xfd\x68\x40\x36\xc0\x47\x66\xb4\x97\
+\xc8\xd3\x58\x65\xe0\x20\x84\x33\x42\x15\x99\x75\x6a\x52\x3f\x80\
+\xaa\x8c\x81\xd0\xaf\xf4\x89\xfe\xb0\x0f\xfa\x01\x30\xfb\xaf\x62\
+\xe7\xc7\xb5\x18\xd3\xca\xfa\x01\x7c\x63\x01\x3c\x83\xc4\x4a\x20\
+\xa6\x1f\x00\x2b\x40\xc4\x12\x8b\x6f\xf1\xe9\x63\x0b\x5b\x3f\x80\
+\x17\x16\x80\xe0\x11\xa2\xf4\xc9\xc1\x84\x7e\x00\x0b\x16\x80\xe0\
+\xbd\x29\xe7\x61\x6b\x06\x99\xc3\x41\xc1\xe3\x53\x6a\x61\xeb\x08\
+\x31\xbb\x82\x82\xab\x19\x2d\xd1\xcd\x07\x3b\x07\x60\x05\x49\x09\
+\x3e\x8e\x1e\x79\xfc\x51\x43\x80\xba\xdc\x22\x30\xa0\x3e\xec\x93\
+\x86\x00\x3d\x76\x94\x98\x48\x9a\x86\x6d\x3e\x80\xf1\x8b\x85\xb7\
+\x4e\xcf\x55\xc7\xc9\x48\x07\x60\x74\x5d\x44\x57\x73\x96\x7c\xa1\
+\xe7\x1a\x01\xb0\x9a\x01\xc1\xad\x90\x1e\x47\xe0\xb1\x66\x00\x8c\
+\xf1\x60\x7f\x83\x1f\x48\x1c\x0a\xf8\x3a\x02\x74\x65\x8e\x06\xc1\
+\x57\xbd\x3c\x2c\x1f\xc0\x95\x3a\x93\xbd\xa2\x3d\xab\xac\x25\x00\
+\x63\x16\xa7\x26\xb1\x12\x6c\xeb\x09\xf0\x49\x66\xac\xff\x5c\x62\
+\x85\x1a\x14\x00\xbd\xfb\x2e\x78\x9c\xec\x44\xed\x6c\x80\x12\x80\
+\x99\xcc\x69\xbc\xbe\xda\x91\x80\x9a\xed\xf3\x19\x89\x33\x22\xb4\
+\x36\xe5\x56\x57\x00\xfa\x18\xfe\xbb\xd0\xb3\x9a\x6a\x17\xc7\x77\
+\x71\x84\x86\xd8\x49\x5a\x94\x6e\x95\x9c\xb3\x89\x55\x00\xd0\xd7\
+\xc8\xc5\x76\xbb\x28\x3f\x96\x50\x09\x00\xf5\x04\x01\xb1\xd3\xf4\
+\x28\xab\xcd\x63\x7d\x01\xe8\x73\xe3\x22\xa7\x61\xac\xc8\x3b\x08\
+\xd2\xa0\x2f\x00\xec\xcb\xaa\x04\x06\xca\xf7\x0e\xaa\x01\xb8\x91\
+\xd5\x15\x22\xef\x43\x75\x56\x3a\x03\xb8\x31\x49\x8b\x43\x05\xc5\
+\xbb\x05\x94\x1d\xa8\x78\x26\xa7\x0c\xf8\xb6\xda\x4e\x80\x3a\x80\
+\x9e\x9c\x38\xb1\x27\xf5\x5b\x47\x15\x01\xd0\xbb\xc3\xdc\x71\x52\
+\xc4\x1d\x48\xb1\x89\xee\x00\xf7\x32\x62\x7c\x3d\xe2\x3a\xdb\x05\
+\xe8\x0e\x40\x8f\x97\x1b\x6e\xa9\x68\xbb\xfa\x03\xdc\x49\xf8\x04\
+\xb2\x0a\x17\x44\x94\x03\xf8\xe9\xad\xa7\x46\x1f\x89\x1b\x0e\xde\
+\x43\x00\x40\x6f\x08\xb8\xb2\x70\xa4\x70\x3d\x24\x00\x00\xf8\x6b\
+\xcb\x20\xd7\x96\xea\x3e\x90\x6a\x00\xd7\xd9\xaa\x10\xb8\xa4\x83\
+\x46\xd2\x5e\x48\x00\xa8\xb3\x39\xcc\xfb\x66\x7d\xd2\x19\x93\xf1\
+\x11\x84\x05\x00\x72\xd4\x00\xa7\xd9\x66\x7d\x20\xc9\x77\x34\x29\
+\x05\x98\x51\x37\xd1\xa5\x68\xbd\xb9\xab\x00\x5a\x40\xf5\x00\xe4\
+\x86\xec\xc7\x88\x96\xb8\x50\x4a\x3e\x68\xa4\x08\xa1\x02\x60\x6c\
+\xfb\x89\xd5\xd6\x4f\x8f\xcd\x89\x87\x11\xe5\xbc\x90\x01\xb0\x76\
+\xbd\x64\xd7\x34\xe9\x7e\x93\xd8\x7c\x9c\x84\xe1\x44\xc9\x3f\x12\
+\x2b\x7e\x3e\xd7\xfb\xfd\xa5\xbe\x37\xc8\x8b\xab\x67\x0a\xee\x68\
+\x53\x0e\xe0\x33\x77\x10\x38\xa5\xce\xf8\x47\x51\x58\x0e\xbe\xe6\
+\x29\x11\x36\x45\x15\xb7\xb3\x28\x07\x00\xbf\xcc\xb3\x9f\xda\x49\
+\xa5\x93\x8c\x20\xd3\x8a\x92\xdb\x69\xd4\x03\x30\xa6\x48\x79\x93\
+\xad\xe8\x96\xd6\x20\x00\xa0\x6b\x6f\x9d\xff\xcc\x2b\x84\x18\x00\
+\x5e\x33\x5b\xe6\xbf\xac\xec\x8a\xca\x60\x00\xc0\xfb\x1c\xdb\xe6\
+\xf5\x2b\xbc\x94\x21\x20\x00\x80\xe1\xe1\xc6\xa5\xff\x56\xe5\xdd\
+\x5c\x81\x01\x00\xb4\x13\x9b\x64\x3f\x7e\xa1\xf6\x76\xc2\x00\x01\
+\x60\x75\x2b\x4c\x60\xff\xad\xfa\x72\xc6\x20\x01\x00\xbc\xb6\xd0\
+\x71\x9a\xc9\x2f\x4b\x80\x48\x01\x00\xc0\xe0\x92\xf3\x48\x59\xa7\
+\x1c\xc8\x7d\x34\x81\x03\x00\xf8\xdf\x2b\xcc\x53\x06\x52\xa5\x5e\
+\x40\xb7\x12\xee\x00\x00\x00\x60\xda\xb9\xcc\x12\x7a\xfd\xb1\xcc\
+\xe5\xdd\x1b\x04\x96\x76\x04\x00\x00\xe0\xbf\x76\x6f\xab\x85\x5c\
+\x26\xe9\xd8\xb1\x98\x93\x3c\xc8\xe6\xce\xaa\xcd\xc7\x69\xc0\xf7\
+\x51\xee\x10\x40\x8f\x84\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\
+\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\
+\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\x00\x08\x80\
+\x00\x08\x60\x2a\x80\x69\x09\x01\x10\x00\x01\x7e\x01\x98\x9b\x10\
+\x00\x01\x10\x00\x01\x8c\x4e\xff\x00\xf3\x6b\xd4\xa5\x75\x51\x85\
+\x33\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x04\x14\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x03\x00\x00\x00\x6b\xac\x58\x54\
+\x00\x00\x00\x9f\x50\x4c\x54\x45\xf8\x7c\x00\xf8\x80\x00\xf8\x80\
+\x08\xf8\x84\x08\xf8\x84\x10\xf8\x88\x10\xf8\x88\x18\xf8\x8c\x18\
+\xf8\x8c\x20\xf8\x90\x20\xf8\x94\x28\xf8\x94\x30\xf8\x98\x30\xf8\
+\x98\x38\xf8\x9c\x38\xf8\xa0\x40\xf8\xa4\x48\xf8\xa4\x50\xf8\xa8\
+\x50\xf8\xa8\x58\xf8\xac\x58\xf8\xb0\x60\xf8\xb0\x68\xf8\xb4\x68\
+\xf8\xb4\x70\xf8\xb8\x70\xf8\xb8\x78\xf8\xbc\x78\xf8\xc0\x80\xf8\
+\xc4\x88\xf8\xc8\x90\xf8\xc8\x98\xf8\xcc\x98\xf8\xd0\xa0\xf8\xd4\
+\xa8\xf8\xd4\xb0\xf8\xd8\xb0\xf8\xd8\xb8\xf8\xdc\xb8\xf8\xe0\xc0\
+\xf8\xe0\xc8\xf8\xe4\xc8\xf8\xe4\xd0\xf8\xe8\xd0\xf8\xec\xd8\xf8\
+\xec\xe0\xf8\xf0\xe0\xf8\xf0\xe8\xf8\xf4\xe8\xf8\xf4\xf0\xf8\xf8\
+\xf0\xf8\xf8\xf8\xf8\xfc\xf8\x35\x75\xa4\x70\x00\x00\x00\x09\x70\
+\x48\x59\x73\x00\x00\x00\x48\x00\x00\x00\x48\x00\x46\xc9\x6b\x3e\
+\x00\x00\x03\x1b\x49\x44\x41\x54\x78\xda\xed\xdd\x61\x73\xd2\x40\
+\x10\x80\xe1\x8b\x10\x23\x1a\x01\x23\x69\x6c\x0b\xb1\x80\x0d\x62\
+\x10\x62\xe8\xff\xff\x6d\xb6\xd5\xd1\x92\x12\x72\x29\x38\x72\xbb\
+\xef\x7e\xce\xb0\xec\x33\xc9\x5d\xb8\xd9\x1d\xcc\x9d\xf2\x30\x00\
+\x00\x00\x00\x00\x00\xdc\x19\x85\x01\x00\x00\x00\xec\x02\xa8\x5a\
+\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x80\xff\x18\x45\xae\x1a\x20\x1b\x79\
+\x91\x5e\x80\xf5\xb8\x77\xff\x35\xde\x68\x05\x98\x0d\xbd\xa7\xbd\
+\x3b\xca\x00\xf2\x4b\xbf\xd2\xbc\xa4\x09\xa0\x48\xc3\xe7\xdd\x5b\
+\x7a\x00\x6e\x23\x6f\x5f\xfb\x9a\x12\x80\xfc\x2a\xa8\xe9\xdf\xd3\
+\x00\x50\xb9\xf5\xb5\x01\xcc\xab\xb7\xbe\x2a\x80\xaf\x89\xdf\xd0\
+\xc2\x2a\x19\x60\xf5\xf8\xc2\xa3\x15\xa0\x48\xdf\x5b\x35\x31\xcb\
+\x04\x28\xa7\x43\xcf\xb2\x8b\x5b\x20\xc0\x76\x1e\x75\xec\xdb\xd8\
+\xc5\x01\x64\x71\xb7\x55\x1f\xbf\x2c\x80\xec\xc2\x6f\x3b\xc8\x20\
+\x08\x60\x91\xbc\x7e\xc1\x24\x87\x14\x80\xac\x65\xf5\xb2\x00\xb2\
+\xd8\x7f\xf1\x2c\x8f\xf3\x00\xe5\x6c\xd4\x3d\x66\x98\xc9\x6d\x80\
+\xcd\xcd\xf0\xd5\x91\xd3\x5c\x0e\x03\xe4\xe3\xbe\x77\xfc\x38\x9b\
+\xa3\x00\xe5\x97\x8b\xe0\x34\xf3\x7c\x2e\x02\x2c\x27\x03\xef\x64\
+\x03\x8d\xae\x01\xe4\x69\xe4\x9b\xd3\x84\x83\x00\xab\x0f\xa7\x2a\
+\xde\x51\x80\xcc\xae\x32\x2f\x4a\x02\x99\x00\x0b\x9b\xf2\x3b\x97\
+\xeb\xfb\xd3\x00\x5f\x24\xc0\xb2\xb9\x2a\x7f\x5c\x3c\x5e\x9a\x88\
+\x04\xf8\xde\x54\x53\x2f\x2d\x7f\x5f\x3a\x15\x09\x50\x1e\xae\xe8\
+\xdd\xb4\xd5\xcd\xe2\xe2\x36\x78\xe8\xc9\x1e\xdc\xee\x6c\x18\x32\
+\x01\xfa\xf5\x0b\xff\xb2\x72\x26\x2a\x13\x20\xae\x29\x3f\x5e\xb5\
+\x7c\x5a\x5c\x05\x48\x6b\xf7\xbd\xbd\xa9\xe5\x01\xec\x59\xda\x82\
+\xc9\x8f\xda\xd4\x02\x7f\x0b\x54\xcf\xbb\x7b\x37\xdb\x03\xa9\x05\
+\x02\x0c\x77\x4a\x08\x67\x87\x53\x0b\x04\xf8\xfc\x74\xdf\xcb\x9a\
+\x52\x0b\x04\x58\xff\x59\xf8\x47\xdf\x9a\x53\x4b\x3c\x0f\xf8\xf5\
+\x26\xd0\x49\x56\x36\xa9\x25\x02\x3c\x6c\x84\xfe\x75\x61\x97\x5a\
+\x22\x40\xe1\x05\x93\xd2\x36\xb5\xc8\x33\xc1\x45\x8b\xd4\x7a\xfb\
+\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x38\x5f\x80\xad\x76\x80\x4d\x33\x40\x21\x1a\xc0\
+\xe2\x7f\xda\x73\xd1\x00\x93\x66\x80\xa9\x68\x80\x7e\x33\x40\x2c\
+\x19\xc0\xe2\x09\x30\xfe\x56\x30\x40\x68\x01\x60\x52\xb9\x00\xb1\
+\x4d\xfd\xa6\xbb\x16\x0a\x50\x8e\x8c\x5d\xbc\xdd\x88\x04\x98\xf7\
+\x8c\x6d\x04\x99\x38\x80\xe5\xd8\xbe\xfc\x87\x18\xcc\x4a\x37\x01\
+\xae\x9f\xc7\x55\x12\x85\x1d\xd3\x3a\xbc\xf0\xe3\xa7\xea\x47\x4d\
+\xce\x1e\xa0\x34\xff\x34\x7c\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x87\x4f\x85\xcf\x23\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x2b\x80\xb6\x00\
+\x00\x00\x00\xfe\x02\xe8\x0d\x00\x00\x00\x00\x00\xd5\xf1\x13\x3b\
+\x45\x7a\xc4\xe1\x22\xe3\x41\x00\x00\x00\x00\x49\x45\x4e\x44\xae\
+\x42\x60\x82\
+\x00\x00\x06\xe8\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x03\x00\x00\x00\x6b\xac\x58\x54\
+\x00\x00\x00\x8a\x50\x4c\x54\x45\x00\xfc\x78\x00\xfc\x80\x08\xfc\
+\x80\x10\xfc\x80\x10\xfc\x88\x18\xfc\x88\x20\xfc\x88\x20\xfc\x90\
+\x28\xfc\x90\x30\xfc\x90\x30\xfc\x98\x38\xfc\x98\x40\xfc\x98\x40\
+\xfc\xa0\x48\xfc\xa0\x50\xfc\xa0\x50\xfc\xa8\x58\xfc\xa8\x60\xfc\
+\xa8\x60\xfc\xb0\x68\xfc\xb0\x70\xfc\xb0\x70\xfc\xb8\x78\xfc\xb8\
+\x80\xfc\xb8\x80\xfc\xc0\x88\xfc\xc0\x90\xfc\xc0\x90\xfc\xc8\x98\
+\xfc\xc8\xa0\xfc\xd0\xa8\xfc\xd0\xb0\xfc\xd0\xb0\xfc\xd8\xb8\xfc\
+\xd8\xc0\xfc\xe0\xc8\xfc\xe0\xd0\xfc\xe0\xd0\xfc\xe8\xd8\xfc\xe8\
+\xe0\xfc\xe8\xe0\xfc\xf0\xe8\xfc\xf0\xf0\xfc\xf0\xf0\xfc\xf8\xf8\
+\xfc\xf8\x60\x3b\x5e\x10\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\
+\x00\x48\x00\x00\x00\x48\x00\x46\xc9\x6b\x3e\x00\x00\x06\x04\x49\
+\x44\x41\x54\x78\xda\xed\xdd\x61\x77\xa2\x38\x14\x06\x60\x42\x61\
+\x60\xa4\xba\xd0\x76\x74\x75\x51\x2a\x32\x50\x62\xf8\xff\x7f\x6f\
+\x3b\x9d\x3d\x67\xdb\x01\x14\x85\x24\x37\xe4\xcd\x77\xcf\xe9\x7d\
+\x2a\xe1\xe6\xe6\x26\x3a\x8d\xe5\xc3\x01\x00\x00\x00\x00\x00\x00\
+\x34\x8e\x85\x03\x00\x00\x00\xc0\x57\x00\xab\xa6\x3e\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x26\x1e\x55\x9e\xae\x93\x28\xf4\x5d\x97\x31\xd7\xf3\x83\x30\
+\x4a\xd6\x69\x56\x08\x1b\x00\xc4\x71\xf3\xe8\xf6\x75\x2c\x06\xf1\
+\xf6\xc8\xe7\x0c\x50\xed\x1e\xd9\xd5\xbe\xcd\x70\x9d\x8b\x59\x02\
+\xf0\x7f\x16\x43\x7b\x57\xd9\xea\x20\xe6\x06\x50\x24\xec\xa6\xfe\
+\x5d\x37\xc9\xe7\x04\x70\x8c\xee\xe8\x61\x0e\x52\x31\x13\x80\xe3\
+\xe2\xce\x36\x6e\x6f\xcb\x67\x00\x50\x44\x23\x3a\xd9\xdd\x9d\xe9\
+\x00\x75\x32\xb2\x99\x3f\x38\x1a\x0d\x90\xba\xe3\xcf\x33\x2c\x6b\
+\x63\x01\xca\xc5\x24\x27\x3a\x1e\x32\x43\x01\x36\x6c\xaa\x43\x2d\
+\x4f\xc2\x40\x80\x89\xfe\xfd\xff\xcd\x04\x95\x71\x00\x53\x3c\xfd\
+\x9f\xdf\x88\x85\x59\x00\x3c\x9e\xfa\x68\x97\x7b\x34\x0a\xe0\xdb\
+\xf4\x87\xdb\xd8\xc1\x20\x00\x2e\xe3\x78\x1f\xcb\xcd\x01\x28\xa4\
+\x1c\x70\x74\x4f\xc6\x00\x1c\xe5\x1c\xf1\xf4\x2a\x53\x00\x52\x49\
+\x87\x5c\xbf\x0b\x43\x00\x36\xb2\x8e\xf9\xbe\x18\x02\x90\xc8\x02\
+\x70\x32\x33\x00\x1e\xa5\x01\x78\xdc\x08\x80\x40\xde\x59\xf7\x17\
+\x23\x00\x98\x3c\x00\x56\x1a\x00\xc0\x1d\x89\x63\x69\x00\xc0\x80\
+\x3c\x88\xb9\x77\x7f\x4b\x0a\xfa\x00\x97\xf2\x20\x6f\xb5\xcd\x8a\
+\x8f\x99\x4c\xf0\x22\xdb\xae\xbc\x9b\x01\x12\xfa\x00\xbd\x79\xd0\
+\x62\xdb\x7e\x82\xcb\x4d\x78\xe3\x2c\xc0\xc9\x03\x74\xe7\x41\xee\
+\xba\x2f\x93\x3d\xc5\x37\x3d\x0f\x7f\x93\x07\xe8\xca\x83\xbc\xdd\
+\xa5\x34\xb6\x5c\xde\x52\x1e\x22\x0f\xd0\xde\x09\x60\x3f\xce\x57\
+\x3e\x93\xdd\x30\x19\x54\xd4\x01\x5a\x79\x50\x38\x60\xe6\xae\x87\
+\x7f\x09\x76\xd4\x01\xfe\x7c\xa2\xe3\x61\x8b\xb8\xe7\xa1\x00\x8f\
+\xc4\x01\xfe\xcc\x83\xd6\x43\x3f\xb8\x1e\xfa\x1e\x20\x0e\x50\xdc\
+\x19\xff\xf0\x55\xe4\x4f\xda\x00\xaf\x5f\xfe\xd8\xbf\xc6\x4d\x9f\
+\x9d\xe3\x40\x1b\xe0\x4b\x1e\xe4\xdf\x94\xb6\xd4\xc3\x76\x13\xd6\
+\xb4\x01\xbe\x3c\xca\xfb\xdb\x3e\x7b\x18\x04\xb0\xa2\x0d\xf0\xf9\
+\x49\xf6\xc7\xe7\x10\x5d\x29\x35\x6d\x80\x68\x4c\xfd\xe2\x34\x04\
+\x20\xa4\x0d\xf0\x39\x0f\xba\x7d\x33\x63\x48\x3e\xe4\xd3\x06\xf8\
+\x94\x07\xb1\xdb\xeb\xd8\x43\xf6\x14\x5c\xd2\x00\x7c\x64\xf9\xc6\
+\x57\x99\x09\xc9\x00\x28\x46\x66\xed\x2f\xa6\x7f\x03\x5e\x47\xa6\
+\x6c\xf9\x80\xe2\x38\x69\x80\x74\xec\x1f\xca\x14\x56\x04\x64\x00\
+\xac\xc7\x96\xef\xae\xa7\x02\x11\x69\x80\x64\x6c\xce\x7e\x7d\x51\
+\x98\x90\x06\xf8\xf4\x0f\xbc\xaf\xc3\x6f\x6f\xf8\x5a\x20\x18\x9b\
+\xb0\xe5\x86\xaf\x06\xd9\xd8\x7f\x54\xa9\x70\x6f\x44\x02\x00\x1f\
+\x93\x07\xff\x5e\x13\x9b\x5d\x11\x2a\xc6\xe4\xc1\x1f\x43\xa8\x7b\
+\x09\xc8\x00\xc8\xc6\x6f\x63\x5e\x03\xd8\x90\x06\x48\xc7\x57\xaf\
+\xaf\x01\x1c\x69\x03\x04\xee\xc8\xa9\xea\x7c\x6d\x25\x20\x48\x03\
+\x7c\x4c\x63\x3f\xf3\x43\xba\xbd\xfb\xd3\xca\x0a\x62\x44\x8f\xce\
+\x56\x57\x00\xf6\x73\x07\x38\x19\xbf\x3d\x3e\x72\x64\x97\x01\xe2\
+\x66\xee\x00\x3b\x65\xef\x00\xa2\x00\x2f\x8a\x0a\xa2\x64\x01\x2e\
+\xd7\x03\xb6\xf3\x07\xb8\xd8\x2a\xe1\xf2\xd9\x03\xd4\x33\xe8\x14\
+\x95\xf7\x12\x60\x6f\xf3\x07\xb8\x38\x07\x3e\x37\xf3\x07\xb8\x74\
+\xde\x90\x55\xf3\x07\xe0\x6c\x06\x07\x26\xc6\x8c\xbd\xba\x57\x00\
+\x4d\x80\x58\x4d\x7f\x1c\x59\x00\xe1\xaa\x68\x0b\x20\x0c\x70\xa9\
+\x47\xe6\x64\x03\xc0\x4a\x51\x9f\x3c\x55\x80\x0b\xef\x00\x9f\xdb\
+\x00\xb0\x55\xb4\x0c\x26\x0b\xd0\xdf\x1e\xf2\xd4\xd8\x00\xd0\xbf\
+\x0e\x08\xce\x56\x00\xf4\x96\x02\x98\x61\x37\x48\xdc\x39\x72\x85\
+\x29\x10\x49\x80\x48\xc5\x56\x00\x61\x80\xde\x7a\x78\x28\xec\x00\
+\xe8\xfb\x02\xb8\x55\x63\x05\x40\xdf\x2b\x80\x49\xbc\x4e\x8c\x14\
+\x40\xdf\x99\xf3\xb4\xb1\x03\x60\x27\xbd\x23\x8a\x36\x40\xdf\x61\
+\x91\xb8\xb1\x04\xa0\x67\x19\xb8\x14\x96\x00\xf4\xcc\x80\x0b\xc9\
+\xf7\x8a\x92\x01\xe0\xdd\xab\xa0\x50\xf6\xa5\xa2\x64\x00\x12\x3d\
+\xf1\x93\x01\xc8\x34\xc5\x4f\x05\xa0\xf6\x34\xc5\x4f\x05\xa0\xf3\
+\xde\xa1\x85\x8a\x7b\xd6\x69\x00\x74\xde\x38\x11\x9d\x1b\x5b\x00\
+\x72\xa6\xfe\xfd\x4f\x09\xa0\x73\x02\x58\x29\xba\x5e\x9e\x00\x80\
+\x58\x28\xcf\x7f\x69\x01\x24\x8a\xb6\x40\xa8\x02\xec\x54\x6c\x82\
+\x13\x06\xc8\x98\xe2\xf5\x2f\x31\x80\xc2\x95\x7a\x1a\x80\x3c\x40\
+\xe5\xc9\xee\x03\xa4\x0d\xc0\x03\xb5\xf5\x2f\x6a\x00\xe7\xf6\x0b\
+\x90\xed\x1b\x7b\x00\x44\xa4\xe8\xfa\x6c\xaa\x00\xed\x1a\x18\xcb\
+\x1a\x8b\x00\x62\x55\x17\xc8\x13\x05\xe8\x88\x3f\x6f\x2c\x02\x88\
+\x95\x5c\x9d\x4e\x17\x20\x56\xf6\x13\x12\x34\x01\xda\xf3\x9f\x57\
+\x36\xf6\x00\x88\xf6\x55\x41\x7e\xd5\xd8\x03\xd0\x11\x7f\xa0\x2b\
+\x7e\x1d\x00\xe7\x76\xfe\x13\xd6\x8d\x3d\x00\x7c\xa1\xa5\xfc\x4d\
+\x06\x80\x87\x7a\xca\xdf\x54\x00\xea\x76\xfc\x91\x68\xec\x01\xa8\
+\x03\x5d\xe5\x6f\x1a\x00\xd5\x37\x6d\xe5\x6f\x12\x00\x95\xaf\xaf\
+\xfc\x4d\x01\xa0\xf4\x35\x96\xbf\x09\x00\x14\x9e\xce\xf2\xb7\x7e\
+\x80\xe2\x41\x6b\xf9\x5b\x3b\xc0\xc9\xd5\x5b\xfe\xd6\x0d\x90\xbb\
+\xca\xfa\xbf\x49\x02\x1c\x5d\xdd\xe5\x6f\xbd\x00\xaf\x4c\x7b\xf9\
+\x5b\x2b\x40\x7b\xff\x4f\x7d\xf9\x5b\x27\xc0\x81\x11\x28\x7f\x6b\
+\x04\xd8\x33\x0a\xe5\x6f\x7d\x00\x29\x8d\xf2\xb7\x36\x80\x1d\x91\
+\xf2\xb7\x2e\x80\x2d\x95\xf2\xb7\x26\x80\x76\x03\xa0\x3f\x45\xf9\
+\x5b\x70\x43\x00\x7e\x8c\x3a\xfe\x24\xf8\x5b\x59\x9c\xf2\xec\xb0\
+\x4f\xb7\x9b\xf5\x4b\x12\xaf\x96\x51\x18\xf8\x0f\xec\xfe\xdb\x4a\
+\x15\x03\x74\x5d\x07\x53\xb7\xc3\xac\xab\xf7\x30\x5f\xdf\xc3\xdc\
+\xbd\x87\xf9\xfc\x2b\xcc\xef\x81\xef\xb9\x6a\xae\x93\x92\x09\xf0\
+\xd4\x79\x0b\x4a\xba\xdb\xbe\x87\x99\xbc\x87\xb9\xb8\x1a\x66\xff\
+\x48\x0d\x00\x90\xf7\xcb\xb3\x53\xde\xac\x2c\x0f\x20\x96\x19\x3f\
+\xfd\x39\x40\xac\xa4\xc6\x3f\xdd\x6d\x22\x92\x00\xc4\x52\x6e\xfc\
+\x4e\x49\x1b\x40\x44\x92\xe3\x9f\xee\x17\x07\xe5\xfc\xda\xdc\x42\
+\x76\xfc\x0e\xa7\x0c\xa0\x20\x7e\xe7\x4c\x18\x80\x87\xf2\xe3\x77\
+\x04\x5d\x80\x3a\x50\x10\xff\x74\xd9\xfa\xe4\x00\x6f\x4a\xe2\xa7\
+\x0b\x50\xf9\x8e\xd5\x00\xa5\xa2\xf8\xa9\x02\x94\x9e\x63\x35\x40\
+\xa1\x2c\x7e\xa2\x00\x2b\x07\x00\x00\x00\x00\x00\x00\xa0\x62\x08\
+\xdb\x01\x38\x00\x2c\x07\xa8\x6d\x07\xa8\x6c\x07\x28\x6c\x07\xa0\
+\x5e\x16\x37\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x60\x2b\x80\
+\x6d\x03\x00\x00\x00\xc0\xff\x00\xf6\x0e\x00\x00\x00\x00\x00\xb0\
+\x7a\xfc\x0b\x43\xd4\xc6\xc6\x44\x07\xe4\xaa\x00\x00\x00\x00\x49\
+\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x09\x13\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x03\x00\x00\x00\x6b\xac\x58\x54\
+\x00\x00\x00\xed\x50\x4c\x54\x45\x78\x00\xf8\x80\x00\xf8\x80\x04\
+\xf8\x80\x08\xf8\x80\x0c\xf8\x88\x10\xf8\x88\x14\xf8\x88\x18\xf8\
+\x88\x1c\xf8\x88\x20\xf8\x90\x20\xf8\x90\x24\xf8\x90\x28\xf8\x90\
+\x2c\xf8\x90\x30\xf8\x98\x30\xf8\x98\x34\xf8\x98\x38\xf8\x98\x3c\
+\xf8\x98\x40\xf8\xa0\x40\xf8\xa0\x44\xf8\xa0\x48\xf8\xa0\x4c\xf8\
+\xa0\x50\xf8\xa8\x50\xf8\xa8\x54\xf8\xa8\x58\xf8\xa8\x5c\xf8\xa8\
+\x60\xf8\xb0\x60\xf8\xb0\x64\xf8\xb0\x68\xf8\xb0\x6c\xf8\xb0\x70\
+\xf8\xb8\x70\xf8\xb8\x74\xf8\xb8\x78\xf8\xb8\x7c\xf8\xb8\x80\xf8\
+\xc0\x80\xf8\xc0\x84\xf8\xc0\x88\xf8\xc0\x8c\xf8\xc0\x90\xf8\xc8\
+\x90\xf8\xc8\x94\xf8\xc8\x98\xf8\xc8\x9c\xf8\xc8\xa0\xf8\xd0\xa0\
+\xf8\xd0\xa4\xf8\xd0\xa8\xf8\xd0\xac\xf8\xd0\xb0\xf8\xd8\xb0\xf8\
+\xd8\xb4\xf8\xd8\xb8\xf8\xd8\xbc\xf8\xd8\xc0\xf8\xe0\xc0\xf8\xe0\
+\xc4\xf8\xe0\xc8\xf8\xe0\xcc\xf8\xe0\xd0\xf8\xe8\xd0\xf8\xe8\xd4\
+\xf8\xe8\xd8\xf8\xe8\xdc\xf8\xe8\xe0\xf8\xf0\xe0\xf8\xf0\xe4\xf8\
+\xf0\xe8\xf8\xf0\xec\xf8\xf0\xf0\xf8\xf8\xf0\xf8\xf8\xf4\xf8\xf8\
+\xf8\xf8\xf8\xfc\xf8\x09\xd1\x39\xc7\x00\x00\x00\x09\x70\x48\x59\
+\x73\x00\x00\x00\x48\x00\x00\x00\x48\x00\x46\xc9\x6b\x3e\x00\x00\
+\x07\xcc\x49\x44\x41\x54\x78\xda\xed\xdd\x69\x43\xda\x4c\x10\x00\
+\xe0\x1c\x50\x90\xa3\x28\x2d\x52\x81\xaa\x78\x03\xe5\xa8\x82\x22\
+\x45\xa8\x81\x0a\x91\x64\xfe\xff\xcf\xe9\x87\xbe\xaf\x72\xe4\xce\
+\x26\x66\x36\xb3\xdf\x23\xd9\x47\xc8\x31\x3b\x33\x2b\x40\xcc\x87\
+\x40\x00\x04\x40\x00\x04\x40\x00\x20\xc4\x70\x10\x00\x01\x10\xc0\
+\x26\x40\xac\x2e\x7d\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\
+\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\
+\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\
+\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\x04\x40\x00\xac\x87\
+\xae\x0c\x5a\x67\x95\x2f\xf9\x74\x52\x96\x04\x29\xf1\x29\x9d\x2d\
+\x56\xce\x5b\x7d\x45\x8f\x03\x80\xd2\x3d\xfe\x2c\x99\xa4\x2c\x4a\
+\x85\x5a\x67\xc6\x33\xc0\xea\xae\x96\xb2\x4d\xdc\x4c\x55\x6f\x5f\
+\xb9\x04\xd0\xee\x0e\x25\x87\xc9\xab\xd2\xb7\xbe\xc6\x1b\xc0\xe4\
+\x58\x76\x95\xc0\x9b\x38\x9f\x73\x04\xa0\xff\x2c\xb8\xcf\x61\x16\
+\x2b\x13\x4e\x00\x5e\x1b\x9f\x3c\xe6\x71\x57\xe7\x1c\x00\xa8\x57\
+\x09\xef\x99\xec\xd2\xf9\x0a\x39\xc0\xab\x9f\xe9\x0b\x82\x20\x64\
+\xc6\x98\x01\xb4\x56\xd2\x77\x39\x83\x78\xa6\xa1\x05\xb8\x4b\x33\
+\xa9\xe8\x38\x58\xe2\x04\x50\xf7\x59\xd5\xb4\xa4\x9f\x51\x02\x3c\
+\xb0\xab\xea\x91\xc7\x18\x01\xae\x18\xd6\x35\x25\x9e\x10\x02\x1c\
+\xb2\xac\xec\x4a\x4c\xf1\x01\x24\x59\x02\x08\xa9\x25\x36\x80\x39\
+\xe3\xea\xbe\xa2\x8e\x0c\xe0\x8e\x75\x7d\xe3\x05\x32\x80\x73\xd6\
+\x00\xe2\x04\x17\xc0\x01\xf3\x12\xd7\x7d\x54\x00\xba\xcc\x1c\x40\
+\xe8\x60\x02\xf8\x1d\x40\x95\x73\x4a\x47\x04\xd0\x0d\xa2\xce\xfb\
+\x16\x11\xc0\x49\x10\x00\x79\x44\x00\xf9\x40\x4a\xfd\x27\x68\x00\
+\x34\xd1\xf4\x6e\x96\xab\x5c\x77\x87\x4f\x53\x45\x99\x8e\x07\x9d\
+\xcb\xf2\x9e\x1b\x80\x4b\x34\x00\x63\x93\x17\xdb\xb3\xe1\x4e\x8c\
+\x6b\xd9\x3f\x71\x1c\x33\xcc\xa1\x01\x68\x19\x86\x79\x47\x66\xf7\
+\xcc\x61\xd9\xa1\xc0\x1c\x0b\x40\xd5\x20\xc4\x6b\xb9\xe8\xa5\x54\
+\x1c\x01\x0c\xb0\x00\x64\x76\xbe\xbc\xb6\x31\x8d\x51\xd6\x01\xc0\
+\x15\x12\x80\xe5\xf6\x89\x9f\x38\x88\x6c\xae\x6a\xf6\x00\x65\x24\
+\x00\xc3\xad\x5f\x7f\xcf\xd9\x61\x0d\x5b\x80\xcf\x48\x00\x6e\x36\
+\x97\x37\x86\x4e\x8f\x6b\xdb\x2e\x13\x20\x01\xd8\x08\x87\x89\xf7\
+\xce\x0f\xbc\xb0\x01\x48\x22\x01\xd8\xb8\xb1\xf7\xdc\x1c\xf9\xc5\
+\x26\x28\x80\x03\xe0\xcf\xc6\xf5\xcf\x5d\x24\xcd\x7a\x29\x4d\xc6\
+\x01\xd0\x5f\x7f\x81\xd1\xfc\x5c\x3e\x90\xfe\x04\xd6\x7e\xc9\xa2\
+\xdb\x78\xf6\xca\x32\x9a\x9c\xc6\x01\x50\xf4\x13\xca\xb4\x0c\x26\
+\x16\x71\x00\xbc\x87\xc3\x92\xee\xf3\x9d\x9e\x2d\x53\x26\x50\x00\
+\xac\x4d\xe1\x07\x8b\xc7\xe8\xb5\x71\x83\x02\xa0\xe7\x2f\x8a\x67\
+\x15\x4c\x1a\xa2\x00\x38\x7d\x3b\xdf\x06\xeb\x70\xe2\x12\x05\xc0\
+\x5b\x4a\x98\xac\x7a\x39\xfc\x97\xf9\xfc\x0b\x28\x02\x22\xda\x5b\
+\x3e\xe4\x77\x4f\xc7\xbf\x84\xf7\x36\x1c\x0c\xc0\xd3\xdb\xf9\x7a\
+\xcb\x6b\x50\xcd\x01\x7e\xa3\x00\x68\xfb\x7c\x75\xd3\x43\x5c\x1c\
+\x0b\x04\xa0\xea\x73\x3d\x57\x33\x05\xe8\xe1\x00\xc8\xfa\x8c\xe2\
+\x2f\x4d\x9f\x83\x91\x2c\x8d\xfd\xec\xfd\x1b\x3f\x3d\x1e\x3f\xe3\
+\x62\x71\x94\x5d\x3c\xed\x3d\xae\xaa\xc7\x04\xc0\x2c\x2e\xf6\x0b\
+\x62\x02\x70\x6c\x3c\xff\x13\x88\x0b\x80\xf1\xcb\x50\x4e\x8b\x0b\
+\x80\x71\x7a\x99\x1c\x4c\xba\x6c\x14\x01\x9a\x86\xc1\xd0\x07\x88\
+\x0d\x40\xce\x08\xe0\x07\xc4\x06\x60\x64\x34\xff\x06\xc4\x07\xa0\
+\x18\x42\x1c\x28\xca\x00\x06\x49\xf6\x62\x07\xe2\x03\xf0\xba\x5b\
+\x64\x22\x0f\x20\x46\x00\xbb\x2b\xe4\x7b\x53\x88\x11\xc0\x6e\x66\
+\x4d\x49\x85\x18\x01\x0c\xb6\x73\xcb\xa4\x56\xc0\x9f\x18\x2d\x80\
+\xbb\xed\xf9\xe7\x7e\x43\x9c\x00\x1a\x5b\xf3\x97\xae\x83\x6f\xa8\
+\x10\x21\x80\xe5\x76\xa6\x5c\x51\x09\xe1\x53\xa3\x03\xd0\xdb\x5a\
+\x14\x4e\xdf\x85\xf2\xb1\x51\x01\x18\x6c\xa5\x16\xcb\x57\xdc\x35\
+\x50\xb0\xfa\xf2\xb7\xb6\xde\x7f\xa4\xfa\x32\xac\xcf\xfe\x78\x00\
+\xa5\x55\x92\x76\x6a\xe6\x07\x53\x95\x53\x00\x75\xf9\xdf\x58\xcc\
+\x95\xa7\x41\xab\x5e\x34\xcd\x08\x4a\xee\xd7\x1a\xc3\x05\x6f\x00\
+\xaa\xe8\xb6\x6c\xba\xda\x7d\xe1\x09\x60\xe0\xa5\x48\xa2\xd0\x5c\
+\x70\x03\xe0\xb1\x8e\x46\xac\x3c\x71\x02\xb0\x27\x78\x1d\xa5\x09\
+\x0f\x00\x33\x3f\xe5\x42\xd5\x17\xfc\x00\x1d\x7f\x15\xf4\x3d\xf4\
+\x00\x65\xc1\xdf\x38\x5a\xe1\x06\xd0\x7d\x76\xd4\x11\x84\xac\x82\
+\x1a\x60\xec\xbf\x6e\x30\xf9\x84\x19\x80\x45\x53\x11\xf9\x11\x31\
+\x00\x93\xb6\x3a\xf2\x08\x2d\x80\xeb\xe7\x60\x93\x9b\x81\x82\x15\
+\xa0\xcf\xa8\x7e\x38\xa3\x22\x05\x60\x56\x4f\x5e\x46\x0a\x90\x66\
+\x05\x20\x74\x51\x02\xcc\x98\xcd\x5f\x48\x2c\x30\x02\x6c\xa7\x3e\
+\x89\x92\x77\x81\x1a\x46\x80\x7f\xa9\x4f\x99\xf2\x45\xe7\x61\x32\
+\x57\x35\x00\x00\x6d\x39\x1b\xf5\xae\xca\x29\xf7\x02\x53\x84\x00\
+\xfa\x65\xf1\xfa\xd1\xb8\x80\x66\x71\x5b\x71\xf9\x94\x5c\xe1\x2a\
+\x2a\x0c\x00\xa0\xdf\x1f\xba\x79\x4c\x10\xe7\xbc\x01\x00\xc0\xfc\
+\xd8\x05\xc1\x25\x87\x00\x00\xb3\x23\xe7\x2d\x85\xb8\x04\x00\x18\
+\x38\xee\x26\x32\xe6\x13\x00\x96\xa5\x70\x7b\xcb\x45\x2f\x49\x4a\
+\xaf\x3b\x03\xf8\xcc\x2b\x80\x49\xa6\xe8\xee\x50\xb9\x05\xb0\xa9\
+\x1f\xff\x7f\x8c\xf8\x05\x58\x2b\xbc\xb4\x18\x2d\x8e\x01\x74\x27\
+\xcd\x18\x4f\x39\x06\x80\x85\x83\x27\xe3\x12\xcf\x00\x4e\x96\x50\
+\xf2\x5c\x03\x38\x08\xa0\xa6\xf8\x06\x18\xd9\x47\x45\xf8\x06\xb0\
+\xff\x0a\x48\x9c\x03\xd8\xe6\x52\x88\x9c\x03\xe8\x76\xad\xc9\x93\
+\x9c\x03\xd8\x46\xd1\x33\xbc\x03\x3c\xda\xa5\x0e\xf1\x0e\xb0\xb2\
+\x89\x0f\x7d\xe5\x1d\xc0\xee\x3e\x70\xc4\x3d\x40\x3d\xc6\xef\x02\
+\x00\x60\xdb\x5c\xb1\xc3\x3d\xc0\xd0\x1a\xe0\x89\x7b\x00\xc5\xfa\
+\x39\x48\xe3\x1e\x60\x11\x46\x8f\xe9\x28\x03\xbc\x0a\x21\xb4\x95\
+\x8b\x32\x80\x6e\x09\xd0\xe6\x1f\x40\xb3\x04\x78\x89\x2c\x80\xfa\
+\xc0\xa8\xd6\x7d\x69\x35\x7f\x56\x3d\xa5\x18\x03\xa8\xf7\xe7\x05\
+\x91\x55\xd3\x3f\xcb\x9d\x9a\x1a\x51\x04\xb8\xcc\x8b\x2c\xff\x3d\
+\x13\x2b\x80\x59\x14\x01\xde\x5b\x1f\x30\x49\xe7\xec\x87\xb1\xd1\
+\x02\x53\x80\xb3\xb7\xf3\x3b\x60\x71\x6e\x8d\xe0\xef\x01\x8c\x01\
+\xd6\x76\x17\x63\xd1\xf3\xe5\xbb\x45\x34\x48\x8b\x24\x80\xc2\x36\
+\x68\x9f\x0d\xa3\xb1\x24\xdb\xbb\xc0\xda\xee\x5a\xfe\xb7\x44\xb2\
+\xb8\x0b\x4a\x51\xcd\x13\x5c\x5b\xd2\x4b\xfb\xfe\x92\x5a\x84\x85\
+\x19\x76\x15\x63\x0b\x70\xca\xf2\x5b\x6a\xbe\xdf\x86\x34\x8f\x2a\
+\xc0\x7a\x43\x60\xf9\x8f\xcf\x07\xe1\x44\x28\xad\x65\xd9\x02\x4c\
+\x18\xe6\x74\x9b\xff\x02\xd2\x5a\x64\x01\x36\xf7\xd7\xf2\xd7\x01\
+\xe1\x4b\x38\x5b\x0d\x31\x7e\x17\xd8\xb8\x73\x25\xfd\x34\x01\x98\
+\x06\x9c\x17\x10\x10\xc0\xe6\x6e\x51\x87\xc0\xea\x2f\xad\x2f\x0a\
+\xcf\xa2\x0c\x70\xbd\x79\xb2\x4d\xcf\x7f\xc8\xbc\xc2\xae\x0f\x51\
+\x06\xd8\xba\x72\x89\x9e\x33\xb9\x0a\xc1\xae\x06\x04\x06\x30\x63\
+\x54\xe1\x65\x9a\x2a\x58\xd0\xa2\x0d\xa0\x6f\x57\x81\xec\x79\x8a\
+\x5c\x4d\xcc\x8a\x49\x12\xac\x77\xdb\x63\x1e\x12\xdb\xd9\x68\x33\
+\xeb\xe1\xb1\x5d\x35\xdb\x63\x43\x62\xbd\xbf\x04\x7b\x80\xdd\x6d\
+\x06\xb3\xae\x9f\x08\x35\xb3\x2c\x41\x31\x80\xde\x4a\xac\x01\x0c\
+\x82\x18\x29\x97\xfd\x70\xf5\x72\x88\xad\xc5\x99\x03\x18\x3d\xc0\
+\x26\xee\xdd\xfc\x85\x55\x29\xe8\x38\x68\xa0\x00\xc6\xc5\x81\x75\
+\xe7\xd7\xee\xc5\x7e\xc0\x05\x02\x01\x03\x80\xf1\xf5\x3b\xeb\xb4\
+\x2f\xfa\xd0\xb4\x62\xa4\x09\x38\x00\xcc\xf6\x5b\xae\x3a\xb9\x16\
+\xae\xce\x4c\x43\x00\x41\xf5\x96\x63\x0e\x50\x35\x9d\x42\xdd\xf6\
+\x91\xe0\xd6\xb4\x82\x32\x31\x02\x2c\x00\x16\xb1\x6c\xa9\x6a\x95\
+\xd3\xa0\xf7\x72\xe6\x11\x80\x67\x40\x03\x60\x9d\xe0\x99\xbd\x31\
+\x79\x36\x9e\x5e\x58\xd4\xcf\x1e\x06\xd8\x5c\x8f\x39\x80\x6d\x8d\
+\x78\xe6\xe4\x76\xeb\x85\x76\xd1\xaf\x5b\xed\x38\x2c\xfd\x00\x40\
+\x04\x00\x4e\x6a\xc2\xe5\x42\xe5\xac\xd1\xe9\x76\xdb\x8d\xcb\xea\
+\x81\x4d\xa5\x60\x36\xd0\xbe\xca\x01\x00\xe4\x05\xa6\xe3\x78\x05\
+\xc8\x00\xaa\x2c\xa7\x9f\x1f\x03\x60\x03\x68\xb0\x9b\x7e\xa2\x8d\
+\xb1\xaf\xf0\x03\xb3\xf9\xd7\xc2\xe8\xac\xca\x1e\x60\xce\x68\xfa\
+\x47\x53\x00\x94\x00\xeb\x2b\xa4\x9e\x87\x58\x7d\x06\xc0\x0a\xe0\
+\xbf\x61\x96\x58\x9b\x01\xe0\x05\xf0\xdb\x2f\x29\xdb\x5c\x00\x60\
+\x06\x80\xc7\x6f\xde\x9b\x86\xc9\xdf\xc7\x10\xea\x08\x26\x51\x72\
+\x71\x93\xf3\x34\xfb\x72\x6f\x05\xc0\x03\x00\x00\x4c\x2f\x32\x2e\
+\x5b\xa4\xd5\x1f\x35\x08\x7f\x04\x99\x2a\xab\xb4\x4a\xce\xee\x08\
+\x62\xae\xd6\x56\xe0\x63\x46\xc0\xb9\xc2\xfa\xb4\x5d\xcd\x5b\x29\
+\xc8\xd9\x4a\x73\xb4\x82\x8f\x1b\xa1\x24\x4b\xcf\x87\xdd\xab\xe3\
+\xc3\x62\x3e\x9d\x4c\xc8\x92\x20\x25\x52\x99\xfc\xfe\xd7\xf2\x69\
+\xb3\x3f\x59\xc0\x47\x8f\x28\x67\x8b\x13\x00\x01\x10\x00\x01\x10\
+\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\
+\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\x10\x00\x01\
+\x10\x00\x01\x10\x00\x01\x10\x40\x80\x00\x71\x1b\x04\x40\x00\x04\
+\xf0\x0e\x10\xdf\x41\x00\x04\x40\x00\x04\x10\xeb\xf1\x17\xe9\x89\
+\x47\x68\xda\x1b\x7c\x00\x00\x00\x00\x00\x49\x45\x4e\x44\xae\x42\
+\x60\x82\
+"
+
+qt_resource_name = b"\
+\x00\x06\
+\x07\x03\x7d\xc3\
+\x00\x69\
+\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
+\x00\x09\
+\x0a\x87\xa4\xa7\
+\x00\x73\
+\x00\x69\x00\x64\x00\x65\x00\x34\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x09\
+\x0a\x88\xa4\xa7\
+\x00\x73\
+\x00\x69\x00\x64\x00\x65\x00\x35\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x09\
+\x0a\x89\xa4\xa7\
+\x00\x73\
+\x00\x69\x00\x64\x00\x65\x00\x36\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x09\
+\x0a\x84\xa4\xa7\
+\x00\x73\
+\x00\x69\x00\x64\x00\x65\x00\x31\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x09\
+\x0a\x85\xa4\xa7\
+\x00\x73\
+\x00\x69\x00\x64\x00\x65\x00\x32\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x09\
+\x0a\x86\xa4\xa7\
+\x00\x73\
+\x00\x69\x00\x64\x00\x65\x00\x33\x00\x2e\x00\x70\x00\x6e\x00\x67\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x02\
+\x00\x00\x00\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x16\x7f\
+\x00\x00\x00\x72\x00\x00\x00\x00\x00\x01\x00\x00\x1a\x97\
+\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x01\x00\x00\x21\x83\
+\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x00\x2a\x00\x00\x00\x00\x00\x01\x00\x00\x05\x42\
+\x00\x00\x00\x42\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xed\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/script/helloscript.py b/examples/script/helloscript.py
new file mode 100755
index 000000000..5ae659f8a
--- /dev/null
+++ b/examples/script/helloscript.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the script/helloscript example from Qt v5.x"""
+
+import sys
+from PySide2 import QtWidgets, QtScript
+
+
+app = QtWidgets.QApplication(sys.argv)
+
+engine = QtScript.QScriptEngine()
+
+button = QtWidgets.QPushButton()
+scriptButton = engine.newQObject(button)
+engine.globalObject().setProperty("button", scriptButton)
+
+engine.evaluate("button.text = 'Hello World from PySide2!'")
+engine.evaluate("button.styleSheet = 'font-style: italic'")
+engine.evaluate("button.show()")
+
+sys.exit(app.exec_())
diff --git a/examples/scriptableapplication/CMakeLists.txt b/examples/scriptableapplication/CMakeLists.txt
new file mode 100644
index 000000000..40e29346a
--- /dev/null
+++ b/examples/scriptableapplication/CMakeLists.txt
@@ -0,0 +1,187 @@
+cmake_minimum_required(VERSION 3.1)
+cmake_policy(VERSION 3.1)
+
+# Enable policy to run automoc on generated files.
+if(POLICY CMP0071)
+ cmake_policy(SET CMP0071 NEW)
+endif()
+
+project(scriptableapplication)
+
+# Set CPP standard to C++11 minimum.
+set(CMAKE_CXX_STANDARD 11)
+
+# Find required Qt packages.
+find_package(Qt5 5.9 REQUIRED COMPONENTS Core Gui Widgets)
+
+# Macro to get various pyside / python include / link flags.
+macro(pyside2_config option output_var)
+ if(${ARGC} GREATER 2)
+ set(is_list ${ARGV2})
+ else()
+ set(is_list "")
+ endif()
+
+ execute_process(
+ COMMAND python "${CMAKE_SOURCE_DIR}/pyside2_config.py" ${option}
+ OUTPUT_VARIABLE ${output_var}
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ if ("${${output_var}}" STREQUAL "")
+ message(FATAL_ERROR "Got empty string when running: pyside2_config.py ${option}")
+ endif()
+ if(is_list)
+ string (REPLACE " " ";" ${output_var} "${${output_var}}")
+ endif()
+endmacro()
+
+# Get relevant general paths, include paths and linker flags.
+pyside2_config(--pyside2 PYSIDE2_PATH)
+set(SHIBOKEN_PATH "${PYSIDE2_PATH}/shiboken2")
+
+if(NOT EXISTS ${SHIBOKEN_PATH})
+ message(FATAL_ERROR "Shiboken executable not found at path: ${SHIBOKEN_PATH}")
+endif()
+
+pyside2_config(--python-include PYTHON_INCLUDE_DIR)
+pyside2_config(--pyside2-include PYSIDE2_INCLUDE_DIR 1)
+pyside2_config(--python-link-cmake PYTHON_LINKING_DATA 1)
+pyside2_config(--pyside2-shared-libraries-cmake PYSIDE2_SHARED_LIBRARIES 1)
+
+# Get all relevant Qt include dirs, to pass them on to shiboken.
+get_property(QT_CORE_INCLUDE_DIRS TARGET Qt5::Core PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+get_property(QT_GUI_INCLUDE_DIRS TARGET Qt5::Gui PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+get_property(QT_WIDGETS_INCLUDE_DIRS TARGET Qt5::Widgets PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
+set(QT_INCLUDE_DIRS ${QT_CORE_INCLUDE_DIRS} ${QT_GUI_INCLUDE_DIRS} ${QT_WIDGETS_INCLUDE_DIRS})
+set(INCLUDES "")
+foreach(INCLUDE_DIR ${QT_INCLUDE_DIRS})
+ list(APPEND INCLUDES "-I${INCLUDE_DIR}")
+endforeach()
+
+# Set up the options to pass to shiboken.
+set(WRAPPED_HEADER ${CMAKE_SOURCE_DIR}/wrappedclasses.h)
+set(TYPESYSTEM_FILE ${CMAKE_SOURCE_DIR}/scriptableapplication.xml)
+
+set(SHIBOKEN_OPTIONS --generator-set=shiboken --enable-parent-ctor-heuristic
+ --enable-pyside-extensions --enable-return-value-heuristic --use-isnull-as-nb_nonzero
+ --avoid-protected-hack
+ ${INCLUDES}
+ -I${CMAKE_SOURCE_DIR}
+ -T${CMAKE_SOURCE_DIR}
+ -T${PYSIDE2_PATH}/typesystems
+ --output-directory=${CMAKE_CURRENT_BINARY_DIR}
+ )
+
+# Specify which sources will be generated by shiboken, and their dependencies.
+set(GENERATED_SOURCES
+ ${CMAKE_CURRENT_BINARY_DIR}/AppLib/applib_module_wrapper.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/AppLib/mainwindow_wrapper.cpp)
+
+set(GENERATED_SOURCES_DEPENDENCIES
+ ${WRAPPED_HEADER}
+ ${TYPESYSTEM_FILE}
+ )
+
+# Add custom target to run shiboken.
+add_custom_command(OUTPUT ${GENERATED_SOURCES}
+ COMMAND ${SHIBOKEN_PATH}
+ ${SHIBOKEN_OPTIONS} ${WRAPPED_HEADER} ${TYPESYSTEM_FILE}
+ DEPENDS ${GENERATED_SOURCES_DEPENDENCIES}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Running generator for ${TYPESYSTEM_FILE}.")
+
+# Set the CPP files.
+set(SOURCES
+ mainwindow.cpp
+ pythonutils.cpp
+ ${GENERATED_SOURCES}
+ )
+
+# We need to include the headers for the module bindings that we use.
+set(PYSIDE2_ADDITIONAL_INCLUDES "")
+foreach(INCLUDE_DIR ${PYSIDE2_INCLUDE_DIR})
+ list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtCore")
+ list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtGui")
+ list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWidgets")
+endforeach()
+
+# =============================================================================================
+# !!! (The section below is deployment related, so in a real world application you will want to
+# take care of this properly with some custom script or tool).
+# =============================================================================================
+# Enable rpaths so that the example can be executed from the build dir.
+set(CMAKE_SKIP_BUILD_RPATH FALSE)
+set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
+SET(CMAKE_INSTALL_RPATH "")
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+# =============================================================================================
+# !!! End of dubious section.
+# =============================================================================================
+
+# Declare executable so we can enable automoc.
+add_executable(${PROJECT_NAME} main.cpp)
+
+# Enable automoc.
+set_property(TARGET ${PROJECT_NAME} PROPERTY AUTOMOC 1)
+
+# Add the rest of the sources.
+target_sources(${PROJECT_NAME} PUBLIC ${SOURCES})
+
+# Apply relevant include and link flags.
+target_include_directories(${PROJECT_NAME} PRIVATE ${PYTHON_INCLUDE_DIR})
+target_include_directories(${PROJECT_NAME} PRIVATE ${PYSIDE2_INCLUDE_DIR})
+target_include_directories(${PROJECT_NAME} PRIVATE ${PYSIDE2_ADDITIONAL_INCLUDES})
+target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR})
+
+target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Widgets)
+target_link_libraries(${PROJECT_NAME} PRIVATE ${PYSIDE2_SHARED_LIBRARIES})
+
+# Find and link to the python library.
+list(GET PYTHON_LINKING_DATA 0 PYTHON_LIBDIR)
+list(GET PYTHON_LINKING_DATA 1 PYTHON_LIB)
+find_library(PYTHON_LINK_FLAGS ${PYTHON_LIB} HINTS ${PYTHON_LIBDIR})
+target_link_libraries(${PROJECT_NAME} PRIVATE ${PYTHON_LINK_FLAGS})
+
+# Same as CONFIG += no_keywords to avoid syntax errors in object.h due to the usage of the word Slot
+target_compile_definitions(${PROJECT_NAME} PRIVATE QT_NO_KEYWORDS)
+
+if(WIN32)
+ # =============================================================================================
+ # !!! (The section below is deployment related, so in a real world application you will want to
+ # take care of this properly (this is simply to eliminate errors that users usually encounter.
+ # =============================================================================================
+ # Circumvent some "#pragma comment(lib)"s in "include/pyconfig.h" which might force to link
+ # against a wrong python shared library.
+
+ set(PYTHON_VERSIONS_LIST 3 32 33 34 35 36 37 38)
+ set(PYTHON_ADDITIONAL_LINK_FLAGS "")
+ foreach(VER ${PYTHON_VERSIONS_LIST})
+ set(PYTHON_ADDITIONAL_LINK_FLAGS
+ "${PYTHON_ADDITIONAL_LINK_FLAGS} /NODEFAULTLIB:\"python${VER}_d.lib\"")
+ set(PYTHON_ADDITIONAL_LINK_FLAGS
+ "${PYTHON_ADDITIONAL_LINK_FLAGS} /NODEFAULTLIB:\"python${VER}.lib\"")
+ endforeach()
+
+ set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "${PYTHON_ADDITIONAL_LINK_FLAGS}")
+
+ # Add custom target to hard link PySide2 shared libraries (just like in qmake example), so you
+ # don't have to set PATH manually to point to the PySide2 package.
+ foreach(LIBRARY_PATH ${PYSIDE2_SHARED_LIBRARIES})
+ string(REGEX REPLACE ".lib$" ".dll" LIBRARY_PATH ${LIBRARY_PATH})
+ get_filename_component(BASE_NAME ${LIBRARY_PATH} NAME)
+ file(TO_NATIVE_PATH ${LIBRARY_PATH} SOURCE_PATH)
+ file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME}" DEST_PATH)
+ add_custom_command(OUTPUT "${BASE_NAME}"
+ COMMAND mklink /H "${DEST_PATH}" "${SOURCE_PATH}"
+ DEPENDS ${LIBRARY_PATH}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ COMMENT "Creating hardlink to PySide2 shared library ${BASE_NAME}")
+
+ # Fake target that depends on the previous one, but has special ALL keyword, which means
+ # it will always be executed.
+ add_custom_target("fake_${BASE_NAME}" ALL DEPENDS ${BASE_NAME})
+ endforeach()
+ # =============================================================================================
+ # !!! End of dubious section.
+ # =============================================================================================
+endif()
diff --git a/examples/scriptableapplication/README.CMake.txt b/examples/scriptableapplication/README.CMake.txt
new file mode 100644
index 000000000..ea658efd5
--- /dev/null
+++ b/examples/scriptableapplication/README.CMake.txt
@@ -0,0 +1,28 @@
+For general information read README.txt instead.
+
+To build this example you will need:
+* A recent version of CMake (3.1+)
+* Make sure that a --standalone PySide2 package (bundled with Qt libraries) is installed into the
+ current active Python environment (system or virtualenv)
+* qmake to be in your PATH (so that CMake find_package(Qt5) works; used for include headers)
+* use the same Qt version for building the example application, as was used for building
+* PySide2, this is to ensure binary compatibility between the newly generated bindings libraries,
+ the PySide2 libraries and the Qt libraries.
+
+For Windows you will also need:
+* Visual studio environment to be active in your terminal
+* Correct visual studio architecture chosen (32 vs 64 bit)
+* Make sure that your Qt + Python + PySide + CMake app build configuration is the same (either or
+ all Release (which is more likely) or all Debug).
+
+You can build this example by executing the following commands (slightly adapted to your file
+system) in a terminal:
+
+cd ~/pyside-setup/examples/scriptableapplication
+(or cd C:\pyside-setup\examples\scriptableapplication)
+mkdir build
+cd build
+cmake -H.. -B. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release
+(or cmake -H.. -B. -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release)
+make (or nmake / jom)
+./scriptableapplication (or scriptableapplication.exe)
diff --git a/examples/scriptableapplication/README.txt b/examples/scriptableapplication/README.txt
new file mode 100644
index 000000000..28bdb44ae
--- /dev/null
+++ b/examples/scriptableapplication/README.txt
@@ -0,0 +1,33 @@
+scriptableapplication demonstrates how to make a Qt C++ application scriptable.
+
+It has a class MainWindow inheriting QMainWindow for which bindings are generated
+using PySide2's shiboken2 bindings generator.
+
+The header wrappedclasses.h is passed to shiboken2 which generates class
+wrappers and headers in a subdirectory which are linked into the application.
+
+pythonutils.cpp has some code which binds the instance of MainWindow
+to a variable 'mainWindow' in the global (__main___) namespace.
+It is then possible to run Python script snippets like
+mainWindow.testFunction1() which trigger the underlying C++ function.
+
+Virtualenv Support
+If the application is started from a terminal with an activated python virtual environment, that
+environment's packages will be used for the python module import process. In this case, make sure
+that the application was built while the virtualenv was active, so that the build system picks up
+the correct python shared library.
+
+Windows Notes
+The build config of the application (Debug or Release) should match the PySide2 build config,
+otherwise the application will not function correctly. In practice this means the only supported
+configurations are:
+1) qmake release config build of the application + PySide2 setup.py without "--debug" flag +
+ python.exe for the PySide2 build process + python36.dll for the linked in shared library +
+ release build of Qt.
+2) qmake debug config build of the application + PySide2 setup.py WITH "--debug" flag +
+ python_d.exe for the PySide2 build process + python36_d.dll for the linked in shared library +
+ debug build of Qt.
+This is necessary because all the shared libraries in question have to link to the same C++ runtime
+library (msvcrt.dll or msvcrtd.dll).
+To make the example as self-contained as possible, the shared libraries in use (pyside2.dll,
+shiboken2.dll) are hard-linked into the build folder of the application.
diff --git a/examples/scriptableapplication/main.cpp b/examples/scriptableapplication/main.cpp
new file mode 100644
index 000000000..167eeb0fa
--- /dev/null
+++ b/examples/scriptableapplication/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+
+int main(int argc, char *argv[])
+{
+ QApplication a(argc, argv);
+ MainWindow mainWindow;
+ const QRect availableGeometry = a.desktop()->availableGeometry(&mainWindow);
+ mainWindow.resize(availableGeometry.width() / 2, availableGeometry.height() / 2);
+ mainWindow.show();
+ return a.exec();
+}
diff --git a/examples/scriptableapplication/mainwindow.cpp b/examples/scriptableapplication/mainwindow.cpp
new file mode 100644
index 000000000..e754bcb93
--- /dev/null
+++ b/examples/scriptableapplication/mainwindow.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "pythonutils.h"
+
+#include <QtWidgets/QAction>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QMenu>
+#include <QtWidgets/QMenuBar>
+#include <QtWidgets/QPlainTextEdit>
+#include <QtWidgets/QStatusBar>
+#include <QtWidgets/QToolBar>
+#include <QtWidgets/QVBoxLayout>
+
+#include <QtGui/QFontDatabase>
+#include <QtGui/QIcon>
+
+#include <QtCore/QDebug>
+#include <QtCore/QTextStream>
+
+static const char defaultScript[] =
+ "print(\"Hello, world\")\n"
+ "mainWindow.testFunction1()\n";
+
+MainWindow::MainWindow()
+ : m_scriptEdit(new QPlainTextEdit(QLatin1String(defaultScript), this))
+{
+ setWindowTitle(tr("Scriptable Application"));
+
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ const QIcon runIcon = QIcon::fromTheme(QStringLiteral("system-run"));
+ QAction *runAction = fileMenu->addAction(runIcon, tr("&Run..."), this, &MainWindow::slotRunScript);
+ runAction->setShortcut(Qt::CTRL + Qt::Key_R);
+ QAction *diagnosticAction = fileMenu->addAction(tr("&Print Diagnostics"), this, &MainWindow::slotPrintDiagnostics);
+ diagnosticAction->setShortcut(Qt::CTRL + Qt::Key_D);
+ fileMenu->addAction(tr("&Invoke testFunction1()"), this, &MainWindow::testFunction1);
+ const QIcon quitIcon = QIcon::fromTheme(QStringLiteral("application-exit"));
+ QAction *quitAction = fileMenu->addAction(quitIcon, tr("&Quit"), qApp, &QCoreApplication::quit);
+ quitAction->setShortcut(Qt::CTRL + Qt::Key_Q);
+
+ QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
+ const QIcon clearIcon = QIcon::fromTheme(QStringLiteral("edit-clear"));
+ QAction *clearAction = editMenu->addAction(clearIcon, tr("&Clear"), m_scriptEdit, &QPlainTextEdit::clear);
+
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ const QIcon aboutIcon = QIcon::fromTheme(QStringLiteral("help-about"));
+ QAction *aboutAction = helpMenu->addAction(aboutIcon, tr("&About Qt"), qApp, &QApplication::aboutQt);
+
+ QToolBar *toolBar = new QToolBar;
+ addToolBar(toolBar);
+ toolBar->addAction(quitAction);
+ toolBar->addSeparator();
+ toolBar->addAction(clearAction);
+ toolBar->addSeparator();
+ toolBar->addAction(runAction);
+ toolBar->addSeparator();
+ toolBar->addAction(aboutAction);
+
+ m_scriptEdit->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
+ setCentralWidget(m_scriptEdit);
+
+ if (!PythonUtils::bindAppObject("__main__", "mainWindow", PythonUtils::MainWindowType, this))
+ statusBar()->showMessage(tr("Error loading the application module"));
+}
+
+void MainWindow::slotRunScript()
+{
+ const QStringList script = m_scriptEdit->toPlainText().trimmed().split(QLatin1Char('\n'), QString::SkipEmptyParts);
+ if (!script.isEmpty())
+ runScript(script);
+}
+
+void MainWindow::slotPrintDiagnostics()
+{
+ const QStringList script = QStringList()
+ << "import sys" << "print('Path=', sys.path)" << "print('Executable=', sys.executable)";
+ runScript(script);
+}
+
+void MainWindow::runScript(const QStringList &script)
+{
+ if (!::PythonUtils::runScript(script))
+ statusBar()->showMessage(tr("Error running script"));
+}
+
+void MainWindow::testFunction1()
+{
+ static int n = 1;
+ QString message;
+ QTextStream(&message) << __FUNCTION__ << " called #" << n++;
+ qDebug().noquote() << message;
+ statusBar()->showMessage(message);
+}
diff --git a/examples/scriptableapplication/mainwindow.h b/examples/scriptableapplication/mainwindow.h
new file mode 100644
index 000000000..4dcafc731
--- /dev/null
+++ b/examples/scriptableapplication/mainwindow.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QtWidgets/QMainWindow>
+
+class QPlainTextEdit;
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+public:
+ MainWindow();
+
+ void testFunction1();
+
+private Q_SLOTS:
+ void slotRunScript();
+ void slotPrintDiagnostics();
+
+private:
+ void runScript(const QStringList &);
+
+ QPlainTextEdit *m_scriptEdit;
+};
+
+#endif // MAINWINDOW_H
diff --git a/examples/scriptableapplication/pyside2.pri b/examples/scriptableapplication/pyside2.pri
new file mode 100644
index 000000000..bd0eeef9e
--- /dev/null
+++ b/examples/scriptableapplication/pyside2.pri
@@ -0,0 +1,19 @@
+PYTHON_INCLUDE = $$system(python $$PWD/pyside2_config.py --python-include)
+isEmpty(PYTHON_INCLUDE): error(Unable to locate Python)
+PYTHON_LFLAGS = $$system(python $$PWD/pyside2_config.py --python-link)
+
+PYSIDE2 = $$system(python $$PWD/pyside2_config.py --pyside2)
+isEmpty(PYSIDE2): error(Unable to locate PySide2)
+PYSIDE2_INCLUDE = $$system(python $$PWD/pyside2_config.py --pyside2-include)
+PYSIDE2_LFLAGS = $$system(python $$PWD/pyside2_config.py --pyside2-link)
+PYSIDE2_SHARED_LIBRARIES = $$system(python $$PWD/pyside2_config.py --pyside2-shared-libraries)
+CLANG_BIN_DIR = $$system(python $$PWD/pyside2_config.py --clang-bin-dir)
+
+INCLUDEPATH += $$PYTHON_INCLUDE $$PYSIDE2_INCLUDE
+LIBS += $$PYTHON_LFLAGS $$PYSIDE2_LFLAGS
+
+!build_pass:message(Using $$PYSIDE2)
+
+!win32 {
+ QMAKE_RPATHDIR += $$PYSIDE2
+}
diff --git a/examples/scriptableapplication/pyside2_config.py b/examples/scriptableapplication/pyside2_config.py
new file mode 100644
index 000000000..361043aef
--- /dev/null
+++ b/examples/scriptableapplication/pyside2_config.py
@@ -0,0 +1,283 @@
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import os, glob, re, sys, imp
+from distutils import sysconfig
+if sys.platform == 'win32':
+ import winreg
+
+usage = """
+Utility to determine include/link options of PySide2 and Python for qmake
+
+Usage: pyside2_config.py [option]
+Options:
+ --python-include Print Python include path
+ --python-link Print Python link flags
+ --pyside2 Print PySide2 location
+ --pyside2-include Print PySide2 include paths
+ --pyside2-link Print PySide2 link flags
+ --pyside2-shared-libraries Print paths of PySide2 shared libraries (.so's, .dylib's, .dll's)
+ --clang-bin-dir Print path to the clang bin directory
+ -a Print all
+ --help/-h Print this help
+"""
+
+def cleanPath(path):
+ return path if sys.platform != 'win32' else path.replace('\\', '/')
+
+def sharedLibrarySuffix():
+ if sys.platform == 'win32':
+ return 'lib'
+ elif sys.platform == 'darwin':
+ return 'dylib'
+ return 'so'
+
+def sharedLibraryGlobPattern():
+ glob = '*.' + sharedLibrarySuffix()
+ return glob if sys.platform == 'win32' else 'lib' + glob
+
+def filterPySide2SharedLibraries(list):
+ def predicate(item):
+ basename = os.path.basename(item)
+ if 'shiboken' in basename or 'pyside2' in basename:
+ return True
+ return False
+ result = [item for item in list if predicate(item)]
+ return result
+
+# Return qmake link option for a library file name
+def linkOption(lib):
+ baseName = os.path.splitext(os.path.basename(lib))[0]
+ link = ' -l'
+ if sys.platform in ['linux', 'linux2', 'darwin']: # Linux: 'libfoo.so' -> '-lfoo'
+ link += baseName[3:]
+ else:
+ link += baseName
+ return link
+
+# Locate PySide2 via package path
+def findPySide2():
+ for p in sys.path:
+ if 'site-' in p:
+ pyside2 = os.path.join(p, 'PySide2')
+ if os.path.exists(pyside2):
+ return cleanPath(os.path.realpath(pyside2))
+ return None
+
+# Return version as "3.5"
+def pythonVersion():
+ return str(sys.version_info[0]) + '.' + str(sys.version_info[1])
+
+def pythonInclude():
+ return sysconfig.get_python_inc()
+
+def pythonLinkQmake():
+ flags = pythonLinkData()
+ if sys.platform == 'win32' or sys.platform == 'darwin':
+ return '-L{} -l{}'.format(flags['libdir'], flags['lib'])
+
+ # Linux and anything else
+ return '-l{}'.format(flags['lib'])
+
+def pythonLinkCmake():
+ flags = pythonLinkData()
+ libdir = flags['libdir']
+ lib = re.sub(r'.dll$', '.lib', flags['lib'])
+ return '{} {}'.format(libdir, lib)
+
+def pythonLinkData():
+ # @TODO Fix to work with static builds of Python
+ libdir = sysconfig.get_config_var('LIBDIR')
+ version = pythonVersion()
+ version_no_dots = version.replace('.', '')
+
+ flags = {}
+ flags['libdir'] = libdir
+ if sys.platform == 'win32':
+ suffix = '_d' if any([tup[0].endswith('_d.pyd') for tup in imp.get_suffixes()]) else ''
+ flags['lib'] = 'python{}{}'.format(version_no_dots, suffix)
+
+ elif sys.platform == 'darwin':
+ flags['lib'] = 'python{}'.format(version)
+
+ # Linux and anything else
+ else:
+ if sys.version_info[0] < 3:
+ suffix = '_d' if any([tup[0].endswith('_d.so') for tup in imp.get_suffixes()]) else ''
+ flags['lib'] = 'python{}{}'.format(version, suffix)
+ else:
+ flags['lib'] = 'python{}{}'.format(version, sys.abiflags)
+
+ return flags
+
+def pyside2Include():
+ pySide2 = findPySide2()
+ if pySide2 is None:
+ return None
+ return "{0}/include/PySide2 {0}/include/shiboken2".format(pySide2)
+
+def pyside2Link():
+ pySide2 = findPySide2()
+ if pySide2 is None:
+ return None
+ link = "-L{}".format(pySide2)
+ glob_result = glob.glob(os.path.join(pySide2, sharedLibraryGlobPattern()))
+ for lib in filterPySide2SharedLibraries(glob_result):
+ link += ' '
+ link += linkOption(lib)
+ return link
+
+def pyside2SharedLibrariesData():
+ pySide2 = findPySide2()
+ if pySide2 is None:
+ return None
+
+ glob_result = glob.glob(os.path.join(pySide2, sharedLibraryGlobPattern()))
+ filtered_libs = filterPySide2SharedLibraries(glob_result)
+ libs = []
+ if sys.platform == 'win32':
+ for lib in filtered_libs:
+ libs.append(os.path.realpath(lib))
+ else:
+ for lib in filtered_libs:
+ libs.append(lib)
+ return libs
+
+def pyside2SharedLibraries():
+ libs = pyside2SharedLibrariesData()
+ if libs is None:
+ return None
+
+ if sys.platform == 'win32':
+ if not libs:
+ return ''
+ dlls = ''
+ for lib in libs:
+ dll = os.path.splitext(lib)[0] + '.dll'
+ dlls += dll + ' '
+
+ return dlls
+ else:
+ libs_string = ''
+ for lib in libs:
+ libs_string += ' ' + lib
+ return libs_string
+
+def pyside2SharedLibrariesCmake():
+ libs = pyside2SharedLibrariesData()
+ result = ' '.join(libs)
+ return result
+
+def clangBinPath():
+ source = 'LLVM_INSTALL_DIR'
+ clangDir = os.environ.get(source, None)
+ if not clangDir:
+ source = 'CLANG_INSTALL_DIR'
+ clangDir = os.environ.get(source, None)
+ if not clangDir:
+ source = 'llvm-config'
+ try:
+ output = run_process_output([source, '--prefix'])
+ if output:
+ clangDir = output[0]
+ except OSError:
+ pass
+ if clangDir:
+ return os.path.realpath(clangDir + os.path.sep + 'bin')
+ return ''
+
+option = sys.argv[1] if len(sys.argv) == 2 else '-a'
+if option == '-h' or option == '--help':
+ print(usage)
+ sys.exit(0)
+
+if option == '--pyside2' or option == '-a':
+ pySide2 = findPySide2()
+ if pySide2 is None:
+ sys.exit('Unable to locate PySide2')
+ print(pySide2)
+
+if option == '--pyside2-link' or option == '-a':
+ l = pyside2Link()
+ if l is None:
+ sys.exit('Unable to locate PySide2')
+ print(l)
+
+if option == '--pyside2-include' or option == '-a':
+ i = pyside2Include()
+ if i is None:
+ sys.exit('Unable to locate PySide2')
+ print(i)
+
+if option == '--python-include' or option == '-a':
+ i = pythonInclude()
+ if i is None:
+ sys.exit('Unable to locate Python')
+ print(i)
+
+if option == '--python-link' or option == '-a':
+ l = pythonLinkQmake()
+ if l is None:
+ sys.exit('Unable to locate Python')
+ print(l)
+
+if option == '--python-link-cmake' or option == '-a':
+ l = pythonLinkCmake()
+ if l is None:
+ sys.exit('Unable to locate Python')
+ print(l)
+
+if option == '--pyside2-shared-libraries' or option == '-a':
+ l = pyside2SharedLibraries()
+ if l is None:
+ sys.exit('Unable to locate the PySide2 shared libraries')
+ print(l)
+
+if option == '--pyside2-shared-libraries-cmake' or option == '-a':
+ l = pyside2SharedLibrariesCmake()
+ if l is None:
+ sys.exit('Unable to locate the PySide2 shared libraries')
+ print(l)
+
+if option == '--clang-bin-dir' or option == '-a':
+ l = clangBinPath()
+ if l is None:
+ sys.exit('Unable to locate Clang')
+ print(l)
diff --git a/examples/scriptableapplication/pythonutils.cpp b/examples/scriptableapplication/pythonutils.cpp
new file mode 100644
index 000000000..27f1bc71c
--- /dev/null
+++ b/examples/scriptableapplication/pythonutils.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pythonutils.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+
+#include <sbkpython.h>
+#include <sbkconverter.h>
+#include <sbkmodule.h>
+
+/* from AppLib bindings */
+
+#if PY_MAJOR_VERSION >= 3
+ extern "C" PyObject *PyInit_AppLib();
+#else
+ extern "C" void initAppLib();
+#endif
+
+// This variable stores all Python types exported by this module.
+extern PyTypeObject **SbkAppLibTypes;
+
+// This variable stores all type converters exported by this module.
+extern SbkConverter **SbkAppLibTypeConverters;
+
+namespace PythonUtils {
+
+static State state = PythonUninitialized;
+
+static void cleanup()
+{
+ if (state > PythonUninitialized) {
+ Py_Finalize();
+ state = PythonUninitialized;
+ }
+}
+
+State init()
+{
+ if (state > PythonUninitialized)
+ return state;
+
+ // If there is an active python virtual environment, use that environment's packages location.
+ QByteArray virtualEnvPath = qgetenv("VIRTUAL_ENV");
+ if (!virtualEnvPath.isEmpty())
+ qputenv("PYTHONHOME", virtualEnvPath);
+
+ Py_Initialize();
+ qAddPostRoutine(cleanup);
+ state = PythonInitialized;
+#if PY_MAJOR_VERSION >= 3
+ const bool pythonInitialized = PyInit_AppLib() != nullptr;
+#else
+ const bool pythonInitialized = true;
+ initAppLib();
+#endif
+ const bool pyErrorOccurred = PyErr_Occurred() != nullptr;
+ if (pythonInitialized && !pyErrorOccurred) {
+ state = AppModuleLoaded;
+ } else {
+ if (pyErrorOccurred)
+ PyErr_Print();
+ qWarning("Failed to initialize the module.");
+ }
+ return state;
+}
+
+bool bindAppObject(const QString &moduleName, const QString &name,
+ int index, QObject *o)
+{
+ if (init() != AppModuleLoaded)
+ return false;
+ PyTypeObject *typeObject = SbkAppLibTypes[index];
+
+ PyObject *po = Shiboken::Conversions::pointerToPython(reinterpret_cast<const SbkObjectType *>(typeObject), o);
+ if (!po) {
+ qWarning() << __FUNCTION__ << "Failed to create wrapper for" << o;
+ return false;
+ }
+ Py_INCREF(po);
+
+ PyObject *module = PyImport_AddModule(moduleName.toLocal8Bit().constData());
+ if (!module) {
+ Py_DECREF(po);
+ if (PyErr_Occurred())
+ PyErr_Print();
+ qWarning() << __FUNCTION__ << "Failed to locate module" << moduleName;
+ return false;
+ }
+
+ if (PyModule_AddObject(module, name.toLocal8Bit().constData(), po) < 0) {
+ if (PyErr_Occurred())
+ PyErr_Print();
+ qWarning() << __FUNCTION__ << "Failed add object" << name << "to" << moduleName;
+ return false;
+ }
+
+ return true;
+}
+
+bool runScript(const QStringList &script)
+{
+ if (init() == PythonUninitialized)
+ return false;
+ bool result = true;
+ for (const QString& lineS : script) {
+ const QByteArray line = lineS.toUtf8();
+ if (PyRun_SimpleString(line.constData()) == -1) {
+ if (PyErr_Occurred())
+ PyErr_Print();
+ qWarning() << __FUNCTION__ << "Error at" << line;
+ result = false;
+ break;
+ }
+ }
+ return result;
+}
+
+} // namespace PythonUtils
diff --git a/examples/scriptableapplication/pythonutils.h b/examples/scriptableapplication/pythonutils.h
new file mode 100644
index 000000000..53e8c4dab
--- /dev/null
+++ b/examples/scriptableapplication/pythonutils.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the PySide examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS O