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

PR: Various additional fixes for Qt 6 compatibility #22620

Merged
merged 3 commits into from
Nov 7, 2024
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
7 changes: 6 additions & 1 deletion spyder/api/widgets/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"""

# Third-party imports
from qtpy import QT6
from qtpy.QtCore import Qt
from qtpy.QtGui import QIcon
from qtpy.QtWidgets import QDialogButtonBox, QProxyStyle, QStyle
Expand All @@ -26,7 +27,11 @@ def styleHint(self, hint, option=None, widget=None, return_data=None):
# platforms. We selected that layout because Windows is our most
# popular platform.
# Solution found in https://stackoverflow.com/a/35907926/438386
return QDialogButtonBox.WinLayout
if QT6: # PySide6/PyQt6
return QDialogButtonBox.ButtonLayout.WinLayout.value
else: # PySide2/PyQt5
return int(QDialogButtonBox.ButtonLayout.WinLayout)


return super().styleHint(hint, option, widget, return_data)

Expand Down
45 changes: 22 additions & 23 deletions spyder/app/tests/test_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import pylint
import pytest
from qtpy import PYQT_VERSION, PYQT5
from qtpy.QtCore import QPoint, Qt, QTimer
from qtpy.QtCore import QPoint, Qt, QTimer, QUrl
from qtpy.QtGui import QImage, QTextCursor
from qtpy.QtWidgets import QAction, QApplication, QInputDialog, QWidget
from qtpy.QtWebEngineWidgets import WEBENGINE
Expand Down Expand Up @@ -2789,14 +2789,13 @@ def test_troubleshooting_menu_item_and_url(main_window, qtbot, monkeypatch):

application_plugin = main_window.application
MockQDesktopServices = Mock()
mockQDesktopServices_instance = MockQDesktopServices()
attr_to_patch = ('spyder.utils.qthelpers.QDesktopServices')
monkeypatch.setattr(attr_to_patch, MockQDesktopServices)

# Unit test of help menu item: Make sure the correct URL is called.
application_plugin.trouble_action.trigger()
assert MockQDesktopServices.openUrl.call_count == 1
mockQDesktopServices_instance.openUrl.called_once_with(__trouble_url__)
MockQDesktopServices.openUrl.assert_called_once_with(
QUrl(__trouble_url__))


@flaky(max_runs=3)
Expand Down Expand Up @@ -3622,37 +3621,37 @@ def test_varexp_rename(main_window, qtbot, tmpdir):
qtbot.mouseClick(main_window.run_button, Qt.LeftButton)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 4,
qtbot.waitUntil(lambda: nsb.editor.model().rowCount() == 4,
timeout=EVAL_TIMEOUT)

# Rename one element
nsb.editor.setCurrentIndex(nsb.editor.model.index(1, 0))
nsb.editor.setCurrentIndex(nsb.editor.model().index(1, 0))
nsb.editor.rename_item(new_name='arr2')

# Wait until all objects have updated in the variable explorer
def data(cm, i, j):
return cm.data(cm.index(i, j))
qtbot.waitUntil(lambda: data(nsb.editor.model, 1, 0) == 'arr2',
qtbot.waitUntil(lambda: data(nsb.editor.model(), 1, 0) == 'arr2',
timeout=EVAL_TIMEOUT)

assert data(nsb.editor.model, 0, 0) == 'a'
assert data(nsb.editor.model, 1, 0) == 'arr2'
assert data(nsb.editor.model, 2, 0) == 'li'
assert data(nsb.editor.model, 3, 0) == 's'
assert data(nsb.editor.model(), 0, 0) == 'a'
assert data(nsb.editor.model(), 1, 0) == 'arr2'
assert data(nsb.editor.model(), 2, 0) == 'li'
assert data(nsb.editor.model(), 3, 0) == 's'

# ---- Run file again ----
with qtbot.waitSignal(shell.executed):
qtbot.mouseClick(main_window.run_button, Qt.LeftButton)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 5,
qtbot.waitUntil(lambda: nsb.editor.model().rowCount() == 5,
timeout=EVAL_TIMEOUT)

assert data(nsb.editor.model, 0, 0) == 'a'
assert data(nsb.editor.model, 1, 0) == 'arr'
assert data(nsb.editor.model, 2, 0) == 'arr2'
assert data(nsb.editor.model, 3, 0) == 'li'
assert data(nsb.editor.model, 4, 0) == 's'
assert data(nsb.editor.model(), 0, 0) == 'a'
assert data(nsb.editor.model(), 1, 0) == 'arr'
assert data(nsb.editor.model(), 2, 0) == 'arr2'
assert data(nsb.editor.model(), 3, 0) == 'li'
assert data(nsb.editor.model(), 4, 0) == 's'


@flaky(max_runs=3)
Expand Down Expand Up @@ -3689,23 +3688,23 @@ def test_varexp_remove(main_window, qtbot, tmpdir):
qtbot.mouseClick(main_window.run_button, Qt.LeftButton)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 4,
qtbot.waitUntil(lambda: nsb.editor.model().rowCount() == 4,
timeout=EVAL_TIMEOUT)

# Remove one element
nsb.editor.setCurrentIndex(nsb.editor.model.index(1, 0))
nsb.editor.setCurrentIndex(nsb.editor.model().index(1, 0))
nsb.editor.remove_item(force=True)

# Wait until all objects have appeared in the variable explorer
qtbot.waitUntil(lambda: nsb.editor.model.rowCount() == 3,
qtbot.waitUntil(lambda: nsb.editor.model().rowCount() == 3,
timeout=EVAL_TIMEOUT)

def data(cm, i, j):
assert cm.rowCount() == 3
return cm.data(cm.index(i, j))
assert data(nsb.editor.model, 0, 0) == 'a'
assert data(nsb.editor.model, 1, 0) == 'li'
assert data(nsb.editor.model, 2, 0) == 's'
assert data(nsb.editor.model(), 0, 0) == 'a'
assert data(nsb.editor.model(), 1, 0) == 'li'
assert data(nsb.editor.model(), 2, 0) == 's'


@flaky(max_runs=3)
Expand Down
4 changes: 2 additions & 2 deletions spyder/plugins/editor/extensions/tests/test_docstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,9 +714,9 @@ def test_docstring_comments(editor_auto_docstring, text, expected):
editor = editor_auto_docstring
editor.set_text(text)

# position cursor somewhere inside the `def` statement
cursor = editor.textCursor()
cursor.movePosition(QTextCursor.NextBlock)
cursor.setPosition(QTextCursor.End, QTextCursor.MoveAnchor)
cursor.setPosition(11, QTextCursor.MoveAnchor)
editor.setTextCursor(cursor)

editor.writer_docstring.write_docstring_for_shortcut()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

# Third party imports
from qtpy import QT_VERSION
from qtpy.QtCore import Qt, QEvent
from qtpy.QtCore import Qt, QEvent, QPointF
from qtpy.QtGui import QTextCursor, QMouseEvent
from qtpy.QtWidgets import QApplication, QTextEdit
import pytest
Expand Down Expand Up @@ -139,7 +139,7 @@ def test_editor_rstrip_keypress(codeeditor, qtbot, input_text, expected_text,
button, position = key
cursor = widget.textCursor()
cursor.setPosition(position)
xypos = widget.cursorRect(cursor).center()
xypos = QPointF(widget.cursorRect(cursor).center())
widget.mousePressEvent(QMouseEvent(
QEvent.MouseButtonPress, xypos,
button, button,
Expand Down
5 changes: 3 additions & 2 deletions spyder/plugins/shortcuts/widgets/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,15 +329,16 @@ def check_conflicts(self):
return conflicts

new_qsequence = self.new_qsequence
no_match = QKeySequence.SequenceMatch.NoMatch
for shortcut in self.shortcuts:
shortcut_qsequence = QKeySequence.fromString(str(shortcut.key))
if shortcut_qsequence.isEmpty():
continue
if (shortcut.context, shortcut.name) == (self.context, self.name):
continue
if shortcut.context in [self.context, '_'] or self.context == '_':
if (shortcut_qsequence.matches(new_qsequence) or
new_qsequence.matches(shortcut_qsequence)):
if (shortcut_qsequence.matches(new_qsequence) != no_match or
new_qsequence.matches(shortcut_qsequence) != no_match):
conflicts.append(shortcut)
return conflicts

Expand Down
28 changes: 12 additions & 16 deletions spyder/plugins/variableexplorer/widgets/dataframeeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1006,10 +1006,9 @@ def resize_to_contents(self, rows=False):

def flags(self, index):
"""Set flags"""
return Qt.ItemFlags(
int(QAbstractTableModel.flags(self, index) |
Qt.ItemIsEditable | Qt.ItemIsEnabled |
Qt.ItemIsSelectable | Qt.EditRole)
return (QAbstractTableModel.flags(self, index) |
Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsEnabled |
Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.EditRole
)

def edit_header_item(self):
Expand Down Expand Up @@ -1086,8 +1085,7 @@ def edit_item(self):
if not index.isValid():
return

# TODO: Remove hard coded "Value" column number (3 here)
self.edit(index.child(index.row(), index.column()))
self.edit(index)

def insert_item(self, axis=0, before_above=False):
"""Insert row or column."""
Expand Down Expand Up @@ -1570,11 +1568,10 @@ def data(self, index, role):

def flags(self, index):
"""Set flags"""
return Qt.ItemFlags(
int(QAbstractTableModel.flags(self, index) |
Qt.ItemIsEditable |
Qt.ItemIsEnabled |
Qt.ItemIsSelectable)
return (QAbstractTableModel.flags(self, index) |
Qt.ItemFlag.ItemIsEditable |
Qt.ItemFlag.ItemIsEnabled |
Qt.ItemFlag.ItemIsSelectable
)

def setData(self, index, value, role):
Expand Down Expand Up @@ -1995,11 +1992,10 @@ def contextMenuEvent(self, event):

def flags(self, index):
"""Set flags"""
return Qt.ItemFlags(
int(QAbstractTableModel.flags(self, index) |
Qt.ItemIsEditable |
Qt.ItemIsEnabled |
Qt.ItemIsSelectable)
return (QAbstractTableModel.flags(self, index) |
Qt.ItemFlag.ItemIsEditable |
Qt.ItemFlag.ItemIsEnabled |
Qt.ItemFlag.ItemIsSelectable
)

def create_table_level(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def test_sort_by_column(namespacebrowser, qtbot):
# Check header is clickable
assert header.sectionsClickable()

model = browser.editor.model
model = browser.editor.model()

# Base check of the model
assert model.rowCount() == 2
Expand Down Expand Up @@ -133,7 +133,7 @@ def test_keys_sorted_and_sort_with_large_rows(namespacebrowser, qtbot):

# Assert we loaded the expected amount of data and that we can fetch
# more.
model = browser.editor.model
model = browser.editor.model()
assert model.rowCount() == ROWS_TO_LOAD
assert model.canFetchMore(QModelIndex())

Expand Down Expand Up @@ -170,7 +170,7 @@ def test_filtering_with_large_rows(namespacebrowser, qtbot):

# Assert we loaded the expected amount of data and that we can fetch
# more data.
model = browser.editor.model
model = browser.editor.model()
assert model.rowCount() == ROWS_TO_LOAD
assert model.canFetchMore(QModelIndex())
assert data(model, 49, 0) == 'e49'
Expand Down
8 changes: 4 additions & 4 deletions spyder/widgets/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,13 +444,13 @@ def pageact2btn(prop, icon=None):
self.webview.pageAction(prop), parent=self.webview, icon=icon)

refresh_button = pageact2btn(
QWebEnginePage.Reload, icon=ima.icon('refresh'))
QWebEnginePage.WebAction.Reload, icon=ima.icon('refresh'))
stop_button = pageact2btn(
QWebEnginePage.Stop, icon=ima.icon('stop'))
QWebEnginePage.WebAction.Stop, icon=ima.icon('stop'))
previous_button = pageact2btn(
QWebEnginePage.Back, icon=ima.icon('previous'))
QWebEnginePage.WebAction.Back, icon=ima.icon('previous'))
next_button = pageact2btn(
QWebEnginePage.Forward, icon=ima.icon('next'))
QWebEnginePage.WebAction.Forward, icon=ima.icon('next'))

stop_button.setEnabled(False)
self.webview.loadStarted.connect(lambda: stop_button.setEnabled(True))
Expand Down
8 changes: 3 additions & 5 deletions spyder/widgets/collectionseditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,7 @@ def mousePressEvent(self, event):
else:
row = index_clicked.row()
# TODO: Remove hard coded "Value" column number (3 here)
self.__index_clicked = index_clicked.child(row, 3)
self.__index_clicked = self.model().index(row, 3)

# Wait for a bit to edit values so dialogs are focused on
# double clicks. That will preserve the way things worked in
Expand Down Expand Up @@ -1158,7 +1158,7 @@ def edit_item(self):
if not index.isValid():
return
# TODO: Remove hard coded "Value" column number (3 here)
self.edit(index.child(index.row(), 3))
self.edit(self.model().index(index.row(), 3))

@Slot()
def remove_item(self, force=False):
Expand Down Expand Up @@ -1304,7 +1304,7 @@ def view_item(self):
if not index.isValid():
return
# TODO: Remove hard coded "Value" column number (3 here)
index = index.child(index.row(), 3)
index = index.model().index(index.row(), 3)
self.delegate.createEditor(self, None, index, object_explorer=True)

def __prepare_plot(self):
Expand Down Expand Up @@ -1470,7 +1470,6 @@ def __init__(self, parent, data, namespacebrowser=None,
names=names,
minmax=self.get_conf('minmax')
)
self.model = self.source_model
self.setModel(self.source_model)
self.delegate = CollectionsDelegate(
self, namespacebrowser, data_function
Expand Down Expand Up @@ -1899,7 +1898,6 @@ def __init__(self, parent, data, shellwidget=None, remote_editing=False,
self.source_model.load_all)

self.proxy_model = CollectionsCustomSortFilterProxy(self)
self.model = self.proxy_model

self.proxy_model.setSourceModel(self.source_model)
self.proxy_model.setDynamicSortFilter(True)
Expand Down
Loading
Loading