Skip to content
Open
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
2 changes: 1 addition & 1 deletion INSTALL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Requirements
============

To run PyFFI's graphical file editor QSkope, you need
`PyQt4 <http://www.riverbankcomputing.co.uk/software/pyqt/download>`_.
`PyQt6 <http://www.riverbankcomputing.co.uk/software/pyqt/download>`_.

Using the Windows installer
===========================
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Python library for processing block structured binary files:
* **Batteries included:** Many tools for files used by 3D games, such
as optimizers, stripifier, tangent space calculator, 2d/3d hull
algorithms, inertia calculator, as well as a general purpose file
editor QSkope (using `PyQt4
editor QSkope (using `PyQt6
<http://www.riverbankcomputing.co.uk/software/pyqt/download>`_), are
included.

Expand Down
2 changes: 1 addition & 1 deletion pyffi/formats/cgf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ def read(self, stream):

# is it a caf file? these are missing chunk headers on controllers
# (note: stream.name may not be a python string for some file
# implementations, notably PyQt4, so convert it explicitely)
# implementations, notably PyQt6, so convert it explicitely)
is_caf = (str(stream.name)[-4:].lower() == ".caf")

chunk_types = [
Expand Down
50 changes: 18 additions & 32 deletions pyffi/qskope/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#
# ***** END LICENSE BLOCK *****

from PyQt4 import QtGui, QtCore
from PyQt6 import QtGui, QtCore , QtWidgets

import pyffi.qskope.global_model
import pyffi.qskope.detail_model
Expand All @@ -61,35 +61,33 @@

# implementation details:
# http://doc.trolltech.com/4.3/qmainwindow.html#details
class QSkope(QtGui.QMainWindow):
class QSkope(QtWidgets.QMainWindow):
"""Main QSkope window."""
def __init__(self, parent = None):
"""Initialize the main window."""
QtGui.QMainWindow.__init__(self, parent)
QtWidgets.QMainWindow.__init__(self, parent)

# set up the menu bar
self.createActions()
self.createMenus()

# set up the global model view
self.globalWidget = QtGui.QTreeView()
self.globalWidget = QtWidgets.QTreeView()
self.globalWidget.setAlternatingRowColors(True)

# set up the detail model view
self.detailWidget = QtGui.QTreeView()
self.detailWidget = QtWidgets.QTreeView()
self.detailDelegate = pyffi.qskope.detail_delegate.DetailDelegate()
self.detailWidget.setItemDelegate(self.detailDelegate)
self.detailWidget.setAlternatingRowColors(True)

# connect global with detail:
# if object is selected in global view, then show its details in the
# detail view
QtCore.QObject.connect(self.globalWidget,
QtCore.SIGNAL("clicked(const QModelIndex &)"),
self.setDetailModel)
self.globalWidget.clicked.connect(self.setDetailModel)

# set up the central widget
self.splitter = QtGui.QSplitter()
self.splitter = QtWidgets.QSplitter()
self.splitter.addWidget(self.globalWidget)
self.splitter.addWidget(self.detailWidget)
self.setCentralWidget(self.splitter)
Expand All @@ -114,42 +112,30 @@ def createActions(self):
# open a file
self.openAct = QtGui.QAction("&Open", self)
self.openAct.setShortcut("Ctrl+O")
QtCore.QObject.connect(self.openAct,
QtCore.SIGNAL("triggered()"),
self.openAction)
self.openAct.triggered.connect(self.openAction)

# save a file
self.saveAct = QtGui.QAction("&Save", self)
self.saveAct.setShortcut("Ctrl+S")
QtCore.QObject.connect(self.saveAct,
QtCore.SIGNAL("triggered()"),
self.saveAction)
self.saveAct.triggered.connect(self.saveAction)

# save a file as ...
self.saveAsAct = QtGui.QAction("Save As...", self)
self.saveAsAct.setShortcut("Ctrl+Shift+S")
QtCore.QObject.connect(self.saveAsAct,
QtCore.SIGNAL("triggered()"),
self.saveAsAction)
self.saveAsAct.triggered.connect(self.saveAsAction)

# exit
self.exitAct = QtGui.QAction("E&xit", self)
self.exitAct.setShortcut("Ctrl+Q")
QtCore.QObject.connect(self.exitAct,
QtCore.SIGNAL("triggered()"),
QtGui.qApp.quit)
self.exitAct.triggered.connect(QtWidgets.QApplication.quit)

# tell something about QSkope
self.aboutQSkopeAct = QtGui.QAction("About QSkope", self)
QtCore.QObject.connect(self.aboutQSkopeAct,
QtCore.SIGNAL("triggered()"),
self.aboutQSkopeAction)
self.aboutQSkopeAct.triggered.connect(self.aboutQSkopeAction)

# tell something about Qt
self.aboutQtAct = QtGui.QAction("About Qt", self)
QtCore.QObject.connect(self.aboutQtAct,
QtCore.SIGNAL("triggered()"),
QtGui.qApp.aboutQt)
self.aboutQtAct.triggered.connect(QtWidgets.QApplication.aboutQt)

# implementation details:
# http://doc.trolltech.com/4.3/mainwindows-menus.html
Expand All @@ -172,7 +158,7 @@ def closeEvent(self, event):
"""Called when the application is closed. Saves the settings."""
settings = self.getSettings(versioned = True)
settings.setValue("MainWindow/geometry", self.saveGeometry())
QtGui.QMainWindow.closeEvent(self, event)
QtWidgets.QMainWindow.closeEvent(self, event)


#
Expand Down Expand Up @@ -294,15 +280,15 @@ def openAction(self):
"""Open a file."""
# wrapper around openFile
# (displays an extra file dialog)
filename = QtGui.QFileDialog.getOpenFileName(self, "Open File")
filename = QtWidgets.QFileDialog.getOpenFileName(self, "Open File")
if filename:
self.openFile(filename = filename)

def saveAsAction(self):
"""Save a file."""
# wrapper around saveAction
# (displays an extra file dialog)
filename = QtGui.QFileDialog.getSaveFileName(self, "Save File")
filename = QtWidgets.QFileDialog.getSaveFileName(self, "Save File")
if filename:
self.fileName = filename
self.saveAction()
Expand All @@ -317,7 +303,7 @@ def saveAction(self):
def aboutQSkopeAction(self):
"""Display an information window about QSkope."""
# create the box
mbox = QtGui.QMessageBox(self)
mbox = QtWidgets.QMessageBox(self)
# set window title and window text
mbox.setWindowTitle("About QSkope")
mbox.setText("""
Expand All @@ -336,4 +322,4 @@ def aboutQSkopeAction(self):
<a href="https://github.com/niftools/pyffi/releases">
PyFFI Github Releases page</a>.""" % pyffi.__version__)
# display the window
mbox.exec_()
mbox.exec()
24 changes: 12 additions & 12 deletions pyffi/qskope/detail_delegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#
# ***** END LICENSE BLOCK *****

from PyQt4 import QtCore, QtGui
from PyQt6 import QtCore, QtGui, QtWidgets

# each delegate type corresponds to a QtGui delegate type
# (see _checkValidEditor for more details)
Expand All @@ -50,7 +50,7 @@
# implementation details:
# http://doc.trolltech.com/4.3/model-view-delegate.html
# http://doc.trolltech.com/4.3/qitemdelegate.html#details
class DetailDelegate(QtGui.QItemDelegate):
class DetailDelegate(QtWidgets.QItemDelegate):
"""Defines an editor for data in the detail view."""

def _checkValidEditor(self, data, editor):
Expand Down Expand Up @@ -78,19 +78,19 @@ def _checkValidEditor(self, data, editor):
# (some combo types may also derive from spin box such as bools,
# in that case prefer the combo box representation)
if isinstance(data, EditableComboBox):
isvalid = isinstance(editor, QtGui.QComboBox)
isvalid = isinstance(editor, QtWidgets.QComboBox)
# check float spin box
elif isinstance(data, EditableFloatSpinBox):
isvalid = isinstance(editor, QtGui.QDoubleSpinBox)
isvalid = isinstance(editor, QtWidgets.QDoubleSpinBox)
# check spin box
elif isinstance(data, EditableSpinBox):
isvalid = isinstance(editor, QtGui.QSpinBox)
isvalid = isinstance(editor, QtWidgets.QSpinBox)
# check text editor
elif isinstance(data, EditableTextEdit):
isvalid = isinstance(editor, QtGui.QTextEdit)
isvalid = isinstance(editor, QtWidgets.QTextEdit)
# check line editor
elif isinstance(data, EditableLineEdit):
isvalid = isinstance(editor, QtGui.QLineEdit)
isvalid = isinstance(editor, QtWidgets.QLineEdit)
else:
# data has no delegate class, which is classified as invalid
isvalid = False
Expand All @@ -112,7 +112,7 @@ def createEditor(self, parent, option, index):
# (see _checkValidEditor for the correct delegate preference order)
if isinstance(node, EditableComboBox):
# a general purpose combo box
editor = QtGui.QComboBox(parent)
editor = QtWidgets.QComboBox(parent)
for key in node.get_editor_keys():
editor.addItem(key)
elif isinstance(node, EditableFloatSpinBox):
Expand All @@ -123,17 +123,17 @@ def createEditor(self, parent, option, index):
editor.setDecimals(node.get_editor_decimals())
elif isinstance(node, EditableSpinBox):
# an integer spin box
editor = QtGui.QSpinBox(parent)
editor = QtWidgets.QSpinBox(parent)
editor.setMinimum(node.get_editor_minimum())
# work around a qt "bug": maximum must be C type "int"
# so cannot be larger than 0x7fffffff
editor.setMaximum(min(node.get_editor_maximum(), 0x7fffffff))
elif isinstance(node, EditableTextEdit):
# a text editor
editor = QtGui.QTextEdit(parent)
editor = QtWidgets.QTextEdit(parent)
elif isinstance(node, EditableLineEdit):
# a line editor
editor = QtGui.QLineEdit(parent)
editor = QtWidgets.QLineEdit(parent)
else:
return None
# check validity
Expand Down Expand Up @@ -195,5 +195,5 @@ def setModelData(self, editor, model, index):
return
# set the model data
# EditRole ensures that setData uses set_editor_value to set the data
model.setData(index, editorvalue, QtCore.Qt.EditRole)
model.setData(index, editorvalue, QtCore.Qt.ItemDataRole.EditRole)

23 changes: 11 additions & 12 deletions pyffi/qskope/detail_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#
# ***** END LICENSE BLOCK *****

from PyQt4 import QtCore
from PyQt6 import QtCore

from pyffi.utils.graph import EdgeFilter, GlobalNode
from pyffi.qskope.detail_tree import DetailTreeItem, DetailTreeItemData
Expand Down Expand Up @@ -81,9 +81,9 @@ def flags(self, index):
"""Return flags for the given index: all indices are enabled and
selectable."""
if not index.isValid():
return QtCore.Qt.ItemFlags()
return QtCore.Qt.ItemFlag()
# all items are enabled and selectable
flags = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
flags = QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable
# determine whether item value can be set
if index.column() == self.COL_VALUE:
try:
Expand All @@ -94,16 +94,16 @@ def flags(self, index):
except NotImplementedError:
pass
else:
flags |= QtCore.Qt.ItemIsEditable
return QtCore.Qt.ItemFlags(flags)
flags |= QtCore.Qt.ItemFlag.ItemIsEditable
return QtCore.Qt.ItemFlag(flags)

def data(self, index, role):
"""Return the data of model index in a particular role. Only
QtCore.Qt.DisplayRole is implemented.
"""
# check if the index is valid
# check if the role is supported
if not index.isValid() or role != QtCore.Qt.DisplayRole:
if not index.isValid() or role != QtCore.Qt.ItemDataRole.DisplayRole:
return None
# get the data for display
item = index.internalPointer()
Expand Down Expand Up @@ -142,8 +142,8 @@ def data(self, index, role):

def headerData(self, section, orientation, role):
"""Return header data."""
if (orientation == QtCore.Qt.Horizontal
and role == QtCore.Qt.DisplayRole):
if (orientation == QtCore.Qt.Orientation.Horizontal
and role == QtCore.Qt.ItemDataRole.DisplayRole):
if section == self.COL_TYPE:
return "Type"
elif section == self.COL_NAME:
Expand Down Expand Up @@ -194,9 +194,9 @@ def parent(self, index):

def setData(self, index, value, role):
"""Set data of a given index from given QVariant value. Only
QtCore.Qt.EditRole is implemented.
QtCore.Qt.ItemDataRole.EditRole is implemented.
"""
if role == QtCore.Qt.EditRole:
if role == QtCore.Qt.ItemDataRole.EditRole:
# fetch the current data, as a regular Python type
node = index.internalPointer().data.node
currentvalue = node.get_value()
Expand Down Expand Up @@ -224,8 +224,7 @@ def setData(self, index, value, role):
# set the value (EditRole, so use set_editor_value, not set_value)
node.set_editor_value(pyvalue)
# tell everyone that the data has changed
self.emit(QtCore.SIGNAL('dataChanged(QModelIndex, QModelIndex)'),
index, index)
self.dataChanged.emit(index,index, [])
return True
# all other cases: failed
return False
22 changes: 11 additions & 11 deletions pyffi/qskope/global_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@
#
# ***** END LICENSE BLOCK *****

from collections import MutableMapping
from collections.abc import MutableMapping

from PyQt4 import QtGui, QtCore
from PyQt6 import QtCore

from pyffi.utils.graph import EdgeFilter
from pyffi.qskope.global_tree import GlobalTreeItemData, GlobalTreeItem
Expand Down Expand Up @@ -76,7 +76,7 @@ def __delitem__(self, key):
# index becomes available
self.free_indices.append(self.data[id(key)])
# remove it
del self.data[id(key)]
del self.data[id(key)]

def clear(self):
# all indices larger than the first element
Expand Down Expand Up @@ -107,27 +107,27 @@ def updateIndexDict(self, item):
self.index_dict[item.data.node]
for child_item in item.children:
self.updateIndexDict(child_item)


def flags(self, index):
"""Return flags for the given index: all indices are enabled and
selectable."""
# all items are selectable
# they are enabled if their edge_type is active
if not index.isValid():
return QtCore.Qt.ItemFlags()
return QtCore.Qt.ItemFlag()
item = index.internalPointer()
if item.edge_type.active:
flags = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
flags = QtCore.Qt.ItemFlag.ItemIsEnabled | QtCore.Qt.ItemFlag.ItemIsSelectable
else:
flags = QtCore.Qt.ItemIsSelectable
return QtCore.Qt.ItemFlags(flags)
flags = QtCore.Qt.ItemFlag.ItemIsSelectable
return QtCore.Qt.ItemFlag(flags)

def data(self, index, role):
"""Return the data of model index in a particular role."""
# check if the index is valid
# check if the role is supported
if not index.isValid() or role != QtCore.Qt.DisplayRole:
if not index.isValid() or role != QtCore.Qt.ItemDataRole.DisplayRole:
return None
# get the data for display
data = index.internalPointer().data
Expand All @@ -146,8 +146,8 @@ def data(self, index, role):

def headerData(self, section, orientation, role):
"""Return header data."""
if (orientation == QtCore.Qt.Horizontal
and role == QtCore.Qt.DisplayRole):
if (orientation == QtCore.Qt.Orientation.Horizontal
and role == QtCore.Qt.ItemDataRole.DisplayRole):
if section == self.COL_TYPE:
return "Type"
elif section == self.COL_NAME:
Expand Down
Loading