Quantcast

PyQt5.6 with Python 3.5 Crash

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

PyQt5.6 with Python 3.5 Crash

Rathinam Signup
Hi All,

I'm using QAbstractItemModel with QTreeView in PyQt5.6-Py3.5. When I call 

model.beginInsertRows(index,i,i) the app crashes. If I try to add children under root index it's working fine. But If I try to add rows on any other index the app crashes. I'm quite sure that it worked without any issues in PyQt4.

Any help would be appreciated. Thanks.

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Florian Bruhin
Hi,

On Fri, May 19, 2017 at 03:25:21PM +0530, Rathinam Signup wrote:
> I'm using QAbstractItemModel with QTreeView in PyQt5.6-Py3.5. When I call
> model.beginInsertRows(index,i,i) the app crashes. If I try to add children
> under root index it's working fine. But If I try to add rows on any other
> index the app crashes. I'm quite sure that it worked without any issues in
> PyQt4.
>
> Any help would be appreciated. Thanks.

Without seeing any code, we can't really tell you much more than the
segfault already does: Probably there's *something* wrong with your code
;-)

I suggest trying to run the pytest-qt modeltester over your model:
http://pytest-qt.readthedocs.io/en/latest/modeltester.html

Florian

--
https://www.qutebrowser.org  | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072  | https://the-compiler.org/pubkey.asc
         I love long mails!  | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Rathinam Signup
In reply to this post by Rathinam Signup
Hi Florian,

Thanks much for the response. It's a big project and I tried my best to extract only the required portion of it. Here's the source code for you to look at. It actually involves getting folder tree structure from server and displaying it with checkboxes that allows the user to choose a sub-set from it.

Whenever the user expands we get the children from server and add it to the tree. Our app crashes when we do exactly this.

In the documentation of pytest-qt it's said that we need to add some items and then test. Does it mean after appending few children at the root level? Thanks again.

self.model.beginInsertRows(index,1,2)
childItem = TreeItem("idxx", "Namexx", "idxy", "idxz", parent=index.internalPointer())
index.internalPointer().appendChild(childItem)
self.model.endInsertRows()


from PyQt5.QtWidgets import QApplication, QTreeView, QWidget, QStyle
from PyQt5.QtCore import QModelIndex, QAbstractItemModel
from PyQt5.Qt import Qt, pyqtSignal

import traceback

LOADING_IN_PROGRESS="Loading"

class TreeItem(object):
    def __init__(self, resource_id, name, parent_id, root_id, parent=None, type="Folder"):
        self.resource_id = resource_id
        self.parent_id = parent_id
        self.root_id = root_id
        self.parentItem = parent
        self.name= name
        self.nodeType=type
        self.childItems = []

        self.populated = None
        self.hasChildren = True

        self.checkState = Qt.Checked

    def insertChild(self, pos, item):
        self.childItems.insert(pos, item)

    def appendChild(self, item):
        self.childItems.append(item)

    def removeChild(self, item):
        self.childItems.pop(0)

    def child(self, row):
        return self.childItems[row]

    def childCount(self):
        return len(self.childItems)

    def data(self, column):
        try:
            return self.name
        except IndexError:
            return None

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)
        return 0

