Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to PyQt6 #285

Merged
merged 1 commit into from
Jan 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ jobs:
if [ "${{ runner.os }}" = "Windows" ]; then
source pyenv/Scripts/activate
else
# Qt6 complains because Ubuntu is missing libEGL.so.1
if [ "${{ runner.os }}" = "Linux" ]; then
sudo apt-get update -y -qq
sudo apt-get install -y -qq libegl1
fi
source pyenv/bin/activate
fi
python -m pip install aqt==${{ matrix.anki }} anki==${{ matrix.anki }} pyqtwebengine pylint
python -m pip install aqt==${{ matrix.anki }} anki==${{ matrix.anki }} PyQt6-WebEngine pylint
- name: Lint
shell: bash
run: |
Expand All @@ -50,4 +55,3 @@ jobs:
export QT_QPA_PLATFORM=minimal
export PYTHONPATH=./
python test.py

2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[MASTER]
ignore=deps
extension-pkg-whitelist=PyQt5
extension-pkg-whitelist=PyQt6

[MESSAGES CONTROL]
disable=C,R,
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ See the [MorphMan wiki](https://github.com/kaegi/MorphMan/wiki) for more informa
```
python -m virtualenv pyenv
source pyenv/bin/activate
python -m pip install aqt==2.1.54 anki==2.1.54 pyqtwebengine pylint
python -m pip install aqt==2.1.54 anki==2.1.54 pyqt6-webengine pylint
export PYTHONPATH=./
```
- Run tests: `python test.py`
Expand Down
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .morph.util import *
from PyQt5.QtWidgets import *
from PyQt6.QtWidgets import *
import anki.stats
from anki.hooks import wrap

Expand Down
2 changes: 1 addition & 1 deletion morph/UI/morphemizerComboBox.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

from PyQt5.QtWidgets import QComboBox
from PyQt6.QtWidgets import QComboBox


class MorphemizerComboBox(QComboBox):
Expand Down
2 changes: 1 addition & 1 deletion morph/browser/massTagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

def pre(b): # :: Browser -> State
note_count = len(b.selectedNotes())
tags, ok = QInputDialog.getText(b, 'Enter tags (e.x \"tag1 tag2\")', 'Tags', QLineEdit.Normal, 'hasMorph')
tags, ok = QInputDialog.getText(b, 'Enter tags (e.x \"tag1 tag2\")', 'Tags', QLineEdit.EchoMode.Normal, 'hasMorph')
if not ok or not tags:
return

Expand Down
6 changes: 3 additions & 3 deletions morph/customTableWidget.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from PyQt5.QtWidgets import QApplication, QTableWidget
from PyQt5.QtGui import QKeySequence
from PyQt6.QtWidgets import QApplication, QTableWidget
from PyQt6.QtGui import QKeySequence

class CustomTableWidget(QTableWidget):

def keyPressEvent(self, event):
if event.matches(QKeySequence.Copy):
if event.matches(QKeySequence.StandardKey.Copy):
text = ''
sel_range = self.selectionModel().selection().first()

Expand Down
3 changes: 3 additions & 0 deletions morph/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ def mkAllDb(all_db=None):
except KeyError:
continue
except TypeError:
# We need to finish the progress bar before presenting an error window or the UI will hang waiting on progress updates.
# The proper solution here is probably to not block the main thread at all by doing the recalc in the background.
mw.progress.finish()
mname = mw.col.models.get(mid)['name']
errorMsg('Failed to get field "{field}" from a note of model "{model}". Please fix your Note Filters '
'under MorphMan > Preferences to match your collection appropriately.'.format(
Expand Down
10 changes: 5 additions & 5 deletions morph/manager.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
import os

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
from anki.utils import is_mac
from .UI import MorphemizerComboBox

Expand All @@ -22,15 +22,15 @@ def getPath(le): # LineEdit -> GUI ()
def getProgressWidget():
progressWidget = QWidget()
progressWidget.setFixedSize(400, 70)
progressWidget.setWindowModality(Qt.ApplicationModal)
progressWidget.setWindowModality(Qt.WindowModality.ApplicationModal)
bar = QProgressBar(progressWidget)
if is_mac:
bar.setFixedSize(380, 50)
else:
bar.setFixedSize(390, 50)
bar.move(10, 10)
per = QLabel(bar)
per.setAlignment(Qt.AlignCenter)
per.setAlignment(Qt.AlignmentFlag.AlignCenter)
progressWidget.show()
return progressWidget, bar

Expand Down
42 changes: 21 additions & 21 deletions morph/preferencesDialog.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt6.QtCore import *
from PyQt6.QtWidgets import *
from PyQt6.QtGui import *
from anki.lang import _

from aqt.utils import tooltip
Expand Down Expand Up @@ -47,15 +47,15 @@ def createNoteFilterTab(self):
self.tableModel = QStandardItemModel(0, 6)
self.tableView = QTableView()
self.tableView.setModel(self.tableModel)
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows)
self.tableView.setSelectionMode(QAbstractItemView.SingleSelection)
self.tableModel.setHeaderData(0, Qt.Horizontal, "Note type")
self.tableModel.setHeaderData(1, Qt.Horizontal, "Tags")
self.tableModel.setHeaderData(2, Qt.Horizontal, "Fields")
self.tableModel.setHeaderData(3, Qt.Horizontal, "Morphemizer")
self.tableModel.setHeaderData(4, Qt.Horizontal, "Read?")
self.tableModel.setHeaderData(5, Qt.Horizontal, "Modify?")
self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
self.tableView.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.tableView.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.tableModel.setHeaderData(0, Qt.Orientation.Horizontal, "Note type")
self.tableModel.setHeaderData(1, Qt.Orientation.Horizontal, "Tags")
self.tableModel.setHeaderData(2, Qt.Orientation.Horizontal, "Fields")
self.tableModel.setHeaderData(3, Qt.Orientation.Horizontal, "Morphemizer")
self.tableModel.setHeaderData(4, Qt.Orientation.Horizontal, "Read?")
self.tableModel.setHeaderData(5, Qt.Orientation.Horizontal, "Modify?")

rowData = get_preference('Filter')
self.tableModel.setRowCount(len(rowData))
Expand Down Expand Up @@ -178,7 +178,7 @@ def createTagsTab(self):
self.checkboxSetNotRequiredTags = QCheckBox(
"Add tags even if not required")
self.checkboxSetNotRequiredTags.setCheckState(
Qt.Checked if get_preference('Option_SetNotRequiredTags') else Qt.Unchecked)
Qt.CheckState.Checked if get_preference('Option_SetNotRequiredTags') else Qt.CheckState.Unchecked)
vbox.addWidget(self.checkboxSetNotRequiredTags)

vbox.addStretch()
Expand Down Expand Up @@ -236,7 +236,7 @@ def createGeneralTab(self):
self.boolOptionList = []
for i, (layout, name, key, tooltipInfo) in enumerate(optionList):
checkBox = QCheckBox(name)
checkBox.setCheckState(Qt.Checked if get_preference(key) else Qt.Unchecked)
checkBox.setCheckState(Qt.CheckState.Checked if get_preference(key) else Qt.CheckState.Unchecked)
checkBox.setToolTip(tooltipInfo)
checkBox.setMinimumSize(0, 30)
self.boolOptionList.append((key, checkBox))
Expand All @@ -250,7 +250,7 @@ def createButtons(self):
hbox = QHBoxLayout()
self.vbox.addLayout(hbox)
buttonCancel = QPushButton("&Cancel")
hbox.addWidget(buttonCancel, 1, Qt.AlignRight)
hbox.addWidget(buttonCancel, 1, Qt.AlignmentFlag.AlignRight)
buttonCancel.setMaximumWidth(150)
buttonCancel.clicked.connect(self.onCancel)

Expand Down Expand Up @@ -282,11 +282,11 @@ def setTableRow(self, rowIndex, data):

readItem = QStandardItem()
readItem.setCheckable(True)
readItem.setCheckState(Qt.Checked if data.get('Read', True) else Qt.Unchecked)
readItem.setCheckState(Qt.CheckState.Checked if data.get('Read', True) else Qt.CheckState.Unchecked)

modifyItem = QStandardItem()
modifyItem.setCheckable(True)
modifyItem.setCheckState(Qt.Checked if data.get('Modify', True) else Qt.Unchecked)
modifyItem.setCheckState(Qt.CheckState.Checked if data.get('Modify', True) else Qt.CheckState.Unchecked)

rowGui['modelComboBox'] = modelComboBox
rowGui['tagsEntry'] = QLineEdit(', '.join(data['Tags']))
Expand Down Expand Up @@ -327,8 +327,8 @@ def rowGuiToFilter(row_gui):
x for x in row_gui['fieldsEntry'].text().split(', ') if x]

