* Added command line tool example similar to 'sopranocmd'
[kdebindings.git] / ruby / qtruby / rails_support / active_table_model.rb
blob7048d803759e8cae4843e21b4978e3d790569194
1 =begin
2 This table model allows an ActiveRecord or ActiveResource to be used as a
3 basis for a Qt::AbstractTableModel for viewing in a Qt::TableView. Example
4 usage:
6 app = Qt::Application.new(ARGV)
7 agencies = TravelAgency.find(:all, :conditions => [:name => 'Another Agency'])
8 model = ActiveTableModel.new(agencies)
9 table = Qt::TableView.new
10 table.model = model
11 table.show
12 app.exec
14 Written by Richard Dale and Silvio Fonseca
16 =end
18 require 'Qt'
19 require 'date'
21 class ActiveTableModel < Qt::AbstractTableModel
22     def initialize(collection, columns=nil)
23         super()
24         @collection = collection
25         if columns
26             if columns.kind_of? Hash
27                 @keys=columns.keys
28                 @labels=columns.values
29             else
30                 @keys=columns
31             end
32         else
33             @keys = build_keys([], @collection.first.attributes)
34         end
35         @labels||=@keys.collect { |k| k.humanize.gsub(/\./, ' ') }
36     end
38     def build_keys(keys, attrs, prefix="")
39         attrs.inject(keys) do |cols, a|
40             if a[1].respond_to? :attributes
41                 build_keys(cols, a[1].attributes, prefix + a[0] + ".")
42             else
43                 cols << prefix + a[0]
44             end
45         end
46     end
48     def rowCount(parent)
49         @collection.size
50     end
52     def columnCount(parent)
53         @keys.size
54     end
57     def [](row)
58         row = row.row if row.is_a?Qt::ModelIndex
59         @collection[row]
60     end
62     def column(name)
63         @keys.index name
64     end
66     def data(index, role=Qt::DisplayRole)
67         invalid = Qt::Variant.new
68         return invalid unless role == Qt::DisplayRole or role == Qt::EditRole
69         item = @collection[index.row]
70         return invalid if item.nil?
71         raise "invalid column #{index.column}" if (index.column < 0 ||
72             index.column >= @keys.size)
73         value = eval("item.attributes['%s']" % @keys[index.column].gsub(/\./, "'].attributes['"))
74         return Qt::Variant.new(value)
75     end
77     def headerData(section, orientation, role=Qt::DisplayRole)
78         invalid = Qt::Variant.new
79         return invalid unless role == Qt::DisplayRole
80         v = case orientation
81         when Qt::Horizontal
82             @labels[section]
83         else
84             section
85         end
86         return Qt::Variant.new(v)
87     end
89     def flags(index)
90         return Qt::ItemIsEditable | super(index)
91     end
93     def setData(index, variant, role=Qt::EditRole)
94         if index.valid? and role == Qt::EditRole
95             att = @keys[index.column]
96             # Don't allow the primary key to be changed
97             if att == 'id'
98                 return false
99             end
101             item = @collection[index.row]
102             raise "invalid column #{index.column}" if (index.column < 0 ||
103                 index.column >= @keys.size)
104             value = variant.value
106             if value.class.name == "Qt::Date"
107                 value = Date.new(value.year, value.month, value.day)
108             elsif value.class.name == "Qt::Time"
109                 value = Time.new(value.hour, value.min, value.sec)
110             end
112             eval("item.attributes['%s'] = value" % att.gsub(/\./, "'].attributes['"))
113             item.save
114             emit dataChanged(index, index)
115             return true
116         else
117             return false
118         end
119     end
122 # kate: indent-width 4;