Skip to content

Commit

Permalink
Upgrade to Qt 6.
Browse files Browse the repository at this point in the history
  • Loading branch information
Bart Feenstra committed Feb 17, 2022
1 parent 02fcb4b commit b622a85
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:

- name: Install APT dependencies
if: startsWith(runner.os, 'Linux')
run: sudo apt-get install herbstluftwm libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libxml2-dev libxslt1-dev xvfb
run: sudo apt-get update && sudo apt-get install herbstluftwm libegl1-mesa libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xfixes0 libxml2-dev libxslt1-dev xvfb

- name: Launch the window manager
if: startsWith(runner.os, 'Linux')
Expand Down
6 changes: 3 additions & 3 deletions betty/extension/gramps/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from xml.etree import ElementTree

import aiofiles
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QFormLayout, QPushButton, QFileDialog, QLineEdit, QHBoxLayout, QVBoxLayout, \
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QWidget, QFormLayout, QPushButton, QFileDialog, QLineEdit, QHBoxLayout, QVBoxLayout, \
QGridLayout
from geopy import Point
from reactives import reactive, ReactiveList
Expand Down Expand Up @@ -683,7 +683,7 @@ def _remove_family_tree() -> None:
self._family_trees_widget._remove_buttons.insert(i, QPushButton('Remove'))
self._family_trees_widget._remove_buttons[i].released.connect(_remove_family_tree)
family_trees_layout.addWidget(self._family_trees_widget._remove_buttons[i], i, 1)
self._layout.insertWidget(0, self._family_trees_widget, alignment=Qt.AlignTop)
self._layout.insertWidget(0, self._family_trees_widget, alignment=Qt.AlignmentFlag.AlignTop)

def _add_family_tree(self):
window = _AddFamilyTreeWindow(self._configuration.family_trees, self)
Expand Down
50 changes: 23 additions & 27 deletions betty/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@
from typing import Sequence, Type, Optional, Union
from urllib.parse import urlparse

from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QApplication, QDesktopWidget, QFileDialog, QMainWindow, QAction, qApp, QVBoxLayout, QLabel, \
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QObject, QCoreApplication
from PyQt6.QtGui import QIcon, QFont, QAction
from PyQt6.QtWidgets import QApplication, QFileDialog, QMainWindow, QVBoxLayout, QLabel, \
QWidget, QPushButton, QMessageBox, QLineEdit, QCheckBox, QFormLayout, QHBoxLayout, QGridLayout, QLayout, \
QStackedLayout, QComboBox, QButtonGroup, QRadioButton
from babel import Locale
Expand Down Expand Up @@ -94,16 +93,16 @@ class UnexpectedExceptionError(ExceptionError):
def __init__(self, exception: Exception, *args, **kwargs):
super(UnexpectedExceptionError, self).__init__(exception, *args, **kwargs)
self.setText('An unexpected error occurred and Betty could not complete the task. Please <a href="https://github.com/bartfeenstra/betty/issues">report this problem</a> and include the following details, so the team behind Betty can address it.')
self.setTextFormat(Qt.RichText)
self.setTextFormat(Qt.TextFormat.RichText)
self.setDetailedText(''.join(traceback.format_exception(type(exception), exception, exception.__traceback__)))


