aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.vscode/settings.json16
-rw-r--r--build_history/blacklist.txt2
-rw-r--r--build_scripts/main.py4
-rw-r--r--build_scripts/platforms/linux.py12
-rw-r--r--build_scripts/platforms/macos.py3
-rw-r--r--build_scripts/platforms/unix.py4
-rw-r--r--build_scripts/utils.py2
-rw-r--r--coin/module_config.yaml4
-rw-r--r--coin_test_instructions.py7
-rw-r--r--doc/changelogs/changes-6.3.272
-rw-r--r--examples/async/eratosthenes/doc/eratosthenes.rst42
-rw-r--r--examples/async/eratosthenes/doc/eratosthenes.svg1
-rw-r--r--examples/async/eratosthenes/eratosthenes.py234
-rw-r--r--examples/async/eratosthenes/eratosthenes.pyproject3
-rw-r--r--examples/async/eratosthenes/requirements.txt2
-rw-r--r--examples/async/minimal/doc/minimal.pngbin0 -> 8135 bytes
-rw-r--r--examples/async/minimal/doc/minimal.rst41
-rw-r--r--examples/async/minimal/minimal.py152
-rw-r--r--examples/async/minimal/minimal.pyproject3
-rw-r--r--examples/async/minimal/requirements.txt1
-rw-r--r--examples/bluetooth/btscanner/device.py4
-rw-r--r--examples/bluetooth/heartrate_game/bluetoothbaseclass.py77
-rw-r--r--examples/bluetooth/heartrate_game/connectionhandler.py88
-rw-r--r--examples/bluetooth/heartrate_game/devicefinder.py159
-rw-r--r--examples/bluetooth/heartrate_game/devicehandler.py344
-rw-r--r--examples/bluetooth/heartrate_game/deviceinfo.py75
-rw-r--r--examples/bluetooth/heartrate_game/doc/heartrate_game.rst9
-rw-r--r--examples/bluetooth/heartrate_game/heartrate_game.pyproject22
-rw-r--r--examples/bluetooth/heartrate_game/heartrate_global.py43
-rw-r--r--examples/bluetooth/heartrate_game/main.py90
-rw-r--r--examples/bluetooth/heartrate_game/qml/App.qml130
-rw-r--r--examples/bluetooth/heartrate_game/qml/BluetoothAlarmDialog.qml121
-rw-r--r--examples/bluetooth/heartrate_game/qml/BottomLine.qml59
-rw-r--r--examples/bluetooth/heartrate_game/qml/Connect.qml188
-rw-r--r--examples/bluetooth/heartrate_game/qml/GameButton.qml88
-rw-r--r--examples/bluetooth/heartrate_game/qml/GamePage.qml93
-rw-r--r--examples/bluetooth/heartrate_game/qml/GameSettings.qml101
-rw-r--r--examples/bluetooth/heartrate_game/qml/Measure.qml244
-rw-r--r--examples/bluetooth/heartrate_game/qml/SplashScreen.qml90
-rw-r--r--examples/bluetooth/heartrate_game/qml/Stats.qml99
-rw-r--r--examples/bluetooth/heartrate_game/qml/StatsLabel.qml82
-rw-r--r--examples/bluetooth/heartrate_game/qml/TitleBar.qml97
-rw-r--r--examples/bluetooth/heartrate_game/qml/images/bt_off_to_on.pngbin0 -> 6143 bytes
-rw-r--r--examples/bluetooth/heartrate_game/qml/images/heart.pngbin0 -> 2664 bytes
-rw-r--r--examples/bluetooth/heartrate_game/qml/images/logo.pngbin0 -> 31915 bytes
-rw-r--r--examples/bluetooth/heartrate_game/qml/main.qml110
-rw-r--r--examples/bluetooth/heartrate_game/qml/qmldir1
-rw-r--r--examples/bluetooth/heartrate_server/doc/heartrate_server.rst8
-rw-r--r--examples/bluetooth/heartrate_server/heartrate_server.py131
-rw-r--r--examples/bluetooth/heartrate_server/heartrate_server.pyproject3
-rw-r--r--examples/charts/chartthemes/main.py39
-rw-r--r--examples/charts/donutbreakdown/donutbreakdown.py3
-rw-r--r--examples/charts/legend/legend.py10
-rw-r--r--examples/charts/lineandbar/lineandbar.py10
-rw-r--r--examples/charts/nesteddonuts/nesteddonuts.py3
-rw-r--r--examples/charts/percentbarchart/percentbarchart.py3
-rw-r--r--examples/corelib/settingseditor/settingseditor.py11
-rw-r--r--examples/corelib/threads/mandelbrot.py3
-rw-r--r--examples/datavisualization/surface/surfacegraph.py14
-rw-r--r--examples/datavisualization/surface_model_numpy/surfacegraph.py14
-rw-r--r--examples/declarative/rendercontrol/rendercontrol_opengl/window_singlethreaded.py6
-rw-r--r--examples/declarative/shared/Button.qml87
-rw-r--r--examples/declarative/shared/CheckBox.qml96
-rw-r--r--examples/declarative/shared/FlickrRssModel.qml82
-rw-r--r--examples/declarative/shared/Images.qml51
-rw-r--r--examples/declarative/shared/Label.qml46
-rw-r--r--examples/declarative/shared/LauncherList.qml242
-rw-r--r--examples/declarative/shared/README11
-rw-r--r--examples/declarative/shared/SimpleLauncherDelegate.qml133
-rw-r--r--examples/declarative/shared/Slider.qml119
-rw-r--r--examples/declarative/shared/TabSet.qml106
-rw-r--r--examples/declarative/shared/TextField.qml80
-rw-r--r--examples/declarative/shared/images/back.pngbin0 -> 1590 bytes
-rw-r--r--examples/declarative/shared/images/checkmark.pngbin0 -> 809 bytes
-rw-r--r--examples/declarative/shared/images/next.pngbin0 -> 1371 bytes
-rw-r--r--examples/declarative/shared/images/qt-logo.pngbin0 -> 6208 bytes
-rw-r--r--examples/declarative/shared/images/slider_handle.pngbin0 -> 887 bytes
-rw-r--r--examples/declarative/shared/images/tab.pngbin0 -> 309 bytes
-rw-r--r--examples/declarative/shared/qmldir11
-rw-r--r--examples/declarative/shared/quick_shared.qrc15
-rw-r--r--examples/declarative/shared/shared.qrc21
-rw-r--r--examples/declarative/shared/shared_rc.py1884
-rw-r--r--examples/declarative/window/AllScreens.qml79
-rw-r--r--examples/declarative/window/CurrentScreen.qml120
-rw-r--r--examples/declarative/window/Splash.qml79
-rw-r--r--examples/declarative/window/doc/window.pngbin0 -> 9863 bytes
-rw-r--r--examples/declarative/window/doc/window.rst35
-rw-r--r--examples/declarative/window/main.py74
-rw-r--r--examples/declarative/window/resources/icon.icnsbin0 -> 59662 bytes
-rw-r--r--examples/declarative/window/resources/icon.icobin0 -> 11825 bytes
-rw-r--r--examples/declarative/window/resources/icon.svg208
-rw-r--r--examples/declarative/window/resources/icon64.pngbin0 -> 3004 bytes
-rw-r--r--examples/declarative/window/window.pyproject3
-rw-r--r--examples/declarative/window/window.qml188
-rw-r--r--examples/declarative/window/window.qrc8
-rw-r--r--examples/declarative/window/window_rc.py328
-rw-r--r--examples/multimedia/audiooutput/audiooutput.py2
-rw-r--r--examples/multimedia/player/player.py3
-rw-r--r--examples/network/googlesuggest/doc/googlesuggest.pngbin0 -> 2467 bytes
-rw-r--r--examples/network/googlesuggest/doc/googlesuggest.rst11
-rw-r--r--examples/network/googlesuggest/googlesuggest.py174
-rw-r--r--examples/network/googlesuggest/googlesuggest.pyproject3
-rw-r--r--examples/network/googlesuggest/main.py51
-rw-r--r--examples/network/googlesuggest/searchbox.py64
-rw-r--r--examples/opengl/contextinfo/contextinfo.py4
-rw-r--r--examples/opengl/hellogl2/hellogl2.py7
-rw-r--r--examples/opengl/threadedqopenglwidget/glwidget.py1
-rw-r--r--examples/quick/painteditem/painteditem.py8
-rw-r--r--examples/samplebinding/CMakeLists.txt4
-rw-r--r--examples/scriptableapplication/CMakeLists.txt2
-rw-r--r--examples/serialport/terminal/console.py86
-rw-r--r--examples/serialport/terminal/doc/terminal.rst9
-rw-r--r--examples/serialport/terminal/images/application-exit.pngbin0 -> 11200 bytes
-rw-r--r--examples/serialport/terminal/images/clear.pngbin0 -> 12543 bytes
-rw-r--r--examples/serialport/terminal/images/connect.pngbin0 -> 15374 bytes
-rw-r--r--examples/serialport/terminal/images/disconnect.pngbin0 -> 15092 bytes
-rw-r--r--examples/serialport/terminal/images/settings.pngbin0 -> 16039 bytes
-rw-r--r--examples/serialport/terminal/main.py54
-rw-r--r--examples/serialport/terminal/mainwindow.py145
-rw-r--r--examples/serialport/terminal/mainwindow.ui162
-rw-r--r--examples/serialport/terminal/rc_terminal.py4464
-rw-r--r--examples/serialport/terminal/settingsdialog.py216
-rw-r--r--examples/serialport/terminal/settingsdialog.ui177
-rw-r--r--examples/serialport/terminal/terminal.pyproject4
-rw-r--r--examples/serialport/terminal/terminal.qrc9
-rw-r--r--examples/serialport/terminal/ui_mainwindow.py149
-rw-r--r--examples/serialport/terminal/ui_settingsdialog.py181
-rw-r--r--examples/sql/books/bookdelegate.py2
-rw-r--r--examples/texttospeech/hello_speak/hello_speak.py4
-rw-r--r--examples/webenginequick/nanobrowser/quicknanobrowser.py2
-rw-r--r--examples/webenginewidgets/markdowneditor/mainwindow.py2
-rw-r--r--examples/webenginewidgets/simplebrowser/simplebrowser.py6
-rw-r--r--examples/webenginewidgets/tabbedbrowser/browsertabwidget.py15
-rw-r--r--examples/webenginewidgets/tabbedbrowser/webengineview.py5
-rw-r--r--examples/widgetbinding/CMakeLists.txt4
-rw-r--r--examples/widgets/animation/easing/easing.py25
-rw-r--r--examples/widgets/animation/easing/form.ui105
-rw-r--r--examples/widgets/animation/easing/ui_form.py61
-rw-r--r--examples/widgets/codeeditor/codeeditor.py4
-rw-r--r--examples/widgets/desktop/screenshot/screenshot.py6
-rw-r--r--examples/widgets/dialogs/standarddialogs/standarddialogs.py18
-rw-r--r--examples/widgets/draganddrop/dropsite/doc/dropsite.rst8
-rw-r--r--examples/widgets/draganddrop/dropsite/droparea.py104
-rw-r--r--examples/widgets/draganddrop/dropsite/dropsite.pyproject3
-rw-r--r--examples/widgets/draganddrop/dropsite/dropsitewindow.py152
-rw-r--r--examples/widgets/draganddrop/dropsite/main.py52
-rw-r--r--examples/widgets/graphicsview/diagramscene/diagramscene.py25
-rw-r--r--examples/widgets/graphicsview/elasticnodes/elasticnodes.py2
-rw-r--r--examples/widgets/itemviews/address_book/address_book.py3
-rw-r--r--examples/widgets/itemviews/address_book/addresswidget.py5
-rw-r--r--examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py5
-rw-r--r--examples/widgets/itemviews/dirview/dirview.py97
-rw-r--r--examples/widgets/itemviews/dirview/dirview.pyproject3
-rw-r--r--examples/widgets/itemviews/dirview/doc/dirview.rst5
-rw-r--r--examples/widgets/itemviews/editabletreemodel/treemodel.py9
-rw-r--r--examples/widgets/itemviews/fetchmore/fetchmore.py2
-rw-r--r--examples/widgets/itemviews/spinboxdelegate/doc/spinboxdelegate.rst3
-rw-r--r--examples/widgets/itemviews/spreadsheet/spreadsheet.py6
-rw-r--r--examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py2
-rw-r--r--examples/widgets/linguist/main.py2
-rw-r--r--examples/widgets/mainwindows/application/application.py8
-rw-r--r--examples/widgets/mainwindows/mdi/mdi.py13
-rw-r--r--examples/widgets/painting/painter/painter.py13
-rw-r--r--examples/widgets/richtext/orderform/orderform.py3
-rw-r--r--examples/widgets/richtext/textobject/textobject.py3
-rw-r--r--examples/widgets/tetrix/tetrix.py2
-rw-r--r--examples/widgets/tools/regularexpression/regularexpressiondialog.py4
-rw-r--r--examples/widgets/tutorials/addressbook/part3.py4
-rw-r--r--examples/widgets/tutorials/addressbook/part4.py7
-rw-r--r--examples/widgets/tutorials/addressbook/part5.py7
-rw-r--r--examples/widgets/tutorials/addressbook/part6.py7
-rw-r--r--examples/widgets/tutorials/addressbook/part7.py7
-rw-r--r--examples/widgets/tutorials/cannon/t14.py2
-rw-r--r--examples/widgets/widgetsgallery/main.py2
-rw-r--r--examples/widgets/widgetsgallery/widgetgallery.py6
-rw-r--r--sources/pyside6/PySide6/QtBluetooth/typesystem_bluetooth.xml2
-rw-r--r--sources/pyside6/PySide6/QtCharts/typesystem_charts.xml2
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml57
-rw-r--r--sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml16
-rw-r--r--sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml2
-rw-r--r--sources/pyside6/PySide6/QtQuick/typesystem_quick.xml2
-rw-r--r--sources/pyside6/PySide6/QtSerialPort/typesystem_serialport.xml2
-rw-r--r--sources/pyside6/PySide6/QtWebEngineCore/typesystem_webenginecore.xml2
-rw-r--r--sources/pyside6/PySide6/QtWidgets/CMakeLists.txt1
-rw-r--r--sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml47
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp39
-rw-r--r--sources/pyside6/PySide6/glue/qtgui.cpp16
-rw-r--r--sources/pyside6/PySide6/glue/qtwidgets.cpp5
-rw-r--r--sources/pyside6/PySide6/qtguihelper.h2
-rw-r--r--sources/pyside6/PySide6/support/deprecated.py30
-rw-r--r--sources/pyside6/PySide6/templates/gui_common.xml9
-rw-r--r--sources/pyside6/doc/CMakeLists.txt4
-rw-r--r--sources/pyside6/doc/additionaldocs.lst111
-rw-r--r--sources/pyside6/doc/considerations.rst163
-rw-r--r--sources/pyside6/doc/developer/enumfeatures_doc.rst159
-rw-r--r--sources/pyside6/doc/developer/pep384impl_doc.rst (renamed from sources/shiboken6/libshiboken/pep384impl_doc.rst)0
-rw-r--r--sources/pyside6/doc/developer/signature_doc.rst (renamed from sources/shiboken6/libshiboken/signature/signature_doc.rst)0
-rw-r--r--sources/pyside6/doc/extras/QtCore.QEnum.rst5
-rw-r--r--sources/pyside6/doc/feature-why.rst2
-rw-r--r--sources/pyside6/doc/gettingstarted-linux.rst54
-rw-r--r--sources/pyside6/doc/gettingstarted-macOS.rst12
-rw-r--r--sources/pyside6/doc/gettingstarted-windows.rst12
-rw-r--r--sources/pyside6/doc/gettingstarted.rst12
-rw-r--r--sources/pyside6/doc/modules.rst135
-rw-r--r--sources/pyside6/doc/package_details.rst4
-rw-r--r--sources/pyside6/doc/porting_from2.rst18
-rw-r--r--sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py18
-rw-r--r--sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py24
-rw-r--r--sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst2
-rw-r--r--sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py174
-rw-r--r--sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py81
-rw-r--r--sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py161
-rw-r--r--sources/pyside6/libpyside/feature_select.cpp4
-rw-r--r--sources/pyside6/libpyside/pysideproperty.cpp2
-rw-r--r--sources/pyside6/libpyside/pysideqenum.cpp2
-rw-r--r--sources/pyside6/libpyside/pysideqflags.cpp10
-rw-r--r--sources/pyside6/libpyside/pysidesignal.cpp102
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp8
-rw-r--r--sources/pyside6/plugins/uitools/customwidget.cpp2
-rw-r--r--sources/pyside6/tests/QtCore/qenum_test.py14
-rw-r--r--sources/pyside6/tests/QtCore/qflags_test.py20
-rw-r--r--sources/pyside6/tests/QtCore/qsysinfo_test.py10
-rw-r--r--sources/pyside6/tests/QtGui/bug_617.py9
-rw-r--r--sources/pyside6/tests/QtGui/qkeysequence_test.py19
-rw-r--r--sources/pyside6/tests/QtGui/qpen_test.py3
-rw-r--r--sources/pyside6/tests/QtSql/qvarianttype_test.py7
-rw-r--r--sources/pyside6/tests/QtWidgets/qformlayout_test.py65
-rw-r--r--sources/pyside6/tests/pysidetest/CMakeLists.txt1
-rw-r--r--sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py166
-rw-r--r--sources/pyside6/tests/pysidetest/qvariant_test.py17
-rw-r--r--sources/pyside6/tests/pysidetest/shared_pointer_test.py2
-rw-r--r--sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp13
-rw-r--r--sources/pyside6/tests/pysidetest/sharedpointertestbench.h4
-rw-r--r--sources/pyside6/tests/registry/existence_test.py17
-rw-r--r--sources/pyside6/tests/registry/init_platform.py60
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp3
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafield.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetafield.h2
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetatype.cpp12
-rw-r--r--sources/shiboken6/ApiExtractor/apiextractor.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp13
-rw-r--r--sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/predefined_templates.cpp4
-rw-r--r--sources/shiboken6/ApiExtractor/typeparser.cpp2
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem_enums.h2
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp4
-rw-r--r--sources/shiboken6/cmake/ShibokenSetup.cmake1
-rw-r--r--sources/shiboken6/data/shiboken6.pc.in2
-rw-r--r--sources/shiboken6/doc/CMakeLists.txt4
-rw-r--r--sources/shiboken6/doc/scripts/patch_qhp.py77
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst13
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp110
-rw-r--r--sources/shiboken6/generator/shiboken/pytypenames.h1
-rw-r--r--sources/shiboken6/generator/shiboken/shibokengenerator.cpp25
-rw-r--r--sources/shiboken6/libshiboken/basewrapper.cpp28
-rw-r--r--sources/shiboken6/libshiboken/basewrapper_p.h3
-rw-r--r--sources/shiboken6/libshiboken/pep384impl.cpp11
-rw-r--r--sources/shiboken6/libshiboken/pep384impl.h3
-rw-r--r--sources/shiboken6/libshiboken/sbkenum.cpp240
-rw-r--r--sources/shiboken6/libshiboken/sbkenum_p.h23
-rw-r--r--sources/shiboken6/libshiboken/sbkfeature_base.cpp139
-rw-r--r--sources/shiboken6/libshiboken/sbkmodule.cpp2
-rw-r--r--sources/shiboken6/libshiboken/signature/signature.cpp14
-rw-r--r--sources/shiboken6/libshiboken/voidptr.cpp4
-rw-r--r--sources/shiboken6/shibokenmodule/Shiboken.pyi16
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py1138
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject1
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py2
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py7
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py9
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py15
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py50
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json2
-rw-r--r--sources/shiboken6/shibokenmodule/typesystem_shiboken.xml21
-rw-r--r--sources/shiboken6/tests/libsample/abstract.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/bytearray.cpp7
-rw-r--r--sources/shiboken6/tests/libsample/bytearray.h1
-rw-r--r--sources/shiboken6/tests/libsample/derived.cpp12
-rw-r--r--sources/shiboken6/tests/libsample/derived.h2
-rw-r--r--sources/shiboken6/tests/libsample/echo.h42
-rw-r--r--sources/shiboken6/tests/libsample/filter.cpp10
-rw-r--r--sources/shiboken6/tests/libsample/filter.h6
-rw-r--r--sources/shiboken6/tests/libsample/functions.cpp6
-rw-r--r--sources/shiboken6/tests/libsample/handle.h8
-rw-r--r--sources/shiboken6/tests/libsample/implicitconv.cpp14
-rw-r--r--sources/shiboken6/tests/libsample/implicitconv.h2
-rw-r--r--sources/shiboken6/tests/libsample/list.h18
-rw-r--r--sources/shiboken6/tests/libsample/listuser.cpp13
-rw-r--r--sources/shiboken6/tests/libsample/listuser.h9
-rw-r--r--sources/shiboken6/tests/libsample/mapuser.cpp8
-rw-r--r--sources/shiboken6/tests/libsample/mapuser.h4
-rw-r--r--sources/shiboken6/tests/libsample/modelindex.h20
-rw-r--r--sources/shiboken6/tests/libsample/modifications.cpp61
-rw-r--r--sources/shiboken6/tests/libsample/modifications.h32
-rw-r--r--sources/shiboken6/tests/libsample/objectmodel.cpp9
-rw-r--r--sources/shiboken6/tests/libsample/objectmodel.h4
-rw-r--r--sources/shiboken6/tests/libsample/objecttype.cpp18
-rw-r--r--sources/shiboken6/tests/libsample/objecttype.h2
-rw-r--r--sources/shiboken6/tests/libsample/objecttypebyvalue.h14
-rw-r--r--sources/shiboken6/tests/libsample/overload.cpp182
-rw-r--r--sources/shiboken6/tests/libsample/overload.h75
-rw-r--r--sources/shiboken6/tests/libsample/overloadsort.cpp35
-rw-r--r--sources/shiboken6/tests/libsample/overloadsort.h41
-rw-r--r--sources/shiboken6/tests/libsample/pen.cpp16
-rw-r--r--sources/shiboken6/tests/libsample/pen.h5
-rw-r--r--sources/shiboken6/tests/libsample/protected.cpp9
-rw-r--r--sources/shiboken6/tests/libsample/protected.h4
-rw-r--r--sources/shiboken6/tests/libsample/reference.cpp10
-rw-r--r--sources/shiboken6/tests/libsample/reference.h4
-rw-r--r--sources/shiboken6/tests/libsample/samplenamespace.cpp15
-rw-r--r--sources/shiboken6/tests/libsample/sometime.cpp5
-rw-r--r--sources/shiboken6/tests/libsample/str.cpp9
-rw-r--r--sources/shiboken6/tests/libsample/str.h2
-rw-r--r--sources/shiboken6/tests/libsample/strlist.h6
-rw-r--r--sources/shiboken6/tests/libsample/templateptr.cpp2
-rw-r--r--sources/shiboken6/tests/libsample/valueandvirtual.h1
-rw-r--r--sources/shiboken6/tests/libsample/virtualmethods.cpp5
-rw-r--r--sources/shiboken6/tests/libsample/virtualmethods.h2
-rw-r--r--sources/shiboken6/tests/libsmart/smart.cpp6
-rw-r--r--sources/shiboken6/tests/libsmart/smart_integer.h3
-rw-r--r--tools/example_gallery/main.py16
-rw-r--r--tools/snippets_translate/converter.py118
-rw-r--r--tools/snippets_translate/handlers.py236
-rw-r--r--tools/snippets_translate/override.py58
-rw-r--r--tools/snippets_translate/snippets_translate.pyproject3
-rw-r--r--tools/snippets_translate/tests/test_converter.py28
-rw-r--r--tools/snippets_translate/tests/test_snippets.py87
327 files changed, 17123 insertions, 2343 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..57f2286da
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,16 @@
+{
+ "editor.rulers": [
+ 72, // comments and docstrings
+ 79, // desirable code length
+ 100 // maximum code length
+ ],
+ "python.testing.unittestArgs": [
+ "-v",
+ "-s",
+ "./sources/pyside6/tests",
+ "-p",
+ "*_test.py"
+ ],
+ "python.testing.pytestEnabled": false,
+ "python.testing.unittestEnabled": true
+}
diff --git a/build_history/blacklist.txt b/build_history/blacklist.txt
index 3355a2b6e..d3455dd60 100644
--- a/build_history/blacklist.txt
+++ b/build_history/blacklist.txt
@@ -33,8 +33,6 @@
linux
darwin
# Open GL functions failures on macOS (2/2020)
-[registry::existence_test]
- darwin
[QtQml::qqmlnetwork_test]
linux ci # extended, see PyPy section below
[QtWidgets::bug_750]
diff --git a/build_scripts/main.py b/build_scripts/main.py
index c654a4e02..d69a5324b 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -960,7 +960,7 @@ class PysideBuild(_build, DistUtilsCommandMixin, BuildInfoCollectorMixin):
_vars['dbg_postfix'] = OPTION["DEBUG"] and "_d" or ""
return prepare_packages_win32(self, _vars)
else:
- return prepare_packages_posix(self, _vars)
+ return prepare_packages_posix(self, _vars, self.is_cross_compile)
except IOError as e:
print('setup.py/prepare_packages: ', e)
raise
@@ -1274,7 +1274,7 @@ class PysideRstDocs(Command, DistUtilsCommandMixin):
elif self.name == SHIBOKEN:
self.sphinx_src = self.out_dir
- sphinx_cmd = ["sphinx-build", "-b", "html", "-c", self.sphinx_src,
+ sphinx_cmd = ["sphinx-build", "-b", "html", "-j", "auto", "-c", self.sphinx_src,
self.doc_dir, self.out_dir]
if run_process(sphinx_cmd) != 0:
raise DistutilsSetupError(f"Error running CMake for {self.doc_dir}")
diff --git a/build_scripts/platforms/linux.py b/build_scripts/platforms/linux.py
index 229d4397d..bf4db5664 100644
--- a/build_scripts/platforms/linux.py
+++ b/build_scripts/platforms/linux.py
@@ -40,12 +40,13 @@
import os
from ..config import config
+from ..options import OPTION
from ..utils import (copy_icu_libs, copydir, copyfile, find_files_using_glob,
linux_patch_executable)
from ..versions import PYSIDE
-def prepare_standalone_package_linux(self, _vars):
+def prepare_standalone_package_linux(self, _vars, cross_build=False):
built_modules = _vars['built_modules']
constrain_modules = None
@@ -85,17 +86,18 @@ def prepare_standalone_package_linux(self, _vars):
# Qt is built against system ICU, or in the Coin CI where ICU
# libs are in a different directory) try to find out / resolve
# which ICU libs are used by QtCore (if used at all) using a
- # custom written ldd, and copy the ICU libs to the Pyside Qt
- # dir if necessary. We choose the QtCore lib to inspect, by
+ # custom written ldd (non-cross build only), and copy the ICU
+ # libs to the Pyside Qt dir if necessary.
+ # We choose the QtCore lib to inspect, by
# checking which QtCore library the shiboken6 executable uses.
- if not maybe_icu_libs:
+ if not maybe_icu_libs and not cross_build:
copy_icu_libs(self._patchelf_path, resolved_destination_lib_dir)
# Set RPATH for Qt libs.
self.update_rpath_for_linux_qt_libraries(destination_lib_dir.format(**_vars))
# Patching designer to use the Qt libraries provided in the wheel
- if config.is_internal_pyside_build():
+ if config.is_internal_pyside_build() and not OPTION['NO_QT_TOOLS']:
assistant_path = "{st_build_dir}/{st_package_name}/assistant".format(**_vars)
linux_patch_executable(self._patchelf_path, assistant_path)
designer_path = "{st_build_dir}/{st_package_name}/designer".format(**_vars)
diff --git a/build_scripts/platforms/macos.py b/build_scripts/platforms/macos.py
index 69c2a436c..07a565f35 100644
--- a/build_scripts/platforms/macos.py
+++ b/build_scripts/platforms/macos.py
@@ -41,6 +41,7 @@ import fnmatch
import os
from ..config import config
+from ..options import OPTION
from ..utils import (copydir, copyfile, macos_add_rpath,
macos_fix_rpaths_for_library)
from ..versions import PYSIDE
@@ -90,7 +91,7 @@ def prepare_standalone_package_macos(self, _vars):
return True
# Patching designer to use the Qt libraries provided in the wheel
- if config.is_internal_pyside_build():
+ if config.is_internal_pyside_build() and not OPTION['NO_QT_TOOLS']:
_macos_patch_executable('assistant', _vars)
_macos_patch_executable('designer', _vars)
_macos_patch_executable('linguist', _vars)
diff --git a/build_scripts/platforms/unix.py b/build_scripts/platforms/unix.py
index 904ae9c0e..ec0a8bb9c 100644
--- a/build_scripts/platforms/unix.py
+++ b/build_scripts/platforms/unix.py
@@ -74,7 +74,7 @@ def _copy_gui_executable(name, _vars=None):
return _unix_copy_gui_executable(name, _vars)
-def prepare_packages_posix(self, _vars):
+def prepare_packages_posix(self, _vars, cross_build=False):
executables = []
libexec_executables = []
@@ -245,7 +245,7 @@ def prepare_packages_posix(self, _vars):
if sys.platform == 'darwin':
prepare_standalone_package_macos(self, _vars)
else:
- prepare_standalone_package_linux(self, _vars)
+ prepare_standalone_package_linux(self, _vars, cross_build)
if config.is_internal_shiboken_generator_build():
# Copy over clang before rpath patching.
diff --git a/build_scripts/utils.py b/build_scripts/utils.py
index 6f44ae5c2..3772a14df 100644
--- a/build_scripts/utils.py
+++ b/build_scripts/utils.py
@@ -947,6 +947,8 @@ def find_qt_core_library_glob(lib_dir):
# ldd for the specified platforms.
# This has less priority because ICU libs are not used in the default
# Qt configuration build.
+# Note: Uses ldd to query shared library dependencies and thus does not
+# work for cross builds.
def copy_icu_libs(patchelf, destination_lib_dir):
"""
Copy ICU libraries that QtCore depends on,
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index fab13c99b..3da0ae8f7 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -16,10 +16,10 @@ accept_configuration:
- condition: property
property: features
not_contains_value: UseLegacyInstructions
- - condition: property # MibnGW and msvc2015 are not supported
+ - condition: property # MinGW and msvc2015 are not supported
property: target.compiler
not_in_values: [Mingw, MSVC2015]
- - condition: property #Webassembly
+ - condition: property # Webassembly
property: target.osVersion
not_equals_value: WebAssembly
- condition: property # Windows on Arm
diff --git a/coin_test_instructions.py b/coin_test_instructions.py
index 8c8838b71..52c61d9eb 100644
--- a/coin_test_instructions.py
+++ b/coin_test_instructions.py
@@ -132,9 +132,10 @@ def run_test_instructions():
# In win machines, there are additional python versions to test with
if CI_HOST_OS == "Windows":
- call_testrunner("3.6.1", str(testRun))
- call_testrunner("3.8.1", str(testRun))
- call_testrunner("3.10.0", str(testRun))
+ if os.environ.get('HOST_OSVERSION_COIN') == 'windows_10_21h2':
+ call_testrunner("3.10.0", str(testRun))
+ else:
+ call_testrunner("3.7.9", str(testRun))
elif CI_HOST_OS == "Linux":
call_testrunner("3.8", str(testRun))
else:
diff --git a/doc/changelogs/changes-6.3.2 b/doc/changelogs/changes-6.3.2
new file mode 100644
index 000000000..c2a40a854
--- /dev/null
+++ b/doc/changelogs/changes-6.3.2
@@ -0,0 +1,72 @@
+Qt for Python 6.3.2 is a bug-fix release.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qtforpython/
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* PySide6 *
+****************************************************************************
+
+ - [PYSIDE-841] New examples have been added (SpinBoxDelegate,
+ Bluetooth heart rate).
+ - [PYSIDE-1312] QFormLayout::takeRow() has been added.
+ - [PYSIDE-1735] The duplication of enum values into the enclosing scope,
+ allowing to write Qt.AlignLeft instead of Qt.Alignment.AlignLeft,
+ is now implemented differently and no longer advertized in PYI
+ files or line completion.
+ - [PYSIDE-1735] The new Python enums are made as compatible to the old ones
+ as possible. It is again allowed to use Qt.Alignment()
+ instead of Qt.AlignmentFlag(0), and a default of 0 is
+ always allowed but also not advertized.
+ Qt.Modifiers/Qt.KeyboardModifierflags can also still be used
+ interchangeably.
+ - [PYSIDE-1735] Most former IntEnum/IntFlag are replaced by pure Enum/Flag
+ classes in a generally compatible way to other implementations.
+ - [PYSIDE-1735] PyEnum handles QKeyCombination correctly with "|" or (deprecated)
+ "+" operators, without falling back to using IntEnum.
+ - [PYSIDE-1735] Python Enums use the newest implementation for Python (3.10)
+ for compatibility and speed.
+ - [PYSIDE-1735] A weird build problem on macOS and other platforms was fixed.
+ - [PYSide-1735] The cleanup calls by were sped up by using PyName for
+ staticMetaObject.
+ - [PYSIDE-1984] The code snippets in the modelview tutorial have been
+ improved.
+ - [PYSIDE-1930] Returning enums from QAbstractItemModel.flags() and
+ QAbstractItemModel.data() has been fixed.
+ - [PYSIDE-1934] The type hinting for the return value of
+ QListWidget.selected_indexes() has been fixed.
+ - [PYSIDE-1960] Initial support for Python 3.11 has been added.
+ - [PYSIDE-1968] The signature of QPixmap.save() has been fixed.
+ - [PYSIDE-1978] The signal
+ QAbstractItemModel.layoutAboutToBeChanged(QList<QPersistentModelIndex>)
+ has been fixed.
+ Also, the error message about using the wrong signal overload
+ has been improved.
+ - [PYSIDE-2030] The converter tools for Python code snippets for the
+ documentation has been improved.
+ - [PYSIDE-2019] Crashes related to QtDataVisualization'QValue3DAxisFormatter
+ have been fixed.
+ - [PYSIDE-2034] The static functions of QMessageBox have been fixed to not
+ block threads.
+ - [PYSIDE-2039] A regression affecting setting override cursors without
+ context manager has been fixed.
+
+
+****************************************************************************
+* Shiboken6 *
+****************************************************************************
+
+ - [PYSIDE-1964] The error message about mistakenly using keyword arguments
+ has been improved.
+ - [PYSIDE-1988] Fixed a mistaken PySequence_Check() type check to be
+ PyTuple_Check(), which only showed in Python 3.11.
diff --git a/examples/async/eratosthenes/doc/eratosthenes.rst b/examples/async/eratosthenes/doc/eratosthenes.rst
new file mode 100644
index 000000000..37758e99f
--- /dev/null
+++ b/examples/async/eratosthenes/doc/eratosthenes.rst
@@ -0,0 +1,42 @@
+Async examples
+==============
+
+The Python language provides keywords for asynchronous operations, i.e.,
+"async" to define coroutines or "await" to schedule asynchronous calls in the
+event loop (see `PEP 492 <https://peps.python.org/pep-0492/>`_). It is up to
+packages to implement an event loop, support for these keywords, and more.
+
+One such package is `trio`. Since both an async package and Qt itself work with
+event loops, special care must be taken to ensure that both event loops work
+with each other. trio offers a dedicated `low-level API
+<https://trio.readthedocs.io/en/stable/reference-lowlevel.html>`_ for more
+complicated use cases such as this. Specifically, there exists a function
+`start_guest_run` that enables running the Trio event loop as a "guest" inside
+another event loop - Qt's in our case.
+
+Based on this functionality, two examples for async usage with Qt have been
+implemented: `eratosthenes` and `minimal`:
+
+.. image:: eratosthenes.svg
+ :alt: Async example: Eratosthenes
+ :width: 400
+
+* `eratosthenes` is a more extensive example that visualizes the Sieve of
+Eratosthenes algorithm. This algorithm per se is not one that is particularly
+suitable for asynchronous operations as it's not I/O-heavy, but synchronizing
+coroutines to a configurable tick allows for a good visualization.
+* `minimal` is a minimal example featuring a button that triggers an
+asynchronous coroutine with a sleep. It is designed to highlight which
+boilerplate code is essential for an async program with Qt and offers a
+starting point for more complex programs.
+
+Both examples feature:
+
+1. A window class.
+2. An `AsyncHelper` class containing `start_guest_run` plus helpers and
+callbacks necessary for its invocation. The entry point for the Trio guest run
+is provided as an argument from outside, which can be any async function.
+
+While `eratosthenes` offloads the asynchronous logic that will run in trio's
+event loop into a separate class, `minimal` demonstrates that async functions
+can be integrated into any class, including subclasses of Qt classes.
diff --git a/examples/async/eratosthenes/doc/eratosthenes.svg b/examples/async/eratosthenes/doc/eratosthenes.svg
new file mode 100644
index 000000000..eaf53da50
--- /dev/null
+++ b/examples/async/eratosthenes/doc/eratosthenes.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="1210.666" height="886.666" viewBox="0 0 908 665" baseProfile="tiny" xmlns:v="https://vecta.io/nano"><style><![CDATA[.B{stroke:none}.C{font-family:.AppleSystemUIFont}.D{font-size:13px}.E{font-weight:700}.F{fill:#000}.G{fill:#548f7c}.H{fill:#bab040}.I{fill:#51a660}.J{fill:#a193b6}.K{fill:#8a4a8f}.L{fill:#45b2a7}.M{fill:#916bbd}.N{fill:#7dad6b}.O{fill:#628f47}.P{fill:#6474c0}.Q{fill:#b182b0}.R{fill:#a94257}.S{fill:#a1794d}.T{fill:#bbac54}.U{fill:#6e4344}.V{fill:#a38b9d}.W{fill:#6c4268}.X{fill:#974c66}.Y{fill:#8163bb}.Z{fill:#bda991}.a{fill:#599c9d}.b{fill:#7ec05e}.c{fill:#b26b51}.d{fill:#434da9}.e{fill:#a46a69}.f{fill:#6a6467}.g{fill:#954ca5}.h{fill:#6f4965}.i{fill:#7a99b1}.j{fill:#786344}.k{fill:#898683}.l{fill:#ac989d}.m{fill:#4f5a7b}.n{fill:#b28c5f}.o{fill:#639747}.p{fill:#aba64a}.q{fill:#916c5e}.r{fill:#b0929e}.s{fill:#909864}.t{fill:#a14faf}]]></style><g fill="none" stroke="#000" fill-rule="evenodd" class="C B"><path d="M0 0h908v665H0z" fill="#ececec" class="D"/><g font-size="14" class="F"><text xml:space="preserve" y="25.781" x="192">🥳</text><text xml:space="preserve" x="214.016" y="25.781"> Congratulations! You found all the prime numbers and solved mathematics. </text><text xml:space="preserve" x="693.031" y="25.781">🥳</text></g><text xml:space="preserve" y="61.906" x="34" class="D F">1</text><text xml:space="preserve" y="61.906" x="67" class="D F">2</text><text xml:space="preserve" y="61.906" x="101" class="D F">3</text><text xml:space="preserve" y="61.906" x="136" class="D E l">4</text><text xml:space="preserve" y="61.906" x="171" class="D F">5</text><text xml:space="preserve" y="61.906" x="206" class="D E U">6</text><text xml:space="preserve" y="61.906" x="241" class="D F">7</text><text xml:space="preserve" y="61.906" x="275" class="D E l">8</text><text xml:space="preserve" y="61.906" x="310" class="D E U">9</text><text xml:space="preserve" y="61.906" x="341" class="D E M">10</text><text xml:space="preserve" y="61.906" x="378" class="D F">11</text><text xml:space="preserve" y="61.906" x="411" class="D E U">12</text><text xml:space="preserve" y="61.906" x="446" class="D F">13</text><text xml:space="preserve" y="61.906" x="480" class="D E G">14</text><text xml:space="preserve" y="61.906" x="516" class="D E M">15</text><text xml:space="preserve" y="61.906" x="550" class="D E l">16</text><text xml:space="preserve" y="61.906" x="586" class="D F">17</text><text xml:space="preserve" y="61.906" x="619" class="D E U">18</text><text xml:space="preserve" y="61.906" x="655" class="D F">19</text><text xml:space="preserve" y="61.906" x="689" class="D E M">20</text><text xml:space="preserve" y="61.906" x="725" class="D E G">21</text><text xml:space="preserve" y="61.906" x="758" class="D E H">22</text><text xml:space="preserve" y="61.906" x="793" class="D F">23</text><text xml:space="preserve" y="61.906" x="827" class="D E U">24</text><text xml:space="preserve" y="61.906" x="862" class="D E M">25</text><text xml:space="preserve" y="85.906" x="28" class="D E I">26</text><text xml:space="preserve" y="85.906" x="63" class="D E U">27</text><text xml:space="preserve" y="85.906" x="96" class="D E G">28</text><text xml:space="preserve" y="85.906" x="132" class="D F">29</text><text xml:space="preserve" y="85.906" x="166" class="D E M">30</text><text xml:space="preserve" y="85.906" x="203" class="D F">31</text><text xml:space="preserve" y="85.906" x="236" class="D E K">32</text><text xml:space="preserve" y="85.906" x="270" class="D E H">33</text><text xml:space="preserve" y="85.906" x="305" class="D E J">34</text><text xml:space="preserve" y="85.906" x="341" class="D E G">35</text><text xml:space="preserve" y="85.906" x="375" class="D E U">36</text><text xml:space="preserve" y="85.906" x="411" class="D F">37</text><text xml:space="preserve" y="85.906" x="444" class="D E L">38</text><text xml:space="preserve" y="85.906" x="479" class="D E I">39</text><text xml:space="preserve" y="85.906" x="514" class="D E M">40</text><text xml:space="preserve" y="85.906" x="551" class="D F">41</text><text xml:space="preserve" y="85.906" x="584" class="D E G">42</text><text xml:space="preserve" y="85.906" x="619" class="D F">43</text><text xml:space="preserve" y="85.906" x="653" class="D E H">44</text><text xml:space="preserve" y="85.906" x="688" class="D E M">45</text><text xml:space="preserve" y="85.906" x="723" class="D E N">46</text><text xml:space="preserve" y="85.906" x="759" class="D F">47</text><text xml:space="preserve" y="85.906" x="792" class="D E K">48</text><text xml:space="preserve" y="85.906" x="827" class="D E G">49</text><text xml:space="preserve" y="85.906" x="861" class="D E M">50</text><text xml:space="preserve" y="109.906" x="29" class="D E J">51</text><text xml:space="preserve" y="109.906" x="62" class="D E I">52</text><text xml:space="preserve" y="109.906" x="97" class="D F">53</text><text xml:space="preserve" y="109.906" x="131" class="D E U">54</text><text xml:space="preserve" y="109.906" x="167" class="D E H">55</text><text xml:space="preserve" y="109.906" x="201" class="D E G">56</text><text xml:space="preserve" y="109.906" x="236" class="D E L">57</text><text xml:space="preserve" y="109.906" x="270" class="D E O">58</text><text xml:space="preserve" y="109.906" x="306" class="D F">59</text><text xml:space="preserve" y="109.906" x="340" class="D E M">60</text><text xml:space="preserve" y="109.906" x="377" class="D F">61</text><text xml:space="preserve" y="109.906" x="410" class="D E P">62</text><text xml:space="preserve" y="109.906" x="444" class="D E G">63</text><text xml:space="preserve" y="109.906" x="479" class="D E K">64</text><text xml:space="preserve" y="109.906" x="514" class="D E I">65</text><text xml:space="preserve" y="109.906" x="549" class="D E H">66</text><text xml:space="preserve" y="109.906" x="585" class="D F">67</text><text xml:space="preserve" y="109.906" x="618" class="D E J">68</text><text xml:space="preserve" y="109.906" x="653" class="D E N">69</text><text xml:space="preserve" y="109.906" x="689" class="D E G">70</text><text xml:space="preserve" y="109.906" x="725" class="D F">71</text><text xml:space="preserve" y="109.906" x="759" class="D E U">72</text><text xml:space="preserve" y="109.906" x="793" class="D F">73</text><text xml:space="preserve" y="109.906" x="828" class="D E Q">74</text><text xml:space="preserve" y="109.906" x="862" class="D E M">75</text><text xml:space="preserve" y="133.906" x="28" class="D E L">76</text><text xml:space="preserve" y="133.906" x="63" class="D E H">77</text><text xml:space="preserve" y="133.906" x="97" class="D E I">78</text><text xml:space="preserve" y="133.906" x="132" class="D F">79</text><text xml:space="preserve" y="133.906" x="166" class="D E K">80</text><text xml:space="preserve" y="133.906" x="202" class="D E U">81</text><text xml:space="preserve" y="133.906" x="236" class="D E R">82</text><text xml:space="preserve" y="133.906" x="271" class="D F">83</text><text xml:space="preserve" y="133.906" x="305" class="D E G">84</text><text xml:space="preserve" y="133.906" x="340" class="D E J">85</text><text xml:space="preserve" y="133.906" x="375" class="D E S">86</text><text xml:space="preserve" y="133.906" x="410" class="D E O">87</text><text xml:space="preserve" y="133.906" x="444" class="D E H">88</text><text xml:space="preserve" y="133.906" x="480" class="D F">89</text><text xml:space="preserve" y="133.906" x="514" class="D E M">90</text><text xml:space="preserve" y="133.906" x="550" class="D E I">91</text><text xml:space="preserve" y="133.906" x="584" class="D E N">92</text><text xml:space="preserve" y="133.906" x="618" class="D E P">93</text><text xml:space="preserve" y="133.906" x="653" class="D E T">94</text><text xml:space="preserve" y="133.906" x="688" class="D E L">95</text><text xml:space="preserve" y="133.906" x="723" class="D E K">96</text><text xml:space="preserve" y="133.906" x="759" class="D F">97</text><text xml:space="preserve" y="133.906" x="792" class="D E G">98</text><text xml:space="preserve" y="133.906" x="827" class="D E H">99</text><text xml:space="preserve" y="133.906" x="858" class="D E M">100</text><text xml:space="preserve" y="157.906" x="27" class="D F">101</text><text xml:space="preserve" y="157.906" x="59" class="D E J">102</text><text xml:space="preserve" y="157.906" x="94" class="D F">103</text><text xml:space="preserve" y="157.906" x="128" class="D E I">104</text><text xml:space="preserve" y="157.906" x="163" class="D E G">105</text><text xml:space="preserve" y="157.906" x="198" class="D E V">106</text><text xml:space="preserve" y="157.906" x="234" class="D F">107</text><text xml:space="preserve" y="157.906" x="267" class="D E W">108</text><text xml:space="preserve" y="157.906" x="303" class="D F">109</text><text xml:space="preserve" y="157.906" x="338" class="D E H">110</text><text xml:space="preserve" y="157.906" x="374" class="D E Q">111</text><text xml:space="preserve" y="157.906" x="408" class="D E K">112</text><text xml:space="preserve" y="157.906" x="443" class="D F">113</text><text xml:space="preserve" y="157.906" x="477" class="D E L">114</text><text xml:space="preserve" y="157.906" x="512" class="D E N">115</text><text xml:space="preserve" y="157.906" x="547" class="D E O">116</text><text xml:space="preserve" y="157.906" x="582" class="D E I">117</text><text xml:space="preserve" y="157.906" x="616" class="D E X">118</text><text xml:space="preserve" y="157.906" x="651" class="D E J">119</text><text xml:space="preserve" y="157.906" x="685" class="D E M">120</text><text xml:space="preserve" y="157.906" x="721" class="D E H">121</text><text xml:space="preserve" y="157.906" x="755" class="D E Y">122</text><text xml:space="preserve" y="157.906" x="789" class="D E R">123</text><text xml:space="preserve" y="157.906" x="824" class="D E P">124</text><text xml:space="preserve" y="157.906" x="858" class="D E M">125</text><text xml:space="preserve" y="181.906" x="25" class="D E G">126</text><text xml:space="preserve" y="181.906" x="60" class="D F">127</text><text xml:space="preserve" y="181.906" x="93" class="D E K">128</text><text xml:space="preserve" y="181.906" x="128" class="D E S">129</text><text xml:space="preserve" y="181.906" x="163" class="D E I">130</text><text xml:space="preserve" y="181.906" x="200" class="D F">131</text><text xml:space="preserve" y="181.906" x="233" class="D E H">132</text><text xml:space="preserve" y="181.906" x="267" class="D E L">133</text><text xml:space="preserve" y="181.906" x="302" class="D E Z">134</text><text xml:space="preserve" y="181.906" x="337" class="D E M">135</text><text xml:space="preserve" y="181.906" x="372" class="D E J">136</text><text xml:space="preserve" y="181.906" x="408" class="D F">137</text><text xml:space="preserve" y="181.906" x="441" class="D E N">138</text><text xml:space="preserve" y="181.906" x="477" class="D F">139</text><text xml:space="preserve" y="181.906" x="511" class="D E G">140</text><text xml:space="preserve" y="181.906" x="547" class="D E T">141</text><text xml:space="preserve" y="181.906" x="581" class="D E a">142</text><text xml:space="preserve" y="181.906" x="615" class="D E I">143</text><text xml:space="preserve" y="181.906" x="650" class="D E K">144</text><text xml:space="preserve" y="181.906" x="685" class="D E O">145</text><text xml:space="preserve" y="181.906" x="720" class="D E b">146</text><text xml:space="preserve" y="181.906" x="755" class="D E G">147</text><text xml:space="preserve" y="181.906" x="789" class="D E Q">148</text><text xml:space="preserve" y="181.906" x="824" class="D F">149</text><text xml:space="preserve" y="181.906" x="858" class="D E M">150</text><text xml:space="preserve" y="205.906" x="27" class="D F">151</text><text xml:space="preserve" y="205.906" x="59" class="D E L">152</text><text xml:space="preserve" y="205.906" x="93" class="D E J">153</text><text xml:space="preserve" y="205.906" x="128" class="D E H">154</text><text xml:space="preserve" y="205.906" x="163" class="D E P">155</text><text xml:space="preserve" y="205.906" x="198" class="D E I">156</text><text xml:space="preserve" y="205.906" x="234" class="D F">157</text><text xml:space="preserve" y="205.906" x="267" class="D E c">158</text><text xml:space="preserve" y="205.906" x="302" class="D E V">159</text><text xml:space="preserve" y="205.906" x="337" class="D E K">160</text><text xml:space="preserve" y="205.906" x="373" class="D E N">161</text><text xml:space="preserve" y="205.906" x="407" class="D E W">162</text><text xml:space="preserve" y="205.906" x="442" class="D F">163</text><text xml:space="preserve" y="205.906" x="476" class="D E R">164</text><text xml:space="preserve" y="205.906" x="511" class="D E H">165</text><text xml:space="preserve" y="205.906" x="546" class="D E d">166</text><text xml:space="preserve" y="205.906" x="582" class="D F">167</text><text xml:space="preserve" y="205.906" x="615" class="D E G">168</text><text xml:space="preserve" y="205.906" x="650" class="D E I">169</text><text xml:space="preserve" y="205.906" x="686" class="D E J">170</text><text xml:space="preserve" y="205.906" x="722" class="D E L">171</text><text xml:space="preserve" y="205.906" x="755" class="D E S">172</text><text xml:space="preserve" y="205.906" x="790" class="D F">173</text><text xml:space="preserve" y="205.906" x="824" class="D E O">174</text><text xml:space="preserve" y="205.906" x="859" class="D E G">175</text><text xml:space="preserve" y="229.906" x="25" class="D E K">176</text><text xml:space="preserve" y="229.906" x="60" class="D E X">177</text><text xml:space="preserve" y="229.906" x="93" class="D E e">178</text><text xml:space="preserve" y="229.906" x="129" class="D F">179</text><text xml:space="preserve" y="229.906" x="163" class="D E M">180</text><text xml:space="preserve" y="229.906" x="200" class="D F">181</text><text xml:space="preserve" y="229.906" x="233" class="D E I">182</text><text xml:space="preserve" y="229.906" x="267" class="D E Y">183</text><text xml:space="preserve" y="229.906" x="302" class="D E N">184</text><text xml:space="preserve" y="229.906" x="337" class="D E Q">185</text><text xml:space="preserve" y="229.906" x="372" class="D E P">186</text><text xml:space="preserve" y="229.906" x="407" class="D E J">187</text><text xml:space="preserve" y="229.906" x="441" class="D E T">188</text><text xml:space="preserve" y="229.906" x="476" class="D E G">189</text><text xml:space="preserve" y="229.906" x="511" class="D E L">190</text><text xml:space="preserve" y="229.906" x="548" class="D F">191</text><text xml:space="preserve" y="229.906" x="581" class="D E K">192</text><text xml:space="preserve" y="229.906" x="616" class="D F">193</text><text xml:space="preserve" y="229.906" x="650" class="D E f">194</text><text xml:space="preserve" y="229.906" x="685" class="D E I">195</text><text xml:space="preserve" y="229.906" x="720" class="D E G">196</text><text xml:space="preserve" y="229.906" x="756" class="D F">197</text><text xml:space="preserve" y="229.906" x="789" class="D E H">198</text><text xml:space="preserve" y="229.906" x="824" class="D F">199</text><text xml:space="preserve" y="229.906" x="857" class="D E M">200</text><text xml:space="preserve" y="253.906" x="25" class="D E Z">201</text><text xml:space="preserve" y="253.906" x="58" class="D E g">202</text><text xml:space="preserve" y="253.906" x="92" class="D E O">203</text><text xml:space="preserve" y="253.906" x="127" class="D E J">204</text><text xml:space="preserve" y="253.906" x="162" class="D E R">205</text><text xml:space="preserve" y="253.906" x="197" class="D E h">206</text><text xml:space="preserve" y="253.906" x="232" class="D E N">207</text><text xml:space="preserve" y="253.906" x="266" class="D E K">208</text><text xml:space="preserve" y="253.906" x="301" class="D E L">209</text><text xml:space="preserve" y="253.906" x="337" class="D E G">210</text><text xml:space="preserve" y="253.906" x="374" class="D F">211</text><text xml:space="preserve" y="253.906" x="407" class="D E V">212</text><text xml:space="preserve" y="253.906" x="441" class="D E a">213</text><text xml:space="preserve" y="253.906" x="476" class="D E i">214</text><text xml:space="preserve" y="253.906" x="511" class="D E S">215</text><text xml:space="preserve" y="253.906" x="546" class="D E W">216</text><text xml:space="preserve" y="253.906" x="581" class="D E P">217</text><text xml:space="preserve" y="253.906" x="615" class="D E j">218</text><text xml:space="preserve" y="253.906" x="650" class="D E b">219</text><text xml:space="preserve" y="253.906" x="684" class="D E H">220</text><text xml:space="preserve" y="253.906" x="721" class="D E J">221</text><text xml:space="preserve" y="253.906" x="754" class="D E Q">222</text><text xml:space="preserve" y="253.906" x="789" class="D F">223</text><text xml:space="preserve" y="253.906" x="823" class="D E K">224</text><text xml:space="preserve" y="253.906" x="858" class="D E M">225</text><text xml:space="preserve" y="277.906" x="24" class="D E k">226</text><text xml:space="preserve" y="277.906" x="59" class="D F">227</text><text xml:space="preserve" y="277.906" x="92" class="D E L">228</text><text xml:space="preserve" y="277.906" x="128" class="D F">229</text><text xml:space="preserve" y="277.906" x="162" class="D E N">230</text><text xml:space="preserve" y="277.906" x="198" class="D E H">231</text><text xml:space="preserve" y="277.906" x="232" class="D E O">232</text><text xml:space="preserve" y="277.906" x="267" class="D F">233</text><text xml:space="preserve" y="277.906" x="301" class="D E I">234</text><text xml:space="preserve" y="277.906" x="336" class="D E T">235</text><text xml:space="preserve" y="277.906" x="371" class="D E X">236</text><text xml:space="preserve" y="277.906" x="406" class="D E c">237</text><text xml:space="preserve" y="277.906" x="440" class="D E J">238</text><text xml:space="preserve" y="277.906" x="476" class="D F">239</text><text xml:space="preserve" y="277.906" x="510" class="D E K">240</text><text xml:space="preserve" y="277.906" x="547" class="D F">241</text><text xml:space="preserve" y="277.906" x="580" class="D E H">242</text><text xml:space="preserve" y="277.906" x="614" class="D E m">243</text><text xml:space="preserve" y="277.906" x="649" class="D E Y">244</text><text xml:space="preserve" y="277.906" x="684" class="D E G">245</text><text xml:space="preserve" y="277.906" x="719" class="D E R">246</text><text xml:space="preserve" y="277.906" x="754" class="D E L">247</text><text xml:space="preserve" y="277.906" x="788" class="D E P">248</text><text xml:space="preserve" y="277.906" x="823" class="D E d">249</text><text xml:space="preserve" y="277.906" x="857" class="D E M">250</text><text xml:space="preserve" y="301.906" x="26" class="D F">251</text><text xml:space="preserve" y="301.906" x="58" class="D E G">252</text><text xml:space="preserve" y="301.906" x="92" class="D E N">253</text><text xml:space="preserve" y="301.906" x="127" class="D E n">254</text><text xml:space="preserve" y="301.906" x="162" class="D E J">255</text><text xml:space="preserve" y="301.906" x="197" class="D E K">256</text><text xml:space="preserve" y="301.906" x="233" class="D F">257</text><text xml:space="preserve" y="301.906" x="266" class="D E S">258</text><text xml:space="preserve" y="301.906" x="301" class="D E Q">259</text><text xml:space="preserve" y="301.906" x="336" class="D E I">260</text><text xml:space="preserve" y="301.906" x="372" class="D E O">261</text><text xml:space="preserve" y="301.906" x="406" class="D E o">262</text><text xml:space="preserve" y="301.906" x="441" class="D F">263</text><text xml:space="preserve" y="301.906" x="475" class="D E H">264</text><text xml:space="preserve" y="301.906" x="510" class="D E V">265</text><text xml:space="preserve" y="301.906" x="545" class="D E L">266</text><text xml:space="preserve" y="301.906" x="580" class="D E e">267</text><text xml:space="preserve" y="301.906" x="614" class="D E Z">268</text><text xml:space="preserve" y="301.906" x="650" class="D F">269</text><text xml:space="preserve" y="301.906" x="685" class="D E W">270</text><text xml:space="preserve" y="301.906" x="722" class="D F">271</text><text xml:space="preserve" y="301.906" x="754" class="D E K">272</text><text xml:space="preserve" y="301.906" x="789" class="D E I">273</text><text xml:space="preserve" y="301.906" x="824" class="D E p">274</text><text xml:space="preserve" y="301.906" x="858" class="D E H">275</text><text xml:space="preserve" y="325.906" x="24" class="D E N">276</text><text xml:space="preserve" y="325.906" x="59" class="D F">277</text><text xml:space="preserve" y="325.906" x="93" class="D E q">278</text><text xml:space="preserve" y="325.906" x="128" class="D E P">279</text><text xml:space="preserve" y="325.906" x="162" class="D E G">280</text><text xml:space="preserve" y="325.906" x="199" class="D F">281</text><text xml:space="preserve" y="325.906" x="232" class="D E T">282</text><text xml:space="preserve" y="325.906" x="267" class="D F">283</text><text xml:space="preserve" y="325.906" x="301" class="D E a">284</text><text xml:space="preserve" y="325.906" x="336" class="D E L">285</text><text xml:space="preserve" y="325.906" x="371" class="D E I">286</text><text xml:space="preserve" y="325.906" x="406" class="D E R">287</text><text xml:space="preserve" y="325.906" x="440" class="D E K">288</text><text xml:space="preserve" y="325.906" x="475" class="D E J">289</text><text xml:space="preserve" y="325.906" x="510" class="D E O">290</text><text xml:space="preserve" y="325.906" x="546" class="D E f">291</text><text xml:space="preserve" y="325.906" x="580" class="D E b">292</text><text xml:space="preserve" y="325.906" x="615" class="D F">293</text><text xml:space="preserve" y="325.906" x="649" class="D E G">294</text><text xml:space="preserve" y="325.906" x="684" class="D E X">295</text><text xml:space="preserve" y="325.906" x="719" class="D E Q">296</text><text xml:space="preserve" y="325.906" x="754" class="D E H">297</text><text xml:space="preserve" y="325.906" x="788" class="D E r">298</text><text xml:space="preserve" y="325.906" x="823" class="D E N">299</text><text xml:space="preserve" y="325.906" x="857" class="D E M">300</text><text xml:space="preserve" y="349.906" x="25" class="D E S">301</text><text xml:space="preserve" y="349.906" x="58" class="D E s">302</text><text xml:space="preserve" y="349.906" x="92" class="D E g">303</text><text xml:space="preserve" y="349.906" x="127" class="D E L">304</text><text xml:space="preserve" y="349.906" x="162" class="D E Y">305</text><text xml:space="preserve" y="349.906" x="197" class="D E J">306</text><text xml:space="preserve" y="349.906" x="233" class="D F">307</text><text xml:space="preserve" y="349.906" x="266" class="D E H">308</text><text xml:space="preserve" y="349.906" x="301" class="D E h">309</text><text xml:space="preserve" y="349.906" x="337" class="D E P">310</text><text xml:space="preserve" y="349.906" x="374" class="D F">311</text><text xml:space="preserve" y="349.906" x="407" class="D E I">312</text><text xml:space="preserve" y="349.906" x="442" class="D F">313</text><text fill="#72a694" xml:space="preserve" y="349.906" x="476" class="D E">314</text><text xml:space="preserve" y="349.906" x="511" class="D E G">315</text><text xml:space="preserve" y="349.906" x="546" class="D E c">316</text><text xml:space="preserve" y="349.906" x="582" class="D F">317</text><text xml:space="preserve" y="349.906" x="615" class="D E V">318</text><text xml:space="preserve" y="349.906" x="650" class="D E O">319</text><text xml:space="preserve" y="349.906" x="684" class="D E K">320</text><text xml:space="preserve" y="349.906" x="720" class="D E i">321</text><text xml:space="preserve" y="349.906" x="754" class="D E N">322</text><text xml:space="preserve" y="349.906" x="788" class="D E L">323</text><text xml:space="preserve" y="349.906" x="823" class="D E W">324</text><text xml:space="preserve" y="349.906" x="857" class="D E I">325</text><text fill="#aa85a2" xml:space="preserve" y="373.906" x="24" class="D E">326</text><text xml:space="preserve" y="373.906" x="58" class="D E j">327</text><text xml:space="preserve" y="373.906" x="92" class="D E R">328</text><text xml:space="preserve" y="373.906" x="127" class="D E T">329</text><text xml:space="preserve" y="373.906" x="162" class="D E H">330</text><text xml:space="preserve" y="373.906" x="199" class="D F">331</text><text xml:space="preserve" y="373.906" x="232" class="D E d">332</text><text xml:space="preserve" y="373.906" x="266" class="D E Q">333</text><text fill="#bca451" xml:space="preserve" y="373.906" x="301" class="D E">334</text><text xml:space="preserve" y="373.906" x="336" class="D E Z">335</text><text xml:space="preserve" y="373.906" x="371" class="D E K">336</text><text xml:space="preserve" y="373.906" x="407" class="D F">337</text><text xml:space="preserve" y="373.906" x="440" class="D E I">338</text><text xml:space="preserve" y="373.906" x="475" class="D E k">339</text><text xml:space="preserve" y="373.906" x="510" class="D E J">340</text><text xml:space="preserve" y="373.906" x="546" class="D E P">341</text><text xml:space="preserve" y="373.906" x="580" class="D E L">342</text><text xml:space="preserve" y="373.906" x="614" class="D E G">343</text><text xml:space="preserve" y="373.906" x="649" class="D E S">344</text><text xml:space="preserve" y="373.906" x="684" class="D E N">345</text><text fill="#8e8dba" xml:space="preserve" y="373.906" x="719" class="D E">346</text><text xml:space="preserve" y="373.906" x="755" class="D F">347</text><text xml:space="preserve" y="373.906" x="788" class="D E O">348</text><text xml:space="preserve" y="373.906" x="823" class="D F">349</text><text xml:space="preserve" y="373.906" x="857" class="D E G">350</text><text xml:space="preserve" y="397.906" x="25" class="D E I">351</text><text xml:space="preserve" y="397.906" x="58" class="D E K">352</text><text xml:space="preserve" y="397.906" x="93" class="D F">353</text><text xml:space="preserve" y="397.906" x="127" class="D E X">354</text><text xml:space="preserve" y="397.906" x="162" class="D E a">355</text><text xml:space="preserve" y="397.906" x="197" class="D E e">356</text><text xml:space="preserve" y="397.906" x="232" class="D E J">357</text><text fill="#79a79e" xml:space="preserve" y="397.906" x="266" class="D E">358</text><text xml:space="preserve" y="397.906" x="302" class="D F">359</text><text xml:space="preserve" y="397.906" x="336" class="D E t">360</text><text xml:space="preserve" y="397.906" x="372" class="D E L">361</text><text fill="#656186" xml:space="preserve" y="397.906" x="406" class="D E">362</text><text xml:space="preserve" y="397.906" x="440" class="D E H">363</text><text xml:space="preserve" y="397.906" x="475" class="D E I">364</text><text xml:space="preserve" y="397.906" x="510" class="D E b">365</text><text xml:space="preserve" y="397.906" x="545" class="D E Y">366</text><text xml:space="preserve" y="397.906" x="581" class="D F">367</text><text xml:space="preserve" y="397.906" x="614" class="D E N">368</text><text xml:space="preserve" y="397.906" x="649" class="D E R">369</text><text xml:space="preserve" y="397.906" x="685" class="D E Q">370</text><text xml:space="preserve" y="397.906" x="721" class="D E V">371</text><text xml:space="preserve" y="397.906" x="754" class="D E P">372</text><text xml:space="preserve" y="397.906" x="789" class="D F">373</text><text xml:space="preserve" y="397.906" x="823" class="D E J">374</text><text xml:space="preserve" y="397.906" x="858" class="D E M">375</text><text xml:space="preserve" y="421.906" x="24" class="D E T">376</text><text xml:space="preserve" y="421.906" x="59" class="D E O">377</text><text xml:space="preserve" y="421.906" x="92" class="D E W">378</text><text xml:space="preserve" y="421.906" x="128" class="D F">379</text><text xml:space="preserve" y="421.906" x="162" class="D E L">380</text><text xml:space="preserve" y="421.906" x="198" class="D E n">381</text><text fill="#94894b" xml:space="preserve" y="421.906" x="232" class="D E">382</text><text xml:space="preserve" y="421.906" x="267" class="D F">383</text><text xml:space="preserve" y="421.906" x="301" class="D E K">384</text><text xml:space="preserve" y="421.906" x="336" class="D E H">385</text><text fill="#87759e" xml:space="preserve" y="421.906" x="371" class="D E">386</text><text xml:space="preserve" y="421.906" x="406" class="D E S">387</text><text xml:space="preserve" y="421.906" x="440" class="D E f">388</text><text xml:space="preserve" y="421.906" x="476" class="D F">389</text><text xml:space="preserve" y="421.906" x="510" class="D E I">390</text><text xml:space="preserve" y="421.906" x="546" class="D E N">391</text><text xml:space="preserve" y="421.906" x="580" class="D E G">392</text><text xml:space="preserve" y="421.906" x="614" class="D E o">393</text><text fill="#9f6db4" xml:space="preserve" y="421.906" x="649" class="D E">394</text><text xml:space="preserve" y="421.906" x="684" class="D E c">395</text><text xml:space="preserve" y="421.906" x="719" class="D E H">396</text><text xml:space="preserve" y="421.906" x="755" class="D F">397</text><text fill="#aebba6" xml:space="preserve" y="421.906" x="788" class="D E">398</text><text xml:space="preserve" y="421.906" x="823" class="D E L">399</text><text xml:space="preserve" y="421.906" x="857" class="D E K">400</text><text xml:space="preserve" y="445.906" x="25" class="D F">401</text><text xml:space="preserve" y="445.906" x="58" class="D E Z">402</text><text xml:space="preserve" y="445.906" x="92" class="D E P">403</text><text xml:space="preserve" y="445.906" x="127" class="D E g">404</text><text xml:space="preserve" y="445.906" x="162" class="D E m">405</text><text xml:space="preserve" y="445.906" x="197" class="D E O">406</text><text xml:space="preserve" y="445.906" x="232" class="D E Q">407</text><text xml:space="preserve" y="445.906" x="266" class="D E J">408</text><text xml:space="preserve" y="445.906" x="302" class="D F">409</text><text xml:space="preserve" y="445.906" x="337" class="D E R">410</text><text xml:space="preserve" y="445.906" x="373" class="D E p">411</text><text xml:space="preserve" y="445.906" x="407" class="D E h">412</text><text xml:space="preserve" y="445.906" x="441" class="D E X">413</text><text xml:space="preserve" y="445.906" x="476" class="D E N">414</text><text xml:space="preserve" y="445.906" x="511" class="D E d">415</text><text xml:space="preserve" y="445.906" x="546" class="D E K">416</text><text xml:space="preserve" y="445.906" x="581" class="D E q">417</text><text xml:space="preserve" y="445.906" x="615" class="D E L">418</text><text xml:space="preserve" y="445.906" x="651" class="D F">419</text><text xml:space="preserve" y="445.906" x="684" class="D E G">420</text><text xml:space="preserve" y="445.906" x="721" class="D F">421</text><text fill="#61a569" xml:space="preserve" y="445.906" x="754" class="D E">422</text><text xml:space="preserve" y="445.906" x="788" class="D E T">423</text><text xml:space="preserve" y="445.906" x="823" class="D E V">424</text><text xml:space="preserve" y="445.906" x="857" class="D E J">425</text><text xml:space="preserve" y="469.906" x="24" class="D E a">426</text><text xml:space="preserve" y="469.906" x="58" class="D E Y">427</text><text xml:space="preserve" y="469.906" x="92" class="D E i">428</text><text xml:space="preserve" y="469.906" x="127" class="D E I">429</text><text xml:space="preserve" y="469.906" x="162" class="D E S">430</text><text xml:space="preserve" y="469.906" x="199" class="D F">431</text><text xml:space="preserve" y="469.906" x="232" class="D E W">432</text><text xml:space="preserve" y="469.906" x="267" class="D F">433</text><text xml:space="preserve" y="469.906" x="301" class="D E P">434</text><text xml:space="preserve" y="469.906" x="336" class="D E O">435</text><text xml:space="preserve" y="469.906" x="371" class="D E j">436</text><text xml:space="preserve" y="469.906" x="406" class="D E N">437</text><text xml:space="preserve" y="469.906" x="440" class="D E b">438</text><text xml:space="preserve" y="469.906" x="476" class="D F">439</text><text xml:space="preserve" y="469.906" x="510" class="D E H">440</text><text xml:space="preserve" y="469.906" x="546" class="D E G">441</text><text xml:space="preserve" y="469.906" x="580" class="D E J">442</text><text xml:space="preserve" y="469.906" x="615" class="D F">443</text><text xml:space="preserve" y="469.906" x="649" class="D E Q">444</text><text xml:space="preserve" y="469.906" x="684" class="D E e">445</text><text fill="#7e6bb4" xml:space="preserve" y="469.906" x="719" class="D E">446</text><text xml:space="preserve" y="469.906" x="754" class="D E r">447</text><text xml:space="preserve" y="469.906" x="788" class="D E K">448</text><text xml:space="preserve" y="469.906" x="823" class="D F">449</text><text xml:space="preserve" y="469.906" x="857" class="D E M">450</text><text xml:space="preserve" y="493.906" x="25" class="D E R">451</text><text xml:space="preserve" y="493.906" x="58" class="D E k">452</text><text xml:space="preserve" y="493.906" x="92" class="D E s">453</text><text fill="#a2569d" xml:space="preserve" y="493.906" x="127" class="D E">454</text><text xml:space="preserve" y="493.906" x="162" class="D E I">455</text><text xml:space="preserve" y="493.906" x="197" class="D E L">456</text><text xml:space="preserve" y="493.906" x="233" class="D F">457</text><text fill="#67ab80" xml:space="preserve" y="493.906" x="266" class="D E">458</text><text xml:space="preserve" y="493.906" x="301" class="D E J">459</text><text xml:space="preserve" y="493.906" x="336" class="D E N">460</text><text xml:space="preserve" y="493.906" x="373" class="D F">461</text><text xml:space="preserve" y="493.906" x="406" class="D E H">462</text><text xml:space="preserve" y="493.906" x="441" class="D F">463</text><text xml:space="preserve" y="493.906" x="475" class="D E O">464</text><text xml:space="preserve" y="493.906" x="510" class="D E P">465</text><text fill="#5db273" xml:space="preserve" y="493.906" x="545" class="D E">466</text><text xml:space="preserve" y="493.906" x="581" class="D F">467</text><text xml:space="preserve" y="493.906" x="614" class="D E I">468</text><text xml:space="preserve" y="493.906" x="649" class="D E Z">469</text><text xml:space="preserve" y="493.906" x="685" class="D E T">470</text><text fill="#72a694" xml:space="preserve" y="493.906" x="721" class="D E">471</text><text xml:space="preserve" y="493.906" x="754" class="D E X">472</text><text xml:space="preserve" y="493.906" x="789" class="D E S">473</text><text xml:space="preserve" y="493.906" x="823" class="D E c">474</text><text xml:space="preserve" y="493.906" x="858" class="D E L">475</text><text xml:space="preserve" y="517.906" x="24" class="D E J">476</text><text xml:space="preserve" y="517.906" x="58" class="D E V">477</text><text fill="#5c989e" xml:space="preserve" y="517.906" x="92" class="D E">478</text><text xml:space="preserve" y="517.906" x="128" class="D F">479</text><text xml:space="preserve" y="517.906" x="162" class="D E K">480</text><text xml:space="preserve" y="517.906" x="198" class="D E Q">481</text><text fill="#bb54ab" xml:space="preserve" y="517.906" x="232" class="D E">482</text><text xml:space="preserve" y="517.906" x="266" class="D E N">483</text><text xml:space="preserve" y="517.906" x="301" class="D E H">484</text><text xml:space="preserve" y="517.906" x="336" class="D E f">485</text><text xml:space="preserve" y="517.906" x="371" class="D E W">486</text><text xml:space="preserve" y="517.906" x="407" class="D F">487</text><text xml:space="preserve" y="517.906" x="440" class="D E Y">488</text><text fill="#aa85a2" xml:space="preserve" y="517.906" x="475" class="D E">489</text><text xml:space="preserve" y="517.906" x="510" class="D E G">490</text><text xml:space="preserve" y="517.906" x="547" class="D F">491</text><text xml:space="preserve" y="517.906" x="580" class="D E R">492</text><text xml:space="preserve" y="517.906" x="614" class="D E O">493</text><text xml:space="preserve" y="517.906" x="649" class="D E L">494</text><text xml:space="preserve" y="517.906" x="684" class="D E H">495</text><text xml:space="preserve" y="517.906" x="719" class="D E P">496</text><text xml:space="preserve" y="517.906" x="754" class="D E a">497</text><text xml:space="preserve" y="517.906" x="788" class="D E d">498</text><text xml:space="preserve" y="517.906" x="823" class="D F">499</text><text xml:space="preserve" y="517.906" x="857" class="D E M">500</text><text fill="#bca451" xml:space="preserve" y="541.906" x="25" class="D E">501</text><text fill="#40448a" xml:space="preserve" y="541.906" x="58" class="D E">502</text><text xml:space="preserve" y="541.906" x="93" class="D F">503</text><text xml:space="preserve" y="541.906" x="127" class="D E t">504</text><text xml:space="preserve" y="541.906" x="162" class="D E g">505</text><text xml:space="preserve" y="541.906" x="197" class="D E N">506</text><text xml:space="preserve" y="541.906" x="232" class="D E I">507</text><text xml:space="preserve" y="541.906" x="266" class="D E n">508</text><text xml:space="preserve" y="541.906" x="302" class="D F">509</text><text xml:space="preserve" y="541.906" x="337" class="D E J">510</text><text xml:space="preserve" y="541.906" x="373" class="D E b">511</text><text xml:space="preserve" y="541.906" x="407" class="D E K">512</text><text xml:space="preserve" y="541.906" x="441" class="D E L">513</text><text fill="#b9a185" xml:space="preserve" y="541.906" x="476" class="D E">514</text><text xml:space="preserve" y="541.906" x="511" class="D E h">515</text><text xml:space="preserve" y="541.906" x="546" class="D E S">516</text><text xml:space="preserve" y="541.906" x="581" class="D E T">517</text><text xml:space="preserve" y="541.906" x="615" class="D E Q">518</text><text fill="#8e8dba" xml:space="preserve" y="541.906" x="650" class="D E">519</text><text xml:space="preserve" y="541.906" x="684" class="D E I">520</text><text xml:space="preserve" y="541.906" x="721" class="D F">521</text><text xml:space="preserve" y="541.906" x="754" class="D E O">522</text><text xml:space="preserve" y="541.906" x="789" class="D F">523</text><text xml:space="preserve" y="541.906" x="823" class="D E o">524</text><text xml:space="preserve" y="541.906" x="857" class="D E G">525</text><text fill="#5f5fb5" xml:space="preserve" y="565.906" x="24" class="D E">526</text><text xml:space="preserve" y="565.906" x="58" class="D E P">527</text><text xml:space="preserve" y="565.906" x="92" class="D E K">528</text><text xml:space="preserve" y="565.906" x="127" class="D E N">529</text><text xml:space="preserve" y="565.906" x="162" class="D E V">530</text><text xml:space="preserve" y="565.906" x="198" class="D E X">531</text><text xml:space="preserve" y="565.906" x="232" class="D E L">532</text><text xml:space="preserve" y="565.906" x="266" class="D E R">533</text><text xml:space="preserve" y="565.906" x="301" class="D E e">534</text><text xml:space="preserve" y="565.906" x="336" class="D E i">535</text><text xml:space="preserve" y="565.906" x="371" class="D E Z">536</text><text fill="#79a79e" xml:space="preserve" y="565.906" x="406" class="D E">537</text><text fill="#a8b675" xml:space="preserve" y="565.906" x="440" class="D E">538</text><text xml:space="preserve" y="565.906" x="475" class="D E H">539</text><text xml:space="preserve" y="565.906" x="510" class="D E W">540</text><text xml:space="preserve" y="565.906" x="547" class="D F">541</text><text fill="#4c7c9f" xml:space="preserve" y="565.906" x="580" class="D E">542</text><text fill="#656186" xml:space="preserve" y="565.906" x="614" class="D E">543</text><text xml:space="preserve" y="565.906" x="649" class="D E J">544</text><text xml:space="preserve" y="565.906" x="684" class="D E j">545</text><text xml:space="preserve" y="565.906" x="719" class="D E I">546</text><text xml:space="preserve" y="565.906" x="755" class="D F">547</text><text xml:space="preserve" y="565.906" x="788" class="D E p">548</text><text xml:space="preserve" y="565.906" x="823" class="D E Y">549</text><text xml:space="preserve" y="565.906" x="857" class="D E H">550</text><text xml:space="preserve" y="589.906" x="25" class="D E O">551</text><text xml:space="preserve" y="589.906" x="58" class="D E N">552</text><text xml:space="preserve" y="589.906" x="92" class="D E c">553</text><text fill="#5d90b0" xml:space="preserve" y="589.906" x="127" class="D E">554</text><text xml:space="preserve" y="589.906" x="162" class="D E Q">555</text><text xml:space="preserve" y="589.906" x="197" class="D E q">556</text><text xml:space="preserve" y="589.906" x="233" class="D F">557</text><text xml:space="preserve" y="589.906" x="266" class="D E P">558</text><text xml:space="preserve" y="589.906" x="301" class="D E S">559</text><text xml:space="preserve" y="589.906" x="336" class="D E K">560</text><text xml:space="preserve" y="589.906" x="372" class="D E J">561</text><text fill="#578f8b" xml:space="preserve" y="589.906" x="406" class="D E">562</text><text xml:space="preserve" y="589.906" x="441" class="D F">563</text><text xml:space="preserve" y="589.906" x="475" class="D E T">564</text><text xml:space="preserve" y="589.906" x="510" class="D E k">565</text><text fill="#8985af" xml:space="preserve" y="589.906" x="545" class="D E">566</text><text xml:space="preserve" y="589.906" x="580" class="D E m">567</text><text xml:space="preserve" y="589.906" x="614" class="D E a">568</text><text xml:space="preserve" y="589.906" x="650" class="D F">569</text><text xml:space="preserve" y="589.906" x="685" class="D E L">570</text><text xml:space="preserve" y="589.906" x="721" class="D F">571</text><text xml:space="preserve" y="589.906" x="754" class="D E I">572</text><text fill="#94894b" xml:space="preserve" y="589.906" x="789" class="D E">573</text><text xml:space="preserve" y="589.906" x="823" class="D E R">574</text><text xml:space="preserve" y="589.906" x="858" class="D E N">575</text><text xml:space="preserve" y="613.906" x="24" class="D E t">576</text><text xml:space="preserve" y="613.906" x="59" class="D F">577</text><text xml:space="preserve" y="613.906" x="92" class="D E J">578</text><text fill="#87759e" xml:space="preserve" y="613.906" x="128" class="D E">579</text><text xml:space="preserve" y="613.906" x="162" class="D E O">580</text><text xml:space="preserve" y="613.906" x="198" class="D E d">581</text><text xml:space="preserve" y="613.906" x="232" class="D E f">582</text><text xml:space="preserve" y="613.906" x="266" class="D E V">583</text><text xml:space="preserve" y="613.906" x="301" class="D E b">584</text><text xml:space="preserve" y="613.906" x="336" class="D E I">585</text><text fill="#ab6984" xml:space="preserve" y="613.906" x="371" class="D E">586</text><text xml:space="preserve" y="613.906" x="407" class="D F">587</text><text xml:space="preserve" y="613.906" x="440" class="D E G">588</text><text xml:space="preserve" y="613.906" x="475" class="D E P">589</text><text xml:space="preserve" y="613.906" x="510" class="D E X">590</text><text fill="#9f6db4" xml:space="preserve" y="613.906" x="546" class="D E">591</text><text xml:space="preserve" y="613.906" x="580" class="D E Q">592</text><text xml:space="preserve" y="613.906" x="615" class="D F">593</text><text xml:space="preserve" y="613.906" x="649" class="D E W">594</text><text xml:space="preserve" y="613.906" x="684" class="D E J">595</text><text xml:space="preserve" y="613.906" x="719" class="D E r">596</text><text fill="#aebba6" xml:space="preserve" y="613.906" x="754" class="D E">597</text><text xml:space="preserve" y="613.906" x="788" class="D E N">598</text><text xml:space="preserve" y="613.906" x="823" class="D F">599</text><text xml:space="preserve" y="613.906" x="857" class="D E M">600</text><text xml:space="preserve" y="637.906" x="26" class="D F">601</text><text xml:space="preserve" y="637.906" x="58" class="D E S">602</text><text xml:space="preserve" y="637.906" x="92" class="D E Z">603</text><text xml:space="preserve" y="637.906" x="127" class="D E s">604</text><text xml:space="preserve" y="637.906" x="162" class="D E H">605</text><text xml:space="preserve" y="637.906" x="197" class="D E g">606</text><text xml:space="preserve" y="637.906" x="233" class="D F">607</text><text xml:space="preserve" y="637.906" x="266" class="D E L">608</text><text xml:space="preserve" y="637.906" x="301" class="D E O">609</text><text xml:space="preserve" y="637.906" x="337" class="D E Y">610</text><text xml:space="preserve" y="637.906" x="373" class="D E T">611</text><text xml:space="preserve" y="637.906" x="407" class="D E J">612</text><text xml:space="preserve" y="637.906" x="442" class="D F">613</text><text fill="#9b6f5d" xml:space="preserve" y="637.906" x="476" class="D E">614</text><text xml:space="preserve" y="637.906" x="511" class="D E R">615</text><text xml:space="preserve" y="637.906" x="546" class="D E H">616</text><text xml:space="preserve" y="637.906" x="582" class="D F">617</text><text xml:space="preserve" y="637.906" x="615" class="D E h">618</text><text xml:space="preserve" y="637.906" x="651" class="D F">619</text><text xml:space="preserve" y="637.906" x="684" class="D E P">620</text><text xml:space="preserve" y="637.906" x="720" class="D E N">621</text><text fill="#be7384" xml:space="preserve" y="637.906" x="754" class="D E">622</text><text xml:space="preserve" y="637.906" x="788" class="D E e">623</text><text xml:space="preserve" y="637.906" x="823" class="D E K">624</text><text xml:space="preserve" y="637.906" x="857" class="D E M">625</text></g></svg>
diff --git a/examples/async/eratosthenes/eratosthenes.py b/examples/async/eratosthenes/eratosthenes.py
new file mode 100644
index 000000000..e57c3c3bc
--- /dev/null
+++ b/examples/async/eratosthenes/eratosthenes.py
@@ -0,0 +1,234 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import (Qt, QEvent, QObject, QTimer, Signal, Slot)
+from PySide6.QtGui import (QColor, QFont, QPalette)
+from PySide6.QtWidgets import (QApplication, QGridLayout, QLabel, QMainWindow, QVBoxLayout, QWidget)
+
+import outcome
+import signal
+import sys
+import traceback
+import trio
+from random import randint
+
+
+class MainWindow(QMainWindow):
+
+ set_num = Signal(int, QColor)
+
+ def __init__(self, rows, cols):
+ super().__init__()
+
+ self.rows = rows
+ self.cols = cols
+
+ widget_central = QWidget()
+ self.setCentralWidget(widget_central)
+
+ layout_outer = QVBoxLayout(widget_central)
+
+ self.widget_outer_text = QLabel()
+ font = QFont()
+ font.setPointSize(14)
+ self.widget_outer_text.setFont(font)
+ layout_outer.addWidget(self.widget_outer_text, alignment=Qt.AlignmentFlag.AlignCenter)
+
+ widget_inner_grid = QWidget()
+ layout_outer.addWidget(widget_inner_grid, alignment=Qt.AlignmentFlag.AlignCenter)
+
+ self.layout_inner_grid = QGridLayout(widget_inner_grid)
+ k = 1
+ for i in range(self.rows):
+ for j in range(self.cols):
+ box = QLabel(f"{k}")
+ self.layout_inner_grid.addWidget(box, i, j, Qt.AlignmentFlag.AlignCenter)
+ k += 1
+
+ self.set_num.connect(self.set_num_handler)
+
+ @Slot(int, QColor)
+ def set_num_handler(self, i, color):
+ row = int((i - 1) / self.cols)
+ col = (i - 1) - (row * self.cols)
+ widget = self.layout_inner_grid.itemAtPosition(row, col).widget()
+
+ font = QFont()
+ font.setWeight(QFont.Bold)
+ palette = QPalette()
+ palette.setColor(QPalette.WindowText, color)
+ widget.setFont(font)
+ widget.setPalette(palette)
+
+
+class Eratosthenes():
+
+ """ This Sieve of Eratosthenes runs on a configurable tick (default
+ 0.1 seconds). At each tick, a new subroutine will be created
+ that will check multiples of the next prime number. Each of
+ these subroutines also operates on the same tick. """
+
+ def __init__(self, num, window, tick=0.1):
+ self.num = num
+ self.sieve = [True] * self.num
+ self.base = 0
+ self.window = window
+ self.tick = tick
+ self.coroutines = []
+ self.done = False
+ self.nursery = None
+
+ async def start(self):
+ async with trio.open_nursery() as self.nursery:
+ self.nursery.start_soon(self.update_text)
+ while self.base <= self.num / 2:
+ await trio.sleep(self.tick)
+ for i in range(self.base + 1, self.num):
+ if self.sieve[i]:
+ self.base = i
+ break
+ self.nursery.start_soon(self.mark_number, self.base + 1)
+ while sum(self.coroutines) > 0:
+ await trio.sleep(self.tick)
+ self.done = True
+
+ async def mark_number(self, base):
+ id = len(self.coroutines)
+ self.coroutines.append(1)
+ color = QColor(randint(64, 192), randint(64, 192), randint(64, 192))
+ for i in range(2 * base, self.num + 1, base):
+ if self.sieve[i - 1]:
+ self.sieve[i - 1] = False
+ self.window.set_num.emit(i, color)
+ await trio.sleep(self.tick)
+ self.coroutines[id] = 0
+
+ async def update_text(self):
+ while not self.done:
+ await trio.sleep(self.tick)
+ if int(trio.lowlevel.current_clock().current_time() + self.tick) % 2:
+ text = "⚙️ ...Calculating prime numbers... ⚙️"
+ else:
+ text = "👩‍💻 ...Hacking the universe... 👩‍💻"
+ self.window.widget_outer_text.setText(text)
+
+ self.window.widget_outer_text.setText(
+ "🥳 Congratulations! You found all the prime numbers and solved mathematics. 🥳"
+ )
+
+
+class AsyncHelper(QObject):
+
+ trigger_signal = Signal()
+
+ class ReenterQtObject(QObject):
+ """ This is a QObject to which an event will be posted, allowing
+ Trio to resume when the event is handled. event.fn() is the
+ next entry point of the Trio event loop. """
+ def event(self, event):
+ if event.type() == QEvent.User + 1:
+ event.fn()
+ return True
+ return False
+
+ class ReenterQtEvent(QEvent):
+ """ This is the QEvent that will be handled by the ReenterQtObject.
+ self.fn is the next entry point of the Trio event loop. """
+ def __init__(self, fn):
+ super().__init__(QEvent.Type(QEvent.User + 1))
+ self.fn = fn
+
+ def __init__(self, entry=None):
+ super().__init__()
+ self.reenter_qt = self.ReenterQtObject()
+ self.entry = entry
+
+ def set_entry(self, entry):
+ self.entry = entry
+
+ @Slot()
+ def launch_guest_run(self):
+ """ To use Trio and Qt together, one must run the Trio event
+ loop as a "guest" inside the Qt "host" event loop. """
+ if not self.entry:
+ raise Exception("No entry point for the Trio guest run was set.")
+ trio.lowlevel.start_guest_run(
+ self.entry,
+ run_sync_soon_threadsafe=self.next_guest_run_schedule,
+ done_callback=self.trio_done_callback,
+ )
+
+ def next_guest_run_schedule(self, fn):
+ """ This function serves to re-schedule the guest (Trio) event
+ loop inside the host (Qt) event loop. It is called by Trio
+ at the end of an event loop run in order to relinquish back
+ to Qt's event loop. By posting an event on the Qt event loop
+ that contains Trio's next entry point, it ensures that Trio's
+ event loop will be scheduled again by Qt. """
+ QApplication.postEvent(self.reenter_qt, self.ReenterQtEvent(fn))
+
+ def trio_done_callback(self, outcome_):
+ """ This function is called by Trio when its event loop has
+ finished. """
+ if isinstance(outcome_, outcome.Error):
+ error = outcome_.error
+ traceback.print_exception(type(error), error, error.__traceback__)
+
+
+if __name__ == "__main__":
+ rows = 40
+ cols = 40
+ num = rows * cols
+
+ app = QApplication(sys.argv)
+ main_window = MainWindow(rows, cols)
+ eratosthenes = Eratosthenes(num, main_window)
+ async_helper = AsyncHelper(entry=eratosthenes.start)
+
+ # This establishes the entry point for the Trio guest run. It varies
+ # depending on how and when its event loop is to be triggered, e.g.,
+ # from the beginning (as here) or rather at a specific moment like
+ # a button press.
+ QTimer.singleShot(0, async_helper.launch_guest_run)
+
+ main_window.show()
+
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ app.exec()
diff --git a/examples/async/eratosthenes/eratosthenes.pyproject b/examples/async/eratosthenes/eratosthenes.pyproject
new file mode 100644
index 000000000..8ea189b3c
--- /dev/null
+++ b/examples/async/eratosthenes/eratosthenes.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["eratosthenes.py"]
+}
diff --git a/examples/async/eratosthenes/requirements.txt b/examples/async/eratosthenes/requirements.txt
new file mode 100644
index 000000000..e2cc10204
--- /dev/null
+++ b/examples/async/eratosthenes/requirements.txt
@@ -0,0 +1,2 @@
+trio
+outcome
diff --git a/examples/async/minimal/doc/minimal.png b/examples/async/minimal/doc/minimal.png
new file mode 100644
index 000000000..b8a18963f
--- /dev/null
+++ b/examples/async/minimal/doc/minimal.png
Binary files differ
diff --git a/examples/async/minimal/doc/minimal.rst b/examples/async/minimal/doc/minimal.rst
new file mode 100644
index 000000000..a72e8a73c
--- /dev/null
+++ b/examples/async/minimal/doc/minimal.rst
@@ -0,0 +1,41 @@
+Async examples
+==============
+
+The Python language provides keywords for asynchronous operations, i.e.,
+"async" to define coroutines or "await" to schedule asynchronous calls in the
+event loop (see `PEP 492 <https://peps.python.org/pep-0492/>`_). It is up to
+packages to implement an event loop, support for these keywords, and more.
+
+One such package is `trio`. Since both an async package and Qt itself work with
+event loops, special care must be taken to ensure that both event loops work
+with each other. trio offers a dedicated `low-level API
+<https://trio.readthedocs.io/en/stable/reference-lowlevel.html>`_ for more
+complicated use cases such as this. Specifically, there exists a function
+`start_guest_run` that enables running the Trio event loop as a "guest" inside
+another event loop - Qt's in our case.
+
+Based on this functionality, two examples for async usage with Qt have been
+implemented: `eratosthenes` and `minimal`:
+
+.. image:: minimal.png
+ :alt: Async example: Minimal
+
+* `eratosthenes` is a more extensive example that visualizes the Sieve of
+Eratosthenes algorithm. This algorithm per se is not one that is particularly
+suitable for asynchronous operations as it's not I/O-heavy, but synchronizing
+coroutines to a configurable tick allows for a good visualization.
+* `minimal` is a minimal example featuring a button that triggers an
+asynchronous coroutine with a sleep. It is designed to highlight which
+boilerplate code is essential for an async program with Qt and offers a
+starting point for more complex programs.
+
+Both examples feature:
+
+1. A window class.
+2. An `AsyncHelper` class containing `start_guest_run` plus helpers and
+callbacks necessary for its invocation. The entry point for the Trio guest run
+is provided as an argument from outside, which can be any async function.
+
+While `eratosthenes` offloads the asynchronous logic that will run in trio's
+event loop into a separate class, `minimal` demonstrates that async functions
+can be integrated into any class, including subclasses of Qt classes.
diff --git a/examples/async/minimal/minimal.py b/examples/async/minimal/minimal.py
new file mode 100644
index 000000000..b816f5725
--- /dev/null
+++ b/examples/async/minimal/minimal.py
@@ -0,0 +1,152 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import (Qt, QEvent, QObject, Signal, Slot)
+from PySide6.QtWidgets import (QApplication, QLabel, QMainWindow, QPushButton, QVBoxLayout, QWidget)
+
+import outcome
+import signal
+import sys
+import traceback
+import trio
+
+
+class MainWindow(QMainWindow):
+
+ def __init__(self, async_signal):
+ super().__init__()
+
+ self.async_signal = async_signal
+
+ widget = QWidget()
+ self.setCentralWidget(widget)
+
+ layout = QVBoxLayout(widget)
+
+ self.text = QLabel("The answer is 42.")
+ layout.addWidget(self.text, alignment=Qt.AlignmentFlag.AlignCenter)
+
+ async_trigger = QPushButton(text="What is the question?")
+ async_trigger.clicked.connect(self.async_start)
+ layout.addWidget(async_trigger, alignment=Qt.AlignmentFlag.AlignCenter)
+
+ @Slot()
+ def async_start(self):
+ self.async_signal.emit()
+
+ async def set_text(self):
+ await trio.sleep(1)
+ self.text.setText("What do you get if you multiply six by nine?")
+
+
+class AsyncHelper(QObject):
+
+ trigger_signal = Signal()
+
+ class ReenterQtObject(QObject):
+ """ This is a QObject to which an event will be posted, allowing
+ Trio to resume when the event is handled. event.fn() is the
+ next entry point of the Trio event loop. """
+ def event(self, event):
+ if event.type() == QEvent.User + 1:
+ event.fn()
+ return True
+ return False
+
+ class ReenterQtEvent(QEvent):
+ """ This is the QEvent that will be handled by the ReenterQtObject.
+ self.fn is the next entry point of the Trio event loop. """
+ def __init__(self, fn):
+ super().__init__(QEvent.Type(QEvent.User + 1))
+ self.fn = fn
+
+ def __init__(self, entry=None):
+ super().__init__()
+ self.reenter_qt = self.ReenterQtObject()
+ self.entry = entry
+
+ def set_entry(self, entry):
+ self.entry = entry
+
+ @Slot()
+ def launch_guest_run(self):
+ """ To use Trio and Qt together, one must run the Trio event
+ loop as a "guest" inside the Qt "host" event loop. """
+ if not self.entry:
+ raise Exception("No entry point for the Trio guest run was set.")
+ trio.lowlevel.start_guest_run(
+ self.entry,
+ run_sync_soon_threadsafe=self.next_guest_run_schedule,
+ done_callback=self.trio_done_callback,
+ )
+
+ def next_guest_run_schedule(self, fn):
+ """ This function serves to re-schedule the guest (Trio) event
+ loop inside the host (Qt) event loop. It is called by Trio
+ at the end of an event loop run in order to relinquish back
+ to Qt's event loop. By posting an event on the Qt event loop
+ that contains Trio's next entry point, it ensures that Trio's
+ event loop will be scheduled again by Qt. """
+ QApplication.postEvent(self.reenter_qt, self.ReenterQtEvent(fn))
+
+ def trio_done_callback(self, outcome_):
+ """ This function is called by Trio when its event loop has
+ finished. """
+ if isinstance(outcome_, outcome.Error):
+ error = outcome_.error
+ traceback.print_exception(type(error), error, error.__traceback__)
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ async_helper = AsyncHelper()
+ main_window = MainWindow(async_helper.trigger_signal)
+ async_helper.set_entry(main_window.set_text)
+
+ # This establishes the entry point for the Trio guest run. It varies
+ # depending on how and when its event loop is to be triggered, e.g.,
+ # at a specific moment like a button press (as here) or rather from
+ # the beginning.
+ async_helper.trigger_signal.connect(async_helper.launch_guest_run)
+
+ main_window.show()
+
+ signal.signal(signal.SIGINT, signal.SIG_DFL)
+ app.exec()
diff --git a/examples/async/minimal/minimal.pyproject b/examples/async/minimal/minimal.pyproject
new file mode 100644
index 000000000..97ff6dbc5
--- /dev/null
+++ b/examples/async/minimal/minimal.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["minimal.py"]
+}
diff --git a/examples/async/minimal/requirements.txt b/examples/async/minimal/requirements.txt
new file mode 100644
index 000000000..ae0d704f0
--- /dev/null
+++ b/examples/async/minimal/requirements.txt
@@ -0,0 +1 @@
+trio
diff --git a/examples/bluetooth/btscanner/device.py b/examples/bluetooth/btscanner/device.py
index bf8194bc5..feb1cd967 100644
--- a/examples/bluetooth/btscanner/device.py
+++ b/examples/bluetooth/btscanner/device.py
@@ -125,7 +125,7 @@ class DeviceDiscoveryDialog(QDialog):
else:
self._local_device.setHostMode(QBluetoothLocalDevice.HostPoweredOff)
- @Slot(QBluetoothLocalDevice.HostMode)
+ @Slot("QBluetoothLocalDevice::HostMode")
def host_mode_state_changed(self, mode):
self._ui.power.setChecked(mode != QBluetoothLocalDevice.HostPoweredOff)
self._ui.discoverable.setChecked(mode == QBluetoothLocalDevice.HostDiscoverable)
@@ -155,7 +155,7 @@ class DeviceDiscoveryDialog(QDialog):
elif chosen_action == remove_pair_action:
self._local_device.requestPairing(address, QBluetoothLocalDevice.Unpaired)
- @Slot(QBluetoothAddress, QBluetoothLocalDevice.Pairing)
+ @Slot(QBluetoothAddress, "QBluetoothLocalDevice::Pairing")
def pairing_done(self, address, pairing):
items = self._ui.list.findItems(address.toString(), Qt.MatchContains)
diff --git a/examples/bluetooth/heartrate_game/bluetoothbaseclass.py b/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
new file mode 100644
index 000000000..c214659ac
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
@@ -0,0 +1,77 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import QObject, Property, Signal, Slot
+
+
+class BluetoothBaseClass(QObject):
+
+ errorChanged = Signal()
+ infoChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.m_error = ""
+ self.m_info = ""
+
+ @Property(str, notify=errorChanged)
+ def error(self):
+ return self.m_error
+
+ @error.setter
+ def error(self, e):
+ if self.m_error != e:
+ self.m_error = e
+ self.errorChanged.emit()
+
+ @Property(str, notify=infoChanged)
+ def info(self):
+ return self.m_info
+
+ @info.setter
+ def info(self, i):
+ if self.m_info != i:
+ self.m_info = i
+ self.infoChanged.emit()
+
+ @Slot()
+ def clearMessages(self):
+ self.info = ""
+ self.error = ""
diff --git a/examples/bluetooth/heartrate_game/connectionhandler.py b/examples/bluetooth/heartrate_game/connectionhandler.py
new file mode 100644
index 000000000..b628e867a
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/connectionhandler.py
@@ -0,0 +1,88 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtBluetooth import QBluetoothLocalDevice
+from PySide6.QtQml import QmlElement
+from PySide6.QtCore import QObject, Property, Signal, Slot
+
+from heartrate_global import simulator
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Shared"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class ConnectionHandler(QObject):
+
+ deviceChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.m_localDevice = QBluetoothLocalDevice()
+ self.m_localDevice.hostModeStateChanged.connect(self.hostModeChanged)
+
+ @Property(bool, notify=deviceChanged)
+ def alive(self):
+ if sys.platform == "darwin":
+ return True
+ if simulator:
+ return True
+ return (self.m_localDevice.isValid()
+ and self.m_localDevice.hostMode() != QBluetoothLocalDevice.HostPoweredOff)
+
+ @Property(bool, constant=True)
+ def requiresAddressType(self):
+ return sys.platform == "linux" # QT_CONFIG(bluez)?
+
+ @Property(str, notify=deviceChanged)
+ def name(self):
+ return self.m_localDevice.name()
+
+ @Property(str, notify=deviceChanged)
+ def address(self):
+ return self.m_localDevice.address().toString()
+
+ @Slot(QBluetoothLocalDevice.HostMode)
+ def hostModeChanged(self, mode):
+ self.deviceChanged.emit()
diff --git a/examples/bluetooth/heartrate_game/devicefinder.py b/examples/bluetooth/heartrate_game/devicefinder.py
new file mode 100644
index 000000000..7527d841e
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/devicefinder.py
@@ -0,0 +1,159 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtBluetooth import (QBluetoothDeviceDiscoveryAgent,
+ QBluetoothDeviceInfo)
+from PySide6.QtQml import QmlElement
+from PySide6.QtCore import QTimer, Property, Signal, Slot
+
+from bluetoothbaseclass import BluetoothBaseClass
+from deviceinfo import DeviceInfo
+from heartrate_global import simulator
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Shared"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+class DeviceFinder(BluetoothBaseClass):
+
+ scanningChanged = Signal()
+ devicesChanged = Signal()
+
+ def __init__(self, handler, parent=None):
+ super().__init__(parent)
+ self.m_deviceHandler = handler
+ self.m_devices = []
+ self.m_demoTimer = QTimer()
+#! [devicediscovery-1]
+ self.m_deviceDiscoveryAgent = QBluetoothDeviceDiscoveryAgent(self)
+ self.m_deviceDiscoveryAgent.setLowEnergyDiscoveryTimeout(15000)
+ self.m_deviceDiscoveryAgent.deviceDiscovered.connect(self.addDevice)
+ self.m_deviceDiscoveryAgent.errorOccurred.connect(self.scanError)
+
+ self.m_deviceDiscoveryAgent.finished.connect(self.scanFinished)
+ self.m_deviceDiscoveryAgent.canceled.connect(self.scanFinished)
+#! [devicediscovery-1]
+ if simulator:
+ self.m_demoTimer.setSingleShot(True)
+ self.m_demoTimer.setInterval(2000)
+ self.m_demoTimer.timeout.connect(self.scanFinished)
+
+ @Slot()
+ def startSearch(self):
+ self.clearMessages()
+ self.m_deviceHandler.setDevice(None)
+ self.m_devices.clear()
+
+ self.devicesChanged.emit()
+
+ if simulator:
+ self.m_demoTimer.start()
+ else:
+#! [devicediscovery-2]
+ self.m_deviceDiscoveryAgent.start(QBluetoothDeviceDiscoveryAgent.LowEnergyMethod)
+#! [devicediscovery-2]
+ self.scanningChanged.emit()
+ self.info = "Scanning for devices..."
+
+#! [devicediscovery-3]
+ @Slot(QBluetoothDeviceInfo)
+ def addDevice(self, device):
+ # If device is LowEnergy-device, add it to the list
+ if device.coreConfigurations() & QBluetoothDeviceInfo.LowEnergyCoreConfiguration:
+ self.m_devices.append(DeviceInfo(device))
+ self.info = "Low Energy device found. Scanning more..."
+#! [devicediscovery-3]
+ self.devicesChanged.emit()
+#! [devicediscovery-4]
+ #...
+#! [devicediscovery-4]
+
+ @Slot(QBluetoothDeviceDiscoveryAgent.Error)
+ def scanError(self, error):
+ if error == QBluetoothDeviceDiscoveryAgent.PoweredOffError:
+ self.error = "The Bluetooth adaptor is powered off."
+ elif error == QBluetoothDeviceDiscoveryAgent.InputOutputError:
+ self.error = "Writing or reading from the device resulted in an error."
+ else:
+ self.error = "An unknown error has occurred."
+
+ @Slot()
+ def scanFinished(self):
+ if simulator:
+ # Only for testing
+ for i in range(5):
+ self.m_devices.append(DeviceInfo(QBluetoothDeviceInfo()))
+
+ if self.m_devices:
+ self.info = "Scanning done."
+ else:
+ self.error = "No Low Energy devices found."
+
+ self.scanningChanged.emit()
+ self.devicesChanged.emit()
+
+ @Slot(str)
+ def connectToService(self, address):
+ self.m_deviceDiscoveryAgent.stop()
+
+ currentDevice = None
+ for entry in self.m_devices:
+ device = entry
+ if device and device.deviceAddress == address:
+ currentDevice = device
+ break
+
+ if currentDevice:
+ self.m_deviceHandler.setDevice(currentDevice)
+
+ self.clearMessages()
+
+ @Property(bool, notify=scanningChanged)
+ def scanning(self):
+ if simulator:
+ return self.m_demoTimer.isActive()
+ return self.m_deviceDiscoveryAgent.isActive()
+
+ @Property("QVariant", notify=devicesChanged)
+ def devices(self):
+ return self.m_devices
diff --git a/examples/bluetooth/heartrate_game/devicehandler.py b/examples/bluetooth/heartrate_game/devicehandler.py
new file mode 100644
index 000000000..93b438f9c
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/devicehandler.py
@@ -0,0 +1,344 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 struct
+
+from enum import IntEnum
+
+from PySide6.QtBluetooth import (QLowEnergyCharacteristic,
+ QLowEnergyController,
+ QLowEnergyDescriptor,
+ QLowEnergyService,
+ QBluetoothUuid)
+from PySide6.QtQml import QmlNamedElement, QmlUncreatable
+from PySide6.QtCore import (QByteArray, QDateTime, QRandomGenerator, QTimer,
+ Property, Signal, Slot, QEnum)
+
+from bluetoothbaseclass import BluetoothBaseClass
+from heartrate_global import simulator
+
+
+# To be used on the @QmlElement decorator
+# (QML_IMPORT_MINOR_VERSION is optional)
+QML_IMPORT_NAME = "Shared"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlNamedElement("AddressType")
+@QmlUncreatable("Enum is not a type")
+class DeviceHandler(BluetoothBaseClass):
+
+ @QEnum
+ class AddressType(IntEnum):
+ PUBLIC_ADDRESS = 1
+ RANDOM_ADDRESS = 2
+
+ measuringChanged = Signal()
+ aliveChanged = Signal()
+ statsChanged = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.m_control = None
+ self.m_service = None
+ self.m_notificationDesc = QLowEnergyDescriptor()
+ self.m_currentDevice = None
+
+ self.m_foundHeartRateService = False
+ self.m_measuring = False
+ self.m_currentValue = 0
+ self.m_min = 0
+ self.m_max = 0
+ self.m_sum = 0
+ self.m_avg = 0.0
+ self.m_calories = 0.0
+
+ self.m_start = QDateTime()
+ self.m_stop = QDateTime()
+
+ self.m_measurements = []
+ self.m_addressType = QLowEnergyController.PublicAddress
+
+ self.m_demoTimer = QTimer()
+
+ if simulator:
+ self.m_demoTimer.setSingleShot(False)
+ self.m_demoTimer.setInterval(2000)
+ self.m_demoTimer.timeout.connect(self.updateDemoHR)
+ self.m_demoTimer.start()
+ self.updateDemoHR()
+
+ @Property(int)
+ def addressType(self):
+ if self.m_addressType == QLowEnergyController.RandomAddress:
+ return DeviceHandler.AddressType.RANDOM_ADDRESS
+ return DeviceHandler.AddressType.PUBLIC_ADDRESS
+
+ @addressType.setter
+ def addressType(self, type):
+ if type == DeviceHandler.AddressType.PUBLIC_ADDRESS:
+ self.m_addressType = QLowEnergyController.PublicAddress
+ elif type == DeviceHandler.AddressType.RANDOM_ADDRESS:
+ self.m_addressType = QLowEnergyController.RandomAddress
+
+ @Slot(QLowEnergyController.Error)
+ def controllerErrorOccurred(self, device):
+ self.error = "Cannot connect to remote device."
+
+ @Slot()
+ def controllerConnected(self):
+ self.info = "Controller connected. Search services..."
+ self.m_control.discoverServices()
+
+ @Slot()
+ def controllerDisconnected(self):
+ self.error = "LowEnergy controller disconnected"
+
+ def setDevice(self, device):
+ self.clearMessages()
+ self.m_currentDevice = device
+
+ if simulator:
+ self.info = "Demo device connected."
+ return
+
+ # Disconnect and delete old connection
+ if self.m_control:
+ self.m_control.disconnectFromDevice()
+ m_control = None
+
+ # Create new controller and connect it if device available
+ if self.m_currentDevice:
+
+ # Make connections
+#! [Connect-Signals-1]
+ self.m_control = QLowEnergyController.createCentral(self.m_currentDevice.getDevice(), self)
+#! [Connect-Signals-1]
+ self.m_control.setRemoteAddressType(self.m_addressType)
+#! [Connect-Signals-2]
+
+ m_control.serviceDiscovered.connect(self.serviceDiscovered)
+ m_control.discoveryFinished.connect(self.serviceScanDone)
+
+ self.m_control.errorOccurred.connect(self.controllerErrorOccurred)
+ self.m_control.connected.connect(self.controllerConnected)
+ self.m_control.disconnected.connect(self.controllerDisconnected)
+
+ # Connect
+ self.m_control.connectToDevice()
+#! [Connect-Signals-2]
+
+ @Slot()
+ def startMeasurement(self):
+ if self.alive:
+ self.m_start = QDateTime.currentDateTime()
+ self.m_min = 0
+ self.m_max = 0
+ self.m_avg = 0
+ self.m_sum = 0
+ self.m_calories = 0.0
+ self.m_measuring = True
+ self.m_measurements.clear()
+ self.measuringChanged.emit()
+
+ @Slot()
+ def stopMeasurement(self):
+ self.m_measuring = False
+ self.measuringChanged.emit()
+
+#! [Filter HeartRate service 1]
+ @Slot(QBluetoothUuid)
+ def serviceDiscovered(self, gatt):
+ if gatt == QBluetoothUuid(QBluetoothUuid.ServiceClassUuid.HeartRate):
+ self.info = "Heart Rate service discovered. Waiting for service scan to be done..."
+ self.m_foundHeartRateService = True
+
+#! [Filter HeartRate service 1]
+
+ @Slot()
+ def serviceScanDone(self):
+ self.info = "Service scan done."
+
+ # Delete old service if available
+ if self.m_service:
+ self.m_service = None
+
+#! [Filter HeartRate service 2]
+ # If heartRateService found, create new service
+ if self.m_foundHeartRateService:
+ self.m_service = self.m_control.createServiceObject(QBluetoothUuid(QBluetoothUuid.ServiceClassUuid.HeartRate), self)
+
+ if self.m_service:
+ self.m_service.stateChanged.connect(self.serviceStateChanged)
+ self.m_service.characteristicChanged.connect(self.updateHeartRateValue)
+ self.m_service.descriptorWritten.connect(self.confirmedDescriptorWrite)
+ self.m_service.discoverDetails()
+ else:
+ self.error = "Heart Rate Service not found."
+#! [Filter HeartRate service 2]
+
+# Service functions
+#! [Find HRM characteristic]
+ @Slot(QLowEnergyService.ServiceState)
+ def serviceStateChanged(self, switch):
+ if switch == QLowEnergyService.RemoteServiceDiscovering:
+ self.setInfo(tr("Discovering services..."))
+ elif switch == QLowEnergyService.RemoteServiceDiscovered:
+ self.setInfo(tr("Service discovered."))
+ hrChar = m_service.characteristic(QBluetoothUuid(QBluetoothUuid.CharacteristicType.HeartRateMeasurement))
+ if hrChar.isValid():
+ self.m_notificationDesc = hrChar.descriptor(QBluetoothUuid.DescriptorType.ClientCharacteristicConfiguration)
+ if self.m_notificationDesc.isValid():
+ self.m_service.writeDescriptor(m_notificationDesc,
+ QByteArray.fromHex(b"0100"))
+ else:
+ self.error = "HR Data not found."
+ self.aliveChanged.emit()
+#! [Find HRM characteristic]
+
+#! [Reading value]
+ @Slot(QLowEnergyCharacteristic, QByteArray)
+ def updateHeartRateValue(self, c, value):
+ # ignore any other characteristic change. Shouldn't really happen though
+ if c.uuid() != QBluetoothUuid(QBluetoothUuid.CharacteristicType.HeartRateMeasurement):
+ return
+
+ data = value.data()
+ flags = int(data[0])
+ # Heart Rate
+ hrvalue = 0
+ if flags & 0x1: # HR 16 bit little endian? otherwise 8 bit
+ hrvalue = struct.unpack("<H", data[1:3])
+ else:
+ hrvalue = struct.unpack("B", data[1:2])
+
+ self.addMeasurement(hrvalue)
+
+#! [Reading value]
+ @Slot()
+ def updateDemoHR(self):
+ randomValue = 0
+ if self.m_currentValue < 30: # Initial value
+ randomValue = 55 + QRandomGenerator.global_().bounded(30)
+ elif not self.m_measuring: # Value when relax
+ random = QRandomGenerator.global_().bounded(5)
+ randomValue = self.m_currentValue - 2 + random
+ randomValue = max(min(randomValue, 55), 75)
+ else: # Measuring
+ random = QRandomGenerator.global_().bounded(10)
+ randomValue = self.m_currentValue + random - 2
+
+ self.addMeasurement(randomValue)
+
+ @Slot(QLowEnergyCharacteristic, QByteArray)
+ def confirmedDescriptorWrite(self, d, value):
+ if (d.isValid() and d == self.m_notificationDesc
+ and value == QByteArray.fromHex(b"0000")):
+ # disabled notifications . assume disconnect intent
+ self.m_control.disconnectFromDevice()
+ self.m_service = None
+
+ @Slot()
+ def disconnectService(self):
+ self.m_foundHeartRateService = False
+
+ # disable notifications
+ if (self.m_notificationDesc.isValid() and self.m_service
+ and self.m_notificationDesc.value() == QByteArray.fromHex(b"0100")):
+ self.m_service.writeDescriptor(self.m_notificationDesc,
+ QByteArray.fromHex(b"0000"))
+ else:
+ if self.m_control:
+ self.m_control.disconnectFromDevice()
+ self.m_service = None
+
+ @Property(bool, notify=measuringChanged)
+ def measuring(self):
+ return self.m_measuring
+
+ @Property(bool, notify=aliveChanged)
+ def alive(self):
+ if simulator:
+ return True
+ if self.m_service:
+ return self.m_service.state() == QLowEnergyService.RemoteServiceDiscovered
+ return False
+
+ @Property(int, notify=statsChanged)
+ def hr(self):
+ return self.m_currentValue
+
+ @Property(int, notify=statsChanged)
+ def time(self):
+ return self.m_start.secsTo(self.m_stop)
+
+ @Property(int, notify=statsChanged)
+ def maxHR(self):
+ return self.m_max
+
+ @Property(int, notify=statsChanged)
+ def minHR(self):
+ return self.m_min
+
+ @Property(float, notify=statsChanged)
+ def average(self):
+ return self.m_avg
+
+ @Property(float, notify=statsChanged)
+ def calories(self):
+ return self.m_calories
+
+ def addMeasurement(self, value):
+ self.m_currentValue = value
+
+ # If measuring and value is appropriate
+ if self.m_measuring and value > 30 and value < 250:
+ self.m_stop = QDateTime.currentDateTime()
+ self.m_measurements.append(value)
+
+ self.m_min = value if self.m_min == 0 else min(value, self.m_min)
+ self.m_max = max(value, self.m_max)
+ self.m_sum += value
+ self.m_avg = float(self.m_sum) / len(self.m_measurements)
+ self.m_calories = ((-55.0969 + (0.6309 * self.m_avg) + (0.1988 * 94)
+ + (0.2017 * 24)) / 4.184) * 60 * self.time / 3600
+
+ self.statsChanged.emit()
diff --git a/examples/bluetooth/heartrate_game/deviceinfo.py b/examples/bluetooth/heartrate_game/deviceinfo.py
new file mode 100644
index 000000000..b0f1b8a8b
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/deviceinfo.py
@@ -0,0 +1,75 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtCore import QObject, Property, Signal
+
+from heartrate_global import simulator
+
+
+class DeviceInfo(QObject):
+
+ deviceChanged = Signal()
+
+ def __init__(self, device):
+ super().__init__()
+ self.m_device = device
+
+ def device(self):
+ return self.m_device
+
+ def setDevice(self, device):
+ self.m_device = device
+ self.deviceChanged.emit()
+
+ @Property(str, notify=deviceChanged)
+ def deviceName(self):
+ if simulator:
+ return "Demo device"
+ return self.m_device.name()
+
+ @Property(str, notify=deviceChanged)
+ def deviceAddress(self):
+ if simulator:
+ return "00:11:22:33:44:55"
+ if sys.platform == "Darwin": # workaround for Core Bluetooth:
+ return self.m_device.deviceUuid().toString()
+ return self.m_device.address().toString()
diff --git a/examples/bluetooth/heartrate_game/doc/heartrate_game.rst b/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
new file mode 100644
index 000000000..0a0938cad
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
@@ -0,0 +1,9 @@
+Bluetooth Low Energy Heart Rate Game
+====================================
+
+The Bluetooth Low Energy Heart Rate Game shows how to develop a
+Bluetooth Low Energy application using the Qt Bluetooth API. The
+application covers the scanning for Bluetooth Low Energy devices,
+connecting to a Heart Rate service on the device, writing
+characteristics and descriptors, and receiving updates from the device
+once the heart rate has changed.
diff --git a/examples/bluetooth/heartrate_game/heartrate_game.pyproject b/examples/bluetooth/heartrate_game/heartrate_game.pyproject
new file mode 100644
index 000000000..e4c40874a
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/heartrate_game.pyproject
@@ -0,0 +1,22 @@
+{
+ "files": ["main.py",
+ "bluetoothbaseclass.py",
+ "connectionhandler.py",
+ "devicefinder.py",
+ "devicehandler.py",
+ "deviceinfo.py",
+ "heartrate_global.py",
+ "qml/main.qml",
+ "qml/App.qml",
+ "qml/BluetoothAlarmDialog.qml",
+ "qml/BottomLine.qml",
+ "qml/Connect.qml",
+ "qml/GameButton.qml",
+ "qml/GamePage.qml",
+ "qml/GameSettings.qml",
+ "qml/Measure.qml",
+ "qml/SplashScreen.qml",
+ "qml/Stats.qml",
+ "qml/StatsLabel.qml",
+ "qml/TitleBar.qml"]
+}
diff --git a/examples/bluetooth/heartrate_game/heartrate_global.py b/examples/bluetooth/heartrate_game/heartrate_global.py
new file mode 100644
index 000000000..8fb4f0f6e
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/heartrate_global.py
@@ -0,0 +1,43 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+simulator = sys.platform == "win32"
diff --git a/examples/bluetooth/heartrate_game/main.py b/examples/bluetooth/heartrate_game/main.py
new file mode 100644
index 000000000..5cf02cbd6
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/main.py
@@ -0,0 +1,90 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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$
+##
+#############################################################################
+
+"""PySide6 port of the bluetooth/heartrate-game example from Qt v6.x"""
+
+import os
+from pathlib import Path
+import sys
+from argparse import ArgumentParser, Namespace, RawDescriptionHelpFormatter
+
+from PySide6.QtQml import QQmlApplicationEngine, QQmlContext
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtCore import QCoreApplication, QLoggingCategory, QUrl
+
+from connectionhandler import ConnectionHandler
+from devicefinder import DeviceFinder
+from devicehandler import DeviceHandler
+from heartrate_global import simulator
+
+
+if __name__ == '__main__':
+ parser = ArgumentParser(prog="heartrate-game",
+ formatter_class=RawDescriptionHelpFormatter)
+
+ parser.add_argument("-v", "--verbose", action="store_true",
+ help="Generate more output")
+ parser.add_argument("-s", "--simulator", action="store_true",
+ help="Use Simulator")
+ options = parser.parse_args()
+ simulator = options.simulator
+ if options.verbose:
+ QLoggingCategory.setFilterRules("qt.bluetooth* = true")
+
+ app = QGuiApplication(sys.argv)
+
+ connectionHandler = ConnectionHandler()
+ deviceHandler = DeviceHandler()
+ deviceFinder = DeviceFinder(deviceHandler)
+
+ engine = QQmlApplicationEngine()
+ engine.setInitialProperties({
+ "connectionHandler": connectionHandler,
+ "deviceFinder": deviceFinder,
+ "deviceHandler": deviceHandler})
+
+ qml_file = os.fspath(Path(__file__).resolve().parent / "qml" / "main.qml")
+ engine.load(QUrl.fromLocalFile(qml_file))
+ if not engine.rootObjects():
+ sys.exit(-1)
+
+ ex = QCoreApplication.exec()
+ del engine
+ sys.exit(ex)
diff --git a/examples/bluetooth/heartrate_game/qml/App.qml b/examples/bluetooth/heartrate_game/qml/App.qml
new file mode 100644
index 000000000..e2b059cf0
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/App.qml
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+
+Item {
+ id: app
+ anchors.fill: parent
+ opacity: 0.0
+
+ Behavior on opacity { NumberAnimation { duration: 500 } }
+
+ property var lastPages: []
+ property int __currentIndex: 0
+
+ function init()
+ {
+ opacity = 1.0
+ showPage("Connect.qml")
+ }
+
+ function prevPage()
+ {
+ lastPages.pop()
+ pageLoader.setSource(lastPages[lastPages.length-1])
+ __currentIndex = lastPages.length-1;
+ }
+
+ function showPage(name)
+ {
+ lastPages.push(name)
+ pageLoader.setSource(name)
+ __currentIndex = lastPages.length-1;
+ }
+
+ TitleBar {
+ id: titleBar
+ currentIndex: __currentIndex
+
+ onTitleClicked: (index) => {
+ if (index < __currentIndex)
+ pageLoader.item.close()
+ }
+ }
+
+ Loader {
+ id: pageLoader
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+
+ onStatusChanged: {
+ if (status === Loader.Ready)
+ {
+ pageLoader.item.init();
+ pageLoader.item.forceActiveFocus()
+ }
+ }
+ }
+
+ Keys.onReleased: (event) => {
+ switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back: {
+ if (__currentIndex > 0) {
+ pageLoader.item.close()
+ event.accepted = true
+ } else {
+ Qt.quit()
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+
+ BluetoothAlarmDialog {
+ id: btAlarmDialog
+ anchors.fill: parent
+ visible: !connectionHandler.alive
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/BluetoothAlarmDialog.qml b/examples/bluetooth/heartrate_game/qml/BluetoothAlarmDialog.qml
new file mode 100644
index 000000000..5d4d5cb72
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/BluetoothAlarmDialog.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+
+Item {
+ id: root
+ anchors.fill: parent
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ opacity: 0.9
+ }
+
+ MouseArea {
+ id: eventEater
+ }
+
+ Rectangle {
+ id: dialogFrame
+
+ anchors.centerIn: parent
+ width: parent.width * 0.8
+ height: parent.height * 0.6
+ border.color: "#454545"
+ color: GameSettings.backgroundColor
+ radius: width * 0.05
+
+ Item {
+ id: dialogContainer
+ anchors.fill: parent
+ anchors.margins: parent.width*0.05
+
+ Image {
+ id: offOnImage
+ anchors.left: quitButton.left
+ anchors.right: quitButton.right
+ anchors.top: parent.top
+ height: GameSettings.heightForWidth(width, sourceSize)
+ source: "images/bt_off_to_on.png"
+ }
+
+ Text {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: offOnImage.bottom
+ anchors.bottom: quitButton.top
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.WordWrap
+ font.pixelSize: GameSettings.mediumFontSize
+ color: GameSettings.textColor
+ text: qsTr("This application cannot be used without Bluetooth. Please switch Bluetooth ON to continue.")
+ }
+
+ GameButton {
+ id: quitButton
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: dialogContainer.width * 0.6
+ height: GameSettings.buttonHeight
+ onClicked: Qt.quit()
+
+ Text {
+ anchors.centerIn: parent
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.bigFontSize
+ text: qsTr("Quit")
+ }
+ }
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/BottomLine.qml b/examples/bluetooth/heartrate_game/qml/BottomLine.qml
new file mode 100644
index 000000000..da6c6f530
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/BottomLine.qml
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+
+Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ width: parent.width * 0.85
+ height: parent.height * 0.05
+ radius: height*0.5
+}
diff --git a/examples/bluetooth/heartrate_game/qml/Connect.qml b/examples/bluetooth/heartrate_game/qml/Connect.qml
new file mode 100644
index 000000000..e15d2c9cd
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/Connect.qml
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+import Shared
+
+GamePage {
+
+ errorMessage: deviceFinder.error
+ infoMessage: deviceFinder.info
+
+ Rectangle {
+ id: viewContainer
+ anchors.top: parent.top
+ anchors.bottom:
+ // only BlueZ platform has address type selection
+ connectionHandler.requiresAddressType ? addressTypeButton.top : searchButton.top
+ anchors.topMargin: GameSettings.fieldMargin + messageHeight
+ anchors.bottomMargin: GameSettings.fieldMargin
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width - GameSettings.fieldMargin*2
+ color: GameSettings.viewColor
+ radius: GameSettings.buttonRadius
+
+
+ Text {
+ id: title
+ width: parent.width
+ height: GameSettings.fieldHeight
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.mediumFontSize
+ text: qsTr("FOUND DEVICES")
+
+ BottomLine {
+ height: 1;
+ width: parent.width
+ color: "#898989"
+ }
+ }
+
+
+ ListView {
+ id: devices
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.top: title.bottom
+ model: deviceFinder.devices
+ clip: true
+
+ delegate: Rectangle {
+ id: box
+ height:GameSettings.fieldHeight * 1.2
+ width: devices.width
+ color: index % 2 === 0 ? GameSettings.delegate1Color : GameSettings.delegate2Color
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ deviceFinder.connectToService(modelData.deviceAddress);
+ app.showPage("Measure.qml")
+ }
+ }
+
+ Text {
+ id: device
+ font.pixelSize: GameSettings.smallFontSize
+ text: modelData.deviceName
+ anchors.top: parent.top
+ anchors.topMargin: parent.height * 0.1
+ anchors.leftMargin: parent.height * 0.1
+ anchors.left: parent.left
+ color: GameSettings.textColor
+ }
+
+ Text {
+ id: deviceAddress
+ font.pixelSize: GameSettings.smallFontSize
+ text: modelData.deviceAddress
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: parent.height * 0.1
+ anchors.rightMargin: parent.height * 0.1
+ anchors.right: parent.right
+ color: Qt.darker(GameSettings.textColor)
+ }
+ }
+ }
+ }
+
+ GameButton {
+ id: addressTypeButton
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: searchButton.top
+ anchors.bottomMargin: GameSettings.fieldMargin*0.5
+ width: viewContainer.width
+ height: GameSettings.fieldHeight
+ visible: connectionHandler.requiresAddressType // only required on BlueZ
+ state: "public"
+ onClicked: state == "public" ? state = "random" : state = "public"
+
+ states: [
+ State {
+ name: "public"
+ PropertyChanges { target: addressTypeText; text: qsTr("Public Address") }
+ PropertyChanges { target: deviceHandler; addressType: AddressType.PUBLIC_ADDRESS }
+ },
+ State {
+ name: "random"
+ PropertyChanges { target: addressTypeText; text: qsTr("Random Address") }
+ PropertyChanges { target: deviceHandler; addressType: AddressType.RANDOM_ADDRESS }
+ }
+ ]
+
+ Text {
+ id: addressTypeText
+ anchors.centerIn: parent
+ font.pixelSize: GameSettings.tinyFontSize
+ color: GameSettings.textColor
+ }
+ }
+
+ GameButton {
+ id: searchButton
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: GameSettings.fieldMargin
+ width: viewContainer.width
+ height: GameSettings.fieldHeight
+ enabled: !deviceFinder.scanning
+ onClicked: deviceFinder.startSearch()
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: GameSettings.tinyFontSize
+ text: qsTr("START SEARCH")
+ color: searchButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/GameButton.qml b/examples/bluetooth/heartrate_game/qml/GameButton.qml
new file mode 100644
index 000000000..c1f496560
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/GameButton.qml
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+import "."
+
+Rectangle {
+ id: button
+ color: baseColor
+ onEnabledChanged: checkColor()
+ radius: GameSettings.buttonRadius
+
+ property color baseColor: GameSettings.buttonColor
+ property color pressedColor: GameSettings.buttonPressedColor
+ property color disabledColor: GameSettings.disabledButtonColor
+
+ signal clicked()
+
+ function checkColor()
+ {
+ if (!button.enabled) {
+ button.color = disabledColor
+ } else {
+ if (mouseArea.containsPress)
+ button.color = pressedColor
+ else
+ button.color = baseColor
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onPressed: checkColor()
+ onReleased: checkColor()
+ onClicked: {
+ checkColor()
+ button.clicked()
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/GamePage.qml b/examples/bluetooth/heartrate_game/qml/GamePage.qml
new file mode 100644
index 000000000..b921f0d62
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/GamePage.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+import "."
+
+Item {
+ anchors.fill: parent
+
+ property string errorMessage: ""
+ property string infoMessage: ""
+ property real messageHeight: msg.height
+ property bool hasError: errorMessage != ""
+ property bool hasInfo: infoMessage != ""
+
+ function init()
+ {
+ }
+
+ function close()
+ {
+ app.prevPage()
+ }
+
+ Rectangle {
+ id: msg
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: GameSettings.fieldHeight
+ color: hasError ? GameSettings.errorColor : GameSettings.infoColor
+ visible: hasError || hasInfo
+
+ Text {
+ id: error
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ minimumPixelSize: 5
+ font.pixelSize: GameSettings.smallFontSize
+ fontSizeMode: Text.Fit
+ color: GameSettings.textColor
+ text: hasError ? errorMessage : infoMessage
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/GameSettings.qml b/examples/bluetooth/heartrate_game/qml/GameSettings.qml
new file mode 100644
index 000000000..bfb485cdf
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/GameSettings.qml
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick
+
+Item {
+ property int wHeight
+ property int wWidth
+
+ // Colors
+ readonly property color backgroundColor: "#2d3037"
+ readonly property color buttonColor: "#202227"
+ readonly property color buttonPressedColor: "#6ccaf2"
+ readonly property color disabledButtonColor: "#555555"
+ readonly property color viewColor: "#202227"
+ readonly property color delegate1Color: Qt.darker(viewColor, 1.2)
+ readonly property color delegate2Color: Qt.lighter(viewColor, 1.2)
+ readonly property color textColor: "#ffffff"
+ readonly property color textDarkColor: "#232323"
+ readonly property color disabledTextColor: "#777777"
+ readonly property color sliderColor: "#6ccaf2"
+ readonly property color errorColor: "#ba3f62"
+ readonly property color infoColor: "#3fba62"
+
+ // Font sizes
+ property real microFontSize: hugeFontSize * 0.2
+ property real tinyFontSize: hugeFontSize * 0.4
+ property real smallTinyFontSize: hugeFontSize * 0.5
+ property real smallFontSize: hugeFontSize * 0.6
+ property real mediumFontSize: hugeFontSize * 0.7
+ property real bigFontSize: hugeFontSize * 0.8
+ property real largeFontSize: hugeFontSize * 0.9
+ property real hugeFontSize: (wWidth + wHeight) * 0.03
+ property real giganticFontSize: (wWidth + wHeight) * 0.04
+
+ // Some other values
+ property real fieldHeight: wHeight * 0.08
+ property real fieldMargin: fieldHeight * 0.5
+ property real buttonHeight: wHeight * 0.08
+ property real buttonRadius: buttonHeight * 0.1
+
+ // Some help functions
+ function widthForHeight(h, ss)
+ {
+ return h/ss.height * ss.width;
+ }
+
+ function heightForWidth(w, ss)
+ {
+ return w/ss.width * ss.height;
+ }
+
+}
diff --git a/examples/bluetooth/heartrate_game/qml/Measure.qml b/examples/bluetooth/heartrate_game/qml/Measure.qml
new file mode 100644
index 000000000..32bac5fcd
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/Measure.qml
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+
+GamePage {
+ id: measurePage
+
+ errorMessage: deviceHandler.error
+ infoMessage: deviceHandler.info
+
+ property real __timeCounter: 0;
+ property real __maxTimeCount: 60
+ property string relaxText: qsTr("Relax!\nWhen you are ready, press Start. You have %1s time to increase heartrate so much as possible.\nGood luck!").arg(__maxTimeCount)
+
+ function close()
+ {
+ deviceHandler.stopMeasurement();
+ deviceHandler.disconnectService();
+ app.prevPage();
+ }
+
+ function start()
+ {
+ if (!deviceHandler.measuring) {
+ __timeCounter = 0;
+ deviceHandler.startMeasurement()
+ }
+ }
+
+ function stop()
+ {
+ if (deviceHandler.measuring) {
+ deviceHandler.stopMeasurement()
+ }
+
+ app.showPage("Stats.qml")
+ }
+
+ Timer {
+ id: measureTimer
+ interval: 1000
+ running: deviceHandler.measuring
+ repeat: true
+ onTriggered: {
+ __timeCounter++;
+ if (__timeCounter >= __maxTimeCount)
+ measurePage.stop()
+ }
+ }
+
+ Column {
+ anchors.centerIn: parent
+ spacing: GameSettings.fieldHeight * 0.5
+
+ Rectangle {
+ id: circle
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.min(measurePage.width, measurePage.height-GameSettings.fieldHeight*4) - 2*GameSettings.fieldMargin
+ height: width
+ radius: width*0.5
+ color: GameSettings.viewColor
+
+ Text {
+ id: hintText
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: -parent.height*0.1
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width * 0.8
+ height: parent.height * 0.6
+ wrapMode: Text.WordWrap
+ text: measurePage.relaxText
+ visible: !deviceHandler.measuring
+ color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ minimumPixelSize: 10
+ font.pixelSize: GameSettings.mediumFontSize
+ }
+
+ Text {
+ id: text
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: -parent.height*0.15
+ font.pixelSize: parent.width * 0.45
+ text: deviceHandler.hr
+ visible: deviceHandler.measuring
+ color: GameSettings.textColor
+ }
+
+ Item {
+ id: minMaxContainer
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width*0.7
+ height: parent.height * 0.15
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: parent.height*0.16
+ visible: deviceHandler.measuring
+
+ Text {
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ text: deviceHandler.minHR
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.hugeFontSize
+
+ Text {
+ anchors.left: parent.left
+ anchors.bottom: parent.top
+ font.pixelSize: parent.font.pixelSize*0.8
+ color: parent.color
+ text: "MIN"
+ }
+ }
+
+ Text {
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ text: deviceHandler.maxHR
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.hugeFontSize
+
+ Text {
+ anchors.right: parent.right
+ anchors.bottom: parent.top
+ font.pixelSize: parent.font.pixelSize*0.8
+ color: parent.color
+ text: "MAX"
+ }
+ }
+ }
+
+ Image {
+ id: heart
+ anchors.horizontalCenter: minMaxContainer.horizontalCenter
+ anchors.verticalCenter: minMaxContainer.bottom
+ width: parent.width * 0.2
+ height: width
+ source: "images/heart.png"
+ smooth: true
+ antialiasing: true
+
+ SequentialAnimation{
+ id: heartAnim
+ running: deviceHandler.alive
+ loops: Animation.Infinite
+ alwaysRunToEnd: true
+ PropertyAnimation { target: heart; property: "scale"; to: 1.2; duration: 500; easing.type: Easing.InQuad }
+ PropertyAnimation { target: heart; property: "scale"; to: 1.0; duration: 500; easing.type: Easing.OutQuad }
+ }
+ }
+ }
+
+ Rectangle {
+ id: timeSlider
+ color: GameSettings.viewColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: circle.width
+ height: GameSettings.fieldHeight
+ radius: GameSettings.buttonRadius
+
+ Rectangle {
+ height: parent.height
+ radius: parent.radius
+ color: GameSettings.sliderColor
+ width: Math.min(1.0,__timeCounter / __maxTimeCount) * parent.width
+ }
+
+ Text {
+ anchors.centerIn: parent
+ color: "gray"
+ text: (__maxTimeCount - __timeCounter).toFixed(0) + " s"
+ font.pixelSize: GameSettings.bigFontSize
+ }
+ }
+ }
+
+ GameButton {
+ id: startButton
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: GameSettings.fieldMargin
+ width: circle.width
+ height: GameSettings.fieldHeight
+ enabled: !deviceHandler.measuring
+ radius: GameSettings.buttonRadius
+
+ onClicked: start()
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: GameSettings.tinyFontSize
+ text: qsTr("START")
+ color: startButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/SplashScreen.qml b/examples/bluetooth/heartrate_game/qml/SplashScreen.qml
new file mode 100644
index 000000000..ecf16c955
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/SplashScreen.qml
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+import "."
+
+Item {
+ id: root
+ anchors.fill: parent
+
+ property bool appIsReady: false
+ property bool splashIsReady: false
+
+ property bool ready: appIsReady && splashIsReady
+ onReadyChanged: if (ready) readyToGo();
+
+ signal readyToGo()
+
+ function appReady()
+ {
+ appIsReady = true
+ }
+
+ function errorInLoadingApp()
+ {
+ Qt.quit()
+ }
+
+ Image {
+ anchors.centerIn: parent
+ width: Math.min(parent.height, parent.width)*0.6
+ height: GameSettings.heightForWidth(width, sourceSize)
+ source: "images/logo.png"
+ }
+
+ Timer {
+ id: splashTimer
+ interval: 1000
+ onTriggered: splashIsReady = true
+ }
+
+ Component.onCompleted: splashTimer.start()
+}
diff --git a/examples/bluetooth/heartrate_game/qml/Stats.qml b/examples/bluetooth/heartrate_game/qml/Stats.qml
new file mode 100644
index 000000000..23cbd18b9
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/Stats.qml
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+
+GamePage {
+
+ Column {
+ anchors.centerIn: parent
+ width: parent.width
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: GameSettings.hugeFontSize
+ color: GameSettings.textColor
+ text: qsTr("RESULT")
+ }
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: GameSettings.giganticFontSize*3
+ color: GameSettings.textColor
+ text: (deviceHandler.maxHR - deviceHandler.minHR).toFixed(0)
+ }
+
+ Item {
+ height: GameSettings.fieldHeight
+ width: 1
+ }
+
+ StatsLabel {
+ title: qsTr("MIN")
+ value: deviceHandler.minHR.toFixed(0)
+ }
+
+ StatsLabel {
+ title: qsTr("MAX")
+ value: deviceHandler.maxHR.toFixed(0)
+ }
+
+ StatsLabel {
+ title: qsTr("AVG")
+ value: deviceHandler.average.toFixed(1)
+ }
+
+
+ StatsLabel {
+ title: qsTr("CALORIES")
+ value: deviceHandler.calories.toFixed(3)
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/StatsLabel.qml b/examples/bluetooth/heartrate_game/qml/StatsLabel.qml
new file mode 100644
index 000000000..6eb19ecb7
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/StatsLabel.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+import "."
+
+Item {
+ height: GameSettings.fieldHeight
+ width: parent.width
+
+ property alias title: leftText.text
+ property alias value: rightText.text
+
+ Text {
+ id: leftText
+ anchors.left: parent.left
+ height: parent.height
+ width: parent.width * 0.45
+ horizontalAlignment: Text.AlignRight
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: GameSettings.mediumFontSize
+ color: GameSettings.textColor
+ }
+
+ Text {
+ id: rightText
+ anchors.right: parent.right
+ height: parent.height
+ width: parent.width * 0.45
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: GameSettings.mediumFontSize
+ color: GameSettings.textColor
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/TitleBar.qml b/examples/bluetooth/heartrate_game/qml/TitleBar.qml
new file mode 100644
index 000000000..1d9ec4c94
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/TitleBar.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+
+Rectangle {
+ id: titleBar
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: GameSettings.fieldHeight
+ color: GameSettings.viewColor
+
+ property var __titles: ["CONNECT", "MEASURE", "STATS"]
+ property int currentIndex: 0
+
+ signal titleClicked(int index)
+
+ Repeater {
+ model: 3
+ Text {
+ width: titleBar.width / 3
+ height: titleBar.height
+ x: index * width
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: __titles[index]
+ font.pixelSize: GameSettings.tinyFontSize
+ color: titleBar.currentIndex === index ? GameSettings.textColor : GameSettings.disabledTextColor
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: titleClicked(index)
+ }
+ }
+ }
+
+
+ Item {
+ anchors.bottom: parent.bottom
+ width: parent.width / 3
+ height: parent.height
+ x: currentIndex * width
+
+ BottomLine{}
+
+ Behavior on x { NumberAnimation { duration: 200 } }
+ }
+
+}
diff --git a/examples/bluetooth/heartrate_game/qml/images/bt_off_to_on.png b/examples/bluetooth/heartrate_game/qml/images/bt_off_to_on.png
new file mode 100644
index 000000000..5ea1f3f06
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/images/bt_off_to_on.png
Binary files differ
diff --git a/examples/bluetooth/heartrate_game/qml/images/heart.png b/examples/bluetooth/heartrate_game/qml/images/heart.png
new file mode 100644
index 000000000..f2b3c0a3e
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/images/heart.png
Binary files differ
diff --git a/examples/bluetooth/heartrate_game/qml/images/logo.png b/examples/bluetooth/heartrate_game/qml/images/logo.png
new file mode 100644
index 000000000..ea0af7e00
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/images/logo.png
Binary files differ
diff --git a/examples/bluetooth/heartrate_game/qml/main.qml b/examples/bluetooth/heartrate_game/qml/main.qml
new file mode 100644
index 000000000..920a82669
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/main.qml
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+import QtQuick
+import QtQuick.Window
+import "."
+import Shared
+
+Window {
+ id: wroot
+ visible: true
+ width: 720 * .7
+ height: 1240 * .7
+ title: qsTr("HeartRateGame")
+ color: GameSettings.backgroundColor
+
+ required property ConnectionHandler connectionHandler
+ required property DeviceFinder deviceFinder
+ required property AddressType deviceHandler
+
+ Component.onCompleted: {
+ GameSettings.wWidth = Qt.binding(function() {return width})
+ GameSettings.wHeight = Qt.binding(function() {return height})
+ }
+
+ Loader {
+ id: splashLoader
+ anchors.fill: parent
+ source: "SplashScreen.qml"
+ asynchronous: false
+ visible: true
+
+ onStatusChanged: {
+ if (status === Loader.Ready) {
+ appLoader.setSource("App.qml");
+ }
+ }
+ }
+
+ Connections {
+ target: splashLoader.item
+ function onReadyToGo() {
+ appLoader.visible = true
+ appLoader.item.init()
+ splashLoader.visible = false
+ splashLoader.setSource("")
+ appLoader.item.forceActiveFocus();
+ }
+ }
+
+ Loader {
+ id: appLoader
+ anchors.fill: parent
+ visible: false
+ asynchronous: true
+ onStatusChanged: {
+ if (status === Loader.Ready)
+ splashLoader.item.appReady()
+ if (status === Loader.Error)
+ splashLoader.item.errorInLoadingApp();
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate_game/qml/qmldir b/examples/bluetooth/heartrate_game/qml/qmldir
new file mode 100644
index 000000000..5e0d2b540
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/qml/qmldir
@@ -0,0 +1 @@
+singleton GameSettings 1.0 GameSettings.qml
diff --git a/examples/bluetooth/heartrate_server/doc/heartrate_server.rst b/examples/bluetooth/heartrate_server/doc/heartrate_server.rst
new file mode 100644
index 000000000..aaa1a0988
--- /dev/null
+++ b/examples/bluetooth/heartrate_server/doc/heartrate_server.rst
@@ -0,0 +1,8 @@
+Bluetooth Low Energy Heart Rate Server
+======================================
+
+The Bluetooth Low Energy Heart Rate Server is a command-line
+application that shows how to develop a Bluetooth GATT server using
+the Qt Bluetooth API. The application covers setting up a GATT
+service, advertising it and notifying clients about changes to
+characteristic values.
diff --git a/examples/bluetooth/heartrate_server/heartrate_server.py b/examples/bluetooth/heartrate_server/heartrate_server.py
new file mode 100644
index 000000000..0696d92c2
--- /dev/null
+++ b/examples/bluetooth/heartrate_server/heartrate_server.py
@@ -0,0 +1,131 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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$
+##
+#############################################################################
+
+"""PySide6 port of the bluetooth/heartrate-server example from Qt v6.x"""
+
+import sys
+from enum import Enum
+
+from PySide6.QtBluetooth import (QBluetoothUuid, QLowEnergyAdvertisingData,
+ QLowEnergyAdvertisingParameters,
+ QLowEnergyCharacteristic,
+ QLowEnergyCharacteristicData,
+ QLowEnergyController,
+ QLowEnergyDescriptorData,
+ QLowEnergyServiceData)
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtCore import QByteArray, QTimer, QLoggingCategory
+
+
+class ValueChange(Enum):
+ VALUE_UP = 1
+ VALUE_DOWN = 2
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ QLoggingCategory.setFilterRules("qt.bluetooth* = true")
+
+#! [Advertising Data]
+ advertising_data = QLowEnergyAdvertisingData()
+ advertising_data.setDiscoverability(QLowEnergyAdvertisingData.DiscoverabilityGeneral)
+ advertising_data.setIncludePowerLevel(True)
+ advertising_data.setLocalName("HeartRateServer")
+ advertising_data.setServices([QBluetoothUuid.ServiceClassUuid.HeartRate])
+#! [Advertising Data]
+
+#! [Service Data]
+ char_data = QLowEnergyCharacteristicData()
+ char_data.setUuid(QBluetoothUuid.CharacteristicType.HeartRateMeasurement)
+ char_data.setValue(QByteArray(2, 0))
+ char_data.setProperties(QLowEnergyCharacteristic.Notify)
+ client_config = QLowEnergyDescriptorData(QBluetoothUuid.DescriptorType.ClientCharacteristicConfiguration,
+ QByteArray(2, 0))
+ char_data.addDescriptor(client_config)
+
+ service_data = QLowEnergyServiceData()
+ service_data.setType(QLowEnergyServiceData.ServiceTypePrimary)
+ service_data.setUuid(QBluetoothUuid.ServiceClassUuid.HeartRate)
+ service_data.addCharacteristic(char_data)
+#! [Service Data]
+
+#! [Start Advertising]
+ le_controller = QLowEnergyController.createPeripheral()
+ service = le_controller.addService(service_data)
+ le_controller.startAdvertising(QLowEnergyAdvertisingParameters(),
+ advertising_data, advertising_data)
+#! [Start Advertising]
+
+#! [Provide Heartbeat]
+ value_change = ValueChange.VALUE_UP
+ heartbeat_timer = QTimer()
+ current_heart_rate = 60
+
+ def heartbeat_provider():
+ global current_heart_rate, value_change, current_heart_rate
+ value = QByteArray()
+ value.append(chr(0)) # Flags that specify the format of the value.
+ value.append(chr(current_heart_rate)) # Actual value.
+ characteristic = service.characteristic(QBluetoothUuid.CharacteristicType.HeartRateMeasurement)
+ assert(characteristic.isValid())
+ # Potentially causes notification.
+ service.writeCharacteristic(characteristic, value)
+ if current_heart_rate == 60:
+ value_change = ValueChange.VALUE_UP
+ elif current_heart_rate == 100:
+ value_change = ValueChange.VALUE_DOWN
+ if value_change == ValueChange.VALUE_UP:
+ current_heart_rate += 1
+ else:
+ current_heart_rate -= 1
+
+ heartbeat_timer.timeout.connect(heartbeat_provider)
+ heartbeat_timer.start(1000)
+#! [Provide Heartbeat]
+
+ def reconnect():
+ service = le_controller.addService(service_data)
+ if not service.isNull():
+ le_controller.startAdvertising(QLowEnergyAdvertisingParameters(),
+ advertising_data, advertising_data)
+
+ le_controller.disconnected.connect(reconnect)
+
+ sys.exit(app.exec())
diff --git a/examples/bluetooth/heartrate_server/heartrate_server.pyproject b/examples/bluetooth/heartrate_server/heartrate_server.pyproject
new file mode 100644
index 000000000..de1fd14a0
--- /dev/null
+++ b/examples/bluetooth/heartrate_server/heartrate_server.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["heartrate_server.py"]
+}
diff --git a/examples/charts/chartthemes/main.py b/examples/charts/chartthemes/main.py
index 5f3bfce10..b385d0b5e 100644
--- a/examples/charts/chartthemes/main.py
+++ b/examples/charts/chartthemes/main.py
@@ -171,7 +171,7 @@ class ThemeWidget(QWidget):
for j in range(len(self.data_table[i])):
data = self.data_table[i][j]
if lower_series:
- points = lower_series.pointsVector()
+ points = lower_series.points()
y_value = points[i].y() + data[0].y()
upper_series.append(QPointF(j, y_value))
else:
@@ -182,10 +182,12 @@ class ThemeWidget(QWidget):
lower_series = upper_series
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_count - 1)
- chart.axisY().setRange(0, self.value_max)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_count - 1)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_max)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
@@ -203,9 +205,10 @@ class ThemeWidget(QWidget):
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisY().setRange(0, self.value_max * 2)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_max * 2)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
@@ -222,10 +225,12 @@ class ThemeWidget(QWidget):
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_max)
- chart.axisY().setRange(0, self.value_count)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_max)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_count)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
@@ -259,10 +264,12 @@ class ThemeWidget(QWidget):
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_max)
- chart.axisY().setRange(0, self.value_count)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_max)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_count)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
@@ -278,10 +285,12 @@ class ThemeWidget(QWidget):
chart.addSeries(series)
chart.createDefaultAxes()
- chart.axisX().setRange(0, self.value_max)
- chart.axisY().setRange(0, self.value_count)
+ axis_x = chart.axes(Qt.Horizontal)[0]
+ axis_x.setRange(0, self.value_max)
+ axis_y = chart.axes(Qt.Vertical)[0]
+ axis_y.setRange(0, self.value_count)
# Add space to label to add space between labels and axis
- chart.axisY().setLabelFormat("%.1f ")
+ axis_y.setLabelFormat("%.1f ")
return chart
diff --git a/examples/charts/donutbreakdown/donutbreakdown.py b/examples/charts/donutbreakdown/donutbreakdown.py
index 3030d1e0d..160494e2a 100644
--- a/examples/charts/donutbreakdown/donutbreakdown.py
+++ b/examples/charts/donutbreakdown/donutbreakdown.py
@@ -42,7 +42,7 @@
import sys
-from PySide6.QtCore import Qt
+from PySide6.QtCore import Qt, Slot
from PySide6.QtGui import QColor, QFont, QPainter, QScreen
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtCharts import QChart, QChartView, QPieSeries, QPieSlice
@@ -66,6 +66,7 @@ class MainSlice(QPieSlice):
def name(self):
return self.name
+ @Slot()
def update_label(self):
p = self.percentage() * 100
self.setLabel(f"{self.name} {p:.2f}%")
diff --git a/examples/charts/legend/legend.py b/examples/charts/legend/legend.py
index 0f3a99d40..84e12dd86 100644
--- a/examples/charts/legend/legend.py
+++ b/examples/charts/legend/legend.py
@@ -41,7 +41,7 @@
"""PySide6 port of the Legend example from Qt v5.x"""
import sys
-from PySide6.QtCore import Qt, QRectF
+from PySide6.QtCore import Qt, QRectF, Slot
from PySide6.QtGui import QBrush, QColor, QPainter, QPen
from PySide6.QtWidgets import (QApplication, QDoubleSpinBox,
QFormLayout, QGridLayout, QGroupBox, QPushButton, QWidget)
@@ -160,6 +160,7 @@ class MainWidget(QWidget):
def hide_legend_spinbox(self):
self.legend_settings.setVisible(False)
+ @Slot()
def toggle_attached(self):
legend = self.chart.legend()
if legend.isAttachedToChart():
@@ -176,6 +177,7 @@ class MainWidget(QWidget):
self.hide_legend_spinbox()
self.update()
+ @Slot()
def add_barset(self):
series_count = self.series.count()
bar_set = QBarSet(f"set {series_count}")
@@ -183,12 +185,14 @@ class MainWidget(QWidget):
bar_set.append([1 + delta, 2 + delta, 3 + delta, 4 + delta])
self.series.append(bar_set)
+ @Slot()
def remove_barset(self):
sets = self.series.barSets()
len_sets = len(sets)
if len_sets > 0:
self.series.remove(sets[len_sets - 1])
+ @Slot()
def set_legend_alignment(self):
button = self.sender()
legend = self.chart.legend()
@@ -211,18 +215,21 @@ class MainWidget(QWidget):
button.setText("Align (Top)")
legend.setAlignment(Qt.AlignTop)
+ @Slot()
def toggle_bold(self):
legend = self.chart.legend()
font = legend.font()
font.setBold(not font.bold())
legend.setFont(font)
+ @Slot()
def toggle_italic(self):
legend = self.chart.legend()
font = legend.font()
font.setItalic(not font.italic())
legend.setFont(font)
+ @Slot()
def font_size_changed(self):
legend = self.chart.legend()
font = legend.font()
@@ -232,6 +239,7 @@ class MainWidget(QWidget):
font.setPointSizeF(font_size)
legend.setFont(font)
+ @Slot()
def update_legend_layout(self):
legend = self.chart.legend()
diff --git a/examples/charts/lineandbar/lineandbar.py b/examples/charts/lineandbar/lineandbar.py
index bfe699199..cba60e970 100644
--- a/examples/charts/lineandbar/lineandbar.py
+++ b/examples/charts/lineandbar/lineandbar.py
@@ -89,13 +89,15 @@ class TestChart(QMainWindow):
self.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
self._axis_x = QBarCategoryAxis()
self._axis_x.append(self.categories)
- self.chart.setAxisX(self._axis_x, self._line_series)
- self.chart.setAxisX(self._axis_x, self._bar_series)
+ self.chart.addAxis(self._axis_x, Qt.AlignBottom)
+ self._line_series.attachAxis(self._axis_x)
+ self._bar_series.attachAxis(self._axis_x)
self._axis_x.setRange("Jan", "Jun")
self._axis_y = QValueAxis()
- self.chart.setAxisY(self._axis_y, self._line_series)
- self.chart.setAxisY(self._axis_y, self._bar_series)
+ self.chart.addAxis(self._axis_x, Qt.AlignLeft)
+ self._line_series.attachAxis(self._axis_y)
+ self._bar_series.attachAxis(self._axis_y)
self._axis_y.setRange(0, 20)
self.chart.legend().setVisible(True)
diff --git a/examples/charts/nesteddonuts/nesteddonuts.py b/examples/charts/nesteddonuts/nesteddonuts.py
index ddc18131b..c9b43e49d 100644
--- a/examples/charts/nesteddonuts/nesteddonuts.py
+++ b/examples/charts/nesteddonuts/nesteddonuts.py
@@ -43,7 +43,7 @@
import sys
-from PySide6.QtCore import Qt, QTimer
+from PySide6.QtCore import Qt, QTimer, Slot
from PySide6.QtGui import QPainter
from PySide6.QtWidgets import QApplication, QGridLayout, QWidget
from PySide6.QtCharts import QChart, QChartView, QPieSeries, QPieSlice
@@ -103,6 +103,7 @@ class Widget(QWidget):
self.donuts.append(donut)
self.chart_view.chart().addSeries(donut)
+ @Slot()
def update_rotation(self):
for donut in self.donuts:
phase_shift = randrange(-50, 100)
diff --git a/examples/charts/percentbarchart/percentbarchart.py b/examples/charts/percentbarchart/percentbarchart.py
index beabe0d6c..de067455c 100644
--- a/examples/charts/percentbarchart/percentbarchart.py
+++ b/examples/charts/percentbarchart/percentbarchart.py
@@ -81,7 +81,8 @@ class MainWindow(QMainWindow):
axis = QBarCategoryAxis()
axis.append(categories)
chart.createDefaultAxes()
- chart.setAxisX(axis, series)
+ chart.addAxis(axis, Qt.AlignBottom)
+ series.attachAxis(axis)
chart.legend().setVisible(True)
chart.legend().setAlignment(Qt.AlignBottom)
diff --git a/examples/corelib/settingseditor/settingseditor.py b/examples/corelib/settingseditor/settingseditor.py
index 389a2ffb7..79fcab5e5 100644
--- a/examples/corelib/settingseditor/settingseditor.py
+++ b/examples/corelib/settingseditor/settingseditor.py
@@ -46,7 +46,7 @@
import sys
from PySide6.QtCore import (QByteArray, QDate, QDateTime, QDir, QEvent, QPoint,
- QRect, QRegularExpression, QSettings, QSize, QTime, QTimer, Qt)
+ QRect, QRegularExpression, QSettings, QSize, QTime, QTimer, Qt, Slot)
from PySide6.QtGui import (QAction, QColor, QIcon, QIntValidator,
QDoubleValidator, QRegularExpressionValidator, QValidator)
from PySide6.QtWidgets import (QAbstractItemView, QApplication,
@@ -183,6 +183,7 @@ class MainWindow(QMainWindow):
self.setWindowTitle("Settings Editor")
self.resize(500, 600)
+ @Slot()
def open_settings(self):
if self.location_dialog is None:
self.location_dialog = LocationDialog(self)
@@ -195,6 +196,7 @@ class MainWindow(QMainWindow):
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(True)
+ @Slot()
def open_inifile(self):
file_name, _ = QFileDialog.getOpenFileName(self, "Open INI File",
'', "INI Files (*.ini *.conf)")
@@ -209,6 +211,7 @@ class MainWindow(QMainWindow):
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
+ @Slot()
def open_property_list(self):
file_name, _ = QFileDialog.getOpenFileName(self,
"Open Property List", '', "Property List Files (*.plist)")
@@ -218,6 +221,7 @@ class MainWindow(QMainWindow):
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
+ @Slot()
def open_registry_path(self):
path, ok = QInputDialog.getText(self, "Open Registry Path",
"Enter the path in the Windows registry:",
@@ -228,6 +232,7 @@ class MainWindow(QMainWindow):
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
+ @Slot()
def about(self):
QMessageBox.about(self, "About Settings Editor",
"The <b>Settings Editor</b> example shows how to access "
@@ -512,6 +517,7 @@ class SettingsTree(QTreeWidget):
def sizeHint(self):
return QSize(800, 600)
+ @Slot(bool)
def set_auto_refresh(self, autoRefresh):
self.auto_refresh = autoRefresh
@@ -522,15 +528,18 @@ class SettingsTree(QTreeWidget):
else:
self.refresh_timer.stop()
+ @Slot(bool)
def set_fallbacks_enabled(self, enabled):
if self.settings is not None:
self.settings.setFallbacksEnabled(enabled)
self.refresh()
+ @Slot()
def maybe_refresh(self):
if self.state() != QAbstractItemView.EditingState:
self.refresh()
+ @Slot()
def refresh(self):
if self.settings is None:
return
diff --git a/examples/corelib/threads/mandelbrot.py b/examples/corelib/threads/mandelbrot.py
index 824f4197d..b1f7a2fc8 100644
--- a/examples/corelib/threads/mandelbrot.py
+++ b/examples/corelib/threads/mandelbrot.py
@@ -47,7 +47,7 @@ import sys
from PySide6.QtCore import (Signal, QMutex, QElapsedTimer, QMutexLocker,
QPoint, QPointF, QSize, Qt, QThread,
- QWaitCondition)
+ QWaitCondition, Slot)
from PySide6.QtGui import QColor, QImage, QPainter, QPixmap, qRgb
from PySide6.QtWidgets import QApplication, QWidget
@@ -340,6 +340,7 @@ class MandelbrotWidget(QWidget):
delta_y = (self.height() - self.pixmap.height()) / 2 - self._pixmap_offset.y()
self.scroll(delta_x, delta_y)
+ @Slot(QImage,float)
def update_pixmap(self, image, scale_factor):
if not self._last_drag_pos.isNull():
return
diff --git a/examples/datavisualization/surface/surfacegraph.py b/examples/datavisualization/surface/surfacegraph.py
index f98c419f9..9bf2f41f8 100644
--- a/examples/datavisualization/surface/surfacegraph.py
+++ b/examples/datavisualization/surface/surfacegraph.py
@@ -108,6 +108,7 @@ class SurfaceGraph(QObject):
self._sqrtSinProxy.resetArray(data_array)
+ @Slot(bool)
def enable_sqrt_sin_model(self, enable):
if enable:
self._sqrtSinSeries.setDrawMode(QSurface3DSeries.DrawSurfaceAndWireframe)
@@ -139,6 +140,7 @@ class SurfaceGraph(QObject):
self._axisMaxSliderZ.setMaximum(SAMPLE_COUNT_Z - 1)
self._axisMaxSliderZ.setValue(SAMPLE_COUNT_Z - 1)
+ @Slot(bool)
def enable_height_map_model(self, enable):
if enable:
self._heightMapSeries.setDrawMode(QSurface3DSeries.DrawSurface)
@@ -173,6 +175,7 @@ class SurfaceGraph(QObject):
self._axisMaxSliderZ.setMaximum(map_grid_count_z - 1)
self._axisMaxSliderZ.setValue(map_grid_count_z - 1)
+ @Slot(int)
def adjust_xmin(self, minimum):
min_x = self._stepX * float(minimum) + self._rangeMinX
@@ -184,6 +187,7 @@ class SurfaceGraph(QObject):
self.set_axis_xrange(min_x, max_x)
+ @Slot(int)
def adjust_xmax(self, maximum):
max_x = self._stepX * float(maximum) + self._rangeMinX
@@ -195,6 +199,7 @@ class SurfaceGraph(QObject):
self.set_axis_xrange(min_x, max_x)
+ @Slot(int)
def adjust_zmin(self, minimum):
min_z = self._stepZ * float(minimum) + self._rangeMinZ
@@ -206,6 +211,7 @@ class SurfaceGraph(QObject):
self.set_axis_zrange(min_z, max_z)
+ @Slot(int)
def adjust_zmax(self, maximum):
max_x = self._stepZ * float(maximum) + self._rangeMinZ
@@ -223,10 +229,11 @@ class SurfaceGraph(QObject):
def set_axis_zrange(self, minimum, maximum):
self._graph.axisZ().setRange(minimum, maximum)
- @Slot()
+ @Slot(int)
def change_theme(self, theme):
self._graph.activeTheme().setType(Q3DTheme.Theme(theme))
+ @Slot()
def set_black_to_yellow_gradient(self):
gr = QLinearGradient()
gr.setColorAt(0.0, Qt.black)
@@ -238,6 +245,7 @@ class SurfaceGraph(QObject):
series.setBaseGradient(gr)
series.setColorStyle(Q3DTheme.ColorStyleRangeGradient)
+ @Slot()
def set_green_to_red_gradient(self):
gr = QLinearGradient()
gr.setColorAt(0.0, Qt.darkGreen)
@@ -249,17 +257,21 @@ class SurfaceGraph(QObject):
series.setBaseGradient(gr)
series.setColorStyle(Q3DTheme.ColorStyleRangeGradient)
+ @Slot()
def toggle_mode_none(self):
self._graph.setSelectionMode(QAbstract3DGraph.SelectionNone)
+ @Slot()
def toggle_mode_item(self):
self._graph.setSelectionMode(QAbstract3DGraph.SelectionItem)
+ @Slot()
def toggle_mode_slice_row(self):
self._graph.setSelectionMode(
QAbstract3DGraph.SelectionItemAndRow | QAbstract3DGraph.SelectionSlice
)
+ @Slot()
def toggle_mode_slice_column(self):
self._graph.setSelectionMode(
QAbstract3DGraph.SelectionItemAndColumn | QAbstract3DGraph.SelectionSlice
diff --git a/examples/datavisualization/surface_model_numpy/surfacegraph.py b/examples/datavisualization/surface_model_numpy/surfacegraph.py
index c95cec2a0..4b69ed161 100644
--- a/examples/datavisualization/surface_model_numpy/surfacegraph.py
+++ b/examples/datavisualization/surface_model_numpy/surfacegraph.py
@@ -150,6 +150,7 @@ class SurfaceGraph(QObject):
self.m_stepX = 0.0
self.m_stepZ = 0.0
+ @Slot(bool)
def enable_sqrt_sin_model(self, enable):
if enable:
self.m_sqrtSinSeries.setDrawMode(QSurface3DSeries.DrawSurfaceAndWireframe)
@@ -181,6 +182,7 @@ class SurfaceGraph(QObject):
self.m_axisMaxSliderZ.setMaximum(SAMPLE_COUNT_Z - 1)
self.m_axisMaxSliderZ.setValue(SAMPLE_COUNT_Z - 1)
+ @Slot(bool)
def enable_height_map_model(self, enable):
if enable:
self.m_heightMapSeries.setDrawMode(QSurface3DSeries.DrawSurface)
@@ -215,6 +217,7 @@ class SurfaceGraph(QObject):
self.m_axisMaxSliderZ.setMaximum(map_grid_count_z - 1)
self.m_axisMaxSliderZ.setValue(map_grid_count_z - 1)
+ @Slot(int)
def adjust_xmin(self, minimum):
min_x = self.m_stepX * float(minimum) + self.m_rangeMinX
@@ -226,6 +229,7 @@ class SurfaceGraph(QObject):
self.set_axis_xrange(min_x, max_x)
+ @Slot(int)
def adjust_xmax(self, maximum):
max_x = self.m_stepX * float(maximum) + self.m_rangeMinX
@@ -237,6 +241,7 @@ class SurfaceGraph(QObject):
self.set_axis_xrange(min_x, max_x)
+ @Slot(int)
def adjust_zmin(self, minimum):
min_z = self.m_stepZ * float(minimum) + self.m_rangeMinZ
@@ -248,6 +253,7 @@ class SurfaceGraph(QObject):
self.set_axis_zrange(min_z, max_z)
+ @Slot(int)
def adjust_zmax(self, maximum):
max_x = self.m_stepZ * float(maximum) + self.m_rangeMinZ
@@ -265,10 +271,11 @@ class SurfaceGraph(QObject):
def set_axis_zrange(self, minimum, maximum):
self.m_graph.axisZ().setRange(minimum, maximum)
- @Slot()
+ @Slot(int)
def change_theme(self, theme):
self.m_graph.activeTheme().setType(Q3DTheme.Theme(theme))
+ @Slot()
def set_black_to_yellow_gradient(self):
gr = QLinearGradient()
gr.setColorAt(0.0, Qt.black)
@@ -280,6 +287,7 @@ class SurfaceGraph(QObject):
series.setBaseGradient(gr)
series.setColorStyle(Q3DTheme.ColorStyleRangeGradient)
+ @Slot()
def set_green_to_red_gradient(self):
gr = QLinearGradient()
gr.setColorAt(0.0, Qt.darkGreen)
@@ -291,17 +299,21 @@ class SurfaceGraph(QObject):
series.setBaseGradient(gr)
series.setColorStyle(Q3DTheme.ColorStyleRangeGradient)
+ @Slot()
def toggle_mode_none(self):
self.m_graph.setSelectionMode(QAbstract3DGraph.SelectionNone)
+ @Slot()
def toggle_mode_item(self):
self.m_graph.setSelectionMode(QAbstract3DGraph.SelectionItem)
+ @Slot()
def toggle_mode_slice_row(self):
self.m_graph.setSelectionMode(
QAbstract3DGraph.SelectionItemAndRow | QAbstract3DGraph.SelectionSlice
)
+ @Slot()
def toggle_mode_slice_column(self):
self.m_graph.setSelectionMode(
QAbstract3DGraph.SelectionItemAndColumn | QAbstract3DGraph.SelectionSlice
diff --git a/examples/declarative/rendercontrol/rendercontrol_opengl/window_singlethreaded.py b/examples/declarative/rendercontrol/rendercontrol_opengl/window_singlethreaded.py
index f6e7bb274..534513277 100644
--- a/examples/declarative/rendercontrol/rendercontrol_opengl/window_singlethreaded.py
+++ b/examples/declarative/rendercontrol/rendercontrol_opengl/window_singlethreaded.py
@@ -55,7 +55,7 @@ from PySide6.QtQml import QQmlComponent, QQmlEngine
from PySide6.QtQuick import (QQuickGraphicsDevice,
QQuickItem, QQuickRenderControl,
QQuickRenderTarget, QQuickWindow)
-from PySide6.QtCore import QCoreApplication, QTimer, QUrl
+from PySide6.QtCore import QCoreApplication, QTimer, QUrl, Slot
from shiboken6 import VoidPtr
from cuberenderer import CubeRenderer
@@ -164,6 +164,7 @@ class WindowSingleThreaded(QWindow):
def set_texture_id(self, texture_id):
self.m_texture_ids[0] = texture_id
+ @Slot()
def createTexture(self):
# The scene graph has been initialized. It is now time to create a
# texture and associate it with the QQuickWindow.
@@ -183,10 +184,12 @@ class WindowSingleThreaded(QWindow):
self.m_textureSize)
self.m_quickWindow.setRenderTarget(target)
+ @Slot()
def destroyTexture(self):
self.m_context.functions().glDeleteTextures(1, self.m_texture_ids)
self.set_texture_id(0)
+ @Slot()
def render(self):
if not self.m_context.makeCurrent(self.m_offscreenSurface):
return
@@ -287,6 +290,7 @@ class WindowSingleThreaded(QWindow):
and self.m_textureSize != self.size() * self.devicePixelRatio()):
self.resizeTexture()
+ @Slot()
def handleScreenChange(self):
if self.m_dpr != self.devicePixelRatio():
self.resizeTexture()
diff --git a/examples/declarative/shared/Button.qml b/examples/declarative/shared/Button.qml
new file mode 100644
index 000000000..d5ba7e459
--- /dev/null
+++ b/examples/declarative/shared/Button.qml
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.12
+import QtQuick.Window 2.1
+
+Item {
+ id: container
+
+ property alias text: buttonLabel.text
+ property alias label: buttonLabel
+ signal clicked
+ property alias containsMouse: hoverHandler.hovered
+ property alias pressed: tapHandler.pressed
+ implicitHeight: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2)
+ implicitWidth: Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3)
+ height: implicitHeight
+ width: implicitWidth
+
+ SystemPalette { id: palette }
+
+ Rectangle {
+ id: frame
+ anchors.fill: parent
+ color: palette.button
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tapHandler.pressed ? Qt.darker(palette.button, 1.3) : palette.button }
+ GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) }
+ }
+ antialiasing: true
+ radius: height / 6
+ border.color: Qt.darker(palette.button, 1.5)
+ border.width: 1
+ }
+
+ TapHandler {
+ id: tapHandler
+ onTapped: container.clicked();
+ }
+ HoverHandler {
+ id: hoverHandler
+ }
+
+ Text {
+ id: buttonLabel
+ text: container.text
+ color: palette.buttonText
+ anchors.centerIn: parent
+ }
+}
diff --git a/examples/declarative/shared/CheckBox.qml b/examples/declarative/shared/CheckBox.qml
new file mode 100644
index 000000000..0e53737ea
--- /dev/null
+++ b/examples/declarative/shared/CheckBox.qml
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.12
+
+Item {
+ id: root
+ implicitHeight: frame.height
+ implicitWidth: row.implicitWidth
+ width: implicitWidth
+ height: implicitHeight
+ property alias text: label.text
+ property bool checked
+ property alias pressed: tapHandler.pressed
+ property alias row: row
+ signal clicked
+
+ SystemPalette { id: palette }
+
+ Row {
+ id: row
+ anchors.verticalCenter: parent.verticalCenter
+ spacing: 6
+ Rectangle {
+ id: frame
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: tapHandler.pressed ? Qt.darker(palette.button, 1.3) : palette.button }
+ GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) }
+ }
+ height: label.implicitHeight * 1.5
+ width: height
+ anchors.margins: 1
+ radius: 3
+ antialiasing: true
+ border.color: Qt.darker(palette.button, 1.5)
+ Image {
+ id: theX
+ source: "images/checkmark.png"
+ anchors.fill: frame
+ anchors.margins: frame.width / 5
+ fillMode: Image.PreserveAspectFit
+ smooth: true
+ visible: root.checked
+ }
+ }
+ Text {
+ id: label
+ color: palette.text
+ anchors.verticalCenter: frame.verticalCenter
+ }
+ }
+ TapHandler {
+ id: tapHandler
+ onTapped: {
+ parent.checked = !parent.checked
+ parent.clicked()
+ }
+ }
+}
diff --git a/examples/declarative/shared/FlickrRssModel.qml b/examples/declarative/shared/FlickrRssModel.qml
new file mode 100644
index 000000000..d2b8b48bc
--- /dev/null
+++ b/examples/declarative/shared/FlickrRssModel.qml
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.12
+
+ListModel {
+ id: flickrImages
+ property string tags : ""
+ readonly property string queryUrl : "http://api.flickr.com/services/feeds/photos_public.gne?"
+
+ function encodeParams(x) {
+ return encodeURIComponent(x.replace(" ",","));
+ }
+ function fetchImages(format) {
+ var requestURL = queryUrl + (tags ? "tags="+encodeParams(tags)+"&" : "") + "format=" + format + "&nojsoncallback=1";
+ var xhr = new XMLHttpRequest;
+ xhr.onreadystatechange = function() {
+ if (xhr.readyState === XMLHttpRequest.DONE) {
+
+ if (xhr.status !== 200) {
+ console.log("Failed to get images from flickr. status code: " + xhr.status);
+ return;
+ }
+
+ var jsonText = xhr.responseText;
+ var objArray = JSON.parse(jsonText.replace(/\'/g,"'"))
+ if (objArray.errors !== undefined)
+ console.log("Error fetching tweets: " + objArray.errors[0].message)
+ else {
+ for (var key in objArray.items) {
+ var rssItem = objArray.items[key];
+ var jsonObject = "{ \"title\": \"" + rssItem.title +"\",\"media\": \"" + rssItem.media.m + "\", \"thumbnail\": \"" + rssItem.media.m.replace(/\_m\.jpg/,"_s.jpg") +"\"}"
+ flickrImages.append(JSON.parse(jsonObject));
+ }
+ }
+ }
+ }
+ xhr.open("GET", requestURL, true);
+ xhr.send();
+ }
+ Component.onCompleted: {
+ fetchImages("json");
+ }
+}
+
diff --git a/examples/declarative/shared/Images.qml b/examples/declarative/shared/Images.qml
new file mode 100644
index 000000000..893b54aa8
--- /dev/null
+++ b/examples/declarative/shared/Images.qml
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQml
+
+QtObject {
+ readonly property url back: Qt.resolvedUrl("images/back.png")
+ readonly property url checkmark: Qt.resolvedUrl("images/checkmark.png")
+ readonly property url next: Qt.resolvedUrl("images/next.png")
+ readonly property url qtLogo: Qt.resolvedUrl("images/qt-logo.png")
+ readonly property url sliderHandle: Qt.resolvedUrl("images/slider_handle.png")
+ readonly property url tab: Qt.resolvedUrl("images/tab.png")
+}
diff --git a/examples/declarative/shared/Label.qml b/examples/declarative/shared/Label.qml
new file mode 100644
index 000000000..58739f194
--- /dev/null
+++ b/examples/declarative/shared/Label.qml
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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
+
+Text {
+ SystemPalette { id: palette }
+ color: palette.text
+}
diff --git a/examples/declarative/shared/LauncherList.qml b/examples/declarative/shared/LauncherList.qml
new file mode 100644
index 000000000..5de2fcb06
--- /dev/null
+++ b/examples/declarative/shared/LauncherList.qml
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Crimson AS <info@crimson.no>
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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 QtQml 2.12
+import QtQml.Models 2.12
+import QtQuick 2.12
+
+Rectangle {
+ id: root
+ property int activePageCount: 0
+
+ //model is a list of {"name":"somename", "url":"file:///some/url/mainfile.qml"}
+ //function used to add to model A) to enforce scheme B) to allow Qt.resolveUrl in url assignments
+
+ color: "#eee"
+ function addExample(name, desc, url) {
+ myModel.append({"name":name, "description":desc, "url":url})
+ }
+ function showExample(url) {
+ pageComponent.createObject(pageContainer, { exampleUrl: url }).show()
+ }
+
+ // The container rectangle here is used to give a nice "feel" when
+ // transitioning into an example.
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+
+ ListView {
+ id: launcherList
+ clip: true
+ delegate: SimpleLauncherDelegate{
+ required property url url
+ onClicked: root.showExample(url)
+ }
+ model: ListModel {id:myModel}
+ anchors.fill: parent
+ enabled: opacity == 1.0
+ }
+ }
+
+ Item {
+ id: pageContainer
+ anchors.fill: parent
+ }
+
+ Component {
+ id: pageComponent
+ Rectangle {
+ id: page
+ clip: true
+ property url exampleUrl
+ width: parent.width
+ height: parent.height - bar.height
+ color: "white"
+ TapHandler {
+ //Eats mouse events
+ }
+ Loader{
+ focus: true
+ source: parent.exampleUrl
+ anchors.fill: parent
+ }
+
+ function show() {
+ showAnim.start()
+ }
+
+ function exit() {
+ exitAnim.start()
+ }
+
+ ParallelAnimation {
+ id: showAnim
+ ScriptAction {
+ script: root.activePageCount++
+ }
+ NumberAnimation {
+ target: launcherList
+ property: "opacity"
+ from: 1.0
+ to: 0.0
+ duration: 500
+ }
+ NumberAnimation {
+ target: launcherList
+ property: "scale"
+ from: 1.0
+ to: 0.0
+ duration: 500
+ }
+ NumberAnimation {
+ target: page
+ property: "x"
+ from: -page.width
+ to: 0
+ duration: 300
+ }
+ }
+ SequentialAnimation {
+ id: exitAnim
+
+ ScriptAction {
+ script: root.activePageCount--
+ }
+
+ ParallelAnimation {
+ NumberAnimation {
+ target: launcherList
+ property: "opacity"
+ from: 0.0
+ to: 1.0
+ duration: 300
+ }
+ NumberAnimation {
+ target: launcherList
+ property: "scale"
+ from: 0.0
+ to: 1.0
+ duration: 300
+ }
+ NumberAnimation {
+ target: page
+ property: "x"
+ from: 0
+ to: -page.width
+ duration: 300
+ }
+ }
+
+ ScriptAction {
+ script: page.destroy()
+ }
+ }
+ }
+ }
+ Rectangle {
+ id: bar
+ visible: height > 0
+ anchors.bottom: parent.bottom
+ width: parent.width
+ height: root.activePageCount > 0 ? 40 : 0
+
+ Behavior on height {
+ NumberAnimation {
+ duration: 300
+ }
+ }
+
+ Rectangle {
+ height: 1
+ color: "#ccc"
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ Rectangle {
+ height: 1
+ color: "#fff"
+ anchors.top: parent.top
+ anchors.topMargin: 1
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+
+ gradient: Gradient {
+ GradientStop { position: 0 ; color: "#eee" }
+ GradientStop { position: 1 ; color: "#ccc" }
+ }
+
+ Image {
+ id: back
+ source: "images/back.png"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.verticalCenterOffset: 2
+ anchors.left: parent.left
+ anchors.leftMargin: 16
+
+ TapHandler {
+ id: tapHandler
+ enabled: root.activePageCount > 0
+ onTapped: {
+ pageContainer.children[pageContainer.children.length - 1].exit()
+ }
+ }
+ Rectangle {
+ anchors.centerIn: back
+ width: 38
+ height: 31
+ anchors.verticalCenterOffset: -1
+ opacity: tapHandler.pressed ? 1 : 0
+ Behavior on opacity { NumberAnimation{ duration: 100 }}
+ gradient: Gradient {
+ GradientStop { position: 0 ; color: "#22000000" }
+ GradientStop { position: 0.2 ; color: "#11000000" }
+ }
+ border.color: "darkgray"
+ antialiasing: true
+ radius: 4
+ }
+ }
+ }
+}
diff --git a/examples/declarative/shared/README b/examples/declarative/shared/README
new file mode 100644
index 000000000..2bf26d7c8
--- /dev/null
+++ b/examples/declarative/shared/README
@@ -0,0 +1,11 @@
+These files are shared between multiple examples as a set of common and
+reusuable components. While they do demonstrate the building of reusable
+components in QML, they are not official examples themselves.
+Consequently they do not have entries in the Qt documentation, and are
+documented only through the code comments within the files. Developers
+new to QML are strongly encouraged to go through the official examples
+before delving into this directory.
+
+For most application use, see the Qt Quick Components project to find
+ready-made Components you can use in your own projects. Qt Quick
+examples do not use them only to avoid external dependencies.
diff --git a/examples/declarative/shared/SimpleLauncherDelegate.qml b/examples/declarative/shared/SimpleLauncherDelegate.qml
new file mode 100644
index 000000000..3279ea11f
--- /dev/null
+++ b/examples/declarative/shared/SimpleLauncherDelegate.qml
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.12
+
+Rectangle {
+ id: container
+ required property string name
+ required property string description
+
+ property Item exampleItem
+ width: ListView.view.width
+ height: button.implicitHeight + 22
+
+ signal clicked()
+
+ gradient: Gradient {
+ GradientStop {
+ position: 0
+ Behavior on color {ColorAnimation { duration: 100 }}
+ color: tapHandler.pressed ? "#e0e0e0" : "#fff"
+ }
+ GradientStop {
+ position: 1
+ Behavior on color {ColorAnimation { duration: 100 }}
+ color: tapHandler.pressed ? "#e0e0e0" : button.containsMouse ? "#f5f5f5" : "#eee"
+ }
+ }
+
+ Image {
+ id: image
+ opacity: 0.7
+ Behavior on opacity {NumberAnimation {duration: 100}}
+ source: "images/next.png"
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.right: parent.right
+ anchors.rightMargin: 16
+ }
+
+ Item {
+ id: button
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.bottom: parent.bottom
+ anchors.right:image.left
+ implicitHeight: col.height
+ height: implicitHeight
+ width: buttonLabel.width + 20
+ property alias containsMouse: hoverHandler.hovered
+
+ TapHandler {
+ id: tapHandler
+ onTapped: container.clicked()
+ }
+ HoverHandler {
+ id: hoverHandler
+ }
+
+ Column {
+ spacing: 2
+ id: col
+ anchors.verticalCenter: parent.verticalCenter
+ width: parent.width
+ Text {
+ id: buttonLabel
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ text: container.name
+ color: "black"
+ font.pixelSize: 22
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ styleColor: "white"
+ style: Text.Raised
+
+ }
+ Text {
+ id: buttonLabel2
+ anchors.left: parent.left
+ anchors.leftMargin: 10
+ text: container.description
+ wrapMode: Text.WrapAtWordBoundaryOrAnywhere
+ color: "#666"
+ font.pixelSize: 12
+ }
+ }
+ }
+
+ Rectangle {
+ height: 1
+ color: "#ccc"
+ anchors.bottom: parent.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ }
+}
diff --git a/examples/declarative/shared/Slider.qml b/examples/declarative/shared/Slider.qml
new file mode 100644
index 000000000..9c1d5bd86
--- /dev/null
+++ b/examples/declarative/shared/Slider.qml
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.12
+
+Item {
+ id: slider
+ height: 26
+ // default drag range is 180: divisible by 2, 3, 4, 5, 6, 9, 10, ...
+ width: sliderName.width + 223 + handle.width / 2
+
+ property real min: 0
+ property real max: 1
+ property real value: min + (max - min) * dragHandler.value
+ property real init: min+(max-min)/2
+ property string name: "Slider"
+ property color color: "#0066cc"
+ property real minLabelWidth: 44
+
+ DragHandler {
+ id: dragHandler
+ target: handle
+ xAxis.minimum: Math.round(-handle.width / 2 + 3)
+ xAxis.maximum: Math.round(groove.width - handle.width / 2 - 3)
+ property real value: (handle.x - xAxis.minimum) / (xAxis.maximum - xAxis.minimum)
+ }
+
+ Component.onCompleted: setValue(init)
+ function setValue(v) {
+ if (min < max) {
+ handle.x = Math.round( v / (max - min) *
+ (dragHandler.xAxis.maximum - dragHandler.xAxis.minimum)
+ + dragHandler.xAxis.minimum);
+// console.log(name, v, "-> handle.x", handle.x, "from fraction", (v / (max - min)),
+// "of drag range", (dragHandler.xAxis.maximum - dragHandler.xAxis.minimum), "px", min, ":", max)
+ }
+ }
+ Rectangle {
+ id:sliderName
+ anchors.left: parent.left
+ anchors.leftMargin: 16
+ height: childrenRect.height
+ width: Math.max(slider.minLabelWidth, childrenRect.width)
+ anchors.verticalCenter: parent.verticalCenter
+ Text {
+ text: slider.name + ":"
+ font.pointSize: 12
+ color: "#333"
+ }
+ }
+
+ Rectangle {
+ id: groove
+ width: parent.width - 8 - sliderName.width
+ color: "#eee"
+ height: 7
+ radius: 3
+ antialiasing: true
+ border.color: Qt.darker(color, 1.2)
+ anchors.left: sliderName.right
+ anchors.right: parent.right
+ anchors.leftMargin: 10
+ anchors.rightMargin: 24
+ anchors.verticalCenter: parent.verticalCenter
+
+ Rectangle {
+ height: parent.height
+ anchors.left: parent.left
+ anchors.right: handle.horizontalCenter
+ color: slider.color
+ radius: 3
+ border.width: 1
+ border.color: Qt.darker(color, 1.3)
+ opacity: 0.8
+ }
+ Image {
+ id: handle
+ source: "images/slider_handle.png"
+ anchors.verticalCenter: parent.verticalCenter
+ }
+ }
+}
diff --git a/examples/declarative/shared/TabSet.qml b/examples/declarative/shared/TabSet.qml
new file mode 100644
index 000000000..c618b20fa
--- /dev/null
+++ b/examples/declarative/shared/TabSet.qml
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.12
+import QtQuick.Window 2.1
+
+Item {
+ id: tabWidget
+
+ // Setting the default property to stack.children means any child items
+ // of the TabWidget are actually added to the 'stack' item's children.
+ // See the "Property Binding"
+ // documentation for details on default properties.
+ default property alias content: stack.children
+
+ property int current: 0
+
+ onCurrentChanged: setZOrders()
+ Component.onCompleted: setZOrders()
+
+ function setZOrders() {
+ for (var i = 0; i < stack.children.length; ++i) {
+ stack.children[i].z = (i == current ? 1 : 0)
+ stack.children[i].enabled = (i == current)
+ }
+ }
+
+ Row {
+ id: header
+
+ Repeater {
+ model: stack.children.length
+ delegate: Rectangle {
+ required property int index
+ width: tabWidget.width / stack.children.length
+ height: Math.max(Screen.pixelDensity * 7, label.implicitHeight * 1.2)
+
+ Rectangle {
+ width: parent.width; height: 1
+ anchors { bottom: parent.bottom; bottomMargin: 1 }
+ color: "#acb2c2"
+ }
+ BorderImage {
+ anchors { fill: parent; leftMargin: 2; topMargin: 5; rightMargin: 1 }
+ border { left: 7; right: 7 }
+ source: "images/tab.png"
+ visible: tabWidget.current == parent.index
+ }
+ Text {
+ id: label
+ horizontalAlignment: Qt.AlignHCenter; verticalAlignment: Qt.AlignVCenter
+ anchors.fill: parent
+ text: stack.children[parent.index].title
+ elide: Text.ElideRight
+ font.bold: tabWidget.current == parent.index
+ }
+ TapHandler {
+ onTapped: tabWidget.current = parent.index
+ }
+ }
+ }
+ }
+
+ Item {
+ id: stack
+ width: tabWidget.width
+ anchors.top: header.bottom; anchors.bottom: tabWidget.bottom
+ }
+}
diff --git a/examples/declarative/shared/TextField.qml b/examples/declarative/shared/TextField.qml
new file mode 100644
index 000000000..559607480
--- /dev/null
+++ b/examples/declarative/shared/TextField.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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.1
+
+Item {
+ id: root
+
+ property alias textInput: textInput
+ property alias text: textInput.text
+ signal accepted
+ signal downPressed
+ implicitWidth: textInput.implicitWidth + rect.radius * 2
+ implicitHeight: textInput.implicitHeight
+
+ function copyAll() {
+ textInput.selectAll()
+ textInput.copy()
+ }
+
+ SystemPalette { id: palette }
+ height: textInput.implicitHeight + 8
+ clip: true
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent
+ radius: height / 4
+ color: palette.button
+ border.color: Qt.darker(palette.button, 1.5)
+ }
+
+ TextInput {
+ id: textInput
+ color: palette.text
+ anchors.fill: parent
+ anchors.leftMargin: rect.radius
+ anchors.rightMargin: rect.radius
+ verticalAlignment: Text.AlignVCenter
+ onAccepted: root.accepted()
+ Keys.onDownPressed: root.downPressed()
+ }
+}
diff --git a/examples/declarative/shared/images/back.png b/examples/declarative/shared/images/back.png
new file mode 100644
index 000000000..53402096b
--- /dev/null
+++ b/examples/declarative/shared/images/back.png
Binary files differ
diff --git a/examples/declarative/shared/images/checkmark.png b/examples/declarative/shared/images/checkmark.png
new file mode 100644
index 000000000..821aafccd
--- /dev/null
+++ b/examples/declarative/shared/images/checkmark.png
Binary files differ
diff --git a/examples/declarative/shared/images/next.png b/examples/declarative/shared/images/next.png
new file mode 100644
index 000000000..cdef8db6e
--- /dev/null
+++ b/examples/declarative/shared/images/next.png
Binary files differ
diff --git a/examples/declarative/shared/images/qt-logo.png b/examples/declarative/shared/images/qt-logo.png
new file mode 100644
index 000000000..30c621c9c
--- /dev/null
+++ b/examples/declarative/shared/images/qt-logo.png
Binary files differ
diff --git a/examples/declarative/shared/images/slider_handle.png b/examples/declarative/shared/images/slider_handle.png
new file mode 100644
index 000000000..63c518be7
--- /dev/null
+++ b/examples/declarative/shared/images/slider_handle.png
Binary files differ
diff --git a/examples/declarative/shared/images/tab.png b/examples/declarative/shared/images/tab.png
new file mode 100644
index 000000000..2ea989b68
--- /dev/null
+++ b/examples/declarative/shared/images/tab.png
Binary files differ
diff --git a/examples/declarative/shared/qmldir b/examples/declarative/shared/qmldir
new file mode 100644
index 000000000..5ccdf6021
--- /dev/null
+++ b/examples/declarative/shared/qmldir
@@ -0,0 +1,11 @@
+module shared
+Button 2.0 Button.qml
+CheckBox 2.1 CheckBox.qml
+FlickrRssModel 2.0 FlickrRssModel.qml
+Label 2.0 Label.qml
+LauncherList 2.0 LauncherList.qml
+SimpleLauncherDelegate 2.0 SimpleLauncherDelegate.qml
+Slider 2.0 Slider.qml
+TabSet 2.1 TabSet.qml
+TextField 2.1 TextField.qml
+singleton Images 2.2 Images.qml
diff --git a/examples/declarative/shared/quick_shared.qrc b/examples/declarative/shared/quick_shared.qrc
new file mode 100644
index 000000000..21f393a64
--- /dev/null
+++ b/examples/declarative/shared/quick_shared.qrc
@@ -0,0 +1,15 @@
+<RCC>
+ <qresource prefix="/quick/shared">
+ <file>LauncherList.qml</file>
+ <file>SimpleLauncherDelegate.qml</file>
+ <file>Button.qml</file>
+ <file>CheckBox.qml</file>
+ <file>Label.qml</file>
+ <file>TextField.qml</file>
+ <file>images/back.png</file>
+ <file>images/next.png</file>
+ <file>images/checkmark.png</file>
+ <file>Slider.qml</file>
+ <file>images/slider_handle.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/declarative/shared/shared.qrc b/examples/declarative/shared/shared.qrc
new file mode 100644
index 000000000..c19063a58
--- /dev/null
+++ b/examples/declarative/shared/shared.qrc
@@ -0,0 +1,21 @@
+<RCC>
+ <qresource prefix="/shared">
+ <file>Button.qml</file>
+ <file>CheckBox.qml</file>
+ <file>FlickrRssModel.qml</file>
+ <file>Images.qml</file>
+ <file>Label.qml</file>
+ <file>LauncherList.qml</file>
+ <file>SimpleLauncherDelegate.qml</file>
+ <file>Slider.qml</file>
+ <file>TabSet.qml</file>
+ <file>TextField.qml</file>
+ <file>images/back.png</file>
+ <file>images/checkmark.png</file>
+ <file>images/next.png</file>
+ <file>images/qt-logo.png</file>
+ <file>images/slider_handle.png</file>
+ <file>images/tab.png</file>
+ <file>qmldir</file>
+ </qresource>
+</RCC>
diff --git a/examples/declarative/shared/shared_rc.py b/examples/declarative/shared/shared_rc.py
new file mode 100644
index 000000000..97e5ecb87
--- /dev/null
+++ b/examples/declarative/shared/shared_rc.py
@@ -0,0 +1,1884 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 6.5.0
+# WARNING! All changes made in this file will be lost!
+
+from PySide6 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x06\x9b\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+12\x0a\x0aItem {\x0a i\
+d: root\x0a impl\
+icitHeight: fram\
+e.height\x0a imp\
+licitWidth: row.\
+implicitWidth\x0a \
+ width: implici\
+tWidth\x0a heigh\
+t: implicitHeigh\
+t\x0a property a\
+lias text: label\
+.text\x0a proper\
+ty bool checked\x0a\
+ property ali\
+as pressed: tapH\
+andler.pressed\x0a \
+ property alia\
+s row: row\x0a s\
+ignal clicked\x0a\x0a \
+ SystemPalette\
+ { id: palette }\
+\x0a\x0a Row {\x0a \
+ id: row\x0a \
+ anchors.vert\
+icalCenter: pare\
+nt.verticalCente\
+r\x0a spacin\
+g: 6\x0a Rec\
+tangle {\x0a \
+ id: frame\x0a \
+ gradi\
+ent: Gradient {\x0a\
+ \
+GradientStop { p\
+osition: 0.0; co\
+lor: tapHandler.\
+pressed ? Qt.dar\
+ker(palette.butt\
+on, 1.3) : palet\
+te.button }\x0a \
+ Grad\
+ientStop { posit\
+ion: 1.0; color:\
+ Qt.darker(palet\
+te.button, 1.3) \
+}\x0a }\x0a\
+ heig\
+ht: label.implic\
+itHeight * 1.5\x0a \
+ width\
+: height\x0a \
+ anchors.mar\
+gins: 1\x0a \
+ radius: 3\x0a \
+ antial\
+iasing: true\x0a \
+ border.\
+color: Qt.darker\
+(palette.button,\
+ 1.5)\x0a \
+ Image {\x0a \
+ id: th\
+eX\x0a \
+ source: \x22imag\
+es/checkmark.png\
+\x22\x0a \
+ anchors.fill: \
+frame\x0a \
+ anchors.ma\
+rgins: frame.wid\
+th / 5\x0a \
+ fillMode:\
+ Image.PreserveA\
+spectFit\x0a \
+ smooth:\
+ true\x0a \
+ visible: r\
+oot.checked\x0a \
+ }\x0a \
+ }\x0a Text\
+ {\x0a i\
+d: label\x0a \
+ color: pale\
+tte.text\x0a \
+ anchors.ver\
+ticalCenter: fra\
+me.verticalCente\
+r\x0a }\x0a \
+}\x0a TapHandler\
+ {\x0a id: t\
+apHandler\x0a \
+ onTapped: {\x0a \
+ parent\
+.checked = !pare\
+nt.checked\x0a \
+ parent.cl\
+icked()\x0a \
+}\x0a }\x0a}\x0a\
+\x00\x00\x04\x1c\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+1\x0a\x0aItem {\x0a id\
+: root\x0a\x0a prop\
+erty alias textI\
+nput: textInput\x0a\
+ property ali\
+as text: textInp\
+ut.text\x0a sign\
+al accepted\x0a \
+signal downPress\
+ed\x0a implicitW\
+idth: textInput.\
+implicitWidth + \
+rect.radius * 2\x0a\
+ implicitHeig\
+ht: textInput.im\
+plicitHeight\x0a\x0a \
+ function copyA\
+ll() {\x0a t\
+extInput.selectA\
+ll()\x0a tex\
+tInput.copy()\x0a \
+ }\x0a\x0a SystemP\
+alette { id: pal\
+ette }\x0a heigh\
+t: textInput.imp\
+licitHeight + 8\x0a\
+ clip: true\x0a\x0a\
+ Rectangle {\x0a\
+ id: rect\
+\x0a anchors\
+.fill: parent\x0a \
+ radius: he\
+ight / 4\x0a \
+ color: palette.\
+button\x0a b\
+order.color: Qt.\
+darker(palette.b\
+utton, 1.5)\x0a \
+}\x0a\x0a TextInput\
+ {\x0a id: t\
+extInput\x0a \
+ color: palette.\
+text\x0a anc\
+hors.fill: paren\
+t\x0a anchor\
+s.leftMargin: re\
+ct.radius\x0a \
+ anchors.rightM\
+argin: rect.radi\
+us\x0a verti\
+calAlignment: Te\
+xt.AlignVCenter\x0a\
+ onAccept\
+ed: root.accepte\
+d()\x0a Keys\
+.onDownPressed: \
+root.downPressed\
+()\x0a }\x0a}\x0a\
+\x00\x00\x00\xc7\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+0\x0a\x0aText {\x0a Sy\
+stemPalette { id\
+: palette }\x0a \
+color: palette.t\
+ext\x0a}\x0a\
+\x00\x00\x0ax\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0aim\
+port QtQuick 2.1\
+2\x0a\x0aRectangle {\x0a \
+ id: container\
+\x0a required pr\
+operty string na\
+me\x0a required \
+property string \
+description\x0a\x0a \
+ property Item e\
+xampleItem\x0a w\
+idth: ListView.v\
+iew.width\x0a he\
+ight: button.imp\
+licitHeight + 22\
+\x0a\x0a signal cli\
+cked()\x0a\x0a grad\
+ient: Gradient {\
+\x0a Gradien\
+tStop {\x0a \
+ position: 0\x0a\
+ Beha\
+vior on color {C\
+olorAnimation { \
+duration: 100 }}\
+\x0a col\
+or: tapHandler.p\
+ressed ? \x22#e0e0e\
+0\x22 : \x22#fff\x22\x0a \
+ }\x0a Gr\
+adientStop {\x0a \
+ positio\
+n: 1\x0a \
+ Behavior on col\
+or {ColorAnimati\
+on { duration: 1\
+00 }}\x0a \
+ color: tapHand\
+ler.pressed ? \x22#\
+e0e0e0\x22 : button\
+.containsMouse ?\
+ \x22#f5f5f5\x22 : \x22#e\
+ee\x22\x0a }\x0a \
+ }\x0a\x0a Image {\
+\x0a id: ima\
+ge\x0a opaci\
+ty: 0.7\x0a \
+Behavior on opac\
+ity {NumberAnima\
+tion {duration: \
+100}}\x0a so\
+urce: \x22images/ne\
+xt.png\x22\x0a \
+anchors.vertical\
+Center: parent.v\
+erticalCenter\x0a \
+ anchors.ri\
+ght: parent.righ\
+t\x0a anchor\
+s.rightMargin: 1\
+6\x0a }\x0a\x0a Ite\
+m {\x0a id: \
+button\x0a a\
+nchors.top: pare\
+nt.top\x0a a\
+nchors.left: par\
+ent.left\x0a \
+ anchors.bottom:\
+ parent.bottom\x0a \
+ anchors.r\
+ight:image.left\x0a\
+ implicit\
+Height: col.heig\
+ht\x0a heigh\
+t: implicitHeigh\
+t\x0a width:\
+ buttonLabel.wid\
+th + 20\x0a \
+property alias c\
+ontainsMouse: ho\
+verHandler.hover\
+ed\x0a\x0a TapH\
+andler {\x0a \
+ id: tapHand\
+ler\x0a \
+onTapped: contai\
+ner.clicked()\x0a \
+ }\x0a \
+HoverHandler {\x0a \
+ id: h\
+overHandler\x0a \
+ }\x0a\x0a C\
+olumn {\x0a \
+ spacing: 2\x0a \
+ id: c\
+ol\x0a a\
+nchors.verticalC\
+enter: parent.ve\
+rticalCenter\x0a \
+ width: \
+parent.width\x0a \
+ Text {\x0a\
+ \
+id: buttonLabel\x0a\
+ \
+anchors.left: pa\
+rent.left\x0a \
+ anchor\
+s.leftMargin: 10\
+\x0a \
+ anchors.right: \
+parent.right\x0a \
+ anc\
+hors.rightMargin\
+: 10\x0a \
+ text: conta\
+iner.name\x0a \
+ color:\
+ \x22black\x22\x0a \
+ font.pi\
+xelSize: 22\x0a \
+ wrap\
+Mode: Text.WrapA\
+tWordBoundaryOrA\
+nywhere\x0a \
+ styleCol\
+or: \x22white\x22\x0a \
+ styl\
+e: Text.Raised\x0a\x0a\
+ }\x0a \
+ Text {\
+\x0a \
+ id: buttonLabel\
+2\x0a \
+ anchors.left: \
+parent.left\x0a \
+ anch\
+ors.leftMargin: \
+10\x0a \
+ text: contain\
+er.description\x0a \
+ w\
+rapMode: Text.Wr\
+apAtWordBoundary\
+OrAnywhere\x0a \
+ color\
+: \x22#666\x22\x0a \
+ font.pi\
+xelSize: 12\x0a \
+ }\x0a \
+ }\x0a }\x0a\x0a R\
+ectangle {\x0a \
+ height: 1\x0a \
+ color: \x22#cc\
+c\x22\x0a ancho\
+rs.bottom: paren\
+t.bottom\x0a \
+ anchors.left: p\
+arent.left\x0a \
+ anchors.right\
+: parent.right\x0a \
+ }\x0a}\x0a\
+\x00\x00\x05\xac\
+\x00\
+\x00\x16\xecx\x9c\xd5\x18ko\xdb6\xf0\xbb\x7f\x05\xa1\
+~q\xd0X\xb2\x9d\xee\x01om\x97\xbaE\x17 ]\
+\x93\xba\x1b\x06\x0c\xfb@K'\x9b\xabD\xaa\x14\x9d4\
+\x08\xfc\xdfwG\x89\xaai\xc9\x8f\xb6\xeb\x80\x1e\x90X\
+<\xde\x1d\xef\xad\xa3\xa2\x88MUq\xa7\xc5biX\
+\x7fz\xc2\xc6\xc3\xd1\x0fl\xaaE^*\xc9\xceg\xec\
+g!S\xf5K\x5c!B\xa9\x9e\xf4\xa2N\x96\xb7K\
+`\xd7\x06w\xf2\x82\xcb;vi\x92\x90(gW\xcf\
+\xff\x1c\x5c\x8a\x18d\x09\x83\x8b\x04\xa4\x11\xa9\x00=a\
+5\xee\x0d\xa4\x83k3@\xb6\x1ct,x\xc6^\xbf\
+a\xcff\xcf\x07g\x83i\xc6W%\xf4z\x22/\x94\
+6(\xfc:\xcf\xd88\x1c\x8d=L\xf8J%\x90\x95\
+\xdb\x1b+\x11\xbf\xabp\xbd7\x10\x1b.\x17\x19\xb0\xfb\
+\x1eC\x10\xc9\x84i\xa5\x8c]\x14Z\x15\xa0\xcd\x1d\x13\
+\xd20\x1e\x1bq\x03W|\x01S\xb5\x92f\xc2\x86=\
+K\x14E9\x1d\xc2D\xc98\xcbDi\x98J\xd9}\
+ y\x0e\xc1$(U\x0e\xf6\xf1\x94\x05+\x9d!&\
+\x15\x19L\xa2(\xa2\x9d\x08QQ\xce\xd1\x8b\x88\x0c\xdf\
+\xe7Y\xb0\xaee\xa6+\x89\xe7\xa1\x97\xd1\xca\x84\x19\xc5\
+xb\x7f\xaa\xb3\xceO\xe8\x19\xd0\xf9:\x06V\xc6K\
+\xc8\x81=\xb3H\x9ee\xea\x16\x8d\x0c5\x94*\xbb\x81\
+\xdf5\xaa\x86b\xf0\x87\x97\xa5XH\xd4\xc7\x94\x95\xea\
+\xb1\xca\x14z;x\x00\x00\x81\xc54\xc7\xe2q/>\
+\xf0\xbc\xc8\xa0O\xea\x9f\xb2\x04\xca\xf8\x94\xc4\x9c\xd4\x9e\
+\x22\xc8\xef\xac\x83C^\x14 \x93\xbe\xb3\xba\xe2\x08\x88\
+E\x8b\x82\xe4\x05\x93\x8a\xbf\xf2\x01\xfe[\x9fX!k\
+\xff\xd4r\xa9n\xdd\xb1[G\x15\xd6\xf1\x18B\x89\xfa\
+\x87\xb1\x06n\xe0\xf5\xfc\x1f\x0c_\xbf\xda\x92\x06\xfd\x08\
+\xfa\x94\xdd3\xa8D\xa0\xe9\x13k\xf8\xfa$$\xc9}\
+wf\xedc\x9b\x96\xb1cd\xbaI\x85%h\xa0x\
+:\xdf/0\xf0\x18\x5c\x89Y\xc9\x82\x14 \x0b\xd8\xed\
+\x12\xa4\x13c4\x97\xa5 \x03\x84\x5cP\xae`\x14\xa4\
+S\x22\xb4T\xdbiF\xc0e\xbcT\xba\x0c1\xf6\xa8\
+g\xc15\x1a\xd6l\xba\xd0\xcc3\x1e\xbf\x0bz\x0d\xfe\
+\x12\x13\xec\x0f\x01\xb7\x1br\x5c\xdabE\xa0D\xd0D\
+\xe2m\xc6\x99(&\xa8\xe5\x0a<4\x06\x0e\x16\xe8\xc5\
+\x09\x9b\x09\xd2\xf4\xb2\xe6\x7f^\xe3\xfd\x13\x084\xbc_\
+\x09\x8d>i\x0a\x83\xbc\x8b\x7f-J%\xa7\x19\x16\x19\
+\xd4\xd5\x14n\x07\xd6cX{+\x9b\xe1\x13k\xa8M\
+.v\x8f\xc6\xd5\x89\xe6S\xeeu \x01V\xde<#\
+\x1dT\xc1c\x81\xea>~\xccF\xe1\xb0\xa1Yo\xe6\
+\xc3\x85\x81|\xc3\xab\xe4Q/\xb1\x0e\xc7\xad\x16\xd4d\
+i\xa7\xb4z\xaf\xd9\xe9\xca\x8cM\x8ec\x22\xe9\x85\xe3\
+c\xf2{4\xb7\x221K\xa7nhW\xde\xfe\x12\xa8\
+e7\x04\xd5\x92\x0d\xd8\x9c\xebz\xe1kR\xe7\xe7\xed\
+R\x98\xbaw8x\xcb\x8b_\xb9L2,\xa9v\x0a\
+E\xd1\x0bnJ\x0c2\xd6\x16\x83\x1b\xdb\x8b6\xf7\xfd\
+\x08_*\x9e\x80nKIU\xbc*;\x1cAP\xaa\
+\x156\xc5\xc6\x90\x1d\xee 8\x98?\xeb\x9e\xb7\xf4\xda\
+T\xff\xa4\xc3:\xda8\x97\x22\x0fK\xc3\xb5\xe9o\xa7\
+y\xb74\xf8 L\xa74\xda8V\xda\x15\xd7\xd8\xf9\
+!#zn\xc5\xb6\xe5QJ9\x0d[\x9b3\xdb\xaa\
+\xcf\xe3\x1d\xbc\xd6:KRW\xf4\xd6\xeb\xf0\xe1\xc3\x16\
+\xcb\xba\x85\xf9m\x95\xcfA\xefS\x91\x00\x8d]\x80\xd9\
+\xd3\xcf\x1c\xb8\xb4\xc74\xac\x0b<\xe8\xa4K\xb5\xca'\
+^\xe1{\xc7)|\x95\xef\xd8KV\xdaj:a\xdf\
+\x0d\xdb\x14\xff\xa7\x81e\xcc3\xf8\xb6\xccku\xaf\x0e\
+\xb3>\xec3i@\x12:Z\x95g\xda\x01\xc3\xce\x0e\
+\x1a\xe6\xaff\xf8\x8a\xa39\x94\x1f\xac$W\x9d\xbd\xff\
+\xba\x94\x06\x83\x0e\x8d[\xa8c\x0a\x9e\xe0\xb8\x98\x11\x1c\
+\x9d\x96\x04\xc7\xd6\x1eA\x15\xcd]Ih\x8fV\xbb\x13\
+\x98`\x7f<\x09\xda\xc9J\xf0\xf5\x8d\xdfS\x97\x04\xdf\
+\x92\xe9;\xeb\x95\xe0p\xcd\x12\xd4\xe6\xee5\xf6PU\
+\x13|\x8e\xd1\x1d5\xf2\x09\x85h\x95\xc2;\x8a\xd1\xea\
+n\xebM\xdb>\xee\xe3\xcaM\x90\xf4\xbfk\x92\xa3F\
+\x81\x13T\xb3\xbe\x11\xa5\xc0\x91tR\x8f[\xec\xc9\x86\
+\xb3\xdc82W\xc6\x90\x1b\xeb\x01\xa6Z6T\xfb\xe6\
+87\xc3uu\x15:\x8a=e\x8f\x86\xac\xb9\xb9\x12\
+<\x83%\xbf\x11J\xe3\xc4\xeet\xf2\x1du8\x8fv\
+\x07k\xd3O\x07\x07^\xa7\xfc\xa8s\xce|\x10\xc7\xb1\
+\x9fw\xce]F\x15\x8d;\xf0\xb9\x93&\x83\xf4\xe3h\
+K\x8bN*\xedM\xc0\xda\x9by\xbf\xdc\x804M?\
+\xdf\x00\xc4\xbf\xc22\x15r[\xfcW\xb1p\xa1y\x22\
+\x80\xbeq\xbc\xac\x9f\xb6Lu\xe8\x19\xea\x85\xf7\xedB\
+U\xd7_\xcc,\xf6\x93\xffUa\xabrv2\x8e6\
+\x19)\xd6\xdd\xc9s\x91c>w\xdc\x94\xe6xK\xf6\
+\x90\xee\x16\x10\x08\xe2(#\x22\x08\x0b\xb9\xe8\x0e\xc1\x0d\
+\xb66\x81\x9d|\x8a\xaa\xd1\xf7\xa7\xdaA>\xfa\x08\xce\
+\xd7iZR+\x1d\x7fA\x8ch\xa3\x89\xf5\xf7~S\
+\xdb{\xb5\x22?\x98\x86\xa0}\x9bp\x97\xe1]\xdd\xa1\
+\xc5\xa1\xe4[\xfa\xb0\x83,\xdd\xbd\xd3\xbb\x1e\x87\xf1R\
+d\x09\x9a\xf6W7\x1a\xed\x92\x0b\xb3\xc4\x1b\xe5\xe8\xef\
+\xb0\xba\xf2|\xd2`\xb6\xab\xea6]\x17\xdb \x5c\xc8\
+\x8e| \xa8[\xe7\xd9\x8f\xad\x1dW\xbag\xa3\x9d\xb2\
+\xbb\x03=h3\xd4\xe3\xd0f,\xc2BCI\xdf\x92\
+\x9eb\x9ew\xbd\x1f7\xbb\xb0\xfbVq\xbf\xddz\xef\
+7:\xedh8d\xeb\xf6;\xf0`\xe1:8\xae\x80\
+\xc7\xe3\xa1\x85\xed*>,%\x1co\xca\x19\x8dv\xcb\
+ic\xe6J'\x9485w\xc2\xf5;\xb4\xabc\xbe\
+\xe4vN\x17\xbc\x14r\xb1\xe3c\x00)H_\x0a\x1e\
+\x1dx\x7f\xaf{\xff\x02>\xc5\xc9[\
+\x00\x00\x0aH\
+/\
+/ Copyright (C) \
+2016 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+12\x0a\x0aItem {\x0a i\
+d: slider\x0a he\
+ight: 26\x0a // \
+default drag ran\
+ge is 180: divis\
+ible by 2, 3, 4,\
+ 5, 6, 9, 10, ..\
+.\x0a width: sli\
+derName.width + \
+223 + handle.wid\
+th / 2\x0a\x0a prop\
+erty real min: 0\
+\x0a property re\
+al max: 1\x0a pr\
+operty real valu\
+e: min + (max - \
+min) * dragHandl\
+er.value\x0a pro\
+perty real init:\
+ min+(max-min)/2\
+\x0a property st\
+ring name: \x22Slid\
+er\x22\x0a property\
+ color color: \x22#\
+0066cc\x22\x0a prop\
+erty real minLab\
+elWidth: 44\x0a\x0a \
+ DragHandler {\x0a \
+ id: dragH\
+andler\x0a t\
+arget: handle\x0a \
+ xAxis.mini\
+mum: Math.round(\
+-handle.width / \
+2 + 3)\x0a x\
+Axis.maximum: Ma\
+th.round(groove.\
+width - handle.w\
+idth / 2 - 3)\x0a \
+ property r\
+eal value: (hand\
+le.x - xAxis.min\
+imum) / (xAxis.m\
+aximum - xAxis.m\
+inimum)\x0a }\x0a\x0a \
+ Component.onC\
+ompleted: setVal\
+ue(init)\x0a fun\
+ction setValue(v\
+) {\x0a if (\
+min < max) {\x0a \
+ handle.\
+x = Math.round( \
+v / (max - min) \
+*\x0a \
+ \
+ (dragHandler.x\
+Axis.maximum - d\
+ragHandler.xAxis\
+.minimum)\x0a \
+ \
+ + drag\
+Handler.xAxis.mi\
+nimum);\x0a// \
+ console.lo\
+g(name, v, \x22-> h\
+andle.x\x22, handle\
+.x, \x22from fracti\
+on\x22, (v / (max -\
+ min)),\x0a// \
+ \x22of dr\
+ag range\x22, (drag\
+Handler.xAxis.ma\
+ximum - dragHand\
+ler.xAxis.minimu\
+m), \x22px\x22, min, \x22\
+:\x22, max)\x0a \
+ }\x0a }\x0a Rec\
+tangle {\x0a \
+ id:sliderName\x0a \
+ anchors.l\
+eft: parent.left\
+\x0a anchors\
+.leftMargin: 16\x0a\
+ height: \
+childrenRect.hei\
+ght\x0a widt\
+h: Math.max(slid\
+er.minLabelWidth\
+, childrenRect.w\
+idth)\x0a an\
+chors.verticalCe\
+nter: parent.ver\
+ticalCenter\x0a \
+ Text {\x0a \
+ text: sli\
+der.name + \x22:\x22\x0a \
+ font.\
+pointSize: 12\x0a \
+ color:\
+ \x22#333\x22\x0a \
+}\x0a }\x0a\x0a Rec\
+tangle {\x0a \
+ id: groove\x0a \
+ width: paren\
+t.width - 8 - sl\
+iderName.width\x0a \
+ color: \x22#\
+eee\x22\x0a hei\
+ght: 7\x0a r\
+adius: 3\x0a \
+ antialiasing: t\
+rue\x0a bord\
+er.color: Qt.dar\
+ker(color, 1.2)\x0a\
+ anchors.\
+left: sliderName\
+.right\x0a a\
+nchors.right: pa\
+rent.right\x0a \
+ anchors.leftM\
+argin: 10\x0a \
+ anchors.rightM\
+argin: 24\x0a \
+ anchors.vertic\
+alCenter: parent\
+.verticalCenter\x0a\
+\x0a Rectang\
+le {\x0a \
+ height: parent.\
+height\x0a \
+ anchors.left:\
+ parent.left\x0a \
+ anchors\
+.right: handle.h\
+orizontalCenter\x0a\
+ colo\
+r: slider.color\x0a\
+ radi\
+us: 3\x0a \
+ border.width: \
+1\x0a bo\
+rder.color: Qt.d\
+arker(color, 1.3\
+)\x0a op\
+acity: 0.8\x0a \
+ }\x0a Ima\
+ge {\x0a \
+ id: handle\x0a \
+ source: \
+\x22images/slider_h\
+andle.png\x22\x0a \
+ anchors.v\
+erticalCenter: p\
+arent.verticalCe\
+nter\x0a }\x0a \
+ }\x0a}\x0a\
+\x00\x00\x06\xc5\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+12\x0a\x0aListModel {\x0a\
+ id: flickrIm\
+ages\x0a propert\
+y string tags : \
+\x22\x22\x0a readonly \
+property string \
+queryUrl : \x22http\
+://api.flickr.co\
+m/services/feeds\
+/photos_public.g\
+ne?\x22\x0a\x0a functi\
+on encodeParams(\
+x) {\x0a ret\
+urn encodeURICom\
+ponent(x.replace\
+(\x22 \x22,\x22,\x22));\x0a \
+}\x0a function f\
+etchImages(forma\
+t) {\x0a var\
+ requestURL = qu\
+eryUrl + (tags ?\
+ \x22tags=\x22+encodeP\
+arams(tags)+\x22&\x22 \
+: \x22\x22) + \x22format=\
+\x22 + format + \x22&n\
+ojsoncallback=1\x22\
+;\x0a var xh\
+r = new XMLHttpR\
+equest;\x0a \
+xhr.onreadystate\
+change = functio\
+n() {\x0a \
+ if (xhr.readyS\
+tate === XMLHttp\
+Request.DONE) {\x0a\
+\x0a \
+ if (xhr.status \
+!== 200) {\x0a \
+ c\
+onsole.log(\x22Fail\
+ed to get images\
+ from flickr. st\
+atus code: \x22 + x\
+hr.status);\x0a \
+ \
+return;\x0a \
+ }\x0a\x0a \
+ var j\
+sonText = xhr.re\
+sponseText;\x0a \
+ var \
+objArray = JSON.\
+parse(jsonText.r\
+eplace(/\x5c'/g,\x22'\x22\
+))\x0a \
+ if (objArray.\
+errors !== undef\
+ined)\x0a \
+ consol\
+e.log(\x22Error fet\
+ching tweets: \x22 \
++ objArray.error\
+s[0].message)\x0a \
+ el\
+se {\x0a \
+ for (va\
+r key in objArra\
+y.items) {\x0a \
+ \
+ var rssItem =\
+ objArray.items[\
+key];\x0a \
+ va\
+r jsonObject = \x22\
+{ \x5c\x22title\x5c\x22: \x5c\x22\x22\
+ + rssItem.title\
+ +\x22\x5c\x22,\x5c\x22media\x5c\x22:\
+ \x5c\x22\x22 + rssItem.m\
+edia.m + \x22\x5c\x22, \x5c\x22\
+thumbnail\x5c\x22: \x5c\x22\x22\
+ + rssItem.media\
+.m.replace(/\x5c_m\x5c\
+.jpg/,\x22_s.jpg\x22) \
++\x22\x5c\x22}\x22\x0a \
+ f\
+lickrImages.appe\
+nd(JSON.parse(js\
+onObject));\x0a \
+ \
+}\x0a \
+ }\x0a \
+}\x0a }\x0a \
+ xhr.open(\x22GE\
+T\x22, requestURL, \
+true);\x0a x\
+hr.send();\x0a }\
+\x0a Component.o\
+nCompleted: {\x0a \
+ fetchImage\
+s(\x22json\x22);\x0a }\
+\x0a}\x0a\x0a\
+\x00\x00\x018\
+m\
+odule shared\x0aBut\
+ton 2.0 Button.q\
+ml\x0aCheckBox 2.1 \
+CheckBox.qml\x0aFli\
+ckrRssModel 2.0 \
+FlickrRssModel.q\
+ml\x0aLabel 2.0 Lab\
+el.qml\x0aLauncherL\
+ist 2.0 Launcher\
+List.qml\x0aSimpleL\
+auncherDelegate \
+2.0 SimpleLaunch\
+erDelegate.qml\x0aS\
+lider 2.0 Slider\
+.qml\x0aTabSet 2.1 \
+TabSet.qml\x0aTextF\
+ield 2.1 TextFie\
+ld.qml\x0asingleton\
+ Images 2.2 Imag\
+es.qml\x0a\
+\x00\x00\x08\xdc\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+12\x0aimport QtQuic\
+k.Window 2.1\x0a\x0aIt\
+em {\x0a id: tab\
+Widget\x0a\x0a // S\
+etting the defau\
+lt property to s\
+tack.children me\
+ans any child it\
+ems\x0a // of th\
+e TabWidget are \
+actually added t\
+o the 'stack' it\
+em's children.\x0a \
+ // See the \x22P\
+roperty Binding\x22\
+\x0a // document\
+ation for detail\
+s on default pro\
+perties.\x0a def\
+ault property al\
+ias content: sta\
+ck.children\x0a\x0a \
+ property int cu\
+rrent: 0\x0a\x0a on\
+CurrentChanged: \
+setZOrders()\x0a \
+ Component.onCom\
+pleted: setZOrde\
+rs()\x0a\x0a functi\
+on setZOrders() \
+{\x0a for (v\
+ar i = 0; i < st\
+ack.children.len\
+gth; ++i) {\x0a \
+ stack.ch\
+ildren[i].z = (i\
+ == current ? 1 \
+: 0)\x0a \
+ stack.children[\
+i].enabled = (i \
+== current)\x0a \
+ }\x0a }\x0a\x0a \
+ Row {\x0a i\
+d: header\x0a\x0a \
+ Repeater {\x0a \
+ model:\
+ stack.children.\
+length\x0a \
+ delegate: Rec\
+tangle {\x0a \
+ require\
+d property int i\
+ndex\x0a \
+ width: tabW\
+idget.width / st\
+ack.children.len\
+gth\x0a \
+ height: Math\
+.max(Screen.pixe\
+lDensity * 7, la\
+bel.implicitHeig\
+ht * 1.2)\x0a\x0a \
+ Recta\
+ngle {\x0a \
+ width\
+: parent.width; \
+height: 1\x0a \
+ an\
+chors { bottom: \
+parent.bottom; b\
+ottomMargin: 1 }\
+\x0a \
+ color: \x22#ac\
+b2c2\x22\x0a \
+ }\x0a \
+ BorderIm\
+age {\x0a \
+ anchor\
+s { fill: parent\
+; leftMargin: 2;\
+ topMargin: 5; r\
+ightMargin: 1 }\x0a\
+ \
+ border { lef\
+t: 7; right: 7 }\
+\x0a \
+ source: \x22im\
+ages/tab.png\x22\x0a \
+ \
+ visible: tabWi\
+dget.current == \
+parent.index\x0a \
+ }\x0a \
+ T\
+ext {\x0a \
+ id: la\
+bel\x0a \
+ horizont\
+alAlignment: Qt.\
+AlignHCenter; ve\
+rticalAlignment:\
+ Qt.AlignVCenter\
+\x0a \
+ anchors.fil\
+l: parent\x0a \
+ te\
+xt: stack.childr\
+en[parent.index]\
+.title\x0a \
+ elide\
+: Text.ElideRigh\
+t\x0a \
+ font.bold:\
+ tabWidget.curre\
+nt == parent.ind\
+ex\x0a \
+ }\x0a \
+ TapHandler \
+{\x0a \
+ onTapped: \
+tabWidget.curren\
+t = parent.index\
+\x0a \
+ }\x0a }\
+\x0a }\x0a }\
+\x0a\x0a Item {\x0a \
+ id: stack\x0a \
+ width: ta\
+bWidget.width\x0a \
+ anchors.to\
+p: header.bottom\
+; anchors.bottom\
+: tabWidget.bott\
+om\x0a }\x0a}\x0a\
+\x00\x00\x02h\
+/\
+/ Copyright (C) \
+2021 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ap\
+ragma Singleton\x0a\
+import QtQml\x0a\x0aQt\
+Object {\x0a rea\
+donly property u\
+rl back: \
+ Qt.resolvedUrl(\
+\x22images/back.png\
+\x22)\x0a readonly \
+property url che\
+ckmark: Qt.re\
+solvedUrl(\x22image\
+s/checkmark.png\x22\
+)\x0a readonly p\
+roperty url next\
+: Qt.res\
+olvedUrl(\x22images\
+/next.png\x22)\x0a \
+readonly propert\
+y url qtLogo: \
+ Qt.resolvedU\
+rl(\x22images/qt-lo\
+go.png\x22)\x0a rea\
+donly property u\
+rl sliderHandle:\
+ Qt.resolvedUrl(\
+\x22images/slider_h\
+andle.png\x22)\x0a \
+readonly propert\
+y url tab: \
+ Qt.resolvedU\
+rl(\x22images/tab.p\
+ng\x22)\x0a}\x0a\
+\x00\x00\x05t\
+/\
+/ Copyright (C) \
+2017 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick 2.\
+12\x0aimport QtQuic\
+k.Window 2.1\x0a\x0aIt\
+em {\x0a id: con\
+tainer\x0a\x0a prop\
+erty alias text:\
+ buttonLabel.tex\
+t\x0a property a\
+lias label: butt\
+onLabel\x0a sign\
+al clicked\x0a p\
+roperty alias co\
+ntainsMouse: hov\
+erHandler.hovere\
+d\x0a property a\
+lias pressed: ta\
+pHandler.pressed\
+\x0a implicitHei\
+ght: Math.max(Sc\
+reen.pixelDensit\
+y * 7, buttonLab\
+el.implicitHeigh\
+t * 1.2)\x0a imp\
+licitWidth: Math\
+.max(Screen.pixe\
+lDensity * 11, b\
+uttonLabel.impli\
+citWidth * 1.3)\x0a\
+ height: impl\
+icitHeight\x0a w\
+idth: implicitWi\
+dth\x0a\x0a SystemP\
+alette { id: pal\
+ette }\x0a\x0a Rect\
+angle {\x0a \
+id: frame\x0a \
+ anchors.fill: \
+parent\x0a c\
+olor: palette.bu\
+tton\x0a gra\
+dient: Gradient \
+{\x0a Gr\
+adientStop { pos\
+ition: 0.0; colo\
+r: tapHandler.pr\
+essed ? Qt.darke\
+r(palette.button\
+, 1.3) : palette\
+.button }\x0a \
+ GradientSt\
+op { position: 1\
+.0; color: Qt.da\
+rker(palette.but\
+ton, 1.3) }\x0a \
+ }\x0a an\
+tialiasing: true\
+\x0a radius:\
+ height / 6\x0a \
+ border.color\
+: Qt.darker(pale\
+tte.button, 1.5)\
+\x0a border.\
+width: 1\x0a }\x0a\x0a\
+ TapHandler {\
+\x0a id: tap\
+Handler\x0a \
+onTapped: contai\
+ner.clicked();\x0a \
+ }\x0a HoverHa\
+ndler {\x0a \
+id: hoverHandler\
+\x0a }\x0a\x0a Text\
+ {\x0a id: b\
+uttonLabel\x0a \
+ text: contain\
+er.text\x0a \
+color: palette.b\
+uttonText\x0a \
+ anchors.center\
+In: parent\x0a }\
+\x0a}\x0a\
+\x00\x00\x03)\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00@\x00\x00\x00@\x08\x06\x00\x00\x00\xaaiq\xde\
+\x00\x00\x02\xf0IDATx\xda\xe5\x9b_h\xcda\
+\x18\xc7?\x9bm1\xab\x91\xc2\xd0Y+5\xbb`h\
+\xc9\x85\x0b7HJ\x93H))\xe5\xc2\xcd\xb0\x91R\
+\xdc(7\xbbP\xae\x88\x5cXI[v%\xc9\x9fb\
+.\xfc\xbd\xc0(\xffN\xc8\xc6\xd9p16\x8c9.\
+~?u\xac\xe3\x9c\xf3}\xb7\xc3\xfb{\xce\xb7\xde\xab\
+\xd3\xef=\xef\xe7y\xdf\xe7\xf7{\xde\xe7}^\xb0\xa7\
+\x12\xa0\x1aX\x03\xb4\x02W\x8080\x00\x0c\x03\x83@\
+w\xf8\xbb9m\x04n\x03\x9f\x80d\x96v\xc3\x12x\
+\x05p1\x07\xe8\xd4\xb6\xc2\x0a|5\xf0Z\x84?\x0f\
+L\xb0\x00_\x16\xfa\xb6\x02\xff\xde\xca\xccO\x04\xee\x89\
+\xf0\x1f\x81\x1a+\x068)\xc2'\x81uV\xe0\x0f8\
+\xc0\xef\xb6\x02\xbf\x0a\xf8.\xc2\xb7\x01\xc5\x16\xe0k\x80\
+!\x11\xfe!Pj\x01~*\xd0#\xc2\xf7\x02\x95V\
+\x96~\x9b\x08?b)\xd89\xec\xf0\xd2\xdbb\xe9\xa5\
+\xa7\xc2\x1f\xb3\x14\xec$D\xf8\xa7\xe1s&\xd4-\xc2\
+\x0f\x02\xe5\x85\xea\xf7?\x81\x95V\xe0\xeb\x1d\xfc\xbe\xd5\
+\x0a\xfcl\xe0\xb3\x08\x7f\xd6\x0a|)pI\x84\xef\x01\
+\xa6Y1@\x93\x83\xdf7X\x81_V\xc8\xdb\xdb\x0a\
+\xe0\xb9\x83\xdf\x17Y1\xc0\x09\x11>\x8e!m\x10\xe1\
+\x07\x809V\xe0g\x02}\xa2\x01\xb6Y\x9a\xfd\x0e\x87\
+\xcc\x8e\x19\xed\x13\xe1\xef[\xda\xe4\xd4\x91\xdb\xf1Uj\
+rc\x91\xa5\xd9\xbf.\xce\xfe&K\xf0\x07E\xf8\xd3\
+\x96\xbe\xf7\x0b\xd0R\xda\x09`J!/\xfd\x98%\xf8\
+\xfd\x22\xfc^K\xf0\x0d\xc07\xb4\xc3\x0cS\xba\x8av\
+\x82;\xd9\x12\xfc\x1e\xf1{\xdf\xe8\xcb\xc0g\x01k\x09\
+\x8e\xa1\xaf\x01G\x80*\xb1\x8fZ\xd1\xef;|\x00/\
+&8X\xe8O3\xc0w\xe2\xf2\xbc \xc0?\xc2\x83\
+\x13\xdc%\xc0\x87,\x03=\x9ac_\x8d\x02\xfcW\x1f\
+B\xdd\x96\xd0\x07\xb3\x0d\xf6Y\x98\xc1\xc9\xa4\x18AM\
+^\xae\x068\xf4\xbf\xe1\xeb\xc5\x08m^\x16\x17:'\
+\xf4u\xc7\x07\xbfW\x8f\x9e\x8fg\xe8k\xb9\x98\xdd\xf1\
+\xa2h\xe9.zF6\x9d\x8a\xc4\xa5\xdf\xe2\xcb'\xaf\
+\xdd\xc1\x00;\xd2\xf4\xa3$7;}\x0aV\x9a\x1c\x0c\
+p\x8b?ko\xe6\x0a\xef\x91^`\xbaO\x06X\xec\
+`\x80a`~J\x1f\x0f\x84g\xb7\xfa\x16\xaeV\x85\
+A\x8ej\x84\xc7\x0e.\xe4eb\xb3$\x5c\xd2\xc9<\
+\xb77\xc0$\x9f\xc0\x7f\x87\x9e?\x80\xcb\xff\xe0\xff\x9a\
+\x81/\xbe\xee\xdaj\xf3<\xfb\xedQ\xd8\xba\xbe\xca\x13\
+\xfc\x8b\x1c\xc2g/\xb4+O\x06\x88LZ;\x86^\
+\x88\x9c\xad\x9d\x89R\xf6\xa6\x1c\xfd\x12B\xa6\xf6\xd6w\
+\xe0\xd1\x09\x88!\xa0k\x1c\xfb\xdf\x19\xc5\x1c\xde\xc2q\
+\x9a\xfd.\x22\xac'c\x84\xef'\xe2\x15\x9b\xab\xc7\x00\
+?\x02l&\xe2*\x03^:\x1a\xe0f\x94@\xffv\
+yp\x04\x98AP\xba\xa6\xaa.\xdc)F^\x95\xe8\
+%\xab\xdb1\xa6\xa5\x02\xfc)\x8c\xdc\xcc\x1a\xad\xf5a\
+\xce0\x1efr\xfa\x08\xae\x9f&\x08.'t:\xba\
+\x8a\x17\xfa\x05\xc1\xf2\xa6\x01\x10\xe5*G\x00\x00\x00\x00\
+IEND\xaeB`\x82\
+\x00\x00\x015\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x10\x00\x00\x00\x1f\x08\x00\x00\x00\x00\xcb\xce\x12h\
+\x00\x00\x00\xfcIDAT(\x15\x05\xc1AjTa\
+\x10\x06\xc0\xea\x9e\x7fF\x12\x17\x22(\xe8\x01t#\xf1\
+\x12\x9e\xdc\xadk\x97\x0a\x0aB\x5cj\x22$\x99y\xaf\
+?\xabj\xeb\xbbo\x7f\x1f\x8e[e\xbd}\xf5&U\
+\xf3\xfd\xc7\xcd\xcbc\x0a\xbf\x7f\x9d>V\xfd\xf9\xf2i\
+{\x08\xb8:|}\xfe\xae\x7f~\xd8\xee\x0a\xd8\xee\xdf\
+\xdfN\xff{vn@\xf4<\xae\xfb\xeb\xc7\x9e\x80\xbd\
+\xfa\xf2\xd4\xe7\x95\x00Fm\xb3ZK\x81\xe9\x9a\xee\xde\
+;\x80JJ\xc7\x000\x95\x85t\x80\x99\xb2jT\x88\
+\xa8\xb2[\x95)AIfY\x22\x22\xe8\x12\x0bB)\
+\xfb!,\x12\x80$\x96\x1a*%\xe20\x16Q#J\
+\xd2m\x91\xda+\x85\xba\xecc\xc5t\x22\xe8\xde\x97%\
+\x00b\xc6\x22\x09P\x11-\x00Bi\x00D\xd3I\x12\
+\x01I,\x92\x10\xa8\xa2\x8bD\x00t\x0e\xba\x04\xb2\x1d\
+j\xfa\xf0\x94\xcbX\xe0x\xc9iM\x9f\xe6\x9cKc\
+j{\xfd\xb9\xce\xe7\xdb\xab\x9a\x14\xb6\xd3\x8b\xe3\xf1?\
+V\x8e\x9e\xad\xee\x91\x1e\xc8\x00\x00\x00\x00IEND\
+\xaeB`\x82\
+\x00\x00\x066\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x0d\x00\x00\x00\x17\x08\x06\x00\x00\x00\xd0\xa6\xc5\x81\
+\x00\x00\x00\x19tEXtSoftware\
+\x00Adobe ImageRead\
+yq\xc9e<\x00\x00\x03$iTXtXML\
+:com.adobe.xmp\x00\x00\
+\x00\x00\x00<?xpacket beg\
+in=\x22\xef\xbb\xbf\x22 id=\x22W5M\
+0MpCehiHzreSzNTc\
+zkc9d\x22?> <x:xmpm\
+eta xmlns:x=\x22ado\
+be:ns:meta/\x22 x:x\
+mptk=\x22Adobe XMP \
+Core 5.3-c011 66\
+.145661, 2012/02\
+/06-14:56:27 \
+ \x22> <rdf:RDF \
+xmlns:rdf=\x22http:\
+//www.w3.org/199\
+9/02/22-rdf-synt\
+ax-ns#\x22> <rdf:De\
+scription rdf:ab\
+out=\x22\x22 xmlns:xmp\
+=\x22http://ns.adob\
+e.com/xap/1.0/\x22 \
+xmlns:xmpMM=\x22htt\
+p://ns.adobe.com\
+/xap/1.0/mm/\x22 xm\
+lns:stRef=\x22http:\
+//ns.adobe.com/x\
+ap/1.0/sType/Res\
+ourceRef#\x22 xmp:C\
+reatorTool=\x22Adob\
+e Photoshop CS6 \
+(Macintosh)\x22 xmp\
+MM:InstanceID=\x22x\
+mp.iid:DCE827695\
+74811E2B0EE92BEE\
+27047DB\x22 xmpMM:D\
+ocumentID=\x22xmp.d\
+id:DCE8276A57481\
+1E2B0EE92BEE2704\
+7DB\x22> <xmpMM:Der\
+ivedFrom stRef:i\
+nstanceID=\x22xmp.i\
+id:DCE8276757481\
+1E2B0EE92BEE2704\
+7DB\x22 stRef:docum\
+entID=\x22xmp.did:D\
+CE82768574811E2B\
+0EE92BEE27047DB\x22\
+/> </rdf:Descrip\
+tion> </rdf:RDF>\
+ </x:xmpmeta> <?\
+xpacket end=\x22r\x22?\
+>\x97\xa0=\xd8\x00\x00\x02\xa8IDATx\xda\x8c\
+\x94_HSQ\x1c\xc7\xcf\xbd\xbb\xd7;\xb7\xdd\xddQ\
+\x90\xbe\x0cb\x9b\x93\xd4\xf5\x10\xc1\x0a\xf4\xc5)\xd8\x1f\
+)Fd\xd4C\xeaK\xe4CB\xf6\x98\xb4\xb5\xad=\
+\xc8\xe8\xc9\xf5\x1e\xf4\x92\xd2\x96E\xeb!Y\x96\xc5\x94\
+\xc2\x94\x05\xb2\xf9\x10H\xed\xa1\x8767\xc1\xfd\xf3\xf6\
+=\xd7ML\x97z\xe0\xcb\xdd\xef\xdc}8\xbf\xf3\xfd\
+\x9es\x19Y\x96\xc9A\xc3j\xb5\x0ep\x1c\xf7\x98\xc8\
+r\xa1P,\xde`\x0e\x82\xdaZ[\xefiu\xba1\
+\xb5 \x90r\xb9Lr\xeb\xeb1n?\xc0f\xb3\xb9\
+\x0c\x06\xc3\x03Q\xaf'u<O\x0a\x85\x02\x11Eq\
+\xb5&d6\x99\x18\xadV;\x06`D\x02\xa0\xd1h\
+\x94\xf9c\x0d\x0d?\xfc~\xff\xcc\x1e\xc8l6\xabt\
+:\xdd\xb8$I\xb7 R__O\x18\x86!\x8d\x8d\
+\x8d\x09\xaf\xcf7\xb1g%\xcb\x16\xf0\xd4 I\xd7\xf5\
+U\x00\xf3F\xa3\xf1\xbb\xc7\xeb\x0d\xa1^A\xf9v\x1b\
+\xb2X,u:Q\x9c\x04\xd0\xabGK\xea\x0a`2\
+\x99\xbe=\xf4x\xa6x\x9e_F9\x09\x15\xb9\x0a\xa0\
+\xc1\xb2/\x01t)\x80ZM\xa8\xa7\xd6\xe6\xe6y\xb7\
+\xdb\x1daY6\x8e2\x04\x95\xe9\xff\x19\xb4$\x01x\
+-\x19\x0c\xedzQ\xdc\x06N\xdal\xb3\xf7GG\xa7\
+\xf1s\x01z\x05mV\xbb\xe2\x90\xc1sl\xb8]\xaa\
+\xae\x80\xdc\xce\xd8\xed\xd3wGFf\xf1~\x1e\x8a@\
+\xff\x84\xc9\xc1\xdaN\xecE\xb1\x95\xba\x84\xf6V\xef\x0c\
+\x0f\x7f\xc2;\x0a\xbd\xab\x15\x09\xdb\xda\xd2\xf2\x91\xe78\
+\x82\xbe\x95\x89T*e\xbc\xd6\xd7w\x16'\xe1\xfd\xff\
+Bg\xc7\x83\xc1\x0f8[\x0b\xa5RI\x99P\xa9T\
+$\x9dNw\xd7\x09\xc2\x0b\xeahM\x08V~y\xe4\
+\xf7O\xc1\xa99\x0a\xa2&h\x99`\x8f\xbd0(\xd2\
+\x04gwC\xf4\xc0\xd2\xbe.B\xa7|^o\xe7\xe2\
+\xd2R\x07\xcd'\x9f\xcf\x93\xcc\xda\x1a\xc9\xa4\xd3\x9f\xb3\
+\xb9\xdc\xf9d2\x99\xd9\x09)O\xa8\x07\xb2\x07\x02\x81\
+\xf6\xb9X\xccA\xf7\xb8\xb1\xb1A\xd6\x00\xa63\x99\xaf\
+\xb9\x5c\xee\x5c\x22\x91\xf8\xbd\x13\xaa\x0e\x07\xd4\xf1$\x18\
+<\x1d\x8dF/( V\xccf\xb3t\x9fq<{\
+\x00\xfe\xdc}`i\x98\xf9\xdbCC4\xb3\xe2\x9bH\
+\xe4\x12\xee\x11\xc3l\xb5\xd2\x06\xcd\xc04G\xad\xabA\
+\xf3\xc9\x0f\x0c\x0eR\xb0\x10\x0e\x87\xaf\x08\x82\xc0\xd2\x0c\
+\xd1\x93yS\x96C*\x97\xcbU\xcb\xd5_\xd0\x1f\x5c\
+\xc2\xa3\x88 \x15\x8f\xc7O\xe0\xc9\x22}\xb2Y.\x1f\
+a\xf7\xb9\xb8\x8b\xd0\x84\xd3\xe9\x5c\xbe\xd9\xdf\xff\x0c\xdf\
+\x88\x0c\x96+uuw\x87\x99C|X\x9a\xa0\xab\x10\
+_\xa9K\x87\x81\xe88\x0e]\x86\xb4\xf4<\xfe\x15`\
+\x00\x07\x7f\xeb\x18\x9af\x83_\x00\x00\x00\x00IEN\
+D\xaeB`\x82\
+\x00\x00\x05[\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x12\x00\x00\x00\x1f\x08\x06\x00\x00\x00\xeaP\x9d\x89\
+\x00\x00\x00\x19tEXtSoftware\
+\x00Adobe ImageRead\
+yq\xc9e<\x00\x00\x03$iTXtXML\
+:com.adobe.xmp\x00\x00\
+\x00\x00\x00<?xpacket beg\
+in=\x22\xef\xbb\xbf\x22 id=\x22W5M\
+0MpCehiHzreSzNTc\
+zkc9d\x22?> <x:xmpm\
+eta xmlns:x=\x22ado\
+be:ns:meta/\x22 x:x\
+mptk=\x22Adobe XMP \
+Core 5.3-c011 66\
+.145661, 2012/02\
+/06-14:56:27 \
+ \x22> <rdf:RDF \
+xmlns:rdf=\x22http:\
+//www.w3.org/199\
+9/02/22-rdf-synt\
+ax-ns#\x22> <rdf:De\
+scription rdf:ab\
+out=\x22\x22 xmlns:xmp\
+=\x22http://ns.adob\
+e.com/xap/1.0/\x22 \
+xmlns:xmpMM=\x22htt\
+p://ns.adobe.com\
+/xap/1.0/mm/\x22 xm\
+lns:stRef=\x22http:\
+//ns.adobe.com/x\
+ap/1.0/sType/Res\
+ourceRef#\x22 xmp:C\
+reatorTool=\x22Adob\
+e Photoshop CS6 \
+(Macintosh)\x22 xmp\
+MM:InstanceID=\x22x\
+mp.iid:DCE827655\
+74811E2B0EE92BEE\
+27047DB\x22 xmpMM:D\
+ocumentID=\x22xmp.d\
+id:DCE8276657481\
+1E2B0EE92BEE2704\
+7DB\x22> <xmpMM:Der\
+ivedFrom stRef:i\
+nstanceID=\x22xmp.i\
+id:DCE8276357481\
+1E2B0EE92BEE2704\
+7DB\x22 stRef:docum\
+entID=\x22xmp.did:D\
+CE82764574811E2B\
+0EE92BEE27047DB\x22\
+/> </rdf:Descrip\
+tion> </rdf:RDF>\
+ </x:xmpmeta> <?\
+xpacket end=\x22r\x22?\
+>\xd9\x0c\xdf\xc0\x00\x00\x01\xcdIDATx\xda\xac\
+\x95;K\x03A\x14\x857\x994\xdaF1>@\xc5\
+\x88A\x8c,*\x16b#XZ\x08\x06\x04\x0b\xa3\xad\
+\x85\x9d`\x13\x0b\x1bm,5\x8d\x88\x89\xd8(B4\
+>@B\x88\x16\x16\x22b:\xff\x86 X\x04]\xcf\
+\x95+\x84e\xe6\xee\xaef\xe0\xec\xcc\xee\x1c\xbey\xec\
+\xbd3\x91\xa5t\xba\xd9\xb2\xac\x03h\x0ez\x832\x87\
+\xb9\x5c\xd6\x0aX\xc2\xd0\x064\x0fE\xa0(\xb4\x07\xf8\
+\xfa_@\xe3\x9a\xef[\x80e\x82\x82\x1e\x0d}\x9b\x80\
+m\xfb\x05)\xdb\xb6\x1fPO@\xbd\x9a\xfeI\xf47\
+\xbdT\xab%/P\x88\x1e\xbc\xe1\x97\xd0\x94\xc1\xb7\x03\
+\xad\xe1'8\xc6\x19\xd1\x03#\xd60\xf2\xa903\xfa\
+\xde\x06\xcf5\xbcf\x90\x0b6\x0c\x0dh\xbcc\x12L\
+\xd5\xbf0\xec\x0cM[\x80\xb5\xc3s\x03\xafc\x041\
+\xec\xd3\x036\x0a\xc5\xe19\xaf\x87)\xddz\xeb`q\
+(\xa9\xb1$\xdd0e\xfa\x0b\x0c+x\xc0\xfa\xe1)\
+\x927\xe4\x15\x1f\x08\x0d\x1a,\x0f-\x18,E(\xa5\
+\xbc@4uZ\x02\x9a1\xde\x1fw\xa1}\x8c)?\
+\xe1\xcf\xb0+4;\xa1\x11\xdd2\xc3\x01\xf22\xca1\
+\xa6+\xef!?\x04\xecS+\xaa24d\xb0\xac\xa8\
+\x06@V\x91\x83\xbb\xca\x03\xd2\x81\xaa$\xcd\x84 b\
+\x1c\x01\xd2\x85\xea\x0eJ\x08\x90\xac\x18\xd9\x0c\xa9@}\
+\x9a\xee/h\x19\x90}1\xd7\x00\xe9\xe1=1A\x16\
+\x019\x12\xb3\x1f\x10J\x87{\xa8[\x80\x1c\x8b\xe7\x11\
+C*\x1ct\xeeR\xa3\x9b\x06\x90\x13\xf1\x84\x04$\xc1\
+\xcb1AR\x80\x14\xc4\xc3\x1f\x90A^NL\x80\x5c\
+x\xc5\x1b]\x8a\xb4q-\x9a\xbe\x0fh\x16\x90[?\
+\xd1\x1f1$!Af\x00)\x07\xb9 \x9f\xff\x0b\xf9\
+\x05\xd1\x81\xf5\xc4\xef\xaf\xd0tP\xc8\xcf\x05\xe98\x8e\
+\xd5\x88\xf2-\xc0\x00\xaa\xfa\xae\x1fG|9m\x00\x00\
+\x00\x00IEND\xaeB`\x82\
+\x00\x00\x03w\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x1b\x00\x00\x00\x1c\x08\x06\x00\x00\x00\x90\xd1\xc4\xed\
+\x00\x00\x00\x09pHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\
+\x01\x00\x9a\x9c\x18\x00\x00\x03)IDATH\x0d\xbd\
+V=LZQ\x14\x06\xa4\xd1PE\x03\x14\x08\x83\xc8\
+fL\xd3\x10\x93\x06\x97\xa6\xdd\xbb3th\x8c\xa1\x1b\
+\x9d\x18\xbauaj\x22k'6\x17\x87v\xec\xd6\xa5\
+\x1b.\x84\x04\x02&\x18\x15\x02\x89\xd2\x8a\xfc$\xb6D\
+y\xaf\xdfw\xfb\xde\xf5\xf9\xfa\xe4\xa76\x9e\xe4\xe4\xde\
+\xc7\xbd\xdf\xf9\xee\xf9\xdey\xe7bWU\xd5v_\xe6\
+\xb8/\x22\xf28'%\xb3\xc3\xb4\xbd\xfah\x84\x0ay\
+\xa0\xd2H\x99\xecc\xd6m\x1a\x09\x09\x8cn$\xe2\x9c\
+$\xd2o#\x1dI\x06\x22\xcaL\x12\xf3\xa8\x13K\x02\
+\xecQ4B1\x82\x90\xe3\x0d\xb3\x94\xd1\x90\x0dI\xe8\
+3\xf0\xd9\x85\x85\x85@\x22\x91x\xbe\xbc\xbc\xbc\xb6\xb8\
+\xb8\xf8\xa8\xdb\xed~\xaf\xd7\xeb\xe5l6\xfb\xad\xdf\xef\
+\x9fb\xcf\x00>\x84+\x9a\xeaL\xf2ZZ\xce\xcd\x8e\
+\xcd$\xe0Af\xe1\x0f\xa3\xd1\xe8\xd3\x9d\x9d\x9dO\xd5\
+j\xf5\xe7\xd9\xd9\x99z~~\xae\xb6\xdbm1\xf2\x99\
+\xbfs=\x16\x8b=\xe1~\x0dG\xbc\xc3\x18{\x1c\xd1\
+<2y]\xa9T\xba$h6\x9b\xea\xe1\xe1!\x83\
+K\xe73\x7f\xe7z\xa9T\xea\xc6\xe3\xf17 \x99\xb7\
+\x22\xbc\xf1\xce4\xf9t\xd9\x1e\x00\xf8j{{\xfb#\
+\xe4s\x22\x03q0\x04\xb14\xca\xe6\xf7\xfbm \xbd\
+L\xa7\xd3\x09H\xfb\x19\x1b/\xe1BVd\xa8\x9a\xc9\
+t\x22'\xa4{\xbc\xbb\xbb\xfb5\x14\x0a\xb9OO\xf9\
+:&3\x9f\xcfg;99\xe9mnn>\xdb\xdb\
+\xdb\xab\x02u\x05\x1f\x82Kapa\x86\xa2`\xa5\xcd\
+\xa6R\xa9w\x81@\xc0\xddj\xb5\xb4\x1d\x93\x0dT \
+\x18\x0c\xba\x93\xc9\xe4{\xc6\x81\x8b\xcae|I\xa6\x85\
+\x12e\xce\xaa\xdb\xd8\xd8xyqq1R:+z\
+\x16\x04q\xc43\x0e\xf6\x90\x83q\xc5\x84#M\x9c\x80\
+\xe3\xd6\xd6\xd6\x0b\x8f\xc737\x18\xb0\x92\xa77\xe2\x88\
+g\x1c\xa0e\x5csf\x8cl\x8fD\x22\xab\x0e\x87\xc3\
+6\x1c\xf2\xddNo\xc4\x11\x1f\x0e\x87\xd7\x80&\x990\
+K2\xb7\xdb\xed\xa7\x1cw1\xe2\x97\x96\x96|\x881\
+\x92L\xed\xf5z-\x96\xf2]\x8c\xf8N\xa7\xf3\x031\
+\xe4\xa9\xad2S\x8f\x8e\x8e\xf6\x15E\xb1\xcd\xcc\xb0K\
+Mo\xc4\x11_\xab\xd5\xca@K2\xf9\x9d\xb14\xb1\
+\xc0\xe8NTQ8\x9f\xcf\x17\x5c.\xd7\x1c+kZ\
+\x03\x8e\x15\xf9k}}=\x8a\x9eY\x03^|k\xe6\
+\xccx\x0a\x85M5\x97\xcb}!hZ9\xb9\x9f8\
+\xe2\xb5\xe6\xac\xdf\x06\xd7\xa5\x8f\x17J\x22\xdd\x07\x99L\
+\xe6\x03;\x81\xd7\xeb\x9d*1\xb6\xacF\xa3\xd1'\x1e\
+@~;\x22&\xe3[f\x86\x0d\xc3B\xa1P\x06\xe0\
+-Nw\x85N26Cf\xc4V\x85\xa2\xb8Bo\
+L\x11\xcf8p\x99\xd9\xd8\xae\xcf.^,\x16{\x93\
+t\xfd\x83\x83\x83\x0eo\x09\x10Xv\xfd\xbf\xc8\xfe\xa8\
+\xf9o\xf7\x19\xef=\x10\xddz\x9f\xc9j\xc4&i\x90\
+\x84\x95I\xa7\xcc\xf4\x1b7\xf5\xca\xca\xca*\xfb\x1e\x0b\
+\xe0\xf8\xf8x\xdf\xea\xa6\x06F\xc8\xc7w\x85\xb90K\
+2\xb9\xf8\x9f\xff\x83\x8c$#\xa9!K=[\x8ef\
+\xd3\xabXV\x9ey\x03\x9f\xc7\x92\xe9 \x8dT`\xf4\
+\xdf\x0c\xa3\x90\xca(\x99aMN'&\x93\x88;L\
+~\x03}U80w\xf4\xee\xee\x00\x00\x00\x00IE\
+ND\xaeB`\x82\
+\x00\x00\x18@\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x01\x00\x00\x00\x01\x00\x08\x06\x00\x00\x00\x5cr\xa8f\
+\x00\x00\x00\x19tEXtSoftware\
+\x00Adobe ImageRead\
+yq\xc9e<\x00\x00\x03*iTXtXML\
+:com.adobe.xmp\x00\x00\
+\x00\x00\x00<?xpacket beg\
+in=\x22\xef\xbb\xbf\x22 id=\x22W5M\
+0MpCehiHzreSzNTc\
+zkc9d\x22?> <x:xmpm\
+eta xmlns:x=\x22ado\
+be:ns:meta/\x22 x:x\
+mptk=\x22Adobe XMP \
+Core 5.6-c132 79\
+.159284, 2016/04\
+/19-13:13:40 \
+ \x22> <rdf:RDF \
+xmlns:rdf=\x22http:\
+//www.w3.org/199\
+9/02/22-rdf-synt\
+ax-ns#\x22> <rdf:De\
+scription rdf:ab\
+out=\x22\x22 xmlns:xmp\
+=\x22http://ns.adob\
+e.com/xap/1.0/\x22 \
+xmlns:xmpMM=\x22htt\
+p://ns.adobe.com\
+/xap/1.0/mm/\x22 xm\
+lns:stRef=\x22http:\
+//ns.adobe.com/x\
+ap/1.0/sType/Res\
+ourceRef#\x22 xmp:C\
+reatorTool=\x22Adob\
+e Photoshop CC 2\
+015.5 (Macintosh\
+)\x22 xmpMM:Instanc\
+eID=\x22xmp.iid:EF4\
+E1F5F50C611E689D\
+8B84085AD92F4\x22 x\
+mpMM:DocumentID=\
+\x22xmp.did:EF4E1F6\
+050C611E689D8B84\
+085AD92F4\x22> <xmp\
+MM:DerivedFrom s\
+tRef:instanceID=\
+\x22xmp.iid:EF4E1F5\
+D50C611E689D8B84\
+085AD92F4\x22 stRef\
+:documentID=\x22xmp\
+.did:EF4E1F5E50C\
+611E689D8B84085A\
+D92F4\x22/> </rdf:D\
+escription> </rd\
+f:RDF> </x:xmpme\
+ta> <?xpacket en\
+d=\x22r\x22?>j\x12\xd3\xd3\x00\x00\x14\xacI\
+DATx\xda\xec\x9d\x09\x98V\xd5y\x80\xbf\x7f\xf6\
+}\x83\x19\x96a\x97m\x10A\xa1\xb8\x00\x06p\xc1h\
+]\xaaF\xf3XS5\x1a\xd7\xb4Q\xa3\xb1\xb1\xc6G\
+\xd3j%mS\x97<\xd5\x94j\x88q\x97 (\x06\
+\x97\x22ZqEPQ\x04\x14\x10d\x86\xd9g\x98}\
+\x9f\xf9{\xbf\x9bj\x091d\x06\xbe\x7f\xe6.\xef;\
+\xcf\xff\x8c\xe3\xa3\xe7\xbf\xf7\xdc\xfb\xbd\xf7\x9cs\xcf\xf9\
+N$\x1a\x8d\x0a\x00\x84\x938\xaa\x00\x00\x01\x00\x00\x02\
+\x00\x00\x04\x00\x00\x08\x00\x00\x10\x00\x00 \x00\x00@\x00\
+\x00\x80\x00\x00\x00\x01\x00\x00\x02\x00\x00\x04\x00\x00\x08\x00\
+\x00\x10\x00\x00 \x00\x00@\x00\x00\x80\x00\x00\x00\x01\x00\
+\x00\x02\x00\x00\x04\x00\x00\x08\x00\x00\x10\x00\x00 \x00\x00\
+@\x00\x00\x80\x00\x00\x00\x01\x00\x00\x02\x00\x00\x04\x00\x00\
+\x08\x00\x00\x10\x00\x00 \x00\x00@\x00\x00\x80\x00\x00\xe0\
+O\x13\xf1\xca\x81,\xd8p\xce\x11\xce\xaf5\xceg0\
+\x97\x05 D\x02 \xf8\x01B*\x00\x82\x1f \xa4\x02\
+ \xf8\x01B*\x00\x82\x1f \xa4\x02 \xf8\x01B*\
+\x00\x82\x1f \xa4\x02 \xf8\x01B*\x00\x82\x1f \xa4\
+\x02 \xf8\x01B*\x00\x82\x1f \xa4\x02 \xf8\x01B\
+*\x00\x82\x1f \xa4\x02 \xf8\x01B*\x00\x82\x1f \
+\xa4\x02 \xf8\x01B*\x00\x82\x1f \xa4\x02 \xf8\x01\
+B*\x00\x82\x1f \xa4\x02 \xf8\x01B*\x00'\xf8\
+\x8fq~\xbd\xec|\xb2\xa8F\x80\x10\x09\x80\xe0\x07\x08\
+\xa9\x00\x08~\x80\x90\x0a\x80\xe0\x07\x08\xa9\x00\x08~\x80\
+\x90\x0a\x80\xe0\x07\x08\xa9\x00\x08~\x80\x90\x0a\x80\xe0\x07\
+\x08\xa9\x00\x08~\x80\x90\x0a\x80\xe0\x07\x08\xa9\x00\x08~\
+\x80\x90\x0a\x80\xe0\x07\x08\xa9\x00\x08\xfe\xfe!#>\xfd\
+\xf7\x15\x1f\x89Hj\x5c\x8a\xb4t\xb7\xba\x7fwE\xbb\
+\xa4\xad\xa7\x9d\x0a\x82\xfe\x17\x00\xc1\x7f\xe8\xc4E\xe2d\
+d\xf2p\x19\x99R(\x85\xc9C\x9d\xcf0)H\x1a\
+$9\x09\xd9\x92\x97\x98+iq\xa9\x92\x16\x9fz\xc0\
+2\xa2\xceOsw\x8b4t5J]W\xbdTw\
+\xee\x95\xaa\x8ej\xd9\xd3^.\xa5\xce\xe7\xf3\xd6/\x9c\
+\x7fWKe\x83\x9d\x00\x08\xfe\x83#3>C\xa6g\
+N\x91\xa9\xe9ErDF\x91\x8cK\x1d-\xc9qI\
+1\xff\xde\xba\xae\x06\xf9\xace\x87lj\xda\x22\x1b\x9b\
+6\xcb\x96\xe6\xcf\x9c\xd6C7\x17\x04\x0eZ\x00\xf5\x04\
+\x7f\xef\x18\xe4<\xc9\xe7\xe7\xce\x919\xd9G\xcb4'\
+\xe8\xf5\xa9?\xd0h\x8b\xe1\xdd\x86\xf7\xe5\xcd\xbau\xf2\
+f\xfd:\xe9\xe8\xe9\xe4BA\x9f\x04\x10\xa5\x1a\x0e\xd4\
+G\x8a\xc8q\xd9\x7f!g\xe6/\x94YYG\xb9\x7f\
+{\x15\x1dOxe\xefZYQ\xf5\x82\xecl\xdd\xcd\
+\xc5\x03\x04p\xb0\xc4G\xe2ea\xde<\xb9`\xe89\
+2\xc2\xe9\xcf\xfb\x8d\x0d\x8d\x1f\xc9\x92\xd2'es\xf3\
+\xa7\x5cL@\x00}av\xf6,\xb9j\xc4\xc5\xbe\x0c\
+\xfc\xfdy\xa7~\x83\xdc_\xb2DJ\xda\xcb\xb8\xb0\x80\
+\x00\x0e\xc4\xe0\xc4<\xb9~\xd4\x95n\x93?HtF\
+;\xe5\xf1\xf2\xe5\xf2X\xf9o=;`\xa8oH\x1e\
+*\xba\xfb\x90\xcb\xf9m\xe5\xf3\xb2\xcc\xf9@\xefH\xa0\
+\x0a~\xcf\xdc\x9cc\xe4G\xa3\xae\x91\xcc\x84\x8c\xc0\x9d\
+[b$Q.\x1ev\xbe\x1c\x9b=C\xee\xd8y\xb7\
+\xfbZ\xd1k\xc49?C\x92\xf2\x0f\xb9\x9c/\xe7Y\
+@o\xeb=\xecM \xe7\xe7{\xc3/\x94\x7f\x1cw\
+S \x83\x7f_&\xa5\x8d\x97\x07&\xff\x8b\xcc\xcc\x9c\
+\xc6\x9d\x0f\x08 !\x92 \xb7\x8f\xbbQ\xfez\xe89\
+\xa19g}B\xfel\xfc\xad\xb20o>w?\x84\
+W\x00\x1a\xfc?\x1d\xf7#9>\xe7\xd8\xf0]\xf4H\
+\x9c\xfcx\xcc\xdf\xc9\x99\xf9\xa7\x10\x01\x08 \x9c\xcd\xfe\
+[\xc6\x5c\x1b\xb8\xc1\xbe\xber\xed\xc8\xcbe^\xeel\
+\xa2\x00\x01\x84\x8b+\x0a\xff\x86\x1b\xff+\x11^'S\
+\xd2'\x12\x09\x08 \x1ch\x93\xff\xdbC\xce\xe2\xca\x7f\
+\xd5\x15\x8a\x97\xdb\xc6\xdd(\xd9\x09\xcc\x06G\x00\x01G\
+\xdf\xf3\xdf4\xfa\xfb\x5c\xf5\xfd\xc8O\x1c$7\x8e\xbe\
+\x9a\x8a\x08\xe3\x03 L'{\xc3\xa8\xab%=>m\
+@\xbe[\x17\xe9\x94uT\xb8K}\xdb{:\xa4=\
+\xda\xee\xfe\xd6\x15\x84\xe9qi\x92\xe4\xfc\xceK\xccq\
+\xdf\x85\x0f\xc4z\x03]\xe0tR\xde7du\xed\xeb\
+D\x05\x02\x08\x1e'\xe4\xce\x95c\xb2g\xf4\xcbwi\
+`\xbf\xdf\xf8\x91|\xdc\xb4E\xb6\xb6l\x93\x92\xb62\
+\xa9\xe9\xdc\xeb\xae\xf7\xff\xf3M\xf2\x04\x19\x96\x5c \xa3\
+SF8}\xf3I2#\xf3\x08\x99\x98vX\xbf\x1c\
+\xf75#.\x91\xb7\xeb\xd7\xbb+\x0c\x01\x01\x04\x86\xe4\
+\xb8d\xb9r\xc4E1\xff\x9e\xf7\x1a>\x94U5\xaf\
+\xc8;N\x10\xa9\x04\x0e\x06\xcd\x0cT\xdcV\xea~\xde\
+\xa8[\xf7U\xd7\xe5\xc4\xbc\xe3\xe5\xcc\xc1\xa78r\x18\
+\x12\xb3\xe3\xd7\xe4%\x17\x0d;_\x1e(\xf95\x91\x81\
+\x00\x82\xc39\x05\xa7\xb9\xfd\xdcX\xa1\xeb\xf0\x1f\xda\xf3\
+\xb8\xecj+\x8eI\xf9\x9a\x05\xe8\xa9\x8ag\xe5\xe9\x8a\
+\xe7dA\xee\x1c\xb9t\xf8\x052<yhL\xbe\xeb\
+\xec\xfc\xd3\xdc\xb9\xf4\x95\x1d\xd5DG\x08\x08\xfc \xa0\
+\xce|\xbb`\xc8\xd91\x0b\xcc\xbf\xdf\xfeOr\xeb\x8e\
+\x9f\xc5,\xf8\xf7E\xbb\x10k\xf6\xbe!\xdf\xdd|\x9d\
+<R\xb6\xb4W]\x8a>?\x11\x22\xf1r\xe1\xd0s\
+\x89\x0c\x04\x10\x0ct\xb6[,\x16\x88\xe8z\xfb\xcb\xb6\
+\x5c\xef6\xfb\xfb\x1b]\xdd\xb7\xa4\xecI\xb9a\xdbm\
+\xd2\xd8\xd5d^\xfe\xa9\x83N\x94AN\xb7\x03\x10\x80\
+\xbf\xfb7\x91\x04\xb7Ik\xcd+\xb5k\xe5\xe6\xedw\
+\xc4$\xf8\xfa\xc2\x87\x8d\x9f\xc8\xf7?\xbd\xd9<Q\xa8\
+\xb6\x02\xce\xce?\x95\xe8@\x00\xfefA\xeel7\x8f\
+\x9f%:J~\xd7\x17\xf7yf]}I{\xa9\xdc\
+\xb8\xedv\xf3\x91\xfb\xd3\x07\x9f\xec.#\x06\x04\xe0[\
+N\x1b|\x92iy:2\xaf\xeb\xe9{\xa2=\x9e:\
+\xcf\xddm{\xe4\xce]\xf7\x98\x96\x99\x95\x90)ss\
+\x8e&B\x10\x80?\xd1t^\xd33\x0e7+O\x83\
+\xfe\x8e]wKkO\x9b'\xcfWS\x7f=[\xf5\
+\xa2\xf9X\x00 \x00\x7f6\xff\xf3\xe6\x9a\x96\xb7\xbcj\
+\x95lk\xf9\xdc\xd3\xe7\xfc`\xe9c\xb2\xb7\xb3\xce\xac\
+\xbc\x99Y\xd3\xdc\xb9\x01\x80\x00|\xc7\xfc\x1c\xbb\xd5~\
+\xbae\xd7\xa3\xe5\xcb<\x7f\xce:\x0e\xb0\xb4r\xa5Y\
+y:%9\x8c\xf9\x12\x10@\x00\x9a\xffcSG\x99\
+>\xfd\xeb\xbb\x1a|q\xee\xda\x0d\xd0\xf5\x06V\xcc\xc9\
+\x99E\x94 \x00\x7fqL\xf6L\xb3\xb2\xba\xa3\xdd\xf2\
+L\xe5*\xdf\x9c\xbb\x8eQ\xac0\x1c\x0b8*s\xaa\
+;\x95\x1a\x82I \xa7\x02\x1fk(\x00\xddv\xab\xc6\
+g\x1br\xbeT\xfb\xaa\x5c4\xec<\x93\xb2\xf4U\xa0\
+.H\xd2\xd7\x9f}A\x93\x8c\x14\xf5!\xd1\x88\xd5\xbe\
+\x8a\xfa\xbd\xe7\x16\x9cn^\xa7-N\xf7\xea\x85\x9a5\
+\x08\xc0\xf3'\x14I\x90\xa9\xe9\x93\xcd\xca{\xd1\x87\x17\
+\xbd\xac\xbd\xc2]\x89\xa8\x9b\x96Z\xa0oS\xfa*\x00\
+\xddFMS\x91\xf77\xb3\xb2\x8et?\xd6TtT\
+\x05R\x00\x81\xeb\x02\x14\xa5O0{\x9a4u7\xbb\
+\xaf\xd7\xfc\x88\xee\x11h\xc5\x91\x99\x87\x0b0\x06\xe0\x0b\
+\xa6eL1+k}\xc3F\xdfn\xbdm)\xae\xf1\
+\xa9c%\x85q\x00\x04\xe0\x97\x16\x80\x15\xeb\x1a>\xf0\
+m=\xe8r^\x9d!hr\x93D\xe2dB\xda8\
+\xa2\x05\x01x\x9f\xc9iv\x02\x18\x88\x95~\x96X\x1e\
+\x7f\x11\x99\x83\x11\x80\xd7\xd1\x85?\x9aW\xcf\x02\xdd?\
+\xcfo\xa3\xff\xfb\xb3\xa9y\xabYY\x87\xa5\x8e!Z\
+\x10\x80\xb7\xb1\x9c\xfc\xf3i\xcbv\xdf\xd7\xc7\xd6\xe6m\
+fe\x8d3\xac[@\x00\xb1\x11@\xca(\xc3\xe0\xf1\
+\xbf\x00\xf4\xd5\x95\xd5\x0c\xc6\xd1)#%>\x12O\xc4\
+ \x00\xef2*e\x04-\x80\xfd\xf8\xcch\x01\x93&\
+\x09\xb1\xd8\xbe\x1b\x10@\xcc(L\x1efV\xd6\x17m\
+%\x81\xa8\x93\xdd\x86\xe71\xc2\xb0~\x01\x01\x9832\
+\xc5\xe6\x06\xd5T_\x96\x0bj\x06V\x00\xa5\x9e\x14,\
+ \x00St\x0a\xb0U\x22\xcb\xe2\xf6\xd2\xc0\x5c\xe0=\
+\x86\xe72$i0\x11\x83\x00\xbcI\xbea\x16\xdb\x92\
+@\x09\xa0\xdc\xae\x8e\x11\x00\x02\xf0*\x05\x86\x03T\x95\
+\x1d5\x81\xb9\xc0U\x9d5f\xfb\x07\x14 \x80\xc0\x11\
+\x98\xd5\x80\xb9\x89v\xa9\xab\xfc>\x01h_4\x97a\
+]g\xbdS?\x87>A\xaa/[\x88\x17\xb7\xedq\
+wL\xea\xfd\x8d\x98`\xb2w\xa3&n\xdd\xddn?\
+\x80\xabu\x88\x00<Lf|\xa6YY\xb5\x86y\xf5\
+\xbc@mW\x9d\x89\x00\xb2\xe23z\xfd\xdf\xea\x0eF\
+\xfa\xe9-\xbay\xcbs\xd3\x7fs\xc8\xc7\xa8\xdf\xf9p\
+\xd9S<\xda\xc3\xd6\x05\xc8J\xc80++H-\x00\
+K\xa1e\x1a\xd61 \x00\xe3\x16\x80\xdd\xcdY\xe7\x93\
+\xfc\x7f\xbd?\x1f\x9b\xe6\xab&\x09E\x02\x08 \xf0-\
+\x80\xc6\xee\xa6@]\xe4\x06\xc3-\xcc\xb2\xe2\x11\x00\x02\
+\xf0 }\x19\xa0\xfas\xb4v\xb7\x06\xea\x22\xb7\xf6\xd8\
+\x9dOfB&Q\x83\x00\xbcGZ|\xaaI9\x1d\
+=\x9d\xbe\xcd\x02\xf4\xa7h1\x14Zf\x0cvZ\x06\
+\x04p\xc8Xm\x01\xde\xd2\xd3\x1a\xb8\x8blyNV\
+\xf9\x16\x01\x01x\x92\xf6\x9e\xf6\xc0\x9dSGO\x07\x17\
+\x16\x82-\x808\xa3S\xe9\x8cv\x05\xee\x22\xb7\x1aJ\
+\x8dMB\x10@\xa0\xc7\x00\x82\xd8\x02\xe86\x94Zb\
+$\x81\xa8A\x00\x00\x80\x00<D\x02O\xa6~!5\
+.\x95J@\x00\xde\xc3j\xe3\x0a}\x0d\x184\x9a\x0d\
+_\x03\xea\x1e\x01\x80\x00<G\x8f\xf3cAR\x5cb\
+\xe0.2\xfdv\x08\xbc\x00Z\xba[\xb9\x9a\xfd\x22\xb5\
+(\x15\x8a\x00 \xac4w\xb7P\x09\x08\xc0{XM\
+\xdf%\xf7= \x00\x1f\xd2\xd6\xd3fRNj\x5cJ\
+\xf0\xba\x00\x11\xa6\xef\x02]\x80\xd0\xb6\x00,\xc7\x00\x9a\
+\xe8\x02 \x00/\xd2i\xf4\xfa.-\x80\xef\xb9\xd3\xe2\
+\xd3\xcc\xcab]\x01\x02\xf0$V\x83SVS\x8a=\
+%\x00\xc3nMG\x14\x01 \x00\x0f\xd2`\x98\xc5'\
+h\x12H5<\x9f\xa6.\xba\x00\x08\xc0\x834\x1a\xa6\
+\xbd\x0aZ7\xc0r`3\x88\xf9\x12\x10\x00-\x80?\
+\xc02\xbd\x98\x17\xc82L\xe3e\x95`\x14\x10\x80)\
+M\x86\x02\x18\x94\x98\x1b\xa8\x8b\x9c\x97`s>\xdd\xd1\
+nf\x5c\x22\x00\x8f\xb6\x00\x0cw\xf3\xcd\x0b\x9a\x00\x0c\
+6\x05\xb1\xaec@\x00\xa6\xec5l\x9aZ\x05L\xd0\
+\x04\xb0\x97\xe6?\x02\xf0*\x95\x1d\xd5fe\x0d6\xdc\
+ix\xa0I\x8c$\x9a%L\xad\x0a\xd0\xa6\xa9\x100\
+\x01\x94\xb7W\x9a\x95U\x98<,0\x17\xb80y\xa8\
+\x9dd;\xab\x89\x18\x04\xe0MZ{\xda\xcc\xb6\xf4\x1a\
+\x992<@\x02\xb0\x93YU\x07\x02@\x00\x1e\xa6\xa2\
+\xc3\xa6\x150$)?0)\xc6\x0aS\x86\x1a\xd6/\
+\x02@\x00!\xe8\x06\xe8&\x98#\x02\xd2\x0d\x18\x91l\
+\xd7\x9a\xd9\xddVB\xc4 \x00\xef\xb2\xa7\xbd\xdc\xac\xac\
+\x89i\x87\x05\xa2N&\xa4\x8d3+\xab\xb8\xbd\x94\x88\
+A\x00\xde\xe5\x8b\xb6b\xb3\xb2\x8a\xd2'\xf8\xbe>\x12\
+\x22\xf1rX\xeah\x93\xb2j:\xf72\x09\x08\x01x\
+\x9b\xcf[w\xd3\x02\xd8\x87\xc3R\xc7\x98\x8de\xec2\
+\x94+ \x80\x18\xb5\x00J\xccR\x83i\xd39\xc5\xe7\
+\xdb`\x15\xa5O4+\xeb\xb3\x96\x1dD\x0b\x02\xf06\
+]\xd1.\xd9\xd1\xba\xd3\xac\xf9|T\xe6\x11\xbe\xae\x8f\
+\x99Y\xd3\x0c\x05\xf09\xd1\x82\x00\xbc\xcf\x96\xe6mf\
+e\xcd\xca:\xd2\xc7\xfd\xff\x04\x99\x91i(\x80\xe6\xed\
+\xbe8o\xf6@\x08\xb9\x0065m5+\xeb\xd8\xec\
+\x99\xee+A?25c\x92Y\x1e\x00\x9df]\xd6\
+Q\xe9\x8b\xf3f\xf7\xe2\x90\x0b\xe0\xc3\xa6Mfe\x0d\
+M*\x90#2\x8a|Y\x0f'\xe6\x1eoV\xd6\x07\
+\x8d\x9b\x88\x14\x04\xe0\x0fj;\xeb\xa4\xb8\xcd\xee}\xf5\
+7\x07\x9d\xe0\xbb:\xd0\xa7\xe0\x82\xdc\xb9f\xe5ml\
+\x8a\xbd\x00\xda\x8c\xb6e\xb7L~\x82\x00|\xca\xba\x86\
+\x0f\xcc\xca\x9a\x9f;\xdbl5]\x7f1/\xe78\xb3\
+\xbc\x86Q\xe7\xe7\xbd\x86\x8d1?f\x1d\xc05\x11@\
+|\x06Q\x1dv\x01\xbcS\xbf\xde\xac,}\x15xn\
+\xc1\xe9\xbe9w\x1d\xb3\xb8`\xe8\xd9f\xe5mm\xde\
+.5\x9d\xb5\xfdr\xec\x16\x13\x8dh\x01 \x00\xa7\xc9\
+\xbaY\x9a\xba\x9b\xcd\xca\xfb\x96#\x00\xbf\xb4\x02\x16\xe4\
+\xce\x91\xd1)#\xcc\xca{\xa3\xfe\xdd~;v\x8bk\
+\x96\x93\x98MT\x87]\x00\xda\x9c\x5c[gw\xe3\xa6\
+\xc7\xa7\xc9\xa5\xc3/\xf0\xfcy\xeb\x0e@\xdf5<N\
+m\xfe\xbfV\xfb\xa6\xaf\x0404)?\x90[\xbc#\
+\x80>\xb2\xa6v\xadiyg\xe5\x7fSfx|b\
+\xd0e\xc3/4M\x00\xf2a\xe3\xa6~}\xfdg\x91\
+\xcfA\xbb@#\x93\x0b\x89\xec\xb0\x0b\xe0\xfd\xc6\x8fM\
+o^\xbd\xb1n\x19s\x9d\xfbj\xd0\x8b\xe8\xc0\xdfy\
+\x05g\x98\x96\xf9B\xcd\x9a~=\x07\xab\x94c\x13\xd2\
+\xc6\x12\xd9a\x17\x806__\xa8~\xc5\xb4\xcc\xdc\xc4\
+\x1c\xf9\xb7\x09\xb7I~\xe2 O\x9d\xab\xb6Ln\x1e\
+s\xadi\x99\xba\xfa\xef\xb5\xbdo\xf5\xaf\x00\x8cR\x8e\
+\xcd\xca:\x8a\xc8\x0e\xbb\x00\x94\xe7\xab_\x96\x0e\xa3M\
+C\xbfd\xb8\xd3\xc4\xbeo\xd2\x9d2\xceh\x99\xed\xa1\
+rR\xde7d\xd1\xf8[\xcd\xfb\xbdK+W\x9a\xbd\
+\x9a\xeb-V\x19\x87\xe6\xe6\x1c\xed9I#\x80\x01@\
+\xfb\x94/\xd5\xda7c5e\xd8\x7fLZ$\x7f\x95\
+\x7f\xea\x80M\x15\xd6\xf7\xfc7\x8c\xbaJ\xfe\xc1y\xf2\
+'\x18oi\xae\xdb\xac\xad\xacz\xa9\xdf\xcf\xc9*\xe3\
+\x90fB\xfe\xc9\xd8\xebM\xb7DC\x00>\xe5\x89\xf2\
+\x15fK\x84\xf7%9.I~0\xf2{r\xff\xe4\
+Erd\xe6\xe1\xfdv>\xf1N\xb0\xeb\xec\xc4\x87\xa7\
+\xfcB\xfer\xf0\xc91\xf9\x8e\x87\xcb\x9fv\x93\xac\xf6\
+7;Zw\x99\x95\xa5S\xb8\x17\x17\xfd\x5c\xe6\xe5\xce\
+v\x85\x00_Od\xc1\x86s\xa2A?I\x0dT}\
+Z\xc7\x92\xcd\xcd\x9f9]\x8e\xff\x96\xb5u\xef\x98m\
+U\xbe/\x05I\x83\xe5\xe4\xbcyr\xc6\xe0\x85\xee?\
+\xc7\x8a\x92\xf6R\xb9t\xf3u1\x91f\xaf\x84=\xf5\
+\x97n\x0b\xcb\x12\x9df\xbc\xb5y\x9bsneR\xef\
+\xb4\x0a\xf5\xdcT\xe0*\x86t\xa7%\x15\x1fIpZ\
+T)\xee\xdf\xfa\xef\xb5\xe5\xa0\xab)\xf5\xf5\xaf\xb6\xae\
+R\x9c\xbf?j\xda,\xb7\xec\xb8+p\xb1\x11\x8a\xb5\
+\x93\xbf)[\xea\xf6\x95c9\x99gJ\xfaD\xf7\xf3\
+\xc3QW\xca\xc6\xc6O\xdc\xc9H\x9b\x9a\xb7\xb83\xe9\
+\x0ef\x9e\xbb\xee\xe63%}\x92LM\x9f,\xd3\x9d\
+\x16\xc6\xa4~\xcaPto\xf1\x83\x03\x16\xfc\x8a\xae\xe6\
+\x1c\x92g+\x00\x9d\xcdyd\xe6T\xf7s\xb0\x04m\
+\xc3\xd8P\x09@w\xb4\xfdU\xe9\x13nK \xe6\x15\
+\xea<9ffMw?\xfb\x8eE\x94\xb7W\xb8\xaf\
+%u\xba\xab\x0a\xa1\xcdibk\xa0\xe9\xcd\xa9\xff\x8f\
+\xca)+!\xc3}\xfa\xe9\xabF\xab\xb9\xfc}\xe1\xd9\
+\xaa\x17eC?\xcc\xfb?\x10\xba\x9a\xf3\xc4\xbc\xe3=\
+w\x0fik\x00\x01\xf8\x18\xbd\xb9u\x9a\xec@,\xef\
+\xcdq\x9e\x1e\xfa\x99\xec\xe1D\xa3\xda<^\xbc\xe7\x91\
+\x01?\x8e\xf7\x1b>\xf2d\xfd\x04U\x00qa\x11\x80\
+\xce\x0bX\xb4\xeb>2\xdb~\x0d:\xe0w\xeb\x8eE\
+\x032\xf0\xb7?\xdaJ\xfa\xb4e;\x02@\x00\xb1\xb9\
+\xb9\xeer$\x00\x7f(\xc6;w\xde\xe3&T\xf5\x0a\
+\xabk_\xf7\x5c=\xe9\xc0\xa0_\xb3C!\x80}x\
+\xb3~\x9d\xfc\xaa\xf4q\x22\xff\xff\xf8\xf7\xdd\xbf\x94\xb7\
+\xea\xdf\xf3\xd41\xad\xae]k\x96 \x84V\x00\x02\xf8\
+#\x1e-_&\xcb*\x9f\x0f}\xf0\xdfS\xbcX~\
+W\xbd\xdas\xc7\xa5\xaf\xea\x96W\xad\xf2\xdcq\xf9-\
+1\x0c\x028\x00\xf7\x97\xfcZ\x9e\xacX\x11\xcas\xd7\
+\xb7\x0f\xff\xbc\xeb^yn\x00f\xfb\xf5\x16\xbd6\xf5\
+F\xbb=\xd3\x02@\x00_\xdb\xf7\xd5Q\xef_\x14?\
+$=\xd1\x9e\xd0\x9cwCW\xa3\xdc\xb4\xfd\xa7\x9e\xec\
+g\xef\x8bNG\xfe\xf9\xee\x07\x10\x00\x02\x88-\xda\xd4\
+\xbc\xd1\x09\x88\xfeJ{5\x90\xe8l\xb6\xcb\xb7\xdc \
+\x1f6~\xe2\x8b\xe3}\xa3n\x9d<\x5c\xf64\x02@\
+\x00\xb1E\x13_\x5c\xb6\xe5\x87\xb2f\xef\x1b\x81=G\
+}\xc5\xa7SY\xab:k|u\xdc\x0f\x97=%\x0f\
+\x96>\x86\x00bD\xfc\xd8+\x8bnG\x01\x22\xed=\
+\x1d\xf2z\xdd;\xeeT\xd4I\xe9\xe3\xdd\x89;AB\
+w\xcc\xd1\x19\x87\xeb\x1b7\xfa\xee\xd8?n\xda\xe2\xae\
+\xb5\x98\x9eq\xf8\x80\x06\xa1&\x99\xf1\xe2\x1c\x05\x04`\
+HYG\x85\xbb\xa8\xa7\xdc\xf9=&u\x94;=7\
+(\xe8\x96\xe7o\xd5\xaf\x97\xda\xae:\xdf\x1d{i{\
+\xb9\xac\xac~\xd9\x15\xb5f\xfc\xd1E;\xfd.\xa2\xe6\
+-\xa6;Oy\x81P\xac\x06<\xe8\xcaq~t{\
+0\xcd\x07\xa8\xfb\x04\x06a\x22\x88>\xc1\xae\xd9\xfac\
+w\x10\xd4\xafh\xf2\x93y9\xb3e\xe1\xa0\xf92-\
+\xa3(f\xcb}\xcb;*\xdd%\xca;[w\xcb\x8e\
+\x96]\xb2\xa9y\xab\x9b)\x09\x01\x84\x90A\x89yr\
+B\xee\x1c9>\xe7X9<c\x92\xafep_\xf1\
+\x83\xb2\xa2\xea\x85@\x5c\x17\xdd\x05iz\xc6\x14\x99\xec\
+t\xdb\xc6\xa5\x8eqS\xa2\xeb\x82\xaa\xdel\xed\xae\x19\
+\x8f4\xa0u\x00xO{\x85\xd3\xca(sw\x95\xd2\
+u\x11\xba,:\x0c\xd3\xc6\x11\xc0A\xa0\x9bO\xcc\xcc\
+\x9c\xe6<}\xa6\xb8\x8b\x8b\xc6:]\x05?\x09Ao\
+\xec\x8b7\xff \xd0o>T\x0c\xf9\x8e\xb4u-\x7f\
+\x5c$\xce]\xef\xdf\x1d\xed\x91\xd6\xee6i\xedi\x95\
+f\xa7\x0et\x95h\xe8[\xb9\x08\xc0\xe2fK\x921\
+)#\xdd<\x81\x85\xc9\xc3\xdc\xd4\xdcC\x93\x0b$/\
+1Wr\x13\xb2\xdd\xc1\xb7\xbe\xa0O\xa6R\xe7\x89T\
+\xdc\xbe\xc7\x1d\xfc\x9a\x96>E\x8e\xc9\x9eaz\xcc:\
+\xe0y\xfb\xe7\xff\xca\xc5C\x00\x08 \xd6\xe8\xda~\x9d\
+F\xaa\x0bJ\xb4\xbf\x9a\xea<\x8d\xe2#\xff\xff\x06V\
+\x9fJ\xfatj\xeeiq'\xea\xec\x9fQH3\x00\
+-\x99r\xafy\x8e;}-\xf8\xb6\xe16j\x80\x00\
+ F\x9c?\xe4,\xb9\xaa\xf0\x22\xd32+;\xaa\xe5\
+\x12\xa7+\xe0\xc5\x857\xd0?0\x11\xc8'\xe8\xe2%\
+\x1d\x8d\xb6D[\x16\x97\x0c\xfb6\x95\x8b\x00\xc0\xebt\
+G\xbb\xdd\xd5{\xd6|\xab\xe0\x0c\xcf\xecq\x00\x08\x00\
+\x0e\x80\xce\x88{\xd1x\xbb.\x1d!\xbfa\xd4\xd5\x81\
+Lv\x01\x08 p\xfc\xe7\x9eG\xa4\xb1\xbb\xc9\xb4L\
+\x9d!xf\xfe)Tn\xf8h@\x00>C\xd7\xc8\
+/\xde\xf3\xa8y\xb9\x97\x0f\xff\x8e\x0cJ\xcc\xa5\x82C\
+\x14\xfc\xceg!\x02\xf0!\xab\xaaW\xbb\xf3\x03,\xd1\
+W\x95\x7f;\xe2R*7D\xc1\xff\xea\xccg\xdeE\
+\x00>D\xe7\xf1\xdf\xb3{\xb1y\x22\x13\xddF\xcbz\
+\xc2\x11x7\xf8\x19\x03\xf01\xdb[w\xca\xf2\x18\xcc\
+\xe7\xbfn\xe4\x15\xee4Z\x08~\xf0#\x00\x9f\xb3\xa4\
+\xec\x09\xf3\xd5i\xba\x90\xe6\xe2a\xe7S\xb9!\x08~\
+\x04\xe0stQ\xcf\xfd%K\xcc\xcb=\x8f\xb9\x01\xa1\
+\x08~\x04\x10\x00^\xdd\xfb\xa6lh\xb4\xddNK\xb7\
+ \xd7MN\x99\x1b\x10\xec\xe0G\x00\x01\xe1\xde\xdd\x8b\
+\xdd\x15\x84\x96\xe8\xce\xc4\xa7\x0f^H\xe5\x068\xf8\x11\
+@@\xd0\x04\x16\x8f\x97/7/\xf7\x8a\xc2\xef\xb8\xdb\
+\x94C0\x83\x1f\x01\x04\x88\xc7+\x96IY{\x85\xe9\
+\xf8\x82\xe6F\x0c\xd3\x9e\x09a\x0b~%\x81\xba\x0a\x06\
+\x1d=\x9dro\xf1\x7f\xc9\xa2\xf1?9\xa4rj;\
+\xebdY\xd5\xf3\xb2\xb2\xeaei\xean\xa6b\x03\x1c\
+\xfc\x08 `\xack\xf8@\xfe\xa7\xeem\x99\x97s\xdc\
+Au#\x9e\xaexV^\xaayM:\xa3\x9dTf\
+\x08\x82\x1f\x01\x04\x90\xfb\x8b\x97\xc8\xd1YG\xf5:{\
+\x90f\x09~\xb2|\x85\x9b\x22\xcc\xcf\x99\x82\xa1\xef\xc1\
+\x8f\x00\x02\x88\xee\xfc\xa3\xbb\xe9\x5cUx\xf1\x01\xff\xbb\
+\xf5\x0d\x1b\xe5\x89\x8a\xe5\xf2A\xe3\xc7TZH\x83\x1f\
+\x01\x04\x94e\x95\xbf\x93\x85y\xf3\xffh2\x8f\x0e\xe8\
+\xbdV\xf7\x96\xfb\xc4\xd7\xa9\xc4\x10\xee\xe0G\x00\x01\xe5\
+\xcb\xecA\xf7M\xbc\xd3\xfd[\x07\x08W\xd5\xac\x96\xa5\
+\x15\xcfIYG%\x15\x14\x1c\xaa\x9d\xcf\x89N\xf0\x1f\
+\xf4L0\x04\x10Pt\x0b\xab\xa5\x95+\xa5\xad\xbbM\
+\x9e\xa9Z\xe5\xe6\x11\x80\xc0\x05\xff\x09N\xf0\x1fR\x1f\
+\x8e\xac\xc0\x00!\x0d~\x85\x89@\x00!\x0d~\x04\x00\
+\x10\xe2\xe0G\x00\x00!\x0e~\x04\x00\x10\xe2\xe0G\x00\
+\x00!\x0e~\x04\x00\x10\xe2\xe0G\x00\x00!\x0e~\x04\
+\x00\x10\xe2\xe0G\x00\x00!\x0e~\x04\x00\x10\xe2\xe0G\
+\x00\x00!\x0e~\x04\x00\x10\xe2\xe0G\x00\x00!\x0e~\
+\x04\x00\x10\xe2\xe0G\x00\x00!\x0e~\x04\x00\x10\xe2\xe0\
+G\x00\x00!\x0e~%\x12\x8d\x92\x10\x08 \xac\xd0\x02\
+\x00@\x00\x00\x80\x00\x00\x00\x01\x00\x00\x02\x00\x00\x04\x00\
+\x00\x08\x00\x00\x10\x00\x00 \x00\x00@\x00\x00\x80\x00\x00\
+\x00\x01\x00\x00\x02\x00\x00\x04\x00\x00\x08\x00\x00\x10\x00\x00\
+ \x00\x00@\x00\x00\x80\x00\x00\x00\x01\x00\x00\x02\x00\x00\
+\x04\x00\x00\x08\x00\x00\x10\x00\x00 \x00\x00@\x00\x00\x80\
+\x00\x00\x00\x01\x00\x00\x02\x00\x00\x04\x00\x00\x08\x00\x00\x10\
+\x00\x00 \x00\x008\x00\xff+\xc0\x00\x1c{0\x19G\
+\x03\xd4k\x00\x00\x00\x00IEND\xaeB`\x82\
+"
+
+qt_resource_name = b"\
+\x00\x06\
+\x07\x9e\x88\xb4\
+\x00s\
+\x00h\x00a\x00r\x00e\x00d\
+\x00\x0c\
+\x00V'\xdc\
+\x00C\
+\x00h\x00e\x00c\x00k\x00B\x00o\x00x\x00.\x00q\x00m\x00l\
+\x00\x0d\
+\x01\xb8P\x9c\
+\x00T\
+\x00e\x00x\x00t\x00F\x00i\x00e\x00l\x00d\x00.\x00q\x00m\x00l\
+\x00\x09\
+\x08\xbf\xf4\xdc\
+\x00L\
+\x00a\x00b\x00e\x00l\x00.\x00q\x00m\x00l\
+\x00\x1a\
+\x04'S\xdc\
+\x00S\
+\x00i\x00m\x00p\x00l\x00e\x00L\x00a\x00u\x00n\x00c\x00h\x00e\x00r\x00D\x00e\x00l\
+\x00e\x00g\x00a\x00t\x00e\x00.\x00q\x00m\x00l\
+\x00\x10\
+\x09\x8e}\x5c\
+\x00L\
+\x00a\x00u\x00n\x00c\x00h\x00e\x00r\x00L\x00i\x00s\x00t\x00.\x00q\x00m\x00l\
+\x00\x0a\
+\x0a\xce\x15\xdc\
+\x00S\
+\x00l\x00i\x00d\x00e\x00r\x00.\x00q\x00m\x00l\
+\x00\x12\
+\x06\xc0(<\
+\x00F\
+\x00l\x00i\x00c\x00k\x00r\x00R\x00s\x00s\x00M\x00o\x00d\x00e\x00l\x00.\x00q\x00m\
+\x00l\
+\x00\x06\
+\x07\x03}\xc3\
+\x00i\
+\x00m\x00a\x00g\x00e\x00s\
+\x00\x06\
+\x07\x84+\x02\
+\x00q\
+\x00m\x00l\x00d\x00i\x00r\
+\x00\x0a\
+\x09\xcc\x1a\xdc\
+\x00T\
+\x00a\x00b\x00S\x00e\x00t\x00.\x00q\x00m\x00l\
+\x00\x0a\
+\x0d\xd0R\xdc\
+\x00I\
+\x00m\x00a\x00g\x00e\x00s\x00.\x00q\x00m\x00l\
+\x00\x0a\
+\x0bhq\x5c\
+\x00B\
+\x00u\x00t\x00t\x00o\x00n\x00.\x00q\x00m\x00l\
+\x00\x0d\
+\x0b]\x12\x87\
+\x00c\
+\x00h\x00e\x00c\x00k\x00m\x00a\x00r\x00k\x00.\x00p\x00n\x00g\
+\x00\x07\
+\x0auW\xa7\
+\x00t\
+\x00a\x00b\x00.\x00p\x00n\x00g\
+\x00\x08\
+\x07\x9eZG\
+\x00b\
+\x00a\x00c\x00k\x00.\x00p\x00n\x00g\
+\x00\x08\
+\x0c\xf7Y\xc7\
+\x00n\
+\x00e\x00x\x00t\x00.\x00p\x00n\x00g\
+\x00\x11\
+\x02G!g\
+\x00s\
+\x00l\x00i\x00d\x00e\x00r\x00_\x00h\x00a\x00n\x00d\x00l\x00e\x00.\x00p\x00n\x00g\
+\
+\x00\x0b\
+\x05R\xbf'\
+\x00q\
+\x00t\x00-\x00l\x00o\x00g\x00o\x00.\x00p\x00n\x00g\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x0c\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x000\x00\x00\x00\x00\x00\x01\x00\x00\x06\x9f\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x8a\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x00\xe2\x00\x00\x00\x00\x00\x01\x00\x00&\x02\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01\x0c\x00\x02\x00\x00\x00\x06\x00\x00\x00\x0e\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x01\x1e\x00\x00\x00\x00\x00\x01\x00\x00,\xcb\
+\x00\x00\x01\x82_\xc7\xcc\xde\
+\x00\x00\x00P\x00\x00\x00\x00\x00\x01\x00\x00\x0a\xbf\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x00\xa2\x00\x01\x00\x00\x00\x01\x00\x00\x16\x06\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x010\x00\x00\x00\x00\x00\x01\x00\x00.\x07\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x00\xc8\x00\x00\x00\x00\x00\x01\x00\x00\x1b\xb6\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01d\x00\x00\x00\x00\x00\x01\x00\x009S\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01J\x00\x00\x00\x00\x00\x01\x00\x006\xe7\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01\xde\x00\x00\x00\x00\x00\x01\x00\x00N\xca\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x02\x06\x00\x00\x00\x00\x00\x01\x00\x00RE\
+\x00\x00\x01\x82_\xc1\xa7\xb9\
+\x00\x00\x01\xb2\x00\x00\x00\x00\x00\x01\x00\x00C1\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01\x9e\x00\x00\x00\x00\x00\x01\x00\x00A\xf8\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01~\x00\x00\x00\x00\x00\x01\x00\x00>\xcb\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x01\xc8\x00\x00\x00\x00\x00\x01\x00\x00Ik\
+\x00\x00\x01\x82Y\xad^\x0f\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/declarative/window/AllScreens.qml b/examples/declarative/window/AllScreens.qml
new file mode 100644
index 000000000..6ce06db58
--- /dev/null
+++ b/examples/declarative/window/AllScreens.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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
+import QtQuick.Controls
+
+Column {
+ id: root
+ spacing: 8
+
+ Label {
+ text: "Total number of screens: " + screenInfo.count
+ font.bold: true
+ }
+
+ Flow {
+ spacing: 12
+ width: parent.width
+
+ Repeater {
+ id: screenInfo
+ model: (Qt.application as Application).screens
+ Label {
+ required property string name
+ required property int virtualX
+ required property int virtualY
+ required property var modelData // avoid shadowing Label.width and height
+
+ lineHeight: 1.5
+ text: name + "\n" + virtualX + ", " + virtualY + " " + modelData.width + "x" + modelData.height
+ }
+ }
+ }
+
+ Component.onCompleted: {
+ var screens = (Qt.application as Application).screens;
+ for (var i = 0; i < screens.length; ++i)
+ console.log("screen " + screens[i].name + " has geometry " +
+ screens[i].virtualX + ", " + screens[i].virtualY + " " +
+ screens[i].width + "x" + screens[i].height)
+ }
+}
diff --git a/examples/declarative/window/CurrentScreen.qml b/examples/declarative/window/CurrentScreen.qml
new file mode 100644
index 000000000..d0f7245ef
--- /dev/null
+++ b/examples/declarative/window/CurrentScreen.qml
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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
+import QtQuick.Controls
+
+Item {
+ id: root
+ width: 400
+ height: propertyGrid.implicitHeight + 16
+
+ function orientationToString(o) {
+ switch (o) {
+ case Qt.PrimaryOrientation:
+ return "primary";
+ case Qt.PortraitOrientation:
+ return "portrait";
+ case Qt.LandscapeOrientation:
+ return "landscape";
+ case Qt.InvertedPortraitOrientation:
+ return "inverted portrait";
+ case Qt.InvertedLandscapeOrientation:
+ return "inverted landscape";
+ }
+ return "unknown";
+ }
+
+ Grid {
+ id: propertyGrid
+ columns: 2
+ spacing: 8
+ x: spacing
+ y: spacing
+
+ //! [screen]
+ Label {
+ text: "Screen \"" + Screen.name + "\":"
+ font.bold: true
+ }
+ Item { width: 1; height: 1 } // spacer
+
+ Label { text: "manufacturer" }
+ Label { text: Screen.manufacturer ? Screen.manufacturer : "unknown" }
+
+ Label { text: "model" }
+ Label { text: Screen.model ? Screen.model : "unknown" }
+
+ Label { text: "serial number" }
+ Label { text: Screen.serialNumber ? Screen.serialNumber : "unknown" }
+
+ Label { text: "dimensions" }
+ Label { text: Screen.width + "x" + Screen.height }
+
+ Label { text: "pixel density" }
+ Label { text: Screen.pixelDensity.toFixed(2) + " dots/mm (" + (Screen.pixelDensity * 25.4).toFixed(2) + " dots/inch)" }
+
+ Label { text: "logical pixel density" }
+ Label { text: Screen.logicalPixelDensity.toFixed(2) + " dots/mm (" + (Screen.logicalPixelDensity * 25.4).toFixed(2) + " dots/inch)" }
+
+ Label { text: "device pixel ratio" }
+ Label { text: Screen.devicePixelRatio.toFixed(2) }
+
+ Label { text: "available virtual desktop" }
+ Label { text: Screen.desktopAvailableWidth + "x" + Screen.desktopAvailableHeight }
+
+ Label { text: "position in virtual desktop" }
+ Label { text: Screen.virtualX + ", " + Screen.virtualY }
+
+ Label { text: "orientation" }
+ Label { text: root.orientationToString(Screen.orientation) + " (" + Screen.orientation + ")" }
+
+ Label { text: "primary orientation" }
+ Label { text: root.orientationToString(Screen.primaryOrientation) + " (" + Screen.primaryOrientation + ")" }
+ //! [screen]
+
+ Label { text: "10mm rectangle" }
+ Rectangle {
+ color: "red"
+ width: Screen.pixelDensity * 10
+ height: width
+ }
+ }
+}
diff --git a/examples/declarative/window/Splash.qml b/examples/declarative/window/Splash.qml
new file mode 100644
index 000000000..41c82c0c7
--- /dev/null
+++ b/examples/declarative/window/Splash.qml
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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
+import shared
+
+//! [splash-properties]
+Window {
+ id: splash
+ color: "transparent"
+ title: "Splash Window"
+ modality: Qt.ApplicationModal
+ flags: Qt.SplashScreen
+ property int timeoutInterval: 2000
+ signal timeout
+//! [splash-properties]
+//! [screen-properties]
+ x: (Screen.width - splashImage.width) / 2
+ y: (Screen.height - splashImage.height) / 2
+//! [screen-properties]
+ width: splashImage.width
+ height: splashImage.height
+
+ Image {
+ id: splashImage
+ source: Images.qtLogo
+ MouseArea {
+ anchors.fill: parent
+ onClicked: Qt.quit()
+ }
+ }
+ //! [timer]
+ Timer {
+ interval: splash.timeoutInterval; running: true; repeat: false
+ onTriggered: {
+ splash.visible = false
+ splash.timeout()
+ }
+ }
+ //! [timer]
+ Component.onCompleted: visible = true
+}
diff --git a/examples/declarative/window/doc/window.png b/examples/declarative/window/doc/window.png
new file mode 100644
index 000000000..72487b4d9
--- /dev/null
+++ b/examples/declarative/window/doc/window.png
Binary files differ
diff --git a/examples/declarative/window/doc/window.rst b/examples/declarative/window/doc/window.rst
new file mode 100644
index 000000000..8736bb629
--- /dev/null
+++ b/examples/declarative/window/doc/window.rst
@@ -0,0 +1,35 @@
+Qt Quick Examples - Window and Screen
+=====================================
+
+This example demonstrates the Window and Screen types in QML.
+
+.. image:: window.png
+ :width: 392
+ :alt: Window and Screen screenshot
+
+In addition, this example demonstrates the usage of the Qt Resource System in
+Qt for Python for more advanced scenarios. There are several QML files, one of
+which imports a module from this sibling directory. Both this "shared" module
+and the QML files of the example need to be compiled into Python modules with
+the resource compiler rcc.
+
+For the "shared" module approach to work with QML and rcc, you need:
+
+* A module definition *qmldir* file
+* A Qt Resource Collection file (.qrc) specifying all the QML files and other
+resources, plus the *qmldir* file
+
+The .qrc file is the input to rcc. This will generate a Python module (called
+*shared_rc* here) that can then be imported from the Python code. At runtime,
+only this Python module is needed, not the .qrc file or any of the .qml files
+or even the image resources, as they have all been compiled into the Python
+module.
+
+For the example, rcc needs:
+
+* A Qt Resource Collection file (.qrc) specifying all the QML files and other
+resources. There is no qmldir file here because this is not a module.
+
+This will generate a Python module (called *window_rc* here) that can then be
+imported from the Python code. Again, only the Python module is needed at
+runtime.
diff --git a/examples/declarative/window/main.py b/examples/declarative/window/main.py
new file mode 100644
index 000000000..74d475e0b
--- /dev/null
+++ b/examples/declarative/window/main.py
@@ -0,0 +1,74 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+from pathlib import Path
+import sys
+
+from PySide6.QtCore import QUrl, qWarning
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtQml import QQmlComponent, QQmlEngine
+from PySide6.QtQuick import QQuickWindow
+
+import window_rc
+
+# Append the parent directory of this file so that Python can find and
+# import from the "shared" sibling directory.
+sys.path.append(os.fspath(Path(__file__).parent.parent))
+from shared import shared_rc
+
+
+if __name__ == "__main__":
+ app = QGuiApplication(sys.argv)
+ engine = QQmlEngine()
+
+ # Add the qrc root as QML import path so that the "shared" module
+ # can be found.
+ engine.addImportPath(":/")
+
+ component = QQmlComponent(engine)
+ QQuickWindow.setDefaultAlphaBuffer(True)
+ component.loadUrl(QUrl("qrc:///window/window.qml"))
+ if component.isReady():
+ component.create()
+ else:
+ qWarning(component.errorString())
+ app.exit(1)
+ app.exec()
diff --git a/examples/declarative/window/resources/icon.icns b/examples/declarative/window/resources/icon.icns
new file mode 100644
index 000000000..88b4b2444
--- /dev/null
+++ b/examples/declarative/window/resources/icon.icns
Binary files differ
diff --git a/examples/declarative/window/resources/icon.ico b/examples/declarative/window/resources/icon.ico
new file mode 100644
index 000000000..52af30a6c
--- /dev/null
+++ b/examples/declarative/window/resources/icon.ico
Binary files differ
diff --git a/examples/declarative/window/resources/icon.svg b/examples/declarative/window/resources/icon.svg
new file mode 100644
index 000000000..0b6153206
--- /dev/null
+++ b/examples/declarative/window/resources/icon.svg
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="128"
+ height="128"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.2 r9819"
+ version="1.0"
+ sodipodi:docname="icon.svg"
+ inkscape:export-filename="/Users/rutledge/dev/qt5-stable/qtdeclarative/examples/quick/window/window/icon80.png"
+ inkscape:export-xdpi="61.509998"
+ inkscape:export-ydpi="61.509998"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient4009">
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4011" />
+ <stop
+ id="stop4019"
+ offset="0.875"
+ style="stop-color:#ffffff;stop-opacity:0.49803922;" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:0;"
+ offset="1"
+ id="stop4013" />
+ </linearGradient>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 186.64798 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="559.62469 : 186.64798 : 1"
+ inkscape:persp3d-origin="279.81235 : 124.43199 : 1"
+ id="perspective4876" />
+ <inkscape:perspective
+ id="perspective2836"
+ inkscape:persp3d-origin="22 : 14.666667 : 1"
+ inkscape:vp_z="44 : 22 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 22 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <filter
+ inkscape:collect="always"
+ id="filter4063"
+ x="-0.195491"
+ width="1.390982"
+ y="-0.16235915"
+ height="1.3247183">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="3.3077485"
+ id="feGaussianBlur4065" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10"
+ guidetolerance="10"
+ objecttolerance="10000"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.9775825"
+ inkscape:cx="62.656189"
+ inkscape:cy="42.423381"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ inkscape:window-width="1280"
+ inkscape:window-height="744"
+ inkscape:window-x="2003"
+ inkscape:window-y="156"
+ showgrid="true"
+ borderlayer="true"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:snap-global="false"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid7194"
+ visible="true"
+ enabled="true"
+ spacingx="8px"
+ spacingy="8px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-66.38047,-391.3222)">
+ <path
+ id="path7304"
+ d="M 95.556318,434.65407 L 165.25811,434.65407 L 165.25811,490.10429 L 95.556318,490.10429 L 95.556318,434.65407 z"
+ style="fill:#01afaf;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:5.24121141000000000;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <path
+ style="fill:#a7c706;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 96.869177,465.30846 c 27.677903,3.04574 41.155393,12.11589 48.000003,24 l -48.000003,0 0,-24 z"
+ id="path7300"
+ sodipodi:nodetypes="cccc"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccc"
+ id="path7302"
+ d="M 165.46767,465.22201 C 137.78977,468.26775 124.31228,477.33791 117.46767,489.22201 L 165.46767,489.22201 L 165.46767,465.22201 z"
+ style="fill:#966406;fill-rule:evenodd;stroke:#000000;stroke-width:3;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1" />
+ <path
+ style="fill:#80ffff;fill-rule:evenodd;stroke:#000000;stroke-width:5.24121141000000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;opacity:1;fill-opacity:1"
+ d="M 95.532809,434.35736 L 74.567964,420.38079 L 74.567964,497.25189 L 95.532809,490.26361 L 95.532809,434.35736 z"
+ id="path7270"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#00ffff;fill-rule:evenodd;stroke:#000000;stroke-width:5.24121141;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 74.567964,455.3222 L 95.532809,462.31048"
+ id="path7272"
+ sodipodi:nodetypes="cc" />
+ <g
+ style="fill:#80ffff;fill-opacity:1"
+ id="g7278"
+ transform="matrix(-0.8735352,0,0,0.8735352,244.36615,64.570513)">
+ <path
+ style="fill:#80ffff;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+ d="M 24,32 L 0,16 L 0,104 L 24,96 L 24,32 z"
+ id="path7280"
+ transform="translate(66.38047,391.3222)" />
+ <path
+ style="fill:#80ffff;fill-rule:evenodd;stroke:#000000;stroke-width:6;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
+ d="M 0,56 L 24,64"
+ id="path7282"
+ transform="translate(66.38047,391.3222)"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <path
+ style="fill:#ffffff;fill-opacity:1;filter:url(#filter4063)"
+ d="m 119.74679,437.94232 c -0.0487,0.003 -0.0932,0.0315 -0.14149,0.0354 -0.1659,0.0132 -0.33372,0.008 -0.49523,0.0354 -0.96156,0.0643 -1.9037,0.14607 -2.86523,0.21224 -2.94807,0.23566 -5.19987,2.66253 -5.19987,6.01345 l 0,39.51194 3.32508,3.07747 0,-0.0354 33.2155,-5.58898 c 2.28673,-0.39587 4.06792,-3.06727 4.06792,-5.97808 l 0,-32.18967 -30.5625,-5.023 c -0.45263,-0.0748 -0.91269,-0.0942 -1.34418,-0.0708 z"
+ id="path3987"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g3"
+ transform="matrix(0.20572087,0,0,0.20572087,113.4162,440.80626)">
+ <path
+ sodipodi:nodetypes="cccccccc"
+ id="path5"
+ style="fill:#006225"
+ d="M 43.09,0.3586 C 40.94,0.0036 38.84,-0.0824 36.81,0.0776 31.968136,0.39505671 27.122677,0.73638425 22.28,1.0696 9.62,2.0816 0,12.4996 0,26.8896 l 0,169.7 14.19,13.2 28.87,-209.42 0.03,-0.011 z"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path7"
+ style="fill:#80c342"
+ d="m 174.4,160 c 0,12.5 -7.75,24.07 -17.57,25.77 L 14.23,209.73 V 25.93 C 14.23,9.21 27.57,-2.27 43.12,0.3 l 131.3,21.52 v 138.2 z"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path11"
+ style="fill:#006225"
+ d="m 154.9,80.96 -12.96,-0.598 0,0.278 6.945,0.32 6.016,0 z"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path13"
+ style="fill:#006225"
+ d="m 144.6,135.6 c 0.66,0.328 1.43,0.476 2.351,0.476 0.161,0 0.329,-0.004 0.497,-0.016 2.55,-0.148 5.32,-0.933 8.343,-2.308 h -6.015 c -1.821,0.832 -3.532,1.457 -5.176,1.848 z"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 91.15,132.4 c 2.351,-6.051 3.511,-17.91 3.511,-35.62 0,-15.89 -1.148,-26.82 -3.484,-32.81 -2.336,-6.027 -5.832,-9.281 -10.52,-9.691 -0.359,-0.031 -0.714,-0.051 -1.058,-0.051 -4.34,0 -7.68,2.535 -10.01,7.625 -2.52,5.543 -3.793,17.04 -3.793,34.44 0,16.82 1.238,28.75 3.734,35.75 2.356,6.672 5.879,9.976 10.5,9.976 0.207,0 0.41,-0.008 0.621,-0.019 4.633,-0.293 8.121,-3.496 10.49,-9.602 m 17.98,3.75 c -4.117,9.707 -10.39,16.06 -18.99,19 0.867,4.449 2.176,7.441 3.922,9.019 1.351,1.211 3.433,1.821 6.222,1.821 0.805,0 1.668,-0.055 2.59,-0.157 v 13.12 l -5.961,0.782 c -1.758,0.23 -3.426,0.343 -5.004,0.343 -5.218,0 -9.445,-1.265 -12.62,-3.824 -4.207,-3.379 -7.308,-9.894 -9.297,-19.54 -9.136,-1.945 -16.26,-7.754 -21.19,-17.5 -5.004,-9.902 -7.551,-24.39 -7.551,-43.34 0,-20.43 3.484,-35.51 10.34,-45.07 5.789,-8.07 13.86,-12.04 24.02,-12.04 1.629,0 3.309,0.102 5.043,0.305 11.95,1.375 20.62,7.016 26.26,16.79 5.535,9.562 8.254,23.27 8.254,41.26 0,16.48 -2,29.45 -6.043,39.02 z M 130.4,45.91 l 11.52,1.238 0,20.21 12.96,0.914 0,12.68 -12.96,-0.598 0,46.33 c 0,4.032 0.445,6.625 1.34,7.789 0.8,1.067 2.046,1.594 3.71,1.594 0.161,0 0.329,-0.004 0.497,-0.016 2.55,-0.148 5.32,-0.933 8.343,-2.308 v 11.65 c -5.136,2.258 -10.18,3.598 -15.12,4.02 -0.718,0.055 -1.41,0.086 -2.078,0.086 -4.48,0 -7.906,-1.301 -10.25,-3.934 -2.73,-3.051 -4.09,-7.949 -4.09,-14.67 V 79.535 L 118.046,79.25 V 65.66 l 7.586,0.547 4.773,-20.3 z"
+ style="fill:#ffffff"
+ id="path17"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path19"
+ style="fill:#006225"
+ d="m 100.3,166 c 0.809,0 1.672,-0.055 2.59,-0.157 H 98.054 C 98.73,165.949 99.507,166 100.3,166 z"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 84.85,63.98 c 2.336,5.997 3.484,16.92 3.484,32.81 0,17.7 -1.16,29.57 -3.512,35.62 -1.894,4.879 -4.527,7.902 -7.863,9.07 0.965,0.368 1.992,0.551 3.078,0.551 0.207,0 0.41,-0.008 0.621,-0.019 4.633,-0.293 8.121,-3.496 10.49,-9.602 2.351,-6.051 3.511,-17.91 3.511,-35.62 0,-15.89 -1.148,-26.82 -3.484,-32.81 -2.336,-6.027 -5.832,-9.281 -10.52,-9.691 -0.359,-0.031 -0.714,-0.051 -1.058,-0.051 -1.09,0 -2.117,0.16 -3.082,0.481 h -0.004 c 3.601,1.121 6.379,4.215 8.336,9.261 z m -2.344,114.3 c -0.113,-0.05 -0.227,-0.105 -0.336,-0.16 -0.012,-0.004 -0.023,-0.012 -0.035,-0.015 -0.102,-0.051 -0.207,-0.106 -0.309,-0.157 -0.019,-0.011 -0.039,-0.019 -0.058,-0.031 -0.09,-0.051 -0.184,-0.098 -0.278,-0.148 -0.027,-0.016 -0.054,-0.036 -0.086,-0.051 -0.082,-0.043 -0.164,-0.09 -0.242,-0.137 -0.039,-0.023 -0.078,-0.047 -0.113,-0.07 -0.07,-0.039 -0.145,-0.082 -0.215,-0.125 -0.047,-0.031 -0.094,-0.059 -0.14,-0.09 -0.059,-0.039 -0.118,-0.074 -0.176,-0.113 -0.059,-0.039 -0.114,-0.075 -0.168,-0.114 -0.051,-0.031 -0.102,-0.066 -0.149,-0.097 -0.066,-0.047 -0.132,-0.094 -0.195,-0.137 -0.039,-0.027 -0.078,-0.055 -0.113,-0.082 -0.078,-0.055 -0.153,-0.113 -0.231,-0.172 -0.023,-0.016 -0.05,-0.035 -0.078,-0.055 -0.098,-0.078 -0.199,-0.156 -0.297,-0.234 -4.207,-3.379 -7.308,-9.894 -9.297,-19.54 -9.136,-1.945 -16.26,-7.754 -21.19,-17.5 -5.004,-9.902 -7.551,-24.39 -7.551,-43.34 0,-20.43 3.484,-35.51 10.34,-45.07 5.789,-8.07 13.86,-12.04 24.02,-12.04 h -6.351 c -10.15,0.008 -18.22,3.977 -24,12.04 -6.855,9.563 -10.34,24.64 -10.34,45.07 0,18.95 2.547,33.44 7.551,43.34 4.934,9.75 12.05,15.56 21.19,17.5 1.989,9.641 5.09,16.16 9.297,19.54 3.176,2.559 7.403,3.824 12.62,3.824 0.098,0 0.199,0 0.297,-0.004 h 5.539 c -3.406,-0.05 -6.383,-0.66 -8.906,-1.828 L 82.498,178.28 z M 128.4,145.6 c -2.73,-3.051 -4.09,-7.949 -4.09,-14.67 V 79.57 l -6.226,-0.285 v -13.59 h -6.016 v 3.035 c 0.871,3.273 1.555,6.82 2.063,10.64 l 4.164,0.192 v 51.36 c 0,6.723 1.367,11.62 4.09,14.67 2.343,2.633 5.765,3.934 10.25,3.934 h 6.015 c -4.48,0 -7.906,-1.301 -10.25,-3.934 z m 2.043,-99.66 -6.016,0 -4.668,19.88 5.911,0.422 4.773,-20.3 z"
+ style="fill:#006225"
+ id="path21"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:5.24121141;stroke-linecap:round;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ d="M 96.506224,434.65407 L 166.20801,434.65407 L 166.20801,490.10429 L 96.506224,490.10429 L 96.506224,434.65407 z"
+ id="rect7265" />
+ </g>
+</svg>
diff --git a/examples/declarative/window/resources/icon64.png b/examples/declarative/window/resources/icon64.png
new file mode 100644
index 000000000..0fa324401
--- /dev/null
+++ b/examples/declarative/window/resources/icon64.png
Binary files differ
diff --git a/examples/declarative/window/window.pyproject b/examples/declarative/window/window.pyproject
new file mode 100644
index 000000000..8ce352cd2
--- /dev/null
+++ b/examples/declarative/window/window.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "window.qml", "Splash.qml", "AllScreens.qml", "CurrentScreen.qml"]
+}
diff --git a/examples/declarative/window/window.qml b/examples/declarative/window/window.qml
new file mode 100644
index 000000000..a744cf60f
--- /dev/null
+++ b/examples/declarative/window/window.qml
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt for Python 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
+import QtQuick.Controls
+
+QtObject {
+ id: root
+ property real defaultSpacing: 10
+ property SystemPalette palette: SystemPalette { }
+
+ property var controlWindow: Window {
+ width: col.implicitWidth + root.defaultSpacing * 2
+ height: col.implicitHeight + root.defaultSpacing * 2
+ color: root.palette.window
+ title: "Control Window"
+ Column {
+ id: col
+ anchors.fill: parent
+ anchors.margins: root.defaultSpacing
+ spacing: root.defaultSpacing
+ property real cellWidth: col.width / 3 - spacing
+ Label { text: "Control the second window:" }
+ Grid {
+ id: grid
+ columns: 3
+ spacing: root.defaultSpacing
+ width: parent.width
+ Button {
+ id: showButton
+ width: col.cellWidth
+ text: root.testWindow.visible ? "Hide" : "Show"
+ onClicked: root.testWindow.visible = !root.testWindow.visible
+ }
+ //! [windowedCheckbox]
+ CheckBox {
+ text: "Windowed"
+ height: showButton.height
+ width: col.cellWidth
+ Binding on checked { value: root.testWindow.visibility === Window.Windowed }
+ onClicked: root.testWindow.visibility = Window.Windowed
+ }
+ //! [windowedCheckbox]
+ CheckBox {
+ height: showButton.height
+ width: col.cellWidth
+ text: "Full Screen"
+ Binding on checked { value: root.testWindow.visibility === Window.FullScreen }
+ onClicked: root.testWindow.visibility = Window.FullScreen
+ }
+ Button {
+ id: autoButton
+ width: col.cellWidth
+ text: "Automatic"
+ onClicked: root.testWindow.visibility = Window.AutomaticVisibility
+ }
+ CheckBox {
+ height: autoButton.height
+ text: "Minimized"
+ Binding on checked { value: root.testWindow.visibility === Window.Minimized }
+ onClicked: root.testWindow.visibility = Window.Minimized
+ }
+ CheckBox {
+ height: autoButton.height
+ text: "Maximized"
+ Binding on checked { value: root.testWindow.visibility === Window.Maximized }
+ onClicked: root.testWindow.visibility = Window.Maximized
+ }
+ }
+ function visibilityToString(v) {
+ switch (v) {
+ case Window.Windowed:
+ return "windowed";
+ case Window.Minimized:
+ return "minimized";
+ case Window.Maximized:
+ return "maximized";
+ case Window.FullScreen:
+ return "fullscreen";
+ case Window.AutomaticVisibility:
+ return "automatic";
+ case Window.Hidden:
+ return "hidden";
+ }
+ return "unknown";
+ }
+ Label {
+ id: visibilityLabel
+ text: "second window is " + (root.testWindow.visible ? "visible" : "invisible") +
+ " and has visibility " + parent.visibilityToString(root.testWindow.visibility)
+ }
+ Rectangle {
+ color: root.palette.text
+ width: parent.width
+ height: 1
+ }
+ CurrentScreen { }
+ Rectangle {
+ color: root.palette.text
+ width: parent.width
+ height: 1
+ }
+ AllScreens { width: parent.width }
+ }
+ }
+
+ property var testWindow: Window {
+ width: 320
+ height: 240
+ color: "#215400"
+ title: "Test Window with color " + color
+ flags: Qt.Window | Qt.WindowFullscreenButtonHint
+ Rectangle {
+ anchors.fill: parent
+ anchors.margins: root.defaultSpacing
+ Label {
+ anchors.centerIn: parent
+ text: "Second Window"
+ }
+ MouseArea {
+ anchors.fill: parent
+ onClicked: root.testWindow.color = "#e0c31e"
+ }
+ Button {
+ anchors.right: parent.right
+ anchors.top: parent.top
+ anchors.margins: root.defaultSpacing
+ text: root.testWindow.visibility === Window.FullScreen ? "exit fullscreen" : "go fullscreen"
+ width: 150
+ onClicked: {
+ if (root.testWindow.visibility === Window.FullScreen)
+ root.testWindow.visibility = Window.AutomaticVisibility
+ else
+ root.testWindow.visibility = Window.FullScreen
+ }
+ }
+ Button {
+ anchors.left: parent.left
+ anchors.top: parent.top
+ anchors.margins: root.defaultSpacing
+ text: "X"
+ width: 30
+ onClicked: root.testWindow.close()
+ }
+ }
+ }
+
+ property var splashWindow: Splash {
+ onTimeout: root.controlWindow.visible = true
+ }
+}
diff --git a/examples/declarative/window/window.qrc b/examples/declarative/window/window.qrc
new file mode 100644
index 000000000..89d1de1b1
--- /dev/null
+++ b/examples/declarative/window/window.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/window">
+ <file>window.qml</file>
+ <file>Splash.qml</file>
+ <file>CurrentScreen.qml</file>
+ <file>AllScreens.qml</file>
+ </qresource>
+</RCC>
diff --git a/examples/declarative/window/window_rc.py b/examples/declarative/window/window_rc.py
new file mode 100644
index 000000000..71a65fc44
--- /dev/null
+++ b/examples/declarative/window/window_rc.py
@@ -0,0 +1,328 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 6.5.0
+# WARNING! All changes made in this file will be lost!
+
+from PySide6 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x04\xe8\
+/\
+/ Copyright (C) \
+2021 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick\x0aim\
+port QtQuick.Con\
+trols\x0a\x0aColumn {\x0a\
+ id: root\x0a \
+ spacing: 8\x0a\x0a \
+ Label {\x0a \
+ text: \x22Total nu\
+mber of screens:\
+ \x22 + screenInfo.\
+count\x0a fo\
+nt.bold: true\x0a \
+ }\x0a\x0a Flow {\x0a\
+ spacing:\
+ 12\x0a widt\
+h: parent.width\x0a\
+\x0a Repeate\
+r {\x0a \
+id: screenInfo\x0a \
+ model\
+: (Qt.applicatio\
+n as Application\
+).screens\x0a \
+ Label {\x0a \
+ re\
+quired property \
+string name\x0a \
+ requ\
+ired property in\
+t virtualX\x0a \
+ requi\
+red property int\
+ virtualY\x0a \
+ requir\
+ed property var \
+modelData // avo\
+id shadowing Lab\
+el.width and hei\
+ght\x0a\x0a \
+ lineHeight:\
+ 1.5\x0a \
+ text: name \
++ \x22\x5cn\x22 + virtual\
+X + \x22, \x22 + virtu\
+alY + \x22 \x22 + mode\
+lData.width + \x22x\
+\x22 + modelData.he\
+ight\x0a \
+ }\x0a }\x0a \
+ }\x0a\x0a Componen\
+t.onCompleted: {\
+\x0a var scr\
+eens = (Qt.appli\
+cation as Applic\
+ation).screens;\x0a\
+ for (var\
+ i = 0; i < scre\
+ens.length; ++i)\
+\x0a con\
+sole.log(\x22screen\
+ \x22 + screens[i].\
+name + \x22 has geo\
+metry \x22 +\x0a \
+ \
+ screens[i].vir\
+tualX + \x22, \x22 + s\
+creens[i].virtua\
+lY + \x22 \x22 +\x0a \
+ \
+ screens[i].wi\
+dth + \x22x\x22 + scre\
+ens[i].height)\x0a \
+ }\x0a}\x0a\
+\x00\x00\x04\x8e\
+\x00\
+\x00\x16\x10x\x9c\xcdXKo\xdb8\x10\xbe\xfbW\xb0\
+\xdaK\xb2\x85\xdf\xed\xc5E\xb0H\x5ctS E\x9b\
+8h\x0a,\xf6\xa0Hc\x8b\x1bZ4H*v6\
+\x9b\xff\xbe#\x91\xd4\xc3\xa2d\xa7q\xb7\xcb\x8b%r\
+\xf8q\xe6\x9b\x878\xee\xf7\xc9\x94\xaf\x1e\x04]D\x8a\
+\x1cM\x8f\xc9h0\x1a\x92\xeb\x08\xc8\xa5\xc2\x95\xe5\xca\
+\x8f\x1f\xc8\x85\x0a{\x9d~\x9f\xcc\xbe\xbc\xff\xd6\xbd\xa0\
+\x01\xc4\x12\xba\x1fC\x88\x15\x9dS\x10\x13b\xe6\xae`\
+\xde\xbdT]\xdc\xb6\x04\x11P\x9f\x91\xcfW\xe4l\xf6\
+\xbe;\xeeN\x99\x9fH\xe8t\xe8r\xc5\x85B\xf0\xcb\
+\x84\x06w[\xaf\xbd)\x8f\x95\xe0Lv:\x97\xea\xf3\
+\xed_\x10(\xf2\xd8!8h8!\x82s\x95\xbd\xac\
+\x04_\x81P\x0fD\x00\x1e\x11\xc2\xdcO\x98\x9a\xad\xfc\
+\x80\xc6\x8b\x09\x19\x0e\xaaB\xb3\x07\xa9`\xf9\xc5g\xa0\
+\x14\x90\x95\xfe\x9dlM?\x92\xa7Nu\xdb\xbd/H\
+\xa0\xd5\xb9\xa1q\xc8\xd7\x13\xa2\x7f\x8dF\xe9X\xd3P\
+E\x13\x14c=4\x84\xd1\x80\xaa\x9bt\x8a\xbc\xce\x94\
+\xedUU#\xbf\x92Q\xbe5\x82\x94\xf1\xea\xde\xf3l\
+n\x8f\xcd\xb8\x89\x0bMH\xcf\x18\xd4[g\xca\xe5\x22\
+\x8a*\x86Vz\x86Q\xa3\xbb\x97\xafO9K\x96q\
+\xc9\x16\xcb2bW\xe6\xfc8\x88\xb8\x90\xbd9el\
+\x82\xf4\x09\xf4\xbaS`\xe9\x8b\x05\x8d\xe5\xc4\xa5}e\
+\x83\xb4\x9e\xda%X\xf5s\x00\x8c\xdd\x14\x84g\xdc\x93\
+>\x19\x93\xaeE\xacl\xbe\xf0o\x81\xa1_\x15lT\
+\x89\x07\x85\x91-\x01\x1d\x1b\x12\xcd\xd8\xc4C\xd7\x977\
+\xfe.h\xb8\xc5\x8b\xe5f\x81K\xb5\x85 c\x12\xed\
+\x1e\xd7\x96\xf6\xb64\x1d&\x984\xc3\xda\xbc\x9a\xccY\
+\xa2\x14\xdf\xf6ZYC\x19\xf1\xb5\x16r\x8a\x94\x026\
+\xa7\xd3)\xa8Y\xcb\xd4V \x95\x8e\x9e\xde=\x95\xf4\
+\x96\x01\xf9\x8dx\xe74\x04\x8f \xb1\xb3\xa8\x1cV\xe5\
+\xc1\xe3)\x86\xf5\x1d\x84\xcd@'\xe4U\xc3R\x0d\xf1\
+\xa96\xd3\xef\xbf\x22\x7fh'B8\x8d \xb8\xbb\xe5\
+\x9b?kb\xd9\xca\x19\xdf4\xb0f\xe2\xe3\xc6\xe0\xb8\
+M\xb1\xd9Z\xd0\xdb\xd3S/c\xf9\x0c\x0fMs\x1b\
+]\x1a\xa4Z\x02\x06\x1e\x16\x1e\x96@\x03e\x94QL\
+\x87\x93\x93\x13\x93\xcf=\xab\xb6\x83\x9et\xecr\x81\xc1\
+\xdbF\xfb\xcf\xc8\xffA\xbc\x1a\x9f~H\x18#\xb3@\
+\x00\xc4n\xb7\xbe\x9c\xff\xf4\x08}\xc2a<P\xe0\xed\
+\xe1\x83\x9d\xd5\xc0O\x14?\x5c5\xf0N\x11n\xe9+\
+\x1a|_\xbeo\x99\x9a\xa3}\xcd\x17\xf7\xb0y\xcf\x80\
+*,o\x0b(c\xd7'\x1a\xd3%\xfd\xbb)\xf9_\
+\x1e%\xf9\x01\x87\x09\x92\x1c\xeeg\xf1\xe5o~0_\
+\xf6\x80\x03\xf1e\xe1v\xf0U}\x9b'q\xa0(\x1a\
+Q@^\xf3\x99\x12h\xda\xd1\xfd\xb1\x83O\xb9\xa6*\
+\x88\x88{1\xf0%l\x97\xd9\x89\xd38\x01*\x111\
+\xf1lq\xf5\xde\xb5\x82\xe5\xc1\xd0\x8e\xb6\xccc|\x07\
+\x9c\xe5j\x07\x5c\x1e\x02\xedpE=k\xc7\x9b\xa3\x9c\
+\xd4\x95\xba\x1d\xd0Q5\xda\x91\xfd\xbch\xb5\x03\xe3\x85\
+&\xdc\xa5e\x94\xc98\x80\xeaaj\xb7$\xf1]\xcc\
+\xd7\xdb{\xaa\xf2\xe6\xaa\xea\xbcr\x16\xc1\x97I\xd5d\
+LJV\xae\xb4\x84J\xe2a\x1bq\xd4r\x7f3\x8f\
+\xd9\x15\x8e\xc6\xf6\xed\x98\xbcv\x12@\x10\xcfG\xfc\xc8\
+\x97%\x8d\xb2C\xcc}\xd5\x91$\xcd\xa9y\xdcB\xc6\
+\x156}~\xbc@-\x1dI\xe4\xe8{R\x02\xbe\xeb\
+.mK\xdf\xb0E\x99i\x22R\x04\xf3\x85\x7f\xfc?\
+\xabzj\x13M\xa2\x9e\x0e\xd0\x92\xb8~r5\xbc\x85\
+\xb7\x9a\xbb\xdd\xf1hP\xebbGo\x8a9c\xb9\xf7\
+\xcbh\xf8\xf6\xcd`P|#lKz\x8d\x87Xt\
+,\x99\x91\xde\x91\x05S\xf6\x94o\x983\x7f\x81}\xd5\
+\xa52\x15\x93\xfcS<\x7f\xc8\x0b\x86\xfel\x9d\xd3R\
+[\xda\xe4\x98\xc3\xf7\xb2M\xa9k\x81\x02<\x01\xc4\xc7\
+\xd8yZF\x8a\xce\xdf\x99\xce\xdf\xed.\xbd\xee\xe6O\
+<\x91p\x8a\x0dq\xcb\xa1\x8d\xe6\xa5\xa3\xe5\xdb\xa9\xfd\
+p\x82\xae\x83A0\x1eB\x9b\x1e\x8dwO\xab\x84\xd0\
+\x91aBP8\xef\x14VV\xf1U.\x89\xcf\x8dr\
+{\xbb\xa5`\xf6\xd9\xd7x\xac\x8d\xb0\xa1\x8a\x94\xbeH\
+i\x8d\x5c\xf0\xf2LS\x16\x0f\xdf\x0e\xda\x08o\xb8\xa9\
+\xcf\x1b*u\x8b\x9a\xc7N\xa4t\x1c\xea\xea\x9d\x0e`\
+\xb2\xde\x88?\xe7\xa0\xbd\xdb\x99g\x06\x17\x83y\x11[\
+\xe9\xcb\xcf\x08-\xef[c\x1c\x8c[\xc3\xa0\x96w\x8c\
+K8j\xfa(6Wk\xb9b\xbe\x8cl\xbd\x9ee\
+o%\xd2x|M\x97\xc0\x13\x9b\x05\x95\x7f3K\x7f\
+\xc1(\x91\x809\xe3\xa9\xf3/I\x8e\xfe,\
+\x00\x00\x03\xfa\
+/\
+/ Copyright (C) \
+2021 The Qt Comp\
+any Ltd.\x0a// SPDX\
+-License-Identif\
+ier: LicenseRef-\
+Qt-Commercial OR\
+ BSD-3-Clause\x0a\x0ai\
+mport QtQuick\x0aim\
+port shared\x0a\x0a//!\
+ [splash-propert\
+ies]\x0aWindow {\x0a \
+ id: splash\x0a \
+ color: \x22transpa\
+rent\x22\x0a title:\
+ \x22Splash Window\x22\
+\x0a modality: Q\
+t.ApplicationMod\
+al\x0a flags: Qt\
+.SplashScreen\x0a \
+ property int t\
+imeoutInterval: \
+2000\x0a signal \
+timeout\x0a//! [spl\
+ash-properties]\x0a\
+//! [screen-prop\
+erties]\x0a x: (\
+Screen.width - s\
+plashImage.width\
+) / 2\x0a y: (Sc\
+reen.height - sp\
+lashImage.height\
+) / 2\x0a//! [scree\
+n-properties]\x0a \
+ width: splashI\
+mage.width\x0a h\
+eight: splashIma\
+ge.height\x0a\x0a I\
+mage {\x0a i\
+d: splashImage\x0a \
+ source: I\
+mages.qtLogo\x0a \
+ MouseArea {\
+\x0a anc\
+hors.fill: paren\
+t\x0a on\
+Clicked: Qt.quit\
+()\x0a }\x0a \
+ }\x0a //! [time\
+r]\x0a Timer {\x0a \
+ interval:\
+ splash.timeoutI\
+nterval; running\
+: true; repeat: \
+false\x0a on\
+Triggered: {\x0a \
+ splash.\
+visible = false\x0a\
+ spla\
+sh.timeout()\x0a \
+ }\x0a }\x0a \
+ //! [timer]\x0a \
+ Component.onCom\
+pleted: visible \
+= true\x0a}\x0a\
+\x00\x00\x02\xff\
+\x00\
+\x00\x0adx\x9c\xadV\xdfo\xda0\x10~\xcf_q\
+\xcb\x13l#\x01\xd6MS\xfa0mT[+\xa1\xb5\
+\x85J\xeb\xb4\xee\xc1$\x07XM\xec\xc8q(h\xe2\
+\x7f\x9f\x9d_8\x90\x12\xaa-O\xb9\xf3w\xf7}\xf1\
+\x9d}q]\x18\xf1x#\xe8b)\xa13\xea\xc2\xb0\
+?\x1c\xc0\xdd\x12\xe1V\xaa\x95(&l\x03c\x198\
+\x96\xeb\xc2\xf4\xe6\xe2\xbe7\xa6>\xb2\x04{W\x012\
+I\xe7\x14\x85\x07\x85o\x82\xf3\xde\xad\xec\xa9\xb0\x08\x85\
+OI\x08\xd7\x13\xf82\xbd\xe8\xbd\xeb\x8dB\x92&h\
+Y4\x8a\xb9\x90*\xf9mJ\xfd\xc7=\xd3\x19q&\
+\x05\x0f\x13\xcb\xba\x92\x18\xc1\x1f\x0b\xd4C\x03\x0f\x04\xe7\
+23\x9eh \x97\x1e\x9c\xf5\xfb\x99\xb9D-\xdc\x83\
+X\xf0\x18\x85\xdc|\x134pT\xd2\x90\xfaT^f\
+\x8b\xf0\x06\x06\x1f\xac\x0c=O\x99/)g\xc0\x05U\
+\xe2\x89~\xbf\xe3S)([tx\xb7\xe0\xd3O\xf2\
+D\xa5\xbf\x84\xba\xd3'\x89\xde\x16\xe7F\xd0\x88\x88\xcd\
+\xf5.\x89Wa\xf4#P\xa6\x82\x81\x1d\xe78\xfb\xfc\
+0\x83\xfahA\xa8lOQ\x00\x1br\x8c\x09\x0b\x12\
+\x9f\xc4\xd8\x9a$,\x91\x0dY\xae\xd8J\xed\x1b\x06'\
++\xa2E\x00\x1c\x91V&=]b\x95\xb5I\xeb\xd6\
+\xda\x87\xa7\xec\x91\xf1'V`\xb6yuu\xed\x8dj\
+\xe9\xb61\xdbb\xa7\x92\x87i\xc4\x12\x0f\x86\xbbr\xc7\
+\xc4W=\xe0\xc1\xc7\xca\xb5\xf6Jo\xe5\xda\xec\x5c\x95\
+\xcfu_\xc1\xaf\xc4\x17\x88\xecw\xe5\x1c\x93\x19\x86\x86\
+\x14\xfdH\x5c\xab>\xb5\xa7\x19\x14\x1el[\xf5en\
+8\x8cD\xa8,\xfb\xc1\xf6\xecZ\xcc\x5c\x1d\x07g\xc6\
+C\xf5%R\xa4\xd8\xb0!\xf91)O\xc5\xe0\xbc:\
+\x10\x03\xd8*m\x99^\x14\xd6\xbe\xb2RMDX:\
+'\xbe\xdaT\x14\xb6\x91\xb6\x0e+d\x9a`\xf8\xd4\xe8\
+\xf5v\xa5)\xab\xd2\xc4\xca\x03\x0c\xdb\xe94\xca\xe0\xc9\
+\xcc\xd3\x08\x12\x14\xfa\xf2ai4;\xe1\xbbr\xf4\xf7\
+\x0c\xbc\xe3\xabyO\xa3\x0dh\xa4nA\xd5\xe3I+\
+gV0]\xf3\xb5\xd1\x07y\xed\x8e\x10\xc4t\xad\xcc\
+@\x93\xc8M+G\x86\xbe\xc8\xc1\x8e\xe4_\x95\x19t\
+\x86]\xcd\x0a\x01\x97\x89\x1bE\xd0\xd1\xf4\x9d\x86\x00x\
+\x0d\xc3\xf7\xceY\xb71\x902\x7f\xd9=\xb6\x13!_\
+P_U\xe0e\x82\x8b\xa8\x9b\x97\xean\x88\xfb7\xf9\
+\x01\xae\xd4@+\xd4\x0b}m\xb5j\xcfC2\x09\x13\
+\x1d`\x12?ODV\x84\x86d\x16\x22\xac\xa8\x90)\
+\xd1{\x95<J\x1e\x9f\xc0\x97\xe1>\x97\x09~45\
+\xd4>\xe8\xb2\xb5\xc1\xb8\xda<= ){\xb1\xa2\x02\
+\x7f\xafE\xbc\x05CE\xb1\xf0\xf3\x08\xaf1\x8f\x9f\xe7\
+\xd1\xff\x00N\xd3\xe4.x\x8c\xa5\xbc\xd8\x1dC\x84\xb1\
+\xa8\xd7\x8e\x96\xbf\x98\xdb\xf0_T\xc5\x07?\x0b\x87\xe2\
+\x0e1\x95\xc6\x92\xb46g\x9e\x13>\xe8\xab\xa3!\xd0\
+\x97\x84-B4\xc3'\xa5so*\xa9Y\xc8\xd5\xff\
+\x9b-0\xa8\x8f\x9eb\xa24\xdf\x0c\x83~\x0d[\xce\
+\x9c,foHm\xad\xad\xf5\x17o|\x1ar\
+"
+
+qt_resource_name = b"\
+\x00\x06\
+\x07\xe0Kg\
+\x00w\
+\x00i\x00n\x00d\x00o\x00w\
+\x00\x0e\
+\x0ei\x17\x5c\
+\x00A\
+\x00l\x00l\x00S\x00c\x00r\x00e\x00e\x00n\x00s\x00.\x00q\x00m\x00l\
+\x00\x0a\
+\x0bi\x98\xbc\
+\x00w\
+\x00i\x00n\x00d\x00o\x00w\x00.\x00q\x00m\x00l\
+\x00\x0a\
+\x08\x90\x1a|\
+\x00S\
+\x00p\x00l\x00a\x00s\x00h\x00.\x00q\x00m\x00l\
+\x00\x11\
+\x02YG\x1c\
+\x00C\
+\x00u\x00r\x00r\x00e\x00n\x00t\x00S\x00c\x00r\x00e\x00e\x00n\x00.\x00q\x00m\x00l\
+\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00h\x00\x01\x00\x00\x00\x01\x00\x00\x0d|\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x00N\x00\x00\x00\x00\x00\x01\x00\x00\x09~\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x004\x00\x01\x00\x00\x00\x01\x00\x00\x04\xec\
+\x00\x00\x01\x82Y\xad^\x0f\
+\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x82Y\xad^\x0f\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/multimedia/audiooutput/audiooutput.py b/examples/multimedia/audiooutput/audiooutput.py
index 2950a66a0..de1177693 100644
--- a/examples/multimedia/audiooutput/audiooutput.py
+++ b/examples/multimedia/audiooutput/audiooutput.py
@@ -289,7 +289,7 @@ class AudioTest(QMainWindow):
QAudio.StoppedState: "StoppedState",
QAudio.IdleState: "IdleState"}
- @Slot(QAudio.State)
+ @Slot("QAudio::State")
def handle_state_changed(self, state):
state = self.state_map.get(state, 'Unknown')
qWarning(f"state = {state}")
diff --git a/examples/multimedia/player/player.py b/examples/multimedia/player/player.py
index d0bdbb4c1..430b876a7 100644
--- a/examples/multimedia/player/player.py
+++ b/examples/multimedia/player/player.py
@@ -203,6 +203,7 @@ class MainWindow(QMainWindow):
self._playlist_index += 1
self._player.setSource(self._playlist[self._playlist_index])
+ @Slot("QMediaPlayer::PlaybackState")
def update_buttons(self, state):
media_count = len(self._playlist)
self._play_action.setEnabled(media_count > 0
@@ -215,7 +216,7 @@ class MainWindow(QMainWindow):
def show_status_message(self, message):
self.statusBar().showMessage(message, 5000)
- @Slot(QMediaPlayer.Error, str)
+ @Slot("QMediaPlayer::Error", str)
def _player_error(self, error, error_string):
print(error_string, file=sys.stderr)
self.show_status_message(error_string)
diff --git a/examples/network/googlesuggest/doc/googlesuggest.png b/examples/network/googlesuggest/doc/googlesuggest.png
new file mode 100644
index 000000000..cb2e91d4d
--- /dev/null
+++ b/examples/network/googlesuggest/doc/googlesuggest.png
Binary files differ
diff --git a/examples/network/googlesuggest/doc/googlesuggest.rst b/examples/network/googlesuggest/doc/googlesuggest.rst
new file mode 100644
index 000000000..ada224311
--- /dev/null
+++ b/examples/network/googlesuggest/doc/googlesuggest.rst
@@ -0,0 +1,11 @@
+Google Suggest Example
+======================
+
+Obtains the list of search recommendations by the Google search engine.
+
+The example uses the QNetworkAccessManager to obtain the list of search
+recommendations by Google as the user types into a QLineEdit.
+
+.. image:: googlesuggest.png
+ :width: 502
+ :alt: google suggest program screenshot
diff --git a/examples/network/googlesuggest/googlesuggest.py b/examples/network/googlesuggest/googlesuggest.py
new file mode 100644
index 000000000..cccc2ceec
--- /dev/null
+++ b/examples/network/googlesuggest/googlesuggest.py
@@ -0,0 +1,174 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 typing import List
+
+from PySide6.QtCore import (QByteArray, QEvent, QObject, QPoint, Qt, QTimer,
+ QXmlStreamReader, Slot)
+from PySide6.QtGui import QPalette
+from PySide6.QtNetwork import (QNetworkAccessManager, QNetworkReply,
+ QNetworkRequest)
+from PySide6.QtWidgets import QFrame, QTreeWidget, QTreeWidgetItem
+
+
+class GSuggestCompletion(QObject):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.editor = parent
+ self.popup = QTreeWidget()
+ self.popup.setWindowFlags(Qt.Popup)
+ self.popup.setFocusPolicy(Qt.NoFocus)
+ self.popup.setFocusProxy(parent)
+ self.popup.setMouseTracking(True)
+
+ self.popup.setColumnCount(1)
+ self.popup.setUniformRowHeights(True)
+ self.popup.setRootIsDecorated(False)
+ self.popup.setEditTriggers(QTreeWidget.NoEditTriggers)
+ self.popup.setSelectionBehavior(QTreeWidget.SelectRows)
+ self.popup.setFrameStyle(QFrame.Box | QFrame.Plain)
+ self.popup.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
+ self.popup.header().hide()
+
+ self.popup.installEventFilter(self)
+
+ self.popup.itemClicked.connect(self.done_completion)
+
+ self.timer = QTimer()
+ self.timer.setSingleShot(True)
+ self.timer.setInterval(500)
+ self.timer.timeout.connect(self.auto_suggest)
+ self.editor.textEdited.connect(self.timer.start)
+
+ self.network_manager = QNetworkAccessManager()
+ self.network_manager.finished.connect(self.handle_network_data)
+
+ def eventFilter(self, obj: QObject, ev: QEvent):
+ if obj is not self.popup:
+ return False
+ if ev.type() == QEvent.MouseButtonPress:
+ self.popup.hide()
+ self.editor.setFocus()
+ return True
+
+ if ev.type() == QEvent.KeyPress:
+ consumed = False
+ key = ev.key()
+ if key in (Qt.Key_Enter, Qt.Key_Return):
+ self.done_completion()
+ consumed = True
+ elif key == Qt.Key_Escape:
+ self.editor.setFocus()
+ self.popup.hide()
+ consumed = True
+ elif key in (
+ Qt.Key_Up,
+ Qt.Key_Down,
+ Qt.Key_Home,
+ Qt.Key_End,
+ Qt.Key_PageUp,
+ Qt.Key_PageDown,
+ ):
+ pass
+ else:
+ self.editor.setFocus()
+ self.editor.event(ev)
+ self.popup.hide()
+ return consumed
+ return False
+
+ def show_completion(self, choices: List[str]):
+ if not choices:
+ return
+ pal = self.editor.palette()
+ color = pal.color(QPalette.Disabled, QPalette.WindowText)
+
+ self.popup.setUpdatesEnabled(False)
+ self.popup.clear()
+
+ for choice in choices:
+ item = QTreeWidgetItem(self.popup)
+ item.setText(0, choice)
+ item.setForeground(0, color)
+
+ self.popup.setCurrentItem(self.popup.topLevelItem(0))
+ self.popup.resizeColumnToContents(0)
+ self.popup.setUpdatesEnabled(True)
+
+ self.popup.move(self.editor.mapToGlobal(QPoint(0, self.editor.height())))
+ self.popup.setFocus()
+ self.popup.show()
+
+ @Slot()
+ def done_completion(self):
+ self.timer.stop()
+ self.popup.hide()
+ self.editor.setFocus()
+ item = self.popup.currentItem()
+ if item:
+ self.editor.setText(item.text(0))
+ self.editor.returnPressed.emit()
+
+ @Slot()
+ def auto_suggest(self):
+ s = self.editor.text()
+ url = f"https://google.com/complete/search?output=toolbar&q={s}"
+ self.network_manager.get(QNetworkRequest(url))
+
+ def prevent_suggest(self):
+ self.timer.stop()
+
+ @Slot()
+ def handle_network_data(self, network_reply: QNetworkReply):
+ url = network_reply.url()
+ if network_reply.error() == QNetworkReply.NoError:
+ choices: List[str] = []
+
+ response: QByteArray = network_reply.readAll()
+ xml = QXmlStreamReader(response)
+ while not xml.atEnd():
+ xml.readNext()
+ if xml.tokenType() == QXmlStreamReader.StartElement:
+ if xml.name() == "suggestion":
+ s = xml.attributes().value("data")
+ choices.append(s)
+ self.show_completion(choices)
+
+ network_reply.deleteLater()
diff --git a/examples/network/googlesuggest/googlesuggest.pyproject b/examples/network/googlesuggest/googlesuggest.pyproject
new file mode 100644
index 000000000..477da86ed
--- /dev/null
+++ b/examples/network/googlesuggest/googlesuggest.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "googlesuggest.py", "searchbox.py"]
+}
diff --git a/examples/network/googlesuggest/main.py b/examples/network/googlesuggest/main.py
new file mode 100644
index 000000000..a11705225
--- /dev/null
+++ b/examples/network/googlesuggest/main.py
@@ -0,0 +1,51 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtWidgets import QApplication
+
+from searchbox import SearchBox
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ search_edit = SearchBox()
+ search_edit.show()
+ sys.exit(app.exec())
diff --git a/examples/network/googlesuggest/searchbox.py b/examples/network/googlesuggest/searchbox.py
new file mode 100644
index 000000000..f4b713ca1
--- /dev/null
+++ b/examples/network/googlesuggest/searchbox.py
@@ -0,0 +1,64 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import Slot
+from PySide6.QtGui import QDesktopServices
+from PySide6.QtWidgets import QLineEdit
+
+from googlesuggest import GSuggestCompletion
+
+
+class SearchBox(QLineEdit):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.completer = GSuggestCompletion(self)
+
+ self.returnPressed.connect(self.do_search)
+ self.setWindowTitle("Search with Google")
+
+ self.adjustSize()
+ self.resize(400, self.height())
+ self.setFocus()
+
+ @Slot()
+ def do_search(self):
+ self.completer.prevent_suggest()
+ url = f"https://www.google.com/search?q={self.text()}"
+ QDesktopServices.openUrl(url)
diff --git a/examples/opengl/contextinfo/contextinfo.py b/examples/opengl/contextinfo/contextinfo.py
index a3bab44d8..67a2cd8d1 100644
--- a/examples/opengl/contextinfo/contextinfo.py
+++ b/examples/opengl/contextinfo/contextinfo.py
@@ -47,7 +47,8 @@ import sys
from textwrap import dedent
-from PySide6.QtCore import QCoreApplication, QLibraryInfo, QSize, QTimer, Qt
+from PySide6.QtCore import (QCoreApplication, QLibraryInfo, QSize, QTimer, Qt,
+ Slot)
from PySide6.QtGui import (QMatrix4x4, QOpenGLContext, QSurfaceFormat, QWindow)
from PySide6.QtOpenGL import (QOpenGLBuffer, QOpenGLShader,
QOpenGLShaderProgram, QOpenGLVertexArrayObject)
@@ -230,6 +231,7 @@ class RenderWindow(QWindow):
self.context.swapBuffers(self)
self.context.doneCurrent()
+ @Slot()
def slot_timer(self):
self.render()
self.angle += 1
diff --git a/examples/opengl/hellogl2/hellogl2.py b/examples/opengl/hellogl2/hellogl2.py
index 733cc25ee..3e1c5ac3d 100644
--- a/examples/opengl/hellogl2/hellogl2.py
+++ b/examples/opengl/hellogl2/hellogl2.py
@@ -46,7 +46,8 @@ from argparse import ArgumentParser, RawTextHelpFormatter
import ctypes
import math
import sys
-from PySide6.QtCore import QCoreApplication, Signal, SIGNAL, SLOT, Qt, QSize, QPointF
+from PySide6.QtCore import (QCoreApplication, Signal, Slot,
+ Qt, QSize, QPointF)
from PySide6.QtGui import (QVector3D, QOpenGLFunctions,
QMatrix4x4, QOpenGLContext, QSurfaceFormat, QVector3DList)
from PySide6.QtOpenGL import (QOpenGLVertexArrayObject, QOpenGLBuffer,
@@ -266,6 +267,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions):
angle -= 360 * 16
return angle
+ @Slot(int)
def set_xrotation(self, angle):
angle = self.normalize_angle(angle)
if angle != self._x_rot:
@@ -273,6 +275,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions):
self.x_rotation_changed.emit(angle)
self.update()
+ @Slot(int)
def set_yrotation(self, angle):
angle = self.normalize_angle(angle)
if angle != self._y_rot:
@@ -280,6 +283,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions):
self.y_rotation_changed.emit(angle)
self.update()
+ @Slot(int)
def set_zrotation(self, angle):
angle = self.normalize_angle(angle)
if angle != self._z_rot:
@@ -287,6 +291,7 @@ class GLWidget(QOpenGLWidget, QOpenGLFunctions):
self.z_rotation_changed.emit(angle)
self.update()
+ @Slot()
def cleanup(self):
self.makeCurrent()
self._logo_vbo.destroy()
diff --git a/examples/opengl/threadedqopenglwidget/glwidget.py b/examples/opengl/threadedqopenglwidget/glwidget.py
index bb3ffdf19..d280dd3bc 100644
--- a/examples/opengl/threadedqopenglwidget/glwidget.py
+++ b/examples/opengl/threadedqopenglwidget/glwidget.py
@@ -105,6 +105,7 @@ class GLWidget(QOpenGLWidget):
def on_resized(self):
self._renderer.unlock_renderer()
+ @Slot()
def grab_context(self):
if not self._renderer:
return
diff --git a/examples/quick/painteditem/painteditem.py b/examples/quick/painteditem/painteditem.py
index 5ae58c56f..03c59dc77 100644
--- a/examples/quick/painteditem/painteditem.py
+++ b/examples/quick/painteditem/painteditem.py
@@ -43,11 +43,16 @@ import sys
from PySide6.QtGui import QPainter, QBrush, QColor
from PySide6.QtWidgets import QApplication
-from PySide6.QtQml import qmlRegisterType
+from PySide6.QtQml import QmlElement
from PySide6.QtCore import QUrl, Property, Signal, Qt, QPointF
from PySide6.QtQuick import QQuickPaintedItem, QQuickView
+QML_IMPORT_NAME = "TextBalloonPlugin"
+QML_IMPORT_MAJOR_VERSION = 1
+QML_IMPORT_MINOR_VERSION = 0 # Optional
+
+@QmlElement
class TextBalloon(QQuickPaintedItem):
rightAlignedChanged = Signal()
@@ -97,7 +102,6 @@ if __name__ == "__main__":
app = QApplication(sys.argv)
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
- qmlRegisterType(TextBalloon, "TextBalloonPlugin", 1, 0, "TextBalloon")
qml_file = Path(__file__).parent / "main.qml"
view.setSource(QUrl.fromLocalFile(qml_file))
diff --git a/examples/samplebinding/CMakeLists.txt b/examples/samplebinding/CMakeLists.txt
index 6de44b6ae..665316623 100644
--- a/examples/samplebinding/CMakeLists.txt
+++ b/examples/samplebinding/CMakeLists.txt
@@ -42,7 +42,7 @@ set(generated_sources
# ================================== Shiboken detection ======================================
# Use provided python interpreter if given.
if(NOT python_interpreter)
- if(WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+ if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
find_program(python_interpreter "python_d")
if(NOT python_interpreter)
message(FATAL_ERROR
@@ -173,7 +173,7 @@ set_property(TARGET ${bindings_library} PROPERTY PREFIX "")
set_property(TARGET ${bindings_library} PROPERTY OUTPUT_NAME
"${bindings_library}${PYTHON_EXTENSION_SUFFIX}")
if(WIN32)
- if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set_property(TARGET ${bindings_library} PROPERTY SUFFIX "_d.pyd")
else()
set_property(TARGET ${bindings_library} PROPERTY SUFFIX ".pyd")
diff --git a/examples/scriptableapplication/CMakeLists.txt b/examples/scriptableapplication/CMakeLists.txt
index ff1cda25e..430932815 100644
--- a/examples/scriptableapplication/CMakeLists.txt
+++ b/examples/scriptableapplication/CMakeLists.txt
@@ -18,7 +18,7 @@ find_package(Qt6 COMPONENTS Widgets)
# Use provided python interpreter if given.
if(NOT python_interpreter)
- if(WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+ if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
find_program(python_interpreter "python_d")
if(NOT python_interpreter)
message(FATAL_ERROR
diff --git a/examples/serialport/terminal/console.py b/examples/serialport/terminal/console.py
new file mode 100644
index 000000000..06c54f0e5
--- /dev/null
+++ b/examples/serialport/terminal/console.py
@@ -0,0 +1,86 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import Qt, Signal, Slot
+from PySide6.QtGui import QPalette
+from PySide6.QtWidgets import QPlainTextEdit
+
+
+UNHANDLED_KEYS = [Qt.Key_Backspace, Qt.Key_Left, Qt.Key_Right, Qt.Key_Up,
+ Qt.Key_Down]
+
+
+class Console(QPlainTextEdit):
+
+ get_data = Signal(bytearray)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.m_localEchoEnabled = False
+ self.document().setMaximumBlockCount(100)
+ p = self.palette()
+ p.setColor(QPalette.Base, Qt.black)
+ p.setColor(QPalette.Text, Qt.green)
+ self.setPalette(p)
+
+ @Slot(bytearray)
+ def put_data(self, data):
+ self.insertPlainText(data.decode("utf8"))
+ bar = self.verticalScrollBar()
+ bar.setValue(bar.maximum())
+
+ def set_local_echo_enabled(self, e):
+ self.m_localEchoEnabled = e
+
+ def keyPressEvent(self, e):
+ key = e.key()
+ if key not in UNHANDLED_KEYS:
+ if self.m_localEchoEnabled:
+ super().keyPressEvent(e)
+ self.get_data.emit(e.text().encode())
+
+ def mousePressEvent(self, e):
+ self.setFocus()
+
+ def mouseDoubleClickEvent(self, e):
+ pass
+
+ def contextMenuEvent(self, e):
+ pass
diff --git a/examples/serialport/terminal/doc/terminal.rst b/examples/serialport/terminal/doc/terminal.rst
new file mode 100644
index 000000000..61579121f
--- /dev/null
+++ b/examples/serialport/terminal/doc/terminal.rst
@@ -0,0 +1,9 @@
+Terminal Example
+================
+
+The Terminal Example shows how to create a terminal for a simple serial
+interface by using Qt Serial Port.
+
+It demonstrates the main features of the QSerialPort class, like configuration,
+I/O implementation and so forth. Also, the class QSerialPortInfo is invoked to
+display information about the serial ports available in the system.
diff --git a/examples/serialport/terminal/images/application-exit.png b/examples/serialport/terminal/images/application-exit.png
new file mode 100644
index 000000000..32be6b3f1
--- /dev/null
+++ b/examples/serialport/terminal/images/application-exit.png
Binary files differ
diff --git a/examples/serialport/terminal/images/clear.png b/examples/serialport/terminal/images/clear.png
new file mode 100644
index 000000000..aa612f1f3
--- /dev/null
+++ b/examples/serialport/terminal/images/clear.png
Binary files differ
diff --git a/examples/serialport/terminal/images/connect.png b/examples/serialport/terminal/images/connect.png
new file mode 100644
index 000000000..dd5a51e98
--- /dev/null
+++ b/examples/serialport/terminal/images/connect.png
Binary files differ
diff --git a/examples/serialport/terminal/images/disconnect.png b/examples/serialport/terminal/images/disconnect.png
new file mode 100644
index 000000000..fd58f7a48
--- /dev/null
+++ b/examples/serialport/terminal/images/disconnect.png
Binary files differ
diff --git a/examples/serialport/terminal/images/settings.png b/examples/serialport/terminal/images/settings.png
new file mode 100644
index 000000000..3d1042e26
--- /dev/null
+++ b/examples/serialport/terminal/images/settings.png
Binary files differ
diff --git a/examples/serialport/terminal/main.py b/examples/serialport/terminal/main.py
new file mode 100644
index 000000000..2c6ad739e
--- /dev/null
+++ b/examples/serialport/terminal/main.py
@@ -0,0 +1,54 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtWidgets import QApplication
+
+from mainwindow import MainWindow
+
+"""PySide6 port of the serialport/terminal example from Qt v6.x"""
+
+
+if __name__ == "__main__":
+ a = QApplication(sys.argv)
+ w = MainWindow()
+ w.show()
+ sys.exit(a.exec())
diff --git a/examples/serialport/terminal/mainwindow.py b/examples/serialport/terminal/mainwindow.py
new file mode 100644
index 000000000..5c985582d
--- /dev/null
+++ b/examples/serialport/terminal/mainwindow.py
@@ -0,0 +1,145 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import QIODeviceBase, Slot
+from PySide6.QtWidgets import QLabel, QMainWindow, QMessageBox
+from PySide6.QtSerialPort import QSerialPort
+
+from ui_mainwindow import Ui_MainWindow
+from console import Console
+from settingsdialog import SettingsDialog
+
+
+HELP = """The <b>Simple Terminal</b> example demonstrates how to
+ use the Qt Serial Port module in modern GUI applications
+ using Qt, with a menu bar, toolbars, and a status bar."""
+
+
+def description(s):
+ return (f"Connected to {s.name} : {s.string_baud_rate}, "
+ f"{s.string_data_bits}, {s.string_parity}, {s.string_stop_bits}, "
+ f"{s.string_flow_control}")
+
+
+class MainWindow(QMainWindow):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.m_ui = Ui_MainWindow()
+ self.m_status = QLabel()
+ self.m_console = Console()
+ self.m_settings = SettingsDialog(self)
+ self.m_serial = QSerialPort(self)
+ self.m_ui.setupUi(self)
+ self.m_console.setEnabled(False)
+ self.setCentralWidget(self.m_console)
+
+ self.m_ui.actionConnect.setEnabled(True)
+ self.m_ui.actionDisconnect.setEnabled(False)
+ self.m_ui.actionQuit.setEnabled(True)
+ self.m_ui.actionConfigure.setEnabled(True)
+
+ self.m_ui.statusBar.addWidget(self.m_status)
+
+ self.m_ui.actionConnect.triggered.connect(self.open_serial_port)
+ self.m_ui.actionDisconnect.triggered.connect(self.close_serial_port)
+ self.m_ui.actionQuit.triggered.connect(self.close)
+ self.m_ui.actionConfigure.triggered.connect(self.m_settings.show)
+ self.m_ui.actionClear.triggered.connect(self.m_console.clear)
+ self.m_ui.actionAbout.triggered.connect(self.about)
+ self.m_ui.actionAboutQt.triggered.connect(qApp.aboutQt)
+
+ self.m_serial.errorOccurred.connect(self.handle_error)
+ self.m_serial.readyRead.connect(self.read_data)
+ self.m_console.get_data.connect(self.write_data)
+
+ @Slot()
+ def open_serial_port(self):
+ s = self.m_settings.settings()
+ self.m_serial.setPortName(s.name)
+ self.m_serial.setBaudRate(s.baud_rate)
+ self.m_serial.setDataBits(s.data_bits)
+ self.m_serial.setParity(s.parity)
+ self.m_serial.setStopBits(s.stop_bits)
+ self.m_serial.setFlowControl(s.flow_control)
+ if self.m_serial.open(QIODeviceBase.ReadWrite):
+ self.m_console.setEnabled(True)
+ self.m_console.set_local_echo_enabled(s.local_echo_enabled)
+ self.m_ui.actionConnect.setEnabled(False)
+ self.m_ui.actionDisconnect.setEnabled(True)
+ self.m_ui.actionConfigure.setEnabled(False)
+ self.show_status_message(description(s))
+ else:
+ QMessageBox.critical(self, "Error", self.m_serial.errorString())
+ self.show_status_message("Open error")
+
+ @Slot()
+ def close_serial_port(self):
+ if self.m_serial.isOpen():
+ self.m_serial.close()
+ self.m_console.setEnabled(False)
+ self.m_ui.actionConnect.setEnabled(True)
+ self.m_ui.actionDisconnect.setEnabled(False)
+ self.m_ui.actionConfigure.setEnabled(True)
+ self.show_status_message("Disconnected")
+
+ @Slot()
+ def about(self):
+ QMessageBox.about(self, "About Simple Terminal", HELP)
+
+ @Slot(bytearray)
+ def write_data(self, data):
+ self.m_serial.write(data)
+
+ @Slot()
+ def read_data(self):
+ data = self.m_serial.readAll()
+ self.m_console.put_data(data.data())
+
+ @Slot(QSerialPort.SerialPortError)
+ def handle_error(self, error):
+ if error == QSerialPort.ResourceError:
+ QMessageBox.critical(self, "Critical Error",
+ self.m_serial.errorString())
+ self.close_serial_port()
+
+ @Slot(str)
+ def show_status_message(self, message):
+ self.m_status.setText(message)
diff --git a/examples/serialport/terminal/mainwindow.ui b/examples/serialport/terminal/mainwindow.ui
new file mode 100644
index 000000000..452fdd537
--- /dev/null
+++ b/examples/serialport/terminal/mainwindow.ui
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Simple Terminal</string>
+ </property>
+ <widget class="QWidget" name="centralWidget">
+ <layout class="QVBoxLayout" name="verticalLayout"/>
+ </widget>
+ <widget class="QMenuBar" name="menuBar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>19</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuCalls">
+ <property name="title">
+ <string>Calls</string>
+ </property>
+ <addaction name="actionConnect"/>
+ <addaction name="actionDisconnect"/>
+ <addaction name="separator"/>
+ <addaction name="actionQuit"/>
+ </widget>
+ <widget class="QMenu" name="menuTools">
+ <property name="title">
+ <string>Tools</string>
+ </property>
+ <addaction name="actionConfigure"/>
+ <addaction name="actionClear"/>
+ </widget>
+ <widget class="QMenu" name="menuHelp">
+ <property name="title">
+ <string>Help</string>
+ </property>
+ <addaction name="actionAbout"/>
+ <addaction name="actionAboutQt"/>
+ </widget>
+ <addaction name="menuCalls"/>
+ <addaction name="menuTools"/>
+ <addaction name="menuHelp"/>
+ </widget>
+ <widget class="QToolBar" name="mainToolBar">
+ <attribute name="toolBarArea">
+ <enum>TopToolBarArea</enum>
+ </attribute>
+ <attribute name="toolBarBreak">
+ <bool>false</bool>
+ </attribute>
+ <addaction name="actionConnect"/>
+ <addaction name="actionDisconnect"/>
+ <addaction name="actionConfigure"/>
+ <addaction name="actionClear"/>
+ </widget>
+ <widget class="QStatusBar" name="statusBar"/>
+ <action name="actionAbout">
+ <property name="text">
+ <string>&amp;About</string>
+ </property>
+ <property name="toolTip">
+ <string>About program</string>
+ </property>
+ <property name="shortcut">
+ <string>Alt+A</string>
+ </property>
+ </action>
+ <action name="actionAboutQt">
+ <property name="text">
+ <string>About Qt</string>
+ </property>
+ </action>
+ <action name="actionConnect">
+ <property name="icon">
+ <iconset resource="terminal.qrc">
+ <normaloff>:/images/connect.png</normaloff>:/images/connect.png</iconset>
+ </property>
+ <property name="text">
+ <string>C&amp;onnect</string>
+ </property>
+ <property name="toolTip">
+ <string>Connect to serial port</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+O</string>
+ </property>
+ </action>
+ <action name="actionDisconnect">
+ <property name="icon">
+ <iconset resource="terminal.qrc">
+ <normaloff>:/images/disconnect.png</normaloff>:/images/disconnect.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Disconnect</string>
+ </property>
+ <property name="toolTip">
+ <string>Disconnect from serial port</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+D</string>
+ </property>
+ </action>
+ <action name="actionConfigure">
+ <property name="icon">
+ <iconset resource="terminal.qrc">
+ <normaloff>:/images/settings.png</normaloff>:/images/settings.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Configure</string>
+ </property>
+ <property name="toolTip">
+ <string>Configure serial port</string>
+ </property>
+ <property name="shortcut">
+ <string>Alt+C</string>
+ </property>
+ </action>
+ <action name="actionClear">
+ <property name="icon">
+ <iconset resource="terminal.qrc">
+ <normaloff>:/images/clear.png</normaloff>:/images/clear.png</iconset>
+ </property>
+ <property name="text">
+ <string>C&amp;lear</string>
+ </property>
+ <property name="toolTip">
+ <string>Clear data</string>
+ </property>
+ <property name="shortcut">
+ <string>Alt+L</string>
+ </property>
+ </action>
+ <action name="actionQuit">
+ <property name="icon">
+ <iconset resource="terminal.qrc">
+ <normaloff>:/images/application-exit.png</normaloff>:/images/application-exit.png</iconset>
+ </property>
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ <property name="shortcut">
+ <string>Ctrl+Q</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources>
+ <include location="terminal.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/examples/serialport/terminal/rc_terminal.py b/examples/serialport/terminal/rc_terminal.py
new file mode 100644
index 000000000..cb3624e21
--- /dev/null
+++ b/examples/serialport/terminal/rc_terminal.py
@@ -0,0 +1,4464 @@
+# Resource object code (Python 3)
+# Created by: object code
+# Created by: The Resource Compiler for Qt version 6.4.0
+# WARNING! All changes made in this file will be lost!
+
+from PySide6 import QtCore
+
+qt_resource_data = b"\
+\x00\x000\xff\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\
+\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\
+\x00\x00\x00\x09pHYs\x00\x00$\xe9\x00\x00$\xe9\
+\x01P$\xe7\xf8\x00\x00\x00\x19tEXtSof\
+tware\x00www.inksca\
+pe.org\x9b\xee<\x1a\x00\x00 \x00ID\
+ATx\x9c\xed\x9dy\x9c\x1dGu\xef\xbf\xd5\xddw\
+\x9f}\xd7\xbe\xcb\xb2\xe5\x1d\x8c\x17\x0161<\x88m\
+\xc2#\x80Cp\x82\x8c\xc3#$\x84\x80\x09\xe4\x85-\
+` \x04L\x02\x0e\x09Kx\x01,\x03q\x1e6y\
+\x1f\xcc\x92\x18\x8cc\x1b\x8f\xf7\xdd\xb2e\xcb\xb2\xd6\xd1\
+H\x9a}\xe6\xae\xbdT\xd5\xfb\xa3\xfa\xf6\xbd3sg\
+\xd1\x8cF\x92\xc9\xfc\xf4iMo\xb7\x97:\xbf>\xe7\
+\xd4\xa9SUBk\xcd\x22\xfe\xfb\xc2:\xd1\x0f\xb0\x88\
+\x13\x0b\xe7X_\xf0\xabW\x89\x0dJ\xdb\x17\x83nG\
+\x8b\x17\x84\x90;S9v\xbd\xe76]8\xd6\xf7Z\
+\xc4\xfc!\x8e\x85\x09\xf8\xea;\xc4+5\xd6\xfb4\x5c\
+\x0c,\xa9q\x8a\x06\x9e\xd1\x88\xcf^{\xb3\xbc\x85E\
+\xbbs\xd2`^\x04\xb8\xee:a5\xee\xb4\xfe\x1a\xcd\
+'\x00{\x96?{B\x09\xf1\xf1\x0f\xfd \xf8\xf9\x9c\
+o\xbc\x88c\x86y\x11\xe0\x86w\xd8\x9f\x03>^\xde\
+N&bt._M\xe7\xb2\x8d\xd4\xb5,\xc7s]\
+\x0a\xb9\x11rc\xc3\xec\xdb\xf98nq,\xfa\xad\x16\
+|\xf5\xda\x1f\xc8\x0f\xcc\xeb\xe9\x171o\xcc\x99\x007\
+\xbc\xdd\xf9m,\xfd3@\xd8B\xb0q\xd3\x06\xd6\x9e\
+\xfd\xdb\x08\xab\xb6[\xe1y>\xbb\xb6w\xb3\xfb\xb9\xc7\
+ \xbc\xa7\x10\xfc\xd5\x07~ \xbf8\xd7\x87_\xc4\xfc\
+1w\x02\xbc\xc3\xfa%\x88\xd7\x02\x9cy\xd6\xd9\xac\xdc\
+\xfc\x1a\x10\x16\xc5\xdc(={w0:\xd8\x8be\xd9\
+t.\xdf\xc0\xd2\xd5\xa7\x22\x84\x00`\xb4\xff \xdd\xbf\
+\xba\x05%%\x80\x16B\x5c\xfd\x81\x1f\x047\x1d\xab\x17\
+Z\xc4\xd1aN\x04\xf8\xd2\x95\xa2+\xe6X=\x80\xbd\
+|\xed\x19\x9c}\xe1\xff\x00\xa0w\xdf\xf3<q\xdf\xcf\
+QJ\x8d;?\x93\xcep\xe1\xeb\xdfA2\xdd\x00\xc0\
+\xe1\xbdO\xf1h\xf7/\x09\xef\xec+\xad\xd6}\xe8f\
+}`^o\xb2\x889aNq\x80\x98c\xbd\x9d\xd0\
+\xe9[u\xca\xb9\x00\x8c\x0e\x1d\xe6\xb1\xee\x9fU\x84\x1f\
+~\xf1\x00\xf9B\x9e\x07n\xbf\x09\xe5\xbb\x00t\xad>\
+\x93SN=#\xba\x9c\x10\xd6\xfb\xe7\xf6\xf8\x8b\x98/\
+\xe6\x18\x08\x12\xbf\x0f\x90nh\xa3\xb1\xa9\x0d\x80\x1d\x8f\
+\xfe*\xb2\xed\xafz\xc7\x17y\xff\x8dy\xae\xfe\xf2s\
+t\xad{\x05\x00\xb9\x82\xcb\xfe'\x7f\x0a\xe1w\xbf\xf6\
+\xcc\xd7\x90L\xa6\xcc\xd5\xe0\x7f\xfd\xdd;Ef>/\
+\xb2\x88\xb9a\x8e\x04\xd0\xab\x00:\x96o\xc4\x0a\xaf0\
+6<\x00@\xfb\xaa\xb3x\xd9\x15\x1f\xc6\x8e%h\xea\
+\xda\xc0%[o\x88~5\xd8\x7f\x88\xdc\xa1\xa7\xcc\x8d\
+\x9d\x18k7\x9dY>\xd4\xe4\xf8\xd6\xd5s{\x96E\
+\xcc\x07s\x0d\x05[\x00\xb6\x1d\x8bvHiT\xbf\xe5\
+\xc4\xc7\x9d\xa8\xa9\xf8\x18\x02\x0c\x01\xb4\x04`\xc5\xba\xb3\
+\xb1-\xbb|\xf0\xcf#Oq\x11\xc7\x0d\xf3\x22@\xe0\
+U\xa2\xbbu\x99$\x00Gv?\xc2\x8e_\x7f\x0f\x00\
+\xaf\x94\xe5\x81[?\x1d\x9d\x93J\xd8(\xbfDa\xe0\
+E\x00b\xc9:V\xac\xddX>\xbc\xf1\x1f\xae\xb2/\
+\x9f\xe3\xf3,b\x8e\x98'\x01\xf2\xd1\x8eeK\xc2\x08\
+\xb0\xd6\xdc\xfe\x8d\xab\xf9\xd6{\x97\xf0\xad?\xeeb\xdf\
+S\xbf\x04 \x19\xb7i\xc8\x98\x18A\xfe\xf0\xd3\xe1\xaf\
+4\xab7\x9e\x1d]Ci\xf5\xc19>\xcf\x22\xe6\x88\
+\xb9\x12`\x00`t\xb0\xbf\xec\xd3\xb1t\xfd9,k\
+KF'\x14\xc6\xfa\x08\xfc\x12\x00\xf1\x98\xc5\xda\xae$\
+e\xfd\xee\x17\x86pG{\xd0J\x92\xaeo\xa5\xa3\xd3\
+\x90Ghq\xe9W\xfe@\x9c\xc1\x22\x8e\x1b\xe6F\x00\
+\xcd\xbf\x03\xe4\xc6\xfa\x19\x19<\x04@\xb2y%K;\
+[\xd8\xb4\x22CkC\x8c\xba\xa4C]\xcaaY[\
+\x92M\xcb3$\xe3\xe3\x9b\x0ar\x87\x9eF+\x09J\
+\xb2zcE\xe6BY\x8bZ\xe08bN\x04\xd0\xa8\
+[\xcb\xeb=/>\x19\xae\x09\xea\x96\x9cE:a\xb3\
+\xaa#\xc5\xc6\xe5i6.K\xd3\xd9\x14\xc7\xb1'\xfb\
+v\xeeh\x0fAa\x08\xad\x02Z\xda\x96QWW_\
+>t\xd5\xdf\xbdSt\xcc\xe5\xb9\x16q\xf4\x98\x13\x01\
+\xae\xbdY?\x02\xec\x05\xd8\xbf\xe79\xdc\xa2\xf1\x052\
+\x9d\xa7\x91h\x5c>\xeb\xeb\xe4\xfb\x9eC\xab\x00\xad5\
+\xab\xd7o*\xefN\xc4\x02\xeb\xbdsy\xaeE\x1c=\
+\xe6\x9c\x11\xa45_\x05PR\xf2\xe4\x03\xbf\x88|\x81\
+\xe6u\x97`\xc5\x92\xd3\xfd4Bix\x0f2(\xa1\
+U@\xe7\x92\xd5\xc4b\xa6Z\xa9\xe1O\xaf\xbbR\xc4\
+g\xf8\xf9\x22\x8e\x01\xe6L\x80k\xffM\xdd\x00\xfaN\
+\x80\xbe\xde\xdd\xec\xdd\xf9\xb8\xb9`,E\xd3\x9aW\xcf\
+\xea\x1aZIJ\x83\xbb\xd1*\xc0\xb2\x04+V\xad.\
+\x1f\xealp\xec\xdf\x9f\xeb\xb3-b\xf6\x98{N\xa0\
+\xd6Z\x07\xfa\x9d\xc00\xc03\x8f\xddMvd\x10\x80\
+d\xf3*2\x1d\xa7\xce\xea2\xc5!C\x00\xad\x02\x96\
+._\x13\xed\x17\xe8Eg\xf08`^I\xa1\xd7\xfe\
+P\x1fD\x8b\xf7\x80\xf9\x9a\x1f\xbb\xf7g(i\x84Y\
+\xbf\xfce8\xc9\xc6\x19\xaf\xa1\x02\x17w\xac\x17\xad$\
+\xf1X\x9c\xae\xae\xae\xf2\xa1\xb3o\xf8\xfd\xd8%\xf3y\
+\xbeE\xcc\x8cyg\x05\x7f\xf0\xe6\xe0V47\x02d\
+G\xfb\xd9\xf1\xd8\xdd\xa6z\xa75\x8d\xab/BX3\
+g\x8a\x15\x87\xf6\xa2T\x80T\x01K\x97\xae\xac\x1c\x10\
+\xf2\xda\xf9>\xdf\x22\xa6\xc71I\x0b\xf7\xd2\xea\xcf\x81\
+\xdd\x00{v>A\xff\xa1\xbdh-\xb1\xe3ud:\
+7O\xfb[\xad5A)\x8b\x97\x1fBII\xaa\xae\
+\x9e\xfa\x86\x86\xf0\xa8\xb8\xe2+\x7f(\xd6\x1f\x8bg\x5c\
+Dm\x1c\x13\x02\xfc\xe5\xb7uVY\xea*@\x02<\
+\xf9\xe0\x9d\x94\x8a9\xb4\x92$[\xd6\x10\xcb\xb4O\xfa\
+\x8d\xd6\x1a\xa54J\x83\xd2P\x1c\xe9E\xc9\x00%\x03\
+\x96t.\x8d\x9eOH\xeb\xcf\x8f\xc53.\xa26\x8e\
+Y\xc7\x90\x0f}_?\x80\xe6\xb3\x00\x9e[\xe0\xe9G\
+\xef\x89\x22}uK\xceD\xd8\xa6V\xa7\xb5F\xe9\x8a\
+\xe0\xcb\x8b[\x18&\xf0\x8a(\x19\xd0\xd0\xdcH<\x1e\
+\xd5\x02\xdf\xf5\xc5+\xc5\xcc\xce\xc4\x22\xe6\x84c\xda3\
+h\x99T\x9f\x03q?\xc0\xc0\xe1\x1e\xf6\xef\xde\x81\xd6\
+\x12a\xd9\xa4;6U\x04\xaf\xaa\x84_^W\x9a\xe2\
+\xd8\x11\xa4\x0aPR\xd1\xde\xdeV\xbel]\xdc\xb1\xde\
+},\x9fs\x11\x15\x1cS\x02\xbc\xed\x87Z\x22\xe4\x1f\
+\x00Y\x80\x9d\xcf>Nvt\x10-\x03\x9cT\x0b\xb1\
+\xfa%\x93\xbe\xfc\xca\xa2q\xf3C\xc8\xc0G\xc9\x80\xe6\
+\xa6f\x84eB\xc8\x02\xde\x7f\xcb\x95b\xb6\xfd\x0e\x16\
+q\x148\xe6}\x03?\xf8\x03\xbd[#\xde\x0f\xa0\x94\
+\xe4\xe9\xc7\x1f\xc6\x0f<\x94\x0cH6\xad\xc2rRh\
+\x0dZU\x04_\xf6\x05\xa4\x94\x94rCH%\xd1@\
+sCS\xf9\xb2\xab\x0e\xda\xf6\x9bg\xba\xf7\xa3\xdf\x12\
+\xb1{o\x12\x7f\xda}\xa3\xf8\x9b\x07\x7f \x1af:\
+\x7f\x11\x0b\xd49\xf4\xda\x7f\x0d\xb6\x01\xb7\x00\xe4s\xa3\
+\xbc\xb8\xf3\x19\xa4\x0cPJ\x93lY\x8bB\xa0\xb4F\
+km\xc8P\xa5\x09\xbc\xc2(2\xf0\x912\xa0\xb1\xb9\
+\xbe\xfa\xb2\xd3\x06\x86\xee\xbdQ\xbc\xb1\x94`\xbb\xd0|\
+\x0d\xc1\xc7\x02\xc9'\x16\xe2\xdd~\xd3\xb0`\xbd\x83\x13\
+B\xfd1\xd0\x03p\xf0\xc0>\x06\x07\xfa\x91R\x82\x15\
+#^\xdf5\xc9\x17\xd0\xca\x10!\x08|\xbcR\x0e)\
+\x03l\xcb&\x9d6\x89\xa3\x08\xbd\xe5\x1f\xde.\xce\x9b\
+x\x9f\xeembs\xf76\xf1\x0b!\xb8\x0d\x88\xd2\x8b\
+\xd0L:w\x11\x93\xb1`\x04\xf8\x93\x1f\xe8a%\xac\
+w\x02\x0a`\xd7\xf3\xcf\xe0\x96\x0aH\x19\xe0\xa4\x9a\xb1\
+\xe2\x99\x9a\xbe\x80\xd6\x1a\xbf\x98CII \x03\xea2\
+U\xc9\xc2v%W\xe0\xa1\x9bD\xeb}7\x8a\xaf\x01\
+O\x02\xaf+\xef\x17V\xf4J\x152,bJ\x1c\x93\
+\xde\xc1\xd3\xe1+\xef\xb0\xaf\x17\xf0\x11\x80\xc6\xc6\x16\xd6\
+\xae_\x8fV\x0a)=\xf2\x83\xfbP\xd2\xd8\xfb\xc8\x1c\
+`4\x81\x93\xa8G\x0b\x0b%%G\xfa\x06\xf1\x83\x00\
+\xc0O%\xd4\x86\xd3/\xe6\xcd\x08>\x05DNB}\
+\xcbJ\xd6\x9cu\x15\x07w\xfe\x94\xc1\x83&\xe5\xccO\
+S\x7f\xc9\xdbtnA_\xf0%\x8ec>>\xc0D\
+\x8c\x05\xea\x13M\x8e\xf5Z\x0d\xe7\x8c\x8e\x0e\xd1w\xf8\
+\x10-\xad\xad(\x0dN\xba\x95\xd2\xd8\x91H\xe8\xd5\x04\
+\xf0\xbd\x12\xc2\x89\xa3\xa4\x22\x9d\x8c3\x9a\x0bhj\xd3\
+\xb15g\xf2\x08\x82\xa8\x8e\x18O6\xb0\xfa\x8c\xb7\xd1\
+\xba\xe2B\x10\x16\xe9\xfa\xa5\x0cb\x08\x10\xcf\xb3\x1ex\
+b\xa1\xdf\xf1\xa5\x8c\x05'\xc0\xa7~\xa8\xbd\x1b\xde.\
+\xae\xc2\xb2\x1e\x05R\x07{{H\xa6\x92\xc4b\x0eX\
+1\xacX\x1a\xdf-L&A\xe0#\xb4@\xa3I7\
+\x08:O\xd14\xb6i\xc0\x08_X\x0e\xcbO\xfdm\
+\x96\xae\x7f\x03\x96\x93\x8a\xee\x17O5G\xeb\xca\xaa\x10\
+e\x11\xb5q\x5c\x86\x88\xf9\xe0\xbf\xe9\x1d\x1a>\x0c\x80\
+\xd6\x1c\xec9\x80\x0c\x02\xb4\x92\x88x\x06-\xec\x9aq\
+\x01\x8dG\xf3\xb2\x1c\xcbO\xcf\x96\x85\x0f@\xfb\xcaW\
+p\xee\x1b\xfe\x96\xe5\x9b\xde<N\xf8\x00N\xa2\xaa\xf6\
+\xa7hf\x11\xd3\xe2\xb8\x8d\x11t\xed\xbf\xca\xaf\x83\xfe\
+\x19@\xa9T\xa2\xaf\xaf\x8f \x08PRb\xc7\xd2U\
+5\x02\x13*n\xe8\xf4Yqf\x8e\x86N\x8fr:\
+q}\xcbj\xce|\xcd\xc7X\x7f\xde{\x89\xa7Z\xc3\
++kP\xa3\xd1}\x9cx\x15\x01\xc4\x22\x01f\xc2\x82\
+\x9b\x80j\x04\x8e\xbe\xc6\x09\xc4\xd3@\xc7\xe8\xe8(\xf1\
+D\x9cd<\x86\xd2\x1aa\xc7P\x81G\xb2A\xd2\xba\
+\xca%\x9e\xaa\xf40\x8e\xa7\x1aY}\xc6[i]v\
+\x01T7/\xeb<\xa8a\xd0\x01Xu\x80\x8d\x1d\xaf\
+\xd4\x1a\x84X4\x013\xe1\xb8\x8e\x12\xf6\xe1\x9bt\x1f\
+Z\x5cS\xde\x1e\x1c\x18\xc4\xf3<\x82 \xc0I(:\
+7\x96X\xb2\xa9\x18\x09_\xd81Vn\xbe\x82s^\
+\xf7\x19Z\x97\xbf\xc2h\x02\xad@\xbb \x0f\x81\xec7\
+\xc2\x07\xd0>\x00\x89TE\xe6Zs\xce\xf1{\xbb\x97\
+&\x16\xbc\x1aX\x0b7\x5ce\xff\x13\x9a\xf7\x01\xa42\
+1Vl\x144\xb6\x97\x22U\x0f\xd0\xbe\xf2<V\x9e\
+\xf6;\xa1\xaa\x17 ,@\x82\x1c\x01]\x1c\xd7\xfd\x1c\
+\x00\xab-\xd4\x02\xf0\xf8\x7f\xfe%\xa5\xfc\x00#=\x1c\
+\xf9\xe9'\xb8M\xc0&`\x9d\x86\xfb<\xb8\xe6\xdbZ\
+g\x8f\xcf\x9b\x9e\xfc8!\x04\xf8\xca\x95\x22e\xc5\xad\
+G\xda\x97\xeb\xd3\x96\xad\xd78\x95>\xa6\xd4\xb7\xacb\
+\xcd\x99\xbfK\xa6y\x0d\x86\x11\xa1\x92R\xa3\xa0\xb3\x95\
+}b\x82\xf2\xb2\x1a\xc12&\xff\xd9\xbb\xbe\xc9\x9d_\
+}\x88\xe7\xef\x8c\xfa\xa1Vc'\xf0;_\xd7\xfa\xf9\
+\x05x\xb5\x97\x1c\x8e\xab\x0fP\xc6\xf9\x97\xf3*\xa5T\
+\xbcZ\x86\xf1d\x03+7_A\xfb\x8a\x97\x81\xb0\x89\
+\xf2\xcc\xf5\xa8\xf9\xea\xd1\xa1\xd0-\xb3\xae\xf5x-\xa0\
+]\x94Tt\x7f\xf7nn\xbb\xeeI\x8a#\x95C\x09\
+\xcb\x02\xadq\x0d\xd97\x027\x09!.\xd0\x8b\xc3\xd5\
+\x1d_\x0d\xd0\xfd\x1dq\x0a6\x7f\x0fD\xbd\x80-\xcb\
+\xa1k\xdd\x85t\xae\xddB,\x96\xc1\xb2\x13\x08+\x06\
+\xaa\x08j\x08\x080B\x0f\x171q\xdd`\xe7={\
+\xb9\xf5cw\xd2\xfbLO\xb4\xaf\xceq8\xaf\xb9\x99\
+\x95\xb1\x18\x85R\x89{FG9\x22#\x95p\xf5\xd7\
+\xb5\xde\xb6\xe0/}\x92\xe3\xb8\x10\xe0\xae\x1bES\xcc\
+\x84n\xdf\x07D\x0a\xbf\xb9k#\x9dk\xcf'\x91n\
+\xc5\xb2\x13\xd8v\x12\xcb\x12Xd\x11\x14\xa9)\xf4h\
+\xdb\x06,\x06\xf7\x8f\xf2\xef\x9f\xfc%O\xfedGt\
+?\xc7\xb28\xaf\xbd\x9d\xb3\x9a\x9aP\xbe\x8f\xefy\xf8\
+\x9e\xc7p\xa9\xc4\x7f\x8c\x8d\x11\xd6/\x0e\xbb\xb0\xf1\xbf\
+\xbb?\xb0\xa0&\xe0\x96[\x84\xbd\xac\xc0{b\x82\xcf\
+@\xa5J\x96\xaao\xa7}\xcd9\xa4\x1b:\xb1\xed$\
+J\xf9 4\xc8>\xb4p\xc1Ia\xdbq\xc2\x98`\
+\xa8\xeeue\x1b\x8d\x9b/q\xfb\x97\xef\xe7\xce\xaf?\
+H\xe0V\x0c\xfd\xe6\xf6v.^\xb1\x82\x14\xe0\xbb.\
+\xbeR(\xdbF\xda6\x0d\xb1\x18\xeb\xe3qvz\x1e\
+@W\x12\xfe\x02\xf8\xf4B\x96\xc1\xc9\x8e\x05#\xc0\xbd\
+7\x89\xd7.\xd5|E\xc3\xe9\xd1\xcd\x12i\x9a\x97\xae\
+\xa7\xbeu9\x96\x930\x1dB,\x17\xe9\x0d \xf5\x08\
+\x8e\x93\x04'\x8dP6\x96e\x87\x03\x86\x8c\x17\xbc\xd6\
+\x9a\x87\xff\xefv~|\xdd\xdd\x8c\x1e\xa9\xb4\xf3,k\
+l\xe4\xf2SNaI&c\xbex\xd7\xc5\xb2\xedh\
+\xb1m\x1beY\x9c\x9eL\xf2\xa2\xe7!\xcd\x15_\xb1\
+P\xef\xffR\xc1\x82\x10\xa0\xfbF\xf1\xbbB\xf0\xa3\xf2\
+\xb6\xb0c4u\xad\xa1\xbem)\xc2\x12h\x1d\xa0\x95\
+M\x10\x1c&(\x0e\x18\x019i\x94\xb0\x11\xc2\xc3\x12\
+\x0eJ8\xd8N\xd9\x194Z`\xcf\xa3\xbd\xfc\xe8\xa3\
+w\xb1\xf7\xb1\xc3\xd1\xbd\x1a\x92I.?\xe3\x0c\xce]\
+\xba\x94 T\xf7\xca\xb2\x90U\xc2\xb7l\x1b\xcb\xb2\xb0\
+l\x9b\x84\xe3\x90\x10\x82\x821}\xff\xedS\xce\x17F\
+\x03Xl\xaa\x1a\x1a\x88\x86\xb6v\x1a:\x96P\xae\xe8\
++\xe5\x13x\xbdh\xd9\x8f\xe3\xa4@\xa4\x11\xcaA)\
+'\xfc\xeb!\xc2u\xcb\x8a1r(\xc7\x8f?s?\
+\x8f\xdc\xfa\x5cy 2\x1c\xcb\xe2\xd5\xeb\xd7\xf3\xdbg\
+\x9cA2\x1e7\x82W*\x12\xb4m\xdb\xa8\xf2\x12\x12\
+B\xd86;\x5c\xb7,|\x84 X\x90\xf7\x7f\x09a\
+A\x08\xe0+\xbe\x1e\xb3\xd8\x82\xe62\x80\xd1#\xbdx\
+\xc51\xdaV\x9d\x86\xe5\x98P\xad\x1d\xebB[I\x94\
+\xecCH\x0f!\x1c\x94\xe5T\x11\xc1#(\x0a\xee\xf9\
+\xe7'\xb9\xfd\x86\xc7\xf1\x0a~t\xfdS\xdb\xdax\xe3\
+\xe6\xcdt65\xe1X\x16\x96eE*~\xaa/\x7f\
+\xd0\xf7\xb9w`\x80>\xd7\x8cUh\xc7\xe1\xf5\x9fd\
+}\xf76q7\xf0\x0d\xe0\x96-[kD\x0d~\xc3\
+\xb1\x80\xb5\x00!\xee\xdb\xc6G4\xfc\x0d!\xd1\x84%\
+h]\xb1\x8eL\xcb\x0a\x00,+\x8e%@\x05=X\
+Ba;)l'\x8d\xe3\xa4y\xf6\x17#\xfc\xf4\xf3\
+\xcf0t\xa02\x0eQ[*\xc5\x1b\xd6\xac\xe1\x94\x8e\
+\x0e\x9cx\x1c'\x1e'\x16\xfe\xd5\x10y\xfb\xbe\xe7\xe1\
+\x85~\xc0p>\xcf\xdd\x07\x0e\xf0\xdc\xf0p\xa4\x94,\
+\x1b.\xf8#Xs\xd1\xb8\x07\xde\x03|\x11\xf8\xd6\x96\
+\xad\xff}\xe2\x03\x0b^\x0d\xbc\xef&q\xa1\xd6\xfc\x1b\
+\x10u\xfaK\xd67\xd3\xba\xf2Tb\x89\x14\x96\x9d\xc0\
+\xb2\x13\x10\x1c\x06\x9d\xa3\x7f\x97\xe6?\xbf\xd0\xc3\xee\x07\
++\x91\x9c\xa4m\xf3\xca\xf6v^\xd6\xd5E\x22\x91\x88\
+\x84\x1f-\x89\x04v,6\x8e\x00\xa5b\x91{\xf6\xec\
+\xa1\xbb\xa7\x07\xbfR\xf7\xe7\xd4K7p\xd9\xc7\xb7\x90\
+h\xe8a\xf8\xd0S\x8c\x0d\xf6M|\xe4\xbb\x80\xab\xb7\
+l\xd5\xfb\x16\xb4`N\x12\x1c\x978@\xf7wD=\
+6\x9f\x01\xdeO8\xc4\xac\xb0\x1c\xdaV\x9fB]\xf3\
+2,;\x81;&\xb8\xf3+\x8f\xf1\xc8-=\xe8\xf2\
+h\xb3\xc0\xe9\x99\x0c[\xda\xda\xa8K\xa5j\x0a\xbez\
+[i\x8d\xef\xba<\xbe\x7f??{\xf6Y\x86\x8b\xc5\
+\xe8\x19:7t\xf1\x96/\xbc\x95\xd3.\xdd\x84\xd2\x12\
+\xad$RI\xdc|\x0f\x83=Opd\xef}\xa8 \
+23c\xc0\x07\xb6l\xd57.x\xe1\x9c`\x1c\xd7\
+H\xe0}7\x8a\xb3\xb5\xe0\x1b\xc0\x05\xe5}\x0d\xedK\
+\xd9uO\x03\xbf\xfe\xfa\x8b\x94\xb2\x15;\xbf\xd4\xb6\xd9\
+RWG{*5I\xd0\xb5\x84\xef\xc4\xe3\x1c\xce\xe5\
+\xf8\xe1\xc3\x0f\xb3\xab\xbf?\xbaN\xaa1\xcde\x7f\xf5\
+&.~\xcfk\xb0\xed\x22P@\xe9\x94I8Q\x0a\
+\xa5$JI\xbcb?\xfb\x9f\xf9w\xb2\x03{\xab\x1f\
+\xf9\xc7\xc0{\xb6l\xd5\x93\xd4\xc4o\x0aN@c\x90\
+\x10\xf7n\xe3C\x02\xae\xef}\x0a\xeb\xb1\x9ba\xf4P\
+\xe5h=\xf02\xcbbuY\xc0\x13\x05]C\xf0.\
+\xf0\x8b\x17^\xe0\xfe={Pe\x0f\xdf\x12\xbc\xf2]\
+\xaf\xe5\x8aO\xbe\x85\xba\xa6!\xb4\xf7,\xc8\xc3\xa6\xcd\
+@\x0b\xa4X\x02\xd62\xb4\xdd\x89V\x1a\xa5\x14J\x07\
+\x0c\xf5\xdcO\xef\xf3\xbfD\xc9\xa8\x82\xd0\x0f\xbc{\xcb\
+V}\xdb\xf1-\xa7\xe3\x83\x13\xd2\x1ax\x9d\x10V\xa1\
+\x83{\xb2}l)\xef\x8ba\x22F\x1b16b6\
+_\xbd\x88\xc5x\xb4\xaf\x8f;v\xef\xa6\xe4W\xb4\xc7\
+\x86W\x9d\xce[\xbf\xf4G,\xdf\xdc\x82\xf6\x9e\x80\xe0\
+ \xe8\x92\xc9#\xd0.Z\xbbH\xe9#\x03\x9f@Y\
+X\xc9\xf3\x10\xce\x1a\xa3\x0d\xb4\xc4\xcd\x0fpp\xc7\x8f\
+\xc9\x0f\xef/_R\x03\x9f\xd8\xb2U\x7f\xfe\xf8\x95\xd2\
+\xf1\xc1\x09!\xc0\xfb\x84\xf8\xb4\x86O\x81\xb1\xf3k\x80\
+\xb3\x81\xea\xa1\xa5,\xc7\xa9)\xfc\xb2\xd7\xbf\xb7X\xe4\
+\x8e\x03\x07\xe8\xaf\xb2\xf3\xad\xab\xbax\xf3\xe7\xdf\xcd9\
+\xff\xf3\x02\xb4\xbf\x0b\xfc\xe7M\xee\x80.\x01nD\x00\
+t\xc9\x10\xa0L\x02\xe9\x81\xbd\x0c;u\x11\x9a\x04J\
++\x94\x0c\xe8\xdf\xf7_\xf4\xef\xee\xae~\xf4\x7f\x01\xfe\
+d\xcbV\xfd\x1b\x13?8\xee\x04\xf83!\xceWp\
+\x1f`\xc5\x80\xdf\x02Zk\x9c'\x84\xa8\xf9\xd5\x8f\x01\
+\xf7\x0c\x0e\xf2b\xb6\xd2\x86\x13\xcf$y\xfd\x87\x7f\x9f\
+K?p%\xb1x\x1e\xed?\x1b\xa6\x8aU\x04^Y\
+7\xdbJy!\x09\xbc\x90\x04>JY\xd8\xa9\x0b\xb1\
+\xe2\xebPZ\xa2\xa4$;\xf0$\xbd\xcf\x8e\x9b\x04\xe3\
+v\xe0m[\xb6\xfef4\x22\x9d\x08\x02\xbcZ\xc1\xdd\
+\x00\x9b\x81\xb3\xa69\xd7\x8e\xc5*\x1e~,\xc6\xa3\xc5\
+\x22O\xe5r\x15;/\x04\xe7\xfd\xde\xc5\xbc\xe9\xb3\xd7\
+\xd0\xb4\xb4\x05-\xf7\xa3\xbdC\x08+\x00\xedM\x10\xfa\
+\x04\x22\xe0\x12\x04\xde\x04M`\xd6\x85\xb3\x86x\xdd%\
+a\xf75I)\xbb\x8f\x9e\xed\xffN\xe0\x95\xca\x8f\xf6\
+\x14p\xf9\x96\xad\xbag\x8aG\x7f\xc9\xe0\xb8\x13\xe0\x8f\
+\x85Xi\xc3>0\xaa\xff\xc2i\xce\x15\x96\x85\x1d\x8f\
+\xf3\x22\xf0\xa8\xe7Q\xaa\x9a\x8af\xf5\xcb\xd7\xf3\xd6\xeb\
+\xafa\xcd\xf9\xa7\x82\xecG\x07\xc6^K\xe9\x83\x96\xd8\
+6\xe3I@\x85\x04Z\x95@{UZ\xc0'\xf0}\
+\xa4\xaa\x90\x01\xab\x95x\xe3\x1b\x80\x04J)\x02w\x98\
+\x9e\xed?\xc4\xcd\x0f\x97\x1f\xe1 \x86\x04O\xf2\x12\xc6\
+q'\xc0uBXGL\xa7\xd1%\x02\xb8\x0c\x98j\
+\xf8\x8f#\xc0cB0\x5c\xf5\x8c\x8d]\x8d\xbc\xe9\xba\
+\xdf\xe3\x15\xef\xb8\x18\xa1]\xb4\xff\x02\xe8\x1c\x888Z\
+\xd9(%\x91\xd2E\x08M,f\x1b\x12\xe0FdP\
+\xb2\x80\x96%\x04.\x08i\x84\x1fj\x82\xc0\xf7\xcc\x00\
+\x15\xca\x90@\x93\x22\xd1t9\xc2j6#\x9bH\x97\
+C\xcf\xdfF.\x1c\xee\x1e3\x0e\xc2[\xb6l\xd5\xbf\
+\x5c\xb8\x12[X\x9c('\xf0j\x0d\xdf\x05X\x86\x99\
+n\xb4\x1ay\xe01\xa0z\x16)'\xe1p\xe9\x9f\xbd\
+\x96\xd7\x7f\xf8\x8d$2)t\xb0\x1b\x82\xfd bh\
+\x1c\x84H\xa0q\x90A\x10\x0e2Q\xc2\xb6m\xe2\xc9\
+\xd88M \x83\x02J\x16A\xbaXN\x80\xd6\x92@\
+z\x04\xbeG\xe0\xf9\xf8\xd2Ck\x89V\x01R\xfa(\
+%H4\xbe\x01;n\x02\x99\x96\xdd\xc0\xe1\x9d?b\
+\xf8\xe0\xa3\xe5G\xf3\x81\xad[\xb6\xea\x9b\x17\xb4\xd0\x16\
+\x08'\x84\x00B\x08\xf1\xa7\xf0\x90\x86\x97\x03l\x01V\
+aF\x98\xda\x0e<\x17\xae\x97q\xd6\x15g\xf0\xe6\xcf\
+\xbd\x85\xf6\xb5\x9d \x07\xd1\xfeS\xa0}\xb4N\x00\x0e\
+\x9a\x18Xq,+\x89\xd6f\x8c\x22\x19\xb8\xc8\xa0D\
+2\x95&\x16\x0f5\x81\xf6\xd0\xb2\x84\xefg\x8d\x19P\
+\x1e\xb6#P: \x08<\xbc\x92K }\x82\xc0G\
+\xe8\x00E\xa8!\xa4$Q\xff*\x12\x99\xb3\x01A,\
+\xb9\x92\xfe=\xb7r\xe4\x85_\x95\x1fQ\x03\xd7n\xd9\
+\xaa\xff\xe1\xb8\x15\xe21\xc2\x09!\x00\xc0\x9f\x08\xb1E\
+\xc0\xbd\xe5\xedf \x87\xf9\x9c\xcahZ\x0e\x97}\xec\
+L\xce\x7f\xfb\xbb\xb0\x84\x8d\x90\xcf\x83\xf7\x0c\x88\x84Q\
+\xf9$\xd0Xh\xe9\xa0qp\xe2\x19\x101d )\
+\x15FP\x81\x8b\xd6\x1euM-XBE\xe6@\xfa\
+\x05|7\x87V\xc6\x0c81\x81\x94&\x97\xc0sK\
+\x04\x81!\x01H\x10\xd28\x87\x81O\xa2\xee\x5cR\x8d\
+\x97 \xac$\xb1\xe4\x1a\x86{~B\xcf\xf6\x1fU\xbf\
+\xd6\x17\xb6l\xd5\x1f=.\x05x\x8cp\xc2\xa6\x8f\xff\
+\x86\xd6\xdd\x1a>J8~\xc00\x15\xe1[\x0e\xd9\xf3\
+\xde\x09\x97}\x066\xbczS\xd8u\x5c\xa3\xdc\xe70\
+I\xa2f\x11\x04\x08\x14J{(\xe5\xe2{y \xc0\
+v\x04\xb1x\x1c\x8dD\xc9\x80\xec\xd0\x91\xaa;\x0b,\
+;\x06\xc22\xc3\xd4\x04\x012P\x08L\x93\xb2\x13\x8b\
+\x01\x02\x81@\x05 \x03\x10\xc2B\x08\x8bR\xf6\x11\xf2\
+C?E\xab\x02\xd2\xeb\xa3y\xf9\x9bX}\xee\xbb\xab\
+\xc7$\xf8\xab\xeem\xe2;\xdd\xdb\xc4\x09\xc9\xb6\x9e\x0b\
+N\x18\x01\x00\xbe\xa1\xf5\x17\x80\xd7\x03}\xc0a\x8cF\
+\xf8\xd2\xe5\x9f\xe3\xaf7\xfe\x96\xc9\xfdt\x9c8h\x8d\
+F\xa1T\x01\xad\x03\xd3\x1bH\x87$\x10\x0at\x80V\
+>\xd2/\xa0\x82\x22\xe8\x80X\x22\x89\xed8h\xad\x08\
+\xfc\x12\xb9\xd1\xc10\x8d\x5c \x84 \x91H\x86\xc3\xd4\
+\x08JE\x0f\xa5\x01!\xb0l\x8bx\xc2\x90\x00\x01*\
+\xd0H_SNf\xf1\x0a\xcf\x91\xed\xff\x11\x81\x7f\x18\
+%\xc7\xa8\xef\xb8\x98\xb5\xaf\xf8P\xf5dY\xef\x02\xfe\
+_\xf761\xbe\xd7\xeaI\x8a\x13f\x02\xc6=\x84\x10\
+\xa2:G\xbf{\x9bx\x1f\xf0O\x00\x9b.\xbc\x9aL\
+\xcbf,\xcbFe\xbf\x8fm;\xe1leq\x10f\
+Q\xda\xc6+\x05hma9\x09\x12\xa9F\xc0B)\
+\xc9\xd8@\x0f\x81_BI\x8f\xc6\xb6\x0e\x12I'\xf4\
+\x07|\xdc\xe2\x18n)\x8b\x0c|,\x1b\xe2I'\xac\
+\x06\x06\xf8\xbeO\xa9(\x09\xbc\x1cR\x05\xa0%\xc2\x91\
+\xe8\xb0\xa9\xd2\x8euP\xdf~%\xf1\xcc\x19\x08\x91\xc0\
+\xcb\xeff\xf7C_\xc2w\xa3<\xc5\xfb\x80+\xb6l\
+\xd5\xc3\x9c\xc48\xa1\x1a\xa0\x8c\x1a\x1d4\x22W@c\
+\x1b\x13\xa0|\x94\x0a\xc2\xd6\xbb\x8a\x19\x80\x00Kh\x10\
+\x12\xa5}\x02\xb7\x80\x96\x9e\xd9oA\xba\xb1\x19\xad\x15\
+ZKF\xfa\x0e\x86s\x16\x9b\xaf9\x91Jb\x09\x0b\
+4\xf8^@\xe0\x06\x08,\x84\x10\xd8\xb6 \x91Ja\
+\xc5Z@\x0bd\x00\xbeK\xd4_E\xfa}\x8c\xf5}\
+\x0f/\xff4\xa0\x88g\xd6\xb2\xfe\xa2O\x93\xa8\x8bF\
+E\xbd\x08\xb8\xb7{\x9b\x98\xfd\x0c\x1a'\x00'\x05\x01\
+j\xa0B\x00M$\xc0r\xd3\xadRj\x82)\xf0q\
+l\x81\x96>Jyxn6:\x16\x8f'Hf\xea\
+\xcc\x98\xc4\x81\xc7H\xff\xe1\xaa\xdb\x08R\x99LH0\
+M\xb1P2QF!@\x08\x84(\x92L\xd7c'\
+:\x11B\xa0%\xf8\xae\x8eH\xa0\x82QF\x0f\x7f\x1b\
+7g\x06!q\x12\x9d\xac\xbb\xe0SdZ\xa2a\xef\
+O\x03\xee\xeb\xde&f7v\xfe\x09\xc0\xc9J\x00\xaf\
+\xbc\xa2\x82B\xe8\x03\xd8\xa6c\xb02\xc9\x1cJI\xa0\
+B\x02\xdb\xc1T\x0d\x95Q\xedF;H@R\xd7\xd8\
+\x1ce\x18\xe7F\x87)\x15*\xe9\xe4\xb6c\x93H%\
+\xd1J#\xa5\xa6\x94/!\x84\xa0\xfc\x0f\xd5G\xba~\
+\x09N\xc2$\xb5\xca@\xe0\x16u\x94\x9c\xaaU\x91\xd1\
+C\xdf\xc0+<\x15^\xaf\x915/\xff(\x8d]\xd1\
+\xac\xa8+0\x9a \xca\x818\x99p\xb2\x12 \xd2\x00\
+R\x16\x8d\x06P\x1a-\x1c\xd3H\x13i\x82 <5\
+@ \x89\xc5mc*\x02\x17\xafX\xd1\x02\x02EC\
+K\x1bZ\x99\xb1\xe8\x06\x0e\xf5Rmu\xd2u)l\
+\xc7\x98\x1a\xb7\xe0\xe1\xb9\x81!A\xb8(o'\x99\x96\
+\x8d\xc4S\xcb\x11\x80\x0a\xc0\xcd\xeb(sIk\x9f\xe1\
+\x9e\xaf\xe2\x17\x9f\x05@X)V\x9cu-\xad\xab\xa2\
+\x99SZ\x80_uo\x13\x97\x1d\x8f\xc2;\x1a\x9c\xac\
+\x04\x884\x80\x0c\x0aFE\xa3P:\x16\xb5\xd9\x97I\
+`L\x81!A,fE5\x82ba\x94j-\x90\
+H&I\xd7\xd5\xa1Qxn\x91\x91\xaa\xac!\x80t\
+}&\xd44P\x183c\x16\x19S\x00\x08MP|\
+\x9c\xba\xb63\x89gV\x01f\x8c\xc3RN\xa3\xa2\x88\
+U\xc0\xf0\xc1\x7f\xc4+>\x83\xf9\xa9\xc3\xd2S\xdfM\
+\xd7\xa6\xdf\x89n\x01\xfc\xb8{\x9b\xd8\xba0E67\
+\x9c\xac\x04\x88R\xb0|7\x17\xfa\x00\x1aM\xac\x22x\
+5\x99\x04\x96\xad\xb1l\x81V\x01\x81\x9bG\xfa%\xaa\
+I\xd0\xd8j\x1c4\xad\x15\x83G\x0e\xe3{\x11\xcf\x88\
+\xc5\x1d\x92\xe9$h\x8d\x94\x8a\xfch\x11Q\xf5\x0f\xed\
+\xe1\x17\x1e\xa3\xb1\xfde\xa4\xea\xd6\x98\x91iB\x12\x94\
+\x93\x87\xb4*2v\xe4&\xdc\xfc\x93\x18GA\xd0\xbe\
+\xfam\xac<\xfb\x8f\x08\x1dO\x07\xf8n\xf76\xf1\x91\
+\xe3R\x8a\xb3\xc0\xc9J\x80(#7p\xf3F]k\
+\x85&\x1e6\xf6H\xa4\x0c\xc2\x86\x9b\xf1\xfe@<a\
+\xcc\x80V\x01n)k\x06\x08\x08\x17\xdb\x114\xb7\xb7\
+\x816)`G\xf6\x8fo\xcd\xcd4d\x10\x96\x85\x96\
+\x1a7\xef\xe1\xbbA\xe4\x10\x22\x04J\x0e\xe3\x95\x9e%\
+\xd3~\x0e\xe9\x86u\xa6\xc3\x92\xd2\xb89E9\x9fT\
+zG\xc8\x0f\xfd\x147\xf70\xe5\x80vc\xd7%\xac\
+\xbb\xf0\x13\xe5\xf1\x8b\x04p}\xf76\xf1\x0f'C\xc0\
+\xe8d%\xc0!B?\xc0+V4@\xb9iV\xc9\
+\xc0\x8c=\x1c\x04U\xfe\x80\x04|\xe2\x09\x0b\xa5\xcd\xc4\
+\x13n>K\xa5\xbah\xb4@CS\x13\xf1x\x02\xad\
+\x15\xd9\xd1Q\xb2#\xa3\x91C'\x84\xa0\xbe\xa5\xc9\xe4\
+\x01\xa0\xc9\x0e\x17@\x85V \xfc\x17\x94v#\xbd\x1e\
+\xea\xda\xce$\xd3\xb2\xd1\x8cs\xac\xa08\xa6\x08\x5cs\
+!\xbf\xf8\x02\x85\xd1\xbb)\x8e\xdd_~\x0d\xd2\x8d\x1b\
+Y\x7f\xd1gH\xd6G5\x84?\x07\xfe\xab{\x9b\x88\
+f\xc78\x118)\x09\xb0e\xabV\x84\x8d\x81\xa5|\
+_8\xc9\x84\x02\xab\xc9h\x00e4\x80\xef\x87D\x08\
+\x1dB\xa5$BHb1\x0bM\x80[\xca#\x037\
+t\x06\xa5\x19_H(\xda\x96vR\xeeh\xda\xbb\xef\
+`H\x1e\x00M<nS\xd7\xb4\x04\xad52P\xe4\
+FK\x94\xa3\x82eM\xe0\x15\x9eD\xc9Q\xeaZ6\
+S\xdfvZ\xd4}\xb1\x94\xd5xEC\x02/\xff\x0c\
+n\xeeQ\x8a\xa3\xbfF+\xd3\xb9%\x96le\xed\xf9\
+\x1f\xa7\xa9+J\x85|%\xf0x\xf76\xf1\x9a\xe3V\
+\xb8\x13pR\x12 \xc4>\x00\xbf\x985m\xf8Z#\
+\xac\xa6\xa8\x1a(\x03\x89\x96\x01\x81?^\x0b(%I\
+\xa4\x9cp*:I\xa9\x90\xc5|\xfdeM\xa0He\
+\x92467\xa1\xd1\xf8%\x8f\xbe\x9e\xd0\xe5\xd0\xe6\xbf\
+\xba\xe6f\x9cX\x06\xa55\xc5\x9c\x8b\xef\x05\x13\xfc\x01\
+E)\xfb\x10Z\xfbd\x9a7Q\xdfi\xe6>\xd6\xda\
+\xf8\x04n\xce\x90\xc0\xcd=\x81Wx\x9e\xc2\xe8\xdd\xa8\
+\xc08\x9d\xb6\x93`\xc5Y\x7fL\xd7\xc6\xab\x08\xfd\x82\
+\x0e\xe0\x97\xdd\xdb\xc4G\xbb\xb7M\x1c\xf8h\xe1q\xd2\
+\x13@)\xf0\xdd~\xb4R\x08\xbb)t\xfa\x14R\x05\
+\x04A@\xe0\xfbF\xf0\xb2B\x00'\x1eCJ\xe3\x1c\
+\x16\xb3c\x15\x0d\x80\x8c4A\xfb\xd2\x0ela\xa1\xb4\
+\xa2\xaf\xb7\x9fR\xbe\x14\xc6w4\xc8\x01\x9a\x97\x9c\x1d\
+\xd6\x0a4c\x03ES\xe5\x0b\xb5\x80\x10\xa0d\x9eR\
+\xce\xe4\x04d\x1a7\xd0\xb4\xf4\xecp\x143p\x0b\x9a\
+\xe2\x98\xe9\xd1\x5c\xca=\x82\xf4z)\x8e\xdeGP\xda\
+e\xdeL\x08\xda\xd7\xbe\x81\xd5/\xffK,'\x0d&\
+\x11\xfa\xf3\xc0m\xdd\xdb\xc4q\x1d\xdb\xf0d&@\x94\
+\x93\xed\x16\xfaM\x0c^$\x8d#\xa8\x0d\x09\x94\x92\x04\
+\x81\x8f\x94\xe35\x80\x10\x8aX\xccF*I\xa9\x90G\
+)\x13\x1a\x8eH\x80\xc4v\xa0sEG8y\x85\xe2\
+\xe0\xee\x1e\xa2\x10\x9fV8N\x81\x86\xb6M\xa0\x08M\
+\x81[\xfe\xfe)\x87\x92\xa5w\x18\xaf\xf8\x1c\x00\xa9\xfa\
+\xb5\xb4,\x7f\x85q\x225x\x05M~D\x83\x92\x94\
+\xc6\x1e@\xcaa\xdc\xfcv\xdc\xdc\xa3\x94\x9d\xc3\xfa\xb6\
+\xd3\xd9\xb0\xe5\xb3$\xea\xa2h\xf1\x15\xc0\xa3\xdd\xdb\xc4\
+\xcb\x16\xbap\xcb8\x99\x09\x10\xe5\xda\xb9\xa1\x1f\xa0\xb5\
+\x02\xab\xd9LF\x85B\x06\xe6\xcb\x0f\x02o\x9c\x1f\xa0\
+\x94$\x91\x8c\xa1\xa5\xa91\x14\xb29*f\xc0\x10@\
+kEcK\x13\xe9\xba\x14Zk\xc6Fs\x0c\xf5\x8d\
+\x18\xcf\x1e\x8d\xf2{i\xe88\x15;^\x8f\xd6\x9ab\
+\xd6\xc3-\x04D.\xa1\xa8\xb4\x0e\x06\xbe\x09/'2\
+\xcbi[\xfd*\xacp\x82,\xbf\xa4\xc9\x0e(\xa4\x0c\
+(\x8d\xdd\x8fR9\x02\xf7@\xe8\x17\x98t\xf6x\xaa\
+\x83\xf5\x17\xfe5\x8d]\xe7\x97_w\x0d\xd0\xdd\xbdM\
+\x1c\x97\x09\xb4Of\x02<X^)e\xfb\x01\x85\xd6\
+Uf\x00\x15U\x09\x03\xcf\x1f\x17\x1dTJ\x12K\xc6\
+L\x8dA)rc\xd9\xaa6\x84\xf2_\x85F\xb1d\
+U8S\xa9\x86\xde\xdd\xbd\x04A9\xe5?@\xfb\x07\
+\xe8Xu\x11Z\x0bP\x90\x1drQJ\x87\x83\x93U\
+\xcc\xb5\x9b}\x14Uv\xf4\x12\xadt\xac\xbd\x04+\x9e\
+1\x13`\xf80\xd6\xa7\xf0\xdd\x12\xc5\xd1\xfb\xd0\xaa\x84\
+\x0aF(\x8e\xde\x8d\x0a\xccT\xbb\x96\x9db\xe5\xd9\xef\
+c\xd9\xe6w!L\xcd0\x01|\xa3{\x9b\xb8\xa7{\
+\x9b\x98.qz\xde8i\x09\xb0e\xab>\x08\xf4\x02\
+\x14\xb3\x03a\xa3\x90\xc6r\xda\x22?\xa0\x9c\xbb\xef\x8f\
+#\x80Y,\x0bl\xc74\x09\xe7\xb3y\x82 \x18/\
+\xfcpI\xa4\x12\xb4v\x9a\xa4O\xdf\x0b8\xbc\xbf\x8f\
+\xf2\x90\xe5\xd2;\x80\x93\xac\xa7e\xe9\xe9(L[A\
+v\xc0\x8b,E\x19Z\xfb\x94\xc6\x1eD\x87\xaa\xdd\x8e\
+\xd5\xd1\xb9\xf6\x12\x12\xe9fSM\x0c \xdb\xa7)e\
+\xf3\x14\xc7\xeeCk\x1f\xadJ\x14\xc7\xba\x09\xdc\xbd\xe1\
+U\x04-+~\x8b\x0d[>G\xb2.\xeaH\xfd*\
+\x8cI\xf8Z\xf76\xd1\xb2\x10\xe5|\xd2\x12 \xc4C\
+\x00~1\x8f\x0a\xc6\x0c\x01b\xcb\xab\x22\x80\xda\x04\x85\
+\x02\xe3\x10N$A<i\xe6\x1bP\x81\xa4\x90\xcd\x87\
+\x1a\xa1\x1cE\xac\x90\xa0c\xe5z\x9c\xb8\x83F3\xd8\
+;L\xa9\xe8b\xdc\xbf\x00\xe9\xed\xa3\xa1\xfdt\x92\x99\
+V\x13\xf4)J\xf2c\x95&\xe52\x94\x1c\xc3\xcd=\
+\x1em[v\x82\xf6\xb5\xaf&\xd3\xb2$\x8c\x1ajr\
+\x83\x8a\xec\xc0(\xc5\xb1\xfb\x0dY\xb4\xc2\xcd=\x81\x9b\
+{(LW\x83D\xdd2\xd6_\xf4i:\xd6\xbd\xb1\
+|\x0f\x1b\xf8S`g\xf76\xf1\xde\xeem\x13G\xc8\
+\x9c\x1fNv\x02Df\xa0\x985\xc1Aae\xc0j\
+\x08\xbfre\xe6\x1c\x9ed\x06B? \x13\x0b{\x00\
++r\xa3\xd9*\xcd1^\x0bXv\x9c\xe5\xebO\x8f\
+\xec\xff\xe1\xbd\x95v\x02\xe9\xed\x05$\xed\xab/\xc4\xb6\
+\x1c\xd0P\x18\x09\x08\xbc\xc9\x894\x81\xdb\x83_\xf6\xf4\
+\x01!lZ\x97_@\xe3\xd2p(\x22\x01\xc5\xacb\
+\xf8\xe0\x00\x85\xe1\x07L\x08\x1b\x08\xdc^\x0a#w\x22\
+\xfd#\xe1;\xc6\xe8\xdcp%\xeb/\xfa8\x89L\xf4\
+\xe1\xb7bF2y\xa4{\x9b\x88\x02\x09\xf3\xc5\xc9N\
+\x80\x87\xca+\xc5\xb1\xbd\xd1N;\xb6\xcc\x08S\x98\xb8\
+\xbd\x96\x12\xaf\xe4\x8d\xab\x0a*%\xb1m\x81\xe5Xh\
+\x14\xb9\xb1\xbc\x99\x9aVI\xb4R\x111\xb4V(9\
+Dc\xd7\xb9d\x1a\xccX\xc3\xd9\x91<\xb9\x91<e\
+\xfd-\xbd\xbd\xd8\xf1zZW\x9d\x13Mm\x93\x1d\x08\
+\xa8\xea\xa7\x12\xc1\xcd?\x83\x0c\x06\xaa\xf6\x08\x1a;\xce\
+\xa4}\xcdY\x80\x00\x0d^I3\xb0\xff\x08\xb9\x81\xbb\
+Q\xaa\x00\x80V%Jc\xf7\xe3\x15\x9e\x84p\xe8\xa2\
+T\xc3)l\xd8\xf2\xb7t\xae\x7fM\xf5\xa0\xa8\xe7`\
+\x9a\x97\xbf\xd7\xbdM,\x99o\x01\x9f\xb4\x04\x10B\x88\
+#\x83<F\x984\x9a\x1f\xaa\x0c\xd8a'V\x84_\
+\xb3\xa9\xf2I\xa5\xf0jh\x00\xa5$\xa9L\x02)\x15\
+JJrcf>c\xa5eT\x95\xd4JGm\x07\
+\xcb7U\xfa)\x1d\xde7\x88*\x1b\x02w\x0fhI\
+\xa6y=\xf5\xad\xe5(!\xe4\x86j0\x00M)\xfb\
+0J\x15\xc7\xedM7\xaeg\xc9)\x17\xe0\xc4\x8c\x16\
+Q\xbefp\xff\x08\xc3=\xff\x85\x0c\x9dA\x00\xbf\xb8\
+\x87\xe2\xc8]\xa8\xc0d\x92\x09+M\xc7\xfakX\xbf\
+\xe5\xa3\xd4\xb5tT_\xf2\x0f\x80\xe7\xbb\xb7\x89\x0f\xcf\
+\xa7\x9cO\x0a\x02\x84\xed\xeeV\xb88B\x88\x18\x10{\
+\xcb_PT\x9aG\x00\xdc\x5c\x0e\xe9\x99/+\x96X\
+\x11\xda\xf1\x00D\xd8\xb7\xbf\xec\x0c\xca\xf1A\xa1T]\
+\x22\xfa\xda\xb3\xc39\xd3\xf3\xb7Z\x0b\x94\x89 \x87I\
+7\xae\xa7\xb9\xcb\x84\xe6\xbd\x92\xcf\xe8\x91\xb1\xb0\xc1\xc7\
+'p\x0d\x01[W\x9cO,\x9e\x04\x05^^S\xcc\
+N6\x05Z\xb9\xb8\xd9\x87\xd1\x8c'H<\xb5\x94%\
+\x9b^E\xb2.\x19\xb5!\x8c\x1e)qd\xd7\xaf\xf1\
+KQ\xd8\x03%s\x14G\xef\xc1/>G\xd9\xe3L\
+\xd6\x9d\xc6\xea\x97\x7f\x8e\xd6U\xe3\xba\xd1d0\xa3\x99\
+\xcc\x19'\x84\x00U\x02\xb7\x85\xa9\xf7\xc40M\xa5\xb1\
+\xaau\x07pJ.\xb7\x81\xd1\xc6\x85\xd1\xbd\xe6\xf7V\
+\x1a;\xd6n\xd4|\xbc\x01%C-\xe0\xfa\xe3s\x05\
+\x94D\xd8\x16\x89LKX\x1d,\x10\x04~$\xf8\xc8\
+\x17P\x0a\x15\x0c\xa3\xb5`\xe9\xfa-\xd1\x94\xb5\x03\xbd\
+c&\xe4\x8cF\x96^4\x89\xa1v\x92\x8eu\xe7\x95\
+\xa3\xc6\xfa\xdd:\xd7\x00\x00\x10pIDAT\xe4\x87\
+\x14\xd2\x9f\xf8\x86 \x83\xa10_p<\xecX\x0b]\
+\x1b.\xa5\xa9\xb3\xf25\x97\xb2\x92\xde\xe7\x1e\xa60\xb2\
+=\xaaI @\x888\xd5\xcefa\xe4 #\x87\xa2\
+\xf0\x88\x07\xbc}\xcbV\xfd\xad9\x8a\x018\x8e\x04\x10\
+\x06\x96\x10\xc2f\xbc\x90k\x09\xbf\xbc\x1e{r'\xff\
+Y\xbeFnhot\xbdX\xd2$f8\xf1z4\
+q\xb4R\xf8n0\xc9\x0fP\xca#\xd3\xbc<T\xf5\
+e-\x10\xd6\x02BM\xa0\xb4B\x05Ch4N\xa2\
+\x95\xae5fpS)\x15\x83\x87\xb2a\xf3\xb1\x8b\xef\
+\xee\x03\x0d\xf1\xf4\x12ZWl@c\xbe\xe2\x91\xc3*\
+jQ\xac\x86_\xda\x83\xef\xee\x9f\xb4_XIZV\
+\xbe\x92\xce\x0d\xa7b;aT\xd1\x87\xc3\xbb\x9eg`\
+\xef\x1d(9B\xaa\xe1\x958\xc9\xb5\xe1/4C=\
+w\xb3\xe7\xe1\xbfAz#`z\xcf\xbdq\xcbV}\
+\xcb\x5c\xe5Q\xc6\x82\x12`\x82\xd0'\x0a\xdc\xa9\xb1/\
+6q\xf9\xc8\x979\x10H\x9e\x03\xc8\x0d\xeeG\x87C\
+\xf9\xc5R\xa7\x00\x84\xde\xfeR\x94R\x04^0),\
+\xac\x94$]\xd7\x81I\x13\xd7d\x87\xf3\x91\xf0UU\
+\x8d@\xc9<Z\x16\xd1Z\xd3\xba\xe2\x5c\xe2I\x93\xd6\
+?6\x90\xc7-\x85\xdezi\x17Q\x18\xb7\xe3\x0cR\
+\x0dM&^\xe0\x9b*^-\xb8\xf9'\x91r\xa4\xc6\
+\x11A\xa6\xe94\x96m~%\xc9\x86ph\x0c\x0d\xd9\
+\xfe\x1c}\xbb\x9f\xc7+\xf5\xa1\xb5\x87V.\x87\x9f\xff\
+>\x07\xb7\x7f\xbb\x5ck\x18\x06^\xb7e\xab\xfe\xc5\xdc\
+\xa42\x1e\x0bB\x80Y\x0a}\xa2\xe0\xa7:\x1e\x1b\xcd\
+\x19-\xa0\x02\x8f\xe2\xa8\xa9f9\xf1\xa5\xd8\xb1V\xb4\
+\xf6\x89\xa7\x96\x86I\x9d\x0a\xafTv\x06\xab\x92ED\
+@\xa6i\x05Z+\x8a\xb9\x12~\xc93\x82\x8f|\x01\
+Y\xa5\x05\x14B\xc4Y\xba\xc1\xe4pj`\xa87g\
+\x9a\xa4U\x09\xdf-wY\x15\xb4\xaf9\x1f;f\xe6\
+0*\x8ei\xdc|\x0d5\xa0%\xa5\xb1\x87\xd0\xda\x9b\
+|\x0cp\xe2\x1d,\xd9p)\xad+Wc\x85=\x8c\
+\x0a#=\xec~\xf0\x06\x06\xf6\xfd_\xf6>\xfay\xfa\
+\xf7\xfc\x22|\x12\x0e\x05\x92K\xb6l\xd5\xf7\xcfM2\
+\x93q\xcc\x08Pe\xd7\x1d\xc2a~j\xfc\xad%\xfc\
+\xf2\xf1ZZ\xc0\x01\x9c\xc7v\x10u\xbf\xce\xf6U\xec\
+j<}\x06(\x0f'\xd5\x82\x10)\xb4V\xb8\xc5\xc9\
+\xb5\x01)sdZ\xd6\x86f@32\x90\x8d\x82A\
+\x91/\xa0\x94\xf1\xc6\x95is\xc8\xb4\xae\xa1\xae\xc5\xd4\
+\xb2\x8a9\x8fb\xd6\x03\xad\xf1\x8b/P\xce\x06\xb5\x9d\
+:\xda\xd7\x9d\x13\x99\xe9l\x7fm\x7f@\xab\x02\xa5\xec\
+#L\x0a!\x96\xcb\xce\xce\xd0\xb1\xfe=l|\xf5\xf5\
+\xd4\xb5\x9a\x0cr\xe9\x178\xfc\xdc/\xc8\x0d\xee6\xd7\
+\xd0\xec\xe9\xed\xe75\x97\xfc\x11;B\xdf\xe9\x98\xc8n\
+\xde\x17)\x0b\x9e\x8a g\x12~\xad\xfdSi\x00\x07\
+\x88]\xf7M^\x08\xa4\x99\x88zl\xe0E\x944i\
+\xdd\x89\xccf\x94\xcca\x09M\xa2n\x05Ji|\xd7\
+D\x06\xc7\x91 \xc8\x91\xaa\xef\xc0\x8e\x9b\xfe\x01\xa3C\
+y\x02?\xac\x0aF\xb5\x01C\x00\x1d&\x8a\xa04]\
+k\xcf\x8f&\xa5\x18>R\x08G\x13\xcb\x13x\x95T\
+\xb2t\xfd*\x9a\xbaL\xe8\xd6x\xf5\xb5\xfd\x01\xe9\xf7\
+\xe1\x15vL\xdao9\xcd\xa4\x1a/\xc6\x89\xaf \x96\
+\xecd\xcd\xcb?LC\xc7\xf8i\x8f\x95\xe2\x99\x07\xb7\
+\xf3\xba+?\xc2\x81\xea\xf2;\x16D\x98\xd7\x8f\xc3\x9b\
+\xdbL\x16|-!\xdb\xd4\xd6\x04Si\x88q\xc4\xe8\
+\x1f\xe2?\xc0\xf4\xd5\xcb\x0dl7\xf7\xb7\xd28\xc9U\
+(\x99%Y\xbf<\xca\xd1\xf3J\x15\x02\x98\xe4\x911\
+4\x8a\xe6\xce\xf5f^B\xa9\x18\x1d\xcaU\xc6\x09\xd4\
+&\xa6\xa0\xfc1\x94r\xa3<\x80X\xaa\x91\xd6e\x9b\
+\x01\xf0]En\xd8\xb4\x03x\x85\x9dTK\xb9y\xd9\
+9$\xebM\x10)\xf04c}\xaa\xe6\xc7\xee\x15w\
+\x12x\xbda\xe1\xd9$2\xa7\x93j|5\x96m\xe6\
+:T\xc10=\xdb\xafg\xacog\xf4\x1b%y\xfa\
+_\xff\x83+>\xfc\xf7\x0cL(\xebh\x09\x890\xa7\
+d\x929\x11 t\xeej=\xcct\x84\x98H\x86\xe9\
+\x04?\x89\x08\xdf\xff\x19\xb7\xea\xd0\x03\x1b\xee\xad\x98\x81\
+D\xe6td0\x82\x93l\xc0\x8e\x99\xb1F\xbc\x92\xaa\
+\xd2\x00\x01\x817\x88\xd6\x8a\xba\xd6\xd5\xa6\xbd^iF\
+\xfb\xf3\xc6a\x0c\xd5\x7f\xb9j(\xbd\xde\x8a\x16\xd0\x9a\
+\x96e\x9bq\xe2F\xb8c\x03\x9ei[\x90\xd9qZ\
+@\x08\x87\x8eu\xaf\xc0\x8e\x9b\xe2t\xf3z\x8a \x11\
+\xb8\xb9\xc7\xb0\xec:\xd2M\x97\xe2$\xd7S\xb6\x1f\xc5\
+\xb1\xc7\xd9u\xff\xc7\x19>\x18\xcde\xa5Gs\xdc\xf0\
+{\xff\x9b\xff\xf1\xcd[\xc8NS\xa6\xd5D\xb0\x8e\x96\
+\x07GM\x80\x09_\xfdD\x81O$C\xf5\xf1Z\x0f\
+>\x93i\x88\x8e\xfd\xf8.\x06\x87F\xf8\x15@);\
+\x88\x9b7\x02\x88%\xd7\x82v\xb1\x04$3+\xd0\xca\
+|\x85J\xaa*\x1f\xa0\x84\x0c\xc6\x10V\x82\xe6\xaeS\
+@C\xe0+r#\xc5*_\xc0\x90 p{\x22\xe1\
+k4\x96\xe3\xd0\xbe\xfa\x5c\xc04\xe8\x8c\x0d\xf8h\xad\
+\x8d\x16\xa8\x82\x13k\xa6k\xfd9\x94{\x8a\x17F'\
+\x07\x89\x84\x95$\xdd\xfc:\x9c\xe4j\x84\x95\x0c\xaf\x99\
+c`\xcf7y\xf1\x81/\x87I\xac\xa0\x14\x83\xdbw\
+\xf1\x07\x97\xff\x19_:db_S\x0a\xbd\x96\x0c\x8e\
+F\x1b\xcc\x9a\x00U\xb6\xbez\xb1klOE\x8c\xd9\
+\x90a*\x12\xc4\x00\xe7\x8e\x07\xf9a\xf9yF\x0e\x95\
+\xb5\x80\x85\x153A\x95d\xc32\xc0\xf8h^QG\
+YCJI\x02o\x00\xa5\x15\x0d\x1d\xa7\x82\x153\xbe\
+@\x7f!\xca\x11\xd0a\xbb@\xe0\x0f\xa2dq\x9c\x16\
+\xa8k]N\xb2\xde8\x84\x85Q\x89WP(9F\
+\xe0U\x0dq\x0a$2\xabi[S\xb1\xdf\xd9\x01\x85\
+W2$\x88\xa76\xd2\xd8u\x0d\xf1\xf4\xe9h\xe5\x12\
+\xb8=\xb8\xb9'\xd8\xff\xe8G9\xf4|w\xd4\xcb\xa8\
+\xe4\xf2\xe0?\xdf\xcae\xef\xfd\x1c\xdd5\xcah\xba\xb2\
+\x1d'\x83\xd9\xfa\x06\xb3:)d\xd4D\xe1O\x14z\
+\xad\xaf~\xba}S1zJS\xf1\x8f7\xf3|\xb6\
+\xc0\xb3\x00\xa3\x87w\x98\x8c_ \x919\x03%s8\
+\xc9\x0cv\xdc\xb4\x9e\xb9\x05\xd3\xa6o\xaao\x12\xe9\x0f\
+\x86\x91A\x87\xa6\xaeS\xc3F\x19\xc9\xd8P1j&\
+.\xfb\x0c\x81{\xc0d\x1f\x85\x03S\x80\xa6}\xcd9\
+\x18\xab\x07c\x03\xd2\xa4}\x15'O=X\xd7r:\
+\xcd\xcb\xc2Lo\x0d\xa3\x87\x14\x96}\x01\x99\xd67\x99\
+\x96L\x8c\xad\x1f\xdc\xf7-v?\xf4\xf7d\x07\xa3\x18\
+\x81:\xd4\xcf\xd7\xde\xf2\x17\x5c\xfd\x83\x9f3\xc8\xe4\x0f\
+j\xaa\x8fn\xcae6$\x98\xf1\x04QI\x7f\x99\xe9\
+\x86S\x9d3\x1b\x06\xcfd\xdf\x22\x12<\xf2\x8c\x99\x8a\
+F+\x8f\xd1\xde\xfb\xc3gL`\xc7\xdb\xb1\x04\xa4\x9b\
+V\x86#\x7f\x84=y\x01\xd0\xf8\xee\x91(\xe8\xd3\xd8\
+\xb9\x01;\x96\x06`\xa4\xaf\x84\xef\x07\xe3\x9a\x87}\xef\
+\xa0\xa92\xea\xb09H+\x12\xa9:\x9a\x96\x98\xe0\x93\
+\xf4\xa10\xacP\xc1\x08\x81_=\xfa\x88)\xaa\xa6%\
+\xe7Q\xdfj\xfc\x11\xad\xe1\xc8\x0b\xf73\xd6\xf7\x0c\xa0\
+(\x8e>D\xcf\xf6\xef\xd0\xb7{\x1fA\x18\x1a\x90\x92\
+\xc1\xbb\x1f\xe5=o\xfb\x08_\x1b\xcd\xa1\xa9-\xf8\xd9\
+\x0a\x7f\x9c\x1cf\x22\xc1l4\xc0l\xd8V}\xd3\xa9\
+\x1e~\xba\x97\x98\xadf\xb0\xbf\xf0\x1d\xees}\x06\x00\
+\x06\x0f<\x82\x0aL[\x88\x93X\x8e\xb0S\xa4\x1b\x97\
+\x81\x16h\xcd\xb8\xc0\x8c\x929\xa4?d\xda\xff\x1dA\
+\xeb\x0a\x13\xee\xd5R3r\xb8T\xe54*\xa47\x88\
+R\xf9p\x04\x11\x15\xf9\x03MKO\xc1\x89\x1b\xe2\xe4\
+G4\x81\xab\xf1\x0b\x93\xb5\x80\xed4\xb1\xe2\xac\xbf\xa2\
+u\xb5i\xb8\xd1(\x0e=\xf7\x13\x0e<\xf5Mz\x9e\
+\xbe\x93\xe2X%X08\xc2\xcf?\xf5\x0d\xde\xfa\xf1\
+\x7f\xe4\xe1Y\x94\xddl>\xc4\xf2y\xd12\x9dO0\
+-\x01\xc2\x1f\xcef\xa9u\xf3\xe9\x1en\xb6\x0c\x9fD\
+\x80|\x11\x9e}\x91\x9f\x00(\x190x\xe0\xd7\x84\xa5\
+l\xa2\x83N\x82dC{\xa8\xe2\x19\x17\x98\x09\xdc\x03\
+F\x98JQ\xd7\xba\x82x\xa6\x09\x80b6\xa0\x98\xf3\
+)\x8fC\xa0\xb52\x11\xbf*\xe1k\xad\x11\xc2\xa2m\
+\xf5\xd9\xd1\xf5\xb2\x03\x9a \x18B\xfa&\x81D\xd8i\
+\x12\xf5\xe7\x92j\xba\x14;\xbe\x9c%\x1b\xdfA\xe7\xba\
+K\xa3\xf3\x0b#cQ\x0e\x81\xeb\xb1\xef\xe7\xf7\xf2'\
+o\xfa \x7f}\xd7#\x8c\xcePfS\x91`\xa6\xb2\
+\xae\xd6\x045I0%\x01\xaaT\x7f\xad\x1bN\xb7\xaf\
+\x169\xa6\xda\x9e\xc9d\xd4\xd4\x12_\xfc.?w=\
+\x06\x01\x86z\xb6\xe3\x15\x8d\x1a\xb6\xecF,\xa7\x99\xfa\
+\xb6\x8dQk]q\xacR\x1d\x0b\xdc\x9eqM\xb4\xed\
+\xab\xcf\xa1\x5c\x0d\x1b=\xe2#\x03\x15%\x92\xfa\xc5\xfd\
+&;\xb8\xdc--\xac\xf7\xa7\x1b\x97\x90i6\x89\xa4\
+\xbe\xab)\x8ej\x02\xef \x89\xba\xb3H7\xbd\x16'\
+\xbe2\xbaf\xe0\xf5Q\xca\xef\x1c\x97=\xa65\xfe\xce\
+}\xfc\x9f+\xff\x92w~\xfe_x\x9c\xa9\x85;\xd3\
+\xbe\xa9d0\xdd2\x09\xd3i\x80Z?\xacu\xc1\xe9\
+\x04m\xd5\xf8\xddlH2-Az\x8e\xe0\xdf\xf1 \
+7\x96K\xb4\x7f\xf7]\x80Q\xf3\xf1\xf4)$2\x1d\
+$\xd2\xadh4^AG\xbe\x80\xd6\x1e\xd2\xab\xd8\xec\
+D\xba\x85\xa6e\xa7\x01 \x03Mn\xc8\x8f4\x80\x0c\
+F\x08\xdc#a\x82\xe8\xf8\xea\x5c\xdb\xaa\xb3\xa3\x91\xc1\
+\xf2\xc3\x82D\xe6\xb7\xb0c\x9d\xd1\xebJ\xbf\x9f\xbe]\
+\xff\x87\xe7\xef\xf9$\xa3\x87\x0fDA\xa1\xb1<\xdb\xaf\
+\xbf\x91\xad\xd7|\x8a\xef\x0d\x8e \xa7x\xbf\xd9\x96\xcd\
+Q/\xb5\x94\xc0l\x090\x15\x9b\xa6#\xc9l\xaf3\
+\x91$\xb3\xd2,\x7f\xfbm\xee\x1b\x18f;@np\
+\x0f\x85\xd1=\x80F\x88\x18Nb\x19MK7\x83\xd1\
+\xe0\xe4\x87+\x02\x0c\xa2\xc6\x1c\x83\xa6%\xa7\x10O\x9b\
+IM\xf3#\x8ab\xb6\xec\x0c\xea\x9a^>\x80\x93\xec\
+\xa0c\xddk\x01\xd0Jrd\xd7/\x91~?*\x18\
+a`\xcf\xf7\xd9q\xd7G8\xb2\xeb\x9e\xa8j\xe7\xf9\
+\x0c\xde\xf1\x00\x9f\xbd\xec}|\xe0'wsh\x16e\
+2\x9b\xb2\x9e\xaa\xec\xa7\xc3\xa4\xe3s\xed\x9e<\x9d\xd0\
+\x8f\xe5\xcbL{\xdd\x7f\xbe\x95\xef|\xec\xdd|I\x08\
+\xec\xbe]\xff\xc5\xaasW#\x83!\x12ug\xa3d\
+\x96T\xd3s\x14\x87\x8f\x10\xb8\x9aRN\x93\xac\x13\x04\
+\xdea\xb4\xf6\xc2d\x0b\xb0\x84\xa0c\xedy\xf4>{\
+\x07J\xf9\x8c\xf5+3T\x5cJ \xfd\x01d0\x84\
+\xed\xb4\x00\x02;\xd1E,\xb1\x06;\xd6N\xbaQ\x93\
+\xed\xdfEad7\xf9\xe1\xbd\x1cx\xfa\xdb\x14Fz\
+\xaa\xe7\x1d\xc2\x0f\x18\xdb\xbe\x8b[?\xff/\xfc\xf8\xd0\
+\x00\x85)\xcan\xb6\xe5\xadg\xd8.\xef\x9bM\xd9F\
+\xa8\xa9\x01j\xa8\x8a\xe9\x1e\xf8h\x188W\xd4$\xc6\
+\x7ft\xd3\xf3\xcc\x8b\xa6\x8d\xc0\xcd\xf71\xdcs\x0fZ\
+y\xa8 G\xb2\xfe\x02Z\x96\x9b\x08\x9e\xd6\xa6\xdaf\
+\x8aLM\xd2\x02\xf1T\x9a\xf6uao,m\x1at\
+\xca]\xbd\x03\xf7 \xf1\xf4&\xd2\xcd\xaf'Yw>\
+v\xac\xc3\xdc^Xtm\xfc\x9f\x94\xb35s\x03{\
+\x22\xe1\xfb\x01\xd9\xc7vp\xd3\x1f~\x9ck\xde\xff\x05\
+n=4\x80\xcbd!LWn\xc7\xaa\x1cg\xbc\xce\
+\x94\xe3\x04\xd6\x88\xfa\xd5r\xd6\xc4\x14\xdb\xd5\x0e\x9c`\
+\xfa\xaa\xcd\xbc\x96%m\xa4\xbf\xf7y\xbe\x9c\x8c\xd3\x82\
+\x80\x95g\xfe\x0e\xe9\xa6\xb3\x88\xa5\xd6\xa3\x82az\x9f\
+\xfd{F\x0e\x1d@\x03\xe9FA]\x8b\x85\xb0\x12\xa4\
+\x9b.\x8d\xb4@\x19#\xbdO3t\xd0\x84xm'\
+\xc6\xb2\xcdo \xd5x*\xb1\xd4\x06\x84\xa8\xccgR\
+\xca\xbe\xc0\xe0\xfe\xdb\x19\xeey\x98\xf2\xb8\x81\x00A@\
+\xfe\xa9\x17\xf8\xf1\x97\xb6q\xdb\x81\xc3\xe41\x09\xad\x1a\
+\xd3\x86\xa1\x8e\xf3\x22\xab\xee\x1fmO\x1c\x92o>\x04\
+8Y\x16\xf1\x91\xab\xd9\xf2\xa6K\xf8\x80\x11\x9c\xc3\xaa\
+s\xaf\x22\xd5p\x0e\x96\xd3\x8a_|\x91]\x0f|\x81\
+\xc0-\x81\x80\xa6.\xa3\xdec\xc9\xd5\xe1\xe0\xcf\x80\xb0\
+\xb1\xe3\x1d8\xb1\x0e\xfa^\xbc\x93\xc1\xfdw\x01\x10O\
+\xb7\xb2\xf2\xec?$\x96\xec\xc4v\xda\xc8\xf6?B\xff\
+\x9e_P\x18\xd93\xae\xac|I\xee\x99\x17\xf8\xf9\xf5\
+\xdb\xb8m\xff!rUB\xa8%\xfc\x89\xfb\xc6\x09\xe8\
+(\x7fw\xb4\xc4\x92\x13\xe5=\x1d\x01\xaa\xbf\xee\x13&\
+\xdc\xd9\x9e\xf7\xdd\xcf\xf0\xbf6\xac\xe4uFp\xf5\xac\
+>\xf7]$\xea^\x06Xd\x07\xba\xd9\xf7\xd8w\xb0\
+c\xf5\xc4\x92\x0d4/k&\x96h \xd9p\x11N\
+\xac\x13\xcbi\xa2b\x0d%\x07\x9e\xfc&#\x87\x1e\x00\
+ \xd5\xb8\x82d]\x0b\xa3Gv\xa0\x82\xf1Y=#\
+Yv=\xb4\x9d\xdb\xff\xe9f\xee\x1d\x1a\xc3\xad!\xb0\
+\xb9|\xb9S\x09\xbf\x16I\xa6\xfc\xd2k\xed\xd3\xd5\xea\
+\xaa,\xe7\xe9\x86\x8a]`-0k\xe1\xceb\x9fH\
+%\x88\xdd\xfcE>\xd9\xd6\xc4f\x80\xba\xd6%\xac<\
+\xebZ\xec\xb8i\xc4)\xe5\xfa(\x8c\x84\xf1\x02G\x90\
+n\x10\x08+aZ\x13#\xe1\x83R%\x0a#\xbb\xe8\
+y\xea[\xf8\xa5\xc9\xa3\xbcJ\x85\xbb\xb7\x97\xee\xdb\xee\
+\xe2\xf6\x1f\xdd\xc1n\xa6\x17\xfaL$8\xae$\xa91\
+\x22\xeb\x8c\x048\x1a!M\xb4\xfb\xf3!\xc1$\x01O\
+sN\xf4w\xc3*\x1a\xbe\xf6Q\xbe\x98N\xd2\x05\xd0\
+\xb2\xf2t\x96\x9ezmd\xeb\xf3\x83{q\x8b\xa6\xc9\
+5\x16\x17$\xea\x04\x888Z\xda\xe4G\x9e'\xd7\xff\
+4c\xfd\xcf\xa3\xd5\xe4\xfc\xbd\x5c\x81\x9e'wr\xc7\
+7o\xe1\xae=\x07#5\xaf\xa7\xf8;\xdd\xfa\xd1\x12\
+`\xae$\x19\xb7\xd4\xfa\xfaa\x06\x02\xc0\xbcL\xc1L\
+\xbf\x9b\xe9\xcb\x9e\xeax\xads\xa2\xfd\x97\xbf\x8a\x15\x1f\
+\xb9\x9a\xeb\x1d\x9b4\xc0\xb2\xcd\x97Q\xdfq\x09*\xc8\
+\x13x#\xf4\xef\xbe\x17\xbf8D\xe0\x8f\xa1\xd4\x18\xca\
+\xaf\x91\xc4g\xa0G\xb2\xecza?\x0f\xfdg7\x0f\
+\xdd~\x1f\xe5\x11$\xca\xcbD\xc1OG\x82\x99\xc8p\
+\xac\x082\xd1\x1c(\x8c\xdd\xaf)|\x98\x05\x01\xa0\xa6\
+)8\xa6\xea{\x16\xc7j\x05\x88j\x12\x00\xe0C\x7f\
+\xc8y\xbf{)\x9f\xe2(\xabSJ\x13\x0c\x8e\xb0}\
+\xc7n\x1e\xbc\xf5\x0e\x1e|l\x07\xc3\x8c\x17\xfaT\xcb\
+\xd1\x90a\xae\x848\x1a\xe2T\x7f\xf9\xd5\x93\xafL\xc2\
+\xac\x87\x8b?\x0a\x12\xccF\xe8\xd3\x09\xbe\x96p\xa7\xfa\
+[\xbd\x8c\xdb\xf7\xd5\xff\xcd[\xcf=\x95wO\xf7N\
+RQ8\xd4\xcfC\xbd\xfd\xec\xda\xb1\x9b]?\xfb5\
+/\xf6\xf6S\xa2\x12d\xa9\xfe;q\xbdZ\xd8\xb3!\
+\xc3l\xb4\xc3|\xb4E\xadc\x93\xbc\xfe\x898\xaa\xf9\
+\x02\xa60\x07\xc7J\xe0S}\xd1\xb3\x16\xfa\xc4\xe5\xdb\
+\x9f\xe6]\xe9\x14-%\x97\x5c\xc9#W(\x92\xcf\x17\
+\xc9\x1d\x1ed\xf0\xce\x87\xd9\xf3\xdcn*\xa3F\x8f\xc7\
+T\x04\xa8E\x84\xe9\x081\x9d\x9f0_2LG\x8e\
+i\xd5~5\x8ez\xc2\x880JXv\xf8fc\xb3\
+gR\xe73\xa9\xf6Z\xc7\x8ef\xa1\xc6\xdf\xd9b:\
+\x0d0\x1b\x930\xd3\xfatZb\xaed\x90\xb5\xbc\xfd\
+\xa9p\xd4m\x01\xe1\xb5\xa5\x10Bc\x04R~\x81\xea\
+\xf5\xf2R\x8eO\xab\xaa\xe3\x13\xf7\x95\xff\x8a\xaa\xed\x99\
+\xd4\xfdt\x84`\xc2\xdfZ\xc2\x9f\x89\x08z\xc2\xfaL\
+\x1aa.d\x98J\xe8s%\xc3\xac\xbf\xfaj\xcck\
+\xca\x98P\x1bL\xf5\xd5\x1f\xad]?*\x1b_ca\
+\x9am\x98=\x01&\x0a\x7f\xaa\xbfs1\x09\xd3\x99\x83\
+\xf9\x98\x8a\x9au\xfc\xd9\xe0\x98\xcc\x19T\x83\x083\x91\
+`N\x8e\xdd,\x16j\xacW\xff\x9d\xb8>\x1d&\x0a\
+}\xe2\xbe\xf9\x9a\x05\x98=\x19ji\x87Y9y3\
+\xe1\x98N\x1a5\x81\x08\xb3\xb5\xefLq\xcelT>\
+\xb3\x5cg\x9a\xf5Z8Z-0q{\xbefa:\
+R\x94\xa3z3\xbc\xc2\xec\xb0`\xb3\x86M\xa81\xd4\
+\x12\xdeL6~\xaa\xfdL\xb1\x7f:\xfb\xcf\x84c\xb3\
+\xc1\xc4\x82\x99\x8a\x00\xd5\xebS\x91b*sp4d\
+8*\xe7n\xb6X\xf0i\xe3j\xa4\x95\xcfE\xe8s\
+U\xf9\xc7\xc2\x04T\xaf\xcf\xc7'\x98\xc9G\xa8\xb5-\
+\x81\x85\x90{\x84\xe3>o`\x95f\x98\x8b\xc0\x8f\xd6\
+\xe1\xabE\x80Z\xdb\x13QK\xf8\xd5\xeb3i\x81\x89\
+\xdb\xb3%\xc3\xbc\x1c\xba\xb9\xe0\x84N\x1c9A;\xcc\
+d\xe3gK\x02&\xac\xcf\xd5\x0c\xccD\x82\xf2\xfa|\
+\x08Pv\xe6\x16\xf63\x9f\x06'\xc5\xcc\xa1\xd5\x98\xd0\
+\x17\xa1\x9a\x10\x1c\xc5z\xf5\xdf\xe9\xd6\xa7\xc2T\xf6\xbf\
+z}\xa2\xb0k\xed\x9bR\xc5\x9f,\xe5~\xd2\x11\xa0\
+\x16&\xf4Q\x98\xad\x1f@\x8d\xed\xa3q\x02a\xea/\
+\xbf\xbc=\x91\x00\xb5\x9c=N\xe62~I\x10`:\
+T%\xb0\xce\xd6\x14\x1c\xad\x06\x98\xe9+?\xa9\x05<\
+\x13^\xf2\x04X\xc4\xfc\xf0\xff\x01-\xef\xe5]0^\
+&Q\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00:\xf4\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\
+\x00\x00\x09\xediCCPICC Prof\
+ile\x00\x00x\x9c\xad\xd6gTS\xd9\x16\x07\xf0\
+\xff\xbd)\x84\x04B\xef- \xddP\xa4Jo\x8a\x0d\
+\x18D\x14\xb0\x02!4)\x11\x82(vP\xb0\xa1`\
+W\xb0+v\x05\x95Q\xc7\x8a\x0a\x22\x8c\xa24\x11Q\
+, 8\x22\x1d\x0b\x82y\x1f\x82e\xd6\x9bY\xef\xcb\
+\xdb\x9f\xf6\xd9k\xdd\xb3\xce\xf9\xed}\xd7:\x80\x94b\
+\x98@\x10G\x02\x88O\x10&\x05L\xf0\xe4\x04\x87\xcc\
+\xe4H\xd4\x81\x0a5H\x03\xb0\x0f\xe3%\x0b<\xfc\xfd\
+}\xf0\xaf\xf1\xb1\x1e\x04\x00\xd4\x98\x85\x09\x04q\x89G\
+\xa3\xab\x11\x97\x97\xa9\x92\xe3\xc2\xe9\x9f\xab\xfb\xf8\xdf\xbf\
+\x03\x00\xb0\x93\x82Cf\x02\x04\x17\x80b\x948w\x07\
+\xa0\x18.\xce\x03\x01(\xa6\x0a\x05B\x80\x88\x06\xa0\xc8\
+\x8b\x0e\x8b\x00\x88\xa5\x00\xb8I\x81\x01^\x00q\x1c\x00\
+;J\x9c_\x06\xc0\x0e\x17\xe7\xe5\x00\xd8\x0byQB\
+\x80h\x00(\xf2\x09\x111\x09\x00\xb5\x03\xa0\xbbF\xf0\
+\x93y\x00\x8b\x0b`^D2/\x1e`m\x04`\x19\
+\x1f\x9f\x18\x01\xb0\xae\x010\xe6\x09\x92\x84\x00\xab\x05\x80\
+Yp\xc8L\x8e\xf8\xc8\xe1\x91\x80u\x08@\x1e\xffY\
+\x9b/\x05\x14i\x02\x8a5?k&\x11\x80F\x01p\
+\xf5\xc4\xcfZ_\x00\x08\x00\x84rUr\xa4\xb5\x15\x00\
+\x80\x90\xf2\x04h/D\xa2>C@b\x0b0\x9c+\
+\x12}=$\x12\x0d\x1f\x06(M\xc0\xad8^J\xd2\
+\xc2\x11/\x82x\x00\xfc\xaf\xb5\xf8\xce#A!\x00\x02\
+$\x95\xce\x90dI\xb1e\xe4\xe4\x15\x94\x94U\xd54\
+4\xb5u8z\xa3\xf4\x0d\x8d\x8cMGs\xcd-,\
+\xc7X\xdb\xd8\xda\xd9\x8futrvqus\xf7\xf0\
+\xf4\x1a7\xde{\xc2\xc4I\x93\xa7\xf8\xf8\xfa\xfd\xe6?\
+5 p\xfa\x8c\xa0\xe0\x90\x99\xb3\xe6\xcc\x9d\x17\x1a\x16\
+\xce\x8b\x88\x8c\x8a\x8e\x89\x9d\x1f\x17\x9f X\x90\x94,\
+LY\x98\xba(m\xc9\xd2e\xcbW\xac\x5c\x95\x9e\xb1\
+&3k\xed\xba\xf5\x1b6fo\xca\xc9\xdd\xb2u\xdb\
+\xf6\x1d;w\xed\xde\x93\x97\xbfw\xff\x81\x83\x87\x0e\x1f\
+9Zp\xec\xf8\x89\x93\xa7N\x9f9{\xae\xb0\xa8\xe8\
+\xfc\x85\x8b\xc5\xbf_\xba|\xe5\x8f\xab\xd7\xae_\xbfq\
+\xf3V\xc9\xed;w\xef\x96\x96\xdd+\xbf_QQ\xf9\
+\xe7\x83\x87UU\x8f\x1eW\xd7\xd4\xd4\xd6\xd5\xd5?i\
+hx\xda\xd8\xf8\xac\xa9\xe9\xf9\x8b\x17\xcd/_\xbez\
+\xfd\xfaMKK\xeb\xdb\xb6\xb6\xf6w\xef\xfez\xff\xbe\
+\xe3CggWwwOo__\xff\xc0\xc0\xc7O\
+\x9f?\x7f\x19\x1c\xfc:44\xfc\xed\x9b\x08$\x95.\
+!\xc9\x94\x92\x96\x91\x95WPTVQS\xd7\xd4\xd2\
+\xe6\xe8\xea\xe9\x1b\x18\x1a\x9b\x98r\xcd\xcc-,\xad\xac\
+ml\xed\xc6:\xfc\x1b\xc0\xb4\x11\x80\xd9#\x00\xfc\xef\
+\x00\x89?\x00\x16\xff\x00X\xbd&3k\xed\xfa\x0d\x1b\
+\xb37m\xfeE \x7f\xef\xbe\x7f\x10\x18\x01\x10\x0b\x88\
+\x01\xee\xfc\x0d\xe0\xd1\xe3\xc7\xd55\xb5\xb5u\xf5\xff\x08\
+\xd0\xfa\x03\xa0C\x0c\xd0\xd3\xd3\xdb\xd7\xdf?\xf0\xf1\xe3\
+\xa7\xcf_\xbe\xfc\xbc?\x85FgH2Y\xd2l\x19\
+Yy\x05E%\x15U5u\x0dMm\x1d\x8e\xae\xde\
+(}\x03#c\x13\xd3\xd1\x5c3s\x0b\xcb1V\xd6\
+66\xb6v\xf6c\x1d\x1c\x9d\x9cG$~\xa5\x10\x0f\
+\xc3w\x8cY\xb3\xe7\xcc\x9d\x17\x1a\x1a\x16\xce\x8b\xf8\xe1\
+\x91\xf0\x0bH\xda\xdfE\xd6\xfdB\xf2}&\xbe\x93\xfc\
+\x93\x89\x98dd(J\xcb\xee\x95\x97\xdf\xff\x95\xa4\xae\
+\xfe\x89\xd8\xe3\xf9\x8b\xe6\x97\xaf^\xbfii}\xdb\xd6\
+\xfe\xee\xaf\xf7\x1d\x1f:\xbb\xba{z\xfb\xfa\x07>~\
+\xfe2\xf8uh\xf8\x9b\x08\x10\xff\xfb\x00@\xb7\x03\x0e\
+'\x003\x98@\xe0!`{1`\xe4\x04\xa8t\x01\
+\xfe\xd2@\xa0\x03\xc8dk\x90\x91\x91 U\x98\xa0\x10\
+\x00\x09\x80\x00\x05tHB\x06\xca\xd0\x81)\xec0\x0e\
+\x81\xe0#\x15\xeb\xb1\x0f\x17Q\x89\x16|#\xd4\x09{\
+b:\x91Ll%\x8a\x89\xa7\xc47\xd2\x80\xf4%\x17\
+\x92\xfb\xc9J\xf2\x0b\xc5\x84\x12B\xd9@\xb9I\xe9\xa7\
+r\xa9\x11\xd4\xbd\xd4\xa74UZ\x10m7\xad\x89\xae\
+G\x8f\xa6_\xa0\x8b$|$\xf6Ht0<\x18\xbb\
+\x18\xbd\x92~\x92g\x98l\xe6\x02f\x03\xcb\x8bU(\
+\xa5-\xb5I\x9a\x94N\x93\x1e`'\xb3\xfbdRe\
+\x86e3\xe5\xe4\xe4\x0e\xca\xdb\xc8W(\x84+|S\
+\xdc\xad\xa4\xaftJ\xd9J\xf9\x9a\xca\x04\x95\x1a\xd5p\
+\xd5~\xb5u\xeaZ\xea\x175|4Z5\x97i\xa9\
+h\x15k\xfbkw\xea\xe4pl8\x8d\xba\x19z\xa3\
+\xf5\xaaG-\xd5\xb7\xd0o2\xd8h\xe8b\xd8it\
+\xd08\xc8\x84mRj\x9a>\xdak\xf40\xf7\xba\xd9\
+\x0as\x0f\x0b\x9aE\xa5\xe5\xb61s\xac\x8c\xacz\xad\
+o\xda\xe4\xd8\x86\xdb\xd9\xda\xb3\xec_\x8f\xbd\xe2\xb0\xd9\
+\x91\xef\xe4\xe2\xac\xe5\xfc\xcd\xa5\xd9\xf5\x86\xdb\x01\xf7\x0c\
+\x8fH\xcf)^\xd6\xe38\xe3e\xc7\x0fywO\xa8\
+\x9fxo\xd2\xed\xc9%Sn\xfb\x94\xf9V\xfa=\xfa\
+\xad\xce\xbfi\xea\xbb\x80\xaf\x81r\xd3\x8df8\x07\x05\
+\x06\x0bB\xb2g\x9e\x99U3[4\xd7b\xde\xbc\xd0\
+\x9c\xb02\x1e\x19\xe1\xc6_\x12y5\x9a\x12\xe3\x1f\xbb\
+w~w\xfc\xe4\x84<\x01\x16\xf0\x92\xca\x84\x96)\xfb\
+S\xe5\x16\xadMc,Y\xbetp\xf9\xca\x95\xccU\
+[3tV_\xca\xf4\xc9j^\xb7d\x83\xd6\xc6\x92\
+M\xc1\x9bE\xb9\xa7\xb7\xce\xda.\xb1\xe3\xcc\xae]{\
+\x8a\xf2_\xef\x97=\xe8|Xp\xf4\xd8\xb1\xfa\x93\x92\
+\xa7'\x9d\xcd.,=/*\xf6\xba\x94~\xa5\xf2\x9a\
+\xec\x8d\xa0[Gn\xf7\x97z\xdc\xcb\xbd\xff\xf2O\x87\
+\x87\x1b\x1e\xbd\xa9\xb1\xad\xdb\xf2\xa4\xb71\xa0\xe9r\xb3\
+\xda\xab\xb47/\xde\xfa\xb7\x97\xbc\xb7\xfeP\xd0m\xd4\
+\x9b7\xa0\xf4i\xd7\xa0\xee\xd0S\x91\xe8G\xff\x99\x90\
+\x81\x0at\xc1\x85\x03&\x22\x04\xb1X\x8a\x1c\x14\xe0\x1a\
+\xea\xd0E0\x09c\xc2\x9b\x88 V\x13\x05D\x05\xd1\
+E*\x93\xaed4\xb9\x85\xbcAvP4)\xbe\x94\
+\x15\x94\x0b\x94v*\x87\x1aL\xddB}Hc\xd3\xfc\
+h\x9bi\xb5t\x0dz8\xfd4\xfd\xb3\x84\xb7\xc46\
+\x896\x863c\x1b\xa3Sr\x8a\xe4\x09&\x8b\x99\xc0\
+\xacgy\xb0\xceJiIeK\x13\xd2\x8b\xa5\xfb\xd9\
+\xc9\xec>\x99\x852C\xb2k\xe4\xe4\xe4\x0e\xfc\xcf\xee\
+\xfbj\xb4j.\xd7R\xd1*\xd6\x9e\xaa\xdd\xad\xb3\x85\
+c\xc7y\xae\x9b\xa9g\xa1\xf7dT\xba\xbe\x9d~\xab\
+\xc1\x0e\xc3\x89\x86_\x8d\xce\x19G\x9a\xe8\x984\x9a\xee\
+\x1e\x1d\xc2U\xe2>3;h\xce\xb7\xe0Z|\xb4\xbc\
+=&\xc7j\xae\xb5\x99\x0dl\x9e\xd8\x9e\xb4\xcb\xb4\x0f\
+\x1f\xeb\xea\xa0\xee\xf0\xd1\xb1\xd6\xe9w\xe7|\x97\x0c\xd7\
+X\xb7\x00w'\x0f#Oy/x\xf5\x8e\xeb\x19\xff\
+\xca\xbbi\xc2\x83\x89w'\x95L.\x99R\xe2s\xc7\
+\xb7\xdc\xaf\xf2\xb7*\xff\xda\xa9\xcd\x01\x9d\x81\xc4t\x85\
+\x19\x06A\xf6\xc1\xfe!\xd13\xd3g\x1d\x98]:\xa7\
+k\x9eF\xa8{Xt\xf8.^=\x9f\x15\xe9\x12\x95\
+\x16}=\x16\xf3\xc7\xc7\xe5\xc4\xbfH4\x17\xa4/h\
+H\xb6\x12\xe6\xa6\xf4\xa7\x86,\xba\x95f\xbad\xff2\
+\x85\xe5\xd9+\x99\xab\xb22(\xabWe\xb2\xb2\xf2\xd6\
+\x19\xaf\xbf\xbc\xd1/\xfb\xfd\xe6\x0d\xb9F[J\xb6\xf1\
+v(\xee|\xbe\xfbI>}\x9f\xcd\x01\xfe\xa1\xddG\
+\x1e\x1c\xa3\x9cp<\x15\x7f\xe6\xf4\xb9\xb6\xf3\xdc\x8b)\
+\xbf\x17_\xfer\xd5\xf9\xfa\xea\x9b\x8fnk\xdd\x0d+\
++*\x1f\xaa\xf4{\x90_\xf5\xa1\xda\xb3vg\xfd\xdb\
+\xa7\xf6\xcfr\x9e\xb7\xbet{\xbd\xa3\xe5C\x9b\xef\xbb\
+\xfd\xef\xbft\xce\xe8\xbe\xde\xa77\xb0\xf6S\xd7\xe0\x9c\
+\xa1\xee\x91\xfe\x93`A\x16\xca\xe0\xc0\x1c.\xf0C8\
+R\xb1\x09\x05(\xc1\x0b\x0c\x13\xda\x84;\x11A\xac#\
+\x8a\x88&\x92A\xda\x91Q\xe4N\xb2\x92BR\x9c(\
+)\x94\x22J7\xd5\x8a*\xa4\xfeA\xa3\xd0\xfchy\
+\xb4\xf7tW\xfa6z\x87\xc4\x04\x89\xa3\x0c:#\x96\
+Q-\xe9*y\x86\xa9\xc3\xdc\xc1\x92eeKIK\
+m\x96V\x92>\xc4\xb6f\x97\xc9\xcc\x91\xf9,\xbb]\
+\xceN\xaeI>K\xc1N\xa1]1_\xc9K\xa9Y\
+y\xad\x8a\xb9J\x83\xea\x1a5;\xb5v\xf5|\x8di\
+\x9aL\xcd[Z\x8b\xb5m\xb4\xbbu\x0a9\xc9\xba\x8e\
+z\x14\xbd{\xa3r\xf5C\x0d\xcc\x0d\x86\x0d+\x8d\xf2\
+\x8c\x13L<MUM{FWr\x0b\xcc2\xccC\
+-\xdc,9c\xa8c\xda\xac*\xac\x0bm\xf6\xd8\xa6\
+\xdb\xc5\xdb\xcf\x1e;\xd9\xc1\xdeQ\xcfI\xc6\x99\xe2<\
+\xe8\xd2\xed\xda\xe2\xd6\xe0^\xe3Q\xeeY\xe2uk\x5c\
+\xe9\xf8R\xef\xb2\x09w&\xde\x9dT9\xb9fJ\x93\
+O\xbbo\xbf\x9f\xc8\x9f9U%\xc0d\x9a[`\xd0\
+\xf4\x84\x19k\x82\xf6\x06_\x09i\x9c9<[g\x8e\
+\xdb\xdc\xb0yY\xa1\x85aM<F\x84-\x9f\x1f\xb9\
++\xaa*\x86\x11;~~F\x5cI\xbc(\xd1U\x90\
+\xbe\xe0~\xb2\x8204\xa5(\x95\x5c\x14\xb8\xf8\xe4\x12\
+ri\xc8\xb2\x8b+\xd4V\xa6\xadj\xc8\xf0\x5c}.\
+S#k\xf5\xda\xee\xf5\xbc\x0d\xd5\xd9\xde\x9bn\xe68\
+\xe6^\xd9\xea\xb0\xed\xea\x0e\xd7\x9d\xa5\xbbg\xec\xe9\xc9\
+\xdf\xba\xcft\xff\x83\x83\x89\x87\xe5\x8f\x5c-\x88<\xce\
+:Qx*\xe1\x8c\xce\xd9\x87\x85\xcb\xcf[_\xe8*\
+>})\xe6\x8a\xe9\x1f\x8d\xd7\xf2n\x04\xddR,\xa9\
+\xbd\xb3\xbdt\xfa=\xa5\xf2\x9a\x8aM\x7fNy\xc8\xac\
+*{\xbc\xa8\xc6\xaa\xb6\xbd\xfe`Cp#\xfb\xd9\x8d\
+\xe7\xf3\x9b\xd5_V\xbc\x16\xb6\xa8\xb6\xdeh\x8b}\xc7\
+\xf8\xebP\x87\xf7\x87\x97]Kz\x94zO\xf4;\x0c\
+T|\x9a\xf5\xb9cp\xed\x90\xeap\xa3H\x04\x88\xdf\
+\x8b\x00\x00Z\x8co\x18\x0f\xff\xe7\x88\x8fK\xf9\xbe'\
+\x09@\x8a\x9f0}\x1a\x00\x06\x00c\x81\xd0?\xf0{\
+\x8e\x18\xf8\x22\x0c<\xf1;\x15\x00\xe8\xb2@\xbe\x11\x00\
+\x5c\xf6M\xfa\xaf}\x85\xfcEB\x00\xf0J\x14,N\
+\x8a\x89\x8a\x16r<\x04\x828>\xc7+1^\x90\x22\
+\xe4'q9\x93\x12x\xe6\x5c\x8e\x95\xa5\xa5-\x00\xfc\
+\x07\x8f\x08\x91L8\xcf\x9b\xb0\x00\x00 \x00IDA\
+Tx\x9c\xed}y\x98\xdcV\x95\xef\xefJ\xaa}\xed\
+\xaa\xde\x17o\xb1\xe3v{K\xec8\xdb\x04\x08\x84I\
+X\xb2\x10\xc0\xc0\x83\x19f\x08o\xc20\x0f\xde\x1b\xc2\
+\x00o\xd8g\x80\x84-\xc0\xcc\x03\x860\x0cd\xb2\xd8\
+$&\xb6\x13'1^\x12;\xc6\x8e\x1d'\x8e\xed8\
+^:\xee\xd5\xbdUwuwu\xd7.UIz\x7f\
+H*]\xa9T\xd5\xbb\xed\x04\x9f\xef\xd3'UI\xba\
+\xba\xba\xe7w\xcfv\xcf\xbd\x22\xb2,\xe3\x12\xfd\xf9\x12\
+s\xa1+p\x89.,]\x02\xc0\x9f9\x15\x01\x80\xa8\
+t!*s\x89\xce?\x95\x94\x00\x97@\xf0\xe7Ae\
+U\xc0%\x10\xbc\xf5iB\x1b\xe0\x12\x08\xde\xda4)\
+#\xf0\x12\x08\xde\xba4i/\xe0\x92q\xf8\xd6\xa4)\
+\xbb\x81\x97@\xf0\xd6\xa2\x22\x00L&2x\x09\x04o\
+\x1d\xb2\x94\x00\x97@\xf0\xe7C%U\xc0dA\xf0\xed\
+o\x7f\xfbR4\xf1ML\xc4\x82\xd1\x86\x9e]\xae\xa3\
+?\xf0\xc0\x03\x5cSS\x93k\x98e\xc5\xbf\xbe\xf9\xe6\
+\xd4\x1c\xd4\xef\x12\xcd1\x15\x01\x80\x10R\xfc\x9fr\xc2\
+\xf0\xdf\xeb\xaf\xbfn\xcbf]\xaeh4\xe6\x16\x88\xe0\
+!\xac(\xdc\xf6\xee\x1b\xce\xcdq}/\xd1,\x93%\
+\x00\x00\x00\xb2\x0c\xb3l\xd0Nuvv:\x12\x09\xc6\
+e\xb3\xc1%I9\xcf\xc0\xf0\x98O\xe0\x05\x9f$\xc9\
+\xb9t\xbc\xef\x95\xf5\xeb\xd7\x0b\xe7\xa3\xf2\x97h\xe6T\
+\x1a\x00\x80\x15\x08HOO\x8f\x03\x80+\x9b%nQ\
+\xccy`c\xbd\xc8I\xbe\x91\xb1\xb8?\x9eJ\xfb\x19\
+\x199\x9e`\xef\xed7];x\x1e\xea\x7f\x89fH\
+\xe5\x00\xa0\xede\xf5\x1a\x02\xc0\x09\xc05:\x9aq\xc7\
+\xb31\x8f$\x12\x9f,\x88\xbe\xbc,\xfb\x09d\xff\xd8\
+X\x220\x1aO\x05\x01\xd9Ar\xe2#\xb7\xdcr\xfd\
+\x99\xf3\xf6&\x97hZT\xca\x827(\xfcM\x9b6\
+1\x00\x5c\x00\xdc\x00\xbc\xa1\x90\xcbW\x1d\x0c\x06\x1c\x8c\
+=\xe0p\xd8\x83\x840AIFE \xe0\x0dU\x86\
+\xfd!\x16hd\xec\xdc\x0fw=\x7f\xe8}s\xfd\x02\
+\x96\x95\x9f\x80.D\x9d.V*%\x01\x0a\xbd\x7f\xcf\
+\x9e=lUU\x8b3\x1cv\xbbkk\xbdn\x00^\
+u\xf3\xe7\xf3y\xff\xe0\xf0\xb8_\x96\x11\x10x>\x98\
+\xcb\xe5\x832P!\x08\xf9\xd0pt4$B\x0eC\
+\x96\x9f\xf8\xcbw^\xfd\xd5Y\xaf\xf8\xe4\x19Yx\x97\
+\xc9\x96-\xff\x19\xe5\xc9Y\xb9\x81\x85\xc6}\xe5\x95W\
+8\x8f\xc7\xe3\xb4\xdb+\xdc\x1c\x07\x8f\xcf\xe7\xf1TT\
+x}\x00|\x00\x02\x00\xfc\x00\x02C\xc3cA1\x97\
+\x0ffs\xf9\x10\x9f\xe5+ #\x9c\x97\xc4\xd0\xc8h\
+<\x9c\xcb\xe5\x02\x90\x99\xa7\x92$\xf1\xa9\x0f\xdcx\xe3\
+\xd8\xb4+Z\x9a\xe1V\xff\x9b\xd5\x98Fr\x89\xe3r\
+\xff\xbd\xa5\x01Q\x12\x00\x8f?\xfe\xb8\xad\xa2b\x91\xab\
+\xae.\xec\xb2\xdb\x19\x0f\xe7rzY\x06>\x9b\x8d\xf3\
+\xd5U\x85\xfcP\x00\x10\x00\x10\x04P\x11\x1bKT\xf0\
+|.\xc4\x0b\xf9P&\x9b\x0d\xcb\x92\x14\x96$\xd97\
+6\x9e\x22\xbc\xc0C\x96\xe5c\x099\xf9\xce\xc9\x82\xa0\
+\x04\xc3i\xc6\x9a\xcf\x93\x12\xd7\xd1T\x0a\x00V\xc7\xe6\
+\xbd\xf2\xe3-\x06\x06K\x00\x00\xc0\xf6\xed\xdb\x1d\x02\xe7\
+\x0f\xbb\xed\xac\xa7\xa1\xbe\xd6\xcb\xb1\x8c\xd7\xc1\xda\xfd\x8c\
+\x8d\xf5\xdb\xedl \x14\x08\x04l66\x08\xa0B\xdd\
+B\xf1D:\x94\xced\xc3\x92(\x85\xe3\x89\x94G\x06\
+\x08d`l<\x89L6\x0b\xc8\xf2X^\x96\xdey\
+\xf3\x8dW\x1f+Y!#\xe3\xad\x18n\xfe\x8fl\xd8\
+\xb0!\xb0n\xdd\x0dW\xf8|\xae\xf96\x9b}>\x00\
+\xb0,7\x8f\x10f>\x000\x8cr\x8b(\x8a\xdd\xa2\
+\x98/\xc4*\x92\xc9\xf4k\xa2\x98\x1b;th\xff\xb1\
+\x8f\x7f\xfc\xe3\xe3P\x98\xadm0\xed\xe9\xff\xdf2@\
+(\x09\x00\x00\xd8\xbe}\xbb\x9f\xd8\x83\x8b\x1dv\xceW\
+W\x15\xf6\xb3v\x9b\xdf\xc6p\x01\xbb\xd3\x1e \x04\xc1\
+\xcap\xa0\xc2\xc6q!\x00!\x00!\x09\x08g\xd3|\
+(\x99\xce\xb8eYF<\x9eB>\x9f\x87\x0c \x93\
+\xe6\x11O\xa6 \xcb\xf2\x98\x0c|\xe1\xa6\xb7\xaf}\xb0\
+P\x89\xf2L\xd7~3\xda\xf1\xce\x9d{\x17\xae^\xbd\
+\xf26\x87\xc3\xf96\x8e\xb3\xadbYv\xde\xb4^\x9e\
+z\xac(\x8a\xe7$)\x7f<\x9b\xcd\xee\xef\xef\x1f\xd8\
+\xb7zu\xcb1\x18\x19o\xde\x00\xbc\xf9\x81P\x16\x00\
+\x00\xb0u\xeb\xde\xa0\xc3\xe3\xbc\x9e\xb3\xb1\xe1\xfa\x9ap\
+\xc0f\xe3\x02\x1c\xc7\x05].{\x05!l\xc8\xefu\
+\x87\xdcnGH\x02\xc2\x90\x10&\x04\x0e^\xc8#\x99\
+LA\x92e$\x12)\xf0|\x0e2\x00!\x97\xc3\xf8\
+x\x12\x90eH\xa2t\xcfM\xef\x5c\xf73\xad\x1e\xd4\
+\xbe\x88\xe9\x9f\xfe\xf4\x97\x17\xdez\xeb{\xde\xbeb\xc5\
+\x92[kk\xabV\xb1,g\xc9\xf0\xd94\xf0EQ\
+<\xc7\xf3\xd9m\xbd\xbd\xbd\x8fP`\x90\xf0\x16\x03\xc2\
+\x84\x00\x00\x80\x1d;\x0e\x86d\x8eY\xcf\xb1\xa4:\x1c\
+\x0eV\xb8]\xae\x0a\x1b\xc3T\xb8<\xce\x10!$\xec\
+\xf7zBN\xa7#D\x08\xec2\x00\xc8@>/\x22\
+\x95NC\x14%$\x92\x19\xa43\x19@\x06\x84\xbc\x88\
+D\x22\x05I\x92 \x89\xd2\x7f\xdft\xe3UwAw\
+G\xb5^N\xee\xbc\xf3\x13\x15\xef}\xef\x07?\xb9r\
+\xe5\xd2O,\x5c\xd8\xb8\xd2\xe7\xf3\xea\x95\x9e\x06\x9fg\
+\x02\x0e\x0d\x0cO=\xf5\xc4w?\xf5\xa9O\x8d\x01\x10\
+a\x01\x847#\x08&\x05\x00\x00x\xf0\xc1\xbd\xce\xda\
+y\xae\xcf\xb3\x84\xac\x08W\x04C\x1e\x8f3\xc4\xb0L\
+\xc8\xe7q\x87\x09C*\x5cN\x07\xe7\xf5\xba\xb5\xa6P\
+ZE\x92\x91L) Hgx\x8c\xc7\x93\xca9I\
+\xc6x<\x0dQ\xccC\x92\xa5\xe3\xbb\xfe\xb4\xe3\x96\xfb\
+\xbe\xf6\xb5q\x00\xccg>\xf3\xc5\x05k\xd6\x5c\xf7\xd5\
+\xb5kW~b\xd9\xb2\xcb\xa6\xfeBS\xe4\xf3T\x80\
+\x91\xcb\x09'\xfe\xf3?\x7f\xf9\xde/~\xf1\x8b1(\
+ \xd0$\x82\xa4^\x22\xbf\xd9@0i\x00\x00\xc0\xb6\
+m\xdb\xdc.o\xf57$\x90\x1b}^O\xb8\x22\xe8\
+\x0b3\x84\x04|>\x0f\xcb\xb1\x0c\x1c\x0e;<n\x97\
+\xd2\x87\xd5be\xc8H\xa7\xb3\xc8\xe7E\x08B\x0e\xa3\
+\xb1q\x88\x92r2\x99\xcc@\xc8\x09\x90E\xe9\xb53\
+\xad\xed\xdfg\xc1\xddz\xfd\xf5k>\xbe`A\xe3\xc4\
+\x15\x9fF\x8f\x9e\x0dp\xe4r\xc2\x89\x7f\xfb\xb7\x1f\xbf\
+\xff\x1b\xdf\xf8\xc6(t\x10\x18T\xc3\x9b\x09\x04S\x02\
+\x80F\xbb\x9f\x7f\xf9\x07 \xb8\xdb\xedv\xf9\xc3!?\
+\x03B\x10\xf0{\xc0\xb1,X\x96\x85\xcf\xe7\x06\x01Q\
+\xe4\x80\xac\xb4NN\x10\xc0\x0b9\xe4s\x22F\xc7\xe2\
+\xc8\x09\x8a]\x90Ld088\x82\xba\x9a*\xacX\
+qyq\x05\xcf\x93\xb8\x9f\xca-\x82\xc0\xbf~\xdf}\
+\xffz\xdb\x0f~\xf0\x83\x11\x00y(\xafhP\x0bo\
+\x16\x10L\x0b\x00\x00\xb0k\xcf\xcb\xdfb\x19\xe6\xdb6\
+\x9b\x0d\xe1\xb0\x1f\x0c!\xf0z<p\xba\xec\xe0X\x06\
+.\xa7\x13,\xc7\xa8\x00PP\x90\xcb\xe7\x91\xcb\xe5!\
+I\x12\xa2#c\x18\x19\x1e\xc7H4\x86u\xebV\xc2\
+\xebu\x97y\x9au\xc4\xfa|\x80\xa3\xd4\xe5\x82\xc0\xbf\
+\xfe\x9d\xef|\xf3\xf6\xfb\xef\xbf_\x03A\x914x3\
+\x80`\xda\x00\x00\x80\xe7\xf6\x1e\xfe[\xc2\xb0\xbf\xb3q\
+6TT\xf8\xc02\x0c\xbc\x1e7\xdcn\x07\x08C\xe0\
+v\xb9\xc0\xb0\x0c41 \x03\x90$E\x15\x9c>\xdd\
+\x05\x02\x06--\x13\xeb\xf9\xf2<\xbbp\xe0\xe0\xf9\xec\
+\xc9\x03\x07\xfe\xf4\xb9\xdbn{\xefQ\xe8 \xa0m\x83\
+\x8b\x1e\x043\x02\x00\x00\xec\xde\xfb\xca\x8d\x0c\xc1\x16\x86\
+e\x82\xe1\x8a\x00X\x8e\x85\xd3\xe1D0\xe0\x01!\x04\
+\x0e\x87\x0d\x1c\xcb\xd1\xfe\x12^z\xe95\xd4\xd5\xd5\xa1\
+\xa6&l\xac\xcc\xb4\x98V\xee\xec\xdc\x83C\x14\xf3\xf1\
+\x17^\xd8s\xc7m\xb7\xbd\xf7\x18\x80\x1c\xded \x98\
+1\x00\x00`\xe7\xde\xc3Wp\x0c\xbb\x87a\x98\xa0\xdf\
+\xef\x85\xc3n\x83\xd3aC0\xe8\x03C\x18\xd8\xed6\
+p\x1c\x07\xc82\x0e\x1f>\x81\xa6\xa6F\x84B\xfeR\
+U\xb2\xfewV\xc1Q:\x8dq:\x86\xa2(\xe6\xe3\
+\xbbv\xed\xb8\xf3C\x1f\xba\xe3U(\x92\x80V\x09\x17\
+5\x08f\x05\x00\x00\xb0u\xef\xde`\x80\xf1\xed!\x84\
+\x5c\xe1\xf3{\xe0\xb4\xdb\xc1\xd9XT\x85+\xc00\x04\
+,\xcb\xe2\xf8\xb17\xd0\xd4\xd4\x80`\xd0W\xbeR%\
+\x99p\xf1\x82C\x14\xf3\xf1\xdd\xbbwZ\x81\x80\x0e \
+]t\xb1\x82Y\x03\x00!\x84<\xfa\xf4\xd3\xc1Z_\
+\xed\x16\x96a\xde\xe1t:\xe0\xf18\xc12,*\xc3\
+A\x9c>\xd5\x8e\xf9\xf3\x9bL\xcc\x9f\x1d\x83\xac\x5cY\
+\xe7\x13\x1c\x14\x08\x8eBQ\x07\x17=\x08f\x05\x00\xa6\
+,\x22\xb2{\xcf\xe1\xdfr\x1c\xf7I\x87\xc3\x0e\x8f\xc7\
+\x85\xfe\xde!\xd4\xd5Vc\xde\xbcz\xd3}eK\x9d\
+b\x1d\xa6^V\xb9{FGcH$\xc6\xd1\xd8\xd8\
+\x04\x96e'q\x8f\x02\x0eE\x1d\xfc\xf1\x83\xeb\xd7\xdf\
+\xf9*\xde\x04 \x981\x00\xcc\xcc\x87\xd2\x12\xcc\xb3\xbb\
+\x0e|\xd3\xe3\xf2|5\x93\xc9\xc2\xedpa\xe5\xcab\
+\x1f\xbf|\xb9e\xcf\xceYY\xf1x\x1c\xbd\xbd=\x88\
+\xc7\xe3`\x18\x02\x8f\xc7\x8de\xcb\x96\x1b@0\xd1s\
+DQ\x8c\xef\xda\xb5C\x03A\x9e\xda.:\x10\xcc\x16\
+\x00\xe8\xc1\x1bV\xddl\x8f\xff\xe1\xd9\xcf\xb1\xc4\xf9\xdd\
+\x1bn\xb8\x0a6\x9b\xad\xc4\xfd\xd3yf\xc93\xd3.\
++\x9dN\xa3\xab\xab\xb3\xc0x\x80\xa8\xe7\x08\x1c\x0e'\
+\x9a\x9b\x97\xc1n\xb7O\xba\xce\xa2(\xc6w\xef.\x02\
+\x81\x160\xbah@0\xa3Y=e\x98\xcf\x01\xb0\x8d\
+\x8d\xa6oX\xb5\xaa\x19\x1c\xc7\xa93\x8d\x8a7Y\x96\
+!\xcb\xb0\xdcJQ\xa9\xebK=\xa3\x5c6X6\xcb\
+\xa3\xad\xad\x0d\xc7\x8f\x1fG<\x9e\x80&\xc8\xb4W\xe3\
+8\x0e\xf5\xf5\xf5\xb0\xdbmT\x9dK\xd7A#\x96e\
+\xfd\xef~\xf7-\x9b7m\xda\xb2\x06\x80Mm\x13\xad\
+}\x0aC\xdb\x17:Gq\xda\x12\xc0$\xfa\x19u\xe3\
+\xd4\xcd\xfe\x9d\xef\xfc\xfb\x1dk\xd7\xae\xfb\xcd5\xd7\xac\
+\x9edy%\xcfL\xf1\xfa\xc9=C\x14E\xf4\xf6\xf6\
+```\x00:\x8e\x09\x18Fq\xedX\x96CMM\
+-jjj,\xc5\xffd\xeb+\x8ab|\xe7\xceg\
+?\xf4\xb1\x8f}\xf8(\x00\x01z\x9c\xe0\xa2\x90\x04\xd3\
+\x02\x80\x05\xf3\x09(\xe6_w\xdd;\xaa>\xfb\xd9/\
+\xed\xba\xf6\xda5\x8d\xa1P\xc0|\xef\x14\x9fU\xf6\xec\
+\x94\xef\x11E\x11\x03\x03\xfd\x88D\x06\x90\xcfK D\
+\xa9\x93\x965D\x08PYY\x85\xfa\xfa\x06U\xe4\xcf\
+|\x5cA\x14\xc5\xf8\xc1\x83/\xdd\xf5\xfe\xf7\xbfk/\
+\x8c\x86\xe1\x05\x07\xc1L\x00@\x1b}\x05\xb1\x0f\xc0\xf9\
+\xf3\x9f?\xf4\x95\xc5\x8b/\xff?W]\xb5r\xaa\xe5\
+N\xf1\xfa\xb2g\x8b\xfe\x89F\x87p\xee\x5c\x17\xf2y\
+\xb1\xd0\xeb\x09\xd1S\xc6|\xbe\x00\xe6\xcdk\x82\xcbe\
+\x1c\x97\xa0\x9f\x13\x8d\x0e!\x12\x89\xe0\xb2\xcb\x16\xc3\xed\
+\xf6L\xa9\xbemmg\xbfp\xd5U+\x1f\x86\x11\x04\
+\xe6\xd1\xc4\xf3\x0a\x04n\xaa7X\xa4o\x19\x00\xb0v\
+\xed\xdb+++\xab\xefjh\xa8)\xa9\xc7K1\xae\
+\xdc{[\x81\xa3\x5c3\x11\xa2\x9f\x8cF\x87\xd0\xdb\xdb\
+\x0b\x9e\x17\x0a=^\xc7/`\xb7;\xb0`\xc1\x22\xf8\
+\xfd\xd6\x01*YV\xbc\x83\x8e\x8e6d\xb3J\x19'\
+N\x9c\xc0\xa2E\x8bPUUU\xaa\x06E\xff,^\
+\xbc\xe4\xa7\xaf\xbcr\x02*\x08\xccT\xc8)P\xe7g\
+\x9e\x17\x10L\x19\x00*\x95\x92\x00\xf6\xbb\xee\xfa\xf4\xdd\
+\x1cg\xf3UV\x86J\xde\x5c\x9eq\xa5\xee\xb1\xbe\xa9\
+\x94\xd4\xd0\x98\xa6\xb9t\x84\xe8V\xbd\xd6\xf3\x1d\x0e;\
+\x1a\x1a\x1a\x10\x0eWR\xcf(v\x0b\xfb\xfaz\x10\x8f\
+'\x0a\xe0QT\x06\xd0\xd5\xd5\x09\x8e\xb3!\x18\x0cZ\
+\xd5\xc0\xf2]\x16/^\xac\x81\xe0\x11\xe8m\x98WO\
+\x9fw\x10L\x09\x00\x16\xbd\x9f\xa56\x1b\x00{8\x5c\
+\xfd\xc1\x8a\x0a?X\x96\x9dr\x8f\x06\xa6\x0e\x0e\xabg\
+\xa4Ri\x9c;\xd7\xa9Z\xf5:\xd3\xb4c\x9bM1\
+\xf0\xaa\xabk\xd4z\xd2\xcfP~\xf0<\x8f\xee\xeeN\
+\x8c\x8e\x8e\x19\xa4\x86V\x8e\xdd\xee@}}\x03\x02\x01\
++\xe6\x97\x7f\x97\xc5\x8b\x17\xff\xf4\xd0\xa1\xe3\xe4\xdak\
+W\xd3\x92\xe0\x82\x80`:\x12\xc0\x10\xf0\x01\xc5\xfc\xfb\
+\xee\xfb\xf9\xc7\x1c\x0eg} Pj\xa0G\xa7\xb9\x00\
+G6\xcb\xa3\xaf\xaf\x17\xd1\xe8\x90\x81\xe1\xf4qee\
+%\x9a\x9a\xe6)\x83S\x16\x94\xcd\xf2\xe8\xed\xed\xc5\xf0\
+p\xd4T\x17Ejp\x1ck\xf2\x0ed\xc8ric\
+\xc4\x1a\xb4\xc0\xd2\xa5\x97\xff\xe4\xd0\xa1\xe3\xb8\xf6\xda\xd5\
+\x8fP\xa7D\xed\x12\xa8v\xc1\x5c\x83`\xa6*\x80v\
+\xfdl\xf5\xf5\x0d\xef&\x84 \x10\xf0\x1b\x18<U\xe3\
+n\xaa\xe0\x10E\x11===\x88D\x06\x8a\xc4\xbcv\
+\xec\xf7\xfb\xb0p\xe1\xa2B0\xc7\xfc\x0cQ\x14\x11\x89\
+\x0c```\x00\xa2(\x16\x01\x87\x10\x82p\xb8\x12\xf3\
+\xe6\xcd+\xb8\x85z\x11\xd6\xe2^\xb9\xa6\xf4\xbb\x9b@\
+@_(Bi\xdb9\x07\xc1\xa4\x01P\x22\xe4[\x10\
+\xff\xabW\xaf\x0dUT\x84\xdf\x09\xc8p\xb9\x5c\x86{\
+\xa7\xd3\xdbK\x11]\x96\xee\xd2E(\xa6)U\xd4\xca\
+\xf5x<hj\x9a\x07\x9f\xcf\xa7\xdeO?[\xd9\xf7\
+\xf6\xf6\x22\x12Q\x18\xaf\xd5\x89f~0X\x81y\xf3\
+\xe6\xc1n\xb7\x97\xac\xef\xf8\xb8b+\x88\xa2\x88\x85\x0b\
+\x17\xc3\xe3\xd1<\x89\xf2\xe0\xb8\xfc\xf2\x02\x08\x1e5\x9d\
+\x96\xa8\xfd\x9c\x81`\xaa\x12\xc0,\xfe\x0b\x06\xe0\xed\xb7\
+\xaf\xbf^k\x1c\x8ec\x8b\xc4\xf5lY\xfe\x1aE\xa3\
+C\xe8\xea\xea\x82$\x89\xa0\x19N\x1bx\xf5\xf5\xba\x81\
+gECCC\xe8\xeb\xd3\xbd\x03s9~\xbf\x0f\xf5\
+\xf5\x0d\x05\xf0X\xd57\x9b\xe5q\xee\x5c\x17b\xb1X\
+\x018\xad\xad\xa7\xd1\xdc\xbc\x0cn\xb7[\xbd\xa7T\x0d\
+\x14p\x5c~\xf9\x92\x9f\xec\xdf\x7f\x84\xdcp\xc3\xdaG\
+J\x5c8g \x98\x89\x0a0\xb8\x7f\xb5\xb5\xb5-\x0c\
+C\xc00\xd6\x83&\xb3e\xf9G\xa3Q\xf4\xf6\xf6@\
+\x10\x04\xaa\xa7\xea\x8c\xe38\x0e\xb5\xb5\xb5\xa8\xab\xab/\
+YV<\x1eG{{\x1bU\x06\x0ae(YL\x0e\
+\xd4\xd7\xd7S\xdeAq}5{\x83\xb6\x15\xb4:\x88\
+\xa2\x88\xd6\xd63hiYN\x8d\x1f\x94\xb7k\x96-\
+[v\xff\xfe\xfdG\xa0\x82\x80@\x8f\x15h4' \
+\x98\x14\x00J\xf8\xfe\x86\xd8\xbf,K\x0c!\x04^\xaf\
+\x12\x1c)1\xe9\xd4\xb2\xfc\xc9\x80#\x1e\x1fGoo\
+/\x12\x89q\x00LQ\x8f\x07\x80\x9a\x9aZ\xd4\xd7\xd7\
+\x974\xf0\xac\x5c:\xba\x0c\x96e-\xc1C\x13m+\
+\xe8\xd2G)\x03 \xb0\xd9XTW\x17\x87\x90'#\
+\xe9\x96-[v\xff\x91#'\xfdk\xd7.\xff\x0f\xea\
+\xf4\x9c\x82`*\x12\x80\x986\x83\x0a\xa8\xaa\xaaYC\
+\x08A2\x99D\x22\x91\x80\xcf\xe7+z\xe9\xe9\x88\xfb\
+dRs\xe94\xc6\xeb\xcc\xd7z]0\x18DS\xd3\
+|8\x1c\xd6\x06\x9e\xe2\xd2\xd1bZy\x1d\xfa\xb8\xa6\
+\xa6\x06\xf5\xf5\x0de\x99\xa6\xd9\x0a\xb4\xda1z\x18U\
+\xa8\xab\xab\xa7\xeaa~G\xebw\xa7\x9f3\x7f\xfe\x82\
+o\xb5\xb5\xf5\xb5,^\xdc\xf0y\xea\x12m(\xb9`\
+\x18Z\x974u\x9a\xae\x0d`V\x01\x1c!\x0ca\x18\
+\x02Y&hk\xeb\xc2\xe2\xc5\x0b\xe0\xf5z\xa7m\x0b\
+(\x22\xb6\x07\xc3\xc3Q\xf5\x1e\xa6\xc00\xad\xd1}>\
+\xbfAGkEh\xcf\xa0\xc5\xb4U\x8f\x07\x80pX\
+a\x9a\xd3\xe9(\xf9\xd2Z$QS\x19F\xf0\x00~\
+\xbf\x0f\x8d\x8d\xf3\xe1v\xbbJ\x96A\xd7\xcf\x8a\xe8v\
+\x09\x06\x83\xeb\xdb\xda\xfa\xb0xq\xc3\xe7`dv\xc1\
+; \x84\xccJ\xc8x&q\x00\x83'@\x08\x08\xc3\
+\x10H\x92\xf22\xed\xed\xddhn^\x04\x97\xcb\x0dQ\
+\x94\x0a7\xeb\xcb\x0dY\x14L1\xee\xf8\xf1#\xd0\x19\
+\xc5P\x0d\xa4\xe8\xe8\xba:EG[\xcf\xdeQ\xc4\xb4\
+f\xd9\x9b\x19O\x08\x81\xcf\xe73\x81\xa7\xb8-c\xb1\
+Qtww\xab\x8c\xd7%\x8e&5\x9cN\x07\xe6\xcf\
+_h0\x12K\x95\xa5\xbf\xe3\xe4\xd4` \x10\x5c\x7f\
+\xf6l\x1f\x96,i\xf8\x9cv\x09\xf4\xf8\x00\xc1,\xa9\
+\x82\xe9H\x00mo\xf0\x04dY\x22\xca0\xaa\xf22\
+\x92\x04\xb4\xb5u\xa3\xa5e\x09\x18\x86C>\xaf\x83\x80\
+a\xac\xeb\xac\x81\xc3\xe1p\xa0\xb9y9\xce\x9e=\x0b\
+I\xd2\x19\xc8q\x1c\x1a\x1a\x1aP]]C\xddSJ\
+L\xe7Q,5\x14\xa6566!\x18\xac\xa0\x9e\xa9\
+\xbe\x14eo\xf4\xf5\xf5\xaa\xb6B\xb1\xd4`Y\x0eM\
+MM%\x01X\x8e\xa6\x02\x8e`0\xb8\xfe\xc5\x17\x8f\
+\x1e\xbc\xfe\xfa+\x1f\x811\xb9A\xeb\x80s/\x01,\
+\x12\x164\xe6\xd3 *\x15.R\x80 \xe1\xf4\xe9\
+\xb3X\xb6l\x098N\x07\x81$\xa1$i\xe0\xf0\xfb\
+\xfdX\xbd\xfa\x0a\xb4\xb7\x9fE2\x99@]\x9d\xc2x\
+%\xb9\xc4\x5cGZL\xf3*\xc3\x0b9\x17\x00\x94\xf1\
+\xfd\xfa\xfazTW\xd7\x94dZ6\xcb\xa3\xa3\xa3\xad\
+\xc0x\xb3\xad\xa1\x19\x89Z\x08\x19\x98\xbb\x18\x87F\xe9\
+4\xbf\x00J\xa4U\x82q\xe4pV\xa4\xc0t\x8d@\
+\x80\x9a\xca\x0d\x80\xd1\x1b\xcc8\xa0\x22\xcb2N\x9fn\
+CK\xcb\x12\xd8\xed6\xf0\xbcb\xd4\x96j\x1b\x1a\x1c\
+\x0c\xc3b\xc9\x92f\x08\x82\x00\xbb\xdd\x0e\x86\x01\xcc\xa0\
+W\x5c\xbav\x08BV}\xbe\x96\xe4\xa43\xb0\xbe^\
+\x03\x8f5\xd3x^\xb77h\xa9A\xeb\xfap\xb8\x0a\
+\x8d\x8dMT\x19T\xc3\xccr\x8cCy\xaf\x14\x9e|\
+r\x17\x9eyf\x17\x07\xc0\x0e\x8b\x09'\x98\x05)0\
+\x938\x80\xb6'\x00\x08!\x1c\x14#P\xbbD\x07\x02\
+-\x09\x1c\x0e\x0e<\x9f\x9f\x94-\xa0\x91\xe6K\xd3\xe0\
+H$\x141\x9dH\xc4\xd5{t\x11\xad3\xadR\xb5\
+\xca\x1dj=\x8c\xe5\xe6\xf3\x22\x06\x07\x07\xd0\xd7\xd7c\
+ik\x10\x02\xf8|^\xcc\x9f\xbf\x08\x0eG\xe9(\xe0\
+l\x8en\xb2,\x83\xbd{_\xc2SO\xedE2\x99\
+\x82,K\xdaX\x0b=\xeb\x88\xee\x883\xa2\xc9\x02\xc0\
+\x1c\x07\xd0\xf6\x94\x04\x90\x89n!\xcbE@P$\x81\
+\x0e\x82l6\x0fz\xcc\x9e\xa6r\xe0\x10\x04\x1e\x9d\x9d\
+m\x88\xc7\xc7)\x8b\x5c\x17\xf9\x0a\xd3\x14\xab\x5c\x0fI\
+\x1b\x9f\x93\xcf+F\xe2\xe0`\x04\xa2\xa8\xb9\xd9\x8c\xa1\
+<\x8f\xc7\x8d\xc6\xc6\xf9\xa0\x17\xa6\x98\xcb\xd1MB\x08\
+\xfa\xfb#x\xf0\xc1\xad\xe8\xee\xee/\x94\x17\x8f\x8fv\
+@\xcf)\xccAW\xbb\x12u\xef\xb4\xd5\xc0t%\x00\
+MD\xadD\xa1\xe7i\x0c4\x03A\x96e\xb4\xb6\xb6\
+c\xf9\xf2%\xf0z\x1dH&\xf9\xd2\x85\x96\x00\xc7\x1b\
+o\x9cA&\x93\x82\x86=\x85\xf1\xca\xf3\x1c\x0e\x07\x16\
+,X\x00\xaf\xd78\x1aIK\x8e\x91\x11\xdaV\xd0t\
+\xbc.\xf6\xedvc\x08y.C\xda\xb2\x0c\xb5\xbdd\
+l\xd8\xf04^|\xf1\xd5B\xb6\x92V\x1f\x9e\xcf\xa4\
+aL*5\xa8^\xcc0.0\x1d\x1b\xc0\xf2\x9c\x12\
+\x06f\xd4\x06\x93J\x02A\x92D\x9c:u\x16--\
+K\xe0\xf39\x90Hd-\x8b-\xd5\x9e\xcd\xcd\xcb\xd1\
+\xd3\xd3\x85\x91\x91\xe1\x0238N\xb1\xcaC\xa1J(\
+\xd2\xa6\xf8\xbe\xb1\xb1Qtww!\x97\xe3\xa1\xebv\
+\x1d<,\xcb\xa1\xba\xba\xa6`\xe0I\x92\xac\xda\x1cV\
+\xf5\x9a\x9c\xea\xd2\xef\xb1~\x19\x9b\x8d\xc5+\xaf\x9c\xc0\
+\xa6M;1::\xa6\x96\xa1\xe4'\xea \x10\xe9l\
+bCF\xf1l\xd0L%\x80\xae1\x0d\x12\xa0<\x10\
+DQ*\x80\xc0\xebu\x22\x99\xccNT|\x81X\x96\
+\xc5\x82\x05\x97\xc1\xef\x0f\xa0\xa7\xe7\x1c\xaa\xab\x8d\x89\x1d\
+f\xc9a\xb4\x15\x8a\x19\x0f(!\xe4\xba\xba\xfa\xa2\xec\
+\xdf\xd2\xde\xca\xcc\xc0\xc1q\x0c\xa2\xd1\x11l\xd8\xf0\x0c\
+N\x9el\x03\x00\xb8\xdd.H\x92\x08\x87\xc3\x81`\xd0\
+\x0bB\x08b\xb1\x04\x86\x87\xfb\xa2(\xee\xf9\xe7\xdd\x06\
+(G\x9a\xe9\xa5J\x00\x85\x01\x13\x01A\x92$\x9c>\
+\xdd\x86\x15+\x96\x22\x18tcl,c\xd1SJ\x0f\
+\xa5\x86B\x95j\x8f7\xdd\xa1\x16!\x08<\xda\xdb\xdb\
+\x90L\xc6-\xa3w\x84\x00\xc1`\x10\x8d\x8d\xf3`\xb7\
+[\x1b\x89\xdauVT\x0a\x1c\xe5b\x1c\x0c\xc3\x80a\
+\x80\xad[wc\xe7\xce\x17\x91\xcf\xe7a\xb7\xdb\x10\x0e\
+\x07\xe1p\xd8\xc0\xf39\x08B\x1e\x0c\xa3\xac\x9bp\xf6\
+\xec9\x0c\x0c\xb4\x0db\x96\x99N\xd3l\x00\xa0@\xb4\
+\xdf<\x19 H\x92\x84\xd6\xd6N,[v\x19\x82A\
+\x97%\x08&\x1aJ5\x93 h\xe1\xdf!\xe8\xae \
+m(*Fb]]\x03\xbc^=\x0aXZ|\x97\
+ns\xab{\xac\x80\xc1\xb2\x04v;\x87\x13'\xce\xe0\
+\xb1\xc7\xfe\x88Hd\x18\x0c\xc3\xa0\xba:\x8c`\xd0\x87\
+|>\x8f\xf1\xf1$x>\x07\x86!\x18\x1d\x8d\xa3\xbd\
+\xbd\x17\xe1p\x00\xa0b-\x98\x03\x10\xcc\x06\x00d\x00\
+\x85\x09\x154M\x06\x08<\xcf\xe3\xf4\xe9\xf6\x02\x08b\
+\xb1b\x10\x94f\x8e~\xac\x8d\xd2\xf5\xf7\xf7\x98\x98\xae\
+\x97\xa1\x19x\xe5$\x87\xd5\xebM\x17\x1c\x0cC`\xb7\
+\xb3\x88\xc7\x13\xf8\xcdo\xb6\xe1\xd5WO\x03\x00\xfc~\
+/\xea\xea\xaa`\xb7\xb3\x18\x1fO!\x1eOB\x92\x14\
+\xd5\xa0\xa9\xd2ht\x146\x1b3\xe7\x9f\xe1\x99)\x00\
+\xb4f\x93\x19F\xf3\xa1\x8b\x83A\x13\x01A\x10x\x9c\
+>\xdd\x81e\xcb\x16\xa1\xb2\xd2\x83X,e\x08\x1dO\
+F\xb7\xf2|\x16##\xd1\xa2\xe8\x1d\x00\xb0\xac\x0d5\
+55\xa8\xad\xd5\x86yKq{\xaa\xae\x5cip\xd8\
+\xed\x1c\x18\x06\xd8\xbb\xf70\x1e\x7f|;r9E\xdc\
+/X\xd0\x00\xaf\xd7\x85t:\x8btl\x00\x99\x14\x00\
+\xb0\xe08-\xdbX7\x00;::\xbbL\x15\x96Q\
+\xba\xf2\xd3\xa2\xa9\x00\xa0\xec\xc3\x8b\xdd@\xed\x96\xc9\x01\
+!\x97\xe3q\xe6L\x07\x9a\x9b\x17\xa1\xa2\xc2\x8b\xd1\xd1\
+\x14\xf2y\x91\xba\xb7|\xcc\xc0\xe5\xf2\xa0\xa5e\x15\xda\
+\xda\xde@*\x15\x87\xe6%\xd5\xd5\xd5\x1bB\xb7\xfa=\
+\xd6\xafX:@79p\xd8l,\x5c.\x1b\xce\x9e\
+\xed\xc2\x83\x0fnA\x7f\xbf\x920\xd2\xd8X\x83\x86\x86\
+\x1aH\x92\x88\xe1\xe114y\xce\xa2\xa1*\x81q\xbf\
+\x0d\xaf\x8d4A\x90\x1d\xd0\xc6,\xb4M\x8d\x9a\xce\x19\
+\xf3\x81\xd9S\x01r4\x1a\xed\xa8\xae\xae^A\x0f\xc9\
+N\x15\x08\x82\xc0\xa3\xb5\xb5\x03K\x97.B(\xe41\
+\x80\xa0|@E9\xc9\xb2\x0c\x96.m\xc6\xc0@?\
+r9\x1e\xb5\xb5\x0d%\x0d\xbc\xc9\xa8\x15\xabg\x948\
+\x0b\x86!p\xbb\xed\xc8f3\xf8\xdd\xef\xb6a\xdf\xbe\
+W\x00\x00\x81\x80\x0fK\x97*\xb9\x0a\xb1X\x1c\x83\x83\
+#\x10\x84\x1c\x9a\xeb\xb3p\xb8\x09\x02#\x02\xae\xaen\
+\xc7\xf1\xd8e\xc8Hn\x03\x00\xd4\x19K\xa5\x18?+\
+`\x98,\x00h\x0e\xd2\xa3R\x85\xb8\xf4\xd8\xd8\xe8\x90\
+bd\xc9\x06\xe6\x97\x03\x02M\x1a\x10\x04!W\x00A\
+8\xecE<\x9eF:-\xa8\xd7L\xae\x17\xea\xa2^\
+{\xa6\xd5=S3\xeeJ\x03\x83\xc0\xed\xb6\x81e\x09\
+\x0e\x1c8\x82\xdf\xff\xfe\x8fH\xa5\xd2\xe08\x16--\
+\x97\xa1\xb2\xb2\x02\x82 \xa0\xbb{\x00\xa9T\x06\x0cC\
+ \x8a9\xd8X\x19\x0e?\x03\x9b\x8b\x81tN\xc0\xaa\
+\x8a6\xb4'\xe7cL\x0c\x81\x10\xc5@\x8e\xc7GN\
+R/1'\x92`\xaa\x12@6\x1d\x17\xb6?\xfca\
+\xe3\xc1\xb7\xbf\xfd\xc6\xff\x09\x00\x92\xa4\xd8\x01\x13\x01\x81\
+\x96\x04\x1a\x11\x02\xe4r9\xb4\xb6v\xa2\xb9y!\x02\
+\x01%\xb12\x9d\x16f9\x14;s\xcb\xdf\xe5\xb2\xc1\
+\xe5\xb2\xa1\xb3\xb3\x0f\xbf\xfb\xdd\x16tu\xf5\x01\x00\xe6\
+\xcf\xaf\xc7\xe2\xc5M \x84`pp\x04\x91\xc80\x08\
+!\xe08\x16\x92$B\x96e\x84\x83\x22\x08\xc3\xc2\xe6\
+\x00|M6$\x07rX\x8avtfd\x8cJ5\
+\xd0\xa4\x0a\x8a\xdb|Vi\xba*\xc0,\x05\xa4}\xfb\
+\xf6\x0c\x8c\x8f\xc7\xba\x83\xc1\x8a\xf9Z\x90d&@\xc8\
+\xe7\x15\x10,]\xaa\x83 \x95\x12\xca0\xed\xfc\x81\xc3\
+\xe1`\xe1\xf18 \x08\x02\x1eyd\x1b\xf6\xee}\x19\
+\x82\x90C8\x1cDK\xcb\x22\x04\x02\x8a\xe4\xea\xe8\xe8\
+A.\x97\x07\xcb\xea\xd6}.\x97\x03\xcbr\xaa\x1c$\
+\x00\x01\x1c.\x0e\xf6\x85,\x92\xbd\x02\xe6\xcb\xed\xf0\xe5\
+\x13\xe8\xe2/\xc3\x0c\x97o\x98\x14M\x08\x00Y\x96\xb5\
+Q\x1e\xb3\x08*0\x1f\xea(\xd5\xbe}{\x9e\xb9\xe3\
+\x8e\x0f\xfd\x83\xc6\xe4\x99\x02!\x97\xcb\xe1\x8d7\xba\xb0\
+t\xe9\x22\x04\x02n\xd8\xed,b\xb1L\xc9\xba\xce5\
+88\x8e\x81\xd7\xab\x18k/\xbdt\x1c\x1b7nG\
+,6\x0e\x9b\x8d\xc3\xca\x95\x97\xe3\xb2\xcb\x1a\xc1\xf3\x02\
+\xda\xdaz16\xa6\x0cV\xd1\xcc\x97e\x19\xa2(\x16\
+V Qk\x00\x10\x02\x86\x10\xcc[\x11\xc4`W\x12\
+\x18\x18B.\x9f\xc7\x91\xb1s]\xc6\x0b/|$\xb0\
+$\xf3\x01\x88\xdf\xf8\xc6\xff\xdd\xb5t\xe9\xb2U\xcb\x96\
+-\xbf\x01\xd0\x99<\x13 \xe4r9tt\xf4`\xd1\
+\xa2&\xb8\x5c\x0e\xc82\x10\x8b\xa5-\x197\x9b\xc3\xb2\
+\xca=\xcaM\x0cC\xe0\xf5:\xe0p\xd8\xd0\xdf?\x88\
+G\x1e\xd9\x86\x13'\xce\x02\x00\x16,\xa8\xc7\xea\xd5\x97\
+\xc3n\xb7\xa1\xafo\x08\xe7\xceE I\x12X\x965\
+xF\x84\x10d\xb3\xd9\x02 4\xa6\xeb\x81T\x02\x99\
+\x10\xcck\x0e\x022 \x0f\x8c\xe0#\xeb\xb8\x8f\xb4\x9e\
+v\xbd\x14\x19\xcdhK\x97X\x05\x85\x080\xfd\xc4\x90\
+I\xad\x0fP\x18\xe75&\x82:\xa0|GP\xfb\x92\
+\x98\x0f\xcaG\xa4\xfc\x8f=\xb6\xf9s--\xab\xae\x07\
+\xf4\x06\xd6\x96\x82\x01dH\x92\xf6\xbf\xb6\xdcJ\xf15\
+\xe6\xff\xddn7\x16-j\x82\xcd\xc6!\x9d\xe6\x11\x8b\
+\xa5K\xd5u\xaamP\x12\x1c\x84\x10x<v\xb8\x5c\
+6\x08B\x0e\xdb\xb6\xed\xc1\xf6\xed\xfb!\x089x<\
+n\x5cs\xcd\x0aTWW \x95\xca\xa2\xb5\xb5\x1b\xa9\
+T\xba\x88\xe9t<\x22\x99LB\x0bP\xddz];\
+\x9c\x0e\x16 DK\xa8\x80\xc7e\x83\xcf\xa7\xe4>\x8c\
+FR\xe8|}\x04\xc9d\xa6\xe3\x99\x97\xde\xf8\xd7g\
+\x0eu\x1c\x05\x90\x04\x90\x06\x90E\xf1\x1a\x03\xb2\xdaV\
+S\x02\xc1T\x01@@M\x05\x87\x02\x02\x17\xa8O\xc9\
+i\xfb\x8d\x1b7\xff\xfd\xca\x95\xab\xaf\xa1\x99\xa8\xed\xa7\
+\x0b\x04\xb7\xdb\x8d\x85\x0b\x1ba\xb3q\xc8\xe5\xf2\x88F\
+\x93e{\xb0\xc5{L\xfaZ\xb7\xdb\x06\x8f\xc7\x01\x96\
+eq\xf4\xe8)l\xdc\xf8\x0c\xfa\xfb\xa3\xb0\xd984\
+7/\xc4\xca\x95K \x8a\x22\xba\xba\xfa\xd1\xdb;h\
+\x1a\xc13o\x0c\x04![\x98\x81\xc4\xb1\x12n\xbe\xaa\
+\x13N\x07\xab\x80O\x05\x8c\xc3\xce!\x14tB\x93\x0a\
+#\x03)t\x9f\x19F6\xcd'\x9f>\xf8\xc6\xdd[\
+\xf7\x9f=\x02\x1d\x00\x02\x8c\x8bOM\x0b\x04S\x01\x00\
+\xa0\x03@\xcbR1K\x01M\x12\xf8\x00x7n|\
+\xe2\xefV\xae\xbc\xe2j\xb5R0\xef\xa7\x03\x04\x9f\xcf\
+\x8b\x85\x0b\x9b\xc00\xa4\x00\x02I*~\x87\xa9\x0a\x02\
+\xed\x15\xedv\x16^\xaf\x13v;\x87ht\x14O<\
+\xb1\x13\xfb\xf7\xbf\x0a\x00hj\xaa\xc1\xda\xb5\xcb\xe1\xf3\
+\xb91::\x8e\x93'\xdb!\x8aRQ\x04O\x97\x00\
+\x0c\xd5\xfb\xf5\xa9\xea>W\x0a7\xae\x89\x80\xd1\xa4\x04\
+\x98\x02\x08\xea\xaa\xdd\xd0\x00@\x08A*.\xe0\xd4\xe1\
+>\xf0\xe9l\xb2\xado\xe4\xfb\xdf\xdf\xf8\xd2F\x00\x19\
+\x00<J\xaf42i\x10Lz\x89\x98\x12j\xc0\x0e\
+\x05\x00f\x10h@\xf0l\xdc\xf8\x87O\xafZ\xb5f\
+\x9d\x15\x00\xb4\xfdT\x81\xe0\xf3y\x0a \x10\x84<\xa2\
+\xd1\x84\x05\x08\xca\x87\x8e\xcd\xc4\xb2\x0c\x02\x01'\x1c\x0e\
+;\x04\x81\xc7\x9e=\x87\xb1u\xeb\x1e$\x12Ix<\
+n\x5c}\xf5r45\xd5\xa9+\x9dw \x16\x8b\x1b\
+\xc4\xbc\x0e\x00\xc6\x00\x04\x86!\xe0y\x1e<\xaf\xe4=\
+\x10B\xe0w\xa5\xf0\xb6+\x06\xc0\x10F-\x03 \xea\
+\xb9\xca\xb0\x0b6\x8e\xa1\xc7\xd9!\xa4\xf38s\xa4\x0f\
+\x89\xf14Z\xcfE\xbf\xf6\x83\x8d\x87\x1f\x85\x02\x00\x1e\
+\xc5k\x13O\x09\x04\xd3\x01\x00\x0d\x02;t\x10h\x9f\
+\x96\xf5\xc0\x08\x04\xf7\xc6\x8d\x9b\xefZ\xbd\xfa\x8auf\
+\xa6\x9a\xf7S\x01\x82\xd7\xab\x83@\x92d\x0c\x0d\xc5\x91\
+\xcb\xe9\xa1\xe3\x09\xde\xa6p\xa4\x19x>\x9f\x13\xb2\x0c\
+\x9c9\xd3\x8e\x87\x1f\xde\x86\xee\xee~\x00\xc0\xea\xd5K\
+\xd1\xd2r\x19\x9cN;\xba\xba\xfa\xd1\xd1\xd1S$\xe2\
+\x95q\x10]\xef\x9b\xa5A<\x1eWG\x1c\x95\xdf>\
+g\x0ao[\xd5\x07B\xb4\x9e\xaf\xde\x0b \xe0s\xc0\
+\xe3\xb1\xa9\xb5$\x85\xea\x8ay\x09'^<\x87\xc4X\
+\x0a\xb1df\xcb?\xfdr\xcf\x17`\x04\x01\xbd\xfa\x98\
+f\xa4O\x08\x82\xa9\x02@k=z^ \x0d\x027\
+t\x9b@\x93\x08\x1e\x00\x9e\x8d\x1b7\x7fj\xf5\xea+\
+\xd7Y1\xd5\xbc\x9f,\x10\x8c \x9008h\x04\xc1\
+Dj@a\xbc\x0b\x0cC\x90L\xa6\xb0q\xe3\xb38\
+x\xf08x^@mm\x18\xeb\xd6\xad@ee\x05\
+\xe2\xf1$N\x9f\xee@&\xc3\x1b\xf4\xba\xc2hk\xa6\
+\xd3~\x7f*\x95V=!\xe5?\xaf3\x85\x1bV\xf6\
+\x17\x98^\xf0\x0a@\xe0rs\xa8\x088\xd4\x86\xd6\x01\
+\xa0\xfdn=\xd6\x87\x81\xae\x11\xc4\x92\x99-\x0f\xed8\
+\xfe\xad\x13\x1d\xb1(\x14U`\xa5\x0e&\x04\xc1\x94V\
+\x09+!\x05\xb4\xd5\xc14{\x80\x96\x04\x9a4pC\
+\x01\xc1\xdf^q\xc5\x95\xeb\x8a\x0d<=el\xaa@\
+\xf0z=X\xb0@\x97\x04\x83\x83\xe3\x13J\x02\x87\x83\
+C(\xe4\x05\xc71\xc8\xe7\xf38p\xe0Ul\xdc\xb8\
+\x1d\xf1x\x12v\xbb\x0dW]\xb5\x1c\x97_>\x1f\x00\
+p\xfat\x07\xa2\xd1X\x81\xe94\xc3\xad\x99\x0e\xc3u\
+\xe3\xe3t\xefW\xad}G\x12\x7f\xb1\xbcO\xf5\x00\xf4\
+akB\xd4\xc9\xa5a\x97\x81\xe9j\xe3\xab\xbf\x81\xb6\
+\x13\x038\xd76\x88,/\x9cy`\xdb\xab\x1f}\xbd\
+s,\x0a\xc5(\x9c\xf2\xeac\xd3\x01\x80V\x0f\xcd \
+d\xa0.\x11\x83bu@K\x017\x00\xf7\xd6\xad\xdb\
+\xff\xa1\xb9y\xd9\x0akK\x7fz@\xf0x\xdc\x05\x10\
+\x002\x86\x87\x93H\xa5x\xad\xce\x85\xfa\xdbl,*\
+*\xdcp8\x14\x11\xdb\xdb;\x80\xdf\xfev+\xce\x9c\
+\xe9\x00\x0047/\xc2\x95W.\x85\xd3\xe9\xc0\xc0@\
+\x14]]\x03\xc8\xe7s\x06\xbd\xce\xb2V\x0c\xb7\xee\xfd\
+\xa2(\x22\x91\xd0g\x17i r\xd9\xd3X\xb7\xa4\x13\
+\x0e;c\x09\x82\x86Z\xaf\x81\xe1\xea\xcd\xeao%\xa8\
+2pn\x04'_\xee\x84 \x08}/\x9e\x1c\xf8\xfb\
+\x0d\xcf\x9dy\x15\xc5 \x98p\x91\xea)\xaf\x13h\xa1\
+\x0a\x0c\xcb\xc4@\x01\x81\x0b\xbaJ0\x80\xa0\xba\xba\xb6\
+\xf2\x89'\x9e\xba\xa7\xaa\xaa\xba\xde\xcc\xe0R@\xa0\xcf\
+\x97\x02B \x10DccMa\xcd\xbf\xe1\xe1D\x01\
+\x04\x0cCPQ\xe1\x86\xc7\xe3\x04\xa0\xac\x0b\xfc\xe4\x93\
+{\xb0s\xe7\x8b\xe0y\x01\xc1\xa0\x1f\xeb\xd6-W\x92\
+4\xc4\x11\xb4\xb7\x9eE\xef\xb8\xab\xc8\x98S\xf6\xa5\x19\
+n\x06F2\x99B.\xa7\x03\x88a\x94\xa4\xd8lv\
+\x0c6\x12\xc1\x0d\xab\x00\xaf\x9bNGW\xee\xab\x0a\xbb\
+\xe0\xb0\xb3EL7K\x85\xe8\xc0\x18^\x7f\xa9\x1d\x99\
+\x0c\x9f8\xf0\xfa\xb9\x8fox\xae\xed\x18t\xef\x80\x9e\
+GP\x12\x043](\x12\xb0X#\x18\xba:\xd0@\
+\xe0\xa16wmmmx\xd3\xa6\xa7\xbeX]]S\
+_\xde\xf7\x9f\x1a\x10\xfc\xfe \xe6\xcd\xd3\xe7\x0d\xc6b\
+I0\x0c\x81\xcf\xa70S\x92$\x1c?~\x06\x0f=\
+\xf4\x14\x06\x07G\xd4\x10\xee\x12\xb4\xb4,\x02@\x90\x1c\
+>\x0a\xf7\xe8\xab\x90\x04\x09\xdd\xb9\xc5\x18\x97kKX\
+\xfa\x13K\x00Q\x141>\x9e\x00\xcb\xea\xcc\xe5\xf98\
+\x92\xc9A\x88\xa22\xbaig2\xfc\x8dkI.\x1c\
+t{\x89\x16\x0f\x00A\xc0o\x87\xdf\xeb,f\xba\x85\
+TH\xc6Rx\xe9\xf9S\x10\x04\x01\x9d\x03\xa3_\xf9\
+\xe1\xef\x8fn\x80.\x09&\x5c\xae~\xa6K\xc5j\xf5\
+1\x83\xa0\x94:(\x80@\x91\x04\xdb\xee\xa9\xa9\xa9\xae\
+\x9f8\x084y \x84\xc3a\xd4\xd6\xd2)_\xca\x8d\
+\x03\x03Ql\xda\xb4\x03\x07\x0f\x1e\x07\x0044Tc\
+\xcd\x9ae\x08\x04|H$R\xe8\xe8\xe8A\x83\xff\x0c\
+\x167\xa6\x11mK\x03y\x09#R=\x86\xc8\xe5&\
+\x00L$\x01\x94\xf3z\xef'\x90\xa4\x1c\x12\x89\x01d\
+\xb3\xba\xbb\xda\xd5\xd5\xf9\xf2\x9e=\xcf\xef\x0f\xfam\xcc\
+/\xef\xfd\xf0\xc7j\xaa\x025Z\xb7r;m\xa8\x0c\
+\xb9\x0bL63]\xf9M\x0a?3)\x1eG\xfet\
+\x1ac#\x09\xf4\x0e\x8d\xdf{\xef\x86#\xbf\x82Q\x12\
+\x14\x81`F\x00\xd0\xebBh)@\x07\x89\xac\x0cC\
+\x17\x8a%A\xe5\x13O<\xad\xaa\x83\xc9D\x03'\x07\
+\x84p8T\x00\x01\xcf\xf38t\xe88\x1e|p+\
+\xb2Y\xa5\xe7\xad[\xb7\x1c\x8b\x165\x82\x10\xa0\xab\xab\
+\x1f\xf1x\x0a\xc9d\x0a\xd7/\xefCu\x05\x0fY\x92\
+1\xd2\x93F>\x91\xc38j1\xc25C&\xb6I\
+J\x00\x06\xb2,\x15\x06\x83\x12\x89A\xa4R\xc3\x85\x05\
+\xa8b\xb1\xd1\xae\x17_<\xb0}`\xa0o@k\xc7\
+\x80b\x0e?z\x00\x00\x10\xb6IDAT\xcf\xe6\xfa\
+\xfe\xd7?rg\xcb\xe2p3\x08`\xe3\x18\xd4\xd5\xf8\
+\xca2]=\xa1\xf1\x01\xf9\x5c\x1e\x07w\x1dGl$\
+\x81\xf1Df\xf3W\x7f{\xe8\x1f\xa1H\x02+\xe3P\
+\x86\x0a\x82\xd9\xfc^\x00m\x18NV\x12xjkk\
+\xc3\x9b7?}OU\x95\xa6\x0ef\x07\x08\x1cg\xc7\
+\xbe}\xaf\xe0\xc8\x91\x93\x18\x1bS\xe6\x0fr\x1c\x87\xab\
+\xaej\xc1\xf2\xe5\x8b\x11\x89D\xd1\xd5\xa5L\xc1\xca\xe7\
+E\xa4RI\xdc\xb02\x82\xaa _`\xeaPG\x1c\
+|\x5c\x80\xc0x\x11u^\x070\xf6\x12\x12\x801\xd8\
+\x08\x89D\x0a\xe3\xe3#\x88\xc7\xfb!\x08Y\xc8\xb2\x8c\
+L&=v\xfc\xf8\xb1\xa7O\x9e<q\x02F\x0b\xbd\
+\xd0y~\xf8\xcd;\xef\xbc\xf6\x8ay\xd7\x10BP_\
+\xeb\x05\xa7\xa6\xb1Y1\xdc\xc4\x83\xc2\xf9\xa3\x07O\xa3\
+\xfb\x8d~$\xd3\x99\xdd\x1b\xf7\xbc\xf1\x8f\xc7\xdbcf\
+\x0f\xc1\xe0\x1d\xcc\xe6'ch\xf7p\x22\x17\xd1\xa0\x0e\
+jkk+7o~\xfa\x1e\xc5&\x98\x5c4\xd0\xfa\
+\x1a\xfd|WW?\x1ezh[\xa1\x8e\x1e\x8f\x1b\x0b\
+\x17\xd6\xe3]\xef\xba\x1a\xaf\xbf\xde\x86\xa1\xa1\x91\x02\x03\
+\x13\x89$DQ\xc4\xf5\xcb\x07P]\xa1\x02@y1\
+\x88\xc9<\x06\xdab\xe0\x89\x17q\xd7\x1a\xe4mA\x13\
+\xd3\x8d6B>\x9fG{\xfb\x09\xa4R1\xb5\xce2\
+:;\xdbv\x1f8\xb0\xff\x05A\x10\xe20\xf6DP\
+m\xc6\x01\xe0\xbe\xf0\x99[\xde\xf5\xc1\xf7,\xbb\xad\xba\
+\xd2\x03\x97\x93C9\xa6'\xc7\xd38\xd7>\x94iY\
+\xb3\xd0\xc5P 9s\xbc\x03\xa7\x8e\xb6#\x91\xc9\xec\
+\xfa\xe7\xff<|\x17\xca\x8c\x1d\xccJ\xc6\x81\xacqC\
+\xd71\xda0q\x1e\x0a\xf2x\xb5\x12\x19(\x83\x19i\
+\x00)uKG\x22\x91\xe1\x0f~\xf0\xd6\x9f\x0c\x0d\x0d\
+\xf6\xeb\xba\x96\x81~\x5cl\x84Y_\xa33C\xad\x17\
+\x00mu\xcf\x0a\x5cye3^{\xed\x0d\x0c\x0f\xc7\
+\xc0\xaa\x9f\xb9\x95$\x85I\x8ca\xaa\x0f\x01\xd4\xb2\xfd\
+\xd5n,\x5cQ\x05\x17\x93B0\xb5\x1f\x0e9\x01\x8e\
+c\xc1q\x0cX\x96)\x94\xc3q,\xe2\xf1!\xb4\xb5\
+\xbd\x8cDb\x04\x92$ah(zj\xcb\x96'\xee\
+\xdd\xb3\xe7\xf9\xa7\x04A\x88\x02H\xa8[\x9c\xda\xc7\xa9\
+\xffS?}`\xc7\x8e\xef\xff\xe2\x85_&Sy\xc1\
+\x1cV\xd6c\x11\x0c\x18B\xd0\xdb6\x8c\xa3\xafv\xf7\
+\xb7u\x0e\x1d'\x0c\x03e#Xv\xe5e\x08\x84\xfd\
+`\x08\x13\x84\x22\x81m\xeaF\x0f'\x03\x98\xc5\x94\x13\
+\x0b\x10h.\x88\x06\x02\xc1\x04\x82\x14,@\x10\x8dF\
+\xfa\xcb3y\xf2@\xd0@\xe0t:\x10\x0c\xfa\x91\xcb\
+\xe5\x11\x8b%T\xa6)\x0c\xccd2`\x18\xe5X\x14\
+a\x0a\x1f\x12\xe4r\x12*\x1b\xbch\xb9\xba\x01\x0eN\
+\x86wl/\x1c\xd9\xae\x02\xe3Y\x96\x85(f\xd0\xd7\
+w\x0aCC\x1dH\xa5\xd2\xc8f3\xb1?\xfdi\xef\
+\xaf\xb6m\xdb\xfc@,6r\x0e\xca0.\xcd\xfc8\
+\x80q\xea\x98\x06A\xf2\x99\xddG_\xfb\x97\x9f>\xfb\
+\xff\x06\x87\x13\xfd\x1a\xd3\x01%\x7f\x80!(\xe4\x11\xf0\
+\xd9< \x13\xe6l\xd7\xf0 \x00\x03H\x9c\x0e;l\
+\x9c\xad\x81\x02\x80yn!\x03\x80\xcc\x1a\x00,@ \
+\x9b@ \xc0(\x092*\xf3\x934\x08\xee\xbc\xf3\xf6\
+\xfb\xa3\xd1\xe1>=\xbe>} h\xc4\xb2,\xecv\
+\x1b\xce\x9d\x1b(0\x9eeYu&\xae6e\x8b\x81\
+\xdb\x99\xa7\xdc-\xe5\xfe\xbc(\x83\x10\x06\x9e\x80\x03\xab\
+n\x98\x07\xbf\x8f\x85#v\x08\xb6t\x07\x08\x9102\
+\xd2\x85\xae\xae\xe3H\xa5\xc6\x90Je\xb2mmg\x9f\
+\xdb\xb0\xe1\xe1\xef\x9c=\xfb\xc6\x09\xf5\xdd\x92&F\xd3\
+\x9b\x06\x82\x02\xf3\xb5\xed\xa9\x1d'\xce\xdc\xfa\xd7\xbf\xfc\
+it8\xdeO3]\xeb\xe5D\x1f|\x22\x90\xc1\x9a\
+\xa5\x85\xcda\x87\xc3\xc6\xd5[\x00\x80v\xe1g?\xe9\
+l\x02\x10\x98\xd5\x81&\x0d\xb4\x17OE\x22\xfd#\x1f\
+\xf8\xc0\xfb~\x12\x8d\x0e\xf5)zv\xfa@P~3\
+\xe0y\x1e\xa2(B\x10\xf2\xe08\xb6 \x01\xb2Y\x1e\
+\x0c\xa3\x1cs\x1c\x8b\x80GQ\xcbf\x10\xe4r\xca\xca\
+WN\xb7\x03+\xae\x9f\x0f_\xd0\x05\xdb\xc8\x01\xa4\xdb\
+\x9f\xc4\xc8H\x1f$IBOO\xcf\xd1\x07\x1f\xfc\xed\
+\x0f^x\xe1\xf9\xa7\xa1K8\xba\xe7\x9bE\x7f\xb9\xff\
+\x93\x00\x92\x91hz\xe4\xca[~\xfc\xbd#'z_\
+62]yG\xbb\xdd\x86\xfaJ\xff\x02\x8ea\xdcz\
+0Iy\xf7\x0a\xf5\x83\xde(\x9eZNg\x14\xcdM\
+\xd6!\x05\x02s\xdaX9\x10h\xea \x19\x89\xf4\x0f\
+\xdfq\xc7{\xee\x8fF\xa3}\xa4\x10[\x9f:\x10\xb4\
+-\x9fW>X\xad\xf7~\x06\xb9\x5c\x1e\x0c\x83\x824\
+`\x18F\x15\x88\xba\xdfM\x08\x01\x01\x03Q\x95\x02 \
+\x80\xcd\xc6a\xcd\x8dKP;?\x84\x0a6\x8e\x1a\xe9\
+\x5cv\xff\x0b\xbb\x7f\xbfi\xd3\xa6\xc7y\x9e\x8f\xa1X\
+\xba%J\xec\x93\xd45\xe6\xff\x0d\xdbm\x7f\xf3\xc0\x7f\
+m\x7f\xfe\xd4\x1f\xf5E0\xd4\x88a}\x00,\xc3\xe0\
+\xed\xeb\x16_G\x88\xa2\x22\x0a\xf5V\xdb\x0cz\x94\xd6\
+\x0c\x00`\xb6U\x00MT\xb8q\x22\xc30MmZ\
+\xcaS*\x12\x89\x8c\xdcq\xc7-*\x08\xb4\x10\xec\xd4\
+\x80\xa0\x89vm\xd3\xf56\x07\x9e\x17\x0a\xba_\xdb\xd4\
+61\xb5\x11\xc0\x0b\xb2\xf1\xd9\x00\x9a\xd7\xcc\xc3\xbc%\
+\xd5\xa8rd\x9d\x1f\xb9\xa6\xf2\x1d^'\xc3\x96x'\
+\x0d\xdc\xf4o\x1a\xf4\xe6N`\x05\x82\xd4]\xf7<\xba\
+\xf97\x8f\xee\x7f\x84\xe7\xf3\x19\xad.\xf5\x0b*q\xcd\
+\xbb[\xe0\x0fy\x0cL\xa7U\x01\x8c\x8c/\x9ad:\
+\xa7y\xc7\x93\x04\x01\x0f\xbd\xc7d\xa0\xf7\x8cT$\x12\
+\x19\xb9\xfd\xf6[\xee\x1f\x1eV@0U \xd0\xe7=\
+\x1e\x17l6\xc5Z\xcf\xe5\x04\x83\xeeW6u\x81\xeb\
+B\xc4U\x05\x02!\xca\xc7\xa5\xa0\x1a\x96ZC\x83`\
+\xc9\xaaF,_\xb7\x10a\x9f\xbb\xee\xde\xbf{\xd7=\
+k\x97T\xd5Q\xef\x94\x85Q\xcai\x9b\xf6?\xfd\xee\
+\x93\x01A\xf2\xeb?|f\xcf\xe7\xbf\xfe\xfb\x9f\xf1\xd9\
+\x5cF\xab\x8b\xbf\xc2SH&\x81\xe6\x05AQ\x17B\
+N\x1aD1\xf3\x0d4\xe7\x89\xe7\x14\x08\xe8\x8f&\x96\
+R\x07ZO)4B$\x12\x19\xbe\xed\xb6\x9b\xef\x8f\
+F\xa3}\xc6^^\x0c\x04\xbd\x17h\xe2\x9f)\x80\xc3\
+f\xe3TQ\xafd\xe8\xd0\xbd_\xbbN\xc8\xcb\xea\xc0\
+\x8b\xd1\x13\x10%@.X\xe1\xc6g\xd5/\xa8\xc4\xea\
+\x1b\x96 \x10p\x85>\xfd\xfe+\xfe\xe9/\x96\xd76\
+\xc2\xe8\xf9\xe4Jl\x02\xb5/g \x1b\xd4\xc5S;\
+O\xb6~\xf8\xee\x07\xbe7\x14M\xf4\x19\x98\xae\xb5\x85\
+j+\x8cD\xc6\xc1\x8b\xd2\xe0D\xfc\x99\xfb\x99\x07(\
+\x92\x04t\xe6\x0a\xddPZo0\xbb\x88\xa9H$\x12\
+U@0\xd4W,\xeeu \x18\xff\xd7{6-\xe6\
+\xb3Y\x01\xb2\x0c\x93j`\xe0r\x88`\x0b\xd1\x14\xbd\
+\x97\x135\x00+\xe6e\xfd\x7f*\xd6@\x08AMC\
+\x08W\xbfk9\xdc\x1e\x87\xfbo\xde\xb3\xfaGw\xbf\
+o\xf9M\xb0H\x9b/\xb3\x99\x81Pd\x17\x81\xf2\x96\
+^:\xdas\xee\xe6\x8f\xfe\xecG\xdd\xbd\xb1\xb3\x05\xa6\
+\x17\x5c_\xa5\x8ebND<)t\xc0h\x90\x17E\
+\xfd\xce\x0b\x00\x00Ku\xa0\x01\xc0\x0a\x04\xe6\x06HG\
+\x22\x91\xe8\xad\xb7\xdelR\x07V@\x80\xc1\x00d\x18\
+\x06\xc1\xa0\xd7\xd0\xfbi@h \x008$2.\x83\
+\xfb\x08\xa2\x03B\xc8I\x06\xa6\xd3\x01\x19\x86\x10\x04\x82\
+^\xbc\xed\xbdW\x22\x10\xf2a\xed\xb2\x86/~a\xfd\
+\x9a\x8f\xc2\xca\xa0\xa0\x9a\x04\xd6@(\x1583H\x83\
+\xbe\xa1Dt\xed-\xf7\xdew\xecd\xcfA30\xf3\
+9\x11\xf1\xb1\x14^<\xd9\xbb\x03\x16\xb9\x82\xd4\xf3\xcf\
+\x1f\x00\x80\x926\x01\x0d\x00s\x0f0\xb9\x88\x91\xe8\xad\
+\xb7\xde\xfc\xe3ht\xc8\x22N\xa0\xf7|]\x0d0\x05\
+\x10\xb0,\xa3\xa6e\x93\xa2\xde\xcf\xb2\x0c\xf8\x9c\x84?\
+\x1d'\xe8\x8eh+\xb1\xa9v\x92\xaak\x85\x5c\xde\xc4\
+\xf4b\xdf\xdc\xedu\xe2\xba\xbf\x5c\x85`\xc8\x87\xa5M\
+\xe1\xcf\x7f\xef\xaek\xff\x15\xc6\x05\x9e4?\xbc\xa8i\
+P^\x1a\xd0\x12\xd1\x00\x84\x9b\xd6\xff\xec\x97[\xb7\x1f\
+\xdd\xa8\xabC\x16\x83=#\x88\xa7\xf8\x13\xbb\x8ft\x9f\
+\x81q$\xd00$\x8c\xd9\x0a\x05O\x85&0\x0c\xcd\
+\xba\xd0\x1c6N\x0e\x0c\x0cDo\xbf\xfd=?\xd2\xd5\
+A) \xe8\x9b$)V|&\xc3\x17\xf5|\x86a\
+02\xd2\x877\xde8\x82\xe8\xf0\x10\x9e\xda3:~\
+\xbam\xf0,\xa1z?@ \x08\xb2%\xd3\x09CK\
+\x05\x02\xbb\xc3\x86w\xdcz\x15\xe6-\xaeC8\xe0\xbd\
+\xf5\xfbw_\xf7\xf3\xcb\x1b\xfda\xe8\xfe\xb8\xd9%\xd3\
+\xda\xc2,\x195\x10\x98\xa3\xa7E\xc6\xe1]\xf7<\xbc\
+\xe5\xd1-/\xfdG.\x9fO\x89\xf9<^>\xd4v\
+\xe2\xbeG\xf7}\x13\xa53\x84\x0a\xea`V\x06\x83\xa6\
+C\xc4\xd8\xc2V\x03H\xda\xc4\x13:\xd9\xb40\x8a\xd8\
+\xd0\xd0P\xf9\xcc3;\xbeTYY\xd3`\x1c0\xd2\
+\xc6\xdb\xfb\xf0\xdf\xff\xfdt\x01\x04W\x5c\xb1\x14\xc9d\
+\x8a2\xe0\x80Tj\x1c}}g\x91J\xc5!\x8a\xf9\
+l__\xff\xa1}\xfb\xf6\xec\x01@>\xf7\xa9w\x5c\
+\xf9\x89\x0f^}\x87,kB\x80\xa0\xbe\xd6\x07\x1b\xc7\
+h\xf5\xa7\xaao=bw\xfah\x07N\x1dmC:\
++\xb4\xfez\xcb+\x7f\xd5\x1a\xc9\x0cA\x01\xb8\xd5\xe8\
+\x9c\xa1y`\xf1I>S\x9b8\xd5c\x87\xdaf\xcc\
+g\xfe\xeam\x8b\xfcn\xbb\xebG\xbf~\xeeU\x18\xbd\
+\x10m2\x89\xf6\xec\xc2\x80\xd4\x05\x03\x000!\x08\xac\
+\xe6\x1dX\x80`\xe7\x97\xaa\xab\xab\x1b\xf4\xa4\x10e\xdf\
+\xd5\xd5\x87\x87\x1ezZ\x95\x10\x12\xaa\xab\x9dp\xbb\x83\
+\xb0\xdb\x9d\xc8\xe5\xb2\xe8\xed}\x03ccQ\xc8\xb2\x8c\
+x<q\xea\xc0\x81\x03\xdbFG\x87F\x00u\x82\x22\
+@\xee\xfa\x1f\xd7\xae\xfc\xe4\x87\xae\xfb\xb0\xc3as\x12\
+\x02T\x86\xdc\xf0z\xf4\xef\x09[1]\xff\xa5\x5c\xd0\
+}\xb6\x1f\x87_x\x0dY!\xd7\x7f\xf0\xf5\x9e\xcfn\
+\xda\xd7u\x14F\x10\x98{\xa6V\x84\xd6&4\x08\xe8\
+\x8e\xa1mv\xea\x1a\xa8e\xd06\x15\xedv\xd2#\x82\
+\x22fk8x&T\x02\x04Z\xa2)=\x05\x8d\xce\
+1,\x0c'744T>\xfb\xec\xce/WU\xd5\
+4\xd0I!\xdd\xdd\x03x\xf8\xe1m \x84@\x10F\
+\x90\xcb\xc5\xa0\x0c\x15\xeb \xc9\xe7\xe5\xd8\xb1c\x877\
+\xb6\xb6\xb6\xb6B\xef\x8d2U\x17\xee\xe6w,\x9d\xff\
+\xad{n\xff,\xcb\xb2\xae\x80\xdfa\x98\xbae\xc5p\
+\xe57\x01}\x22:0\x8a?\xedx\x05\xe9t&\xf1\
+\xe2\x89\xbeO<\xbe\xaf\xb3\x14\x08hI@\x1b\x90t\
+\xa7\xa0\x81\xa0\xed\xcd\x00\xb0\xb2%\xcc\xcf\x12q!l\
+\x003\x95\xb1\x094\x11I#\xb9\xc8E\xec\xeb\xeb\x8b\
+\xbe\xef}7\xff0\x1a\x1d,\xb8\x88J\xe6\xae\xf6Q\
+h\x09\x82\x10\x83,K\x90$IM\xd1f\xd0\xdf\x1f\
+\xd9\xf1\xe4\x93O\xdc\xdb\xda\xdaz\x0c\xc6Q:\xc3\x08\
+\xdd\xce\x17Z[?\xf0\xb7\xbf\xf8V,\x9e\xee\xcb\xe5\
+\xb4\x88\xa01\xecJ\x07\x872)\x01\xcf?\xf9\x0a\xe2\
+\xc9\xec\x08Q\xad\xf3\xea\xfaJ\xdct\xfb\xf5p\xbb\x5c\
+\xbe\xebW6<\x0a\x9dy\x9a=`\x88\xceY\xb4\x87\
+\xd9S\xa2E;\x1dR\xa6\xdbF\x9b>\xa6\xa5\x86\x15\
+}\xad\x1c8\xcf^@)\xb2\x00\x01\x8d\xe2r.\xa2\
+\xe2\x12\xf5\xf5\x0d\xbd\xff\xfd\xb7|?\x91\x88\x8f\x98\xe3\
+\x00<?\x0cY\x16\x0b\xf6A&\x93o\xdb\xbe}\xfb\
+\xb7\xf6\xec\xd9\xf9\x87l6=\x04\x85\xf9\xe3(\x06A\
+ap&\x1aKG?\xf5\x8f\xffu\x7fk{\xe4\x84\
+\x15\xd3\xe9\x80L\x7f\xd702i\x01\xcf\xec:\xb1\x9f\
+\x1e\xbc\x09U\x05q\xd9\xb2y\xe0X\xd6\x07E\xa2\xd1\
+#t\xe6Q\xbaR\xf9\x15t\xcf\xb62\x96\xe9P\xb3\
+&\xfa\xadr\x02\x0b \xb8(\x00\x00\x94\x05A\xa9`\
+\x91A\x1a\xf4\xf6\xf6\x0e}\xedk\xff\xfco<\xcfg\
+\xb4F\x97\xe5<x~Te>\x9b\xe9\xee\x1e|x\
+\xf3\xe6\x0d?\x18\x1e\x8et\xa1\x98\xe1\xe3(=F\x9f\
+\x88\x0c\xa5\x86\xd6\xdf\xfd\xeb\x7f\xdf\x7f\xb8c\x8f9\xd4\
+LG\xe1\x92c\x19\xe4s\xf9\xec\xe1c]Qs\xd0\
+\xc8\xae.9\xbf\xa8\xca\x19\x82.\xd2K\x86iQ\x0c\
+\x84R\xae\x22m\xf0\xd1af\xed\x1a\xda\x0b(\xa8\x19\
+Y\x96/\xbc\x0a\xa0i\x0a \xa0\x07\x5c\x0a\x92`\xd3\
+\xa6\xc7N}\xe9K_\xf8\xae \xe4\xd2\x84\x10\xa4\xd3\
+C`\x18\x1bb\xb1\xccs[\xb6<\xf1\xe5\x03\x07v\
+\xeeFq&N\xa9\xbd\xf9\xba$\x80\xe4\x9d\x9f~\xe0\
+\xe1\xff\xdap\xe0\xa1\xc2\xbc>S\x14\xcef\xe7\xe0p\
+8\x9c\x12d\x16\xa0\xc3\xd5\xac\xe2:\x12\x06\xd7,o\
+Z\x81b\x15Pn\x11h\xf3\xd0:\xdd&\xf4\x98\x0a\
+\xbd\x99\x19\xafI\x00P\xfb\xd9]*v6H\x96\x0d\
+K\xd2HP\x1af\xa2Y\x9f\xda\xb5\xf9M\x9b\x1e;\
+i\xb7\xdb\xbf}\xf7\xdd\x9f\xff6\xcfg\xa3\xaf\xbe\xfa\
+\xf2\xaf[[Ot\xc28\xf6\xa0\x01\xc9\xca%\xd3\x12\
+5\xe9\xc4VCC~\xe5{[\x9f\xeb\xec\x8e\x0e\x7f\
+\xeb\x9fn\xff\xac\xd3i7|*,\x10\xf2\xa2\xafs\
+\x08\x7f\xb9\xf6\xb2\xeb\x08a\x0d\x9eB(\xac\xe4\x13\x8a\
+\x0a8\xe8\xdeo\xfc\xbe\x0dL\xb9\xfbz{\x00\xd4G\
+\xa3\xa8\xf6\x01\x8a\xc1c\x0e\x01\x1bt\xbfV\xf6E\x07\
+\x00`B\x10\x98\xdd\x96\x02\xf3\xd5-\xf7\xe8\xa3\x0f\xbf\
+v\xeaT\xeb\xe7\x8f\x1e=\x1cU\xaf\xd1\x98\xa71\x9b\
+\x16\x8f\xf4,\x1a\xda\x0b\xd0\x98\x94\xa3\xca.\x00\xe1W\
+\x8f\x1c8:4\x9a\xfc\xf1\xfd\xdf\xfe\xe8\xff\xaa\x08x\
+B\xcac\x08j\x9b\xc2h{\xbd\x07k\xafY\xd2L\
+\x87\x8e\x01\xc0\xee\xb4\x83\x10\x06\x90I\xa9\xe5\xdf-%\
+\x80\xd6\x1e\xea^{g\xcdf\xa0\xdb\x83\xb6!\xe8\xf6\
+1\xb4\xd9\x8cg\x06\x9d/\xb2p\x11\xe9\x00\x89\xe6\x0e\
+i\xbe\xb0\xb6\xa7-l\x8dh\xcf\x82\xd6\x9f4s\xad\
+2uiW\x94\x9e\xdf\xa0\xc5$\x5c\x8du\xfe\xf0s\
+\x7f\xf8\xd2Wj\xab\x02\x8d\xda\xad\xf9\x5c\x1e6\xbb\x8d\
+~\x0f\x00\xc0P\xff\x08v?\xb9\x1fO<\x7f\xea\xd3\
+;\x8f\xf6jK\xbe\xa4\xa0\xebmC\xee\xbey\x1e\x9f\
+\xa9M\x0a\x7f\x95m\xc42\xcc\x07.\x22#\xd0\x8a\xca\
+\xd8\x04\xb4!\xa4\x19@\xe6\xb1\x03s\xda\x15\x9dq\xa3\
+Y\xca\xb4\xb5,Xl\x1ac\xe8!ZC8\xb6w\
+ \x1e\xbdi\xfd\xfd\xf7\x1d;\xd1}P3\xfalv\
+\x9b\x1e\x92\xa6<\x85hd\x14\x0ca\xb0\xf3ho\xdb\
+,\xb4\x89U\xfa]\xd1fq\xbd\x81.j\x00\x00\xea\
+\x1b\x18S\xcch\xc3\xd0*N`\x1e93\xa7`\xd1\
+n\x12\xed'\xd3\xd2\xc0\xec~\x96\x1c\xa0\x02\x90\xea\xed\
+\x1f\x8b\xbe\xe3C\xf7\xffj\xc7\x9e\xd7\xb7\x99\x99nH\
+\xd2 \x04\xa2$\xcfx\x05p\xaaM\x0a\xc7\xa5\xc8|\
+\xbd\x99.z\x00hd\x91gH\xeb}\xab\x84\x0as\
+*\x96U\x8f7\xab\x00\xb3\x95]\xce\xfb0\x03-\xb9\
+\xfe\xee_=\xf6\xbb\x8d\xfb~[\xe4\x1e\xaa\xbf3\x89\
+,\xc6S\xc2k(1\x7f\xffB\xd0Ei\x04\x96\x22\
+\xca\x08\x02\x8c\x8d\xa7\xe9\xf8r.\x95\xf9\xc3\x8b\xda=\
+\xa5\x92%h\x83J\xa2\x8e\xcd 4$}\xfc\xefo\
+<\xb6\xf3\xd0\xd1\x8e\xce_\xdc\xfb\xc9\x7fv\xd8mn\
+=<\x0c\x0cGb87\x14\xdfO]O\xbf\x83\x8c\
+\x0b\x00\x887\x15\x00\x80\x22\x10\xd06\xc2d\xdc\x22\x9a\
+\xf9\x80\xd15\xb2jt\xedc\xcd\x80\x22\x09\xcc\x0c3\
+\x83A\x04\x90\xdf\xb0\xf9\xe5S6\x8e\xfd\x97\xef~\xf9\
+\xc3\xffPY\xe9\x9f\x0f(\xe3\x01C\xd1D\xc7/\xb6\
+\x1cy\x1a\xd6K\xb9\x94\xab\xc7\x9c\xd1E\xed\x05\x94#\
+\x93\x87`\x8e\xa5[\xc5\xd5\xcd`14\xb8YGN\
+\xe0\x81hk#\xd1\xf3\x1e\xcd\xc3\xb4\xdc\x92E\x95\xfe\
+}[\xbf\xfe=\xaf\xcb\xb1\xe8\xd9?\x1cx\xed\x0b\xf7\
+o\xfeZ\xffp:\x0a]Ei*\xa9(\x16QJ\
+g\xcf6\xbdi\x01\x00\x141\x09\xa6c3\x00\xe8}\
+\xe1\xb8\x5cC[\x80\xcc*o\xa1\xd4\x10\xad\x16\xeb'\
+w\x7f\xe4\xfaE\xbf~\xfc\xc5V\x14g\x0ck\x86h\
+\xd1\xf4\xedK\x00\x98\x02\x99|\xe3r~qY\x97h\
+\x82\xf2\xe9\x8d\x96\x04t\x02\x0b\xbd\xd1a^\xf3\x10\xad\
+9VO\x07\xa2&\xb5\xbc\xdbl\xd1\x9b\xce\x06\xb0\x22\
+Cd\xab(NR|\xcdt\xca7\x95KG%K\
+\x0d\xd6\xd0\xa1^\xed<=\xc4m\x1e\xa5+\xa8\xa5\xf3\
+\xc5|\xe0-\x02\x00\x9a\xe6\xaa\xf1J\x18\x9ffOD\
+\x03\x81\xc6|:\x09T\xeb\xe1y\xd3vA\xdd\xc1\xb7\
+\x1c\x00\xe6\x92,\xdcPm\x8c\xc2,\x05\xf20&}\
+jDO\x8c1\x8f\xd2]\x10]\xfc\x96\xb0\x01\xce7\
+\x95\xf0@\x18\x14\x8f\xee\x95J\xf20\x07\x82J\xae\xe3\
+7\xd7t\x09\x003\xa0\x12\xae\xa2\xd5\x06X\xc7\xea'\
+\x5c\xc9s\xae\xe9\x12\x00fH\x16\xae\xa8UL\x02(\
+vE\xe9\xe8\xe2\x05a>p\x09\x00\xb3Be\xdcP\
+\xabhd\xd1\xf1\x85b>p\x09\x00\xb3J\x16c\xf5\
+\x13\xd2\x85d>p\x09\x00sF\xe5\xc0p\xa1\x99N\
+\xd3%\x00\xfc\x99\xd3\x9b&\x1f\xe0\x12\xcd\x0d\xfd\x7f\xc7\
+\xc0 \xf9A,]\x89\x00\x00\x00\x00IEND\xae\
+B`\x82\
+\x00\x00>\xa7\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\
+\x00\x00\x00\x09pHYs\x00\x00\x00H\x00\x00\x00H\
+\x00F\xc9k>\x00\x00\x00\x09vpAg\x00\x00\x00\
+\x80\x00\x00\x00\x80\x000\xe11\x9a\x00\x00\x00\x06bK\
+GD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00=\xd0\
+IDATx\xda\xed}wXTW\xb7\xf7\xb5\xbe\
+\xd1D\x93\x18\x13\x937\xd1\x98\xc4\x98hL\xb0\xc7\xde\
+{G\xc5\x0a\x16D\x14\xectP\xaa`/tA\x04\
+APD\xc1^@E\xc5\x82\x15D\xa4\xd8+\xf6\xa8\
+\xc9\xfb\xdd\xfb\xbd\xf7~\xff\xeco\xad}\xd6\x1e\xf6\x9c\
+93\x0ch\xd4\xe4\xca\xf3\xac\x07ef\xce\xcc\x9c\xdf\
+o\xad\xbd\xda^\xfb?\xfe\xe3\xdd\xcf\x9f\xf6S\xfd\xbb\
+_*\xa1\xbc\xbb\x13\x7f\x91\x9f\xfa\x8d\x7f\xae\xf4\xd5\xf7\
+\xcdP*\xab\xa4\x12>\xf6\xee\x0e\xfd\xdd\x00\xff\xe1\x97\
+J \x95%\xa9JRM%\xe2\xef\xe2y\xef\xc8\xf0\
+W\xfei\xf0\xa3E%\x90\xca$\xd5@\xaa\x83\xfc\x03\
+\xa4\x06\xc8\xfb$\x1f\x90\x88\xff\xd7\xa0\xe7T\x13\xaf}\
+w'\xffr\xc07\x07\xe0\x9b\x03x\xcd\xab\x80\x00\x90\
+\xcd\x01\xd0\xe65Aj\x81|\xd4n\xc0\xf8o\x06N\
+\xf1\x1a:|F\xa0\xe70\x07\xff\x99\x03m=\x87\xc1\
+\xdf\xeb\x81|\x0aR\x07\xa46=\x1f_W\x95\xae\xf5\
+\xce\x1a\xbc! +U\x10|\x01<hu\xf3\x0fA\
+\xea\xf6\xb1\x9e\xd7c\xe4\x9c%\xfbF;\xad`j\x19\
+5o\xf9\x1f\xc3\x1c\x03V\xc1\xf3\xbe\x06\xf9\x02\xe4\x13\
+\x22\xcc{\xefH\xf0z\xb5Vhn\x15\xba\xf1U\xe9\
+\xdf\x95M\x81 \xbd\x1e\x9f_\x9d4\xb86i\xf5\x97\
+C\xa7\xfb\xfa!\xd0\xd6n\xc1\xcc/b3\x8b\xdfq\
+\x84\xed?\x96\xc3v\x1f9\xc76\xc0\xbf\xfd\xe1o\xf8\
+\xb8\xd5\x9c%E\x16]\x06\xb6!\x22|F\xd7\x10$\
+xG\x80?\x11\xf4\xaa\x92\xd6\xe2\x0d\xaf\xa1\x92\x7f\x10\
+\xb0:m\x14\x80\xa8\xb4\xfe=\xd2\xdcOZ\xf7\x1e\xf9\
+\xc3\xe0\xa9\x0b\x9c\xac\xe6.\xbb\x87\xe0z\xacJd\xa9\
+\x07N\xb1\xbdY\xb9,\xe3D\x1e\xcb<\x95\xcf\x8e\x9e\
+-`'r\x8a\xd8\xa9\xbc\xcbl\xfd\xb6C\x9c\x04#\
+f\x05\x9d\x87\xd7\xff\x0c\xf2\x0d\x91\xa0\x16\xbd\x7f\x95w\
+$x\xf5\xc0\x0b\xd0k\x90\xb9F\x8d\xfb\x98L\xb0\x90\
+:d\xc6?\xa0\xe7\xc9D\x90\xd7\xfa\x9a\xf4\xbc\xcf\x86\
+\xd8{\xcfC\xb3\x8e\x80\xceX\xb8\x96E&g\xb0\xb4\
+\x83g\xd8\xae\xc3\xe7\x80\x009\x9c\x00\x87\x88\x00\xc7\x91\
+\x00\x17.\xb3\xb3\xf9WYtJ\x06'A\x1f\x1b\xa7\
+ \x22AC\xfa\x0c\xef\xd3{\xbc#\xc0+\x02\xbf\xaa\
+\xe4\x9c\xd5&\x90?\x03\x8d\x9d\x08\x1a\x18m5g\xe9\
+\xc9\x91\xb3\x17\xef\xb7\x9c\xb1pE\xa7a\x93;\xc0c\
+_\x916~LDx\x8f\x00\xa9&\x99\xfc\x8f@>\
+\x87\xd7oA\x10g\x06\xc6\xb0\xc8\xcd\x19l\xeb\x813\
+z\x92v\xe8,\xdbw,W\x93\x00\xb9\x85\xd7\x99\xbd\
+O$X\x81E7\xe0Z\x1dA\x9a\x80\xfc\x93\x88\xf5\
+\xce\x0a\xbc$\xf8B[\xab\x93&\xd7&\xed\xfab\x88\
+\xbd\xcf\xdcQs\x97\xdd\x15N\xd98\xd7`\x90\xd5:\
+'\x0d\x009`\xd1uPKxn}Z\xd7?$\
+\xd0kH\xe0\x7f\x01\x84\x89\xc3\xe7/Z\xbbM\x0f\xf4\
+\x8c\xec|.\xf2\xdf\xf6\x1f\xbf\xa0\x10\xe0\xbc>\x01\xc2\
+\x92\xf6\xf2\xf7\x84\xeb\xf5\x03iIK\xc1'\xf4^U\
+\xcd\xf0CLI\xa5wZ\xafh0j\xf2\xe7\xfd&\
+\xb8\x8c\x02m/\xc4\x1b>\xd6e5\xb3\xf1\x8c`\x93\
+\xbc\xd72;\xbful\xda\xc28\xe6\x18\xb8\x9e\xd9z\
+\xaf\xe1\x80\x80\x07_\xfcs\xa7\xfe\xed\x09\x90\xcf\xe9\x1a\
+\x1f\x8ak\x81\x97?\x0e\x9f7?d\x93\x0e\xe4\xd3\xf9\
+\xd7\xd8\x9d\x07\xbf\xb1\x92\xc7\xcfA\x9e\xb1\xdb\xf7\x9f\xb2\
+\xa3\xe7\x8a\xf8c\xa9 \x87O_\xe2\x04\xc8\x96\x08\x10\
+\xb3\xf5\x00\x7f\xbf\x1fZw\xb5!+\xf0\x03\x85\x89\xba\
+e@\xc3\xffP\xfb1ZRM\xb5tU\xfa\xdf\x04\
+\xbep\xd0\xb8g\xde\xc5\xd2\xae\x1d\x00z\x0ao\xf4\x18\
+\xe7\x95\xcc\xda#\x9c\x03/d\x0a\x11`FP<\x9b\
+\xbdd\x03\x9b\xb9(\x9e\x832l\xba\xdf^x\xbd\x05\
+\xc8wd\x9a\xebQ\xd8\xf6-X\x89\xb3\x93\xe7\x87\xe9\
+\xc0\xbfP|[\x01\xfe\xd13v\x8f\xe4\xee\xc3\xdf\xb8\
+\xa4\x9f\xbc\xa8\xb3\x022\x01r$\x0b\xd0\xb8U\x97\xa9\
+p\xdd\xee \xcd\xe8\xbdj\x91\xf5\xaal\x22\xd7\xf0\x01\
+}\xc7\x8fTR\x9b\x1e\xab)\x91\x81G7\xff[\xc0\
+\xafA\xdaZ\xcf\xd21`\xa5\x12\x92\xadfN\xcb\x12\
+XP\xccN.\xee\xc1\x9b\xf5\x09\x10\x00\x16\x80\x080\
+oy\x12\x9b\xea\x1b\xcd\x81i\xd5\xd3r\x14\x5c\xa79\
+\xc8\xf7\xe4\xa4}\xf7k\xff\xb1}d\xd3\x8fZ^\x0a\
+\xba\x02\xfc\x1d\x14\xb0\x06\xb7\x1f<e\x17.\xdf\xe6\xcf\
+\xdb\x01N\xe1\xf1\xf3\x85\xa5\x04(@\x02\xec\x11K\xc0\
+D\x90\xdeD\xb8/U~@\x15\x8d\x5c\xc3'}m\
+\x9cz\x0c\x9d\xee7k\xf8\xcc\xc0eB\xfaOr\x1d\
+\x09\x11\xc9\x8fd\xb5>\xa1\xe7\xbe\xff\xb7O4\x11\x01\
+\xaa\x92\xe6\x7f(;hn+7\xb0\x8d{O\x1a8\
+h\x9b\xf6es\x22L\xf15$\x80\xf3\x8a\x8d\x1c\x98\
+\x81S\xbcv\xc2\xb5\xba\x80\xb4\x00i\x8a\xdez\xbf\x09\
+\xce\xfe\xf8XLj&\xbf\xce\xe5[\x0ft\xda\x8e\xa0\
+\x0b\xe0q\x09\xb8u\xff\x09\xcb\xbfzWG\x80c\x9c\
+\x00\xc5\xec\x0c\x11\xc0uy<\x03\x92>\x80\xebN\x06\
+\xe9Kd\xfb\x8a4\xf9=\x95\xe3\x89\x9a]\x17A\x97\
+}\x18-\x1913hk\xa7\xa1\x93:\x11\x99\xea\xd2\
+kk\xd0\xf5\xfe^$ \xf0\xab\x10\xcb\xd1t\xd6\x1b\
+2\xcd'@\xed\xa0\xed\x87p\xec\x5c\xc1M\x90\x1b`\
+\x8e\xf3t\x7fw]\x95l@\x00\xd7\x95\x9b\xd8\xe4\xf9\
+\xe1\x0c\xa2\x83'p\xbd\x81 \x9dA\xda\x82\xfc:\xd0\
+\xd6#\x01\xaf-^\x7fG\x07\xfcS=\xe0o\x95<\
+a7A.^\xb9cH\x80\x8bW8\x010\x0a\x18\
+0\xd9=\x07\xae;\x09\xa4\x0fY\x00A\x00\xe1xr\
+?\x06\xfc\x8e\x9eVs\x97\x16\xe0{#q\xe2\xd32\
+Y\xfa\xd1\x5c\x96u\xaa\x80\x1d\xcc\xcac{\x0f\xe5\xb0\
+\xe8M\x07\xd8\xfcU\x1b\xd9xpj14\x1dh\xeb\
+\xe9A\x96\xab\x1e)\x86\x8e\x04\x7f7\x02T#S\xf7\
+I\x8b\xee\xc3~\xc6/?o\xc9z\x1dH\x97\xae\xdd\
+cO\x9f\xff\x8b\xcb\x93\xe7\x7f\xb0'\xcf\xfe`\xc7r\
+.\xf3\xc76\xec:\xce\xec\x89\x00\xb3\x88\x00.@\x80\
+\x19\x81\xb1\x5c\x9b:\x0c\xb2\xf1\x87\xeb\xf6\x07\xe9\x01\xd2\
+\x13\xbc\xffK\x18\xf6\xe1k\xf7\x1e\xbb \x81\xfeT\x07\
+:\xca\x8d{\x8f\xb9\x9c\xbax\x8d?wOV\x8eB\
+\x80\x5c\x85\x00\xd9\xb9E\xfc\xfa\xbd\xc6\xcd>\x08\xd7\x9d\
+\x00\xd2\x0b\xe4\x17\x22\x80\xa8\x13\xf0\xd4r\xefqsz\
+\xe3w\x9a\xe8\x11\xc22\x8e\xe5\xb0K\xc5\xb7XN\xfe\
+uv\xea\xfce\x85\x00\xc7.r\x02l\xdf\x7f\x96m\
+\xd9\x95\xcdb6\x1dbv\x0b\x22(\xcf0o\x0e\xf9\
+1\x9f\xd3\xf5\xfe>\xd9F\x95\xf6\xe3\x97\xfb'\xc4\xf7\
+\x8bd\x13\x8d\x0e\xda\x13\x04\x1e@\x7fL\xf2\xe8\xb7\xdf\
+\xb9\xec:\x9a\xc3\x9f\xe3\xbcbS)\x01\x96)\x04\xf0\
+\x80\xe5a\xac\xcbJ6h\x8a\xd7I\xb8\xeeh\x90!\
+ C\xc1*<\xc6e\x05_w\xf0\xd4%=m\xbf\
+I\xa0\xa3\x5c\xbf\x8b\xf2\x88e\x9e)\xe0\xcf\xc5|\x80\
+L\x80\xed\x07Oq\x80\xda\xf4\x19\x15\x05\xd7\xb5&\x82\
+!\x01\x1aP\xf8\x89\xa6\xfb\xf3\x9ecf\xf6\xe3\xe0{\
+\x86\xb0\xec\x9c\x22v\xf5\xc6=V\x00~\x85\x01\x012\
+s\xd8\x8et \xc0\xeel\x96\xb4\xed8[\xbb)\x93\
+M\x99\x1f\xc1`\xb9\xf8W\xb3\x8e}\xd1\x82}+e\
+\x1b\xab\xff-\xf2\x0c\xd2\xda_\x83\x9c\x9eo\x86\xcf\x08\
+<,<\xf4m\x99\xe7J\x81'\xd0Q\x1e>Ey\
+\xc1N^\xb8\xc2\x9f\x17\xb21C!\xc0b}\x02\xd8\
+\xf9\xaca\x10:\xfe\x17\x5c\xd7\x0eA\x02o\xdd\x1eA\
+\xf3\x8f\xdc\xc2_w\x02^/k\xfb\xf5{\x0a\xe8\xd7\
+P\xee<bW\xef<d\xfbh\xb99p2\x8f\x1d\
+;W\xc8N\x12\x01B6\xec\xe6\x04\xf8\xbeE\xc7\x05\
+p\xedqD\x00\x0b\x0a=q\xed\xae?\xc8n\xbe\x0b\
+>\x07\xbfOj\x86\x92Z\xde\x0e\xdfi\xc7\xe1\xf3l\
+'\xc8>\xb0@\x87N\xe4s\x02\xec\x93\x08\xb0\x11\x08\
+\xb0>\xe5([\x19\xa38\x99\xe0\x1c\x86I\xe4\xaaS\
+V\x9e\xe1\xafh\xfe?\xa0u\xee\xc7\xe13\x83r\x85\
+\x89>\x90}\xa9\x14\xf4\xdf\x14\xd0\x1f\xa0<y\xc1\xee\
+?y\xce5V8\x84\x0eD\x80\xb9\x12\x01\xe6,Q\
+B\xc2\x1e\xa3\x1d\xb7\xf5\xb1q\xda9\xc4\xde'\x17\xff\
+/\xb2~y\xb0\xbe\xcb\xda.\x03\x7f\xf5\xf6Cv\x05\
+D,C\x98\x07\x90\x09\x10\x10\x99\xc2\xe0\xb3\xfe\x0e\x9f\
+\xd9\x19d<-\x01\xad\xf0;`\xd4\x01\x96,\x08\xdf\
+\xcb}U\x22KI?\xc5v\x08\xe0\x8f\x9c\xe7\x96k\
+7\xc8\x1e \xc4^\xb0,\xfb\x8f\xe5I\x048\xa5#\
+\xc0\xda\x8dh\x05\xc2\x19.[p\xcd\x0e\x94g\xf8\x5c\
+\x1df\xfe\xd5C\xbf\xea\xb4^b\xfc\xfc3\x84Cy\
+\xa5\x04\xc8\xd7i\xbb\x0c\xfc}\x9e\xacQ\x126\xb8\x8e\
+\xe3s}\x22\xd2\xf4\x08\x80\x11\xc2\xfc\xb0-l\xbc[\
+\xb0\xce\xbb\xb6q\x0ffv\xde\x91\xba\xa8\xa2\xe8F\x89\
+\x02\xfa]\x02]\x02\xfe\x0aD\x07y\x14\x02\xa6\x1d<\
+\xcb\x09\x90E\x048\x0d\x04\x98\x19\xb8\x96\x0ds\xf0\x7f\
+\x0c\x9f\xd9\x8d\xc2\xc0\x01\x94\x0cj\xd5g\xfc\xdcyJ\
+Q)I\x07\xfa!x}N\xd1MV\x00\xfe\x8c\x10\
+L>e\x9c\xbc\xc8\xd2\xc1\xc1\xdd\x9fu\x81\x13`+\
+\x11 ~\x8bB\x00\xa7\xc5\xf1\x0c\x9c\xc7\xff\x94\xc2\xcc\
+\x06\x94\xd0z\xef/\xbb\x0c\xa82~\xef\xd1\x17\xc2\xd4\
+msX\x02.\x0a\x02\xa0\xf9\xd5\x81.\x03/%l\
+\xce^\xba\xc1\x9f\x1b\x99r\xc8\x90\x00\xa1[`I\xd8\
+\xc0\x5cW$\xb2\x80\xa8mli\xdcn\xb6j\xc3>\
+\x9dV\xab\xb5\xfd\xca\xed\x07<,D)\x06\xc9&\x07\
+\x10#\x80\xc3\xa7\xf3\xf5\x08 H\x05K\xcc\xff\xed?\
+\xc9\xed\x80E\x97\x81\x0e\x98\x12n?p\xbc\x1d\xae\xdb\
+\xd3\xfd\xa2x\x06\x11\xb5\x1d\x1dI\x19x\x9d\x5c\xbf\x07\
+>\xce-N\xf4\x83\xa7\xf2\xd9\xae\x03\xe7\xd8\xd6=@\
+\x80\xed'8\x01b\x80\x00\xee\xcb\x12E\xae\x01}\x98\
+_\xc9!\xacKQ\xc6\xdb\xbf\x0ch\xe4\xbd\xab\xa8R\
+\xa1\xef\xd3\xfa\x8f\xe1N\xabAv^;\xf0\x0b\x0b-\
+Ep\x84\xb6k%l\x10@\x01(\x82\x8f\xe2\x8c\x04\
+X\xad\x10\xc0'\x22\x95\x83\x1f\x14\xb3\x83\x13 lS\
+\x86\x8e\x5c\xb2\xb6\xeb\x80\xbfy\x9fK\xd1\x8d\xfb\xec\xe8\
+\xb9b\xfe\x5c4\xd7z\x04\xc8\xbb\xc2\xce_\xba\xc6R\
+\xf6\x9f`AQ[ud\xb0t\x5cx\x09\x8bC\xd8\
+K\x80\x15E4\xf1\x98hB\xa0e\xd0\x85\x14\x92d\
+\x83/\x92\x09\x16b\xdf\x91\x5cN\x80M\x12\x01f\xf8\
+\xaf\xc5\xfa\xc63\xb87V \x98\x1bh,\xa5\x9b\xdf\
+^\x02h\x94r\xabK\xe5\xdc\x9a\xf4\x05jQ\xcc\x5c\
+\x8f\x98\xdd\xa6m\xbf1\xb3\xf0f._\xbf\x8b\xdf\xfc\
+\xe3\xb9W\x0c\xd2\xb3\xea\x84\x0dz\xf3\xf8\xdc\xc0\xb5;\
+8\x01\xfc\x01\xf0\x95\xa0\xe9\x11\x9b\x0f\xb2\xf5;\xb2X\
+\xe2\xee\x13\x06\x89\xa4#g\x8b\xf4\xb4\x9d\x83N\xc0\x17\
+\xc2\xd2\x80\x22\x96\x97\xfd\xb0Ngr\x02\x14\xe8\x11\xe0\
+B\xd1\x0dv\xe9\xca-^\x17\x88\xdf\x9e\xc9\xa6\xf9*\
+\xb5\x88\xc4]\xc7\xf8k1\x82\xd0\x02\x5c-g/]\
+gG\xcf\x16\xb2\xf4\xac<\x89\x00Y\x10\x0ef\xb2\x89\
+\x1e\xa1\x0c\xfc\x09\xf4\x01\xc6\x80t\xa5\xaa\xe3\xe7\xe47\
+\xbd}e\xe7\xb2\xfa\xecH\xdb\xebRH#\xf2\xf3\x0d\
+\xc8yj\x072h\xc4\xec\xc5O\xc52\xb0\xebH\x8e\
+AzV\x17\xb7\xdfW\xc27L\x0e\xe1s\xb5\x80\xd6\
+\x12\xd4\xfe\xc2\xeb%\xa5\xda\xae\x02\x1e\x1fC\xc0\xb0\x1c\
+,,\x00\x96\x84\x91\x00\xd8\x14\x82\x048G\x04\xc8\x07\
+\x02\x14]\xbf\xc3\xae\xde\xbc\xc7n\xdc\xb9\xcf\xbd}L\
+T\xa1I\xbft\xf5\xae\x09\xe0K\xe0u%\xdc\x0f9\
+\x0f\x9f\xff\xd8\xf9\x22\x96\x01\xce`*\x11 ak\x16\
+\x0b\x08S\xacK\x97\xe1v\xc9\x7f\x09\x02\x98\xea\xb3\xeb\
+6rZ\xeba\x8e\x01\x0b\xb0~o5gI\xf6H\
+\x100m[z\x8f\x9f;\x9e\xd2\xb4-(c7\xa4\
+\xe7\xd8Y\xc9\xf8\xc5\xe3wfq\x00\x10$\xad,\x9d\
+\x08\xe1\xd0\x94\xef\xc9\xba\xa0\x03\x18M\xef\xa1\xd3\x05<\
+Y\x94[t\x0b\x9c\xaf[ej;\x02\x22\x80\x17r\
+\xf8L!'\x01\x86\xa3\x18\xbea\xd8\x86\xa6\xfat\xde\
+e}\x02\x5c\xbb\xc3\xae\x00\x01\xce\x17\x5c\xe7\x0e\xddA\
+X\xd3qm7\x05\xba\x90b\x90s`\x01N\x80e\
+9p\xfc\x22K\xdd{\x9am\xdaq\x82\xadK>\xcc\
+\xb5\x7f\xc4\xcc\xa0\x17pO\xe6\xbc\xd5K\x80\xa9>\xbb\
+\xd6\xbdF\xfc\x88E\x1d\xd1u3\xc6e\x15/\xe7\xa2\
+\x88\xb5\x13<\xff\xc3M\xdb\xf5\xeaG\x9e\xee\x88\x9f;\
+\xf6\xf3\x90S\xc1\x87\xc1<\x96\x95\xb0AO>\xb7\xf8\
+6\x07\xd7\xe4\xdanD\xdb\x8dIv\xdeU\xbe\xc4\xa0\
+%R\xc2\xb7\x5cn\xde\x8f\x82?\x80\xe9\xe0\xfc\xcb\x0a\
+\x01.^\xbe\xc9=zt\xe8r\x0ao\xea\x01\xaf\x06\
+]\x00_\xcc\xff}\x8f\x9d\x02\x8b\x92\x0d\xb2\xe7P\x0e\
+'@2\x10\xc0\xd1O)h5\xef:x\x0d\xdc\x93\
+\xe9o\xad\x13h\xac\xcf\x8e\xb2zN\x02\xf8qn!\
+l\xc2\xfc(\xbdR.\x8a\xb5G\x98h\xe4\xb8\xd6\xb6\
+\xef\xa8\xb9\x14S;b\x91\xc5\x1e\xd6T\x9e\x10:t\
+\xae\xcc\x84\x0d\x8a\x96'o\xae\xb6\x97%X\x14\xc2\xb0\
+\x0d\xc9\xb0\xef\xf8\x05^\x9b8\x00\x80cu\x10-\x01\
+Z\x06\x5c&\xce\xc0s\x8a\x10\xf4\x1b\xc6A\xe7r\xb3\
+\x84]\x069\x0b\x96\xe4\xf4\xc5\xab\xec88\x8b\x18\x05\
+\xa4\x01\x01\x5c\x97&\xf0{\xd2i\xe8\xa4\xbd\x14fN\
+\xa0ZC\xf3\xb7*\x0c4R\xc6\xfd\x8c7oP\x83\
+%o\xde\xf0\x8a4\x00^\x96\x09^\x8a\xf3\x84\xf1n\
+\xbb\xfe\xe3\x96\x7f\xdf\xa2\x93\xd7 \xbb\xf9ErJ\x18\
+\xcd\xb8~\xc2\xe6\xa1\xf1\x10\xae\x82\xdan\x8e\xa0Fc\
+<\x7f\x22\xf7\xb2.|;\x04\xa4@\x02\x9c\x02ka\
+\x0e\xe8\x97\xe1s\xa1\x5c\x80\xeb`e\xf1\x0c\x10 \xe3\
+h\x1e'\xc0bp`\xf1{\xc3\xd2\x98\x0b\xf7\xd2\x87\
+\xb4\xdf\x92r\x0c?\x92\xcf\xf4v$\x824\xc0\xff|\
+\xe4\xec\xc5\x19\x22\xfd\x19\x10\x95\xc6\xa2\xb6dB\xe8u\
+\x80\xf9\xad\xd9\xc6\xbbw\x8c\x92\x00\xac\x03.\x0fd\x0d\
+\x9e\x89\x8e\x1d\x11\x0e\x9e\x81u\xb2<\xda^\xf4\x12\xda\
+n\x8e\xe7\x8er\xf1\xf2mv<\xa7\x18|\x05\x8c\x0e\
+.+\xe6\xde(\xe8\x0a\xf0WPn\xdd\x07\x8br\x9b\
+\xfb\x11(X\x0f\xc88z\x81E&\xa5\xf3\xef\x0f\x0a\
+T\x04\xf7\x12\x9bM\xd1\x22\x8e\xa5,csjA\xff\
+\xe4\xadH\x05K\x85\x1c]\x0d\x7f\xf8\xcc\xa0\xadr\xae\
+\xddX\x0d\xdf\x18\x09&.\x88fc]\x839y\xe4\
+&\xcdLp\xe8^\x97\xb6\x17\x96%7JL\xae\xe9\
+\x08\xb8\x1a\xf4\xcb\x04\xba\x90\x82kw\xb9\xc3\x88]E\
+\xa7\xc0Q=r\xf2\x12K\xdey\x9c\xefE\x18\xe6\xe0\
+\xff\xb4Q\xf3\x0e\xc1d\xfa'Q\x86\xb1-5\xb5\xd4\
+{+Z\xcfU\xa6\x1f\xc3\x91O\xfb\xd8\xcc\x1b\xa3\x06\
+\x1fc\xed\xbc\xcbw\xb8\x88\xd6*\x14\xb4\x06\xc6H\xe0\
+\xb4b\xa3N\xeb\xd1\x03\xc7\x10O\x0d\xba:a\xf3\xb2\
+\xda^6\xe8\x04|\x19\xe6]\xcf\xc4\xdf\xd2\x07\x1d\xe5\
+*~\x07x<\x17|\x06\x94\xf3\xe0/\x9c<W\xcc\
+\xb5\x7f\xca\x82p\xece\xfc\xefF\x16\xed#\xe0~b\
+\x81\xc9\x1ed\x18\x99\xfe\xa6T`\xfaH\xea\x09\xa8\x22\
+z\x0e\xb5\xe4uj?~\xa8\xfa`\xfa\xcf\xc8}v\
+\xb8N\xaa\x1b-D\xf5\x0eeU\xe2~\x03\xf0\x91\x18\
+rw.\x82k\xae\xb6\x17\xbe&\xd0\xb5\xb5\xfd\xbe\x0e\
+\xf4\xcb\x06\xa0+\xc0_\x03\xc1\x7f\xe7\x15\xdfT\x04\xee\
+\xcf\xf9\xbck\xa0\xfd\xf9\xcc1 \x9a\x8d\x9c\xbd\xe4\x7f\
+~\xe94`3\xdc\xcb\x85 \xb3\xa9\x84-J\xcc_\
+K{\x0e\xaaK\xbb\xa0\xe4]Qj\xf9\xf3\x1aJU\
+M\x1c\x9fB\xa8\xd2B\x0e\xdbP\xf3\xb5\x126(g\
+A\xa3\xd1\xab\xc7\xe7\xad\xdbvT\xe7\x17 !\x04\xf8\
+\x18\xbf_)\x97\xb6\x97\xbc<\xe0\x22d+/\xe87\
+\x8d\x83.\x80\xbfvG\xf9}\xe9\xcam\xf0\x1bn\xf1\
+\xdf\xf9\xe0\xd4\x22\x01b\xb7\x1cT\x1aK\xc6\xce*\x84\
+{\xb9\x12\xc4\x83Z\xcc\x84\xe9oD\xa6_\xde\x88Z\
+]\xda\x19%\xb2\xaa\xb2h\xee\x90z\xd5\xce\x9f\xae\x8a\
+\xd7s\xec\xacIr\x99\x15C&\xad\x84\x8d\x88\xdb1\
+C\x86\x152|n\xc2\xae\xe3\xdcI\x14&\x1f\x0b'\
+ek{\x09\x81^b\x14\xfcB\xb3\x81/\xe1\xdan\
+\x14\xf4\x9b\x1a\xe6\xfd\xa6\xa1yWk\xbb\x00\xfe:\x97\
+\x87\xac\x10\xd6}\x04\xbe\xf0\xda\x1dv\x19\xc3J$\x00\
+|\xd7lX\x02|C\x939\x09\xda\x0d\x18\x97F\x8e\
+\xdf\x18\xea2\x16=\x00\xa2/\xf0})\x85\xfe!\xf5\
+\x06\xc8YU\xb1s\xf9\x13\xb2\xcc\xf2\x0e\xa9*\xaf\x84\
+\x08\xd2\xfa/\xbax\xea\xf7\x18=c\x8aL\x00\xec\xa3\
+3\x1a\xb7S\xe9\x15\xc1\xdd\x9d\x95\xab\xb7\x0b\x07;p\
+Mi\xbb,j\xa0\xf55\xbd\xc4\xc4\xef\x12\xa3\xa6]\
+\x0b\xf8\xcb*m\xd7\x03\xbc\x0c\xd0\xf17>\xa7\x18\xbb\
+\x80\xae\xde\x01\xe7\xf1.\xbb\x01\xcf\xb9\x02\x9f\x05\xdb\xc2\
+8\x01\xce\x17\xb3\xa3\xd9\x05\xcc\xd1?\x1a7\x9c\xfe\xbb\
+Y\x87\xbe\x18\xfa\x8d\xa4\xac\xe8OR\x87Q\x1di+\
+\x5c\xbd\xde\xe3\xe7\xf4\x1a1\x13wF)YU!\x98\
+t\xeb4\x847\x94\xd6'B\x88\x1dR\xaf\xa6\xb3X\
+\xd5\xc6\x85,\xfb\xba\xfb(\x87\xa9\xe5m\xb4\x10k{\
+\x16\xdc\x80tX\x071\x8bgL\xdb\x8d\x01oT\xa3\
+U\x82iYY\xb0\xce\x8fb\xcc\xbc\x17\x9b\x09\xfaU\
+\x03\xd0\x95u\x1e\x01GM/\xb8\xaah<\x0a\x82\x7f\
+\x19\xfe~\xeb\xeeC\x1d\x01r\x80\x00\xd8\x16v\x14\xc2\
+\xc0m\xe9\xa7\x99\x0dD\x01C\xa7\xfb]\x85{\x8a\xed\
+\xec\xdd\xa4}\x0d\x08\xe6\x97\xadz\x0e\xff\x09\xa2\x04\x1f\
+\xb9\xabx\x82[(\xb3q\x0de\xd6.!l\x9c\xb3\
+^v5\xcd\xa2\xeb\xa0V\xd2\x0e)y\xf7r\xe5W\
+\xe5\x00\x22\xbb\x1a\xb6\xe9c5X\xf6\x012\xcf\x14\x1a\
+O\xd8\x18]\xdbM\x03o\x0e\xd0(\x08\xec\xa9\x8bW\
+y\x19\x16\x134\x98\x97\x17\x89\x1a\x0c'1f?r\
+\xb6\x90\xa7r\xb3\xe09\x18\xc7c&.\x17\x9c\xb2K\
+\xa0\xa5\xc6L\xbc\x81\xb6K\xa0_\xb9U\xc2\x01F-\
+\xbf\x04\xa0\xe3o\x01z\xf1\x0d\x05x\xac\x15\x5c\x85\xe7\
+]\xc3k\xdc \x02\xe4_\x93\xfa\x02\xf3X\xd4Fe\
+\xc3i\xefq\xb37P#+\xeen\xb2\xe87\xd1\xd5\
+\x11B\xecT\x1d\xe8\xee\xa1l\xb6\xffz\xe6\xb6(\x99\
+\xb9\x04nbs\xfd\x92\xd8,\xef\x0d\xcc\xd1+\x9e\xd9\
+\xbb\xc72\x1b\x97p\xad\x1dR\xf5^\xc9\x16v-\x0b\
+\x80u|\xcb\x19\x0b\xf3\xe5(\xe0t\xfeu\xa3\x8d\x16\
+\xa6\xd6v\xe3\xe0\x1b\x7f\x1c\x97\x1c\x8c0\xb0\xeb\x06\xd3\
+\xb3\x07E\x86\xee\xb4\x02|\xd2\xeecl#\xca\x9ec\
+l\xd3\x9e\xe3,y\xaf\x22\x08>\x16a0\x89\x83)\
+]\xcc\xc9cV.\x0f\xc0A+`\xa0\xedw\x04\xf0\
+\x0f9)\x10`\x5c\xd7Q\x84\xb6ce\xb0X\x00\x7f\
+S\x06\xbe\x84]\x87k\xdd\xc0\xd7\xc3\xef\x02\xad\xce\xe0\
+\xcc\x1c\xe6\xbcd=fD\xff\xab\xc3\xe0\x09\xbe\x03m\
+=\xe2\xad\xe6,}\xc0S\xe9.\xab\xd8\xac\x80X\xe6\
+\xb7:\x95\xf9\xaf\xde\xc6\xbc\x97oe\x1e\x8bS8\x01\
+\xe6\xf9\x13\x01\xe6\xc7\xb3i\x1eq\xcc\xce\x0d\x1ck\xe7\
+(\xb1\xc7 G\xeaU\xfc\x94\x96\x83\x8a7\x95j\xf9\
+\x00X\xc9\xeb4l\xb2\xab\xd8\xc8!H\x80\x159\xf3\
+B\xb8\x8aI>\x00\x8f)YQ\x84A\xd0\xb7\x83/\
+\x11\xbca\x0fs\x87\xcf1\x85Z\xabM\x89\x9dw\x04\
+\xf3Z\x9d\xc4\x22\x93\xf7\x03q\xf2\xd8\xd9|%;\x87\
+\x89\x1a$\x02\xfa\x00B\xdbQ\xf39\xe8WKA/\
+\xb8fB\xdbI\xe3\xaf\xdfQ\x80\xbfy\xf7\x01\xbbu\
+\xef!\xbb]\xf2\x90;\x82\xb9\xf9J\x22H&\xc0\xc6\
+\xed\xc7\xf8N(\xf1\xf9f\xf8\xc70\xefU\x9bY\xf2\
+\x8e\x93\xec\x10<\x07-\x07J\xe6\x89|\x16\xb7\xf9\x08\
+s\x15\x04\xf0\xd1'\x80\xadK\x0c\xb3q\xa2\xd6r\xeb\
+yb\x0b{\xfdW\xd2T\xaa\xd5\xcb\x87=\xf7\x03l\
+=\xf6\xa9I\x80\xeb{\x01\x0f\xaf^\x0d\xe8\xdc\x0f\x00\
+\x8fZ\xc9\xc5+\xda\x8e\xc5\x99\xc8\xe4t\x1eOKk\
+\xe0\xbf\xfaMp)\xee1\xda\xf1t\xcb\x1e\x96\xdb[\
+\xf5\xb4L\x835t\xab,\xe0\xbc\x9e\xec7\xd1\xa5\x00\
+\xcc\xeb\x1f\xe2u\xd8\x87\x10\xbf\xfd0\x15y\x94\x98\xbd\
+\x80\xaf\xe7w\x80p\xb7\x0dM<\xad\xed\x8a\xb6\x97\xe8\
+\xcc\xbc\x1at\x05\xf8G\xec\xce\xfdG\xec\xee\xfd\xc7 \
+\x8fX^\xe1Mv\x1a\x08p\xecT!\x07W4\x86\
+.Z\x93\xc6\xbc\x83\x93Y\xfc\xd6#\xec\xf8\x99\x22v\
+\x17^\xf7\xec\xf9\x0b\xf6\xfc\xc5\xef\xec\xc5\xef\xbf\xb3\xdf\
+\x7f\xff\x83\xfd\xf1\x87\x22\xb7\xc1\xa7\x08^\xb7_\x93\x00\
+\x93\x9c\xd6\xb21N\xab\xc4\x16\xf6\x0eTJV5\x95\
+ZTz\x99<\x80\xe8\xe6\xfd\x812V#\x80m\xbb\
+\xf0Fb%Od\xf4\xb0\x84\x8a\xa1\xe1\xcb\x02\x8f\x0e\
+\x1bf\x06\xf9\xda~J\x01~e\xc2^6\xd1S\xa9\
+(\x82\x03\xf5\xac\x8b\xe5\x94\x93M\xdavO\x84\xcf\x12\
+\x02\xb2\x9cr\xea\x01TX\xc1\x0c\xdb|\x92\x05\xf47\
+|,\xa8\xc9\xaf=\xa3\xba\x8e\xb0?\x84\x8d\x9e|\x9d\
+\xf5\x08a\xe1\x1b\xf7\xf2}\x80z&\xde\xe8\xda\xae\x98\
+x\x0e\xfc]}m\xbfS\xf2\x88\x03~\xef\xc1c.\
+%\x0f\x9f\xb0\xfb\x8f <\x06\x82p\x02\x9c\x16\x04\xc8\
+\xe5\x048\x92}\x89\x15\x01\xc9t\xa0\xbf\xd0\x07\xfdw\
+\x10$\x02>\x86\xcf\xf9\xed\xd9s\xde?\xa0E\x80\xf1\
+Na\xa2\xa7\xd0HSi\xc5\x09 \xf7\xf37\xa4\xfd\
+\xf1X\xd3\x9f\x80\x1d,\x18\xd2 \x09D5\x0f\x1b*\
+\xb0\xa2g\x16\xd87\x0c\xc35\xd4z\xbe\xce\x93C\x87\
+\xcd\x22v\xbe1\x8a\xb33{\xc9\xfft\x18d\x93\x05\
+\xef\x1dI\xc9\x94@\x02\x18[\xb6gQE\x0dw\xf0\
+\xdaR\x92e2\xfd{*=6\x8b\x9e\x8b\xc4X\xd8\
+\xaa\xd7\x88\x8d\x03\xa7x^U\x88\x1c\xc9\xd2\x0edk\
+\x82nL\xdbo\xdfS@\xe7\xda\xae\x02\xfd\xc1\xa3\xa7\
+\xec\xe1\xe3\xa7\xec\xd1\x93\xdf\xb8`>\x00\x09\x80R\x08\
+D{\xfc\xf4\x19{\x0e\xa0\xbe\x10\xda\xfe\x87\x04<\x90\
+\x00\xff\x8e\x8f?{\x06\xc0\xff\xf6\x9c=\x81\xe7?~\
+\xf2\x8c\xdd\x81\xf7t\x0a\xd8\xc8\x090\xd5-VG\x00\
+\x1b\xa7H~\x8f:\x0e\x998\x9f:\xae\x1a\xe9\xf7\x13\
+T\x9c\x00z;z\xa8U\xa9\x13\x95.\xa75\xef6\
+8\x14I\x80\xebYT\xca\x01\xdeU\x83\x9d:&A\
+\x97\xa4H\x05~\xd6\xf9\x22\x0e<v\xdcx\x87\xa7\xea\
+J\xc8\xe0\xe9\xfe\x0fx\xba\xa9\xf0\x9e\xab)\x8d\xeaN\
+\x80N\xa1\x0d\x1b#\xa8\x99b\x00\x11\xb4/I?\xfa\
+\xdb\x10z\xce8\x22\xc5\x0c\x10W\x10\xdf\xd6\xbdF$\
+\x09\x8b\xb0xm*o\xfa\xd0\x81~\xbb\x14\xf4\x9bw\
+\x0dM\xbc\x0et\x0e\xfcS\xf6\xe01\x02\xaf\x80\x8e \
+#pO\x01@$\x03>\xc7\x98\x89\xd7\x81\xfe\xe2\x85\
+N\xdb\x9f\xea\x80\x87\xeb\xc15\x1f\xe2\xf5\xe1\x1a\xe8'\
+L\xf3T\x13 B\xde\x22\xd7\x85p\xaaW\xdaR\xf6\
+r\x04\xa8.\x8aA\xb4u\xa9%\x99\x1a\xbc\x99s \
+\x0e\x8d\xc67w^\x1a\xaf\xec\x84\x01\x93m\x0ax\xad\
+\xa4\x0c:z\x18\xb6\x1d\x81\xf0\x0d;mg.J\xd0\
+\x81\x0f&\xff72\xf7\xcbH\xe3gQ\x05m$\x81\
+\xdb\x9d\xd6\xbe\xb6\xf4\xd9\x9a\x93\x19\xb4\xa0\x7f\xb7\xa4\xc7\
+:\xd0s1\xf4\x1aN[\xbd\xd02\xb8\x80\xf8\xf5\x1c\
+33\x0b\xdfo\xce\xa2u\xec\xfc\xa5\xabf\x9bxY\
+\xdb\x11,\x04\xed\xc9o\x00<\x80\x88@*\xa0\xbf \
+\x13\xaf\xd6v\xc5\xf4\x1b\x82\xfeL\x02\x1d\xc8\xf3\xe0\x09\
++\xc1\xf7\x05\xd2\x9d\x00\x7fa\xba\x8a\x00\xd2\x12 \xb6\
+\xaf\xa9f\x18\xbc<\x01D[w\x03\xbaxg\xaab\
+M\xed5n\xf6!|\xf3\xe4}'yc%v\xcb\
+\xc8\xa0\x17\xdd0\x9d\x95\xcb\x87u\x10[\xb1\xb1c\x96\
+o\x02\xf5\x8f\xe5%c\x1c\x14\x81\x95\xb3&m{$\
+\xc0\xfb,&\xad\x9fF\x05\x94\xfe\xf4\x19Z\xd1\xe7\xf9\
+\x9e\xc8\xf95y\xc1_\x91\xd4\xa7\xbf}K\xcf\xf9\x89\
+\x08\xd1\x91\xea\xef\xf8\x1dp\xf2\x87#^\xbfu\xef\x91\
+\x09h\xd1\xf8\x1e\xbf\xdc\x22\xa3\xda.@\x7f\xf8D\xd2\
+\xf6\xdf\x14m\xd7\x81^\x96\xb6K&\xfe\xe9o\xcft\
+\xda\x8e\xd7\xc5\xeb\xe3\xfb\x94\x00\xf0\x08::\x88w\xee\
+=\xe2\xce .#\xd3=\xd7\xeb\x080\x99\x9c@K\
+\xc7\x85\xf7\xa9\xab\xa8'9\xec_\x92\x03\x8f\x04\xa8l\
+\xf6\xdccU\xc7\xaf<\xbf\xe73\xba\x99\xcd\xe8\x06\x0e\
+j\xdc\xaa\xb3#n\x9a\xc0\x10\x0bM?\x86jei\
+\xbb\x9c\x99\xc3\xd8\xff$x\xe2h\xfac\xb7\x1d\xd1U\
+\x0c\xb1\xc3\x08\xc1\xff\xa5\xf3\x80dr\xf0\x5c\xc8t[\
+\x92\x16\xb7&3\xf7\x0d1\xfd3)7\xfe\xa1JD\
+\x97\xf2\xa7\xf4\xdc\xaf\xc9\xa1\xb5\xa0$Lo\xb2\x08\xe8\
+3\xccm\xdeup\x84 \xc1\xe9\xbcb\xaey:m\
+7b\xe2\x15m\x7fQ.\x87\xce\x98\x89\xe7\xda\x8e\x84\
++Q\x80G_\x033\x8b\xe8L\xde\x80%\xe9(8\
+\x8f\x82\x00S\x80\x00\x13h\xfd\xefbi\xb7\xf9\xa5-\
+\x80\x91\x8e_\xbc\x81\x9fA\x98\xd5\x0c\xd6\xca`\x08\xa7\
+2qo\xdf0\x07\xbfSC\xa6\xf9\xe4\xe0\x9boI\
+W\xda\xa4\xb1\xf7\xdd\x9c\xdc\xbb\x10\xdc,\x81\x89\x9a\x9d\
+\x87\xcf\xe9\xc0\x1f\xef\xae\x98\xb3\x0e\x83'\x1c\x82\xf7]\
+D\xe0O\xa6u\xbc3\x15O\xbe\x93&x\xd6VU\
+\xc7\xb4D\x1e;W\x87\xd6\xc7\xfa\x1425'\xbff\
+\x00-k\x8e\xcd\xbb\x0d\x09\x11$\xc06p\xd9\xa1\xd3\
+\xd4\xf6\x17\xc6\x1c\xba\xdf\x8d:t\x1ct=m\x7fl\
+\xa0\xed\xb7\xd0\xff\xb8\x0d\xc0\xdf\x02\x7f\x04s\x15p\x0f\
+1\x82\x10\x04\x98\xe4\xa2$\x82\x869\x06<\xa4\x02\xd3\
+\xe8\x0a\xf9\x00\xa6:~\xc1[nb\xe9\x18\xb0J\xdd\
+\xf1+Z\xbb\xe6,\x8a\xe5N\x1bf\xe4L\x95VK\
+EI\xc3\xe6\xf2\x9e\xbbb\xfeZ\xfb\x80X]\xcb\x18\
+\x9f\xfaa\xebq\x13\xde{\x099j\x08\xfe`\xb2:\
+\xcdTS;k\x1a\x19\xb8T\xd9\xc8N\xa5\xea\xf2@\
+\x07\xbaI_\xd3\x0dkK\xcb\x02\xfa\x16S[t\x1b\
+\xb2\x0a\xac\xdb\xbf\x9d\x96\xc4\xe9i;\x82\xfe\xdb\xf3\x17\
+e;t\xcf\xcbv\xe8\xb4L<\x07\x9d\xb4\xfd:\x00\
+\x7f\x0d\xf3\x0e\x18\x95\x80\xb5\xbc\x0c\x8e\xf2\xa2\xb0\x9d\x9c\
+\x00\xb6\xae\x98\x0f\xe1\xcb\xe4\xbf\xd1j\x91?3\xb4\xdc\
+Q@Y\x1d\xbf\xa2\xf1\xd3X\xc7\xef\x9a\x94\x83<C\
+\xc7;e\x8d\x16]\xf4\x0b/\xe8\xf1\x8b\xb4,\x8ez\
+Q\x9b\xfeF\xcd\xdb\x87\xc2\xfb{\xd2\x96\xef\xa1\xa4\xa1\
+?Ie\xd3\x0f$\xe0\xcdj\x8a\xd0 y\x0d\xfa\xae\
+u\xc8\x5c6\xa2}\x0b\xddh\xa9\x99\x02^\xf5z\xfc\
+\xee\x09\xdb35\x1d\xba?T\xda^\xb6\x89\xd7w\xe8\
+\x14\xe0\x1fJ\xda.\x83^\xa2\x03\xbd\xf8\xea]\x9e3\
+\xc0,\xe2t\xafXf\xe3\x1aF\x89\xb0\xa0?,\xba\
+\x0c\x8a\x81\xcf\xeaD\xe6\xbf|y\x00e\x84z\xc5;\
+~\xa7\x82\xc3\x86m\xd2\x18\xba]\xc2\x0fz\xd3x\xb5\
+Mn\xa88Gm\xd2\xe1\xc9\x07t\xd7\xc2\xf7\xa0m\
+\xde\xa7(y\xe3@\xa1[\x17\xd2\xfc\x06\xaa\x8e\x99\x0a\
+\xd5\xbe\x8dX\xbb\x0f\xc9\xaa|CKL\x17\x22\xc1\xd4\
+\xbe\x13\x9c\x8f\xe3\xe7\xca\xbf|\xc3<\x87\x8e\xac\xc5#\
+3\x1c:\x03\x13\xaf\xd2\xf6b,/C\x84\x84\xc3&\
+p\xed\xb7_\x10%\xc2\xe2\xff\xc6\xfb\xd4\xa8y\x87U\
+\xd4W8\x85\xacd\xf92\x81\xca\x0c|\xfd\x8e_1\
+\xb8\x09\xfb\xd7\x16F\xa5\xb1\x15\xf1{\xb9\xe0^<\xb7\
+\xd5\xfa\xcd\x9e\x0b\xa3\xb7\xf3\xca\x1bnx\xd0\x04]\xa3\
+\x93\x06\xabq\xd8&\x8d\xa4\x91\xaf\x85\x8d\xa2\x8a\xf6w\
+X)u\xca\xf6\xa45\xba\xa1\xa4\xf9\xafdr\x86\x11\
+\xcb\xf7)-\x09?\xd3\x16\xad\x11\xdf\xb7\xec4\x0f\x1d\
+]\xef\x90\x8d/\xe1\xd0\x11\xe8*\x87N\xcb\xc4sm\
+\x07\xd0\x0b\x01t\x04\x1ek\x02\xeb\xb6\x1c\xe0YK\xae\
+ \xa3\x1c\xcf4\xb2h\x1fI\xf9\x10\x17\xb2\x92\xc3\x89\
+\xb4\xe6\xd7\x020,\x00\x02\xe8u\xfc\x8a\xc9\x9a\x8bc\
+\xb6\xf1M\x11\xe9'.\x96\x16a\xa4\x92\xeb\xae#\xe7\
+!\xec\xcb\xe6a\x1f\x96\x5c/\xf0\x82\x8aq\xd0E\xb3\
+$\x0av\xc9b\x11\x06w\xf5\xca\xed\xe2\x8a\xf6\xcf\xc8\
+&\xd3oK\x83\x9f\xda\x90i\xfeS\x864\xab\x22\x1e\
+1\xb4\xb2.\x11\xae9\x11pl\xd7\xe1S\x93\xf0\xf3\
+\x9d\x81\xa8@h\xfbS\xb3\x1d\xba\x87\x9a\xda\xae3\xf1\
+\x98}\xbc\xa6\x98\xf8B\xd2v\x04\xfd\xf8\xd9\x02\x16\x9e\
+\xb4\x97\x0f\xa9\x22\xbf\xe8\x06\x84\xc4q\x14\x12\xcf\xa7\x9e\
+\xc2\x89\xb4Dv-W5\xf0\xcbF?\xe1y8t\
+r\x86~\xc7/\x82\xaf\x80~\x91@/-\xb9*u\
+\xf6\x02\x1e\xb3c\xec\x8e\x9b\x1dO\x80\x17\x8fk\xbe)\
+\xd0E}\x1dS\xadH\x00$\x90\xac\xfd\xe3\xdcB\xf9\
+\x97l\xda\xaeg\x18%z\xac\x88\xd1M\xa5\xd9\xbc\x7f\
+\xda.\x19\xad)fD\xbc6DD[\xdc\xc7\xb0 \
+8I/f\x17\xda^\xa6\x897\xaa\xedwJ\xb5\x1d\
+@?\x97w\x95%\xed8\xc2f\x07\xc6\xe8\x0a^\x08\
+<\x16\xb5\xc8)\xf6\x06\x99GZ/\xf2!\x1d\xa5i\
+\xe6\xe6\xf5\x03\x10\x01\xd09\xd0u\xfcbx\x87f_\
+\xbd\x13\x86\x83~F\x01]4X \xf0r\x9d\x9do\
+~(\xb8N}\xf07\xb8\xa0\x97\xafT\xdan\xf1\xfd\
+u\xb9\x85J\x9b\xf4\x85\xe2\x9blY\xdcn=\x02`\
+\xd2g\xe0\x14\xcfk\xa4\xfd\x93\xe9\x8b\xb5\x92\xa6s\xd7\
+\xfc\xb3w\xc9j\xec\x81\xf8'\x11\x10\x89h\xd5u\xc4\
+\xd4D\x04$\xe7\xd2\xd52\x1d:C\x13o\xe8\xd0a\
+M@h;&wpn\x90\xbd\xb7\xc8~\xfa>\xef\
+l9\xe54e@\xb1\xd8\xe5K\x8e\x9e=-\x8d\x83\
+\xc8Y\x15\xf9\x90\x06\xe5\xea\x08\x22\x02TS\xce\xc5\xe1\
+/l\x84o\xbcp\xcdV\xea\xaa\xb9d\xd0U\xa3\x03\
+\x9d\x03\x7f\x99'p0\x8eGO\x1e\x1d:l\xb2\x10\
+uv\x99\x0c\x1ct*\xb9b\xb7,N\xe3V\xef\x16\
+\xc2\xf7\xee6\xd2\xfe\x00\xed\x90\x1d%\xc5\xb2_\xbc\xce\
+\x89YR\x05\xb4\xa6<\xd0\x02\x09\x89I/\xfc\x9c+\
+b\xb7\x9b\x17\xb3\xab\xb4]m\xe2\xb1[8\xfd\xc8\x05\
+\xbeM\x1ck\xfeQ\x89\x87\x98\xeb\xd2\x0d\x22\xa5\x8b\xd9\
+\xcf\x08\xca\x83\xb8\x93C<\x9er!=(d\xfdI\
+\x1a\x91[G\x9a\x9a^vO \x10\x00S\x83\x98!\
+\xe2\xb5\xfev\x03\xc6\xf5\xc67^\xb39C\xcf\xc4c\
+\x86N\xad\xed\x22|;-\x80\x07\x87\xee\xec\xa5\xd2\x06\
+\x0b4\xf1\xa8\xed\x17H\xdb\x05\xf0\xb8\xc5\x1aK\xae\x09\
+;\xb3T\x1bG\xc3\xc5\x0e\xd9\x08\xaa\xdc\x0d\x22\xd3\xfb\
+\xcd\xeb\xde\x22\xa5J\x7f\xd7\x22\x026\xa1\x04\x94\xd5@\
+[\xcf\xd3\xd3\xfd\xd6\x94\xc3\xa1\x93M\xbc\x02|>(\
+\xc3\xc5\xc2\x9b\xec@V\x1eK\xd9\x95\xcd\x12\xd3\x8eq\
+\x02D\x03\x01\xdc\x96\xeaF\xc5DJI\xb0)\x14\x0d\
+\xf5\xa2\x18\xffgZ\x9e\xbe\x94\xb4\xbef\xb9\xda\xc3\x89\
+\x00x\x1a\x96^\xc7/\xb6R\xa9\xb5]\x80\xae\xa7\xed\
+\xf9W\xf5\xbajr\x8ch{>\xf5\xc7\xcb]5X\
+\xe5\xd3Z\xff)\x9c\xb1\xd6\xc8e\xff\xe3un\x90\xd4\
+\x1akGV`@7\xabi\xb1\xf8YO\x9e/4\
+\xc3\xa1+5\xf1X\x0eF\xd0\xf3\x0a\xe0\xfe\x5c\xba\xc1\
+\xbb\x84\xb0\xdbG\x8f\x00I\x87\x98\x7f\x882,\xa2\xc9\
+\xaf=b\xa4<\x88%\x99\xfb\x16\x14\xe2\xd5'\xa7\xf8\
+#i\xc6p\xb5rYH @\x15\x22\x80\xe8\xf7k\
+\x89o\xbcr\xfd\xceRm\xbf i\xfb\xc5+d\xe2\
+\x8di{)\xe8\x8a\xb6\x1b\xef\xaaQ\xe7\x120\xcf0\
+\xc4\xde\xe7\x0ey\xb5#\xc9\xa9iL_\xf2\xb5\x9f\xcc\
+ad\xb2\x19\x9a\xdb\xee\xbft\x1e\xc0G\xdbl\xd8~\
+\xb8L\x87\xee\x92\x00\x1d\xe4\x02\x00\x9f{\xe9:\xef\x0f\
+\xc46qt\xf6\xb0E\x0c\x09\x90\x94v\x9c\xc5\xa5(\
+\x04\x08\x0aWv\x0d\xb7\xee=r\x03\xdd\x8f1\xa4\x10\
+-I\xeb\x85\xb9\xaf\xa5qZJ\xa5\xf2\x12\x00\xd6\x0b\
+\x8b\x8fi\x9dk=r\xf6\x92GNK\xd7\xeb@7\
+\xa5\xed\xb2C\xa76\xf1\xa6\xbaj\x0eBd\xa1&\x00\
+\xa6\x94\x07\xd9y\x15S\xa5o\xb0d\xfeE,\xfb\xda\
+7HJV\xa0\xa6\xf0\x91\xa8pd\x09\xd1\xc0oK\
+\xa2S\xf5cv=m\xbfi\xa0\xed\xd8\x1a\x8ek\xfe\
+\xb9\x0bp/\xc1\x92\x9e\xc9\xbd\xc2\x09\x80#c\x93h\
+^ '@\x84\x8e\x00q\xd2\x96\xf1N\xaa\xbd\x03b\
+\xba\xf8{\xaa-d\x95^\xca\x02\x0c\x98\xec\xcec\xdd\
+\xd4\x8cl=\x87\xee\xbc\x09\x87N\x98\xf8\xb2\xda\xa4E\
+\x83E\xdc\xf6#\x06\x04\xa0-S\x99\xaai\xdc\xf5\xa5\
+q\xec\x95\xdf\x10\x01\xe4\xb6\xf8\x06\xa4\x85\xfd\x879\xf8\
+_v[\x91\xa0\xe7\xd0\x19\x98x\x95\xb6\x9f\x05\xe0\x11\
+tl\x0d\xc3\x0ea\xdc)\x84\xbb\x85\xc5\xc8X>0\
+2)S\x22\x80U\x1c)\xc40\x89\x00\x0d)\xc3'\
+\x9f\x99TSE\x04\xf3\xee\x95\xda\x07\xc0$B\x93\xb6\
+=,q\xf2\xf6\x04\x8f`\xb67\xeb\xbc\x81C\x97g\
+J\xdb\x8d\xb6I\xebw\xd5`\xdd@\x93\x00\xca0f\
+\x1b\xedR\xe6\x9b\xd9\x1eM$0l\x8a\x9d\xec\x9e\x8e\
+Y9Cm\xbf\xce\xb5]\x01\xfd\x9a\x04\xfa\x15\xde\x15\
+\x8c\xbb\x83p\x97\xf0\x89\xb3E\xbc\x09T\x84~\xf2\xc4\
+\xd0ED\x00,B\x0ds\xf0\xbb\x02\xa1\xf1n\x90\xf5\
+\xb8)\xa7\xdd\x80\xf1=\xa5\x0d$\xea\x12x\xadrm\
+\x0fSG\x01\xc4\xb0\xaem\xfaX\xb9b\xbf:~\xc1\
+\xd0\xc4=,\xfdx\xaeI\x87\xae\xcc6iUW\x8d\
+_d\x9a&\x01z\x8f\x9b\x93A\xf1\xadzBV\xd5\
+7L\x80\xaaRS,~\xae\xae\xfd&\xb8\xf0\xcd\x1b\
+\x06&\xde\x84\xb6\x9f\x04\xd0\xb1\x93\xe78\xf5\x05\xa2\xf9\
+\xc7\xdc\xbezdlH\xec~\xe6\xbc8\x81\xcd\x0e\x88\
+e\xb6^\x11l\xac\xf3*\x83\x16wP\xd2\xd3\xb0\x0c\
+e`\x85\x16\x9c\xf7\xfe\xd2\xf6\xb0:\xaa\x03\xb4*\x97\
+\x95\x08\xd2\xcb\x03\xd0p\xa2A\x8d[v\x9e\x81\xe1\x8e\
+\xfc\xa6\xb3\x83b\x98O\xe8&\x16\xb1i\x1f\xdb\x07\xd6\
+\xe1\xd4\x85\xe2\x0a\xb5I\xfb\xad1B\x80\xf1s\xd2)\
+\xb3\xd5\x99F\xa4|\xf6\xa6'di\xf8\x01\xe8\x98v\
+\xea7\xd1\x85\xd7J\xb4M\xfc\x95R\xd0u\xda.\x83\
+^\xc0M\xffa\x88\x002\x8f\xe7\x1b\x8c\x8c\x8d\x88?\
+\xc0\xdb\xbf\x97G\xeda\x8b\xc2w\xb2\x80\xe0ml\xfe\
+\xb2-ln\xc0\x06\xe6\xe8\xbd\x8e\xd9yF1k\xd7\
+\x10=b !\xfaX\xcf\x1dG\xcb\xd4g\xd2\x01Z\
+\xc6I\xa0\x95\x09$\xd3\xdb\x85\x0a\x0bv?\xb5\xef\x13\
+\xd4~\xe0\xf8M=\xc7\xcc<6\xc4\xde\xfb.\xf6\xe0\
+\x8b7\x8d\xda\x9c^\xae6i\xd1U\xe3\xaf14\x02\
+\xb3\x804$\xf1m&@]R\x92\x0e\xfd&\xba\xa6\
+\xe0=\x90\x1d:\xa1\xedj\x13\x9fu\xaaP\x01\x1d\xb4\
+\xfd0\x00\x8f\xa1\xdf\xa1\xe3\x17\xf9\x06\x11\xcc\x03p\x02\
+\xd0\xc4PN\x80\x84R\x02,&\x02\xf8\xacHe\x9e\
+KR\x98kP2\xdf\x1c2\x9b\xf6\x06\xd8{\xc4\xb2\
+\x89.\x91\xbc\x1d\x0c?\xcf\x80\xc9\x1e^\xd2\x99\x03\x1f\
+\xe9\x93@U\x0d\xd4\xaa\x05\x90\xe7\xdd\x5c\xaa\x87O\xa2\
+\xbc\xbc'U\x9e\xb0J\xb7\x06\xdf,:%\xbdBm\
+\xd2XQ\xd4\x0a\x03\x87N\xf7\xbd\xfe\x16/\x01\x22\x1f\
+\x807\xb7}\xff\x89\xae\x9b\xf1\x1e\xe8\x9b\xf8b\xc5\xc4\
+\x9f\xd17\xf1\xb2\xb6\xe3\x9e\x00<5\x04\x81\xc7i!\
+\x98\x05\xc4M\x22;3\xce\xe9\xc6\xc6\xc5&\x1ff\xe1\
+\xf1\x19l\x85\x8e\x00\xdb9\x01\xbc\x88\x00N\xfe\x1b9\
+\x01f\xe0\xde\x00j\x0c\x9d\xec\xb2\x96\x8ds\x0a\xa1\x91\
+\xf3n\xde\xd4\xfb\xf8\x854iD\xbb!D\xa3\x1a(\
+F\xb96'M\x1c@iY[\x89\x08|<\xfa\xda\
+-\x19\x15j\x93\x0e\xd0 \x80\x94\x08\xd2\xeag\xab\xf6\
+\xb6\x11`\xb0\xbd\xf7a\xdcjf\xa8\xed\xb2\x897\xd4\
+v\x01\xfa\xfe\xc3\xb9|s\x086w\xec9t\x9e\xed\
+>x\x9eO\x0eC\x22`\xbb\xd7\xf6\xfdg\xd8\xb6}\
+gx\x82\x08}\x03$\xc4\xd2\x88]\xdc\x0a\xe0\x9e\x00\
+A\x00\xb91\x14;\x83\xc7:\xadV\x0e\x9e\xe8\xd0\xb7\
+\xab4p\x82*\xa8\x16U4\x9bB5\xfa\x01\xeaQ\
+\xb8\xd1\x94\xe2\xf1\xaeD\x84\xd1\x94\x95r\x1e2\xcd\xe7\
+v@\xc4f\xf3\xda\xa4\x9f\xea\xb7I/\x8f\xdf\xa31\
+C0\x9cN\xff\x1a\xeeCa\xa08\x93\xe7\xc379\
+&\xcd\x18\x01pX\xb4\xd3\xe28\x03\x87\xee\x88\xce\xc4\
+\xe7K\xa0\xe7)\xa0\xa3\xb6\x1f\x16\xa0\xe7\x18\x82\x0e\xb2\
+\x8d\x03\x7f\x9a\xcf\x10\xc4Q\xb2\xb8<`\x9e\x00\x93E\
+\x9bw\x9e\xe4\x84\xc0\xa5\x01\x97\x81\x19\x0b\x12\xf4\x1aC\
+\xb13x\x82\x93h\xa7\xf3\x8c\x97z(\xa8\x81\xc6\xa2\
+\x9a1\x02\xa8;\x82j\xd3z\xf7%}\xe1\x9f\x88\x08\
+=hY\xb0Es\xed\xb5:\xb1Bm\xd2\xd8:\xae\
+5:\x0e?8\xf8\x1a)T\x07hM\x1f\xfe\x8d\x0e\
+J4\xe6\x03\xe0g\x0dZ\xb3\xd5\xc0\xa1\xe3&\xde\x98\
+\xb6\x03\xe8{\x0e\x1a\xd7v\x05\xf4\xd3|\x884\x86\x86\
+\x02t\xdc\x04\x82\xc5\x22t\x141_\x80$\xc0\xa2\x11\
+Z\x015\x01\x84\x15\x181+\xe8&Yp\xa9\x94n\
+\xf1\x0f\xf4\xf9p\xe9/\xabEJ\x9e\xfd\xfb)i\xe2\
+\xf7\x94\x04\xc18t\x14\x98\xc0\xbcyKbM\xee\x84\
+1\xd6&\x8d\x872j\xb5\x96qG\xd0\xde\xfb\x229\
+\xa0\x1d\xe8=?}\x93\xa3R\xb5\xa2\x80\x0e\x83l\xf8\
+\x98\x9c5\x1b\xd35L|^)\xe8\xa6\xb4}\xbf\xa2\
+\xedi\xa0\xed\xb8\xf6+\xa0\x9f\xd2\x07\x1d\xfc\x01t\x0e\
+\x11\xf4$\x00=1\xf5\x18\xdb\xb05\x8b\x0f\x97F\x87\
+q\xd5\xda}\x0a\x01\xdc\xf5\x09 m\x10\x11\xe5t*\
+\xa8Y\xd4\x00\x02T\xd5$\x80\x89\xbd\x00\xa29\xf4+\
+r\xcc\x10\x98\xa1bchE\xda\xa4\xb1r\xa6E\x00\
+\xd1\x0a\xfeK\xe7\x01\xb3\xc9\x09\xfdIU\x0a\xae\xf46\
+\xe4\x01\xfaOr\x0d\xc5\xcf\xb9=\xfd\xb4\x81C\xa7h\
+{N\xa9\xb6\x1f\x00\xe03\x10\xf8\xb3\x1a\xdaN&^\
+O\xdbO\x94j{\x9a\xa2\xed\x1b\x00x\x01:\xfa\x03\
+X4\x8a\x05\xc1M\xa2\xb8\x14\xe8\x08\xe0l@\x80\x11\
+R\x7f\xe0g\x18\xee\x9b$\x80\x11K \x0ea\xfe'\
+m\xa4h\xd7q\xc8$/\x1c\xf3\x8eoR|\xfdN\
+\x85\xda\xa4\xf1\xc0'c\xcb@_\x1b\xa7\x1d\xb4\x9f\xaf\
+\xc5\x9b\x9e\x97\xab\x95\x09\x1c\xe6\x18p\x02\xcf\xf7\xd14\
+\xf1&\x1c:}m\xd70\xf1\xa4\xed\xfa\xa0g\xb1\xf5\
+\x00<\x16\x8a8\xf0\x00\xfa\xbaM\x87\xf9\x01\x13\x986\
+\xf6[\x95\xa6\x10\xc0u\x9d\x8e\x00\xe3\x9cB\xf9\xe9&\
+\x14Qu+\x8d\xa8,ja\xde\xc7\x1c\x02TQ5\
+I\xe2\xda\xd7\x00G\x90\x0cs\xf0\xdb+\xf6\x05`\x07\
+/f\x06+\xd2&\xbd.\xed\xb0\xa6\x15\xc0\xa6P\xcc\
+B\xfe\xd0\xba\xdbx*\xbc4\x22\xd3\xfb\xa6*\x82z\
+\xb5\x80\xb6}G\x0d\xe4C2\xc3R\xccr\xe8\xd4&\
+^q\xe8Njk;\x9a\xf8\xd4,Cm\x17\xa0o\
+\xca\xe4y\x02,\x18\xa1\x0f\xb0f\xc3A\xb6|\xcd\x1e\
+>*F&\xc0\x18'\x9eS)\xa0\xe6\x91\x1e\xa5\x96\
+\x94\x13\xa0:f\x80?o\xf8C%s;d\xebv\
+\xb6\x9c\xd2\x1e\xe7\xd6\x8c\x9a\xb7\x8c'\x81f\x05\xc5\xb2\
+\xed\x87\xcep\xc7\xcf\xec}o\xaa6i\xac&j\x11\
+@\xb4\x85c\xaaU\x0a\x07\xd5g\xf4\xbe\xce\x9e\x00\xdd\
+\x8cD$\xe3 \xbb\xf91\xf8\xf9Rv\x9fT9t\
+g+\xec\xd0\x19\x98\xf8\x94R\x13\x1f\x03\xc0\xaf\xe5\xda\
+~\x887\x8bD%\x1e\xe4\xc0G&\x1c\xe0\x19\xc3\xa5\
+\x91\xbb\xf4\x08 v\x08w\x19\xce\xb7\x88\x8d\xa7-t\
+j\x02T25\x0d\xa4\xaa\xbc\x0fp\xe8t?_\xbc\
+\xe0$\xcfP\xb6:~'\xef\x8b\x7fU\xfb\xde<\x8c\
+\xcc\x12\x16V\xa0y\xb7\xc1\xb6\xd4\xf6\xf4\x9d\xca\x0aT\
+~Mma\xa2AT\x98\xfffVs\x96<\x98\x1d\
+\xb8\xee\xa5\x1c:\x01:w\xe8\xb6\x18\xd1\xf6\x8d\x86\xda\
+\xceA\x07\xc1\x9c@\xd8\xfa\x0c\x16\x1a\x97\xce\xe7\x07\x09\
+\x02Lr\x8e\xd6\xda\x22\xd6\xb9t\x8b\x98\xc5\x07F\x97\
+\x00\x95\xb9\xab\xdd\xb6\xdf\xe8Fx\xca\x07^\x10\x81/\
+y\xf8\xd8\xe4\xd6f\xa3m\xd2\x8f\x8c\xb7I\xef8t\
+\xd6\xe84q\xe5`\xa6\x80\x02\xb2\x02\xa2\xcf\xfd\xa3\xd7\
+\xd5\x1a\xa6\xd1\x17\xf8\x0d\xc4\xd6+x\x02,\xf9\xe0K\
+8tZ&^h\xbb\x06\xe8:m\xcf`\xe1\x00z\
+\x18\x80\x8e\xc0c\xc1\x08\xd3\xc5s\xfd\x129\x01&\xbb\
+D\x8b\xcd\x22\xea-b\xbf\x96n\x11\xb3\xa8\xa9\xe9\x04\
+\xaa\xf2\x00<%\x8c\x95&\xbc`p\xc2N3\xf7\xbd\
+U\xacMz\xce\xd2DM\x12\x88\xc3%\xc0!\x5cK\
+\xbe\x80\xd8\xe9R\xfb\xcf^\x0a\xb4:\x83!2\xf9\x15\
+3l3\x17\xc6\x94\x82n\xd2\xa1;\xae\xed\xd0\xa5\x18\
+w\xe8\x14\xe0\xf5M<\x07\x9d\xb4]\x80\xbe:f\x1f\
+[\x05\xb20d;\x9b\xea\x01\xf7\xca%\xd4\xcc-b\
+\x16\xefi\xe6\x01\x88\x00\xf2@\xe8\xaf,g,\xdc\x86\
+f\x1f\xd7k\x01\xfc\x8b\x97\xdc\xf7\xa6\xd5&}\xf0D\
+\x9e\xd1i\xe2\xb8\x14\xe0\x17\xeb<\xcc\xd6\x85\xe2\xd9o\
+i)\xf8\xd3\xc6\xa8\x1b\x19\x88\xf1\xdd\xf0\x19\x81Gx\
+\x1bX\xeaQ\x03\x13o\xd4\xa1\xdbZ>\x87Nm\xe2\
+\xb9\xb6\xc7\xaa\x80_\xbb\x97\xad\x8c\xde\xcb\x02C\xb7\xf1\
+\xc1\x91\xe5\xdb\x22fQ\x1dk?\xc6\x08PUrv\
+\xbe\x835\xf8~p\xc2.\xa3\x0e\x1d7\xf1O*\xb0\
+\xb5Y\xd7CwW\xd7&\x1d\x18\xbd\xc3\xe8\x99\x02\x18\
+mX\xcd]\xf6\x9f\xed\x07ZO!67Tm\x0c\
+\xad\xf2*}\x02\xc9\x12\xd6\xa4\xdaz\x83\x01\x93\xdd\xe7\
+\xe3\x8d\xf6\x0bM)\xbfC\xb7\xd9\xd0\xa1C\xd01\x81\
+\x84!$Z\x92\xd0\xf5\xfb\x98\xcf\xea\xcd\xbc\x17Pm\
+\xe2\x15\xd0\xf7\xb1\x95\x00\xfc\x0a\x00\x1e\xd3\xc0.\x8b7\
+\xf0Y\x82\x1cxe\x8bX\x84y[\xc4,\xaa\x9aJ\
+\x05\xcb-\xd0M9\xdbwd\x9a\xed\xd0\xdd-\xd7\xbe\
+7\xfd6\xe9s\x17\xaf\xb1i\x01qe\x91\xe0\xff\xb4\
+\x1fd3\x99\xbe\xd4\xd7\x92%x\xefU8\x86\x1aG\
+\xe2\xa0%\xfc\xb2\xeb\x08\xfbah\xfa\xed\xbd#_\x99\
+C\xb7yg6O!c\x02\x09s\x07\xb3\x16\xc6\xe8\
+5{L\xf6\x0ag\xd3}\xa3\x99\xd3\xa2\x04\xb6`\xe5\
+f\xe6\xbbz\x0b\x9b\xbf\x22\x99\x0f\x8f\xb4qS*~\
+\x83\xed\xbd\xef\x01\xf0k\xa8m\xdc\xcc-b\x1a\xc5 \
+\xaa\x06\xca\xc3 1\xe3g!\xb6C\x9b\xeb\xd0\xa9\xb5\
+\xdd`'L\x19m\xd2\xbb\x0f\x9f7y\xba\x88 \x01\
+\xf8\x04\x81\xb4s\xf7\x1bU\xe3C\x85\xc7\xa5\xab\xc0\x17\
+\x89\xaf/`=m\x85\xa1\xaf\xb5\xebj\xee\xbc\x99\x17\
+\xb3\x9bv\xe8\xd0\xc4#\xf0|`$\xfc\x8e\xdd\x92I\
+\x1bb\xa6\x15\xb4\xe9c\x95\xd5\xddjz\xee\x00[\x8f\
+[r\xdf\x85,\xb8s\xaaU\xcf\xe1\x9b\x09\xf8\x05\xe4\
+\xed\x9b\xb9E\xcct9X\x8c\x83\xe5\x8d\x8fx\xb3#\
+7\xed\xe3\xc0?0{\xdf[\xc9K\xb5I'\xee<\
+V&\x09\xf0&\x0c\xb1\xf7\xd9\xdc\xacc\xdf\xceR\x8b\
+\xf4'\x1a-\xd2UL\xcd\x0cP\x9dv*g=?\
+\xe6\xe0w\x1d\xd4\x12\xe7\xef\x8e\x07\xf0#\x133L:\
+t\xc2\xc4\x9b\xe3\xd0\xe1k\xe5\x91\xb1\x98Q\x04\xff\x02\
+\x0f\x8c\xc6\x16\xf0\x18\xda\x09\x84s\x0fq=_\xd9\xaa\
+\xd7\x88M(\x16]\x06\xc6\x12\xe8~T\x92\x9fC\xc0\
+\x8fy\xa9-b\x1a\x04\xe0\xdd\xc1\xc3\x1c\xfc\xb3q\xf7\
+\x8bnk\xb3\xa4\xedfom\xae@\x9bt\xfc\xf6,\
+\x93\xa7\x8e\x89\xbe\x01\x9c\xab\x8bM\x92T\xed\x92;e\
+k\xab\xda\xa5\xabi\x10B}\xa6\xb1\x98\x84\xc2k\x1e\
+\xdd\xac\xa6\x0f\x01\xcd\xff\x03\xc1\x8f\xd8\x90\xfeJ\x1c\xba\
+Pr\xe8\xb0G@\x8c\x8c\x0d^\xbf\x9b\x7f\x97\x16\xdd\
+\x87b/d\x944\xf7\xd0\x87@v'\xa7\xce\x95<\
+\xfb\xd9\x14\xdeM\xa2\x1e\x8dA\x94\xe8\xa9\xf8\x161\x8d\
+%\x80\x9f\xec-\xe6\x01o\xdcu\xd4\xe4\xac\x1a\xe1\xd0\
+\xa1\x89?\x95S\xcc\xb2\xcf\x17\xbdT\x9b4v\xd5\xc4\
+\xa5\x1d1I\x02\xcc\x16b\xe5\x90N\x1d;\xdfc\xf4\
+\x0c[j!kH7\xe0S\xd2dA\x86\x9ad\x1d\
+\xde#\x11g\x1a\x7f@\xdf\xf9\x13\xf2} \xd6\xf7\xf0\
+@\xb3\x8f\xe0\x87'\xec7\xcb\xa1\x8bJ4\x12\xbe\xa9\
+\x1c:\xbc\x0e\x12_\x8c\x8cu[\xbeA>A\x04\x0f\
+\x8f\xf2'\xb0g\x90vO\xa2\x89_\xe3)\xaf?\x92\
+\xf6\x05\xf6%'\xaf\x0deJ\xbf{\xa9-bD\x00\
+\x83\xd6\xe7\xa1\xd3|\xcf\xe1\x07\xdc\xba\xff\x84Qm\xbf\
+Pp\x9d\xc5\xa5\x1eb\xb3\x83\xd6\xf1/\xe3\x1d\xb2\xe9\
+\xa5\xdb\xa4Q;6l?\xc6'\x8f\x18#\x81\xado\
+\x0c\x9b4\x7f\x0d\x1bK\xcb\x02F-\x83\xec\xe6/F\
+\xa7\x8d\xca\xc8_\xd3w\xa9GQ\xc3'\xa4\x19u\xa4\
+iah5\xbe\xc2C\x17\x86L\xf3\x09\x00\x93\xcf\xcf\
+/t\xf0\x8b\x06\x903\x09\xf8#&\x1c:\x15\xe8\xf1\
+r\xcc\x9e\xaex\xf1\xeb\xf6\xe9\xc27\xfc\xfe\xa8\x04\xf2\
+\xc8\xd8\xf9\xab6\xea\xd6\xf6\xef[t\xf4\xa7\x0d\xa0\xd6\
+\xe4\xc9\x0f$\xb0{\x91\x89\xefD\x89\x9d\xe6d\xea\xbf\
+\x95\x80\xffP\xb5E\xcc|_\x88\xa2\x00\x83y\xc0?\
+\xb4\xeej\x0d\xeb\xd3\x1d\xfc\x80K\xd6\xa6\xb1\x8cc9\
+\xb0v\xdf`\xa7r\x8bY\xf2\xee,\xde!,\x9c\x93\
+\xa1\xd3\xfd\x9e\xf7\x9f\xec\xc6\xc7\xc9\xec<xZ\xdf\xc4\
+\x97\xb3MZ4X\xec<p\x8e\xb9\xadJ6J\x00\
+\x1c*\xe5\x10\x18\xcf\xec\xc0c\xb6q\x0f\xd1}\x16 \
+C\xc9\x88YA\x07q\x9a\x19\x90\xc2\xa5\x8f\x8d\xd3\x98\
+\xbe\x13\x9cG\xe3\xc8\x1b\x94\x81\xb6\x9evx\xda\x06\x9e\
+{(F\xe0\xa0\xe0\x89\xe0\x8b\xd6l+\x97C\x17.\
+g\xe8\x8c\xc4\xec+\xa2\xf7\xf0\xb20\xfaA\x0a\x01\xae\
+(\x048\xae\xcc\x0c^\x1d\xb7[\x1cI\x7f\xff\xe7\x8e\
+\xfd\xdc\xa8\x8c\xdb\x87\x00oC\x807#+\xf7\x1d\xad\
+\xf1_\x10\xb1?\xd4\xd8\x1bX>GX\xca\x03\xd4 \
+\x0d\x11\xf3\x80\xf1CX\xf7\xb1\x9e\xbb\x07\xcb\x8bj\x8f\
+\x14<\xd5?z\x8f\x9b\x93G\xe3[\xd7\x81\xc4\xa1\xf7\
+:\xd5;\xe2\xa5\xda\xa4\xd5=t!\x1b\xf6\x1bX\x03\
+$\x00\xfe\xcd!p=\x9b\x05q1\x1e%?w\xe9\
+\x066#0\x96\xd9\xf9\xaca\x13<B\xcb\x1c\x1f\x8f\
+\x89.\xe7e\xf1lI\xccv\xb6n+h\xfc\xd6\xa3\
+z&>F\x14a\xca\x99\xa1[)\x80\x87\x98\x1d\xab\
+u\xcb\xd6\xec\xe6\xce\xa3X\x0aO\xe7J\x048\x9c\xcb\
+\x0bI\x91\x89\xe9\x0c\xa3\x0d\xac\x81\xb4\xe93\xca\x89\x1a\
+o\xdaHk\xbb\x00]^\xdej\xbe\x14\xf0\x1a\x99@\
+Q\xf8\xf8\x82\xd8\xd6\x9e\x1c\x8d\x09\xdf\xb7\xe8\xe4\x06\x1f\
+,\x1aw\xeft\xb3\x9a\xb6\x9f\xbc\xd2\xa54\xb1b1\
+\xfd{\x05N\xb1\xe0)\xe4\xf8]\x15n\x93\xd6\xea\xaa\
+\xd9\x9e~\x86-\x8d\xd9\xcd\xa6\xfa)D\xb0\xf5)%\
+\xc0\xcc\xc5\x09\x9c\x00\xce+71\xf7\xd5\x9b\x99W\xe8\
+\x16\xe6\x13\x91\xca\x9bO\x17\x84\xa5p\xf1\x8d\xd8\xc2\x02\
+\xd6\xa4\xb2\xc0\xe84\xb6<n\x17[\x9b\x9a\xc9\xe2\xb6\
+\x1d\xe1N\xe7z\x04\xbe\x9c\x0e\x1d\x9a\xf8\x90u\x1a\xda\
+\x8e\xa0G)\xa0/\x8d\xdc\xcd\x96D\xecb\x8b\xc3w\
+\xf1\xfe~$\x0d\xde\x0bT\x0a\xb4zH\xf6\xfd\x9c\x00\
+\xe7xvqMR\x06\x9b\xba Rl\x92YF\xe6\
+\xbe\x09-g\xe2L\xa0Z\xd2,D\xb3\xa7\xa3U\xa4\
+\xf8\xd1\x80\xd8\xd7\x81\x1aB\xc7P\x8aq\x06\xc5\x9e\xf3\
+H\xe6\x90\xcc#\x8f\xd5\xa7\x8f\xf5\xbc3\xbcd\xba\xe7\
+D\x85\xda\xa45\xbbj\xa4\x92k\x088g\x9e\xc1)\
+*\x02$2\xe7\x15\xfa\x04\xc0\xf6\xf3\xa0\x98\x1dlI\
+\xec.>\xe0*8q?\x0b\xdb\x94\xc1\xb7\xa6\xc5l\
+9,i\xbb\x0at3\x1c:\xfd\x0c])\xe8\xcb\x22\
+w\xf3\x12\xad\x02\xfcN>\xcf/(t\x07\x0b\x04\xc1\
+\xdc=\xfe\x0d\xbf\x1f\xde\x13\x99\x00XL\xc2<\x03\xfa\
+\x1e\xd3}\xa3(\xdc\xf5N\xa1\x84\xce\xb7D\x80\x0f_\
+\xf9\xc9`&\x86\x22\xd4%\xe65\xa50\xa3\x079%\
+\xc3)\x04\x19M\xbf\x85\x8c\xa1L\x94#83\xbe\xb0\
+\xc6>\xb4q\x0f\xe6\xe7\xe3\x94\xabM\xba\x9c]5\xd1\
+\x9b\x0e\xb1e\xebv3\xff\xc8m\xcc/\x22\x8dy\x87\
+m\xd5#\xc0\x8a\xf5{\xd8\xaa\xf8},b\xe3\x01\x16\
+\x05\xcfE\xc0\xcb\xef\xd0\x95\x82n\xa0\xedk\xd4\xdaN\
+\xa0\x87)\xa0\x07\x02\xe8\x0b\x83\xb7\xf3\xcd\x1dx\xfc\x0b\
+v\xf0\xf8\xaeL\xe3\xe9d\xbc\x17j\x02`\xd4\x81\xcb\
+\xcf\x1cX\xca\x94\x8d\x1e\xee\xab\x09\x83\xafhy\xae\xf9\
+\xa7\x95\xc4\xa5\xfe7\xb9\x13H4\x84\xfeL\x89\x86\x0e\
+Tc\xeeB\xbf\xc5\xbf\xbbK\xad\xe3\xd3\xc4\x98U<\
+\x22\xcdx\x9bt\xeeK\xb7I\x9b\xdfUc\x9eC\x17\
+f\x86C\xa76\xf1\x06\xda\x8e\xa0\x87\xa8@\xe7\xc0\xa7\
+\xf2\x0d\x1eX\xc3_\xb0l+\x7f/\xbc\x0f\xf8\x9d\x91\
+\xd4\x98b\xc6\xcf\x8d\xe4\xc4\xcf\xe4\xe0\xab\x94x\xdb\xf4\
+\xb6\x1aB\x18\xfc\xf9\xd5PUfL\x8cR\xfd\x8c\x88\
+\xf0\x0d}\x90\x1f\xc8G\x10\xd2\x94LU;\x0a[\xc6\
+u\x19n\xb7\x89\xcf\x1b\x82\xb5\xf7u\xb4I\x9b\xddU\
+c\xd4\xa13]\x84Q\xb4\xdd\x88\x89\x0f+5\xf1\x5c\
+\xdbW\xebk;\x07}\x05\x80\x0e\xc0\xe3\x1e\xbf\xf9K\
+\xb70\xaf\xa5)|\x93\x07^\x07\xbf\xab\xd8\x15$\x08\
+\x80\x9f\x0fI\x87E\x9f\xa1\xd3}\xd3\xa9?R\xea\xf1\
+\xff\x13\xdb\xe34:\x83?PM\xdb\x16'W~N\
+\xf2%\xadSh%:\x83\xb3\xe8\xcc\xe7\x07\x07\xc5\xbe\
+\xd66\xe9\x8av\xd5\x94:t\xfb\xccv\xe8\x16\x01\xe8\
+A&L\xbc\x8fJ\xdb\x11x/\x00\x1eA\xc7\x13\xc0\
+<\x16of\xee\x8b63\xb7\xa0d\xfe\x1a\xfc\x9e:\
+\x02$+\x04\xc0\xcf\x86\x07IaZ\xde\xb0\xc7\xffO\
+n\x8f\xd3\x18\xa5*O\xdb~\x9fHQKJ\xa1\x22\
+\x09~l\xda\xaeW\x1f,\xdf:\xf8E\x01\xc0g_\
+{\x9b\xb4\xe9\xae\x9a\xf29tK\xcbp\xe8\x04\xe8\xfe\
+\x00\xa0\x9f\xda\xc4//\x05\x1d\xf7\xf4)\xc0\x97\x82\x8e\
+{\xfc\xf0\x140\x97\x85\x9b\x98s\xc0F\xfez$\xf9\
+\x06\x15\x01\xb0\x22\xa8\xdd\xe3\xff\x9a\x86fi\x14MD\
+\x0e\xbd\xba\xbam\xfc\x97\xce\x03\xdb\x8e\x9c\xbd\xf8\xaa\xb5\
+[0K\x82\xf0\xaaL\x87n\xef\xabo\x93.\x8fC\
+\xb7\xca\xa8C\xb7\xab\x5c\x0e\x9db\xe2S9\xe8\x5c\xdb\
+%\x13\xaf\x03}Q\xb2\x02\xbc\x00}\xe1F\xbe\xc7\xcf\
+\xc9?\x89\xf7\xf6ck\x17Z&\xfc\x9e\xb1\xda\x04P\
+\xf5\xf8\xbf\x81]\xd3\xd2\x99\xf5\x95\xa5\xd6\xf1\x1a\xe4'\
+\xd4\x1f\xe6\xe0\xc7\x87(\xaeIJ\x7fcm\xd2\x91\x09\
+/\xe7\xd0-\xae\x80C\x87\xaf\x93M\xbc\xe7bCm\
+\xc7C\x1f\x9dI\xdb\x11x\x05\xf4$6\xc77\x91\x0b\
+n\xf3\xc2]\xc0\x82\x00Hb$\x80s)\x01T=\
+\xfeop\xd3\xacj\x82\x162\xf13q\xac\xbc\xe7\xca\
+\xa4W\xdf&m\xa4\x08\x13\x9dX1\x87n\xb9)\x87\
+N\xcf\xc4\xab\x1d\xbaT\x03\x87.\x19\xc8\xbb$&\x8d\
+M\xf7^\xab\xa7\xed\xae\x1a\xda\x8e\xa0\xcf\xf3S\xb4]\
+\x80\x8eg\x00\xce\xf2N`3\x17$p\xab\xa1\x10\xe0\
+\x08\xff^H\xde\xc9\x9e\xe1\xe2\x18\x18U\x8f\xbf<\x05\
+\xfc5\x93@\xe3$\xb1\xaf ^\xf5\xe2\xd5\xc3\xed\xc7\
+\x14\x87n\xdfkj\x936R\x841\xcf\xa1\xdbi\xb6\
+C\xe7\xadr\xe8\x90\x04AkR\xd9D\x8f\xd2\x1a\x84\
+\xadg$\x07[\xd1\xf6\x8d\x8a\xb6\xfb\xebk\xfbl\x01\
+\xbc\xf7\x066\x13\x80\xc7\x1d\xbe\xb8\xcd\x1b\x87= \x81\
+\xd0\xea\xc5\xd2\xc4\xd0\xc0\xf04~\xdd\xee\xa3\x1cv\xd2\
+)&\xdd\xdf\x86\xedr\x9aC\x14\x07O]\xc0O\x0d\
+\xabH\x9bt\xc4\x86\x03\x5c\xbb_E\x9b\xb4N\xdb5\
+L\xfc\xd2\x88\xb2\x1d:?3\x1c\xba\xb8-G\xd8\x89\
+\xf3E|t\xbb\xe5\x8c\x85\xff\xf5C\xeb\xae\x19\x9d\x86\
+N\xbe\x80\xdf\xdf\xda5\x98\xcd\xf5O\xd4\x81\xae\xa7\xed\
+\x04\xfaL\x09t\x07\xaf\xf5\x5cp\x93'\x92M\x0c\x8c\
+\x5c\xb1v7\x0f\x01-\x95\x1e\x7f1:WLN\x91\
+\x8e\x81y\xb3\x04x\x9f\x1c\x92\xc6\x83\xec\xbc\xf8\xf4\xcc\
+\xf2\xb6I\xc7\x00\xd0v\xbe\xeb\xd8\x14\x10\xbf\xb0\xd4\x97\
+j\x93^Y\x11\x87n\xb5)\x87N?fGBa\
+\x173NM\xbbX|\x93\x05Eo\xc5\xd9<\xff\x0f\
+\xbe?\xb6h%\xb5\x1fd}\x02\x1b5\xf1h\xf7\x19\
+\xde\xeb9\xe8\xb3%\x13\x8f\xda\x8e\xa0\xe3\xc9\xdf\x02t\
+<\xfc\x11\x05{\xfb\x91\xe4x\x7f\x16\x86\xa72\xecG\
+\xb0Rz\xfc\xc3h8\xf4\x10\xaa\x0d|\xa7\x7f\x0c\xcc\
+\x9b#@52C\xe8\x904\xc51fH\x80\xf2\xb4\
+I\xaf\x05\x0d\x9f\x11\x94\xa04yx*[\x9a&z\
+\x842\xbf\x90-\xe5n\x93\xd64\xf1\xe68t+\x0d\
+3tZ1\xfb\x8e\x83gY\xf6\x85b>%\x15\xb7\
+\xb5!\x01R3N*\x99\xba\xbe\xa3p\xbea4\xce\
+\xf6\xc5\x13\xce\x90\x04\xb8?o\x9a\xd7:=\x13/@\
+\xc7\xf3\xfe\x14\xd0\x15\xe0q\x7f?\xbeg\x04V=\xbd\
+#E\x1d\xe0.\x84\xd4\xa1Tw\x19G\xd5A\x8b7\
+\xbdYV\xed\x00\x8a.\xe2\x9fz\x8cv\xf4\xe6cf\
+\xd7\xed2\xdb\xa1sZ\xb6Q\x0f|\x1c\x8f\x8e\xc2\xcf\
+\xf3u\x0f\xe1'icC\xc5\xabu\xe8\x8c\x9b\xf8\xf9\
+&b\xf6-\xfbNq\x02\xe0\xf0\xcc\x1c~\xda\xf8M\
+>*o\x9ao$\x1b\xa0\x1cn\xb5\x8a*\xa3\x8b\x1a\
+5\xef\x10<\xcc\xc1\xff\x11\xf7\x0b\xdc\xa34\xb5\x1dA\
+\xb7Cq]\xc7\xec=\xd7\xe9\x0a@XN\xef8d\
+b:\x1d\x93\xe7L]A\x03I\xfb\x1bK#_\xde\
+\xd8\xd4\x14y\xcb\xb4\x8e\x00\xe8\xa0\xe0\x80IG\xbfh\
+=\x13o\xcc\xa1\xf3\x5c\x95\xc2[\xbbp8\x948\x19\
+\xf4;\x8bv\x1b\xb1\xa7\xa0m\xdf\xd1\x07\xc0\xa7\xb8\xcf\
+\x0f\xa9\x82u\xd0k\xc5&\xf3\x8a0\xe1\x8a\x89/\x97\
+C\xb7T_\xdb\xdd9\xf0R\xccN\x0e\x1d\x9a\xff\xec\
+\x5c$\xc0\x15=\x02\xac\x8a\xdf\xc9??\x80\xbe\x9c\xda\
+\xb3\xb1\x8f\xcf\x03\xfe\xbfh\x90\xdd\xfcb|l\xbcs\
+0\xb3u\x8b\xe6\xdb\xb8\xa7\x12\xe8|3\xa7\xcbZx\
+\xactsG\x97\xe1v\xc7\xa8/\xd0\x8f\xaa\xab\x93\xc8\
+\xf4\x8b)\xa1_\x91\xf6\xd7x\x93\x83\xb3\xb4N\x14G\
+\xc7\xa4s\x97\xe1S\x97\xe2\x97qZ\xbc\xde\xa4C\x17\
+\x00\xde\xad\xd8\xf5\x83\x8c\xa7\xb3\x01\xc3H\x8bV\xd0M\
+\x08i\xd9\xc3r\x07\xbf^P\xbcyE\x98r:t\
+\x9eF\xb4\xddE\xca\xd0\xc91\xfb\xd13\x05D\x80k\
+:\x02\x1c9}Q\xec^J#s\xed@\x8d\x9b3\
+\xb1\xbf\xaf\xbb\xd5tl\xa6\xf9\xb7\x88\x14\xc69\x05s\
+\xc1\xa3\xde\xc4\xdfz\x8f\x9f\x9b\xd3\xc8\xa2}85\x84\
+zP\xc9\xdd\x9az1:I\xc7\xe4\xd5\x95\xea\x00U\
+\xde4\x01\xe4\xb99\xdf\x91\x89\x1a\x0c\xce\xe0\x09\xbe\x85\
+< \x86\x85\xc5\xef\xd7s\xe8\xc2\xe3\xd3\x99\xfb\xb2\xc4\
+\xd2\xedL\xa5\x07\x1f-\xa2NX\x0f\xea)\xc0\xdf>\
+x\xb27>\xd7\x07\xac\x85)\x87N]\x84\xf1]\x95\
+\xaa\x17\xb3{.\xdb\xcc\x9c\x03\x13\x99S 8d~\
+q<fw\x09\xdch2C7O\xca\xd0\x09/~\
+\xe3\x8e\xe3\x9c\x00\xe79\x01np\x02\xe0h\x5c\x5c\x06\
+\x86N\xf3\xbdA\xe0O\xa0\xa4\xcd8\x9a{\xcc\x0f\xa8\
+\x06\x071\xb1\xaf\x8d\xf3\x89!\xd3|n\xa1\xf4\x9f\xe4\
+\x96\xd7m\xe4\xb4t:\x1c\xcb\x8f\xbe\xf3,z\xcdH\
+\xea\xc6jG\x9a/\xc0\xaf\xf5\xba\xb7\xc8\x9b;8\xa1\
+>9(\xfcp\xa5>\xd6\xf3v\x0bvO\x99\x1f\xc1\
+\xa6\xf9D\x81\xac\xd11\xbe\xdfD\x97\xc2&\xbf\xf6X\
+'\xedj\x99KC\x91'\xd3\x0d\xc4._\xc7\xeeV\
+\x0e\xfc:\x01!i\xbc\x08\xb3X\x1d\xb3\x1bq\xe8<\
+W\xa7\xb0\xf9a[\x98o$v\x05mg\xb3\x17\xc5\
+\x19\xb4\x83\xd9yE\x01\xe8\xe6e\xe8D\xf8\x16\x10\xb2\
+M\x8f\x0082\x17\x09\x10\xbf]\xd9\xdc\xf1s\xc7~\
+\x1e\x14\xae\x0d\xa6\xd2\xf8`:\xf7h\x02y\xf2\xb3\xa8\
+\xbd\xdbU\xa3\xd5{\x22=\xb7?\x95\xd7\xc5\xb9\x00_\
+\xa9\xc0\xaf\xfaF\xc17\xe2\x08\xd6\xa3\x0f\xfb+}q\
+\xebf\x1d\xfa\xfa`\x02\x034\xe3&\x8e\x94\xc3\x90\x06\
+\x7f\xb7\x06\xad&S\xe7%\xedj\x19C[\x9a\xfa\xd3\
+h\x18\x5c\xf7\xc6\xf6\x9b\xe8z\x18\xbb~\xb5\x1c:\x7f\
+\x13\x0e\x9d{\xf0fN\x00\xd1\x166\x15\xc8\x07\x9f\xe3\
+\xf7\xe6\xdd\x86\x1c\xfd\xb1M\xb7=\xa0}%\xe3\xc0\xf7\
+\x90\xb5}\xae\x89\x0c\xdd\x8c\x05\xc2\x8b\x8fg\x99\xd9\xf9\
+\x0a\x01\x8a\x90\x00\xb78\x01\xb2\xce^\x12\xbb{\xe2h\
+\x8aZ/\x8a\xd9;Q\xfa\xb6\x0f\x91a$Y\x87\xf1\
+\x1a\xad\xde}\xe85\xadU{\x1d>\x96\x9a>\xab\x98\
+<\x03\xe8\x0d&\x83>&\xa66\xa5>\xc2\xfe\xf4\xe5\
+\xec\x09d\xb7\x9f\xda\xf7^Bf\xce\x99\xd6G[i\
+WKw2w\xad\xa9\xfb\x08o\xc4 \xf0\xa4\x8bq\
+XrYE\x18\xd9\xa1\xf3\x5c\x96\xa2\x10@\xea\x0b\xb4\
+v\x0ff\xd8\xb1\x0c\xd7\xc4\xc3\x97\xd6w\x18ds\x0c\
+\x01s\xf4\x8e+\x05\xddwC\xa9\xb6/H0\x1a\xbe\
+a\x12\xe8\xfc\xa5k|r\xbaB\x80;|\x5c.^\
+\xaf\x8f\xcd\xbc]D\xe4.\xd4T\xfb3I\x0b\xfa^\
+\x1di\xdf^w\x92\xaeD\x92\xb6R\xab\xf77\xd2n\
+\xa7\xda\xaa\x16\xb0J\xff\xf1\xb6\xfc\xa8f\x09\xbd/\xe6\
+\x08\xd1\x97\xf8\x95\x96\x83\xa1\xd4!dC\x1e\xedDZ\
+\x1bG\x90\xa5\xe8&mnhL[\xbd~\xa4\x1b\xd6\
+\x83\xf7\xe8\xfb\xc6\x18\xef\xaa\xd1p\xe8\xdc\x97n\xe6}\
+\x812\x01x:\xd5jz.\x9d\xc1\x83\xdb\xaeBp\
+\x90\xc2$\xb7p\xd3\x19:\xcf\xd2\xf0\xcd\x9e\xc27t\
+\x18e\x02\x14q\x02\xdcS\x08`\xad#@\x07Z\xbb\
+\xc5Q\xf6\x0d\xe9\xdf\x8d\xe9\xfe4%iB\x7f\xfbV\
+\xea\xfa\xfdD\xd5\xf1[\xf5\x8d\x85{\xe5\xac\x09\xc8-\
+d\x8d\xa5\x0e\xa1\xaed\x12\xfb\xd0\xc0\x82\x1e\xc4\xfaV\
+R\xcb\xf3WRs\x09\xfa\x13M\x9a\xb6\xeb\xd5\x8fO\
+(\xf7\x8f3\xe8\xaaQg\xe8\xf4\x8a0\xcb\xf4\x1bC\
+\xddi\xe3E\xcb\x9e\x96i\xd4\xbd\x8c\x9b/\xfc\xd1\x09\
+\xc3d\x8dl\xe2\x8de\xe8\xd4\xe1\x9b\x9a\x00\x19\xc7s\
+\xf8{t\x1a:)R\xca\xd85&M\x16\x9bR\xea\
+R\xd6Tn\xa4\xa9\xa71\xef\xbf\xe6+\xef\xf8}M\
+K\x81\x18.\xf91}\xb9\x06\xd4>\xd6\x94v\xf3Z\
+\x904\xa3\x96\xb2o\xa4m\x5c\x1f\x11\xeb?\xa2\x9b\xf2\
+=\xac\xa7\xfcx6\x97\xa0$\xb3\xbaj\x84C\xe7\xa2\
+\x22\x80C\xc0Z\x11\xa7\xaf\xa0%\x08\xe3\xeb\xb9\xb0\x0c\
+$pg\xd0#Z3C\xa7\x03\xddM\x01}\x8a\xcb\
+:>\x8f\xd7\xd69\x86\xed<xN\x8f\x00\x8b\xd7\xa6\
+\xf2\xf7h\xdc\xb2\xf3\x1c\xe9\xb43y\x98EM\x12\xb9\
+\x99\xe6\x03\xe9\xff\xa2\xcd\xbb\xfa_\x06\xf82Z\xc8j\
+I\xbd\x84_\x90\x86\xd7\x97N\xb9\xa8'\x99\xba\xf7\xa5\
+}{\xef\xcba%_\x02|b\xcc\xee\xaaA\x87\x0e\
+O!\x17\x04\x98\x1f\x9a\xc2\xb7\x8e\x0d\x9c\xe2u\x85\xc0\
+w\xa0H\x03\x97\xa3\xe9\xb8\xd9\xc5\xc6%L\xcf\xc4\x0b\
+\xd0\x85\xb6s\xd0\xf9\x10\xc6\xd2I\x9cx\x8a\x1a\x12\x00\
+OL\xc1s\x13h\x94\xcdI\xf2k\xfa\xd1\xfa\xdf@\
+J\xdaT\x936\xa9VSIU\x8d#\xef\xff\x1a\xc0\
+\x97\xd1B&\xda\xc7jQ\xc9XHmb\xbf\xbc\xb9\
+\xa1\xaa\xd4\x5cR\x87\xacC[<\xc0j\xb2G\x84\x0e\
+t\xf7\xb2\xbaj\xfc\x139\x01\xdcV'\xf3\x09dX\
+\xad\xb3*\x1d\x9a\xe4H\x9e\xb7%\x9d\xc13\xb6\xff$\
+\xd7Ln\x05\x00p\xd9\xc4O\x91A\xa7\xd9{B\xd0\
+_8GK\xc0\xd6\xf4\x13\xfc=\x869\x04<\xfa\xbe\
+E\xc7\x05&\x8e\xbb\xab\x22\x9d\xe8UY\x0d\xf6_\x12\
+p3:\x86\xd4\xadc\xb2T\xd3`\xbd\x9cW\xe0'\
+u\x0e\x98\xec\xce\x13AxR\x86\xa9\x0c\x9d\x88\xd9\xe7\
+\x04*\x04p\x0c\x8c\xe5\xd54e]\x9e\xbc\x93\xcc\xbe\
+5\x85b=\xc5\x1e\x87_:\x0f\x98\xcbK\xb8\xce\xa1\
+z&^\x0d\xba,\x09iYl\xdb\x81S\xb0\xd4\xc4\
++#\xd9\x1c\xfc\x1f\xc3\xf2\xb2\x98\x086\x9c<\xfd\x1f\
+\xdex\xc9\xf6-\xb2\x08\xc6\xa4\x92\xc6s\xf5\xb6\xa87\
+i\xdb}\xb8\xd5\xdc\xa5\xff\x89\xc7\xa3\xcc\x0bH2\xdd\
+U\xe3\x93\xc0\xec}\xd7\xb2q\x04<\x8eP\xb1\xe82\
+0\x8er\xf3\xb6\xe4\x9cu\xa5\x90\xab-\xfd{(\x8e\
+\xa5\xc5\xe7\xdb8\x85\x9b\x04\x1e\x05\xc3F\xe7\xa5\xebu\
+\x99L*\xda\x04JS\xb9\xfa\x90\xf9oh\xd6\xd1\xed\
+\xef~\x0c\xfc\x08\xf5!\x8d\xdd\xc0Y\xf3\xe3Z\xea\x12\
+\xcck\xecZ]5\xd3\xbdb\x19\xd6\xe0Em\x01<\
+\xfem\xb4W\xd1\x93r\x11\xc3\x09\xf0\x16R\x08\xd6\x8a\
+\xac\xc1\xe8\x81S<\xb3\xf1\xb5c\x9d\x82\xf9\xbc}5\
+\xf0\x13\x9d\xa2u\x03\x98\xa5\x14v8E\x14N\xe4S\
+\x0c\xa6\x1c\xc8\x8f\xe4\xf7\xd4~+\xd2\xb6\x7f1\x8b\xa1\
+7\x96U\x1c`\xd5n\xc0\xf8\xc5bw\xf2\x04\xd70\
+f\xeb\xbe\x86Mv\x8f\xe4b\xe3ZZM\xa3\xa2\xd2\
+j\xd2JW:\x83x\x04%]ZHs\x03\x1a\x12\
+P\x22s9\xa1\xc7\xe8\x19i\xe2=\xf0\xfc\x1d\x9c\xb9\
+/\xa4\xb4h3\xe7\x82T\xbb\xf0\xa2\x84\x96\x0d\x81/\
+\x8a6\x0d^\xd7I\xe7\x7fG\x02\xc8\xb3\x0a\xeb\x933\
+\x85\x9a;\x02C,<Ul\xc4\xac\xa0\xe7\xfa[\xd4\
+\x83\xfe\x00\xf0\xb2I#\xe5\x89Y\x93\xc8\xd9\x13\xe7\xed\
+6\x92\xc2\xcezt\xfd\x9fh\xcdF\x00'}\xdf\xa2\
+\x93g\xf7Q\x0e\xbby\xc1\xc6\xde\xe7\x0e6e\xa0\xf4\
+\xb1\x9ew\xb6\xc9\xaf=\xa34R\xd8V\xb4\x13\xaa\x83\
+\xaabW\xeb\xad\xcc\xde\xfdE|\x06\xf9\x00\xabo\xa5\
+C*F\xd2Mw\xa2\xe9X\x01\xd44\x81\xa0\xf8R\
+\x987G51\xab\x13\xe5 \xbe\x95\xf2\xea\xb5\xa5\x83\
+0\xbe&\x92u\x22\x12X\x933\xe7BD\xf2\xa5*\
+\xa5\x17\xfdM\xa4\xb0GS\xbc\xdf\x95\x96\x92\x1f\x89P\
+u\xa5\xd1u\xef\xd6\xfe\x97\xb4\x02\x1f\x12h\x8d\x88\x04\
+\xdd\xc8\x91\x1bO ;\x12 3h\x9d\x9f(\x0dN\
+\x92'f}\xad\x1a'\xf7\x9e\x94\xab\x10$hF\xeb\
+w_\xf2\x17\xc6\x13\xd0SI&\xd3\xdfF\x10\xb1\xba\
+J\xc3\x1b\xbe\xa55\xbf\x8e4\xbc\xb2\xea[S\xb4\xf9\
+\x8b:\x83\xf2\x01V\x9fSb\xe8\x17\x02\xa9'\xb5H\
+Y\x12 \x96\xa4\xbd}\xa4\xc1I\x02\x98\x7fj\x9c\xa4\
+YU\xe3,\x84\xfa\x14\xba\xb5\xa4%\xa1'\x01=\x90\
+\xa4\x1f\xfd\xad#=\xa7\xa94\x9f\xa7\xaej0S\x95\
+w\xe0\xbf\xba\xa5@\x90\xe03r\xae\x1a\x13\x11ZS\
+\x9d\xa1\x03\x91\xa2\x8d\xc6\xe0\xa4\xbaF&fU\xd6\xd8\
+\x01]\x87\xb4X8\x87\xbf\x10\xd0\xad\xc9\xc47\x97\x0a\
+V\x0d\xa5\x1c\x7f\xc5\x073\xbd\xfb1\x9b\x04\xefI \
+\xd5\x93\xb6\xa97\x22\xaf\xbe\x91\xaa\x9af\x0c\x18\x1d8\
+\x1ag#\xc9s\x02?\xa7\xf7\x10\xd1BC\xba\xb68\
+\xa8\xb9\xce+\x9d\xcf\xf3\xee\xc7\x18\x09,h~!\x0e\
+\xb1\xb4\xc09\xb78\xec\xf8\x03\xe5\xa4s\x0b<\x01\x0b\
+\xe7\xdf\x7fJ\xbf\xf1\xff\x1f\xe1\x89\x188\x13\x1f\x8fG\
+SNC\xe5\xaf\xad\xac9\x22U\xff=\xaa\xd1kj\
+J\xef\x81\xe3\xd5\xeb\x90|\xa4\x1c\xb0\x8dg,\xf3\xcf\
+!\xae_\xd9\xd4\xf5\xdf\xfd\xbc\x82\x9f\xfa?\xfcR\x09\
+\xa42HU\x90\xea \xff\x00\xa9\x01RS\x92\x1a\xf4\
+w|\xbc\x1a=\x1f\xa5R9\xae_\x99^+\xde\xe3\
+=I\xfeAR\x8d>\x87\xd9\xd7\x7f\xf7\xf3\x8a~\xbe\
+\xfa\xbeY%\x90\xca$U@\xaaJREz\x0c\xa5\
+\xd2K^_\xbcG\x95Wq\xedw?\x7f\xc2\xcf?\
+\xbfmRI\xc8\xbb\xbb\xf1\xee\xe7\xddO\x05~\xfe?\
+\xaeY\xd8\xf4\x1d\xfb\xf58\x00\x00\x00%tEXt\
+date:create\x002010\
+-02-10T01:44:25-\
+06:00\x0e\xe0\x0c\x1b\x00\x00\x00%tEX\
+tdate:modify\x00200\
+4-05-23T19:30:34\
+-05:00\x17\xb7\x8ah\x00\x00\x00\x00IE\
+ND\xaeB`\x82\
+\x00\x00+\xc0\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\
+\x00\x00\x00\x09pHYs\x00\x00\x1b\xaf\x00\x00\x1b\xaf\
+\x01^\x1a\x91\x1c\x00\x00\x00\x07tIME\x07\xd7\x0c\
+\x1b\x16\x028\x83\x98\xbev\x00\x00\x00\x06bKGD\
+\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00+MID\
+ATx\xda\xec}\x0b\x98\x1dGu\xe6\xa9\xee{\xef\
+\xbcG\xa3\xd1s4\x92,K\xb24zX\x96%[\
+\xd8\x18l$\x1b\x1c\xb2!` vx\x85\x04\xb0\x9c\
+\x00\xbb\xd9\x0d!l\xbe\xddM\x80\x04\x16\xf2e\x13v\
+\x93\xfd\x92\xdd\x95\x8d\xf1\x02\x1f\xb6\xc3\xe2\xe5e\xcb\x18\
+Y\x0f\x83\xf1\xfb%\x8d\xde\xb2,\xcfhF\xf3~\xdc\
+\xb9s_\xdd\xb5\xe7\xd4\xdc\xfa\xaa{\xce\xed\xee{\xaf\
+\xee\x05\x99\x9dc\x97\xba\xbb\xba\xfbvW\xfd\x7f\x9ds\
+\xeaTu\x0d\xcc\xc9\x9c\xcc\xc9\x9c\xcc\xc9\x9c\xcc\xc9\xff\
+\x97\x22\xa0B\x91\xe0\x97\xdb\x01\xacM\xb8\xfd\x1dL\x1b\
+aNj!\xdd\x98\x1e\xc4t\x04\xd3\x03\x00n5\x80\
+\x14\x95\x00\xdf\x8d`\xb7\xe2\xb6\x1e@\xa40\xad\xc4\xfd\
+S\x85}\x98\x93\x9aK#\x80\x5c\x8b\xe9\x5ca?\x8d\
+ib\xa6\xe1\xb9\xa2F\x04 \xc6\x89\xab1\x0d\xcf\xb4\
+t\x11\x03\xb0S\xcd\xcd\x96\xed\xbaVFJ\xcb\xb1m\
+\x01\xb1\x98\x88\x03@\x0c\xe6\xa4\x16\x92\xc7\x94S;y\
+i;\x8e\xac\x13\xc2u,\xcbmL&]<\xe7\xa0\
+f\x90\x0b\x00\xdc\x17p{;\xa6\xaa\x10@\x16\xae\xeb\
+\x9bi\xe1\xb1\xb6D\x22\xe6\xdav\x5c\xc6bq\xe98\
+q\xb7\xae.\x1ekl\x8c\xdb\xf1xB\x02\x08\x1b\xe6\
+\xd4@\xad\x84\xb0p\x80*\xd9\x96\xd0\xd9)\x1d)s\
+\xd0\xd3\x93\x96CC\x19\x91\xcf\xe7,\xc7\xc9\x8de\xb3\
+\xf9F\xa4H\x07]\x8e)\x0a\x8bX\x89$\xb1\xd2\x00\
+\xf1\xfa\x96\x96D^\xcaz\xb9x\xf1\xfclG\xc7m\
+\xd0\xd0\xf0\x0e)\xe5\x95\xe9T\xaa5;:\x9a\x00)\
+k_\x09\xbf\xa4kd\x85\xef#\xab\xfe^<\xdf\x8a\
+\xc7\xa1\xb1\xb55k77O\xd9\xabWw\xdb\x00\xfb\
+\x12\xbd\xbd\x0f\xe4\x7f\xf1\x8b\x81\xfa\xba\xbatzr2\
+[P\x16.\xddZ\xb1\x06\x90\x05\xf0/ \xf8\xf9\xe6\
+\xe6\x86x\x22\xd1\x94\xbb\xf6\xda\x0f\xda\x1d\x1d\x9f\xb1[\
+Z\x16\xbb\xb9\x1c\xb8SS\x90\xbdp\x01\xd2\xe7\xd0\x22\
+Iy\xd1\xe0\x8a\xda\x00^98\x95\x83n\xceW\xf9\
+\x9cUW\x07-\x9b6A|\xfe|\x8855\xa9c\
+7\x9d\x1e\xce\xf7\xf5\xfd]\xe2\xa7?\xfd\xdf\xb9d2\
+\x19K&\xa7\x97\x14H B\x1e\x13\x8b\x00\x9fT\x7f\
+\x5c655\xc4\xda\xdb\xe7\xbb7\xdd\xf47\xcd]]\
+\xef\xb3\x12\x09\xc8\xa7R\xe0LN\x82\x10\x02\xc4\xd0P\
+\xe5\xa0\xd7\xa6\xa5DK\xad\x00\xaf\xdd\xbb\x9bk\x84\x00\
+\xbb\xb1Q\x81oSjn\x86xs\xf3\x02g\xf9\xf2\
+/M\xc6\xe3\xdb\xe2\x0f?\xfcYGJ\xe8\xc3\xc6\xd9\
+\x01\x90\xa5{\x82H\x10\x0b\xb3\xfb\x83t\xbe\xa5\xa5N\
+\xc4b-\xf2\xado\xfdj\xeb\xce\x9d\x0a|'\x99\x84\
+\x98\x10\x9e\x1b$\xb8\x8eSS\x15/\xab\x0f0\xff\xcd\
+\x1a<[\xd6\x80\xd4BJ\xb0\x1a\x1a\x08x\x22\x00\x11\
+A\x11\x22\xbe`\x01B!\xdf7\xd4\xdf\x9fm:p\
+\xe0s\x88\x9d;89\xe9.\x02\xc8\xcb\x00\x7f \x16\
+f\xf7\xf1d<\xe58\x8d\xd6\xb6mw\xb4^y\xe5\
+\xfb\xe9!\x22\x1eW\x0ct\xf1\xe1n&\x03\xaeeA\
+l\xf5jX\xb8p!\xc4\x17/\x06\xc0\xe3*Hm\
+[tm\x9f_\xf3\x86\xe0&\x93J\xed\x03\x99\xe0T\
+\x8a\x9cB\x10\xd9\xac\xc2\x830\xaa_\xb5\xea\x03c\xe7\
+\xce=\xddt\xf6\xec\xfd\xf5\x08\xbe\xc7\x17\x90%\x11\x80\
+\xfa\xf4m\x08\xe5tSS\xa2\xae\xb5\xb5M\xae\x5c\xf9\
+\x19\xab\xbe\x1e\x1cT)b\xd92\x80\xae.\x10\xf8\xb0\
+&\xb4A\xa2\xb5\x15&{{!36\x06\xd3\xd9,\
+1\x10\xe6\xa4\xb6BX\xc4\x10\xe8\xe6\x8e\x0e\xa8\x9f7\
+\x0f\xb2##\x90A?L\x9e:\x05\x12\xc9\x11\xc7\xc6\
+(\xdb\xdb\xff,\xd6\xd3\xf3H\xb2\xa9)\x8d\xb8\xe5\xc6\
+\x02\x1c\xc2X\x10\xf3\x86\xe8\x9c\x94u\xa9\x85\x0b\xdf\xd3\
+\xd2\xd6\xb6\x84\x98\x96ok\x03\x81\xaa\x87\xfa\xfau\xd8\
+\xeaGN\x9e\x84\xd1'\x9f\x04\xe9\xba0'\xbf|\x19\
+C\xc0\x9b\xb1A.\xbd\xf6Z\xc8\x0c\x0f\xc3\x94m+\
+s\x1cC\xcd`\xcf\x9b\xd71\xd4\xde\xfe\xdb\xed\x03\x03\
+\xf7\x01@f\xed\x8c\x19\x00Q\x8a\x06\x18\xa3\xd6\xdf\xd8\
+h\xa3\x9dO\xe4[[o&\x80S\xd8\xba\x01S\x0c\
+\x1f\xd4\xb0f\x0d\xf4=\xfb,$\xcf\x9f\x879\xf9\xd5\
+\xcadO\x0f\xd8h\x0e\x16l\xd8\x00\xe3/\xbf\x0c\xd3\
+\xa8\xa5\xed\xe9i@\xbf\x0d\x9c\xfa\xfa\x9b\x11\xc3\xef\x10\
+\x96c\xa9\x94\xd5\x06\xe0Fj\x80/\x00\x88\xdd\x98\xb2\
+\xaek\xa3mI\xb8 \xb7`?\x1fr\xe4\xf8\x0d\x0d\
+);?\x8e\xc0\xd3\x83\xe7\xe4\xd2\x90\xf1\xd3\xa7\xa1e\
+\xc5\x0a\xb2\xfd0\xf6\xfc\xf3\x90Es\x9cH\xa7\xc1\x11\
+\xe2*\x07 AXN\x03\x88\xff\x8a\x89\x94|(\x01\
+\xfe\x92\xbc\x7fL\xf5\x96e\xb9R\xc6\x9ct\xa6u\xa2\
+\xfb\x08@C\xa3\xf2:\x1b\xd7\xaf\x87\xe1\xe3\xc7\x01\xe6\
+\xd4\xfe%#.b1~\xe6\x0c$\xd0\x1f8\xbfw\
+\xafr\x0e\x85\xe3\xc0\xc2\xa6\xa66\x89\x18\x12\x96\x08\xb4\
+ l?\x1fB\x00\xc3(\x00\xd1h\xdb\x16\xe4\xf3\xb1\
+\xa9\xfe\xbe\xba\xb1\xbe~\xd02\xff\xfd\xef\x07'\x9f\x87\
+9\xb9\xb4\x84\x9c\xf0f\xd4\x02\xd3\x14\x9f)\x98\xe6\xfa\
+e\xcb\xea\x00\x09\x80\xe6\xc0\x22L\x17\x95\xda\x0d\x14\x98\
+\xf2R\x0a\x89\xbb\xd3\x93I\xc50-\x0e\xc0\x9c\xd3w\
+\x09J\x1eU>\x8e\xc7\x80@\x7f@\xcbT\x12\xb1S\
+a\x03)D9\x91\xc0v\x001N7Ii\xe5\xd2\
+i\x7f\x1f4\x93\x99\xeb\xea]\x82\x22\x1d\x07t\x840\
+W\xc8\xcb\x12v3\xa6\x5c\x10\xa6e\x85\x82]Pw\
+\x88<\xaa{9\xebAs\xf0_rb\x1a\xa5\x10\xa0\
+\xf1!\xec\xdcDBp\xbc\xa2}\x00\x05>%\xaf\xfa\
+\x879\xf5\x7f\xe9J\x11\x5c\x1c\xcc#\x0c\x01\x13a:\
+\xbf\x14\x02\x9c\xc24\x8d\xa9\xb1@\x00\x1f\xf8\x05\x02\xcc\
+Q\xe0R\x13\xd30\xa5\xd1\x00j\xab|\x00L)\xc2\
+\xb6\x14\x02\xf4`ZP0\x01\x16\xfe/\x01j\xaa\x01\
+\x1cL\x8f\x9f=\x0b\xcf\xbe\xf6\x1aLb\x00\xe3\xf2%\
+K\xe0\xb77n\x84\xc5\xe8\xcc\xfc:I?\xda\xe3\x1f\
+vw\xc3\x99\x81\x01hE;\xbd\x03\xfb\xec7\xad\x5c\
+\x09vU\x09\xc0:\xfa\xb4o\xb9\x1a\xdbRM\xc0<\
+LycW\x8cTY\x03\xd03\xee{\xe9%\xe8\xc5\
+.LKK\x0b,\xc6q\x85!$\xc1?\xfd\xecg\
+\xf0\xc1\xed\xdba\x0d\xe6\xfd:\xc8q,\xdf\xfd/\xbc\
+\x00\xf5\x18F_\x82\x04w\x1c\x07\x0ea\xf0\xe6,\xc6\
+\xf0?\xbce\x0b\xc4\xaa\xe4\x03\x88\x82\x060\xe0\xab\x13\
+`\x170\x1d.\x95\x00Y\x00\xea\x01\x08\x04\xdab\xa3\
+SU\xd2\x009L\xf7\x1f;\x06yl\xe9\xef|\xe7\
+;\xe1\x8a+\xae\x80:\xdc\xef\xef\xef\x87\x17\xb0\xb2\x1e\
+:z\x14nCM\xb0\x1a[\xcb\x1bYNNN\xc2\
+\x0fO\x9c\x80-W]\x05\xdb\xb6m\x83\xc5\x18IM\
+\xa368\x81y\xcfc\xd4\xee~,\xe7\x1d8\xb8\x16\
+\x93\xf2b\x09\xa01\xf2m\x09C\x0b\xb1$L\xa1\x0c\
+\x02@\xbc\xe0<\x143\x01\xb2\x0a\xe0\x7f\x17\x072\x00\
+#\x8b\xef\xba\xf9f\xb8\x0a+\xa7\x09\xc7\xb4\x85\x10\x8a\
+\x08\xabq\xa0i\xdf\xbe}\xf0#\x8cm\xff\xd6\xda\xb5\
+\xb0\x0aG\xbf\xde\x88r\x1a\xe3\xf2\x8f\xbc\xfa*\x5c\xbb\
+c\x07\xec\xda\xb5\x0b\x96\xe1\xc0M,\x16#\xb0T9\
+\x97/_\x0e\x8f=\xf6\x18|\x17\x07\xd5\xde\xbbf\xcd\
+\xc5\x91\x80\x1c\xbe\xe2C\xc9\xc2\xc5\x94+wF\x90\xf0\
+ld\x15\x09\x90G\x90\x1fB{O\xc3\xc8\xb7\x16\xc0\
+o4\xad\x5ci\x81\xcb.\xbb\x0cn\xbd\xf5VUY\
+{_y\x05~\x03\x8fW&\x12\xf0F\x923h\xca\
+~\xf2\xfa\xeb\xb0\xfd\x9ak\x14\xf8\x1d8tk\xdb\xb6\
+1\xb3\x18\xb6\xdd\x8ef\x8e\xcaH$\xf8>\xfaA\xef\
+Z\xb9\x92HP\xb9\x0f D\xb1)v\xa2\x82I\xa1\
+\xc6{\x94U$\x00\x81\xff#\x1cD\xb2\x10\xfc]o\
+{\x1blA\xfbg\xc07B\x15E\xad\xe5\x96[n\
+Q\xfb\x8f\x1d>\x0c\xb7tv\xc2\x0a\xac\xac7\x82\x9c\
+\xcdd`?\x9a\xb2m\x08\xf0\xdb\xb0\x9cK\x97.5\
+\xe0\x1bQZo\xeb\xd6\xad@\xb2\x7f\xff~\xf8qo\
+/\xfc&\x96\xdbv\xdd\xaa\xf5\x02\x1c\xde\x9b\x8b&@\
+\xbd\x0e\xf9V\xd1\x04\x10\xf8{\xd1\x03\x16\xc8\xfc]7\
+\xdd\x04\x9b7o\xf6\x83\xcfI\xa0Z\xcd\xce\x9d;\xd5\
+\xfe~\xf4\xa0w\xa2\xfd\xec\xb4,\xb8\x94\xe5\x5c.\x07\
+\x87p\xc8|\xeb\xd5W\xc3\x8d7\xdeHN\x9f\x01\x9f\
+\x0b\xd5\x81\x22\x81\x85\xe5:x\xf0 \xec\xc5\x89\x1d\xef\
+X\xb4\xa8l\x12\x18\x87\x9d\x9b\x00A\x98\x96J\x80U\
+\x05'P1G\xcab&\xa0\x22\xf0\x1fC\x8f\xd7B\
+\xf0oz\xeb[a\xe3\xc6\x8d\x0c\xfc0\x12PE\xd2\
+\xfe!t\x98n\xc4YH\xcb\x84\x80KQ^w\x1c\
+\xf8\xf9\xf8\xb82k7\xdcp\x03\x03?\x8c\x04\xa4\x0d\
+\x89\x04\x87\x0e\x1d\x82}\xa3\xa3\xb0\x0b\xeb\xaa,\x12\xe8\
+k\x85\xf0;\x82\x88a\xbe\xa0\xcdW\x95J\x80\x13\x98\
+\x5c\xea>\x04\x98\x80r(@*\xe9 MR@\xe0\
+\xa8R\xba\xba\xba\x18\xf8\xa5\x90\xe0\xadH\x1c\xaa\xa0'\
+q(\xfaz\xec\x1e.\xbd\xc4\xc6#\xceK\x09O%\
+\x93p\xe5\x95W\xc2\xf5\xd7_\xcf\xc1\x8f&\x01iE\
+\xe5\x08?\x89\xb3\xac\x0e\xa5Rpc}=\x01[\x96\
+\x06\x90|\x22\xaa(`\x09\xe1\x04\xe0'\x84S\x85@\
+\xd0kX\x08\x0b\xc1\xbf\xfeMoR\xe07`_\xb8\
+\x5c!\xe0\xa9\xfbD\x04\xa2J}\x06\xbbP;\xa8O\
+\xed8\x97\x06\xf8\x98\x9eE\xbb\xbf\x09\x01|\x13\x96\x13\
+\xdf\x95\xde\x99@!@\xcb\x22\xc1\xa6M\x9b\xd4\xbdO\
+?\xfd4\xf4\xe0v96\x9ep\xe1\xb8H\xbf/g\
+\x11\x96e;\x81\xf9\x5cN;\x0f\x17\xa5\x01\x12\xe8\xc1\
+_\x8f\xdd\x9du\xeb\xd6U\x00\xbea6\x01\xbf\x08m\
+\xe3u\xd7]\xa7*\xe89\xecF^\x83N\xe1\xc2_\
+\xf1\xdc\x84\x0b\xf8./\x22\x117\xa0Y\xbb\xf6\xdak\
+\xe9\x1d\xbd\xe0WD\x82\x0d\x1b6\xa8\xf2\x8e\xe0\xb8\xbe\
+\xdb\xdd]\x1e\x01x\xdcF\xe41\xc5\xcb!\x00q\xae\
+\x0e\x13\xeb\x05T\x10\x08\xba\x12\x9d\xa1y\xed\xedP_\
+__\x09\xf8\x8c\x044\xfd|\xc7\x8e\x1dj\xffE$\
+\xc1V\x22A6\x0b\xbf\x0a\x19\xc0g\xbf\x8c\xdb\xf5]\
+]\xd4\xa5S\xef\xa6A\xd7[-\xe5\x92`=\xce\xbc\
+\x9aD2\x0d`\x0f\xa8$\xd1D\xe3f@\xe5N\x95\
+\xab\x01\x94\x13X\x85^@\x13\x82Ca^\x0a\x7f\xba\
+\xae[!\xf8&O\x93\x80*\x9cZ\xdaa\x9c\x0a\xb5\
+9\x91\x80\x05\xe94\xfc2e\x10\x9fy\x04\x09\xb0~\
+\xedZ\xe5\xc5/X\xb0\x80\xde\x87\xbd\xb3!\x82\xda/\
+\xd9\xe4\xb5bW\xd9\xe9\xef\xa7\xfa.+\x0e`\x86\x83\
+\x0d\x01\xdcrM@KaDPV!\x10\xd4\x8f\x11\
+\xbd\xc5\xd8B\xe2\xf18\x85@\x89\x04e\x82\xcfI@\
+\x15D$\xb8\x1a\xb5\x0b\xed\x1f\xc3 \xca\x06\x1a\xeeD\
+\xc7\xe9\x97!C\xa8\xcd\x8ec\xbab\xf5j\xe5\xbd\xb7\
+\xb7\xb73\xa0=Z\x80\x9d\x8b\x02_iK\xbc\xbe\x1f\
+c\x03\xb2\x02'\xd0l\x0d\x86-\xe5\x10 W\xe86\
+\x08)/:\x104\x85v\xec\xd4w\xbf\x0b]\x1f\xf8\
+\x00\x15L\x93\xa0b\xf0It\xa5R\xab\xa3.\x17U\
+\xdaI\xfc8u\x1d\xe6\xcfC\xa7\xa9\x962\x82~\xcc\
+)\x0ca\xafY\xb5Jy\xed\xf3\xe9\xe3\x18!\x02[\
+~\xb4&\xe0\xe0St\xf0\xd8\xfd\xf7\xc3TooE\
+\xdd@\x1ff\x84!>0W\xceX@\x0a\x93M\xa9\
+J\x81\xa0\x81\xe7\x9e\x03\x81\x85[\x7f\xc7\x1d\x8c\x04\x0c\
+\xfc2I@\xad\x8f\xba^d\x1a\xce`\xe8u5\xe6\
+\xb5NL@-d\x0c#w\xaf\xb6\xb5\xc1jtl\
+)\x96\xd1\x86\xfb\x1e\xf0\xc3\x81\xe7\xfb\x81\xe0\x9fx\xf0\
+A\x18x\xe6\x99\xca\x22\x81\xc5\xc7\x02 U\xae\x06\x88\
+\x11\xf8\xbc\x1bH\xc0U\xe6-?\xf5\x94Rk\xeb\x7f\
+\xf7w\x19\x09\xca\x04\x9fU0\xb5B\xdd}:\x87\xa1\
+\xe6\xcb\xf0|\x0b\x06d\xaa)\xe3\xe8\xc7\x9cC\xb3\xb3\
+j\xc5\x0a\xea\xceR,?\x08|\xb6\x0d!\x01\x07\xff\
+\x81\x07\xa0\xff\x17\xbf\xa8|>\x007\x01\x16\xe6\x95\xae\
+\x01\x9e\xf38\x81v\xb1\xd0\xe2E\xcc\x07\xe8\xc3\x82\xd1\
+\x8bv}\xf0\x83^\x12T\x02>\xabx\x02\x84\xbaO\
+T\x99\xbdX\x91\x9dx\xae\x09\xc7\xe1\xab!I\xfc\xed\
+^\x8c\xe7\xaf\xec\xec\xa4\xee,9h\xc1-\xdd/\x91\
+$ \xcd\xa5\xc1?\x8ej\xbf\x0f\x83@\x15\x89\x94^\
+\xf5\xcf\xc6\x03\x14\xb6\xa5j\x80D\x81In\x0df\x04\
+\x11\xbb\xa9\xf0\x1b>\xf4!M\x02\xea!P^\xe5~\
+\x81\xf1\x9c\x09 U\xa9\xfdX\xa1\x1d\xd4\xa5\x1a\x1d)\
+\x7fU$\xe9\x05\xbf\x0d\xfa\x11\xf8\xe58H\xb3v\xed\
+Z\x0d>{~\x08\xe0\x81\xe6\x80\xde\x99F?\x95\xcd\
+\xff\xcew\xa0\xff\xe7?\xbf\xb8\x09!\xbc\x17\xa00\x14\
+\x05Le9\x04\xc8b\xb2\x00D-f\x04\x11\xcb\xe9\
+\x857~\xf8\xc3\x8a\x04\xd3\xd3\xd3D\x02\x06ri\xe0\
+s\x12\xacY\xb3F\xed_@\x22,\x01\x09\x8d#\xc3\
+\x15}\xef=5\xbf\x1d\x06/[\x05\x9d\x18\x8a^\x85\
+N_sss1\x13\xa4\xf3J6\x01$\x1a|\xea\
+\x1d\x1d\xfb\xf6\xb7\xe1|(\xf8\x95G\x02\x89\x12n\x01\
+\xd3L9\x1f\x86\xc8|^\xb8\xb6-\xcc\x8fVwN\
+\xa0b;\x91\xe0#\x1fQ\x11\xc2T*E$\xa8\x10\
+|N\x82\xcb/\xbf\x5c\xed\x0f\xc6l\xd5\x04\xea\x87\x06\
+C\x14\x00\xe7\xc7t\xfbB\x18^\xb3\x16:\x16/\xa6\
+\xf9\x09\x14\xcb\xa0\xdfc\xcf/\xc7\x04\xe8\xfb\xb4\xcdO\
+$\x12p\xf4[\xdf\x82>\x9c\x02w\xb1\x22\x03\x06\x83\
+0W\x10\x96\xa2\xfc\x09!zF\x10'\x80\x84\xea\x88\
+*8\xfe\xde\xc6\x8f~\x94H@\x9a\x80\xe6\xb2W\x02\
+>S\x85\x04\x18\x01G\x95=\x1c\x8bC;H\xa8\x1f\
+\x1c(iE\xac\xd4\xc2E0r\xc5zX\x82\x91\xb8\
+\x15+VD\xb5\xfc\xb2m>E\xfa\x08\xfc\xeeo~\
+\x13\xfa\x9ex\x02\xb8T\xee\x03`\x81\xfd\xf8T2\x1f\
+\x80 p0\x05G\x02\xab'\xe7\x91\x04T9\x9b~\
+\xff\xf7iK\x9a@\xf7\x0e\xe8\xf8\xa2\xe2\x04\x04\x1c\x01\
+H$\x18\xb5I\x13\x1c\x81\xc4@\x1f\x84Iz\xe1\x12\
+\x98\xdc\xb0\x19\x96,\x5cH\x93R\xf4T\xb5\xa0\xf7)\
+\xcb\xfb\xa7\xf7\xa0\xdfS\xe0\xdfw\x1f\x9c/\x1b\xfc\xe8\
+H\xa0\xe0>\x80\xc20_\x0e\x01\xd2\xd4\x0d,t!\
+X$PJ\x95\xaa)T\x11\xf4\x9b\x9b\xff\xe0\x0f\xe8\
+\xd0k\x0e*\xf6\x0bH4\x09h\xee\x1d\xb5\xbcQ4\
+\x07\xf3\x0eK\x88\xf7\x9f/\xba\x1cYfI\x07$7\
+]\x05\x8b\x10|\x9c\xc5C-\x95\xa9\xf6\x88\xae_\x10\
+)\xe8\xf9\x06\xfco|\x03zq\xdc\xbf\xaa\xe2q\x02\
+gafY\x1a\xd3r4\x805k,\x80\xb6\xc2\xb6\
+k\xf6u\xd0y\xaa\x10\x22\xc1\xc7>\x06$SSS\
+D\x82\xca\x9dB#d^hN\x81j\x81\xe3Wm\
+\x87\x16*x\x7f\x0fx%\xbbd\x19\xa4\xf0\xdc\xc2\xf6\
+v\x1a\xce\xa5{\x82Z=\x039*\x8f\xbc|\x02\x9f\
+\x9c\xbe#\xf7\xde\x0b\xbd\x07\x0f\xd6\xe4\x13qEjK\
+\x14\x9d\x14J\x98\xc6\xca]&\xae\x90\xfc\x5c\x92\xb2f\
+\x9f\x87Q\xc5\xd0o_\xf9\x89O\x00I2\x99\xac\x0a\
+\x09\x08\xf8\x86\xc2\x9c|\xda\x9f\xd8\xbe\x03\x1a\x9f\x93\x10\
+\xeb{\x1dHr\x1d\xcb!\xbd\xed:hok\xa31\
+\x06r\xd0\x02\xc2\xb5\xac\xe5G\x9a\x00z\x1ei!\xfa\
+\xcd\xc3\xf7\xdcS\x0b\xf0\x8d\x0f\x00\x82\x22\xae\xcc\x04@\
+\xb9>@ca\xea\xf6\xec\xf9\x00\xc2\x125\xd3\x00F\
+\x13`\x05I$\xc1\x9d\xbb\xa9\xd5h\x12T%XD\
+ \xe8\xf1\xfa\xe4\x8e\x1b\xc0z\x86L\x0f\x96u\xc7[\
+\xa0\xad\xb5\x95\xc2\xca\x1a\xfc0{\x1f@\x04v\x1d\xa9\
+}rF\x0b\xe0\xdf\x0d\xbd\x07\x0e\x18\xac\xaa\xaf\x02H\
+e\xb38\x80\xd6\xe2\x84\xa9[\xb2\x09\xf0;\x10&\xc6\
+,,pi\xaf\x16\x04\x10f\xd3\x87$\xa0\xedf$\
+\x81\xd6\x04\xd8;\xa8d\xf8\x98\x81Ej\x98\x06\x91\x08\
+\x9c\xa9\xeb\xdf\xa6\xce\xb5\x22H\x14\xd7\xa7s\xfa\xfa\x08\
+\x89\xd4\x02\xa4\xf6\x09|\xd2<G\xee\xd9\x03\xe7\x0f\xec\
+W\x95)M\xc0\xbe\xaa\x22u/@Xlv\xb7\xd0\
+f\xbdd\x02\x18\xb5a\xf9\xd8dY\x98I\x0c\xab\xbe\
+({\xe3!A\xff\x13H\x02\xcc\xdc\xf4\x89\xbb\xa8p\
+\x86\x04\x95;\x85\xb4\xafI@\x80\xeb~=\xc5\x0d\xc8\
+9+e\xbc\xbe\xa4p/\x05w\x14\xf8\xd8\xf2\xbb\x11\
+\xfc\xbe\x83\x08\xbeg)\xdc*s\xc0\x94\x8d~\xdd\xe2\
+\x91@(\xe0\x99\xa8 \x0e\xa0Dz\x08 \xabl\x02\
+\x84N\x9e\x07\x8aBm\xf5\x1f:\x00\x82\x82Ew\xfe\
+!\x90LNN\x96J\x82\xa8<\x02\x9cH\xa0[k\
+\x98\xe9\x882\x03\xcc\xe1#B5b\xcb\xef\xfe\xfa\xff\
+\x82~l\xf9\xde\x89\x15R\xfa\x9d,\xb7z\x0c\xf08\
+\x81\x5c\xb1\xcar|\x00\x07\x93\xadv\x1c\xcb7\xb0\xa0\
+|\x00\xb7j\x04\x10^\x06H\x93g\x9a\x0a\x91\x80*\
+\x10\x83E\xbb?\x09\x9a\x04\xb9\x5c\xae\x1c\xf0\xc3\xc0\x8a\
+\xea\xda\xb2\xfc \x22h\x9bO\xa4\x22\xf0\x8f\xde\xf3?\
+\x14\xf8$B\xdb}\x93\xfcj\xa0\x0a\xda`\xe9\x8e\x1d\
+Eq\x91\x88\xa1\x82\xb2\x1c\x02d0\xd5S\xf9\x8a\xf6\
+\x02p{\x91\xc1 1{G\xf2}\x01&\x0d<\xb1\
+_\x9d\xd0$\x98\x98\x98 MPi\xb0(\x1a\x5c\x1e\
+O\x08#\x85\x0f\xfc\x06\x02\xff\xee\x7f\x86\x0b\x07\x1f\x07\
+\x0d\xbc\xb6\xfd\xc2\x0f\xbe9W!\x09h\x95\xd0%\xf8\
+\xe9\xd9\xe2\xed\xd8\xb5]\xb9\x12\x06\xf0c\xd3\xe1\xeen\
+6%\x8c\x12a\xdaP\x0a\x01\x86\x0b\x01\x03\xcbt!\
+@\x9a\x82V\xcd\x04\x08\x13k\xe6\xea\xdf\xf7\xd0\x99\xfd\
+\xc1'\x1e\x87c\xb8\xd3u\xe7\xa7\xc8h\xc3\xf8\xf8\xb8\
+&A\xa5&!\x8a\x08\xa1\xa3z\xfa\xbc\xd6$4'\
+\x81\x02G\xc7\xef\xfe'\x188\xb8\x8f\xa9}U\x8c`\
+\x0dP\xb2-\xa0%b\x17\xe1,\xa8%\x08z\x1b\x8e\
+Nf\xb0\x1e\xce>\xfc0\x9cz\xe8!\x98\xec9\x07\
+R\xba\x8c\x00\xda\x09 l#\x090N\xea\xc4L\x0a\
+\xf5\x93\xd6\xb6*\x0e\x07\xfb\xb4\xbd\xd0\x15\xe2qZ\xa5\
+\x87\x04\xbeD\xa25\xc1>\xaa)$\xc1\xbf\x06iH\
+p1NaI$\x08\x13r\xf84\xf8'\xef\xfe\xef\
+\x04\xbeQf\xd2\xef\xe4rm0\x8b nq\xe7\xb0\
+\x19\xa3\x92\xed\x1b7\xaa\xd5@[q\x90\xcb\xc11\x93\
+\xd7\xb1K\xf9\xf4W\xbe\x02=8o\xd0\xc9f\x89\x94\
+\xa8\x05:qk\xb1U\xdf\x09\xcbx\xa9\xeb\x03Lb\
+ZU\x98\x14j\x151\x01\x12.2\x10\xa4\xc0\xd7\xd4\
+d\xc0\x1b\x8f\xc5\xf2\x94@\x18]6\x84$8\x8e\x07\
+\xeb\xee\xfc7\x80B$ \x9f\xa0\x1a$\x88R\xf3\xec\
+\x1c\x82O\xb1\x03\x8aW \xf8\xff\x88\xe0\xff\xd4\x00m\
+\xd4\xbf\x12\x03\xbe\x1fx\x90\x5c\x13$0p\xd4\x8a\xc3\
+\xcf\xf3\xb0\x85/\xe8\xea\x82:$X\xb2\xb7\x17z\x10\
+\xf4\xd7\xbf\xf8E\xe8\x7f\xea)\x02\x9d\xd7+5P\xab\
+\xe8\xac`h lK!\xc0\x94\xf1\xcd\x84\x89\x03\x98\
+@P\x85\x91@\xfd\xa3\xfe\x0c\xc9}\x00\xf3pn&\
+4\x11\x86\x0eaE\xe3\xce\x15w\xfe\xb1\x02C\x93\x00\
+\xa5\x9af\x80\xf2B[>\xc5\x13\x9aT\xcb\xff\x07\x18\
+:\xf0\x98&v \xe0\x9a\x1c\xca\xbcz\xce7.Z\
+\x0c\xcd8\xef\xa0y\xf9Je\xcb\xeb\x90T\xf9\xa9\x14\
+\x0c\xe0\xea)\xaf\xec\xd9\x03=\x07\x0f\xd2\xc2\xd0%M\
+'wY$PW\xa3\xc16\xda\x09,\xd4?\x9b\x10\
+b\x19\x13P\xbe\xcd\xe7N\xa0\x06\xd7\xa8\x1a\xa6\x1d\xfc\
+d\x11\x052\x00\x91\xe01*\x1e\x92\xe0\xdf\x01\xc9\xd8\
+\xd8\x98!\x01\x97\xaa:\x85\xd4\x85\xd4\xe0\x9f\xbe\xe7\x1f\
+`\xf8\xe0O\xfc:7\xc0\xd6+\xf0\xd1_h\xec\xe8\
+\x84\xc6\xce\x15\xd0\xd4\xb9\x12\x9ah\xa0\xaa\xa1\x11\x01\x9f\
+\x82!\x5c\x0b\xe1\xd87\xef\x83\x0b\xcf=\x0fCG\xba\
+\xc1\xc9\xe5\xcbjb\x82\xf0\xb1<\x9a\xca\xd3\x962\xa5\
+\xce\x09\x5c\xab\xb16A\x04\x1f\x8a\x13'O\xc0\xe4D\
+\x12\x12-\xad\xf4gJ\xe8\xa1\xd1\xcc\xd4\xff0\x80\xf5\
+\x83\xf4\x89Y*\xdf\x00\x8e\xfb\x9a\xce&\x7f\x04Ip\
+\x0a$\xac\xbd\xf3O@\x93 \x9b\xcdF\x9b\x82\xca\xcd\
+\x80i\xf9MM\x08\xfe\x7f\xc3\x96\xff\xa8GMj\xa0\
+\xb5\xc3\xd6\x04\x89\xb6v\x88\xcf\x9b\x0f\x89\xf6\x85\xd0\xb0\
+t\x194,\xe9P\xc5N\x9e{\x0dF\xbb_\x863\
+\xdf{\x10F\x8f\x1d\x85\xb1\xd3\xa7\x11pG\xdd\xebJ\
+]\xd6\xb2\xc2\xc6\x84\x05%\x16\x08\xb24\xb6\xa5\xc7\x01\
+\x8c\xc8Y\x04\x98\x1e\x1c\x84\xd1\xd7z\xe8A\x8a\xcd\x89\
+\xd6\x19\x22\xc4\x1a\x1aT\x8a75\xd19?\xf8b\x96\
+j\xd4\xa0[\xb3T=\x8b\x0e\xfa#R\x8a\xdc\xd2\x1f\
+\xe4\x1e=\xf4\x138\x8d\x99\xab?\xf1'\xaa\x1b6<\
+<\x5c\xc9\xcc\xa2H\xb3\xa0\xbd}\x0d\xfe\xab\xf7|\x0d\
+F\x0e>\x0a\x16\x16&\x86\xf3\x06c\xd8 b\x04\xf4\
+\xbcv\x88\xb5\xb6A\xbc\x0d\xc3\xcdu\xf5\x90\x1d\x1b\x81\
+\x14\x0e?\xa7\xce\xbf\x0eC\xcf<\x09\x13gN\xc1\xf8\
+\xa9\x93\x90\x9bN\x83\x06\xdbU\xb6\x96\x90*\xecke\
+\x8b\xfb\xaez\x8f\x92\x09\xc0\xc6\x02X\x07\xa34\x02\x98\
+\x86f\x88`\x9c@\x17U\xad6\x039T]V\x22\
+A\xeb\xd4\x12!\xd4\x90q\x1cU\xa3M3]\xeb\xeb\
+ \x86\xf9v]\x0cbxM\xac.A\x8e\x8ai\xc9\
+\x8a\x04\x5c\xbd\xebd\xc07&\x82i\x05 \x12<\x0a\
+\xa7\x9d<t|\xe4\xd3d\x07\xd9\xb8A%\x91B.\
+fR\xc7\xe0\xc1\xbd`\xe5s\xb0\xf4\xd6\xf7@\xbc\xa5\
+\x0d\xa4\xeb@z\xf0\x02\xa4\x07\xfaa\xe2\xe8K\x0a\xf0\
+\xe9\xf3\xbd\x90\xea\xeb\x85\x5c*\x05\xb2\x00\xb2\xda\x16\x12\
+\x91Y\x17\x1f\xd4\xbe.\x93\xc7G\xf08\xcc\xa5p\x80\
+\xea\xd64>\xe3z\xa8T\xee\x22Q\xf5\x1a\x13\x1f\x01\
+\x04=\x84\xcdDq\xd2i\x95\xb4\xa4\xf1%l\x04<\
+^\x8f\xa0c\x8a\xd7\xd5\x11\x190\x0f5FC\x03n\
+\x91\x144W\x8f\x92%\x0al\x93\xba\x99c\x1em\x0a\
+6\xadP(\xa3%x\x22y\xf5\xf4)\x189\xfc\x0a\
+,\x5cd>\xcd\x8eP\xefl\x1be\x02\xc8\xbc\x9c\xc5\
+\xcf\xd0\xd2\xdd\xaf\x80\xf5\xdc\x01\xc8\x10\xe8\x17\xfa 3\
+<\x00n\xde-\xc4Hf\xc0\x93>\xa0M\xeb\xd6\xb5\
+\xe7j\xa0=\xa0\x83\x97\x0cZ;\x16\xf2\xa4,\x85\x00\
+|J\x98\xe6P\xa6\xc2?\x1b\x07l0\xc8\xb6K\x9a\
+\x9e\xe4f\xd3\xe8\x94!1\x92\x009KOW\xa3$\
+f\x88\x81\xa4 \x22\xc4(\xd1q\xa2@\x12\xcc\x07\xcc\
+\x13q\xd2&D\x06L\xb1\x19scS\x9eecR\
+\xf9\xb4U\xfd\xde\x13N\x0c\x1e\x1eq\xe0\x86\xee\xa3\xb8\
+8C\x1b\xfb\x12\xb9r\x7f\x80\x9f\x1b\x18\x18\x80G_\
+\x1b\x82\xf5'O\xc3\x8a\xf3'\x11,\xa3\xbe\x15\xe8T\
+F\x0d\xbekZ9#\x81O\xdd\x9b}a\xd1}\xfe\
+\x9e\x91k\xe2&\x11&\x80O\x09\xd3Z\xa0\xf2\xbf\x1c\
+\xea\xd7\x00\x94J\x8f\xf2\xd1V\x83\xaf\x13H$G\x06\
+\xf2\xb9\x8c\xaa,\x07\xf3\xb2\x9a\x1c\x82\x92!\x8b(v\
+L\xe0\xdbJ{\xa8\xd4\xdb\xd9\x05{\xdb\xd7\xc1e\xab\
+\x96\xc1\xca\x95+\xc9N3`\xab\xe5\x14\xea\x91\xc3\xf5\
+]\x1b\xe0\xe9\xb1qU\xc6\xe5}'u%k\xb0\x8d\
+\xf3_8\x90\xae\xb6\xc5Av\xde\xdf\xe5\x05\xe1\xd1\x00\
+\xa5\x9b\x82B/ \xc0\x7f\xab\x94\x00\xd2\xbb\x15V\xa4\
+\xd7/\xc0\x03\xb6!\x02O\xe6\x9c\xb9\xd6\x80\xed\xcf\xb7\
+\xccy\x22\x90p\xf3\x00\xb9<\xbc\xbex=\xfcta\
+\x17\x5c\xbe\xearZB\xc6\x10\x80\x83Y\x09\xf8\x81\xd3\
+\xcb\xe8\xa3P\xca\x7f\xa6\xa0\x85\x96\x9f?\x81\xc7\x1al\
+M\x04\xcfV\xb7j\x9f\xca\xf7\x01o\xda\x15\x11\xc4\x00\
+\xef#\x82\x14\xe1\xa8\x8aB\x85\xc9*\x13\xc0H\xa1\xc0\
+!\xc2\xe2\xb9\x82'C\x10\x03\xac\xaf\xb5s\xf0\xb96\
+\xe8]\xb6\x1e\xf6_\xb6\x03\xc1_E\xe0\xd3\x14p\x05\
+~I\x12=\x88\x14\xda\x15\xd4$ _\xe3\x19a)\
+0;\x91\x04\xbeV\x8f\x09\xbcdP@\x878}\xfe\
+\x16\xcfM\x01]\xa4\xfd\x8b\xd0n\xa0`\xe7+%\x00\
+'\x01!`\x8b\xa8\xd6o\xd4\xb9>\xd6\xc9\xa7\x0d\xb8\
+\x99\x10^R0\xf0\x8df8\x8fj\xff\xe0\xe5\xd7\xc1\
+*\x04\xfd-oy\x8b\x06\x9f\xc0\x8a\x021\x0a\xf4\x92\
+\x9dG\x8a\xfd\xd3\x17\xc2$\xcf\x14^\xba\xb3\xe7\xb8\x01\
+\xdc\xa7\xe2\x0d\xa0f\xdf\xeb\xf4\x05\xb4x\x03<\x0b\x8a\
+q\xd1\xa1`\xabv&@h\x14\x22\xc7y=\xac\x15\
+\xde\xe3\x00\xff\x00\x8a\x98\x81\x00\xf0\xfb\x96w\xc1\xa1\xd5\
+o&\xd0\xd5\xa2QZ\xed3\x09V\xff\x17\xed\x0f\x08\
+!|\x8b:\xd1\xf1s\x85\xd9R\xcbz\x8e\x15#\x81\
+q\xe6\xfc\xf1\x0d\xbf)\xf4\x86\xc5\x85\x0f\x80h-\xa0\
+\xf1\x1154\x01Rw\xcdJm\xfd,\x8f\x1ds\x0d\
+`\xb4\x03\x07\x7f\xc5\x06xb\xcd\x0d\x1a|\xfa\xe8\xc3\
+\xd8\xfc\xf2\xa5\xe2o\x0d\xf4\xb16\x07\x9a\x04\xcf+\x12\
+\x00t\xf8I`\xc0\xf5\xd9yN\x00i\xae1-=\
+L\x0bpbb\xaa\xad\x09\xa0Tn\xeb7y\x22B\
+#P\x0a\xf0\x0f\xfaWl\x84'\xd7\xa1\xad\xc7\x16\xff\
+\xe67\xbfY\x83\xcf\x00\xaaP\xcat\x0a\x0d\x11\xf4l\
+c2\x07\xe4\x13\xbcP\x88Y,}\x9dH`\x1a\x86\
+\x0b\xdc\xb37Q\xd2P\xe0\xa3\xb5\x80\x19\x0d\xc4$\xaa\
+n\x02\xcc\xf3M \xa8\xe2\xd6o\x12\xbfF'1\xcb\
+\x14\x5cX\xb9\x11\x9e\xeaz\x1b\x81O\xcb\xc4i\xf0\xc3\
+\xa6f\xd7\x8a\x10\x0c|\xaf&\xa0\xf5\x09h\xffE|\
+\xe9\xad\xb8]z\xee(@\x80\x83G\xc7\x92\x01\x1d\x05\
+<\xd7\x02<\x0eP\xd3^\x80UZ/@\x04k\x04\
+\xde-\xe4\xf7\x99s\x04\xfe&xz\xe3N\xb2\xf5\xb4\
+\x08c\x90\xda\xaf\x84\x08z%\xcf\xc0\xd0q4\x09\xf8\
+\xc7'z\x91\x8a\x97\xed\x19\x9f`\xf1\xb9n\x05\xbc\x15\
+\x06t\xb4\xdd7y\xfe\x095\xdc\x07\xa8u/@=\
+\xc4\xcf\x01c\xc3\x81\xf5\xed\x99F`=\x00\x11\xac!\
+\x06Wm\x86\xe76\xef\x82\x95+V\xd2\xda\x80\x04\xbe\
+\x06MK\xc5$\xa0Q=\xfa\x0a\x88\xae\x1d\x1c\x1c\xf4\
+\x8e\x22\x86\x80\x1f=c\x98\x1cCZB\x86H\xf0\x8a\
+m\xab\xf2-|\xad\x1bd@\xdf\xde7\xe8\x22B\xc8\
+\xa0\xcf{\xef\x9d}\xdaV\xf8\x98\xdb\xaaj\x02\x8c\xae\
+\x0f\x9a\xd6mR\xa860\x89\xf7\x08\xcc\xf1\xd0\xe5\x9b\
+\xe1\xf9-o\x87\x15\xcbW\x10\xf8\xf4\x81'\xeb\xeaE\
+\x11\xc1\x80\xc5\xc1\xa7/\x84Zp\x14S\x16\xae\xbdp\
+\xe1\x02\x91 \xda\x0c\x18\x92\x153\x05l\xb5\xcf\x97-\
+\x1b6\x82\x80\x85g\x8fxL\x01w\x00\x95\x96(\xe6\
+\x04\xd2\xc6O\x1a#\xb3FG\xad\x82-\x95U&\x80\
+\xdf\xc6\x84v\x03MR\x9b\x08\xff\xc0\x10\xc6O\x84\xa1\
+\xd5W\xc2K[o\xc5\x96\xbfB-\xbf\xda\xd9\xd9I\
+\x95Y\x0a\xc0%\xb7|\x02\x7f\xf0ow\x83\xeb\xe4a\
+\xf1\xe7\xee\x01\x12\x22A&\x93)\xc5/`\xa0\x17\x09\
+\x16\x19M\x10\xb3U\x09\x17\xbcz\xd8O\xf8R\xec\xfc\
+l\xd2\x801'R\xfb\x11&\x0eP\x0b\x13\xc0#M\
+>\xf1\xab\x7f\x03\xae\xc9\x8f\xe8\x1d\xf8\xaf\x1dY\xbd\x05\
+\x0eo\x7f'\x81O\xab\x81\x12\xf8\xe1-\xdf\x80\x10y\
+\x9e~\x87\xc0o\xc6\xf1\xfc\xa1\xff\xb2\x1b\xd2\x8f\xcc\x00\
+?Dj\xfa\xcf\xd4>\xfd\xcd\x22\xa5\x09\xa2G\x07\x03\
+\xbba\x8c\x04D\xdeW,[\xe5\xcd?\xf3\x8a\x0fP\
+\xab\x08\xf0\xd276\x10\xd0\xdb\xf2\x10B\xb2\xe7WG\
+\x03pM \x8c\x0f\xe0\xc3S\x14R\xb4F\xe0>\x82\
+'ot\xed\x16\xe8\xde\xf1\xafH\xed\x13\xf8\xfao\xec\
+D}\x9f\x1ft\xde\xb7\xafg\xf2\x10\xf8\xc3\x7f\xb7\x1b\
+2{\xef\x01\xad\xcc\xb2\x8f\xdd\x07\xc3\x02`\xc1g\x0d\
+\x09P\x13\x04=\x8b\x01\xadS\x10\x09h\xdd_\x22\xc1\
+\xe1\x98\xad\x1c\xc3y\xa7^\x06\xe1\x03\x9e5\x08?I\
+|f $\x12h\xd5\xc6\x070[\x0b\x13\xef\x06\xf2\
+\xd6=[\xfd\xcfV\xf5E\xfc\x83\xb1\xb5W\xc1\xb1\xeb\
+\xdeE\xb6\x9e\xfe\xba\x16\x03?p5N~>t\x02\
+\xe7\x08\x82\x9f}T\x83o$\xf7\xd3\xfb`D\x00\xb4\
+\xff\xa9\x8f\x04L\xcd\xe3~X\xf2M\x1c\xa1\xad&\x01\
+\xad^FyG\x90\x08+\x05\x92\xe0\xe4K`\xcdn\
+\xf1\x8c\x10\xbe\x06\xe4'\x04\x80\x8fD\xea\xbcmB\xcb\
+Jj1\x18\x14\xe9\x02h\xc0!J\xfd\x9b\xeb'\xd6\
+m\x85Soy7\xac\xe8\x5cN\xeb\xff\x12\xf8\xd4b\
+\x18\x98\x95h\x01=u\x9b\xc0\x1f\xfd\xdan\xc8\xfdD\
+\x83\xcf%\x8f$\x18\xc5\xed\xfcp\x120\x90\xa3\xb4\x01\
+%r\x0c5\x09\xba\xed\x98\xd2\x04\xcd\xc7_\xf4:\xc3\
+\xc6\x114\x00\x07\xf7\xf9\x85\xf9z\xd7\xf1\xcf\x09\xac\x9d\
+\x09P\x05\xb3-\xf3>\x82c+|\x19A\x041\xa7\
+'\xd7]\x0dgn\xbc\x8dl=\x81\xaf\xff\xbaV\xb1\
+\x96]\xa6\x160\x1fm\x10\xf8c_+\xb4|\xafY\
+bk\xeb#\x09\xf6\xdd\x07cx\xa2\xed3E\x1d\xc3\
+b\xe0j2Dh\x03C\x02\xd2l\xa4\x09:\xc0\x82\
+\xc6\xe3\xcfs\x80\x85\x1f`\xa9\xb2\x82\x9dEa\xba\xe3\
+t\xae\x96&@\x18V\x82o\xec\x9e\x89)H0A\
+\x92]W\xc3\xb9]\xef\xc7E\x18;i\xc9uZ\x97\
+G\x83_\xb1\xad\xd7\xe7\xcc\xe7Z\x0d\x08\xfe]\xa0\xd5\
+\xbee*\xcbG\x00u\xabE\xfb\x05\x12\x80\x8f\x04\xfa\
+\xe3\x13\x06.\x07\x9f\x93\x02\xc5\xab\x09\xe8o\x06\x164\
+\x81\x0d\x8b\x01\xa0\xe1\xe8\xf3^\x80\xcdVrs*\x03\
+\xd1\x15:\x12\xa8M@M\xbb\x81\x06Ls\x10\x16\x1f\
+`\x92\xea\xda\x06=\xb7\xdcN\xea\x9e\xc0g\x7fc'\
+\xa0UG\x02O\xa2?\xd4\xd4\xe0\xe7\x1e\xbd\xdb7\xc9\
+\x04f\xbf\x97\xd4\x0b``\x92\x9c\x04B\x08M\x02\x03\
+fx\x0a\xd5\x14\xda' \x92vcj\xa7\xf1\x84\xc3\
+\xcf\x85\x03\xac\xdf\xdbx\xffL\x84\x1e\xaeW\xe5\xa8\xb2\
+\x090\xf3\x01`\xd6\xe39\x09D\x04A\xa67n\x87\
+\xfe[\xef\x80\xcee\x9d\xb4\xde>\x81o\xbaz\xd1\xea\
+=\x8c\x14\xf4;\x85\xaft\xeb5\xf8\x1axC\x80\xd9\
+\xa3s\x1a|\xda\x9aO\xb6\x98&\xc0\x88!'\x01\x07\
+8\xd2,h\x12\xd0\xd2\xb3\xb4\x7f\xcc\xfe\x84z\x99\xc4\
+\xe1gA\xfb\x01\xb2h\xd7/\xa0~-\xefX\x00\xd4\
+(\x10$0\x15\x0a\x15 \xa6\xa2Cz\x09\x99\xcd\xdb\
+a\xe07>\x00\xcb:\x0d\xf8\x1e\x9b\x1f\x01v\xb4\xcd\
+\xd7\x8b3\x8c\xfe=\xd9|j\xf9lv\x91&\x80\x11\
+/\xf8\xe0\x9d\xae\xcd5\xc1\xd0\xd0\x10\x91\x80\x01\xca\xc9\
+\x10M\x10M\x02*\x7f\xb7u'4K,\xc3+\xcf\
+\xfaL\xbd4\xe0\x078\xdd\xe6\x9ce\xcfL\x92\x95\xb5\
+\xeb\x05\xa8\xc4\xc5o\xdf\x03%\xbb\xe9\x1a\x18\xf9\xad\x0f\
+\xc1\xb2\x8ee\xb4\xc6?-\xc7F-\xb6\xdcV^t\
+_\xaf\xc9\xa3\xc1\xcf \xf8\xbeh#\x9f~\xe6\x11C\
+\x00W\xf2\x99;\xd4;\x18\x93H\x82?U$\xa0\x8f\
+O\xf4\x00R\x04\xc8\xfc\x18\x85\x99\x03\xfa[\xc9t|\
+\xcc\xbaKU\xa0\xfd\xd23|\xb9V.\xfc\xbc%\xaa\
+\xee\x04\xfa\xbf\xdd\x0c\x09\x05\x0b\xff\x01\x93\xfc\xe6ka\
+\xec\xdd\x1fFG\xaf\x83\xe6\xd3\x19\x9b\x1f\x0dn\xc89\
+\xa3\xf6\xf5\x9a<#\x7f\x7f\x17d\x1e\xf1\xb5|\xd3-\
+\xf5k\x02#\xa6\xf5\xb3\xe1[\xdd\xdb\xc9\xee\x9b\xe9\x22\
+\xb6\x7f\xf6\xeb@2::J$\xf0i\x01\xae\x0d\xa2\
+\xc9\xa1'\x9a\xd2\xda\xc6t|\xdc\xfaCHH\xbc\xee\
+\xa5\xa7Y\xc4\x8f\x89\xd0\xe7\xd9h`\x0dz\x01\x9a\xb9\
+E\xf0\x17\x11\x19r\xeb\x0e\x98x\xcf\xef\x91\x97O\x13\
+'\x0c\xf8\xd1}\xfb(\x82\x98\xa5\xd8\xea\xea0\xc2\x87\
+\xe0\xef\xdd\xc3\xcd\x10\x9fuD\xc9w\x91\x99\xcd\xeb\x8f\
+\xc5KO\xf4-C\x11C\x10\x141\xa4g\xd3\xb7\x88\
+\x9a\x04\xd1\x80\xf3}6\xdb\x98V$W$\xf8\xd0\x1f\
+A\x9c2_|:\xb4\x8e\xfd(\xebo%\xa0\xc6&\
+\xc0\x16!\x04\xe0\x99\x895\xeb!\xfd\xe1?\x82\xa5\xad\
+\xea\x0f:\x90\xda\x0f\x1a\xd2\x0do\xf1|\xdf\xb7\x08\xe3\
+\xd0\xdfRl\x1f\xc1\xb7\xc2\xa2\x92|\xd2\xa9\xd0\xaa\xbf\
+\xe8$\x0d\x1e}K?\xfa\x0d\x18\xc2\xedBC\x02\xbd\
+\xb61\x03:,i\x09\x22\xc1\xa9\x8f~\x1a\xec\xb1\xbf\
+\x02\xf7\xccIS?\xa1\x04\x90T\x9e\xb2\xc7\x02\xacR\
+M\x80\xf12M\x14%L\xf4\xf9\xe5\x9f\xfc\x0c,]\
+\xd6I-\xdf\x80\x1f.a\xb1u\x9f\xcd\xd7\xe0\xd3\xa8\
+^\xea\xc7{\x82m$\x14\xd5\x08|~\xa2aKh\
+\xa4s\x1aI0\xf8\xd5\x8f\x91\xbfA\xb1\x06r>\x09\
+t\x9d\x18\xd8\xc5\xf2\x83\x84\xcaCs\x1e\xd7um\x80\
+\xf6\x8f}\xaa\xbc\x857tAj\xa1\x01\xa4~\x88-\
+\xcaz\xa9U;\xdf\x0eY\x10\xa4\xa6K\x05?\xb2\xf5\
+\xeb%\xd7i\xbd\xbf\x81\xbfQ\xe0\x13\x90\xbfTI!\
+\x09\x06$\xc0\xe2\x7f\xaf4\x81Z\xbd\xccq\x9cR#\
+\x84$\xa1$\xa0\x19PK\xda\xe6\xc1\xc0\x7f\xfc\xb7P\
+\xa2\x18\xdf\xa6\x96&@x\xbfQ\x12\xd176#H\
+VK+\x9bvU:\x09\xf8*\x18z\xbd\xfd\xfe\xaf\
+\xee\x86\xa9\x1f\xed\x01;\x08|\xe9\xe9\xdf\xcf\xcew1\
+Y\xa6\xdf\xefB\xc4*\x9e\xfa\x94\xe7|r\xef7\xc0\
+\x95\x02\x96\xfe\xf9\xddz\x81k2\x07\xd1\xaa?Z\x94\
+vkp\x1d(]\x8c\x13\xa8\xa4&&\x80\x0aac\
+b\xe7\x83o\xea\xfd\xc1\xbf\x90mSj\xb2\x0ca\x95\
+\xa6\xc3\xbb\x1a\xfc\xbe\xaf\xec\x86\x89\x1f\xec\xd1x1\x80\
+\x0d\xa2\xe6\xbcK@{\xbe\xdeu\x5c\xef1%~\xbf\
+d?\xe7\x7f`\xf2\x91{\xe1\xfc\x97?\x8e\xad\xb6\x8e\
+\xb4\x1c\xbdc\x90\x16(k\xd2\x0ai\x81\xbe\x87\x1fb\
+U\x1aV\xe9\x0a\x9bj\x13\x80\x87\x82\x8bx\xf9!7\
+\xbd\xf8\xf9\xcf\xc1\xf8\xd1W\xa8@\x9a\x04\x95\x10\xc1\xf7\
+gV\xce\xff\xe7\xdd0\xfe}c\xf3\x0dH\x06H\xde\
+t=\x81\x1e\xa9\xc9`H\xe0\xfb~\x1fT\xe2\xc4\xe0\
+\xbf\xa96\x13\x0f\xe3\x12\xf0\x7f\xfdq|\xb78-\x1e\
+A$\xf0\xf9\x04(e\x83?q\xfc\x08\xbc\xf8\x97\x9f\
+\x8d\xaac#\x9ap\x16T\x99\x00&\xd1\xd5,\x0e\x10\
+\xc5N'=\x0d\xfbn\xdbuQ$ \x9bOZ\x84\
+\xc0\xef\xf9\xf2n\x18\xfd\xbf\x1a|\xd6\xea\x0d\xc8\x1ah\
+\x93\xccB\x0d\x06t\x93\xcc5\xfe\xa9V\xd2\x9f\xcc\xae\
+\xb9\x9ed\xfc\xc7\xf7BO\x81\x04\xa8\xa5\xe8\x9d\x09\x90\
+\x8a\xc0\x9f<\xde\x0d\x8f\xbf\xf7fpRS\x10j\x95\
+\xa4g#MW\xb7\xda&\x80OZ\x10\x01D\x09P\
+M\xd9\xd1\x11\xd8\xff\xbe\x9ba\xe2\xd8\xe1\xb2I@-\
+H\xdfs\xeeK\xbba\xe4\xa1=\x06`\x7f\xec\x9e\xdb\
+\x7f\x7f2$\xa0\xe4\x86$C\x16\xad\x11\xfc\x04\x01J\
+\xdc\x5c\x8c\xfd\xf0^8\xf7\xc5\x8f\xd3\xbb\x12a\xe9\xdd\
+\xcb\x07\xffD7\xd6\xd5.\xc8\x0e\x0d\x9a2\x84\x80\x22\
+\xa5\xd7A\x87\xaa\x9a\x00.\xda\x04\xc8\xa2\x0f1\x95\x0c\
+\xc5H0\x0c\x07\xb0`\x13\xc7\x03H\x10\xf1\xb7t_\
+\xfbk\x04\xff{{\x02AV q;\xcf\x01\xf7\xd9\
+~v\x8f\x01\x9f\x11(\xcc\xbf0\x84\x19\xf9\xc1\xbdp\
+\xf6\x0b\x1f\xa7w\xa6w\xa72\x94\x05\xfeA\x02\x7fx\
+\xd0<\xa6\x14\xa7\xd4\xd7M\xaf\xa1\x090\xc3\x8d\xc1\x17\
+\x9a]\xdeJ\xb2#\xc3p\xe8\xfd7\xa3\x8a;\xc2H\
+\x10\x06\xfe\xab_\xdc\x0d\x83\xff\xc78|FM{\x9e\
+\xe1\xcf\xe3\xad\x9e\x11A\x1f\xb3|c&\x98\x06a\xa4\
+)\xaa\x11F\xbe\xffux\xf5\xf3\x8c\x04\xe1\xe0\x9f\xec\
+\x86'~g\x17dF\x06\x99\xca\xd7\x19\x81Y\xae&\
+\x00\xd4\xd8\x07\x10\x04\x8c0\xf9Q/\xc8\x9c2\x22\xc1\
+\x10\x15\xd4K\x82\xd0?\xa4|\xe6\x0b3\xe0\x03\x03\xbe\
+\x90\x0c\x88\x8c\x1c\xae\xda\xf7m\x8d\x160\xa0\x17'\x81\
+I\x06h\x93\x02\xc8h\xf2\x86\x1e\xfa:\x9c\xfe\x8b0\
+\x12\x18\xf0\x93\x08\xfe\xcf\xb0N\xd2C\x83\x86\xd4!N\
+'\x9f\x17\xea%\x80\xa0\xbdZ\x98\x00\xe1_\xcd\x889\
+B\xe16\xca5eP$\xf8\xd9\x1dH\x82\x13G\xc8\
+V\xea?\x9fJ\x8e\x139z\x94\xa7\x8eO}~7\
+\x5c\xf8\xee\x9e\xd2*\xde\x0b2\xb3\xf7\xe1v\xdf\xa1\xc4\
+\xae\xd5\xe4\xe2&\x81\x83^\x9c\x1c\x83H\x82\x93\xffI\
+\x91@;\xb1TFM\x0a\x95\xa7\xc0\xbf\x1d[\xfe\xf0\
+`pc\x8a\xa8kn\x02d-\x02AR9\x19\x86\
+\xc8f\xe0\x5c\x9a\x15/\x8c#\xe8\xb2y\x81\xa6\xc5\x12\
+\x09\x86\x87\xe0I$\xc1\x9b\xef\xdf\x07\xad]W\xaa\xca\
+\xf1\xca\x89\xbf\xd8\x0d\x03\x08\xbeey*Xx+\x99\
+\x1f\xbb\xc4O\xbd\xef\x9a\x90\xafY{\x98\xcd\xab\xe7\x9f\
+\xc0\xbb\xdc\x84\x98}\x9d\x82H\xc8\x890\xf0\xbd\xaf\xab\
+k\xd6}\xe9n\x02\xdf\xd7\xbd%\x7f\x88\xea\x80l\xbe\
+O\xbcZ\x0c\x02\x9dN&\x96\xed\xa9sY\x0b\x1f@\
+\x84\xda\x18\x03\xb0,-8\x93!M\xf0\xee\xeb\xe1\xb5\
+o\xffO\xea\xf2\xa8R'O\x1d\x85\x17>z3\xf4\
+=hZ>\xab\xdc PLk5[\xae\xde\xfd-\
+\x9f\xf5\x00\xb8\x16\xe0\xa6@\xefG\x13\x81\x8e\xfb\x91\x04\
+/\xfc\xdeN\x98:\xd5\xad.t\xa6Sp\xee;{\
+\xb0\xec\xd7\x11\xf8\xe6Zo5\x85;\x80<\x82\xa9\xf1\
+\x11\xa2z\xa1`>\xa3'\xa8\x9b\xc1[\xbd)\x8ci\
+mRp\xbf!\x8f\xc0\x1f\xfe\xf3\xbb\xa0\xfb?\xdc\xe5\
+\x1f\xc3\xb7\xbc\xd3\xb4\xb8\x160\x1e\xb0\x09\xeb\xbafm\
+T\xad\x91\xf8\xa4\x067\x8a\xf0\x5c\x0bpRq\xf3\xe2\
+\xbf\x9e\x13c\xec\xe9\x03\xf0\x8b\xdf\xdc<s\x8f\xe3\xf1\
+C\x98I\x0b\xa8\xd7R\x08B\x15W\xd3\xb1\x00A\x89\
+\xbf\x9b\x998\x11L\x0a\xe9%\x85\xf4\x83\x22\xbc\x15\xa0\
+\xaf\xe5y\xba\xe5\xf9&\xcf[\xe67\xf5\x08\xaewM\
+a6\x1c(eX\x1d\x19\xc2\xf2\xdeD\xb8O`R\
+8\x11L\x9eF2<j)\xa3\xa2\x92\x92\xed\xd7\x86\
+\x00\x82\x92%\xf8h\xa0\x07 W_\xeb\x03.XK\
+(\x89\x04\xde\x7f\x0c>\x0d`\x9ei\xb9\x851\xfdb\
+\x5c\x95&\x83OV\xf5\x1bY\xd7\xa7b\x03}\x01\x9e\
+\xe7M\xe5\xf5\x18\x8c\xc9\xe1`s3\xca\xbb\xdbFD\
+\xd5\x09\xa0+H\xbf\xac\x8cx\x86\xbe\x96\xb5x\x1f\xf0\
+\x02\xbc\x05\x0c\x03^\x83l\xde\xc3\xd2\xe7\xe9'\x8d\xba\
+W\x22\xe8X\x14\x88 \xbd\x1a\xc0\xcff\x8b\x03oZ\
+\x9d\x8f\x00Q\xa6\x80\xfb\x1f&\x85\x82n\x12\x037\x5c\
+\xfdK_\x0c\x22*2D\xc7\x15\x10\xc0.hm\xfd\
+\x97\xc2tH*=\x99\xa1\x85\x9f\xd5\xd2\xadN\xd6\xfb\
+\xde\xbc\x95\x9a\x93\x9c\x9dRFy\xf6Av\xdeoB\
+,/\x09\xf4\xb1!\x82\xe9\x91\xd0\xbe\xf0\xbc\xd6\x0cA\
+\x98\xb8\xb3[\x17\x07\xd4\x98\x80`m\xc0\xbb\x9f\xa5\xf5\
+\x18\xfc\xf7\x82I>\x82\x05\xa8\x7f\xc2\x84\xb0\xc9 F\
+TX\xa1\xca,\xf5\x8c&I\x98\xe6K!\xc0\x08\xa6\
+%\xfa},\xcb\x8d\xcfk\x81x\xbc\x1e\xa4\xe3\xc0\xf4\
+h\x16\x1a\x97\xb4B]k=\xe4RY\xd0\xe2k\xb5\
+\xc6\x8eF\xdby\xc9\xc9`\xfc\x03\xaf\x9d7\xe7\x8c\xba\
+\xf7\x93@\xa8\x8b\x02\xbb}\x85\x8a0\x8e\xa0`<\xf5\
+\x1f\xb8\xe1\xddB\xee\x17\x84\x98\x00(\xa3\xc7 C\xba\
+z|P\xcaH}[#4u\xb4\xc1\xd4\xf0IH\
+\xe0\x88\xa4\x93\xcbA>\x9fQE)\xf0_\x8e\x94B\
+\x80.\xbcat\xe6\xb7\x1d!e>^_\x97mh\
+_\x94\xb0h\xfa\xb6h\x05\x22\xc4\xa2-\x9d\x90\xec\x9f\
+\x00#e\xday\x19\xa0\x05\x14\x90\xdc\xf37\xde\xbd\xfe\
+y?\x09\x84>6\x7fj\xc6 \xa8\x89\xc1\xfe\x22Y\
+\x88\xb8\xcc\x170+\x81\x1bR\x98\xae`HWT\xb2\
+\xf1\x06\x16J.\xcb?0\x04\xf3\xaf\xdb\xb0\xec\xba\xb5\
+\x10on\x80\xf1\xa1\x8c\xfa\x9b\x0dnr\x12,\x07\xa8\
+\x95\xe6\x08KL\x92\xb0\x8d\x8c\x03\xd0\x1d\x85^J\x1e\
+\xa4L\x0b\xd7MZu1\xb5\xfc{v\x1a`\xf0\xf8\
+8t\xdd~\x0d4-n\xf1c\x1e\xf0\xb2A\xf6\xcf\
+\x0d\xa9\x18\xa9\x13\xef{s\x1b\xecz\xce\x05l)9\
+\xe682928D,\xdd\x90V\xaf\xaf\x09\xf2\x0f\
+\xd8\xe8e\xb4\xcf\xc0c(\x9c\xc4\xad\xcb\xdba\xfd{\
+\xf1;\xcbg{!9\x9aQ\x84\x90\xe0\x92)\x9f\x14\
+\x00\x19\xc2\x920\xcd\x96\x12\x08\x1a\x9bQ\x0bn\xe1\xc6\
+);\x9d~U\xda\x16X\xf5\x0924\xd0\xfb\xc28\
+\xc4\xdb\xe6\xc35\x9f\xde\xe9!A\xa8\xf3\xc2\x0b\xc6\xae\
+\xe1]%7X\xdd\x9a\xfd\xc0\xf0\xad\xc9s\xf8~t\
+\x92\x0cx\xbe\x0d\x18k\x08xw^\xbe\xa0\x14@\x04\
+\x17\xf85$-\x08\xfe5\x7f|\x0b\x1e\x0b8\xf2\xd8\
+\x19R\xa7\x0aU\xc7\xc9C\x03\xc0\x19\xc2\x90\xb0$L\
+\xc7J1\x01I\x00\xd9\x86\x8cq\xf1&\x010\xd1\x94\
+J?;\x95Ln\xafokC\xfcQ\x0bL\xb9p\
+\xf2'\x03\xb0\xf6\xed\xab\xe0\xa6/\xdf\x06G\x1fx\x16\
+\x06_\xee\x81\xccD\x9aj\xc7\xf7\x19\x16%\xf3e\x0e\
+\xdf\x82\xa0\xc4\xaf\x05\xb3\xef\xbb\x06\x84?Iu\x9d\xc7\
+\xc9\xa3-\x1dz\x8f\x85\xdf!\xf6\xafO\x10\xc0_\x9f\
+#hH\xaa\xb6\x96\xc9S[\xcb\xe4{;\xee\xa2p\
+\x9d\xa0\xe4\x9a{\xa0p,<[\xcb\xf57\x08\x97\xf2\
+\xcd\xbd*Y\x9e\xdf\xb6m\x0b\x12\xf3\x1a`\xc9\xd6\xcb\
+`\xe3\x07v`F\x0c\x9e\xfc\xc6K05\x92\x06+\
+n\xa3\x7f\x96\xc6\xdf\xc8\xc3\x02\x17\x9e\x05\xc4\x90\xb0\xc4\
+\x94'l#\x09@\xc1\xca\x9b\x94\xbaP\xac\x19_\x99\
+\xcd\xef\x7f\xb1\xbf\xff}\xce\xd2\xa5\x0b\xe3M\xcd\xca\x10\
+\x8f\xf5&\xe1\xe5\x7fI\xc1\xf2m\xf3a\xeb'w\x81\
+3\x91\x84\xa9\x0b\x13\xe0d\xf2Xp\xbe\x02\x16\x89e\
+\xec\xb5\xb9\xc6\xf7\xa1\xa6\xf7>\xbe\x8a\x18\x04]\xe3\xcd\
+\x9f\x0d0\xe5W\xd2O\x96E\xc2\xae\xc5\x8e\x8b\x13\xc5\
+\x10(\xe0X\x93\xc7\xdc\x17\x14\x80*\xfe\xdbv\x22\x06\
+\xcd\xd8\xf2\xed\x86z\xe8y\xbe\x0f\xba\x1f?;\xa3\xfa\
+\xd1T;\xa9\x0cd\x93IH\xb80\xb8\xd6\x85\x83.\
+b\x98G,\x13\x00.a[\xd27\x1d\x8f\xcf`R\
+\x87\xff\xb4\xbb\x00\xab_\xb5\xc5\xed#\x9d\x1d\x9fZ\xb2\
+e\x8b\xb0bqp\xe8\x0f>d\x90\x22\xa8fb\x09\
+\x89\x0c\x1e\x85\x96\xc5MP\xd7\x5c\x07B\xd7z\xd4W\
+C\xc2l\xf8\xb5\xfc\xbc\x14\x81\xd7F\x03,\xa0r\x99\
+\x0d~h\xd4\x8d_\xc3\xaf\x8f\xf8=\x19\x1e\xdcs]\
+\x09\xf9\xb4\x03\x99\x14\xc0pO\x12Rci\xd5U'\
+'\x9d<\xff\x89\xbe\xf3\xa8\xa5\xa7\xe4Z\x07\xfe\xf1\x0a\
+\x17\x1e\xb4\xd0\x0c\xb83\x9d\xbb\xccN\xbc\xbd\xa48\xc0\
+\x01\x00\xf9\x0e\x80\x9c\x03\x90\xc4;.\xacr\xe4#\xc9\
+\xbe\xfe+\xfa\xa4{k\xfb\xe5\xab\xc1\xaa\xabC\xecs\
+\xea\xafW\xa6\xc6\xd30\xf6\x1a\x9a\x80\xe4DTC\x0a\
+>_\x85\xebd\xc5\xe7\xdexB\x7f\x94\xab\xbe\x15M\
+\xb2m\xab$\x10\xfc\x5c\x12\xc9\x80\x83k\xd9T\x0a\x16\
+\xb9\xf0(\xb6\xfe\xbd\x80\xd8Y\x88a\x1c\xb1|4\xa0\
+\xa8v\xb1\xcc\xfd\x98\xde\x87\xa9\x19@N\x93C\x88i\
+\xb1+\xcf\x0c\xa7\xa6\xe6\x0f\x8f\x0c\xafqs9\xd5\x1e\
+]\xc7Q)7\x9d\xc24\xcdg\xab\x5c\xe2\x04\x90\xf0\
+\xc6\x14\x9b\xbe\xb5\x88\xc7@\xd2\x7f\xf9<\x06\xe8& \
+5:\x8c\x9a!#\x09\xfcm\x0e\xfc3\x00\x9c\xcd\x03\
+\x0c6\x02\x9e\x02p\xee\x0c'\x00\x97+\x00\xe4\x22\xdc\
+\x92\xed\x903}\xc9\xecR\x17\x8e\xa1\x9a\x19\x1d\x9e\x18\
+_=5>\xd6H\xb6&\x8b\xe0\xe73\x19p\xf3\xb9\
+\x80\x0a\xad}\xe5K\xf8u\x17>\xfd\x1b\x1b!:{\
+\xd3\xa8y'!\x97\x9e\x86x\xde\x1d\xbc\xdc\x85{6\
+\xbb\xf0-\x02\x9fZ\x7f\x0c \x99B\xec\x9eB\x0c\xf7\
+Wb\x1d\x1f\xc7\xf3\x13\x00V+\xf2@\x024\x09\x80\
+v\x0a\x14:\x00\x9dg,\xb8i\xd4\x82k\xa6\x01V\
+;\x02\x9a]\xbc\xa6V\xa0\xc9\xaa\x9f\x7f\xe3\x13\xc7\x02\
+\xc8\xfe\xbf\xf6\xce %b\x18\x0c\xa3/I\xe9\x8c\x8c\
+\xcc\x0c\x1e\xc1\xa5\xa7\xd0\x8d\x9e\xc0\x03x\x12\xebI\xbc\
+\x95\xcb\xd9\xb9\xb48Hal\x9b\xc4/\x18A\x17\xe2\
+\x14\x1dWy\xf0\xb6%\xe1\x0b\xfc\xc9\x1fH+x9\
+\x8al\xd2n?m\xf8\x1c<\xa6\xe0#\xb4\x06:e\
+\xd7/!\x5c|?\xd5\xbd\xeev\x8c\xea\x87]A5\
+\xc0|\x84\x14\xf6\xcaJ`i`\x11a\x06T\xd2Q\
+\xf8\x0f\xbc\x1c?z5\xf9\xa8\xb7\xb5\xb2z\xaf\xf9\xbb\
+-\x8c\x97\xb9\x0d\xfc\xab\xdb@\x03\xf1\x1a\xc2\x0d\x0ck\
+\xf0#\xf4@g\xe1)\x05\x9f49\xfc\xf0\xe9\xb7\xbf\
+\x14\xfe\x1c\xf3\xf513\x1f\xf3\x22H\x06\x89t0\xb4\
+\x10\xee!^\xc9\x9f\xbf9\x81\x06\xcc\xadT=\xb1\x1d\
+\xb8\xb9\xac\xc1\xbeJ\x97{5\x1eLO\xe1\x10\xd4\xd2\
+A\x0c\x80\x878\x83\xd0\xcb\x1d\xf8\x85<\x87p\x07\xb1\
+\x91\x13\x16\xd5t\x1ay\x06\xe6X\xae\xf3\xc06)x\
+yB\xe1\x90\xb4\xb2\x86x*{\xe09wo\x1fd\
+C\xa1P(\x14\x0a\x85\xc2~\xbc\x01\xc5\xf3\xa3!\xeb\
+\x0d6:\x00\x00\x00\x00IEND\xaeB`\x82\
+\x00\x00<\x0e\
+\x89\
+PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\
+\x00\x00\x80\x00\x00\x00\x80\x08\x06\x00\x00\x00\xc3>a\xcb\
+\x00\x00\x09\xediCCPICC Prof\
+ile\x00\x00x\x9c\xad\xd6gTS\xd9\x16\x07\xf0\
+\xff\xbd)\x84\x04B\xef- \xddP\xa4Jo\x8a\x0d\
+\x18D\x14\xb0\x02!4)\x11\x82(vP\xb0\xa1`\
+W\xb0+v\x05\x95Q\xc7\x8a\x0a\x22\x8c\xa24\x11Q\
+, 8\x22\x1d\x0b\x82y\x1f\x82e\xd6\x9bY\xef\xcb\
+\xdb\x9f\xf6\xd9k\xdd\xb3\xce\xf9\xed}\xd7:\x80\x94b\
+\x98@\x10G\x02\x88O\x10&\x05L\xf0\xe4\x04\x87\xcc\
+\xe4H\xd4\x81\x0a5H\x03\xb0\x0f\xe3%\x0b<\xfc\xfd\
+}\xf0\xaf\xf1\xb1\x1e\x04\x00\xd4\x98\x85\x09\x04q\x89G\
+\xa3\xab\x11\x97\x97\xa9\x92\xe3\xc2\xe9\x9f\xab\xfb\xf8\xdf\xbf\
+\x03\x00\xb0\x93\x82Cf\x02\x04\x17\x80b\x948w\x07\
+\xa0\x18.\xce\x03\x01(\xa6\x0a\x05B\x80\x88\x06\xa0\xc8\
+\x8b\x0e\x8b\x00\x88\xa5\x00\xb8I\x81\x01^\x00q\x1c\x00\
+;J\x9c_\x06\xc0\x0e\x17\xe7\xe5\x00\xd8\x0byQB\
+\x80h\x00(\xf2\x09\x111\x09\x00\xb5\x03\xa0\xbbF\xf0\
+\x93y\x00\x8b\x0b`^D2/\x1e`m\x04`\x19\
+\x1f\x9f\x18\x01\xb0\xae\x010\xe6\x09\x92\x84\x00\xab\x05\x80\
+Yp\xc8L\x8e\xf8\xc8\xe1\x91\x80u\x08@\x1e\xffY\
+\x9b/\x05\x14i\x02\x8a5?k&\x11\x80F\x01p\
+\xf5\xc4\xcfZ_\x00\x08\x00\x84rUr\xa4\xb5\x15\x00\
+\x80\x90\xf2\x04h/D\xa2>C@b\x0b0\x9c+\
+\x12}=$\x12\x0d\x1f\x06(M\xc0\xad8^J\xd2\
+\xc2\x11/\x82x\x00\xfc\xaf\xb5\xf8\xce#A!\x00\x02\
+$\x95\xce\x90dI\xb1e\xe4\xe4\x15\x94\x94U\xd54\
+4\xb5u8z\xa3\xf4\x0d\x8d\x8cMGs\xcd-,\
+\xc7X\xdb\xd8\xda\xd9\x8futrvqus\xf7\xf0\
+\xf4\x1a7\xde{\xc2\xc4I\x93\xa7\xf8\xf8\xfa\xfd\xe6?\
+5 p\xfa\x8c\xa0\xe0\x90\x99\xb3\xe6\xcc\x9d\x17\x1a\x16\
+\xce\x8b\x88\x8c\x8a\x8e\x89\x9d\x1f\x17\x9f X\x90\x94,\
+LY\x98\xba(m\xc9\xd2e\xcbW\xac\x5c\x95\x9e\xb1\
+&3k\xed\xba\xf5\x1b6fo\xca\xc9\xdd\xb2u\xdb\
+\xf6\x1d;w\xed\xde\x93\x97\xbfw\xff\x81\x83\x87\x0e\x1f\
+9Zp\xec\xf8\x89\x93\xa7N\x9f9{\xae\xb0\xa8\xe8\
+\xfc\x85\x8b\xc5\xbf_\xba|\xe5\x8f\xab\xd7\xae_\xbfq\
+\xf3V\xc9\xed;w\xef\x96\x96\xdd+\xbf_QQ\xf9\
+\xe7\x83\x87UU\x8f\x1eW\xd7\xd4\xd4\xd6\xd5\xd5?i\
+hx\xda\xd8\xf8\xac\xa9\xe9\xf9\x8b\x17\xcd/_\xbez\
+\xfd\xfaMKK\xeb\xdb\xb6\xb6\xf6w\xef\xfez\xff\xbe\
+\xe3CggWwwOo__\xff\xc0\xc0\xc7O\
+\x9f?\x7f\x19\x1c\xfc:44\xfc\xed\x9b\x08$\x95.\
+!\xc9\x94\x92\x96\x91\x95WPTVQS\xd7\xd4\xd2\
+\xe6\xe8\xea\xe9\x1b\x18\x1a\x9b\x98r\xcd\xcc-,\xad\xac\
+ml\xed\xc6:\xfc\x1b\xc0\xb4\x11\x80\xd9#\x00\xfc\xef\
+\x00\x89?\x00\x16\xff\x00X\xbd&3k\xed\xfa\x0d\x1b\
+\xb37m\xfeE \x7f\xef\xbe\x7f\x10\x18\x01\x10\x0b\x88\
+\x01\xee\xfc\x0d\xe0\xd1\xe3\xc7\xd55\xb5\xb5u\xf5\xff\x08\
+\xd0\xfa\x03\xa0C\x0c\xd0\xd3\xd3\xdb\xd7\xdf?\xf0\xf1\xe3\
+\xa7\xcf_\xbe\xfc\xbc?\x85FgH2Y\xd2l\x19\
+Yy\x05E%\x15U5u\x0dMm\x1d\x8e\xae\xde\
+(}\x03#c\x13\xd3\xd1\x5c3s\x0b\xcb1V\xd6\
+66\xb6v\xf6c\x1d\x1c\x9d\x9cG$~\xa5\x10\x0f\
+\xc3w\x8cY\xb3\xe7\xcc\x9d\x17\x1a\x1a\x16\xce\x8b\xf8\xe1\
+\x91\xf0\x0bH\xda\xdfE\xd6\xfdB\xf2}&\xbe\x93\xfc\
+\x93\x89\x98dd(J\xcb\xee\x95\x97\xdf\xff\x95\xa4\xae\
+\xfe\x89\xd8\xe3\xf9\x8b\xe6\x97\xaf^\xbfii}\xdb\xd6\
+\xfe\xee\xaf\xf7\x1d\x1f:\xbb\xba{z\xfb\xfa\x07>~\
+\xfe2\xf8uh\xf8\x9b\x08\x10\xff\xfb\x00@\xb7\x03\x0e\
+'\x003\x98@\xe0!`{1`\xe4\x04\xa8t\x01\
+\xfe\xd2@\xa0\x03\xc8dk\x90\x91\x91 U\x98\xa0\x10\
+\x00\x09\x80\x00\x05tHB\x06\xca\xd0\x81)\xec0\x0e\
+\x81\xe0#\x15\xeb\xb1\x0f\x17Q\x89\x16|#\xd4\x09{\
+b:\x91Ll%\x8a\x89\xa7\xc47\xd2\x80\xf4%\x17\
+\x92\xfb\xc9J\xf2\x0b\xc5\x84\x12B\xd9@\xb9I\xe9\xa7\
+r\xa9\x11\xd4\xbd\xd4\xa74UZ\x10m7\xad\x89\xae\
+G\x8f\xa6_\xa0\x8b$|$\xf6Ht0<\x18\xbb\
+\x18\xbd\x92~\x92g\x98l\xe6\x02f\x03\xcb\x8bU(\
+\xa5-\xb5I\x9a\x94N\x93\x1e`'\xb3\xfbdRe\
+\x86e3\xe5\xe4\xe4\x0e\xca\xdb\xc8W(\x84+|S\
+\xdc\xad\xa4\xaftJ\xd9J\xf9\x9a\xca\x04\x95\x1a\xd5p\
+\xd5~\xb5u\xeaZ\xea\x175|4Z5\x97i\xa9\
+h\x15k\xfbkw\xea\xe4pl8\x8d\xba\x19z\xa3\
+\xf5\xaaG-\xd5\xb7\xd0o2\xd8h\xe8b\xd8it\
+\xd08\xc8\x84mRj\x9a>\xdak\xf40\xf7\xba\xd9\
+\x0as\x0f\x0b\x9aE\xa5\xe5\xb61s\xac\x8c\xacz\xad\
+o\xda\xe4\xd8\x86\xdb\xd9\xda\xb3\xec_\x8f\xbd\xe2\xb0\xd9\
+\x91\xef\xe4\xe2\xac\xe5\xfc\xcd\xa5\xd9\xf5\x86\xdb\x01\xf7\x0c\
+\x8fH\xcf)^\xd6\xe38\xe3e\xc7\x0fywO\xa8\
+\x9fxo\xd2\xed\xc9%Sn\xfb\x94\xf9V\xfa=\xfa\
+\xad\xce\xbfi\xea\xbb\x80\xaf\x81r\xd3\x8df8\x07\x05\
+\x06\x0bB\xb2g\x9e\x99U3[4\xd7b\xde\xbc\xd0\
+\x9c\xb02\x1e\x19\xe1\xc6_\x12y5\x9a\x12\xe3\x1f\xbb\
+w~w\xfc\xe4\x84<\x01\x16\xf0\x92\xca\x84\x96)\xfb\
+S\xe5\x16\xadMc,Y\xbetp\xf9\xca\x95\xccU\
+[3tV_\xca\xf4\xc9j^\xb7d\x83\xd6\xc6\x92\
+M\xc1\x9bE\xb9\xa7\xb7\xce\xda.\xb1\xe3\xcc\xae]{\
+\x8a\xf2_\xef\x97=\xe8|Xp\xf4\xd8\xb1\xfa\x93\x92\
+\xa7'\x9d\xcd.,=/*\xf6\xba\x94~\xa5\xf2\x9a\
+\xec\x8d\xa0[Gn\xf7\x97z\xdc\xcb\xbd\xff\xf2O\x87\
+\x87\x1b\x1e\xbd\xa9\xb1\xad\xdb\xf2\xa4\xb71\xa0\xe9r\xb3\
+\xda\xab\xb47/\xde\xfa\xb7\x97\xbc\xb7\xfeP\xd0m\xd4\
+\x9b7\xa0\xf4i\xd7\xa0\xee\xd0S\x91\xe8G\xff\x99\x90\
+\x81\x0at\xc1\x85\x03&\x22\x04\xb1X\x8a\x1c\x14\xe0\x1a\
+\xea\xd0E0\x09c\xc2\x9b\x88 V\x13\x05D\x05\xd1\
+E*\x93\xaed4\xb9\x85\xbcAvP4)\xbe\x94\
+\x15\x94\x0b\x94v*\x87\x1aL\xddB}Hc\xd3\xfc\
+h\x9bi\xb5t\x0dz8\xfd4\xfd\xb3\x84\xb7\xc46\
+\x896\x863c\x1b\xa3Sr\x8a\xe4\x09&\x8b\x99\xc0\
+\xacgy\xb0\xceJiIeK\x13\xd2\x8b\xa5\xfb\xd9\
+\xc9\xec>\x99\x852C\xb2k\xe4\xe4\xe4\x0e\xfc\xcf\xee\
+\xfbj\xb4j.\xd7R\xd1*\xd6\x9e\xaa\xdd\xad\xb3\x85\
+c\xc7y\xae\x9b\xa9g\xa1\xf7dT\xba\xbe\x9d~\xab\
+\xc1\x0e\xc3\x89\x86_\x8d\xce\x19G\x9a\xe8\x984\x9a\xee\
+\x1e\x1d\xc2U\xe2>3;h\xce\xb7\xe0Z|\xb4\xbc\
+=&\xc7j\xae\xb5\x99\x0dl\x9e\xd8\x9e\xb4\xcb\xb4\x0f\
+\x1f\xeb\xea\xa0\xee\xf0\xd1\xb1\xd6\xe9w\xe7|\x97\x0c\xd7\
+X\xb7\x00w'\x0f#Oy/x\xf5\x8e\xeb\x19\xff\
+\xca\xbbi\xc2\x83\x89w'\x95L.\x99R\xe2s\xc7\
+\xb7\xdc\xaf\xf2\xb7*\xff\xda\xa9\xcd\x01\x9d\x81\xc4t\x85\
+\x19\x06A\xf6\xc1\xfe!\xd13\xd3g\x1d\x98]:\xa7\
+k\x9eF\xa8{Xt\xf8.^=\x9f\x15\xe9\x12\x95\
+\x16}=\x16\xf3\xc7\xc7\xe5\xc4\xbfH4\x17\xa4/h\
+H\xb6\x12\xe6\xa6\xf4\xa7\x86,\xba\x95f\xbad\xff2\
+\x85\xe5\xd9+\x99\xab\xb22(\xabWe\xb2\xb2\xf2\xd6\
+\x19\xaf\xbf\xbc\xd1/\xfb\xfd\xe6\x0d\xb9F[J\xb6\xf1\
+v(\xee|\xbe\xfbI>}\x9f\xcd\x01\xfe\xa1\xddG\
+\x1e\x1c\xa3\x9cp<\x15\x7f\xe6\xf4\xb9\xb6\xf3\xdc\x8b)\
+\xbf\x17_\xfer\xd5\xf9\xfa\xea\x9b\x8fnk\xdd\x0d+\
++*\x1f\xaa\xf4{\x90_\xf5\xa1\xda\xb3vg\xfd\xdb\
+\xa7\xf6\xcfr\x9e\xb7\xbet{\xbd\xa3\xe5C\x9b\xef\xbb\
+\xfd\xef\xbft\xce\xe8\xbe\xde\xa77\xb0\xf6S\xd7\xe0\x9c\
+\xa1\xee\x91\xfe\x93`A\x16\xca\xe0\xc0\x1c.\xf0C8\
+R\xb1\x09\x05(\xc1\x0b\x0c\x13\xda\x84;\x11A\xac#\
+\x8a\x88&\x92A\xda\x91Q\xe4N\xb2\x92BR\x9c(\
+)\x94\x22J7\xd5\x8a*\xa4\xfeA\xa3\xd0\xfchy\
+\xb4\xf7tW\xfa6z\x87\xc4\x04\x89\xa3\x0c:#\x96\
+Q-\xe9*y\x86\xa9\xc3\xdc\xc1\x92eeKIK\
+m\x96V\x92>\xc4\xb6f\x97\xc9\xcc\x91\xf9,\xbb]\
+\xceN\xaeI>K\xc1N\xa1]1_\xc9K\xa9Y\
+y\xad\x8a\xb9J\x83\xea\x1a5;\xb5v\xf5|\x8di\
+\x9aL\xcd[Z\x8b\xb5m\xb4\xbbu\x0a9\xc9\xba\x8e\
+z\x14\xbd{\xa3r\xf5C\x0d\xcc\x0d\x86\x0d+\x8d\xf2\
+\x8c\x13L<MUM{FWr\x0b\xcc2\xccC\
+-\xdc,9c\xa8c\xda\xac*\xac\x0bm\xf6\xd8\xa6\
+\xdb\xc5\xdb\xcf\x1e;\xd9\xc1\xdeQ\xcfI\xc6\x99\xe2<\
+\xe8\xd2\xed\xda\xe2\xd6\xe0^\xe3Q\xeeY\xe2uk\x5c\
+\xe9\xf8R\xef\xb2\x09w&\xde\x9dT9\xb9fJ\x93\
+O\xbbo\xbf\x9f\xc8\x9f9U%\xc0d\x9a[`\xd0\
+\xf4\x84\x19k\x82\xf6\x06_\x09i\x9c9<[g\x8e\
+\xdb\xdc\xb0yY\xa1\x85aM<F\x84-\x9f\x1f\xb9\
++\xaa*\x86\x11;~~F\x5cI\xbc(\xd1U\x90\
+\xbe\xe0~\xb2\x8204\xa5(\x95\x5c\x14\xb8\xf8\xe4\x12\
+ri\xc8\xb2\x8b+\xd4V\xa6\xadj\xc8\xf0\x5c}.\
+S#k\xf5\xda\xee\xf5\xbc\x0d\xd5\xd9\xde\x9bn\xe68\
+\xe6^\xd9\xea\xb0\xed\xea\x0e\xd7\x9d\xa5\xbbg\xec\xe9\xc9\
+\xdf\xba\xcft\xff\x83\x83\x89\x87\xe5\x8f\x5c-\x88<\xce\
+:Qx*\xe1\x8c\xce\xd9\x87\x85\xcb\xcf[_\xe8*\
+>})\xe6\x8a\xe9\x1f\x8d\xd7\xf2n\x04\xddR,\xa9\
+\xbd\xb3\xbdt\xfa=\xa5\xf2\x9a\x8aM\x7fNy\xc8\xac\
+*{\xbc\xa8\xc6\xaa\xb6\xbd\xfe`Cp#\xfb\xd9\x8d\
+\xe7\xf3\x9b\xd5_V\xbc\x16\xb6\xa8\xb6\xdeh\x8b}\xc7\
+\xf8\xebP\x87\xf7\x87\x97]Kz\x94zO\xf4;\x0c\
+T|\x9a\xf5\xb9cp\xed\x90\xeap\xa3H\x04\x88\xdf\
+\x8b\x00\x00Z\x8co\x18\x0f\xff\xe7\x88\x8fK\xf9\xbe'\
+\x09@\x8a\x9f0}\x1a\x00\x06\x00c\x81\xd0?\xf0{\
+\x8e\x18\xf8\x22\x0c<\xf1;\x15\x00\xe8\xb2@\xbe\x11\x00\
+\x5c\xf6M\xfa\xaf}\x85\xfcEB\x00\xf0J\x14,N\
+\x8a\x89\x8a\x16r<\x04\x828>\xc7+1^\x90\x22\
+\xe4'q9\x93\x12x\xe6\x5c\x8e\x95\xa5\xa5-\x00\xfc\
+\x07\x8f\x08\x91L8\xcf\x9b\xb0\x00\x00 \x00IDA\
+Tx\x9c\xed}y\x9c\x5cU\x9d\xef\xf7\xdc\xa5\xf6\xad\
+\xbbz\xdf\x93\xce\xbe\x07\x0cc\x10\x95\x00\x03\x08\x88\xe8\
+\xa0\xbe,\x84\x04\xf8\xa08\xce<\x9e\xcb\x88\x06\x12\xc0\
+\x91y\xbc7\x8e\xa3\x83\xdbg\x06\x01\xc5\x04d\x10|\
+\x82Q\x90@p\x09\x88\x06!\xa1\x93\xd0\xdd\xe9\xee\xa4\
+\x93\xde\xbb\xab\xba\xba\xd6[u\xef\xfb\xe3\xdcs\xb7\xba\
+U]\xd5I $\xf9}>\xf7S\xd5\xb7\xef\xbd\xe7\
+\xdc\xf3\xfd\x9e\xdfv\x96\x22\x00\x88\xa2(\x0a\xce\xc9Y\
+)\x1c\x00\x10B\xc8\xbb]\x91s\xf2\xee\x08Q\x0fM\
+\xcei\x83\xb3K8\xeb\x89s\xda\xe0\xec\x92<\x02\x00\
+\xe7Hp6\x89-\x01\x80s$8[\x84+f\xf2\
+\x09!\xe4\x89'\x9e\xe0\xdf\xc1\xfa\x9c\x93wX\x88\xa2\
+(\x04\x00\xac\x1d~\xdb\xb6md\xf1\xe2+\x9c\x92+\
+\xed\x05\x17\xcf\xad\xbb\xfa\xea\x89w\xa5\x86\xe7\xe4\x94\x8a\
+F\x00@'\xc1\xb6m\xdb\xc8G?\xfaQ\x17\x17\x08\
+xG\x06\xc6}S\x93R \x97\xcb\xa4>\xf9\xb1K\
+\x0e\xbdk5='\xa7DL\x04\x00\x80'\x9ex\x82\
+[\xb4\xe8\xc3n\xb7[\xf1&ri\x1f\x0790>\
+6\x15\x1c\x1d\x9f\x08)\x8a\xa2\x1c\xed\x8e\xff\xfa\x1f\xff\
+\xf1#\xe9w\xab\xc2\xe7\xe4\xe4\x0a\x01%\x01\xfb\x9b\x03\
+\xe0\x89\xc7\xe3\xde\xc1\x89\x84\x1fr6\x90M\xe6\x82\x92\
+\x92\xabH'S\x15\xc7\x87F+r9\x85\x83$o\
+\xbf\xee\xba\x0f\x1d=\xa9\x159A\xa7\xf3\x5c\xfebf\
+\xa2%\x82^|Q\xe1/\xbe\x18^\x00^\x00~\x00\
+\x81\xe3\xc7\xc7BYE\x0e%\xe2\xe9\x0aE\xc9V\xa6\
+R\xd9\xca\xc1\xe1\xb1j)+\xb9\xb9\x1c~p\xcd5\
+\x17\xbd4\xa3B\x8b\x83=\x13\x22\xd8\x82\x7f\x8e\x14\xd3\
+\x0b\x01@\xf6\xef\xdf/z\xbd^OMM\x8d\xd7\xe3\
+\xf1\x04\x00\x04\x00\x84\x00\x84\x86F\xa3\x15R&S\x99\
+\x88\xa7\xc3\x92\x9c\xab\xcaf\xe5\xea\xa1\xa1\xd1\xea\x8c$\
+\xd5\xc8P\xfe\xf5\xda+>\xf0\x1f%\x17f\x06\xde\x0a\
+4\xb19_\x88\x0cV`\x95\x02\x9f\xf4\x8fsD(\
+(\xe4\xa1\x87^t-ZT\xeb\xf5z\x9d^\xbf\xdf\
+\xe3\x0f\x85\x82\x81@\xc0\x1d\x02%@%\x80\xca\xf1\xf1\
+X8\x99\x96\xaa\x92\xc9du:\x9d\xa9V@jF\
+\xc7\x22\xd5\x89D\xca!+\xca\xc3\xd7\x5c\xb1zs\xc1\
+\x02\xf2{\xbb\x11hb\xf3\xb7\xf1\x9a\xe9\xc4\x08\xacl\
+9g\xfd\x9b\xfeq\x8e\x0c&\x11\x1c\x8e\x98/!\x87\
+|.\xde\xe9Oe3\xa1\xc9\xc9\xa9@\x0e\xb9\x8a\x8a\
+\x80\xaf\x02@\x18@\xb8\xb2\xd2_\x15\x9dLTs<\
+\xaay\x9e\xab\x89\xc7S\xe1p8$\x8aB\x0c\xd1X\
+|\xd3\xb3\xcf\xedi\x93\x12\xe9\x8f_w\xdd\xc5\x11\xa0\
+ \xe8V\x809\x9b\xff\x99\xce\xbf\xf5V\xd7EZE\
+\x85\xfc\xca?\xf5\xd4\xb3o\xdeq\xc7\xff\x8c\x80\x82\xac\
+\x80\x82\xce\x00fe\xb1\xf3\x00\xa0\xb0\xba\x9d#\x02\x15\
+\xf2\xe0\xcf~U\xed\x17\xf9\xc6\xc6\x86\xba@(\xe8\xaf\
+p8\x5cA\x97\xd3Q\xe9p\x88\x955U\x810\x80\
+jv$\xd3\xd9\x9a\xc9\xc9\xa9\xcatF\xe2c\xb1\x04\
+dYF<\x91D$:\x05YV\xfe\xaa(\xd9\xcd\
+\xd7\x5cq\xd1\x1b\xc6\xe7\xc3\x0c4g\xf7\xf9\xd4SO\
+\xb5\xae\x5c\xb9\xeaC\x1e\x8fw\x89\xd3\xe9Z\xeat:\
+\x96p\x1c\x17,Zq\x03\xc5dY\x8ef\xb3\xd9}\
+\xe9t\xea\xf7\xd1h\xf4\xcdg\x9eyn\xf7?\xfc\xc3\
+-\x11P\xe0\x19)\xac\xc79\x12@\xedu?yr\
+g\x9d\x87w\xbf?\x14\xf6W\xd4VUV\xb8\x9cb\
+\xa5\xdb\xe9\x0a;\x5cbUUe\xa0\x1a@\x8dz\x84\
+\xa4\xac\xc2E\xa31HR\x0e\xe3\x13Q\xe4d\x05\x19\
+I\xc2\xe8X\x14\x8a,G2r\xf6\x13\xd7]y\xd1\
+n\x14\x00\x1b\x00\xb7z\xf5U\x95\xb7\xdf\xfe\xf9\x0f\xae\
+Zu\xde\xd5UU\xa1%N\xa7s\x89\xa9R'\x98\
+\x84&\x04\x90$i_,\x96\xf8\xe9\xbe}\x7f\xfe\xe5\
+e\x97]\xd6\x033\x194Mq\xb6\x93@S\xcb;\
+~\xfe\xfc\x5c\x87\xc3yeE\xc0__\x13\x0eU\x89\
+\xa2P\xe5\x0b\xb8k\x04\xc2WWV\x85j\x04\x0e\x01\
+vm.\x07\xc4\xa6\x12\x90\xb2Y\x8c\x8cE \xa5%\
+\xc8\x8aB\x09\x91\x95\x91\xc9H7\x7f\xf4\xaa\x0f<\x0a\
+\x0a:\x07\x80\x07\xc0m\xdd\xfa\x1f\x1b\xd6\xac\xb9\xf0\xea\
+\x05\x0b\xe6|$\x14\x0ah\x95\xe0\x0a\x8eH\xd8Tx\
+\x06\xe4\x90$i\xdf\xd8\xd8\xd8}--\xf5O#\x9f\
+\x08\x00\xce^\x22\x98\xe6\x03\xfc\xecg\xbfmp\xfa\x5c\
+_u:\xc5\x96\xc6\xba\xeaj\xd1!\xd6\xf8\xbc\x9e\x1a\
+\x87C\xf0\x05\xfd\x1e8\x1c\xba!V\x14`2\x96\x80\
+$e119\x85\xf8T\x029Y\xc1\xd4T\x02\xe9\
+T\x06\x99l\xfa\xd1\x8f^\xf9\xc1\xcf\xad^}U\xe5\
+'?\xf9?\xfe\xfe\xa2\x8b.\xb8u\xee\xdc\xd6\xa0\xd3\
+\xe9\xccK;\x17\x93\x93I\x8e\xe1\xe1\xa1\xdb\x9a\x9a\xea\
+~\x0c \x87|\xf3pV\x92 oB\xc8\x8e\x9f\xbf\
+0\xdb\xe7r\xdd\xebp\x88\x1f\xa8\xae\x0e\xd5\xb8\x5cN\
+w0\xe0\x87(\xf2\xb0#\xc1T2\x83lF\xc2x\
+d\x12\x93\x93q@Q0\x95L!\x95L\xa3\xaf\xbb\
+\x7f\xff\x82\x05s\x9a\xcf?\x7fqQ{n\xaa\xd0)\
+&\xc7\xc0\xc0\xc0\xe7Z[\x1b\x1e\xc19\x12\x00(0\
+#\xe8\xd1\x9d;\x03A\x12|^\x10\x84\x0b\xeak*\
+\xe1p\x88\xf0\xfb=p\xbb\x9cp\xba\x5c\xf0{\x1dT\
+\x7f\xaaM\x95IKH\xa7%\xc4\xe2\x09\x0c\x8fL \
+\x16\x9dB,\x9a\xc0E\x17\x9d\x07\xa7\xd3axz>\
+b\xe5\xa8\xf4\x93E\x8e\xd1\xd1\xe1\xaf56\xd6~\x07\
+\x94\x049\x18\xfc\x82s\x0404\xc03\xbf\xd9\xf3\x90\
+\xc0\xf3\x9bB!?\xbc\x1e7B!\x1f<n'\x1c\
+\x0e\x11\x1e\x97\x8b\xe2)\xd3\xd6\xcb\xe6\xb2\xc8\xa4%\xec\
+\xdb\xd7\x09\xbf/\x80\xf6\xf6f\xfb\x02\x0bb\xf8\xce\x92\
+#\x91Hl\xaf\xa8\xf0~\x06@\x16g1\x09\xc8t\
+\xef\xfa\xecs\x7f\xfc\x16G\xb8\xdbC\xa1\x00\xbc^7\
+<n'\xc2\x15Ap<\x07\xaf\xc7\xad_\xa8(\xf8\
+\xfd\x1f\xfe\x8a\xb6\xd6f\x84\xc3\x15\xda\xe9\x13\xb7\xe1\xf6\
+\x0f8\x19\xe4H&\x13\xdb++5\x12\xc8\x86\xe3\xac\
+!\xc1\xb4\x04\x00\x80g\x9f{e\x13\xc7q\x0fy<\
+N\x84\x82\x01\xb8]\x0e\x84\xc3\x01\x88\x9c\x00\x97\xdb\x01\
+I\xcaa\xd7\x0b\xafa\xf5\xea\x95\x16\x95o**\xef\
+\xcc\xe9@\x8eD\x22\xb1\xbd\xaa\xcaw\xd6j\x82\x92\x08\
+\x00\x00\xcf\xfc\xfa\x95\x8by\x9e<\xe5\xf6\xb8BA\xbf\
+\x17N\x87\x88\xfa\xba*\xf0<\x87\xdf\xff\xeeu\x5cp\
+\xc1\x0a8\x1c\x85\xc0W\x0b+\x08\xcc\xbbK\x0e\x0b\x09\
+\xce*MP2\x01\x08!\xe4\xc9\xff\xb7{\xa5\xd7\xed\
+zA\x10\xc5Pe\xc8\x07A\x14q\xac\x7f\x10\xcb\x96\
+,\x80\xcf\xe7\xb5\xbb\xab\xf4\x8a\x9cdrd\xb39d\
+\xb3\x12\xdcn\x97\xcd\x7f\xf3\x1f\x10\x8f'\xb6\xd7\xd4\x9c\
+}$(\x87\x00\x1c\x00\xee\x1b\xdf\xf8v\xc5y\x17\xac\
+\xfa\xad 8\x96\xc5\xa2SX\xbcp.jk\xab\xa7\
+\xb9\xd7\xf6l\xe9\x95,\x93\x1c\x03\x03\xc7\xd1\xd3\xd3\x83\
+l6\x87E\x8b\x16\xa2\xaa\xca\xbe~\xd6\xe7R\x12\x04\
+>\x0b@\xc2YB\x82\x92\x08\xa0\x0e\xa0\x10\xd0\x8c\x1e\
+\xff\x99\xcf\xfc\xaf\xf0e\x97_\xb3\xb3\xa6\xaaj\xe9\xb2\
+e\x0bm\xae/\xa3\x02'\x91\x1c\x83\x83\x14\xf8T*\
+\x0dB\x088\x8e\xfes\xfe\xfcE\xa8\xad\xad-Is\
+$\x12\x89\xed55\x01[\x9f\x008\xf3\xf2\x04\xd36\
+\x89\x01|-\xad\xdb\xdb{XLL%C\x0b\x16\xb4\
+\x83\xb6\x87\xf9P\x14\x05\x8a\x02\xdb\xc3*\xf6\xd7)\xb6\
+\xcf\xb5\x9b\xf7\xa1(\xc0\xc4\xc4\x04\xf6\xee\xdd\x8b\x8e\x8e\
+\x8e<\xf0C\xa1\x0a\xd51U \xcb\x0ad\x19\xb6\x07\
+\x13\x8f\xc7\xb3nxx\xf2\x87\xdf\xfc\xe67\xc3\xa0\x84\
+7\x8ec\x9cq\xd3\xe5m\x06Y\xa9\x18^\x945\x00\
+\xaf^/\x5cy\xe5'\xbe\xbat\xe9\x82fQ\x14\x01\
+\xd8\x03\xcb\xc0\xb26\x17\xbd\xd6\xbe\x0d\xed\xaf-\xfc\xdc\
+\x89\x89\x09\xf4\xf6\x1eF$\x12\x01!\x00!\x9c\x06\xbe\
+\xcb\xe5F{{;*+\xab,\xcf\xb2\xaf\x17%\x01\
+=\xe9ry\xd6m\xde\xfc\xb9\xa5\x92$]u\xc7\x1d\
+w\x8c\x81j\x035\xebA\x87\x94\xcf\x14M`K\x80\
+\x02\xe0\xf3\x00\x84M\x9bno\xaf\xad\xad\xbf\xb5\xa5\xa5\
+\x11\xb2\xb1\xeb\xa8\xc2Y\xf4\xec\xa9 G2\x99Do\
+o\x0f\x06\x07\x8f\xab1>\xc7\xea\x0dQ\x14\xd1\xde\xde\
+\x8e\xda\xda:SY\xec\xb9\x91\xc8\x04B\xa1\x8ai\xeb\
+%\x08\xc2\xd2[o\xfd\xc7_\x01`$\xc8\xa9\x17\x9d\
+Q$(\xa8\x01\x90?IC\x00 \xaeZ\xf57_\
+\x993\xa7Uk\xc0\xfc\x9e\x94O\x0a&'J\x8ed\
+2\x85\xde\xde\xc3\x18\x1c\x1c\x00!\x04\x84\xf0\xea\xb5\x14\
+\xf8\xc6\xc6F466A\x10\x84\xbcgG\x22\xe3\x9a\
+\xb6\xa8\xafo\xc0\x82\x05F\xdf\xc5\x5c\x18\xbb\x97\xe7\xc5\
+\xa5\xb7\xdc\xa2\x91`\xd4\xf8\x9a8CH\x90G\x00\x83\
+\xcd\xcf\xeb\xfd\x1b7~f\xb6\xcf\x17\xf8Tmm\x8d\
+v}\xb1\xd7?Y\xe4\xc8f\xb38r\xa4\x0f\xc7\x8e\
+\xf5#\x97\xcb\xaa\xea^\xab/\xea\xeaj\xd1\xd2\xd2\x06\
+\x97\xcb\x9dwo$\x92o&\x86\x86\x86\x90H\xc4\xb1\
+t\xe9\x0a\x08\x82\x00@)\xe8\xb8\x8a\xe2\x99M\x82\xe9\
+4\x80\xd1\xf6\x8b\xef\x7f\xff\x9a/\x07\x83>\xb8\xddN\
+\xd8\xbd\xb3\xd5?:\x19\xe4\xe8\xed\xedA\x7f\xffQd\
+\xb3Yp\x1cQ{>%K(T\x81y\xf3\xe6\xc3\
+\xe5r\xa9\xe5\xe9@\xeafb\xc0t\x0f@\xe0r\xb9\
+\xd0\xd0\xd0\xa4\x82?]]\x15\x88\xa2\xb0\xf4\xe6\x9b\xff\
+\x81\x91`\x1c\xd4'\x00\xce\x00\x12\x98\x08`\xb1\xfdF\
+\x02\x88\x1f\xf8\xc0\x9a\xaa`0x}\xb1\x98\x7f\x9au\
+\x86\x96k\x0bW\x8a\x10`pp\x00\xbd\xbd\x87\x91J\
+\xa5\x00\x10\x0d|\x00\x08\x06ChmmC \x10\xc8\
+\xd3\x1c\x89\x04\x05~hh@+\x97i\x0cA\x10\xd1\
+\xd8\xd8\x84\xd6\xd6VC}\xa7\xf79\x14\x85j\x02\x03\
+\x09\xc6\x0c\x97\xbe\xa7I`\xa7\x01\xac\xe0\x0b\x00\xc4\x8f\
+~\xf4\xfa\xab9\x8e\x83\xdf\xef\xcb\x03\xba\x94\xc8\xa8T\
+r\x8c\x8c\x8c\xa0\xab\xebm\xa4\xd3\x14xB85~\
+'p:\xddhmmCmm\xadv=\xd3\x1c\xb9\
+\x5c\x0eG\x8f\x1e)\xa0-\x08Z[\xdb\xd0\xd0\xd0h\
+\xe3\x1f(\xc8f\xb3\x98\x9a\x9aDEE\xa5\xa1\xbe\xac\
+)t\x11\x04q\xe9\xe6\xcd\x9f\xdf\x09\xe0#g\x0a\x09\
+\x8a\x11@\xb3\xfd\x00\xc4\xea\xea\xba\xcb9\x8e\xd3\xd4\xad\
+Q\xca\xe9\xf9v\xa2(\x0a\x22\x91\x09\xf4\xf4\xf4 \x1a\
+\x1d\xd7@c!\x1d\xcfS\x07\xaf\xb5\xb5M\xbd\xde|\
+?3\x13\xb9\x5c\x16FmA\x08\x87\x9a\x9aZ\xb4\xb6\
+\xb6\xc1\xe9t\x02\xd0\x09\xc3q\x1c$I\xc2\xb1cG\
+p\xf4h?d9\x8b\xf9\xf3\x17\xa1\xae\xae\xdeX3\
+\xf5\x1d\xf43\x0e\x87\xb8d\xf3\xe6\xcf\xed\xbc\xe0\x82\x0f\
+}\xf6\x92K.\xdc\x0b\x9d%\xefI\x12h\x99@\x83\
+\xfa7\x02\xef\x04\xe0\x02\xe0y\xfc\xf1\xe7\xf7r\x1c\xf1\
+_t\xd1\xea\xa2\x0f,o\x10\x87`j*\x86\xce\xce\
+C\x88F#\x008\x8d0\x0c\xfc\x96\x96\xd6<{\xcd\
+dpp\x10\xbd\xbd\x87\x91N\xa7A\x08\xd4\xe4\x0f\x05\
+>\x18\x0c\xa1\xa5\xa5\x05\xc1`H}\x9e\xf9\xde\xfe\xfe\
+\xa3\xe8\xed\xed\xc9\xd3\x16\x8d\x8dMho\x9f3m\xdd\
+eY\x8e\xbe\xf9\xe6\xebW_r\xc9\x85\xaf\xc3<~\
+\xf0\x9e\xca\x18Z[\xd5\x1a\xffk\xe1\x9f(\x0a~Y\
+V\xa6U\xffE\x1c}\x139\x98\x9364t\x1c\x0c\
+4\xb3g_\x8f\x96\x96V[\x8d\xa3\x9b\x894\xacn\
+\x8b\xcb\xe5\xc6\xdc\xb9\xf3\x11\x0a\x85L\xf7\xb0j\x0f\x0c\
+P\xdf\x22\x93I\x83j\x0bN\x8b\x0ejj\xea\xd0\xd0\
+`\x9f\xdf\xd0\xdf\x81c\x9f\xc1e\xcbV>\xbbk\xd7\
+\x1f\xafV5\x81\xd6\x04x\x0fi\x02;\x02\xe4\x85\x7f\
+\xcb\x97\x9f_I\x08\x01\xcf\x03\xb1X\x14\x81@H#\
+B9\xea_\x96\x81\x5c.\x8b\xce\xceC\x18\x1c\x1c\x00\
+\x05\x80W\x01\xd0S\xb7\xed\xed\xed\xf0z}y\xcf\x8f\
+D\x22\xe8\xed\xed6i\x0b\xaa)\xa0\xf9\x0755\xb5\
+\xb6\xf5\x8aD&p\xf0\xe0\x01\xa4\xd3)\xb0H\x97\xf6\
+|\x0e\xa1P\x08\xcd\xcdm\x08\x06\x03\xea\xbd\xc6w0\
+\xbf\x93\x85\x1c\xc1%K\x96\x1bI\xa0\xc0\x901,\xd8\
+0\xa7\x91\x08@^~\xdb\x98\x07\xe0\x01\x08\x17_|\
+\xf9\x22\x8e\xe3\xa0(\x0a:::\xb1h\xd1\x5c\x84B\
+!d\xb3Vm`~\xb8\x11\x84l6\x8b\xfe\xfe#\
+\x16[\xcdi\xe0;\x9dn\xcc\x9f?\x1f\x81\x00\xed\xb9\
+\xc6v\x8e\xc7\xa7\xd0\xd9y\x08\x93\x93\x11\xb5\x0c\x06>\
+ \x08\x02\x1a\x1b\x9b\xd0\xd0\xd0\x08\x96\x9a6\x0a\xcd\x03\
+\xf4\xa8y\x00=\x1cd\xe9\xe2Y\xb3f#\x1cf\xe9\
+b\xa5\xech\x85\xe3\xb8\xe0\x92%\xcb\x9f\xdd\xbd\xfbO\
+W}\xf8\xc3\x17\xec\x05\xcd\x18\xb2q\x83\xd3\xde\x14\x14\
+\xd2\x00&- I\xb2\xc0\xf3\x1cdY\x86\xa2\x10\x1c\
+8\xd0\x85\xc5\x8b\xe7\x22\x10\x08\x22\x9b\xcdi7\xd3W\
+\xb5w\x02h\xde\xbe\xc7`\xab)\xf8N\xa7K\xed\xb9\
+u\xea3t\x10R)=\x96\xa7\x9aWO\xf9\x02\x04\
+55uhoo\xd7\xfc\x03c[\xa7RI\x1c<\
+\xd8\x91\xa7-\x00\xa8\xe9\xe29\x9a\xb60\xcaLBY\
+B\xb8\xe0\x82\x05\x8b\x7fe \x01\xa0\xae98\xddI\
+`$\x805\x07\xa0\x91\x80\x90\x1cGU-\x05@\x96\
+ettP\x12x\xbd\x01\xe4r9\xc3ch\xd7\xb5\
+j\x83\xaa\xaa0\xce?\x7f\x15::\xdeB&\x93\x86\
+(\x8a\xa8\xafg=\xd7\xccCI\x92\xd0\xd5\xf5\xb6\x9a\
+\xc41\x12\x86\xf6\xfap\xb8\x1a\xb3g\xcf1x\xf6\xfa\
+\xbd\xe9\xb4\x9e\x07P\xa70h\xe0\x1b\xb5\x05\x0d\x075\
+\x07\xb8\xa4\xc6*\x86#\xc7q\xc1\xb6\xb69\x7f\x0f\xe0\
+3\xd6\xc68\x9dIP(\x13h\x1c\x02%\x8aB\xd7\
+T\x12BY\xcf\x88\xc0\xccA0\x18B:-\x99\x1e\
+`\xf7\xba^\xaf\x0f+W\xbe\x0f\xc3\xc3\x83\xa8\xad\xad\
+\x83 \xf0\xea\xb52\x00\x0e\xd9\xac\xa4\x9a\x09\x96\xf2e\
+\xc0P\x10\xa9\xadn\xd5<{\xab\x899v\xec\x08z\
+{{4\xdbN\x9dK\xfa:55\xf5\x98={6\
+x^\xc8\x8bTN4\x8c\x05\x80\xa1\xa1\x11\xfc\xe0\x07\
+\x8f\xb7=\xfd\xf4o\xce\xbb\xee\xba+\xacN\xe1iK\
+\x82bQ\x801\x12\xe0x\x9eh=\xcdH\x84\x83\x07\
+\xbb\xb1b\xc5b8\x1cN\xa4R\x92\xe1\x11\xba\x18\x1b\
+\x5c\x10x444\x020\x93\xa4\xb7\xb7\x1b\xc7\x8e\xd1\
+$\x0e#\x1bS\xfb.\x97\x0b\xb3f\xcd1\xd8j\xbd\
+\x1e\xcc\xb7`\xf72m\xc1\xfe\x1f\x0c\x860w\xee|\
+m\x9c\x00(=R\xa1e\x15'G6\x9b\xc5\x13O\
+\xfc\x1a\xcf>\xbb\x1b\xb7\xdd\xb6\xee\xc2U\xab\x96\xef\xee\
+\xee\x1e\xd8\xde\xde^\x7f\xab\xf11\x00\xe4\xd3\x91\x04\xc5\
+\x12A\xdaA\x88B\x08\xe1\xc1\xf3\x0a\x14E\xce#\xc2\
+\x9bo\x1e\xc0\x8a\x15\x8b\xe1r\x89H&\xa5\xa2c\xed\
+V\x19\x1a\x1a0\xc4\xf2\xc4`\xab9\xf0<\x8f\x96\x96\
+6\x8d0\x86\xa5|\x00h\x1e\xa0\xab\xab\x13\xd9,u\
+*\xd9}\x84\x105\x0f\xd0\x86`\x90.J*\xd4\xee\
+3\x0dc9\x8e\xc3\xab\xaf\xbe\x8e\xef\x7f\xffq\xac^\
+\xbd\x02\xdf\xfd\xee6x<\x1e\x002\x9cN\xef\xba\xee\
+\xee\xa1\xe0\x8e\x1d\x8f~\xe6\xce;\xbf\xc8\x86\x929\x9c\
+\x86$\x98n0H\xfdT\x08\xc7\x11\xb5\xe7\xe5\x13\x01\
+P\xf0\xc6\x1b\x1dX\xbe|\x11\x02\x017&'\x936\
+\x8f\xcb\xcf\xaa\xa5\xd3)\xf4\xf7\x1f1\x80O\x8b\x13\x04\
+\x11\x0d\x0d\xcdhll\xd4\xcc\x04\xa0\xf7|6N`\
+$\x0d@Aq\xb9\x5chiiU\x1d<\xce\xd6\x14\
+\x99\xf3\xfc\xe5\x85\xb1\x1cG066\x8e\x1f\xfe\xf0q\
+\x0c\x0e\x8ea\xcb\x96\xcf\xa1\xad-_\xa3\x89\xa2\xfb\xea\
+\xb5ko\xdc\x09\xe0#\xa73\x09\x0ai\x00\xcbw\x1e\
+<O\x09 \xcb\xb0%\x82\xa2(\xd8\xb7\xaf\x03\xcb\x96\
+-B0\xe8F4\x9a\xb0y\x9c\xb9\x91\x1c\x0e\x17\x96\
+/?\x1f\xdd\xdd\x9d\x18\x19\x19\x04@PWW\x87\xe6\
+\xe66[\x07/\x12\x99@ww'\xe2\xf1\xa9<m\
+!\x8afmA\xcb\xb1wH\x8bE+\x85\xc8A\xb5\
+\x9d\x8c\xa7\x9f\xde\x85'\x9f|\x1e\xd7_\x7f\x05\xee\xb8\
+\xe3\xb3\x86|\x08-\xcfL\x02q\xe9\xda\xb57\xee\x94\
+$\xe9\xaa{\xee\xb9c\x14\xa7!\x09\xec\xa2\x00\xab\xa8\
+&\x80\xe67x\x1eE\x88\xa0`\xdf\xbe\x83X\xbat\
+\x01\x02\x01\x0f&'\x93\x06O\xdb\xf6\xd1\xe0y\x1e\xf3\
+\xe6-@UU5\x9cN\x17\xbc^:\xbd\xdc8\x85\
++\x12\x99@__\x0f&'#`\xaa\x9ei\x0b\x80\
+\xd3\x80\xe7y^\xed\xa5\xe6R\xec\x9b\xb9tr8\x9d\
+<\xfe\xfa\xd7\x03\xf8\xeew\xb7\xa3\xa9\xa9\x0e\xdf\xfb\xde\
+\xdd\xf0z=\x05\xc1\xa7\xa4\xa5\xf3\x22\x05A\x5c\xbai\
+\xd3\xad\xfbW\xaf\xfe\xe0UW^\xf9\x81\xd7\xa1\xcf,\
+R\x08!\xf4\xcaw\x91\x08\xc5L\x80Ih\x22\x88\xa8\
+/]\x9c\x08\xfb\xf6\x1d\xc2\xd2\xa5\xf3\x11\x0e{16\
+\x16\xd7&\x89\xe6\x8bN\x8e\xca\xcaJ\xd39\x80 \x9d\
+N\xa1\xb3\xf3\x10\xc6\xc6\xc6\x0cy~]\xe5\xd7\xd4\xd4\
+\xa3\xb5\xb5U\xd3\x16\xec\xdeb>G9\xe4p8\x04\
+D\x22\x11|\xfb\xdb\xff\x8d\x8e\x8e\xc3\xb8\xfd\xf6\x1b\xb1\
+x\xf1<\xf5\xbe\xe9\xc1gu\x22\x84\x0b\xce\x9b\xb7\xf0\
+W\xbf\xf8\xc5\xcbW\x7f\xecc\x1f2\x8e\x1d\x10\xbc\xcb\
+i\xe3\x92\x86n8\x8e\xd3\x06L\xe8w\x1el\x02&\
+\xcf\xd3C\x1fP\xe1\x01(\xd8\xbf\xff\x10b\xb18\xc2\
+a/\x00R\xd6\xcc`\x9a\xc4y\x0b{\xf6\xfcA\x05\
+\x9f^\xc7\xc0\x0f\x06CX\xb1\xe2|\xcc\x9d;\x0f\x0e\
+\x87\xb3\xac\x99\xc5\xa5\xcc\x0c\xe6y\x1eN'\x8f\x9d;\
+_\xc2M7\xdd\x89\x86\x86:<\xf8\xe07\xb0ti\
+\xf9\xe0\x1b\x93EK\x96,y\xf6\x0f\x7f\xe8\xf8\x18h\
+\xc7c\x11\x96\xeah\x97\x18o\x9ed)C\x03\xe8y\
+\x00Yfqma\x8d\xa0(\xc0[o\xbd\x8d\xc5\x8b\
+\xe7\xa1\xaa\xca\x8bH$\x0eI\xa2\xadl7\xd6\xce\x84\
+\x10@\x92r\x18\x1d\x1d\xd5F\x04\xe9y\x02\xaf\xd7\x8f\
+Y\xb3\xda\x11\x0c\x06U\xd5m\xd7iJI\xe5\xda\x9b\
+%B\x08\xdcn'\xba\xbb\xfbp\xff\xfd\xff\x85P(\
+\x80\x1f\xfc\xe0nTW\x87\x01\xd8E\x08\xa5\x81O?\
+\x15\x10B\x82\xf5\xf5\xf5\xdb\xf7\xec9\xf8\xb9\xd5\xab\x17\
+<\x02=m\xfc\xae\xe5\x0a\x8c\x04\xb0+X\x01\xa0\xf0\
+<\xaf0\x1f\x80\xcd\xae)\x8d\x08\x8aJ\x82\xf9\x08\x87\
+\x03\x18\x19\x89\x19R\xc7\xf6 (\x0aM\x18\x9dw\xde\
+*\x1c8\xf0\x16\x12\x898\x5c.\xb7\xc1\xb3\xd7\xaf\xb3\
+\x97\xc2\xf3\xfb\x0a\x91\x83\x02/\x22\x99L\xe2\xdb\xdf~\
+\x0c/\xbf\xfc\x17\xdc~\xfb\x8dX\xbdz\x85\xd6\xdb\x19\
+\xf8\xe6\xdeo.\xb7\x18\xf8:Q\x14TW\xd7|o\
+\xcf\x9e\x83PI\xa07\x06\xdey\x12\x105\xf7n\x1a\
+\xfc\x81>\x0f@\xdb5\xf4\xd5W\xdf\xdaMU(\xcb\
+\xdc15K_J\xff[1\xfd\x9f\x85N\x0b\x17\xce\
+C(\xe4\xc7\xc8\xc8$\xb2\xd9\x22\xc1\xb6\xb1r\x04\x18\
+\x1e\x1eDee\x95a>@>\xba\xe5(O\xeb\xb5\
+.\x97\x08\x87\x83\xc3s\xcf\xed\xc1\x0f\x7f\xf8\x04.\xbd\
+\xf4o\xb0n\xdd5&'\xcf\x1e\xfc\xc2\xbd\xdf|\x9d\
+\x19|\xfd<\x90H$~\xba|y\x93u=\xa2B\
+\x1f\xf1\xce\x90\xc0J\x00\x0e\x80\x08\xc0\x01\x0b\x01^x\
+\xe1\x95\x87\xfd\xfe\xc0lfW\xcb%\x02@\xb0x\xf1\
+<\x04\x02~D\x22\x09\xc4\xe3\xf9\xfbM3u_R\
+\xc5\x0bD\x15\xa5]G\x1d<\x9f\xcf\x85\xae\xae^|\
+\xf3\x9b\x0fC\x96e\xdc~\xfb&\xcc\x9a\xd5d\xa8s\
+\xf9\xe0[{\xbf\xfe\x1c3\xf8\xacm\x12\x89\xe4\xf6\x15\
++\x9ao\xc5\xbbD\x02;'\xd0\xe85i\x0b${\
+{\x0f\xbf\xc2ql\x08\x97S\xa7jq0\xae\xc61\
+:\x83Vg\x91\x10\xa0\xa3\xa3\x0b\x93\x931\x84\xc3\x1e\
+x\xbd\xce\xbc\x82\xa9\x83f\x7f\xe4U\xb2\x80\xe3gu\
+\xfat2B\x0d\xcb8\x84B\x1e\x88\x22\xc1\xb7\xbe\xf5\
+0\xbe\xf6\xb5\x7f\xc7\x9a5\xef\xc7w\xbes\x97\x06\xbe\
+^\x1fV\xd6\xcc\xc0\xb7ZU+\xf8\x8a\x02\xb8\xdd\xae\
+uo\xbc\xd1\xff\xf8\xb6m\xf7\x87aH\xbd\xe3\x1dr\
+\x0c\x8d\x04P\x0c\x9fF\xf0s\x00r\xdb\xb7\xff\xe47\
+\xb9\x5c.\xce\xf3\x14\xfc\x99\x10\x01\x90q\xe0@7&\
+'S\x08\x87=\xf0x\x0ay\xf0\xf9\x15-\x95\x1c\x85\
+\x9eG\xc7\x05\xdc\xf0\xfb]x\xf9\xe5\xd7\xb0v\xed\x97\
+0>\x1e\xc5\x0f~p/>\xf6\xb1Ka\xeclv\
+\x1d\xafT\xf0\xd3\xe9$\x0e\x1d:\x80\x97_~\x11\x83\
+\x83\x83Z\xdd\xed\x9fG\xcf;\x1c\xce\xab\xaf\xbf\xfe\x86\
+_\xab$`\xeb\x11\xd9\x9c\x82SJ\x04\xa3\x09\x00\xf4\
+Y@\x22\xa8\x1f\xe0\x86n\x06\x82\xff\xf2/\xffv\xdd\
+\x95W^\xf3y]\xad\xc9y!W)\xa6A\x10\x04\
+,X0\x07\x81\x80\x1bSS\x19\x8c\x8e\xc6\xa0\xcf\xdb\
+/\xa1\xd2e4\x07\xcf\x13x\xbdNx\xbd\x0etv\
+\x1e\xc1\x03\x0fl\xc7\xd0\xd0\x18\xbe\xf0\x85MX\xb2\xc4\
+\x1c\xd6\x19\xbf\x17\xeb\xfdv\xe0KR\x16G\x8e\xf4\xa0\
+\xbf\xbf\x9f\xd5\x12\x1c\x07\xb4\xb5\xcdF]]\x93m\xef\
+g\x04`\x0es6+\xed{\xf2\xc9G\xaf\xbc\xe7\x9e\
+\xaf\x8cC\xdf\xc0J\xad\x86rJ\xf2\x05V\x02\x18\xa7\
+\x82;@\x09\xe0\x01%\x80\x1f@\xf0\xde{\xef\xbf\xe6\
+\xdak?\xfe\x19\xb3}+\x9f\x08\x0e\x87\x03\x8b\x17\xcf\
+\x85\xcb%j$(X\xc9\x19\x92\xc3\xe3q \x10p\
+!\x93\xc9\xe0G?\xfa9~\xf1\x8b\x97p\xfd\xf5W\
+`\xfd\xfak\xf2\x1c6\xe3\xf7rT\x7f.'\xe1\xe8\
+\xd1~\x1c;vDsn\xd94v\x00\xa8\xabkD\
+k\xebl\xf59\xf6\xe0\x1b\xcb\xca\xe5r\xd1\x9e\x9eC\
+\x1f\xb9\xf6\xda\x8bY\xd6\x90icE\xbd\xee\xe4\x13\x00\
+\x80]$ \x82:\x82n\x00>\xe8$\x08l\xdbv\
+\xdfG>\xfe\xf1O\xde\xcc\x1aa\xa6D\x10E\x07\x16\
+/\x9e\xa3\x91`l,\x0eY\x96\xcb\xf4\xea\xf3\xc9\xe1\
+t\x0a\x08\x85\xdc\xe08\xe0\xe5\x97\xff\x8c\xef\x7f\xffq\
+\xd4\xd6V\xe3\x0b_\xd8\x84\x9a\x9aJ\xb5.'\x0e\xfe\
+\xd0\xd0 \xba\xba\x0e!\x9b\xcd\x19\x1cX\xfaYYY\
+\x85\xd6\xd6Yp8\xd8\xaa\xa5\xe9\xc1g\xff\xcb\xe5\xe4\
+\xe8\xa1C\x1dW}\xf2\x93\x97\xee\x85\xc1\x0f\xc3) \
+\x81\x1d\x01\xd8L`\x16\x0e\xbaa&A\x00\x80\x7f\xeb\
+\xd6\xaf_\xfew\x7f\xb7v\x13\x03z\xa6Dp:\x1d\
+X\xb8p\x0e\xdcn\x11\xe9t\x0e\x03\x03\x11\x95 \x85\
+\x13E\x85D\x10xTVz\xe1t\x8a\xe8\xef\x1f\xc0\
+\x03\x0fl\xc7\x9bov\xe2\x8b_\xbc\x09\x17^\xb8B\
+\x9b\xd0\x99\x1f\xae\x95\x07\xfe\xe0\xe0 \xfa\xfa\x0ek\x8b\
+WX]\x09\x01\xfc\xfe\x10\x9a\x9b[\xe0\xf7\x07\xa7U\
+\xfb\xf9e\xe9f%\x9b\x95\xa3\xc3\xc3\x03\xb7]~\xf9\
+yO\xc1\xac\x09\xd4\xdbN\x0e\x09\xec\xd6\x05X\xcd\x80\
+\xd1\x17`\xfe\x80\x1f\x80o\xcb\x96\xaf\xff\xed\xa7?\xbd\
+v\xa3\xd1\x03\x9f\x09\x11\x1c\x0e\x11\x8b\x16\xcd\x85\xd3)\
+ \x93\xc9\xe1\xf8\xf1\x88\xad\xe3d\xa8\xb6\xe9/\x8e\xe3\
+\x10\x0a\xb9\x10\x08\xb8\x91Lf\xf0\xf0\xc3?\xc7SO\
+\xbd\x80+\xaf\xfc \xd6\xaf\xbf\x16>\x9f\xa7 \xf8\xc6\
+\xef\xcc\x16\xeb\xd7\x99\xc1g\x13L\xe9\xa0\x14X\xbb\x01\
+ p:]hnnEuu\x8dm\xc8788\
+\x88#Gz\x11\x0a\x85\xd0\xde>\xdfT\xae\x15|Z\
+UZ\xf6\xf8\xf8\xc8mk\xd6,{\x18\xa7H\x13\x98\
+\xb6\x88\xb1\xd1\x02,'\xc0H\xe0\x03%\x01\xd3\x06\xbe\
+\xbb\xee\xba\xf7\xd2O\x7fz\xc3\x0dF\xb0gB\x04Q\
+t`\xd1\xa29\x1a\x09\x86\x86bH\xa7\xe9\x1a\xccb\
+\x8bMB!\x0f\xfc~7\x14E\xc6_\xfe\xf2\x16\xbe\
+\xf9\xcdG\xe0\xf1\xb8\xf1\xc5/n\xc6\xec\xd9\xcdZ\xf9\
+\xb4\x1ch\xe51)\xd6\xfbY\xfdb\xb1)tw\xbf\
+\x8dH\x84\x8dF2\x0dE\xe7\x19\xd6\xd77\xa2\xa9\xa9\
+E}\x8e\x19\xfcHd\x1c}}\xbd\x88F#\xda\x0c\
+\xa7`0\x84y\xf3\x16\x80\xe3\x84\xa2\xe0\xab5\xc2\xf8\
+\xf8\xe8mk\xd6,c{\x1c\xb3-n\xd5\xea\x9e\x18\
+\x09\xec\x08@ki\xd8\x11\x04zf\xd0\xa8\x09|\xea\
+\xe1\xdd\xb2\xe5\x9e\xcb\xd6\xae\xdd\xb8\x81\x02;s\x22\x88\
+\xa2\x88\x85\x0b)\x09d\x198v,\xa2\x91\xc0*\x81\
+\x80\x13\xa1\x90\x0f\x82@p\xfc\xf80\xfe\xf3?\xff\x1b\
+{\xf6\xbc\x89\x8d\x1b\xaf\xc5u\xd7\xfd\xad\xa9L\xdaR\
+Z\x8bi\xcf\x98N\xf5\xd3\xfd\x08z\xd45\x0c\xe6\x09\
+\x22\x84\x10\xd4\xd77\xa1\xa9\xa9\x19</\xa8\xcf\xd1\xef\
+\x8f\xc7c\xe8\xea\xeaTg%\xeb\xf3(\x09!p8\
+\x9cho\x9f\x0b\x9f/\x88\xe9\xc0g\xdfS\xa9\xd4O\
+\xdf\xff\xfe\xd9\xb7\xc2\xbc\xbd\xad\x82\x13$A\xde&Q\
+\x16-`t\x08\xb5eb\xd0\x89`$\xc1\xa5\xeb\xd6\
+m\xdc\xc0\x18=S\x22\x88\xa2\x13\x0b\x17\xce6\x91\x80\
+\xce5\xa4\xe2\xf18PQ\xe1\x85\xdb- \x93\x91\xf0\
+\xd8c;\xf1\x93\x9f<\x83\x95+\x17\xe1K_\xda\x0c\
+\xaf\xd7ciT\xb9l\xf0\xb3Y\x09G\x8f\x1eA_\
+_\x0fk\x15\xd66\x00\x80p\xb8\x0amm\xedp8\
+\x1c\x86r\xe8\x97T*\x89\xbe\xbe^\xdb\xa9\xec\x82\xc0\
+\xa3\xb6\xb6\x09\x8d\x8dMZY\xac\xae\xc5\xc0g\xd7\xa5\
+R\xc9\x9f\xae^=\x87\x91\xe0\xa4d\x0d\x8b\x11\x80\x1d\
+L\x0b\x18I`\xd4\x04\x8c\x08\xde\xbb\xee\xfa\xfa%k\
+\xd7\xde\xb0\x81\xd9\xf6\x99\x12A\x10D\xcc\x9f?\x1bn\
+7%\xc1\xc8H\x0c\xc9d\x06UU~x\xbd\x0e\xe4\
+r\x0a^\x7f\xbd\x03\x0f<\xb0\x03\xb1X\x02_\xfa\xd2\
+f,_\xbe\xc0F\x9d\x96\xe7\xf4IR\x16\xfd\xfd}\
+\xda\x0ac\xc08\xf1\x84N0mjjE0\x18\xb4\
+\x80\xa7 \x97\xcb\xa2\xb7\xb7\x07\xc7\x8f\xb3_\xd33\xce\
+J\x06\xea\xeb\x1b\xd1\xd8\xd8\x0c\x8ec3\xa1\xadu\x05\
+t\x02\x14\x1eLJ\xa5\xd2\xcf<\xf3\xcc\xd3\xb7\xdew\
+\xdf\x17X\xae\xe0\x844\x81\xed6q\x16\x12h{\x04\
+\x80\xfa\x03l\x9c\x80\xe5\x08\xf2H\xb0n\xdd\x0d\x1bt\
+`\xe9\x0b\x94K\x04\x9e\x171o\x1e%\x81Q\x06\x06\
+\xc6\xf0\xe8\xa3\xbf\xc4\xd3O\xef\xc2\xc6\x8d\x1f\xc3\x86\x0d\
+\xd7\x16h\xd0\xf2\x9c\xbe\xc1\xc1\xe3\xe8\xed\xedA2\x99\
+\x84\xfe\xfaT\x5c.\xb7\xe6\xe0Y\xcb\xa2S\xd9\xfb\xd5\
+\x15O9\xb5\xfd\xa0\xdd_Y\x19Fk\xeblu\xde\
+B\xbe\xd37<L\x9d\xc3\xa6\xa6VTW\xb3\xd1N\
+\xf3\xc0\x92U\xcbH\x92\xb4\xef\x97\xbf|\xea\x0a\x03\x09\
+f\xec\x18\x16\xdc'\xd0\x86\x04VM\xe0\x04%\x00#\
+\x01s\x10U\x12P\x9f\xe0D\x88\xe0v;1wn\
+;\x04\x81\xce\x11\xd8\xb5\xebU<\xf0\xc0chn\xae\
+\xc3\x97\xbf\xbc\x1955\xc6i\xe2\xe5\x83\x0f\x00##\
+\xc3\xe8\xeaz\x1b\xa9T\x12\xc6y\xb0\x84\x00</\xa2\
+\xa1\xa1\x11\xcd\xcd-\xb6=rpp\x00]]oC\
+_/\xa8\x9b\x8a@ \x88\xa6\xa6f\xd5\xce\xe7{\xfc\
+\xa3\xa3\xa3\xe8\xe9\xe9B:\x9d\xd6\xeemkkG]\
+]]\xc1\xdeO\x17\xe7\xd2\xef\x99Lz\xdf\xb3\xcf\xfe\
+\xe2\x84IPt\xa3H\x8b?`\x0d\x0fY\xa6\xd0N\
+\x13x\xb6n\xfd\xe7K\xd6\xaf\xdf\xb8\x81\xb2v\xe6D\
+\x10\x04\x11\xbbw\xbf\x8e?\xfc\xe15\x8c\x8fO\xe2\xcb\
+_\xbe\x19\x17^\xb8\x12\x85{Ii\xe0\xd3\xfd\x08\xba\
+U\xcf^{_0\x9bM\x81o\x05\xcfsy\x80\x8c\
+\x8c\x8c\xa0\xbb\xbb\xd3\x04\x1eS\xf5.\x97\x0b\x8d\x8d-\
+\x9a\xb60\x9a\x19E\x01\xa2\xd1\x09\xf4\xf5\xf5\x22\x16\x8b\
+j\xf7\xb2\xb2=\x1e\x0f\xe6\xce]\xa8\xcdr\xb2\x82o\
+~/\x19\xb9\x9c\x1c\x1d\x188~\xf9'>q\xe1\xeb\
+\xa0\xe0\xe7\xd4\xb2N\x0e\x01\xd4\x8aYM\x81\xddx\x81\
+\x91\x04>\xf6}\xeb\xd6\x7f\xbed\xc3\x06\xea\x18\x9e\x08\
+\x11>\xff\xf9\xff\x0d\x00\xf8\xd9\xcf\xbe\x85P\xc8\x0f\x14\
+\xb1\x91\xd39}\xc9d\x12\x1d\x1do\x19\x80'\x86\xe4\
+\x12\x87p8\x8cY\xb3\xda\xe1p8M\xf7)\x0a\xb4\
+\xc9\xa9\xec^=*\xd0\xc3\xc1\xc6\xc6f\xc0&\xd9\x93\
+N'\xf1\xf6\xdb\x87\xb4\xa8\xc0X\xae\xc3\xe1Fcc\
+\x13\xaa\xaa\xf2M\x0c}N>\xf8\xecoY\xceE\x07\
+\x06\x06.\xff\xc4'.dY\xc3\xb2|\x81R\xa7\x84\
+)\xd0cO\xf67}\x8bB);\x00\xf7\xde{\xe7\
+.\x8e\x03\xd6\xad\xdb\xb4\x81\xe7\xe9\xc2RYV\xb4\x19\
+E\x8a\x02\xd5)bD \x00\xf4\xff\xb3\xd0IQd\
+\x10\xc2\xe1\xad\xb7\x0e\xe2\x82\x0bV\x18\x16\x83\xd2\xaaX\
+{\x7f^\xe5\x15\x05\xc9d\x12==\x87\x0d!\x1d\xab\
+>\x00\xb0%\xe2-\x08\x04\xf4\x0c\x1e{\xcdd\x92\x8e\
+\xf0\xe9;\x8d\x99ME]\x1d\xcd\x03\xf0<\x0f+\xf8\
+\xa9T\x02}}\xbd\x18\x1e\x1eR\xcb5\x93\xa6\xb6\xb6\
+\x01uuu\xe0\xb8B\xefT\x18|@\x01\xc7q\xc1\
+\xda\xda\xfa\xe7~\xfc\xe3\x9f\xbdo\xe3\xc6O\xf5\x00\xe5\
+M2\x9d\x96\x00\x8a\xa2\xb0\x1f[d\xde&k\xe5\x1c\
+\x80\xcc4\xb7\x93\xbb\xef\xbe\xf3EE!d\xc3\x86M\
+\xeb\xa9sW>\x11\xd8\x8bOM\xc5\xf1\xa7?\xbd\x81\
+\x0b.X\xae\xc6\xde\xa5\xa9~\x80\xf6\xde\xd1\xd1Q\xb0\
+Q:\xa6\xea\x9dN'ZZ\xdaPUUkz\x1e\
+h\xd8\xa5\xe6\x01\xe8\xb0.\x03\x8f\x91\xa7\xba\xba\x16\xcd\
+\xcd-&\x95M\xebB\xf7A8v\xec(\xfa\xfaz\
+M\xf72\xd2UW\xd7\xa0\xa5e\xb6F\x1a\xd6\x0e\xe5\
+\x80\xcf\xca\xcaf3AA\xf0\xce\x02\xd0\xab\x16pr\
+5\x80\x81\x04Z\xdci\xf8\xb7d\x7f\x97.\xf7\xdc\xb3\
+e\x17\xc7\x11e\xfd\xfa\x1b7(\x0a}\xe1r\x88\x00\
+@\x9d\x7f@05\x15\xc7k\xaf\xbd\x81U\xab\x96k\
+!U)v\xbf\xb6\xb6\x01^o\x00\x87\x0eu \x1e\
+\x8fC\x14y\xd4\xd55\xa3\xa5\xa5%ox\x97\x8e\xf0\
+\xd1-d\x98\x92\xb3\x86\x83\xcd\xcd\xadj\xbe_6\x01\
+\x22IY\x1c?\xde\xaf\xaeU\xcci\x93a\x14\x85~\
+\x06\x02!\xcc\x9a5G31f\xd2\xe9R*\xf8\xb4\
+\xcc$$)\xa3\xedg\x5c\x8e\x94<+\xd8\xa2\x09\xac\
+\xbaV\xb1\x14\x9eW\x91m\xdb\xbe\xf6\x22\xa0\x90\x1bn\
+\xd8\xbc\x9e\x86_\xa5\x13\x81\xe3xu\xfa9\x0fYV\
+05\x95\xc4\xde\xbd\xfbq\xdeyK\xb4\xa2J\xf1\xf8\
+\xbd^/\x96-[\x89\xa1\xa1\x01\xd4\xd4\xd4i\x0bI\
+\x18\x08t\xa7\xb1>\xf4\xf7\x1fA.'\xe7\xf5Z\x97\
+\xcb\x8d\xb6\xb6\xd9\xa8\xa8\x08\xab\xcf77\xc3\xe0\xe0\x00\
+\xfa\xfaz\x0d;\x9c\xe9\xf7z\xbd~\xb4\xb6\xce\x82\xdf\
+\xef7i\x99B\xbe\x8c\xb9\xed\x8b\x0f&\xa5\xd3\x09\x16\
+\x822\x93\x5c\xb2\x19(\x99\x006b%AF\xab\x9d\
+.&\x22l\xdb\xb6e\x17\x00l\xdc\xb8y=u`\
+J#\x02\x9da\xc4\xab3\x8c\xe8\xb3&'\xa7\xd0\xd1\
+\xd1\x89\xa5K\x17h\xe3\xf0\xa5d\xfax^@CC\
+c^C\x0f\x0d\xd1<@*\xa5{\xf6\x00\x1d\x87\xe0\
+y\x11\xcd\xcd\xad\xa8\xabk\xb0\xed\x91\xd1\xe8\x04\xde~\
+\xfb\x00\x92\xc9\xb4\xc1G`\xa4\xa1QA8\x5c\x8b\xe9\
+2}\x85T\xbfU\x8c\xef\x94\xc9$\x91\xcdJ\x90$\
+I[c`\x7f\x97\xbd\x94E\x00\x8b\x16`&\xc1Z\
+ \xb1|\x9a\xbeo\xdbF\xcd\xc1\x0d7l\xde`\x9c\
+^^\x8c\x08\x82\xc0\xc0\xd7\xa7\xa0\xf3<0::\x8e\
+\x03\x07\xba\xb0p\xe1\x5cH\x92>f0]\x8e_o\
+h:Xs\xf0`\x87\x01x\x98\xc6\xf6\x19\xf0</\
+\xe4\x81\x1f\x89D\xd0\xd7w\x18\xd1(\x0d\xe9\x8c>\x82\
+ \x88\xa8\xabk@mm\x03\x04A0E'\xe5\x80\
+o\xd7\xfb\x8d\x92\xc9\xc4!\xcb\x0a$I\xb6\xb6\xf7\xc9\
+q\x02\xadR\x80\x04y\x97\x15{\xc6]w}\xedE\
+EQ\xc8\xc6\x8d7\xad\xb7\xae3\xb0#\x02\xb3\xff\xc6\
+\x06f\xfe\xc1\xd0\xd00\x08\x01\x16,\x98\x03I\xca\x95\
+\x05~*\x95DWW'2\x99\xb4a\x16\x0f-\xa3\
+\xa6\xa6\x0eMM-p\xb9\x5c\xa6\x04\x8c\xa2\xc8H\xa5\
+R\xe8\xee\xee\xc4\xd8\xd8\x08\xcc>\x02\x00p\xa8\xae\xae\
+Ak\xeb,\xc3 \x91\xb5\x0d\x8d\x9f\xe5;}\xfa{\
+)H$\xe2\xc8\xe5d\xa8\xbb\xd7\x9e:\x1f\xc0(6\
+\x91\x81\x9d\x14RG\x04\x00\xd9\xbau\xcb.\x80\xc3\x8d\
+7\xde\xb4\x1e6\x0bN\x8cD\xe0y\xa6\x01\xf4-j\
+\x00\x9d\x08\x83\x83#\x00\x80\x85\x0b\xe7\x9av*)\x06\
+>\xa0\xc0\xe9ta\xc5\x8a\xf3\xd1\xdd}\x08CCC\
+\xda\xb2\xb3\xa6\xa6V\x04\x02A\xf5Z\xfd\xf5\x92\xc9$\
+\x8e\x1c1\x8e\x0e\xb2qj\xfa\x19\x0c\x06\xd0\xde>\xcf\
+\x10\x15\xd8\x0f\xf2\x98\xdb\x92]W\x1e\xf8<O\x10\x8b\
+E\x90\xcd\xe6\xa0(2\xb2\xba\x02<u&\xc0\x5cq\
+\x8d\x04\x80\xbd\x16\xb0\x13v\xbd\x02\x00[\xb7~u\x17\
+@\xb0i\xd3M\xeb)X\xf6D`k\x13\xd9\x1e\x05\
+vD\x18\x1a\x1a\x05\xc7\x11\xcc\x9f\xdfn;\x84l\x05\
+\x9f\xfd\xcd\xf3\x1c\xe6\xce]\x88`\xb0\x12\x1c\xc7#\x1c\
+\x0e\xe7\x81\x22It\xfb\x19:H\x9438\x87t\x1b\
+[r\xfcT\x05\x00\x00\x11\xd0IDAT\x8f\xc7\x8b\
+\xb6\xb6\xd9e\x0d\xef\xda\xa9\xf4R\xc1\xa7\xdaPA,\
+\x16\x81,\xe7\xd4\xb6\x92\xca\xb6\xff\xc0\x899\x813%\
+\x01\x13\x02\x00[\xb7\xde\xb1\x8b\xe3\x00j\x0ex\xd8\x11\
+\x81M57\x9b\x80|\x22\x0c\x0e\x8e\xc0\xe1p`\xd6\
+\xac\x16$\x93\x92Z\xc7\xfc\xaa\xd9\x01B\x07b\xf2\xd5\
+qo\xefam\xfb\x19\xa6\xeaY\xb9N\xa7\x0bMM\
+-\xa8\xaa\xaa\xb1Q\xe7\xb4\xdcr\xec~~\x1d\xed\xc0\
+\xa7s\x1eGF\x8e#\x93\x91\xb4\x0c\xab\xea\x03\xbc\xb3\
+\x04P+\xa5\x00Z\xcaX\x1b\x90(G\xee\xbc\xf3\x8e\
+\x17\x09\x01n\xbc\xf1\xe6\xf5\xb2\x0cX\x89\xc0\xf3\xbc\xaa\
+\x01x\x00\xf9[\xd4\xb0|\xbd,\x03G\x8f\x1e\x07!\
+@[[+\x92\xc9\x0c\x14%\x97\xd7\xfb\xf3\xdf\x81\x9e\
+7\x02B\xb7\xae\xe9Qw+\xd7w*\x03h}\xea\
+\xeb\x1bQ_\xdf\xa8\xe5\x22\x8c2\x13\xf0\xad\xbd?\xbf\
+\x8e\x14|\x97\xcb\x81T*\x8eh4\x02\xb6s+\xbd\
+'k\xffr\xd3\xc8\x09\x13\xc0PA\xa3_\x90\x9b\xe6\
+\xf2<\xa6n\xd9r\xc7\x8b\x00\xb0i\xd3-\xeb\x15\x85\
+\xce\x0b`D\x10\x04}\xd1\x89\xa2\x187\xa4\xa0\xaa\x90\
+9\x84ta*\x87#G\x06A\x08\x87\xb6\xb6f\xc4\
+\xe3i\xe8\xdb\xd9\xd8\xaf\xe21\x8a,+\x18\x1b\x1bA\
+WW'd9k\x99\xd4A5Ek\xebl5*\
+0\x82g\xff\xbc\x13\xf5\xf8\x8dd\xa7\x0bid\x0c\x0c\
+\x1cC6+\xc3\x98\x84\xcaM\xd7\xe2\x05\xe4\xa4\x11\x00\
+\xc8#A!\x93P(l\xc4\x96-w\xbc\x04\x00\x9b\
+7\xdf\xb2^]%\x0bYfK\xd3i>\x80\xfa\x05\
+\x80\xbe!\x05\xc0\xb4\x82\xa2@3\x1dT\x13\x10\xb4\xb6\
+6!\x1eOk\xb6R\xadiAP\x00\xba\x0f\xe1\xf2\
+\xe5.tt\xec\xd7\xf6\x14\x0e\x04\x82\x9a\x83\xa7\xbe\xab\
+\xed\xfd\xf9\xbd\xdf\xd4B3\x02\x1f\x00\xbc^'8\x8e\
+C__/\x92\xc9\xa4v\x9d1B\xb1i\xdbi\xe5\
+\xa4\x12\x000\x91\xa0\x98O`m\x1e#\x09^\x048\
+\xdct\xd3-\xeb\xe9 \x10\xcd\x00\xa6R\xa3\xeaw\xa3\
+\x83\xc8\xcc\x00\xfbM\x01\xb3y8z\xf488\x8e\xa0\
+\xb9\xb9\x11\x89D\x06\x99L\x16\xa5\xf6H\xaf\xd7\x8f\x15\
++\xde\x87\xa3G\xfbPYY\x89@ X \xb4,\
+\xc7\xee[\xdb\x8a}\x16\x06\x9f\xe7\x09|>\xba\xb6`\
+p\xf08\x22\x91\x88\xda1\x8c#\xab\xb2i\xc7\xd6r\
+\xe4\xa4\x13\x00(Y\x13h\x97[>\xb1e\xcb?\xbd\
+\x08\x007\xddt\x8b\x9a'P\x90J\x0d\x80\xe3t\xdf\
+\xc0H\x04\xa00\x11\x8e\x1c9\x06B(\x098\x0e\x16\
+\xe7\xb0x\x8f\x14\x04\x1emm\xb3\x8dU;\x01\xf0\xcb\
+w\xfa\x5c.\x01\x1e\x8f\x03\xb2\x0c\x8c\x8d\x8d\xe2\xf8\xf1\
+\xe3\xda,&\xdd\xf6\x9b\x9e\xf7\xee\xf9\x00VQI\xc0\
+\xfe4N\x99\xb1\x9f\xe6\xab\xde\xc6\x8e-[\xfei\x17\
+\xcfs\xca\xe6\xcd7oH&G\xc0\xcf?j\x88\x02\
+\xca#B_\xdf1\x08\x02\x8f\xc6\xc6:5\x01$\xe1\
+D\xd4\xb1\xfe\x8e0\xfc\xef\xe48}\xcc\xe4\xf9\xfd.\
+8\x1c4\x838>>\x82\xc3\x87{4\xe0\xd9}\xba\
+\x13X\xa4E\xa7\x91SF\x00\xa0 \x09Xu\xa7\xb3\
+W\xca\x1dw|i\x17!\xc0\xd4Td\xc5\xa4\xd4{\
+\x84\xe3\xc8U\x80\x11\xec\xd2\x89\xd0\xd7w\x0cN\xa7\x88\
+\xeaj\xfa\x9bG\xc9$\x1d\xc9.?\xfbf\xfe\x9fM\
+\xb5O\xc8\xe9s\xbbE\x04\x02n\xed\xfa\xe3\xc7\x87\xd4\
+!e\xa6\xf2e\x8b\xfa\xa7\xf7\xe5f\xe8\x05\x9eR\x02\
+\x00\x05I\x00\x14&\x80b<\xbe\xf2\x95/\xfd\x16\xc0\
+\x1e\xbc\x047\xb7\x89\x5cE\xe3\x7f\xf5ae\x10\x01\x00\
+:;\xfb@\x08\x87\xaa\xaa0DQ\xc0\xe4dB\xad\
+#\xabk\xe9\xe0O\xe7\xf4\x95\x0b>\xcf\xf3\x08\x85<\
+p8\xe8\x88g6\xab\xe0\xed\xb7\xbb022l\x0b\
+\xbcN\x08:bzZD\x01\x85\xc4@\x02c3e\
+\xa1\x03m\xba\xdcp\x98f!ut\xec\x7fm\xd1\xa2\
+%\xab\xf4D\x10\xfd\x07\x0d\x19\x01E\xa1D\xa0~\x83\
+>\x9f@\x96\x89\xa6*;;{A\x08AUU%\
+\x00\x17\x22\x11\xf3\xae\xa6'\x06~\xf9c\xfb<\xcf!\
+\x18\xf4\xc0\xe3qh '\x93I\xbc\xf5\xd6!LM\
+M\x99\x80\xa7\xcf7\x03\xaf\xd7\xf7\x1d\x1c\x0b\x98\x89\x94\
+\x11\x1d\x18\x9dBv\xad\x0c@\xb9\xe5\x96u?z\xf0\
+\xc1\xedX\xb4h\x99J\x02\x0a2\x0d\x07\xd9\x08\x22\xdb\
+\xb0\x8a\x03\xbb\xc6\xbaqUWW/x\x9eCee\
+\x05\x00\x0e\x13\x13\xf1<[l\xa8\xb7\xfaI\xab4\x13\
+\xbbo~\x1e-G\x10h\x8f\xf7z\x1d\x06\xc7\x0e\xe8\
+\xe9\xe9C_\x1f\xdd-]\xcf]\x14\x06\x9e\x9d'\x84\
+\xb3\xebL\xd3\xca;F\x00\xa0$\x12X{\xbf\xd5o\
+\xc0\xcd7\xaf\xfb\xd1\x83\x0f\xee\xc0\x92%\xcbV\xc9\xb2\
+\x0e\xb21u\x0c@\xeb\xf5\xf6\xe6A\xc1\xdbo\x1f\xc6\
+\x82\x05sPY\x19T\x87\x96\xe3jJ\xb9\x90\xd3w\
+b\x1e?\xfb\xdb\xebu!\x18t\xc1\xe9\x14A\xb5\x13\
+\xbd\xfe\xf8\xf1Atw\xf7 \x91HZ\x80\xd7m\xbd\
+^\xae\xfe?\xaa\x1dd$\x93\xc9\x08f@\x80ig\
+\x05\x9f\x0a\xb1\xacA$\xb0\xfcD\x1d\xf4\x05\xa9l)\
+\x9au\xed\x81\xe7\xc1\x07w\xdc\xb4t\xe9\xf2U\xcc\x1e\
+\xb2\xa5e\x80\xde\x9b\xf4\xf3\x8a\xe1\xbc~\x0d\xc7\xf1X\
+\xbcx\x0e\x02\x01?$I_\x9a>\xbd\xea/\x0f|\
+\x87CD0\xe8\x82\xc7\xe3\x80 \xf0\x06\xbb\x9d\xc3\xd1\
+\xa3\x038|\xb8\x0f\xf1xB\xbb\xc7\x0a\xbc^\xa6Q\
+\x0bPR\xb3\xbfo\xbf}]\x10tR\x0e\xdblJ\
+9\xd53\x82f,\x86\xf1\x03\xeb\x84\x12\xc5\xe6\x00\xcc\
+\xccV\x00\xe0\xe6\x9b\xd7\xfe\xe8\xa1\x87v`\xc9\x92\xe5\
+\xab\x14\x85\x80\xe3\xa8\xdag\xbd\xc4\xceO\xa0e\xea\x1a\
+AQ\xe8/\x9f\xac\x5c\xb9\x18.\x97\x03\x0d\x0d!\x1c\
+;F;Rq\xd5o|\x17\xd8^\xe7\xf39\xe1\xf1\
+8\xe0\xf3\xb9 \x08\x9cf\xc7eYF,\x16\xc3\xd1\
+\xa3\xc7q\xf4\xe8 \xd2\xe9\x0c\xac!\x9d\xd1\xc9\xb3\x02\
+o$;;\x9fN\xa7\xfe`i\xaf\x92\xe5]!\x80\
+E\x8c\xb6>\x0fh\x9bk\x01\x954\x9b7\xaf\xfd\xd1\
+\xc3\x0f\xef\xc0\xe2\xc5+V\xb1\xb9\x01\xe5\x12A\x96e\
+\x1c8\xd0\x89%K\xe6\xc1\xe1\x10\xd1\xd8X\x89\xfe\xfe\
+1\xe4r\xa5\xd9}\x80\xfd\x00\x95\x08\xaf\xd7\x01\x8f\xc7\
+\x05\x8fG4i\x91l6\x87d2\x81\x81\x81a\x1c\
+;6\x8c\xd1\xd1\x09\x14\x0b\xe9t;_\x1cx6\x12\
+\x98H\xc4w\x96\xd0v\xb6\xf2\xae\x98\x00S\x05\xcc3\
+/\xd9\x90\x9b`8\xack\x11\xf3\xcc\xc1#\x8f\xfc\xec\
+\xa6\xc5\x8b\x97\xae2\x02V\xaei\xf0x\x9c*\x09\xe8\
+\xd4\xaf\xbe\xbe\x88\xda;i\xe5d\x19p\xbby\xf0<\
+\x0f\x97K\xd46\x9f\x12E\x1e\xa2h\x8c\x18(0\x92\
+\x94\xc5\xc8\xc8\x04\x86\x87G100\x82\xc9\xc9\xb8\x01\
+P\xfb\x90nr2\x06\xc2s\xe0\x09\x07\x10\x80S'\
+\xc1X\x81\x07\x8c\xa9`\x19\xcf<\xf3\xe4\xac\xdd\xbb\x7f\
+1\x02:C[\xdb?\xa0\x14\x13\xf0\xae\x13\x00\xc8#\
+\x81q\xaf<F\x00\xe3~E\x8c\x00\x1eXH\xb0t\
+\xe9\xf2Uf\x0fY\x07Yw\xc6\xcc\xff7n\x5c\xc5\
+H\xe0t\xd2\xd9\xc2\xe9tN\x03\xb8\x90(\x0a\x90\xcb\
+\x01\x91\xc8$&&\xa2\x18\x1b\x9bD$\x12\xc3\xd8\x18\
+5%\xd6\x9c\xbd]H\x97\xcdf\x11O$\xe0\xf5{\
+\x00B \x8a\x028N@6+\x81\x00\xc8\xa4$d\
+\xa5\xacf\xfb\x19\xf0\x8a\xa2 \x99L<\xbem\xdbm\
+\x9f\x05\xb5\xff\x8c\x00\x8a\xfaN\xef\x0d\x02\x00EI \
+\xc2^\x13\xe4\x91\xe0\xc7?~Bs\x0c\x8d\xea\xdal\
+S\xed\x89\xc0\xb4\x82\xc7\xe3\xc4\xa2Es\xf2V%\x03\
+@4\x9aD&\x93A$2\x85L&\x83\xf1\xf1I\
+\xc4\xe3\x09D\x22Sy\x0ef>\xf0\xac\xac\xfc\x90\x0e\
+<u\x14EQ\x04\xc7\x11\xa43\x12\x04A\x80 \xf0\
+\xc8HY\x88\xa2\x00)%al$\xa2\x01\xcf\xca\xf9\
+\xf3\x9f\x7f\xff\xbe'\x9e\xf8\xafNP\xf0\xb3P\x09P\
+\x0a\xf8\xc0iD\x00\xa0$\x12\xb0\xc8\x80E\x07^\xcb\
+\xa1\x91\x00`\x0d\x0c\xe8v\xbbt\xf3 \x08\x9c:\xe6\
+\xae`l,b!\x8e1\x04+\x0e<`\xef\xd9\xb3\
+zI\xb9\x1c\x9cN\x11\x0e\x87\x00Q\x14\xe1p\x88\xe0\
+x\x1e\xa9T\x8a\x12B\xe0!e(\x09\x92\x89$\x06\
+\x8f\x8dh\xe5$\x93\xf1'\xee\xbd\xf7\xf3\xb7\x81\xf6\xfe\
+\x0c\x0c\xab\x84K%@\x19?\xf5|\xea\xc5Pi\xe6\
+\x18\xb2#\xab\x1ei\x00I\xf5H\x00\x88\xab\xc7\x94\xfa\
+\x99\xd8\xb8\xf1\x93?\xda\xb7\xef\xcd\xd7\xcc\xbb\x96r\xea\
+n\xa6\xfa/\x92\x17\xda\xe5\x94}\x8e\x8fObtt\
+\x02##\x13Z\xac-\xcb9\xd0\xcd \x14\xe4r\xb2\
+\x06\xb2\xa2\xb0sl\xf7\xd2\x9c\xa6\xees9\x19\xfa\xae\
+\xa6\xb2\xc1\xc1\xa3\xcfJ&\x92j\xbd\xd4zp\xf4\xe7\
+oB\xc1\x008\x9e\x83 p\xf0\xf9<\xe09\x82P\
+E\x10\x0dMu\xc8\xe5\x14d\xb3\xd9\xc9\x9d;\x1f\xbb\
+\x13\xe6-c`\xf8,IN+\x02\x00\x05I\x90\x83\
+N\x82\x0c(\x11R\xa0$`\xe0O\xb1\xef\x1b7^\
+\xff\xe0\x9f\xfe\xb4\xe7\xe5|`K'\x82,\xcb\xb6\xc0\
+\xeb\xde9=\xcf\x80\xd75C>\xf0\xec\x7f,\xf67\
+\x9e\xa7\x1bR\x00\x84#\xf4P\xc9\xe0\x10\x05\x84B~\
+\xf0\x84\xa7$\xf0{!\x08\x02*\xaa\x02hi\xab\xc3\
+\xb1c}_|\xed\xb5\xdf\x8f\x1b\xdaH\x8b\xa6J\xed\
+\xfd\xc0iH\x00\xa0(\x09\x98\x9d\xcb@\xd7\x04L\x1b\
+0\x22\xc4\x01$o\xbdu\xe3\x8e\xed\xdb\x1f\xd9\xc1@\
+.\x97\x08,\x06g\xea\xdb\xd8{\xed\x80g\xe02-\
+\xa0\xdbzJ\x06+\xf0\x8c$9EA\x22E\x7f\xd0\
+\x9a\xe7\x088B\xc0\xab\xf5r\xf0\x22B\x15~\x08\x82\
+\x00\x87C\xa49\x05\x8eGeu%.\xbdr\xcde\
+\xc8\xdf0\xaal9-\x09\x00Lk\x0e$P\x12\xa4\
+\xa0\x13 \xcf$\xdc\x7f\xff\xd7w\xff\xf4\xa7?\xd9\xc1\
+\xc0-\x87\x08\xd4_\x90M=\x9f\x01o\xd7\xab\xf3\xcf\
++\xeayc\x92\xc7\xa8\x1dt\x13\x90\xc9HH&(\
+\x098\xb5.\x84\xa7\x87S\x14Q[\x13\x86\xd3\xe9\x00\
+Gxx\xbd.\x08<\x07\x9f\xcf\xff\xe9\x9d\xcf\xfd\xf1\
+\xa5\xaf~\xf5\x1b>\xe8\x1a\xa0l\x12\x9c\xb6\x04\x00\xa6\
+5\x07V\x12$a\xf6\x07\xe2\x00\xe2\xf7\xdf\x7f\xcf\xee\
+\xc7\x1e{d\x87qws+\x11x^'\x02\xdb\x09\
+\x9d\x86w\x8a\x0a\x94\x0e*\xfb4\x02o\xf4\x05\x8c\xc0\
+\xe7\xfb\x08\xb2\xea\x1f\xe8Z%\x95\xce \x9d\xca \x9d\
+\x91\x90H\xa44\xe09F\x06\x9e\xc0\xedr \x5c\x11\
+\x80C\xe4A8\x0e^\xaf\x1b\x02\xcf\x81\x13\x84e\x1f\
+\xba\xf4\xb2\xdf\xfc\xeb\x0f\x7f\x18D\x19\xa1\x9fQNk\
+\x02\x00\x05I\x90\x85\xd9'\xb0j\x02\xcd\x1f\x00\x10\xbf\
+\xef\xbe{vo\xdf\xfe\xc8\x0e\xb6\xc8\x94ny\xcf\xe7\
+\x11\x82N?g&\xc0\xda\xcbu\x07\xcf\xaeW3\xe0\
+\xcd>\x02\x03\xdex\xde\xe80\xca@N\x81\xac(H\
+\xa5\xd2Hg$\xc4\x13)p\xcc!$4<$\x1c\
+\x01\xc7s\xa8\xa8\x0c@\x14\xe9*)\xaf\xd7\x0d\x9e\x13\
+ \xf0\xfc\xf2\xa5\xed+\x7f\xfb\xd3g\x9e\x09\xce\xa4}\
+O\x87T\xf0\xb4\xa2(ys\x0c9\x18\xb6R\x9f\xe6\
+v\x02\x00\xf7\xddw\xcfn\x00\xd8\xb0a\xf3ZEK\
+\x0d\xd3,\x1b\x9b;\xa0(l.\x014\xdb]NH\
+g\x8c\xf1\x999P\xeb\xaf]g\x0d\x1b\x03\x01\x1f\xd2\
+\xc9\x0c\x9c\x0e\x07R\xa9\x14\x9c\x0e\x11\xf1x\x12N\xa7\
+\x83F\x04\xbc\xa0M\x85\xe39\x0e\x95\x15AD\x221\
+H\xd9\x1c\xbc\x1e\x17\xd2\x99\x0c\xb2$\xbb\xbc\xc6W\xbf\
+\xeb\xa9\x17_\x5c\x03 \x822\xe4\xb4\xd7\x00Ll4\
+\x81\x02{s\xc0\xa2\x03k\x88\x18\xbf\xef\xbe{v?\
+\xfa\xe8C;\xd823\xda\xeb\xcd?~\xc1\xb4\x81\x1e\
+\xba\x95\x1e\xd2\xe9\xfeB.O{PS\x91\x7f\xde\xe7\
+\xf3#1\x95@:\x93\x81\x02 \x99\xce \x95\xc9 \
+\x1eO\x82\xe7\x08\x04\x81\x03\xa7\xa6\x85\x01\x80\xe7xT\
+V\x04\xe0q\xbb\xc0q\x80\xdb\xe5\x84(\x8a\xe0\x09Y\
+\x11\xe0\x82\xbf\xde\xb9\xf3\xd5@9\xed\xfa\x9e!\x00\xa0\
+f7X\x16\xc7\x1c\xfa\x94\xe2\x18&\xa0\x92\xe0'?\
+yd\x87\xd1\x07\xb0#\x02-\xaf\xbc\x90\xce\xf8\xa9\xab\
+\x7f\x1dx\xddw0\x9f\x0f\x87+\x10\x8bL!\x9d\xa2\
+c\x0f\xc9d\x06\xe9L\x06\xe3\x91I\xd0\xfc\x13Q5\
+\x13\xa7-M\x0b\x05|p\xbb\xdd \x00\x5c.\xa7\xcc\
+\x8b|\x84\x00\x15.\xbf\xf3\xbf^z\xe9\xafm\xa5\xb6\
+\xe9{\x8a\x00\x16)\xe6\x18\x1a\xf3\x04V\x12$\xef\xbb\
+o\xdb\xcb\x8f>\xfa\xf0cl\xd9\xb9\x1d\x11\xe86l\
+\xe5\x85t\x85\xf3\x05f?\xc2H\x08\xfa<\x05^\x8f\
+\x17\x91\xb1(\xd2\xc9$\x00\x19\xc9T\x1a\xb9\xac\x82H\
+tJ}U\x0a>@s\x06\xe0\x80P\xd0\x07\xb7\xdb\
+\x99!\x04Cn\xa7\xb3O\x10\xf9>\xa2@\x82H>\
+\xfb\xc2\x0b\xaf\xd4\xa2\x04yO\x12\xa0\x809\xb0j\x02\
+;\x12h\xe6\xe0\x1b\xdf\xd8\xb6\xfb\xd1G\x1fzL\xef\
+\xf9f\x22\x14\xf2\xec\x8b\x85tv\xf9\x02c\xe4\xa0\x9f\
+\xd7\x817\x96\x93N\xa7\xde\xf8\xe3\x1fw\x7f11\x15\
+\x7fE\x91\x81d:\x0dI\xcab|b\x0a\x80\x0c\x02\
+\x9a,\xd2\x9a\x01J,\x14\xf4\x1d\xf58\x1d\xbd\x84\xa0\
+\xcf\xe5v\x1d\x11\x1d\xc2Q\x02e\x9cw\xbb/\xff\xed\
+o\xff2\xadcxZ\x8d\x05\xccD,\xfb\x18\x1ag\
+\x17\xd9mkk\xdd\xf2\xdes\xd7]\xf7~\xe8\x86\x1b\
+nZ\xcb\xc6\x0b\xd8\x18\xfb\x9bov\x22\x12\x89\xc1n\
+\xfe\x9d\xd1\x14\x00\xd61\x80\xe2\xe7\xed\x06\x85\x12\x89\xa9\
+\xee\xce\xce\xfd\x0f=\xfd\xf4C\xcf\x03H\xcd\x9b\xb7\x04\
+_\xb9\xf3\x1b\xff'\xe0\xf7_\x11\xf0\xfb\x10\x08x\xe1\
+t\x88\xa8\xac\x0cR\xed\x04E\x020\xce\x112\x0c(\
+\xc3\x00\x19\x8d\xc7S#\xf1xbL!\x18\x97r\xd9\
+\xf1TJ\x8a\x082\x19\xcdf\xc7\xffz\xf1\xc5\x17\xa7\
+\x0a\xb6\xdf{\x9d\x00@A\x12\x18\xa7\x971\x12X7\
+\xb9\xf6\x82\x92\xe0\xc3\x1b7\xde\xb4\x16\x80\x06\xd6\xde\xbd\
+\x07\x11\x89L\x96\xe5\xd9\x97\x0e<\xbdf||d\xcf\
+\xc1\x83\xaf?\xf1\xfc\xf3O\xbe\x0a\xaa\xad\x98\xd6J7\
+5\xcdU\xfe\xef\xbf\xfd\xc7\xbf\x07B\xc1\xeb\xddN\x17\
+\xbc\x1e'DQP*\xc3\xc1\x04O\xc80\x08\x19\x01\
+0\x0c\xc2\x8dr\x8a2\x0apc\xc9tj<\x12\x8d\
+Op\xbc<\x91\xcd*\xd1X\x22=\xc9I\xa9\xe8K\
+/\xfdj\xf8\xee\xbb\xef\xb6\x9d\x87\xf9\x9e\x08\x03K\x14\
+c\x88\xc8\xcc\x81\xdd5\xd6\xef\xca\xd7\xbf\xbe\xf5E\x9e\
+\xe7\x94\x0d\x1b6\xaf3\xae#`\xbd\xbf\xd4\x90\xae\x90\
+&0\x86\x8e\x89\xc4T\xcf\xb1c}\xcf\xbf\xfe\xfa\xef\
+^\xee\xe8\xd8\xdb\x07\x0a:;\x98\xe9\xca\xf4\xf7wf\
+\xd7~\xea\xcaM\xbf\xf8\xd5\xef\x93\xb2#wC<\x95\
+\xcay\x88kb|<:\x14\x0e\x87Fx`D\x01\
+O\xc1\xe71Nd\x8c\xbb\xdc\xae\x89\x0aE\x89D\x22\
+\xb1\xa8\xcc#\xc6\xb9\x9c\xb1\xd8\xb8\x94(\xd6hg\x84\
+\x06\x00\xa6\x9dTb\xa7\x09\x8cs\x0a<\x00\xdc\xf7\xdc\
+s\xdf\xc57\xdc\xb0i\x03\xa0\xe0\x95W\xf6ct4\
+\x02\xe3\x9c\x02#\xf0\xa5\x9c\xa73\x832\x89h4\xb2\
+\x7ftt\xe0\xcd\xbd{\xf7\xfc\xee\xe0\xc1\xbf\x1c\x85>\
+|k=$\xc3\xc1\xf2\xfc\xb9\xdf\xec\xfa\xf3\xf7\x04\x8e\
+\x5cNxn\xd8\xe7q\x0f\x8b\x227Z\x15\xae\x18\xe5\
+@\xc6\x14\x9e\x8cC\xc1\x04\xe1\x94\x09NFD\x96\x95\
+\xc9\xa9\xa9d,\x16\x1b\x9e\x02\x90x\xdf\xfb\xde\xa7u\
+\x04\xbb,\xe1\x19C\x00\xa0,\x12\x18\x7f\xf8\x82}\xba\
+\x01\xb8\xbe\xf2\x95-\x7f\xb3y\xf3-\x9b\xff\xf2\x97\x83\
+\xee\xd1\xd1\x88I\xfd\xb3\xf1\x81b\xc0G\xa3c\x1d\x13\
+\x13\x13\xbd\x91\xc8\xc8\xe1#G\xba\xba^}\xf5\xa5C\
+0\x03\xcb\x9cT\xbb\xeflB\x87\xf1P\x00(\xbf\xdd\
+\xf5\xdaW\x09\xc7\xaf\xe4En\xd4\xe3v\x8d:\x1c\xe2\
+xU\xc87N\x04q\x82\xc8\x88\xc8<\x89\x0a\x0a\x99\
+T\x94\xe4\x14\x80\xf8\xef~\xf7\xbb\xd4\xa7>\xf5\xa9\xfc\
+\xc9\xed\x16\xc0\xcf(\x02\x00\x05I`\xfc\xf9\x1bF\x02\
+\xe3F\xd7n\xc39\xc7\xa7?\xbdv\xcee\x97}j\
+\xcb\xd4T\xd2C\x97ie\x12\xb1\xd8\xe4\x11\xa3=\x1f\
+\x19\x198@\x08\xe4h4:<668\xb4\x7f\xff\
+\x9f\xba\x87\x87\x07'\xa1\x83\xc8\x22\x12\xeb\xa7ds\xde\
+\x0a\xbcq\x88W\x1b\xe4y\xe1w{\xd7r \xb3y\
+\x8e\x1bw\xb9\x5c\xe3\x0e'\x17\x09WUDx\x19\x93\
+\xb9\x1c&eY\x88\xc7b\xfd\xf1%K\x96\x14\xdd\xbd\
+\xd5H\x823\x8e\x00@\xc9\x9a\xc0\xa8\x0d\xd8\xef\x1f\xb8\
+\xd4\xff\x8b\xa0\xa41n\xbf\xca\x1a\xca\x18vZAc\
+\xdf\xb3%\x1ev\xbd\xdd4\xb6\x0f\xcb\xec\x9e]/\xef\
+\xfd\x10\xcfqaA\x14\x22.\x81\x8f\x12\x978\x19r\
+\xfbc>\x1f\x89\xef\xde\xbd;i\xd7\xeb\xed\x84=\xf3\
+\x8c$\x00`K\x02ct`\xfc\xcd\x03\xb6\x08\x85}\
+g\xd3\xcfx\xc3\xbd\x80\xb97\xca\x96\xc3J\x00v\x18\
+m9[\xb0a\x04\x9e\xddc\x04\xde\xd4\xeb\xed\xec\xf6\
+\xee\xdd\xaf\xcf\xcd\xf1\xc4\xe1\x80\x18\xe3yLE\x22\x8e\
+\xf8UW\xcd\x9bn\xe3\xee<Q\x14E9c\x09\x00\
+\x14%\x01\xfb\xbd\x03\xa3F\x10a\x06\x9fC\xbe\x06(\
+D\x82\x9c\xcd\xdf\x85\xb4\x83b8W\x10x\xa0\xf8\xd0\
+\xeeK/\xfd5\x14\x15\xe3\xb9\xa0$%\xd7\xacY3\
+\xc3\xb5\xc1g\xb0\x06`R`\xdd\x81\xf1\x87/\x8ck\
+\x10\xd8\xdfF\xf0\x0bi\x00\xeb\xa7\xb1'\xdb\x1d9\xcb\
+3r6\xcf\xa5'J\x04\xc5\xf0n3\x923^\x03\
+\x18\xa5\xc8zD\xce\xe6\xbb\x15|\xc0\x0c\x92\x1d\x09\xac\
+\xe7\xec\xce\xdb\xf5\xf4\xb2\x81/\xf0^e\xc9\x19\xef\x03\
+\xd8I\x01\x93\xc0Y\x0e\x82|\xf5\x0f\xe4\x83V\xca!\
+\xdb\x5c\x0f\x9c \xe8E\xde\xab$9\xe3\xa3\x80bR\
+\xc0$\x90\x02\x87\x9dXIP\xec\x9cI\xb5\xe3$\x03\
+o\x94RIp\xc6\xe7\x01J\x11KcY\x01/F\
+\x80\xbc\x1e\x5c\xe0\xbb\xddu'\x1dt\xabLG\x823\
+>\x13X\xae\xd8\x10\xc1\xee\xbbU\x0a5\x98\xed\xf9S\
+\x0d\xbaU\x0a\x91\xa0P=\xcej\x020)\xd2s\xac\
+>\xc0\xb4\xf2N\x03n'\xd6\xf7)V\xa7s\x04\xb0\
+\x91\x99\xa8\xd2\xd3M\xd8;LW\xd7s\x048\xcb\xe5\
+=9%\xec\x9c\x9c<\xf9\xff.}$/\xf4\x80\x9c\
+-\x00\x00\x00\x00IEND\xaeB`\x82\
+"
+
+qt_resource_name = b"\
+\x00\x06\
+\x07\x03}\xc3\
+\x00i\
+\x00m\x00a\x00g\x00e\x00s\
+\x00\x09\
+\x0b\x85\x83\x07\
+\x00c\
+\x00l\x00e\x00a\x00r\x00.\x00p\x00n\x00g\
+\x00\x0e\
+\x0a\x93\x87\x07\
+\x00d\
+\x00i\x00s\x00c\x00o\x00n\x00n\x00e\x00c\x00t\x00.\x00p\x00n\x00g\
+\x00\x0c\
+\x0b\xdf!G\
+\x00s\
+\x00e\x00t\x00t\x00i\x00n\x00g\x00s\x00.\x00p\x00n\x00g\
+\x00\x14\
+\x07@\xa2\xc7\
+\x00a\
+\x00p\x00p\x00l\x00i\x00c\x00a\x00t\x00i\x00o\x00n\x00-\x00e\x00x\x00i\x00t\x00.\
+\x00p\x00n\x00g\
+\x00\x0b\
+\x0bs\x9d\xc7\
+\x00c\
+\x00o\x00n\x00n\x00e\x00c\x00t\x00.\x00p\x00n\x00g\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00j\x00\x00\x00\x00\x00\x01\x00\x00\xaa\xa6\
+\x00\x00\x01\x81<\xe7\xd0\x1c\
+\x00\x00\x00*\x00\x00\x00\x00\x00\x01\x00\x001\x03\
+\x00\x00\x01\x81<\xe7\xd0\x1c\
+\x00\x00\x00\x98\x00\x00\x00\x00\x00\x01\x00\x00\xd6j\
+\x00\x00\x01\x81<\xe7\xd0\x1c\
+\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x81<\xe7\xd0\x1c\
+\x00\x00\x00L\x00\x00\x00\x00\x00\x01\x00\x00k\xfb\
+\x00\x00\x01\x81<\xe7\xd0\x1c\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/serialport/terminal/settingsdialog.py b/examples/serialport/terminal/settingsdialog.py
new file mode 100644
index 000000000..2a10d9a6c
--- /dev/null
+++ b/examples/serialport/terminal/settingsdialog.py
@@ -0,0 +1,216 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtCore import Slot
+from PySide6.QtGui import QIntValidator
+from PySide6.QtWidgets import QComboBox
+from PySide6.QtSerialPort import QSerialPort, QSerialPortInfo
+
+from PySide6.QtWidgets import QDialog
+
+from ui_settingsdialog import Ui_SettingsDialog
+
+
+BLANK_STRING = "N/A"
+
+
+CUSTOM_BAUDRATE_INDEX = 4
+
+
+class Settings():
+
+ def __init__(self):
+ self.name = ""
+ self.baud_rate = 0
+ self.string_baud_rate = ""
+ self.data_bits = QSerialPort.Data8
+ self.string_data_bits = ""
+ self.parity = QSerialPort.NoParity
+ self.string_parity = ""
+ self.stop_bits = QSerialPort.OneStop
+ self.string_stop_bits = ""
+ self.flow_control = QSerialPort.SoftwareControl
+ self.string_flow_control = ""
+ self.local_echo_enabled = False
+
+
+class SettingsDialog(QDialog):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ self.m_ui = Ui_SettingsDialog()
+ self._custom_port_index = -1
+ self.m_ui.setupUi(self)
+ self.m_currentSettings = Settings()
+ self.m_intValidator = QIntValidator(0, 4000000, self)
+
+ self.m_ui.baudRateBox.setInsertPolicy(QComboBox.NoInsert)
+
+ self.m_ui.applyButton.clicked.connect(self.apply)
+ self.m_ui.serialPortInfoListBox.currentIndexChanged.connect(self.show_port_info)
+ self.m_ui.baudRateBox.currentIndexChanged.connect(self.check_custom_baud_rate_policy)
+ self.m_ui.serialPortInfoListBox.currentIndexChanged.connect(self.check_custom_device_path_policy)
+
+ self.fill_ports_parameters()
+ self.fill_ports_info()
+
+ self.update_settings()
+
+ def settings(self):
+ return self.m_currentSettings
+
+ @Slot(int)
+ def show_port_info(self, idx):
+ if idx == -1:
+ return
+
+ list = self.m_ui.serialPortInfoListBox.itemData(idx)
+ count = len(list) if list else 0
+ description = list[1] if count > 1 else BLANK_STRING
+ self.m_ui.descriptionLabel.setText(f"Description: {description}")
+ manufacturer = list[2] if count > 2 else BLANK_STRING
+ self.m_ui.manufacturerLabel.setText(f"Manufacturer: {manufacturer}")
+ serialno = list[3] if count > 3 else BLANK_STRING
+ self.m_ui.serialNumberLabel.setText(f"Serial number: {serialno}")
+ location = list[4] if count > 4 else BLANK_STRING
+ self.m_ui.locationLabel.setText(f"Location: {location}")
+ vendor = list[5] if count > 5 else BLANK_STRING
+ self.m_ui.vidLabel.setText(f"Vendor Identifier: {vendor}")
+ id = list[6] if count > 6 else BLANK_STRING
+ self.m_ui.pidLabel.setText(f"Product Identifier: {id}")
+
+ @Slot()
+ def apply(self):
+ self.update_settings()
+ self.hide()
+
+ @Slot(int)
+ def check_custom_baud_rate_policy(self, idx):
+ is_custom_baud_rate = idx == CUSTOM_BAUDRATE_INDEX
+ self.m_ui.baudRateBox.setEditable(is_custom_baud_rate)
+ if is_custom_baud_rate:
+ self.m_ui.baudRateBox.clearEditText()
+ edit = self.m_ui.baudRateBox.lineEdit()
+ edit.setValidator(self.m_intValidator)
+
+ @Slot(int)
+ def check_custom_device_path_policy(self, idx):
+ is_custom_path = idx == self._custom_port_index
+ self.m_ui.serialPortInfoListBox.setEditable(is_custom_path)
+ if is_custom_path:
+ self.m_ui.serialPortInfoListBox.clearEditText()
+
+ def fill_ports_parameters(self):
+ self.m_ui.baudRateBox.addItem("9600", QSerialPort.Baud9600)
+ self.m_ui.baudRateBox.addItem("19200", QSerialPort.Baud19200)
+ self.m_ui.baudRateBox.addItem("38400", QSerialPort.Baud38400)
+ self.m_ui.baudRateBox.addItem("115200", QSerialPort.Baud115200)
+ self.m_ui.baudRateBox.addItem("Custom")
+
+ self.m_ui.dataBitsBox.addItem("5", QSerialPort.Data5)
+ self.m_ui.dataBitsBox.addItem("6", QSerialPort.Data6)
+ self.m_ui.dataBitsBox.addItem("7", QSerialPort.Data7)
+ self.m_ui.dataBitsBox.addItem("8", QSerialPort.Data8)
+ self.m_ui.dataBitsBox.setCurrentIndex(3)
+
+ self.m_ui.parityBox.addItem("None", QSerialPort.NoParity)
+ self.m_ui.parityBox.addItem("Even", QSerialPort.EvenParity)
+ self.m_ui.parityBox.addItem("Odd", QSerialPort.OddParity)
+ self.m_ui.parityBox.addItem("Mark", QSerialPort.MarkParity)
+ self.m_ui.parityBox.addItem("Space", QSerialPort.SpaceParity)
+
+ self.m_ui.stopBitsBox.addItem("1", QSerialPort.OneStop)
+ if sys.platform == "win32":
+ self.m_ui.stopBitsBox.addItem("1.5", QSerialPort.OneAndHalfStop)
+
+ self.m_ui.stopBitsBox.addItem("2", QSerialPort.TwoStop)
+
+ self.m_ui.flowControlBox.addItem("None", QSerialPort.NoFlowControl)
+ self.m_ui.flowControlBox.addItem("RTS/CTS", QSerialPort.HardwareControl)
+ self.m_ui.flowControlBox.addItem("XON/XOFF", QSerialPort.SoftwareControl)
+
+ def fill_ports_info(self):
+ self.m_ui.serialPortInfoListBox.clear()
+ for info in QSerialPortInfo.availablePorts():
+ list = []
+ description = info.description()
+ manufacturer = info.manufacturer()
+ serial_number = info.serialNumber()
+ list.append(info.portName())
+ list.append(description if description else BLANK_STRING)
+ list.append(manufacturer if manufacturer else BLANK_STRING)
+ list.append(serial_number if serial_number else BLANK_STRING)
+ list.append(info.systemLocation())
+ vid = info.vendorIdentifier()
+ list.append(f"{vid:x}" if vid else BLANK_STRING)
+ pid = info.productIdentifier()
+ list.append(f"{pid:x}" if pid else BLANK_STRING)
+ self.m_ui.serialPortInfoListBox.addItem(list[0], list)
+
+ self._custom_port_index = self.m_ui.serialPortInfoListBox.count()
+ self.m_ui.serialPortInfoListBox.addItem("Custom")
+
+ def update_settings(self):
+ self.m_currentSettings.name = self.m_ui.serialPortInfoListBox.currentText()
+
+ baud_index = self.m_ui.baudRateBox.currentIndex()
+ if baud_index == CUSTOM_BAUDRATE_INDEX:
+ text = self.m_ui.baudRateBox.currentText()
+ self.m_currentSettings.baud_rate = int(text)
+ else:
+ self.m_currentSettings.baud_rate = self.m_ui.baudRateBox.currentData()
+ self.m_currentSettings.string_baud_rate = f"{self.m_currentSettings.baud_rate}"
+
+ self.m_currentSettings.data_bits = self.m_ui.dataBitsBox.currentData()
+ self.m_currentSettings.string_data_bits = self.m_ui.dataBitsBox.currentText()
+
+ self.m_currentSettings.parity = self.m_ui.parityBox.currentData()
+ self.m_currentSettings.string_parity = self.m_ui.parityBox.currentText()
+
+ self.m_currentSettings.stop_bits = self.m_ui.stopBitsBox.currentData()
+ self.m_currentSettings.string_stop_bits = self.m_ui.stopBitsBox.currentText()
+
+ self.m_currentSettings.flow_control = self.m_ui.flowControlBox.currentData()
+ self.m_currentSettings.string_flow_control = self.m_ui.flowControlBox.currentText()
+
+ self.m_currentSettings.local_echo_enabled = self.m_ui.localEchoCheckBox.isChecked()
diff --git a/examples/serialport/terminal/settingsdialog.ui b/examples/serialport/terminal/settingsdialog.ui
new file mode 100644
index 000000000..8f15b1a52
--- /dev/null
+++ b/examples/serialport/terminal/settingsdialog.ui
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SettingsDialog</class>
+ <widget class="QDialog" name="SettingsDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>281</width>
+ <height>262</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Settings</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="1">
+ <widget class="QGroupBox" name="parametersBox">
+ <property name="title">
+ <string>Select Parameters</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QLabel" name="baudRateLabel">
+ <property name="text">
+ <string>BaudRate:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="baudRateBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="dataBitsLabel">
+ <property name="text">
+ <string>Data bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="dataBitsBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="parityLabel">
+ <property name="text">
+ <string>Parity:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="parityBox"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="stopBitsLabel">
+ <property name="text">
+ <string>Stop bits:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="stopBitsBox"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="flowControlLabel">
+ <property name="text">
+ <string>Flow control:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="flowControlBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QGroupBox" name="selectBox">
+ <property name="title">
+ <string>Select Serial Port</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QComboBox" name="serialPortInfoListBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="descriptionLabel">
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="manufacturerLabel">
+ <property name="text">
+ <string>Manufacturer:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="serialNumberLabel">
+ <property name="text">
+ <string>Serial number:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="locationLabel">
+ <property name="text">
+ <string>Location:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="vidLabel">
+ <property name="text">
+ <string>Vendor ID:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="pidLabel">
+ <property name="text">
+ <string>Product ID:</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>96</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="applyButton">
+ <property name="text">
+ <string>Apply</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QGroupBox" name="additionalOptionsGroupBox">
+ <property name="title">
+ <string>Additional options</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QCheckBox" name="localEchoCheckBox">
+ <property name="text">
+ <string>Local echo</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/serialport/terminal/terminal.pyproject b/examples/serialport/terminal/terminal.pyproject
new file mode 100644
index 000000000..ed64bd91a
--- /dev/null
+++ b/examples/serialport/terminal/terminal.pyproject
@@ -0,0 +1,4 @@
+{
+ "files": ["main.py", "console.py", "mainwindow.py", "mainwindow.ui",
+ "settingsdialog.py", "settingsdialog.ui", "terminal.qrc"]
+}
diff --git a/examples/serialport/terminal/terminal.qrc b/examples/serialport/terminal/terminal.qrc
new file mode 100644
index 000000000..0b4987941
--- /dev/null
+++ b/examples/serialport/terminal/terminal.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/connect.png</file>
+ <file>images/disconnect.png</file>
+ <file>images/application-exit.png</file>
+ <file>images/settings.png</file>
+ <file>images/clear.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/serialport/terminal/ui_mainwindow.py b/examples/serialport/terminal/ui_mainwindow.py
new file mode 100644
index 000000000..6aa0fcc53
--- /dev/null
+++ b/examples/serialport/terminal/ui_mainwindow.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'mainwindow.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.0
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
+ QCursor, QFont, QFontDatabase, QGradient,
+ QIcon, QImage, QKeySequence, QLinearGradient,
+ QPainter, QPalette, QPixmap, QRadialGradient,
+ QTransform)
+from PySide6.QtWidgets import (QApplication, QMainWindow, QMenu, QMenuBar,
+ QSizePolicy, QStatusBar, QToolBar, QVBoxLayout,
+ QWidget)
+import rc_terminal
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ if not MainWindow.objectName():
+ MainWindow.setObjectName(u"MainWindow")
+ MainWindow.resize(400, 300)
+ self.actionAbout = QAction(MainWindow)
+ self.actionAbout.setObjectName(u"actionAbout")
+ self.actionAboutQt = QAction(MainWindow)
+ self.actionAboutQt.setObjectName(u"actionAboutQt")
+ self.actionConnect = QAction(MainWindow)
+ self.actionConnect.setObjectName(u"actionConnect")
+ icon = QIcon()
+ icon.addFile(u":/images/connect.png", QSize(), QIcon.Normal, QIcon.Off)
+ self.actionConnect.setIcon(icon)
+ self.actionDisconnect = QAction(MainWindow)
+ self.actionDisconnect.setObjectName(u"actionDisconnect")
+ icon1 = QIcon()
+ icon1.addFile(u":/images/disconnect.png", QSize(), QIcon.Normal, QIcon.Off)
+ self.actionDisconnect.setIcon(icon1)
+ self.actionConfigure = QAction(MainWindow)
+ self.actionConfigure.setObjectName(u"actionConfigure")
+ icon2 = QIcon()
+ icon2.addFile(u":/images/settings.png", QSize(), QIcon.Normal, QIcon.Off)
+ self.actionConfigure.setIcon(icon2)
+ self.actionClear = QAction(MainWindow)
+ self.actionClear.setObjectName(u"actionClear")
+ icon3 = QIcon()
+ icon3.addFile(u":/images/clear.png", QSize(), QIcon.Normal, QIcon.Off)
+ self.actionClear.setIcon(icon3)
+ self.actionQuit = QAction(MainWindow)
+ self.actionQuit.setObjectName(u"actionQuit")
+ icon4 = QIcon()
+ icon4.addFile(u":/images/application-exit.png", QSize(), QIcon.Normal, QIcon.Off)
+ self.actionQuit.setIcon(icon4)
+ self.centralWidget = QWidget(MainWindow)
+ self.centralWidget.setObjectName(u"centralWidget")
+ self.verticalLayout = QVBoxLayout(self.centralWidget)
+ self.verticalLayout.setSpacing(6)
+ self.verticalLayout.setContentsMargins(11, 11, 11, 11)
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ MainWindow.setCentralWidget(self.centralWidget)
+ self.menuBar = QMenuBar(MainWindow)
+ self.menuBar.setObjectName(u"menuBar")
+ self.menuBar.setGeometry(QRect(0, 0, 400, 19))
+ self.menuCalls = QMenu(self.menuBar)
+ self.menuCalls.setObjectName(u"menuCalls")
+ self.menuTools = QMenu(self.menuBar)
+ self.menuTools.setObjectName(u"menuTools")
+ self.menuHelp = QMenu(self.menuBar)
+ self.menuHelp.setObjectName(u"menuHelp")
+ MainWindow.setMenuBar(self.menuBar)
+ self.mainToolBar = QToolBar(MainWindow)
+ self.mainToolBar.setObjectName(u"mainToolBar")
+ MainWindow.addToolBar(Qt.TopToolBarArea, self.mainToolBar)
+ self.statusBar = QStatusBar(MainWindow)
+ self.statusBar.setObjectName(u"statusBar")
+ MainWindow.setStatusBar(self.statusBar)
+
+ self.menuBar.addAction(self.menuCalls.menuAction())
+ self.menuBar.addAction(self.menuTools.menuAction())
+ self.menuBar.addAction(self.menuHelp.menuAction())
+ self.menuCalls.addAction(self.actionConnect)
+ self.menuCalls.addAction(self.actionDisconnect)
+ self.menuCalls.addSeparator()
+ self.menuCalls.addAction(self.actionQuit)
+ self.menuTools.addAction(self.actionConfigure)
+ self.menuTools.addAction(self.actionClear)
+ self.menuHelp.addAction(self.actionAbout)
+ self.menuHelp.addAction(self.actionAboutQt)
+ self.mainToolBar.addAction(self.actionConnect)
+ self.mainToolBar.addAction(self.actionDisconnect)
+ self.mainToolBar.addAction(self.actionConfigure)
+ self.mainToolBar.addAction(self.actionClear)
+
+ self.retranslateUi(MainWindow)
+
+ QMetaObject.connectSlotsByName(MainWindow)
+ # setupUi
+
+ def retranslateUi(self, MainWindow):
+ MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"Simple Terminal", None))
+ self.actionAbout.setText(QCoreApplication.translate("MainWindow", u"&About", None))
+#if QT_CONFIG(tooltip)
+ self.actionAbout.setToolTip(QCoreApplication.translate("MainWindow", u"About program", None))
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ self.actionAbout.setShortcut(QCoreApplication.translate("MainWindow", u"Alt+A", None))
+#endif // QT_CONFIG(shortcut)
+ self.actionAboutQt.setText(QCoreApplication.translate("MainWindow", u"About Qt", None))
+ self.actionConnect.setText(QCoreApplication.translate("MainWindow", u"C&onnect", None))
+#if QT_CONFIG(tooltip)
+ self.actionConnect.setToolTip(QCoreApplication.translate("MainWindow", u"Connect to serial port", None))
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ self.actionConnect.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+O", None))
+#endif // QT_CONFIG(shortcut)
+ self.actionDisconnect.setText(QCoreApplication.translate("MainWindow", u"&Disconnect", None))
+#if QT_CONFIG(tooltip)
+ self.actionDisconnect.setToolTip(QCoreApplication.translate("MainWindow", u"Disconnect from serial port", None))
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ self.actionDisconnect.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+D", None))
+#endif // QT_CONFIG(shortcut)
+ self.actionConfigure.setText(QCoreApplication.translate("MainWindow", u"&Configure", None))
+#if QT_CONFIG(tooltip)
+ self.actionConfigure.setToolTip(QCoreApplication.translate("MainWindow", u"Configure serial port", None))
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ self.actionConfigure.setShortcut(QCoreApplication.translate("MainWindow", u"Alt+C", None))
+#endif // QT_CONFIG(shortcut)
+ self.actionClear.setText(QCoreApplication.translate("MainWindow", u"C&lear", None))
+#if QT_CONFIG(tooltip)
+ self.actionClear.setToolTip(QCoreApplication.translate("MainWindow", u"Clear data", None))
+#endif // QT_CONFIG(tooltip)
+#if QT_CONFIG(shortcut)
+ self.actionClear.setShortcut(QCoreApplication.translate("MainWindow", u"Alt+L", None))
+#endif // QT_CONFIG(shortcut)
+ self.actionQuit.setText(QCoreApplication.translate("MainWindow", u"&Quit", None))
+#if QT_CONFIG(shortcut)
+ self.actionQuit.setShortcut(QCoreApplication.translate("MainWindow", u"Ctrl+Q", None))
+#endif // QT_CONFIG(shortcut)
+ self.menuCalls.setTitle(QCoreApplication.translate("MainWindow", u"Calls", None))
+ self.menuTools.setTitle(QCoreApplication.translate("MainWindow", u"Tools", None))
+ self.menuHelp.setTitle(QCoreApplication.translate("MainWindow", u"Help", None))
+ # retranslateUi
+
diff --git a/examples/serialport/terminal/ui_settingsdialog.py b/examples/serialport/terminal/ui_settingsdialog.py
new file mode 100644
index 000000000..212b60b25
--- /dev/null
+++ b/examples/serialport/terminal/ui_settingsdialog.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'settingsdialog.ui'
+##
+## Created by: Qt User Interface Compiler version 6.4.0
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+ QFont, QFontDatabase, QGradient, QIcon,
+ QImage, QKeySequence, QLinearGradient, QPainter,
+ QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QDialog,
+ QGridLayout, QGroupBox, QHBoxLayout, QLabel,
+ QPushButton, QSizePolicy, QSpacerItem, QVBoxLayout,
+ QWidget)
+
+class Ui_SettingsDialog(object):
+ def setupUi(self, SettingsDialog):
+ if not SettingsDialog.objectName():
+ SettingsDialog.setObjectName(u"SettingsDialog")
+ SettingsDialog.resize(281, 262)
+ self.gridLayout_3 = QGridLayout(SettingsDialog)
+ self.gridLayout_3.setObjectName(u"gridLayout_3")
+ self.parametersBox = QGroupBox(SettingsDialog)
+ self.parametersBox.setObjectName(u"parametersBox")
+ self.gridLayout_2 = QGridLayout(self.parametersBox)
+ self.gridLayout_2.setObjectName(u"gridLayout_2")
+ self.baudRateLabel = QLabel(self.parametersBox)
+ self.baudRateLabel.setObjectName(u"baudRateLabel")
+
+ self.gridLayout_2.addWidget(self.baudRateLabel, 0, 0, 1, 1)
+
+ self.baudRateBox = QComboBox(self.parametersBox)
+ self.baudRateBox.setObjectName(u"baudRateBox")
+
+ self.gridLayout_2.addWidget(self.baudRateBox, 0, 1, 1, 1)
+
+ self.dataBitsLabel = QLabel(self.parametersBox)
+ self.dataBitsLabel.setObjectName(u"dataBitsLabel")
+
+ self.gridLayout_2.addWidget(self.dataBitsLabel, 1, 0, 1, 1)
+
+ self.dataBitsBox = QComboBox(self.parametersBox)
+ self.dataBitsBox.setObjectName(u"dataBitsBox")
+
+ self.gridLayout_2.addWidget(self.dataBitsBox, 1, 1, 1, 1)
+
+ self.parityLabel = QLabel(self.parametersBox)
+ self.parityLabel.setObjectName(u"parityLabel")
+
+ self.gridLayout_2.addWidget(self.parityLabel, 2, 0, 1, 1)
+
+ self.parityBox = QComboBox(self.parametersBox)
+ self.parityBox.setObjectName(u"parityBox")
+
+ self.gridLayout_2.addWidget(self.parityBox, 2, 1, 1, 1)
+
+ self.stopBitsLabel = QLabel(self.parametersBox)
+ self.stopBitsLabel.setObjectName(u"stopBitsLabel")
+
+ self.gridLayout_2.addWidget(self.stopBitsLabel, 3, 0, 1, 1)
+
+ self.stopBitsBox = QComboBox(self.parametersBox)
+ self.stopBitsBox.setObjectName(u"stopBitsBox")
+
+ self.gridLayout_2.addWidget(self.stopBitsBox, 3, 1, 1, 1)
+
+ self.flowControlLabel = QLabel(self.parametersBox)
+ self.flowControlLabel.setObjectName(u"flowControlLabel")
+
+ self.gridLayout_2.addWidget(self.flowControlLabel, 4, 0, 1, 1)
+
+ self.flowControlBox = QComboBox(self.parametersBox)
+ self.flowControlBox.setObjectName(u"flowControlBox")
+
+ self.gridLayout_2.addWidget(self.flowControlBox, 4, 1, 1, 1)
+
+
+ self.gridLayout_3.addWidget(self.parametersBox, 0, 1, 1, 1)
+
+ self.selectBox = QGroupBox(SettingsDialog)
+ self.selectBox.setObjectName(u"selectBox")
+ self.gridLayout = QGridLayout(self.selectBox)
+ self.gridLayout.setObjectName(u"gridLayout")
+ self.serialPortInfoListBox = QComboBox(self.selectBox)
+ self.serialPortInfoListBox.setObjectName(u"serialPortInfoListBox")
+
+ self.gridLayout.addWidget(self.serialPortInfoListBox, 0, 0, 1, 1)
+
+ self.descriptionLabel = QLabel(self.selectBox)
+ self.descriptionLabel.setObjectName(u"descriptionLabel")
+
+ self.gridLayout.addWidget(self.descriptionLabel, 1, 0, 1, 1)
+
+ self.manufacturerLabel = QLabel(self.selectBox)
+ self.manufacturerLabel.setObjectName(u"manufacturerLabel")
+
+ self.gridLayout.addWidget(self.manufacturerLabel, 2, 0, 1, 1)
+
+ self.serialNumberLabel = QLabel(self.selectBox)
+ self.serialNumberLabel.setObjectName(u"serialNumberLabel")
+
+ self.gridLayout.addWidget(self.serialNumberLabel, 3, 0, 1, 1)
+
+ self.locationLabel = QLabel(self.selectBox)
+ self.locationLabel.setObjectName(u"locationLabel")
+
+ self.gridLayout.addWidget(self.locationLabel, 4, 0, 1, 1)
+
+ self.vidLabel = QLabel(self.selectBox)
+ self.vidLabel.setObjectName(u"vidLabel")
+
+ self.gridLayout.addWidget(self.vidLabel, 5, 0, 1, 1)
+
+ self.pidLabel = QLabel(self.selectBox)
+ self.pidLabel.setObjectName(u"pidLabel")
+
+ self.gridLayout.addWidget(self.pidLabel, 6, 0, 1, 1)
+
+
+ self.gridLayout_3.addWidget(self.selectBox, 0, 0, 1, 1)
+
+ self.horizontalLayout = QHBoxLayout()
+ self.horizontalLayout.setObjectName(u"horizontalLayout")
+ self.horizontalSpacer = QSpacerItem(96, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
+
+ self.horizontalLayout.addItem(self.horizontalSpacer)
+
+ self.applyButton = QPushButton(SettingsDialog)
+ self.applyButton.setObjectName(u"applyButton")
+
+ self.horizontalLayout.addWidget(self.applyButton)
+
+
+ self.gridLayout_3.addLayout(self.horizontalLayout, 2, 0, 1, 2)
+
+ self.additionalOptionsGroupBox = QGroupBox(SettingsDialog)
+ self.additionalOptionsGroupBox.setObjectName(u"additionalOptionsGroupBox")
+ self.verticalLayout = QVBoxLayout(self.additionalOptionsGroupBox)
+ self.verticalLayout.setObjectName(u"verticalLayout")
+ self.localEchoCheckBox = QCheckBox(self.additionalOptionsGroupBox)
+ self.localEchoCheckBox.setObjectName(u"localEchoCheckBox")
+ self.localEchoCheckBox.setChecked(True)
+
+ self.verticalLayout.addWidget(self.localEchoCheckBox)
+
+
+ self.gridLayout_3.addWidget(self.additionalOptionsGroupBox, 1, 0, 1, 2)
+
+
+ self.retranslateUi(SettingsDialog)
+
+ QMetaObject.connectSlotsByName(SettingsDialog)
+ # setupUi
+
+ def retranslateUi(self, SettingsDialog):
+ SettingsDialog.setWindowTitle(QCoreApplication.translate("SettingsDialog", u"Settings", None))
+ self.parametersBox.setTitle(QCoreApplication.translate("SettingsDialog", u"Select Parameters", None))
+ self.baudRateLabel.setText(QCoreApplication.translate("SettingsDialog", u"BaudRate:", None))
+ self.dataBitsLabel.setText(QCoreApplication.translate("SettingsDialog", u"Data bits:", None))
+ self.parityLabel.setText(QCoreApplication.translate("SettingsDialog", u"Parity:", None))
+ self.stopBitsLabel.setText(QCoreApplication.translate("SettingsDialog", u"Stop bits:", None))
+ self.flowControlLabel.setText(QCoreApplication.translate("SettingsDialog", u"Flow control:", None))
+ self.selectBox.setTitle(QCoreApplication.translate("SettingsDialog", u"Select Serial Port", None))
+ self.descriptionLabel.setText(QCoreApplication.translate("SettingsDialog", u"Description:", None))
+ self.manufacturerLabel.setText(QCoreApplication.translate("SettingsDialog", u"Manufacturer:", None))
+ self.serialNumberLabel.setText(QCoreApplication.translate("SettingsDialog", u"Serial number:", None))
+ self.locationLabel.setText(QCoreApplication.translate("SettingsDialog", u"Location:", None))
+ self.vidLabel.setText(QCoreApplication.translate("SettingsDialog", u"Vendor ID:", None))
+ self.pidLabel.setText(QCoreApplication.translate("SettingsDialog", u"Product ID:", None))
+ self.applyButton.setText(QCoreApplication.translate("SettingsDialog", u"Apply", None))
+ self.additionalOptionsGroupBox.setTitle(QCoreApplication.translate("SettingsDialog", u"Additional options", None))
+ self.localEchoCheckBox.setText(QCoreApplication.translate("SettingsDialog", u"Local echo", None))
+ # retranslateUi
+
diff --git a/examples/sql/books/bookdelegate.py b/examples/sql/books/bookdelegate.py
index 1af914d7d..0c3f83f27 100644
--- a/examples/sql/books/bookdelegate.py
+++ b/examples/sql/books/bookdelegate.py
@@ -90,8 +90,6 @@ class BookDelegate(QSqlRelationalDelegate):
painter.drawPixmap(x, y, self.star)
x += width
- # Since we draw the grid ourselves:
- self.drawFocus(painter, option, option.rect.adjusted(0, 0, -1, -1))
pen = painter.pen()
painter.setPen(option.palette.color(QPalette.Mid))
diff --git a/examples/texttospeech/hello_speak/hello_speak.py b/examples/texttospeech/hello_speak/hello_speak.py
index 97a46121d..2d1fcc882 100644
--- a/examples/texttospeech/hello_speak/hello_speak.py
+++ b/examples/texttospeech/hello_speak/hello_speak.py
@@ -42,7 +42,7 @@
"""PySide6 QTextToSpeech example"""
import sys
-from PySide6.QtCore import Qt
+from PySide6.QtCore import Qt, Slot
from PySide6.QtWidgets import (QApplication, QComboBox, QFormLayout,
QHBoxLayout, QLineEdit, QMainWindow, QPushButton, QSlider, QWidget)
@@ -91,12 +91,14 @@ class MainWindow(QMainWindow):
self.setWindowTitle('QTextToSpeech Example (no engines available)')
self.sayButton.setEnabled(False)
+ @Slot()
def say(self):
self.sayButton.setEnabled(False)
self.engine.setVoice(self.voices[self.voiceCombo.currentIndex()])
self.engine.setVolume(float(self.volumeSlider.value()) / 100)
self.engine.say(self.text.text())
+ @Slot("QTextToSpeech::State")
def stateChanged(self, state):
if (state == QTextToSpeech.State.Ready):
self.sayButton.setEnabled(True)
diff --git a/examples/webenginequick/nanobrowser/quicknanobrowser.py b/examples/webenginequick/nanobrowser/quicknanobrowser.py
index 393bf5808..119bea213 100644
--- a/examples/webenginequick/nanobrowser/quicknanobrowser.py
+++ b/examples/webenginequick/nanobrowser/quicknanobrowser.py
@@ -48,8 +48,8 @@ from PySide6.QtWebEngineQuick import QtWebEngineQuick
def main():
- app = QApplication([])
QtWebEngineQuick.initialize()
+ app = QApplication([])
engine = QQmlApplicationEngine()
qml_file_path = os.path.join(os.path.dirname(__file__), 'browser.qml')
qml_url = QUrl.fromLocalFile(os.path.abspath(qml_file_path))
diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.py b/examples/webenginewidgets/markdowneditor/mainwindow.py
index 5bf455b96..ff5eb9c19 100644
--- a/examples/webenginewidgets/markdowneditor/mainwindow.py
+++ b/examples/webenginewidgets/markdowneditor/mainwindow.py
@@ -84,7 +84,7 @@ class MainWindow(QMainWindow):
data = defaultTextFile.readAll()
self._ui.editor.setPlainText(data.data().decode('utf8'))
- @Slot(str)
+ @Slot()
def plainTextEditChanged(self):
self.m_content.setText(self._ui.editor.toPlainText())
diff --git a/examples/webenginewidgets/simplebrowser/simplebrowser.py b/examples/webenginewidgets/simplebrowser/simplebrowser.py
index f5d550439..557f9fec6 100644
--- a/examples/webenginewidgets/simplebrowser/simplebrowser.py
+++ b/examples/webenginewidgets/simplebrowser/simplebrowser.py
@@ -42,7 +42,7 @@
"""PySide6 WebEngineWidgets Example"""
import sys
-from PySide6.QtCore import QUrl
+from PySide6.QtCore import QUrl, Slot
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import (QApplication, QLineEdit,
QMainWindow, QPushButton, QToolBar)
@@ -80,17 +80,21 @@ class MainWindow(QMainWindow):
self.webEngineView.page().titleChanged.connect(self.setWindowTitle)
self.webEngineView.page().urlChanged.connect(self.urlChanged)
+ @Slot()
def load(self):
url = QUrl.fromUserInput(self.addressLineEdit.text())
if url.isValid():
self.webEngineView.load(url)
+ @Slot()
def back(self):
self.webEngineView.page().triggerAction(QWebEnginePage.Back)
+ @Slot()
def forward(self):
self.webEngineView.page().triggerAction(QWebEnginePage.Forward)
+ @Slot(QUrl)
def urlChanged(self, url):
self.addressLineEdit.setText(url.toString())
diff --git a/examples/webenginewidgets/tabbedbrowser/browsertabwidget.py b/examples/webenginewidgets/tabbedbrowser/browsertabwidget.py
index 1fb7ead45..5930902b6 100644
--- a/examples/webenginewidgets/tabbedbrowser/browsertabwidget.py
+++ b/examples/webenginewidgets/tabbedbrowser/browsertabwidget.py
@@ -43,8 +43,8 @@ from functools import partial
from bookmarkwidget import BookmarkWidget
from webengineview import WebEngineView
from historywindow import HistoryWindow
-from PySide6 import QtCore
-from PySide6.QtCore import Qt, QUrl
+from PySide6.QtCore import Qt, QUrl, Signal, Slot
+from PySide6.QtGui import QIcon
from PySide6.QtWidgets import QMenu, QTabBar, QTabWidget
from PySide6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEnginePage
@@ -52,9 +52,9 @@ from PySide6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEnginePage
class BrowserTabWidget(QTabWidget):
"""Enables having several tabs with QWebEngineView."""
- url_changed = QtCore.Signal(QUrl)
- enabled_changed = QtCore.Signal(QWebEnginePage.WebAction, bool)
- download_requested = QtCore.Signal(QWebEngineDownloadRequest)
+ url_changed = Signal(QUrl)
+ enabled_changed = Signal(QWebEnginePage.WebAction, bool)
+ download_requested = Signal(QWebEngineDownloadRequest)
def __init__(self, window_factory_function):
super().__init__()
@@ -104,21 +104,25 @@ class BrowserTabWidget(QTabWidget):
index = self.currentIndex()
return self._webengineviews[index].url() if index >= 0 else QUrl()
+ @Slot(QUrl)
def _url_changed(self, url):
index = self.currentIndex()
if index >= 0 and self._webengineviews[index] == self.sender():
self.url_changed.emit(url)
+ @Slot(str)
def _title_changed(self, title):
index = self._index_of_page(self.sender())
if (index >= 0):
self.setTabText(index, BookmarkWidget.short_title(title))
+ @Slot(QIcon)
def _icon_changed(self, icon):
index = self._index_of_page(self.sender())
if (index >= 0):
self.setTabIcon(index, icon)
+ @Slot(object,bool)
def _enabled_changed(self, web_action, enabled):
index = self.currentIndex()
if index >= 0 and self._webengineviews[index] == self.sender():
@@ -240,5 +244,6 @@ class BrowserTabWidget(QTabWidget):
return p
return -1
+ @Slot(QWebEngineDownloadRequest)
def _download_requested(self, item):
self.download_requested.emit(item)
diff --git a/examples/webenginewidgets/tabbedbrowser/webengineview.py b/examples/webenginewidgets/tabbedbrowser/webengineview.py
index 185be0a31..47b3598c2 100644
--- a/examples/webenginewidgets/tabbedbrowser/webengineview.py
+++ b/examples/webenginewidgets/tabbedbrowser/webengineview.py
@@ -41,7 +41,7 @@
from PySide6.QtWebEngineCore import QWebEnginePage
from PySide6.QtWebEngineWidgets import QWebEngineView
-from PySide6 import QtCore
+from PySide6.QtCore import Signal, Slot
_web_actions = [QWebEnginePage.Back, QWebEnginePage.Forward,
QWebEnginePage.Reload,
@@ -52,7 +52,7 @@ _web_actions = [QWebEnginePage.Back, QWebEnginePage.Forward,
class WebEngineView(QWebEngineView):
- enabled_changed = QtCore.Signal(QWebEnginePage.WebAction, bool)
+ enabled_changed = Signal(QWebEnginePage.WebAction, bool)
@staticmethod
def web_actions():
@@ -86,6 +86,7 @@ class WebEngineView(QWebEngineView):
return self._tab_factory_func()
return self._window_factory_func()
+ @Slot()
def _enabled_changed(self):
action = self.sender()
web_action = self._actions[action]
diff --git a/examples/widgetbinding/CMakeLists.txt b/examples/widgetbinding/CMakeLists.txt
index 2fe1ddcb0..c51f47620 100644
--- a/examples/widgetbinding/CMakeLists.txt
+++ b/examples/widgetbinding/CMakeLists.txt
@@ -52,7 +52,7 @@ set(generated_sources
# ================================== Shiboken detection ======================================
# Use provided python interpreter if given.
if(NOT python_interpreter)
- if(WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+ if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
find_program(python_interpreter "python_d")
if(NOT python_interpreter)
message(FATAL_ERROR
@@ -218,7 +218,7 @@ set_property(TARGET ${bindings_library} PROPERTY PREFIX "")
set_property(TARGET ${bindings_library} PROPERTY OUTPUT_NAME
"${bindings_library}${PYTHON_EXTENSION_SUFFIX}")
if(WIN32)
- if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+ if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set_property(TARGET ${bindings_library} PROPERTY SUFFIX "_d.pyd")
else()
set_property(TARGET ${bindings_library} PROPERTY SUFFIX ".pyd")
diff --git a/examples/widgets/animation/easing/easing.py b/examples/widgets/animation/easing/easing.py
index 6df69717c..a7aee6cb5 100644
--- a/examples/widgets/animation/easing/easing.py
+++ b/examples/widgets/animation/easing/easing.py
@@ -148,7 +148,7 @@ class Window(QWidget):
self._anim = Animation(self._item, b'pos')
self._anim.setEasingCurve(QEasingCurve.OutBounce)
- self._ui.easingCurvePicker.setCurrentRow(int(QEasingCurve.OutBounce))
+ self._ui.easingCurvePicker.setCurrentRow(0)
self.start_animation()
@@ -161,15 +161,8 @@ class Window(QWidget):
brush = QBrush(gradient)
- # The original C++ code uses undocumented calls to get the names of the
- # different curve types. We do the Python equivalant (but without
- # cheating)
- curve_types = [(n, c) for n, c in QEasingCurve.__dict__.items()
- if (isinstance(c, QEasingCurve.Type)
- and c != QEasingCurve.Custom
- and c != QEasingCurve.NCurveTypes
- and c != QEasingCurve.TCBSpline)]
- curve_types.sort(key=lambda ct: ct[1])
+ curve_types = [(f"QEasingCurve.{e.name}", e) for e in QEasingCurve.Type if e.value <= 40]
+
with QPainter(pix) as painter:
@@ -229,15 +222,15 @@ class Window(QWidget):
self._anim.setEasingCurve(curve_type)
self._anim.setCurrentTime(0)
- is_elastic = (curve_type >= QEasingCurve.InElastic
- and curve_type <= QEasingCurve.OutInElastic)
- is_bounce = (curve_type >= QEasingCurve.InBounce
- and curve_type <= QEasingCurve.OutInBounce)
+ is_elastic = (curve_type.value >= QEasingCurve.InElastic.value
+ and curve_type.value <= QEasingCurve.OutInElastic.value)
+ is_bounce = (curve_type.value >= QEasingCurve.InBounce.value
+ and curve_type.value <= QEasingCurve.OutInBounce.value)
self._ui.periodSpinBox.setEnabled(is_elastic)
self._ui.amplitudeSpinBox.setEnabled(is_elastic or is_bounce)
- self._ui.overshootSpinBox.setEnabled(curve_type >= QEasingCurve.InBack
- and curve_type <= QEasingCurve.OutInBack)
+ self._ui.overshootSpinBox.setEnabled(curve_type.value >= QEasingCurve.InBack.value
+ and curve_type.value <= QEasingCurve.OutInBack.value)
def path_changed(self, index):
self._anim.set_path_type(index)
diff --git a/examples/widgets/animation/easing/form.ui b/examples/widgets/animation/easing/form.ui
index 2397b1787..364aebeda 100644
--- a/examples/widgets/animation/easing/form.ui
+++ b/examples/widgets/animation/easing/form.ui
@@ -49,12 +49,27 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>16777215</height>
+ </size>
+ </property>
<property name="title">
<string>Path type</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
<widget class="QRadioButton" name="lineRadio">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>40</height>
+ </size>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
<property name="text">
<string>Line</string>
</property>
@@ -62,17 +77,23 @@
<bool>true</bool>
</property>
<attribute name="buttonGroup">
- <string notr="true">buttonGroup</string>
+ <string>buttonGroup</string>
</attribute>
</widget>
</item>
- <item>
+ <item row="1" column="0">
<widget class="QRadioButton" name="circleRadio">
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>40</height>
+ </size>
+ </property>
<property name="text">
<string>Circle</string>
</property>
<attribute name="buttonGroup">
- <string notr="true">buttonGroup</string>
+ <string>buttonGroup</string>
</attribute>
</widget>
</item>
@@ -96,6 +117,18 @@
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
<property name="text">
<string>Period</string>
</property>
@@ -106,6 +139,18 @@
<property name="enabled">
<bool>false</bool>
</property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
@@ -117,18 +162,17 @@
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Amplitude</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
+ <item row="2" column="1">
<widget class="QDoubleSpinBox" name="amplitudeSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
@@ -140,18 +184,30 @@
</property>
</widget>
</item>
- <item row="2" column="0">
+ <item row="4" column="0">
<widget class="QLabel" name="label_3">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
<property name="text">
<string>Overshoot</string>
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="4" column="1">
<widget class="QDoubleSpinBox" name="overshootSpinBox">
<property name="enabled">
<bool>false</bool>
</property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
<property name="minimum">
<double>-1.000000000000000</double>
</property>
@@ -163,6 +219,19 @@
</property>
</widget>
</item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>30</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>Amplitude</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
@@ -196,10 +265,6 @@
<resources/>
<connections/>
<buttongroups>
- <buttongroup name="buttonGroup">
- <property name="exclusive">
- <bool>true</bool>
- </property>
- </buttongroup>
+ <buttongroup name="buttonGroup"/>
</buttongroups>
</ui>
diff --git a/examples/widgets/animation/easing/ui_form.py b/examples/widgets/animation/easing/ui_form.py
index 07bfa8fb3..0ff7a1547 100644
--- a/examples/widgets/animation/easing/ui_form.py
+++ b/examples/widgets/animation/easing/ui_form.py
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
################################################################################
-## Form generated from reading UI file 'form.ui'
+## Form generated from reading UI file 'form2.ui'
##
-## Created by: Qt User Interface Compiler version 6.2.3
+## Created by: Qt User Interface Compiler version 6.4.0
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
@@ -47,23 +47,26 @@ class Ui_Form(object):
self.verticalLayout.setObjectName(u"verticalLayout")
self.groupBox_2 = QGroupBox(Form)
self.groupBox_2.setObjectName(u"groupBox_2")
- self.verticalLayout_2 = QVBoxLayout(self.groupBox_2)
- self.verticalLayout_2.setObjectName(u"verticalLayout_2")
+ self.groupBox_2.setMaximumSize(QSize(16777215, 16777215))
+ self.gridLayout_2 = QGridLayout(self.groupBox_2)
+ self.gridLayout_2.setObjectName(u"gridLayout_2")
self.lineRadio = QRadioButton(self.groupBox_2)
self.buttonGroup = QButtonGroup(Form)
self.buttonGroup.setObjectName(u"buttonGroup")
- self.buttonGroup.setExclusive(True)
self.buttonGroup.addButton(self.lineRadio)
self.lineRadio.setObjectName(u"lineRadio")
+ self.lineRadio.setMaximumSize(QSize(16777215, 40))
+ self.lineRadio.setLayoutDirection(Qt.LeftToRight)
self.lineRadio.setChecked(True)
- self.verticalLayout_2.addWidget(self.lineRadio)
+ self.gridLayout_2.addWidget(self.lineRadio, 0, 0, 1, 1)
self.circleRadio = QRadioButton(self.groupBox_2)
self.buttonGroup.addButton(self.circleRadio)
self.circleRadio.setObjectName(u"circleRadio")
+ self.circleRadio.setMaximumSize(QSize(16777215, 40))
- self.verticalLayout_2.addWidget(self.circleRadio)
+ self.gridLayout_2.addWidget(self.circleRadio, 1, 0, 1, 1)
self.verticalLayout.addWidget(self.groupBox_2)
@@ -80,45 +83,61 @@ class Ui_Form(object):
self.formLayout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow)
self.label = QLabel(self.groupBox)
self.label.setObjectName(u"label")
+ sizePolicy2 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
+ sizePolicy2.setHorizontalStretch(0)
+ sizePolicy2.setVerticalStretch(0)
+ sizePolicy2.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
+ self.label.setSizePolicy(sizePolicy2)
+ self.label.setMinimumSize(QSize(0, 30))
self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label)
self.periodSpinBox = QDoubleSpinBox(self.groupBox)
self.periodSpinBox.setObjectName(u"periodSpinBox")
self.periodSpinBox.setEnabled(False)
+ sizePolicy3 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
+ sizePolicy3.setHorizontalStretch(0)
+ sizePolicy3.setVerticalStretch(0)
+ sizePolicy3.setHeightForWidth(self.periodSpinBox.sizePolicy().hasHeightForWidth())
+ self.periodSpinBox.setSizePolicy(sizePolicy3)
+ self.periodSpinBox.setMinimumSize(QSize(0, 30))
self.periodSpinBox.setMinimum(-1.000000000000000)
self.periodSpinBox.setSingleStep(0.100000000000000)
self.periodSpinBox.setValue(-1.000000000000000)
self.formLayout.setWidget(0, QFormLayout.FieldRole, self.periodSpinBox)
- self.label_2 = QLabel(self.groupBox)
- self.label_2.setObjectName(u"label_2")
-
- self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2)
-
self.amplitudeSpinBox = QDoubleSpinBox(self.groupBox)
self.amplitudeSpinBox.setObjectName(u"amplitudeSpinBox")
self.amplitudeSpinBox.setEnabled(False)
+ self.amplitudeSpinBox.setMinimumSize(QSize(0, 30))
self.amplitudeSpinBox.setMinimum(-1.000000000000000)
self.amplitudeSpinBox.setSingleStep(0.100000000000000)
self.amplitudeSpinBox.setValue(-1.000000000000000)
- self.formLayout.setWidget(1, QFormLayout.FieldRole, self.amplitudeSpinBox)
+ self.formLayout.setWidget(2, QFormLayout.FieldRole, self.amplitudeSpinBox)
self.label_3 = QLabel(self.groupBox)
self.label_3.setObjectName(u"label_3")
+ self.label_3.setMinimumSize(QSize(0, 30))
- self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3)
+ self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_3)
self.overshootSpinBox = QDoubleSpinBox(self.groupBox)
self.overshootSpinBox.setObjectName(u"overshootSpinBox")
self.overshootSpinBox.setEnabled(False)
+ self.overshootSpinBox.setMinimumSize(QSize(0, 30))
self.overshootSpinBox.setMinimum(-1.000000000000000)
self.overshootSpinBox.setSingleStep(0.100000000000000)
self.overshootSpinBox.setValue(-1.000000000000000)
- self.formLayout.setWidget(2, QFormLayout.FieldRole, self.overshootSpinBox)
+ self.formLayout.setWidget(4, QFormLayout.FieldRole, self.overshootSpinBox)
+
+ self.label_2 = QLabel(self.groupBox)
+ self.label_2.setObjectName(u"label_2")
+ self.label_2.setMinimumSize(QSize(0, 30))
+
+ self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_2)
self.verticalLayout.addWidget(self.groupBox)
@@ -132,11 +151,11 @@ class Ui_Form(object):
self.graphicsView = QGraphicsView(Form)
self.graphicsView.setObjectName(u"graphicsView")
- sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
- sizePolicy2.setHorizontalStretch(0)
- sizePolicy2.setVerticalStretch(0)
- sizePolicy2.setHeightForWidth(self.graphicsView.sizePolicy().hasHeightForWidth())
- self.graphicsView.setSizePolicy(sizePolicy2)
+ sizePolicy4 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ sizePolicy4.setHorizontalStretch(0)
+ sizePolicy4.setVerticalStretch(0)
+ sizePolicy4.setHeightForWidth(self.graphicsView.sizePolicy().hasHeightForWidth())
+ self.graphicsView.setSizePolicy(sizePolicy4)
self.gridLayout.addWidget(self.graphicsView, 1, 1, 1, 1)
@@ -153,7 +172,7 @@ class Ui_Form(object):
self.circleRadio.setText(QCoreApplication.translate("Form", u"Circle", None))
self.groupBox.setTitle(QCoreApplication.translate("Form", u"Properties", None))
self.label.setText(QCoreApplication.translate("Form", u"Period", None))
- self.label_2.setText(QCoreApplication.translate("Form", u"Amplitude", None))
self.label_3.setText(QCoreApplication.translate("Form", u"Overshoot", None))
+ self.label_2.setText(QCoreApplication.translate("Form", u"Amplitude", None))
# retranslateUi
diff --git a/examples/widgets/codeeditor/codeeditor.py b/examples/widgets/codeeditor/codeeditor.py
index 25290c63f..1961b2f4b 100644
--- a/examples/widgets/codeeditor/codeeditor.py
+++ b/examples/widgets/codeeditor/codeeditor.py
@@ -106,11 +106,11 @@ class CodeEditor(QPlainTextEdit):
bottom = top + self.blockBoundingRect(block).height()
block_number += 1
- @Slot()
+ @Slot(int)
def update_line_number_area_width(self, newBlockCount):
self.setViewportMargins(self.line_number_area_width(), 0, 0, 0)
- @Slot()
+ @Slot(QRect, int)
def update_line_number_area(self, rect, dy):
if dy:
self.line_number_area.scroll(0, dy)
diff --git a/examples/widgets/desktop/screenshot/screenshot.py b/examples/widgets/desktop/screenshot/screenshot.py
index 19aa4c354..529f35bba 100644
--- a/examples/widgets/desktop/screenshot/screenshot.py
+++ b/examples/widgets/desktop/screenshot/screenshot.py
@@ -42,7 +42,8 @@
import sys
-from PySide6.QtCore import QDir, QPoint, QRect, QStandardPaths, Qt, QTimer
+from PySide6.QtCore import (QDir, QPoint, QRect, QStandardPaths, Qt, QTimer,
+ Slot)
from PySide6.QtGui import QGuiApplication, QImageWriter
from PySide6.QtWidgets import (QApplication, QCheckBox, QDialog, QFileDialog,
QGridLayout, QGroupBox, QHBoxLayout, QLabel,
@@ -109,6 +110,7 @@ class Screenshot(QWidget):
if scaled_size != self.screenshot_label.pixmap().size():
self.update_screenshot_label()
+ @Slot()
def new_screenshot(self):
if self.hide_this_window_checkbox.isChecked():
self.hide()
@@ -116,6 +118,7 @@ class Screenshot(QWidget):
QTimer.singleShot(self.delay_spinbox.value() * 1000, self.shoot_screen)
+ @Slot()
def save_screenshot(self):
fmt = "png" # In order to avoid shadowing built-in format
initial_path = QStandardPaths.writableLocation(QStandardPaths.PicturesLocation)
@@ -164,6 +167,7 @@ class Screenshot(QWidget):
if self.hide_this_window_checkbox.isChecked():
self.show()
+ @Slot()
def update_checkbox(self):
if self.delay_spinbox.value() == 0:
self.hide_this_window_checkbox.setDisabled(True)
diff --git a/examples/widgets/dialogs/standarddialogs/standarddialogs.py b/examples/widgets/dialogs/standarddialogs/standarddialogs.py
index e456893e3..4cc324ef0 100644
--- a/examples/widgets/dialogs/standarddialogs/standarddialogs.py
+++ b/examples/widgets/dialogs/standarddialogs/standarddialogs.py
@@ -43,7 +43,7 @@
"""PySide6 port of the widgets/dialogs/standarddialogs example from Qt v5.x"""
import sys
-from PySide6.QtCore import QDir, QRect, Qt
+from PySide6.QtCore import QDir, QRect, Qt, Slot
from PySide6.QtGui import QFont, QPalette, QScreen
from PySide6.QtWidgets import (QApplication, QColorDialog, QCheckBox, QDialog,
QErrorMessage, QFontDialog, QFileDialog, QFrame,
@@ -275,18 +275,21 @@ class Dialog(QDialog):
self.setWindowTitle("Standard Dialogs")
+ @Slot()
def set_integer(self):
i, ok = QInputDialog.getInt(self,
"QInputDialog.getInteger()", "Percentage:", 25, 0, 100, 1)
if ok:
self._integer_label.setText(f"{i}%")
+ @Slot()
def set_double(self):
d, ok = QInputDialog.getDouble(self, "QInputDialog.getDouble()",
"Amount:", 37.56, -10000, 10000, 2)
if ok:
self._double_label.setText(f"${d:g}")
+ @Slot()
def set_item(self):
items = ("Spring", "Summer", "Fall", "Winter")
@@ -295,6 +298,7 @@ class Dialog(QDialog):
if ok and item:
self._item_label.setText(item)
+ @Slot()
def set_text(self):
text, ok = QInputDialog.getText(self, "QInputDialog.getText()",
"User name:", QLineEdit.Normal,
@@ -302,12 +306,14 @@ class Dialog(QDialog):
if ok and text != '':
self._text_label.setText(text)
+ @Slot()
def set_multiline_text(self):
text, ok = QInputDialog.getMultiLineText(self, "QInputDialog::getMultiLineText()",
"Address:", "John Doe\nFreedom Street")
if ok and text != '':
self._multiline_text_label.setText(text)
+ @Slot()
def set_color(self):
options_value = self._color_options.value()
options = QColorDialog.ColorDialogOptions(options_value)
@@ -318,6 +324,7 @@ class Dialog(QDialog):
self._color_label.setPalette(QPalette(color))
self._color_label.setAutoFillBackground(True)
+ @Slot()
def set_font(self):
options_value = self._font_options.value()
options = QFontDialog.FontDialogOptions(options_value)
@@ -332,6 +339,7 @@ class Dialog(QDialog):
self._font_label.setText(font.key())
self._font_label.setFont(font)
+ @Slot()
def set_existing_directory(self):
options_value = self._file_options.value()
options = QFileDialog.Options(options_value) | QFileDialog.ShowDirsOnly
@@ -342,6 +350,7 @@ class Dialog(QDialog):
if directory:
self._directory_label.setText(directory)
+ @Slot()
def set_open_file_name(self):
options_value = self._file_options.value()
options = QFileDialog.Options(options_value)
@@ -353,6 +362,7 @@ class Dialog(QDialog):
if fileName:
self._open_file_name_label.setText(fileName)
+ @Slot()
def set_open_file_names(self):
options_value = self._file_options.value()
options = QFileDialog.Options(options_value)
@@ -365,6 +375,7 @@ class Dialog(QDialog):
file_list = ', '.join(files)
self._open_file_names_label.setText(f"[{file_list}]")
+ @Slot()
def set_save_file_name(self):
options_value = self._file_options.value()
options = QFileDialog.Options(options_value)
@@ -376,6 +387,7 @@ class Dialog(QDialog):
if fileName:
self._save_file_name_label.setText(fileName)
+ @Slot()
def critical_message(self):
reply = QMessageBox.critical(self, "QMessageBox.critical()",
Dialog.MESSAGE,
@@ -387,6 +399,7 @@ class Dialog(QDialog):
else:
self._critical_label.setText("Ignore")
+ @Slot()
def information_message(self):
reply = QMessageBox.information(self,
"QMessageBox.information()", Dialog.MESSAGE)
@@ -395,6 +408,7 @@ class Dialog(QDialog):
else:
self._information_label.setText("Escape")
+ @Slot()
def question_message(self):
reply = QMessageBox.question(self, "QMessageBox.question()",
Dialog.MESSAGE,
@@ -406,6 +420,7 @@ class Dialog(QDialog):
else:
self._question_label.setText("Cancel")
+ @Slot()
def warning_message(self):
msg_box = QMessageBox(QMessageBox.Warning,
"QMessageBox.warning()", Dialog.MESSAGE,
@@ -417,6 +432,7 @@ class Dialog(QDialog):
else:
self._warning_label.setText("Continue")
+ @Slot()
def error_message(self):
self._error_message_dialog.showMessage("This dialog shows and remembers "
"error messages. If the checkbox is checked (as it is by "
diff --git a/examples/widgets/draganddrop/dropsite/doc/dropsite.rst b/examples/widgets/draganddrop/dropsite/doc/dropsite.rst
new file mode 100644
index 000000000..8d6c42bc8
--- /dev/null
+++ b/examples/widgets/draganddrop/dropsite/doc/dropsite.rst
@@ -0,0 +1,8 @@
+Drop Site Example
+=================
+
+The Drop Site example shows how to distinguish the various MIME formats
+available in a drag and drop operation.
+
+It accepts drops from other applications and displays the MIME formats
+provided by the drag object.
diff --git a/examples/widgets/draganddrop/dropsite/droparea.py b/examples/widgets/draganddrop/dropsite/droparea.py
new file mode 100644
index 000000000..16416cef2
--- /dev/null
+++ b/examples/widgets/draganddrop/dropsite/droparea.py
@@ -0,0 +1,104 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 PySide6.QtCore import QMimeData, Qt, Slot, Signal
+from PySide6.QtGui import QPalette, QPixmap
+from PySide6.QtWidgets import QFrame, QLabel
+
+
+class DropArea(QLabel):
+
+ changed = Signal(QMimeData)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setMinimumSize(200, 200)
+ self.setFrameStyle(QFrame.Sunken | QFrame.StyledPanel)
+ self.setAlignment(Qt.AlignCenter)
+ self.setAcceptDrops(True)
+ self.setAutoFillBackground(True)
+ self.clear()
+
+ def dragEnterEvent(self, event):
+ self.setText("<drop content>")
+ self.setBackgroundRole(QPalette.Highlight)
+
+ event.acceptProposedAction()
+ self.changed.emit(event.mimeData())
+
+ def dragMoveEvent(self, event):
+ event.acceptProposedAction()
+
+ def dropEvent(self, event):
+ mime_data = event.mimeData()
+
+ if mime_data.hasImage():
+ self.setPixmap(QPixmap(mime_data.imageData()))
+ elif mime_data.hasFormat("text/markdown"):
+ self.setText(mime_data.data("text/markdown"))
+ self.setTextFormat(Qt.MarkdownText)
+ elif mime_data.hasHtml():
+ self.setText(mime_data.html())
+ self.setTextFormat(Qt.RichText)
+ elif mime_data.hasText():
+ self.setText(mime_data.text())
+ self.setTextFormat(Qt.PlainText)
+ elif mime_data.hasUrls():
+ url_list = mime_data.urls()
+ text = ""
+ for i in range(0, min(len(url_list), 32)):
+ text += url_list[i].path() + "\n"
+ self.setText(text)
+ else:
+ self.setText("Cannot display data")
+
+ self.setBackgroundRole(QPalette.Dark)
+ event.acceptProposedAction()
+
+ def dragLeaveEvent(self, event):
+ self.clear()
+ event.accept()
+
+ @Slot()
+ def clear(self):
+ self.setText("<drop content>")
+ self.setBackgroundRole(QPalette.Dark)
+
+ self.changed.emit(None)
diff --git a/examples/widgets/draganddrop/dropsite/dropsite.pyproject b/examples/widgets/draganddrop/dropsite/dropsite.pyproject
new file mode 100644
index 000000000..0173d5cb9
--- /dev/null
+++ b/examples/widgets/draganddrop/dropsite/dropsite.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "droparea.py", "dropsitewindow.py"]
+}
diff --git a/examples/widgets/draganddrop/dropsite/dropsitewindow.py b/examples/widgets/draganddrop/dropsite/dropsitewindow.py
new file mode 100644
index 000000000..ddf9afc6b
--- /dev/null
+++ b/examples/widgets/draganddrop/dropsite/dropsitewindow.py
@@ -0,0 +1,152 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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 re
+from PySide6.QtCore import QMimeData, Qt, Slot
+from PySide6.QtGui import QGuiApplication
+from PySide6.QtWidgets import (QAbstractItemView, QPushButton,
+ QDialogButtonBox, QLabel,
+ QTableWidget, QTableWidgetItem,
+ QVBoxLayout, QWidget)
+
+from droparea import DropArea
+
+DESCRIPTION = """This example accepts drags from other applications and
+displays the MIME types provided by the drag object."""
+
+
+_WHITESPACE_PATTERN = re.compile(r"\s+")
+
+
+def simplify_whitespace(s):
+ return _WHITESPACE_PATTERN.sub(" ", s).strip()
+
+
+class DropSiteWindow(QWidget):
+
+ def __init__(self):
+ super().__init__()
+ drop_area = DropArea()
+ abstract_label = QLabel()
+ self._formats_table = QTableWidget()
+
+ button_box = QDialogButtonBox()
+ abstract_label = QLabel(DESCRIPTION)
+ abstract_label.setWordWrap(True)
+ abstract_label.adjustSize()
+
+ drop_area = DropArea()
+ drop_area.changed.connect(self.update_formats_table)
+
+ self._formats_table = QTableWidget()
+ self._formats_table.setColumnCount(2)
+ self._formats_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
+ self._formats_table.setHorizontalHeaderLabels(["Format", "Content"])
+ self._formats_table.horizontalHeader().setStretchLastSection(True)
+
+ clear_button = QPushButton("Clear")
+ self._copy_button = QPushButton("Copy")
+ quit_button = QPushButton("Quit")
+
+ button_box = QDialogButtonBox()
+ button_box.addButton(clear_button, QDialogButtonBox.ActionRole)
+ button_box.addButton(self._copy_button, QDialogButtonBox.ActionRole)
+ self._copy_button.setVisible(False)
+
+ button_box.addButton(quit_button, QDialogButtonBox.RejectRole)
+
+ quit_button.clicked.connect(self.close)
+ clear_button.clicked.connect(drop_area.clear)
+ self._copy_button.clicked.connect(self.copy)
+
+ main_layout = QVBoxLayout(self)
+ main_layout.addWidget(abstract_label)
+ main_layout.addWidget(drop_area)
+ main_layout.addWidget(self._formats_table)
+ main_layout.addWidget(button_box)
+
+ self.setWindowTitle("Drop Site")
+ self.resize(700, 500)
+
+ @Slot(QMimeData)
+ def update_formats_table(self, mime_data):
+ self._formats_table.setRowCount(0)
+ self._copy_button.setEnabled(False)
+ if not mime_data:
+ return
+
+ for format in mime_data.formats():
+ format_item = QTableWidgetItem(format)
+ format_item.setFlags(Qt.ItemIsEnabled)
+ format_item.setTextAlignment(Qt.AlignTop | Qt.AlignLeft)
+
+ if format == "text/plain":
+ text = simplify_whitespace(mime_data.text())
+ elif format == "text/markdown":
+ text = mime_data.data("text/markdown").data().decode("utf8")
+ elif format == "text/html":
+ text = simplify_whitespace(mime_data.html())
+ elif format == "text/uri-list":
+ url_list = mime_data.urls()
+ text = ""
+ for i in range(0, min(len(url_list), 32)):
+ text += url_list[i].toString() + " "
+ else:
+ data = mime_data.data(format)
+ if data.size() > 32:
+ data.truncate(32)
+ text = data.toHex(" ").data().decode("utf8").upper()
+
+ row = self._formats_table.rowCount()
+ self._formats_table.insertRow(row)
+ self._formats_table.setItem(row, 0, QTableWidgetItem(format))
+ self._formats_table.setItem(row, 1, QTableWidgetItem(text))
+
+ self._formats_table.resizeColumnToContents(0)
+ self._copy_button.setEnabled(self._formats_table.rowCount() > 0)
+
+ @Slot()
+ def copy(self):
+ text = ""
+ for row in range(0, self._formats_table.rowCount()):
+ c1 = self._formats_table.item(row, 0).text()
+ c2 = self._formats_table.item(row, 1).text()
+ text += f"{c1}: {c2}\n"
+ QGuiApplication.clipboard().setText(text)
diff --git a/examples/widgets/draganddrop/dropsite/main.py b/examples/widgets/draganddrop/dropsite/main.py
new file mode 100644
index 000000000..498a5c139
--- /dev/null
+++ b/examples/widgets/draganddrop/dropsite/main.py
@@ -0,0 +1,52 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtWidgets import QApplication
+
+from dropsitewindow import DropSiteWindow
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+ window = DropSiteWindow()
+ window.show()
+ sys.exit(app.exec())
diff --git a/examples/widgets/graphicsview/diagramscene/diagramscene.py b/examples/widgets/graphicsview/diagramscene/diagramscene.py
index b56e8d6fe..6f473d75a 100644
--- a/examples/widgets/graphicsview/diagramscene/diagramscene.py
+++ b/examples/widgets/graphicsview/diagramscene/diagramscene.py
@@ -44,10 +44,11 @@ import math
import sys
from PySide6.QtCore import (QLineF, QPointF, QRect, QRectF, QSize, QSizeF, Qt,
- Signal)
+ Signal, Slot)
from PySide6.QtGui import (QAction, QColor, QFont, QIcon, QIntValidator,
QPainter, QPainterPath, QPen, QPixmap, QPolygonF)
-from PySide6.QtWidgets import (QApplication, QButtonGroup, QComboBox,
+from PySide6.QtWidgets import (QAbstractButton, QApplication, QButtonGroup,
+ QComboBox,
QFontComboBox, QGraphicsAnchorLayout,
QGraphicsItem, QGraphicsLineItem,
QGraphicsPolygonItem, QGraphicsTextItem,
@@ -420,6 +421,7 @@ class MainWindow(QMainWindow):
self.setCentralWidget(self.widget)
self.setWindowTitle("Diagramscene")
+ @Slot(QAbstractButton)
def background_button_group_clicked(self, button):
buttons = self._background_button_group.buttons()
for myButton in buttons:
@@ -439,6 +441,7 @@ class MainWindow(QMainWindow):
self.scene.update()
self.view.update()
+ @Slot(int)
def button_group_clicked(self, idx):
buttons = self._button_group.buttons()
for button in buttons:
@@ -451,15 +454,18 @@ class MainWindow(QMainWindow):
self.scene.set_item_type(idx)
self.scene.set_mode(DiagramScene.InsertItem)
+ @Slot()
def delete_item(self):
for item in self.scene.selectedItems():
if isinstance(item, DiagramItem):
item.remove_arrows()
self.scene.removeItem(item)
+ @Slot(int)
def pointer_group_clicked(self, i):
self.scene.set_mode(self._pointer_type_group.checkedId())
+ @Slot()
def bring_to_front(self):
if not self.scene.selectedItems():
return
@@ -473,6 +479,7 @@ class MainWindow(QMainWindow):
z_value = item.zValue() + 0.1
selected_item.setZValue(z_value)
+ @Slot()
def send_to_back(self):
if not self.scene.selectedItems():
return
@@ -486,21 +493,26 @@ class MainWindow(QMainWindow):
z_value = item.zValue() - 0.1
selected_item.setZValue(z_value)
+ @Slot(QGraphicsPolygonItem)
def item_inserted(self, item):
self._pointer_type_group.button(DiagramScene.MoveItem).setChecked(True)
self.scene.set_mode(self._pointer_type_group.checkedId())
self._button_group.button(item.diagram_type).setChecked(False)
+ @Slot(QGraphicsTextItem)
def text_inserted(self, item):
self._button_group.button(self.insert_text_button).setChecked(False)
self.scene.set_mode(self._pointer_type_group.checkedId())
+ @Slot(QFont)
def current_font_changed(self, font):
self.handle_font_change()
+ @Slot(int)
def font_size_changed(self, font):
self.handle_font_change()
+ @Slot(str)
def scene_scale_changed(self, scale):
new_scale = int(scale[:-1]) / 100.0
old_matrix = self.view.transform()
@@ -508,6 +520,7 @@ class MainWindow(QMainWindow):
self.view.translate(old_matrix.dx(), old_matrix.dy())
self.view.scale(new_scale, new_scale)
+ @Slot()
def text_color_changed(self):
self._text_action = self.sender()
self._font_color_tool_button.setIcon(self.create_color_tool_button_icon(
@@ -515,6 +528,7 @@ class MainWindow(QMainWindow):
QColor(self._text_action.data())))
self.text_button_triggered()
+ @Slot()
def item_color_changed(self):
self._fill_action = self.sender()
self._fill_color_tool_button.setIcon(self.create_color_tool_button_icon(
@@ -522,6 +536,7 @@ class MainWindow(QMainWindow):
QColor(self._fill_action.data())))
self.fill_button_triggered()
+ @Slot()
def line_color_changed(self):
self._line_action = self.sender()
self._line_color_tool_button.setIcon(self.create_color_tool_button_icon(
@@ -529,15 +544,19 @@ class MainWindow(QMainWindow):
QColor(self._line_action.data())))
self.line_button_triggered()
+ @Slot()
def text_button_triggered(self):
self.scene.set_text_color(QColor(self._text_action.data()))
+ @Slot()
def fill_button_triggered(self):
self.scene.set_item_color(QColor(self._fill_action.data()))
+ @Slot()
def line_button_triggered(self):
self.scene.set_line_color(QColor(self._line_action.data()))
+ @Slot()
def handle_font_change(self):
font = self._font_combo.currentFont()
font.setPointSize(int(self._font_size_combo.currentText()))
@@ -550,6 +569,7 @@ class MainWindow(QMainWindow):
self.scene.set_font(font)
+ @Slot(QGraphicsItem)
def item_selected(self, item):
font = item.font()
color = item.defaultTextColor()
@@ -559,6 +579,7 @@ class MainWindow(QMainWindow):
self._italic_action.setChecked(font.italic())
self._underline_action.setChecked(font.underline())
+ @Slot()
def about(self):
QMessageBox.about(self, "About Diagram Scene",
"The <b>Diagram Scene</b> example shows use of the graphics framework.")
diff --git a/examples/widgets/graphicsview/elasticnodes/elasticnodes.py b/examples/widgets/graphicsview/elasticnodes/elasticnodes.py
index 8d0fcf0f3..201c35f0a 100644
--- a/examples/widgets/graphicsview/elasticnodes/elasticnodes.py
+++ b/examples/widgets/graphicsview/elasticnodes/elasticnodes.py
@@ -167,7 +167,7 @@ class Node(QGraphicsItem):
self._new_pos = QPointF()
self.setFlag(QGraphicsItem.ItemIsMovable)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges)
- self.setCacheMode(self.DeviceCoordinateCache)
+ self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
self.setZValue(-1)
def item_type(self):
diff --git a/examples/widgets/itemviews/address_book/address_book.py b/examples/widgets/itemviews/address_book/address_book.py
index e00664974..77f63437f 100644
--- a/examples/widgets/itemviews/address_book/address_book.py
+++ b/examples/widgets/itemviews/address_book/address_book.py
@@ -40,6 +40,7 @@
##
#############################################################################
+from PySide6.QtCore import Slot
from PySide6.QtGui import QAction
from PySide6.QtWidgets import (QMainWindow, QFileDialog, QApplication)
@@ -98,11 +99,13 @@ class MainWindow(QMainWindow):
#
# In PySide6, these functions return a tuple: (filename, filter)
+ @Slot()
def open_file(self):
filename, _ = QFileDialog.getOpenFileName(self)
if filename:
self._address_widget.read_from_file(filename)
+ @Slot()
def save_file(self):
filename, _ = QFileDialog.getSaveFileName(self)
if filename:
diff --git a/examples/widgets/itemviews/address_book/addresswidget.py b/examples/widgets/itemviews/address_book/addresswidget.py
index 3dec400c6..2a8db4366 100644
--- a/examples/widgets/itemviews/address_book/addresswidget.py
+++ b/examples/widgets/itemviews/address_book/addresswidget.py
@@ -45,7 +45,7 @@ try:
except ImportError:
import pickle
-from PySide6.QtCore import (Qt, Signal, QRegularExpression, QModelIndex,
+from PySide6.QtCore import (Qt, Signal, Slot, QRegularExpression, QModelIndex,
QItemSelection, QSortFilterProxyModel)
from PySide6.QtWidgets import QTabWidget, QMessageBox, QTableView, QAbstractItemView
@@ -73,6 +73,7 @@ class AddressWidget(QTabWidget):
self.setup_tabs()
+ @Slot()
def add_entry(self, name=None, address=None):
""" Add an entry to the addressbook. """
if name is None and address is None:
@@ -121,6 +122,7 @@ class AddressWidget(QTabWidget):
table_view = self.currentWidget()
table_view.resizeRowToContents(ix.row())
+ @Slot()
def edit_entry(self):
""" Edit an entry in the addressbook. """
table_view = self.currentWidget()
@@ -153,6 +155,7 @@ class AddressWidget(QTabWidget):
ix = self._table_model.index(row, 1, QModelIndex())
self._table_model.setData(ix, new_address, Qt.EditRole)
+ @Slot()
def remove_entry(self):
""" Remove an entry from the addressbook. """
table_view = self.currentWidget()
diff --git a/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py
index d229f84b4..fa44337d2 100644
--- a/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py
+++ b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py
@@ -42,7 +42,7 @@
import sys
from PySide6.QtCore import (QDate, QDateTime, QRegularExpression,
- QSortFilterProxyModel, QTime, Qt)
+ QSortFilterProxyModel, QTime, Qt, Slot)
from PySide6.QtGui import QStandardItemModel
from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout,
QGroupBox, QHBoxLayout, QLabel, QLineEdit,
@@ -140,6 +140,7 @@ class Window(QWidget):
self._proxy_model.setSourceModel(model)
self._source_view.setModel(model)
+ @Slot()
def filter_reg_exp_changed(self):
syntax_nr = self._filter_syntax_combo_box.currentData()
pattern = self._filter_pattern_line_edit.text()
@@ -155,9 +156,11 @@ class Window(QWidget):
reg_exp.setPatternOptions(options)
self._proxy_model.setFilterRegularExpression(reg_exp)
+ @Slot()
def filter_column_changed(self):
self._proxy_model.setFilterKeyColumn(self._filter_column_combo_box.currentIndex())
+ @Slot()
def sort_changed(self):
if self._sort_case_sensitivity_check_box.isChecked():
case_sensitivity = Qt.CaseSensitive
diff --git a/examples/widgets/itemviews/dirview/dirview.py b/examples/widgets/itemviews/dirview/dirview.py
new file mode 100644
index 000000000..1815e3c61
--- /dev/null
+++ b/examples/widgets/itemviews/dirview/dirview.py
@@ -0,0 +1,97 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+from argparse import ArgumentParser, RawTextHelpFormatter
+
+from PySide6.QtWidgets import (QApplication, QFileSystemModel,
+ QFileIconProvider, QScroller, QTreeView)
+from PySide6.QtCore import QDir
+
+"""PySide6 port of the widgets/itemviews/dirview example from Qt v6.x"""
+
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ name = "Dir View"
+ argument_parser = ArgumentParser(description=name,
+ formatter_class=RawTextHelpFormatter)
+ argument_parser.add_argument("--no-custom", "-c", action="store_true",
+ help="Set QFileSystemModel.DontUseCustomDirectoryIcons")
+ argument_parser.add_argument("--no-watch", "-w", action="store_true",
+ help="Set QFileSystemModel.DontWatch")
+ argument_parser.add_argument("directory",
+ help="The directory to start in.",
+ nargs='?', type=str)
+ options = argument_parser.parse_args()
+ root_path = options.directory
+
+ model = QFileSystemModel()
+ icon_provider = QFileIconProvider()
+ model.setIconProvider(icon_provider)
+ model.setRootPath("")
+ if options.no_custom:
+ model.setOption(QFileSystemModel.DontUseCustomDirectoryIcons)
+ if options.no_watch:
+ model.setOption(QFileSystemModel.DontWatchForChanges)
+ tree = QTreeView()
+ tree.setModel(model)
+ if root_path:
+ root_index = model.index(QDir.cleanPath(root_path))
+ if root_index.isValid():
+ tree.setRootIndex(root_index)
+
+ # Demonstrating look and feel features
+ tree.setAnimated(False)
+ tree.setIndentation(20)
+ tree.setSortingEnabled(True)
+ availableSize = tree.screen().availableGeometry().size()
+ tree.resize(availableSize / 2)
+ tree.setColumnWidth(0, tree.width() / 3)
+
+ # Make it flickable on touchscreens
+ QScroller.grabGesture(tree, QScroller.ScrollerGestureType.TouchGesture)
+
+ tree.setWindowTitle(name)
+ tree.show()
+
+ sys.exit(app.exec())
+
diff --git a/examples/widgets/itemviews/dirview/dirview.pyproject b/examples/widgets/itemviews/dirview/dirview.pyproject
new file mode 100644
index 000000000..9470083c9
--- /dev/null
+++ b/examples/widgets/itemviews/dirview/dirview.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["dirview.py"]
+}
diff --git a/examples/widgets/itemviews/dirview/doc/dirview.rst b/examples/widgets/itemviews/dirview/doc/dirview.rst
new file mode 100644
index 000000000..7044fdf58
--- /dev/null
+++ b/examples/widgets/itemviews/dirview/doc/dirview.rst
@@ -0,0 +1,5 @@
+Dir View Example
+================
+
+The Dir View example shows a tree view of the local file system. It uses the
+QFileSystemModel class to provide file and directory information.
diff --git a/examples/widgets/itemviews/editabletreemodel/treemodel.py b/examples/widgets/itemviews/editabletreemodel/treemodel.py
index b7c994fb0..88e53ac82 100644
--- a/examples/widgets/itemviews/editabletreemodel/treemodel.py
+++ b/examples/widgets/itemviews/editabletreemodel/treemodel.py
@@ -39,14 +39,11 @@
#############################################################################
-from PySide6.QtCore import QModelIndex, Qt, QAbstractItemModel, Signal
+from PySide6.QtCore import QModelIndex, Qt, QAbstractItemModel
from treeitem import TreeItem
class TreeModel(QAbstractItemModel):
- # Define signals
- dataChanged = Signal(QModelIndex, QModelIndex, object)
- headerDataChanged = Signal(Qt.Orientation, int, int)
def __init__(self, headers: list, data: str, parent=None):
super().__init__(parent)
@@ -191,9 +188,7 @@ class TreeModel(QAbstractItemModel):
result: bool = self.root_item.set_data(section, value)
if result:
- # todo: Check if emit headerDataChanged signal is correct
- # emit headerDataChanged(orientation, section, section)
- self.headerDataChanged(orientation, section, section)
+ self.headerDataChanged.emit(orientation, section, section)
return result
diff --git a/examples/widgets/itemviews/fetchmore/fetchmore.py b/examples/widgets/itemviews/fetchmore/fetchmore.py
index 75c5c226e..5e53f2c2f 100644
--- a/examples/widgets/itemviews/fetchmore/fetchmore.py
+++ b/examples/widgets/itemviews/fetchmore/fetchmore.py
@@ -151,7 +151,7 @@ class Window(QWidget):
self.setWindowTitle("Fetch More Example")
- @Slot(str, int, int)
+ @Slot(str,int,int,int)
def update_log(self, path, start, number, total):
native_path = QDir.toNativeSeparators(path)
last = start + number - 1
diff --git a/examples/widgets/itemviews/spinboxdelegate/doc/spinboxdelegate.rst b/examples/widgets/itemviews/spinboxdelegate/doc/spinboxdelegate.rst
index 954480067..12e505207 100644
--- a/examples/widgets/itemviews/spinboxdelegate/doc/spinboxdelegate.rst
+++ b/examples/widgets/itemviews/spinboxdelegate/doc/spinboxdelegate.rst
@@ -1,2 +1,5 @@
+SpinBox Delegate Example
+=========================
+
A simple example that shows how a view can use a custom delegate to edit
data obtained from a model.
diff --git a/examples/widgets/itemviews/spreadsheet/spreadsheet.py b/examples/widgets/itemviews/spreadsheet/spreadsheet.py
index 0eb424a72..5f7d76da0 100644
--- a/examples/widgets/itemviews/spreadsheet/spreadsheet.py
+++ b/examples/widgets/itemviews/spreadsheet/spreadsheet.py
@@ -171,7 +171,7 @@ class SpreadSheet(QMainWindow):
about_menu = self.menuBar().addMenu("&Help")
about_menu.addAction(self._about_spreadsheet)
- @Slot()
+ @Slot(QTableWidgetItem)
def update_status(self, item: QTableWidgetItem) -> None:
if item and item == self._table.currentItem():
self.statusBar().showMessage(str(item.data(Qt.StatusTipRole)), 1000)
@@ -181,7 +181,7 @@ class SpreadSheet(QMainWindow):
)
)
- @Slot()
+ @Slot(QTableWidgetItem)
def update_color(self, item: QTableWidgetItem) -> None:
pix = QPixmap(16, 16)
col = QColor()
@@ -206,7 +206,7 @@ class SpreadSheet(QMainWindow):
self._color_action.setIcon(pix)
- @Slot()
+ @Slot(QTableWidgetItem)
def update_line_edit(self, item: QTableWidgetItem) -> None:
if item != self._table.currentItem():
return
diff --git a/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py
index f7fa3f474..003e1596e 100644
--- a/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py
+++ b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py
@@ -88,7 +88,7 @@ class Dialog(QDialog):
self._main_layout.setSizeConstraint(QLayout.SetNoConstraint)
self.setMinimumSize(0, 0)
- orientation = Qt.Orientation(int(self._buttons_orientation_combo_box.itemData(index)))
+ orientation = Qt.Orientation(self._buttons_orientation_combo_box.itemData(index))
if orientation == self._button_box.orientation():
return
diff --git a/examples/widgets/linguist/main.py b/examples/widgets/linguist/main.py
index 7a2855057..59786f92d 100644
--- a/examples/widgets/linguist/main.py
+++ b/examples/widgets/linguist/main.py
@@ -79,7 +79,7 @@ class Window(QMainWindow):
if __name__ == '__main__':
app = QApplication(sys.argv)
- path = QLibraryInfo.location(QLibraryInfo.TranslationsPath)
+ path = QLibraryInfo.path(QLibraryInfo.TranslationsPath)
translator = QTranslator(app)
if translator.load(QLocale.system(), 'qtbase', '_', path):
app.installTranslator(translator)
diff --git a/examples/widgets/mainwindows/application/application.py b/examples/widgets/mainwindows/application/application.py
index 0aa1a3c86..336ce536f 100644
--- a/examples/widgets/mainwindows/application/application.py
+++ b/examples/widgets/mainwindows/application/application.py
@@ -44,7 +44,7 @@ from argparse import ArgumentParser, RawTextHelpFormatter
import sys
from PySide6.QtCore import (QByteArray, QFile, QFileInfo, QSaveFile, QSettings,
- QTextStream, Qt)
+ QTextStream, Qt, Slot)
from PySide6.QtGui import QAction, QIcon, QKeySequence
from PySide6.QtWidgets import (QApplication, QFileDialog, QMainWindow,
QMessageBox, QTextEdit, QWidget)
@@ -80,23 +80,27 @@ class MainWindow(QMainWindow):
else:
event.ignore()
+ @Slot()
def new_file(self):
if self.maybe_save():
self._text_edit.clear()
self.set_current_file('')
+ @Slot()
def open(self):
if self.maybe_save():
fileName, filtr = QFileDialog.getOpenFileName(self)
if fileName:
self.load_file(fileName)
+ @Slot()
def save(self):
if self._cur_file:
return self.save_file(self._cur_file)
return self.save_as()
+ @Slot()
def save_as(self):
fileName, filtr = QFileDialog.getSaveFileName(self)
if fileName:
@@ -104,12 +108,14 @@ class MainWindow(QMainWindow):
return False
+ @Slot()
def about(self):
QMessageBox.about(self, "About Application",
"The <b>Application</b> example demonstrates how to write "
"modern GUI applications using Qt, with a menu bar, "
"toolbars, and a status bar.")
+ @Slot()
def document_was_modified(self):
self.setWindowModified(self._text_edit.document().isModified())
diff --git a/examples/widgets/mainwindows/mdi/mdi.py b/examples/widgets/mainwindows/mdi/mdi.py
index e8ed8792f..a5afc18f3 100644
--- a/examples/widgets/mainwindows/mdi/mdi.py
+++ b/examples/widgets/mainwindows/mdi/mdi.py
@@ -47,7 +47,7 @@ from functools import partial
import sys
from PySide6.QtCore import (QByteArray, QFile, QFileInfo, QPoint, QSettings,
- QSaveFile, QSize, QTextStream, Qt)
+ QSaveFile, QSize, QTextStream, Qt, Slot)
from PySide6.QtGui import QAction, QIcon, QKeySequence
from PySide6.QtWidgets import (QApplication, QFileDialog, QMainWindow,
QMdiArea, QMessageBox, QTextEdit, QWidget)
@@ -194,11 +194,13 @@ class MainWindow(QMainWindow):
self.write_settings()
event.accept()
+ @Slot()
def new_file(self):
child = self.create_mdi_child()
child.new_file()
child.show()
+ @Slot()
def open(self):
file_name, _ = QFileDialog.getOpenFileName(self)
if file_name:
@@ -216,31 +218,38 @@ class MainWindow(QMainWindow):
else:
child.close()
+ @Slot()
def save(self):
if self.active_mdi_child() and self.active_mdi_child().save():
self.statusBar().showMessage("File saved", 2000)
+ @Slot()
def save_as(self):
if self.active_mdi_child() and self.active_mdi_child().save_as():
self.statusBar().showMessage("File saved", 2000)
+ @Slot()
def cut(self):
if self.active_mdi_child():
self.active_mdi_child().cut()
+ @Slot()
def copy(self):
if self.active_mdi_child():
self.active_mdi_child().copy()
+ @Slot()
def paste(self):
if self.active_mdi_child():
self.active_mdi_child().paste()
+ @Slot()
def about(self):
QMessageBox.about(self, "About MDI",
"The <b>MDI</b> example demonstrates how to write multiple "
"document interface applications using Qt.")
+ @Slot()
def update_menus(self):
has_mdi_child = (self.active_mdi_child() is not None)
self._save_act.setEnabled(has_mdi_child)
@@ -259,6 +268,7 @@ class MainWindow(QMainWindow):
self._cut_act.setEnabled(has_selection)
self._copy_act.setEnabled(has_selection)
+ @Slot()
def update_window_menu(self):
self._window_menu.clear()
self._window_menu.addAction(self._close_act)
@@ -440,6 +450,7 @@ class MainWindow(QMainWindow):
return window
return None
+ @Slot()
def switch_layout_direction(self):
if self.layoutDirection() == Qt.LeftToRight:
QApplication.setLayoutDirection(Qt.RightToLeft)
diff --git a/examples/widgets/painting/painter/painter.py b/examples/widgets/painting/painter/painter.py
index 6626afb7a..ed5e74b0a 100644
--- a/examples/widgets/painting/painter/painter.py
+++ b/examples/widgets/painting/painter/painter.py
@@ -173,7 +173,8 @@ class MainWindow(QMainWindow):
self.setCentralWidget(self.painter_widget)
- self.set_color(Qt.black)
+ self.color = Qt.black
+ self.set_color(self.color)
self.mime_type_filters = ["image/png", "image/jpeg"]
@@ -212,19 +213,21 @@ class MainWindow(QMainWindow):
@Slot()
def on_color_clicked(self):
- color = QColorDialog.getColor(Qt.black, self)
+ color = QColorDialog.getColor(self.color, self)
+
if color:
self.set_color(color)
def set_color(self, color: QColor = Qt.black):
+ self.color = color
# Create color icon
pix_icon = QPixmap(32, 32)
- pix_icon.fill(color)
+ pix_icon.fill(self.color)
self.color_action.setIcon(QIcon(pix_icon))
- self.painter_widget.pen.setColor(color)
- self.color_action.setText(QColor(color).name())
+ self.painter_widget.pen.setColor(self.color)
+ self.color_action.setText(QColor(self.color).name())
if __name__ == "__main__":
diff --git a/examples/widgets/richtext/orderform/orderform.py b/examples/widgets/richtext/orderform/orderform.py
index 10cb64dc3..313d2009e 100644
--- a/examples/widgets/richtext/orderform/orderform.py
+++ b/examples/widgets/richtext/orderform/orderform.py
@@ -194,6 +194,7 @@ class MainWindow(QMainWindow):
'12 High Street\nSmall Town\nThis country',
dialog.order_items(), True)
+ @Slot()
def open_dialog(self):
dialog = DetailsDialog("Enter Customer Details", self)
@@ -201,6 +202,7 @@ class MainWindow(QMainWindow):
self.create_letter(dialog.sender_name(), dialog.sender_address(),
dialog.order_items(), dialog.send_offers())
+ @Slot()
def print_file(self):
editor = self.letters.currentWidget()
printer = QPrinter()
@@ -279,6 +281,7 @@ class DetailsDialog(QDialog):
def send_offers(self):
return self._offers_check_box.isChecked()
+ @Slot()
def verify(self):
if self._name_edit.text() and self._address_edit.toPlainText():
self.accept()
diff --git a/examples/widgets/richtext/textobject/textobject.py b/examples/widgets/richtext/textobject/textobject.py
index db32d24e6..b8daabd2c 100644
--- a/examples/widgets/richtext/textobject/textobject.py
+++ b/examples/widgets/richtext/textobject/textobject.py
@@ -46,7 +46,7 @@ import os
from pathlib import Path
import sys
-from PySide6.QtCore import QFile, QIODevice, QObject, QSizeF, Qt
+from PySide6.QtCore import QFile, QIODevice, QObject, QSizeF, Qt, Slot
from PySide6.QtGui import (QTextCharFormat, QTextFormat, QTextObjectInterface,
QPyTextObject)
from PySide6.QtWidgets import (QApplication, QHBoxLayout, QLabel, QLineEdit,
@@ -89,6 +89,7 @@ class Window(QWidget):
self.setWindowTitle(self.tr("Text Object Example"))
+ @Slot()
def insert_text_object(self):
file_name = self._file_name_line_edit.text()
file = QFile(file_name)
diff --git a/examples/widgets/tetrix/tetrix.py b/examples/widgets/tetrix/tetrix.py
index 54536c2ae..621a81ac9 100644
--- a/examples/widgets/tetrix/tetrix.py
+++ b/examples/widgets/tetrix/tetrix.py
@@ -178,6 +178,7 @@ class TetrixBoard(QFrame):
return QSize(TetrixBoard.board_width * 5 + self.frameWidth() * 2,
TetrixBoard.board_height * 5 + self.frameWidth() * 2)
+ @Slot()
def start(self):
if self._is_paused:
return
@@ -197,6 +198,7 @@ class TetrixBoard(QFrame):
self.new_piece()
self.timer.start(self.timeout_time(), self)
+ @Slot()
def pause(self):
if not self._is_started:
return
diff --git a/examples/widgets/tools/regularexpression/regularexpressiondialog.py b/examples/widgets/tools/regularexpression/regularexpressiondialog.py
index a21a4365c..fd654c7c8 100644
--- a/examples/widgets/tools/regularexpression/regularexpressiondialog.py
+++ b/examples/widgets/tools/regularexpression/regularexpressiondialog.py
@@ -113,6 +113,7 @@ class PatternLineEdit(QLineEdit):
self.copyToCodeAction.triggered.connect(self.copyToCode)
self.pasteFromCodeAction.triggered.connect(self.pasteFromCode)
+ @Slot()
def escapeSelection(self):
selection = self.selectedText()
selection_start = self.selectionStart()
@@ -126,9 +127,11 @@ class PatternLineEdit(QLineEdit):
)
self.setText(t)
+ @Slot()
def copyToCode(self):
QGuiApplication.clipboard().setText(patternToCode(self.text()))
+ @Slot()
def pasteFromCode(self):
self.setText(codeToPattern(QGuiApplication.clipboard().text()))
@@ -202,6 +205,7 @@ class RegularExpressionDialog(QDialog):
self.palette.setColor(QPalette.Text, color)
widget.setPalette(self.palette)
+ @Slot()
def refresh(self):
self.setUpdatesEnabled(False)
self.pattern = self.patternLineEdit.text()
diff --git a/examples/widgets/tutorials/addressbook/part3.py b/examples/widgets/tutorials/addressbook/part3.py
index 686a1c530..fae65c156 100644
--- a/examples/widgets/tutorials/addressbook/part3.py
+++ b/examples/widgets/tutorials/addressbook/part3.py
@@ -148,6 +148,7 @@ class AddressBook(QWidget):
self._submit_button.show()
self._cancel_button.show()
+ @Slot()
def submit_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -181,6 +182,7 @@ class AddressBook(QWidget):
self._submit_button.hide()
self._cancel_button.hide()
+ @Slot()
def cancel(self):
self._name_line.setText(self._old_name)
self._address_text.setText(self._old_address)
@@ -200,6 +202,7 @@ class AddressBook(QWidget):
self._submit_button.hide()
self._cancel_button.hide()
+ @Slot()
def next(self):
name = self._name_line.text()
it = iter(self.contacts)
@@ -217,6 +220,7 @@ class AddressBook(QWidget):
self._name_line.setText(next_name)
self._address_text.setText(next_address)
+ @Slot()
def previous(self):
name = self._name_line.text()
diff --git a/examples/widgets/tutorials/addressbook/part4.py b/examples/widgets/tutorials/addressbook/part4.py
index b12f1c010..c13908f98 100644
--- a/examples/widgets/tutorials/addressbook/part4.py
+++ b/examples/widgets/tutorials/addressbook/part4.py
@@ -143,6 +143,7 @@ class AddressBook(QWidget):
self.setLayout(main_layout)
self.setWindowTitle("Simple Address Book")
+ @Slot()
def add_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
@@ -152,12 +153,14 @@ class AddressBook(QWidget):
self.update_interface(self.AddingMode)
+ @Slot()
def edit_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
self.update_interface(self.EditingMode)
+ @Slot()
def submit_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -195,11 +198,13 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def cancel(self):
self._name_line.setText(self._old_name)
self._address_text.setText(self._old_address)
self.update_interface(self.NavigationMode)
+ @Slot()
def remove_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -218,6 +223,7 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def next(self):
name = self._name_line.text()
it = iter(self.contacts)
@@ -235,6 +241,7 @@ class AddressBook(QWidget):
self._name_line.setText(next_name)
self._address_text.setText(next_address)
+ @Slot()
def previous(self):
name = self._name_line.text()
diff --git a/examples/widgets/tutorials/addressbook/part5.py b/examples/widgets/tutorials/addressbook/part5.py
index 7da3a8322..a8259fa76 100644
--- a/examples/widgets/tutorials/addressbook/part5.py
+++ b/examples/widgets/tutorials/addressbook/part5.py
@@ -150,6 +150,7 @@ class AddressBook(QWidget):
self.setLayout(main_layout)
self.setWindowTitle("Simple Address Book")
+ @Slot()
def add_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
@@ -159,12 +160,14 @@ class AddressBook(QWidget):
self.update_interface(self.AddingMode)
+ @Slot()
def edit_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
self.update_interface(self.EditingMode)
+ @Slot()
def submit_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -202,11 +205,13 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def cancel(self):
self._name_line.setText(self._old_name)
self._address_text.setText(self._old_address)
self.update_interface(self.NavigationMode)
+ @Slot()
def remove_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -225,6 +230,7 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def next(self):
name = self._name_line.text()
it = iter(self.contacts)
@@ -242,6 +248,7 @@ class AddressBook(QWidget):
self._name_line.setText(next_name)
self._address_text.setText(next_address)
+ @Slot()
def previous(self):
name = self._name_line.text()
diff --git a/examples/widgets/tutorials/addressbook/part6.py b/examples/widgets/tutorials/addressbook/part6.py
index eb0cec30e..ad5aa04bd 100644
--- a/examples/widgets/tutorials/addressbook/part6.py
+++ b/examples/widgets/tutorials/addressbook/part6.py
@@ -160,6 +160,7 @@ class AddressBook(QWidget):
self.setLayout(main_layout)
self.setWindowTitle("Simple Address Book")
+ @Slot()
def add_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
@@ -169,12 +170,14 @@ class AddressBook(QWidget):
self.update_interface(self.AddingMode)
+ @Slot()
def edit_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
self.update_interface(self.EditingMode)
+ @Slot()
def submit_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -212,11 +215,13 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def cancel(self):
self._name_line.setText(self._old_name)
self._address_text.setText(self._old_address)
self.update_interface(self.NavigationMode)
+ @Slot()
def remove_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -235,6 +240,7 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def next(self):
name = self._name_line.text()
it = iter(self.contacts)
@@ -252,6 +258,7 @@ class AddressBook(QWidget):
self._name_line.setText(next_name)
self._address_text.setText(next_address)
+ @Slot()
def previous(self):
name = self._name_line.text()
diff --git a/examples/widgets/tutorials/addressbook/part7.py b/examples/widgets/tutorials/addressbook/part7.py
index 817a54219..22e949663 100644
--- a/examples/widgets/tutorials/addressbook/part7.py
+++ b/examples/widgets/tutorials/addressbook/part7.py
@@ -166,6 +166,7 @@ class AddressBook(QWidget):
self.setLayout(main_layout)
self.setWindowTitle("Simple Address Book")
+ @Slot()
def add_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
@@ -175,12 +176,14 @@ class AddressBook(QWidget):
self.update_interface(self.AddingMode)
+ @Slot()
def edit_contact(self):
self._old_name = self._name_line.text()
self._old_address = self._address_text.toPlainText()
self.update_interface(self.EditingMode)
+ @Slot()
def submit_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -218,11 +221,13 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def cancel(self):
self._name_line.setText(self._old_name)
self._address_text.setText(self._old_address)
self.update_interface(self.NavigationMode)
+ @Slot()
def remove_contact(self):
name = self._name_line.text()
address = self._address_text.toPlainText()
@@ -241,6 +246,7 @@ class AddressBook(QWidget):
self.update_interface(self.NavigationMode)
+ @Slot()
def next(self):
name = self._name_line.text()
it = iter(self.contacts)
@@ -258,6 +264,7 @@ class AddressBook(QWidget):
self._name_line.setText(next_name)
self._address_text.setText(next_address)
+ @Slot()
def previous(self):
name = self._name_line.text()
diff --git a/examples/widgets/tutorials/cannon/t14.py b/examples/widgets/tutorials/cannon/t14.py
index 283bef326..4c1916a73 100644
--- a/examples/widgets/tutorials/cannon/t14.py
+++ b/examples/widgets/tutorials/cannon/t14.py
@@ -379,7 +379,7 @@ class GameBoard(QWidget):
QShortcut(QKeySequence(Qt.Key_Enter), self, self.fire)
QShortcut(QKeySequence(Qt.Key_Return), self, self.fire)
- QShortcut(QKeySequence(Qt.CTRL + Qt.Key_Q), self, self.close)
+ QShortcut(QKeySequence(Qt.CTRL | Qt.Key_Q), self, self.close)
top_layout = QHBoxLayout()
top_layout.addWidget(shoot)
diff --git a/examples/widgets/widgetsgallery/main.py b/examples/widgets/widgetsgallery/main.py
index 7c1a03b35..b2391d3a1 100644
--- a/examples/widgets/widgetsgallery/main.py
+++ b/examples/widgets/widgetsgallery/main.py
@@ -48,8 +48,6 @@ from widgetgallery import WidgetGallery
if __name__ == '__main__':
- QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
- QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
app = QApplication()
gallery = WidgetGallery()
gallery.show()
diff --git a/examples/widgets/widgetsgallery/widgetgallery.py b/examples/widgets/widgetsgallery/widgetgallery.py
index c0bb392e2..f2a63262a 100644
--- a/examples/widgets/widgetsgallery/widgetgallery.py
+++ b/examples/widgets/widgetsgallery/widgetgallery.py
@@ -45,7 +45,7 @@ from PySide6.QtGui import (QCursor, QDesktopServices, QGuiApplication, QIcon,
QKeySequence, QShortcut, QStandardItem,
QStandardItemModel, QScreen, QWindow)
from PySide6.QtCore import (QDateTime, QDir, QLibraryInfo, QMetaObject,
- QSysInfo, QTextStream, QTimer, Qt, qVersion)
+ QSysInfo, QTextStream, QTimer, Qt, qVersion, Slot)
POEM = """Twinkle, twinkle, little star,
@@ -217,9 +217,11 @@ class WidgetGallery(QDialog):
self.windowHandle().screenChanged.connect(self.update_systeminfo)
self.update_systeminfo()
+ @Slot(str)
def change_style(self, style_name):
QApplication.setStyle(QStyleFactory.create(style_name))
+ @Slot()
def advance_progressbar(self):
cur_val = self._progress_bar.value()
max_val = self._progress_bar.maximum()
@@ -416,6 +418,7 @@ class WidgetGallery(QDialog):
timer.start(1000)
return result
+ @Slot()
def update_systeminfo(self):
"""Display system information"""
system_info = SYSTEMINFO.format(sys.version,
@@ -424,6 +427,7 @@ class WidgetGallery(QDialog):
screen_info(self))
self._systeminfo_textbrowser.setHtml(system_info)
+ @Slot()
def help_on_current_widget(self):
"""Display help on widget under mouse"""
w = QApplication.widgetAt(QCursor.pos(self.screen()))
diff --git a/sources/pyside6/PySide6/QtBluetooth/typesystem_bluetooth.xml b/sources/pyside6/PySide6/QtBluetooth/typesystem_bluetooth.xml
index 165cd310f..7c260bfc0 100644
--- a/sources/pyside6/PySide6/QtBluetooth/typesystem_bluetooth.xml
+++ b/sources/pyside6/PySide6/QtBluetooth/typesystem_bluetooth.xml
@@ -53,7 +53,7 @@
<enum-type name="Pairing"/>
</object-type>
<object-type name="QBluetoothDeviceDiscoveryAgent">
- <enum-type name="DiscoveryMethod"/>
+ <enum-type name="DiscoveryMethod" flags="DiscoveryMethods"/>
<enum-type name="Error"/>
</object-type>
<value-type name="QBluetoothDeviceInfo">
diff --git a/sources/pyside6/PySide6/QtCharts/typesystem_charts.xml b/sources/pyside6/PySide6/QtCharts/typesystem_charts.xml
index fa42f442a..7c793a4c5 100644
--- a/sources/pyside6/PySide6/QtCharts/typesystem_charts.xml
+++ b/sources/pyside6/PySide6/QtCharts/typesystem_charts.xml
@@ -116,7 +116,7 @@
</modify-function>
</object-type>
<object-type name="QBoxSet">
- <enum-type name="ValuePositions"/>
+ <enum-type name="ValuePositions" python-type="IntEnum"/>
</object-type>
<object-type name="QCandlestickLegendMarker"/>
<object-type name="QCandlestickModelMapper"/>
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index c471cecef..8fe9e153e 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -328,11 +328,29 @@
</conversion-rule>
</primitive-type>
- <value-type name="QKeyCombination"/>
+ <value-type name="QKeyCombination">
+ <!-- The following do-nothing function is needed for coercion of constructs like
+ QKeyCombination(Qt.CTRL | Qt.Key_B)
+ -->
+ <add-function signature="QKeyCombination(QKeyCombination)">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp"
+ snippet="keycombination-from-keycombination"/>
+ </add-function>
+ <!-- This is just a copy of KeyModifier to handle Modifier the same -->
+ <add-function signature="QKeyCombination(Qt::Modifier @modifiers@, Qt::Key @key@)">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp"
+ snippet="keycombination-from-modifier"/>
+ </add-function>
+ </value-type>
<value-type name="QMetaType">
- <enum-type name="Type"/>
+ <enum-type name="Type" python-type="IntEnum"/>
<enum-type name="TypeFlag" flags="TypeFlags"/>
+ <!-- PYSIDE-1735: The class QMetaType.Type must be allowed because int is gone -->
+ <add-function signature="QMetaType(QMetaType::Type)">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp"
+ snippet="metatype-from-metatype-type"/>
+ </add-function>
<conversion-rule>
<native-to-target file="../glue/qtcore.cpp" snippet="conversion-qmetatype-pytypeobject"/>
<target-to-native>
@@ -525,7 +543,7 @@
<extra-includes>
<include file-name="QtCore/QProperty" location="global"/>
</extra-includes>
- <enum-type name="AlignmentFlag" flags="Alignment"/>
+ <enum-type name="AlignmentFlag" python-type="IntFlag" flags="Alignment"/>
<enum-type name="AnchorPoint" since="4.6"/>
<enum-type name="ApplicationAttribute"/>
<enum-type name="ApplicationState" flags="ApplicationStates" since="5.1"/>
@@ -552,11 +570,11 @@
<enum-type name="EventPriority"/>
<enum-type name="FillRule"/>
<enum-type name="FindChildOption" flags="FindChildOptions" since="5.0"/>
- <enum-type name="FocusPolicy"/>
+ <enum-type name="FocusPolicy" python-type="IntFlag"/>
<enum-type name="FocusReason"/>
<enum-type name="GestureFlag" flags="GestureFlags" since="4.6"/>
<enum-type name="GestureState" since="4.6"/>
- <enum-type name="GestureType" since="4.6"/>
+ <enum-type name="GestureType" python-type="IntEnum" since="4.6"/>
<enum-type name="GlobalColor"/>
<enum-type name="HighDpiScaleFactorRoundingPolicy" since="5.14"/>
<enum-type name="HitTestAccuracy"/>
@@ -564,16 +582,16 @@
<enum-type name="InputMethodHint" flags="InputMethodHints" since="4.6"/>
<enum-type name="InputMethodQuery" flags="InputMethodQueries"/>
<enum-type name="EnterKeyType" since="5.6"/>
- <enum-type name="ItemDataRole"/>
+ <enum-type name="ItemDataRole" python-type="IntEnum"/>
<enum-type name="ItemFlag" flags="ItemFlags"/>
<enum-type name="ItemSelectionMode"/>
<enum-type name="ItemSelectionOperation" since="5.5"/>
- <enum-type name="Key"/>
+ <enum-type name="Key" python-type="IntEnum"/>
<enum-type name="KeyboardModifier" flags="KeyboardModifiers"/>
<enum-type name="LayoutDirection"/>
<enum-type name="MaskMode"/>
<enum-type name="MatchFlag" flags="MatchFlags"/>
- <enum-type name="Modifier"/>
+ <enum-type name="Modifier" python-type="Flag"/>
<enum-type name="MouseButton" flags="MouseButtons"/>
<enum-type name="MouseEventFlag" flags="MouseEventFlags" since="5.3"/>
<enum-type name="MouseEventSource" since="5.3"/>
@@ -594,7 +612,7 @@
<enum-type name="SplitBehaviorFlags" flags="SplitBehavior" since="5.14"/>
<enum-type name="TabFocusBehavior" since="5.5"/>
<enum-type name="TextElideMode"/>
- <enum-type name="TextFlag"/>
+ <enum-type name="TextFlag" python-type="IntFlag"/>
<enum-type name="TextFormat"/>
<enum-type name="TextInteractionFlag" flags="TextInteractionFlags"/>
<enum-type name="TileRule" since="4.6"/>
@@ -611,7 +629,7 @@
<enum-type name="WindowFrameSection"/>
<enum-type name="WindowModality"/>
<enum-type name="WindowState" flags="WindowStates"/>
- <enum-type name="WindowType" flags="WindowFlags"/>
+ <enum-type name="WindowType" python-type="IntFlag" flags="WindowFlags"/>
<enum-type name="CursorMoveStyle" since="4.8" revision="4800"/>
<modify-function signature="^operator.\(Qt::AlignmentFlag,Qt::TextFlag\)$"
@@ -867,6 +885,10 @@
<add-function signature="QDateTime(int,int,int,int,int,int)">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qdatetime-2"/>
</add-function>
+ <!-- PYSIDE-1735: Qt::TimeSpec is no more compatible with int -->
+ <add-function signature="QDateTime(int,int,int,int,int,int,int,Qt::TimeSpec=Qt::LocalTime)">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qdatetime-3"/>
+ </add-function>
<add-function signature="__repr__" return-type="PyObject*">
<inject-code class="target" position="beginning">
<insert-template name="repr_code">
@@ -1295,10 +1317,10 @@
<value-type name="QLocale">
<enum-type name="Country"/>
<enum-type name="DataSizeFormat" flags="DataSizeFormats" since="5.10"/>
- <enum-type name="FloatingPointPrecisionOption" since="5.7"/>
+ <enum-type name="FloatingPointPrecisionOption" python-type="IntEnum" since="5.7"/>
<enum-type name="FormatType"/>
<enum-type name="Language"/>
- <enum-type name="LanguageCodeType" flags="LanguageCodeTypes" since="6.3"/>
+ <enum-type name="LanguageCodeType" python-type="IntFlag" flags="LanguageCodeTypes" since="6.3"/>
<enum-type name="MeasurementSystem"/>
<enum-type name="NumberOption" flags="NumberOptions"/>
<enum-type name="Script" since="4.8" revision="4800"/>
@@ -1793,9 +1815,9 @@
<value-type name="QUrl" hash-function="PySide::hash">
<!-- Qt5: lots of changes -->
- <enum-type name="ComponentFormattingOption" flags="ComponentFormattingOptions,FormattingOptions"/>
+ <enum-type name="ComponentFormattingOption" python-type="IntFlag" flags="ComponentFormattingOptions,FormattingOptions"/>
<!-- note: above duplication of attribute is not by default XML compliant! -->
- <enum-type name="UrlFormattingOption"/>
+ <enum-type name="UrlFormattingOption" python-type="IntFlag"/>
<enum-type name="UserInputResolutionOption" flags="UserInputResolutionOptions"/>
<enum-type name="ParsingMode"/>
<enum-type name="AceProcessingOption" flags="AceProcessingOptions" since="6.3"/>
@@ -2571,8 +2593,9 @@
</inject-documentation>
</add-function>
</object-type>
- <object-type name="QEvent" polymorphic-id-expression="%1-&gt;type() == QEvent::None">
- <enum-type name="Type"/>
+ <object-type name="QEvent" polymorphic-id-expression="%1-&gt;type() == QEvent::None"
+ qt-register-metatype="base">
+ <enum-type name="Type" python-type="IntEnum"/>
<add-function signature="__repr__" return-type="PyObject">
<inject-code class="target" position="beginning"
file="../glue/qtcore.cpp" snippet="repr-qevent"/>
@@ -2592,7 +2615,7 @@
<object-type name="QDataStream" stream="yes">
<enum-type name="FloatingPointPrecision" since="4.6"/>
<enum-type name="Status"/>
- <enum-type name="Version"/>
+ <enum-type name="Version" python-type="IntEnum"/>
<enum-type name="ByteOrder"/>
<extra-includes>
<include file-name="QtCore/QtCore" location="global"/>
diff --git a/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml b/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml
index 16096ba94..16f36a23d 100644
--- a/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml
+++ b/sources/pyside6/PySide6/QtGui/typesystem_gui_common.xml
@@ -401,9 +401,7 @@
<enum-type name="StandardKey"/>
<add-function signature="__repr__" return-type="PyObject*">
- <inject-code class="target" position="beginning">
- <insert-template name="qkeysequence_repr"/>
- </inject-code>
+ <inject-code class="target" position="beginning" file="../glue/qtgui.cpp" snippet="qkeysequence-repr"/>
</add-function>
<add-function signature="__reduce__" return-type="PyObject*">
@@ -521,10 +519,10 @@
<enum-type name="VerticalAlignment"/>
</value-type>
<value-type name="QTextFormat" >
- <enum-type name="FormatType"/>
- <enum-type name="ObjectTypes"/>
+ <enum-type name="FormatType" python-type="IntEnum"/>
+ <enum-type name="ObjectTypes" python-type="IntEnum"/>
<enum-type name="PageBreakFlag" flags="PageBreakFlags"/>
- <enum-type name="Property"/>
+ <enum-type name="Property" python-type="IntEnum"/>
</value-type>
<value-type name="QTextListFormat">
<enum-type name="Style"/>
@@ -698,11 +696,11 @@
<value-type name="QFont" >
<enum-type name="Capitalization"/>
<enum-type name="SpacingType"/>
- <enum-type name="Stretch"/>
+ <enum-type name="Stretch" python-type="IntEnum"/>
<enum-type name="Style"/>
<enum-type name="StyleHint"/>
<enum-type name="StyleStrategy"/>
- <enum-type name="Weight"/>
+ <enum-type name="Weight" python-type="IntEnum"/>
<enum-type name="HintingPreference" since="4.8" revision="4800"/>
<extra-includes>
<include file-name="QStringList" location="global"/>
@@ -1857,7 +1855,7 @@
<enum-type name="FindFlag" flags="FindFlags"/>
<enum-type name="MarkdownFeature" flags="MarkdownFeatures" since="5.14"/>
<enum-type name="MetaInformation"/>
- <enum-type name="ResourceType"/>
+ <enum-type name="ResourceType" python-type="IntEnum"/>
<enum-type name="Stacks" since="4.7"/>
<modify-function signature="setDocumentLayout(QAbstractTextDocumentLayout*)">
<modify-argument index="1">
diff --git a/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml b/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml
index 1bf22761b..1cd3412a3 100644
--- a/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml
+++ b/sources/pyside6/PySide6/QtMultimedia/typesystem_multimedia.xml
@@ -146,7 +146,7 @@
<enum-type name="MediaStatus"/>
<enum-type name="PlaybackState" since="6.1"/>
<enum-type name="Error"/>
- <enum-type name="Loops" since="6.2.3"/>
+ <enum-type name="Loops" python-type="IntEnum" since="6.2.3"/>
</object-type>
<!-- see qtmultimedia/5773f7214c7430a98dea3974c0597cb3ee0ea7f5 might reappear in 6.3
<object-type name="QMediaPlaylist"/>
diff --git a/sources/pyside6/PySide6/QtQuick/typesystem_quick.xml b/sources/pyside6/PySide6/QtQuick/typesystem_quick.xml
index de257a93c..7fa7260b9 100644
--- a/sources/pyside6/PySide6/QtQuick/typesystem_quick.xml
+++ b/sources/pyside6/PySide6/QtQuick/typesystem_quick.xml
@@ -138,7 +138,7 @@
<object-type name="QSGGeometry">
<enum-type name="DataPattern"/>
<enum-type name="AttributeType" since="5.8"/>
- <enum-type name="DrawingMode" since="5.8"/>
+ <enum-type name="DrawingMode" python-type="IntEnum" since="5.8"/>
<enum-type name="Type" since="5.8"/>
<value-type name="Attribute"/>
<value-type name="AttributeSet"/>
diff --git a/sources/pyside6/PySide6/QtSerialPort/typesystem_serialport.xml b/sources/pyside6/PySide6/QtSerialPort/typesystem_serialport.xml
index 06b04856b..c08d5b2be 100644
--- a/sources/pyside6/PySide6/QtSerialPort/typesystem_serialport.xml
+++ b/sources/pyside6/PySide6/QtSerialPort/typesystem_serialport.xml
@@ -42,7 +42,7 @@
<typesystem package="PySide6.QtSerialPort">
<load-typesystem name="QtCore/typesystem_core.xml" generate="no"/>
<object-type name="QSerialPort">
- <enum-type name="BaudRate"/>
+ <enum-type name="BaudRate" python-type="IntEnum"/>
<enum-type name="DataBits"/>
<enum-type name="Direction" flags="Directions"/>
<enum-type name="FlowControl"/>
diff --git a/sources/pyside6/PySide6/QtWebEngineCore/typesystem_webenginecore.xml b/sources/pyside6/PySide6/QtWebEngineCore/typesystem_webenginecore.xml
index 9514100e4..c37b01f86 100644
--- a/sources/pyside6/PySide6/QtWebEngineCore/typesystem_webenginecore.xml
+++ b/sources/pyside6/PySide6/QtWebEngineCore/typesystem_webenginecore.xml
@@ -122,7 +122,7 @@
<value-type name="QWebEngineScript">
<enum-type name="InjectionPoint"/>
- <enum-type name="ScriptWorldId"/>
+ <enum-type name="ScriptWorldId" python-type="IntEnum"/>
</value-type>
<object-type name="QWebEngineScriptCollection"/>
diff --git a/sources/pyside6/PySide6/QtWidgets/CMakeLists.txt b/sources/pyside6/PySide6/QtWidgets/CMakeLists.txt
index 3f960bcff..85d4cdfd2 100644
--- a/sources/pyside6/PySide6/QtWidgets/CMakeLists.txt
+++ b/sources/pyside6/PySide6/QtWidgets/CMakeLists.txt
@@ -37,6 +37,7 @@ ${QtWidgets_GEN_DIR}/qfocusframe_wrapper.cpp
${QtWidgets_GEN_DIR}/qfontcombobox_wrapper.cpp
${QtWidgets_GEN_DIR}/qfontdialog_wrapper.cpp
${QtWidgets_GEN_DIR}/qformlayout_wrapper.cpp
+${QtWidgets_GEN_DIR}/qformlayout_takerowresult_wrapper.cpp
${QtWidgets_GEN_DIR}/qframe_wrapper.cpp
${QtWidgets_GEN_DIR}/qgesture_wrapper.cpp
${QtWidgets_GEN_DIR}/qgestureevent_wrapper.cpp
diff --git a/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml b/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml
index 55d45d068..1c0d4d706 100644
--- a/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml
+++ b/sources/pyside6/PySide6/QtWidgets/typesystem_widgets_common.xml
@@ -219,7 +219,7 @@
<value-type name="QSizePolicy">
<enum-type name="ControlType" flags="ControlTypes"/>
<enum-type name="Policy"/>
- <enum-type name="PolicyFlag"/>
+ <enum-type name="PolicyFlag" python-type="IntFlag"/>
</value-type>
<value-type name="QTableWidgetSelectionRange"/>
@@ -509,7 +509,7 @@
</object-type>
<object-type name="QDateEdit"/>
<object-type name="QDialog">
- <enum-type name="DialogCode"/>
+ <enum-type name="DialogCode" python-type="IntEnum"/>
<modify-function signature="exec()" allow-thread="yes"/>
<add-function signature="exec_()" return-type="int">
<inject-code file="../glue/qtwidgets.cpp" snippet="qapplication-exec"/>
@@ -904,7 +904,6 @@
</object-type>
<object-type name="QMenuBar">
- <inject-code class="native" position="beginning" file="../glue/qtwidgets.cpp" snippet="qwidget-addaction-glue"/>
<modify-function signature="addMenu(QMenu*)">
<modify-argument index="return">
<parent index="1" action="add"/>
@@ -1154,17 +1153,17 @@
</add-function>
</object-type>
<object-type name="QStyle">
- <enum-type name="ComplexControl"/>
- <enum-type name="ContentsType"/>
- <enum-type name="ControlElement"/>
- <enum-type name="PixelMetric"/>
- <enum-type name="PrimitiveElement"/>
+ <enum-type name="ComplexControl" python-type="IntEnum"/>
+ <enum-type name="ContentsType" python-type="IntEnum"/>
+ <enum-type name="ControlElement" python-type="IntEnum"/>
+ <enum-type name="PixelMetric" python-type="IntEnum"/>
+ <enum-type name="PrimitiveElement" python-type="IntEnum"/>
<enum-type name="RequestSoftwareInputPanel" since="4.6"/>
- <enum-type name="StandardPixmap"/>
+ <enum-type name="StandardPixmap" python-type="IntEnum"/>
<enum-type name="StateFlag" flags="State"/>
- <enum-type name="StyleHint"/>
+ <enum-type name="StyleHint" python-type="IntEnum"/>
<enum-type name="SubControl" flags="SubControls"/>
- <enum-type name="SubElement"/>
+ <enum-type name="SubElement" python-type="IntEnum"/>
<modify-function signature="drawComplexControl(QStyle::ComplexControl,const QStyleOptionComplex*,QPainter*,const QWidget*)const">
<modify-argument index="3" invalidate-after-use="yes"/>
<modify-argument index="4">
@@ -1782,7 +1781,7 @@
<modify-function signature="closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)" allow-thread="yes"/>
</object-type>
<object-type name="QTableWidgetItem" >
- <enum-type name="ItemType"/>
+ <enum-type name="ItemType" python-type="IntEnum"/>
<modify-function signature="read(QDataStream&amp;)" allow-thread="yes">
<modify-argument index="1" invalidate-after-use="yes"/>
</modify-function>
@@ -1791,7 +1790,7 @@
</modify-function>
</object-type>
<object-type name="QListWidgetItem" >
- <enum-type name="ItemType"/>
+ <enum-type name="ItemType" python-type="IntEnum"/>
<modify-function signature="QListWidgetItem(const QString&amp;,QListWidget*,int)">
<modify-argument index="this">
<parent index="2" action="add"/>
@@ -1851,7 +1850,7 @@
</object-type>
<object-type name="QTreeWidgetItem" hash-function="qHash">
<enum-type name="ChildIndicatorPolicy"/>
- <enum-type name="ItemType"/>
+ <enum-type name="ItemType" python-type="IntEnum"/>
<modify-function signature="read(QDataStream&amp;)" allow-thread="yes">
<modify-argument index="1" invalidate-after-use="yes"/>
</modify-function>
@@ -2285,7 +2284,7 @@
<object-type name="QMessageBox">
<enum-type name="ButtonRole"/>
<enum-type name="Icon"/>
- <enum-type name="StandardButton" flags="StandardButtons"/>
+ <enum-type name="StandardButton" python-type="IntFlag" flags="StandardButtons"/>
<modify-function signature="removeButton(QAbstractButton*)">
<modify-argument index="1">
<parent index="this" action="add"/>
@@ -2295,10 +2294,19 @@
<include file-name="QPixmap" location="global"/>
</extra-includes>
+ <!-- FIXME PYSIDE-7: Remove deprecated overloads -->
<modify-function signature="critical(QWidget*,const QString&amp;,const QString&amp;,QFlags&lt;QMessageBox::StandardButton&gt;,QMessageBox::StandardButton)" allow-thread="yes"/>
+ <modify-function signature="critical(QWidget*,const QString&amp;,const QString&amp;,QMessageBox::StandardButton,QMessageBox::StandardButton)"
+ allow-thread="yes"/>
<modify-function signature="information(QWidget*,const QString&amp;,const QString&amp;,QFlags&lt;QMessageBox::StandardButton&gt;,QMessageBox::StandardButton)" allow-thread="yes"/>
+ <modify-function signature="information(QWidget*,const QString&amp;,const QString&amp;,QMessageBox::StandardButton,QMessageBox::StandardButton)"
+ allow-thread="yes"/>
<modify-function signature="question(QWidget*,const QString&amp;,const QString&amp;,QFlags&lt;QMessageBox::StandardButton&gt;,QMessageBox::StandardButton)" allow-thread="yes"/>
+ <modify-function signature="question(QWidget*,const QString&amp;,const QString&amp;,QMessageBox::StandardButton,QMessageBox::StandardButton)"
+ allow-thread="yes"/>
<modify-function signature="warning(QWidget*,const QString&amp;,const QString&amp;,QFlags&lt;QMessageBox::StandardButton&gt;,QMessageBox::StandardButton)" allow-thread="yes"/>
+ <modify-function signature="warning(QWidget*,const QString&amp;,const QString&amp;,QMessageBox::StandardButton,QMessageBox::StandardButton)"
+ allow-thread="yes"/>
<modify-function signature="QMessageBox(const QString&amp;,const QString&amp;,QMessageBox::Icon,int,int,int,QWidget*,QFlags&lt;Qt::WindowType&gt;)" remove="all"/>
<modify-function signature="critical(QWidget*,const QString&amp;,const QString&amp;,int,int,int)" remove="all"/>
<modify-function signature="critical(QWidget*,const QString&amp;,const QString&amp;,const QString&amp;,const QString&amp;,const QString&amp;,int,int)" remove="all"/>
@@ -2740,8 +2748,8 @@
</modify-function>
</object-type>
<object-type name="QFrame">
- <enum-type name="Shadow"/>
- <enum-type name="Shape"/>
+ <enum-type name="Shadow" python-type="IntEnum"/>
+ <enum-type name="Shape" python-type="IntEnum"/>
<enum-type name="StyleMask"/>
</object-type>
<object-type name="QSpinBox"/>
@@ -2895,7 +2903,7 @@
<object-type name="QCommandLinkButton"/>
<!-- FIXME PYSIDE7: Move to QtGui -->
<object-type name="QFileSystemModel" polymorphic-id-expression="qobject_cast&lt;QFileSystemModel*&gt;(%1)">
- <enum-type name="Roles"/>
+ <enum-type name="Roles" python-type="IntEnum"/>
<enum-type name="Option" flags="Options" since="5.14"/>
<modify-function signature="setIconProvider(QAbstractFileIconProvider*)">
<modify-argument index="1">
@@ -2912,6 +2920,9 @@
<enum-type name="ItemRole"/>
<enum-type name="RowWrapPolicy"/>
+ <value-type name="TakeRowResult">
+ <include file-name="QFormLayout" location="global"/>
+ </value-type>
<modify-function signature="getLayoutPosition(QLayout*,int*,QFormLayout::ItemRole*)const">
<modify-argument index="0">
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index 321aa7264..6b7e1a597 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -127,6 +127,15 @@ else {
// @snippet qsettings-value
+// @snippet metatype-from-metatype-type
+Shiboken::AutoDecRef intArg;
+if (usingNewEnum())
+ intArg.reset(PyObject_GetAttrString(%PYARG_1, "value"));
+else
+ intArg.reset(PyObject_CallMethod(%PYARG_1, "__int__", nullptr));
+%0 = new %TYPE(PyLong_AsLong(intArg));
+// @snippet metatype-from-metatype-type
+
// @snippet conversion-pytypeobject-qmetatype
auto *pyType = reinterpret_cast<PyTypeObject *&>(%in);
if (Shiboken::String::checkType(pyType))
@@ -411,6 +420,12 @@ QTime time(%4, %5, %6);
%0 = new %TYPE(date, time);
// @snippet qdatetime-2
+// @snippet qdatetime-3
+QDate date(%1, %2, %3);
+QTime time(%4, %5, %6, %7);
+%0 = new %TYPE(date, time, %8);
+// @snippet qdatetime-3
+
// @snippet qdatetime-topython
QDate date = %CPPSELF.date();
QTime time = %CPPSELF.time();
@@ -1578,10 +1593,8 @@ QDebug(&result).nospace() << "<PySide6.QtCore.QEvent(" << %CPPSELF->type() << ")
// @snippet repr-qevent
// @snippet qmetaproperty_write_enum
-if (Shiboken::Enum::check(%PYARG_2)) {
- int in = %CONVERTTOCPP[int](%PYARG_2);
- cppArg1 = QVariant(in);
-}
+if (Shiboken::Enum::check(%PYARG_2))
+ cppArg1 = QVariant(int(Shiboken::Enum::getValue(%PYARG_2)));
// @snippet qmetaproperty_write_enum
// @snippet qdatastream-read-bytes
@@ -1605,11 +1618,17 @@ if (dataChar == nullptr) {
// @snippet qloggingcategory_to_cpp
// @snippet qabstractitemmodel_data
-::QVariant %0 ;
-if (Shiboken::Enum::check(%PYARG_0)) {
- int in = %CONVERTTOCPP[int](%PYARG_0);
- %0 = QVariant(in);
-} else {
+::QVariant %0;
+if (Shiboken::Enum::check(%PYARG_0))
+ %0 = QVariant(int(Shiboken::Enum::getValue(%PYARG_0)));
+else
pythonToCpp(pyResult, &cppResult);
-}
// @snippet qabstractitemmodel_data
+
+// @snippet keycombination-from-keycombination
+cptr = new ::%TYPE(%1);
+// @snippet keycombination-from-keycombination
+
+// @snippet keycombination-from-modifier
+cptr = new ::%TYPE(%1, %2);
+// @snippet keycombination-from-modifier
diff --git a/sources/pyside6/PySide6/glue/qtgui.cpp b/sources/pyside6/PySide6/glue/qtgui.cpp
index 8cfdd69a3..0d4c779a1 100644
--- a/sources/pyside6/PySide6/glue/qtgui.cpp
+++ b/sources/pyside6/PySide6/glue/qtgui.cpp
@@ -216,10 +216,22 @@ if (_i < 0 || _i >= %CPPSELF.count()) {
PyErr_SetString(PyExc_IndexError, "index out of bounds");
return 0;
}
-int item = (*%CPPSELF)[_i];
-return %CONVERTTOPYTHON[int](item);
+QKeyCombination item = (*%CPPSELF)[_i];
+if (usingNewEnum())
+ return %CONVERTTOPYTHON[QKeyCombination](item);
+auto combined = item.toCombined();
+return %CONVERTTOPYTHON[int](combined);
// @snippet qkeysequence-getitem
+// @snippet qkeysequence-repr
+auto ObTuple_Type = reinterpret_cast<PyObject *>(&PyTuple_Type);
+auto ObSelf_Type = reinterpret_cast<PyObject *>(Py_TYPE(%PYSELF));
+Shiboken::AutoDecRef surrogate(PyObject_CallFunctionObjArgs(ObTuple_Type, %PYSELF, nullptr));
+Shiboken::AutoDecRef argstr(PyObject_Repr(surrogate));
+Shiboken::AutoDecRef name(PyObject_GetAttrString(ObSelf_Type, "__name__"));
+return PyUnicode_Concat(name, argstr);
+// @snippet qkeysequence-repr
+
// @snippet qpicture-data
%PYARG_0 = Shiboken::Buffer::newObject(%CPPSELF.data(), %CPPSELF.size());
// @snippet qpicture-data
diff --git a/sources/pyside6/PySide6/glue/qtwidgets.cpp b/sources/pyside6/PySide6/glue/qtwidgets.cpp
index b355f41cb..f95db9ee5 100644
--- a/sources/pyside6/PySide6/glue/qtwidgets.cpp
+++ b/sources/pyside6/PySide6/glue/qtwidgets.cpp
@@ -96,6 +96,11 @@ QFormLayout::ItemRole _role;
%CPPSELF->%FUNCTION_NAME(%ARGUMENT_NAMES, &_row, &_role);
%PYARG_0 = PyTuple_New(2);
PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[int](_row));
+// On the C++ side, *rolePtr is not set if row == -1, in which case on
+// the Python side this gets converted to a random value outside the
+// enum range. Fix this by setting _role to a default value here.
+if (_row == -1)
+ _role = QFormLayout::LabelRole;
PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QFormLayout::ItemRole](_role));
// @snippet qformlayout-fix-args
diff --git a/sources/pyside6/PySide6/qtguihelper.h b/sources/pyside6/PySide6/qtguihelper.h
index 4fee6c53e..acc0de6a8 100644
--- a/sources/pyside6/PySide6/qtguihelper.h
+++ b/sources/pyside6/PySide6/qtguihelper.h
@@ -50,7 +50,7 @@ namespace QtGuiHelper {
Q_DISABLE_COPY_MOVE(QOverrideCursorGuard)
QOverrideCursorGuard() = default;
- ~QOverrideCursorGuard() { restoreOverrideCursor(); }
+ ~QOverrideCursorGuard() = default;
void restoreOverrideCursor()
{
diff --git a/sources/pyside6/PySide6/support/deprecated.py b/sources/pyside6/PySide6/support/deprecated.py
index cd620eb05..a0df14715 100644
--- a/sources/pyside6/PySide6/support/deprecated.py
+++ b/sources/pyside6/PySide6/support/deprecated.py
@@ -50,6 +50,9 @@ Functions that are to be called for
Note that this fixing code is run after all initializations, but before the
import is finished. But that is no problem since the module is passed in.
+
+PYSIDE-1735: This is also used now for missing other functions (overwriting __or__
+ in Qt.(Keyboard)Modifier).
"""
import warnings
@@ -75,4 +78,31 @@ def _unused_fix_for_QtGui(QtGui):
if name.startswith("QMatrix") and "data" in cls.__dict__:
cls.constData = constData
+# PYSIDE-1735: Fix for a special enum function
+def fix_for_QtCore(QtCore):
+ from enum import Flag
+ Qt = QtCore.Qt
+ flag_or = Flag.__or__
+
+ def func_or(self, other):
+ if isinstance(self, Flag) and isinstance(other, Flag):
+ # this is normal or-ing flags together
+ return Qt.KeyboardModifier(self.value | other.value)
+ return QtCore.QKeyCombination(self, other)
+
+ def func_add(self, other):
+ warnings.warn(dedent(f"""
+ The "+" operator is deprecated in Qt For Python 6.0 .
+ Please use "|" instead."""), PySideDeprecationWarningRemovedInQt6, stacklevel=2)
+ return func_or(self, other)
+
+ Qt.KeyboardModifier.__or__ = func_or
+ Qt.KeyboardModifier.__ror__ = func_or
+ Qt.Modifier.__or__ = func_or
+ Qt.Modifier.__ror__ = func_or
+ Qt.KeyboardModifier.__add__ = func_add
+ Qt.KeyboardModifier.__radd__ = func_add
+ Qt.Modifier.__add__ = func_add
+ Qt.Modifier.__radd__ = func_add
+
# eof
diff --git a/sources/pyside6/PySide6/templates/gui_common.xml b/sources/pyside6/PySide6/templates/gui_common.xml
index ee132a77f..e3cc91828 100644
--- a/sources/pyside6/PySide6/templates/gui_common.xml
+++ b/sources/pyside6/PySide6/templates/gui_common.xml
@@ -129,15 +129,6 @@
}
</template>
- <template name="qkeysequence_repr">
- QString result;
- QDebug debug(&amp;result);
- debug.noquote();
- debug.nospace();
- debug &lt;&lt; (*%CPPSELF);
- %PYARG_0 = Shiboken::String::fromCString(result.toUtf8().constData());
- </template>
-
<template name="validator_conversionrule">
QValidator::State %out;
diff --git a/sources/pyside6/doc/CMakeLists.txt b/sources/pyside6/doc/CMakeLists.txt
index 9d4fcf144..c8f21b23a 100644
--- a/sources/pyside6/doc/CMakeLists.txt
+++ b/sources/pyside6/doc/CMakeLists.txt
@@ -194,7 +194,7 @@ if (FULLDOCSBUILD)
endif()
add_custom_target(apidoc
- COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} ${CMAKE_CURRENT_BINARY_DIR}/rst html
+ COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} -j auto ${CMAKE_CURRENT_BINARY_DIR}/rst html
COMMENT "Generating PySide htmls..."
)
@@ -215,7 +215,7 @@ else()
set(PATCH_QHP_SCRIPT "${CMAKE_CURRENT_LIST_DIR}/../../shiboken6/doc/scripts/patch_qhp.py")
file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/html/PySide.qhp QHP_FILE)
add_custom_command(TARGET apidoc POST_BUILD
- COMMAND ${python_executable} ${PATCH_QHP_SCRIPT} -f ${QHP_FILE} -v pyside6
+ COMMAND ${python_executable} ${PATCH_QHP_SCRIPT} -p -v pyside6 ${QHP_FILE}
COMMAND "${qhelpgenerator_binary}" ${QHP_FILE}
COMMENT "Generating QCH from a QHP file..."
VERBATIM
diff --git a/sources/pyside6/doc/additionaldocs.lst b/sources/pyside6/doc/additionaldocs.lst
index 9216fb895..25d1d0067 100644
--- a/sources/pyside6/doc/additionaldocs.lst
+++ b/sources/pyside6/doc/additionaldocs.lst
@@ -154,7 +154,6 @@ qml-tutorial2.webxml
qml-tutorial3.webxml
qmldiskcache.webxml
qmlexampletoggleswitch.webxml
-qmlextendingexamples.webxml
qmlreference.webxml
qndeffilter-record.webxml
qoutputrange.webxml
@@ -184,7 +183,6 @@ qt3d-qml.webxml
qt3d-scene2d-example.webxml
qt3d-scene3d-example.webxml
qt3d-shadow-map-qml-example.webxml
-qt3d-simple-cpp-example.webxml
qt3d-simple-qml-example.webxml
qt3d-simplecustommaterial-example.webxml
qt3d-wave-example.webxml
@@ -196,45 +194,27 @@ qt3drender-porting-to-rhi.webxml
qt3drender-protips.webxml
qtalgorithms.webxml
qtbluetooth-btchat-example.webxml
-qtbluetooth-btscanner-example.webxml
qtbluetooth-changes-qt6.webxml
-qtbluetooth-heartrate-game-example.webxml
-qtbluetooth-heartrate-server-example.webxml
qtbluetooth-le-overview.webxml
qtbluetooth-lowenergyscanner-example.webxml
qtbluetooth-overview.webxml
qtbluetooth-pingpong-example.webxml
qtcborcommon.webxml
-qtcharts-areachart-example.webxml
-qtcharts-audio-example.webxml
-qtcharts-barchart-example.webxml
qtcharts-barmodelmapper-example.webxml
qtcharts-boxplotchart-example.webxml
-qtcharts-callout-example.webxml
qtcharts-candlestickchart-example.webxml
qtcharts-changes-qt6.webxml
-qtcharts-chartthemes-example.webxml
qtcharts-customchart-example.webxml
qtcharts-datetimeaxis-example.webxml
-qtcharts-donutbreakdown-example.webxml
qtcharts-donutchart-example.webxml
-qtcharts-dynamicspline-example.webxml
qtcharts-examples.webxml
qtcharts-horizontalbarchart-example.webxml
qtcharts-horizontalpercentbarchart-example.webxml
qtcharts-horizontalstackedbarchart-example.webxml
-qtcharts-legend-example.webxml
qtcharts-legendmarkers-example.webxml
-qtcharts-lineandbar-example.webxml
-qtcharts-linechart-example.webxml
-qtcharts-logvalueaxis-example.webxml
-qtcharts-modeldata-example.webxml
qtcharts-multiaxis-example.webxml
-qtcharts-nesteddonuts-example.webxml
qtcharts-openglseries-example.webxml
qtcharts-overview.webxml
-qtcharts-percentbarchart-example.webxml
-qtcharts-piechart-example.webxml
qtcharts-piechartcustomization-example.webxml
qtcharts-piechartdrilldown-example.webxml
qtcharts-pointsselectionandmarkers-example.webxml
@@ -245,7 +225,6 @@ qtcharts-qmlcustomizations-example.webxml
qtcharts-qmlcustomlegend-example.webxml
qtcharts-qmlf1legends-example.webxml
qtcharts-qmloscilloscope-example.webxml
-qtcharts-qmlpolarchart-example.webxml
qtcharts-qmlweather-example.webxml
qtcharts-scatterchart-example.webxml
qtcharts-scatterinteractions-example.webxml
@@ -253,7 +232,6 @@ qtcharts-selectedbar-example.webxml
qtcharts-splinechart-example.webxml
qtcharts-stackedbarchart-example.webxml
qtcharts-stackedbarchartdrilldown-example.webxml
-qtcharts-temperaturerecords-example.webxml
qtcharts-zoomlinechart-example.webxml
qtconcurrent-imagescaling-example.webxml
qtconcurrent-map-example.webxml
@@ -267,17 +245,13 @@ qtconcurrenttask.webxml
qtcore-changes-qt6.webxml
qtcore-ipc-localfortuneclient-example.webxml
qtcore-ipc-localfortuneserver-example.webxml
-qtcore-ipc-sharedmemory-example.webxml
-qtcore-mimetypes-mimetypebrowser-example.webxml
qtcore-platform-androidnotifier-example.webxml
qtcore-serialization-savegame-example.webxml
-qtcore-threads-mandelbrot-example.webxml
qtcore-threads-queuedcustomtype-example.webxml
qtcore-threads-semaphores-example.webxml
qtcore-threads-waitconditions-example.webxml
qtcore-tools-contiguouscache-example.webxml
qtcore-tools-customtype-example.webxml
-qtdatavis3d-bars-example.webxml
qtdatavis3d-custominput-example.webxml
qtdatavis3d-customitems-example.webxml
qtdatavis3d-customproxy-example.webxml
@@ -296,7 +270,6 @@ qtdatavis3d-qmlsurface-example.webxml
qtdatavis3d-qmlsurfacelayers-example.webxml
qtdatavis3d-rotations-example.webxml
qtdatavis3d-scatter-example.webxml
-qtdatavis3d-surface-example.webxml
qtdatavis3d-texturesurface-example.webxml
qtdatavis3d-volumetric-example.webxml
qtdatavisualization-data-handling.webxml
@@ -309,8 +282,6 @@ qtdbus-cmake-qt-add-dbus-interface.webxml
qtdbus-cmake-qt-add-dbus-interfaces.webxml
qtdbus-cmake-qt-generate-dbus-interface.webxml
qtdbus-complexpingpong-example.webxml
-qtdbus-listnames-example.webxml
-qtdbus-pingpong-example.webxml
qtdbus-remotecontrolledcar-example.webxml
qtdesigner-calculatorbuilder-example.webxml
qtdesigner-calculatorform-example.webxml
@@ -318,7 +289,6 @@ qtdesigner-components.webxml
qtdesigner-containerextension-example.webxml
qtdesigner-customwidgetplugin-example.webxml
qtdesigner-manual.webxml
-qtdesigner-taskmenuextension-example.webxml
qtdesigner-worldtimeclockbuilder-example.webxml
qtdesigner-worldtimeclockplugin-example.webxml
qtest-overview.webxml
@@ -339,28 +309,18 @@ qtmath.webxml
qtmultimedia-apple.webxml
qtmultimedia-changes-qt6.webxml
qtmultimedia-multimedia-audiodevices-example.webxml
-qtmultimedia-multimedia-audiooutput-example.webxml
qtmultimedia-multimedia-audiorecorder-example.webxml
-qtmultimedia-multimedia-audiosource-example.webxml
qtmultimedia-multimedia-declarative-camera-example.webxml
qtmultimedia-multimedia-spectrum-example.webxml
qtmultimedia-multimedia-video-mediaplayer-example.webxml
qtmultimedia-multimedia-video-qmlvideo-example.webxml
qtmultimedia-multimedia-video-recorder-example.webxml
-qtmultimedia-multimediawidgets-camera-example.webxml
-qtmultimedia-multimediawidgets-player-example.webxml
qtmultimedia-multimediawidgets-videographicsitem-example.webxml
qtmultimedia-multimediawidgets-videowidget-example.webxml
-qtnetwork-blockingfortuneclient-example.webxml
qtnetwork-broadcastreceiver-example.webxml
qtnetwork-broadcastsender-example.webxml
-qtnetwork-download-example.webxml
qtnetwork-downloadmanager-example.webxml
-qtnetwork-fortuneclient-example.webxml
-qtnetwork-fortuneserver-example.webxml
-qtnetwork-googlesuggest-example.webxml
qtnetwork-http-example.webxml
-qtnetwork-loopback-example.webxml
qtnetwork-multicastreceiver-example.webxml
qtnetwork-multicastsender-example.webxml
qtnetwork-network-chat-example.webxml
@@ -368,10 +328,8 @@ qtnetwork-programming.webxml
qtnetwork-securesocketclient-example.webxml
qtnetwork-secureudpclient-example.webxml
qtnetwork-secureudpserver-example.webxml
-qtnetwork-threadedfortuneserver-example.webxml
qtnetwork-torrent-example.webxml
qtnetworkauth-changes-qt6.webxml
-qtnetworkauth-redditclient-example.webxml
qtnetworkauth-twittertimeline-example.webxml
qtnfc-annotatedurl-example.webxml
qtnfc-changes-qt6.webxml
@@ -379,10 +337,8 @@ qtnfc-ndefeditor-example.webxml
qtnfc-overview.webxml
qtopengl-2dpainting-example.webxml
qtopengl-cube-example.webxml
-qtopengl-hellogl2-example.webxml
qtopengl-hellogles3-example.webxml
qtopengl-openglwindow-example.webxml
-qtopengl-textures-example.webxml
qtplugin.webxml
qtpositioning-android.webxml
qtpositioning-changes-qt6.webxml
@@ -416,7 +372,6 @@ qtqml-syntax-directoryimports.webxml
qtqml-syntax-imports.webxml
qtqml-syntax-objectattributes.webxml
qtqml-syntax-propertybinding.webxml
-qtqml-syntax-signals.webxml
qtqml-tool-qmltc.webxml
qtqml-tutorials-extending-qml-example.webxml
qtqml-typesystem-basictypes.webxml
@@ -451,8 +406,6 @@ qtquick-keyinteraction-example.webxml
qtquick-layouts-example.webxml
qtquick-localstorage-example.webxml
qtquick-models-abstractitemmodel-example.webxml
-qtquick-models-objectlistmodel-example.webxml
-qtquick-models-stringlistmodel-example.webxml
qtquick-modelviewsdata-cppmodels.webxml
qtquick-modelviewsdata-modelview.webxml
qtquick-modelviewsdata-topic.webxml
@@ -469,8 +422,6 @@ qtquick-positioning-righttoleft.webxml
qtquick-positioning-topic.webxml
qtquick-quick-accessibility-example.webxml
qtquick-quickwidgets-quickwidget-example.webxml
-qtquick-rendercontrol-rendercontrol-d3d11-example.webxml
-qtquick-rendercontrol-rendercontrol-opengl-example.webxml
qtquick-righttoleft-example.webxml
qtquick-scenegraph-customgeometry-example.webxml
qtquick-scenegraph-custommaterial-example.webxml
@@ -481,7 +432,6 @@ qtquick-scenegraph-materials.webxml
qtquick-scenegraph-metaltextureimport-example.webxml
qtquick-scenegraph-metalunderqml-example.webxml
qtquick-scenegraph-nodes.webxml
-qtquick-scenegraph-openglunderqml-example.webxml
qtquick-scenegraph-twotextureproviders-example.webxml
qtquick-scenegraph-vulkantextureimport-example.webxml
qtquick-scenegraph-vulkanunderqml-example.webxml
@@ -518,13 +468,11 @@ qtquick-visualcanvas-scenegraph.webxml
qtquick-visualcanvas-topic.webxml
qtquick-visualcanvas-visualparent.webxml
qtquick-visualtypes-topic.webxml
-qtquick-window-example.webxml
qtquickcontrols-changes-qt6.webxml
qtquickcontrols-chattutorial-example.webxml
qtquickcontrols-contactlist-example.webxml
qtquickcontrols-eventcalendar-example.webxml
qtquickcontrols-flatstyle-example.webxml
-qtquickcontrols-gallery-example.webxml
qtquickcontrols-imagine-automotive-example.webxml
qtquickcontrols-imagine-musicplayer-example.webxml
qtquickcontrols-sidepanel-example.webxml
@@ -568,8 +516,6 @@ qtremoteobjects-custom-transport.webxml
qtremoteobjects-external-schemas.webxml
qtremoteobjects-gettingstarted.webxml
qtremoteobjects-interaction.webxml
-qtremoteobjects-modelviewclient-example.webxml
-qtremoteobjects-modelviewserver-example.webxml
qtremoteobjects-node.webxml
qtremoteobjects-qmlmodelviewclient-example.webxml
qtremoteobjects-registry.webxml
@@ -621,13 +567,11 @@ qtserialport-cwritersync-example.webxml
qtserialport-enumerator-example.webxml
qtserialport-examples.webxml
qtserialport-terminal-example.webxml
-qtsql-books-example.webxml
qtsql-cachedtable-example.webxml
qtsql-changes-qt6.webxml
qtsql-drilldown-example.webxml
qtsql-masterdetail-example.webxml
qtsql-querymodel-example.webxml
-qtsql-relationaltablemodel-example.webxml
qtsql-sqlbrowser-example.webxml
qtsql-sqlwidgetmapper-example.webxml
qtsql-tablemodel-example.webxml
@@ -650,7 +594,6 @@ qtwebchannel-chatclient-qml-example.webxml
qtwebchannel-chatserver-cpp-example.webxml
qtwebchannel-examples.webxml
qtwebchannel-javascript.webxml
-qtwebchannel-standalone-example.webxml
qtwebengine-changes-qt6.webxml
qtwebengine-features.webxml
qtwebengine-overview.webxml
@@ -658,18 +601,14 @@ qtwebengine-platform-notes.webxml
qtwebengine-webenginequick-customdialogs-example.webxml
qtwebengine-webenginequick-lifecycle-example.webxml
qtwebengine-webenginequick-minimal-example.webxml
-qtwebengine-webenginequick-quicknanobrowser-example.webxml
qtwebengine-webenginequick-recipebrowser-example.webxml
qtwebengine-webenginequick-webengineaction-example.webxml
qtwebengine-webenginewidgets-contentmanipulation-example.webxml
qtwebengine-webenginewidgets-cookiebrowser-example.webxml
qtwebengine-webenginewidgets-html2pdf-example.webxml
qtwebengine-webenginewidgets-maps-example.webxml
-qtwebengine-webenginewidgets-markdowneditor-example.webxml
qtwebengine-webenginewidgets-minimal-example.webxml
-qtwebengine-webenginewidgets-notifications-example.webxml
qtwebengine-webenginewidgets-printme-example.webxml
-qtwebengine-webenginewidgets-simplebrowser-example.webxml
qtwebengine-webenginewidgets-spellchecker-example.webxml
qtwebengine-webenginewidgets-stylesheetbrowser-example.webxml
qtwebengine-webenginewidgets-videoplayer-example.webxml
@@ -685,45 +624,21 @@ qtwebsockets-simplechat-example.webxml
qtwebsockets-sslechoclient-example.webxml
qtwebsockets-sslechoserver-example.webxml
qtwebsockets-testing.webxml
-qtwidgets-animation-easing-example.webxml
-qtwidgets-desktop-screenshot-example.webxml
-qtwidgets-desktop-systray-example.webxml
-qtwidgets-dialogs-classwizard-example.webxml
-qtwidgets-dialogs-extension-example.webxml
-qtwidgets-dialogs-findfiles-example.webxml
-qtwidgets-dialogs-licensewizard-example.webxml
-qtwidgets-dialogs-standarddialogs-example.webxml
-qtwidgets-dialogs-tabdialog-example.webxml
-qtwidgets-dialogs-trivialwizard-example.webxml
-qtwidgets-draganddrop-draggableicons-example.webxml
-qtwidgets-draganddrop-draggabletext-example.webxml
-qtwidgets-draganddrop-dropsite-example.webxml
qtwidgets-draganddrop-fridgemagnets-example.webxml
qtwidgets-draganddrop-puzzle-example.webxml
-qtwidgets-effects-blurpicker-example.webxml
qtwidgets-effects-fademessage-example.webxml
-qtwidgets-gallery-example.webxml
qtwidgets-gestures-imagegestures-example.webxml
-qtwidgets-graphicsview-anchorlayout-example.webxml
qtwidgets-graphicsview-basicgraphicslayouts-example.webxml
qtwidgets-graphicsview-chip-example.webxml
-qtwidgets-graphicsview-collidingmice-example.webxml
-qtwidgets-graphicsview-diagramscene-example.webxml
-qtwidgets-graphicsview-dragdroprobot-example.webxml
-qtwidgets-graphicsview-elasticnodes-example.webxml
qtwidgets-graphicsview-embeddeddialogs-example.webxml
qtwidgets-graphicsview-flowlayout-example.webxml
qtwidgets-graphicsview-simpleanchorlayout-example.webxml
qtwidgets-graphicsview-weatheranchorlayout-example.webxml
-qtwidgets-itemviews-addressbook-example.webxml
-qtwidgets-itemviews-basicsortfiltermodel-example.webxml
qtwidgets-itemviews-chart-example.webxml
qtwidgets-itemviews-coloreditorfactory-example.webxml
qtwidgets-itemviews-combowidgetmapper-example.webxml
qtwidgets-itemviews-customsortfiltermodel-example.webxml
qtwidgets-itemviews-dirview-example.webxml
-qtwidgets-itemviews-editabletreemodel-example.webxml
-qtwidgets-itemviews-fetchmore-example.webxml
qtwidgets-itemviews-frozencolumn-example.webxml
qtwidgets-itemviews-interview-example.webxml
qtwidgets-itemviews-pixelator-example.webxml
@@ -731,23 +646,11 @@ qtwidgets-itemviews-puzzle-example.webxml
qtwidgets-itemviews-simpledommodel-example.webxml
qtwidgets-itemviews-simpletreemodel-example.webxml
qtwidgets-itemviews-simplewidgetmapper-example.webxml
-qtwidgets-itemviews-spinboxdelegate-example.webxml
-qtwidgets-itemviews-spreadsheet-example.webxml
-qtwidgets-itemviews-stardelegate-example.webxml
-qtwidgets-layouts-basiclayouts-example.webxml
-qtwidgets-layouts-borderlayout-example.webxml
-qtwidgets-layouts-dynamiclayouts-example.webxml
-qtwidgets-layouts-flowlayout-example.webxml
-qtwidgets-mainwindows-application-example.webxml
-qtwidgets-mainwindows-dockwidgets-example.webxml
qtwidgets-mainwindows-mainwindow-example.webxml
-qtwidgets-mainwindows-mdi-example.webxml
qtwidgets-mainwindows-menus-example.webxml
qtwidgets-mainwindows-sdi-example.webxml
qtwidgets-painting-affine-example.webxml
-qtwidgets-painting-basicdrawing-example.webxml
qtwidgets-painting-composition-example.webxml
-qtwidgets-painting-concentriccircles-example.webxml
qtwidgets-painting-deform-example.webxml
qtwidgets-painting-fontsampler-example.webxml
qtwidgets-painting-gradients-example.webxml
@@ -756,9 +659,6 @@ qtwidgets-painting-painterpaths-example.webxml
qtwidgets-painting-pathstroke-example.webxml
qtwidgets-painting-transformations-example.webxml
qtwidgets-richtext-calendar-example.webxml
-qtwidgets-richtext-orderform-example.webxml
-qtwidgets-richtext-syntaxhighlighter-example.webxml
-qtwidgets-richtext-textedit-example.webxml
qtwidgets-tools-completer-example.webxml
qtwidgets-tools-customcompleter-example.webxml
qtwidgets-tools-echoplugin-example.webxml
@@ -766,7 +666,6 @@ qtwidgets-tools-i18n-example.webxml
qtwidgets-tools-plugandpaint-app-example.webxml
qtwidgets-tools-plugandpaint-plugins-basictools-example.webxml
qtwidgets-tools-plugandpaint-plugins-extrafilters-example.webxml
-qtwidgets-tools-regularexpression-example.webxml
qtwidgets-tools-settingseditor-example.webxml
qtwidgets-tools-styleplugin-example.webxml
qtwidgets-tools-treemodelcompleter-example.webxml
@@ -776,13 +675,6 @@ qtwidgets-touch-dials-example.webxml
qtwidgets-touch-fingerpaint-example.webxml
qtwidgets-touch-knobs-example.webxml
qtwidgets-touch-pinchzoom-example.webxml
-qtwidgets-tutorials-addressbook-part1-example.webxml
-qtwidgets-tutorials-addressbook-part2-example.webxml
-qtwidgets-tutorials-addressbook-part3-example.webxml
-qtwidgets-tutorials-addressbook-part4-example.webxml
-qtwidgets-tutorials-addressbook-part5-example.webxml
-qtwidgets-tutorials-addressbook-part6-example.webxml
-qtwidgets-tutorials-addressbook-part7-example.webxml
qtwidgets-tutorials-notepad-example.webxml
qtwidgets-tutorials-widgets-childwidget-example.webxml
qtwidgets-tutorials-widgets-nestedlayouts-example.webxml
@@ -792,7 +684,6 @@ qtwidgets-widgets-analogclock-example.webxml
qtwidgets-widgets-calculator-example.webxml
qtwidgets-widgets-calendarwidget-example.webxml
qtwidgets-widgets-charactermap-example.webxml
-qtwidgets-widgets-codeeditor-example.webxml
qtwidgets-widgets-digitalclock-example.webxml
qtwidgets-widgets-elidedlabel-example.webxml
qtwidgets-widgets-groupbox-example.webxml
@@ -808,12 +699,10 @@ qtwidgets-widgets-spinboxes-example.webxml
qtwidgets-widgets-styles-example.webxml
qtwidgets-widgets-stylesheet-example.webxml
qtwidgets-widgets-tablet-example.webxml
-qtwidgets-widgets-tetrix-example.webxml
qtwidgets-widgets-tooltips-example.webxml
qtwidgets-widgets-validators-example.webxml
qtwidgets-widgets-wiggly-example.webxml
qtwidgets-widgets-windowflags-example.webxml
-qtxml-dombookmarks-example.webxml
qtxml-streambookmarks-example.webxml
qtxml-xmlstreamlint-example.webxml
quick-changes-qt6.webxml
diff --git a/sources/pyside6/doc/considerations.rst b/sources/pyside6/doc/considerations.rst
index 08e53e329..a17cbc269 100644
--- a/sources/pyside6/doc/considerations.rst
+++ b/sources/pyside6/doc/considerations.rst
@@ -222,3 +222,166 @@ Tools
* ``pyside6-designer``: Qt User Interface Designer. This is a graphical tool
to create designs of Qt Widget-based forms and use custom widgets
(see :ref:`using_ui_files`, :ref:`designer_custom_widgets`).
+
+
+.. _NewEnumSystem:
+
+The New Python Enums
+====================
+
+The Motivation to use new Enums
+-------------------------------
+
+For a long time, there were just the Shiboken enums, which were modelled as exact as possible
+after the existing enums in Qt. These enums are small classes which also inherit from
+int.
+
+Meanwhile, Python enums have been developed over the years. They have become a natural
+part of modern Python. The implementation is perfectly modelled after the needs of Python
+users. It is therefore just consequent to stop having two different enum implementations
+in the same application and instead to use the new Python implementation everywhere.
+
+Existing Work
+-------------
+
+The new enums beginning with PySide 6.3, replace the Shiboken enums
+with Python variants, which harmonize the builtin enums with the already existing
+``QEnum`` "macro" shown in the :ref:`QEnum` section.
+
+
+Activating the New Enums
+------------------------
+
+The new approach to enum will be the default in ``PySide 6.4``, but a preview is already built
+into ``PySide 6.3`` with the environment variable:
+`PYSIDE63_OPTION_PYTHON_ENUM=1 python3 <myscript>` enables the new enums.
+In ``PySide 6.4``, this flag is by default on, but it can be switched to the old Shiboken
+enums by setting the variable to 0.
+
+This environment variable will stay until a general acceptance of the new enums has been
+reached and a fallback to the old implementation is no longer needed.
+
+
+The Differences between old and new Enums
+-----------------------------------------
+
+Python enums and Shiboken enums are more or less compatible with each other.
+Tiny differences are in restrictions:
+
+ * Python enums cannot inherit from each other, whereas Shiboken enums can
+
+ * Python enums don't allow undefined values, Shiboken enums do
+
+ * Python enums always need exactly one argument, Shiboken enums have a default zero value
+
+ * Python enums rarely inherit from int, Shiboken enums always do
+
+More visible are the differences between flags, as shown in the following:
+
+The Shiboken flag constructor example has been in PySide prior to 6.3:
+
+::
+
+ flags = Qt.Alignment()
+ enum = Qt.AlignmentFlag
+
+with enum shortcuts like
+
+::
+
+ Qt.AlignLeft = Qt.AlignmentFlag.AlignLeft
+ Qt.AlignTop = Qt.AlignmentFlag.AlignTop
+
+In PySide 6.3, these shortcuts and flags no longer exist (officially).
+Instead, Python has an enum.Flags class which is a subclass of the enum.Enum class.
+But don't be too scared, here comes the good news...
+
+
+Doing a Smooth Transition from the Old Enums
+--------------------------------------------
+
+Changing all the enum code to suddenly use the new syntax is cumbersome and error-prone,
+because such necessary changes are not easy to find.
+Therefore a ``forgiveness mode`` was developed:
+
+The ``forgiveness mode`` allows you to continue using the old constructs but translates them
+silently into the new ones. If you for example write
+
+::
+
+ flags = Qt.Alignment()
+ enum = Qt.AlignLeft
+
+ item.setForeground(QColor(Qt.green))
+
+ flags_type = QPainter.RenderHints
+ flags = QPainter.RenderHints()
+
+ chart_view.setRenderHint(QPainter.Antialiasing)
+
+you get in reality a construct that mimics the following code which is the
+recommended way of writing Flags and Enums:
+
+::
+
+ flags = Qt.AlignmentFlag(0)
+ enum = Qt.AlignmentFlag.AlignLeft
+
+ item.setForeground(QColor(Qt.GlobalColor.green))
+
+ flags_type = QPainter.RenderHint
+ flags = QPainter.RenderHint(0)
+
+ chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)
+
+This has the effect that you can initially ignore the difference between old and new enums,
+as long as the new enums are properties of classes. (This does not work on global enums
+which don't have a class, see ``Limitations`` below.)
+
+
+Forgiveness Mode and Type Hints
+-------------------------------
+
+When you inspect for instance ``QtCore.pyi``, you will only find the new enums, although
+the old ones are still allowed. Also, line completion will only work with the new constructs
+and never propose the old ones.
+
+The reason to implement ``forgiveness mode`` this way was
+
+ * to make the transition as smooth as possible, but
+
+ * to encourage people to use the new enums whenever new code is written.
+
+So you can continue to write:
+
+::
+
+ self.text.setAlignment(Qt.AlignCenter)
+
+but this construct is used and recommended for the future:
+
+::
+
+ self.text.setAlignment(Qt.AlignmentFlag.AlignCenter)
+
+
+Limitations:
+------------
+
+The forgiveness mode works very well whenever the enum class is embedded in a normal
+PySide class. But there are a few global enums, where especially the ``QtMsgType``
+is a problem:
+
+::
+
+ t = QtMsgType.QtDebugMsg
+
+cannot be written in the shortcut form
+
+::
+
+ t = QtDebugMsg
+
+because there is no surrounding PySide class that provides the forgiving mode
+implementation. Typically, the needed changes are easily found because they often occur
+in an import statement.
diff --git a/sources/pyside6/doc/developer/enumfeatures_doc.rst b/sources/pyside6/doc/developer/enumfeatures_doc.rst
new file mode 100644
index 000000000..63535d5f2
--- /dev/null
+++ b/sources/pyside6/doc/developer/enumfeatures_doc.rst
@@ -0,0 +1,159 @@
+************************
+The Set of Enum Features
+************************
+
+The development of the new Python enums took the form of a series of patches.
+While we put a lot of effort into supporting the old Enums (without promoting
+them), it is still possible that someone has a case where they cannot use
+the Python enums as they are now. To avoid people setting the environment
+flag to disable this completely, we implemented a way to select each
+combination of enum functions step by step with a specific set of flags.
+
+
+The Possible Enum Flags
+=======================
+
+This is the table of all flags used to control the creation of Python enums.
+
+====================== ===== ======================================================
+Flag Name Value
+====================== ===== ======================================================
+ENOPT_OLD_ENUM 0x00 (False) Disable new enums
+ENOPT_NEW_ENUM 0x01 (True) The default for PySide 6.4, full implementation
+ENOPT_INHERIT_INT 0x02 Turn all Enum into IntEnum and Flag into IntFlag
+ENOPT_GLOBAL_SHORTCUT 0x04 Re-add shortcuts for global enums
+ENOPT_SCOPED_SHORTCUT 0x08 Re-add shortcuts for scoped enums
+ENOPT_NO_FAKESHORTCUT 0x10 Don't fake rename (forgiveness mode)
+ENOPT_NO_FAKERENAMES 0x20 Don't fake shortcuts (forgiveness mode)
+ENOPT_NO_ZERODEFAULT 0x40 Don't use zero default (forgiveness mode)
+ENOPT_NO_MISSING 0x80 Don't allow missing values in Enum
+====================== ===== ======================================================
+
+Such a set of flags can be defined either by the environment variable
+``PYSIDE63_OPTION_PYTHON_ENUM`` or set by the Python variable
+``sys.pyside63_option_python_enum`` before PySide6 is imported.
+The environment variable also supports arbitrary integer expressions
+by using ``ast.literal_eval``.
+
+
+ENOPT_OLD_ENUM (0x00)
+---------------------
+
+This option completely disables the new enum implementation.
+Even though this is a valid option, we want to avoid it if possible.
+The goal is to eventually remove the old implementation. To make this
+possible, we have made the individual features of the enum implementation
+accessible as flags. This way, if users report problems, we may be able
+to provide a temporary solution before extending enum support accordingly.
+
+
+ENOPT_NEW_ENUM (0x01)
+---------------------
+
+In a perfect world, no one would choose anything other than this default
+setting. Unfortunately, reality is not always like that. That is why
+there are the following flags.
+
+
+The most likely flags needed
+============================
+
+If there are errors, they are likely to be the following: Either implicit
+assumptions are there that require IntEnum, or global enums are used that
+unfortunately cannot be replaced with tricks.
+
+
+ENOPT_INHERIT_INT (0x02)
+------------------------
+
+When this flag is set, all ``enum.Enum/enum.Flag`` classes are converted to
+``enum.IntEnum/enum.IntFlag``. This solves the most likely compatibility
+problem when switching to Python enums. The old Shiboken enums always
+inherit from int, but most Python enums do not.
+
+It was a decision of Python developers not to let enums inherit from int by
+default, since no order should be implied. In most cases, inheritance from
+int can be avoided, either by using the value property or better by
+uplifting: instead of using ``AnEnum.AnInstance.value`` in a function that
+expects an int argument, you can also convert the integer to an enumeration
+instance after the call by ``AnEnum(int_arg)`` and use that in comparisons.
+
+However, there are cases where this is not possible, and explicit support in
+PySide is simply not available. In those cases, you can use this flag as a
+workaround until we have implemented alternatives.
+
+
+ENOPT_GLOBAL_SHORTCUT (0x04)
+----------------------------
+
+At the beginning of the Python enum implementation, we continued to support
+the shortcut behavior of Shiboken enums: the enum constants were mirrored
+into the enclosing scope.
+This was later emulated in the course of forgiveness mode. For enum classes
+in a PySide class this works fine, but for enum classes directly on the module
+level there is no good way to implement forgiveness.
+
+It is unlikely that errors are hidden for global enums, because they should
+already produce an error during import. But for cases without access to
+the source code, you can help yourself with this flag.
+
+A flag value of 0x6 is likely to solve the majority of problems.
+
+
+Flags for completeness
+======================
+
+The following flags complement the description of Python Enums.
+They essentially serve the better understanding of the
+implementation and make it fully transparent and customizable.
+
+
+ENOPT_SCOPED_SHORTCUT (0x08)
+----------------------------
+
+For completeness, we also supported mirroring scoped enums, although this
+has since been replaced by forgiveness mode. If you want to try this,
+please also use the ENOPT_NO_FAKESHORTCUT flag (0x10), otherwise the
+effect of this flag will remain invisible.
+
+
+ENOPT_NO_FAKERENAMES (0x10)
+---------------------------
+
+Forgiveness mode emulates renaming ``Enum.Flag`` classes back to Shiboken
+QFlags structures, which have slightly different names.
+So when such a defunct name is used, the system replaces it internally
+with the new ``enum.Flag`` structure. Unless special boundary problems
+are provoked, this replacement should work.
+
+To see the effect of this renaming, you can turn it off with this flag.
+
+
+ENOPT_NO_ZERODEFAULT (0x40)
+---------------------------
+
+As part of the forgiveness mode, Python enums can be created by a
+parameterless call, although Python enums actually force a parameter
+when called.
+
+The effect can be examined if this flag is set to disable it.
+
+
+ENOPT_NO_MISSING (0x80)
+-----------------------
+
+There are a few cases where Shiboken enums use missing values. In
+``enum.Flag`` structures, this is allowed anyway because we have set the
+``FlagBoundary.KEEP`` flag (see ``enum.py``).
+
+Normal ``enum.Enum`` structures don't have this provision, but the
+``enum`` module allows to pass a ``_missing_`` function for customization.
+
+Our way of dealing with this situation is to create a new fake
+``enum.Enum`` class with the same name and a nameless instance, and
+pretend with an attribute setting that it has the same type.
+The additional instances created in this way are recorded in a class dict
+``_sbk_missing_`` in order to preserve their identity.
+
+You will see the effect of not defining a ``_missing_`` function if you
+set this flag.
diff --git a/sources/shiboken6/libshiboken/pep384impl_doc.rst b/sources/pyside6/doc/developer/pep384impl_doc.rst
index 9ee74a26c..9ee74a26c 100644
--- a/sources/shiboken6/libshiboken/pep384impl_doc.rst
+++ b/sources/pyside6/doc/developer/pep384impl_doc.rst
diff --git a/sources/shiboken6/libshiboken/signature/signature_doc.rst b/sources/pyside6/doc/developer/signature_doc.rst
index 0fb26ae52..0fb26ae52 100644
--- a/sources/shiboken6/libshiboken/signature/signature_doc.rst
+++ b/sources/pyside6/doc/developer/signature_doc.rst
diff --git a/sources/pyside6/doc/extras/QtCore.QEnum.rst b/sources/pyside6/doc/extras/QtCore.QEnum.rst
index d33134264..d42da91ab 100644
--- a/sources/pyside6/doc/extras/QtCore.QEnum.rst
+++ b/sources/pyside6/doc/extras/QtCore.QEnum.rst
@@ -87,6 +87,5 @@ The Python way to specify this would be
class Alignment(enum.Flag):
...
-We are considering to map all builtin enums and flags to Python enums as well
-in a later release.
-
+Meanwhile we have converted all enums and flags to Python Enums (optional in ``PySide 6.3``,
+default in ``PySide 6.4``), see the :ref:`NewEnumSystem` section.
diff --git a/sources/pyside6/doc/feature-why.rst b/sources/pyside6/doc/feature-why.rst
index a795e640c..33bcf1651 100644
--- a/sources/pyside6/doc/feature-why.rst
+++ b/sources/pyside6/doc/feature-why.rst
@@ -1,4 +1,4 @@
-.. _features-why:
+.. _feature-why:
Why do we have a __feature__?
=============================
diff --git a/sources/pyside6/doc/gettingstarted-linux.rst b/sources/pyside6/doc/gettingstarted-linux.rst
index 8db657dac..d32412fdf 100644
--- a/sources/pyside6/doc/gettingstarted-linux.rst
+++ b/sources/pyside6/doc/gettingstarted-linux.rst
@@ -37,41 +37,71 @@ variable required::
7z x libclang-release_100-based-linux-Rhel7.6-gcc5.3-x86_64.7z
export LLVM_INSTALL_DIR=$PWD/libclang
-Getting PySide
-~~~~~~~~~~~~~~
+Getting the source
+~~~~~~~~~~~~~~~~~~
Cloning the official repository can be done by::
- git clone --recursive https://code.qt.io/pyside/pyside-setup
+ git clone https://code.qt.io/pyside/pyside-setup
Checking out the version that we want to build, for example 6.0::
- cd pyside-setup && git checkout 6.0
+ cd pyside-setup && git checkout 6.2
Install the general dependencies::
pip install -r requirements.txt
.. note:: Keep in mind you need to use the same version as your Qt installation.
- Additionally, :command:`git checkout -b 6.0 --track origin/6.0` could be a better option
+ Additionally, :command:`git checkout -b 6.2 --track origin/6.2` could be a better option
in case you want to work on it.
-Building PySide
-~~~~~~~~~~~~~~~
+Building and Installing (setuptools)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `setuptools` approach uses the `setup.py` file to execute the build,
+install, and packaging steps.
Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
for example, :command:`/opt/Qt/6.0.0/gcc_64/bin/qtpaths`.
Build can take a few minutes, so it is recommended to use more than one CPU core::
- python setup.py build --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
-
-Installing PySide
-~~~~~~~~~~~~~~~~~
+ python setup.py build --qtpaths=/opt/Qt/6.2.1/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
To install on the current directory, just run::
- python setup.py install --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+ python setup.py install --qtpaths=/opt/Qt/6.2.1/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+
+Building and Installing (cmake)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The `setuptools` approach includes internal `CMake` calls when
+building and installing the project, but a CMake-only approach is only
+recommended for packaging the project for distribution builds.
+
+Assumming that Qt is in PATH, for example, the configure step can be done with::
+
+ cmake -B /path/to/the/build/directory \
+ -S /path/to/the/pyside-setup \
+ -DCMAKE_INSTALL_PREFIX=/where/to/install \
+ -DPYTHON_EXECUTABLE=/path/to/interpreter
+
+.. note:: You can add `-DFORCE_LIMITED_API=yes` in case you want to have a
+ build which will be compatible with Python 3.7+.
+
+and then for building::
+
+ cmake --build /path/to/the/build/directory --parallel X
+
+where `X` is the amount of processes you want to use.
+Finally, the install step can be done with::
+
+ cmake --install /path/to/the/build/directory
+
+.. note:: You can build only pyside6 or only shiboken6 by using
+ the diferent source directories with the option `-S`.
+
Test installation
~~~~~~~~~~~~~~~~~
diff --git a/sources/pyside6/doc/gettingstarted-macOS.rst b/sources/pyside6/doc/gettingstarted-macOS.rst
index 21e9af393..546902717 100644
--- a/sources/pyside6/doc/gettingstarted-macOS.rst
+++ b/sources/pyside6/doc/gettingstarted-macOS.rst
@@ -45,11 +45,11 @@ Getting PySide
Cloning the official repository can be done by::
- git clone --recursive https://code.qt.io/pyside/pyside-setup
+ git clone https://code.qt.io/pyside/pyside-setup
-Checking out the version that we want to build, for example, 6.0::
+Checking out the version that we want to build, for example, 6.2::
- cd pyside-setup && git checkout 6.0
+ cd pyside-setup && git checkout 6.2
Install the general dependencies::
@@ -61,18 +61,18 @@ Building PySide
~~~~~~~~~~~~~~~
Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
-for example, ``/opt/Qt/6.0.0/gcc_64/bin/qtpaths``.
+for example, ``/opt/Qt/6.2.1/gcc_64/bin/qtpaths``.
Build can take a few minutes, so it is recommended to use more than one CPU core::
- python setup.py build --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+ python setup.py build --qtpaths=/opt/Qt/6.2.1/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
Installing PySide
~~~~~~~~~~~~~~~~~
To install on the current directory, just run::
- python setup.py install --qtpaths=/opt/Qt/6.0.0/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
+ python setup.py install --qtpaths=/opt/Qt/6.2.1/gcc_64/bin/qtpaths --build-tests --ignore-git --parallel=8
Test installation
~~~~~~~~~~~~~~~~~
diff --git a/sources/pyside6/doc/gettingstarted-windows.rst b/sources/pyside6/doc/gettingstarted-windows.rst
index 369cb95eb..0e1f5cdfe 100644
--- a/sources/pyside6/doc/gettingstarted-windows.rst
+++ b/sources/pyside6/doc/gettingstarted-windows.rst
@@ -7,14 +7,14 @@ selected when using the online installer.
Requirements
------------
- * `MSVC2017`_ (or MSVC2019) for Python 3 on Windows,
+ * `MSVC2022`_ or (MSVC2019) for Python 3 on Windows,
* `OpenSSL`_ (optional for SSL support, Qt must have been configured using the same SSL library).
* ``sphinx`` package for the documentation (optional).
.. note:: Python 3.8.0 was missing some API required for PySide/Shiboken so it's not possible
to use it for a Windows build.
-.. _MSVC2017: https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools
+.. _MSVC2022: https://visualstudio.microsoft.com/downloads/
.. _OpenSSL: https://sourceforge.net/projects/openssl/
Building from source on Windows 10
@@ -53,11 +53,11 @@ Getting PySide
Cloning the official repository can be done by::
- git clone --recursive https://code.qt.io/pyside/pyside-setup
+ git clone https://code.qt.io/pyside/pyside-setup
-Checking out the version that we want to build, for example, 6.0::
+Checking out the version that we want to build, for example, 6.2::
- cd pyside-setup && git checkout 6.0
+ cd pyside-setup && git checkout 6.2
Install the general dependencies::
@@ -69,7 +69,7 @@ Building PySide
~~~~~~~~~~~~~~~
Check your Qt installation path, to specifically use that version of qtpaths to build PySide.
-for example, ``E:\Qt\6.0.0\msvc2019_64\bin\qtpaths.exe``.
+for example, ``C:\Qt\6.2.1\msvc2019_64\bin\qtpaths.exe``.
Build can take a few minutes, so it is recommended to use more than one CPU core::
diff --git a/sources/pyside6/doc/gettingstarted.rst b/sources/pyside6/doc/gettingstarted.rst
index 2ff8e30c2..47829171b 100644
--- a/sources/pyside6/doc/gettingstarted.rst
+++ b/sources/pyside6/doc/gettingstarted.rst
@@ -94,7 +94,7 @@ Using the ``--build-tests`` option will enable us to run all the auto tests insi
python testrunner.py test > testlog.txt
.. note:: On Windows, don't forget to have qtpaths in your path
- (:command:`set PATH=E:\\\Path\\\to\\\Qt\\\6.0.0\\\msvc2019_64\\\bin;%PATH%`)
+ (:command:`set PATH=C:\\\Path\\\to\\\Qt\\\6.2.1\\\msvc2019_64\\\bin;%PATH%`)
You can also run a specific test (for example ``qpainter_test``) by running::
@@ -321,7 +321,7 @@ An example of the ``setup.py`` invocation might look like the following:
--parallel=8 --ignore-git --reuse-build --standalone --limited-api=yes \
--cmake-toolchain-file=/opt/toolchain-aarch64.cmake \
--qt-host-path=/opt/Qt/6.3.0/gcc_64 \
- --plat-name=linux_aarch64 \
+ --plat-name=linux_aarch64
Depending on the target platform, you could use ``linux_armv7``,
``linux_aarch64``, etc.
@@ -431,7 +431,7 @@ The target executes several steps:
#. ``sphinx`` is run to produce the documentation in HTML format.
Re-running the command will not execute step 1 unless the file
-``qdoc_output/webxml/qtcore-index.webxml`` is removed from the build tree.
+``qdoc-output/webxml/qtcore-index.webxml`` is removed from the build tree.
Similarly, step 2 will not be executed unless the file ``rst/PySide6/QtCore/index.rst``
is removed.
@@ -457,12 +457,6 @@ Qt Assistant::
assistant -register PySide.qch
-.. note:: Qt Assistant renders the QCH content using the QTextBrowser backend, which supports
- a subset of the CSS styles, However, Qt Creator offers an alternative litehtml-based
- backend, which offers better browsing experience. At the moment, this is not the default
- backend, so you have to select the litehtml backend
- explicitly under the ``General`` tab in ``Qt Creator >> Tools >> Options >> Help``.
-
Using the internal tools
------------------------
diff --git a/sources/pyside6/doc/modules.rst b/sources/pyside6/doc/modules.rst
index 9b20d6906..193e59d37 100644
--- a/sources/pyside6/doc/modules.rst
+++ b/sources/pyside6/doc/modules.rst
@@ -1,5 +1,5 @@
-Qt Modules
-===========
+Qt Modules Supported by Qt for Python
+=====================================
.. toctree::
:hidden:
@@ -18,7 +18,6 @@ Qt Modules
---
-
:mod:`QtCharts <PySide6.QtCharts>`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -79,22 +78,29 @@ Qt Modules
---
- :mod:`QtNetwork <PySide6.QtNetwork>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ :mod:`Qt Multimedia <PySide6.QtMultimedia>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Offers classes that let you to write TCP/IP clients and servers.
+ Provides API for multimedia-specific use cases.
---
- :mod:`QtNfc <PySide6.QtNfc>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ :mod:`Qt Multimedia Widgets <PySide6.QtMultimediaWidgets>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The NFC API provides connectivity between NFC enabled devices.
+ Provides the widget-based multimedia API.
---
- :mod:`QtNetworkAuth <PySide6.QtNetworkAuth>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ :mod:`QtNetwork <PySide6.QtNetwork>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Offers classes that let you to write TCP/IP clients and servers.
+
+ ---
+
+ :mod:`Qt Network Authorization <PySide6.QtNetworkAuth>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Provides a set of APIs that enable Qt applications to obtain limited
access to online accounts and HTTP services without exposing users'
@@ -102,12 +108,10 @@ Qt Modules
---
- :mod:`QtRemoteObjects <PySide6.QtRemoteObjects>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ :mod:`QtNfc <PySide6.QtNfc>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Inter-Process Communication (IPC) module developed for Qt. This module
- extends Qt's existing functionalities to enable information exchange
- between processes or computers, easily.
+ The NFC API provides connectivity between NFC enabled devices.
---
@@ -118,17 +122,18 @@ Qt Modules
---
- :mod:`QtOpenGLFunctions <PySide6.QtOpenGLFunctions>`
+ :mod:`QtOpenGL Widgets <PySide6.QtOpenGLWidgets>`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
+ Provides the OpenGLWidget class enabling OpenGL rendering for a certain
+ part of the widget tree.
---
- :mod:`QtOpenGLWidgets <PySide6.QtOpenGLWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ :mod:`Qt Positioning <PySide6.QtPositioning>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The QOpenGLWidget class is a widget for rendering OpenGL graphics.
+ Provides access to position, satellite info and area monitoring classes.
---
@@ -167,6 +172,36 @@ Qt Modules
---
+ :mod:`QtRemoteObjects <PySide6.QtRemoteObjects>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Inter-Process Communication (IPC) module developed for Qt. This module
+ extends Qt's existing functionalities to enable information exchange
+ between processes or computers, easily.
+
+ ---
+
+ :mod:`Qt Scxml <PySide6.QtScxml>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Provides classes to create and use state machines from SCXML files.
+
+ ---
+
+ :mod:`Qt Sensors <PySide6.QtSensors>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Provides access to sensor hardware.
+
+ ---
+
+ :mod:`Qt Serial Port <PySide6.QtSerialPort>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Provides classes to interact with hardware and virtual serial ports.
+
+ ---
+
:mod:`Qt Scxml <PySide6.QtScxml>`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -188,15 +223,6 @@ Qt Modules
---
- :mod:`QtSerialPort <PySide6.QtSerialPort>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides the basic functionality, which includes configuring, I/O
- operations, getting and setting the control signals of the RS-232
- pinouts.
-
- ---
-
:mod:`QtSvg <PySide6.QtSvg>`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -225,24 +251,11 @@ Qt Modules
---
- :mod:`QtWidgets <PySide6.QtWidgets>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ :mod:`Qt WebChannel <PySide6.QtWebChannel>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Extends Qt GUI with C++ widget functionality.
-
- ---
-
- :mod:`QtXml <PySide6.QtXml>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides a C++ implementation of DOM.
-
- ---
-
- :mod:`Qt3DAnimation <PySide6.Qt3DAnimation>`
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- Provides basic elements required to animate 3D objects.
+ Provides access to QObject or QML objects from HTML clients for seamless
+ integration of Qt applications with HTML/JavaScript clients.
---
@@ -267,6 +280,34 @@ Qt Modules
---
+ :mod:`Qt WebSockets <PySide6.QtWebSockets>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Provides WebSocket communication compliant with RFC 6455.
+
+ ---
+
+ :mod:`QtWidgets <PySide6.QtWidgets>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Extends Qt GUI with C++ widget functionality.
+
+ ---
+
+ :mod:`QtXml <PySide6.QtXml>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Provides a C++ implementation of DOM.
+
+ ---
+
+ :mod:`Qt3DAnimation <PySide6.Qt3DAnimation>`
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+ Provides basic elements required to animate 3D objects.
+
+ ---
+
:mod:`Qt3D Core <PySide6.Qt3DCore>`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/sources/pyside6/doc/package_details.rst b/sources/pyside6/doc/package_details.rst
index 3fd3d86f7..a5baa334e 100644
--- a/sources/pyside6/doc/package_details.rst
+++ b/sources/pyside6/doc/package_details.rst
@@ -5,7 +5,9 @@ Package Details
Having a large project as the Qt Framework available from one simple
installation line::
- pip install pyside6
+
+ pip install pyside6
+
is really beneficial,
but it might be confusing to newcomers.
diff --git a/sources/pyside6/doc/porting_from2.rst b/sources/pyside6/doc/porting_from2.rst
index aa3e41780..2d5c8414f 100644
--- a/sources/pyside6/doc/porting_from2.rst
+++ b/sources/pyside6/doc/porting_from2.rst
@@ -4,23 +4,17 @@ Porting Applications from PySide2 to PySide6
Module Availability
-------------------
-Qt for Python 6.0.0 initially ships with the essential
-`Modules <https://doc.qt.io/qt-6/qtmodules.html>`_ and some
-add-ons (Qt 3D, Qt Concurrent, Qt Help, Qt OpenGL, Qt Print Support
-Qt Quick Widgets, Qt SQL, Qt SVG, Qt UI Tools and Qt XML).
-
-More modules will follow in subsequent releases as they
-are added to Qt.
-
-For Qt for Python 6.1, Active Qt, Qt Charts, Qt Data Visualization,
-Qt StateMachine and Qt SCXML are planned.
+Qt for Python 6.2.0 provides all modules planned for inclusion in Qt 6.
Module-Level Changes
--------------------
-* *Qt Quick Controls 1* have been removed.
+* The modules *QtMacExtras*, *Qt Quick Controls 1*, *QtWinExtras*,
+ *QtXmlPatterns* and *QtX11Extras* have been removed.
* ``QStateMachine`` and related classes have been extracted to a new
*QtStateMachine* module.
+* The modules *QtWebKit* and *QtWebKitWidgets* have been replaced by the new
+ *QtWebEngineCore*, *QtWebEngineQuick* and *QtWebEngineWidgets* modules.
* ``QXmlReader`` and related classes (*SAX API*) have been removed.
* The content of the *QtOpenGL* module has been replaced. The class
``QGLWidget`` and related classes (``QGLContext``, ``QGLFunctions``,
@@ -97,4 +91,4 @@ accordingly. For example:
More information can be found in the
`Porting to Qt 6 <https://doc.qt.io/qt-6/portingguide.html>`_ Guide
-and the `Qt 6.0 Documentation <https://doc.qt.io/qt-6/index.html>`_ .
+and the `Qt 6.2 Documentation <https://doc.qt.io/qt-6/index.html>`_ .
diff --git a/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py b/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py
new file mode 100644
index 000000000..de386a5ac
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/examples/widgets/itemviews/spinboxdelegate/delegate_0.h.py
@@ -0,0 +1,18 @@
+class SpinBoxDelegate(QStyledItemDelegate):
+ """A delegate that allows the user to change integer values from the model
+ using a spin box widget. """
+
+ def __init__(self, parent=None):
+ ...
+
+ def createEditor(self, parent, option, index):
+ ...
+
+ def setEditorData(self, editor, index):
+ ...
+
+ def setModelData(self, editor, model, index):
+ ...
+
+ def updateEditorGeometry(self, editor, option, index):
+ ...
diff --git a/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py b/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py
new file mode 100644
index 000000000..02a02aaf8
--- /dev/null
+++ b/sources/pyside6/doc/snippets/qtbase/src/widgets/doc/snippets/stringlistmodel/model_0.h.py
@@ -0,0 +1,24 @@
+class StringListModel(QAbstractListModel):
+ def __init__(self, strings, parent=None):
+ ...
+
+ def rowCount(self, parent=QModelIndex()):
+ ...
+
+ def data(self, index, role):
+ ...
+
+ def headerData(self, section, orientation, role=Qt.DisplayRole):
+ ...
+
+ def flags(self, index):
+ ...
+
+ def setData(self, index, value, role=Qt.EditRole):
+ ...
+
+ def insertRows(self, position, rows, parent):
+ ...
+
+ def removeRows(self, position, rows, parent):
+ ...
diff --git a/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst b/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst
index 470b4ab70..d22075812 100644
--- a/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst
+++ b/sources/pyside6/doc/tutorials/basictutorial/signals_and_slots.rst
@@ -185,7 +185,7 @@ the different functionality.
speak = Signal((int,), (str,))
def __init__(self, parent=None):
- super().__init__(self, parent)
+ super().__init__(parent)
self.speak[int].connect(self.say_something)
self.speak[str].connect(self.say_something)
diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py b/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py
new file mode 100644
index 000000000..cebc99447
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/modelviewprogramming/qlistview-dnd.py
@@ -0,0 +1,174 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtWidgets import (QAbstractItemView, QApplication, QMainWindow,
+ QListView)
+from PySide6.QtCore import (QByteArray, QDataStream, QIODevice, QMimeData,
+ QModelIndex, QStringListModel, Qt)
+
+
+class DragDropListModel(QStringListModel):
+ """A simple model that uses a QStringList as its data source."""
+
+ def __init__(self, strings, parent=None):
+ super().__init__(strings, parent)
+
+#! [0]
+
+ def canDropMimeData(self, data, action, row, column, parent):
+ if not data.hasFormat("application/vnd.text.list"):
+ return False
+
+ if column > 0:
+ return False
+
+ return True
+#! [0]
+#! [1]
+ def dropMimeData(self, data, action, row, column, parent):
+ if not self.canDropMimeData(data, action, row, column, parent):
+ return False
+
+ if action == Qt.IgnoreAction:
+ return True
+#! [1]
+
+#! [2]
+ begin_row = 0
+
+ if row != -1:
+ begin_row = row
+#! [2] #! [3]
+ elif parent.isValid():
+ begin_row = parent.row()
+#! [3] #! [4]
+ else:
+ begin_row = self.rowCount(QModelIndex())
+#! [4]
+
+#! [5]
+ encoded_data = data.data("application/vnd.text.list")
+ stream = QDataStream(encoded_data, QIODevice.ReadOnly)
+ new_items = []
+ while not stream.atEnd():
+ new_items.append(stream.readQString())
+#! [5]
+
+#! [6]
+ self.insertRows(begin_row, len(new_items), QModelIndex())
+ for text in new_items:
+ idx = self.index(begin_row, 0, QModelIndex())
+ self.setData(idx, text)
+ begin_row += 1
+
+ return True
+#! [6]
+
+#! [7]
+ def flags(self, index):
+ default_flags = super().flags(index)
+ if index.isValid():
+ return Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled | default_flags
+ return Qt.ItemIsDropEnabled | default_flags
+#! [7]
+
+#! [8]
+ def mimeData(self, indexes):
+ mime_data = QMimeData()
+ encoded_data = QByteArray()
+ stream = QDataStream(encoded_data, QIODevice.WriteOnly)
+ for index in indexes:
+ if index.isValid():
+ text = self.data(index, Qt.DisplayRole)
+ stream.writeQString(text)
+
+ mime_data.setData("application/vnd.text.list", encoded_data)
+ return mime_data
+#! [8]
+
+#! [9]
+ def mimeTypes(self):
+ return ["application/vnd.text.list"]
+#! [9]
+
+#! [10]
+ def supportedDropActions(self):
+ return Qt.CopyAction | Qt.MoveAction
+#! [10]
+
+
+class MainWindow(QMainWindow):
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ file_menu = self.menuBar().addMenu("&File")
+ quit_action = file_menu.addAction("E&xit")
+ quit_action.setShortcut("Ctrl+Q")
+
+#! [mainwindow0]
+ self._list_view = QListView(self)
+ self._list_view.setSelectionMode(QAbstractItemView.ExtendedSelection)
+ self._list_view.setDragEnabled(True)
+ self._list_view.setAcceptDrops(True)
+ self._list_view.setDropIndicatorShown(True)
+#! [mainwindow0]
+
+ quit_action.triggered.connect(self.close)
+
+ self.setup_list_items()
+
+ self.setCentralWidget(self._list_view)
+ self.setWindowTitle("List View")
+
+ def setup_list_items(self):
+ items = ["Oak", "Fir", "Pine", "Birch", "Hazel", "Redwood", "Sycamore",
+ "Chestnut", "Mahogany"]
+ model = DragDropListModel(items, self)
+ self._list_view.setModel(model)
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ window = MainWindow()
+ window.show()
+ sys.exit(app.exec())
diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py b/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py
new file mode 100644
index 000000000..503834aaf
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/modelviewprogramming/simplemodel-use.py
@@ -0,0 +1,81 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtWidgets import (QApplication, QFileSystemModel, QLabel,
+ QVBoxLayout, QWidget)
+from PySide6.QtGui import QPalette
+from PySide6.QtCore import QDir, Qt
+
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+ window = QWidget()
+ layout = QVBoxLayout(window)
+ title = QLabel("Some items from the directory model", window)
+ title.setBackgroundRole(QPalette.Base)
+ title.setMargin(8)
+ layout.addWidget(title)
+
+#! [0]
+ model = QFileSystemModel()
+ model.setRootPath(QDir.currentPath())
+
+ def on_directory_loaded(directory):
+ parent_index = model.index(directory)
+ num_rows = model.rowCount(parent_index)
+#! [1]
+ for row in range(num_rows):
+ index = model.index(row, 0, parent_index)
+#! [1]
+#! [2]
+ text = model.data(index, Qt.DisplayRole)
+#! [2]
+ label = QLabel(text, window)
+ layout.addWidget(label)
+
+ model.directoryLoaded.connect(on_directory_loaded)
+#! [0]
+
+ window.setWindowTitle("A simple model example")
+ window.show()
+ sys.exit(app.exec())
diff --git a/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py b/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py
new file mode 100644
index 000000000..9d3631f62
--- /dev/null
+++ b/sources/pyside6/doc/tutorials/modelviewprogramming/stringlistmodel.py
@@ -0,0 +1,161 @@
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the Qt for Python 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
+
+from PySide6.QtWidgets import (QApplication, QListView)
+from PySide6.QtCore import QAbstractListModel, QStringListModel, QModelIndex, Qt
+
+
+#! [0]
+class StringListModel(QAbstractListModel):
+ def __init__(self, strings, parent=None):
+ super().__init__(parent)
+ self._strings = strings
+
+#! [0]
+ def rowCount(self, parent=QModelIndex()):
+ """Returns the number of items in the string list as the number of rows
+ in the model."""
+ return len(self._strings)
+#! [0]
+
+#! [1]
+ def data(self, index, role):
+ """Returns an appropriate value for the requested data.
+ If the view requests an invalid index, an invalid variant is returned.
+ Any valid index that corresponds to a string in the list causes that
+ string to be returned."""
+ row = index.row()
+ if not index.isValid() or row >= len(self._strings):
+ return None
+ if role != Qt.DisplayRole and role != Qt.EditRole:
+ return None
+ return self._strings[row]
+#! [1]
+
+#! [2]
+ def headerData(self, section, orientation, role=Qt.DisplayRole):
+ """Returns the appropriate header string depending on the orientation of
+ the header and the section. If anything other than the display role is
+ requested, we return an invalid variant."""
+ if role != Qt.DisplayRole:
+ return None
+ if orientation == Qt.Horizontal:
+ return f"Column {section}"
+ return f"Row {section}"
+#! [2]
+
+#! [3]
+ def flags(self, index):
+ """Returns an appropriate value for the item's flags. Valid items are
+ enabled, selectable, and editable."""
+
+ if not index.isValid():
+ return Qt.ItemIsEnabled
+ return super().flags(index) | Qt.ItemIsEditable
+#! [3]
+
+ #! [4]
+ def setData(self, index, value, role=Qt.EditRole):
+ """Changes an item in the string list, but only if the following conditions
+ are met:
+
+ # The index supplied is valid.
+ # The index corresponds to an item to be shown in a view.
+ # The role associated with editing text is specified.
+
+ The dataChanged() signal is emitted if the item is changed."""
+
+ if index.isValid() and role == Qt.EditRole:
+ self._strings[index.row()] = value
+ self.dataChanged.emit(index, index, {role})
+ return True
+#! [4] #! [5]
+ return False
+#! [5]
+
+#! [6]
+ def insertRows(self, position, rows, parent):
+ """Inserts a number of rows into the model at the specified position."""
+ self.beginInsertRows(QModelIndex(), position, position + rows - 1)
+ for row in range(rows):
+ self._strings.insert(position, "")
+ self.endInsertRows()
+ return True
+#! [6] #! [7]
+#! [7]
+
+#! [8]
+ def removeRows(self, position, rows, parent):
+ """Removes a number of rows from the model at the specified position."""
+ self.beginRemoveRows(QModelIndex(), position, position + rows - 1)
+ for row in range(rows):
+ del self._strings[position]
+ self.endRemoveRows()
+ return True
+#! [8] #! [9]
+#! [9]
+
+
+#! [main0]
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+
+#! [main1]
+ numbers = ["One", "Two", "Three", "Four", "Five"]
+ model = StringListModel(numbers)
+#! [main0] #! [main1] #! [main2] #! [main3]
+ view = QListView()
+#! [main2]
+ view.setWindowTitle("View onto a string list model")
+#! [main4]
+ view.setModel(model)
+#! [main3] #! [main4]
+
+ model.insertRows(5, 7, QModelIndex())
+ for row in range(5, 12):
+ index = model.index(row, 0, QModelIndex())
+ model.setData(index, f"{row+1}")
+
+#! [main5]
+ view.show()
+ sys.exit(app.exec())
+#! [main5]
diff --git a/sources/pyside6/libpyside/feature_select.cpp b/sources/pyside6/libpyside/feature_select.cpp
index 1a0f00018..a97f26d6d 100644
--- a/sources/pyside6/libpyside/feature_select.cpp
+++ b/sources/pyside6/libpyside/feature_select.cpp
@@ -500,7 +500,7 @@ static PyObject *methodWithNewName(PyTypeObject *type,
return descr;
}
-static bool feature_01_addLowerNames(PyTypeObject *type, PyObject *prev_dict, int id)
+static bool feature_01_addLowerNames(PyTypeObject *type, PyObject *prev_dict, int /* id */)
{
PyMethodDef *meth = type->tp_methods;
PyObject *lower_dict = type->tp_dict;
@@ -788,7 +788,7 @@ static bool patch_property_impl()
//
#define SIMILAR_FEATURE(xx) \
-static bool feature_##xx##_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id) \
+static bool feature_##xx##_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int /* id */) \
{ \
PyObject *dict = type->tp_dict; \
if (PyDict_Update(dict, prev_dict) < 0) \
diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp
index 5e68253d8..b9f788b61 100644
--- a/sources/pyside6/libpyside/pysideproperty.cpp
+++ b/sources/pyside6/libpyside/pysideproperty.cpp
@@ -103,6 +103,7 @@ static PyType_Slot PySidePropertyType_slots[] = {
{Py_tp_init, reinterpret_cast<void *>(qpropertyTpInit)},
{Py_tp_new, reinterpret_cast<void *>(qpropertyTpNew)},
{Py_tp_getset, PySidePropertyType_getset},
+ {Py_tp_del, reinterpret_cast<void *>(PyObject_GC_Del)},
{0, nullptr}
};
@@ -271,6 +272,7 @@ static void qpropertyDeAlloc(PyObject *self)
// This was not needed before Python 3.8 (Python issue 35810)
Py_DECREF(Py_TYPE(self));
}
+ PyObject_GC_UnTrack(self);
Py_TYPE(self)->tp_free(self);
}
diff --git a/sources/pyside6/libpyside/pysideqenum.cpp b/sources/pyside6/libpyside/pysideqenum.cpp
index bc4515ca0..2ac26b02c 100644
--- a/sources/pyside6/libpyside/pysideqenum.cpp
+++ b/sources/pyside6/libpyside/pysideqenum.cpp
@@ -53,7 +53,7 @@ extern "C" {
using namespace Shiboken;
-static PyObject *analyzePyEnum(PyObject *pyenum, PyObject *container = nullptr)
+static PyObject *analyzePyEnum(PyObject *pyenum)
{
/*
* This is the straight-forward implementation of QEnum/QFlag. It does no
diff --git a/sources/pyside6/libpyside/pysideqflags.cpp b/sources/pyside6/libpyside/pysideqflags.cpp
index 8cc6b0b30..197119ec3 100644
--- a/sources/pyside6/libpyside/pysideqflags.cpp
+++ b/sources/pyside6/libpyside/pysideqflags.cpp
@@ -100,8 +100,14 @@ extern "C" {
{
int result = 0;
if (!PyNumber_Check(other)) {
- PyErr_BadArgument();
- return nullptr;
+ switch (op) {
+ case Py_EQ:
+ Py_RETURN_FALSE;
+ case Py_NE:
+ Py_RETURN_TRUE;
+ default:
+ Py_RETURN_NOTIMPLEMENTED;
+ }
}
if (self == other) {
diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp
index a4bc583e6..a365d351f 100644
--- a/sources/pyside6/libpyside/pysidesignal.cpp
+++ b/sources/pyside6/libpyside/pysidesignal.cpp
@@ -172,12 +172,12 @@ PyTypeObject *PySideSignal_TypeF(void)
return type;
}
-static PyObject *signalInstanceRepr(PyObject *self)
+static PyObject *signalInstanceRepr(PyObject *obSelf)
{
- auto *data = reinterpret_cast<PySideSignalInstance *>(self);
- auto *typeName = Py_TYPE(self)->tp_name;
+ auto *self = reinterpret_cast<PySideSignalInstance *>(obSelf);
+ auto *typeName = Py_TYPE(obSelf)->tp_name;
return Shiboken::String::fromFormat("<%s %s at %p>", typeName,
- data->d->signature.constData(), self);
+ self->d->signature.constData(), obSelf);
}
static PyMethodDef SignalInstance_methods[] = {
@@ -213,7 +213,7 @@ PyTypeObject *PySideSignalInstance_TypeF(void)
return type;
}
-static int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds)
+static int signalTpInit(PyObject *obSelf, PyObject *args, PyObject *kwds)
{
static PyObject * const emptyTuple = PyTuple_New(0);
static const char *kwlist[] = {"name", "arguments", nullptr};
@@ -221,27 +221,28 @@ static int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds)
PyObject *argArguments = nullptr;
if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds,
- "|sO:QtCore.Signal", const_cast<char **>(kwlist), &argName, &argArguments))
+ "|sO:QtCore.Signal{name, arguments}",
+ const_cast<char **>(kwlist), &argName, &argArguments))
return -1;
bool tupledArgs = false;
- PySideSignal *data = reinterpret_cast<PySideSignal *>(self);
- if (!data->data)
- data->data = new PySideSignalData;
+ PySideSignal *self = reinterpret_cast<PySideSignal *>(obSelf);
+ if (!self->data)
+ self->data = new PySideSignalData;
if (argName)
- data->data->signalName = argName;
+ self->data->signalName = argName;
const Py_ssize_t argument_size =
argArguments != nullptr && PySequence_Check(argArguments)
? PySequence_Size(argArguments) : 0;
if (argument_size > 0) {
- data->data->signalArguments = new QByteArrayList();
- data->data->signalArguments->reserve(argument_size);
+ self->data->signalArguments = new QByteArrayList();
+ self->data->signalArguments->reserve(argument_size);
for (Py_ssize_t i = 0; i < argument_size; ++i) {
Shiboken::AutoDecRef item(PySequence_GetItem(argArguments, i));
Shiboken::AutoDecRef strObj(PyUnicode_AsUTF8String(item));
if (char *s = PyBytes_AsString(strObj))
- data->data->signalArguments->append(QByteArray(s));
+ self->data->signalArguments->append(QByteArray(s));
}
}
@@ -251,7 +252,7 @@ static int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds)
tupledArgs = true;
const auto sig = PySide::Signal::parseSignature(arg);
PySide::Signal::appendSignature(
- data,
+ self,
PySide::Signal::SignalSignature(sig));
}
}
@@ -259,37 +260,39 @@ static int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds)
if (!tupledArgs) {
const auto sig = PySide::Signal::parseSignature(args);
PySide::Signal::appendSignature(
- data,
+ self,
PySide::Signal::SignalSignature(sig));
}
return 0;
}
-static void signalFree(void *self)
+static void signalFree(void *vself)
{
- auto pySelf = reinterpret_cast<PyObject *>(self);
- auto data = reinterpret_cast<PySideSignal *>(self);
- delete data->data->signalArguments;
- delete data->data;
- data->data = nullptr;
- Py_XDECREF(data->homonymousMethod);
- data->homonymousMethod = nullptr;
+ auto pySelf = reinterpret_cast<PyObject *>(vself);
+ auto self = reinterpret_cast<PySideSignal *>(vself);
+ if (self->data) {
+ delete self->data->signalArguments;
+ delete self->data;
+ self->data = nullptr;
+ }
+ Py_XDECREF(self->homonymousMethod);
+ self->homonymousMethod = nullptr;
Py_TYPE(pySelf)->tp_base->tp_free(self);
}
-static PyObject *signalGetItem(PyObject *self, PyObject *key)
+static PyObject *signalGetItem(PyObject *obSelf, PyObject *key)
{
- auto data = reinterpret_cast<PySideSignal *>(self);
+ auto self = reinterpret_cast<PySideSignal *>(obSelf);
QByteArray sigKey;
if (key) {
sigKey = PySide::Signal::parseSignature(key);
} else {
- sigKey = data->data == nullptr || data->data->signatures.isEmpty()
- ? PySide::Signal::voidType() : data->data->signatures.constFirst().signature;
+ sigKey = self->data == nullptr || self->data->signatures.isEmpty()
+ ? PySide::Signal::voidType() : self->data->signatures.constFirst().signature;
}
- auto sig = PySide::Signal::buildSignature(data->data->signalName, sigKey);
+ auto sig = PySide::Signal::buildSignature(self->data->signalName, sigKey);
return Shiboken::String::fromCString(sig.constData());
}
@@ -299,12 +302,12 @@ static PyObject *signalToString(PyObject *self)
return signalGetItem(self, nullptr);
}
-static void signalInstanceFree(void *self)
+static void signalInstanceFree(void *vself)
{
- auto pySelf = reinterpret_cast<PyObject *>(self);
- auto data = reinterpret_cast<PySideSignalInstance *>(self);
+ auto pySelf = reinterpret_cast<PyObject *>(vself);
+ auto self = reinterpret_cast<PySideSignalInstance *>(vself);
- PySideSignalInstancePrivate *dataPvt = data->d;
+ PySideSignalInstancePrivate *dataPvt = self->d;
Py_XDECREF(dataPvt->homonymousMethod);
@@ -313,7 +316,7 @@ static void signalInstanceFree(void *self)
dataPvt->next = nullptr;
}
delete dataPvt;
- data->d = nullptr;
+ self->d = nullptr;
Py_TYPE(pySelf)->tp_base->tp_free(self);
}
@@ -753,8 +756,10 @@ static const char *MetaSignal_SignatureStrings[] = {
static const char *Signal_SignatureStrings[] = {
"PySide6.QtCore.Signal(self,*types:type,name:str=nullptr,arguments:str=nullptr)",
- "1:PySide6.QtCore.Signal.__get__(self,instance:None,owner:Optional[typing.Any])->PySide6.QtCore.Signal",
- "0:PySide6.QtCore.Signal.__get__(self,instance:PySide6.QtCore.QObject,owner:Optional[typing.Any])->PySide6.QtCore.SignalInstance",
+ "1:PySide6.QtCore.Signal.__get__(self,instance:None,owner:Optional[typing.Any])->"
+ "PySide6.QtCore.Signal",
+ "0:PySide6.QtCore.Signal.__get__(self,instance:PySide6.QtCore.QObject,"
+ "owner:Optional[typing.Any])->PySide6.QtCore.SignalInstance",
nullptr}; // Sentinel
static const char *SignalInstance_SignatureStrings[] = {
@@ -768,17 +773,20 @@ void init(PyObject *module)
if (InitSignatureStrings(PySideMetaSignal_TypeF(), MetaSignal_SignatureStrings) < 0)
return;
Py_INCREF(PySideMetaSignal_TypeF());
- PyModule_AddObject(module, "MetaSignal", reinterpret_cast<PyObject *>(PySideMetaSignal_TypeF()));
+ auto *obMetaSignal_Type = reinterpret_cast<PyObject *>(PySideMetaSignal_TypeF());
+ PyModule_AddObject(module, "MetaSignal", obMetaSignal_Type);
if (InitSignatureStrings(PySideSignal_TypeF(), Signal_SignatureStrings) < 0)
return;
Py_INCREF(PySideSignal_TypeF());
- PyModule_AddObject(module, "Signal", reinterpret_cast<PyObject *>(PySideSignal_TypeF()));
+ auto *obSignal_Type = reinterpret_cast<PyObject *>(PySideSignal_TypeF());
+ PyModule_AddObject(module, "Signal", obSignal_Type);
if (InitSignatureStrings(PySideSignalInstance_TypeF(), SignalInstance_SignatureStrings) < 0)
return;
Py_INCREF(PySideSignalInstance_TypeF());
- PyModule_AddObject(module, "SignalInstance", reinterpret_cast<PyObject *>(PySideSignalInstance_TypeF()));
+ auto *obSignalInstance_Type = reinterpret_cast<PyObject *>(PySideSignalInstance_TypeF());
+ PyModule_AddObject(module, "SignalInstance", obSignalInstance_Type);
}
bool checkType(PyObject *pyObj)
@@ -897,29 +905,29 @@ static void appendSignature(PySideSignal *self, const SignalSignature &signature
self->data->signatures.append({signature.m_parameterTypes, signature.m_attributes});
}
-static void instanceInitialize(PySideSignalInstance *self, PyObject *name, PySideSignal *data, PyObject *source, int index)
+static void instanceInitialize(PySideSignalInstance *self, PyObject *name, PySideSignal *signal, PyObject *source, int index)
{
self->d = new PySideSignalInstancePrivate;
PySideSignalInstancePrivate *selfPvt = self->d;
selfPvt->next = nullptr;
- if (data->data->signalName.isEmpty())
- data->data->signalName = Shiboken::String::toCString(name);
- selfPvt->signalName = data->data->signalName;
+ if (signal->data->signalName.isEmpty())
+ signal->data->signalName = Shiboken::String::toCString(name);
+ selfPvt->signalName = signal->data->signalName;
selfPvt->source = source;
- const auto &signature = data->data->signatures.at(index);
+ const auto &signature = signal->data->signatures.at(index);
selfPvt->signature = buildSignature(self->d->signalName, signature.signature);
selfPvt->attributes = signature.attributes;
selfPvt->homonymousMethod = nullptr;
- if (data->homonymousMethod) {
- selfPvt->homonymousMethod = data->homonymousMethod;
+ if (signal->homonymousMethod) {
+ selfPvt->homonymousMethod = signal->homonymousMethod;
Py_INCREF(selfPvt->homonymousMethod);
}
index++;
- if (index < data->data->signatures.size()) {
+ if (index < signal->data->signatures.size()) {
selfPvt->next = PyObject_New(PySideSignalInstance, PySideSignalInstance_TypeF());
- instanceInitialize(selfPvt->next, name, data, source, index);
+ instanceInitialize(selfPvt->next, name, signal, source, index);
}
}
diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp
index 67302beab..1efd8cb3b 100644
--- a/sources/pyside6/libpyside/signalmanager.cpp
+++ b/sources/pyside6/libpyside/signalmanager.cpp
@@ -244,7 +244,7 @@ static void PyObject_PythonToCpp_PyObject_PTR(PyObject *pyIn, void *cppOut)
{
*reinterpret_cast<PyObject **>(cppOut) = pyIn;
}
-static PythonToCppFunc is_PyObject_PythonToCpp_PyObject_PTR_Convertible(PyObject *pyIn)
+static PythonToCppFunc is_PyObject_PythonToCpp_PyObject_PTR_Convertible(PyObject * /* pyIn */)
{
return PyObject_PythonToCpp_PyObject_PTR;
}
@@ -413,8 +413,12 @@ int SignalManager::SignalManagerPrivate::qtPropertyMetacall(QObject *object,
pp->d->metaCall(pySelf, call, args);
Py_XDECREF(pp);
- if (PyErr_Occurred())
+ if (PyErr_Occurred()) {
+ qWarning().noquote().nospace()
+ << "An error occurred executing the property metacall " << call
+ << " on property \"" << mp.name() << "\" of " << object;
handleMetaCallError(object, &result);
+ }
return result;
}
diff --git a/sources/pyside6/plugins/uitools/customwidget.cpp b/sources/pyside6/plugins/uitools/customwidget.cpp
index 8b7a61238..4fba3f811 100644
--- a/sources/pyside6/plugins/uitools/customwidget.cpp
+++ b/sources/pyside6/plugins/uitools/customwidget.cpp
@@ -134,7 +134,7 @@ QWidget *PyCustomWidget::createWidget(QWidget *parent)
return reinterpret_cast<QWidget *>(Shiboken::Object::cppPointer(result, Py_TYPE(result)));
}
-void PyCustomWidget::initialize(QDesignerFormEditorInterface *core)
+void PyCustomWidget::initialize(QDesignerFormEditorInterface *)
{
m_initialized = true;
}
diff --git a/sources/pyside6/tests/QtCore/qenum_test.py b/sources/pyside6/tests/QtCore/qenum_test.py
index 612a3873b..4514dd256 100644
--- a/sources/pyside6/tests/QtCore/qenum_test.py
+++ b/sources/pyside6/tests/QtCore/qenum_test.py
@@ -45,7 +45,7 @@ from PySide6.QtCore import Qt, QIODevice, QObject, QEnum, QFlag
class TestEnum(unittest.TestCase):
-
+ @unittest.skipIf(sys.pyside63_option_python_enum, "not adequate for new enums to ask the value")
def testToInt(self):
self.assertEqual(QIODevice.NotOpen, 0)
self.assertEqual(QIODevice.ReadOnly, 1)
@@ -56,6 +56,7 @@ class TestEnum(unittest.TestCase):
self.assertEqual(QIODevice.Text, 16)
self.assertEqual(QIODevice.Unbuffered, 32)
+ @unittest.skipIf(sys.pyside63_option_python_enum, "not adequate for new enums to ask the value")
def testToIntInFunction(self):
self.assertEqual(str(int(QIODevice.WriteOnly)), "2")
@@ -105,18 +106,21 @@ class TestEnum(unittest.TestCase):
class TestQFlags(unittest.TestCase):
+ newenum = sys.pyside63_option_python_enum
+
def testToItn(self):
om = QIODevice.NotOpen
+ omcmp = om.value if self.newenum else om
self.assertEqual(om, QIODevice.NotOpen)
- self.assertTrue(om == 0)
+ self.assertTrue(omcmp == 0)
- self.assertTrue(om != QIODevice.ReadOnly)
- self.assertTrue(om != 1)
+ self.assertTrue(omcmp != QIODevice.ReadOnly)
+ self.assertTrue(omcmp != 1)
def testToIntInFunction(self):
om = QIODevice.WriteOnly
- self.assertEqual(int(om), 2)
+ self.assertEqual(int(om.value if self.newenum else om), 2)
def testNonExtensibleEnums(self):
try:
diff --git a/sources/pyside6/tests/QtCore/qflags_test.py b/sources/pyside6/tests/QtCore/qflags_test.py
index 3800a003c..77e61560f 100644
--- a/sources/pyside6/tests/QtCore/qflags_test.py
+++ b/sources/pyside6/tests/QtCore/qflags_test.py
@@ -111,6 +111,25 @@ class QFlagOperatorTest(unittest.TestCase):
flags = Qt.NoItemFlags | Qt.ItemIsUserCheckable
self.assertEqual(flags | Qt.ItemIsEnabled, Qt.ItemIsEnabled | flags)
+ def testEqualNonNumericalObject(self):
+ '''QFlags ==,!= non-numerical object '''
+ flags = Qt.NoItemFlags | Qt.ItemIsUserCheckable
+
+ self.assertTrue(flags != None) # noqa: E711
+ self.assertFalse(flags == None) # noqa: E711
+
+ self.assertTrue(flags != "tomato")
+ self.assertFalse(flags == "tomato")
+
+ with self.assertRaises(TypeError):
+ flags > None
+ with self.assertRaises(TypeError):
+ flags >= None
+ with self.assertRaises(TypeError):
+ flags < None
+ with self.assertRaises(TypeError):
+ flags <= None
+
class QFlagsOnQVariant(unittest.TestCase):
def testQFlagsOnQVariant(self):
@@ -120,6 +139,7 @@ class QFlagsOnQVariant(unittest.TestCase):
class QFlagsWrongType(unittest.TestCase):
+ @unittest.skipIf(sys.pyside63_option_python_enum, "Qt.ItemFlag is no longer an IntEnum")
def testWrongType(self):
'''Wrong type passed to QFlags binary operators'''
for op in operator.or_, operator.and_, operator.xor:
diff --git a/sources/pyside6/tests/QtCore/qsysinfo_test.py b/sources/pyside6/tests/QtCore/qsysinfo_test.py
index ebd0f82ee..b55d4380c 100644
--- a/sources/pyside6/tests/QtCore/qsysinfo_test.py
+++ b/sources/pyside6/tests/QtCore/qsysinfo_test.py
@@ -39,13 +39,15 @@ from PySide6.QtCore import QSysInfo
class TestQSysInfo(unittest.TestCase):
+ newenum = sys.pyside63_option_python_enum
+
def testEnumEndian(self):
- self.assertEqual(QSysInfo.BigEndian, 0)
- self.assertEqual(QSysInfo.LittleEndian, 1)
- self.assertTrue(QSysInfo.ByteOrder > -1)
+ self.assertEqual(QSysInfo.BigEndian.value if self.newenum else QSysInfo.BigEndian, 0)
+ self.assertEqual(QSysInfo.LittleEndian.value if self.newenum else QSysInfo.LittleEndian, 1)
+ self.assertTrue((QSysInfo.ByteOrder.value if self.newenum else QSysInfo.ByteOrder) > -1)
def testEnumSizes(self):
- self.assertTrue(QSysInfo.WordSize > 0)
+ self.assertTrue((QSysInfo.WordSize.value if self.newenum else QSysInfo.WordSize) > 0)
if __name__ == '__main__':
diff --git a/sources/pyside6/tests/QtGui/bug_617.py b/sources/pyside6/tests/QtGui/bug_617.py
index 36ad2b8ed..b8e578d1b 100644
--- a/sources/pyside6/tests/QtGui/bug_617.py
+++ b/sources/pyside6/tests/QtGui/bug_617.py
@@ -41,12 +41,7 @@ from PySide6.QtGui import QColor
class MyEvent(QEvent):
def __init__(self):
- if sys.pyside63_option_python_enum:
- # PYSIDE-1735: Python Enum: We cannot assign arbitrary numbers.
- # They must exist as constants in the type.
- QEvent.__init__(self, QEvent.Type(1000))
- else:
- QEvent.__init__(self, QEvent.Type(999))
+ QEvent.__init__(self, QEvent.Type(999))
class Bug617(unittest.TestCase):
@@ -57,7 +52,7 @@ class Bug617(unittest.TestCase):
def testOutOfBounds(self):
e = MyEvent()
- self.assertEqual(repr(e.type()), "<Type.User: 1000>"
+ self.assertEqual(repr(e.type()), "<Type.999: 999>"
if sys.pyside63_option_python_enum else "PySide6.QtCore.QEvent.Type(999)")
diff --git a/sources/pyside6/tests/QtGui/qkeysequence_test.py b/sources/pyside6/tests/QtGui/qkeysequence_test.py
index 4ec261a9f..112c22b9a 100644
--- a/sources/pyside6/tests/QtGui/qkeysequence_test.py
+++ b/sources/pyside6/tests/QtGui/qkeysequence_test.py
@@ -45,11 +45,20 @@ class QKeySequenceTest(UsesQGuiApplication):
def testGetItemOperator(self):
# bug #774
- ks = QKeySequence(Qt.SHIFT, Qt.CTRL, Qt.Key_P, Qt.Key_R)
- self.assertEqual(ks[0], Qt.SHIFT)
- self.assertEqual(ks[1], Qt.CTRL)
- self.assertEqual(ks[2], Qt.Key_P)
- self.assertEqual(ks[3], Qt.Key_R)
+ if sys.pyside63_option_python_enum:
+ # PYSIDE-1735: Remapped from Qt.Modifier to Qt.KeyboardModifier
+ # Note that Qt.(Keyboard)?Modifier will be no longer IntFlag.
+ ks = QKeySequence(Qt.ShiftModifier, Qt.ControlModifier, Qt.Key_P, Qt.Key_R)
+ self.assertEqual(ks[0].keyboardModifiers(), Qt.ShiftModifier)
+ self.assertEqual(ks[1].keyboardModifiers(), Qt.ControlModifier)
+ self.assertEqual(ks[2].key(), Qt.Key_P)
+ self.assertEqual(ks[3].key(), Qt.Key_R)
+ else:
+ ks = QKeySequence(Qt.SHIFT, Qt.CTRL, Qt.Key_P, Qt.Key_R)
+ self.assertEqual(ks[0], Qt.SHIFT)
+ self.assertEqual(ks[1], Qt.CTRL)
+ self.assertEqual(ks[2], Qt.Key_P)
+ self.assertEqual(ks[3], Qt.Key_R)
if __name__ == '__main__':
diff --git a/sources/pyside6/tests/QtGui/qpen_test.py b/sources/pyside6/tests/QtGui/qpen_test.py
index a1148b4fa..3c1ae9f6b 100644
--- a/sources/pyside6/tests/QtGui/qpen_test.py
+++ b/sources/pyside6/tests/QtGui/qpen_test.py
@@ -51,7 +51,8 @@ class Painting(QRasterWindow):
with QPainter(self) as painter:
painter.setPen(Qt.NoPen)
self.penFromEnum = painter.pen()
- painter.setPen(int(Qt.NoPen))
+ intVal = Qt.NoPen.value if sys.pyside63_option_python_enum else int(Qt.NoPen)
+ painter.setPen(intVal)
self.penFromInteger = painter.pen()
QTimer.singleShot(20, self.close)
diff --git a/sources/pyside6/tests/QtSql/qvarianttype_test.py b/sources/pyside6/tests/QtSql/qvarianttype_test.py
index 2b3dfa4b0..c62c7a55f 100644
--- a/sources/pyside6/tests/QtSql/qvarianttype_test.py
+++ b/sources/pyside6/tests/QtSql/qvarianttype_test.py
@@ -42,11 +42,14 @@ from PySide6.QtSql import QSqlField
class QVariantTypeTest(unittest.TestCase):
def testQVariantType(self):
+ new_enum = sys.pyside63_option_python_enum
+ cmp_id = QMetaType.QString.value if new_enum else QMetaType.QString
+
f = QSqlField("name", QMetaType(QMetaType.QString))
- self.assertEqual(f.metaType().id(), QMetaType.QString)
+ self.assertEqual(f.metaType().id(), cmp_id)
f = QSqlField("name", QMetaType.fromName(b"QString"))
- self.assertEqual(f.metaType().id(), QMetaType.QString)
+ self.assertEqual(f.metaType().id(), cmp_id)
f = QSqlField("name", QMetaType.fromName(b"double"))
self.assertEqual(f.metaType(), float)
diff --git a/sources/pyside6/tests/QtWidgets/qformlayout_test.py b/sources/pyside6/tests/QtWidgets/qformlayout_test.py
index 55348daaa..7cd59b63f 100644
--- a/sources/pyside6/tests/QtWidgets/qformlayout_test.py
+++ b/sources/pyside6/tests/QtWidgets/qformlayout_test.py
@@ -35,7 +35,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
from init_paths import init_test_paths
init_test_paths(False)
-from PySide6.QtWidgets import QFormLayout, QWidget
+from PySide6.QtWidgets import QFormLayout, QWidget, QLabel, QMainWindow
from helper.usesqapplication import UsesQApplication
@@ -44,12 +44,11 @@ class QFormLayoutTest(UsesQApplication):
def testGetItemPosition(self):
formlayout = QFormLayout()
- if not sys.pyside63_option_python_enum:
- # PYSIDE-1735: This gives random values if no row exists.
- row, role = formlayout.getItemPosition(0)
- self.assertTrue(isinstance(row, int))
- self.assertTrue(isinstance(role, QFormLayout.ItemRole))
- self.assertEqual(row, -1)
+
+ row, role = formlayout.getItemPosition(0)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, -1)
widget = QWidget()
formlayout.addRow(widget)
@@ -62,12 +61,11 @@ class QFormLayoutTest(UsesQApplication):
def testGetWidgetPosition(self):
formlayout = QFormLayout()
widget = QWidget()
- if not sys.pyside63_option_python_enum:
- # PYSIDE-1735: This gives random values if no row exists.
- row, role = formlayout.getWidgetPosition(widget)
- self.assertTrue(isinstance(row, int))
- self.assertTrue(isinstance(role, QFormLayout.ItemRole))
- self.assertEqual(row, -1)
+
+ row, role = formlayout.getWidgetPosition(widget)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, -1)
formlayout.addRow(widget)
row, role = formlayout.getWidgetPosition(widget)
@@ -79,12 +77,11 @@ class QFormLayoutTest(UsesQApplication):
def testGetLayoutPosition(self):
formlayout = QFormLayout()
layout = QFormLayout()
- if not sys.pyside63_option_python_enum:
- # PYSIDE-1735: This gives random values if no row exists.
- row, role = formlayout.getLayoutPosition(layout)
- self.assertTrue(isinstance(row, int))
- self.assertTrue(isinstance(role, QFormLayout.ItemRole))
- self.assertEqual(row, -1)
+
+ row, role = formlayout.getLayoutPosition(layout)
+ self.assertTrue(isinstance(row, int))
+ self.assertTrue(isinstance(role, QFormLayout.ItemRole))
+ self.assertEqual(row, -1)
formlayout.addRow(layout)
row, role = formlayout.getLayoutPosition(layout)
@@ -93,7 +90,35 @@ class QFormLayoutTest(UsesQApplication):
self.assertEqual(row, 0)
self.assertEqual(role, QFormLayout.SpanningRole)
+ def testTakeRow(self):
+ window = QMainWindow()
+ window.setCentralWidget(QWidget())
+ formlayout = QFormLayout(window.centralWidget())
+
+ widget_label = "blub"
+ widget = QLabel(widget_label)
+
+ self.assertEqual(formlayout.count(), 0)
+ formlayout.addRow(widget)
+ self.assertEqual(formlayout.count(), 1)
+ self.assertEqual(formlayout.itemAt(0).widget(), widget)
+
+ widget_id = id(widget)
+
+ # Now there are no more references to the original widget on the
+ # Python side. Assert that this does not break the references to
+ # the widget on the C++ side so that "taking" the row will work.
+ del widget
+
+ takeRowResult = formlayout.takeRow(0)
+ self.assertEqual(formlayout.count(), 0)
+
+ widget = takeRowResult.fieldItem.widget()
+
+ self.assertIsNotNone(widget)
+ self.assertEqual(widget_id, id(widget))
+ self.assertEqual(widget.text(), widget_label)
+
if __name__ == "__main__":
unittest.main()
-
diff --git a/sources/pyside6/tests/pysidetest/CMakeLists.txt b/sources/pyside6/tests/pysidetest/CMakeLists.txt
index ee2a295fe..f7df67751 100644
--- a/sources/pyside6/tests/pysidetest/CMakeLists.txt
+++ b/sources/pyside6/tests/pysidetest/CMakeLists.txt
@@ -157,3 +157,4 @@ PYSIDE_TEST(signalwithdefaultvalue_test.py)
PYSIDE_TEST(typedef_signal_test.py)
PYSIDE_TEST(version_test.py)
PYSIDE_TEST(mock_as_slot_test.py)
+PYSIDE_TEST(pyenum_relax_options_test.py)
diff --git a/sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py b/sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py
new file mode 100644
index 000000000..844fc2bce
--- /dev/null
+++ b/sources/pyside6/tests/pysidetest/pyenum_relax_options_test.py
@@ -0,0 +1,166 @@
+#!/usr/bin/python
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $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-1735: Testing different relax options for Enums
+
+This test uses different configurations and initializes QtCore with it.
+Because re-initialization is not possible, the test uses a subprocess
+for it. This makes the test pretty slow.
+
+Maybe we should implement a way to re-initialize QtCore enums without
+using subprocess, just to speed this up??
+"""
+
+import os
+import sys
+import unittest
+
+from pathlib import Path
+sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
+from init_paths import init_test_paths
+init_test_paths(False)
+
+import subprocess
+import tempfile
+from textwrap import dedent
+
+
+def runtest(program):
+ passed_path = os.fspath(Path(__file__).resolve().parents[1])
+ with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix=".py") as fp:
+ preamble = dedent(f"""
+ import os
+ import sys
+ from pathlib import Path
+ sys.path.append({passed_path!r})
+ from init_paths import init_test_paths
+ init_test_paths(False)
+ """)
+ print(preamble, program, file=fp)
+ fp.close()
+ try:
+ subprocess.run([sys.executable, fp.name], check=True, capture_output=True)
+ return True
+ except subprocess.CalledProcessError as e:
+ print(f"\ninfo: {e.__class__.__name__}: {e.stderr}")
+ return False
+ finally:
+ os.unlink(fp.name)
+
+def testprog2(option):
+ return runtest(dedent(f"""
+ sys.pyside63_option_python_enum = {option}
+ from PySide6 import QtCore
+ from enum import IntEnum
+ assert(issubclass(QtCore.Qt.DateFormat, IntEnum))
+ """))
+
+def testprog4(option):
+ return runtest(dedent(f"""
+ sys.pyside63_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.QtDebugMsg
+ """))
+
+def testprog8_16(option):
+ # this test needs flag 16, or the effect would be hidden by forgiving mode
+ return runtest(dedent(f"""
+ sys.pyside63_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.AlignTop
+ """))
+
+def testprog32(option):
+ return runtest(dedent(f"""
+ sys.pyside63_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.Alignment
+ """))
+
+def testprog64(option):
+ return runtest(dedent(f"""
+ sys.pyside63_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.AlignmentFlag()
+ """))
+
+def testprog128(option):
+ return runtest(dedent(f"""
+ sys.pyside63_option_python_enum = {option}
+ from PySide6 import QtCore
+ QtCore.Qt.Key(1234567)
+ """))
+
+
+class TestPyEnumRelaxOption(unittest.TestCase):
+ """
+ This test is a bit involved, because we cannot unload QtCore after it is loaded once.
+ We use subprocess to test different cases, anyway.
+ """
+
+ def test_enumIsIntEnum(self):
+ self.assertTrue(testprog2(2))
+ self.assertFalse(testprog2(4))
+
+ def test_globalDefault(self):
+ self.assertTrue(testprog4(4))
+ self.assertFalse(testprog4(1))
+ self.assertTrue(testprog4(12))
+
+ def test_localDefault(self):
+ self.assertTrue(testprog8_16(8+16))
+ self.assertFalse(testprog8_16(0+16))
+
+ def test_fakeRenames(self):
+ self.assertTrue(testprog32(1))
+ self.assertFalse(testprog32(32))
+
+ def test_zeroDefault(self):
+ self.assertTrue(testprog64(1))
+ self.assertFalse(testprog64(64))
+
+ def test_Missing(self):
+ self.assertTrue(testprog128(1))
+ self.assertFalse(testprog128(128))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/qvariant_test.py b/sources/pyside6/tests/pysidetest/qvariant_test.py
index 637aa95cf..e6977082e 100644
--- a/sources/pyside6/tests/pysidetest/qvariant_test.py
+++ b/sources/pyside6/tests/pysidetest/qvariant_test.py
@@ -36,8 +36,8 @@ from init_paths import init_test_paths
init_test_paths(True)
from testbinding import TestObject
-from PySide6.QtCore import Qt
-from PySide6.QtGui import QKeySequence
+from PySide6.QtCore import Qt, QKeyCombination
+from PySide6.QtGui import QKeySequence, QAction
from helper.usesqapplication import UsesQApplication
@@ -46,9 +46,20 @@ class QVariantTest(UsesQApplication):
def testQKeySequenceQVariantOperator(self):
# bug #775
- ks = QKeySequence(Qt.SHIFT, Qt.CTRL, Qt.Key_P, Qt.Key_R)
+ ks = QKeySequence(Qt.ShiftModifier, Qt.ControlModifier, Qt.Key_P, Qt.Key_R)
self.assertEqual(TestObject.checkType(ks), 4107)
+ # PYSIDE-1735: Test the new way to address QKeyCombination after moving IntEnum to Enum
+ @unittest.skipUnless(sys.pyside63_option_python_enum, "only implemented for new enums")
+ def testQKeySequenceMoreVariations(self):
+ QAction().setShortcut(Qt.CTRL | Qt.Key_B)
+ QAction().setShortcut(Qt.CTRL | Qt.ALT | Qt.Key_B)
+ QAction().setShortcut(Qt.CTRL | Qt.AltModifier | Qt.Key_B)
+ QAction().setShortcut(QKeySequence(QKeyCombination(Qt.CTRL | Qt.Key_B)))
+ QKeySequence(Qt.CTRL | Qt.Key_Q)
+ # Issues a warning but works as well
+ QKeySequence(Qt.CTRL + Qt.Key_Q)
+
if __name__ == '__main__':
unittest.main()
diff --git a/sources/pyside6/tests/pysidetest/shared_pointer_test.py b/sources/pyside6/tests/pysidetest/shared_pointer_test.py
index e5baa551c..c0b875407 100644
--- a/sources/pyside6/tests/pysidetest/shared_pointer_test.py
+++ b/sources/pyside6/tests/pysidetest/shared_pointer_test.py
@@ -45,6 +45,8 @@ class SharedPointerTests(unittest.TestCase):
p = SharedPointerTestbench.createSharedPointerQObject()
self.assertEqual(p.objectName(), "TestObject")
SharedPointerTestbench.printSharedPointerQObject(p)
+ p = SharedPointerTestbench.createSharedPointerConstQObject()
+ SharedPointerTestbench.printSharedPointerConstQObject(p)
def testIntSharedPointer(self):
p = SharedPointerTestbench.createSharedPointerInt(42)
diff --git a/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp b/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp
index f04059043..46875345b 100644
--- a/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp
+++ b/sources/pyside6/tests/pysidetest/sharedpointertestbench.cpp
@@ -54,3 +54,16 @@ void SharedPointerTestbench::printSharedPointerQObject(const QSharedPointer<QObj
{
qDebug() << __FUNCTION__ << p.data();
}
+
+QSharedPointer<const QObject> SharedPointerTestbench::createSharedPointerConstQObject()
+{
+ auto *o = new QObject;
+ o->setObjectName(u"ConstTestObject"_qs);
+ QSharedPointer<const QObject> result(o);
+ return result;
+}
+
+void SharedPointerTestbench::printSharedPointerConstQObject(const QSharedPointer<const QObject> &p)
+{
+ qDebug() << __FUNCTION__ << p.data();
+}
diff --git a/sources/pyside6/tests/pysidetest/sharedpointertestbench.h b/sources/pyside6/tests/pysidetest/sharedpointertestbench.h
index 1732a59e5..7abbf6d29 100644
--- a/sources/pyside6/tests/pysidetest/sharedpointertestbench.h
+++ b/sources/pyside6/tests/pysidetest/sharedpointertestbench.h
@@ -45,6 +45,10 @@ public:
static QSharedPointer<QObject> createSharedPointerQObject();
static void printSharedPointerQObject(const QSharedPointer<QObject> &p);
+
+ static QSharedPointer<const QObject> createSharedPointerConstQObject();
+ static void printSharedPointerConstQObject(const QSharedPointer<const QObject> &p);
+
};
#endif // SHAREDPOINTERTESTBENCH_H
diff --git a/sources/pyside6/tests/registry/existence_test.py b/sources/pyside6/tests/registry/existence_test.py
index 2ab18152a..fa6cdde34 100644
--- a/sources/pyside6/tests/registry/existence_test.py
+++ b/sources/pyside6/tests/registry/existence_test.py
@@ -72,8 +72,8 @@ import unittest
from pathlib import Path
sys.path.append(os.fspath(Path(__file__).resolve().parents[1]))
-from init_paths import init_all_test_paths
-init_all_test_paths()
+from init_paths import init_test_paths
+init_test_paths(True)
from init_platform import enum_all, generate_all
from util import (isolate_warnings, check_warnings, suppress_warnings, warn,
@@ -119,6 +119,19 @@ if have_refmodule and not hasattr(sig_exists, dict_name):
have_refmodule = False
+class TestUnrecognizedOffending(unittest.TestCase):
+ """
+ We run the signature generation on all modules and raise an error
+ if a warning was issued. This is better than turning warnings into
+ errors because that would stop early before we have all warnings.
+ """
+ def test_signatures_recognized(self):
+ with isolate_warnings():
+ found_sigs = enum_all()
+ if check_warnings():
+ raise RuntimeError("There are errors, see above.")
+
+
@unittest.skipIf(not have_refmodule,
"not activated for this platform or version")
class TestSignaturesExists(unittest.TestCase):
diff --git a/sources/pyside6/tests/registry/init_platform.py b/sources/pyside6/tests/registry/init_platform.py
index 06c488ee3..e22d2c9b8 100644
--- a/sources/pyside6/tests/registry/init_platform.py
+++ b/sources/pyside6/tests/registry/init_platform.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2019 The Qt Company Ltd.
+## Copyright (C) 2022 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -113,13 +113,7 @@ def set_ospaths(build_dir):
ps = os.pathsep
ospath_var = "PATH" if sys.platform == "win32" else "LD_LIBRARY_PATH"
old_val = os.environ.get(ospath_var, "")
- lib_path = [os.path.join(build_dir, "pyside6", "libpyside"),
- os.path.join(build_dir, "pyside6", "tests", "pysidetest"),
- os.path.join(build_dir, "shiboken6", "tests", "libminimal"),
- os.path.join(build_dir, "shiboken6", "tests", "libsample"),
- os.path.join(build_dir, "shiboken6", "tests", "libother"),
- os.path.join(build_dir, "shiboken6", "tests", "libsmart"),
- os.path.join(build_dir, "shiboken6", "libshiboken")]
+ lib_path = [os.path.join(build_dir, "pyside6", "tests", "pysidetest"),]
ospath = ps.join(lib_path + old_val.split(ps))
os.environ[ospath_var] = ospath
@@ -139,12 +133,6 @@ all_modules.append("testbinding")
from shiboken6 import Shiboken
all_modules.append("shiboken6.Shiboken")
-# 'sample/smart' are needed by 'other', so import them first.
-for modname in "minimal sample smart other".split():
- sys.path.insert(0, os.path.join(shiboken_build_dir, "tests", modname + "binding"))
- __import__(modname)
- all_modules.append(modname)
-
from shibokensupport.signature.lib.enum_sig import SimplifyingEnumerator
# Make sure not to get .pyc in Python2.
@@ -208,6 +196,48 @@ def enum_all():
return ret
+LICENSE_TEXT = """
+#############################################################################
+##
+## Copyright (C) 2022 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $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$
+##
+#############################################################################
+"""
+
+
def generate_all():
refPath = get_refpath()
module = os.path.basename(os.path.splitext(refPath)[0])
@@ -218,7 +248,7 @@ def generate_all():
license_line = next((lno for lno, line in enumerate(lines)
if "$QT_END_LICENSE$" in line))
fmt.print("#recreate # uncomment this to enforce generation")
- fmt.print("".join(lines[:license_line + 3]))
+ fmt.print(LICENSE_TEXT)
version = sys.version.replace('\n', ' ')
build = qt_build()
fmt.print(dedent(f'''\
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 995e1f316..89ab145ab 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -3116,8 +3116,7 @@ void AbstractMetaBuilderPrivate::inheritTemplateFunctions(AbstractMetaClass *sub
for (const AbstractMetaField &field : templateClassFields) {
// If the field is modified or the instantiation has a field named
// the same as an existing field we have shadowing, so we need to skip it.
- if (field.isModifiedRemoved(TypeSystem::All)
- || field.isStatic()
+ if (field.isModifiedRemoved() || field.isStatic()
|| AbstractMetaField::find(existingSubclassFields, field.name()).has_value()) {
continue;
}
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp
index 0d2761ac8..a8117b99b 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafield.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetafield.cpp
@@ -80,7 +80,7 @@ std::optional<AbstractMetaField>
/*******************************************************************************
* Indicates that this field has a modification that removes it
*/
-bool AbstractMetaField::isModifiedRemoved(int types) const
+bool AbstractMetaField::isModifiedRemoved() const
{
const FieldModificationList &mods = modifications();
for (const FieldModification &mod : mods) {
diff --git a/sources/shiboken6/ApiExtractor/abstractmetafield.h b/sources/shiboken6/ApiExtractor/abstractmetafield.h
index e36f4c30e..d4b930607 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetafield.h
+++ b/sources/shiboken6/ApiExtractor/abstractmetafield.h
@@ -56,7 +56,7 @@ public:
FieldModificationList modifications() const;
- bool isModifiedRemoved(int types = TypeSystem::All) const;
+ bool isModifiedRemoved() const;
bool generateOpaqueContainer() const;
const AbstractMetaType &type() const;
diff --git a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
index d47b25ef2..b5fa4100c 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetatype.cpp
@@ -668,16 +668,8 @@ QString AbstractMetaTypeData::formatPythonSignature() const
result += TypeInfo::indirectionKeyword(i);
// If it is a flags type, we replace it with the full name:
// "PySide6.QtCore.Qt.ItemFlags" instead of "PySide6.QtCore.QFlags<Qt.ItemFlag>"
- if (m_typeEntry->isFlags()) {
- // PYSIDE-1735: We need to provide both the flags type and the original enum type
- // as a choice at runtime.
- auto flagsTypeEntry = static_cast<const FlagsTypeEntry *>(m_typeEntry);
- auto enumTypeEntry = flagsTypeEntry->originator();
- result = m_typeEntry->targetLangPackage() + u".^^"_s
- + flagsTypeEntry->targetLangName() + u"^^"_s
- + enumTypeEntry->targetLangName() + u"^^"_s;
- }
-
+ if (m_typeEntry->isFlags())
+ result = m_typeEntry->qualifiedTargetLangName();
result.replace(u"::"_s, u"."_s);
return result;
}
diff --git a/sources/shiboken6/ApiExtractor/apiextractor.cpp b/sources/shiboken6/ApiExtractor/apiextractor.cpp
index d45f2c543..944fe4e13 100644
--- a/sources/shiboken6/ApiExtractor/apiextractor.cpp
+++ b/sources/shiboken6/ApiExtractor/apiextractor.cpp
@@ -483,7 +483,7 @@ void ApiExtractorPrivate::addInstantiatedSmartPointer(InstantiationCollectContex
const AbstractMetaType &type)
{
InstantiatedSmartPointer smp;
- smp.type = simplifiedType(type);
+ smp.type = canonicalSmartPtrInstantiation(type);
smp.smartPointer = AbstractMetaClass::findClass(m_builder->smartPointers(),
type.typeEntry());
Q_ASSERT(smp.smartPointer);
diff --git a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
index 44f3e97c4..9cc9f28a9 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/clangbuilder.cpp
@@ -676,8 +676,11 @@ QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &c
if (equalSign == std::string::npos)
return QString();
++equalSign;
- return QString::fromLocal8Bit(snippet.data() + equalSign,
- qsizetype(snippet.size() - equalSign)).trimmed();
+ QString result = QString::fromLocal8Bit(snippet.data() + equalSign,
+ qsizetype(snippet.size() - equalSign));
+ // Fix a default expression as read from code. Simplify white space
+ result.remove(u'\r');
+ return result.contains(u'"') ? result.trimmed() : result.simplified();
}
// Resolve a type (loop over aliases/typedefs), for example for base classes
@@ -846,10 +849,10 @@ bool BuilderPrivate::visitHeader(const QString &fileName) const
case Platform::macOS:
// Parse the following system headers to get the correct typdefs for types like
// int32_t, which are used in the macOS implementation of OpenGL framework.
+ // They are installed under /Applications/Xcode.app/Contents/Developer/Platforms...
if (baseName == u"gltypes.h"
- || fileName.startsWith(u"/usr/include/_types")
- || fileName.startsWith(u"/usr/include/_types")
- || fileName.startsWith(u"/usr/include/sys/_types")) {
+ || fileName.contains(u"/usr/include/_types")
+ || fileName.contains(u"/usr/include/sys/_types")) {
return true;
}
break;
diff --git a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
index 1c6b39228..c5f67a337 100644
--- a/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
+++ b/sources/shiboken6/ApiExtractor/clangparser/compilersupport.cpp
@@ -284,8 +284,8 @@ static QString compilerFromCMake(const QString &defaultCompiler)
{
// Added !defined(Q_OS_DARWIN) due to PYSIDE-1032
QString result = defaultCompiler;
- if (platform() != Platform::macOS)
#ifdef CMAKE_CXX_COMPILER
+ if (platform() != Platform::macOS)
result = QString::fromLocal8Bit(CMAKE_CXX_COMPILER);
#endif
return result;
diff --git a/sources/shiboken6/ApiExtractor/predefined_templates.cpp b/sources/shiboken6/ApiExtractor/predefined_templates.cpp
index 96610844c..494e4076b 100644
--- a/sources/shiboken6/ApiExtractor/predefined_templates.cpp
+++ b/sources/shiboken6/ApiExtractor/predefined_templates.cpp
@@ -35,7 +35,7 @@ using namespace Qt::StringLiterals;
static QString pySequenceToCppContainer(const QString &insertFunc,
bool reserve)
{
- QString result;
+ QString result = u"(%out).clear();\n"_s;
if (reserve) {
result += uR"(if (PyList_Check(%in)) {
const Py_ssize_t size = PySequence_Size(%in);
@@ -93,6 +93,7 @@ static QString pyDictToCppMap(bool isQMap)
{
return uR"(PyObject *key;
PyObject *value;
+%out.clear();
Py_ssize_t pos = 0;
while (PyDict_Next(%in, &pos, &key, &value)) {
%OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
@@ -159,6 +160,7 @@ static QString pyDictToCppMultiHash(bool isQMultiHash)
{
return uR"(PyObject *key;
PyObject *values;
+ %out.clear();
Py_ssize_t pos = 0;
while (PyDict_Next(%in, &pos, &key, &values)) {
%OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
diff --git a/sources/shiboken6/ApiExtractor/typeparser.cpp b/sources/shiboken6/ApiExtractor/typeparser.cpp
index 1b2e770c8..91e4b41eb 100644
--- a/sources/shiboken6/ApiExtractor/typeparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typeparser.cpp
@@ -304,7 +304,7 @@ TypeInfo TypeParser::parse(const QString &str, QString *errorMessage)
break;
}
- tok = scanner.nextToken();
+ tok = scanner.nextToken(errorMessage);
}
if (stack.isEmpty() || stack.constFirst().qualifiedName().isEmpty()) {
diff --git a/sources/shiboken6/ApiExtractor/typesystem_enums.h b/sources/shiboken6/ApiExtractor/typesystem_enums.h
index fba411c2c..0148d1eba 100644
--- a/sources/shiboken6/ApiExtractor/typesystem_enums.h
+++ b/sources/shiboken6/ApiExtractor/typesystem_enums.h
@@ -109,7 +109,9 @@ enum class CPythonType
enum class PythonEnumType {
Unspecified,
+ Enum,
IntEnum,
+ Flag,
IntFlag
};
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index ae929d035..33d40432f 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -261,8 +261,10 @@ ENUM_LOOKUP_LINEAR_SEARCH()
ENUM_LOOKUP_BEGIN(TypeSystem::PythonEnumType, Qt::CaseSensitive,
pythonEnumTypeFromAttribute)
{
+ {u"Enum", TypeSystem::PythonEnumType::Enum},
{u"IntEnum", TypeSystem::PythonEnumType::IntEnum},
- {u"IntFlag", TypeSystem::PythonEnumType::IntFlag}
+ {u"Flag", TypeSystem::PythonEnumType::Flag},
+ {u"IntFlag", TypeSystem::PythonEnumType::IntFlag},
};
ENUM_LOOKUP_LINEAR_SEARCH()
diff --git a/sources/shiboken6/cmake/ShibokenSetup.cmake b/sources/shiboken6/cmake/ShibokenSetup.cmake
index 76bf86a10..c9b022e1e 100644
--- a/sources/shiboken6/cmake/ShibokenSetup.cmake
+++ b/sources/shiboken6/cmake/ShibokenSetup.cmake
@@ -183,7 +183,6 @@ set(shiboken_python_files
"signature/parser.py"
"__init__.py"
"feature.py"
- "enum_310.py"
)
# uninstall target
diff --git a/sources/shiboken6/data/shiboken6.pc.in b/sources/shiboken6/data/shiboken6.pc.in
index d05fe8991..3ba422627 100644
--- a/sources/shiboken6/data/shiboken6.pc.in
+++ b/sources/shiboken6/data/shiboken6.pc.in
@@ -1,6 +1,6 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
-libdir=@LIB_INSTALL_DIR@
+libdir=@CMAKE_INSTALL_PREFIX@/@LIB_INSTALL_DIR@
includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken6
python_interpreter=@PYTHON_EXECUTABLE@
python_include_dir=@PYTHON_INCLUDE_DIRS@
diff --git a/sources/shiboken6/doc/CMakeLists.txt b/sources/shiboken6/doc/CMakeLists.txt
index 4cd459c23..0f909b3c5 100644
--- a/sources/shiboken6/doc/CMakeLists.txt
+++ b/sources/shiboken6/doc/CMakeLists.txt
@@ -18,7 +18,7 @@ if(SPHINX_BUILD)
# conditional tag for sphinx build
#string(JOIN "_" SPHINX_TAG ${DOC_OUTPUT_FORMAT} "format")
add_custom_target(doc
- COMMAND ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} -c . ${CMAKE_CURRENT_SOURCE_DIR} html
+ COMMAND ${SPHINX_BUILD} -b ${DOC_OUTPUT_FORMAT} -j auto -c . ${CMAKE_CURRENT_SOURCE_DIR} html
COMMENT "Generating shiboken documentation HTML files"
VERBATIM)
@@ -41,7 +41,7 @@ if(SPHINX_BUILD)
endif()
add_custom_command(TARGET doc POST_BUILD
- COMMAND "${python_executable}" ${PATCH_QHP_SCRIPT} -f ${QHP_FILE} -v shiboken6
+ COMMAND "${python_executable}" ${PATCH_QHP_SCRIPT} -v shiboken6 ${QHP_FILE}
COMMAND "${qhelpgenerator_binary}" ${QHP_FILE}
COMMENT "Generating shiboken documentation QCH files based on the QHP files"
VERBATIM)
diff --git a/sources/shiboken6/doc/scripts/patch_qhp.py b/sources/shiboken6/doc/scripts/patch_qhp.py
index a9f858889..586c8d1fe 100644
--- a/sources/shiboken6/doc/scripts/patch_qhp.py
+++ b/sources/shiboken6/doc/scripts/patch_qhp.py
@@ -39,31 +39,60 @@
import fileinput
import re
+import sys
from argparse import ArgumentParser, RawTextHelpFormatter
-options = ArgumentParser(description='Qhp file updater',
- formatter_class=RawTextHelpFormatter)
-options.add_argument('-f',
- '--filename',
- type=str,
- help='Qhp filename with the relative path.',
- required=True)
-options.add_argument('-v',
- '--vfolder',
- type=str,
- help='String to be injected into the Qhp file.')
-args=options.parse_args()
-try:
- for line in fileinput.input(args.filename,inplace=True,backup='.bak'):
- line_copy=line.strip()
- if not line_copy: # check for empty line
- continue
- match=re.match('(^.*virtualFolder.)doc(.*$)',line)
+DESC="""Qhp file updater
+
+Replaces virtual folder ids in .qhp files preparing for
+registering the documentation in Qt Assistant."""
+
+
+VIRTUAL_FOLDER_PATTERN = re.compile("(^.*virtualFolder.)doc(.*$)")
+# Strip "PySide6.QtModule." from index entries
+INDEX_CLASS_PATTERN = re.compile(r'^(\s*<keyword name=")PySide6\.[^.]+\.(.*\(class in .*)$')
+INDEX_METHOD_PATTERN = re.compile(r'^(\s+<keyword name=".* \()PySide6\.[^.]+\.(.*>)$')
+
+
+virtual_folder = ""
+strip_pyside_module = False
+
+
+def process_line(line):
+ global virtual_folder
+ match = VIRTUAL_FOLDER_PATTERN.match(line)
+ if match:
+ print(f"{match.group(1)}{virtual_folder}{match.group(2)}")
+ return
+ if strip_pyside_module:
+ match = INDEX_METHOD_PATTERN.match(line)
+ if match:
+ print(f"{match.group(1)}{match.group(2)}")
+ return
+ match = INDEX_CLASS_PATTERN.match(line)
if match:
- repl=''.join([match.group(1), args.vfolder, match.group(2)])
- print(line.replace(match.group(0),repl),end=' ')
- else:
- print(line.rstrip())
-except:
- pass
+ print(f"{match.group(1)}{match.group(2)}")
+ return
+ sys.stdout.write(line)
+
+
+if __name__ == '__main__':
+ arg_parser = ArgumentParser(description=DESC,
+ formatter_class=RawTextHelpFormatter)
+ arg_parser.add_argument('-v', '--vfolder', type=str,
+ help='String to be injected into the Qhp file.')
+ arg_parser.add_argument("--pyside", "-p", action="store_true",
+ help="Strip the PySide module path off the index entries.")
+ arg_parser.add_argument("file", type=str, help='Qhp filename.')
+ options = arg_parser.parse_args()
+ virtual_folder = options.vfolder
+ strip_pyside_module = options.pyside
+
+ try:
+ with fileinput.input(options.file, inplace=True,
+ backup=".bak") as fh:
+ for line in fh:
+ process_line(line)
+ except Exception as e:
+ print(f"WARNING: patch_qhp.py failed: {e}", file=sys.stderr)
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index 6dda54786..867a4dd8d 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -108,14 +108,17 @@ rejection
<typesystem>
<rejection class="..."
function-name="..."
+ argument-type="..."
field-name="..." />
</typesystem>
- The **class** attribute is the C++ class name of the class to reject. Use the
- *optional* **function-name** or **field-name** attributes to reject a particular
- function or field. Note that the **field-name** and **function-name** cannot
- be specified at the same time. To remove all occurrences of a given field or
- function, set the class attribute to \*.
+ The **class** attribute is the C++ class name of the class to reject. Use
+ the *optional* **function-name**, **argument-type**, or **field-name**
+ attributes to reject a particular function, function with arguments of a
+ particular type, or a field. Note that the **field-name** and
+ **function-name**/**argument-type** cannot be specified at the same time.
+ To remove all occurrences of a given field or function, set the class
+ attribute to \*.
.. _primitive-type:
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index 25d16615a..5198ff34e 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -388,15 +388,104 @@ static QString _plainName(const QString &s)
return cutPos < 0 ? s : s.right(s.length() - (cutPos + 2));
}
-static QString BuildEnumFlagInfo(const EnumTypeEntry *enumType)
+/**********************************************************************
+ *
+ * Decision whether to use an IntEnum/IntFlag
+ * ------------------------------------------
+ *
+ * Unfortunately, all attempts to drive this decision automagically
+ * did not work out. We therefore compile a list in with known
+ * IntEnum and IntFlag.
+ */
+
+/*
+ * This function is now unused and replaced by TypeSystem::PythonEnumType
+ */
+#if 0
+static QSet<QString> useIntSet()
+{
+ static const QSet<QString> result{
+ /* IntEnum */ u"PySide6.QtCore.QDataStream.Version"_s,
+ /* IntEnum */ u"PySide6.QtCore.QEvent.Type"_s,
+ /* IntEnum */ u"PySide6.QtCore.QLocale.FloatingPointPrecisionOption"_s,
+ /* IntFlag */ u"PySide6.QtCore.QLocale.LanguageCodeType"_s,
+ /* IntFlag */ u"PySide6.QtCore.QUrl.ComponentFormattingOption"_s,
+ // note: "QUrl::UrlFormattingOption" is set as IntFlag without flags
+ /* IntFlag */ u"PySide6.QtCore.QUrl.UrlFormattingOption"_s,
+ /* IntFlag */ u"PySide6.QtCore.Qt.AlignmentFlag"_s,
+ /* IntFlag */ u"PySide6.QtCore.Qt.FocusPolicy"_s,
+ /* IntEnum */ u"PySide6.QtCore.Qt.GestureType"_s,
+ /* IntEnum */ u"PySide6.QtCore.Qt.ItemDataRole"_s,
+ /* IntEnum */ u"PySide6.QtCore.Qt.Key"_s,
+ /* Flag */ u"PySide6.QtCore.Qt.Modifier"_s,
+ // note: "Qt::TextFlag" is set as IntFlag without flags
+ /* IntFlag */ u"PySide6.QtCore.Qt.TextFlag"_s,
+ /* IntFlag */ u"PySide6.QtCore.Qt.WindowType"_s,
+ // This is found in QtWidgets but should be in QtGui.
+ /* IntEnum */ u"PySide6.QtGui.QFileSystemModel.Roles"_s,
+ /* IntEnum */ u"PySide6.QtGui.QFont.Stretch"_s,
+ /* IntEnum */ u"PySide6.QtGui.QFont.Weight"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextDocument.ResourceType"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextFormat.FormatType"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextFormat.ObjectTypes"_s,
+ /* IntEnum */ u"PySide6.QtGui.QTextFormat.Property"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QDialog.DialogCode"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QFrame.Shadow"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QFrame.Shape"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QListWidgetItem.ItemType"_s,
+ /* IntFlag */ u"PySide6.QtWidgets.QMessageBox.StandardButton"_s,
+ // note: "QSizePolicy::PolicyFlag" is set as IntFlag without flags
+ /* IntFlag */ u"PySide6.QtWidgets.QSizePolicy.PolicyFlag"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.ComplexControl"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.ContentsType"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.ControlElement"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.PixelMetric"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.PrimitiveElement"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.StandardPixmap"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.StyleHint"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QStyle.SubElement"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QTableWidgetItem.ItemType"_s,
+ /* IntEnum */ u"PySide6.QtWidgets.QTreeWidgetItem.ItemType"_s,
+ /* IntEnum */ u"PySide6.QtCharts.QBoxSet.ValuePositions"_s,
+ /* IntEnum */ u"PySide6.QtMultimedia.QMediaPlayer.Loops"_s,
+ /* IntEnum */ u"PySide6.QtQuick.QSGGeometry.DrawingMode"_s,
+ /* IntEnum */ u"PySide6.QtWebEngineCore.QWebEngineScript.ScriptWorldId"_s,
+ // Added because it should really be used as number
+ /* IntEnum */ u"PySide6.QtCore.QMetaType.Type"_s,
+ /* IntEnum */ u"PySide6.QtSerialPort.QSerialPort.BaudRate"_s,
+ };
+ return result;
+}
+#endif
+
+static bool _shouldInheritInt(const AbstractMetaEnum &cppEnum)
+{
+ if (!cppEnum.fullName().startsWith(u"PySide6."_s))
+ return true;
+ // static auto intSet = useIntSet();
+ // return intSet.contains(cppEnum.fullName());
+ return false;
+}
+
+static QString BuildEnumFlagInfo(const AbstractMetaEnum &cppEnum)
{
+ auto *enumType = cppEnum.typeEntry();
QString result = _plainName(enumType->name());
auto flags = enumType->flags();
- if (flags) {
- result += u":IntFlag:"_s + _plainName(flags->flagsName());
- } else {
- result += u":IntEnum"_s;
- }
+ auto decision = enumType->pythonEnumType();
+ bool _int = _shouldInheritInt(cppEnum);
+ bool _flag = bool(flags);
+
+ if (decision != TypeSystem::PythonEnumType::Unspecified) {
+ _int = decision == TypeSystem::PythonEnumType::IntEnum ||
+ decision == TypeSystem::PythonEnumType::IntFlag;
+ _flag = decision == TypeSystem::PythonEnumType::Flag ||
+ decision == TypeSystem::PythonEnumType::IntFlag;
+ }
+ result += _flag ? (_int ? u":IntFlag"_s : u":Flag"_s)
+ : (_int ? u":IntEnum"_s : u":Enum"_s);
+ if (flags)
+ result += u':' + _plainName(flags->flagsName());
return u'"' + result + u'"';
}
@@ -694,7 +783,7 @@ void CppGenerator::generateClass(TextStream &s, const GeneratorContext &classCon
// PYSIDE-1735: Write an EnumFlagInfo structure
QStringList sorter;
for (const auto &entry : qAsConst(classEnums))
- sorter.append(BuildEnumFlagInfo(entry.typeEntry()));
+ sorter.append(BuildEnumFlagInfo(entry));
sorter.sort();
if (!sorter.empty()) {
s << "static const char *" << className << "_EnumFlagInfo[] = {\n" << indent;
@@ -5965,10 +6054,11 @@ void CppGenerator::writeClassRegister(TextStream &s,
AbstractMetaEnumList classEnums = metaClass->enums();
metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums);
- writeEnumsInitialization(s, classEnums, ErrorReturn::Void);
if (!classContext.forSmartPointer() && !classEnums.isEmpty())
- s << "SbkObjectType_SetEnumFlagInfo(pyType, " << chopType(pyTypeName)
- << "_EnumFlagInfo);\n";
+ s << "// Pass the ..._EnumFlagInfo to the class.\n"
+ << "SbkObjectType_SetEnumFlagInfo(pyType, " << chopType(pyTypeName)
+ << "_EnumFlagInfo);\n\n";
+ writeEnumsInitialization(s, classEnums, ErrorReturn::Void);
if (metaClass->hasSignals())
writeSignalInitialization(s, metaClass);
diff --git a/sources/shiboken6/generator/shiboken/pytypenames.h b/sources/shiboken6/generator/shiboken/pytypenames.h
index caeb6f671..1ca13f1ae 100644
--- a/sources/shiboken6/generator/shiboken/pytypenames.h
+++ b/sources/shiboken6/generator/shiboken/pytypenames.h
@@ -33,7 +33,6 @@
static inline QString pyBoolT() { return QStringLiteral("PyBool"); }
static inline QString pyFloatT() { return QStringLiteral("PyFloat"); }
-static inline QString pyIntT() { return QStringLiteral("PyLong"); }
static inline QString pyLongT() { return QStringLiteral("PyLong"); }
static inline QString pyObjectT() { return QStringLiteral("object"); }
static inline QString pyStrT() { return QStringLiteral("str"); }
diff --git a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
index 268cb7c25..a56ecc76a 100644
--- a/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/shibokengenerator.cpp
@@ -125,17 +125,17 @@ static const QHash<QString, QString> &primitiveTypesCorrespondences()
{u"char"_s, sbkCharT()},
{u"signed char"_s, sbkCharT()},
{u"unsigned char"_s, sbkCharT()},
- {intT(), pyIntT()},
- {u"signed int"_s, pyIntT()},
- {u"uint"_s, pyIntT()},
- {u"unsigned int"_s, pyIntT()},
- {shortT(), pyIntT()},
- {u"ushort"_s, pyIntT()},
- {u"signed short"_s, pyIntT()},
- {u"signed short int"_s, pyIntT()},
- {unsignedShortT(), pyIntT()},
- {u"unsigned short int"_s, pyIntT()},
- {longT(), pyIntT()},
+ {intT(), pyLongT()},
+ {u"signed int"_s, pyLongT()},
+ {u"uint"_s, pyLongT()},
+ {u"unsigned int"_s, pyLongT()},
+ {shortT(), pyLongT()},
+ {u"ushort"_s, pyLongT()},
+ {u"signed short"_s, pyLongT()},
+ {u"signed short int"_s, pyLongT()},
+ {unsignedShortT(), pyLongT()},
+ {u"unsigned short int"_s, pyLongT()},
+ {longT(), pyLongT()},
{doubleT(), pyFloatT()},
{floatT(), pyFloatT()},
{u"unsigned long"_s, pyLongT()},
@@ -770,8 +770,7 @@ QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction
bool ShibokenGenerator::isNumber(const QString &cpythonApiName)
{
- return cpythonApiName == pyIntT()
- || cpythonApiName == pyFloatT() || cpythonApiName == pyLongT()
+ return cpythonApiName == pyFloatT() || cpythonApiName == pyLongT()
|| cpythonApiName == pyBoolT();
}
diff --git a/sources/shiboken6/libshiboken/basewrapper.cpp b/sources/shiboken6/libshiboken/basewrapper.cpp
index f049975b7..14aed3606 100644
--- a/sources/shiboken6/libshiboken/basewrapper.cpp
+++ b/sources/shiboken6/libshiboken/basewrapper.cpp
@@ -140,7 +140,7 @@ check_set_special_type_attr(PyTypeObject *type, PyObject *value, const char *nam
// PYSIDE-1177: Add a setter to allow setting type doc.
static int
-type_set_doc(PyTypeObject *type, PyObject *value, void *context)
+type_set_doc(PyTypeObject *type, PyObject *value, void * /* context */)
{
if (!check_set_special_type_attr(type, value, "__doc__"))
return -1;
@@ -390,6 +390,17 @@ static void SbkDeallocWrapperCommon(PyObject *pyObj, bool canDelete)
}
}
+static inline PyObject *_Sbk_NewVarObject(PyTypeObject *type)
+{
+ // PYSIDE-1970: Support __slots__, implemented by PyVarObject
+ auto const baseSize = sizeof(SbkObject);
+ auto varCount = Py_SIZE(type);
+ auto *self = PyObject_GC_NewVar(PyObject, type, varCount);
+ if (varCount)
+ std::memset(reinterpret_cast<char *>(self) + baseSize, 0, varCount * sizeof(void *));
+ return self;
+}
+
void SbkDeallocWrapper(PyObject *pyObj)
{
SbkDeallocWrapperCommon(pyObj, true);
@@ -469,7 +480,7 @@ PyObject *MakeQAppWrapper(PyTypeObject *type)
}
// monitoring the last application state
- PyObject *qApp_curr = type != nullptr ? PyObject_GC_New(PyObject, type) : Py_None;
+ PyObject *qApp_curr = type != nullptr ? _Sbk_NewVarObject(type) : Py_None;
static PyObject *builtins = PyEval_GetBuiltins();
if (PyDict_SetItem(builtins, Shiboken::PyName::qApp(), qApp_curr) < 0)
return nullptr;
@@ -574,11 +585,11 @@ static PyTypeObject *SbkObjectType_tp_new(PyTypeObject *metatype, PyObject *args
return newType;
}
-static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype)
+static PyObject *_setupNew(PyObject *obSelf, PyTypeObject *subtype)
{
auto *obSubtype = reinterpret_cast<PyObject *>(subtype);
auto *sbkSubtype = subtype;
- auto *obSelf = reinterpret_cast<PyObject *>(self);
+ auto *self = reinterpret_cast<SbkObject *>(obSelf);
Py_INCREF(obSubtype);
auto d = new SbkObjectPrivate;
@@ -602,18 +613,19 @@ static PyObject *_setupNew(SbkObject *self, PyTypeObject *subtype)
return obSelf;
}
-PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject *, PyObject *)
+PyObject *SbkObject_tp_new(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
{
- SbkObject *self = PyObject_GC_New(SbkObject, subtype);
+ PyObject *self = _Sbk_NewVarObject(subtype);
return _setupNew(self, subtype);
}
PyObject *SbkQApp_tp_new(PyTypeObject *subtype, PyObject *, PyObject *)
{
- auto self = reinterpret_cast<SbkObject *>(MakeQAppWrapper(subtype));
+ auto *obSelf = MakeQAppWrapper(subtype);
+ auto *self = reinterpret_cast<SbkObject *>(obSelf);
if (self == nullptr)
return nullptr;
- auto ret = _setupNew(self, subtype);
+ auto ret = _setupNew(obSelf, subtype);
auto priv = self->d;
priv->isQAppSingleton = 1;
return ret;
diff --git a/sources/shiboken6/libshiboken/basewrapper_p.h b/sources/shiboken6/libshiboken/basewrapper_p.h
index 259206d7a..8d7e0b7a9 100644
--- a/sources/shiboken6/libshiboken/basewrapper_p.h
+++ b/sources/shiboken6/libshiboken/basewrapper_p.h
@@ -150,7 +150,8 @@ struct SbkObjectTypePrivate
void (*subtype_init)(PyTypeObject *, PyObject *, PyObject *);
const char **propertyStrings;
const char **enumFlagInfo;
- PyObject *flagsDict;
+ PyObject *enumFlagsDict;
+ PyObject *enumTypeDict;
};
diff --git a/sources/shiboken6/libshiboken/pep384impl.cpp b/sources/shiboken6/libshiboken/pep384impl.cpp
index 1ddbe3ba1..861f45465 100644
--- a/sources/shiboken6/libshiboken/pep384impl.cpp
+++ b/sources/shiboken6/libshiboken/pep384impl.cpp
@@ -381,11 +381,12 @@ static const char *utf8FastPath(PyObject *str)
const char *_PepUnicode_AsString(PyObject *str)
{
/*
- * We need to keep the string alive but cannot borrow the Python object.
- * Ugly easy way out: We re-code as an interned bytes string. This
- * produces a pseudo-leak as long as there are new strings.
- * Typically, this function is used for name strings, and the dict size
- * will not grow so much.
+ * This function is the surrogate for PyUnicode_AsUTF8, which keeps the data
+ * in the unicode object as long as that object exists.
+ *
+ * The function does too much if not optimized by utf8, because it keeps the
+ * string alive, unconditionally.
+ * We should not rely on this behavior and think of PyUnicode_AsUTF8, only.
*/
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
diff --git a/sources/shiboken6/libshiboken/pep384impl.h b/sources/shiboken6/libshiboken/pep384impl.h
index 1241621cf..2fcab0272 100644
--- a/sources/shiboken6/libshiboken/pep384impl.h
+++ b/sources/shiboken6/libshiboken/pep384impl.h
@@ -229,6 +229,9 @@ LIBSHIBOKEN_API int Pep_GetVerboseFlag(void);
// PyUnicode_GetSize is deprecated in favor of PyUnicode_GetLength.
#define PepUnicode_GetLength(op) PyUnicode_GetLength((PyObject *)(op))
+// Unfortunately, we cannot ask this at runtime
+// #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030A0000
+// FIXME: Python 3.10: Replace _PepUnicode_AsString by PyUnicode_AsUTF8
#ifdef Py_LIMITED_API
LIBSHIBOKEN_API const char *_PepUnicode_AsString(PyObject *);
diff --git a/sources/shiboken6/libshiboken/sbkenum.cpp b/sources/shiboken6/libshiboken/sbkenum.cpp
index 817f5254c..983703dc2 100644
--- a/sources/shiboken6/libshiboken/sbkenum.cpp
+++ b/sources/shiboken6/libshiboken/sbkenum.cpp
@@ -401,6 +401,8 @@ PyObject *unpickleEnum(PyObject *enum_class_name, PyObject *value)
return PyObject_CallFunctionObjArgs(klass, value, nullptr);
}
+int enumOption{};
+
} // namespace Enum
} // namespace Shiboken
@@ -430,11 +432,13 @@ static PyMethodDef SbkEnumObject_Methods[] = {
{nullptr, nullptr, 0, nullptr} // Sentinel
};
+static PyObject *PyEnumModule{};
static PyObject *PyEnumMeta{};
static PyObject *PyEnum{};
static PyObject *PyIntEnum{};
static PyObject *PyFlag{};
static PyObject *PyIntFlag{};
+static PyObject *PyFlag_KEEP{};
PyTypeObject *getPyEnumMeta()
{
@@ -443,6 +447,7 @@ PyTypeObject *getPyEnumMeta()
static auto *mod = PyImport_ImportModule("enum");
if (mod) {
+ PyEnumModule = mod;
PyEnumMeta = PyObject_GetAttrString(mod, "EnumMeta");
if (PyEnumMeta && PyType_Check(PyEnumMeta))
PyEnum = PyObject_GetAttrString(mod, "Enum");
@@ -452,8 +457,12 @@ PyTypeObject *getPyEnumMeta()
PyFlag = PyObject_GetAttrString(mod, "Flag");
if (PyFlag && PyType_Check(PyFlag))
PyIntFlag = PyObject_GetAttrString(mod, "IntFlag");
- if (PyIntFlag && PyType_Check(PyIntFlag))
+ if (PyIntFlag && PyType_Check(PyIntFlag)) {
+ // KEEP is defined from Python 3.11 on.
+ PyFlag_KEEP = PyObject_GetAttrString(mod, "KEEP");
+ PyErr_Clear();
return reinterpret_cast<PyTypeObject *>(PyEnumMeta);
+ }
}
Py_FatalError("Python module 'enum' not found");
return nullptr;
@@ -461,23 +470,25 @@ PyTypeObject *getPyEnumMeta()
void init_enum()
{
- static bool is_initialized = false;
- if (is_initialized)
+ static bool isInitialized = false;
+ if (isInitialized)
return;
- if (!(is_initialized || enum_unpickler || _init_enum()))
+ if (!(isInitialized || enum_unpickler || _init_enum()))
Py_FatalError("could not load enum pickling helper function");
Py_AtExit(cleanupEnumTypes);
// PYSIDE-1735: Determine whether we should use the old or the new enum implementation.
- static const char *envname = "PYSIDE63_OPTION_PYTHON_ENUM";
- const char *envsetting = getenv(envname);
- // I tried to use the save version getenv_s instead, but this function does not
- // exist on macOS. But this does no harm:
- // This variable has been set already by parser.py initialization.
- assert(envsetting);
- useOldEnum = strncmp(envsetting, "0", 10) == 0;
+ static PyObject *sysmodule = PyImport_AddModule("sys");
+ static PyObject *option = PyObject_GetAttrString(sysmodule, "pyside63_option_python_enum");
+ if (!option || !PyLong_Check(option)) {
+ PyErr_Clear();
+ option = PyLong_FromLong(0);
+ }
+ int ignoreOver{};
+ Enum::enumOption = PyLong_AsLongAndOverflow(option, &ignoreOver);
+ useOldEnum = Enum::enumOption == Enum::ENOPT_OLD_ENUM;
getPyEnumMeta();
- is_initialized = true;
+ isInitialized = true;
}
// PYSIDE-1735: Helper function supporting QEnum
@@ -498,6 +509,13 @@ int enumIsFlag(PyObject *ob_type)
return 0;
}
+// PYSIDE-1735: Helper function to ask what enum we are using
+bool usingNewEnum()
+{
+ init_enum();
+ return !useOldEnum;
+}
+
} // extern "C"
//
@@ -719,13 +737,17 @@ newItem(PyTypeObject *enumType, long itemValue, const char *itemName)
if (useOldEnum)
return newItemOld(enumType, itemValue, itemName);
- if (!itemName) {
- //PyObject *enumObj = getEnumItemFromValue(enumType, itemValue);
- PyObject *enumObj = PyObject_CallFunction(reinterpret_cast<PyObject *>(enumType), "i", itemValue);
- //if (enumObj)
- return enumObj;
- }
- return PyObject_GetAttrString(reinterpret_cast<PyObject *>(enumType), itemName);
+ auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
+ if (!itemName)
+ return PyObject_CallFunction(obEnumType, "i", itemValue);
+
+ static PyObject *const _member_map_ = String::createStaticString("_member_map_");
+ auto *member_map = PyDict_GetItem(enumType->tp_dict, _member_map_);
+ if (!(member_map && PyDict_Check(member_map)))
+ return nullptr;
+ auto *result = PyDict_GetItemString(member_map, itemName);
+ Py_XINCREF(result);
+ return result;
}
} // namespace Shiboken
@@ -982,6 +1004,115 @@ static PyTypeObject *recordCurrentEnum(PyObject *scopeOrModule,
return nullptr;
}
+static bool is_old_version()
+{
+ auto *sysmodule = PyImport_AddModule("sys");
+ auto *dic = PyModule_GetDict(sysmodule);
+ auto *version = PyDict_GetItemString(dic, "version_info");
+ auto *major = PyTuple_GetItem(version, 0);
+ auto *minor = PyTuple_GetItem(version, 1);
+ auto number = PyLong_AsLong(major) * 1000 + PyLong_AsLong(minor);
+ return number <= 3008;
+}
+
+///////////////////////////////////////////////////////////////////////
+//
+// Support for Missing Values
+// ==========================
+//
+// Qt enums sometimes use undefined values in enums.
+// The enum module handles this by the option "KEEP" for Flag and
+// IntFlag. The handling of missing enum values is still strict.
+//
+// We changed that (also for compatibility with some competitor)
+// and provide a `_missing_` function that creates the missing value.
+//
+// The idea:
+// ---------
+// We cannot modify the already created class.
+// But we can create a one-element class with the new value and
+// pretend that this is the already existing class.
+//
+// We create each constant only once and keep the result in a dict
+// "_sbk_missing_". This is similar to a competitor's "_sip_missing_".
+//
+static PyObject *missing_func(PyObject * /* self */ , PyObject *args)
+{
+ // In order to relax matters to be more compatible with C++, we need
+ // to create a pseudo-member with that value.
+ static auto *const _sbk_missing = Shiboken::String::createStaticString("_sbk_missing_");
+ static auto *const _name = Shiboken::String::createStaticString("__name__");
+ static auto *const _mro = Shiboken::String::createStaticString("__mro__");
+ static auto *const _class = Shiboken::String::createStaticString("__class__");
+
+ PyObject *klass{}, *value{};
+ if (!PyArg_UnpackTuple(args, "missing", 2, 2, &klass, &value))
+ Py_RETURN_NONE;
+ if (!PyLong_Check(value))
+ Py_RETURN_NONE;
+ auto *type = reinterpret_cast<PyTypeObject *>(klass);
+ auto *sbk_missing = PyDict_GetItem(type->tp_dict, _sbk_missing);
+ if (!sbk_missing) {
+ sbk_missing = PyDict_New();
+ PyDict_SetItem(type->tp_dict, _sbk_missing, sbk_missing);
+ }
+ // See if the value is already in the dict.
+ AutoDecRef val_str(PyObject_CallMethod(value, "__str__", nullptr));
+ auto *ret = PyDict_GetItem(sbk_missing, val_str);
+ if (ret) {
+ Py_INCREF(ret);
+ return ret;
+ }
+ // No, we must create a new object and insert it into the dict.
+ AutoDecRef cls_name(PyObject_GetAttr(klass, _name));
+ AutoDecRef mro(PyObject_GetAttr(klass, _mro));
+ auto *baseClass(PyTuple_GetItem(mro, 1));
+ AutoDecRef param(PyDict_New());
+ PyDict_SetItem(param, val_str, value);
+ AutoDecRef fake(PyObject_CallFunctionObjArgs(baseClass, cls_name.object(), param.object(),
+ nullptr));
+ ret = PyObject_GetAttr(fake, val_str);
+ PyDict_SetItem(sbk_missing, val_str, ret);
+ // Now the real fake: Pretend that the type is our original type!
+ PyObject_SetAttr(ret, _class, klass);
+ return ret;
+}
+
+static struct PyMethodDef dummy_methods[] = {
+ {"_missing_", reinterpret_cast<PyCFunction>(missing_func), METH_VARARGS|METH_STATIC, nullptr},
+ {nullptr, nullptr, 0, nullptr}
+};
+
+static PyType_Slot dummy_slots[] = {
+ {Py_tp_base, reinterpret_cast<void *>(&PyType_Type)},
+ {Py_tp_methods, reinterpret_cast<void *>(dummy_methods)},
+ {0, nullptr}
+};
+
+static PyType_Spec dummy_spec = {
+ "1:builtins.EnumType",
+ 0,
+ 0,
+ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
+ dummy_slots,
+};
+
+static PyObject *create_missing_func(PyObject *klass)
+{
+ // When creating the class, memorize it in the missing function by
+ // a partial function argument.
+ static auto *const type = SbkType_FromSpec(&dummy_spec);
+ static auto *const obType = reinterpret_cast<PyObject *>(type);
+ static auto *const _missing = Shiboken::String::createStaticString("_missing_");
+ static auto *const func = PyObject_GetAttr(obType, _missing);
+ static auto *const functools = PyImport_ImportModule("_functools"); // builtin
+ static auto *const _partial = Shiboken::String::createStaticString("partial");
+ static auto *const partial = PyObject_GetAttr(functools, _partial);
+ return PyObject_CallFunctionObjArgs(partial, func, klass, nullptr);
+}
+//
+////////////////////////////////////////////////////////////////////////
+
PyTypeObject *morphLastEnumToPython()
{
/// The Python Enum internal structure is way too complicated.
@@ -1001,14 +1132,37 @@ PyTypeObject *morphLastEnumToPython()
// If that happens, use the existing new type to keep type checks correct.
return setp->replacementType;
}
+
+ auto *scopeOrModule = lec.scopeOrModule;
+ static PyObject *enumName = String::createStaticString("IntEnum");
+ if (PyType_Check(scopeOrModule)) {
+ // For global objects, we have no good solution, yet where to put the int info.
+ auto type = reinterpret_cast<PyTypeObject *>(scopeOrModule);
+ auto *sotp = PepType_SOTP(type);
+ if (!sotp->enumFlagsDict)
+ initEnumFlagsDict(type);
+ enumName = PyDict_GetItem(sotp->enumTypeDict, String::fromCString(lec.name));
+ }
+
PyObject *key, *value;
Py_ssize_t pos = 0;
PyObject *values = PyDict_GetItem(enumType->tp_dict, PyName::values());
if (!values)
return nullptr;
+ AutoDecRef PyEnumType(PyObject_GetAttr(PyEnumModule, enumName));
+ assert(PyEnumType.object());
+ bool isFlag = PyObject_IsSubclass(PyEnumType, PyFlag);
+
+ // See if we should use the Int versions of the types, again
+ bool useIntInheritance = Enum::enumOption & Enum::ENOPT_INHERIT_INT;
+ if (useIntInheritance) {
+ auto *surrogate = PyObject_IsSubclass(PyEnumType, PyFlag) ? PyIntFlag : PyIntEnum;
+ Py_INCREF(surrogate);
+ PyEnumType.reset(surrogate);
+ }
+
// Walk the values dict and create a Python enum type.
- auto *PyEnumType = lec.flagsType ? PyIntFlag : PyIntEnum;
AutoDecRef name(PyUnicode_FromString(lec.name));
AutoDecRef args(PyList_New(0));
auto *pyName = name.object();
@@ -1022,21 +1176,55 @@ PyTypeObject *morphLastEnumToPython()
PyTuple_SET_ITEM(key_value, 1, num);
PyList_Append(pyArgs, key_value);
}
- auto *obNewType = PyObject_CallFunctionObjArgs(PyEnumType, pyName, pyArgs, nullptr);
- if (!obNewType || PyObject_SetAttr(lec.scopeOrModule, pyName, obNewType) < 0)
- return nullptr;
+ // We now create the new type. Since Python 3.11, we need to pass in
+ // `boundary=KEEP` because the default STRICT crashes on us.
+ // See QDir.Filter.Drives | QDir.Filter.Files
+ AutoDecRef callArgs(Py_BuildValue("(OO)", pyName, pyArgs));
+ AutoDecRef callDict(PyDict_New());
+ static PyObject *boundary = String::createStaticString("boundary");
+ if (PyFlag_KEEP)
+ PyDict_SetItem(callDict, boundary, PyFlag_KEEP);
+ auto *obNewType = PyObject_Call(PyEnumType, callArgs, callDict);
+ if (!obNewType || PyObject_SetAttr(scopeOrModule, pyName, obNewType) < 0)
+ return nullptr;
+
+ // For compatibility with Qt enums, provide a permissive missing method for (Int)?Enum.
+ if (!isFlag) {
+ bool supportMissing = !(Enum::enumOption & Enum::ENOPT_NO_MISSING);
+ if (supportMissing) {
+ AutoDecRef enum_missing(create_missing_func(obNewType));
+ PyObject_SetAttrString(obNewType, "_missing_", enum_missing);
+ }
+ }
+
auto *newType = reinterpret_cast<PyTypeObject *>(obNewType);
auto *obEnumType = reinterpret_cast<PyObject *>(enumType);
AutoDecRef qual_name(PyObject_GetAttr(obEnumType, PyMagicName::qualname()));
PyObject_SetAttr(obNewType, PyMagicName::qualname(), qual_name);
AutoDecRef module(PyObject_GetAttr(obEnumType, PyMagicName::module()));
PyObject_SetAttr(obNewType, PyMagicName::module(), module);
+
+ // See if we should re-introduce shortcuts in the enclosing object.
+ const bool useGlobalShortcut = (Enum::enumOption & Enum::ENOPT_GLOBAL_SHORTCUT) != 0;
+ const bool useScopedShortcut = (Enum::enumOption & Enum::ENOPT_SCOPED_SHORTCUT) != 0;
+ if (useGlobalShortcut || useScopedShortcut) {
+ bool isModule = PyModule_Check(scopeOrModule);
+ pos = 0;
+ while (PyDict_Next(values, &pos, &key, &value)) {
+ AutoDecRef entry(PyObject_GetAttr(obNewType, key));
+ if ((useGlobalShortcut && isModule) || (useScopedShortcut && !isModule))
+ if (PyObject_SetAttr(scopeOrModule, key, entry) < 0)
+ return nullptr;
+ }
+ }
+
// Protect against double initialization
setp->replacementType = newType;
-#if PY_VERSION_HEX < 0x03080000
+
// PYSIDE-1735: Old Python versions can't stand the early enum deallocation.
- Py_INCREF(enumType);
-#endif
+ static bool old_python_version = is_old_version();
+ if (old_python_version)
+ Py_INCREF(obEnumType);
return newType;
}
diff --git a/sources/shiboken6/libshiboken/sbkenum_p.h b/sources/shiboken6/libshiboken/sbkenum_p.h
index f19cbbf00..62a9fc307 100644
--- a/sources/shiboken6/libshiboken/sbkenum_p.h
+++ b/sources/shiboken6/libshiboken/sbkenum_p.h
@@ -52,6 +52,9 @@ struct SbkEnumTypePrivate
extern "C" {
+/// PYSIDE-1735: Pass on the Python enum/flag information.
+LIBSHIBOKEN_API void initEnumFlagsDict(PyTypeObject *type);
+
/// PYSIDE-1735: Patching the Enum / Flags implementation. Remove in 6.4
LIBSHIBOKEN_API PyTypeObject *morphLastEnumToPython();
LIBSHIBOKEN_API PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObject *EType);
@@ -60,7 +63,27 @@ LIBSHIBOKEN_API PyTypeObject *mapFlagsToSameEnum(PyTypeObject *FType, PyTypeObje
LIBSHIBOKEN_API PyTypeObject *getPyEnumMeta();
/// PYSIDE-1735: Helper function supporting QEnum
LIBSHIBOKEN_API int enumIsFlag(PyObject *ob_enum);
+/// PYSIDE-1735: Helper function to ask what enum we are using
+LIBSHIBOKEN_API bool usingNewEnum();
}
+namespace Shiboken { namespace Enum {
+
+enum : int {
+ ENOPT_OLD_ENUM = 0x00,
+ ENOPT_NEW_ENUM = 0x01,
+ ENOPT_INHERIT_INT = 0x02,
+ ENOPT_GLOBAL_SHORTCUT = 0x04,
+ ENOPT_SCOPED_SHORTCUT = 0x08,
+ ENOPT_NO_FAKESHORTCUT = 0x10,
+ ENOPT_NO_FAKERENAMES = 0x20,
+ ENOPT_NO_ZERODEFAULT = 0x40,
+ ENOPT_NO_MISSING = 0x80,
+};
+
+LIBSHIBOKEN_API extern int enumOption;
+
+}}
+
#endif // SBKENUM_P_H
diff --git a/sources/shiboken6/libshiboken/sbkfeature_base.cpp b/sources/shiboken6/libshiboken/sbkfeature_base.cpp
index 770735e5c..8f1d4f33a 100644
--- a/sources/shiboken6/libshiboken/sbkfeature_base.cpp
+++ b/sources/shiboken6/libshiboken/sbkfeature_base.cpp
@@ -209,22 +209,30 @@ static bool currentOpcode_Is_CallMethNoArgs()
return opcode2 == PRECALL && oparg2 == 0;
}
-static void _initFlagsDict(SbkObjectTypePrivate *sotp)
+void initEnumFlagsDict(PyTypeObject *type)
{
+ // We create a dict for all flag enums that holds the original C++ name
+ // and a dict that gives every enum/flag type name.
static PyObject *const split = Shiboken::String::createStaticString("split");
static PyObject *const colon = Shiboken::String::createStaticString(":");
+ auto sotp = PepType_SOTP(type);
auto **enumFlagInfo = sotp->enumFlagInfo;
auto *dict = PyDict_New();
+ auto *typeDict = PyDict_New();
for (; *enumFlagInfo; ++enumFlagInfo) {
AutoDecRef line(PyUnicode_FromString(*enumFlagInfo));
AutoDecRef parts(PyObject_CallMethodObjArgs(line, split, colon, nullptr));
+ auto *name = PyList_GetItem(parts, 0);
if (PyList_Size(parts) == 3) {
auto *key = PyList_GetItem(parts, 2);
- auto *value = PyList_GetItem(parts, 0);
+ auto *value = name;
PyDict_SetItem(dict, key, value);
}
+ auto *typeName = PyList_GetItem(parts, 1);
+ PyDict_SetItem(typeDict, name, typeName);
}
- sotp->flagsDict = dict;
+ sotp->enumFlagsDict = dict;
+ sotp->enumTypeDict = typeDict;
}
static PyObject *replaceNoArgWithZero(PyObject *callable)
@@ -264,10 +272,13 @@ PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
// no longer advertized in PYI files or line completion.
if (ret && Py_TYPE(ret) == EnumMeta && currentOpcode_Is_CallMethNoArgs()) {
- // We provide a zero argument for compatibility if it is a call with no args.
- auto *hold = replaceNoArgWithZero(ret);
- Py_DECREF(ret);
- ret = hold;
+ bool useZeroDefault = !(Enum::enumOption & Enum::ENOPT_NO_ZERODEFAULT);
+ if (useZeroDefault) {
+ // We provide a zero argument for compatibility if it is a call with no args.
+ auto *hold = replaceNoArgWithZero(ret);
+ Py_DECREF(ret);
+ ret = hold;
+ }
}
if (!ret && name != ignAttr1 && name != ignAttr2) {
@@ -287,60 +298,66 @@ PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
const char **enumFlagInfo = sotp->enumFlagInfo;
if (!(enumFlagInfo))
continue;
- if (!sotp->flagsDict)
- _initFlagsDict(sotp);
- auto *rename = PyDict_GetItem(sotp->flagsDict, name);
- if (rename) {
- /*
- * Part 1: Look into the flagsDict if we have an old flags name.
- * -------------------------------------------------------------
- * We need to replace the parameterless
-
- QtCore.Qt.Alignment()
-
- * by the one-parameter call
-
- QtCore.Qt.AlignmentFlag(0)
-
- * That means: We need to bind the zero as default into a wrapper and
- * return that to be called.
- *
- * Addendum:
- * ---------
- * We first need to look into the current opcode of the bytecode to find
- * out if we have a call like above or just a type lookup.
- */
- auto *flagType = PyDict_GetItem(type_base->tp_dict, rename);
- if (currentOpcode_Is_CallMethNoArgs())
- return replaceNoArgWithZero(flagType);
- Py_INCREF(flagType);
- return flagType;
+ if (!sotp->enumFlagsDict)
+ initEnumFlagsDict(type_base);
+ bool useFakeRenames = !(Enum::enumOption & Enum::ENOPT_NO_FAKERENAMES);
+ if (useFakeRenames) {
+ auto *rename = PyDict_GetItem(sotp->enumFlagsDict, name);
+ if (rename) {
+ /*
+ * Part 1: Look into the enumFlagsDict if we have an old flags name.
+ * -------------------------------------------------------------
+ * We need to replace the parameterless
+
+ QtCore.Qt.Alignment()
+
+ * by the one-parameter call
+
+ QtCore.Qt.AlignmentFlag(0)
+
+ * That means: We need to bind the zero as default into a wrapper and
+ * return that to be called.
+ *
+ * Addendum:
+ * ---------
+ * We first need to look into the current opcode of the bytecode to find
+ * out if we have a call like above or just a type lookup.
+ */
+ auto *flagType = PyDict_GetItem(type_base->tp_dict, rename);
+ if (currentOpcode_Is_CallMethNoArgs())
+ return replaceNoArgWithZero(flagType);
+ Py_INCREF(flagType);
+ return flagType;
+ }
}
- auto *dict = type_base->tp_dict;
- PyObject *key, *value;
- Py_ssize_t pos = 0;
- while (PyDict_Next(dict, &pos, &key, &value)) {
- /*
- * Part 2: Check for a duplication into outer scope.
- * -------------------------------------------------
- * We need to replace the shortcut
-
- QtCore.Qt.AlignLeft
-
- * by the correct call
-
- QtCore.Qt.AlignmentFlag.AlignLeft
-
- * That means: We need to search all Enums of the class.
- */
- if (Py_TYPE(value) == EnumMeta) {
- auto *valtype = reinterpret_cast<PyTypeObject *>(value);
- auto *member_map = PyDict_GetItem(valtype->tp_dict, _member_map_);
- if (member_map && PyDict_Check(member_map)) {
- auto *result = PyDict_GetItem(member_map, name);
- if (result) {
- Py_INCREF(result);
- return result;
+ bool useFakeShortcuts = !(Enum::enumOption & Enum::ENOPT_NO_FAKESHORTCUT);
+ if (useFakeShortcuts) {
+ auto *dict = type_base->tp_dict;
+ PyObject *key, *value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(dict, &pos, &key, &value)) {
+ /*
+ * Part 2: Check for a duplication into outer scope.
+ * -------------------------------------------------
+ * We need to replace the shortcut
+
+ QtCore.Qt.AlignLeft
+
+ * by the correct call
+
+ QtCore.Qt.AlignmentFlag.AlignLeft
+
+ * That means: We need to search all Enums of the class.
+ */
+ if (Py_TYPE(value) == EnumMeta) {
+ auto *valtype = reinterpret_cast<PyTypeObject *>(value);
+ auto *member_map = PyDict_GetItem(valtype->tp_dict, _member_map_);
+ if (member_map && PyDict_Check(member_map)) {
+ auto *result = PyDict_GetItem(member_map, name);
+ if (result) {
+ Py_INCREF(result);
+ return result;
+ }
}
}
}
@@ -351,7 +368,7 @@ PyObject *mangled_type_getattro(PyTypeObject *type, PyObject *name)
return ret;
}
-PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context)
+PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void * /* context */)
{
/*
* This is the override for getting a dict.
diff --git a/sources/shiboken6/libshiboken/sbkmodule.cpp b/sources/shiboken6/libshiboken/sbkmodule.cpp
index e5f4e2f88..ab733abfb 100644
--- a/sources/shiboken6/libshiboken/sbkmodule.cpp
+++ b/sources/shiboken6/libshiboken/sbkmodule.cpp
@@ -72,7 +72,7 @@ PyObject *import(const char *moduleName)
return module;
}
-PyObject *create(const char *moduleName, void *moduleData)
+PyObject *create(const char * /* moduleName */, void *moduleData)
{
Shiboken::init();
return PyModule_Create(reinterpret_cast<PyModuleDef *>(moduleData));
diff --git a/sources/shiboken6/libshiboken/signature/signature.cpp b/sources/shiboken6/libshiboken/signature/signature.cpp
index ca46c777c..80a6dca51 100644
--- a/sources/shiboken6/libshiboken/signature/signature.cpp
+++ b/sources/shiboken6/libshiboken/signature/signature.cpp
@@ -128,7 +128,7 @@ PyObject *GetTypeKey(PyObject *ob)
static PyObject *empty_dict = nullptr;
-PyObject *TypeKey_to_PropsDict(PyObject *type_key, PyObject *obtype)
+PyObject *TypeKey_to_PropsDict(PyObject *type_key)
{
PyObject *dict = PyDict_GetItem(pyside_globals->arg_dict, type_key);
if (dict == nullptr) {
@@ -196,7 +196,7 @@ PyObject *GetSignature_Function(PyObject *obfunc, PyObject *modifier)
AutoDecRef type_key(GetTypeKey(obtype_mod));
if (type_key.isNull())
Py_RETURN_NONE;
- PyObject *dict = TypeKey_to_PropsDict(type_key, obtype_mod);
+ PyObject *dict = TypeKey_to_PropsDict(type_key);
if (dict == nullptr)
return nullptr;
AutoDecRef func_name(PyObject_GetAttr(obfunc, PyMagicName::name()));
@@ -224,7 +224,7 @@ PyObject *GetSignature_Wrapper(PyObject *ob, PyObject *modifier)
AutoDecRef class_key(GetTypeKey(objclass));
if (func_name.isNull() || objclass.isNull() || class_key.isNull())
return nullptr;
- PyObject *dict = TypeKey_to_PropsDict(class_key, objclass);
+ PyObject *dict = TypeKey_to_PropsDict(class_key);
if (dict == nullptr)
return nullptr;
PyObject *props = PyDict_GetItem(dict, func_name);
@@ -242,7 +242,7 @@ PyObject *GetSignature_TypeMod(PyObject *ob, PyObject *modifier)
AutoDecRef ob_name(PyObject_GetAttr(ob, PyMagicName::name()));
AutoDecRef ob_key(GetTypeKey(ob));
- PyObject *dict = TypeKey_to_PropsDict(ob_key, ob);
+ PyObject *dict = TypeKey_to_PropsDict(ob_key);
if (dict == nullptr)
return nullptr;
PyObject *props = PyDict_GetItem(dict, ob_name);
@@ -580,13 +580,13 @@ static PyObject *adjustFuncName(const char *func_name)
if (prop_name) {
auto _prop_name = String::toCString(prop_name);
if (is_class_prop)
- sprintf(_buf, "%s.__dict__['%s'].fset", _path, _prop_name);
+ snprintf(_buf, sizeof(_buf), "%s.__dict__['%s'].fset", _path, _prop_name);
else
- sprintf(_buf, "%s.%s.fset", _path, _prop_name);
+ snprintf(_buf, sizeof(_buf), "%s.%s.fset", _path, _prop_name);
}
else {
auto _name = String::toCString(name);
- sprintf(_buf, "%s.%s", _path, _name);
+ snprintf(_buf, sizeof(_buf), "%s.%s", _path, _name);
}
return String::fromCString(_buf);
}
diff --git a/sources/shiboken6/libshiboken/voidptr.cpp b/sources/shiboken6/libshiboken/voidptr.cpp
index fdbd95efb..b97d0bbda 100644
--- a/sources/shiboken6/libshiboken/voidptr.cpp
+++ b/sources/shiboken6/libshiboken/voidptr.cpp
@@ -53,7 +53,7 @@ typedef struct {
bool isWritable;
} SbkVoidPtrObject;
-PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+PyObject *SbkVoidPtrObject_new(PyTypeObject *type, PyObject * /* args */, PyObject * /* kwds */)
{
// PYSIDE-560: It is much safer to first call a function and then do a
// type cast than to do everything in one line. The bad construct looked
@@ -189,7 +189,7 @@ PyObject *SbkVoidPtrObject_int(PyObject *v)
return PyLong_FromVoidPtr(sbkObject->cptr);
}
-PyObject *toBytes(PyObject *self, PyObject *args)
+PyObject *toBytes(PyObject *self, PyObject * /* args */)
{
auto *sbkObject = reinterpret_cast<SbkVoidPtrObject *>(self);
if (sbkObject->size < 0) {
diff --git a/sources/shiboken6/shibokenmodule/Shiboken.pyi b/sources/shiboken6/shibokenmodule/Shiboken.pyi
index e312f6912..c0bfe3907 100644
--- a/sources/shiboken6/shibokenmodule/Shiboken.pyi
+++ b/sources/shiboken6/shibokenmodule/Shiboken.pyi
@@ -59,15 +59,15 @@ class VoidPtr(object): ...
def _unpickle_enum(arg__1: object, arg__2: object) -> object: ...
-def createdByPython(arg__1: object) -> bool: ...
-def delete(arg__1: object) -> None: ...
-def dump(arg__1: object) -> object: ...
-def getAllValidWrappers() -> object: ...
-def getCppPointer(arg__1: object) -> object: ...
-def invalidate(arg__1: object) -> None: ...
+def createdByPython(arg__1: Shiboken.Object) -> bool: ...
+def delete(arg__1: Shiboken.Object) -> None: ...
+def dump(arg__1: object) -> str: ...
+def getAllValidWrappers() -> list[Shiboken.Object]: ...
+def getCppPointer(arg__1: Shiboken.Object) -> tuple[int, ...]: ...
+def invalidate(arg__1: Shiboken.Object) -> None: ...
def isValid(arg__1: object) -> bool: ...
-def ownedByPython(arg__1: object) -> bool: ...
-def wrapInstance(arg__1: int, arg__2: type) -> object: ...
+def ownedByPython(arg__1: Shiboken.Object) -> bool: ...
+def wrapInstance(arg__1: int, arg__2: type) -> Shiboken.Object: ...
# eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py
deleted file mode 100644
index 97d189c59..000000000
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/enum_310.py
+++ /dev/null
@@ -1,1138 +0,0 @@
-#############################################################################
-##
-## Copyright (C) 2022 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $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$
-##
-#############################################################################
-
-PSF_LICENSE = """
-PSF LICENSE AGREEMENT FOR PYTHON 3.10.4
-
-1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and
- the Individual or Organization ("Licensee") accessing and otherwise using Python
- 3.10.4 software in source or binary form and its associated documentation.
-
-2. Subject to the terms and conditions of this License Agreement, PSF hereby
- grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
- analyze, test, perform and/or display publicly, prepare derivative works,
- distribute, and otherwise use Python 3.10.4 alone or in any derivative
- version, provided, however, that PSF's License Agreement and PSF's notice of
- copyright, i.e., "Copyright © 2001-2022 Python Software Foundation; All Rights
- Reserved" are retained in Python 3.10.4 alone or in any derivative version
- prepared by Licensee.
-
-3. In the event Licensee prepares a derivative work that is based on or
- incorporates Python 3.10.4 or any part thereof, and wants to make the
- derivative work available to others as provided herein, then Licensee hereby
- agrees to include in any such work a brief summary of the changes made to Python
- 3.10.4.
-
-4. PSF is making Python 3.10.4 available to Licensee on an "AS IS" basis.
- PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF
- EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE
- USE OF PYTHON 3.10.4 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS.
-
-5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 3.10.4
- FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF
- MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 3.10.4, OR ANY DERIVATIVE
- THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
-
-6. This License Agreement will automatically terminate upon a material breach of
- its terms and conditions.
-
-7. Nothing in this License Agreement shall be deemed to create any relationship
- of agency, partnership, or joint venture between PSF and Licensee. This License
- Agreement does not grant permission to use PSF trademarks or trade name in a
- trademark sense to endorse or promote products or services of Licensee, or any
- third party.
-
-8. By copying, installing or otherwise using Python 3.10.4, Licensee agrees
- to be bound by the terms and conditions of this License Agreement.
-"""
-
-import sys
-from types import MappingProxyType, DynamicClassAttribute
-
-
-__all__ = [
- 'EnumMeta',
- 'Enum', 'IntEnum', 'Flag', 'IntFlag',
- 'auto', 'unique',
- ]
-
-
-def _is_descriptor(obj):
- """
- Returns True if obj is a descriptor, False otherwise.
- """
- return (
- hasattr(obj, '__get__') or
- hasattr(obj, '__set__') or
- hasattr(obj, '__delete__')
- )
-
-def _is_dunder(name):
- """
- Returns True if a __dunder__ name, False otherwise.
- """
- return (
- len(name) > 4 and
- name[:2] == name[-2:] == '__' and
- name[2] != '_' and
- name[-3] != '_'
- )
-
-def _is_sunder(name):
- """
- Returns True if a _sunder_ name, False otherwise.
- """
- return (
- len(name) > 2 and
- name[0] == name[-1] == '_' and
- name[1:2] != '_' and
- name[-2:-1] != '_'
- )
-
-def _is_private(cls_name, name):
- # do not use `re` as `re` imports `enum`
- pattern = '_%s__' % (cls_name, )
- pat_len = len(pattern)
- if (
- len(name) > pat_len
- and name.startswith(pattern)
- and name[pat_len:pat_len+1] != ['_']
- and (name[-1] != '_' or name[-2] != '_')
- ):
- return True
- else:
- return False
-
-def _make_class_unpicklable(cls):
- """
- Make the given class un-picklable.
- """
- def _break_on_call_reduce(self, proto):
- raise TypeError('%r cannot be pickled' % self)
- cls.__reduce_ex__ = _break_on_call_reduce
- cls.__module__ = '<unknown>'
-
-_auto_null = object()
-class auto:
- """
- Instances are replaced with an appropriate value in Enum class suites.
- """
- value = _auto_null
-
-
-class _EnumDict(dict):
- """
- Track enum member order and ensure member names are not reused.
-
- EnumMeta will use the names found in self._member_names as the
- enumeration member names.
- """
- def __init__(self):
- super().__init__()
- self._member_names = []
- self._last_values = []
- self._ignore = []
- self._auto_called = False
-
- def __setitem__(self, key, value):
- """
- Changes anything not dundered or not a descriptor.
-
- If an enum member name is used twice, an error is raised; duplicate
- values are not checked for.
-
- Single underscore (sunder) names are reserved.
- """
- if _is_private(self._cls_name, key):
- import warnings
- warnings.warn(
- "private variables, such as %r, will be normal attributes in 3.11"
- % (key, ),
- DeprecationWarning,
- stacklevel=2,
- )
- if _is_sunder(key):
- if key not in (
- '_order_', '_create_pseudo_member_',
- '_generate_next_value_', '_missing_', '_ignore_',
- ):
- raise ValueError('_names_ are reserved for future Enum use')
- if key == '_generate_next_value_':
- # check if members already defined as auto()
- if self._auto_called:
- raise TypeError("_generate_next_value_ must be defined before members")
- setattr(self, '_generate_next_value', value)
- elif key == '_ignore_':
- if isinstance(value, str):
- value = value.replace(',',' ').split()
- else:
- value = list(value)
- self._ignore = value
- already = set(value) & set(self._member_names)
- if already:
- raise ValueError(
- '_ignore_ cannot specify already set names: %r'
- % (already, )
- )
- elif _is_dunder(key):
- if key == '__order__':
- key = '_order_'
- elif key in self._member_names:
- # descriptor overwriting an enum?
- raise TypeError('Attempted to reuse key: %r' % key)
- elif key in self._ignore:
- pass
- elif not _is_descriptor(value):
- if key in self:
- # enum overwriting a descriptor?
- raise TypeError('%r already defined as: %r' % (key, self[key]))
- if isinstance(value, auto):
- if value.value == _auto_null:
- value.value = self._generate_next_value(
- key,
- 1,
- len(self._member_names),
- self._last_values[:],
- )
- self._auto_called = True
- value = value.value
- self._member_names.append(key)
- self._last_values.append(value)
- super().__setitem__(key, value)
-
-
-# Dummy value for Enum as EnumMeta explicitly checks for it, but of course
-# until EnumMeta finishes running the first time the Enum class doesn't exist.
-# This is also why there are checks in EnumMeta like `if Enum is not None`
-Enum = None
-
-class EnumMeta(type):
- """
- Metaclass for Enum
- """
- @classmethod
- def __prepare__(metacls, cls, bases, **kwds):
- # check that previous enum members do not exist
- metacls._check_for_existing_members(cls, bases)
- # create the namespace dict
- enum_dict = _EnumDict()
- enum_dict._cls_name = cls
- # inherit previous flags and _generate_next_value_ function
- member_type, first_enum = metacls._get_mixins_(cls, bases)
- if first_enum is not None:
- enum_dict['_generate_next_value_'] = getattr(
- first_enum, '_generate_next_value_', None,
- )
- return enum_dict
-
- def __new__(metacls, cls, bases, classdict, **kwds):
- # an Enum class is final once enumeration items have been defined; it
- # cannot be mixed with other types (int, float, etc.) if it has an
- # inherited __new__ unless a new __new__ is defined (or the resulting
- # class will fail).
- #
- # remove any keys listed in _ignore_
- classdict.setdefault('_ignore_', []).append('_ignore_')
- ignore = classdict['_ignore_']
- for key in ignore:
- classdict.pop(key, None)
- member_type, first_enum = metacls._get_mixins_(cls, bases)
- __new__, save_new, use_args = metacls._find_new_(
- classdict, member_type, first_enum,
- )
-
- # save enum items into separate mapping so they don't get baked into
- # the new class
- enum_members = {k: classdict[k] for k in classdict._member_names}
- for name in classdict._member_names:
- del classdict[name]
-
- # adjust the sunders
- _order_ = classdict.pop('_order_', None)
-
- # check for illegal enum names (any others?)
- invalid_names = set(enum_members) & {'mro', ''}
- if invalid_names:
- raise ValueError('Invalid enum member name: {0}'.format(
- ','.join(invalid_names)))
-
- # create a default docstring if one has not been provided
- if '__doc__' not in classdict:
- classdict['__doc__'] = 'An enumeration.'
-
- enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
- enum_class._member_names_ = [] # names in definition order
- enum_class._member_map_ = {} # name->value map
- enum_class._member_type_ = member_type
-
- # save DynamicClassAttribute attributes from super classes so we know
- # if we can take the shortcut of storing members in the class dict
- dynamic_attributes = {
- k for c in enum_class.mro()
- for k, v in c.__dict__.items()
- if isinstance(v, DynamicClassAttribute)
- }
-
- # Reverse value->name map for hashable values.
- enum_class._value2member_map_ = {}
-
- # If a custom type is mixed into the Enum, and it does not know how
- # to pickle itself, pickle.dumps will succeed but pickle.loads will
- # fail. Rather than have the error show up later and possibly far
- # from the source, sabotage the pickle protocol for this class so
- # that pickle.dumps also fails.
- #
- # However, if the new class implements its own __reduce_ex__, do not
- # sabotage -- it's on them to make sure it works correctly. We use
- # __reduce_ex__ instead of any of the others as it is preferred by
- # pickle over __reduce__, and it handles all pickle protocols.
- if '__reduce_ex__' not in classdict:
- if member_type is not object:
- methods = ('__getnewargs_ex__', '__getnewargs__',
- '__reduce_ex__', '__reduce__')
- if not any(m in member_type.__dict__ for m in methods):
- if '__new__' in classdict:
- # too late, sabotage
- _make_class_unpicklable(enum_class)
- else:
- # final attempt to verify that pickling would work:
- # travel mro until __new__ is found, checking for
- # __reduce__ and friends along the way -- if any of them
- # are found before/when __new__ is found, pickling should
- # work
- sabotage = None
- for chain in bases:
- for base in chain.__mro__:
- if base is object:
- continue
- elif any(m in base.__dict__ for m in methods):
- # found one, we're good
- sabotage = False
- break
- elif '__new__' in base.__dict__:
- # not good
- sabotage = True
- break
- if sabotage is not None:
- break
- if sabotage:
- _make_class_unpicklable(enum_class)
- # instantiate them, checking for duplicates as we go
- # we instantiate first instead of checking for duplicates first in case
- # a custom __new__ is doing something funky with the values -- such as
- # auto-numbering ;)
- for member_name in classdict._member_names:
- value = enum_members[member_name]
- if not isinstance(value, tuple):
- args = (value, )
- else:
- args = value
- if member_type is tuple: # special case for tuple enums
- args = (args, ) # wrap it one more time
- if not use_args:
- enum_member = __new__(enum_class)
- if not hasattr(enum_member, '_value_'):
- enum_member._value_ = value
- else:
- enum_member = __new__(enum_class, *args)
- if not hasattr(enum_member, '_value_'):
- if member_type is object:
- enum_member._value_ = value
- else:
- enum_member._value_ = member_type(*args)
- value = enum_member._value_
- enum_member._name_ = member_name
- enum_member.__objclass__ = enum_class
- enum_member.__init__(*args)
- # If another member with the same value was already defined, the
- # new member becomes an alias to the existing one.
- for name, canonical_member in enum_class._member_map_.items():
- if canonical_member._value_ == enum_member._value_:
- enum_member = canonical_member
- break
- else:
- # Aliases don't appear in member names (only in __members__).
- enum_class._member_names_.append(member_name)
- # performance boost for any member that would not shadow
- # a DynamicClassAttribute
- if member_name not in dynamic_attributes:
- setattr(enum_class, member_name, enum_member)
- # now add to _member_map_
- enum_class._member_map_[member_name] = enum_member
- try:
- # This may fail if value is not hashable. We can't add the value
- # to the map, and by-value lookups for this value will be
- # linear.
- enum_class._value2member_map_[value] = enum_member
- except TypeError:
- pass
-
- # double check that repr and friends are not the mixin's or various
- # things break (such as pickle)
- # however, if the method is defined in the Enum itself, don't replace
- # it
- for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):
- if name in classdict:
- continue
- class_method = getattr(enum_class, name)
- obj_method = getattr(member_type, name, None)
- enum_method = getattr(first_enum, name, None)
- if obj_method is not None and obj_method is class_method:
- setattr(enum_class, name, enum_method)
-
- # replace any other __new__ with our own (as long as Enum is not None,
- # anyway) -- again, this is to support pickle
- if Enum is not None:
- # if the user defined their own __new__, save it before it gets
- # clobbered in case they subclass later
- if save_new:
- enum_class.__new_member__ = __new__
- enum_class.__new__ = Enum.__new__
-
- # py3 support for definition order (helps keep py2/py3 code in sync)
- if _order_ is not None:
- if isinstance(_order_, str):
- _order_ = _order_.replace(',', ' ').split()
- if _order_ != enum_class._member_names_:
- raise TypeError('member order does not match _order_')
-
- return enum_class
-
- def __bool__(self):
- """
- classes/types should always be True.
- """
- return True
-
- def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
- """
- Either returns an existing member, or creates a new enum class.
-
- This method is used both when an enum class is given a value to match
- to an enumeration member (i.e. Color(3)) and for the functional API
- (i.e. Color = Enum('Color', names='RED GREEN BLUE')).
-
- When used for the functional API:
-
- `value` will be the name of the new class.
-
- `names` should be either a string of white-space/comma delimited names
- (values will start at `start`), or an iterator/mapping of name, value pairs.
-
- `module` should be set to the module this class is being created in;
- if it is not set, an attempt to find that module will be made, but if
- it fails the class will not be picklable.
-
- `qualname` should be set to the actual location this class can be found
- at in its module; by default it is set to the global scope. If this is
- not correct, unpickling will fail in some circumstances.
-
- `type`, if set, will be mixed in as the first base class.
- """
- if names is None: # simple value lookup
- return cls.__new__(cls, value)
- # otherwise, functional API: we're creating a new Enum type
- return cls._create_(
- value,
- names,
- module=module,
- qualname=qualname,
- type=type,
- start=start,
- )
-
- def __contains__(cls, obj):
- if not isinstance(obj, Enum):
- import warnings
- warnings.warn(
- "in 3.12 __contains__ will no longer raise TypeError, but will return True if\n"
- "obj is a member or a member's value",
- DeprecationWarning,
- stacklevel=2,
- )
- raise TypeError(
- "unsupported operand type(s) for 'in': '%s' and '%s'" % (
- type(obj).__qualname__, cls.__class__.__qualname__))
- return isinstance(obj, cls) and obj._name_ in cls._member_map_
-
- def __delattr__(cls, attr):
- # nicer error message when someone tries to delete an attribute
- # (see issue19025).
- if attr in cls._member_map_:
- raise AttributeError("%s: cannot delete Enum member." % cls.__name__)
- super().__delattr__(attr)
-
- def __dir__(self):
- return (
- ['__class__', '__doc__', '__members__', '__module__']
- + self._member_names_
- )
-
- def __getattr__(cls, name):
- """
- Return the enum member matching `name`
-
- We use __getattr__ instead of descriptors or inserting into the enum
- class' __dict__ in order to support `name` and `value` being both
- properties for enum members (which live in the class' __dict__) and
- enum members themselves.
- """
- if _is_dunder(name):
- raise AttributeError(name)
- try:
- return cls._member_map_[name]
- except KeyError:
- raise AttributeError(name) from None
-
- def __getitem__(cls, name):
- return cls._member_map_[name]
-
- def __iter__(cls):
- """
- Returns members in definition order.
- """
- return (cls._member_map_[name] for name in cls._member_names_)
-
- def __len__(cls):
- return len(cls._member_names_)
-
- @property
- def __members__(cls):
- """
- Returns a mapping of member name->value.
-
- This mapping lists all enum members, including aliases. Note that this
- is a read-only view of the internal mapping.
- """
- return MappingProxyType(cls._member_map_)
-
- def __repr__(cls):
- return "<enum %r>" % cls.__name__
-
- def __reversed__(cls):
- """
- Returns members in reverse definition order.
- """
- return (cls._member_map_[name] for name in reversed(cls._member_names_))
-
- def __setattr__(cls, name, value):
- """
- Block attempts to reassign Enum members.
-
- A simple assignment to the class namespace only changes one of the
- several possible ways to get an Enum member from the Enum class,
- resulting in an inconsistent Enumeration.
- """
- member_map = cls.__dict__.get('_member_map_', {})
- if name in member_map:
- raise AttributeError('Cannot reassign members.')
- super().__setattr__(name, value)
-
- def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
- """
- Convenience method to create a new Enum class.
-
- `names` can be:
-
- * A string containing member names, separated either with spaces or
- commas. Values are incremented by 1 from `start`.
- * An iterable of member names. Values are incremented by 1 from `start`.
- * An iterable of (member name, value) pairs.
- * A mapping of member name -> value pairs.
- """
- metacls = cls.__class__
- bases = (cls, ) if type is None else (type, cls)
- _, first_enum = cls._get_mixins_(cls, bases)
- classdict = metacls.__prepare__(class_name, bases)
-
- # special processing needed for names?
- if isinstance(names, str):
- names = names.replace(',', ' ').split()
- if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
- original_names, names = names, []
- last_values = []
- for count, name in enumerate(original_names):
- value = first_enum._generate_next_value_(name, start, count, last_values[:])
- last_values.append(value)
- names.append((name, value))
-
- # Here, names is either an iterable of (name, value) or a mapping.
- for item in names:
- if isinstance(item, str):
- member_name, member_value = item, names[item]
- else:
- member_name, member_value = item
- classdict[member_name] = member_value
- enum_class = metacls.__new__(metacls, class_name, bases, classdict)
-
- # TODO: replace the frame hack if a blessed way to know the calling
- # module is ever developed
- if module is None:
- try:
- module = sys._getframe(2).f_globals['__name__']
- except (AttributeError, ValueError, KeyError):
- pass
- if module is None:
- _make_class_unpicklable(enum_class)
- else:
- enum_class.__module__ = module
- if qualname is not None:
- enum_class.__qualname__ = qualname
-
- return enum_class
-
- def _convert_(cls, name, module, filter, source=None):
- """
- Create a new Enum subclass that replaces a collection of global constants
- """
- # convert all constants from source (or module) that pass filter() to
- # a new Enum called name, and export the enum and its members back to
- # module;
- # also, replace the __reduce_ex__ method so unpickling works in
- # previous Python versions
- module_globals = vars(sys.modules[module])
- if source:
- source = vars(source)
- else:
- source = module_globals
- # _value2member_map_ is populated in the same order every time
- # for a consistent reverse mapping of number to name when there
- # are multiple names for the same number.
- members = [
- (name, value)
- for name, value in source.items()
- if filter(name)]
- try:
- # sort by value
- members.sort(key=lambda t: (t[1], t[0]))
- except TypeError:
- # unless some values aren't comparable, in which case sort by name
- members.sort(key=lambda t: t[0])
- cls = cls(name, members, module=module)
- cls.__reduce_ex__ = _reduce_ex_by_name
- module_globals.update(cls.__members__)
- module_globals[name] = cls
- return cls
-
- @staticmethod
- def _check_for_existing_members(class_name, bases):
- for chain in bases:
- for base in chain.__mro__:
- if issubclass(base, Enum) and base._member_names_:
- raise TypeError(
- "%s: cannot extend enumeration %r"
- % (class_name, base.__name__)
- )
-
- @staticmethod
- def _get_mixins_(class_name, bases):
- """
- Returns the type for creating enum members, and the first inherited
- enum class.
-
- bases: the tuple of bases that was given to __new__
- """
- if not bases:
- return object, Enum
-
- def _find_data_type(bases):
- data_types = set()
- for chain in bases:
- candidate = None
- for base in chain.__mro__:
- if base is object:
- continue
- elif issubclass(base, Enum):
- if base._member_type_ is not object:
- data_types.add(base._member_type_)
- break
- elif '__new__' in base.__dict__:
- if issubclass(base, Enum):
- continue
- data_types.add(candidate or base)
- break
- else:
- candidate = candidate or base
- if len(data_types) > 1:
- raise TypeError('%r: too many data types: %r' % (class_name, data_types))
- elif data_types:
- return data_types.pop()
- else:
- return None
-
- # ensure final parent class is an Enum derivative, find any concrete
- # data type, and check that Enum has no members
- first_enum = bases[-1]
- if not issubclass(first_enum, Enum):
- raise TypeError("new enumerations should be created as "
- "`EnumName([mixin_type, ...] [data_type,] enum_type)`")
- member_type = _find_data_type(bases) or object
- if first_enum._member_names_:
- raise TypeError("Cannot extend enumerations")
- return member_type, first_enum
-
- @staticmethod
- def _find_new_(classdict, member_type, first_enum):
- """
- Returns the __new__ to be used for creating the enum members.
-
- classdict: the class dictionary given to __new__
- member_type: the data type whose __new__ will be used by default
- first_enum: enumeration to check for an overriding __new__
- """
- # now find the correct __new__, checking to see of one was defined
- # by the user; also check earlier enum classes in case a __new__ was
- # saved as __new_member__
- __new__ = classdict.get('__new__', None)
-
- # should __new__ be saved as __new_member__ later?
- save_new = __new__ is not None
-
- if __new__ is None:
- # check all possibles for __new_member__ before falling back to
- # __new__
- for method in ('__new_member__', '__new__'):
- for possible in (member_type, first_enum):
- target = getattr(possible, method, None)
- if target not in {
- None,
- None.__new__,
- object.__new__,
- Enum.__new__,
- }:
- __new__ = target
- break
- if __new__ is not None:
- break
- else:
- __new__ = object.__new__
-
- # if a non-object.__new__ is used then whatever value/tuple was
- # assigned to the enum member name will be passed to __new__ and to the
- # new enum member's __init__
- if __new__ is object.__new__:
- use_args = False
- else:
- use_args = True
- return __new__, save_new, use_args
-
-
-class Enum(metaclass=EnumMeta):
- """
- Generic enumeration.
-
- Derive from this class to define new enumerations.
- """
- def __new__(cls, value):
- # all enum instances are actually created during class construction
- # without calling this method; this method is called by the metaclass'
- # __call__ (i.e. Color(3) ), and by pickle
- if type(value) is cls:
- # For lookups like Color(Color.RED)
- return value
- # by-value search for a matching enum member
- # see if it's in the reverse mapping (for hashable values)
- try:
- return cls._value2member_map_[value]
- except KeyError:
- # Not found, no need to do long O(n) search
- pass
- except TypeError:
- # not there, now do long search -- O(n) behavior
- for member in cls._member_map_.values():
- if member._value_ == value:
- return member
- # still not found -- try _missing_ hook
- try:
- exc = None
- result = cls._missing_(value)
- except Exception as e:
- exc = e
- result = None
- try:
- if isinstance(result, cls):
- return result
- else:
- ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
- if result is None and exc is None:
- raise ve_exc
- elif exc is None:
- exc = TypeError(
- 'error in %s._missing_: returned %r instead of None or a valid member'
- % (cls.__name__, result)
- )
- if not isinstance(exc, ValueError):
- exc.__context__ = ve_exc
- raise exc
- finally:
- # ensure all variables that could hold an exception are destroyed
- exc = None
- ve_exc = None
-
- def _generate_next_value_(name, start, count, last_values):
- """
- Generate the next value when not given.
-
- name: the name of the member
- start: the initial start value or None
- count: the number of existing members
- last_value: the last value assigned or None
- """
- for last_value in reversed(last_values):
- try:
- return last_value + 1
- except TypeError:
- pass
- else:
- return start
-
- @classmethod
- def _missing_(cls, value):
- return None
-
- def __repr__(self):
- return "<%s.%s: %r>" % (
- self.__class__.__name__, self._name_, self._value_)
-
- def __str__(self):
- return "%s.%s" % (self.__class__.__name__, self._name_)
-
- def __dir__(self):
- """
- Returns all members and all public methods
- """
- added_behavior = [
- m
- for cls in self.__class__.mro()
- for m in cls.__dict__
- if m[0] != '_' and m not in self._member_map_
- ] + [m for m in self.__dict__ if m[0] != '_']
- return (['__class__', '__doc__', '__module__'] + added_behavior)
-
- def __format__(self, format_spec):
- """
- Returns format using actual value type unless __str__ has been overridden.
- """
- # mixed-in Enums should use the mixed-in type's __format__, otherwise
- # we can get strange results with the Enum name showing up instead of
- # the value
-
- # pure Enum branch, or branch with __str__ explicitly overridden
- str_overridden = type(self).__str__ not in (Enum.__str__, Flag.__str__)
- if self._member_type_ is object or str_overridden:
- cls = str
- val = str(self)
- # mix-in branch
- else:
- cls = self._member_type_
- val = self._value_
- return cls.__format__(val, format_spec)
-
- def __hash__(self):
- return hash(self._name_)
-
- def __reduce_ex__(self, proto):
- return self.__class__, (self._value_, )
-
- # DynamicClassAttribute is used to provide access to the `name` and
- # `value` properties of enum members while keeping some measure of
- # protection from modification, while still allowing for an enumeration
- # to have members named `name` and `value`. This works because enumeration
- # members are not set directly on the enum class -- __getattr__ is
- # used to look them up.
-
- @DynamicClassAttribute
- def name(self):
- """The name of the Enum member."""
- return self._name_
-
- @DynamicClassAttribute
- def value(self):
- """The value of the Enum member."""
- return self._value_
-
-
-class IntEnum(int, Enum):
- """Enum where members are also (and must be) ints"""
-
-
-def _reduce_ex_by_name(self, proto):
- return self.name
-
-class Flag(Enum):
- """
- Support for flags
- """
-
- def _generate_next_value_(name, start, count, last_values):
- """
- Generate the next value when not given.
-
- name: the name of the member
- start: the initial start value or None
- count: the number of existing members
- last_value: the last value assigned or None
- """
- if not count:
- return start if start is not None else 1
- for last_value in reversed(last_values):
- try:
- high_bit = _high_bit(last_value)
- break
- except Exception:
- raise TypeError('Invalid Flag value: %r' % last_value) from None
- return 2 ** (high_bit+1)
-
- @classmethod
- def _missing_(cls, value):
- """
- Returns member (possibly creating it) if one can be found for value.
- """
- original_value = value
- if value < 0:
- value = ~value
- possible_member = cls._create_pseudo_member_(value)
- if original_value < 0:
- possible_member = ~possible_member
- return possible_member
-
- @classmethod
- def _create_pseudo_member_(cls, value):
- """
- Create a composite member iff value contains only members.
- """
- pseudo_member = cls._value2member_map_.get(value, None)
- if pseudo_member is None:
- # verify all bits are accounted for
- _, extra_flags = _decompose(cls, value)
- if extra_flags:
- raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
- # construct a singleton enum pseudo-member
- pseudo_member = object.__new__(cls)
- pseudo_member._name_ = None
- pseudo_member._value_ = value
- # use setdefault in case another thread already created a composite
- # with this value
- pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
- return pseudo_member
-
- def __contains__(self, other):
- """
- Returns True if self has at least the same flags set as other.
- """
- if not isinstance(other, self.__class__):
- raise TypeError(
- "unsupported operand type(s) for 'in': '%s' and '%s'" % (
- type(other).__qualname__, self.__class__.__qualname__))
- return other._value_ & self._value_ == other._value_
-
- def __repr__(self):
- cls = self.__class__
- if self._name_ is not None:
- return '<%s.%s: %r>' % (cls.__name__, self._name_, self._value_)
- members, uncovered = _decompose(cls, self._value_)
- return '<%s.%s: %r>' % (
- cls.__name__,
- '|'.join([str(m._name_ or m._value_) for m in members]),
- self._value_,
- )
-
- def __str__(self):
- cls = self.__class__
- if self._name_ is not None:
- return '%s.%s' % (cls.__name__, self._name_)
- members, uncovered = _decompose(cls, self._value_)
- if len(members) == 1 and members[0]._name_ is None:
- return '%s.%r' % (cls.__name__, members[0]._value_)
- else:
- return '%s.%s' % (
- cls.__name__,
- '|'.join([str(m._name_ or m._value_) for m in members]),
- )
-
- def __bool__(self):
- return bool(self._value_)
-
- def __or__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.__class__(self._value_ | other._value_)
-
- def __and__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.__class__(self._value_ & other._value_)
-
- def __xor__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.__class__(self._value_ ^ other._value_)
-
- def __invert__(self):
- members, uncovered = _decompose(self.__class__, self._value_)
- inverted = self.__class__(0)
- for m in self.__class__:
- if m not in members and not (m._value_ & self._value_):
- inverted = inverted | m
- return self.__class__(inverted)
-
-
-class IntFlag(int, Flag):
- """
- Support for integer-based Flags
- """
-
- @classmethod
- def _missing_(cls, value):
- """
- Returns member (possibly creating it) if one can be found for value.
- """
- if not isinstance(value, int):
- raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
- new_member = cls._create_pseudo_member_(value)
- return new_member
-
- @classmethod
- def _create_pseudo_member_(cls, value):
- """
- Create a composite member iff value contains only members.
- """
- pseudo_member = cls._value2member_map_.get(value, None)
- if pseudo_member is None:
- need_to_create = [value]
- # get unaccounted for bits
- _, extra_flags = _decompose(cls, value)
- # timer = 10
- while extra_flags:
- # timer -= 1
- bit = _high_bit(extra_flags)
- flag_value = 2 ** bit
- if (flag_value not in cls._value2member_map_ and
- flag_value not in need_to_create
- ):
- need_to_create.append(flag_value)
- if extra_flags == -flag_value:
- extra_flags = 0
- else:
- extra_flags ^= flag_value
- for value in reversed(need_to_create):
- # construct singleton pseudo-members
- pseudo_member = int.__new__(cls, value)
- pseudo_member._name_ = None
- pseudo_member._value_ = value
- # use setdefault in case another thread already created a composite
- # with this value
- pseudo_member = cls._value2member_map_.setdefault(value, pseudo_member)
- return pseudo_member
-
- def __or__(self, other):
- if not isinstance(other, (self.__class__, int)):
- return NotImplemented
- result = self.__class__(self._value_ | self.__class__(other)._value_)
- return result
-
- def __and__(self, other):
- if not isinstance(other, (self.__class__, int)):
- return NotImplemented
- return self.__class__(self._value_ & self.__class__(other)._value_)
-
- def __xor__(self, other):
- if not isinstance(other, (self.__class__, int)):
- return NotImplemented
- return self.__class__(self._value_ ^ self.__class__(other)._value_)
-
- __ror__ = __or__
- __rand__ = __and__
- __rxor__ = __xor__
-
- def __invert__(self):
- result = self.__class__(~self._value_)
- return result
-
-
-def _high_bit(value):
- """
- returns index of highest bit, or -1 if value is zero or negative
- """
- return value.bit_length() - 1
-
-def unique(enumeration):
- """
- Class decorator for enumerations ensuring unique member values.
- """
- duplicates = []
- for name, member in enumeration.__members__.items():
- if name != member.name:
- duplicates.append((name, member.name))
- if duplicates:
- alias_details = ', '.join(
- ["%s -> %s" % (alias, name) for (alias, name) in duplicates])
- raise ValueError('duplicate values found in %r: %s' %
- (enumeration, alias_details))
- return enumeration
-
-def _decompose(flag, value):
- """
- Extract all members from the value.
- """
- # _decompose is only called if the value is not named
- not_covered = value
- negative = value < 0
- members = []
- for member in flag:
- member_value = member.value
- if member_value and member_value & value == member_value:
- members.append(member)
- not_covered &= ~member_value
- if not negative:
- tmp = not_covered
- while tmp:
- flag_value = 2 ** _high_bit(tmp)
- if flag_value in flag._value2member_map_:
- members.append(flag._value2member_map_[flag_value])
- not_covered &= ~flag_value
- tmp &= ~flag_value
- if not members and value in flag._value2member_map_:
- members.append(flag._value2member_map_[value])
- members.sort(key=lambda m: m._value_, reverse=True)
- if len(members) > 1 and members[0].value == value:
- # we have the breakdown, don't need the value member itself
- members.pop(0)
- return members, not_covered
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
index a08143968..7147a4148 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
@@ -1,6 +1,5 @@
{
"files": ["__init__.py",
- "enum_310.py",
"feature.py",
"fix-complaints.py",
"signature/__init__.py",
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index 2fd2b6c4f..94e2143f2 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
@@ -236,7 +236,7 @@ def create_signature(props, key):
# parser.
pass
else:
- if varnames[0] in ("self", "cls"):
+ if varnames and varnames[0] in ("self", "cls"):
varnames = varnames[1:]
# calculate the modifications
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
index e7184fa25..6cd402de3 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
@@ -175,7 +175,9 @@ class ExactEnumerator(object):
self.collision_track.add(thing_name)
init_signature = getattr(klass, "__signature__", None)
- enums.sort(key=lambda tup: tup[1 : 3]) # sort by class then enum value
+ new_enum = sys.pyside63_option_python_enum
+ # sort by class then enum value
+ enums.sort(key=lambda tup: (tup[1], tup[2].value if new_enum else tup[2]))
# We want to handle functions and properties together.
func_prop = sorted(functions + properties, key=lambda tup: tup[0])
@@ -192,7 +194,8 @@ class ExactEnumerator(object):
if len(enums):
self.section()
for enum_name, enum_class_name, value in enums:
- with self.fmt.enum(enum_class_name, enum_name, int(value)):
+ with self.fmt.enum(enum_class_name, enum_name,
+ value.value if new_enum else value):
pass
if len(subclasses):
self.section()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
index c28683810..4b2316af5 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
@@ -148,13 +148,8 @@ from shibokensupport.signature import importhandler
from shibokensupport.signature.lib import enum_sig
from shibokensupport.signature.lib import pyi_generator
from shibokensupport.signature.lib import tool
-if sys.version_info[:2] < (3, 10):
- # PYSIDE-1735: Use the faster and more complete enum implementation.
- from shibokensupport import enum_310 as enum
- sys.modules["enum"] = enum
- # compatibility
- if sys.version_info[:2] < (3, 8):
- enum.Enum._convert = classmethod(enum.EnumMeta._convert_)
+
+import enum
if "PySide6" in sys.modules:
# We publish everything under "PySide6.support", again.
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 63cb423c1..f1148eaaf 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -61,7 +61,7 @@ class ellipsis(object):
return "..."
ellipsis = ellipsis()
-Point = typing.Tuple[float, float]
+Point = typing.Tuple[int, int]
Variant = typing.Any
QImageCleanupFunction = typing.Callable
@@ -318,6 +318,8 @@ type_map.update({
"zero(str)": "",
"zero(typing.Any)": None,
"zero(Any)": None,
+ # This can be refined by importing numpy.typing optionally, but better than nothing.
+ "numpy.ndarray": typing.List[typing.Any],
})
type_map.update({
@@ -692,9 +694,20 @@ def init_PySide6_QtBluetooth():
return locals()
+def init_PySide6_QtHttpServer():
+ type_map.update({
+ "qMakePair(1u, 1u)": (1, 1),
+ })
+ return locals()
+
+
def init_testbinding():
type_map.update({
"testbinding.PySideCPP2.TestObjectWithoutNamespace": testbinding.TestObjectWithoutNamespace,
+ "testbinding.FlagsNamespace.Options": testbinding.Option,
+ "FlagsNamespace.Option.NoOptions": 0,
+ "StdIntList": typing.List[int],
+ 'Str("")': str(""),
})
return locals()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index 1d4dadc55..9674ca769 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -37,6 +37,7 @@
##
#############################################################################
+import ast
import enum
import functools
import keyword
@@ -94,31 +95,32 @@ def _get_flag_enum_option():
flag = True
elif opt in ("no", "off", "false"):
flag = False
- elif opt.isnumeric():
- flag = bool(int(opt))
+ else:
+ # instead of a simple int() conversion, let's allow for "0xf" or "0b1111"
+ try:
+ flag = ast.literal_eval(opt)
+ except Exception:
+ flag = True
elif hasattr(sys, sysname):
- flag = bool(getattr(sys, sysname))
+ flag = getattr(sys, sysname)
+ if not isinstance(flag, int):
+ flag = True
+ p = f"\n *** Python is at version {'.'.join(map(str, pyminver))} now."
# PYSIDE-1797: Emit a warning when we may remove pep384_issue33738.cpp
if pyminver and pyminver >= (3, 8):
- warnings.warn(f"\n *** Python is at version {'.'.join(map(str, pyminver))} now. "
- f"The file pep384_issue33738.cpp should be removed ASAP! ***")
+ warnings.warn(f"{p} The file pep384_issue33738.cpp should be removed ASAP! ***")
+ # _PepUnicode_AsString: Fix a broken promise
+ if pyminver and pyminver >= (3, 10):
+ warnings.warn(f"{p} _PepUnicode_AsString can now be replaced by PyUnicode_AsUTF8! ***")
# PYSIDE-1960: Emit a warning when we may remove pep384_issue33738.cpp
if pyminver and pyminver >= (3, 11):
- warnings.warn(f"\n *** Python is at version {'.'.join(map(str, pyminver))} now. "
- f"The files bufferprocs_py37.(cpp|h) should be removed ASAP! ***")
- # PYSIDE-1735: Emit a warning when we may update enum_310.py
- if pymaxver and pymaxver > (3, 10):
- if sys.version_info >= (3, 11, 0) and sys.version_info.releaselevel == "final":
- warnings.warn(f"\n *** Python is at version {'.'.join(map(str, pymaxver))} now. "
- f"Please check if enum_310.py should be updated! ***")
- # PYSIDE-1735: Emit a warning when we may update enum_310.py
+ warnings.warn(f"{p} The files bufferprocs_py37.(cpp|h) should be removed ASAP! ***")
+ # PYSIDE-1735: Emit a warning when we should maybe evict forgiveness mode
if ver[:2] >= (7, 0):
- warnings.warn(f"\n *** PySide is at version {'.'.join(map(str, ver[:2]))} now. "
- f"Please drop the forgiving Enum behavior in `mangled_type_getattro` ***")
- # modify the sys attribute to bool
+ warnings.warn(f"{p} Please drop Enum forgiveness mode in `mangled_type_getattro` ***")
+ # normalize the sys attribute
setattr(sys, sysname, flag)
- # modify the env attribute to "0" or "1"
- os.environ[envname] = str(int(flag))
+ os.environ[envname] = str(flag)
return flag
@@ -434,18 +436,6 @@ def handle_retvar(obj):
def calculate_props(line):
- # PYSIDE-1735: QFlag is now divided into fields for future Python Enums, like
- # "PySide.QtCore.^^Qt.ItemFlags^^Qt.ItemFlag^^"
- # Resolve that until Enum is finally settled.
- while "^^" in line:
- parts = line.split("^^", 3)
- selected = EnumSelect.SELECTION
- line = parts[0] + parts[selected.value] + parts[3]
- if selected is EnumSelect.NEW:
- _old, _new = EnumSelect.OLD.value, EnumSelect.NEW.value
- line = re.sub(rf"\b{parts[_old]}\b", parts[_new], line)
- type_map[parts[_old]] = parts[_new]
-
parsed = SimpleNamespace(**_parse_line(line.strip()))
arglist = parsed.arglist
annotations = {}
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
index e261bf271..0f05aea8b 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
@@ -3,7 +3,7 @@
"Name": "Python",
"QDocModule": "QtForPython",
"QtUsage": "Used for Qt for Python in the signature extension.",
- "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files (enum_310.py). See the folder sources/shiboken6/files.dir/shibokensupport .",
+ "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files. See the folder sources/shiboken6/files.dir/shibokensupport .",
"Homepage": "http://www.python.org/",
"Version": "3.7.0",
"LicenseId": "Python-2.0",
diff --git a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
index 5bc361644..34079eb44 100644
--- a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
+++ b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml
@@ -29,7 +29,7 @@
</inject-code>
</add-function>
- <add-function signature="getCppPointer(PyObject*)" return-type="PyObject*">
+ <add-function signature="getCppPointer(PyObject*)" return-type="PySequence*">
<inject-code>
if (Shiboken::Object::checkType(%1)) {
std::vector&lt;void*> ptrs = Shiboken::Object::cppPointers(reinterpret_cast&lt;SbkObject *&gt;(%1));
@@ -74,7 +74,7 @@
</inject-code>
</add-function>
- <add-function signature="dump(PyObject*)" return-type="PyObject*">
+ <add-function signature="dump(PyObject*)" return-type="const char *">
<inject-code>
if (!Shiboken::Object::checkType(%1)) {
%PYARG_0 = Shiboken::String::fromCString("Ordinary Python type.");
@@ -85,19 +85,18 @@
</inject-code>
</add-function>
- <add-function signature="getAllValidWrappers(void)" return-type="PyObject*">
+ <add-function signature="getAllValidWrappers(void)" return-type="PySequence*">
<inject-code>
- std::set&lt;PyObject*&gt; setAll = Shiboken::BindingManager::instance().getAllPyObjects();
+ const auto setAll = Shiboken::BindingManager::instance().getAllPyObjects();
PyObject* listAll = PyList_New(0);
- if (listAll == NULL)
- return NULL;
+ if (listAll == nullptr)
+ return nullptr;
- const std::set&lt;PyObject*&gt;::iterator end = setAll.end();
- for (std::set&lt;PyObject*&gt;::iterator iter = setAll.begin(); iter != end; ++iter) {
- if (*iter != NULL) {
- if (PyList_Append(listAll, *iter) != 0) {
+ for (auto *o : setAll) {
+ if (o != nullptr) {
+ if (PyList_Append(listAll, o) != 0) {
Py_DECREF(listAll);
- return NULL;
+ return nullptr;
}
}
}
diff --git a/sources/shiboken6/tests/libsample/abstract.cpp b/sources/shiboken6/tests/libsample/abstract.cpp
index 3b2b1ef0a..3f2849cd3 100644
--- a/sources/shiboken6/tests/libsample/abstract.cpp
+++ b/sources/shiboken6/tests/libsample/abstract.cpp
@@ -91,7 +91,7 @@ void Abstract::callVirtualGettingEnum(PrintFormat p)
virtualGettingAEnum(p);
}
-void Abstract::virtualGettingAEnum(Abstract::PrintFormat p)
+void Abstract::virtualGettingAEnum(Abstract::PrintFormat)
{
}
diff --git a/sources/shiboken6/tests/libsample/bytearray.cpp b/sources/shiboken6/tests/libsample/bytearray.cpp
index 021d2a079..ee1e1ca93 100644
--- a/sources/shiboken6/tests/libsample/bytearray.cpp
+++ b/sources/shiboken6/tests/libsample/bytearray.cpp
@@ -57,13 +57,6 @@ ByteArray::ByteArray(const char* data, int len)
m_data[len] = '\0';
}
-ByteArray::ByteArray(const ByteArray& other)
-{
- m_data = std::vector<char>(other.size() + 1);
- memcpy(&m_data[0], &other.m_data[0], other.size());
- m_data[other.size()] = '\0';
-}
-
int
ByteArray::size() const
{
diff --git a/sources/shiboken6/tests/libsample/bytearray.h b/sources/shiboken6/tests/libsample/bytearray.h
index 5dfb63fd5..a6bb4c6c6 100644
--- a/sources/shiboken6/tests/libsample/bytearray.h
+++ b/sources/shiboken6/tests/libsample/bytearray.h
@@ -40,7 +40,6 @@ public:
ByteArray(char data);
ByteArray(const char* data);
ByteArray(const char* data, int len);
- ByteArray(const ByteArray& other);
int size() const;
char at(int i) const;
diff --git a/sources/shiboken6/tests/libsample/derived.cpp b/sources/shiboken6/tests/libsample/derived.cpp
index 0dc026876..62b6669de 100644
--- a/sources/shiboken6/tests/libsample/derived.cpp
+++ b/sources/shiboken6/tests/libsample/derived.cpp
@@ -74,26 +74,22 @@ Derived::defaultValue(int n)
return ((double) n) + 0.1;
}
-OverloadedFuncEnum
-Derived::overloaded(int i, int d)
+OverloadedFuncEnum Derived::overloaded(int, int)
{
return OverloadedFunc_ii;
}
-OverloadedFuncEnum
-Derived::overloaded(double n)
+OverloadedFuncEnum Derived::overloaded(double)
{
return OverloadedFunc_d;
}
-Derived::OtherOverloadedFuncEnum
-Derived::otherOverloaded(int a, int b, bool c, double d)
+Derived::OtherOverloadedFuncEnum Derived::otherOverloaded(int, int, bool, double)
{
return OtherOverloadedFunc_iibd;
}
-Derived::OtherOverloadedFuncEnum
-Derived::otherOverloaded(int a, double b)
+Derived::OtherOverloadedFuncEnum Derived::otherOverloaded(int, double)
{
return OtherOverloadedFunc_id;
}
diff --git a/sources/shiboken6/tests/libsample/derived.h b/sources/shiboken6/tests/libsample/derived.h
index 783a6dc50..27fa11668 100644
--- a/sources/shiboken6/tests/libsample/derived.h
+++ b/sources/shiboken6/tests/libsample/derived.h
@@ -49,7 +49,7 @@ public:
public:
void uselessMethod() {}
SomeInnerClass operator+(const SomeInnerClass& other) { return other; }
- bool operator==(const SomeInnerClass& other) { return true; }
+ bool operator==(const SomeInnerClass &) { return true; }
};
Derived(int id = -1);
diff --git a/sources/shiboken6/tests/libsample/echo.h b/sources/shiboken6/tests/libsample/echo.h
index 3f645694a..db86a494f 100644
--- a/sources/shiboken6/tests/libsample/echo.h
+++ b/sources/shiboken6/tests/libsample/echo.h
@@ -40,16 +40,44 @@ public:
Echo(){}
~Echo(){}
- void doNothingWithConstBool(const bool hi) {}
- void methodWithNamedArg(const Str& string = Str("")) {}
+ void doNothingWithConstBool(const bool hi);
+ void methodWithNamedArg(const Str& string = Str(""));
Str operator()(const Str& s, const int i) { return s + i; }
// These method are here just for compilation test purposes
- Echo& operator<<(unsigned int item) { return *this; }
- Echo& operator<<(signed int item) { return *this; }
- Echo& operator<<(const ObjectType* item) { return *this; }
- Echo& operator<<(Str str) { return *this; }
+ Echo& operator<<(unsigned int item);
+ Echo& operator<<(signed int item);
+ Echo& operator<<(const ObjectType *item);
+ Echo& operator<<(Str str);
};
-#endif
+inline void Echo::doNothingWithConstBool(const bool)
+{
+}
+
+inline void Echo::methodWithNamedArg(const Str &)
+{
+}
+
+inline Echo &Echo::operator<<(unsigned int)
+{
+ return *this;
+}
+
+inline Echo &Echo::operator<<(signed int)
+{
+ return *this;
+}
+
+inline Echo &Echo::operator<<(const ObjectType *)
+{
+ return *this;
+}
+
+inline Echo &Echo::operator<<(Str)
+{
+ return *this;
+}
+
+#endif // ECHO_H
diff --git a/sources/shiboken6/tests/libsample/filter.cpp b/sources/shiboken6/tests/libsample/filter.cpp
index f862babd2..c92e1f084 100644
--- a/sources/shiboken6/tests/libsample/filter.cpp
+++ b/sources/shiboken6/tests/libsample/filter.cpp
@@ -43,11 +43,6 @@ Union::Union(const Intersection& filter)
m_filters.push_back(filter);
}
-Union::Union(const Union& filter)
-{
- m_filters = filter.filters();
-}
-
Intersection::Intersection(const Data& filter)
{
m_filters.push_back(filter);
@@ -58,11 +53,6 @@ Intersection::Intersection(const Union& filter)
m_filters.push_back(filter);
}
-Intersection::Intersection(const Intersection& filter)
-{
- m_filters = filter.filters();
-}
-
Intersection operator&(const Intersection& a, const Intersection& b)
{
Intersection filter;
diff --git a/sources/shiboken6/tests/libsample/filter.h b/sources/shiboken6/tests/libsample/filter.h
index e318cba20..298441d4f 100644
--- a/sources/shiboken6/tests/libsample/filter.h
+++ b/sources/shiboken6/tests/libsample/filter.h
@@ -66,8 +66,7 @@ public:
Union(const Data&);
Union(const Intersection&);
- Union() {};
- Union(const Union&);
+ Union() = default;
std::list<Filter> filters() const { return m_filters; }
void addFilter(const Filter& data) { m_filters.push_back(data); }
@@ -82,8 +81,7 @@ public:
Intersection(const Data&);
Intersection(const Union&);
- Intersection() {};
- Intersection(const Intersection&);
+ Intersection() = default;
std::list<Filter> filters() const { return m_filters; }
void addFilter(const Filter& data) { m_filters.push_back(data); }
diff --git a/sources/shiboken6/tests/libsample/functions.cpp b/sources/shiboken6/tests/libsample/functions.cpp
index 303b006a7..246faf553 100644
--- a/sources/shiboken6/tests/libsample/functions.cpp
+++ b/sources/shiboken6/tests/libsample/functions.cpp
@@ -103,14 +103,12 @@ returnCString()
return __FUNCTION__;
}
-GlobalOverloadFuncEnum
-overloadedFunc(int val)
+GlobalOverloadFuncEnum overloadedFunc(int)
{
return GlobalOverloadFunc_i;
}
-GlobalOverloadFuncEnum
-overloadedFunc(double val)
+GlobalOverloadFuncEnum overloadedFunc(double)
{
return GlobalOverloadFunc_d;
}
diff --git a/sources/shiboken6/tests/libsample/handle.h b/sources/shiboken6/tests/libsample/handle.h
index 824c28b9a..57e644c32 100644
--- a/sources/shiboken6/tests/libsample/handle.h
+++ b/sources/shiboken6/tests/libsample/handle.h
@@ -48,7 +48,7 @@ public:
explicit HandleHolder(HANDLE ptr = nullptr) : m_handle(ptr) {}
explicit HandleHolder(Foo::HANDLE val): m_handle2(val) {}
- inline void set(HANDLE ptr) { HANDLE tmp; tmp = m_handle; m_handle = tmp; }
+ void set(HANDLE ptr);
inline void set(const Foo::HANDLE& val) { m_handle2 = val; }
inline HANDLE handle() { return m_handle; }
inline Foo::HANDLE handle2() { return m_handle2; }
@@ -62,6 +62,12 @@ private:
Foo::HANDLE m_handle2;
};
+inline void HandleHolder::set(HANDLE)
+{
+ HANDLE tmp = m_handle;
+ m_handle = tmp;
+}
+
struct LIBSAMPLE_API PrimitiveStruct {};
using PrimitiveStructPtr = struct PrimitiveStruct *;
struct LIBSAMPLE_API PrimitiveStructPointerHolder
diff --git a/sources/shiboken6/tests/libsample/implicitconv.cpp b/sources/shiboken6/tests/libsample/implicitconv.cpp
index 88af0d936..00b02fceb 100644
--- a/sources/shiboken6/tests/libsample/implicitconv.cpp
+++ b/sources/shiboken6/tests/libsample/implicitconv.cpp
@@ -28,6 +28,11 @@
#include "implicitconv.h"
+ImplicitConv::ImplicitConv(const Null &) :
+ m_ctorEnum(CtorPrimitiveType)
+{
+}
+
ImplicitConv
ImplicitConv::implicitConvCommon(ImplicitConv implicit)
{
@@ -41,26 +46,27 @@ ImplicitConv::implicitConvDefault(ImplicitConv implicit)
}
ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(ImplicitConv implicit, int dummyArg)
+ImplicitConv::implicitConvOverloading(ImplicitConv, int)
{
return ImplicitConv::OverFunc_Ii;
}
ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(ImplicitConv implicit, bool dummyArg)
+ImplicitConv::implicitConvOverloading(ImplicitConv, bool)
{
return ImplicitConv::OverFunc_Ib;
}
ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(int dummyArg)
+ImplicitConv::implicitConvOverloading(int)
{
return ImplicitConv::OverFunc_i;
}
ImplicitConv::ICOverloadedFuncEnum
-ImplicitConv::implicitConvOverloading(CtorEnum dummyArg)
+ImplicitConv::implicitConvOverloading(CtorEnum)
{
return ImplicitConv::OverFunc_C;
}
+
diff --git a/sources/shiboken6/tests/libsample/implicitconv.h b/sources/shiboken6/tests/libsample/implicitconv.h
index ea859a1a6..10e98ccc5 100644
--- a/sources/shiboken6/tests/libsample/implicitconv.h
+++ b/sources/shiboken6/tests/libsample/implicitconv.h
@@ -58,7 +58,7 @@ public:
ImplicitConv(CtorEnum ctorEnum) : m_ctorEnum(ctorEnum), m_objId(-1), m_value(-1.0) {}
ImplicitConv(ObjectType&) : m_ctorEnum(CtorObjectTypeReference), m_objId(-1), m_value(-1.0) {}
ImplicitConv(double value, bool=true) : m_ctorEnum(CtorNone), m_value(value) {}
- ImplicitConv(const Null& null) : m_ctorEnum(CtorPrimitiveType) {}
+ ImplicitConv(const Null &null);
~ImplicitConv() {}
inline CtorEnum ctorEnum() { return m_ctorEnum; }
diff --git a/sources/shiboken6/tests/libsample/list.h b/sources/shiboken6/tests/libsample/list.h
index f4970d947..e44567a73 100644
--- a/sources/shiboken6/tests/libsample/list.h
+++ b/sources/shiboken6/tests/libsample/list.h
@@ -52,9 +52,13 @@ public:
inline IntList() : m_ctorUsed(NoParamsCtor) {}
inline explicit IntList(int val) : m_ctorUsed(IntCtor) { push_back(val); }
- inline IntList(const IntList& lst) : List<int>(lst), m_ctorUsed(CopyCtor) {}
inline IntList(const List<int>& lst) : List<int>(lst), m_ctorUsed(ListOfIntCtor) {}
+ inline IntList(const IntList& lst) : List<int>(lst), m_ctorUsed(CopyCtor) {}
+ IntList(IntList &&) = default;
+ IntList &operator=(const IntList &) = default;
+ IntList &operator=(IntList &&) = default;
+
inline void append(int v) { insert(end(), v); }
CtorEnum constructorUsed() { return m_ctorUsed; }
private:
@@ -73,9 +77,13 @@ public:
inline PointValueList() : m_ctorUsed(NoParamsCtor) {}
inline explicit PointValueList(Point val) : m_ctorUsed(PointCtor) { push_back(val); }
- inline PointValueList(const PointValueList& lst) : List<Point>(lst), m_ctorUsed(CopyCtor) {}
inline PointValueList(const List<Point>& lst) : List<Point>(lst), m_ctorUsed(ListOfPointValuesCtor) {}
+ inline PointValueList(const PointValueList& lst) : List<Point>(lst), m_ctorUsed(CopyCtor) {}
+ PointValueList(PointValueList &&) = default;
+ PointValueList &operator=(const PointValueList &) = default;
+ PointValueList &operator=(PointValueList &&) = default;
+
inline void append(Point v) { insert(end(), v); }
CtorEnum constructorUsed() { return m_ctorUsed; }
private:
@@ -94,9 +102,13 @@ public:
inline ObjectTypePtrList() : m_ctorUsed(NoParamsCtor) {}
inline explicit ObjectTypePtrList(ObjectType* val) : m_ctorUsed(ObjectTypeCtor) { push_back(val); }
- inline ObjectTypePtrList(const ObjectTypePtrList& lst) : List<ObjectType*>(lst), m_ctorUsed(CopyCtor) {}
inline ObjectTypePtrList(const List<ObjectType*>& lst) : List<ObjectType*>(lst), m_ctorUsed(ListOfObjectTypePtrCtor) {}
+ inline ObjectTypePtrList(const ObjectTypePtrList& lst) : List<ObjectType*>(lst), m_ctorUsed(CopyCtor) {}
+ ObjectTypePtrList(ObjectTypePtrList &&) = default;
+ ObjectTypePtrList &operator=(const ObjectTypePtrList &) = default;
+ ObjectTypePtrList &operator=(ObjectTypePtrList &&) = default;
+
inline void append(ObjectType* v) { insert(end(), v); }
CtorEnum constructorUsed() { return m_ctorUsed; }
private:
diff --git a/sources/shiboken6/tests/libsample/listuser.cpp b/sources/shiboken6/tests/libsample/listuser.cpp
index 995220b6f..a19b4a537 100644
--- a/sources/shiboken6/tests/libsample/listuser.cpp
+++ b/sources/shiboken6/tests/libsample/listuser.cpp
@@ -38,6 +38,13 @@ ListUser::callCreateList()
return createList();
}
+ListUser::ListUser() = default;
+ListUser::ListUser(const ListUser &other) = default;
+ListUser::ListUser(ListUser &&other) = default;
+ListUser &ListUser::operator=(const ListUser &other) = default;
+ListUser &ListUser::operator=(ListUser &&other) = default;
+ListUser::~ListUser() = default;
+
std::list<int>
ListUser::createList()
{
@@ -68,14 +75,12 @@ ListUser::sumList(std::list<double> vallist)
return std::accumulate(vallist.begin(), vallist.end(), 0.0);
}
-ListUser::ListOfSomething
-ListUser::listOfPoints(const std::list<Point>& pointlist)
+ListUser::ListOfSomething ListUser::listOfPoints(const std::list<Point> &)
{
return ListOfPoint;
}
-ListUser::ListOfSomething
-ListUser::listOfPoints(const std::list<PointF>& pointlist)
+ListUser::ListOfSomething ListUser::listOfPoints(const std::list<PointF> &)
{
return ListOfPointF;
}
diff --git a/sources/shiboken6/tests/libsample/listuser.h b/sources/shiboken6/tests/libsample/listuser.h
index 7e67039d9..9596de2c7 100644
--- a/sources/shiboken6/tests/libsample/listuser.h
+++ b/sources/shiboken6/tests/libsample/listuser.h
@@ -46,9 +46,12 @@ public:
ListOfPointF
};
- ListUser() {}
- ListUser(const ListUser& other) : m_lst(other.m_lst) {}
- virtual ~ListUser() {}
+ ListUser();
+ ListUser(const ListUser &other);
+ ListUser(ListUser &&other);
+ ListUser &operator=(const ListUser &other);
+ ListUser &operator=(ListUser &&other);
+ virtual ~ListUser();
virtual std::list<int> createList();
std::list<int> callCreateList();
diff --git a/sources/shiboken6/tests/libsample/mapuser.cpp b/sources/shiboken6/tests/libsample/mapuser.cpp
index e2a0f7181..677939fe0 100644
--- a/sources/shiboken6/tests/libsample/mapuser.cpp
+++ b/sources/shiboken6/tests/libsample/mapuser.cpp
@@ -66,6 +66,14 @@ MapUser::showMap(std::map<std::string, int> mapping)
cout << (*it).first << " => " << (*it).second << endl;
}
+void MapUser::pointerToMap(std::map<std::string, std::string> *)
+{
+}
+
+void MapUser::referenceToMap(std::map<std::string, std::string> &)
+{
+}
+
std::map<int, std::list<std::list<double> > > MapUser::foo() const
{
std::map<int, std::list<std::list<double> > > result;
diff --git a/sources/shiboken6/tests/libsample/mapuser.h b/sources/shiboken6/tests/libsample/mapuser.h
index ad434b957..9dcc040c5 100644
--- a/sources/shiboken6/tests/libsample/mapuser.h
+++ b/sources/shiboken6/tests/libsample/mapuser.h
@@ -53,8 +53,8 @@ public:
inline std::map<std::string, std::list<int> > getMap() { return m_map; }
// Compile test
- static void pointerToMap(std::map<std::string, std::string>* arg) {}
- static void referenceToMap(std::map<std::string, std::string>& arg) {}
+ static void pointerToMap(std::map<std::string, std::string> *arg);
+ static void referenceToMap(std::map<std::string, std::string> &arg);
inline const std::map<int, ByteArray>& passMapIntValueType(const std::map<int, ByteArray>& arg) { return arg; }
diff --git a/sources/shiboken6/tests/libsample/modelindex.h b/sources/shiboken6/tests/libsample/modelindex.h
index dd3ddc089..370b1bce3 100644
--- a/sources/shiboken6/tests/libsample/modelindex.h
+++ b/sources/shiboken6/tests/libsample/modelindex.h
@@ -34,21 +34,22 @@
class ModelIndex
{
public:
- ModelIndex() : m_value(0) {}
- ModelIndex(const ModelIndex& other) { m_value = other.m_value; }
+ ModelIndex() = default;
+
inline void setValue(int value) { m_value = value; }
inline int value() const { return m_value; }
static int getValue(const ModelIndex& index) { return index.value(); }
private:
- int m_value;
+ int m_value = 0;
};
class ReferentModelIndex
{
public:
- ReferentModelIndex() {}
- ReferentModelIndex(const ModelIndex& index) : m_index(index) {}
- ReferentModelIndex(const ReferentModelIndex& other) { m_index = other.m_index; }
+ ReferentModelIndex() = default;
+
+ explicit ReferentModelIndex(const ModelIndex& index) : m_index(index) {}
+
inline void setValue(int value) { m_index.setValue(value); }
inline int value() const { return m_index.value(); }
operator const ModelIndex&() const { return m_index; }
@@ -59,9 +60,10 @@ private:
class PersistentModelIndex
{
public:
- PersistentModelIndex() {}
- PersistentModelIndex(const ModelIndex& index) : m_index(index) {}
- PersistentModelIndex(const PersistentModelIndex& other) { m_index = other.m_index; }
+ PersistentModelIndex() = default;
+
+ explicit PersistentModelIndex(const ModelIndex& index) : m_index(index) {}
+
inline void setValue(int value) { m_index.setValue(value); }
inline int value() const { return m_index.value(); }
operator ModelIndex() const { return m_index; }
diff --git a/sources/shiboken6/tests/libsample/modifications.cpp b/sources/shiboken6/tests/libsample/modifications.cpp
index 627d17b45..c9c85b65b 100644
--- a/sources/shiboken6/tests/libsample/modifications.cpp
+++ b/sources/shiboken6/tests/libsample/modifications.cpp
@@ -43,6 +43,67 @@ Modifications::~Modifications()
delete m_object;
}
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, Point, Point)
+{
+ return Overloaded_ibPP;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, int)
+{
+ return Overloaded_ibii;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, Point)
+{
+ return Overloaded_ibiP;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, bool)
+{
+ return Overloaded_ibib;
+}
+
+Modifications::OverloadedModFunc Modifications::overloaded(int, bool, int, double)
+{
+ return Overloaded_ibid;
+}
+
+void Modifications::argRemoval0(int, bool, int, int)
+{
+}
+
+void Modifications::argRemoval0(int, bool, int, bool)
+{
+}
+
+void Modifications::argRemoval1(int, bool, Point, Point, int)
+{
+}
+
+void Modifications::argRemoval1(int, bool, int, bool)
+{
+}
+
+void Modifications::argRemoval2(int, bool, Point, Point, int)
+{
+}
+
+void Modifications::argRemoval3(int, Point, bool, Point, int)
+{
+}
+
+void Modifications::argRemoval4(int, Point, bool, Point, int)
+{
+}
+
+void Modifications::argRemoval5(int, bool, Point, Point, int)
+{
+}
+
+void Modifications::argRemoval5(int, bool, int, bool)
+{
+}
+
std::pair<double, double>
Modifications::pointToPair(Point pt, bool* ok)
{
diff --git a/sources/shiboken6/tests/libsample/modifications.h b/sources/shiboken6/tests/libsample/modifications.h
index 888c66d18..f7059de8c 100644
--- a/sources/shiboken6/tests/libsample/modifications.h
+++ b/sources/shiboken6/tests/libsample/modifications.h
@@ -58,26 +58,30 @@ public:
// those overloaded methods should be heavily modified
// to push the overload decisor to its limits
- inline OverloadedModFunc overloaded(int a0, bool b0, int c0, double d0) { return Overloaded_ibid; }
- inline OverloadedModFunc overloaded(int a1, bool b1, int c1, bool d1) { return Overloaded_ibib; }
- inline OverloadedModFunc overloaded(int a2, bool b2, int c2, Point d2) { return Overloaded_ibiP; }
- inline OverloadedModFunc overloaded(int a3, bool b3, int c3 = 123, int d3 = 456) { return Overloaded_ibii; }
- inline OverloadedModFunc overloaded(int a4, bool b4, Point c4, Point d4) { return Overloaded_ibPP; }
+ OverloadedModFunc overloaded(int a0, bool b0, int c0, double d0);
+ OverloadedModFunc overloaded(int a1, bool b1, int c1, bool d1);
+ OverloadedModFunc overloaded(int a2, bool b2, int c2, Point d2);
+ OverloadedModFunc overloaded(int a3, bool b3, int c3 = 123, int d3 = 456);
+ OverloadedModFunc overloaded(int a4, bool b4, Point c4, Point d4);
- inline void argRemoval0(int a0, bool a1, int a2 = 123, int a3 = 456) {}
- inline void argRemoval0(int a0, bool a1, int a2, bool a3) {}
+ void argRemoval0(int a0, bool a1, int a2 = 123, int a3 = 456);
+ void argRemoval0(int a0, bool a1, int a2, bool a3);
- inline void argRemoval1(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4), int a4 = 333) {}
- inline void argRemoval1(int a0, bool a1, int a2, bool a3) {}
+ void argRemoval1(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4),
+ int a4 = 333);
+ void argRemoval1(int a0, bool a1, int a2, bool a3);
- inline void argRemoval2(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4), int a4 = 333) {}
+ void argRemoval2(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4),
+ int a4 = 333);
- inline void argRemoval3(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 333) {}
+ void argRemoval3(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4),
+ int a4 = 333);
- inline void argRemoval4(int a0, Point a1, bool a2, Point a3 = Point(3, 4), int a4 = 333) {}
+ void argRemoval4(int a0, Point a1, bool a2, Point a3 = Point(3, 4), int a4 = 333);
- inline void argRemoval5(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4), int a4 = 333) {}
- inline void argRemoval5(int a0, bool a1, int a2, bool a3) {}
+ void argRemoval5(int a0, bool a1, Point a2 = Point(1, 2), Point a3 = Point(3, 4),
+ int a4 = 333);
+ void argRemoval5(int a0, bool a1, int a2, bool a3);
// 'ok' must be removed and the return value will be changed
// to a tuple (PyObject*) containing the expected result plus
diff --git a/sources/shiboken6/tests/libsample/objectmodel.cpp b/sources/shiboken6/tests/libsample/objectmodel.cpp
index c92fb2ec2..58792b1e5 100644
--- a/sources/shiboken6/tests/libsample/objectmodel.cpp
+++ b/sources/shiboken6/tests/libsample/objectmodel.cpp
@@ -40,3 +40,12 @@ ObjectModel::data() const
return m_data;
}
+ObjectModel::MethodCalled ObjectModel::receivesObjectTypeFamily(const ObjectModel &)
+{
+ return ObjectModel::ObjectModelCalled;
+}
+
+ObjectModel::MethodCalled ObjectModel::receivesObjectTypeFamily(const ObjectType &)
+{
+ return ObjectModel::ObjectTypeCalled;
+}
diff --git a/sources/shiboken6/tests/libsample/objectmodel.h b/sources/shiboken6/tests/libsample/objectmodel.h
index 1890ac47f..04f644f99 100644
--- a/sources/shiboken6/tests/libsample/objectmodel.h
+++ b/sources/shiboken6/tests/libsample/objectmodel.h
@@ -45,8 +45,8 @@ public:
// The MethodCalled enum and related static methods were created to
// test bug #630 [http://bugs.openbossa.org/show_bug.cgi?id=630]
enum MethodCalled { ObjectTypeCalled, ObjectModelCalled };
- static MethodCalled receivesObjectTypeFamily(const ObjectType& object) { return ObjectModel::ObjectTypeCalled; }
- static MethodCalled receivesObjectTypeFamily(const ObjectModel& object) { return ObjectModel::ObjectModelCalled; }
+ static MethodCalled receivesObjectTypeFamily(const ObjectType &object);
+ static MethodCalled receivesObjectTypeFamily(const ObjectModel &object);
private:
// The model holds only one piece of data.
diff --git a/sources/shiboken6/tests/libsample/objecttype.cpp b/sources/shiboken6/tests/libsample/objecttype.cpp
index e5926d0c2..75f9b4c2d 100644
--- a/sources/shiboken6/tests/libsample/objecttype.cpp
+++ b/sources/shiboken6/tests/libsample/objecttype.cpp
@@ -158,8 +158,7 @@ ObjectType::causeEvent(Event::EventType eventType)
return event(&e);
}
-bool
-ObjectType::event(Event* event)
+bool ObjectType::event(Event *)
{
return true;
}
@@ -179,6 +178,10 @@ ObjectType::callInvalidateEvent(Event* event)
invalidateEvent(event);
}
+void ObjectType::invalidateEvent(Event *)
+{
+}
+
void
ObjectType::setLayout(ObjectTypeLayout* l)
{
@@ -230,13 +233,13 @@ objectTypeHash(const ObjectType* objectType)
return reinterpret_cast<std::size_t>(objectType);
}
-unsigned char
-ObjectType::callWithEnum(const Str& prefix, Event::EventType type, unsigned char value){
+unsigned char ObjectType::callWithEnum(const Str &, Event::EventType, unsigned char value)
+{
return value*value;
}
-unsigned char
-ObjectType::callWithEnum(const Str& prefix, unsigned char value) {
+unsigned char ObjectType::callWithEnum(const Str &, unsigned char value)
+{
return value;
}
@@ -305,8 +308,7 @@ ObjectTypeDerived::~ObjectTypeDerived()
{
}
-bool
-ObjectTypeDerived::event(Event* event)
+bool ObjectTypeDerived::event(Event *)
{
return true;
}
diff --git a/sources/shiboken6/tests/libsample/objecttype.h b/sources/shiboken6/tests/libsample/objecttype.h
index 5863d5f2d..50abd6491 100644
--- a/sources/shiboken6/tests/libsample/objecttype.h
+++ b/sources/shiboken6/tests/libsample/objecttype.h
@@ -101,7 +101,7 @@ public:
static int processEvent(ObjectTypeList objects, Event *event);
void callInvalidateEvent(Event* event);
- virtual void invalidateEvent(Event* event) {}
+ virtual void invalidateEvent(Event *event);
// This nonsense method emulate QWidget.setLayout method
// All layout objects will became children of this object.
diff --git a/sources/shiboken6/tests/libsample/objecttypebyvalue.h b/sources/shiboken6/tests/libsample/objecttypebyvalue.h
index 64fa78c83..48c111ae4 100644
--- a/sources/shiboken6/tests/libsample/objecttypebyvalue.h
+++ b/sources/shiboken6/tests/libsample/objecttypebyvalue.h
@@ -35,12 +35,20 @@ class ObjectTypeByValue
{
public:
ObjectTypeByValue returnSomeKindOfMe() { return ObjectTypeByValue(); }
- void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe) {}
+ void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe);
- void acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue> listOfMe) {}
+ void acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue> listOfMe);
// prop used to check for segfaults
ProtectedProperty prop;
};
-#endif
+inline void ObjectTypeByValue::acceptKindOfMeAsValue(ObjectTypeByValue)
+{
+}
+
+inline void ObjectTypeByValue::acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue>)
+{
+}
+
+#endif // OBJECTTYPEBYVALUE_H
diff --git a/sources/shiboken6/tests/libsample/overload.cpp b/sources/shiboken6/tests/libsample/overload.cpp
index ebf19586e..171e7ebb3 100644
--- a/sources/shiboken6/tests/libsample/overload.cpp
+++ b/sources/shiboken6/tests/libsample/overload.cpp
@@ -33,18 +33,194 @@ Overload::FunctionEnum Overload::overloaded()
return Function0;
}
-Overload::FunctionEnum Overload::overloaded(Size* size)
+Overload::FunctionEnum Overload::overloaded(Size *)
{
return Function1;
}
-Overload::FunctionEnum Overload::overloaded(Point* point, ParamEnum param)
+Overload::FunctionEnum Overload::overloaded(Point *, ParamEnum)
{
return Function2;
}
-Overload::FunctionEnum Overload::overloaded(const Point& point)
+Overload::FunctionEnum Overload::overloaded(const Point &)
{
return Function3;
}
+void Overload::differentReturnTypes(ParamEnum)
+{
+
+}
+
+int Overload::differentReturnTypes(ParamEnum, int val)
+{
+ return val;
+}
+
+int Overload::intOverloads(const Point &, double)
+{
+ return 1; }
+
+int Overload::intOverloads(int, int)
+{
+ return 2; }
+
+int Overload::intOverloads(int, int, double)
+{
+ return 3;
+}
+
+Overload::FunctionEnum Overload::intDoubleOverloads(double, double) const
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::intDoubleOverloads(int, int) const
+{
+ return Function0;
+}
+
+void Overload::singleOverload(Point *)
+{
+}
+
+Overload::FunctionEnum Overload::wrapperIntIntOverloads(const Polygon &, int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::wrapperIntIntOverloads(const Point &, int, int)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::strBufferOverloads(const Str &, const char *, bool)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::strBufferOverloads(unsigned char *, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText(const PointF &, const Str &)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText(const Point &, const Str &)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText(const RectF &, const Str &, const Echo &)
+{
+ return Function4;
+}
+
+Overload::FunctionEnum Overload::drawText(const RectF &, int, const Str &)
+{
+ return Function3;
+}
+
+Overload::FunctionEnum Overload::drawText(const Rect &, int, const Str &)
+{
+ return Function2;
+}
+
+Overload::FunctionEnum Overload::drawText(int, int, const Str &)
+{
+ return Function5;
+}
+
+Overload::FunctionEnum Overload::drawText(int, int, int, int, int, const Str &)
+{
+ return Function6;
+}
+
+Overload::FunctionEnum Overload::drawText2(const PointF &, const Str &)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText2(const Point &, const Str &)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText2(int, int, const Str &)
+{
+ return Function5;
+}
+
+Overload::FunctionEnum Overload::drawText2(const RectF &, const Str &, const Echo &)
+{
+ return Function4;
+}
+
+Overload::FunctionEnum Overload::drawText2(const RectF &, int, const Str &)
+{
+ return Function3;
+}
+
+Overload::FunctionEnum Overload::drawText2(const Rect &, int, const Str &)
+{
+ return Function2;
+}
+
+Overload::FunctionEnum Overload::drawText2(int, int, int, int, int, const Str &)
+{
+ return Function6;
+}
+
+Overload::FunctionEnum Overload::drawText3(const Str &, const Str &, const Str &)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText3(int, int, int, int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::drawText4(int, int, int)
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::drawText4(int, int, int, int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::acceptSequence()
+{
+ return Function0;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(const Str &, ParamEnum)
+{
+ return Function2;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(int, int)
+{
+ return Function1;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(void *)
+{
+ return Function5;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(const char *const[])
+{
+ return Function4;
+}
+
+Overload::FunctionEnum Overload::acceptSequence(const Size &)
+{
+ return Function3;
+}
diff --git a/sources/shiboken6/tests/libsample/overload.h b/sources/shiboken6/tests/libsample/overload.h
index aa2572d50..50df42d92 100644
--- a/sources/shiboken6/tests/libsample/overload.h
+++ b/sources/shiboken6/tests/libsample/overload.h
@@ -65,61 +65,63 @@ public:
FunctionEnum overloaded(Point* point, ParamEnum param);
FunctionEnum overloaded(const Point& point);
- inline void differentReturnTypes(ParamEnum param = Param0) {}
- inline int differentReturnTypes(ParamEnum param, int val) { return val; }
+ void differentReturnTypes(ParamEnum param = Param0);
+ int differentReturnTypes(ParamEnum param, int val);
- inline int intOverloads(const Point& p, double d) { return 1; }
- inline int intOverloads(int i, int i2) { return 2; }
- inline int intOverloads(int i, int removedArg, double d) { return 3; }
+ int intOverloads(const Point &p, double d);
+ int intOverloads(int i, int i2);
+ int intOverloads(int i, int removedArg, double d);
- inline FunctionEnum intDoubleOverloads(int a0, int a1) const { return Function0; }
- inline FunctionEnum intDoubleOverloads(double a0, double a1) const { return Function1; }
+ FunctionEnum intDoubleOverloads(int a0, int a1) const;
+ FunctionEnum intDoubleOverloads(double a0, double a1) const;
- void singleOverload(Point* x) {}
+ void singleOverload(Point *x);
Point* singleOverload() {return new Point();}
// Similar to QImage::trueMatrix(QMatrix,int,int) and QImage::trueMatrix(QTransform,int,int)
- FunctionEnum wrapperIntIntOverloads(const Point& arg0, int arg1, int arg2) { return Function0; }
- FunctionEnum wrapperIntIntOverloads(const Polygon& arg0, int arg1, int arg2) { return Function1; }
+ FunctionEnum wrapperIntIntOverloads(const Point &arg0, int arg1, int arg2);
+ FunctionEnum wrapperIntIntOverloads(const Polygon &arg0, int arg1, int arg2);
// Similar to QImage constructor
- FunctionEnum strBufferOverloads(const Str &arg0, const char *arg1 = nullptr, bool arg2 = true) { return Function0; }
- FunctionEnum strBufferOverloads(unsigned char* arg0, int arg1) { return Function1; }
+ FunctionEnum strBufferOverloads(const Str &arg0, const char *arg1 = nullptr,
+ bool arg2 = true);
+ FunctionEnum strBufferOverloads(unsigned char* arg0, int arg1);
FunctionEnum strBufferOverloads() { return Function2; }
// Similar to QPainter::drawText(...)
- FunctionEnum drawText(const Point& a0, const Str& a1) { return Function0; }
- FunctionEnum drawText(const PointF& a0, const Str& a1) { return Function1; }
- FunctionEnum drawText(const Rect& a0, int a1, const Str& a2) { return Function2; }
- FunctionEnum drawText(const RectF& a0, int a1, const Str& a2) { return Function3; }
- FunctionEnum drawText(const RectF& a0, const Str& a1, const Echo& a2 = Echo()) { return Function4; }
- FunctionEnum drawText(int a0, int a1, const Str& a2) { return Function5; }
- FunctionEnum drawText(int a0, int a1, int a2, int a3, int a4, const Str& a5) { return Function6; }
+ FunctionEnum drawText(const Point &a0, const Str &a1);
+ FunctionEnum drawText(const PointF &a0, const Str &a1);
+ FunctionEnum drawText(const Rect &a0, int a1, const Str &a2);
+ FunctionEnum drawText(const RectF &a0, int a1, const Str &a2);
+ FunctionEnum drawText(const RectF &a0, const Str &a1, const Echo &a2 = Echo());
+ FunctionEnum drawText(int a0, int a1, const Str &a2);
+ FunctionEnum drawText(int a0, int a1, int a2, int a3, int a4, const Str &a5);
// A variant of the one similar to QPainter::drawText(...)
- FunctionEnum drawText2(const Point& a0, const Str& a1) { return Function0; }
- FunctionEnum drawText2(const PointF& a0, const Str& a1) { return Function1; }
- FunctionEnum drawText2(const Rect& a0, int a1, const Str& a2) { return Function2; }
- FunctionEnum drawText2(const RectF& a0, int a1, const Str& a2) { return Function3; }
- FunctionEnum drawText2(const RectF& a0, const Str& a1, const Echo& a2 = Echo()) { return Function4; }
- FunctionEnum drawText2(int a0, int a1, const Str& a2) { return Function5; }
- FunctionEnum drawText2(int a0, int a1, int a2, int a3 = 0, int a4 = 0, const Str& a5 = Str()) { return Function6; }
+ FunctionEnum drawText2(const Point &a0, const Str &a1);
+ FunctionEnum drawText2(const PointF &a0, const Str &a1);
+ FunctionEnum drawText2(const Rect &a0, int a1, const Str &a2);
+ FunctionEnum drawText2(const RectF &a0, int a1, const Str &a2);
+ FunctionEnum drawText2(const RectF &a0, const Str &a1, const Echo &a2 = Echo());
+ FunctionEnum drawText2(int a0, int a1, const Str &a2);
+ FunctionEnum drawText2(int a0, int a1, int a2, int a3 = 0, int a4 = 0,
+ const Str &a5 = Str());
// A simpler variant of the one similar to QPainter::drawText(...)
- FunctionEnum drawText3(const Str& a0, const Str& a1, const Str& a2) { return Function0; }
- FunctionEnum drawText3(int a0, int a1, int a2, int a3, int a4) { return Function1; }
+ FunctionEnum drawText3(const Str &a0, const Str &a1, const Str &a2);
+ FunctionEnum drawText3(int a0, int a1, int a2, int a3, int a4);
// Another simpler variant of the one similar to QPainter::drawText(...)
- FunctionEnum drawText4(int a0, int a1, int a2) { return Function0; }
- FunctionEnum drawText4(int a0, int a1, int a2, int a3, int a4) { return Function1; }
+ FunctionEnum drawText4(int a0, int a1, int a2);
+ FunctionEnum drawText4(int a0, int a1, int a2, int a3, int a4);
- FunctionEnum acceptSequence() { return Function0; }
- FunctionEnum acceptSequence(int a0, int a1) { return Function1; }
- FunctionEnum acceptSequence(const Str& a0, ParamEnum a1 = Param0) { return Function2; }
- FunctionEnum acceptSequence(const Size& a0) { return Function3; }
+ FunctionEnum acceptSequence();
+ FunctionEnum acceptSequence(int a0, int a1);
+ FunctionEnum acceptSequence(const Str &a0, ParamEnum a1 = Param0);
+ FunctionEnum acceptSequence(const Size &a0);
// The type must be changed to PySequence.
- FunctionEnum acceptSequence(const char* const a0[]) { return Function4; }
- FunctionEnum acceptSequence(void* a0) { return Function5; }
+ FunctionEnum acceptSequence(const char* const a0[]);
+ FunctionEnum acceptSequence(void *a0);
};
class LIBSAMPLE_API Overload2 : public Overload
@@ -140,4 +142,3 @@ private:
};
#endif // OVERLOAD_H
-
diff --git a/sources/shiboken6/tests/libsample/overloadsort.cpp b/sources/shiboken6/tests/libsample/overloadsort.cpp
index 8534ef0f1..1e46f71cc 100644
--- a/sources/shiboken6/tests/libsample/overloadsort.cpp
+++ b/sources/shiboken6/tests/libsample/overloadsort.cpp
@@ -28,6 +28,41 @@
#include "overloadsort.h"
+const char *SortedOverload::overload(int)
+{
+ return "int";
+}
+
+const char *SortedOverload::overload(double)
+{
+ return "double";
+}
+
+const char *SortedOverload::overload(ImplicitBase)
+{
+ return "ImplicitBase";
+}
+
+const char *SortedOverload::overload(ImplicitTarget)
+{
+ return "ImplicitTarget";
+}
+
+const char *SortedOverload::overload(const std::list<ImplicitBase> &)
+{
+ return "list(ImplicitBase)";
+}
+
+int SortedOverload::implicit_overload(const ImplicitBase &)
+{
+ return 1;
+}
+
+const char *SortedOverload::overloadDeep(int, ImplicitBase &)
+{
+ return "ImplicitBase";
+}
+
int CustomOverloadSequence::overload(short v) const
{
return v + int(sizeof(v));
diff --git a/sources/shiboken6/tests/libsample/overloadsort.h b/sources/shiboken6/tests/libsample/overloadsort.h
index ad720222c..8645be8d7 100644
--- a/sources/shiboken6/tests/libsample/overloadsort.h
+++ b/sources/shiboken6/tests/libsample/overloadsort.h
@@ -43,41 +43,26 @@ class ImplicitBase
{
public:
ImplicitBase(){}
- ImplicitBase(const ImplicitTarget &b){}
+ ImplicitBase(const ImplicitTarget &b);
};
-class SortedOverload
+inline ImplicitBase::ImplicitBase(const ImplicitTarget &)
{
-public:
-
- inline const char *overload(int x) {
- return "int";
- }
-
- inline const char *overload(double x) {
- return "double";
- }
-
- inline const char *overload(ImplicitBase x) {
- return "ImplicitBase";
- }
+}
- inline const char *overload(ImplicitTarget x) {
- return "ImplicitTarget";
- }
-
- inline const char *overload(const std::list<ImplicitBase> &x) {
- return "list(ImplicitBase)";
- }
+class LIBSAMPLE_API SortedOverload
+{
+public:
- inline int implicit_overload(const ImplicitBase &x) {
- return 1;
- }
+ const char *overload(int x);
+ const char *overload(double x);
+ const char *overload(ImplicitBase x);
+ const char *overload(ImplicitTarget x);
+ const char *overload(const std::list<ImplicitBase> &x);
- inline const char *overloadDeep(int x, ImplicitBase &y) {
- return "ImplicitBase";
- }
+ int implicit_overload(const ImplicitBase &x);
+ const char *overloadDeep(int x, ImplicitBase &y);
inline const char* pyObjOverload(int, int) { return "int,int"; }
inline const char* pyObjOverload(unsigned char*, int) { return "PyObject,int"; }
diff --git a/sources/shiboken6/tests/libsample/pen.cpp b/sources/shiboken6/tests/libsample/pen.cpp
index b5c9356d6..f6f005a95 100644
--- a/sources/shiboken6/tests/libsample/pen.cpp
+++ b/sources/shiboken6/tests/libsample/pen.cpp
@@ -28,11 +28,11 @@
#include "pen.h"
-Color::Color(SampleNamespace::InValue arg) : m_null(false)
+Color::Color(SampleNamespace::InValue) : m_null(false)
{
}
-Color::Color(unsigned int arg) : m_null(false)
+Color::Color(unsigned int) : m_null(false)
{
}
@@ -74,24 +74,28 @@ Pen::Pen() : m_ctor(EmptyCtor)
{
}
-Pen::Pen(SampleNamespace::Option option) : m_ctor(EnumCtor)
+Pen::Pen(SampleNamespace::Option) : m_ctor(EnumCtor)
{
}
-Pen::Pen(const Color& color) : m_ctor(ColorCtor)
+Pen::Pen(const Color &) : m_ctor(ColorCtor)
{
}
-Pen::Pen(const Pen& pen) : m_ctor(CopyCtor)
+Pen::Pen(const Pen &) : m_ctor(CopyCtor)
{
}
+Pen::Pen(Pen &&) = default;
+Pen &Pen::operator=(const Pen& pen) = default;
+Pen &Pen::operator=(Pen &&) = default;
+
int Pen::ctorType()
{
return m_ctor;
}
-void Pen::drawLine(int x1, int y1, int x2, int y2, RenderHints renderHints)
+void Pen::drawLine(int, int, int, int, RenderHints)
{
}
diff --git a/sources/shiboken6/tests/libsample/pen.h b/sources/shiboken6/tests/libsample/pen.h
index 3e4fe5dd8..d66e5fd9e 100644
--- a/sources/shiboken6/tests/libsample/pen.h
+++ b/sources/shiboken6/tests/libsample/pen.h
@@ -74,7 +74,10 @@ public:
Pen();
Pen(SampleNamespace::Option option);
Pen(const Color& color);
- Pen(const Pen& pen);
+ Pen(const Pen &pen);
+ Pen(Pen &&);
+ Pen &operator=(const Pen &pen);
+ Pen &operator=(Pen &&);
// PYSIDE-1325, default initializer
void drawLine(int x1, int y1, int x2, int y2, RenderHints renderHints = {});
diff --git a/sources/shiboken6/tests/libsample/protected.cpp b/sources/shiboken6/tests/libsample/protected.cpp
index b0f3f1cdc..1220ddae4 100644
--- a/sources/shiboken6/tests/libsample/protected.cpp
+++ b/sources/shiboken6/tests/libsample/protected.cpp
@@ -30,3 +30,12 @@
int ProtectedVirtualDestructor::dtor_called = 0;
+const char *ProtectedNonPolymorphic::dataTypeName(void *) const
+{
+ return "pointer";
+}
+
+const char *ProtectedNonPolymorphic::dataTypeName(int) const
+{
+ return "integer";
+}
diff --git a/sources/shiboken6/tests/libsample/protected.h b/sources/shiboken6/tests/libsample/protected.h
index 0f4fbf299..3085c7c2d 100644
--- a/sources/shiboken6/tests/libsample/protected.h
+++ b/sources/shiboken6/tests/libsample/protected.h
@@ -50,8 +50,8 @@ protected:
inline int protectedSum(int a0, int a1) { return a0 + a1; }
inline int modifiedProtectedSum(int a0, int a1) { return a0 + a1; }
inline static const char* protectedStatic() { return "protectedStatic"; }
- inline const char* dataTypeName(void *data = nullptr) const { return "pointer"; }
- inline const char* dataTypeName(int data) const { return "integer"; }
+ const char *dataTypeName(void *data = nullptr) const;
+ const char *dataTypeName(int data) const;
private:
std::string m_name;
diff --git a/sources/shiboken6/tests/libsample/reference.cpp b/sources/shiboken6/tests/libsample/reference.cpp
index 37ce1a590..047d91c7b 100644
--- a/sources/shiboken6/tests/libsample/reference.cpp
+++ b/sources/shiboken6/tests/libsample/reference.cpp
@@ -37,6 +37,11 @@ Reference::show() const
cout << "Reference.objId: " << m_objId << ", address: " << this;
}
+Reference &Reference::returnMySecondArg(int, Reference &ref)
+{
+ return ref;
+}
+
int
Reference::usesReferenceVirtual(Reference& r, int inc)
{
@@ -76,3 +81,8 @@ Reference::callAlterReferenceIdVirtual(Reference& r)
ObjTypeReference::~ObjTypeReference()
{
}
+
+ObjTypeReference &ObjTypeReference::returnMySecondArg(int, ObjTypeReference &ref)
+{
+ return ref;
+}
diff --git a/sources/shiboken6/tests/libsample/reference.h b/sources/shiboken6/tests/libsample/reference.h
index 2c0498c6f..4646a43c9 100644
--- a/sources/shiboken6/tests/libsample/reference.h
+++ b/sources/shiboken6/tests/libsample/reference.h
@@ -58,7 +58,7 @@ public:
inline static int multiplier() { return 10; }
virtual Reference& returnMyFirstArg(Reference& ref) { return ref; }
- virtual Reference& returnMySecondArg(int a, Reference& ref) { return ref; }
+ virtual Reference& returnMySecondArg(int a, Reference &ref);
// nonsense operator to test if Shiboken is ignoring dereference operators.
int operator*() { return m_objId; }
@@ -73,7 +73,7 @@ public:
ObjTypeReference(const ObjTypeReference&) {}
virtual ~ObjTypeReference();
virtual ObjTypeReference& returnMyFirstArg(ObjTypeReference& ref) { return ref; }
- virtual ObjTypeReference& returnMySecondArg(int a, ObjTypeReference& ref) { return ref; }
+ virtual ObjTypeReference &returnMySecondArg(int a, ObjTypeReference &ref);
virtual ObjTypeReference& justAPureVirtualFunc(ObjTypeReference& ref) = 0;
};
diff --git a/sources/shiboken6/tests/libsample/samplenamespace.cpp b/sources/shiboken6/tests/libsample/samplenamespace.cpp
index b3ef96f5a..74ea7cbfa 100644
--- a/sources/shiboken6/tests/libsample/samplenamespace.cpp
+++ b/sources/shiboken6/tests/libsample/samplenamespace.cpp
@@ -86,8 +86,7 @@ getNumber(Option opt)
return retval;
}
-void
-doSomethingWithArray(const unsigned char* data, unsigned int size, const char* format)
+void doSomethingWithArray(const unsigned char *, unsigned int, const char *)
{
// This function does nothing in fact.
// It is here as a dummy copy of QPixmap.loadFromData method
@@ -100,23 +99,19 @@ enumItemAsDefaultValueToIntArgument(int value)
return value;
}
-void
-forceDecisorSideA(ObjectType* object)
+void forceDecisorSideA(ObjectType *)
{
}
-void
-forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object)
+void forceDecisorSideA(const Point &, const Str &, ObjectType *)
{
}
-void
-forceDecisorSideB(int a, ObjectType* object)
+void forceDecisorSideB(int, ObjectType *)
{
}
-void
-forceDecisorSideB(int a, const Point& pt, const Str& text, ObjectType* object)
+void forceDecisorSideB(int, const Point &, const Str &, ObjectType *)
{
}
diff --git a/sources/shiboken6/tests/libsample/sometime.cpp b/sources/shiboken6/tests/libsample/sometime.cpp
index 851b3b913..be6c2e70f 100644
--- a/sources/shiboken6/tests/libsample/sometime.cpp
+++ b/sources/shiboken6/tests/libsample/sometime.cpp
@@ -56,8 +56,7 @@ Time::somethingCompletelyDifferent()
return ZeroArgs;
}
-Time::NumArgs
-Time::somethingCompletelyDifferent(int h, int m, ImplicitConv ic, ObjectType* type)
+Time::NumArgs Time::somethingCompletelyDifferent(int, int, ImplicitConv ic, ObjectType *type)
{
if (type)
return FourArgs;
@@ -72,7 +71,7 @@ Time::toString() const
if (m_is_null)
return Str();
char buffer[13];
- sprintf(buffer, "%02d:%02d:%02d.%03d", m_hour, m_minute, m_second, m_msec);
+ snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d.%03d", m_hour, m_minute, m_second, m_msec);
return Str(buffer);
}
diff --git a/sources/shiboken6/tests/libsample/str.cpp b/sources/shiboken6/tests/libsample/str.cpp
index 0411569b2..5f1bc3b37 100644
--- a/sources/shiboken6/tests/libsample/str.cpp
+++ b/sources/shiboken6/tests/libsample/str.cpp
@@ -34,11 +34,6 @@
using namespace std;
-Str::Str(const Str& s)
-{
- init(s.cstring());
-}
-
Str::Str(char c)
{
char str[2] = { c, 0 };
@@ -57,10 +52,6 @@ Str::init(const char* cstr)
m_str = cstr;
}
-Str::~Str()
-{
-}
-
Str
Str::arg(const Str& s) const
{
diff --git a/sources/shiboken6/tests/libsample/str.h b/sources/shiboken6/tests/libsample/str.h
index 2f7cee8c3..38b23eecb 100644
--- a/sources/shiboken6/tests/libsample/str.h
+++ b/sources/shiboken6/tests/libsample/str.h
@@ -35,10 +35,8 @@
class LIBSAMPLE_API Str
{
public:
- Str(const Str& s);
Str(char c);
Str(const char* cstr = "");
- ~Str();
Str arg(const Str& s) const;
diff --git a/sources/shiboken6/tests/libsample/strlist.h b/sources/shiboken6/tests/libsample/strlist.h
index 43aa15390..e9dcaca04 100644
--- a/sources/shiboken6/tests/libsample/strlist.h
+++ b/sources/shiboken6/tests/libsample/strlist.h
@@ -46,9 +46,13 @@ public:
inline StrList() : m_ctorUsed(NoParamsCtor) {}
inline explicit StrList(const Str& str) : m_ctorUsed(StrCtor) { push_back(str); }
- inline StrList(const StrList& lst) : std::list<Str>(lst), m_ctorUsed(CopyCtor) {}
inline StrList(const std::list<Str>& lst) : std::list<Str>(lst), m_ctorUsed(ListOfStrCtor) {}
+ inline StrList(const StrList &lst) : std::list<Str>(lst), m_ctorUsed(CopyCtor) {}
+ StrList(StrList &&) = default;
+ StrList &operator=(const StrList &) = default;
+ StrList &operator=(StrList &&) = default;
+
inline void append(Str str) { push_back(str); }
Str join(const Str& sep) const;
diff --git a/sources/shiboken6/tests/libsample/templateptr.cpp b/sources/shiboken6/tests/libsample/templateptr.cpp
index fa5bb8206..d9510ebdd 100644
--- a/sources/shiboken6/tests/libsample/templateptr.cpp
+++ b/sources/shiboken6/tests/libsample/templateptr.cpp
@@ -28,6 +28,6 @@
#include "templateptr.h"
-void TemplatePtr::dummy(std::list<std::pair<BlackBox *, BlackBox *> > & items)
+void TemplatePtr::dummy(std::list<std::pair<BlackBox *, BlackBox *> > &)
{
} \ No newline at end of file
diff --git a/sources/shiboken6/tests/libsample/valueandvirtual.h b/sources/shiboken6/tests/libsample/valueandvirtual.h
index 34a6788e2..85676847d 100644
--- a/sources/shiboken6/tests/libsample/valueandvirtual.h
+++ b/sources/shiboken6/tests/libsample/valueandvirtual.h
@@ -33,7 +33,6 @@ class ValueAndVirtual
{
public:
ValueAndVirtual(int id) : m_id(id) {}
- ValueAndVirtual(const ValueAndVirtual &other) { m_id = other.m_id; }
bool operator()(int id, int id2) { return id == id2; }
diff --git a/sources/shiboken6/tests/libsample/virtualmethods.cpp b/sources/shiboken6/tests/libsample/virtualmethods.cpp
index 705835c0b..21f3be200 100644
--- a/sources/shiboken6/tests/libsample/virtualmethods.cpp
+++ b/sources/shiboken6/tests/libsample/virtualmethods.cpp
@@ -57,6 +57,11 @@ VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const
*bottom = m_bottom;
}
+int VirtualMethods::recursionOnModifiedVirtual(Str) const
+{
+ return 0;
+}
+
const Str & VirtualMethods::returnConstRef() const
{
static const Str result;
diff --git a/sources/shiboken6/tests/libsample/virtualmethods.h b/sources/shiboken6/tests/libsample/virtualmethods.h
index 577f6919e..46ad85988 100644
--- a/sources/shiboken6/tests/libsample/virtualmethods.h
+++ b/sources/shiboken6/tests/libsample/virtualmethods.h
@@ -106,7 +106,7 @@ public:
getMargins(left, top, right, bottom);
}
- virtual int recursionOnModifiedVirtual(Str arg) const { return 0; }
+ virtual int recursionOnModifiedVirtual(Str arg) const;
int callRecursionOnModifiedVirtual(Str arg) const { return recursionOnModifiedVirtual(arg); }
virtual const Str & returnConstRef() const;
diff --git a/sources/shiboken6/tests/libsmart/smart.cpp b/sources/shiboken6/tests/libsmart/smart.cpp
index 09e1274de..8b142a910 100644
--- a/sources/shiboken6/tests/libsmart/smart.cpp
+++ b/sources/shiboken6/tests/libsmart/smart.cpp
@@ -293,7 +293,5 @@ Smart::Integer2::Integer2()
{
}
-Smart::Integer2::Integer2(const Smart::Integer2 &other)
- : Integer (other)
-{
-}
+Smart::Integer2::Integer2(const Smart::Integer2 &) = default;
+Smart::Integer2 &Smart::Integer2::operator=(const Integer2 &) = default;
diff --git a/sources/shiboken6/tests/libsmart/smart_integer.h b/sources/shiboken6/tests/libsmart/smart_integer.h
index 0f2dfcec9..a9ee6b1c4 100644
--- a/sources/shiboken6/tests/libsmart/smart_integer.h
+++ b/sources/shiboken6/tests/libsmart/smart_integer.h
@@ -81,7 +81,8 @@ namespace Smart {
class LIB_SMART_API Integer2 : public Integer {
public:
Integer2();
- Integer2(const Integer2 &other);
+ Integer2(const Integer2 &);
+ Integer2 &operator=(const Integer2 &);
};
} // namespace Smart
diff --git a/tools/example_gallery/main.py b/tools/example_gallery/main.py
index 291514ab0..7e69c36fe 100644
--- a/tools/example_gallery/main.py
+++ b/tools/example_gallery/main.py
@@ -168,7 +168,7 @@ def get_code_tabs(files, project_dir):
_path = project_dir / project_file
_file_content = ""
try:
- with open(_path, "r") as _f:
+ with open(_path, "r", encoding="utf-8") as _f:
_file_content = remove_licenses(_f.read())
except UnicodeDecodeError as e:
print(f"example_gallery: error decoding {_path}:{e}")
@@ -180,10 +180,10 @@ def get_code_tabs(files, project_dir):
def get_header_title(example_dir):
- _title = str(example_dir)
_index = example_dir.parts.index("examples")
- url_name = "/".join(example_dir.parts[_index + 1:])
- url = f"{BASE_URL}/{url_name}"
+ rel_path = "/".join(example_dir.parts[_index:])
+ _title = rel_path
+ url = f"{BASE_URL}/{rel_path}"
return (
"..\n This file was auto-generated by the 'examples_gallery' "
"script.\n Any change will be lost!\n\n"
@@ -198,7 +198,7 @@ if __name__ == "__main__":
DIR = Path(__file__).parent
EXAMPLES_DOC = Path(f"{DIR}/../../sources/pyside6/doc/examples").resolve()
EXAMPLES_DIR = Path(f"{DIR}/../../examples/").resolve()
- BASE_URL = "https://code.qt.io/cgit/pyside/pyside-setup.git/tree/examples"
+ BASE_URL = "https://code.qt.io/cgit/pyside/pyside-setup.git/tree"
columns = 5
gallery = ""
@@ -276,7 +276,7 @@ if __name__ == "__main__":
files = []
try:
- with pyproject_file.open("r") as pyf:
+ with pyproject_file.open("r", encoding="utf-8") as pyf:
pyproject = json.load(pyf)
files = pyproject["files"]
except (json.JSONDecodeError, KeyError) as e:
@@ -286,11 +286,11 @@ if __name__ == "__main__":
if files:
rst_file_full = EXAMPLES_DOC / rst_file
- with open(rst_file_full, "w") as out_f:
+ with open(rst_file_full, "w", encoding="utf-8") as out_f:
if has_doc:
doc_rst = original_doc_dir / f"{example_name}.rst"
- with open(doc_rst) as doc_f:
+ with open(doc_rst, encoding="utf-8") as doc_f:
content_f = doc_f.read()
# Copy other files in the 'doc' directory, but
diff --git a/tools/snippets_translate/converter.py b/tools/snippets_translate/converter.py
index 01df94505..98de860b2 100644
--- a/tools/snippets_translate/converter.py
+++ b/tools/snippets_translate/converter.py
@@ -46,10 +46,38 @@ from handlers import (handle_array_declarations, handle_casts, handle_class,
handle_inc_dec, handle_include, handle_keywords,
handle_methods_return_type, handle_negate,
handle_type_var_declaration, handle_useless_qt_classes,
- handle_void_functions)
+ handle_new,
+ handle_void_functions, handle_qt_connects)
from parse_utils import dstrip, get_indent, remove_ref
+VOID_METHOD_PATTERN = re.compile(r"^ *void *[\w\_]+(::)?[\w\d\_]+\(")
+QT_QUALIFIER_PATTERN = re.compile(r"Q[\w]+::")
+TERNARY_OPERATOR_PATTERN = re.compile(r"^.* \? .+ : .+$")
+COUT_PATTERN = re.compile("^ *(std::)?cout")
+FOR_PATTERN = re.compile(r"^ *for *\(")
+FOREACH_PATTERN = re.compile(r"^ *foreach *\(")
+ELSE_PATTERN = re.compile(r"^ *}? *else *{?")
+ELSE_REPLACEMENT_PATTERN = re.compile(r"}? *else *{?")
+CLASS_PATTERN = re.compile(r"^ *class ")
+STRUCT_PATTERN = re.compile(r"^ *struct ")
+DELETE_PATTERN = re.compile(r"^ *delete ")
+VAR1_PATTERN = re.compile(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*\&]+(\(.*?\))? ?(?!.*=|:).*$")
+VAR2_PATTERN = re.compile(r"^[a-zA-Z0-9]+(<.*?>)? [\w]+::[\w\*\&]+\(.*\)$")
+VAR3_PATTERN = re.compile(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*]+ *= *[\w\.\"\']*(\(.*?\))?")
+VAR4_PATTERN = re.compile(r"\w+ = [A-Z]{1}\w+")
+CONSTRUCTOR_PATTERN = re.compile(r"^ *\w+::\w+\(.*?\)")
+ARRAY_VAR_PATTERN = re.compile(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*]+\[?\]? * =? *\{")
+RETURN_TYPE_PATTERN = re.compile(r"^[a-zA-Z0-9]+(<.*?>)? [\w]+::[\w\*\&]+\(.*\)$")
+FUNCTION_PATTERN = re.compile(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*\&]+\(.*\)$")
+ITERATOR_PATTERN = re.compile(r"(std::)?[\w]+<[\w]+>::(const_)?iterator")
+SCOPE_PATTERN = re.compile(r"[\w]+::")
+
+
+QUALIFIERS = {"public:", "protected:", "private:", "public slots:",
+ "protected slots:", "private slots:", "signals:"}
+
+
def snippet_translate(x):
## Cases which are not C++
@@ -64,18 +92,23 @@ def snippet_translate(x):
x = x[:-1]
# Remove lines with only '{' or '}'
- if x.strip() == "{" or x.strip() == "}":
+ xs = x.strip()
+ if xs == "{" or xs == "}":
return ""
# Skip lines with the snippet related identifier '//!'
- if x.strip().startswith("//!"):
+ if xs.startswith("//!"):
return x
# handle lines with only comments using '//'
- if x.lstrip().startswith("//"):
+ if xs.startswith("//"):
x = x.replace("//", "#", 1)
return x
+ qt_connects = handle_qt_connects(x)
+ if qt_connects:
+ return qt_connects
+
# Handle "->"
if "->" in x:
x = x.replace("->", ".")
@@ -97,7 +130,7 @@ def snippet_translate(x):
# This contains an extra whitespace because of some variables
# that include the string 'new'
if "new " in x:
- x = x.replace("new ", "")
+ x = handle_new(x)
# Handle 'const'
# Some variables/functions have the word 'const' so we explicitly
@@ -140,11 +173,11 @@ def snippet_translate(x):
x = handle_keywords(x, "throw", "raise")
# handle 'void Class::method(...)' and 'void method(...)'
- if re.search(r"^ *void *[\w\_]+(::)?[\w\d\_]+\(", x):
+ if VOID_METHOD_PATTERN.search(x):
x = handle_void_functions(x)
# 'Q*::' -> 'Q*.'
- if re.search(r"Q[\w]+::", x):
+ if QT_QUALIFIER_PATTERN.search(x):
x = x.replace("::", ".")
# handle 'nullptr'
@@ -152,78 +185,76 @@ def snippet_translate(x):
x = x.replace("nullptr", "None")
## Special Cases Rules
-
+ xs = x.strip()
# Special case for 'main'
- if x.strip().startswith("int main("):
+ if xs.startswith("int main("):
return f'{get_indent(x)}if __name__ == "__main__":'
- if x.strip().startswith("QApplication app(argc, argv)"):
+ if xs.startswith("QApplication app(argc, argv)"):
return f"{get_indent(x)}app = QApplication([])"
# Special case for 'return app.exec()'
- if x.strip().startswith("return app.exec"):
+ if xs.startswith("return app.exec"):
return x.replace("return app.exec()", "sys.exit(app.exec())")
# Handle includes -> import
- if x.strip().startswith("#include"):
+ if xs.startswith("#include"):
x = handle_include(x)
return dstrip(x)
- if x.strip().startswith("emit "):
+ if xs.startswith("emit "):
x = handle_emit(x)
return dstrip(x)
# *_cast
if "_cast<" in x:
x = handle_casts(x)
+ xs = x.strip()
# Handle Qt classes that needs to be removed
x = handle_useless_qt_classes(x)
# Handling ternary operator
- if re.search(r"^.* \? .+ : .+$", x.strip()):
+ if TERNARY_OPERATOR_PATTERN.search(xs):
x = x.replace(" ? ", " if ")
x = x.replace(" : ", " else ")
+ xs = x.strip()
# Handle 'while', 'if', and 'else if'
# line might end in ')' or ") {"
- if x.strip().startswith(("while", "if", "else if", "} else if")):
+ if xs.startswith(("while", "if", "else if", "} else if")):
x = handle_conditions(x)
return dstrip(x)
- elif re.search("^ *}? *else *{?", x):
- x = re.sub(r"}? *else *{?", "else:", x)
+ elif ELSE_PATTERN.search(x):
+ x = ELSE_REPLACEMENT_PATTERN.sub("else:", x)
return dstrip(x)
# 'cout' and 'endl'
- if re.search("^ *(std::)?cout", x) or ("endl" in x) or x.lstrip().startswith("qDebug()"):
+ if COUT_PATTERN.search(x) or ("endl" in x) or xs.startswith("qDebug()"):
x = handle_cout_endl(x)
return dstrip(x)
# 'for' loops
- if re.search(r"^ *for *\(", x.strip()):
+ if FOR_PATTERN.search(xs):
return dstrip(handle_for(x))
# 'foreach' loops
- if re.search(r"^ *foreach *\(", x.strip()):
+ if FOREACH_PATTERN.search(xs):
return dstrip(handle_foreach(x))
# 'class' and 'structs'
- if re.search(r"^ *class ", x) or re.search(r"^ *struct ", x):
+ if CLASS_PATTERN.search(x) or STRUCT_PATTERN.search(x):
if "struct " in x:
x = x.replace("struct ", "class ")
return handle_class(x)
# 'delete'
- if re.search(r"^ *delete ", x):
+ if DELETE_PATTERN.search(x):
return x.replace("delete", "del")
- # 'public:'
- if re.search(r"^public:$", x.strip()):
- return x.replace("public:", "# public")
-
- # 'private:'
- if re.search(r"^private:$", x.strip()):
- return x.replace("private:", "# private")
+ # 'public:', etc
+ if xs in QUALIFIERS:
+ return f"# {x}".replace(":", "")
# For expressions like: `Type var`
# which does not contain a `= something` on the right side
@@ -238,9 +269,9 @@ def snippet_translate(x):
# At the end we skip methods with the form:
# QStringView Message::body()
# to threat them as methods.
- if (re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*\&]+(\(.*?\))? ?(?!.*=|:).*$", x.strip())
- and x.strip().split()[0] not in ("def", "return", "and", "or")
- and not re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w]+::[\w\*\&]+\(.*\)$", x.strip())
+ if (VAR1_PATTERN.search(xs)
+ and xs.split()[0] not in ("def", "return", "and", "or")
+ and not VAR2_PATTERN.search(xs)
and ("{" not in x and "}" not in x)):
# FIXME: this 'if' is a hack for a function declaration with this form:
@@ -257,7 +288,7 @@ def snippet_translate(x):
# QSome thing = b(...)
# float v = 0.1
# QSome *thing = ...
- if (re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*]+ *= *[\w\.\"\']*(\(.*?\))?", x.strip())
+ if (VAR3_PATTERN.search(xs)
and ("{" not in x and "}" not in x)):
left, right = x.split("=", 1)
var_name = " ".join(left.strip().split()[1:])
@@ -268,23 +299,23 @@ def snippet_translate(x):
# layout = QVBoxLayout
# so we need to add '()' at the end if it's just a word
# with only alpha numeric content
- if re.search(r"\w+ = [A-Z]{1}\w+", x.strip()) and not x.strip().endswith(")"):
+ if VAR4_PATTERN.search(xs) and not xs.endswith(")"):
x = f"{x.rstrip()}()"
return dstrip(x)
# For constructors, that we now the shape is:
# ClassName::ClassName(...)
- if re.search(r"^ *\w+::\w+\(.*?\)", x.strip()):
+ if CONSTRUCTOR_PATTERN.search(xs):
x = handle_constructors(x)
return dstrip(x)
# For base object constructor:
# : QWidget(parent)
if (
- x.strip().startswith(": ")
+ xs.startswith(": ")
and ("<<" not in x)
and ("::" not in x)
- and not x.strip().endswith(";")
+ and not xs.endswith(";")
):
return handle_constructor_default_values(x)
@@ -293,27 +324,30 @@ def snippet_translate(x):
# type var_name[] = {...
# type var_name {...
# if re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*]+\[\] * = *\{", x.strip()):
- if re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*]+\[?\]? * =? *\{", x.strip()):
+ if ARRAY_VAR_PATTERN.search(xs):
x = handle_array_declarations(x)
+ xs = x.strip()
# Methods with return type
# int Class::method(...)
# QStringView Message::body()
- if re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w]+::[\w\*\&]+\(.*\)$", x.strip()):
+ if RETURN_TYPE_PATTERN.search(xs):
# We just need to capture the 'method name' and 'arguments'
x = handle_methods_return_type(x)
+ xs = x.strip()
# Handling functions
# By this section of the function, we cover all the other cases
# So we can safely assume it's not a variable declaration
- if re.search(r"^[a-zA-Z0-9]+(<.*?>)? [\w\*\&]+\(.*\)$", x.strip()):
+ if FUNCTION_PATTERN.search(xs):
x = handle_functions(x)
+ xs = x.strip()
# if it is a C++ iterator declaration, then ignore it due to dynamic typing in Python
# eg: std::vector<int> it;
# the case of iterator being used inside a for loop is already handed in handle_for(..)
# TODO: handle iterator initialization statement like it = container.begin();
- if re.search(r"(std::)?[\w]+<[\w]+>::(const_)?iterator", x):
+ if ITERATOR_PATTERN.search(x):
x = ""
return x
@@ -321,7 +355,7 @@ def snippet_translate(x):
# 'Namespace*::' -> 'Namespace*.'
# TODO: In the case where a C++ class function is defined outside the class, this would be wrong
# but we do not have such a code snippet yet
- if re.search(r"[\w]+::", x):
+ if SCOPE_PATTERN.search(x):
x = x.replace("::", ".")
# General return for no special cases
diff --git a/tools/snippets_translate/handlers.py b/tools/snippets_translate/handlers.py
index 8f58d218f..8a074a040 100644
--- a/tools/snippets_translate/handlers.py
+++ b/tools/snippets_translate/handlers.py
@@ -43,9 +43,39 @@ import sys
from parse_utils import (dstrip, get_indent, get_qt_module_class,
parse_arguments, remove_ref, replace_main_commas)
-IF_PATTERN = re.compile(r'^if\s*\(')
-ELSE_IF_PATTERN = re.compile(r'^}?\s*else if\s*\(')
-WHILE_PATTERN = re.compile(r'^while\s*\(')
+IF_PATTERN = re.compile(r'^\s*if\s*\(')
+PARENTHESES_NONEMPTY_CONTENT_PATTERN = re.compile(r"\((.+)\)")
+LOCAL_INCLUDE_PATTERN = re.compile(r'"(.*)"')
+GLOBAL_INCLUDE_PATTERN = re.compile(r"<(.*)>")
+IF_CONDITION_PATTERN = PARENTHESES_NONEMPTY_CONTENT_PATTERN
+ELSE_IF_PATTERN = re.compile(r'^\s*}?\s*else if\s*\(')
+WHILE_PATTERN = re.compile(r'^\s*while\s*\(')
+CAST_PATTERN = re.compile(r"[a-z]+_cast<(.*?)>\((.*?)\)") # Non greedy match of <>
+ITERATOR_LOOP_PATTERN = re.compile(r"= *(.*)egin\(")
+REMOVE_TEMPLATE_PARAMETER_PATTERN = re.compile("<.*>")
+PARENTHESES_CONTENT_PATTERN = re.compile(r"\((.*)\)")
+CONSTRUCTOR_BODY_PATTERN = re.compile(".*{ *}.*")
+CONSTRUCTOR_BODY_REPLACEMENT_PATTERN = re.compile("{ *}")
+CONSTRUCTOR_BASE_PATTERN = re.compile("^ *: *")
+NEGATE_PATTERN = re.compile(r"!(.)")
+CLASS_TEMPLATE_PATTERN = re.compile(r".*<.*>")
+EMPTY_CLASS_PATTERN = re.compile(r".*{.*}")
+EMPTY_CLASS_REPLACEMENT_PATTERN = re.compile(r"{.*}")
+FUNCTION_BODY_PATTERN = re.compile(r"\{(.*)\}")
+ARRAY_DECLARATION_PATTERN = re.compile(r"^[a-zA-Z0-9\<\>]+ ([\w\*]+) *\[?\]?")
+RETURN_TYPE_PATTERN = re.compile(r"^ *[a-zA-Z0-9]+ [\w]+::([\w\*\&]+\(.*\)$)")
+CAPTURE_PATTERN = re.compile(r"^ *([a-zA-Z0-9]+) ([\w\*\&]+\(.*\)$)")
+USELESS_QT_CLASSES_PATTERNS = [
+ re.compile(r"QLatin1String\((.*)\)"),
+ re.compile(r"QLatin1Char\((.*)\)")
+]
+COMMENT1_PATTERN = re.compile(r" *# *[\w\ ]+$")
+COMMENT2_PATTERN = re.compile(r" *# *(.*)$")
+COUT_ENDL_PATTERN = re.compile(r"cout *<<(.*)<< *.*endl")
+COUT1_PATTERN = re.compile(r" *<< *")
+COUT2_PATTERN = re.compile(r".*cout *<<")
+COUT_ENDL2_PATTERN = re.compile(r"<< +endl")
+NEW_PATTERN = re.compile(r"new +([a-zA-Z][a-zA-Z0-9_]*)")
def handle_condition(x, name):
@@ -62,10 +92,9 @@ def handle_condition(x, name):
comment = f" #{comment_content[-1]}"
x = x.replace(f"//{comment_content[-1]}", "")
- re_par = re.compile(r"\((.+)\)")
- match = re_par.search(x)
+ match = IF_CONDITION_PATTERN.search(x)
if match:
- condition = re_par.search(x).group(1)
+ condition = match.group(1)
return f"{get_indent(x)}{name} {condition.strip()}:{comment}"
else:
print(f'snippets_translate: Warning "{x}" does not match condition pattern',
@@ -93,34 +122,23 @@ def handle_inc_dec(x, operator):
def handle_casts(x):
- re_type = re.compile(r"<(.*)>")
- re_data = re.compile(r"_cast<.*>\((.*)\)")
- type_name = re_type.search(x)
- data_name = re_data.search(x)
-
- if type_name and data_name:
- type_name = type_name.group(1).replace("*", "")
- data_name = data_name.group(1)
- new_value = f"{type_name}({data_name})"
-
- if "static_cast" in x:
- x = re.sub(r"static_cast<.*>\(.*\)", new_value, x)
- elif "dynamic_cast" in x:
- x = re.sub(r"dynamic_cast<.*>\(.*\)", new_value, x)
- elif "const_cast" in x:
- x = re.sub(r"const_cast<.*>\(.*\)", new_value, x)
- elif "reinterpret_cast" in x:
- x = re.sub(r"reinterpret_cast<.*>\(.*\)", new_value, x)
- elif "qobject_cast" in x:
- x = re.sub(r"qobject_cast<.*>\(.*\)", new_value, x)
+ while True:
+ match = CAST_PATTERN.search(x)
+ if not match:
+ break
+ type_name = match.group(1).strip()
+ while type_name.endswith("*") or type_name.endswith("&") or type_name.endswith(" "):
+ type_name = type_name[:-1]
+ data_name = match.group(2).strip()
+ python_cast = f"{type_name}({data_name})"
+ x = x[0:match.start(0)] + python_cast + x[match.end(0):]
return x
def handle_include(x):
if '"' in x:
- re_par = re.compile(r'"(.*)"')
- header = re_par.search(x)
+ header = LOCAL_INCLUDE_PATTERN.search(x)
if header:
header_name = header.group(1).replace(".h", "")
module_name = header_name.replace('/', '.')
@@ -130,8 +148,7 @@ def handle_include(x):
# besides '"something.h"'
x = ""
elif "<" in x and ">" in x:
- re_par = re.compile(r"<(.*)>")
- name = re_par.search(x).group(1)
+ name = GLOBAL_INCLUDE_PATTERN.search(x).group(1)
t = get_qt_module_class(name)
# if it's not a Qt module or class, we discard it.
if t is None:
@@ -159,8 +176,7 @@ def handle_conditions(x):
def handle_for(x):
- re_content = re.compile(r"\((.*)\)")
- content = re_content.search(x)
+ content = PARENTHESES_CONTENT_PATTERN.search(x)
new_x = x
if content:
@@ -175,7 +191,7 @@ def handle_for(x):
# iterators
if "begin(" in x.lower() and "end(" in x.lower():
- name = re.search(r"= *(.*)egin\(", start)
+ name = ITERATOR_LOOP_PATTERN.search(start)
iterable = None
iterator = None
if name:
@@ -256,23 +272,22 @@ def handle_for(x):
def handle_foreach(x):
- re_content = re.compile(r"\((.*)\)")
- content = re_content.search(x)
+ content = PARENTHESES_CONTENT_PATTERN.search(x)
if content:
parenthesis = content.group(1)
iterator, iterable = parenthesis.split(",", 1)
# remove iterator type
it = dstrip(iterator.split()[-1])
# remove <...> from iterable
- value = re.sub("<.*>", "", iterable)
+ value = REMOVE_TEMPLATE_PARAMETER_PATTERN.sub("", iterable)
return f"{get_indent(x)}for {it} in {value}:"
def handle_type_var_declaration(x):
# remove content between <...>
if "<" in x and ">" in x:
- x = " ".join(re.sub("<.*>", "", i) for i in x.split())
- content = re.search(r"\((.*)\)", x)
+ x = " ".join(REMOVE_TEMPLATE_PARAMETER_PATTERN.sub("", i) for i in x.split())
+ content = PARENTHESES_CONTENT_PATTERN.search(x)
if content:
# this means we have something like:
# QSome thing(...)
@@ -288,8 +303,7 @@ def handle_type_var_declaration(x):
def handle_constructors(x):
- re_content = re.compile(r"\((.*)\)")
- arguments = re_content.search(x).group(1)
+ arguments = PARENTHESES_CONTENT_PATTERN.search(x).group(1)
class_method = x.split("(")[0].split("::")
if len(class_method) == 2:
# Equal 'class name' and 'method name'
@@ -307,8 +321,8 @@ def handle_constructor_default_values(x):
# we discard that section completely, since even with a single
# value, we don't need to take care of it, for example:
# ' : a(1) { } -> self.a = 1
- if re.search(".*{ *}.*", x):
- x = re.sub("{ *}", "", x)
+ if CONSTRUCTOR_BODY_PATTERN.search(x):
+ x = CONSTRUCTOR_BODY_REPLACEMENT_PATTERN.sub("", x)
values = "".join(x.split(":", 1))
# Check the commas that are not inside round parenthesis
@@ -323,26 +337,24 @@ def handle_constructor_default_values(x):
if "@" in values:
return_values = ""
for arg in values.split("@"):
- arg = re.sub("^ *: *", "", arg).strip()
+ arg = CONSTRUCTOR_BASE_PATTERN.sub("", arg).strip()
if arg.startswith("Q"):
class_name = arg.split("(")[0]
content = arg.replace(class_name, "")[1:-1]
- return_values += f" {class_name}.__init__(self, {content})\n"
+ return_values += f" super().__init__({content})\n"
elif arg:
var_name = arg.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- content = re_par.search(arg).group(1)
+ content = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(arg).group(1)
return_values += f" self.{var_name} = {content}\n"
else:
- arg = re.sub("^ *: *", "", values).strip()
+ arg = CONSTRUCTOR_BASE_PATTERN.sub("", values).strip()
if arg.startswith("Q"):
class_name = arg.split("(")[0]
content = arg.replace(class_name, "")[1:-1]
- return f" {class_name}.__init__(self, {content})"
+ return f" super().__init__({content})"
elif arg:
var_name = arg.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- match = re_par.search(arg)
+ match = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(arg)
if match:
content = match.group(1)
return f" self.{var_name} = {content}"
@@ -356,27 +368,27 @@ def handle_constructor_default_values(x):
def handle_cout_endl(x):
# if comment at the end
comment = ""
- if re.search(r" *# *[\w\ ]+$", x):
- comment = f' # {re.search(" *# *(.*)$", x).group(1)}'
+ if COMMENT1_PATTERN.search(x):
+ match = COMMENT2_PATTERN.search(x).group(1)
+ comment = f' # {match}'
x = x.split("#")[0]
if "qDebug()" in x:
x = x.replace("qDebug()", "cout")
if "cout" in x and "endl" in x:
- re_cout_endl = re.compile(r"cout *<<(.*)<< *.*endl")
- data = re_cout_endl.search(x)
+ data = COUT_ENDL_PATTERN.search(x)
if data:
data = data.group(1)
- data = re.sub(" *<< *", ", ", data)
+ data = COUT1_PATTERN.sub(", ", data)
x = f"{get_indent(x)}print({data}){comment}"
elif "cout" in x:
- data = re.sub(".*cout *<<", "", x)
- data = re.sub(" *<< *", ", ", data)
+ data = COUT2_PATTERN.sub("", x)
+ data = COUT1_PATTERN.sub(", ", data)
x = f"{get_indent(x)}print({data}){comment}"
elif "endl" in x:
- data = re.sub("<< +endl", "", x)
- data = re.sub(" *<< *", ", ", data)
+ data = COUT_ENDL2_PATTERN.sub("", x)
+ data = COUT1_PATTERN.sub(", ", data)
x = f"{get_indent(x)}print({data}){comment}"
x = x.replace("( ", "(").replace(" )", ")").replace(" ,", ",").replace("(, ", "(")
@@ -392,8 +404,7 @@ def handle_negate(x):
elif "/*" in x:
if x.index("/*") < x.index("!"):
return x
- re_negate = re.compile(r"!(.)")
- next_char = re_negate.search(x).group(1)
+ next_char = NEGATE_PATTERN.search(x).group(1)
if next_char not in ("=", '"'):
x = x.replace("!", "not ")
return x
@@ -401,8 +412,7 @@ def handle_negate(x):
def handle_emit(x):
function_call = x.replace("emit ", "").strip()
- re_content = re.compile(r"\((.*)\)")
- match = re_content.search(function_call)
+ match = PARENTHESES_CONTENT_PATTERN.search(function_call)
if not match:
stmt = x.strip()
print(f'snippets_translate: Warning "{stmt}" does not match function call',
@@ -425,15 +435,14 @@ def handle_void_functions(x):
# if the arguments are in the same line:
arguments = None
if ")" in x:
- re_content = re.compile(r"\((.*)\)")
- parenthesis = re_content.search(x).group(1)
+ parenthesis = PARENTHESES_CONTENT_PATTERN.search(x).group(1)
arguments = dstrip(parse_arguments(parenthesis))
elif "," in x:
arguments = dstrip(parse_arguments(x.split("(")[-1]))
# check if includes a '{ ... }' after the method signature
after_signature = x.split(")")[-1]
- re_decl = re.compile(r"\{(.*)\}").search(after_signature)
+ re_decl = FUNCTION_BODY_PATTERN.search(after_signature)
extra = ""
if re_decl:
extra = re_decl.group(1)
@@ -469,13 +478,13 @@ def handle_class(x):
bases_name = ""
# Check if the class_name is templated, then remove it
- if re.search(r".*<.*>", class_name):
+ if CLASS_TEMPLATE_PATTERN.search(class_name):
class_name = class_name.split("<")[0]
# Special case: invalid notation for an example:
# class B() {...} -> clas B(): pass
- if re.search(r".*{.*}", class_name):
- class_name = re.sub(r"{.*}", "", class_name).rstrip()
+ if EMPTY_CLASS_PATTERN.search(class_name):
+ class_name = EMPTY_CLASS_REPLACEMENT_PATTERN.sub("", class_name).rstrip()
return f"{class_name}(): pass"
# Special case: check if the line ends in ','
@@ -491,8 +500,7 @@ def handle_class(x):
def handle_array_declarations(x):
- re_varname = re.compile(r"^[a-zA-Z0-9\<\>]+ ([\w\*]+) *\[?\]?")
- content = re_varname.search(x.strip())
+ content = ARRAY_DECLARATION_PATTERN.search(x.strip())
if content:
var_name = content.group(1)
rest_line = "".join(x.split("{")[1:])
@@ -501,13 +509,11 @@ def handle_array_declarations(x):
def handle_methods_return_type(x):
- re_capture = re.compile(r"^ *[a-zA-Z0-9]+ [\w]+::([\w\*\&]+\(.*\)$)")
- capture = re_capture.search(x)
+ capture = RETURN_TYPE_PATTERN.search(x)
if capture:
content = capture.group(1)
method_name = content.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- par_capture = re_par.search(x)
+ par_capture = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(x)
arguments = "(self)"
if par_capture:
arguments = f"(self, {par_capture.group(1)})"
@@ -516,13 +522,14 @@ def handle_methods_return_type(x):
def handle_functions(x):
- re_capture = re.compile(r"^ *[a-zA-Z0-9]+ ([\w\*\&]+\(.*\)$)")
- capture = re_capture.search(x)
+ capture = CAPTURE_PATTERN.search(x)
if capture:
- content = capture.group(1)
+ return_type = capture.group(1)
+ if return_type == "return": # "return QModelIndex();"
+ return x
+ content = capture.group(2)
function_name = content.split("(")[0]
- re_par = re.compile(r"\((.+)\)")
- par_capture = re_par.search(x)
+ par_capture = PARENTHESES_NONEMPTY_CONTENT_PATTERN.search(x)
arguments = ""
if par_capture:
for arg in par_capture.group(1).split(","):
@@ -535,10 +542,71 @@ def handle_functions(x):
def handle_useless_qt_classes(x):
- _classes = ("QLatin1String", "QLatin1Char")
- for i in _classes:
- re_content = re.compile(fr"{i}\((.*)\)")
- content = re_content.search(x)
+ for c in USELESS_QT_CLASSES_PATTERNS:
+ content = c.search(x)
if content:
x = x.replace(content.group(0), content.group(1))
return x
+
+
+def handle_new(x):
+ """Parse operator new() and add parentheses were needed:
+ func(new Foo, new Bar(x))" -> "func(Foo(), Bar(x))"""
+ result = ""
+ last_pos = 0
+ for match in NEW_PATTERN.finditer(x):
+ end = match.end(0)
+ parentheses_needed = end >= len(x) or x[end] != "("
+ type_name = match.group(1)
+ result += x[last_pos:match.start(0)] + type_name
+ if parentheses_needed:
+ result += "()"
+ last_pos = end
+ result += x[last_pos:]
+ return result
+
+
+# The code below handles pairs of instance/pointer to member functions (PMF)
+# which appear in Qt in connect statements like:
+# "connect(fontButton, &QAbstractButton::clicked, this, &Dialog::setFont)".
+# In a first pass, these pairs are replaced by:
+# "connect(fontButton.clicked, self.setFont)" to be able to handle statements
+# spanning lines. A 2nd pass then checks for the presence of a connect
+# statement and replaces it by:
+# "fontButton.clicked.connect(self.setFont)".
+# To be called right after checking for comments.
+
+
+INSTANCE_PMF_RE = re.compile(r"&?(\w+),\s*&\w+::(\w+)")
+
+
+CONNECT_RE = re.compile(r"^(\s*)(QObject::)?connect\((\w+\.\w+),\s*")
+
+
+def handle_qt_connects(line):
+ if not INSTANCE_PMF_RE.search(line):
+ return None
+ # 1st pass, "fontButton, &QAbstractButton::clicked" -> "fontButton.clicked"
+ last_pos = 0
+ result = ""
+ for match in INSTANCE_PMF_RE.finditer(line):
+ instance = match.group(1)
+ if instance == "this":
+ instance = "self"
+ member_fun = match.group(2)
+ next_pos = match.start()
+ result += line[last_pos:next_pos]
+ last_pos = match.end()
+ result += f"{instance}.{member_fun}"
+ result += line[last_pos:]
+
+ # 2nd pass, reorder connect.
+ connect_match = CONNECT_RE.match(result)
+ if not connect_match:
+ return result
+
+ space = connect_match.group(1)
+ signal_ = connect_match.group(3)
+ connect_stmt = f"{space}{signal_}.connect("
+ connect_stmt += result[connect_match.end():]
+ return connect_stmt
diff --git a/tools/snippets_translate/override.py b/tools/snippets_translate/override.py
index f0f76fd2b..c766b3336 100644
--- a/tools/snippets_translate/override.py
+++ b/tools/snippets_translate/override.py
@@ -41,6 +41,7 @@ from pathlib import Path
ROOT_PATH = Path(__file__).parents[2]
EXAMPLES_PATH = ROOT_PATH / "examples"
+TUTORIAL_EXAMPLES_PATH = ROOT_PATH / "sources" / "pyside6" / "doc" / "tutorials"
_PYTHON_EXAMPLE_SNIPPET_MAPPING = {
@@ -76,7 +77,9 @@ _PYTHON_EXAMPLE_SNIPPET_MAPPING = {
(EXAMPLES_PATH / "widgets" / "tutorials" / "modelview" / "7_selections.py", "1"),
("qtbase/examples/widgets/tutorials/modelview/7_selections/mainwindow.cpp",
"quoting modelview_b"):
- (EXAMPLES_PATH / "widgets" / "tutorials" / "modelview" / "7_selections.py", "2")
+ (EXAMPLES_PATH / "widgets" / "tutorials" / "modelview" / "7_selections.py", "2"),
+ ("qtbase/src/widgets/doc/snippets/qlistview-dnd/mainwindow.cpp.cpp", "0"):
+ (TUTORIAL_EXAMPLES_PATH / "modelviewprogramming" / "qlistview-dnd.py", "mainwindow0")
}
@@ -87,6 +90,59 @@ def python_example_snippet_mapping():
global _python_example_snippet_mapping
if not _python_example_snippet_mapping:
result = _PYTHON_EXAMPLE_SNIPPET_MAPPING
+
+ qt_path = "qtbase/src/widgets/doc/snippets/simplemodel-use/main.cpp"
+ pyside_path = TUTORIAL_EXAMPLES_PATH / "modelviewprogramming" / "stringlistmodel.py"
+ for i in range(3):
+ snippet_id = str(i)
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
+ qt_path = "qtbase/src/widgets/doc/snippets/stringlistmodel/main.cpp"
+ pyside_path = TUTORIAL_EXAMPLES_PATH / "modelviewprogramming" / "stringlistmodel.py"
+ for i in range(6):
+ snippet_id = str(i)
+ result[(qt_path, snippet_id)] = pyside_path, f"main{snippet_id}"
+
+ qt_path = "qtbase/examples/widgets/itemviews/spinboxdelegate/delegate.cpp"
+ pyside_path = (EXAMPLES_PATH / "widgets" / "itemviews" / "spinboxdelegate"
+ / "spinboxdelegate.py")
+ for i in range(5):
+ snippet_id = str(i)
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
+ qt_path = "qtbase/src/widgets/doc/snippets/stringlistmodel/model.cpp"
+ pyside_path = (TUTORIAL_EXAMPLES_PATH / "modelviewprogramming"
+ / "stringlistmodel.py")
+ for i in range(10):
+ snippet_id = str(i)
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
+ qt_path = "qtbase/src/widgets/doc/snippets/qlistview-dnd/model.cpp"
+ pyside_path = (TUTORIAL_EXAMPLES_PATH / "modelviewprogramming"
+ / "qlistview-dnd.py")
+ for i in range(11):
+ snippet_id = str(i)
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
+ qt_path = "qtconnectivity/examples/bluetooth/heartrate_game/devicefinder.cpp"
+ pyside_path = EXAMPLES_PATH / "bluetooth" / "heartrate_game" / "devicefinder.py"
+ for i in range(5):
+ snippet_id = f"devicediscovery-{i}"
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
+ qt_path = "qtconnectivity/examples/bluetooth/heartrate_game/devicehandler.cpp"
+ pyside_path = EXAMPLES_PATH / "bluetooth" / "heartrate_game" / "devicehandler.py"
+ for snippet_id in ["Connect-Signals-1", "Connect-Signals-2",
+ "Filter HeartRate service 2", "Find HRM characteristic",
+ "Reading value"]:
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
+ qt_path = "qtconnectivity/examples/bluetooth/heartrate_server/main.cpp"
+ pyside_path = EXAMPLES_PATH / "bluetooth" / "heartrate_server" / "heartrate_server.py"
+ for snippet_id in ["Advertising Data", "Start Advertising", "Service Data",
+ "Provide Heartbeat"]:
+ result[(qt_path, snippet_id)] = pyside_path, snippet_id
+
_python_example_snippet_mapping = result
return _python_example_snippet_mapping
diff --git a/tools/snippets_translate/snippets_translate.pyproject b/tools/snippets_translate/snippets_translate.pyproject
index 6073e9b89..f660033c1 100644
--- a/tools/snippets_translate/snippets_translate.pyproject
+++ b/tools/snippets_translate/snippets_translate.pyproject
@@ -1,3 +1,4 @@
{
- "files": ["main.py", "converter.py", "handlers.py", "override.py", "tests/test_converter.py"]
+ "files": ["main.py", "converter.py", "handlers.py", "override.py",
+ "tests/test_converter.py", "tests/test_snippets.py"]
}
diff --git a/tools/snippets_translate/tests/test_converter.py b/tools/snippets_translate/tests/test_converter.py
index a41f3190e..813c07ac5 100644
--- a/tools/snippets_translate/tests/test_converter.py
+++ b/tools/snippets_translate/tests/test_converter.py
@@ -78,6 +78,7 @@ def test_and_or():
def test_while_if_elseif():
assert st("while(a)") == "while a:"
assert st("if (condition){") == "if condition:"
+ assert st(" if (condition){") == " if condition:"
assert st("} else if (a) {") == " elif a:"
assert (
st("if (!m_vbo.isCreated()) // init() failed,")
@@ -99,7 +100,11 @@ def test_else():
def test_new():
assert st("a = new Something(...);") == "a = Something(...)"
- assert st("a = new Something") == "a = Something"
+ assert st("a = new Something") == "a = Something()"
+ assert st("foo(new X, new Y(b), new Z)") == "foo(X(), Y(b), Z())"
+ # Class member initialization list
+ assert st("m_mem(new Something(p)),") == "m_mem(Something(p)),"
+ assert st("m_mem(new Something),") == "m_mem(Something()),"
def test_semicolon():
@@ -126,6 +131,10 @@ def test_cast():
st("elapsed = (elapsed + qobject_cast<QTimer*>(sender())->interval()) % 1000;")
== "elapsed = (elapsed + QTimer(sender()).interval()) % 1000"
)
+ assert (
+ st("a = qobject_cast<type*>(data) * 9 + static_cast<int>(42)")
+ == "a = type(data) * 9 + int(42)"
+ )
def test_double_colon():
@@ -136,7 +145,7 @@ def test_double_colon():
# multiline statement connect statement
# eg: connect(reply, &QNetworkReply::errorOccurred,
# this, &MyClass::slotError);
- assert st("this, &MyClass::slotError);") == "self, MyClass.slotError)"
+ assert st("this, &MyClass::slotError);") == "self.slotError)"
def test_cout_endl():
@@ -321,24 +330,24 @@ def test_constuctors():
def test_inheritance_init():
assert (
st(": QClass(fun(re, 1, 2), parent), a(1)")
- == " QClass.__init__(self, fun(re, 1, 2), parent)\n self.a = 1"
+ == " super().__init__(fun(re, 1, 2), parent)\n self.a = 1"
)
assert (
st(": QQmlNdefRecord(copyFooRecord(record), parent)")
- == " QQmlNdefRecord.__init__(self, copyFooRecord(record), parent)"
+ == " super().__init__(copyFooRecord(record), parent)"
)
assert (
st(" : QWidget(parent), helper(helper)")
- == " QWidget.__init__(self, parent)\n self.helper = helper"
+ == " super().__init__(parent)\n self.helper = helper"
)
- assert st(" : QWidget(parent)") == " QWidget.__init__(self, parent)"
+ assert st(" : QWidget(parent)") == " super().__init__(parent)"
assert (
st(": a(0), bB(99), cC2(1), p_S(10),")
== " self.a = 0\n self.bB = 99\n self.cC2 = 1\n self.p_S = 10"
)
assert (
st(": QAbstractFileEngineIterator(nameFilters, filters), index(0) ")
- == " QAbstractFileEngineIterator.__init__(self, nameFilters, filters)\n self.index = 0"
+ == " super().__init__(nameFilters, filters)\n self.index = 0"
)
assert (
st(": m_document(doc), m_text(text)") == " self.m_document = doc\n self.m_text = text"
@@ -348,7 +357,7 @@ def test_inheritance_init():
st(": option->palette.color(QPalette::Mid);")
== " self.option.palette.color = QPalette.Mid"
)
- assert st(": QSqlResult(driver) {}") == " QSqlResult.__init__(self, driver)"
+ assert st(": QSqlResult(driver) {}") == " super().__init__(driver)"
def test_arrays():
@@ -366,6 +375,7 @@ def test_functions():
st("QString myDecoderFunc(const QByteArray &localFileName);")
== "def myDecoderFunc(localFileName):"
)
+ assert st("return QModelIndex();") == "return QModelIndex()"
def test_foreach():
@@ -409,7 +419,7 @@ def test_special_cases():
)
assert (
st("QObject::connect(&window1, &Window::messageSent,")
- == "QObject.connect(window1, Window.messageSent,"
+ == "window1.messageSent.connect("
)
assert st("double num;") == "num = float()"
diff --git a/tools/snippets_translate/tests/test_snippets.py b/tools/snippets_translate/tests/test_snippets.py
index 802bbc662..3c04a14b1 100644
--- a/tools/snippets_translate/tests/test_snippets.py
+++ b/tools/snippets_translate/tests/test_snippets.py
@@ -37,7 +37,7 @@
##
#############################################################################
-from main import get_snippets, get_snippet_ids
+from main import _get_snippets, get_snippet_ids, CPP_SNIPPET_PATTERN
def test_stacking():
@@ -48,13 +48,23 @@ def test_stacking():
"//! [C] //! [A] ",
"//! [B] //! [D] //! [E]",
]
- snippets = get_snippets(lines)
+ snippets = _get_snippets(lines, CPP_SNIPPET_PATTERN)
assert len(snippets) == 5
- assert len(snippets[0]) == 4 # A starts at line 0 and ends at line 3
- assert len(snippets[1]) == 5 # B starts at line 0 and ends at line 4
- assert len(snippets[2]) == 3 # C starts at line 1 and ends at line 3
- assert len(snippets[3]) == 4 # D starts at line 1 and ends at line 4
- assert len(snippets[4]) == 4 # E starts at line 1 and ends at line 4
+
+ snippet_a = snippets["A"]
+ assert len(snippet_a) == 4 # A starts at line 0 and ends at line 3
+
+ snippet_b = snippets["B"]
+ assert len(snippet_b) == 5 # B starts at line 0 and ends at line 4
+
+ snippet_c = snippets["C"]
+ assert len(snippet_c) == 3 # C starts at line 1 and ends at line 3
+
+ snippet_d = snippets["D"]
+ assert len(snippet_d) == 4 # D starts at line 1 and ends at line 4
+
+ snippet_e = snippets["E"]
+ assert len(snippet_e) == 4 # E starts at line 1 and ends at line 4
def test_nesting():
@@ -67,17 +77,20 @@ def test_nesting():
"//! [C]",
"//! [B]",
]
- snippets = get_snippets(lines)
+ snippets = _get_snippets(lines, CPP_SNIPPET_PATTERN)
assert len(snippets) == 3
- assert len(snippets[0]) == 5
- assert snippets[0] == lines[:5]
+ snippet_a = snippets["A"]
+ assert len(snippet_a) == 5
+ assert snippet_a == lines[:5]
- assert len(snippets[1]) == 6
- assert snippets[1] == lines[1:]
+ snippet_b = snippets["B"]
+ assert len(snippet_b) == 6
+ assert snippet_b == lines[1:]
- assert len(snippets[2]) == 4
- assert snippets[2] == lines[2:6]
+ snippet_c = snippets["C"]
+ assert len(snippet_c) == 4
+ assert snippet_c == lines[2:6]
def test_overlapping():
@@ -93,17 +106,20 @@ def test_overlapping():
"posttext",
"//! [C]",
]
- snippets = get_snippets(lines)
+ snippets = _get_snippets(lines, CPP_SNIPPET_PATTERN)
assert len(snippets) == 3
- assert len(snippets[0]) == 4
- assert snippets[0] == lines[1:5]
+ snippet_a = snippets["A"]
+ assert len(snippet_a) == 4
+ assert snippet_a == lines[1:5]
- assert len(snippets[1]) == 7
- assert snippets[1] == lines[3:]
+ snippet_c = snippets["C"]
+ assert len(snippet_c) == 7
+ assert snippet_c == lines[3:]
- assert len(snippets[2]) == 4
- assert snippets[2] == lines[4:8]
+ snippet_b = snippets["B"]
+ assert len(snippet_b) == 4
+ assert snippet_b == lines[4:8]
def test_snippets():
@@ -118,20 +134,27 @@ def test_snippets():
"posttext"
]
- snippets = get_snippets(lines)
+ snippets = _get_snippets(lines, CPP_SNIPPET_PATTERN)
assert len(snippets) == 2
- assert len(snippets[0]) == 3
- assert snippets[0] == lines[1:4]
+ snippet_a = snippets["A"]
+ assert len(snippet_a) == 3
+ assert snippet_a == lines[1:4]
- assert len(snippets[1]) == 4
- assert snippets[1] == lines[3:7]
+ snippet_b = snippets["B"]
+ assert len(snippet_b) == 4
+ assert snippet_b == lines[3:7]
def test_snippet_ids():
- assert get_snippet_ids("") == []
- assert get_snippet_ids("//! ") == [] # Invalid id
- assert get_snippet_ids("//! [some name]") == ["some name"]
- assert get_snippet_ids("//! [some name] [some other name]") == ["some name"]
- assert get_snippet_ids("//! [some name] //! ") == ["some name"] # Invalid id
- assert get_snippet_ids("//! [some name] //! [some other name]") == ["some name", "some other name"]
+ assert get_snippet_ids("", CPP_SNIPPET_PATTERN) == []
+ assert get_snippet_ids("//! ",
+ CPP_SNIPPET_PATTERN) == [] # Invalid id
+ assert get_snippet_ids("//! [some name]",
+ CPP_SNIPPET_PATTERN) == ["some name"]
+ assert get_snippet_ids("//! [some name] [some other name]",
+ CPP_SNIPPET_PATTERN) == ["some name"]
+ assert get_snippet_ids("//! [some name] //! ",
+ CPP_SNIPPET_PATTERN) == ["some name"] # Invalid id
+ assert get_snippet_ids("//! [some name] //! [some other name]",
+ CPP_SNIPPET_PATTERN) == ["some name", "some other name"]