On Monday 06 December 2010 03:50:26 Marco Polo wrote:
> This is the piece of code that makes ruby to crash:
> 
> <code>
>     def load_plists
>         #return
>         @ui.lists_tv.clear
>         DBIntf::connection.execute( "SELECT * FROM plists ORDER BY
> LOWER(sname)" ) do |row|
>             @ui.lists_tv.addTopLevelItem(Qt::TreeWidgetItem.new {
> setText(0, row[0]); setText(1, row[1]) })
>         end
>     end
> </code>
> 
> I added the order by statement to get rid from the sort in the tree
> view. The tree view comes from a qtdesigner ui file and is used as a
> list
> view, there are no children and only 16 entries in the sqlite3 plists
> table.
> In another similar case, slightly more complex, i have 2000+ entries and
> it works even if sort is enabled but only if the code is surrounded with
> GC.enable/disable:
> 
> <code>
>     def load_entries
>         clear
> 
>         GC.disable
>         has_compile = false
>         DBIntf::connection.execute(generate_sql) do |row|
>             map_row_to_entry(row, Qt::TreeWidgetItem.new)
>             has_compile = true if row[ROW_REF] == "0"
>         end
>         unless @mc.main_filter.empty?
>             unless has_compile
>                 map_row_to_entry(["0", "Compilation"],
> Qt::TreeWidgetItem.new)
>             end
>         end
> 
>         GC.enable
>         return self
>     end
> </code>
> 
> In this case, the class inherits a treeview.
> 
> Thanks for the links and your help.
> 
> marco

First of all, just to be clear, you're using tree widgets, not tree views. 
Asides from this, I don't see anything wrong with your code. As I said in my 
other mail, I think your best option is to post the C backtrace from the crash 
to either the qt-ruby forum or mailing list. If you do, you may be asked for a 
small program which reproduces the crash. I guess this might not be easy to 
do.

If all else fails, you can try replacing the tree widget with a tree view 
coupled with a Qt::StandardItemModel. Model/View-based widgets (Qt::ListView, 
Qt::TreeView and Qt::TableView) are more flexible than their *Widget 
counterparts and, when used with a Qt::StandardItemModel, are just as easy to 
use.

If you choose to do so, you can create the view widget using the designer just 
like you did with the tree widget. Then, in your widget's constructor do 
something like (referring to your first piece of code):

@ui.lists_tv.model = Qt::StandardItemModel.new @ui.lists_tv

Then, in your load_plists method, you can do something like this:

@ui.lists_tv.clear
DBIntf::connection.execute( "SELECT * FROM plists ORDER BY LOWER(sname)" ) do 
|row|
  items = row.map{|i| Qt::StandardItem.new i}
  @ui.lists_tv.model.append_row items
end

Even if you don't find TreeView better than TreeWidget, it may avoid the 
crashes you see.


By the way, referring to your first message, why do you think that using qt-
ruby "our code looks like to a c++ app written in another language (you
almost lose all advantages of a clean ruby port like ruby-gnome2, exception 
messages are unclear when it's qt related)"? (I never used ruby-gnome2, so I 
can't compare with it).

Looking at your code, it seems you aren't aware that you can replace camel-
case names with snake-case ones (for example, addTopLevelItem could have been 
written as add_top_level_item). Also, in case you aren't aware, methods 
starting with is are availlable in the more rubysh form ending with a question 
mark: isEmpty can also be called as empty?. I'm not sure if this is also the 
case for methods starting with has. Setters methods taking a single argument 
are also availlable as methods ending with =. For instance, the Qt::TreeView 
setColumnCount method can also be written as column_count =.

Regarding the exception issue, I'm afraid I have to agree they are often 
wrong. In particular (I guess this is what you're referring to), qt-ruby 
raises NoMethodError even when the method does exist, but takes different 
arguments from what you passed. I read somewhere that this is to mimic the 
behaviour you get in C++, where using the wrong arguments would make the 
compiler complain about calling a non existing method. I thought to post a bug 
report about this but decided against that knowing they would have rejected it 
because of compatibility issues.

I hope this helps

Stefano