Source: qr-tools Version: 2.1-2 Severity: minor Tags: upstream patch Attached is a patch to port qr-tools from PyQt5 to PyQt6.
I noticed upstream is not active anymore, so I don't think there is anywhere to forward it. In the absence of an active upstream, I think it'd be meaningful to carry it to the Debian package. Thank you for maintaining qr-tools! I've found it to be quite useful. It's one of the last Qt5 tools on my system, and I started getting worried about its inclusion in Debian, hence this patch :) HTH! Regards, Faidon
diff --git a/debian/control b/debian/control index eaf78ec..55f335e 100644 --- a/debian/control +++ b/debian/control @@ -7,7 +7,7 @@ Build-Depends: dh-python, python3, python3-setuptools, - qttools5-dev-tools, + qt6-tools-dev, Standards-Version: 4.7.3 Rules-Requires-Root: no Homepage: https://launchpad.net/qr-tools @@ -20,7 +20,7 @@ Depends: python3-pil, python3-zbar, qrencode, - libqt5multimedia5-plugins, + libqt6multimedia6, ${misc:Depends}, ${python3:Depends} Description: high level library for reading and generating QR codes @@ -33,8 +33,8 @@ Architecture: all Section: utils Depends: python3-qrtools, - python3-pyqt5, - python3-pyqt5.qtmultimedia, + python3-pyqt6, + python3-pyqt6.qtmultimedia, ${misc:Depends}, ${python3:Depends} Description: Qt frontend for QR code generator and decoder diff --git a/debian/patches/Port-from-PyQt5-to-PyQt6.patch b/debian/patches/Port-from-PyQt5-to-PyQt6.patch new file mode 100644 index 0000000..e73f3b5 --- /dev/null +++ b/debian/patches/Port-from-PyQt5-to-PyQt6.patch @@ -0,0 +1,231 @@ +From: Faidon Liambotis <[email protected]> +Date: Mon, 2 Mar 2026 11:14:01 +0200 +Subject: Port from PyQt5 to PyQt6 + +--- + qtqr.py | 86 ++++++++++++++++++++++++++++++++++++----------------------------- + 1 file changed, 48 insertions(+), 38 deletions(-) + +diff --git a/qtqr.py b/qtqr.py +index 84f9c7c..0f8276e 100644 +--- a/qtqr.py ++++ b/qtqr.py +@@ -11,11 +11,10 @@ uses python-zbar for decoding from files and webcam + + import sys, os + from math import ceil +-from PyQt5 import QtCore, QtGui, QtNetwork, QtWidgets ++from PyQt6 import QtCore, QtGui, QtNetwork, QtWidgets + from qrtools import QR + from PIL import Image +-from PyQt5.QtMultimedia import QCameraInfo +-from PyQt5.QtWidgets import QDialog ++from PyQt6.QtMultimedia import QMediaDevices + + __author__ = "Ramiro Algozino" + __email__ = "[email protected]" +@@ -233,7 +232,7 @@ class MainWindow(QtWidgets.QMainWindow): + + #QLabel for displaying the Generated QRCode + self.qrcode = QtWidgets.QLabel(self.tr('Start typing to create QR Code\n or drop here image files for decoding.')) +- self.qrcode.setAlignment(QtCore.Qt.AlignVCenter | QtCore.Qt.AlignHCenter) ++ self.qrcode.setAlignment(QtCore.Qt.AlignmentFlag.AlignVCenter | QtCore.Qt.AlignmentFlag.AlignHCenter) + self.scroll = QtWidgets.QScrollArea() + self.scroll.setWidgetResizable(True) + self.scroll.setWidget(self.qrcode) +@@ -245,9 +244,9 @@ class MainWindow(QtWidgets.QMainWindow): + self.decodeFileButton = QtWidgets.QPushButton(QtGui.QIcon.fromTheme(u'document-open'), self.tr('Decode from &File')) + self.decodeWebcamButton = QtWidgets.QPushButton(QtGui.QIcon.fromTheme(u'camera-web'), self.tr('Decode from &Webcam')) + +- self.exitAction = QtWidgets.QAction(QtGui.QIcon.fromTheme(u'application-exit'), self.tr('E&xit'), self) ++ self.exitAction = QtGui.QAction(QtGui.QIcon.fromTheme(u'application-exit'), self.tr('E&xit'), self) + self.addAction(self.exitAction) +- self.aboutAction = QtWidgets.QAction(QtGui.QIcon.fromTheme(u"help-about"), self.tr("&About"), self) ++ self.aboutAction = QtGui.QAction(QtGui.QIcon.fromTheme(u"help-about"), self.tr("&About"), self) + self.addAction(self.aboutAction) + + # UI Tunning +@@ -689,7 +688,7 @@ class MainWindow(QtWidgets.QMainWindow): + u"Decode from file", + u"The file <b>%s</b> doesn't exist." % + os.path.abspath(fn), +- QtWidgets.QMessageBox.Ok ++ QtWidgets.QMessageBox.StandardButton.Ok + ) + + def decodeFromMemory(self, image): +@@ -778,29 +777,29 @@ class MainWindow(QtWidgets.QMainWindow): + } + if action[qr.data_type] != u"": + msgBox = QtWidgets.QMessageBox( +- QtWidgets.QMessageBox.Question, ++ QtWidgets.QMessageBox.Icon.Question, + self.tr('Decode QRCode'), + msg[qr.data_type]() + action[qr.data_type], +- QtWidgets.QMessageBox.No | +- QtWidgets.QMessageBox.Yes, ++ QtWidgets.QMessageBox.StandardButton.No | ++ QtWidgets.QMessageBox.StandardButton.Yes, + self + ) +- msgBox.addButton(self.tr("&Edit"), QtWidgets.QMessageBox.ApplyRole) +- msgBox.setDefaultButton(QtWidgets.QMessageBox.Yes) +- rsp = msgBox.exec_() ++ msgBox.addButton(self.tr("&Edit"), QtWidgets.QMessageBox.ButtonRole.ApplyRole) ++ msgBox.setDefaultButton(QtWidgets.QMessageBox.StandardButton.Yes) ++ rsp = msgBox.exec() + else: + msgBox = QtWidgets.QMessageBox( +- QtWidgets.QMessageBox.Information, ++ QtWidgets.QMessageBox.Icon.Information, + self.tr("Decode QRCode"), + msg[qr.data_type]() + action[qr.data_type], +- QtWidgets.QMessageBox.Ok, ++ QtWidgets.QMessageBox.StandardButton.Ok, + self + ) +- msgBox.addButton(self.tr("&Edit"), QtWidgets.QMessageBox.ApplyRole) +- msgBox.setDefaultButton(QtWidgets.QMessageBox.Ok) +- rsp = msgBox.exec_() ++ msgBox.addButton(self.tr("&Edit"), QtWidgets.QMessageBox.ButtonRole.ApplyRole) ++ msgBox.setDefaultButton(QtWidgets.QMessageBox.StandardButton.Ok) ++ rsp = msgBox.exec() + +- if rsp == QtWidgets.QMessageBox.Yes: ++ if rsp == QtWidgets.QMessageBox.StandardButton.Yes: + #Open Link + if qr.data_type == 'email': + link = 'mailto:'+ data +@@ -814,7 +813,7 @@ class MainWindow(QtWidgets.QMainWindow): + link = qr.data_decode[qr.data_type](qr.data) + print (u"Opening " + link) + QtGui.QDesktopServices.openUrl(QtCore.QUrl(link)) +- elif rsp == 0: ++ elif rsp == 0 or rsp == QtWidgets.QMessageBox.StandardButton.NoButton: + #Edit the code + data = qr.data_decode[qr.data_type](qr.data) + try: +@@ -871,7 +870,7 @@ class MainWindow(QtWidgets.QMainWindow): + self.wifiSSIDEdit.setText(data[0] or "") + self.wifiEncryptionType.setCurrentIndex({u"WEP":0,u"WPA":1,u"nopass":2}.get(data[1]) or 0) + self.wifiPasswordEdit.setText(data[2] or "") +- self.wifiHiddenNetwork.setCheckState(True if data[3] == "true" else False) ++ self.wifiHiddenNetwork.setChecked(True if data[3] == "true" else False) + self.tabs.setCurrentIndex(tabIndex) + elif qr.data_type == 'sepa': + self.sepaNameEdit.setText(data.get('name')[0]) +@@ -892,10 +891,18 @@ class MainWindow(QtWidgets.QMainWindow): + vdDialog = VideoDevices() + device_desc = vdDialog.videoDevice.currentText() + if vdDialog.videoDevice.count() != 1: +- d_res = vdDialog.exec_() +- device_desc = {QDialog.Rejected: '', QDialog.Accepted: vdDialog.videoDevice.currentText()}[d_res] +- device = {device.description(): device.deviceName() +- for device in QCameraInfo.availableCameras()}.get(device_desc, None) ++ d_res = vdDialog.exec() ++ device_desc = { ++ QtWidgets.QDialog.DialogCode.Rejected: '', ++ QtWidgets.QDialog.DialogCode.Accepted: vdDialog.videoDevice.currentText(), ++ }[d_res] ++ device = {device.description(): device.id() ++ for device in QMediaDevices.videoInputs()}.get(device_desc, None) ++ if device and not isinstance(device, str): ++ try: ++ device = bytes(device).decode('utf-8', errors='ignore') ++ except Exception: ++ device = str(device) + + if device: + qr = QR() +@@ -906,7 +913,7 @@ class MainWindow(QtWidgets.QMainWindow): + self, + self.tr("Webcam not availabled"), + self.tr("<p>Oops! failed to connect to the webcam.<br /> Maybe your webcam is already busy in another application?</p>"), +- QtWidgets.QMessageBox.Ok ++ QtWidgets.QMessageBox.StandardButton.Ok + ) + return + try: +@@ -916,7 +923,7 @@ class MainWindow(QtWidgets.QMainWindow): + self, + self.tr("Decoding Failed"), + self.tr(f"<p>oops! Your code seems to be of type '{qr.data_type}', but no decoding for data '{qr.data}' could be found.</p>"), +- QtWidgets.QMessageBox.Ok ++ QtWidgets.QMessageBox.StandardButton.Ok + ) + else: + if matchData == 'NULL': +@@ -924,7 +931,7 @@ class MainWindow(QtWidgets.QMainWindow): + self, + self.tr("Decoding Failed"), + self.tr("<p>Oops! no code was found.<br /> Maybe your webcam didn't focus.</p>"), +- QtWidgets.QMessageBox.Ok ++ QtWidgets.QMessageBox.StandardButton.Ok + ) + else: + self.showInfo(qr) +@@ -966,9 +973,9 @@ class MainWindow(QtWidgets.QMainWindow): + + def toggleShowPassword(self, status): + if status == 0: +- self.wifiPasswordEdit.setEchoMode(QtWidgets.QLineEdit.Password) ++ self.wifiPasswordEdit.setEchoMode(QtWidgets.QLineEdit.EchoMode.Password) + elif status == 2: +- self.wifiPasswordEdit.setEchoMode(QtWidgets.QLineEdit.Normal) ++ self.wifiPasswordEdit.setEchoMode(QtWidgets.QLineEdit.EchoMode.Normal) + + + class VideoDevices(QtWidgets.QDialog): +@@ -982,13 +989,16 @@ class VideoDevices(QtWidgets.QDialog): + self.videoDevice = QtWidgets.QComboBox() + self.label = QtWidgets.QLabel(self.tr("You are about to decode from your webcam. Please put the code in front of your camera with a good light source and keep it steady.\nQtQR will try to detect automatically the QR Code.\n\nPlease select the video device you want to use for decoding:")) + self.label.setWordWrap(True) +- self.Buttons = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel) ++ self.Buttons = QtWidgets.QDialogButtonBox( ++ QtWidgets.QDialogButtonBox.StandardButton.Ok | ++ QtWidgets.QDialogButtonBox.StandardButton.Cancel ++ ) + self.Buttons.accepted.connect(self.accept) + self.Buttons.rejected.connect(self.reject) + self.layout = QtWidgets.QVBoxLayout() + self.hlayout = QtWidgets.QHBoxLayout() + self.vlayout = QtWidgets.QVBoxLayout() +- self.hlayout.addWidget(self.icon, 0, QtCore.Qt.AlignTop) ++ self.hlayout.addWidget(self.icon, 0, QtCore.Qt.AlignmentFlag.AlignTop) + self.vlayout.addWidget(self.label) + self.vlayout.addWidget(self.videoDevice) + self.hlayout.addLayout(self.vlayout) +@@ -996,7 +1006,7 @@ class VideoDevices(QtWidgets.QDialog): + self.layout.addStretch() + self.layout.addWidget(self.Buttons) + self.setLayout(self.layout) +- self.videoDevice.addItems([info.description() for info in QCameraInfo.availableCameras()]) ++ self.videoDevice.addItems([info.description() for info in QMediaDevices.videoInputs()]) + + + if __name__ == '__main__': +@@ -1010,14 +1020,14 @@ if __name__ == '__main__': + # "qtqr_" + locale)) + # We load from standard location the translations + translator.load("qtqr_" + locale, +- QtCore.QLibraryInfo.location( +- QtCore.QLibraryInfo.TranslationsPath) ++ QtCore.QLibraryInfo.path( ++ QtCore.QLibraryInfo.LibraryPath.TranslationsPath) + ) + app.installTranslator(translator) + qtTranslator=QtCore.QTranslator() + qtTranslator.load("qt_" + locale, +- QtCore.QLibraryInfo.location( +- QtCore.QLibraryInfo.TranslationsPath) ++ QtCore.QLibraryInfo.path( ++ QtCore.QLibraryInfo.LibraryPath.TranslationsPath) + ) + app.installTranslator(qtTranslator) + +@@ -1031,4 +1041,4 @@ if __name__ == '__main__': + for fn in sys.argv[1:]: + # We should check if the file exists. + mw.decodeFile(fn) +- sys.exit(app.exec_()) ++ sys.exit(app.exec()) diff --git a/debian/patches/series b/debian/patches/series index 818836e..3f6fa6d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1 +1,2 @@ fix-961503.patch +Port-from-PyQt5-to-PyQt6.patch diff --git a/debian/qtqr.install b/debian/qtqr.install index 40e08da..8193878 100644 --- a/debian/qtqr.install +++ b/debian/qtqr.install @@ -1,2 +1,2 @@ -*.qm usr/share/qt5/translations +*.qm usr/share/qt6/translations debian/qtqr.desktop usr/share/applications diff --git a/debian/rules b/debian/rules index e760782..c62aa9a 100755 --- a/debian/rules +++ b/debian/rules @@ -1,7 +1,5 @@ #!/usr/bin/make -f -export QT_SELECT := 5 - %: dh $@ --buildsystem=pybuild --with python3 @@ -9,7 +7,7 @@ ts = $(wildcard qtqr_*.ts) qm = $(ts:ts=qm) execute_after_dh_auto_build: $(qm) $(qm): %.qm: %.ts - lrelease -nounfinished $< -qm $@ + /usr/lib/qt6/bin/lrelease -nounfinished $< -qm $@ execute_after_dh_auto_install: install -m 644 qtqr.py debian/qtqr/usr/bin/qtqr

