diff options
author | Cristian Maureira-Fredes <Cristian.Maureira-Fredes@qt.io> | 2021-02-05 10:07:19 +0100 |
---|---|---|
committer | Cristian Maureira-Fredes <Cristian.Maureira-Fredes@qt.io> | 2021-02-09 22:01:33 +0100 |
commit | cc22cec1e61906408ba696fd6b5243c14b4a7f77 (patch) | |
tree | d105a1e7bff1231c8f19b4f00627ebb6a04ff19a | |
parent | 95df729709f6b460479c0a374e46ea4af629a0bb (diff) |
examples: directory structure
When generating the gallery automatically, the structure
of the examples was not the same for all the modules.
This reorganization was made under the following assumption:
An example requires:
- its own directory,
- a '.pyproject' file,
- one or more '.py' files,
- extra files (likes images, .rc, .ui, etc)
Even for cases when subdirectories are made to depict categories, like
'widgets/state-machine/...', one directory is required per example.
There should not be '.pyproject' files for categories,
except for the general 'examples.pyproject' to open all of them.
Task-number: PYSIDE-1490
Change-Id: Ie690773c816a248016dbebaad90fbb1d1c2aeea5
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
(cherry picked from commit 33743aeb2be37d166bcc3291a98dd22026871cef)
161 files changed, 2650 insertions, 267 deletions
diff --git a/examples/3d/simple3d.py b/examples/3d/simple3d/simple3d.py index 3c6ff3bf6..3c6ff3bf6 100644 --- a/examples/3d/simple3d.py +++ b/examples/3d/simple3d/simple3d.py diff --git a/examples/3d/3d.pyproject b/examples/3d/simple3d/simple3d.pyproject index 4c85ba5a4..4c85ba5a4 100644 --- a/examples/3d/3d.pyproject +++ b/examples/3d/simple3d/simple3d.pyproject diff --git a/examples/axcontainer/axviewer.py b/examples/axcontainer/axviewer.py index 2bd32ef0b..fcab3d903 100644 --- a/examples/axcontainer/axviewer.py +++ b/examples/axcontainer/axviewer.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2017 The Qt Company Ltd. diff --git a/examples/axcontainer/axviewer/axviewer.py b/examples/axcontainer/axviewer/axviewer.py new file mode 100644 index 000000000..04989c4f8 --- /dev/null +++ b/examples/axcontainer/axviewer/axviewer.py @@ -0,0 +1,83 @@ + +############################################################################# +## +## Copyright (C) 2017 The Qt Company Ltd. +## Contact: http://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 Active Qt Viewer example""" + +import sys +from PySide6.QtAxContainer import QAxSelect, QAxWidget +from PySide6.QtGui import QAction +from PySide6.QtWidgets import (QApplication, QDialog, + QMainWindow, QMessageBox, QToolBar) + +class MainWindow(QMainWindow): + + def __init__(self): + super(MainWindow, self).__init__() + + toolBar = QToolBar() + self.addToolBar(toolBar) + fileMenu = self.menuBar().addMenu("&File") + loadAction = QAction("Load...", self, shortcut="Ctrl+L", triggered=self.load) + fileMenu.addAction(loadAction) + toolBar.addAction(loadAction) + exitAction = QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close) + fileMenu.addAction(exitAction) + + aboutMenu = self.menuBar().addMenu("&About") + aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt) + aboutMenu.addAction(aboutQtAct) + self.axWidget = QAxWidget() + self.setCentralWidget(self.axWidget) + + def load(self): + axSelect = QAxSelect(self) + if axSelect.exec_() == QDialog.Accepted: + clsid = axSelect.clsid() + if not self.axWidget.setControl(clsid): + QMessageBox.warning(self, "AxViewer", "Unable to load " + clsid + ".") + +if __name__ == '__main__': + app = QApplication(sys.argv) + mainWin = MainWindow() + availableGeometry = mainWin.screen().availableGeometry() + mainWin.resize(availableGeometry.width() / 3, availableGeometry.height() / 2) + mainWin.show() + sys.exit(app.exec_()) diff --git a/examples/axcontainer/axcontainer.pyproject b/examples/axcontainer/axviewer/axviewer.pyproject index b054d6f18..b054d6f18 100644 --- a/examples/axcontainer/axcontainer.pyproject +++ b/examples/axcontainer/axviewer/axviewer.pyproject diff --git a/examples/charts/audio.py b/examples/charts/audio.py index 6d7b4895a..8a4b148af 100644 --- a/examples/charts/audio.py +++ b/examples/charts/audio.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2018 The Qt Company Ltd. diff --git a/examples/charts/audio/audio.py b/examples/charts/audio/audio.py new file mode 100644 index 000000000..969f2b9ab --- /dev/null +++ b/examples/charts/audio/audio.py @@ -0,0 +1,126 @@ + +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 charts/audio example from Qt v5.x""" + +import sys +from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis +from PySide6.QtCore import QPointF +from PySide6.QtMultimedia import (QAudioDeviceInfo, QAudioFormat, + QAudioInput) +from PySide6.QtWidgets import QApplication, QMainWindow, QMessageBox + +sampleCount = 2000 +resolution = 4 + +class MainWindow(QMainWindow): + def __init__(self, device): + super(MainWindow, self).__init__() + + self.series = QLineSeries() + self.chart = QChart() + self.chart.addSeries(self.series) + self.axisX = QValueAxis() + self.axisX.setRange(0, sampleCount) + self.axisX.setLabelFormat("%g") + self.axisX.setTitleText("Samples") + self.axisY = QValueAxis() + self.axisY.setRange(-1, 1) + self.axisY.setTitleText("Audio level") + self.chart.setAxisX(self.axisX, self.series) + self.chart.setAxisY(self.axisY, self.series) + self.chart.legend().hide() + self.chart.setTitle("Data from the microphone ({})".format(device.deviceName())) + + formatAudio = QAudioFormat() + formatAudio.setSampleRate(8000) + formatAudio.setChannelCount(1) + formatAudio.setSampleSize(8) + formatAudio.setCodec("audio/pcm") + formatAudio.setByteOrder(QAudioFormat.LittleEndian) + formatAudio.setSampleType(QAudioFormat.UnSignedInt) + + self.audioInput = QAudioInput(device, formatAudio, self) + self.ioDevice = self.audioInput.start() + self.ioDevice.readyRead.connect(self._readyRead) + + self.chartView = QChartView(self.chart) + self.setCentralWidget(self.chartView) + + self.buffer = [QPointF(x, 0) for x in range(sampleCount)] + self.series.append(self.buffer) + + def closeEvent(self, event): + if self.audioInput is not None: + self.audioInput.stop() + event.accept() + + def _readyRead(self): + data = self.ioDevice.readAll() + availableSamples = data.size() // resolution + start = 0 + if (availableSamples < sampleCount): + start = sampleCount - availableSamples + for s in range(start): + self.buffer[s].setY(self.buffer[s + availableSamples].y()) + + dataIndex = 0 + for s in range(start, sampleCount): + value = (ord(data[dataIndex]) - 128) / 128 + self.buffer[s].setY(value) + dataIndex = dataIndex + resolution + self.series.replace(self.buffer) + +if __name__ == '__main__': + app = QApplication(sys.argv) + + inputDevice = QAudioDeviceInfo.defaultInputDevice() + if (inputDevice.isNull()): + QMessageBox.warning(None, "audio", "There is no audio input device available.") + sys.exit(-1) + + mainWin = MainWindow(inputDevice) + mainWin.setWindowTitle("audio") + availableGeometry = app.desktop().availableGeometry(mainWin) + size = availableGeometry.height() * 3 / 4 + mainWin.resize(size, size) + mainWin.show() + sys.exit(app.exec_()) diff --git a/examples/charts/audio/audio.pyproject b/examples/charts/audio/audio.pyproject new file mode 100644 index 000000000..00d15e1ab --- /dev/null +++ b/examples/charts/audio/audio.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["audio.py"] +} diff --git a/examples/charts/callout.py b/examples/charts/callout/callout.py index 666b2aae5..666b2aae5 100644 --- a/examples/charts/callout.py +++ b/examples/charts/callout/callout.py diff --git a/examples/charts/callout/callout.pyproject b/examples/charts/callout/callout.pyproject new file mode 100644 index 000000000..1360c97b4 --- /dev/null +++ b/examples/charts/callout/callout.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["callout.py"] +} diff --git a/examples/charts/charts.pyproject b/examples/charts/charts.pyproject deleted file mode 100644 index 15a48a3a1..000000000 --- a/examples/charts/charts.pyproject +++ /dev/null @@ -1,5 +0,0 @@ -{ - "files": ["percentbarchart.py", "donutbreakdown.py", "legend.py", "nesteddonuts.py", - "modeldata.py", "lineandbar.py", "memoryusage.py", "callout.py", "audio.py", - "linechart.py", "logvalueaxis.py", "piechart.py", "temperaturerecords.py"] -} diff --git a/examples/charts/donutbreakdown/donutbreakdown.py b/examples/charts/donutbreakdown/donutbreakdown.py new file mode 100644 index 000000000..4c319c84f --- /dev/null +++ b/examples/charts/donutbreakdown/donutbreakdown.py @@ -0,0 +1,182 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Donut Chart Breakdown example from Qt v5.x""" + + +import sys +from PySide6.QtCore import Qt +from PySide6.QtGui import QColor, QFont, QPainter, QScreen +from PySide6.QtWidgets import QApplication, QMainWindow +from PySide6.QtCharts import QChart, QChartView, QPieSeries, QPieSlice + +class MainSlice(QPieSlice): + def __init__(self, breakdown_series, parent=None): + super(MainSlice, self).__init__(parent) + + self.breakdown_series = breakdown_series + self.name = None + + self.percentageChanged.connect(self.update_label) + + def get_breakdown_series(self): + return self.breakdown_series + + def setName(self, name): + self.name = name + + def name(self): + return self.name + + def update_label(self): + self.setLabel("{} {:.2f}%".format(self.name, + self.percentage() * 100)) + + +class DonutBreakdownChart(QChart): + def __init__(self, parent=None): + super(DonutBreakdownChart, self).__init__(QChart.ChartTypeCartesian, + parent, Qt.WindowFlags()) + self.main_series = QPieSeries() + self.main_series.setPieSize(0.7) + self.addSeries(self.main_series) + + def add_breakdown_series(self, breakdown_series, color): + font = QFont("Arial", 8) + + # add breakdown series as a slice to center pie + main_slice = MainSlice(breakdown_series) + main_slice.setName(breakdown_series.name()) + main_slice.setValue(breakdown_series.sum()) + self.main_series.append(main_slice) + + # customize the slice + main_slice.setBrush(color) + main_slice.setLabelVisible() + main_slice.setLabelColor(Qt.white) + main_slice.setLabelPosition(QPieSlice.LabelInsideHorizontal) + main_slice.setLabelFont(font) + + # position and customize the breakdown series + breakdown_series.setPieSize(0.8) + breakdown_series.setHoleSize(0.7) + breakdown_series.setLabelsVisible() + + for pie_slice in breakdown_series.slices(): + color = QColor(color).lighter(115) + pie_slice.setBrush(color) + pie_slice.setLabelFont(font) + + # add the series to the chart + self.addSeries(breakdown_series) + + # recalculate breakdown donut segments + self.recalculate_angles() + + # update customize legend markers + self.update_legend_markers() + + def recalculate_angles(self): + angle = 0 + slices = self.main_series.slices() + for pie_slice in slices: + breakdown_series = pie_slice.get_breakdown_series() + breakdown_series.setPieStartAngle(angle) + angle += pie_slice.percentage() * 360.0 # full pie is 360.0 + breakdown_series.setPieEndAngle(angle) + + def update_legend_markers(self): + # go through all markers + for series in self.series(): + markers = self.legend().markers(series) + for marker in markers: + if series == self.main_series: + # hide markers from main series + marker.setVisible(False) + else: + # modify markers from breakdown series + marker.setLabel("{} {:.2f}%".format( + marker.slice().label(), + marker.slice().percentage() * 100, 0)) + marker.setFont(QFont("Arial", 8)) + +if __name__ == "__main__": + app = QApplication(sys.argv) + # Graph is based on data of: + # 'Total consumption of energy increased by 10 per cent in 2010' + # Statistics Finland, 13 December 2011 + # http://www.stat.fi/til/ekul/2010/ekul_2010_2011-12-13_tie_001_en.html + series1 = QPieSeries() + series1.setName("Fossil fuels") + series1.append("Oil", 353295) + series1.append("Coal", 188500) + series1.append("Natural gas", 148680) + series1.append("Peat", 94545) + + series2 = QPieSeries() + series2.setName("Renewables") + series2.append("Wood fuels", 319663) + series2.append("Hydro power", 45875) + series2.append("Wind power", 1060) + + series3 = QPieSeries() + series3.setName("Others") + series3.append("Nuclear energy", 238789) + series3.append("Import energy", 37802) + series3.append("Other", 32441) + + donut_breakdown = DonutBreakdownChart() + donut_breakdown.setAnimationOptions(QChart.AllAnimations) + donut_breakdown.setTitle("Total consumption of energy in Finland 2010") + donut_breakdown.legend().setAlignment(Qt.AlignRight) + donut_breakdown.add_breakdown_series(series1, Qt.red) + donut_breakdown.add_breakdown_series(series2, Qt.darkGreen) + donut_breakdown.add_breakdown_series(series3, Qt.darkBlue) + + window = QMainWindow() + chart_view = QChartView(donut_breakdown) + chart_view.setRenderHint(QPainter.Antialiasing) + window.setCentralWidget(chart_view) + available_geometry = window.screen().availableGeometry() + size = available_geometry.height() * 0.75 + window.resize(size, size * 0.8) + window.show() + + sys.exit(app.exec_()) diff --git a/examples/charts/donutbreakdown/donutbreakdown.pyproject b/examples/charts/donutbreakdown/donutbreakdown.pyproject new file mode 100644 index 000000000..6225792da --- /dev/null +++ b/examples/charts/donutbreakdown/donutbreakdown.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["donutbreakdown.py"] +} diff --git a/examples/charts/legend/legend.py b/examples/charts/legend/legend.py new file mode 100644 index 000000000..71fd94885 --- /dev/null +++ b/examples/charts/legend/legend.py @@ -0,0 +1,252 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Legend example from Qt v5.x""" + +import sys +from PySide6.QtCore import Qt, QRectF +from PySide6.QtGui import QBrush, QColor, QPainter, QPen +from PySide6.QtWidgets import (QApplication, QDoubleSpinBox, + QFormLayout, QGridLayout, QGroupBox, QPushButton, QWidget) +from PySide6.QtCharts import QBarSeries, QBarSet, QChart, QChartView + +class MainWidget(QWidget): + def __init__(self, parent=None): + super(MainWidget, self).__init__(parent) + self.chart = QChart() + self.series = QBarSeries() + + self.main_layout = QGridLayout() + self.button_layout = QGridLayout() + self.font_layout = QFormLayout() + + self.font_size = QDoubleSpinBox() + + self.legend_posx = QDoubleSpinBox() + self.legend_posy = QDoubleSpinBox() + self.legend_width = QDoubleSpinBox() + self.legend_height = QDoubleSpinBox() + + self.detach_legend_button = QPushButton("Toggle attached") + self.detach_legend_button.clicked.connect(self.toggle_attached) + self.button_layout.addWidget(self.detach_legend_button, 0, 0) + + self.add_set_button = QPushButton("add barset") + self.add_set_button.clicked.connect(self.add_barset) + self.button_layout.addWidget(self.add_set_button, 2, 0) + + self.remove_barset_button = QPushButton("remove barset") + self.remove_barset_button.clicked.connect(self.remove_barset) + self.button_layout.addWidget(self.remove_barset_button, 3, 0) + + self.align_button = QPushButton("Align (Bottom)") + self.align_button.clicked.connect(self.set_legend_alignment) + self.button_layout.addWidget(self.align_button, 4, 0) + + self.bold_button = QPushButton("Toggle bold") + self.bold_button.clicked.connect(self.toggle_bold) + self.button_layout.addWidget(self.bold_button, 8, 0) + + self.italic_button = QPushButton("Toggle italic") + self.italic_button.clicked.connect(self.toggle_italic) + self.button_layout.addWidget(self.italic_button, 9, 0) + + self.legend_posx.valueChanged.connect(self.update_legend_layout) + self.legend_posy.valueChanged.connect(self.update_legend_layout) + self.legend_width.valueChanged.connect(self.update_legend_layout) + self.legend_height.valueChanged.connect(self.update_legend_layout) + + legend_layout = QFormLayout() + legend_layout.addRow("HPos", self.legend_posx) + legend_layout.addRow("VPos", self.legend_posy) + legend_layout.addRow("Width", self.legend_width) + legend_layout.addRow("Height", self.legend_height) + + self.legend_settings = QGroupBox("Detached legend") + self.legend_settings.setLayout(legend_layout) + self.button_layout.addWidget(self.legend_settings) + self.legend_settings.setVisible(False) + + # Create chart view with the chart + self.chart_view = QChartView(self.chart, self) + + # Create spinbox to modify font size + self.font_size.setValue(self.chart.legend().font().pointSizeF()) + self.font_size.valueChanged.connect(self.font_size_changed) + + self.font_layout.addRow("Legend font size", self.font_size) + + # Create layout for grid and detached legend + self.main_layout.addLayout(self.button_layout, 0, 0) + self.main_layout.addLayout(self.font_layout, 1, 0) + self.main_layout.addWidget(self.chart_view, 0, 1, 3, 1) + self.setLayout(self.main_layout) + + self.create_series() + + def create_series(self): + self.add_barset() + self.add_barset() + self.add_barset() + self.add_barset() + + self.chart.addSeries(self.series) + self.chart.setTitle("Legend detach example") + self.chart.createDefaultAxes() + + self.chart.legend().setVisible(True) + self.chart.legend().setAlignment(Qt.AlignBottom) + + self.chart_view.setRenderHint(QPainter.Antialiasing) + + def show_legend_spinbox(self): + self.legend_settings.setVisible(True) + chart_viewrect = self.chart_view.rect() + + self.legend_posx.setMinimum(0) + self.legend_posx.setMaximum(chart_viewrect.width()) + self.legend_posx.setValue(150) + + self.legend_posy.setMinimum(0) + self.legend_posy.setMaximum(chart_viewrect.height()) + self.legend_posy.setValue(150) + + self.legend_width.setMinimum(0) + self.legend_width.setMaximum(chart_viewrect.width()) + self.legend_width.setValue(150) + + self.legend_height.setMinimum(0) + self.legend_height.setMaximum(chart_viewrect.height()) + self.legend_height.setValue(75) + + def hideLegendSpinbox(self): + self.legend_settings.setVisible(False) + + def toggle_attached(self): + legend = self.chart.legend() + if legend.isAttachedToChart(): + legend.detachFromChart() + legend.setBackgroundVisible(True) + legend.setBrush(QBrush(QColor(128, 128, 128, 128))) + legend.setPen(QPen(QColor(192, 192, 192, 192))) + + self.show_legend_spinbox() + self.update_legend_layout() + else: + legend.attachToChart() + legend.setBackgroundVisible(False) + self.hideLegendSpinbox() + self.update() + + def add_barset(self): + series_count = self.series.count() + bar_set = QBarSet(f"set {series_count}") + delta = series_count * 0.1 + bar_set.append([1 + delta, 2 + delta, 3 + delta, 4 + delta]) + self.series.append(bar_set) + + def remove_barset(self): + sets = self.series.barSets() + len_sets = len(sets) + if len_sets > 0: + self.series.remove(sets[len_sets - 1]) + + def set_legend_alignment(self): + button = self.sender() + legend = self.chart.legend() + alignment = legend.alignment() + + if alignment == Qt.AlignTop: + legend.setAlignment(Qt.AlignLeft) + if button: + button.setText("Align (Left)") + elif alignment == Qt.AlignLeft: + legend.setAlignment(Qt.AlignBottom) + if button: + button.setText("Align (Bottom)") + elif alignment == Qt.AlignBottom: + legend.setAlignment(Qt.AlignRight) + if button: + button.setText("Align (Right)") + else: + if button: + button.setText("Align (Top)") + legend.setAlignment(Qt.AlignTop) + + def toggle_bold(self): + legend = self.chart.legend() + font = legend.font() + font.setBold(not font.bold()) + legend.setFont(font) + + def toggle_italic(self): + legend = self.chart.legend() + font = legend.font() + font.setItalic(not font.italic()) + legend.setFont(font) + + def font_size_changed(self): + legend = self.chart.legend() + font = legend.font() + font_size = self.font_size.value() + if font_size < 1: + font_size = 1 + font.setPointSizeF(font_size) + legend.setFont(font) + + def update_legend_layout(self): + legend = self.chart.legend() + + rect = QRectF(self.legend_posx.value(), + self.legend_posy.value(), + self.legend_width.value(), + self.legend_height.value()) + legend.setGeometry(rect) + + legend.update() + +if __name__ == "__main__": + app = QApplication(sys.argv) + w = MainWidget() + available_geometry = w.screen().availableGeometry() + size = available_geometry.height() * 0.75 + w.setFixedSize(size, size) + w.show() + sys.exit(app.exec_()) diff --git a/examples/charts/legend/legend.pyproject b/examples/charts/legend/legend.pyproject new file mode 100644 index 000000000..f130dcf01 --- /dev/null +++ b/examples/charts/legend/legend.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["legend.py"] +} diff --git a/examples/charts/lineandbar.py b/examples/charts/lineandbar.py index e06298e63..871e06853 100644 --- a/examples/charts/lineandbar.py +++ b/examples/charts/lineandbar.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2018 The Qt Company Ltd. diff --git a/examples/charts/lineandbar/lineandbar.py b/examples/charts/lineandbar/lineandbar.py new file mode 100644 index 000000000..219da17b5 --- /dev/null +++ b/examples/charts/lineandbar/lineandbar.py @@ -0,0 +1,117 @@ + +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 line/bar example from Qt v5.x""" + +import sys +from PySide6.QtCore import QPoint, Qt +from PySide6.QtGui import QPainter +from PySide6.QtWidgets import QMainWindow, QApplication +from PySide6.QtCharts import (QBarCategoryAxis, QBarSeries, QBarSet, QChart, + QChartView, QLineSeries, QValueAxis) + + +class TestChart(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + + self.set0 = QBarSet("Jane") + self.set1 = QBarSet("John") + self.set2 = QBarSet("Axel") + self.set3 = QBarSet("Mary") + self.set4 = QBarSet("Sam") + + self.set0.append([1, 2, 3, 4, 5, 6]) + self.set1.append([5, 0, 0, 4, 0, 7]) + self.set2.append([3, 5, 8, 13, 8, 5]) + self.set3.append([5, 6, 7, 3, 4, 5]) + self.set4.append([9, 7, 5, 3, 1, 2]) + + self.barSeries = QBarSeries() + self.barSeries.append(self.set0) + self.barSeries.append(self.set1) + self.barSeries.append(self.set2) + self.barSeries.append(self.set3) + self.barSeries.append(self.set4) + + self.lineSeries = QLineSeries() + self.lineSeries.setName("trend") + self.lineSeries.append(QPoint(0, 4)) + self.lineSeries.append(QPoint(1, 15)) + self.lineSeries.append(QPoint(2, 20)) + self.lineSeries.append(QPoint(3, 4)) + self.lineSeries.append(QPoint(4, 12)) + self.lineSeries.append(QPoint(5, 17)) + + self.chart = QChart() + self.chart.addSeries(self.barSeries) + self.chart.addSeries(self.lineSeries) + self.chart.setTitle("Line and barchart example") + + self.categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] + self.axisX = QBarCategoryAxis() + self.axisX.append(self.categories) + self.chart.setAxisX(self.axisX, self.lineSeries) + self.chart.setAxisX(self.axisX, self.barSeries) + self.axisX.setRange("Jan", "Jun") + + self.axisY = QValueAxis() + self.chart.setAxisY(self.axisY, self.lineSeries) + self.chart.setAxisY(self.axisY, self.barSeries) + self.axisY.setRange(0, 20) + + self.chart.legend().setVisible(True) + self.chart.legend().setAlignment(Qt.AlignBottom) + + self.chartView = QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(440, 300) + + sys.exit(app.exec_()) diff --git a/examples/charts/lineandbar/lineandbar.pyproject b/examples/charts/lineandbar/lineandbar.pyproject new file mode 100644 index 000000000..8d9010cf7 --- /dev/null +++ b/examples/charts/lineandbar/lineandbar.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["lineandbar.py"] +} diff --git a/examples/charts/linechart/linechart.py b/examples/charts/linechart/linechart.py new file mode 100644 index 000000000..84cd0c8b3 --- /dev/null +++ b/examples/charts/linechart/linechart.py @@ -0,0 +1,84 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 linechart example from Qt v5.x""" + +import sys +from PySide6.QtCore import QPointF +from PySide6.QtGui import QPainter +from PySide6.QtWidgets import QMainWindow, QApplication +from PySide6.QtCharts import QChart, QChartView, QLineSeries + + +class TestChart(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + + self.series = QLineSeries() + self.series.append(0, 6) + self.series.append(2, 4) + self.series.append(3, 8) + self.series.append(7, 4) + self.series.append(10, 5) + self.series.append(QPointF(11, 1)) + self.series.append(QPointF(13, 3)) + self.series.append(QPointF(17, 6)) + self.series.append(QPointF(18, 3)) + self.series.append(QPointF(20, 2)) + + self.chart = QChart() + self.chart.legend().hide() + self.chart.addSeries(self.series) + self.chart.createDefaultAxes() + self.chart.setTitle("Simple line chart example") + + self.chartView = QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(440, 300) + sys.exit(app.exec_()) diff --git a/examples/charts/linechart/linechart.pyproject b/examples/charts/linechart/linechart.pyproject new file mode 100644 index 000000000..a0b84c285 --- /dev/null +++ b/examples/charts/linechart/linechart.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["linechart.py"] +} diff --git a/examples/charts/logvalueaxis/logvalueaxis.py b/examples/charts/logvalueaxis/logvalueaxis.py new file mode 100644 index 000000000..c5e90c584 --- /dev/null +++ b/examples/charts/logvalueaxis/logvalueaxis.py @@ -0,0 +1,95 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Logarithmic Axis Example from Qt v5.x""" + + + +import sys +from PySide6.QtCore import Qt, QPointF +from PySide6.QtGui import QPainter +from PySide6.QtWidgets import QMainWindow, QApplication +from PySide6.QtCharts import (QChart, QChartView, QLineSeries, QLogValueAxis, + QValueAxis) + + +class TestChart(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + + self.series = QLineSeries() + self.series.append([ + QPointF(1.0, 1.0), QPointF(2.0, 73.0), QPointF(3.0, 268.0), + QPointF(4.0, 17.0), QPointF(5.0, 4325.0), QPointF(6.0, 723.0)]) + + self.chart = QChart() + self.chart.addSeries(self.series) + self.chart.legend().hide() + self.chart.setTitle("Logarithmic axis example") + + self.axisX = QValueAxis() + self.axisX.setTitleText("Data point") + self.axisX.setLabelFormat("%i") + self.axisX.setTickCount(self.series.count()) + self.chart.addAxis(self.axisX, Qt.AlignBottom) + self.series.attachAxis(self.axisX) + + self.axisY = QLogValueAxis() + self.axisY.setTitleText("Values") + self.axisY.setLabelFormat("%g") + self.axisY.setBase(8.0) + self.axisY.setMinorTickCount(-1) + self.chart.addAxis(self.axisY, Qt.AlignLeft) + self.series.attachAxis(self.axisY) + + self.chartView = QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(800, 600) + + sys.exit(app.exec_()) diff --git a/examples/charts/logvalueaxis/logvalueaxis.pyproject b/examples/charts/logvalueaxis/logvalueaxis.pyproject new file mode 100644 index 000000000..b6b3a8e74 --- /dev/null +++ b/examples/charts/logvalueaxis/logvalueaxis.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["logvalueaxis.py"] +} diff --git a/examples/charts/memoryusage.py b/examples/charts/memoryusage.py index 9d7a99311..1266f3566 100644 --- a/examples/charts/memoryusage.py +++ b/examples/charts/memoryusage.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2017 The Qt Company Ltd. diff --git a/examples/charts/memoryusage/memoryusage.py b/examples/charts/memoryusage/memoryusage.py new file mode 100644 index 000000000..a6c536de5 --- /dev/null +++ b/examples/charts/memoryusage/memoryusage.py @@ -0,0 +1,126 @@ + +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Charts example: Simple memory usage viewer""" + +import os +import sys +from PySide6.QtCore import QProcess +from PySide6.QtWidgets import QApplication, QMainWindow +from PySide6.QtCharts import QChart, QChartView, QPieSeries + + +def runProcess(command, arguments): + process = QProcess() + process.start(command, arguments) + process.waitForFinished() + std_output = process.readAllStandardOutput().data().decode('utf-8') + return std_output.split('\n') + +def getMemoryUsage(): + result = [] + if sys.platform == 'win32': + # Windows: Obtain memory usage in KB from 'tasklist' + for line in runProcess('tasklist', [])[3:]: + if len(line) >= 74: + command = line[0:23].strip() + if command.endswith('.exe'): + command = command[0:len(command) - 4] + memoryUsage = float(line[64:74].strip().replace(',', '').replace('.', '')) + legend = '' + if memoryUsage > 10240: + legend = '{} {}M'.format(command, round(memoryUsage / 1024)) + else: + legend = '{} {}K'.format(command, round(memoryUsage)) + result.append([legend, memoryUsage]) + else: + # Unix: Obtain memory usage percentage from 'ps' + psOptions = ['-e', 'v'] + memoryColumn = 8 + commandColumn = 9 + if sys.platform == 'darwin': + psOptions = ['-e', '-v'] + memoryColumn = 11 + commandColumn = 12 + for line in runProcess('ps', psOptions): + tokens = line.split(None) + if len(tokens) > commandColumn and "PID" not in tokens: # Percentage and command + command = tokens[commandColumn] + if not command.startswith('['): + command = os.path.basename(command) + memoryUsage = round(float(tokens[memoryColumn].replace(',', '.'))) + legend = '{} {}%'.format(command, memoryUsage) + result.append([legend, memoryUsage]) + + result.sort(key = lambda x: x[1], reverse=True) + return result + +class MainWindow(QMainWindow): + + def __init__(self): + super(MainWindow, self).__init__() + + self.setWindowTitle('Memory Usage') + + memoryUsage = getMemoryUsage() + if len(memoryUsage) > 5: + memoryUsage = memoryUsage[0:4] + + self.series = QPieSeries() + for item in memoryUsage: + self.series.append(item[0], item[1]) + + slice = self.series.slices()[0] + slice.setExploded() + slice.setLabelVisible() + self.chart = QChart() + self.chart.addSeries(self.series) + self.chartView = QChartView(self.chart) + self.setCentralWidget(self.chartView) + +if __name__ == '__main__': + app = QApplication(sys.argv) + mainWin = MainWindow() + availableGeometry = mainWin.screen().availableGeometry() + size = availableGeometry.height() * 3 / 4 + mainWin.resize(size, size) + mainWin.show() + sys.exit(app.exec_()) diff --git a/examples/charts/memoryusage/memoryusage.pyproject b/examples/charts/memoryusage/memoryusage.pyproject new file mode 100644 index 000000000..4a3c69ef6 --- /dev/null +++ b/examples/charts/memoryusage/memoryusage.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["memoryusage.py"] +} diff --git a/examples/charts/modeldata.py b/examples/charts/modeldata.py index 739b73d63..2ee4ee1a0 100644 --- a/examples/charts/modeldata.py +++ b/examples/charts/modeldata.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2018 The Qt Company Ltd. diff --git a/examples/charts/modeldata/modeldata.py b/examples/charts/modeldata/modeldata.py new file mode 100644 index 000000000..1d10190f4 --- /dev/null +++ b/examples/charts/modeldata/modeldata.py @@ -0,0 +1,183 @@ + +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Model Data example from Qt v5.x""" + +import sys +from random import randrange + +from PySide6.QtCore import QAbstractTableModel, QModelIndex, QRect, Qt +from PySide6.QtGui import QColor, QPainter +from PySide6.QtWidgets import (QApplication, QGridLayout, QHeaderView, + QTableView, QWidget) +from PySide6.QtCharts import QChart, QChartView, QLineSeries, QVXYModelMapper + + +class CustomTableModel(QAbstractTableModel): + def __init__(self): + QAbstractTableModel.__init__(self) + self.input_data = [] + self.mapping = {} + self.column_count = 4 + self.row_count = 15 + + for i in range(self.row_count): + data_vec = [0]*self.column_count + for k in range(len(data_vec)): + if k % 2 == 0: + data_vec[k] = i * 50 + randrange(30) + else: + data_vec[k] = randrange(100) + self.input_data.append(data_vec) + + def rowCount(self, parent=QModelIndex()): + return len(self.input_data) + + def columnCount(self, parent=QModelIndex()): + return self.column_count + + def headerData(self, section, orientation, role): + if role != Qt.DisplayRole: + return None + + if orientation == Qt.Horizontal: + if section % 2 == 0: + return "x" + else: + return "y" + else: + return "{}".format(section + 1) + + def data(self, index, role=Qt.DisplayRole): + if role == Qt.DisplayRole: + return self.input_data[index.row()][index.column()] + elif role == Qt.EditRole: + return self.input_data[index.row()][index.column()] + elif role == Qt.BackgroundRole: + for color, rect in self.mapping.items(): + if rect.contains(index.column(), index.row()): + return QColor(color) + # cell not mapped return white color + return QColor(Qt.white) + return None + + def setData(self, index, value, role=Qt.EditRole): + if index.isValid() and role == Qt.EditRole: + self.input_data[index.row()][index.column()] = float(value) + self.dataChanged.emit(index, index) + return True + return False + + def flags(self, index): + return Qt.ItemIsEnabled | Qt.ItemIsEditable | Qt.ItemIsSelectable + + def add_mapping(self, color, area): + self.mapping[color] = area + + def clear_mapping(self): + self.mapping = {} + + + +class TableWidget(QWidget): + def __init__(self): + QWidget.__init__(self) + + self.model = CustomTableModel() + + self.table_view = QTableView() + self.table_view.setModel(self.model) + self.table_view.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) + self.table_view.verticalHeader().setSectionResizeMode(QHeaderView.Stretch) + + self.chart = QChart() + self.chart.setAnimationOptions(QChart.AllAnimations) + + self.series = QLineSeries() + self.series.setName("Line 1") + self.mapper = QVXYModelMapper(self) + self.mapper.setXColumn(0) + self.mapper.setYColumn(1) + self.mapper.setSeries(self.series) + self.mapper.setModel(self.model) + self.chart.addSeries(self.series) + + # for storing color hex from the series + seriesColorHex = "#000000" + + # get the color of the series and use it for showing the mapped area + seriesColorHex = "{}".format(self.series.pen().color().name()) + self.model.add_mapping(seriesColorHex, QRect(0, 0, 2, self.model.rowCount())) + + # series 2 + self.series = QLineSeries() + self.series.setName("Line 2") + + self.mapper = QVXYModelMapper(self) + self.mapper.setXColumn(2) + self.mapper.setYColumn(3) + self.mapper.setSeries(self.series) + self.mapper.setModel(self.model) + self.chart.addSeries(self.series) + + # get the color of the series and use it for showing the mapped area + seriesColorHex = "{}".format(self.series.pen().color().name()) + self.model.add_mapping(seriesColorHex, QRect(2, 0, 2, self.model.rowCount())) + + self.chart.createDefaultAxes() + self.chart_view = QChartView(self.chart) + self.chart_view.setRenderHint(QPainter.Antialiasing) + self.chart_view.setMinimumSize(640, 480) + + # create main layout + self.main_layout = QGridLayout() + self.main_layout.addWidget(self.table_view, 1, 0) + self.main_layout.addWidget(self.chart_view, 1, 1) + self.main_layout.setColumnStretch(1, 1) + self.main_layout.setColumnStretch(0, 0) + self.setLayout(self.main_layout) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + w = TableWidget() + w.show() + sys.exit(app.exec_()) diff --git a/examples/charts/modeldata/modeldata.pyproject b/examples/charts/modeldata/modeldata.pyproject new file mode 100644 index 000000000..e10d49eb2 --- /dev/null +++ b/examples/charts/modeldata/modeldata.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["modeldata.py"] +} diff --git a/examples/charts/nesteddonuts.py b/examples/charts/nesteddonuts.py index 09c77d022..9ea11a57f 100644 --- a/examples/charts/nesteddonuts.py +++ b/examples/charts/nesteddonuts.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2018 The Qt Company Ltd. diff --git a/examples/charts/nesteddonuts/nesteddonuts.py b/examples/charts/nesteddonuts/nesteddonuts.py new file mode 100644 index 000000000..9005980a2 --- /dev/null +++ b/examples/charts/nesteddonuts/nesteddonuts.py @@ -0,0 +1,137 @@ + +############################################################################# +## +## Copyright (C) 2018 The Qt Company Ltd. +## Contact: http://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 Nested Donuts example from Qt v5.x""" + +import sys + +from PySide6.QtCore import Qt, QTimer +from PySide6.QtGui import QPainter +from PySide6.QtWidgets import QApplication, QGridLayout, QWidget +from PySide6.QtCharts import QChart, QChartView, QPieSeries, QPieSlice + + +from random import randrange +from functools import partial + +class Widget(QWidget): + def __init__(self): + QWidget.__init__(self) + self.setMinimumSize(800, 600) + self.donuts = [] + self.chart_view = QChartView() + self.chart_view.setRenderHint(QPainter.Antialiasing) + self.chart = self.chart_view.chart() + self.chart.legend().setVisible(False) + self.chart.setTitle("Nested donuts demo") + self.chart.setAnimationOptions(QChart.AllAnimations) + + self.min_size = 0.1 + self.max_size = 0.9 + self.donut_count = 5 + + self.setup_donuts() + + # create main layout + self.main_layout = QGridLayout(self) + self.main_layout.addWidget(self.chart_view, 1, 1) + self.setLayout(self.main_layout) + + self.update_timer = QTimer(self) + self.update_timer.timeout.connect(self.update_rotation) + self.update_timer.start(1250) + + def setup_donuts(self): + for i in range(self.donut_count): + donut = QPieSeries() + slccount = randrange(3, 6) + for j in range(slccount): + value = randrange(100, 200) + + slc = QPieSlice(str(value), value) + slc.setLabelVisible(True) + slc.setLabelColor(Qt.white) + slc.setLabelPosition(QPieSlice.LabelInsideTangential) + + # Connection using an extra parameter for the slot + slc.hovered[bool].connect(partial(self.explode_slice, slc=slc)) + + donut.append(slc) + size = (self.max_size - self.min_size)/self.donut_count + donut.setHoleSize(self.min_size + i * size) + donut.setPieSize(self.min_size + (i + 1) * size) + + self.donuts.append(donut) + self.chart_view.chart().addSeries(donut) + + + + def update_rotation(self): + for donut in self.donuts: + phase_shift = randrange(-50, 100) + donut.setPieStartAngle(donut.pieStartAngle() + phase_shift) + donut.setPieEndAngle(donut.pieEndAngle() + phase_shift) + + def explode_slice(self, exploded, slc): + if exploded: + self.update_timer.stop() + slice_startangle = slc.startAngle() + slice_endangle = slc.startAngle() + slc.angleSpan() + + donut = slc.series() + idx = self.donuts.index(donut) + for i in range(idx + 1, len(self.donuts)): + self.donuts[i].setPieStartAngle(slice_endangle) + self.donuts[i].setPieEndAngle(360 + slice_startangle) + else: + for donut in self.donuts: + donut.setPieStartAngle(0) + donut.setPieEndAngle(360) + + self.update_timer.start() + + slc.setExploded(exploded) + +if __name__ == "__main__": + app = QApplication(sys.argv) + w = Widget() + w.show() + sys.exit(app.exec_()) diff --git a/examples/charts/nesteddonuts/nesteddonuts.pyproject b/examples/charts/nesteddonuts/nesteddonuts.pyproject new file mode 100644 index 000000000..69653ae73 --- /dev/null +++ b/examples/charts/nesteddonuts/nesteddonuts.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["nesteddonuts.py"] +} diff --git a/examples/charts/percentbarchart.py b/examples/charts/percentbarchart.py index a70cae7cf..ffc5742da 100644 --- a/examples/charts/percentbarchart.py +++ b/examples/charts/percentbarchart.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2018 The Qt Company Ltd. diff --git a/examples/charts/percentbarchart/percentbarchart.py b/examples/charts/percentbarchart/percentbarchart.py new file mode 100644 index 000000000..b9301f36e --- /dev/null +++ b/examples/charts/percentbarchart/percentbarchart.py @@ -0,0 +1,99 @@ + +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Percent Bar Chart example from Qt v5.x""" + +import sys +from PySide6.QtCore import Qt +from PySide6.QtGui import QPainter +from PySide6.QtWidgets import (QMainWindow, QApplication) +from PySide6.QtCharts import (QBarCategoryAxis, QBarSet, QChart, QChartView, + QPercentBarSeries) + +class MainWindow(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + + set0 = QBarSet("Jane") + set1 = QBarSet("John") + set2 = QBarSet("Axel") + set3 = QBarSet("Mary") + set4 = QBarSet("Samantha") + + set0.append([1, 2, 3, 4, 5, 6]) + set1.append([5, 0, 0, 4, 0, 7]) + set2.append([3, 5, 8, 13, 8, 5]) + set3.append([5, 6, 7, 3, 4, 5]) + set4.append([9, 7, 5, 3, 1, 2]) + + series = QPercentBarSeries() + series.append(set0) + series.append(set1) + series.append(set2) + series.append(set3) + series.append(set4) + + chart = QChart() + chart.addSeries(series) + chart.setTitle("Simple percentbarchart example") + chart.setAnimationOptions(QChart.SeriesAnimations) + + categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun"] + axis = QBarCategoryAxis() + axis.append(categories) + chart.createDefaultAxes() + chart.setAxisX(axis, series) + + chart.legend().setVisible(True) + chart.legend().setAlignment(Qt.AlignBottom) + + chart_view = QChartView(chart) + chart_view.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(chart_view) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + w = MainWindow() + w.resize(420, 300) + w.show() + sys.exit(app.exec_()) diff --git a/examples/charts/percentbarchart/percentbarchart.pyproject b/examples/charts/percentbarchart/percentbarchart.pyproject new file mode 100644 index 000000000..0cf3778af --- /dev/null +++ b/examples/charts/percentbarchart/percentbarchart.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["percentbarchart.py"] +} diff --git a/examples/charts/piechart/piechart.py b/examples/charts/piechart/piechart.py new file mode 100644 index 000000000..29947263d --- /dev/null +++ b/examples/charts/piechart/piechart.py @@ -0,0 +1,87 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Pie Chart Example from Qt v5.x""" + +import sys +from PySide6.QtCore import Qt +from PySide6.QtGui import QPainter, QPen +from PySide6.QtWidgets import QMainWindow, QApplication +from PySide6.QtCharts import QChart, QChartView, QPieSeries + + +class TestChart(QMainWindow): + + def __init__(self): + QMainWindow.__init__(self) + + self.series = QPieSeries() + + self.series.append('Jane', 1) + self.series.append('Joe', 2) + self.series.append('Andy', 3) + self.series.append('Barbara', 4) + self.series.append('Axel', 5) + + self.slice = self.series.slices()[1] + self.slice.setExploded() + self.slice.setLabelVisible() + self.slice.setPen(QPen(Qt.darkGreen, 2)) + self.slice.setBrush(Qt.green) + + self.chart = QChart() + self.chart.addSeries(self.series) + self.chart.setTitle('Simple piechart example') + self.chart.legend().hide() + + self.chartView = QChartView(self.chart) + self.chartView.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(self.chartView) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + + window = TestChart() + window.show() + window.resize(440, 300) + + sys.exit(app.exec_()) diff --git a/examples/charts/piechart/piechart.pyproject b/examples/charts/piechart/piechart.pyproject new file mode 100644 index 000000000..2578b435e --- /dev/null +++ b/examples/charts/piechart/piechart.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["piechart.py"] +} diff --git a/examples/charts/temperaturerecords/temperaturerecords.py b/examples/charts/temperaturerecords/temperaturerecords.py new file mode 100644 index 000000000..3a8a86f42 --- /dev/null +++ b/examples/charts/temperaturerecords/temperaturerecords.py @@ -0,0 +1,96 @@ +############################################################################# +## +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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 Temperature Records example from Qt v5.x""" + +import sys +from PySide6.QtCore import Qt +from PySide6.QtGui import QPainter +from PySide6.QtWidgets import QMainWindow, QApplication +from PySide6.QtCharts import (QBarCategoryAxis, QBarSet, QChart, QChartView, + QStackedBarSeries, QValueAxis) + + +class MainWindow(QMainWindow): + def __init__(self): + QMainWindow.__init__(self) + low = QBarSet("Min") + high = QBarSet("Max") + low.append([-52, -50, -45.3, -37.0, -25.6, -8.0, + -6.0, -11.8, -19.7, -32.8, -43.0, -48.0]) + high.append([11.9, 12.8, 18.5, 26.5, 32.0, 34.8, + 38.2, 34.8, 29.8, 20.4, 15.1, 11.8]) + + series = QStackedBarSeries() + series.append(low) + series.append(high) + + chart = QChart() + chart.addSeries(series) + chart.setTitle("Temperature records in celcius") + chart.setAnimationOptions(QChart.SeriesAnimations) + + categories = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", + "Aug", "Sep", "Oct", "Nov", "Dec"] + axisX = QBarCategoryAxis() + axisX.append(categories) + axisX.setTitleText("Month") + chart.addAxis(axisX, Qt.AlignBottom) + axisY = QValueAxis() + axisY.setRange(-52, 52) + axisY.setTitleText("Temperature [°C]") + chart.addAxis(axisY, Qt.AlignLeft) + series.attachAxis(axisX) + series.attachAxis(axisY) + + chart.legend().setVisible(True) + chart.legend().setAlignment(Qt.AlignBottom) + + chart_view = QChartView(chart) + chart_view.setRenderHint(QPainter.Antialiasing) + + self.setCentralWidget(chart_view) + +if __name__ == "__main__": + app = QApplication(sys.argv) + w = MainWindow() + w.resize(600, 300) + w.show() + sys.exit(app.exec_()) diff --git a/examples/charts/temperaturerecords/temperaturerecords.pyproject b/examples/charts/temperaturerecords/temperaturerecords.pyproject new file mode 100644 index 000000000..8db39e340 --- /dev/null +++ b/examples/charts/temperaturerecords/temperaturerecords.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["temperaturerecords.py"] +} diff --git a/examples/corelib/tools/regexp.py b/examples/corelib/regexp/regexp.py index 48c03309e..48c03309e 100644 --- a/examples/corelib/tools/regexp.py +++ b/examples/corelib/regexp/regexp.py diff --git a/examples/corelib/tools/tools.pyproject b/examples/corelib/regexp/regexp.pyproject index 63f9c6198..63f9c6198 100644 --- a/examples/corelib/tools/tools.pyproject +++ b/examples/corelib/regexp/regexp.pyproject diff --git a/examples/corelib/tools/settingseditor/settingseditor.py b/examples/corelib/settingseditor/settingseditor.py index 9e2a2a2d8..9e2a2a2d8 100644 --- a/examples/corelib/tools/settingseditor/settingseditor.py +++ b/examples/corelib/settingseditor/settingseditor.py diff --git a/examples/corelib/tools/settingseditor/settingseditor.pyproject b/examples/corelib/settingseditor/settingseditor.pyproject index 9eb637af2..9eb637af2 100644 --- a/examples/corelib/tools/settingseditor/settingseditor.pyproject +++ b/examples/corelib/settingseditor/settingseditor.pyproject diff --git a/examples/corelib/tools/codecs/codecs.pyproject b/examples/corelib/tools/codecs/codecs.pyproject deleted file mode 100644 index 72237d60b..000000000 --- a/examples/corelib/tools/codecs/codecs.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["codecs.py"] -} diff --git a/examples/datavisualization/bars3d.py b/examples/datavisualization/bars3d.py index 759983341..5004fc7fc 100644 --- a/examples/datavisualization/bars3d.py +++ b/examples/datavisualization/bars3d.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2017 The Qt Company Ltd. diff --git a/examples/datavisualization/bars3d/bars3d.py b/examples/datavisualization/bars3d/bars3d.py new file mode 100644 index 000000000..e025fcd20 --- /dev/null +++ b/examples/datavisualization/bars3d/bars3d.py @@ -0,0 +1,115 @@ + +############################################################################# +## +## Copyright (C) 2017 The Qt Company Ltd. +## Contact: http://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 QtDataVisualization example""" + +import sys +from PySide6.QtCore import Qt +from PySide6.QtGui import QGuiApplication +from PySide6.QtWidgets import QApplication, QSizePolicy, QMainWindow, QWidget +from PySide6.QtDataVisualization import (Q3DBars, QBar3DSeries, QBarDataItem, + QCategory3DAxis, QValue3DAxis) + + +def dataToBarDataRow(data): + return list(QBarDataItem(d) for d in data) + +def dataToBarDataArray(data): + return list(dataToBarDataRow(row) for row in data) + +class MainWindow(QMainWindow): + + def __init__(self): + super(MainWindow, self).__init__() + + self.setWindowTitle('Qt DataVisualization 3D Bars') + + self.bars = Q3DBars() + + self.columnAxis = QCategory3DAxis() + self.columnAxis.setTitle('Columns') + self.columnAxis.setTitleVisible(True) + self.columnAxis.setLabels(['Column1', 'Column2']) + self.columnAxis.setLabelAutoRotation(30) + + self.rowAxis = QCategory3DAxis() + self.rowAxis.setTitle('Rows') + self.rowAxis.setTitleVisible(True) + self.rowAxis.setLabels(['Row1', 'Row2']) + self.rowAxis.setLabelAutoRotation(30) + + self.valueAxis = QValue3DAxis() + self.valueAxis.setTitle('Values') + self.valueAxis.setTitleVisible(True) + self.valueAxis.setRange(0, 5) + + self.bars.setRowAxis(self.rowAxis) + self.bars.setColumnAxis(self.columnAxis) + self.bars.setValueAxis(self.valueAxis) + + self.series = QBar3DSeries() + self.arrayData = [[1, 2], [3, 4]] + self.series.dataProxy().addRows(dataToBarDataArray(self.arrayData)) + + self.bars.setPrimarySeries(self.series) + + self.container = QWidget.createWindowContainer(self.bars) + + if not self.bars.hasContext(): + print("Couldn't initialize the OpenGL context.") + sys.exit(-1) + + camera = self.bars.scene().activeCamera() + camera.setYRotation(22.5) + + geometry = QGuiApplication.primaryScreen().geometry() + size = geometry.height() * 3 / 4 + self.container.setMinimumSize(size, size) + + self.container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.container.setFocusPolicy(Qt.StrongFocus) + self.setCentralWidget(self.container) + +if __name__ == '__main__': + app = QApplication(sys.argv) + mainWin = MainWindow() + mainWin.show() + sys.exit(app.exec_()) diff --git a/examples/datavisualization/datavisualization.pyproject b/examples/datavisualization/bars3d/bars3d.pyproject index 415133f09..415133f09 100644 --- a/examples/datavisualization/datavisualization.pyproject +++ b/examples/datavisualization/bars3d/bars3d.pyproject diff --git a/examples/declarative/declarative.pyproject b/examples/declarative/declarative.pyproject deleted file mode 100644 index e64c1d934..000000000 --- a/examples/declarative/declarative.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["view.qml", "scrolling.py", "usingmodel.py"] -} diff --git a/examples/declarative/scrolling.py b/examples/declarative/scrolling/scrolling.py index 63f79a45b..63f79a45b 100644 --- a/examples/declarative/scrolling.py +++ b/examples/declarative/scrolling/scrolling.py diff --git a/examples/declarative/scrolling/scrolling.pyproject b/examples/declarative/scrolling/scrolling.pyproject new file mode 100644 index 000000000..105c321ca --- /dev/null +++ b/examples/declarative/scrolling/scrolling.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["scrolling.py"] +} diff --git a/examples/declarative/usingmodel.py b/examples/declarative/usingmodel/usingmodel.py index a32945a25..a32945a25 100644 --- a/examples/declarative/usingmodel.py +++ b/examples/declarative/usingmodel/usingmodel.py diff --git a/examples/declarative/usingmodel/usingmodel.pyproject b/examples/declarative/usingmodel/usingmodel.pyproject new file mode 100644 index 000000000..600cdb409 --- /dev/null +++ b/examples/declarative/usingmodel/usingmodel.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["view.qml", "usingmodel.py"] +} diff --git a/examples/declarative/view.qml b/examples/declarative/usingmodel/view.qml index 8eb4f7f97..8eb4f7f97 100644 --- a/examples/declarative/view.qml +++ b/examples/declarative/usingmodel/view.qml diff --git a/examples/macextras/macpasteboardmime.py b/examples/macextras/macpasteboardmime/macpasteboardmime.py index 3da05a313..3da05a313 100644 --- a/examples/macextras/macpasteboardmime.py +++ b/examples/macextras/macpasteboardmime/macpasteboardmime.py diff --git a/examples/macextras/macextras.pyproject b/examples/macextras/macpasteboardmime/macpasteboardmime.pyproject index d559b7ca4..d559b7ca4 100644 --- a/examples/macextras/macextras.pyproject +++ b/examples/macextras/macpasteboardmime/macpasteboardmime.pyproject diff --git a/examples/multimedia/audiooutput.py b/examples/multimedia/audiooutput/audiooutput.py index 44c0f6910..44c0f6910 100644 --- a/examples/multimedia/audiooutput.py +++ b/examples/multimedia/audiooutput/audiooutput.py diff --git a/examples/multimedia/audiooutput/audiooutput.pyproject b/examples/multimedia/audiooutput/audiooutput.pyproject new file mode 100644 index 000000000..399a7c648 --- /dev/null +++ b/examples/multimedia/audiooutput/audiooutput.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["audiooutput.py"] +} diff --git a/examples/multimedia/camera.py b/examples/multimedia/camera/camera.py index e8e95b7ee..e8e95b7ee 100644 --- a/examples/multimedia/camera.py +++ b/examples/multimedia/camera/camera.py diff --git a/examples/multimedia/camera/camera.pyproject b/examples/multimedia/camera/camera.pyproject new file mode 100644 index 000000000..ffc6a11ed --- /dev/null +++ b/examples/multimedia/camera/camera.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["camera.py"] +} diff --git a/examples/multimedia/shutter.svg b/examples/multimedia/camera/shutter.svg index 18493361d..18493361d 100644 --- a/examples/multimedia/shutter.svg +++ b/examples/multimedia/camera/shutter.svg diff --git a/examples/multimedia/multimedia.pyproject b/examples/multimedia/multimedia.pyproject deleted file mode 100644 index a0b8b441c..000000000 --- a/examples/multimedia/multimedia.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["player.py", "audiooutput.py", "camera.py"] -} diff --git a/examples/multimedia/player.py b/examples/multimedia/player/player.py index bffcb3906..bffcb3906 100644 --- a/examples/multimedia/player.py +++ b/examples/multimedia/player/player.py diff --git a/examples/multimedia/player/player.pyproject b/examples/multimedia/player/player.pyproject new file mode 100644 index 000000000..2e16f4505 --- /dev/null +++ b/examples/multimedia/player/player.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["player.py"] +} diff --git a/examples/network/blockingfortuneclient.py b/examples/network/blockingfortuneclient/blockingfortuneclient.py index 4ee0ce622..4ee0ce622 100644 --- a/examples/network/blockingfortuneclient.py +++ b/examples/network/blockingfortuneclient/blockingfortuneclient.py diff --git a/examples/network/blockingfortuneclient/blockingfortuneclient.pyproject b/examples/network/blockingfortuneclient/blockingfortuneclient.pyproject new file mode 100644 index 000000000..85abd7e70 --- /dev/null +++ b/examples/network/blockingfortuneclient/blockingfortuneclient.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["blockingfortuneclient.py"] +} diff --git a/examples/network/fortuneclient.py b/examples/network/fortuneclient/fortuneclient.py index 99ca41b0e..99ca41b0e 100644 --- a/examples/network/fortuneclient.py +++ b/examples/network/fortuneclient/fortuneclient.py diff --git a/examples/network/fortuneclient/fortuneclient.pyproject b/examples/network/fortuneclient/fortuneclient.pyproject new file mode 100644 index 000000000..fb684690a --- /dev/null +++ b/examples/network/fortuneclient/fortuneclient.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["fortuneclient.py"] +} diff --git a/examples/network/fortuneserver.py b/examples/network/fortuneserver/fortuneserver.py index 7b8f05a32..7b8f05a32 100644 --- a/examples/network/fortuneserver.py +++ b/examples/network/fortuneserver/fortuneserver.py diff --git a/examples/network/fortuneserver/fortuneserver.pyproject b/examples/network/fortuneserver/fortuneserver.pyproject new file mode 100644 index 000000000..b97b4156f --- /dev/null +++ b/examples/network/fortuneserver/fortuneserver.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["fortuneserver.py"] +} diff --git a/examples/network/network.pyproject b/examples/network/network.pyproject deleted file mode 100644 index 44b9ec433..000000000 --- a/examples/network/network.pyproject +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": ["blockingfortuneclient.py", "fortuneserver.py", - "threadedfortuneserver.py", "fortuneclient.py"] -} diff --git a/examples/network/threadedfortuneserver.py b/examples/network/threadedfortuneserver/threadedfortuneserver.py index 839a2a57e..839a2a57e 100644 --- a/examples/network/threadedfortuneserver.py +++ b/examples/network/threadedfortuneserver/threadedfortuneserver.py diff --git a/examples/network/threadedfortuneserver/threadedfortuneserver.pyproject b/examples/network/threadedfortuneserver/threadedfortuneserver.pyproject new file mode 100644 index 000000000..c0d401d48 --- /dev/null +++ b/examples/network/threadedfortuneserver/threadedfortuneserver.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["threadedfortuneserver.py"] +} diff --git a/examples/opengl/contextinfo.py b/examples/opengl/contextinfo/contextinfo.py index 0a686d388..0a686d388 100644 --- a/examples/opengl/contextinfo.py +++ b/examples/opengl/contextinfo/contextinfo.py diff --git a/examples/opengl/contextinfo/contextinfo.pyproject b/examples/opengl/contextinfo/contextinfo.pyproject new file mode 100644 index 000000000..0758180ae --- /dev/null +++ b/examples/opengl/contextinfo/contextinfo.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["contextinfo.py"] +} diff --git a/examples/opengl/hellogl2.py b/examples/opengl/hellogl2/hellogl2.py index bcffdf3c9..bcffdf3c9 100644 --- a/examples/opengl/hellogl2.py +++ b/examples/opengl/hellogl2/hellogl2.py diff --git a/examples/opengl/hellogl2/hellogl2.pyproject b/examples/opengl/hellogl2/hellogl2.pyproject new file mode 100644 index 000000000..331d835af --- /dev/null +++ b/examples/opengl/hellogl2/hellogl2.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["hellogl2.py"] +} diff --git a/examples/opengl/opengl.pyproject b/examples/opengl/opengl.pyproject deleted file mode 100644 index 20b289d7b..000000000 --- a/examples/opengl/opengl.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["hellogl2.py", "contextinfo.py"] -} diff --git a/examples/quick/customitems/painteditem/painteditem.pyproject b/examples/quick/customitems/painteditem/painteditem.pyproject deleted file mode 100644 index 0c70ebe59..000000000 --- a/examples/quick/customitems/painteditem/painteditem.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["main.qml", "painteditem.pyproject"] -} diff --git a/examples/quick/customitems/painteditem/main.qml b/examples/quick/painteditem/main.qml index d3404cad6..d3404cad6 100644 --- a/examples/quick/customitems/painteditem/main.qml +++ b/examples/quick/painteditem/main.qml diff --git a/examples/quick/customitems/painteditem/painteditem.py b/examples/quick/painteditem/painteditem.py index 5476bdbaf..5476bdbaf 100644 --- a/examples/quick/customitems/painteditem/painteditem.py +++ b/examples/quick/painteditem/painteditem.py diff --git a/examples/quick/painteditem/painteditem.pyproject b/examples/quick/painteditem/painteditem.pyproject new file mode 100644 index 000000000..0597c2a97 --- /dev/null +++ b/examples/quick/painteditem/painteditem.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["main.qml", "painteditem.py"] +} diff --git a/examples/texttospeech/texttospeech.py b/examples/texttospeech/hello_speak/hello_speak.py index b5f2cc84b..b5f2cc84b 100644 --- a/examples/texttospeech/texttospeech.py +++ b/examples/texttospeech/hello_speak/hello_speak.py diff --git a/examples/texttospeech/hello_speak/hello_speak.pyproject b/examples/texttospeech/hello_speak/hello_speak.pyproject new file mode 100644 index 000000000..15b9b8529 --- /dev/null +++ b/examples/texttospeech/hello_speak/hello_speak.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["hello_speak.py"] +} diff --git a/examples/texttospeech/texttospeech.pyproject b/examples/texttospeech/texttospeech.pyproject deleted file mode 100644 index 69fc13f90..000000000 --- a/examples/texttospeech/texttospeech.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["texttospeech.py"] -} diff --git a/examples/uiloader/uiloader.py b/examples/uitools/uiloader/uiloader.py index 21b126bb2..21b126bb2 100644 --- a/examples/uiloader/uiloader.py +++ b/examples/uitools/uiloader/uiloader.py diff --git a/examples/uitools/uiloader/uiloader.pyproject b/examples/uitools/uiloader/uiloader.pyproject new file mode 100644 index 000000000..3f4ea8c07 --- /dev/null +++ b/examples/uitools/uiloader/uiloader.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["uiloader.py"] +} diff --git a/examples/webenginequick/browser.qml b/examples/webenginequick/nanobrowser/browser.qml index 781453863..781453863 100644 --- a/examples/webenginequick/browser.qml +++ b/examples/webenginequick/nanobrowser/browser.qml diff --git a/examples/webenginequick/webenginequick.pyproject b/examples/webenginequick/nanobrowser/nanobrowser.pyproject index dd9039229..dd9039229 100644 --- a/examples/webenginequick/webenginequick.pyproject +++ b/examples/webenginequick/nanobrowser/nanobrowser.pyproject diff --git a/examples/webenginequick/quicknanobrowser.py b/examples/webenginequick/nanobrowser/quicknanobrowser.py index 1bcb045c1..1bcb045c1 100644 --- a/examples/webenginequick/quicknanobrowser.py +++ b/examples/webenginequick/nanobrowser/quicknanobrowser.py diff --git a/examples/webenginewidgets/simplebrowser.py b/examples/webenginewidgets/simplebrowser/simplebrowser.py index 8c5ec0704..8c5ec0704 100644 --- a/examples/webenginewidgets/simplebrowser.py +++ b/examples/webenginewidgets/simplebrowser/simplebrowser.py diff --git a/examples/webenginewidgets/webenginewidgets.pyproject b/examples/webenginewidgets/simplebrowser/simplebrowser.pyproject index 6bc12af6b..6bc12af6b 100644 --- a/examples/webenginewidgets/webenginewidgets.pyproject +++ b/examples/webenginewidgets/simplebrowser/simplebrowser.pyproject diff --git a/examples/widgets/codeeditor/codeeditor.pyproject b/examples/widgets/codeeditor/codeeditor.pyproject new file mode 100644 index 000000000..f51cfc6d2 --- /dev/null +++ b/examples/widgets/codeeditor/codeeditor.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["codeeditor.py", "main.py"] +} diff --git a/examples/widgets/dialogs/dialogs.pyproject b/examples/widgets/dialogs/dialogs.pyproject deleted file mode 100644 index 001fd141b..000000000 --- a/examples/widgets/dialogs/dialogs.pyproject +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": ["findfiles.py", "standarddialogs.py", "extension.py", - "trivialwizard.py"] -} diff --git a/examples/widgets/dialogs/extension.py b/examples/widgets/dialogs/extension/extension.py index 891e55533..891e55533 100644 --- a/examples/widgets/dialogs/extension.py +++ b/examples/widgets/dialogs/extension/extension.py diff --git a/examples/widgets/dialogs/extension/extension.pyproject b/examples/widgets/dialogs/extension/extension.pyproject new file mode 100644 index 000000000..e0f2ba73b --- /dev/null +++ b/examples/widgets/dialogs/extension/extension.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["extension.py"] +} diff --git a/examples/widgets/dialogs/findfiles.py b/examples/widgets/dialogs/findfiles/findfiles.py index 5e26f73ad..5e26f73ad 100644 --- a/examples/widgets/dialogs/findfiles.py +++ b/examples/widgets/dialogs/findfiles/findfiles.py diff --git a/examples/widgets/dialogs/findfiles/findfiles.pyproject b/examples/widgets/dialogs/findfiles/findfiles.pyproject new file mode 100644 index 000000000..c2fae6dff --- /dev/null +++ b/examples/widgets/dialogs/findfiles/findfiles.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["findfiles.py"] +} diff --git a/examples/widgets/dialogs/standarddialogs.py b/examples/widgets/dialogs/standarddialogs/standarddialogs.py index 5e0f80c4d..5e0f80c4d 100644 --- a/examples/widgets/dialogs/standarddialogs.py +++ b/examples/widgets/dialogs/standarddialogs/standarddialogs.py diff --git a/examples/widgets/dialogs/standarddialogs/standarddialogs.pyproject b/examples/widgets/dialogs/standarddialogs/standarddialogs.pyproject new file mode 100644 index 000000000..766902e3e --- /dev/null +++ b/examples/widgets/dialogs/standarddialogs/standarddialogs.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["standarddialogs.py"] +} diff --git a/examples/widgets/dialogs/trivialwizard.py b/examples/widgets/dialogs/trivialwizard/trivialwizard.py index 88b8e97b8..88b8e97b8 100644 --- a/examples/widgets/dialogs/trivialwizard.py +++ b/examples/widgets/dialogs/trivialwizard/trivialwizard.py diff --git a/examples/widgets/dialogs/trivialwizard/trivialwizard.pyproject b/examples/widgets/dialogs/trivialwizard/trivialwizard.pyproject new file mode 100644 index 000000000..739a43a7a --- /dev/null +++ b/examples/widgets/dialogs/trivialwizard/trivialwizard.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["trivialwizard.py"] +} diff --git a/examples/widgets/graphicsview/anchorlayout.py b/examples/widgets/graphicsview/anchorlayout/anchorlayout.py index 0b1ec0a03..0b1ec0a03 100644 --- a/examples/widgets/graphicsview/anchorlayout.py +++ b/examples/widgets/graphicsview/anchorlayout/anchorlayout.py diff --git a/examples/widgets/graphicsview/anchorlayout/anchorlayout.pyproject b/examples/widgets/graphicsview/anchorlayout/anchorlayout.pyproject new file mode 100644 index 000000000..49ed7b734 --- /dev/null +++ b/examples/widgets/graphicsview/anchorlayout/anchorlayout.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["anchorlayout.py"] +} diff --git a/examples/widgets/graphicsview/elasticnodes.py b/examples/widgets/graphicsview/elasticnodes/elasticnodes.py index 1eefdc0bb..1eefdc0bb 100644 --- a/examples/widgets/graphicsview/elasticnodes.py +++ b/examples/widgets/graphicsview/elasticnodes/elasticnodes.py diff --git a/examples/widgets/graphicsview/elasticnodes/elasticnodes.pyproject b/examples/widgets/graphicsview/elasticnodes/elasticnodes.pyproject new file mode 100644 index 000000000..f6083e795 --- /dev/null +++ b/examples/widgets/graphicsview/elasticnodes/elasticnodes.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["elasticnodes.py"] +} diff --git a/examples/widgets/graphicsview/graphicsview.pyproject b/examples/widgets/graphicsview/graphicsview.pyproject deleted file mode 100644 index 007d36bd2..000000000 --- a/examples/widgets/graphicsview/graphicsview.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["elasticnodes.py", "anchorlayout.py"] -} diff --git a/examples/widgets/itemviews/basicsortfiltermodel.py b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py index 845755cb9..845755cb9 100644 --- a/examples/widgets/itemviews/basicsortfiltermodel.py +++ b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.py diff --git a/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.pyproject b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.pyproject new file mode 100644 index 000000000..3351bba88 --- /dev/null +++ b/examples/widgets/itemviews/basicfiltermodel/basicsortfiltermodel.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["basicsortfiltermodel.py"] +} diff --git a/examples/widgets/itemviews/fetchmore.py b/examples/widgets/itemviews/fetchmore/fetchmore.py index c91874004..c91874004 100644 --- a/examples/widgets/itemviews/fetchmore.py +++ b/examples/widgets/itemviews/fetchmore/fetchmore.py diff --git a/examples/widgets/itemviews/fetchmore/fetchmore.pyproject b/examples/widgets/itemviews/fetchmore/fetchmore.pyproject new file mode 100644 index 000000000..e5c369374 --- /dev/null +++ b/examples/widgets/itemviews/fetchmore/fetchmore.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["fetchmore.py"] +} diff --git a/examples/widgets/itemviews/itemviews.pyproject b/examples/widgets/itemviews/itemviews.pyproject deleted file mode 100644 index a582259cc..000000000 --- a/examples/widgets/itemviews/itemviews.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["basicsortfiltermodel.py", "fetchmore.py"] -} diff --git a/examples/widgets/layouts/basiclayouts.py b/examples/widgets/layouts/basiclayouts/basiclayouts.py index 25a9b7760..25a9b7760 100644 --- a/examples/widgets/layouts/basiclayouts.py +++ b/examples/widgets/layouts/basiclayouts/basiclayouts.py diff --git a/examples/widgets/layouts/basiclayouts/basiclayouts.pyproject b/examples/widgets/layouts/basiclayouts/basiclayouts.pyproject new file mode 100644 index 000000000..c573f5688 --- /dev/null +++ b/examples/widgets/layouts/basiclayouts/basiclayouts.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["basiclayouts.py"] +} diff --git a/examples/widgets/layouts/dynamiclayouts.py b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py index 5d2f2babe..5d2f2babe 100644 --- a/examples/widgets/layouts/dynamiclayouts.py +++ b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.py diff --git a/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pyproject b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pyproject new file mode 100644 index 000000000..c4276741f --- /dev/null +++ b/examples/widgets/layouts/dynamiclayouts/dynamiclayouts.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["dynamiclayouts.py"] +} diff --git a/examples/widgets/layouts/flowlayout.py b/examples/widgets/layouts/flowlayout/flowlayout.py index 8f4d41480..8f4d41480 100644 --- a/examples/widgets/layouts/flowlayout.py +++ b/examples/widgets/layouts/flowlayout/flowlayout.py diff --git a/examples/widgets/layouts/flowlayout/flowlayout.pyproject b/examples/widgets/layouts/flowlayout/flowlayout.pyproject new file mode 100644 index 000000000..fd7f285de --- /dev/null +++ b/examples/widgets/layouts/flowlayout/flowlayout.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["flowlayout.py"] +} diff --git a/examples/widgets/layouts/layouts.pyproject b/examples/widgets/layouts/layouts.pyproject deleted file mode 100644 index 85eb22785..000000000 --- a/examples/widgets/layouts/layouts.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["basiclayouts.py", "dynamiclayouts.py", "flowlayout.py"] -} diff --git a/examples/widgets/painting/concentriccircles.py b/examples/widgets/painting/concentriccircles/concentriccircles.py index 08520b063..08520b063 100644 --- a/examples/widgets/painting/concentriccircles.py +++ b/examples/widgets/painting/concentriccircles/concentriccircles.py diff --git a/examples/widgets/painting/painting.pyproject b/examples/widgets/painting/concentriccircles/concentriccircles.pyproject index ed24e12b0..ed24e12b0 100644 --- a/examples/widgets/painting/painting.pyproject +++ b/examples/widgets/painting/concentriccircles/concentriccircles.pyproject diff --git a/examples/widgets/richtext/orderform.py b/examples/widgets/richtext/orderform/orderform.py index ed7b29d61..ed7b29d61 100644 --- a/examples/widgets/richtext/orderform.py +++ b/examples/widgets/richtext/orderform/orderform.py diff --git a/examples/widgets/richtext/orderform/orderform.pyproject b/examples/widgets/richtext/orderform/orderform.pyproject new file mode 100644 index 000000000..47be69fd2 --- /dev/null +++ b/examples/widgets/richtext/orderform/orderform.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["orderform.py"] +} diff --git a/examples/widgets/richtext/richtext.pyproject b/examples/widgets/richtext/richtext.pyproject deleted file mode 100644 index e91a98961..000000000 --- a/examples/widgets/richtext/richtext.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["syntaxhighlighter.py", "orderform.py"] -} diff --git a/examples/widgets/richtext/syntaxhighlighter.py b/examples/widgets/richtext/syntaxhighlighter.py deleted file mode 100644 index 52b3d53b8..000000000 --- a/examples/widgets/richtext/syntaxhighlighter.py +++ /dev/null @@ -1,203 +0,0 @@ - -############################################################################# -## -## Copyright (C) 2013 Riverbank Computing Limited. -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: http://www.qt.io/licensing/ -## -## This file is part of the 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 widgets/richtext/syntaxhighlighter example from Qt v5.x""" - -from PySide6 import QtCore, QtGui, QtWidgets - - -class MainWindow(QtWidgets.QMainWindow): - def __init__(self, parent=None): - super(MainWindow, self).__init__(parent) - - self.setupFileMenu() - self.setupHelpMenu() - self.setupEditor() - - self.setCentralWidget(self.editor) - self.setWindowTitle("Syntax Highlighter") - - def about(self): - QtWidgets.QMessageBox.about(self, "About Syntax Highlighter", - "<p>The <b>Syntax Highlighter</b> example shows how to " \ - "perform simple syntax highlighting by subclassing the " \ - "QSyntaxHighlighter class and describing highlighting " \ - "rules using regular expressions.</p>") - - def newFile(self): - self.editor.clear() - - def openFile(self, path=None): - if not path: - path = QtWidgets.QFileDialog.getOpenFileName(self, "Open File", - '', "C++ Files (*.cpp *.h)") - - if path: - inFile = QtCore.QFile(path[0]) - if inFile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text): - text = inFile.readAll() - text = str(text, encoding='ascii') - self.editor.setPlainText(text) - - def setupEditor(self): - font = QtGui.QFont() - font.setFamily('Courier') - font.setFixedPitch(True) - font.setPointSize(10) - - self.editor = QtWidgets.QTextEdit() - self.editor.setFont(font) - - self.highlighter = Highlighter(self.editor.document()) - - def setupFileMenu(self): - fileMenu = QtWidgets.QMenu("&File", self) - self.menuBar().addMenu(fileMenu) - - fileMenu.addAction("&New...", self.newFile, "Ctrl+N") - fileMenu.addAction("&Open...", self.openFile, "Ctrl+O") - fileMenu.addAction("E&xit", qApp.quit, "Ctrl+Q") - - def setupHelpMenu(self): - helpMenu = QtWidgets.QMenu("&Help", self) - self.menuBar().addMenu(helpMenu) - - helpMenu.addAction("&About", self.about) - helpMenu.addAction("About &Qt", qApp.aboutQt) - - -class Highlighter(QtGui.QSyntaxHighlighter): - def __init__(self, parent=None): - super(Highlighter, self).__init__(parent) - - keywordFormat = QtGui.QTextCharFormat() - keywordFormat.setForeground(QtCore.Qt.darkBlue) - keywordFormat.setFontWeight(QtGui.QFont.Bold) - - keywordPatterns = ["\\bchar\\b", "\\bclass\\b", "\\bconst\\b", - "\\bdouble\\b", "\\benum\\b", "\\bexplicit\\b", "\\bfriend\\b", - "\\binline\\b", "\\bint\\b", "\\blong\\b", "\\bnamespace\\b", - "\\boperator\\b", "\\bprivate\\b", "\\bprotected\\b", - "\\bpublic\\b", "\\bshort\\b", "\\bsignals\\b", "\\bsigned\\b", - "\\bslots\\b", "\\bstatic\\b", "\\bstruct\\b", - "\\btemplate\\b", "\\btypedef\\b", "\\btypename\\b", - "\\bunion\\b", "\\bunsigned\\b", "\\bvirtual\\b", "\\bvoid\\b", - "\\bvolatile\\b"] - - self.highlightingRules = [(QtCore.QRegularExpression(pattern), keywordFormat) - for pattern in keywordPatterns] - - classFormat = QtGui.QTextCharFormat() - classFormat.setFontWeight(QtGui.QFont.Bold) - classFormat.setForeground(QtCore.Qt.darkMagenta) - pattern = QtCore.QRegularExpression(r'\bQ[A-Za-z]+\b') - assert pattern.isValid() - self.highlightingRules.append((pattern, classFormat)) - - singleLineCommentFormat = QtGui.QTextCharFormat() - singleLineCommentFormat.setForeground(QtCore.Qt.red) - pattern = QtCore.QRegularExpression('//[^\n]*') - assert pattern.isValid() - self.highlightingRules.append((pattern, singleLineCommentFormat)) - - self.multiLineCommentFormat = QtGui.QTextCharFormat() - self.multiLineCommentFormat.setForeground(QtCore.Qt.red) - - quotationFormat = QtGui.QTextCharFormat() - quotationFormat.setForeground(QtCore.Qt.darkGreen) - pattern = QtCore.QRegularExpression('".*"') - assert pattern.isValid() - self.highlightingRules.append((pattern, quotationFormat)) - - functionFormat = QtGui.QTextCharFormat() - functionFormat.setFontItalic(True) - functionFormat.setForeground(QtCore.Qt.blue) - pattern = QtCore.QRegularExpression(r'\b[A-Za-z0-9_]+(?=\()') - assert pattern.isValid() - self.highlightingRules.append((pattern, functionFormat)) - - self.commentStartExpression = QtCore.QRegularExpression(r'/\*') - assert self.commentStartExpression.isValid() - self.commentEndExpression = QtCore.QRegularExpression(r'\*/') - assert self.commentEndExpression.isValid() - - def highlightBlock(self, text): - for pattern, format in self.highlightingRules: - match = pattern.match(text) - while match.hasMatch(): - index = match.capturedStart(0) - length = match.capturedLength(0) - self.setFormat(index, length, format) - match = pattern.match(text, index + length) - - self.setCurrentBlockState(0) - - startIndex = 0 - if self.previousBlockState() != 1: - match = self.commentStartExpression.match(text) - startIndex = match.capturedStart(0) if match.hasMatch() else -1 - - while startIndex >= 0: - match = self.commentEndExpression.match(text, startIndex) - if match.hasMatch(): - endIndex = match.capturedStart(0) - length = match.capturedLength(0) - commentLength = endIndex - startIndex + length - else: - self.setCurrentBlockState(1) - commentLength = len(text) - startIndex - - self.setFormat(startIndex, commentLength, - self.multiLineCommentFormat) - match = self.commentStartExpression.match(text, startIndex + commentLength) - startIndex = match.capturedStart(0) if match.hasMatch() else -1 - - -if __name__ == '__main__': - - import sys - - app = QtWidgets.QApplication(sys.argv) - window = MainWindow() - window.resize(640, 512) - window.show() - sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/eventtrans.py b/examples/widgets/state-machine/eventtrans.py index 3445832a0..60c464b77 100644 --- a/examples/widgets/state-machine/eventtrans.py +++ b/examples/widgets/state-machine/eventtrans.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> diff --git a/examples/widgets/state-machine/eventtrans/eventtrans.py b/examples/widgets/state-machine/eventtrans/eventtrans.py new file mode 100644 index 000000000..312b4e258 --- /dev/null +++ b/examples/widgets/state-machine/eventtrans/eventtrans.py @@ -0,0 +1,94 @@ + +############################################################################# +## +## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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.QtWidgets import * +from PySide6.QtCore import * +from PySide6.QtStateMachine import QEventTransition, QState, QStateMachine + + +class MainWindow(QMainWindow): + def __init__(self): + super(MainWindow, self).__init__() + button = QPushButton(self) + button.setGeometry(QRect(100, 100, 100, 100)) + + machine = QStateMachine(self) + s1 = QState() + s1.assignProperty(button, 'text', 'Outside') + s2 = QState() + s2.assignProperty(button, 'text', 'Inside') + + enterTransition = QEventTransition(button, QEvent.Enter) + enterTransition.setTargetState(s2) + s1.addTransition(enterTransition) + + leaveTransition = QEventTransition(button, QEvent.Leave) + leaveTransition.setTargetState(s1) + s2.addTransition(leaveTransition) + + s3 = QState() + s3.assignProperty(button, 'text', 'Pressing...') + + pressTransition = QEventTransition(button, QEvent.MouseButtonPress) + pressTransition.setTargetState(s3) + s2.addTransition(pressTransition) + + releaseTransition = QEventTransition(button, QEvent.MouseButtonRelease) + releaseTransition.setTargetState(s2) + s3.addTransition(releaseTransition) + + machine.addState(s1) + machine.addState(s2) + machine.addState(s3) + + machine.setInitialState(s1) + machine.start() + + self.setCentralWidget(button) + self.show() + +if __name__ == '__main__': + import sys + + app = QApplication(sys.argv) + mainWin = MainWindow() + sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/eventtrans/eventtrans.pyproject b/examples/widgets/state-machine/eventtrans/eventtrans.pyproject new file mode 100644 index 000000000..b2f660a8f --- /dev/null +++ b/examples/widgets/state-machine/eventtrans/eventtrans.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["eventtrans.py"] +} diff --git a/examples/widgets/state-machine/factstates.py b/examples/widgets/state-machine/factstates.py index 64b9613ec..d3feaa650 100644 --- a/examples/widgets/state-machine/factstates.py +++ b/examples/widgets/state-machine/factstates.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> diff --git a/examples/widgets/state-machine/factstates/factstates.py b/examples/widgets/state-machine/factstates/factstates.py new file mode 100644 index 000000000..3608f2a49 --- /dev/null +++ b/examples/widgets/state-machine/factstates/factstates.py @@ -0,0 +1,114 @@ + +############################################################################# +## +## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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.QtWidgets import * +from PySide6.QtCore import * +from PySide6.QtStateMachine import (QFinalState, QSignalTransition, QState, + QStateMachine) + + +class Factorial(QObject): + xChanged = Signal(int) + def __init__(self): + super(Factorial, self).__init__() + self.xval = -1 + self.facval = 1 + def getX(self): + return self.xval + def setX(self, x): + if self.xval == x: + return + self.xval = x + self.xChanged.emit(x) + x = Property(int, getX, setX) + def getFact(self): + return self.facval + def setFact(self, fac): + self.facval = fac + fac = Property(int, getFact, setFact) + +class FactorialLoopTransition(QSignalTransition): + def __init__(self, fact): + super(FactorialLoopTransition, self).__init__(fact, SIGNAL('xChanged(int)')) + self.fact = fact + def eventTest(self, e): + if not super(FactorialLoopTransition, self).eventTest(e): + return False + return e.arguments()[0] > 1 + def onTransition(self, e): + x = e.arguments()[0] + fac = self.fact.fac + self.fact.fac = x * fac + self.fact.x = x - 1 + +class FactorialDoneTransition(QSignalTransition): + def __init__(self, fact): + super(FactorialDoneTransition, self).__init__(fact, SIGNAL('xChanged(int)')) + self.fact = fact + def eventTest(self, e): + if not super(FactorialDoneTransition, self).eventTest(e): + return False + return e.arguments()[0] <= 1 + def onTransition(self, e): + print(self.fact.fac) + +if __name__ == '__main__': + import sys + app = QCoreApplication(sys.argv) + factorial = Factorial() + machine = QStateMachine() + + compute = QState(machine) + compute.assignProperty(factorial, 'fac', 1) + compute.assignProperty(factorial, 'x', 6) + compute.addTransition(FactorialLoopTransition(factorial)) + + done = QFinalState(machine) + doneTransition = FactorialDoneTransition(factorial) + doneTransition.setTargetState(done) + compute.addTransition(doneTransition) + + machine.setInitialState(compute) + machine.finished.connect(app.quit) + machine.start() + + sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/factstates/factstates.pyproject b/examples/widgets/state-machine/factstates/factstates.pyproject new file mode 100644 index 000000000..751a5005b --- /dev/null +++ b/examples/widgets/state-machine/factstates/factstates.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["factstates.py"] +} diff --git a/examples/widgets/state-machine/pingpong.py b/examples/widgets/state-machine/pingpong.py index 6d64bebc6..99f5ef1d5 100644 --- a/examples/widgets/state-machine/pingpong.py +++ b/examples/widgets/state-machine/pingpong.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> diff --git a/examples/widgets/state-machine/pingpong/pingpong.py b/examples/widgets/state-machine/pingpong/pingpong.py new file mode 100644 index 000000000..f2e1f59f7 --- /dev/null +++ b/examples/widgets/state-machine/pingpong/pingpong.py @@ -0,0 +1,98 @@ + +############################################################################# +## +## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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.QtWidgets import * +from PySide6.QtCore import * +from PySide6.QtStateMachine import QAbstractTransition, QState, QStateMachine + + +class PingEvent(QEvent): + def __init__(self): + super(PingEvent, self).__init__(QEvent.Type(QEvent.User+2)) +class PongEvent(QEvent): + def __init__(self): + super(PongEvent, self).__init__(QEvent.Type(QEvent.User+3)) + +class Pinger(QState): + def __init__(self, parent): + super(Pinger, self).__init__(parent) + def onEntry(self, e): + self.p = PingEvent() + self.machine().postEvent(self.p) + print('ping?') + +class PongTransition(QAbstractTransition): + def eventTest(self, e): + return e.type() == QEvent.User+3 + def onTransition(self, e): + self.p = PingEvent() + machine.postDelayedEvent(self.p, 500) + print('ping?') +class PingTransition(QAbstractTransition): + def eventTest(self, e): + return e.type() == QEvent.User+2 + def onTransition(self, e): + self.p = PongEvent() + machine.postDelayedEvent(self.p, 500) + print('pong!') + +if __name__ == '__main__': + import sys + app = QCoreApplication(sys.argv) + + machine = QStateMachine() + group = QState(QState.ParallelStates) + group.setObjectName('group') + + pinger = Pinger(group) + pinger.setObjectName('pinger') + pinger.addTransition(PongTransition()) + + ponger = QState(group) + ponger.setObjectName('ponger') + ponger.addTransition(PingTransition()) + + machine.addState(group) + machine.setInitialState(group) + machine.start() + + sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/pingpong/pingpong.pyproject b/examples/widgets/state-machine/pingpong/pingpong.pyproject new file mode 100644 index 000000000..67b48e5ab --- /dev/null +++ b/examples/widgets/state-machine/pingpong/pingpong.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["pingpong.py"] +} diff --git a/examples/widgets/state-machine/rogue.py b/examples/widgets/state-machine/rogue.py index af37b522b..7ce271ff1 100644 --- a/examples/widgets/state-machine/rogue.py +++ b/examples/widgets/state-machine/rogue.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> diff --git a/examples/widgets/state-machine/rogue/rogue.py b/examples/widgets/state-machine/rogue/rogue.py new file mode 100644 index 000000000..b830d6023 --- /dev/null +++ b/examples/widgets/state-machine/rogue/rogue.py @@ -0,0 +1,205 @@ + +############################################################################# +## +## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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.QtWidgets import * +from PySide6.QtGui import * +from PySide6.QtCore import * +from PySide6.QtStateMachine import (QEventTransition, QFinalState, + QKeyEventTransition, QState, QStateMachine) + + +class MovementTransition(QEventTransition): + def __init__(self, window): + super(MovementTransition, self).__init__(window, QEvent.KeyPress) + self.window = window + def eventTest(self, event): + if event.type() == QEvent.StateMachineWrapped and \ + event.event().type() == QEvent.KeyPress: + key = event.event().key() + return key == Qt.Key_2 or key == Qt.Key_8 or \ + key == Qt.Key_6 or key == Qt.Key_4 + return False + def onTransition(self, event): + key = event.event().key() + if key == Qt.Key_4: + self.window.movePlayer(self.window.Left) + if key == Qt.Key_8: + self.window.movePlayer(self.window.Up) + if key == Qt.Key_6: + self.window.movePlayer(self.window.Right) + if key == Qt.Key_2: + self.window.movePlayer(self.window.Down) + +class Custom(QState): + def __init__(self, parent, mw): + super(Custom, self).__init__(parent) + self.mw = mw + + def onEntry(self, e): + print(self.mw.status) + +class MainWindow(QMainWindow): + def __init__(self): + super(MainWindow, self).__init__() + self.pX = 5 + self.pY = 5 + self.width = 35 + self.height = 20 + self.statusStr = '' + + font = QFont() + if 'Monospace' in QFontDatabase.families(): + font = QFont('Monospace', 12) + else: + for family in QFontDatabase.families(): + if database.isFixedPitch(family): + font = QFont(family, 12) + self.setFont(font) + + self.setupMap() + self.buildMachine() + self.show() + def setupMap(self): + self.map = [] + generator = QRandomGenerator().global_() + for x in range(self.width): + column = [] + for y in range(self.height): + if x == 0 or x == self.width - 1 or y == 0 or \ + y == self.height - 1 or generator.bounded(0, 40) == 0: + column.append('#') + else: + column.append('.') + self.map.append(column) + + def buildMachine(self): + machine = QStateMachine(self) + + inputState = Custom(machine, self) + # this line sets the status + self.status = 'hello!' + # however this line does not + inputState.assignProperty(self, 'status', 'Move the rogue with 2, 4, 6, and 8') + + machine.setInitialState(inputState) + machine.start() + + transition = MovementTransition(self) + inputState.addTransition(transition) + + quitState = QState(machine) + quitState.assignProperty(self, 'status', 'Really quit(y/n)?') + + yesTransition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_Y) + self.finalState = QFinalState(machine) + yesTransition.setTargetState(self.finalState) + quitState.addTransition(yesTransition) + + noTransition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_N) + noTransition.setTargetState(inputState) + quitState.addTransition(noTransition) + + quitTransition = QKeyEventTransition(self, QEvent.KeyPress, Qt.Key_Q) + quitTransition.setTargetState(quitState) + inputState.addTransition(quitTransition) + + machine.setInitialState(inputState) + machine.finished.connect(qApp.quit) + machine.start() + + def sizeHint(self): + metrics = QFontMetrics(self.font()) + return QSize(metrics.horizontalAdvance('X') * self.width, + metrics.height() * (self.height + 1)) + def paintEvent(self, event): + metrics = QFontMetrics(self.font()) + painter = QPainter(self) + fontHeight = metrics.height() + fontWidth = metrics.horizontalAdvance('X') + + painter.fillRect(self.rect(), Qt.black) + painter.setPen(Qt.white) + + yPos = fontHeight + painter.drawText(QPoint(0, yPos), self.status) + for y in range(self.height): + yPos += fontHeight + xPos = 0 + for x in range(self.width): + if y == self.pY and x == self.pX: + xPos += fontWidth + continue + painter.drawText(QPoint(xPos, yPos), self.map[x][y]) + xPos += fontWidth + painter.drawText(QPoint(self.pX * fontWidth, (self.pY + 2) * fontHeight), '@') + def movePlayer(self, direction): + if direction == self.Left: + if self.map[self.pX - 1][self.pY] != '#': + self.pX -= 1 + elif direction == self.Right: + if self.map[self.pX + 1][self.pY] != '#': + self.pX += 1 + elif direction == self.Up: + if self.map[self.pX][self.pY - 1] != '#': + self.pY -= 1 + elif direction == self.Down: + if self.map[self.pX][self.pY + 1] != '#': + self.pY += 1 + self.repaint() + def getStatus(self): + return self.statusStr + def setStatus(self, status): + self.statusStr = status + self.repaint() + status = Property(str, getStatus, setStatus) + Up = 0 + Down = 1 + Left = 2 + Right = 3 + Width = 35 + Height = 20 + +if __name__ == '__main__': + import sys + app = QApplication(sys.argv) + mainWin = MainWindow() + sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/rogue/rogue.pyproject b/examples/widgets/state-machine/rogue/rogue.pyproject new file mode 100644 index 000000000..b8baf9802 --- /dev/null +++ b/examples/widgets/state-machine/rogue/rogue.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["rogue.py"] +} diff --git a/examples/widgets/state-machine/state-machine.pyproject b/examples/widgets/state-machine/state-machine.pyproject deleted file mode 100644 index dafb204c8..000000000 --- a/examples/widgets/state-machine/state-machine.pyproject +++ /dev/null @@ -1,4 +0,0 @@ -{ - "files": ["pingpong.py", "trafficlight.py", "twowaybutton.py", - "eventtrans.py", "rogue.py", "factstates.py"] -} diff --git a/examples/widgets/state-machine/trafficlight.py b/examples/widgets/state-machine/trafficlight.py index 4aa8d560e..b0ea807b9 100644 --- a/examples/widgets/state-machine/trafficlight.py +++ b/examples/widgets/state-machine/trafficlight.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> diff --git a/examples/widgets/state-machine/trafficlight/trafficlight.py b/examples/widgets/state-machine/trafficlight/trafficlight.py new file mode 100644 index 000000000..3631fdbbb --- /dev/null +++ b/examples/widgets/state-machine/trafficlight/trafficlight.py @@ -0,0 +1,141 @@ + +############################################################################# +## +## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: http://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.QtWidgets import * +from PySide6.QtGui import * +from PySide6.QtCore import * +from PySide6.QtStateMachine import QFinalState, QState, QStateMachine + + +class LightWidget(QWidget): + def __init__(self, color): + super(LightWidget, self).__init__() + self.color = color + self.onVal = False + def isOn(self): + return self.onVal + def setOn(self, on): + if self.onVal == on: + return + self.onVal = on + self.update() + @Slot() + def turnOff(self): + self.setOn(False) + @Slot() + def turnOn(self): + self.setOn(True) + def paintEvent(self, e): + if not self.onVal: + return + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing) + painter.setBrush(self.color) + painter.drawEllipse(0, 0, self.width(), self.height()) + + on = Property(bool, isOn, setOn) + +class TrafficLightWidget(QWidget): + def __init__(self): + super(TrafficLightWidget, self).__init__() + vbox = QVBoxLayout(self) + self.redLight = LightWidget(Qt.red) + vbox.addWidget(self.redLight) + self.yellowLight = LightWidget(Qt.yellow) + vbox.addWidget(self.yellowLight) + self.greenLight = LightWidget(Qt.green) + vbox.addWidget(self.greenLight) + pal = QPalette() + pal.setColor(QPalette.Window, Qt.black) + self.setPalette(pal) + self.setAutoFillBackground(True) + +def createLightState(light, duration, parent=None): + lightState = QState(parent) + timer = QTimer(lightState) + timer.setInterval(duration) + timer.setSingleShot(True) + timing = QState(lightState) + timing.entered.connect(light.turnOn) + timing.entered.connect(timer.start) + timing.exited.connect(light.turnOff) + done = QFinalState(lightState) + timing.addTransition(timer, SIGNAL('timeout()'), done) + lightState.setInitialState(timing) + return lightState + +class TrafficLight(QWidget): + def __init__(self): + super(TrafficLight, self).__init__() + vbox = QVBoxLayout(self) + widget = TrafficLightWidget() + vbox.addWidget(widget) + vbox.setContentsMargins(0, 0, 0, 0) + + machine = QStateMachine(self) + redGoingYellow = createLightState(widget.redLight, 1000) + redGoingYellow.setObjectName('redGoingYellow') + yellowGoingGreen = createLightState(widget.redLight, 1000) + yellowGoingGreen.setObjectName('redGoingYellow') + redGoingYellow.addTransition(redGoingYellow, SIGNAL('finished()'), yellowGoingGreen) + greenGoingYellow = createLightState(widget.yellowLight, 3000) + greenGoingYellow.setObjectName('redGoingYellow') + yellowGoingGreen.addTransition(yellowGoingGreen, SIGNAL('finished()'), greenGoingYellow) + yellowGoingRed = createLightState(widget.greenLight, 1000) + yellowGoingRed.setObjectName('redGoingYellow') + greenGoingYellow.addTransition(greenGoingYellow, SIGNAL('finished()'), yellowGoingRed) + yellowGoingRed.addTransition(yellowGoingRed, SIGNAL('finished()'), redGoingYellow) + + machine.addState(redGoingYellow) + machine.addState(yellowGoingGreen) + machine.addState(greenGoingYellow) + machine.addState(yellowGoingRed) + machine.setInitialState(redGoingYellow) + machine.start() + +if __name__ == '__main__': + import sys + app = QApplication(sys.argv) + widget = TrafficLight() + widget.resize(110, 300) + widget.show() + sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/trafficlight/trafficlight.pyproject b/examples/widgets/state-machine/trafficlight/trafficlight.pyproject new file mode 100644 index 000000000..912472693 --- /dev/null +++ b/examples/widgets/state-machine/trafficlight/trafficlight.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["trafficlight.py"] +} diff --git a/examples/widgets/state-machine/twowaybutton.py b/examples/widgets/state-machine/twowaybutton.py index 44a011d69..3ac7a86aa 100644 --- a/examples/widgets/state-machine/twowaybutton.py +++ b/examples/widgets/state-machine/twowaybutton.py @@ -1,4 +1,3 @@ - ############################################################################# ## ## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> diff --git a/examples/widgets/state-machine/twowaybutton/twowaybutton.py b/examples/widgets/state-machine/twowaybutton/twowaybutton.py new file mode 100644 index 000000000..6b3c58359 --- /dev/null +++ b/examples/widgets/state-machine/twowaybutton/twowaybutton.py @@ -0,0 +1,72 @@ + +############################################################################# +## +## Copyright (C) 2010 velociraptor Genjix <aphidia@hotmail.com> +## Copyright (C) 2021 The Qt Company Ltd. +## Contact: http://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.QtWidgets import * +from PySide6.QtCore import * +from PySide6.QtStateMachine import QState, QStateMachine + + +if __name__ == '__main__': + import sys + app = QApplication(sys.argv) + button = QPushButton() + machine = QStateMachine() + + off = QState() + off.assignProperty(button, 'text', 'Off') + off.setObjectName('off') + + on = QState() + on.setObjectName('on') + on.assignProperty(button, 'text', 'On') + + off.addTransition(button, SIGNAL('clicked()'), on) + # Let's use the new style signals just for the kicks. + on.addTransition(button.clicked, off) + + machine.addState(off) + machine.addState(on) + machine.setInitialState(off) + machine.start() + button.resize(100, 50) + button.show() + sys.exit(app.exec_()) diff --git a/examples/widgets/state-machine/twowaybutton/twowaybutton.pyproject b/examples/widgets/state-machine/twowaybutton/twowaybutton.pyproject new file mode 100644 index 000000000..223a51e32 --- /dev/null +++ b/examples/widgets/state-machine/twowaybutton/twowaybutton.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["twowaybutton.py"] +} diff --git a/examples/widgets/widgets/tetrix.py b/examples/widgets/tetrix/tetrix.py index 69c6d4bff..69c6d4bff 100644 --- a/examples/widgets/widgets/tetrix.py +++ b/examples/widgets/tetrix/tetrix.py diff --git a/examples/widgets/tetrix/tetrix.pyproject b/examples/widgets/tetrix/tetrix.pyproject new file mode 100644 index 000000000..75121ea64 --- /dev/null +++ b/examples/widgets/tetrix/tetrix.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["tetrix.py"] +} diff --git a/examples/widgets/threads/thread_signals.pyproject b/examples/widgets/threads/thread_signals.pyproject new file mode 100644 index 000000000..e36f7633c --- /dev/null +++ b/examples/widgets/threads/thread_signals.pyproject @@ -0,0 +1,3 @@ +{ + "files": ["thread_signals.py"] +} diff --git a/examples/tutorial/tutorial.pyproject b/examples/widgets/tutorials/cannon/cannon.pyproject index 09478e108..09478e108 100644 --- a/examples/tutorial/tutorial.pyproject +++ b/examples/widgets/tutorials/cannon/cannon.pyproject diff --git a/examples/tutorial/t1.py b/examples/widgets/tutorials/cannon/t1.py index 43fea90c4..43fea90c4 100644 --- a/examples/tutorial/t1.py +++ b/examples/widgets/tutorials/cannon/t1.py diff --git a/examples/tutorial/t10.py b/examples/widgets/tutorials/cannon/t10.py index ca7e9d9b7..ca7e9d9b7 100644 --- a/examples/tutorial/t10.py +++ b/examples/widgets/tutorials/cannon/t10.py diff --git a/examples/tutorial/t11.py b/examples/widgets/tutorials/cannon/t11.py index c3d2e1271..c3d2e1271 100644 --- a/examples/tutorial/t11.py +++ b/examples/widgets/tutorials/cannon/t11.py diff --git a/examples/tutorial/t12.py b/examples/widgets/tutorials/cannon/t12.py index 290ecc82e..290ecc82e 100644 --- a/examples/tutorial/t12.py +++ b/examples/widgets/tutorials/cannon/t12.py diff --git a/examples/tutorial/t13.py b/examples/widgets/tutorials/cannon/t13.py index b54945e25..b54945e25 100644 --- a/examples/tutorial/t13.py +++ b/examples/widgets/tutorials/cannon/t13.py diff --git a/examples/tutorial/t14.py b/examples/widgets/tutorials/cannon/t14.py index d558d2e61..d558d2e61 100644 --- a/examples/tutorial/t14.py +++ b/examples/widgets/tutorials/cannon/t14.py diff --git a/examples/tutorial/t2.py b/examples/widgets/tutorials/cannon/t2.py index d51986f47..d51986f47 100644 --- a/examples/tutorial/t2.py +++ b/examples/widgets/tutorials/cannon/t2.py diff --git a/examples/tutorial/t3.py b/examples/widgets/tutorials/cannon/t3.py index fa96d6ff1..fa96d6ff1 100644 --- a/examples/tutorial/t3.py +++ b/examples/widgets/tutorials/cannon/t3.py diff --git a/examples/tutorial/t4.py b/examples/widgets/tutorials/cannon/t4.py index 4c30dfcbb..4c30dfcbb 100644 --- a/examples/tutorial/t4.py +++ b/examples/widgets/tutorials/cannon/t4.py diff --git a/examples/tutorial/t5.py b/examples/widgets/tutorials/cannon/t5.py index af36578cd..af36578cd 100644 --- a/examples/tutorial/t5.py +++ b/examples/widgets/tutorials/cannon/t5.py diff --git a/examples/tutorial/t6.py b/examples/widgets/tutorials/cannon/t6.py index 9094c0ce9..9094c0ce9 100644 --- a/examples/tutorial/t6.py +++ b/examples/widgets/tutorials/cannon/t6.py diff --git a/examples/tutorial/t7.py b/examples/widgets/tutorials/cannon/t7.py index 590bd516c..590bd516c 100644 --- a/examples/tutorial/t7.py +++ b/examples/widgets/tutorials/cannon/t7.py diff --git a/examples/tutorial/t8.py b/examples/widgets/tutorials/cannon/t8.py index 3761b4353..3761b4353 100644 --- a/examples/tutorial/t8.py +++ b/examples/widgets/tutorials/cannon/t8.py diff --git a/examples/tutorial/t9.py b/examples/widgets/tutorials/cannon/t9.py index ca949c1ac..ca949c1ac 100644 --- a/examples/tutorial/t9.py +++ b/examples/widgets/tutorials/cannon/t9.py diff --git a/examples/widgets/widgets/widgets.pyproject b/examples/widgets/widgets/widgets.pyproject deleted file mode 100644 index b4e3ef67e..000000000 --- a/examples/widgets/widgets/widgets.pyproject +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["tetrix.py", "hellogl_openglwidget_legacy.py"] -} |