From a2ce2d09e444bad85f57d7d79f0dd5aabf8512ca Mon Sep 17 00:00:00 2001 From: Dpeta Date: Fri, 19 Aug 2022 13:12:58 +0200 Subject: [PATCH] PyQt5 fallback --- CHANGELOG.md | 3 +- README.md | 5 +- console.py | 21 ++++++-- convo.py | 54 ++++++++++++------- dataobjs.py | 6 ++- generic.py | 8 ++- irc.py | 10 ++-- logviewer.py | 18 +++++-- memos.py | 48 +++++++++-------- menus.py | 12 +++-- mood.py | 6 ++- ostools.py | 6 ++- parsetools.py | 6 ++- pesterchum.py | 147 ++++++++++++++++++++++++++++---------------------- profile.py | 6 ++- pyquirks.py | 6 ++- randomer.py | 6 ++- setup.py | 6 +-- toast.py | 6 ++- 19 files changed, 248 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 95b3d10..b3d40eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ - Send ping if we haven't received any data from the server in 30 seconds. - Show S3RV3R NOT R3SPOND1NG if the server hasn't responded in 45 seconds. (15 seconds after ping) - Close connection and try to reconnect if the server hasn't responded in 90 seconds. (60 seconds after ping) - + - Fallback to PyQt5. (for Windows 7 users mainly) + ### Fixed - Error when manually moving group. - EOF on send not resulting in a disconnect. diff --git a/README.md b/README.md index 347d384..f3bbfff 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,8 @@ Pesterchum is a Python script. This means that as long as you have Python instal ### REQUIREMENTS - [Python 3] - - [PyQt6] - - On Linux, optionally [pygame] for audio. (QtMultimedia has a [GStreamer] dependency on Linux) + - [PyQt6] or [PyQt5] + - (Linux-specific) [pygame] or [GStreamer] for audio. ### WALKTHROUGH @@ -102,6 +102,7 @@ Pesterchum is a Python script. This means that as long as you have Python instal [Python 3]: https://www.python.org/downloads/ [pip]: https://pypi.org/project/pip/ +[PyQt5]: https://pypi.org/project/PyQt5/ [PyQt6]: https://pypi.org/project/PyQt6/ [pygame]: https://pypi.org/project/pygame/ [GStreamer]: https://gstreamer.freedesktop.org/ diff --git a/console.py b/console.py index 55a8150..18f23be 100644 --- a/console.py +++ b/console.py @@ -9,7 +9,13 @@ import datetime import logging import logging.config -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6.QtGui import QAction +except ImportError: + print("PyQt5 fallback (console.py)") + from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5.QtWidgets import QAction import dataobjs #import generic @@ -448,7 +454,12 @@ class ConsoleText(QtWidgets.QTextEdit): def mousePressEvent(self, event): if event.button() == QtCore.Qt.MouseButton.LeftButton: - url = self.anchorAt(event.position().toPoint()) + if 'PyQt6' in sys.modules: + # PyQt6 + url = self.anchorAt(event.position().toPoint()) + elif 'PyQt5' in sys.modules: + # PyQt5 + url = self.anchorAt(event.pos()) if url != "": # Skip memo/handle recognition # NOTE: Ctrl+Click copies the URL. Maybe it should select it? @@ -463,7 +474,11 @@ class ConsoleText(QtWidgets.QTextEdit): def mouseMoveEvent(self, event): # Change our cursor when we roll over links (anchors). super(ConsoleText, self).mouseMoveEvent(event) - if self.anchorAt(event.position().toPoint()): + if 'PyQt6' in sys.modules: + pos = event.position().toPoint() + elif 'PyQt5' in sys.modules: + pos = event.pos() + if self.anchorAt(pos): if self.viewport().cursor().shape != QtCore.Qt.CursorShape.PointingHandCursor: self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.PointingHandCursor)) else: diff --git a/convo.py b/convo.py index 488a96c..f69bd75 100644 --- a/convo.py +++ b/convo.py @@ -1,10 +1,17 @@ +import sys import logging import logging.config from string import Template from time import strftime from datetime import datetime, timedelta -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6.QtGui import QShortcut, QAction +except ImportError: + print("PyQt5 fallback (convo.py)") + from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5.QtWidgets import QAction, QShortcut import ostools from dataobjs import PesterHistory @@ -33,17 +40,17 @@ class PesterTabWindow(QtWidgets.QFrame): self.tabs.tabMoved[int, int].connect(self.tabMoved) self.shortcuts = AttrDict() - self.shortcuts.tabNext = QtGui.QShortcut( + self.shortcuts.tabNext = QShortcut( QtGui.QKeySequence('Ctrl+j'), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) - self.shortcuts.tabLast = QtGui.QShortcut( + self.shortcuts.tabLast = QShortcut( QtGui.QKeySequence('Ctrl+k'), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) # Note that we use reversed keys here. - self.shortcuts.tabUp = QtGui.QShortcut( + self.shortcuts.tabUp = QShortcut( QtGui.QKeySequence('Ctrl+PgDown'), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) - self.shortcuts.tabDn = QtGui.QShortcut( + self.shortcuts.tabDn = QShortcut( QtGui.QKeySequence('Ctrl+PgUp'), self, context=QtCore.Qt.ShortcutContext.WidgetWithChildrenShortcut) @@ -523,7 +530,10 @@ class PesterText(QtWidgets.QTextEdit): def mousePressEvent(self, event): if event.button() == QtCore.Qt.MouseButton.LeftButton: - url = self.anchorAt(event.position().toPoint()) + if 'PyQt6' in sys.modules: + url = self.anchorAt(event.position().toPoint()) + if 'PyQt5' in sys.modules: + url = self.anchorAt(event.pos()) if url != "": if url[0] == "#" and url != "#pesterchum": self.parent().mainwindow.showMemos(url[1:]) @@ -539,7 +549,11 @@ class PesterText(QtWidgets.QTextEdit): QtWidgets.QTextEdit.mousePressEvent(self, event) def mouseMoveEvent(self, event): QtWidgets.QTextEdit.mouseMoveEvent(self, event) - if self.anchorAt(event.position().toPoint()): + if 'PyQt6' in sys.modules: + pos = event.position().toPoint() + if 'PyQt5' in sys.modules: + pos = event.pos() + if self.anchorAt(pos): if self.viewport().cursor().shape != QtCore.Qt.CursorShape.PointingHandCursor: self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.PointingHandCursor)) else: @@ -627,21 +641,21 @@ class PesterConvo(QtWidgets.QFrame): self.optionsMenu = QtWidgets.QMenu(self) self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"]) - self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self) + self.addChumAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self) self.addChumAction.triggered.connect(self.addThisChum) - self.blockAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self) + self.blockAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self) self.blockAction.triggered.connect(self.blockThisChum) - self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self) + self.quirksOff = QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self) self.quirksOff.setCheckable(True) self.quirksOff.toggled[bool].connect(self.toggleQuirks) - self.oocToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self) + self.oocToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self) self.oocToggle.setCheckable(True) self.oocToggle.toggled[bool].connect(self.toggleOOC) - self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self) + self.unblockchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self) self.unblockchum.triggered.connect(self.unblockChumSlot) - self.reportchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self) + self.reportchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self) self.reportchum.triggered.connect(self.reportThisChum) - self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self) + self.logchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self) self.logchum.triggered.connect(self.openChumLogs) # For this, we'll want to use setChecked to toggle these so they match @@ -654,25 +668,25 @@ class PesterConvo(QtWidgets.QFrame): # Theme support :3c #if self.mainwindow.theme.has_key("main/menus/rclickchumlist/beeponmessage"): try: - self._beepToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/beeponmessage"], self) + self._beepToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/beeponmessage"], self) except: - self._beepToggle = QtGui.QAction("BEEP ON MESSAGE", self) + self._beepToggle = QAction("BEEP ON MESSAGE", self) self._beepToggle.setCheckable(True) self._beepToggle.toggled[bool].connect(self.toggleBeep) #if self.mainwindow.theme.has_key("main/menus/rclickchumlist/flashonmessage"): try: - self._flashToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/flashonmessage"], self) + self._flashToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/flashonmessage"], self) except: - self._flashToggle = QtGui.QAction("FLASH ON MESSAGE", self) + self._flashToggle = QAction("FLASH ON MESSAGE", self) self._flashToggle.setCheckable(True) self._flashToggle.toggled[bool].connect(self.toggleFlash) #if self.mainwindow.theme.has_key("main/menus/rclickchumlist/mutenotifications"): try: - self._muteToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/mutenotifications"], self) + self._muteToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/mutenotifications"], self) except: - self._muteToggle = QtGui.QAction("MUTE NOTIFICATIONS", self) + self._muteToggle = QAction("MUTE NOTIFICATIONS", self) self._muteToggle.setCheckable(True) self._muteToggle.toggled[bool].connect(self.toggleMute) diff --git a/dataobjs.py b/dataobjs.py index 8c85521..ccef5fb 100644 --- a/dataobjs.py +++ b/dataobjs.py @@ -4,7 +4,11 @@ import ostools _datadir = ostools.getDataDir() logging.config.fileConfig(_datadir + "logging.ini") PchumLog = logging.getLogger('pchumLogger') -from PyQt6 import QtGui +try: + from PyQt6 import QtGui +except ImportError: + print("PyQt5 fallback (dataobjs.py)") + from PyQt5 import QtGui from datetime import datetime import re import random diff --git a/generic.py b/generic.py index 7a259d7..f8d79f4 100644 --- a/generic.py +++ b/generic.py @@ -1,4 +1,8 @@ -from PyQt6 import QtGui, QtWidgets +try: + from PyQt6 import QtGui, QtWidgets +except ImportError: + print("PyQt5 fallback (generic.py)") + from PyQt5 import QtGui, QtWidgets from datetime import timedelta class mysteryTime(timedelta): @@ -128,7 +132,7 @@ class MovingWindow(QtWidgets.QFrame): if event.button() == 1: self.moving = event.globalPos() - self.pos() except AttributeError as e: - print("PyQt6 <= 5.14?") + print("PyQt <= 5.14?") print(str(e)) if event.button() == 1: self.moving = event.globalPos() - self.pos() diff --git a/irc.py b/irc.py index e475aec..49521a9 100644 --- a/irc.py +++ b/irc.py @@ -5,7 +5,11 @@ import random import time import json -from PyQt6 import QtCore, QtGui +try: + from PyQt6 import QtCore, QtGui +except ImportError: + print("PyQt5 fallback (irc.py)") + from PyQt5 import QtCore, QtGui import ostools from mood import Mood @@ -342,8 +346,8 @@ class PesterIRC(QtCore.QThread): @QtCore.pyqtSlot() def pingServer(self): try: - self.cli.send("PING :B33") - #self.cli.send("PING %s" % int(time.time())) + if hasattr(self, 'cli'): + self.cli.send("PING :B33") except OSError as e: PchumLog.warning(e) self.setConnectionBroken() diff --git a/logviewer.py b/logviewer.py index 5b0adcf..155588b 100644 --- a/logviewer.py +++ b/logviewer.py @@ -1,9 +1,14 @@ import os +import sys import codecs import re import ostools from time import strftime, strptime -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets +except ImportError: + print("PyQt5 fallback (logviewer.py)") + from PyQt5 import QtCore, QtGui, QtWidgets from generic import RightClickList, RightClickTree from parsetools import convertTags from convo import PesterText @@ -272,7 +277,10 @@ class PesterLogText(PesterText): def focusInEvent(self, event): QtWidgets.QTextEdit.focusInEvent(self, event) def mousePressEvent(self, event): - url = self.anchorAt(event.position().toPoint()) + if 'PyQt6' in sys.modules: + url = self.anchorAt(event.position().toPoint()) + if 'PyQt5' in sys.modules: + url = self.anchorAt(event.pos()) if url != "": if url[0] == "#" and url != "#pesterchum": self.parent().parent.showMemos(url[1:]) @@ -284,7 +292,11 @@ class PesterLogText(PesterText): QtWidgets.QTextEdit.mousePressEvent(self, event) def mouseMoveEvent(self, event): QtWidgets.QTextEdit.mouseMoveEvent(self, event) - if self.anchorAt(event.position().toPoint()): + if 'PyQt6' in sys.modules: + pos = event.position().toPoint() + if 'PyQt5' in sys.modules: + pos = event.pos() + if self.anchorAt(pos): if self.viewport().cursor().shape != QtCore.Qt.CursorShape.PointingHandCursor: self.viewport().setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.PointingHandCursor)) else: diff --git a/memos.py b/memos.py index 1e3f18b..1d879b4 100644 --- a/memos.py +++ b/memos.py @@ -4,7 +4,13 @@ import re from string import Template from datetime import timedelta, datetime -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6.QtGui import QAction +except ImportError: + print("PyQt5 fallback (memos.py)") + from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5.QtWidgets import QAction import ostools import parsetools @@ -418,17 +424,17 @@ class PesterMemo(PesterConvo): self.userlist.setSizePolicy(QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Expanding)) self.userlist.optionsMenu = QtWidgets.QMenu(self) - self.pesterChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) + self.pesterChumAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) self.pesterChumAction.triggered.connect(self.newPesterSlot) - self.addchumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self) + self.addchumAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self) self.addchumAction.triggered.connect(self.addChumSlot) - self.banuserAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self) + self.banuserAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/banuser"], self) self.banuserAction.triggered.connect(self.banSelectedUser) - self.opAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self) + self.opAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/opuser"], self) self.opAction.triggered.connect(self.opSelectedUser) - self.voiceAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/voiceuser"], self) + self.voiceAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/voiceuser"], self) self.voiceAction.triggered.connect(self.voiceSelectedUser) - self.quirkDisableAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirkkill"], self) + self.quirkDisableAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirkkill"], self) self.quirkDisableAction.triggered.connect(self.killQuirkUser) self.userlist.optionsMenu.addAction(self.pesterChumAction) self.userlist.optionsMenu.addAction(self.addchumAction) @@ -437,38 +443,38 @@ class PesterMemo(PesterConvo): self.optionsMenu = QtWidgets.QMenu(self) self.optionsMenu.setStyleSheet(self.mainwindow.theme["main/defaultwindow/style"]) # So it doesn't inherit the memo's background image. # Fixes floating "PESTERLOG:" - self.oocToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self) + self.oocToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/ooc"], self) self.oocToggle.setCheckable(True) self.oocToggle.toggled[bool].connect(self.toggleOOC) - self.quirksOff = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self) + self.quirksOff = QAction(self.mainwindow.theme["main/menus/rclickchumlist/quirksoff"], self) self.quirksOff.setCheckable(True) self.quirksOff.toggled[bool].connect(self.toggleQuirks) - self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self) + self.logchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self) self.logchum.triggered.connect(self.openChumLogs) - self.invitechum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/invitechum"], self) + self.invitechum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/invitechum"], self) self.invitechum.triggered.connect(self.inviteChums) #if self.mainwindow.theme.has_key("main/menus/rclickchumlist/beeponmessage"): try: - self._beepToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/beeponmessage"], self) + self._beepToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/beeponmessage"], self) except: - self._beepToggle = QtGui.QAction("BEEP ON MESSAGE", self) + self._beepToggle = QAction("BEEP ON MESSAGE", self) self._beepToggle.setCheckable(True) self._beepToggle.toggled[bool].connect(self.toggleBeep) #if self.mainwindow.theme.has_key("main/menus/rclickchumlist/flashonmessage"): try: - self._flashToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/flashonmessage"], self) + self._flashToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/flashonmessage"], self) except: - self._flashToggle = QtGui.QAction("FLASH ON MESSAGE", self) + self._flashToggle = QAction("FLASH ON MESSAGE", self) self._flashToggle.setCheckable(True) self._flashToggle.toggled[bool].connect(self.toggleFlash) #if self.mainwindow.theme.has_key("main/menus/rclickchumlist/mutenotifications"): try: - self._muteToggle = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/mutenotifications"], self) + self._muteToggle = QAction(self.mainwindow.theme["main/menus/rclickchumlist/mutenotifications"], self) except: - self._muteToggle = QtGui.QAction("MUTE NOTIFICATIONS", self) + self._muteToggle = QAction("MUTE NOTIFICATIONS", self) self._muteToggle.setCheckable(True) self._muteToggle.toggled[bool].connect(self.toggleMute) @@ -483,16 +489,16 @@ class PesterMemo(PesterConvo): self.optionsMenu.addAction(self.invitechum) self.chanModeMenu = QtWidgets.QMenu(self.mainwindow.theme["main/menus/rclickchumlist/memosetting"], self) - self.chanNoquirks = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/memonoquirk"], self) + self.chanNoquirks = QAction(self.mainwindow.theme["main/menus/rclickchumlist/memonoquirk"], self) self.chanNoquirks.setCheckable(True) self.chanNoquirks.toggled[bool].connect(self.noquirksChan) - self.chanHide = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/memohidden"], self) + self.chanHide = QAction(self.mainwindow.theme["main/menus/rclickchumlist/memohidden"], self) self.chanHide.setCheckable(True) self.chanHide.toggled[bool].connect(self.hideChan) - self.chanInvite = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/memoinvite"], self) + self.chanInvite = QAction(self.mainwindow.theme["main/menus/rclickchumlist/memoinvite"], self) self.chanInvite.setCheckable(True) self.chanInvite.toggled[bool].connect(self.inviteChan) - self.chanMod = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/memomute"], self) + self.chanMod = QAction(self.mainwindow.theme["main/menus/rclickchumlist/memomute"], self) self.chanMod.setCheckable(True) self.chanMod.toggled[bool].connect(self.modChan) self.chanModeMenu.addAction(self.chanNoquirks) diff --git a/menus.py b/menus.py index d5eced6..1b1702f 100644 --- a/menus.py +++ b/menus.py @@ -1,7 +1,13 @@ import re from os import remove -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6.QtGui import QAction +except ImportError: + print("PyQt5 fallback (menus.py)") + from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5.QtWidgets import QAction import ostools import parsetools @@ -1558,9 +1564,9 @@ class PesterUserlist(QtWidgets.QDialog): self.userarea.setStyleSheet(self.theme["main/chums/style"]) self.userarea.optionsMenu = QtWidgets.QMenu(self) - self.addChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self) + self.addChumAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/addchum"], self) self.addChumAction.triggered.connect(self.addChumSlot) - self.pesterChumAction = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) + self.pesterChumAction = QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) self.pesterChumAction.triggered.connect(self.pesterChumSlot) self.userarea.optionsMenu.addAction(self.addChumAction) self.userarea.optionsMenu.addAction(self.pesterChumAction) diff --git a/mood.py b/mood.py index 587fb55..e5c05dc 100644 --- a/mood.py +++ b/mood.py @@ -1,4 +1,8 @@ -from PyQt6 import QtCore, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets +except ImportError: + print("PyQt5 fallback (mood.py)") + from PyQt5 import QtCore, QtGui, QtWidgets from generic import PesterIcon diff --git a/ostools.py b/ostools.py index d3b00a2..b6c9d07 100644 --- a/ostools.py +++ b/ostools.py @@ -2,7 +2,11 @@ import os import sys import platform -from PyQt6.QtCore import QStandardPaths +try: + from PyQt6.QtCore import QStandardPaths +except ImportError: + print("PyQt5 fallback (ostools.py)") + from PyQt5.QtCore import QStandardPaths def isOSX(): return sys.platform == "darwin" diff --git a/parsetools.py b/parsetools.py index 942980b..074772f 100644 --- a/parsetools.py +++ b/parsetools.py @@ -5,7 +5,11 @@ import collections from copy import copy from datetime import timedelta -from PyQt6 import QtGui, QtWidgets +try: + from PyQt6 import QtGui, QtWidgets +except ImportError: + print("PyQt5 fallback (parsetools.py)") + from PyQt5 import QtGui, QtWidgets import dataobjs import ostools diff --git a/pesterchum.py b/pesterchum.py index ddb634a..8dacc5a 100644 --- a/pesterchum.py +++ b/pesterchum.py @@ -37,18 +37,24 @@ import time import json from pnc.dep.attrdict import AttrDict -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6.QtGui import QShortcut, QAction, QActionGroup +except ImportError: + print("PyQt5 fallback (pesterchum.py)") + from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5.QtWidgets import QAction, QShortcut, QActionGroup -vnum = QtCore.qVersion() -major = int(vnum[:vnum.find(".")]) -if vnum.find(".", vnum.find(".")+1) != -1: - minor = int(vnum[vnum.find(".")+1:vnum.find(".", vnum.find(".")+1)]) -else: - minor = int(vnum[vnum.find(".")+1:]) -if (major < 6) or ((major > 6) and (minor < 2)): - print("ERROR: Pesterchum requires at least Qt version >= 6.2") - print("You currently have version " + str(vnum) + ". Please upgrade Qt.") - sys.exit() +#vnum = QtCore.qVersion() +#major = int(vnum[:vnum.find(".")]) +#if vnum.find(".", vnum.find(".")+1) != -1: +# minor = int(vnum[vnum.find(".")+1:vnum.find(".", vnum.find(".")+1)]) +#else: +# minor = int(vnum[vnum.find(".")+1:]) +#if (major < 6) or ((major > 6) and (minor < 2)): +# print("ERROR: Pesterchum requires at least Qt version >= 6.2") +# print("You currently have version " + str(vnum) + ". Please upgrade Qt.") +# sys.exit() import ostools # Placed here before importing the rest of pesterchum, since bits of it need @@ -389,23 +395,23 @@ class chumArea(RightClickTree): self.groupMenu = QtWidgets.QMenu(self) self.canonMenu = QtWidgets.QMenu(self) self.optionsMenu = QtWidgets.QMenu(self) - self.pester = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) + self.pester = QAction(self.mainwindow.theme["main/menus/rclickchumlist/pester"], self) self.pester.triggered.connect(self.activateChum) - self.removechum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removechum"], self) + self.removechum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/removechum"], self) self.removechum.triggered.connect(self.removeChum) - self.blockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self) + self.blockchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/blockchum"], self) self.blockchum.triggered.connect(self.blockChum) - self.logchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self) + self.logchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/viewlog"], self) self.logchum.triggered.connect(self.openChumLogs) - self.reportchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self) + self.reportchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/report"], self) self.reportchum.triggered.connect(self.reportChum) - self.findalts = QtGui.QAction("Find Alts", self) + self.findalts = QAction("Find Alts", self) self.findalts.triggered.connect(self.findAlts) - self.removegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/removegroup"], self) + self.removegroup = QAction(self.mainwindow.theme["main/menus/rclickchumlist/removegroup"], self) self.removegroup.triggered.connect(self.removeGroup) - self.renamegroup = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/renamegroup"], self) + self.renamegroup = QAction(self.mainwindow.theme["main/menus/rclickchumlist/renamegroup"], self) self.renamegroup.triggered.connect(self.renameGroup) - self.notes = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/notes"], self) + self.notes = QAction(self.mainwindow.theme["main/menus/rclickchumlist/notes"], self) self.notes.triggered.connect(self.editNotes) self.optionsMenu.addAction(self.pester) @@ -509,14 +515,20 @@ class chumArea(RightClickTree): if thisitem.rfind(" (") != -1: thisitem = thisitem[0:thisitem.rfind(" (")] if thisitem == "Chums" or thisitem in self.groups: - droppos = self.itemAt(event.position().toPoint()) + if 'PyQt6' in sys.modules: + droppos = self.itemAt(event.position().toPoint()) + elif 'PyQt5' in sys.modules: + droppos = self.itemAt(event.pos()) if not droppos: return droppos = str(droppos.text(0)) if droppos.rfind(" ") != -1: droppos = droppos[0:droppos.rfind(" ")] if droppos == "Chums" or droppos in self.groups: saveOpen = event.source().currentItem().isExpanded() - saveDrop = self.itemAt(event.position().toPoint()) + if 'PyQt6' in sys.modules: + saveDrop = self.itemAt(event.position().toPoint()) + if 'PyQt5' in sys.modules: + saveDrop = self.itemAt(event.pos()) saveItem = self.takeTopLevelItem(self.indexOfTopLevelItem(event.source().currentItem())) self.insertTopLevelItems(self.indexOfTopLevelItem(saveDrop)+1, [saveItem]) if saveOpen: @@ -531,7 +543,10 @@ class chumArea(RightClickTree): self.mainwindow.config.saveGroups(gTemp) # Drop item is a chum else: - eventpos = event.position().toPoint() + if 'PyQt6' in sys.modules: + eventpos = event.position().toPoint() + if 'PyQt5' in sys.modules: + eventpos = event.pos() item = self.itemAt(eventpos) if item: text = str(item.text(0)) @@ -584,7 +599,7 @@ class chumArea(RightClickTree): text = text[0:text.rfind(" (")] currentGroup = text self.moveMenu.clear() - actGroup = QtGui.QActionGroup(self) + actGroup = QActionGroup(self) groups = self.groups[:] for gtext in groups: @@ -592,7 +607,7 @@ class chumArea(RightClickTree): continue movegroup = self.moveMenu.addAction(gtext) actGroup.addAction(movegroup) - actGroup.triggered[QtGui.QAction].connect(self.moveToGroup) + actGroup.triggered[QAction].connect(self.moveToGroup) def addChum(self, chum): if len([c for c in self.chums if c.handle == chum.handle]) != 0: @@ -1029,7 +1044,7 @@ class chumArea(RightClickTree): self.takeItem(chumLabel) self.addItem(chumLabel) self.takeTopLevelItem(i) - @QtCore.pyqtSlot(QtGui.QAction) + @QtCore.pyqtSlot(QAction) def moveToGroup(self, item): if not item: return @@ -1071,7 +1086,7 @@ class trollSlum(chumArea): self.setIndentation(0) self.optionsMenu = QtWidgets.QMenu(self) - self.unblockchum = QtGui.QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self) + self.unblockchum = QAction(self.mainwindow.theme["main/menus/rclickchumlist/unblockchum"], self) self.unblockchum.triggered.connect(self.unblockChumSignal) self.optionsMenu.addAction(self.unblockchum) @@ -1284,35 +1299,35 @@ class PesterWindow(MovingWindow): self.move(100, 100) - talk = QtGui.QAction(self.theme["main/menus/client/talk"], self) + talk = QAction(self.theme["main/menus/client/talk"], self) self.talk = talk talk.triggered.connect(self.openChat) - logv = QtGui.QAction(self.theme["main/menus/client/logviewer"], self) + logv = QAction(self.theme["main/menus/client/logviewer"], self) self.logv = logv logv.triggered.connect(self.openLogv) - grps = QtGui.QAction(self.theme["main/menus/client/addgroup"], self) + grps = QAction(self.theme["main/menus/client/addgroup"], self) self.grps = grps grps.triggered.connect(self.addGroupWindow) - self.rand = QtGui.QAction(self.theme["main/menus/client/randen"], self) + self.rand = QAction(self.theme["main/menus/client/randen"], self) self.rand.triggered.connect(self.randhandler.getEncounter) - opts = QtGui.QAction(self.theme["main/menus/client/options"], self) + opts = QAction(self.theme["main/menus/client/options"], self) self.opts = opts opts.triggered.connect(self.openOpts) - exitaction = QtGui.QAction(self.theme["main/menus/client/exit"], self) + exitaction = QAction(self.theme["main/menus/client/exit"], self) self.exitaction = exitaction exitaction.triggered.connect(self.killApp, QtCore.Qt.ConnectionType.QueuedConnection) - userlistaction = QtGui.QAction(self.theme["main/menus/client/userlist"], self) + userlistaction = QAction(self.theme["main/menus/client/userlist"], self) self.userlistaction = userlistaction userlistaction.triggered.connect(self.showAllUsers) - memoaction = QtGui.QAction(self.theme["main/menus/client/memos"], self) + memoaction = QAction(self.theme["main/menus/client/memos"], self) self.memoaction = memoaction memoaction.triggered.connect(self.showMemos) - self.importaction = QtGui.QAction(self.theme["main/menus/client/import"], self) + self.importaction = QAction(self.theme["main/menus/client/import"], self) self.importaction.triggered.connect(self.importExternalConfig) - self.idleaction = QtGui.QAction(self.theme["main/menus/client/idle"], self) + self.idleaction = QAction(self.theme["main/menus/client/idle"], self) self.idleaction.setCheckable(True) self.idleaction.toggled[bool].connect(self.toggleIdle) - self.reconnectAction = QtGui.QAction(self.theme["main/menus/client/reconnect"], self) + self.reconnectAction = QAction(self.theme["main/menus/client/reconnect"], self) self.reconnectAction.triggered.connect(self.disconnectIRC) self.menu = QtWidgets.QMenuBar(self) @@ -1322,19 +1337,19 @@ class PesterWindow(MovingWindow): if self.theme.has_key("main/menus/client/console"): self.console = AttrDict(dict( window = None, - action = QtGui.QAction(self.theme["main/menus/client/console"], self), + action = QAction(self.theme["main/menus/client/console"], self), is_open = False )) else: self.console = AttrDict(dict( window = None, - action = QtGui.QAction("Console", self), + action = QAction("Console", self), is_open = False )) self.console.shortcuts = AttrDict(dict( - conkey = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+`"), self, + conkey = QShortcut(QtGui.QKeySequence("Ctrl+`"), self, context=QtCore.Qt.ShortcutContext.ApplicationShortcut), - curwgt = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+Alt+w"), self, + curwgt = QShortcut(QtGui.QKeySequence("Ctrl+Alt+w"), self, context=QtCore.Qt.ShortcutContext.ApplicationShortcut) )) self.console.action.triggered.connect(self.toggleConsole) @@ -1367,18 +1382,18 @@ class PesterWindow(MovingWindow): filemenu.addAction(self.reconnectAction) filemenu.addAction(exitaction) - changequirks = QtGui.QAction(self.theme["main/menus/profile/quirks"], self) + changequirks = QAction(self.theme["main/menus/profile/quirks"], self) self.changequirks = changequirks changequirks.triggered.connect(self.openQuirks) - loadslum = QtGui.QAction(self.theme["main/menus/profile/block"], self) + loadslum = QAction(self.theme["main/menus/profile/block"], self) self.loadslum = loadslum loadslum.triggered.connect(self.showTrollSlum) - changecoloraction = QtGui.QAction(self.theme["main/menus/profile/color"], self) + changecoloraction = QAction(self.theme["main/menus/profile/color"], self) self.changecoloraction = changecoloraction changecoloraction.triggered.connect(self.changeMyColor) - switch = QtGui.QAction(self.theme["main/menus/profile/switch"], self) + switch = QAction(self.theme["main/menus/profile/switch"], self) self.switch = switch switch.triggered.connect(self.switchProfile) @@ -1389,27 +1404,27 @@ class PesterWindow(MovingWindow): profilemenu.addAction(changecoloraction) profilemenu.addAction(switch) - self.helpAction = QtGui.QAction(self.theme["main/menus/help/help"], self) + self.helpAction = QAction(self.theme["main/menus/help/help"], self) self.helpAction.triggered.connect(self.launchHelp) - self.botAction = QtGui.QAction(self.theme["main/menus/help/calsprite"], self) + self.botAction = QAction(self.theme["main/menus/help/calsprite"], self) self.botAction.triggered.connect(self.loadCalsprite) - self.nickServAction = QtGui.QAction(self.theme["main/menus/help/nickserv"], self) + self.nickServAction = QAction(self.theme["main/menus/help/nickserv"], self) self.nickServAction.triggered.connect(self.loadNickServ) - self.chanServAction = QtGui.QAction(self.theme["main/menus/help/chanserv"], self) + self.chanServAction = QAction(self.theme["main/menus/help/chanserv"], self) self.chanServAction.triggered.connect(self.loadChanServ) - self.aboutAction = QtGui.QAction(self.theme["main/menus/help/about"], self) + self.aboutAction = QAction(self.theme["main/menus/help/about"], self) self.aboutAction.triggered.connect(self.aboutPesterchum) # Because I can't expect all themes to have this included. #if self.theme.has_key("main/menus/help/reportbug"): try: - self.reportBugAction = QtGui.QAction(self.theme["main/menus/help/reportbug"], self) + self.reportBugAction = QAction(self.theme["main/menus/help/reportbug"], self) except: - self.reportBugAction = QtGui.QAction("REPORT BUG", self) + self.reportBugAction = QAction("REPORT BUG", self) try: - self.xyzRulesAction = QtGui.QAction(self.theme["main/menus/help/rules"], self) + self.xyzRulesAction = QAction(self.theme["main/menus/help/rules"], self) except: - self.xyzRulesAction = QtGui.QAction("RULES", self) + self.xyzRulesAction = QAction("RULES", self) self.reportBugAction.triggered.connect(self.reportBug) self.xyzRulesAction.triggered.connect(self.xyzRules) @@ -1498,11 +1513,6 @@ class PesterWindow(MovingWindow): self.pcUpdate['QString', 'QString'].connect(self.updateMsg) - self.pingtimer = QtCore.QTimer() - self.pingtimer.timeout.connect(self.checkPing) - self.sincerecv = 0 # Time since last recv - self.pingtimer.start(1000*15) # time in ms - self.mychumhandleLabel.adjustSize() # Required so "CHUMHANDLE:" regardless of style-sheet. self.moodsLabel.adjustSize() # Required so "MOOD:" regardless of style-sheet. @@ -1518,6 +1528,11 @@ class PesterWindow(MovingWindow): self.sendNotice.emit(code, RANDNICK) except: PchumLog.warning("No randomEncounter set in userconfig?") + + # Client --> Server pings + self.pingtimer = QtCore.QTimer() + self.pingtimer.timeout.connect(self.checkPing) + self.sincerecv = 0 # Time since last recv @QtCore.pyqtSlot(QString, QString) def updateMsg(self, ver, url): @@ -2245,6 +2260,12 @@ class PesterWindow(MovingWindow): self.doAutoIdentify() self.doAutoJoins() + # Start client --> server pings + if hasattr(self, 'pingtimer') == False: + self.pingtimer.start(1000*15) # time in ms + else: + self.pingtimer.start(1000*15) + @QtCore.pyqtSlot() def blockSelectedChum(self): curChumListing = self.chumList.currentItem() @@ -3774,14 +3795,14 @@ class MainProgram(QtCore.QObject): moodCategories[k] = moodMenu.addMenu(k.upper()) self.moodactions = {} for (i,m) in enumerate(Mood.moods): - maction = QtGui.QAction(m.upper(), self) + maction = QAction(m.upper(), self) mobj = PesterMoodAction(i, self.widget.moods.updateMood) maction.triggered.connect(mobj.updateMood) self.moodactions[i] = mobj moodCategories[Mood.revmoodcats[m]].addAction(maction) - miniAction = QtGui.QAction("MINIMIZE", self) + miniAction = QAction("MINIMIZE", self) miniAction.triggered.connect(self.widget.showMinimized) - exitAction = QtGui.QAction("EXIT", self) + exitAction = QAction("EXIT", self) exitAction.triggered.connect(self.widget.killApp, QtCore.Qt.ConnectionType.QueuedConnection) self.traymenu.addAction(miniAction) self.traymenu.addAction(exitAction) diff --git a/profile.py b/profile.py index d0ee6d9..408c35e 100644 --- a/profile.py +++ b/profile.py @@ -11,7 +11,11 @@ from string import Template from datetime import datetime from time import strftime -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets +except ImportError: + print("PyQt5 fallback (profile.py)") + from PyQt5 import QtCore, QtGui, QtWidgets import ostools from mood import Mood diff --git a/pyquirks.py b/pyquirks.py index 8b0777d..a516063 100644 --- a/pyquirks.py +++ b/pyquirks.py @@ -2,7 +2,11 @@ import logging import logging.config import importlib.util -from PyQt6 import QtWidgets +try: + from PyQt6 import QtWidgets +except ImportError: + print("PyQt5 fallback (pyquirks.py)") + from PyQt5 import QtWidgets import ostools from quirks import ScriptQuirks diff --git a/randomer.py b/randomer.py index 40c375d..2f947d8 100644 --- a/randomer.py +++ b/randomer.py @@ -1,7 +1,11 @@ import logging import logging.config -from PyQt6 import QtCore, QtWidgets +try: + from PyQt6 import QtCore, QtWidgets +except ImportError: + print("PyQt5 fallback (randomer.py)") + from PyQt5 import QtCore, QtWidgets import ostools diff --git a/setup.py b/setup.py index 04036bd..c082d20 100644 --- a/setup.py +++ b/setup.py @@ -35,9 +35,9 @@ includefiles = ["quirks", "PCskins.png", "Pesterchum.png"] build_exe_options = { - "includes": ['PyQt6.QtCore', - 'PyQt6.QtGui', - 'PyQt6.QtWidgets'], +# "includes": ['PyQt6.QtCore', +# 'PyQt6.QtGui', +# 'PyQt6.QtWidgets'], "excludes": ['collections.sys', 'collections._sre', 'collections._json', diff --git a/toast.py b/toast.py index a01f742..8a9b391 100644 --- a/toast.py +++ b/toast.py @@ -4,7 +4,11 @@ import inspect import logging import logging.config -from PyQt6 import QtCore, QtGui, QtWidgets +try: + from PyQt6 import QtCore, QtGui, QtWidgets +except ImportError: + print("PyQt5 fallback (toast.py)") + from PyQt5 import QtCore, QtGui, QtWidgets import ostools