Your message dated Mon, 02 Mar 2026 14:35:45 +0000
with message-id <[email protected]>
and subject line Bug#1129518: fixed in qr-tools 2.1-3
has caused the Debian Bug report #1129518,
regarding Patch to port to PyQt6
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact [email protected]
immediately.)


-- 
1129518: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1129518
Debian Bug Tracking System
Contact [email protected] with problems
--- Begin Message ---
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

--- End Message ---
--- Begin Message ---
Source: qr-tools
Source-Version: 2.1-3
Done: Georges Khaznadar <[email protected]>

We believe that the bug you reported is fixed in the latest version of
qr-tools, which is due to be installed in the Debian FTP archive.

A summary of the changes between this version and the previous one is
attached.

Thank you for reporting the bug, which will now be closed.  If you
have further comments please address them to [email protected],
and the maintainer will reopen the bug report if appropriate.

Debian distribution maintenance software
pp.
Georges Khaznadar <[email protected]> (supplier of updated qr-tools package)

(This message was generated automatically at their request; if you
believe that there is a problem with it please contact the archive
administrators by mailing [email protected])


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Mon, 02 Mar 2026 15:13:22 +0100
Source: qr-tools
Architecture: source
Version: 2.1-3
Distribution: unstable
Urgency: medium
Maintainer: Georges Khaznadar <[email protected]>
Changed-By: Georges Khaznadar <[email protected]>
Closes: 1129518
Changes:
 qr-tools (2.1-3) unstable; urgency=medium
 .
   * applied Faidon Liambotis' patch, thanks!. Closes: #1129518
     (Patch to port to PyQt6)
Checksums-Sha1:
 e0d6118e7f811c24c2db664d966856dbaac30303 1949 qr-tools_2.1-3.dsc
 8af23a948c7c9bdfd75510d7546dc10ea55fdd38 13216 qr-tools_2.1-3.debian.tar.xz
 826a025ded316a1ccace9c26959e8732054cb39a 11037 qr-tools_2.1-3_source.buildinfo
Checksums-Sha256:
 c5708f3ed85b731246e393f29cf076a1822f7d82b9e42ceab3a5ce1334afaaf9 1949 
qr-tools_2.1-3.dsc
 948a2b580c7092fbd37da66eda2e903ebf04da063a24fb1e0e41ad974dfa6ecb 13216 
qr-tools_2.1-3.debian.tar.xz
 101bf5bad4e19aced8a97d704b868069a45c23641b42809e17c76e500f38f0a7 11037 
qr-tools_2.1-3_source.buildinfo
Files:
 6b3132143f0a717e69fc31be0b991821 1949 python optional qr-tools_2.1-3.dsc
 4ccdf6d10f926b8ce8c4ef68dffb1352 13216 python optional 
qr-tools_2.1-3.debian.tar.xz
 74db37dbc098df0cc0da7d1ba6d66069 11037 python optional 
qr-tools_2.1-3_source.buildinfo

-----BEGIN PGP SIGNATURE-----

iQJIBAEBCgAyFiEEM0CzZP9nFT+3zK6FHCgWkHE2rjkFAmmlm+MUHGdlb3JnZXNr
QGRlYmlhbi5vcmcACgkQHCgWkHE2rjki2xAAjFLIGb9N7GRvZb1ArPISdqkRWtIK
rtmglUAc79HpPSloNAlpC32fOnW8yoGpkeukLlXUjk5pOljAemrPcYiZTPpPCDMF
vsa/bfm9iBSmkRQIW3EpaTcYHGt8PkBtitqACRA39DSjLne03p8+AYO/41ryKI+9
fULTJB+BJ56MHt8ommwfWK/kMpIV9lb6KS+Mswb7wOJJWUGJv3SUiWM7py92Qiut
oN7iWPMkzwQBduYB57p63WQO4DpFaZggeXGz4NJihrj6VXEYinrTBLlt+p4BPeYi
4rCkWngZOjaHyrZlPEiFhfDeR1xM8I62z2up93cWpGU/bsUtqgW1hMIJBvVA4DK6
sIBBuIYMEBFzvYKPsWDI7Vs1iNW10ZUUaPQp5DTrXgDxgUeBcR94eC6YI2uWTDm5
B555ePS0NC81N6Ay3pGZs2D5GamBksVn/U9MStw3RiOAha/ubUIiWGZsyxgYP7DG
6sOOoesSX0Cnp8h3ozq5w9StFPMommysuvC5Gcxeh2ca1jWYRm87CpZJYYGemcuz
6NxtmQIM4E1sF0zZjVfXy6ovFb6XnH49M32g6/1pOsIBz1gdLAVqus9yWCGT7M9d
c4DjCgSvQ0aaUytIF3GiewLFddoqId8GLEst6wSg2/DHkOZyUzfL5SskA8QsqhNf
4rwB243nG1q1GHU=
=O3T9
-----END PGP SIGNATURE-----

Attachment: pgp6rVxTbpZi_.pgp
Description: PGP signature


--- End Message ---

Reply via email to