class TreeModel(QAbstractItemModel):
    inProgress = pyqtSignal(str,str)
    def __init__(self, parentDialog):
        super().__init__(parent=None)
        self.checks = {}

        self.widget=QWidget()
        self.parentCls = parentDialog
        self.rootItem = parentDialog.rootItem
        self.dbHandle = parentDialog.dbhandle

    def hasChildren(self,index):
        return True

    def columnCount(self, parent):
        return 1

    def data(self, index, role):
        try:
            if not index.isValid():
                return None

            if role == Qt.CheckStateRole:
                if index.column() == 0:
                    if index.internalPointer().resource_id==LOADING_IN_PROGRESS:
                        return None
                    else:
                        return self.getCheckState(index)

            elif role == Qt.DecorationRole:
                if index.internalPointer().resource_id==LOADING_IN_PROGRESS:
                    return None
                else:
                    return self.widget.style().standardIcon(QStyle.SP_DirIcon)

            elif role == Qt.DisplayRole:
                item = index.internalPointer()
                return item.data(index.column())

            elif role == Qt.UserRole:
                uniqueId = index.internalPointer().resource_id+index.internalPointer().root_id
                return uniqueId

            else:
                return None
        except Exception as err:
            traceback.print_exc()

    def getCheckState(self, index):
        if index.isValid():
            return index.internalPointer().checkState

    def setData(self, index, value, role):
        try:
            if not index.isValid():
                return None
            if index.internalPointer().resource_id!=LOADING_IN_PROGRESS and (role == Qt.CheckStateRole and index.column() == 0):
                #self.checks[index] = value

                if (value ==  Qt.Unchecked and not
                    self.db.can_uncheck(index.internalPointer().resource_id)):
                    if index.internalPointer().checkState:
                        self.inProgress.emit(index.internalPointer().resource_id,index.internalPointer().root_id)
                    return True

                index.internalPointer().checkState = value

                if value== Qt.PartiallyChecked:
                    self.dataChanged.emit(index,index)
                    return True

                for i in range(self.rowCount(index)):
                    child=self.index(i, 0, index)
                    if child.internalPointer().resource_id!=LOADING_IN_PROGRESS:
                        self.setData(child, value, Qt.CheckStateRole)

                if value ==  Qt.Unchecked:
                    parent  =   self.parent(index)

                    while parent.isValid() and self.data(parent, Qt.CheckStateRole) == Qt.Checked:
                        self.setData(parent, Qt.PartiallyChecked, Qt.CheckStateRole)
                        #parent.setCheckState(column, QtCore.Qt.PartiallyChecked)
                        parent  =   parent.parent()

                else:
                    parent  =   self.parent(index)
                    while parent.isValid():
#                        ispartial = not all(self.data(parent, QtCore.Qt.CheckStateRole)==value for i in range(self.rowCount(parent)) if parent.isValid())
                        ispartial=False
                        for i in range(self.rowCount(parent)):
                            child=self.index(i, 0, parent)
                            if child.internalPointer().resource_id!=LOADING_IN_PROGRESS:
                                if self.data(child, Qt.CheckStateRole)!=value:
                                    ispartial=True
                                    break

                        newstate =   [value, Qt.PartiallyChecked][ispartial]
                        #parent.setCheckState(value, newstate)
                        if self.data(parent, Qt.CheckStateRole)!=newstate:
                            self.setData(parent, newstate, Qt.CheckStateRole)
                        parent  =   parent.parent()

                self.dataChanged.emit(index,index)
                return True

            return super().setData(index, value, role)
        except Exception as err:
            traceback.print_exc()

    def flags(self, index):
        try:
            flags=super().flags(index) #|QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
            if not index.isValid():
                return Qt.NoItemFlags
            if index.internalPointer().resource_id == LOADING_IN_PROGRESS:
                return flags & ~Qt.ItemIsUserCheckable & ~Qt.ItemIsEnabled
            return flags|Qt.ItemIsUserCheckable
        except Exception as err:
            traceback.print_exc()

    def headerData(self, section, orientation, role):
        return None

    def index(self, row, column, parent):
        try:
            if not self.hasIndex(row, column, parent):
                return QModelIndex()

            if not parent.isValid():
                parentItem = self.rootItem
            else:
                parentItem = parent.internalPointer()

            childItem = parentItem.child(row)
            if childItem:
                return self.createIndex(row, column, childItem)
            else:
                return QModelIndex()
        except Exception as err:
            traceback.print_exc()

    def parent(self, index):
        try:
            if not index.isValid():
                return QModelIndex()

            childItem = index.internalPointer()
            parentItem = childItem.parent()

            if parentItem == self.rootItem:
                return QModelIndex()

            return self.createIndex(parentItem.row(), 0, parentItem)
        except Exception as err:
            traceback.print_exc()

    def rowCount(self, parent):
        try:
            if parent.column() > 0:
                return 0
            if not parent.isValid():
                parentItem = self.rootItem
            else:
                parentItem = parent.internalPointer()
            return parentItem.childCount()
        except Exception as err:
            traceback.print_exc()

Hi,

On Fri, May 19, 2017 at 03:25:21PM +0530, Rathinam Signup wrote:
> I'm using QAbstractItemModel with QTreeView in PyQt5.6-Py3.5. When I call
> model.beginInsertRows(index,i,i) the app crashes. If I try to add children
> under root index it's working fine. But If I try to add rows on any other
> index the app crashes. I'm quite sure that it worked without any issues in
> PyQt4.
>
> Any help would be appreciated. Thanks.

Without seeing any code, we can't really tell you much more than the
segfault already does: Probably there's *something* wrong with your code
;-)

I suggest trying to run the pytest-qt modeltester over your model:
http://pytest-qt.readthedocs.io/en/latest/modeltester.html

Florian


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Florian Bruhin
Hi,

On Fri, May 19, 2017 at 05:21:28PM +0530, Rathinam Signup wrote:
> In the documentation of pytest-qt it's said that we need to add some items
> and then test. Does it mean after appending few children at the root level?

Basically the modeltester tries to check if the model behaves correctly
with whatever it does. It can test quite a few things without any
modifications to the model, but ideally you should start the modeltester
and then do various modifications to the model. In my code, I have
various test cases for the model, and simply also activate the
modeltester for all of them.

Some comments about the code below:

> class TreeItem(object):
>     def __init__(self, resource_id, name, parent_id, root_id,
> parent=None, type="Folder"):
>         self.resource_id = resource_id
>         self.parent_id = parent_id
>         self.root_id = root_id
>         self.parentItem = parent
>         self.name= name
>         self.nodeType=type
>         self.childItems = []
Wouldn't it be easier to just use a QStandardItemModel with
QStandardItems?

>     def insertChild(self, pos, item):
>         self.childItems.insert(pos, item)
>
>     def appendChild(self, item):
>         self.childItems.append(item)
>
>     def removeChild(self, item):
>         self.childItems.pop(0)

Does your model call begin* and end* appropriately?

> class TreeModel(QAbstractItemModel):
>     [...]
>
>     def hasChildren(self,index):
>         return True

This seems wrong, your leaf items dont have any children.

Florian

--
https://www.qutebrowser.org  | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072  | https://the-compiler.org/pubkey.asc
         I love long mails!  | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Rathinam Signup
In reply to this post by Rathinam Signup
Hi Florian,

Thanks again for the response.

>Wouldn't it be easier to just use a QStandardItemModel with
>QStandardItems

Maybe. But I developed this code based on the simpletreemodel provided with PyQt Examples>Item Views. So continued with it.

>Does your model call begin* and end* appropriately?

I haven't used InsertChild at all in my code. I always add beginInsertRows before append child and endInsertRows after it's appended. In this line, the app is crashing.

>This seems wrong, your leaf items dont have any children.

I intentionally returned True. When the user expands the item I connect with the server and check for children and if it doesn't have any children, No children text is added to the tree.

Do you know how can I view the crash report in PyQt? Thanks


Hi,

> In the documentation of pytest-qt it's said that we need to add some items
> and then test. Does it mean after appending few children at the root level?

Basically the modeltester tries to check if the model behaves correctly
with whatever it does. It can test quite a few things without any
modifications to the model, but ideally you should start the modeltester
and then do various modifications to the model. In my code, I have
various test cases for the model, and simply also activate the
modeltester for all of them.

Some comments about the code below:

> class TreeItem(object):
>     def __init__(self, resource_id, name, parent_id, root_id,
> parent=None, type="Folder"):
>         self.resource_id = resource_id
>         self.parent_id = parent_id
>         self.root_id = root_id
>         self.parentItem = parent
>         self.name= name
>         self.nodeType=type
>         self.childItems = []

Wouldn't it be easier to just use a QStandardItemModel with
QStandardItems?

>     def insertChild(self, pos, item):
>         self.childItems.insert(pos, item)
>
>     def appendChild(self, item):
>         self.childItems.append(item)
>
>     def removeChild(self, item):
>         self.childItems.pop(0)

Does your model call begin* and end* appropriately?

> class TreeModel(QAbstractItemModel):
>     [...]
>
>     def hasChildren(self,index):
>         return True

