[PyQt] Class woes - QtCore.QAbstractItemModel.__init__(self)
C C
coastalchaos at hotmail.co.uk
Fri May 29 18:11:04 BST 2015
I've managed to get a sample of the code together to show all the class inheritance which produces exactly the same error as in the application with PyQt5. They PyQt4 version doesn't error.
The red line is the one throwing the error.
from __future__ import division, print_function, unicode_literals
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtCore import Qt, pyqtSignal
import weakref
#from PyQt4 import QtCore, QtGui
#from PyQt4.QtCore import pyqtSignal, Qt
class IViewModel(object):
"""
Interface for a generic model in a model/view pattern
"""
def __init__(self, session, data):
"""
Constructor accepts the database session to be used to update the items
in case of a database's change received by the ``databaseChanged()``
signal and the user defined initial data.
:param data: The view model data to display
:param session: The database' session
:type session: sqlalchemy.orm.session.Session
:type data: object
"""
raise NotImplementedError(self)
def indentation(self):
"""
Return the current indentation value
:rtype: int
"""
raise NotImplementedError(self)
class BaseViewModel(QtCore.QAbstractItemModel, IViewModel):
"""
Base view model implementation.
In the concrete implementation of this class you can define a custom size
and resize mode for every column of the model but only in x* controls.
Also set the :py:attr:`.BaseViewModel.orm_classes` static attribute to a
tuple of classed to be used to filter incoming `databaseChanged` signals.
To do that you just need to re-implement the
:py:meth:`.BaseViewModel.columnWidth()` and
:py:meth:`.BaseViewModel.columnWidthMode()` methods with your custom column
sizes and resize modes.
Custom signals:
* databaseChanged(PyQt_PyObject)
Emitted from the QCoreApplication's instance after changes in the
database, an instance of :py:class:`.SessionStatusVO` will be sent within
the signal
"""
INDENTATION_CHAR = " "
"""
Character to be used during indentation indentation
:type: string
""" # pylint: disable=W0105
INDENTATION_LEVEL = -1
"""
Number of columns starting from the left side which will be indented.
A value of -1 means all values in every column will be indented; a value of
0 (zero) means no indentation will be applied.
:type: int
""" # pylint: disable=W0105
orm_classes = ()
"""
Class level variable which stores the list of ORM classes to be used as a
filter when a databaseChanged() signal is received.
Only the changes on the classes listed in this variable will be forwarded
to the update/add/remove item's code.
:type: list
""" # pylint: disable=W0105
def __init__(self, session, data):
"""
See :py:class:`.IViewModel`
"""
# Call superclass
QtCore.QAbstractItemModel.__init__(self)
#super(BaseViewModel, self).__init__(session, data)
# Protected attributes
self._indentation = self.INDENTATION_LEVEL
self._data = data
# Public attributes
self.session = session
class ContextHelpMixin(object):
"""
Mixin class to add support for a context help activated by pressing the F1
key
"""
DEFAULT = "<not_set>"
trigger = pyqtSignal()
helpIdentifierVisible = pyqtSignal(bool)
def __init__(self, *args, **kwds):
"""
Empty constructor
"""
# Public attributes
self._context_help_name = self.DEFAULT
self._overlay = None
# Connect signals
# self.trigger.connect(
# QtWidgets.QApplication.instance(),
# QtCore.pyqtSignal(b"helpIdentifierVisible(bool)"),
# self._on_identifier_visible_signal
# )
self.trigger.connect(self._on_identifier_visible_signal)
class xDialog(ContextHelpMixin, QtWidgets.QDialog):
"""
Custom dialog class which supports the contextual help and display it as
window modal, which blocks the interaction only on the dialog's parent and
its ancestors but not to other windows in the same Qt application's loop.
"""
def __init__(self, *args, **kwds):
"""
See QDialog
"""
# Call superclasses
QtWidgets.QDialog.__init__(self, *args, **kwds)
ContextHelpMixin.__init__(self)
# Set up dialog
self.setWindowModality(Qt.WindowModal)
class BaseViewMixin(object):
"""
Mixin implementation for a base view class.
Protected attributes are added to the class only if they are set.
"""
def data(self):
"""
Return current window data
:rtype: object
"""
return self._data if hasattr(self, "_data") else None
def setData(self, value):
"""
Set current window data
:param value: The per view data
:type value: object
"""
self._data = value # pylint: disable=W0201
def delegate(self):
"""
Returns the view's delegate
:rtype: puremvc.interfaces.IMediator
"""
if hasattr(self, "_delegate") and self._delegate is not None:
return self._delegate()
return None
def setDelegate(self, value):
"""
Keeps a weak reference of the view's delegate
:param mediator: The view's mediator
:type mediator: puremvc.interfaces.IMediator
"""
# pylint: disable=W0201
self._delegate = weakref.ref(value) if value is not None else None
# pylint: enable=W0201
class Enumerator(object):
"""
An enumerator class is a class which cannot be instantiated and offers only
a set of static constants
"""
@classmethod
def members(cls):
"""
Class method that returns a list with the enumerator members
:rtype: list( object )
"""
return [getattr(cls, member_name) for member_name in sorted(vars(cls))
if not member_name.startswith("__")]
def __init__(self): # pylint: disable=W0231
raise SyntaxError("You cannot create an instance of this class")
class CustomItemRoles(Enumerator):
"""
Enumerates the custom item roles used by the application
"""
IDENTIFIER_ROLE = Qt.UserRole + 1
"""
Returns a unique identifier for the model index item
:rtype: object
""" # pylint: disable=W0105
class BaseViewModelItem(object):
"""
Base view model item implementation
"""
def __init__(self, value, parent=None):
"""
Constructor accepts the user defined data and the optional item's
parent
:param value: The data displayed by this model item
:param parent: The optional item's parent
:type value: object
:type parent: :py:class:`.BaseViewModelItem`
"""
# Public attributes
self.value = value
self.parent = parent
self.children = []
def setData(self, index, value, role):
"""
Sets data for the column index and role.
See QAbstractItemModel.setData()
:param index: The column index
:param value: The value to be set
:param role: The item's role
:type index: int
:type value: object
:type role: Qt::ItemDataRole
"""
pass
def data(self, index, role):
"""
Returns data for the column index and role.
In details:
* for Qt::UserRole returns the value referenced by the model view item
* for :py:attr:`.CustomItemRoles.IDENTIFIER_ROLE` returns the
ID of the object if any
See QAbstractItemModel.data()
:param index: The column index
:param role: The requested role
:type index: int
:type role: Qt::ItemDataRole
:rtype: object
"""
if role == CustomItemRoles.IDENTIFIER_ROLE:
return self.identifier()
if role == Qt.UserRole:
return self.value
class UsernameItem(BaseViewModelItem):
"""
Single Username item
"""
def data(self, index, role):
"""
See QAbstractItemModel.data()
"""
# Display role
if role in (Qt.DisplayRole, Qt.EditRole) and index == 0:
return self.value.username
# Default
return super(UsernameItem, self).data(index, role)
class UsernamesModel(BaseViewModel):
"""
Model for usernames list view
"""
COLUMNS = ("Username",)
def __init__(self, session, users, current_user=None):
"""
Constructor accepts the database session, the list of users and the
optional current logged user
:param session: The database session
:param users: The list of users
:param current_user: The current logged user
:type session: sqlachemy.orm.session
:type users: list( :py:class:`.User` )
:type current_user: :py:class:`.User`
"""
# Call superclass
super(UsernamesModel, self).__init__(
session, [UsernameItem(user) for user in users])
# Protected attributes
self._current_user = current_user
class LogonView(BaseViewMixin, xDialog): #, Ui_LogonDialog):
"""
Logon dialog which let the user to choose the user name and input enter the
password to logon into the application.
If the Cancel button is pressed the application will be closed.
If the logon fails an error message appears on the screen.
The user cannot close the dialog unless press the Cancel button or logon
into the application.
"""
def __init__(self): # pylint: disable=W0231
"""
Empty constructor
"""
# Call superclasses
BaseViewMixin.__init__(self)
xDialog.__init__(
self, flags=(Qt.CustomizeWindowHint | Qt.WindowTitleHint
| Qt.WindowStaysOnTopHint)
)
# Setup UI
self.setupUi(self)
self.password.setFocus(Qt.OtherFocusReason)
def setData(self, users):
"""
Show the users by the current system location
:param users: The list of current system location's users
:type users: list( :py:class:`.User` )
"""
# Call superclass
super(LogonView, self).setData(users)
# Set data
self.username.setModel(
SortViewModelProxy(UsernamesModel(self.delegate().session, users)))
self.password.setText()
if __name__ == '__main__':
users=[['1','a'],['2','b'],['3','c'],['4','d']]
a = UsernamesModel(1, users)
pass
The error message is:-
File "/Users/CC/Documents/work/CC.code.trunk/splash_example.py", line 390, in <module>
a = UsernamesModel(1, users)
File "/Users/CC/Documents/work/CC.code.trunk/splash_example.py", line 337, in __init__
session, [UsernameItem(user) for user in users])
File "/Users/CC/Documents/work/CC.code.trunk/splash_example.py", line 95, in __init__
QtCore.QAbstractItemModel.__init__(self)
TypeError: __init__() takes exactly 3 arguments (1 given)
If you rem out the PyQt5 imports and unrem the PyQt4 imports then you'll see that there isn't a problem.
I have seen the post by
Chris O'Halloran - 28 May 00:47 [PyQt] Addition of parent argument when subclassing with super.
And wondered if he was also having a similar issue but managed to get around it.
I have tried the super() function but to no avail.
I've also looked at http://pyqt.sourceforge.net/Docs/PyQt5/pyqt4_differences.html#cooperative-multi-inheritance for clues
Many thanks in advance
Rob
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.riverbankcomputing.com/pipermail/pyqt/attachments/20150529/4f8e8257/attachment-0001.html>
More information about the PyQt
mailing list