Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/graphs/2d/graphsaudio/GraphsAudio/Main.qml50
-rw-r--r--examples/graphs/2d/graphsaudio/GraphsAudio/qmldir2
-rw-r--r--examples/graphs/2d/graphsaudio/doc/graphsaudio.rst8
-rw-r--r--examples/graphs/2d/graphsaudio/doc/graphsaudio.webpbin0 -> 12908 bytes
-rw-r--r--examples/graphs/2d/graphsaudio/graphsaudio.pyproject3
-rw-r--r--examples/graphs/2d/graphsaudio/main.py80
-rw-r--r--examples/xml/dombookmarks/dombookmarks.py20
7 files changed, 153 insertions, 10 deletions
diff --git a/examples/graphs/2d/graphsaudio/GraphsAudio/Main.qml b/examples/graphs/2d/graphsaudio/GraphsAudio/Main.qml
new file mode 100644
index 000000000..51bf3ef12
--- /dev/null
+++ b/examples/graphs/2d/graphsaudio/GraphsAudio/Main.qml
@@ -0,0 +1,50 @@
+// Copyright (C) 2025 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import QtQuick
+import QtQuick.Controls
+import QtGraphs
+
+ApplicationWindow {
+ visible: true
+ width: 1000
+ height: 800
+ title: "Data from the microphone (" + device_name + ")"
+
+ GraphsView {
+ id: graph
+ anchors.fill: parent
+
+ LineSeries {
+ id: audio_series
+ width: 2
+ color: "#007acc"
+ }
+
+ axisX: ValueAxis {
+ min: 0
+ max: 2000
+ tickInterval : 500
+ labelFormat: "%g"
+ titleText: "Samples"
+ }
+
+ axisY: ValueAxis {
+ min: -1
+ max: 1
+ tickInterval : 0.5
+ labelFormat: "%0.1f"
+ titleText: "Audio level"
+ }
+ }
+
+ Connections {
+ target: audio_bridge
+ function onDataUpdated(buffer) {
+ audio_series.clear()
+ for (let i = 0; i < buffer.length; ++i) {
+ audio_series.append(buffer[i])
+ }
+ }
+ }
+}
diff --git a/examples/graphs/2d/graphsaudio/GraphsAudio/qmldir b/examples/graphs/2d/graphsaudio/GraphsAudio/qmldir
new file mode 100644
index 000000000..cc5408a66
--- /dev/null
+++ b/examples/graphs/2d/graphsaudio/GraphsAudio/qmldir
@@ -0,0 +1,2 @@
+module GraphsAudio
+Main 1.0 Main.qml
diff --git a/examples/graphs/2d/graphsaudio/doc/graphsaudio.rst b/examples/graphs/2d/graphsaudio/doc/graphsaudio.rst
new file mode 100644
index 000000000..f19b28caf
--- /dev/null
+++ b/examples/graphs/2d/graphsaudio/doc/graphsaudio.rst
@@ -0,0 +1,8 @@
+GraphsAudio Example
+===================
+
+This example shows the drawing of dynamic data (microphone input) using QtGraphs and Qml.
+
+.. image:: graphsaudio.webp
+ :width: 400
+ :alt: GraphsAudio Screenshot
diff --git a/examples/graphs/2d/graphsaudio/doc/graphsaudio.webp b/examples/graphs/2d/graphsaudio/doc/graphsaudio.webp
new file mode 100644
index 000000000..bb57b18e5
--- /dev/null
+++ b/examples/graphs/2d/graphsaudio/doc/graphsaudio.webp
Binary files differ
diff --git a/examples/graphs/2d/graphsaudio/graphsaudio.pyproject b/examples/graphs/2d/graphsaudio/graphsaudio.pyproject
new file mode 100644
index 000000000..eff791919
--- /dev/null
+++ b/examples/graphs/2d/graphsaudio/graphsaudio.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py", "GraphsAudio/Main.qml", "GraphsAudio/qmldir"]
+}
diff --git a/examples/graphs/2d/graphsaudio/main.py b/examples/graphs/2d/graphsaudio/main.py
new file mode 100644
index 000000000..239aee036
--- /dev/null
+++ b/examples/graphs/2d/graphsaudio/main.py
@@ -0,0 +1,80 @@
+# Copyright (C) 2025 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+from __future__ import annotations
+
+import sys
+from pathlib import Path
+from PySide6.QtCore import QObject, QPointF, Slot, Signal
+from PySide6.QtMultimedia import QAudioFormat, QAudioSource, QMediaDevices
+from PySide6.QtWidgets import QMessageBox
+from PySide6.QtQml import QQmlApplicationEngine
+from PySide6.QtGui import QGuiApplication
+
+
+SAMPLE_COUNT = 2000
+RESOLUTION = 4
+
+
+class Audio(QObject):
+ dataUpdated = Signal(list)
+
+ def __init__(self, device):
+ super().__init__()
+
+ format_audio = QAudioFormat()
+ format_audio.setSampleRate(8000)
+ format_audio.setChannelCount(1)
+ format_audio.setSampleFormat(QAudioFormat.UInt8)
+
+ self.device_name = device.description()
+
+ self._audio_input = QAudioSource(device, format_audio, self)
+ self._io_device = self._audio_input.start()
+ self._io_device.readyRead.connect(self._readyRead)
+
+ self._buffer = [QPointF(x, 0) for x in range(SAMPLE_COUNT)]
+
+ def closeEvent(self, event):
+ if self._audio_input is not None:
+ self._audio_input.stop()
+ event.accept()
+
+ @Slot()
+ def _readyRead(self):
+ data = self._io_device.readAll()
+ available_samples = data.size() // RESOLUTION
+ start = 0
+ if (available_samples < SAMPLE_COUNT):
+ start = SAMPLE_COUNT - available_samples
+ for s in range(start):
+ self._buffer[s].setY(self._buffer[s + available_samples].y())
+
+ data_index = 0
+ for s in range(start, SAMPLE_COUNT):
+ value = (ord(data[data_index]) - 128) / 128
+ self._buffer[s].setY(value)
+ data_index = data_index + RESOLUTION
+
+ self.dataUpdated.emit(self._buffer)
+
+
+if __name__ == '__main__':
+ app = QGuiApplication(sys.argv)
+ engine = QQmlApplicationEngine()
+
+ input_devices = QMediaDevices.audioInputs()
+ if not input_devices:
+ QMessageBox.warning(None, "audio", "There is no audio input device available.")
+ sys.exit(-1)
+
+ audio_bridge = Audio(input_devices[0])
+ engine.rootContext().setContextProperty("audio_bridge", audio_bridge)
+
+ device = input_devices[0]
+ device_name = device.description()
+ engine.rootContext().setContextProperty("device_name", device_name)
+
+ engine.addImportPath(Path(__file__).parent)
+ engine.loadFromModule("GraphsAudio", "Main")
+
+ sys.exit(app.exec())
diff --git a/examples/xml/dombookmarks/dombookmarks.py b/examples/xml/dombookmarks/dombookmarks.py
index f5afdeef8..f02251849 100644
--- a/examples/xml/dombookmarks/dombookmarks.py
+++ b/examples/xml/dombookmarks/dombookmarks.py
@@ -7,7 +7,7 @@ from __future__ import annotations
import sys
-from PySide6.QtCore import QDir, QFile, Qt, QTextStream
+from PySide6.QtCore import QDir, QFile, QObject, Qt, QTextStream
from PySide6.QtGui import QAction, QIcon, QKeySequence
from PySide6.QtWidgets import (QApplication, QFileDialog, QHeaderView,
QMainWindow, QMessageBox, QStyle, QTreeWidget,
@@ -93,6 +93,7 @@ class XbelTree(QTreeWidget):
def __init__(self, parent=None):
super().__init__(parent)
+ self._update_conn_id = None
self.header().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
self.setHeaderLabels(("Title", "Location"))
@@ -111,11 +112,12 @@ class XbelTree(QTreeWidget):
self._bookmark_icon.addPixmap(style.standardPixmap(QStyle.StandardPixmap.SP_FileIcon))
def read(self, device):
- ok, errorStr, errorLine, errorColumn = self._dom_document.setContent(device, True)
- if not ok:
+ result = self._dom_document.setContent(device,
+ QDomDocument.ParseOption.UseNamespaceProcessing)
+ if not result:
QMessageBox.information(self.window(), "DOM Bookmarks",
- f"Parse error at line {errorLine}, "
- f"column {errorColumn}:\n{errorStr}")
+ f"Parse error at line {result.errorLine}, "
+ f"column {result.errorColumn}:\n{result.errorMessage}")
return False
root = self._dom_document.documentElement()
@@ -131,17 +133,15 @@ class XbelTree(QTreeWidget):
self.clear()
# It might not be connected.
- try:
- self.itemChanged.disconnect(self.update_dom_element)
- except RuntimeError:
- pass
+ if self._update_conn_id:
+ QObject.disconnect(self._update_conn_id)
child = root.firstChildElement('folder')
while not child.isNull():
self.parse_folder_element(child)
child = child.nextSiblingElement('folder')
- self.itemChanged.connect(self.update_dom_element)
+ self._update_conn_id = self.itemChanged.connect(self.update_dom_element)
return True