filter['Morphemizer'] = row_gui['morphemizerComboBox'].getCurrent().getName()
filter['Read'] = row_gui['readCheckBox'].checkState() != Qt.Unchecked
filter['Modify'] = row_gui['modifyCheckBox'].checkState() != Qt.Unchecked
filter['Read'] = row_gui['readCheckBox'].checkState() != Qt.CheckState.Unchecked
filter['Modify'] = row_gui['modifyCheckBox'].checkState() != Qt.CheckState.Unchecked

return filter

Expand All @@ -339,14 +339,14 @@ def readConfigFromGui(self):
for (key, entry) in self.tagEntryList:
cfg[key] = entry.text()
for (key, checkBox) in self.boolOptionList:
cfg[key] = (checkBox.checkState() == Qt.Checked)
cfg[key] = (checkBox.checkState() == Qt.CheckState.Checked)

cfg['Filter'] = []
for i, rowGui in enumerate(self.rowGui):
cfg['Filter'].append(self.rowGuiToFilter(rowGui))

cfg['Option_SetNotRequiredTags'] = self.checkboxSetNotRequiredTags.checkState(
) != Qt.Unchecked
) != Qt.CheckState.Unchecked

return cfg

Expand Down
24 changes: 12 additions & 12 deletions morph/readability.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
from collections import namedtuple
from contextlib import redirect_stdout, redirect_stderr

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *

