"Segmentation fault" with QtRuby

Hello everyone!

Using QtRuby, I tried to implement the “Read-only example model”
(Creating new models chapter) of the “Model/View programming” technology
section of Qt Assistant.

But when I launch the example, I got this error :
main.rb:5: [BUG] Segmentation fault
ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]

Abandon

Here is the code :

slmodel.rb

class SLModel < Qt::AbstractListModel
def initialize string_list, parent = nil
super parent

@string_list = string_list

end

def rowCount parent = Qt::ModelIndex.new
@string_list.length
end

def data index, role
return Qt::Variant.new unless index.isValid
return Qt::Variant.new if index.row >= @string_list.length

return @string_list[index.row] if role == Qt.DisplayRole

Qt::Variant.new

end

def headerData section, orientation, role = Qt.DisplayRole

return Qt::Variant.new if role != Qt.DisplayRole

if orientation == Qt.Horizontal

“Column #{section}”

else

“Row #{section}”

end

end

end

window.rb

require ‘slmodel’

class Window < Qt::Widget
def initialize parent = nil
super parent

@list = %w[Alpha Beta Gamma Omega]
@model = SLModel.new @list, self
@view = Qt::ListView.new

@view.setModel @model

layout = Qt::VBoxLayout.new
layout.addWidget @view

setLayout layout

end
end

main.rb

require ‘Qt4’
require ‘window’

a = Qt::Application.new ARGV
window = Window.new
window.show
a.exec

As the error message doesn’t give me that much explanations, I don’t
know what is the origin of the problem…
Is it because I forgot to implement some virtual methods from
Qt::AbstractListModel?

Thanks!

Thank you for the reply!

The problem with your code is that the #data method must always return a
Qt::Variant. You correctly return an invalid Qt::Variant when the index
doesn’t correspond to a valid data, but when you pick a value from
@string_list, you return the value as it is. From the name of the
variable
(and also from the code in the Window’s constructor) it’s clear that the
contents of this instance variable are strings, not Qt::Variant, so you
get
the error. The third line of the data method should be:

return Qt::Variant.new @string_list[index.row] if role == Qt.DisplayRole

Indeed, it works!
So, I will be more careful with the C++ return type now.

By the way (in case you aren’t already aware of this), qtruby allows you
to
write code in a more rubysh way (rather than C+±ish). This means you
can:

  • use snake_case instead of camelCase from method names (for example,
    layout.add_widget instead of layout.addWidget)
  • use assignment instead of “setter” methods (but only for setter
    methods
    taking one argument). For example, self.layout = layout instead of
    setLayout
    layout

Yes, I’m aware of this, but since I’m a beginner both with Ruby and Qt,
I use CamelCase so that I know that is a Qt-method or Qt-attribute.
Maybe at some point, when I’ll be comfortable enough with Qt, I’ll
switch to “snake_case”…

I hope this helps

Yes, a lot! Thanks once again!

On Sunday 05 September 2010, Arturo Bonechi wrote:

|Hello everyone!
|
|Using QtRuby, I tried to implement the “Read-only example model”
|(Creating new models chapter) of the “Model/View programming” technology
|section of Qt Assistant.
|
|But when I launch the example, I got this error :
|main.rb:5: [BUG] Segmentation fault
|ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
|
|Abandon
|
|Here is the code :
|# slmodel.rb
|class SLModel < Qt::AbstractListModel
| def initialize string_list, parent = nil
| super parent
|
| @string_list = string_list
| end
|
| def rowCount parent = Qt::ModelIndex.new
| @string_list.length
| end
|
| def data index, role
| return Qt::Variant.new unless index.isValid
| return Qt::Variant.new if index.row >= @string_list.length
|
| return @string_list[index.row] if role == Qt.DisplayRole
|
| Qt::Variant.new
| end

The problem with your code is that the #data method must always return a
Qt::Variant. You correctly return an invalid Qt::Variant when the index
doesn’t correspond to a valid data, but when you pick a value from
@string_list, you return the value as it is. From the name of the
variable
(and also from the code in the Window’s constructor) it’s clear that the
contents of this instance variable are strings, not Qt::Variant, so you
get
the error. The third line of the data method should be:

return Qt::Variant.new @string_list[index.row] if role == Qt.DisplayRole

|# def headerData section, orientation, role = Qt.DisplayRole
|# return Qt::Variant.new if role != Qt.DisplayRole
|#
|# if orientation == Qt.Horizontal
|# “Column #{section}”
|# else
|# “Row #{section}”
|# end
|# end
|end
|
|# window.rb
|require ‘slmodel’
|
|class Window < Qt::Widget
| def initialize parent = nil
| super parent
|
| @list = %w[Alpha Beta Gamma Omega]
| @model = SLModel.new @list, self
| @view = Qt::ListView.new
|
| @view.setModel @model
|
| layout = Qt::VBoxLayout.new
| layout.addWidget @view
|
| setLayout layout
| end
|end
|
|# main.rb
|require ‘Qt4’
|require ‘window’
|
|a = Qt::Application.new ARGV
|window = Window.new
|window.show
|a.exec
|

By the way (in case you aren’t already aware of this), qtruby allows you
to
write code in a more rubysh way (rather than C+±ish). This means you
can:

  • use snake_case instead of camelCase from method names (for example,
    layout.add_widget instead of layout.addWidget)
  • use assignment instead of “setter” methods (but only for setter
    methods
    taking one argument). For example, self.layout = layout instead of
    setLayout
    layout

I hope this helps

Stefano