Merge pull request #1204 from thatfuckingbird/qt6

Qt6 port
This commit is contained in:
Hydrus Network Developer 2022-07-30 16:15:43 -05:00 committed by GitHub
commit 11f59669aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 46 deletions

View File

@ -56,7 +56,7 @@ if not HG.twisted_is_broke:
from twisted.internet import threads, reactor, defer
PubSubEventType = QC.QEvent.Type( QC.QEvent.registerEventType() )
PubSubEventType = QP.registerEventType()
class PubSubEvent( QC.QEvent ):
@ -95,7 +95,7 @@ class PubSubEventCatcher( QC.QObject ):
def MessageHandler( msg_type, context, text ):
if msg_type not in ( QC.QtDebugMsg, QC.QtInfoMsg ):
if msg_type not in ( QC.QtMsgType.QtDebugMsg, QC.QtMsgType.QtInfoMsg ):
# Set a breakpoint here to be able to see where the warnings originate from.
HydrusData.Print( text )
@ -542,7 +542,7 @@ class Controller( HydrusController.HydrusController ):
else:
QP.CallAfter( QW.QApplication.instance().quit )
QP.CallAfter( QW.QApplication.instance().exit )
elif sig == signal.SIGTERM:
@ -2104,7 +2104,7 @@ class Controller( HydrusController.HydrusController ):
self._DestroySplash()
QP.CallAfter( QW.QApplication.quit )
QP.CallAfter( QW.QApplication.exit )
return
@ -2125,7 +2125,7 @@ class Controller( HydrusController.HydrusController ):
self.CleanRunningFile()
QP.CallAfter( QW.QApplication.quit )
QP.CallAfter( QW.QApplication.exit )
except Exception as e:
@ -2200,7 +2200,7 @@ class Controller( HydrusController.HydrusController ):
self._program_is_shut_down = True
QP.CallAfter( QW.QApplication.quit )
QP.CallAfter( QW.QApplication.exit )

View File

