* Added an implicit type conversion operator so that a PlasmaScripting.Applet
[kdebindings.git] / ruby / qtruby / rails_support / active_item_model.rb
blobf2e3b2000dc95f2aac1d986039cd0d8cce8bdbe8
1 =begin
2 This table model allows an ActiveRecord or ActiveResource to be used as a
3 basis for a Qt::AbstractItemModel for viewing in a Qt::TreeView. Example
4 usage:
6 app = Qt::Application.new(ARGV)
7 agencies = TravelAgency.find(:all)
8 model = ActiveItemModel.new(agencies)
9 tree = Qt::TreeView.new
10 tree.model = model
11 tree.show
12 app.exec
14 Written by Richard Dale and Silvio Fonseca
16 =end
18 require 'Qt'
20 #require "active_record"
21 #require "active_support"
22 #require "active_resource"
24 require 'date'
26 class TreeItem
27     attr_reader :childItems, :resource, :itemData
29     def initialize(item, keys, parent = nil, prefix="")
30         @keys = keys
31         @parentItem = parent
32         @childItems = []
33         @resource = item
34         if @resource.respond_to? :attributes
35             @resource.attributes.inject(@itemData = {}) do |data, a|
36                 if a[1].respond_to? :attributes
37                     TreeItem.new(a[1], @keys, self, prefix + a[0] + ".")
38                 else
39                     data[prefix + a[0]] = a[1]
40                 end
41                 data
42             end
43         else
44             @itemData = item
45         end
47         if @parentItem
48             @parentItem.appendChild(self)
49         end
50     end
51     
52     def appendChild(item)
53         @childItems.push(item)
54     end
55     
56     def child(row)
57         return @childItems[row]
58     end
59     
60     def childCount
61         return @childItems.length
62     end
63     
64     def columnCount
65         return @itemData.length
66     end
67     
68     def data(column)
69         return Qt::Variant.new(@itemData[@keys[column]])
70     end
71     
72     def parent
73         return @parentItem
74     end
75     
76     def row
77         if !@parentItem.nil?
78             return @parentItem.childItems.index(self)
79         end
80     
81         return 0
82     end
83 end
85 class ActiveItemModel < Qt::AbstractItemModel    
86     def initialize(collection, columns=nil)
87         super()
88         @collection = collection
89         @keys = build_keys([], @collection.first.attributes)
90         @keys.inject(@labels = {}) do |labels, k| 
91             labels[k] = k.humanize.gsub(/\./, ' ')
92             labels 
93         end
95         @rootItem = TreeItem.new(@labels, @keys)
96         @collection.each do |row|
97             TreeItem.new(row, @keys, @rootItem)
98         end
99     end
101     def build_keys(keys, attrs, prefix="")
102         attrs.inject(keys) do |cols, a|
103             if a[1].respond_to? :attributes
104                 build_keys(cols, a[1].attributes, prefix + a[0] + ".")
105             else
106                 cols << prefix + a[0]
107             end
108         end
109     end
110     
111     def columnCount(parent)
112         if parent.valid?
113             return parent.internalPointer.columnCount
114         else
115             return @rootItem.columnCount
116         end
117     end
118     
119     def data(index, role)
120         if !index.valid?
121             return Qt::Variant.new
122         end
123     
124         if role != Qt::DisplayRole
125             return Qt::Variant.new
126         end
127     
128         item = index.internalPointer
129         return item.data(index.column)
130     end
132     def setData(index, variant, role=Qt::EditRole)
133         if index.valid? and role == Qt::EditRole
134             raise "invalid column #{index.column}" if (index.column < 0 ||
135                 index.column >= @keys.size)
137             att = @keys[index.column]
138             item = index.internalPointer
140             if ! item.itemData.has_key? att
141                 return false
142             end
144             value = variant.value
146             if value.class.name == "Qt::Date"
147                 value = Date.new(value.year, value.month, value.day)
148             elsif value.class.name == "Qt::Time"
149                 value = Time.new(value.hour, value.min, value.sec)
150             end
152             att.gsub!(/.*\.(.*)/, '\1')
153             # Don't allow the primary key to be changed
154             if att == 'id'
155                 return false
156             end
158             eval("item.resource.attributes['%s'] = value" % att)
159             item.resource.save
160             emit dataChanged(index, index)
161             return true
162         else
163             return false
164         end
165     end
166     
167     def flags(index)
168         if !index.valid?
169             return Qt::ItemIsEnabled
170         end
171     
172         return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable
173     end
174     
175     def headerData(section, orientation, role)
176         if orientation == Qt::Horizontal && role == Qt::DisplayRole
177             return Qt::Variant.new(@labels[@keys[section]])
178         end
179     
180         return Qt::Variant.new
181     end
182     
183     def index(row, column, parent)
184         if !parent.valid?
185             parentItem = @rootItem
186         else
187             parentItem = parent.internalPointer
188         end
189     
190         @childItem = parentItem.child(row)
191         if ! @childItem.nil?
192             return createIndex(row, column, @childItem)
193         else
194             return Qt::ModelIndex.new
195         end
196     end
197     
198     def parent(index)
199         if !index.valid?
200             return Qt::ModelIndex.new
201         end
202     
203         childItem = index.internalPointer
204         parentItem = childItem.parent
205     
206         if parentItem == @rootItem
207             return Qt::ModelIndex.new
208         end
209     
210         return createIndex(parentItem.row, 0, parentItem)
211     end
212     
213     def rowCount(parent)
214         if !parent.valid?
215             parentItem = @rootItem
216         else
217             parentItem = parent.internalPointer
218         end
219     
220         return parentItem.childCount
221     end