From aea48bf8e53a90e30ca7223b0c4d4536ec1aae2e Mon Sep 17 00:00:00 2001 From: Milan Nikolic Date: Thu, 10 Oct 2024 23:33:51 +0200 Subject: [PATCH] Migrate to Qt6 --- README.rst | 6 +- bin/m64py | 14 ++- dist/debian/control | 12 +- dist/debian/m64py.6 | 2 +- dist/macosx/m64py.spec | 2 +- dist/redhat/build.sh | 2 +- dist/redhat/m64py.spec.in | 4 +- dist/windows/m64py.iss.in | 2 +- dist/windows/m64py.spec | 2 +- requirements.txt | 2 +- setup.py | 87 ++++++-------- src/m64py/core/defs.py | 2 +- src/m64py/core/vidext.py | 26 ++-- src/m64py/frontend/cheat.py | 46 +++----- src/m64py/frontend/dialogs.py | 16 +-- src/m64py/frontend/glwidget.py | 39 +----- src/m64py/frontend/input.py | 3 +- src/m64py/frontend/joystick.py | 4 +- src/m64py/frontend/keymap.py | 190 +++++++++++++++--------------- src/m64py/frontend/log.py | 12 +- src/m64py/frontend/mainwindow.py | 78 ++++++++---- src/m64py/frontend/plugin.py | 14 +-- src/m64py/frontend/recentfiles.py | 5 +- src/m64py/frontend/rominfo.py | 2 +- src/m64py/frontend/romlist.py | 24 ++-- src/m64py/frontend/romreader.py | 10 +- src/m64py/frontend/settings.py | 16 +-- src/m64py/frontend/worker.py | 2 +- src/m64py/ui/about.ui | 123 ++++++++++--------- src/m64py/ui/cheat.ui | 31 ++--- src/m64py/ui/imageview.py | 6 +- src/m64py/ui/inputbutton.py | 12 +- 32 files changed, 378 insertions(+), 418 deletions(-) diff --git a/README.rst b/README.rst index 12bd501..7385f3e 100644 --- a/README.rst +++ b/README.rst @@ -13,7 +13,7 @@ About ===== -M64Py is a Qt5 front-end (GUI) for Mupen64Plus, a cross-platform +M64Py is a Qt6 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator. Front-end is written in Python and it provides a user-friendly interface over the Mupen64Plus shared library. @@ -32,14 +32,14 @@ Features Dependencies ============ -* `PyQt5 `_ (QtCore, QtGui, QtWidgets, QtOpenGL) +* `PyQt6 `_ (QtCore, QtGui, QtWidgets) * `PySDL2 `_ Ubuntu ++++++ -``sudo apt install libsdl2-dev qttools5-dev-tools pyqt5-dev-tools python3-pyqt5 python3-pyqt5.qtopengl`` +``sudo apt install libsdl2-dev qttools6-dev-tools pyqt6-dev-tools python3-pyqt6`` PyPi ++++ diff --git a/bin/m64py b/bin/m64py index b14c088..4f52b77 100755 --- a/bin/m64py +++ b/bin/m64py @@ -28,10 +28,10 @@ if os.path.isdir(os.path.join("..", "src")) and os.path.isfile( os.environ["DBUS_FATAL_WARNINGS"] = "0" try: - from PyQt5.QtWidgets import QApplication - from PyQt5.QtCore import Qt, QLocale, QTranslator + from PyQt6.QtWidgets import QApplication + from PyQt6.QtCore import Qt, QLocale, QTranslator except ImportError as err: - sys.stderr.write("This application needs PyQt5 module%sError:%s%s" % ( + sys.stderr.write("This application needs PyQt6 module%sError:%s%s" % ( os.linesep, str(err), os.linesep)) sys.exit(1) @@ -42,6 +42,12 @@ except ImportError as err: os.linesep, str(err), os.linesep)) sys.exit(1) +try: + from m64py.ui import i18n_rc +except ImportError: + sys.stderr.write("You have to run setup.py build first\n") + sys.exit(1) + def handle_exception(exc_type, exc_value, exc_traceback): if issubclass(exc_type, KeyboardInterrupt): return @@ -73,6 +79,6 @@ if __name__ == "__main__": signal.signal(signal.SIGINT, signal.SIG_DFL) except AttributeError: pass - sys.exit(app.exec_()) + sys.exit(app.exec()) except KeyboardInterrupt: pass diff --git a/dist/debian/control b/dist/debian/control index 57fde7c..2973f55 100644 --- a/dist/debian/control +++ b/dist/debian/control @@ -12,8 +12,8 @@ Build-Depends: debhelper (>= 9), dh-python, python3, - python3-pyqt5, - pyqt5-dev-tools, + python3-pyqt6, + pyqt6-dev-tools, X-Python3-Version: >= 3.4 Package: m64py @@ -29,10 +29,8 @@ Depends: mupen64plus-input-all | mupen64plus-input, mupen64plus-rsp-all | mupen64plus-rsp, mupen64plus-video-all | mupen64plus-video, - python3-opengl, - python3-pyqt5, - python3-pyqt5.qtopengl, - python3-pyqt5.qtsvg, + python3-pyqt6, + python3-pyqt6.qtsvg, python3-sdl2, Provides: mupen64plus-ui, @@ -41,7 +39,7 @@ Recommends: python3-lzma | p7zip, unrar, Description: Python based graphical frontend for mupen64plus - M64Py is a Qt5 front-end (GUI) for Mupen64Plus, a cross-platform + M64Py is a Qt6 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator. M64Py is written in Python and it provides a user-friendly interface over Mupen64Plus shared library. . diff --git a/dist/debian/m64py.6 b/dist/debian/m64py.6 index d574fa8..c04bd93 100644 --- a/dist/debian/m64py.6 +++ b/dist/debian/m64py.6 @@ -28,7 +28,7 @@ m64py \- Mupen64plus frontend .B m64py [\fIoptions\fP] .br .SH DESCRIPTION -m64py is a graphical Qt5 frontend for the Nintendo64 emulator mupen64plus +m64py is a graphical Qt6 frontend for the Nintendo64 emulator mupen64plus .PP .PP .SH OPTIONS diff --git a/dist/macosx/m64py.spec b/dist/macosx/m64py.spec index ee7bef5..a9299a0 100644 --- a/dist/macosx/m64py.spec +++ b/dist/macosx/m64py.spec @@ -5,7 +5,7 @@ DIST_DIR = os.environ["DIST_DIR"] BASE_DIR = os.environ["BASE_DIR"] a = Analysis([join(BASE_DIR, 'm64py')], pathex=[join(BASE_DIR, 'src')], - hiddenimports=['pickle', 'PyQt5.Qt'], + hiddenimports=['pickle', 'PyQt6.Qt'], hookspath=None, runtime_hooks=None) diff --git a/dist/redhat/build.sh b/dist/redhat/build.sh index af61caf..5dfe900 100755 --- a/dist/redhat/build.sh +++ b/dist/redhat/build.sh @@ -1,5 +1,5 @@ #!/bin/sh -yum install rpm-build PyQt5-devel -y +yum install rpm-build PyQt6-devel -y VERSION=`cat ../../src/m64py/core/defs.py | grep FRONTEND_VERSION | awk -F' = ' '{print $2}' | tr -d '"'` sed "s/{VERSION}/$VERSION/g" m64py.spec.in > m64py.spec cd ../../ && python setup.py sdist diff --git a/dist/redhat/m64py.spec.in b/dist/redhat/m64py.spec.in index ecb159d..2243614 100644 --- a/dist/redhat/m64py.spec.in +++ b/dist/redhat/m64py.spec.in @@ -15,10 +15,10 @@ Prefix: %{_prefix} BuildArch: noarch Vendor: Milan Nikolic Url: http://m64py.sourceforge.net -Requires: PyQt5 PySDL2 +Requires: PyQt6 PySDL2 %description -M64Py is a Qt5 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator. +M64Py is a Qt6 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator. %prep %setup -n %{name}-%{unmangled_version} diff --git a/dist/windows/m64py.iss.in b/dist/windows/m64py.iss.in index 59d07a7..2e42317 100644 --- a/dist/windows/m64py.iss.in +++ b/dist/windows/m64py.iss.in @@ -32,7 +32,7 @@ Source: "m64py\*.zip"; DestDir: "{app}"; Source: "m64py\*.v64"; DestDir: "{app}"; Source: "m64py\*.pyd"; DestDir: "{app}"; Source: "m64py\doc\*"; DestDir: "{app}\doc"; -Source: "m64py\PyQt5\*"; DestDir: "{app}\PyQt5"; Flags: recursesubdirs +Source: "m64py\PyQt6\*"; DestDir: "{app}\PyQt6"; Flags: recursesubdirs Source: "m64py\AUTHORS"; DestDir: "{app}"; Source: "m64py\COPYING"; DestDir: "{app}"; Source: "m64py\README.rst"; DestDir: "{app}"; diff --git a/dist/windows/m64py.spec b/dist/windows/m64py.spec index e801784..99f359f 100644 --- a/dist/windows/m64py.spec +++ b/dist/windows/m64py.spec @@ -4,7 +4,7 @@ from os.path import join DIST_DIR = os.environ["DIST_DIR"] BASE_DIR = os.environ["BASE_DIR"] -a = Analysis([join(BASE_DIR, 'm64py')], hiddenimports=['pickle', 'PyQt5.Qt'], pathex=[join(BASE_DIR, 'src')]) +a = Analysis([join(BASE_DIR, 'm64py')], hiddenimports=['pickle', 'PyQt6.Qt'], pathex=[join(BASE_DIR, 'src')]) pyz = PYZ(a.pure) diff --git a/requirements.txt b/requirements.txt index f9b68da..3187c73 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -pyqt5 +pyqt6 pysdl2 diff --git a/setup.py b/setup.py index dd2fed8..2a4a385 100644 --- a/setup.py +++ b/setup.py @@ -9,10 +9,8 @@ import sys import tempfile import urllib import zipfile +import fileinput -import distutils -import distutils.command.build as distutils_build -import distutils.command.clean as distutils_clean import setuptools try: @@ -42,52 +40,52 @@ class BuildQt(setuptools.Command): pass def compile_rc(self, qrc_file): - import PyQt5 py_file = os.path.splitext(qrc_file)[0] + "_rc.py" if not newer(qrc_file, py_file): return - origpath = os.getenv("PATH") - path = origpath.split(os.pathsep) - path.append(os.path.dirname(PyQt5.__file__)) - os.putenv("PATH", os.pathsep.join(path)) - if subprocess.call(["pyrcc5", qrc_file, "-o", py_file]) > 0: + path = os.getenv("PATH").split(os.pathsep) + path.extend(["/usr/lib64/qt6/bin", "/usr/lib64/qt6/libexec", + "/usr/lib/qt6/bin", "/usr/lib/qt6/libexec", + "/usr/lib/x86_64-linux-gnu/qt6/bin", "/usr/lib/x86_64-linux-gnu/qt6/libexec"]) + os.environ["PATH"] = os.pathsep.join(path) + rcc_exe = shutil.which("rcc") + if rcc_exe is None: + self.warn("Unable to find Qt Resource Compiler (rcc)") + sys.exit(1) + if subprocess.call(["rcc", "-g", "python", qrc_file, "-o", py_file]) > 0: self.warn("Unable to compile resource file {}".format(qrc_file)) if not os.path.exists(py_file): sys.exit(1) - os.putenv("PATH", origpath) + for line in fileinput.input(py_file, inplace=True): + if "PySide6" in line: + line = line.replace("PySide6", "PyQt6") + sys.stdout.write(line) def compile_ui(self, ui_file): - from PyQt5 import uic + from PyQt6 import uic py_file = os.path.splitext(ui_file)[0] + "_ui.py" if not newer(ui_file, py_file): return with open(py_file, "w") as a_file: - uic.compileUi(ui_file, a_file, from_imports=True) + uic.compileUi(ui_file, a_file) def compile_ts(self, ts_file): - import PyQt5 - from PyQt5.QtCore import QLibraryInfo qm_file = os.path.splitext(ts_file)[0] + ".qm" if not newer(ts_file, qm_file): return - origpath = os.getenv("PATH") - path = origpath.split(os.pathsep) - path.append(os.path.dirname(PyQt5.__file__)) - os.putenv("PATH", os.pathsep.join(path)) - lr_exe = QLibraryInfo.location(QLibraryInfo.LibraryLocation.BinariesPath) - if lr_exe: - lr_exe = os.path.join(lr_exe, "lrelease") - if not os.path.exists(lr_exe): - lr_exe = None - lr_exe = lr_exe or distutils.spawn.find_executable("lrelease") or distutils.spawn.find_executable("lrelease-qt5") + path = os.getenv("PATH").split(os.pathsep) + path.extend(["/usr/lib64/qt6/bin", "/usr/lib64/qt6/libexec", + "/usr/lib/qt6/bin", "/usr/lib/qt6/libexec", + "/usr/lib/x86_64-linux-gnu/qt6/bin", "/usr/lib/x86_64-linux-gnu/qt6/libexec"]) + os.environ["PATH"] = os.pathsep.join(path) + lr_exe = shutil.which("lrelease") if lr_exe is None: - self.warn("Unable to find Qt's Linguist lrelease or lrelease-qt5 tools") + self.warn("Unable to find Qt Linguist (lrelease)") sys.exit(1) if subprocess.call([lr_exe, ts_file, "-qm", qm_file]) > 0: self.warn("Unable to compile translation file {}".format(qm_file)) if not os.path.exists(qm_file): sys.exit(1) - os.putenv("PATH", origpath) def run(self): basepath = os.path.join(os.path.dirname(__file__), "src", "m64py", "ui") @@ -120,7 +118,7 @@ class BuildDmg(setuptools.Command): def copy_emulator(self): src_path = os.path.join(self.dist_dir, "mupen64plus", "Contents") dest_path = os.path.join(self.dist_dir, "dmg", "M64Py.app", "Contents") - distutils.dir_util.copy_tree(src_path, dest_path) + shutil.copytree(src_path, dest_path, dirs_exist_ok=True) def copy_files(self): dest_path = os.path.join(self.dist_dir, "dmg") @@ -189,7 +187,7 @@ class BuildDmg(setuptools.Command): class BuildExe(setuptools.Command): """ - Requires PyQt5, rarfile, PyLZMA, PyWin32, PyInstaller and Inno + Requires PyQt6, rarfile, PyLZMA, PyWin32, PyInstaller and Inno Setup 5. """ @@ -233,7 +231,7 @@ class BuildExe(setuptools.Command): rar_dir = os.path.join(os.environ["ProgramFiles(x86)"], "Unrar") if not os.path.isfile(os.path.join(rar_dir, "UnRAR.exe")): tempdir = tempfile.mkdtemp() - urllib.request.urlretrieve("http://www.rarlab.com/rar/unrarw32.exe", + urllib.request.urlretrieve("http://www.rarlab.com/rar/unrarw64.exe", os.path.join(tempdir, "unrar.exe")) subprocess.call([os.path.join(tempdir, "unrar.exe"), "-s"]) shutil.rmtree(tempdir) @@ -248,12 +246,12 @@ class BuildExe(setuptools.Command): for dir_name in ["api", "man6", "applications", "apps"]: shutil.rmtree(os.path.join(dest_path, dir_name), True) for dir_name in ["qml", "translations"]: - shutil.rmtree(os.path.join(dest_path, "PyQt5", "Qt", dir_name), True) - for file_name in glob.glob(os.path.join(dest_path, "PyQt5", "Qt*.pyd")): - if os.path.basename(file_name) not in ["Qt.pyd", "QtCore.pyd", "QtGui.pyd", "QtWidgets.pyd", "QtOpenGL.pyd"]: + shutil.rmtree(os.path.join(dest_path, "PyQt6", "Qt", dir_name), True) + for file_name in glob.glob(os.path.join(dest_path, "PyQt6", "Qt*.pyd")): + if os.path.basename(file_name) not in ["Qt.pyd", "QtCore.pyd", "QtGui.pyd", "QtWidgets.pyd"]: os.remove(file_name) - for file_name in glob.glob(os.path.join(dest_path, "Qt5*.dll")): - if os.path.basename(file_name) not in ["Qt5Core.dll", "Qt5Gui.dll", "Qt5Widgets.dll", "Qt5OpenGL.dll"]: + for file_name in glob.glob(os.path.join(dest_path, "Qt6*.dll")): + if os.path.basename(file_name) not in ["Qt6Core.dll", "Qt6Gui.dll", "Qt6Widgets.dll"]: os.remove(file_name) def run_build(self): @@ -381,23 +379,11 @@ class CleanLocal(setuptools.Command): os.remove(a_path) -class MyBuild(distutils_build.build): - def run(self): - self.run_command("build_qt") - distutils_build.build.run(self) - - -class MyClean(distutils_clean.clean): - def run(self): - self.run_command("clean_local") - distutils_clean.clean.run(self) - - setuptools.setup( name="m64py", version=FRONTEND_VERSION, description="A frontend for Mupen64Plus", - long_description="A Qt5 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator.", + long_description="A Qt6 front-end (GUI) for Mupen64Plus, a cross-platform plugin-based Nintendo 64 emulator.", author="Milan Nikolic", author_email="gen2brain@gmail.com", license="GNU GPLv3", @@ -405,16 +391,15 @@ setuptools.setup( package_dir={'': "src"}, packages=["m64py", "m64py.core", "m64py.frontend", "m64py.ui"], scripts=["bin/m64py"], - requires=["PyQt5", "PySDL2"], + requires=["PyQt6", "PySDL2"], platforms=["Linux", "Windows", "Darwin"], cmdclass={ - 'build': MyBuild, + 'build': BuildQt, 'build_dmg': BuildDmg, 'build_exe': BuildExe, 'build_qt': BuildQt, 'build_zip': BuildZip, - 'clean': MyClean, - 'clean_local': CleanLocal + 'clean': CleanLocal }, data_files=[ ("share/pixmaps", ["xdg/m64py.png"]), diff --git a/src/m64py/core/defs.py b/src/m64py/core/defs.py index c0c7c23..946c9be 100644 --- a/src/m64py/core/defs.py +++ b/src/m64py/core/defs.py @@ -23,7 +23,7 @@ CORE_API_VERSION = 0x20001 CONFIG_API_VERSION = 0x20302 VIDEXT_API_VERSION = 0x030300 MINIMUM_CORE_VERSION = 0x020600 -FRONTEND_VERSION = "0.2.6" +FRONTEND_VERSION = "0.3.0" SIZE_1X = (320, 240) SIZE_2X = (640, 480) diff --git a/src/m64py/core/vidext.py b/src/m64py/core/vidext.py index 2f54f64..be074fe 100644 --- a/src/m64py/core/vidext.py +++ b/src/m64py/core/vidext.py @@ -16,8 +16,8 @@ import ctypes -from PyQt5.QtWidgets import QApplication -from PyQt5.QtGui import QSurfaceFormat +from PyQt6.QtWidgets import QApplication +from PyQt6.QtGui import QSurfaceFormat from sdl2 import SDL_WasInit, SDL_InitSubSystem, SDL_QuitSubSystem, SDL_INIT_VIDEO from sdl2 import SDL_GetNumDisplayModes, SDL_DisplayMode, SDL_GetDisplayMode @@ -62,9 +62,9 @@ class Video: if not self.glcontext: self.glformat = QSurfaceFormat.defaultFormat() self.glformat.setVersion(3, 3) - self.glformat.setOption(QSurfaceFormat.DeprecatedFunctions, 1) - self.glformat.setProfile(QSurfaceFormat.CompatibilityProfile) - self.glformat.setRenderableType(QSurfaceFormat.OpenGL) + self.glformat.setOption(QSurfaceFormat.FormatOption.DeprecatedFunctions, 1) + self.glformat.setProfile(QSurfaceFormat.OpenGLContextProfile.CompatibilityProfile) + self.glformat.setRenderableType(QSurfaceFormat.RenderableType.OpenGL) self.glformat.setDepthBufferSize(24) self.glformat.setSwapInterval(0) @@ -220,29 +220,29 @@ class Video: def set_profile(self, value): if value == M64P_GL_CONTEXT_PROFILE_CORE: - self.glformat.setProfile(QSurfaceFormat.CoreProfile) + self.glformat.setProfile(QSurfaceFormat.OpenGLContextProfile.CoreProfile) elif value == M64P_GL_CONTEXT_PROFILE_COMPATIBILITY: - self.glformat.setProfile(QSurfaceFormat.CompatibilityProfile) + self.glformat.setProfile(QSurfaceFormat.OpenGLContextProfile.CompatibilityProfile) else: - self.glformat.setProfile(QSurfaceFormat.CompatibilityProfile) + self.glformat.setProfile(QSurfaceFormat.OpenGLContextProfile.CompatibilityProfile) def get_profile(self): profile = self.glformat.profile() - if profile == QSurfaceFormat.CoreProfile: + if profile == QSurfaceFormat.OpenGLContextProfile.CoreProfile: return M64P_GL_CONTEXT_PROFILE_CORE - elif profile == QSurfaceFormat.CompatibilityProfile: + elif profile == QSurfaceFormat.OpenGLContextProfile.CompatibilityProfile: return M64P_GL_CONTEXT_PROFILE_COMPATIBILITY else: return M64P_GL_CONTEXT_PROFILE_COMPATIBILITY def set_doublebuffer(self, value): if value == 1: - self.glformat.setSwapBehavior(QSurfaceFormat.DoubleBuffer) + self.glformat.setSwapBehavior(QSurfaceFormat.SwapBehavior.DoubleBuffer) elif value == 0: - self.glformat.setSwapBehavior(QSurfaceFormat.SingleBuffer) + self.glformat.setSwapBehavior(QSurfaceFormat.SwapBehavior.SingleBuffer) def get_doublebuffer(self): - if self.glformat.swapBehavior() == QSurfaceFormat.DoubleBuffer: + if self.glformat.swapBehavior() == QSurfaceFormat.SwapBehavior.DoubleBuffer: return 1 return 0 diff --git a/src/m64py/frontend/cheat.py b/src/m64py/frontend/cheat.py index d1ef07e..5a47f00 100644 --- a/src/m64py/frontend/cheat.py +++ b/src/m64py/frontend/cheat.py @@ -18,8 +18,8 @@ import os import re from collections import defaultdict -from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QListWidgetItem, QTreeWidgetItemIterator -from PyQt5.QtCore import Qt +from PyQt6.QtWidgets import QDialog, QTreeWidgetItem, QListWidgetItem, QTreeWidgetItemIterator +from PyQt6.QtCore import Qt from m64py.core.defs import * from m64py.utils import sl @@ -69,41 +69,31 @@ class Cheat(QDialog, Ui_CheatDialog): for k3,v3 in sorted(v2.items()): child2 = QTreeWidgetItem(child1) child2.setText(0, k3) - child2.setCheckState(0, Qt.Unchecked) - child2.setData(0, Qt.UserRole, v3) + child2.setCheckState(0, Qt.CheckState.Unchecked) + child2.setData(0, Qt.ItemDataRole.UserRole, v3) self.treeWidget.addTopLevelItem(child2) else: - child1.setCheckState(0, Qt.Unchecked) - child1.setData(0, Qt.UserRole, v2) + child1.setCheckState(0, Qt.CheckState.Unchecked) + child1.setData(0, Qt.ItemDataRole.UserRole, v2) else: - top.setCheckState(0, Qt.Unchecked) - top.setData(0, Qt.UserRole, v1) + top.setCheckState(0, Qt.CheckState.Unchecked) + top.setData(0, Qt.ItemDataRole.UserRole, v1) - self.treeWidget.sortItems(0, Qt.AscendingOrder) + self.treeWidget.sortItems(0, Qt.SortOrder.AscendingOrder) self.treeWidget.itemChanged.connect(self.activate_cheat) self.treeWidget.itemClicked.connect(self.on_item_clicked) - self.treeWidget.itemSelectionChanged.connect(self.on_selection_changed) self.pushUnmarkAll.clicked.connect(self.on_unmark_all) - def on_selection_changed(self): - """Sets description""" - items = self.treeWidget.selectedItems() - for item in items: - data = item.data(0, Qt.UserRole) - if data: - for cheat in data: - cd, address, value, choices = cheat - desc = cd if cd else "" - self.labelDesc.setText(desc) - def on_item_clicked(self, item, column): """Sets description""" - data = item.data(column, Qt.UserRole) + data = item.data(column, Qt.ItemDataRole.UserRole) if data: for cheat in data: cd, address, value, choices = cheat desc = cd if cd else "" self.labelDesc.setText(desc) + if desc: + break def on_unmark_all(self): """Deactivates all cheats""" @@ -111,8 +101,8 @@ class Cheat(QDialog, Ui_CheatDialog): while it.value(): item = it.value() state = item.checkState(0) - if state == Qt.Checked: - item.setCheckState(0, Qt.Unchecked) + if state == Qt.CheckState.Checked: + item.setCheckState(0, Qt.CheckState.Unchecked) it += 1 def activate_cheat(self, item, column): @@ -125,8 +115,8 @@ class Cheat(QDialog, Ui_CheatDialog): parent = parent.parent() if parent: name = "%s\\%s" % (parent.text(column), name) - data = item.data(column, Qt.UserRole) - if state == Qt.Checked: + data = item.data(column, Qt.ItemDataRole.UserRole) + if state == Qt.CheckState.Checked: codes_type = M64pCheatCode * len(data) codes = codes_type() for num, cheat in enumerate(data): @@ -136,7 +126,7 @@ class Cheat(QDialog, Ui_CheatDialog): rval = choices.exec_() if rval == QDialog.Accepted: curr_item = choices.listWidget.currentItem() - value = curr_item.data(Qt.UserRole) + value = curr_item.data(Qt.ItemDataRole.UserRole) else: #item.setCheckState(0, Qt.Unchecked) return @@ -282,5 +272,5 @@ class Choices(QDialog, Ui_ChoicesDialog): for choice in sorted(self.choices, key=lambda choice: choice[1]): value, name = choice item = QListWidgetItem(name.replace('"', '')) - item.setData(Qt.UserRole, value) + item.setData(Qt.ItemDataRole.UserRole, value) self.listWidget.addItem(item) diff --git a/src/m64py/frontend/dialogs.py b/src/m64py/frontend/dialogs.py index ec62e3d..0d5f511 100644 --- a/src/m64py/frontend/dialogs.py +++ b/src/m64py/frontend/dialogs.py @@ -15,19 +15,15 @@ # along with this program. If not, see . import sys -from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QDialog, QMessageBox, QListWidgetItem +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import QDialog, QMessageBox, QListWidgetItem from m64py.utils import version_split from m64py.core.defs import FRONTEND_VERSION -try: - from m64py.ui.about_ui import Ui_AboutDialog - from m64py.ui.license_ui import Ui_LicenseDialog - from m64py.ui.archive_ui import Ui_ArchiveDialog -except ModuleNotFoundError: - sys.stderr.write("You have to run setup.py build first\n") - sys.exit(1) +from m64py.ui.about_ui import Ui_AboutDialog +from m64py.ui.license_ui import Ui_LicenseDialog +from m64py.ui.archive_ui import Ui_ArchiveDialog class AboutDialog(QDialog, Ui_AboutDialog): @@ -70,6 +66,6 @@ class ArchiveDialog(QDialog, Ui_ArchiveDialog): self.listWidget.clear() for fname in files: item = QListWidgetItem(fname) - item.setData(Qt.UserRole, fname) + item.setData(Qt.ItemDataRole.UserRole, fname) self.listWidget.addItem(item) self.listWidget.setCurrentRow(0) diff --git a/src/m64py/frontend/glwidget.py b/src/m64py/frontend/glwidget.py index d4e641f..2b39dd7 100644 --- a/src/m64py/frontend/glwidget.py +++ b/src/m64py/frontend/glwidget.py @@ -14,11 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtCore import Qt -from PyQt5.QtGui import QWindow, QOpenGLContext - -from m64py.core.defs import * -from m64py.frontend.keymap import QT2SDL2 +from PyQt6.QtGui import QWindow, QOpenGLContext, QSurface class GLWidget(QWindow): @@ -27,7 +23,7 @@ class GLWidget(QWindow): self.parent = parent QWindow.__init__(self, None) - self.setSurfaceType(QWindow.OpenGLSurface) + self.setSurfaceType(QSurface.SurfaceType.OpenGLSurface) self.ctx = QOpenGLContext() def context(self): @@ -40,34 +36,3 @@ class GLWidget(QWindow): def mouseDoubleClickEvent(self, event): self.parent.toggle_fs.emit() - - def keyPressEvent(self, event): - if self.parent.worker.state != M64EMU_RUNNING: - return - - key = event.key() - modifiers = event.modifiers() - - if modifiers & Qt.AltModifier and (key == Qt.Key_Enter or key == Qt.Key_Return): - self.parent.toggle_fs.emit() - elif key == Qt.Key_F3: - self.parent.worker.save_title() - elif key == Qt.Key_F4: - self.parent.worker.save_snapshot() - else: - try: - sdl_key = QT2SDL2[key] - self.parent.worker.send_sdl_keydown(sdl_key) - except KeyError: - pass - - def keyReleaseEvent(self, event): - if self.parent.worker.state != M64EMU_RUNNING: - return - - key = event.key() - try: - sdl_key = QT2SDL2[key] - self.parent.worker.send_sdl_keyup(sdl_key) - except KeyError: - pass diff --git a/src/m64py/frontend/input.py b/src/m64py/frontend/input.py index ff9657d..9b6d18d 100644 --- a/src/m64py/frontend/input.py +++ b/src/m64py/frontend/input.py @@ -16,8 +16,7 @@ import re -from PyQt5.QtWidgets import QDialog -from PyQt5.QtGui import QKeySequence +from PyQt6.QtWidgets import QDialog from sdl2 import SDL_WasInit, SDL_InitSubSystem, SDL_QuitSubSystem, SDL_INIT_VIDEO from sdl2.keyboard import SDL_GetScancodeName, SDL_GetScancodeFromName diff --git a/src/m64py/frontend/joystick.py b/src/m64py/frontend/joystick.py index 6eb913c..d6a92ea 100644 --- a/src/m64py/frontend/joystick.py +++ b/src/m64py/frontend/joystick.py @@ -17,7 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtCore import QObject, pyqtSignal, QTime, QTimer +from PyQt6.QtCore import QObject, pyqtSignal, QTime, QTimer from sdl2 import SDL_WasInit, SDL_InitSubSystem, SDL_INIT_JOYSTICK from sdl2 import SDL_JoystickOpen, SDL_JoystickClose, SDL_NumJoysticks, SDL_JoystickNameForIndex @@ -195,6 +195,6 @@ class Joystick(QObject): elif self.auto_repeat and changed != 0: if self.button_repeat_timers[i].elapsed() >= self.auto_repeat_delay: self.button_value_changed.emit(i, changed) - self.button[si] = changed + self.button[i] = changed else: self.button_repeat_timers[i].restart() diff --git a/src/m64py/frontend/keymap.py b/src/m64py/frontend/keymap.py index d73f014..2941059 100644 --- a/src/m64py/frontend/keymap.py +++ b/src/m64py/frontend/keymap.py @@ -14,7 +14,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtCore import Qt +from PyQt6.QtCore import Qt from m64py.frontend.keycodes import * @@ -22,100 +22,100 @@ QT2SDL2 = dict() SCANCODE2KEYCODE = dict() KEYCODE2SCANCODE = dict() -QT2SDL2[Qt.Key_A] = SDL_SCANCODE_A -QT2SDL2[Qt.Key_B] = SDL_SCANCODE_B -QT2SDL2[Qt.Key_C] = SDL_SCANCODE_C -QT2SDL2[Qt.Key_D] = SDL_SCANCODE_D -QT2SDL2[Qt.Key_E] = SDL_SCANCODE_E -QT2SDL2[Qt.Key_F] = SDL_SCANCODE_F -QT2SDL2[Qt.Key_G] = SDL_SCANCODE_G -QT2SDL2[Qt.Key_H] = SDL_SCANCODE_H -QT2SDL2[Qt.Key_I] = SDL_SCANCODE_I -QT2SDL2[Qt.Key_J] = SDL_SCANCODE_J -QT2SDL2[Qt.Key_K] = SDL_SCANCODE_K -QT2SDL2[Qt.Key_L] = SDL_SCANCODE_L -QT2SDL2[Qt.Key_M] = SDL_SCANCODE_M -QT2SDL2[Qt.Key_N] = SDL_SCANCODE_N -QT2SDL2[Qt.Key_O] = SDL_SCANCODE_O -QT2SDL2[Qt.Key_P] = SDL_SCANCODE_P -QT2SDL2[Qt.Key_Q] = SDL_SCANCODE_Q -QT2SDL2[Qt.Key_R] = SDL_SCANCODE_R -QT2SDL2[Qt.Key_S] = SDL_SCANCODE_S -QT2SDL2[Qt.Key_T] = SDL_SCANCODE_T -QT2SDL2[Qt.Key_U] = SDL_SCANCODE_U -QT2SDL2[Qt.Key_V] = SDL_SCANCODE_V -QT2SDL2[Qt.Key_W] = SDL_SCANCODE_W -QT2SDL2[Qt.Key_X] = SDL_SCANCODE_X -QT2SDL2[Qt.Key_Y] = SDL_SCANCODE_Y -QT2SDL2[Qt.Key_Z] = SDL_SCANCODE_Z -QT2SDL2[Qt.Key_0] = SDL_SCANCODE_0 -QT2SDL2[Qt.Key_1] = SDL_SCANCODE_1 -QT2SDL2[Qt.Key_2] = SDL_SCANCODE_2 -QT2SDL2[Qt.Key_3] = SDL_SCANCODE_3 -QT2SDL2[Qt.Key_4] = SDL_SCANCODE_4 -QT2SDL2[Qt.Key_5] = SDL_SCANCODE_5 -QT2SDL2[Qt.Key_6] = SDL_SCANCODE_6 -QT2SDL2[Qt.Key_7] = SDL_SCANCODE_7 -QT2SDL2[Qt.Key_8] = SDL_SCANCODE_8 -QT2SDL2[Qt.Key_9] = SDL_SCANCODE_9 -QT2SDL2[Qt.Key_F1] = SDL_SCANCODE_F1 -QT2SDL2[Qt.Key_F2] = SDL_SCANCODE_F2 -QT2SDL2[Qt.Key_F3] = SDL_SCANCODE_F3 -QT2SDL2[Qt.Key_F4] = SDL_SCANCODE_F4 -QT2SDL2[Qt.Key_F5] = SDL_SCANCODE_F5 -QT2SDL2[Qt.Key_F6] = SDL_SCANCODE_F6 -QT2SDL2[Qt.Key_F7] = SDL_SCANCODE_F7 -QT2SDL2[Qt.Key_F8] = SDL_SCANCODE_F8 -QT2SDL2[Qt.Key_F9] = SDL_SCANCODE_F9 -QT2SDL2[Qt.Key_F10] = SDL_SCANCODE_F10 -QT2SDL2[Qt.Key_F11] = SDL_SCANCODE_F11 -QT2SDL2[Qt.Key_F12] = SDL_SCANCODE_F12 -QT2SDL2[Qt.Key_F13] = SDL_SCANCODE_F13 -QT2SDL2[Qt.Key_F14] = SDL_SCANCODE_F14 -QT2SDL2[Qt.Key_F15] = SDL_SCANCODE_F15 -QT2SDL2[Qt.Key_Insert] = SDL_SCANCODE_INSERT -QT2SDL2[Qt.Key_Delete] = SDL_SCANCODE_DELETE -QT2SDL2[Qt.Key_Home] = SDL_SCANCODE_HOME -QT2SDL2[Qt.Key_End] = SDL_SCANCODE_END -QT2SDL2[Qt.Key_PageUp] = SDL_SCANCODE_PAGEUP -QT2SDL2[Qt.Key_PageDown] = SDL_SCANCODE_PAGEDOWN -QT2SDL2[Qt.Key_Up] = SDL_SCANCODE_UP -QT2SDL2[Qt.Key_Down] = SDL_SCANCODE_DOWN -QT2SDL2[Qt.Key_Left] = SDL_SCANCODE_LEFT -QT2SDL2[Qt.Key_Right] = SDL_SCANCODE_RIGHT -QT2SDL2[Qt.Key_Return] = SDL_SCANCODE_RETURN -QT2SDL2[Qt.Key_Enter] = SDL_SCANCODE_RETURN2 -QT2SDL2[Qt.Key_Escape] = SDL_SCANCODE_ESCAPE -QT2SDL2[Qt.Key_Pause] = SDL_SCANCODE_PAUSE -QT2SDL2[Qt.Key_QuoteLeft] = SDL_SCANCODE_GRAVE -QT2SDL2[Qt.Key_Backspace] = SDL_SCANCODE_BACKSPACE -QT2SDL2[Qt.Key_Tab] = SDL_SCANCODE_TAB -QT2SDL2[Qt.Key_CapsLock] = SDL_SCANCODE_CAPSLOCK -QT2SDL2[Qt.Key_Space] = SDL_SCANCODE_SPACE -QT2SDL2[Qt.Key_Slash] = SDL_SCANCODE_SLASH -QT2SDL2[Qt.Key_Backslash] = SDL_SCANCODE_BACKSLASH -QT2SDL2[Qt.Key_Minus] = SDL_SCANCODE_MINUS -QT2SDL2[Qt.Key_Plus] = SDL_SCANCODE_UNKNOWN -QT2SDL2[Qt.Key_Equal] = SDL_SCANCODE_EQUALS -QT2SDL2[Qt.Key_BracketLeft] = SDL_SCANCODE_LEFTBRACKET -QT2SDL2[Qt.Key_BracketRight] = SDL_SCANCODE_RIGHTBRACKET -QT2SDL2[Qt.Key_Semicolon] = SDL_SCANCODE_SEMICOLON -QT2SDL2[Qt.Key_Apostrophe] = SDL_SCANCODE_APOSTROPHE -QT2SDL2[Qt.Key_Comma] = SDL_SCANCODE_COMMA -QT2SDL2[Qt.Key_Period] = SDL_SCANCODE_PERIOD -QT2SDL2[Qt.Key_Alt] = SDL_SCANCODE_LALT -QT2SDL2[Qt.Key_Control] = SDL_SCANCODE_LCTRL -QT2SDL2[Qt.Key_Shift] = SDL_SCANCODE_LSHIFT -QT2SDL2[Qt.AltModifier.__int__()] = SDL_SCANCODE_LALT -QT2SDL2[Qt.ControlModifier.__int__()] = SDL_SCANCODE_LCTRL -QT2SDL2[Qt.ShiftModifier.__int__()] = SDL_SCANCODE_LSHIFT -QT2SDL2[Qt.Key_Print] = SDL_SCANCODE_PRINTSCREEN -QT2SDL2[Qt.Key_ScrollLock] = SDL_SCANCODE_SCROLLLOCK -QT2SDL2[Qt.Key_Meta] = SDL_SCANCODE_LGUI -QT2SDL2[Qt.MetaModifier.__int__()] = SDL_SCANCODE_LGUI -QT2SDL2[Qt.Key_Super_L] = SDL_SCANCODE_LGUI -QT2SDL2[Qt.Key_Super_R] = SDL_SCANCODE_RGUI -QT2SDL2[Qt.Key_unknown] = SDL_SCANCODE_UNKNOWN +QT2SDL2[Qt.Key.Key_A] = SDL_SCANCODE_A +QT2SDL2[Qt.Key.Key_B] = SDL_SCANCODE_B +QT2SDL2[Qt.Key.Key_C] = SDL_SCANCODE_C +QT2SDL2[Qt.Key.Key_D] = SDL_SCANCODE_D +QT2SDL2[Qt.Key.Key_E] = SDL_SCANCODE_E +QT2SDL2[Qt.Key.Key_F] = SDL_SCANCODE_F +QT2SDL2[Qt.Key.Key_G] = SDL_SCANCODE_G +QT2SDL2[Qt.Key.Key_H] = SDL_SCANCODE_H +QT2SDL2[Qt.Key.Key_I] = SDL_SCANCODE_I +QT2SDL2[Qt.Key.Key_J] = SDL_SCANCODE_J +QT2SDL2[Qt.Key.Key_K] = SDL_SCANCODE_K +QT2SDL2[Qt.Key.Key_L] = SDL_SCANCODE_L +QT2SDL2[Qt.Key.Key_M] = SDL_SCANCODE_M +QT2SDL2[Qt.Key.Key_N] = SDL_SCANCODE_N +QT2SDL2[Qt.Key.Key_O] = SDL_SCANCODE_O +QT2SDL2[Qt.Key.Key_P] = SDL_SCANCODE_P +QT2SDL2[Qt.Key.Key_Q] = SDL_SCANCODE_Q +QT2SDL2[Qt.Key.Key_R] = SDL_SCANCODE_R +QT2SDL2[Qt.Key.Key_S] = SDL_SCANCODE_S +QT2SDL2[Qt.Key.Key_T] = SDL_SCANCODE_T +QT2SDL2[Qt.Key.Key_U] = SDL_SCANCODE_U +QT2SDL2[Qt.Key.Key_V] = SDL_SCANCODE_V +QT2SDL2[Qt.Key.Key_W] = SDL_SCANCODE_W +QT2SDL2[Qt.Key.Key_X] = SDL_SCANCODE_X +QT2SDL2[Qt.Key.Key_Y] = SDL_SCANCODE_Y +QT2SDL2[Qt.Key.Key_Z] = SDL_SCANCODE_Z +QT2SDL2[Qt.Key.Key_0] = SDL_SCANCODE_0 +QT2SDL2[Qt.Key.Key_1] = SDL_SCANCODE_1 +QT2SDL2[Qt.Key.Key_2] = SDL_SCANCODE_2 +QT2SDL2[Qt.Key.Key_3] = SDL_SCANCODE_3 +QT2SDL2[Qt.Key.Key_4] = SDL_SCANCODE_4 +QT2SDL2[Qt.Key.Key_5] = SDL_SCANCODE_5 +QT2SDL2[Qt.Key.Key_6] = SDL_SCANCODE_6 +QT2SDL2[Qt.Key.Key_7] = SDL_SCANCODE_7 +QT2SDL2[Qt.Key.Key_8] = SDL_SCANCODE_8 +QT2SDL2[Qt.Key.Key_9] = SDL_SCANCODE_9 +QT2SDL2[Qt.Key.Key_F1] = SDL_SCANCODE_F1 +QT2SDL2[Qt.Key.Key_F2] = SDL_SCANCODE_F2 +QT2SDL2[Qt.Key.Key_F3] = SDL_SCANCODE_F3 +QT2SDL2[Qt.Key.Key_F4] = SDL_SCANCODE_F4 +QT2SDL2[Qt.Key.Key_F5] = SDL_SCANCODE_F5 +QT2SDL2[Qt.Key.Key_F6] = SDL_SCANCODE_F6 +QT2SDL2[Qt.Key.Key_F7] = SDL_SCANCODE_F7 +QT2SDL2[Qt.Key.Key_F8] = SDL_SCANCODE_F8 +QT2SDL2[Qt.Key.Key_F9] = SDL_SCANCODE_F9 +QT2SDL2[Qt.Key.Key_F10] = SDL_SCANCODE_F10 +QT2SDL2[Qt.Key.Key_F11] = SDL_SCANCODE_F11 +QT2SDL2[Qt.Key.Key_F12] = SDL_SCANCODE_F12 +QT2SDL2[Qt.Key.Key_F13] = SDL_SCANCODE_F13 +QT2SDL2[Qt.Key.Key_F14] = SDL_SCANCODE_F14 +QT2SDL2[Qt.Key.Key_F15] = SDL_SCANCODE_F15 +QT2SDL2[Qt.Key.Key_Insert] = SDL_SCANCODE_INSERT +QT2SDL2[Qt.Key.Key_Delete] = SDL_SCANCODE_DELETE +QT2SDL2[Qt.Key.Key_Home] = SDL_SCANCODE_HOME +QT2SDL2[Qt.Key.Key_End] = SDL_SCANCODE_END +QT2SDL2[Qt.Key.Key_PageUp] = SDL_SCANCODE_PAGEUP +QT2SDL2[Qt.Key.Key_PageDown] = SDL_SCANCODE_PAGEDOWN +QT2SDL2[Qt.Key.Key_Up] = SDL_SCANCODE_UP +QT2SDL2[Qt.Key.Key_Down] = SDL_SCANCODE_DOWN +QT2SDL2[Qt.Key.Key_Left] = SDL_SCANCODE_LEFT +QT2SDL2[Qt.Key.Key_Right] = SDL_SCANCODE_RIGHT +QT2SDL2[Qt.Key.Key_Return] = SDL_SCANCODE_RETURN +QT2SDL2[Qt.Key.Key_Enter] = SDL_SCANCODE_RETURN2 +QT2SDL2[Qt.Key.Key_Escape] = SDL_SCANCODE_ESCAPE +QT2SDL2[Qt.Key.Key_Pause] = SDL_SCANCODE_PAUSE +QT2SDL2[Qt.Key.Key_QuoteLeft] = SDL_SCANCODE_GRAVE +QT2SDL2[Qt.Key.Key_Backspace] = SDL_SCANCODE_BACKSPACE +QT2SDL2[Qt.Key.Key_Tab] = SDL_SCANCODE_TAB +QT2SDL2[Qt.Key.Key_CapsLock] = SDL_SCANCODE_CAPSLOCK +QT2SDL2[Qt.Key.Key_Space] = SDL_SCANCODE_SPACE +QT2SDL2[Qt.Key.Key_Slash] = SDL_SCANCODE_SLASH +QT2SDL2[Qt.Key.Key_Backslash] = SDL_SCANCODE_BACKSLASH +QT2SDL2[Qt.Key.Key_Minus] = SDL_SCANCODE_MINUS +QT2SDL2[Qt.Key.Key_Plus] = SDL_SCANCODE_UNKNOWN +QT2SDL2[Qt.Key.Key_Equal] = SDL_SCANCODE_EQUALS +QT2SDL2[Qt.Key.Key_BracketLeft] = SDL_SCANCODE_LEFTBRACKET +QT2SDL2[Qt.Key.Key_BracketRight] = SDL_SCANCODE_RIGHTBRACKET +QT2SDL2[Qt.Key.Key_Semicolon] = SDL_SCANCODE_SEMICOLON +QT2SDL2[Qt.Key.Key_Apostrophe] = SDL_SCANCODE_APOSTROPHE +QT2SDL2[Qt.Key.Key_Comma] = SDL_SCANCODE_COMMA +QT2SDL2[Qt.Key.Key_Period] = SDL_SCANCODE_PERIOD +QT2SDL2[Qt.Key.Key_Alt] = SDL_SCANCODE_LALT +QT2SDL2[Qt.Key.Key_Control] = SDL_SCANCODE_LCTRL +QT2SDL2[Qt.Key.Key_Shift] = SDL_SCANCODE_LSHIFT +QT2SDL2[Qt.KeyboardModifier.AltModifier] = SDL_SCANCODE_LALT +QT2SDL2[Qt.KeyboardModifier.ControlModifier] = SDL_SCANCODE_LCTRL +QT2SDL2[Qt.KeyboardModifier.ShiftModifier] = SDL_SCANCODE_LSHIFT +QT2SDL2[Qt.Key.Key_Print] = SDL_SCANCODE_PRINTSCREEN +QT2SDL2[Qt.Key.Key_ScrollLock] = SDL_SCANCODE_SCROLLLOCK +QT2SDL2[Qt.Key.Key_Meta] = SDL_SCANCODE_LGUI +QT2SDL2[Qt.KeyboardModifier.MetaModifier] = SDL_SCANCODE_LGUI +QT2SDL2[Qt.Key.Key_Super_L] = SDL_SCANCODE_LGUI +QT2SDL2[Qt.Key.Key_Super_R] = SDL_SCANCODE_RGUI +QT2SDL2[Qt.Key.Key_unknown] = SDL_SCANCODE_UNKNOWN SCANCODE2KEYCODE[SDL_SCANCODE_A] = SDLK_a SCANCODE2KEYCODE[SDL_SCANCODE_B] = SDLK_b diff --git a/src/m64py/frontend/log.py b/src/m64py/frontend/log.py index 268ef20..5ee0b7f 100644 --- a/src/m64py/frontend/log.py +++ b/src/m64py/frontend/log.py @@ -17,17 +17,17 @@ import sys import logging -from PyQt5.QtCore import pyqtSignal -from PyQt5.QtWidgets import QDialog -from PyQt5.QtGui import QTextCursor +from PyQt6.QtCore import pyqtSignal +from PyQt6.QtWidgets import QDialog +from PyQt6.QtGui import QTextCursor from m64py.ui.logview_ui import Ui_LogView class Log: - def __init__(self, out=None, logview=None): + def __init__(self, out=None, view=None): self.out = out - self.logview = logview + self.logview = view def write(self, msg): if self.out: @@ -50,7 +50,7 @@ class LogView(QDialog, Ui_LogView): self.msg_written.connect(self.on_msg_written) def on_msg_written(self, msg): - self.textEdit.moveCursor(QTextCursor.End) + self.textEdit.moveCursor(QTextCursor.MoveOperation.End) self.textEdit.insertPlainText(msg) diff --git a/src/m64py/frontend/mainwindow.py b/src/m64py/frontend/mainwindow.py index f4844ed..6132d29 100644 --- a/src/m64py/frontend/mainwindow.py +++ b/src/m64py/frontend/mainwindow.py @@ -17,10 +17,10 @@ import os import sys -from PyQt5.QtGui import QKeySequence, QPixmap, QOpenGLContext -from PyQt5.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem -from PyQt5.QtWidgets import QAction, QLabel, QFileDialog, QStackedWidget, QActionGroup, QSizePolicy, QWidget, QDialog -from PyQt5.QtCore import Qt, QTimer, QFileInfo, QEvent, QMargins, pyqtSignal, pyqtSlot +from PyQt6.QtGui import QKeySequence, QPixmap, QOpenGLContext, QAction, QActionGroup +from PyQt6.QtWidgets import QApplication, QMainWindow, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem +from PyQt6.QtWidgets import QLabel, QFileDialog, QStackedWidget, QSizePolicy, QWidget, QDialog +from PyQt6.QtCore import Qt, QTimer, QFileInfo, QEvent, QMargins, pyqtSignal, pyqtSlot from m64py.core.defs import * from m64py.frontend.dialogs import * @@ -34,6 +34,9 @@ from m64py.frontend.settings import Settings from m64py.frontend.glwidget import GLWidget from m64py.ui.mainwindow_ui import Ui_MainWindow from m64py.frontend.recentfiles import RecentFiles +from m64py.frontend.keymap import QT2SDL2 +from m64py.ui import icons_rc +from m64py.ui import images_rc class MainWindow(QMainWindow, Ui_MainWindow): @@ -61,11 +64,11 @@ class MainWindow(QMainWindow, Ui_MainWindow): self._initialize_attempt = 0 logview.setParent(self) - logview.setWindowFlags(Qt.Dialog) + logview.setWindowFlags(Qt.WindowType.Dialog) self.statusbar_label = QLabel() self.statusbar_label.setIndent(2) - self.statusbar_label.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Fixed) + self.statusbar_label.setSizePolicy(QSizePolicy.Policy.Ignored, QSizePolicy.Policy.Fixed) self.statusbar.addPermanentWidget(self.statusbar_label, 1) self.update_status(self.tr( "Welcome to M64Py version %s." % FRONTEND_VERSION)) @@ -97,10 +100,11 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.worker.quit() def changeEvent(self, event): - if event.type() == QEvent.WindowStateChange: - if event.oldState() == Qt.WindowMaximized: + if event.type() == QEvent.Type.WindowStateChange: + if event.oldState() == Qt.WindowState.WindowMaximized: self.maximized = False - elif event.oldState() == Qt.WindowNoState and self.windowState() == Qt.WindowMaximized: + elif (event.oldState() == Qt.WindowState.WindowNoState and + self.windowState() == Qt.WindowState.WindowMaximized): self.maximized = True def resizeEvent(self, event): @@ -123,6 +127,37 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.create_size_actions() self.center_widget() + def keyPressEvent(self, event): + if self.worker.state != M64EMU_RUNNING: + return + + key = event.key() + modifiers = event.modifiers() + + if modifiers & Qt.KeyboardModifier.AltModifier and (key == Qt.Key.Key_Enter or key == Qt.Key.Key_Return): + self.toggle_fs.emit() + elif key == Qt.Key.Key_F3: + self.worker.save_title() + elif key == Qt.Key.Key_F4: + self.worker.save_snapshot() + else: + try: + sdl_key = QT2SDL2[key] + self.worker.send_sdl_keydown(sdl_key) + except KeyError: + pass + + def keyReleaseEvent(self, event): + if self.worker.state != M64EMU_RUNNING: + return + + key = event.key() + try: + sdl_key = QT2SDL2[key] + self.worker.send_sdl_keyup(sdl_key) + except KeyError: + pass + def window_size_triggered(self, size): window_width, window_height = size if self.vidext and self.worker.core.get_handle(): @@ -172,7 +207,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): def center_widget(self): """Centers widget on desktop.""" size = self.size() - desktop = QApplication.desktop() + desktop = self.screen().geometry() width, height = size.width(), size.height() dwidth, dheight = desktop.width(), desktop.height() cw, ch = (dwidth/2)-(width/2), (dheight/2)-(height/2) @@ -196,7 +231,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): """Creates central widgets.""" self.stack = QStackedWidget(None) palette = self.stack.palette() - palette.setColor(self.stack.backgroundRole(), Qt.black) + palette.setColor(self.stack.backgroundRole(), Qt.GlobalColor.black) self.stack.setPalette(palette) self.stack.setAutoFillBackground(True) @@ -251,13 +286,16 @@ class MainWindow(QMainWindow, Ui_MainWindow): else: self.menubar.hide() self.statusbar.hide() - self.setWindowState(self.windowState() ^ Qt.WindowFullScreen) + self.setWindowState(self.windowState() ^ Qt.WindowState.WindowFullScreen) def on_file_open(self, filepath=None, filename=None): """Opens ROM file.""" if not filepath: action = self.sender() filepath = action.data() + if not os.path.isfile(filepath): + InfoDialog(self, "File %s not found." % filepath).exec() + return self.worker.core_state_query(M64CORE_EMU_STATE) if self.worker.state in [M64EMU_RUNNING, M64EMU_PAUSED]: self.worker.stop() @@ -291,10 +329,10 @@ class MainWindow(QMainWindow, Ui_MainWindow): def on_archive_dialog(self, files): """Shows archive dialog.""" archive = ArchiveDialog(self, files) - rval = archive.exec_() - if rval == QDialog.Accepted: + rval = archive.exec() + if rval == QDialog.DialogCode.Accepted: curr_item = archive.listWidget.currentItem() - fname = curr_item.data(Qt.UserRole) + fname = curr_item.data(Qt.ItemDataRole.UserRole) self.worker.filename = fname def on_state_changed(self, states): @@ -324,9 +362,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.actionGraphics.setEnabled(not action) self.actionPlugins.setEnabled(not action) - """Wait up to 10 seconds for core initialization, checking once a second. - If not yet initialized, start another QTimer. Else, toggle UI actions.""" def wait_for_initialize(self): + """Wait up to 10 seconds for core initialization, checking once a second. + If not yet initialized, start another QTimer. Else, toggle UI actions.""" if self.worker.core_state_query(M64CORE_EMU_STATE) == M64EMU_STOPPED: self._initialize_attempt += 1 if self._initialize_attempt < 10: @@ -361,7 +399,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): def on_actionManually_triggered(self): """Shows ROM file dialog.""" dialog = QFileDialog() - dialog.setFileMode(QFileDialog.ExistingFile) + dialog.setFileMode(QFileDialog.FileMode.ExistingFile) last_dir = self.settings.qset.value("last_dir") file_path, _ = dialog.getOpenFileName( self, self.tr("Load ROM Image"), last_dir, @@ -395,7 +433,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): def on_actionLoadFrom_triggered(self): """Loads state from file.""" dialog = QFileDialog() - dialog.setFileMode(QFileDialog.ExistingFile) + dialog.setFileMode(QFileDialog.FileMode.ExistingFile) file_path, _ = dialog.getOpenFileName( self, self.tr("Load State From File"), os.path.join(self.worker.core.config.get_path("UserData"), "save"), @@ -518,6 +556,6 @@ class View(QGraphicsView): QGraphicsView.__init__(self, parent) self.setContentsMargins(QMargins()) self.setStyleSheet("QGraphicsView {border:0px solid;margin:0px;}") - self.setResizeAnchor(QGraphicsView.AnchorViewCenter) + self.setResizeAnchor(QGraphicsView.ViewportAnchor.AnchorViewCenter) self.setScene(QGraphicsScene(self)) self.scene().addItem(QGraphicsPixmapItem(QPixmap(":/images/front.png"))) diff --git a/src/m64py/frontend/plugin.py b/src/m64py/frontend/plugin.py index 39a8fbb..b50d8a2 100644 --- a/src/m64py/frontend/plugin.py +++ b/src/m64py/frontend/plugin.py @@ -14,8 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtCore import Qt -from PyQt5.QtWidgets import QDialog, QLabel, QSpinBox, QComboBox, QLineEdit, QCheckBox +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import QDialog, QLabel, QSpinBox, QComboBox, QLineEdit, QCheckBox import re from m64py.core.defs import * @@ -84,8 +84,8 @@ class Plugin(QDialog, Ui_PluginDialog): widget = QLineEdit() widget.setToolTip(param_help) self.gridLayout.addWidget( - QLabel(format_label(param_desc)), row1, 1, Qt.AlignRight) - self.gridLayout.addWidget(widget, row1, 2, Qt.AlignLeft) + QLabel(format_label(param_desc)), row1, 1, Qt.AlignmentFlag.AlignRight) + self.gridLayout.addWidget(widget, row1, 2, Qt.AlignmentFlag.AlignLeft) self.widgets[param_name] = (widget, widget.__class__, opts) elif param_type == M64TYPE_INT: row1 += 1 @@ -98,7 +98,7 @@ class Plugin(QDialog, Ui_PluginDialog): widget = QComboBox() widget.setToolTip(param_help) widget.setMinimumContentsLength(14) - widget.setSizeAdjustPolicy(QComboBox.AdjustToMinimumContentsLength) + widget.setSizeAdjustPolicy(QComboBox.SizeAdjustPolicy.AdjustToMinimumContentsLengthWithIcon) for idx, key in enumerate(sorted(opts.keys())): value = opts[key] opts[key] = (idx, value) @@ -106,8 +106,8 @@ class Plugin(QDialog, Ui_PluginDialog): widget.addItem(value) widget.setItemData(idx, data) self.gridLayout.addWidget( - QLabel(format_label(param_desc)), row1, 1, Qt.AlignRight) - self.gridLayout.addWidget(widget, row1, 2, Qt.AlignLeft) + QLabel(format_label(param_desc)), row1, 1, Qt.AlignmentFlag.AlignRight) + self.gridLayout.addWidget(widget, row1, 2, Qt.AlignmentFlag.AlignLeft) self.widgets[param_name] = (widget, widget.__class__, opts) elif param_type == M64TYPE_BOOL: row2 += 1 diff --git a/src/m64py/frontend/recentfiles.py b/src/m64py/frontend/recentfiles.py index 7901a80..9cc52f2 100644 --- a/src/m64py/frontend/recentfiles.py +++ b/src/m64py/frontend/recentfiles.py @@ -14,9 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtGui import QIcon, QPixmap -from PyQt5.QtWidgets import QAction -from PyQt5.QtCore import QFileInfo +from PyQt6.QtGui import QIcon, QPixmap, QAction +from PyQt6.QtCore import QFileInfo class RecentFiles(): diff --git a/src/m64py/frontend/rominfo.py b/src/m64py/frontend/rominfo.py index 7f21bf4..16c16fa 100644 --- a/src/m64py/frontend/rominfo.py +++ b/src/m64py/frontend/rominfo.py @@ -16,7 +16,7 @@ import os -from PyQt5.QtWidgets import QMessageBox +from PyQt6.QtWidgets import QMessageBox from m64py.utils import sl diff --git a/src/m64py/frontend/romlist.py b/src/m64py/frontend/romlist.py index 036b2c7..da4b06a 100644 --- a/src/m64py/frontend/romlist.py +++ b/src/m64py/frontend/romlist.py @@ -16,9 +16,9 @@ import os -from PyQt5.QtCore import Qt -from PyQt5.QtGui import QPixmap -from PyQt5.QtWidgets import QMainWindow, QDesktopWidget, QListWidgetItem, QGraphicsPixmapItem +from PyQt6.QtCore import Qt +from PyQt6.QtGui import QPixmap +from PyQt6.QtWidgets import QMainWindow, QListWidgetItem, QGraphicsPixmapItem from m64py.frontend.romreader import ROMReader from m64py.ui.romlist_ui import Ui_ROMList @@ -37,7 +37,7 @@ class ROMList(QMainWindow, Ui_ROMList): """Constructor.""" QMainWindow.__init__(self, parent) self.setupUi(self) - self.setAttribute(Qt.WA_DeleteOnClose, True) + self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True) self.parent = parent self.core = self.parent.worker.core @@ -47,7 +47,7 @@ class ROMList(QMainWindow, Ui_ROMList): self.snapshot_item = None rect = self.frameGeometry() - rect.moveCenter(QDesktopWidget().availableGeometry().center()) + rect.moveCenter(self.screen().geometry().center()) self.move(rect.topLeft()) self.splitter.setStretchFactor(0, 1) self.splitter.setStretchFactor(1, 2) @@ -73,7 +73,7 @@ class ROMList(QMainWindow, Ui_ROMList): self.reader.stop() def keyPressEvent(self, event): - if event.key() == Qt.Key_Escape: + if event.key() == Qt.Key.Key_Escape: self.close() def connect_signals(self): @@ -95,7 +95,7 @@ class ROMList(QMainWindow, Ui_ROMList): if isinstance(goodname, bytes): goodname = goodname.decode() list_item = QListWidgetItem(goodname) - list_item.setData(Qt.UserRole, (crc, goodname, path, fname)) + list_item.setData(Qt.ItemDataRole.UserRole, (crc, goodname, path, fname)) self.listWidget.addItem(list_item) self.progressBar.setValue(0) self.progressBar.hide() @@ -135,19 +135,19 @@ class ROMList(QMainWindow, Ui_ROMList): def on_item_open(self): item = self.listWidget.currentItem() - crc, goodname, path, fname = item.data(Qt.UserRole) + crc, goodname, path, fname = item.data(Qt.ItemDataRole.UserRole) if path: self.file_open(path, fname) def on_item_activated(self, item): - crc, goodname, path, fname = item.data(Qt.UserRole) + crc, goodname, path, fname = item.data(Qt.ItemDataRole.UserRole) if path: self.file_open(path, fname) def on_item_changed(self, current, previous): if not current: return - crc, goodname, path, fname = current.data(Qt.UserRole) + crc, goodname, path, fname = current.data(Qt.ItemDataRole.UserRole) title = QPixmap(os.path.join( self.user_data_path, "title", "%s.png") % crc) @@ -169,9 +169,9 @@ class ROMList(QMainWindow, Ui_ROMList): self.snapshotView.scene().removeItem(self.snapshot_item) title_pixmap = title.scaled( - self.titleView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) + self.titleView.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) snapshot_pixmap = snapshot.scaled( - self.snapshotView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) + self.snapshotView.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) title_item = QGraphicsPixmapItem(title_pixmap) snapshot_item = QGraphicsPixmapItem(snapshot_pixmap) diff --git a/src/m64py/frontend/romreader.py b/src/m64py/frontend/romreader.py index 6ffc114..b0d534c 100644 --- a/src/m64py/frontend/romreader.py +++ b/src/m64py/frontend/romreader.py @@ -18,7 +18,7 @@ import os import ctypes import fnmatch -from PyQt5.QtCore import QThread +from PyQt6.QtCore import QThread from m64py.utils import sl from m64py.core.defs import M64pRomHeader @@ -99,7 +99,7 @@ class ROMReader(QThread): crc2 |= ((crc2_pre >> 24) & 0xff) << 0 else: return None - return (crc1, crc2) + return crc1, crc2 def read_files(self): """Reads files.""" @@ -115,9 +115,11 @@ class ROMReader(QThread): if crc_tuple: rom_settings = self.parent.core.get_rom_settings( crc_tuple[0], crc_tuple[1]) + crc = "%X%X" % (crc_tuple[0], crc_tuple[1]) if rom_settings: - crc = "%X%X" % (crc_tuple[0], crc_tuple[1]) self.roms.append((crc, rom_settings.goodname, fullpath, fname)) + else: + self.roms.append((crc, os.path.splitext(os.path.basename(fname))[0], fullpath, fname)) archive.close() except Exception as err: log.warn(str(err)) @@ -135,4 +137,4 @@ class ROMReader(QThread): def run(self): """Starts thread.""" self.read_files() - self.exec_() + self.exec() diff --git a/src/m64py/frontend/settings.py b/src/m64py/frontend/settings.py index a776d98..6dd611d 100644 --- a/src/m64py/frontend/settings.py +++ b/src/m64py/frontend/settings.py @@ -17,8 +17,8 @@ import os import sys -from PyQt5.QtCore import Qt, QSettings -from PyQt5.QtWidgets import QDialog, QFileDialog, QRadioButton, QVBoxLayout +from PyQt6.QtCore import Qt, QSettings +from PyQt6.QtWidgets import QDialog, QFileDialog, QRadioButton, QVBoxLayout from m64py.core.defs import * from m64py.loader import find_library @@ -42,7 +42,7 @@ class Settings(QDialog, Ui_Settings): self.combomap = {} self.qset = QSettings("m64py", "m64py") - self.qset.setDefaultFormat(QSettings.IniFormat) + self.qset.setDefaultFormat(QSettings.Format.IniFormat) self.add_items() self.connect_signals() @@ -130,11 +130,11 @@ class Settings(QDialog, Ui_Settings): widget, groupbox, directory = args dialog = QFileDialog() if directory: - dialog.setFileMode(QFileDialog.Directory) + dialog.setFileMode(QFileDialog.FileMode.Directory) path = dialog.getExistingDirectory( - self, groupbox.title(), widget.text(), QFileDialog.ShowDirsOnly) + self, groupbox.title(), widget.text(), QFileDialog.Option.ShowDirsOnly) else: - dialog.setFileMode(QFileDialog.ExistingFile) + dialog.setFileMode(QFileDialog.FileMode.ExistingFile) path, _ = dialog.getOpenFileName( self, groupbox.title(), widget.text(), "%s (*%s);;All files (*)" % (groupbox.title(), DLL_FILTER)) @@ -297,7 +297,7 @@ class Settings(QDialog, Ui_Settings): combo.addItem(name) index = combo.findText(str(name)) combo.setItemData(index, plugin_desc) - combo.setItemData(index, plugin_desc, Qt.ToolTipRole) + combo.setItemData(index, plugin_desc, Qt.ItemDataRole.ToolTipRole) current = self.qset.value("Plugins/%s" % ( PLUGIN_NAME[plugin_type]), PLUGIN_DEFAULT[plugin_type]) index = combo.findText(current) @@ -319,7 +319,7 @@ class Settings(QDialog, Ui_Settings): "%sx%s" % (w, h), (w, h)) index = self.comboResolution.findText( - "%sx%s" % (width, height), Qt.MatchExactly) + "%sx%s" % (width, height), Qt.MatchFlag.MatchExactly) if index == -1: index = 0 self.comboResolution.setCurrentIndex(index) self.comboResolution.setEnabled(not self.parent.vidext) diff --git a/src/m64py/frontend/worker.py b/src/m64py/frontend/worker.py index c3bd49f..ea1ca7e 100644 --- a/src/m64py/frontend/worker.py +++ b/src/m64py/frontend/worker.py @@ -17,7 +17,7 @@ import os import shutil -from PyQt5.QtCore import QThread, QTimer +from PyQt6.QtCore import QThread, QTimer from sdl2 import SDL_EnableScreenSaver, SDL_DisableScreenSaver from m64py.utils import sl diff --git a/src/m64py/ui/about.ui b/src/m64py/ui/about.ui index b20164b..b66534a 100644 --- a/src/m64py/ui/about.ui +++ b/src/m64py/ui/about.ui @@ -45,10 +45,9 @@ <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; color:#000000;">M64Py version: FRONTEND_VERSION</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="https://m64py.sourceforge.net/"><span style=" text-decoration: underline; color:#0000ff;">M64Py</span></a><span style=" font-size:10pt;"> version: FRONTEND_VERSION</span></p> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-style:italic;">A frontend for Mupen64Plus.</span></p> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://m64py.sourceforge.net"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">http://m64py.sourceforge.net</span></a></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt; text-decoration: underline; color:#0000ff;"><br /></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Author: Milan Nikolic (gen2brain)</span></p> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">This program is released under the terms of the</span></p> <p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.gnu.org/licenses/gpl-3.0.txt"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">GNU General Public License version 3</span></a><span style=" font-size:10pt;">.</span></p> @@ -68,65 +67,65 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Liberation Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Mupen64Plus is licensed under the</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.gnu.org/licenses/gpl-2.0.txt"><span style=" font-family:'Sans Serif'; text-decoration: underline; color:#0000ff;">GNU General Public License version 2</span></a><span style=" font-family:'Sans Serif';">.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The authors of Mupen64Plus are:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Richard Goedeken (Richard42)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Sven Eckelmann (ecsv)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * John Chadwick (NMN)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * James Hood (Ebenblues)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Scott Gorman (okaygo)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Scott Knauert (Tillin9)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Jesse Dean (DarkJezter)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Louai Al-Khanji (slougi)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Bob Forder (orbitaldecay)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Jason Espinosa (hasone)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Bobby Smiles (bsmiles32)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Dorian Fevrier (Narann)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Richard Hender (ricrpi)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Will Nayes (wnayes)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Conchur Navid</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Gillou68310</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * HyperHacker</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * littleguy77</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Nebuleon</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * and others.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Mupen64Plus API documentation (located in doc/emuwiki-api-doc/*) is Copyright(C) 2009-2011</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">by Richard Goedeken and is licensed under the GNU General Public License version 2.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Mupen64Plus is based on GPL-licensed source code from Mupen64 v0.5, originally written by:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Hacktarux</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Dave2001</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Zilmar</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Gregor Anich (Blight)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Juha Luotio (JttL)</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * and others.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">GPL-license demo rom (mupen64plus.v64) is written by:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Marshallh</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The OGLFT library used for the On-Screen Display is based on GPL/LGPL-licensed code Copyright 2002 lignum Computing.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">More information about this library is available at the following websites:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> - </span><a href="http://oglft.sourceforge.net/index.html"><span style=" font-family:'Sans Serif'; text-decoration: underline; color:#0000ff;">http://oglft.sourceforge.net/index.html</span></a></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> - </span><a href="http://directory.fsf.org/project/OGLFT/"><span style=" font-family:'Sans Serif'; text-decoration: underline; color:#0000ff;">http://directory.fsf.org/project/OGLFT/</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">Additionally, mupen includes a number of components licensed under other OSI approved licenses:</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The BSD license:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * minizip by Gilles Vollant and others,</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="ftp://ftp.info-zip.org/pub/infozip/license.html"><span style=" font-family:'Sans Serif'; text-decoration: underline; color:#0000ff;">ftp://ftp.info-zip.org/pub/infozip/license.html</span></a></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The zlib/libpng license:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * Adler-32 by Mark Adler</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * libpng by Glenn Randers-Pehrson, Peter Deutsch, and Guy Eric Schalnat</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * MD5 hashing code by Peter Deutsch</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';">The Bitstream license:</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif';"> * The TrueType font (data/font.ttf) is licensed by the Bitstream license.</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif';"><br /></p></body></html> +</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Mupen64Plus is licensed under the</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="http://www.gnu.org/licenses/gpl-2.0.txt"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">GNU General Public License version 2</span></a><span style=" font-size:10pt;">.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The authors of Mupen64Plus are:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Richard Goedeken (Richard42)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Sven Eckelmann (ecsv)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * John Chadwick (NMN)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * James Hood (Ebenblues)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Scott Gorman (okaygo)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Scott Knauert (Tillin9)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Jesse Dean (DarkJezter)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Louai Al-Khanji (slougi)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Bob Forder (orbitaldecay)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Jason Espinosa (hasone)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Bobby Smiles (bsmiles32)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Dorian Fevrier (Narann)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Richard Hender (ricrpi)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Will Nayes (wnayes)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Conchur Navid</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Gillou68310</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * HyperHacker</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * littleguy77</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Nebuleon</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * and others.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Mupen64Plus API documentation (located in doc/emuwiki-api-doc/*) is Copyright(C) 2009-2011</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">by Richard Goedeken and is licensed under the GNU General Public License version 2.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Mupen64Plus is based on GPL-licensed source code from Mupen64 v0.5, originally written by:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Hacktarux</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Dave2001</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Zilmar</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Gregor Anich (Blight)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Juha Luotio (JttL)</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * and others.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">GPL-license demo rom (mupen64plus.v64) is written by:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Marshallh</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The OGLFT library used for the On-Screen Display is based on GPL/LGPL-licensed code Copyright 2002 lignum Computing.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">More information about this library is available at the following websites:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> - </span><a href="http://oglft.sourceforge.net/index.html"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">http://oglft.sourceforge.net/index.html</span></a></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> - </span><a href="http://directory.fsf.org/project/OGLFT/"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">http://directory.fsf.org/project/OGLFT/</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">Additionally, mupen includes a number of components licensed under other OSI approved licenses:</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The BSD license:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * minizip by Gilles Vollant and others,</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="ftp://ftp.info-zip.org/pub/infozip/license.html"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">ftp://ftp.info-zip.org/pub/infozip/license.html</span></a></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The zlib/libpng license:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * Adler-32 by Mark Adler</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * libpng by Glenn Randers-Pehrson, Peter Deutsch, and Guy Eric Schalnat</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * MD5 hashing code by Peter Deutsch</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;">The Bitstream license:</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt;"> * The TrueType font (data/font.ttf) is licensed by the Bitstream license.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html> true diff --git a/src/m64py/ui/cheat.ui b/src/m64py/ui/cheat.ui index feea1ea..98f515c 100644 --- a/src/m64py/ui/cheat.ui +++ b/src/m64py/ui/cheat.ui @@ -159,38 +159,18 @@ QGroupBox::title { 0 - - background: #FFF; - true - - - 0 - 0 - 308 - 44 - - - - - 0 - 0 - - - - - 0 - 0 - - - + + + + Qt::PlainText Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -198,6 +178,9 @@ QGroupBox::title { true + + Qt::TextSelectableByMouse + diff --git a/src/m64py/ui/imageview.py b/src/m64py/ui/imageview.py index 8025499..6197942 100644 --- a/src/m64py/ui/imageview.py +++ b/src/m64py/ui/imageview.py @@ -14,8 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene -from PyQt5.QtCore import Qt, QRectF +from PyQt6.QtWidgets import QGraphicsView, QGraphicsScene +from PyQt6.QtCore import Qt, QRectF class ImageView(QGraphicsView): @@ -28,7 +28,7 @@ class ImageView(QGraphicsView): for item in self.scene().items(): pixmap = item.pixmap() pixmap = pixmap.scaled( - size, Qt.KeepAspectRatio, Qt.SmoothTransformation) + size, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation) item.setPixmap(pixmap) self.ensureVisible(item) self.centerOn(item) diff --git a/src/m64py/ui/inputbutton.py b/src/m64py/ui/inputbutton.py index 2307c5c..0335f04 100644 --- a/src/m64py/ui/inputbutton.py +++ b/src/m64py/ui/inputbutton.py @@ -14,8 +14,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from PyQt5.QtWidgets import QPushButton -from PyQt5.QtCore import Qt +from PyQt6.QtWidgets import QPushButton +from PyQt6.QtCore import Qt from sdl2.keyboard import SDL_GetScancodeName @@ -35,7 +35,7 @@ class InputButton(QPushButton): self.parent = parent self.input = None self.joystick = None - self.setFocusPolicy(Qt.ClickFocus) + self.setFocusPolicy(Qt.FocusPolicy.ClickFocus) def showEvent(self, event): dialog = self.parent.parentWidget().parent() @@ -55,15 +55,15 @@ class InputButton(QPushButton): def keyPressEvent(self, event): modifier = event.modifiers() - if modifier == Qt.NoModifier or modifier == Qt.KeypadModifier: + if modifier == Qt.KeyboardModifier.NoModifier or modifier == Qt.KeyboardModifier.KeypadModifier: key = event.key() else: key = modifier.__int__() - if key == Qt.Key_Escape: + if key == Qt.Key.Key_Escape: text = self.key self.setCheckable(False) - elif key == Qt.Key_Backspace: + elif key == Qt.Key.Key_Backspace: text = self.tr("Select...") self.setCheckable(False) else: