diff --git a/puddlestuff/about.py b/puddlestuff/about.py
index ba3c6dc..bcb5bca 100755
--- a/puddlestuff/about.py
+++ b/puddlestuff/about.py
@@ -2,9 +2,9 @@
 import mutagen
 from importlib import import_module
 from platform import python_version
-from PyQt5.QtCore import PYQT_VERSION_STR, QT_VERSION_STR, Qt
-from PyQt5.QtGui import QPixmap
-from PyQt5.QtWidgets import QApplication, QDialog, QHBoxLayout, QLabel, QScrollArea, QTabWidget, QVBoxLayout, QWidget
+from PyQt6.QtCore import PYQT_VERSION_STR, QT_VERSION_STR, Qt
+from PyQt6.QtGui import QPixmap
+from PyQt6.QtWidgets import QApplication, QDialog, QHBoxLayout, QLabel, QScrollArea, QTabWidget, QVBoxLayout, QWidget
 
 from . import version_string, changeset
 from .puddleobjects import OKCancel
@@ -130,4 +130,4 @@ if __name__ == '__main__':
     app = QApplication([])
     win = AboutPuddletag()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/action_shortcuts.py b/puddlestuff/action_shortcuts.py
index b3b5818..a86d033 100644
--- a/puddlestuff/action_shortcuts.py
+++ b/puddlestuff/action_shortcuts.py
@@ -2,8 +2,9 @@
 import os
 from functools import partial
 
-from PyQt5.QtCore import QFileSystemWatcher, QItemSelectionModel, pyqtSignal
-from PyQt5.QtWidgets import QAction, QApplication, QDialog, QHBoxLayout, QLabel, QLineEdit, QListWidgetItem, QPushButton, QVBoxLayout
+from PyQt6.QtCore import QFileSystemWatcher, QItemSelectionModel, pyqtSignal
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QApplication, QDialog, QHBoxLayout, QLabel, QLineEdit, QListWidgetItem, QPushButton, QVBoxLayout
 
 from . import puddleobjects as puddleobjects
 from . import puddletag
@@ -404,4 +405,4 @@ if __name__ == '__main__':
     win = ShortcutEditor(buttons=True)
     win.loadSettings()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/actiondlg.py b/puddlestuff/actiondlg.py
index 7d2147e..818e21b 100644
--- a/puddlestuff/actiondlg.py
+++ b/puddlestuff/actiondlg.py
@@ -4,8 +4,9 @@ import sys
 from copy import copy, deepcopy
 from functools import partial
 
-from PyQt5.QtCore import Qt, pyqtSignal
-from PyQt5.QtWidgets import QAbstractItemView, QAction, QApplication, QCheckBox, QComboBox, QCompleter, \
+from PyQt6.QtCore import Qt, pyqtSignal
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QCheckBox, QComboBox, QCompleter, \
     QDialog, QFrame, QGridLayout, QInputDialog, QLabel, QLineEdit, QListWidgetItem, QMenu, QMessageBox, \
     QScrollArea, QSizePolicy, QSpinBox, QStackedWidget, QToolButton, QVBoxLayout, QWidget
 from pyparsing import delimited_list, alphanums, Combine, Word, QuotedString
@@ -85,7 +86,7 @@ class ShortcutDialog(QDialog):
         self.close()
 
     def getShortcut(self):
-        self.exec_()
+        self.exec()
         if self._text.valid:
             return str(self._text.text()), self.ok
         else:
@@ -128,7 +129,7 @@ class ShortcutName(QDialog):
             self._ok.setEnabled(False)
 
     def getText(self):
-        self.exec_()
+        self.exec()
         return str(self._text.text()), self.ok
 
 
@@ -1091,4 +1092,4 @@ if __name__ == "__main__":
     app.setApplicationName("puddletag")
     qb = ActionWindow([('Path', '__path'), ('Artist', 'artist'), ('Title', 'title'), ('Album', 'album'), ('Track', 'track'), ('Length', '__length'), ('Year', 'date')])
     qb.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/audioinfo/util.py b/puddlestuff/audioinfo/util.py
index e8e8357..f4cb2f7 100644
--- a/puddlestuff/audioinfo/util.py
+++ b/puddlestuff/audioinfo/util.py
@@ -10,7 +10,7 @@ from errno import ENOENT
 from os import path, stat
 
 import mutagen
-from PyQt5.QtCore import QMimeDatabase
+from PyQt6.QtCore import QMimeDatabase
 
 from .constants import *
 
diff --git a/puddlestuff/confirmations.py b/puddlestuff/confirmations.py
index ec5bfc2..8e6459c 100644
--- a/puddlestuff/confirmations.py
+++ b/puddlestuff/confirmations.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 import os
 
-from PyQt5.QtWidgets import QApplication, QWidget, QCheckBox, QVBoxLayout
+from PyQt6.QtWidgets import QApplication, QWidget, QCheckBox, QVBoxLayout
 
 from .constants import CONFIGDIR
 from .puddleobjects import PuddleConfig
@@ -90,4 +90,4 @@ if __name__ == '__main__':
     print(_confirmations)
     win = Settings()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/constants.py b/puddlestuff/constants.py
index 129e576..3e0dbfa 100755
--- a/puddlestuff/constants.py
+++ b/puddlestuff/constants.py
@@ -3,7 +3,7 @@ import os
 import sys
 from os.path import dirname, join
 
-from PyQt5.QtCore import Qt
+from PyQt6.QtCore import Qt
 
 from .translations import translate
 
diff --git a/puddlestuff/duplicates/algwin.py b/puddlestuff/duplicates/algwin.py
index 88c4fd1..fb30a31 100644
--- a/puddlestuff/duplicates/algwin.py
+++ b/puddlestuff/duplicates/algwin.py
@@ -1,9 +1,9 @@
 import os
 import sys
 
-from PyQt5.QtCore import Qt, pyqtSignal
-from PyQt5.QtGui import QDoubleValidator
-from PyQt5.QtWidgets import QAction, QApplication, QCheckBox, QComboBox, QDialog, QFrame, QHBoxLayout, \
+from PyQt6.QtCore import Qt, pyqtSignal
+from PyQt6.QtGui import QAction, QDoubleValidator
+from PyQt6.QtWidgets import QApplication, QCheckBox, QComboBox, QDialog, QFrame, QHBoxLayout, \
     QInputDialog, QLabel, QLineEdit, QMessageBox, QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, \
     QWidget
 
@@ -139,62 +139,6 @@ class DupeTree(QTreeWidget):
     def dragEnterEvent(self, event):
         event.reject()
 
-    # def mouseMoveEvent(self, event):
-    # QTreeWidget.mouseMoveEvent(self, event)
-    # if event.buttons() != Qt.MouseButton.LeftButton:
-    # return
-    # mimeData = QMimeData()
-    # plainText = ""
-    # tags= []
-    # pnt = QPoint(*self.StartPosition)
-    # if (event.pos() - pnt).manhattanLength()  < QApplication.startDragDistance():
-    # return
-    ##I'm adding plaintext to MimeData
-    ##because XMMS doesn't seem to work well with Qt's URL's
-    # for z in self.selectedFiles():
-    # url = QUrl.fromLocalFile(z['__filename'])
-    # plainText = plainText + unicode(url.toString()) + "\n"
-    # tags.append(url)
-    # mimeData = QMimeData()
-    # mimeData.setUrls(tags)
-    # mimeData.setText(plainText)
-
-    # drag = QDrag(self)
-    # drag.setDragCursor(QPixmap(), self.dropaction)
-    # drag.setMimeData(mimeData)
-    # drag.setHotSpot(event.pos() - self.rect().topLeft())
-    # dropaction = drag.exec_(self.dropaction)
-
-    # def mousePressEvent(self, event):
-    # if event.buttons() == Qt.MouseButton.RightButton:
-    # e = QContextMenuEvent(QContextMenuEvent.Reason.Mouse, event.pos(), event.globalPos())
-    # self.contextMenuEvent(e)
-    # return
-    # if event.buttons() == Qt.MouseButton.LeftButton:
-    # self.StartPosition = [event.pos().x(), event.pos().y()]
-    # QTreeWidget.mousePressEvent(self, event)
-
-    # def contextMenuEvent(self, event):
-    # menu = QMenu(self)
-    # move = QAction('Move duplicates', self)
-    # delete = QAction('Delete duplicates', self)
-    # remove = QAction('Remove from listing', self)
-
-    # delete.triggered.connect(self._move)
-    # create.triggered.connect(self._delete)
-    # rename.triggered.connect(self._remove)
-    # [menu.addAction(z) for z in [move, remove, delete]]
-    # menu.exec_(event.globalPos())
-
-    # def _remove(self):
-    # pass
-
-    # def _delete(self):
-    # pass
-
-    # def _move(self):
-    # pass
-
 
 class AlgWin(QWidget):
     okCLickedSignal = pyqtSignal(Algo, name='okClicked')