class Text(QLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setTextFormat(Qt.RichText)
self.setTextFormat(Qt.TextFormat.RichText)
self.setWordWrap(True)
self.setTextInteractionFlags(Qt.LinksAccessibleByKeyboard | Qt.LinksAccessibleByMouse | Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
self.setTextInteractionFlags(Qt.TextInteractionFlag.LinksAccessibleByKeyboard | Qt.TextInteractionFlag.LinksAccessibleByMouse | Qt.TextInteractionFlag.TextSelectableByKeyboard | Qt.TextInteractionFlag.TextSelectableByMouse)
self.setOpenExternalLinks(True)


Expand All @@ -128,7 +127,7 @@ def __init__(self, *args, **kwargs):
self.setWindowTitle(self.title)
self.setWindowIcon(QIcon(path.join(path.dirname(__file__), 'assets', 'public', 'static', 'betty-512x512.png')))
geometry = self.frameGeometry()
geometry.moveCenter(QDesktopWidget().availableGeometry().center())
geometry.moveCenter(QApplication.primaryScreen().availableGeometry().center())
self.move(geometry.topLeft())


Expand All @@ -140,9 +139,6 @@ class BettyMainWindow(BettyWindow):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowIcon(QIcon(path.join(path.dirname(__file__), 'assets', 'public', 'static', 'betty-512x512.png')))
geometry = self.frameGeometry()
geometry.moveCenter(QDesktopWidget().availableGeometry().center())
self.move(geometry.topLeft())
self._initialize_menu()

def _initialize_menu(self) -> None:
Expand Down Expand Up @@ -170,7 +166,7 @@ def _initialize_menu(self) -> None:

exit_action = QAction('Exit', self)
exit_action.setShortcut('Ctrl+Q')
exit_action.triggered.connect(qApp.quit)
exit_action.triggered.connect(QCoreApplication.quit)
self.betty_menu.addAction(exit_action)

self.help_menu = menu_bar.addMenu('&Help')
Expand Down Expand Up @@ -258,14 +254,14 @@ def __init__(self, *args, **kwargs):
self.setCentralWidget(central_widget)

welcome = _WelcomeTitle('Welcome to Betty')
welcome.setAlignment(QtCore.Qt.AlignCenter)
welcome.setAlignment(Qt.AlignmentFlag.AlignCenter)
central_layout.addWidget(welcome)

welcome_caption = _WelcomeText('Betty is a static site generator for your <a href="https://gramps-project.org/">Gramps</a> and <a href="https://en.wikipedia.org/wiki/GEDCOM">GEDCOM</a> family trees.')
central_layout.addWidget(welcome_caption)

project_instruction = _WelcomeHeading('Work on a new or existing site of your own')
project_instruction.setAlignment(QtCore.Qt.AlignCenter)
project_instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
central_layout.addWidget(project_instruction)

project_layout = QHBoxLayout()
Expand All @@ -280,7 +276,7 @@ def __init__(self, *args, **kwargs):
project_layout.addWidget(self.new_project_button)

demo_instruction = _WelcomeHeading('View a demonstration of what a Betty site looks like')
demo_instruction.setAlignment(QtCore.Qt.AlignCenter)
demo_instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
central_layout.addWidget(demo_instruction)

self.demo_button = _WelcomeAction('View a demo site', self)
Expand All @@ -293,7 +289,7 @@ def __init__(self, pane_selectors_layout: QLayout, panes_layout: QStackedLayout,
super().__init__(*args, **kwargs)
self.setProperty('pane-selector', 'true')
self.setFlat(panes_layout.currentWidget() != pane)
self.setCursor(Qt.PointingHandCursor)
self.setCursor(Qt.CursorShape.PointingHandCursor)
self.released.connect(lambda: [pane_selectors_layout.itemAt(i).widget().setFlat(True) for i in range(0, pane_selectors_layout.count())])
self.released.connect(lambda: self.setFlat(False))
self.released.connect(lambda: panes_layout.setCurrentWidget(pane))
Expand Down Expand Up @@ -493,7 +489,7 @@ def _build_locales_configuration(self) -> None:
self._locales_configuration_widget.setLayout(self._locales_configuration_layout)
self._locales_configuration_widget._remove_buttons = {}
self._locales_configuration_widget._default_buttons = {}
self._layout.insertWidget(0, self._locales_configuration_widget, alignment=Qt.AlignTop)
self._layout.insertWidget(0, self._locales_configuration_widget, alignment=Qt.AlignmentFlag.AlignTop)

for i, locale_configuration in enumerate(sorted(
self._app.configuration.locales,
Expand Down Expand Up @@ -586,7 +582,7 @@ def __init__(self, app: App, extension_type: Type[Union[Extension, GuiBuilder]],
self._app = app

layout = QVBoxLayout()
layout.setAlignment(QtCore.Qt.AlignTop)
layout.setAlignment(Qt.AlignmentFlag.AlignTop)
self.setLayout(layout)

enable_layout = QFormLayout()
Expand Down Expand Up @@ -645,10 +641,10 @@ def __init__(self, configuration_file_path: str, *args, **kwargs):
self.setCentralWidget(central_widget)

pane_selectors_layout = QVBoxLayout()
central_layout.addLayout(pane_selectors_layout, 0, 0, Qt.AlignTop | Qt.AlignLeft)
central_layout.addLayout(pane_selectors_layout, 0, 0, Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft)

panes_layout = QStackedLayout()
central_layout.addLayout(panes_layout, 0, 1, Qt.AlignTop | Qt.AlignRight)
central_layout.addLayout(panes_layout, 0, 1, Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight)

self._general_configuration_pane = _ProjectGeneralConfigurationPane(self._app)
panes_layout.addWidget(self._general_configuration_pane)
Expand Down Expand Up @@ -769,7 +765,7 @@ class _LogRecordViewerHandlerObject(QObject):

def __init__(self, viewer: LogRecordViewer):
super().__init__()
self.log.connect(viewer.log, Qt.QueuedConnection)
self.log.connect(viewer.log, Qt.ConnectionType.QueuedConnection)


class LogRecordViewerHandler(logging.Handler):
Expand Down Expand Up @@ -802,8 +798,8 @@ class _GenerateWindow(BettyWindow):
def __init__(self, app: App, *args, **kwargs):
super().__init__(*args, **kwargs)

self.setWindowModality(Qt.ApplicationModal)
self.setWindowFlags(self.windowFlags() ^ Qt.WindowCloseButtonHint)
self.setWindowModality(Qt.WindowModality.ApplicationModal)
self.setWindowFlags(self.windowFlags() ^ Qt.WindowType.WindowCloseButtonHint)

central_layout = QVBoxLayout()
central_widget = QWidget()
Expand Down Expand Up @@ -890,7 +886,7 @@ def __init__(self, *args, **kwargs):
self.setCentralWidget(central_widget)

self._loading_instruction = Text('Loading...')
self._loading_instruction.setAlignment(QtCore.Qt.AlignCenter)
self._loading_instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
self._central_layout.addWidget(self._loading_instruction)

@classmethod
Expand All @@ -910,11 +906,11 @@ def _server_started(self) -> None:
self._loading_instruction.close()

instance_instruction = Text(self._build_instruction())
instance_instruction.setAlignment(QtCore.Qt.AlignCenter)
instance_instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
self._central_layout.addWidget(instance_instruction)

general_instruction = Text('Keep this window open to keep the site running.')
general_instruction.setAlignment(QtCore.Qt.AlignCenter)
general_instruction.setAlignment(Qt.AlignmentFlag.AlignCenter)
self._central_layout.addWidget(general_instruction)

stop_server_button = QPushButton('Stop the site', self)
Expand Down Expand Up @@ -1003,7 +999,7 @@ def __init__(self, *args, **kwargs):
'Copyright 2019-%s <a href="twitter.com/bartFeenstra">Bart Feenstra</a> & contributors. Betty is made available to you under the <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">GNU General Public License, Version 3</a> (GPLv3).' % datetime.now().year,
'Follow Betty on <a href="https://twitter.com/Betty_Project">Twitter</a> and <a href="https://github.com/bartfeenstra/betty">Github</a>.'
])))
label.setAlignment(QtCore.Qt.AlignCenter)
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.setCentralWidget(label)


Expand Down
7 changes: 4 additions & 3 deletions betty/pytests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from typing import Union, List, Type, Dict

import pytest
from PyQt5 import QtCore
from PyQt5.QtWidgets import QMainWindow, QMenu, QAction, QWidget, QApplication
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import QMainWindow, QMenu, QWidget, QApplication

from betty.gui import Error

Expand Down Expand Up @@ -55,7 +56,7 @@ def _navigate(item: Union[QMainWindow, QMenu], attributes: List[str]) -> None:
attribute = attributes.pop(0)
item = getattr(item, attribute)
if isinstance(item, QMenu):
qtbot.mouseClick(item, QtCore.Qt.LeftButton)
qtbot.mouseClick(item, Qt.MouseButton.LeftButton)
elif isinstance(item, QAction):
item.trigger()
else:
Expand Down
16 changes: 8 additions & 8 deletions betty/pytests/extension/gramps/test__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from pathlib import Path

from PyQt5 import QtCore
from PyQt5.QtWidgets import QFileDialog
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QFileDialog
from reactives import ReactiveList

from betty.app import App
Expand All @@ -20,13 +20,13 @@ async def test_add_family_tree_set_path(assert_not_window, assert_window, tmpdir
qtbot.addWidget(widget)
widget.show()

qtbot.mouseClick(widget._add_family_tree_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(widget._add_family_tree_button, Qt.MouseButton.LeftButton)
add_family_tree_window = assert_window(_AddFamilyTreeWindow)

file_path = '/tmp/family-tree.gpkg'
add_family_tree_window._widget._file_path.setText(file_path)

qtbot.mouseClick(add_family_tree_window._widget._save_and_close, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_family_tree_window._widget._save_and_close, Qt.MouseButton.LeftButton)
assert_not_window(_AddFamilyTreeWindow)

assert len(sut._configuration.family_trees) == 1
Expand All @@ -44,13 +44,13 @@ async def test_add_family_tree_find_path(assert_window, mocker, tmpdir, qtbot) -
qtbot.addWidget(widget)
widget.show()

qtbot.mouseClick(widget._add_family_tree_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(widget._add_family_tree_button, Qt.MouseButton.LeftButton)

add_family_tree_window = assert_window(_AddFamilyTreeWindow)
file_path = '/tmp/family-tree.gpkg'
mocker.patch.object(QFileDialog, 'getOpenFileName', mocker.MagicMock(return_value=[file_path, None]))
qtbot.mouseClick(add_family_tree_window._widget._file_path_find, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_family_tree_window._widget._save_and_close, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_family_tree_window._widget._file_path_find, Qt.MouseButton.LeftButton)
qtbot.mouseClick(add_family_tree_window._widget._save_and_close, Qt.MouseButton.LeftButton)

assert len(sut._configuration.family_trees) == 1
family_tree = sut._configuration.family_trees[0]
Expand All @@ -74,7 +74,7 @@ async def test_remove_family_tree(tmpdir, qtbot) -> None:
qtbot.addWidget(widget)
widget.show()

qtbot.mouseClick(widget._family_trees_widget._remove_buttons[0], QtCore.Qt.LeftButton)
qtbot.mouseClick(widget._family_trees_widget._remove_buttons[0], Qt.MouseButton.LeftButton)

assert len(sut._configuration.family_trees) == 0
assert [] == widget._family_trees_widget._remove_buttons
20 changes: 10 additions & 10 deletions betty/pytests/test_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from os import path

import pytest
from PyQt5 import QtCore
from PyQt5.QtWidgets import QFileDialog
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QFileDialog
from babel import Locale

from betty import fs
Expand Down Expand Up @@ -65,7 +65,7 @@ def test_welcome_window_open_project_with_invalid_file_should_error(assert_error
# Purposefully leave the file empty so it is invalid.
configuration_file_path.write('')
mocker.patch.object(QFileDialog, 'getOpenFileName', mocker.MagicMock(return_value=[configuration_file_path, None]))
qtbot.mouseClick(sut.open_project_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(sut.open_project_button, Qt.MouseButton.LeftButton)

error = assert_error(ExceptionError)
assert isinstance(error.exception, ConfigurationError)
Expand All @@ -83,7 +83,7 @@ def test_welcome_window_open_project_with_valid_file_should_show_project_window(
'base_url': 'https://example.com',
}))
mocker.patch.object(QFileDialog, 'getOpenFileName', mocker.MagicMock(return_value=[configuration_file_path, None]))
qtbot.mouseClick(sut.open_project_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(sut.open_project_button, Qt.MouseButton.LeftButton)

assert_window(ProjectWindow)

Expand All @@ -96,7 +96,7 @@ def test_welcome_window_view_demo_site(assert_window, mocker, qtbot) -> None:
qtbot.addWidget(sut)
sut.show()

qtbot.mouseClick(sut.demo_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(sut.demo_button, Qt.MouseButton.LeftButton)

assert_window(_ServeDemoWindow)

Expand Down Expand Up @@ -208,15 +208,15 @@ def test_project_window_localization_configuration_add_locale(qtbot, assert_not_
qtbot.addWidget(sut)
sut.show()

qtbot.mouseClick(sut._localization_configuration_pane._add_locale_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(sut._localization_configuration_pane._add_locale_button, Qt.MouseButton.LeftButton)
add_locale_window = assert_window(_AddLocaleWindow)

locale = 'nl-NL'
alias = 'nl'
add_locale_window._locale.setCurrentText(Locale.parse(locale, '-').get_display_name())
add_locale_window._alias.setText(alias)

qtbot.mouseClick(add_locale_window._save_and_close, QtCore.Qt.LeftButton)
qtbot.mouseClick(add_locale_window._save_and_close, Qt.MouseButton.LeftButton)
assert_not_window(_AddLocaleWindow)

assert locale in sut._configuration.locales
Expand All @@ -242,7 +242,7 @@ def test_project_window_localization_configuration_remove_locale(qtbot, minimal_
qtbot.addWidget(sut)
sut.show()

qtbot.mouseClick(sut._localization_configuration_pane._locales_configuration_widget._remove_buttons[locale], QtCore.Qt.LeftButton)
qtbot.mouseClick(sut._localization_configuration_pane._locales_configuration_widget._remove_buttons[locale], Qt.MouseButton.LeftButton)

assert locale not in sut._configuration.locales

Expand Down Expand Up @@ -320,7 +320,7 @@ async def test_generate_window_close_button_should_close_window(assert_not_windo
with qtbot.waitSignal(sut._thread.finished):
sut.show()

qtbot.mouseClick(sut._close_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(sut._close_button, Qt.MouseButton.LeftButton)
assert_not_window(_GenerateWindow)


Expand All @@ -335,5 +335,5 @@ async def test_generate_window_serve_button_should_open_serve_window(assert_wind
with qtbot.waitSignal(sut._thread.finished):
sut.show()

qtbot.mouseClick(sut._serve_button, QtCore.Qt.LeftButton)
qtbot.mouseClick(sut._serve_button, Qt.MouseButton.LeftButton)
assert_window(_ServeAppWindow)
2 changes: 1 addition & 1 deletion betty/tests/_package/test_license_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class PackageLicensesTest(TestCase):
_GPL_V3_COMPATIBLE_DISTRIBUTIONS = (
'PyQt5-sip',
'PyQt6-sip',
'graphlib-backport', # Released under the Python Software Foundation License.
)

Expand Down
2 changes: 1 addition & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[pytest]
qt_api=pyqt5
qt_api=pyqt6
testpaths=betty/pytests
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
'markupsafe ~= 2.0.1',
'orderedset ~= 2.0.3',
'pdf2image ~= 1.16.0',
'PyQt5 ~= 5.15.6',
'PyQt6 ~= 6.2.3',
'python-resize-image ~= 1.1.20',
'pyyaml ~= 6.0.0',
'reactives ~= 0.2.0',
Expand Down

0 comments on commit b622a85

Please sign in to comment.