This seems wrong, your leaf items dont have any children.

Florian


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Rathinam Signup
In reply to this post by Rathinam Signup
Hi all,

I did test the same code by porting it back to PyQt4 and it works without any issues. So I can assure you that the bug is with PyQt 5.6. Can you please suggest some ways to view the crash report like in which thread the crash occured?

I set the primary key as User Data in the QAbstractItemModel. When the user expands the item I pass this primary key to a QThread which connects with the server and when the results are obtained, I add children for the corresponding tree item. When the execution hits the line beginInsertRows the app crashes. Please help me to fix this issue. Thanks.
 
Hi Florian,

Thanks again for the response.

>Wouldn't it be easier to just use a QStandardItemModel with
>QStandardItems

Maybe. But I developed this code based on the simpletreemodel provided with
PyQt Examples>Item Views. So continued with it.

>Does your model call begin* and end* appropriately?

I haven't used InsertChild at all in my code. I always add beginInsertRows
before append child and endInsertRows after it's appended. In this line,
the app is crashing.

>This seems wrong, your leaf items dont have any children.

I intentionally returned True. When the user expands the item I connect
with the server and check for children and if it doesn't have any children,
No children text is added to the tree.

Do you know how can I view the crash report in PyQt? Thanks


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Rathinam Signup
In reply to this post by Rathinam Signup
I would like to add that I did test my model with the Model Tester provided here https://github.com/bgr/PyQt5_modeltest and didn't find any bugs. Thanks

On Sat, May 20, 2017 at 8:53 PM, Rathinam Signup <[hidden email]> wrote:
Hi all,

I did test the same code by porting it back to PyQt4 and it works without any issues. So I can assure you that the bug is with PyQt 5.6. Can you please suggest some ways to view the crash report like in which thread the crash occured?

I set the primary key as User Data in the QAbstractItemModel. When the user expands the item I pass this primary key to a QThread which connects with the server and when the results are obtained, I add children for the corresponding tree item. When the execution hits the line beginInsertRows the app crashes. Please help me to fix this issue. Thanks.


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Barry Scott
In reply to this post by Rathinam Signup


> On 19 May 2017, at 12:51, Rathinam Signup <[hidden email]> wrote:
>
> class TreeItem(object):

Should this be derived from QtGui.QStandardItem?

Barry


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Rathinam Signup
In reply to this post by Rathinam Signup
Hi Barry,

Thanks for the response. Since I'm quite new to model-view framework in Qt, I built my model by using the simpletreemodel.py provided with the PyQt Examples when PyQt is installed. Do you see any issues? 

I'm using Windows 10, Python 3.5 with PyQt5 whereas the machine with PyQt4 has Win 8 OS installed. Will it make any difference? Thanks.

On Sat, May 20, 2017 at 11:02 PM, Barry <[hidden email]> wrote:

> class TreeItem(object):

Should this be derived from QtGui.QStandardItem?

Barry




_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Florian Bruhin
In reply to this post by Rathinam Signup
Hi,

On Sat, May 20, 2017 at 08:53:29PM +0530, Rathinam Signup wrote:
> I did test the same code by porting it back to *PyQt4* and it works without
> any issues. So I can assure you that *the bug is with PyQt 5.6*.

Not necessarily. If anything, the bug would probably be in Qt 5, PyQt is
just a relatively thin wrapper around that.

However, it's also possible something is just different in Qt 4 and
Qt 5, and there's still something wrong with your code (custom models
are *hard*, that's why I said it's way easier to base things on a
QStandardItemModel), and it just didn't show up as a crash on Qt 4.

> Can you please suggest some ways to view the crash report like in
> which thread the crash occured?

With whatever you'd use to do so on your system for other (C++)
applications. For example, DebugDiag on Windows or gdb or coredumpctl on
Linux.

> I set the primary key as User Data in the QAbstractItemModel. When the user
> expands the item I pass this primary key to a QThread which connects with
> the server and when the results are obtained, I add children for the
> corresponding tree item. When the execution hits the line beginInsertRows
> the app crashes.

Are you inserting things into your model from a thread? AFAIK, Qt does
not support that - so if that worked with Qt 4, that was pure luck.