@@ -255,18 +199,13 @@ class AlgWin(QWidget):
 
         self.tags.setText(' | '.join(alg.tags))
         self.threshold.setText('%.2f' % (alg.threshold * 100))
-        if alg.matchcase:
-            self.matchcase.setCheckState(Qt.CheckState.Checked)
-        else:
-            self.matchcase.setCheckState(Qt.CheckState.Unchecked)
+        self.matchcase.setChecked(bool(alg.matchcase))
 
     def saveAlgo(self):
         tags = [x for x in [z.strip() for z in str(self.tags.text()).split("|")] if x != ""]
         func = funcs[self.alcombo.currentIndex()]
         threshold = float(str(self.threshold.text())) / 100
-        matchcase = False
-        if self.matchcase.checkState() == Qt.CheckState.Checked:
-            matchcase = True
+        matchcase = self.matchcase.isChecked()
 
         return Algo(tags, threshold, func, matchcase)
 
@@ -471,4 +410,4 @@ if __name__ == "__main__":
     qb.show()
     QApplication.processEvents()
     qb.loadDupes(lib, algos, ['%artist% - %title%', '%title%'])
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/functions_dialogs.py b/puddlestuff/functions_dialogs.py
index a7e5785..8de5876 100644
--- a/puddlestuff/functions_dialogs.py
+++ b/puddlestuff/functions_dialogs.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-from PyQt5.QtWidgets import (QCheckBox, QLabel, QHBoxLayout, QSpinBox,
+from PyQt6.QtWidgets import (QCheckBox, QLabel, QHBoxLayout, QSpinBox,
                              QVBoxLayout, QWidget)
 
 from .translations import translate
diff --git a/puddlestuff/genres.py b/puddlestuff/genres.py
index d2df0e2..756514b 100755
--- a/puddlestuff/genres.py
+++ b/puddlestuff/genres.py
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
 import os
 
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QHBoxLayout, QListWidgetItem, QWidget
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QHBoxLayout, QListWidgetItem, QWidget
 
 from . import audioinfo
 from .constants import CONFIGDIR
diff --git a/puddlestuff/helperwin.py b/puddlestuff/helperwin.py
index 3cd50dd..a5ec4c3 100644
--- a/puddlestuff/helperwin.py
+++ b/puddlestuff/helperwin.py
@@ -5,9 +5,9 @@ import os
 import sys
 from copy import deepcopy
 
-from PyQt5.QtCore import QItemSelectionModel, Qt, pyqtRemoveInputHook, pyqtSignal
-from PyQt5.QtGui import QPalette, QBrush, QColor
-from PyQt5.QtWidgets import QAbstractItemView, QAction, QApplication, QCheckBox, QComboBox, QCompleter, \
+from PyQt6.QtCore import QItemSelectionModel, Qt, pyqtRemoveInputHook, pyqtSignal
+from PyQt6.QtGui import QAction, QPalette, QBrush, QColor
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QCheckBox, QComboBox, QCompleter, \
     QDialog, QFileDialog, QFrame, QGridLayout, QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMessageBox, \
     QPlainTextEdit, QPushButton, QSpinBox, QTableWidget, QTableWidgetItem, QTextEdit, QToolButton, QVBoxLayout
 
@@ -30,7 +30,7 @@ TAG_DISP = "<b>%s: </b> %s, "
 
 
 class AutonumberDialog(QDialog):
-    newtracks = pyqtSignal(int, int, 'Qt::CheckState', int, str, str, 'Qt::CheckState', name='newtracks')
+    newtracks = pyqtSignal(int, int, bool, int, str, str, bool, name='newtracks')
 
     def __init__(self, parent=None, minval=0, numtracks=0,
                  enablenumtracks=False):
@@ -130,8 +130,7 @@ class AutonumberDialog(QDialog):
 
         self._loadSettings()
 
-    def showDirectorySplittingOptions(self, state):
-        is_checked = state == Qt.CheckState.Checked
+    def showDirectorySplittingOptions(self, is_checked: bool):
         for widget in self.custom_numbering_widgets:
             widget.setVisible(is_checked)
 
@@ -161,11 +160,11 @@ class AutonumberDialog(QDialog):
         self.newtracks.emit(
             self._start.value(),
             numtracks,
-            self._restart_numbering.checkState(),
+            self._restart_numbering.isChecked(),
             self._padlength.value(),
             str(self.grouping.text()),
             str(self.output_field.currentText()),
-            self.count_by_group.checkState()
+            self.count_by_group.isChecked(),
         )
 
         self._saveSettings()
@@ -174,17 +173,17 @@ class AutonumberDialog(QDialog):
         cparser = PuddleConfig()
         section = 'autonumbering'
         self._start.setValue(cparser.get(section, 'start', 1))
-        self._separator.setCheckState(
-            cparser.get(section, 'separator', Qt.CheckState.Unchecked))
+        self._separator.setChecked(
+            cparser.get(section, 'separator', False))
         self._padlength.setValue(cparser.get(section, 'padlength', 1))
 
-        self._restart_numbering.setCheckState(
-            cparser.get(section, 'restart', Qt.CheckState.Unchecked))
+        self._restart_numbering.setChecked(
+            cparser.get(section, 'restart', False))
 
-        self.count_by_group.setCheckState(
-            cparser.get(section, 'count_by_group', Qt.CheckState.Unchecked))
+        self.count_by_group.setChecked(
+            cparser.get(section, 'count_by_group', False))
 
-        self.showDirectorySplittingOptions(self._restart_numbering.checkState())
+        self.showDirectorySplittingOptions(self._restart_numbering.isChecked())
 
         self.grouping.setText(cparser.get(section, 'grouping', '%__dirpath%'))
 
@@ -200,10 +199,10 @@ class AutonumberDialog(QDialog):
         cparser = PuddleConfig()
         section = 'autonumbering'
         cparser.set(section, 'start', self._start.value())
-        cparser.set(section, 'separator', self._separator.checkState())
-        cparser.set(section, 'count_by_group', self.count_by_group.checkState())
+        cparser.set(section, 'separator', self._separator.isChecked())
+        cparser.set(section, 'count_by_group', self.count_by_group.isChecked())
         cparser.set(section, 'numtracks', self._numtracks.value())
-        cparser.set(section, 'restart', self._restart_numbering.checkState())
+        cparser.set(section, 'restart', self._restart_numbering.isChecked())
         cparser.set(section, 'padlength', self._padlength.value())
         cparser.set(section, 'grouping', self.grouping.text())
         cparser.set(section, 'output_field', self.output_field.currentText())
@@ -1178,4 +1177,4 @@ if __name__ == "__main__":
     wid.resize(200, 400)
     wid.show()
     pyqtRemoveInputHook()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/libraries/quodlibetlib.py b/puddlestuff/libraries/quodlibetlib.py
index 9484da1..5f4cb97 100755
--- a/puddlestuff/libraries/quodlibetlib.py
+++ b/puddlestuff/libraries/quodlibetlib.py
@@ -7,8 +7,9 @@ from copy import deepcopy
 from functools import partial
 
 import quodlibet.config
-from PyQt5.QtCore import QDir, Qt
-from PyQt5.QtWidgets import QCompleter, QFileDialog, QFileSystemModel, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget
+from PyQt6.QtCore import QDir, Qt
+from PyQt6.QtGui import QFileSystemModel
+from PyQt6.QtWidgets import QCompleter, QFileDialog, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget
 from quodlibet.query import Query
 
 from .. import audioinfo
diff --git a/puddlestuff/libraries/rhythmbox.py b/puddlestuff/libraries/rhythmbox.py
index a45e07c..d0c69a0 100644
--- a/puddlestuff/libraries/rhythmbox.py
+++ b/puddlestuff/libraries/rhythmbox.py
@@ -28,8 +28,8 @@ from os import path
 from xml.sax import make_parser
 from xml.sax.handler import ContentHandler
 
-from PyQt5.QtCore import QDir, QSettings, QUrl
-from PyQt5.QtWidgets import QFileDialog, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget
+from PyQt6.QtCore import QDir, QSettings, QUrl
+from PyQt6.QtWidgets import QFileDialog, QHBoxLayout, QLabel, QLineEdit, QPushButton, QVBoxLayout, QWidget
 
 from .. import audioinfo
 from .. import musiclib
diff --git a/puddlestuff/loadshortcuts.py b/puddlestuff/loadshortcuts.py
index b6c3a6b..325cb42 100644
--- a/puddlestuff/loadshortcuts.py
+++ b/puddlestuff/loadshortcuts.py
@@ -2,7 +2,8 @@
 import os
 import sys
 
-from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QMenu, QMenuBar, QToolBar
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QApplication, QMainWindow, QMenu, QMenuBar, QToolBar
 
 from .constants import CONFIGDIR
 from .puddleobjects import PuddleConfig, get_icon, open_resourcefile
@@ -165,4 +166,4 @@ if __name__ == '__main__':
     win.toolbar = win.addToolBar('toolbar')
     loadShortCuts()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/m3u.py b/puddlestuff/m3u.py
index 9a96c64..c4d241a 100644
--- a/puddlestuff/m3u.py
+++ b/puddlestuff/m3u.py
@@ -4,7 +4,7 @@ import sys
 from os.path import abspath, dirname, normcase, normpath, splitdrive
 from os.path import join as path_join
 
-from PyQt5.QtWidgets import QFileDialog, QApplication
+from PyQt6.QtWidgets import QFileDialog, QApplication
 
 from . import audioinfo
 from .audioinfo.util import lnglength, encode_fn
diff --git a/puddlestuff/mainwin/action_dialogs.py b/puddlestuff/mainwin/action_dialogs.py
index 23a232a..31e1e4e 100644
--- a/puddlestuff/mainwin/action_dialogs.py
+++ b/puddlestuff/mainwin/action_dialogs.py
@@ -1,7 +1,7 @@
 from functools import partial
 
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QPushButton, QHBoxLayout, QListWidgetItem
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QPushButton, QHBoxLayout, QListWidgetItem
 
 from ..actiondlg import ActionWindow, CreateFunction
 from ..constants import RIGHTDOCK, SELECTIONCHANGED
diff --git a/puddlestuff/mainwin/artwork.py b/puddlestuff/mainwin/artwork.py
index 2c88476..e2dc2fa 100644
--- a/puddlestuff/mainwin/artwork.py
+++ b/puddlestuff/mainwin/artwork.py
@@ -1,10 +1,10 @@
 # -*- coding: utf-8 -*-
 import tempfile
 
-from PyQt5.QtCore import QRect, Qt
-from PyQt5.QtGui import QFont, QFontMetrics, QPainter, QBrush
-from PyQt5.QtSvg import QSvgGenerator
-from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QWidget
+from PyQt6.QtCore import QRect, Qt
+from PyQt6.QtGui import QFont, QFontMetrics, QPainter, QBrush
+from PyQt6.QtSvg import QSvgGenerator
+from PyQt6.QtWidgets import QHBoxLayout, QVBoxLayout, QWidget
 
 from ..audioinfo.util import commonimages
 from ..constants import KEEP, BLANK
diff --git a/puddlestuff/mainwin/dirview.py b/puddlestuff/mainwin/dirview.py
index e9fbcd6..4ce83c8 100644
--- a/puddlestuff/mainwin/dirview.py
+++ b/puddlestuff/mainwin/dirview.py
@@ -1,8 +1,8 @@
 import os
 
-from PyQt5.QtCore import QDir, QDirIterator, QItemSelectionModel, QMutex, QSettings, QUrl, Qt, pyqtSignal
-from PyQt5.QtGui import QDesktopServices
-from PyQt5.QtWidgets import QAbstractItemView, QAction, QCheckBox, QFileSystemModel, QHeaderView, QMenu, QTreeView, QVBoxLayout, QWidget
+from PyQt6.QtCore import QDir, QDirIterator, QItemSelectionModel, QMutex, QSettings, QUrl, Qt, pyqtSignal
+from PyQt6.QtGui import QAction, QDesktopServices, QFileSystemModel
+from PyQt6.QtWidgets import QAbstractItemView, QCheckBox, QHeaderView, QMenu, QTreeView, QVBoxLayout, QWidget
 
 from ..constants import LEFTDOCK, QT_CONFIG
 from ..puddleobjects import (PuddleConfig, PuddleThread,
@@ -125,7 +125,7 @@ class DirView(QTreeView):
         menu.addAction(show_header)
         menu.addAction(open_dir)
 
-        menu.exec_(event.globalPos())
+        menu.exec(event.globalPos())
         super(DirView, self).contextMenuEvent(event)
 
     def dirMoved(self, dirs):
@@ -357,10 +357,7 @@ class DirViewWidget(QWidget):
         self.dirview.saveSettings()
 
     def setSubFolders(self, check):
-        if check == Qt.CheckState.Checked:
-            value = True
-        else:
-            value = False
+        value = (check == Qt.CheckState.Checked)
         self.dirview.subfolders = value
         save_gen_settings({'Su&bfolders': value})
         self._status['table'].subFolders = value
diff --git a/puddlestuff/mainwin/filterwin.py b/puddlestuff/mainwin/filterwin.py
index eb8159e..8f615c8 100644
--- a/puddlestuff/mainwin/filterwin.py
+++ b/puddlestuff/mainwin/filterwin.py
@@ -1,5 +1,5 @@
-from PyQt5.QtCore import QTimer, pyqtSignal
-from PyQt5.QtWidgets import (QWidget, QLineEdit, QPushButton)
+from PyQt6.QtCore import QTimer, pyqtSignal
+from PyQt6.QtWidgets import (QWidget, QLineEdit, QPushButton)
 
 from ..constants import BOTTOMDOCK
 from ..puddleobjects import create_buddy, PuddleCombo
diff --git a/puddlestuff/mainwin/funcs.py b/puddlestuff/mainwin/funcs.py
index 0810f32..cf7e643 100644
--- a/puddlestuff/mainwin/funcs.py
+++ b/puddlestuff/mainwin/funcs.py
@@ -2,16 +2,17 @@ import json
 import os
 import pickle
 from collections import OrderedDict
+from typing import List, Optional
 
-from PyQt5.QtCore import QByteArray, QMimeData, pyqtSignal, QObject
-from PyQt5.QtWidgets import QApplication
+from PyQt6.QtCore import QByteArray, QMimeData, pyqtSignal, QObject
+from PyQt6.QtWidgets import QApplication
 
 from .. import actiondlg
 from .. import findfunc
 from .. import helperwin
 from ..puddleobjects import (PuddleConfig, PuddleDock)
 
-from ..audioinfo import PATH, DIRPATH, FILETAGS, tag_to_json, encode_fn, decode_fn
+from ..audioinfo import PATH, DIRPATH, FILETAGS, AbstractTag, tag_to_json, encode_fn, decode_fn
 from .. import musiclib, about as about
 from ..util import split_by_tag, translate, to_string
 from .. import functions
@@ -171,7 +172,7 @@ def check_copy_data(data):
         noImgBtn = msgbox.addButton(translate("Messages", "Copy without images."),
                                     QMessageBox.ButtonRole.ApplyRole)
 
-        msgbox.exec_()
+        msgbox.exec()
 
         if msgbox.clickedButton() is yesBtn:
             return 0
@@ -277,7 +278,9 @@ def _pad(trknum, total, padlen):
     return text
 
 
-def number_tracks(tags, parent, offset, numtracks, restartdirs, padlength, split_field='__dirpath', output_field='track', by_group=False):
+def number_tracks(tags: List[AbstractTag], parent: Optional[QObject], offset: int, numtracks: int, restartdirs: bool,
+                  padlength: int, split_field: str = '__dirpath', output_field: str = 'track',
+                  by_group: bool = False) -> None:
     """Numbers the selected tracks sequentially in the range
     between the indexes.
     The first item of indices is the starting track.
@@ -494,7 +497,7 @@ def search_replace(parent=None):
 def show_about(parent=None):
     win = about.AboutPuddletag(parent)
     win.setModal(True)
-    win.exec_()
+    win.exec()
 
 
 def tag_to_file():
diff --git a/puddlestuff/mainwin/logdialog.py b/puddlestuff/mainwin/logdialog.py
index 0a32e42..32ce76d 100644
--- a/puddlestuff/mainwin/logdialog.py
+++ b/puddlestuff/mainwin/logdialog.py
@@ -1,6 +1,6 @@
-from PyQt5.QtCore import QMutex
-from PyQt5.QtGui import QTextOption
-from PyQt5.QtWidgets import QApplication, QHBoxLayout, QPushButton, QTextEdit, QVBoxLayout, QWidget
+from PyQt6.QtCore import QMutex
+from PyQt6.QtGui import QTextOption
+from PyQt6.QtWidgets import QApplication, QHBoxLayout, QPushButton, QTextEdit, QVBoxLayout, QWidget
 
 from ..constants import RIGHTDOCK
 from ..translations import translate
@@ -57,4 +57,4 @@ if __name__ == '__main__':
     app = QApplication([])
     win = LogDialog()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/mainwin/patterncombo.py b/puddlestuff/mainwin/patterncombo.py
index 0c7586d..8bd8dd8 100644
--- a/puddlestuff/mainwin/patterncombo.py
+++ b/puddlestuff/mainwin/patterncombo.py
@@ -1,8 +1,9 @@
 import sys
 
-from PyQt5.QtCore import Qt, pyqtSignal
-from PyQt5.QtWidgets import QAbstractItemView, QApplication, QComboBox, QFrame, QHBoxLayout, QInputDialog, QPushButton, \
-    QShortcut, QVBoxLayout
+from PyQt6.QtCore import Qt, pyqtSignal
+from PyQt6.QtGui import QShortcut
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QComboBox, QFrame, QHBoxLayout, QInputDialog, QPushButton, \
+    QVBoxLayout
 
 from ..puddleobjects import (PuddleConfig, ListBox,
                              ListButtons)
@@ -156,4 +157,4 @@ if __name__ == '__main__':
     app = QApplication(sys.argv)
     win = PatternCombo(['one', 'the', 'three'])
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/mainwin/previews.py b/puddlestuff/mainwin/previews.py
index 0ac77d3..49f8e03 100644
--- a/puddlestuff/mainwin/previews.py
+++ b/puddlestuff/mainwin/previews.py
@@ -1,7 +1,8 @@
 from functools import partial
 
-from PyQt5.QtCore import QObject, pyqtSignal
-from PyQt5.QtWidgets import QAction, QMenu
+from PyQt6.QtCore import QObject, pyqtSignal
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QMenu
 
 from ..puddleobjects import PuddleConfig
 
@@ -13,7 +14,7 @@ from ..translations import translate
 status = {}
 
 _previews = []
-_sort_action = None
+_sort_menu = None
 
 ENABLED = translate("Menus", 'Enabl&e Preview Mode')
 DISABLED = translate("Menus", 'Disabl&e Preview Mode')
@@ -87,8 +88,8 @@ def create_actions(parent):
     revert.setShortcut('Ctrl+Shift+Z')
     revert.triggered.connect(undo_last)
 
-    sort = QAction('Sort &By', parent)
-    sort.triggered.connect(sort_by_fields)
+    global _sort_menu
+    _sort_menu = QMenu('Sort &By', parent)
 
     clear_cells = PreviewAction('Clear Selected &Cells', parent)
     clear_cells.triggered.connect(clear_selected_cells)
@@ -97,8 +98,6 @@ def create_actions(parent):
     options = cparser.get('table', 'sortoptions',
                           ['__filename,track,__dirpath', 'track, album',
                            '__filename,album,__dirpath'])
-    global _sort_action
-    _sort_action = sort
     sort_actions = set_sort_options(options)
 
     preview_actions = [clear_selection, write, revert, clear_cells]
@@ -109,22 +108,21 @@ def create_actions(parent):
 
     [connect_shortcut(z, FILESSELECTED) for z in preview_actions]
 
-    return [enable_preview, clear_selection, write, revert, sort,
+    return [enable_preview, clear_selection, write, revert, _sort_menu.menuAction(),
             clear_cells] + sort_actions
 
 
 def set_sort_options(options):
-    parent = _sort_action.parentWidget()
-    menu = QMenu(parent)
+    for action in _sort_menu.actions():
+        _sort_menu.removeAction(action)
+
     sort_actions = []
     options = [[z.strip() for z in option.split(',')] for option in options]
     for option in options:
-        action = QAction('/'.join(option), parent)
+        action = _sort_menu.addAction('/'.join(option))
         action.sortOption = option
-        menu.addAction(action)
         action.triggered.connect(sort_by_fields)
         sort_actions.append(action)
-    _sort_action.setMenu(menu)
     status['sort_actions'] = sort_actions
     return sort_actions
 
diff --git a/puddlestuff/mainwin/releasewidget.py b/puddlestuff/mainwin/releasewidget.py
index b1a39d3..21942fa 100755
--- a/puddlestuff/mainwin/releasewidget.py
+++ b/puddlestuff/mainwin/releasewidget.py
@@ -3,9 +3,10 @@ import traceback
 from copy import deepcopy
 from functools import partial
 
-from PyQt5 import QtCore
-from PyQt5.QtCore import QModelIndex, Qt, pyqtRemoveInputHook, pyqtSignal
-from PyQt5.QtWidgets import QAbstractItemView, QAction, QApplication, QHeaderView, QMenu, QStyle, QTreeView, QWidget
+from PyQt6 import QtCore
+from PyQt6.QtCore import QModelIndex, Qt, pyqtRemoveInputHook, pyqtSignal
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QHeaderView, QMenu, QStyle, QTreeView, QWidget
 
 from ..findfunc import parsefunc
 from ..puddleobjects import (PuddleThread,
@@ -112,7 +113,7 @@ class Header(QHeaderView):
             menu.addAction(action)
 
         [create_action(order) for order in self.sortOptions]
-        menu.exec_(event.globalPos())
+        menu.exec(event.globalPos())
 
 
 class RootItem(object):
@@ -757,4 +758,4 @@ if __name__ == "__main__":
     view.setModel(model)
     view.setWindowTitle("Simple Tree Model")
     view.show()
-    sys.exit(app.exec_())
+    sys.exit(app.exec())
diff --git a/puddlestuff/mainwin/storedtags.py b/puddlestuff/mainwin/storedtags.py
index 82c8243..a2d727d 100755
--- a/puddlestuff/mainwin/storedtags.py
+++ b/puddlestuff/mainwin/storedtags.py
@@ -1,8 +1,8 @@
 import os
 
-from PyQt5.QtCore import QMutex, Qt
-from PyQt5.QtGui import QFont
-from PyQt5.QtWidgets import QApplication, QGridLayout, QLabel, QScrollArea, QVBoxLayout, QWidget
+from PyQt6.QtCore import QMutex, Qt
+from PyQt6.QtGui import QFont
+from PyQt6.QtWidgets import QApplication, QGridLayout, QLabel, QScrollArea, QVBoxLayout, QWidget
 
 from .. import audioinfo
 from ..audioinfo import tag_versions
diff --git a/puddlestuff/mainwin/tagpanel.py b/puddlestuff/mainwin/tagpanel.py
index d4182ab..c401463 100644
--- a/puddlestuff/mainwin/tagpanel.py
+++ b/puddlestuff/mainwin/tagpanel.py
@@ -1,10 +1,10 @@
 import os
-import sip
 import sys
 
-from PyQt5.QtCore import QEvent, QThread, Qt, pyqtRemoveInputHook, pyqtSignal
-from PyQt5.QtGui import QBrush
-from PyQt5.QtWidgets import QApplication, QComboBox, QCompleter, QDialog, QGroupBox, QHBoxLayout, \
+from PyQt6 import sip
+from PyQt6.QtCore import QEvent, QThread, Qt, pyqtRemoveInputHook, pyqtSignal
+from PyQt6.QtGui import QBrush
+from PyQt6.QtWidgets import QApplication, QComboBox, QCompleter, QDialog, QGroupBox, QHBoxLayout, \
     QLabel, QLineEdit, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget
 
 from ..audioinfo import INFOTAGS
@@ -543,4 +543,4 @@ if __name__ == '__main__':
     app = QApplication(sys.argv)
     win = SettingsWin()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/mainwin/tagsources.py b/puddlestuff/mainwin/tagsources.py
index 21ca5c6..c06c1a8 100644
--- a/puddlestuff/mainwin/tagsources.py
+++ b/puddlestuff/mainwin/tagsources.py
@@ -5,8 +5,8 @@ import sys
 import traceback
 from copy import deepcopy
 
-from PyQt5.QtCore import Qt, pyqtRemoveInputHook, pyqtSignal
-from PyQt5.QtWidgets import QAbstractItemView, QApplication, QCheckBox, QComboBox, QDialog, QGroupBox, QHBoxLayout, \
+from PyQt6.QtCore import Qt, pyqtRemoveInputHook, pyqtSignal
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QCheckBox, QComboBox, QDialog, QGroupBox, QHBoxLayout, \
     QInputDialog, QLabel, QLineEdit, QPushButton, QSpinBox, QTextEdit, QToolButton, QVBoxLayout, \
     QWidget
 
@@ -235,10 +235,7 @@ class SimpleDialog(QDialog):
                 vbox.addWidget(control)
             elif ctype == CHECKBOX:
                 control = QCheckBox(desc)
-                if default:
-                    control.setCheckState(Qt.CheckState.Checked)
-                else:
-                    control.setCheckState(Qt.CheckState.Unchecked)
+                control.setChecked(bool(default))
                 vbox.addWidget(control)
             elif ctype == SPINBOX:
                 control = QSpinBox()
@@ -961,4 +958,4 @@ if __name__ == '__main__':
     status['selectedfiles'] = exampletags.tags
     win = MainWin(status)
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/mainwin/tagtools.py b/puddlestuff/mainwin/tagtools.py
index 2cdd44d..0ead56d 100644
--- a/puddlestuff/mainwin/tagtools.py
+++ b/puddlestuff/mainwin/tagtools.py
@@ -1,7 +1,7 @@
 import traceback
 from functools import partial
 
-from PyQt5.QtWidgets import QMessageBox
+from PyQt6.QtWidgets import QMessageBox
 from mutagen import id3, apev2
 
 from .. import audioinfo
diff --git a/puddlestuff/mainwin/teststuff.py b/puddlestuff/mainwin/teststuff.py
index 36c5ead..2d0c1ad 100644
--- a/puddlestuff/mainwin/teststuff.py
+++ b/puddlestuff/mainwin/teststuff.py
@@ -1,6 +1,6 @@
 import tags
-from PyQt5.QtCore import pyqtSignal
-from PyQt5.QtWidgets import QInputDialog, QPushButton, QVBoxLayout, QWidget
+from PyQt6.QtCore import pyqtSignal
+from PyQt6.QtWidgets import QInputDialog, QPushButton, QVBoxLayout, QWidget
 
 from .. import audioinfo
 from ..audioinfo.util import (PATH,
diff --git a/puddlestuff/masstag/dialogs.py b/puddlestuff/masstag/dialogs.py
index a918533..1c436ce 100644
--- a/puddlestuff/masstag/dialogs.py
+++ b/puddlestuff/masstag/dialogs.py
@@ -3,8 +3,8 @@ import os
 from copy import deepcopy
 from functools import partial
 
-from PyQt5.QtCore import QMutex, QObject, pyqtSignal
-from PyQt5.QtWidgets import QApplication, QCheckBox, QComboBox, QDialog, QGridLayout, QHBoxLayout, QLabel, \
+from PyQt6.QtCore import QMutex, QObject, pyqtSignal
+from PyQt6.QtWidgets import QApplication, QCheckBox, QComboBox, QDialog, QGridLayout, QHBoxLayout, QLabel, \
     QLineEdit, QPushButton, QSpinBox, QTextEdit, QVBoxLayout, QWidget
 
 from .. import masstag as masstag_module
@@ -701,4 +701,4 @@ if __name__ == '__main__':
     win = MassTagEdit(sources)
     win.loadProfiles()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/musiclib.py b/puddlestuff/musiclib.py
index 74eb92a..7173036 100644
--- a/puddlestuff/musiclib.py
+++ b/puddlestuff/musiclib.py
@@ -13,8 +13,8 @@ import sys
 from collections import defaultdict
 from functools import partial
 
-from PyQt5.QtCore import QObject, Qt, pyqtRemoveInputHook, pyqtSignal
-from PyQt5.QtWidgets import QAbstractItemView, QApplication, QDialog, QFrame, QHBoxLayout, QLineEdit, \
+from PyQt6.QtCore import QObject, Qt, pyqtRemoveInputHook, pyqtSignal
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QDialog, QFrame, QHBoxLayout, QLineEdit, \
     QListWidget, QMessageBox, QPushButton, QStackedWidget, QStyle, QTreeWidget, QTreeWidgetItem, QVBoxLayout, \
     QWidget
 
@@ -487,4 +487,4 @@ if __name__ == "__main__":
     qb.loadtags.connect(b)
 
     qb.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/pluginloader.py b/puddlestuff/pluginloader.py
index 35f624d..307e9f9 100755
--- a/puddlestuff/pluginloader.py
+++ b/puddlestuff/pluginloader.py
@@ -4,8 +4,8 @@ import sys
 from os.path import exists
 from importlib import import_module
 
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QApplication, QDialog, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QVBoxLayout
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QApplication, QDialog, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QVBoxLayout
 from configobj import ConfigObj
 
 from .constants import (FUNCTIONS, TAGSOURCE, SAVEDIR, PLUGINDIR,
@@ -165,4 +165,4 @@ if __name__ == '__main__':
     app = QApplication([])
     win = PluginConfig()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/plugins/dupe_fields/__init__.py b/puddlestuff/plugins/dupe_fields/__init__.py
index 8f10e1c..2849256 100644
--- a/puddlestuff/plugins/dupe_fields/__init__.py
+++ b/puddlestuff/plugins/dupe_fields/__init__.py
@@ -1,5 +1,6 @@
-from PyQt5.QtCore import QObject, pyqtSignal
-from PyQt5.QtWidgets import QAction, QInputDialog
+from PyQt6.QtCore import QObject, pyqtSignal
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QInputDialog
 
 from .. import status, connect_control
 from ...puddletag import add_shortcuts
diff --git a/puddlestuff/plugins/extended_tags/__init__.py b/puddlestuff/plugins/extended_tags/__init__.py
index 87a90da..a972b3d 100644
--- a/puddlestuff/plugins/extended_tags/__init__.py
+++ b/puddlestuff/plugins/extended_tags/__init__.py
@@ -1,5 +1,5 @@
-from PyQt5.QtCore import pyqtSignal
-from PyQt5.QtWidgets import QAction
+from PyQt6.QtCore import pyqtSignal
+from PyQt6.QtGui import QAction
 
 from ...audioinfo import commontags
 from ...constants import (LEFTDOCK, SELECTIONCHANGED,
diff --git a/puddlestuff/plugins/id3_tools/__init__.py b/puddlestuff/plugins/id3_tools/__init__.py
index 2ffda63..78bd817 100644
--- a/puddlestuff/plugins/id3_tools/__init__.py
+++ b/puddlestuff/plugins/id3_tools/__init__.py
@@ -1,7 +1,8 @@
 from functools import partial
 
-from PyQt5.QtCore import QObject
-from PyQt5.QtWidgets import QApplication, QMessageBox, QAction
+from PyQt6.QtCore import QObject
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QApplication, QMessageBox
 
 from .. import connect_shortcut, status
 from ... import audioinfo
diff --git a/puddlestuff/plugins/modified_time/__init__.py b/puddlestuff/plugins/modified_time/__init__.py
index 48a29e9..500f030 100644
--- a/puddlestuff/plugins/modified_time/__init__.py
+++ b/puddlestuff/plugins/modified_time/__init__.py
@@ -2,7 +2,8 @@ import os
 import time
 from datetime import timedelta, datetime
 
-from PyQt5.QtWidgets import QAction, QApplication, QMessageBox
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QApplication, QMessageBox
 
 from .. import status
 from ... import audioinfo
diff --git a/puddlestuff/plugins/save_tags/__init__.py b/puddlestuff/plugins/save_tags/__init__.py
index 83ea454..c42d1ab 100644
--- a/puddlestuff/plugins/save_tags/__init__.py
+++ b/puddlestuff/plugins/save_tags/__init__.py
@@ -3,7 +3,8 @@ import traceback
 
 import mutagen
 import pickle
-from PyQt5.QtWidgets import QAction, QFileDialog
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QFileDialog
 
 from .. import status
 from ...puddletag import add_shortcuts
diff --git a/puddlestuff/plugins/view_all_fields/__init__.py b/puddlestuff/plugins/view_all_fields/__init__.py
index 005037c..7cd6609 100644
--- a/puddlestuff/plugins/view_all_fields/__init__.py
+++ b/puddlestuff/plugins/view_all_fields/__init__.py
@@ -1,7 +1,8 @@
 import os
 
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QAbstractItemView, QAction, QApplication, QFrame, QHBoxLayout, QInputDialog, QLabel, \
+from PyQt6.QtCore import Qt
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QFrame, QHBoxLayout, QInputDialog, QLabel, \
     QPushButton, QVBoxLayout
 
 from ...puddlesettings import add_config_widget
@@ -189,4 +190,4 @@ if __name__ == '__main__':
     app = QApplication([])
     win = Settings()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/puddleobjects.py b/puddlestuff/puddleobjects.py
index c5e3aa9..4e1d026 100644
--- a/puddlestuff/puddleobjects.py
+++ b/puddlestuff/puddleobjects.py
@@ -12,19 +12,21 @@ import time
 from bisect import bisect_left, insort_left  # for unique function.
 from collections import defaultdict
 from copy import copy
-from functools import partial
+from functools import partial, reduce
 from glob import glob
 from io import StringIO
 from itertools import groupby  # for unique function.
+from operator import or_
 from typing import Any, Callable, Generator, List, Optional, Tuple, Union
 
-from PyQt5.QtCore import QBuffer, QByteArray, QCollator, QCollatorSortKey, QDir, QLocale, QObject, QRectF, QSettings, \
+from PyQt6.QtCore import QBuffer, QByteArray, QCollator, QCollatorSortKey, QDir, QLocale, QObject, QRectF, QSettings, \
     QSize, QThread, QTimer, Qt, pyqtSignal
-from PyQt5.QtCore import QFile, QIODevice
-from PyQt5.QtGui import QIcon, QBrush, QPixmap, QImage, \
+from PyQt6.QtCore import QFile, QIODevice
+from PyQt6.QtGui import QAction, QIcon, QBrush, QPixmap, QImage, \
     QKeySequence
-from PyQt5.QtSvg import QGraphicsSvgItem, QSvgRenderer
-from PyQt5.QtWidgets import QAbstractItemView, QAction, QApplication, QComboBox, QDialog, QDialogButtonBox, \
+from PyQt6.QtSvg import QSvgRenderer
+from PyQt6.QtSvgWidgets import QGraphicsSvgItem
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QComboBox, QDialog, QDialogButtonBox, \
     QDockWidget, QFileDialog, QFrame, QGraphicsPixmapItem, QGraphicsScene, QGraphicsView, QGridLayout, QHBoxLayout, \
     QHeaderView, QLabel, QLayout, QLineEdit, QListWidget, QMenu, QMessageBox, QProgressBar, QPushButton, QSizePolicy, \
     QTextEdit, QToolButton, QVBoxLayout, QWidget
@@ -77,10 +79,8 @@ def keycmp(modifier):
 modifiers = {}
 for i in range(1, len(mod_keys)):
     for keys in set(itertools.permutations(mod_keys, i)):
-        mod = keys[0]
-        for key in keys[1:]:
-            mod = mod | key
-        modifiers[int(mod)] = '+'.join(mod_keys[key] for key in sorted(keys, key=keycmp) if mod_keys[key])
+        mask = reduce(or_, keys)
+        modifiers[mask] = '+'.join(mod_keys[key] for key in sorted(keys, key=keycmp) if mod_keys[key])
 
 mod_keys = set((Qt.Key.Key_Shift, Qt.Key.Key_Control, Qt.Key.Key_Meta, Qt.Key.Key_Alt))
 
@@ -499,7 +499,7 @@ def errormsg(parent, msg, maximum):
                          parent)
         mb.setDefaultButton(QMessageBox.StandardButton.Yes)
         mb.setEscapeButton(QMessageBox.StandardButton.No)
-        ret = mb.exec_()
+        ret = mb.exec()
         if ret == QMessageBox.StandardButton.No:
             return False
         elif ret == QMessageBox.StandardButton.YesToAll:
@@ -2371,7 +2371,7 @@ class PuddleHeader(QHeaderView):
 
     def contextMenuEvent(self, event):
         menu = self.getMenu()
-        menu.exec_(event.globalPos())
+        menu.exec(event.globalPos())
 
 
 class PuddleStatus(object):
@@ -2446,7 +2446,7 @@ class ShortcutEditor(QLineEdit):
         text = ''
 
         if event.modifiers():
-            text = modifiers[int(event.modifiers())]
+            text = modifiers[event.modifiers()]
 
         if event.key() not in mod_keys:
             if text:
@@ -2493,4 +2493,4 @@ if __name__ == '__main__':
     app = QApplication(sys.argv)
     widget = MainWin()
     widget.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/puddlesettings.py b/puddlestuff/puddlesettings.py
index f55fcf1..493f9b9 100644
--- a/puddlestuff/puddlesettings.py
+++ b/puddlestuff/puddlesettings.py
@@ -2,9 +2,9 @@ import os
 import sys
 from copy import deepcopy
 
-from PyQt5.QtCore import QAbstractListModel, QItemSelection, QItemSelectionModel, QModelIndex, Qt, pyqtSignal
-from PyQt5.QtGui import QBrush, QColor, QPalette
-from PyQt5.QtWidgets import QAbstractItemView, QApplication, QCheckBox, QColorDialog, QComboBox, QDialog, QFrame, \
+from PyQt6.QtCore import QAbstractListModel, QItemSelection, QItemSelectionModel, QModelIndex, Qt, pyqtSignal
+from PyQt6.QtGui import QBrush, QColor, QPalette
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QCheckBox, QColorDialog, QComboBox, QDialog, QFrame, \
     QGridLayout, QGroupBox, QHBoxLayout, QLabel, QLineEdit, QListView, QMessageBox, QPushButton, QRadioButton, \
     QStackedWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget
 
@@ -74,17 +74,11 @@ class SettingsCheckBox(QCheckBox):
 
     @property
     def settingValue(self):
-        if self.checkState() == Qt.CheckState.Checked:
-            return self._text, True
-        else:
-            return self._text, False
+        return self._text, self.isChecked()
 
     @settingValue.setter
     def settingValue(self, value):
-        if value:
-            self.setCheckState(Qt.CheckState.Checked)
-        else:
-            self.setCheckState(Qt.CheckState.Unchecked)
+        self.setChecked(bool(value))
 
 
 class SettingsLineEdit(QWidget):
@@ -205,10 +199,6 @@ class Playlist(QWidget):
     def __init__(self, parent=None):
         QWidget.__init__(self, parent)
 
-        def inttocheck(value):
-            if value:
-                return Qt.CheckState.Checked
-            return Qt.CheckState.Unchecked
 
         cparser = PuddleConfig()
 
@@ -217,14 +207,14 @@ class Playlist(QWidget):
 
         self.extinfo = QCheckBox(translate("Playlist Settings", '&Write extended info'), self)
         self.extinfo.stateChanged.connect(self.extpattern.setEnabled)
-        self.extinfo.setCheckState(inttocheck(cparser.load('playlist', 'extinfo', 1, True)))
-        self.extpattern.setEnabled(self.extinfo.checkState())
+        self.extinfo.setChecked(cparser.load('playlist', 'extinfo', True))
+        self.extpattern.setEnabled(self.extinfo.isChecked())
 
         self.reldir = QCheckBox(translate("Playlist Settings", 'Entries &relative to working directory'))
-        self.reldir.setCheckState(inttocheck(cparser.load('playlist', 'reldir', 0, True)))
+        self.reldir.setChecked(cparser.load('playlist', 'reldir', False))
 
         self.windows_separator = QCheckBox(translate("Playlist Settings", 'Use windows path separator (\\)'))
-        self.windows_separator.setCheckState(inttocheck(cparser.load('playlist', 'windows_separator', 0, True)))
+        self.windows_separator.setChecked(cparser.load('playlist', 'windows_separator', False))
 
         self.filename = QLineEdit()
         self.filename.setText(cparser.load('playlist', 'filepattern', 'puddletag.m3u'))
@@ -245,19 +235,12 @@ class Playlist(QWidget):
         self.setLayout(vbox)
 
     def applySettings(self, control=None):
-
-        def checktoint(checkbox):
-            if checkbox.checkState() == Qt.CheckState.Checked:
-                return 1
-            else:
-                return 0
-
         cparser = PuddleConfig()
-        cparser.setSection('playlist', 'extinfo', checktoint(self.extinfo))
+        cparser.setSection('playlist', 'extinfo', self.extinfo.isChecked())
         cparser.setSection('playlist', 'extpattern', str(self.extpattern.text()))
-        cparser.setSection('playlist', 'reldir', checktoint(self.reldir))
+        cparser.setSection('playlist', 'reldir', self.reldir.isChecked())
         cparser.setSection('playlist', 'filepattern', str(self.filename.text()))
-        cparser.setSection('playlist', 'windows_separator', checktoint(self.windows_separator))
+        cparser.setSection('playlist', 'windows_separator', self.windows_separator.isChecked())
 
 
 class TagMappings(QWidget):
@@ -488,8 +471,8 @@ class ListModel(QAbstractListModel):
     def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole):
         if role == Qt.ItemDataRole.TextAlignmentRole:
             if orientation == Qt.Orientation.Horizontal:
-                return int(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
-            return int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+                return Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter
+            return Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
         if role != Qt.ItemDataRole.DisplayRole:
             return None
         if orientation == Qt.Orientation.Horizontal:
@@ -720,4 +703,4 @@ if __name__ == "__main__":
     app.setApplicationName("puddletag")
     qb = SettingsDialog()
     qb.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/puddletag.py b/puddlestuff/puddletag.py
index e9f5507..c2e5db2 100644
--- a/puddlestuff/puddletag.py
+++ b/puddlestuff/puddletag.py
@@ -5,9 +5,9 @@ import sys
 import urllib.parse
 from functools import partial
 
-from PyQt5.QtCore import QDir, QSettings, QUrl, pyqtRemoveInputHook, pyqtSignal
-from PyQt5.QtGui import QDesktopServices
-from PyQt5.QtWidgets import QAction, QApplication, QFileDialog, QFrame, QLabel, QMainWindow, QMenu, QMessageBox, QSplitter, QVBoxLayout, QWidget
+from PyQt6.QtCore import QDir, QSettings, QUrl, pyqtRemoveInputHook, pyqtSignal
+from PyQt6.QtGui import QAction, QDesktopServices
+from PyQt6.QtWidgets import QApplication, QFileDialog, QFrame, QLabel, QMainWindow, QMenu, QMessageBox, QSplitter, QVBoxLayout, QWidget
 
 from . import loadshortcuts as ls
 from . import m3u, genres
@@ -1095,4 +1095,4 @@ if __name__ == '__main__':
     app = QApplication(sys.argv)
     win = MainWin()
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/resource.py b/puddlestuff/resource.py
index e322ef5..0fbd25f 100644
--- a/puddlestuff/resource.py
+++ b/puddlestuff/resource.py
@@ -2,7 +2,7 @@
 
 from os.path import abspath, dirname, join
 
-from PyQt5.QtCore import QDir
+from PyQt6.QtCore import QDir
 
 
 package_path = abspath(dirname(__file__))
diff --git a/puddlestuff/shortcutsettings.py b/puddlestuff/shortcutsettings.py
index 6727612..d2556e5 100644
--- a/puddlestuff/shortcutsettings.py
+++ b/puddlestuff/shortcutsettings.py
@@ -1,9 +1,9 @@
 import os
 import sys
 
-from PyQt5.QtCore import QEvent, QLineF, QRectF, Qt, pyqtRemoveInputHook
-from PyQt5.QtGui import QBrush, QKeySequence, QPainter, QPalette, QPen
-from PyQt5.QtWidgets import qApp, QAbstractItemDelegate, QAbstractItemView, QApplication, QFrame, QItemDelegate, QLabel, \
+from PyQt6.QtCore import QEvent, QLineF, QRectF, Qt, pyqtRemoveInputHook
+from PyQt6.QtGui import QBrush, QKeySequence, QPainter, QPalette, QPen
+from PyQt6.QtWidgets import QAbstractItemDelegate, QAbstractItemView, QApplication, QFrame, QItemDelegate, QLabel, \
     QTableWidget, QTableWidgetItem, QVBoxLayout, QWidget
 
 from . import loadshortcuts as ls
@@ -16,11 +16,6 @@ pyqtRemoveInputHook()
 
 class ActionEditorWidget(QLabel):
 
-    # Redefine the tr() function for this class.
-    def tr(self, text):
-
-        return qApp.translate("ActionEditorWidget", text)
-
     def __init__(self, text, parent):
 
         QLabel.__init__(self, text, parent)
@@ -87,7 +82,7 @@ class ActionEditorWidget(QLabel):
         size = self.height() / 2.0
         rect = QRectF(self.width() - size, size * 0.5, size, size)
 
-        if rect.contains(event.localPos()):
+        if rect.contains(event.position()):
             self.clear()
             self.valid = True
             event.accept()
@@ -189,11 +184,6 @@ class ActionEditorDelegate(QItemDelegate):
 
 class ActionEditorDialog(QWidget):
 
-    # Redefine the tr() function for this class.
-    def tr(self, text):
-
-        return qApp.translate("ActionEditorDialog", text)
-
     def __init__(self, actions, parent=None):
 
         super(ActionEditorDialog, self).__init__(parent)
@@ -321,4 +311,4 @@ if __name__ == '__main__':
     win = ActionEditorDialog(actions)
     # win.loadSettings(actions)
     win.show()
-    app.exec_()
+    app.exec()
diff --git a/puddlestuff/tagmodel.py b/puddlestuff/tagmodel.py
index 80746bb..a074a61 100755
--- a/puddlestuff/tagmodel.py
+++ b/puddlestuff/tagmodel.py
@@ -9,10 +9,10 @@ from os import path
 from subprocess import Popen
 from typing import Dict
 
-from PyQt5.QtCore import QAbstractTableModel, QEvent, QItemSelection, QItemSelectionModel, QItemSelectionRange, \
+from PyQt6.QtCore import QAbstractTableModel, QEvent, QItemSelection, QItemSelectionModel, QItemSelectionRange, \
     QMetaObject, QMimeData, QModelIndex, QPoint, QUrl, Qt, pyqtSignal, pyqtSlot, Q_ARG
-from PyQt5.QtGui import QColor, QFont, QDrag, QPalette
-from PyQt5.QtWidgets import QAbstractItemDelegate, QAbstractItemView, QAction, QApplication, QDialog, QGridLayout, QGroupBox, \
+from PyQt6.QtGui import QAction, QColor, QFont, QDrag, QPalette
+from PyQt6.QtWidgets import QAbstractItemDelegate, QAbstractItemView, QApplication, QDialog, QGridLayout, QGroupBox, \
     QHBoxLayout, QHeaderView, QLabel, QLineEdit, QMenu, QMessageBox, QPushButton, QStyledItemDelegate, QTableView, \
     QVBoxLayout
 
@@ -445,7 +445,7 @@ class ColumnSettings(HeaderSetting):
             self.tags[row][0] = str(self.textname.text())
             self.tags[row][1] = str(self.tag.currentText())
         checked = [z for z in range(self.listbox.count()) if
-                   self.listbox.item(z).checkState()]
+                   self.listbox.item(z).checkState() == Qt.CheckState.Checked]
         titles = [z[0] for z in self.tags]
         tags = [z[1] for z in self.tags]
         cparser = PuddleConfig()
@@ -468,8 +468,7 @@ class ColumnSettings(HeaderSetting):
 
     def duplicate(self):
         item = self.listbox.currentItem()
-        if item:
-            checked = item.checkState()
+        checked = item.checkState()
         HeaderSetting.duplicate(self)
         self.listbox.currentItem().setCheckState(checked)
 
@@ -787,8 +786,8 @@ class TagModel(QAbstractTableModel):
     def headerData(self, section, orientation, role=Qt.ItemDataRole.DisplayRole):
         if role == Qt.ItemDataRole.TextAlignmentRole:
             if orientation == Qt.Orientation.Horizontal:
-                return int(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter)
-            return int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter)
+                return Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter
+            return Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter
         if role != Qt.ItemDataRole.DisplayRole:
             return None
         if orientation == Qt.Orientation.Horizontal:
@@ -1331,7 +1330,7 @@ class TableHeader(QHeaderView):
             translate("Column Settings", "&Select Columns"))
         settings.triggered.connect(self.setTitles)
 
-        menu.exec_(event.globalPos())
+        menu.exec(event.globalPos())
 
     def mousePressEvent(self, event):
         if event.button == Qt.MouseButton.RightButton:
@@ -1641,7 +1640,7 @@ class TagTable(QTableView):
 
     def contextMenuEvent(self, event):
         if self.contextMenu:
-            self.contextMenu.exec_(event.globalPos())
+            self.contextMenu.exec(event.globalPos())
 
     @property
     def isempty(self):
@@ -1717,7 +1716,7 @@ class TagTable(QTableView):
         if event.source() == self and \
                 hasattr(mime, 'draggedRows') and mime.draggedRows:
 
-            row = self.rowAt(event.pos().y())
+            row = self.rowAt(event.position().toPoint().y())
             if row == -1:
                 row = self.rowCount() - 1
             self.saveSelection()
@@ -1786,7 +1785,7 @@ class TagTable(QTableView):
         drag = QDrag(self)
         drag.setMimeData(mimeData)
         drag.setHotSpot(event.pos() - self.rect().topLeft())
-        dropaction = drag.exec_()
+        dropaction = drag.exec()
         if dropaction == Qt.DropAction.MoveAction:
             if not os.path.exists(filenames[0]):
                 self.deleteSelected(False, False, False)
diff --git a/puddlestuff/tagsources/__init__.py b/puddlestuff/tagsources/__init__.py
index 9399295..2ff3269 100644
--- a/puddlestuff/tagsources/__init__.py
+++ b/puddlestuff/tagsources/__init__.py
@@ -9,7 +9,7 @@ from html.parser import HTMLParser
 from importlib import import_module
 from os.path import join, exists
 
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
 
 from .. import version_string
 from ..constants import CONFIGDIR
diff --git a/puddlestuff/translations.py b/puddlestuff/translations.py
index e401de2..7ae0719 100644
--- a/puddlestuff/translations.py
+++ b/puddlestuff/translations.py
@@ -1,4 +1,4 @@
-from PyQt5.QtWidgets import QApplication
+from PyQt6.QtWidgets import QApplication
 
 
 def translate(context, source_text):
diff --git a/puddlestuff/util.py b/puddlestuff/util.py
index 0eb2ced..a79533c 100644
--- a/puddlestuff/util.py
+++ b/puddlestuff/util.py
@@ -9,7 +9,7 @@ from operator import itemgetter
 from xml.sax.saxutils import escape as escape_html
 from mutagen import MutagenError
 
-from PyQt5.QtWidgets import QAction
+from PyQt6.QtGui import QAction
 
 from . import translations, constants
 from .audioinfo import (FILETAGS, setmodtime, PATH, FILENAME,
diff --git a/puddletag b/puddletag
index bbd7c83..b85e0ea 100755
--- a/puddletag
+++ b/puddletag
@@ -63,6 +63,22 @@ def _migrate_action_shortcut_filenames():
         fo.write(json.dumps(data, indent=2))
 
 
+def _migrate_checkstates():
+    from puddlestuff.puddleobjects import PuddleConfig
+    cparser = PuddleConfig()
+    for section, key in (
+        ('autonumbering', 'separator'),
+        ('autonumbering', 'restart'),
+        ('autonumbering', 'count_by_group'),
+        ('playlist', 'extinfo'),
+        ('playlist', 'reldir'),
+        ('playlist', 'windows_separator'),
+    ):
+        old_value = cparser.get(section, key, None)
+        if old_value is not None and isinstance(old_value, int):
+            cparser.set(section, key, bool(old_value))
+
+
 def migrate_settings():
     from puddlestuff.constants import CONFIGDIR, SAVEDIR
     for dirpath in [CONFIGDIR, SAVEDIR]:
@@ -91,6 +107,7 @@ def migrate_settings():
     _migrate_action_shortcuts()
     convert_ini_files()
     _migrate_action_shortcut_filenames()
+    _migrate_checkstates()
 
 
 def _migrate_action_shortcuts():
@@ -126,7 +143,7 @@ def check_libs():
               'http://code.google.com/p/configobj/'),
              ('pyparsing', '(python3-pyparsing or python3-parsing in most distros)',
               'https://github.com/pyparsing/pyparsing/'),
-             ('PyQt5', '(python3-pyqt5 usually)',
+             ('PyQt6', '(python3-pyqt6 usually)',
               'http://www.riverbankcomputing.co.uk/software/pyqt/intro')]
 
     found = True
@@ -148,7 +165,7 @@ def check_libs():
 
     try:
         if not found:
-            from PyQt5.QtWidgets import QApplication, QMessageBox
+            from PyQt6.QtWidgets import QApplication, QMessageBox
             app = QApplication([])
             QMessageBox.critical(None, 'puddletag', '\n'.join(errors))
     except:
@@ -226,14 +243,14 @@ def load_language(qapp, langfile=None):
     if langargs and langargs != 'default':
         translator = QTranslator()
         translator.load("qt_" + QLocale.system().name(),
-                        QLibraryInfo.location(QLibraryInfo.LibraryLocation.TranslationsPath))
+                        QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath))
         translators.append(translator)
 
         if 'puddletag_' in langargs[0]:
             translator = QTranslator()
             locale = langargs[0][len('puddletag_'):-len('.qm')]
             translator.load("qt_" + locale,
-                            QLibraryInfo.location(QLibraryInfo.LibraryLocation.TranslationsPath))
+                            QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath))
             print("Locale: " + locale)
             translators.append(translator)
 
@@ -244,7 +261,7 @@ def load_language(qapp, langfile=None):
     elif langargs != 'default':
         translator = QTranslator()
         translator.load("qt_" + QLocale.system().name(),
-                        QLibraryInfo.location(QLibraryInfo.LibraryLocation.TranslationsPath))
+                        QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath))
         print("Locale: " + str(QLocale.system().name()))
         translators.append(translator)
 
@@ -286,8 +303,8 @@ def print_info():
 
 
 def splashscreen():
-    from PyQt5.QtGui import QFont, QPainter, QPixmap
-    from PyQt5.QtWidgets import QSplashScreen
+    from PyQt6.QtGui import QFont, QPainter, QPixmap
+    from PyQt6.QtWidgets import QSplashScreen
     from puddlestuff import version_string
 
     pixmap = QPixmap('icons:puddlelogo.png')
@@ -326,8 +343,8 @@ class StdOut(object):
 
 if __name__ == '__main__':
     check_libs()
-    from PyQt5.QtWidgets import QApplication
-    from PyQt5.QtCore import (pyqtRemoveInputHook, QTranslator,
+    from PyQt6.QtWidgets import QApplication
+    from PyQt6.QtCore import (pyqtRemoveInputHook, QTranslator,
                               QLibraryInfo, QLocale)
     import logging
     from configobj import ConfigObj
@@ -375,4 +392,4 @@ if __name__ == '__main__':
     elif load_gen_settings([('&Load last folder at startup', False)])[0][1]:
         if win._lastdir and os.path.exists(win._lastdir[0]):
             win.openDir(win._lastdir[0], False)
-    app.exec_()
+    app.exec()
diff --git a/requirements.in b/requirements.in
index 5beece3..16b7470 100644
--- a/requirements.in
+++ b/requirements.in
@@ -1,5 +1,5 @@
 # core functionalities
-pyqt5==5.15.11
+PyQt6>=6.4.0
 configobj==5.0.9
 mutagen==1.47.0
 pyparsing>=3.1.2
diff --git a/requirements.txt b/requirements.txt
index 15a47d2..40cd2ff 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,5 @@
 #
-# This file is autogenerated by pip-compile with Python 3.10
+# This file is autogenerated by pip-compile with Python 3.13
 # by the following command:
 #
 #    pip-compile
@@ -24,12 +24,12 @@ pyacoustid==1.3.0
     # via -r requirements.in
 pyparsing==3.2.3
     # via -r requirements.in
-pyqt5==5.15.11
+pyqt6==6.9.0
     # via -r requirements.in
-pyqt5-qt5==5.15.2
-    # via pyqt5
-pyqt5-sip==12.15.0
-    # via pyqt5
+pyqt6-qt6==6.9.0
+    # via pyqt6
+pyqt6-sip==13.10.0
+    # via pyqt6
 rapidfuzz==3.10.0
     # via levenshtein
 requests==2.32.4
diff --git a/restore_tag.py b/restore_tag.py
index 1a84058..fdb2b89 100644
--- a/restore_tag.py
+++ b/restore_tag.py
@@ -4,7 +4,8 @@ import pickle
 import traceback
 
 import mutagen
-from PyQt5.QtWidgets import QAction, QFileDialog
+from PyQt6.QtGui import QAction
+from PyQt6.QtWidgets import QFileDialog
 from puddlestuff.plugins import status
 
 last_fn = {'fn': '~'}