try:
from PyQt5 import QtWebSockets, QtNetwork
from PyQt6 import QtWebSockets, QtNetwork
except:
pass

Expand Down Expand Up @@ -104,7 +104,7 @@ def getPath(le, caption, open_directory=False): # LineEdit -> GUI ()
try:
if open_directory:
path = QFileDialog.getExistingDirectory(caption=caption, directory=start_path,
options=QFileDialog.ShowDirsOnly)
options=QFileDialog.Option.ShowDirsOnly)
else:
path = QFileDialog.getOpenFileName(caption=caption, directory=start_path)[0]
except:
Expand Down Expand Up @@ -271,7 +271,7 @@ def load(self, path, save_lines=False):
class TableInteger(QTableWidgetItem):
def __init__(self, value):
super(TableInteger, self).__init__(str(int(value)))
self.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.setTextAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)

def __lt__(self, other):
lvalue = self.text()
Expand All @@ -281,7 +281,7 @@ def __lt__(self, other):
class TableFloat(QTableWidgetItem):
def __init__(self, value):
super(TableFloat, self).__init__('%0.03f' % value)
self.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.setTextAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)

def __lt__(self, other):
lvalue = self.text()
Expand All @@ -291,7 +291,7 @@ def __lt__(self, other):
class TablePercent(QTableWidgetItem):
def __init__(self, value):
super(TablePercent, self).__init__('%0.02f' % value)
self.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)
self.setTextAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignVCenter)

def __lt__(self, other):
lvalue = self.text()
Expand Down Expand Up @@ -433,8 +433,8 @@ def __init__(self, parent=None):
self.clients = set()