On Sat, May 20, 2017 at 06:32:38PM +0100, Barry wrote:
> > On 19 May 2017, at 12:51, Rathinam Signup <[hidden email]> wrote:
> >
> > class TreeItem(object):
>
> Should this be derived from QtGui.QStandardItem?

Since it's not a QStandardItemModel, probably not ;-)

On Sat, May 20, 2017 at 10:11:34PM +0530, Rathinam Signup wrote:
> I would like to add that I did test my model with the Model Tester provided
> here https://github.com/bgr/PyQt5_modeltest and didn't find any bugs. Thanks

Even when modifying your model? Note that the pytest-qt model tester
adds some additional tests on top of those, though.

Florian

--
https://www.qutebrowser.org  | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072  | https://the-compiler.org/pubkey.asc
         I love long mails!  | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Rathinam Signup
In reply to this post by Rathinam Signup
Hi Florian,

Thanks for the response.

>custom models are *hard*, that's why I said it's way easier to base things on a >QStandardItemModel

I'll check by changing my model from QAbstractItemModel to QStandardItemModel. I'll also try to test the same with the latest PyQt(5.8.x) version also.

>With whatever you'd use to do so on your system for other (C++)
>applications. For example, DebugDiag on Windows or gdb or coredumpctl on
>Linux.

Can you suggest any equivalent tools in Python?

>Are you inserting things into your model from a thread? AFAIK, Qt does
>not support that - so if that worked with Qt 4, that was pure luck.

I'm using a QThread here to fetch children items from server. It must be noted that I'm not passing the model indexes here. Instead I pass a key and just before inserting the rows, I retrieve the parent index from the model that corresponds to the particular key. Will try pytest-qt to test my model also. Thanks.

On Sun, May 21, 2017 at 2:02 AM, Florian Bruhin <[hidden email]> wrote:
Hi,

On Sat, May 20, 2017 at 08:53:29PM +0530, Rathinam Signup wrote:
> I did test the same code by porting it back to *PyQt4* and it works without
> any issues. So I can assure you that *the bug is with PyQt 5.6*.

Not necessarily. If anything, the bug would probably be in Qt 5, PyQt is
just a relatively thin wrapper around that.

However, it's also possible something is just different in Qt 4 and
Qt 5, and there's still something wrong with your code (custom models
are *hard*, that's why I said it's way easier to base things on a
QStandardItemModel), and it just didn't show up as a crash on Qt 4.

> Can you please suggest some ways to view the crash report like in
> which thread the crash occured?

With whatever you'd use to do so on your system for other (C++)
applications. For example, DebugDiag on Windows or gdb or coredumpctl on
Linux.

> I set the primary key as User Data in the QAbstractItemModel. When the user
> expands the item I pass this primary key to a QThread which connects with
> the server and when the results are obtained, I add children for the
> corresponding tree item. When the execution hits the line beginInsertRows
> the app crashes.

Are you inserting things into your model from a thread? AFAIK, Qt does
not support that - so if that worked with Qt 4, that was pure luck.

On Sat, May 20, 2017 at 06:32:38PM +0100, Barry wrote:
> > On 19 May 2017, at 12:51, Rathinam Signup <[hidden email]> wrote:
> >
> > class TreeItem(object):
>
> Should this be derived from QtGui.QStandardItem?

Since it's not a QStandardItemModel, probably not ;-)

On Sat, May 20, 2017 at 10:11:34PM +0530, Rathinam Signup wrote:
> I would like to add that I did test my model with the Model Tester provided
> here https://github.com/bgr/PyQt5_modeltest and didn't find any bugs. Thanks

Even when modifying your model? Note that the pytest-qt model tester
adds some additional tests on top of those, though.

Florian


_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Florian Bruhin
Hi,

On Mon, May 22, 2017 at 12:58:37PM +0530, Rathinam Signup wrote:
> >With whatever you'd use to do so on your system for other (C++)
> >applications. For example, DebugDiag on Windows or gdb or coredumpctl on
> >Linux.
>
> Can you suggest any equivalent tools in Python?

There's the faulthandler module:
https://docs.python.org/3/library/faulthandler.html

