diff --git a/nxt_editor/__init__.py b/nxt_editor/__init__.py index cf2523c..7aaae07 100644 --- a/nxt_editor/__init__.py +++ b/nxt_editor/__init__.py @@ -36,10 +36,7 @@ class StringSignaler(QtCore.QObject): def make_resources(qrc_path=None, result_path=None): - import PySide2 - pyside_dir = os.path.dirname(PySide2.__file__) - full_pyside2rcc_path = os.path.join(pyside_dir, 'pyside2-rcc') - full_rcc_path = os.path.join(pyside_dir, 'rcc') + import subprocess this_dir = os.path.dirname(os.path.realpath(__file__)) if not qrc_path: qrc_path = os.path.join(this_dir, 'resources/resources.qrc') @@ -47,37 +44,13 @@ def make_resources(qrc_path=None, result_path=None): result_path = os.path.join(this_dir, 'qresources.py') msg = 'First launch nxt resource generation from {} to {}' logger.info(msg.format(qrc_path, result_path)) - import subprocess - ver = ['-py2'] - if sys.version_info[0] == 3: - ver += ['-py3'] - args = [qrc_path] + ver + ['-o', result_path] - try: - subprocess.check_call(['pyside2-rcc'] + args) - except: - pass - else: - return + args = [qrc_path, '-o', result_path, '-g', 'python'] try: - subprocess.check_call([full_pyside2rcc_path] + args) + subprocess.call(['pyside6-rcc'] + args) except: - pass - else: - return - try: - subprocess.check_call([full_rcc_path, '-g', 'python', qrc_path, - '-o', result_path], cwd=pyside_dir) - except: - pass - else: - return - try: - subprocess.check_call(['rcc', '-g', 'python', qrc_path, - '-o', result_path], cwd=pyside_dir) - except: - raise Exception("Failed to generate UI resources using pyside2 rcc!" - " Reinstalling pyside2 may fix the problem. If you " + raise Exception("Failed to generate UI resources using PySide rcc!" + " Reinstalling PySide6 may fix the problem. If you " "know how to use rcc please build from: \"{}\" and " "output to \"{}\"".format(qrc_path, result_path)) else: @@ -129,9 +102,12 @@ def launch_editor(paths=None, start_rpc=True): def show_new_editor(paths=None, start_rpc=True): path = None - if paths is not None: + if paths and isinstance(paths, list): path = paths[0] paths.pop(0) + elif isinstance(paths, str): + path = paths + paths = [] else: paths = [] # Deferred import since main window relies on us diff --git a/nxt_editor/constants.py b/nxt_editor/constants.py index 51c6174..c1bc4ee 100644 --- a/nxt_editor/constants.py +++ b/nxt_editor/constants.py @@ -22,7 +22,7 @@ class EDITOR_VERSION(object): class FONTS(object): - DEFAULT_FAMILY = 'RobotoMono-Regular' + DEFAULT_FAMILY = 'Roboto Mono' DEFAULT_SIZE = 10 diff --git a/nxt_editor/dialogs.py b/nxt_editor/dialogs.py index c6653bc..998edaa 100644 --- a/nxt_editor/dialogs.py +++ b/nxt_editor/dialogs.py @@ -297,7 +297,7 @@ def build_widgets(self): self.save_details_button.released.connect(self.on_save_details) self.detail_buttons_layout = QtWidgets.QHBoxLayout() - self.detail_buttons_layout.addStretch(streth=1) + self.detail_buttons_layout.addStretch(1) self.detail_buttons_layout.addWidget(self.save_details_button) self.detail_buttons_layout.addWidget(self.copy_details_button) @@ -314,7 +314,7 @@ def build_widgets(self): self.top_right_layout = QtWidgets.QVBoxLayout() self.top_right_layout.addWidget(self.text_label) self.top_right_layout.addWidget(self.info_label) - self.top_right_layout.addStretch(streth=1) + self.top_right_layout.addStretch(1) self.top_right_layout.addLayout(self.buttons_layout) self.top_layout = QtWidgets.QHBoxLayout() self.top_layout.addWidget(self.icon) diff --git a/nxt_editor/dockwidgets/build_view.py b/nxt_editor/dockwidgets/build_view.py index 3d21643..768e214 100644 --- a/nxt_editor/dockwidgets/build_view.py +++ b/nxt_editor/dockwidgets/build_view.py @@ -315,7 +315,7 @@ class BuildTable(QtWidgets.QTableView): """ def __init__(self): super(BuildTable, self).__init__() - self.setSelectionMode(self.NoSelection) + self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection) self.horizontalHeader().hide() self.verticalHeader().hide() self.break_delegate = LetterCheckboxDelegeate('B') @@ -342,7 +342,7 @@ def setModel(self, model): header = self.horizontalHeader() header.setStretchLastSection(False) header.setDefaultSectionSize(28) - header.setSectionResizeMode(header.Fixed) + header.setSectionResizeMode(QtWidgets.QHeaderView.Fixed) if header.count(): column = BuildModel.PATH_COLUMN header.setSectionResizeMode(column, QtWidgets.QHeaderView.Stretch) diff --git a/nxt_editor/dockwidgets/code_editor.py b/nxt_editor/dockwidgets/code_editor.py index 0005dda..307a18c 100644 --- a/nxt_editor/dockwidgets/code_editor.py +++ b/nxt_editor/dockwidgets/code_editor.py @@ -1271,7 +1271,7 @@ def paintEvent(self, event): def get_width(self): count = self.editor.blockCount() - width = self.fontMetrics().width(str(count)) + 10 + width = self.fontMetrics().horizontalAdvance(str(count)) + 10 return width def update_width(self): diff --git a/nxt_editor/dockwidgets/find_rep.py b/nxt_editor/dockwidgets/find_rep.py index bd94f67..23aaa9c 100644 --- a/nxt_editor/dockwidgets/find_rep.py +++ b/nxt_editor/dockwidgets/find_rep.py @@ -196,7 +196,7 @@ def setModel(self, model): super(SearchResultsTree, self).setModel(model) header = self.header() header.setStretchLastSection(False) - header.setSectionResizeMode(header.ResizeToContents) + header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents) if self.model(): self.model().modelReset.connect(self.expandAll) diff --git a/nxt_editor/dockwidgets/layer_manager.py b/nxt_editor/dockwidgets/layer_manager.py index 4aed6f5..3c2aeea 100644 --- a/nxt_editor/dockwidgets/layer_manager.py +++ b/nxt_editor/dockwidgets/layer_manager.py @@ -100,7 +100,7 @@ def setModel(self, model): header = self.header() header.setStretchLastSection(False) header.setDefaultSectionSize(LayerTreeView.SIZE) - header.setSectionResizeMode(header.Fixed) + header.setSectionResizeMode(QtWidgets.QHeaderView.Fixed) if header.count(): header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch) self.hideColumn(LayerModel.TARGET_COLUMN) diff --git a/nxt_editor/dockwidgets/output_log.py b/nxt_editor/dockwidgets/output_log.py index b5ec502..0ec8508 100644 --- a/nxt_editor/dockwidgets/output_log.py +++ b/nxt_editor/dockwidgets/output_log.py @@ -205,7 +205,7 @@ def __init__(self, graph_model=None, parent=None): self.buttons_layout = QtWidgets.QHBoxLayout() self.buttons_layout.addWidget(self.log_filter_button) - self.buttons_layout.addStretch(stretch=1) + self.buttons_layout.addStretch(1) self.buttons_layout.addWidget(self.clear_rich_button) self.rich_output_layout = QtWidgets.QVBoxLayout() diff --git a/nxt_editor/dockwidgets/property_editor.py b/nxt_editor/dockwidgets/property_editor.py index 2f80f38..2c114e0 100644 --- a/nxt_editor/dockwidgets/property_editor.py +++ b/nxt_editor/dockwidgets/property_editor.py @@ -12,7 +12,7 @@ QtCore.QStringListModel except AttributeError: del QtCore - from PySide2 import QtCore + from PySide6 import QtCore # Internal from nxt_editor import user_dir diff --git a/nxt_editor/dockwidgets/syntax.py b/nxt_editor/dockwidgets/syntax.py index 246c23f..6b3eb07 100644 --- a/nxt_editor/dockwidgets/syntax.py +++ b/nxt_editor/dockwidgets/syntax.py @@ -39,15 +39,15 @@ class PythonHighlighter(QSyntaxHighlighter): # Comparison '==', '!=', '<', '<=', '>', '>=', # Arithmetic - '\+', '-', '\*', '/', '//', '\%', '\*\*', + r'\+', '-', r'\*', '/', '//', r'\%', r'\*\*', # In-place - '\+=', '-=', '\*=', '/=', '\%=', + r'\+=', '-=', r'\*=', '/=', r'\%=', # Bitwise - '\^', '\|', '\&', '\~', '>>', '<<' + r'\^', r'\|', r'\&', r'\~', '>>', '<<' ] # Python braces - braces = ['\{', '\}', '\(', '\)', '\[', '\]'] + braces = [r'\{', r'\}', r'\(', r'\)', r'\[', r'\]'] def __init__(self, document=None): super(PythonHighlighter, self).__init__(document) @@ -117,7 +117,8 @@ def highlightBlock(self, text): # Do other syntax formatting for rule in self.rules: expression, nth, formatting = rule - index = expression.indexIn(text, 0) + match = expression.match(text) + index = match.capturedStart() # This is here because you can't do nested logic in regex nested = 0 if rule in self.special_rules: @@ -126,10 +127,10 @@ def highlightBlock(self, text): while index >= 0: # We actually want the index of the nth match - index = expression.pos(nth) - length = len(expression.cap(nth)) + index = match.capturedStart(nth) + length = len(match.captured(nth)) self.setFormat(index, length + nested, formatting) - index = expression.indexIn(text, index + length) + index = match.capturedStart(text) self.setCurrentBlockState(0) @@ -151,17 +152,19 @@ def match_multiline(self, text, delimiter, in_state, style): add = 0 # Otherwise, look for the delimiter on this line else: - start = delimiter.indexIn(text) + match = delimiter.match(text) + start = match.capturedStart() # Move past this match - add = delimiter.matchedLength() + add = match.capturedLength() # As long as there's a delimiter match on this line... while start >= 0: + match = delimiter.match(text) # Look for the ending delimiter - end = delimiter.indexIn(text, start + add) + end = match.capturedStart() + (start + add) # Ending delimiter on this line? if end >= add: - length = end - start + add + delimiter.matchedLength() + length = end - start + add + match.capturedLength() self.setCurrentBlockState(0) # No; multi-line string else: @@ -170,7 +173,7 @@ def match_multiline(self, text, delimiter, in_state, style): # Apply formatting self.setFormat(start, length, style) # Look for the next match - start = delimiter.indexIn(text, start + length) + start = match.capturedStart() + (start + length) # Return True if still inside a multi-line string, False otherwise if self.currentBlockState() == in_state: diff --git a/nxt_editor/dockwidgets/widget_builder.py b/nxt_editor/dockwidgets/widget_builder.py index b773b2c..1ecb1a2 100644 --- a/nxt_editor/dockwidgets/widget_builder.py +++ b/nxt_editor/dockwidgets/widget_builder.py @@ -15,7 +15,7 @@ QtCore.QStringListModel except AttributeError: del QtCore - from PySide2 import QtCore + from PySide6 import QtCore # Internal import nxt_editor diff --git a/nxt_editor/node_graphics_item.py b/nxt_editor/node_graphics_item.py index b8de726..128f4b7 100644 --- a/nxt_editor/node_graphics_item.py +++ b/nxt_editor/node_graphics_item.py @@ -9,8 +9,6 @@ from Qt import QtWidgets from Qt import QtGui from Qt import QtCore -from PySide2 import __version_info__ as qt_version - # Internal import nxt_editor from nxt import nxt_path, nxt_node @@ -25,16 +23,8 @@ MIN_LOD = user_prefs.get(USER_PREF.LOD, .4) -_pyside_version = qt_version - - -if _pyside_version[1] < 11: - graphic_type = QtWidgets.QGraphicsItem -else: - graphic_type = QtWidgets.QGraphicsObject - -class NodeGraphicsItem(graphic_type): +class NodeGraphicsItem(QtWidgets.QGraphicsObject): """The graphics item used to represent nodes in the graph. Contains instances of NodeGraphicsPlug for each attribute on the associated node. Contains functionality for arranging children into stacks. @@ -262,13 +252,13 @@ def screen_pos(self): def itemChange(self, change, value): """Override of QtWidgets.QGraphicsItem itemChange.""" # keep connections drawing to node as it moves - if change is self.ItemScenePositionHasChanged: + if change is QtWidgets.QGraphicsItem.ItemPositionChange: graphics = self.view.get_node_connection_graphics(self.node_path) for connection in graphics: connection.rebuild_line() # TODO: Take into account the positions of every selected node and snap them all to a grid as soon as # the user preses shift. This will avoid the weird wavy snapping effect we have right now - if change == self.ItemPositionChange and self.scene(): + if change == QtWidgets.QGraphicsItem.ItemPositionChange and self.scene(): ml = QtWidgets.QApplication.mouseButtons() == QtCore.Qt.LeftButton shift = QtWidgets.QApplication.keyboardModifiers() == QtCore.Qt.ShiftModifier force_snap = self.view.alignment_actions.snap_action.isChecked() diff --git a/nxt_editor/pixmap_button.py b/nxt_editor/pixmap_button.py index 3239ad4..e4a07f6 100644 --- a/nxt_editor/pixmap_button.py +++ b/nxt_editor/pixmap_button.py @@ -71,7 +71,7 @@ def paintEvent(self, event): pix = self.pixmap_pressed painter = QtGui.QPainter(self) - painter.drawPixmap(event.rect(), pix) + painter.drawPixmap(event.rect(), QtGui.QPixmap(pix)) del painter def enterEvent(self, event): diff --git a/nxt_editor/stage_view.py b/nxt_editor/stage_view.py index 11151ec..d6ad664 100644 --- a/nxt_editor/stage_view.py +++ b/nxt_editor/stage_view.py @@ -8,12 +8,12 @@ from Qt import QtWidgets from Qt import QtGui from Qt import QtCore +from Qt import QtCompat # Interal import nxt_editor from nxt import nxt_node, tokens -from nxt_editor.node_graphics_item import (NodeGraphicsItem, NodeGraphicsPlug, - _pyside_version) +from nxt_editor.node_graphics_item import NodeGraphicsItem, NodeGraphicsPlug from nxt_editor.connection_graphics_item import AttrConnectionGraphic from nxt_editor.dialogs import NxtWarningDialog from nxt_editor.commands import * @@ -42,8 +42,6 @@ def __init__(self, model, parent=None): super(StageView, self).__init__(parent=parent) self.main_window = parent self._do_anim_pref = user_prefs.get(USER_PREF.ANIMATION, True) - if _pyside_version[1] < 11: - self._do_anim_pref = False self.do_animations = self._do_anim_pref self.once_sec_timer = QtCore.QTimer(self) self.once_sec_timer.timeout.connect(self.calculate_fps) @@ -79,8 +77,8 @@ def __init__(self, model, parent=None): self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) self.horizontalScrollBar().setValue(0) self.verticalScrollBar().setValue(0) - self.setOptimizationFlag(self.DontSavePainterState, enabled=True) - self.setOptimizationFlag(self.DontAdjustForAntialiasing, enabled=True) + self.setOptimizationFlag(QtWidgets.QGraphicsView.DontSavePainterState, enabled=True) + self.setOptimizationFlag(QtWidgets.QGraphicsView.DontAdjustForAntialiasing, enabled=True) # scene self._scene = QtWidgets.QGraphicsScene() self.setScene(self._scene) @@ -700,7 +698,7 @@ def mousePressEvent(self, event): self.zoom_start_pos = event.pos() self._previous_mouse_pos = event.pos() event.accept() - if event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.MidButton: + if event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.MiddleButton: self.zooming = True self.zoom_start_pos = event.pos() self._previous_mouse_pos = event.pos() @@ -825,11 +823,11 @@ def mouseReleaseEvent(self, event): event.accept() if self.zooming: - if event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.MidButton: + if event.buttons() == QtCore.Qt.LeftButton | QtCore.Qt.MiddleButton: self.zooming = False elif event.buttons() == QtCore.Qt.LeftButton: self.zooming = False - elif event.buttons() == QtCore.Qt.MidButton: + elif event.buttons() == QtCore.Qt.MiddleButton: self.zooming = False if (self._rubber_band_origin is not None and event.button() is QtCore.Qt.LeftButton): @@ -993,11 +991,11 @@ def mouseDoubleClickEvent(self, event): item.collapse_node() def wheelEvent(self, event): - self._view_pos = event.pos() + self._view_pos = event.position().toPoint() self._scene_pos = self.mapToScene(self._view_pos) try: - new_scale = event.delta() * .001 + 1.0 + new_scale = event.angleDelta().y() * .001 + 1.0 except AttributeError: new_scale = 1.1 diff --git a/nxt_editor/user_dir.py b/nxt_editor/user_dir.py index 6353f68..2b6c4c9 100644 --- a/nxt_editor/user_dir.py +++ b/nxt_editor/user_dir.py @@ -10,6 +10,7 @@ import json import logging +import shutil import sys if sys.version_info[0] == 2: @@ -209,10 +210,10 @@ def read(self): return try: with open(self.path, 'r+b') as fp: - if sys.version_info[0] == 2: - contents = pickle.load(fp) - else: - contents = pickle.load(fp, encoding='bytes') + contents = pickle.load(fp, encoding='bytes') + except ModuleNotFoundError as e: + if 'PySide2' in e.msg: + shutil.move(self.path, self.path + '.backup') except pickle.UnpicklingError: broken_files.setdefault(self.path, 0) times_hit = broken_files[self.path] diff --git a/setup.py b/setup.py index 2f524c9..551b78d 100644 --- a/setup.py +++ b/setup.py @@ -32,7 +32,7 @@ url="https://github.com/nxt-dev/nxt_editor", packages=setuptools.find_packages(), python_requires=">=3.7, <3.12", - install_requires=["nxt-core<1.0,>=0.14", "qt.py<3", "pyside2>=5.11,<=5.16"], + install_requires=["nxt-core<1.0,>=0.14", "qt.py<3", "PySide6>=6,<6.8"], package_data={ # covers text nxt files "": ["*.nxt"],