@ -692,6 +692,8 @@ class FrameGUI( ClientGUITopLevelWindows.MainFrameThatResizes, CAC.ApplicationCo
library_versions.append( ( 'sqlite', sqlite3.sqlite_version ) )
library_versions.append( ( 'qtpy', qtpy.__version__ ) )
library_versions.append( ( 'Qt', QC.__version__ ) )
if qtpy.PYSIDE2:
@ -705,11 +707,27 @@ class FrameGUI( ClientGUITopLevelWindows.MainFrameThatResizes, CAC.ApplicationCo
elif qtpy.PYQT5:
from PyQt5.Qt import PYQT_VERSION_STR # pylint: disable=E0401,E0611
from sip import SIP_VERSION_STR # pylint: disable=E0401
from PyQt5.sip import SIP_VERSION_STR # pylint: disable=E0401
library_versions.append( ( 'PyQt5', PYQT_VERSION_STR ) )
library_versions.append( ( 'sip', SIP_VERSION_STR ) )
elif qtpy.PYSIDE6:
import PySide6
import shiboken6
library_versions.append( ( 'PySide6', PySide6.__version__ ) )
library_versions.append( ( 'shiboken6', shiboken6.__version__ ) )
elif qtpy.PYQT6:
from PyQt6.QtCore import PYQT_VERSION_STR # pylint: disable=E0401
from PyQt6.sip import SIP_VERSION_STR # pylint: disable=E0401
library_versions.append( ( 'PyQt6', PYQT_VERSION_STR ) )
library_versions.append( ( 'sip', SIP_VERSION_STR ) )
CBOR_AVAILABLE = False
try:
@ -3315,7 +3333,7 @@ class FrameGUI( ClientGUITopLevelWindows.MainFrameThatResizes, CAC.ApplicationCo
ClientGUIMenus.AppendMenuItem( data_actions, 'flush log', 'Command the log to write any buffered contents to hard drive.', HydrusData.DebugPrint, 'Flushing log' )
ClientGUIMenus.AppendMenuItem( data_actions, 'enable truncated image loading', 'Enable the truncated image loading to test out broken jpegs.', self._EnableLoadTruncatedImages )
ClientGUIMenus.AppendSeparator( data_actions )
ClientGUIMenus.AppendMenuItem( data_actions, 'simulate program quit signal', 'Kill the program via a QApplication quit.', QW.QApplication.instance().quit )
ClientGUIMenus.AppendMenuItem( data_actions, 'simulate program exit signal', 'Kill the program via a QApplication exit.', QW.QApplication.instance().exit )
ClientGUIMenus.AppendMenu( debug, data_actions, 'data actions' )

View File

@ -193,7 +193,7 @@ class FileDropTarget( QC.QObject ):
if event.type() == QC.QEvent.Drop:
if self.OnDrop( event.pos().x(), event.pos().y() ):
if self.OnDrop( event.position().toPoint().x(), event.position().toPoint().y() ):
event.setDropAction( self.OnData( event.mimeData(), event.proposedAction() ) )

View File

@ -84,11 +84,11 @@ def ConvertQtImageToNumPy( qt_image: QG.QImage ):
data_bytearray = qt_image.bits()
if QP.qtpy.PYSIDE2:
if QP.qtpy.PYSIDE2 or QP.qtpy.PYSIDE6:
data_bytes = bytes( data_bytearray )
elif QP.qtpy.PYQT5:
elif QP.qtpy.PYQT5 or QP.qtpy.PYQT6:
data_bytes = data_bytearray.asstring( height * width * depth )
@ -162,11 +162,11 @@ def GetDifferentLighterDarkerColour( colour, intensity = 3 ):
def GetDisplayPosition( window ):
return QW.QApplication.desktop().availableGeometry( window ).topLeft()
return window.screen().availableGeometry().topLeft()
def GetDisplaySize( window ):
return QW.QApplication.desktop().availableGeometry( window ).size()
return window.screen().availableGeometry().size()
def GetLighterDarkerColour( colour, intensity = 3 ):

View File

@ -26,16 +26,16 @@ default_numerical_colours[ ClientRatings.MIXED ] = ( ( 0, 0, 0 ), ( 95, 95, 95 )
STAR_COORDS = []
STAR_COORDS.append( QC.QPoint( 6, 0 ) ) # top
STAR_COORDS.append( QC.QPoint( 9, 4 ) )
STAR_COORDS.append( QC.QPoint( 12, 4 ) ) # right
STAR_COORDS.append( QC.QPoint( 9, 8 ) )
STAR_COORDS.append( QC.QPoint( 10, 12 ) ) # bottom right
STAR_COORDS.append( QC.QPoint( 6, 10 ) )
STAR_COORDS.append( QC.QPoint( 2, 12 ) ) # bottom left
STAR_COORDS.append( QC.QPoint( 3, 8 ) )
STAR_COORDS.append( QC.QPoint( 0, 4 ) ) # left
STAR_COORDS.append( QC.QPoint( 3, 4 ) )
STAR_COORDS.append( QC.QPointF( 6, 0 ) ) # top
STAR_COORDS.append( QC.QPointF( 9, 4 ) )
STAR_COORDS.append( QC.QPointF( 12, 4 ) ) # right
STAR_COORDS.append( QC.QPointF( 9, 8 ) )
STAR_COORDS.append( QC.QPointF( 10, 12 ) ) # bottom right
STAR_COORDS.append( QC.QPointF( 6, 10 ) )
STAR_COORDS.append( QC.QPointF( 2, 12 ) ) # bottom left
STAR_COORDS.append( QC.QPointF( 3, 8 ) )
STAR_COORDS.append( QC.QPointF( 0, 4 ) ) # left
STAR_COORDS.append( QC.QPointF( 3, 4 ) )
def DrawLike( painter, x, y, service_key, rating_state ):

View File

@ -86,7 +86,7 @@ class ResizingScrolledPanel( QW.QScrollArea ):
#visible_size = self.widget().visibleRegion().boundingRect().size()
#size_hint = self.widget().sizeHint() + self.size() - visible_size
available_screen_size = QW.QApplication.desktop().availableGeometry( self ).size()
available_screen_size = self.screen().availableGeometry().size()
screen_fill_factor = 0.85 # don't let size hint be bigger than this percentage of the available screen width/height

View File

@ -2,7 +2,7 @@
import os
# If not explicitely set, prefer PySide2 instead of the qtpy default which is PyQt5
# If not explicitly set, prefer PySide2/PySide6 instead of the qtpy default which is PyQt5
# It is important that this runs on startup *before* anything is imported from qtpy.
# Since test.py, client.py and client.pyw all import this module first before any other Qt related ones, this requirement is satisfied.
@ -10,13 +10,21 @@ if not 'QT_API' in os.environ:
try:
import PySide2
import PySide2 # Qt5
os.environ[ 'QT_API' ] = 'pyside2'
except ImportError as e:
pass
try:
import PySide6 # Qt6
os.environ[ 'QT_API' ] = 'pyside6'
except ImportError as e:
pass
#
@ -31,7 +39,7 @@ from collections import defaultdict
if qtpy.PYQT5:
import sip # pylint: disable=E0401
from PyQt5 import sip # pylint: disable=E0401
def isValid( obj ):
@ -42,16 +50,34 @@ if qtpy.PYQT5:
return True
elif qtpy.PYQT6:
from PyQt6 import sip # pylint: disable=E0401
def isValid( obj ):
if isinstance( obj, sip.simplewrapper ):
return not sip.isdeleted( obj )
return True
elif qtpy.PYSIDE2:
import shiboken2
isValid = shiboken2.isValid
elif qtpy.PYSIDE6:
import shiboken6
isValid = shiboken6.isValid
else:
raise RuntimeError( 'You need either PySide2 or PyQt5' )
raise RuntimeError( 'You need one of PySide2, PySide6, PyQt5 or PyQt6' )
from hydrus.core import HydrusConstants as HC
@ -62,7 +88,12 @@ from hydrus.client import ClientConstants as CC
def MonkeyPatchMissingMethods():
if qtpy.PYQT5:
if qtpy.PYQT5 or qtpy.PYSIDE2:
QG.QMouseEvent.globalPosition = lambda self, *args, **kwargs: self.globalPos( *args, **kwargs )
QG.QDropEvent.position = lambda self, *args, **kwargs: self.posF( *args, **kwargs )
if qtpy.PYQT5 or qtpy.PYQT6:
def MonkeyPatchGetSaveFileName( original_function ):
@ -81,7 +112,15 @@ def MonkeyPatchMissingMethods():
QW.QFileDialog.getSaveFileName = MonkeyPatchGetSaveFileName( QW.QFileDialog.getSaveFileName )
def registerEventType():
if qtpy.PYSIDE2 or qtpy.PYSIDE6:
return QC.QEvent.Type( QC.QEvent.registerEventType() )
return QC.QEvent.registerEventType()
class HBoxLayout( QW.QHBoxLayout ):
@ -410,7 +449,7 @@ class TabBar( QW.QTabBar ):
self._last_clicked_tab_index = index
self._last_clicked_global_pos = event.globalPos()
self._last_clicked_global_pos = event.globalPosition()
QW.QTabBar.mousePressEvent( self, event )
@ -483,7 +522,7 @@ class TabBar( QW.QTabBar ):
if 'application/hydrus-tab' not in event.mimeData().formats():
tab_index = self.tabAt( event.pos() )
tab_index = self.tabAt( event.position().toPoint() )
if tab_index != -1:
@ -619,7 +658,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
return
if e.globalPos() == clicked_global_pos:
if e.globalPosition() == clicked_global_pos:
# don't start a drag until movement
@ -655,7 +694,7 @@ class TabWidgetWithDnD( QW.QTabWidget ):
def dragEnterEvent( self, e ):
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.pos() ) ) ):
if self.currentWidget() and self.currentWidget().rect().contains( self.currentWidget().mapFromGlobal( self.mapToGlobal( e.position().toPoint() ) ) ):
return QW.QTabWidget.dragEnterEvent( self, e )
@ -1161,19 +1200,25 @@ def AdjustOpacity( image, opacity_factor ):
def ToKeySequence( modifiers, key ):
if isinstance( modifiers, QC.Qt.KeyboardModifiers ):
if qtpy.PYQT5 or qtpy.PYSIDE2:
seq_str = ''
if isinstance( modifiers, QC.Qt.KeyboardModifiers ):
seq_str = ''
for modifier in [ QC.Qt.ShiftModifier, QC.Qt.ControlModifier, QC.Qt.AltModifier, QC.Qt.MetaModifier, QC.Qt.KeypadModifier, QC.Qt.GroupSwitchModifier ]:
if modifiers & modifier: seq_str += QG.QKeySequence( modifier ).toString()
seq_str += QG.QKeySequence( key ).toString()
return QG.QKeySequence( seq_str )
else: return QG.QKeySequence( key + modifiers )
for modifier in [ QC.Qt.ShiftModifier, QC.Qt.ControlModifier, QC.Qt.AltModifier, QC.Qt.MetaModifier, QC.Qt.KeypadModifier, QC.Qt.GroupSwitchModifier ]:
if modifiers & modifier: seq_str += QG.QKeySequence( modifier ).toString()
seq_str += QG.QKeySequence( key ).toString()
return QG.QKeySequence( seq_str )
else: return QG.QKeySequence( key + modifiers )
else:
return QG.QKeySequence( QC.QKeyCombination( modifiers, key ) )
def AddShortcut( widget, modifier, key, callable, *args ):
@ -1191,7 +1236,7 @@ def GetBackgroundColour( widget ):
return widget.palette().color( QG.QPalette.Window )
CallAfterEventType = QC.QEvent.Type( QC.QEvent.registerEventType() )
CallAfterEventType = registerEventType()
class CallAfterEvent( QC.QEvent ):