But the crash is happening in C++, so that won't be very useful.

Florian

--
https://www.qutebrowser.org  | [hidden email] (Mail/XMPP)
   GPG: 916E B0C8 FD55 A072  | https://the-compiler.org/pubkey.asc
         I love long mails!  | https://email.is-not-s.ms/

_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt

signature.asc (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: PyQt5.6 with Python 3.5 Crash

Hans-Peter Jansen-2
In reply to this post by Rathinam Signup
Hi Rathinam,

On Freitag, 19. Mai 2017 17:21:28 Rathinam Signup wrote:

>
> class TreeItem(object):
>     def __init__(self, resource_id, name, parent_id, root_id,
> parent=None, type="Folder"):
>         self.resource_id = resource_id
>         self.parent_id = parent_id
>         self.root_id = root_id
>         self.parentItem = parent
>         self.name= name
>         self.nodeType=type
>         self.childItems = []
>
>         self.populated = None
>         self.hasChildren = True
>
>         self.checkState = Qt.Checked
>
>     def insertChild(self, pos, item):
>         self.childItems.insert(pos, item)
>
>     def appendChild(self, item):
>         self.childItems.append(item)
>
>     def removeChild(self, item):
>         self.childItems.pop(0)
>
>     def child(self, row):
>         return self.childItems[row]

This doesn't catch invalid rows..

>     def childCount(self):
>         return len(self.childItems)
>
>     def data(self, column):
>         try:
>             return self.name
>         except IndexError:
>             return None

while you will never harvest an IndexError here.

Guess, the two methods bodies are mixed up...

>     def parent(self):
>         return self.parentItem
>
>     def row(self):
>         if self.parentItem:
>             return self.parentItem.childItems.index(self)
>         return 0
>
> class TreeModel(QAbstractItemModel):
>     inProgress = pyqtSignal(str,str)
>     def __init__(self, parentDialog):
>         super().__init__(parent=None)
>         self.checks = {}
>
>         self.widget=QWidget()
>         self.parentCls = parentDialog
>         self.rootItem = parentDialog.rootItem
>         self.dbHandle = parentDialog.dbhandle
>
>     def hasChildren(self,index):
>         return True

Either implement this in a sane way, or not at all.

>     def columnCount(self, parent):
>         return 1
>
>     def data(self, index, role):
>         try:
>             if not index.isValid():
>                 return None
>
>             if role == Qt.CheckStateRole:
>                 if index.column() == 0:
>                     if index.internalPointer().resource_id==LOADING_IN_PROGRESS:
>                         return None
>                     else:
>                         return self.getCheckState(index)
>
>             elif role == Qt.DecorationRole:
>                 if index.internalPointer().resource_id==LOADING_IN_PROGRESS:
>                     return None
>                 else:
>                     return self.widget.style().standardIcon(QStyle.SP_DirIcon)
>
>             elif role == Qt.DisplayRole:
>                 item = index.internalPointer()
>                 return item.data(index.column())
>
>             elif role == Qt.UserRole:
>                 uniqueId =
> index.internalPointer().resource_id+index.internalPointer().root_id
>                 return uniqueId
>
>             else:
>                 return None
>         except Exception as err:
>             traceback.print_exc()

By ignoring the exception, you're making things worse...

>     def getCheckState(self, index):
>         if index.isValid():
>             return index.internalPointer().checkState
>
>     def setData(self, index, value, role):
>         try:
>             if not index.isValid():
>                 return None

setData return booleans

>             if index.internalPointer().resource_id!=LOADING_IN_PROGRESS
> and (role == Qt.CheckStateRole and index.column() == 0):
>                 #self.checks[index] = value
>
>                 if (value ==  Qt.Unchecked and not
>                     self.db.can_uncheck(index.internalPointer().resource_id)):
>                     if index.internalPointer().checkState:
>
> self.inProgress.emit(index.internalPointer().resource_id,index.internalPointer().root_id)
>                     return True
>
>                 index.internalPointer().checkState = value
>
>                 if value== Qt.PartiallyChecked:
>                     self.dataChanged.emit(index,index)
>                     return True
>
>                 for i in range(self.rowCount(index)):
>                     child=self.index(i, 0, index)
>                     if child.internalPointer().resource_id!=LOADING_IN_PROGRESS:
>                         self.setData(child, value, Qt.CheckStateRole)
>
>                 if value ==  Qt.Unchecked:
>                     parent  =   self.parent(index)
>
>                     while parent.isValid() and self.data(parent,
> Qt.CheckStateRole) == Qt.Checked:
>                         self.setData(parent, Qt.PartiallyChecked,
> Qt.CheckStateRole)
>                         #parent.setCheckState(column,
> QtCore.Qt.PartiallyChecked)
>                         parent  =   parent.parent()
>
>                 else:
>                     parent  =   self.parent(index)
>                     while parent.isValid():
> #                        ispartial = not all(self.data(parent,
> QtCore.Qt.CheckStateRole)==value for i in range(self.rowCount(parent))
> if parent.isValid())
>                         ispartial=False
>                         for i in range(self.rowCount(parent)):
>                             child=self.index(i, 0, parent)
>                             if
> child.internalPointer().resource_id!=LOADING_IN_PROGRESS:
>                                 if self.data(child, Qt.CheckStateRole)!=value:
>                                     ispartial=True
>                                     break
>
>                         newstate =   [value, Qt.PartiallyChecked][ispartial]
>                         #parent.setCheckState(value, newstate)
>                         if self.data(parent, Qt.CheckStateRole)!=newstate:
>                             self.setData(parent, newstate, Qt.CheckStateRole)
>                         parent  =   parent.parent()
>
>                 self.dataChanged.emit(index,index)
>                 return True
>
>             return super().setData(index, value, role)
>         except Exception as err:
>             traceback.print_exc()

