filcuc / nimqml

Qt Qml bindings for the Nim programming language
Other
162 stars 20 forks source link

Crash on indexCallback with QAbstractTableModel #35

Closed arkanoid87 closed 2 years ago

arkanoid87 commented 2 years ago

Hi! Thanks for this wonderful lib. I'm working with it and I find it nice to use.

I'm exploring how to link model with UI, but I'm stuck when I'm trying to create a TableView that uses Nim model with RegisterSingletonType. I'm experiencing crash on indexCallback when trying to print value via role name but I can't find where the problem is.

If I use setRootContextProperty instead of qmlRegisterSingletonType as in abstractitemmodel example it works, but I'm trying to avoiding this approach as I've read that it is going to be deprecated.

My dev environment is ubuntu 20.04 with Qt 5.12 from apt repository.

I've wrapped up a minimal test case: tablemodel.zip please mind tablemodel.nimble file as I use LD_LIBRARY_PATH to point to DOtherSide build path

I'll paste nim and qml code here to make it easier to understand the context:

main.nim

import NimQml
import model

proc mainProc() =
  var app = newQApplication()
  defer: app.delete()

  let tableModel = qmlRegisterSingletonType("TableModel", 1, 0, "TableModel", proc(): TableModel = newTableModel())

  var engine = newQQmlApplicationEngine()
  defer: engine.delete()

  engine.load(newQUrl("Main.qml"))

  app.exec()

when isMainModule:
  mainProc()
  GC_fullcollect()

model.nim

import std/tables
import NimQml

type
  RoleNames {.pure.} = enum
    CustomRole = UserRole + 1,

QtObject:
  type
    TableModel* = ref object of QAbstractTableModel
      customData*: seq[seq[int]]

  proc delete(self: TableModel) =
    self.QAbstractTableModel.delete

  proc setup(self: TableModel) =
    self.QAbstractTableModel.setup

  proc newTableModel*(): TableModel =
    new(result, delete)
    result.customData =  @[@[1,2,3],@[4,5,6],@[7,8,9]]
    result.setup

  method rowCount(self: TableModel, index: QModelIndex = nil): int =
    return self.customData.len # rowCountCallback works

  method columnCount(self: TableModel, index: QModelIndex = nil): int =
    return 3 # columnCountCallback works

  method data(self: TableModel, index: QModelIndex, role: int): QVariant =
    assert(false) # never reached. Crash on indexCallback

  method roleNames(self: TableModel): Table[int, string] =
    {RoleNames.CustomRole.int: "customrole"}.toTable

Main.qml

import QtQuick 2.12
import QtQuick.Window 2.1
import TableModel 1.0

Window {
    width: 640
    height: 480
    Component.onCompleted: visible = true

    TableView {
        id: table
        anchors.fill: parent
        columnSpacing: 1
        rowSpacing: 1
        clip: true

        model: TableModel

        delegate: Rectangle {
            implicitWidth: 100
            implicitHeight: 50
            Text {
                text: row + "," + column // works
                // text: customrole // crash in indexCallback
            }
            MouseArea {
                anchors.fill: parent
                onClicked: {
                  console.log(row,column,index)
                }
                onDoubleClicked: {
                  console.log(customrole) // double click on cell to replicate crash
                }
            }
        }
    }
}

Debug output (after replicating crash by double clicking on TableView's cell

arkanoid@box ~/n/m/e/tablemodel> nimble exec
  Executing task exec in /home/arkanoid/nim/experiments/tablemodel/tablemodel.nimble
  Verifying dependencies for tablemodel@0.1.0
      Info: Dependency on nimqml@>= 0.9.0 already satisfied
  Verifying dependencies for nimqml@0.9.0
   Building tablemodel/main using c backend
  Executing task ldrun in /home/arkanoid/nim/experiments/tablemodel/tablemodel.nimble
NimQml: QMetaObject: newQObjectMetaObject
NimQml: QMetaObject: newQAbstractItemModelMetaObject
NimQml: QMetaObject: newQAbstractListModelMetaObject
NimQml: QMetaObject: newQAbstractItemTableMetaObject
NimQml: QMetaObject: newQMetaObject
NimQml: QAbstractTableModel: setup
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: columnCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: columnCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: roleNamesCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
NimQml: QAbstractItemModel: rowCountCallback
qml: 2 2 8
qml: 2 2 8
NimQml: QAbstractItemModel: indexCallback
Traceback (most recent call last)
/home/arkanoid/nim/experiments/tablemodel/main.nim(18) main
/home/arkanoid/nim/experiments/tablemodel/main.nim(15) mainProc
/home/arkanoid/.nimble/pkgs/nimqml-0.9.0/nimqml/private/qapplication.nim(8) exec
/home/arkanoid/.nimble/pkgs/nimqml-0.9.0/nimqml/private/qabstractitemmodel.nim(106) indexCallback
/home/arkanoid/.nimble/pkgs/nimqml-0.9.0/nimqml/private/qabstractitemmodel.nim(100) index
/home/arkanoid/.nimble/pkgs/nimqml-0.9.0/nimqml/private/qabstracttablemodel.nim(51) index
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Segmentation fault (core dumped)
stack trace: (most recent call last)
/tmp/nimblecache-3325854957/nimscriptapi_1393979116.nim(187, 16)
/home/arkanoid/nim/experiments/tablemodel/tablemodel.nimble(22, 7) ldrunTask
/home/arkanoid/.choosenim/toolchains/nim-1.6.0/lib/system/nimscript.nim(273, 7) exec
/home/arkanoid/.choosenim/toolchains/nim-1.6.0/lib/system/nimscript.nim(273, 7) Error: unhandled exception: FAILED: LD_LIBRARY_PATH=../../lib/DOtherSide/build/lib ./main [OSError]
     Error: Exception raised during nimble script execution
stack trace: (most recent call last)
/tmp/nimblecache-3325854957/nimscriptapi_1393979116.nim(187, 16)
/home/arkanoid/nim/experiments/tablemodel/tablemodel.nimble(19, 7) execTask
/home/arkanoid/.choosenim/toolchains/nim-1.6.0/lib/system/nimscript.nim(273, 7) exec
/home/arkanoid/.choosenim/toolchains/nim-1.6.0/lib/system/nimscript.nim(273, 7) Error: unhandled exception: FAILED: nimble ldrun [OSError]
     Error: Exception raised during nimble script execution

Screen before crash

Thanks

filcuc commented 2 years ago

Thank you for the report i'll look at it this weekend. @arkanoid87 Can you please provide me all the versions for DOtherSide, NimQml and Nim.

arkanoid87 commented 2 years ago

Thanks!

DOtherSide: 0.8.0 (2fd6baf current master)
NimQml: 0.9.0
Nim: 1.6.0 (727c6378d2464090564dbcd9bc8b9ac648467e38)
filcuc commented 2 years ago

I debugged the problem yestarday evening and i got it working applying a big patch on the DOtherSide library. In pratice the use of QAbstractItemModel istantiated from qml (thus registered with qmlRegisterType or qmlRegisterSingletonType) is broken. I hope to cleanup the patch in these days. Until then use the setContextProperty

filcuc commented 2 years ago

I've released a new DOtherSide version v0.8.1. @arkanoid87 this bug should be with that version. If you test again with your executable be sure to implement the data method otherwise you trigger your assert

arkanoid87 commented 2 years ago

it works! Grazie!