diff --git a/ai_diffusion/client.py b/ai_diffusion/client.py
index 574a6d37a..13b6ff332 100644
--- a/ai_diffusion/client.py
+++ b/ai_diffusion/client.py
@@ -2,7 +2,7 @@
from abc import ABC, abstractmethod
from enum import Enum
from typing import Any, AsyncGenerator, Iterable, NamedTuple
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from .api import WorkflowInput
from .image import ImageCollection
diff --git a/ai_diffusion/connection.py b/ai_diffusion/connection.py
index 73fd0485f..d5be049b4 100644
--- a/ai_diffusion/connection.py
+++ b/ai_diffusion/connection.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from enum import Enum
-from PyQt5.QtCore import QObject, pyqtSignal, QUrl
-from PyQt5.QtGui import QDesktopServices
+from PyQt6.QtCore import QObject, pyqtSignal, QUrl
+from PyQt6.QtGui import QDesktopServices
import asyncio
from .client import Client, ClientMessage, ClientEvent, DeviceInfo, SharedWorkflow, MissingResources
diff --git a/ai_diffusion/control.py b/ai_diffusion/control.py
index d88de3f3d..e64ebac67 100644
--- a/ai_diffusion/control.py
+++ b/ai_diffusion/control.py
@@ -1,5 +1,5 @@
from __future__ import annotations
-from PyQt5.QtCore import QObject, pyqtSignal, QUuid, Qt
+from PyQt6.QtCore import QObject, pyqtSignal, QUuid, Qt
from typing import Any, NamedTuple
from pathlib import Path
import json
diff --git a/ai_diffusion/custom_workflow.py b/ai_diffusion/custom_workflow.py
index 596655993..1f7bb62a3 100644
--- a/ai_diffusion/custom_workflow.py
+++ b/ai_diffusion/custom_workflow.py
@@ -7,8 +7,8 @@
from dataclasses import dataclass
from typing import Any, Awaitable, Callable, NamedTuple, Literal, TYPE_CHECKING
from pathlib import Path
-from PyQt5.QtCore import Qt, QObject, QUuid, QAbstractListModel, QSortFilterProxyModel, QModelIndex
-from PyQt5.QtCore import QMetaObject, QTimer, pyqtSignal
+from PyQt6.QtCore import Qt, QObject, QUuid, QAbstractListModel, QSortFilterProxyModel, QModelIndex
+from PyQt6.QtCore import QMetaObject, QTimer, pyqtSignal
from .api import WorkflowInput
from .client import TextOutput, ClientOutput
diff --git a/ai_diffusion/document.py b/ai_diffusion/document.py
index f26b7fec4..7fb29e0d2 100644
--- a/ai_diffusion/document.py
+++ b/ai_diffusion/document.py
@@ -4,7 +4,7 @@
from weakref import WeakValueDictionary
import krita
from krita import Krita
-from PyQt5.QtCore import QObject, QUuid, QByteArray, QTimer, pyqtSignal
+from PyQt6.QtCore import QObject, QUuid, QByteArray, QTimer, pyqtSignal
from .image import Extent, Bounds, Mask, Image
from .layer import Layer, LayerManager, LayerType
diff --git a/ai_diffusion/eventloop.py b/ai_diffusion/eventloop.py
index a8ff3ffd0..8e3afcb53 100644
--- a/ai_diffusion/eventloop.py
+++ b/ai_diffusion/eventloop.py
@@ -1,7 +1,7 @@
import asyncio
import threading
from typing import Callable
-from PyQt5.QtCore import QTimer
+from PyQt6.QtCore import QTimer
_loop = asyncio.new_event_loop()
_timer = QTimer()
diff --git a/ai_diffusion/extension.py b/ai_diffusion/extension.py
index ba4c32013..cfcaaa0aa 100644
--- a/ai_diffusion/extension.py
+++ b/ai_diffusion/extension.py
@@ -1,7 +1,7 @@
import sys
from pathlib import Path
from typing import Callable
-from PyQt5.QtWidgets import QAction
+from PyQt6.QtGui import QAction
from krita import Extension, Krita, DockWidgetFactory, DockWidgetFactoryBase, Window # type: ignore
from . import eventloop, __version__
@@ -79,5 +79,5 @@ def createActions(self, window):
Krita.instance().addExtension(AIToolsExtension(Krita.instance()))
Krita.instance().addDockWidgetFactory(
- DockWidgetFactory("imageDiffusion", DockWidgetFactoryBase.DockRight, ImageDiffusionWidget) # type: ignore
+ DockWidgetFactory("imageDiffusion", DockWidgetFactoryBase.DockPosition.DockRight, ImageDiffusionWidget) # type: ignore
)
diff --git a/ai_diffusion/files.py b/ai_diffusion/files.py
index 9bedc2a91..51bed38e4 100644
--- a/ai_diffusion/files.py
+++ b/ai_diffusion/files.py
@@ -5,8 +5,8 @@
from dataclasses import dataclass, asdict
from pathlib import Path
from typing import Any, NamedTuple, Sequence, cast
-from PyQt5.QtCore import QAbstractListModel, QSortFilterProxyModel, QModelIndex, Qt
-from PyQt5.QtGui import QIcon
+from PyQt6.QtCore import QAbstractListModel, QSortFilterProxyModel, QModelIndex, Qt
+from PyQt6.QtGui import QIcon
from .util import encode_json, read_json_with_comments, user_data_dir, client_logger as log
diff --git a/ai_diffusion/image.py b/ai_diffusion/image.py
index c5eabd7ba..4b295c79b 100644
--- a/ai_diffusion/image.py
+++ b/ai_diffusion/image.py
@@ -1,9 +1,9 @@
from __future__ import annotations
from enum import Enum
from math import sqrt
-from PyQt5.QtGui import QImage, QImageWriter, QImageReader, QPixmap, QIcon, QPainter, QColorSpace
-from PyQt5.QtGui import qRgba, qRed, qGreen, qBlue, qAlpha, qGray
-from PyQt5.QtCore import Qt, QByteArray, QBuffer, QRect, QSize, QFile, QIODevice
+from PyQt6.QtGui import QImage, QImageWriter, QImageReader, QPixmap, QIcon, QPainter, QColorSpace
+from PyQt6.QtGui import qRgba, qRed, qGreen, qBlue, qAlpha, qGray
+from PyQt6.QtCore import Qt, QByteArray, QBuffer, QRect, QSize, QFile, QIODevice
from typing import Callable, Iterable, SupportsIndex, Tuple, NamedTuple, Union, Optional
from itertools import product
from pathlib import Path
@@ -484,11 +484,11 @@ def data(self):
return buffer
else:
ptr = ensure(self._qimage.constBits(), "Accessing data of invalid image")
- return QByteArray(ptr.asstring(self._qimage.byteCount()))
+ return QByteArray(ptr.asstring(self._qimage.sizeInBytes()))
@property
def size(self): # in bytes
- return self._qimage.byteCount()
+ return self._qimage.sizeInBytes()
def to_array(self):
import numpy as np
diff --git a/ai_diffusion/jobs.py b/ai_diffusion/jobs.py
index b8c375377..38a9b89db 100644
--- a/ai_diffusion/jobs.py
+++ b/ai_diffusion/jobs.py
@@ -4,7 +4,7 @@
from datetime import datetime
from enum import Enum, Flag
from typing import Any, NamedTuple, TYPE_CHECKING
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from .image import Bounds, ImageCollection
from .settings import settings
diff --git a/ai_diffusion/layer.py b/ai_diffusion/layer.py
index 836299da3..f2bf791dc 100644
--- a/ai_diffusion/layer.py
+++ b/ai_diffusion/layer.py
@@ -2,8 +2,8 @@
from contextlib import contextmanager, nullcontext
from enum import Enum
import krita
-from PyQt5.QtCore import QObject, QUuid, QByteArray, QTimer, pyqtSignal
-from PyQt5.QtGui import QImage
+from PyQt6.QtCore import QObject, QUuid, QByteArray, QTimer, pyqtSignal
+from PyQt6.QtGui import QImage
from .image import Extent, Bounds, Image, ImageCollection
from .util import acquire_elements, ensure, maybe, client_logger as log
diff --git a/ai_diffusion/model.py b/ai_diffusion/model.py
index 0031f1cae..e26c58aec 100644
--- a/ai_diffusion/model.py
+++ b/ai_diffusion/model.py
@@ -8,8 +8,8 @@
from tempfile import TemporaryDirectory
import time
from typing import Any, NamedTuple
-from PyQt5.QtCore import QObject, QUuid, pyqtSignal, Qt
-from PyQt5.QtGui import QPainter, QColor, QBrush
+from PyQt6.QtCore import QObject, QUuid, pyqtSignal, Qt
+from PyQt6.QtGui import QPainter, QColor, QBrush
import uuid
from . import eventloop, workflow, util
diff --git a/ai_diffusion/network.py b/ai_diffusion/network.py
index 432d8fe0a..51b245031 100644
--- a/ai_diffusion/network.py
+++ b/ai_diffusion/network.py
@@ -6,8 +6,8 @@
from datetime import datetime
from pathlib import Path
from typing import NamedTuple
-from PyQt5.QtCore import QByteArray, QUrl, QFile, QBuffer
-from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QSslError
+from PyQt6.QtCore import QByteArray, QUrl, QFile, QBuffer
+from PyQt6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply, QSslError
from .localization import translate as _
from .util import client_logger as log
@@ -35,7 +35,7 @@ def __str__(self):
@staticmethod
def from_reply(reply: QNetworkReply):
- code: QNetworkReply.NetworkError = reply.error() # type: ignore (bug in PyQt5-stubs)
+ code: QNetworkReply.NetworkError = reply.error() # type: ignore (bug in PyQt6-stubs)
url = reply.url().toString()
status = reply.attribute(QNetworkRequest.Attribute.HttpStatusCodeAttribute)
if reply.isReadable():
@@ -96,7 +96,7 @@ def http(
self._cleanup()
request = QNetworkRequest(QUrl(url))
- request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True)
+ request.setAttribute(QNetworkRequest.Attribute.RedirectPolicyAttribute, True)
request.setRawHeader(b"ngrok-skip-browser-warning", b"69420")
if bearer:
request.setRawHeader(b"Authorization", f"Bearer {bearer}".encode("utf-8"))
@@ -146,7 +146,7 @@ async def upload(self, url: str, data: QByteArray | bytes, sha256: str | None =
assert isinstance(data, QByteArray)
request = QNetworkRequest(QUrl(url))
- request.setAttribute(QNetworkRequest.Attribute.FollowRedirectsAttribute, True)
+ request.setAttribute(QNetworkRequest.Attribute.RedirectPolicyAttribute, True)
if sha256:
request.setRawHeader(b"x-amz-checksum-sha256", sha256.encode("utf-8"))
request.setHeader(
@@ -173,7 +173,7 @@ async def upload(self, url: str, data: QByteArray | bytes, sha256: str | None =
def download(self, url: str):
self._cleanup()
request = QNetworkRequest(QUrl(url))
- request.setAttribute(QNetworkRequest.Attribute.FollowRedirectsAttribute, True)
+ request.setAttribute(QNetworkRequest.Attribute.RedirectPolicyAttribute, True)
reply = self._net.get(request)
assert reply is not None, f"Network request for {url} failed: reply is None"
@@ -201,7 +201,7 @@ def _upload_progress(self, bytes_sent: int, bytes_total: int):
def _finished(self, reply: QNetworkReply):
future = None
try:
- code = reply.error() # type: ignore (bug in PyQt5-stubs)
+ code = reply.error() # type: ignore (bug in PyQt6-stubs)
tracker = self._requests[reply]
future = tracker.future
if future.cancelled():
@@ -274,13 +274,13 @@ def final(self):
async def _try_download(network: QNetworkAccessManager, url: str, path: Path):
out_file = QFile(str(path) + ".part")
- if not out_file.open(QFile.ReadWrite | QFile.Append): # type: ignore
+ if not out_file.open(QFile.OpenModeFlag.ReadWrite | QFile.OpenModeFlag.Append): # type: ignore
raise Exception(
_("Error during download: could not open {path} for writing", path=out_file.fileName())
)
request = QNetworkRequest(QUrl(_map_host(url)))
- request.setAttribute(QNetworkRequest.FollowRedirectsAttribute, True)
+ request.setAttribute(QNetworkRequest.Attribute.RedirectPolicyAttribute, True)
if out_file.size() > 0:
log.info(f"Found {path}.part, resuming download from {out_file.size()} bytes")
request.setRawHeader(b"Range", f"bytes={out_file.size()}-".encode("utf-8"))
@@ -302,7 +302,7 @@ def handle_finished():
out_file.close()
if finished_future.cancelled():
return # operation was cancelled, discard result
- if reply.error() == QNetworkReply.NetworkError.NoError: # type: ignore (bug in PyQt5-stubs)
+ if reply.error() == QNetworkReply.NetworkError.NoError: # type: ignore (bug in PyQt6-stubs)
finished_future.set_result(path)
elif reply.attribute(QNetworkRequest.HttpStatusCodeAttribute) == 416:
# 416 = Range Not Satisfiable
diff --git a/ai_diffusion/persistence.py b/ai_diffusion/persistence.py
index 5438521bf..f319837c9 100644
--- a/ai_diffusion/persistence.py
+++ b/ai_diffusion/persistence.py
@@ -5,9 +5,9 @@
from enum import Enum
from typing import Any
from time import time
-from PyQt5.QtCore import QObject, QByteArray
-from PyQt5.QtGui import QImageReader
-from PyQt5.QtWidgets import QMessageBox
+from PyQt6.QtCore import QObject, QByteArray
+from PyQt6.QtGui import QImageReader
+from PyQt6.QtWidgets import QMessageBox
from .api import InpaintMode, FillMode
from .image import ImageCollection
diff --git a/ai_diffusion/pose.py b/ai_diffusion/pose.py
index d1b153eee..9f4ff985c 100644
--- a/ai_diffusion/pose.py
+++ b/ai_diffusion/pose.py
@@ -1,7 +1,7 @@
from functools import reduce
import operator
from typing import Dict, List, NamedTuple, Optional
-from PyQt5.QtCore import QPointF
+from PyQt6.QtCore import QPointF
from .image import Extent
from .util import batched
diff --git a/ai_diffusion/properties.py b/ai_diffusion/properties.py
index 00902e9e5..6122f9a41 100644
--- a/ai_diffusion/properties.py
+++ b/ai_diffusion/properties.py
@@ -2,8 +2,8 @@
from enum import Enum
from typing import Any, NamedTuple, Sequence, TypeVar, Generic
-from PyQt5.QtCore import QObject, QMetaObject, QUuid, pyqtBoundSignal
-from PyQt5.QtWidgets import QComboBox
+from PyQt6.QtCore import QObject, QMetaObject, QUuid, pyqtBoundSignal
+from PyQt6.QtWidgets import QComboBox
T = TypeVar("T")
diff --git a/ai_diffusion/region.py b/ai_diffusion/region.py
index 1cd39ef1e..d3dcd0b51 100644
--- a/ai_diffusion/region.py
+++ b/ai_diffusion/region.py
@@ -1,6 +1,6 @@
from __future__ import annotations
from enum import Enum
-from PyQt5.QtCore import QObject, QUuid, pyqtSignal
+from PyQt6.QtCore import QObject, QUuid, pyqtSignal
from . import eventloop, model, workflow
from .api import ConditioningInput, RegionInput
diff --git a/ai_diffusion/root.py b/ai_diffusion/root.py
index ecc2000f4..1a69bbadd 100644
--- a/ai_diffusion/root.py
+++ b/ai_diffusion/root.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Callable
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from .connection import Connection, ConnectionState
from .client import ClientMessage
diff --git a/ai_diffusion/server.py b/ai_diffusion/server.py
index 04e6779a4..d1088f00e 100644
--- a/ai_diffusion/server.py
+++ b/ai_diffusion/server.py
@@ -8,7 +8,7 @@
import os
import time
from typing import Callable, NamedTuple, Optional, Union
-from PyQt5.QtNetwork import QNetworkAccessManager
+from PyQt6.QtNetwork import QNetworkAccessManager
from .settings import settings, ServerBackend
from . import eventloop, resources
diff --git a/ai_diffusion/settings.py b/ai_diffusion/settings.py
index f35fee942..9cd468f88 100644
--- a/ai_diffusion/settings.py
+++ b/ai_diffusion/settings.py
@@ -5,7 +5,7 @@
from enum import Enum
from pathlib import Path
from typing import NamedTuple, Optional, Any
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from .util import is_macos, is_windows, user_data_dir, client_logger as log
from .util import encode_json, read_json_with_comments
diff --git a/ai_diffusion/style.py b/ai_diffusion/style.py
index 955f94a72..6567d61d4 100644
--- a/ai_diffusion/style.py
+++ b/ai_diffusion/style.py
@@ -4,7 +4,7 @@
from typing import Iterable, NamedTuple
import json
from pathlib import Path
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from .api import CheckpointInput, LoraInput
from .settings import Setting, settings
diff --git a/ai_diffusion/ui/animation.py b/ai_diffusion/ui/animation.py
index 5d96796cd..f771ca7e8 100644
--- a/ai_diffusion/ui/animation.py
+++ b/ai_diffusion/ui/animation.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from PyQt5.QtCore import Qt, QMetaObject
-from PyQt5.QtWidgets import (
+from PyQt6.QtCore import Qt, QMetaObject
+from PyQt6.QtWidgets import (
QWidget,
QVBoxLayout,
QHBoxLayout,
@@ -102,12 +102,12 @@ def __init__(self):
self.target_layer = QComboBox(self)
self.target_layer.setMinimumContentsLength(20)
self.target_layer.setSizeAdjustPolicy(
- QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLength
+ QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon
)
layout.addWidget(self.target_layer)
self.preview_area = QLabel(self)
- self.preview_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+ self.preview_area.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.preview_area.setAlignment(
Qt.AlignmentFlag(Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)
)
diff --git a/ai_diffusion/ui/autocomplete.py b/ai_diffusion/ui/autocomplete.py
index 2b6534a93..91109dbe4 100644
--- a/ai_diffusion/ui/autocomplete.py
+++ b/ai_diffusion/ui/autocomplete.py
@@ -3,9 +3,9 @@
import csv
from typing import cast
-from PyQt5.QtWidgets import QApplication, QCompleter, QPlainTextEdit, QStyledItemDelegate, QStyle
-from PyQt5.QtGui import QFont, QPalette, QPen, QColor, QFontMetrics, QTextCursor
-from PyQt5.QtCore import Qt, QStringListModel, QSize, QRect, QAbstractProxyModel
+from PyQt6.QtWidgets import QApplication, QCompleter, QPlainTextEdit, QStyledItemDelegate, QStyle
+from PyQt6.QtGui import QFont, QPalette, QPen, QColor, QFontMetrics, QTextCursor
+from PyQt6.QtCore import Qt, QStringListModel, QSize, QRect, QAbstractProxyModel
from ..root import root
from ..settings import settings
diff --git a/ai_diffusion/ui/control.py b/ai_diffusion/ui/control.py
index 4feab95fa..e667c5b6f 100644
--- a/ai_diffusion/ui/control.py
+++ b/ai_diffusion/ui/control.py
@@ -1,9 +1,9 @@
from __future__ import annotations
-from PyQt5.QtGui import QResizeEvent
-from PyQt5.QtWidgets import QWidget, QLabel, QSlider, QToolButton, QCheckBox
-from PyQt5.QtWidgets import QComboBox, QHBoxLayout, QVBoxLayout, QGridLayout, QFrame
-from PyQt5.QtCore import Qt, QMetaObject, pyqtSignal
+from PyQt6.QtGui import QResizeEvent
+from PyQt6.QtWidgets import QWidget, QLabel, QSlider, QToolButton, QCheckBox
+from PyQt6.QtWidgets import QComboBox, QHBoxLayout, QVBoxLayout, QGridLayout, QFrame
+from PyQt6.QtCore import Qt, QMetaObject, pyqtSignal
from ..resources import ControlMode
from ..properties import Binding, bind, bind_combo, bind_toggle
diff --git a/ai_diffusion/ui/custom_workflow.py b/ai_diffusion/ui/custom_workflow.py
index 33b071e84..7c0b3f0b0 100644
--- a/ai_diffusion/ui/custom_workflow.py
+++ b/ai_diffusion/ui/custom_workflow.py
@@ -3,12 +3,12 @@
from typing import Any, Callable
from krita import Krita
-from PyQt5.QtCore import Qt, pyqtSignal, QMetaObject, QUuid, QUrl, QPoint, QSize
-from PyQt5.QtGui import QFontMetrics, QIcon, QDesktopServices, QPalette
-from PyQt5.QtWidgets import QComboBox, QFileDialog, QFrame, QGridLayout, QHBoxLayout, QMenu
-from PyQt5.QtWidgets import QLabel, QLineEdit, QListWidgetItem, QMessageBox, QSpinBox, QAction
-from PyQt5.QtWidgets import QToolButton, QVBoxLayout, QWidget, QSlider, QDoubleSpinBox
-from PyQt5.QtWidgets import QScrollArea, QTextEdit, QSplitter
+from PyQt6.QtCore import Qt, pyqtSignal, QMetaObject, QUuid, QUrl, QPoint, QSize
+from PyQt6.QtGui import QFontMetrics, QIcon, QDesktopServices, QPalette, QAction
+from PyQt6.QtWidgets import QComboBox, QFileDialog, QFrame, QGridLayout, QHBoxLayout, QMenu
+from PyQt6.QtWidgets import QLabel, QLineEdit, QListWidgetItem, QMessageBox, QSpinBox
+from PyQt6.QtWidgets import QToolButton, QVBoxLayout, QWidget, QSlider, QDoubleSpinBox
+from PyQt6.QtWidgets import QScrollArea, QTextEdit, QSplitter
from ..custom_workflow import CustomParam, ParamKind, SortedWorkflows, WorkflowSource
from ..custom_workflow import CustomGenerationMode
diff --git a/ai_diffusion/ui/diffusion.py b/ai_diffusion/ui/diffusion.py
index f13a9fca8..429b7e1a6 100644
--- a/ai_diffusion/ui/diffusion.py
+++ b/ai_diffusion/ui/diffusion.py
@@ -1,7 +1,7 @@
from __future__ import annotations
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QStackedWidget
-from PyQt5.QtWidgets import QCheckBox
+from PyQt6.QtCore import Qt
+from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QStackedWidget
+from PyQt6.QtWidgets import QCheckBox
from krita import Krita, DockWidget
import krita
diff --git a/ai_diffusion/ui/generation.py b/ai_diffusion/ui/generation.py
index f57ce27e5..5769786bb 100644
--- a/ai_diffusion/ui/generation.py
+++ b/ai_diffusion/ui/generation.py
@@ -1,13 +1,13 @@
from __future__ import annotations
from textwrap import wrap as wrap_text
from typing import cast
-from PyQt5.QtCore import Qt, QEvent, QMetaObject, QSize, QPoint, QTimer, QUuid, pyqtSignal
-from PyQt5.QtCore import QItemSelectionModel
-from PyQt5.QtGui import QGuiApplication, QMouseEvent, QKeyEvent, QKeySequence
-from PyQt5.QtGui import QPalette, QColor, QIcon
-from PyQt5.QtWidgets import QAction, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QProgressBar
-from PyQt5.QtWidgets import QListWidget, QListWidgetItem, QListView, QSizePolicy
-from PyQt5.QtWidgets import QComboBox, QCheckBox, QMenu, QMessageBox, QToolButton
+from PyQt6.QtCore import Qt, QEvent, QMetaObject, QSize, QPoint, QTimer, QUuid, pyqtSignal
+from PyQt6.QtCore import QItemSelectionModel
+from PyQt6.QtGui import QGuiApplication, QMouseEvent, QKeyEvent, QKeySequence
+from PyQt6.QtGui import QPalette, QColor, QIcon, QAction
+from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QProgressBar
+from PyQt6.QtWidgets import QListWidget, QListWidgetItem, QListView, QSizePolicy
+from PyQt6.QtWidgets import QComboBox, QCheckBox, QMenu, QMessageBox, QToolButton
from ..properties import Binding, Bind, bind, bind_combo, bind_toggle
from ..image import Bounds, Extent, Image
@@ -54,13 +54,13 @@ def __init__(self, parent: QWidget | None):
self._model = root.active_model
self._connections = []
- self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
- self.setResizeMode(QListView.Adjust)
+ self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
+ self.setResizeMode(QListView.ResizeMode.Adjust)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
- self.setFlow(QListView.LeftToRight)
- self.setViewMode(QListWidget.IconMode)
+ self.setFlow(QListView.Flow.LeftToRight)
+ self.setViewMode(QListWidget.ViewMode.IconMode)
self.setIconSize(theme.screen_scale(self, QSize(self._thumb_size, self._thumb_size)))
- self.setFrameStyle(QListWidget.NoFrame)
+ self.setFrameStyle(QListWidget.Shape.NoFrame)
self.setStyleSheet(self._list_css)
self.setSelectionMode(QListWidget.SelectionMode.ExtendedSelection)
self.setDragEnabled(False)
@@ -260,7 +260,7 @@ def update_apply_button(self):
rect = self.visualItemRect(selected[0])
font = self._apply_button.fontMetrics()
context_visible = rect.width() >= 0.6 * self.iconSize().width()
- apply_text_visible = font.width(_("Apply")) < 0.35 * rect.width()
+ apply_text_visible = font.horizontalAdvance(_("Apply")) < 0.35 * rect.width()
apply_pos = QPoint(rect.left() + 3, rect.bottom() - self._apply_button.height() - 2)
if context_visible:
cw = self._context_button.width()
@@ -542,7 +542,7 @@ def ctx_icon(name):
)
self.context_combo.setMinimumContentsLength(20)
self.context_combo.setSizeAdjustPolicy(
- QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLength
+ QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon
)
self.context_combo.currentIndexChanged.connect(self.set_context)
diff --git a/ai_diffusion/ui/interval_slider.py b/ai_diffusion/ui/interval_slider.py
index b27a4ada7..790d41b8d 100644
--- a/ai_diffusion/ui/interval_slider.py
+++ b/ai_diffusion/ui/interval_slider.py
@@ -14,11 +14,11 @@
from typing import Tuple
-from PyQt5.QtCore import pyqtSignal as Signal
+from PyQt6.QtCore import pyqtSignal as Signal
-from PyQt5.QtWidgets import QWidget, QStyleOptionSlider, QSizePolicy, QStyle, QSlider
-from PyQt5.QtGui import QPainter, QMouseEvent, QPalette, QBrush
-from PyQt5.QtCore import QRect, Qt, QSize
+from PyQt6.QtWidgets import QWidget, QStyleOptionSlider, QSizePolicy, QStyle, QSlider
+from PyQt6.QtGui import QPainter, QMouseEvent, QPalette, QBrush
+from PyQt6.QtCore import QRect, Qt, QSize
# Based on idea and in part the code from
diff --git a/ai_diffusion/ui/live.py b/ai_diffusion/ui/live.py
index 4b8f40db2..c3d06c65d 100644
--- a/ai_diffusion/ui/live.py
+++ b/ai_diffusion/ui/live.py
@@ -1,6 +1,6 @@
from __future__ import annotations
-from PyQt5.QtCore import QMetaObject, Qt
-from PyQt5.QtWidgets import (
+from PyQt6.QtCore import QMetaObject, Qt
+from PyQt6.QtWidgets import (
QWidget,
QVBoxLayout,
QHBoxLayout,
diff --git a/ai_diffusion/ui/region.py b/ai_diffusion/ui/region.py
index 0a7032f7c..3c3917ee2 100644
--- a/ai_diffusion/ui/region.py
+++ b/ai_diffusion/ui/region.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from enum import Enum
-from PyQt5.QtWidgets import QWidget, QLabel, QToolButton, QHBoxLayout, QVBoxLayout, QFrame, QMenu
-from PyQt5.QtGui import (
+from PyQt6.QtWidgets import QWidget, QLabel, QToolButton, QHBoxLayout, QVBoxLayout, QFrame, QMenu
+from PyQt6.QtGui import (
QGuiApplication,
QMouseEvent,
QResizeEvent,
@@ -11,7 +11,7 @@
QIcon,
QFontMetrics,
)
-from PyQt5.QtCore import QObject, QEvent, Qt, QMetaObject, QSize, pyqtSignal
+from PyQt6.QtCore import QObject, QEvent, Qt, QMetaObject, QSize, pyqtSignal
from ..root import root
from ..client import Client
diff --git a/ai_diffusion/ui/server.py b/ai_diffusion/ui/server.py
index c035e647c..91f8a2f43 100644
--- a/ai_diffusion/ui/server.py
+++ b/ai_diffusion/ui/server.py
@@ -2,9 +2,9 @@
from enum import Enum
from pathlib import Path
from typing import Optional
-from PyQt5.QtCore import Qt, QUrl, pyqtSignal
-from PyQt5.QtGui import QDesktopServices
-from PyQt5.QtWidgets import (
+from PyQt6.QtCore import Qt, QUrl, pyqtSignal
+from PyQt6.QtGui import QDesktopServices
+from PyQt6.QtWidgets import (
QWidget,
QCheckBox,
QComboBox,
@@ -292,7 +292,7 @@ def __init__(self, srv: Server, parent=None):
self._manage_button = QToolButton(self)
self._manage_button.setText(_("Manage"))
- self._manage_button.setPopupMode(QToolButton.InstantPopup)
+ self._manage_button.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
self._manage_button.setMinimumWidth(150)
menu = QMenu(self)
@@ -334,7 +334,7 @@ def __init__(self, srv: Server, parent=None):
scroll = QScrollArea(self)
scroll.setWidget(package_list)
scroll.setWidgetResizable(True)
- scroll.setFrameStyle(QFrame.NoFrame)
+ scroll.setFrameStyle(QFrame.Shape.NoFrame)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
layout.addWidget(scroll, 1)
diff --git a/ai_diffusion/ui/settings.py b/ai_diffusion/ui/settings.py
index c1bfd6225..81d1b2577 100644
--- a/ai_diffusion/ui/settings.py
+++ b/ai_diffusion/ui/settings.py
@@ -2,7 +2,7 @@
from krita import Krita
from typing import Optional
-from PyQt5.QtWidgets import (
+from PyQt6.QtWidgets import (
QVBoxLayout,
QHBoxLayout,
QDialog,
@@ -20,8 +20,8 @@
QMessageBox,
QCheckBox,
)
-from PyQt5.QtCore import Qt, QMetaObject, QSize, QUrl, pyqtSignal
-from PyQt5.QtGui import QDesktopServices, QGuiApplication, QCursor, QFontMetrics
+from PyQt6.QtCore import Qt, QMetaObject, QSize, QUrl, pyqtSignal
+from PyQt6.QtGui import QDesktopServices, QGuiApplication, QCursor, QFontMetrics
from ..client import Client, User, MissingResources
from ..cloud_client import CloudClient
diff --git a/ai_diffusion/ui/settings_widgets.py b/ai_diffusion/ui/settings_widgets.py
index 9ae1efadd..bbc14c146 100644
--- a/ai_diffusion/ui/settings_widgets.py
+++ b/ai_diffusion/ui/settings_widgets.py
@@ -2,7 +2,7 @@
from enum import Enum
from typing import Any
-from PyQt5.QtWidgets import (
+from PyQt6.QtWidgets import (
QVBoxLayout,
QHBoxLayout,
QCheckBox,
@@ -17,8 +17,8 @@
QScrollArea,
QFrame,
)
-from PyQt5.QtCore import Qt, QAbstractItemModel, QSize, pyqtSignal
-from PyQt5.QtGui import QIcon
+from PyQt6.QtCore import Qt, QAbstractItemModel, QSize, pyqtSignal
+from PyQt6.QtGui import QIcon
from ..localization import translate as _
from ..settings import Setting, settings
@@ -69,7 +69,7 @@ def __init__(self, setting: Setting, parent=None):
super().__init__(parent)
self._key_label = QLabel(f"{setting.name}
{setting.desc}")
- self._key_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
+ self._key_label.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred)
self._checkbox: QCheckBox | None = None
self._widget: QWidget | None = None
@@ -441,7 +441,7 @@ def __init__(self, title: str):
scroll = QScrollArea(self)
scroll.setWidget(inner)
scroll.setWidgetResizable(True)
- scroll.setFrameStyle(QFrame.NoFrame)
+ scroll.setFrameStyle(QFrame.Shape.NoFrame)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
frame_layout.addWidget(scroll)
diff --git a/ai_diffusion/ui/style.py b/ai_diffusion/ui/style.py
index 50595d465..a95ea6576 100644
--- a/ai_diffusion/ui/style.py
+++ b/ai_diffusion/ui/style.py
@@ -2,7 +2,7 @@
from typing import Optional, cast
from pathlib import Path
-from PyQt5.QtWidgets import (
+from PyQt6.QtWidgets import (
QVBoxLayout,
QHBoxLayout,
QPushButton,
@@ -18,8 +18,8 @@
QMessageBox,
QLineEdit,
)
-from PyQt5.QtCore import Qt, QUrl, pyqtSignal
-from PyQt5.QtGui import QDesktopServices, QPalette, QColor
+from PyQt6.QtCore import Qt, QUrl, pyqtSignal
+from PyQt6.QtGui import QDesktopServices, QPalette, QColor
from krita import Krita
from ..client import resolve_arch
@@ -599,7 +599,7 @@ def __init__(self, server: Server):
frame_layout.addLayout(builtin_layout)
frame = QFrame(self)
- frame.setFrameStyle(QFrame.StyledPanel)
+ frame.setFrameStyle(QFrame.Shape.StyledPanel)
frame.setLineWidth(1)
frame.setLayout(frame_layout)
self._layout.addWidget(frame)
diff --git a/ai_diffusion/ui/switch.py b/ai_diffusion/ui/switch.py
index 59d73d596..89e146869 100644
--- a/ai_diffusion/ui/switch.py
+++ b/ai_diffusion/ui/switch.py
@@ -2,16 +2,16 @@
from https://stackoverflow.com/a/51825815
"""
-from PyQt5.QtCore import QPropertyAnimation, QSize, Qt, pyqtProperty # type: ignore
-from PyQt5.QtGui import QPainter
-from PyQt5.QtWidgets import QAbstractButton, QSizePolicy
+from PyQt6.QtCore import QPropertyAnimation, QSize, Qt, pyqtProperty # type: ignore
+from PyQt6.QtGui import QPainter
+from PyQt6.QtWidgets import QAbstractButton, QSizePolicy
class SwitchWidget(QAbstractButton):
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setCheckable(True)
- self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
+ self.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
self._thumb_radius = self.fontMetrics().height() // 2
self._track_radius = self._thumb_radius + 2
@@ -69,7 +69,7 @@ def resizeEvent(self, a0):
def paintEvent(self, e):
p = QPainter(self)
- p.setRenderHint(QPainter.Antialiasing, True)
+ p.setRenderHint(QPainter.RenderHint.Antialiasing, True)
p.setPen(Qt.PenStyle.NoPen)
track_opacity = self._track_opacity
thumb_opacity = 1.0
diff --git a/ai_diffusion/ui/theme.py b/ai_diffusion/ui/theme.py
index e7dbda4dd..3f4fedff3 100644
--- a/ai_diffusion/ui/theme.py
+++ b/ai_diffusion/ui/theme.py
@@ -1,7 +1,7 @@
from __future__ import annotations
-from PyQt5.QtCore import Qt, QObject, QSize
-from PyQt5.QtGui import QGuiApplication, QPalette, QIcon, QPixmap, QFontMetrics
-from PyQt5.QtWidgets import QVBoxLayout, QLabel, QWidget
+from PyQt6.QtCore import Qt, QObject, QSize
+from PyQt6.QtGui import QGuiApplication, QPalette, QIcon, QPixmap, QFontMetrics
+from PyQt6.QtWidgets import QVBoxLayout, QLabel, QWidget
from pathlib import Path
from ..files import FileFormat
@@ -21,7 +21,7 @@
highlight = "#8df" if is_dark else "#357"
progress_alt = "#a16207" if is_dark else "#ca8a04"
active = _palette.color(QPalette.ColorRole.Highlight).name()
-line = _palette.color(QPalette.ColorRole.Background).darker(120).name()
+line = _palette.color(QPalette.ColorRole.Window).darker(120).name()
line_base = _palette.color(QPalette.ColorRole.Base).darker(120).name()
flat_combo_stylesheet = f"""
diff --git a/ai_diffusion/ui/upscale.py b/ai_diffusion/ui/upscale.py
index c9b8c7e47..7883a4f39 100644
--- a/ai_diffusion/ui/upscale.py
+++ b/ai_diffusion/ui/upscale.py
@@ -1,6 +1,6 @@
-from PyQt5.QtCore import Qt, QMetaObject, QEvent, pyqtSignal
-from PyQt5.QtGui import QCursor
-from PyQt5.QtWidgets import (
+from PyQt6.QtCore import Qt, QMetaObject, QEvent, pyqtSignal
+from PyQt6.QtGui import QCursor
+from PyQt6.QtWidgets import (
QWidget,
QVBoxLayout,
QHBoxLayout,
diff --git a/ai_diffusion/ui/widget.py b/ai_diffusion/ui/widget.py
index 942eeb771..ac86c86c3 100644
--- a/ai_diffusion/ui/widget.py
+++ b/ai_diffusion/ui/widget.py
@@ -1,8 +1,9 @@
from __future__ import annotations
from typing import Any, Callable, cast
-from PyQt5.QtWidgets import (
- QAction,
+from PyQt6.QtGui import QAction
+
+from PyQt6.QtWidgets import (
QSlider,
QWidget,
QPlainTextEdit,
@@ -22,7 +23,7 @@
QFrame,
QScrollBar,
)
-from PyQt5.QtGui import (
+from PyQt6.QtGui import (
QCloseEvent,
QDesktopServices,
QGuiApplication,
@@ -35,7 +36,7 @@
QPaintEvent,
QKeySequence,
)
-from PyQt5.QtCore import Qt, QMetaObject, QSize, pyqtSignal, QEvent, QUrl
+from PyQt6.QtCore import Qt, QMetaObject, QSize, pyqtSignal, QEvent, QUrl
from krita import Krita
from ..style import Style, Styles
@@ -272,7 +273,7 @@ def _update(self):
def sizeHint(self) -> QSize:
original = super().sizeHint()
- width = original.height() * 0.75 + self.fontMetrics().width(" 99 ") + 20
+ width = original.height() * 0.75 + self.fontMetrics().horizontalAdvance(" 99 ") + 20
return QSize(int(width), original.height())
def paintEvent(self, a0):
@@ -719,7 +720,7 @@ def __init__(self, parent):
self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
self.setMenu(menu)
- self.setPopupMode(QToolButton.InstantPopup)
+ self.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
self.setToolTip(
_("Switch between workspaces: image generation, upscaling, live preview and animation.")
)
@@ -771,7 +772,7 @@ def operation(self, value: str):
def minimumSizeHint(self):
fm = self.fontMetrics()
- return QSize(fm.width(self._operation) + 40, 12 + int(1.3 * fm.height()))
+ return QSize(fm.horizontalAdvance(self._operation) + 40, 12 + int(1.3 * fm.height()))
def enterEvent(self, a0: QEvent | None):
if client := root.connection.client_if_connected:
@@ -796,7 +797,7 @@ def mouseReleaseEvent(self, e: QMouseEvent | None):
def paintEvent(self, a0: QPaintEvent | None) -> None:
opt = QStyleOption()
opt.initFrom(self)
- opt.state |= QStyle.StateFlag.State_Sunken if self.isDown() else 0
+ opt.state |= QStyle.StateFlag.State_Sunken if self.isDown() else QStyle.StateFlag.State_None
painter = QPainter(self)
fm = self.fontMetrics()
style = ensure(self.style())
@@ -807,9 +808,9 @@ def paintEvent(self, a0: QPaintEvent | None) -> None:
)
rect = self.rect()
pixmap = self.icon().pixmap(int(fm.height() * 1.3))
- is_hover = int(opt.state) & QStyle.StateFlag.State_MouseOver
+ is_hover = opt.state & QStyle.StateFlag.State_MouseOver
element = QStyle.PrimitiveElement.PE_PanelButtonCommand
- content_width = fm.width(self._operation) + 5 + pixmap.width()
+ content_width = fm.horizontalAdvance(self._operation) + 5 + pixmap.width()
content_rect = rect.adjusted(int(0.5 * (rect.width() - content_width)), 0, 0, 0)
style.drawPrimitive(element, opt, painter, self)
style.drawItemPixmap(painter, content_rect, align, pixmap)
@@ -996,7 +997,7 @@ def _paint_tool_drop_down(widget: QToolButton, text: str | None = None):
rect = widget.rect()
pixmap = widget.icon().pixmap(int(rect.height() * 0.75))
element = QStyle.PrimitiveElement.PE_Widget
- if int(opt.state) & QStyle.StateFlag.State_MouseOver:
+ if opt.state & QStyle.StateFlag.State_MouseOver:
element = QStyle.PrimitiveElement.PE_PanelButtonCommand
style.drawPrimitive(element, opt, painter, widget)
style.drawItemPixmap(painter, rect.adjusted(4, 0, 0, 0), align, pixmap)
diff --git a/ai_diffusion/updates.py b/ai_diffusion/updates.py
index 44f72e8e2..6911c02d2 100644
--- a/ai_diffusion/updates.py
+++ b/ai_diffusion/updates.py
@@ -6,7 +6,7 @@
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import NamedTuple
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from . import __version__, eventloop
from .network import RequestManager
diff --git a/ai_diffusion/util.py b/ai_diffusion/util.py
index 7542f6924..f6723ec3f 100644
--- a/ai_diffusion/util.py
+++ b/ai_diffusion/util.py
@@ -15,8 +15,8 @@
import statistics
import zipfile
from typing import Any, Callable, Iterable, Optional, Sequence, TypeVar
-from PyQt5 import sip
-from PyQt5.QtCore import QObject, QStandardPaths
+from PyQt6 import sip
+from PyQt6.QtCore import QObject, QStandardPaths
T = TypeVar("T")
R = TypeVar("R")
@@ -35,11 +35,11 @@ def _get_user_data_dir():
dir.mkdir(exist_ok=True)
return dir
try:
- dir = Path(QStandardPaths.writableLocation(QStandardPaths.AppDataLocation))
+ dir = Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation))
if dir.exists() and "krita" in dir.name.lower():
dir = dir / "ai_diffusion"
else:
- dir = Path(QStandardPaths.writableLocation(QStandardPaths.GenericDataLocation))
+ dir = Path(QStandardPaths.writableLocation(QStandardPaths.StandardLocation.GenericDataLocation))
dir = dir / "krita-ai-diffusion"
dir.mkdir(exist_ok=True)
return dir
diff --git a/tests/conftest.py b/tests/conftest.py
index 3e664c69c..1fe0a4ed8 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -4,7 +4,7 @@
import subprocess
import dotenv
from pathlib import Path
-from PyQt5.QtCore import QCoreApplication
+from PyQt6.QtCore import QCoreApplication
sys.path.append(str(Path(__file__).parent.parent))
from ai_diffusion import eventloop, network, util
diff --git a/tests/test_api.py b/tests/test_api.py
index 56d6f8605..3012a405a 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -1,4 +1,4 @@
-from PyQt5.QtCore import Qt
+from PyQt6.QtCore import Qt
from ai_diffusion.api import (
WorkflowInput,
diff --git a/tests/test_custom_workflow.py b/tests/test_custom_workflow.py
index bf79394a4..0ff53f482 100644
--- a/tests/test_custom_workflow.py
+++ b/tests/test_custom_workflow.py
@@ -2,7 +2,7 @@
import pytest
from copy import copy
from pathlib import Path
-from PyQt5.QtCore import Qt
+from PyQt6.QtCore import Qt
from ai_diffusion.api import CustomWorkflowInput, ImageInput, WorkflowInput
from ai_diffusion.client import Client, ClientModels, CheckpointInfo, TextOutput
diff --git a/tests/test_files.py b/tests/test_files.py
index 18a0d94b2..42803d19f 100644
--- a/tests/test_files.py
+++ b/tests/test_files.py
@@ -1,6 +1,6 @@
from pathlib import Path
-from PyQt5.QtCore import Qt, QModelIndex
-from PyQt5.QtGui import QIcon
+from PyQt6.QtCore import Qt, QModelIndex
+from PyQt6.QtGui import QIcon
from ai_diffusion.files import File, FileCollection, FileSource, FileFilter
diff --git a/tests/test_image.py b/tests/test_image.py
index 839368e34..23691fec8 100644
--- a/tests/test_image.py
+++ b/tests/test_image.py
@@ -1,7 +1,7 @@
import pytest
import numpy as np
-from PyQt5.QtGui import QImage, qRgba
-from PyQt5.QtCore import Qt, QByteArray
+from PyQt6.QtGui import QImage, qRgba
+from PyQt6.QtCore import Qt, QByteArray
from PIL import Image as PILImage
from ai_diffusion.image import Mask, Bounds, Extent, Image, ImageCollection
from .config import image_dir, result_dir, reference_dir
@@ -109,8 +109,8 @@ def test_image_from_packed_bytes():
@pytest.mark.skip("Benchmark")
def test_image_compress_speed():
- from PyQt5.QtGui import QImageWriter
- from PyQt5.QtCore import QBuffer, QByteArray, QFile, QIODevice
+ from PyQt6.QtGui import QImageWriter
+ from PyQt6.QtCore import QBuffer, QByteArray, QFile, QIODevice
from timeit import default_timer
img = Image.load("tests/images/beach_1536x1024.webp")
diff --git a/tests/test_properties.py b/tests/test_properties.py
index 78dbc9ef0..9c16e05a4 100644
--- a/tests/test_properties.py
+++ b/tests/test_properties.py
@@ -1,6 +1,6 @@
from enum import Enum
import pytest
-from PyQt5.QtCore import QObject, pyqtSignal
+from PyQt6.QtCore import QObject, pyqtSignal
from ai_diffusion.properties import Property, ObservableProperties, bind, serialize, deserialize
diff --git a/tests/test_server.py b/tests/test_server.py
index e7d1d38e1..d59064e64 100644
--- a/tests/test_server.py
+++ b/tests/test_server.py
@@ -1,6 +1,6 @@
from pathlib import Path
from tempfile import TemporaryDirectory
-from PyQt5.QtNetwork import QNetworkAccessManager
+from PyQt6.QtNetwork import QNetworkAccessManager
import asyncio
import pytest
import shutil
diff --git a/tests/test_updates.py b/tests/test_updates.py
index e540a9624..a802d2ceb 100644
--- a/tests/test_updates.py
+++ b/tests/test_updates.py
@@ -2,7 +2,7 @@
import pytest
from aiohttp import ClientSession
from pathlib import Path
-from PyQt5.QtCore import pyqtBoundSignal
+from PyQt6.QtCore import pyqtBoundSignal
from ai_diffusion.util import ZipFile
from ai_diffusion.updates import AutoUpdate, UpdateState