aboutsummaryrefslogtreecommitdiffstats
path: root/examples/corelib
diff options
context:
space:
mode:
Diffstat (limited to 'examples/corelib')
-rw-r--r--examples/corelib/ipc/sharedmemory/dialog.py93
-rw-r--r--examples/corelib/ipc/sharedmemory/dialog.ui47
-rw-r--r--examples/corelib/ipc/sharedmemory/image.pngbin0 -> 10199 bytes
-rw-r--r--examples/corelib/ipc/sharedmemory/main.py15
-rw-r--r--examples/corelib/ipc/sharedmemory/qt.pngbin0 -> 2991 bytes
-rw-r--r--examples/corelib/ipc/sharedmemory/sharedmemory.pyproject3
-rw-r--r--examples/corelib/ipc/sharedmemory/ui_dialog.py57
-rw-r--r--examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.pngbin0 -> 22569 bytes
-rw-r--r--examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.rst10
-rw-r--r--examples/corelib/mimetypesbrowser/mainwindow.py161
-rw-r--r--examples/corelib/mimetypesbrowser/mimetypemodel.py136
-rw-r--r--examples/corelib/mimetypesbrowser/mimetypesbrowser.py24
-rw-r--r--examples/corelib/mimetypesbrowser/mimetypesbrowser.pyproject3
-rw-r--r--examples/corelib/settingseditor/doc/settingseditor.pngbin0 -> 10234 bytes
-rw-r--r--examples/corelib/settingseditor/doc/settingseditor.rst10
-rw-r--r--examples/corelib/settingseditor/settingseditor.py (renamed from examples/corelib/tools/settingseditor/settingseditor.py)219
-rw-r--r--examples/corelib/settingseditor/settingseditor.pyproject (renamed from examples/corelib/tools/settingseditor/settingseditor.pyproject)0
-rw-r--r--examples/corelib/threads/doc/threads.pngbin0 -> 61689 bytes
-rw-r--r--examples/corelib/threads/doc/threads.rst10
-rw-r--r--examples/corelib/threads/mandelbrot.py392
-rw-r--r--examples/corelib/tools/codecs/codecs.pyproject3
-rw-r--r--examples/corelib/tools/regexp.py194
-rw-r--r--examples/corelib/tools/tools.pyproject3
23 files changed, 863 insertions, 517 deletions
diff --git a/examples/corelib/ipc/sharedmemory/dialog.py b/examples/corelib/ipc/sharedmemory/dialog.py
new file mode 100644
index 000000000..134900047
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/dialog.py
@@ -0,0 +1,93 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+import os
+from pathlib import Path
+
+from PySide6.QtWidgets import QFileDialog, QDialog
+from PySide6.QtCore import QBuffer, QIODeviceBase, Slot, QSharedMemory, QDataStream, qVersion
+from PySide6.QtGui import QImage, QPixmap
+from ui_dialog import Ui_Dialog
+
+
+class Dialog(QDialog):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+
+ v = qVersion()
+ name = f"QSharedMemoryExample_v{v}"
+ self._shared_memory = QSharedMemory(name)
+
+ self.ui = Ui_Dialog()
+ self.ui.setupUi(self)
+ self.ui.loadFromFileButton.clicked.connect(self.load_from_file)
+ self.ui.loadFromSharedMemoryButton.clicked.connect(self.load_from_memory)
+ self.setWindowTitle("SharedMemory Example")
+
+ def ensure_detached(self):
+ if self._shared_memory.isAttached():
+ self.detach()
+
+ def closeEvent(self, e):
+ self.ensure_detached()
+ e.accept()
+
+ @Slot()
+ def load_from_file(self):
+ self.ensure_detached()
+
+ self.ui.label.setText("Select an image file")
+ dir = Path(__file__).resolve().parent
+ fileName, _ = QFileDialog.getOpenFileName(self, "Choose Image",
+ os.fspath(dir),
+ "Images (*.png *.jpg)")
+ if not fileName:
+ return
+ image = QImage()
+ if not image.load(fileName):
+ self.ui.label.setText("Selected file is not an image, please select another.")
+ return
+ self.ui.label.setPixmap(QPixmap.fromImage(image))
+
+ # load into shared memory
+ buffer = QBuffer()
+ buffer.open(QIODeviceBase.WriteOnly)
+ out = QDataStream(buffer)
+ out << image
+ buffer.close()
+ size = buffer.size()
+
+ if not self._shared_memory.create(size):
+ self.ui.label.setText("Unable to create shared memory segment.")
+ return
+
+ self._shared_memory.lock()
+ _to = memoryview(self._shared_memory.data())
+ _from = buffer.data().data()
+ _to[0:size] = _from[0:size]
+ self._shared_memory.unlock()
+
+ @Slot()
+ def load_from_memory(self):
+ if not self._shared_memory.isAttached() and not self._shared_memory.attach():
+ self.ui.label.setText("Unable to attach to shared memory segment.\n"
+ "Load an image first.")
+ return
+
+ self._shared_memory.lock()
+ mv = memoryview(self._shared_memory.constData())
+ buffer = QBuffer()
+ buffer.setData(mv.tobytes())
+ buffer.open(QBuffer.ReadOnly)
+ _in = QDataStream(buffer)
+ image = QImage()
+ _in >> image
+ buffer.close()
+ self._shared_memory.unlock()
+ self._shared_memory.detach()
+
+ self.ui.label.setPixmap(QPixmap.fromImage(image))
+
+ def detach(self):
+ if not self._shared_memory.detach():
+ self.ui.label.setText(self.tr("Unable to detach from shared memory.")) # noqa: F821
diff --git a/examples/corelib/ipc/sharedmemory/dialog.ui b/examples/corelib/ipc/sharedmemory/dialog.ui
new file mode 100644
index 000000000..e99d6fb3c
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/dialog.ui
@@ -0,0 +1,47 @@
+<ui version="4.0" >
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>451</width>
+ <height>322</height>
+ </rect>
+ </property>
+ <property name="windowTitle" >
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QPushButton" name="loadFromFileButton" >
+ <property name="text" >
+ <string>Load Image From File...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0" >
+ <widget class="QLabel" name="label" >
+ <property name="text" >
+ <string>Launch two of these dialogs. In the first, press the top button and load an image from a file. In the second, press the bottom button and display the loaded image from shared memory.</string>
+ </property>
+ <property name="alignment" >
+ <set>Qt::AlignCenter</set>
+ </property>
+ <property name="wordWrap" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" >
+ <widget class="QPushButton" name="loadFromSharedMemoryButton" >
+ <property name="text" >
+ <string>Display Image From Shared Memory</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/corelib/ipc/sharedmemory/image.png b/examples/corelib/ipc/sharedmemory/image.png
new file mode 100644
index 000000000..dd9345306
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/image.png
Binary files differ
diff --git a/examples/corelib/ipc/sharedmemory/main.py b/examples/corelib/ipc/sharedmemory/main.py
new file mode 100644
index 000000000..e497c8de6
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/main.py
@@ -0,0 +1,15 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the ipc/sharedmemory example from Qt v6.x"""
+
+import sys
+from PySide6.QtWidgets import QApplication
+from dialog import Dialog
+
+
+if __name__ == "__main__":
+ application = QApplication()
+ dialog = Dialog()
+ dialog.show()
+ sys.exit(application.exec())
diff --git a/examples/corelib/ipc/sharedmemory/qt.png b/examples/corelib/ipc/sharedmemory/qt.png
new file mode 100644
index 000000000..4f68e162d
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/qt.png
Binary files differ
diff --git a/examples/corelib/ipc/sharedmemory/sharedmemory.pyproject b/examples/corelib/ipc/sharedmemory/sharedmemory.pyproject
new file mode 100644
index 000000000..14fe88f13
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/sharedmemory.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["dialog.py", "dialog.ui", "image.png", "main.py", "qt.png"]
+}
diff --git a/examples/corelib/ipc/sharedmemory/ui_dialog.py b/examples/corelib/ipc/sharedmemory/ui_dialog.py
new file mode 100644
index 000000000..2cd544f40
--- /dev/null
+++ b/examples/corelib/ipc/sharedmemory/ui_dialog.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+
+################################################################################
+## Form generated from reading UI file 'dialog.ui'
+##
+## Created by: Qt User Interface Compiler version 6.7.0
+##
+## WARNING! All changes made in this file will be lost when recompiling UI file!
+################################################################################
+
+from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
+ QMetaObject, QObject, QPoint, QRect,
+ QSize, QTime, QUrl, Qt)
+from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
+ QFont, QFontDatabase, QGradient, QIcon,
+ QImage, QKeySequence, QLinearGradient, QPainter,
+ QPalette, QPixmap, QRadialGradient, QTransform)
+from PySide6.QtWidgets import (QApplication, QDialog, QGridLayout, QLabel,
+ QPushButton, QSizePolicy, QWidget)
+
+class Ui_Dialog(object):
+ def setupUi(self, Dialog):
+ if not Dialog.objectName():
+ Dialog.setObjectName(u"Dialog")
+ Dialog.resize(451, 322)
+ self.gridLayout = QGridLayout(Dialog)
+ self.gridLayout.setObjectName(u"gridLayout")
+ self.loadFromFileButton = QPushButton(Dialog)
+ self.loadFromFileButton.setObjectName(u"loadFromFileButton")
+
+ self.gridLayout.addWidget(self.loadFromFileButton, 0, 0, 1, 1)
+
+ self.label = QLabel(Dialog)
+ self.label.setObjectName(u"label")
+ self.label.setAlignment(Qt.AlignCenter)
+ self.label.setWordWrap(True)
+
+ self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
+
+ self.loadFromSharedMemoryButton = QPushButton(Dialog)
+ self.loadFromSharedMemoryButton.setObjectName(u"loadFromSharedMemoryButton")
+
+ self.gridLayout.addWidget(self.loadFromSharedMemoryButton, 2, 0, 1, 1)
+
+
+ self.retranslateUi(Dialog)
+
+ QMetaObject.connectSlotsByName(Dialog)
+ # setupUi
+
+ def retranslateUi(self, Dialog):
+ Dialog.setWindowTitle(QCoreApplication.translate("Dialog", u"Dialog", None))
+ self.loadFromFileButton.setText(QCoreApplication.translate("Dialog", u"Load Image From File...", None))
+ self.label.setText(QCoreApplication.translate("Dialog", u"Launch two of these dialogs. In the first, press the top button and load an image from a file. In the second, press the bottom button and display the loaded image from shared memory.", None))
+ self.loadFromSharedMemoryButton.setText(QCoreApplication.translate("Dialog", u"Display Image From Shared Memory", None))
+ # retranslateUi
+
diff --git a/examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.png b/examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.png
new file mode 100644
index 000000000..3c4a476b3
--- /dev/null
+++ b/examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.png
Binary files differ
diff --git a/examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.rst b/examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.rst
new file mode 100644
index 000000000..e8e4d1ecd
--- /dev/null
+++ b/examples/corelib/mimetypesbrowser/doc/mimetypesbrowser.rst
@@ -0,0 +1,10 @@
+MIME Type Browser Example
+=========================
+
+A Python application that demonstrates the analogous example in C++
+`MIME Type Browser Example <https://doc.qt.io/qt-6/qtcore-mimetypes-mimetypebrowser-example.html>`_
+
+.. image:: mimetypesbrowser.png
+ :width: 400
+ :alt: mimetypebrowser screenshot
+
diff --git a/examples/corelib/mimetypesbrowser/mainwindow.py b/examples/corelib/mimetypesbrowser/mainwindow.py
new file mode 100644
index 000000000..76404eeb7
--- /dev/null
+++ b/examples/corelib/mimetypesbrowser/mainwindow.py
@@ -0,0 +1,161 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from mimetypemodel import MimeTypeModel
+from PySide6.QtCore import (QDir, QFileInfo, QMimeDatabase, QModelIndex, Qt,
+ Slot)
+from PySide6.QtGui import QAction, QKeySequence
+from PySide6.QtWidgets import (QAbstractItemView, QApplication, QDialog,
+ QFileDialog, QInputDialog, QMainWindow,
+ QMessageBox, QSplitter, QTextEdit, QTreeView,
+ QWidget)
+
+
+class MainWindow(QMainWindow):
+ def __init__(self, parent: QWidget = None) -> None:
+ super().__init__(parent=parent)
+ self.m_find_index: int = 0
+ self.m_model = MimeTypeModel(self)
+ self.m_tree_view = QTreeView(self)
+ self.m_details_text = QTextEdit(self)
+ self.m_find_matches = []
+
+ self.setWindowTitle("Qt Mime Database Browser")
+
+ # create actions
+ self.detect_file_action = QAction(
+ "&Detect File Type...", self, shortcut="Ctrl+O", triggered=self.detect_file
+ )
+ self.exit_action = QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close)
+ self.m_find_action = QAction("&Find...", self, shortcut="Ctrl+F", triggered=self.find)
+ self.m_find_next_action = QAction(
+ "Find &Next", self, shortcut="Ctrl+G", triggered=self.find_next
+ )
+ self.m_find_previous_action = QAction(
+ "Find &Previous",
+ self,
+ shortcut="Ctrl+Shift+G",
+ triggered=self.find_previous,
+ )
+ self.about_action = QAction(
+ "About Qt",
+ self,
+ shortcut=QKeySequence(QKeySequence.HelpContents),
+ triggered=QApplication.aboutQt,
+ )
+
+ # add action to menu
+ self.file_menu = self.menuBar().addMenu("&File")
+ self.file_menu.addAction(self.detect_file_action)
+ self.file_menu.addAction(self.exit_action)
+ self.find_menu = self.menuBar().addMenu("&Edit")
+ self.find_menu.addAction(self.m_find_action)
+ self.find_menu.addAction(self.m_find_next_action)
+ self.find_menu.addAction(self.m_find_previous_action)
+ self.about_menu = self.menuBar().addMenu("&About")
+ self.about_menu.addAction(self.about_action)
+
+ self.central_splitter = QSplitter(self)
+ self.setCentralWidget(self.central_splitter)
+
+ self.m_tree_view.setUniformRowHeights(True)
+ self.m_tree_view.setModel(self.m_model)
+
+ self.items = self.m_model.findItems(
+ "application/octet-stream",
+ Qt.MatchContains | Qt.MatchFixedString | Qt.MatchRecursive,
+ )
+
+ if self.items:
+ self.m_tree_view.expand(self.m_model.indexFromItem(self.items[0]))
+
+ self.m_tree_view.selectionModel().currentChanged.connect(self.current_changed)
+ self.central_splitter.addWidget(self.m_tree_view)
+ self.m_details_text.setReadOnly(True)
+ self.central_splitter.addWidget(self.m_details_text)
+
+ self.update_find_actions()
+
+ @Slot()
+ def detect_file(self):
+ file_name = QFileDialog.getOpenFileName(self, "Choose File")
+ if not file_name:
+ return
+
+ mime_database = QMimeDatabase()
+ fi = QFileInfo(file_name[0])
+ mime_type = mime_database.mimeTypeForFile(fi)
+ index = (
+ self.m_model.indexForMimeType(mime_type.name())
+ if mime_type.isValid()
+ else QModelIndex()
+ )
+
+ if index.isValid():
+ self.statusBar().showMessage(f'{fi.fileName()}" is of type "{mime_type.name()}"')
+ self._select_and_goto(index)
+ else:
+ QMessageBox.information(
+ self,
+ "Unknown File Type",
+ f"The type of {QDir.toNativeSeparators(file_name)} could not be determined.",
+ )
+
+ @Slot()
+ def find(self):
+ input_dialog = QInputDialog(self)
+ input_dialog.setWindowTitle("Find")
+ input_dialog.setLabelText("Text")
+ if input_dialog.exec() != QDialog.Accepted:
+ return
+
+ value = input_dialog.textValue().strip()
+ if not value:
+ return
+
+ self.m_find_matches.clear()
+ self.m_find_index = 0
+ items = self.m_model.findItems(
+ value, Qt.MatchContains | Qt.MatchFixedString | Qt.MatchRecursive
+ )
+
+ for item in items:
+ self.m_find_matches.append(self.m_model.indexFromItem(item))
+
+ self.statusBar().showMessage(f'{len(self.m_find_matches)} mime types match "{value}".')
+ self.update_find_actions()
+
+ if self.m_find_matches:
+ self._select_and_goto(self.m_find_matches[0])
+
+ @Slot()
+ def find_next(self):
+ self.m_find_index = self.m_find_index + 1
+ if self.m_find_index >= len(self.m_find_matches):
+ self.m_find_index = 0
+ if self.m_find_index < len(self.m_find_matches):
+ self._select_and_goto(self.m_find_matches[self.m_find_index])
+
+ @Slot()
+ def find_previous(self):
+ self.m_find_index = self.m_find_index - 1
+ if self.m_find_index < 0:
+ self.m_find_index = len(self.m_find_matches) - 1
+ if self.m_find_index >= 0:
+ self._select_and_goto(self.m_find_matches[self.m_find_index])
+
+ @Slot(QModelIndex)
+ def current_changed(self, index: QModelIndex):
+ if index.isValid():
+ self.m_details_text.setText(
+ MimeTypeModel.formatMimeTypeInfo(self.m_model.mimeType(index))
+ )
+
+ def update_find_actions(self):
+ self.find_next_previous_enabled = len(self.m_find_matches) > 1
+ self.m_find_next_action.setEnabled(self.find_next_previous_enabled)
+ self.m_find_previous_action.setEnabled(self.find_next_previous_enabled)
+
+ def _select_and_goto(self, index: QModelIndex):
+ self.m_tree_view.scrollTo(index, QAbstractItemView.PositionAtCenter)
+ self.m_tree_view.setCurrentIndex(index)
diff --git a/examples/corelib/mimetypesbrowser/mimetypemodel.py b/examples/corelib/mimetypesbrowser/mimetypemodel.py
new file mode 100644
index 000000000..5243f110e
--- /dev/null
+++ b/examples/corelib/mimetypesbrowser/mimetypemodel.py
@@ -0,0 +1,136 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+from typing import List
+
+from PySide6.QtCore import QMimeDatabase, QMimeType, QModelIndex, QObject, Qt, qWarning
+from PySide6.QtGui import QStandardItem, QStandardItemModel
+
+mimeTypeRole = Qt.UserRole + 1
+iconQueriedRole = Qt.UserRole + 2
+
+
+def createRow(t: QMimeType):
+ name_item = QStandardItem(t.name())
+ flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
+ name_item.setData(t, mimeTypeRole)
+ name_item.setData(False, iconQueriedRole)
+ name_item.setFlags(flags)
+ name_item.setToolTip(t.comment())
+ return [name_item]
+
+
+class MimeTypeModel(QStandardItemModel):
+ def __init__(self, parent: QObject = None):
+ super().__init__(0, 1, parent)
+ self.setHorizontalHeaderLabels(["Name"])
+ self.m_name_index_hash = {}
+ self.populate()
+
+ def populate(self):
+ mime_database = QMimeDatabase()
+ all_types: List[QMimeType] = mime_database.allMimeTypes()
+
+ # Move top level types to rear end of list, sort this partition,
+ # create top level items and truncate the list.
+ with_parent_mimetypes, without_parent_mimetypes = [], []
+
+ for mime_type in all_types:
+ if mime_type.parentMimeTypes():
+ with_parent_mimetypes.append(mime_type)
+ else:
+ without_parent_mimetypes.append(mime_type)
+
+ without_parent_mimetypes.sort(key=lambda x: x.name())
+
+ for top_level_type in without_parent_mimetypes:
+ row = createRow(top_level_type)
+ self.appendRow(row)
+ self.m_name_index_hash[top_level_type.name()] = self.indexFromItem(row[0])
+
+ all_types = with_parent_mimetypes
+
+ while all_types:
+ # Find a type inheriting one that is already in the model.
+ name_index_value: QModelIndex = None
+ name_index_key = ""
+ for mime_type in all_types:
+ name_index_value = self.m_name_index_hash.get(
+ mime_type.parentMimeTypes()[0]
+ )
+ if name_index_value:
+ name_index_key = mime_type.parentMimeTypes()[0]
+ break
+
+ if not name_index_value:
+ orphaned_mime_types = ", ".join(
+ [mime_type.name() for mime_type in all_types]
+ )
+ qWarning(f"Orphaned mime types: {orphaned_mime_types}")
+ break
+
+ # Move types inheriting the parent type to rear end of list, sort this partition,
+ # append the items to parent and truncate the list.
+ parent_name = name_index_key
+ with_parent_name, without_parent_name = [], []
+
+ for mime_type in all_types:
+ if parent_name in mime_type.parentMimeTypes():
+ with_parent_name.append(mime_type)
+ else:
+ without_parent_name.append(mime_type)
+
+ without_parent_name.sort(key=lambda x: x.name())
+ parent_item = self.itemFromIndex(name_index_value)
+
+ for mime_type in with_parent_name:
+ row = createRow(mime_type)
+ parent_item.appendRow(row)
+ self.m_name_index_hash[mime_type.name()] = self.indexFromItem(row[0])
+
+ all_types = without_parent_name
+
+ def mimeType(self, index: QModelIndex):
+ return index.data(mimeTypeRole)
+
+ def indexForMimeType(self, name):
+ return self.m_name_index_hash[name]
+
+ @staticmethod
+ def formatMimeTypeInfo(t: QMimeType):
+ out = f"<html><head/><body><h3><center>{t.name()}</center></h3><br><table>"
+ aliases_str = ", ".join(t.aliases())
+ if aliases_str:
+ out += f"<tr><td>Aliases:</td><td> ({aliases_str})"
+
+ out += (
+ f"</td></tr><tr><td>Comment:</td><td>{t.comment()}"
+ f"</td></tr><tr><td>Icon name:</td><td>{t.iconName()}</td></tr>"
+ f"<tr><td>Generic icon name</td><td>{t.genericIconName()}</td></tr>"
+ )
+
+ filter_str = t.filterString()
+ if filter_str:
+ out += f"<tr><td>Filter:</td><td>{filter_str}</td></tr>"
+
+ patterns_str = ", ".join(t.globPatterns())
+ if patterns_str:
+ out += f"<tr><td>Glob patterns:</td><td>{patterns_str}</td></tr>"
+
+ parentMimeTypes_str = ", ".join(t.parentMimeTypes())
+ if parentMimeTypes_str:
+ out += f"<tr><td>Parent types:</td><td>{parentMimeTypes_str}</td></tr>"
+
+ suffixes = t.suffixes()
+ if suffixes:
+ out += "<tr><td>Suffixes:</td><td>"
+ preferredSuffix = t.preferredSuffix()
+ if preferredSuffix:
+ suffixes.remove(preferredSuffix)
+ out += f"<b>{preferredSuffix}</b> "
+ suffixes_str = ", ".join(suffixes)
+ out += f"{suffixes_str}</td></tr>"
+
+ out += "</table></body></html>"
+
+ return out
diff --git a/examples/corelib/mimetypesbrowser/mimetypesbrowser.py b/examples/corelib/mimetypesbrowser/mimetypesbrowser.py
new file mode 100644
index 000000000..4742a31b8
--- /dev/null
+++ b/examples/corelib/mimetypesbrowser/mimetypesbrowser.py
@@ -0,0 +1,24 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the corelib/mimetypes/mimetypebrowser example from from Qt"""
+
+import argparse
+import sys
+
+from mainwindow import MainWindow
+from PySide6.QtWidgets import QApplication
+
+if __name__ == "__main__":
+ app = QApplication(sys.argv)
+
+ parser = argparse.ArgumentParser(description="MimeTypesBrowser Example")
+ parser.add_argument("-v", "--version", action="version", version="%(prog)s 1.0")
+ args = parser.parse_args()
+
+ mainWindow = MainWindow()
+ availableGeometry = mainWindow.screen().availableGeometry()
+ mainWindow.resize(availableGeometry.width() / 3, availableGeometry.height() / 2)
+ mainWindow.show()
+
+ sys.exit(app.exec())
diff --git a/examples/corelib/mimetypesbrowser/mimetypesbrowser.pyproject b/examples/corelib/mimetypesbrowser/mimetypesbrowser.pyproject
new file mode 100644
index 000000000..ada4252da
--- /dev/null
+++ b/examples/corelib/mimetypesbrowser/mimetypesbrowser.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["mimetypesbrowser.py"]
+}
diff --git a/examples/corelib/settingseditor/doc/settingseditor.png b/examples/corelib/settingseditor/doc/settingseditor.png
new file mode 100644
index 000000000..d281125d3
--- /dev/null
+++ b/examples/corelib/settingseditor/doc/settingseditor.png
Binary files differ
diff --git a/examples/corelib/settingseditor/doc/settingseditor.rst b/examples/corelib/settingseditor/doc/settingseditor.rst
new file mode 100644
index 000000000..4c60dbe8e
--- /dev/null
+++ b/examples/corelib/settingseditor/doc/settingseditor.rst
@@ -0,0 +1,10 @@
+Settings Editor Example
+=======================
+
+The Settings Editor example shows how Qt's standard settings support is used in
+an application by providing an editor that enables the user to view the
+settings for installed applications, and modify those that can be edited.
+
+.. image:: settingseditor.png
+ :width: 400
+ :alt: Settings Editor Screenshot
diff --git a/examples/corelib/tools/settingseditor/settingseditor.py b/examples/corelib/settingseditor/settingseditor.py
index 121d7cb0e..f87a2f4b5 100644
--- a/examples/corelib/tools/settingseditor/settingseditor.py
+++ b/examples/corelib/settingseditor/settingseditor.py
@@ -1,59 +1,26 @@
-# -*- coding: utf-8 -*-
-
-#############################################################################
-##
-## Copyright (C) 2013 Riverbank Computing Limited.
-## Copyright (C) 2020 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$
-##
-#############################################################################
-
-"""PySide2 port of the widgets/tools/settingseditor example from Qt v5.x"""
+# Copyright (C) 2013 Riverbank Computing Limited.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+"""PySide6 port of the widgets/tools/settingseditor example from Qt v5.x"""
import sys
-from PySide2.QtCore import (QByteArray, QDate, QDateTime, QDir, QEvent, QPoint,
- QRect, QRegularExpression, QSettings, QSize, QTime, QTimer, Qt)
-from PySide2.QtGui import (QAction, QColor, QIcon, QIntValidator,
- QDoubleValidator, QRegularExpressionValidator, QValidator)
-from PySide2.QtWidgets import (QAbstractItemView, QApplication,
- QCheckBox, QComboBox, QFileDialog, QDialog, QDialogButtonBox, QGridLayout,
- QGroupBox, QHeaderView, QInputDialog, QItemDelegate, QLabel, QLineEdit,
- QMainWindow, QMessageBox, QStyle, QSpinBox, QStyleOptionViewItem,
- QTableWidget, QTableWidgetItem, QTreeWidget, QTreeWidgetItem, QVBoxLayout)
+from PySide6.QtCore import (QByteArray, QDate, QDateTime, QDir, QEvent, QPoint,
+ QRect, QRegularExpression, QSettings, QSize, QTime,
+ QTimer, Qt, Slot)
+from PySide6.QtGui import (QAction, QColor, QIcon, QIntValidator,
+ QDoubleValidator, QRegularExpressionValidator,
+ QValidator)
+from PySide6.QtWidgets import (QAbstractItemView, QApplication,
+ QCheckBox, QComboBox, QFileDialog, QDialog,
+ QDialogButtonBox, QGridLayout,
+ QGroupBox, QHeaderView, QInputDialog,
+ QItemDelegate, QLabel, QLineEdit,
+ QMainWindow, QMessageBox, QStyle, QSpinBox,
+ QStyleOptionViewItem, QTableWidget,
+ QTableWidgetItem, QTreeWidget, QTreeWidgetItem,
+ QVBoxLayout)
class TypeChecker:
@@ -87,14 +54,14 @@ class TypeChecker:
self.size_exp = QRegularExpression(self.point_exp)
date_pattern = '([0-9]{,4})-([0-9]{,2})-([0-9]{,2})'
- self.date_exp = QRegularExpression('^{}$'.format(date_pattern))
+ self.date_exp = QRegularExpression(f'^{date_pattern}$')
assert self.date_exp.isValid()
time_pattern = '([0-9]{,2}):([0-9]{,2}):([0-9]{,2})'
- self.time_exp = QRegularExpression('^{}$'.format(time_pattern))
+ self.time_exp = QRegularExpression(f'^{time_pattern}$')
assert self.time_exp.isValid()
- pattern = '^{}T{}$'.format(date_pattern, time_pattern)
+ pattern = f'^{date_pattern}T{time_pattern}$'
self.dateTime_exp = QRegularExpression(pattern)
assert self.dateTime_exp.isValid()
@@ -167,7 +134,7 @@ class TypeChecker:
class MainWindow(QMainWindow):
def __init__(self, parent=None):
- super(MainWindow, self).__init__(parent)
+ super().__init__(parent)
self.settings_tree = SettingsTree()
self.setCentralWidget(self.settings_tree)
@@ -183,11 +150,12 @@ class MainWindow(QMainWindow):
self.setWindowTitle("Settings Editor")
self.resize(500, 600)
+ @Slot()
def open_settings(self):
if self.location_dialog is None:
self.location_dialog = LocationDialog(self)
- if self.location_dialog.exec_():
+ if self.location_dialog.exec():
settings = QSettings(self.location_dialog.format(),
self.location_dialog.scope(),
self.location_dialog.organization(),
@@ -195,9 +163,10 @@ class MainWindow(QMainWindow):
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(True)
+ @Slot()
def open_inifile(self):
file_name, _ = QFileDialog.getOpenFileName(self, "Open INI File",
- '', "INI Files (*.ini *.conf)")
+ '', "INI Files (*.ini *.conf)")
if file_name:
self.load_ini_file(file_name)
@@ -209,77 +178,71 @@ class MainWindow(QMainWindow):
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
+ @Slot()
def open_property_list(self):
file_name, _ = QFileDialog.getOpenFileName(self,
- "Open Property List", '', "Property List Files (*.plist)")
+ "Open Property List", '',
+ "Property List Files (*.plist)")
if file_name:
settings = QSettings(file_name, QSettings.NativeFormat)
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
+ @Slot()
def open_registry_path(self):
path, ok = QInputDialog.getText(self, "Open Registry Path",
- "Enter the path in the Windows registry:",
- QLineEdit.Normal, 'HKEY_CURRENT_USER\\')
+ "Enter the path in the Windows registry:",
+ QLineEdit.Normal, 'HKEY_CURRENT_USER\\')
if ok and path != '':
settings = QSettings(path, QSettings.NativeFormat)
self.set_settings_object(settings)
self.fallbacks_action.setEnabled(False)
+ @Slot()
def about(self):
QMessageBox.about(self, "About Settings Editor",
- "The <b>Settings Editor</b> example shows how to access "
- "application settings using Qt.")
-
- def createActions(self):
- self.openSettingsAct = QtGui.QAction("&Open Application Settings...",
- self, shortcut="Ctrl+O", triggered=self.openSettings)
-
- self.openIniFileAct = QtGui.QAction("Open I&NI File...", self,
- shortcut="Ctrl+N", triggered=self.openIniFile)
-
- self.openPropertyListAct = QtGui.QAction("Open macOS &Property List...",
- self, shortcut="Ctrl+P", triggered=self.openPropertyList)
+ "The <b>Settings Editor</b> example shows how to access "
+ "application settings using Qt.")
def create_actions(self):
self.open_settings_action = QAction("&Open Application Settings...",
- self, shortcut="Ctrl+O", triggered=self.open_settings)
+ self, shortcut="Ctrl+O", triggered=self.open_settings)
self.open_ini_file_action = QAction("Open I&NI File...", self,
- shortcut="Ctrl+N", triggered=self.open_inifile)
+ shortcut="Ctrl+N", triggered=self.open_inifile)
- self.open_property_list_action = QAction("Open macOS &Property List...",
- self, shortcut="Ctrl+P", triggered=self.open_property_list)
+ self.open_property_list_action = QAction("Open macOS &Property List...", self,
+ shortcut="Ctrl+P",
+ triggered=self.open_property_list)
if sys.platform != 'darwin':
self.open_property_list_action.setEnabled(False)
self.open_registry_path_action = QAction(
- "Open Windows &Registry Path...", self, shortcut="Ctrl+G",
- triggered=self.open_registry_path)
+ "Open Windows &Registry Path...", self, shortcut="Ctrl+G",
+ triggered=self.open_registry_path)
if sys.platform != 'win32':
self.open_registry_path_action.setEnabled(False)
self.refresh_action = QAction("&Refresh", self, shortcut="Ctrl+R",
- enabled=False, triggered=self.settings_tree.refresh)
+ enabled=False, triggered=self.settings_tree.refresh)
- self.exit_action = QAction("E&xit", self, shortcut="Ctrl+Q",
- triggered=self.close)
+ self.exit_action = QAction("E&xit", self, shortcut="Ctrl+Q", triggered=self.close)
self.auto_refresh_action = QAction("&Auto-Refresh", self,
- shortcut="Ctrl+A", checkable=True, enabled=False)
+ shortcut="Ctrl+A", checkable=True, enabled=False)
self.auto_refresh_action.triggered[bool].connect(self.settings_tree.set_auto_refresh)
self.auto_refresh_action.triggered[bool].connect(self.refresh_action.setDisabled)
self.fallbacks_action = QAction("&Fallbacks", self,
- shortcut="Ctrl+F", checkable=True, enabled=False)
+ shortcut="Ctrl+F", checkable=True, enabled=False)
self.fallbacks_action.triggered[bool].connect(self.settings_tree.set_fallbacks_enabled)
self.about_action = QAction("&About", self, triggered=self.about)
self.about_Qt_action = QAction("About &Qt", self,
- triggered=qApp.aboutQt)
+ triggered=qApp.aboutQt) # noqa: F821
def create_menus(self):
self.file_menu = self.menuBar().addMenu("&File")
@@ -315,12 +278,12 @@ class MainWindow(QMainWindow):
if not settings.isWritable():
nice_name += " (read only)"
- self.setWindowTitle("{} - Settings Editor".format(nice_name))
+ self.setWindowTitle(f"{nice_name} - Settings Editor")
class LocationDialog(QDialog):
def __init__(self, parent=None):
- super(LocationDialog, self).__init__(parent)
+ super().__init__(parent)
self.format_combo = QComboBox()
self.format_combo.addItem("Native")
@@ -378,17 +341,17 @@ class LocationDialog(QDialog):
locations_layout = QVBoxLayout(self.locations_groupbox)
locations_layout.addWidget(self.locations_table)
- mainLayout = QGridLayout(self)
- mainLayout.addWidget(format_label, 0, 0)
- mainLayout.addWidget(self.format_combo, 0, 1)
- mainLayout.addWidget(scope_label, 1, 0)
- mainLayout.addWidget(self.scope_cCombo, 1, 1)
- mainLayout.addWidget(organization_label, 2, 0)
- mainLayout.addWidget(self.organization_combo, 2, 1)
- mainLayout.addWidget(application_label, 3, 0)
- mainLayout.addWidget(self.application_combo, 3, 1)
- mainLayout.addWidget(self.locations_groupbox, 4, 0, 1, 2)
- mainLayout.addWidget(self.button_box, 5, 0, 1, 2)
+ main_layout = QGridLayout(self)
+ main_layout.addWidget(format_label, 0, 0)
+ main_layout.addWidget(self.format_combo, 0, 1)
+ main_layout.addWidget(scope_label, 1, 0)
+ main_layout.addWidget(self.scope_cCombo, 1, 1)
+ main_layout.addWidget(organization_label, 2, 0)
+ main_layout.addWidget(self.organization_combo, 2, 1)
+ main_layout.addWidget(application_label, 3, 0)
+ main_layout.addWidget(self.application_combo, 3, 1)
+ main_layout.addWidget(self.locations_groupbox, 4, 0, 1, 2)
+ main_layout.addWidget(self.button_box, 5, 0, 1, 2)
self.update_locations()
@@ -425,21 +388,21 @@ class LocationDialog(QDialog):
if self.scope() == QSettings.SystemScope:
continue
- actualScope = QSettings.UserScope
+ actual_scope = QSettings.UserScope
else:
- actualScope = QSettings.SystemScope
+ actual_scope = QSettings.SystemScope
for j in range(2):
if j == 0:
if not self.application():
continue
- actualApplication = self.application()
+ actual_application = self.application()
else:
- actualApplication = ''
+ actual_application = ''
- settings = QSettings(self.format(), actualScope,
- self.organization(), actualApplication)
+ settings = QSettings(self.format(), actual_scope,
+ self.organization(), actual_application)
row = self.locations_table.rowCount()
self.locations_table.setRowCount(row + 1)
@@ -472,7 +435,7 @@ class LocationDialog(QDialog):
class SettingsTree(QTreeWidget):
def __init__(self, parent=None):
- super(SettingsTree, self).__init__(parent)
+ super().__init__(parent)
self._type_checker = TypeChecker()
self.setItemDelegate(VariantDelegate(self._type_checker, self))
@@ -512,6 +475,7 @@ class SettingsTree(QTreeWidget):
def sizeHint(self):
return QSize(800, 600)
+ @Slot(bool)
def set_auto_refresh(self, autoRefresh):
self.auto_refresh = autoRefresh
@@ -522,15 +486,18 @@ class SettingsTree(QTreeWidget):
else:
self.refresh_timer.stop()
+ @Slot(bool)
def set_fallbacks_enabled(self, enabled):
if self.settings is not None:
self.settings.setFallbacksEnabled(enabled)
self.refresh()
+ @Slot()
def maybe_refresh(self):
if self.state() != QAbstractItemView.EditingState:
self.refresh()
+ @Slot()
def refresh(self):
if self.settings is None:
return
@@ -538,7 +505,7 @@ class SettingsTree(QTreeWidget):
# The signal might not be connected.
try:
self.itemChanged.disconnect(self.update_setting)
- except:
+ except Exception:
pass
self.settings.sync()
@@ -561,7 +528,6 @@ class SettingsTree(QTreeWidget):
key = ancestor.text(0) + '/' + key
ancestor = ancestor.parent()
- d = item.data(2, Qt.UserRole)
self.settings.setValue(key, item.data(2, Qt.UserRole))
if self.auto_refresh:
@@ -613,7 +579,7 @@ class SettingsTree(QTreeWidget):
if value_type:
value = self.settings.value(key, type=value_type)
child.setText(1, value.__class__.__name__)
- child.setText(2, VariantDelegate.displayText(value))
+ child.setText(2, VariantDelegate.display_text(value))
child.setData(2, Qt.UserRole, value)
while divider_index < self.child_count(parent):
@@ -666,7 +632,7 @@ class SettingsTree(QTreeWidget):
class VariantDelegate(QItemDelegate):
def __init__(self, type_checker, parent=None):
- super(VariantDelegate, self).__init__(parent)
+ super().__init__(parent)
self._type_checker = type_checker
def paint(self, painter, option, index):
@@ -711,7 +677,7 @@ class VariantDelegate(QItemDelegate):
elif isinstance(editor, QSpinBox):
editor.setValue(value)
else:
- editor.setText(self.displayText(value))
+ editor.setText(self.display_text(value))
def value_from_lineedit(self, lineedit, model, index):
if not lineedit.isModified():
@@ -733,9 +699,9 @@ class VariantDelegate(QItemDelegate):
value = editor.value()
else:
value = self.value_from_lineedit(editor, model, index)
- if not value is None:
+ if value is not None:
model.setData(index, value, Qt.UserRole)
- model.setData(index, self.displayText(value), Qt.DisplayRole)
+ model.setData(index, self.display_text(value), Qt.DisplayRole)
@staticmethod
def is_supported_type(value):
@@ -744,7 +710,7 @@ class VariantDelegate(QItemDelegate):
QSize, list))
@staticmethod
- def displayText(value):
+ def display_text(value):
if isinstance(value, str):
return value
if isinstance(value, bool):
@@ -752,23 +718,30 @@ class VariantDelegate(QItemDelegate):
if isinstance(value, (int, float, QByteArray)):
return str(value)
if isinstance(value, QColor):
- return '({},{},{},{})'.format(value.red(), value.green(),
- value.blue(), value.alpha())
+ (r, g, b, a) = (value.red(), value.green(), value.blue(), value.alpha())
+ return f'({r},{g},{b},{a})'
if isinstance(value, (QDate, QDateTime, QTime)):
return value.toString(Qt.ISODate)
if isinstance(value, QPoint):
- return '({},{})'.format(value.x(), value.y())
+ x = value.x()
+ y = value.y()
+ return f'({x},{y})'
if isinstance(value, QRect):
- return '({},{},{},{})'.format(value.x(), value.y(), value.width(),
- value.height())
+ x = value.x()
+ y = value.y()
+ w = value.width()
+ h = value.height()
+ return f'({x},{y},{w},{h})'
if isinstance(value, QSize):
- return '({},{})'.format(value.width(), value.height())
+ w = value.width()
+ h = value.height()
+ return f'({w},{h})'
if isinstance(value, list):
- return ','.join(value)
+ return ','.join(map(repr, value))
if value is None:
return '<Invalid>'
- return '<{}>'.format(value)
+ return f'<{value}>'
if __name__ == '__main__':
@@ -777,4 +750,4 @@ if __name__ == '__main__':
if len(sys.argv) > 1:
main_win.load_ini_file(sys.argv[1])
main_win.show()
- sys.exit(app.exec_())
+ sys.exit(app.exec())
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/threads/doc/threads.png b/examples/corelib/threads/doc/threads.png
new file mode 100644
index 000000000..d022f4aff
--- /dev/null
+++ b/examples/corelib/threads/doc/threads.png
Binary files differ
diff --git a/examples/corelib/threads/doc/threads.rst b/examples/corelib/threads/doc/threads.rst
new file mode 100644
index 000000000..d1bcf6fd4
--- /dev/null
+++ b/examples/corelib/threads/doc/threads.rst
@@ -0,0 +1,10 @@
+Mandelbrot Threads Example
+==========================
+
+The Mandelbrot example demonstrates multi-thread programming using Qt. It shows
+how to use a worker thread to perform heavy computations without blocking the
+main thread's event loop.
+
+.. image:: threads.png
+ :width: 400
+ :alt: Mandelbrot Threads Screenshot
diff --git a/examples/corelib/threads/mandelbrot.py b/examples/corelib/threads/mandelbrot.py
index c0ca70d68..4689813d4 100644
--- a/examples/corelib/threads/mandelbrot.py
+++ b/examples/corelib/threads/mandelbrot.py
@@ -1,83 +1,60 @@
+# Copyright (C) 2013 Riverbank Computing Limited.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-#############################################################################
-##
-## 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$
-##
-#############################################################################
-
-"""PySide2 port of the corelib/threads/mandelbrot example from Qt v5.x, originating from PyQt"""
-
-from PySide2.QtCore import (Signal, QMutex, QMutexLocker, QPoint, QSize, Qt,
- QThread, QWaitCondition)
-from PySide2.QtGui import QColor, QImage, QPainter, QPixmap, qRgb
-from PySide2.QtWidgets import QApplication, QWidget
-
-
-DefaultCenterX = -0.647011
-DefaultCenterY = -0.0395159
-DefaultScale = 0.00403897
-
-ZoomInFactor = 0.8
-ZoomOutFactor = 1 / ZoomInFactor
-ScrollStep = 20
+"""PySide6 port of the corelib/threads/mandelbrot example from Qt v5.x, originating from PyQt"""
+
+from argparse import ArgumentParser, RawTextHelpFormatter
+import sys
+
+from PySide6.QtCore import (Signal, QMutex, QElapsedTimer, QMutexLocker,
+ QPoint, QPointF, QSize, Qt, QThread,
+ QWaitCondition, Slot)
+from PySide6.QtGui import QColor, QImage, QPainter, QPixmap, qRgb
+from PySide6.QtWidgets import QApplication, QWidget
+
+
+DEFAULT_CENTER_X = -0.647011
+DEFAULT_CENTER_Y = -0.0395159
+DEFAULT_SCALE = 0.00403897
+
+ZOOM_IN_FACTOR = 0.8
+ZOOM_OUT_FACTOR = 1 / ZOOM_IN_FACTOR
+SCROLL_STEP = 20
+
+
+NUM_PASSES = 8
+
+
+INFO_KEY = 'info'
+
+
+HELP = ("Use mouse wheel or the '+' and '-' keys to zoom. Press and "
+ "hold left mouse button to scroll.")
class RenderThread(QThread):
- ColormapSize = 512
+ colormap_size = 512
- renderedImage = Signal(QImage, float)
+ rendered_image = Signal(QImage, float)
def __init__(self, parent=None):
- super(RenderThread, self).__init__(parent)
+ super().__init__(parent)
self.mutex = QMutex()
self.condition = QWaitCondition()
- self.centerX = 0.0
- self.centerY = 0.0
- self.scaleFactor = 0.0
- self.resultSize = QSize()
+ self._center_x = 0.0
+ self._center_y = 0.0
+ self._scale_factor = 0.0
+ self._result_size = QSize()
self.colormap = []
self.restart = False
self.abort = False
- for i in range(RenderThread.ColormapSize):
- self.colormap.append(self.rgbFromWaveLength(380.0 + (i * 400.0 / RenderThread.ColormapSize)))
+ for i in range(RenderThread.colormap_size):
+ self.colormap.append(
+ self.rgb_from_wave_length(380.0 + (i * 400.0 / RenderThread.colormap_size)))
def stop(self):
self.mutex.lock()
@@ -87,84 +64,94 @@ class RenderThread(QThread):
self.wait(2000)
- def render(self, centerX, centerY, scaleFactor, resultSize):
- locker = QMutexLocker(self.mutex)
-
- self.centerX = centerX
- self.centerY = centerY
- self.scaleFactor = scaleFactor
- self.resultSize = resultSize
+ def render(self, centerX, centerY, scale_factor, resultSize):
+ with QMutexLocker(self.mutex):
+ self._center_x = centerX
+ self._center_y = centerY
+ self._scale_factor = scale_factor
+ self._result_size = resultSize
- if not self.isRunning():
- self.start(QThread.LowPriority)
- else:
- self.restart = True
- self.condition.wakeOne()
+ if not self.isRunning():
+ self.start(QThread.LowPriority)
+ else:
+ self.restart = True
+ self.condition.wakeOne()
def run(self):
+ timer = QElapsedTimer()
+
while True:
self.mutex.lock()
- resultSize = self.resultSize
- scaleFactor = self.scaleFactor
- centerX = self.centerX
- centerY = self.centerY
+ resultSize = self._result_size
+ scale_factor = self._scale_factor
+ centerX = self._center_x
+ centerY = self._center_y
self.mutex.unlock()
- halfWidth = resultSize.width() // 2
- halfHeight = resultSize.height() // 2
+ half_width = resultSize.width() // 2
+ half_height = resultSize.height() // 2
image = QImage(resultSize, QImage.Format_RGB32)
- NumPasses = 8
curpass = 0
- while curpass < NumPasses:
- MaxIterations = (1 << (2 * curpass + 6)) + 32
- Limit = 4
- allBlack = True
+ while curpass < NUM_PASSES:
+ timer.restart()
+ max_iterations = (1 << (2 * curpass + 6)) + 32
+ LIMIT = 4
+ all_black = True
- for y in range(-halfHeight, halfHeight):
+ for y in range(-half_height, half_height):
if self.restart:
break
if self.abort:
return
- ay = 1j * (centerY + (y * scaleFactor))
+ ay = 1j * (centerY + (y * scale_factor))
- for x in range(-halfWidth, halfWidth):
- c0 = centerX + (x * scaleFactor) + ay
+ for x in range(-half_width, half_width):
+ c0 = centerX + (x * scale_factor) + ay
c = c0
- numIterations = 0
+ num_iterations = 0
- while numIterations < MaxIterations:
- numIterations += 1
- c = c*c + c0
- if abs(c) >= Limit:
+ while num_iterations < max_iterations:
+ num_iterations += 1
+ c = c * c + c0
+ if abs(c) >= LIMIT:
break
- numIterations += 1
- c = c*c + c0
- if abs(c) >= Limit:
+ num_iterations += 1
+ c = c * c + c0
+ if abs(c) >= LIMIT:
break
- numIterations += 1
- c = c*c + c0
- if abs(c) >= Limit:
+ num_iterations += 1
+ c = c * c + c0
+ if abs(c) >= LIMIT:
break
- numIterations += 1
- c = c*c + c0
- if abs(c) >= Limit:
+ num_iterations += 1
+ c = c * c + c0
+ if abs(c) >= LIMIT:
break
- if numIterations < MaxIterations:
- image.setPixel(x + halfWidth, y + halfHeight,
- self.colormap[numIterations % RenderThread.ColormapSize])
- allBlack = False
+ if num_iterations < max_iterations:
+ image.setPixel(x + half_width, y + half_height,
+ self.colormap[
+ num_iterations % RenderThread.colormap_size])
+ all_black = False
else:
- image.setPixel(x + halfWidth, y + halfHeight, qRgb(0, 0, 0))
+ image.setPixel(x + half_width, y + half_height, qRgb(0, 0, 0))
- if allBlack and curpass == 0:
+ if all_black and curpass == 0:
curpass = 4
else:
if not self.restart:
- self.renderedImage.emit(image, scaleFactor)
+ elapsed = timer.elapsed()
+ unit = 'ms'
+ if elapsed > 2000:
+ elapsed /= 1000
+ unit = 's'
+ text = (f"Pass {curpass + 1}/{NUM_PASSES}, "
+ f"max iterations: {max_iterations}, time: {elapsed}{unit}")
+ image.setText(INFO_KEY, text)
+ self.rendered_image.emit(image, scale_factor)
curpass += 1
self.mutex.lock()
@@ -173,7 +160,7 @@ class RenderThread(QThread):
self.restart = False
self.mutex.unlock()
- def rgbFromWaveLength(self, wave):
+ def rgb_from_wave_length(self, wave):
r = 0.0
g = 0.0
b = 0.0
@@ -206,143 +193,160 @@ class RenderThread(QThread):
g = pow(g * s, 0.8)
b = pow(b * s, 0.8)
- return qRgb(r*255, g*255, b*255)
+ return qRgb(r * 255, g * 255, b * 255)
class MandelbrotWidget(QWidget):
def __init__(self, parent=None):
- super(MandelbrotWidget, self).__init__(parent)
+ super().__init__(parent)
self.thread = RenderThread()
self.pixmap = QPixmap()
- self.pixmapOffset = QPoint()
- self.lastDragPos = QPoint()
+ self._pixmap_offset = QPointF()
+ self._last_drag_pos = QPointF()
- self.centerX = DefaultCenterX
- self.centerY = DefaultCenterY
- self.pixmapScale = DefaultScale
- self.curScale = DefaultScale
+ self._center_x = DEFAULT_CENTER_X
+ self._center_y = DEFAULT_CENTER_Y
+ self._pixmap_scale = DEFAULT_SCALE
+ self._cur_scale = DEFAULT_SCALE
- self.thread.renderedImage.connect(self.updatePixmap)
+ self.thread.rendered_image.connect(self.update_pixmap)
self.setWindowTitle("Mandelbrot")
self.setCursor(Qt.CrossCursor)
- self.resize(550, 400)
+ self._info = ''
def paintEvent(self, event):
- painter = QPainter(self)
- painter.fillRect(self.rect(), Qt.black)
-
- if self.pixmap.isNull():
+ with QPainter(self) as painter:
+ painter.fillRect(self.rect(), Qt.black)
+
+ if self.pixmap.isNull():
+ painter.setPen(Qt.white)
+ painter.drawText(self.rect(), Qt.AlignCenter,
+ "Rendering initial image, please wait...")
+ return
+
+ if self._cur_scale == self._pixmap_scale:
+ painter.drawPixmap(self._pixmap_offset, self.pixmap)
+ else:
+ scale_factor = self._pixmap_scale / self._cur_scale
+ new_width = int(self.pixmap.width() * scale_factor)
+ new_height = int(self.pixmap.height() * scale_factor)
+ new_x = self._pixmap_offset.x() + (self.pixmap.width() - new_width) / 2
+ new_y = self._pixmap_offset.y() + (self.pixmap.height() - new_height) / 2
+
+ painter.save()
+ painter.translate(new_x, new_y)
+ painter.scale(scale_factor, scale_factor)
+ exposed, _ = painter.transform().inverted()
+ exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
+ painter.drawPixmap(exposed, self.pixmap, exposed)
+ painter.restore()
+
+ text = HELP
+ if self._info:
+ text += ' ' + self._info
+ metrics = painter.fontMetrics()
+ text_width = metrics.horizontalAdvance(text)
+
+ painter.setPen(Qt.NoPen)
+ painter.setBrush(QColor(0, 0, 0, 127))
+ painter.drawRect((self.width() - text_width) / 2 - 5, 0, text_width + 10,
+ metrics.lineSpacing() + 5)
painter.setPen(Qt.white)
- painter.drawText(self.rect(), Qt.AlignCenter,
- "Rendering initial image, please wait...")
- return
-
- if self.curScale == self.pixmapScale:
- painter.drawPixmap(self.pixmapOffset, self.pixmap)
- else:
- scaleFactor = self.pixmapScale / self.curScale
- newWidth = int(self.pixmap.width() * scaleFactor)
- newHeight = int(self.pixmap.height() * scaleFactor)
- newX = self.pixmapOffset.x() + (self.pixmap.width() - newWidth) / 2
- newY = self.pixmapOffset.y() + (self.pixmap.height() - newHeight) / 2
-
- painter.save()
- painter.translate(newX, newY)
- painter.scale(scaleFactor, scaleFactor)
- exposed, _ = painter.transform().inverted()
- exposed = exposed.mapRect(self.rect()).adjusted(-1, -1, 1, 1)
- painter.drawPixmap(exposed, self.pixmap, exposed)
- painter.restore()
-
- text = "Use mouse wheel or the '+' and '-' keys to zoom. Press and " \
- "hold left mouse button to scroll."
- metrics = painter.fontMetrics()
- textWidth = metrics.horizontalAdvance(text)
-
- painter.setPen(Qt.NoPen)
- painter.setBrush(QColor(0, 0, 0, 127))
- painter.drawRect((self.width() - textWidth) / 2 - 5, 0, textWidth + 10,
- metrics.lineSpacing() + 5)
- painter.setPen(Qt.white)
- painter.drawText((self.width() - textWidth) / 2,
- metrics.leading() + metrics.ascent(), text)
+ painter.drawText((self.width() - text_width) / 2,
+ metrics.leading() + metrics.ascent(), text)
def resizeEvent(self, event):
- self.thread.render(self.centerX, self.centerY, self.curScale, self.size())
+ self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
def keyPressEvent(self, event):
if event.key() == Qt.Key_Plus:
- self.zoom(ZoomInFactor)
+ self.zoom(ZOOM_IN_FACTOR)
elif event.key() == Qt.Key_Minus:
- self.zoom(ZoomOutFactor)
+ self.zoom(ZOOM_OUT_FACTOR)
elif event.key() == Qt.Key_Left:
- self.scroll(-ScrollStep, 0)
+ self.scroll(-SCROLL_STEP, 0)
elif event.key() == Qt.Key_Right:
- self.scroll(+ScrollStep, 0)
+ self.scroll(+SCROLL_STEP, 0)
elif event.key() == Qt.Key_Down:
- self.scroll(0, -ScrollStep)
+ self.scroll(0, -SCROLL_STEP)
elif event.key() == Qt.Key_Up:
- self.scroll(0, +ScrollStep)
+ self.scroll(0, +SCROLL_STEP)
+ elif event.key() == Qt.Key_Q:
+ self.close()
else:
super(MandelbrotWidget, self).keyPressEvent(event)
def wheelEvent(self, event):
- numDegrees = event.angleDelta().y() / 8
- numSteps = numDegrees / 15.0
- self.zoom(pow(ZoomInFactor, numSteps))
+ num_degrees = event.angleDelta().y() / 8
+ num_steps = num_degrees / 15.0
+ self.zoom(pow(ZOOM_IN_FACTOR, num_steps))
def mousePressEvent(self, event):
if event.buttons() == Qt.LeftButton:
- self.lastDragPos = QPoint(event.pos())
+ self._last_drag_pos = event.position()
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
- self.pixmapOffset += event.pos() - self.lastDragPos
- self.lastDragPos = QPoint(event.pos())
+ pos = event.position()
+ self._pixmap_offset += pos - self._last_drag_pos
+ self._last_drag_pos = pos
self.update()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
- self.pixmapOffset += event.pos() - self.lastDragPos
- self.lastDragPos = QPoint()
+ pos = event.position()
+ self._pixmap_offset += pos - self._last_drag_pos
+ self._last_drag_pos = QPointF()
- deltaX = (self.width() - self.pixmap.width()) / 2 - self.pixmapOffset.x()
- deltaY = (self.height() - self.pixmap.height()) / 2 - self.pixmapOffset.y()
- self.scroll(deltaX, deltaY)
+ delta_x = (self.width() - self.pixmap.width()) / 2 - self._pixmap_offset.x()
+ delta_y = (self.height() - self.pixmap.height()) / 2 - self._pixmap_offset.y()
+ self.scroll(delta_x, delta_y)
- def updatePixmap(self, image, scaleFactor):
- if not self.lastDragPos.isNull():
+ @Slot(QImage, float)
+ def update_pixmap(self, image, scale_factor):
+ if not self._last_drag_pos.isNull():
return
+ self._info = image.text(INFO_KEY)
self.pixmap = QPixmap.fromImage(image)
- self.pixmapOffset = QPoint()
- self.lastDragPosition = QPoint()
- self.pixmapScale = scaleFactor
+ self._pixmap_offset = QPointF()
+ self._last_drag_position = QPointF()
+ self._pixmap_scale = scale_factor
self.update()
def zoom(self, zoomFactor):
- self.curScale *= zoomFactor
+ self._cur_scale *= zoomFactor
self.update()
- self.thread.render(self.centerX, self.centerY, self.curScale,
- self.size())
+ self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
def scroll(self, deltaX, deltaY):
- self.centerX += deltaX * self.curScale
- self.centerY += deltaY * self.curScale
+ self._center_x += deltaX * self._cur_scale
+ self._center_y += deltaY * self._cur_scale
self.update()
- self.thread.render(self.centerX, self.centerY, self.curScale,
- self.size())
+ self.thread.render(self._center_x, self._center_y, self._cur_scale, self.size())
if __name__ == '__main__':
-
- import sys
+ parser = ArgumentParser(description='Qt Mandelbrot Example',
+ formatter_class=RawTextHelpFormatter)
+ parser.add_argument('--passes', '-p', type=int, help='Number of passes (1-8)')
+ options = parser.parse_args()
+ if options.passes:
+ NUM_PASSES = int(options.passes)
+ if NUM_PASSES < 1 or NUM_PASSES > 8:
+ print(f'Invalid value: {options.passes}')
+ sys.exit(-1)
app = QApplication(sys.argv)
widget = MandelbrotWidget()
+ geometry = widget.screen().availableGeometry()
+ widget.resize((2 * geometry.size()) / 3)
+ pos = (geometry.size() - widget.size()) / 2
+ widget.move(geometry.topLeft() + QPoint(pos.width(), pos.height()))
+
widget.show()
- r = app.exec_()
+ r = app.exec()
widget.thread.stop()
sys.exit(r)
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/corelib/tools/regexp.py b/examples/corelib/tools/regexp.py
deleted file mode 100644
index 3a953329a..000000000
--- a/examples/corelib/tools/regexp.py
+++ /dev/null
@@ -1,194 +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$
-##
-#############################################################################
-
-"""PySide2 port of the widgets/tools/regexp example from Qt v5.x"""
-
-from PySide2 import QtCore, QtGui, QtWidgets
-
-
-class RegExpDialog(QtWidgets.QDialog):
- MaxCaptures = 6
-
- def __init__(self, parent=None):
- super(RegExpDialog, self).__init__(parent)
-
- self.patternComboBox = QtWidgets.QComboBox()
- self.patternComboBox.setEditable(True)
- self.patternComboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Preferred)
-
- patternLabel = QtWidgets.QLabel("&Pattern:")
- patternLabel.setBuddy(self.patternComboBox)
-
- self.escapedPatternLineEdit = QtWidgets.QLineEdit()
- self.escapedPatternLineEdit.setReadOnly(True)
- palette = self.escapedPatternLineEdit.palette()
- palette.setBrush(QtGui.QPalette.Base,
- palette.brush(QtGui.QPalette.Disabled, QtGui.QPalette.Base))
- self.escapedPatternLineEdit.setPalette(palette)
-
- escapedPatternLabel = QtWidgets.QLabel("&Escaped Pattern:")
- escapedPatternLabel.setBuddy(self.escapedPatternLineEdit)
-
- self.syntaxComboBox = QtWidgets.QComboBox()
- self.syntaxComboBox.addItem("Regular expression v1",
- QtCore.QRegExp.RegExp)
- self.syntaxComboBox.addItem("Regular expression v2",
- QtCore.QRegExp.RegExp2)
- self.syntaxComboBox.addItem("Wildcard", QtCore.QRegExp.Wildcard)
- self.syntaxComboBox.addItem("Fixed string",
- QtCore.QRegExp.FixedString)
-
- syntaxLabel = QtWidgets.QLabel("&Pattern Syntax:")
- syntaxLabel.setBuddy(self.syntaxComboBox)
-
- self.textComboBox = QtWidgets.QComboBox()
- self.textComboBox.setEditable(True)
- self.textComboBox.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
- QtWidgets.QSizePolicy.Preferred)
-
- textLabel = QtWidgets.QLabel("&Text:")
- textLabel.setBuddy(self.textComboBox)
-
- self.caseSensitiveCheckBox = QtWidgets.QCheckBox("Case &Sensitive")
- self.caseSensitiveCheckBox.setChecked(True)
- self.minimalCheckBox = QtWidgets.QCheckBox("&Minimal")
-
- indexLabel = QtWidgets.QLabel("Index of Match:")
- self.indexEdit = QtWidgets.QLineEdit()
- self.indexEdit.setReadOnly(True)
-
- matchedLengthLabel = QtWidgets.QLabel("Matched Length:")
- self.matchedLengthEdit = QtWidgets.QLineEdit()
- self.matchedLengthEdit.setReadOnly(True)
-
- self.captureLabels = []
- self.captureEdits = []
- for i in range(self.MaxCaptures):
- self.captureLabels.append(QtWidgets.QLabel("Capture %d:" % i))
- self.captureEdits.append(QtWidgets.QLineEdit())
- self.captureEdits[i].setReadOnly(True)
- self.captureLabels[0].setText("Match:")
-
- checkBoxLayout = QtWidgets.QHBoxLayout()
- checkBoxLayout.addWidget(self.caseSensitiveCheckBox)
- checkBoxLayout.addWidget(self.minimalCheckBox)
- checkBoxLayout.addStretch(1)
-
- mainLayout = QtWidgets.QGridLayout()
- mainLayout.addWidget(patternLabel, 0, 0)
- mainLayout.addWidget(self.patternComboBox, 0, 1)
- mainLayout.addWidget(escapedPatternLabel, 1, 0)
- mainLayout.addWidget(self.escapedPatternLineEdit, 1, 1)
- mainLayout.addWidget(syntaxLabel, 2, 0)
- mainLayout.addWidget(self.syntaxComboBox, 2, 1)
- mainLayout.addLayout(checkBoxLayout, 3, 0, 1, 2)
- mainLayout.addWidget(textLabel, 4, 0)
- mainLayout.addWidget(self.textComboBox, 4, 1)
- mainLayout.addWidget(indexLabel, 5, 0)
- mainLayout.addWidget(self.indexEdit, 5, 1)
- mainLayout.addWidget(matchedLengthLabel, 6, 0)
- mainLayout.addWidget(self.matchedLengthEdit, 6, 1)
-
- for i in range(self.MaxCaptures):
- mainLayout.addWidget(self.captureLabels[i], 7 + i, 0)
- mainLayout.addWidget(self.captureEdits[i], 7 + i, 1)
- self.setLayout(mainLayout)
-
- self.patternComboBox.editTextChanged.connect(self.refresh)
- self.textComboBox.editTextChanged.connect(self.refresh)
- self.caseSensitiveCheckBox.toggled.connect(self.refresh)
- self.minimalCheckBox.toggled.connect(self.refresh)
- self.syntaxComboBox.currentIndexChanged.connect(self.refresh)
-
- self.patternComboBox.addItem("[A-Za-z_]+([A-Za-z_0-9]*)")
- self.textComboBox.addItem("(10 + delta4)* 32")
-
- self.setWindowTitle("RegExp")
- self.setFixedHeight(self.sizeHint().height())
- self.refresh()
-
- def refresh(self):
- self.setUpdatesEnabled(False)
-
- pattern = self.patternComboBox.currentText()
- text = self.textComboBox.currentText()
-
- escaped = str(pattern)
- escaped.replace('\\', '\\\\')
- escaped.replace('"', '\\"')
- self.escapedPatternLineEdit.setText('"' + escaped + '"')
-
- rx = QtCore.QRegExp(pattern)
- cs = QtCore.Qt.CaseInsensitive
- if self.caseSensitiveCheckBox.isChecked():
- cs = QtCore.Qt.CaseSensitive
- rx.setCaseSensitivity(cs)
- rx.setMinimal(self.minimalCheckBox.isChecked())
- syntax = self.syntaxComboBox.itemData(self.syntaxComboBox.currentIndex())
- rx.setPatternSyntax(QtCore.QRegExp.PatternSyntax(syntax))
-
- palette = self.patternComboBox.palette()
- if rx.isValid():
- palette.setColor(QtGui.QPalette.Text,
- self.textComboBox.palette().color(QtGui.QPalette.Text))
- else:
- palette.setColor(QtGui.QPalette.Text, QtCore.Qt.red)
- self.patternComboBox.setPalette(palette)
-
- self.indexEdit.setText(str(rx.indexIn(text)))
- self.matchedLengthEdit.setText(str(rx.matchedLength()))
-
- for i in range(self.MaxCaptures):
- self.captureLabels[i].setEnabled(i <= rx.captureCount())
- self.captureEdits[i].setEnabled(i <= rx.captureCount())
- self.captureEdits[i].setText(rx.cap(i))
-
- self.setUpdatesEnabled(True)
-
-if __name__ == '__main__':
-
- import sys
-
- app = QtWidgets.QApplication(sys.argv)
- dialog = RegExpDialog()
- sys.exit(dialog.exec_())
diff --git a/examples/corelib/tools/tools.pyproject b/examples/corelib/tools/tools.pyproject
deleted file mode 100644
index 63f9c6198..000000000
--- a/examples/corelib/tools/tools.pyproject
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "files": ["regexp.py"]
-}