Hmm, failed to follow your logic here, but the comment from data() applies,
but why would you want to call the super class here?

>     def flags(self, index):
>         try:
>             flags=super().flags(index) #|QtCore.Qt.ItemIsEnabled |
> QtCore.Qt.ItemIsSelectable
>             if not index.isValid():
>                 return Qt.NoItemFlags
>             if index.internalPointer().resource_id == LOADING_IN_PROGRESS:
>                 return flags & ~Qt.ItemIsUserCheckable & ~Qt.ItemIsEnabled
>             return flags|Qt.ItemIsUserCheckable
>         except Exception as err:
>             traceback.print_exc()

isValid check _after_ calling the super class?

>     def headerData(self, section, orientation, role):
>         return None
>
>     def index(self, row, column, parent):
>         try:
>             if not self.hasIndex(row, column, parent):
>                 return QModelIndex()
>
>             if not parent.isValid():
>                 parentItem = self.rootItem
>             else:
>                 parentItem = parent.internalPointer()
>
>             childItem = parentItem.child(row)
>             if childItem:
>                 return self.createIndex(row, column, childItem)
>             else:
>                 return QModelIndex()
>         except Exception as err:
>             traceback.print_exc()
>
>     def parent(self, index):
>         try:
>             if not index.isValid():
>                 return QModelIndex()
>
>             childItem = index.internalPointer()
>             parentItem = childItem.parent()
>
>             if parentItem == self.rootItem:
>                 return QModelIndex()
>
>             return self.createIndex(parentItem.row(), 0, parentItem)
>         except Exception as err:
>             traceback.print_exc()
>
>     def rowCount(self, parent):
>         try:
>             if parent.column() > 0:
>                 return 0
>             if not parent.isValid():
>                 parentItem = self.rootItem
>             else:
>                 parentItem = parent.internalPointer()
>             return parentItem.childCount()
>         except Exception as err:
>             traceback.print_exc()

Apart, from what Florian already said, you contribute to your issues by
catching and ignoring any exceptions. Given, that you feed your model
from another thread, you get exactly, what you asked for: disaster..
Better feed your model by emitting data from threads and consuming it
in the main thread.

The usual strategy applies: extract/reduce the code to the minimum possible.
You will get something, that's testable and shareable, and chances are big,
that you're able to solve your issue in that course.

Good luck,
Pete
_______________________________________________
PyQt mailing list    [hidden email]
https://www.riverbankcomputing.com/mailman/listinfo/pyqt
Loading...