if cfg('Option_EnableWebService'):
self.server = QtWebSockets.QWebSocketServer('MorphMan Service', QtWebSockets.QWebSocketServer.NonSecureMode)
if self.server.listen(QtNetwork.QHostAddress.LocalHost, 9779):
self.server = QtWebSockets.QWebSocketServer('MorphMan Service', QtWebSockets.QWebSocketServer.SslMode.NonSecureMode)
if self.server.listen(QtNetwork.QHostAddress.SpecialAddress.LocalHost, 9779):
self.write('Web Service Created: '+self.server.serverName()+' : '+self.server.serverAddress().toString()+':'+str(self.server.serverPort()) + '\n')
else:
self.write("Could't create Web Service\n")
Expand Down Expand Up @@ -568,11 +568,11 @@ def clearOutput(self):
self.ui.outputText.clear()

def writeOutput(self, m):
self.ui.outputText.moveCursor(QTextCursor.End)
self.ui.outputText.moveCursor(QTextCursor.MoveOperation.End)
self.ui.outputText.insertPlainText(m)

def write(self, txt):
self.ui.outputText.moveCursor(QTextCursor.End)
self.ui.outputText.moveCursor(QTextCursor.MoveOperation.End)
self.ui.outputText.insertPlainText(txt)

def flush(self):
Expand Down
22 changes: 10 additions & 12 deletions morph/readability_settings_ui.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'morph/readability_settings.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
# Created by: PyQt6 UI code generator 6.4.0
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# WARNING: Any manual changes made to this file will be lost when pyuic6 is
# run again. Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt6 import QtCore, QtGui, QtWidgets


class Ui_ReadabilitySettingsDialog(object):
Expand All @@ -35,28 +33,28 @@ def setupUi(self, ReadabilitySettingsDialog):
self.resetLearnedAfterEachInputCheckBox.setObjectName("resetLearnedAfterEachInputCheckBox")
self.verticalLayout.addWidget(self.resetLearnedAfterEachInputCheckBox)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint)
self.horizontalLayout.setObjectName("horizontalLayout")
self.optimalMasterTargetLabel = QtWidgets.QLabel(self.studyPlanGroup)
self.optimalMasterTargetLabel.setMinimumSize(QtCore.QSize(0, 0))
self.optimalMasterTargetLabel.setObjectName("optimalMasterTargetLabel")
self.horizontalLayout.addWidget(self.optimalMasterTargetLabel)
self.optimalMasterTargetSpinBox = QtWidgets.QDoubleSpinBox(self.studyPlanGroup)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.optimalMasterTargetSpinBox.sizePolicy().hasHeightForWidth())
self.optimalMasterTargetSpinBox.setSizePolicy(sizePolicy)
self.optimalMasterTargetSpinBox.setMinimumSize(QtCore.QSize(0, 0))
self.optimalMasterTargetSpinBox.setMaximumSize(QtCore.QSize(16777215, 16777215))
self.optimalMasterTargetSpinBox.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
self.optimalMasterTargetSpinBox.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter)
self.optimalMasterTargetSpinBox.setPrefix("")
self.optimalMasterTargetSpinBox.setMinimum(0.0)
self.optimalMasterTargetSpinBox.setMaximum(100.0)
self.optimalMasterTargetSpinBox.setProperty("value", 0.0)
self.optimalMasterTargetSpinBox.setObjectName("optimalMasterTargetSpinBox")
self.horizontalLayout.addWidget(self.optimalMasterTargetSpinBox)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum)
self.horizontalLayout.addItem(spacerItem)
self.verticalLayout.addLayout(self.horizontalLayout)
self.verticalLayout_3.addWidget(self.studyPlanGroup)
Expand Down Expand Up @@ -98,11 +96,11 @@ def setupUi(self, ReadabilitySettingsDialog):
self.webServiceCheckBox.setObjectName("webServiceCheckBox")
self.verticalLayout_4.addWidget(self.webServiceCheckBox)
self.verticalLayout_3.addWidget(self.extrasGroup)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding)
self.verticalLayout_3.addItem(spacerItem1)
self.buttonBox = QtWidgets.QDialogButtonBox(ReadabilitySettingsDialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.StandardButton.Cancel|QtWidgets.QDialogButtonBox.StandardButton.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout_3.addWidget(self.buttonBox)

Expand Down
Loading